zidane-ui 9.1.13 → 9.1.16

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 (290) hide show
  1. package/dist/adapters/index.d.ts +2 -2
  2. package/dist/adapters/index.js +2 -2
  3. package/dist/adapters/live.d.ts +29 -3
  4. package/dist/adapters/live.js +9 -1
  5. package/dist/adapters/server-composer-host.js +17 -2
  6. package/dist/adapters/server-extensions-host.d.ts +0 -1
  7. package/dist/adapters/server-extensions-host.js +4 -15
  8. package/dist/adapters/server-git-host.js +7 -16
  9. package/dist/adapters/server-host.js +181 -43
  10. package/dist/adapters/server-machines-host.d.ts +2 -0
  11. package/dist/adapters/server-machines-host.js +22 -23
  12. package/dist/adapters/server-onboarding-host.d.ts +1 -1
  13. package/dist/adapters/server-onboarding-host.js +3 -4
  14. package/dist/adapters/server-session-host.js +22 -3
  15. package/dist/adapters/server-settings-accounts.js +2 -2
  16. package/dist/adapters/server-settings-host.js +2 -2
  17. package/dist/adapters/server-settings-performance.js +7 -9
  18. package/dist/adapters/server-settings-sections.js +13 -14
  19. package/dist/adapters/server-sidebar-host.js +2 -2
  20. package/dist/adapters/sse-host.js +68 -3
  21. package/dist/adapters/sse-protocol.d.ts +12 -2
  22. package/dist/adapters/sse-protocol.js +4 -2
  23. package/dist/app/AppHostProvider.js +4 -3
  24. package/dist/app/ModalProvider.d.ts +13 -3
  25. package/dist/app/ModalProvider.js +103 -24
  26. package/dist/app/NoticeStack.d.ts +33 -0
  27. package/dist/app/NoticeStack.js +90 -0
  28. package/dist/app/index.d.ts +3 -2
  29. package/dist/app/index.js +3 -2
  30. package/dist/chat/SessionFilterMenu.d.ts +1 -1
  31. package/dist/chat/SessionFilterMenu.js +2 -1
  32. package/dist/chat/composer/Composer.js +10 -8
  33. package/dist/chat/composer/ModelChainList.js +17 -8
  34. package/dist/chat/composer/ModelChainTooltip.js +5 -2
  35. package/dist/chat/composer/use-draft-target.d.ts +20 -1
  36. package/dist/chat/composer/use-draft-target.js +121 -5
  37. package/dist/chat/composer/use-new-session-defaults.d.ts +5 -1
  38. package/dist/chat/composer/use-new-session-defaults.js +17 -4
  39. package/dist/chat/headless/chip-labels.d.ts +1 -0
  40. package/dist/chat/headless/chip-labels.js +1 -0
  41. package/dist/chat/headless/composer/labels-editor.d.ts +0 -2
  42. package/dist/chat/headless/composer/labels-editor.js +0 -2
  43. package/dist/chat/headless/draft-target.d.ts +21 -1
  44. package/dist/chat/headless/fixture-host.js +17 -2
  45. package/dist/chat/headless/host.d.ts +3 -3
  46. package/dist/chat/headless/index.d.ts +9 -9
  47. package/dist/chat/headless/index.js +2 -2
  48. package/dist/chat/headless/labels.d.ts +13 -6
  49. package/dist/chat/headless/labels.js +10 -9
  50. package/dist/chat/headless/session-list.d.ts +20 -8
  51. package/dist/chat/headless/session-list.js +1 -0
  52. package/dist/chat/headless/sidebar/directory.d.ts +56 -14
  53. package/dist/chat/headless/sidebar/directory.js +149 -70
  54. package/dist/chat/headless/sidebar/index.d.ts +3 -3
  55. package/dist/chat/headless/sidebar/index.js +2 -2
  56. package/dist/chat/headless/sidebar/labels.d.ts +15 -8
  57. package/dist/chat/headless/sidebar/types.d.ts +3 -1
  58. package/dist/chat/headless/sidebar/view.d.ts +13 -5
  59. package/dist/chat/headless/sidebar/view.js +31 -11
  60. package/dist/chat/headless/streams/actions.d.ts +5 -3
  61. package/dist/chat/headless/streams/actions.js +3 -2
  62. package/dist/chat/headless/streams/index.d.ts +3 -3
  63. package/dist/chat/headless/streams/merge.d.ts +6 -10
  64. package/dist/chat/headless/streams/merge.js +7 -21
  65. package/dist/chat/headless/streams/session-streams.d.ts +29 -4
  66. package/dist/chat/headless/streams/session-streams.js +86 -0
  67. package/dist/chat/headless/streams/store.d.ts +162 -16
  68. package/dist/chat/headless/streams/store.js +334 -38
  69. package/dist/chat/headless/streams/types.d.ts +10 -7
  70. package/dist/chat/headless/transcript-labels.d.ts +1 -0
  71. package/dist/chat/interactions/PlanCard.js +10 -3
  72. package/dist/chat/interactions/QuestionForm.js +7 -3
  73. package/dist/chat/interactions/card-ui.d.ts +5 -3
  74. package/dist/chat/interactions/card-ui.js +9 -7
  75. package/dist/chat/rich-composer/RichComposer.js +1 -7
  76. package/dist/chat/rich-composer/composer-extensions.d.ts +0 -2
  77. package/dist/chat/rich-composer/composer-extensions.js +2 -2
  78. package/dist/chat/rich-composer/use-composer-editor.d.ts +0 -2
  79. package/dist/chat/rich-composer/use-composer-editor.js +1 -2
  80. package/dist/chat/sidebar/SessionSidebar.js +5 -5
  81. package/dist/chat/sidebar/SidebarFilterMenu.js +3 -1
  82. package/dist/chat/sidebar/SidebarFrame.d.ts +4 -0
  83. package/dist/chat/sidebar/SidebarFrame.js +27 -9
  84. package/dist/chat/sidebar/SidebarGroupHeader.js +1 -1
  85. package/dist/chat/sidebar/SidebarHostProvider.d.ts +8 -5
  86. package/dist/chat/sidebar/SidebarHostProvider.js +13 -9
  87. package/dist/chat/sidebar/SidebarToggleButton.js +7 -3
  88. package/dist/chat/sidebar/index.d.ts +2 -2
  89. package/dist/chat/sidebar/session-menu.js +4 -4
  90. package/dist/chat/sidebar/useSaveViewAsSpace.js +2 -2
  91. package/dist/chat/testing/contract.js +2 -2
  92. package/dist/chat/transcript/AuthFailureCard.js +11 -8
  93. package/dist/chat/transcript/BadgeMenu.js +13 -2
  94. package/dist/chat/transcript/MermaidDiagram.js +7 -3
  95. package/dist/chat/transcript/fold.d.ts +4 -0
  96. package/dist/chat/transcript/fold.js +53 -22
  97. package/dist/chat/transcript/script-input.d.ts +1 -1
  98. package/dist/chat/transcript/shell-block.js +7 -3
  99. package/dist/chat/transcript/useStickToBottom.js +12 -0
  100. package/dist/components/BrowserSignIn.js +23 -21
  101. package/dist/components/Form.d.ts +6 -4
  102. package/dist/components/Form.js +16 -8
  103. package/dist/components/LoadError.d.ts +4 -2
  104. package/dist/components/LoadError.js +13 -9
  105. package/dist/components/Notice.d.ts +29 -0
  106. package/dist/components/Notice.js +63 -0
  107. package/dist/components/PanelEmpty.d.ts +1 -1
  108. package/dist/components/PanelEmpty.js +4 -2
  109. package/dist/components/Restricted.d.ts +1 -1
  110. package/dist/components/palette/PaletteList.js +8 -1
  111. package/dist/components/palette/PalettePanel.js +14 -6
  112. package/dist/core.css +24 -5
  113. package/dist/dist/{index-Bq87OcGy.d.ts → index-BZM8tu4L.d.ts} +28 -3
  114. package/dist/dist/index.d.ts +2 -2
  115. package/dist/dist/{timeout-B5pO5I5a.d.ts → timeout-Cyx3VGPz.d.ts} +1 -1
  116. package/dist/extensions/ExtensionSettingsPage.js +1 -4
  117. package/dist/extensions/ExtensionSettingsSection.js +4 -3
  118. package/dist/extensions/ExtensionSettingsSidebar.js +2 -6
  119. package/dist/extensions/SettingsWireForm.d.ts +1 -7
  120. package/dist/extensions/SettingsWireForm.js +7 -5
  121. package/dist/extensions/headless/fixture-host.d.ts +1 -5
  122. package/dist/extensions/headless/fixture-host.js +1 -4
  123. package/dist/extensions/headless/host.d.ts +1 -11
  124. package/dist/extensions/headless/index.d.ts +3 -3
  125. package/dist/extensions/headless/index.js +2 -2
  126. package/dist/extensions/headless/select.d.ts +1 -11
  127. package/dist/extensions/headless/select.js +1 -18
  128. package/dist/files/EditorColumn.js +12 -1
  129. package/dist/files/TreeColumn.js +13 -20
  130. package/dist/files/useOpenFiles.js +2 -0
  131. package/dist/git/BranchMenu.js +5 -3
  132. package/dist/git/ImportRepoDialog.js +18 -9
  133. package/dist/git/MoveSessionDialog.js +15 -7
  134. package/dist/git/RemoteFolderPicker.js +34 -16
  135. package/dist/git/SyncChip.js +17 -17
  136. package/dist/git/WherePicker.d.ts +16 -1
  137. package/dist/git/WherePicker.js +80 -36
  138. package/dist/git/headless/environment.d.ts +33 -3
  139. package/dist/git/headless/environment.js +33 -5
  140. package/dist/git/headless/index.d.ts +2 -2
  141. package/dist/git/headless/index.js +2 -2
  142. package/dist/git/headless/labels.d.ts +15 -2
  143. package/dist/git/headless/labels.js +17 -4
  144. package/dist/git/useEnvironmentChoices.d.ts +3 -1
  145. package/dist/git/useEnvironmentChoices.js +6 -3
  146. package/dist/index.d.ts +2 -1
  147. package/dist/index.js +2 -1
  148. package/dist/labels.d.ts +5 -0
  149. package/dist/labels.js +5 -0
  150. package/dist/machines/AddMachineDialog.d.ts +34 -0
  151. package/dist/machines/AddMachineDialog.js +464 -0
  152. package/dist/machines/Banners.d.ts +33 -4
  153. package/dist/machines/Banners.js +64 -3
  154. package/dist/machines/DaemonMenu.js +27 -4
  155. package/dist/machines/HostCapabilities.d.ts +1 -3
  156. package/dist/machines/HostCapabilities.js +24 -45
  157. package/dist/machines/HostSyncPanel.js +123 -129
  158. package/dist/machines/HostsSection.d.ts +4 -1
  159. package/dist/machines/HostsSection.js +30 -7
  160. package/dist/machines/MachinesExplainer.d.ts +17 -0
  161. package/dist/machines/MachinesExplainer.js +71 -0
  162. package/dist/machines/MachinesProvider.d.ts +14 -2
  163. package/dist/machines/MachinesProvider.js +35 -1
  164. package/dist/machines/ServerAddedCard.d.ts +31 -0
  165. package/dist/machines/ServerAddedCard.js +72 -0
  166. package/dist/machines/ServerCard.js +91 -215
  167. package/dist/machines/ServerMachinesPanel.d.ts +2 -2
  168. package/dist/machines/ServerMachinesPanel.js +184 -323
  169. package/dist/machines/ServerUpdatePanel.js +51 -40
  170. package/dist/machines/ShareThisComputerForm.d.ts +19 -0
  171. package/dist/machines/ShareThisComputerForm.js +133 -0
  172. package/dist/machines/TokensPanel.d.ts +5 -3
  173. package/dist/machines/TokensPanel.js +98 -78
  174. package/dist/machines/headless/fixture-host.d.ts +19 -3
  175. package/dist/machines/headless/fixture-host.js +42 -5
  176. package/dist/machines/headless/fixtures.js +4 -6
  177. package/dist/machines/headless/host.d.ts +40 -19
  178. package/dist/machines/headless/index.d.ts +3 -3
  179. package/dist/machines/headless/index.js +2 -2
  180. package/dist/machines/headless/labels.d.ts +63 -20
  181. package/dist/machines/headless/labels.js +88 -25
  182. package/dist/machines/headless/messages.js +8 -0
  183. package/dist/machines/headless/stores.d.ts +9 -2
  184. package/dist/machines/headless/stores.js +28 -1
  185. package/dist/machines/index.d.ts +7 -3
  186. package/dist/machines/index.js +8 -4
  187. package/dist/machines/testing/contract.d.ts +15 -3
  188. package/dist/machines/testing/contract.js +68 -14
  189. package/dist/motion/grow.d.ts +8 -1
  190. package/dist/motion/grow.js +10 -4
  191. package/dist/onboarding/demos/index.js +1 -1
  192. package/dist/onboarding/headless/labels.d.ts +13 -0
  193. package/dist/onboarding/headless/labels.js +8 -0
  194. package/dist/onboarding/index.js +3 -3
  195. package/dist/onboarding/sources/SourceBrowser.js +11 -7
  196. package/dist/onboarding/steps/ConnectorsStep.js +1 -1
  197. package/dist/onboarding/steps/ImportStep.js +4 -1
  198. package/dist/onboarding/steps/ReadyStep.js +9 -2
  199. package/dist/onboarding/steps/SkillsStep.js +1 -1
  200. package/dist/onboarding/steps/connect/KeyForm.js +6 -2
  201. package/dist/onboarding/steps/connect/ProviderPanel.js +6 -2
  202. package/dist/onboarding/steps/connect/ProviderReady.js +25 -20
  203. package/dist/onboarding/steps/tasks.js +17 -14
  204. package/dist/server/sse-handler.js +141 -19
  205. package/dist/session/ArtifactsPanel.js +39 -17
  206. package/dist/session/PlanTracker.js +12 -7
  207. package/dist/session/ProjectHome.js +13 -11
  208. package/dist/session/RemindersPanel.js +34 -16
  209. package/dist/session/RunningWorkDialog.js +6 -2
  210. package/dist/session/SecretsPanel.js +29 -10
  211. package/dist/session/SessionDetailsDialog.d.ts +1 -1
  212. package/dist/session/SessionDetailsDialog.js +18 -10
  213. package/dist/session/SideChat.js +10 -7
  214. package/dist/session/TurnDetailsDialog.js +19 -5
  215. package/dist/session/UsagePanel.js +10 -4
  216. package/dist/session/headless/host.d.ts +2 -0
  217. package/dist/session/headless/labels.d.ts +19 -1
  218. package/dist/session/headless/labels.js +15 -1
  219. package/dist/session/headless/queue.js +2 -1
  220. package/dist/session/headless/reminder-labels.d.ts +4 -0
  221. package/dist/session/headless/reminder-labels.js +4 -0
  222. package/dist/settings/SettingsRestricted.d.ts +1 -1
  223. package/dist/settings/SettingsRestricted.js +4 -4
  224. package/dist/settings/SettingsShell.d.ts +7 -0
  225. package/dist/settings/SettingsShell.js +6 -1
  226. package/dist/settings/headless/fixture-performance.d.ts +1 -1
  227. package/dist/settings/headless/host.d.ts +2 -2
  228. package/dist/settings/headless/labels.d.ts +3 -3
  229. package/dist/settings/headless/labels.js +3 -3
  230. package/dist/settings/headless/performance.d.ts +3 -4
  231. package/dist/settings/headless/search.d.ts +1 -1
  232. package/dist/settings/index.d.ts +2 -1
  233. package/dist/settings/index.js +2 -1
  234. package/dist/settings/sections/editor/EditorSection.js +7 -4
  235. package/dist/settings/sections/editor/labels.d.ts +1 -0
  236. package/dist/settings/sections/editor/labels.js +1 -0
  237. package/dist/settings/sections/environments/EnvironmentsSection.js +19 -12
  238. package/dist/settings/sections/environments/labels.d.ts +1 -0
  239. package/dist/settings/sections/environments/labels.js +2 -1
  240. package/dist/settings/sections/extensions/ExtensionConfigRows.d.ts +1 -3
  241. package/dist/settings/sections/extensions/ExtensionConfigRows.js +20 -19
  242. package/dist/settings/sections/extensions/ExtensionOptionsSection.js +2 -1
  243. package/dist/settings/sections/extensions/options-labels.d.ts +2 -1
  244. package/dist/settings/sections/extensions/options-labels.js +2 -1
  245. package/dist/settings/sections/index.d.ts +2 -1
  246. package/dist/settings/sections/index.js +2 -1
  247. package/dist/settings/sections/logs/LogsSection.d.ts +2 -2
  248. package/dist/settings/sections/logs/LogsSection.js +2 -2
  249. package/dist/settings/sections/mcp/McpSection.d.ts +1 -1
  250. package/dist/settings/sections/mcp/McpSection.js +12 -6
  251. package/dist/settings/sections/mcp/McpServerRow.js +20 -13
  252. package/dist/settings/sections/mcp/labels.d.ts +8 -2
  253. package/dist/settings/sections/mcp/labels.js +8 -2
  254. package/dist/settings/sections/models/ModelRows.js +1 -1
  255. package/dist/settings/sections/models/NewChatPlaceRow.d.ts +26 -0
  256. package/dist/settings/sections/models/NewChatPlaceRow.js +78 -0
  257. package/dist/settings/sections/models/SpacesDefaultsSection.js +15 -3
  258. package/dist/settings/sections/models/labels.d.ts +7 -0
  259. package/dist/settings/sections/models/labels.js +7 -0
  260. package/dist/settings/sections/models/model-test.js +7 -4
  261. package/dist/settings/sections/performance/PerformanceSection.js +16 -6
  262. package/dist/settings/sections/performance/labels.d.ts +1 -1
  263. package/dist/settings/sections/performance/labels.js +1 -1
  264. package/dist/settings/sections/providers/ProvidersSection.d.ts +1 -1
  265. package/dist/settings/sections/providers/ProvidersSection.js +14 -7
  266. package/dist/settings/sections/providers/ServerProvidersSection.d.ts +1 -1
  267. package/dist/settings/sections/providers/ServerProvidersSection.js +11 -5
  268. package/dist/settings/sections/providers/labels.d.ts +2 -2
  269. package/dist/settings/sections/providers/labels.js +2 -2
  270. package/dist/settings/sections/skills/SkillList.js +1 -1
  271. package/dist/settings/sections/skills/SkillsSection.js +1 -1
  272. package/dist/settings/testing/performance.contract.js +8 -12
  273. package/dist/styles.css +32 -3
  274. package/dist/terminal/HostTerminalSurface.js +15 -5
  275. package/dist/terminal/TerminalPanel.js +30 -17
  276. package/dist/terminal/TerminalSurface.js +11 -4
  277. package/dist/terminal/headless/labels.d.ts +5 -0
  278. package/dist/terminal/headless/labels.js +5 -0
  279. package/dist/terminal/headless/store.d.ts +1 -1
  280. package/dist/terminal/headless/store.js +6 -3
  281. package/dist/workspace/LayoutBudget.d.ts +5 -1
  282. package/dist/workspace/LayoutBudget.js +14 -1
  283. package/dist/workspace/PanelContentView.d.ts +1 -1
  284. package/dist/workspace/PanelContentView.js +17 -6
  285. package/dist/workspace/WorkspaceProvider.js +3 -2
  286. package/dist/workspace/headless/labels.d.ts +1 -0
  287. package/dist/workspace/headless/labels.js +1 -0
  288. package/package.json +3 -3
  289. package/src/styles/motion.css +8 -0
  290. package/src/styles/primitives.css +7 -0
