@kortix/ui 0.14.8 → 0.14.9

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 (528) hide show
  1. package/README.md +2 -2
  2. package/dist/_vendor/kortix-shared.js +63 -3
  3. package/dist/_vendor/shared/app-config.d.ts +175 -0
  4. package/dist/_vendor/shared/channel-message.d.ts +34 -5
  5. package/dist/_vendor/shared/index.d.ts +1 -0
  6. package/dist/_vendor/shared/space-slug.d.ts +37 -0
  7. package/dist/access/access/access-detail-shell.js +1 -1
  8. package/dist/access/access/principal-picker.d.ts +11 -0
  9. package/dist/access/access/principal-picker.js +3 -2
  10. package/dist/apps/app-preview-pool.d.ts +7 -2
  11. package/dist/apps/app-preview-pool.js +11 -5
  12. package/dist/apps/app-shared.d.ts +22 -15
  13. package/dist/apps/app-shared.js +37 -19
  14. package/dist/apps/index.d.ts +2 -2
  15. package/dist/apps/index.js +2 -2
  16. package/dist/artifacts/artifact-frame.d.ts +16 -0
  17. package/dist/artifacts/artifact-frame.js +51 -0
  18. package/dist/artifacts/artifact-session.d.ts +18 -0
  19. package/dist/artifacts/artifact-session.js +101 -0
  20. package/dist/artifacts/frame-policy.d.ts +30 -0
  21. package/dist/artifacts/frame-policy.js +61 -0
  22. package/dist/artifacts/index.d.ts +3 -0
  23. package/dist/artifacts/index.js +5 -0
  24. package/dist/browser/sandbox-browser-chrome.d.ts +4 -1
  25. package/dist/browser/sandbox-browser-chrome.js +2 -2
  26. package/dist/customize/agents/agent-grant-pages.d.ts +5 -1
  27. package/dist/customize/agents/agent-grant-pages.js +30 -4
  28. package/dist/customize/agents/agent-page.js +3 -1
  29. package/dist/customize/agents/agent-policy-sets.d.ts +43 -0
  30. package/dist/customize/agents/agent-policy-sets.js +72 -0
  31. package/dist/customize/agents/agent-triggers-section.js +2 -1
  32. package/dist/customize/connectors/add-mcp/add-mcp-server-dialog.d.ts +6 -1
  33. package/dist/customize/connectors/add-mcp/add-mcp-server-dialog.js +10 -4
  34. package/dist/customize/connectors/agent-access.d.ts +35 -0
  35. package/dist/customize/connectors/agent-access.js +77 -0
  36. package/dist/customize/connectors/catalog/browse-sections.d.ts +2 -29
  37. package/dist/customize/connectors/catalog/browse-sections.js +7 -74
  38. package/dist/customize/connectors/catalog/catalog-entry.d.ts +18 -37
  39. package/dist/customize/connectors/catalog/catalog-entry.js +28 -40
  40. package/dist/customize/connectors/catalog/connector-browse.d.ts +3 -32
  41. package/dist/customize/connectors/catalog/connector-browse.js +19 -50
  42. package/dist/customize/connectors/catalog/use-catalog.d.ts +20 -59
  43. package/dist/customize/connectors/catalog/use-catalog.js +48 -175
  44. package/dist/customize/connectors/connector-identity.d.ts +9 -11
  45. package/dist/customize/connectors/connector-identity.js +13 -42
  46. package/dist/customize/connectors/connector-moves-banner.d.ts +2 -1
  47. package/dist/customize/connectors/connector-moves-banner.js +4 -6
  48. package/dist/customize/connectors/connector-routes.d.ts +21 -9
  49. package/dist/customize/connectors/connector-routes.js +29 -20
  50. package/dist/customize/connectors/connectors-page.js +53 -82
  51. package/dist/customize/connectors/detail/app-page.js +226 -98
  52. package/dist/customize/connectors/detail/computer-app-page.d.ts +16 -0
  53. package/dist/customize/connectors/detail/computer-app-page.js +39 -0
  54. package/dist/customize/connectors/detail/connector-accounts.js +3 -1
  55. package/dist/customize/connectors/detail/connector-advanced-tools.d.ts +4 -1
  56. package/dist/customize/connectors/detail/connector-advanced-tools.js +2 -2
  57. package/dist/customize/connectors/detail/connector-agents.d.ts +14 -0
  58. package/dist/customize/connectors/detail/connector-agents.js +69 -0
  59. package/dist/customize/connectors/detail/connector-detail-tabs.js +2 -1
  60. package/dist/customize/connectors/detail/connector-move-row.d.ts +8 -5
  61. package/dist/customize/connectors/detail/connector-move-row.js +23 -14
  62. package/dist/customize/connectors/detail/connector-page.d.ts +4 -1
  63. package/dist/customize/connectors/detail/connector-page.js +14 -10
  64. package/dist/customize/connectors/detail/connector-policy-sets.d.ts +28 -0
  65. package/dist/customize/connectors/detail/connector-policy-sets.js +203 -0
  66. package/dist/customize/connectors/detail/connector-settings.d.ts +4 -1
  67. package/dist/customize/connectors/detail/connector-settings.js +7 -3
  68. package/dist/customize/connectors/detail/connector-status.d.ts +19 -6
  69. package/dist/customize/connectors/detail/connector-status.js +34 -10
  70. package/dist/customize/connectors/detail/connector-tabs.d.ts +4 -1
  71. package/dist/customize/connectors/detail/connector-tabs.js +8 -2
  72. package/dist/customize/connectors/detail/connector-tools.d.ts +3 -3
  73. package/dist/customize/connectors/detail/connector-tools.js +105 -48
  74. package/dist/customize/connectors/detail/email-inboxes.d.ts +43 -0
  75. package/dist/customize/connectors/detail/email-inboxes.js +184 -0
  76. package/dist/customize/connectors/detail/provider-info.d.ts +1 -1
  77. package/dist/customize/connectors/detail/provider-info.js +2 -2
  78. package/dist/customize/connectors/detail/status-badge.d.ts +1 -1
  79. package/dist/customize/connectors/detail/status-badge.js +4 -5
  80. package/dist/customize/connectors/detail/use-connector-detail.d.ts +6 -0
  81. package/dist/customize/connectors/detail/use-connector-detail.js +14 -4
  82. package/dist/customize/connectors/install/install-dialog.d.ts +23 -0
  83. package/dist/customize/connectors/install/install-dialog.js +40 -0
  84. package/dist/customize/connectors/install/install.d.ts +13 -2
  85. package/dist/customize/connectors/install/install.js +9 -4
  86. package/dist/customize/connectors/install/use-install.d.ts +19 -2
  87. package/dist/customize/connectors/install/use-install.js +65 -37
  88. package/dist/customize/connectors/install/way-kind.d.ts +5 -0
  89. package/dist/customize/connectors/install/way-kind.js +16 -0
  90. package/dist/customize/connectors/provider-label.d.ts +2 -1
  91. package/dist/customize/connectors/provider-label.js +13 -3
  92. package/dist/customize/connectors/tools/pattern-rule-draft.d.ts +4 -0
  93. package/dist/customize/connectors/tools/pattern-rule-draft.js +12 -3
  94. package/dist/customize/connectors/tools/policy-sets.d.ts +27 -0
  95. package/dist/customize/connectors/tools/policy-sets.js +41 -0
  96. package/dist/customize/connectors/tools/tool-groups.d.ts +32 -9
  97. package/dist/customize/connectors/tools/tool-groups.js +78 -16
  98. package/dist/customize/connectors/tools/tool-policy-control.d.ts +11 -10
  99. package/dist/customize/connectors/tools/tool-policy-control.js +15 -16
  100. package/dist/customize/connectors/tools/tool-policy-labels.d.ts +6 -5
  101. package/dist/customize/connectors/tools/tool-policy-labels.js +17 -16
  102. package/dist/customize/connectors/tools/tool-policy.d.ts +50 -4
  103. package/dist/customize/connectors/tools/tool-policy.js +74 -8
  104. package/dist/customize/connectors/use-agent-access.d.ts +85 -0
  105. package/dist/customize/connectors/use-agent-access.js +72 -0
  106. package/dist/customize/migrate-to-v2/index.d.ts +1 -2
  107. package/dist/customize/migrate-to-v2/index.js +1 -2
  108. package/dist/customize/migrate-to-v2/migration-prompt.d.ts +12 -25
  109. package/dist/customize/migrate-to-v2/migration-prompt.js +34 -236
  110. package/dist/customize/migrate-to-v2/upgrade-defs.d.ts +1 -1
  111. package/dist/customize/migrate-to-v2/upgrade-defs.js +7 -6
  112. package/dist/customize/migrate-to-v2/upgrade-view.js +7 -7
  113. package/dist/customize/migrate-to-v2/use-run-upgrade.d.ts +3 -3
  114. package/dist/customize/providers/provider-accordion.js +17 -2
  115. package/dist/customize/sections/component/channel-access-panel.d.ts +16 -0
  116. package/dist/customize/sections/component/channel-access-panel.js +146 -0
  117. package/dist/customize/sections/component/channel-connect-hero.d.ts +3 -2
  118. package/dist/customize/sections/component/channel-connect-hero.js +3 -2
  119. package/dist/customize/sections/component/channel-hero-frame.d.ts +31 -0
  120. package/dist/customize/sections/component/channel-hero-frame.js +40 -0
  121. package/dist/customize/sections/component/channel-mocks.d.ts +6 -0
  122. package/dist/customize/sections/component/channel-mocks.js +46 -0
  123. package/dist/customize/sections/component/channel-row.d.ts +13 -3
  124. package/dist/customize/sections/component/channel-row.js +10 -4
  125. package/dist/customize/sections/component/email-connect-form.d.ts +27 -0
  126. package/dist/customize/sections/component/email-connect-form.js +183 -0
  127. package/dist/customize/sections/component/slack-connect-card.d.ts +7 -0
  128. package/dist/customize/sections/component/slack-connect-card.js +2 -3
  129. package/dist/customize/sections/component/teams-connect-card.d.ts +7 -0
  130. package/dist/customize/sections/component/teams-connect-card.js +2 -3
  131. package/dist/customize/sections/component/telegram-channel-row.js +16 -25
  132. package/dist/customize/sections/connectors-view.d.ts +1 -15
  133. package/dist/customize/sections/connectors-view.js +81 -314
  134. package/dist/customize/sections/view/agent-editor-catalog.js +5 -0
  135. package/dist/customize/sections/view/channels-view.d.ts +5 -1
  136. package/dist/customize/sections/view/channels-view.js +61 -75
  137. package/dist/customize/sections/view/gateway/gateway-overview.js +10 -2
  138. package/dist/customize/settings/tabs/experimental-tab.js +35 -16
  139. package/dist/customize/shared/catalog/catalog-empty-state.d.ts +1 -12
  140. package/dist/customize/shared/catalog/catalog-empty-state.js +3 -3
  141. package/dist/customize/shared/channels-switch-dialog.d.ts +18 -0
  142. package/dist/customize/shared/channels-switch-dialog.js +30 -0
  143. package/dist/customize/shared/feature-gate-screen.js +27 -9
  144. package/dist/customize/shared/use-customize-prefetch.d.ts +2 -3
  145. package/dist/customize/shared/use-customize-prefetch.js +9 -27
  146. package/dist/customize/triggers/schedule/post-to-field.d.ts +18 -0
  147. package/dist/customize/triggers/schedule/post-to-field.js +49 -0
  148. package/dist/customize/triggers/schedule/schedule-copy.d.ts +10 -6
  149. package/dist/customize/triggers/schedule/schedule-copy.js +42 -11
  150. package/dist/customize/triggers/schedule/schedule-detail-sheet.js +2 -1
  151. package/dist/customize/triggers/schedule/trigger-composer-logic.d.ts +22 -0
  152. package/dist/customize/triggers/schedule/trigger-composer-logic.js +25 -0
  153. package/dist/customize/triggers/schedule/trigger-composer.d.ts +5 -0
  154. package/dist/customize/triggers/schedule/trigger-composer.js +23 -14
  155. package/dist/customize/triggers/schedule/trigger-edit-logic.js +3 -0
  156. package/dist/customize/triggers/schedule/trigger-filter.js +1 -1
  157. package/dist/customize/triggers/schedule/trigger-runs-logic.d.ts +2 -2
  158. package/dist/customize/triggers/schedule/trigger-runs-panel.js +1 -0
  159. package/dist/customize/triggers/schedule/trigger-toast.js +2 -1
  160. package/dist/customize/triggers/schedule-view.js +5 -2
  161. package/dist/files/index.d.ts +1 -0
  162. package/dist/files/index.js +1 -0
  163. package/dist/files/project/change-request-recovery.d.ts +1 -26
  164. package/dist/files/project/change-request-recovery.js +1 -59
  165. package/dist/files/project/components/change-request-detail-dialog.js +13 -3
  166. package/dist/files/project/components/drive-explorer.js +15 -15
  167. package/dist/files/project/components/drive-toolbar.d.ts +16 -2
  168. package/dist/files/project/components/drive-toolbar.js +14 -5
  169. package/dist/files/project/hooks/use-change-request-recovery.js +3 -19
  170. package/dist/files/project/hooks/use-change-requests.d.ts +1 -0
  171. package/dist/files/project/hooks/use-change-requests.js +11 -2
  172. package/dist/files/renderers/image-frame.d.ts +46 -0
  173. package/dist/files/renderers/image-frame.js +59 -0
  174. package/dist/files/renderers/image-renderer.d.ts +11 -1
  175. package/dist/files/renderers/image-renderer.js +13 -3
  176. package/dist/files/renderers/pdf/pdf-clipboard.d.ts +2 -0
  177. package/dist/files/renderers/pdf/pdf-clipboard.js +21 -0
  178. package/dist/files/renderers/pdf/pdf-viewer.js +4 -2
  179. package/dist/files/renderers/show-content-renderer.d.ts +9 -1
  180. package/dist/files/renderers/show-content-renderer.js +56 -14
  181. package/dist/files/runtime/file-source.js +2 -0
  182. package/dist/files/runtime/hooks/use-binary-blob.d.ts +10 -1
  183. package/dist/files/runtime/hooks/use-binary-blob.js +10 -4
  184. package/dist/files/runtime/hooks/use-shared-image.d.ts +41 -0
  185. package/dist/files/runtime/hooks/use-shared-image.js +177 -0
  186. package/dist/files/viewer/file-content-renderer.d.ts +22 -1
  187. package/dist/files/viewer/file-content-renderer.js +50 -7
  188. package/dist/files/viewer/file-header.d.ts +7 -3
  189. package/dist/files/viewer/file-header.js +20 -11
  190. package/dist/files/viewer/file-preview-modal.d.ts +1 -1
  191. package/dist/files/viewer/file-preview-modal.js +10 -22
  192. package/dist/files/viewer/file-source.d.ts +13 -0
  193. package/dist/files/viewer/use-file-content-state.d.ts +2 -0
  194. package/dist/files/viewer/use-file-content-state.js +28 -10
  195. package/dist/files/viewer/viewer-actions.d.ts +3 -1
  196. package/dist/files/viewer/viewer-actions.js +2 -2
  197. package/dist/hooks/use-media-query.d.ts +1 -0
  198. package/dist/hooks/use-mobile.d.ts +5 -0
  199. package/dist/hooks/use-mobile.js +8 -0
  200. package/dist/i18n/en.d.ts +873 -85
  201. package/dist/i18n/en.js +888 -100
  202. package/dist/i18n/ui-catalog/localize-ui-catalog.js +4 -0
  203. package/dist/i18n/ui-catalog/remaining-ui-translation-keys.generated.js +15 -3
  204. package/dist/index.d.ts +2 -2
  205. package/dist/index.js +2 -2
  206. package/dist/internal/account-hub/account-settings-sidebar.js +1 -1
  207. package/dist/internal/account-hub/hub-sheet.d.ts +9 -1
  208. package/dist/internal/account-hub/hub-sheet.js +21 -5
  209. package/dist/internal/account-hub/sections.d.ts +1 -1
  210. package/dist/internal/account-hub/sections.js +2 -1
  211. package/dist/internal/auth/auth-card-shell.js +3 -3
  212. package/dist/internal/components/agent-mark.js +5 -2
  213. package/dist/internal/connector-logo/connector-logo-source.d.ts +63 -0
  214. package/dist/internal/connector-logo/connector-logo-source.js +48 -0
  215. package/dist/internal/connector-logo/connector-logo.d.ts +39 -0
  216. package/dist/internal/connector-logo/connector-logo.js +56 -0
  217. package/dist/internal/connector-logo/connector-mark-files.d.ts +11 -0
  218. package/dist/internal/connector-logo/connector-mark-files.js +35 -0
  219. package/dist/internal/files/file-read-retry.d.ts +13 -0
  220. package/dist/internal/files/file-read-retry.js +23 -3
  221. package/dist/internal/files/session-drive-files.d.ts +5 -1
  222. package/dist/internal/files/session-drive-files.js +7 -2
  223. package/dist/internal/hooks/channels/use-channels-installations.d.ts +32 -5
  224. package/dist/internal/hooks/channels/use-channels-installations.js +55 -7
  225. package/dist/internal/hooks/channels/use-email-inboxes.d.ts +19 -0
  226. package/dist/internal/hooks/channels/use-email-inboxes.js +48 -0
  227. package/dist/internal/hooks/connectors/use-add-account.js +1 -1
  228. package/dist/internal/hooks/index.d.ts +1 -1
  229. package/dist/internal/hooks/index.js +1 -1
  230. package/dist/internal/hooks/projects/use-new-project-session.d.ts +9 -0
  231. package/dist/internal/hooks/projects/use-new-project-session.js +28 -12
  232. package/dist/internal/hooks/use-auto-scroll.d.ts +8 -1
  233. package/dist/internal/hooks/use-auto-scroll.js +4 -4
  234. package/dist/internal/icons/telegram.d.ts +5 -0
  235. package/dist/internal/icons/telegram.js +6 -1
  236. package/dist/internal/layout/nav-hover-card.d.ts +35 -0
  237. package/dist/internal/layout/nav-hover-card.js +84 -0
  238. package/dist/internal/layout/project-nav-row.d.ts +3 -1
  239. package/dist/internal/layout/project-nav-row.js +3 -2
  240. package/dist/internal/layout/project-page-header.d.ts +4 -2
  241. package/dist/internal/layout/project-page-header.js +4 -3
  242. package/dist/internal/layout/project-settings-nav.js +59 -2
  243. package/dist/internal/lib/browser-error-noise.d.ts +1 -1
  244. package/dist/internal/lib/browser-error-noise.js +1 -1
  245. package/dist/internal/lib/browser-noise/rules/injected-scripts.d.ts +7 -0
  246. package/dist/internal/lib/browser-noise/rules/injected-scripts.js +15 -0
  247. package/dist/internal/lib/manifest-version.d.ts +1 -1
  248. package/dist/internal/lib/manifest-version.js +2 -2
  249. package/dist/internal/lib/memory-href.d.ts +16 -0
  250. package/dist/internal/lib/memory-href.js +46 -0
  251. package/dist/internal/lib/use-project-feature-flags.js +9 -9
  252. package/dist/internal/lib/utils/heic-convert.d.ts +1 -1
  253. package/dist/internal/lib/utils/heic-convert.js +3 -4
  254. package/dist/internal/lib/web-notifications.d.ts +20 -0
  255. package/dist/internal/lib/web-notifications.js +48 -4
  256. package/dist/internal/notifications/notification-bell.d.ts +4 -1
  257. package/dist/internal/notifications/notification-bell.js +2 -2
  258. package/dist/internal/selection/selection-bar.d.ts +2 -1
  259. package/dist/internal/selection/selection-bar.js +1 -1
  260. package/dist/internal/stores/file-preview-store.d.ts +29 -2
  261. package/dist/internal/stores/file-preview-store.js +19 -1
  262. package/dist/internal/stores/kortix-computer-store.js +3 -0
  263. package/dist/internal/stores/sidebar-nav-store.d.ts +1 -1
  264. package/dist/internal/stores/sidebar-nav-store.js +3 -1
  265. package/dist/lib/routes.d.ts +13 -1
  266. package/dist/lib/routes.js +13 -0
  267. package/dist/markdown/index.d.ts +2 -1
  268. package/dist/markdown/index.js +2 -1
  269. package/dist/markdown/setup-links/approval-decision.d.ts +1 -0
  270. package/dist/markdown/setup-links/approval-decision.js +6 -2
  271. package/dist/markdown/setup-links/connector-handshake.d.ts +3 -1
  272. package/dist/markdown/setup-links/connector-handshake.js +12 -10
  273. package/dist/markdown/setup-links/secret-intake-form.d.ts +0 -10
  274. package/dist/markdown/setup-links/secret-intake-form.js +1 -1
  275. package/dist/markdown/setup-links/show-connect-hero.d.ts +28 -0
  276. package/dist/markdown/setup-links/show-connect-hero.js +91 -0
  277. package/dist/markdown/unified-markdown.js +5 -5
  278. package/dist/primitives/badge.d.ts +1 -1
  279. package/dist/primitives/badge.js +2 -0
  280. package/dist/primitives/disclosure.js +14 -2
  281. package/dist/primitives/empty-art.d.ts +12 -0
  282. package/dist/primitives/empty-art.js +11 -0
  283. package/dist/primitives/mermaid-renderer.d.ts +2 -0
  284. package/dist/primitives/mermaid-renderer.js +21 -15
  285. package/dist/primitives/resizable.js +6 -1
  286. package/dist/primitives/resize-seam.d.ts +11 -0
  287. package/dist/primitives/resize-seam.js +12 -0
  288. package/dist/primitives/sidebar-panel.js +4 -7
  289. package/dist/primitives/tabs.d.ts +14 -1
  290. package/dist/primitives/tabs.js +1 -1
  291. package/dist/providers/ui-provider.d.ts +9 -0
  292. package/dist/session/composer/ComposerAboveCard.d.ts +1 -1
  293. package/dist/session/composer/ComposerAboveCard.js +2 -2
  294. package/dist/session/composer/ComposerCard.d.ts +1 -1
  295. package/dist/session/composer/ComposerCard.js +3 -3
  296. package/dist/session/composer/agent-selector.d.ts +13 -1
  297. package/dist/session/composer/agent-selector.js +25 -5
  298. package/dist/session/composer/composer-agent-access.d.ts +15 -0
  299. package/dist/session/composer/composer-agent-access.js +27 -0
  300. package/dist/session/composer/composer-chat-input.d.ts +8 -2
  301. package/dist/session/composer/composer-chat-input.js +8 -6
  302. package/dist/session/composer/composer-logic.d.ts +16 -0
  303. package/dist/session/composer/composer-logic.js +12 -0
  304. package/dist/session/composer/composer-underbar.d.ts +3 -1
  305. package/dist/session/composer/composer-underbar.js +4 -3
  306. package/dist/session/composer/composer.d.ts +15 -1
  307. package/dist/session/composer/composer.js +19 -1
  308. package/dist/session/composer/draft/composer-draft.d.ts +6 -2
  309. package/dist/session/composer/draft/composer-draft.js +5 -1
  310. package/dist/session/composer/reasoning-effort-selector.js +1 -1
  311. package/dist/session/models/chatgpt-connection-button.d.ts +11 -0
  312. package/dist/session/models/chatgpt-connection-button.js +54 -0
  313. package/dist/session/models/model-selector.js +5 -2
  314. package/dist/session/models/use-model-connection-gate.d.ts +5 -5
  315. package/dist/session/models/use-model-connection-gate.js +5 -5
  316. package/dist/session/outcomes/jump-to-outcome.d.ts +10 -0
  317. package/dist/session/outcomes/jump-to-outcome.js +11 -0
  318. package/dist/session/outcomes/session-outcomes-bridge.d.ts +14 -0
  319. package/dist/session/outcomes/session-outcomes-bridge.js +12 -0
  320. package/dist/session/outcomes/session-outcomes-provider.d.ts +3 -1
  321. package/dist/session/outcomes/session-outcomes-provider.js +33 -3
  322. package/dist/session/panel/easy/app-preview.d.ts +10 -0
  323. package/dist/session/panel/easy/app-preview.js +31 -12
  324. package/dist/session/panel/easy/change-requests-card.d.ts +7 -0
  325. package/dist/session/panel/easy/change-requests-card.js +17 -0
  326. package/dist/session/panel/easy/easy-panel-logic.js +7 -1
  327. package/dist/session/panel/easy/easy-panel.js +5 -2
  328. package/dist/session/panel/easy/file-preview.js +1 -1
  329. package/dist/session/panel/easy/outputs-card.d.ts +2 -1
  330. package/dist/session/panel/easy/outputs-card.js +3 -2
  331. package/dist/session/panel/mobile-tool-drawer.js +7 -1
  332. package/dist/session/panel/session-audit-panel.js +9 -2
  333. package/dist/session/panel/session-detail-panel.js +9 -3
  334. package/dist/session/panel/session-files-explorer.d.ts +9 -0
  335. package/dist/session/panel/session-files-explorer.js +12 -3
  336. package/dist/session/panel/session-panel-provider.d.ts +15 -1
  337. package/dist/session/panel/session-panel-provider.js +32 -7
  338. package/dist/session/panel/shared/derive-panels.d.ts +8 -1
  339. package/dist/session/panel/shared/derive-panels.js +12 -2
  340. package/dist/session/panel/shared/output-priority.js +2 -0
  341. package/dist/session/participants/session-participants.d.ts +5 -1
  342. package/dist/session/participants/session-participants.js +9 -2
  343. package/dist/session/prompts/approval-request.d.ts +5 -0
  344. package/dist/session/prompts/approval-request.js +7 -1
  345. package/dist/session/prompts/session-approval-review.d.ts +9 -0
  346. package/dist/session/prompts/session-approval-review.js +18 -0
  347. package/dist/session/status/session-error-banner.js +2 -49
  348. package/dist/session/status/session-starting-loader.d.ts +14 -2
  349. package/dist/session/status/session-starting-loader.js +16 -4
  350. package/dist/session/thread/after-first-prompt.d.ts +7 -0
  351. package/dist/session/thread/after-first-prompt.js +8 -0
  352. package/dist/session/thread/detect-command.d.ts +12 -0
  353. package/dist/session/thread/detect-command.js +20 -0
  354. package/dist/session/thread/session-chat.d.ts +3 -1
  355. package/dist/session/thread/session-chat.js +377 -252
  356. package/dist/session/thread/session-thread.d.ts +3 -1
  357. package/dist/session/thread/session-thread.js +9 -2
  358. package/dist/session/thread/thread-boot-rows.d.ts +36 -0
  359. package/dist/session/thread/thread-boot-rows.js +89 -0
  360. package/dist/session/thread/transcript-rows.d.ts +31 -0
  361. package/dist/session/thread/transcript-rows.js +3 -0
  362. package/dist/session/thread/transcript.d.ts +0 -9
  363. package/dist/session/thread/transcript.js +104 -19
  364. package/dist/session/tool/shared/infrastructure-contexts.d.ts +28 -0
  365. package/dist/session/tool/shared/infrastructure-contexts.js +31 -3
  366. package/dist/session/tool/tool-part-renderer.d.ts +5 -4
  367. package/dist/session/tool/tool-part-renderer.js +8 -3
  368. package/dist/session/tool/tools/bash-tool.js +7 -6
  369. package/dist/session/tool/tools/channel-send-card.d.ts +1 -2
  370. package/dist/session/tool/tools/channel-send.d.ts +2 -1
  371. package/dist/session/tool/tools/codemode-tool.js +1 -1
  372. package/dist/session/tool/tools/connector-tools.js +1 -1
  373. package/dist/session/tool/tools/image-gen-tool.d.ts +1 -1
  374. package/dist/session/tool/tools/image-gen-tool.js +240 -53
  375. package/dist/session/tool/tools/show-tool.js +19 -8
  376. package/dist/session/turn/channel-brand.d.ts +8 -3
  377. package/dist/session/turn/channel-brand.js +20 -4
  378. package/dist/session/turn/message-author.d.ts +8 -0
  379. package/dist/session/turn/message-author.js +24 -0
  380. package/dist/session/turn/message-row.d.ts +52 -0
  381. package/dist/session/turn/message-row.js +44 -0
  382. package/dist/session/turn/plan-anchor.d.ts +1 -1
  383. package/dist/session/turn/plan-anchor.js +1 -1
  384. package/dist/session/turn/user-message.d.ts +7 -1
  385. package/dist/session/turn/user-message.js +21 -7
  386. package/dist/styles.css +1 -1
  387. package/dist/workspace/home/access-requests-bell.d.ts +9 -2
  388. package/dist/workspace/home/access-requests-bell.js +20 -6
  389. package/dist/workspace/home/first-chat.d.ts +8 -21
  390. package/dist/workspace/home/first-chat.js +22 -72
  391. package/dist/workspace/index.d.ts +6 -0
  392. package/dist/workspace/index.js +6 -0
  393. package/dist/workspace/layout/project-home.d.ts +14 -2
  394. package/dist/workspace/layout/project-home.js +60 -21
  395. package/dist/workspace/layout/use-project-home-send.d.ts +9 -1
  396. package/dist/workspace/layout/use-project-home-send.js +82 -3
  397. package/dist/workspace/memory/body-doc.d.ts +17 -0
  398. package/dist/workspace/memory/body-doc.js +208 -0
  399. package/dist/workspace/memory/body-extensions.d.ts +38 -0
  400. package/dist/workspace/memory/body-extensions.js +103 -0
  401. package/dist/workspace/memory/company-memory-page.d.ts +8 -0
  402. package/dist/workspace/memory/company-memory-page.js +16 -0
  403. package/dist/workspace/memory/memory-all.d.ts +20 -0
  404. package/dist/workspace/memory/memory-all.js +27 -0
  405. package/dist/workspace/memory/memory-body.d.ts +19 -0
  406. package/dist/workspace/memory/memory-body.js +139 -0
  407. package/dist/workspace/memory/memory-empty.d.ts +13 -0
  408. package/dist/workspace/memory/memory-empty.js +28 -0
  409. package/dist/workspace/memory/memory-history.d.ts +27 -0
  410. package/dist/workspace/memory/memory-history.js +108 -0
  411. package/dist/workspace/memory/memory-labels.d.ts +16 -0
  412. package/dist/workspace/memory/memory-labels.js +47 -0
  413. package/dist/workspace/memory/memory-page-list.d.ts +34 -0
  414. package/dist/workspace/memory/memory-page-list.js +156 -0
  415. package/dist/workspace/memory/memory-reader.d.ts +58 -0
  416. package/dist/workspace/memory/memory-reader.js +123 -0
  417. package/dist/workspace/memory/memory-view.d.ts +21 -0
  418. package/dist/workspace/memory/memory-view.js +124 -0
  419. package/dist/workspace/memory/remember-popover.d.ts +19 -0
  420. package/dist/workspace/memory/remember-popover.js +61 -0
  421. package/dist/workspace/memory/remember-this.d.ts +12 -0
  422. package/dist/workspace/memory/remember-this.js +89 -0
  423. package/dist/workspace/memory/source-mark.d.ts +18 -0
  424. package/dist/workspace/memory/source-mark.js +79 -0
  425. package/dist/workspace/memory/used-memory-chip.d.ts +14 -0
  426. package/dist/workspace/memory/used-memory-chip.js +61 -0
  427. package/dist/workspace/new/advanced-fields.d.ts +2 -1
  428. package/dist/workspace/new/advanced-fields.js +2 -2
  429. package/dist/workspace/new/source-param.d.ts +1 -1
  430. package/dist/workspace/new/source-param.js +3 -1
  431. package/dist/workspace/new/use-create-workspace.d.ts +8 -10
  432. package/dist/workspace/new/use-create-workspace.js +3 -3
  433. package/dist/workspace/projects/onboarding/app-logo.d.ts +7 -2
  434. package/dist/workspace/projects/onboarding/app-logo.js +6 -13
  435. package/dist/workspace/projects/policies-panel.js +5 -3
  436. package/dist/workspace/review/review-actions.d.ts +4 -2
  437. package/dist/workspace/review/review-actions.js +8 -2
  438. package/dist/workspace/review/review-center.js +11 -7
  439. package/dist/workspace/review/review-detail.d.ts +10 -0
  440. package/dist/workspace/review/review-detail.js +101 -13
  441. package/dist/workspace/saved-session-skeleton.d.ts +2 -2
  442. package/dist/workspace/saved-session-skeleton.js +3 -3
  443. package/dist/workspace/session-workspace.js +15 -13
  444. package/dist/workspace/sessions/project-sessions-view.js +3 -2
  445. package/dist/workspace/sessions/sessions-toolbar.d.ts +3 -1
  446. package/dist/workspace/sessions/sessions-toolbar.js +2 -2
  447. package/dist/workspace/sidebar/footer/project-apps-nav.d.ts +5 -0
  448. package/dist/workspace/sidebar/footer/project-apps-nav.js +41 -2
  449. package/dist/workspace/sidebar/footer/project-artifacts-nav.d.ts +6 -0
  450. package/dist/workspace/sidebar/footer/project-artifacts-nav.js +22 -0
  451. package/dist/workspace/sidebar/footer/project-manifest-upgrade-alert.js +13 -13
  452. package/dist/workspace/sidebar/footer/project-memory-nav.d.ts +7 -0
  453. package/dist/workspace/sidebar/footer/project-memory-nav.js +19 -0
  454. package/dist/workspace/sidebar/nav-row-meta.js +14 -2
  455. package/dist/workspace/sidebar/project-nav-items.js +3 -0
  456. package/dist/workspace/sidebar/project-session-list.js +68 -56
  457. package/dist/workspace/sidebar/project-sidebar.js +9 -2
  458. package/dist/workspace/sidebar/project-spaces-nav.d.ts +8 -0
  459. package/dist/workspace/sidebar/project-spaces-nav.js +69 -0
  460. package/dist/workspace/sidebar/session-group-order.d.ts +9 -0
  461. package/dist/workspace/sidebar/session-group-order.js +25 -0
  462. package/dist/workspace/sidebar/session-group-sections.d.ts +62 -0
  463. package/dist/workspace/sidebar/session-group-sections.js +267 -0
  464. package/dist/workspace/sidebar/session-list-chrome.d.ts +28 -0
  465. package/dist/workspace/sidebar/session-list-chrome.js +50 -0
  466. package/dist/workspace/spaces/channel-glyph.d.ts +5 -0
  467. package/dist/workspace/spaces/channel-glyph.js +6 -0
  468. package/dist/workspace/spaces/channel-setup.d.ts +16 -0
  469. package/dist/workspace/spaces/channel-setup.js +105 -0
  470. package/dist/workspace/spaces/channels-onboarding.d.ts +13 -0
  471. package/dist/workspace/spaces/channels-onboarding.js +37 -0
  472. package/dist/workspace/spaces/create-channel-dialog.d.ts +16 -0
  473. package/dist/workspace/spaces/create-channel-dialog.js +158 -0
  474. package/dist/workspace/spaces/private-channels-not-in.d.ts +9 -0
  475. package/dist/workspace/spaces/private-channels-not-in.js +69 -0
  476. package/dist/workspace/spaces/space-agents.d.ts +10 -0
  477. package/dist/workspace/spaces/space-agents.js +10 -0
  478. package/dist/workspace/spaces/space-details-dialog.d.ts +20 -0
  479. package/dist/workspace/spaces/space-details-dialog.js +176 -0
  480. package/dist/workspace/spaces/space-link-label.d.ts +49 -0
  481. package/dist/workspace/spaces/space-link-label.js +73 -0
  482. package/dist/workspace/spaces/space-links.d.ts +19 -0
  483. package/dist/workspace/spaces/space-links.js +230 -0
  484. package/dist/workspace/spaces/space-members.d.ts +46 -0
  485. package/dist/workspace/spaces/space-members.js +182 -0
  486. package/dist/workspace/spaces/space-roster.d.ts +15 -0
  487. package/dist/workspace/spaces/space-roster.js +44 -0
  488. package/dist/workspace/spaces/space-threads-tab.d.ts +56 -0
  489. package/dist/workspace/spaces/space-threads-tab.js +156 -0
  490. package/dist/workspace/spaces/space-timeline-view.d.ts +254 -0
  491. package/dist/workspace/spaces/space-timeline-view.js +235 -0
  492. package/dist/workspace/spaces/space-timeline.d.ts +106 -0
  493. package/dist/workspace/spaces/space-timeline.js +183 -0
  494. package/dist/workspace/spaces/space-triggers.d.ts +13 -0
  495. package/dist/workspace/spaces/space-triggers.js +78 -0
  496. package/dist/workspace/spaces/space-view.d.ts +37 -0
  497. package/dist/workspace/spaces/space-view.js +436 -0
  498. package/package.json +27 -36
  499. package/skills/kortix-ui/SKILL.md +3 -3
  500. package/skills/kortix-ui/references/custom-dashboard.md +3 -3
  501. package/skills/kortix-ui/references/modules.md +28 -4
  502. package/skills/kortix-ui/references/theming.md +1 -1
  503. package/dist/customize/connectors/catalog/merge-search.d.ts +0 -10
  504. package/dist/customize/connectors/catalog/merge-search.js +0 -26
  505. package/dist/customize/connectors/detail/find-easy-connect-app.d.ts +0 -29
  506. package/dist/customize/connectors/detail/find-easy-connect-app.js +0 -22
  507. package/dist/customize/migrate-to-v2/use-migrate-to-v2.d.ts +0 -9
  508. package/dist/customize/migrate-to-v2/use-migrate-to-v2.js +0 -24
  509. package/dist/customize/sections/connector-connection-header.d.ts +0 -36
  510. package/dist/customize/sections/connector-connection-header.js +0 -33
  511. package/dist/customize/sections/connector-connection-modal.d.ts +0 -34
  512. package/dist/customize/sections/connector-connection-modal.js +0 -72
  513. package/dist/customize/sections/discover-catalogue-card.d.ts +0 -19
  514. package/dist/customize/sections/discover-catalogue-card.js +0 -26
  515. package/dist/customize/sections/discover-catalogue-detail.d.ts +0 -15
  516. package/dist/customize/sections/discover-catalogue-detail.js +0 -24
  517. package/dist/customize/sections/discover-catalogue.d.ts +0 -17
  518. package/dist/customize/sections/discover-catalogue.js +0 -132
  519. package/dist/customize/sections/llm-provider/provider-access-menu.d.ts +0 -10
  520. package/dist/customize/sections/llm-provider/provider-access-menu.js +0 -23
  521. package/dist/files/project/components/drive-empty-art.d.ts +0 -2
  522. package/dist/files/project/components/drive-empty-art.js +0 -5
  523. package/dist/internal/hooks/use-media-query.d.ts +0 -2
  524. package/dist/internal/share/public-share-link-button.d.ts +0 -14
  525. package/dist/internal/share/public-share-link-button.js +0 -17
  526. package/dist/markdown/setup-links/app-credentials-form.d.ts +0 -12
  527. package/dist/markdown/setup-links/app-credentials-form.js +0 -115
  528. /package/dist/{internal/hooks → hooks}/use-media-query.js +0 -0
