{"version":3,"sources":["../../src/components/AccountSwitcherProvider.tsx","../../src/hooks/useSession.ts","../../src/hooks/useUser.ts","../../src/hooks/useAccountSwitcher.ts","../../src/hooks/useHandoffArrival.ts"],"sourcesContent":["'use client';\r\n\r\nimport React, { createContext, useContext, useState, useEffect, useCallback, useRef } from 'react';\r\nimport type {\r\n  Session,\r\n  AccountSwitcherConfig,\r\n  AccountSwitcherContextValue,\r\n  ConfirmPayload,\r\n  PromptPayload,\r\n  AlertPayload,\r\n  UrlRedirectPayload,\r\n} from '../lib/types';\r\nimport { PostMessageClient } from '../lib/client';\r\nimport { MESSAGE_TYPES } from '../lib/message-protocol';\r\nimport { DialogManager } from '../lib/dialogs';\r\n\r\n// Cross-bundle singleton context.\r\n//\r\n// tsup builds this package as multiple entry points (index, components, hooks,\r\n// sharing) with `splitting: false`, which DUPLICATES this module — and its\r\n// `createContext()` call — into every entry bundle. That yields distinct\r\n// Context objects, so a Provider imported from one entry (e.g. the root) and a\r\n// consumer imported from another (e.g. `/sharing`'s HandoffLanding) never\r\n// match, and the consumer reads `null`. Anchoring the Context on `globalThis`\r\n// behind a stable `Symbol.for()` key guarantees exactly ONE shared Context\r\n// object across all bundles at runtime. See tsup.config.ts.\r\nconst CONTEXT_KEY = Symbol.for('@benbraide/auth-service-nextjs/AccountSwitcherContext');\r\ntype AccountSwitcherReactContext = React.Context<AccountSwitcherContextValue | null>;\r\nconst contextRegistry = globalThis as unknown as Record<symbol, AccountSwitcherReactContext | undefined>;\r\nconst AccountSwitcherContext: AccountSwitcherReactContext =\r\n  contextRegistry[CONTEXT_KEY] ??\r\n  (contextRegistry[CONTEXT_KEY] = createContext<AccountSwitcherContextValue | null>(null));\r\n\r\nexport interface AccountSwitcherProviderProps extends AccountSwitcherConfig {\r\n  children: React.ReactNode;\r\n}\r\n\r\n/**\r\n * Provider component for account switcher functionality\r\n * Wraps your app to provide session state and switcher methods\r\n */\r\nexport function AccountSwitcherProvider({\r\n  children,\r\n  backendUrl,\r\n  authServiceUrl,\r\n  serviceApiKey,\r\n  onSessionChange,\r\n  onAccountChange,\r\n  onError,\r\n  debug = false,\r\n  dialogs,\r\n  onConfirmRequest,\r\n  onPromptRequest,\r\n  onAlertRequest,\r\n  autoResize = true,\r\n  minHeight = 200,\r\n  maxHeight = null,\r\n  onResize,\r\n  onNavigate,\r\n  onNavigateToAddAccount,\r\n  onNavigateToManageAccount,\r\n  onNavigateToAvatarUpdate,\r\n}: AccountSwitcherProviderProps) {\r\n  const [session, setSession] = useState<Session>({\r\n    isAuthenticated: false,\r\n    currentUser: null,\r\n    accounts: [],\r\n  });\r\n  const [isLoading, setIsLoading] = useState(false);\r\n  const [error, setError] = useState<Error | null>(null);\r\n  // State mirror of clientRef so the context value updates (and consumers such\r\n  // as HandoffLanding re-render) once the PostMessage client is initialized in\r\n  // the mount effect below.\r\n  const [activeClient, setActiveClient] = useState<PostMessageClient | null>(null);\r\n  const clientRef = useRef<PostMessageClient | null>(null);\r\n  const dialogManagerRef = useRef<DialogManager | null>(null);\r\n\r\n  // Use refs for callbacks to avoid recreating PostMessageClient on every prop change\r\n  const debugRef = useRef(debug);\r\n  const onSessionChangeRef = useRef(onSessionChange);\r\n  const onAccountChangeRef = useRef(onAccountChange);\r\n  const onErrorRef = useRef(onError);\r\n  const onConfirmRequestRef = useRef(onConfirmRequest);\r\n  const onPromptRequestRef = useRef(onPromptRequest);\r\n  const onAlertRequestRef = useRef(onAlertRequest);\r\n  const onNavigateRef = useRef(onNavigate);\r\n  const onNavigateToAddAccountRef = useRef(onNavigateToAddAccount);\r\n  const onNavigateToManageAccountRef = useRef(onNavigateToManageAccount);\r\n  const onNavigateToAvatarUpdateRef = useRef(onNavigateToAvatarUpdate);\r\n\r\n  // Update refs whenever callbacks change\r\n  useEffect(() => {\r\n    debugRef.current = debug;\r\n    onSessionChangeRef.current = onSessionChange;\r\n    onAccountChangeRef.current = onAccountChange;\r\n    onErrorRef.current = onError;\r\n    onConfirmRequestRef.current = onConfirmRequest;\r\n    onPromptRequestRef.current = onPromptRequest;\r\n    onAlertRequestRef.current = onAlertRequest;\r\n    onNavigateRef.current = onNavigate;\r\n    onNavigateToAddAccountRef.current = onNavigateToAddAccount;\r\n    onNavigateToManageAccountRef.current = onNavigateToManageAccount;\r\n    onNavigateToAvatarUpdateRef.current = onNavigateToAvatarUpdate;\r\n  });\r\n\r\n  // Initialize PostMessage client\r\n  useEffect(() => {\r\n    if (typeof window === 'undefined') return;\r\n\r\n    // Initialize dialog manager if dialogs are enabled\r\n    if (dialogs?.enabled !== false) {\r\n      const dialogManager = new DialogManager(dialogs || {});\r\n      dialogManager.injectDialogStyles();\r\n      dialogManagerRef.current = dialogManager;\r\n    }\r\n\r\n    const config: AccountSwitcherConfig = {\r\n      backendUrl,\r\n      authServiceUrl,\r\n      serviceApiKey,\r\n      onSessionChange,\r\n      onAccountChange,\r\n      onError,\r\n      debug,\r\n      dialogs,\r\n      onConfirmRequest,\r\n      onPromptRequest,\r\n      onAlertRequest,\r\n      autoResize,\r\n      minHeight,\r\n      maxHeight,\r\n      onResize,\r\n    };\r\n\r\n    const client = new PostMessageClient(config);\r\n    clientRef.current = client;\r\n    // Publish into state so the context value exposes a live `client` to\r\n    // consumers (e.g. the cross-product handoff) once it's ready.\r\n    setActiveClient(client);\r\n\r\n    // Set up session change listener\r\n    client.on(MESSAGE_TYPES.SESSION_CHANGED, (data: any) => {\r\n      const sessionData = data.payload || data;\r\n      const newSession: Session = {\r\n        isAuthenticated: sessionData.isAuthenticated || false,\r\n        currentUser: sessionData.currentUser || null,\r\n        accounts: sessionData.accounts || [],\r\n      };\r\n\r\n      setSession(newSession);\r\n      onSessionChangeRef.current?.(newSession);\r\n    });\r\n\r\n    // Set up account change listener\r\n    client.on(MESSAGE_TYPES.ACCOUNT_SWITCHED, (data: any) => {\r\n      const payload = data.payload || data;\r\n\r\n      // ACCOUNT_SWITCHED only sends { user_uuid }, not the full user object\r\n      // Find the full user object from the accounts array\r\n      setSession((prevSession) => {\r\n        const switchedUser = prevSession.accounts.find(\r\n          (account) => account.uuid === payload.user_uuid\r\n        );\r\n\r\n        if (switchedUser) {\r\n          // Update current user with the full user object from accounts\r\n          const newSession = {\r\n            ...prevSession,\r\n            currentUser: switchedUser,\r\n          };\r\n\r\n          // Call the callback with the full user object\r\n          onAccountChangeRef.current?.(switchedUser);\r\n\r\n          return newSession;\r\n        }\r\n\r\n        // If user not found in accounts, keep previous session\r\n        if (debug) {\r\n          console.warn('[AccountSwitcher] Switched user not found in accounts:', payload.user_uuid);\r\n        }\r\n        return prevSession;\r\n      });\r\n    });\r\n\r\n    // Set up error listener\r\n    client.on(MESSAGE_TYPES.ERROR, (data: any) => {\r\n      const err = data.payload || data;\r\n      const error = new Error(err.message || 'Unknown error');\r\n      setError(error);\r\n      onErrorRef.current?.(error);\r\n    });\r\n\r\n    // NOTE: SIZE_CHANGED is now handled directly in AccountSwitcher component\r\n    // using direct DOM manipulation to avoid re-renders. If you need resize notifications,\r\n    // use the onHeightChange prop on the AccountSwitcher component instead.\r\n\r\n    // Set up navigation handlers\r\n    client.on(MESSAGE_TYPES.ADD_ACCOUNT, (data: any) => {\r\n      const payload = data.payload || data;\r\n      if (payload.landing_url) {\r\n        if (onNavigateToAddAccountRef.current) {\r\n          onNavigateToAddAccountRef.current(payload.landing_url);\r\n        } else {\r\n          window.location.href = payload.landing_url;\r\n        }\r\n      }\r\n    });\r\n\r\n    client.on(MESSAGE_TYPES.MANAGE_ACCOUNT, (data: any) => {\r\n      const payload = data.payload || data;\r\n      if (payload.management_url) {\r\n        if (onNavigateToManageAccountRef.current) {\r\n          onNavigateToManageAccountRef.current(payload.management_url);\r\n        } else {\r\n          window.location.href = payload.management_url;\r\n        }\r\n      }\r\n    });\r\n\r\n    client.on(MESSAGE_TYPES.UPDATE_AVATAR, (data: any) => {\r\n      const payload = data.payload || data;\r\n      if (payload.avatar_url) {\r\n        if (onNavigateToAvatarUpdateRef.current) {\r\n          onNavigateToAvatarUpdateRef.current(payload.avatar_url);\r\n        } else {\r\n          window.location.href = payload.avatar_url;\r\n        }\r\n      }\r\n    });\r\n\r\n    // Set up unified URL redirect handler (Unified Action Protocol)\r\n    client.on(MESSAGE_TYPES.URL_REDIRECT, (data: any) => {\r\n      const payload = data.payload || data;\r\n      const redirectPayload: UrlRedirectPayload = {\r\n        url: payload.url,\r\n        reason: payload.reason,\r\n        openInNewTab: payload.openInNewTab || false,\r\n      };\r\n\r\n      if (onNavigateRef.current) {\r\n        // Use new unified navigation handler\r\n        onNavigateRef.current(redirectPayload);\r\n      } else {\r\n        // Fallback to legacy handlers or default behavior\r\n        const { url, reason, openInNewTab } = redirectPayload;\r\n\r\n        // Try legacy handlers first based on reason\r\n        if (reason === 'add-account' && onNavigateToAddAccountRef.current) {\r\n          onNavigateToAddAccountRef.current(url);\r\n        } else if (reason === 'manage-account' && onNavigateToManageAccountRef.current) {\r\n          onNavigateToManageAccountRef.current(url);\r\n        } else if (reason === 'update-avatar' && onNavigateToAvatarUpdateRef.current) {\r\n          onNavigateToAvatarUpdateRef.current(url);\r\n        } else {\r\n          // Default navigation behavior\r\n          if (openInNewTab) {\r\n            window.open(url, '_blank');\r\n          } else {\r\n            window.location.href = url;\r\n          }\r\n        }\r\n      }\r\n    });\r\n\r\n    // Set up dialog handlers\r\n    if (dialogs?.enabled !== false) {\r\n      // Confirm dialog\r\n      client.on(MESSAGE_TYPES.CONFIRM_REQUEST, async (data: any) => {\r\n        if (debug) {\r\n          console.log('[AccountSwitcher] CONFIRM_REQUEST received:', data);\r\n        }\r\n        const { requestId, payload } = data;\r\n\r\n        try {\r\n          let result: boolean;\r\n\r\n          if (onConfirmRequestRef.current) {\r\n            // Use custom handler if provided\r\n            result = await onConfirmRequestRef.current(payload as ConfirmPayload);\r\n          } else if (dialogManagerRef.current) {\r\n            // Use custom dialog manager\r\n            result = await dialogManagerRef.current.showConfirm(payload as ConfirmPayload);\r\n          } else {\r\n            // Fallback to browser confirm\r\n            result = window.confirm(payload.message);\r\n          }\r\n\r\n          client.sendDialogResponse(MESSAGE_TYPES.REQUEST_RESPONSE, requestId, {\r\n            confirmed: result,\r\n          });\r\n        } catch (err) {\r\n          client.sendDialogResponse(MESSAGE_TYPES.REQUEST_RESPONSE, requestId, {\r\n            confirmed: false,\r\n          });\r\n        }\r\n      });\r\n\r\n      // Prompt dialog\r\n      client.on(MESSAGE_TYPES.PROMPT_REQUEST, async (data: any) => {\r\n        const { requestId, payload } = data;\r\n\r\n        try {\r\n          let value: string | null = null;\r\n          let cancelled = true;\r\n\r\n          if (onPromptRequestRef.current) {\r\n            // Use custom handler if provided\r\n            const customResult = await onPromptRequestRef.current(payload as PromptPayload);\r\n            value = customResult;\r\n            cancelled = customResult === null;\r\n          } else if (dialogManagerRef.current) {\r\n            // Use custom dialog manager\r\n            const result = await dialogManagerRef.current.showPrompt(payload as PromptPayload);\r\n            value = result.value;\r\n            cancelled = result.cancelled;\r\n          } else {\r\n            // Fallback to browser prompt\r\n            const browserResult = window.prompt(payload.message, payload.defaultValue || '');\r\n            value = browserResult;\r\n            cancelled = browserResult === null;\r\n          }\r\n\r\n          client.sendDialogResponse(MESSAGE_TYPES.REQUEST_RESPONSE, requestId, {\r\n            value,\r\n            cancelled,\r\n          });\r\n        } catch (err) {\r\n          client.sendDialogResponse(MESSAGE_TYPES.REQUEST_RESPONSE, requestId, {\r\n            value: null,\r\n            cancelled: true,\r\n          });\r\n        }\r\n      });\r\n\r\n      // Alert dialog\r\n      client.on(MESSAGE_TYPES.ALERT_REQUEST, async (data: any) => {\r\n        const { requestId, payload } = data;\r\n\r\n        try {\r\n          if (onAlertRequestRef.current) {\r\n            // Use custom handler if provided\r\n            await onAlertRequestRef.current(payload as AlertPayload);\r\n          } else if (dialogManagerRef.current) {\r\n            // Use custom dialog manager\r\n            await dialogManagerRef.current.showAlert(payload as AlertPayload);\r\n          } else {\r\n            // Fallback to browser alert\r\n            window.alert(payload.message);\r\n          }\r\n\r\n          client.sendDialogResponse(MESSAGE_TYPES.REQUEST_RESPONSE, requestId, {\r\n            acknowledged: true,\r\n          });\r\n        } catch (err) {\r\n          client.sendDialogResponse(MESSAGE_TYPES.REQUEST_RESPONSE, requestId, {\r\n            acknowledged: false,\r\n          });\r\n        }\r\n      });\r\n    }\r\n\r\n    return () => {\r\n      client.destroy();\r\n      clientRef.current = null;\r\n      setActiveClient(null);\r\n    };\r\n  }, []);\r\n\r\n  const switchAccount = useCallback(async (userUuid: string) => {\r\n    if (!clientRef.current) throw new Error('Client not initialized');\r\n\r\n    setIsLoading(true);\r\n    setError(null);\r\n\r\n    try {\r\n      await clientRef.current.switchAccount(userUuid);\r\n    } catch (err) {\r\n      const error = err as Error;\r\n      setError(error);\r\n      throw error;\r\n    } finally {\r\n      setIsLoading(false);\r\n    }\r\n  }, []);\r\n\r\n  const addAccount = useCallback(async () => {\r\n    if (!clientRef.current) throw new Error('Client not initialized');\r\n\r\n    try {\r\n      await clientRef.current.addAccount();\r\n    } catch (err) {\r\n      const error = err as Error;\r\n      setError(error);\r\n      throw error;\r\n    }\r\n  }, []);\r\n\r\n  const manageAccount = useCallback(async () => {\r\n    if (!clientRef.current) throw new Error('Client not initialized');\r\n\r\n    try {\r\n      await clientRef.current.manageAccount();\r\n    } catch (err) {\r\n      const error = err as Error;\r\n      setError(error);\r\n      throw error;\r\n    }\r\n  }, []);\r\n\r\n  const updateAvatar = useCallback(async () => {\r\n    if (!clientRef.current) throw new Error('Client not initialized');\r\n\r\n    try {\r\n      await clientRef.current.updateAvatar();\r\n    } catch (err) {\r\n      const error = err as Error;\r\n      setError(error);\r\n      throw error;\r\n    }\r\n  }, []);\r\n\r\n  const logoutAccount = useCallback(async (userUuid: string) => {\r\n    if (!clientRef.current) throw new Error('Client not initialized');\r\n\r\n    setIsLoading(true);\r\n    setError(null);\r\n\r\n    try {\r\n      await clientRef.current.logoutAccount(userUuid);\r\n    } catch (err) {\r\n      const error = err as Error;\r\n      setError(error);\r\n      throw error;\r\n    } finally {\r\n      setIsLoading(false);\r\n    }\r\n  }, []);\r\n\r\n  const logoutAll = useCallback(async () => {\r\n    if (!clientRef.current) throw new Error('Client not initialized');\r\n\r\n    setIsLoading(true);\r\n    setError(null);\r\n\r\n    try {\r\n      await clientRef.current.logoutAll();\r\n    } catch (err) {\r\n      const error = err as Error;\r\n      setError(error);\r\n      throw error;\r\n    } finally {\r\n      setIsLoading(false);\r\n    }\r\n  }, []);\r\n\r\n  const refresh = useCallback(async () => {\r\n    if (!clientRef.current) throw new Error('Client not initialized');\r\n\r\n    setIsLoading(true);\r\n    setError(null);\r\n\r\n    try {\r\n      const sessionData = await clientRef.current.getSession();\r\n      setSession(sessionData);\r\n    } catch (err) {\r\n      const error = err as Error;\r\n      setError(error);\r\n      throw error;\r\n    } finally {\r\n      setIsLoading(false);\r\n    }\r\n  }, []);\r\n\r\n  const registerIframe = useCallback((iframe: HTMLIFrameElement, origin: string) => {\r\n    if (!clientRef.current) {\r\n      console.warn('[AccountSwitcherProvider] Client not initialized, cannot register iframe');\r\n      return;\r\n    }\r\n\r\n    clientRef.current.setIframe(iframe, origin);\r\n\r\n    // Fetch initial session after iframe is registered\r\n    // Wait a bit for the iframe to be ready and handshake to complete\r\n    setTimeout(async () => {\r\n      try {\r\n        setIsLoading(true);\r\n        const sessionData = await clientRef.current!.getSession();\r\n        setSession(sessionData);\r\n      } catch (err) {\r\n        if (debugRef.current) {\r\n          console.error('[AccountSwitcherProvider] Failed to fetch initial session:', err);\r\n        }\r\n      } finally {\r\n        setIsLoading(false);\r\n      }\r\n    }, 1000); // Give the iframe time to complete handshake\r\n  }, []); // No dependencies - uses only refs and setState\r\n\r\n  const sendMessage = useCallback((type: string, payload?: unknown) => {\r\n    if (!clientRef.current) {\r\n      console.warn('[AccountSwitcherProvider] Client not initialized, cannot send message:', type);\r\n      return;\r\n    }\r\n    clientRef.current.send(type, payload);\r\n  }, []);\r\n\r\n  const value: AccountSwitcherContextValue = {\r\n    session,\r\n    isLoading,\r\n    error,\r\n    switchAccount,\r\n    addAccount,\r\n    manageAccount,\r\n    updateAvatar,\r\n    logoutAccount,\r\n    logoutAll,\r\n    refresh,\r\n    registerIframe,\r\n    client: activeClient,\r\n    sendMessage,\r\n  };\r\n\r\n  return (\r\n    <AccountSwitcherContext.Provider value={value}>\r\n      {children}\r\n    </AccountSwitcherContext.Provider>\r\n  );\r\n}\r\n\r\n/**\r\n * Hook to access the account switcher context\r\n * @throws Error if used outside of AccountSwitcherProvider\r\n */\r\nexport function useAccountSwitcherContext() {\r\n  const context = useContext(AccountSwitcherContext);\r\n\r\n  if (!context) {\r\n    throw new Error(\r\n      'useAccountSwitcherContext must be used within AccountSwitcherProvider'\r\n    );\r\n  }\r\n\r\n  return context;\r\n}\r\n","import { useAccountSwitcherContext } from '../components/AccountSwitcherProvider';\n\n/**\n * Hook to access session state\n * Returns current session information including authentication status, user, and accounts\n */\nexport function useSession() {\n  const { session, isLoading, error } = useAccountSwitcherContext();\n\n  return {\n    ...session,\n    isLoading,\n    error,\n  };\n}\n","import { useAccountSwitcherContext } from '../components/AccountSwitcherProvider';\n\n/**\n * Hook to access current user\n * Returns the currently authenticated user or null\n */\nexport function useUser() {\n  const { session } = useAccountSwitcherContext();\n\n  return session.currentUser;\n}\n","import { useAccountSwitcherContext } from '../components/AccountSwitcherProvider';\r\n\r\n/**\r\n * Hook to access account switcher methods\r\n * Returns methods for switching accounts, adding accounts, managing account, updating avatar, and logging out\r\n */\r\nexport function useAccountSwitcher() {\r\n  const {\r\n    switchAccount,\r\n    addAccount,\r\n    manageAccount,\r\n    updateAvatar,\r\n    logoutAccount,\r\n    logoutAll,\r\n    refresh,\r\n    client,\r\n    sendMessage,\r\n  } = useAccountSwitcherContext();\r\n\r\n  return {\r\n    switchAccount,\r\n    addAccount,\r\n    manageAccount,\r\n    updateAvatar,\r\n    logoutAccount,\r\n    logoutAll,\r\n    refresh,\r\n    // The live PostMessage client + sender, needed by the cross-product handoff\r\n    // (HandoffLanding → multiAccountAutoAdd). `client` is null until the\r\n    // provider's mount effect initializes it.\r\n    client,\r\n    sendMessage,\r\n  };\r\n}\r\n","'use client';\r\nimport { useCallback, useEffect, useRef, useState } from 'react';\r\nimport { usePathname, useRouter, useSearchParams } from 'next/navigation';\r\n\r\nconst PARAM = '_toast';\r\n\r\nexport interface HandoffArrival {\r\n  toast: string | null;\r\n  dismiss: () => void;\r\n}\r\n\r\n/**\r\n * Reads the `?_toast=…` query param once on mount, scrubs it from the URL via\r\n * `router.replace`, and returns the decoded message. Intended to be mounted in\r\n * a top-level layout so any page the user lands on after a cross-product\r\n * handoff (F2 → F5) can render the arrival banner.\r\n */\r\nexport function useHandoffArrival(): HandoffArrival {\r\n  const router = useRouter();\r\n  const pathname = usePathname();\r\n  const params = useSearchParams();\r\n  const fired = useRef(false);\r\n  const [toast, setToast] = useState<string | null>(null);\r\n\r\n  useEffect(() => {\r\n    if (fired.current) return;\r\n    fired.current = true;\r\n\r\n    const raw = params?.get(PARAM);\r\n    if (!raw) return;\r\n\r\n    setToast(raw);\r\n\r\n    const remaining = new URLSearchParams(params?.toString() ?? '');\r\n    remaining.delete(PARAM);\r\n    const qs = remaining.toString();\r\n    router.replace(qs ? `${pathname}?${qs}` : pathname);\r\n  }, [params, pathname, router]);\r\n\r\n  const dismiss = useCallback(() => setToast(null), []);\r\n\r\n  return { toast, dismiss };\r\n}\r\n"],"mappings":";;;AAEA,SAAgB,eAAe,YAAY,UAAU,WAAW,aAAa,cAAc;AA0gBvF;AAlfJ,IAAM,cAAc,OAAO,IAAI,uDAAuD;AAEtF,IAAM,kBAAkB;AACxB,IAAM,yBACJ,gBAAgB,WAAW,MAC1B,gBAAgB,WAAW,IAAI,cAAkD,IAAI;AAufjF,SAAS,4BAA4B;AAC1C,QAAM,UAAU,WAAW,sBAAsB;AAEjD,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;AC1hBO,SAAS,aAAa;AAC3B,QAAM,EAAE,SAAS,WAAW,MAAM,IAAI,0BAA0B;AAEhE,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA;AAAA,EACF;AACF;;;ACRO,SAAS,UAAU;AACxB,QAAM,EAAE,QAAQ,IAAI,0BAA0B;AAE9C,SAAO,QAAQ;AACjB;;;ACJO,SAAS,qBAAqB;AACnC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,IAAI,0BAA0B;AAE9B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA;AAAA;AAAA;AAAA,IAIA;AAAA,IACA;AAAA,EACF;AACF;;;AChCA,SAAS,eAAAA,cAAa,aAAAC,YAAW,UAAAC,SAAQ,YAAAC,iBAAgB;AACzD,SAAS,aAAa,WAAW,uBAAuB;AAExD,IAAM,QAAQ;AAaP,SAAS,oBAAoC;AAClD,QAAM,SAAS,UAAU;AACzB,QAAM,WAAW,YAAY;AAC7B,QAAM,SAAS,gBAAgB;AAC/B,QAAM,QAAQD,QAAO,KAAK;AAC1B,QAAM,CAAC,OAAO,QAAQ,IAAIC,UAAwB,IAAI;AAEtD,EAAAF,WAAU,MAAM;AACd,QAAI,MAAM,QAAS;AACnB,UAAM,UAAU;AAEhB,UAAM,MAAM,QAAQ,IAAI,KAAK;AAC7B,QAAI,CAAC,IAAK;AAEV,aAAS,GAAG;AAEZ,UAAM,YAAY,IAAI,gBAAgB,QAAQ,SAAS,KAAK,EAAE;AAC9D,cAAU,OAAO,KAAK;AACtB,UAAM,KAAK,UAAU,SAAS;AAC9B,WAAO,QAAQ,KAAK,GAAG,QAAQ,IAAI,EAAE,KAAK,QAAQ;AAAA,EACpD,GAAG,CAAC,QAAQ,UAAU,MAAM,CAAC;AAE7B,QAAM,UAAUD,aAAY,MAAM,SAAS,IAAI,GAAG,CAAC,CAAC;AAEpD,SAAO,EAAE,OAAO,QAAQ;AAC1B;","names":["useCallback","useEffect","useRef","useState"]}