@elevasis/ui 1.2.1 → 1.3.1

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.
Files changed (59) hide show
  1. package/dist/CoreAuthKitInner-3J4RVQO6.js +43 -0
  2. package/dist/api/index.d.ts +32 -18
  3. package/dist/api/index.js +4 -2
  4. package/dist/auth/context.d.ts +23 -5
  5. package/dist/auth/index.d.ts +119 -30
  6. package/dist/auth/index.js +6 -3
  7. package/dist/chunk-2JBWPFHF.js +108 -0
  8. package/dist/chunk-4VGWQ5AN.js +91 -0
  9. package/dist/chunk-72HOBFMP.js +87 -0
  10. package/dist/{chunk-WNWKOCGJ.js → chunk-A3MCANC6.js} +296 -2
  11. package/dist/{chunk-JKERRYVS.js → chunk-BLO4SISK.js} +7 -3
  12. package/dist/chunk-DD3CCMCZ.js +15 -0
  13. package/dist/chunk-FWZJH3TL.js +13 -0
  14. package/dist/{chunk-GEFB5YIR.js → chunk-JBFFCZI4.js} +1 -1
  15. package/dist/chunk-JGJSZ3UE.js +47 -0
  16. package/dist/{chunk-7AI5ZYJ4.js → chunk-JVAZHVNV.js} +2 -94
  17. package/dist/{chunk-ZGHDPDTF.js → chunk-JYSYHVLU.js} +3 -3
  18. package/dist/{chunk-5UWFGBFM.js → chunk-L2CM2CUA.js} +16 -4
  19. package/dist/chunk-NEK6JKPW.js +75 -0
  20. package/dist/{chunk-J3FALDQE.js → chunk-NXHL23JW.js} +7 -13
  21. package/dist/{chunk-OUHGHTE7.js → chunk-O3PY6B6E.js} +3 -2
  22. package/dist/{chunk-YULUKCS6.js → chunk-PVVQTENF.js} +1 -1
  23. package/dist/chunk-TIRMFDM4.js +33 -0
  24. package/dist/{chunk-PYL4XW6H.js → chunk-TMFCNFLW.js} +1 -1
  25. package/dist/{chunk-S66I2PYB.js → chunk-TN3PU2WK.js} +1 -1
  26. package/dist/chunk-TYV5NJV2.js +1 -0
  27. package/dist/{chunk-B64YDSAY.js → chunk-TZPAA4RC.js} +54 -97
  28. package/dist/chunk-UMXDDEAG.js +148 -0
  29. package/dist/chunk-XLV6LYN2.js +157 -0
  30. package/dist/components/command-queue/index.js +6 -4
  31. package/dist/components/index.js +9 -7
  32. package/dist/components/notifications/index.js +4 -3
  33. package/dist/display/index.js +3 -2
  34. package/dist/hooks/index.d.ts +2630 -3
  35. package/dist/hooks/index.js +9 -5
  36. package/dist/hooks/published.d.ts +2630 -3
  37. package/dist/hooks/published.js +7 -3
  38. package/dist/index.d.ts +759 -164
  39. package/dist/index.js +24 -18
  40. package/dist/initialization/index.d.ts +49 -1
  41. package/dist/initialization/index.js +5 -2
  42. package/dist/organization/index.d.ts +61 -2
  43. package/dist/organization/index.js +5 -2
  44. package/dist/profile/index.d.ts +30 -2
  45. package/dist/profile/index.js +2 -1
  46. package/dist/provider/index.d.ts +116 -43
  47. package/dist/provider/index.js +10 -6
  48. package/dist/provider/published.d.ts +88 -28
  49. package/dist/provider/published.js +9 -4
  50. package/dist/supabase/index.js +2 -47
  51. package/dist/utils/index.js +2 -1
  52. package/package.json +15 -2
  53. package/dist/CoreAuthKitInner-KM72EYJS.js +0 -19
  54. package/dist/chunk-GDV44UWF.js +0 -138
  55. package/dist/chunk-HBRMWW6V.js +0 -43
  56. package/dist/chunk-NIAVTSMB.js +0 -21
  57. package/dist/chunk-QSVZP2NU.js +0 -214
  58. package/dist/chunk-ZQVPUAGR.js +0 -89
  59. /package/dist/{chunk-Q47SPRY7.js → chunk-RNP5R5I3.js} +0 -0
package/dist/index.d.ts CHANGED
@@ -44,8 +44,10 @@ declare function getPreset(name: PresetName | (string & {})): ThemePreset;
44
44
  */
45
45
  interface ApiClientContextValue {
46
46
  getAccessToken: () => Promise<string | undefined>;
47
+ /** @deprecated Read via getOrganizationId() instead. Kept for downstream context consumers during migration. */
47
48
  organizationId: string | null;
48
49
  isOrganizationReady: boolean;
50
+ getOrganizationId: () => string | null;
49
51
  onError?: (endpoint: string, error: Error, details?: ApiErrorDetails) => void;
50
52
  }
