@theoremjs/studio 0.0.0-stage → 0.3.2

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 (473) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +295 -2
  3. package/agreement.d.ts +14 -0
  4. package/agreement.js +80 -0
  5. package/asks.d.ts +47 -0
  6. package/asks.js +54 -0
  7. package/browser-connection.d.ts +49 -0
  8. package/browser-connection.js +215 -0
  9. package/browser-engine.d.ts +11 -0
  10. package/browser-engine.js +11 -0
  11. package/browser-execution.d.ts +6 -0
  12. package/browser-execution.js +18 -0
  13. package/browser-live.d.ts +4 -0
  14. package/browser-live.js +132 -0
  15. package/browser-transport.d.ts +33 -0
  16. package/browser-transport.js +229 -0
  17. package/browser.d.ts +4 -0
  18. package/browser.js +4 -0
  19. package/canonical.d.ts +10 -0
  20. package/canonical.js +25 -0
  21. package/compile-workspace.d.ts +28 -0
  22. package/compile-workspace.js +295 -0
  23. package/compile.d.ts +65 -0
  24. package/compile.js +1605 -0
  25. package/concierge-demo.d.ts +17 -0
  26. package/concierge-demo.js +1230 -0
  27. package/conversation-key.d.ts +5 -0
  28. package/conversation-key.js +10 -0
  29. package/decision-example-images.d.ts +30 -0
  30. package/decision-example-images.js +30 -0
  31. package/deno.json +3 -0
  32. package/draft.d.ts +407 -0
  33. package/draft.js +505 -0
  34. package/editors.d.ts +29 -0
  35. package/editors.js +51 -0
  36. package/example-embedding-files.d.ts +11 -0
  37. package/example-embedding-files.js +20 -0
  38. package/example.d.ts +36 -0
  39. package/example.js +357 -0
  40. package/guardrail-probe.d.ts +100 -0
  41. package/guardrail-probe.js +722 -0
  42. package/held-credentials.d.ts +28 -0
  43. package/held-credentials.js +87 -0
  44. package/installed.mjs +40 -0
  45. package/lent-keys.d.ts +122 -0
  46. package/lent-keys.js +47 -0
  47. package/line-diff.d.ts +15 -0
  48. package/line-diff.js +41 -0
  49. package/live-connection.d.ts +22 -0
  50. package/live-connection.js +27 -0
  51. package/live-session-bridge.d.ts +15 -0
  52. package/live-session-bridge.js +202 -0
  53. package/map-line.d.ts +19 -0
  54. package/map-line.js +42 -0
  55. package/map.d.ts +154 -0
  56. package/map.js +525 -0
  57. package/media-accept.d.ts +19 -0
  58. package/media-accept.js +65 -0
  59. package/mod.d.ts +39 -0
  60. package/mod.js +33 -0
  61. package/origins.d.ts +52 -0
  62. package/origins.js +165 -0
  63. package/package.json +85 -4
  64. package/page/assets/Banner-BISz3nXA.js +2 -0
  65. package/page/assets/BottomSheet-BwfBDtje.js +1 -0
  66. package/page/assets/Card-Lp-0P5eL.js +1 -0
  67. package/page/assets/CardWall-CBRLdDZW.js +1 -0
  68. package/page/assets/Center-nHS1JSux.js +1 -0
  69. package/page/assets/CheckboxInput-Cj5pk-KI.js +2 -0
  70. package/page/assets/CodeBlock-C7XJ4ioE.js +51 -0
  71. package/page/assets/CollapsibleGroup-N7_SOjbm.js +2 -0
  72. package/page/assets/ContextMenu-CBu9H-9H.js +2 -0
  73. package/page/assets/DateInput-BGrQ5tPC.js +1 -0
  74. package/page/assets/Dialog-DELWQo-v.js +1 -0
  75. package/page/assets/EmptyState-C8W4JKBZ.js +1 -0
  76. package/page/assets/HoverCard-D1Y1ltWQ.js +1 -0
  77. package/page/assets/Icon-JrysT8aU.js +3 -0
  78. package/page/assets/IconAlertTriangle-BqAEqqdU.js +1 -0
  79. package/page/assets/IconButton-DlOGzJIX.js +1 -0
  80. package/page/assets/IconEye-BB5aY-wQ.js +1 -0
  81. package/page/assets/IconFileText-6zOFKKrF.js +1 -0
  82. package/page/assets/IconSearch-BTx66a40.js +1 -0
  83. package/page/assets/IconShield-DDOh7Gr5.js +1 -0
  84. package/page/assets/ItemSwipeLayer-Ckn4X6h9.js +1 -0
  85. package/page/assets/PaneState-BvA2tLQg.js +1 -0
  86. package/page/assets/PaneState-eUzUkNE8.css +1 -0
  87. package/page/assets/ScrollableArea-Ckugdj1N.js +1 -0
  88. package/page/assets/Section-DJ97F7QE.js +1 -0
  89. package/page/assets/SegmentedControlItem-h-aaXzyS.js +1 -0
  90. package/page/assets/SidePanel-BL32abk8.js +1 -0
  91. package/page/assets/StackItem-CQviqAfM.js +1 -0
  92. package/page/assets/Text-bum6zWWx.js +2 -0
  93. package/page/assets/TimestampHoverCard-DQIG0RZF.js +1 -0
  94. package/page/assets/ToolResultCharts-CgshSv9Q.js +1 -0
  95. package/page/assets/Tooltip-BH9xiRMl.js +1 -0
  96. package/page/assets/TraceInspector-_yZiz05W.js +1 -0
  97. package/page/assets/TraceOverview-BPO-HIYK.js +57 -0
  98. package/page/assets/VStack-CkVMcNiK.js +1 -0
  99. package/page/assets/_virtual_studio-type-sources-ByxqQaOG.js +12936 -0
  100. package/page/assets/arrive-DvbqpeRS.js +1 -0
  101. package/page/assets/browser-engine-CYq9DQAM.js +9 -0
  102. package/page/assets/browser-transport-D-2jDYe7.js +47 -0
  103. package/page/assets/codicon-DF1abBS2.ttf +0 -0
  104. package/page/assets/compile-egress-BSxOdX4K.js +23 -0
  105. package/page/assets/container.stylex-BmOi-8DQ.js +1 -0
  106. package/page/assets/createReactComponent-CZwsv6DD.js +1 -0
  107. package/page/assets/decision-example-images-CZGr7YIT.js +1 -0
  108. package/page/assets/devWarning-DxuplmRl.js +1 -0
  109. package/page/assets/editor-DjpsE8to.css +1 -0
  110. package/page/assets/editor.api-Cd3ViPQa.js +908 -0
  111. package/page/assets/editor.worker-6GY8RhDc.js +1 -0
  112. package/page/assets/editor.worker-BmdWdrHZ.js +33 -0
  113. package/page/assets/editors-BJX_S59A.js +1 -0
  114. package/page/assets/egress-automata-B5ZGE1mT.js +1 -0
  115. package/page/assets/embedding-space-view-CfQBPDxD.js +140 -0
  116. package/page/assets/encode-files-Bc3HJyAh.js +1 -0
  117. package/page/assets/export-agent-C3yyzXH8.js +43 -0
  118. package/page/assets/figtree-latin-400-normal-BD4aNku5.woff +0 -0
  119. package/page/assets/figtree-latin-400-normal-g7Dtegnw.woff2 +0 -0
  120. package/page/assets/figtree-latin-500-normal-BWnGEVsr.woff2 +0 -0
  121. package/page/assets/figtree-latin-500-normal-B_yy1phn.woff +0 -0
  122. package/page/assets/figtree-latin-600-normal-BM_oTo4n.woff +0 -0
  123. package/page/assets/figtree-latin-600-normal-Cv_xCTDl.woff2 +0 -0
  124. package/page/assets/figtree-latin-700-normal-BCCt2T1q.woff +0 -0
  125. package/page/assets/figtree-latin-700-normal-th6qEP7c.woff2 +0 -0
  126. package/page/assets/focusOutline.stylex-BT0kfa4t.js +1 -0
  127. package/page/assets/focusableSelector-DXZeMU85.js +1 -0
  128. package/page/assets/groupStyles-C7Ter7zC.js +1 -0
  129. package/page/assets/guardrail-tester-Gut5xK4a.js +9 -0
  130. package/page/assets/host-patterns-C9RMP16Q.js +1 -0
  131. package/page/assets/index-CvvmFKgS.js +105 -0
  132. package/page/assets/index-DOaHlqBo.css +1 -0
  133. package/page/assets/isRtlElement-BG33-k_H.js +1 -0
  134. package/page/assets/labels-provider-4TIWDvsE.js +3 -0
  135. package/page/assets/lent-keys-C32ems-I.js +1 -0
  136. package/page/assets/live-ingress-lDUGPwth.js +1 -0
  137. package/page/assets/live-messages-CnkL4GWi.js +1 -0
  138. package/page/assets/mergeProps-ptS-gIMz.js +1 -0
  139. package/page/assets/padding.stylex-B76907Zf.js +1 -0
  140. package/page/assets/preload-helper-DpV6A1kQ.js +1 -0
  141. package/page/assets/reader-BOCCYaRp.js +7 -0
  142. package/page/assets/register-CDgivxvX.js +2 -0
  143. package/page/assets/rolldown-runtime-hePW80VL.js +1 -0
  144. package/page/assets/schemas-BQ9Jydzb.js +56 -0
  145. package/page/assets/shaped-data-BcarWqd5.js +16 -0
  146. package/page/assets/sharedResizeObserver-4U9Xq5Oq.js +1 -0
  147. package/page/assets/stub-DhdcU_Ew.js +471 -0
  148. package/page/assets/studio-code-pane-C_SAbcOa.js +8 -0
  149. package/page/assets/studio-console-DZwlEsvr.js +3 -0
  150. package/page/assets/studio-decision-B0FnCAXA.js +1 -0
  151. package/page/assets/studio-embedding-CmA51HVo.js +2 -0
  152. package/page/assets/studio-host-console-By7hqu2l.js +2 -0
  153. package/page/assets/studio-live-BrcVQcyV.js +1 -0
  154. package/page/assets/studio-map-B_xSia-z.js +1 -0
  155. package/page/assets/studio-map-Bb06Tw1F.css +1 -0
  156. package/page/assets/studio-monaco-CbKf90i6.css +1 -0
  157. package/page/assets/studio-monaco-xfyfezQS.js +34 -0
  158. package/page/assets/studio-ts.worker-B-EXG4Sv.js +67741 -0
  159. package/page/assets/studio-ts.worker-BXtW3z-O.js +1 -0
  160. package/page/assets/studio-type-checker-BOvxudki.js +23 -0
  161. package/page/assets/themeProps-3IqahpCr.js +1 -0
  162. package/page/assets/tokens.stylex-DkHf0P9C.js +1 -0
  163. package/page/assets/tool-schema-idaOe2nI.js +18 -0
  164. package/page/assets/trace-patterns-DnYJa0nI.js +1 -0
  165. package/page/assets/trace-record-C3zNksA_.js +1 -0
  166. package/page/assets/trace-schema-9CdEyG6Q.js +1 -0
  167. package/page/assets/tree-DqyAMsbI.js +3 -0
  168. package/page/assets/turn-client-Du3Um3Mg.js +2 -0
  169. package/page/assets/types-BhfXQCLx.js +1 -0
  170. package/page/assets/typescript-20GgZ8PJ.js +1 -0
  171. package/page/assets/use-one-call-Hcs8YBp1.js +1 -0
  172. package/page/assets/useAdaptivePresentation-BzmPCddb.js +1 -0
  173. package/page/assets/useClipboard-BgGRxRMJ.js +1 -0
  174. package/page/assets/useContainerReveal-BFy8N_QU.js +1 -0
  175. package/page/assets/useDevWarning-Z9SoixOP.js +1 -0
  176. package/page/assets/useLayerDismissal-B_G7IWpC.js +1 -0
  177. package/page/assets/useMediaQuery-BCT0NUeZ.js +1 -0
  178. package/page/assets/useScrollLock-Dyf6PHJt.js +1 -0
  179. package/page/assets/useScrollableArea-0NzdiBCq.js +1 -0
  180. package/page/assets/useTooltip-CJM_xhLB.js +1 -0
  181. package/page/assets/workspace-DZALqEDX.js +1 -0
  182. package/page/assets/zip-DTcEfps6.js +1 -0
  183. package/page/index.html +90 -0
  184. package/page.mjs +49 -0
  185. package/people.d.ts +87 -0
  186. package/people.js +110 -0
  187. package/policy.d.ts +43 -0
  188. package/policy.js +102 -0
  189. package/ports.d.mts +32 -0
  190. package/ports.mjs +85 -0
  191. package/probe-battery.d.ts +13 -0
  192. package/probe-battery.js +404 -0
  193. package/providers.d.ts +149 -0
  194. package/providers.js +306 -0
  195. package/read-source.d.ts +48 -0
  196. package/read-source.js +1301 -0
  197. package/read-steps.d.ts +23 -0
  198. package/read-steps.js +2 -0
  199. package/reader.d.ts +11 -0
  200. package/reader.js +11 -0
  201. package/registrations.d.ts +83 -0
  202. package/registrations.js +1 -0
  203. package/requirements.d.ts +22 -0
  204. package/requirements.js +38 -0
  205. package/run-payload-core.d.ts +28 -0
  206. package/run-payload-core.js +123 -0
  207. package/run-payload.d.ts +32 -0
  208. package/run-payload.js +26 -0
  209. package/runtime-scope.d.ts +84 -0
  210. package/runtime-scope.js +308 -0
  211. package/runtime.d.ts +84 -0
  212. package/runtime.js +387 -0
  213. package/section-notes.d.ts +33 -0
  214. package/section-notes.js +38 -0
  215. package/serve-page.mjs +96 -0
  216. package/server/draft-decide.d.ts +72 -0
  217. package/server/draft-decide.js +111 -0
  218. package/server/draft-embedding.d.ts +3 -0
  219. package/server/draft-embedding.js +35 -0
  220. package/server/draft-handler.d.ts +82 -0
  221. package/server/draft-handler.js +213 -0
  222. package/server/draft-probe.d.ts +14 -0
  223. package/server/draft-probe.js +61 -0
  224. package/server/draft-replies.d.ts +22 -0
  225. package/server/draft-replies.js +46 -0
  226. package/server/edited-session.d.ts +28 -0
  227. package/server/edited-session.js +83 -0
  228. package/server/edits.d.ts +38 -0
  229. package/server/edits.js +195 -0
  230. package/server/handler.d.ts +133 -0
  231. package/server/handler.js +598 -0
  232. package/server/lent-draft.d.ts +19 -0
  233. package/server/lent-draft.js +23 -0
  234. package/server/live.d.ts +15 -0
  235. package/server/live.js +96 -0
  236. package/server/open-editor.d.ts +63 -0
  237. package/server/open-editor.js +115 -0
  238. package/server/origins.d.ts +18 -0
  239. package/server/origins.js +330 -0
  240. package/server/project-source.d.ts +208 -0
  241. package/server/project-source.js +1042 -0
  242. package/server/project.d.ts +22 -0
  243. package/server/project.js +56 -0
  244. package/server/run-traces.d.ts +20 -0
  245. package/server/run-traces.js +96 -0
  246. package/server/save-new.d.ts +29 -0
  247. package/server/save-new.js +514 -0
  248. package/server/save-plan.d.ts +46 -0
  249. package/server/save-plan.js +1134 -0
  250. package/server/save-remove.d.ts +21 -0
  251. package/server/save-remove.js +528 -0
  252. package/server/save-session.d.ts +96 -0
  253. package/server/save-session.js +418 -0
  254. package/server/save-wire.d.ts +235 -0
  255. package/server/save-wire.js +8 -0
  256. package/server/save.d.ts +52 -0
  257. package/server/save.js +209 -0
  258. package/server/serve.d.ts +23 -0
  259. package/server/serve.js +413 -0
  260. package/server/test-connection.d.ts +17 -0
  261. package/server/test-connection.js +362 -0
  262. package/server/test-key.d.ts +2 -0
  263. package/server/test-key.js +83 -0
  264. package/server/watch.d.ts +28 -0
  265. package/server/watch.js +93 -0
  266. package/server/zod-edit.d.ts +74 -0
  267. package/server/zod-edit.js +558 -0
  268. package/server.d.ts +8 -0
  269. package/server.js +8 -0
  270. package/setups.mjs +170 -0
  271. package/shared-carry.d.ts +114 -0
  272. package/shared-carry.js +523 -0
  273. package/shared-settings.d.ts +34 -0
  274. package/shared-settings.js +70 -0
  275. package/source.d.ts +75 -0
  276. package/source.js +414 -0
  277. package/start.mjs +169 -0
  278. package/stream-lines.d.ts +9 -0
  279. package/stream-lines.js +27 -0
  280. package/stub.d.ts +6 -0
  281. package/stub.js +33 -0
  282. package/surface.d.ts +53 -0
  283. package/surface.js +631 -0
  284. package/system-markup.d.ts +20 -0
  285. package/system-markup.js +51 -0
  286. package/tool-schema.d.ts +23 -0
  287. package/tool-schema.js +69 -0
  288. package/tools.d.ts +16 -0
  289. package/tools.js +91 -0
  290. package/traces.d.ts +24 -0
  291. package/traces.js +29 -0
  292. package/transport.d.ts +57 -0
  293. package/transport.js +187 -0
  294. package/tree.d.ts +32 -0
  295. package/tree.js +83 -0
  296. package/types.d.ts +62 -0
  297. package/types.js +6 -0
  298. package/ui/acting-as-button.d.ts +2 -0
  299. package/ui/acting-as-button.js +16 -0
  300. package/ui/add-provider.d.ts +13 -0
  301. package/ui/add-provider.js +20 -0
  302. package/ui/boot-mark.css +53 -0
  303. package/ui/boot-mark.d.ts +19 -0
  304. package/ui/boot-mark.js +128 -0
  305. package/ui/boot-paint.d.ts +8 -0
  306. package/ui/boot-paint.js +8 -0
  307. package/ui/brand-icons.d.ts +57 -0
  308. package/ui/brand-icons.js +148 -0
  309. package/ui/built/theme.css +830 -0
  310. package/ui/built/theme.css.d.ts +9 -0
  311. package/ui/built/theorem-studio.d.ts +13 -0
  312. package/ui/built/theorem-studio.js +705 -0
  313. package/ui/built/theorem-studio.variants.d.ts +28 -0
  314. package/ui/code/monaco-contributions.d.ts +45 -0
  315. package/ui/code/studio-code.d.ts +7 -0
  316. package/ui/code/studio-code.js +253 -0
  317. package/ui/code/studio-monaco.d.ts +44 -0
  318. package/ui/code/studio-monaco.js +48 -0
  319. package/ui/code/studio-ts.worker.d.ts +1 -0
  320. package/ui/code/studio-ts.worker.js +16 -0
  321. package/ui/code/studio-type-checker.d.ts +12 -0
  322. package/ui/code/studio-type-checker.js +308 -0
  323. package/ui/code/studio-type-sources.d.ts +26 -0
  324. package/ui/confirm-write.d.ts +12 -0
  325. package/ui/confirm-write.js +45 -0
  326. package/ui/diff-block.d.ts +21 -0
  327. package/ui/diff-block.js +17 -0
  328. package/ui/figtree.css +59 -0
  329. package/ui/file-place.d.ts +4 -0
  330. package/ui/file-place.js +26 -0
  331. package/ui/guardrail-tester.d.ts +18 -0
  332. package/ui/guardrail-tester.js +248 -0
  333. package/ui/inspector-context.d.ts +119 -0
  334. package/ui/inspector-context.js +84 -0
  335. package/ui/inspector.d.ts +247 -0
  336. package/ui/inspector.js +284 -0
  337. package/ui/lib/acting-as.d.ts +25 -0
  338. package/ui/lib/acting-as.js +90 -0
  339. package/ui/lib/boot-sequence.d.ts +32 -0
  340. package/ui/lib/boot-sequence.js +57 -0
  341. package/ui/lib/export-agent.d.ts +11 -0
  342. package/ui/lib/export-agent.js +335 -0
  343. package/ui/lib/facet-icons.d.ts +20 -0
  344. package/ui/lib/facet-icons.js +21 -0
  345. package/ui/lib/panel-motion.d.ts +8 -0
  346. package/ui/lib/panel-motion.js +74 -0
  347. package/ui/lib/project-address.d.ts +14 -0
  348. package/ui/lib/project-address.js +24 -0
  349. package/ui/lib/project-starting.d.ts +13 -0
  350. package/ui/lib/project-starting.js +30 -0
  351. package/ui/lib/project-traces.d.ts +17 -0
  352. package/ui/lib/project-traces.js +54 -0
  353. package/ui/lib/read-map.d.ts +30 -0
  354. package/ui/lib/read-map.js +173 -0
  355. package/ui/lib/read-progress.d.ts +14 -0
  356. package/ui/lib/read-progress.js +12 -0
  357. package/ui/lib/refusal-lines.d.ts +3 -0
  358. package/ui/lib/refusal-lines.js +8 -0
  359. package/ui/lib/studio-activity.d.ts +5 -0
  360. package/ui/lib/studio-activity.js +17 -0
  361. package/ui/lib/studio-console.d.ts +27 -0
  362. package/ui/lib/studio-console.js +9 -0
  363. package/ui/lib/studio-conversation.d.ts +20 -0
  364. package/ui/lib/studio-conversation.js +130 -0
  365. package/ui/lib/studio-examples.d.ts +31 -0
  366. package/ui/lib/studio-examples.js +25 -0
  367. package/ui/lib/studio-labels.d.ts +6 -0
  368. package/ui/lib/studio-labels.js +13 -0
  369. package/ui/lib/studio-map-kept.d.ts +17 -0
  370. package/ui/lib/studio-map-kept.js +48 -0
  371. package/ui/lib/studio-open.d.ts +22 -0
  372. package/ui/lib/studio-open.js +54 -0
  373. package/ui/lib/studio-page.d.ts +33 -0
  374. package/ui/lib/studio-page.js +121 -0
  375. package/ui/lib/studio-prefs.d.ts +26 -0
  376. package/ui/lib/studio-prefs.js +87 -0
  377. package/ui/lib/studio-project.d.ts +106 -0
  378. package/ui/lib/studio-project.js +177 -0
  379. package/ui/lib/studio-restore.d.ts +49 -0
  380. package/ui/lib/studio-restore.js +251 -0
  381. package/ui/lib/studio-run-open.d.ts +15 -0
  382. package/ui/lib/studio-run-open.js +16 -0
  383. package/ui/lib/studio-session.d.ts +34 -0
  384. package/ui/lib/studio-session.js +17 -0
  385. package/ui/lib/studio-settings.d.ts +15 -0
  386. package/ui/lib/studio-settings.js +48 -0
  387. package/ui/lib/studio-store.d.ts +64 -0
  388. package/ui/lib/studio-store.js +391 -0
  389. package/ui/lib/studio-watch.d.ts +12 -0
  390. package/ui/lib/studio-watch.js +27 -0
  391. package/ui/lib/tab-fills.d.ts +6 -0
  392. package/ui/lib/tab-fills.js +14 -0
  393. package/ui/lib/tool-credentials.d.ts +3 -0
  394. package/ui/lib/tool-credentials.js +23 -0
  395. package/ui/lib/tool-probe.d.ts +19 -0
  396. package/ui/lib/tool-probe.js +104 -0
  397. package/ui/lib/type-icons.d.ts +35 -0
  398. package/ui/lib/type-icons.js +38 -0
  399. package/ui/lib/when-idle.d.ts +5 -0
  400. package/ui/lib/when-idle.js +14 -0
  401. package/ui/lib/zip.d.ts +5 -0
  402. package/ui/lib/zip.js +8 -0
  403. package/ui/map-token.css +11 -0
  404. package/ui/map-token.d.ts +17 -0
  405. package/ui/map-token.js +29 -0
  406. package/ui/mcp-icon.d.ts +6 -0
  407. package/ui/mcp-icon.js +8 -0
  408. package/ui/motion.css +113 -0
  409. package/ui/pan.d.ts +32 -0
  410. package/ui/pan.js +90 -0
  411. package/ui/profile-editor.d.ts +33 -0
  412. package/ui/profile-editor.js +2638 -0
  413. package/ui/provider-editor.d.ts +15 -0
  414. package/ui/provider-editor.js +92 -0
  415. package/ui/read-map.css +48 -0
  416. package/ui/read-map.d.ts +7 -0
  417. package/ui/read-map.js +163 -0
  418. package/ui/refusal-detail.d.ts +4 -0
  419. package/ui/refusal-detail.js +21 -0
  420. package/ui/shared-change.d.ts +9 -0
  421. package/ui/shared-change.js +28 -0
  422. package/ui/shell-motion.css +121 -0
  423. package/ui/shell-motion.d.ts +73 -0
  424. package/ui/shell-motion.js +194 -0
  425. package/ui/studio-code-pane.d.ts +19 -0
  426. package/ui/studio-code-pane.js +44 -0
  427. package/ui/studio-compare.d.ts +80 -0
  428. package/ui/studio-compare.js +326 -0
  429. package/ui/studio-conflicts.d.ts +17 -0
  430. package/ui/studio-conflicts.js +87 -0
  431. package/ui/studio-connection.d.ts +64 -0
  432. package/ui/studio-connection.js +286 -0
  433. package/ui/studio-decision.d.ts +6 -0
  434. package/ui/studio-decision.js +49 -0
  435. package/ui/studio-embedding.d.ts +6 -0
  436. package/ui/studio-embedding.js +30 -0
  437. package/ui/studio-host-console.d.ts +6 -0
  438. package/ui/studio-host-console.js +17 -0
  439. package/ui/studio-host.d.ts +73 -0
  440. package/ui/studio-host.js +12 -0
  441. package/ui/studio-live.d.ts +17 -0
  442. package/ui/studio-live.js +26 -0
  443. package/ui/studio-map.css +273 -0
  444. package/ui/studio-map.d.ts +17 -0
  445. package/ui/studio-map.js +397 -0
  446. package/ui/studio-nav.d.ts +24 -0
  447. package/ui/studio-nav.js +17 -0
  448. package/ui/studio-no-project.d.ts +5 -0
  449. package/ui/studio-no-project.js +9 -0
  450. package/ui/studio-run.css +76 -0
  451. package/ui/studio-run.d.ts +14 -0
  452. package/ui/studio-run.js +119 -0
  453. package/ui/studio-runner.d.ts +45 -0
  454. package/ui/studio-runner.js +187 -0
  455. package/ui/studio-save.d.ts +49 -0
  456. package/ui/studio-save.js +307 -0
  457. package/ui/studio-screen.d.ts +61 -0
  458. package/ui/studio-screen.js +2078 -0
  459. package/ui/studio-settings.d.ts +31 -0
  460. package/ui/studio-settings.js +288 -0
  461. package/ui/studio-shell.css +27 -0
  462. package/ui/studio-shell.d.ts +43 -0
  463. package/ui/studio-shell.js +87 -0
  464. package/ui/studio-theme.d.ts +7 -0
  465. package/ui/studio-theme.js +94 -0
  466. package/ui/studio.css +427 -0
  467. package/ui/theorem-mark.css +84 -0
  468. package/ui/theorem-mark.d.ts +22 -0
  469. package/ui/theorem-mark.js +21 -0
  470. package/vite.d.mts +30 -0
  471. package/vite.mjs +277 -0
  472. package/workspace.d.ts +230 -0
  473. package/workspace.js +1054 -0
