@exegia/corpora-ui 0.20.0 → 0.22.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/dist-lib/components/blocks/auth/auth-flow-atom.d.ts +77 -0
- package/dist-lib/components/blocks/auth/auth-session-atom.d.ts +28 -0
- package/dist-lib/components/blocks/auth/auth-state-type.d.ts +71 -0
- package/dist-lib/components/blocks/auth/auth-state.d.ts +9 -0
- package/dist-lib/components/blocks/auth/use-auth-state.d.ts +52 -0
- package/dist-lib/components/blocks/layout.d.ts +4 -1
- package/dist-lib/components/blocks/nav/sidebar/__tests__/ai-sidebar-atom.test.d.ts +1 -0
- package/dist-lib/components/blocks/nav/sidebar/ai-sidebar-atom.d.ts +217 -0
- package/dist-lib/components/blocks/nav/sidebar/index.d.ts +3 -1
- package/dist-lib/components/blocks/nav/sidebar/sidebar-context.d.ts +3 -0
- package/dist-lib/components/blocks/nav/sidebar/sidebar-row.d.ts +3 -1
- package/dist-lib/components/blocks/nav/sidebar/type.d.ts +109 -29
- package/dist-lib/components/blocks/nav/sidebar/use-ai-sidebar-state.d.ts +29 -0
- package/dist-lib/components/blocks/nav/sidebar/use-ai-sidebar.d.ts +6 -1
- package/dist-lib/components/blocks/nav/sidebar/utils.d.ts +1 -1
- package/dist-lib/components/blocks/profile/index.d.ts +7 -0
- package/dist-lib/components/blocks/profile/profile-card-atom.d.ts +68 -0
- package/dist-lib/components/blocks/profile/profile-card-block.d.ts +28 -39
- package/dist-lib/components/blocks/profile/type.d.ts +80 -0
- package/dist-lib/components/blocks/profile/use-profile-card-state.d.ts +24 -0
- package/dist-lib/components/blocks/profile/use-profile-card.d.ts +34 -0
- package/dist-lib/components/blocks/shell/__tests__/shell-fit-atom.test.d.ts +1 -0
- package/dist-lib/components/blocks/shell/__tests__/shell-metrics.test.d.ts +1 -0
- package/dist-lib/components/blocks/shell/animated-panel-provider.d.ts +1 -1
- package/dist-lib/components/blocks/shell/animated-panel.d.ts +1 -1
- package/dist-lib/components/blocks/shell/index.d.ts +4 -12
- package/dist-lib/components/blocks/shell/shell-fit-atom.d.ts +68 -0
- package/dist-lib/components/blocks/shell/shell-metrics.d.ts +54 -0
- package/dist-lib/components/blocks/shell/type.d.ts +115 -3
- package/dist-lib/components/blocks/shell/use-shell-fit-state.d.ts +25 -0
- package/dist-lib/components/blocks/shell/use-shell-fit.d.ts +14 -0
- package/dist-lib/components/blocks/shell/use-shell-panels.d.ts +12 -1
- package/dist-lib/components/blocks/shell/utils.d.ts +32 -0
- package/dist-lib/components/composed/__tests__/logo.test.d.ts +1 -0
- package/dist-lib/components/composed/logo.d.ts +34 -0
- package/dist-lib/components/composed/tree/__tests__/tree-atom.test.d.ts +1 -0
- package/dist-lib/components/composed/tree/constants.d.ts +4 -4
- package/dist-lib/components/composed/tree/index.d.ts +3 -1
- package/dist-lib/components/composed/tree/tree-atom.d.ts +160 -0
- package/dist-lib/components/composed/tree/tree-node.d.ts +6 -1
- package/dist-lib/components/composed/tree/type.d.ts +116 -18
- package/dist-lib/components/composed/tree/use-tree-dnd.d.ts +18 -7
- package/dist-lib/components/composed/tree/use-tree-state.d.ts +25 -0
- package/dist-lib/components/composed/tree/use-tree.d.ts +4 -0
- package/dist-lib/components/composed/user-avatar.d.ts +5 -28
- package/dist-lib/components/user-avatar/__tests__/user-avatar.test.d.ts +1 -0
- package/dist-lib/components/user-avatar/component.d.ts +1 -8
- package/dist-lib/components/user-avatar/index.d.ts +5 -0
- package/dist-lib/components/user-avatar/presence-badge.d.ts +16 -0
- package/dist-lib/components/user-avatar/type.d.ts +53 -0
- package/dist-lib/components/user-avatar/use-user-avatar-state.d.ts +26 -0
- package/dist-lib/components/user-avatar/use-user-avatar.d.ts +37 -0
- package/dist-lib/components/user-avatar/user-avatar-atom.d.ts +64 -0
- package/dist-lib/components/user-avatar/utils.d.ts +22 -0
- package/dist-lib/index.d.ts +6 -3
- package/dist-lib/index.js +3732 -2670
- package/dist-lib/index.js.map +1 -1
- package/dist-lib/state/exegia-provider.d.ts +51 -0
- package/dist-lib/state/index.d.ts +4 -0
- package/dist-lib/state/store.d.ts +17 -0
- package/package.json +15 -12
- package/src/components/blocks/auth/__tests__/auth-state-atom.test.tsx +247 -0
- package/src/components/blocks/auth/auth-flow-atom.ts +238 -0
- package/src/components/blocks/auth/auth-session-atom.ts +82 -0
- package/src/components/blocks/auth/auth-state-type.ts +97 -0
- package/src/components/blocks/auth/auth-state.ts +52 -0
- package/src/components/blocks/auth/use-auth-state.ts +127 -0
- package/src/components/blocks/layout.ts +30 -2
- package/src/components/blocks/nav/sidebar/__tests__/ai-sidebar-atom.test.tsx +325 -0
- package/src/components/blocks/nav/sidebar/ai-sidebar-atom.ts +698 -0
- package/src/components/blocks/nav/sidebar/ai-sidebar.tsx +48 -42
- package/src/components/blocks/nav/sidebar/index.ts +53 -1
- package/src/components/blocks/nav/sidebar/sidebar-context.ts +15 -0
- package/src/components/blocks/nav/sidebar/sidebar-row.tsx +119 -50
- package/src/components/blocks/nav/sidebar/type.ts +125 -30
- package/src/components/blocks/nav/sidebar/use-ai-sidebar-state.ts +123 -0
- package/src/components/blocks/nav/sidebar/use-ai-sidebar.ts +301 -248
- package/src/components/blocks/nav/sidebar/utils.ts +1 -1
- package/src/components/blocks/profile/__tests__/profile-card-block.test.tsx +194 -0
- package/src/components/blocks/profile/index.ts +28 -0
- package/src/components/blocks/profile/profile-card-atom.ts +247 -0
- package/src/components/blocks/profile/profile-card-block.tsx +153 -74
- package/src/components/blocks/profile/type.ts +95 -0
- package/src/components/blocks/profile/use-profile-card-state.ts +67 -0
- package/src/components/blocks/profile/use-profile-card.ts +126 -0
- package/src/components/blocks/shell/__tests__/shell-fit-atom.test.tsx +360 -0
- package/src/components/blocks/shell/__tests__/shell-layout.test.tsx +192 -3
- package/src/components/blocks/shell/__tests__/shell-metrics.test.ts +108 -0
- package/src/components/blocks/shell/animated-panel-inset.tsx +5 -1
- package/src/components/blocks/shell/animated-panel-provider.tsx +77 -11
- package/src/components/blocks/shell/animated-panel-trigger.tsx +4 -0
- package/src/components/blocks/shell/animated-panel.tsx +126 -29
- package/src/components/blocks/shell/index.ts +18 -13
- package/src/components/blocks/shell/shell-fit-atom.ts +243 -0
- package/src/components/blocks/shell/shell-layout.tsx +55 -53
- package/src/components/blocks/shell/shell-metrics.ts +79 -0
- package/src/components/blocks/shell/type.ts +130 -3
- package/src/components/blocks/shell/use-shell-fit-state.ts +49 -0
- package/src/components/blocks/shell/use-shell-fit.ts +135 -0
- package/src/components/blocks/shell/use-shell-panels.ts +57 -4
- package/src/components/blocks/shell/utils.ts +44 -4
- package/src/components/composed/__tests__/logo.test.tsx +60 -0
- package/src/components/composed/logo.tsx +159 -0
- package/src/components/composed/tree/CLAUDE.md +132 -0
- package/src/components/composed/tree/__tests__/tree-atom.test.tsx +217 -0
- package/src/components/composed/tree/__tests__/tree.test.tsx +162 -37
- package/src/components/composed/tree/__tests__/use-tree.test.tsx +2 -1
- package/src/components/composed/tree/constants.ts +4 -4
- package/src/components/composed/tree/index.ts +38 -0
- package/src/components/composed/tree/tree-atom.ts +590 -0
- package/src/components/composed/tree/tree-node.tsx +117 -78
- package/src/components/composed/tree/tree.tsx +24 -16
- package/src/components/composed/tree/type.ts +125 -15
- package/src/components/composed/tree/use-tree-dnd.ts +82 -51
- package/src/components/composed/tree/use-tree-state.ts +105 -0
- package/src/components/composed/tree/use-tree.ts +185 -184
- package/src/components/composed/user-avatar.tsx +11 -99
- package/src/components/user-avatar/__tests__/user-avatar.test.tsx +286 -0
- package/src/components/user-avatar/component.tsx +151 -22
- package/src/components/user-avatar/fallback.tsx +3 -1
- package/src/components/user-avatar/index.ts +19 -0
- package/src/components/user-avatar/presence-badge.tsx +56 -0
- package/src/components/user-avatar/type.ts +58 -0
- package/src/components/user-avatar/use-user-avatar-state.ts +60 -0
- package/src/components/user-avatar/use-user-avatar.ts +180 -0
- package/src/components/user-avatar/user-avatar-atom.ts +218 -0
- package/src/components/user-avatar/utils.ts +94 -0
- package/src/index.ts +35 -3
- package/src/state/exegia-provider.tsx +79 -0
- package/src/state/index.ts +4 -0
- package/src/state/store.ts +19 -0
- package/dist-lib/components/blocks/nav/sidebar-block.d.ts +0 -14
- package/dist-lib/components/blocks/nav/sidebar-nav-row.d.ts +0 -3
- package/dist-lib/components/blocks/nav/types.d.ts +0 -60
- package/dist-lib/components/blocks/nav/utils.d.ts +0 -1
- package/dist-lib/components/blocks/shell/animated-sidebar-content.d.ts +0 -2
- package/dist-lib/components/blocks/shell/animated-sidebar-footer.d.ts +0 -2
- package/dist-lib/components/blocks/shell/animated-sidebar-group-content.d.ts +0 -2
- package/dist-lib/components/blocks/shell/animated-sidebar-group-label.d.ts +0 -2
- package/dist-lib/components/blocks/shell/animated-sidebar-group.d.ts +0 -2
- package/dist-lib/components/blocks/shell/animated-sidebar-header.d.ts +0 -2
- package/dist-lib/components/blocks/shell/animated-sidebar-menu-button.d.ts +0 -3
- package/dist-lib/components/blocks/shell/animated-sidebar-menu-item.d.ts +0 -2
- package/dist-lib/components/blocks/shell/animated-sidebar-menu-sub-button.d.ts +0 -3
- package/dist-lib/components/blocks/shell/animated-sidebar-menu-sub-item.d.ts +0 -2
- package/dist-lib/components/blocks/shell/animated-sidebar-menu-sub.d.ts +0 -2
- package/dist-lib/components/blocks/shell/animated-sidebar-menu.d.ts +0 -2
- package/src/components/blocks/nav/__tests__/sidebar-block.test.tsx +0 -125
- package/src/components/blocks/nav/sidebar-block.tsx +0 -142
- package/src/components/blocks/nav/sidebar-nav-row.tsx +0 -78
- package/src/components/blocks/nav/types.ts +0 -65
- package/src/components/blocks/nav/utils.ts +0 -4
- package/src/components/blocks/shell/animated-sidebar-content.tsx +0 -19
- package/src/components/blocks/shell/animated-sidebar-footer.tsx +0 -19
- package/src/components/blocks/shell/animated-sidebar-group-content.tsx +0 -16
- package/src/components/blocks/shell/animated-sidebar-group-label.tsx +0 -29
- package/src/components/blocks/shell/animated-sidebar-group.tsx +0 -16
- package/src/components/blocks/shell/animated-sidebar-header.tsx +0 -16
- package/src/components/blocks/shell/animated-sidebar-menu-button.tsx +0 -151
- package/src/components/blocks/shell/animated-sidebar-menu-item.tsx +0 -20
- package/src/components/blocks/shell/animated-sidebar-menu-sub-button.tsx +0 -85
- package/src/components/blocks/shell/animated-sidebar-menu-sub-item.tsx +0 -19
- package/src/components/blocks/shell/animated-sidebar-menu-sub.tsx +0 -44
- package/src/components/blocks/shell/animated-sidebar-menu.tsx +0 -26
- /package/dist-lib/components/blocks/{nav/__tests__/sidebar-block.test.d.ts → auth/__tests__/auth-state-atom.test.d.ts} +0 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session state for the auth blocks — singleton atoms, deliberately NOT a
|
|
3
|
+
* family.
|
|
4
|
+
*
|
|
5
|
+
* A session is one-per-store: one signed-in user per app (per
|
|
6
|
+
* `ExegiaProvider` store; SSR isolation comes from passing a fresh store).
|
|
7
|
+
* Instance keying is for multi-instance components; a family here would
|
|
8
|
+
* imply several concurrent users and be a lie.
|
|
9
|
+
*
|
|
10
|
+
* Import direction: this module is the LEAF — it imports nothing from
|
|
11
|
+
* `auth-flow-atom.ts`. The flow module imports `signInAtom` from here (for
|
|
12
|
+
* `completeAuthFlowAtom`) and defines the composite `endAuthSessionAtom`
|
|
13
|
+
* that pairs `signOutAtom` with a flow reset. `signOutAtom` below clears the
|
|
14
|
+
* session only.
|
|
15
|
+
*/
|
|
16
|
+
import { atom } from "jotai"
|
|
17
|
+
|
|
18
|
+
import type {
|
|
19
|
+
AuthSessionState,
|
|
20
|
+
AuthSessionStatus,
|
|
21
|
+
AuthUser,
|
|
22
|
+
} from "./auth-state-type"
|
|
23
|
+
|
|
24
|
+
// ── primitives ───────────────────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
/** `"unknown"` until the app restores or rejects a session at boot. */
|
|
27
|
+
export const authSessionStatusAtom = atom<AuthSessionStatus>("unknown")
|
|
28
|
+
authSessionStatusAtom.debugLabel = "auth-session/status"
|
|
29
|
+
|
|
30
|
+
export const authUserAtom = atom<AuthUser | null>(null)
|
|
31
|
+
authUserAtom.debugLabel = "auth-session/user"
|
|
32
|
+
|
|
33
|
+
// ── derived ──────────────────────────────────────────────────────────────
|
|
34
|
+
|
|
35
|
+
export const isAuthenticatedAtom = atom(
|
|
36
|
+
(get) => get(authSessionStatusAtom) === "authenticated"
|
|
37
|
+
)
|
|
38
|
+
isAuthenticatedAtom.debugLabel = "auth-session/isAuthenticated"
|
|
39
|
+
|
|
40
|
+
export const authSessionStateAtom = atom<AuthSessionState>((get) => ({
|
|
41
|
+
status: get(authSessionStatusAtom),
|
|
42
|
+
user: get(authUserAtom),
|
|
43
|
+
}))
|
|
44
|
+
authSessionStateAtom.debugLabel = "auth-session/state"
|
|
45
|
+
|
|
46
|
+
// ── actions ──────────────────────────────────────────────────────────────
|
|
47
|
+
|
|
48
|
+
export const signInAtom = atom(null, (_get, set, user: AuthUser) => {
|
|
49
|
+
set(authUserAtom, user)
|
|
50
|
+
set(authSessionStatusAtom, "authenticated")
|
|
51
|
+
})
|
|
52
|
+
signInAtom.debugLabel = "auth-session/signIn"
|
|
53
|
+
|
|
54
|
+
export const updateAuthUserAtom = atom(
|
|
55
|
+
null,
|
|
56
|
+
(get, set, patch: Partial<AuthUser>) => {
|
|
57
|
+
const user = get(authUserAtom)
|
|
58
|
+
// No-op when signed out: there is no user to merge into, and inventing
|
|
59
|
+
// one from a partial patch would fabricate an identity.
|
|
60
|
+
if (user === null) return
|
|
61
|
+
set(authUserAtom, { ...user, ...patch })
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
updateAuthUserAtom.debugLabel = "auth-session/updateUser"
|
|
65
|
+
|
|
66
|
+
/** What an app calls at boot when session restore fails. */
|
|
67
|
+
export const markUnauthenticatedAtom = atom(null, (_get, set) => {
|
|
68
|
+
set(authSessionStatusAtom, "unauthenticated")
|
|
69
|
+
set(authUserAtom, null)
|
|
70
|
+
})
|
|
71
|
+
markUnauthenticatedAtom.debugLabel = "auth-session/markUnauthenticated"
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Clears the session only. Most consumers want `endAuthSessionAtom` from
|
|
75
|
+
* `auth-flow-atom.ts` instead, which also returns the default flow to the
|
|
76
|
+
* login step — the hooks expose that one as `signOut`.
|
|
77
|
+
*/
|
|
78
|
+
export const signOutAtom = atom(null, (_get, set) => {
|
|
79
|
+
set(authUserAtom, null)
|
|
80
|
+
set(authSessionStatusAtom, "unauthenticated")
|
|
81
|
+
})
|
|
82
|
+
signOutAtom.debugLabel = "auth-session/signOut"
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for the auth coordination state (`auth-flow-atom.ts` /
|
|
3
|
+
* `auth-session-atom.ts`).
|
|
4
|
+
*
|
|
5
|
+
* This file stays dependency-free of the atom modules: types only, no atom
|
|
6
|
+
* imports. The auth blocks themselves are unaware of this layer — they keep
|
|
7
|
+
* field values in local `useState` — these types describe the coordination
|
|
8
|
+
* state an app wires *around* the blocks.
|
|
9
|
+
*/
|
|
10
|
+
import type { AuthStatus } from "./auth-shell"
|
|
11
|
+
|
|
12
|
+
export type AuthFlowId = string
|
|
13
|
+
|
|
14
|
+
/** Which auth block the app is showing. */
|
|
15
|
+
export type AuthFlowStep =
|
|
16
|
+
| "login"
|
|
17
|
+
| "signup"
|
|
18
|
+
| "verify-code"
|
|
19
|
+
| "forgot-password"
|
|
20
|
+
| "update-password"
|
|
21
|
+
| "onboarding"
|
|
22
|
+
| "success"
|
|
23
|
+
|
|
24
|
+
export type AuthFlowChannel = "email" | "sms"
|
|
25
|
+
|
|
26
|
+
export interface AuthFlowState {
|
|
27
|
+
step: AuthFlowStep
|
|
28
|
+
/** The identifier in flight — an email or phone number. Cleared by reset
|
|
29
|
+
* and by signOut. Never store passwords or codes here. */
|
|
30
|
+
identifier: string | null
|
|
31
|
+
/** `identifier` masked for display — "y•••@example.com", "•••1234". */
|
|
32
|
+
maskedIdentifier: string | null
|
|
33
|
+
channel: AuthFlowChannel
|
|
34
|
+
status: AuthStatus
|
|
35
|
+
error: string | null
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Options for `beginAuthVerificationAtom` / `beginVerification`. */
|
|
39
|
+
export interface BeginAuthVerificationOptions {
|
|
40
|
+
identifier: string
|
|
41
|
+
/** @default "email" */
|
|
42
|
+
channel?: AuthFlowChannel
|
|
43
|
+
/** @default "verify-code" */
|
|
44
|
+
step?: AuthFlowStep
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** What `useAuthFlowActions(flowId)` returns. */
|
|
48
|
+
export interface AuthFlowActions {
|
|
49
|
+
/** Show a step; resets status to `"idle"` and clears the error. Keeps the
|
|
50
|
+
* identifier. */
|
|
51
|
+
goToStep: (step: AuthFlowStep) => void
|
|
52
|
+
/** Record the identifier in flight and move to the verification step. */
|
|
53
|
+
beginVerification: (options: BeginAuthVerificationOptions) => void
|
|
54
|
+
/** Mark the flow `"loading"` while an async attempt is in flight. */
|
|
55
|
+
beginAttempt: () => void
|
|
56
|
+
/** Mark the flow `"error"` with a message. */
|
|
57
|
+
fail: (message: string) => void
|
|
58
|
+
/** Mark the flow `"success"`; when a user is given, also sign the session
|
|
59
|
+
* in. */
|
|
60
|
+
complete: (user?: AuthUser) => void
|
|
61
|
+
/** Back to the initial values (login step, no identifier). */
|
|
62
|
+
reset: () => void
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** The signed-in identity, kept for the whole session. Structurally
|
|
66
|
+
* assignable to `ProfileCardUser`, so it drops into `ProfileCardBlock`. */
|
|
67
|
+
export interface AuthUser {
|
|
68
|
+
id: string
|
|
69
|
+
name: string
|
|
70
|
+
/** Secondary line — a handle, an email, a role. */
|
|
71
|
+
username?: string
|
|
72
|
+
email?: string
|
|
73
|
+
/** Avatar image URL. */
|
|
74
|
+
avatar?: string
|
|
75
|
+
initials?: string
|
|
76
|
+
/** App-specific extras the library never interprets. */
|
|
77
|
+
metadata?: Record<string, unknown>
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/** `unknown` until the app restores or rejects a session at boot. */
|
|
81
|
+
export type AuthSessionStatus = "unknown" | "unauthenticated" | "authenticated"
|
|
82
|
+
|
|
83
|
+
export interface AuthSessionState {
|
|
84
|
+
status: AuthSessionStatus
|
|
85
|
+
user: AuthUser | null
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** What `useAuthSessionActions()` returns. */
|
|
89
|
+
export interface AuthSessionActions {
|
|
90
|
+
signIn: (user: AuthUser) => void
|
|
91
|
+
/** Shallow-merge a patch into the signed-in user; no-op when signed out. */
|
|
92
|
+
updateUser: (patch: Partial<AuthUser>) => void
|
|
93
|
+
/** What an app calls at boot when session restore fails. */
|
|
94
|
+
markUnauthenticated: () => void
|
|
95
|
+
/** Sign out AND return the default auth flow to the login step. */
|
|
96
|
+
signOut: () => void
|
|
97
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public barrel for the auth coordination state. Explicit named exports
|
|
3
|
+
* only — never `export *` from the atom modules, so internals can move
|
|
4
|
+
* without becoming a breaking-change surface.
|
|
5
|
+
*/
|
|
6
|
+
export {
|
|
7
|
+
DEFAULT_AUTH_FLOW_ID,
|
|
8
|
+
authFlowChannelAtom,
|
|
9
|
+
authFlowErrorAtom,
|
|
10
|
+
authFlowIdentifierAtom,
|
|
11
|
+
authFlowMaskedIdentifierAtom,
|
|
12
|
+
authFlowStateAtom,
|
|
13
|
+
authFlowStatusAtom,
|
|
14
|
+
authFlowStepAtom,
|
|
15
|
+
beginAuthAttemptAtom,
|
|
16
|
+
beginAuthVerificationAtom,
|
|
17
|
+
completeAuthFlowAtom,
|
|
18
|
+
endAuthSessionAtom,
|
|
19
|
+
failAuthFlowAtom,
|
|
20
|
+
goToAuthStepAtom,
|
|
21
|
+
maskAuthIdentifier,
|
|
22
|
+
removeAuthFlowInstance,
|
|
23
|
+
resetAuthFlowAtom,
|
|
24
|
+
} from "./auth-flow-atom"
|
|
25
|
+
export {
|
|
26
|
+
authSessionStateAtom,
|
|
27
|
+
authSessionStatusAtom,
|
|
28
|
+
authUserAtom,
|
|
29
|
+
isAuthenticatedAtom,
|
|
30
|
+
markUnauthenticatedAtom,
|
|
31
|
+
signInAtom,
|
|
32
|
+
signOutAtom,
|
|
33
|
+
updateAuthUserAtom,
|
|
34
|
+
} from "./auth-session-atom"
|
|
35
|
+
export {
|
|
36
|
+
useAuthFlow,
|
|
37
|
+
useAuthFlowActions,
|
|
38
|
+
useAuthSession,
|
|
39
|
+
useAuthSessionActions,
|
|
40
|
+
} from "./use-auth-state"
|
|
41
|
+
export type {
|
|
42
|
+
AuthFlowActions,
|
|
43
|
+
AuthFlowChannel,
|
|
44
|
+
AuthFlowId,
|
|
45
|
+
AuthFlowState,
|
|
46
|
+
AuthFlowStep,
|
|
47
|
+
AuthSessionActions,
|
|
48
|
+
AuthSessionState,
|
|
49
|
+
AuthSessionStatus,
|
|
50
|
+
AuthUser,
|
|
51
|
+
BeginAuthVerificationOptions,
|
|
52
|
+
} from "./auth-state-type"
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import { useAtomValue, useSetAtom } from "jotai"
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
DEFAULT_AUTH_FLOW_ID,
|
|
8
|
+
authFlowStateAtom,
|
|
9
|
+
beginAuthAttemptAtom,
|
|
10
|
+
beginAuthVerificationAtom,
|
|
11
|
+
completeAuthFlowAtom,
|
|
12
|
+
endAuthSessionAtom,
|
|
13
|
+
failAuthFlowAtom,
|
|
14
|
+
goToAuthStepAtom,
|
|
15
|
+
resetAuthFlowAtom,
|
|
16
|
+
} from "./auth-flow-atom"
|
|
17
|
+
import {
|
|
18
|
+
authSessionStateAtom,
|
|
19
|
+
isAuthenticatedAtom,
|
|
20
|
+
markUnauthenticatedAtom,
|
|
21
|
+
signInAtom,
|
|
22
|
+
updateAuthUserAtom,
|
|
23
|
+
} from "./auth-session-atom"
|
|
24
|
+
import type {
|
|
25
|
+
AuthFlowActions,
|
|
26
|
+
AuthFlowId,
|
|
27
|
+
AuthFlowState,
|
|
28
|
+
AuthSessionActions,
|
|
29
|
+
AuthSessionState,
|
|
30
|
+
} from "./auth-state-type"
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Read the auth flow registered under `flowId` from anywhere below
|
|
34
|
+
* `ExegiaProvider`. Pairs with `useAuthFlowActions` to wire the auth blocks
|
|
35
|
+
* into one flow — the blocks keep passwords and codes in local state, the
|
|
36
|
+
* flow tracks which block shows and what identifier is in flight:
|
|
37
|
+
*
|
|
38
|
+
* ```tsx
|
|
39
|
+
* const flow = useAuthFlow()
|
|
40
|
+
* const { beginVerification, complete, fail } = useAuthFlowActions()
|
|
41
|
+
*
|
|
42
|
+
* {flow.step === "login" && (
|
|
43
|
+
* <LoginBlock
|
|
44
|
+
* onSubmit={async ({ email }) => {
|
|
45
|
+
* await api.requestCode(email)
|
|
46
|
+
* beginVerification({ identifier: email })
|
|
47
|
+
* }}
|
|
48
|
+
* />
|
|
49
|
+
* )}
|
|
50
|
+
* {flow.step === "verify-code" && (
|
|
51
|
+
* <CodeAuthBlock
|
|
52
|
+
* destination={flow.maskedIdentifier ?? undefined}
|
|
53
|
+
* onVerify={async (code) => complete(await api.verify(code))}
|
|
54
|
+
* />
|
|
55
|
+
* )}
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* This returns the whole state object, so the caller re-renders on any
|
|
59
|
+
* change. A component that reads one field should subscribe to that field's
|
|
60
|
+
* atom instead: `useAtomValue(authFlowStepAtom(flowId))`.
|
|
61
|
+
*/
|
|
62
|
+
export function useAuthFlow(
|
|
63
|
+
flowId: AuthFlowId = DEFAULT_AUTH_FLOW_ID
|
|
64
|
+
): AuthFlowState {
|
|
65
|
+
return useAtomValue(authFlowStateAtom(flowId))
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Drive the auth flow registered under `flowId` from anywhere. Writes only —
|
|
70
|
+
* the caller never re-renders when the flow changes. See `useAuthFlow` for
|
|
71
|
+
* the intended wiring; a block's submit handler typically runs
|
|
72
|
+
* `beginAttempt()` → the API call → `complete(user)` or `fail(message)`.
|
|
73
|
+
*/
|
|
74
|
+
export function useAuthFlowActions(
|
|
75
|
+
flowId: AuthFlowId = DEFAULT_AUTH_FLOW_ID
|
|
76
|
+
): AuthFlowActions {
|
|
77
|
+
const goToStep = useSetAtom(goToAuthStepAtom(flowId))
|
|
78
|
+
const beginVerification = useSetAtom(beginAuthVerificationAtom(flowId))
|
|
79
|
+
const beginAttempt = useSetAtom(beginAuthAttemptAtom(flowId))
|
|
80
|
+
const fail = useSetAtom(failAuthFlowAtom(flowId))
|
|
81
|
+
const complete = useSetAtom(completeAuthFlowAtom(flowId))
|
|
82
|
+
const reset = useSetAtom(resetAuthFlowAtom(flowId))
|
|
83
|
+
|
|
84
|
+
return React.useMemo(
|
|
85
|
+
() => ({
|
|
86
|
+
goToStep,
|
|
87
|
+
beginVerification,
|
|
88
|
+
beginAttempt,
|
|
89
|
+
fail,
|
|
90
|
+
complete,
|
|
91
|
+
reset,
|
|
92
|
+
}),
|
|
93
|
+
[goToStep, beginVerification, beginAttempt, fail, complete, reset]
|
|
94
|
+
)
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Read the session: `status` (`"unknown"` until the app restores or rejects
|
|
99
|
+
* a session at boot), the signed-in `user`, and derived `isAuthenticated`.
|
|
100
|
+
*/
|
|
101
|
+
export function useAuthSession(): AuthSessionState & {
|
|
102
|
+
isAuthenticated: boolean
|
|
103
|
+
} {
|
|
104
|
+
const state = useAtomValue(authSessionStateAtom)
|
|
105
|
+
const isAuthenticated = useAtomValue(isAuthenticatedAtom)
|
|
106
|
+
return React.useMemo(
|
|
107
|
+
() => ({ ...state, isAuthenticated }),
|
|
108
|
+
[state, isAuthenticated]
|
|
109
|
+
)
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Drive the session. Writes only. `signOut` is the composite
|
|
114
|
+
* `endAuthSessionAtom`: it clears the session AND returns the default flow
|
|
115
|
+
* to the login step — the one to wire to a logout button.
|
|
116
|
+
*/
|
|
117
|
+
export function useAuthSessionActions(): AuthSessionActions {
|
|
118
|
+
const signIn = useSetAtom(signInAtom)
|
|
119
|
+
const updateUser = useSetAtom(updateAuthUserAtom)
|
|
120
|
+
const markUnauthenticated = useSetAtom(markUnauthenticatedAtom)
|
|
121
|
+
const signOut = useSetAtom(endAuthSessionAtom)
|
|
122
|
+
|
|
123
|
+
return React.useMemo(
|
|
124
|
+
() => ({ signIn, updateUser, markUnauthenticated, signOut }),
|
|
125
|
+
[signIn, updateUser, markUnauthenticated, signOut]
|
|
126
|
+
)
|
|
127
|
+
}
|
|
@@ -1,7 +1,35 @@
|
|
|
1
|
-
import ShellLayout
|
|
1
|
+
import ShellLayout, {
|
|
2
|
+
AnimatedPanel,
|
|
3
|
+
AnimatedPanelTrigger,
|
|
4
|
+
useShellPanels,
|
|
5
|
+
resetShellPanelWidthAtom,
|
|
6
|
+
resizeShellPanelAtom,
|
|
7
|
+
shellFitFitsAtom,
|
|
8
|
+
shellFitMeasuredAtom,
|
|
9
|
+
shellFitMetricsAtom,
|
|
10
|
+
shellFitPanelBoundsAtom,
|
|
11
|
+
shellFitPanelWidthAtom,
|
|
12
|
+
shellFitRequestedWidthAtom,
|
|
13
|
+
shellFitStateAtom,
|
|
14
|
+
} from "@/components/blocks/shell"
|
|
2
15
|
|
|
3
16
|
const Layout = {
|
|
4
|
-
Main: ShellLayout
|
|
17
|
+
Main: ShellLayout,
|
|
18
|
+
Panel: AnimatedPanel,
|
|
19
|
+
Trigger: AnimatedPanelTrigger,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export {
|
|
23
|
+
useShellPanels,
|
|
24
|
+
resetShellPanelWidthAtom,
|
|
25
|
+
resizeShellPanelAtom,
|
|
26
|
+
shellFitFitsAtom,
|
|
27
|
+
shellFitMeasuredAtom,
|
|
28
|
+
shellFitMetricsAtom,
|
|
29
|
+
shellFitPanelBoundsAtom,
|
|
30
|
+
shellFitPanelWidthAtom,
|
|
31
|
+
shellFitRequestedWidthAtom,
|
|
32
|
+
shellFitStateAtom,
|
|
5
33
|
}
|
|
6
34
|
|
|
7
35
|
export default Layout
|