@datalayer/core 1.2.14 → 1.2.17

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.
@@ -51,6 +51,12 @@ export type AnonymousKeyExpiredProps = {
51
51
  temporary?: boolean;
52
52
  /** Called after a successful sign-in, once the token is stored. */
53
53
  onSignedIn?: () => void;
54
+ /**
55
+ * Called on *Sign up with email*, for a host with a router to send the
56
+ * reader to its own sign-up page; without it, the form opens its sign-up
57
+ * address.
58
+ */
59
+ onSignUp?: () => void;
54
60
  };
55
- export declare function AnonymousKeyExpired({ agentName, sandboxStillRuns, temporary, onSignedIn, }: AnonymousKeyExpiredProps): JSX.Element;
61
+ export declare function AnonymousKeyExpired({ agentName, sandboxStillRuns, temporary, onSignedIn, onSignUp, }: AnonymousKeyExpiredProps): JSX.Element;
56
62
  export default AnonymousKeyExpired;
@@ -5,7 +5,7 @@ import { Box } from '@datalayer/primer-addons';
5
5
  import { KeyIcon } from '@primer/octicons-react';
6
6
  import { SignInSimple } from '../../views/iam/SignInSimple.js';
7
7
  import { useCoreStore, iamStore } from '../../state/substates/index.js';
