@perspective-ai/sdk 1.0.0-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +333 -0
  2. package/dist/browser.cjs +1939 -0
  3. package/dist/browser.cjs.map +1 -0
  4. package/dist/browser.d.cts +213 -0
  5. package/dist/browser.d.ts +213 -0
  6. package/dist/browser.js +1900 -0
  7. package/dist/browser.js.map +1 -0
  8. package/dist/cdn/perspective.global.js +406 -0
  9. package/dist/cdn/perspective.global.js.map +1 -0
  10. package/dist/constants.cjs +142 -0
  11. package/dist/constants.cjs.map +1 -0
  12. package/dist/constants.d.cts +104 -0
  13. package/dist/constants.d.ts +104 -0
  14. package/dist/constants.js +127 -0
  15. package/dist/constants.js.map +1 -0
  16. package/dist/index.cjs +1596 -0
  17. package/dist/index.cjs.map +1 -0
  18. package/dist/index.d.cts +155 -0
  19. package/dist/index.d.ts +155 -0
  20. package/dist/index.js +1579 -0
  21. package/dist/index.js.map +1 -0
  22. package/package.json +83 -0
  23. package/src/browser.test.ts +388 -0
  24. package/src/browser.ts +509 -0
  25. package/src/config.test.ts +81 -0
  26. package/src/config.ts +95 -0
  27. package/src/constants.ts +214 -0
  28. package/src/float.test.ts +332 -0
  29. package/src/float.ts +231 -0
  30. package/src/fullpage.test.ts +224 -0
  31. package/src/fullpage.ts +126 -0
  32. package/src/iframe.test.ts +1037 -0
  33. package/src/iframe.ts +421 -0
  34. package/src/index.ts +61 -0
  35. package/src/loading.ts +90 -0
  36. package/src/popup.test.ts +344 -0
  37. package/src/popup.ts +157 -0
  38. package/src/slider.test.ts +277 -0
  39. package/src/slider.ts +158 -0
  40. package/src/styles.ts +395 -0
  41. package/src/types.ts +148 -0
  42. package/src/utils.test.ts +162 -0
  43. package/src/utils.ts +86 -0
  44. package/src/widget.test.ts +375 -0
  45. package/src/widget.ts +195 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/config.ts","../src/constants.ts","../src/utils.ts","../src/iframe.ts","../src/loading.ts","../src/styles.ts","../src/widget.ts","../src/popup.ts","../src/slider.ts","../src/float.ts","../src/fullpage.ts"],"names":["createNoOpHandle"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Embed SDK configuration\n * SSR-safe - DOM access is guarded and lazy\n */\n\nimport type { SDKConfig } from \"./types\";\n\n/** Default production host */\nconst DEFAULT_HOST = \"https://getperspective.ai\";\n\n/** Global SDK configuration - can be set before creating embeds */\nlet globalConfig: SDKConfig = {};\n\n/**\n * Configure the SDK globally\n * Call this before creating any embeds if you need to override defaults\n */\nexport function configure(config: SDKConfig): void {\n globalConfig = { ...globalConfig, ...config };\n}\n\n/**\n * Get the current SDK configuration\n */\nexport function getConfig(): SDKConfig {\n return { ...globalConfig };\n}\n\n/**\n * Check if DOM is available (SSR safety)\n */\nexport function hasDom(): boolean {\n return typeof window !== \"undefined\" && typeof document !== \"undefined\";\n}\n\nfunction normalizeToOrigin(host: string): string {\n try {\n return new URL(host).origin;\n } catch {\n return host;\n }\n}\n\nexport function getHost(instanceHost?: string): string {\n // Instance-level override\n if (instanceHost) {\n return normalizeToOrigin(instanceHost);\n }\n\n // Global config override\n if (globalConfig.host) {\n return normalizeToOrigin(globalConfig.host);\n }\n\n // Try to infer from script src (only in browser, only at load time)\n if (hasDom()) {\n const scriptHost = getScriptHost();\n if (scriptHost) {\n return scriptHost;\n }\n }\n\n return DEFAULT_HOST;\n}\n\n// Capture script src at load time - document.currentScript only available during initial execution\nlet capturedScriptHost: string | null = null;\n\nfunction getScriptHost(): string | null {\n if (capturedScriptHost !== null) {\n return capturedScriptHost;\n }\n\n if (!hasDom()) {\n return null;\n }\n\n const currentScript = document.currentScript as HTMLScriptElement | null;\n if (currentScript?.src) {\n try {\n capturedScriptHost = new URL(currentScript.src).origin;\n return capturedScriptHost;\n } catch {\n // Invalid URL, ignore\n }\n }\n\n capturedScriptHost = \"\"; // Mark as attempted\n return null;\n}\n\n// Capture script host immediately when module loads (in browser)\nif (hasDom()) {\n getScriptHost();\n}\n","/**\n * Shared constants for Perspective Embed SDK\n * This file is SSR-safe - no DOM access at import time\n * Used by both SDK bundle and the main Perspective app\n */\n\n// ============================================================================\n// SDK Version & Features\n// ============================================================================\n\n/** SDK version for handshake protocol */\nexport const SDK_VERSION = \"1.0.0\";\n\n/** Feature flags as bitset for version negotiation */\nexport const FEATURES = {\n RESIZE: 1 << 0, // 0b0001\n THEME_SYNC: 1 << 1, // 0b0010\n ANON_ID: 1 << 2, // 0b0100\n SCROLLBAR_STYLES: 1 << 3, // 0b1000\n} as const;\n\n/** Current SDK feature set */\nexport const CURRENT_FEATURES =\n FEATURES.RESIZE |\n FEATURES.THEME_SYNC |\n FEATURES.ANON_ID |\n FEATURES.SCROLLBAR_STYLES;\n\n// ============================================================================\n// URL Parameter Keys\n// ============================================================================\n\nexport const PARAM_KEYS = {\n // User identification\n email: \"email\",\n name: \"name\",\n\n // Navigation\n returnUrl: \"returnUrl\",\n\n // Interview behavior\n voice: \"voice\",\n scroll: \"scroll\",\n hideProgress: \"hideProgress\",\n hideGreeting: \"hideGreeting\",\n hideBranding: \"hideBranding\",\n\n // Interview mode & auth\n mode: \"mode\",\n invite: \"invite\",\n\n // System (internal)\n embed: \"embed\",\n embedType: \"embed_type\",\n theme: \"theme\",\n} as const;\n\nexport type ParamKey = (typeof PARAM_KEYS)[keyof typeof PARAM_KEYS];\n\n// ============================================================================\n// Brand Color Keys\n// ============================================================================\n\nexport const BRAND_KEYS = {\n // Light mode\n primary: \"brand.primary\",\n secondary: \"brand.secondary\",\n bg: \"brand.bg\",\n text: \"brand.text\",\n\n // Dark mode\n darkPrimary: \"brand.dark.primary\",\n darkSecondary: \"brand.dark.secondary\",\n darkBg: \"brand.dark.bg\",\n darkText: \"brand.dark.text\",\n} as const;\n\nexport type BrandKey = (typeof BRAND_KEYS)[keyof typeof BRAND_KEYS];\n\n// ============================================================================\n// UTM Parameters (auto-forwarded from parent URL)\n// ============================================================================\n\nexport const UTM_PARAMS = [\n \"utm_source\",\n \"utm_medium\",\n \"utm_campaign\",\n \"utm_term\",\n \"utm_content\",\n] as const;\n\nexport type UtmParam = (typeof UTM_PARAMS)[number];\n\n// ============================================================================\n// Reserved Parameters (cannot be overridden via custom params)\n// ============================================================================\n\nexport const RESERVED_PARAMS: Set<string> = new Set([\n PARAM_KEYS.embed,\n PARAM_KEYS.embedType,\n PARAM_KEYS.theme,\n BRAND_KEYS.primary,\n BRAND_KEYS.secondary,\n BRAND_KEYS.bg,\n BRAND_KEYS.text,\n BRAND_KEYS.darkPrimary,\n BRAND_KEYS.darkSecondary,\n BRAND_KEYS.darkBg,\n BRAND_KEYS.darkText,\n ...UTM_PARAMS,\n]);\n\n// ============================================================================\n// Data Attributes (HTML declarative initialization)\n// ============================================================================\n\nexport const DATA_ATTRS = {\n widget: \"data-perspective-widget\",\n popup: \"data-perspective-popup\",\n slider: \"data-perspective-slider\",\n float: \"data-perspective-float\", // Primary name\n chat: \"data-perspective-chat\", // Legacy alias\n fullpage: \"data-perspective-fullpage\",\n params: \"data-perspective-params\",\n brand: \"data-perspective-brand\",\n brandDark: \"data-perspective-brand-dark\",\n theme: \"data-perspective-theme\",\n noStyle: \"data-perspective-no-style\",\n} as const;\n\nexport type DataAttr = (typeof DATA_ATTRS)[keyof typeof DATA_ATTRS];\n\n// ============================================================================\n// PostMessage Event Types\n// ============================================================================\n\nexport const MESSAGE_TYPES = {\n // SDK -> Iframe (initialization)\n init: \"perspective:init\",\n\n // Iframe -> SDK\n ready: \"perspective:ready\",\n resize: \"perspective:resize\",\n submit: \"perspective:submit\",\n close: \"perspective:close\",\n error: \"perspective:error\",\n redirect: \"perspective:redirect\",\n\n // SDK -> Iframe (internal)\n anonId: \"perspective:anon-id\",\n injectStyles: \"perspective:inject-styles\",\n themeChange: \"perspective:theme-change\",\n\n // Iframe -> SDK (internal)\n requestScrollbarStyles: \"perspective:request-scrollbar-styles\",\n} as const;\n\nexport type MessageType = (typeof MESSAGE_TYPES)[keyof typeof MESSAGE_TYPES];\n\n// ============================================================================\n// Error Codes\n// ============================================================================\n\nexport const ERROR_CODES = {\n SDK_OUTDATED: \"SDK_OUTDATED\",\n INVALID_RESEARCH: \"INVALID_RESEARCH\",\n UNKNOWN: \"UNKNOWN\",\n} as const;\n\nexport type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES];\n\n// ============================================================================\n// Param Values (for boolean-like string params)\n// ============================================================================\n\nexport const PARAM_VALUES = {\n disabled: \"0\",\n enabled: \"1\",\n true: \"true\",\n false: \"false\",\n} as const;\n\n// ============================================================================\n// Theme Values\n// ============================================================================\n\nexport const THEME_VALUES = {\n dark: \"dark\",\n light: \"light\",\n system: \"system\",\n} as const;\n\nexport type ThemeValue = (typeof THEME_VALUES)[keyof typeof THEME_VALUES];\n\n// ============================================================================\n// Interview Mode Values (for mode param)\n// ============================================================================\n\nexport const MODE_VALUES = {\n preview: \"preview\",\n restart: \"restart\",\n normal: \"normal\",\n simulated: \"simulated\",\n} as const;\n\nexport type ModeValue = (typeof MODE_VALUES)[keyof typeof MODE_VALUES];\n\n// ============================================================================\n// localStorage Keys\n// ============================================================================\n\nexport const STORAGE_KEYS = {\n anonId: \"perspective-anon-id\",\n} as const;\n","/**\n * Shared utilities for the Perspective Embed SDK\n * SSR-safe - DOM access is guarded\n */\n\nimport { THEME_VALUES, type ThemeValue } from \"./constants\";\nimport { hasDom } from \"./config\";\n\n/**\n * Join class names, filtering out falsy values\n */\nexport function cn(...classes: (string | false | null | undefined)[]): string {\n return classes\n .map((c) => (c || \"\").split(\" \"))\n .flat()\n .filter(Boolean)\n .join(\" \");\n}\n\n/**\n * Get the perspective theme class based on the theme value\n * Returns \"perspective-{theme}-theme\" when theme is available, undefined otherwise\n */\nexport function getThemeClass(theme: string | undefined): string | undefined {\n return theme && theme !== THEME_VALUES.system\n ? `perspective-${theme}-theme`\n : undefined;\n}\n\n/**\n * Resolve whether dark mode should be used.\n * Priority: 1) explicit theme override, 2) system preference\n * SSR-safe: defaults to light theme on server\n */\nexport function resolveIsDark(theme?: ThemeValue | string): boolean {\n if (theme === THEME_VALUES.dark) return true;\n if (theme === THEME_VALUES.light) return false;\n // system or undefined → use system preference (or light on server)\n if (!hasDom()) return false;\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n}\n\n/**\n * Resolve effective theme based on override and system preference\n * Returns the theme string ('light' or 'dark')\n */\nexport function resolveTheme(themeOverride?: ThemeValue): \"light\" | \"dark\" {\n return resolveIsDark(themeOverride) ? \"dark\" : \"light\";\n}\n\n/**\n * Normalize and validate hex color. Returns undefined for invalid colors.\n */\nexport function normalizeHex(color: string): string | undefined {\n const trimmed = color.trim();\n if (!trimmed) return undefined;\n\n const normalized = trimmed.startsWith(\"#\") ? trimmed : `#${trimmed}`;\n\n // Validate hex format (#RGB, #RRGGBB, or #RRGGBBAA)\n if (/^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$/.test(normalized)) {\n return normalized;\n }\n\n // Try to extract valid hex chars\n const hexChars = normalized.slice(1).replace(/[^0-9a-fA-F]/g, \"\");\n if (hexChars.length >= 6) return `#${hexChars.slice(0, 6)}`;\n if (hexChars.length >= 3) return `#${hexChars.slice(0, 3)}`;\n\n return undefined;\n}\n\n/**\n * Convert hex to rgba for spinner track\n */\nexport function hexToRgba(hex: string, alpha: number): string {\n const result = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n if (!result || !result[1] || !result[2] || !result[3]) {\n return `rgba(118, 41, 200, ${alpha})`;\n }\n\n const r = parseInt(result[1], 16);\n const g = parseInt(result[2], 16);\n const b = parseInt(result[3], 16);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n","/**\n * iframe creation and postMessage communication\n * SSR-safe - all DOM access is guarded\n */\n\nimport type {\n BrandColors,\n EmbedConfig,\n EmbedMessage,\n EmbedType,\n} from \"./types\";\nimport { hasDom } from \"./config\";\nimport {\n UTM_PARAMS,\n RESERVED_PARAMS,\n PARAM_KEYS,\n BRAND_KEYS,\n MESSAGE_TYPES,\n THEME_VALUES,\n PARAM_VALUES,\n STORAGE_KEYS,\n SDK_VERSION,\n CURRENT_FEATURES,\n} from \"./constants\";\nimport { normalizeHex } from \"./utils\";\n\n/** Validate redirect URL - allow https, http localhost, and relative URLs */\nfunction isAllowedRedirectUrl(url: string): boolean {\n if (!url || typeof url !== \"string\") return false;\n try {\n const parsed = new URL(url, window.location.origin);\n const protocol = parsed.protocol.toLowerCase();\n const hostname = parsed.hostname.toLowerCase();\n\n if (protocol === \"https:\") return true;\n if (\n protocol === \"http:\" &&\n (hostname === \"localhost\" || hostname === \"127.0.0.1\")\n )\n return true;\n\n return false;\n } catch {\n return false;\n }\n}\n\n/** Get or create persistent anonymous ID */\nfunction getOrCreateAnonId(): string {\n if (!hasDom()) return \"\";\n\n try {\n let id = localStorage.getItem(STORAGE_KEYS.anonId);\n if (!id) {\n id = crypto.randomUUID();\n localStorage.setItem(STORAGE_KEYS.anonId, id);\n }\n return id;\n } catch {\n // localStorage might be blocked\n return crypto.randomUUID();\n }\n}\n\n/** Collect UTM params from current page URL */\nfunction getUtmParams(): Record<string, string> {\n if (!hasDom()) return {};\n\n const params: Record<string, string> = {};\n const searchParams = new URLSearchParams(window.location.search);\n\n for (const key of UTM_PARAMS) {\n const value = searchParams.get(key);\n if (value) {\n params[key] = value;\n }\n }\n\n return params;\n}\n\n/** Build iframe URL with all params */\nfunction buildIframeUrl(\n researchId: string,\n type: EmbedType,\n host: string,\n customParams?: Record<string, string>,\n brand?: { light?: BrandColors; dark?: BrandColors },\n themeOverride?: \"dark\" | \"light\" | \"system\"\n): string {\n const url = new URL(`${host}/interview/${researchId}`);\n\n // Base embed params\n url.searchParams.set(PARAM_KEYS.embed, PARAM_VALUES.true);\n url.searchParams.set(PARAM_KEYS.embedType, type === \"float\" ? \"chat\" : type);\n\n // Detect and pass system theme preference (can be overridden)\n if (hasDom()) {\n const isDark = window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n if (themeOverride && themeOverride !== THEME_VALUES.system) {\n url.searchParams.set(PARAM_KEYS.theme, themeOverride);\n } else {\n url.searchParams.set(\n PARAM_KEYS.theme,\n isDark ? THEME_VALUES.dark : THEME_VALUES.light\n );\n }\n } else {\n // SSR fallback\n url.searchParams.set(PARAM_KEYS.theme, themeOverride || THEME_VALUES.light);\n }\n\n // Auto-forward UTM params from parent\n const utmParams = getUtmParams();\n for (const [key, value] of Object.entries(utmParams)) {\n url.searchParams.set(key, value);\n }\n\n // Helper to set param only if color is valid\n const setColor = (key: string, color: string | undefined) => {\n if (!color) return;\n const normalized = normalizeHex(color);\n if (normalized) url.searchParams.set(key, normalized);\n };\n\n // Add brand colors using short keys\n if (brand?.light) {\n setColor(BRAND_KEYS.primary, brand.light.primary);\n setColor(BRAND_KEYS.secondary, brand.light.secondary);\n setColor(BRAND_KEYS.bg, brand.light.bg);\n setColor(BRAND_KEYS.text, brand.light.text);\n }\n\n // Add dark mode brand colors\n if (brand?.dark) {\n setColor(BRAND_KEYS.darkPrimary, brand.dark.primary);\n setColor(BRAND_KEYS.darkSecondary, brand.dark.secondary);\n setColor(BRAND_KEYS.darkBg, brand.dark.bg);\n setColor(BRAND_KEYS.darkText, brand.dark.text);\n }\n\n // Add custom params, filtering out reserved keys\n if (customParams) {\n for (const [key, value] of Object.entries(customParams)) {\n if (!RESERVED_PARAMS.has(key)) {\n url.searchParams.set(key, value);\n }\n }\n }\n\n return url.toString();\n}\n\nexport function createIframe(\n researchId: string,\n type: EmbedType,\n host: string,\n params?: Record<string, string>,\n brand?: { light?: BrandColors; dark?: BrandColors },\n themeOverride?: \"dark\" | \"light\" | \"system\"\n): HTMLIFrameElement {\n if (!hasDom()) {\n // Return a stub for SSR\n return {} as HTMLIFrameElement;\n }\n\n const iframe = document.createElement(\"iframe\");\n iframe.src = buildIframeUrl(\n researchId,\n type,\n host,\n params,\n brand,\n themeOverride\n );\n iframe.setAttribute(\"allow\", \"microphone; camera\");\n iframe.setAttribute(\"allowfullscreen\", \"true\");\n iframe.setAttribute(\n \"sandbox\",\n \"allow-scripts allow-same-origin allow-forms allow-popups allow-modals allow-top-navigation\"\n );\n iframe.setAttribute(\"data-perspective\", \"true\");\n iframe.style.cssText = \"border:none;\";\n\n return iframe;\n}\n\nexport function setupMessageListener(\n researchId: string,\n config: Partial<EmbedConfig>,\n iframe: HTMLIFrameElement,\n host: string,\n options?: { skipResize?: boolean }\n): () => void {\n if (!hasDom()) {\n return () => {};\n }\n\n const handler = (event: MessageEvent<EmbedMessage>) => {\n // Security: Only accept messages from our embed host and from the expected iframe\n if (event.origin !== host) return;\n if (event.source !== iframe.contentWindow) return;\n\n // Only process messages from our embed\n if (typeof event.data?.type !== \"string\") return;\n if (!event.data.type.startsWith(\"perspective:\")) return;\n if (event.data.researchId !== researchId) return;\n\n switch (event.data.type) {\n case MESSAGE_TYPES.ready:\n // Send scrollbar styles when iframe is ready\n sendScrollbarStyles(iframe, host);\n // Send anon_id for anonymous auth\n sendMessage(iframe, host, {\n type: MESSAGE_TYPES.anonId,\n anonId: getOrCreateAnonId(),\n });\n // Send init message with version/features for handshake\n sendMessage(iframe, host, {\n type: MESSAGE_TYPES.init,\n version: SDK_VERSION,\n features: CURRENT_FEATURES,\n researchId,\n });\n config.onReady?.();\n break;\n\n case MESSAGE_TYPES.resize:\n // Auto-resize iframe height (skip for fixed-container embeds)\n if (!options?.skipResize) {\n iframe.style.height = `${event.data.height}px`;\n }\n break;\n\n case MESSAGE_TYPES.submit:\n config.onSubmit?.({ researchId });\n break;\n\n case MESSAGE_TYPES.close:\n config.onClose?.();\n break;\n\n case MESSAGE_TYPES.error:\n const error = new Error(\n event.data.error\n ) as import(\"./types\").EmbedError;\n error.code =\n (event.data.code as import(\"./types\").ErrorCode) || \"UNKNOWN\";\n config.onError?.(error);\n break;\n\n case MESSAGE_TYPES.redirect:\n const redirectUrl = event.data.url;\n // Security: Only allow http(s) and localhost URLs\n if (!isAllowedRedirectUrl(redirectUrl)) {\n console.warn(\n \"[Perspective] Blocked unsafe redirect URL:\",\n redirectUrl\n );\n return;\n }\n if (config.onNavigate) {\n config.onNavigate(redirectUrl);\n } else {\n // Fallback: auto-navigate parent page\n window.location.href = redirectUrl;\n }\n break;\n }\n };\n\n window.addEventListener(\"message\", handler);\n return () => window.removeEventListener(\"message\", handler);\n}\n\n/** Send a message to the embed iframe */\nexport function sendMessage(\n iframe: HTMLIFrameElement,\n host: string,\n message: { type: string; [key: string]: unknown }\n): void {\n if (!hasDom()) return;\n iframe.contentWindow?.postMessage(message, host);\n}\n\n/** Track all active iframes for theme change notifications */\nconst activeIframes = new Map<HTMLIFrameElement, string>();\n\nexport function registerIframe(\n iframe: HTMLIFrameElement,\n host: string\n): () => void {\n activeIframes.set(iframe, host);\n return () => {\n activeIframes.delete(iframe);\n if (activeIframes.size === 0) {\n teardownGlobalListeners();\n }\n };\n}\n\n/** Get scrollbar CSS styles */\nfunction getScrollbarStyles(): string {\n if (!hasDom()) return \"\";\n\n const isDark = window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n const borderColor = isDark ? \"hsl(217 33% 17%)\" : \"hsl(240 6% 90%)\";\n\n return `\n * {\n scrollbar-width: thin;\n scrollbar-color: ${borderColor} transparent;\n }\n *::-webkit-scrollbar {\n width: 10px;\n height: 10px;\n }\n *::-webkit-scrollbar-track {\n background: transparent;\n }\n *::-webkit-scrollbar-thumb {\n background-color: ${borderColor};\n border-radius: 9999px;\n border: 2px solid transparent;\n background-clip: padding-box;\n }\n *::-webkit-scrollbar-thumb:hover {\n background-color: color-mix(in srgb, ${borderColor} 80%, currentColor);\n }\n `;\n}\n\n/** Send scrollbar styles to an iframe */\nexport function sendScrollbarStyles(\n iframe: HTMLIFrameElement,\n host: string\n): void {\n const styles = getScrollbarStyles();\n sendMessage(iframe, host, {\n type: MESSAGE_TYPES.injectStyles,\n styles,\n });\n}\n\n/** Notify all active iframes of theme change */\nexport function notifyThemeChange(): void {\n if (!hasDom()) return;\n\n const isDark = window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n\n activeIframes.forEach((host, iframe) => {\n const message = {\n type: MESSAGE_TYPES.themeChange,\n theme: isDark ? THEME_VALUES.dark : THEME_VALUES.light,\n };\n sendMessage(iframe, host, message);\n sendScrollbarStyles(iframe, host);\n });\n}\n\nlet themeListener: ((e: MediaQueryListEvent) => void) | null = null;\nlet themeMediaQuery: MediaQueryList | null = null;\nlet globalMessageHandler: ((event: MessageEvent) => void) | null = null;\nlet globalListenersInitialized = false;\n\nfunction setupThemeListener(): void {\n if (themeListener || !hasDom()) return;\n\n themeMediaQuery = window.matchMedia(\"(prefers-color-scheme: dark)\");\n themeListener = () => notifyThemeChange();\n themeMediaQuery.addEventListener(\"change\", themeListener);\n}\n\nfunction teardownThemeListener(): void {\n if (themeListener && themeMediaQuery) {\n themeMediaQuery.removeEventListener(\"change\", themeListener);\n themeListener = null;\n themeMediaQuery = null;\n }\n}\n\nfunction setupGlobalListeners(): void {\n if (!hasDom() || globalMessageHandler) return;\n\n setupThemeListener();\n\n globalMessageHandler = (event: MessageEvent) => {\n if (!event.data?.type?.startsWith(\"perspective:\")) return;\n if (event.data.type === MESSAGE_TYPES.requestScrollbarStyles) {\n const iframes = Array.from(\n document.querySelectorAll(\"iframe[data-perspective]\")\n );\n const sourceIframe = iframes.find(\n (iframe) => (iframe as HTMLIFrameElement).contentWindow === event.source\n ) as HTMLIFrameElement | undefined;\n if (sourceIframe) {\n const host = activeIframes.get(sourceIframe);\n if (host && event.origin === host) {\n sendScrollbarStyles(sourceIframe, host);\n }\n }\n }\n };\n\n window.addEventListener(\"message\", globalMessageHandler);\n}\n\nfunction teardownGlobalListeners(): void {\n if (globalMessageHandler) {\n window.removeEventListener(\"message\", globalMessageHandler);\n globalMessageHandler = null;\n }\n teardownThemeListener();\n globalListenersInitialized = false;\n}\n\nexport function ensureGlobalListeners(): void {\n if (globalListenersInitialized) return;\n globalListenersInitialized = true;\n setupGlobalListeners();\n}\n","/**\n * Loading indicator for embed iframes\n * SSR-safe - returns no-op on server\n */\n\nimport type { BrandColors, ThemeValue } from \"./types\";\nimport { hasDom } from \"./config\";\nimport { resolveTheme, hexToRgba } from \"./utils\";\n\n/** Default colors matching codebase theme */\nconst DEFAULT_COLORS = {\n light: {\n bg: \"#ffffff\",\n primary: \"#7629C8\",\n },\n dark: {\n bg: \"#02040a\",\n primary: \"#B170FF\",\n },\n};\n\nexport interface LoadingOptions {\n /** Theme override: 'dark', 'light', or 'system' (uses system preference) */\n theme?: ThemeValue;\n /** Brand colors - uses primary color for spinner */\n brand?: {\n light?: BrandColors;\n dark?: BrandColors;\n };\n}\n\n/** Get colors for loading indicator based on theme and brand */\nfunction getLoadingColors(options?: LoadingOptions): {\n bg: string;\n primary: string;\n} {\n const theme = resolveTheme(options?.theme);\n const isDark = theme === \"dark\";\n\n // Get brand colors for current theme\n const brandColors = isDark ? options?.brand?.dark : options?.brand?.light;\n\n return {\n bg:\n brandColors?.bg ||\n (isDark ? DEFAULT_COLORS.dark.bg : DEFAULT_COLORS.light.bg),\n primary:\n brandColors?.primary ||\n (isDark ? DEFAULT_COLORS.dark.primary : DEFAULT_COLORS.light.primary),\n };\n}\n\nexport function createLoadingIndicator(options?: LoadingOptions): HTMLElement {\n // SSR safety - return empty div on server\n if (!hasDom()) {\n return { remove: () => {}, style: {} } as unknown as HTMLElement;\n }\n\n const colors = getLoadingColors(options);\n\n const container = document.createElement(\"div\");\n container.className = \"perspective-loading\";\n container.style.cssText = `\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n bottom: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: ${colors.bg};\n transition: opacity 0.3s ease;\n z-index: 1;\n `;\n\n // Create spinner (keyframes defined in styles.ts)\n const spinner = document.createElement(\"div\");\n spinner.style.cssText = `\n width: 2.5rem;\n height: 2.5rem;\n border: 3px solid ${hexToRgba(colors.primary, 0.15)};\n border-top-color: ${colors.primary};\n border-radius: 50%;\n animation: perspective-spin 0.8s linear infinite;\n `;\n\n container.appendChild(spinner);\n return container;\n}\n","/**\n * CSS styles injected by the embed script\n * SSR-safe - DOM access is guarded\n */\n\nimport { hasDom } from \"./config\";\n\nlet stylesInjected = false;\n\nconst LIGHT_THEME = `\n --perspective-overlay-bg: rgba(0, 0, 0, 0.5);\n --perspective-modal-bg: #ffffff;\n --perspective-modal-text: #151B23;\n --perspective-close-bg: rgba(0, 0, 0, 0.1);\n --perspective-close-text: #666666;\n --perspective-close-hover-bg: rgba(0, 0, 0, 0.2);\n --perspective-close-hover-text: #333333;\n --perspective-border: hsl(240 6% 90%);\n`;\n\nconst DARK_THEME = `\n --perspective-overlay-bg: rgba(0, 0, 0, 0.7);\n --perspective-modal-bg: #02040a;\n --perspective-modal-text: #ffffff;\n --perspective-close-bg: rgba(255, 255, 255, 0.1);\n --perspective-close-text: #a0a0a0;\n --perspective-close-hover-bg: rgba(255, 255, 255, 0.2);\n --perspective-close-hover-text: #ffffff;\n --perspective-border: hsl(217 33% 17%);\n`;\n\nexport function injectStyles(): void {\n if (!hasDom()) return;\n if (stylesInjected) return;\n stylesInjected = true;\n\n const style = document.createElement(\"style\");\n style.id = \"perspective-embed-styles\";\n style.textContent = `\n /* Theme-aware color variables */\n .perspective-embed-root, .perspective-light-theme {\n ${LIGHT_THEME}\n --perspective-shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);\n --perspective-shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);\n --perspective-shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);\n --perspective-shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n --perspective-radius: 1.2rem;\n --perspective-radius-sm: calc(var(--perspective-radius) - 4px);\n }\n\n /* Dark theme */\n .perspective-dark-theme {\n ${DARK_THEME}\n }\n\n /* System dark mode support */\n @media (prefers-color-scheme: dark) {\n .perspective-embed-root:not(.perspective-light-theme) {\n ${DARK_THEME}\n }\n }\n\n /* Scrollbar styling */\n .perspective-modal,\n .perspective-slider,\n .perspective-float-window,\n .perspective-chat-window {\n scrollbar-width: thin;\n scrollbar-color: var(--perspective-border) transparent;\n }\n\n .perspective-modal::-webkit-scrollbar,\n .perspective-slider::-webkit-scrollbar,\n .perspective-float-window::-webkit-scrollbar,\n .perspective-chat-window::-webkit-scrollbar {\n width: 10px;\n height: 10px;\n }\n\n .perspective-modal::-webkit-scrollbar-track,\n .perspective-slider::-webkit-scrollbar-track,\n .perspective-float-window::-webkit-scrollbar-track,\n .perspective-chat-window::-webkit-scrollbar-track {\n background: transparent;\n }\n\n .perspective-modal::-webkit-scrollbar-thumb,\n .perspective-slider::-webkit-scrollbar-thumb,\n .perspective-float-window::-webkit-scrollbar-thumb,\n .perspective-chat-window::-webkit-scrollbar-thumb {\n background-color: var(--perspective-border);\n border-radius: 9999px;\n border: 2px solid transparent;\n background-clip: padding-box;\n }\n\n .perspective-modal::-webkit-scrollbar-thumb:hover,\n .perspective-slider::-webkit-scrollbar-thumb:hover,\n .perspective-float-window::-webkit-scrollbar-thumb:hover,\n .perspective-chat-window::-webkit-scrollbar-thumb:hover {\n background-color: color-mix(in srgb, var(--perspective-border) 80%, currentColor);\n }\n\n /* Overlay for popup/modal */\n .perspective-overlay {\n position: fixed;\n inset: 0;\n background: var(--perspective-overlay-bg);\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 9999;\n animation: perspective-fade-in 0.2s ease-out;\n }\n\n @keyframes perspective-fade-in {\n from { opacity: 0; }\n to { opacity: 1; }\n }\n\n @keyframes perspective-spin {\n to { transform: rotate(360deg); }\n }\n\n /* Modal container */\n .perspective-modal {\n position: relative;\n width: 90%;\n max-width: 600px;\n height: 80vh;\n max-height: 700px;\n background: var(--perspective-modal-bg);\n color: var(--perspective-modal-text);\n border-radius: var(--perspective-radius);\n overflow: hidden;\n box-shadow: var(--perspective-shadow-xl);\n animation: perspective-slide-up 0.3s ease-out;\n }\n\n @keyframes perspective-slide-up {\n from {\n opacity: 0;\n transform: translateY(20px) scale(0.95);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n }\n\n .perspective-modal iframe {\n width: 100%;\n height: 100%;\n border: none;\n }\n\n /* Close button */\n .perspective-close {\n position: absolute;\n top: 1rem;\n right: 1.5rem;\n width: 2rem;\n height: 2rem;\n border: none;\n background: var(--perspective-close-bg);\n color: var(--perspective-close-text);\n border-radius: 50%;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 1rem;\n z-index: 10;\n transition: background-color 0.2s ease, color 0.2s ease;\n }\n\n .perspective-close:hover {\n background: var(--perspective-close-hover-bg);\n color: var(--perspective-close-hover-text);\n }\n\n .perspective-close:focus-visible {\n outline: 2px solid currentColor;\n outline-offset: 2px;\n }\n\n .perspective-close svg {\n width: 1rem;\n height: 1rem;\n stroke-width: 2;\n }\n\n /* Slider drawer */\n .perspective-slider {\n position: fixed;\n top: 0;\n right: 0;\n width: 100%;\n max-width: 450px;\n height: 100%;\n background: var(--perspective-modal-bg);\n color: var(--perspective-modal-text);\n box-shadow: var(--perspective-shadow-xl);\n z-index: 9999;\n animation: perspective-slide-in 0.3s ease-out;\n }\n\n @keyframes perspective-slide-in {\n from { transform: translateX(100%); }\n to { transform: translateX(0); }\n }\n\n .perspective-slider iframe {\n width: 100%;\n height: 100%;\n border: none;\n }\n\n .perspective-slider .perspective-close {\n top: 1rem;\n right: 2rem;\n }\n\n /* Slider backdrop */\n .perspective-slider-backdrop {\n position: fixed;\n inset: 0;\n background: var(--perspective-overlay-bg);\n z-index: 9998;\n animation: perspective-fade-in 0.2s ease-out;\n }\n\n /* Float bubble (and legacy chat-bubble alias) */\n .perspective-float-bubble,\n .perspective-chat-bubble {\n position: fixed;\n bottom: 1.5rem;\n right: 1.5rem;\n width: 3.75rem;\n height: 3.75rem;\n border-radius: 50%;\n background: var(--perspective-float-bg, var(--perspective-chat-bg, #7629C8));\n color: white;\n border: none;\n cursor: pointer;\n box-shadow: var(--perspective-float-shadow, var(--perspective-chat-shadow, 0 4px 12px rgba(118, 41, 200, 0.4)));\n z-index: 9996;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: transform 0.2s ease, box-shadow 0.2s ease;\n }\n\n .perspective-float-bubble:hover,\n .perspective-chat-bubble:hover {\n transform: scale(1.05);\n box-shadow: var(--perspective-float-shadow-hover, var(--perspective-chat-shadow-hover, 0 6px 16px rgba(118, 41, 200, 0.5)));\n }\n\n .perspective-float-bubble:focus-visible,\n .perspective-chat-bubble:focus-visible {\n outline: 2px solid currentColor;\n outline-offset: 2px;\n }\n\n .perspective-float-bubble svg,\n .perspective-chat-bubble svg {\n width: 1.75rem;\n height: 1.75rem;\n stroke-width: 2;\n }\n\n /* Float window (and legacy chat-window alias) */\n .perspective-float-window,\n .perspective-chat-window {\n position: fixed;\n bottom: 6.25rem;\n right: 1.5rem;\n width: 380px;\n height: calc(100vh - 8.75rem);\n max-height: 600px;\n background: var(--perspective-modal-bg);\n color: var(--perspective-modal-text);\n border-radius: var(--perspective-radius);\n overflow: hidden;\n box-shadow: var(--perspective-shadow-xl);\n z-index: 9997;\n animation: perspective-float-open 0.3s ease-out;\n }\n\n @keyframes perspective-float-open {\n from {\n opacity: 0;\n transform: translateY(20px) scale(0.9);\n }\n to {\n opacity: 1;\n transform: translateY(0) scale(1);\n }\n }\n\n .perspective-float-window iframe,\n .perspective-chat-window iframe {\n width: 100%;\n height: 100%;\n border: none;\n }\n\n .perspective-float-window .perspective-close,\n .perspective-chat-window .perspective-close {\n top: 1rem;\n right: 1.5rem;\n }\n\n /* Fullpage */\n .perspective-fullpage {\n position: fixed;\n inset: 0;\n z-index: 9999;\n background: var(--perspective-modal-bg);\n }\n\n .perspective-fullpage iframe {\n width: 100%;\n height: 100%;\n border: none;\n }\n\n /* Responsive */\n @media (max-width: 640px) {\n .perspective-modal {\n width: 100%;\n height: 100%;\n max-width: none;\n max-height: none;\n border-radius: 0;\n }\n\n .perspective-slider {\n max-width: 100%;\n }\n\n .perspective-float-window,\n .perspective-chat-window {\n width: calc(100% - 2rem);\n right: 1rem;\n bottom: 5.625rem;\n height: calc(100vh - 7.5rem);\n }\n\n .perspective-float-bubble,\n .perspective-chat-bubble {\n bottom: 1rem;\n right: 1rem;\n }\n }\n\n @media (max-width: 450px) {\n .perspective-float-window,\n .perspective-chat-window {\n width: calc(100% - 1rem);\n right: 0.5rem;\n bottom: 5rem;\n height: calc(100vh - 6.5rem);\n }\n\n .perspective-float-bubble,\n .perspective-chat-bubble {\n bottom: 0.75rem;\n right: 0.75rem;\n width: 3.5rem;\n height: 3.5rem;\n }\n\n .perspective-float-bubble svg,\n .perspective-chat-bubble svg {\n width: 1.5rem;\n height: 1.5rem;\n }\n }\n `;\n\n document.head.appendChild(style);\n}\n\nexport const MIC_ICON = `<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M12 18.75a6 6 0 006-6v-1.5m-6 7.5a6 6 0 01-6-6v-1.5m6 7.5v3.75m-3.75 0h7.5M12 15.75a3 3 0 01-3-3V4.5a3 3 0 116 0v8.25a3 3 0 01-3 3z\" />\n</svg>`;\n\n/** @deprecated Use MIC_ICON instead */\nexport const CHAT_ICON = MIC_ICON;\n\nexport const CLOSE_ICON = `<svg xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M6 18L18 6M6 6l12 12\" />\n</svg>`;\n","/**\n * Inline widget embed - renders directly in a container element\n * SSR-safe - returns no-op handle on server\n */\n\nimport type { EmbedConfig, EmbedHandle } from \"./types\";\nimport { hasDom, getHost } from \"./config\";\nimport {\n createIframe,\n setupMessageListener,\n registerIframe,\n ensureGlobalListeners,\n} from \"./iframe\";\nimport { createLoadingIndicator } from \"./loading\";\nimport { injectStyles } from \"./styles\";\nimport { cn, getThemeClass } from \"./utils\";\n\ntype WidgetResources = {\n cleanup: () => void;\n unregister: () => void;\n wrapper: HTMLElement;\n};\n\nconst widgetResources = new WeakMap<HTMLIFrameElement, WidgetResources>();\n\nfunction createNoOpHandle(researchId: string, type: \"widget\"): EmbedHandle {\n return {\n unmount: () => {},\n update: () => {},\n destroy: () => {},\n researchId,\n type,\n iframe: null,\n container: null,\n };\n}\n\nfunction createExistingWidgetHandle(\n container: HTMLElement,\n researchId: string\n): EmbedHandle {\n const existingWrapper = container.querySelector<HTMLElement>(\n \".perspective-embed-root\"\n );\n const existingIframe = container.querySelector<HTMLIFrameElement>(\n \"iframe[data-perspective]\"\n );\n\n let destroyed = false;\n\n const unmount = () => {\n if (destroyed) return;\n destroyed = true;\n\n if (existingIframe) {\n const resources = widgetResources.get(existingIframe);\n if (resources) {\n resources.cleanup();\n resources.unregister();\n widgetResources.delete(existingIframe);\n }\n }\n existingWrapper?.remove();\n };\n\n return {\n unmount,\n update: () => {},\n destroy: unmount,\n researchId,\n type: \"widget\" as const,\n iframe: existingIframe,\n container,\n };\n}\n\nexport function createWidget(\n container: HTMLElement | null,\n config: EmbedConfig\n): EmbedHandle {\n const { researchId } = config;\n\n // SSR safety: return no-op handle\n if (!hasDom() || !container) {\n return createNoOpHandle(researchId, \"widget\");\n }\n\n // Idempotency check for React Strict Mode\n if (container.querySelector(\"iframe[data-perspective]\")) {\n return createExistingWidgetHandle(container, researchId);\n }\n\n const host = getHost(config.host);\n\n injectStyles();\n ensureGlobalListeners();\n\n // Create wrapper for positioning\n const wrapper = document.createElement(\"div\");\n wrapper.className = cn(\"perspective-embed-root\", getThemeClass(config.theme));\n wrapper.style.cssText =\n \"position:relative;width:100%;height:100%;min-height:500px;\";\n\n // Create loading indicator with theme and brand colors\n const loading = createLoadingIndicator({\n theme: config.theme,\n brand: config.brand,\n });\n wrapper.appendChild(loading);\n\n // Create iframe (hidden initially)\n const iframe = createIframe(\n researchId,\n \"widget\",\n host,\n config.params,\n config.brand,\n config.theme\n );\n iframe.style.width = \"100%\";\n iframe.style.height = \"100%\";\n iframe.style.minHeight = \"500px\";\n iframe.style.opacity = \"0\";\n iframe.style.transition = \"opacity 0.3s ease\";\n\n wrapper.appendChild(iframe);\n container.appendChild(wrapper);\n\n // Mutable config reference for updates\n let currentConfig = { ...config };\n\n // Set up message listener with loading state handling\n const cleanup = setupMessageListener(\n researchId,\n {\n get onReady() {\n return () => {\n // Hide loading, show iframe\n loading.style.opacity = \"0\";\n iframe.style.opacity = \"1\";\n setTimeout(() => loading.remove(), 300);\n currentConfig.onReady?.();\n };\n },\n get onSubmit() {\n return currentConfig.onSubmit;\n },\n get onNavigate() {\n return currentConfig.onNavigate;\n },\n get onClose() {\n return currentConfig.onClose;\n },\n get onError() {\n return currentConfig.onError;\n },\n },\n iframe,\n host,\n { skipResize: true }\n );\n\n // Register iframe for theme change notifications\n const unregisterIframe = registerIframe(iframe, host);\n\n widgetResources.set(iframe, {\n cleanup,\n unregister: unregisterIframe,\n wrapper,\n });\n\n let destroyed = false;\n\n const unmount = () => {\n if (destroyed) return;\n destroyed = true;\n\n cleanup();\n unregisterIframe();\n widgetResources.delete(iframe);\n wrapper.remove();\n };\n\n return {\n unmount,\n update: (options) => {\n currentConfig = { ...currentConfig, ...options };\n },\n destroy: unmount,\n researchId,\n type: \"widget\" as const,\n iframe,\n container,\n };\n}\n","/**\n * Popup/modal embed - opens in a centered modal overlay\n * SSR-safe - returns no-op handle on server\n */\n\nimport type { EmbedConfig, EmbedHandle } from \"./types\";\nimport { hasDom, getHost } from \"./config\";\nimport {\n createIframe,\n setupMessageListener,\n registerIframe,\n ensureGlobalListeners,\n} from \"./iframe\";\nimport { createLoadingIndicator } from \"./loading\";\nimport { injectStyles, CLOSE_ICON } from \"./styles\";\nimport { cn, getThemeClass } from \"./utils\";\n\nfunction createNoOpHandle(researchId: string): EmbedHandle {\n return {\n unmount: () => {},\n update: () => {},\n destroy: () => {},\n researchId,\n type: \"popup\",\n iframe: null,\n container: null,\n };\n}\n\nexport function openPopup(config: EmbedConfig): EmbedHandle {\n const { researchId } = config;\n\n // SSR safety: return no-op handle\n if (!hasDom()) {\n return createNoOpHandle(researchId);\n }\n const host = getHost(config.host);\n\n injectStyles();\n ensureGlobalListeners();\n\n // Create overlay\n const overlay = document.createElement(\"div\");\n overlay.className = cn(\n \"perspective-overlay perspective-embed-root\",\n getThemeClass(config.theme)\n );\n\n // Create modal container\n const modal = document.createElement(\"div\");\n modal.className = \"perspective-modal\";\n\n // Create close button\n const closeBtn = document.createElement(\"button\");\n closeBtn.className = \"perspective-close\";\n closeBtn.innerHTML = CLOSE_ICON;\n closeBtn.setAttribute(\"aria-label\", \"Close\");\n\n // Create loading indicator with theme and brand colors\n const loading = createLoadingIndicator({\n theme: config.theme,\n brand: config.brand,\n });\n loading.style.borderRadius = \"16px\";\n\n // Create iframe (hidden initially)\n const iframe = createIframe(\n researchId,\n \"popup\",\n host,\n config.params,\n config.brand,\n config.theme\n );\n iframe.style.opacity = \"0\";\n iframe.style.transition = \"opacity 0.3s ease\";\n\n modal.appendChild(closeBtn);\n modal.appendChild(loading);\n modal.appendChild(iframe);\n overlay.appendChild(modal);\n document.body.appendChild(overlay);\n\n // Mutable config reference for updates\n let currentConfig = { ...config };\n let isOpen = true;\n let messageCleanup: (() => void) | null = null;\n\n // Register iframe for theme change notifications\n const unregisterIframe = registerIframe(iframe, host);\n\n const destroy = () => {\n if (!isOpen) return;\n isOpen = false;\n messageCleanup?.();\n unregisterIframe();\n overlay.remove();\n document.removeEventListener(\"keydown\", escHandler);\n currentConfig.onClose?.();\n };\n\n // Set up message listener with loading state handling\n messageCleanup = setupMessageListener(\n researchId,\n {\n get onReady() {\n return () => {\n loading.style.opacity = \"0\";\n iframe.style.opacity = \"1\";\n setTimeout(() => loading.remove(), 300);\n currentConfig.onReady?.();\n };\n },\n get onSubmit() {\n return currentConfig.onSubmit;\n },\n get onNavigate() {\n return currentConfig.onNavigate;\n },\n get onClose() {\n return destroy;\n },\n get onError() {\n return currentConfig.onError;\n },\n },\n iframe,\n host,\n { skipResize: true }\n );\n\n // Close handlers\n closeBtn.addEventListener(\"click\", destroy);\n overlay.addEventListener(\"click\", (e) => {\n if (e.target === overlay) destroy();\n });\n\n // ESC key closes\n const escHandler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n destroy();\n }\n };\n document.addEventListener(\"keydown\", escHandler);\n\n return {\n unmount: destroy,\n update: (options: Parameters<EmbedHandle[\"update\"]>[0]) => {\n currentConfig = { ...currentConfig, ...options };\n },\n destroy,\n researchId,\n type: \"popup\" as const,\n iframe,\n container: overlay,\n };\n}\n","/**\n * Slider/drawer embed - slides in from the right\n * SSR-safe - returns no-op handle on server\n */\n\nimport type { EmbedConfig, EmbedHandle } from \"./types\";\nimport { hasDom, getHost } from \"./config\";\nimport {\n createIframe,\n setupMessageListener,\n registerIframe,\n ensureGlobalListeners,\n} from \"./iframe\";\nimport { createLoadingIndicator } from \"./loading\";\nimport { injectStyles, CLOSE_ICON } from \"./styles\";\nimport { cn, getThemeClass } from \"./utils\";\n\nfunction createNoOpHandle(researchId: string): EmbedHandle {\n return {\n unmount: () => {},\n update: () => {},\n destroy: () => {},\n researchId,\n type: \"slider\",\n iframe: null,\n container: null,\n };\n}\n\nexport function openSlider(config: EmbedConfig): EmbedHandle {\n const { researchId } = config;\n\n // SSR safety: return no-op handle\n if (!hasDom()) {\n return createNoOpHandle(researchId);\n }\n const host = getHost(config.host);\n\n injectStyles();\n ensureGlobalListeners();\n\n // Create backdrop\n const backdrop = document.createElement(\"div\");\n backdrop.className = cn(\n \"perspective-slider-backdrop perspective-embed-root\",\n getThemeClass(config.theme)\n );\n\n // Create slider container\n const slider = document.createElement(\"div\");\n slider.className = cn(\n \"perspective-slider perspective-embed-root\",\n getThemeClass(config.theme)\n );\n\n // Create close button\n const closeBtn = document.createElement(\"button\");\n closeBtn.className = \"perspective-close\";\n closeBtn.innerHTML = CLOSE_ICON;\n closeBtn.setAttribute(\"aria-label\", \"Close\");\n\n // Create loading indicator with theme and brand colors\n const loading = createLoadingIndicator({\n theme: config.theme,\n brand: config.brand,\n });\n\n // Create iframe (hidden initially)\n const iframe = createIframe(\n researchId,\n \"slider\",\n host,\n config.params,\n config.brand,\n config.theme\n );\n iframe.style.opacity = \"0\";\n iframe.style.transition = \"opacity 0.3s ease\";\n\n slider.appendChild(closeBtn);\n slider.appendChild(loading);\n slider.appendChild(iframe);\n document.body.appendChild(backdrop);\n document.body.appendChild(slider);\n\n // Mutable config reference for updates\n let currentConfig = { ...config };\n let isOpen = true;\n let messageCleanup: (() => void) | null = null;\n\n // Register iframe for theme change notifications\n const unregisterIframe = registerIframe(iframe, host);\n\n const destroy = () => {\n if (!isOpen) return;\n isOpen = false;\n messageCleanup?.();\n unregisterIframe();\n slider.remove();\n backdrop.remove();\n document.removeEventListener(\"keydown\", escHandler);\n currentConfig.onClose?.();\n };\n\n // Set up message listener with loading state handling\n messageCleanup = setupMessageListener(\n researchId,\n {\n get onReady() {\n return () => {\n loading.style.opacity = \"0\";\n iframe.style.opacity = \"1\";\n setTimeout(() => loading.remove(), 300);\n currentConfig.onReady?.();\n };\n },\n get onSubmit() {\n return currentConfig.onSubmit;\n },\n get onNavigate() {\n return currentConfig.onNavigate;\n },\n get onClose() {\n return destroy;\n },\n get onError() {\n return currentConfig.onError;\n },\n },\n iframe,\n host,\n { skipResize: true }\n );\n\n // Close handlers\n closeBtn.addEventListener(\"click\", destroy);\n backdrop.addEventListener(\"click\", destroy);\n\n // ESC key closes\n const escHandler = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n destroy();\n }\n };\n document.addEventListener(\"keydown\", escHandler);\n\n return {\n unmount: destroy,\n update: (options: Parameters<EmbedHandle[\"update\"]>[0]) => {\n currentConfig = { ...currentConfig, ...options };\n },\n destroy,\n researchId,\n type: \"slider\" as const,\n iframe,\n container: slider,\n };\n}\n","/**\n * Floating bubble embed - floating button that opens a chat window\n * SSR-safe - returns no-op handle on server\n */\n\nimport type { EmbedConfig, FloatHandle, ThemeConfig } from \"./types\";\nimport { hasDom, getHost } from \"./config\";\nimport {\n createIframe,\n setupMessageListener,\n registerIframe,\n ensureGlobalListeners,\n} from \"./iframe\";\nimport { createLoadingIndicator } from \"./loading\";\nimport { injectStyles, MIC_ICON, CLOSE_ICON } from \"./styles\";\nimport { cn, getThemeClass, resolveIsDark } from \"./utils\";\n\ntype FloatConfig = EmbedConfig & { _themeConfig?: ThemeConfig };\n\nfunction createNoOpHandle(researchId: string): FloatHandle {\n return {\n unmount: () => {},\n update: () => {},\n destroy: () => {},\n open: () => {},\n close: () => {},\n toggle: () => {},\n isOpen: false,\n researchId,\n type: \"float\",\n iframe: null,\n container: null,\n };\n}\n\nexport function createFloatBubble(config: FloatConfig): FloatHandle {\n const { researchId, _themeConfig, theme, brand } = config;\n\n // SSR safety: return no-op handle\n if (!hasDom()) {\n return createNoOpHandle(researchId);\n }\n const host = getHost(config.host);\n\n injectStyles();\n ensureGlobalListeners();\n\n // Create bubble button\n const bubble = document.createElement(\"button\");\n bubble.className = cn(\n \"perspective-float-bubble perspective-embed-root\",\n getThemeClass(config.theme)\n );\n bubble.innerHTML = MIC_ICON;\n bubble.setAttribute(\"aria-label\", \"Open chat\");\n bubble.setAttribute(\"data-perspective\", \"float-bubble\");\n\n // Apply theme color if available\n if (_themeConfig || brand) {\n const isDark = resolveIsDark(theme);\n const bg = isDark\n ? (brand?.dark?.primary ?? _themeConfig?.darkPrimaryColor ?? \"#a78bfa\")\n : (brand?.light?.primary ?? _themeConfig?.primaryColor ?? \"#7c3aed\");\n bubble.style.setProperty(\"--perspective-float-bg\", bg);\n bubble.style.setProperty(\n \"--perspective-float-shadow\",\n `0 4px 12px ${bg}66`\n );\n bubble.style.setProperty(\n \"--perspective-float-shadow-hover\",\n `0 6px 16px ${bg}80`\n );\n bubble.style.backgroundColor = bg;\n bubble.style.boxShadow = `0 4px 12px ${bg}66`;\n }\n\n document.body.appendChild(bubble);\n\n let floatWindow: HTMLElement | null = null;\n let iframe: HTMLIFrameElement | null = null;\n let cleanup: (() => void) | null = null;\n let unregisterIframe: (() => void) | null = null;\n let isOpen = false;\n\n // Mutable config reference for updates\n let currentConfig = { ...config };\n\n const openFloat = () => {\n if (isOpen) return;\n isOpen = true;\n\n // Create float window\n floatWindow = document.createElement(\"div\");\n floatWindow.className = cn(\n \"perspective-float-window perspective-embed-root\",\n getThemeClass(currentConfig.theme)\n );\n\n // Create close button\n const closeBtn = document.createElement(\"button\");\n closeBtn.className = \"perspective-close\";\n closeBtn.innerHTML = CLOSE_ICON;\n closeBtn.setAttribute(\"aria-label\", \"Close chat\");\n closeBtn.addEventListener(\"click\", closeFloat);\n\n // Create loading indicator with theme and brand colors\n const loading = createLoadingIndicator({\n theme: currentConfig.theme,\n brand: currentConfig.brand,\n });\n loading.style.borderRadius = \"16px\";\n\n // Create iframe (hidden initially)\n iframe = createIframe(\n researchId,\n \"float\",\n host,\n currentConfig.params,\n currentConfig.brand,\n currentConfig.theme\n );\n iframe.style.opacity = \"0\";\n iframe.style.transition = \"opacity 0.3s ease\";\n\n floatWindow.appendChild(closeBtn);\n floatWindow.appendChild(loading);\n floatWindow.appendChild(iframe);\n document.body.appendChild(floatWindow);\n\n // Set up message listener with loading state handling\n cleanup = setupMessageListener(\n researchId,\n {\n get onReady() {\n return () => {\n loading.style.opacity = \"0\";\n iframe!.style.opacity = \"1\";\n setTimeout(() => loading.remove(), 300);\n currentConfig.onReady?.();\n };\n },\n get onSubmit() {\n return currentConfig.onSubmit;\n },\n get onNavigate() {\n return currentConfig.onNavigate;\n },\n get onClose() {\n return closeFloat;\n },\n get onError() {\n return currentConfig.onError;\n },\n },\n iframe,\n host,\n { skipResize: true }\n );\n\n // Register iframe for theme change notifications\n if (iframe) {\n unregisterIframe = registerIframe(iframe, host);\n }\n\n // Update bubble icon to close\n bubble.innerHTML = CLOSE_ICON;\n bubble.setAttribute(\"aria-label\", \"Close chat\");\n };\n\n const closeFloat = () => {\n if (!isOpen) return;\n isOpen = false;\n\n cleanup?.();\n unregisterIframe?.();\n floatWindow?.remove();\n floatWindow = null;\n iframe = null;\n cleanup = null;\n unregisterIframe = null;\n\n // Restore bubble icon\n bubble.innerHTML = MIC_ICON;\n bubble.setAttribute(\"aria-label\", \"Open chat\");\n\n currentConfig.onClose?.();\n };\n\n // Toggle on bubble click\n bubble.addEventListener(\"click\", () => {\n if (isOpen) {\n closeFloat();\n } else {\n openFloat();\n }\n });\n\n const unmount = () => {\n closeFloat();\n bubble.remove();\n };\n\n return {\n unmount,\n update: (options: Parameters<FloatHandle[\"update\"]>[0]) => {\n currentConfig = { ...currentConfig, ...options };\n },\n destroy: unmount,\n open: openFloat,\n close: closeFloat,\n toggle: () => {\n if (isOpen) {\n closeFloat();\n } else {\n openFloat();\n }\n },\n get isOpen() {\n return isOpen;\n },\n researchId,\n type: \"float\" as const,\n get iframe() {\n return iframe;\n },\n container: bubble,\n };\n}\n\n/** @deprecated Use createFloatBubble instead */\nexport const createChatBubble = createFloatBubble;\n","/**\n * Fullpage embed - takes over entire viewport\n * SSR-safe - returns no-op handle on server\n */\n\nimport type { EmbedConfig, EmbedHandle } from \"./types\";\nimport { hasDom, getHost } from \"./config\";\nimport {\n createIframe,\n setupMessageListener,\n registerIframe,\n ensureGlobalListeners,\n} from \"./iframe\";\nimport { createLoadingIndicator } from \"./loading\";\nimport { injectStyles } from \"./styles\";\nimport { cn, getThemeClass } from \"./utils\";\n\nfunction createNoOpHandle(researchId: string): EmbedHandle {\n return {\n unmount: () => {},\n update: () => {},\n destroy: () => {},\n researchId,\n type: \"fullpage\" as const,\n iframe: null,\n container: null,\n };\n}\n\nexport function createFullpage(config: EmbedConfig): EmbedHandle {\n const { researchId } = config;\n\n // SSR safety: return no-op handle\n if (!hasDom()) {\n return createNoOpHandle(researchId);\n }\n const host = getHost(config.host);\n\n injectStyles();\n ensureGlobalListeners();\n\n // Create fullpage container\n const container = document.createElement(\"div\");\n container.className = cn(\n \"perspective-embed-root perspective-fullpage\",\n getThemeClass(config.theme)\n );\n\n // Create loading indicator with theme and brand colors\n const loading = createLoadingIndicator({\n theme: config.theme,\n brand: config.brand,\n });\n container.appendChild(loading);\n\n // Create iframe (hidden initially)\n const iframe = createIframe(\n researchId,\n \"fullpage\",\n host,\n config.params,\n config.brand,\n config.theme\n );\n iframe.style.opacity = \"0\";\n iframe.style.transition = \"opacity 0.3s ease\";\n\n container.appendChild(iframe);\n document.body.appendChild(container);\n\n // Mutable config reference for updates\n let currentConfig = { ...config };\n let messageCleanup: (() => void) | null = null;\n\n // Register iframe for theme change notifications\n const unregisterIframe = registerIframe(iframe, host);\n\n const unmount = () => {\n messageCleanup?.();\n unregisterIframe();\n container.remove();\n currentConfig.onClose?.();\n };\n\n // Set up message listener\n messageCleanup = setupMessageListener(\n researchId,\n {\n get onReady() {\n return () => {\n loading.style.opacity = \"0\";\n iframe.style.opacity = \"1\";\n setTimeout(() => loading.remove(), 300);\n currentConfig.onReady?.();\n };\n },\n get onSubmit() {\n return currentConfig.onSubmit;\n },\n get onNavigate() {\n return currentConfig.onNavigate;\n },\n get onClose() {\n return unmount;\n },\n get onError() {\n return currentConfig.onError;\n },\n },\n iframe,\n host,\n { skipResize: true }\n );\n\n return {\n unmount,\n update: (options) => {\n currentConfig = { ...currentConfig, ...options };\n },\n destroy: unmount,\n researchId,\n type: \"fullpage\" as const,\n iframe,\n container,\n };\n}\n"]}
