@opengeni/react 3.3.2 → 3.4.1-canary.38960406141001

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 (855) hide show
  1. package/README.md +769 -22
  2. package/dist/accounts.js +2 -0
  3. package/dist/accounts.js.map +1 -1
  4. package/dist/approvals.d.ts +2 -1
  5. package/dist/artifacts-document.js +5 -3
  6. package/dist/artifacts-presentation.js +5 -3
  7. package/dist/artifacts-spreadsheet.d.ts +1 -1
  8. package/dist/artifacts-spreadsheet.js +5 -3
  9. package/dist/artifacts.d.ts +5 -1
  10. package/dist/artifacts.js +536 -42
  11. package/dist/artifacts.js.map +1 -1
  12. package/dist/browser-viewer-ZWR6MWJ7.js +19 -0
  13. package/dist/capability-catalog-row.d.ts +20 -0
  14. package/dist/capability-logo-fallback.d.ts +3 -0
  15. package/dist/chat-interactive-block-4EUKJXUO.js +14 -0
  16. package/dist/chunk-2DDJ6YH6.js +41 -0
  17. package/dist/chunk-2DDJ6YH6.js.map +1 -0
  18. package/dist/chunk-2HVLQ26H.js +183 -0
  19. package/dist/chunk-2HVLQ26H.js.map +1 -0
  20. package/dist/{chunk-XYRDDSXF.js → chunk-2I6R3GCZ.js} +4285 -3980
  21. package/dist/chunk-2I6R3GCZ.js.map +1 -0
  22. package/dist/{chunk-JAQ5K7W6.js → chunk-2SFFYIH3.js} +1178 -166
  23. package/dist/chunk-2SFFYIH3.js.map +1 -0
  24. package/dist/chunk-3PVDYTTB.js +24 -0
  25. package/dist/chunk-3PVDYTTB.js.map +1 -0
  26. package/dist/chunk-3RJKUVCA.js +14068 -0
  27. package/dist/chunk-3RJKUVCA.js.map +1 -0
  28. package/dist/chunk-3UZCWK46.js +298 -0
  29. package/dist/chunk-3UZCWK46.js.map +1 -0
  30. package/dist/chunk-47CKUXTW.js +293 -0
  31. package/dist/chunk-47CKUXTW.js.map +1 -0
  32. package/dist/chunk-4QYP6QUI.js +109 -0
  33. package/dist/chunk-4QYP6QUI.js.map +1 -0
  34. package/dist/chunk-5EY26VZ7.js +1053 -0
  35. package/dist/chunk-5EY26VZ7.js.map +1 -0
  36. package/dist/chunk-5I4VRWBB.js +56 -0
  37. package/dist/chunk-5I4VRWBB.js.map +1 -0
  38. package/dist/chunk-5WOR7UCL.js +191 -0
  39. package/dist/chunk-5WOR7UCL.js.map +1 -0
  40. package/dist/chunk-5YJLGOM5.js +51 -0
  41. package/dist/chunk-5YJLGOM5.js.map +1 -0
  42. package/dist/chunk-6JFN3OWG.js +386 -0
  43. package/dist/chunk-6JFN3OWG.js.map +1 -0
  44. package/dist/chunk-7QJT5O4S.js +35 -0
  45. package/dist/chunk-7QJT5O4S.js.map +1 -0
  46. package/dist/chunk-A55KV72M.js +402 -0
  47. package/dist/chunk-A55KV72M.js.map +1 -0
  48. package/dist/chunk-ADWCLI4G.js +2028 -0
  49. package/dist/chunk-ADWCLI4G.js.map +1 -0
  50. package/dist/chunk-B27E3V37.js +29 -0
  51. package/dist/chunk-B27E3V37.js.map +1 -0
  52. package/dist/chunk-B7TC2A33.js +83 -0
  53. package/dist/chunk-B7TC2A33.js.map +1 -0
  54. package/dist/chunk-BLL56F7R.js +385 -0
  55. package/dist/chunk-BLL56F7R.js.map +1 -0
  56. package/dist/chunk-BOFEQC6K.js +162 -0
  57. package/dist/chunk-BOFEQC6K.js.map +1 -0
  58. package/dist/chunk-CM7LVUKC.js +35 -0
  59. package/dist/chunk-CM7LVUKC.js.map +1 -0
  60. package/dist/chunk-CORUP6JB.js +122 -0
  61. package/dist/chunk-CORUP6JB.js.map +1 -0
  62. package/dist/chunk-CSX5FFKZ.js +35 -0
  63. package/dist/chunk-CSX5FFKZ.js.map +1 -0
  64. package/dist/chunk-EGVHJKGJ.js +3125 -0
  65. package/dist/chunk-EGVHJKGJ.js.map +1 -0
  66. package/dist/{chunk-NEXLLTP4.js → chunk-G76LSA76.js} +6 -5
  67. package/dist/chunk-G76LSA76.js.map +1 -0
  68. package/dist/{chunk-PEI6RANI.js → chunk-GQMRL52F.js} +311 -75
  69. package/dist/chunk-GQMRL52F.js.map +1 -0
  70. package/dist/{chunk-ELIYWBZR.js → chunk-GUUXOISA.js} +1113 -457
  71. package/dist/chunk-GUUXOISA.js.map +1 -0
  72. package/dist/{chunk-HUIKIDM5.js → chunk-I7X2P4FU.js} +225 -116
  73. package/dist/chunk-I7X2P4FU.js.map +1 -0
  74. package/dist/chunk-IGFZFLI2.js +1390 -0
  75. package/dist/chunk-IGFZFLI2.js.map +1 -0
  76. package/dist/{chunk-4MDLEHXL.js → chunk-IMSUVYQB.js} +26 -13
  77. package/dist/chunk-IMSUVYQB.js.map +1 -0
  78. package/dist/chunk-IOYHDEP3.js +38 -0
  79. package/dist/chunk-IOYHDEP3.js.map +1 -0
  80. package/dist/chunk-IZV5FTJC.js +55 -0
  81. package/dist/chunk-IZV5FTJC.js.map +1 -0
  82. package/dist/chunk-KF33GTWN.js +343 -0
  83. package/dist/chunk-KF33GTWN.js.map +1 -0
  84. package/dist/chunk-KSGQ5ODA.js +457 -0
  85. package/dist/chunk-KSGQ5ODA.js.map +1 -0
  86. package/dist/{chunk-ZPBTI3TE.js → chunk-KZC6QRNR.js} +1513 -697
  87. package/dist/chunk-KZC6QRNR.js.map +1 -0
  88. package/dist/chunk-LJUMYUBO.js +218 -0
  89. package/dist/chunk-LJUMYUBO.js.map +1 -0
  90. package/dist/chunk-LSW2OJVV.js +380 -0
  91. package/dist/chunk-LSW2OJVV.js.map +1 -0
  92. package/dist/chunk-M357MHH3.js +2 -0
  93. package/dist/chunk-M357MHH3.js.map +1 -0
  94. package/dist/chunk-MK2TQO4Y.js +24 -0
  95. package/dist/chunk-MK2TQO4Y.js.map +1 -0
  96. package/dist/chunk-N7S72EXK.js +25 -0
  97. package/dist/chunk-N7S72EXK.js.map +1 -0
  98. package/dist/{chunk-YVCHAQZY.js → chunk-NKMYZFHA.js} +616 -621
  99. package/dist/chunk-NKMYZFHA.js.map +1 -0
  100. package/dist/chunk-NX4ADH73.js +14 -0
  101. package/dist/chunk-NX4ADH73.js.map +1 -0
  102. package/dist/chunk-O7F6UJO4.js +71 -0
  103. package/dist/chunk-O7F6UJO4.js.map +1 -0
  104. package/dist/chunk-OYQQJL3J.js +16 -0
  105. package/dist/chunk-OYQQJL3J.js.map +1 -0
  106. package/dist/{chunk-H5YGYNXS.js → chunk-P4BNUO57.js} +60 -17
  107. package/dist/chunk-P4BNUO57.js.map +1 -0
  108. package/dist/{chunk-JVYQRRC4.js → chunk-PEHTX3V7.js} +21 -1
  109. package/dist/chunk-PEHTX3V7.js.map +1 -0
  110. package/dist/chunk-PMV53IMM.js +26 -0
  111. package/dist/chunk-PMV53IMM.js.map +1 -0
  112. package/dist/{chunk-KCGXPP5V.js → chunk-PYEOPA4M.js} +13 -7
  113. package/dist/chunk-PYEOPA4M.js.map +1 -0
  114. package/dist/{chunk-KZ73RL76.js → chunk-QHUE7E4N.js} +8 -3
  115. package/dist/chunk-QHUE7E4N.js.map +1 -0
  116. package/dist/chunk-QV3DJVRZ.js +11 -0
  117. package/dist/chunk-QV3DJVRZ.js.map +1 -0
  118. package/dist/chunk-R5SBNG7S.js +810 -0
  119. package/dist/chunk-R5SBNG7S.js.map +1 -0
  120. package/dist/chunk-RI42H5IU.js +326 -0
  121. package/dist/chunk-RI42H5IU.js.map +1 -0
  122. package/dist/chunk-S2QH6EZ5.js +211 -0
  123. package/dist/chunk-S2QH6EZ5.js.map +1 -0
  124. package/dist/chunk-SHLZMAJN.js +304 -0
  125. package/dist/chunk-SHLZMAJN.js.map +1 -0
  126. package/dist/chunk-TGXK4BAZ.js +293 -0
  127. package/dist/chunk-TGXK4BAZ.js.map +1 -0
  128. package/dist/{chunk-5YK2ZDIG.js → chunk-TNEZNMSN.js} +4 -10
  129. package/dist/chunk-TNEZNMSN.js.map +1 -0
  130. package/dist/{chunk-22KP6LR5.js → chunk-TXS65BB2.js} +3 -1
  131. package/dist/{chunk-22KP6LR5.js.map → chunk-TXS65BB2.js.map} +1 -1
  132. package/dist/chunk-UNJPZGNK.js +63 -0
  133. package/dist/chunk-UNJPZGNK.js.map +1 -0
  134. package/dist/{chunk-IOLVN74D.js → chunk-V5ZUJT2T.js} +175 -42
  135. package/dist/chunk-V5ZUJT2T.js.map +1 -0
  136. package/dist/chunk-WBJY57A3.js +402 -0
  137. package/dist/chunk-WBJY57A3.js.map +1 -0
  138. package/dist/chunk-WIUKB3LD.js +1911 -0
  139. package/dist/chunk-WIUKB3LD.js.map +1 -0
  140. package/dist/{chunk-ICA6R6TW.js → chunk-WNN7NO2N.js} +1451 -355
  141. package/dist/chunk-WNN7NO2N.js.map +1 -0
  142. package/dist/{chunk-3AGBGTRT.js → chunk-X5UVUIMF.js} +1712 -1174
  143. package/dist/chunk-X5UVUIMF.js.map +1 -0
  144. package/dist/chunk-XDA5QJE7.js +402 -0
  145. package/dist/chunk-XDA5QJE7.js.map +1 -0
  146. package/dist/{chunk-VZTQ73XT.js → chunk-XEA5BCMA.js} +3 -1
  147. package/dist/{chunk-VZTQ73XT.js.map → chunk-XEA5BCMA.js.map} +1 -1
  148. package/dist/chunk-XHF7OYAN.js +1150 -0
  149. package/dist/chunk-XHF7OYAN.js.map +1 -0
  150. package/dist/chunk-YSRBFJMQ.js +43 -0
  151. package/dist/chunk-YSRBFJMQ.js.map +1 -0
  152. package/dist/chunk-ZOZAPAUO.js +174 -0
  153. package/dist/chunk-ZOZAPAUO.js.map +1 -0
  154. package/dist/chunk-ZQV5W7YC.js +809 -0
  155. package/dist/chunk-ZQV5W7YC.js.map +1 -0
  156. package/dist/chunk-ZUWF4NF7.js +13 -0
  157. package/dist/chunk-ZUWF4NF7.js.map +1 -0
  158. package/dist/client.d.ts +16 -7
  159. package/dist/clipboard.js +3 -1
  160. package/dist/commands/types.d.ts +2 -0
  161. package/dist/components/anthropic-mark.d.ts +3 -0
  162. package/dist/components/approval-surface.d.ts +19 -6
  163. package/dist/components/artifacts/artifact-chrome.d.ts +120 -0
  164. package/dist/components/artifacts/artifact-sandbox.d.ts +30 -0
  165. package/dist/components/artifacts/artifact-surface.d.ts +4 -2
  166. package/dist/components/artifacts/chat-interactive-block.d.ts +29 -0
  167. package/dist/components/artifacts/deferred-chat-media.d.ts +15 -0
  168. package/dist/components/artifacts/document-editor.d.ts +4 -2
  169. package/dist/components/artifacts/editable-artifact-ui.d.ts +2 -1
  170. package/dist/components/artifacts/editable-artifact-view.d.ts +48 -0
  171. package/dist/components/artifacts/editable-document.d.ts +1 -1
  172. package/dist/components/artifacts/editable-presentation.d.ts +2 -2
  173. package/dist/components/artifacts/editable-spreadsheet.d.ts +8 -3
  174. package/dist/components/artifacts/index.d.ts +9 -2
  175. package/dist/components/artifacts/inline-html-document.d.ts +2 -0
  176. package/dist/components/artifacts/latest-task-runner.d.ts +15 -0
  177. package/dist/components/artifacts/presentation-editor.d.ts +6 -2
  178. package/dist/components/artifacts/published-html-artifact-frame.d.ts +23 -3
  179. package/dist/components/artifacts/session-artifact-viewer.d.ts +39 -0
  180. package/dist/components/artifacts/site-view.d.ts +26 -0
  181. package/dist/components/artifacts/spreadsheet-command-queue.d.ts +20 -0
  182. package/dist/components/artifacts/spreadsheet-download.d.ts +7 -0
  183. package/dist/components/artifacts/spreadsheet-general-display.d.ts +24 -0
  184. package/dist/components/artifacts/spreadsheet-grid.d.ts +10 -3
  185. package/dist/components/artifacts/spreadsheet-resize.d.ts +50 -0
  186. package/dist/components/artifacts/spreadsheet-submissions.d.ts +9 -0
  187. package/dist/components/artifacts/visualization-assets.gen.d.ts +2 -0
  188. package/dist/components/browser-select-control.d.ts +16 -0
  189. package/dist/components/browser-viewer.d.ts +11 -2
  190. package/dist/components/chat-composer.d.ts +21 -3
  191. package/dist/components/child-session-link.d.ts +9 -0
  192. package/dist/components/claude-mark.d.ts +3 -0
  193. package/dist/components/code-editor.d.ts +1 -4
  194. package/dist/components/composer-transcription-control.d.ts +7 -0
  195. package/dist/components/composer.d.ts +34 -67
  196. package/dist/components/computer-viewer.d.ts +1 -1
  197. package/dist/components/copy-button.d.ts +3 -1
  198. package/dist/components/desktop-viewer.d.ts +1 -1
  199. package/dist/components/grok-mark.d.ts +26 -0
  200. package/dist/components/human-input-form.d.ts +28 -32
  201. package/dist/components/human-input-surface.d.ts +7 -2
  202. package/dist/components/linkified-text.d.ts +18 -0
  203. package/dist/components/machine-input-display.d.ts +22 -1
  204. package/dist/components/machines/agent-status-icon.d.ts +6 -0
  205. package/dist/components/machines/machine-detail.d.ts +7 -1
  206. package/dist/components/machines/machine-status.d.ts +48 -0
  207. package/dist/components/markdown-table-layout.d.ts +18 -0
  208. package/dist/components/markdown.d.ts +37 -4
  209. package/dist/components/message-timeline.d.ts +86 -7
  210. package/dist/components/model-mark.d.ts +29 -0
  211. package/dist/components/model-policy-picker-menu.d.ts +9 -0
  212. package/dist/components/model-policy-picker.d.ts +35 -28
  213. package/dist/components/new-conversation.d.ts +32 -0
  214. package/dist/components/open-geni-chat.d.ts +73 -0
  215. package/dist/components/open-geni-links.d.ts +68 -0
  216. package/dist/components/openrouter-mark.d.ts +6 -0
  217. package/dist/components/opper-mark.d.ts +7 -0
  218. package/dist/components/preview-loading.d.ts +2 -0
  219. package/dist/components/provider-recovery-notice.d.ts +16 -0
  220. package/dist/components/queue-item-content.d.ts +9 -0
  221. package/dist/components/rehype-secret-refs.d.ts +23 -0
  222. package/dist/components/remark-soft-line-breaks.d.ts +38 -0
  223. package/dist/components/sandbox-files.d.ts +3 -1
  224. package/dist/components/sandbox-workspace.d.ts +18 -0
  225. package/dist/components/secret-question-field.d.ts +31 -0
  226. package/dist/components/secret-ref-chip.d.ts +35 -0
  227. package/dist/components/session-capability-frame.d.ts +37 -0
  228. package/dist/components/session-chrome.d.ts +57 -8
  229. package/dist/components/session-commands-panel.d.ts +6 -0
  230. package/dist/components/session-commands.d.ts +6 -0
  231. package/dist/components/session-connection-request.d.ts +8 -0
  232. package/dist/components/session-conversation.d.ts +157 -0
  233. package/dist/components/session-list.d.ts +39 -0
  234. package/dist/components/session-mcp-capability-card.d.ts +41 -0
  235. package/dist/components/session-proxy-scope.d.ts +35 -0
  236. package/dist/components/session-status.d.ts +4 -1
  237. package/dist/components/session-usage-limit-notice.d.ts +39 -0
  238. package/dist/components/timeline-anchor.d.ts +24 -0
  239. package/dist/components/timeline-annotation-chrome.d.ts +25 -0
  240. package/dist/components/timeline-annotation-layout.d.ts +42 -0
  241. package/dist/components/timeline-annotation-markers.d.ts +8 -0
  242. package/dist/components/timeline-annotation-reveal-context.d.ts +4 -0
  243. package/dist/components/timeline-annotation-shared.d.ts +31 -0
  244. package/dist/components/timeline-annotations-dialog.d.ts +3 -2
  245. package/dist/components/timeline-annotations.d.ts +13 -3
  246. package/dist/components/timeline-reading-progress.d.ts +11 -0
  247. package/dist/components/timeline-search.d.ts +34 -0
  248. package/dist/components/timeline-settlement.d.ts +16 -0
  249. package/dist/components/tool-action-review.d.ts +47 -0
  250. package/dist/components/tool-review-history.d.ts +25 -0
  251. package/dist/components/usage-limit-notice.d.ts +49 -0
  252. package/dist/components/usage-member-list.d.ts +91 -0
  253. package/dist/components/usage-meter.d.ts +73 -0
  254. package/dist/components/use-viewer-menu-dismiss.d.ts +2 -0
  255. package/dist/components/user-message-body.d.ts +10 -1
  256. package/dist/composer-messages.d.ts +74 -0
  257. package/dist/composer-messages.js +9 -0
  258. package/dist/composer-messages.js.map +1 -0
  259. package/dist/composer-voice-events.d.ts +8 -0
  260. package/dist/composer.d.ts +5 -4
  261. package/dist/composer.js +26 -13
  262. package/dist/computer-viewer-GMLDXPON.js +20 -0
  263. package/dist/computer-viewer-GMLDXPON.js.map +1 -0
  264. package/dist/connect-account-identity.d.ts +8 -0
  265. package/dist/connect-accounts.d.ts +15 -0
  266. package/dist/connect-chooser.d.ts +18 -0
  267. package/dist/connect-panel.d.ts +18 -0
  268. package/dist/connect-setup.d.ts +18 -0
  269. package/dist/connect.d.ts +21 -0
  270. package/dist/connect.js +2149 -0
  271. package/dist/connect.js.map +1 -0
  272. package/dist/connection-catalog.d.ts +38 -0
  273. package/dist/connection-discovery.d.ts +12 -0
  274. package/dist/connection-installed.d.ts +17 -0
  275. package/dist/connection-logo.d.ts +9 -0
  276. package/dist/connection-service-logo.d.ts +8 -0
  277. package/dist/connection-service-presentation.d.ts +13 -0
  278. package/dist/connection-skeleton.d.ts +5 -0
  279. package/dist/connection-type-picker.d.ts +6 -0
  280. package/dist/conversation-timeline.d.ts +5 -0
  281. package/dist/desktop.d.ts +7 -0
  282. package/dist/desktop.js +27 -0
  283. package/dist/desktop.js.map +1 -0
  284. package/dist/device-authorization.d.ts +23 -0
  285. package/dist/diffs.d.ts +8 -0
  286. package/dist/diffs.js +15 -0
  287. package/dist/diffs.js.map +1 -0
  288. package/dist/discovery-cache.d.ts +5 -0
  289. package/dist/editor.d.ts +7 -0
  290. package/dist/editor.js +22 -0
  291. package/dist/editor.js.map +1 -0
  292. package/dist/embedded-new-voice-OCRNT6U5.js +18 -0
  293. package/dist/embedded-new-voice-OCRNT6U5.js.map +1 -0
  294. package/dist/embedded-voice-RPHPYVBT.js +18 -0
  295. package/dist/embedded-voice-RPHPYVBT.js.map +1 -0
  296. package/dist/{fleet-decision-row-GGCAT4E4.js → fleet-decision-row-SI63O5V4.js} +4 -1
  297. package/dist/fleet-decision-row-SI63O5V4.js.map +1 -0
  298. package/dist/hooks/latest-question.d.ts +25 -0
  299. package/dist/hooks/shared-machines-list.d.ts +4 -0
  300. package/dist/hooks/shared-query.d.ts +113 -0
  301. package/dist/hooks/use-attached-browsers.d.ts +1 -1
  302. package/dist/hooks/use-auth-runs.d.ts +1 -4
  303. package/dist/hooks/use-available-models.d.ts +1 -1
  304. package/dist/hooks/use-browser-frame-stream.d.ts +1 -1
  305. package/dist/hooks/use-browser-session.d.ts +12 -1
  306. package/dist/hooks/use-client-config-flags.d.ts +49 -0
  307. package/dist/hooks/use-codex-accounts.d.ts +59 -10
  308. package/dist/hooks/use-composer.d.ts +24 -2
  309. package/dist/hooks/use-computer-frame-stream.d.ts +1 -1
  310. package/dist/hooks/use-computer-input-posture.d.ts +13 -0
  311. package/dist/hooks/use-computer-session.d.ts +4 -0
  312. package/dist/hooks/use-connect.d.ts +23 -0
  313. package/dist/hooks/use-desktop-stream.d.ts +1 -1
  314. package/dist/hooks/use-file-attachments.d.ts +12 -0
  315. package/dist/hooks/use-goal.d.ts +2 -1
  316. package/dist/hooks/use-last-started-turn-policy.d.ts +5 -1
  317. package/dist/hooks/use-new-conversation.d.ts +56 -0
  318. package/dist/hooks/use-new-session-draft.d.ts +74 -0
  319. package/dist/hooks/use-realtime-voice-models.d.ts +7 -0
  320. package/dist/hooks/use-sandbox-files.d.ts +4 -1
  321. package/dist/hooks/use-session-conversation.d.ts +49 -0
  322. package/dist/hooks/use-session-events.d.ts +26 -5
  323. package/dist/hooks/use-session-mcp-approval-policy.d.ts +2 -2
  324. package/dist/hooks/use-session-model-account.d.ts +48 -0
  325. package/dist/hooks/use-supergrok-accounts.d.ts +7 -1
  326. package/dist/hooks/use-terminal-stream.d.ts +11 -5
  327. package/dist/hooks/use-usage.d.ts +40 -0
  328. package/dist/hooks/use-vaults.d.ts +53 -0
  329. package/dist/hooks/use-voice-input.d.ts +8 -1
  330. package/dist/hooks/use-workspace-edit.d.ts +4 -0
  331. package/dist/hooks/use-workspace-sessions.d.ts +24 -5
  332. package/dist/human-input-model.d.ts +122 -0
  333. package/dist/identity-link-accounts.d.ts +11 -0
  334. package/dist/identity-link-consent.d.ts +18 -0
  335. package/dist/index.d.ts +82 -20
  336. package/dist/index.js +2340 -6603
  337. package/dist/index.js.map +1 -1
  338. package/dist/interaction.d.ts +1 -1
  339. package/dist/interaction.js +14 -24
  340. package/dist/interaction.js.map +1 -1
  341. package/dist/latest-question-R77KWSUP.js +118 -0
  342. package/dist/latest-question-R77KWSUP.js.map +1 -0
  343. package/dist/lib/clipboard.d.ts +7 -0
  344. package/dist/lib/error-message.d.ts +7 -0
  345. package/dist/lib/format.d.ts +58 -4
  346. package/dist/lib/host-theme.d.ts +77 -0
  347. package/dist/lib/interaction-errors.d.ts +3 -0
  348. package/dist/lib/menu-styles.d.ts +22 -0
  349. package/dist/lib/notify-observer.d.ts +2 -0
  350. package/dist/lib/pierre-diffs-loader.d.ts +20 -0
  351. package/dist/lib/provider-recovery.d.ts +55 -0
  352. package/dist/lib/scrollbars.d.ts +11 -0
  353. package/dist/lib/terminal-input-readiness.d.ts +11 -0
  354. package/dist/lib/transient-retry.d.ts +25 -0
  355. package/dist/lib/workbench-peers.d.ts +36 -0
  356. package/dist/lib/xterm-theme.d.ts +7 -5
  357. package/dist/machines.js +9 -5
  358. package/dist/markdown-table-layout-3PV2UAAH.js +113 -0
  359. package/dist/markdown-table-layout-3PV2UAAH.js.map +1 -0
  360. package/dist/mcp-connection-status.d.ts +14 -0
  361. package/dist/model-mark-paths.d.ts +34 -0
  362. package/dist/model-mark-paths.js +16 -0
  363. package/dist/model-mark-paths.js.map +1 -0
  364. package/dist/model-picker-model.d.ts +111 -0
  365. package/dist/model-picker-model.js +25 -0
  366. package/dist/model-picker-model.js.map +1 -0
  367. package/dist/model-policy-picker-menu-7GJ5URPR.js +17 -0
  368. package/dist/model-policy-picker-menu-7GJ5URPR.js.map +1 -0
  369. package/dist/model-policy.d.ts +30 -3
  370. package/dist/model-policy.js +14 -1
  371. package/dist/native-previews.d.ts +28 -0
  372. package/dist/native-previews.js +82 -0
  373. package/dist/native-previews.js.map +1 -0
  374. package/dist/new-session-draft.d.ts +7 -0
  375. package/dist/new-session-draft.js +639 -0
  376. package/dist/new-session-draft.js.map +1 -0
  377. package/dist/notification-text.d.ts +27 -0
  378. package/dist/{noto-sans-arabic-loader-IA2T4X2A.js → noto-sans-arabic-loader-XSH2KYWJ.js} +3 -1
  379. package/dist/{noto-sans-arabic-loader-IA2T4X2A.js.map → noto-sans-arabic-loader-XSH2KYWJ.js.map} +1 -1
  380. package/dist/{noto-sans-jp-loader.generated-HFGLYBR3.js → noto-sans-jp-loader.generated-MR5L6V7K.js} +3 -1
  381. package/dist/{noto-sans-jp-loader.generated-HFGLYBR3.js.map → noto-sans-jp-loader.generated-MR5L6V7K.js.map} +1 -1
  382. package/dist/older-history.d.ts +3 -2
  383. package/dist/organization-model.d.ts +32 -0
  384. package/dist/organization-model.js +65 -0
  385. package/dist/organization-model.js.map +1 -0
  386. package/dist/{platform-activity-row-BJHUHXAT.js → platform-activity-row-5OCKOQWZ.js} +16 -78
  387. package/dist/platform-activity-row-5OCKOQWZ.js.map +1 -0
  388. package/dist/plugin-details.d.ts +14 -0
  389. package/dist/plugin-discovery.d.ts +25 -0
  390. package/dist/preview-loading-paint.d.ts +20 -0
  391. package/dist/provider.d.ts +25 -2
  392. package/dist/queue-presentation-model.d.ts +72 -0
  393. package/dist/queue-presentation-model.js +38 -0
  394. package/dist/queue-presentation-model.js.map +1 -0
  395. package/dist/{queue-surface-implementation-BSKUWHRI.js → queue-surface-implementation-GJBH7NKO.js} +65 -265
  396. package/dist/queue-surface-implementation-GJBH7NKO.js.map +1 -0
  397. package/dist/realtime/embedded-new-voice.d.ts +1 -0
  398. package/dist/realtime/embedded-voice.d.ts +1 -0
  399. package/dist/realtime/realtime-control.d.ts +4 -65
  400. package/dist/realtime/session-realtime.d.ts +78 -0
  401. package/dist/realtime.js +25 -1333
  402. package/dist/realtime.js.map +1 -1
  403. package/dist/sandbox-files-O27IPOZW.js +21 -0
  404. package/dist/sandbox-files-O27IPOZW.js.map +1 -0
  405. package/dist/sandbox-label-model.d.ts +30 -0
  406. package/dist/sandbox-label-model.js +20 -0
  407. package/dist/sandbox-label-model.js.map +1 -0
  408. package/dist/scrollbars.d.ts +1 -0
  409. package/dist/scrollbars.js +10 -0
  410. package/dist/scrollbars.js.map +1 -0
  411. package/dist/secret-reference-label.d.ts +14 -0
  412. package/dist/secrets-ui.d.ts +57 -0
  413. package/dist/session-agents-model.d.ts +10 -0
  414. package/dist/session-agents-model.js +25 -0
  415. package/dist/session-agents-model.js.map +1 -0
  416. package/dist/session-attention-model.d.ts +8 -0
  417. package/dist/session-attention-model.js +47 -0
  418. package/dist/session-attention-model.js.map +1 -0
  419. package/dist/session-auth-recommendation.d.ts +5 -0
  420. package/dist/session-capability-policy.d.ts +31 -0
  421. package/dist/session-feedback-model.d.ts +20 -0
  422. package/dist/session-feedback-model.js +56 -0
  423. package/dist/session-feedback-model.js.map +1 -0
  424. package/dist/session-list-model.d.ts +138 -0
  425. package/dist/session-list-model.js +274 -0
  426. package/dist/session-list-model.js.map +1 -0
  427. package/dist/session-realtime-7DJOIHQW.js +21 -0
  428. package/dist/session-realtime-7DJOIHQW.js.map +1 -0
  429. package/dist/session-realtime.d.ts +7 -0
  430. package/dist/session-realtime.js +19 -0
  431. package/dist/session-realtime.js.map +1 -0
  432. package/dist/session-status-model.d.ts +36 -0
  433. package/dist/session-ui.d.ts +39 -1
  434. package/dist/session-ui.js +126 -12
  435. package/dist/session-ui.js.map +1 -1
  436. package/dist/session.d.ts +8 -2
  437. package/dist/session.js +35 -20
  438. package/dist/site-snapshot.d.ts +14 -0
  439. package/dist/sites-ui.d.ts +24 -0
  440. package/dist/sites.d.ts +3 -0
  441. package/dist/sites.js +14 -0
  442. package/dist/sites.js.map +1 -0
  443. package/dist/skill-discovery.d.ts +47 -0
  444. package/dist/terminal.d.ts +8 -0
  445. package/dist/terminal.js +32 -0
  446. package/dist/terminal.js.map +1 -0
  447. package/dist/testing/session-scenarios.d.ts +10 -0
  448. package/dist/testing/session-scenarios.js +367 -0
  449. package/dist/testing/session-scenarios.js.map +1 -0
  450. package/dist/timeline/activity-rail.d.ts +11 -2
  451. package/dist/timeline/agent-identity.d.ts +30 -0
  452. package/dist/timeline/agent-row.d.ts +31 -0
  453. package/dist/timeline/allowance-exhausted-row.d.ts +24 -0
  454. package/dist/timeline/compaction-copy.d.ts +46 -0
  455. package/dist/timeline/focus-sequence.d.ts +9 -0
  456. package/dist/timeline/genie-copy.d.ts +3 -0
  457. package/dist/timeline/genie-loading.d.ts +47 -0
  458. package/dist/timeline/index.d.ts +10 -5
  459. package/dist/timeline/knowledge-receipt.d.ts +17 -0
  460. package/dist/timeline/message-sender.d.ts +19 -0
  461. package/dist/timeline/notice-presentation.d.ts +13 -0
  462. package/dist/timeline/parsers.d.ts +11 -0
  463. package/dist/timeline/patch-apply-command.d.ts +18 -0
  464. package/dist/timeline/platform-activity-presentation.d.ts +21 -0
  465. package/dist/timeline/platform-activity-row.d.ts +1 -2
  466. package/dist/timeline/presented-image.d.ts +11 -0
  467. package/dist/timeline/projection.d.ts +31 -2
  468. package/dist/timeline/provider-logo.d.ts +15 -0
  469. package/dist/timeline/question-nav-model.d.ts +23 -0
  470. package/dist/timeline/registry.d.ts +12 -1
  471. package/dist/timeline/retained-image.d.ts +18 -0
  472. package/dist/timeline/retained-loaders.d.ts +27 -0
  473. package/dist/timeline/rolling-activity.d.ts +11 -0
  474. package/dist/timeline/screenshot-lightbox.d.ts +23 -1
  475. package/dist/timeline/session-usage-limit-row.d.ts +11 -0
  476. package/dist/timeline/shared.d.ts +4 -1
  477. package/dist/timeline/startup-dispatch-details.d.ts +5 -0
  478. package/dist/timeline/startup-preference.d.ts +3 -0
  479. package/dist/timeline/startup-timings.d.ts +4 -0
  480. package/dist/timeline/tool-display-name.d.ts +5 -2
  481. package/dist/timeline/tool-presentation.d.ts +172 -0
  482. package/dist/timeline/turn-summary-model.d.ts +95 -0
  483. package/dist/timeline/turn-summary.d.ts +20 -54
  484. package/dist/timeline/types.d.ts +179 -7
  485. package/dist/timeline/work-presentation.d.ts +60 -0
  486. package/dist/timeline-annotation-markers-U3G66KUD.js +166 -0
  487. package/dist/timeline-annotation-markers-U3G66KUD.js.map +1 -0
  488. package/dist/timeline-annotation-selection-BI7QTPTZ.js +242 -0
  489. package/dist/timeline-annotation-selection-BI7QTPTZ.js.map +1 -0
  490. package/dist/timeline-annotations-dialog-FOMHSDTE.js +274 -0
  491. package/dist/timeline-annotations-dialog-FOMHSDTE.js.map +1 -0
  492. package/dist/timeline-model.d.ts +29 -0
  493. package/dist/timeline-model.js +254 -0
  494. package/dist/timeline-model.js.map +1 -0
  495. package/dist/usage/allowance-copy.d.ts +25 -0
  496. package/dist/usage/session-usage-limit.d.ts +88 -0
  497. package/dist/usage/summary.d.ts +35 -0
  498. package/dist/usage.d.ts +17 -0
  499. package/dist/usage.js +1187 -0
  500. package/dist/usage.js.map +1 -0
  501. package/dist/voice-recording-owner.d.ts +7 -0
  502. package/package.json +106 -7
  503. package/src/approvals.ts +8 -1
  504. package/src/artifacts-spreadsheet.ts +1 -0
  505. package/src/artifacts.ts +44 -0
  506. package/src/assets/README.md +8 -0
  507. package/src/assets/gmail.ico +0 -0
  508. package/src/assets/outlook.ico +0 -0
  509. package/src/capability-catalog-row.tsx +94 -0
  510. package/src/capability-logo-fallback.ts +22 -0
  511. package/src/client.ts +20 -31
  512. package/src/commands/registry.ts +18 -15
  513. package/src/commands/types.ts +2 -0
  514. package/src/components/anthropic-mark.tsx +10 -0
  515. package/src/components/approval-surface.tsx +401 -138
  516. package/src/components/artifacts/artifact-chrome.tsx +413 -0
  517. package/src/components/artifacts/artifact-sandbox.tsx +193 -0
  518. package/src/components/artifacts/artifact-surface.tsx +40 -20
  519. package/src/components/artifacts/chat-interactive-block.tsx +260 -0
  520. package/src/components/artifacts/deferred-chat-media.tsx +67 -0
  521. package/src/components/artifacts/document-editor.tsx +141 -16
  522. package/src/components/artifacts/editable-artifact-ui.tsx +4 -2
  523. package/src/components/artifacts/editable-artifact-view.tsx +197 -0
  524. package/src/components/artifacts/editable-artifact-workbench.tsx +5 -2
  525. package/src/components/artifacts/editable-document.tsx +37 -36
  526. package/src/components/artifacts/editable-presentation.tsx +36 -18
  527. package/src/components/artifacts/editable-spreadsheet.tsx +543 -103
  528. package/src/components/artifacts/index.ts +45 -0
  529. package/src/components/artifacts/inline-html-document.ts +24 -0
  530. package/src/components/artifacts/latest-task-runner.ts +49 -0
  531. package/src/components/artifacts/presentation-editor.tsx +323 -67
  532. package/src/components/artifacts/published-html-artifact-frame.tsx +122 -5
  533. package/src/components/artifacts/session-artifact-viewer.tsx +378 -0
  534. package/src/components/artifacts/site-view.tsx +121 -0
  535. package/src/components/artifacts/spreadsheet-canvas.ts +5 -10
  536. package/src/components/artifacts/spreadsheet-command-queue.ts +184 -0
  537. package/src/components/artifacts/spreadsheet-download.tsx +109 -0
  538. package/src/components/artifacts/spreadsheet-general-display.ts +43 -0
  539. package/src/components/artifacts/spreadsheet-grid.tsx +344 -144
  540. package/src/components/artifacts/spreadsheet-resize.tsx +421 -0
  541. package/src/components/artifacts/spreadsheet-submissions.tsx +46 -0
  542. package/src/components/artifacts/visualization-assets/base.css +1015 -0
  543. package/src/components/artifacts/visualization-assets/helpers.html +349 -0
  544. package/src/components/artifacts/visualization-assets.gen.ts +3 -0
  545. package/src/components/browser-select-control.tsx +312 -0
  546. package/src/components/browser-viewer.tsx +778 -318
  547. package/src/components/chat-composer.tsx +47 -5
  548. package/src/components/child-session-link.tsx +36 -0
  549. package/src/components/claude-mark.tsx +11 -0
  550. package/src/components/code-editor.tsx +13 -16
  551. package/src/components/composer-transcription-control.tsx +128 -30
  552. package/src/components/composer.tsx +404 -195
  553. package/src/components/computer-viewer.tsx +880 -253
  554. package/src/components/copy-button.tsx +13 -5
  555. package/src/components/desktop-viewer.tsx +1 -1
  556. package/src/components/enrollment-consent.tsx +1 -1
  557. package/src/components/enrollment-device-flow.tsx +1 -1
  558. package/src/components/file-browser.tsx +10 -14
  559. package/src/components/fleet-tile.tsx +5 -3
  560. package/src/components/generated-video-player.tsx +4 -2
  561. package/src/components/grok-mark.tsx +34 -0
  562. package/src/components/human-input-form.tsx +590 -283
  563. package/src/components/human-input-surface.tsx +11 -0
  564. package/src/components/interaction-intervention-banner.tsx +2 -2
  565. package/src/components/linkified-text.tsx +79 -0
  566. package/src/components/machine-card.tsx +35 -78
  567. package/src/components/machine-dock-bar.tsx +1 -1
  568. package/src/components/machine-input-display.ts +197 -3
  569. package/src/components/machines/agent-status-icon.tsx +31 -0
  570. package/src/components/machines/machine-detail.tsx +200 -31
  571. package/src/components/machines/machine-operation-policy.tsx +1 -1
  572. package/src/components/machines/machine-status.ts +241 -0
  573. package/src/components/machines-dashboard.tsx +2 -17
  574. package/src/components/markdown-table-layout.ts +143 -0
  575. package/src/components/markdown.tsx +466 -129
  576. package/src/components/message-timeline.tsx +2370 -667
  577. package/src/components/model-mark.tsx +102 -0
  578. package/src/components/model-picker.tsx +15 -4
  579. package/src/components/model-policy-picker-menu.tsx +371 -0
  580. package/src/components/model-policy-picker.tsx +252 -429
  581. package/src/components/new-conversation.tsx +221 -0
  582. package/src/components/open-geni-chat.tsx +309 -0
  583. package/src/components/open-geni-links.tsx +179 -0
  584. package/src/components/openrouter-mark.tsx +13 -0
  585. package/src/components/opper-mark.tsx +18 -0
  586. package/src/components/pierre-diff.tsx +41 -16
  587. package/src/components/pierre-file.tsx +35 -10
  588. package/src/components/preview-loading.tsx +109 -0
  589. package/src/components/provider-recovery-notice.tsx +49 -0
  590. package/src/components/queue-item-content.ts +14 -0
  591. package/src/components/queue-surface-implementation.tsx +51 -356
  592. package/src/components/queue-surface-state.tsx +3 -1
  593. package/src/components/rehype-secret-refs.ts +98 -0
  594. package/src/components/remark-soft-line-breaks.ts +166 -0
  595. package/src/components/sandbox-files.tsx +91 -15
  596. package/src/components/sandbox-terminal.tsx +84 -13
  597. package/src/components/sandbox-workspace.tsx +147 -51
  598. package/src/components/secret-question-field.tsx +324 -0
  599. package/src/components/secret-ref-chip.tsx +185 -0
  600. package/src/components/session-capability-frame.tsx +197 -0
  601. package/src/components/session-chrome.tsx +842 -251
  602. package/src/components/session-commands-panel.tsx +126 -0
  603. package/src/components/session-commands.tsx +18 -0
  604. package/src/components/session-connection-request.tsx +97 -0
  605. package/src/components/session-conversation.tsx +876 -0
  606. package/src/components/session-list.tsx +257 -0
  607. package/src/components/session-mcp-capability-card.tsx +680 -0
  608. package/src/components/session-proxy-scope.tsx +153 -0
  609. package/src/components/session-status.tsx +26 -17
  610. package/src/components/session-usage-limit-notice.tsx +174 -0
  611. package/src/components/timeline-anchor.tsx +119 -0
  612. package/src/components/timeline-annotation-chrome.tsx +196 -0
  613. package/src/components/timeline-annotation-layout.ts +268 -0
  614. package/src/components/timeline-annotation-markers.tsx +185 -0
  615. package/src/components/timeline-annotation-reveal-context.ts +9 -0
  616. package/src/components/timeline-annotation-selection.tsx +106 -54
  617. package/src/components/timeline-annotation-shared.ts +245 -0
  618. package/src/components/timeline-annotations-dialog.tsx +185 -128
  619. package/src/components/timeline-annotations.tsx +189 -45
  620. package/src/components/timeline-reading-progress.ts +80 -0
  621. package/src/components/timeline-search.tsx +168 -0
  622. package/src/components/timeline-settlement.ts +60 -0
  623. package/src/components/tool-action-review.tsx +650 -0
  624. package/src/components/tool-review-history.tsx +88 -0
  625. package/src/components/usage-limit-notice.tsx +179 -0
  626. package/src/components/usage-member-list.tsx +792 -0
  627. package/src/components/usage-meter.tsx +382 -0
  628. package/src/components/use-viewer-menu-dismiss.ts +33 -0
  629. package/src/components/user-message-body.tsx +27 -2
  630. package/src/components/workspace-dock.tsx +18 -1
  631. package/src/composer-messages.ts +150 -0
  632. package/src/composer-voice-events.ts +12 -0
  633. package/src/composer.ts +6 -1
  634. package/src/connect-account-identity.tsx +34 -0
  635. package/src/connect-accounts.tsx +233 -0
  636. package/src/connect-chooser.tsx +336 -0
  637. package/src/connect-panel.tsx +99 -0
  638. package/src/connect-setup.tsx +355 -0
  639. package/src/connect.ts +60 -0
  640. package/src/connection-assets.d.ts +4 -0
  641. package/src/connection-catalog.tsx +162 -0
  642. package/src/connection-discovery.tsx +238 -0
  643. package/src/connection-installed.tsx +51 -0
  644. package/src/connection-logo.tsx +37 -0
  645. package/src/connection-service-logo.tsx +55 -0
  646. package/src/connection-service-presentation.ts +46 -0
  647. package/src/connection-skeleton.tsx +16 -0
  648. package/src/connection-type-picker.tsx +36 -0
  649. package/src/conversation-timeline.ts +92 -0
  650. package/src/desktop.ts +24 -0
  651. package/src/device-authorization.tsx +98 -0
  652. package/src/diffs.ts +16 -0
  653. package/src/discovery-cache.ts +42 -0
  654. package/src/editor.ts +13 -0
  655. package/src/hooks/internal.ts +3 -2
  656. package/src/hooks/latest-question.ts +164 -0
  657. package/src/hooks/shared-machines-list.ts +34 -1
  658. package/src/hooks/shared-query.ts +721 -0
  659. package/src/hooks/use-attached-browsers.ts +1 -1
  660. package/src/hooks/use-auth-runs.ts +0 -27
  661. package/src/hooks/use-available-models.ts +2 -2
  662. package/src/hooks/use-browser-frame-stream.ts +19 -2
  663. package/src/hooks/use-browser-session.ts +680 -205
  664. package/src/hooks/use-browser-sessions.ts +32 -1
  665. package/src/hooks/use-client-config-flags.ts +118 -0
  666. package/src/hooks/use-codex-accounts.ts +247 -47
  667. package/src/hooks/use-composer.ts +227 -44
  668. package/src/hooks/use-computer-frame-stream.ts +25 -7
  669. package/src/hooks/use-computer-input-posture.ts +94 -0
  670. package/src/hooks/use-computer-session.ts +409 -95
  671. package/src/hooks/use-connect.ts +23 -0
  672. package/src/hooks/use-desktop-stream.ts +19 -28
  673. package/src/hooks/use-file-attachments.ts +80 -4
  674. package/src/hooks/use-goal.ts +79 -9
  675. package/src/hooks/use-last-started-turn-policy.ts +37 -11
  676. package/src/hooks/use-machines.ts +4 -0
  677. package/src/hooks/use-new-conversation.ts +374 -0
  678. package/src/hooks/use-new-session-draft.ts +813 -0
  679. package/src/hooks/use-realtime-voice-models.ts +46 -0
  680. package/src/hooks/use-sandbox-files.ts +68 -20
  681. package/src/hooks/use-session-background-commands.ts +22 -11
  682. package/src/hooks/use-session-capabilities.ts +3 -2
  683. package/src/hooks/use-session-conversation.ts +150 -0
  684. package/src/hooks/use-session-events.ts +531 -335
  685. package/src/hooks/use-session-mcp-approval-policy.ts +13 -5
  686. package/src/hooks/use-session-model-account.ts +174 -0
  687. package/src/hooks/use-session.ts +30 -2
  688. package/src/hooks/use-slash-commands.ts +6 -11
  689. package/src/hooks/use-supergrok-accounts.ts +22 -8
  690. package/src/hooks/use-terminal-stream.ts +153 -27
  691. package/src/hooks/use-transcription.ts +6 -0
  692. package/src/hooks/use-turn-queue.ts +2 -1
  693. package/src/hooks/use-usage.ts +100 -0
  694. package/src/hooks/use-vaults.ts +153 -0
  695. package/src/hooks/use-video-artifact-playback.ts +1 -1
  696. package/src/hooks/use-voice-input.ts +127 -19
  697. package/src/hooks/use-workspace-capture.ts +3 -2
  698. package/src/hooks/use-workspace-edit.ts +23 -5
  699. package/src/hooks/use-workspace-sessions.ts +74 -7
  700. package/src/human-input-model.ts +359 -0
  701. package/src/identity-link-accounts.tsx +148 -0
  702. package/src/identity-link-consent.tsx +192 -0
  703. package/src/index.ts +262 -16
  704. package/src/interaction.ts +1 -0
  705. package/src/lib/clipboard.ts +29 -0
  706. package/src/lib/error-message.ts +37 -0
  707. package/src/lib/format.ts +205 -10
  708. package/src/lib/host-theme.ts +529 -0
  709. package/src/lib/interaction-errors.ts +15 -0
  710. package/src/lib/menu-styles.ts +44 -0
  711. package/src/lib/notify-observer.ts +15 -0
  712. package/src/lib/pierre-diffs-loader.ts +53 -0
  713. package/src/lib/provider-recovery.ts +243 -0
  714. package/src/lib/scrollbars.ts +30 -0
  715. package/src/lib/terminal-input-readiness.ts +51 -0
  716. package/src/lib/transient-retry.ts +99 -0
  717. package/src/lib/workbench-peers.ts +62 -0
  718. package/src/lib/xterm-theme.ts +23 -21
  719. package/src/mcp-connection-status.ts +35 -0
  720. package/src/model-mark-paths.ts +53 -0
  721. package/src/model-picker-model.ts +330 -0
  722. package/src/model-policy.ts +299 -74
  723. package/src/native-previews.ts +100 -0
  724. package/src/new-session-draft.ts +22 -0
  725. package/src/notification-text.ts +81 -0
  726. package/src/older-history.ts +22 -4
  727. package/src/organization-model.ts +118 -0
  728. package/src/plugin-details.tsx +185 -0
  729. package/src/plugin-discovery.tsx +196 -0
  730. package/src/preview-loading-paint.ts +68 -0
  731. package/src/provider.tsx +74 -15
  732. package/src/queue-presentation-model.ts +464 -0
  733. package/src/realtime/dropdown-menu.tsx +19 -12
  734. package/src/realtime/embedded-new-voice.tsx +1 -0
  735. package/src/realtime/embedded-voice.tsx +3 -0
  736. package/src/realtime/realtime-control.tsx +138 -550
  737. package/src/realtime/session-realtime.ts +566 -0
  738. package/src/sandbox-label-model.ts +53 -0
  739. package/src/scrollbars.ts +3 -0
  740. package/src/secret-reference-label.ts +43 -0
  741. package/src/secrets-ui.tsx +59 -0
  742. package/src/session-agents-model.ts +33 -0
  743. package/src/session-attention-model.ts +62 -0
  744. package/src/session-auth-recommendation.ts +48 -0
  745. package/src/session-capability-policy.ts +196 -0
  746. package/src/session-context.ts +3 -4
  747. package/src/session-feedback-model.ts +95 -0
  748. package/src/session-list-model.ts +434 -0
  749. package/src/session-realtime.ts +18 -0
  750. package/src/session-status-model.ts +99 -0
  751. package/src/session-ui.ts +98 -1
  752. package/src/session.ts +17 -1
  753. package/src/site-snapshot.ts +74 -0
  754. package/src/sites-ui.tsx +348 -0
  755. package/src/sites.ts +3 -0
  756. package/src/skill-discovery.tsx +208 -0
  757. package/src/terminal.ts +26 -0
  758. package/src/testing/session-scenarios.ts +404 -0
  759. package/src/timeline/activity-rail.tsx +242 -101
  760. package/src/timeline/agent-identity.tsx +84 -0
  761. package/src/timeline/agent-row.tsx +231 -0
  762. package/src/timeline/allowance-exhausted-row.tsx +86 -0
  763. package/src/timeline/compaction-copy.ts +115 -0
  764. package/src/timeline/fleet-decision-projection.ts +2 -1
  765. package/src/timeline/fleet-decision-row.tsx +1 -0
  766. package/src/timeline/focus-sequence.ts +44 -0
  767. package/src/timeline/genie-copy.ts +19 -0
  768. package/src/timeline/genie-loading.tsx +143 -0
  769. package/src/timeline/index.ts +30 -2
  770. package/src/timeline/knowledge-receipt.tsx +100 -0
  771. package/src/timeline/message-sender.tsx +71 -0
  772. package/src/timeline/notice-presentation.ts +48 -0
  773. package/src/timeline/parsers.ts +42 -2
  774. package/src/timeline/patch-apply-command.tsx +135 -0
  775. package/src/timeline/platform-activity-presentation.ts +166 -0
  776. package/src/timeline/platform-activity-row.tsx +15 -90
  777. package/src/timeline/presented-image.ts +63 -0
  778. package/src/timeline/projection.ts +1742 -76
  779. package/src/timeline/provider-logo.tsx +53 -0
  780. package/src/timeline/question-nav-model.ts +28 -0
  781. package/src/timeline/registry.ts +26 -4
  782. package/src/timeline/retained-image.ts +97 -0
  783. package/src/timeline/retained-loaders.ts +91 -0
  784. package/src/timeline/rolling-activity.tsx +80 -0
  785. package/src/timeline/screenshot-lightbox.tsx +228 -5
  786. package/src/timeline/session-usage-limit-row.tsx +42 -0
  787. package/src/timeline/shared.tsx +42 -15
  788. package/src/timeline/startup-dispatch-details.tsx +36 -0
  789. package/src/timeline/startup-preference.ts +33 -0
  790. package/src/timeline/startup-timings.tsx +145 -0
  791. package/src/timeline/tool-display-name.ts +19 -7
  792. package/src/timeline/tool-presentation.ts +1316 -0
  793. package/src/timeline/tool-renderers.tsx +835 -1138
  794. package/src/timeline/turn-summary-model.ts +343 -0
  795. package/src/timeline/turn-summary.tsx +272 -365
  796. package/src/timeline/types.ts +189 -6
  797. package/src/timeline/work-presentation.ts +189 -0
  798. package/src/timeline-model.ts +143 -0
  799. package/src/usage/allowance-copy.ts +64 -0
  800. package/src/usage/session-usage-limit.ts +266 -0
  801. package/src/usage/summary.ts +93 -0
  802. package/src/usage.ts +70 -0
  803. package/src/voice-recording-owner.ts +22 -0
  804. package/styles/compiled.css +2319 -748
  805. package/styles/connect.css +290 -0
  806. package/styles/connect.d.ts +1 -0
  807. package/styles/effective-tokens.css +1 -0
  808. package/styles/index.css +309 -9
  809. package/styles/responsive.css +99 -7
  810. package/styles/session-capability.css +44 -0
  811. package/styles/tokens.css +134 -66
  812. package/dist/browser-viewer-MKKFRRRV.js +0 -14
  813. package/dist/chunk-2DZVYHVO.js +0 -470
  814. package/dist/chunk-2DZVYHVO.js.map +0 -1
  815. package/dist/chunk-3AGBGTRT.js.map +0 -1
  816. package/dist/chunk-4MDLEHXL.js.map +0 -1
  817. package/dist/chunk-5YK2ZDIG.js.map +0 -1
  818. package/dist/chunk-7EAFGICR.js +0 -302
  819. package/dist/chunk-7EAFGICR.js.map +0 -1
  820. package/dist/chunk-ELIYWBZR.js.map +0 -1
  821. package/dist/chunk-H5YGYNXS.js.map +0 -1
  822. package/dist/chunk-HUIKIDM5.js.map +0 -1
  823. package/dist/chunk-ICA6R6TW.js.map +0 -1
  824. package/dist/chunk-IOLVN74D.js.map +0 -1
  825. package/dist/chunk-JAQ5K7W6.js.map +0 -1
  826. package/dist/chunk-JVYQRRC4.js.map +0 -1
  827. package/dist/chunk-KCGXPP5V.js.map +0 -1
  828. package/dist/chunk-KZ73RL76.js.map +0 -1
  829. package/dist/chunk-NEXLLTP4.js.map +0 -1
  830. package/dist/chunk-PEI6RANI.js.map +0 -1
  831. package/dist/chunk-VTOREEXF.js +0 -142
  832. package/dist/chunk-VTOREEXF.js.map +0 -1
  833. package/dist/chunk-WSK7G5LE.js +0 -170
  834. package/dist/chunk-WSK7G5LE.js.map +0 -1
  835. package/dist/chunk-X4A66EWZ.js +0 -223
  836. package/dist/chunk-X4A66EWZ.js.map +0 -1
  837. package/dist/chunk-XYRDDSXF.js.map +0 -1
  838. package/dist/chunk-YG4QEQF5.js +0 -9557
  839. package/dist/chunk-YG4QEQF5.js.map +0 -1
  840. package/dist/chunk-YVCHAQZY.js.map +0 -1
  841. package/dist/chunk-ZPBTI3TE.js.map +0 -1
  842. package/dist/computer-viewer-FWEZISW4.js +0 -16
  843. package/dist/fleet-decision-row-GGCAT4E4.js.map +0 -1
  844. package/dist/hooks/use-environments.d.ts +0 -41
  845. package/dist/hooks/use-packs.d.ts +0 -32
  846. package/dist/platform-activity-row-BJHUHXAT.js.map +0 -1
  847. package/dist/queue-surface-implementation-BSKUWHRI.js.map +0 -1
  848. package/dist/timeline-annotation-selection-3L7LHGG2.js +0 -187
  849. package/dist/timeline-annotation-selection-3L7LHGG2.js.map +0 -1
  850. package/dist/timeline-annotations-dialog-U7EVLR75.js +0 -196
  851. package/dist/timeline-annotations-dialog-U7EVLR75.js.map +0 -1
  852. package/src/hooks/use-environments.ts +0 -182
  853. package/src/hooks/use-packs.ts +0 -157
  854. /package/dist/{browser-viewer-MKKFRRRV.js.map → browser-viewer-ZWR6MWJ7.js.map} +0 -0
  855. /package/dist/{computer-viewer-FWEZISW4.js.map → chat-interactive-block-4EUKJXUO.js.map} +0 -0
