@k2b/cloud 0.38.0 → 0.40.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.
- package/README.md +8 -0
- package/package.json +12 -5
- package/scripts/build-canvas-workers.ts +109 -29
- package/scripts/build.ts +3 -5
- package/src/_internal/app-favicon.ts +4 -2
- package/src/_internal/app-path.ts +25 -0
- package/src/_internal/app-presentation.ts +4 -0
- package/src/_internal/canvas-worker.ts +5 -3
- package/src/_internal/capabilities.ts +72 -48
- package/src/_internal/capability-reviews.ts +81 -0
- package/src/_internal/capability-schemas.ts +29 -0
- package/src/_internal/capability-sentences.ts +216 -1
- package/src/_internal/capability-streams.ts +7 -0
- package/src/_internal/define-app.ts +63 -16
- package/src/_internal/font-preloads.ts +2 -1
- package/src/_internal/panel-cookie.ts +39 -0
- package/src/_internal/registry-validation.ts +21 -26
- package/src/_internal/runtime-context.ts +1 -0
- package/src/_internal/runtime-watcher.ts +6 -0
- package/src/_internal/static-assets.ts +52 -3
- package/src/_internal/status-preserving-ssr.ts +2 -0
- package/src/access/PermissionEditor.browser-harness.tsx +57 -38
- package/src/access/PermissionEditor.tsx +32 -7
- package/src/access/ResourceApiKeys.tsx +5 -1
- package/src/account/EntitySearch.tsx +1 -1
- package/src/ai/action-review.ts +101 -0
- package/src/ai/approval-routes.ts +5 -2
- package/src/ai/approvals.ts +139 -28
- package/src/ai/background-review.ts +72 -0
- package/src/ai/browser.ts +10 -0
- package/src/ai/capabilities.ts +29 -11
- package/src/ai/capability-execution.ts +76 -43
- package/src/ai/capability-result.ts +95 -0
- package/src/ai/chat/action-card.ts +398 -0
- package/src/ai/chat/action-messages.ts +129 -0
- package/src/ai/chat/action-question.browser-harness.tsx +245 -0
- package/src/ai/chat/action-question.fixtures.ts +733 -0
- package/src/ai/chat/action-question.tsx +669 -0
- package/src/ai/chat/action-sentences.ts +1 -44
- package/src/ai/chat/blocks.tsx +19 -25
- package/src/ai/chat/message-actions.tsx +6 -0
- package/src/ai/chat/tool-action.tsx +481 -0
- package/src/ai/chat/turn-view.tsx +45 -163
- package/src/ai/chat/view-block.tsx +22 -7
- package/src/ai/chat-task-contracts.ts +31 -3
- package/src/ai/chat-task-reasons-migrate.ts +75 -0
- package/src/ai/chat-task-reasons.ts +92 -0
- package/src/ai/chat-tasks.ts +438 -78
- package/src/ai/client/controller.ts +59 -0
- package/src/ai/default-tools.ts +9 -1
- package/src/ai/executor.ts +190 -39
- package/src/ai/index.ts +14 -0
- package/src/ai/migrate.ts +39 -4
- package/src/ai/projects-routes.ts +3 -0
- package/src/ai/protocol.ts +14 -2
- package/src/ai/recent-resources.ts +240 -0
- package/src/ai/recent-sent-refs.ts +38 -0
- package/src/ai/request-context.ts +7 -1
- package/src/ai/routes.ts +172 -2
- package/src/ai/runtime.ts +13 -27
- package/src/ai/skills-routes.ts +3 -0
- package/src/ai/skills.ts +10 -1
- package/src/ai/store.ts +232 -27
- package/src/ai/timeline.ts +9 -1
- package/src/ai/tool-audit.ts +8 -0
- package/src/ai/tool-wording.ts +67 -0
- package/src/ai/turn-abort.ts +33 -0
- package/src/ai/types.ts +40 -4
- package/src/api/accounts-entities.ts +2 -1
- package/src/api/admin-ai-projects.ts +2 -0
- package/src/api/admin-ai-skills.ts +2 -0
- package/src/api/admin-ai-usage.ts +2 -0
- package/src/api/admin-core-settings.ts +190 -139
- package/src/api/admin-geoip.ts +80 -0
- package/src/api/admin-identity.ts +3 -0
- package/src/api/admin-lifecycle.ts +3 -0
- package/src/api/admin-outgoing-mail.ts +6 -2
- package/src/api/app-approval.ts +54 -6
- package/src/api/approvals-loader.ts +23 -1
- package/src/api/approvals.ts +3 -1
- package/src/api/auth.ts +25 -6
- package/src/api/capabilities.ts +44 -11
- package/src/api/capability-streams.ts +12 -0
- package/src/api/help.ts +4 -28
- package/src/api/index.ts +7 -1
- package/src/api/lasting-access-messages.ts +17 -0
- package/src/api/mcp.ts +3 -0
- package/src/api/me-panel-consent.ts +71 -0
- package/src/api/me.ts +80 -33
- package/src/api/search.ts +3 -1
- package/src/api/sync-ops.ts +2 -0
- package/src/api/widgets.ts +3 -0
- package/src/approvals/Approvals.tsx +180 -238
- package/src/approvals/messages.ts +12 -24
- package/src/browser/CloudResourceSearch.browser-harness.tsx +10 -2
- package/src/browser/CloudResourceSearch.tsx +10 -6
- package/src/browser/app-approval.ts +60 -6
- package/src/browser/commands.ts +22 -6
- package/src/browser/composer-catalog.ts +145 -0
- package/src/browser/composer-insert-messages.ts +31 -0
- package/src/browser/composer-insert.ts +160 -0
- package/src/browser/composer-open-messages.ts +17 -0
- package/src/browser/composer-open.ts +110 -0
- package/src/browser/discoverable-command.ts +6 -0
- package/src/browser/hints.ts +6 -0
- package/src/browser/live-connection.ts +26 -2
- package/src/browser/navigation-apps.ts +7 -0
- package/src/browser/panel-context-bridge.ts +30 -0
- package/src/browser/panel-context-receiver.ts +53 -0
- package/src/browser/panel-menu.tsx +56 -0
- package/src/browser/panel-messages.ts +35 -0
- package/src/browser/panel-shortcuts.ts +31 -0
- package/src/browser/panel-slot.ts +756 -0
- package/src/browser/panel.ts +65 -0
- package/src/browser/resource-picker.tsx +12 -1
- package/src/browser/search-commands.ts +6 -3
- package/src/capabilities/client.ts +8 -2
- package/src/capabilities/reviews.ts +205 -0
- package/src/capabilities/server.ts +10 -3
- package/src/capabilities/testing.ts +47 -0
- package/src/capabilities/types.ts +2 -2
- package/src/cli/account.ts +13 -3
- package/src/cli/admin/geoip.ts +115 -0
- package/src/cli/admin/index.ts +3 -0
- package/src/contracts/app-approval.ts +159 -12
- package/src/contracts/app.ts +14 -0
- package/src/contracts/approvals.ts +2 -2
- package/src/contracts/capabilities.ts +410 -18
- package/src/contracts/geoip.ts +42 -0
- package/src/contracts/index.ts +3 -0
- package/src/contracts/panel-context-plain.ts +99 -0
- package/src/contracts/panel-context.ts +93 -0
- package/src/contracts/registry.ts +3 -1
- package/src/contracts/seen-hints.ts +35 -0
- package/src/contracts/shared.ts +2 -0
- package/src/server/client-ip.ts +5 -0
- package/src/server/help-payload.ts +38 -0
- package/src/server/middleware/auth.ts +11 -1
- package/src/server/middleware/middleware.ts +9 -0
- package/src/server/middleware/no-transform.ts +19 -0
- package/src/server/middleware/rate-limit.ts +4 -6
- package/src/server/request-context/address.ts +45 -0
- package/src/server/request-context/geoip.ts +380 -0
- package/src/server/request-context/index.ts +33 -0
- package/src/server/request-context/user-agent.ts +95 -0
- package/src/server/services/access.ts +5 -1
- package/src/services/accounts/posix.ts +2 -1
- package/src/services/app-approval.ts +533 -90
- package/src/services/approvals/device.ts +9 -5
- package/src/services/approvals/index.ts +6 -5
- package/src/services/approvals/list.ts +26 -5
- package/src/services/auth-flows/notification-sender.ts +3 -0
- package/src/services/geoip/index.ts +164 -0
- package/src/services/geoip/store.ts +30 -0
- package/src/services/geoip/upload.ts +150 -0
- package/src/services/identity/routes.ts +5 -1
- package/src/services/index.ts +32 -3
- package/src/services/known-browsers.ts +312 -0
- package/src/services/login-address-store.ts +51 -0
- package/src/services/login-context.ts +118 -0
- package/src/services/mandates/index.ts +3 -0
- package/src/services/mandates/policy.ts +15 -3
- package/src/services/notifications/browser.ts +16 -5
- package/src/services/notifications/email-frame.ts +1 -1
- package/src/services/oauth-tokens.ts +16 -2
- package/src/services/panel-context-consent.ts +58 -0
- package/src/services/pdf/image-protocol.ts +135 -0
- package/src/services/pdf/image-variants.ts +124 -0
- package/src/services/pdf/image-worker.ts +31 -0
- package/src/services/pdf/image.ts +109 -0
- package/src/services/pdf/index.ts +9 -0
- package/src/services/service-account-credentials.ts +21 -0
- package/src/services/session/index.ts +97 -16
- package/src/services/session/recent.ts +13 -0
- package/src/services/settings/api.ts +11 -6
- package/src/services/settings/app.ts +5 -4
- package/src/services/settings/core-settings.ts +4 -3
- package/src/services/settings/index.ts +19 -17
- package/src/services/settings/namespace.ts +2 -1
- package/src/services/settings/store.ts +83 -11
- package/src/services/webauthn.ts +12 -0
- package/src/shared/ai-platform-prompt.ts +1 -1
- package/src/shared/app-presentation.ts +1 -0
- package/src/shared/email-html.ts +2 -0
- package/src/shared/help.ts +3 -0
- package/src/shared/redirect.ts +12 -0
- package/src/shared-text/cursor.ts +22 -0
- package/src/shared-text/documents.ts +142 -0
- package/src/shared-text/events.ts +43 -0
- package/src/shared-text/index.ts +12 -0
- package/src/shared-text/log.ts +48 -0
- package/src/shared-text/text-diff.ts +23 -0
- package/src/shared-text/types.ts +41 -0
- package/src/ssr/AdminLayout.tsx +2 -0
- package/src/ssr/AppLaunchpadPanel.tsx +2 -2
- package/src/ssr/CloudShell.island.tsx +95 -10
- package/src/ssr/Layout.tsx +66 -10
- package/src/ssr/LayoutHeader.tsx +15 -9
- package/src/ssr/LayoutHelp.browser-harness.tsx +2 -0
- package/src/ssr/LayoutHelp.tsx +435 -274
- package/src/ssr/LayoutHelpPanel.browser-harness.tsx +136 -0
- package/src/ssr/LayoutHelpTrigger.tsx +27 -2
- package/src/ssr/LayoutRail.tsx +2 -2
- package/src/ssr/LayoutTabBar.tsx +29 -0
- package/src/ssr/MobileNavigation.tsx +2 -2
- package/src/ssr/PanelLayout.tsx +35 -0
- package/src/ssr/PanelRuntime.island.tsx +94 -0
- package/src/ssr/PanelSlot.tsx +158 -0
- package/src/ssr/PanelTrigger.tsx +49 -0
- package/src/ssr/ShellRuntime.island.tsx +69 -5
- package/src/ssr/app-appearance.ts +3 -2
- package/src/ssr/app-color.ts +105 -0
- package/src/ssr/app-launchpad.tsx +18 -1
- package/src/ssr/app-navigation.ts +28 -0
- package/src/ssr/compact-shell.baseline.json +5270 -0
- package/src/ssr/compact-shell.browser-harness.ts +439 -0
- package/src/ssr/dialog-app-colors.browser-harness.tsx +43 -0
- package/src/ssr/help-messages.ts +4 -0
- package/src/ssr/help.ts +20 -0
- package/src/ssr/hints.ts +25 -0
- package/src/ssr/index.ts +5 -0
- package/src/ssr/islands/index.ts +4 -3
- package/src/ssr/layout-context.ts +2 -0
- package/src/ssr/layout-help-article.server.ts +50 -0
- package/src/ssr/layout-help-start.ts +33 -7
- package/src/ssr/panel-consent.ts +29 -0
- package/src/ssr/panel-context.ts +10 -0
- package/src/ssr/panel-slot.browser-harness.tsx +159 -0
- package/src/ssr/platform-messages.ts +48 -0
- package/src/ssr/rail-navigation.ts +44 -0
- package/src/ssr/shell-data.tsx +5 -0
- package/src/ssr/shell-shortcuts.ts +13 -2
- package/src/styles/effects.css +201 -11
- package/src/styles/file-chooser.css +2 -1
- package/src/styles/global.css +314 -63
- package/src/styles/panel.css +416 -0
- package/src/styles/resource-search.css +6 -2
- package/src/styles/tokens.css +36 -13
- package/src/styles/utilities-buttons.css +3 -2
- package/src/styles/utilities-data.css +2 -1
- package/src/styles/utilities-feedback.css +2 -2
- package/src/styles/utilities-layout.css +3 -13
- package/src/styles/utilities-markdown-editor.css +6 -6
- package/src/styles/utilities-navigation.css +22 -43
package/src/ssr/Layout.tsx
CHANGED
|
@@ -2,26 +2,31 @@ import type { DateContext } from "@k2b/stdlib";
|
|
|
2
2
|
import { AppWorkspace, appWorkspaceLayoutStyle, keyboardPlatform, LocaleProvider, NoticeCard, PageTrailProvider } from "@k2b/ui";
|
|
3
3
|
import type { JSX } from "solid-js/jsx-runtime";
|
|
4
4
|
import { readAppWorkspaceLayoutCookie, resolveAppWorkspaceLayoutForSidebar } from "../_internal/app-workspace-state";
|
|
5
|
+
import { readPanelCookie } from "../_internal/panel-cookie";
|
|
5
6
|
import { readShellFocusCookie } from "../_internal/shell-focus";
|
|
6
7
|
import { resolveNavMatch } from "../contracts/app"; // ==========================
|
|
8
|
+
import { type CloudResourceRef, CloudResourceRefSchema } from "../contracts/capabilities";
|
|
9
|
+
import { PANEL_HELP_ID_MAX_LENGTH, PanelPageContextSchema } from "../contracts/panel-context";
|
|
7
10
|
import { isPwaShellAvailable } from "../contracts/pwa";
|
|
8
11
|
import { defaultRailPreferences } from "../contracts/rail-preferences";
|
|
9
12
|
import { hasRole, type User } from "../contracts/shared";
|
|
10
13
|
import { getLocale } from "../server/locale";
|
|
11
14
|
import { getDateConfig } from "../server/time";
|
|
12
|
-
import { dates } from "../shared";
|
|
15
|
+
import { dates, resolveHomePath } from "../shared";
|
|
13
16
|
import { readThemePreferenceFromCookieHeader } from "../shared/theme";
|
|
14
17
|
import AnnouncementBanners from "./AnnouncementBanners";
|
|
15
18
|
import { appAppearanceStyle, resolveCurrentApp } from "./app-appearance";
|
|
16
|
-
import { resolveRuntimeRoute, visibleNavigationApps } from "./app-navigation";
|
|
19
|
+
import { resolveRuntimeRoute, visibleNavigationApps, visiblePanelProviders } from "./app-navigation";
|
|
17
20
|
import { getLayoutHelp, layoutHelpFailed } from "./help";
|
|
18
21
|
import LayoutFooter from "./LayoutFooter";
|
|
19
22
|
import LayoutHeader from "./LayoutHeader";
|
|
20
23
|
import LayoutRail, { type LayoutAppLink } from "./LayoutRail";
|
|
24
|
+
import LayoutTabBar from "./LayoutTabBar";
|
|
21
25
|
import type { LayoutContext } from "./layout-context";
|
|
22
26
|
import { HELP_VIEW_LIMIT } from "./layout-help-start";
|
|
23
27
|
import type { LayoutBreadcrumb } from "./layout-runtime";
|
|
24
28
|
import PageTrailRow from "./PageTrailRow";
|
|
29
|
+
import PanelSlot from "./PanelSlot";
|
|
25
30
|
import { derivePageTrail } from "./page-trail";
|
|
26
31
|
import { platformMessages } from "./platform-messages";
|
|
27
32
|
import { sortRailApps } from "./rail-navigation";
|
|
@@ -39,8 +44,12 @@ type LayoutProps = {
|
|
|
39
44
|
title?: string | Breadcrumb[];
|
|
40
45
|
/** Up to three ids of the current app's Help articles that fit this page; Help lists them first under "For this view". Unknown ids and articles the reader may not see are ignored. */
|
|
41
46
|
help?: readonly string[];
|
|
47
|
+
/** Share only the current place with the visible panel; false disables context for this document. */
|
|
48
|
+
context?: { scope?: CloudResourceRef } | false;
|
|
42
49
|
fullPage?: boolean /** Keep the shell viewport-bound and suppress its footer. */;
|
|
43
50
|
fullWidth?: boolean /** Delegate scrolling and clipping to the page's work surface. */;
|
|
51
|
+
/** Hide the panel slot on this page (sign-in, print, presentation, public pages). */
|
|
52
|
+
panel?: false;
|
|
44
53
|
focusMode?: boolean /** Render only the app canvas and content for dedicated editors or pop-out windows. */;
|
|
45
54
|
flushCanvas?: boolean /** Remove app-canvas spacing for edge-to-edge focus surfaces such as pop-out windows. */;
|
|
46
55
|
/** Final localized app-specific export or printing guidance, shown when no data-print-region exists. */
|
|
@@ -155,6 +164,11 @@ export default function Layout(props: LayoutProps) {
|
|
|
155
164
|
const lang = getLocale(c);
|
|
156
165
|
const t = platformMessages.resolve([lang]).t;
|
|
157
166
|
const user = c.get("user");
|
|
167
|
+
const providers = user && props.panel !== false ? visiblePanelProviders(runtime.apps, user, lang) : [];
|
|
168
|
+
const panelState = readPanelCookie(
|
|
169
|
+
providers.length ? cookie : undefined,
|
|
170
|
+
providers.map((provider) => provider.id),
|
|
171
|
+
);
|
|
158
172
|
const pathname = new URL(c.req.raw.url).pathname;
|
|
159
173
|
const currentRoute = resolveRuntimeRoute(runtime.apps, pathname);
|
|
160
174
|
const currentApp = resolveCurrentApp(runtime.apps, pathname);
|
|
@@ -185,6 +199,7 @@ export default function Layout(props: LayoutProps) {
|
|
|
185
199
|
const page = c.get("page") as Record<string, unknown>;
|
|
186
200
|
const pageTitle = typeof title === "string" ? title : (title?.at(-1)?.title ?? appName);
|
|
187
201
|
if (!page.title) page.title = pageTitle;
|
|
202
|
+
page.appAccent = currentApp?.appearance?.accent;
|
|
188
203
|
const breadcrumbs: Breadcrumb[] = !title ? [{ title: appName }] : typeof title === "string" ? [{ title }] : title;
|
|
189
204
|
// The way up is derived from the title array by one rule (see `derivePageTrail`). Anonymous pages keep their
|
|
190
205
|
// header breadcrumbs, and focus surfaces such as pop-out editors have no way up; both show the title alone. The
|
|
@@ -207,19 +222,48 @@ export default function Layout(props: LayoutProps) {
|
|
|
207
222
|
// keeps short and long pages at the same width where scrollbars take space.
|
|
208
223
|
const mainLayoutClass = fullPage || fullWidth ? "flex flex-col" : "md:overflow-auto md:[scrollbar-gutter:stable]";
|
|
209
224
|
const canvasStyle =
|
|
210
|
-
[
|
|
225
|
+
[
|
|
226
|
+
appAppearanceStyle(currentApp?.appearance),
|
|
227
|
+
appWorkspaceLayoutStyle(workspaceLayout),
|
|
228
|
+
panelState.widthRem !== undefined ? `--cloud-panel-width-set:${panelState.widthRem}rem` : "",
|
|
229
|
+
focusMode && flushCanvas ? "padding:0" : "",
|
|
230
|
+
]
|
|
211
231
|
.filter(Boolean)
|
|
212
232
|
.join(";") || undefined;
|
|
213
233
|
const appLabel = currentApp?.name ?? (pathname.startsWith("/admin") ? t.admin : undefined);
|
|
214
234
|
const helpIds = new Set(registeredHelp?.documents.map((topic) => topic.id));
|
|
215
|
-
const viewHelp = [...new Set(props.help)]
|
|
235
|
+
const viewHelp = [...new Set(props.help)]
|
|
236
|
+
.filter((id) => helpIds.has(id) && id.length <= PANEL_HELP_ID_MAX_LENGTH)
|
|
237
|
+
.slice(0, HELP_VIEW_LIMIT);
|
|
238
|
+
const scope = props.context && CloudResourceRefSchema.safeParse(props.context.scope);
|
|
239
|
+
// Fail closed: a page whose place does not validate shares nothing rather than failing to render.
|
|
240
|
+
const pageContext =
|
|
241
|
+
(providers.length &&
|
|
242
|
+
props.context !== false &&
|
|
243
|
+
PanelPageContextSchema.safeParse({
|
|
244
|
+
v: 1,
|
|
245
|
+
seq: 0,
|
|
246
|
+
pageId: crypto.randomUUID(),
|
|
247
|
+
app: currentApp?.id,
|
|
248
|
+
...(scope && scope.success ? { scope: scope.data } : {}),
|
|
249
|
+
...(viewHelp.length ? { help: viewHelp } : {}),
|
|
250
|
+
}).data) ||
|
|
251
|
+
null;
|
|
252
|
+
const panel: ShellData["panel"] = providers.length
|
|
253
|
+
? { providers, provider: panelState.provider ?? providers[0]?.id, context: pageContext, consent: c.get("panelConsent") }
|
|
254
|
+
: undefined;
|
|
216
255
|
const shellData: ShellData = {
|
|
256
|
+
...(panel ? { panel } : {}),
|
|
217
257
|
platform: keyboardPlatform(c.req.raw.headers.get("User-Agent") ?? ""),
|
|
218
258
|
...(viewHelp.length ? { help: viewHelp } : {}),
|
|
219
259
|
...(layoutHelpFailed(c) ? { helpFailed: true as const } : {}),
|
|
220
260
|
apps: allApps,
|
|
221
261
|
...(user
|
|
222
|
-
? {
|
|
262
|
+
? {
|
|
263
|
+
rail: c.get("railPreferences") ?? defaultRailPreferences(),
|
|
264
|
+
home: resolveHomePath(settings?.app?.home_path),
|
|
265
|
+
profile: { name: profileName, avatarSrc: profileAvatarSrc, appHref },
|
|
266
|
+
}
|
|
223
267
|
: {}),
|
|
224
268
|
legalLinks,
|
|
225
269
|
theme,
|
|
@@ -231,20 +275,27 @@ export default function Layout(props: LayoutProps) {
|
|
|
231
275
|
return (
|
|
232
276
|
<LocaleProvider locale={lang}>
|
|
233
277
|
<div
|
|
234
|
-
class="cloud-app-canvas flex h-dvh w-full overflow-hidden"
|
|
278
|
+
class="cloud-app-canvas relative flex h-dvh w-full overflow-hidden"
|
|
235
279
|
style={canvasStyle}
|
|
280
|
+
data-panel-transient=""
|
|
236
281
|
data-app-id={currentApp?.id}
|
|
237
282
|
data-app-base={currentRoute?.prefix}
|
|
238
283
|
data-page-trail-title-only=""
|
|
239
284
|
data-layout-full-page="true"
|
|
240
285
|
data-workspace-sidebar-collapsed={workspaceLayout?.sidebarCollapsed ? "true" : undefined}
|
|
241
286
|
>
|
|
242
|
-
<ShellRuntime pageTrail help={runtimeHelp} />
|
|
287
|
+
<ShellRuntime pageTrail help={runtimeHelp} panel={panel ? true : undefined} />
|
|
243
288
|
<PageTrailProvider trail={pageTrail}>
|
|
244
|
-
<main class="min-h-0 min-w-0 flex-1">
|
|
289
|
+
<main class="min-h-0 min-w-0 flex-1" data-cloud-app-area="">
|
|
245
290
|
<AppWorkspace.LayoutStateProvider state={workspaceLayout}>{props.children}</AppWorkspace.LayoutStateProvider>
|
|
246
291
|
</main>
|
|
247
292
|
</PageTrailProvider>
|
|
293
|
+
{/* Focus pages carry shell data only for their panel providers. */}
|
|
294
|
+
{panel && (
|
|
295
|
+
<ShellDataProvider data={{ panel, platform: shellData.platform, theme, apps: [], legalLinks: [], searchLinks: {} }}>
|
|
296
|
+
<PanelSlot panel={panel} state={{ ...panelState, open: false }} platform={shellData.platform} />
|
|
297
|
+
</ShellDataProvider>
|
|
298
|
+
)}
|
|
248
299
|
<div data-print-fallback="">
|
|
249
300
|
<p>{t.printFallbackTitle}</p>
|
|
250
301
|
<p>{props.printHint ?? t.printFallbackHint}</p>
|
|
@@ -261,6 +312,7 @@ export default function Layout(props: LayoutProps) {
|
|
|
261
312
|
<div
|
|
262
313
|
class={`cloud-app-canvas relative flex w-full ${fullPage ? "h-dvh overflow-hidden" : "min-h-dvh md:h-dvh md:overflow-hidden"}`}
|
|
263
314
|
style={canvasStyle}
|
|
315
|
+
data-panel={panelState.open ? "open" : undefined}
|
|
264
316
|
data-app-id={currentApp?.id}
|
|
265
317
|
data-app-base={currentRoute?.prefix}
|
|
266
318
|
data-page-trail-title-only={titleOnly ? "" : undefined}
|
|
@@ -270,6 +322,7 @@ export default function Layout(props: LayoutProps) {
|
|
|
270
322
|
data-workspace-sidebar-collapsed={workspaceLayout?.sidebarCollapsed ? "true" : undefined}
|
|
271
323
|
>
|
|
272
324
|
<ShellRuntime
|
|
325
|
+
panel={panel ? true : undefined}
|
|
273
326
|
workspace={{ appId: currentApp?.id }}
|
|
274
327
|
pageTrail
|
|
275
328
|
focus={showRail}
|
|
@@ -284,11 +337,12 @@ export default function Layout(props: LayoutProps) {
|
|
|
284
337
|
banners={user && announcements?.banners.length ? true : undefined}
|
|
285
338
|
/>
|
|
286
339
|
<ShellDataProvider data={shellData}>
|
|
287
|
-
{showRail && <LayoutRail currentPath={requestPath(c)} />}
|
|
340
|
+
{showRail && <LayoutRail currentPath={requestPath(c)} panelOpen={panel ? panelState.open : undefined} />}
|
|
288
341
|
{showRail && <ShellFocusToggle variant="float" />}
|
|
289
342
|
{showRail && <div class="cloud-shell-reveal" data-cloud-shell-reveal="" aria-hidden="true" />}
|
|
290
|
-
<div class="layout-shell-content flex min-h-0 min-w-0 flex-1 flex-col">
|
|
343
|
+
<div class="layout-shell-content flex min-h-0 min-w-0 flex-1 flex-col" data-cloud-app-area="">
|
|
291
344
|
<LayoutHeader
|
|
345
|
+
panelOpen={panel ? panelState.open : undefined}
|
|
292
346
|
authenticated={showRail}
|
|
293
347
|
title={appLabel ?? breadcrumbs.at(-1)?.title}
|
|
294
348
|
launchpad={!!(user || appLabel)}
|
|
@@ -305,6 +359,8 @@ export default function Layout(props: LayoutProps) {
|
|
|
305
359
|
</PageTrailProvider>
|
|
306
360
|
{!fullPage && !showRail && <LayoutFooter appName={settings?.app?.copyright || appName} legalLinks={legalLinks} />}
|
|
307
361
|
</div>
|
|
362
|
+
{panel && <PanelSlot panel={panel} state={panelState} platform={shellData.platform} />}
|
|
363
|
+
{showRail && <LayoutTabBar currentPath={requestPath(c)} />}
|
|
308
364
|
</ShellDataProvider>
|
|
309
365
|
<div data-print-fallback="">
|
|
310
366
|
<p>{t.printFallbackTitle}</p>
|
package/src/ssr/LayoutHeader.tsx
CHANGED
|
@@ -5,6 +5,7 @@ import { platformMessages } from "./platform-messages";
|
|
|
5
5
|
|
|
6
6
|
type LayoutHeaderProps = {
|
|
7
7
|
authenticated: boolean;
|
|
8
|
+
panelOpen?: boolean;
|
|
8
9
|
title?: string;
|
|
9
10
|
launchpad: boolean;
|
|
10
11
|
breadcrumbs?: LayoutBreadcrumb[];
|
|
@@ -14,10 +15,12 @@ type LayoutHeaderProps = {
|
|
|
14
15
|
* Phones (below `md`) always get this header. From `md` it remains only on
|
|
15
16
|
* anonymous pages; signed-in people reach Home, search, help, the app grid,
|
|
16
17
|
* and their profile through the rail, so the app area starts at the top edge.
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
18
|
+
* On a signed-in phone it is the title row on the app gradient: Home moves to
|
|
19
|
+
* the bottom bar's Start, so the row holds the title, search, help, and the
|
|
20
|
+
* app menu. Anonymous pages have no rail: up to `lg` their header keeps Home,
|
|
21
|
+
* the app name, help, search, and the app grid, and from `lg` it shows the
|
|
22
|
+
* breadcrumbs. Home and Sign in stay server markup, so focus on them survives
|
|
23
|
+
* the shell's mount; the shell renders the title and the controls between them.
|
|
21
24
|
*/
|
|
22
25
|
export default function LayoutHeader(props: LayoutHeaderProps) {
|
|
23
26
|
const locale = useLocale();
|
|
@@ -29,13 +32,16 @@ export default function LayoutHeader(props: LayoutHeaderProps) {
|
|
|
29
32
|
>
|
|
30
33
|
{/* A long title must not squeeze the button; `shrink-0` sits on a wrapper because the button's own
|
|
31
34
|
styles would win over a utility on the link. */}
|
|
32
|
-
|
|
33
|
-
<
|
|
34
|
-
<
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
{!props.authenticated && (
|
|
36
|
+
<div class="flex shrink-0">
|
|
37
|
+
<IconButtonLink href="/" label={t().home}>
|
|
38
|
+
<img src="/branding/logo" alt="" class="h-6 w-6" />
|
|
39
|
+
</IconButtonLink>
|
|
40
|
+
</div>
|
|
41
|
+
)}
|
|
37
42
|
<CloudShell
|
|
38
43
|
slot="header"
|
|
44
|
+
panelOpen={props.panelOpen}
|
|
39
45
|
authenticated={props.authenticated}
|
|
40
46
|
title={props.title}
|
|
41
47
|
launchpad={props.launchpad}
|
|
@@ -75,6 +75,8 @@ window.fetch = Object.assign(
|
|
|
75
75
|
const ids = params.has("start")
|
|
76
76
|
? documents.filter((document) => document.title.toLocaleLowerCase().includes(query)).map((document) => document.id)
|
|
77
77
|
: ["topic-0", "topic-1"];
|
|
78
|
+
// Tests wait for an answered search by this count, not for a spinner that can come and go between two polls (#1403).
|
|
79
|
+
document.documentElement.dataset.helpSearches = String(Number(document.documentElement.dataset.helpSearches ?? 0) + 1);
|
|
78
80
|
return Response.json({ locale: "en", ids });
|
|
79
81
|
}
|
|
80
82
|
const id = path.split("/").at(-1) ?? "topic-0";
|