@stigmer/react 3.41.0 → 3.41.1-dev.20261003094357.g39d6aa748646

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 (510) hide show
  1. package/README.md +1 -1
  2. package/access/ManageAccessButton.d.ts +1 -1
  3. package/access/ManageAccessButton.js +1 -1
  4. package/access/ManageAccessDialog.js +1 -1
  5. package/access/ManageAccessDialog.js.map +1 -1
  6. package/agent/AgentDetailView.d.ts.map +1 -1
  7. package/agent/AgentDetailView.js +2 -1
  8. package/agent/AgentDetailView.js.map +1 -1
  9. package/api-key/ApiKeyListPanel.d.ts.map +1 -1
  10. package/api-key/ApiKeyListPanel.js +2 -1
  11. package/api-key/ApiKeyListPanel.js.map +1 -1
  12. package/attachment/AttachmentImageLightbox.d.ts.map +1 -1
  13. package/attachment/AttachmentImageLightbox.js.map +1 -1
  14. package/billing/AutoRechargeCard.d.ts +3 -3
  15. package/billing/AutoRechargeCard.d.ts.map +1 -1
  16. package/billing/AutoRechargeCard.js +4 -4
  17. package/billing/AutoRechargeCard.js.map +1 -1
  18. package/billing/BillingSection.d.ts.map +1 -1
  19. package/billing/BillingSection.js +7 -6
  20. package/billing/BillingSection.js.map +1 -1
  21. package/billing/CreditLedgerTable.d.ts +3 -3
  22. package/billing/CreditLedgerTable.d.ts.map +1 -1
  23. package/billing/CreditLedgerTable.js +3 -3
  24. package/billing/CreditLedgerTable.js.map +1 -1
  25. package/billing/CreditPackGrid.d.ts +1 -1
  26. package/billing/CreditPackGrid.js +1 -1
  27. package/billing/PaymentMethodCard.d.ts +1 -1
  28. package/billing/PaymentMethodCard.js +1 -1
  29. package/billing/PlanSection.d.ts +3 -3
  30. package/billing/PlanSection.d.ts.map +1 -1
  31. package/billing/PlanSection.js +4 -3
  32. package/billing/PlanSection.js.map +1 -1
  33. package/billing/ProviderKeysSection.js +13 -13
  34. package/billing/ProviderKeysSection.js.map +1 -1
  35. package/billing/plan-features.js +1 -1
  36. package/billing/plan-features.js.map +1 -1
  37. package/billing/useBillingAccount.d.ts +4 -4
  38. package/billing/useBillingAccount.d.ts.map +1 -1
  39. package/billing/useBillingAccount.js +7 -7
  40. package/billing/useBillingAccount.js.map +1 -1
  41. package/billing/useBillingUsageReport.d.ts +4 -4
  42. package/billing/useBillingUsageReport.d.ts.map +1 -1
  43. package/billing/useBillingUsageReport.js +7 -7
  44. package/billing/useBillingUsageReport.js.map +1 -1
  45. package/billing/useChangePlan.d.ts +2 -2
  46. package/billing/useChangePlan.d.ts.map +1 -1
  47. package/billing/useChangePlan.js +4 -4
  48. package/billing/useChangePlan.js.map +1 -1
  49. package/billing/useCreateBillingPortalSession.d.ts +2 -2
  50. package/billing/useCreateBillingPortalSession.d.ts.map +1 -1
  51. package/billing/useCreateBillingPortalSession.js +3 -3
  52. package/billing/useCreateBillingPortalSession.js.map +1 -1
  53. package/billing/useCreateCheckoutSession.d.ts +2 -2
  54. package/billing/useCreateCheckoutSession.d.ts.map +1 -1
  55. package/billing/useCreateCheckoutSession.js +2 -2
  56. package/billing/useCreateCheckoutSession.js.map +1 -1
  57. package/billing/useCreatePaymentMethodSetupSession.d.ts +1 -1
  58. package/billing/useCreatePaymentMethodSetupSession.d.ts.map +1 -1
  59. package/billing/useCreatePaymentMethodSetupSession.js +2 -2
  60. package/billing/useCreatePaymentMethodSetupSession.js.map +1 -1
  61. package/billing/useCreditLedger.d.ts +4 -4
  62. package/billing/useCreditLedger.d.ts.map +1 -1
  63. package/billing/useCreditLedger.js +7 -7
  64. package/billing/useCreditLedger.js.map +1 -1
  65. package/billing/useCustomerModelPricing.d.ts +4 -4
  66. package/billing/useCustomerModelPricing.d.ts.map +1 -1
  67. package/billing/useCustomerModelPricing.js +6 -6
  68. package/billing/useCustomerModelPricing.js.map +1 -1
  69. package/billing/useEntitlements.d.ts +2 -2
  70. package/billing/useEntitlements.d.ts.map +1 -1
  71. package/billing/useEntitlements.js +4 -4
  72. package/billing/useEntitlements.js.map +1 -1
  73. package/billing/usePeriodEstimate.d.ts +1 -1
  74. package/billing/usePeriodEstimate.d.ts.map +1 -1
  75. package/billing/usePeriodEstimate.js +3 -3
  76. package/billing/usePeriodEstimate.js.map +1 -1
  77. package/billing/useProviderKeys.d.ts +5 -5
  78. package/billing/useProviderKeys.d.ts.map +1 -1
  79. package/billing/useProviderKeys.js +7 -7
  80. package/billing/useProviderKeys.js.map +1 -1
  81. package/billing/useSetAutoRechargeConfig.d.ts +2 -2
  82. package/billing/useSetAutoRechargeConfig.d.ts.map +1 -1
  83. package/billing/useSetAutoRechargeConfig.js +2 -2
  84. package/billing/useSetAutoRechargeConfig.js.map +1 -1
  85. package/billing/useSubscription.d.ts +3 -3
  86. package/billing/useSubscription.d.ts.map +1 -1
  87. package/billing/useSubscription.js +7 -7
  88. package/billing/useSubscription.js.map +1 -1
  89. package/channel-app/ChannelAppListPanel.d.ts.map +1 -1
  90. package/channel-app/ChannelAppListPanel.js +2 -1
  91. package/channel-app/ChannelAppListPanel.js.map +1 -1
  92. package/channel-app/slackAppSetup.d.ts +0 -23
  93. package/channel-app/slackAppSetup.d.ts.map +1 -1
  94. package/channel-app/slackAppSetup.js +3 -2
  95. package/channel-app/slackAppSetup.js.map +1 -1
  96. package/channel-app/whatsappAppSetup.d.ts +0 -26
  97. package/channel-app/whatsappAppSetup.d.ts.map +1 -1
  98. package/channel-app/whatsappAppSetup.js +2 -1
  99. package/channel-app/whatsappAppSetup.js.map +1 -1
  100. package/cursor-accounts/CursorAccountEditor.js +3 -3
  101. package/cursor-accounts/CursorAccountEditor.js.map +1 -1
  102. package/cursor-accounts/CursorAccountsConsole.js +3 -3
  103. package/cursor-accounts/CursorAccountsConsole.js.map +1 -1
  104. package/dashboard/OperationalDashboard.d.ts +1 -4
  105. package/dashboard/OperationalDashboard.d.ts.map +1 -1
  106. package/dashboard/OperationalDashboard.js +1 -3
  107. package/dashboard/OperationalDashboard.js.map +1 -1
  108. package/dashboard/useDashboardSummary.d.ts +1 -3
  109. package/dashboard/useDashboardSummary.d.ts.map +1 -1
  110. package/dashboard/useDashboardSummary.js +1 -1
  111. package/dashboard/useDashboardSummary.js.map +1 -1
  112. package/environment/EnvironmentListPanel.d.ts.map +1 -1
  113. package/environment/EnvironmentListPanel.js +2 -1
  114. package/environment/EnvironmentListPanel.js.map +1 -1
  115. package/environment/EnvironmentVariableEditor.d.ts.map +1 -1
  116. package/environment/EnvironmentVariableEditor.js +2 -1
  117. package/environment/EnvironmentVariableEditor.js.map +1 -1
  118. package/execution/ArtifactFileContent.d.ts.map +1 -1
  119. package/execution/ArtifactFileContent.js +2 -1
  120. package/execution/ArtifactFileContent.js.map +1 -1
  121. package/execution/McpToolDetail.d.ts.map +1 -1
  122. package/execution/McpToolDetail.js +2 -1
  123. package/execution/McpToolDetail.js.map +1 -1
  124. package/execution/ResultView.d.ts.map +1 -1
  125. package/execution/ResultView.js +2 -1
  126. package/execution/ResultView.js.map +1 -1
  127. package/execution/TerminalSession.js +1 -1
  128. package/execution/TerminalSession.js.map +1 -1
  129. package/execution/ThreadSkeleton.d.ts.map +1 -1
  130. package/execution/ThreadSkeleton.js +2 -1
  131. package/execution/ThreadSkeleton.js.map +1 -1
  132. package/execution/file-path-resolver.d.ts.map +1 -1
  133. package/execution/file-path-resolver.js +3 -2
  134. package/execution/file-path-resolver.js.map +1 -1
  135. package/execution/sandbox-path-normalizer.d.ts +0 -11
  136. package/execution/sandbox-path-normalizer.d.ts.map +1 -1
  137. package/execution/sandbox-path-normalizer.js +2 -1
  138. package/execution/sandbox-path-normalizer.js.map +1 -1
  139. package/github/parseGitUrl.d.ts.map +1 -1
  140. package/github/parseGitUrl.js +16 -4
  141. package/github/parseGitUrl.js.map +1 -1
  142. package/iam-policy/GrantAccessForm.d.ts +3 -3
  143. package/iam-policy/GrantAccessForm.d.ts.map +1 -1
  144. package/iam-policy/GrantAccessForm.js +3 -3
  145. package/iam-policy/GrantAccessForm.js.map +1 -1
  146. package/iam-policy/OrgMembersPanel.d.ts +3 -3
  147. package/iam-policy/OrgMembersPanel.d.ts.map +1 -1
  148. package/iam-policy/OrgMembersPanel.js +4 -3
  149. package/iam-policy/OrgMembersPanel.js.map +1 -1
  150. package/iam-policy/PeopleWithAccess.d.ts +2 -2
  151. package/iam-policy/PeopleWithAccess.d.ts.map +1 -1
  152. package/iam-policy/PeopleWithAccess.js +2 -2
  153. package/iam-policy/PeopleWithAccess.js.map +1 -1
  154. package/iam-policy/PrincipalPicker.d.ts +2 -2
  155. package/iam-policy/PrincipalPicker.d.ts.map +1 -1
  156. package/iam-policy/PrincipalPicker.js +2 -2
  157. package/iam-policy/PrincipalPicker.js.map +1 -1
  158. package/iam-policy/SharePanel.d.ts +3 -3
  159. package/iam-policy/SharePanel.d.ts.map +1 -1
  160. package/iam-policy/SharePanel.js +3 -3
  161. package/iam-policy/SharePanel.js.map +1 -1
  162. package/iam-policy/useCreateIamPolicy.d.ts +1 -1
  163. package/iam-policy/useCreateIamPolicy.js +1 -1
  164. package/iam-policy/useDeleteIamPolicy.d.ts +1 -1
  165. package/iam-policy/useDeleteIamPolicy.js +1 -1
  166. package/iam-policy/useGranteeCandidates.d.ts +3 -3
  167. package/iam-policy/useGranteeCandidates.d.ts.map +1 -1
  168. package/iam-policy/useGranteeCandidates.js +2 -2
  169. package/iam-policy/useGranteeCandidates.js.map +1 -1
  170. package/iam-policy/useOwnerAssignment.d.ts +2 -2
  171. package/iam-policy/useOwnerAssignment.d.ts.map +1 -1
  172. package/iam-policy/useOwnerAssignment.js +3 -3
  173. package/iam-policy/useOwnerAssignment.js.map +1 -1
  174. package/iam-policy/usePrincipalsCount.d.ts +4 -4
  175. package/iam-policy/usePrincipalsCount.d.ts.map +1 -1
  176. package/iam-policy/usePrincipalsCount.js +7 -7
  177. package/iam-policy/usePrincipalsCount.js.map +1 -1
  178. package/iam-policy/useResourceAccess.d.ts +1 -1
  179. package/iam-policy/useResourceAccess.js +1 -1
  180. package/iam-policy/useRevokeOrgAccess.d.ts +1 -1
  181. package/iam-policy/useRevokeOrgAccess.d.ts.map +1 -1
  182. package/iam-policy/useRevokeOrgAccess.js +2 -2
  183. package/iam-policy/useRevokeOrgAccess.js.map +1 -1
  184. package/identity-account/AccountPreferencesPanel.d.ts.map +1 -1
  185. package/identity-account/AccountPreferencesPanel.js +2 -1
  186. package/identity-account/AccountPreferencesPanel.js.map +1 -1
  187. package/identity-provider/IdentityProviderDetailPanel.js +4 -4
  188. package/identity-provider/IdentityProviderDetailPanel.js.map +1 -1
  189. package/identity-provider/IdentityProviderListPanel.d.ts.map +1 -1
  190. package/identity-provider/IdentityProviderListPanel.js +2 -1
  191. package/identity-provider/IdentityProviderListPanel.js.map +1 -1
  192. package/identity-provider/IdentityProviderWizard.js +1 -1
  193. package/identity-provider/IdentityProviderWizard.js.map +1 -1
  194. package/identity-provider/SsoLoginPrompt.js +2 -1
  195. package/identity-provider/SsoLoginPrompt.js.map +1 -1
  196. package/identity-provider/useIdentityProviderList.d.ts +2 -2
  197. package/identity-provider/useIdentityProviderList.js +2 -2
  198. package/index.d.ts +1 -1
  199. package/index.d.ts.map +1 -1
  200. package/index.js +1 -1
  201. package/index.js.map +1 -1
  202. package/inline-edit/InlineEditImage.d.ts +4 -0
  203. package/inline-edit/InlineEditImage.d.ts.map +1 -1
  204. package/inline-edit/InlineEditImage.js +12 -11
  205. package/inline-edit/InlineEditImage.js.map +1 -1
  206. package/inline-edit/InlineEditText.d.ts +4 -0
  207. package/inline-edit/InlineEditText.d.ts.map +1 -1
  208. package/inline-edit/InlineEditText.js +12 -11
  209. package/inline-edit/InlineEditText.js.map +1 -1
  210. package/inline-edit/InlineEditTextarea.d.ts +4 -0
  211. package/inline-edit/InlineEditTextarea.d.ts.map +1 -1
  212. package/inline-edit/InlineEditTextarea.js +11 -16
  213. package/inline-edit/InlineEditTextarea.js.map +1 -1
  214. package/inline-edit/useInlineDraft.d.ts +26 -0
  215. package/inline-edit/useInlineDraft.d.ts.map +1 -0
  216. package/inline-edit/useInlineDraft.js +61 -0
  217. package/inline-edit/useInlineDraft.js.map +1 -0
  218. package/internal/DialogShell.d.ts +21 -0
  219. package/internal/DialogShell.d.ts.map +1 -1
  220. package/internal/DialogShell.js +51 -4
  221. package/internal/DialogShell.js.map +1 -1
  222. package/internal/LoadingRegion.d.ts +35 -0
  223. package/internal/LoadingRegion.d.ts.map +1 -0
  224. package/internal/LoadingRegion.js +33 -0
  225. package/internal/LoadingRegion.js.map +1 -0
  226. package/internal/markdown-components.d.ts.map +1 -1
  227. package/internal/markdown-components.js +18 -4
  228. package/internal/markdown-components.js.map +1 -1
  229. package/internal/trim.d.ts +7 -0
  230. package/internal/trim.d.ts.map +1 -0
  231. package/internal/trim.js +12 -0
  232. package/internal/trim.js.map +1 -0
  233. package/invitation/InvitationManager.d.ts.map +1 -1
  234. package/invitation/InvitationManager.js +2 -1
  235. package/invitation/InvitationManager.js.map +1 -1
  236. package/invitation/InvitationRedemption.d.ts.map +1 -1
  237. package/invitation/InvitationRedemption.js +5 -4
  238. package/invitation/InvitationRedemption.js.map +1 -1
  239. package/invitation/useInvitationPreview.d.ts +1 -1
  240. package/invitation/useInvitationPreview.js +1 -1
  241. package/licenses/LicenseDetail.d.ts.map +1 -1
  242. package/licenses/LicenseDetail.js +3 -3
  243. package/licenses/LicenseDetail.js.map +1 -1
  244. package/licenses/LicenseIssueForm.js +6 -6
  245. package/licenses/LicenseIssueForm.js.map +1 -1
  246. package/licenses/license-draft.d.ts +1 -1
  247. package/licenses/license-draft.d.ts.map +1 -1
  248. package/licenses/license-draft.js +3 -3
  249. package/licenses/license-draft.js.map +1 -1
  250. package/licenses/license-format.js +1 -1
  251. package/licenses/license-format.js.map +1 -1
  252. package/mcp-server/McpServerDetailView.d.ts.map +1 -1
  253. package/mcp-server/McpServerDetailView.js +2 -1
  254. package/mcp-server/McpServerDetailView.js.map +1 -1
  255. package/memory/MemoryListPanel.d.ts.map +1 -1
  256. package/memory/MemoryListPanel.js +2 -1
  257. package/memory/MemoryListPanel.js.map +1 -1
  258. package/oauth-app/OAuthAppListPanel.d.ts.map +1 -1
  259. package/oauth-app/OAuthAppListPanel.js +2 -1
  260. package/oauth-app/OAuthAppListPanel.js.map +1 -1
  261. package/organization/OrgPreferencesPanel.d.ts +3 -3
  262. package/organization/OrgPreferencesPanel.d.ts.map +1 -1
  263. package/organization/OrgPreferencesPanel.js +6 -5
  264. package/organization/OrgPreferencesPanel.js.map +1 -1
  265. package/organization/OrgProfilePanel.d.ts +3 -3
  266. package/organization/OrgProfilePanel.d.ts.map +1 -1
  267. package/organization/OrgProfilePanel.js +8 -7
  268. package/organization/OrgProfilePanel.js.map +1 -1
  269. package/organization/index.d.ts +1 -0
  270. package/organization/index.d.ts.map +1 -1
  271. package/organization/index.js +1 -0
  272. package/organization/index.js.map +1 -1
  273. package/organization/useFollowSessionOrganization.d.ts +9 -0
  274. package/organization/useFollowSessionOrganization.d.ts.map +1 -0
  275. package/organization/useFollowSessionOrganization.js +52 -0
  276. package/organization/useFollowSessionOrganization.js.map +1 -0
  277. package/package.json +5 -5
  278. package/plan-catalog/plan-draft.js +3 -3
  279. package/plan-catalog/plan-draft.js.map +1 -1
  280. package/platform-client/PlatformClientListPanel.d.ts.map +1 -1
  281. package/platform-client/PlatformClientListPanel.js +2 -1
  282. package/platform-client/PlatformClientListPanel.js.map +1 -1
  283. package/plugin/PluginDetailView.d.ts.map +1 -1
  284. package/plugin/PluginDetailView.js +2 -1
  285. package/plugin/PluginDetailView.js.map +1 -1
  286. package/portal-container.d.ts +8 -0
  287. package/portal-container.d.ts.map +1 -1
  288. package/portal-container.js +8 -0
  289. package/portal-container.js.map +1 -1
  290. package/provider.d.ts +4 -1
  291. package/provider.d.ts.map +1 -1
  292. package/provider.js +4 -1
  293. package/provider.js.map +1 -1
  294. package/public-base-url-context.d.ts.map +1 -1
  295. package/public-base-url-context.js +2 -1
  296. package/public-base-url-context.js.map +1 -1
  297. package/schedule/ScheduleDetailView.d.ts.map +1 -1
  298. package/schedule/ScheduleDetailView.js +2 -1
  299. package/schedule/ScheduleDetailView.js.map +1 -1
  300. package/session/SessionViewer.d.ts +7 -2
  301. package/session/SessionViewer.d.ts.map +1 -1
  302. package/session/SessionViewer.js +7 -2
  303. package/session/SessionViewer.js.map +1 -1
  304. package/session/useSessionConversation.d.ts +10 -1
  305. package/session/useSessionConversation.d.ts.map +1 -1
  306. package/session/useSessionConversation.js +5 -3
  307. package/session/useSessionConversation.js.map +1 -1
  308. package/settings/EnvironmentsSection.d.ts.map +1 -1
  309. package/settings/EnvironmentsSection.js +2 -1
  310. package/settings/EnvironmentsSection.js.map +1 -1
  311. package/settings/MembersSection.js +2 -2
  312. package/settings/MembersSection.js.map +1 -1
  313. package/settings/OrgPreferencesSection.js +1 -1
  314. package/settings/OrgPreferencesSection.js.map +1 -1
  315. package/settings/OrgProfileSection.js +1 -1
  316. package/settings/OrgProfileSection.js.map +1 -1
  317. package/settings/TeamsSection.js +1 -1
  318. package/settings/TeamsSection.js.map +1 -1
  319. package/settings/UsageSection.js +1 -1
  320. package/settings/UsageSection.js.map +1 -1
  321. package/sharing/ShareAgentDialog.d.ts.map +1 -1
  322. package/sharing/ShareAgentDialog.js +2 -1
  323. package/sharing/ShareAgentDialog.js.map +1 -1
  324. package/sharing/SharedAgentChat.d.ts.map +1 -1
  325. package/sharing/SharedAgentChat.js +2 -1
  326. package/sharing/SharedAgentChat.js.map +1 -1
  327. package/sidebar/WorkspaceSidebar.d.ts.map +1 -1
  328. package/sidebar/WorkspaceSidebar.js +2 -1
  329. package/sidebar/WorkspaceSidebar.js.map +1 -1
  330. package/skill/SkillDetailView.d.ts.map +1 -1
  331. package/skill/SkillDetailView.js +2 -1
  332. package/skill/SkillDetailView.js.map +1 -1
  333. package/skill/SkillDiffDialog.d.ts.map +1 -1
  334. package/skill/SkillDiffDialog.js +2 -1
  335. package/skill/SkillDiffDialog.js.map +1 -1
  336. package/skill/SkillFileBrowser.d.ts.map +1 -1
  337. package/skill/SkillFileBrowser.js +2 -1
  338. package/skill/SkillFileBrowser.js.map +1 -1
  339. package/src/access/ManageAccessButton.tsx +1 -1
  340. package/src/access/ManageAccessDialog.tsx +1 -1
  341. package/src/agent/AgentDetailView.tsx +4 -4
  342. package/src/api-key/ApiKeyListPanel.tsx +4 -4
  343. package/src/attachment/AttachmentImageLightbox.tsx +3 -4
  344. package/src/billing/AutoRechargeCard.tsx +5 -5
  345. package/src/billing/BillingSection.tsx +10 -9
  346. package/src/billing/CreditLedgerTable.tsx +4 -4
  347. package/src/billing/CreditPackGrid.tsx +1 -1
  348. package/src/billing/PaymentMethodCard.tsx +1 -1
  349. package/src/billing/PlanSection.tsx +6 -5
  350. package/src/billing/ProviderKeysSection.tsx +15 -15
  351. package/src/billing/plan-features.ts +1 -1
  352. package/src/billing/useBillingAccount.ts +7 -7
  353. package/src/billing/useBillingUsageReport.ts +7 -7
  354. package/src/billing/useChangePlan.ts +6 -6
  355. package/src/billing/useCreateBillingPortalSession.ts +4 -4
  356. package/src/billing/useCreateCheckoutSession.ts +3 -3
  357. package/src/billing/useCreatePaymentMethodSetupSession.ts +3 -3
  358. package/src/billing/useCreditLedger.ts +7 -7
  359. package/src/billing/useCustomerModelPricing.ts +7 -7
  360. package/src/billing/useEntitlements.ts +5 -5
  361. package/src/billing/usePeriodEstimate.ts +4 -4
  362. package/src/billing/useProviderKeys.ts +12 -12
  363. package/src/billing/useSetAutoRechargeConfig.ts +3 -3
  364. package/src/billing/useSubscription.ts +7 -7
  365. package/src/channel-app/ChannelAppListPanel.tsx +4 -4
  366. package/src/channel-app/slackAppSetup.ts +3 -2
  367. package/src/channel-app/whatsappAppSetup.ts +2 -1
  368. package/src/cursor-accounts/CursorAccountEditor.tsx +3 -3
  369. package/src/cursor-accounts/CursorAccountsConsole.tsx +5 -5
  370. package/src/dashboard/OperationalDashboard.tsx +1 -6
  371. package/src/dashboard/useDashboardSummary.ts +2 -4
  372. package/src/environment/EnvironmentListPanel.tsx +4 -4
  373. package/src/environment/EnvironmentVariableEditor.tsx +4 -4
  374. package/src/execution/ArtifactFileContent.tsx +3 -2
  375. package/src/execution/McpToolDetail.tsx +3 -3
  376. package/src/execution/ResultView.tsx +3 -3
  377. package/src/execution/TerminalSession.tsx +1 -1
  378. package/src/execution/ThreadSkeleton.tsx +4 -4
  379. package/src/execution/file-path-resolver.ts +3 -2
  380. package/src/execution/sandbox-path-normalizer.ts +2 -1
  381. package/src/github/parseGitUrl.ts +13 -4
  382. package/src/iam-policy/GrantAccessForm.tsx +4 -4
  383. package/src/iam-policy/OrgMembersPanel.tsx +7 -7
  384. package/src/iam-policy/PeopleWithAccess.tsx +3 -3
  385. package/src/iam-policy/PrincipalPicker.tsx +3 -3
  386. package/src/iam-policy/SharePanel.tsx +4 -4
  387. package/src/iam-policy/useCreateIamPolicy.ts +1 -1
  388. package/src/iam-policy/useDeleteIamPolicy.ts +1 -1
  389. package/src/iam-policy/useGranteeCandidates.ts +3 -3
  390. package/src/iam-policy/useOwnerAssignment.ts +3 -3
  391. package/src/iam-policy/usePrincipalsCount.ts +7 -7
  392. package/src/iam-policy/useResourceAccess.ts +1 -1
  393. package/src/iam-policy/useRevokeOrgAccess.ts +3 -3
  394. package/src/identity-account/AccountPreferencesPanel.tsx +4 -4
  395. package/src/identity-provider/IdentityProviderDetailPanel.tsx +3 -9
  396. package/src/identity-provider/IdentityProviderListPanel.tsx +4 -4
  397. package/src/identity-provider/IdentityProviderWizard.tsx +1 -1
  398. package/src/identity-provider/SsoLoginPrompt.tsx +6 -5
  399. package/src/identity-provider/useIdentityProviderList.ts +2 -2
  400. package/src/index.ts +1 -0
  401. package/src/inline-edit/InlineEditImage.tsx +13 -11
  402. package/src/inline-edit/InlineEditText.tsx +13 -11
  403. package/src/inline-edit/InlineEditTextarea.tsx +12 -16
  404. package/src/inline-edit/useInlineDraft.ts +85 -0
  405. package/src/internal/DialogShell.tsx +80 -3
  406. package/src/internal/LoadingRegion.tsx +46 -0
  407. package/src/internal/loading-region-markup.json +71 -0
  408. package/src/internal/markdown-components.tsx +15 -4
  409. package/src/internal/trim.ts +10 -0
  410. package/src/invitation/InvitationManager.tsx +4 -4
  411. package/src/invitation/InvitationRedemption.tsx +7 -7
  412. package/src/invitation/useInvitationPreview.ts +1 -1
  413. package/src/licenses/LicenseDetail.tsx +8 -6
  414. package/src/licenses/LicenseIssueForm.tsx +6 -6
  415. package/src/licenses/license-draft.ts +4 -4
  416. package/src/licenses/license-format.ts +1 -1
  417. package/src/mcp-server/McpServerDetailView.tsx +4 -4
  418. package/src/memory/MemoryListPanel.tsx +4 -4
  419. package/src/oauth-app/OAuthAppListPanel.tsx +4 -4
  420. package/src/organization/OrgPreferencesPanel.tsx +9 -9
  421. package/src/organization/OrgProfilePanel.tsx +12 -12
  422. package/src/organization/index.ts +1 -0
  423. package/src/organization/useFollowSessionOrganization.ts +54 -0
  424. package/src/plan-catalog/plan-draft.ts +3 -3
  425. package/src/platform-client/PlatformClientListPanel.tsx +4 -4
  426. package/src/plugin/PluginDetailView.tsx +3 -2
  427. package/src/portal-container.ts +8 -0
  428. package/src/provider.tsx +4 -1
  429. package/src/public-base-url-context.ts +2 -1
  430. package/src/schedule/ScheduleDetailView.tsx +4 -4
  431. package/src/session/SessionViewer.tsx +13 -3
  432. package/src/session/useSessionConversation.ts +14 -3
  433. package/src/settings/EnvironmentsSection.tsx +3 -2
  434. package/src/settings/MembersSection.tsx +3 -3
  435. package/src/settings/OrgPreferencesSection.tsx +1 -1
  436. package/src/settings/OrgProfileSection.tsx +1 -1
  437. package/src/settings/TeamsSection.tsx +1 -1
  438. package/src/settings/UsageSection.tsx +1 -1
  439. package/src/sharing/ShareAgentDialog.tsx +2 -1
  440. package/src/sharing/SharedAgentChat.tsx +4 -4
  441. package/src/sidebar/WorkspaceSidebar.tsx +3 -2
  442. package/src/skill/SkillDetailView.tsx +4 -4
  443. package/src/skill/SkillDiffDialog.tsx +4 -4
  444. package/src/skill/SkillFileBrowser.tsx +4 -4
  445. package/src/team/TeamDetailPanel.tsx +3 -3
  446. package/src/team/TeamListPanel.tsx +3 -2
  447. package/src/team/TeamMembersPanel.tsx +3 -3
  448. package/src/usage/OrgUsagePanel.tsx +9 -9
  449. package/src/usage/useExportCSV.ts +9 -9
  450. package/src/usage/useOrgUsageReport.ts +7 -7
  451. package/src/version-history/VersionTimeline.tsx +4 -4
  452. package/src/workflow/WorkflowVersionDiffViewer.tsx +4 -4
  453. package/src/workflow/WorkflowVersionTimeline.tsx +4 -4
  454. package/src/workflow/useDiagnoseExecutionFlow.ts +23 -18
  455. package/src/workflow/useExplainWorkflowFlow.ts +7 -3
  456. package/src/workflow/useRefineWorkflowFlow.ts +17 -10
  457. package/src/workflow/useWorkflowArchitectFlow.ts +7 -3
  458. package/src/workspace/ExplorerTree.tsx +4 -8
  459. package/src/workspace/FileViewer.tsx +4 -5
  460. package/styles.css +1 -1
  461. package/team/TeamDetailPanel.d.ts +2 -2
  462. package/team/TeamDetailPanel.d.ts.map +1 -1
  463. package/team/TeamDetailPanel.js +2 -2
  464. package/team/TeamDetailPanel.js.map +1 -1
  465. package/team/TeamListPanel.d.ts.map +1 -1
  466. package/team/TeamListPanel.js +2 -1
  467. package/team/TeamListPanel.js.map +1 -1
  468. package/team/TeamMembersPanel.d.ts +2 -2
  469. package/team/TeamMembersPanel.d.ts.map +1 -1
  470. package/team/TeamMembersPanel.js +2 -2
  471. package/team/TeamMembersPanel.js.map +1 -1
  472. package/usage/OrgUsagePanel.d.ts +3 -3
  473. package/usage/OrgUsagePanel.d.ts.map +1 -1
  474. package/usage/OrgUsagePanel.js +6 -5
  475. package/usage/OrgUsagePanel.js.map +1 -1
  476. package/usage/useExportCSV.d.ts +2 -2
  477. package/usage/useExportCSV.d.ts.map +1 -1
  478. package/usage/useExportCSV.js +9 -9
  479. package/usage/useExportCSV.js.map +1 -1
  480. package/usage/useOrgUsageReport.d.ts +4 -4
  481. package/usage/useOrgUsageReport.d.ts.map +1 -1
  482. package/usage/useOrgUsageReport.js +7 -7
  483. package/usage/useOrgUsageReport.js.map +1 -1
  484. package/version-history/VersionTimeline.d.ts.map +1 -1
  485. package/version-history/VersionTimeline.js +2 -1
  486. package/version-history/VersionTimeline.js.map +1 -1
  487. package/workflow/WorkflowVersionDiffViewer.d.ts.map +1 -1
  488. package/workflow/WorkflowVersionDiffViewer.js +2 -1
  489. package/workflow/WorkflowVersionDiffViewer.js.map +1 -1
  490. package/workflow/WorkflowVersionTimeline.d.ts.map +1 -1
  491. package/workflow/WorkflowVersionTimeline.js +2 -1
  492. package/workflow/WorkflowVersionTimeline.js.map +1 -1
  493. package/workflow/useDiagnoseExecutionFlow.d.ts.map +1 -1
  494. package/workflow/useDiagnoseExecutionFlow.js +23 -18
  495. package/workflow/useDiagnoseExecutionFlow.js.map +1 -1
  496. package/workflow/useExplainWorkflowFlow.d.ts.map +1 -1
  497. package/workflow/useExplainWorkflowFlow.js +7 -3
  498. package/workflow/useExplainWorkflowFlow.js.map +1 -1
  499. package/workflow/useRefineWorkflowFlow.d.ts.map +1 -1
  500. package/workflow/useRefineWorkflowFlow.js +14 -10
  501. package/workflow/useRefineWorkflowFlow.js.map +1 -1
  502. package/workflow/useWorkflowArchitectFlow.d.ts.map +1 -1
  503. package/workflow/useWorkflowArchitectFlow.js +7 -3
  504. package/workflow/useWorkflowArchitectFlow.js.map +1 -1
  505. package/workspace/ExplorerTree.d.ts.map +1 -1
  506. package/workspace/ExplorerTree.js +2 -5
  507. package/workspace/ExplorerTree.js.map +1 -1
  508. package/workspace/FileViewer.d.ts.map +1 -1
  509. package/workspace/FileViewer.js +2 -1
  510. package/workspace/FileViewer.js.map +1 -1
