@jxsuite/studio 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (419) hide show
  1. package/canvas.html +21 -0
  2. package/dist/chunks/Overlay.dev-qfjzkms8.js +23 -0
  3. package/dist/chunks/{Overlay.dev-cszx7yn5.js.map → Overlay.dev-qfjzkms8.js.map} +1 -1
  4. package/dist/chunks/{adapter-z8fkmbmv.js → adapter-qfnesn5v.js} +2 -2
  5. package/dist/chunks/{cf-settings-mmyv436d.js → cf-settings-73sh5z4p.js} +3 -3
  6. package/dist/chunks/{components-0hzentwq.js → components-2bpqp4mq.js} +5 -7
  7. package/dist/chunks/{components-0hzentwq.js.map → components-2bpqp4mq.js.map} +1 -1
  8. package/dist/chunks/content-source-34gnkbnn.js +38 -0
  9. package/dist/chunks/content-source-34gnkbnn.js.map +9 -0
  10. package/dist/chunks/convert-to-repeater-t8kxre5s.js +258 -0
  11. package/dist/chunks/convert-to-repeater-t8kxre5s.js.map +10 -0
  12. package/dist/chunks/extension-sections-6mqydz35.js +301 -0
  13. package/dist/chunks/extension-sections-6mqydz35.js.map +11 -0
  14. package/dist/chunks/files-8kn321h1.js +70 -0
  15. package/dist/chunks/files-8kn321h1.js.map +9 -0
  16. package/dist/chunks/{format-host-2c188n41.js → format-host-mkwsmt8d.js} +3 -3
  17. package/dist/chunks/git-panel-tjbr191d.js +51 -0
  18. package/dist/chunks/git-panel-tjbr191d.js.map +9 -0
  19. package/dist/chunks/{index-baeg2x3y.js → index-7pxchcce.js} +4 -3
  20. package/dist/chunks/{index-baeg2x3y.js.map → index-7pxchcce.js.map} +3 -3
  21. package/dist/chunks/{jx-validate-qx8degj7.js → jx-validate-v6qgknrs.js} +3 -3
  22. package/dist/chunks/layers-panel-87pb25km.js +58 -0
  23. package/dist/chunks/layers-panel-87pb25km.js.map +9 -0
  24. package/dist/chunks/{monaco-setup-zjdp9zdw.js → monaco-setup-e0yh25j4.js} +4 -75
  25. package/dist/chunks/{monaco-setup-zjdp9zdw.js.map → monaco-setup-e0yh25j4.js.map} +3 -4
  26. package/dist/chunks/publish-panel-m0fcgdrt.js +21 -0
  27. package/dist/chunks/publish-panel-m0fcgdrt.js.map +9 -0
  28. package/dist/chunks/quick-search-rhs6cbsb.js +53 -0
  29. package/dist/chunks/quick-search-rhs6cbsb.js.map +9 -0
  30. package/dist/chunks/right-panel-zpdxd98t.js +37 -0
  31. package/dist/chunks/right-panel-zpdxd98t.js.map +9 -0
  32. package/dist/chunks/section-registry-zmckaxf4.js +30 -0
  33. package/dist/chunks/section-registry-zmckaxf4.js.map +9 -0
  34. package/dist/chunks/sp-overlay.dev-9ran0sfq.js +18 -0
  35. package/dist/chunks/sp-overlay.dev-9ran0sfq.js.map +9 -0
  36. package/dist/chunks/sp-popover.dev-rebmdncr.js +9 -0
  37. package/dist/chunks/sp-popover.dev-rebmdncr.js.map +9 -0
  38. package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js +15 -0
  39. package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js.map +9 -0
  40. package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js +15 -0
  41. package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js.map +9 -0
  42. package/dist/chunks/{sp-tray.dev-pb2fsd65.js → sp-tray.dev-ey59vfh7.js} +10 -8
  43. package/dist/chunks/{sp-tray.dev-pb2fsd65.js.map → sp-tray.dev-ey59vfh7.js.map} +2 -2
  44. package/dist/chunks/{studio-9qr6fq7p.js → studio-0rqqhrdy.js} +10 -378
  45. package/dist/chunks/{studio-9qr6fq7p.js.map → studio-0rqqhrdy.js.map} +4 -14
  46. package/dist/chunks/{studio-5x6tqqec.js → studio-2sj1jj3v.js} +10 -8
  47. package/dist/chunks/{studio-5x6tqqec.js.map → studio-2sj1jj3v.js.map} +2 -2
  48. package/dist/chunks/{studio-h3fw0wn8.js → studio-3fk1ac9z.js} +6 -4
  49. package/dist/chunks/{studio-h3fw0wn8.js.map → studio-3fk1ac9z.js.map} +2 -2
  50. package/dist/chunks/studio-41exgzhq.js +6690 -0
  51. package/dist/chunks/studio-41exgzhq.js.map +38 -0
  52. package/dist/chunks/{studio-7v2bpweq.js → studio-4mqb9a0j.js} +6 -4
  53. package/dist/chunks/{studio-7v2bpweq.js.map → studio-4mqb9a0j.js.map} +2 -2
  54. package/dist/chunks/studio-50k77cca.js +1787 -0
  55. package/dist/chunks/studio-50k77cca.js.map +18 -0
  56. package/dist/chunks/{studio-56v3zwk6.js → studio-6a0h7sne.js} +10 -8
  57. package/dist/chunks/{studio-56v3zwk6.js.map → studio-6a0h7sne.js.map} +2 -2
  58. package/dist/chunks/studio-6f0am8f2.js +53 -0
  59. package/dist/chunks/studio-6f0am8f2.js.map +10 -0
  60. package/dist/chunks/studio-6nmjc5qk.js +7002 -0
  61. package/dist/chunks/studio-6nmjc5qk.js.map +32 -0
  62. package/dist/chunks/studio-7afd21nw.js +67 -0
  63. package/dist/chunks/studio-7afd21nw.js.map +10 -0
  64. package/dist/chunks/{studio-xze4zrs1.js → studio-7bmdvzne.js} +2 -2
  65. package/dist/chunks/studio-7bmdvzne.js.map +10 -0
  66. package/dist/chunks/studio-8jpzqk5s.js +128 -0
  67. package/dist/chunks/studio-8jpzqk5s.js.map +10 -0
  68. package/dist/chunks/studio-94m77tgk.js +1482 -0
  69. package/dist/chunks/studio-94m77tgk.js.map +13 -0
  70. package/dist/chunks/studio-9je6w5sq.js +1000 -0
  71. package/dist/chunks/studio-9je6w5sq.js.map +16 -0
  72. package/dist/chunks/{studio-w7c6kvk7.js → studio-a7pzveq1.js} +2 -2
  73. package/dist/chunks/{studio-97qcgvdn.js → studio-adn0z1k3.js} +14 -8
  74. package/dist/chunks/{studio-97qcgvdn.js.map → studio-adn0z1k3.js.map} +3 -3
  75. package/dist/chunks/{studio-kr88ryr7.js → studio-bsxxx3x2.js} +17 -15
  76. package/dist/chunks/{studio-kr88ryr7.js.map → studio-bsxxx3x2.js.map} +7 -6
  77. package/dist/chunks/studio-bw5dz6km.js +608 -0
  78. package/dist/chunks/studio-bw5dz6km.js.map +21 -0
  79. package/dist/chunks/studio-c6s5getc.js +4232 -0
  80. package/dist/chunks/studio-c6s5getc.js.map +39 -0
  81. package/dist/chunks/studio-cjm7fdjf.js +451 -0
  82. package/dist/chunks/studio-cjm7fdjf.js.map +14 -0
  83. package/dist/chunks/{studio-cx91mnh8.js → studio-ckwz4d3x.js} +53 -53
  84. package/dist/chunks/{studio-cx91mnh8.js.map → studio-ckwz4d3x.js.map} +5 -5
  85. package/dist/chunks/studio-dg7zyt5x.js +28 -0
  86. package/dist/chunks/studio-dg7zyt5x.js.map +10 -0
  87. package/dist/chunks/studio-dzcyvvvz.js +166 -0
  88. package/dist/chunks/studio-dzcyvvvz.js.map +10 -0
  89. package/dist/chunks/{studio-7kqe41sa.js → studio-evkr5d3b.js} +15 -7
  90. package/dist/chunks/{studio-7kqe41sa.js.map → studio-evkr5d3b.js.map} +5 -4
  91. package/dist/chunks/studio-f12h6177.js +411 -0
  92. package/dist/chunks/studio-f12h6177.js.map +13 -0
  93. package/dist/chunks/studio-hbp1s8m9.js +1817 -0
  94. package/dist/chunks/studio-hbp1s8m9.js.map +14 -0
  95. package/dist/chunks/studio-k2sxjph5.js +15295 -0
  96. package/dist/chunks/studio-k2sxjph5.js.map +235 -0
  97. package/dist/chunks/studio-myje51t3.js +385 -0
  98. package/dist/chunks/studio-myje51t3.js.map +12 -0
  99. package/dist/chunks/studio-na6rwzhw.js +353 -0
  100. package/dist/chunks/studio-na6rwzhw.js.map +11 -0
  101. package/dist/chunks/{studio-4k0m4fmp.js → studio-p471gg5n.js} +126 -3
  102. package/dist/chunks/studio-p471gg5n.js.map +14 -0
  103. package/dist/chunks/{studio-9bjwf0d4.js → studio-rgwcpast.js} +5 -46
  104. package/dist/chunks/{studio-9bjwf0d4.js.map → studio-rgwcpast.js.map} +4 -5
  105. package/dist/chunks/{studio-hhj92gcr.js → studio-s519zc99.js} +3 -3
  106. package/dist/chunks/studio-sas7mt3k.js +75 -0
  107. package/dist/chunks/studio-sas7mt3k.js.map +10 -0
  108. package/dist/chunks/studio-t5wqwzdh.js +74 -0
  109. package/dist/chunks/studio-t5wqwzdh.js.map +10 -0
  110. package/dist/chunks/{studio-9qpspwfn.js → studio-temv5bw4.js} +5 -5
  111. package/dist/chunks/{studio-9qpspwfn.js.map → studio-temv5bw4.js.map} +1 -1
  112. package/dist/chunks/{studio-qkvt37c0.js → studio-tr20m8g8.js} +669 -18
  113. package/dist/chunks/studio-tr20m8g8.js.map +9 -0
  114. package/dist/chunks/{studio-ygzav7z5.js → studio-v96qfnww.js} +5514 -4291
  115. package/dist/chunks/studio-v96qfnww.js.map +54 -0
  116. package/dist/chunks/studio-vcetc91k.js +659 -0
  117. package/dist/chunks/studio-vcetc91k.js.map +10 -0
  118. package/dist/chunks/{studio-n9zmpxjg.js → studio-vmymjefp.js} +2972 -4937
  119. package/dist/chunks/studio-vmymjefp.js.map +98 -0
  120. package/dist/chunks/{studio-bghqfmea.js → studio-wwseqyw0.js} +2 -2
  121. package/dist/chunks/studio-x9hmy5kr.js +390 -0
  122. package/dist/chunks/studio-x9hmy5kr.js.map +10 -0
  123. package/dist/chunks/studio-xa0ce0n7.js +335 -0
  124. package/dist/chunks/studio-xa0ce0n7.js.map +10 -0
  125. package/dist/chunks/studio-xm3dbxvn.js +378 -0
  126. package/dist/chunks/studio-xm3dbxvn.js.map +19 -0
  127. package/dist/chunks/{studio-nqw433kv.js → studio-xmvbhg31.js} +2 -2
  128. package/dist/chunks/studio-zv37yrfa.js +1054 -0
  129. package/dist/chunks/studio-zv37yrfa.js.map +13 -0
  130. package/dist/chunks/{ws-client-q7hkz3j9.js → ws-client-654ts66j.js} +6 -4
  131. package/dist/chunks/ws-client-654ts66j.js.map +11 -0
  132. package/dist/iframe-entry.js +668 -230
  133. package/dist/studio.js +23711 -35185
  134. package/index.html +35 -4685
  135. package/package.json +17 -15
  136. package/src/about/about-modal.ts +42 -11
  137. package/src/browse/library-commands.ts +240 -0
  138. package/src/browse/library-layouts.ts +369 -0
  139. package/src/browse/library-model.ts +396 -0
  140. package/src/browse/library-pane.ts +1049 -0
  141. package/src/browse/library-preview.ts +252 -0
  142. package/src/browse/library-source.ts +150 -0
  143. package/src/canvas/canvas-helpers.ts +33 -9
  144. package/src/canvas/canvas-live-render.ts +45 -29
  145. package/src/canvas/canvas-patcher.ts +151 -31
  146. package/src/canvas/canvas-perf.ts +46 -7
  147. package/src/canvas/canvas-render.ts +1092 -220
  148. package/src/canvas/canvas-surface.ts +240 -0
  149. package/src/canvas/canvas-utils.ts +1166 -124
  150. package/src/canvas/iframe-drop.ts +2 -1
  151. package/src/canvas/iframe-entry.ts +241 -4
  152. package/src/canvas/iframe-host.ts +1226 -143
  153. package/src/canvas/iframe-inline-edit.ts +31 -0
  154. package/src/canvas/iframe-interaction.ts +76 -16
  155. package/src/canvas/iframe-keys.ts +107 -45
  156. package/src/canvas/iframe-overlay.ts +38 -1
  157. package/src/canvas/iframe-protocol.ts +137 -2
  158. package/src/canvas/iframe-render.ts +70 -2
  159. package/src/canvas/iframe-slash.ts +6 -0
  160. package/src/canvas/path-mapping.ts +56 -6
  161. package/src/canvas/surface-registry.ts +292 -0
  162. package/src/collab/collab-commands.ts +244 -0
  163. package/src/collab/collab-session.ts +198 -32
  164. package/src/collab/collab-state.ts +28 -2
  165. package/src/collab/presence-chips.ts +100 -9
  166. package/src/commands/active-registry.ts +42 -0
  167. package/src/commands/app-commands.ts +176 -0
  168. package/src/commands/budget.ts +158 -0
  169. package/src/commands/command-args.ts +253 -0
  170. package/src/commands/context.ts +387 -0
  171. package/src/commands/defaults.ts +580 -0
  172. package/src/commands/keymap.ts +571 -0
  173. package/src/commands/levels.ts +345 -0
  174. package/src/commands/live-context.ts +193 -0
  175. package/src/commands/reference.ts +227 -0
  176. package/src/commands/registry.ts +293 -0
  177. package/src/component-props.ts +3 -2
  178. package/src/content/draft-state.ts +106 -0
  179. package/src/content/entry-commands.ts +282 -0
  180. package/src/content/entry-editor.ts +327 -0
  181. package/src/content/entry-fields.ts +116 -0
  182. package/src/content/entry-model.ts +175 -0
  183. package/src/editor/canvas-context-menu.ts +17 -11
  184. package/src/editor/canvas-slash-bridge.ts +11 -4
  185. package/src/editor/context-menu.ts +804 -204
  186. package/src/editor/convert-to-component.ts +31 -10
  187. package/src/editor/convert-to-repeater.ts +3 -2
  188. package/src/editor/inline-edit-apply.ts +5 -5
  189. package/src/editor/inline-edit.ts +86 -50
  190. package/src/editor/insert-zone-action.ts +1 -1
  191. package/src/editor/shortcuts.ts +1043 -329
  192. package/src/editor/slash-menu.ts +1 -0
  193. package/src/files/elements.ts +166 -0
  194. package/src/files/file-ops.ts +178 -31
  195. package/src/files/files.ts +898 -268
  196. package/src/files/fs-events.ts +21 -0
  197. package/src/files/media-meta.ts +203 -0
  198. package/src/files/media-paths.ts +141 -0
  199. package/src/files/media-upload.ts +7 -3
  200. package/src/files/media-usage.ts +189 -0
  201. package/src/github/github-auth.ts +235 -33
  202. package/src/github/github-publish.ts +80 -21
  203. package/src/grid/grid-controller.ts +152 -12
  204. package/src/grid/grid-layout.ts +225 -20
  205. package/src/grid/grid-open.ts +120 -0
  206. package/src/grid/grid-panel.ts +554 -39
  207. package/src/grid/grid-source.ts +27 -1
  208. package/src/grid/redirects-grid.ts +599 -0
  209. package/src/grid/redirects.ts +398 -0
  210. package/src/grid/sources/content-source.ts +108 -2
  211. package/src/i18n/i18n-commands.ts +322 -0
  212. package/src/new-project/add-repo-modal.ts +8 -10
  213. package/src/new-project/import-tab.ts +34 -9
  214. package/src/new-project/location-fields.ts +9 -1
  215. package/src/new-project/new-project-modal.ts +270 -262
  216. package/src/packages/jxsuite-update.ts +97 -48
  217. package/src/packages/pull-package-sync.ts +18 -9
  218. package/src/page-params.ts +2 -1
  219. package/src/panels/activity-bar.ts +152 -91
  220. package/src/panels/activity-panel.ts +481 -0
  221. package/src/panels/ai-chat/chat-markdown.ts +8 -3
  222. package/src/panels/ai-chat/chat-view.ts +245 -18
  223. package/src/panels/ai-chat/composer.ts +31 -5
  224. package/src/panels/ai-chat/sessions-view.ts +17 -10
  225. package/src/panels/ai-panel.ts +279 -120
  226. package/src/panels/block-action-bar.ts +1115 -224
  227. package/src/panels/bottom-dock.ts +337 -0
  228. package/src/panels/canvas-dnd-bridge.ts +37 -8
  229. package/src/panels/chat-panel.ts +29 -12
  230. package/src/panels/data-explorer.ts +254 -112
  231. package/src/panels/data-grid.ts +10 -4
  232. package/src/panels/dnd.ts +28 -51
  233. package/src/panels/editors.ts +434 -107
  234. package/src/panels/elements-panel.ts +66 -2
  235. package/src/panels/empty-state.ts +112 -0
  236. package/src/panels/events-panel.ts +596 -82
  237. package/src/panels/formula-workspace.ts +408 -218
  238. package/src/panels/frontmatter-fields.ts +51 -10
  239. package/src/panels/frontmatter-panel.ts +357 -79
  240. package/src/panels/git-panel.ts +375 -164
  241. package/src/panels/head-panel.ts +791 -85
  242. package/src/panels/i18n-panel.ts +592 -0
  243. package/src/panels/imports-panel.ts +95 -85
  244. package/src/panels/jump-bar.ts +584 -0
  245. package/src/panels/layers-panel.ts +1106 -328
  246. package/src/panels/left-panel.ts +109 -204
  247. package/src/panels/navigator-panels.ts +131 -0
  248. package/src/panels/overlays.ts +7 -2
  249. package/src/panels/pane-context.ts +1477 -0
  250. package/src/panels/pane-grid.ts +406 -0
  251. package/src/panels/panel-registry.ts +340 -0
  252. package/src/panels/panel-scheduler.ts +75 -0
  253. package/src/panels/problems-panel.ts +234 -0
  254. package/src/panels/properties-panel.ts +946 -1139
  255. package/src/panels/provenance.ts +258 -0
  256. package/src/panels/quick-search.ts +791 -122
  257. package/src/panels/right-panel.ts +228 -102
  258. package/src/panels/seo-modal.ts +395 -0
  259. package/src/panels/settings-pane.ts +203 -0
  260. package/src/panels/signals-panel.ts +354 -137
  261. package/src/panels/statement-editor.ts +41 -25
  262. package/src/panels/statusbar.ts +342 -106
  263. package/src/panels/style-panel.ts +974 -463
  264. package/src/panels/style-utils.ts +3 -3
  265. package/src/panels/stylebook-doc.ts +4 -2
  266. package/src/panels/stylebook-layers-panel.ts +3 -2
  267. package/src/panels/stylebook-panel.ts +51 -26
  268. package/src/panels/tab-strip.ts +1058 -78
  269. package/src/panels/target-line.ts +274 -0
  270. package/src/panels/toolbar.ts +631 -484
  271. package/src/panels/welcome-screen.ts +301 -198
  272. package/src/platform-errors.ts +26 -3
  273. package/src/platform.ts +96 -2
  274. package/src/platforms/cloud.ts +71 -8
  275. package/src/platforms/devserver.ts +92 -29
  276. package/src/publish/deploy-checklist.ts +383 -0
  277. package/src/publish/pages-service.ts +10 -1
  278. package/src/publish/publish-commands.ts +218 -0
  279. package/src/publish/publish-panel.ts +110 -16
  280. package/src/recent-projects.ts +3 -2
  281. package/src/services/a11y-report.ts +505 -0
  282. package/src/services/ai-models.ts +75 -2
  283. package/src/services/ai-project-tools.ts +29 -10
  284. package/src/services/ai-system-prompt.ts +53 -14
  285. package/src/services/ai-tools.ts +39 -3
  286. package/src/services/ai-writes.ts +154 -0
  287. package/src/services/announce.ts +97 -0
  288. package/src/services/automation.ts +424 -175
  289. package/src/services/cem-export.ts +9 -4
  290. package/src/services/clock.ts +61 -0
  291. package/src/services/document-assistant.ts +36 -8
  292. package/src/services/idle.ts +179 -0
  293. package/src/services/import-client.ts +26 -0
  294. package/src/services/monaco-buffer.ts +627 -0
  295. package/src/services/monaco-lazy.ts +36 -0
  296. package/src/services/notify.ts +271 -0
  297. package/src/services/profile.ts +155 -0
  298. package/src/services/references.ts +0 -0
  299. package/src/services/token-lint.ts +3 -2
  300. package/src/services/tool-executor.ts +53 -7
  301. package/src/services/trusted-types.ts +123 -0
  302. package/src/settings/contexts-section.ts +427 -0
  303. package/src/settings/contributed-section.ts +149 -11
  304. package/src/settings/css-vars-editor.ts +306 -349
  305. package/src/settings/defs-editor.ts +93 -34
  306. package/src/settings/dependencies-editor.ts +7 -7
  307. package/src/settings/extension-sections.ts +37 -5
  308. package/src/settings/general-settings.ts +204 -121
  309. package/src/settings/locales-section.ts +347 -0
  310. package/src/settings/preferences-accounts.ts +140 -0
  311. package/src/settings/preferences-dialog.ts +620 -0
  312. package/src/settings/preferences-keymap.ts +270 -0
  313. package/src/settings/project-sections.ts +260 -0
  314. package/src/settings/section-registry.ts +169 -0
  315. package/src/settings/settings-document.ts +385 -0
  316. package/src/shell.ts +1549 -0
  317. package/src/site-context.ts +45 -20
  318. package/src/state.ts +14 -275
  319. package/src/store.ts +88 -43
  320. package/src/studio.ts +790 -346
  321. package/src/style/live-preview.ts +36 -0
  322. package/src/style/project-styles.ts +349 -0
  323. package/src/style/token-ref.ts +123 -0
  324. package/src/tabs/patch-ops.ts +16 -4
  325. package/src/tabs/project-config.ts +416 -0
  326. package/src/tabs/selection.ts +323 -0
  327. package/src/tabs/tab.ts +182 -47
  328. package/src/tabs/transact.ts +209 -28
  329. package/src/types.ts +68 -13
  330. package/src/ui/ai-credentials-form.ts +39 -35
  331. package/src/ui/ai-managed-connect.ts +113 -0
  332. package/src/ui/dynamic-slot.ts +224 -81
  333. package/src/ui/expression-editor.ts +71 -63
  334. package/src/ui/field-input.ts +4 -6
  335. package/src/ui/field-row.ts +215 -38
  336. package/src/ui/form-controls.ts +194 -7
  337. package/src/ui/layers.ts +492 -69
  338. package/src/ui/media-picker.ts +115 -25
  339. package/src/ui/panel-resize.ts +109 -91
  340. package/src/ui/progress-modal.ts +131 -50
  341. package/src/ui/regions.ts +462 -0
  342. package/src/ui/schema-form.ts +229 -45
  343. package/src/ui/spectrum.ts +24 -8
  344. package/src/ui/timing.ts +49 -0
  345. package/src/ui/value-selector.ts +20 -0
  346. package/src/ui/value-source.ts +348 -0
  347. package/src/ui/virtual-window.ts +400 -0
  348. package/src/utils/edit-display.ts +3 -2
  349. package/src/utils/inherited-style.ts +67 -37
  350. package/src/view.ts +64 -78
  351. package/src/workspace/pane-derive.ts +1258 -0
  352. package/src/workspace/session.ts +317 -0
  353. package/src/workspace/workspace.ts +1345 -23
  354. package/styles/canvas.css +653 -0
  355. package/styles/forced-colors.css +106 -0
  356. package/styles/inspector.css +1454 -0
  357. package/styles/overlays.css +2704 -0
  358. package/styles/panels.css +1701 -0
  359. package/styles/shell.css +1423 -0
  360. package/styles/tokens.css +151 -0
  361. package/dist/chunks/Overlay.dev-cszx7yn5.js +0 -22
  362. package/dist/chunks/extension-sections-qct0gt8f.js +0 -531
  363. package/dist/chunks/extension-sections-qct0gt8f.js.map +0 -12
  364. package/dist/chunks/files-02zn5y24.js +0 -50
  365. package/dist/chunks/files-02zn5y24.js.map +0 -9
  366. package/dist/chunks/git-panel-mbb0y0hz.js +0 -28
  367. package/dist/chunks/git-panel-mbb0y0hz.js.map +0 -9
  368. package/dist/chunks/layers-panel-9qekmqk1.js +0 -26
  369. package/dist/chunks/layers-panel-9qekmqk1.js.map +0 -9
  370. package/dist/chunks/settings-modal-gj0hrah4.js +0 -29
  371. package/dist/chunks/settings-modal-gj0hrah4.js.map +0 -9
  372. package/dist/chunks/sp-overlay.dev-earn5as8.js +0 -17
  373. package/dist/chunks/sp-overlay.dev-earn5as8.js.map +0 -9
  374. package/dist/chunks/sp-popover.dev-frxtfejn.js +0 -8
  375. package/dist/chunks/sp-popover.dev-frxtfejn.js.map +0 -9
  376. package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js +0 -14
  377. package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js.map +0 -9
  378. package/dist/chunks/sp-tooltip.dev-a9fywesm.js +0 -21
  379. package/dist/chunks/sp-tooltip.dev-a9fywesm.js.map +0 -10
  380. package/dist/chunks/studio-4k0m4fmp.js.map +0 -13
  381. package/dist/chunks/studio-568nx4t5.js +0 -469
  382. package/dist/chunks/studio-568nx4t5.js.map +0 -14
  383. package/dist/chunks/studio-9smfzqhc.js +0 -19
  384. package/dist/chunks/studio-9smfzqhc.js.map +0 -10
  385. package/dist/chunks/studio-asvf0j9e.js +0 -429
  386. package/dist/chunks/studio-asvf0j9e.js.map +0 -13
  387. package/dist/chunks/studio-d77qm3pk.js +0 -3427
  388. package/dist/chunks/studio-d77qm3pk.js.map +0 -26
  389. package/dist/chunks/studio-j6gqyjf4.js +0 -1854
  390. package/dist/chunks/studio-j6gqyjf4.js.map +0 -18
  391. package/dist/chunks/studio-n9zmpxjg.js.map +0 -115
  392. package/dist/chunks/studio-qkvt37c0.js.map +0 -9
  393. package/dist/chunks/studio-rq0vxb19.js +0 -3744
  394. package/dist/chunks/studio-rq0vxb19.js.map +0 -22
  395. package/dist/chunks/studio-wd6ewdvd.js +0 -853
  396. package/dist/chunks/studio-wd6ewdvd.js.map +0 -12
  397. package/dist/chunks/studio-xq0t7n5t.js +0 -140
  398. package/dist/chunks/studio-xq0t7n5t.js.map +0 -10
  399. package/dist/chunks/studio-xze4zrs1.js.map +0 -10
  400. package/dist/chunks/studio-ygzav7z5.js.map +0 -46
  401. package/dist/chunks/studio-zmy7241e.js +0 -399
  402. package/dist/chunks/studio-zmy7241e.js.map +0 -12
  403. package/dist/chunks/ws-client-q7hkz3j9.js.map +0 -11
  404. package/src/browse/browse-modal.ts +0 -69
  405. package/src/browse/browse.ts +0 -904
  406. package/src/canvas/canvas-diff.ts +0 -216
  407. package/src/canvas/nested-site-style.ts +0 -58
  408. package/src/new-project/design-fields.ts +0 -264
  409. package/src/new-project/templates.ts +0 -61
  410. package/src/panels/tab-bar.ts +0 -548
  411. package/src/settings/settings-modal.ts +0 -203
  412. /package/dist/chunks/{adapter-z8fkmbmv.js.map → adapter-qfnesn5v.js.map} +0 -0
  413. /package/dist/chunks/{cf-settings-mmyv436d.js.map → cf-settings-73sh5z4p.js.map} +0 -0
  414. /package/dist/chunks/{format-host-2c188n41.js.map → format-host-mkwsmt8d.js.map} +0 -0
  415. /package/dist/chunks/{jx-validate-qx8degj7.js.map → jx-validate-v6qgknrs.js.map} +0 -0
  416. /package/dist/chunks/{studio-w7c6kvk7.js.map → studio-a7pzveq1.js.map} +0 -0
  417. /package/dist/chunks/{studio-hhj92gcr.js.map → studio-s519zc99.js.map} +0 -0
  418. /package/dist/chunks/{studio-bghqfmea.js.map → studio-wwseqyw0.js.map} +0 -0
  419. /package/dist/chunks/{studio-nqw433kv.js.map → studio-xmvbhg31.js.map} +0 -0