51
53
  interface ApiErrorDetails {
@@ -56,11 +58,70 @@ interface ApiErrorDetails {
56
58
  interface ApiClientProviderProps {
57
59
  children: React.ReactNode;
58
60
  getAccessToken: () => Promise<string | undefined>;
59
- organizationId: string | null;
61
+ /**
62
+ * Static org ID. Used when org ID is stable at render time.
63
+ * Cannot reflect org switches without re-rendering the provider.
64
+ * Prefer getOrganizationId for dynamic org context.
65
+ * @deprecated Pass getOrganizationId instead for dynamic org resolution.
66
+ */
67
+ organizationId?: string | null;
68
+ /**
69
+ * Callback invoked on every request to read the current org ID.
70
+ * Takes precedence over organizationId when provided.
71
+ * Allows org switching without re-rendering the provider tree.
72
+ */
73
+ getOrganizationId?: () => string | null;
60
74
  isOrganizationReady: boolean;
61
75
  onError?: (endpoint: string, error: Error, details?: ApiErrorDetails) => void;
62
76
  }
63
77
 
78
+ /**
79
+ * Pluggable notification adapter interface.
80
+ *
81
+ * Implement this to connect any notification library (Mantine, react-toastify, etc.)
82
+ * to the Elevasis UI hooks.
83
+ */
84
+ interface NotificationAdapter {
85
+ success(title: string, message: string): void;
86
+ error(title: string, message: string): void;
87
+ info(title: string, message: string): void;
88
+ warning(title: string, message: string): void;
89
+ /** Formats and displays an API error using structured error-utils helpers. */
90
+ apiError(error: unknown): void;
91
+ }
92
+ /**
93
+ * Provides a notification adapter to all descendant components.
94
+ *
95
+ * Pass a `MantineNotificationAdapter` for Command Center, or any custom
96
+ * adapter for other consumers (template, tests, etc.).
97
+ *
98
+ * When omitted, hooks fall back to the console adapter automatically.
99
+ *
100
+ * @example
101
+ * ```tsx
102
+ * import { NotificationProvider } from '@repo/ui/provider'
103
+ * import { mantineNotificationAdapter } from '@repo/ui/provider'
104
+ *
105
+ * <NotificationProvider adapter={mantineNotificationAdapter}>
106
+ * <App />
107
+ * </NotificationProvider>
108
+ * ```
109
+ */
110
+ declare function NotificationProvider({ adapter, children }: {
111
+ adapter: NotificationAdapter;
112
+ children: ReactNode;
113
+ }): react_jsx_runtime.JSX.Element;
114
+ /**
115
+ * Returns the active notification adapter.
116
+ *
117
+ * Falls back to the console adapter when used outside a NotificationProvider,
118
+ * so hooks remain functional in template environments without Mantine.
119
+ *
120
+ * Named `useNotificationAdapter` to avoid collision with the data-fetching
121
+ * `useNotifications` hook exported from `hooks/monitoring`.
122
+ */
123
+ declare function useNotificationAdapter(): NotificationAdapter;
124
+
64
125
  /** Flat + per-scheme override pattern. Flat values apply to both; `light`/`dark` win over flat. */
65
126
  type WithSchemes<T> = T & {
66
127
  light?: T;
@@ -121,10 +182,10 @@ interface ElevasisThemeConfig extends ElevasisCoreThemeConfig {
121
182
  }
122
183
  /**
123
184
  * Auth configuration union.
124
- * 'authkit' (WorkOS AuthKit) and 'oauth' (WorkOS Connect) are implemented.
185
+ * 'authkit' (WorkOS AuthKit) is the supported mode.
125
186
  * 'apiKey' is defined for forward type compatibility but will throw at runtime.
126
187
  */
127
- type AuthConfig = AuthKitConfig | OAuthConfig | ApiKeyConfig;
188
+ type AuthConfig = AuthKitConfig | ApiKeyConfig;
128
189
  interface AuthKitConfig {
129
190
  mode: 'authkit';
130
191
  clientId: string;
@@ -135,25 +196,13 @@ interface AuthKitConfig {
135
196
  /** Keep refresh tokens in localStorage. Defaults to false. */
136
197
  devMode?: boolean;
137
198
  }
138
- /** OAuth config for "Sign in with Elevasis" via WorkOS Connect. */
139
- interface OAuthConfig {
140
- mode: 'oauth';
141
- clientId: string;
142
- redirectUri: string;
143
- /** Persist tokens in sessionStorage. Default is memory-only. */
144
- tokenStorage?: 'session';
145
- /** Pre-select organization in WorkOS flow. */
146
- organizationId?: string;
147
- /** Auth provider for the authorize request. Defaults to 'authkit' (hosted login UI). */
148
- provider?: 'authkit' | 'GoogleOAuth' | 'MicrosoftOAuth' | 'GitHubOAuth' | 'AppleOAuth';
149
- }
150
199
  /** Deferred -- will throw at runtime. */
151
200
  interface ApiKeyConfig {
152
201
  mode: 'apiKey';
153
202
  key: string;
154
203
  }
155
204
  interface ElevasisCoreProviderProps {
156
- /** Auth configuration. Supports 'authkit' and 'oauth' modes. */
205
+ /** Auth configuration. Supports 'authkit' mode. */
157
206
  auth: AuthConfig;
158
207
  /**
159
208
  * Elevasis core theme configuration (Mantine-free).
@@ -162,16 +211,18 @@ interface ElevasisCoreProviderProps {
162
211
  */
163
212
  theme?: ElevasisCoreThemeConfig;
164
213
  /**
165
- * Override organization ID resolution.
166
- * Command-center passes Zustand-managed org ID here.
167
- * SDK consumers typically omit this (auto-resolved from JWT/API key).
214
+ * @deprecated Organization ID is now resolved automatically via OrganizationProvider.
215
+ * This prop is accepted for backwards compatibility during migration but is no longer
216
+ * used when the full provider stack is active (apiUrl provided).
168
217
  */
169
218
  organizationId?: string | null;
170
219
  /** Custom QueryClient. If omitted, a default is created internally. */
171
220
  queryClient?: QueryClient;
172
221
  /**
173
222
  * API base URL (e.g., 'https://api.elevasis.com' or 'http://localhost:5170').
174
- * When provided, ElevasisCoreProvider composes ApiClientProvider + ElevasisServiceProvider internally.
223
+ * When provided, ElevasisCoreProvider composes the full provider stack:
224
+ * ApiClientProvider + ElevasisServiceProvider + ProfileProvider +
225
+ * OrganizationProvider + NotificationProvider + InitializationProvider.
175
226
  * When omitted, no service context is provided (theme-only mode).
176
227
  */
177
228
  apiUrl?: string;
@@ -181,11 +232,19 @@ interface ElevasisCoreProviderProps {
181
232
  */
182
233
  onError?: (endpoint: string, error: Error, details?: ApiErrorDetails) => void;
183
234
  /**
184
- * Override organization readiness check.
185
- * Defaults to `!!organizationId` if not provided.
186
- * Command-center passes `!!currentMembership` for its stricter readiness requirement.
235
+ * @deprecated Organization readiness is now managed internally by OrganizationProvider.
236
+ * Accepted for backwards compatibility but ignored when apiUrl is provided.
187
237
  */
188
238
  isOrganizationReady?: boolean;
239
+ /**
240
+ * Notification adapter for displaying success/error/info messages.
241
+ * When provided, wraps the subtree in a NotificationProvider with this adapter.
242
+ * When omitted, the console fallback adapter is used automatically.
243
+ *
244
+ * ElevasisUIProvider (Mantine variant) passes mantineNotificationAdapter here automatically.
245
+ * Headless/SDK consumers can pass a custom adapter or omit for console output.
246
+ */
247
+ notifications?: NotificationAdapter;
189
248
  /**
190
249
  * Whether to inject CSS variables, `data-elevasis-scheme` attribute, and font links.
191
250
  * Set to `false` when the consumer has its own complete design system and only
@@ -195,7 +254,7 @@ interface ElevasisCoreProviderProps {
195
254
  children: ReactNode;
196
255
  }
197
256
  interface ElevasisProviderProps {
198
- /** Auth configuration. Supports 'authkit' and 'oauth' modes. */
257
+ /** Auth configuration. Supports 'authkit' mode. */
199
258
  auth: AuthConfig;
200
259
  /**
201
260
  * Elevasis theme configuration.
@@ -204,16 +263,15 @@ interface ElevasisProviderProps {
204
263
  */
205
264
  theme?: ElevasisThemeConfig;
206
265
  /**
207
- * Override organization ID resolution.
208
- * Command-center passes Zustand-managed org ID here.
209
- * SDK consumers typically omit this (auto-resolved from JWT/API key).
266
+ * @deprecated Organization ID is now resolved automatically via OrganizationProvider.
267
+ * Accepted for backwards compatibility during migration but no longer used internally.
210
268
  */
211
269
  organizationId?: string | null;
212
270
  /** Custom QueryClient. If omitted, a default is created internally. */
213
271
  queryClient?: QueryClient;
214
272
  /**
215
273
  * API base URL (e.g., 'https://api.elevasis.com' or 'http://localhost:5170').
216
- * When provided, ElevasisProvider composes ApiClientProvider + ElevasisServiceProvider internally.
274
+ * When provided, ElevasisUIProvider composes the full provider stack via ElevasisCoreProvider.
217
275
  * When omitted, no service context is provided (theme-only mode).
218
276
  */
219
277
  apiUrl?: string;
@@ -223,9 +281,8 @@ interface ElevasisProviderProps {
223
281
  */
224
282
  onError?: (endpoint: string, error: Error, details?: ApiErrorDetails) => void;
225
283
  /**
226
- * Override organization readiness check.
227
- * Defaults to `!!organizationId` if not provided.
228
- * Command-center passes `!!currentMembership` for its stricter readiness requirement.
284
+ * @deprecated Organization readiness is now managed internally by OrganizationProvider.
285
+ * Accepted for backwards compatibility but ignored when apiUrl is provided.
229
286
  */
230
287
  isOrganizationReady?: boolean;
231
288
  children: ReactNode;
@@ -3684,6 +3741,34 @@ interface OrgFeatureConfig {
3684
3741
  * Overrides org-level feature config for specific users
3685
3742
  */
3686
3743
  type MembershipFeatureConfig = OrgFeatureConfig;
3744
+ /**
3745
+ * User-global config (stored in users.config)
3746
+ * Training and theme are user-specific, NOT org-specific
3747
+ */
3748
+ interface UserConfig {
3749
+ training?: {
3750
+ enabled?: boolean;
3751
+ allowed_courses?: string[];
3752
+ allowed_course_groups?: CourseGroup[];
3753
+ };
3754
+ theme?: {
3755
+ preset?: 'default' | 'tactical' | 'regal' | 'cyber-volt' | 'aurora' | 'rose-gold' | 'midnight' | 'ember' | 'obsidian' | 'honey' | 'abyss' | 'canopy' | 'slate' | 'cyber-strike' | 'cyber-flux' | 'cyber-void';
3756
+ colorScheme?: 'light' | 'dark' | 'auto';
3757
+ };
3758
+ onboarding?: {
3759
+ completed?: boolean;
3760
+ completedAt?: string;
3761
+ role?: string;
3762
+ primaryUseCase?: string[];
3763
+ experienceLevel?: string;
3764
+ /** Onboarding guide system state (set by checklist/tour system) */
3765
+ guides?: {
3766
+ completedIds?: string[];
3767
+ dismissed?: boolean;
3768
+ completedAt?: string;
3769
+ };
3770
+ };
3771
+ }
3687
3772
 
3688
3773
  /**
3689
3774
  * Organization Membership types based on WorkOS API
@@ -5766,18 +5851,19 @@ declare function TanStackRouterBridge({ children }: {
5766
5851
  /**
5767
5852
  * UI provider for Elevasis-powered applications. Includes Mantine theme integration.
5768
5853
  *
5769
- * Composes: MantineThemeProvider + QueryClientProvider + auth provider +
5770
- * auth bridge. When apiUrl is provided, also composes
5771
- * ApiClientProvider + ElevasisServiceProvider.
5854
+ * A thin Mantine shell around ElevasisCoreProvider. Handles:
5855
+ * - MantineProvider with theme resolution (presets, token overrides, color scheme)
5856
+ * - Google Font injection for preset fonts
5857
+ * - CSS variables resolver
5858
+ * - Mantine notification adapter (wired into NotificationProvider automatically)
5772
5859
  *
5773
- * Supports authkit and oauth modes. apiKey mode will throw until implemented.
5860
+ * All auth, API, profile, organization, and initialization composition is
5861
+ * delegated to ElevasisCoreProvider.
5774
5862
  *
5775
5863
  * @example Command-center (dogfooding)
5776
5864
  * ```tsx
5777
5865
  * <ElevasisUIProvider
5778
5866
  * auth={{ mode: 'authkit', clientId: '...', redirectUri: '/auth-redirect' }}
5779
- * organizationId={currentWorkOSOrganizationId}
5780
- * isOrganizationReady={!!currentMembership}
5781
5867
  * apiUrl={import.meta.env.VITE_API_SERVER}
5782
5868
  * onError={handleApiError}
5783
5869
  * queryClient={queryClient}
@@ -5803,7 +5889,7 @@ declare function TanStackRouterBridge({ children }: {
5803
5889
  * </ElevasisUIProvider>
5804
5890
  * ```
5805
5891
  */
5806
- declare function ElevasisUIProvider({ auth, theme, organizationId, queryClient, apiUrl, onError, isOrganizationReady, children }: ElevasisProviderProps): react_jsx_runtime.JSX.Element;
5892
+ declare function ElevasisUIProvider({ theme, children, ...coreProps }: ElevasisProviderProps): react_jsx_runtime.JSX.Element;
5807
5893
  /** @deprecated Use ElevasisUIProvider instead. Alias kept for backwards compatibility. */
5808
5894
  declare const ElevasisProvider: typeof ElevasisUIProvider;
5809
5895
 
@@ -5814,21 +5900,36 @@ declare const ElevasisProvider: typeof ElevasisUIProvider;
5814
5900
  * variables, set `data-elevasis-scheme`, or load fonts. Consumers that need
5815
5901
  * Elevasis theming should use `ElevasisProvider` (Mantine) instead.
5816
5902
  *
5817
- * Composes: QueryClientProvider + auth provider + auth bridge.
5818
- * When apiUrl is provided, also composes ApiClientProvider + ElevasisServiceProvider.
5903
+ * When `apiUrl` is provided, composes the full provider stack:
5904
+ * QueryClientProvider -> AuthProvider -> ApiClientProvider ->
5905
+ * ElevasisServiceProvider -> ProfileProvider -> OrganizationProvider ->
5906
+ * NotificationProvider -> InitializationProvider
5907
+ *
5908
+ * The `notifications` prop wires a custom adapter (e.g. mantineNotificationAdapter)
5909
+ * into the NotificationProvider. When omitted, the console fallback is used.
5819
5910
  *
5820
5911
  * @example Headless SDK consumer
5821
5912
  * ```tsx
5822
5913
  * <ElevasisCoreProvider
5823
5914
  * auth={{ mode: 'authkit', clientId: '...', redirectUri: '/' }}
5824
- * theme={{ colorScheme: 'dark', preset: 'default' }}
5825
5915
  * apiUrl="https://api.elevasis.com"
5826
5916
  * >
5827
5917
  * <Dashboard />
5828
5918
  * </ElevasisCoreProvider>
5829
5919
  * ```
5920
+ *
5921
+ * @example With custom notification adapter
5922
+ * ```tsx
5923
+ * <ElevasisCoreProvider
5924
+ * auth={{ mode: 'authkit', clientId: '...', redirectUri: '/' }}
5925
+ * apiUrl="https://api.elevasis.com"
5926
+ * notifications={myNotificationAdapter}
5927
+ * >
5928
+ * <Dashboard />
5929
+ * </ElevasisCoreProvider>
5930
+ * ```
5830
5931
  */
5831
- declare function ElevasisCoreProvider({ auth, organizationId, queryClient, apiUrl, onError, isOrganizationReady, children }: ElevasisCoreProviderProps): react_jsx_runtime.JSX.Element;
5932
+ declare function ElevasisCoreProvider({ auth, queryClient, apiUrl, onError, notifications, children }: ElevasisCoreProviderProps): react_jsx_runtime.JSX.Element;
5832
5933
 
5833
5934
  /**
5834
5935
  * Hook to access the ElevasisServiceProvider context.
@@ -5859,6 +5960,20 @@ declare function useElevasisServices(): ElevasisServiceContextValue;
5859
5960
  */
5860
5961
  declare function ElevasisServiceProvider({ apiRequest, organizationId, isReady, children }: ElevasisServiceProviderProps): react_jsx_runtime.JSX.Element;
5861
5962
 
5963
+ /**
5964
+ * Mantine-backed notification adapter.
5965
+ *
5966
+ * Wraps `@mantine/notifications` with the same defaults as `notify.tsx`
5967
+ * (`autoClose: 5000`, `position: 'top-right'`). The `apiError()` method
5968
+ * replicates `showApiErrorNotification` behavior including retryAfter-based
5969
+ * autoClose.
5970
+ *
5971
+ * Use this adapter in Command Center (Mantine-powered) consumers.
5972
+ * Template consumers should omit the NotificationProvider and rely on the
5973
+ * console fallback, or supply their own adapter.
5974
+ */
5975
+ declare const mantineNotificationAdapter: NotificationAdapter;
5976
+
5862
5977
  declare function useCommandQueue({ status, limit, offset, humanCheckpoint, timeRange, priorityMin, priorityMax, }?: {
5863
5978
  status?: TaskStatus;
5864
5979
  limit?: number;
@@ -6529,6 +6644,43 @@ declare function useMarkAllAsRead(): _tanstack_react_query.UseMutationResult<voi
6529
6644
  */
6530
6645
  declare function useNotificationCount(): _tanstack_react_query.UseQueryResult<number, Error>;
6531
6646
 
6647
+ /**
6648
+ * Hook that provides a standardized error notification handler
6649
+ * for use in React Query mutation hooks.
6650
+ *
6651
+ * Delegates to the active NotificationAdapter so it works in any
6652
+ * consumer (Mantine, Sonner, console fallback, etc.)
6653
+ *
6654
+ * @example
6655
+ * ```typescript
6656
+ * const mutation = useMutation({
6657
+ * mutationFn: deleteApiKey,
6658
+ * onError: useErrorNotification()
6659
+ * })
6660
+ * ```
6661
+ */
6662
+ declare function useErrorNotification(): (error: unknown) => void;
6663
+
6664
+ /**
6665
+ * Hook that provides a standardized success notification handler.
6666
+ * Delegates to the active NotificationAdapter.
6667
+ */
6668
+ declare function useSuccessNotification(): (title: string, message: string) => void;
6669
+
6670
+ /**
6671
+ * Hook that provides a standardized warning notification handler.
6672
+ * Delegates to the active NotificationAdapter.
6673
+ */
6674
+ declare function useWarningNotification(): (title: string, message: string) => void;
6675
+
6676
+ /**
6677
+ * Generic batch delete hook. Deletes multiple rows from a Supabase table by ID.
6678
+ *
6679
+ * @param tableName - Supabase table name (e.g. 'acq_social_posts')
6680
+ * @param invalidateQueryKeys - Array of query key prefixes to invalidate on success
6681
+ */
6682
+ declare function useBatchDelete(tableName: string, invalidateQueryKeys: readonly (readonly unknown[])[]): _tanstack_react_query.UseMutationResult<void, Error, string[], unknown>;
6683
+
6532
6684
  /**
6533
6685
  * Query key factories for observability hooks.
6534
6686
  * Scoped by organizationId for cache isolation between tenants.
@@ -6732,7 +6884,7 @@ declare function useGetExecutionHistory(scheduleId: string | undefined, options?
6732
6884
  executions: {
6733
6885
  id: string;
6734
6886
  createdAt: string;
6735
- status: "running" | "completed" | "failed" | "cancelled";
6887
+ status: "completed" | "failed" | "running" | "cancelled";
6736
6888
  step: number | null;
6737
6889
  itemLabel: string | null;
6738
6890
  duration: number | null;
@@ -6915,43 +7067,394 @@ declare class OperationsService {
6915
7067
  archiveSession(sessionId: string): Promise<void>;
6916
7068
  }
6917
7069
 
6918
- interface AuthAdapter {
6919
- user: {
6920
- id: string;
6921
- } | null;
7070
+ /**
7071
+ * Shared hook for pagination state management.
7072
+ * Encapsulates page state, offset calculation, and reset-on-filter-change.
7073
+ *
7074
+ * @param pageSize - Number of items per page
7075
+ * @param resetDeps - When any dependency changes, page resets to 1. Omit to disable auto-reset.
7076
+ * @param total - When provided, automatically retreats to the last valid page if the current page becomes empty (e.g., after bulk deletion).
7077
+ */
7078
+ declare function usePaginationState(pageSize: number, resetDeps?: unknown[], total?: number): {
7079
+ page: number;
7080
+ setPage: react.Dispatch<react.SetStateAction<number>>;
7081
+ offset: number;
7082
+ totalPages: (total: number) => number;
7083
+ };
7084
+
7085
+ /**
7086
+ * Generic table row selection hook.
7087
+ * Tracks selected IDs, provides toggle/toggleAll/clear, and computes selection state.
7088
+ *
7089
+ * @param items - Current page items (must have `id: string`)
7090
+ * @param allItems - All items across all pages (for "select all" to work across pages). Defaults to `items`.
7091
+ */
7092
+ declare function useTableSelection<T extends {
7093
+ id: string;
7094
+ }>(items: T[], allItems?: T[]): {
7095
+ selectedIds: Set<string>;
7096
+ toggle: (id: string) => void;
7097
+ togglePage: () => void;
7098
+ clear: () => void;
7099
+ isPageAllSelected: boolean;
7100
+ isPagePartiallySelected: boolean;
7101
+ selectedCount: number;
7102
+ isSelected: (id: string) => boolean;
7103
+ };
7104
+
7105
+ type SortDirection = 'asc' | 'desc';
7106
+ interface SortState {
7107
+ column: string;
7108
+ direction: SortDirection;
7109
+ }
7110
+ /**
7111
+ * Generic table sorting hook.
7112
+ * Manages sort column + direction, and provides a sort utility for client-side data.
7113
+ */
7114
+ declare function useTableSort(defaultColumn: string, defaultDirection?: SortDirection): {
7115
+ sort: SortState;
7116
+ toggleSort: (column: string) => void;
7117
+ };
7118
+ /**
7119
+ * Sort an array of items by a column using accessor functions.
7120
+ *
7121
+ * @param data - Array to sort (not mutated)
7122
+ * @param sort - Current sort state
7123
+ * @param accessors - Map of column name → accessor function
7124
+ */
7125
+ declare function sortData<T>(data: T[], sort: SortState, accessors: Record<string, (item: T) => string | number | boolean | null | undefined>): T[];
7126
+ /**
7127
+ * Hook that combines useTableSort with memoized sortData.
7128
+ * Returns the sort state, toggle function, and a memoized sort function.
7129
+ */
7130
+ declare function useSortedData<T>(data: T[], defaultColumn: string, accessors: Record<string, (item: T) => string | number | boolean | null | undefined>, defaultDirection?: SortDirection): {
7131
+ sorted: T[];
7132
+ sort: SortState;
7133
+ toggleSort: (column: string) => void;
7134
+ };
7135
+
7136
+ /**
7137
+ * Type for the useOrganizations hook return value
7138
+ */
7139
+ interface UseOrganizationsReturn {
7140
+ currentWorkOSOrganizationId: string | null;
7141
+ currentMembership: MembershipWithDetails | null;
7142
+ setCurrentWorkOSOrganizationId: (id: string | null) => void;
7143
+ setCurrentMembership: (membership: MembershipWithDetails | null) => void;
7144
+ setOrganizationsInitializing: (initializing: boolean) => void;
7145
+ setOrganizationsLoading: (loading: boolean) => void;
7146
+ setOrganizationsError: (error: string | null) => void;
7147
+ organizations: {
7148
+ isInitializing: boolean;
7149
+ isOrgRefreshing: boolean;
7150
+ error: string | null;
7151
+ };
7152
+ }
7153
+ /**
7154
+ * Type for the useApiClient hook return value
7155
+ */
7156
+ interface UseApiClientReturn {
7157
+ apiRequest: <T = unknown>(path: string, options?: RequestInit) => Promise<T>;
7158
+ }
7159
+ /**
7160
+ * Return type for useOrgInitialization hook
7161
+ */
7162
+ interface UseOrgInitializationReturn {
7163
+ memberships: MembershipWithDetails[];
7164
+ isInitializing: boolean;
6922
7165
  isLoading: boolean;
6923
- getAccessToken: () => Promise<string>;
6924
- organizationId?: string | null;
7166
+ isInitialized: boolean;
7167
+ error: string | null;
7168
+ currentOrganization: MembershipWithDetails['organization'] | null;
7169
+ retry: () => Promise<void>;
6925
7170
  }
6926
- declare function useAuthContext(): AuthAdapter;
6927
- declare function AuthProvider({ value, children }: {
6928
- value: AuthAdapter;
6929
- children: ReactNode;
6930
- }): react.FunctionComponentElement<react.ProviderProps<AuthAdapter | null>>;
7171
+ /**
7172
+ * Factory function to create a useOrgInitialization hook for your app.
7173
+ *
7174
+ * Usage in app:
7175
+ * ```typescript
7176
+ * import { createUseOrgInitialization } from '@repo/ui/organization'
7177
+ * import { useOrganizations } from './hooks/useOrganizations'
7178
+ * import { useApiClient } from './api/hooks/useApiClient'
7179
+ *
7180
+ * export const useOrgInitialization = createUseOrgInitialization(
7181
+ * useOrganizations,
7182
+ * useApiClient
7183
+ * )
7184
+ * ```
7185
+ *
7186
+ * This pattern allows the shared package to provide the hook logic
7187
+ * while each app provides its own hook instances.
7188
+ */
7189
+ declare function createUseOrgInitialization(useOrganizations: () => UseOrganizationsReturn, useApiClient: () => UseApiClientReturn): () => UseOrgInitializationReturn;
6931
7190
 
7191
+ interface InitializationError {
7192
+ layer: 'auth' | 'profile' | 'organization';
7193
+ message: string;
7194
+ originalError?: Error;
7195
+ }
7196
+ interface AppInitializationState {
7197
+ userReady: boolean;
7198
+ organizationReady: boolean;
7199
+ allReady: boolean;
7200
+ isInitializing: boolean;
7201
+ error: InitializationError | null;
7202
+ retry: () => void;
7203
+ profile: SupabaseUserProfile | null;
7204
+ }
6932
7205
  /**
6933
- * Bridge component that reads WorkOS AuthKit state and provides it
6934
- * via the generic AuthContext. Place inside AuthKitProvider.
7206
+ * Factory function to create a useAppInitialization hook for your app.
6935
7207
  *
6936
- * Narrows WorkOS User to { id: string } -- @repo/ui hooks only need the ID.
6937
- * Uses useMemo to stabilize the user object and prevent unnecessary
6938
- * useEffect re-runs in downstream hooks.
7208
+ * Usage in app:
7209
+ * ```typescript
7210
+ * import { createUseAppInitialization } from '@repo/ui/initialization'
7211
+ * import { useOrgInitialization } from './organization/hooks/useOrgInitialization'
7212
+ *
7213
+ * export const useAppInitialization = createUseAppInitialization(useOrgInitialization)
7214
+ * ```
7215
+ *
7216
+ * This pattern allows the shared package to provide the hook logic
7217
+ * while each app provides its own hook instances.
6939
7218
  */
6940
- declare function WorkOSAuthBridge({ children }: {
6941
- children: ReactNode;
6942
- }): react_jsx_runtime.JSX.Element;
7219
+ declare function createUseAppInitialization(useOrgInitialization: () => UseOrgInitializationReturn): () => AppInitializationState;
7220
+
7221
+ /**
7222
+ * The value exposed by OrganizationProvider to all consumers.
7223
+ */
7224
+ interface OrganizationContextValue {
7225
+ /** WorkOS organization ID of the currently selected organization. */
7226
+ currentWorkOSOrganizationId: string | null;
7227
+ /** Supabase (UUID) organization ID of the currently selected organization. */
7228
+ currentSupabaseOrganizationId: string | null;
7229
+ /** Full membership record for the currently selected organization. */
7230
+ currentMembership: MembershipWithDetails | null;
7231
+ /** All memberships for the authenticated user. */
7232
+ memberships: MembershipWithDetails[];
7233
+ /** True while the initial membership list is being fetched. */
7234
+ isInitializing: boolean;
7235
+ /** True while a subsequent org switch / refresh is in flight. */
7236
+ isOrgRefreshing: boolean;
7237
+ /** Error message if the membership fetch or org switch failed. */
7238
+ error: string | null;
7239
+ /**
7240
+ * Switch the active organization.
7241
+ *
7242
+ * Persists the selection to `last_visited_org` on the user profile and
7243
+ * invalidates all org-scoped TanStack Query cache entries.
7244
+ *
7245
+ * @param workosOrgId - WorkOS organization ID to switch to.
7246
+ */
7247
+ switchOrganization: (workosOrgId: string) => void;
7248
+ /**
7249
+ * Re-fetch memberships and retry org selection after an error.
7250
+ */
7251
+ retry: () => Promise<void>;
7252
+ }
7253
+ /**
7254
+ * Consumes the nearest OrganizationProvider.
7255
+ *
7256
+ * @throws {Error} If called outside of an OrganizationProvider tree.
7257
+ */
7258
+ declare function useOrganization(): OrganizationContextValue;
7259
+
7260
+ type RestrictionSource = 'org' | 'membership' | null;
7261
+ interface FeatureAccessResult {
7262
+ allowed: boolean;
7263
+ restrictedBy: RestrictionSource;
7264
+ }
7265
+ /**
7266
+ * Factory that creates a `useFeatureAccess` hook scoped to the consumer's
7267
+ * feature configuration.
7268
+ *
7269
+ * @param useInitialization - Initialization hook providing `profile` and `organizationReady`
7270
+ * @param useOrganization - Organization hook providing `currentMembership`
7271
+ * @param optInFeatures - Feature keys that are disabled by default (must be explicitly enabled)
7272
+ * @param getCoursesByGroup - Resolver that maps a course group name to its course slugs
7273
+ *
7274
+ * @example
7275
+ * ```typescript
7276
+ * // In your app's feature-access module
7277
+ * import { createUseFeatureAccess } from '@repo/ui/hooks'
7278
+ * import { useInitialization } from '@repo/ui/initialization'
7279
+ * import { useOrganization } from '@repo/ui/organization'
7280
+ * import { getCoursesByGroup } from './training/registry'
7281
+ *
7282
+ * export const useFeatureAccess = createUseFeatureAccess({
7283
+ * useInitialization,
7284
+ * useOrganization,
7285
+ * optInFeatures: ['acquisition', 'calibration'],
7286
+ * getCoursesByGroup,
7287
+ * })
7288
+ * ```
7289
+ */
7290
+ declare function createUseFeatureAccess({ useInitialization, useOrganization, optInFeatures, getCoursesByGroup }: {
7291
+ useInitialization: () => Pick<AppInitializationState, 'profile' | 'organizationReady'>;
7292
+ useOrganization: () => Pick<OrganizationContextValue, 'currentMembership'>;
7293
+ optInFeatures?: string[];
7294
+ getCoursesByGroup?: (group: CourseGroup) => string[];
7295
+ }): () => {
7296
+ orgConfig: OrgFeatureConfig | undefined;
7297
+ membershipConfig: OrgFeatureConfig | undefined;
7298
+ userConfig: UserConfig | undefined;
7299
+ hasFeature: (featureKey: string) => boolean;
7300
+ checkFeature: (featureKey: string) => FeatureAccessResult;
7301
+ hasTrainingAccess: () => boolean;
7302
+ getAllowedCourses: () => string[] | null;
7303
+ getResolvedCourseAccess: () => string[] | null;
7304
+ hasAccessToCourse: (courseSlug: string) => boolean;
7305
+ getEnabledGroups: () => CourseGroup[];
7306
+ isReady: boolean;
7307
+ };
6943
7308
 
6944
- interface OAuthContextValue {
7309
+ interface EventSourceMessage {
7310
+ id: string;
7311
+ event: string;
7312
+ data: string;
7313
+ retry?: number;
7314
+ }
7315
+
7316
+ interface FetchEventSourceWithTokenRefreshOptions {
7317
+ url: string;
7318
+ getToken: () => Promise<string | undefined>;
7319
+ headers?: Record<string, string>;
7320
+ signal: AbortSignal;
7321
+ /** Delay in ms before reconnecting after token refresh. Defaults to 2000. */
7322
+ tokenRefreshDelayMs?: number;
7323
+ onopen?: (response: Response) => void | Promise<void>;
7324
+ onmessage?: (event: EventSourceMessage) => void;
7325
+ onerror?: (error: unknown) => void;
7326
+ onclose?: () => void;
7327
+ }
7328
+
7329
+ interface SSEConnectionManagerOptions {
7330
+ /** Grace period in ms before closing idle connections. Defaults to 5000. */
7331
+ closeGracePeriodMs?: number;
7332
+ }
7333
+ /**
7334
+ * SSE Connection Manager
7335
+ *
7336
+ * Ensures only ONE SSE connection exists per endpoint, preventing duplicate
7337
+ * connections when components re-render or remount.
7338
+ *
7339
+ * Benefits:
7340
+ * - Prevents resource waste from duplicate connections
7341
+ * - Eliminates race conditions from overlapping connections
7342
+ * - Automatically manages connection lifecycle
7343
+ * - Shares single connection across multiple subscribers
7344
+ */
7345
+ declare class SSEConnectionManager {
7346
+ private connections;
7347
+ private closeGracePeriodMs;
7348
+ constructor(options?: SSEConnectionManagerOptions);
7349
+ /**
7350
+ * Subscribe to an SSE endpoint
7351
+ *
7352
+ * If a connection already exists for this endpoint, reuses it.
7353
+ * Otherwise, creates a new connection.
7354
+ *
7355
+ * @param key - Unique identifier for the connection (e.g., 'notifications', 'resource-executive-agent')
7356
+ * @param subscriberId - Unique identifier for this subscriber (usually component instance)
7357
+ * @param options - SSE connection options
7358
+ * @returns Unsubscribe function to call when component unmounts
7359
+ */
7360
+ subscribe(key: string, subscriberId: string, options: Omit<FetchEventSourceWithTokenRefreshOptions, 'signal'>): () => void;
7361
+ /**
7362
+ * Unsubscribe from an SSE endpoint
7363
+ *
7364
+ * If this is the last subscriber, closes the connection after grace period.
7365
+ */
7366
+ private unsubscribe;
7367
+ /**
7368
+ * Force close a connection and all its subscribers
7369
+ */
7370
+ closeConnection(key: string): void;
7371
+ /**
7372
+ * Get current connection status
7373
+ */
7374
+ getConnectionInfo(): Map<string, {
7375
+ url: string;
7376
+ subscribers: number;
7377
+ }>;
7378
+ }
7379
+
7380
+ interface UseSSEConnectionOptions {
7381
+ manager: SSEConnectionManager;
7382
+ /** Shared connection key — all subscribers with the same key share ONE connection. */
7383
+ connectionKey: string;
7384
+ url: string;
7385
+ /** When false the subscription is skipped. Defaults to true. */
7386
+ enabled?: boolean;
7387
+ headers?: Record<string, string>;
7388
+ /** Called for each non-empty SSE message with the raw `event.data` string. */
7389
+ onmessage: (data: string) => void;
7390
+ /**
7391
+ * Called when the connection opens. Return a non-empty string to set it as
7392
+ * the error state (e.g. `response.status === 403 ? 'Access denied' : undefined`).
7393
+ */
7394
+ onopen?: (response: Response) => string | void;
7395
+ onerror?: (err: Error) => void;
7396
+ onclose?: () => void;
7397
+ }
7398
+ /**
7399
+ * Generic SSE subscription hook.
7400
+ *
7401
+ * Handles token refresh, connection state, subscriber ID generation, and
7402
+ * subscribe/cleanup lifecycle via the shared SSEConnectionManager.
7403
+ *
7404
+ * Domain-specific event parsing (e.g. `ExecutionSSEEvent`) stays in the
7405
+ * caller's `onmessage` handler.
7406
+ *
7407
+ * @example
7408
+ * ```typescript
7409
+ * const { connected, error } = useSSEConnection({
7410
+ * manager: sseConnectionManager,
7411
+ * connectionKey: `resource-${resourceId}`,
7412
+ * url: `${API_URL}/api/execution-engine/sse/${resourceId}`,
7413
+ * enabled: isOrganizationReady,
7414
+ * headers: { [HTTP_HEADERS.WORKOS_ORGANIZATION_ID]: orgId },
7415
+ * onmessage: (data) => {
7416
+ * const event = JSON.parse(data)
7417
+ * // handle domain-specific event
7418
+ * },
7419
+ * })
7420
+ * ```
7421
+ */
7422
+ declare function useSSEConnection({ manager, connectionKey, url, enabled, headers, onmessage, onopen, onerror, onclose }: UseSSEConnectionOptions): {
7423
+ connected: boolean;
7424
+ error: string | null;
7425
+ };
7426
+
7427
+ interface AuthContextValue {
6945
7428
  user: {
6946
7429
  id: string;
6947
7430
  } | null;
6948
7431
  isLoading: boolean;
6949
- organizationId: string | null;
6950
7432
  getAccessToken: () => Promise<string>;
6951
- error: string | null;
6952
- initiateOAuthFlow: () => void;
7433
+ organizationId?: string | null;
7434
+ /**
7435
+ * Trigger WorkOS AuthKit's sign-in flow (redirect to WorkOS hosted auth page).
7436
+ * Used by ProtectedRoute for auto-recovery when `canRecover()` returns true.
7437
+ */
7438
+ signIn: (options?: {
7439
+ state?: {
7440
+ returnTo?: string;
7441
+ };
7442
+ }) => void;
7443
+ /**
7444
+ * Returns true when a previous session can be recovered (refresh token
7445
+ * exists in storage). ProtectedRoute calls `signIn()` only when this returns
7446
+ * true; otherwise it navigates to the login page.
7447
+ *
7448
+ * Explicit logout clears the stored token, so canRecover() returns false
7449
+ * and the user sees the login page as expected.
7450
+ */
7451
+ canRecover: () => boolean;
6953
7452
  }
6954
- declare function useOAuthContext(): OAuthContextValue;
7453
+ declare function useAuthContext(): AuthContextValue;
7454
+ declare function AuthProvider({ value, children }: {
7455
+ value: AuthContextValue;
7456
+ children: ReactNode;
7457
+ }): react.FunctionComponentElement<react.ProviderProps<AuthContextValue | null>>;
6955
7458
 
6956
7459
  /**
6957
7460
  * Returns a stable reference to getAccessToken that won't change between renders
@@ -6996,6 +7499,120 @@ declare function useStableAccessToken(): () => Promise<string>;
6996
7499
  */
6997
7500
  declare function useSessionCheck(): void;
6998
7501
 
7502
+ interface ProtectedRouteProps {
7503
+ children: ReactNode;
7504
+ /**
7505
+ * Path to redirect to when user is unauthenticated and the auth adapter
7506
+ * does not provide a `signIn` function.
7507
+ * @default '/login'
7508
+ */
7509
+ redirectTo?: string;
7510
+ /**
7511
+ * Rendered while initialization is in progress.
7512
+ * When not provided, nothing is rendered during initialization.
7513
+ */
7514
+ fallback?: ReactNode;
7515
+ /**
7516
+ * Rendered when initialization fails with a non-organization error.
7517
+ * Receives the error and a retry callback.
7518
+ * When not provided, the error is silently swallowed (children not rendered).
7519
+ */
7520
+ errorFallback?: (error: InitializationError, retry: () => void) => ReactNode;
7521
+ /**
7522
+ * When true (default), waits for both user AND organization to be ready
7523
+ * before rendering children. When false, only waits for user readiness.
7524
+ * @default true
7525
+ */
7526
+ waitForOrganization?: boolean;
7527
+ }
7528
+ /**
7529
+ * Headless route guard for authenticated pages.
7530
+ *
7531
+ * Reads initialization state from the nearest InitializationProvider.
7532
+ *
7533
+ * When `canRecover()` returns true (refresh token exists), unauthenticated users
7534
+ * are sent directly to WorkOS AuthKit via `signIn()`. WorkOS checks its
7535
+ * server-side session and either signs the user in immediately (page-reload case)
7536
+ * or shows a login form (logged-out case). Explicit logout destroys the
7537
+ * server-side session, so the next auto-signIn correctly presents a login form
7538
+ * rather than looping.
7539
+ *
7540
+ * When `canRecover()` returns false, falls back to navigating to `redirectTo`
7541
+ * (default: '/login') with a `returnTo` search param.
7542
+ *
7543
+ * Organization-layer errors are allowed through -- routes like /invitations
7544
+ * must be accessible even when the user has no org membership.
7545
+ *
7546
+ * @example
7547
+ * // With custom fallback (your Mantine loader):
7548
+ * <ProtectedRoute fallback={<AppShellLoader />}>
7549
+ * <DashboardPage />
7550
+ * </ProtectedRoute>
7551
+ *
7552
+ * @example
7553
+ * // Wait only for user, not org (e.g. /invitations route):
7554
+ * <ProtectedRoute waitForOrganization={false}>
7555
+ * <InvitationsPage />
7556
+ * </ProtectedRoute>
7557
+ */
7558
+ declare function ProtectedRoute({ children, redirectTo, fallback, errorFallback, waitForOrganization }: ProtectedRouteProps): react_jsx_runtime.JSX.Element | null;
7559
+
7560
+ interface AdminGuardProps {
7561
+ children: ReactNode;
7562
+ /**
7563
+ * Path to redirect non-admin users to.
7564
+ * @default '/'
7565
+ */
7566
+ redirectTo?: string;
7567
+ /**
7568
+ * Rendered while user readiness is being determined.
7569
+ * When not provided, nothing is rendered during initialization.
7570
+ */
7571
+ fallback?: ReactNode;
7572
+ }
7573
+ /**
7574
+ * Headless route guard for platform admin pages.
7575
+ *
7576
+ * Reads `profile.is_platform_admin` from the nearest InitializationProvider.
7577
+ * Non-admin users are redirected to `redirectTo` (default: '/').
7578
+ *
7579
+ * Must be nested inside a ProtectedRoute (or equivalent) so that
7580
+ * `userReady` is guaranteed to be true when this guard runs.
7581
+ *
7582
+ * @example
7583
+ * <ProtectedRoute>
7584
+ * <AdminGuard fallback={<AppShellLoader />}>
7585
+ * <AdminDashboard />
7586
+ * </AdminGuard>
7587
+ * </ProtectedRoute>
7588
+ */
7589
+ declare function AdminGuard({ children, redirectTo, fallback }: AdminGuardProps): react_jsx_runtime.JSX.Element | null;
7590
+
7591
+ interface ProfileContextValue {
7592
+ profile: SupabaseUserProfile | null;
7593
+ loading: boolean;
7594
+ error: Error | null;
7595
+ refetch: () => Promise<void>;
7596
+ }
7597
+ /**
7598
+ * Consumes the nearest ProfileProvider.
7599
+ *
7600
+ * @throws {Error} If called outside of a ProfileProvider tree.
7601
+ */
7602
+ declare function useProfile(): ProfileContextValue;
7603
+ /**
7604
+ * Provides shared profile state to its subtree via React Context.
7605
+ *
7606
+ * Wraps useUserProfile so that all consumers share one profile fetch
7607
+ * instead of each triggering an independent sync call.
7608
+ *
7609
+ * Must be rendered inside the auth and service provider layers so that
7610
+ * the underlying hook can access useAuthContext and useElevasisServices.
7611
+ */
7612
+ declare function ProfileProvider({ children }: {
7613
+ children: ReactNode;
7614
+ }): react.FunctionComponentElement<react.ProviderProps<ProfileContextValue | null>>;
7615
+
6999
7616
  interface UseUserProfileOptions {
7000
7617
  /**
7001
7618
  * Optional error handler for profile sync failures
@@ -7053,6 +7670,24 @@ declare class UserProfileService {
7053
7670
  }>): Promise<SupabaseUserProfile | null>;
7054
7671
  }
7055
7672
 
7673
+ /**
7674
+ * Provides organization state to its subtree via React Context.
7675
+ *
7676
+ * Must be rendered inside:
7677
+ * - ElevasisServiceProvider (needs apiRequest)
7678
+ * - ProfileProvider (needs useProfile for last_visited_org preference)
7679
+ * - A TanStack QueryClientProvider (needs useQueryClient for cache invalidation)
7680
+ *
7681
+ * Behaviors:
7682
+ * - Fetches all memberships for the authenticated user via GET /memberships/my-memberships
7683
+ * - Selects the active org by priority: saved preference > WorkOS org ID > first membership
7684
+ * - Persists org switches to PATCH /users/me { last_visited_org }
7685
+ * - Clears all state when the user signs out (user becomes null)
7686
+ */
7687
+ declare function OrganizationProvider({ children }: {
7688
+ children: ReactNode;
7689
+ }): react.FunctionComponentElement<react.ProviderProps<OrganizationContextValue | null>>;
7690
+
7056
7691
  interface OrganizationsState {
7057
7692
  currentWorkOSOrganizationId: string | null;
7058
7693
  currentSupabaseOrganizationId: string | null;
@@ -7135,61 +7770,6 @@ declare function createUseOrganizations<TStore extends OrganizationsSlice>(useSt
7135
7770
  error: string | null;
7136
7771
  };
7137
7772
 
7138
- /**
7139
- * Type for the useOrganizations hook return value
7140
- */
7141
- interface UseOrganizationsReturn$1 {
7142
- currentWorkOSOrganizationId: string | null;
7143
- currentMembership: MembershipWithDetails | null;
7144
- setCurrentWorkOSOrganizationId: (id: string | null) => void;
7145
- setCurrentMembership: (membership: MembershipWithDetails | null) => void;
7146
- setOrganizationsInitializing: (initializing: boolean) => void;
7147
- setOrganizationsLoading: (loading: boolean) => void;
7148
- setOrganizationsError: (error: string | null) => void;
7149
- organizations: {
7150
- isInitializing: boolean;
7151
- isOrgRefreshing: boolean;
7152
- error: string | null;
7153
- };
7154
- }
7155
- /**
7156
- * Type for the useApiClient hook return value
7157
- */
7158
- interface UseApiClientReturn {
7159
- apiRequest: <T = unknown>(path: string, options?: RequestInit) => Promise<T>;
7160
- }
7161
- /**
7162
- * Return type for useOrgInitialization hook
7163
- */
7164
- interface UseOrgInitializationReturn {
7165
- memberships: MembershipWithDetails[];
7166
- isInitializing: boolean;
7167
- isLoading: boolean;
7168
- isInitialized: boolean;
7169
- error: string | null;
7170
- currentOrganization: MembershipWithDetails['organization'] | null;
7171
- retry: () => Promise<void>;
7172
- }
7173
- /**
7174
- * Factory function to create a useOrgInitialization hook for your app.
7175
- *
7176
- * Usage in app:
7177
- * ```typescript
7178
- * import { createUseOrgInitialization } from '@repo/ui/organization'
7179
- * import { useOrganizations } from './hooks/useOrganizations'
7180
- * import { useApiClient } from './api/hooks/useApiClient'
7181
- *
7182
- * export const useOrgInitialization = createUseOrgInitialization(
7183
- * useOrganizations,
7184
- * useApiClient
7185
- * )
7186
- * ```
7187
- *
7188
- * This pattern allows the shared package to provide the hook logic
7189
- * while each app provides its own hook instances.
7190
- */
7191
- declare function createUseOrgInitialization(useOrganizations: () => UseOrganizationsReturn$1, useApiClient: () => UseApiClientReturn): () => UseOrgInitializationReturn;
7192
-
7193
7773
  type Organization = NonNullable<MembershipWithDetails['organization']>;
7194
7774
  interface OrganizationSwitcherProps {
7195
7775
  currentOrganization: Organization | undefined;
@@ -7229,66 +7809,81 @@ declare function useApiClientContext(): ApiClientContextValue;
7229
7809
  * }
7230
7810
  * ```
7231
7811
  */
7232
- declare function ApiClientProvider({ children, getAccessToken, organizationId, isOrganizationReady, onError }: ApiClientProviderProps): react_jsx_runtime.JSX.Element;
7812
+ declare function ApiClientProvider({ children, getAccessToken, organizationId, getOrganizationId: getOrganizationIdProp, isOrganizationReady, onError }: ApiClientProviderProps): react_jsx_runtime.JSX.Element;
7233
7813
 
7234
7814
  /**
7235
- * Return type of useOrganizations hook (subset needed by useApiClient)
7236
- */
7237
- interface UseOrganizationsReturn {
7238
- isInitializing: boolean;
7239
- isOrgRefreshing: boolean;
7240
- }
7241
- /**
7242
- * Factory function to create a useApiClient hook for your app.
7815
+ * Hook that returns apiRequest and deferredApiRequest bound to the current
7816
+ * ApiClientContext. apiUrl is the only parameter because org ID is resolved
7817
+ * at call time via getOrganizationId() from context.
7243
7818
  *
7244
- * This pattern allows the shared package to provide the hook logic
7245
- * while each app provides its own useOrganizations hook and API URL.
7819
+ * When OrganizationProvider is present in the tree, isOrganizationReady and
7820
+ * isInitializing reflect the live org state (currentWorkOSOrganizationId,
7821
+ * isInitializing, isOrgRefreshing). When OrganizationProvider is absent
7822
+ * (e.g. theme-only mode, testing), the hook falls back to the values from
7823
+ * ApiClientContext.
7246
7824
  *
7247
- * Usage in app:
7825
+ * Usage:
7248
7826
  * ```typescript
7249
- * import { createUseApiClient } from '@repo/ui/api'
7250
- * import { useOrganizations } from './organization/hooks/useOrganizations'
7827
+ * import { useApiClient } from '@repo/ui/api'
7251
7828
  *
7252
7829
  * const API_URL = import.meta.env.VITE_API_SERVER || 'http://localhost:5170'
7253
- * export const useApiClient = createUseApiClient(useOrganizations, API_URL)
7830
+ *
7831
+ * function useMyClient() {
7832
+ * return useApiClient(API_URL)
7833
+ * }
7254
7834
  * ```
7255
7835
  */
7256
- declare function createUseApiClient(useOrganizations: () => UseOrganizationsReturn, apiUrl: string): () => {
7836
+ declare function useApiClient(apiUrl: string): {
7257
7837
  apiRequest: <T>(endpoint: string, options?: RequestInit) => Promise<T>;
7258
7838
  deferredApiRequest: <T>(endpoint: string, options?: RequestInit) => Promise<T>;
7259
7839
  isOrganizationReady: boolean;
7260
7840
  isInitializing: boolean;
7261
7841
  };
7262
7842
 
7263
- interface InitializationError {
7264
- layer: 'auth' | 'profile' | 'organization';
7265
- message: string;
7266
- originalError?: Error;
7267
- }
7268
- interface AppInitializationState {
7269
- userReady: boolean;
7270
- organizationReady: boolean;
7271
- allReady: boolean;
7272
- isInitializing: boolean;
7273
- error: InitializationError | null;
7274
- retry: () => void;
7275
- profile: SupabaseUserProfile | null;
7276
- }
7843
+ declare const InitializationContext: react.Context<AppInitializationState | null>;
7277
7844
  /**
7278
- * Factory function to create a useAppInitialization hook for your app.
7845
+ * Consumes the nearest InitializationProvider.
7279
7846
  *
7280
- * Usage in app:
7281
- * ```typescript
7282
- * import { createUseAppInitialization } from '@repo/ui/initialization'
7283
- * import { useOrgInitialization } from './organization/hooks/useOrgInitialization'
7847
+ * @throws {Error} If called outside of an InitializationProvider tree.
7848
+ */
7849
+ declare function useInitialization(): AppInitializationState;
7850
+ /**
7851
+ * Aggregates auth, profile, and organization state into a single initialization context.
7284
7852
  *
7285
- * export const useAppInitialization = createUseAppInitialization(useOrgInitialization)
7286
- * ```
7853
+ * Must be rendered inside:
7854
+ * - An AuthProvider (needs useAuthContext)
7855
+ * - A ProfileProvider (needs useProfile)
7856
+ * - An OrganizationProvider (needs useOrganization)
7287
7857
  *
7288
- * This pattern allows the shared package to provide the hook logic
7289
- * while each app provides its own hook instances.
7858
+ * Initialization Layers (Sequential):
7859
+ * 1. WorkOS Auth (useAuthContext)
7860
+ * 2. User Profile Sync (useProfile)
7861
+ * 3. Organization Context (useOrganization)
7862
+ *
7863
+ * @example
7864
+ * // Org-scoped pages with data queries (most common)
7865
+ * const { organizationReady } = useInitialization()
7866
+ * const { data, isLoading } = useResources()
7867
+ * if (!organizationReady || isLoading) return <SubshellLoader />
7868
+ *
7869
+ * @example
7870
+ * // Pages accessible without org (invitations, pending)
7871
+ * const { userReady, error } = useInitialization()
7872
+ * if (!userReady) return <SubshellLoader />
7873
+ * if (error?.layer === 'organization') {
7874
+ * return <PendingInvitationPage message={error.message} />
7875
+ * }
7876
+ *
7877
+ * @example
7878
+ * // Pages with error handling
7879
+ * const { organizationReady, error, retry } = useInitialization()
7880
+ * if (error?.layer === 'organization') return <NoOrgError error={error} />
7881
+ * if (error) return <ErrorCard error={error} onRetry={retry} />
7882
+ * if (!organizationReady) return <SubshellLoader />
7290
7883
  */
7291
- declare function createUseAppInitialization(useOrgInitialization: () => UseOrgInitializationReturn): () => AppInitializationState;
7884
+ declare function InitializationProvider({ children }: {
7885
+ children: ReactNode;
7886
+ }): react.FunctionComponentElement<react.ProviderProps<AppInitializationState | null>>;
7292
7887
 
7293
- export { AGENT_CONSTANTS, APIClientError, APIErrorAlert, ActionModal, AgentDefinitionDisplay, AgentExecutionTimeline, AgentExecutionVisualizer, AgentIterationEdge, AgentIterationNode, ApiClientProvider, AuthProvider, BaseEdge, BaseNode, CONTAINER_CONSTANTS, ChatHeader, ChatInputArea, ChatInterface, ChatSidebar, CollapsibleJsonSection, CollapsibleSection, ConfigCard, ConfirmationInputModal, ConfirmationModal, ContextViewer, ContractDisplay, CustomModal, CustomSelector, DetailCardSkeleton, ElevasisCoreProvider, ElevasisProvider, ElevasisServiceProvider, ElevasisUIProvider, EmptyState, EmptyVisualizer, ExecutionLogsTable, ExecutionStats, ExecutionStatusBadge, FormFieldRenderer, GRAPH_CONSTANTS, GlowingHandle, GraphBackground, GraphContainer, GraphFitViewButton, GraphFitViewHandler, GraphLegend, JsonViewer, ListSkeleton, MessageBubble, NavigationButton, NewKnowledgeMapEdge, NewKnowledgeMapGraph, NewKnowledgeMapNode, NotificationBell, NotificationItem, NotificationList, NotificationPanel, OperationsService, OrganizationSwitcher, PageNotFound, PageTitleCaption, ResourceCard, ResourceDefinitionSection, ResourceHealthChart, RouterProvider, SHARED_VIZ_CONSTANTS, STATUS_COLORS, StatCard, StatCardSkeleton, StatsCardSkeleton, StyledMarkdown, TIMELINE_CONSTANTS, TabCountBadge, TanStackRouterBridge, TaskCard, TimeRangeSelector, TimelineAxis, TimelineBar, TimelineContainer, TimelineRow, ToolsListDisplay, TrendIndicator, UnifiedWorkflowEdge, UnifiedWorkflowGraph, UnifiedWorkflowNode, UserProfileService, VisualizerContainer, WORKFLOW_CONSTANTS, WorkOSAuthBridge, WorkflowDefinitionDisplay, WorkflowExecutionTimeline, calculateBarPosition, calculateGraphHeight, catalogItemToResourceDefinition, createCssVariablesResolver, createOrganizationsSlice, createUseApiClient, createUseAppInitialization, createUseOrgInitialization, createUseOrganizations, executionsKeys, formatDate, formatDuration, formatErrorMessage, generateShades, getEdgeColor, getEdgeOpacity, getErrorInfo, getErrorTitle, getGraphBackgroundStyles, getHealthColor, getIcon, getPreset, getResourceColor, getResourceIcon, getResourceStatusColor, getStatusColors, getStatusIcon, iconMap, isAPIClientError, mantineThemeOverride, observabilityKeys, scheduleKeys, shouldAnimateEdge, showApiErrorNotification, showErrorNotification, showInfoNotification, showSuccessNotification, showWarningNotification, useActivities, useActivityTrend, useAgentIterationData, useApiClientContext, useAuthContext, useBulkDeleteExecutions, useBusinessImpact, useCancelExecution, useCancelSchedule, useCommandQueue, useCommandQueueTotals, useConnectionHighlight, useCostBreakdown, useCostByModel, useCostSummary, useCostTrends, useCreateSchedule, useDashboardMetrics, useDeleteExecution, useDeleteSchedule, useDeleteTask, useDirectedChainHighlighting, useElevasisServices, useErrorAnalysis, useErrorDetail, useErrorDetails, useErrorDistribution, useErrorTrends, useExecuteAsync, useExecution, useExecutionHealth, useExecutionLogs, useExecutionPath, useExecutions, useFitViewTrigger, useGetExecutionHistory, useGetSchedule, useGraphBackgroundStyles, useGraphHighlighting, useGraphTheme, useListSchedules, useMarkAllAsRead, useMarkAsRead, useMergedExecution, useNewKnowledgeMapLayout, useNodeSelection, useNotificationCount, useNotifications, useOAuthContext, usePatchTask, usePauseSchedule, useReactFlowAgent, useSessionCheck as useRefocusSessionCheck, useResolveAllErrors, useResolveError, useResolveErrorsByExecution, useResourceDefinition, useResources, useResumeSchedule, useRetryExecution, useRouterContext, useSessionCheck, useStableAccessToken, useSubmitAction, useTimelineData, useTopFailingResources, useUnifiedWorkflowLayout, useUnresolveError, useUpdateAnchor, useUpdateSchedule, useUserProfile, useWorkflowStepsLayout, validateEmail };
7294
- export type { ActivityTrendResponse, AgentIterationEdgeData, AgentIterationNodeData, AgentStatus, ApiClientContextValue, ApiClientProviderProps, ApiErrorDetails, ApiKeyConfig, AppInitializationState, AuthAdapter, AuthConfig, AuthKitConfig, BulkDeleteExecutionsParams, BulkDeleteExecutionsResult, BusinessImpactMetrics, CancelExecutionParams, CancelExecutionResult, ContextViewerProps, CostBreakdownItem, CreateScheduleInput, CreateSessionResponse, DeleteExecutionParams, DirectedChainHighlightingOptions, DirectedChainHighlightingResult, EdgeColorOptions, EdgeOpacityOptions, ElevasisCoreProviderProps, ElevasisCoreThemeConfig, ElevasisProviderProps, ElevasisServiceContextValue, ElevasisServiceProviderProps, ElevasisThemeConfig, ElevasisTokenOverrides, ErrorDistributionItem, ErrorDistributionParams, ErrorFilters, ErrorTrendsParams, ExecuteAsyncParams, ExecuteAsyncResult, ExecutionErrorDetails, ExecutionHistoryItem, ExecutionHistoryResponse, ExecutionLogEntry, ExecutionLogsPageResponse, ExecutionLogsTableProps, ExecutionPathState, ExecutionStatus$1 as ExecutionStatus, FailingResource, FitViewButtonVariant, GlowIntensity, GraphFitViewHandlerProps, GraphHeightOptions, GraphHighlightingResult, GraphMode, GraphThemeColors, InitializationError, JsonViewerProps, KnowledgeMapEdgeData, KnowledgeMapNodeData, LinkProps, ListActivitiesResponse, ListSchedulesFilters, ListSchedulesResponse, NavigationButtonProps, NodeColorType, OAuthConfig, OAuthContextValue, OrganizationsActions, OrganizationsSlice, OrganizationsState, PresetName, ResourcesResponse, RetryExecutionParams, RouterAdapter, SerializedKnowledgeMap, SerializedKnowledgeNode, SessionListItem, StatCardProps, StatusColorScheme, StatusIconColors, StepExecutionData, StyledMarkdownProps, SubmitActionRequest, SubmitActionResponse, TablerIcon, TaskSchedule, ThemePreset, TimelineBarProps, TimelineContainerProps, TimelineRowProps, TopFailingResourcesParams, TrendIndicatorProps, UnifiedWorkflowEdgeData, UnifiedWorkflowNodeData, UpdateScheduleInput, UseActivitiesParams, UseActivityTrendParams, UseApiClientReturn, UseExecutionHealthParams, UseExecutionLogsParams, UseOrgInitializationReturn, UseOrganizationsReturn$1 as UseOrganizationsReturn, UseUserProfileReturn, WithSchemes, WorkflowEdgeType, WorkflowStepEdgeData, WorkflowStepNodeData, WorkflowStepsLayoutInput };
7888
+ export { AGENT_CONSTANTS, APIClientError, APIErrorAlert, ActionModal, AdminGuard, AgentDefinitionDisplay, AgentExecutionTimeline, AgentExecutionVisualizer, AgentIterationEdge, AgentIterationNode, ApiClientProvider, AuthProvider, BaseEdge, BaseNode, CONTAINER_CONSTANTS, ChatHeader, ChatInputArea, ChatInterface, ChatSidebar, CollapsibleJsonSection, CollapsibleSection, ConfigCard, ConfirmationInputModal, ConfirmationModal, ContextViewer, ContractDisplay, CustomModal, CustomSelector, DetailCardSkeleton, ElevasisCoreProvider, ElevasisProvider, ElevasisServiceProvider, ElevasisUIProvider, EmptyState, EmptyVisualizer, ExecutionLogsTable, ExecutionStats, ExecutionStatusBadge, FormFieldRenderer, GRAPH_CONSTANTS, GlowingHandle, GraphBackground, GraphContainer, GraphFitViewButton, GraphFitViewHandler, GraphLegend, InitializationContext, InitializationProvider, JsonViewer, ListSkeleton, MessageBubble, NavigationButton, NewKnowledgeMapEdge, NewKnowledgeMapGraph, NewKnowledgeMapNode, NotificationBell, NotificationItem, NotificationList, NotificationPanel, NotificationProvider, OperationsService, OrganizationProvider, OrganizationSwitcher, PageNotFound, PageTitleCaption, ProfileProvider, ProtectedRoute, ResourceCard, ResourceDefinitionSection, ResourceHealthChart, RouterProvider, SHARED_VIZ_CONSTANTS, STATUS_COLORS, StatCard, StatCardSkeleton, StatsCardSkeleton, StyledMarkdown, TIMELINE_CONSTANTS, TabCountBadge, TanStackRouterBridge, TaskCard, TimeRangeSelector, TimelineAxis, TimelineBar, TimelineContainer, TimelineRow, ToolsListDisplay, TrendIndicator, UnifiedWorkflowEdge, UnifiedWorkflowGraph, UnifiedWorkflowNode, UserProfileService, VisualizerContainer, WORKFLOW_CONSTANTS, WorkflowDefinitionDisplay, WorkflowExecutionTimeline, calculateBarPosition, calculateGraphHeight, catalogItemToResourceDefinition, createCssVariablesResolver, createOrganizationsSlice, createUseAppInitialization, createUseFeatureAccess, createUseOrgInitialization, createUseOrganizations, executionsKeys, formatDate, formatDuration, formatErrorMessage, generateShades, getEdgeColor, getEdgeOpacity, getErrorInfo, getErrorTitle, getGraphBackgroundStyles, getHealthColor, getIcon, getPreset, getResourceColor, getResourceIcon, getResourceStatusColor, getStatusColors, getStatusIcon, iconMap, isAPIClientError, mantineNotificationAdapter, mantineThemeOverride, observabilityKeys, scheduleKeys, shouldAnimateEdge, showApiErrorNotification, showErrorNotification, showInfoNotification, showSuccessNotification, showWarningNotification, sortData, useActivities, useActivityTrend, useAgentIterationData, useApiClient, useApiClientContext, useAuthContext, useBatchDelete, useBulkDeleteExecutions, useBusinessImpact, useCancelExecution, useCancelSchedule, useCommandQueue, useCommandQueueTotals, useConnectionHighlight, useCostBreakdown, useCostByModel, useCostSummary, useCostTrends, useCreateSchedule, useDashboardMetrics, useDeleteExecution, useDeleteSchedule, useDeleteTask, useDirectedChainHighlighting, useElevasisServices, useErrorAnalysis, useErrorDetail, useErrorDetails, useErrorDistribution, useErrorNotification, useErrorTrends, useExecuteAsync, useExecution, useExecutionHealth, useExecutionLogs, useExecutionPath, useExecutions, useFitViewTrigger, useGetExecutionHistory, useGetSchedule, useGraphBackgroundStyles, useGraphHighlighting, useGraphTheme, useInitialization, useListSchedules, useMarkAllAsRead, useMarkAsRead, useMergedExecution, useNewKnowledgeMapLayout, useNodeSelection, useNotificationAdapter, useNotificationCount, useNotifications, useOrganization, usePaginationState, usePatchTask, usePauseSchedule, useProfile, useReactFlowAgent, useSessionCheck as useRefocusSessionCheck, useResolveAllErrors, useResolveError, useResolveErrorsByExecution, useResourceDefinition, useResources, useResumeSchedule, useRetryExecution, useRouterContext, useSSEConnection, useSessionCheck, useSortedData, useStableAccessToken, useSubmitAction, useSuccessNotification, useTableSelection, useTableSort, useTimelineData, useTopFailingResources, useUnifiedWorkflowLayout, useUnresolveError, useUpdateAnchor, useUpdateSchedule, useUserProfile, useWarningNotification, useWorkflowStepsLayout, validateEmail };
7889
+ export type { ActivityTrendResponse, AdminGuardProps, AgentIterationEdgeData, AgentIterationNodeData, AgentStatus, ApiClientContextValue, ApiClientProviderProps, ApiErrorDetails, ApiKeyConfig, AppInitializationState, AuthConfig, AuthContextValue, AuthKitConfig, BulkDeleteExecutionsParams, BulkDeleteExecutionsResult, BusinessImpactMetrics, CancelExecutionParams, CancelExecutionResult, ContextViewerProps, CostBreakdownItem, CreateScheduleInput, CreateSessionResponse, DeleteExecutionParams, DirectedChainHighlightingOptions, DirectedChainHighlightingResult, EdgeColorOptions, EdgeOpacityOptions, ElevasisCoreProviderProps, ElevasisCoreThemeConfig, ElevasisProviderProps, ElevasisServiceContextValue, ElevasisServiceProviderProps, ElevasisThemeConfig, ElevasisTokenOverrides, ErrorDistributionItem, ErrorDistributionParams, ErrorFilters, ErrorTrendsParams, ExecuteAsyncParams, ExecuteAsyncResult, ExecutionErrorDetails, ExecutionHistoryItem, ExecutionHistoryResponse, ExecutionLogEntry, ExecutionLogsPageResponse, ExecutionLogsTableProps, ExecutionPathState, ExecutionStatus$1 as ExecutionStatus, FailingResource, FitViewButtonVariant, GlowIntensity, GraphFitViewHandlerProps, GraphHeightOptions, GraphHighlightingResult, GraphMode, GraphThemeColors, InitializationError, JsonViewerProps, KnowledgeMapEdgeData, KnowledgeMapNodeData, LinkProps, ListActivitiesResponse, ListSchedulesFilters, ListSchedulesResponse, NavigationButtonProps, NodeColorType, NotificationAdapter, OrganizationContextValue, OrganizationsActions, OrganizationsSlice, OrganizationsState, PresetName, ProfileContextValue, ProtectedRouteProps, ResourcesResponse, RetryExecutionParams, RouterAdapter, SerializedKnowledgeMap, SerializedKnowledgeNode, SessionListItem, SortDirection, SortState, StatCardProps, StatusColorScheme, StatusIconColors, StepExecutionData, StyledMarkdownProps, SubmitActionRequest, SubmitActionResponse, TablerIcon, TaskSchedule, ThemePreset, TimelineBarProps, TimelineContainerProps, TimelineRowProps, TopFailingResourcesParams, TrendIndicatorProps, UnifiedWorkflowEdgeData, UnifiedWorkflowNodeData, UpdateScheduleInput, UseActivitiesParams, UseActivityTrendParams, UseApiClientReturn, UseExecutionHealthParams, UseExecutionLogsParams, UseOrgInitializationReturn, UseOrganizationsReturn, UseSSEConnectionOptions, UseUserProfileReturn, WithSchemes, WorkflowEdgeType, WorkflowStepEdgeData, WorkflowStepNodeData, WorkflowStepsLayoutInput };