@k2b/cloud 0.31.0 → 0.33.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/package.json +8 -6
- package/src/_internal/define-app.ts +20 -9
- package/src/_internal/page-responses.ts +5 -1
- package/src/ai/app-skills.ts +1 -7
- package/src/ai/audio-tool.ts +2 -1
- package/src/ai/browser.ts +109 -0
- package/src/ai/capabilities.ts +6 -2
- package/src/ai/chart-block.ts +431 -81
- package/src/ai/chat/action-sentences.ts +13 -7
- package/src/ai/chat/blocks.tsx +11 -7
- package/src/ai/chat/builtin-tools.tsx +9 -7
- package/src/ai/chat/chart-block.tsx +218 -44
- package/src/ai/chat/explorer-block.tsx +276 -0
- package/src/ai/chat/file-tools.tsx +40 -1
- package/src/ai/chat/message-actions.tsx +6 -0
- package/src/ai/chat/message-utils.ts +7 -0
- package/src/ai/chat/messages.ts +16 -0
- package/src/ai/chat/presentation.tsx +13 -3
- package/src/ai/chat/reference-text.tsx +34 -0
- package/src/ai/chat/tool-groups.ts +1 -0
- package/src/ai/chat/tool-names.ts +14 -0
- package/src/ai/chat/turn-view.tsx +17 -7
- package/src/ai/chat/view-block.browser-harness.tsx +35 -0
- package/src/ai/chat/view-block.tsx +417 -0
- package/src/ai/chat/visual-tools.tsx +32 -53
- package/src/ai/client-tool-results.ts +9 -0
- package/src/ai/code-source-contracts.ts +17 -2
- package/src/ai/code-source-tools.ts +1 -0
- package/src/ai/default-tool-contracts.ts +334 -91
- package/src/ai/default-tools.ts +89 -13
- package/src/ai/executor.ts +173 -31
- package/src/ai/file-error.ts +2 -0
- package/src/ai/file-tools.ts +27 -7
- package/src/ai/files-store.ts +60 -0
- package/src/ai/html-pdf-tool.ts +3 -2
- package/src/ai/http.ts +37 -12
- package/src/ai/index.ts +90 -0
- package/src/ai/local-tool-contracts.ts +244 -0
- package/src/ai/malformed-tool-call-repair.ts +144 -0
- package/src/ai/markdown-pdf-tool.ts +2 -1
- package/src/ai/memories.ts +48 -1
- package/src/ai/memory-learning.ts +17 -6
- package/src/ai/memory-tool.ts +1 -0
- package/src/ai/migrate.ts +15 -0
- package/src/ai/openai-api-messages.ts +53 -0
- package/src/ai/openai-api-slots.ts +40 -0
- package/src/ai/openai-api.ts +383 -0
- package/src/ai/protocol.ts +6 -2
- package/src/ai/provider.ts +17 -4
- package/src/ai/request-context.ts +33 -0
- package/src/ai/routes.ts +96 -57
- package/src/ai/runtime.ts +48 -12
- package/src/ai/settings.ts +5 -0
- package/src/ai/skill-catalog.ts +20 -5
- package/src/ai/skill-format.ts +17 -7
- package/src/ai/skill-tool.ts +15 -5
- package/src/ai/skills-routes.ts +20 -6
- package/src/ai/skills.ts +26 -7
- package/src/ai/store.ts +25 -0
- package/src/ai/system-prompt.ts +69 -10
- package/src/ai/timeline.ts +3 -1
- package/src/ai/tools.ts +3 -0
- package/src/ai/types.ts +9 -0
- package/src/ai/view-block.ts +941 -0
- package/src/ai/vision-tool.ts +2 -1
- package/src/api/admin-identity.ts +6 -1
- package/src/api/app-approval-actions.ts +36 -0
- package/src/api/app-approval.ts +10 -2
- package/src/api/approvals-loader.ts +15 -0
- package/src/api/approvals.ts +120 -0
- package/src/api/index.ts +3 -0
- package/src/api/me.ts +12 -3
- package/src/approvals/Approvals.browser-harness.tsx +16 -0
- package/src/approvals/Approvals.tsx +621 -0
- package/src/approvals/ApprovalsNavStatus.tsx +20 -0
- package/src/approvals/messages.ts +95 -0
- package/src/approvals/ui.ts +8 -0
- package/src/browser/app-approval.ts +32 -0
- package/src/browser/choose-files.tsx +26 -13
- package/src/browser/commands.ts +13 -4
- package/src/browser/file-provider-error.ts +11 -0
- package/src/browser/file-providers.ts +3 -12
- package/src/browser/files.tsx +1 -2
- package/src/browser/live-connection.ts +2 -3
- package/src/browser/navigation-search.ts +4 -1
- package/src/browser/provider-list.ts +2 -1
- package/src/browser/save-files.tsx +13 -2
- package/src/cli/account.ts +21 -2
- package/src/cli/commands.ts +4 -2
- package/src/contracts/app-approval.ts +120 -0
- package/src/contracts/approval-paths.ts +4 -0
- package/src/contracts/approvals.ts +81 -0
- package/src/contracts/command-path.ts +17 -0
- package/src/contracts/commands.ts +5 -15
- package/src/contracts/shared.ts +5 -0
- package/src/events/live-protocol.ts +2 -1
- package/src/events/live-server-message.ts +40 -0
- package/src/events/testing.ts +88 -0
- package/src/server/index.ts +2 -0
- package/src/server/middleware/auth.ts +11 -1
- package/src/server/request-timeout.ts +22 -0
- package/src/server/services/access.ts +4 -3
- package/src/services/app-approval.ts +103 -15
- package/src/services/approvals/cursor.ts +15 -0
- package/src/services/approvals/device.ts +112 -0
- package/src/services/approvals/index.ts +27 -11
- package/src/services/approvals/list.ts +120 -0
- package/src/services/approvals/migrate.ts +9 -1
- package/src/services/identity/models-only-auth.ts +25 -0
- package/src/services/notifications/email-frame.ts +16 -3
- package/src/services/outbox.ts +13 -6
- package/src/services/service-account-credentials.ts +22 -10
- package/src/services/settings/core-settings.ts +27 -0
- package/src/shared/ai-platform-prompt.ts +29 -3
- package/src/shared/email-html.ts +4 -0
- package/src/shared/index.ts +6 -1
- package/src/shared/markdown/extensions/code.ts +14 -0
- package/src/shared/markdown/index.ts +4 -4
- package/src/shared/theme.ts +41 -20
- package/src/ssr/AnnouncementBanners.tsx +30 -0
- package/src/ssr/AppBadge.tsx +4 -4
- package/src/ssr/AppLaunchpadPanel.tsx +6 -6
- package/src/ssr/CloudShell.island.tsx +91 -0
- package/src/ssr/GlobalSearchTrigger.tsx +51 -0
- package/src/ssr/Layout.tsx +56 -85
- package/src/ssr/LayoutHeader.tsx +31 -77
- package/src/ssr/LayoutHelp.tsx +2 -57
- package/src/ssr/LayoutHelpTrigger.tsx +51 -0
- package/src/ssr/{LayoutPreferences.island.tsx → LayoutPreferences.tsx} +2 -2
- package/src/ssr/LayoutRail.tsx +15 -69
- package/src/ssr/MinimalLayout.tsx +2 -3
- package/src/ssr/MinimalLayoutPreferences.island.tsx +12 -15
- package/src/ssr/MobileNavigation.tsx +13 -8
- package/src/ssr/MobileProfileActions.tsx +10 -7
- package/src/ssr/PageTrailRow.tsx +14 -0
- package/src/ssr/{ProfilePreferences.island.tsx → ProfilePreferences.tsx} +12 -7
- package/src/ssr/PwaLayout.tsx +0 -2
- package/src/ssr/PwaRuntime.island.tsx +1 -1
- package/src/ssr/{RailApps.island.tsx → RailApps.tsx} +2 -2
- package/src/ssr/ShellRuntime.island.tsx +170 -0
- package/src/ssr/TimezoneCookie.island.tsx +3 -19
- package/src/ssr/WorkspaceNavigationProvider.tsx +20 -1
- package/src/ssr/announcements-dialog.tsx +66 -0
- package/src/ssr/app-badges.ts +50 -6
- package/src/ssr/{AppLaunchpad.island.tsx → app-launchpad.tsx} +42 -62
- package/src/ssr/busy-action.ts +19 -0
- package/src/ssr/islands/index.ts +9 -6
- package/src/ssr/launchpad-surface.tsx +15 -0
- package/src/ssr/layout-help-registry.tsx +60 -0
- package/src/ssr/mobile-navigation.browser-harness.tsx +20 -0
- package/src/ssr/page-trail.browser-harness.tsx +52 -3
- package/src/ssr/preference-controller.ts +30 -21
- package/src/ssr/profile-actions.ts +26 -15
- package/src/ssr/profile-preferences-messages.ts +8 -4
- package/src/ssr/rail-context.ts +8 -12
- package/src/ssr/rail-navigation.ts +5 -3
- package/src/ssr/runtime.ts +6 -1
- package/src/ssr/shell-data.tsx +48 -0
- package/src/ssr/timezone-cookie.ts +22 -0
- package/src/ssr/workspace-navigation.ts +25 -2
- package/src/styles/approvals.css +390 -0
- package/src/styles/global.css +22 -7
- package/src/styles/utilities-navigation.css +13 -0
- package/src/workflows/language/compiler.ts +1 -1
- package/src/ssr/AppWorkspaceController.island.tsx +0 -21
- package/src/ssr/BrowserPushRegistration.island.tsx +0 -12
- package/src/ssr/GlobalAnnouncements.island.tsx +0 -117
- package/src/ssr/GlobalSearchTrigger.island.tsx +0 -75
- package/src/ssr/LayoutHelpTrigger.island.tsx +0 -61
- package/src/ssr/PageTrailRow.island.tsx +0 -20
- package/src/ssr/PageTrailRuntime.island.tsx +0 -26
- package/src/ssr/RegisteredHelpDocuments.island.tsx +0 -3
- /package/src/ssr/{LayoutBreadcrumbs.island.tsx → LayoutBreadcrumbs.tsx} +0 -0
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
import { Button, dialogCore, IconButton, MarkdownView, NoticeCard, PanelDialog, panelDialogOptions, useLocale } from "@k2b/ui";
|
|
2
|
-
import { createSignal, For, onMount, Show } from "solid-js";
|
|
3
|
-
import {
|
|
4
|
-
ANNOUNCEMENTS_COOKIE,
|
|
5
|
-
ANNOUNCEMENTS_COOKIE_MAX_AGE_SECONDS,
|
|
6
|
-
type AnnouncementCookieState,
|
|
7
|
-
mergeAnnouncementCookieState,
|
|
8
|
-
serializeAnnouncementCookieState,
|
|
9
|
-
} from "../contracts/announcement-cookie";
|
|
10
|
-
import type { AnnouncementDisplayEntry } from "../contracts/announcements";
|
|
11
|
-
import { platformMessages } from "./platform-messages";
|
|
12
|
-
|
|
13
|
-
type Props = {
|
|
14
|
-
banners: AnnouncementDisplayEntry[];
|
|
15
|
-
announcements: AnnouncementDisplayEntry[];
|
|
16
|
-
latestAnnouncementVersion: number;
|
|
17
|
-
cookieState: AnnouncementCookieState;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
const writeCookieState = (state: AnnouncementCookieState) => {
|
|
21
|
-
document.cookie = `${ANNOUNCEMENTS_COOKIE}=${serializeAnnouncementCookieState(state)}; Path=/; Max-Age=${ANNOUNCEMENTS_COOKIE_MAX_AGE_SECONDS}; SameSite=Lax`;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
export default function GlobalAnnouncements(props: Props) {
|
|
25
|
-
const locale = useLocale();
|
|
26
|
-
const t = () => platformMessages.resolve([locale()]).t;
|
|
27
|
-
const [cookieState, setCookieState] = createSignal(props.cookieState);
|
|
28
|
-
const [banners, setBanners] = createSignal(props.banners);
|
|
29
|
-
|
|
30
|
-
const dismissBanner = (version: number) => {
|
|
31
|
-
const next = mergeAnnouncementCookieState(cookieState(), { dismissedBannerVersions: [version] });
|
|
32
|
-
setCookieState(next);
|
|
33
|
-
writeCookieState(next);
|
|
34
|
-
setBanners((items) => items.filter((item) => item.version !== version));
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const closeAnnouncements = () => {
|
|
38
|
-
const next = mergeAnnouncementCookieState(cookieState(), {
|
|
39
|
-
seenAnnouncementVersion: props.latestAnnouncementVersion,
|
|
40
|
-
});
|
|
41
|
-
setCookieState(next);
|
|
42
|
-
writeCookieState(next);
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
onMount(() => {
|
|
46
|
-
if (props.announcements.length === 0) return;
|
|
47
|
-
|
|
48
|
-
void dialogCore
|
|
49
|
-
.open<void>(
|
|
50
|
-
(close) => (
|
|
51
|
-
<PanelDialog>
|
|
52
|
-
<PanelDialog.Header
|
|
53
|
-
title={t().announcements}
|
|
54
|
-
subtitle={t().latestPlatformUpdates}
|
|
55
|
-
icon="ti ti-speakerphone text-blue-500"
|
|
56
|
-
close={() => close()}
|
|
57
|
-
/>
|
|
58
|
-
<PanelDialog.Body>
|
|
59
|
-
<For each={props.announcements}>
|
|
60
|
-
{(entry) => (
|
|
61
|
-
<article class="panel-dialog-section rounded-[var(--ui-radius-surface)] p-4">
|
|
62
|
-
<div class="mb-3 flex items-start justify-between gap-3">
|
|
63
|
-
<div class="min-w-0">
|
|
64
|
-
<h2 class="text-base font-semibold text-primary">{entry.title}</h2>
|
|
65
|
-
<p class="mt-0.5 text-xs text-dimmed">
|
|
66
|
-
{new Date(entry.publishedAt).toLocaleDateString(locale(), {
|
|
67
|
-
year: "numeric",
|
|
68
|
-
month: "short",
|
|
69
|
-
day: "numeric",
|
|
70
|
-
})}
|
|
71
|
-
</p>
|
|
72
|
-
</div>
|
|
73
|
-
<span class="rounded bg-zinc-100 px-1.5 py-0.5 text-[10px] font-medium text-dimmed dark:bg-zinc-800">
|
|
74
|
-
v{entry.version}
|
|
75
|
-
</span>
|
|
76
|
-
</div>
|
|
77
|
-
<MarkdownView trustedHtml={entry.bodyHtml} />
|
|
78
|
-
</article>
|
|
79
|
-
)}
|
|
80
|
-
</For>
|
|
81
|
-
</PanelDialog.Body>
|
|
82
|
-
<PanelDialog.Footer>
|
|
83
|
-
<span />
|
|
84
|
-
<Button size="sm" onClick={() => close()}>
|
|
85
|
-
{t().gotIt}
|
|
86
|
-
</Button>
|
|
87
|
-
</PanelDialog.Footer>
|
|
88
|
-
</PanelDialog>
|
|
89
|
-
),
|
|
90
|
-
panelDialogOptions,
|
|
91
|
-
)
|
|
92
|
-
.then(closeAnnouncements);
|
|
93
|
-
});
|
|
94
|
-
|
|
95
|
-
return (
|
|
96
|
-
<Show when={banners().length > 0}>
|
|
97
|
-
<div class="flex shrink-0 flex-col gap-1">
|
|
98
|
-
<For each={banners()}>
|
|
99
|
-
{(banner) => (
|
|
100
|
-
<div class="cloud-announcement">
|
|
101
|
-
<NoticeCard tone={banner.tone} title={banner.title}>
|
|
102
|
-
<MarkdownView
|
|
103
|
-
trustedHtml={banner.bodyHtml}
|
|
104
|
-
headingScale="compact"
|
|
105
|
-
class="-mx-2 max-h-36 overflow-y-auto overscroll-contain pl-2 pr-3 [&_p]:my-0"
|
|
106
|
-
/>
|
|
107
|
-
</NoticeCard>
|
|
108
|
-
<IconButton size="sm" label={t().dismissBanner} onClick={() => dismissBanner(banner.version)}>
|
|
109
|
-
<i class="ti ti-x" aria-hidden="true" />
|
|
110
|
-
</IconButton>
|
|
111
|
-
</div>
|
|
112
|
-
)}
|
|
113
|
-
</For>
|
|
114
|
-
</div>
|
|
115
|
-
</Show>
|
|
116
|
-
);
|
|
117
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import { IconButton, Tooltip, useLocale } from "@k2b/ui";
|
|
2
|
-
import { createEffect, onCleanup, onMount } from "solid-js";
|
|
3
|
-
import { registerContextAwareCommand } from "../browser/command-bridge";
|
|
4
|
-
import { attachCommandShortcuts } from "../browser/command-shortcuts";
|
|
5
|
-
import type { NavigationSearchItem } from "../browser/navigation-search";
|
|
6
|
-
import { importOnDemand } from "../browser/reload";
|
|
7
|
-
import { openGlobalSearch } from "../browser/search";
|
|
8
|
-
import { registerGlobalSearchHost } from "../browser/search-bridge";
|
|
9
|
-
import { createGlobalSearchHost } from "./global-search-host";
|
|
10
|
-
import { platformMessages } from "./platform-messages";
|
|
11
|
-
|
|
12
|
-
type GlobalSearchTriggerProps = {
|
|
13
|
-
variant: "header" | "rail" | "host";
|
|
14
|
-
class?: string;
|
|
15
|
-
registerCommand?: boolean;
|
|
16
|
-
searchLinks?: NavigationSearchItem[];
|
|
17
|
-
searchResources?: boolean;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
/** Opens the spotlight-style global search dialog from nav/header trigger points. */
|
|
21
|
-
export default function GlobalSearchTrigger(props: GlobalSearchTriggerProps) {
|
|
22
|
-
const locale = useLocale();
|
|
23
|
-
const t = () => platformMessages.resolve([locale()]).t;
|
|
24
|
-
|
|
25
|
-
if (props.registerCommand) {
|
|
26
|
-
const host = createGlobalSearchHost(() => props.searchLinks ?? [], props.searchResources);
|
|
27
|
-
onMount(() => {
|
|
28
|
-
onCleanup(registerGlobalSearchHost(host.open, host.dispose));
|
|
29
|
-
});
|
|
30
|
-
// Commands, their schemas and the capability client load on the first shortcut, not with every page.
|
|
31
|
-
onMount(() =>
|
|
32
|
-
onCleanup(
|
|
33
|
-
attachCommandShortcuts(
|
|
34
|
-
(command) =>
|
|
35
|
-
void importOnDemand(() => import("../browser/commands")).then((commands) => commands?.runContextAwareCommand(command)),
|
|
36
|
-
),
|
|
37
|
-
),
|
|
38
|
-
);
|
|
39
|
-
createEffect(() =>
|
|
40
|
-
onCleanup(
|
|
41
|
-
registerContextAwareCommand({
|
|
42
|
-
id: "cloud.search",
|
|
43
|
-
title: t().openGlobalSearch,
|
|
44
|
-
description: t().globalSearchDescription,
|
|
45
|
-
icon: "ti ti-search",
|
|
46
|
-
shortcut: "mod+k",
|
|
47
|
-
action: { search: {} },
|
|
48
|
-
}),
|
|
49
|
-
),
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
if (props.variant === "host") return null;
|
|
54
|
-
|
|
55
|
-
if (props.variant === "rail")
|
|
56
|
-
return (
|
|
57
|
-
<Tooltip.Trigger
|
|
58
|
-
type="button"
|
|
59
|
-
class={`rail-item text-blue-500 hover:bg-blue-500/10 hover:text-blue-600 dark:text-blue-400 dark:hover:bg-blue-500/15 dark:hover:text-blue-300 ${props.class ?? ""}`}
|
|
60
|
-
onClick={() => openGlobalSearch()}
|
|
61
|
-
aria-label={t().openGlobalSearch}
|
|
62
|
-
placement="right"
|
|
63
|
-
delay={0}
|
|
64
|
-
content={t().searchShortcut}
|
|
65
|
-
>
|
|
66
|
-
<i class="ti ti-search text-base" />
|
|
67
|
-
</Tooltip.Trigger>
|
|
68
|
-
);
|
|
69
|
-
|
|
70
|
-
return (
|
|
71
|
-
<IconButton class={props.class} onClick={() => openGlobalSearch()} label={t().openGlobalSearch} title={t().searchShortcut}>
|
|
72
|
-
<i class="ti ti-search text-base" />
|
|
73
|
-
</IconButton>
|
|
74
|
-
);
|
|
75
|
-
}
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { IconButton, Tooltip, useLocale } from "@k2b/ui";
|
|
2
|
-
import { createEffect, onCleanup } from "solid-js";
|
|
3
|
-
import { registerContextAwareCommand } from "../browser/command-bridge";
|
|
4
|
-
import type { GlobalSearchHelpApp } from "./GlobalSearchHelpDialog";
|
|
5
|
-
import { openLayoutHelpDialog } from "./LayoutHelp";
|
|
6
|
-
import { platformMessages } from "./platform-messages";
|
|
7
|
-
|
|
8
|
-
type LayoutHelpTriggerProps = {
|
|
9
|
-
variant: "header" | "rail";
|
|
10
|
-
class?: string;
|
|
11
|
-
registerCommand?: boolean;
|
|
12
|
-
searchHelpApps?: GlobalSearchHelpApp[];
|
|
13
|
-
accent?: string;
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
/** Opens end-user help from either the desktop rail or the compact header. */
|
|
17
|
-
export default function LayoutHelpTrigger(props: LayoutHelpTriggerProps) {
|
|
18
|
-
const locale = useLocale();
|
|
19
|
-
const t = () => platformMessages.resolve([locale()]).t;
|
|
20
|
-
const searchHelpApps = props.searchHelpApps ?? [];
|
|
21
|
-
|
|
22
|
-
const openHelp = () => {
|
|
23
|
-
openLayoutHelpDialog(searchHelpApps, props.accent);
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
if (props.registerCommand) {
|
|
27
|
-
createEffect(() =>
|
|
28
|
-
onCleanup(
|
|
29
|
-
registerContextAwareCommand({
|
|
30
|
-
id: "cloud.help",
|
|
31
|
-
title: t().openShortcutHelp,
|
|
32
|
-
description: t().shortcutHelpDescription,
|
|
33
|
-
icon: "ti ti-help-circle",
|
|
34
|
-
shortcut: "shift+/",
|
|
35
|
-
action: openHelp,
|
|
36
|
-
}),
|
|
37
|
-
),
|
|
38
|
-
);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (props.variant === "rail")
|
|
42
|
-
return (
|
|
43
|
-
<Tooltip.Trigger
|
|
44
|
-
type="button"
|
|
45
|
-
class={`rail-item text-blue-500 hover:bg-blue-500/10 hover:text-blue-600 dark:text-blue-400 dark:hover:bg-blue-500/15 dark:hover:text-blue-300 ${props.class ?? ""}`}
|
|
46
|
-
onClick={openHelp}
|
|
47
|
-
aria-label={t().openHelp}
|
|
48
|
-
placement="right"
|
|
49
|
-
delay={0}
|
|
50
|
-
content={t().helpShortcut}
|
|
51
|
-
>
|
|
52
|
-
<i class="ti ti-help-circle text-base" />
|
|
53
|
-
</Tooltip.Trigger>
|
|
54
|
-
);
|
|
55
|
-
|
|
56
|
-
return (
|
|
57
|
-
<IconButton class={props.class} onClick={openHelp} label={t().openHelp} title={t().helpShortcut}>
|
|
58
|
-
<i class="ti ti-help-circle text-base" />
|
|
59
|
-
</IconButton>
|
|
60
|
-
);
|
|
61
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { PageTitle, usePageTrail } from "@k2b/ui";
|
|
2
|
-
import { Show } from "solid-js";
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* The shell's own place for the way up, above pages without a workspace. It
|
|
6
|
-
* shows only on a page with a page above it, and steps back when the page
|
|
7
|
-
* renders a workspace (whose head shows it) or its own `PageTrail`.
|
|
8
|
-
*/
|
|
9
|
-
export default function PageTrailRow() {
|
|
10
|
-
const trail = usePageTrail();
|
|
11
|
-
const deep = () => {
|
|
12
|
-
const current = trail();
|
|
13
|
-
return current?.ancestors.length ? current : undefined;
|
|
14
|
-
};
|
|
15
|
-
return (
|
|
16
|
-
<div class="layout-page-head" data-trail={deep() ? "up" : undefined}>
|
|
17
|
-
<Show when={deep()}>{(current) => <PageTitle trail={current()} as="p" fallback />}</Show>
|
|
18
|
-
</div>
|
|
19
|
-
);
|
|
20
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { followPageTrail, installPageTitleController, useLocale } from "@k2b/ui";
|
|
2
|
-
import { onCleanup, onMount } from "solid-js";
|
|
3
|
-
import { installPageTrailRuntime } from "./page-trail-runtime";
|
|
4
|
-
import { platformMessages } from "./platform-messages";
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* One owner per document for the way up: it collapses every page title path
|
|
8
|
-
* to its space, keeps server-rendered workspace heads current after
|
|
9
|
-
* `layout.update()`, runs the per-tab memory behind up links, and offers
|
|
10
|
-
* "One level up" (Alt+↑) while the page has a page above it.
|
|
11
|
-
*/
|
|
12
|
-
export default function PageTrailRuntime() {
|
|
13
|
-
const locale = useLocale();
|
|
14
|
-
onMount(() => {
|
|
15
|
-
const t = platformMessages.resolve([locale()]).t;
|
|
16
|
-
const disposeTitles = installPageTitleController(document);
|
|
17
|
-
const disposeFollow = followPageTrail(document);
|
|
18
|
-
const disposeRuntime = installPageTrailRuntime((page) => ({ title: t.pageUp({ page }), description: t.pageUpDescription }));
|
|
19
|
-
onCleanup(() => {
|
|
20
|
-
disposeTitles();
|
|
21
|
-
disposeFollow();
|
|
22
|
-
disposeRuntime();
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
File without changes
|