@@ -1,26 +1,186 @@
1
+ "use client";
1
2
  import {
2
3
  ArtifactSurface,
3
4
  EditableArtifactMessage,
4
5
  editableArtifactAccessRevoked,
5
6
  editableArtifactStatusLabel,
6
7
  useEditableArtifactView
7
- } from "./chunk-KCGXPP5V.js";
8
+ } from "./chunk-PYEOPA4M.js";
9
+ import {
10
+ ArtifactButton
11
+ } from "./chunk-TGXK4BAZ.js";
8
12
  import {
9
13
  cn
10
- } from "./chunk-22KP6LR5.js";
14
+ } from "./chunk-TXS65BB2.js";
11
15
 
12
16
  // src/components/artifacts/spreadsheet-grid.tsx
13
17
  import { PlusIcon } from "lucide-react";
14
18
  import {
15
- useCallback,
16
- useEffect,
19
+ useCallback as useCallback3,
20
+ useEffect as useEffect3,
17
21
  useId,
18
22
  useLayoutEffect,
19
- useMemo,
20
- useRef,
21
- useState
23
+ useMemo as useMemo2,
24
+ useRef as useRef3,
25
+ useState as useState3
22
26
  } from "react";
23
27
 
28
+ // src/components/artifacts/spreadsheet-command-queue.ts
29
+ import { useCallback, useEffect, useRef, useState } from "react";
30
+ function overlaps(a, b) {
31
+ return a.top <= b.bottom && a.bottom >= b.top && a.left <= b.right && a.right >= b.left;
32
+ }
33
+ function contains(a, b) {
34
+ return a.top <= b.top && a.bottom >= b.bottom && a.left <= b.left && a.right >= b.right;
35
+ }
36
+ function useSpreadsheetCommandQueue({
37
+ scopeKey,
38
+ enabled,
39
+ onCommandError
40
+ }) {
41
+ const [pendingCount, setPendingCount] = useState(0);
42
+ const [failures, setFailures] = useState([]);
43
+ const commandsRef = useRef(/* @__PURE__ */ new Map());
44
+ const nextIdRef = useRef(0);
45
+ const mountedRef = useRef(true);
46
+ const optionsRef = useRef({ scopeKey, enabled, onCommandError });
47
+ optionsRef.current = { scopeKey, enabled, onCommandError };
48
+ const scopeRef = useRef({ key: scopeKey, epoch: 0 });
49
+ if (scopeRef.current.key !== scopeKey) {
50
+ scopeRef.current = { key: scopeKey, epoch: scopeRef.current.epoch + 1 };
51
+ }
52
+ useEffect(() => {
53
+ mountedRef.current = true;
54
+ return () => {
55
+ mountedRef.current = false;
56
+ };
57
+ }, []);
58
+ useEffect(() => {
59
+ commandsRef.current.clear();
60
+ setPendingCount(0);
61
+ setFailures([]);
62
+ }, [scopeKey]);
63
+ const refreshFailures = useCallback(() => {
64
+ setFailures(
65
+ [...commandsRef.current.values()].filter(
66
+ (command) => command.message !== void 0 && !command.covered
67
+ )
68
+ );
69
+ }, []);
70
+ const clearPreflightFailure = useCallback(() => {
71
+ let changed = false;
72
+ for (const previous of commandsRef.current.values()) {
73
+ if (previous.target === null && previous.message !== void 0) {
74
+ commandsRef.current.delete(previous.id);
75
+ changed = true;
76
+ }
77
+ }
78
+ if (changed) refreshFailures();
79
+ }, [refreshFailures]);
80
+ const run = useCallback(
81
+ (invoke, retry, rollback, target, accepted) => {
82
+ if (!optionsRef.current.enabled) return;
83
+ const scope = optionsRef.current.scopeKey;
84
+ const epoch = scopeRef.current.epoch;
85
+ const id = ++nextIdRef.current;
86
+ clearPreflightFailure();
87
+ const command = { id, target: null, overlapped: false, covered: false };
88
+ commandsRef.current.set(id, command);
89
+ const current = () => mountedRef.current && optionsRef.current.scopeKey === scope && scopeRef.current.epoch === epoch;
90
+ const fail = (cause) => {
91
+ if (!current()) return;
92
+ rollback(id);
93
+ if (command.covered) {
94
+ commandsRef.current.delete(id);
95
+ return;
96
+ }
97
+ const error = cause instanceof Error ? cause : new Error(String(cause));
98
+ command.message = error.message || "Spreadsheet change failed";
99
+ command.retry = () => {
100
+ if (!current() || !optionsRef.current.enabled || command.overlapped) return;
101
+ commandsRef.current.delete(id);
102
+ refreshFailures();
103
+ retry();
104
+ };
105
+ refreshFailures();
106
+ optionsRef.current.onCommandError?.(error);
107
+ };
108
+ let result;
109
+ try {
110
+ command.target = typeof target === "function" ? target() : target ?? null;
111
+ if (command.target) {
112
+ for (const previous of commandsRef.current.values()) {
113
+ if (previous.id === id || !previous.target || !overlaps(command.target, previous.target))
114
+ continue;
115
+ previous.overlapped = true;
116
+ previous.covered ||= contains(command.target, previous.target);
117
+ if (previous.covered && previous.message !== void 0)
118
+ commandsRef.current.delete(previous.id);
119
+ }
120
+ refreshFailures();
121
+ }
122
+ result = invoke(id);
123
+ } catch (cause) {
124
+ fail(cause);
125
+ return;
126
+ }
127
+ const succeed = () => {
128
+ if (!current()) return;
129
+ commandsRef.current.delete(id);
130
+ accepted?.(id);
131
+ };
132
+ if (!result || typeof result.then !== "function") {
133
+ succeed();
134
+ return;
135
+ }
136
+ setPendingCount((count) => count + 1);
137
+ void Promise.resolve(result).then(
138
+ () => {
139
+ if (!current()) return;
140
+ setPendingCount((count) => Math.max(0, count - 1));
141
+ succeed();
142
+ },
143
+ (cause) => {
144
+ if (!current()) return;
145
+ setPendingCount((count) => Math.max(0, count - 1));
146
+ fail(cause);
147
+ }
148
+ );
149
+ },
150
+ [clearPreflightFailure, refreshFailures]
151
+ );
152
+ const first = failures[0];
153
+ return {
154
+ run,
155
+ clearPreflightFailure,
156
+ pendingCount,
157
+ error: first ? {
158
+ message: failures.length > 1 ? `${first.message} (${failures.length} changes not saved)` : first.message,
159
+ retry: enabled && !first.overlapped ? first.retry : void 0
160
+ } : null
161
+ };
162
+ }
163
+
164
+ // src/components/artifacts/spreadsheet-general-display.ts
165
+ function formatSpreadsheetGeneralDisplay(value) {
166
+ if (value === null || value === void 0) return "";
167
+ if (value instanceof Date) return Number.isNaN(value.getTime()) ? "" : value.toLocaleDateString();
168
+ if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
169
+ if (typeof value === "number") {
170
+ if (Object.is(value, -0) || value === 0) return "0";
171
+ if (!Number.isFinite(value)) return String(value);
172
+ const rounded = Number(value.toPrecision(15));
173
+ return String(Number.isFinite(rounded) ? rounded : value);
174
+ }
175
+ return String(value);
176
+ }
177
+ function spreadsheetCellEditSource(value) {
178
+ if (value === null || value === void 0) return "";
179
+ if (value instanceof Date) return Number.isNaN(value.getTime()) ? "" : value.toLocaleDateString();
180
+ if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
181
+ return String(value);
182
+ }
183
+
24
184
  // src/components/artifacts/spreadsheet-canvas.ts