@@ -0,0 +1,31 @@
1
+ import { type ReactNode } from 'react';
2
+ import type { ProjectSession } from './lib/studio-project.ts';
3
+ /** The door to Settings at the foot of the shell's rail. Nothing shows until a screen can open them. */
4
+ export declare function SettingsRailButton(): import("react").JSX.Element | null;
5
+ /** Watching the project's files: absent when the studio command was started without it. */
6
+ export interface WatchChoice {
7
+ on: boolean;
8
+ set: (on: boolean) => void;
9
+ }
10
+ /** Whether changing a shared value asks first, as the store holds it. */
11
+ export interface SharedAsking {
12
+ asks: boolean;
13
+ set: (asks: boolean) => void;
14
+ }
15
+ /** What the Project section can do to this tab; an action is absent when there is nothing for it to do. */
16
+ export interface TabActions {
17
+ clearChats: () => void;
18
+ discard: (() => void) | undefined;
19
+ }
20
+ export interface StudioSettingsProps {
21
+ project: ProjectSession;
22
+ /** The `@theoremjs/agents` version the studio runs. */
23
+ version: string;
24
+ watch: WatchChoice | undefined;
25
+ shared: SharedAsking;
26
+ actions: TabActions;
27
+ /** The key slots, as the studio's Keys panel shows them. */
28
+ keys: ReactNode;
29
+ }
30
+ /** Settings, inside the studio's panel: the panel widens over the preview to hold them. */
31
+ export declare function StudioSettings(props: StudioSettingsProps): import("react").JSX.Element;
@@ -0,0 +1,288 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /**
3
+ * Settings for the studio open on a project: where every choice about how the studio behaves is
4
+ * made. Choices are kept in this browser, keys in this tab, and nothing is written to the project.
5
+ */
6
+ import { AlertDialog } from '@astryxdesign/core/AlertDialog';
7
+ import { Button } from '@astryxdesign/core/Button';
8
+ import { CheckboxInput } from '@astryxdesign/core/CheckboxInput';
9
+ import { Divider } from '@astryxdesign/core/Divider';
10
+ import { Field } from '@astryxdesign/core/Field';
11
+ import { Grid } from '@astryxdesign/core/Grid';
12
+ import { Heading } from '@astryxdesign/core/Heading';
13
+ import { HStack } from '@astryxdesign/core/HStack';
14
+ import { useMediaQuery } from '@astryxdesign/core/hooks';
15
+ import { Icon } from '@astryxdesign/core/Icon';
16
+ import { IconButton } from '@astryxdesign/core/IconButton';
17
+ import { Layout, LayoutContent } from '@astryxdesign/core/Layout';
18
+ import { MetadataList, MetadataListItem } from '@astryxdesign/core/MetadataList';
19
+ import { RadioList, RadioListItem } from '@astryxdesign/core/RadioList';
20
+ import { Section } from '@astryxdesign/core/Section';
21
+ import { SegmentedControl, SegmentedControlItem } from '@astryxdesign/core/SegmentedControl';
22
+ import { StackItem } from '@astryxdesign/core/Stack';
23
+ import { Tab, TabList } from '@astryxdesign/core/TabList';
24
+ import { Text } from '@astryxdesign/core/Text';
25
+ import { TreeList } from '@astryxdesign/core/TreeList';
26
+ import { Typeahead } from '@astryxdesign/core/Typeahead';
27
+ import { VStack } from '@astryxdesign/core/VStack';
28
+ import { IconBrandVscode, IconDeviceDesktopCode, IconPlus, IconSearch, IconSettings, IconX, } from '@tabler/icons-react';
29
+ import { useEffect, useId, useState } from 'react';
30
+ import { editorLabel, STUDIO_EDITORS } from "../editors.js";
31
+ import { IconCursor } from "./brand-icons.js";
32
+ import { freshPerson, listPeople, useActingAs } from "./lib/acting-as.js";
33
+ import { setPref, usePref } from "./lib/studio-prefs.js";
34
+ import { closeSettings, openSettings, SETTINGS_SECTIONS, showSettingsSection, useSettingsDoor, } from "./lib/studio-settings.js";
35
+ import { NAV_WIDTH } from "./studio-nav.js";
36
+ const SECTION_LABELS = {
37
+ files: 'Files',
38
+ confirmations: 'Confirmations',
39
+ keys: 'Keys',
40
+ people: 'People',
41
+ project: 'Project',
42
+ about: 'About',
43
+ };
44
+ /** Every setting by name, for the search: choosing one opens its section. `words` is what else a builder might type. */
45
+ const SETTINGS = [
46
+ {
47
+ id: 'editor',
48
+ label: 'Open files in',
49
+ section: 'files',
50
+ words: 'editor automatic vs code vscode cursor',
51
+ },
52
+ { id: 'watch', label: 'Watch files', section: 'files', words: 'reload save' },
53
+ { id: 'files-toast', label: 'Tell me when files change', section: 'files', words: 'note notify' },
54
+ {
55
+ id: 'ask-shared',
56
+ label: 'Ask before changing a shared value',
57
+ section: 'confirmations',
58
+ words: 'confirm asking',
59
+ },
60
+ {
61
+ id: 'ask-writes',
62
+ label: 'Ask before a tool writes',
63
+ section: 'confirmations',
64
+ words: 'confirm asking destructive run',
65
+ },
66
+ { id: 'keys', label: 'Model keys', section: 'keys', words: 'api key provider' },
67
+ {
68
+ id: 'acting-as',
69
+ label: 'Who a run acts as',
70
+ section: 'people',
71
+ words: 'person user account place sign in',
72
+ },
73
+ { id: 'open-project', label: 'Open project and setup file', section: 'project' },
74
+ {
75
+ id: 'clear-chats',
76
+ label: "Clear this tab's chats",
77
+ section: 'project',
78
+ words: 'conversation reset',
79
+ },
80
+ { id: 'discard', label: 'Discard unsaved edits', section: 'project', words: 'revert reset' },
81
+ { id: 'version', label: 'Package version', section: 'about' },
82
+ { id: 'address', label: 'Studio address', section: 'about', words: 'url port server' },
83
+ ];
84
+ const settingsSource = {
85
+ search: (query) => {
86
+ const asked = query.toLowerCase();
87
+ return SETTINGS.filter((setting) => `${setting.label} ${setting.words ?? ''}`.toLowerCase().includes(asked));
88
+ },
89
+ bootstrap: () => [...SETTINGS],
90
+ };
91
+ /** The door to Settings at the foot of the shell's rail. Nothing shows until a screen can open them. */
92
+ export function SettingsRailButton() {
93
+ const door = useSettingsDoor();
94
+ if (!door.ready)
95
+ return null;
96
+ return (_jsx(IconButton, { label: "Settings", variant: "ghost", size: "lg", icon: _jsx(Icon, { icon: IconSettings }), tooltip: door.open ? 'Back to the studio' : 'Settings', "aria-pressed": door.open, onClick: () => {
97
+ if (door.open)
98
+ closeSettings();
99
+ else
100
+ openSettings();
101
+ } }));
102
+ }
103
+ /** One group of settings: what it is about on the left, its controls on the right. Titled as the editor titles a section. */
104
+ function Group({ title, about, children }) {
105
+ return (_jsxs(Grid, { columns: { minWidth: 320 }, gap: 10, children: [_jsxs(VStack, { gap: 1, children: [_jsx(Text, { type: "label", weight: "semibold", children: title }), _jsx(Text, { type: "supporting", color: "secondary", children: about })] }), _jsx(VStack, { gap: 5, children: children })] }));
106
+ }
107
+ const AUTOMATIC = 'automatic';
108
+ /** Where files open: the studio's own pick, or one of the two editors Settings offers. */
109
+ const EDITOR_CHOICES = [
110
+ { value: AUTOMATIC, label: 'Automatic', icon: IconDeviceDesktopCode },
111
+ ...STUDIO_EDITORS.filter((editor) => editor.choice).map((editor) => ({
112
+ value: editor.command,
113
+ label: editor.label,
114
+ icon: editor.command === 'cursor' ? IconCursor : IconBrandVscode,
115
+ })),
116
+ ];
117
+ /** What Automatic opens files in, in the builder's words. */
118
+ function automaticNote(automatic) {
119
+ return automatic
120
+ ? `Automatic opens ${editorLabel(automatic)}.`
121
+ : 'Automatic opens the editor the studio was started with.';
122
+ }
123
+ function EditorChoice({ automatic }) {
124
+ const editor = usePref('editor');
125
+ const id = useId();
126
+ return (_jsx(Field, { label: "Open files in", description: automaticNote(automatic), inputID: id, isGroupLabel: true, children: _jsx(SegmentedControl, { label: "Open files in", size: "sm", value: editor || AUTOMATIC, onChange: (next) => {
127
+ setPref('editor', next === AUTOMATIC ? '' : next);
128
+ }, children: EDITOR_CHOICES.map((choice) => (_jsx(SegmentedControlItem, { value: choice.value, label: choice.label, icon: _jsx(Icon, { icon: choice.icon, size: "sm" }) }, choice.value))) }) }));
129
+ }
130
+ function FilesSettings({ project, watch, }) {
131
+ const filesToast = usePref('filesToast');
132
+ return (_jsxs(_Fragment, { children: [_jsx(Group, { title: "Your editor", about: "Where a file opens when you follow a setting to the line that sets it.", children: _jsx(EditorChoice, { automatic: project.editor }) }), _jsx(Divider, {}), _jsxs(Group, { title: "Changes from your files", about: "What the studio does when your editor saves a file your setup reads.", children: [_jsx(CheckboxInput, { label: "Watch files", description: "Take in what your editor saves, as it saves. Your unsaved studio edits are kept.", value: watch?.on ?? false, isDisabled: !watch, disabledMessage: "The studio command was started with --no-watch.", onChange: (on) => watch?.set(on) }), _jsx(CheckboxInput, { label: "Tell me when files change", description: "A short note each time a save in your editor changed a setting here.", value: filesToast === 'on', onChange: (on) => {
133
+ setPref('filesToast', on ? 'on' : 'off');
134
+ } })] })] }));
135
+ }
136
+ const isAskWrites = (value) => value === 'always' || value === 'destructive';
137
+ function ConfirmationSettings({ shared }) {
138
+ const askWrites = usePref('askWrites');
139
+ return (_jsxs(_Fragment, { children: [_jsx(Group, { title: "Shared values", about: "A value several agents share changes on every one of them.", children: _jsx(CheckboxInput, { label: "Ask before changing a shared value", description: "Shows which agents and files the change reaches, before it is made.", value: shared.asks, onChange: shared.set }) }), _jsx(Divider, {}), _jsx(Group, { title: "Tools that write", about: "A real run of a tool that writes can change something outside the studio.", children: _jsxs(RadioList, { label: "Ask before a run", value: askWrites, onChange: (next) => {
140
+ if (isAskWrites(next))
141
+ setPref('askWrites', next);
142
+ }, children: [_jsx(RadioListItem, { value: "always", label: "Every tool that writes", description: "Shows the input the run would send, each time." }), _jsx(RadioListItem, { value: "destructive", label: "Only destructive tools", description: "Tools that read and write run straight away. Tools marked destructive still ask." })] }) })] }));
143
+ }
144
+ const NO_ONE = 'no-one';
145
+ const personValue = (person) => `person:${person.id}`;
146
+ function PlacePicker({ offer, place, onChange, }) {
147
+ return (_jsx(SegmentedControl, { label: "Place", size: "sm", value: place, onChange: onChange, children: offer.places.map((each) => (_jsx(SegmentedControlItem, { value: each.id, label: each.label }, each.id))) }));
148
+ }
149
+ /** What went wrong, in the words it was said in. */
150
+ const said = (error) => (error instanceof Error ? error.message : String(error));
151
+ /** The people in a place, as the setup file answers them, and what it said when it could not. */
152
+ function usePeopleIn(project, offer, place) {
153
+ const [found, setFound] = useState();
154
+ useEffect(() => {
155
+ if (!offer.existing)
156
+ return;
157
+ let isCurrent = true;
158
+ listPeople(project, place).then((people) => {
159
+ if (isCurrent)
160
+ setFound({ place, people });
161
+ }, (error) => {
162
+ if (isCurrent)
163
+ setFound({ place, people: [], error: said(error) });
164
+ });
165
+ return () => {
166
+ isCurrent = false;
167
+ };
168
+ }, [project, offer.existing, place]);
169
+ return found?.place === place ? found : undefined;
170
+ }
171
+ /** A new person the setup makes in a place, picked as soon as it is made; and what it said when it could not. */
172
+ function useFreshPerson(project) {
173
+ const { choose } = useActingAs();
174
+ const [made, setMade] = useState([]);
175
+ const [making, setMaking] = useState();
176
+ const make = (place) => {
177
+ setMaking({ place });
178
+ freshPerson(project, place).then((person) => {
179
+ setMade((before) => [...before, { place, person }]);
180
+ setMaking(undefined);
181
+ choose({ place, person });
182
+ }, (error) => {
183
+ setMaking({ place, error: said(error) });
184
+ });
185
+ };
186
+ return { made, making, make };
187
+ }
188
+ /** The people to offer in a place: the ones the setup listed, then any picked or made here it did not. */
189
+ function shownPeople(place, listed, actingAs, made) {
190
+ const shown = [...listed];
191
+ const here = [...(actingAs ? [actingAs] : []), ...made].filter((each) => each.place === place);
192
+ for (const { person } of here)
193
+ if (!shown.some((each) => each.id === person.id))
194
+ shown.push(person);
195
+ return shown;
196
+ }
197
+ /** The radio the pick shows as in a place: no one, its person, or none when the person is elsewhere. */
198
+ function pickedIn(place, actingAs) {
199
+ if (!actingAs)
200
+ return NO_ONE;
201
+ return actingAs.place === place ? personValue(actingAs.person) : '';
202
+ }
203
+ function PersonList({ place, shown }) {
204
+ const { actingAs, choose } = useActingAs();
205
+ return (_jsxs(RadioList, { label: "Person", value: pickedIn(place, actingAs), onChange: (next) => {
206
+ if (next === NO_ONE)
207
+ choose(undefined);
208
+ const person = shown.find((each) => personValue(each) === next);
209
+ if (person)
210
+ choose({ place, person });
211
+ }, children: [_jsx(RadioListItem, { value: NO_ONE, label: "No one", description: "Runs act for no one." }), shown.map((person) => (_jsx(RadioListItem, { value: personValue(person), label: person.label, description: _jsx(Text, { type: "supporting", color: "secondary", maxLines: 1, hasTruncateTooltip: "end", children: person.id }) }, person.id)))] }));
212
+ }
213
+ function Muted({ children }) {
214
+ return (_jsx(Text, { type: "supporting", color: "secondary", children: children }));
215
+ }
216
+ function PeoplePicker({ project, offer }) {
217
+ const { actingAs } = useActingAs();
218
+ const [place, setPlace] = useState(actingAs?.place ?? offer.places[0]?.id ?? '');
219
+ const placeId = useId();
220
+ const found = usePeopleIn(project, offer, place);
221
+ const fresh = useFreshPerson(project);
222
+ const makingHere = fresh.making?.place === place ? fresh.making : undefined;
223
+ const error = found?.error ?? makingHere?.error;
224
+ return (_jsxs(_Fragment, { children: [_jsx(Field, { label: "Place", description: "Where the people your app names live.", inputID: placeId, isGroupLabel: true, children: _jsx(PlacePicker, { offer: offer, place: place, onChange: setPlace }) }), _jsx(PersonList, { place: place, shown: shownPeople(place, found?.people ?? [], actingAs, fresh.made) }), offer.existing && !found && _jsx(Muted, { children: "Finding the people here\u2026" }), offer.fresh && (_jsx(HStack, { children: _jsx(Button, { label: "New person", variant: "secondary", icon: _jsx(Icon, { icon: IconPlus, size: "sm" }), isDisabled: makingHere !== undefined && makingHere.error === undefined, onClick: () => {
225
+ fresh.make(place);
226
+ } }) })), error && _jsx(Muted, { children: error })] }));
227
+ }
228
+ function PeopleSettings({ project }) {
229
+ const { offer, problem } = useActingAs();
230
+ return (_jsx(Group, { title: "Who a run acts as", about: "Your app's tools act for this person. Your setup file names the places and the people, and makes new ones.", children: offer ? (_jsx(PeoplePicker, { project: project, offer: offer })) : (_jsx(Muted, { children: problem ?? 'Your setup file offers no people, so every run acts as no one.' })) }));
231
+ }
232
+ function ProjectSettings({ project, actions }) {
233
+ const [clearing, setClearing] = useState(false);
234
+ return (_jsxs(_Fragment, { children: [_jsx(Group, { title: "Open project", about: "What the studio command opened. The studio reads it from your files.", children: _jsxs(MetadataList, { children: [_jsx(MetadataListItem, { label: "Project", children: project.name }), project.setup && _jsx(MetadataListItem, { label: "Setup file", children: project.setup }), _jsx(MetadataListItem, { label: "Agents", children: String(project.profiles.length) })] }) }), _jsx(Divider, {}), _jsxs(Group, { title: "This tab", about: "What this tab holds that your files do not.", children: [_jsxs(VStack, { gap: 1, children: [_jsx(HStack, { children: _jsx(Button, { label: "Clear this tab's chats", variant: "secondary", onClick: () => {
235
+ setClearing(true);
236
+ } }) }), _jsx(Text, { type: "supporting", color: "secondary", children: "Every agent's preview conversation starts again." })] }), _jsxs(VStack, { gap: 1, children: [_jsx(HStack, { children: _jsx(Button, { label: "Discard unsaved edits", variant: "secondary", isDisabled: !actions.discard, onClick: actions.discard }) }), _jsx(Text, { type: "supporting", color: "secondary", children: actions.discard
237
+ ? 'The studio opens your files as they are. Undo brings the edits back.'
238
+ : 'Nothing here differs from your files.' })] })] }), _jsx(AlertDialog, { isOpen: clearing, onOpenChange: setClearing, title: "Clear this tab's chats?", description: "Every agent's preview conversation in this tab is removed. This can't be undone.", actionLabel: "Clear chats", actionVariant: "destructive", onAction: () => {
239
+ actions.clearChats();
240
+ setClearing(false);
241
+ } })] }));
242
+ }
243
+ function AboutSettings({ project, version }) {
244
+ return (_jsx(Group, { title: "This studio", about: "Settings are kept in this browser. Keys stay in this tab. Neither is written to your project.", children: _jsxs(MetadataList, { children: [_jsx(MetadataListItem, { label: "Package", children: `@theoremjs/agents ${version}` }), _jsx(MetadataListItem, { label: "Studio address", children: `${location.origin}/studio/` }), _jsx(MetadataListItem, { label: "Project server", children: new URL(project.endpoint, location.href).origin })] }) }));
245
+ }
246
+ function SectionBody({ section, ...props }) {
247
+ switch (section) {
248
+ case 'files':
249
+ return _jsx(FilesSettings, { project: props.project, watch: props.watch });
250
+ case 'confirmations':
251
+ return _jsx(ConfirmationSettings, { shared: props.shared });
252
+ case 'keys':
253
+ return (_jsx(Group, { title: "Model keys", about: "Your own keys, to run an agent with. Never saved, never written to your project.", children: props.keys }));
254
+ case 'people':
255
+ return _jsx(PeopleSettings, { project: props.project });
256
+ case 'project':
257
+ return _jsx(ProjectSettings, { project: props.project, actions: props.actions });
258
+ default:
259
+ return _jsx(AboutSettings, { project: props.project, version: props.version });
260
+ }
261
+ }
262
+ const isSection = (value) => SETTINGS_SECTIONS.includes(value);
263
+ /** The nav's head, as the studio's tree and the docs head theirs: the name, what is open, then the search. */
264
+ function SettingsNavHead({ project, version }) {
265
+ return (_jsxs(VStack, { gap: 4, children: [_jsxs(VStack, { gap: 1, children: [_jsx(Heading, { level: 3, children: "theorem studio" }), _jsx(Text, { type: "supporting", color: "secondary", children: `${project.name} · @theoremjs/agents ${version}` })] }), _jsx(Typeahead, { label: "Search", isLabelHidden: true, placeholder: "Search settings...", searchSource: settingsSource, value: null, onChange: (item) => {
266
+ const found = SETTINGS.find((setting) => setting.id === item?.id);
267
+ if (found)
268
+ showSettingsSection(found.section);
269
+ }, hasEntriesOnFocus: true, startIcon: IconSearch })] }));
270
+ }
271
+ /** The widest the settings grow, so a wide screen does not stretch a row across it. */
272
+ const SETTINGS_WIDTH = '72rem';
273
+ /** Settings, inside the studio's panel: the panel widens over the preview to hold them. */
274
+ export function StudioSettings(props) {
275
+ const isNarrow = useMediaQuery('(max-width: 768px)');
276
+ const { section } = useSettingsDoor();
277
+ return (_jsx(Section, { variant: "transparent", height: "100%", padding: 0, children: _jsx(Layout, { height: "fill", start: isNarrow ? undefined : (_jsx(Section, { variant: "transparent", width: NAV_WIDTH, height: "100%", padding: 4, dividers: ['end'], children: _jsxs(VStack, { gap: 4, height: "100%", children: [_jsx(SettingsNavHead, { project: props.project, version: props.version }), _jsx(TreeList, { className: "studio-settings-tree", density: "compact", "aria-label": "Settings", items: SETTINGS_SECTIONS.map((each) => ({
278
+ id: each,
279
+ label: SECTION_LABELS[each],
280
+ isSelected: section === each,
281
+ onClick: () => {
282
+ showSettingsSection(each);
283
+ },
284
+ })) })] }) })), content: _jsxs(LayoutContent, { padding: 0, children: [_jsx(Section, { variant: "transparent", padding: 3, dividers: ['bottom'], children: _jsxs(HStack, { gap: 2, vAlign: "center", children: [_jsx(StackItem, { size: "fill", children: _jsx(Heading, { level: 4, maxLines: 1, children: SECTION_LABELS[section] }) }), _jsx(IconButton, { label: "Close settings", variant: "ghost", icon: _jsx(Icon, { icon: IconX, size: "sm" }), tooltip: "Back to the studio", onClick: closeSettings })] }) }), _jsx(Section, { variant: "transparent", padding: 3, maxWidth: SETTINGS_WIDTH, className: "studio-settings-body", children: _jsxs(VStack, { gap: 4, children: [isNarrow && _jsx(SettingsNavHead, { project: props.project, version: props.version }), isNarrow && (_jsx(VStack, { hAlign: "center", children: _jsx(TabList, { value: section, onChange: (next) => {
285
+ if (isSection(next))
286
+ showSettingsSection(next);
287
+ }, children: SETTINGS_SECTIONS.map((each) => (_jsx(Tab, { value: each, label: SECTION_LABELS[each] }, each))) }) })), _jsx(SectionBody, { section: section, ...props })] }) })] }) }) }));
288
+ }
@@ -0,0 +1,27 @@
1
+ /*
2
+ * A panel scrolls in Astryx's ScrollableArea. Its content box is at least as
3
+ * tall as the scrollport, so a short body leaves an empty stretch under the
4
+ * rows. Nothing in a panel needs that minimum. The :not(#) chain is how
5
+ * Astryx locks the minimum; the class has to match it to let the box size to
6
+ * the rows.
7
+ */
8
+ .theorem-panel-scroll [data-scroll-content]:not(#\#):not(#\#):not(#\#):not(#\#) {
9
+ min-height: auto;
10
+ }
11
+
12
+ /* The rail is inline at md and up. Only when it yields to the drawer
13
+ should the page take the same start inset as top and right. */
14
+ @media (width < 768px) {
15
+ [role="main"] {
16
+ margin-inline-start: var(--spacing-4);
17
+ width: calc(100% - 2 * var(--spacing-4));
18
+ }
19
+ }
20
+
21
+ /* A dialog sits in the top layer, above the rail and the screen's edge. Insetting it to the shell's
22
+ page (see ShellBounds) centres it there. Menus and pickers are left to Astryx: an inset moves
23
+ them off the field they open under. */
24
+ dialog:modal {
25
+ inset: var(--shell-top, 0px) var(--shell-right, 0px) var(--shell-bottom, 0px)
26
+ var(--shell-left, 0px);
27
+ }
@@ -0,0 +1,43 @@
1
+ import { type DefinedTheme } from '@astryxdesign/core/theme';
2
+ import { type ReactNode, type SVGProps } from 'react';
3
+ import { type PackageLinks } from './studio-nav.ts';
4
+ /**
5
+ * JSR brand mark (from jsr.io's icon), filled in the current colour. It spans the
6
+ * full 24-unit box, as Tabler's brand-npm does with its stroke, so Astryx's icon
7
+ * sizing sets both at the same visual size.
8
+ */
9
+ declare function IconJsr(props: SVGProps<SVGSVGElement>): import("react").JSX.Element;
10
+ /** The icon each of the rail's rows carries, by its label. */
11
+ export declare const PAGE_ICONS: {
12
+ readonly Studio: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
13
+ readonly Docs: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
14
+ };
15
+ export declare const PACKAGE_ICONS: {
16
+ readonly GitHub: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
17
+ readonly JSR: typeof IconJsr;
18
+ readonly npm: import("react").ForwardRefExoticComponent<import("@tabler/icons-react").IconProps & import("react").RefAttributes<SVGSVGElement>>;
19
+ };
20
+ export interface StudioRailProps {
21
+ /** The theme the page is drawn in. The rail is always its dark mode, so its icons read on black. */
22
+ theme: DefinedTheme;
23
+ /** The path of the page on screen, which picks the selected row. */
24
+ pathname: string;
25
+ /** Where the package is published. */
26
+ packages: PackageLinks;
27
+ /**
28
+ * The website's address, given when the studio runs away from it. The studio is then this
29
+ * page, and every other page opens on the website: the pages in a new tab, so the studio stays open.
30
+ */
31
+ site?: string;
32
+ /** What sits at the foot of the rail. */
33
+ footerIcons?: ReactNode;
34
+ }
35
+ /** The icon rail: the mark, the website's pages, and where the package is published. */
36
+ export declare function StudioRail({ theme, pathname, packages, site, footerIcons }: StudioRailProps): import("react").JSX.Element;
37
+ /**
38
+ * Publishes where the shell's page sits as `--shell-top|right|bottom|left` (distance from each
39
+ * viewport edge). A dialog lives in the browser's top layer, which a clip cannot reach, so
40
+ * studio-shell.css insets it to this box and it centres there.
41
+ */
42
+ export declare function ShellBounds(): null;
43
+ export {};
@@ -0,0 +1,87 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * The shell the studio sits in: the icon rail on the black base, and the page beside it. The
4
+ * website frames every page with these; the studio on its own frames its one page the same way.
5
+ */
6
+ import { Icon } from '@astryxdesign/core/Icon';
7
+ import { SideNav, SideNavHeading, SideNavItem, SideNavSection } from '@astryxdesign/core/SideNav';
8
+ import { Theme } from '@astryxdesign/core/theme';
9
+ import { IconBook2, IconBrandGithub, IconBrandNpm, IconPlayerPlay } from '@tabler/icons-react';
10
+ import { useEffect } from 'react';
11
+ import { SITE_PAGES } from "./studio-nav.js";
12
+ import { IconTheorem } from "./theorem-mark.js";
13
+ import './studio-shell.css';
14
+ /**
15
+ * JSR brand mark (from jsr.io's icon), filled in the current colour. It spans the
16
+ * full 24-unit box, as Tabler's brand-npm does with its stroke, so Astryx's icon
17
+ * sizing sets both at the same visual size.
18
+ */
19
+ function IconJsr(props) {
20
+ return (_jsx("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": true, ...props, children: _jsx("path", { d: "M3.692 5.538v3.693H0v7.384h7.385v1.847h12.923v-3.693H24V7.385h-7.385V5.538Zm1.846 1.847h1.847v7.384H1.846v-3.692h1.846v1.846h1.846zm3.693 0h5.538V9.23h-3.692v1.846h3.692v5.538H9.231V14.77h3.692v-1.846H9.231Zm7.384 1.846h5.539v3.692h-1.846v-1.846h-1.846v5.538h-1.847z" }) }));
21
+ }
22
+ /**
23
+ * Astryx link component for off-site destinations: opens in a new tab with no opener.
24
+ * Astryx hands custom link components `to` alongside `href` (for routers); a plain anchor drops it.
25
+ */
26
+ function NewTabLink({ to: _to, ...props }) {
27
+ return _jsx("a", { ...props, target: "_blank", rel: "noopener noreferrer" });
28
+ }
29
+ /** The icon each of the rail's rows carries, by its label. */
30
+ export const PAGE_ICONS = { Studio: IconPlayerPlay, Docs: IconBook2 };
31
+ export const PACKAGE_ICONS = { GitHub: IconBrandGithub, JSR: IconJsr, npm: IconBrandNpm };
32
+ /** A rail row's icon, a size up from the rail's own, so the marks read on a large screen. */
33
+ function railIcon(icon, isSelected = false) {
34
+ return _jsx(Icon, { icon: icon, size: "md", color: isSelected ? 'inherit' : 'secondary' });
35
+ }
36
+ /** The icon rail: the mark, the website's pages, and where the package is published. */
37
+ export function StudioRail({ theme, pathname, packages, site, footerIcons }) {
38
+ const at = (href) => {
39
+ if (site === undefined)
40
+ return href;
41
+ return href === '/studio' ? '/studio/' : `${site}${href}`;
42
+ };
43
+ return (_jsx(Theme, { theme: theme, mode: "dark", children: _jsxs(SideNav, { collapsible: { isCollapsed: true, hasButton: false }, header: _jsx(SideNavHeading, { heading: "theorem", headingHref: at('/'), icon: railIcon(IconTheorem, true) }), footerIcons: footerIcons, children: [_jsx(SideNavSection, { title: "Site", isHeaderHidden: true, children: SITE_PAGES.map(({ label, href }) => {
44
+ const isSelected = pathname === href || pathname.startsWith(`${href}/`);
45
+ return (_jsx(SideNavItem, { label: label, href: at(href), size: "lg", icon: railIcon(PAGE_ICONS[label], isSelected), as: site !== undefined && href !== '/studio' ? NewTabLink : undefined, isSelected: isSelected, "data-home-nav-anchor": href }, href));
46
+ }) }), _jsx(SideNavSection, { title: "Packages", isHeaderHidden: true, children: packages.map(({ label, href }) => (_jsx(SideNavItem, { label: label, href: href, size: "lg", icon: railIcon(PACKAGE_ICONS[label]), as: NewTabLink, "data-home-nav-anchor": href }, href))) })] }) }));
47
+ }
48
+ const MAIN_ID = 'astryx-app-shell-main';
49
+ const VARS = ['top', 'right', 'bottom', 'left'];
50
+ /**
51
+ * Publishes where the shell's page sits as `--shell-top|right|bottom|left` (distance from each
52
+ * viewport edge). A dialog lives in the browser's top layer, which a clip cannot reach, so
53
+ * studio-shell.css insets it to this box and it centres there.
54
+ */
55
+ export function ShellBounds() {
56
+ useEffect(() => {
57
+ const root = document.documentElement;
58
+ const main = document.getElementById(MAIN_ID);
59
+ if (!main)
60
+ return;
61
+ const measure = () => {
62
+ const box = main.getBoundingClientRect();
63
+ const edges = {
64
+ top: box.top,
65
+ right: globalThis.innerWidth - box.right,
66
+ bottom: globalThis.innerHeight - box.bottom,
67
+ left: box.left,
68
+ };
69
+ for (const edge of VARS)
70
+ root.style.setProperty(`--shell-${edge}`, `${String(Math.max(0, edges[edge]))}px`);
71
+ };
72
+ measure();
73
+ const observer = new ResizeObserver(measure);
74
+ observer.observe(main);
75
+ globalThis.addEventListener('resize', measure);
76
+ /* The shell moves between pages without resizing; re-measure as a dialog opens. */
77
+ document.addEventListener('beforetoggle', measure, true);
78
+ return () => {
79
+ observer.disconnect();
80
+ globalThis.removeEventListener('resize', measure);
81
+ document.removeEventListener('beforetoggle', measure, true);
82
+ for (const edge of VARS)
83
+ root.style.removeProperty(`--shell-${edge}`);
84
+ };
85
+ }, []);
86
+ return null;
87
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * The look of the studio and the shell it sits in: Theorem's theme on a black base, with the page
3
+ * drawn as a rounded panel inset from the viewport edges beside the rail. The website's theme
4
+ * extends this one, so the studio looks the same on the website and on its own.
5
+ * `npm --prefix studio run theme:build` compiles it to `built/`, which is what a page imports.
6
+ */
7
+ export declare const studioTheme: import("@astryxdesign/core/theme").ResolvedDefinedTheme;
@@ -0,0 +1,94 @@
1
+ import { defineTheme } from '@astryxdesign/core/theme';
2
+ import { tablerIcons } from '@theoremjs/react/ui/icons';
3
+ import { theoremTheme } from '@theoremjs/react/ui/theme';
4
+ /**
5
+ * The look of the studio and the shell it sits in: Theorem's theme on a black base, with the page
6
+ * drawn as a rounded panel inset from the viewport edges beside the rail. The website's theme
7
+ * extends this one, so the studio looks the same on the website and on its own.
8
+ * `npm --prefix studio run theme:build` compiles it to `built/`, which is what a page imports.
9
+ */
10
+ export const studioTheme = defineTheme({
11
+ name: 'theorem-studio',
12
+ extends: theoremTheme,
13
+ // Restated so the built module carries the registry; a build keeps only the icons its source imports.
14
+ icons: tablerIcons,
15
+ tokens: {
16
+ // Behind the rail and the page panel, in both modes.
17
+ '--color-background-body': '#000000',
18
+ // The type ladder, a step above Astryx's: body is 16px, not 14px. Text and heading types read these.
19
+ '--font-size-xs': '0.6875rem',
20
+ '--font-size-sm': '0.875rem',
21
+ '--font-size-base': '1rem',
22
+ '--font-size-lg': '1.1875rem',
23
+ '--font-size-xl': '1.375rem',
24
+ '--font-size-2xl': '1.625rem',
25
+ '--font-size-3xl': '2rem',
26
+ '--font-size-4xl': '2.375rem',
27
+ '--font-size-5xl': '2.75rem',
28
+ },
29
+ components: {
30
+ // why: Astryx fixes every toast at 400px, so a short message sits in a wide empty box. Let it
31
+ // size to its text; the viewport lines toasts up on the end edge, so the toast stays there.
32
+ toast: {
33
+ base: {
34
+ width: 'fit-content',
35
+ minWidth: 'min(240px, 100%)',
36
+ justifySelf: 'end',
37
+ },
38
+ },
39
+ // AppShell's elevated variant only rounds the panel when a TopNav is
40
+ // present; with the rail alone, inset top, bottom, and the trailing edge.
41
+ // The leading edge stays flush to the rail. The matching start inset
42
+ // is added in studio-shell.css only below the drawer breakpoint.
43
+ 'layout-content': {
44
+ base: {
45
+ ':where([role="main"])': {
46
+ height: 'calc(100% - 2 * var(--spacing-4))',
47
+ marginBlock: 'var(--spacing-4)',
48
+ marginInlineEnd: 'var(--spacing-4)',
49
+ borderRadius: 'var(--radius-page)',
50
+ },
51
+ },
52
+ },
53
+ // A clear gap between rail groups; Astryx's own section spacing reads as one list.
54
+ 'side-nav-section': {
55
+ base: {
56
+ paddingBlock: 'var(--spacing-3)',
57
+ },
58
+ },
59
+ // Neutral's selected fill (accent-muted) matches the dark page surface, so a selected row
60
+ // vanishes; the pressed overlay reads on any surface in either mode.
61
+ 'tree-list-item': {
62
+ 'selected:selected': {
63
+ backgroundColor: 'var(--color-overlay-pressed)',
64
+ },
65
+ },
66
+ // A name longer than its column (a tool's snake_case, which never wraps) ends in an ellipsis
67
+ // rather than running under the column's edge.
68
+ 'tree-list-item-label': {
69
+ base: {
70
+ minWidth: '0',
71
+ overflow: 'hidden',
72
+ textOverflow: 'ellipsis',
73
+ whiteSpace: 'nowrap',
74
+ },
75
+ },
76
+ // Same fill and corners as the elevated shell's page panel (surface + radius-page, no border),
77
+ // for pages that sit on the base and draw their own panels.
78
+ section: {
79
+ 'variant:raised': {
80
+ backgroundColor: 'var(--color-background-surface)',
81
+ borderRadius: 'var(--radius-page)',
82
+ // Content scrolling past the rounded corners would otherwise draw outside them.
83
+ overflow: 'clip',
84
+ },
85
+ },
86
+ // Inline code in prose reads as part of its sentence: the sentence's own typeface, at its size
87
+ // and weight. Astryx sets it in the code typeface.
88
+ code: {
89
+ base: {
90
+ fontFamily: 'inherit',
91
+ },
92
+ },
93
+ },
94
+ });