@@ -0,0 +1,158 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { ApiError } from '@kortix/sdk';
4
+ import { useCreateProjectSpace, usePrivateChannelsAvailable, useUpdateProjectSpace } from '@kortix/sdk/react';
5
+ import { spaceSlug } from '../../_vendor/kortix-shared.js';
6
+ import { LockSimpleIcon } from '@phosphor-icons/react';
7
+ import { useId, useState } from 'react';
8
+ import { useTranslations } from '../../i18n/index.js';
9
+ import { uiRoutes } from '../../lib/routes.js';
10
+ import { Button } from '../../primitives/button.js';
11
+ import { Field, FieldDescription, FieldGroup, FieldLabel } from '../../primitives/field.js';
12
+ import { Input } from '../../primitives/input.js';
13
+ import { Switch } from '../../primitives/switch.js';
14
+ import Loading from '../../primitives/loading.js';
15
+ import { Modal, ModalBody, ModalContent, ModalDescription, ModalFooter, ModalHeader, ModalTitle, } from '../../primitives/modal.js';
16
+ import { useOptionalSidebar } from '../../primitives/sidebar.js';
17
+ import { successToast } from '../../primitives/toast.js';
18
+ import { UiLink as Link, useUiRouter } from '../../providers/ui-provider.js';
19
+ /** The API accepts up to 80; the slug keeps the first 40 slug characters. */
20
+ const NAME_MAX = 80;
21
+ const DESCRIPTION_MAX = 160;
22
+ /**
23
+ * "Create a channel": a name with a live `#slug` preview, an optional
24
+ * description and "Private" (only the people added to it see it), shown
25
+ * only where the spaces list says `private_channels_available`. Every error stays in the dialog (the SDK call does not toast).
26
+ * On success the dialog closes and the new channel opens.
27
+ *
28
+ * With `space` it renames that channel instead: the same fields, filled in,
29
+ * and the page follows the new slug.
30
+ */
31
+ export function CreateChannelDialog({ projectId, open, onOpenChange, space, }) {
32
+ const t = useTranslations('spaces.create');
33
+ const tI18nComplete = useTranslations('hardcodedUi.i18nComplete');
34
+ const id = useId();
35
+ const router = useUiRouter();
36
+ const sidebar = useOptionalSidebar();
37
+ const create = useCreateProjectSpace(projectId);
38
+ const update = useUpdateProjectSpace(projectId);
39
+ const pending = create.isPending || update.isPending;
40
+ const [name, setName] = useState('');
41
+ const [description, setDescription] = useState('');
42
+ const [isPrivate, setIsPrivate] = useState(false);
43
+ // "Private" shows only where the server allows it.
44
+ const privateAvailable = usePrivateChannelsAvailable(projectId).data === true;
45
+ const [error, setError] = useState(null);
46
+ // A rename opens on the channel's current name and description (set while
47
+ // rendering, the moment it opens, so the first frame already shows them).
48
+ const fillFor = open && space ? space.space_id : null;
49
+ const [filledFor, setFilledFor] = useState(null);
50
+ if (fillFor !== filledFor) {
51
+ setFilledFor(fillFor);
52
+ if (space && fillFor) {
53
+ setName(space.name);
54
+ setDescription(space.description ?? '');
55
+ }
56
+ }
57
+ const slug = spaceSlug(name);
58
+ // A manager outside a private channel renames it and nothing else (D1), from the private-channel list.
59
+ const nameOnly = space?.visibility === 'private' && space.is_member === false;
60
+ const close = () => {
61
+ if (pending)
62
+ return;
63
+ setName('');
64
+ setDescription('');
65
+ setIsPrivate(false);
66
+ setError(null);
67
+ onOpenChange(false);
68
+ };
69
+ const onError = (err) => {
70
+ if (err instanceof ApiError && err.status === 409 && err.code === 'slug_taken') {
71
+ const archivedId = err.data?.archived === true && typeof err.data.space_id === 'string' ? err.data.space_id : null;
72
+ setError({ kind: 'taken', slug, archivedId, canEdit: err.data?.can_edit !== false });
73
+ }
74
+ else if (err instanceof ApiError && err.status === 400 && err.code === 'invalid_name') {
75
+ setError({ kind: 'invalid' });
76
+ }
77
+ else if (err instanceof ApiError && err.status === 409 && err.code === 'private_channels_unavailable') {
78
+ setError({ kind: 'unavailable' });
79
+ }
80
+ else {
81
+ setError({ kind: 'failed' });
82
+ }
83
+ };
84
+ const submit = () => {
85
+ if (pending)
86
+ return;
87
+ if (!name.trim())
88
+ return setError({ kind: 'empty' });
89
+ if (!slug)
90
+ return setError({ kind: 'invalid' });
91
+ const done = (saved) => {
92
+ setName('');
93
+ setDescription('');
94
+ setIsPrivate(false);
95
+ setError(null);
96
+ onOpenChange(false);
97
+ const href = uiRoutes().channel(projectId, saved.slug ?? slug);
98
+ if (space) {
99
+ successToast(t('renamed'));
100
+ if (saved.slug !== space.slug && !nameOnly)
101
+ router.replace(href);
102
+ return;
103
+ }
104
+ successToast(t('created'));
105
+ // On a phone the dialog opens from the sidebar sheet: close it so the channel shows.
106
+ sidebar?.setOpenMobile(false);
107
+ router.push(href);
108
+ };
109
+ if (space) {
110
+ update.mutate({
111
+ spaceId: space.space_id,
112
+ input: {
113
+ name: name.trim(),
114
+ // Only a changed description is sent.
115
+ ...(description.trim() !== (space.description ?? '') ? { description: description.trim() || null } : {}),
116
+ },
117
+ }, { onSuccess: done, onError });
118
+ return;
119
+ }
120
+ create.mutate({
121
+ name: name.trim(),
122
+ ...(description.trim() ? { description: description.trim() } : {}),
123
+ ...(isPrivate ? { visibility: 'private' } : {}),
124
+ }, { onSuccess: done, onError });
125
+ };
126
+ let errorText = null;
127
+ if (error?.kind === 'empty')
128
+ errorText = t('nameRequired');
129
+ else if (error?.kind === 'invalid')
130
+ errorText = t('invalidName');
131
+ else if (error?.kind === 'failed')
132
+ errorText = t(space ? 'renameFailed' : 'failed');
133
+ else if (error?.kind === 'unavailable')
134
+ errorText = t('privateUnavailable');
135
+ else if (error?.kind === 'taken') {
136
+ const { slug: takenSlug, archivedId, canEdit } = error;
137
+ // An archived channel's page offers Unarchive when it knows the channel's id
138
+ // and the caller may edit the channel; otherwise it says who may.
139
+ const takenHref = uiRoutes().channel(projectId, takenSlug);
140
+ const archivedQuery = archivedId ? `?archived=${encodeURIComponent(archivedId)}${canEdit ? '' : '&locked=1'}` : '';
141
+ errorText = t.rich('slugTaken', {
142
+ slug: takenSlug,
143
+ link: (chunks) => (_jsx(Link, { href: `${takenHref}${archivedQuery}`, onClick: close, className: "text-foreground underline underline-offset-4", children: chunks })),
144
+ });
145
+ }
146
+ return (_jsx(Modal, { open: open, onOpenChange: (next) => !next && close(), children: _jsxs(ModalContent, { className: "lg:max-w-md", children: [_jsxs(ModalHeader, { children: [_jsx(ModalTitle, { children: t(space ? 'renameTitle' : 'title') }), _jsx(ModalDescription, { children: t(space ? 'renameDescription' : isPrivate ? 'descriptionPrivate' : 'description') })] }), _jsxs("form", { onSubmit: (event) => {
147
+ event.preventDefault();
148
+ submit();
149
+ }, children: [_jsx(ModalBody, { children: _jsxs(FieldGroup, { className: "gap-5", children: [_jsxs(Field, { className: "gap-1.5", children: [_jsx(FieldLabel, { htmlFor: `${id}-name`, children: t('nameLabel') }), _jsx(Input, { id: `${id}-name`, autoComplete: "off", spellCheck: false, autoFocus: true, value: name, maxLength: NAME_MAX, placeholder: t('namePlaceholder'), "aria-invalid": error && error.kind !== 'failed' && error.kind !== 'unavailable' ? true : undefined, "aria-describedby": `${id}-name-hint`, onChange: (event) => {
150
+ setName(event.target.value);
151
+ if (error)
152
+ setError(null);
153
+ } }), _jsxs(FieldDescription, { id: `${id}-name-hint`, className: error ? 'text-destructive' : 'font-mono', children: [_jsx("span", { "aria-live": "polite", children: errorText }), errorText ? null : `#${slug || t('slugPlaceholder')}`] })] }), nameOnly ? null : _jsxs(Field, { className: "gap-1.5", children: [_jsx(FieldLabel, { htmlFor: `${id}-description`, children: t('descriptionLabel') }), _jsx(Input, { id: `${id}-description`, autoComplete: "off", value: description, maxLength: DESCRIPTION_MAX, placeholder: t('descriptionPlaceholder'), onChange: (event) => setDescription(event.target.value) })] }), space || !privateAvailable ? null : (_jsxs(Field, { orientation: "horizontal", className: "items-start justify-between gap-4", children: [_jsxs("div", { className: "min-w-0 space-y-0.5", children: [_jsxs(FieldLabel, { htmlFor: `${id}-private`, className: "flex items-center gap-1.5", children: [_jsx(LockSimpleIcon, { className: "size-3.5 shrink-0" }), t('privateLabel')] }), _jsxs(FieldDescription, { id: `${id}-private-hint`, children: [t('privateHint'), " ", t('privateLimits')] })] }), _jsx(Switch, { id: `${id}-private`, checked: isPrivate, "aria-describedby": `${id}-private-hint`, onCheckedChange: (next) => {
154
+ setIsPrivate(next);
155
+ if (error?.kind === 'unavailable')
156
+ setError(null);
157
+ }, disabled: pending, className: "mt-0.5 shrink-0" })] }))] }) }), _jsxs(ModalFooter, { className: "sm:justify-between", children: [_jsx(Button, { type: "button", variant: "outline-ghost", onClick: close, disabled: pending, children: tI18nComplete.raw('text19766ed6ccb2') }), _jsxs(Button, { type: "submit", disabled: pending, "aria-busy": pending || undefined, children: [pending ? _jsx(Loading, { className: "size-4 shrink-0" }) : null, t(space ? 'save' : 'submit')] })] })] })] }) }));
158
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Project managers only: a quiet sidebar row under Channels that opens the
3
+ * private channels they are not in (owner decision D1). They rename, archive
4
+ * and add people there, never read the channel. A channel its last member left
5
+ * is recovered here. Hidden for everyone else and when there is none.
6
+ */
7
+ export declare function PrivateChannelsNotInRow({ projectId }: {
8
+ projectId: string;
9
+ }): import("react").JSX.Element | null;
@@ -0,0 +1,69 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { usePrivateChannelsNotIn, useUpdateProjectSpace } from '@kortix/sdk/react';
4
+ import { DotsThreeIcon, LockSimpleIcon } from '@phosphor-icons/react';
5
+ import { useState } from 'react';
6
+ import { useTranslations } from '../../i18n/index.js';
7
+ import { PROJECT_ACTIONS } from '../../internal/lib/project-actions.js';
8
+ import { useProjectCan } from '../../internal/lib/use-project-can.js';
9
+ import { Badge } from '../../primitives/badge.js';
10
+ import { Button } from '../../primitives/button.js';
11
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '../../primitives/dropdown-menu.js';
12
+ import { Modal, ModalBody, ModalContent, ModalDescription, ModalHeader, ModalTitle } from '../../primitives/modal.js';
13
+ import { SidebarMenuButton, SidebarMenuItem } from '../../primitives/sidebar.js';
14
+ import { errorToast, successToast } from '../../primitives/toast.js';
15
+ import { CreateChannelDialog } from './create-channel-dialog.js';
16
+ import { AddChannelMembersDialog } from './space-members.js';
17
+ /**
18
+ * The channel as the rename and add-people dialogs read it. A manager outside
19
+ * it is not a member and may not edit its agents or description (D1).
20
+ */
21
+ function asSpace(channel) {
22
+ return {
23
+ space_id: channel.space_id,
24
+ kind: 'channel',
25
+ slug: channel.slug,
26
+ name: channel.name,
27
+ description: null,
28
+ is_default: false,
29
+ dm_agent_name: null,
30
+ archived_at: channel.archived_at,
31
+ created_at: channel.created_at,
32
+ updated_at: channel.created_at,
33
+ can_edit: false,
34
+ agents: [],
35
+ is_member: false,
36
+ visibility: 'private',
37
+ };
38
+ }
39
+ /**
40
+ * Project managers only: a quiet sidebar row under Channels that opens the
41
+ * private channels they are not in (owner decision D1). They rename, archive
42
+ * and add people there, never read the channel. A channel its last member left
43
+ * is recovered here. Hidden for everyone else and when there is none.
44
+ */
45
+ export function PrivateChannelsNotInRow({ projectId }) {
46
+ const t = useTranslations('spaces.privateNotIn');
47
+ const manager = useProjectCan(projectId, PROJECT_ACTIONS.PROJECT_MEMBERS_MANAGE).allowed === true;
48
+ const list = usePrivateChannelsNotIn(projectId, { enabled: manager });
49
+ const [open, setOpen] = useState(false);
50
+ const channels = list.data ?? [];
51
+ if (!manager || channels.length === 0)
52
+ return null;
53
+ return (_jsxs(_Fragment, { children: [_jsx(SidebarMenuItem, { children: _jsxs(SidebarMenuButton, { onClick: () => setOpen(true), className: "text-muted-foreground hover:text-sidebar-foreground", children: [_jsx(LockSimpleIcon, {}), _jsx("span", { className: "truncate", children: t('row') }), _jsx("span", { className: "ml-auto text-xs tabular-nums", children: channels.length })] }) }), _jsx(Modal, { open: open, onOpenChange: setOpen, children: _jsxs(ModalContent, { className: "lg:max-w-md", children: [_jsxs(ModalHeader, { children: [_jsx(ModalTitle, { children: t('title') }), _jsx(ModalDescription, { children: t('description') })] }), _jsx(ModalBody, { className: "space-y-px", children: channels.map((channel) => (_jsx(PrivateChannelRow, { projectId: projectId, channel: channel }, channel.space_id))) })] }) })] }));
54
+ }
55
+ function PrivateChannelRow({ projectId, channel }) {
56
+ const t = useTranslations('spaces.privateNotIn');
57
+ const update = useUpdateProjectSpace(projectId);
58
+ const [renaming, setRenaming] = useState(false);
59
+ const [adding, setAdding] = useState(false);
60
+ const space = asSpace(channel);
61
+ const archived = channel.archived_at !== null;
62
+ const setArchived = (next) => update.mutate({ spaceId: channel.space_id, input: { archived: next } }, {
63
+ onSuccess: () => successToast(t(next ? 'archivedToast' : 'unarchivedToast', { name: channel.slug })),
64
+ onError: () => errorToast(t('failed', { name: channel.slug })),
65
+ });
66
+ return (_jsxs("div", { className: "flex items-center gap-3 rounded-md px-2 py-2", children: [_jsx(LockSimpleIcon, { className: "text-muted-foreground size-4 shrink-0" }), _jsxs("div", { className: "min-w-0 flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("span", { className: "truncate text-sm font-medium", children: channel.slug }), archived ? _jsx(Badge, { variant: "secondary", children: t('archived') }) : null] }), _jsx("p", { className: "text-muted-foreground truncate text-xs", children: channel.created_by_name
67
+ ? t('meta', { count: channel.member_count, name: channel.created_by_name })
68
+ : t('metaNoCreator', { count: channel.member_count }) })] }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon-sm", className: "text-muted-foreground shrink-0", "aria-label": t('menu', { name: channel.slug }), disabled: update.isPending, children: _jsx(DotsThreeIcon, { className: "size-4" }) }) }), _jsxs(DropdownMenuContent, { align: "end", children: [archived ? null : _jsx(DropdownMenuItem, { onSelect: () => setAdding(true), children: t('addPeople') }), _jsx(DropdownMenuItem, { onSelect: () => setRenaming(true), children: t('rename') }), _jsx(DropdownMenuItem, { onSelect: () => setArchived(!archived), children: t(archived ? 'unarchive' : 'archive') })] })] }), _jsx(CreateChannelDialog, { projectId: projectId, open: renaming, onOpenChange: setRenaming, space: space }), _jsx(AddChannelMembersDialog, { projectId: projectId, space: space, open: adding, onOpenChange: setAdding })] }));
69
+ }
@@ -0,0 +1,10 @@
1
+ import type { ProjectSpace } from '@kortix/sdk';
2
+ /**
3
+ * The channel's agents the project still offers, in the channel's order: the
4
+ * first is the default a new thread starts on. Empty when the channel has no
5
+ * agent list (then the project's default applies, as before).
6
+ */
7
+ export declare function offeredChannelAgents(space: Pick<ProjectSpace, 'agents'> | null | undefined, offered: readonly {
8
+ name: string;
9
+ }[]): string[];
10
+ export { channelRunnableAgents } from '../../session/composer/composer-agent-access.js';
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The channel's agents the project still offers, in the channel's order: the
3
+ * first is the default a new thread starts on. Empty when the channel has no
4
+ * agent list (then the project's default applies, as before).
5
+ */
6
+ export function offeredChannelAgents(space, offered) {
7
+ const names = new Set(offered.map((agent) => agent.name));
8
+ return (space?.agents ?? []).filter((name) => names.has(name));
9
+ }
10
+ export { channelRunnableAgents } from '../../session/composer/composer-agent-access.js';
@@ -0,0 +1,20 @@
1
+ import { type ProjectSpace } from '@kortix/sdk';
2
+ export type SpaceDetailsTab = 'about' | 'members';
3
+ /**
4
+ * A channel's details, opened from `# name` in the header or the roster's
5
+ * "View all members": About (name, description, default agent, who can see
6
+ * it, when it was made, Leave, Archive) and Members (one list of its people,
7
+ * then its agents). The pencils, Archive and the agent row menus show only
8
+ * to the channel's creator or a project manager (`can_edit`). "Add members"
9
+ * shows to whoever may add people (`can_add`: a member, the creator, a
10
+ * manager) or edit the channel; its picker offers each only what they may add.
11
+ */
12
+ export declare function SpaceDetailsDialog({ space, tab, onTabChange, onOpenChange, onEdit, onArchive, }: {
13
+ space: ProjectSpace;
14
+ /** Null: closed. */
15
+ tab: SpaceDetailsTab | null;
16
+ onTabChange: (tab: SpaceDetailsTab) => void;
17
+ onOpenChange: (open: boolean) => void;
18
+ onEdit: () => void;
19
+ onArchive: () => void;
20
+ }): import("react").JSX.Element;
@@ -0,0 +1,176 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { getProjectDetail } from '@kortix/sdk';
4
+ import { contract, qk, useLeaveProjectSpace, usePrivateChannelsAvailable, useProjectSpaceMembers, useProjectTriggers, useRemoveProjectSpaceMember, useUpdateProjectSpace, } from '@kortix/sdk/react';
5
+ import { DotsThreeIcon, MagnifyingGlassIcon, PencilSimpleIcon, PlusIcon } from '@phosphor-icons/react';
6
+ import { useQuery } from '@tanstack/react-query';
7
+ import { useMemo, useState } from 'react';
8
+ import { useLocale, useTranslations } from '../../i18n/index.js';
9
+ import { AgentMark } from '../../internal/components/agent-mark.js';
10
+ import { Button } from '../../primitives/button.js';
11
+ import { ConfirmDialog } from '../../primitives/confirm-dialog.js';
12
+ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from '../../primitives/dropdown-menu.js';
13
+ import Hint from '../../primitives/hint.js';
14
+ import { InputGroupSearch, InputGroupSearchClear, InputGroupSearchIcon, InputGroupSearchInput, } from '../../primitives/input-group.js';
15
+ import { Modal, ModalBody, ModalContent, ModalHeader, ModalTitle } from '../../primitives/modal.js';
16
+ import Loading from '../../primitives/loading.js';
17
+ import { Skeleton } from '../../primitives/skeleton.js';
18
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from '../../primitives/tabs.js';
19
+ import { errorToast, successToast } from '../../primitives/toast.js';
20
+ import { useSessionIds } from '../../providers/session-ids.js';
21
+ import { ChannelGlyph } from './channel-glyph.js';
22
+ import { AddChannelMembersDialog, MemberAvatar } from './space-members.js';
23
+ import { agentLabel } from './space-timeline.js';
24
+ /**
25
+ * A channel's details, opened from `# name` in the header or the roster's
26
+ * "View all members": About (name, description, default agent, who can see
27
+ * it, when it was made, Leave, Archive) and Members (one list of its people,
28
+ * then its agents). The pencils, Archive and the agent row menus show only
29
+ * to the channel's creator or a project manager (`can_edit`). "Add members"
30
+ * shows to whoever may add people (`can_add`: a member, the creator, a
31
+ * manager) or edit the channel; its picker offers each only what they may add.
32
+ */
33
+ export function SpaceDetailsDialog({ space, tab, onTabChange, onOpenChange, onEdit, onArchive, }) {
34
+ const t = useTranslations('spaces.details');
35
+ const { projectId } = useSessionIds();
36
+ const [adding, setAdding] = useState(false);
37
+ return (_jsxs(_Fragment, { children: [_jsx(Modal, { open: tab !== null, onOpenChange: onOpenChange, children: _jsxs(ModalContent, { className: "lg:max-w-md", children: [_jsx(ModalHeader, { children: _jsxs(ModalTitle, { className: "flex min-w-0 items-center gap-1", children: [_jsx(ChannelGlyph, { visibility: space.visibility, className: "size-4 shrink-0" }), _jsx("span", { className: "truncate", children: space.slug })] }) }), _jsxs(Tabs, { value: tab ?? 'about', onValueChange: (value) => onTabChange(value), className: "gap-0", children: [_jsxs(TabsList, { type: "underline", size: "sm", className: "w-full shrink-0 justify-start gap-4 px-5", children: [_jsx(TabsTrigger, { value: "about", className: "w-fit flex-none", children: t('about') }), _jsx(TabsTrigger, { value: "members", className: "w-fit flex-none", children: t('members') })] }), _jsx(TabsContent, { value: "about", children: _jsx(AboutPane, { space: space, onEdit: onEdit, onArchive: onArchive }) }), _jsx(TabsContent, { value: "members", children: projectId ? (_jsx(MembersPane, { projectId: projectId, space: space, onAdd: () => setAdding(true) })) : null })] })] }) }), projectId ? (_jsx(AddChannelMembersDialog, { projectId: projectId, space: space, open: adding, onOpenChange: setAdding })) : null] }));
38
+ }
39
+ /** Label over value, a pencil at the row's end: the channel's facts, one per row. */
40
+ function AboutPane({ space, onEdit, onArchive }) {
41
+ const t = useTranslations('spaces.details');
42
+ const locale = useLocale();
43
+ const { projectId } = useSessionIds();
44
+ // A message that names no agent goes to the project's default agent.
45
+ const detail = useQuery({
46
+ queryKey: qk.project.detail(projectId ?? ''),
47
+ queryFn: () => getProjectDetail(projectId),
48
+ enabled: !!projectId,
49
+ ...contract('config'),
50
+ });
51
+ // A channel with an agent list starts a new thread on its first agent.
52
+ const channelDefault = space.agents?.[0] ?? null;
53
+ const defaultAgent = channelDefault ?? detail.data?.config.default_agent ?? detail.data?.config.open_code_default_agent ?? null;
54
+ const created = new Date(space.created_at).toLocaleDateString(locale, { dateStyle: 'medium' });
55
+ // Its creator or a project manager; an older API sends no `can_edit`.
56
+ const editable = space.can_edit !== false;
57
+ const edit = (field) => (editable ? _jsx(EditButton, { field: field, onClick: onEdit }) : null);
58
+ // "Make private" shows only where the server allows private channels.
59
+ const privateAvailable = usePrivateChannelsAvailable(projectId).data === true;
60
+ return (_jsxs(ModalBody, { className: "pt-1", children: [_jsxs("dl", { className: "divide-border divide-y", children: [_jsxs(DetailRow, { label: t('name'), action: edit(t('name')), children: ["#", space.slug] }), _jsx(DetailRow, { label: t('description'), action: edit(t('description')), children: space.description || _jsx("span", { className: "text-muted-foreground", children: t('noDescription') }) }), defaultAgent ? (_jsx(DetailRow, { label: t('defaultAgent'), hint: channelDefault ? t('channelDefaultHint') : t('defaultAgentHint'), children: _jsxs("span", { className: "flex items-center gap-2", children: [_jsx(AgentMark, { slug: defaultAgent, size: 14 }), agentLabel(defaultAgent)] }) })) : null, _jsx(DetailRow, { label: t('visibility'), action: editable && privateAvailable && !space.is_default && space.visibility !== 'private' && projectId ? (_jsx(MakePrivateButton, { projectId: projectId, space: space })) : null, children: space.visibility === 'private' ? t('visibilityPrivate') : t('visibilityProject') }), _jsx(DetailRow, { label: t('created'), children: created })] }), _jsx(LeaveRow, { projectId: projectId ?? null, space: space }), space.is_default || !editable ? null : (_jsxs("div", { className: "flex items-center justify-between gap-4 border-t pt-4", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-sm font-medium", children: t('archiveTitle') }), _jsx("p", { className: "text-muted-foreground text-xs text-pretty", children: t('archiveHint') })] }), _jsx(Button, { variant: "destructive", size: "sm", onClick: onArchive, children: t('archive') })] }))] }));
61
+ }
62
+ /**
63
+ * Search and "Add members" on one row, then one flat list of everyone in the
64
+ * channel: you, the other people A–Z by display name (never an email), then
65
+ * the channel's agents in order, the first tagged Default. A person row's menu
66
+ * is Leave channel on your own row and Remove on another's when you may; an
67
+ * agent row's menu (Make default, Remove) shows to whoever may edit the
68
+ * channel. People and agents not in the channel are only in the "Add members"
69
+ * picker. A private channel ends the list with one line on who can see it.
70
+ * `#general` is every project member, with no menus. The search filters the list.
71
+ */
72
+ function MembersPane({ projectId, space, onAdd }) {
73
+ const t = useTranslations('spaces.details');
74
+ const editable = space.can_edit !== false;
75
+ const name = space.slug ?? space.name;
76
+ const update = useUpdateProjectSpace(projectId);
77
+ const members = useProjectSpaceMembers(projectId, space.space_id);
78
+ const canAdd = members.data?.can_add === true;
79
+ const [query, setQuery] = useState('');
80
+ const needle = query.trim().toLowerCase();
81
+ const agents = useMemo(() => space.agents ?? [], [space.agents]);
82
+ const people = useMemo(() => [...(members.data?.members ?? [])].sort((a, b) => Number(b.is_viewer) - Number(a.is_viewer) || a.name.localeCompare(b.name)), [members.data]);
83
+ const shownPeople = people.filter((person) => !needle || person.name.toLowerCase().includes(needle));
84
+ const shownAgents = agents.filter((agent) => !needle || agentLabel(agent).toLowerCase().includes(needle) || agent.toLowerCase().includes(needle));
85
+ const save = (next, done) => update.mutate({ spaceId: space.space_id, input: { agents: next } }, { onSuccess: () => successToast(done), onError: () => errorToast(t('agentsFailed')) });
86
+ return (_jsxs(ModalBody, { className: "space-y-4 pt-4", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(InputGroupSearch, { className: "flex-1", children: [_jsx(InputGroupSearchIcon, { children: _jsx(MagnifyingGlassIcon, {}) }), _jsx(InputGroupSearchInput, { placeholder: t('search'), "aria-label": t('find'), value: query, onChange: (event) => setQuery(event.target.value), size: "sm" }), _jsx(InputGroupSearchClear, { onClick: () => setQuery('') })] }), canAdd || editable ? (_jsxs(Button, { size: "sm", variant: "secondary", className: "shrink-0 gap-1.5", onClick: onAdd, children: [_jsx(PlusIcon, { className: "size-4 shrink-0" }), t('addMembers')] })) : null] }), members.isLoading ? (_jsx("div", { className: "space-y-1", children: [0, 1, 2].map((index) => (_jsxs("div", { className: "flex min-h-10 items-center gap-2.5", children: [_jsx(Skeleton, { className: "size-7 rounded-full" }), _jsx(Skeleton, { className: "h-3.5 w-32" })] }, index))) })) : needle && shownPeople.length + shownAgents.length === 0 ? (_jsx("p", { className: "text-muted-foreground px-3 py-6 text-center text-xs", children: t('noMatches', { query: query.trim() }) })) : (_jsxs("div", { className: "space-y-2", children: [_jsxs("ul", { className: "-mx-2", children: [shownPeople.map((person) => (_jsx(MemberRow, { avatar: _jsx(MemberAvatar, { member: person }), name: person.name, tag: person.is_viewer ? t('you') : null, trailing: person.can_remove ? _jsx(PersonMenu, { projectId: projectId, space: space, person: person }) : null }, person.user_id))), shownAgents.map((agent) => {
87
+ const isDefault = agent === agents[0];
88
+ const label = agentLabel(agent);
89
+ return (_jsx(MemberRow, { avatar: _jsx(AgentMark, { slug: agent, size: 21 }), name: label, tag: isDefault ? t('defaultTag') : t('agentTag'), trailing: editable ? (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon-sm", className: "text-muted-foreground shrink-0", "aria-label": t('agentMenu', { agent: label }), disabled: update.isPending, children: _jsx(DotsThreeIcon, { className: "size-4" }) }) }), _jsxs(DropdownMenuContent, { align: "end", children: [isDefault ? null : (_jsx(DropdownMenuItem, { onSelect: () => save([agent, ...agents.filter((item) => item !== agent)], t('defaultSet', { agent: label, name })), children: t('makeDefault') })), _jsx(DropdownMenuItem, { onSelect: () => save(agents.filter((item) => item !== agent), t('agentRemoved', { agent: label, name })), children: t('removeAgent', { name }) })] })] })) : null }, agent));
90
+ })] }), space.visibility === 'private' && !needle ? (_jsx("p", { className: "text-muted-foreground text-xs text-pretty", children: t('privateNote', { name }) })) : null] }))] }));
91
+ }
92
+ /**
93
+ * "Make private", for the channel's creator or a project manager, behind a
94
+ * confirm that says what changes: only members see
95
+ * it from then on, the people who started a thread or added a link become
96
+ * members, everyone else loses it, it cannot be made public again, and the
97
+ * triggers that post into it stop (the API refuses a trigger run into a
98
+ * private channel).
99
+ */
100
+ function MakePrivateButton({ projectId, space }) {
101
+ const t = useTranslations('spaces.details');
102
+ const update = useUpdateProjectSpace(projectId);
103
+ const [open, setOpen] = useState(false);
104
+ // Read once the confirm opens: the count the warning names.
105
+ const triggers = useProjectTriggers(open ? projectId : null);
106
+ const triggerCount = triggers.data?.triggers.filter((trigger) => trigger.space_id === space.space_id).length ?? 0;
107
+ const name = space.slug ?? space.name;
108
+ return (_jsxs(_Fragment, { children: [_jsx(Button, { variant: "outline", size: "sm", className: "shrink-0", onClick: () => setOpen(true), children: t('makePrivate') }), _jsx(ConfirmDialog, { open: open, onOpenChange: setOpen, title: t('makePrivateTitle', { name }), description: _jsxs("div", { className: "space-y-2", children: [_jsx("p", { children: t('makePrivateWho', { name }) }), _jsx("p", { children: t('makePrivateLeave') }), _jsx("p", { children: t('makePrivateFinal') }), triggerCount > 0 ? _jsx("p", { children: t('makePrivateTriggers', { count: triggerCount }) }) : null, _jsx("p", { children: t('privateLimits') })] }), confirmLabel: t('makePrivate'), isPending: update.isPending, onConfirm: () => update.mutate({ spaceId: space.space_id, input: { visibility: 'private' } }, {
109
+ onSuccess: () => {
110
+ setOpen(false);
111
+ successToast(t('madePrivate', { name }));
112
+ },
113
+ // The app's mutation default toasts the server's reason (a 409
114
+ // `private_channels_unavailable` included); a second toast here would repeat it.
115
+ }) })] }));
116
+ }
117
+ /** "Leave this channel" for a member who may leave (not the creator, nobody in `#general`). A private channel asks first. */
118
+ function LeaveRow({ projectId, space }) {
119
+ const t = useTranslations('spaces.details');
120
+ const members = useProjectSpaceMembers(projectId, space.is_default ? null : space.space_id);
121
+ const leave = useLeaveProjectSpace(projectId ?? '', space.space_id);
122
+ const [confirming, setConfirming] = useState(false);
123
+ const self = members.data?.members.find((member) => member.is_viewer);
124
+ if (!projectId || !self?.can_remove)
125
+ return null;
126
+ const name = space.slug ?? space.name;
127
+ const isPrivate = space.visibility === 'private';
128
+ const run = () => leave.mutate(undefined, {
129
+ onSuccess: () => successToast(t('left', { name })),
130
+ onError: () => errorToast(t('peopleFailed')),
131
+ });
132
+ return (_jsxs("div", { className: "flex items-center justify-between gap-4 border-t pt-4", children: [_jsxs("div", { className: "min-w-0", children: [_jsx("p", { className: "text-sm font-medium", children: t('leaveTitle') }), _jsx("p", { className: "text-muted-foreground text-xs text-pretty", children: isPrivate ? t('leaveHintPrivate') : t('leaveHint') })] }), _jsxs(Button, { variant: "outline", size: "sm", disabled: leave.isPending, "aria-busy": leave.isPending || undefined, onClick: () => (isPrivate ? setConfirming(true) : run()), children: [leave.isPending ? _jsx(Loading, { className: "size-4 shrink-0" }) : null, t('leave')] }), _jsx(LeavePrivateConfirm, { name: name, open: confirming, onOpenChange: setConfirming, pending: leave.isPending, onConfirm: run })] }));
133
+ }
134
+ /** The confirm before leaving a private channel: leaving takes away every thread of it, the leaver's own too. */
135
+ function LeavePrivateConfirm({ name, open, onOpenChange, pending, onConfirm, }) {
136
+ const t = useTranslations('spaces.details');
137
+ return (_jsx(ConfirmDialog, { open: open, onOpenChange: onOpenChange, title: t('leavePrivateTitle', { name }), description: t('leaveHintPrivate'), confirmLabel: t('leave'), confirmVariant: "destructive", isPending: pending, onConfirm: () => {
138
+ onOpenChange(false);
139
+ onConfirm();
140
+ } }));
141
+ }
142
+ /** A person row's menu: Leave channel on your own row, Remove from #name on another's. */
143
+ function PersonMenu({ projectId, space, person }) {
144
+ const t = useTranslations('spaces.details');
145
+ const name = space.slug ?? space.name;
146
+ const remove = useRemoveProjectSpaceMember(projectId, space.space_id);
147
+ const leave = useLeaveProjectSpace(projectId, space.space_id);
148
+ const pending = remove.isPending || leave.isPending;
149
+ const [confirming, setConfirming] = useState(false);
150
+ const runLeave = () => leave.mutate(undefined, {
151
+ onSuccess: () => successToast(t('left', { name })),
152
+ onError: () => errorToast(t('peopleFailed')),
153
+ });
154
+ const onSelect = () => person.is_viewer
155
+ ? space.visibility === 'private'
156
+ ? setConfirming(true)
157
+ : runLeave()
158
+ : remove.mutate(person.user_id, {
159
+ onSuccess: () => successToast(t('personRemoved', { person: person.name, name })),
160
+ onError: () => errorToast(t('peopleFailed')),
161
+ });
162
+ return (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon-sm", className: "text-muted-foreground shrink-0", "aria-label": t('personMenu', { person: person.name }), disabled: pending, children: _jsx(DotsThreeIcon, { className: "size-4" }) }) }), _jsx(DropdownMenuContent, { align: "end", children: _jsx(DropdownMenuItem, { onSelect: onSelect, children: person.is_viewer ? t('leave') : t('removePerson', { name }) }) }), _jsx(LeavePrivateConfirm, { name: name, open: confirming, onOpenChange: setConfirming, pending: leave.isPending, onConfirm: runLeave })] }));
163
+ }
164
+ /** Avatar, name, a muted tag ("(you)", "Agent", "Default"), then the row's menu. No hover fill: the row itself is not clickable. */
165
+ function MemberRow({ avatar, name, tag, trailing }) {
166
+ return (_jsxs("li", { className: "flex min-h-10 items-center gap-2.5 px-2", children: [_jsx("span", { className: "flex size-8 shrink-0 items-center justify-center", children: avatar }), _jsxs("span", { className: "flex min-w-0 flex-1 items-baseline gap-1.5", children: [_jsx("span", { className: "truncate text-sm font-medium", children: name }), tag ? _jsx("span", { className: "text-muted-foreground shrink-0 text-xs", children: tag }) : null] }), trailing] }));
167
+ }
168
+ function DetailRow({ label, hint, action, children, }) {
169
+ return (_jsxs("div", { className: "flex items-start justify-between gap-4 py-3", children: [_jsxs("div", { className: "min-w-0 space-y-0.5", children: [_jsx("dt", { className: "text-muted-foreground text-xs font-medium", children: label }), _jsx("dd", { className: "text-sm text-pretty wrap-anywhere", children: children }), hint ? _jsx("p", { className: "text-muted-foreground text-xs text-pretty", children: hint }) : null] }), action] }));
170
+ }
171
+ /** A pencil, named for the row it edits: a screen reader has no row. */
172
+ function EditButton({ field, onClick }) {
173
+ const t = useTranslations('spaces.details');
174
+ const label = t('editField', { field });
175
+ return (_jsx(Hint, { label: label, side: "left", children: _jsx(Button, { variant: "ghost", size: "icon-sm", className: "text-muted-foreground shrink-0", "aria-label": label, onClick: onClick, children: _jsx(PencilSimpleIcon, { className: "size-3.5" }) }) }));
176
+ }
@@ -0,0 +1,49 @@
1
+ /**
2
+ * How the Links tab names a link: the server's title when it has one, else,
3
+ * without fetching it, the decoded path ("file/Pricing page") under the host
4
+ * ("paper.design"). A link with no path is named by its host.
5
+ */
6
+ /** The host without `www.`; the raw text when it does not parse. */
7
+ export declare function linkHost(url: string): string;
8
+ /** The path and query, decoded, without the outer slashes; '' for a bare host. */
9
+ export declare function linkPathTitle(url: string): string;
10
+ /**
11
+ * The row's title: the server's `display_title` (the title a member gave, else
12
+ * the page's fetched title), else the title a member gave, else the path, else the host.
13
+ */
14
+ export declare function linkTitle(link: {
15
+ url: string;
16
+ title: string | null;
17
+ display_title?: string | null;
18
+ }): string;
19
+ /** The Added filter's windows: the Threads tab's Activity values. */
20
+ export declare const LINK_ADDED: readonly ["today", "last7", "last30"];
21
+ export type LinkAdded = (typeof LINK_ADDED)[number];
22
+ /**
23
+ * The Links tab's search and filters, as the URL holds them
24
+ * (`?q=&pinned=1&by=&added=`). `by` is `me` or a user id.
25
+ */
26
+ export interface LinkFilters {
27
+ q: string;
28
+ pinned: boolean;
29
+ by: string | null;
30
+ added: LinkAdded | null;
31
+ }
32
+ export declare function linkFiltersFromParams(params: {
33
+ get(name: string): string | null;
34
+ }): LinkFilters;
35
+ type FilterableLink = {
36
+ url: string;
37
+ title: string | null;
38
+ display_title?: string | null;
39
+ site_name?: string | null;
40
+ pinned: boolean;
41
+ created_by: string | null;
42
+ last_shared_at: string;
43
+ };
44
+ /**
45
+ * The links that match: the search reads the title, the site name, the host and
46
+ * the URL (case-insensitive); `by: 'me'` reads `viewerId`; Added reads the last share.
47
+ */
48
+ export declare function filterLinks<T extends FilterableLink>(links: readonly T[], filters: LinkFilters, viewerId: string | undefined, now: Date): T[];
49
+ export {};
@@ -0,0 +1,73 @@
1
+ /**
2
+ * How the Links tab names a link: the server's title when it has one, else,
3
+ * without fetching it, the decoded path ("file/Pricing page") under the host
4
+ * ("paper.design"). A link with no path is named by its host.
5
+ */
6
+ /** The host without `www.`; the raw text when it does not parse. */
7
+ export function linkHost(url) {
8
+ try {
9
+ return new URL(url).hostname.replace(/^www\./, '');
10
+ }
11
+ catch {
12
+ return url;
13
+ }
14
+ }
15
+ /** The path and query, decoded, without the outer slashes; '' for a bare host. */
16
+ export function linkPathTitle(url) {
17
+ let pathname;
18
+ let search;
19
+ try {
20
+ ({ pathname, search } = new URL(url));
21
+ }
22
+ catch {
23
+ return '';
24
+ }
25
+ // `+` means a space in a query only; in a path it is a plus (`wiki/C++`).
26
+ const text = decode(pathname) + decode(search.replace(/\+/g, ' '));
27
+ return text.replace(/^\/+|\/+$/g, '').replace(/\s+/g, ' ').trim();
28
+ }
29
+ /** A malformed escape stays as written. */
30
+ function decode(raw) {
31
+ try {
32
+ return decodeURIComponent(raw);
33
+ }
34
+ catch {
35
+ return raw;
36
+ }
37
+ }
38
+ /**
39
+ * The row's title: the server's `display_title` (the title a member gave, else
40
+ * the page's fetched title), else the title a member gave, else the path, else the host.
41
+ */
42
+ export function linkTitle(link) {
43
+ return link.display_title?.trim() || link.title?.trim() || linkPathTitle(link.url) || linkHost(link.url);
44
+ }
45
+ /** The Added filter's windows: the Threads tab's Activity values. */
46
+ export const LINK_ADDED = ['today', 'last7', 'last30'];
47
+ export function linkFiltersFromParams(params) {
48
+ const added = params.get('added');
49
+ return {
50
+ q: params.get('q')?.trim() ?? '',
51
+ pinned: params.get('pinned') === '1',
52
+ by: params.get('by') || null,
53
+ added: LINK_ADDED.find((value) => value === added) ?? null,
54
+ };
55
+ }
56
+ /** Local midnight today, 6 days earlier (7 days with today) or 29 days earlier. */
57
+ function linkAddedSince(added, now) {
58
+ const days = added === 'today' ? 0 : added === 'last7' ? 6 : 29;
59
+ return new Date(now.getFullYear(), now.getMonth(), now.getDate() - days).getTime();
60
+ }
61
+ /**
62
+ * The links that match: the search reads the title, the site name, the host and
63
+ * the URL (case-insensitive); `by: 'me'` reads `viewerId`; Added reads the last share.
64
+ */
65
+ export function filterLinks(links, filters, viewerId, now) {
66
+ const q = filters.q.toLowerCase();
67
+ const by = filters.by === 'me' ? viewerId : filters.by;
68
+ const since = filters.added ? linkAddedSince(filters.added, now) : null;
69
+ return links.filter((link) => (!filters.pinned || link.pinned) &&
70
+ (!filters.by || link.created_by === by) &&
71
+ (since === null || Date.parse(link.last_shared_at) >= since) &&
72
+ (!q || [linkTitle(link), link.site_name ?? '', linkHost(link.url), link.url].some((text) => text.toLowerCase().includes(q))));
73
+ }
@@ -0,0 +1,19 @@
1
+ import { type ProjectSpace } from '@kortix/sdk';
2
+ /**
3
+ * A channel's Links tab, laid out like its Threads tab: one toolbar (search,
4
+ * the Filter menu, the active filters, "Add link"), then one list on one left
5
+ * edge. Pinned links come first under "Pinned"; the others follow by the day
6
+ * they were last shared (Today, Yesterday, Earlier). The channel's links all
7
+ * load at once, so search and filters read the loaded list. The URL holds
8
+ * them (`?q=&pinned=1&by=&added=`).
9
+ */
10
+ export declare function SpaceLinks({ projectId, space, place, onOpenThread, params, setParams, }: {
11
+ projectId: string;
12
+ space: ProjectSpace;
13
+ place: string;
14
+ onOpenThread?: (sessionId: string) => void;
15
+ params: {
16
+ get(name: string): string | null;
17
+ };
18
+ setParams: (change: (params: URLSearchParams) => void) => void;
19
+ }): import("react").JSX.Element;