8
- export function AnonymousKeyExpired({ agentName, sandboxStillRuns = false, temporary = true, onSignedIn, }) {
8
+ export function AnonymousKeyExpired({ agentName, sandboxStillRuns = false, temporary = true, onSignedIn, onSignUp, }) {
9
9
  const { configuration } = useCoreStore();
10
10
  const handleSignIn = useCallback((token) => {
11
11
  /*
@@ -91,6 +91,6 @@ export function AnonymousKeyExpired({ agentName, sandboxStillRuns = false, tempo
91
91
  // has one and harmless for one that does not.
92
92
  loginUrl: configuration?.iamUrl
93
93
  ? `${configuration.iamUrl}/api/iam/v1/login`
94
- : undefined, onSignIn: handleSignIn })] }) }));
94
+ : undefined, onSignIn: handleSignIn, onSignUp: onSignUp })] }) }));
95
95
  }
96
96
  export default AnonymousKeyExpired;
@@ -18,6 +18,17 @@ export type StatusLabelProps = {
18
18
  size?: 'small' | 'large';
19
19
  sx?: Record<string, unknown>;
20
20
  };
21
+ /**
22
+ * The tone of each named label. A role or a stage is a quality, not a
23
+ * verdict, so none is in attention's amber: the theme keeps success, attention
24
+ * and danger for verdicts (LOOP T-14, T-29) — *admin* is quiet.
25
+ */
26
+ export declare const NAMED_LABEL_TONES: {
27
+ readonly alpha: "accent";
28
+ readonly admin: "neutral";
29
+ readonly default: "accent";
30
+ readonly soon: "neutral";
31
+ };
21
32
  /**
22
33
  * The pill the named labels below are made of.
23
34
  *
@@ -22,6 +22,17 @@ const TONES = {
22
22
  borderColor: 'border.default',
23
23
  },
24
24
  };
25
+ /**
26
+ * The tone of each named label. A role or a stage is a quality, not a
27
+ * verdict, so none is in attention's amber: the theme keeps success, attention
28
+ * and danger for verdicts (LOOP T-14, T-29) — *admin* is quiet.
29
+ */
30
+ export const NAMED_LABEL_TONES = {
31
+ alpha: 'accent',
32
+ admin: 'neutral',
33
+ default: 'accent',
34
+ soon: 'neutral',
35
+ };
25
36
  /**
26
37
  * The pill the named labels below are made of.
27
38
  *
@@ -42,25 +53,25 @@ export function StatusLabel(props) {
42
53
  */
43
54
  export function AlphaLabel(props = {}) {
44
55
  const { children = 'alpha', ...rest } = props;
45
- return (_jsx(StatusLabel, { tone: "accent", ...rest, children: children }));
56
+ return (_jsx(StatusLabel, { tone: NAMED_LABEL_TONES.alpha, ...rest, children: children }));
46
57
  }
47
58
  /**
48
59
  * Something reserved to the administrators of the platform.
49
60
  */
50
61
  export function AdminLabel(props = {}) {
51
62
  const { children = 'admin', ...rest } = props;
52
- return (_jsx(StatusLabel, { tone: "attention", ...rest, children: children }));
63
+ return (_jsx(StatusLabel, { tone: NAMED_LABEL_TONES.admin, ...rest, children: children }));
53
64
  }
54
65
  /**
55
66
  * The one that is taken when none is chosen — the default space of an account.
56
67
  */
57
68
  export function DefaultLabel(props = {}) {
58
69
  const { children = 'default', ...rest } = props;
59
- return (_jsx(StatusLabel, { tone: "accent", ...rest, children: children }));
70
+ return (_jsx(StatusLabel, { tone: NAMED_LABEL_TONES.default, ...rest, children: children }));
60
71
  }
61
72
  /** "soon": what is announced but not yet there. */
62
73
  export function SoonLabel(props = {}) {
63
74
  const { children = 'soon', ...rest } = props;
64
- return (_jsx(StatusLabel, { tone: "neutral", ...rest, children: children }));
75
+ return (_jsx(StatusLabel, { tone: NAMED_LABEL_TONES.soon, ...rest, children: children }));
65
76
  }
66
77
  export default StatusLabel;
@@ -2,6 +2,7 @@ export * from './useAuthorization';
2
2
  export * from './useBackdrop';
3
3
  export * from './useBackdropJupyterLab';
4
4
  export * from './useCache';
5
+ export * from './libraryApp';
5
6
  export * from './useContainsFocus';
6
7
  export * from './useContents';
7
8
  export * from './useDatalayer';
@@ -6,6 +6,7 @@ export * from './useAuthorization.js';
6
6
  export * from './useBackdrop.js';
7
7
  export * from './useBackdropJupyterLab.js';
8
8
  export * from './useCache.js';
9
+ export * from './libraryApp.js';
9
10
  export * from './useContainsFocus.js';
10
11
  export * from './useContents.js';
11
12
  export * from './useDatalayer.js';
@@ -0,0 +1,37 @@
1
+ /**
2
+ * What the Library says of a published application beyond any item's fields:
3
+ * its face, its kind and whether it runs live.
4
+ *
5
+ * Spacer keeps them beside the app's item, from its Appspec, and the Library
6
+ * projection carries them: `face_s` (the JSON of its `id`, `emoji`, `avatar`
7
+ * and `banner`, each only when set), `app_kind_s` and `runs_live_b` — an app
8
+ * that runs live can be tried before it is cloned: not a decision, and naming
9
+ * the agent it runs on.
10
+ *
11
+ * @module hooks/libraryApp
12
+ */
13
+ /** The kinds of application. */
14
+ export declare const LIBRARY_APP_KINDS: readonly ["decision", "chat", "widget", "worker"];
15
+ export type LibraryAppKind = (typeof LIBRARY_APP_KINDS)[number];
16
+ /** An application's face, as its Appspec says it: each only when set. */
17
+ export type LibraryAppFace = {
18
+ /** The Appspec's id: what seeds its banner, and the agent it runs as. */
19
+ id?: string;
20
+ emoji?: string;
21
+ /** The drawing chosen, by name, from the profile's set. */
22
+ avatar?: string;
23
+ /** The banner chosen, by name, from the profile's set. */
24
+ banner?: string;
25
+ };
26
+ export type LibraryAppFields = {
27
+ /** None when the Library answered without one. */
28
+ face?: LibraryAppFace;
29
+ /** None when the Library answered without one. */
30
+ appKind?: LibraryAppKind;
31
+ /** Whether it can be tried before it is cloned. */
32
+ runsLive: boolean;
33
+ };
34
+ /** The face `face_s` carries; a value that is not a face's JSON is refused. */
35
+ export declare function libraryAppFaceOf(value: unknown): LibraryAppFace | undefined;
36
+ /** The face, kind and liveness of an app as the Library answers it. */
37
+ export declare function libraryAppFieldsOf(raw: Record<string, unknown>): LibraryAppFields;
@@ -0,0 +1,59 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /**
6
+ * What the Library says of a published application beyond any item's fields:
7
+ * its face, its kind and whether it runs live.
8
+ *
9
+ * Spacer keeps them beside the app's item, from its Appspec, and the Library
10
+ * projection carries them: `face_s` (the JSON of its `id`, `emoji`, `avatar`
11
+ * and `banner`, each only when set), `app_kind_s` and `runs_live_b` — an app
12
+ * that runs live can be tried before it is cloned: not a decision, and naming
13
+ * the agent it runs on.
14
+ *
15
+ * @module hooks/libraryApp
16
+ */
17
+ /** The kinds of application. */
18
+ export const LIBRARY_APP_KINDS = [
19
+ 'decision',
20
+ 'chat',
21
+ 'widget',
22
+ 'worker',
23
+ ];
24
+ const FACE_KEYS = ['id', 'emoji', 'avatar', 'banner'];
25
+ /** The face `face_s` carries; a value that is not a face's JSON is refused. */
26
+ export function libraryAppFaceOf(value) {
27
+ if (value === undefined || value === null || value === '') {
28
+ return undefined;
29
+ }
30
+ if (typeof value !== 'string') {
31
+ throw new Error(`An app's face is not a string: ${String(value)}`);
32
+ }
33
+ const parsed = JSON.parse(value);
34
+ if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
35
+ throw new Error(`An app's face is not an object: ${value}`);
36
+ }
37
+ const face = {};
38
+ for (const key of FACE_KEYS) {
39
+ const field = parsed[key];
40
+ if (typeof field === 'string' && field) {
41
+ face[key] = field;
42
+ }
43
+ }
44
+ return face;
45
+ }
46
+ /** The face, kind and liveness of an app as the Library answers it. */
47
+ export function libraryAppFieldsOf(raw) {
48
+ const kind = raw.app_kind_s;
49
+ if (kind !== undefined &&
50
+ !LIBRARY_APP_KINDS.includes(kind)) {
51
+ throw new Error(`An app's kind is not one of ${LIBRARY_APP_KINDS}: ${String(kind)}`);
52
+ }
53
+ const face = libraryAppFaceOf(raw.face_s);
54
+ return {
55
+ ...(face ? { face } : {}),
56
+ ...(kind ? { appKind: kind } : {}),
57
+ runsLive: raw.runs_live_b === true,
58
+ };
59
+ }
@@ -39,6 +39,7 @@
39
39
  import { useQuery, useQueries, useMutation, useQueryClient, } from '@tanstack/react-query';
40
40
  import { BOOTSTRAP_USER_ONBOARDING, asContact, asInvite, asOrganization, asSecret, asTeam, asToken, asUser, } from '../models/index.js';
41
41
  import { asSpace } from './cacheConverters.js';
42
+ import { libraryAppFieldsOf } from './libraryApp.js';
42
43
  import { useCoreStore, useIAMStore, profileStore } from '../state/index.js';
43
44
  import { asDisplayName, namesAsInitials, asArray } from '../utils/index.js';
44
45
  import { useDatalayer } from './useDatalayer.js';
@@ -880,10 +881,13 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
880
881
  /**
881
882
  * A published agentic UI application: what it answers, and its definition
882
883
  * as the library hands it over — `model_s`, the string the Studio reads
883
- * the definition from, left unparsed because the Studio owns its shape.
884
+ * the definition from, left unparsed because the Studio owns its shape —
885
+ * and its face, its kind and whether it runs live (`libraryAppFieldsOf`),
886
+ * so its card draws it and the gallery opens one that runs live.
884
887
  */
885
888
  const toApp = (raw) => {
886
889
  return {
890
+ ...libraryAppFieldsOf(raw),
887
891
  id: raw.uid,
888
892
  type: 'app',
889
893
  name: raw.name_t,
@@ -1836,6 +1840,9 @@ export const useCache = ({ loginRoute = '/login' } = {}) => {
1836
1840
  if (settings.docsInPlace !== undefined) {
1837
1841
  body.docs_in_place_b = settings.docsInPlace;
1838
1842
  }
1843
+ if (settings.showAdvanced !== undefined) {
1844
+ body.show_advanced_b = settings.showAdvanced;
1845
+ }
1839
1846
  return requestDatalayer({
1840
1847
  url: `${configuration.iamUrl}/api/iam/v1/users/${userId}/settings`,
1841
1848
  method: 'PUT',
@@ -1,6 +1,7 @@
1
1
  export declare const AI_AGENTS_URL_KEY = "aiAgents_url_s";
2
2
  export declare const CAN_INVITE_URL_KEY = "can_invite_b";
3
3
  export declare const DOCS_IN_PLACE_KEY = "docs_in_place_b";
4
+ export declare const SHOW_ADVANCED_KEY = "show_advanced_b";
4
5
  export type IUserSettings = {
5
6
  aiAgentsUrl?: string;
6
7
  canInvite?: boolean;
@@ -13,11 +14,19 @@ export type IUserSettings = {
13
14
  * full-window documentation.
14
15
  */
15
16
  docsInPlace?: boolean;
17
+ /**
18
+ * Whether the Studio shows what a Maker does not need — *Show advanced*.
19
+ *
20
+ * Undefined means the user has never chosen: the Studio makes a first
21
+ * choice for them, and keeps it here.
22
+ */
23
+ showAdvanced?: boolean;
16
24
  };
17
25
  export declare class UserSettings implements IUserSettings {
18
26
  private _aiAgentsUrl?;
19
27
  private _canInvite?;
20
28
  private _docsInPlace?;
29
+ private _showAdvanced?;
21
30
  constructor(s: any);
22
31
  get aiAgentsUrl(): string | undefined;
23
32
  set aiAgentsUrl(value: string | undefined);
@@ -25,5 +34,7 @@ export declare class UserSettings implements IUserSettings {
25
34
  set canInvite(value: boolean | undefined);
26
35
  get docsInPlace(): boolean | undefined;
27
36
  set docsInPlace(value: boolean | undefined);
37
+ get showAdvanced(): boolean | undefined;
38
+ set showAdvanced(value: boolean | undefined);
28
39
  }
29
40
  export default UserSettings;
@@ -5,14 +5,17 @@
5
5
  export const AI_AGENTS_URL_KEY = 'aiAgents_url_s';
6
6
  export const CAN_INVITE_URL_KEY = 'can_invite_b';
7
7
  export const DOCS_IN_PLACE_KEY = 'docs_in_place_b';
8
+ export const SHOW_ADVANCED_KEY = 'show_advanced_b';
8
9
  export class UserSettings {
9
10
  _aiAgentsUrl;
10
11
  _canInvite;
11
12
  _docsInPlace;
13
+ _showAdvanced;
12
14
  constructor(s) {
13
15
  this._aiAgentsUrl = s[AI_AGENTS_URL_KEY] ?? undefined;
14
16
  this._canInvite = s[CAN_INVITE_URL_KEY] ?? undefined;
15
17
  this._docsInPlace = s[DOCS_IN_PLACE_KEY] ?? undefined;
18
+ this._showAdvanced = s[SHOW_ADVANCED_KEY] ?? undefined;
16
19
  }
17
20
  get aiAgentsUrl() {
18
21
  return this._aiAgentsUrl;
@@ -32,5 +35,11 @@ export class UserSettings {
32
35
  set docsInPlace(value) {
33
36
  this._docsInPlace = value;
34
37
  }
38
+ get showAdvanced() {
39
+ return this._showAdvanced;
40
+ }
41
+ set showAdvanced(value) {
42
+ this._showAdvanced = value;
43
+ }
35
44
  }
36
45
  export default UserSettings;
@@ -122,6 +122,12 @@ export interface SignInSimpleProps {
122
122
  * Sign-up URL opened when clicking the sign-up button.
123
123
  */
124
124
  signUpHref?: string;
125
+ /**
126
+ * Called on the sign-up button instead of opening `signUpHref`: a host
127
+ * with a router sends the reader to its own sign-up page without leaving
128
+ * the app.
129
+ */
130
+ onSignUp?: () => void;
125
131
  /**
126
132
  * Forgot-password URL for password form.
127
133
  */
@@ -101,7 +101,7 @@ const SignInInputGlobalStyle = createGlobalStyle `
101
101
  }
102
102
  `;
103
103
  // ── Component ────────────────────────────────────────────────────────
104
- export const SignInSimple = ({ onSignIn, onApiKeySignIn, loginUrl: loginUrlProp, name, title = 'Datalayer OTEL', description = 'Sign in to access the observability dashboard.', icon, leadingIcon = _jsx(TelescopeIcon, { size: 24 }), github = false, google = false, linkedin = false, apiKey = false, signUp = true, socialSignInNavigationTarget, asDoc = false, fillHeight = true, hideHero = false, calloutTitle, calloutDescription, passwordToggleLabel = 'Sign in with a password', signUpTitle = "Don't have an account?", signUpDescription = 'Create a free Datalayer account with your email address.', signUpLabel = 'Sign up with email', signUpHref = 'https://datalayer.ai/signup', forgotPasswordHref = '/password', forgotPasswordLabel = 'Forgot password?', showForgotPassword = true, socialButtonMarginTop = 3, actionButtonMaxWidth = 320, }) => {
104
+ export const SignInSimple = ({ onSignIn, onApiKeySignIn, loginUrl: loginUrlProp, name, title = 'Datalayer OTEL', description = 'Sign in to access the observability dashboard.', icon, leadingIcon = _jsx(TelescopeIcon, { size: 24 }), github = false, google = false, linkedin = false, apiKey = false, signUp = true, socialSignInNavigationTarget, asDoc = false, fillHeight = true, hideHero = false, calloutTitle, calloutDescription, passwordToggleLabel = 'Sign in with a password', signUpTitle = "Don't have an account?", signUpDescription = 'Create a free Datalayer account with your email address.', signUpLabel = 'Sign up with email', signUpHref = 'https://datalayer.ai/signup', onSignUp, forgotPasswordHref = '/password', forgotPasswordLabel = 'Forgot password?', showForgotPassword = true, socialButtonMarginTop = 3, actionButtonMaxWidth = 320, }) => {
105
105
  const compactDocMode = asDoc && !hideHero;
106
106
  const headingText = name ?? (asDoc && title === 'Datalayer OTEL' ? 'Datalayer Sign In' : title);
107
107
  const headingIcon = icon ?? (asDoc ? _jsx(SignInIcon, { size: 24 }) : leadingIcon);
@@ -208,8 +208,12 @@ export const SignInSimple = ({ onSignIn, onApiKeySignIn, loginUrl: loginUrlProp,
208
208
  closeApiKeyDialog();
209
209
  }, [apiKeyValue, onApiKeySignIn, closeApiKeyDialog]);
210
210
  const handleSignUp = useCallback(() => {
211
+ if (onSignUp) {
212
+ onSignUp();
213
+ return;
214
+ }
211
215
  window.location.assign(signUpHref);
212
- }, [signUpHref]);
216
+ }, [onSignUp, signUpHref]);
213
217
  const handleForgotPassword = useCallback(() => {
214
218
  if (!forgotPasswordHref) {
215
219
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datalayer/core",
3
- "version": "1.2.14",
3
+ "version": "1.2.17",
4
4
  "type": "module",
5
5
  "workspaces": [
6
6
  ".",