@@ -1,17 +1,140 @@
1
1
  /// <reference lib="dom" />
2
2
  /**
3
- * GitHub OAuth Device Flow authentication for Jx Studio.
3
+ * GitHub sign-in for Jx Studio: the desktop's loopback redirect, and the browser's device flow.
4
4
  *
5
- * Uses the Device Flow so the user authenticates in their browser without needing a server-side
6
- * redirect endpoint.
5
+ * **Which flow runs depends on what the build has, not on preference.** A desktop launcher exposes
6
+ * `githubAuth` on `globalThis.__jxPlatform`, backed by an RFC 8252 loopback redirect with PKCE —
7
+ * the user signs in on GitHub's own page in their own browser, the authorization code comes back to
8
+ * a loopback server, and the token is stored in the app's config folder at `0600`. A page in a
9
+ * browser has no loopback server to redirect to, so it keeps the Device Flow below.
10
+ *
11
+ * The Device Flow needs no server-side redirect endpoint, which is exactly why it was chosen here
12
+ * and exactly why it is the wrong tool for a desktop app: RFC 8628 designed it for devices that
13
+ * cannot show a browser or take typed input, and it costs the user a code copied between windows.
14
+ *
15
+ * **This flow fails, and until now it failed silently.** `https://github.com/login/device/code`
16
+ * sends no `Access-Control-Allow-Origin`, so a browser cannot call it: in Studio-in-a-browser the
17
+ * very first request rejects with a bare `TypeError`. That rejection used to become a thrown
18
+ * `Error` out of {@link authenticateGithub}, into `void createGithubRepository(…)` in
19
+ * `panels/git-panel.ts`, and from there into an unhandled promise rejection — the user clicked
20
+ * "Create GitHub repository" and the app did nothing at all, forever, with no message anywhere.
21
+ *
22
+ * Three failures now reach a surface, each as the kind of record §16 says it is:
23
+ *
24
+ * - **Unreachable** (CORS, offline, DNS) → a **Problem**, because it must be fixed and the fix is not
25
+ * in this dialog, carrying `git.signInToGithub` as its Retry;
26
+ * - **Refused by GitHub** (an HTTP error, `access_denied`, `expired_token`) → a **toast**, because
27
+ * the state is now correct and there is nothing to fix — the user declined, or waited too long;
28
+ * - **A poll that keeps failing** → a Problem after {@link MAX_POLL_FAILURES} consecutive rejections,
29
+ * rather than the previous empty catch that re-armed the timer forever. A dialog that says
30
+ * "Waiting for authorization…" against a network that will never answer is the exact dishonesty
31
+ * the feedback system exists to end.
32
+ *
33
+ * **What it cannot tell you.** A cross-origin block and an unplugged cable are the same `TypeError`
34
+ * here — the browser withholds the reason on purpose — so the detail names both rather than
35
+ * guessing between them.
36
+ *
37
+ * The token is returned to callers and never rendered. In a browser it is stored in `localStorage`;
38
+ * on the desktop it is in the launcher's `0600` credential store and this module holds it only in
39
+ * memory for the session. `settings/preferences-accounts.ts` lists it as _stored or not_ and is the
40
+ * only place it can be revoked (`studio.md` §15 rule 1).
7
41
  */
