@k2b/cloud 0.40.0 → 0.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/package.json +9 -5
  2. package/src/_internal/bounded-json.ts +14 -2
  3. package/src/_internal/capabilities.ts +87 -8
  4. package/src/_internal/capability-reviews.ts +6 -0
  5. package/src/_internal/capability-sentences.ts +2 -1
  6. package/src/_internal/capability-timeout.ts +71 -0
  7. package/src/_internal/define-app.ts +158 -92
  8. package/src/_internal/heartbeat.ts +203 -14
  9. package/src/_internal/http-drain.ts +56 -0
  10. package/src/_internal/registry-validation.ts +3 -0
  11. package/src/_internal/registry.ts +28 -1
  12. package/src/_internal/runtime-context.ts +1 -0
  13. package/src/_internal/setup-lock.ts +103 -0
  14. package/src/_internal/status-preserving-ssr.ts +2 -0
  15. package/src/access/PermissionEditor.tsx +16 -17
  16. package/src/access/PrincipalPicker.tsx +45 -10
  17. package/src/access/messages.ts +8 -0
  18. package/src/access/principal-label.ts +18 -0
  19. package/src/access/ui.ts +1 -0
  20. package/src/account/EntitySearch.tsx +5 -4
  21. package/src/ai/action-review.ts +2 -1
  22. package/src/ai/app-skill-store.ts +1 -1
  23. package/src/ai/capabilities.ts +21 -3
  24. package/src/ai/capability-execution.ts +14 -12
  25. package/src/ai/chat/action-card.ts +76 -4
  26. package/src/ai/chat/action-messages.ts +14 -0
  27. package/src/ai/chat/action-question.browser-harness.tsx +12 -0
  28. package/src/ai/chat/action-question.tsx +214 -23
  29. package/src/ai/chat/action-text.ts +288 -0
  30. package/src/ai/chat/tool-action-words.ts +31 -0
  31. package/src/ai/chat/tool-action.tsx +1 -26
  32. package/src/ai/chat-tasks.ts +2 -1
  33. package/src/ai/client/controller.ts +150 -32
  34. package/src/ai/client/transport.ts +14 -2
  35. package/src/ai/code-capability-routes.ts +27 -23
  36. package/src/ai/code-runtime-tools.ts +14 -16
  37. package/src/ai/code-source-tools.ts +16 -18
  38. package/src/ai/executor.ts +64 -21
  39. package/src/ai/fetch-file-tool.ts +67 -76
  40. package/src/ai/firecrawl-tools.ts +15 -2
  41. package/src/ai/http.ts +1 -0
  42. package/src/ai/index.ts +1 -0
  43. package/src/ai/migrate.ts +28 -0
  44. package/src/ai/open-questions.ts +168 -0
  45. package/src/ai/projects.ts +1 -2
  46. package/src/ai/protocol.ts +2 -2
  47. package/src/ai/question-text.ts +8 -0
  48. package/src/ai/recent-resources.ts +12 -5
  49. package/src/ai/review-content.ts +77 -0
  50. package/src/ai/routes.ts +119 -35
  51. package/src/ai/runtime.ts +1 -0
  52. package/src/ai/skill-tool.ts +17 -6
  53. package/src/ai/skills-routes.ts +72 -27
  54. package/src/ai/skills.ts +139 -60
  55. package/src/ai/store.ts +184 -31
  56. package/src/ai/testing.ts +36 -0
  57. package/src/ai/tool-sentences.ts +152 -34
  58. package/src/ai/tool-wording.ts +12 -6
  59. package/src/ai/tools.ts +8 -3
  60. package/src/ai/types.ts +25 -4
  61. package/src/ai/usage.ts +2 -2
  62. package/src/api/admin-core-settings.ts +15 -2
  63. package/src/api/admin-geo.ts +54 -0
  64. package/src/api/admin-linux-identities.ts +6 -3
  65. package/src/api/admin-outgoing-mail.ts +29 -15
  66. package/src/api/app-approval-actions.ts +31 -7
  67. package/src/api/approvals-loader.ts +3 -3
  68. package/src/api/approvals.ts +51 -0
  69. package/src/api/apps.ts +4 -2
  70. package/src/api/auth/schemas.ts +3 -0
  71. package/src/api/auth.ts +54 -18
  72. package/src/api/capabilities.ts +258 -181
  73. package/src/api/capability-streams.ts +21 -13
  74. package/src/api/cli-plugins.ts +4 -1
  75. package/src/api/geo-glyphs.ts +11 -0
  76. package/src/api/geo.ts +128 -0
  77. package/src/api/help.ts +12 -4
  78. package/src/api/index.ts +5 -0
  79. package/src/api/mcp.ts +73 -41
  80. package/src/api/me-panel-consent.ts +8 -5
  81. package/src/api/me.ts +79 -3
  82. package/src/api/search.ts +21 -14
  83. package/src/api/sync-ops.ts +19 -13
  84. package/src/api/widgets.ts +42 -18
  85. package/src/approvals/Approvals.tsx +30 -66
  86. package/src/approvals/approval-card.ts +68 -0
  87. package/src/browser/CloudResourceSearch.browser-harness.tsx +53 -1
  88. package/src/browser/CloudResourceSearch.tsx +3 -13
  89. package/src/browser/PanelLeaveNotice.tsx +18 -0
  90. package/src/browser/navigation-search.ts +78 -25
  91. package/src/browser/panel-leave.ts +69 -0
  92. package/src/browser/panel-messages.ts +12 -0
  93. package/src/browser/panel-slot.ts +173 -24
  94. package/src/browser/panel.ts +3 -0
  95. package/src/browser/resource-search-messages.ts +2 -0
  96. package/src/capabilities/client.ts +28 -1
  97. package/src/capabilities/executions.ts +22 -3
  98. package/src/capabilities/geo-client.ts +57 -0
  99. package/src/capabilities/response.ts +2 -1
  100. package/src/capabilities/review-storage.ts +24 -0
  101. package/src/capabilities/reviews.ts +17 -3
  102. package/src/capabilities/server.ts +36 -16
  103. package/src/cli/access.ts +15 -23
  104. package/src/cli/admin/linux.ts +13 -2
  105. package/src/cli/admin/outgoing-mail.ts +26 -4
  106. package/src/cli/capabilities.ts +19 -0
  107. package/src/config/env.ts +0 -6
  108. package/src/contracts/app-access.ts +48 -0
  109. package/src/contracts/app-approval.ts +3 -3
  110. package/src/contracts/app.ts +4 -1
  111. package/src/contracts/approvals.ts +2 -2
  112. package/src/contracts/avatar.ts +186 -0
  113. package/src/contracts/capabilities.ts +149 -55
  114. package/src/contracts/geo-admin.ts +127 -0
  115. package/src/contracts/geo-map.ts +19 -0
  116. package/src/contracts/geo-route.ts +168 -0
  117. package/src/contracts/geo.ts +248 -0
  118. package/src/contracts/index.ts +4 -0
  119. package/src/contracts/outgoing-mail.ts +17 -4
  120. package/src/contracts/registry.ts +2 -0
  121. package/src/contracts/shared.ts +3 -0
  122. package/src/events/app-access.ts +68 -0
  123. package/src/events/live-delivery.ts +128 -0
  124. package/src/events/live.ts +14 -130
  125. package/src/geo/CloudMap.tsx +95 -0
  126. package/src/geo/map-messages.ts +17 -0
  127. package/src/geo/ui.ts +1 -0
  128. package/src/index.ts +2 -0
  129. package/src/server/client-ip.ts +36 -0
  130. package/src/server/index.ts +3 -4
  131. package/src/server/middleware/app-access.ts +312 -0
  132. package/src/server/middleware/auth.ts +5 -3
  133. package/src/server/middleware/invocation.ts +11 -0
  134. package/src/server/middleware/rate-limit.ts +4 -4
  135. package/src/server/services/access.ts +13 -9
  136. package/src/server/services/index.ts +0 -2
  137. package/src/server/services/services.ts +0 -2
  138. package/src/services/accounts/app.ts +23 -3
  139. package/src/services/accounts/posix.ts +21 -7
  140. package/src/services/accounts/users.ts +12 -1
  141. package/src/services/allowed-network-fetch.ts +16 -10
  142. package/src/services/app-access-metrics.ts +24 -0
  143. package/src/services/app-access.ts +123 -0
  144. package/src/services/app-discovery.ts +27 -0
  145. package/src/services/approvals/content.ts +40 -0
  146. package/src/services/approvals/device.ts +49 -33
  147. package/src/services/approvals/index.ts +15 -6
  148. package/src/services/approvals/list.ts +6 -11
  149. package/src/services/approvals/question.ts +72 -0
  150. package/src/services/audit/index.ts +1 -0
  151. package/src/services/auth-flows/ipa.ts +39 -2
  152. package/src/services/auth-flows/password-reset.ts +32 -6
  153. package/src/services/downstream-budget.ts +87 -0
  154. package/src/services/geo/admin.ts +262 -0
  155. package/src/services/geo/bucket.ts +67 -0
  156. package/src/services/geo/cache.ts +57 -0
  157. package/src/services/geo/costs.ts +5 -0
  158. package/src/services/geo/errors.ts +41 -0
  159. package/src/services/geo/fixtures/README.md +17 -0
  160. package/src/services/geo/fixtures/along.json +355 -0
  161. package/src/services/geo/fixtures/autocomplete.json +218 -0
  162. package/src/services/geo/fixtures/geocode.json +129 -0
  163. package/src/services/geo/fixtures/places.json +355 -0
  164. package/src/services/geo/fixtures/reverse.json +61 -0
  165. package/src/services/geo/fixtures/routing.json +57 -0
  166. package/src/services/geo/geoapify-route.ts +93 -0
  167. package/src/services/geo/geoapify.ts +281 -0
  168. package/src/services/geo/ledger.ts +122 -0
  169. package/src/services/geo/map.ts +160 -0
  170. package/src/services/geo/migrate.ts +25 -0
  171. package/src/services/geo/polyline.ts +184 -0
  172. package/src/services/geo/route-chain.ts +145 -0
  173. package/src/services/geo/route-costs.ts +9 -0
  174. package/src/services/geo/route-geometry.ts +39 -0
  175. package/src/services/geo/route-plan.ts +172 -0
  176. package/src/services/geo/route-service.ts +433 -0
  177. package/src/services/geo/service.ts +300 -0
  178. package/src/services/geo/settings.ts +49 -0
  179. package/src/services/help/index.ts +16 -7
  180. package/src/services/help/types.ts +6 -1
  181. package/src/services/identity/invocation-actor.ts +20 -2
  182. package/src/services/identity/issue-invocation.ts +67 -0
  183. package/src/services/identity/key-ring.ts +5 -3
  184. package/src/services/identity/runtime-config.ts +23 -0
  185. package/src/services/index.ts +11 -0
  186. package/src/services/mandates/index.ts +40 -3
  187. package/src/services/network-security.ts +6 -3
  188. package/src/services/network-transport.ts +99 -0
  189. package/src/services/notifications/catalog.ts +3 -2
  190. package/src/services/notifications/runtime.ts +1 -0
  191. package/src/services/notifications/web-push-transport.ts +45 -38
  192. package/src/services/outgoing-mail/dispatcher.ts +6 -1
  193. package/src/services/outgoing-mail/index.ts +55 -1
  194. package/src/services/outgoing-mail/messages.ts +82 -3
  195. package/src/services/outgoing-mail/resolve-host.ts +2 -2
  196. package/src/services/outgoing-mail/retention.ts +13 -1
  197. package/src/services/outgoing-mail/store.ts +36 -6
  198. package/src/services/outgoing-mail/test-send.ts +34 -4
  199. package/src/services/outgoing-mail/transport.ts +1 -1
  200. package/src/services/pdf/gotenberg.ts +11 -38
  201. package/src/services/pdf/markdown.ts +160 -2
  202. package/src/services/pdf/template-preview.ts +1 -1
  203. package/src/services/public-http.ts +28 -40
  204. package/src/services/session/index.ts +203 -29
  205. package/src/services/settings/app.ts +4 -1
  206. package/src/services/settings/core-settings.ts +88 -0
  207. package/src/services/settings/defaults.ts +8 -2
  208. package/src/services/settings/errors.ts +11 -0
  209. package/src/services/settings/geo-budget.ts +40 -0
  210. package/src/services/settings/index.ts +4 -3
  211. package/src/services/settings/store.ts +25 -17
  212. package/src/services/weather/geo.ts +29 -111
  213. package/src/services/weather/index.ts +4 -3
  214. package/src/services/weather/locations.ts +8 -5
  215. package/src/services/weather/migrate.ts +1 -0
  216. package/src/services/weather/settings.ts +0 -16
  217. package/src/shared/__snapshots__/avatar-art.test.ts.snap +5 -0
  218. package/src/shared/avatar-art.ts +400 -0
  219. package/src/shared/index.ts +2 -0
  220. package/src/shared/network-address.ts +22 -3
  221. package/src/shared/template-rendering.ts +36 -4
  222. package/src/shared-text/documents.ts +1 -1
  223. package/src/shared-text/index.ts +2 -0
  224. package/src/shared-text/log.ts +51 -3
  225. package/src/shared-text/snapshots.ts +340 -0
  226. package/src/ssr/AdminLayout.tsx +4 -2
  227. package/src/ssr/CloudShell.island.tsx +6 -0
  228. package/src/ssr/HelpPanelArticle.island.tsx +308 -0
  229. package/src/ssr/HelpPanelBack.island.tsx +32 -0
  230. package/src/ssr/HelpPanelMenu.island.tsx +133 -0
  231. package/src/ssr/HelpPanelSearch.island.tsx +123 -0
  232. package/src/ssr/HelpPanelShortcuts.island.tsx +22 -0
  233. package/src/ssr/HelpPanelView.island.tsx +27 -0
  234. package/src/ssr/Layout.tsx +65 -15
  235. package/src/ssr/LayoutHelp.browser-harness.tsx +1 -1
  236. package/src/ssr/LayoutHelp.tsx +185 -542
  237. package/src/ssr/LayoutHelpPanel.browser-harness.tsx +6 -7
  238. package/src/ssr/LayoutHelpPanel.server.browser-harness.tsx +131 -0
  239. package/src/ssr/LayoutHelpPanel.server.tsx +115 -0
  240. package/src/ssr/PanelRuntime.island.tsx +11 -7
  241. package/src/ssr/PwaLayout.tsx +2 -2
  242. package/src/ssr/RailApps.tsx +6 -0
  243. package/src/ssr/ShellRuntime.island.tsx +23 -7
  244. package/src/ssr/__snapshots__/Layout.unchanged.render.test.tsx.snap +151 -0
  245. package/src/ssr/__snapshots__/LayoutHelp.ssr.render.test.tsx.snap +29 -0
  246. package/src/ssr/admin-navigation.ts +1 -0
  247. package/src/ssr/app-badges.ts +6 -1
  248. package/src/ssr/compact-shell.browser-harness.ts +44 -5
  249. package/src/ssr/help.ts +7 -5
  250. package/src/ssr/index.ts +2 -1
  251. package/src/ssr/islands/index.ts +3 -4
  252. package/src/ssr/layout-context.ts +2 -0
  253. package/src/ssr/layout-help-panel-controls.tsx +43 -0
  254. package/src/ssr/layout-help-panel-document.ts +67 -0
  255. package/src/ssr/layout-help-panel-lifecycle.ts +32 -0
  256. package/src/ssr/layout-help-panel-menu.tsx +113 -0
  257. package/src/ssr/layout-help-panel-modules.ts +7 -0
  258. package/src/ssr/layout-help-panel-reader.tsx +159 -0
  259. package/src/ssr/layout-help-panel-search.tsx +69 -0
  260. package/src/ssr/layout-help-panel-shortcuts.ts +7 -0
  261. package/src/ssr/layout-help-panel-state.ts +141 -0
  262. package/src/ssr/layout-help-panel-types.ts +19 -0
  263. package/src/ssr/layout-help-views.tsx +484 -0
  264. package/src/ssr/mobile-menu-history.ts +4 -0
  265. package/src/ssr/page-swap-fixture/Column.island.tsx +15 -0
  266. package/src/ssr/page-swap-fixture/ProviderProbe.island.tsx +31 -0
  267. package/src/ssr/page-swap.browser-harness.tsx +177 -0
  268. package/src/ssr/page-swap.ts +28 -0
  269. package/src/ssr/page-trail-runtime.ts +32 -13
  270. package/src/ssr/panel-consent.ts +2 -2
  271. package/src/ssr/panel-idle.ts +9 -0
  272. package/src/ssr/panel-slot.browser-harness.tsx +3 -0
  273. package/src/ssr/platform-messages.ts +8 -0
  274. package/src/ssr/runtime.ts +17 -0
  275. package/src/ssr/shell-data.tsx +10 -2
  276. package/src/styles/approvals.css +6 -0
  277. package/src/styles/effects.css +15 -0
  278. package/src/styles/global.css +70 -6
  279. package/src/server/services/geo.ts +0 -215
