@semiont/react-ui 0.4.17 → 0.4.19
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/{chunk-FAI3S4BM.mjs → chunk-R4CCMFJH.mjs} +14 -2
- package/dist/chunk-R4CCMFJH.mjs.map +1 -0
- package/dist/index.d.mts +45 -15
- package/dist/index.mjs +10299 -359
- package/dist/index.mjs.map +1 -1
- package/dist/test-utils.mjs +1 -1
- package/package.json +1 -1
- package/src/components/modals/ResourceSearchModal.tsx +69 -57
- package/src/components/modals/SearchModal.tsx +54 -51
- package/src/components/modals/__tests__/ResourceSearchModal.test.tsx +59 -82
- package/src/components/modals/__tests__/SearchModal.search-wiring.test.tsx +221 -0
- package/src/components/resource/event-formatting.ts +0 -6
- package/src/components/resource/panels/ReferenceEntry.tsx +1 -1
- package/src/components/resource/panels/__tests__/ReferenceEntry.test.tsx +1 -1
- package/src/features/resource-discovery/__tests__/ResourceDiscoveryPage.test.tsx +46 -45
- package/src/features/resource-discovery/components/ResourceDiscoveryPage.tsx +23 -29
- package/dist/chunk-FAI3S4BM.mjs.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/contexts/knowledge-base-session/storage.ts","../src/contexts/knowledge-base-session/notify.ts","../src/contexts/KnowledgeBaseSessionContext.tsx","../src/contexts/knowledge-base-session/refresh.ts","../src/components/Toast.tsx","../src/contexts/OpenResourcesContext.tsx","../src/contexts/TranslationContext.tsx"],"sourcesContent":["/**\n * Pure helpers for the KnowledgeBaseSession provider.\n *\n * Contains:\n * - localStorage shape and read/write helpers for KB list, active KB id,\n * and per-KB sessions\n * - JWT expiry parsing and \"is expired\" check\n * - URL/protocol helpers for KB instances\n * - The public `getKbSessionStatus(kbId)` helper that the KB-list UI uses\n * to color status dots without subscribing to context changes\n *\n * No React imports, no module-scoped state, no side effects beyond\n * localStorage. Splitting these out of the provider file makes them\n * unit-testable in isolation and keeps the React provider focused on\n * lifecycle and state.\n */\n\nimport type { KnowledgeBase, KbSessionStatus } from '../../types/knowledge-base';\n\n// ---------- Storage keys ----------\n\nconst SESSION_PREFIX = 'semiont.session.';\nexport const STORAGE_KEY = 'semiont.knowledgeBases';\nexport const ACTIVE_KEY = 'semiont.activeKnowledgeBaseId';\n\n/** Refresh the access token this many milliseconds before it expires. */\nexport const REFRESH_BEFORE_EXP_MS = 5 * 60 * 1000;\n\n/** The shape persisted to localStorage per KB. */\nexport interface StoredSession {\n access: string;\n refresh: string;\n}\n\nexport function sessionKey(kbId: string): string {\n return `${SESSION_PREFIX}${kbId}`;\n}\n\n// ---------- Per-KB session storage ----------\n\nexport function getStoredSession(kbId: string): StoredSession | null {\n const raw = localStorage.getItem(sessionKey(kbId));\n if (!raw) return null;\n try {\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed.access === 'string' && typeof parsed.refresh === 'string') {\n return { access: parsed.access, refresh: parsed.refresh };\n }\n } catch {\n // malformed entry — treat as no session\n }\n return null;\n}\n\nexport function setStoredSession(kbId: string, session: StoredSession): void {\n localStorage.setItem(sessionKey(kbId), JSON.stringify(session));\n}\n\nexport function clearStoredSession(kbId: string): void {\n localStorage.removeItem(sessionKey(kbId));\n}\n\n// ---------- JWT helpers ----------\n\nexport function parseJwtExpiry(token: string): Date | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3 || !parts[1]) return null;\n const payload = JSON.parse(atob(parts[1])) as { exp?: number };\n if (!payload.exp) return null;\n return new Date(payload.exp * 1000);\n } catch {\n return null;\n }\n}\n\nexport function isJwtExpired(token: string): boolean {\n const expiry = parseJwtExpiry(token);\n if (!expiry) return true;\n return expiry.getTime() < Date.now();\n}\n\n// ---------- KB list storage ----------\n\nfunction migrateLegacyEntry(entry: any): KnowledgeBase {\n if (entry.host !== undefined) return entry as KnowledgeBase;\n // Legacy format: { id, label, backendUrl }\n try {\n const url = new URL(entry.backendUrl);\n return {\n id: entry.id,\n label: entry.label,\n host: url.hostname,\n port: parseInt(url.port, 10) || (url.protocol === 'https:' ? 443 : 80),\n protocol: url.protocol === 'https:' ? 'https' : 'http',\n email: '',\n };\n } catch {\n return {\n id: entry.id,\n label: entry.label || 'Unknown',\n host: 'localhost',\n port: 4000,\n protocol: 'http',\n email: '',\n };\n }\n}\n\nexport function loadKnowledgeBases(): KnowledgeBase[] {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) return [];\n const entries = JSON.parse(raw) as any[];\n return entries.map(migrateLegacyEntry);\n } catch {\n return [];\n }\n}\n\nexport function saveKnowledgeBases(knowledgeBases: KnowledgeBase[]): void {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(knowledgeBases));\n}\n\n// ---------- Public pure helpers ----------\n\nexport function defaultProtocol(host: string): 'http' | 'https' {\n return host === 'localhost' || host === '127.0.0.1' ? 'http' : 'https';\n}\n\nexport function kbBackendUrl(kb: KnowledgeBase): string {\n return `${kb.protocol}://${kb.host}:${kb.port}`;\n}\n\n/**\n * Read the locally-stored credential status for a KB. Pure / synchronous —\n * does not subscribe to context changes. Used by KB-list UI to color status\n * dots without requiring re-renders on every tick.\n */\nexport function getKbSessionStatus(kbId: string): KbSessionStatus {\n const stored = getStoredSession(kbId);\n if (!stored) return 'signed-out';\n return isJwtExpired(stored.access) ? 'expired' : 'authenticated';\n}\n\nexport function generateKbId(): string {\n return crypto.randomUUID();\n}\n","/**\n * Module-scoped session-expired / permission-denied notifier.\n *\n * The provider registers itself with this module-scoped slot on mount and\n * unregisters on unmount via {@link registerAuthNotifyHandlers}. Code outside\n * the React tree (notably the React Query QueryCache.onError handler in app\n * providers) calls {@link notifySessionExpired} or {@link notifyPermissionDenied}\n * to reach the active provider.\n *\n * When no provider is mounted (e.g. on the landing page), these calls are\n * no-ops — there is nothing to notify.\n *\n * No React imports — this is plain module state. The provider effect that\n * calls `registerAuthNotifyHandlers` runs inside React but the module itself\n * is React-agnostic.\n */\n\ntype Notify = (message?: string) => void;\n\nlet activeOnSessionExpired: Notify | null = null;\nlet activeOnPermissionDenied: Notify | null = null;\n\nexport function notifySessionExpired(message?: string): void {\n activeOnSessionExpired?.(message);\n}\n\nexport function notifyPermissionDenied(message?: string): void {\n activeOnPermissionDenied?.(message);\n}\n\n/**\n * Install handlers for session-expired and permission-denied notifications.\n * Returns an unregister callback. Intended to be called from a React useEffect\n * with the cleanup callback returned from the effect.\n *\n * Only one provider is expected to be mounted at a time. If a second provider\n * mounts before the first unmounts, its handlers replace the previous ones —\n * the previous provider becomes deaf to notifications. In practice this only\n * happens during the brief window of a React StrictMode double-mount or a\n * test that mounts and unmounts multiple providers rapidly.\n */\nexport function registerAuthNotifyHandlers(handlers: {\n onSessionExpired: Notify;\n onPermissionDenied: Notify;\n}): () => void {\n activeOnSessionExpired = handlers.onSessionExpired;\n activeOnPermissionDenied = handlers.onPermissionDenied;\n return () => {\n activeOnSessionExpired = null;\n activeOnPermissionDenied = null;\n };\n}\n","/**\n * KnowledgeBaseSessionContext — single source of truth for \"which KB and\n * what's the session against it.\"\n *\n * This provider merges what used to be three separate concerns in the\n * frontend (KnowledgeBaseProvider + KnowledgeBaseAuthBridge + AuthProvider)\n * plus the library-side SessionProvider, into one coherent unit.\n *\n * Why merged: a session in this app is always a session against a specific\n * KB. There is no auth without a KB. Switching KBs means switching sessions\n * atomically.\n *\n * What it owns:\n * - The list of configured KBs (persisted to localStorage)\n * - Which KB is currently active (persisted to localStorage)\n * - The validated session (token + user) for the active KB\n * - The \"session expired\" and \"permission denied\" flags that drive the modals\n * - JWT expiry derivations (for the session-timer UI)\n * - Mount-time validation flow with manual 401 recovery\n * - Proactive refresh: a timer that fires before the access token expires\n * - Cross-tab sync: when another tab refreshes or signs out, this tab updates\n *\n * Implementation is split across the `knowledge-base-session/` directory:\n * - `storage.ts` — localStorage shape, JWT helpers, KB list helpers\n * - `refresh.ts` — `performRefresh` and the in-flight Promise dedup map\n * - `notify.ts` — module-scoped notify functions and the register helper\n *\n * Mounting: must be inside `EventBusProvider` and `TranslationProvider` (it\n * uses neither, but the modals it sits next to do). It does NOT depend on\n * any other library context. Mount it inside the protected layout boundary.\n */\n\nimport React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { SemiontApiClient, APIError } from '@semiont/api-client';\nimport { baseUrl, EventBus, accessToken } from '@semiont/core';\nimport type { components } from '@semiont/core';\nimport type {\n KnowledgeBase,\n NewKnowledgeBase,\n} from '../types/knowledge-base';\nimport {\n ACTIVE_KEY,\n REFRESH_BEFORE_EXP_MS,\n clearStoredSession,\n generateKbId,\n getStoredSession,\n isJwtExpired,\n kbBackendUrl,\n loadKnowledgeBases,\n parseJwtExpiry,\n saveKnowledgeBases,\n sessionKey,\n setStoredSession,\n} from './knowledge-base-session/storage';\nimport { performRefresh } from './knowledge-base-session/refresh';\nimport { registerAuthNotifyHandlers } from './knowledge-base-session/notify';\nimport type { StoredSession } from './knowledge-base-session/storage';\n\ntype UserInfo = components['schemas']['UserResponse'];\n\nexport interface AuthSession {\n token: string;\n user: UserInfo;\n}\n\n// Re-export the public surface so consumers can keep importing from this module\nexport {\n defaultProtocol,\n kbBackendUrl,\n getKbSessionStatus,\n} from './knowledge-base-session/storage';\nexport type { StoredSession } from './knowledge-base-session/storage';\nexport {\n notifySessionExpired,\n notifyPermissionDenied,\n} from './knowledge-base-session/notify';\n\n// ---------- Context value ----------\n\ninterface KnowledgeBaseSessionValue {\n // KB list\n knowledgeBases: KnowledgeBase[];\n activeKnowledgeBase: KnowledgeBase | null;\n\n // Session state for the active KB\n session: AuthSession | null;\n isLoading: boolean;\n\n // Derived auth fields (memoized off `session.user`)\n user: UserInfo | null;\n token: string | null;\n isAuthenticated: boolean;\n hasValidBackendToken: boolean;\n isFullyAuthenticated: boolean;\n displayName: string;\n avatarUrl: string | null;\n userDomain: string | undefined;\n isAdmin: boolean;\n isModerator: boolean;\n\n // JWT expiry (derived from session.token)\n expiresAt: Date | null;\n\n // Modal-driving flags\n sessionExpiredAt: number | null;\n sessionExpiredMessage: string | null;\n permissionDeniedAt: number | null;\n permissionDeniedMessage: string | null;\n\n // Mutations\n addKnowledgeBase: (kb: NewKnowledgeBase, access: string, refresh: string) => KnowledgeBase;\n removeKnowledgeBase: (id: string) => void;\n setActiveKnowledgeBase: (id: string) => void;\n updateKnowledgeBase: (id: string, updates: Partial<KnowledgeBase>) => void;\n /** Re-auth on an existing KB: store the new tokens and refresh the session. */\n signIn: (id: string, access: string, refresh: string) => void;\n /** Sign out of a KB: clear its stored tokens. If it's the active KB, clear in-memory session too. */\n signOut: (id: string) => void;\n\n /**\n * Refresh the active KB's access token. Returns the new access token, or\n * null if no refresh token is available or the refresh failed. Concurrent\n * calls deduplicate via an in-flight Promise per KB. Used by the api-client's\n * 401-recovery hook and by the proactive refresh timer.\n */\n refreshActive: () => Promise<string | null>;\n\n // Modal acks\n acknowledgeSessionExpired: () => void;\n acknowledgePermissionDenied: () => void;\n}\n\n/**\n * Raw context export. Exposed for test utilities that need to construct\n * a mock provider without going through localStorage and JWT validation.\n * Production code should always use {@link useKnowledgeBaseSession} instead.\n */\nexport const KnowledgeBaseSessionContext = createContext<KnowledgeBaseSessionValue | undefined>(undefined);\n\nexport type { KnowledgeBaseSessionValue };\n\n// ---------- Provider ----------\n\nexport function KnowledgeBaseSessionProvider({ children }: { children: React.ReactNode }) {\n // KB list and active selection\n const [knowledgeBases, setKnowledgeBases] = useState<KnowledgeBase[]>(() => loadKnowledgeBases());\n const [activeKnowledgeBaseId, setActiveKnowledgeBaseId] = useState<string | null>(() => {\n const saved = localStorage.getItem(ACTIVE_KEY);\n const loaded = loadKnowledgeBases();\n if (saved && loaded.some(kb => kb.id === saved)) return saved;\n return loaded[0]?.id ?? null;\n });\n\n // Session state for the active KB\n const [session, setSession] = useState<AuthSession | null>(null);\n const [isLoading, setIsLoading] = useState<boolean>(() => {\n const id = activeKnowledgeBaseId;\n if (!id) return false;\n const stored = getStoredSession(id);\n if (!stored) return false;\n // We'll either validate (if access fresh) or refresh (if refresh available)\n return !isJwtExpired(stored.access) || stored.refresh != null;\n });\n\n // Modal flags\n const [sessionExpiredAt, setSessionExpiredAt] = useState<number | null>(null);\n const [sessionExpiredMessage, setSessionExpiredMessage] = useState<string | null>(null);\n const [permissionDeniedAt, setPermissionDeniedAt] = useState<number | null>(null);\n const [permissionDeniedMessage, setPermissionDeniedMessage] = useState<string | null>(null);\n\n // Persist KB list and active id\n useEffect(() => {\n saveKnowledgeBases(knowledgeBases);\n }, [knowledgeBases]);\n\n useEffect(() => {\n if (activeKnowledgeBaseId) {\n localStorage.setItem(ACTIVE_KEY, activeKnowledgeBaseId);\n } else {\n localStorage.removeItem(ACTIVE_KEY);\n }\n }, [activeKnowledgeBaseId]);\n\n const activeKnowledgeBase = useMemo(\n () => knowledgeBases.find(kb => kb.id === activeKnowledgeBaseId) ?? null,\n [knowledgeBases, activeKnowledgeBaseId]\n );\n\n // Refs for cross-effect coordination\n const activeKbRef = useRef<KnowledgeBase | null>(activeKnowledgeBase);\n useEffect(() => {\n activeKbRef.current = activeKnowledgeBase;\n }, [activeKnowledgeBase]);\n\n const proactiveRefreshTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n /**\n * Schedule a one-shot timer that fires `REFRESH_BEFORE_EXP_MS` before the\n * given access token expires. Cancels any prior pending timer.\n */\n const scheduleProactiveRefresh = useCallback((accessTokenStr: string) => {\n if (proactiveRefreshTimerRef.current) {\n clearTimeout(proactiveRefreshTimerRef.current);\n proactiveRefreshTimerRef.current = null;\n }\n const expiresAt = parseJwtExpiry(accessTokenStr);\n if (!expiresAt) return;\n const refreshAt = expiresAt.getTime() - REFRESH_BEFORE_EXP_MS;\n const delay = Math.max(0, refreshAt - Date.now());\n proactiveRefreshTimerRef.current = setTimeout(() => {\n proactiveRefreshTimerRef.current = null;\n // Fire-and-forget: refreshActive captures activeKbRef and updates state\n refreshActiveRef.current?.();\n }, delay);\n }, []);\n\n // refreshActive needs to be stable across renders for the api-client wiring\n // and also needs to read fresh activeKnowledgeBase via the ref. We define\n // the function via a ref so callers can capture a stable reference.\n const refreshActiveRef = useRef<(() => Promise<string | null>) | null>(null);\n const refreshActive = useCallback(async (): Promise<string | null> => {\n const kb = activeKbRef.current;\n if (!kb) return null;\n const newAccess = await performRefresh(kb);\n if (newAccess) {\n // Update the in-memory session token so consumers see the new value\n setSession(prev => (prev ? { ...prev, token: newAccess } : prev));\n scheduleProactiveRefresh(newAccess);\n } else {\n // Refresh failed — surface the modal\n setSession(null);\n clearStoredSession(kb.id);\n setSessionExpiredMessage('Your session has expired. Please sign in again.');\n setSessionExpiredAt(Date.now());\n if (proactiveRefreshTimerRef.current) {\n clearTimeout(proactiveRefreshTimerRef.current);\n proactiveRefreshTimerRef.current = null;\n }\n }\n return newAccess;\n }, [scheduleProactiveRefresh]);\n refreshActiveRef.current = refreshActive;\n\n // Mount-time validation. This is the only 401-handling path that does NOT\n // go through the api-client's `tokenRefresher` hook. Two structural reasons:\n //\n // 1. ApiClientProvider hasn't mounted yet — the protected layout mounts\n // ApiClientProvider as a CHILD of this provider, so at validation time\n // the configured api-client (the one with `tokenRefresher`) doesn't\n // exist yet.\n //\n // 2. Even if it did, having the api-client silently recover would mean\n // this effect would never see the 401. But this effect is what BUILDS\n // the session — it needs to know whether validation succeeded so it\n // can either set `session = { token, user }` or surface the modal.\n //\n // So this effect uses a fresh throwaway api-client (no refresher) and\n // handles 401 manually: try one refresh, retry getMe with the new token,\n // surface the modal only if both fail. The duplication with the api-client's\n // beforeRetry hook is structural — do not try to consolidate them.\n useEffect(() => {\n if (!activeKnowledgeBase) {\n setSession(null);\n setIsLoading(false);\n return;\n }\n\n const stored = getStoredSession(activeKnowledgeBase.id);\n if (!stored) {\n setSession(null);\n setIsLoading(false);\n return;\n }\n\n let cancelled = false;\n\n const validate = async (tokenToUse: string) => {\n const client = new SemiontApiClient({\n baseUrl: baseUrl(kbBackendUrl(activeKnowledgeBase)),\n eventBus: new EventBus(),\n });\n try {\n const data = await client.getMe({ auth: accessToken(tokenToUse) });\n if (cancelled) return;\n setSession({ token: tokenToUse, user: data as UserInfo });\n scheduleProactiveRefresh(tokenToUse);\n } catch (error) {\n if (cancelled) return;\n setSession(null);\n if (error instanceof APIError && error.status === 401) {\n // Try one refresh on 401 from getMe before surfacing the modal\n const refreshed = await performRefresh(activeKnowledgeBase);\n if (cancelled) return;\n if (refreshed) {\n return validate(refreshed);\n }\n clearStoredSession(activeKnowledgeBase.id);\n setSessionExpiredMessage('Your session has expired. Please sign in again.');\n setSessionExpiredAt(Date.now());\n }\n } finally {\n if (!cancelled) setIsLoading(false);\n }\n };\n\n setIsLoading(true);\n\n if (isJwtExpired(stored.access)) {\n (async () => {\n const refreshed = await performRefresh(activeKnowledgeBase);\n if (cancelled) return;\n if (refreshed) {\n await validate(refreshed);\n } else {\n setSession(null);\n clearStoredSession(activeKnowledgeBase.id);\n setIsLoading(false);\n }\n })();\n } else {\n validate(stored.access);\n }\n\n return () => {\n cancelled = true;\n };\n }, [activeKnowledgeBase, scheduleProactiveRefresh]);\n\n // Cancel proactive refresh timer on unmount\n useEffect(() => {\n return () => {\n if (proactiveRefreshTimerRef.current) {\n clearTimeout(proactiveRefreshTimerRef.current);\n proactiveRefreshTimerRef.current = null;\n }\n };\n }, []);\n\n // Cross-tab sync: listen for storage events on the active KB's session key\n useEffect(() => {\n if (!activeKnowledgeBaseId) return;\n const watchKey = sessionKey(activeKnowledgeBaseId);\n const handler = (e: StorageEvent) => {\n if (e.key !== watchKey) return;\n if (!e.newValue) {\n // Token was cleared in another tab\n setSession(null);\n if (proactiveRefreshTimerRef.current) {\n clearTimeout(proactiveRefreshTimerRef.current);\n proactiveRefreshTimerRef.current = null;\n }\n return;\n }\n try {\n const parsed = JSON.parse(e.newValue) as StoredSession;\n if (typeof parsed.access === 'string') {\n // Update our in-memory session token (user info is unchanged)\n setSession(prev => (prev ? { ...prev, token: parsed.access } : prev));\n scheduleProactiveRefresh(parsed.access);\n }\n } catch {\n // Ignore malformed payloads\n }\n };\n window.addEventListener('storage', handler);\n return () => window.removeEventListener('storage', handler);\n }, [activeKnowledgeBaseId, scheduleProactiveRefresh]);\n\n // Register module-scoped notify handlers so the QueryCache 401/403 handlers\n // can reach the active provider instance. Returns a cleanup callback that\n // unregisters the handlers when the active KB id changes or the provider\n // unmounts.\n useEffect(() => {\n return registerAuthNotifyHandlers({\n onSessionExpired: (message) => {\n setSessionExpiredMessage(message ?? 'Your session has expired. Please sign in again.');\n setSessionExpiredAt(Date.now());\n setSession(null);\n if (activeKnowledgeBaseId) {\n clearStoredSession(activeKnowledgeBaseId);\n }\n if (proactiveRefreshTimerRef.current) {\n clearTimeout(proactiveRefreshTimerRef.current);\n proactiveRefreshTimerRef.current = null;\n }\n },\n onPermissionDenied: (message) => {\n setPermissionDeniedMessage(message ?? 'You do not have permission to perform this action.');\n setPermissionDeniedAt(Date.now());\n },\n });\n }, [activeKnowledgeBaseId]);\n\n // Mutations\n const addKnowledgeBase = useCallback((input: NewKnowledgeBase, access: string, refresh: string): KnowledgeBase => {\n const kb: KnowledgeBase = { id: generateKbId(), ...input };\n setStoredSession(kb.id, { access, refresh });\n setKnowledgeBases(prev => [...prev, kb]);\n setActiveKnowledgeBaseId(kb.id);\n return kb;\n }, []);\n\n const removeKnowledgeBase = useCallback((id: string) => {\n clearStoredSession(id);\n setKnowledgeBases(prev => {\n const remaining = prev.filter(kb => kb.id !== id);\n setActiveKnowledgeBaseId(activeId => activeId === id ? (remaining[0]?.id ?? null) : activeId);\n return remaining;\n });\n }, []);\n\n const setActiveKnowledgeBase = useCallback((id: string) => {\n setActiveKnowledgeBaseId(id);\n }, []);\n\n const updateKnowledgeBase = useCallback((id: string, updates: Partial<KnowledgeBase>) => {\n setKnowledgeBases(prev => prev.map(kb => kb.id === id ? { ...kb, ...updates } : kb));\n }, []);\n\n const signIn = useCallback((id: string, access: string, refresh: string) => {\n setStoredSession(id, { access, refresh });\n // Replace the matching KB with a fresh object so the activeKnowledgeBase\n // memo's `find()` returns a new reference, the validation effect re-runs,\n // and the new tokens get used.\n setKnowledgeBases(prev => prev.map(kb => kb.id === id ? { ...kb } : kb));\n setActiveKnowledgeBaseId(id);\n }, []);\n\n const signOut = useCallback((id: string) => {\n clearStoredSession(id);\n setActiveKnowledgeBaseId(activeId => {\n if (activeId === id) {\n setSession(null);\n if (proactiveRefreshTimerRef.current) {\n clearTimeout(proactiveRefreshTimerRef.current);\n proactiveRefreshTimerRef.current = null;\n }\n }\n return activeId;\n });\n // Bump the KB list so consumers reading kbStatus(id) see the change\n setKnowledgeBases(prev => [...prev]);\n }, []);\n\n const acknowledgeSessionExpired = useCallback(() => {\n setSessionExpiredAt(null);\n setSessionExpiredMessage(null);\n }, []);\n\n const acknowledgePermissionDenied = useCallback(() => {\n setPermissionDeniedAt(null);\n setPermissionDeniedMessage(null);\n }, []);\n\n // Tick state forces re-derivation of expiresAt-based fields once a minute,\n // so the session-timer UI updates without each consumer running its own interval.\n const [, setTick] = useState(0);\n useEffect(() => {\n const interval = setInterval(() => setTick(t => t + 1), 30_000);\n return () => clearInterval(interval);\n }, []);\n\n // Derived auth fields\n const value = useMemo<KnowledgeBaseSessionValue>(() => {\n const user = session?.user ?? null;\n const token = session?.token ?? null;\n const expiresAt = token ? parseJwtExpiry(token) : null;\n\n return {\n knowledgeBases,\n activeKnowledgeBase,\n session,\n isLoading,\n user,\n token,\n isAuthenticated: !!session,\n hasValidBackendToken: !!token,\n isFullyAuthenticated: !!session,\n displayName: user?.name ?? user?.email?.split('@')[0] ?? 'User',\n avatarUrl: user?.image ?? null,\n userDomain: user?.domain || user?.email?.split('@')[1],\n isAdmin: user?.isAdmin ?? false,\n isModerator: user?.isModerator ?? false,\n expiresAt,\n sessionExpiredAt,\n sessionExpiredMessage,\n permissionDeniedAt,\n permissionDeniedMessage,\n addKnowledgeBase,\n removeKnowledgeBase,\n setActiveKnowledgeBase,\n updateKnowledgeBase,\n signIn,\n signOut,\n refreshActive,\n acknowledgeSessionExpired,\n acknowledgePermissionDenied,\n };\n }, [\n knowledgeBases,\n activeKnowledgeBase,\n session,\n isLoading,\n sessionExpiredAt,\n sessionExpiredMessage,\n permissionDeniedAt,\n permissionDeniedMessage,\n addKnowledgeBase,\n removeKnowledgeBase,\n setActiveKnowledgeBase,\n updateKnowledgeBase,\n signIn,\n signOut,\n refreshActive,\n acknowledgeSessionExpired,\n acknowledgePermissionDenied,\n ]);\n\n return (\n <KnowledgeBaseSessionContext.Provider value={value}>\n {children}\n </KnowledgeBaseSessionContext.Provider>\n );\n}\n\n// ---------- Hook ----------\n\nexport function useKnowledgeBaseSession(): KnowledgeBaseSessionValue {\n const ctx = useContext(KnowledgeBaseSessionContext);\n if (!ctx) {\n throw new Error(\n 'useKnowledgeBaseSession requires KnowledgeBaseSessionProvider. ' +\n 'This component is rendered outside the auth boundary. ' +\n 'Move it into a protected layout.'\n );\n }\n return ctx;\n}\n","/**\n * Refresh-token coordination for the KnowledgeBaseSession provider.\n *\n * Module-scoped state: an in-flight Promise per KB so concurrent 401s for\n * the same KB deduplicate to a single network call. No React, no provider\n * dependency — the React provider calls `performRefresh(kb)` and the\n * api-client's `tokenRefresher` hook indirectly calls it via the provider's\n * `refreshActive` method.\n */\n\nimport { SemiontApiClient } from '@semiont/api-client';\nimport { baseUrl, EventBus, refreshToken as makeRefreshToken } from '@semiont/core';\nimport type { KnowledgeBase } from '../../types/knowledge-base';\nimport { getStoredSession, setStoredSession, kbBackendUrl } from './storage';\n\n/**\n * One in-flight refresh promise per KB. Ensures concurrent 401s for the same\n * KB deduplicate to a single network call.\n */\nconst inFlightRefreshes: Map<string, Promise<string | null>> = new Map();\n\n/**\n * Refresh the active KB's access token. Returns the new access token, or\n * null if no refresh token is available or the refresh failed.\n *\n * IMPORTANT: this constructs a fresh `SemiontApiClient` *without* a\n * `tokenRefresher`. Do not be tempted to reuse the configured client (e.g.\n * via `useApiClient()` from a layout): a refresh-call returning 401 would\n * recursively re-enter the refresher, calling `/api/tokens/refresh` again,\n * in an infinite loop. The throwaway client deliberately has no recovery\n * path — a 401 here propagates as `null` and surfaces the modal upstream.\n *\n * Concurrent calls for the same KB deduplicate via the in-flight Promise\n * Map keyed by `kb.id`, so simultaneous 401s on different requests trigger\n * only one network round-trip to `/api/tokens/refresh`.\n */\nexport async function performRefresh(kb: KnowledgeBase): Promise<string | null> {\n const existing = inFlightRefreshes.get(kb.id);\n if (existing) return existing;\n\n const promise = (async (): Promise<string | null> => {\n const stored = getStoredSession(kb.id);\n if (!stored) return null;\n\n const client = new SemiontApiClient({\n baseUrl: baseUrl(kbBackendUrl(kb)),\n eventBus: new EventBus(),\n });\n\n try {\n const response = await client.refreshToken(makeRefreshToken(stored.refresh));\n const newAccess = response.access_token;\n if (!newAccess) return null;\n setStoredSession(kb.id, { access: newAccess, refresh: stored.refresh });\n return newAccess;\n } catch {\n return null;\n }\n })();\n\n inFlightRefreshes.set(kb.id, promise);\n try {\n return await promise;\n } finally {\n inFlightRefreshes.delete(kb.id);\n }\n}\n","'use client';\n\nimport React, { useEffect, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport './Toast.css';\n\nexport type ToastType = 'success' | 'error' | 'info' | 'warning';\n\nexport interface ToastMessage {\n id: string;\n message: string;\n type: ToastType;\n duration?: number;\n}\n\ninterface ToastProps {\n toast: ToastMessage;\n onClose: (id: string) => void;\n}\n\nconst icons = {\n success: (\n <svg className=\"semiont-toast-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M5 13l4 4L19 7\" />\n </svg>\n ),\n error: (\n <svg className=\"semiont-toast-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n ),\n warning: (\n <svg className=\"semiont-toast-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z\" />\n </svg>\n ),\n info: (\n <svg className=\"semiont-toast-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n ),\n};\n\nfunction Toast({ toast, onClose }: ToastProps) {\n useEffect(() => {\n const timer = setTimeout(() => {\n onClose(toast.id);\n }, toast.duration || 3000);\n\n return () => clearTimeout(timer);\n }, [toast, onClose]);\n\n return (\n <div\n className=\"semiont-toast\"\n data-variant={toast.type}\n role=\"alert\"\n >\n <div className=\"semiont-toast-icon-wrapper\">{icons[toast.type]}</div>\n <p className=\"semiont-toast-message\">{toast.message}</p>\n <button\n onClick={() => onClose(toast.id)}\n className=\"semiont-toast-close\"\n aria-label=\"Close\"\n >\n <svg className=\"semiont-toast-close-icon\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path strokeLinecap=\"round\" strokeLinejoin=\"round\" strokeWidth={2} d=\"M6 18L18 6M6 6l12 12\" />\n </svg>\n </button>\n </div>\n );\n}\n\ninterface ToastContainerProps {\n toasts: ToastMessage[];\n onClose: (id: string) => void;\n}\n\nexport function ToastContainer({ toasts, onClose }: ToastContainerProps) {\n const [mounted, setMounted] = useState(false);\n\n useEffect(() => {\n setMounted(true);\n return () => setMounted(false);\n }, []);\n\n if (!mounted) return null;\n\n return createPortal(\n <div className=\"semiont-toast-container\">\n {toasts.map((toast) => (\n <Toast key={toast.id} toast={toast} onClose={onClose} />\n ))}\n </div>,\n document.body\n );\n}\n\n// Toast context and hook for global toast management\ninterface ToastContextType {\n showToast: (message: string, type?: ToastType, duration?: number) => void;\n showSuccess: (message: string, duration?: number) => void;\n showError: (message: string, duration?: number) => void;\n showWarning: (message: string, duration?: number) => void;\n showInfo: (message: string, duration?: number) => void;\n}\n\nconst ToastContext = React.createContext<ToastContextType | undefined>(undefined);\n\nexport function ToastProvider({ children }: { children: React.ReactNode }) {\n const [toasts, setToasts] = useState<ToastMessage[]>([]);\n\n const showToast = React.useCallback((message: string, type: ToastType = 'info', duration?: number) => {\n const id = Date.now().toString();\n const newToast: ToastMessage = duration !== undefined\n ? { id, message, type, duration }\n : { id, message, type };\n setToasts((prev) => [...prev, newToast]);\n }, []);\n\n const showSuccess = React.useCallback((message: string, duration?: number) => showToast(message, 'success', duration), [showToast]);\n const showError = React.useCallback((message: string, duration?: number) => showToast(message, 'error', duration), [showToast]);\n const showWarning = React.useCallback((message: string, duration?: number) => showToast(message, 'warning', duration), [showToast]);\n const showInfo = React.useCallback((message: string, duration?: number) => showToast(message, 'info', duration), [showToast]);\n\n const handleClose = React.useCallback((id: string) => {\n setToasts((prev) => prev.filter((toast) => toast.id !== id));\n }, []);\n\n const contextValue = React.useMemo(\n () => ({ showToast, showSuccess, showError, showWarning, showInfo }),\n [showToast, showSuccess, showError, showWarning, showInfo]\n );\n\n return (\n <ToastContext.Provider value={contextValue}>\n {children}\n <ToastContainer toasts={toasts} onClose={handleClose} />\n </ToastContext.Provider>\n );\n}\n\nexport function useToast() {\n const context = React.useContext(ToastContext);\n if (context === undefined) {\n throw new Error('useToast must be used within a ToastProvider');\n }\n return context;\n}","'use client';\n\nimport React, { createContext, useContext } from 'react';\nimport type { OpenResourcesManager } from '../types/OpenResourcesManager';\n\nconst OpenResourcesContext = createContext<OpenResourcesManager | undefined>(undefined);\n\n/**\n * Provider Pattern: Accepts OpenResourcesManager implementation as prop\n * and makes it available to child components via Context.\n *\n * Apps provide their own implementation (localStorage, sessionStorage, database, etc.)\n * and pass it to this provider at the root level.\n *\n * @example\n * ```tsx\n * // In app root\n * const openResourcesManager = useOpenResourcesManager(); // App's implementation\n *\n * <OpenResourcesProvider openResourcesManager={openResourcesManager}>\n * <App />\n * </OpenResourcesProvider>\n * ```\n */\nexport function OpenResourcesProvider({\n openResourcesManager,\n children\n}: {\n openResourcesManager: OpenResourcesManager;\n children: React.ReactNode;\n}) {\n return (\n <OpenResourcesContext.Provider value={openResourcesManager}>\n {children}\n </OpenResourcesContext.Provider>\n );\n}\n\n/**\n * Hook to access OpenResourcesManager from Context\n * Components use this hook to access open resources functionality\n */\nexport function useOpenResources(): OpenResourcesManager {\n const context = useContext(OpenResourcesContext);\n if (context === undefined) {\n throw new Error('useOpenResources must be used within an OpenResourcesProvider');\n }\n return context;\n}","'use client';\n\nimport { createContext, useContext, ReactNode, useState, useEffect, useMemo } from 'react';\nimport type { TranslationManager } from '../types/TranslationManager';\n\n// Static import for default English only - always needed as fallback\nimport enTranslations from '../../translations/en.json';\n\nconst TranslationContext = createContext<TranslationManager | null>(null);\n\n// Cache for dynamically loaded translations\nconst translationCache = new Map<string, any>();\n\n/**\n * Process ICU MessageFormat plural syntax\n * Supports: {count, plural, =0 {text} =1 {text} other {text}}\n */\nfunction processPluralFormat(text: string, params: Record<string, any>): string {\n // Match {paramName, plural, ...} with proper brace counting\n const pluralMatch = text.match(/\\{(\\w+),\\s*plural,\\s*/);\n if (!pluralMatch) {\n return text;\n }\n\n const paramName = pluralMatch[1];\n const count = params[paramName];\n if (count === undefined) {\n return text;\n }\n\n // Find the matching closing brace by counting\n let startPos = pluralMatch[0].length;\n let braceCount = 1; // We're inside the first {\n let endPos = startPos;\n\n for (let i = startPos; i < text.length; i++) {\n if (text[i] === '{') braceCount++;\n else if (text[i] === '}') {\n braceCount--;\n if (braceCount === 0) {\n endPos = i;\n break;\n }\n }\n }\n\n const pluralCases = text.substring(startPos, endPos);\n\n // Parse plural cases: =0 {text} =1 {text} other {text}\n const cases: Record<string, string> = {};\n const caseRegex = /(?:=(\\d+)|(\\w+))\\s*\\{([^}]+)\\}/g;\n let caseMatch;\n\n while ((caseMatch = caseRegex.exec(pluralCases)) !== null) {\n const [, exactNumber, keyword, textContent] = caseMatch;\n const key = exactNumber !== undefined ? `=${exactNumber}` : keyword;\n cases[key] = textContent;\n }\n\n // Select appropriate case\n const exactMatch = cases[`=${count}`];\n if (exactMatch !== undefined) {\n const result = exactMatch.replace(/#/g, String(count));\n return text.substring(0, pluralMatch.index!) + result + text.substring(endPos + 1);\n }\n\n const otherCase = cases['other'];\n if (otherCase !== undefined) {\n const result = otherCase.replace(/#/g, String(count));\n return text.substring(0, pluralMatch.index!) + result + text.substring(endPos + 1);\n }\n\n return text;\n}\n\n// List of available locales (can be extended without importing all files)\nexport const AVAILABLE_LOCALES = [\n 'ar', // Arabic\n 'bn', // Bengali\n 'cs', // Czech\n 'da', // Danish\n 'de', // German\n 'el', // Greek\n 'en', // English\n 'es', // Spanish\n 'fa', // Persian/Farsi\n 'fi', // Finnish\n 'fr', // French\n 'he', // Hebrew\n 'hi', // Hindi\n 'id', // Indonesian\n 'it', // Italian\n 'ja', // Japanese\n 'ko', // Korean\n 'ms', // Malay\n 'nl', // Dutch\n 'no', // Norwegian\n 'pl', // Polish\n 'pt', // Portuguese\n 'ro', // Romanian\n 'sv', // Swedish\n 'th', // Thai\n 'tr', // Turkish\n 'uk', // Ukrainian\n 'vi', // Vietnamese\n 'zh', // Chinese\n] as const;\nexport type AvailableLocale = typeof AVAILABLE_LOCALES[number];\n\n// Lazy load translations for a specific locale\nasync function loadTranslations(locale: string): Promise<any> {\n // Check cache first\n if (translationCache.has(locale)) {\n return translationCache.get(locale);\n }\n\n // English is already loaded statically\n if (locale === 'en') {\n translationCache.set('en', enTranslations);\n return enTranslations;\n }\n\n try {\n // Dynamic import for all other locales\n const translations = await import(`../../translations/${locale}.json`);\n const translationData = translations.default || translations;\n translationCache.set(locale, translationData);\n return translationData;\n } catch (error) {\n console.error(`Failed to load translations for locale: ${locale}`, error);\n // Fall back to English\n return enTranslations;\n }\n}\n\n// Default English translation manager (using static import)\nconst defaultTranslationManager: TranslationManager = {\n t: (namespace: string, key: string, params?: Record<string, any>) => {\n const translations = enTranslations as Record<string, Record<string, string>>;\n const translation = translations[namespace]?.[key];\n\n if (!translation) {\n console.warn(`Translation not found for ${namespace}.${key}`);\n return `${namespace}.${key}`;\n }\n\n // Handle parameter interpolation and plural format\n if (params && typeof translation === 'string') {\n let result = translation;\n // First process plural format\n result = processPluralFormat(result, params);\n // Then handle simple parameter interpolation\n Object.entries(params).forEach(([paramKey, paramValue]) => {\n result = result.replace(new RegExp(`\\\\{\\\\{${paramKey}\\\\}\\\\}`, 'g'), String(paramValue));\n });\n return result;\n }\n\n return translation;\n },\n};\n\nexport interface TranslationProviderProps {\n /**\n * Option 1: Provide a complete TranslationManager implementation\n */\n translationManager?: TranslationManager;\n\n /**\n * Option 2: Use built-in translations by specifying a locale\n * When adding new locales, just add the JSON file and update AVAILABLE_LOCALES\n */\n locale?: string;\n\n /**\n * Loading component to show while translations are being loaded\n * Only relevant when using dynamic locale loading\n */\n loadingComponent?: ReactNode;\n\n children: ReactNode;\n}\n\n/**\n * Provider for translation management with dynamic loading\n *\n * Three modes of operation:\n * 1. No provider: Components use default English strings\n * 2. With locale prop: Dynamically loads translations for that locale\n * 3. With translationManager: Use custom translation implementation\n */\nexport function TranslationProvider({\n translationManager,\n locale,\n loadingComponent = null,\n children,\n}: TranslationProviderProps) {\n const [loadedTranslations, setLoadedTranslations] = useState<any>(null);\n const [isLoading, setIsLoading] = useState(false);\n\n // Load translations when locale changes\n useEffect(() => {\n if (locale && !translationManager) {\n setIsLoading(true);\n loadTranslations(locale)\n .then(translations => {\n setLoadedTranslations(translations);\n setIsLoading(false);\n })\n .catch(error => {\n console.error('Failed to load translations:', error);\n setLoadedTranslations(enTranslations); // Fall back to English\n setIsLoading(false);\n });\n }\n }, [locale, translationManager]);\n\n // Create translation manager from loaded translations\n const localeManager = useMemo<TranslationManager | null>(() => {\n if (!loadedTranslations) return null;\n\n return {\n t: (namespace: string, key: string, params?: Record<string, any>) => {\n const translation = loadedTranslations[namespace]?.[key];\n\n if (!translation) {\n console.warn(`Translation not found for ${namespace}.${key} in locale ${locale}`);\n return `${namespace}.${key}`;\n }\n\n // Handle parameter interpolation and plural format\n if (params && typeof translation === 'string') {\n let result = translation;\n // First process plural format\n result = processPluralFormat(result, params);\n // Then handle simple parameter interpolation\n Object.entries(params).forEach(([paramKey, paramValue]) => {\n result = result.replace(new RegExp(`\\\\{\\\\{${paramKey}\\\\}\\\\}`, 'g'), String(paramValue));\n });\n return result;\n }\n\n return translation;\n },\n };\n }, [loadedTranslations, locale]);\n\n // If custom translation manager provided, use it\n if (translationManager) {\n return (\n <TranslationContext.Provider value={translationManager}>\n {children}\n </TranslationContext.Provider>\n );\n }\n\n // If locale provided and still loading, show loading component\n if (locale && isLoading) {\n return <>{loadingComponent}</>;\n }\n\n // If locale provided and translations loaded, use them\n if (locale && localeManager) {\n return (\n <TranslationContext.Provider value={localeManager}>\n {children}\n </TranslationContext.Provider>\n );\n }\n\n // Default: use English translations\n return (\n <TranslationContext.Provider value={defaultTranslationManager}>\n {children}\n </TranslationContext.Provider>\n );\n}\n\n/**\n * Hook to access translations within a namespace\n *\n * Works in three modes:\n * 1. Without provider: Returns default English translations\n * 2. With provider using locale: Returns dynamically loaded translations for that locale\n * 3. With custom provider: Uses the custom translation manager\n *\n * @param namespace - Translation namespace (e.g., 'Toolbar', 'ResourceViewer')\n * @returns Function to translate keys within the namespace\n */\nexport function useTranslations(namespace: string) {\n const context = useContext(TranslationContext);\n\n // If no context (no provider), use default English translations\n if (!context) {\n return (key: string, params?: Record<string, any>) => {\n const translations = enTranslations as Record<string, Record<string, string>>;\n const translation = translations[namespace]?.[key];\n\n if (!translation) {\n console.warn(`Translation not found for ${namespace}.${key}`);\n return `${namespace}.${key}`;\n }\n\n // Handle parameter interpolation and plural format\n if (params && typeof translation === 'string') {\n let result = translation;\n // First process plural format\n result = processPluralFormat(result, params);\n // Then handle simple parameter interpolation\n Object.entries(params).forEach(([paramKey, paramValue]) => {\n result = result.replace(new RegExp(`\\\\{\\\\{${paramKey}\\\\}\\\\}`, 'g'), String(paramValue));\n });\n return result;\n }\n\n return translation;\n };\n }\n\n // Return a function that translates keys within this namespace\n return (key: string, params?: Record<string, any>) => context.t(namespace, key, params);\n}\n\n/**\n * Hook to preload translations for a locale\n * Useful for preloading translations before navigation\n */\nexport function usePreloadTranslations() {\n return {\n preload: async (locale: string) => {\n try {\n await loadTranslations(locale);\n return true;\n } catch (error) {\n console.error(`Failed to preload translations for ${locale}:`, error);\n return false;\n }\n },\n isLoaded: (locale: string) => translationCache.has(locale),\n };\n}"],"mappings":";;;;;;;;;AAqBA,IAAM,iBAAiB;AAChB,IAAM,cAAc;AACpB,IAAM,aAAa;AAGnB,IAAM,wBAAwB,IAAI,KAAK;AAQvC,SAAS,WAAW,MAAsB;AAC/C,SAAO,GAAG,cAAc,GAAG,IAAI;AACjC;AAIO,SAAS,iBAAiB,MAAoC;AACnE,QAAM,MAAM,aAAa,QAAQ,WAAW,IAAI,CAAC;AACjD,MAAI,CAAC,IAAK,QAAO;AACjB,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,GAAG;AAC7B,QAAI,UAAU,OAAO,OAAO,WAAW,YAAY,OAAO,OAAO,YAAY,UAAU;AACrF,aAAO,EAAE,QAAQ,OAAO,QAAQ,SAAS,OAAO,QAAQ;AAAA,IAC1D;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AAEO,SAAS,iBAAiB,MAAc,SAA8B;AAC3E,eAAa,QAAQ,WAAW,IAAI,GAAG,KAAK,UAAU,OAAO,CAAC;AAChE;AAEO,SAAS,mBAAmB,MAAoB;AACrD,eAAa,WAAW,WAAW,IAAI,CAAC;AAC1C;AAIO,SAAS,eAAe,OAA4B;AACzD,MAAI;AACF,UAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,QAAI,MAAM,WAAW,KAAK,CAAC,MAAM,CAAC,EAAG,QAAO;AAC5C,UAAM,UAAU,KAAK,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC;AACzC,QAAI,CAAC,QAAQ,IAAK,QAAO;AACzB,WAAO,IAAI,KAAK,QAAQ,MAAM,GAAI;AAAA,EACpC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,aAAa,OAAwB;AACnD,QAAM,SAAS,eAAe,KAAK;AACnC,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OAAO,QAAQ,IAAI,KAAK,IAAI;AACrC;AAIA,SAAS,mBAAmB,OAA2B;AACrD,MAAI,MAAM,SAAS,OAAW,QAAO;AAErC,MAAI;AACF,UAAM,MAAM,IAAI,IAAI,MAAM,UAAU;AACpC,WAAO;AAAA,MACL,IAAI,MAAM;AAAA,MACV,OAAO,MAAM;AAAA,MACb,MAAM,IAAI;AAAA,MACV,MAAM,SAAS,IAAI,MAAM,EAAE,MAAM,IAAI,aAAa,WAAW,MAAM;AAAA,MACnE,UAAU,IAAI,aAAa,WAAW,UAAU;AAAA,MAChD,OAAO;AAAA,IACT;AAAA,EACF,QAAQ;AACN,WAAO;AAAA,MACL,IAAI,MAAM;AAAA,MACV,OAAO,MAAM,SAAS;AAAA,MACtB,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,OAAO;AAAA,IACT;AAAA,EACF;AACF;AAEO,SAAS,qBAAsC;AACpD,MAAI;AACF,UAAM,MAAM,aAAa,QAAQ,WAAW;AAC5C,QAAI,CAAC,IAAK,QAAO,CAAC;AAClB,UAAM,UAAU,KAAK,MAAM,GAAG;AAC9B,WAAO,QAAQ,IAAI,kBAAkB;AAAA,EACvC,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEO,SAAS,mBAAmB,gBAAuC;AACxE,eAAa,QAAQ,aAAa,KAAK,UAAU,cAAc,CAAC;AAClE;AAIO,SAAS,gBAAgB,MAAgC;AAC9D,SAAO,SAAS,eAAe,SAAS,cAAc,SAAS;AACjE;AAEO,SAAS,aAAa,IAA2B;AACtD,SAAO,GAAG,GAAG,QAAQ,MAAM,GAAG,IAAI,IAAI,GAAG,IAAI;AAC/C;AAOO,SAAS,mBAAmB,MAA+B;AAChE,QAAM,SAAS,iBAAiB,IAAI;AACpC,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,aAAa,OAAO,MAAM,IAAI,YAAY;AACnD;AAEO,SAAS,eAAuB;AACrC,SAAO,OAAO,WAAW;AAC3B;;;AChIA,IAAI,yBAAwC;AAC5C,IAAI,2BAA0C;AAEvC,SAAS,qBAAqB,SAAwB;AAC3D,2BAAyB,OAAO;AAClC;AAEO,SAAS,uBAAuB,SAAwB;AAC7D,6BAA2B,OAAO;AACpC;AAaO,SAAS,2BAA2B,UAG5B;AACb,2BAAyB,SAAS;AAClC,6BAA2B,SAAS;AACpC,SAAO,MAAM;AACX,6BAAyB;AACzB,+BAA2B;AAAA,EAC7B;AACF;;;ACnBA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,oBAAAA,mBAAkB,gBAAgB;AAC3C,SAAS,WAAAC,UAAS,YAAAC,WAAU,mBAAmB;;;AChC/C,SAAS,wBAAwB;AACjC,SAAS,SAAS,UAAU,gBAAgB,wBAAwB;AAQpE,IAAM,oBAAyD,oBAAI,IAAI;AAiBvE,eAAsB,eAAe,IAA2C;AAC9E,QAAM,WAAW,kBAAkB,IAAI,GAAG,EAAE;AAC5C,MAAI,SAAU,QAAO;AAErB,QAAM,WAAW,YAAoC;AACnD,UAAM,SAAS,iBAAiB,GAAG,EAAE;AACrC,QAAI,CAAC,OAAQ,QAAO;AAEpB,UAAM,SAAS,IAAI,iBAAiB;AAAA,MAClC,SAAS,QAAQ,aAAa,EAAE,CAAC;AAAA,MACjC,UAAU,IAAI,SAAS;AAAA,IACzB,CAAC;AAED,QAAI;AACF,YAAM,WAAW,MAAM,OAAO,aAAa,iBAAiB,OAAO,OAAO,CAAC;AAC3E,YAAM,YAAY,SAAS;AAC3B,UAAI,CAAC,UAAW,QAAO;AACvB,uBAAiB,GAAG,IAAI,EAAE,QAAQ,WAAW,SAAS,OAAO,QAAQ,CAAC;AACtE,aAAO;AAAA,IACT,QAAQ;AACN,aAAO;AAAA,IACT;AAAA,EACF,GAAG;AAEH,oBAAkB,IAAI,GAAG,IAAI,OAAO;AACpC,MAAI;AACF,WAAO,MAAM;AAAA,EACf,UAAE;AACA,sBAAkB,OAAO,GAAG,EAAE;AAAA,EAChC;AACF;;;AD6cI;AA9XG,IAAM,8BAA8B,cAAqD,MAAS;AAMlG,SAAS,6BAA6B,EAAE,SAAS,GAAkC;AAExF,QAAM,CAAC,gBAAgB,iBAAiB,IAAI,SAA0B,MAAM,mBAAmB,CAAC;AAChG,QAAM,CAAC,uBAAuB,wBAAwB,IAAI,SAAwB,MAAM;AACtF,UAAM,QAAQ,aAAa,QAAQ,UAAU;AAC7C,UAAM,SAAS,mBAAmB;AAClC,QAAI,SAAS,OAAO,KAAK,QAAM,GAAG,OAAO,KAAK,EAAG,QAAO;AACxD,WAAO,OAAO,CAAC,GAAG,MAAM;AAAA,EAC1B,CAAC;AAGD,QAAM,CAAC,SAAS,UAAU,IAAI,SAA6B,IAAI;AAC/D,QAAM,CAAC,WAAW,YAAY,IAAI,SAAkB,MAAM;AACxD,UAAM,KAAK;AACX,QAAI,CAAC,GAAI,QAAO;AAChB,UAAM,SAAS,iBAAiB,EAAE;AAClC,QAAI,CAAC,OAAQ,QAAO;AAEpB,WAAO,CAAC,aAAa,OAAO,MAAM,KAAK,OAAO,WAAW;AAAA,EAC3D,CAAC;AAGD,QAAM,CAAC,kBAAkB,mBAAmB,IAAI,SAAwB,IAAI;AAC5E,QAAM,CAAC,uBAAuB,wBAAwB,IAAI,SAAwB,IAAI;AACtF,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,SAAwB,IAAI;AAChF,QAAM,CAAC,yBAAyB,0BAA0B,IAAI,SAAwB,IAAI;AAG1F,YAAU,MAAM;AACd,uBAAmB,cAAc;AAAA,EACnC,GAAG,CAAC,cAAc,CAAC;AAEnB,YAAU,MAAM;AACd,QAAI,uBAAuB;AACzB,mBAAa,QAAQ,YAAY,qBAAqB;AAAA,IACxD,OAAO;AACL,mBAAa,WAAW,UAAU;AAAA,IACpC;AAAA,EACF,GAAG,CAAC,qBAAqB,CAAC;AAE1B,QAAM,sBAAsB;AAAA,IAC1B,MAAM,eAAe,KAAK,QAAM,GAAG,OAAO,qBAAqB,KAAK;AAAA,IACpE,CAAC,gBAAgB,qBAAqB;AAAA,EACxC;AAGA,QAAM,cAAc,OAA6B,mBAAmB;AACpE,YAAU,MAAM;AACd,gBAAY,UAAU;AAAA,EACxB,GAAG,CAAC,mBAAmB,CAAC;AAExB,QAAM,2BAA2B,OAA6C,IAAI;AAMlF,QAAM,2BAA2B,YAAY,CAAC,mBAA2B;AACvE,QAAI,yBAAyB,SAAS;AACpC,mBAAa,yBAAyB,OAAO;AAC7C,+BAAyB,UAAU;AAAA,IACrC;AACA,UAAM,YAAY,eAAe,cAAc;AAC/C,QAAI,CAAC,UAAW;AAChB,UAAM,YAAY,UAAU,QAAQ,IAAI;AACxC,UAAM,QAAQ,KAAK,IAAI,GAAG,YAAY,KAAK,IAAI,CAAC;AAChD,6BAAyB,UAAU,WAAW,MAAM;AAClD,+BAAyB,UAAU;AAEnC,uBAAiB,UAAU;AAAA,IAC7B,GAAG,KAAK;AAAA,EACV,GAAG,CAAC,CAAC;AAKL,QAAM,mBAAmB,OAA8C,IAAI;AAC3E,QAAM,gBAAgB,YAAY,YAAoC;AACpE,UAAM,KAAK,YAAY;AACvB,QAAI,CAAC,GAAI,QAAO;AAChB,UAAM,YAAY,MAAM,eAAe,EAAE;AACzC,QAAI,WAAW;AAEb,iBAAW,UAAS,OAAO,EAAE,GAAG,MAAM,OAAO,UAAU,IAAI,IAAK;AAChE,+BAAyB,SAAS;AAAA,IACpC,OAAO;AAEL,iBAAW,IAAI;AACf,yBAAmB,GAAG,EAAE;AACxB,+BAAyB,iDAAiD;AAC1E,0BAAoB,KAAK,IAAI,CAAC;AAC9B,UAAI,yBAAyB,SAAS;AACpC,qBAAa,yBAAyB,OAAO;AAC7C,iCAAyB,UAAU;AAAA,MACrC;AAAA,IACF;AACA,WAAO;AAAA,EACT,GAAG,CAAC,wBAAwB,CAAC;AAC7B,mBAAiB,UAAU;AAmB3B,YAAU,MAAM;AACd,QAAI,CAAC,qBAAqB;AACxB,iBAAW,IAAI;AACf,mBAAa,KAAK;AAClB;AAAA,IACF;AAEA,UAAM,SAAS,iBAAiB,oBAAoB,EAAE;AACtD,QAAI,CAAC,QAAQ;AACX,iBAAW,IAAI;AACf,mBAAa,KAAK;AAClB;AAAA,IACF;AAEA,QAAI,YAAY;AAEhB,UAAM,WAAW,OAAO,eAAuB;AAC7C,YAAM,SAAS,IAAIC,kBAAiB;AAAA,QAClC,SAASC,SAAQ,aAAa,mBAAmB,CAAC;AAAA,QAClD,UAAU,IAAIC,UAAS;AAAA,MACzB,CAAC;AACD,UAAI;AACF,cAAM,OAAO,MAAM,OAAO,MAAM,EAAE,MAAM,YAAY,UAAU,EAAE,CAAC;AACjE,YAAI,UAAW;AACf,mBAAW,EAAE,OAAO,YAAY,MAAM,KAAiB,CAAC;AACxD,iCAAyB,UAAU;AAAA,MACrC,SAAS,OAAO;AACd,YAAI,UAAW;AACf,mBAAW,IAAI;AACf,YAAI,iBAAiB,YAAY,MAAM,WAAW,KAAK;AAErD,gBAAM,YAAY,MAAM,eAAe,mBAAmB;AAC1D,cAAI,UAAW;AACf,cAAI,WAAW;AACb,mBAAO,SAAS,SAAS;AAAA,UAC3B;AACA,6BAAmB,oBAAoB,EAAE;AACzC,mCAAyB,iDAAiD;AAC1E,8BAAoB,KAAK,IAAI,CAAC;AAAA,QAChC;AAAA,MACF,UAAE;AACA,YAAI,CAAC,UAAW,cAAa,KAAK;AAAA,MACpC;AAAA,IACF;AAEA,iBAAa,IAAI;AAEjB,QAAI,aAAa,OAAO,MAAM,GAAG;AAC/B,OAAC,YAAY;AACX,cAAM,YAAY,MAAM,eAAe,mBAAmB;AAC1D,YAAI,UAAW;AACf,YAAI,WAAW;AACb,gBAAM,SAAS,SAAS;AAAA,QAC1B,OAAO;AACL,qBAAW,IAAI;AACf,6BAAmB,oBAAoB,EAAE;AACzC,uBAAa,KAAK;AAAA,QACpB;AAAA,MACF,GAAG;AAAA,IACL,OAAO;AACL,eAAS,OAAO,MAAM;AAAA,IACxB;AAEA,WAAO,MAAM;AACX,kBAAY;AAAA,IACd;AAAA,EACF,GAAG,CAAC,qBAAqB,wBAAwB,CAAC;AAGlD,YAAU,MAAM;AACd,WAAO,MAAM;AACX,UAAI,yBAAyB,SAAS;AACpC,qBAAa,yBAAyB,OAAO;AAC7C,iCAAyB,UAAU;AAAA,MACrC;AAAA,IACF;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,YAAU,MAAM;AACd,QAAI,CAAC,sBAAuB;AAC5B,UAAM,WAAW,WAAW,qBAAqB;AACjD,UAAM,UAAU,CAAC,MAAoB;AACnC,UAAI,EAAE,QAAQ,SAAU;AACxB,UAAI,CAAC,EAAE,UAAU;AAEf,mBAAW,IAAI;AACf,YAAI,yBAAyB,SAAS;AACpC,uBAAa,yBAAyB,OAAO;AAC7C,mCAAyB,UAAU;AAAA,QACrC;AACA;AAAA,MACF;AACA,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,EAAE,QAAQ;AACpC,YAAI,OAAO,OAAO,WAAW,UAAU;AAErC,qBAAW,UAAS,OAAO,EAAE,GAAG,MAAM,OAAO,OAAO,OAAO,IAAI,IAAK;AACpE,mCAAyB,OAAO,MAAM;AAAA,QACxC;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AACA,WAAO,iBAAiB,WAAW,OAAO;AAC1C,WAAO,MAAM,OAAO,oBAAoB,WAAW,OAAO;AAAA,EAC5D,GAAG,CAAC,uBAAuB,wBAAwB,CAAC;AAMpD,YAAU,MAAM;AACd,WAAO,2BAA2B;AAAA,MAChC,kBAAkB,CAAC,YAAY;AAC7B,iCAAyB,WAAW,iDAAiD;AACrF,4BAAoB,KAAK,IAAI,CAAC;AAC9B,mBAAW,IAAI;AACf,YAAI,uBAAuB;AACzB,6BAAmB,qBAAqB;AAAA,QAC1C;AACA,YAAI,yBAAyB,SAAS;AACpC,uBAAa,yBAAyB,OAAO;AAC7C,mCAAyB,UAAU;AAAA,QACrC;AAAA,MACF;AAAA,MACA,oBAAoB,CAAC,YAAY;AAC/B,mCAA2B,WAAW,oDAAoD;AAC1F,8BAAsB,KAAK,IAAI,CAAC;AAAA,MAClC;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAAC,qBAAqB,CAAC;AAG1B,QAAM,mBAAmB,YAAY,CAAC,OAAyB,QAAgB,YAAmC;AAChH,UAAM,KAAoB,EAAE,IAAI,aAAa,GAAG,GAAG,MAAM;AACzD,qBAAiB,GAAG,IAAI,EAAE,QAAQ,QAAQ,CAAC;AAC3C,sBAAkB,UAAQ,CAAC,GAAG,MAAM,EAAE,CAAC;AACvC,6BAAyB,GAAG,EAAE;AAC9B,WAAO;AAAA,EACT,GAAG,CAAC,CAAC;AAEL,QAAM,sBAAsB,YAAY,CAAC,OAAe;AACtD,uBAAmB,EAAE;AACrB,sBAAkB,UAAQ;AACxB,YAAM,YAAY,KAAK,OAAO,QAAM,GAAG,OAAO,EAAE;AAChD,+BAAyB,cAAY,aAAa,KAAM,UAAU,CAAC,GAAG,MAAM,OAAQ,QAAQ;AAC5F,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,CAAC;AAEL,QAAM,yBAAyB,YAAY,CAAC,OAAe;AACzD,6BAAyB,EAAE;AAAA,EAC7B,GAAG,CAAC,CAAC;AAEL,QAAM,sBAAsB,YAAY,CAAC,IAAY,YAAoC;AACvF,sBAAkB,UAAQ,KAAK,IAAI,QAAM,GAAG,OAAO,KAAK,EAAE,GAAG,IAAI,GAAG,QAAQ,IAAI,EAAE,CAAC;AAAA,EACrF,GAAG,CAAC,CAAC;AAEL,QAAM,SAAS,YAAY,CAAC,IAAY,QAAgB,YAAoB;AAC1E,qBAAiB,IAAI,EAAE,QAAQ,QAAQ,CAAC;AAIxC,sBAAkB,UAAQ,KAAK,IAAI,QAAM,GAAG,OAAO,KAAK,EAAE,GAAG,GAAG,IAAI,EAAE,CAAC;AACvE,6BAAyB,EAAE;AAAA,EAC7B,GAAG,CAAC,CAAC;AAEL,QAAM,UAAU,YAAY,CAAC,OAAe;AAC1C,uBAAmB,EAAE;AACrB,6BAAyB,cAAY;AACnC,UAAI,aAAa,IAAI;AACnB,mBAAW,IAAI;AACf,YAAI,yBAAyB,SAAS;AACpC,uBAAa,yBAAyB,OAAO;AAC7C,mCAAyB,UAAU;AAAA,QACrC;AAAA,MACF;AACA,aAAO;AAAA,IACT,CAAC;AAED,sBAAkB,UAAQ,CAAC,GAAG,IAAI,CAAC;AAAA,EACrC,GAAG,CAAC,CAAC;AAEL,QAAM,4BAA4B,YAAY,MAAM;AAClD,wBAAoB,IAAI;AACxB,6BAAyB,IAAI;AAAA,EAC/B,GAAG,CAAC,CAAC;AAEL,QAAM,8BAA8B,YAAY,MAAM;AACpD,0BAAsB,IAAI;AAC1B,+BAA2B,IAAI;AAAA,EACjC,GAAG,CAAC,CAAC;AAIL,QAAM,CAAC,EAAE,OAAO,IAAI,SAAS,CAAC;AAC9B,YAAU,MAAM;AACd,UAAM,WAAW,YAAY,MAAM,QAAQ,OAAK,IAAI,CAAC,GAAG,GAAM;AAC9D,WAAO,MAAM,cAAc,QAAQ;AAAA,EACrC,GAAG,CAAC,CAAC;AAGL,QAAM,QAAQ,QAAmC,MAAM;AACrD,UAAM,OAAO,SAAS,QAAQ;AAC9B,UAAM,QAAQ,SAAS,SAAS;AAChC,UAAM,YAAY,QAAQ,eAAe,KAAK,IAAI;AAElD,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,iBAAiB,CAAC,CAAC;AAAA,MACnB,sBAAsB,CAAC,CAAC;AAAA,MACxB,sBAAsB,CAAC,CAAC;AAAA,MACxB,aAAa,MAAM,QAAQ,MAAM,OAAO,MAAM,GAAG,EAAE,CAAC,KAAK;AAAA,MACzD,WAAW,MAAM,SAAS;AAAA,MAC1B,YAAY,MAAM,UAAU,MAAM,OAAO,MAAM,GAAG,EAAE,CAAC;AAAA,MACrD,SAAS,MAAM,WAAW;AAAA,MAC1B,aAAa,MAAM,eAAe;AAAA,MAClC;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF,GAAG;AAAA,IACD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SACE,oBAAC,4BAA4B,UAA5B,EAAqC,OACnC,UACH;AAEJ;AAIO,SAAS,0BAAqD;AACnE,QAAM,MAAM,WAAW,2BAA2B;AAClD,MAAI,CAAC,KAAK;AACR,UAAM,IAAI;AAAA,MACR;AAAA,IAGF;AAAA,EACF;AACA,SAAO;AACT;;;AE/hBA,OAAOC,UAAS,aAAAC,YAAW,YAAAC,iBAAgB;AAC3C,SAAS,oBAAoB;AAoBvB,gBAAAC,MA8BF,YA9BE;AAHN,IAAM,QAAQ;AAAA,EACZ,SACE,gBAAAA,KAAC,SAAI,WAAU,sBAAqB,MAAK,QAAO,QAAO,gBAAe,SAAQ,aAC5E,0BAAAA,KAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,aAAa,GAAG,GAAE,kBAAiB,GACxF;AAAA,EAEF,OACE,gBAAAA,KAAC,SAAI,WAAU,sBAAqB,MAAK,QAAO,QAAO,gBAAe,SAAQ,aAC5E,0BAAAA,KAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,aAAa,GAAG,GAAE,wBAAuB,GAC9F;AAAA,EAEF,SACE,gBAAAA,KAAC,SAAI,WAAU,sBAAqB,MAAK,QAAO,QAAO,gBAAe,SAAQ,aAC5E,0BAAAA,KAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,aAAa,GAAG,GAAE,wIAAuI,GAC9M;AAAA,EAEF,MACE,gBAAAA,KAAC,SAAI,WAAU,sBAAqB,MAAK,QAAO,QAAO,gBAAe,SAAQ,aAC5E,0BAAAA,KAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,aAAa,GAAG,GAAE,6DAA4D,GACnI;AAEJ;AAEA,SAAS,MAAM,EAAE,OAAO,QAAQ,GAAe;AAC7C,EAAAC,WAAU,MAAM;AACd,UAAM,QAAQ,WAAW,MAAM;AAC7B,cAAQ,MAAM,EAAE;AAAA,IAClB,GAAG,MAAM,YAAY,GAAI;AAEzB,WAAO,MAAM,aAAa,KAAK;AAAA,EACjC,GAAG,CAAC,OAAO,OAAO,CAAC;AAEnB,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAU;AAAA,MACV,gBAAc,MAAM;AAAA,MACpB,MAAK;AAAA,MAEL;AAAA,wBAAAD,KAAC,SAAI,WAAU,8BAA8B,gBAAM,MAAM,IAAI,GAAE;AAAA,QAC/D,gBAAAA,KAAC,OAAE,WAAU,yBAAyB,gBAAM,SAAQ;AAAA,QACpD,gBAAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,MAAM,QAAQ,MAAM,EAAE;AAAA,YAC/B,WAAU;AAAA,YACV,cAAW;AAAA,YAEX,0BAAAA,KAAC,SAAI,WAAU,4BAA2B,MAAK,QAAO,QAAO,gBAAe,SAAQ,aAClF,0BAAAA,KAAC,UAAK,eAAc,SAAQ,gBAAe,SAAQ,aAAa,GAAG,GAAE,wBAAuB,GAC9F;AAAA;AAAA,QACF;AAAA;AAAA;AAAA,EACF;AAEJ;AAOO,SAAS,eAAe,EAAE,QAAQ,QAAQ,GAAwB;AACvE,QAAM,CAAC,SAAS,UAAU,IAAIE,UAAS,KAAK;AAE5C,EAAAD,WAAU,MAAM;AACd,eAAW,IAAI;AACf,WAAO,MAAM,WAAW,KAAK;AAAA,EAC/B,GAAG,CAAC,CAAC;AAEL,MAAI,CAAC,QAAS,QAAO;AAErB,SAAO;AAAA,IACL,gBAAAD,KAAC,SAAI,WAAU,2BACZ,iBAAO,IAAI,CAAC,UACX,gBAAAA,KAAC,SAAqB,OAAc,WAAxB,MAAM,EAAoC,CACvD,GACH;AAAA,IACA,SAAS;AAAA,EACX;AACF;AAWA,IAAM,eAAeG,OAAM,cAA4C,MAAS;AAEzE,SAAS,cAAc,EAAE,SAAS,GAAkC;AACzE,QAAM,CAAC,QAAQ,SAAS,IAAID,UAAyB,CAAC,CAAC;AAEvD,QAAM,YAAYC,OAAM,YAAY,CAAC,SAAiB,OAAkB,QAAQ,aAAsB;AACpG,UAAM,KAAK,KAAK,IAAI,EAAE,SAAS;AAC/B,UAAM,WAAyB,aAAa,SACxC,EAAE,IAAI,SAAS,MAAM,SAAS,IAC9B,EAAE,IAAI,SAAS,KAAK;AACxB,cAAU,CAAC,SAAS,CAAC,GAAG,MAAM,QAAQ,CAAC;AAAA,EACzC,GAAG,CAAC,CAAC;AAEL,QAAM,cAAcA,OAAM,YAAY,CAAC,SAAiB,aAAsB,UAAU,SAAS,WAAW,QAAQ,GAAG,CAAC,SAAS,CAAC;AAClI,QAAM,YAAYA,OAAM,YAAY,CAAC,SAAiB,aAAsB,UAAU,SAAS,SAAS,QAAQ,GAAG,CAAC,SAAS,CAAC;AAC9H,QAAM,cAAcA,OAAM,YAAY,CAAC,SAAiB,aAAsB,UAAU,SAAS,WAAW,QAAQ,GAAG,CAAC,SAAS,CAAC;AAClI,QAAM,WAAWA,OAAM,YAAY,CAAC,SAAiB,aAAsB,UAAU,SAAS,QAAQ,QAAQ,GAAG,CAAC,SAAS,CAAC;AAE5H,QAAM,cAAcA,OAAM,YAAY,CAAC,OAAe;AACpD,cAAU,CAAC,SAAS,KAAK,OAAO,CAAC,UAAU,MAAM,OAAO,EAAE,CAAC;AAAA,EAC7D,GAAG,CAAC,CAAC;AAEL,QAAM,eAAeA,OAAM;AAAA,IACzB,OAAO,EAAE,WAAW,aAAa,WAAW,aAAa,SAAS;AAAA,IAClE,CAAC,WAAW,aAAa,WAAW,aAAa,QAAQ;AAAA,EAC3D;AAEA,SACE,qBAAC,aAAa,UAAb,EAAsB,OAAO,cAC3B;AAAA;AAAA,IACD,gBAAAH,KAAC,kBAAe,QAAgB,SAAS,aAAa;AAAA,KACxD;AAEJ;AAEO,SAAS,WAAW;AACzB,QAAM,UAAUG,OAAM,WAAW,YAAY;AAC7C,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AACA,SAAO;AACT;;;AClJA,SAAgB,iBAAAC,gBAAe,cAAAC,mBAAkB;AA8B7C,gBAAAC,YAAA;AA3BJ,IAAM,uBAAuBF,eAAgD,MAAS;AAmB/E,SAAS,sBAAsB;AAAA,EACpC;AAAA,EACA;AACF,GAGG;AACD,SACE,gBAAAE,KAAC,qBAAqB,UAArB,EAA8B,OAAO,sBACnC,UACH;AAEJ;AAMO,SAAS,mBAAyC;AACvD,QAAM,UAAUD,YAAW,oBAAoB;AAC/C,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI,MAAM,+DAA+D;AAAA,EACjF;AACA,SAAO;AACT;;;AC9CA,SAAS,iBAAAE,gBAAe,cAAAC,aAAuB,YAAAC,WAAU,aAAAC,YAAW,WAAAC,gBAAe;AAwP7E,SAQK,UARL,OAAAC,YAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAlPN,IAAM,qBAAqBC,eAAyC,IAAI;AAGxE,IAAM,mBAAmB,oBAAI,IAAiB;AAM9C,SAAS,oBAAoB,MAAc,QAAqC;AAE9E,QAAM,cAAc,KAAK,MAAM,uBAAuB;AACtD,MAAI,CAAC,aAAa;AAChB,WAAO;AAAA,EACT;AAEA,QAAM,YAAY,YAAY,CAAC;AAC/B,QAAM,QAAQ,OAAO,SAAS;AAC9B,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AAGA,MAAI,WAAW,YAAY,CAAC,EAAE;AAC9B,MAAI,aAAa;AACjB,MAAI,SAAS;AAEb,WAAS,IAAI,UAAU,IAAI,KAAK,QAAQ,KAAK;AAC3C,QAAI,KAAK,CAAC,MAAM,IAAK;AAAA,aACZ,KAAK,CAAC,MAAM,KAAK;AACxB;AACA,UAAI,eAAe,GAAG;AACpB,iBAAS;AACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,QAAM,cAAc,KAAK,UAAU,UAAU,MAAM;AAGnD,QAAM,QAAgC,CAAC;AACvC,QAAM,YAAY;AAClB,MAAI;AAEJ,UAAQ,YAAY,UAAU,KAAK,WAAW,OAAO,MAAM;AACzD,UAAM,CAAC,EAAE,aAAa,SAAS,WAAW,IAAI;AAC9C,UAAM,MAAM,gBAAgB,SAAY,IAAI,WAAW,KAAK;AAC5D,UAAM,GAAG,IAAI;AAAA,EACf;AAGA,QAAM,aAAa,MAAM,IAAI,KAAK,EAAE;AACpC,MAAI,eAAe,QAAW;AAC5B,UAAM,SAAS,WAAW,QAAQ,MAAM,OAAO,KAAK,CAAC;AACrD,WAAO,KAAK,UAAU,GAAG,YAAY,KAAM,IAAI,SAAS,KAAK,UAAU,SAAS,CAAC;AAAA,EACnF;AAEA,QAAM,YAAY,MAAM,OAAO;AAC/B,MAAI,cAAc,QAAW;AAC3B,UAAM,SAAS,UAAU,QAAQ,MAAM,OAAO,KAAK,CAAC;AACpD,WAAO,KAAK,UAAU,GAAG,YAAY,KAAM,IAAI,SAAS,KAAK,UAAU,SAAS,CAAC;AAAA,EACnF;AAEA,SAAO;AACT;AAGO,IAAM,oBAAoB;AAAA,EAC/B;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AAAA,EACA;AAAA;AACF;AAIA,eAAe,iBAAiB,QAA8B;AAE5D,MAAI,iBAAiB,IAAI,MAAM,GAAG;AAChC,WAAO,iBAAiB,IAAI,MAAM;AAAA,EACpC;AAGA,MAAI,WAAW,MAAM;AACnB,qBAAiB,IAAI,MAAM,UAAc;AACzC,WAAO;AAAA,EACT;AAEA,MAAI;AAEF,UAAM,eAAe,MAAa,mDAAsB,MAAM;AAC9D,UAAM,kBAAkB,aAAa,WAAW;AAChD,qBAAiB,IAAI,QAAQ,eAAe;AAC5C,WAAO;AAAA,EACT,SAAS,OAAO;AACd,YAAQ,MAAM,2CAA2C,MAAM,IAAI,KAAK;AAExE,WAAO;AAAA,EACT;AACF;AAGA,IAAM,4BAAgD;AAAA,EACpD,GAAG,CAAC,WAAmB,KAAa,WAAiC;AACnE,UAAM,eAAe;AACrB,UAAM,cAAc,aAAa,SAAS,IAAI,GAAG;AAEjD,QAAI,CAAC,aAAa;AAChB,cAAQ,KAAK,6BAA6B,SAAS,IAAI,GAAG,EAAE;AAC5D,aAAO,GAAG,SAAS,IAAI,GAAG;AAAA,IAC5B;AAGA,QAAI,UAAU,OAAO,gBAAgB,UAAU;AAC7C,UAAI,SAAS;AAEb,eAAS,oBAAoB,QAAQ,MAAM;AAE3C,aAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,CAAC,UAAU,UAAU,MAAM;AACzD,iBAAS,OAAO,QAAQ,IAAI,OAAO,SAAS,QAAQ,UAAU,GAAG,GAAG,OAAO,UAAU,CAAC;AAAA,MACxF,CAAC;AACD,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AACF;AA+BO,SAAS,oBAAoB;AAAA,EAClC;AAAA,EACA;AAAA,EACA,mBAAmB;AAAA,EACnB;AACF,GAA6B;AAC3B,QAAM,CAAC,oBAAoB,qBAAqB,IAAIC,UAAc,IAAI;AACtE,QAAM,CAAC,WAAW,YAAY,IAAIA,UAAS,KAAK;AAGhD,EAAAC,WAAU,MAAM;AACd,QAAI,UAAU,CAAC,oBAAoB;AACjC,mBAAa,IAAI;AACjB,uBAAiB,MAAM,EACpB,KAAK,kBAAgB;AACpB,8BAAsB,YAAY;AAClC,qBAAa,KAAK;AAAA,MACpB,CAAC,EACA,MAAM,WAAS;AACd,gBAAQ,MAAM,gCAAgC,KAAK;AACnD,8BAAsB,UAAc;AACpC,qBAAa,KAAK;AAAA,MACpB,CAAC;AAAA,IACL;AAAA,EACF,GAAG,CAAC,QAAQ,kBAAkB,CAAC;AAG/B,QAAM,gBAAgBC,SAAmC,MAAM;AAC7D,QAAI,CAAC,mBAAoB,QAAO;AAEhC,WAAO;AAAA,MACL,GAAG,CAAC,WAAmB,KAAa,WAAiC;AACnE,cAAM,cAAc,mBAAmB,SAAS,IAAI,GAAG;AAEvD,YAAI,CAAC,aAAa;AAChB,kBAAQ,KAAK,6BAA6B,SAAS,IAAI,GAAG,cAAc,MAAM,EAAE;AAChF,iBAAO,GAAG,SAAS,IAAI,GAAG;AAAA,QAC5B;AAGA,YAAI,UAAU,OAAO,gBAAgB,UAAU;AAC7C,cAAI,SAAS;AAEb,mBAAS,oBAAoB,QAAQ,MAAM;AAE3C,iBAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,CAAC,UAAU,UAAU,MAAM;AACzD,qBAAS,OAAO,QAAQ,IAAI,OAAO,SAAS,QAAQ,UAAU,GAAG,GAAG,OAAO,UAAU,CAAC;AAAA,UACxF,CAAC;AACD,iBAAO;AAAA,QACT;AAEA,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF,GAAG,CAAC,oBAAoB,MAAM,CAAC;AAG/B,MAAI,oBAAoB;AACtB,WACE,gBAAAC,KAAC,mBAAmB,UAAnB,EAA4B,OAAO,oBACjC,UACH;AAAA,EAEJ;AAGA,MAAI,UAAU,WAAW;AACvB,WAAO,gBAAAA,KAAA,YAAG,4BAAiB;AAAA,EAC7B;AAGA,MAAI,UAAU,eAAe;AAC3B,WACE,gBAAAA,KAAC,mBAAmB,UAAnB,EAA4B,OAAO,eACjC,UACH;AAAA,EAEJ;AAGA,SACE,gBAAAA,KAAC,mBAAmB,UAAnB,EAA4B,OAAO,2BACjC,UACH;AAEJ;AAaO,SAAS,gBAAgB,WAAmB;AACjD,QAAM,UAAUC,YAAW,kBAAkB;AAG7C,MAAI,CAAC,SAAS;AACZ,WAAO,CAAC,KAAa,WAAiC;AACpD,YAAM,eAAe;AACrB,YAAM,cAAc,aAAa,SAAS,IAAI,GAAG;AAEjD,UAAI,CAAC,aAAa;AAChB,gBAAQ,KAAK,6BAA6B,SAAS,IAAI,GAAG,EAAE;AAC5D,eAAO,GAAG,SAAS,IAAI,GAAG;AAAA,MAC5B;AAGA,UAAI,UAAU,OAAO,gBAAgB,UAAU;AAC7C,YAAI,SAAS;AAEb,iBAAS,oBAAoB,QAAQ,MAAM;AAE3C,eAAO,QAAQ,MAAM,EAAE,QAAQ,CAAC,CAAC,UAAU,UAAU,MAAM;AACzD,mBAAS,OAAO,QAAQ,IAAI,OAAO,SAAS,QAAQ,UAAU,GAAG,GAAG,OAAO,UAAU,CAAC;AAAA,QACxF,CAAC;AACD,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AAGA,SAAO,CAAC,KAAa,WAAiC,QAAQ,EAAE,WAAW,KAAK,MAAM;AACxF;AAMO,SAAS,yBAAyB;AACvC,SAAO;AAAA,IACL,SAAS,OAAO,WAAmB;AACjC,UAAI;AACF,cAAM,iBAAiB,MAAM;AAC7B,eAAO;AAAA,MACT,SAAS,OAAO;AACd,gBAAQ,MAAM,sCAAsC,MAAM,KAAK,KAAK;AACpE,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,UAAU,CAAC,WAAmB,iBAAiB,IAAI,MAAM;AAAA,EAC3D;AACF;","names":["SemiontApiClient","baseUrl","EventBus","SemiontApiClient","baseUrl","EventBus","React","useEffect","useState","jsx","useEffect","useState","React","createContext","useContext","jsx","createContext","useContext","useState","useEffect","useMemo","jsx","createContext","useState","useEffect","useMemo","jsx","useContext"]}
|