@semiont/react-ui 0.4.14 → 0.4.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -12
- package/dist/KnowledgeBaseSessionContext-CpYaCbnC.d.mts +174 -0
- package/dist/{PdfAnnotationCanvas.client-CW6SKH2U.mjs → PdfAnnotationCanvas.client-CHDCGQBR.mjs} +3 -3
- package/dist/{chunk-HNZOXH4L.mjs → chunk-OZICDVH7.mjs} +5 -3
- package/dist/chunk-OZICDVH7.mjs.map +1 -0
- package/dist/chunk-R2U7P4TK.mjs +865 -0
- package/dist/chunk-R2U7P4TK.mjs.map +1 -0
- package/dist/{chunk-BQJWOK4C.mjs → chunk-VN5NY4SN.mjs} +9 -8
- package/dist/chunk-VN5NY4SN.mjs.map +1 -0
- package/dist/index.d.mts +139 -169
- package/dist/index.mjs +2197 -1947
- package/dist/index.mjs.map +1 -1
- package/dist/test-utils.d.mts +13 -62
- package/dist/test-utils.mjs +40 -21
- package/dist/test-utils.mjs.map +1 -1
- package/package.json +5 -3
- package/src/components/ProtectedErrorBoundary.tsx +95 -0
- package/src/components/__tests__/ProtectedErrorBoundary.test.tsx +197 -0
- package/src/components/modals/PermissionDeniedModal.tsx +140 -0
- package/src/components/modals/ReferenceWizardModal.tsx +3 -2
- package/src/components/modals/SessionExpiredModal.tsx +101 -0
- package/src/components/modals/__tests__/PermissionDeniedModal.test.tsx +150 -0
- package/src/components/modals/__tests__/SessionExpiredModal.test.tsx +115 -0
- package/src/components/resource/AnnotationHistory.tsx +5 -6
- package/src/components/resource/HistoryEvent.tsx +7 -7
- package/src/components/resource/__tests__/AnnotationHistory.test.tsx +33 -34
- package/src/components/resource/__tests__/HistoryEvent.test.tsx +17 -19
- package/src/components/resource/__tests__/event-formatting.test.ts +70 -94
- package/src/components/resource/event-formatting.ts +56 -56
- package/src/components/resource/panels/ReferenceEntry.tsx +7 -5
- package/src/components/resource/panels/ResourceInfoPanel.tsx +8 -6
- package/src/components/resource/panels/__tests__/ReferenceEntry.test.tsx +12 -12
- package/src/components/resource/panels/__tests__/ResourceInfoPanel.test.tsx +1 -0
- package/src/features/resource-viewer/__tests__/AnnotationCreationPending.test.tsx +1 -1
- package/src/features/resource-viewer/__tests__/AnnotationDeletionIntegration.test.tsx +4 -4
- package/src/features/resource-viewer/__tests__/AnnotationProgressDismissal.test.tsx +5 -10
- package/src/features/resource-viewer/__tests__/BindFlowIntegration.test.tsx +23 -54
- package/src/features/resource-viewer/__tests__/DetectionFlowBug.test.tsx +6 -6
- package/src/features/resource-viewer/__tests__/DetectionFlowIntegration.test.tsx +7 -19
- package/src/features/resource-viewer/__tests__/ToastNotifications.test.tsx +1 -1
- package/src/features/resource-viewer/__tests__/YieldFlowIntegration.test.tsx +18 -44
- package/src/features/resource-viewer/__tests__/annotation-progress-flow.test.tsx +6 -6
- package/src/features/resource-viewer/components/ResourceViewerPage.tsx +24 -26
- package/dist/TranslationManager-CudgH3gw.d.mts +0 -107
- package/dist/chunk-BQJWOK4C.mjs.map +0 -1
- package/dist/chunk-HNZOXH4L.mjs.map +0 -1
- package/dist/chunk-OL5UST25.mjs +0 -413
- package/dist/chunk-OL5UST25.mjs.map +0 -1
- /package/dist/{PdfAnnotationCanvas.client-CW6SKH2U.mjs.map → PdfAnnotationCanvas.client-CHDCGQBR.mjs.map} +0 -0
package/README.md
CHANGED
|
@@ -74,26 +74,32 @@ Import the styles in your app's main CSS file:
|
|
|
74
74
|
import {
|
|
75
75
|
TranslationProvider,
|
|
76
76
|
ApiClientProvider,
|
|
77
|
-
|
|
77
|
+
KnowledgeBaseSessionProvider,
|
|
78
|
+
ProtectedErrorBoundary,
|
|
79
|
+
SessionExpiredModal,
|
|
80
|
+
PermissionDeniedModal,
|
|
78
81
|
} from '@semiont/react-ui';
|
|
79
82
|
import { QueryClientProvider } from '@tanstack/react-query';
|
|
80
83
|
|
|
81
84
|
function App({ children }) {
|
|
82
85
|
const translationManager = useTranslationManager(); // Your implementation
|
|
83
|
-
const apiClientManager = useApiClientManager(); // Your implementation
|
|
84
|
-
const sessionManager = useSessionManager(); // Your implementation
|
|
85
86
|
const queryClient = new QueryClient();
|
|
86
87
|
|
|
87
88
|
return (
|
|
88
|
-
<
|
|
89
|
-
<
|
|
90
|
-
<ApiClientProvider
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
<TranslationProvider translationManager={translationManager}>
|
|
90
|
+
<QueryClientProvider client={queryClient}>
|
|
91
|
+
<ApiClientProvider baseUrl="https://api.example.com">
|
|
92
|
+
{/* Mount KnowledgeBaseSessionProvider only on protected routes */}
|
|
93
|
+
<KnowledgeBaseSessionProvider>
|
|
94
|
+
<ProtectedErrorBoundary>
|
|
95
|
+
<SessionExpiredModal />
|
|
96
|
+
<PermissionDeniedModal />
|
|
97
|
+
{children}
|
|
98
|
+
</ProtectedErrorBoundary>
|
|
99
|
+
</KnowledgeBaseSessionProvider>
|
|
94
100
|
</ApiClientProvider>
|
|
95
|
-
</
|
|
96
|
-
</
|
|
101
|
+
</QueryClientProvider>
|
|
102
|
+
</TranslationProvider>
|
|
97
103
|
);
|
|
98
104
|
}
|
|
99
105
|
```
|
|
@@ -187,7 +193,7 @@ See [docs/STYLES.md](docs/STYLES.md) for detailed CSS documentation.
|
|
|
187
193
|
|
|
188
194
|
All cross-cutting concerns use the Provider Pattern:
|
|
189
195
|
|
|
190
|
-
- **
|
|
196
|
+
- **KnowledgeBaseSessionProvider** - KB list, active KB, validated session, modal state — one merged provider that's the single source of truth for "which KB and what's the session against it"
|
|
191
197
|
- **TranslationProvider** - Internationalization
|
|
192
198
|
- **ApiClientProvider** - Authenticated API client
|
|
193
199
|
- **OpenResourcesProvider** - Recently opened resources
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
import { components } from '@semiont/core';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Open Resources Manager Interface
|
|
7
|
+
*
|
|
8
|
+
* Manages a list of open resources (documents/files) with persistence.
|
|
9
|
+
* This interface allows apps to provide their own implementation of resource management
|
|
10
|
+
* (localStorage, sessionStorage, database, etc.) while components remain framework-agnostic.
|
|
11
|
+
*
|
|
12
|
+
* Components accept this manager as a prop instead of consuming from Context.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* // In app (e.g., frontend/src/hooks/useOpenResourcesManager.ts)
|
|
17
|
+
* export function useOpenResourcesManager(): OpenResourcesManager {
|
|
18
|
+
* const [openResources, setOpenResources] = useState<OpenResource[]>([]);
|
|
19
|
+
*
|
|
20
|
+
* // Implementation details...
|
|
21
|
+
*
|
|
22
|
+
* return {
|
|
23
|
+
* openResources,
|
|
24
|
+
* addResource,
|
|
25
|
+
* removeResource,
|
|
26
|
+
* updateResourceName,
|
|
27
|
+
* reorderResources
|
|
28
|
+
* };
|
|
29
|
+
* }
|
|
30
|
+
*
|
|
31
|
+
* // Pass to components as props
|
|
32
|
+
* <KnowledgeNavigation openResourcesManager={openResourcesManager} />
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
interface OpenResource {
|
|
36
|
+
/** Unique identifier for the resource */
|
|
37
|
+
id: string;
|
|
38
|
+
/** Display name of the resource */
|
|
39
|
+
name: string;
|
|
40
|
+
/** Timestamp when the resource was opened */
|
|
41
|
+
openedAt: number;
|
|
42
|
+
/** Order/position for manual sorting (optional for backward compatibility) */
|
|
43
|
+
order?: number;
|
|
44
|
+
/** Media type for icon display (e.g., 'application/pdf', 'text/plain') */
|
|
45
|
+
mediaType?: string;
|
|
46
|
+
/** Working-tree URI (e.g. "file://docs/overview.md") — used as tooltip in navigation */
|
|
47
|
+
storageUri?: string;
|
|
48
|
+
}
|
|
49
|
+
interface OpenResourcesManager {
|
|
50
|
+
/** List of currently open resources */
|
|
51
|
+
openResources: OpenResource[];
|
|
52
|
+
/**
|
|
53
|
+
* Add a new resource to the open list or update if already exists
|
|
54
|
+
* @param id - Unique resource identifier
|
|
55
|
+
* @param name - Display name of the resource
|
|
56
|
+
* @param mediaType - Optional media type for icon display
|
|
57
|
+
* @param storageUri - Optional working-tree URI (e.g. "file://docs/overview.md")
|
|
58
|
+
*/
|
|
59
|
+
addResource: (id: string, name: string, mediaType?: string, storageUri?: string) => void;
|
|
60
|
+
/**
|
|
61
|
+
* Remove a resource from the open list
|
|
62
|
+
* @param id - Resource identifier to remove
|
|
63
|
+
*/
|
|
64
|
+
removeResource: (id: string) => void;
|
|
65
|
+
/**
|
|
66
|
+
* Update the display name of an open resource
|
|
67
|
+
* @param id - Resource identifier
|
|
68
|
+
* @param name - New display name
|
|
69
|
+
*/
|
|
70
|
+
updateResourceName: (id: string, name: string) => void;
|
|
71
|
+
/**
|
|
72
|
+
* Reorder resources by moving from one index to another
|
|
73
|
+
* @param oldIndex - Current position index
|
|
74
|
+
* @param newIndex - Desired position index
|
|
75
|
+
*/
|
|
76
|
+
reorderResources: (oldIndex: number, newIndex: number) => void;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* KnowledgeBase — a connection to a Semiont backend instance.
|
|
81
|
+
*
|
|
82
|
+
* Each KB has its own JWT, its own API base URL, and its own session.
|
|
83
|
+
* The user is "authenticated against KB X" — never globally authenticated.
|
|
84
|
+
*/
|
|
85
|
+
interface KnowledgeBase {
|
|
86
|
+
id: string;
|
|
87
|
+
label: string;
|
|
88
|
+
host: string;
|
|
89
|
+
port: number;
|
|
90
|
+
protocol: 'http' | 'https';
|
|
91
|
+
email: string;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Input shape for adding a new KB. The id is generated by the provider.
|
|
95
|
+
*/
|
|
96
|
+
type NewKnowledgeBase = Omit<KnowledgeBase, 'id'>;
|
|
97
|
+
/**
|
|
98
|
+
* Status of the locally-stored credential for a KB. Derived from the
|
|
99
|
+
* presence and validity of the JWT in localStorage.
|
|
100
|
+
*/
|
|
101
|
+
type KbSessionStatus = 'authenticated' | 'expired' | 'signed-out' | 'unreachable';
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Translation management interface
|
|
105
|
+
* Apps implement this to provide translations using their preferred i18n library
|
|
106
|
+
*/
|
|
107
|
+
interface TranslationManager {
|
|
108
|
+
/**
|
|
109
|
+
* Translate a key within a namespace
|
|
110
|
+
* @param namespace - Translation namespace (e.g., 'Toolbar', 'ResourceViewer')
|
|
111
|
+
* @param key - Translation key within the namespace
|
|
112
|
+
* @param params - Optional parameters for interpolation
|
|
113
|
+
* @returns Translated string
|
|
114
|
+
*/
|
|
115
|
+
t: (namespace: string, key: string, params?: Record<string, any>) => string;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
type UserInfo = components['schemas']['UserResponse'];
|
|
119
|
+
interface AuthSession {
|
|
120
|
+
token: string;
|
|
121
|
+
user: UserInfo;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
interface KnowledgeBaseSessionValue {
|
|
125
|
+
knowledgeBases: KnowledgeBase[];
|
|
126
|
+
activeKnowledgeBase: KnowledgeBase | null;
|
|
127
|
+
session: AuthSession | null;
|
|
128
|
+
isLoading: boolean;
|
|
129
|
+
user: UserInfo | null;
|
|
130
|
+
token: string | null;
|
|
131
|
+
isAuthenticated: boolean;
|
|
132
|
+
hasValidBackendToken: boolean;
|
|
133
|
+
isFullyAuthenticated: boolean;
|
|
134
|
+
displayName: string;
|
|
135
|
+
avatarUrl: string | null;
|
|
136
|
+
userDomain: string | undefined;
|
|
137
|
+
isAdmin: boolean;
|
|
138
|
+
isModerator: boolean;
|
|
139
|
+
expiresAt: Date | null;
|
|
140
|
+
sessionExpiredAt: number | null;
|
|
141
|
+
sessionExpiredMessage: string | null;
|
|
142
|
+
permissionDeniedAt: number | null;
|
|
143
|
+
permissionDeniedMessage: string | null;
|
|
144
|
+
addKnowledgeBase: (kb: NewKnowledgeBase, access: string, refresh: string) => KnowledgeBase;
|
|
145
|
+
removeKnowledgeBase: (id: string) => void;
|
|
146
|
+
setActiveKnowledgeBase: (id: string) => void;
|
|
147
|
+
updateKnowledgeBase: (id: string, updates: Partial<Pick<KnowledgeBase, 'label'>>) => void;
|
|
148
|
+
/** Re-auth on an existing KB: store the new tokens and refresh the session. */
|
|
149
|
+
signIn: (id: string, access: string, refresh: string) => void;
|
|
150
|
+
/** Sign out of a KB: clear its stored tokens. If it's the active KB, clear in-memory session too. */
|
|
151
|
+
signOut: (id: string) => void;
|
|
152
|
+
/**
|
|
153
|
+
* Refresh the active KB's access token. Returns the new access token, or
|
|
154
|
+
* null if no refresh token is available or the refresh failed. Concurrent
|
|
155
|
+
* calls deduplicate via an in-flight Promise per KB. Used by the api-client's
|
|
156
|
+
* 401-recovery hook and by the proactive refresh timer.
|
|
157
|
+
*/
|
|
158
|
+
refreshActive: () => Promise<string | null>;
|
|
159
|
+
acknowledgeSessionExpired: () => void;
|
|
160
|
+
acknowledgePermissionDenied: () => void;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Raw context export. Exposed for test utilities that need to construct
|
|
164
|
+
* a mock provider without going through localStorage and JWT validation.
|
|
165
|
+
* Production code should always use {@link useKnowledgeBaseSession} instead.
|
|
166
|
+
*/
|
|
167
|
+
declare const KnowledgeBaseSessionContext: React__default.Context<KnowledgeBaseSessionValue | undefined>;
|
|
168
|
+
|
|
169
|
+
declare function KnowledgeBaseSessionProvider({ children }: {
|
|
170
|
+
children: React__default.ReactNode;
|
|
171
|
+
}): react_jsx_runtime.JSX.Element;
|
|
172
|
+
declare function useKnowledgeBaseSession(): KnowledgeBaseSessionValue;
|
|
173
|
+
|
|
174
|
+
export { type AuthSession as A, type KbSessionStatus as K, type NewKnowledgeBase as N, type OpenResourcesManager as O, type TranslationManager as T, type KnowledgeBase as a, type OpenResource as b, KnowledgeBaseSessionContext as c, KnowledgeBaseSessionProvider as d, type KnowledgeBaseSessionValue as e, useKnowledgeBaseSession as u };
|
package/dist/{PdfAnnotationCanvas.client-CW6SKH2U.mjs → PdfAnnotationCanvas.client-CHDCGQBR.mjs}
RENAMED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
"use client";
|
|
3
3
|
import {
|
|
4
4
|
createHoverHandlers
|
|
5
|
-
} from "./chunk-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-VN5NY4SN.mjs";
|
|
6
|
+
import "./chunk-OZICDVH7.mjs";
|
|
7
7
|
import "./chunk-D4GAAQMM.mjs";
|
|
8
8
|
|
|
9
9
|
// src/components/pdf-annotation/PdfAnnotationCanvas.tsx
|
|
@@ -487,4 +487,4 @@ function PdfAnnotationCanvas({
|
|
|
487
487
|
export {
|
|
488
488
|
PdfAnnotationCanvas
|
|
489
489
|
};
|
|
490
|
-
//# sourceMappingURL=PdfAnnotationCanvas.client-
|
|
490
|
+
//# sourceMappingURL=PdfAnnotationCanvas.client-CHDCGQBR.mjs.map
|
|
@@ -29,6 +29,7 @@ import { jsx as jsx2 } from "react/jsx-runtime";
|
|
|
29
29
|
var ApiClientContext = createContext2(void 0);
|
|
30
30
|
function ApiClientProvider({
|
|
31
31
|
baseUrl: url,
|
|
32
|
+
tokenRefresher,
|
|
32
33
|
children
|
|
33
34
|
}) {
|
|
34
35
|
const eventBus = useEventBus();
|
|
@@ -37,9 +38,10 @@ function ApiClientProvider({
|
|
|
37
38
|
baseUrl: baseUrl(url),
|
|
38
39
|
eventBus,
|
|
39
40
|
// Use no timeout in test environment to avoid AbortController issues with ky + vitest
|
|
40
|
-
...process.env.NODE_ENV !== "test" && { timeout: 3e4 }
|
|
41
|
+
...process.env.NODE_ENV !== "test" && { timeout: 3e4 },
|
|
42
|
+
...tokenRefresher && { tokenRefresher }
|
|
41
43
|
}),
|
|
42
|
-
[url, eventBus]
|
|
44
|
+
[url, eventBus, tokenRefresher]
|
|
43
45
|
);
|
|
44
46
|
return /* @__PURE__ */ jsx2(ApiClientContext.Provider, { value: client, children });
|
|
45
47
|
}
|
|
@@ -57,4 +59,4 @@ export {
|
|
|
57
59
|
ApiClientProvider,
|
|
58
60
|
useApiClient
|
|
59
61
|
};
|
|
60
|
-
//# sourceMappingURL=chunk-
|
|
62
|
+
//# sourceMappingURL=chunk-OZICDVH7.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/contexts/EventBusContext.tsx","../src/contexts/ApiClientContext.tsx"],"sourcesContent":["'use client';\n\nimport { createContext, useContext, useRef, type ReactNode } from 'react';\nimport { EventBus } from '@semiont/core';\n\nconst EventBusContext = createContext<EventBus | null>(null);\n\nexport interface EventBusProviderProps {\n children: ReactNode;\n}\n\n/**\n * Unified event bus provider for all application events.\n *\n * Each provider mount creates a fresh EventBus instance. This means:\n * - Workspace switches (which remount via key prop) get isolated buses\n * - Tests get isolation naturally — no resetEventBusForTesting needed\n *\n * Operation handlers (API calls triggered by events) are set up separately via\n * the useBindFlow hook, which should be called at the resource page level.\n */\nexport function EventBusProvider({ children }: EventBusProviderProps) {\n const eventBusRef = useRef<EventBus | null>(null);\n if (!eventBusRef.current) {\n eventBusRef.current = new EventBus();\n }\n const eventBus = eventBusRef.current;\n\n return (\n <EventBusContext.Provider value={eventBus}>\n {children}\n </EventBusContext.Provider>\n );\n}\n\n/**\n * Hook to access the unified event bus\n *\n * Use this everywhere instead of:\n * - useMakeMeaningEvents()\n * - useNavigationEvents()\n * - useGlobalSettingsEvents()\n *\n * @example\n * ```typescript\n * const eventBus = useEventBus();\n *\n * // Emit any event\n * eventBus.get('beckon:hover').next({ annotationId: '123' });\n * eventBus.get('browse:sidebar-toggle').next(undefined);\n * eventBus.get('settings:theme-changed').next({ theme: 'dark' });\n *\n * // Subscribe to any event\n * useEffect(() => {\n * const unsubscribe = eventBus.on('beckon:hover', ({ annotationId }) => {\n * console.log(annotationId);\n * });\n * return () => unsubscribe();\n * }, []);\n * ```\n */\nexport function useEventBus(): EventBus {\n const eventBus = useContext(EventBusContext);\n if (!eventBus) {\n throw new Error('useEventBus must be used within EventBusProvider');\n }\n return eventBus;\n}\n","'use client';\n\nimport { createContext, useContext, ReactNode, useMemo } from 'react';\nimport { baseUrl } from '@semiont/core';\nimport { SemiontApiClient, type TokenRefresher } from '@semiont/api-client';\nimport { useEventBus } from './EventBusContext';\n\nconst ApiClientContext = createContext<SemiontApiClient | undefined>(undefined);\n\nexport interface ApiClientProviderProps {\n baseUrl: string;\n /**\n * Optional 401-recovery hook. If provided, the api-client will retry\n * requests once with a fresh token when a 401 is encountered. The\n * frontend's protected layouts pass `useKnowledgeBaseSession().refreshActive`\n * here so the api-client can transparently recover from expired access tokens.\n */\n tokenRefresher?: TokenRefresher;\n children: ReactNode;\n}\n\n/**\n * Provider for API client — must be nested inside EventBusProvider.\n * The client is re-created when the baseUrl changes (workspace switch).\n * The EventBus is taken from EventBusContext so client and UI components\n * share the same workspace-scoped bus.\n */\nexport function ApiClientProvider({\n baseUrl: url,\n tokenRefresher,\n children,\n}: ApiClientProviderProps) {\n const eventBus = useEventBus();\n\n const client = useMemo(\n () => new SemiontApiClient({\n baseUrl: baseUrl(url),\n eventBus,\n // Use no timeout in test environment to avoid AbortController issues with ky + vitest\n ...(process.env.NODE_ENV !== 'test' && { timeout: 30000 }),\n ...(tokenRefresher && { tokenRefresher }),\n }),\n [url, eventBus, tokenRefresher]\n );\n\n return (\n <ApiClientContext.Provider value={client}>\n {children}\n </ApiClientContext.Provider>\n );\n}\n\n/**\n * Hook to access the stateless API client singleton\n * Must be used within an ApiClientProvider\n * @returns Stateless SemiontApiClient instance\n */\nexport function useApiClient(): SemiontApiClient {\n const context = useContext(ApiClientContext);\n\n if (context === undefined) {\n throw new Error('useApiClient must be used within an ApiClientProvider');\n }\n\n return context;\n}\n"],"mappings":";;;AAEA,SAAS,eAAe,YAAY,cAA8B;AAClE,SAAS,gBAAgB;AA0BrB;AAxBJ,IAAM,kBAAkB,cAA+B,IAAI;AAgBpD,SAAS,iBAAiB,EAAE,SAAS,GAA0B;AACpE,QAAM,cAAc,OAAwB,IAAI;AAChD,MAAI,CAAC,YAAY,SAAS;AACxB,gBAAY,UAAU,IAAI,SAAS;AAAA,EACrC;AACA,QAAM,WAAW,YAAY;AAE7B,SACE,oBAAC,gBAAgB,UAAhB,EAAyB,OAAO,UAC9B,UACH;AAEJ;AA4BO,SAAS,cAAwB;AACtC,QAAM,WAAW,WAAW,eAAe;AAC3C,MAAI,CAAC,UAAU;AACb,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AACA,SAAO;AACT;;;ACjEA,SAAS,iBAAAA,gBAAe,cAAAC,aAAuB,eAAe;AAC9D,SAAS,eAAe;AACxB,SAAS,wBAA6C;AA0ClD,gBAAAC,YAAA;AAvCJ,IAAM,mBAAmBC,eAA4C,MAAS;AAoBvE,SAAS,kBAAkB;AAAA,EAChC,SAAS;AAAA,EACT;AAAA,EACA;AACF,GAA2B;AACzB,QAAM,WAAW,YAAY;AAE7B,QAAM,SAAS;AAAA,IACb,MAAM,IAAI,iBAAiB;AAAA,MACzB,SAAS,QAAQ,GAAG;AAAA,MACpB;AAAA;AAAA,MAEA,GAAI,QAAQ,IAAI,aAAa,UAAU,EAAE,SAAS,IAAM;AAAA,MACxD,GAAI,kBAAkB,EAAE,eAAe;AAAA,IACzC,CAAC;AAAA,IACD,CAAC,KAAK,UAAU,cAAc;AAAA,EAChC;AAEA,SACE,gBAAAD,KAAC,iBAAiB,UAAjB,EAA0B,OAAO,QAC/B,UACH;AAEJ;AAOO,SAAS,eAAiC;AAC/C,QAAM,UAAUE,YAAW,gBAAgB;AAE3C,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI,MAAM,uDAAuD;AAAA,EACzE;AAEA,SAAO;AACT;","names":["createContext","useContext","jsx","createContext","useContext"]}
|