@@ -10,6 +10,7 @@ import { PANEL_HELP_ID_MAX_LENGTH, PanelPageContextSchema } from "../contracts/p
10
10
  import { isPwaShellAvailable } from "../contracts/pwa";
11
11
  import { defaultRailPreferences } from "../contracts/rail-preferences";
12
12
  import { hasRole, type User } from "../contracts/shared";
13
+ import { isAppSessionActor } from "../server/actor";
13
14
  import { getLocale } from "../server/locale";
14
15
  import { getDateConfig } from "../server/time";
15
16
  import { dates, resolveHomePath } from "../shared";
@@ -27,14 +28,15 @@ import { HELP_VIEW_LIMIT } from "./layout-help-start";
27
28
  import type { LayoutBreadcrumb } from "./layout-runtime";
28
29
  import PageTrailRow from "./PageTrailRow";
29
30
  import PanelSlot from "./PanelSlot";
31
+ import { getPageSwapBuild, pageSwapSignature } from "./page-swap";
30
32
  import { derivePageTrail } from "./page-trail";
31
33
  import { platformMessages } from "./platform-messages";
32
34
  import { sortRailApps } from "./rail-navigation";
33
35
  import { requestPath } from "./request-path";
34
- import { getLocalizedRuntimeContext, type RuntimeContext } from "./runtime";
36
+ import { getDisplayRuntimeContext, getLocalizedRuntimeContext, type RuntimeContext } from "./runtime";
35
37
  import ShellFocusToggle from "./ShellFocusToggle";
