@marinoscar/platform-web 0.1.0-next.6 → 0.1.0-next.8
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/CHANGELOG.md +21 -0
- package/dist/ai/ui/index.d.ts +9 -0
- package/dist/ai/ui/index.d.ts.map +1 -1
- package/dist/ai/ui/index.js +7 -0
- package/dist/ai/ui/index.js.map +1 -1
- package/dist/ai/ui/user/AccountSignInProviderCard.d.ts +128 -0
- package/dist/ai/ui/user/AccountSignInProviderCard.d.ts.map +1 -0
- package/dist/ai/ui/user/AccountSignInProviderCard.js +87 -0
- package/dist/ai/ui/user/AccountSignInProviderCard.js.map +1 -0
- package/dist/ai/ui/user/DefaultAiModelPicker.d.ts +13 -0
- package/dist/ai/ui/user/DefaultAiModelPicker.d.ts.map +1 -1
- package/dist/ai/ui/user/DefaultAiModelPicker.js +5 -0
- package/dist/ai/ui/user/DefaultAiModelPicker.js.map +1 -1
- package/dist/ai/ui/user/KeylessProviderCard.d.ts +18 -1
- package/dist/ai/ui/user/KeylessProviderCard.d.ts.map +1 -1
- package/dist/ai/ui/user/KeylessProviderCard.js +10 -1
- package/dist/ai/ui/user/KeylessProviderCard.js.map +1 -1
- package/dist/ai/ui/user/UserAiKeyCard.d.ts +22 -0
- package/dist/ai/ui/user/UserAiKeyCard.d.ts.map +1 -1
- package/dist/ai/ui/user/UserAiKeyCard.js +5 -0
- package/dist/ai/ui/user/UserAiKeyCard.js.map +1 -1
- package/dist/ai/ui/user/aiErrorText.d.ts +10 -2
- package/dist/ai/ui/user/aiErrorText.d.ts.map +1 -1
- package/dist/ai/ui/user/aiErrorText.js +10 -2
- package/dist/ai/ui/user/aiErrorText.js.map +1 -1
- package/dist/identity/headless/index.d.ts +2 -0
- package/dist/identity/headless/index.d.ts.map +1 -1
- package/dist/identity/headless/index.js +1 -0
- package/dist/identity/headless/index.js.map +1 -1
- package/dist/identity/headless/local-identity.d.ts +63 -0
- package/dist/identity/headless/local-identity.d.ts.map +1 -0
- package/dist/identity/headless/local-identity.js +84 -0
- package/dist/identity/headless/local-identity.js.map +1 -0
- package/dist/identity/headless/types.d.ts +7 -0
- package/dist/identity/headless/types.d.ts.map +1 -1
- package/dist/identity/headless/use-permissions.d.ts +6 -1
- package/dist/identity/headless/use-permissions.d.ts.map +1 -1
- package/dist/identity/headless/use-permissions.js +24 -9
- package/dist/identity/headless/use-permissions.js.map +1 -1
- package/dist/identity/index.d.ts +1 -1
- package/dist/identity/index.d.ts.map +1 -1
- package/dist/identity/index.js +1 -1
- package/dist/identity/index.js.map +1 -1
- package/dist/shell/headless/index.d.ts +2 -0
- package/dist/shell/headless/index.d.ts.map +1 -1
- package/dist/shell/headless/index.js +1 -0
- package/dist/shell/headless/index.js.map +1 -1
- package/dist/shell/headless/preferences.d.ts +72 -0
- package/dist/shell/headless/preferences.d.ts.map +1 -0
- package/dist/shell/headless/preferences.js +83 -0
- package/dist/shell/headless/preferences.js.map +1 -0
- package/dist/shell/headless/rail-preference.d.ts.map +1 -1
- package/dist/shell/headless/rail-preference.js +44 -1
- package/dist/shell/headless/rail-preference.js.map +1 -1
- package/dist/shell/testing/index.d.ts +2 -0
- package/dist/shell/testing/index.d.ts.map +1 -0
- package/dist/shell/testing/index.js +6 -0
- package/dist/shell/testing/index.js.map +1 -0
- package/dist/shell/testing/shell-local-host.suite.d.ts +11 -0
- package/dist/shell/testing/shell-local-host.suite.d.ts.map +1 -0
- package/dist/shell/testing/shell-local-host.suite.js +152 -0
- package/dist/shell/testing/shell-local-host.suite.js.map +1 -0
- package/dist/shell/ui/ShellBottomNav.d.ts.map +1 -1
- package/dist/shell/ui/ShellBottomNav.js +14 -1
- package/dist/shell/ui/ShellBottomNav.js.map +1 -1
- package/dist/shell/ui/ShellUserMenu.d.ts +33 -1
- package/dist/shell/ui/ShellUserMenu.d.ts.map +1 -1
- package/dist/shell/ui/ShellUserMenu.js +12 -5
- package/dist/shell/ui/ShellUserMenu.js.map +1 -1
- package/dist/shell/ui/index.d.ts +1 -1
- package/dist/shell/ui/index.d.ts.map +1 -1
- package/package.json +6 -2
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export { AuthContext, AuthProvider, useAuth, useOptionalAuth } from './auth-context.js';
|
|
2
|
+
export { LocalIdentityProvider, createLocalAuthContextValue } from './local-identity.js';
|
|
3
|
+
export type { LocalIdentityInput, LocalIdentityProviderProps } from './local-identity.js';
|
|
2
4
|
export { useCurrentUserExtension, userExtension } from './user-extensions.js';
|
|
3
5
|
export type { AuthProviderProps } from './auth-context.js';
|
|
4
6
|
export type { AuthContextValue, AuthProviderInfo, AuthRole, AuthSessionClient, AuthUser, LoginOptions, OrgMembershipSummary, OrgSummary, } from './types.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/identity/headless/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACxF,OAAO,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAC9E,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3D,YAAY,EACV,gBAAgB,EAChB,gBAAgB,EAChB,QAAQ,EACR,iBAAiB,EACjB,QAAQ,EACR,YAAY,EACZ,oBAAoB,EACpB,UAAU,GACX,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,YAAY,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC9F,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAClG,OAAO,EACL,yBAAyB,EACzB,2BAA2B,EAC3B,oBAAoB,GACrB,MAAM,6BAA6B,CAAC;AACrC,YAAY,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACjG,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AACxD,YAAY,EACV,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,2BAA2B,EAC3B,WAAW,EACX,eAAe,EACf,SAAS,EACT,mBAAmB,EACnB,eAAe,EACf,SAAS,EACT,mBAAmB,EACnB,eAAe,EACf,OAAO,EACP,YAAY,EACZ,sBAAsB,EACtB,SAAS,EACT,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,SAAS,EACT,YAAY,EACZ,cAAc,EACd,aAAa,EACb,aAAa,GACd,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,2BAA2B,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AACpG,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAC/E,YAAY,EACV,0BAA0B,EAC1B,sBAAsB,EACtB,mBAAmB,EACnB,2BAA2B,EAC3B,sBAAsB,EACtB,mBAAmB,EACnB,gCAAgC,EAChC,2BAA2B,EAC3B,sBAAsB,EACtB,sBAAsB,GACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,YAAY,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AAChF,YAAY,EAAE,6BAA6B,EAAE,MAAM,uCAAuC,CAAC;AAC3F,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAC9F,YAAY,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACrH,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/identity/headless/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
// registry and the device-activation credential logic. Documented in
|
|
5
5
|
// ../README.md. Explicit named exports only.
|
|
6
6
|
export { AuthContext, AuthProvider, useAuth, useOptionalAuth } from './auth-context.js';
|
|
7
|
+
export { LocalIdentityProvider, createLocalAuthContextValue } from './local-identity.js';
|
|
7
8
|
export { useCurrentUserExtension, userExtension } from './user-extensions.js';
|
|
8
9
|
export { usePermissions } from './use-permissions.js';
|
|
9
10
|
export { RequireAuth, RequireMultiOrg, RequirePermission, useOrgsFeature } from './guards.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/identity/headless/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,2EAA2E;AAC3E,6EAA6E;AAC7E,qEAAqE;AACrE,6CAA6C;AAE7C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACxF,OAAO,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAY9E,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE9F,OAAO,EACL,yBAAyB,EACzB,2BAA2B,EAC3B,oBAAoB,GACrB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACjG,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AA+BxD,OAAO,EAAE,2BAA2B,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAcpG,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AAEhF,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAE9F,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,wBAAwB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/identity/headless/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,2EAA2E;AAC3E,6EAA6E;AAC7E,qEAAqE;AACrE,6CAA6C;AAE7C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACxF,OAAO,EAAE,qBAAqB,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAEzF,OAAO,EAAE,uBAAuB,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAY9E,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE9F,OAAO,EACL,yBAAyB,EACzB,2BAA2B,EAC3B,oBAAoB,GACrB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACjG,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AA+BxD,OAAO,EAAE,2BAA2B,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAcpG,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAExD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uCAAuC,CAAC;AAEhF,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAEhD,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAE9F,OAAO,EACL,uBAAuB,EACvB,sBAAsB,EACtB,sBAAsB,EACtB,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
2
|
+
import type { AuthContextValue } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* The one local user a {@link LocalIdentityProvider} presents.
|
|
5
|
+
*
|
|
6
|
+
* @stability experimental
|
|
7
|
+
*/
|
|
8
|
+
export interface LocalIdentityInput {
|
|
9
|
+
/** The local user's id. */
|
|
10
|
+
userId: string;
|
|
11
|
+
/**
|
|
12
|
+
* The name the user menu shows.
|
|
13
|
+
*
|
|
14
|
+
* @defaultValue `'You'`
|
|
15
|
+
*/
|
|
16
|
+
displayName?: string;
|
|
17
|
+
/** The email, or `null`/absent for none (shown as an empty string). */
|
|
18
|
+
email?: string | null;
|
|
19
|
+
/** The permissions the local user holds (the exact strings a destination or card names). */
|
|
20
|
+
permissions: readonly string[];
|
|
21
|
+
/** The role names the local user holds. */
|
|
22
|
+
roles?: readonly string[];
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Builds the {@link AuthContextValue} of a local, always-signed-in user:
|
|
26
|
+
* `isAuthenticated` is `true`, there are no sign-in providers, `mode` is
|
|
27
|
+
* `'local'`, and `login`, `logout`, `refreshUser`, `switchOrg` and
|
|
28
|
+
* `setAccessToken` do nothing.
|
|
29
|
+
*
|
|
30
|
+
* @param input - see {@link LocalIdentityInput}.
|
|
31
|
+
* @returns the context value; give it a stable identity (memoize) when passing it to `AuthContext.Provider`.
|
|
32
|
+
*
|
|
33
|
+
* @stability experimental
|
|
34
|
+
*/
|
|
35
|
+
export declare function createLocalAuthContextValue(input: LocalIdentityInput): AuthContextValue;
|
|
36
|
+
/**
|
|
37
|
+
* Props of {@link LocalIdentityProvider}: a {@link LocalIdentityInput} and the tree.
|
|
38
|
+
*
|
|
39
|
+
* @stability experimental
|
|
40
|
+
*/
|
|
41
|
+
export type LocalIdentityProviderProps = LocalIdentityInput & {
|
|
42
|
+
/** The tree. */
|
|
43
|
+
children: ReactNode;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Provides a local, always-signed-in user as the auth context. For a host with
|
|
47
|
+
* no API session; mount it where an `AuthProvider` would go.
|
|
48
|
+
*
|
|
49
|
+
* @param props - see {@link LocalIdentityProviderProps}.
|
|
50
|
+
* @returns the provider element.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```tsx
|
|
54
|
+
* <LocalIdentityProvider userId="local" permissions={['notes:read', 'notes:write']}>
|
|
55
|
+
* <ShellLayout navigation={navigation} />
|
|
56
|
+
* </LocalIdentityProvider>
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @extensionPoint component
|
|
60
|
+
* @stability experimental
|
|
61
|
+
*/
|
|
62
|
+
export declare function LocalIdentityProvider({ children, userId, displayName, email, permissions, roles, }: LocalIdentityProviderProps): ReactElement;
|
|
63
|
+
//# sourceMappingURL=local-identity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-identity.d.ts","sourceRoot":"","sources":["../../../src/identity/headless/local-identity.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGrD,OAAO,KAAK,EAAE,gBAAgB,EAAY,MAAM,YAAY,CAAC;AAE7D;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,4FAA4F;IAC5F,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,2CAA2C;IAC3C,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B;AAKD;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,kBAAkB,GAAG,gBAAgB,CA0BvF;AAED;;;;GAIG;AACH,MAAM,MAAM,0BAA0B,GAAG,kBAAkB,GAAG;IAC5D,gBAAgB;IAChB,QAAQ,EAAE,SAAS,CAAC;CACrB,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,QAAQ,EACR,MAAM,EACN,WAAW,EACX,KAAK,EACL,WAAW,EACX,KAAK,GACN,EAAE,0BAA0B,GAAG,YAAY,CAgB3C"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// =============================================================================
|
|
3
|
+
// Local identity (a host with no API session, e.g. a desktop shell)
|
|
4
|
+
// =============================================================================
|
|
5
|
+
//
|
|
6
|
+
// A local host has one user, known at start-up, with a fixed permission set.
|
|
7
|
+
// `LocalIdentityProvider` provides an `AuthContext` value for it
|
|
8
|
+
// (`mode: 'local'`) so the shell's chrome (`usePermissions`, the user menu) works
|
|
9
|
+
// unchanged. Nothing here calls the network; every session verb is a no-op.
|
|
10
|
+
// =============================================================================
|
|
11
|
+
import { useMemo } from 'react';
|
|
12
|
+
import { AuthContext } from './auth-context.js';
|
|
13
|
+
const noop = () => undefined;
|
|
14
|
+
const resolved = () => Promise.resolve();
|
|
15
|
+
/**
|
|
16
|
+
* Builds the {@link AuthContextValue} of a local, always-signed-in user:
|
|
17
|
+
* `isAuthenticated` is `true`, there are no sign-in providers, `mode` is
|
|
18
|
+
* `'local'`, and `login`, `logout`, `refreshUser`, `switchOrg` and
|
|
19
|
+
* `setAccessToken` do nothing.
|
|
20
|
+
*
|
|
21
|
+
* @param input - see {@link LocalIdentityInput}.
|
|
22
|
+
* @returns the context value; give it a stable identity (memoize) when passing it to `AuthContext.Provider`.
|
|
23
|
+
*
|
|
24
|
+
* @stability experimental
|
|
25
|
+
*/
|
|
26
|
+
export function createLocalAuthContextValue(input) {
|
|
27
|
+
const user = {
|
|
28
|
+
id: input.userId,
|
|
29
|
+
email: input.email ?? '',
|
|
30
|
+
displayName: input.displayName ?? 'You',
|
|
31
|
+
profileImageUrl: null,
|
|
32
|
+
roles: (input.roles ?? []).map((name) => ({ name })),
|
|
33
|
+
permissions: [...input.permissions],
|
|
34
|
+
isActive: true,
|
|
35
|
+
createdAt: new Date(0).toISOString(),
|
|
36
|
+
};
|
|
37
|
+
return {
|
|
38
|
+
user,
|
|
39
|
+
isLoading: false,
|
|
40
|
+
isAuthenticated: true,
|
|
41
|
+
providers: [],
|
|
42
|
+
sessionExpired: false,
|
|
43
|
+
login: noop,
|
|
44
|
+
logout: resolved,
|
|
45
|
+
refreshUser: resolved,
|
|
46
|
+
setAccessToken: noop,
|
|
47
|
+
activeOrg: null,
|
|
48
|
+
memberships: [],
|
|
49
|
+
switchOrg: resolved,
|
|
50
|
+
mode: 'local',
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Provides a local, always-signed-in user as the auth context. For a host with
|
|
55
|
+
* no API session; mount it where an `AuthProvider` would go.
|
|
56
|
+
*
|
|
57
|
+
* @param props - see {@link LocalIdentityProviderProps}.
|
|
58
|
+
* @returns the provider element.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```tsx
|
|
62
|
+
* <LocalIdentityProvider userId="local" permissions={['notes:read', 'notes:write']}>
|
|
63
|
+
* <ShellLayout navigation={navigation} />
|
|
64
|
+
* </LocalIdentityProvider>
|
|
65
|
+
* ```
|
|
66
|
+
*
|
|
67
|
+
* @extensionPoint component
|
|
68
|
+
* @stability experimental
|
|
69
|
+
*/
|
|
70
|
+
export function LocalIdentityProvider({ children, userId, displayName, email, permissions, roles, }) {
|
|
71
|
+
const permissionKey = permissions.join('\u0000');
|
|
72
|
+
const roleKey = (roles ?? []).join('\u0000');
|
|
73
|
+
const value = useMemo(() => createLocalAuthContextValue({
|
|
74
|
+
userId,
|
|
75
|
+
...(displayName === undefined ? {} : { displayName }),
|
|
76
|
+
...(email === undefined ? {} : { email }),
|
|
77
|
+
permissions,
|
|
78
|
+
...(roles === undefined ? {} : { roles }),
|
|
79
|
+
}),
|
|
80
|
+
// The arrays are compared by content so an inline literal does not rebuild the value every render.
|
|
81
|
+
[userId, displayName, email, permissionKey, roleKey]);
|
|
82
|
+
return _jsx(AuthContext.Provider, { value: value, children: children });
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=local-identity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-identity.js","sourceRoot":"","sources":["../../../src/identity/headless/local-identity.tsx"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,oEAAoE;AACpE,gFAAgF;AAChF,EAAE;AACF,6EAA6E;AAC7E,iEAAiE;AACjE,kFAAkF;AAClF,4EAA4E;AAC5E,gFAAgF;AAEhF,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAGhC,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAyBhD,MAAM,IAAI,GAAG,GAAS,EAAE,CAAC,SAAS,CAAC;AACnC,MAAM,QAAQ,GAAG,GAAkB,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;AAExD;;;;;;;;;;GAUG;AACH,MAAM,UAAU,2BAA2B,CAAC,KAAyB;IACnE,MAAM,IAAI,GAAa;QACrB,EAAE,EAAE,KAAK,CAAC,MAAM;QAChB,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE;QACxB,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,KAAK;QACvC,eAAe,EAAE,IAAI;QACrB,KAAK,EAAE,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,WAAW,EAAE,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC;QACnC,QAAQ,EAAE,IAAI;QACd,SAAS,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;KACrC,CAAC;IACF,OAAO;QACL,IAAI;QACJ,SAAS,EAAE,KAAK;QAChB,eAAe,EAAE,IAAI;QACrB,SAAS,EAAE,EAAE;QACb,cAAc,EAAE,KAAK;QACrB,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,QAAQ;QAChB,WAAW,EAAE,QAAQ;QACrB,cAAc,EAAE,IAAI;QACpB,SAAS,EAAE,IAAI;QACf,WAAW,EAAE,EAAE;QACf,SAAS,EAAE,QAAQ;QACnB,IAAI,EAAE,OAAO;KACd,CAAC;AACJ,CAAC;AAYD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,qBAAqB,CAAC,EACpC,QAAQ,EACR,MAAM,EACN,WAAW,EACX,KAAK,EACL,WAAW,EACX,KAAK,GACsB;IAC3B,MAAM,aAAa,GAAG,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACjD,MAAM,OAAO,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,OAAO,CACnB,GAAG,EAAE,CACH,2BAA2B,CAAC;QAC1B,MAAM;QACN,GAAG,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;QACrD,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;QACzC,WAAW;QACX,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;KAC1C,CAAC;IACJ,mGAAmG;IACnG,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,aAAa,EAAE,OAAO,CAAC,CACrD,CAAC;IACF,OAAO,KAAC,WAAW,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAAwB,CAAC;AAC/E,CAAC"}
|
|
@@ -161,6 +161,13 @@ export interface AuthContextValue {
|
|
|
161
161
|
* Rejects when the API refuses; the current session is then unchanged.
|
|
162
162
|
*/
|
|
163
163
|
switchOrg: (orgId: string) => Promise<void>;
|
|
164
|
+
/**
|
|
165
|
+
* Where the identity comes from. Absent or `'server'`: an {@link AuthProvider}
|
|
166
|
+
* session against the API. `'local'`: a {@link LocalIdentityProvider}, a
|
|
167
|
+
* single local user with no API (a desktop host); the shell hides sign-out and
|
|
168
|
+
* the organization switcher by default and nothing here reaches the network.
|
|
169
|
+
*/
|
|
170
|
+
mode?: 'server' | 'local';
|
|
164
171
|
}
|
|
165
172
|
/**
|
|
166
173
|
* What {@link AuthProvider} drives sessions through: the access-token holder
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/identity/headless/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/identity/headless/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -26,8 +26,13 @@ export interface UsePermissionsReturn {
|
|
|
26
26
|
/**
|
|
27
27
|
* The signed-in user's permissions and roles, as predicates.
|
|
28
28
|
*
|
|
29
|
+
* The source, in order: the {@link AuthContext} (an `AuthProvider`, or the
|
|
30
|
+
* `LocalIdentityProvider` of a local host); else the `PlatformHostProvider`'s
|
|
31
|
+
* viewer (`hasPermission` only: the viewer port cannot list permissions or
|
|
32
|
+
* roles, so `permissions` and `roles` are empty and `isAdmin` is `false`).
|
|
33
|
+
*
|
|
29
34
|
* @returns see {@link UsePermissionsReturn}.
|
|
30
|
-
* @throws Error
|
|
35
|
+
* @throws Error when neither an `AuthProvider`/`LocalIdentityProvider` nor a `PlatformHostProvider` is mounted.
|
|
31
36
|
*
|
|
32
37
|
* @example
|
|
33
38
|
* ```tsx
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-permissions.d.ts","sourceRoot":"","sources":["../../../src/identity/headless/use-permissions.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-permissions.d.ts","sourceRoot":"","sources":["../../../src/identity/headless/use-permissions.ts"],"names":[],"mappings":"AASA;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,uDAAuD;IACvD,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,+CAA+C;IAC/C,KAAK,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACnB,+EAA+E;IAC/E,aAAa,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC;IAC/C,sDAAsD;IACtD,gBAAgB,EAAE,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC;IAClD,mDAAmD;IACnD,iBAAiB,EAAE,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC;IACnD,4CAA4C;IAC5C,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACnC,uDAAuD;IACvD,UAAU,EAAE,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC;IAC/C,6CAA6C;IAC7C,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,IAAI,oBAAoB,CAyErD"}
|
|
@@ -2,12 +2,18 @@
|
|
|
2
2
|
// reference app's `hooks/usePermissions.ts`. These only decide what the UI
|
|
3
3
|
// shows; the API enforces every permission.
|
|
4
4
|
import { useCallback, useMemo } from 'react';
|
|
5
|
-
import {
|
|
5
|
+
import { useOptionalPlatformHost } from '../../core/index.js';
|
|
6
|
+
import { useOptionalAuth } from './auth-context.js';
|
|
6
7
|
/**
|
|
7
8
|
* The signed-in user's permissions and roles, as predicates.
|
|
8
9
|
*
|
|
10
|
+
* The source, in order: the {@link AuthContext} (an `AuthProvider`, or the
|
|
11
|
+
* `LocalIdentityProvider` of a local host); else the `PlatformHostProvider`'s
|
|
12
|
+
* viewer (`hasPermission` only: the viewer port cannot list permissions or
|
|
13
|
+
* roles, so `permissions` and `roles` are empty and `isAdmin` is `false`).
|
|
14
|
+
*
|
|
9
15
|
* @returns see {@link UsePermissionsReturn}.
|
|
10
|
-
* @throws Error
|
|
16
|
+
* @throws Error when neither an `AuthProvider`/`LocalIdentityProvider` nor a `PlatformHostProvider` is mounted.
|
|
11
17
|
*
|
|
12
18
|
* @example
|
|
13
19
|
* ```tsx
|
|
@@ -19,22 +25,26 @@ import { useAuth } from './auth-context.js';
|
|
|
19
25
|
* @stability stable
|
|
20
26
|
*/
|
|
21
27
|
export function usePermissions() {
|
|
22
|
-
const
|
|
28
|
+
const auth = useOptionalAuth();
|
|
29
|
+
const viewer = useOptionalPlatformHost()?.viewer ?? null;
|
|
30
|
+
const user = auth?.user;
|
|
23
31
|
const permissions = useMemo(() => {
|
|
24
32
|
return new Set(user?.permissions || []);
|
|
25
33
|
}, [user?.permissions]);
|
|
26
34
|
const roles = useMemo(() => {
|
|
27
35
|
return new Set(user?.roles?.map((r) => r.name) || []);
|
|
28
36
|
}, [user?.roles]);
|
|
37
|
+
// The viewer port answers one permission at a time; used only without an AuthContext.
|
|
38
|
+
const viewerCheck = auth === null ? viewer : null;
|
|
29
39
|
const hasPermission = useCallback((permission) => {
|
|
30
|
-
return permissions.has(permission);
|
|
31
|
-
}, [permissions]);
|
|
40
|
+
return viewerCheck ? viewerCheck.hasPermission(permission) : permissions.has(permission);
|
|
41
|
+
}, [permissions, viewerCheck]);
|
|
32
42
|
const hasAnyPermission = useCallback((...perms) => {
|
|
33
|
-
return perms.some((p) =>
|
|
34
|
-
}, [
|
|
43
|
+
return perms.some((p) => hasPermission(p));
|
|
44
|
+
}, [hasPermission]);
|
|
35
45
|
const hasAllPermissions = useCallback((...perms) => {
|
|
36
|
-
return perms.every((p) =>
|
|
37
|
-
}, [
|
|
46
|
+
return perms.every((p) => hasPermission(p));
|
|
47
|
+
}, [hasPermission]);
|
|
38
48
|
const hasRole = useCallback((role) => {
|
|
39
49
|
return roles.has(role);
|
|
40
50
|
}, [roles]);
|
|
@@ -44,6 +54,11 @@ export function usePermissions() {
|
|
|
44
54
|
const isAdmin = useMemo(() => {
|
|
45
55
|
return roles.has('admin');
|
|
46
56
|
}, [roles]);
|
|
57
|
+
if (auth === null && viewer === null) {
|
|
58
|
+
throw new Error('usePermissions: no permission source. Mount an AuthProvider (or a LocalIdentityProvider for a local host) ' +
|
|
59
|
+
"from '@marinoscar/platform-web/identity/headless', or a PlatformHostProvider from '@marinoscar/platform-web/core' " +
|
|
60
|
+
'(its viewer answers hasPermission).');
|
|
61
|
+
}
|
|
47
62
|
return {
|
|
48
63
|
permissions,
|
|
49
64
|
roles,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-permissions.js","sourceRoot":"","sources":["../../../src/identity/headless/use-permissions.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,2EAA2E;AAC3E,4CAA4C;AAE5C,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAE7C,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"use-permissions.js","sourceRoot":"","sources":["../../../src/identity/headless/use-permissions.ts"],"names":[],"mappings":"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"}
|
package/dist/identity/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { useAuth, usePermissions } from './headless/index.js';
|
|
1
|
+
export { useAuth, usePermissions, LocalIdentityProvider } from './headless/index.js';
|
|
2
2
|
export type { IdentityDataTableProps, IdentityTableColumn, IdentityTableFilter, IdentityTableRowAction, } from './headless/index.js';
|
|
3
3
|
export { IdentityTable } from './ui/table.js';
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/identity/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/identity/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACrF,YAAY,EACV,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,GACvB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
|
package/dist/identity/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// dependency (notifications -> identity). Not a package subpath: apps import
|
|
5
5
|
// `@marinoscar/platform-web/identity/headless` and `/identity/ui`. Narrow on
|
|
6
6
|
// purpose: only what a sibling uses.
|
|
7
|
-
export { useAuth, usePermissions } from './headless/index.js';
|
|
7
|
+
export { useAuth, usePermissions, LocalIdentityProvider } from './headless/index.js';
|
|
8
8
|
// The table seam: the app's DataTable from the identity adapters, else the
|
|
9
9
|
// plain MUI fallback.
|
|
10
10
|
export { IdentityTable } from './ui/table.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/identity/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,0EAA0E;AAC1E,4EAA4E;AAC5E,6EAA6E;AAC7E,6EAA6E;AAC7E,qCAAqC;AAErC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/identity/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,0EAA0E;AAC1E,4EAA4E;AAC5E,6EAA6E;AAC7E,6EAA6E;AAC7E,qCAAqC;AAErC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAOrF,2EAA2E;AAC3E,sBAAsB;AACtB,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { groupDestinationRuns, isDestinationVisible, isExternalUrl, owns, resolveActiveDestination, shellDestinationRoutes, } from './navigation.js';
|
|
2
2
|
export type { ShellConsole, ShellConsoleBack, ShellDestination, ShellDestinationRun, ShellIcon, ShellIconProps, ShellNavigation, ShellRailPreference, ShellSettingsSurface, } from './navigation.js';
|
|
3
|
+
export { ShellPreferencesProvider, createLocalStorageShellPreferencesPort, useOptionalShellPreferencesPort, } from './preferences.js';
|
|
4
|
+
export type { ShellPreferences, ShellPreferencesPort, ShellPreferencesProviderProps } from './preferences.js';
|
|
3
5
|
export { useShellRailPreference } from './rail-preference.js';
|
|
4
6
|
export type { ShellRailPreferenceOptions, UseShellRailPreferenceResult } from './rail-preference.js';
|
|
5
7
|
export { BUILTIN_SHELL_THEME_MODES, createShellTheme, isBuiltinThemeMode, listThemeModes, registerThemeMode, shellComponentOverrides, shellPalette, useOptionalShellTheme, useShellTheme, } from './theme.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shell/headless/index.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,IAAI,EACJ,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,SAAS,EACT,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,YAAY,EAAE,0BAA0B,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AACrG,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,uBAAuB,EACvB,YAAY,EACZ,qBAAqB,EACrB,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,sBAAsB,EACtB,cAAc,EACd,wBAAwB,EACxB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/shell/headless/index.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,IAAI,EACJ,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,SAAS,EACT,cAAc,EACd,eAAe,EACf,mBAAmB,EACnB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,wBAAwB,EACxB,sCAAsC,EACtC,+BAA+B,GAChC,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AAC9G,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,YAAY,EAAE,0BAA0B,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AACrG,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,uBAAuB,EACvB,YAAY,EACZ,qBAAqB,EACrB,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,YAAY,EACV,sBAAsB,EACtB,cAAc,EACd,wBAAwB,EACxB,oBAAoB,EACpB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,YAAY,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// theme and providers composition, with no component (issue #868). Documented
|
|
3
3
|
// in ../README.md.
|
|
4
4
|
export { groupDestinationRuns, isDestinationVisible, isExternalUrl, owns, resolveActiveDestination, shellDestinationRoutes, } from './navigation.js';
|
|
5
|
+
export { ShellPreferencesProvider, createLocalStorageShellPreferencesPort, useOptionalShellPreferencesPort, } from './preferences.js';
|
|
5
6
|
export { useShellRailPreference } from './rail-preference.js';
|
|
6
7
|
export { BUILTIN_SHELL_THEME_MODES, createShellTheme, isBuiltinThemeMode, listThemeModes, registerThemeMode, shellComponentOverrides, shellPalette, useOptionalShellTheme, useShellTheme, } from './theme.js';
|
|
7
8
|
export { ShellProviders } from './providers.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/shell/headless/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,8EAA8E;AAC9E,mBAAmB;AAEnB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,IAAI,EACJ,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AAYzB,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,uBAAuB,EACvB,YAAY,EACZ,qBAAqB,EACrB,aAAa,GACd,MAAM,YAAY,CAAC;AAQpB,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/shell/headless/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,8EAA8E;AAC9E,mBAAmB;AAEnB,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,aAAa,EACb,IAAI,EACJ,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,iBAAiB,CAAC;AAYzB,OAAO,EACL,wBAAwB,EACxB,sCAAsC,EACtC,+BAA+B,GAChC,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,uBAAuB,EACvB,YAAY,EACZ,qBAAqB,EACrB,aAAa,GACd,MAAM,YAAY,CAAC;AAQpB,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* The preferences the shell stores per viewer. Absent means the default.
|
|
4
|
+
*
|
|
5
|
+
* @stability experimental
|
|
6
|
+
*/
|
|
7
|
+
export interface ShellPreferences {
|
|
8
|
+
/** The desktop rail is collapsed. Absent: expanded. */
|
|
9
|
+
railCollapsed?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Where a host keeps {@link ShellPreferences}.
|
|
13
|
+
*
|
|
14
|
+
* @extensionPoint option
|
|
15
|
+
* @stability experimental
|
|
16
|
+
*/
|
|
17
|
+
export interface ShellPreferencesPort {
|
|
18
|
+
/** Reads the stored preferences (an empty object when none). */
|
|
19
|
+
read(): ShellPreferences | Promise<ShellPreferences>;
|
|
20
|
+
/** Stores the fields of `patch`; fields it omits are left as they are. */
|
|
21
|
+
write(patch: Partial<ShellPreferences>): void | Promise<void>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Props of {@link ShellPreferencesProvider}.
|
|
25
|
+
*
|
|
26
|
+
* @stability experimental
|
|
27
|
+
*/
|
|
28
|
+
export interface ShellPreferencesProviderProps {
|
|
29
|
+
/** The port; keep its identity stable. */
|
|
30
|
+
port: ShellPreferencesPort;
|
|
31
|
+
/** The tree. */
|
|
32
|
+
children: ReactNode;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Stores the shell's preferences through `port` instead of `/user-settings`.
|
|
36
|
+
* Mount it for the whole life of the shell: `useShellRailPreference` picks its
|
|
37
|
+
* source from whether a provider is mounted.
|
|
38
|
+
*
|
|
39
|
+
* @param props - see {@link ShellPreferencesProviderProps}.
|
|
40
|
+
* @returns the provider element.
|
|
41
|
+
*
|
|
42
|
+
* @extensionPoint component
|
|
43
|
+
* @stability experimental
|
|
44
|
+
*/
|
|
45
|
+
export declare function ShellPreferencesProvider({ port, children }: ShellPreferencesProviderProps): ReactElement;
|
|
46
|
+
/**
|
|
47
|
+
* The preferences port in context, or `null` when no
|
|
48
|
+
* {@link ShellPreferencesProvider} is mounted.
|
|
49
|
+
*
|
|
50
|
+
* @returns the port, or `null`.
|
|
51
|
+
*
|
|
52
|
+
* @stability experimental
|
|
53
|
+
*/
|
|
54
|
+
export declare function useOptionalShellPreferencesPort(): ShellPreferencesPort | null;
|
|
55
|
+
/**
|
|
56
|
+
* A port over `window.localStorage`: one JSON object under `key`. Every storage
|
|
57
|
+
* access is guarded, so a blocked or full store reads as "no preferences" and
|
|
58
|
+
* a failed write is dropped; the shell then keeps the choice for the session.
|
|
59
|
+
*
|
|
60
|
+
* @param key - the storage key. Default `'shell-preferences'`.
|
|
61
|
+
* @returns the port.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```tsx
|
|
65
|
+
* const port = createLocalStorageShellPreferencesPort('myapp.shell');
|
|
66
|
+
* <ShellPreferencesProvider port={port}>...</ShellPreferencesProvider>
|
|
67
|
+
* ```
|
|
68
|
+
*
|
|
69
|
+
* @stability experimental
|
|
70
|
+
*/
|
|
71
|
+
export declare function createLocalStorageShellPreferencesPort(key?: string): ShellPreferencesPort;
|
|
72
|
+
//# sourceMappingURL=preferences.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preferences.d.ts","sourceRoot":"","sources":["../../../src/shell/headless/preferences.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAErD;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,uDAAuD;IACvD,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,gEAAgE;IAChE,IAAI,IAAI,gBAAgB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACrD,0EAA0E;IAC1E,KAAK,CAAC,KAAK,EAAE,OAAO,CAAC,gBAAgB,CAAC,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/D;AAKD;;;;GAIG;AACH,MAAM,WAAW,6BAA6B;IAC5C,0CAA0C;IAC1C,IAAI,EAAE,oBAAoB,CAAC;IAC3B,gBAAgB;IAChB,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,6BAA6B,GAAG,YAAY,CAExG;AAED;;;;;;;GAOG;AACH,wBAAgB,+BAA+B,IAAI,oBAAoB,GAAG,IAAI,CAE7E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,sCAAsC,CAAC,GAAG,SAAsB,GAAG,oBAAoB,CAuBtG"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// =============================================================================
|
|
3
|
+
// The shell preferences port (a host with no `/user-settings`)
|
|
4
|
+
// =============================================================================
|
|
5
|
+
//
|
|
6
|
+
// The rail's collapse preference lives in the viewer's `navigation`
|
|
7
|
+
// user-settings namespace by default (`useShellRailPreference`). A host with no
|
|
8
|
+
// API (a desktop shell) mounts `ShellPreferencesProvider` with a port that reads
|
|
9
|
+
// and writes the same values locally, and the rail then never touches the API.
|
|
10
|
+
// =============================================================================
|
|
11
|
+
import { createContext, useContext } from 'react';
|
|
12
|
+
const ShellPreferencesContext = createContext(null);
|
|
13
|
+
ShellPreferencesContext.displayName = 'ShellPreferencesContext';
|
|
14
|
+
/**
|
|
15
|
+
* Stores the shell's preferences through `port` instead of `/user-settings`.
|
|
16
|
+
* Mount it for the whole life of the shell: `useShellRailPreference` picks its
|
|
17
|
+
* source from whether a provider is mounted.
|
|
18
|
+
*
|
|
19
|
+
* @param props - see {@link ShellPreferencesProviderProps}.
|
|
20
|
+
* @returns the provider element.
|
|
21
|
+
*
|
|
22
|
+
* @extensionPoint component
|
|
23
|
+
* @stability experimental
|
|
24
|
+
*/
|
|
25
|
+
export function ShellPreferencesProvider({ port, children }) {
|
|
26
|
+
return _jsx(ShellPreferencesContext.Provider, { value: port, children: children });
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The preferences port in context, or `null` when no
|
|
30
|
+
* {@link ShellPreferencesProvider} is mounted.
|
|
31
|
+
*
|
|
32
|
+
* @returns the port, or `null`.
|
|
33
|
+
*
|
|
34
|
+
* @stability experimental
|
|
35
|
+
*/
|
|
36
|
+
export function useOptionalShellPreferencesPort() {
|
|
37
|
+
return useContext(ShellPreferencesContext);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A port over `window.localStorage`: one JSON object under `key`. Every storage
|
|
41
|
+
* access is guarded, so a blocked or full store reads as "no preferences" and
|
|
42
|
+
* a failed write is dropped; the shell then keeps the choice for the session.
|
|
43
|
+
*
|
|
44
|
+
* @param key - the storage key. Default `'shell-preferences'`.
|
|
45
|
+
* @returns the port.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```tsx
|
|
49
|
+
* const port = createLocalStorageShellPreferencesPort('myapp.shell');
|
|
50
|
+
* <ShellPreferencesProvider port={port}>...</ShellPreferencesProvider>
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @stability experimental
|
|
54
|
+
*/
|
|
55
|
+
export function createLocalStorageShellPreferencesPort(key = 'shell-preferences') {
|
|
56
|
+
const readAll = () => {
|
|
57
|
+
try {
|
|
58
|
+
const raw = window.localStorage.getItem(key);
|
|
59
|
+
if (raw === null)
|
|
60
|
+
return {};
|
|
61
|
+
const parsed = JSON.parse(raw);
|
|
62
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))
|
|
63
|
+
return {};
|
|
64
|
+
const railCollapsed = parsed.railCollapsed;
|
|
65
|
+
return typeof railCollapsed === 'boolean' ? { railCollapsed } : {};
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return {};
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
return {
|
|
72
|
+
read: readAll,
|
|
73
|
+
write(patch) {
|
|
74
|
+
try {
|
|
75
|
+
window.localStorage.setItem(key, JSON.stringify({ ...readAll(), ...patch }));
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// Storage unavailable: the preference lasts for the session only.
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=preferences.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preferences.js","sourceRoot":"","sources":["../../../src/shell/headless/preferences.tsx"],"names":[],"mappings":";AAAA,gFAAgF;AAChF,+DAA+D;AAC/D,gFAAgF;AAChF,EAAE;AACF,oEAAoE;AACpE,gFAAgF;AAChF,iFAAiF;AACjF,+EAA+E;AAC/E,gFAAgF;AAEhF,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AA0BlD,MAAM,uBAAuB,GAAG,aAAa,CAA8B,IAAI,CAAC,CAAC;AACjF,uBAAuB,CAAC,WAAW,GAAG,yBAAyB,CAAC;AAchE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,wBAAwB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAiC;IACxF,OAAO,KAAC,uBAAuB,CAAC,QAAQ,IAAC,KAAK,EAAE,IAAI,YAAG,QAAQ,GAAoC,CAAC;AACtG,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,+BAA+B;IAC7C,OAAO,UAAU,CAAC,uBAAuB,CAAC,CAAC;AAC7C,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,sCAAsC,CAAC,GAAG,GAAG,mBAAmB;IAC9E,MAAM,OAAO,GAAG,GAAqB,EAAE;QACrC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC7C,IAAI,GAAG,KAAK,IAAI;gBAAE,OAAO,EAAE,CAAC;YAC5B,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACxC,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;gBAAE,OAAO,EAAE,CAAC;YACtF,MAAM,aAAa,GAAI,MAAsC,CAAC,aAAa,CAAC;YAC5E,OAAO,OAAO,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,CAAC;IACF,OAAO;QACL,IAAI,EAAE,OAAO;QACb,KAAK,CAAC,KAAK;YACT,IAAI,CAAC;gBACH,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,OAAO,EAAE,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC;YAC/E,CAAC;YAAC,MAAM,CAAC;gBACP,kEAAkE;YACpE,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rail-preference.d.ts","sourceRoot":"","sources":["../../../src/shell/headless/rail-preference.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAI7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"rail-preference.d.ts","sourceRoot":"","sources":["../../../src/shell/headless/rail-preference.ts"],"names":[],"mappings":"AAsBA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAI7D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAY3D;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IACzC,4EAA4E;IAC5E,GAAG,CAAC,EAAE,iBAAiB,CAAC;CACzB;AAED;;;;GAIG;AACH,MAAM,WAAW,4BAA6B,SAAQ,mBAAmB;IACvE,2FAA2F;IAC3F,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,GAAE,0BAA+B,GAAG,4BAA4B,CAK7G"}
|
|
@@ -17,9 +17,10 @@
|
|
|
17
17
|
// at which point the stored value either carries the new value (success) or
|
|
18
18
|
// the old one (failure): the revert is the same path as the commit.
|
|
19
19
|
// =============================================================================
|
|
20
|
-
import { useCallback, useMemo, useRef, useState } from 'react';
|
|
20
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
21
21
|
import { useUserSettings } from '../../settings/index.js';
|
|
22
22
|
import { useIsMounted } from '../internal/use-is-mounted.js';
|
|
23
|
+
import { useOptionalShellPreferencesPort } from './preferences.js';
|
|
23
24
|
/**
|
|
24
25
|
* The desktop rail's collapse preference, stored in the viewer's `navigation`
|
|
25
26
|
* user-settings namespace (`railCollapsed`). Optimistic toggle; a default is
|
|
@@ -33,6 +34,48 @@ import { useIsMounted } from '../internal/use-is-mounted.js';
|
|
|
33
34
|
* @stability experimental
|
|
34
35
|
*/
|
|
35
36
|
export function useShellRailPreference(options = {}) {
|
|
37
|
+
// The source is fixed for the life of the shell (a provider is mounted or it
|
|
38
|
+
// is not), so choosing between the two hooks here keeps the hook order stable.
|
|
39
|
+
const port = useOptionalShellPreferencesPort();
|
|
40
|
+
return port ? usePortRailPreference(port) : useServerRailPreference(options);
|
|
41
|
+
}
|
|
42
|
+
/** The preference over a host's {@link ShellPreferencesPort}; never touches the API. */
|
|
43
|
+
function usePortRailPreference(port) {
|
|
44
|
+
const [railCollapsed, setRailCollapsed] = useState(false);
|
|
45
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
46
|
+
// A write made before the first read resolves wins over the stale read.
|
|
47
|
+
const touched = useRef(false);
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
let cancelled = false;
|
|
50
|
+
void Promise.resolve()
|
|
51
|
+
.then(() => port.read())
|
|
52
|
+
.then((stored) => {
|
|
53
|
+
if (cancelled || touched.current)
|
|
54
|
+
return;
|
|
55
|
+
setRailCollapsed(stored.railCollapsed === true);
|
|
56
|
+
})
|
|
57
|
+
.catch(() => undefined)
|
|
58
|
+
.finally(() => {
|
|
59
|
+
if (!cancelled)
|
|
60
|
+
setIsLoading(false);
|
|
61
|
+
});
|
|
62
|
+
return () => {
|
|
63
|
+
cancelled = true;
|
|
64
|
+
};
|
|
65
|
+
}, [port]);
|
|
66
|
+
const toggleRailCollapsed = useCallback(() => {
|
|
67
|
+
touched.current = true;
|
|
68
|
+
const next = !railCollapsed;
|
|
69
|
+
setRailCollapsed(next);
|
|
70
|
+
void Promise.resolve()
|
|
71
|
+
.then(() => port.write({ railCollapsed: next }))
|
|
72
|
+
// The choice stays for this session when the port cannot keep it.
|
|
73
|
+
.catch(() => undefined);
|
|
74
|
+
}, [port, railCollapsed]);
|
|
75
|
+
return { railCollapsed, toggleRailCollapsed, isLoading };
|
|
76
|
+
}
|
|
77
|
+
/** The preference over `/user-settings` (the default). */
|
|
78
|
+
function useServerRailPreference(options) {
|
|
36
79
|
const { settings, isLoading, updateSettings } = useUserSettings({
|
|
37
80
|
syncTheme: false,
|
|
38
81
|
...(options.api === undefined ? {} : { api: options.api }),
|