@@ -0,0 +1,155 @@
1
+ import { ThemeValue, ErrorCode } from './constants.cjs';
2
+ export { BRAND_KEYS, BrandKey, CURRENT_FEATURES, DATA_ATTRS, FEATURES, MESSAGE_TYPES, MessageType, PARAM_KEYS, ParamKey, SDK_VERSION, THEME_VALUES } from './constants.cjs';
3
+
4
+ /**
5
+ * Type definitions for the Perspective Embed SDK
6
+ * This file is TYPE-ONLY - no runtime value imports or exports
7
+ * SSR-safe by design
8
+ */
9
+
10
+ type EmbedType = "widget" | "popup" | "slider" | "float" | "fullpage" | "chat";
11
+ /** Brand colors that can be passed via embed code */
12
+ interface BrandColors {
13
+ /** Primary accent color (buttons, links, focus states) */
14
+ primary?: string;
15
+ /** Secondary accent color */
16
+ secondary?: string;
17
+ /** Background color of the embed */
18
+ bg?: string;
19
+ /** Primary text color */
20
+ text?: string;
21
+ }
22
+ interface EmbedConfig {
23
+ researchId: string;
24
+ type?: EmbedType;
25
+ /** Custom button text for popup/slider triggers */
26
+ buttonText?: string;
27
+ /** Custom params to pass to the interview (for tracking/attribution) */
28
+ params?: Record<string, string>;
29
+ /** Brand colors to override Research settings */
30
+ brand?: {
31
+ light?: BrandColors;
32
+ dark?: BrandColors;
33
+ };
34
+ /** Force theme mode: 'dark', 'light', or 'system' (default) */
35
+ theme?: ThemeValue;
36
+ /** Override the default host (defaults to https://getperspective.ai) */
37
+ host?: string;
38
+ /** Callback when embed is ready */
39
+ onReady?: () => void;
40
+ /** Callback when interview is submitted/completed */
41
+ onSubmit?: (data: {
42
+ researchId: string;
43
+ }) => void;
44
+ /** Callback when embed wants to navigate. If provided, parent handles navigation; otherwise SDK navigates via window.location.href */
45
+ onNavigate?: (url: string) => void;
46
+ /** Callback when embed is closed */
47
+ onClose?: () => void;
48
+ /** Callback on any error */
49
+ onError?: (error: EmbedError) => void;
50
+ }
51
+ /** Embed error with code for programmatic handling */
52
+ interface EmbedError extends Error {
53
+ code?: ErrorCode;
54
+ }
55
+ interface EmbedInstance {
56
+ researchId: string;
57
+ type: EmbedType;
58
+ iframe: HTMLIFrameElement;
59
+ container: HTMLElement;
60
+ destroy: () => void;
61
+ }
62
+ /** Handle returned by embed creation functions */
63
+ interface EmbedHandle {
64
+ unmount: () => void;
65
+ update: (options: Partial<Pick<EmbedConfig, "onReady" | "onSubmit" | "onNavigate" | "onClose" | "onError">>) => void;
66
+ /** @deprecated Use unmount() instead */
67
+ destroy: () => void;
68
+ /** @deprecated For legacy compatibility */
69
+ readonly researchId: string;
70
+ /** @deprecated For legacy compatibility */
71
+ readonly type: EmbedType;
72
+ /** @deprecated For legacy compatibility - may be null on server */
73
+ readonly iframe: HTMLIFrameElement | null;
74
+ /** @deprecated For legacy compatibility - may be null on server */
75
+ readonly container: HTMLElement | null;
76
+ }
77
+ /** Handle for float bubble with open/close control (persistent UI element) */
78
+ interface FloatHandle extends Omit<EmbedHandle, "type"> {
79
+ open: () => void;
80
+ close: () => void;
81
+ toggle: () => void;
82
+ readonly isOpen: boolean;
83
+ readonly type: "float";
84
+ }
85
+ /** @deprecated Use FloatHandle for float bubble, EmbedHandle for popup/slider */
86
+ type ModalHandle = FloatHandle;
87
+ /** Theme configuration from API */
88
+ interface ThemeConfig {
89
+ primaryColor: string;
90
+ textColor: string;
91
+ darkPrimaryColor: string;
92
+ darkTextColor: string;
93
+ }
94
+ /** SDK global configuration */
95
+ interface SDKConfig {
96
+ /** Override the default host */
97
+ host?: string;
98
+ }
99
+
100
+ /**
101
+ * Inline widget embed - renders directly in a container element
102
+ * SSR-safe - returns no-op handle on server
103
+ */
104
+
105
+ declare function createWidget(container: HTMLElement | null, config: EmbedConfig): EmbedHandle;
106
+
107
+ /**
108
+ * Popup/modal embed - opens in a centered modal overlay
109
+ * SSR-safe - returns no-op handle on server
110
+ */
111
+
112
+ declare function openPopup(config: EmbedConfig): EmbedHandle;
113
+
114
+ /**
115
+ * Slider/drawer embed - slides in from the right
116
+ * SSR-safe - returns no-op handle on server
117
+ */
118
+
119
+ declare function openSlider(config: EmbedConfig): EmbedHandle;
120
+
121
+ /**
122
+ * Floating bubble embed - floating button that opens a chat window
123
+ * SSR-safe - returns no-op handle on server
124
+ */
125
+
126
+ type FloatConfig = EmbedConfig & {
127
+ _themeConfig?: ThemeConfig;
128
+ };
129
+ declare function createFloatBubble(config: FloatConfig): FloatHandle;
130
+ /** @deprecated Use createFloatBubble instead */
131
+ declare const createChatBubble: typeof createFloatBubble;
132
+
133
+ /**
134
+ * Fullpage embed - takes over entire viewport
135
+ * SSR-safe - returns no-op handle on server
136
+ */
137
+
138
+ declare function createFullpage(config: EmbedConfig): EmbedHandle;
139
+
140
+ /**
141
+ * Embed SDK configuration
142
+ * SSR-safe - DOM access is guarded and lazy
143
+ */
144
+
145
+ /**
146
+ * Configure the SDK globally
147
+ * Call this before creating any embeds if you need to override defaults
148
+ */
149
+ declare function configure(config: SDKConfig): void;
150
+ /**
151
+ * Get the current SDK configuration
152
+ */
153
+ declare function getConfig(): SDKConfig;
154
+
155
+ export { type BrandColors, type EmbedConfig, type EmbedError, type EmbedHandle, type EmbedInstance, type EmbedType, type FloatHandle, type ModalHandle, type SDKConfig, type ThemeConfig, ThemeValue, configure, createChatBubble, createFloatBubble, createFullpage, createWidget, getConfig, openPopup, openSlider };
@@ -0,0 +1,155 @@
1
+ import { ThemeValue, ErrorCode } from './constants.js';
2
+ export { BRAND_KEYS, BrandKey, CURRENT_FEATURES, DATA_ATTRS, FEATURES, MESSAGE_TYPES, MessageType, PARAM_KEYS, ParamKey, SDK_VERSION, THEME_VALUES } from './constants.js';
3
+
4
+ /**
5
+ * Type definitions for the Perspective Embed SDK
6
+ * This file is TYPE-ONLY - no runtime value imports or exports
7
+ * SSR-safe by design
8
+ */
9
+
10
+ type EmbedType = "widget" | "popup" | "slider" | "float" | "fullpage" | "chat";
11
+ /** Brand colors that can be passed via embed code */
12
+ interface BrandColors {
13
+ /** Primary accent color (buttons, links, focus states) */
14
+ primary?: string;
15
+ /** Secondary accent color */
16
+ secondary?: string;
17
+ /** Background color of the embed */
18
+ bg?: string;
19
+ /** Primary text color */
20
+ text?: string;
21
+ }
22
+ interface EmbedConfig {
23
+ researchId: string;
24
+ type?: EmbedType;
25
+ /** Custom button text for popup/slider triggers */
26
+ buttonText?: string;
27
+ /** Custom params to pass to the interview (for tracking/attribution) */
28
+ params?: Record<string, string>;
29
+ /** Brand colors to override Research settings */
30
+ brand?: {
31
+ light?: BrandColors;
32
+ dark?: BrandColors;
33
+ };
34
+ /** Force theme mode: 'dark', 'light', or 'system' (default) */
35
+ theme?: ThemeValue;
36
+ /** Override the default host (defaults to https://getperspective.ai) */
37
+ host?: string;
38
+ /** Callback when embed is ready */
39
+ onReady?: () => void;
40
+ /** Callback when interview is submitted/completed */
41
+ onSubmit?: (data: {
42
+ researchId: string;
43
+ }) => void;
44
+ /** Callback when embed wants to navigate. If provided, parent handles navigation; otherwise SDK navigates via window.location.href */
45
+ onNavigate?: (url: string) => void;
46
+ /** Callback when embed is closed */
47
+ onClose?: () => void;
48
+ /** Callback on any error */
49
+ onError?: (error: EmbedError) => void;
50
+ }
51
+ /** Embed error with code for programmatic handling */
52
+ interface EmbedError extends Error {
53
+ code?: ErrorCode;
54
+ }
55
+ interface EmbedInstance {
56
+ researchId: string;
57
+ type: EmbedType;
58
+ iframe: HTMLIFrameElement;
59
+ container: HTMLElement;
60
+ destroy: () => void;
61
+ }
62
+ /** Handle returned by embed creation functions */
63
+ interface EmbedHandle {
64
+ unmount: () => void;
65
+ update: (options: Partial<Pick<EmbedConfig, "onReady" | "onSubmit" | "onNavigate" | "onClose" | "onError">>) => void;
66
+ /** @deprecated Use unmount() instead */
67
+ destroy: () => void;
68
+ /** @deprecated For legacy compatibility */
69
+ readonly researchId: string;
70
+ /** @deprecated For legacy compatibility */
71
+ readonly type: EmbedType;
72
+ /** @deprecated For legacy compatibility - may be null on server */
73
+ readonly iframe: HTMLIFrameElement | null;
74
+ /** @deprecated For legacy compatibility - may be null on server */
75
+ readonly container: HTMLElement | null;
76
+ }
77
+ /** Handle for float bubble with open/close control (persistent UI element) */
78
+ interface FloatHandle extends Omit<EmbedHandle, "type"> {
79
+ open: () => void;
80
+ close: () => void;
81
+ toggle: () => void;
82
+ readonly isOpen: boolean;
83
+ readonly type: "float";
84
+ }
85
+ /** @deprecated Use FloatHandle for float bubble, EmbedHandle for popup/slider */
86
+ type ModalHandle = FloatHandle;
87
+ /** Theme configuration from API */
88
+ interface ThemeConfig {
89
+ primaryColor: string;
90
+ textColor: string;
91
+ darkPrimaryColor: string;
92
+ darkTextColor: string;
93
+ }
94
+ /** SDK global configuration */
95
+ interface SDKConfig {
96
+ /** Override the default host */
97
+ host?: string;
98
+ }
99
+
100
+ /**
101
+ * Inline widget embed - renders directly in a container element
102
+ * SSR-safe - returns no-op handle on server
103
+ */
104
+
105
+ declare function createWidget(container: HTMLElement | null, config: EmbedConfig): EmbedHandle;
106
+
107
+ /**
108
+ * Popup/modal embed - opens in a centered modal overlay
109
+ * SSR-safe - returns no-op handle on server
110
+ */
111
+
112
+ declare function openPopup(config: EmbedConfig): EmbedHandle;
113
+
114
+ /**
115
+ * Slider/drawer embed - slides in from the right
116
+ * SSR-safe - returns no-op handle on server
117
+ */
118
+
119
+ declare function openSlider(config: EmbedConfig): EmbedHandle;
120
+
121
+ /**
122
+ * Floating bubble embed - floating button that opens a chat window
123
+ * SSR-safe - returns no-op handle on server
124
+ */
125
+
126
+ type FloatConfig = EmbedConfig & {
127
+ _themeConfig?: ThemeConfig;
128
+ };
129
+ declare function createFloatBubble(config: FloatConfig): FloatHandle;
130
+ /** @deprecated Use createFloatBubble instead */
131
+ declare const createChatBubble: typeof createFloatBubble;
132
+
133
+ /**
134
+ * Fullpage embed - takes over entire viewport
135
+ * SSR-safe - returns no-op handle on server
136
+ */
137
+
138
+ declare function createFullpage(config: EmbedConfig): EmbedHandle;
139
+
140
+ /**
141
+ * Embed SDK configuration
142
+ * SSR-safe - DOM access is guarded and lazy
143
+ */
144
+
145
+ /**
146
+ * Configure the SDK globally
147
+ * Call this before creating any embeds if you need to override defaults
148
+ */
149
+ declare function configure(config: SDKConfig): void;
150
+ /**
151
+ * Get the current SDK configuration
152
+ */
153
+ declare function getConfig(): SDKConfig;
154
+
155
+ export { type BrandColors, type EmbedConfig, type EmbedError, type EmbedHandle, type EmbedInstance, type EmbedType, type FloatHandle, type ModalHandle, type SDKConfig, type ThemeConfig, ThemeValue, configure, createChatBubble, createFloatBubble, createFullpage, createWidget, getConfig, openPopup, openSlider };