@@ -56,8 +56,6 @@ interface CapabilitiesViewProps {
56
56
  local?: boolean;
57
57
  /** Installs a missing tool there. Absent: a missing tool offers nothing. */
58
58
  onInstall?: (name: string) => void;
59
- /** This connection may not install (a chat token): Install shows, Admin only. */
60
- installRestricted?: boolean;
61
59
  /** The tool being installed. */
62
60
  installing?: string | null;
63
61
  /** How the last install went: its output shows under the tools when it failed. */
@@ -77,6 +75,6 @@ interface CapabilitiesViewProps {
77
75
  *
78
76
  * @param props - {@link CapabilitiesViewProps}.
79
77
  */
80
- declare function CapabilitiesView({ caps, error, checking, onRecheck, local, onInstall, installRestricted, installing, installed, className, style }: CapabilitiesViewProps): import("react").JSX.Element;
78
+ declare function CapabilitiesView({ caps, error, checking, onRecheck, local, onInstall, installing, installed, className, style }: CapabilitiesViewProps): import("react").JSX.Element;
81
79
  //#endregion
82
80
  export { CapabilitiesView, CapabilitiesViewProps, CapabilityTags, CapabilityTagsProps, HostCapabilitiesState, useHostCapabilities };
@@ -1,7 +1,7 @@
1
1
  import { BTN_SECONDARY } from "../components/button.js";
2
2
  import { CopyButton } from "../components/CopyButton.js";
3
+ import { Notice } from "../components/Notice.js";
3
4
  import { MetaChip, OpLine } from "../components/Form.js";
4
- import { Restricted } from "../components/Restricted.js";
5
5
  import { machinesError } from "./headless/host.js";
6
6
  import { useMachinesHost, useMachinesLabels } from "./MachinesProvider.js";
7
7
  import { RoutedLink } from "../extensions/links.js";
@@ -14,7 +14,7 @@ import { HOST_TOOLS, capabilityTags, toolInstall } from "zidane/chat/pure";
14
14
  * tags on its row in a list, and the full check on its page (OS, tools on
15
15
  * PATH, sandbox, environment kinds, what it allows, disk) with Re-check.
16
16
  * On a server, a missing tool's row offers its install (`toolInstall`):
17
- * Install runs it there (`MachinesHost.installTool`, Admin only), a command
17
+ * Install runs it there (`MachinesHost.installTool`), a command
18
18
  * that needs root is offered to copy, else the tool's page.
19
19
  */
20
20
  /**
@@ -129,7 +129,7 @@ const GRID = "m-0 p-0 list-none grid grid-cols-2 gap-px rounded-zg-md overflow-h
129
129
  *
130
130
  * @param props - {@link CapabilitiesViewProps}.
131
131
  */
132
- function CapabilitiesView({ caps, error, checking, onRecheck, local = false, onInstall, installRestricted = false, installing = null, installed = null, className = "", style }) {
132
+ function CapabilitiesView({ caps, error, checking, onRecheck, local = false, onInstall, installing = null, installed = null, className = "", style }) {
133
133
  const labels = useMachinesLabels();
134
134
  const installAction = (name, label) => {
135
135
  if (!onInstall || !caps || caps.partial) return void 0;
@@ -148,18 +148,13 @@ function CapabilitiesView({ caps, error, checking, onRecheck, local = false, onI
148
148
  className: "text-xs text-[var(--zg-text-muted)] hover:text-[var(--zg-text)] shrink-0",
149
149
  children: labels.machinesCapsInstallPage
150
150
  });
151
- return /* @__PURE__ */ jsx(Restricted, {
152
- restricted: installRestricted,
153
- reason: labels.machinesAdminOnly,
154
- inline: true,
155
- children: /* @__PURE__ */ jsx("button", {
156
- type: "button",
157
- className: BTN_SECONDARY,
158
- "aria-label": labels.machinesCapsInstallLabel(label),
159
- disabled: installing !== null,
160
- onClick: () => onInstall(name),
161
- children: installing === name ? labels.machinesCapsInstalling : labels.machinesCapsInstall
162
- })
151
+ return /* @__PURE__ */ jsx("button", {
152
+ type: "button",
153
+ className: BTN_SECONDARY,
154
+ "aria-label": labels.machinesCapsInstallLabel(label),
155
+ disabled: installing !== null,
156
+ onClick: () => onInstall(name),
157
+ children: installing === name ? labels.machinesCapsInstalling : labels.machinesCapsInstall
163
158
  });
164
159
  };
165
160
  const installedLabel = installed ? HOST_TOOLS.find((tool) => tool.name === installed.name)?.label ?? installed.name : "";
@@ -182,9 +177,11 @@ function CapabilitiesView({ caps, error, checking, onRecheck, local = false, onI
182
177
  }), caps.workspace.freeBytes !== void 0 && /* @__PURE__ */ jsx(MetaChip, { children: labels.machinesCapsFree(caps.workspace.freeBytes) })] }),
183
178
  caps?.partial && /* @__PURE__ */ jsx("span", { children: labels.machinesCapsPartial }),
184
179
  !caps && !error && /* @__PURE__ */ jsx("span", { children: labels.machinesCapsChecking }),
185
- error && /* @__PURE__ */ jsx("span", {
186
- className: "text-zg-danger",
187
- children: labels.machinesError(error)
180
+ error && /* @__PURE__ */ jsx(Notice, {
181
+ tone: "error",
182
+ compact: true,
183
+ detail: error.detail,
184
+ children: labels.machinesFailed(error.kind)
188
185
  })
189
186
  ]
190
187
  }), /* @__PURE__ */ jsx("button", {
@@ -242,33 +239,15 @@ function CapabilitiesView({ caps, error, checking, onRecheck, local = false, onI
242
239
  detail: env.available ? labels.machinesCapsEnvAvailable : labels.machinesCapsNotAvailable,
243
240
  ...env.reason ? { title: env.reason } : {}
244
241
  }, env.kind)),
245
- !local && /* @__PURE__ */ jsxs(Fragment, { children: [
246
- /* @__PURE__ */ jsx(Fact, {
247
- ok: caps.allows.remoteInstalls,
248
- icon: "i-ph-download-simple",
249
- label: labels.machinesCapsRemoteInstalls
250
- }),
251
- /* @__PURE__ */ jsx(Fact, {
252
- ok: caps.allows.asMachine,
253
- icon: "i-ph-hard-drives",
254
- label: labels.machinesCapsAsMachine
255
- }),
256
- /* @__PURE__ */ jsx(Fact, {
257
- ok: caps.allows.sync,
258
- icon: "i-ph-arrows-clockwise",
259
- label: labels.machinesCapsSync
260
- }),
261
- /* @__PURE__ */ jsx(Fact, {
262
- ok: caps.allows.clone,
263
- icon: "i-ph-git-branch",
264
- label: labels.machinesCapsClone
265
- }),
266
- /* @__PURE__ */ jsx(Fact, {
267
- ok: caps.allows.createFolders,
268
- icon: "i-ph-folder-plus",
269
- label: labels.machinesCapsCreateFolders
270
- })
271
- ] })
242
+ !local && /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Fact, {
243
+ ok: caps.allows.asMachine,
244
+ icon: "i-ph-hard-drives",
245
+ label: labels.machinesCapsAsMachine
246
+ }), /* @__PURE__ */ jsx(Fact, {
247
+ ok: caps.allows.sync,
248
+ icon: "i-ph-arrows-clockwise",
249
+ label: labels.machinesCapsSync
250
+ })] })
272
251
  ]