25
185
  var TILE_SIZE = 256;
26
186
  var MAX_CACHE_PHYSICAL_PIXELS = 32e6;
@@ -266,7 +426,7 @@ var SpreadsheetCanvasRenderer = class {
266
426
  paintTileGrid(context, input, tileLeft, tileTop, tileRight, tileBottom);
267
427
  for (const cell of cells) {
268
428
  const value = input.projection.valueAt(cell);
269
- const text = displayValue(value);
429
+ const text = formatSpreadsheetGeneralDisplay(value);
270
430
  if (!text) continue;
271
431
  paintCellText(context, input, cell, text, tileLeft, tileTop);
272
432
  }
@@ -351,7 +511,7 @@ function paintSelection(context, input) {
351
511
  const top = input.columnHeaderHeight + input.rows.offsetAt(selection.top) - input.logicalScrollTop;
352
512
  const bottom = input.columnHeaderHeight + input.rows.offsetAt(selection.bottom + 1) - input.logicalScrollTop;
353
513
  context.save();
354
- setFill(context, input.theme.accent, "#3b82f6");
514
+ setFill(context, input.theme.accent, "#545454");
355
515
  context.globalAlpha = 0.1;
356
516
  context.fillRect(left, top, right - left, bottom - top);
357
517
  context.restore();
@@ -360,7 +520,7 @@ function paintSelection(context, input) {
360
520
  const activeWidth = input.columns.sizeAt(selection.focusColumn);
361
521
  const activeHeight = input.rows.sizeAt(selection.focusRow);
362
522
  context.save();
363
- setStroke(context, input.theme.accent, "#3b82f6");
523
+ setStroke(context, input.theme.accent, "#545454");
364
524
  context.lineWidth = 2;
365
525
  context.strokeRect(
366
526
  activeLeft + 1,
@@ -522,12 +682,6 @@ function ellipsize(context, input, maximumWidth) {
522
682
  function finitePositive(value, fallback) {
523
683
  return value !== void 0 && Number.isFinite(value) && value > 0 ? value : fallback;
524
684
  }
525
- function displayValue(value) {
526
- if (value === null || value === void 0) return "";
527
- if (value instanceof Date) return Number.isNaN(value.getTime()) ? "" : value.toLocaleDateString();
528
- if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
529
- return String(value);
530
- }
531
685
  function columnName(index) {
532
686
  let value = index + 1;
533
687
  let result = "";
@@ -542,8 +696,330 @@ function clamp(value, minimum, maximum) {
542
696
  return Math.max(minimum, Math.min(maximum, value));
543
697
  }
544
698
 
699
+ // src/components/artifacts/spreadsheet-resize.tsx
700
+ import {
701
+ useCallback as useCallback2,
702
+ useEffect as useEffect2,
703
+ useMemo,
704
+ useRef as useRef2,
705
+ useState as useState2
706
+ } from "react";
707
+ import { jsx } from "react/jsx-runtime";
708
+ var MIN_SIZE = 8;
709
+ var MAX_SIZE = 4096;
710
+ function keyOf(change) {
711
+ return `${change.axis}:${change.index}`;
712
+ }
713
+ function boundedSize(size) {
714
+ return Math.max(MIN_SIZE, Math.min(MAX_SIZE, Math.round(size)));
715
+ }
716
+ function useSpreadsheetResizing(options) {
717
+ const optionsRef = useRef2(options);
718
+ optionsRef.current = options;
719
+ const [gesture, setGesture] = useState2(null);
720
+ const [pending, setPending] = useState2([]);
721
+ const [inFlightCount, setInFlightCount] = useState2(0);
722
+ const [errors, setErrors] = useState2([]);
723
+ const errorsRef = useRef2(/* @__PURE__ */ new Map());
724
+ const activeRef = useRef2(null);
725
+ const pendingRef = useRef2(/* @__PURE__ */ new Map());
726
+ const frameRef = useRef2(null);
727
+ const nextIdRef = useRef2(0);
728
+ const scopeRef = useRef2(0);
729
+ const mountedRef = useRef2(true);
730
+ const clearError = useCallback2(() => {
731
+ errorsRef.current.clear();
732
+ setErrors([]);
733
+ }, []);
734
+ const cancelFrame = useCallback2(() => {
735
+ if (frameRef.current !== null) globalThis.cancelAnimationFrame?.(frameRef.current);
736
+ frameRef.current = null;
737
+ }, []);
738
+ const cancel = useCallback2(() => {
739
+ cancelFrame();
740
+ activeRef.current = null;
741
+ setGesture(null);
742
+ }, [cancelFrame]);
743
+ useEffect2(() => {
744
+ mountedRef.current = true;
745
+ return () => {
746
+ mountedRef.current = false;
747
+ scopeRef.current += 1;
748
+ cancelFrame();
749
+ };
750
+ }, [cancelFrame]);
751
+ useEffect2(() => {
752
+ scopeRef.current += 1;
753
+ cancel();
754
+ pendingRef.current.clear();
755
+ setPending([]);
756
+ setInFlightCount(0);
757
+ clearError();
758
+ }, [cancel, clearError, options.enabled, options.generationId, options.sheetId]);
759
+ const authoritativeSize = useCallback2((axis, index) => {
760
+ const current = optionsRef.current;
761
+ const entries = axis === "row" ? current.rowHeights : current.columnWidths;
762
+ return entries.find(([at]) => at === index)?.[1] ?? (axis === "row" ? current.defaultRowHeight : current.defaultColumnWidth);
763
+ }, []);
764
+ useEffect2(() => {
765
+ let changed = false;
766
+ for (const [key, entry] of pendingRef.current) {
767
+ if (entry.settled && (authoritativeSize(entry.axis, entry.index) === entry.size || options.revision !== entry.baseRevision)) {
768
+ pendingRef.current.delete(key);
769
+ changed = true;
770
+ }
771
+ }
772
+ if (changed) setPending([...pendingRef.current.values()]);
773
+ }, [authoritativeSize, options.columnWidths, options.revision, options.rowHeights, pending]);
774
+ const submit = useCallback2((change) => {
775
+ const current = optionsRef.current;
776
+ if (!current.enabled || !current.commit || change.sheetId !== current.sheetId) return;
777
+ const scope = scopeRef.current;
778
+ const id = ++nextIdRef.current;
779
+ const key = keyOf(change);
780
+ const entry = { ...change, id, baseRevision: current.revision, settled: false };
781
+ pendingRef.current.set(key, entry);
782
+ setPending([...pendingRef.current.values()]);
783
+ errorsRef.current.delete(key);
784
+ setErrors([...errorsRef.current.values()]);
785
+ current.onStart?.();
786
+ let asynchronous = false;
787
+ const settle = (failed, cause) => {
788
+ if (!mountedRef.current || scopeRef.current !== scope) return;
789
+ if (asynchronous) setInFlightCount((count) => Math.max(0, count - 1));
790
+ const latest = pendingRef.current.get(key);
791
+ if (latest?.id !== id) return;
792
+ if (failed) {
793
+ pendingRef.current.delete(key);
794
+ const failure = cause instanceof Error ? cause : new Error(String(cause));
795
+ errorsRef.current.set(key, {
796
+ key,
797
+ message: failure.message || "Spreadsheet resize failed",
798
+ retry: () => {
799
+ if (!mountedRef.current || scopeRef.current !== scope) return;
800
+ submit(change);
801
+ }
802
+ });
803
+ setErrors([...errorsRef.current.values()]);
804
+ optionsRef.current.onCommandError?.(failure);
805
+ } else {
806
+ pendingRef.current.set(key, {
807
+ ...entry,
808
+ baseRevision: optionsRef.current.revision,
809
+ settled: true
810
+ });
811
+ }
812
+ setPending([...pendingRef.current.values()]);
813
+ };
814
+ try {
815
+ const result = current.commit(change);
816
+ if (result && typeof result.then === "function") {
817
+ asynchronous = true;
818
+ setInFlightCount((count) => count + 1);
819
+ void Promise.resolve(result).then(
820
+ () => settle(false),
821
+ (cause) => settle(true, cause)
822
+ );
823
+ } else {
824
+ settle(false);
825
+ }
826
+ } catch (cause) {
827
+ settle(true, cause);
828
+ }
829
+ }, []);
830
+ const update = useCallback2((next) => {
831
+ activeRef.current = next;
832
+ if (frameRef.current !== null) return;
833
+ if (typeof globalThis.requestAnimationFrame !== "function") {
834
+ setGesture(next);
835
+ return;
836
+ }
837
+ frameRef.current = globalThis.requestAnimationFrame(() => {
838
+ frameRef.current = null;
839
+ if (mountedRef.current) setGesture(activeRef.current);
840
+ });
841
+ }, []);
842
+ const finish = useCallback2(() => {
843
+ const active = activeRef.current;
844
+ cancel();
845
+ if (!active || active.size === active.startSize) return;
846
+ submit({ sheetId: active.sheetId, axis: active.axis, index: active.index, size: active.size });
847
+ }, [cancel, submit]);
848
+ const begin = useCallback2(
849
+ (axis, index, pointerId, position) => {
850
+ const current = optionsRef.current;
851
+ if (!current.enabled || !current.commit) return;
852
+ const existing = pendingRef.current.get(keyOf({ axis, index }));
853
+ const size = existing?.size ?? authoritativeSize(axis, index);
854
+ cancel();
855
+ const next = {
856
+ sheetId: current.sheetId,
857
+ axis,
858
+ index,
859
+ size,
860
+ startSize: size,
861
+ startPosition: position,
862
+ pointerId
863
+ };
864
+ activeRef.current = next;
865
+ setGesture(next);
866
+ current.onStart?.();
867
+ },
868
+ [authoritativeSize, cancel]
869
+ );
870
+ const handleProps = useCallback2(
871
+ (axis, index) => ({
872
+ onPointerDown(event) {
873
+ if (event.button !== 0 || event.isPrimary === false) return;
874
+ event.preventDefault();
875
+ event.stopPropagation();
876
+ event.currentTarget.focus({ preventScroll: true });
877
+ begin(axis, index, event.pointerId, axis === "column" ? event.clientX : event.clientY);
878
+ event.currentTarget.setPointerCapture?.(event.pointerId);
879
+ },
880
+ onPointerMove(event) {
881
+ const active = activeRef.current;
882
+ if (!active || active.pointerId !== event.pointerId || active.axis !== axis || active.index !== index)
883
+ return;
884
+ event.preventDefault();
885
+ event.stopPropagation();
886
+ const position = axis === "column" ? event.clientX : event.clientY;
887
+ update({
888
+ ...active,
889
+ size: boundedSize(active.startSize + position - active.startPosition)
890
+ });
891
+ },
892
+ onPointerUp(event) {
893
+ const active = activeRef.current;
894
+ if (!active || active.pointerId !== event.pointerId || active.axis !== axis || active.index !== index)
895
+ return;
896
+ event.preventDefault();
897
+ event.stopPropagation();
898
+ const position = axis === "column" ? event.clientX : event.clientY;
899
+ activeRef.current = {
900
+ ...active,
901
+ size: boundedSize(active.startSize + position - active.startPosition)
902
+ };
903
+ finish();
904
+ if (event.currentTarget.hasPointerCapture?.(event.pointerId)) {
905
+ event.currentTarget.releasePointerCapture?.(event.pointerId);
906
+ }
907
+ },
908
+ onPointerCancel(event) {
909
+ const active = activeRef.current;
910
+ if (active?.pointerId === event.pointerId && active.axis === axis && active.index === index)
911
+ cancel();
912
+ event.stopPropagation();
913
+ },
914
+ onLostPointerCapture(event) {
915
+ const active = activeRef.current;
916
+ if (active?.pointerId === event.pointerId && active.axis === axis && active.index === index)
917
+ cancel();
918
+ },
919
+ onKeyDown(event) {
920
+ event.stopPropagation();
921
+ if (event.key === "Escape") {
922
+ event.preventDefault();
923
+ cancel();
924
+ return;
925
+ }
926
+ if (event.key === "Enter") {
927
+ event.preventDefault();
928
+ finish();
929
+ return;
930
+ }
931
+ const negative = axis === "column" ? "ArrowLeft" : "ArrowUp";
932
+ const positive = axis === "column" ? "ArrowRight" : "ArrowDown";
933
+ if (event.key !== negative && event.key !== positive && event.key !== "Home") return;
934
+ event.preventDefault();
935
+ if (activeRef.current?.pointerId !== null || activeRef.current.axis !== axis || activeRef.current.index !== index) {
936
+ begin(axis, index, null, 0);
937
+ }
938
+ const active = activeRef.current;
939
+ if (!active) return;
940
+ const current = optionsRef.current;
941
+ const size = event.key === "Home" ? axis === "row" ? current.defaultRowHeight : current.defaultColumnWidth : active.size + (event.key === negative ? -1 : 1) * (event.shiftKey ? 1 : 8);
942
+ update({ ...active, size: boundedSize(size) });
943
+ },
944
+ onKeyUp(event) {
945
+ event.stopPropagation();
946
+ const active = activeRef.current;
947
+ if (active?.axis === axis && active.index === index && (event.key === "Home" || event.key.startsWith("Arrow")))
948
+ finish();
949
+ },
950
+ onBlur() {
951
+ const active = activeRef.current;
952
+ if (active?.pointerId === null && active.axis === axis && active.index === index) finish();
953
+ }
954
+ }),
955
+ [begin, cancel, finish, update]
956
+ );
957
+ const pendingRows = useMemo(() => pending.filter((entry) => entry.axis === "row"), [pending]);
958
+ const pendingColumns = useMemo(
959
+ () => pending.filter((entry) => entry.axis === "column"),
960
+ [pending]
961
+ );
962
+ const rowGesture = gesture?.axis === "row" ? gesture : null;
963
+ const columnGesture = gesture?.axis === "column" ? gesture : null;
964
+ const rowHeights = useMemo(
965
+ () => previewDimensions(options.rowHeights, pendingRows, rowGesture),
966
+ [options.rowHeights, pendingRows, rowGesture]
967
+ );
968
+ const columnWidths = useMemo(
969
+ () => previewDimensions(options.columnWidths, pendingColumns, columnGesture),
970
+ [options.columnWidths, pendingColumns, columnGesture]
971
+ );
972
+ const previewKey = [
973
+ ...pending.map((entry) => `${entry.axis}:${entry.index}:${entry.size}`),
974
+ ...gesture ? [`${gesture.axis}:${gesture.index}:${gesture.size}`] : []
975
+ ].join(";");
976
+ return {
977
+ rowHeights,
978
+ columnWidths,
979
+ previewKey,
980
+ handleProps,
981
+ pendingCount: inFlightCount,
982
+ error: errors[0] ? { message: errors[0].message, retry: options.enabled ? errors[0].retry : void 0 } : null,
983
+ clearError
984
+ };
985
+ }
986
+ function previewDimensions(entries, pending, gesture) {
987
+ if (!pending.length && !gesture) return entries;
988
+ const projected = new Map(entries);
989
+ for (const entry of pending) projected.set(entry.index, entry.size);
990
+ if (gesture) projected.set(gesture.index, gesture.size);
991
+ return [...projected.entries()];
992
+ }
993
+ function SpreadsheetResizeHandle({
994
+ axis,
995
+ label,
996
+ size,
997
+ ...handlers
998
+ }) {
999
+ return /* @__PURE__ */ jsx(
1000
+ "div",
1001
+ {
1002
+ ...handlers,
1003
+ role: "separator",
1004
+ tabIndex: 0,
1005
+ "aria-label": label,
1006
+ "aria-orientation": axis === "column" ? "vertical" : "horizontal",
1007
+ "aria-valuemin": MIN_SIZE,
1008
+ "aria-valuemax": MAX_SIZE,
1009
+ "aria-valuenow": size,
1010
+ "aria-valuetext": `${size} pixels`,
1011
+ "data-og-resize-axis": axis,
1012
+ style: { [axis === "column" ? "right" : "bottom"]: "calc(var(--spacing) * -1)" },
1013
+ className: cn(
1014
+ "pointer-events-auto absolute z-40 touch-none outline-hidden hover:bg-og-accent/20 focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-og-accent",
1015
+ axis === "column" ? "top-0 h-full w-2 cursor-col-resize" : "left-0 h-2 w-full cursor-row-resize"
1016
+ )
1017
+ }
1018
+ );
1019
+ }
1020
+
545
1021
  // src/components/artifacts/spreadsheet-grid.tsx
546
- import { jsx, jsxs } from "react/jsx-runtime";
1022
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
547
1023
  var MAX_ROWS = 1048576;
548
1024
  var MAX_COLUMNS = 16384;
549
1025
  var ROW_HEADER_WIDTH = 48;
@@ -556,7 +1032,8 @@ var MAX_MOUNTED_AXIS_ITEMS = 512;
556
1032
  var MAX_MOUNTED_GRID_CELLS = 2048;
557
1033
  var MAX_CLIPBOARD_INPUT_BYTES = 4 * 1024 * 1024;
558
1034
  var MAX_CLIPBOARD_CELLS = 65536;
559
- var useClientLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
1035
+ var EMPTY_DIMENSIONS = [];
1036
+ var useClientLayoutEffect = typeof window === "undefined" ? useEffect3 : useLayoutEffect;
560
1037
  function boundedInteger(value, fallback, max) {
561
1038
  if (value === void 0) return fallback;
562
1039
  if (!Number.isFinite(value)) return fallback;
@@ -795,12 +1272,6 @@ function isCellSelected(selection, row, col) {
795
1272
  const normalized = normalizeSelection(selection);
796
1273
  return row >= normalized.top && row <= normalized.bottom && col >= normalized.left && col <= normalized.right;
797
1274
  }
798
- function displayValue2(value) {
799
- if (value === null || value === void 0) return "";
800
- if (value instanceof Date) return Number.isNaN(value.getTime()) ? "" : value.toLocaleDateString();
801
- if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
802
- return String(value);
803
- }
804
1275
  function parseCellInput(input) {
805
1276
  if (input === "") return null;
806
1277
  const normalized = input.trim();
@@ -909,7 +1380,7 @@ function spreadsheetCanvasTheme(element) {
909
1380
  const border = computedToken(style, "--og-color-border", "#d1d5db");
910
1381
  const foreground = style.color || computedToken(style, "--og-color-fg", "#111827");
911
1382
  const mutedForeground = computedToken(style, "--og-color-fg-muted", "#6b7280");
912
- const accent = computedToken(style, "--og-color-accent", "#3b82f6");
1383
+ const accent = computedToken(style, "--og-color-accent", "#545454");
913
1384
  const error = computedToken(style, "--og-color-status-failed", "#dc2626");
914
1385
  const fontFamily = style.fontFamily || computedToken(
915
1386
  style,
@@ -944,11 +1415,11 @@ function spreadsheetCanvasTheme(element) {
944
1415
  };
945
1416
  }
946
1417
  function useWorkbookViewState(workbook) {
947
- const [view, setView] = useState(() => ({
1418
+ const [view, setView] = useState3(() => ({
948
1419
  revision: workbook.revision,
949
1420
  dimensionRevision: 0
950
1421
  }));
951
- useEffect(() => {
1422
+ useEffect3(() => {
952
1423
  setView(
953
1424
  (current) => current.revision === workbook.revision ? current : { revision: workbook.revision, dimensionRevision: current.dimensionRevision + 1 }
954
1425
  );
@@ -985,20 +1456,20 @@ function SpreadsheetArtifactSurface({
985
1456
  return availableSheets[0];
986
1457
  }
987
1458
  })();
988
- const [activeSheetId, setActiveSheetId] = useState(initial?.id ?? null);
1459
+ const [activeSheetId, setActiveSheetId] = useState3(initial?.id ?? null);
989
1460
  const activeSheet = availableSheets.find((sheet) => sheet.id === activeSheetId) ?? availableSheets[0] ?? null;
990
- useEffect(() => {
1461
+ useEffect3(() => {
991
1462
  if (!activeSheet && activeSheetId !== null) setActiveSheetId(null);
992
1463
  else if (activeSheet && activeSheet.id !== activeSheetId) setActiveSheetId(activeSheet.id);
993
1464
  }, [activeSheet, activeSheetId, revision]);
994
- const selectSheet = useCallback(
1465
+ const selectSheet = useCallback3(
995
1466
  (sheet) => {
996
1467
  workbook.worksheets.setActiveWorksheet(sheet);
997
1468
  setActiveSheetId(sheet.id);
998
1469
  },
999
1470
  [workbook]
1000
1471
  );
1001
- const addSheet = useCallback(() => {
1472
+ const addSheet = useCallback3(() => {
1002
1473
  const sheet = workbook.worksheets.add(nextAvailableSheetName(workbook));
1003
1474
  selectSheet(sheet);
1004
1475
  }, [selectSheet, workbook]);
@@ -1009,7 +1480,7 @@ function SpreadsheetArtifactSurface({
1009
1480
  role: "tablist",
1010
1481
  "aria-label": "Worksheets",
1011
1482
  children: [
1012
- availableSheets.map((sheet) => /* @__PURE__ */ jsx(
1483
+ availableSheets.map((sheet) => /* @__PURE__ */ jsx2(
1013
1484
  "button",
1014
1485
  {
1015
1486
  type: "button",
@@ -1024,20 +1495,20 @@ function SpreadsheetArtifactSurface({
1024
1495
  },
1025
1496
  sheet.id
1026
1497
  )),
1027
- !readOnly && allowAddSheet ? /* @__PURE__ */ jsx(
1498
+ !readOnly && allowAddSheet ? /* @__PURE__ */ jsx2(
1028
1499
  "button",
1029
1500
  {
1030
1501
  type: "button",
1031
1502
  onClick: addSheet,
1032
1503
  "aria-label": "Add worksheet",
1033
1504
  className: "grid size-7 shrink-0 place-items-center rounded-og-sm text-og-fg-muted hover:bg-og-surface-3 hover:text-og-fg [&>svg]:size-3.5",
1034
- children: /* @__PURE__ */ jsx(PlusIcon, {})
1505
+ children: /* @__PURE__ */ jsx2(PlusIcon, {})
1035
1506
  }
1036
1507
  ) : null
1037
1508
  ]
1038
1509
  }
1039
1510
  );
1040
- return /* @__PURE__ */ jsx(
1511
+ return /* @__PURE__ */ jsx2(
1041
1512
  ArtifactSurface,
1042
1513
  {
1043
1514
  modality: "spreadsheet",
@@ -1045,7 +1516,7 @@ function SpreadsheetArtifactSurface({
1045
1516
  subtitle: subtitle ?? (activeSheet ? `${availableSheets.length} sheet${availableSheets.length === 1 ? "" : "s"}` : "Empty workbook"),
1046
1517
  actions,
1047
1518
  footer,
1048
- children: activeSheet ? /* @__PURE__ */ jsx(
1519
+ children: activeSheet ? /* @__PURE__ */ jsx2(
1049
1520
  SpreadsheetGrid,
1050
1521
  {
1051
1522
  ...gridProps,
@@ -1054,19 +1525,19 @@ function SpreadsheetArtifactSurface({
1054
1525
  readOnly
1055
1526
  },
1056
1527
  activeSheet.id
1057
- ) : /* @__PURE__ */ jsx(
1528
+ ) : /* @__PURE__ */ jsx2(
1058
1529
  "div",
1059
1530
  {
1060
1531
  className: "grid h-full place-items-center bg-og-bg p-6 text-center",
1061
1532
  style: { minHeight: 224 },
1062
1533
  children: /* @__PURE__ */ jsxs("div", { children: [
1063
- /* @__PURE__ */ jsx("p", { className: "text-og-base font-medium text-og-fg", children: "This workbook has no worksheets." }),
1064
- !readOnly && allowAddSheet ? /* @__PURE__ */ jsx(
1534
+ /* @__PURE__ */ jsx2("p", { className: "text-og-base font-medium text-og-fg", children: "This workbook has no worksheets." }),
1535
+ !readOnly && allowAddSheet ? /* @__PURE__ */ jsx2(
1065
1536
  "button",
1066
1537
  {
1067
1538
  type: "button",
1068
1539
  onClick: addSheet,
1069
- className: "mt-3 rounded-og-sm bg-og-accent-deep px-3 py-1.5 text-og-sm font-medium text-og-accent-fg",
1540
+ className: "mt-3 rounded-og-sm border border-og-primary-border bg-og-primary text-og-primary-fg px-3 py-1.5 text-og-sm font-medium hover:bg-og-primary-hover",
1070
1541
  children: "Add worksheet"
1071
1542
  }
1072
1543
  ) : null
@@ -1086,12 +1557,13 @@ function SpreadsheetGrid({
1086
1557
  overscanColumns = 2,
1087
1558
  onSelectionChange,
1088
1559
  onCommit,
1560
+ onResize,
1089
1561
  onViewportChange,
1090
1562
  className
1091
1563
  }) {
1092
1564
  const { revision, dimensionRevision } = useWorkbookViewState(workbook);
1093
1565
  const boundedProjection = requestedRowCount !== void 0 || requestedColumnCount !== void 0;
1094
- const usedRange = useMemo(() => {
1566
+ const usedRange = useMemo2(() => {
1095
1567
  void revision;
1096
1568
  return boundedProjection ? worksheet.usedRangeAddress() : null;
1097
1569
  }, [boundedProjection, revision, worksheet]);
@@ -1111,15 +1583,15 @@ function SpreadsheetGrid({
1111
1583
  MAX_COLUMNS,
1112
1584
  MAX_COLUMNS
1113
1585
  );
1114
- const rowHeights = useMemo(() => {
1586
+ const rowHeights = useMemo2(() => {
1115
1587
  void dimensionRevision;
1116
1588
  return [...worksheet.rowHeightEntries()];
1117
1589
  }, [dimensionRevision, worksheet]);
1118
- const columnWidths = useMemo(() => {
1590
+ const columnWidths = useMemo2(() => {
1119
1591
  void dimensionRevision;
1120
1592
  return [...worksheet.columnWidthEntries()];
1121
1593
  }, [dimensionRevision, worksheet]);
1122
- const projection = useMemo(() => {
1594
+ const projection = useMemo2(() => {
1123
1595
  void dimensionRevision;
1124
1596
  const cells = new SparseSpreadsheetCellIndex(
1125
1597
  function* projectedCells() {
@@ -1153,7 +1625,7 @@ function SpreadsheetGrid({
1153
1625
  const data = worksheet.cellData(row, col);
1154
1626
  return {
1155
1627
  value: data.formula ? workbook.valueAt(worksheet, { row, col }) : data.value,
1156
- input: data.formula ?? displayValue2(data.value),
1628
+ input: data.formula ?? spreadsheetCellEditSource(data.value),
1157
1629
  format: data.format
1158
1630
  };
1159
1631
  }
@@ -1169,7 +1641,7 @@ function SpreadsheetGrid({
1169
1641
  workbook,
1170
1642
  worksheet
1171
1643
  ]);
1172
- const commit = useCallback(
1644
+ const commit = useCallback3(
1173
1645
  (next) => {
1174
1646
  const target = worksheet.getCell(next.cell.row, next.cell.col);
1175
1647
  if (next.kind === "formula") target.formulas = [[next.input]];
@@ -1178,7 +1650,7 @@ function SpreadsheetGrid({
1178
1650
  },
1179
1651
  [onCommit, worksheet]
1180
1652
  );
1181
- const commitRange = useCallback(
1653
+ const commitRange = useCallback3(
1182
1654
  (next) => {
1183
1655
  if (next.rows * next.columns !== next.inputs.length) {
1184
1656
  throw new Error("Spreadsheet paste shape is invalid");
@@ -1199,7 +1671,7 @@ function SpreadsheetGrid({
1199
1671
  },
1200
1672
  [workbook, worksheet]
1201
1673
  );
1202
- const clear = useCallback(
1674
+ const clear = useCallback3(
1203
1675
  (next) => {
1204
1676
  const normalized = normalizeSelection(next);
1205
1677
  worksheet.getRangeByIndexes(
@@ -1211,7 +1683,15 @@ function SpreadsheetGrid({
1211
1683
  },
1212
1684
  [worksheet]
1213
1685
  );
1214
- return /* @__PURE__ */ jsx(
1686
+ const resize = useCallback3(
1687
+ (change) => {
1688
+ if (change.axis === "column") worksheet.setColumnWidth(change.index, change.size);
1689
+ else worksheet.setRowHeight(change.index, change.size);
1690
+ onResize?.(change);
1691
+ },
1692
+ [onResize, worksheet]
1693
+ );
1694
+ return /* @__PURE__ */ jsx2(
1215
1695
  SpreadsheetProjectionGrid,
1216
1696
  {
1217
1697
  projection,
@@ -1222,6 +1702,7 @@ function SpreadsheetGrid({
1222
1702
  commit,
1223
1703
  commitRange,
1224
1704
  clear,
1705
+ resize,
1225
1706
  onViewportChange,
1226
1707
  className
1227
1708
  }
@@ -1236,65 +1717,117 @@ function SpreadsheetProjectionGrid({
1236
1717
  commit,
1237
1718
  commitRange,
1238
1719
  clear,
1720
+ resize,
1721
+ pendingTransactions = 0,
1722
+ syncStatus,
1723
+ syncError,
1239
1724
  onCommandError,
1240
1725
  onViewportChange,
1241
1726
  className
1242
1727
  }) {
1243
1728
  const { revision, rowCount, columnCount } = projection;
1244
- const dimensionRevision = projection.dimensionRevision ?? 0;
1245
1729
  const editable = !readOnly && commit !== void 0;
1246
- const rows = useMemo(() => {
1247
- void dimensionRevision;
1248
- return buildAxis(rowCount, projection.defaultRowHeight ?? 24, projection.rowHeights ?? []);
1249
- }, [dimensionRevision, projection.defaultRowHeight, projection.rowHeights, rowCount]);
1250
- const columns = useMemo(() => {
1251
- void dimensionRevision;
1252
- return buildAxis(
1253
- columnCount,
1254
- projection.defaultColumnWidth ?? 96,
1255
- projection.columnWidths ?? []
1256
- );
1257
- }, [columnCount, dimensionRevision, projection.columnWidths, projection.defaultColumnWidth]);
1258
- const canvasRows = useMemo(() => canvasAxis(rows), [rows]);
1259
- const canvasColumns = useMemo(() => canvasAxis(columns), [columns]);
1260
- const [selection, setSelection] = useState(() => ({
1730
+ const commandQueue = useSpreadsheetCommandQueue({
1731
+ scopeKey: `${projection.sheetId}:${projection.generationId ?? "none"}`,
1732
+ enabled: editable,
1733
+ onCommandError
1734
+ });
1735
+ const [commandFailure, setCommandFailure] = useState3(null);
1736
+ const clearPreflightFailure = commandQueue.clearPreflightFailure;
1737
+ const clearCommandFailure = useCallback3(() => {
1738
+ setCommandFailure(null);
1739
+ clearPreflightFailure();
1740
+ }, [clearPreflightFailure]);
1741
+ const resizing = useSpreadsheetResizing({
1742
+ sheetId: projection.sheetId,
1743
+ generationId: projection.generationId,
1744
+ revision: projection.dimensionRevision ?? revision,
1745
+ rowHeights: projection.rowHeights ?? EMPTY_DIMENSIONS,
1746
+ columnWidths: projection.columnWidths ?? EMPTY_DIMENSIONS,
1747
+ defaultRowHeight: projection.defaultRowHeight ?? 24,
1748
+ defaultColumnWidth: projection.defaultColumnWidth ?? 96,
1749
+ enabled: !readOnly && resize !== void 0,
1750
+ commit: resize,
1751
+ onCommandError,
1752
+ onStart: clearCommandFailure
1753
+ });
1754
+ const dimensionRevision = `${projection.dimensionRevision ?? 0}:${resizing.previewKey}`;
1755
+ const rows = useMemo2(() => {
1756
+ return buildAxis(rowCount, projection.defaultRowHeight ?? 24, resizing.rowHeights);
1757
+ }, [projection.defaultRowHeight, resizing.rowHeights, rowCount]);
1758
+ const columns = useMemo2(() => {
1759
+ return buildAxis(columnCount, projection.defaultColumnWidth ?? 96, resizing.columnWidths);
1760
+ }, [columnCount, resizing.columnWidths, projection.defaultColumnWidth]);
1761
+ const canvasRows = useMemo2(() => canvasAxis(rows), [rows]);
1762
+ const canvasColumns = useMemo2(() => canvasAxis(columns), [columns]);
1763
+ const [selection, setSelection] = useState3(() => ({
1261
1764
  sheetId: projection.sheetId,
1262
1765
  anchor: { row: 0, col: 0 },
1263
1766
  focus: { row: 0, col: 0 }
1264
1767
  }));
1265
- const [editMode, setEditMode] = useState(null);
1266
- const [draft, setDraft] = useState(
1768
+ const [editMode, setEditMode] = useState3(null);
1769
+ const [draft, setDraft] = useState3(
1267
1770
  () => projection.readCell(selection.focus.row, selection.focus.col)?.input ?? ""
1268
1771
  );
1269
- const [pendingCommands, setPendingCommands] = useState(0);
1270
- const [commandFailure, setCommandFailure] = useState(null);
1271
- const [viewport, setViewport] = useState({
1772
+ const visibleCommandFailure = resizing.error ?? commandQueue.error ?? commandFailure ?? (syncError ? { message: syncError, retry: void 0 } : null);
1773
+ const pendingCommandCount = commandQueue.pendingCount + resizing.pendingCount + pendingTransactions;
1774
+ const visibleSyncStatus = pendingCommandCount > 0 && (!syncStatus || syncStatus === "Saved" || syncStatus === "Read only") ? "Saving\u2026" : syncStatus;
1775
+ const runQueuedCommand = commandQueue.run;
1776
+ const [viewport, setViewport] = useState3({
1272
1777
  width: FALLBACK_VIEWPORT_WIDTH,
1273
1778
  height: FALLBACK_VIEWPORT_HEIGHT,
1274
1779
  scrollLeft: 0,
1275
1780
  scrollTop: 0,
1276
1781
  devicePixelRatio: 1
1277
1782
  });
1278
- const [canvasReady, setCanvasReady] = useState(false);
1279
- const [canvasEpoch, setCanvasEpoch] = useState(0);
1280
- const viewportRef = useRef(null);
1281
- const canvasRef = useRef(null);
1282
- const editorRef = useRef(null);
1283
- const selectionRef = useRef(selection);
1284
- const selectingRef = useRef(null);
1285
- const committingRef = useRef(false);
1286
- const composingRef = useRef(false);
1287
- const commitAfterCompositionRef = useRef(false);
1288
- const selectDraftOnFocusRef = useRef(true);
1289
- const initialDraftRef = useRef(draft);
1290
- const optimisticInputRef = useRef(null);
1291
- const mountedRef = useRef(true);
1292
- const commandScopeRef = useRef(0);
1293
- const latestCommandRef = useRef(0);
1294
- const canvasRendererRef = useRef(null);
1783
+ const [canvasReady, setCanvasReady] = useState3(false);
1784
+ const [canvasEpoch, setCanvasEpoch] = useState3(0);
1785
+ const viewportRef = useRef3(null);
1786
+ const canvasRef = useRef3(null);
1787
+ const editorRef = useRef3(null);
1788
+ const selectionRef = useRef3(selection);
1789
+ const selectingRef = useRef3(null);
1790
+ const committingRef = useRef3(false);
1791
+ const composingRef = useRef3(false);
1792
+ const commitAfterCompositionRef = useRef3(false);
1793
+ const selectDraftOnFocusRef = useRef3(true);
1794
+ const initialDraftRef = useRef3(draft);
1795
+ const optimisticInputsRef = useRef3(
1796
+ /* @__PURE__ */ new Map()
1797
+ );
1798
+ const [optimisticEpoch, setOptimisticEpoch] = useState3(0);
1799
+ const refreshOptimisticInputs = useCallback3(() => setOptimisticEpoch((value) => value + 1), []);
1800
+ const optimisticScope = `${projection.sheetId}:${projection.generationId ?? "none"}`;
1801
+ const optimisticScopeRef = useRef3(optimisticScope);
1802
+ if (optimisticScopeRef.current !== optimisticScope) {
1803
+ optimisticScopeRef.current = optimisticScope;
1804
+ optimisticInputsRef.current.clear();
1805
+ }
1806
+ const projectionRef = useRef3(projection);
1807
+ projectionRef.current = projection;
1808
+ const editModeRef = useRef3(editMode);
1809
+ editModeRef.current = editMode;
1810
+ const canvasRendererRef = useRef3(null);
1295
1811
  if (!canvasRendererRef.current) canvasRendererRef.current = new SpreadsheetCanvasRenderer();
1296
1812
  const reactId = useId().replaceAll(":", "");
1297
- const updateSelection = useCallback(
1813
+ const readEditInput = useCallback3(
1814
+ (cell) => optimisticInputsRef.current.get(`${cell.row}:${cell.col}`)?.input ?? projectionRef.current.readCell(cell.row, cell.col)?.input ?? "",
1815
+ []
1816
+ );
1817
+ const forgetOptimisticInputs = useCallback3(
1818
+ (target) => {
1819
+ let changed = false;
1820
+ for (const [key, entry] of optimisticInputsRef.current) {
1821
+ if (entry.row >= target.top && entry.row <= target.bottom && entry.col >= target.left && entry.col <= target.right) {
1822
+ optimisticInputsRef.current.delete(key);
1823
+ changed = true;
1824
+ }
1825
+ }
1826
+ if (changed) refreshOptimisticInputs();
1827
+ },
1828
+ [refreshOptimisticInputs]
1829
+ );
1830
+ const updateSelection = useCallback3(
1298
1831
  (next) => {
1299
1832
  selectionRef.current = next;
1300
1833
  setSelection(next);
@@ -1302,39 +1835,44 @@ function SpreadsheetProjectionGrid({
1302
1835
  },
1303
1836
  [onSelectionChange]
1304
1837
  );
1305
- useEffect(() => {
1838
+ useEffect3(() => {
1306
1839
  if (selection.sheetId === projection.sheetId) return;
1307
- commandScopeRef.current += 1;
1308
- latestCommandRef.current += 1;
1309
1840
  const next = {
1310
1841
  sheetId: projection.sheetId,
1311
1842
  anchor: { row: 0, col: 0 },
1312
1843
  focus: { row: 0, col: 0 }
1313
1844
  };
1314
- optimisticInputRef.current = null;
1315
- setPendingCommands(0);
1845
+ optimisticInputsRef.current.clear();
1316
1846
  setCommandFailure(null);
1317
1847
  setEditMode(null);
1318
1848
  updateSelection(next);
1319
1849
  }, [projection.sheetId, selection.sheetId, updateSelection]);
1320
- useEffect(() => {
1321
- mountedRef.current = true;
1322
- return () => {
1323
- mountedRef.current = false;
1324
- commandScopeRef.current += 1;
1325
- latestCommandRef.current += 1;
1326
- };
1327
- }, []);
1328
- useEffect(() => {
1329
- if (editMode !== null) return;
1330
- const optimistic = optimisticInputRef.current;
1331
- if (optimistic?.sheetId === projection.sheetId && optimistic.row === selection.focus.row && optimistic.col === selection.focus.col && optimistic.baseRevision === revision) {
1332
- setDraft(optimistic.input);
1333
- return;
1850
+ useEffect3(() => {
1851
+ optimisticInputsRef.current.clear();
1852
+ refreshOptimisticInputs();
1853
+ }, [projection.generationId, projection.sheetId, refreshOptimisticInputs]);
1854
+ useClientLayoutEffect(() => {
1855
+ let changed = false;
1856
+ for (const [key, optimistic] of optimisticInputsRef.current) {
1857
+ const coverage = projection.coverage;
1858
+ const covered = !coverage || optimistic.row >= coverage.rowStart && optimistic.row < coverage.rowEnd && optimistic.col >= coverage.columnStart && optimistic.col < coverage.columnEnd;
1859
+ if (!optimistic.pending && covered && (projection.readCell(optimistic.row, optimistic.col)?.input === optimistic.input || revision !== optimistic.baseRevision)) {
1860
+ optimisticInputsRef.current.delete(key);
1861
+ changed = true;
1862
+ }
1334
1863
  }
1335
- if (optimistic && optimistic.baseRevision !== revision) optimisticInputRef.current = null;
1336
- setDraft(projection.readCell(selection.focus.row, selection.focus.col)?.input ?? "");
1337
- }, [editMode, projection, revision, selection.focus.col, selection.focus.row]);
1864
+ if (changed) refreshOptimisticInputs();
1865
+ if (editMode === null) setDraft(readEditInput(selection.focus));
1866
+ }, [
1867
+ commandQueue.pendingCount,
1868
+ editMode,
1869
+ projection,
1870
+ readEditInput,
1871
+ revision,
1872
+ selection.focus,
1873
+ refreshOptimisticInputs,
1874
+ optimisticEpoch
1875
+ ]);
1338
1876
  useClientLayoutEffect(() => {
1339
1877
  const element = viewportRef.current;
1340
1878
  if (!element) return;
@@ -1355,10 +1893,10 @@ function SpreadsheetProjectionGrid({
1355
1893
  globalThis.removeEventListener?.("resize", measure);
1356
1894
  };
1357
1895
  }, []);
1358
- useEffect(() => {
1896
+ useEffect3(() => {
1359
1897
  return () => canvasRendererRef.current?.dispose();
1360
1898
  }, []);
1361
- useEffect(() => {
1899
+ useEffect3(() => {
1362
1900
  if (typeof document === "undefined") return;
1363
1901
  let active = true;
1364
1902
  void document.fonts?.ready.then(() => {
@@ -1383,7 +1921,7 @@ function SpreadsheetProjectionGrid({
1383
1921
  observer.disconnect();
1384
1922
  };
1385
1923
  }, []);
1386
- useEffect(() => {
1924
+ useEffect3(() => {
1387
1925
  if (editMode !== "cell") return;
1388
1926
  const editor = editorRef.current;
1389
1927
  editor?.focus();
@@ -1391,7 +1929,7 @@ function SpreadsheetProjectionGrid({
1391
1929
  if (selectDraftOnFocusRef.current) editor.select();
1392
1930
  else editor.setSelectionRange(editor.value.length, editor.value.length);
1393
1931
  }, [editMode]);
1394
- const ensureVisible = useCallback(
1932
+ const ensureVisible = useCallback3(
1395
1933
  (cell) => {
1396
1934
  const element = viewportRef.current;
1397
1935
  if (!element) return;
@@ -1428,7 +1966,7 @@ function SpreadsheetProjectionGrid({
1428
1966
  },
1429
1967
  [columns, rows]
1430
1968
  );
1431
- const moveSelection = useCallback(
1969
+ const moveSelection = useCallback3(
1432
1970
  (rowDelta, colDelta, extend) => {
1433
1971
  const focus = {
1434
1972
  row: Math.max(0, Math.min(rowCount - 1, selection.focus.row + rowDelta)),
@@ -1444,45 +1982,14 @@ function SpreadsheetProjectionGrid({
1444
1982
  },
1445
1983
  [columnCount, ensureVisible, projection.sheetId, rowCount, selection, updateSelection]
1446
1984
  );
1447
- const runCommand = useCallback(
1448
- (invoke, retry, rollback) => {
1449
- const commandId = latestCommandRef.current + 1;
1450
- latestCommandRef.current = commandId;
1451
- const scope = commandScopeRef.current;
1985
+ const runCommand = useCallback3(
1986
+ (invoke, retry, rollback, target, accepted) => {
1452
1987
  setCommandFailure(null);
1453
- const fail = (cause) => {
1454
- if (!mountedRef.current || commandScopeRef.current !== scope || latestCommandRef.current !== commandId) {
1455
- return;
1456
- }
1457
- const error = cause instanceof Error ? cause : new Error(String(cause));
1458
- rollback();
1459
- setCommandFailure({ message: error.message || "Spreadsheet change failed", retry });
1460
- onCommandError?.(error);
1461
- };
1462
- let result;
1463
- try {
1464
- result = invoke();
1465
- } catch (cause) {
1466
- fail(cause);
1467
- return;
1468
- }
1469
- if (!result || typeof result.then !== "function") return;
1470
- setPendingCommands((current) => current + 1);
1471
- void Promise.resolve(result).then(
1472
- () => {
1473
- if (!mountedRef.current || commandScopeRef.current !== scope) return;
1474
- setPendingCommands((current) => Math.max(0, current - 1));
1475
- },
1476
- (cause) => {
1477
- if (!mountedRef.current || commandScopeRef.current !== scope) return;
1478
- setPendingCommands((current) => Math.max(0, current - 1));
1479
- fail(cause);
1480
- }
1481
- );
1988
+ runQueuedCommand(invoke, retry, rollback, target, accepted);
1482
1989
  },
1483
- [onCommandError]
1990
+ [runQueuedCommand]
1484
1991
  );
1485
- const reportCommandFailure = useCallback(
1992
+ const reportCommandFailure = useCallback3(
1486
1993
  (cause) => {
1487
1994
  const error = cause instanceof Error ? cause : new Error(String(cause));
1488
1995
  setCommandFailure({ message: error.message || "Spreadsheet action failed" });
@@ -1490,7 +1997,7 @@ function SpreadsheetProjectionGrid({
1490
1997
  },
1491
1998
  [onCommandError]
1492
1999
  );
1493
- const commitDraft = useCallback(
2000
+ const commitDraft = useCallback3(
1494
2001
  (input = draft) => {
1495
2002
  if (committingRef.current) return;
1496
2003
  committingRef.current = true;
@@ -1516,21 +2023,41 @@ function SpreadsheetProjectionGrid({
1516
2023
  kind: input.startsWith("=") ? "formula" : "value"
1517
2024
  };
1518
2025
  const execute = () => {
1519
- optimisticInputRef.current = {
1520
- sheetId: projection.sheetId,
1521
- row: selection.focus.row,
1522
- col: selection.focus.col,
1523
- input,
1524
- baseRevision: revision
1525
- };
1526
- setDraft(input);
2026
+ const retryFocus = selectionRef.current.focus;
2027
+ if (editModeRef.current === null && retryFocus.row === next.cell.row && retryFocus.col === next.cell.col) {
2028
+ setDraft(input);
2029
+ }
2030
+ const key = `${next.cell.row}:${next.cell.col}`;
1527
2031
  runCommand(
1528
- () => commit(next),
2032
+ (commandId) => {
2033
+ optimisticInputsRef.current.set(key, {
2034
+ ...next.cell,
2035
+ input,
2036
+ baseRevision: revision,
2037
+ commandId,
2038
+ pending: true
2039
+ });
2040
+ refreshOptimisticInputs();
2041
+ return commit(next);
2042
+ },
1529
2043
  execute,
1530
- () => {
1531
- optimisticInputRef.current = null;
2044
+ (commandId) => {
2045
+ if (optimisticInputsRef.current.get(key)?.commandId !== commandId) return;
2046
+ optimisticInputsRef.current.delete(key);
2047
+ refreshOptimisticInputs();
1532
2048
  const current = selectionRef.current.focus;
1533
- setDraft(projection.readCell(current.row, current.col)?.input ?? "");
2049
+ if (editModeRef.current === null && current.row === next.cell.row && current.col === next.cell.col) {
2050
+ setDraft(readEditInput(current));
2051
+ }
2052
+ },
2053
+ { top: next.cell.row, bottom: next.cell.row, left: next.cell.col, right: next.cell.col },
2054
+ (commandId) => {
2055
+ const optimistic = optimisticInputsRef.current.get(key);
2056
+ if (optimistic?.commandId === commandId) {
2057
+ optimistic.pending = false;
2058
+ optimistic.baseRevision = projectionRef.current.revision;
2059
+ refreshOptimisticInputs();
2060
+ }
1534
2061
  }
1535
2062
  );
1536
2063
  };
@@ -1542,36 +2069,64 @@ function SpreadsheetProjectionGrid({
1542
2069
  committingRef.current = false;
1543
2070
  });
1544
2071
  },
1545
- [commit, draft, editable, projection, revision, runCommand, selection.focus]
2072
+ [
2073
+ commit,
2074
+ draft,
2075
+ editable,
2076
+ projection,
2077
+ readEditInput,
2078
+ revision,
2079
+ runCommand,
2080
+ selection.focus,
2081
+ refreshOptimisticInputs
2082
+ ]
1546
2083
  );
1547
- const clearSelection = useCallback(() => {
2084
+ const clearSelection = useCallback3(() => {
1548
2085
  if (!editable || !clear) return;
1549
2086
  const current = selection;
2087
+ const target = normalizeSelection(current);
1550
2088
  const execute = () => runCommand(
1551
- () => clear(current),
2089
+ () => {
2090
+ forgetOptimisticInputs(target);
2091
+ return clear(current);
2092
+ },
1552
2093
  execute,
1553
2094
  () => {
1554
- }
2095
+ },
2096
+ target
1555
2097
  );
1556
2098
  execute();
1557
- }, [clear, editable, runCommand, selection]);
1558
- const pasteClipboard = useCallback(
2099
+ }, [clear, editable, forgetOptimisticInputs, runCommand, selection]);
2100
+ const pasteClipboard = useCallback3(
1559
2101
  (event) => {
1560
2102
  if (!editable || editMode !== null) return;
1561
2103
  const clipboardText = event.clipboardData.getData("text/plain");
1562
2104
  if (!clipboardText && !event.clipboardData.types.includes("text/plain")) return;
1563
2105
  event.preventDefault();
2106
+ const previousSelection = selectionRef.current;
2107
+ const anchor = previousSelection.focus;
1564
2108
  const execute = () => {
1565
- const previousSelection = selectionRef.current;
1566
- const invoke = () => {
1567
- const parsed = parseSpreadsheetClipboard(clipboardText);
1568
- const anchor = previousSelection.focus;
1569
- if (anchor.row + parsed.rows > rowCount || anchor.col + parsed.columns > columnCount) {
2109
+ let prepared;
2110
+ let target;
2111
+ const prepare = () => {
2112
+ prepared = parseSpreadsheetClipboard(clipboardText);
2113
+ if (anchor.row + prepared.rows > rowCount || anchor.col + prepared.columns > columnCount) {
1570
2114
  throw new Error("Clipboard range does not fit in this worksheet");
1571
2115
  }
1572
- if (!commitRange && parsed.inputs.length !== 1) {
2116
+ if (!commitRange && prepared.inputs.length !== 1) {
1573
2117
  throw new Error("This spreadsheet adapter does not support rectangular paste");
1574
2118
  }
2119
+ target = {
2120
+ top: anchor.row,
2121
+ left: anchor.col,
2122
+ bottom: anchor.row + prepared.rows - 1,
2123
+ right: anchor.col + prepared.columns - 1
2124
+ };
2125
+ return target;
2126
+ };
2127
+ const invoke = () => {
2128
+ const parsed = prepared;
2129
+ forgetOptimisticInputs(target);
1575
2130
  const bottomRight = {
1576
2131
  row: anchor.row + parsed.rows - 1,
1577
2132
  col: anchor.col + parsed.columns - 1
@@ -1599,7 +2154,17 @@ function SpreadsheetProjectionGrid({
1599
2154
  kind: input.startsWith("=") ? "formula" : "value"
1600
2155
  });
1601
2156
  };
1602
- runCommand(invoke, execute, () => updateSelection(previousSelection));
2157
+ runCommand(
2158
+ invoke,
2159
+ execute,
2160
+ () => {
2161
+ const current = selectionRef.current;
2162
+ if (target && current.anchor.row === anchor.row && current.anchor.col === anchor.col && current.focus.row === target.bottom && current.focus.col === target.right) {
2163
+ updateSelection(previousSelection);
2164
+ }
2165
+ },
2166
+ prepare
2167
+ );
1603
2168
  };
1604
2169
  execute();
1605
2170
  },
@@ -1610,13 +2175,14 @@ function SpreadsheetProjectionGrid({
1610
2175
  editMode,
1611
2176
  editable,
1612
2177
  ensureVisible,
2178
+ forgetOptimisticInputs,
1613
2179
  projection.sheetId,
1614
2180
  rowCount,
1615
2181
  runCommand,
1616
2182
  updateSelection
1617
2183
  ]
1618
2184
  );
1619
- const copySelection = useCallback(
2185
+ const copySelection = useCallback3(
1620
2186
  (event) => {
1621
2187
  if (editMode !== null) return;
1622
2188
  const selected = normalizeSelection(selectionRef.current);
@@ -1647,19 +2213,19 @@ function SpreadsheetProjectionGrid({
1647
2213
  },
1648
2214
  [editMode, projection, reportCommandFailure]
1649
2215
  );
1650
- const beginEditing = useCallback(
2216
+ const beginEditing = useCallback3(
1651
2217
  (initial, cell = selectionRef.current.focus) => {
1652
2218
  if (!editable) return;
1653
2219
  ensureVisible(cell);
1654
- const current = projection.readCell(cell.row, cell.col)?.input ?? "";
2220
+ const current = readEditInput(cell);
1655
2221
  initialDraftRef.current = current;
1656
2222
  selectDraftOnFocusRef.current = initial === void 0;
1657
2223
  setDraft(initial ?? current);
1658
2224
  setEditMode("cell");
1659
2225
  },
1660
- [editable, ensureVisible, projection]
2226
+ [editable, ensureVisible, readEditInput]
1661
2227
  );
1662
- const onGridKeyDown = useCallback(
2228
+ const onGridKeyDown = useCallback3(
1663
2229
  (event) => {
1664
2230
  if (editMode !== null) return;
1665
2231
  if (event.nativeEvent.isComposing || event.nativeEvent.keyCode === 229) return;
@@ -1733,7 +2299,7 @@ function SpreadsheetProjectionGrid({
1733
2299
  projection.usedRange
1734
2300
  ]
1735
2301
  );
1736
- const onEditorKeyDown = useCallback(
2302
+ const onEditorKeyDown = useCallback3(
1737
2303
  (event) => {
1738
2304
  if (composingRef.current || event.nativeEvent.isComposing) return;
1739
2305
  if (event.key === "Enter") {
@@ -1742,7 +2308,7 @@ function SpreadsheetProjectionGrid({
1742
2308
  } else if (event.key === "Escape") {
1743
2309
  event.preventDefault();
1744
2310
  committingRef.current = true;
1745
- setDraft(projection.readCell(selection.focus.row, selection.focus.col)?.input ?? "");
2311
+ setDraft(readEditInput(selection.focus));
1746
2312
  setEditMode(null);
1747
2313
  viewportRef.current?.focus();
1748
2314
  queueMicrotask(() => {
@@ -1750,12 +2316,12 @@ function SpreadsheetProjectionGrid({
1750
2316
  });
1751
2317
  }
1752
2318
  },
1753
- [commitDraft, projection, selection.focus.col, selection.focus.row]
2319
+ [commitDraft, readEditInput, selection.focus]
1754
2320
  );
1755
- const onEditorCompositionStart = useCallback(() => {
2321
+ const onEditorCompositionStart = useCallback3(() => {
1756
2322
  composingRef.current = true;
1757
2323
  }, []);
1758
- const onEditorCompositionEnd = useCallback(
2324
+ const onEditorCompositionEnd = useCallback3(
1759
2325
  (input) => {
1760
2326
  composingRef.current = false;
1761
2327
  if (!commitAfterCompositionRef.current) return;
@@ -1764,7 +2330,7 @@ function SpreadsheetProjectionGrid({
1764
2330
  },
1765
2331
  [commitDraft]
1766
2332
  );
1767
- const commitEditorOnBlur = useCallback(
2333
+ const commitEditorOnBlur = useCallback3(
1768
2334
  (mode, input) => {
1769
2335
  if (editMode !== mode) return;
1770
2336
  if (composingRef.current) {
@@ -1775,7 +2341,7 @@ function SpreadsheetProjectionGrid({
1775
2341
  },
1776
2342
  [commitDraft, editMode]
1777
2343
  );
1778
- const selectCell = useCallback(
2344
+ const selectCell = useCallback3(
1779
2345
  (cell, extend) => {
1780
2346
  const current = selectionRef.current;
1781
2347
  const next = {
@@ -1789,7 +2355,7 @@ function SpreadsheetProjectionGrid({
1789
2355
  },
1790
2356
  [projection.sheetId, updateSelection]
1791
2357
  );
1792
- const hitTestCell = useCallback(
2358
+ const hitTestCell = useCallback3(
1793
2359
  (clientX, clientY) => {
1794
2360
  const element = viewportRef.current;
1795
2361
  if (!element) return null;
@@ -1815,7 +2381,7 @@ function SpreadsheetProjectionGrid({
1815
2381
  },
1816
2382
  [columnCount, columns, rowCount, rows]
1817
2383
  );
1818
- const onGridPointerDown = useCallback(
2384
+ const onGridPointerDown = useCallback3(
1819
2385
  (event) => {
1820
2386
  if (event.button !== 0) return;
1821
2387
  const cell = hitTestCell(event.clientX, event.clientY);
@@ -1834,7 +2400,7 @@ function SpreadsheetProjectionGrid({
1834
2400
  },
1835
2401
  [hitTestCell, projection.sheetId, updateSelection]
1836
2402
  );
1837
- const onGridPointerMove = useCallback(
2403
+ const onGridPointerMove = useCallback3(
1838
2404
  (event) => {
1839
2405
  const selecting = selectingRef.current;
1840
2406
  if (!selecting || selecting.pointerId !== event.pointerId) return;
@@ -1846,11 +2412,11 @@ function SpreadsheetProjectionGrid({
1846
2412
  },
1847
2413
  [hitTestCell, projection.sheetId, updateSelection]
1848
2414
  );
1849
- const stopPointerSelection = useCallback((pointerId) => {
2415
+ const stopPointerSelection = useCallback3((pointerId) => {
1850
2416
  if (pointerId !== void 0 && selectingRef.current?.pointerId !== pointerId) return;
1851
2417
  selectingRef.current = null;
1852
2418
  }, []);
1853
- useEffect(() => {
2419
+ useEffect3(() => {
1854
2420
  if (typeof window === "undefined") return;
1855
2421
  const stopSelecting = () => stopPointerSelection();
1856
2422
  window.addEventListener("pointerup", stopSelecting);
@@ -1906,7 +2472,7 @@ function SpreadsheetProjectionGrid({
1906
2472
  const activeCellVisible = selection.focus.row >= rowWindow.start && selection.focus.row < rowWindow.end && selection.focus.col >= columnWindow.start && selection.focus.col < columnWindow.end;
1907
2473
  const activeCellId = `${reactId}-cell-${selection.focus.row}-${selection.focus.col}`;
1908
2474
  const hiddenActiveValue = activeCellVisible ? null : projection.readCell(selection.focus.row, selection.focus.col)?.value;
1909
- useEffect(() => {
2475
+ useEffect3(() => {
1910
2476
  if (!onViewportChange) return;
1911
2477
  const next = {
1912
2478
  sheetId: projection.sheetId,
@@ -2016,11 +2582,11 @@ function SpreadsheetProjectionGrid({
2016
2582
  "div",
2017
2583
  {
2018
2584
  className: cn("relative flex h-full min-w-0 flex-col bg-og-bg", className),
2019
- "data-og-command-state": commandFailure ? "error" : pendingCommands > 0 ? "pending" : "idle",
2585
+ "data-og-command-state": visibleCommandFailure ? "error" : pendingCommandCount > 0 ? "pending" : "idle",
2020
2586
  style: { minHeight: 256 },
2021
2587
  children: [
2022
2588
  /* @__PURE__ */ jsxs("div", { className: "flex min-h-9 shrink-0 items-center border-b border-og-border bg-og-surface-1", children: [
2023
- /* @__PURE__ */ jsx(
2589
+ /* @__PURE__ */ jsx2(
2024
2590
  "output",
2025
2591
  {
2026
2592
  "aria-label": "Selected range",
@@ -2029,17 +2595,17 @@ function SpreadsheetProjectionGrid({
2029
2595
  children: selectionName(selection)
2030
2596
  }
2031
2597
  ),
2032
- /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "px-2 font-og-mono text-og-sm italic text-og-fg-subtle", children: "fx" }),
2033
- /* @__PURE__ */ jsx(
2598
+ /* @__PURE__ */ jsx2("span", { "aria-hidden": true, className: "px-2 font-og-mono text-og-sm italic text-og-fg-subtle", children: "fx" }),
2599
+ /* @__PURE__ */ jsx2(
2034
2600
  "input",
2035
2601
  {
2036
2602
  "aria-label": "Formula or value",
2037
2603
  readOnly: !editable,
2038
- "aria-invalid": commandFailure ? "true" : void 0,
2604
+ "aria-invalid": visibleCommandFailure ? "true" : void 0,
2039
2605
  value: draft,
2040
2606
  onFocus: () => {
2041
2607
  if (editable) {
2042
- const current = projection.readCell(selection.focus.row, selection.focus.col)?.input ?? "";
2608
+ const current = readEditInput(selection.focus);
2043
2609
  initialDraftRef.current = current;
2044
2610
  setDraft(current);
2045
2611
  setEditMode("formula");
@@ -2052,22 +2618,30 @@ function SpreadsheetProjectionGrid({
2052
2618
  onBlur: (event) => commitEditorOnBlur("formula", event.currentTarget.value),
2053
2619
  className: "h-8 min-w-0 flex-1 bg-transparent px-1 font-mono text-og-sm text-og-fg outline-hidden placeholder:text-og-fg-subtle"
2054
2620
  }
2055
- )
2621
+ ),
2622
+ visibleSyncStatus ? /* @__PURE__ */ jsx2(
2623
+ "output",
2624
+ {
2625
+ "aria-label": "Spreadsheet sync status",
2626
+ className: "shrink-0 px-2 text-og-xs text-og-fg-muted",
2627
+ children: visibleCommandFailure ? "Not saved" : visibleSyncStatus
2628
+ }
2629
+ ) : null
2056
2630
  ] }),
2057
- /* @__PURE__ */ jsx("div", { role: "status", "aria-live": "polite", className: "sr-only", children: commandFailure?.message ?? (pendingCommands > 0 ? "Saving spreadsheet changes" : "") }),
2058
- commandFailure ? /* @__PURE__ */ jsxs(
2631
+ /* @__PURE__ */ jsx2("div", { role: "status", "aria-live": "polite", className: "sr-only", children: visibleCommandFailure?.message ?? (pendingCommandCount > 0 ? "Saving spreadsheet changes" : "") }),
2632
+ visibleCommandFailure ? /* @__PURE__ */ jsxs(
2059
2633
  "div",
2060
2634
  {
2061
2635
  role: "alert",
2062
2636
  className: "absolute bottom-2 left-2 z-50 flex items-center gap-2 rounded-og-sm border border-og-status-failed/30 bg-og-surface-1/95 px-2 py-1 text-og-xs text-og-status-failed shadow-og-sm",
2063
2637
  style: { maxWidth: "calc(100% - 1rem)" },
2064
2638
  children: [
2065
- /* @__PURE__ */ jsx("span", { className: "truncate", children: commandFailure.message }),
2066
- commandFailure.retry ? /* @__PURE__ */ jsx(
2639
+ /* @__PURE__ */ jsx2("span", { className: "truncate", children: visibleCommandFailure.message }),
2640
+ visibleCommandFailure.retry ? /* @__PURE__ */ jsx2(
2067
2641
  "button",
2068
2642
  {
2069
2643
  type: "button",
2070
- onClick: commandFailure.retry,
2644
+ onClick: visibleCommandFailure.retry,
2071
2645
  className: "shrink-0 rounded-og-xs px-1.5 py-0.5 font-medium outline-hidden hover:bg-og-surface-3 focus-visible:ring-2 focus-visible:ring-og-accent",
2072
2646
  children: "Retry"
2073
2647
  }
@@ -2075,7 +2649,7 @@ function SpreadsheetProjectionGrid({
2075
2649
  ]
2076
2650
  }
2077
2651
  ) : null,
2078
- /* @__PURE__ */ jsx(
2652
+ /* @__PURE__ */ jsx2(
2079
2653
  "div",
2080
2654
  {
2081
2655
  ref: viewportRef,
@@ -2086,7 +2660,7 @@ function SpreadsheetProjectionGrid({
2086
2660
  "aria-colcount": columnCount,
2087
2661
  "aria-multiselectable": "true",
2088
2662
  "aria-readonly": !editable,
2089
- "aria-busy": pendingCommands > 0 ? "true" : void 0,
2663
+ "aria-busy": pendingCommandCount > 0 ? "true" : void 0,
2090
2664
  "aria-activedescendant": activeCellId,
2091
2665
  onKeyDown: onGridKeyDown,
2092
2666
  onCopy: copySelection,
@@ -2120,10 +2694,14 @@ function SpreadsheetProjectionGrid({
2120
2694
  className: "relative",
2121
2695
  style: {
2122
2696
  width: horizontalProjection.physicalTotal,
2123
- height: verticalProjection.physicalTotal
2697
+ height: verticalProjection.physicalTotal,
2698
+ // Centered boundary handles must not enlarge the bounded scroll
2699
+ // extent at the final row/column. Unlike hidden, clip does not
2700
+ // create another scroll container for the sticky headers.
2701
+ overflow: "clip"
2124
2702
  },
2125
2703
  children: [
2126
- /* @__PURE__ */ jsx(
2704
+ /* @__PURE__ */ jsx2(
2127
2705
  "canvas",
2128
2706
  {
2129
2707
  ref: canvasRef,
@@ -2138,7 +2716,7 @@ function SpreadsheetProjectionGrid({
2138
2716
  }
2139
2717
  }
2140
2718
  ),
2141
- /* @__PURE__ */ jsx(
2719
+ /* @__PURE__ */ jsx2(
2142
2720
  "div",
2143
2721
  {
2144
2722
  "aria-hidden": true,
@@ -2150,12 +2728,12 @@ function SpreadsheetProjectionGrid({
2150
2728
  }
2151
2729
  }
2152
2730
  ),
2153
- /* @__PURE__ */ jsx("div", { role: "row", className: "contents", children: columnLayout.map(({ col, left, width }) => /* @__PURE__ */ jsx(
2731
+ /* @__PURE__ */ jsx2("div", { role: "row", className: "contents", children: columnLayout.map(({ col, left, width }) => /* @__PURE__ */ jsxs(
2154
2732
  "div",
2155
2733
  {
2156
2734
  role: "columnheader",
2157
2735
  "aria-colindex": col + 1,
2158
- className: "sticky top-0 z-30 grid select-none place-items-center overflow-hidden border-b border-r border-og-border bg-og-surface-2 text-og-xs font-medium text-og-fg-muted",
2736
+ className: "pointer-events-none sticky top-0 z-30 grid select-none place-items-center border-b border-r border-og-border bg-og-surface-2 text-og-xs font-medium text-og-fg-muted",
2159
2737
  style: {
2160
2738
  position: "absolute",
2161
2739
  left,
@@ -2168,7 +2746,18 @@ function SpreadsheetProjectionGrid({
2168
2746
  color: "transparent"
2169
2747
  } : void 0
2170
2748
  },
2171
- children: columnName2(col)
2749
+ children: [
2750
+ /* @__PURE__ */ jsx2("span", { className: "max-w-full overflow-hidden", children: columnName2(col) }),
2751
+ !readOnly && resize ? /* @__PURE__ */ jsx2(
2752
+ SpreadsheetResizeHandle,
2753
+ {
2754
+ axis: "column",
2755
+ label: `Resize column ${columnName2(col)}`,
2756
+ size: width,
2757
+ ...resizing.handleProps("column", col)
2758
+ }
2759
+ ) : null
2760
+ ]
2172
2761
  },
2173
2762
  `header-${col}`
2174
2763
  )) }),
@@ -2185,11 +2774,11 @@ function SpreadsheetProjectionGrid({
2185
2774
  height
2186
2775
  },
2187
2776
  children: [
2188
- /* @__PURE__ */ jsx(
2777
+ /* @__PURE__ */ jsxs(
2189
2778
  "div",
2190
2779
  {
2191
2780
  role: "rowheader",
2192
- className: "sticky left-0 z-20 grid h-full select-none place-items-center border-b border-r border-og-border bg-og-surface-2 text-og-xs text-og-fg-muted",
2781
+ className: "pointer-events-none sticky left-0 z-20 grid h-full select-none place-items-center border-b border-r border-og-border bg-og-surface-2 text-og-xs text-og-fg-muted",
2193
2782
  style: {
2194
2783
  width: ROW_HEADER_WIDTH,
2195
2784
  ...canvasReady ? {
@@ -2198,7 +2787,18 @@ function SpreadsheetProjectionGrid({
2198
2787
  color: "transparent"
2199
2788
  } : void 0
2200
2789
  },
2201
- children: row + 1
2790
+ children: [
2791
+ row + 1,
2792
+ !readOnly && resize ? /* @__PURE__ */ jsx2(
2793
+ SpreadsheetResizeHandle,
2794
+ {
2795
+ axis: "row",
2796
+ label: `Resize row ${row + 1}`,
2797
+ size: height,
2798
+ ...resizing.handleProps("row", row)
2799
+ }
2800
+ ) : null
2801
+ ]
2202
2802
  }
2203
2803
  ),
2204
2804
  columnLayout.map(({ col, left, width }) => {
@@ -2210,34 +2810,41 @@ function SpreadsheetProjectionGrid({
2210
2810
  format: {}
2211
2811
  };
2212
2812
  const value = data.value;
2813
+ const optimistic = editable ? optimisticInputsRef.current.get(`${row}:${col}`) : void 0;
2814
+ const display = optimistic ? optimistic.input : formatSpreadsheetGeneralDisplay(value);
2213
2815
  const address = cellName({ row, col });
2214
2816
  const error = typeof value === "string" && value.startsWith("#");
2215
- return /* @__PURE__ */ jsx(
2817
+ return /* @__PURE__ */ jsx2(
2216
2818
  "div",
2217
2819
  {
2218
2820
  id: `${reactId}-cell-${row}-${col}`,
2219
2821
  role: "gridcell",
2220
2822
  "aria-colindex": col + 1,
2221
2823
  "aria-selected": selected,
2222
- "aria-label": `${address}${value === null ? "" : `, ${displayValue2(value)}`}`,
2824
+ "aria-label": `${address}${display ? `, ${display}` : ""}${optimistic ? optimistic.input.startsWith("=") ? ", pending formula, awaiting calculation" : ", pending edit" : ""}`,
2825
+ "data-og-pending-input": optimistic ? "true" : void 0,
2223
2826
  "data-og-cell": address,
2224
2827
  className: cn(
2225
2828
  "pointer-events-none absolute top-0 flex h-full min-w-0 overflow-hidden border-b border-r border-og-border px-1.5 text-og-fg",
2226
- !canvasReady && selected && !active && "bg-og-accent/10",
2227
- !canvasReady && active && "z-10 bg-og-accent/10 ring-2 ring-inset ring-og-accent",
2829
+ (!canvasReady || optimistic) && selected && !active && "bg-og-accent/10",
2830
+ (!canvasReady || optimistic) && active && "z-10 bg-og-accent/10 ring-2 ring-inset ring-og-accent",
2228
2831
  !canvasReady && error && "text-og-status-failed"
2229
2832
  ),
2230
2833
  style: {
2231
2834
  left,
2232
2835
  width,
2233
2836
  ...cellStyle(data.format),
2234
- ...canvasReady ? {
2837
+ ...canvasReady && !optimistic ? {
2235
2838
  background: "transparent",
2236
2839
  borderColor: "transparent",
2237
2840
  color: "transparent"
2841
+ } : void 0,
2842
+ ...optimistic ? {
2843
+ background: data.format.fill ?? "var(--og-color-surface-1)",
2844
+ zIndex: 10
2238
2845
  } : void 0
2239
2846
  },
2240
- children: active && editMode === "cell" ? /* @__PURE__ */ jsx(
2847
+ children: active && editMode === "cell" ? /* @__PURE__ */ jsx2(
2241
2848
  "input",
2242
2849
  {
2243
2850
  ref: editorRef,
@@ -2251,7 +2858,7 @@ function SpreadsheetProjectionGrid({
2251
2858
  onPointerDown: (event) => event.stopPropagation(),
2252
2859
  className: "pointer-events-auto absolute inset-0 size-full bg-og-surface-1 px-1.5 font-mono text-og-sm text-og-fg outline-hidden ring-2 ring-inset ring-og-accent"
2253
2860
  }
2254
- ) : /* @__PURE__ */ jsx("span", { className: "block min-w-0 overflow-hidden text-ellipsis", children: displayValue2(value) })
2861
+ ) : /* @__PURE__ */ jsx2("span", { className: "block min-w-0 overflow-hidden text-ellipsis", children: display })
2255
2862
  },
2256
2863
  col
2257
2864
  );
@@ -2261,14 +2868,14 @@ function SpreadsheetProjectionGrid({
2261
2868
  `row-${row}`
2262
2869
  );
2263
2870
  }),
2264
- !activeCellVisible ? /* @__PURE__ */ jsx("div", { role: "row", "aria-rowindex": selection.focus.row + 1, className: "sr-only", children: /* @__PURE__ */ jsx(
2871
+ !activeCellVisible ? /* @__PURE__ */ jsx2("div", { role: "row", "aria-rowindex": selection.focus.row + 1, className: "sr-only", children: /* @__PURE__ */ jsx2(
2265
2872
  "div",
2266
2873
  {
2267
2874
  id: activeCellId,
2268
2875
  role: "gridcell",
2269
2876
  "aria-colindex": selection.focus.col + 1,
2270
2877
  "aria-selected": "true",
2271
- "aria-label": `${cellName(selection.focus)}${hiddenActiveValue == null ? "" : `, ${displayValue2(hiddenActiveValue)}`}`
2878
+ "aria-label": `${cellName(selection.focus)}${hiddenActiveValue == null ? "" : `, ${formatSpreadsheetGeneralDisplay(hiddenActiveValue)}`}`
2272
2879
  }
2273
2880
  ) }) : null
2274
2881
  ]
@@ -2288,8 +2895,140 @@ import {
2288
2895
  spreadsheetSheetId
2289
2896
  } from "@opengeni/sdk/editable-artifacts";
2290
2897
  import { PlusIcon as PlusIcon2 } from "lucide-react";
2291
- import { useCallback as useCallback2, useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
2292
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
2898
+ import {
2899
+ useCallback as useCallback4,
2900
+ useEffect as useEffect5,
2901
+ useId as useId2,
2902
+ useLayoutEffect as useLayoutEffect2,
2903
+ useMemo as useMemo3,
2904
+ useRef as useRef5,
2905
+ useState as useState6
2906
+ } from "react";
2907
+
2908
+ // src/components/artifacts/spreadsheet-download.tsx
2909
+ import { DownloadIcon, LoaderCircleIcon } from "lucide-react";
2910
+ import { useEffect as useEffect4, useRef as useRef4, useState as useState5, useSyncExternalStore } from "react";
2911
+
2912
+ // src/components/artifacts/spreadsheet-submissions.tsx
2913
+ import { createContext, useContext, useState as useState4 } from "react";
2914
+ import { jsx as jsx3 } from "react/jsx-runtime";
2915
+ function createSubmissionQueue() {
2916
+ let pending = 0;
2917
+ const listeners = /* @__PURE__ */ new Set();
2918
+ const emit = () => {
2919
+ for (const listener of listeners) listener();
2920
+ };
2921
+ return {
2922
+ getPending: () => pending,
2923
+ subscribe: (listener) => {
2924
+ listeners.add(listener);
2925
+ return () => {
2926
+ listeners.delete(listener);
2927
+ };
2928
+ },
2929
+ async run(invoke) {
2930
+ pending++;
2931
+ emit();
2932
+ try {
2933
+ return await invoke();
2934
+ } finally {
2935
+ pending--;
2936
+ emit();
2937
+ }
2938
+ }
2939
+ };
2940
+ }
2941
+ var standaloneQueue = {
2942
+ getPending: () => 0,
2943
+ subscribe: (_listener) => () => {
2944
+ },
2945
+ run: (invoke) => invoke()
2946
+ };
2947
+ var SubmissionContext = createContext(null);
2948
+ function SpreadsheetSubmissionProvider({ children }) {
2949
+ const [queue] = useState4(createSubmissionQueue);
2950
+ return /* @__PURE__ */ jsx3(SubmissionContext.Provider, { value: queue, children });
2951
+ }
2952
+ function useSpreadsheetSubmissions() {
2953
+ return useContext(SubmissionContext) ?? standaloneQueue;
2954
+ }
2955
+
2956
+ // src/components/artifacts/spreadsheet-download.tsx
2957
+ import { Fragment, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
2958
+ function SpreadsheetDownloadButton({
2959
+ session,
2960
+ title,
2961
+ download
2962
+ }) {
2963
+ const view = useEditableArtifactView(session);
2964
+ const submissions = useSpreadsheetSubmissions();
2965
+ const submitting = useSyncExternalStore(
2966
+ submissions.subscribe,
2967
+ submissions.getPending,
2968
+ submissions.getPending
2969
+ );
2970
+ const active = useRef4(null);
2971
+ const [busy, setBusy] = useState5(false);
2972
+ const [error, setError] = useState5(false);
2973
+ const ready = view.state === "live" && submitting === 0 && view.pendingTransactions === 0 && view.blockedPending.length === 0 && !view.authoringBlockedReason;
2974
+ useEffect4(() => () => active.current?.abort(), [session]);
2975
+ useEffect4(() => {
2976
+ if (view.state === "failed" || view.state === "closed") {
2977
+ active.current?.abort();
2978
+ active.current = null;
2979
+ setBusy(false);
2980
+ }
2981
+ }, [view.state]);
2982
+ const start = async () => {
2983
+ if (active.current || !ready || submissions.getPending()) return;
2984
+ const current = session.getView();
2985
+ if (current.state !== "live" || current.pendingTransactions || current.blockedPending.length || current.authoringBlockedReason)
2986
+ return;
2987
+ const controller = new AbortController();
2988
+ active.current = controller;
2989
+ setBusy(true);
2990
+ setError(false);
2991
+ try {
2992
+ const blob = await download(controller.signal);
2993
+ if (controller.signal.aborted) return;
2994
+ const url = URL.createObjectURL(blob);
2995
+ try {
2996
+ const anchor = document.createElement("a");
2997
+ anchor.href = url;
2998
+ anchor.download = `${title.replace(/[\\/:*?"<>|\u0000-\u001f]/g, "_").replace(/\.xlsx$/i, "").trim() || "Workbook"}.xlsx`;
2999
+ anchor.rel = "noopener";
3000
+ anchor.click();
3001
+ } finally {
3002
+ setTimeout(() => URL.revokeObjectURL(url), 0);
3003
+ }
3004
+ } catch {
3005
+ if (!controller.signal.aborted) setError(true);
3006
+ } finally {
3007
+ if (!controller.signal.aborted) {
3008
+ active.current = null;
3009
+ setBusy(false);
3010
+ }
3011
+ }
3012
+ };
3013
+ return /* @__PURE__ */ jsxs2(Fragment, { children: [
3014
+ error ? /* @__PURE__ */ jsx4("span", { role: "alert", className: "text-og-xs text-og-fg-muted", children: "Download failed. Try again." }) : null,
3015
+ /* @__PURE__ */ jsxs2(
3016
+ ArtifactButton,
3017
+ {
3018
+ onClick: () => void start(),
3019
+ disabled: busy || !ready,
3020
+ title: ready ? "Download workbook as XLSX" : "Wait for workbook changes to sync",
3021
+ children: [
3022
+ busy ? /* @__PURE__ */ jsx4(LoaderCircleIcon, { className: "animate-spin", "aria-hidden": true }) : /* @__PURE__ */ jsx4(DownloadIcon, { "aria-hidden": true }),
3023
+ busy ? "Preparing\u2026" : "Download"
3024
+ ]
3025
+ }
3026
+ )
3027
+ ] });
3028
+ }
3029
+
3030
+ // src/components/artifacts/editable-spreadsheet.tsx
3031
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
2293
3032
  var EXCEL_MAX_ROWS = 1048576;
2294
3033
  var EXCEL_MAX_COLUMNS = 16384;
2295
3034
  var INITIAL_VIEWPORT_ROWS = 64;
@@ -2298,7 +3037,19 @@ var MAX_INTERACTIVE_QUERY_CELLS = 65536;
2298
3037
  var MAX_INTERACTIVE_QUERY_BYTES = 8 * 1024 * 1024;
2299
3038
  var EMPTY_FORMAT = Object.freeze({});
2300
3039
  var EMPTY_SHEETS = [];
2301
- function EditableSpreadsheetGrid({
3040
+ var useClientLayoutEffect2 = typeof window === "undefined" ? useEffect5 : useLayoutEffect2;
3041
+ var SESSION_KEYS = /* @__PURE__ */ new WeakMap();
3042
+ var nextSessionKey = 0;
3043
+ function EditableSpreadsheetGrid(props) {
3044
+ return /* @__PURE__ */ jsx5(
3045
+ EditableSpreadsheetGridSession,
3046
+ {
3047
+ ...props
3048
+ },
3049
+ `${spreadsheetSessionKey(props.session)}:${props.sheet.sheetId}:${props.sheet.generationId ?? "pending"}`
3050
+ );
3051
+ }
3052
+ function EditableSpreadsheetGridSession({
2302
3053
  session,
2303
3054
  sheet,
2304
3055
  metadataRevision,
@@ -2309,39 +3060,51 @@ function EditableSpreadsheetGrid({
2309
3060
  overscanColumns = 2,
2310
3061
  onSelectionChange,
2311
3062
  onCommit,
3063
+ onResize,
2312
3064
  onCommandError,
2313
3065
  onViewportChange,
2314
3066
  className
2315
3067
  }) {
3068
+ const authoringLifetime = useSpreadsheetAuthoringLifetime();
3069
+ const submissions = useSpreadsheetSubmissions();
3070
+ const view = useEditableArtifactView(session);
2316
3071
  const rowCount = boundedSheetCount(requestedRowCount, EXCEL_MAX_ROWS, sheet.usedBounds?.endRow);
2317
3072
  const columnCount = boundedSheetCount(
2318
3073
  requestedColumnCount,
2319
3074
  EXCEL_MAX_COLUMNS,
2320
3075
  sheet.usedBounds?.endColumn
2321
3076
  );
2322
- const [state, setState] = useState2(() => ({
3077
+ const [state, setState] = useState6(() => ({
3078
+ session,
3079
+ generationId: sheet.generationId,
2323
3080
  query: initialViewportQuery(sheet.sheetId, rowCount, columnCount),
2324
3081
  projection: null,
2325
3082
  error: null
2326
3083
  }));
2327
- const activeCellRef = useRef2({ row: 0, column: 0 });
2328
- useEffect2(() => {
2329
- setState({
2330
- query: initialViewportQuery(sheet.sheetId, rowCount, columnCount),
2331
- projection: null,
2332
- error: null
2333
- });
3084
+ const activeCellRef = useRef5({ row: 0, column: 0 });
3085
+ useEffect5(() => {
3086
+ setState(
3087
+ (current) => current.session === session && current.generationId === sheet.generationId && current.query.sheetId === sheet.sheetId ? current : {
3088
+ session,
3089
+ generationId: sheet.generationId,
3090
+ query: initialViewportQuery(sheet.sheetId, rowCount, columnCount),
3091
+ projection: null,
3092
+ error: null
3093
+ }
3094
+ );
2334
3095
  activeCellRef.current = { row: 0, column: 0 };
2335
- }, [columnCount, rowCount, session, sheet.sheetId]);
2336
- useEffect2(() => {
3096
+ }, [columnCount, rowCount, session, sheet.generationId, sheet.sheetId]);
3097
+ useEffect5(() => {
2337
3098
  const query = state.query;
2338
- return session.subscribeSpreadsheetViewport(
3099
+ const matchesScope = (current) => current.session === session && current.generationId === sheet.generationId && sameViewportQuery(current.query, query);
3100
+ let active = true;
3101
+ const unsubscribe = session.subscribeSpreadsheetViewport(
2339
3102
  query,
2340
3103
  (projection2) => {
2341
- if (!sameViewport(projection2, query)) return;
3104
+ if (!active || !sameViewport(projection2, query)) return;
2342
3105
  if (sheet.generationId !== null && projection2.generationId !== sheet.generationId) {
2343
3106
  setState(
2344
- (current) => sameViewportQuery(current.query, query) ? {
3107
+ (current) => matchesScope(current) ? {
2345
3108
  ...current,
2346
3109
  projection: null,
2347
3110
  error: new Error("Spreadsheet generation changed; refreshing metadata")
@@ -2350,97 +3113,146 @@ function EditableSpreadsheetGrid({
2350
3113
  return;
2351
3114
  }
2352
3115
  setState(
2353
- (current) => sameViewportQuery(current.query, query) ? { query, projection: projection2, error: null } : current
3116
+ (current) => matchesScope(current) ? { ...current, projection: projection2, error: null } : current
2354
3117
  );
2355
3118
  },
2356
3119
  {
2357
3120
  onError(error) {
2358
- setState(
2359
- (current) => sameViewportQuery(current.query, query) ? { ...current, error } : current
2360
- );
3121
+ if (!active) return;
3122
+ setState((current) => matchesScope(current) ? { ...current, error } : current);
2361
3123
  }
2362
3124
  }
2363
3125
  );
3126
+ return () => {
3127
+ active = false;
3128
+ unsubscribe();
3129
+ };
2364
3130
  }, [session, sheet.generationId, state.query]);
2365
- const projection = useMemo2(
3131
+ const projection = useMemo3(
2366
3132
  () => projectSdkViewport(
2367
3133
  sheet,
2368
3134
  metadataRevision,
2369
3135
  state.query,
2370
- state.projection,
3136
+ state.session === session && state.generationId === sheet.generationId ? state.projection : null,
2371
3137
  rowCount,
2372
3138
  columnCount
2373
3139
  ),
2374
- [columnCount, metadataRevision, rowCount, sheet, state.projection, state.query]
3140
+ [columnCount, metadataRevision, rowCount, session, sheet, state]
2375
3141
  );
2376
- const generation = useMemo2(() => sheetGeneration(sheet), [sheet]);
2377
- const editable = !readOnly && generation !== null;
2378
- const handleCommit = useCallback2(
3142
+ const generation = useMemo3(() => sheetGeneration(sheet), [sheet]);
3143
+ const editable = !readOnly && view.writable && !view.authoringBlockedReason && generation !== null;
3144
+ const syncStatus = view.authoringBlockedReason ? "Waiting for earlier edits\u2026" : view.state === "live" ? editable ? "Saved" : "Read only" : editableArtifactStatusLabel(view);
3145
+ const syncError = view.blockedPending.length > 0 ? "Some earlier changes could not sync." : view.lastError?.message;
3146
+ const resizable = editable && sheet.defaultRowHeight !== void 0 && sheet.defaultColumnWidth !== void 0;
3147
+ const handleCommit = useCallback4(
2379
3148
  async (commit) => {
3149
+ const lifetime = requireSpreadsheetAuthoringLifetime(authoringLifetime);
2380
3150
  if (!generation) throw new Error("This sheet generation is not writable yet");
2381
3151
  const input = spreadsheetCellInput(commit.input, commit.kind);
2382
- await session.applySpreadsheetCommands({
2383
- version: SPREADSHEET_ARTIFACT_COMMAND_VERSION,
2384
- commands: [
2385
- {
2386
- kind: "cells.set",
2387
- sheet: generation,
2388
- anchor: { row: commit.cell.row, column: commit.cell.col },
2389
- rows: 1,
2390
- columns: 1,
2391
- cells: [input]
2392
- }
2393
- ]
2394
- });
2395
- onCommit?.(commit);
3152
+ await submissions.run(
3153
+ () => session.applySpreadsheetCommands({
3154
+ version: SPREADSHEET_ARTIFACT_COMMAND_VERSION,
3155
+ commands: [
3156
+ {
3157
+ kind: "cells.set",
3158
+ sheet: generation,
3159
+ anchor: { row: commit.cell.row, column: commit.cell.col },
3160
+ rows: 1,
3161
+ columns: 1,
3162
+ cells: [input]
3163
+ }
3164
+ ]
3165
+ })
3166
+ );
3167
+ if (authoringLifetime.current === lifetime) onCommit?.(commit);
2396
3168
  },
2397
- [generation, onCommit, session]
3169
+ [authoringLifetime, generation, onCommit, session, submissions]
2398
3170
  );
2399
- const handleClear = useCallback2(
3171
+ const handleClear = useCallback4(
2400
3172
  async (selection) => {
3173
+ requireSpreadsheetAuthoringLifetime(authoringLifetime);
2401
3174
  if (!generation) throw new Error("This sheet generation is not writable yet");
2402
3175
  const top = Math.min(selection.anchor.row, selection.focus.row);
2403
3176
  const bottom = Math.max(selection.anchor.row, selection.focus.row);
2404
3177
  const left = Math.min(selection.anchor.col, selection.focus.col);
2405
3178
  const right = Math.max(selection.anchor.col, selection.focus.col);
2406
- await session.applySpreadsheetCommands({
2407
- version: SPREADSHEET_ARTIFACT_COMMAND_VERSION,
2408
- commands: [
2409
- {
2410
- kind: "range.clear",
2411
- sheet: generation,
2412
- range: {
2413
- start: { row: top, column: left },
2414
- end: { row: bottom, column: right }
3179
+ await submissions.run(
3180
+ () => session.applySpreadsheetCommands({
3181
+ version: SPREADSHEET_ARTIFACT_COMMAND_VERSION,
3182
+ commands: [
3183
+ {
3184
+ kind: "range.clear",
3185
+ sheet: generation,
3186
+ range: {
3187
+ start: { row: top, column: left },
3188
+ end: { row: bottom, column: right }
3189
+ }
2415
3190
  }
2416
- }
2417
- ]
2418
- });
3191
+ ]
3192
+ })
3193
+ );
2419
3194
  },
2420
- [generation, session]
3195
+ [authoringLifetime, generation, session, submissions]
2421
3196
  );
2422
- const handleCommitRange = useCallback2(
3197
+ const handleCommitRange = useCallback4(
2423
3198
  async (commit) => {
3199
+ requireSpreadsheetAuthoringLifetime(authoringLifetime);
2424
3200
  if (!generation) throw new Error("This sheet generation is not writable yet");
2425
- await session.applySpreadsheetCommands({
2426
- version: SPREADSHEET_ARTIFACT_COMMAND_VERSION,
2427
- commands: [
2428
- {
2429
- kind: "cells.set",
2430
- sheet: generation,
2431
- anchor: { row: commit.anchor.row, column: commit.anchor.col },
2432
- rows: commit.rows,
2433
- columns: commit.columns,
2434
- cells: commit.inputs.map(
2435
- (input) => spreadsheetCellInput(input, input.startsWith("=") ? "formula" : "value")
2436
- )
2437
- }
2438
- ]
2439
- });
3201
+ await submissions.run(
3202
+ () => session.applySpreadsheetCommands({
3203
+ version: SPREADSHEET_ARTIFACT_COMMAND_VERSION,
3204
+ commands: [
3205
+ {
3206
+ kind: "cells.set",
3207
+ sheet: generation,
3208
+ anchor: { row: commit.anchor.row, column: commit.anchor.col },
3209
+ rows: commit.rows,
3210
+ columns: commit.columns,
3211
+ cells: commit.inputs.map(
3212
+ (input) => spreadsheetCellInput(input, input.startsWith("=") ? "formula" : "value")
3213
+ )
3214
+ }
3215
+ ]
3216
+ })
3217
+ );
2440
3218
  },
2441
- [generation, session]
3219
+ [authoringLifetime, generation, session, submissions]
2442
3220
  );
2443
- const handleSelection = useCallback2(
3221
+ const handleResize = useCallback4(
3222
+ async (change) => {
3223
+ const lifetime = requireSpreadsheetAuthoringLifetime(authoringLifetime);
3224
+ if (!generation) throw new Error("This sheet generation is not writable yet");
3225
+ await submissions.run(
3226
+ () => session.applySpreadsheetCommands({
3227
+ version: SPREADSHEET_ARTIFACT_COMMAND_VERSION,
3228
+ commands: [
3229
+ change.axis === "column" ? {
3230
+ kind: "column.width.set",
3231
+ sheet: generation,
3232
+ column: change.index,
3233
+ width: change.size === sheet.defaultColumnWidth ? null : change.size
3234
+ } : {
3235
+ kind: "row.height.set",
3236
+ sheet: generation,
3237
+ row: change.index,
3238
+ height: change.size === sheet.defaultRowHeight ? null : change.size
3239
+ }
3240
+ ]
3241
+ })
3242
+ );
3243
+ if (authoringLifetime.current === lifetime) onResize?.(change);
3244
+ },
3245
+ [
3246
+ authoringLifetime,
3247
+ generation,
3248
+ onResize,
3249
+ session,
3250
+ sheet.defaultColumnWidth,
3251
+ sheet.defaultRowHeight,
3252
+ submissions
3253
+ ]
3254
+ );
3255
+ const handleSelection = useCallback4(
2444
3256
  (selection) => {
2445
3257
  activeCellRef.current = {
2446
3258
  row: selection.focus.row,
@@ -2449,6 +3261,7 @@ function EditableSpreadsheetGrid({
2449
3261
  setState((current) => {
2450
3262
  if (queryContains(current.query, selection.focus.row, selection.focus.col)) return current;
2451
3263
  return {
3264
+ ...current,
2452
3265
  query: boundedViewportQuery(
2453
3266
  sheet.sheetId,
2454
3267
  selection.focus.row,
@@ -2467,7 +3280,7 @@ function EditableSpreadsheetGrid({
2467
3280
  },
2468
3281
  [columnCount, onSelectionChange, rowCount, sheet.sheetId]
2469
3282
  );
2470
- const handleViewport = useCallback2(
3283
+ const handleViewport = useCallback4(
2471
3284
  (viewport) => {
2472
3285
  const next = boundedViewportQuery(
2473
3286
  sheet.sheetId,
@@ -2480,14 +3293,23 @@ function EditableSpreadsheetGrid({
2480
3293
  activeCellRef.current
2481
3294
  );
2482
3295
  setState(
2483
- (current) => sameViewportQuery(current.query, next) ? current : { query: next, projection: current.projection, error: null }
3296
+ (current) => sameViewportQuery(current.query, next) ? current : { ...current, query: next, error: null }
2484
3297
  );
2485
3298
  onViewportChange?.(viewport);
2486
3299
  },
2487
3300
  [columnCount, onViewportChange, rowCount, sheet.sheetId]
2488
3301
  );
2489
- return /* @__PURE__ */ jsxs2("div", { className: cn("relative h-full min-h-0", className), children: [
2490
- /* @__PURE__ */ jsx2(
3302
+ if (editableArtifactAccessRevoked(view)) {
3303
+ return /* @__PURE__ */ jsx5(
3304
+ EditableArtifactMessage,
3305
+ {
3306
+ title: "Spreadsheet unavailable",
3307
+ detail: "You no longer have access to this artifact"
3308
+ }
3309
+ );
3310
+ }
3311
+ return /* @__PURE__ */ jsxs3("div", { className: cn("relative h-full min-h-0", className), children: [
3312
+ /* @__PURE__ */ jsx5(
2491
3313
  SpreadsheetProjectionGrid,
2492
3314
  {
2493
3315
  projection,
@@ -2498,11 +3320,15 @@ function EditableSpreadsheetGrid({
2498
3320
  commit: editable ? handleCommit : void 0,
2499
3321
  commitRange: editable ? handleCommitRange : void 0,
2500
3322
  clear: editable ? handleClear : void 0,
3323
+ resize: resizable ? handleResize : void 0,
3324
+ pendingTransactions: view.pendingTransactions,
3325
+ syncStatus,
3326
+ syncError,
2501
3327
  onCommandError,
2502
3328
  onViewportChange: handleViewport
2503
3329
  }
2504
3330
  ),
2505
- state.error ? /* @__PURE__ */ jsx2(
3331
+ state.error && state.session === session && state.generationId === sheet.generationId ? /* @__PURE__ */ jsx5(
2506
3332
  "output",
2507
3333
  {
2508
3334
  role: "status",
@@ -2513,65 +3339,73 @@ function EditableSpreadsheetGrid({
2513
3339
  ) : null
2514
3340
  ] });
2515
3341
  }
2516
- function EditableSpreadsheetArtifactSurface({
3342
+ function EditableSpreadsheetArtifactSurface(props) {
3343
+ return /* @__PURE__ */ jsx5(SpreadsheetSubmissionProvider, { children: /* @__PURE__ */ jsx5(EditableSpreadsheetArtifactSurfaceSession, { ...props }) }, spreadsheetSessionKey(props.session));
3344
+ }
3345
+ function EditableSpreadsheetArtifactSurfaceSession({
2517
3346
  session,
2518
3347
  title = "Workbook",
3348
+ showHeader,
2519
3349
  subtitle,
2520
3350
  actions,
3351
+ download,
2521
3352
  initialSheetId,
2522
3353
  allowAddSheet = true,
2523
3354
  readOnly = false,
2524
3355
  ...gridProps
2525
3356
  }) {
3357
+ const authoringLifetime = useSpreadsheetAuthoringLifetime();
3358
+ const submissions = useSpreadsheetSubmissions();
2526
3359
  const { metadata, error: metadataError } = useSpreadsheetMetadata(session);
2527
3360
  const view = useEditableArtifactView(session);
2528
- const [activeSheetId, setActiveSheetId] = useState2(initialSheetId ?? null);
2529
- const [creatingSheet, setCreatingSheet] = useState2(false);
2530
- const [surfaceError, setSurfaceError] = useState2(null);
3361
+ const [activeSheetId, setActiveSheetId] = useState6(initialSheetId ?? null);
3362
+ const [creatingSheet, setCreatingSheet] = useState6(false);
3363
+ const [surfaceError, setSurfaceError] = useState6(null);
2531
3364
  const sheets = metadata?.sheets ?? EMPTY_SHEETS;
2532
3365
  const activeSheet = sheets.find((sheet) => sheet.sheetId === activeSheetId) ?? (initialSheetId ? sheets.find((sheet) => sheet.sheetId === initialSheetId) : void 0) ?? sheets[0] ?? null;
2533
- const writable = !readOnly && view.writable;
3366
+ const writable = !readOnly && view.writable && !view.authoringBlockedReason;
2534
3367
  const accessRevoked = editableArtifactAccessRevoked(view);
2535
- const addSheet = useCallback2(async () => {
3368
+ const addSheet = useCallback4(async () => {
2536
3369
  if (!writable || creatingSheet) return;
3370
+ const lifetime = requireSpreadsheetAuthoringLifetime(authoringLifetime);
2537
3371
  setCreatingSheet(true);
2538
3372
  setSurfaceError(null);
2539
3373
  try {
2540
3374
  const after = activeSheet ? sheetGeneration(activeSheet) : null;
2541
- const created = await session.createSpreadsheetSheet({
2542
- name: nextAvailableSheetName2(sheets),
2543
- after
2544
- });
2545
- setActiveSheetId(created.sheetId);
3375
+ const created = await submissions.run(
3376
+ () => session.createSpreadsheetSheet({
3377
+ name: nextAvailableSheetName2(sheets),
3378
+ after
3379
+ })
3380
+ );
3381
+ if (authoringLifetime.current === lifetime) setActiveSheetId(created.sheetId);
2546
3382
  } catch (cause) {
2547
- setSurfaceError(asError(cause));
3383
+ if (authoringLifetime.current === lifetime) setSurfaceError(asError(cause));
2548
3384
  } finally {
2549
- setCreatingSheet(false);
3385
+ if (authoringLifetime.current === lifetime) setCreatingSheet(false);
2550
3386
  }
2551
- }, [activeSheet, creatingSheet, session, sheets, writable]);
2552
- const footer = /* @__PURE__ */ jsxs2(
3387
+ }, [activeSheet, authoringLifetime, creatingSheet, session, sheets, submissions, writable]);
3388
+ const footer = /* @__PURE__ */ jsxs3(
2553
3389
  "div",
2554
3390
  {
2555
3391
  className: "flex min-h-9 items-center gap-1 overflow-x-auto px-2",
2556
3392
  role: "tablist",
2557
3393
  "aria-label": "Worksheets",
2558
3394
  children: [
2559
- sheets.map((sheet) => /* @__PURE__ */ jsx2(
2560
- "button",
3395
+ sheets.map((sheet) => /* @__PURE__ */ jsx5(
3396
+ EditableWorksheetTab,
2561
3397
  {
2562
- type: "button",
2563
- role: "tab",
2564
- "aria-selected": sheet.sheetId === activeSheet?.sheetId,
2565
- onClick: () => setActiveSheetId(sheet.sheetId),
2566
- className: cn(
2567
- "h-7 shrink-0 rounded-og-sm px-2.5 text-og-sm outline-hidden transition-colors focus-visible:ring-2 focus-visible:ring-og-accent",
2568
- sheet.sheetId === activeSheet?.sheetId ? "bg-og-surface-3 font-medium text-og-fg" : "text-og-fg-muted hover:bg-og-surface-3 hover:text-og-fg"
2569
- ),
2570
- children: sheet.name
3398
+ session,
3399
+ sheet,
3400
+ sheets,
3401
+ selected: sheet.sheetId === activeSheet?.sheetId,
3402
+ writable,
3403
+ onSelect: () => setActiveSheetId(sheet.sheetId),
3404
+ onCommandError: gridProps.onCommandError
2571
3405
  },
2572
3406
  `${sheet.sheetId}:${sheet.generationId ?? "pending"}`
2573
3407
  )),
2574
- writable && allowAddSheet ? /* @__PURE__ */ jsx2(
3408
+ writable && allowAddSheet ? /* @__PURE__ */ jsx5(
2575
3409
  "button",
2576
3410
  {
2577
3411
  type: "button",
@@ -2579,29 +3413,33 @@ function EditableSpreadsheetArtifactSurface({
2579
3413
  disabled: creatingSheet,
2580
3414
  "aria-label": creatingSheet ? "Adding worksheet" : "Add worksheet",
2581
3415
  className: "grid size-7 shrink-0 place-items-center rounded-og-sm text-og-fg-muted outline-hidden hover:bg-og-surface-3 hover:text-og-fg focus-visible:ring-2 focus-visible:ring-og-accent disabled:opacity-50 [&>svg]:size-3.5",
2582
- children: /* @__PURE__ */ jsx2(PlusIcon2, {})
3416
+ children: /* @__PURE__ */ jsx5(PlusIcon2, {})
2583
3417
  }
2584
3418
  ) : null
2585
3419
  ]
2586
3420
  }
2587
3421
  );
2588
3422
  const error = surfaceError ?? metadataError;
2589
- return /* @__PURE__ */ jsx2(
3423
+ return /* @__PURE__ */ jsx5(
2590
3424
  ArtifactSurface,
2591
3425
  {
2592
3426
  modality: "spreadsheet",
2593
3427
  title,
3428
+ showHeader,
2594
3429
  subtitle: subtitle ?? (accessRevoked ? editableArtifactStatusLabel(view) : metadata ? `${sheets.length} sheet${sheets.length === 1 ? "" : "s"}` : editableArtifactStatusLabel(view)),
2595
- actions,
3430
+ actions: download ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
3431
+ actions,
3432
+ /* @__PURE__ */ jsx5(SpreadsheetDownloadButton, { session, title, download })
3433
+ ] }) : actions,
2596
3434
  footer: accessRevoked ? void 0 : footer,
2597
3435
  busy: !accessRevoked && !metadata && !error,
2598
- children: accessRevoked ? /* @__PURE__ */ jsx2(
3436
+ children: accessRevoked ? /* @__PURE__ */ jsx5(
2599
3437
  EditableArtifactMessage,
2600
3438
  {
2601
3439
  title: "Access changed",
2602
3440
  detail: editableArtifactStatusLabel(view)
2603
3441
  }
2604
- ) : activeSheet && metadata ? /* @__PURE__ */ jsx2(
3442
+ ) : activeSheet && metadata ? /* @__PURE__ */ jsx5(
2605
3443
  EditableSpreadsheetGrid,
2606
3444
  {
2607
3445
  ...gridProps,
@@ -2611,19 +3449,19 @@ function EditableSpreadsheetArtifactSurface({
2611
3449
  readOnly: !writable
2612
3450
  },
2613
3451
  `${activeSheet.sheetId}:${activeSheet.generationId ?? "pending"}`
2614
- ) : error ? /* @__PURE__ */ jsx2(EditableArtifactMessage, { title: "Could not open this workbook", detail: error.message }) : metadata ? /* @__PURE__ */ jsx2("div", { className: "grid h-full place-items-center bg-og-bg p-6 text-center", children: /* @__PURE__ */ jsxs2("div", { children: [
2615
- /* @__PURE__ */ jsx2("p", { className: "text-og-base font-medium text-og-fg", children: "This workbook has no worksheets." }),
2616
- writable && allowAddSheet ? /* @__PURE__ */ jsx2(
3452
+ ) : error ? /* @__PURE__ */ jsx5(EditableArtifactMessage, { title: "Could not open this workbook", detail: error.message }) : metadata ? /* @__PURE__ */ jsx5("div", { className: "grid h-full place-items-center bg-og-bg p-6 text-center", children: /* @__PURE__ */ jsxs3("div", { children: [
3453
+ /* @__PURE__ */ jsx5("p", { className: "text-og-base font-medium text-og-fg", children: "This workbook has no worksheets." }),
3454
+ writable && allowAddSheet ? /* @__PURE__ */ jsx5(
2617
3455
  "button",
2618
3456
  {
2619
3457
  type: "button",
2620
3458
  onClick: () => void addSheet(),
2621
3459
  disabled: creatingSheet,
2622
- className: "mt-3 rounded-og-sm bg-og-accent-deep px-3 py-1.5 text-og-sm font-medium text-og-accent-fg outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent disabled:opacity-50",
3460
+ className: "mt-3 rounded-og-sm border border-og-primary-border bg-og-primary text-og-primary-fg px-3 py-1.5 text-og-sm font-medium hover:bg-og-primary-hover outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent disabled:opacity-50",
2623
3461
  children: creatingSheet ? "Adding\u2026" : "Add worksheet"
2624
3462
  }
2625
3463
  ) : null
2626
- ] }) }) : /* @__PURE__ */ jsx2(
3464
+ ] }) }) : /* @__PURE__ */ jsx5(
2627
3465
  EditableArtifactMessage,
2628
3466
  {
2629
3467
  title: "Opening workbook",
@@ -2633,18 +3471,272 @@ function EditableSpreadsheetArtifactSurface({
2633
3471
  }
2634
3472
  );
2635
3473
  }
2636
- function useSpreadsheetMetadata(session) {
2637
- const [state, setState] = useState2({ metadata: null, error: null });
2638
- useEffect2(
2639
- () => session.subscribeSpreadsheetMetadata({}, (metadata) => setState({ metadata, error: null }), {
2640
- onError: (error) => setState((current) => ({ ...current, error }))
2641
- }),
2642
- [session]
3474
+ function EditableWorksheetTab({
3475
+ session,
3476
+ sheet,
3477
+ sheets,
3478
+ selected,
3479
+ writable,
3480
+ onSelect,
3481
+ onCommandError
3482
+ }) {
3483
+ const submissions = useSpreadsheetSubmissions();
3484
+ const [editing, setEditing] = useState6(false);
3485
+ const [name, setName] = useState6(sheet.name);
3486
+ const [saving, setSaving] = useState6(false);
3487
+ const [accepted, setAccepted] = useState6(false);
3488
+ const [error, setError] = useState6(null);
3489
+ const inputRef = useRef5(null);
3490
+ const tabRef = useRef5(null);
3491
+ const busyRef = useRef5(false);
3492
+ const mountedRef = useRef5(true);
3493
+ const latestRef = useRef5({ session, sheet, writable });
3494
+ latestRef.current = { session, sheet, writable };
3495
+ const errorId = useId2();
3496
+ const canRename = writable && sheet.generationId !== null;
3497
+ const scopeRef = useRef5({
3498
+ session,
3499
+ sheetId: sheet.sheetId,
3500
+ generationId: sheet.generationId,
3501
+ canRename
3502
+ });
3503
+ if (scopeRef.current.session !== session || scopeRef.current.sheetId !== sheet.sheetId || scopeRef.current.generationId !== sheet.generationId || scopeRef.current.canRename !== canRename) {
3504
+ scopeRef.current = {
3505
+ session,
3506
+ sheetId: sheet.sheetId,
3507
+ generationId: sheet.generationId,
3508
+ canRename
3509
+ };
3510
+ }
3511
+ useEffect5(() => {
3512
+ mountedRef.current = true;
3513
+ return () => {
3514
+ mountedRef.current = false;
3515
+ };
3516
+ }, []);
3517
+ useEffect5(() => {
3518
+ setEditing(false);
3519
+ setSaving(false);
3520
+ setAccepted(false);
3521
+ setError(null);
3522
+ busyRef.current = false;
3523
+ }, [session, sheet.generationId, sheet.sheetId, canRename]);
3524
+ useEffect5(() => {
3525
+ if (!editing) return;
3526
+ inputRef.current?.focus();
3527
+ inputRef.current?.select();
3528
+ }, [editing]);
3529
+ useEffect5(() => {
3530
+ if (!accepted || !editing || sheet.name !== name) return;
3531
+ const restoreFocus = document.activeElement === document.body || document.activeElement === inputRef.current;
3532
+ setEditing(false);
3533
+ setSaving(false);
3534
+ setAccepted(false);
3535
+ busyRef.current = false;
3536
+ if (restoreFocus) queueMicrotask(() => tabRef.current?.focus({ preventScroll: true }));
3537
+ }, [accepted, editing, name, sheet.name]);
3538
+ const start = () => {
3539
+ if (!canRename || busyRef.current) return;
3540
+ onSelect();
3541
+ setName(sheet.name);
3542
+ setError(null);
3543
+ setAccepted(false);
3544
+ setEditing(true);
3545
+ };
3546
+ const cancel = () => {
3547
+ if (busyRef.current) return;
3548
+ setEditing(false);
3549
+ setError(null);
3550
+ queueMicrotask(() => tabRef.current?.focus({ preventScroll: true }));
3551
+ };
3552
+ const rename = async () => {
3553
+ if (!canRename || busyRef.current) return;
3554
+ const generation = sheetGeneration(sheet);
3555
+ if (!generation) return;
3556
+ const next = name.trim();
3557
+ if (!next || next.length > 31 || /[\\/?*[\]:\0]/u.test(next)) {
3558
+ setError("Use 1\u201331 characters without \\ / ? * [ ] :.");
3559
+ return;
3560
+ }
3561
+ if (sheets.some((other) => other.sheetId !== sheet.sheetId && other.name === next)) {
3562
+ setError("A worksheet already has this name.");
3563
+ return;
3564
+ }
3565
+ if (next === sheet.name) {
3566
+ cancel();
3567
+ return;
3568
+ }
3569
+ setName(next);
3570
+ setError(null);
3571
+ setSaving(true);
3572
+ busyRef.current = true;
3573
+ const scope = scopeRef.current;
3574
+ const current = () => mountedRef.current && scopeRef.current === scope && latestRef.current.writable;
3575
+ try {
3576
+ await submissions.run(
3577
+ () => session.applySpreadsheetCommands({
3578
+ version: SPREADSHEET_ARTIFACT_COMMAND_VERSION,
3579
+ commands: [{ kind: "sheet.rename", sheet: generation, name: next }]
3580
+ })
3581
+ );
3582
+ if (current()) setAccepted(true);
3583
+ } catch (cause) {
3584
+ if (!current()) return;
3585
+ const failure = asError(cause);
3586
+ busyRef.current = false;
3587
+ setSaving(false);
3588
+ setError(failure.message || "Could not rename worksheet. Try again.");
3589
+ onCommandError?.(failure);
3590
+ queueMicrotask(() => inputRef.current?.focus());
3591
+ }
3592
+ };
3593
+ const tab = /* @__PURE__ */ jsx5(
3594
+ "button",
3595
+ {
3596
+ ref: tabRef,
3597
+ type: "button",
3598
+ role: "tab",
3599
+ tabIndex: editing && canRename ? -1 : void 0,
3600
+ "aria-selected": selected,
3601
+ "aria-keyshortcuts": canRename ? "F2" : void 0,
3602
+ title: canRename ? "Double-click or press F2 to rename" : void 0,
3603
+ onClick: onSelect,
3604
+ onDoubleClick: start,
3605
+ onKeyDown: (event) => {
3606
+ if (event.key === "F2") {
3607
+ event.preventDefault();
3608
+ start();
3609
+ }
3610
+ },
3611
+ className: cn(
3612
+ "h-7 shrink-0 rounded-og-sm px-2.5 text-og-sm outline-hidden transition-colors focus-visible:ring-2 focus-visible:ring-og-accent",
3613
+ selected ? "bg-og-surface-3 font-medium text-og-fg" : "text-og-fg-muted hover:bg-og-surface-3 hover:text-og-fg"
3614
+ ),
3615
+ children: sheet.name
3616
+ }
2643
3617
  );
2644
- return state;
3618
+ return editing && canRename ? /* @__PURE__ */ jsxs3(Fragment2, { children: [
3619
+ /* @__PURE__ */ jsx5("span", { className: "sr-only", children: tab }),
3620
+ /* @__PURE__ */ jsxs3(
3621
+ "form",
3622
+ {
3623
+ className: "flex min-w-0 flex-wrap items-center gap-1 py-1",
3624
+ style: { width: "min(18rem, 100%)" },
3625
+ onSubmit: (event) => {
3626
+ event.preventDefault();
3627
+ void rename();
3628
+ },
3629
+ children: [
3630
+ /* @__PURE__ */ jsx5(
3631
+ "input",
3632
+ {
3633
+ ref: inputRef,
3634
+ "aria-label": "Worksheet name",
3635
+ "aria-invalid": error ? "true" : void 0,
3636
+ "aria-describedby": error ? errorId : void 0,
3637
+ disabled: saving,
3638
+ value: name,
3639
+ onInput: (event) => {
3640
+ setName(event.currentTarget.value);
3641
+ setError(null);
3642
+ },
3643
+ onKeyDown: (event) => {
3644
+ if (event.nativeEvent.isComposing || event.keyCode === 229) return;
3645
+ if (event.key === "Escape") {
3646
+ event.preventDefault();
3647
+ cancel();
3648
+ }
3649
+ if (event.key === "Enter") {
3650
+ event.preventDefault();
3651
+ void rename();
3652
+ }
3653
+ },
3654
+ className: "h-7 w-40 rounded-og-sm border border-og-border bg-og-surface-1 px-2 text-og-sm text-og-fg outline-hidden focus-visible:ring-2 focus-visible:ring-og-accent disabled:opacity-50"
3655
+ }
3656
+ ),
3657
+ saving ? /* @__PURE__ */ jsx5("span", { role: "status", className: "text-og-xs text-og-fg-muted", children: "Renaming\u2026" }) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
3658
+ /* @__PURE__ */ jsx5(
3659
+ "button",
3660
+ {
3661
+ type: "submit",
3662
+ className: "rounded-og-sm px-2 py-1 text-og-xs text-og-fg outline-hidden hover:bg-og-surface-3 focus-visible:ring-2 focus-visible:ring-og-accent",
3663
+ children: "Save"
3664
+ }
3665
+ ),
3666
+ /* @__PURE__ */ jsx5(
3667
+ "button",
3668
+ {
3669
+ type: "button",
3670
+ onClick: cancel,
3671
+ className: "rounded-og-sm px-2 py-1 text-og-xs text-og-fg-muted outline-hidden hover:bg-og-surface-3 focus-visible:ring-2 focus-visible:ring-og-accent",
3672
+ children: "Cancel"
3673
+ }
3674
+ )
3675
+ ] }),
3676
+ error ? /* @__PURE__ */ jsx5(
3677
+ "span",
3678
+ {
3679
+ id: errorId,
3680
+ role: "alert",
3681
+ className: "text-og-xs text-og-status-failed",
3682
+ style: { flexBasis: "100%", overflowWrap: "anywhere" },
3683
+ children: error
3684
+ }
3685
+ ) : null
3686
+ ]
3687
+ }
3688
+ )
3689
+ ] }) : tab;
3690
+ }
3691
+ function spreadsheetSessionKey(session) {
3692
+ let key = SESSION_KEYS.get(session);
3693
+ if (key === void 0) {
3694
+ key = ++nextSessionKey;
3695
+ SESSION_KEYS.set(session, key);
3696
+ }
3697
+ return key;
3698
+ }
3699
+ function useSpreadsheetAuthoringLifetime() {
3700
+ const lifetime = useRef5({});
3701
+ useClientLayoutEffect2(() => {
3702
+ lifetime.current = {};
3703
+ return () => {
3704
+ lifetime.current = null;
3705
+ };
3706
+ }, []);
3707
+ return lifetime;
3708
+ }
3709
+ function requireSpreadsheetAuthoringLifetime(lifetime) {
3710
+ if (!lifetime.current) throw new Error("Spreadsheet authoring session changed");
3711
+ return lifetime.current;
3712
+ }
3713
+ function useSpreadsheetMetadata(session) {
3714
+ const [state, setState] = useState6({ session, metadata: null, error: null });
3715
+ useEffect5(() => {
3716
+ let active = true;
3717
+ const unsubscribe = session.subscribeSpreadsheetMetadata(
3718
+ {},
3719
+ (metadata) => {
3720
+ if (active) setState({ session, metadata, error: null });
3721
+ },
3722
+ {
3723
+ onError: (error) => {
3724
+ if (active)
3725
+ setState(
3726
+ (current) => current.session === session ? { ...current, error } : { session, metadata: null, error }
3727
+ );
3728
+ }
3729
+ }
3730
+ );
3731
+ return () => {
3732
+ active = false;
3733
+ unsubscribe();
3734
+ };
3735
+ }, [session]);
3736
+ return state.session === session ? state : { metadata: null, error: null };
2645
3737
  }
2646
3738
  function projectSdkViewport(sheet, metadataRevision, query, viewport, rowCount, columnCount) {
2647
- const current = viewport && sameViewport(viewport, query) ? viewport : null;
3739
+ const current = viewport && viewport.sheetId === sheet.sheetId && viewport.generationId === sheet.generationId ? viewport : null;
2648
3740
  const projectedCells = (current?.cells ?? []).map((cell) => ({
2649
3741
  row: cell.row,
2650
3742
  col: cell.column,
@@ -2661,8 +3753,12 @@ function projectSdkViewport(sheet, metadataRevision, query, viewport, rowCount,
2661
3753
  sheetId: sheet.sheetId,
2662
3754
  sheetName: sheet.name,
2663
3755
  generationId: current?.generationId ?? sheet.generationId,
2664
- revision: `${metadataRevision}:${current?.revision ?? "loading"}`,
3756
+ revision: current?.revision.toString() ?? "loading",
2665
3757
  dimensionRevision: metadataRevision.toString(),
3758
+ defaultRowHeight: sheet.defaultRowHeight,
3759
+ defaultColumnWidth: sheet.defaultColumnWidth,
3760
+ rowHeights: sheet.rowHeights,
3761
+ columnWidths: sheet.columnWidths,
2666
3762
  rowCount,
2667
3763
  columnCount,
2668
3764
  usedRange: used ? {
@@ -2688,7 +3784,7 @@ function projectSdkViewport(sheet, metadataRevision, query, viewport, rowCount,
2688
3784
  const cell = byCoordinate.get(`${row}:${column}`);
2689
3785
  return cell ? {
2690
3786
  value: cell.value,
2691
- input: cell.formula ?? displayValue3(cell.value),
3787
+ input: cell.formula ?? displayValue(cell.value),
2692
3788
  format: cell.format
2693
3789
  } : null;
2694
3790
  }
@@ -2799,7 +3895,7 @@ function boundedSheetCount(requested, maximum, usedEnd) {
2799
3895
  const usedCount = usedEnd === void 0 || !Number.isSafeInteger(usedEnd) ? 1 : Math.max(1, Math.min(maximum, usedEnd + 1));
2800
3896
  return Math.max(requestedCount, usedCount);
2801
3897
  }
2802
- function displayValue3(value) {
3898
+ function displayValue(value) {
2803
3899
  if (value === null || value === void 0) return "";
2804
3900
  if (value instanceof Date) return Number.isNaN(value.getTime()) ? "" : value.toISOString();
2805
3901
  if (typeof value === "boolean") return value ? "TRUE" : "FALSE";
@@ -2825,4 +3921,4 @@ export {
2825
3921
  EditableSpreadsheetGrid,
2826
3922
  EditableSpreadsheetArtifactSurface
2827
3923
  };
2828
- //# sourceMappingURL=chunk-ICA6R6TW.js.map
3924
+ //# sourceMappingURL=chunk-WNN7NO2N.js.map