@datalayer/core 1.2.10 → 1.2.13
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 +5 -5
- package/lib/api/iam/authentication.js +6 -4
- package/lib/api/iam/healthz.js +2 -2
- package/lib/api/iam/oauth2.js +18 -12
- package/lib/api/iam/secrets.js +1 -2
- package/lib/api/mcp/observability.d.ts +9 -2
- package/lib/api/mcp/observability.js +40 -15
- package/lib/client/auth/strategies.js +1 -1
- package/lib/client/mixins/IAMMixin.js +2 -2
- package/lib/components/checkout/StripeCheckout.d.ts +1 -1
- package/lib/components/checkout/StripeCheckout.js +1 -1
- package/lib/components/display/VisuallyHidden.d.ts +1 -2
- package/lib/components/sharing/sandboxSharing.js +7 -1
- package/lib/config/Configuration.d.ts +4 -4
- package/lib/config/Configuration.js +7 -7
- package/lib/config/index.d.ts +1 -0
- package/lib/config/index.js +1 -0
- package/lib/config/planes.d.ts +45 -0
- package/lib/config/planes.js +53 -0
- package/lib/hooks/useBackdrop.d.ts +4 -5
- package/lib/hooks/useCache.d.ts +52 -19
- package/lib/hooks/useCache.js +310 -198
- package/lib/hooks/useContents.js +3 -0
- package/lib/hooks/useMcp.js +1 -1
- package/lib/hooks/useNavigate.js +10 -0
- package/lib/hooks/useWindowSize.js +1 -1
- package/lib/models/IAMProvidersSpecs.d.ts +10 -5
- package/lib/models/IAMProvidersSpecs.js +0 -23
- package/lib/models/URN.d.ts +37 -0
- package/lib/models/URN.js +59 -1
- package/lib/navigation/adapters/react-router.d.ts +1 -1
- package/lib/navigation/adapters/react-router.js +3 -0
- package/lib/state/sessionEnd.js +1 -1
- package/lib/state/substates/CoreState.js +3 -16
- package/lib/state/substates/IAMState.d.ts +3 -3
- package/lib/state/substates/NavigationState.d.ts +92 -0
- package/lib/state/substates/NavigationState.js +304 -0
- package/lib/state/substates/index.d.ts +1 -0
- package/lib/state/substates/index.js +1 -0
- package/lib/utils/Handles.js +1 -1
- package/lib/utils/Screencapture.d.ts +15 -0
- package/lib/utils/Screencapture.js +26 -23
- package/lib/views/mcp/McpDashboard.js +15 -10
- package/lib/views/mcp/McpHome.js +13 -6
- package/lib/views/mcp/types.d.ts +4 -0
- package/package.json +9 -7
- package/scripts/generate-mcp-types.py +15 -9
package/lib/hooks/useNavigate.js
CHANGED
|
@@ -14,10 +14,17 @@
|
|
|
14
14
|
* `window.open` otherwise, so a button gets it too. `newTab` in the options
|
|
15
15
|
* opens a new tab outright.
|
|
16
16
|
*
|
|
17
|
+
* Every navigation that stays in this tab is also **recorded** against the
|
|
18
|
+
* shell the reader is in ({@link state/substates/NavigationState}). That is
|
|
19
|
+
* what lets a reader switch from Agentify back to Home and find the page they
|
|
20
|
+
* left rather than a landing page, and it is done here — the one place every
|
|
21
|
+
* navigation goes through — rather than in an effect per layout.
|
|
22
|
+
*
|
|
17
23
|
* @module hooks/useNavigate
|
|
18
24
|
*/
|
|
19
25
|
import { useCallback, useMemo } from 'react';
|
|
20
26
|
import { useLayoutStore } from '../state/index.js';
|
|
27
|
+
import { navigationStore } from '../state/substates/NavigationState.js';
|
|
21
28
|
import { createNativeNavigate } from '../navigation/adapters/native.js';
|
|
22
29
|
// Import React Router hooks from our wrapper
|
|
23
30
|
import { useNavigateRR } from '../navigation/adapters/react-router.js';
|
|
@@ -125,6 +132,9 @@ export const useNavigate = () => {
|
|
|
125
132
|
window.scrollTo(0, 0);
|
|
126
133
|
document.body.scrollTop = 0;
|
|
127
134
|
}
|
|
135
|
+
// Where the reader is now, for the shell they are in. A new tab and a
|
|
136
|
+
// step back through history are both already past by here.
|
|
137
|
+
navigationStore.getState().rememberRoute(to);
|
|
128
138
|
if (rrNavigate) {
|
|
129
139
|
rrNavigate(to, { replace: options.replace, state: options.state });
|
|
130
140
|
return;
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { IUser } from './User';
|
|
2
2
|
export type IIAMProviderName = 'bluesky' | 'discord' | 'github' | 'google' | 'linkedin' | 'okta' | 'x';
|
|
3
|
+
/** Providers whose access token is intentionally available to browser code. */
|
|
4
|
+
export type IBrowserTokenProviderName = Exclude<IIAMProviderName, 'bluesky' | 'linkedin'>;
|
|
3
5
|
export type IIAMProviderSpec = {
|
|
4
6
|
name: IIAMProviderName;
|
|
5
7
|
oauth2CallbackServerRoute: string;
|
|
6
8
|
oauth2CallbackUIRoute: string;
|
|
9
|
+
};
|
|
10
|
+
/** Provider metadata used only when its access token may be read by the UI. */
|
|
11
|
+
export type IBrowserTokenProviderSpec = IIAMProviderSpec & {
|
|
12
|
+
name: IBrowserTokenProviderName;
|
|
7
13
|
accessTokenCookieName: (user: IUser) => string;
|
|
8
14
|
refreshTokenCookieName: string;
|
|
9
15
|
userInfoURL: string;
|
|
@@ -13,11 +19,10 @@ export type IIAMProviderSpec = {
|
|
|
13
19
|
};
|
|
14
20
|
export declare class IAMProvidersSpecs {
|
|
15
21
|
private constructor();
|
|
16
|
-
static getProvider(providerIAMProvidersType:
|
|
17
|
-
static readonly
|
|
18
|
-
static readonly
|
|
19
|
-
static readonly Google: IIAMProviderSpec;
|
|
22
|
+
static getProvider(providerIAMProvidersType: IBrowserTokenProviderName): IBrowserTokenProviderSpec;
|
|
23
|
+
static readonly GitHub: IBrowserTokenProviderSpec;
|
|
24
|
+
static readonly Google: IBrowserTokenProviderSpec;
|
|
20
25
|
static readonly LinkedIn: IIAMProviderSpec;
|
|
21
|
-
static readonly Okta:
|
|
26
|
+
static readonly Okta: IBrowserTokenProviderSpec;
|
|
22
27
|
}
|
|
23
28
|
export default IAMProvidersSpecs;
|
|
@@ -6,18 +6,12 @@ export class IAMProvidersSpecs {
|
|
|
6
6
|
constructor() { }
|
|
7
7
|
static getProvider(providerIAMProvidersType) {
|
|
8
8
|
switch (providerIAMProvidersType) {
|
|
9
|
-
case 'bluesky': {
|
|
10
|
-
return this.Bluesky;
|
|
11
|
-
}
|
|
12
9
|
case 'github': {
|
|
13
10
|
return this.GitHub;
|
|
14
11
|
}
|
|
15
12
|
case 'google': {
|
|
16
13
|
return this.Google;
|
|
17
14
|
}
|
|
18
|
-
case 'linkedin': {
|
|
19
|
-
return this.LinkedIn;
|
|
20
|
-
}
|
|
21
15
|
case 'okta': {
|
|
22
16
|
return this.Okta;
|
|
23
17
|
}
|
|
@@ -27,17 +21,6 @@ export class IAMProvidersSpecs {
|
|
|
27
21
|
}
|
|
28
22
|
}
|
|
29
23
|
}
|
|
30
|
-
static Bluesky = {
|
|
31
|
-
name: 'bluesky',
|
|
32
|
-
oauth2CallbackServerRoute: 'jupyter_iam/oauth2/callback',
|
|
33
|
-
oauth2CallbackUIRoute: '/iam/oauth2/bluesky/callback',
|
|
34
|
-
accessTokenCookieName: (user) => `__datalayer__bluesky_access_token_${user.id}`,
|
|
35
|
-
refreshTokenCookieName: '__datalayer__bluesky_refresh_token',
|
|
36
|
-
userInfoURL: '',
|
|
37
|
-
tokenRefreshURL: '',
|
|
38
|
-
postShareURL: '',
|
|
39
|
-
registerUploadURL: '',
|
|
40
|
-
};
|
|
41
24
|
static GitHub = {
|
|
42
25
|
name: 'github',
|
|
43
26
|
oauth2CallbackServerRoute: 'jupyter_iam/oauth2/callback',
|
|
@@ -64,12 +47,6 @@ export class IAMProvidersSpecs {
|
|
|
64
47
|
name: 'linkedin',
|
|
65
48
|
oauth2CallbackServerRoute: 'jupyter_iam/oauth2/callback',
|
|
66
49
|
oauth2CallbackUIRoute: '/iam/oauth2/linkedin/callback',
|
|
67
|
-
accessTokenCookieName: (user) => `__datalayer__linkedin_access_token_${user.id}`,
|
|
68
|
-
refreshTokenCookieName: '__datalayer__linkedin_refresh_token',
|
|
69
|
-
userInfoURL: 'https://api.linkedin.com/v2/userinfo',
|
|
70
|
-
tokenRefreshURL: '',
|
|
71
|
-
postShareURL: 'https://api.linkedin.com/v2/ugcPosts',
|
|
72
|
-
registerUploadURL: 'https://api.linkedin.com/v2/assets?action=registerUpload',
|
|
73
50
|
};
|
|
74
51
|
static Okta = {
|
|
75
52
|
name: 'okta',
|
package/lib/models/URN.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type { IIAMProviderName } from './IAMProvidersSpecs';
|
|
2
|
+
/** What an identity provider's account URN starts with, before its name. */
|
|
3
|
+
export declare const IAM_PROVIDER_URN_PREFIX = "urn:dla:iam:ext::";
|
|
1
4
|
export declare class URN implements IURN {
|
|
2
5
|
private _partition;
|
|
3
6
|
private _service;
|
|
@@ -12,7 +15,41 @@ export declare class URN implements IURN {
|
|
|
12
15
|
get account(): string;
|
|
13
16
|
get type(): string;
|
|
14
17
|
get uid(): string;
|
|
18
|
+
/** An identity provider's account (`urn:dla:iam:ext::github:…`). */
|
|
19
|
+
get isIAMProviderAccount(): boolean;
|
|
20
|
+
toString(): string;
|
|
15
21
|
}
|
|
22
|
+
/** A URN, or `undefined` when the value is not one — never a throw. */
|
|
23
|
+
export declare function parseURN(value?: string | null): URN | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Where an account came from, read from its `origin`.
|
|
26
|
+
*
|
|
27
|
+
* - `datalayer`: made on Datalayer, with a password.
|
|
28
|
+
* - `iam-provider`: made by signing in with an identity provider, which it
|
|
29
|
+
* still signs in through (`urn:dla:iam:ext::<provider>:<account id>`).
|
|
30
|
+
* - `urn`: any other URN — an AWS Marketplace or enterprise origin.
|
|
31
|
+
* - `unknown`: nothing recorded, or a value that is none of the above.
|
|
32
|
+
*/
|
|
33
|
+
export type IAccountOrigin = {
|
|
34
|
+
kind: 'datalayer';
|
|
35
|
+
} | {
|
|
36
|
+
kind: 'iam-provider';
|
|
37
|
+
provider: IIAMProviderName;
|
|
38
|
+
accountId: string;
|
|
39
|
+
urn: URN;
|
|
40
|
+
} | {
|
|
41
|
+
kind: 'urn';
|
|
42
|
+
urn: URN;
|
|
43
|
+
} | {
|
|
44
|
+
kind: 'unknown';
|
|
45
|
+
value: string;
|
|
46
|
+
};
|
|
47
|
+
export declare function accountOriginOf(origin?: string | null): IAccountOrigin;
|
|
48
|
+
/**
|
|
49
|
+
* Whether an account signs in through a provider: disconnecting that
|
|
50
|
+
* provider would leave it nothing to sign in with.
|
|
51
|
+
*/
|
|
52
|
+
export declare function signsInWith(origin: string | null | undefined, provider: IIAMProviderName): boolean;
|
|
16
53
|
/**
|
|
17
54
|
Datalayer Uniform Resource Name (URN)
|
|
18
55
|
|
package/lib/models/URN.js
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
|
+
/** What an identity provider's account URN starts with, before its name. */
|
|
6
|
+
export const IAM_PROVIDER_URN_PREFIX = 'urn:dla:iam:ext::';
|
|
5
7
|
export class URN {
|
|
6
8
|
_partition;
|
|
7
9
|
_service;
|
|
@@ -17,7 +19,8 @@ export class URN {
|
|
|
17
19
|
this._region = parts[3];
|
|
18
20
|
this._account = parts[4];
|
|
19
21
|
this._type = parts[5];
|
|
20
|
-
|
|
22
|
+
// The rest, colons and all: a provider's account id may carry them.
|
|
23
|
+
this._uid = parts.slice(6).join(':');
|
|
21
24
|
}
|
|
22
25
|
get partition() {
|
|
23
26
|
return this._partition;
|
|
@@ -37,4 +40,59 @@ export class URN {
|
|
|
37
40
|
get uid() {
|
|
38
41
|
return this._uid;
|
|
39
42
|
}
|
|
43
|
+
/** An identity provider's account (`urn:dla:iam:ext::github:…`). */
|
|
44
|
+
get isIAMProviderAccount() {
|
|
45
|
+
return this._service === 'iam' && this._region === 'ext' && !!this._type;
|
|
46
|
+
}
|
|
47
|
+
toString() {
|
|
48
|
+
return [
|
|
49
|
+
'urn',
|
|
50
|
+
this._partition,
|
|
51
|
+
this._service,
|
|
52
|
+
this._region,
|
|
53
|
+
this._account,
|
|
54
|
+
this._type,
|
|
55
|
+
this._uid,
|
|
56
|
+
].join(':');
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/** A URN, or `undefined` when the value is not one — never a throw. */
|
|
60
|
+
export function parseURN(value) {
|
|
61
|
+
const text = (value ?? '').trim();
|
|
62
|
+
if (!text.toLowerCase().startsWith('urn:') || text.split(':').length < 7) {
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
return new URN(text);
|
|
66
|
+
}
|
|
67
|
+
const IAM_PROVIDER_NAMES = [
|
|
68
|
+
'bluesky',
|
|
69
|
+
'discord',
|
|
70
|
+
'github',
|
|
71
|
+
'google',
|
|
72
|
+
'linkedin',
|
|
73
|
+
'okta',
|
|
74
|
+
'x',
|
|
75
|
+
];
|
|
76
|
+
export function accountOriginOf(origin) {
|
|
77
|
+
const value = (origin ?? '').trim();
|
|
78
|
+
if (value === 'datalayer') {
|
|
79
|
+
return { kind: 'datalayer' };
|
|
80
|
+
}
|
|
81
|
+
const urn = parseURN(value);
|
|
82
|
+
if (!urn) {
|
|
83
|
+
return { kind: 'unknown', value };
|
|
84
|
+
}
|
|
85
|
+
const provider = urn.type.toLowerCase();
|
|
86
|
+
if (urn.isIAMProviderAccount && IAM_PROVIDER_NAMES.includes(provider)) {
|
|
87
|
+
return { kind: 'iam-provider', provider, accountId: urn.uid, urn };
|
|
88
|
+
}
|
|
89
|
+
return { kind: 'urn', urn };
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Whether an account signs in through a provider: disconnecting that
|
|
93
|
+
* provider would leave it nothing to sign in with.
|
|
94
|
+
*/
|
|
95
|
+
export function signsInWith(origin, provider) {
|
|
96
|
+
const parsed = accountOriginOf(origin);
|
|
97
|
+
return parsed.kind === 'iam-provider' && parsed.provider === provider;
|
|
40
98
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import * as ReactRouterDom from 'react-router-dom';
|
|
2
2
|
export declare const useParamsRR: typeof ReactRouterDom.useParams;
|
|
3
3
|
export declare const useLocationRR: typeof ReactRouterDom.useLocation;
|
|
4
|
-
export declare const useNavigateRR:
|
|
4
|
+
export declare const useNavigateRR: () => ReactRouterDom.NavigateFunction;
|
|
@@ -9,4 +9,7 @@ import * as ReactRouterDom from 'react-router-dom';
|
|
|
9
9
|
// Export hooks for use in our navigation hooks
|
|
10
10
|
export const useParamsRR = ReactRouterDom.useParams;
|
|
11
11
|
export const useLocationRR = ReactRouterDom.useLocation;
|
|
12
|
+
// Typed here rather than inferred: the inferred type carries React Router's
|
|
13
|
+
// own doc comment, whose links (`redirect`, `To`, `<ScrollRestoration>`) point
|
|
14
|
+
// at symbols these docs do not include, and typedoc fails the build on them.
|
|
12
15
|
export const useNavigateRR = ReactRouterDom.useNavigate;
|
package/lib/state/sessionEnd.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { createStore } from 'zustand/vanilla';
|
|
6
6
|
import { useStore } from 'zustand';
|
|
7
|
+
import { DEFAULT_PLANE_URLS } from '../../config/planes.js';
|
|
7
8
|
import { configLogger } from '../../utils/Logger.js';
|
|
8
9
|
let loadConfigurationFromServer = true;
|
|
9
10
|
let initialConfiguration = {
|
|
@@ -15,22 +16,8 @@ let initialConfiguration = {
|
|
|
15
16
|
whiteLabel: true,
|
|
16
17
|
loadConfigurationFromServer: true,
|
|
17
18
|
jupyterServerless: false,
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
managerUrl: 'https://prod1.datalayer.run',
|
|
21
|
-
runtimesUrl: 'https://r1.datalayer.run',
|
|
22
|
-
schedulerUrl: 'https://r1.datalayer.run',
|
|
23
|
-
libraryUrl: 'https://prod1.datalayer.run',
|
|
24
|
-
spacerUrl: 'https://prod1.datalayer.run',
|
|
25
|
-
aiAgentsUrl: 'https://r1.datalayer.run',
|
|
26
|
-
aiInferenceUrl: 'https://r1.datalayer.run',
|
|
27
|
-
jupyterMcpServerUrl: 'https://mcp.datalayer.run/mcp',
|
|
28
|
-
otelUrl: 'https://prod1.datalayer.run',
|
|
29
|
-
// Defaults to prod so telemetry is consumed from the production OTEL service
|
|
30
|
-
growthUrl: 'https://prod1.datalayer.run',
|
|
31
|
-
inboundsUrl: 'https://prod1.datalayer.run',
|
|
32
|
-
successUrl: 'https://prod1.datalayer.run',
|
|
33
|
-
supportUrl: 'https://prod1.datalayer.run',
|
|
19
|
+
// Which plane each service is on is said once, in `config/planes`.
|
|
20
|
+
...DEFAULT_PLANE_URLS,
|
|
34
21
|
launcher: {
|
|
35
22
|
category: 'Datalayer',
|
|
36
23
|
name: 'Datalayer',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { IUser, IIAMProviderName } from '../../models';
|
|
1
|
+
import { IUser, IIAMProviderName, IBrowserTokenProviderName } from '../../models';
|
|
2
2
|
import type { ICredits, ICreditsReservation } from '../../models';
|
|
3
3
|
/**
|
|
4
4
|
* Limit to warn about low credits in milliseconds.
|
|
@@ -55,8 +55,8 @@ export type IAMState = IIAMState & {
|
|
|
55
55
|
*/
|
|
56
56
|
refreshCredits: () => Promise<void>;
|
|
57
57
|
checkIAMToken: (token: string) => Promise<void>;
|
|
58
|
-
setIAMProviderAccessToken: (provider:
|
|
59
|
-
getIAMProviderAccessToken: (user: IUser, provider:
|
|
58
|
+
setIAMProviderAccessToken: (provider: IBrowserTokenProviderName, accessToken?: string | null) => void;
|
|
59
|
+
getIAMProviderAccessToken: (user: IUser, provider: IBrowserTokenProviderName) => string | undefined;
|
|
60
60
|
refreshUser: () => Promise<void>;
|
|
61
61
|
refreshUserByTokenStored: () => Promise<void>;
|
|
62
62
|
refreshUserByToken: (token: string) => Promise<void>;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/** The signed-in shell: the platform, the business cases, or the admin. */
|
|
2
|
+
/**
|
|
3
|
+
* The four shells of the signed-in application.
|
|
4
|
+
*
|
|
5
|
+
* `studio` is where an agentic UI application is composed, validated and
|
|
6
|
+
* shipped — the default for somebody who has not chosen, and what the root
|
|
7
|
+
* shows. `home` is the whole platform, shown as *Power*, at `/power`: the key
|
|
8
|
+
* is kept so a cookie written before the Studio existed still names the
|
|
9
|
+
* shell it meant. `agentify` is the business cases; `admin` is the
|
|
10
|
+
* platform's administration.
|
|
11
|
+
*/
|
|
12
|
+
export type NavigationView = 'studio' | 'home' | 'agentify' | 'admin';
|
|
13
|
+
/** The shells, and where each one opens when it has not been visited. */
|
|
14
|
+
export declare const NAVIGATION_VIEW_HOMES: Record<NavigationView, string>;
|
|
15
|
+
/** Well-known view identifiers for {@link NavigationState.tabsByView}. */
|
|
16
|
+
export declare const LIBRARY_VIEW = "library";
|
|
17
|
+
export declare const AGENTS_VIEW = "agents";
|
|
18
|
+
export declare const SETTINGS_VIEW = "settings";
|
|
19
|
+
export declare const DATALAYER_VIEW = "datalayer";
|
|
20
|
+
export declare const CONTENTS_VIEW = "contents";
|
|
21
|
+
export declare const TUTOR_VIEW = "tutor";
|
|
22
|
+
export type NavigationState = {
|
|
23
|
+
/** The shell the reader last chose. */
|
|
24
|
+
view: NavigationView;
|
|
25
|
+
/** State which shell is being shown. */
|
|
26
|
+
setView: (view: NavigationView) => void;
|
|
27
|
+
/** Swap the platform and the business cases. */
|
|
28
|
+
toggleView: () => void;
|
|
29
|
+
/** The page each shell was last on. */
|
|
30
|
+
lastRouteByView: Partial<Record<NavigationView, string>>;
|
|
31
|
+
/**
|
|
32
|
+
* Remember a page as the current shell's, or as another's when told.
|
|
33
|
+
*
|
|
34
|
+
* Called by {@link useNavigate} for every navigation, which is what makes
|
|
35
|
+
* this the one place the answer comes from.
|
|
36
|
+
*/
|
|
37
|
+
rememberRoute: (route: string, view?: NavigationView) => void;
|
|
38
|
+
/** Where a shell was left, or where it opens when it never was. */
|
|
39
|
+
routeForView: (view: NavigationView) => string;
|
|
40
|
+
/** Last selected tab, by view identifier. */
|
|
41
|
+
tabsByView: Record<string, string>;
|
|
42
|
+
/** Keep the tab a view was left on. */
|
|
43
|
+
setViewTab: (view: string, tab: string) => void;
|
|
44
|
+
/** The tab a view was left on, if any. */
|
|
45
|
+
getViewTab: (view: string) => string | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* The route a signed-out reader asked for, to resume after signing in.
|
|
48
|
+
*
|
|
49
|
+
* Never persisted: a reload must land on the default route, and the OAuth
|
|
50
|
+
* round trip carries its target in `post_auth_redirect` instead.
|
|
51
|
+
*/
|
|
52
|
+
requestedRoute?: string;
|
|
53
|
+
setRequestedRoute: (route: string) => void;
|
|
54
|
+
clearRequestedRoute: () => void;
|
|
55
|
+
/** The address the reader was on before the documentation. */
|
|
56
|
+
docsOrigin?: string;
|
|
57
|
+
setDocsOrigin: (origin: string) => void;
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Whether a page is worth remembering as a shell's.
|
|
61
|
+
*
|
|
62
|
+
* Not the sign-in pages, the OAuth callbacks or the documentation: coming
|
|
63
|
+
* back to a shell should land on the work, not on the door the reader came
|
|
64
|
+
* through or on a page that belongs to no shell.
|
|
65
|
+
*/
|
|
66
|
+
export declare function isRememberableRoute(route: string): boolean;
|
|
67
|
+
/**
|
|
68
|
+
* The shell a route belongs to, read off its first segment.
|
|
69
|
+
*
|
|
70
|
+
* The store used to trust whatever `view` said when a route was recorded,
|
|
71
|
+
* and `view` was only ever written by the header toggle. A reader who
|
|
72
|
+
* reached Home through a sidebar link while the toggle still said Agentify
|
|
73
|
+
* had their Home pages filed under Agentify — and the toggle, seeing
|
|
74
|
+
* "Agentify" already chosen, did nothing when they clicked it.
|
|
75
|
+
*/
|
|
76
|
+
export declare function viewForRoute(route: string): NavigationView;
|
|
77
|
+
export declare const navigationStore: import("zustand").StoreApi<NavigationState>;
|
|
78
|
+
/**
|
|
79
|
+
* The hook, shaped like a `zustand` store created with `create`: callable
|
|
80
|
+
* with or without a selector, and carrying `getState`, `setState` and
|
|
81
|
+
* `subscribe` for the callers — a router guard, a test — that read it outside
|
|
82
|
+
* a render.
|
|
83
|
+
*/
|
|
84
|
+
export interface UseNavigationStore {
|
|
85
|
+
(): NavigationState;
|
|
86
|
+
<T>(selector: (state: NavigationState) => T): T;
|
|
87
|
+
getState: () => NavigationState;
|
|
88
|
+
setState: typeof navigationStore.setState;
|
|
89
|
+
subscribe: typeof navigationStore.subscribe;
|
|
90
|
+
}
|
|
91
|
+
export declare const useNavigationStore: UseNavigationStore;
|
|
92
|
+
export default useNavigationStore;
|