8
42
 
9
43
  import { html } from "lit-html";
44
+ import { errorMessage } from "@jxsuite/schema/parse";
45
+ import { notify } from "../services/notify";
10
46
  import { showDialog } from "../ui/layers";
11
47
 
12
48
  const CLIENT_ID = "Ov23liYVlMFpgjOEPXJH";
13
49
  const STORAGE_KEY = "jx_github_token";
14
50
 
51
+ /**
52
+ * The desktop launcher's RFC 8252 sign-in, when this build is running inside one.
53
+ *
54
+ * Launcher-only, like `updater` and `windowControls`, and reached the same way — a loopback
55
+ * redirect needs a loopback server, which a page in a browser does not have.
56
+ */
57
+ interface NativeGithubAuth {
58
+ signIn: (force?: boolean) => Promise<{ token: string }>;
59
+ signOut: () => Promise<{ ok: boolean }>;
60
+ status: () => Promise<{ stored: boolean }>;
61
+ }
62
+
63
+ function nativeAuth(): NativeGithubAuth | null {
64
+ return (
65
+ (globalThis as unknown as { __jxPlatform?: { githubAuth?: NativeGithubAuth } }).__jxPlatform
66
+ ?.githubAuth ?? null
67
+ );
68
+ }
69
+
70
+ /**
71
+ * The token the desktop store handed us this session.
72
+ *
73
+ * On the desktop the token at rest is a `0600` file in the user's config directory, **not**
74
+ * `localStorage` — so it is not readable by script in the webview between sessions, and it does not
75
+ * survive in a place a stray extension or a copied profile can reach. Holding it in a module
76
+ * variable is what keeps {@link getGithubToken} synchronous for its callers.
77
+ */
78
+ let nativeToken: string | null = null;
79
+
80
+ /** Whether the desktop store holds a token, as of the last time it was asked. */
81
+ let nativeStored = false;
82
+
83
+ /**
84
+ * Record that the desktop's credential store does (or does not) hold a token.
85
+ *
86
+ * The launcher calls this once at startup. It carries a **boolean, not the token**: the accounts
87
+ * pane only needs to know whether one exists, and handing the webview a credential it has not been
88
+ * asked to use is the exposure the 0600 store exists to remove. When a sign-in does happen the
89
+ * token arrives through {@link authenticateGithub} and lives in memory for that session.
90
+ *
91
+ * @param {boolean} stored
92
+ */
93
+ export function hydrateGithubToken(stored: boolean): void {
94
+ nativeStored = stored;
95
+ }
96
+
97
+ /**
98
+ * Whether a GitHub credential exists, wherever it lives.
99
+ *
100
+ * Separate from {@link getGithubToken} because the two questions genuinely differ on the desktop: a
101
+ * token can be stored on disk and not yet in this session's memory, and the accounts pane asks
102
+ * "signed in?" while rendering — synchronously — where an API caller asks for the credential itself
103
+ * and can await it.
104
+ *
105
+ * @returns {boolean}
106
+ */
107
+ export function githubTokenStored(): boolean {
108
+ return nativeToken !== null || nativeStored || localStorage.getItem(STORAGE_KEY) !== null;
109
+ }
110
+
111
+ /** Where the credential this build would use actually lives, for text that says so. */
112
+ export function githubTokenLocation(): "desktop" | "browser" {
113
+ return nativeAuth() ? "desktop" : "browser";
114
+ }
115
+
116
+ /** One key for the whole sign-in, so a second attempt REPLACES the first report. */
117
+ const NOTIFY_KEY = "github.auth";
118
+
119
+ const SOURCE = "Source Control";
120
+
121
+ /** The Retry every report carries — one command, so the button's label comes off the record. */
122
+ const RETRY = "git.signInToGithub";
123
+
124
+ /**
125
+ * How many consecutive poll rejections end the wait.
126
+ *
127
+ * Three, not one: the device flow legitimately polls across a laptop's sleep and a Wi-Fi hop, and
128
+ * failing on the first blip would abandon a sign-in the user is in the middle of completing.
129
+ */
130
+ export const MAX_POLL_FAILURES = 3;
131
+
132
+ /** Both halves of what a browser will not tell us, said once. */
133
+ const UNREACHABLE_DETAIL =
134
+ "The request never reached GitHub. GitHub's device-flow endpoints send no CORS headers, so a " +
135
+ "browser cannot call them directly — the desktop app can. A machine that is offline fails " +
136
+ "identically, and the browser does not say which happened.";
137
+
15
138
  interface DeviceCodeResponse {
16
139
  device_code: string;
17
140
  user_code: string;
@@ -25,18 +148,73 @@ interface TokenResponse {
25
148
  }
26
149
 
27
150
  export function getGithubToken() {
28
- return localStorage.getItem(STORAGE_KEY);
151
+ return nativeToken ?? localStorage.getItem(STORAGE_KEY);
29
152
  }
30
153
 
31
154
  export function clearGithubToken() {
155
+ nativeToken = null;
156
+ nativeStored = false;
32
157
  localStorage.removeItem(STORAGE_KEY);
158
+ // Fire-and-forget: the accounts pane's revoke is synchronous, and a store that failed to forget
159
+ // The token is not something the user can act on from there.
160
+ void nativeAuth()
161
+ ?.signOut()
162
+ .catch(() => {});
163
+ }
164
+
165
+ /** The request never completed — a Problem, with the one sentence that covers both causes. */
166
+ function reportUnreachable(error: unknown): void {
167
+ notify.error("Could not reach GitHub to sign in.", {
168
+ action: RETRY,
169
+ detail: `${UNREACHABLE_DETAIL}\n\n${errorMessage(error)}`,
170
+ key: NOTIFY_KEY,
171
+ source: SOURCE,
172
+ });
173
+ }
174
+
175
+ /** GitHub answered, and said no. Nothing is broken, so this rests rather than persists. */
176
+ function reportRefused(message: string, detail: string): void {
177
+ notify.warn(message, { action: RETRY, detail, key: NOTIFY_KEY, source: SOURCE });
178
+ }
179
+
180
+ /**
181
+ * Start the device flow.
182
+ *
183
+ * @returns The device code payload, or null when the request failed — reported, never thrown, so a
184
+ * caller that forgot to catch cannot turn a network error back into silence.
185
+ */
186
+ async function requestDeviceCode(): Promise<DeviceCodeResponse | null> {
187
+ let codeRes: Response;
188
+ try {
189
+ codeRes = await fetch("https://github.com/login/device/code", {
190
+ body: JSON.stringify({ client_id: CLIENT_ID, scope: "repo" }),
191
+ headers: {
192
+ Accept: "application/json",
193
+ "Content-Type": "application/json",
194
+ },
195
+ method: "POST",
196
+ });
197
+ } catch (error) {
198
+ reportUnreachable(error);
199
+ return null;
200
+ }
201
+
202
+ if (!codeRes.ok) {
203
+ reportRefused(
204
+ "GitHub refused to start the sign-in.",
205
+ `GitHub answered ${codeRes.status}${codeRes.statusText ? ` ${codeRes.statusText}` : ""}.`,
206
+ );
207
+ return null;
208
+ }
209
+ return (await codeRes.json()) as DeviceCodeResponse;
33
210
  }
34
211
 
35
212
  /**
36
213
  * Authenticate with GitHub via the Device Flow. Shows a dialog with the user code and polls until
37
214
  * the user completes authorization or cancels.
38
215
  *
39
- * @returns {Promise<string | null>} The access token, or null if cancelled.
216
+ * @returns {Promise<string | null>} The access token, or null if it failed or was cancelled. Every
217
+ * `null` that is not a cancellation has already been reported.
40
218
  */
41
219
  export async function authenticateGithub() {
42
220
  const existing = getGithubToken();
@@ -44,25 +222,43 @@ export async function authenticateGithub() {
44
222
  return existing;
45
223
  }
46
224
 
47
- const codeRes = await fetch("https://github.com/login/device/code", {
48
- body: JSON.stringify({ client_id: CLIENT_ID, scope: "repo" }),
49
- headers: {
50
- Accept: "application/json",
51
- "Content-Type": "application/json",
52
- },
53
- method: "POST",
54
- });
225
+ /*
226
+ * The desktop takes the loopback redirect (RFC 8252): its browser opens the provider's own page,
227
+ * the code comes back to a loopback server, and PKCE binds the exchange. The device flow below is
228
+ * for the browser Studio, which has no loopback server to redirect to — and whose first request
229
+ * to GitHub's device endpoint is refused by CORS anyway.
230
+ */
231
+ const native = nativeAuth();
232
+ if (native) {
233
+ try {
234
+ const { token } = await native.signIn();
235
+ nativeToken = token;
236
+ return token;
237
+ } catch (error) {
238
+ reportRefused("GitHub sign-in was not completed.", errorMessage(error));
239
+ return null;
240
+ }
241
+ }
55
242
 
56
- if (!codeRes.ok) {
57
- throw new Error("Failed to initiate GitHub device flow");
243
+ const codeData = await requestDeviceCode();
244
+ if (!codeData) {
245
+ return null;
58
246
  }
59
- const codeData = (await codeRes.json()) as DeviceCodeResponse;
60
247
 
61
248
  const { device_code, user_code, verification_uri, interval = 5 } = codeData;
62
249
 
63
- return showDialog((done) => {
250
+ return showDialog<string | null>((done) => {
64
251
  let cancelled = false;
65
252
  let pollTimer: ReturnType<typeof setTimeout> | null = null;
253
+ let failures = 0;
254
+
255
+ const stop = () => {
256
+ cancelled = true;
257
+ if (pollTimer) {
258
+ clearTimeout(pollTimer);
259
+ }
260
+ done(null);
261
+ };
66
262
 
67
263
  const poll = async () => {
68
264
  if (cancelled) {
@@ -82,6 +278,7 @@ export async function authenticateGithub() {
82
278
  method: "POST",
83
279
  });
84
280
  const tokenData = (await tokenRes.json()) as TokenResponse;
281
+ failures = 0;
85
282
 
86
283
  if (tokenData.access_token) {
87
284
  localStorage.setItem(STORAGE_KEY, tokenData.access_token);
@@ -99,9 +296,26 @@ export async function authenticateGithub() {
99
296
  return;
100
297
  }
101
298
 
102
- // Expired_token or access_denied
299
+ // Expired_token, access_denied, or anything else GitHub decides to answer. The state is
300
+ // Correct — there is no token because the user did not grant one — so this rests.
301
+ reportRefused(
302
+ "GitHub sign-in was not completed.",
303
+ tokenData.error === "access_denied"
304
+ ? "The authorization was declined on GitHub."
305
+ : tokenData.error === "expired_token"
306
+ ? "The device code expired before it was entered."
307
+ : `GitHub answered "${tokenData.error ?? "an unrecognised response"}".`,
308
+ );
309
+ cancelled = true;
103
310
  done(null);
104
- } catch {
311
+ } catch (error) {
312
+ failures += 1;
313
+ if (failures >= MAX_POLL_FAILURES) {
314
+ reportUnreachable(error);
315
+ cancelled = true;
316
+ done(null);
317
+ return;
318
+ }
105
319
  pollTimer = setTimeout(poll, interval * 1000);
106
320
  }
107
321
  };
@@ -113,20 +327,8 @@ export async function authenticateGithub() {
113
327
  open
114
328
  headline="Sign in to GitHub"
115
329
  cancel-label="Cancel"
116
- @cancel=${() => {
117
- cancelled = true;
118
- if (pollTimer) {
119
- clearTimeout(pollTimer);
120
- }
121
- done(null);
122
- }}
123
- @close=${() => {
124
- cancelled = true;
125
- if (pollTimer) {
126
- clearTimeout(pollTimer);
127
- }
128
- done(null);
129
- }}
330
+ @cancel=${stop}
331
+ @close=${stop}
130
332
  >
131
333
  <div class="github-auth-dialog">
132
334
  <p>Enter this code on GitHub to authorize Jx Studio:</p>
@@ -1,13 +1,30 @@
1
1
  /// <reference lib="dom" />
2
- /** Publish a local project to GitHub — creates a new repo and pushes. */
2
+ /**
3
+ * Create a GitHub repository for a local project, add it as `origin`, and push.
4
+ *
5
+ * **This is not publishing, and it used to say it was.** Two unrelated operations shared the verb
6
+ * (plan §9.5): this one creates a git repository, and `publish/publish-panel.ts` connects a hosting
7
+ * provider that then builds the site. A user who wanted the second and found the first got a GitHub
8
+ * repository and no site, and a user who wanted the first read "Publish to GitHub" and reasonably
9
+ * expected a URL. The function, the dialog headline, the activity title and the notification source
10
+ * now all say _Create GitHub Repository_; `Publish:` belongs to `publish/publish-commands.ts`.
11
+ *
12
+ * **It is an Activity, not three toasts.** Three `notify.info` lines sharing one key replaced each
13
+ * other in a corner while a multi-second, three-request, partially-committing operation ran with no
14
+ * log and no cancel — and its middle step (`gitAddRemote`) had no error path at all, so a remote
15
+ * that already existed failed the push with a message about pushing. `beginActivity` gives it the
16
+ * ordered steps, the captured log, and `fail()`, which raises the Problem the failure needs and
17
+ * carries the log as its detail (§7.3). The caller therefore never also notifies.
18
+ */
3
19
 
4
20
  import { html } from "lit-html";
5
21
  import { errorMessage } from "@jxsuite/schema/parse";
6
22
  import { ref } from "lit-html/directives/ref.js";
7
23
  import { showDialog } from "../ui/layers";
8
24
  import { authenticateGithub } from "./github-auth";
25
+ import { beginActivity } from "../panels/activity-panel";
9
26
  import { getPlatform } from "../platform";
10
- import { statusMessage } from "../panels/statusbar";
27
+ import { notify } from "../services/notify";
11
28
 
12
29
  interface GithubErrorResponse {
13
30
  errors?: { message?: string }[];
@@ -19,24 +36,34 @@ interface GithubRepoResponse {
19
36
  html_url: string;
20
37
  }
21
38
 
39
+ /** What the dialog collects. */
40
+ export interface RepoOptions {
41
+ name: string;
42
+ description: string;
43
+ isPrivate: boolean;
44
+ }
45
+
46
+ /** The ordered steps, named once so the activity and its tests cannot disagree. */
47
+ export const REPO_STEPS = ["Create the repository", "Add the remote", "Push"] as const;
48
+
22
49
  /**
23
- * Full "Publish to GitHub" flow: 1. Authenticate (or reuse stored token) 2. Prompt for repo name /
24
- * visibility 3. Create the repo via GitHub API 4. Add remote + push
50
+ * Full "Create GitHub Repository" flow: 1. Authenticate (or reuse a stored token) 2. Prompt for
51
+ * repo name / visibility 3. Create the repo via the GitHub API 4. Add remote + push
52
+ *
53
+ * A failed sign-in returns `false` having already reported itself — `github-auth.ts` owns that
54
+ * message, because "GitHub is unreachable from a browser" is not a fact about creating a
55
+ * repository.
25
56
  *
26
57
  * @param {{ projectName: string }} opts
27
- * @returns {Promise<boolean>} True if published successfully
58
+ * @returns {Promise<boolean>} True if the repository was created and pushed.
28
59
  */
29
- export async function publishToGithub({ projectName }: { projectName: string }) {
60
+ export async function createGithubRepository({ projectName }: { projectName: string }) {
30
61
  const token = await authenticateGithub();
31
62
  if (!token) {
32
63
  return false;
33
64
  }
34
65
 
35
- const repoOpts = await showDialog<{
36
- name: string;
37
- description: string;
38
- isPrivate: boolean;
39
- } | null>((done) => {
66
+ const repoOpts = await showDialog<RepoOptions | null>((done) => {
40
67
  let _nameInput: HTMLInputElement | null = null;
41
68
  let _descInput: HTMLInputElement | null = null;
42
69
  let _privateToggle: HTMLInputElement | null = null;
@@ -44,7 +71,7 @@ export async function publishToGithub({ projectName }: { projectName: string })
44
71
  return html`
45
72
  <sp-dialog-wrapper
46
73
  open
47
- headline="Publish to GitHub"
74
+ headline="Create GitHub Repository"
48
75
  confirm-label="Create Repository"
49
76
  cancel-label="Cancel"
50
77
  @confirm=${() => {
@@ -97,8 +124,14 @@ export async function publishToGithub({ projectName }: { projectName: string })
97
124
  return false;
98
125
  }
99
126
 
100
- statusMessage("Creating GitHub repository…");
127
+ const activity = beginActivity({
128
+ source: "Source Control",
129
+ status: `Creating ${repoOpts.name}…`,
130
+ steps: [...REPO_STEPS],
131
+ title: "Create GitHub repository",
132
+ });
101
133
 
134
+ activity.step(REPO_STEPS[0]);
102
135
  const createRes = await fetch("https://api.github.com/user/repos", {
103
136
  body: JSON.stringify({
104
137
  auto_init: false,
@@ -112,33 +145,59 @@ export async function publishToGithub({ projectName }: { projectName: string })
112
145
  "Content-Type": "application/json",
113
146
  },
114
147
  method: "POST",
148
+ }).catch((error: unknown) => {
149
+ activity.log(errorMessage(error));
150
+ return null;
115
151
  });
116
152
 
153
+ if (!createRes) {
154
+ activity.fail("Could not reach GitHub to create the repository.", {
155
+ action: "git.createGithubRepository",
156
+ });
157
+ return false;
158
+ }
159
+
117
160
  if (!createRes.ok) {
118
161
  const err = (await createRes.json()) as GithubErrorResponse;
119
- const msg = err.errors?.[0]?.message || err.message || "Failed to create repository";
120
- statusMessage(`Error: ${msg}`);
162
+ activity.log(err.errors?.[0]?.message || err.message || `GitHub answered ${createRes.status}.`);
163
+ activity.fail("Could not create the GitHub repository.", {
164
+ action: "git.createGithubRepository",
165
+ });
121
166
  return false;
122
167
  }
123
168
 
124
169
  const repo = (await createRes.json()) as GithubRepoResponse;
170
+ activity.log(`Created ${repo.html_url}`);
125
171
  const platform = getPlatform();
126
172
 
127
- statusMessage("Setting remote and pushing…");
128
-
129
- await platform.gitAddRemote("origin", repo.clone_url);
173
+ activity.step(REPO_STEPS[1]);
174
+ try {
175
+ await platform.gitAddRemote("origin", repo.clone_url);
176
+ } catch (error) {
177
+ // The remote had no error path at all before this, so an `origin` that already existed
178
+ // Surfaced as a push failure describing the push.
179
+ activity.log(errorMessage(error));
180
+ activity.fail("The repository was created, but the remote could not be added.", {
181
+ action: "panel.focus.git",
182
+ });
183
+ return false;
184
+ }
130
185
 
131
- statusMessage("Pushing to GitHub…");
186
+ activity.step(REPO_STEPS[2]);
132
187
  try {
133
188
  await platform.gitPush({ setUpstream: true });
134
189
  } catch (error) {
135
- statusMessage(`Push failed: ${errorMessage(error)}`);
190
+ activity.log(errorMessage(error));
191
+ activity.fail("The repository was created, but the push failed.", {
192
+ action: "git.push",
193
+ });
136
194
  return false;
137
195
  }
138
196
 
139
197
  // Lazy import breaks the github-publish ↔ git-panel module cycle
140
198
  const { refreshGitStatus } = await import("../panels/git-panel");
141
199
  await refreshGitStatus();
142
- statusMessage(`Published to GitHub: ${repo.html_url}`);
200
+ activity.done(repo.html_url);
201
+ notify.success(`Repository created: ${repo.html_url}`, { key: "github.repo" });
143
202
  return true;
144
203
  }