36
38
  import ShellRuntime from "./ShellRuntime.island";
37
- import { type ShellData, ShellDataProvider } from "./shell-data";
39
+ import { type ShellData, ShellDataProvider, ShellDataScript } from "./shell-data";
38
40
 
39
41
  // Types
40
42
  type Breadcrumb = LayoutBreadcrumb;
@@ -164,7 +166,9 @@ export default function Layout(props: LayoutProps) {
164
166
  const lang = getLocale(c);
165
167
  const t = platformMessages.resolve([lang]).t;
166
168
  const user = c.get("user");
167
- const providers = user && props.panel !== false ? visiblePanelProviders(runtime.apps, user, lang) : [];
169
+ const displayIds = new Set(getDisplayRuntimeContext(c).apps.map((app) => app.id));
170
+ const displayApps = runtime.apps.filter((app) => displayIds.has(app.id));
171
+ const providers = user && props.panel !== false ? visiblePanelProviders(displayApps, user, lang) : [];
168
172
  const panelState = readPanelCookie(
169
173
  providers.length ? cookie : undefined,
170
174
  providers.map((provider) => provider.id),
@@ -178,12 +182,14 @@ export default function Layout(props: LayoutProps) {
178
182
  readAppWorkspaceLayoutCookie(cookie, currentApp?.id),
179
183
  workspaceSidebarCollapsible,
180
184
  );
181
- const { primary: primaryApps, more: moreApps } = buildNavLinks(runtime.apps, user, lang);
185
+ const { primary: primaryApps, more: moreApps } = buildNavLinks(displayApps, user, lang);
182
186
  const allApps = sortRailApps([...primaryApps, ...moreApps], lang);
183
187
  const visibleAppIds = new Set(allApps.map((app) => app.id));
184
188
  const searchLinks = Object.fromEntries(
185
- runtime.apps.flatMap((app) => (visibleAppIds.has(app.id) && app.searchLinks?.length ? [[app.id, app.searchLinks] as const] : [])),
189
+ displayApps.flatMap((app) => (visibleAppIds.has(app.id) && app.searchLinks?.length ? [[app.id, app.searchLinks] as const] : [])),
186
190
  );
191
+ const swapBuild = getPageSwapBuild(c);
192
+ const swap = swapBuild !== undefined && !focusMode && !!currentRoute?.prefix;
187
193
  const settings = c.get("settings");
188
194
  const announcements = c.get("announcements");
189
195
  const appName = settings?.app?.name || "Cloud";
@@ -212,7 +218,7 @@ export default function Layout(props: LayoutProps) {
212
218
  // The app bar and the app's navigation hidden with Cmd/Ctrl+\ or the sidebar buttons; phones ignore it in CSS.
213
219
  const shellFocus = showRail && readShellFocusCookie(cookie);
214
220
  // The profile menu offers the mobile app only while the installation runs it.
215
- const appHref = user && isPwaShellAvailable(runtime.apps) ? "/me/app" : undefined;
221
+ const appHref = user && isPwaShellAvailable(displayApps) ? "/me/app" : undefined;
216
222
  const profileName = user?.displayName || user?.uid || "?";
217
223
  const profileAvatarSrc =
218
224
  user?.avatarHash && user.id
@@ -271,6 +277,30 @@ export default function Layout(props: LayoutProps) {
271
277
  searchLinks,
272
278
  appId: currentApp?.id,
273
279
  };
280
+ // What the kept shell shows outside the column: when any of it differs, the next page loads as a document.
281
+ const signature = swap
282
+ ? pageSwapSignature({
283
+ app: currentApp?.id,
284
+ kind: user ? "app" : "anonymous",
285
+ user: user?.id ?? null,
286
+ appSession: isAppSessionActor(c.get("actor")),
287
+ locale: lang,
288
+ theme: c.get("page").theme,
289
+ build: swapBuild,
290
+ shell: {
291
+ // The document's <html> theme and the profile menu keep this preference.
292
+ themePreference: theme,
293
+ providers,
294
+ apps: allApps,
295
+ legalLinks,
296
+ searchLinks,
297
+ home: shellData.home,
298
+ profile: shellData.profile,
299
+ announcements: user ? (announcements?.latestAnnouncementVersion ?? null) : null,
300
+ help: registeredHelp?.manifestHash ?? (layoutHelpFailed(c) ? "failed" : null),
301
+ },
302
+ })
303
+ : undefined;
274
304
  if (focusMode) {
275
305
  return (
276
306
  <LocaleProvider locale={lang}>
@@ -310,8 +340,11 @@ export default function Layout(props: LayoutProps) {
310
340
  return (
311
341
  <LocaleProvider locale={lang}>
312
342
  <div
313
- class={`cloud-app-canvas relative flex w-full ${fullPage ? "h-dvh overflow-hidden" : "min-h-dvh md:h-dvh md:overflow-hidden"}`}
343
+ class={`cloud-app-canvas relative flex w-full ${fullPage && !swap ? "h-dvh overflow-hidden" : "min-h-dvh md:h-dvh md:overflow-hidden"}`}
314
344
  style={canvasStyle}
345
+ data-nav-shell={signature}
346
+ data-nav-scope={swap ? currentRoute?.prefix : undefined}
347
+ data-nav-attributes={swap ? "data-layout-full-page data-workspace-sidebar-collapsed" : undefined}
315
348
  data-panel={panelState.open ? "open" : undefined}
316
349
  data-app-id={currentApp?.id}
317
350
  data-app-base={currentRoute?.prefix}
@@ -334,13 +367,18 @@ export default function Layout(props: LayoutProps) {
334
367
  ? { entries: announcements.announcements, latestVersion: announcements.latestAnnouncementVersion }
335
368
  : undefined
336
369
  }
337
- banners={user && announcements?.banners.length ? true : undefined}
370
+ banners={user && (swap || announcements?.banners.length) ? true : undefined}
338
371
  />
339
- <ShellDataProvider data={shellData}>
372
+ <ShellDataProvider data={shellData} skipScript={swap}>
340
373
  {showRail && <LayoutRail currentPath={requestPath(c)} panelOpen={panel ? panelState.open : undefined} />}
341
374
  {showRail && <ShellFocusToggle variant="float" />}
342
375
  {showRail && <div class="cloud-shell-reveal" data-cloud-shell-reveal="" aria-hidden="true" />}
343
- <div class="layout-shell-content flex min-h-0 min-w-0 flex-1 flex-col" data-cloud-app-area="">
376
+ <div
377
+ class="layout-shell-content flex min-h-0 min-w-0 flex-1 flex-col"
378
+ data-cloud-app-area=""
379
+ data-nav-root={swap ? "" : undefined}
380
+ >
381
+ {swap && <ShellDataScript data={shellData} />}
344
382
  <LayoutHeader
345
383
  panelOpen={panel ? panelState.open : undefined}
346
384
  authenticated={showRail}
@@ -353,19 +391,31 @@ export default function Layout(props: LayoutProps) {
353
391
  {user && <ExpiryWarnings user={user} dateConfig={dateConfig} locale={lang} />}
354
392
  <PageTrailProvider trail={pageTrail}>
355
393
  <PageTrailRow trail={pageTrail} />
356
- <main class={`layout-content-main min-h-0 min-w-0 flex-1 ${mainLayoutClass}`}>
394
+ <main
395
+ class={`layout-content-main min-h-0 min-w-0 flex-1 ${mainLayoutClass}`}
396
+ data-scroll-preserve={swap ? "cloud-main" : undefined}
397
+ data-scroll-page={swap ? "" : undefined}
398
+ >
357
399
  <AppWorkspace.LayoutStateProvider state={workspaceLayout}>{props.children}</AppWorkspace.LayoutStateProvider>
358
400
  </main>
359
401
  </PageTrailProvider>
360
402
  {!fullPage && !showRail && <LayoutFooter appName={settings?.app?.copyright || appName} legalLinks={legalLinks} />}
403
+ {swap && (
404
+ <div data-print-fallback="">
405
+ <p>{t.printFallbackTitle}</p>
406
+ <p>{props.printHint ?? t.printFallbackHint}</p>
407
+ </div>
408
+ )}
361
409
  </div>
362
410
  {panel && <PanelSlot panel={panel} state={panelState} platform={shellData.platform} />}
363
411
  {showRail && <LayoutTabBar currentPath={requestPath(c)} />}
364
412
  </ShellDataProvider>
365
- <div data-print-fallback="">
366
- <p>{t.printFallbackTitle}</p>
367
- <p>{props.printHint ?? t.printFallbackHint}</p>
368
- </div>
413
+ {!swap && (
414
+ <div data-print-fallback="">
415
+ <p>{t.printFallbackTitle}</p>
416
+ <p>{props.printHint ?? t.printFallbackHint}</p>
417
+ </div>
418
+ )}
369
419
  </div>
370
420
  </LocaleProvider>
371
421
  );
@@ -100,7 +100,7 @@ if (!main) throw new Error("Missing Layout main");
100
100
  const embedded = params.has("embedded");
101
101
  const referenceHost = params.get("host");
102
102
  if (referenceHost === "grids" || referenceHost === "pulse") {
103
- // The Grids and Pulse query reference windows: one article beside the reference sidebar, without the Cloud shell.
103
+ // The Grids query reference windows: one article beside the reference sidebar, without the Cloud shell.
104
104
  const host = document.createElement("div");
105
105
  host.className = "h-dvh";
106
106
  document.body.replaceChildren(host);