273
252
  })
274
253
  ] })]
@@ -1,6 +1,5 @@
1
1
  import { BTN_SECONDARY } from "../components/button.js";
2
2
  import { Checkbox, OpLine, SegmentedRow } from "../components/Form.js";
3
- import { Restricted } from "../components/Restricted.js";
4
3
  import { constant, useReadable } from "../chat/headless/store.js";
5
4
  import { machinesError } from "./headless/host.js";
6
5
  import { shortList, syncBlockedReason } from "./headless/sync.js";
@@ -136,140 +135,135 @@ function HostSyncPanel({ host, confirm, className = "", style }) {
136
135
  };
137
136
  const reset = sync?.reset;
138
137
  const push = sync?.push;
139
- const restricted = host.scope !== void 0 && host.scope !== "admin";
140
- return /* @__PURE__ */ jsx(Restricted, {
141
- restricted,
142
- reason: labels.machinesAdminOnly,
143
- children: /* @__PURE__ */ jsxs("div", {
144
- className: `px-3 pb-3 space-y-3 ${className}`.trimEnd(),
145
- style,
146
- "data-testid": `sync-${host.id}`,
147
- children: [
148
- /* @__PURE__ */ jsx(SegmentedRow, {
149
- label: labels.machinesSyncMode,
150
- description: labels.machinesSyncModeDescription(state.device?.name, host.name),
151
- value: config.mode,
152
- onChange: (mode) => send({ mode }),
153
- options: SYNC_MODES.map((mode) => ({
154
- value: mode,
155
- label: labels.machinesSyncModes[mode]
156
- }))
157
- }),
158
- /* @__PURE__ */ jsx("ul", {
159
- className: "m-0 p-0 list-none grid grid-cols-2 gap-1.5",
160
- "aria-label": labels.machinesSyncWhat,
161
- children: SYNC_CATEGORIES.map((category) => {
162
- const on = config.categories.includes(category);
163
- const waiting = config.pending.includes(category);
164
- const reason = syncBlockedReason(category, caps);
165
- const blocked = reason ? labels.machinesSyncBlocked(reason, host.name) : void 0;
166
- const info = labels.machinesSyncCategories[category];
167
- return /* @__PURE__ */ jsx("li", {
168
- className: "min-w-0",
169
- children: /* @__PURE__ */ jsxs("button", {
170
- type: "button",
171
- role: "checkbox",
172
- "aria-checked": on,
173
- "aria-label": info.label,
174
- title: blocked ?? info.description,
175
- disabled: Boolean(blocked) && !on || !configure,
176
- className: `flex w-full min-w-0 items-center gap-2.5 px-2.5 py-2 rounded-zg-md border text-left cursor-pointer disabled:cursor-default disabled:opacity-zg-disabled transition-colors ${on ? "border-[var(--zg-accent)] bg-[color-mix(in_srgb,var(--zg-accent)_8%,transparent)]" : "border-[var(--zg-hairline)] bg-transparent hover:bg-[var(--zg-row-hover)]"}`,
177
- onClick: () => void toggleCategory(category),
178
- children: [
179
- /* @__PURE__ */ jsx("span", {
180
- "aria-hidden": true,
181
- className: `${CATEGORY_ICON[category]} text-zg-body shrink-0 ${on ? "text-[var(--zg-accent)]" : "text-[var(--zg-text-muted)]"}`
182
- }),
183
- /* @__PURE__ */ jsxs("span", {
184
- className: "flex-1 min-w-0",
185
- children: [/* @__PURE__ */ jsx("span", {
186
- className: "block truncate text-xs font-medium text-[var(--zg-text)]",
187
- children: info.label
188
- }), /* @__PURE__ */ jsx("span", {
189
- className: `block truncate text-zg-meta ${waiting || blocked ? "text-zg-warn" : "text-[var(--zg-text-muted)]"}`,
190
- children: blocked ?? (waiting ? labels.machinesSyncWaiting : info.description)
191
- })]
192
- }),
193
- /* @__PURE__ */ jsx(Checkbox, { checked: on })
194
- ]
195
- })
196
- }, category);
197
- })
198
- }),
199
- config.categories.includes("keys") && /* @__PURE__ */ jsx(SyncAccounts, {
200
- host,
201
- accounts: state.local.accounts,
202
- keys: config.keys,
203
- onToggleKey: (provider) => void toggleKey(provider)
204
- }),
205
- config.categories.includes("mcps") && state.local.stdioMcps.length > 0 && /* @__PURE__ */ jsx(Hint, {
206
- icon: "i-ph-terminal",
207
- title: state.local.stdioMcps.join(", "),
208
- children: labels.machinesSyncStdio(host.name, shortList(state.local.stdioMcps, labels))
209
- }),
210
- config.categories.includes("extensions") && state.local.localExtensions.length > 0 && /* @__PURE__ */ jsx(Hint, {
211
- icon: "i-ph-puzzle-piece",
212
- title: state.local.localExtensions.join(", "),
213
- children: labels.machinesSyncNotSyncable(shortList(state.local.localExtensions, labels))
214
- }),
215
- state.conflict && config.mode !== "off" && /* @__PURE__ */ jsxs("div", {
216
- className: "flex items-center gap-3",
217
- children: [
218
- /* @__PURE__ */ jsx(Hint, {
219
- icon: "i-ph-arrows-left-right",
220
- children: labels.machinesSyncFrom(state.conflict)
221
- }),
222
- /* @__PURE__ */ jsx("span", { className: "flex-1" }),
223
- takeOver && /* @__PURE__ */ jsx("button", {
138
+ return /* @__PURE__ */ jsxs("div", {
139
+ className: `px-3 pb-3 space-y-3 ${className}`.trimEnd(),
140
+ style,
141
+ "data-testid": `sync-${host.id}`,
142
+ children: [
143
+ /* @__PURE__ */ jsx(SegmentedRow, {
144
+ label: labels.machinesSyncMode,
145
+ description: labels.machinesSyncModeDescription(state.device?.name, host.name),
146
+ value: config.mode,
147
+ onChange: (mode) => send({ mode }),
148
+ options: SYNC_MODES.map((mode) => ({
149
+ value: mode,
150
+ label: labels.machinesSyncModes[mode]
151
+ }))
152
+ }),
153
+ /* @__PURE__ */ jsx("ul", {
154
+ className: "m-0 p-0 list-none grid grid-cols-2 gap-1.5",
155
+ "aria-label": labels.machinesSyncWhat,
156
+ children: SYNC_CATEGORIES.map((category) => {
157
+ const on = config.categories.includes(category);
158
+ const waiting = config.pending.includes(category);
159
+ const reason = syncBlockedReason(category, caps);
160
+ const blocked = reason ? labels.machinesSyncBlocked(reason, host.name) : void 0;
161
+ const info = labels.machinesSyncCategories[category];
162
+ return /* @__PURE__ */ jsx("li", {
163
+ className: "min-w-0",
164
+ children: /* @__PURE__ */ jsxs("button", {
224
165
  type: "button",
225
- className: BTN_SECONDARY,
226
- onClick: () => void takeOverNow(),
227
- children: labels.machinesSyncTakeOver
228
- })
229
- ]
230
- }),
231
- overrides.map((field) => /* @__PURE__ */ jsxs("div", {
232
- className: "flex items-center gap-3",
233
- children: [
234
- /* @__PURE__ */ jsxs(Hint, {
235
- icon: "i-ph-pencil-simple",
236
- title: labels.machinesSyncEditedOnTitle(host.name),
166
+ role: "checkbox",
167
+ "aria-checked": on,
168
+ "aria-label": info.label,
169
+ title: blocked ?? info.description,
170
+ disabled: Boolean(blocked) && !on || !configure,
171
+ className: `flex w-full min-w-0 items-center gap-2.5 px-2.5 py-2 rounded-zg-md border text-left cursor-pointer disabled:cursor-default disabled:opacity-zg-disabled transition-colors ${on ? "border-[var(--zg-accent)] bg-[color-mix(in_srgb,var(--zg-accent)_8%,transparent)]" : "border-[var(--zg-hairline)] bg-transparent hover:bg-[var(--zg-row-hover)]"}`,
172
+ onClick: () => void toggleCategory(category),
237
173
  children: [
238
- field,
239
- " ",
240
174
  /* @__PURE__ */ jsx("span", {
241
- className: "opacity-70",
242
- children: labels.machinesSyncEditedOn(host.name)
243
- })
175
+ "aria-hidden": true,
176
+ className: `${CATEGORY_ICON[category]} text-zg-body shrink-0 ${on ? "text-[var(--zg-accent)]" : "text-[var(--zg-text-muted)]"}`
177
+ }),
178
+ /* @__PURE__ */ jsxs("span", {
179
+ className: "flex-1 min-w-0",
180
+ children: [/* @__PURE__ */ jsx("span", {
181
+ className: "block truncate text-xs font-medium text-[var(--zg-text)]",
182
+ children: info.label
183
+ }), /* @__PURE__ */ jsx("span", {
184
+ className: `block truncate text-zg-meta ${waiting || blocked ? "text-zg-warn" : "text-[var(--zg-text-muted)]"}`,
185
+ children: blocked ?? (waiting ? labels.machinesSyncWaiting : info.description)
186
+ })]
187
+ }),
188
+ /* @__PURE__ */ jsx(Checkbox, { checked: on })
244
189
  ]
245
- }),
246
- /* @__PURE__ */ jsx("span", { className: "flex-1" }),
247
- reset && /* @__PURE__ */ jsx("button", {
248
- type: "button",
249
- className: BTN_SECONDARY,
250
- onClick: () => void act(() => reset(host.id, field)),
251
- children: labels.machinesSyncAgain
252
190
  })
253
- ]
254
- }, field)),
255
- /* @__PURE__ */ jsxs("div", {
256
- className: "flex items-center gap-2 pt-1 border-t border-[var(--zg-hairline)]",
257
- children: [/* @__PURE__ */ jsxs("span", {
258
- className: "flex-1 min-w-0 inline-flex items-center gap-2 pt-2 text-xs text-[var(--zg-text-muted)]",
259
- children: [statusText, /* @__PURE__ */ jsx(SyncOutcomeBadge, { state })]
260
- }), config.mode !== "off" && state.connected && state.supported && push && /* @__PURE__ */ jsx("button", {
261
- type: "button",
262
- className: `${BTN_SECONDARY} mt-2`,
263
- onClick: () => void act(() => push(host.id)),
264
- children: labels.machinesSyncPushNow
265
- })]
266
- }),
267
- error && /* @__PURE__ */ jsx(OpLine, {
268
- kind: "error",
269
- children: error
191
+ }, category);
270
192
  })
271
- ]
272
- })
193
+ }),
194
+ config.categories.includes("keys") && /* @__PURE__ */ jsx(SyncAccounts, {
195
+ host,
196
+ accounts: state.local.accounts,
197
+ keys: config.keys,
198
+ onToggleKey: (provider) => void toggleKey(provider)
199
+ }),
200
+ config.categories.includes("mcps") && state.local.stdioMcps.length > 0 && /* @__PURE__ */ jsx(Hint, {
201
+ icon: "i-ph-terminal",
202
+ title: state.local.stdioMcps.join(", "),
203
+ children: labels.machinesSyncStdio(host.name, shortList(state.local.stdioMcps, labels))
204
+ }),
205
+ config.categories.includes("extensions") && state.local.localExtensions.length > 0 && /* @__PURE__ */ jsx(Hint, {
206
+ icon: "i-ph-puzzle-piece",
207
+ title: state.local.localExtensions.join(", "),
208
+ children: labels.machinesSyncNotSyncable(shortList(state.local.localExtensions, labels))
209
+ }),
210
+ state.conflict && config.mode !== "off" && /* @__PURE__ */ jsxs("div", {
211
+ className: "flex items-center gap-3",
212
+ children: [
213
+ /* @__PURE__ */ jsx(Hint, {
214
+ icon: "i-ph-arrows-left-right",
215
+ children: labels.machinesSyncFrom(state.conflict)
216
+ }),
217
+ /* @__PURE__ */ jsx("span", { className: "flex-1" }),
218
+ takeOver && /* @__PURE__ */ jsx("button", {
219
+ type: "button",
220
+ className: BTN_SECONDARY,
221
+ onClick: () => void takeOverNow(),
222
+ children: labels.machinesSyncTakeOver
223
+ })
224
+ ]
225
+ }),
226
+ overrides.map((field) => /* @__PURE__ */ jsxs("div", {
227
+ className: "flex items-center gap-3",
228
+ children: [
229
+ /* @__PURE__ */ jsxs(Hint, {
230
+ icon: "i-ph-pencil-simple",
231
+ title: labels.machinesSyncEditedOnTitle(host.name),
232
+ children: [
233
+ field,
234
+ " ",
235
+ /* @__PURE__ */ jsx("span", {
236
+ className: "opacity-70",
237
+ children: labels.machinesSyncEditedOn(host.name)
238
+ })
239
+ ]
240
+ }),
241
+ /* @__PURE__ */ jsx("span", { className: "flex-1" }),
242
+ reset && /* @__PURE__ */ jsx("button", {
243
+ type: "button",
244
+ className: BTN_SECONDARY,
245
+ onClick: () => void act(() => reset(host.id, field)),
246
+ children: labels.machinesSyncAgain
247
+ })
248
+ ]
249
+ }, field)),
250
+ /* @__PURE__ */ jsxs("div", {
251
+ className: "flex items-center gap-2 pt-1 border-t border-[var(--zg-hairline)]",
252
+ children: [/* @__PURE__ */ jsxs("span", {
253
+ className: "flex-1 min-w-0 inline-flex items-center gap-2 pt-2 text-xs text-[var(--zg-text-muted)]",
254
+ children: [statusText, /* @__PURE__ */ jsx(SyncOutcomeBadge, { state })]
255
+ }), config.mode !== "off" && state.connected && state.supported && push && /* @__PURE__ */ jsx("button", {
256
+ type: "button",
257
+ className: `${BTN_SECONDARY} mt-2`,
258
+ onClick: () => void act(() => push(host.id)),
259
+ children: labels.machinesSyncPushNow
260
+ })]
261
+ }),
262
+ error && /* @__PURE__ */ jsx(OpLine, {
263
+ kind: "error",
264
+ children: error
265
+ })
266
+ ]
273
267
  });
274
268
  }
275
269
  //#endregion
@@ -1,4 +1,5 @@
1
1
  import { MachinesConfirm } from "./MachinesProvider.js";
2
+ import { NewChatsServer } from "./ServerAddedCard.js";
2
3
  import { CSSProperties } from "react";
3
4
  //#region src/machines/HostsSection.d.ts
4
5
  /** Props for {@link HostsSection}. */
@@ -7,6 +8,8 @@ interface HostsSectionProps {
7
8
  confirm?: MachinesConfirm;
8
9
  /** "Now" for the relative dates (screenshots). Default: the clock. */
9
10
  now?: number;
11
+ /** Where new chats start: a server just added offers to be it. Absent: no such switch. */
12
+ newChats?: NewChatsServer;
10
13
  /** Extra classes on the root. */
11
14
  className?: string;
12
15
  /** Inline styles on the root. */
@@ -17,6 +20,6 @@ interface HostsSectionProps {
17
20
  *
18
21
  * @param props - `confirm`, `now`, `className` and `style`.
19
22
  */
20
- declare function HostsSection({ confirm, now, className, style }: HostsSectionProps): import("react").JSX.Element;
23
+ declare function HostsSection({ confirm, now, newChats, className, style }: HostsSectionProps): import("react").JSX.Element;
21
24
  //#endregion
22
25
  export { HostsSection, HostsSectionProps };
@@ -1,4 +1,5 @@
1
1
  import { BTN_LG_PRIMARY } from "../components/button.js";
2
+ import { Notice } from "../components/Notice.js";
2
3
  import { ErrorNote, FormCard, FormSection, MetaChip } from "../components/Form.js";
3
4
  import { constant, useReadable } from "../chat/headless/store.js";
4
5
  import { useMachinesConfirm, useMachinesHost, useMachinesLabels } from "./MachinesProvider.js";
@@ -11,9 +12,11 @@ import { CapabilitiesView, CapabilityTags, useHostCapabilities } from "./HostCap
11
12
  import { SyncOutcomeBadge } from "./SyncOutcomeBadge.js";
12
13
  import { HostSyncPanel, useHostSync } from "./HostSyncPanel.js";
13
14
  import { SettingsTutorial } from "../settings/SettingsTutorial.js";
15
+ import { ServerAddedCard } from "./ServerAddedCard.js";
14
16
  import { hostOfSettingsFocus } from "./headless/settings-focus.js";
15
17
  import { ServerMachinesPanel } from "./ServerMachinesPanel.js";
16
18
  import { ServerUpdatePanel } from "./ServerUpdatePanel.js";
19
+ import { TokensPanel } from "./TokensPanel.js";
17
20
  import { jsx, jsxs } from "react/jsx-runtime";
18
21
  import { useCallback, useContext, useMemo, useRef, useState } from "react";
19
22
  //#region src/machines/HostsSection.tsx
@@ -44,7 +47,7 @@ const NO_SAVED = constant({
44
47
  *
45
48
  * @param props - `confirm`, `now`, `className` and `style`.
46
49
  */
47
- function HostsSection({ confirm, now, className, style }) {
50
+ function HostsSection({ confirm, now, newChats, className, style }) {
48
51
  const host = useMachinesHost();
49
52
  const labels = useMachinesLabels();
50
53
  const providerConfirm = useMachinesConfirm();
@@ -52,6 +55,7 @@ function HostsSection({ confirm, now, className, style }) {
52
55
  const { hosts } = useReadable(host.hosts ?? NO_HOSTS);
53
56
  const registry = useReadable(host.savedHosts?.state ?? NO_SAVED);
54
57
  const [adding, setAdding] = useState(false);
58
+ const [added, setAdded] = useState(null);
55
59
  /** The host whose page is open; `null`: the list. */
56
60
  const [openId, setOpenId] = useState(null);
57
61
  const open = openId ? hosts.find((h) => h.id === openId) : void 0;
@@ -104,11 +108,19 @@ function HostsSection({ confirm, now, className, style }) {
104
108
  /* @__PURE__ */ jsx(SettingsTutorial, { topic: "hosts" }),
105
109
  adding && /* @__PURE__ */ jsx(AddServerForm, {
106
110
  onCancel: closeAdding,
107
- onAdded: async () => {
111
+ onAdded: async (result) => {
108
112
  closeAdding();
109
113
  await changed();
114
+ if (!result.host) return;
115
+ setAdded(result.host);
116
+ if (newChats && !newChats.hostId) newChats.set(result.host, true);
110
117
  }
111
118
  }),
119
+ added && /* @__PURE__ */ jsx(ServerAddedCard, {
120
+ host: added,
121
+ ...newChats ? { newChats } : {},
122
+ onDone: () => setAdded(null)
123
+ }),
112
124
  registry.status === "error" && registry.error && /* @__PURE__ */ jsx(ErrorNote, { children: labels.machinesSavedHostsError(registry.error.detail) }),
113
125
  /* @__PURE__ */ jsx(FormSection, {
114
126
  title: labels.machinesHostsTitle,
@@ -161,8 +173,10 @@ function HostListRow({ host, saved, onOpen, now }) {
161
173
  ]
162
174
  }), /* @__PURE__ */ jsxs("span", {
163
175
  className: "flex flex-wrap items-center gap-1.5",
164
- children: [/* @__PURE__ */ jsx(CapabilityTags, { caps }), !local && host.error && host.status !== "connected" ? /* @__PURE__ */ jsx("span", {
165
- className: "text-xs text-zg-danger truncate",
176
+ children: [/* @__PURE__ */ jsx(CapabilityTags, { caps }), !local && host.error && host.status !== "connected" ? /* @__PURE__ */ jsx(Notice, {
177
+ tone: "error",
178
+ compact: true,
179
+ className: "min-w-0",
166
180
  children: host.error
167
181
  }) : local ? /* @__PURE__ */ jsx("span", {
168
182
  className: "text-xs text-[var(--zg-text-muted)]",
@@ -181,10 +195,11 @@ function HostListRow({ host, saved, onOpen, now }) {
181
195
  })
182
196
  });
183
197
  }
184
- /** A host's page: its overview and actions, what it can do, its sync and machines. */
198
+ /** A host's page: its overview and actions, what it can do, its sync, machines and tokens. */
185
199
  function HostDetail({ host, saved, onChanged, onBack, confirm, now }) {
186
200
  const labels = useMachinesLabels();
187
- const syncState = useMachinesHost().sync?.state;
201
+ const machinesHost = useMachinesHost();
202
+ const syncState = machinesHost.sync?.state;
188
203
  const { state: sync } = useHostSync(host.id);
189
204
  const local = host.kind === "local";
190
205
  const capabilities = useHostCapabilities(host.id, local || host.status === "connected");
@@ -207,7 +222,6 @@ function HostDetail({ host, saved, onChanged, onBack, confirm, now }) {
207
222
  onRecheck: () => void capabilities.recheck(),
208
223
  local,
209
224
  ...!local && capabilities.install ? { onInstall: (name) => void capabilities.install(name) } : {},
210
- installRestricted: host.scope !== void 0 && host.scope !== "admin",
211
225
  installing: capabilities.installing,
212
226
  installed: capabilities.installed
213
227
  }) })
@@ -281,6 +295,15 @@ function HostDetail({ host, saved, onChanged, onBack, confirm, now }) {
281
295
  ...now !== void 0 ? { now } : {}
282
296
  })
283
297
  }) })
298
+ }),
299
+ machinesHost.tokens && /* @__PURE__ */ jsx(FormSection, {
300
+ title: labels.machinesTokensTitle,
301
+ layout: "cards",
302
+ children: /* @__PURE__ */ jsx(FormCard, { children: /* @__PURE__ */ jsx(TokensPanel, {
303
+ host,
304
+ confirm,
305
+ ...now !== void 0 ? { now } : {}
306
+ }) })
284
307
  })
285
308
  ]
286
309
  });
@@ -0,0 +1,17 @@
1
+ import { CSSProperties } from "react";
2
+ //#region src/machines/MachinesExplainer.d.ts
3
+ /** Props for {@link MachinesExplainer}. */
4
+ interface MachinesExplainerProps {
5
+ /** Extra classes on the root. */
6
+ className?: string;
7
+ /** Inline styles on the root. */
8
+ style?: CSSProperties;
9
+ }
10
+ /**
11
+ * Renders the picture of this app, the server and its machines, with the sentence that explains them.
12
+ *
13
+ * @param props - `className` and `style`.
14
+ */
15
+ declare function MachinesExplainer({ className, style }: MachinesExplainerProps): import("react").JSX.Element;
16
+ //#endregion
17
+ export { MachinesExplainer, MachinesExplainerProps };
@@ -0,0 +1,71 @@
1
+ import { useMachinesLabels } from "./MachinesProvider.js";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ //#region src/machines/MachinesExplainer.tsx
4
+ /** One place in the picture: its glyph, its name, what it does. */
5
+ function Place({ icon, name, fact }) {
6
+ return /* @__PURE__ */ jsxs("li", {
7
+ className: "flex-1 min-w-0 flex flex-col items-center gap-1 text-center",
8
+ children: [
9
+ /* @__PURE__ */ jsx("span", {
10
+ "aria-hidden": true,
11
+ className: "zg-well inline-flex items-center justify-center size-9 rounded-zg-md text-base text-[var(--zg-text-muted)]",
12
+ children: /* @__PURE__ */ jsx("span", { className: icon })
13
+ }),
14
+ /* @__PURE__ */ jsx("span", {
15
+ className: "text-xs font-medium text-[var(--zg-text)]",
16
+ children: name
17
+ }),
18
+ /* @__PURE__ */ jsx("span", {
19
+ className: "text-zg-meta text-[var(--zg-text-muted)] leading-snug",
20
+ children: fact
21
+ })
22
+ ]
23
+ });
24
+ }
25
+ /** The arrow between two places. */
26
+ function Arrow() {
27
+ return /* @__PURE__ */ jsx("li", {
28
+ "aria-hidden": true,
29
+ className: "shrink-0 pt-2.5 text-[var(--zg-text-subtle)]",
30
+ children: /* @__PURE__ */ jsx("span", { className: "i-ph-arrow-right text-zg-ui" })
31
+ });
32
+ }
33
+ /**
34
+ * Renders the picture of this app, the server and its machines, with the sentence that explains them.
35
+ *
36
+ * @param props - `className` and `style`.
37
+ */
38
+ function MachinesExplainer({ className = "", style }) {
39
+ const labels = useMachinesLabels();
40
+ return /* @__PURE__ */ jsxs("div", {
41
+ className: `space-y-3 ${className}`.trimEnd(),
42
+ style,
43
+ children: [/* @__PURE__ */ jsxs("ol", {
44
+ className: "m-0 p-0 list-none flex items-start gap-1",
45
+ children: [
46
+ /* @__PURE__ */ jsx(Place, {
47
+ icon: "i-ph-laptop",
48
+ name: labels.machinesPictureApp,
49
+ fact: labels.machinesPictureAppFact
50
+ }),
51
+ /* @__PURE__ */ jsx(Arrow, {}),
52
+ /* @__PURE__ */ jsx(Place, {
53
+ icon: "i-ph-hard-drives",
54
+ name: labels.machinesPictureServer,
55
+ fact: labels.machinesPictureServerFact
56
+ }),
57
+ /* @__PURE__ */ jsx(Arrow, {}),
58
+ /* @__PURE__ */ jsx(Place, {
59
+ icon: "i-ph-desktop-tower",
60
+ name: labels.machinesPictureMachines,
61
+ fact: labels.machinesPictureMachinesFact
62
+ })
63
+ ]
64
+ }), /* @__PURE__ */ jsx("p", {
65
+ className: "m-0 text-xs text-[var(--zg-text-muted)] text-center zg-balance",
66
+ children: labels.machinesExplain
67
+ })]
68
+ });
69
+ }
70
+ //#endregion
71
+ export { MachinesExplainer };
@@ -1,6 +1,6 @@
1
1
  import { SessionPresence } from "./headless/presence.js";
2
2
  import { MachinesLabels } from "./headless/labels.js";
3
- import { MachinesAction, MachinesHost } from "./headless/host.js";
3
+ import { MachineInfo, MachinesAction, MachinesHost } from "./headless/host.js";
4
4
  import { ConfirmOptions } from "../components/ConfirmDialog.js";
5
5
  import { ReactNode } from "react";
6
6
  //#region src/machines/MachinesProvider.d.ts
@@ -23,6 +23,11 @@ interface MachinesProviderProps {
23
23
  * @param props - Provider props: the `host`, optional `labels` and `confirm`, and the `children` to render.
24
24
  */
25
25
  declare function MachinesProvider({ host, labels, confirm, children }: MachinesProviderProps): import("react").JSX.Element;
26
+ /**
27
+ * Wraps a subtree rendered elsewhere (a modal layer, mounted above the providers) in this provider's host,
28
+ * confirm and labels, so it reads what the place that opened it reads.
29
+ */
30
+ declare function useMachinesBridge(): (node: ReactNode) => ReactNode;
26
31
  /** Returns the {@link MachinesHost} from the nearest {@link MachinesProvider}, or an empty host outside one. */
27
32
  declare function useMachinesHost(): MachinesHost;
28
33
  /** Returns how the machines components ask before a destructive action. */
@@ -42,6 +47,13 @@ declare function usePermitted(action: MachinesAction): boolean;
42
47
  * @param enabled - Whether to listen (the app has servers and shows a picker).
43
48
  */
44
49
  declare function useLentServers(enabled: boolean): ReadonlySet<string>;
50
+ /**
51
+ * The machines of each of `hostIds`, by host id, kept current (a machine that joins or leaves shows at once).
52
+ * Empty without the host's `machines`, or when the token cannot list them.
53
+ *
54
+ * @param hostIds - The servers to list.
55
+ */
56
+ declare function useServerMachines(hostIds: readonly string[]): ReadonlyMap<string, readonly MachineInfo[]>;
45
57
  /** The names of the machines last heard online, from every host; empty without the host's `machines`. */
46
58
  declare function useOnlineMachines(): ReadonlySet<string>;
47
59
  /** Every live session's presence, by session id (list-level decisions: ordering, counts); empty without `presence`. */
@@ -53,4 +65,4 @@ declare function usePresenceMap(): ReadonlyMap<string, SessionPresence>;
53
65
  */
54
66
  declare function useSessionPresence(sessionId: string | null): SessionPresence | null;
55
67
  //#endregion
56
- export { MachinesConfirm, MachinesProvider, MachinesProviderProps, useLentServers, useMachinesConfirm, useMachinesHost, useMachinesLabels, useOnlineMachines, usePermitted, usePresenceMap, useSessionPresence };
68
+ export { MachinesConfirm, MachinesProvider, MachinesProviderProps, useLentServers, useMachinesBridge, useMachinesConfirm, useMachinesHost, useMachinesLabels, useOnlineMachines, usePermitted, usePresenceMap, useServerMachines, useSessionPresence };