@@ -10,6 +10,7 @@ import { Tooltip, TooltipContent, TooltipTrigger } from "../internal/tooltip.js"
10
10
  import { useIdentityProviderList } from "./useIdentityProviderList.js";
11
11
  import { useDeleteIdentityProvider } from "./useDeleteIdentityProvider.js";
12
12
  import { SpinnerIcon } from "../internal/SpinnerIcon.js";
13
+ import { LoadingRegion } from "../internal/LoadingRegion.js";
13
14
 
14
15
  /** Props for {@link IdentityProviderListPanel}. */
15
16
  export interface IdentityProviderListPanelProps {
@@ -75,10 +76,9 @@ export function IdentityProviderListPanel({
75
76
 
76
77
  if (isLoading) {
77
78
  return (
78
- <div
79
+ <LoadingRegion
79
80
  className={cn("stg:space-y-2", className)}
80
- aria-busy="true"
81
- aria-label="Loading identity providers"
81
+ label="Loading identity providers"
82
82
  >
83
83
  {Array.from({ length: 2 }, (_, i) => (
84
84
  <div
@@ -86,7 +86,7 @@ export function IdentityProviderListPanel({
86
86
  className="stg:bg-muted-subtle stg:h-14 stg:animate-pulse stg:rounded-lg"
87
87
  />
88
88
  ))}
89
- </div>
89
+ </LoadingRegion>
90
90
  );
91
91
  }
92
92
 
@@ -557,7 +557,7 @@ function ReviewStep({
557
557
  value={userinfoEndpoint}
558
558
  onChange={onUserinfoEndpointChange}
559
559
  placeholder="https://example.com/userinfo"
560
- hint="Optional — used to fetch user profile data during token exchange"
560
+ hint="Optional. Read only when Stigmer creates an account from a token with no email claim"
561
561
  disabled={isCreating}
562
562
  />
563
563
 
@@ -186,6 +186,7 @@ function resolvePhase(
186
186
 
187
187
  import { forwardRef, useId } from "react";
188
188
  import { SpinnerIcon } from "../internal/SpinnerIcon.js";
189
+ import { LoadingRegion } from "../internal/LoadingRegion.js";
189
190
 
190
191
  interface OrgInputFormProps {
191
192
  readonly value: string;
@@ -241,16 +242,16 @@ const OrgInputForm = forwardRef<HTMLInputElement, OrgInputFormProps>(
241
242
 
242
243
  function LoadingState({ org }: { org: string }) {
243
244
  return (
244
- <div
245
+ <LoadingRegion
245
246
  className="stg:flex stg:flex-col stg:items-center stg:gap-3 stg:py-4"
246
- aria-busy="true"
247
- aria-label={`Looking up SSO provider for ${org}`}
247
+ label={`Looking up SSO provider for ${org}`}
248
248
  >
249
249
  <SpinnerIcon size={20} className="stg:text-muted-foreground" />
250
- <p className="stg:text-sm stg:text-muted-foreground">
250
+ {/* The hidden label says it in full; this is its short visible form. */}
251
+ <p className="stg:text-sm stg:text-muted-foreground" aria-hidden="true">
251
252
  Looking up <span className="stg:font-medium stg:text-foreground">{org}</span>&hellip;
252
253
  </p>
253
- </div>
254
+ </LoadingRegion>
254
255
  );
255
256
  }
256
257
 
@@ -32,8 +32,8 @@ export interface UseIdentityProviderListReturn {
32
32
  *
33
33
  * @example
34
34
  * ```tsx
35
- * function IdpSettings({ orgId }: { orgId: string }) {
36
- * const { identityProviders, isLoading, error } = useIdentityProviderList(orgId);
35
+ * function IdpSettings({ org }: { org: string }) {
36
+ * const { identityProviders, isLoading, error } = useIdentityProviderList(org);
37
37
  *
38
38
  * if (isLoading) return <Skeleton />;
39
39
  * if (error) return <ErrorMessage error={error} />;
package/src/index.ts CHANGED
@@ -1123,6 +1123,7 @@ export {
1123
1123
  useOrg,
1124
1124
  useActiveOrgSlug,
1125
1125
  useActiveOrgId,
1126
+ useFollowSessionOrganization,
1126
1127
  useOrgGate,
1127
1128
  useOrganization,
1128
1129
  useCreateOrganization,
@@ -1,8 +1,9 @@
1
1
  "use client";
2
2
 
3
- import { useCallback, useEffect, useRef, useState } from "react";
3
+ import { useCallback, useRef, useState } from "react";
4
4
  import { cn } from "@stigmer/theme";
5
5
  import type { InlineEditBaseProps } from "./types.js";
6
+ import { useInlineDraft } from "./useInlineDraft.js";
6
7
 
7
8
  /** Props for {@link InlineEditImage}. */
8
9
  export interface InlineEditImageProps extends InlineEditBaseProps {
@@ -21,6 +22,10 @@ export interface InlineEditImageProps extends InlineEditBaseProps {
21
22
  *
22
23
  * Shows the current image (or fallback icon). On click, reveals
23
24
  * an input for entering a new image URL with confirm/cancel.
25
+ *
26
+ * The draft is seeded from `value` when editing opens. While the editor is
27
+ * open, a draft the user has edited keeps their text if `value` changes, and
28
+ * an untouched draft follows the new `value`.
24
29
  */
25
30
  export function InlineEditImage({
26
31
  value,
@@ -32,18 +37,15 @@ export function InlineEditImage({
32
37
  error,
33
38
  className,
34
39
  }: InlineEditImageProps) {
35
- const [isEditing, setIsEditing] = useState(false);
36
- const [draft, setDraft] = useState(value);
37
40
  const [localError, setLocalError] = useState<string | null>(null);
38
41
  const inputRef = useRef<HTMLInputElement>(null);
42
+ const { isEditing, setIsEditing, draft, setDraft, startEditing } =
43
+ useInlineDraft(value, inputRef);
39
44
 
40
- useEffect(() => {
41
- if (isEditing) {
42
- setDraft(value);
43
- setLocalError(null);
44
- requestAnimationFrame(() => inputRef.current?.focus());
45
- }
46
- }, [isEditing, value]);
45
+ const handleEdit = useCallback(() => {
46
+ setLocalError(null);
47
+ startEditing();
48
+ }, [startEditing]);
47
49
 
48
50
  const handleConfirm = useCallback(async () => {
49
51
  const trimmed = draft.trim();
@@ -81,7 +83,7 @@ export function InlineEditImage({
81
83
  <div className={cn("stg:group/inline-edit stg:inline-flex", className)}>
82
84
  <button
83
85
  type="button"
84
- onClick={() => { if (!disabled) setIsEditing(true); }}
86
+ onClick={() => { if (!disabled) handleEdit(); }}
85
87
  disabled={disabled}
86
88
  className={cn(
87
89
  "stg:relative stg:rounded-md stg:p-0.5 stg:transition-colors",
@@ -1,8 +1,9 @@
1
1
  "use client";
2
2
 
3
- import { useCallback, useEffect, useRef, useState } from "react";
3
+ import { useCallback, useRef, useState } from "react";
4
4
  import { cn } from "@stigmer/theme";
5
5
  import type { InlineEditBaseProps } from "./types.js";
6
+ import { useInlineDraft } from "./useInlineDraft.js";
6
7
 
7
8
  /** Props for {@link InlineEditText}. */
8
9
  export interface InlineEditTextProps extends InlineEditBaseProps {
@@ -24,6 +25,10 @@ export interface InlineEditTextProps extends InlineEditBaseProps {
24
25
  * Displays the value as styled text. On click, transitions to an input
25
26
  * with inline confirm/cancel controls. Confirm triggers `onSave`;
26
27
  * cancel reverts. Escape key also cancels.
28
+ *
29
+ * The draft is seeded from `value` when editing opens. While the editor is
30
+ * open, a draft the user has edited keeps their text if `value` changes, and
31
+ * an untouched draft follows the new `value`.
27
32
  */
28
33
  export function InlineEditText({
29
34
  value,
@@ -36,18 +41,15 @@ export function InlineEditText({
36
41
  error,
37
42
  className,
38
43
  }: InlineEditTextProps) {
39
- const [isEditing, setIsEditing] = useState(false);
40
- const [draft, setDraft] = useState(value);
41
44
  const [localError, setLocalError] = useState<string | null>(null);
42
45
  const inputRef = useRef<HTMLInputElement>(null);
46
+ const { isEditing, setIsEditing, draft, setDraft, startEditing } =
47
+ useInlineDraft(value, inputRef);
43
48
 
44
- useEffect(() => {
45
- if (isEditing) {
46
- setDraft(value);
47
- setLocalError(null);
48
- requestAnimationFrame(() => inputRef.current?.focus());
49
- }
50
- }, [isEditing, value]);
49
+ const handleEdit = useCallback(() => {
50
+ setLocalError(null);
51
+ startEditing();
52
+ }, [startEditing]);
51
53
 
52
54
  const handleConfirm = useCallback(async () => {
53
55
  const trimmed = draft.trim();
@@ -91,7 +93,7 @@ export function InlineEditText({
91
93
  <div className={cn("stg:group/inline-edit", className)}>
92
94
  <button
93
95
  type="button"
94
- onClick={() => { if (!disabled) setIsEditing(true); }}
96
+ onClick={() => { if (!disabled) handleEdit(); }}
95
97
  disabled={disabled}
96
98
  className={cn(
97
99
  "stg:inline-flex stg:w-full stg:items-center stg:gap-1.5 stg:rounded-md stg:px-1.5 stg:py-0.5 stg:text-left stg:transition-colors",
@@ -3,6 +3,7 @@
3
3
  import { useCallback, useEffect, useRef, useState } from "react";
4
4
  import { cn } from "@stigmer/theme";
5
5
  import type { InlineEditBaseProps } from "./types.js";
6
+ import { useInlineDraft } from "./useInlineDraft.js";
6
7
 
7
8
  /** Props for {@link InlineEditTextarea}. */
8
9
  export interface InlineEditTextareaProps extends InlineEditBaseProps {
@@ -23,6 +24,10 @@ export interface InlineEditTextareaProps extends InlineEditBaseProps {
23
24
  *
24
25
  * In read mode, renders the value as preformatted text with expand/collapse.
25
26
  * On click, opens a textarea with confirm/cancel. Ctrl+Enter confirms.
27
+ *
28
+ * The draft is seeded from `value` when editing opens. While the editor is
29
+ * open, a draft the user has edited keeps their text if `value` changes, and
30
+ * an untouched draft follows the new `value`.
26
31
  */
27
32
  export function InlineEditTextarea({
28
33
  value,
@@ -35,24 +40,15 @@ export function InlineEditTextarea({
35
40
  error,
36
41
  className,
37
42
  }: InlineEditTextareaProps) {
38
- const [isEditing, setIsEditing] = useState(false);
39
- const [draft, setDraft] = useState(value);
40
43
  const [localError, setLocalError] = useState<string | null>(null);
41
44
  const textareaRef = useRef<HTMLTextAreaElement>(null);
45
+ const { isEditing, setIsEditing, draft, setDraft, startEditing } =
46
+ useInlineDraft(value, textareaRef, { caretAtEnd: true });
42
47
 
43
- useEffect(() => {
44
- if (isEditing) {
45
- setDraft(value);
46
- setLocalError(null);
47
- requestAnimationFrame(() => {
48
- const ta = textareaRef.current;
49
- if (ta) {
50
- ta.focus();
51
- ta.selectionStart = ta.value.length;
52
- }
53
- });
54
- }
55
- }, [isEditing, value]);
48
+ const handleEdit = useCallback(() => {
49
+ setLocalError(null);
50
+ startEditing();
51
+ }, [startEditing]);
56
52
 
57
53
  // Auto-resize textarea
58
54
  useEffect(() => {
@@ -103,7 +99,7 @@ export function InlineEditTextarea({
103
99
  <div className={cn("stg:group/inline-edit", className)}>
104
100
  <button
105
101
  type="button"
106
- onClick={() => { if (!disabled) setIsEditing(true); }}
102
+ onClick={() => { if (!disabled) handleEdit(); }}
107
103
  disabled={disabled}
108
104
  className={cn(
109
105
  "stg:w-full stg:rounded-md stg:px-2 stg:py-1.5 stg:text-left stg:transition-colors",
@@ -0,0 +1,85 @@
1
+ "use client";
2
+
3
+ /**
4
+ * The draft, focus and caret contract shared by the click-to-edit text
5
+ * editors (`InlineEditText`, `InlineEditTextarea`, `InlineEditImage`), kept in
6
+ * one place so the three cannot drift apart. Internal: not exported from the
7
+ * package.
8
+ *
9
+ * - Opening seeds the draft from the stored value and focuses the field in
10
+ * the commit that shows it, never a frame later, so a selection made right
11
+ * after opening (select-all, then type) is not collapsed afterwards
12
+ * (stigmer/stigmer#1575). A layout effect is used rather than a passive one
13
+ * because, in a browser, a passive effect may run after paint and after the
14
+ * next input.
15
+ * - An untouched draft follows the stored value, so a save never writes a
16
+ * stale copy over a change made elsewhere; once the user edits, the draft
17
+ * is theirs until they save or cancel. The follow is adjusted during render
18
+ * (the `ResizableSplit` idiom), so the field never shows the stale value.
19
+ */
20
+ import { useCallback, useLayoutEffect, useMemo, useState } from "react";
21
+ import type { RefObject } from "react";
22
+
23
+ /** Return value of {@link useInlineDraft}. */
24
+ export interface UseInlineDraftReturn {
25
+ /** `true` while the field is open for editing. */
26
+ readonly isEditing: boolean;
27
+ /** Open or close the field without reseeding the draft. */
28
+ readonly setIsEditing: (editing: boolean) => void;
29
+ /** The text in the field. */
30
+ readonly draft: string;
31
+ /** Replace the text in the field (the user typed, or a control reset it). */
32
+ readonly setDraft: (draft: string) => void;
33
+ /** Open the field with the draft seeded from the stored value. */
34
+ readonly startEditing: () => void;
35
+ }
36
+
37
+ /**
38
+ * Holds an inline editor's open state and draft, and places focus when the
39
+ * field opens (the contract in this module's header).
40
+ *
41
+ * @param value - The stored value.
42
+ * @param fieldRef - The input or textarea shown while editing.
43
+ * @param options.caretAtEnd - Place the caret after the text on opening.
44
+ */
45
+ export function useInlineDraft(
46
+ value: string,
47
+ fieldRef: RefObject<HTMLInputElement | HTMLTextAreaElement | null>,
48
+ options?: { readonly caretAtEnd?: boolean },
49
+ ): UseInlineDraftReturn {
50
+ const caretAtEnd = options?.caretAtEnd ?? false;
51
+ const [isEditing, setIsEditing] = useState(false);
52
+ const [draft, setDraft] = useState(value);
53
+ // The stored value the draft was last seeded from.
54
+ const [seed, setSeed] = useState(value);
55
+
56
+ // An untouched draft follows the stored value (see the module header).
57
+ if (value !== seed) {
58
+ setSeed(value);
59
+ if (draft === seed) setDraft(value);
60
+ }
61
+
62
+ const startEditing = useCallback(() => {
63
+ setDraft(value);
64
+ setSeed(value);
65
+ setIsEditing(true);
66
+ }, [value]);
67
+
68
+ // A layout effect, not a frame later: focus (and the caret) land in the
69
+ // commit that shows the field, before the browser handles the next input.
70
+ useLayoutEffect(() => {
71
+ if (!isEditing) return;
72
+ const field = fieldRef.current;
73
+ if (!field) return;
74
+ field.focus();
75
+ if (caretAtEnd) {
76
+ const end = field.value.length;
77
+ field.setSelectionRange(end, end);
78
+ }
79
+ }, [isEditing, fieldRef, caretAtEnd]);
80
+
81
+ return useMemo(
82
+ () => ({ isEditing, setIsEditing, draft, setDraft, startEditing }),
83
+ [isEditing, draft, startEditing],
84
+ );
85
+ }
@@ -1,8 +1,17 @@
1
1
  "use client";
2
2
 
3
- import { useCallback, useEffect, useRef } from "react";
4
- import type { MouseEvent, ReactNode, SyntheticEvent } from "react";
3
+ import { useCallback, useEffect, useRef, useState } from "react";
4
+ import type {
5
+ KeyboardEvent,
6
+ MouseEvent,
7
+ ReactNode,
8
+ SyntheticEvent,
9
+ } from "react";
5
10
  import { cn } from "@stigmer/theme";
11
+ import {
12
+ PortalContainerContext,
13
+ useStigmerPortalContainer,
14
+ } from "../portal-container.js";
6
15
 
7
16
  /**
8
17
  * Width presets for {@link DialogShell}, mapping to Tailwind `max-w-*`
@@ -79,6 +88,27 @@ export interface DialogShellProps {
79
88
  * escaped the #652 fence, and animation classes present on some dialogs and
80
89
  * missing from others.
81
90
  *
91
+ * Popups opened inside a modal shell render inside it (stigmer#1509). A
92
+ * modal `<dialog>` sits in the browser's top layer and makes the rest of
93
+ * the document inert, so a popover, menu or tooltip portaled into the
94
+ * provider's `document.body` container would paint beneath the dialog and
95
+ * refuse every click. The shell therefore owns an empty portal target as
96
+ * its last child and re-provides it through {@link PortalContainerContext}:
97
+ * every SDK popup below it lands in the top layer with the dialog, themed
98
+ * by ordinary inheritance from the provider's in-tree scope. The target is
99
+ * a zero-size fixed box, so the dialog's own scrolling box never clips a
100
+ * popup that extends past its edge. The target
101
+ * carries no `data-stgm-portal` marker; that selector keeps meaning the one
102
+ * body container. A non-modal shell is in-flow, so it keeps the provider's
103
+ * container.
104
+ *
105
+ * Because those popups now receive keys, Escape pressed while one is open
106
+ * belongs to the popup: Base UI closes it but does not prevent the
107
+ * keydown's default, which is the dialog's own close request. The shell
108
+ * notes, before any popup handler runs, whether its target held a popup,
109
+ * and keeps the dialog open for that one close request; the next Escape
110
+ * closes the dialog.
111
+ *
82
112
  * Internal on purpose — not exported from the package until a host needs it.
83
113
  * The `stigmer/no-handrolled-dialog` lint rule fences new `<dialog>`
84
114
  * elements onto this shell.
@@ -102,6 +132,19 @@ export function DialogShell({
102
132
  "aria-labelledby": ariaLabelledby,
103
133
  }: DialogShellProps) {
104
134
  const dialogRef = useRef<HTMLDialogElement>(null);
135
+ const inheritedPortalContainer = useStigmerPortalContainer();
136
+ // State, not a ref: children must re-render with the element once it
137
+ // mounts. Until then the value is `null`, which Base UI reads as "wait
138
+ // for a container" — no popup flashes into the body first.
139
+ const [portalTarget, setPortalTarget] = useState<HTMLDivElement | null>(
140
+ null,
141
+ );
142
+ // Set while one Escape keydown is in flight and a popup was open when it
143
+ // started; see the doc comment. Cleared by the cancel it guards, or by a
144
+ // task queued at keydown time when the browser sends no cancel (it may
145
+ // skip one for a repeated Escape without user activation), so it can
146
+ // never swallow a later Escape meant for the dialog.
147
+ const escapeClosesPopupRef = useRef(false);
105
148
 
106
149
  // Sync the native top-layer state to the controlled prop. Runs on mount
107
150
  // too, so a shell mounted with `open` already true shows immediately.
@@ -121,11 +164,28 @@ export function DialogShell({
121
164
  const handleCancel = useCallback(
122
165
  (e: SyntheticEvent<HTMLDialogElement>) => {
123
166
  e.preventDefault();
167
+ if (escapeClosesPopupRef.current) {
168
+ escapeClosesPopupRef.current = false;
169
+ return;
170
+ }
124
171
  onOpenChange(false);
125
172
  },
126
173
  [onOpenChange],
127
174
  );
128
175
 
176
+ // Capture phase: runs before the popup's own key handlers, which stop
177
+ // propagation, while the popup is certainly still mounted.
178
+ const handleKeyDownCapture = useCallback(
179
+ (e: KeyboardEvent<HTMLDialogElement>) => {
180
+ if (e.key !== "Escape" || !portalTarget?.hasChildNodes()) return;
181
+ escapeClosesPopupRef.current = true;
182
+ setTimeout(() => {
183
+ escapeClosesPopupRef.current = false;
184
+ }, 0);
185
+ },
186
+ [portalTarget],
187
+ );
188
+
129
189
  // A native close the effect did not perform (e.g. a `method="dialog"`
130
190
  // form submit) must not leave the controlled state stranded open.
131
191
  const handleClose = useCallback(() => {
@@ -146,6 +206,7 @@ export function DialogShell({
146
206
  ref={dialogRef}
147
207
  open={modal ? undefined : open || undefined}
148
208
  onCancel={modal ? handleCancel : undefined}
209
+ onKeyDownCapture={modal ? handleKeyDownCapture : undefined}
149
210
  onClose={modal ? handleClose : undefined}
150
211
  onClick={modal && dismissOnBackdrop ? handleClick : undefined}
151
212
  aria-label={ariaLabel}
@@ -163,7 +224,23 @@ export function DialogShell({
163
224
  className,
164
225
  )}
165
226
  >
166
- {children}
227
+ <PortalContainerContext.Provider
228
+ value={modal ? portalTarget : inheritedPortalContainer}
229
+ >
230
+ {children}
231
+ </PortalContainerContext.Provider>
232
+ {/* A zero-size fixed box at the viewport origin, not an in-flow
233
+ div: a fixed box's containing block is the viewport, so popups
234
+ positioned inside it escape the dialog's own overflow clip (a
235
+ modal dialog scrolls its content) while staying in its top layer.
236
+ An in-flow target left every popup cut off at the dialog's edge
237
+ in Chromium. */}
238
+ {modal && (
239
+ <div
240
+ ref={setPortalTarget}
241
+ className="stg:fixed stg:top-0 stg:left-0 stg:size-0"
242
+ />
243
+ )}
167
244
  </dialog>
168
245
  );
169
246
  }
@@ -0,0 +1,46 @@
1
+ import type { ReactNode } from "react";
2
+
3
+ /**
4
+ * The SDK's container for a labelled loading region: the region a skeleton
5
+ * fills while its data is in flight, marked busy and named for a screen reader
6
+ * without a role. A skeleton with no name needs none of this and stays a bare
7
+ * busy element.
8
+ *
9
+ * Why hidden text, not `aria-label`: a `div` with no role may not take
10
+ * `aria-label` (axe `aria-prohibited-attr`, WCAG 4.1.2), so a labelled
11
+ * skeleton fails any page audit it is on screen for (stigmer/stigmer#1653).
12
+ * Why no role: `status` is what this console's phase badges, empty states and
13
+ * notices carry, and `progressbar` its usage gauge, so a skeleton with either
14
+ * would answer locators meant for them.
15
+ *
16
+ * Why not a live region: a loading placeholder is not news. The content that
17
+ * replaces it is what a screen reader user reads, and an announcement per
18
+ * skeleton would talk over every panel that loads at once.
19
+ *
20
+ * `label` names a wordless skeleton ("Loading sessions"). Leave it out, or
21
+ * empty, when the children already say what is loading in visible text, so a
22
+ * screen reader does not read it twice. The hidden text comes first: the
23
+ * containers space their children with `space-y-*` and `gap-*`, and an
24
+ * absolutely positioned first child changes neither, where a trailing one
25
+ * would give the last placeholder a margin it never had. The
26
+ * `stigmer/require-loading-region` lint rule sends a busy element here when
27
+ * axe would refuse its name, or when it takes role="status".
28
+ *
29
+ * @internal Not part of the public API.
30
+ */
31
+ export function LoadingRegion({
32
+ label,
33
+ className,
34
+ children,
35
+ }: {
36
+ readonly label?: string;
37
+ readonly className?: string;
38
+ readonly children?: ReactNode;
39
+ }) {
40
+ return (
41
+ <div className={className} aria-busy="true">
42
+ {label ? <span className="stg:sr-only">{label}</span> : null}
43
+ {children}
44
+ </div>
45
+ );
46
+ }
@@ -0,0 +1,71 @@
1
+ {
2
+ "$comment": "Which elements axe-core refuses a name on, for the stigmer/require-loading-region lint rule (tools/eslint-plugin-stigmer/rules/require-loading-region.js), which reports a busy, labelled element with no role written when its tag is in namelessElements. Measured, not judged: src/internal/__tests__/a11y/loading-region-markup.browser.test.ts renders every HTML element, busy, labelled, empty and with no role, through axe's aria-prohibited-attr in Chromium, and fails, printing what axe measured, when these lists disagree. Update a list by copying that output.",
3
+ "axeCore": "4.11.4",
4
+ "namelessElements": [
5
+ "abbr",
6
+ "address",
7
+ "b",
8
+ "bdi",
9
+ "bdo",
10
+ "blockquote",
11
+ "br",
12
+ "caption",
13
+ "cite",
14
+ "code",
15
+ "col",
16
+ "colgroup",
17
+ "data",
18
+ "del",
19
+ "div",
20
+ "em",
21
+ "figcaption",
22
+ "hgroup",
23
+ "i",
24
+ "ins",
25
+ "kbd",
26
+ "legend",
27
+ "map",
28
+ "mark",
29
+ "p",
30
+ "picture",
31
+ "pre",
32
+ "q",
33
+ "rt",
34
+ "ruby",
35
+ "s",
36
+ "samp",
37
+ "small",
38
+ "span",
39
+ "strong",
40
+ "sub",
41
+ "sup",
42
+ "time",
43
+ "u",
44
+ "var",
45
+ "wbr"
46
+ ],
47
+ "elementsLeftToAxe": {
48
+ "a": {
49
+ "reason": "an a with an href is a link, which takes a name; the rule cannot see an href passed in a spread",
50
+ "accepted": "<a id=\"probe\" href=\"#x\" aria-busy=\"true\" aria-label=\"Loading\"></a>"
51
+ },
52
+ "td": {
53
+ "reason": "a table cell takes a name inside a table; axe cannot judge one alone",
54
+ "accepted": "<table><tbody><tr><td id=\"probe\" aria-busy=\"true\" aria-label=\"Loading\"></td></tr></tbody></table>"
55
+ },
56
+ "th": {
57
+ "reason": "a header cell takes a name inside a table; axe cannot judge one alone",
58
+ "accepted": "<table><tbody><tr><th id=\"probe\" aria-busy=\"true\" aria-label=\"Loading\"></th></tr></tbody></table>"
59
+ }
60
+ },
61
+ "elementsAxeSkips": {
62
+ "area": "hidden by default",
63
+ "audio": "hidden by default without controls",
64
+ "datalist": "hidden by default",
65
+ "dialog": "hidden until opened",
66
+ "noscript": "not rendered while scripting runs",
67
+ "rp": "hidden by default",
68
+ "template": "inert content",
69
+ "slot": "outside axe's tree"
70
+ }
71
+ }
@@ -97,7 +97,7 @@ export function unwrapEnclosingMarkdownFence(
97
97
  * blank lines only). Group 1 is the heading text; the match spans through the
98
98
  * heading's trailing newline(s) so `body` starts at the first content line.
99
99
  */
100
- const LEADING_H1_RE = /^#[ \t]+(.+?)[ \t]*(?:\r?\n+|$)/;
100
+ const LEADING_H1_MARKER = /^#[ \t]+/;
101
101
 
102
102
  /**
103
103
  * Splits a markdown document into its leading `# H1` title and the remaining
@@ -115,10 +115,21 @@ export function extractLeadingH1(markdown: string): {
115
115
  readonly title: string | null;
116
116
  readonly body: string;
117
117
  } {
118
+ // Read line by line: a single pattern over the heading and the newlines
119
+ // after it backtracks on a long run of spaces.
118
120
  const trimmed = markdown.trim();
119
- const match = LEADING_H1_RE.exec(trimmed);
120
- if (!match) return { title: null, body: markdown };
121
- return { title: match[1], body: trimmed.slice(match[0].length) };
121
+ const lineEnd = trimmed.indexOf("\n");
122
+ const firstLine = lineEnd === -1 ? trimmed : trimmed.slice(0, lineEnd);
123
+ const marker = LEADING_H1_MARKER.exec(firstLine);
124
+ if (!marker) return { title: null, body: markdown };
125
+ const rawTitle = firstLine.slice(marker[0].length).replace(/\r$/, "");
126
+ let titleEnd = rawTitle.length;
127
+ while (titleEnd > 0 && (rawTitle[titleEnd - 1] === " " || rawTitle[titleEnd - 1] === "\t")) titleEnd -= 1;
128
+ const title = rawTitle.slice(0, titleEnd);
129
+ if (title === "") return { title: null, body: markdown };
130
+ let bodyStart = lineEnd === -1 ? trimmed.length : lineEnd + 1;
131
+ while (trimmed[bodyStart] === "\n") bodyStart += 1;
132
+ return { title, body: trimmed.slice(bodyStart) };
122
133
  }
123
134
 
124
135
  /**
@@ -0,0 +1,10 @@
1
+ /**
2
+ * `value` without its trailing run of `char`. A `/x+$/` regex rescans the run
3
+ * from every starting position, so a long run costs quadratic time; this walks
4
+ * it once.
5
+ */
6
+ export function trimTrailing(value: string, char: string): string {
7
+ let end = value.length;
8
+ while (end > 0 && value[end - 1] === char) end -= 1;
9
+ return end === value.length ? value : value.slice(0, end);
10
+ }
@@ -21,6 +21,7 @@ import { RoleSelector } from "../iam-policy/RoleSelector.js";
21
21
  import { useOwnerAssignment } from "../iam-policy/useOwnerAssignment.js";
22
22
  import { SpinnerIcon } from "../internal/SpinnerIcon.js";
23
23
  import { useCopyFeedback } from "../internal/useCopyFeedback.js";
24
+ import { LoadingRegion } from "../internal/LoadingRegion.js";
24
25
 
25
26
  // ---------------------------------------------------------------------------
26
27
  // Public API
@@ -115,10 +116,9 @@ export function InvitationManager({
115
116
 
116
117
  if (isLoading) {
117
118
  return (
118
- <div
119
+ <LoadingRegion
119
120
  className={cn("stg:space-y-2", className)}
120
- aria-busy="true"
121
- aria-label="Loading invitations"
121
+ label="Loading invitations"
122
122
  >
123
123
  {Array.from({ length: 2 }, (_, i) => (
124
124
  <div
@@ -126,7 +126,7 @@ export function InvitationManager({
126
126
  className="stg:bg-muted-subtle stg:h-14 stg:animate-pulse stg:rounded-lg"
127
127
  />
128
128
  ))}
129
- </div>
129
+ </LoadingRegion>
130
130
  );
131
131
  }
132
132