cobrowse-agent-ui 1.4.2 → 1.6.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"cobrowse-agent-ui.js","sources":["../lib/components/CodeEntry/index.tsx","../lib/icons/external-link.svg?react","../lib/components/ExternalLink/index.tsx","../lib/components/UserIcon/index.tsx","../lib/main.ts"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n type ForwardedRef,\n type ReactNode,\n type ClipboardEvent,\n type ChangeEvent,\n type KeyboardEvent\n} from 'react'\nimport { useTranslation } from 'react-i18next'\nimport clsx from 'clsx'\nimport styles from './CodeEntry.module.css'\n\nexport interface CodeEntryHandle {\n clear: () => void\n focus: (index: number) => void\n}\n\nexport interface CodeEntryProps {\n ref?: ForwardedRef<CodeEntryHandle>\n className?: string\n inputClassName?: string\n focusOnRender?: boolean\n onCode?: (code: string) => Promise<boolean> | boolean\n label?: ReactNode | false\n children?: ReactNode\n}\n\nconst CODE_LENGTH = 6\nconst EMTPY_STATE = Array<string>(CODE_LENGTH).fill('')\nconst KEY_BACKSPACE = 'Backspace'\nconst KEY_ARROW_LEFT = 'ArrowLeft'\nconst KEY_ARROW_RIGHT = 'ArrowRight'\n\nconst getElementIndex = (refsArr: Array<HTMLInputElement | null>, elem: HTMLInputElement) =>\n refsArr.findIndex((el) => el === elem)\n\nconst focusPreviousInput = (refsArr: Array<HTMLInputElement | null>, elem: HTMLInputElement) => {\n refsArr[Math.max(getElementIndex(refsArr, elem) - 1, 0)]?.focus()\n}\n\nconst focusNextInput = (refsArr: Array<HTMLInputElement | null>, elem: HTMLInputElement) => {\n refsArr[Math.min(getElementIndex(refsArr, elem) + 1, CODE_LENGTH - 1)]?.focus()\n}\n\nconst moveFocusForArrowKey = (\n refsArr: Array<HTMLInputElement | null>,\n elem: HTMLInputElement,\n key: typeof KEY_ARROW_LEFT | typeof KEY_ARROW_RIGHT\n) => {\n const isRTL = getComputedStyle(elem).direction === 'rtl'\n const movesToPrevious = key === KEY_ARROW_LEFT ? !isRTL : isRTL\n\n if (movesToPrevious) {\n focusPreviousInput(refsArr, elem)\n } else {\n focusNextInput(refsArr, elem)\n }\n}\n\nconst CodeEntry = ({ ref, className, inputClassName, focusOnRender = false, onCode, label, children }: CodeEntryProps) => {\n const { t } = useTranslation()\n const [validating, setValidating] = useState(false)\n const [code, setCode] = useState(EMTPY_STATE)\n const refs = useRef<Array<HTMLInputElement | null>>([])\n\n useImperativeHandle(ref, () => ({\n clear () {\n setCode(EMTPY_STATE)\n },\n focus (index) {\n refs.current[index]?.focus()\n }\n }), [])\n\n const getCode = useCallback(() => code.join('').substring(0, CODE_LENGTH), [code])\n\n const focusFirstEmptyInput = useCallback(() => {\n const firstEmptyIndex = code.findIndex((digit) => digit === '')\n const targetIndex = firstEmptyIndex === -1 ? CODE_LENGTH - 1 : firstEmptyIndex\n\n refs.current[targetIndex]?.focus()\n }, [code])\n\n const tryComplete = useCallback(async (codeValue: string) => {\n setValidating(true)\n\n try {\n const isValid = await onCode?.(codeValue)\n\n if (isValid) {\n setCode(EMTPY_STATE)\n\n if (refs.current[0]) {\n setTimeout(() => refs.current[0]?.focus(), 0)\n }\n } else {\n setTimeout(() => refs.current[CODE_LENGTH - 1]?.focus(), 0)\n }\n } catch (e) {\n if (refs.current[CODE_LENGTH - 1]) {\n setTimeout(() => refs.current[CODE_LENGTH - 1]?.focus(), 0)\n }\n\n throw e\n } finally {\n setValidating(false)\n }\n }, [onCode])\n\n // Run the tryComplete function when the code state changes\n useEffect(() => {\n const code = getCode()\n\n if (code.length !== CODE_LENGTH) {\n return\n }\n\n void tryComplete(code)\n }, [getCode, tryComplete])\n\n const setDigit = useCallback((digit: number, value: string) => {\n if (digit > (CODE_LENGTH - 1)) {\n return\n }\n\n setCode((code) => {\n const updatedCode = [...code]\n\n updatedCode[digit] = value\n\n return updatedCode\n })\n }, [])\n\n const handlePaste = useCallback((event: ClipboardEvent<HTMLInputElement>) => {\n if (validating) {\n return\n }\n\n const { clipboardData } = event\n const pastedData = clipboardData.getData('Text').trim()\n\n // Exit early if the pasted data contains anything other than just digits\n if (!/^[0-9]+$/.test(pastedData)) {\n event.preventDefault()\n\n return\n }\n\n const digits = pastedData.split('')\n // Start pasting from the first digit if the clipboard holds a full code,\n // otherwise just paste from the currently selected input onwards\n let digit = pastedData.length === CODE_LENGTH\n ? 0\n : parseInt(event.currentTarget.getAttribute('data-digit') ?? '0', 10)\n\n digits.forEach((value) => {\n setDigit(digit, value)\n\n digit += 1\n })\n\n refs.current[Math.min(digit, CODE_LENGTH - 1)]?.focus()\n\n event.preventDefault()\n }, [setDigit, validating])\n\n const handleOnChange = useCallback((event: ChangeEvent<HTMLInputElement>) => {\n const { target, target: { value } } = event\n const digit = parseInt(target.getAttribute('data-digit') ?? '0', 10)\n const digits = value.match(/[0-9]/g) ?? []\n\n if (digits.length === 0) {\n setDigit(digit, '')\n\n return\n }\n\n if (digits.length === 1) {\n setDigit(digit, digits[0])\n focusNextInput(refs.current, target)\n }\n }, [setDigit])\n\n const handleKeyDown = useCallback((event: KeyboardEvent<HTMLInputElement>) => {\n const { key, currentTarget, metaKey, ctrlKey } = event\n\n // On backspace on empty node go back to previous\n if (currentTarget.value.length === 0 && key === KEY_BACKSPACE) {\n focusPreviousInput(refs.current, currentTarget)\n } else if (key === KEY_ARROW_LEFT || key === KEY_ARROW_RIGHT) {\n // Move focus according to visual direction\n moveFocusForArrowKey(refs.current, currentTarget, key)\n event.preventDefault()\n } else if (!metaKey && !ctrlKey && key.length === 1 && !/^[0-9]$/.test(key)) {\n // Prevent non-numeric characters that might appear in numbers (e.g 'e')\n // but allow backspaces too\n event.preventDefault()\n }\n }, [])\n\n const handleKeyUp = useCallback((event: KeyboardEvent<HTMLInputElement>) => {\n const { currentTarget, repeat } = event\n const { value } = currentTarget\n\n if (!repeat && /[0-9]/.test(value)) {\n focusNextInput(refs.current, currentTarget)\n }\n }, [])\n\n const invalid = !validating && getCode().length === CODE_LENGTH\n\n return (\n <fieldset\n className={clsx(styles.root, className)}\n >\n {label !== false && (\n <legend\n className={styles.legend}\n onClick={focusFirstEmptyInput}\n >\n <span>{label ?? t('Support code')}</span>\n </legend>\n )}\n <div className={clsx(styles.digits, invalid && styles.invalid)} role='group'>\n {code.map((value, index) => (\n <input\n key={index}\n inputMode='numeric'\n className={clsx(styles.input, inputClassName)}\n disabled={validating}\n onKeyDown={handleKeyDown}\n onKeyUp={handleKeyUp}\n onChange={handleOnChange}\n onPaste={handlePaste}\n value={value}\n data-digit={index}\n ref={(el) => { refs.current[index] = el }}\n autoFocus={focusOnRender && index === 0}\n aria-label={t('Digit {{digit}}', { digit: index + 1 })}\n />\n ))}\n {children}\n </div>\n </fieldset>\n )\n}\n\nexport default CodeEntry\n","import * as React from \"react\";\nconst SvgExternalLink = (props) => /* @__PURE__ */ React.createElement(\"svg\", { xmlns: \"http://www.w3.org/2000/svg\", viewBox: \"0 0 24 24\", fill: \"none\", stroke: \"currentColor\", strokeWidth: 2, strokeLinecap: \"round\", strokeLinejoin: \"round\", width: 14, height: 14, \"aria-hidden\": \"true\", ...props }, /* @__PURE__ */ React.createElement(\"path\", { d: \"M15 3h6v6\" }), /* @__PURE__ */ React.createElement(\"path\", { d: \"M10 14 21 3\" }), /* @__PURE__ */ React.createElement(\"path\", { d: \"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" }));\nexport default SvgExternalLink;\n","import type { ReactNode } from 'react'\nimport IconExternalLink from '@/icons/external-link.svg?react'\nimport styles from './ExternalLink.module.css'\n\nexport interface ExternalLinkProps {\n href: string\n children?: ReactNode\n}\n\nconst ExternalLink = ({ href, children }: ExternalLinkProps) => (\n <a className={styles.root} href={href} target=\"_blank\" rel=\"noopener noreferrer\">\n {children}\n <IconExternalLink />\n </a>\n)\n\nexport default ExternalLink\n","import clsx from 'clsx'\nimport styles from './UserIcon.module.css'\n\nexport interface UserIconUser {\n name?: string\n picture?: string\n colour?: string\n}\n\nexport interface UserIconProps {\n user?: UserIconUser\n className?: string\n}\n\nconst UserIcon = ({ user, className }: UserIconProps) => {\n const initials = (): string => {\n if (!user?.name || user.picture) return ''\n\n return user.name\n .trim()\n .split(/\\s+/)\n .map(part => part.toUpperCase().charAt(0))\n .join('')\n .slice(0, 2)\n }\n\n if (!user) return null\n\n return (\n <div\n className={clsx(styles.root, className)}\n title={user.name}\n style={{\n backgroundImage: user.picture ? `url(${user.picture || ''})` : undefined,\n backgroundColor: user.colour\n }}\n >\n <span>{initials()}</span>\n </div>\n )\n}\n\nexport default UserIcon\n","import CodeEntryComponent from '@/components/CodeEntry'\nimport ExternalLinkComponent from '@/components/ExternalLink'\nimport PlatformIconComponent from '@/components/PlatformIcon'\nimport DeviceComponent from '@/components/Device'\nimport SessionComponent from '@/components/Session'\nimport SmartConnectButtonComponent from '@/components/SmartConnectButton'\nimport UserIconComponent from '@/components/UserIcon'\nimport RefreshButtonComponent from '@/components/RefreshButton'\nimport LoaderComponent from '@/components/Loader'\nimport i18nInstance from '@/i18n'\n\nexport type { CodeEntryProps } from '@/components/CodeEntry'\nexport type { ExternalLinkProps } from '@/components/ExternalLink'\nexport type { DeviceData, DeviceProps } from '@/components/Device'\nexport type { SessionData, SessionProps } from '@/components/Session'\nexport type { SmartConnectButtonProps } from '@/components/SmartConnectButton'\nexport type { RefreshButtonProps } from '@/components/RefreshButton'\nexport type { LoaderProps } from '@/components/Loader'\n\nexport const CodeEntry = CodeEntryComponent\nexport const ExternalLink = ExternalLinkComponent\nexport const PlatformIcon = PlatformIconComponent\nexport const Device = DeviceComponent\nexport const Session = SessionComponent\nexport const SmartConnectButton = SmartConnectButtonComponent\nexport const UserIcon = UserIconComponent\nexport const RefreshButton = RefreshButtonComponent\nexport const Loader = LoaderComponent\nexport const i18n = i18nInstance\n"],"names":["CODE_LENGTH","EMTPY_STATE","KEY_BACKSPACE","KEY_ARROW_LEFT","KEY_ARROW_RIGHT","getElementIndex","refsArr","elem","el","focusPreviousInput","_a","focusNextInput","moveFocusForArrowKey","key","isRTL","CodeEntry","ref","className","inputClassName","focusOnRender","onCode","label","children","t","useTranslation","validating","setValidating","useState","code","setCode","refs","useRef","useImperativeHandle","index","getCode","useCallback","focusFirstEmptyInput","firstEmptyIndex","digit","targetIndex","tryComplete","codeValue","__async","useEffect","setDigit","value","updatedCode","handlePaste","event","clipboardData","pastedData","digits","_b","handleOnChange","target","handleKeyDown","currentTarget","metaKey","ctrlKey","handleKeyUp","repeat","invalid","jsxs","clsx","styles","jsx","SvgExternalLink","props","React","__spreadValues","ExternalLink","href","IconExternalLink","UserIcon","user","initials","part","CodeEntryComponent","ExternalLinkComponent","PlatformIcon","PlatformIconComponent","Device","DeviceComponent","Session","SessionComponent","SmartConnectButton","SmartConnectButtonComponent","UserIconComponent","RefreshButton","RefreshButtonComponent","Loader","LoaderComponent","i18n","i18nInstance"],"mappings":"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"}
1
+ {"version":3,"file":"cobrowse-agent-ui.js","sources":["../lib/i18n/bind.ts","../lib/icons/external-link.svg?react","../lib/components/ExternalLink/index.tsx","../lib/components/UserIcon/index.tsx","../lib/icons/phone.svg?react","../lib/components/CancelButton/index.tsx","../lib/components/BlockingError/index.tsx","../lib/components/CobrowseProvider/index.tsx","../lib/components/Frame/RemoteContext.ts","../lib/hooks/useStableCallback.ts","../lib/components/Frame/index.tsx","../lib/hooks/useSession.ts","../lib/components/SessionEmbed/Overlay.tsx","../lib/components/SessionEmbed/useSessionUrl.ts","../lib/components/SessionEmbed/index.tsx","../lib/components/ConnectDevice/useConnectDevice.ts","../lib/components/ConnectDevice/index.tsx","../lib/main.ts"],"sourcesContent":["import type { i18n as I18nInstance } from 'i18next'\nimport i18n from './instance'\n\ntype BindableI18n = Pick<I18nInstance, 'language' | 'resolvedLanguage' | 'on' | 'off'>\n\nconst getLanguage = ({ resolvedLanguage, language }: BindableI18n) => resolvedLanguage ?? language\n\n// Allows a consumer app to do `bindI18n(i18nInstance)` so that the\n// agent UI instance stays in sync when language changes.\nexport const bindI18n = (consumerI18n: BindableI18n) => {\n const syncLanguage = (language?: string) => {\n if (!language || getLanguage(i18n) === language) {\n return\n }\n\n void i18n.changeLanguage(language)\n }\n\n const handleLanguageChanged = (language: string) => {\n syncLanguage(language)\n }\n\n syncLanguage(getLanguage(consumerI18n))\n\n consumerI18n.on('languageChanged', handleLanguageChanged)\n\n return () => {\n consumerI18n.off('languageChanged', handleLanguageChanged)\n }\n}\n","import * as React from \"react\";\nconst SvgExternalLink = (props) => /* @__PURE__ */ React.createElement(\"svg\", { xmlns: \"http://www.w3.org/2000/svg\", viewBox: \"0 0 24 24\", fill: \"none\", stroke: \"currentColor\", strokeWidth: 2, strokeLinecap: \"round\", strokeLinejoin: \"round\", width: 14, height: 14, \"aria-hidden\": \"true\", ...props }, /* @__PURE__ */ React.createElement(\"path\", { d: \"M15 3h6v6\" }), /* @__PURE__ */ React.createElement(\"path\", { d: \"M10 14 21 3\" }), /* @__PURE__ */ React.createElement(\"path\", { d: \"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6\" }));\nexport default SvgExternalLink;\n","import type { ReactNode } from 'react'\nimport IconExternalLink from '@/icons/external-link.svg?react'\nimport styles from './ExternalLink.module.css'\n\nexport interface ExternalLinkProps {\n href: string\n children?: ReactNode\n}\n\nconst ExternalLink = ({ href, children }: ExternalLinkProps) => (\n <a className={styles.root} href={href} target=\"_blank\" rel=\"noopener noreferrer\">\n {children}\n <IconExternalLink />\n </a>\n)\n\nexport default ExternalLink\n","import clsx from 'clsx'\nimport styles from './UserIcon.module.css'\n\nexport interface UserIconUser {\n name?: string\n picture?: string\n colour?: string\n}\n\nexport interface UserIconProps {\n user?: UserIconUser\n className?: string\n}\n\nconst UserIcon = ({ user, className }: UserIconProps) => {\n const initials = (): string => {\n if (!user?.name || user.picture) return ''\n\n return user.name\n .trim()\n .split(/\\s+/)\n .map(part => part.toUpperCase().charAt(0))\n .join('')\n .slice(0, 2)\n }\n\n if (!user) return null\n\n return (\n <div\n className={clsx(styles.root, className)}\n title={user.name}\n style={{\n backgroundImage: user.picture ? `url(${user.picture || ''})` : undefined,\n backgroundColor: user.colour\n }}\n >\n <span>{initials()}</span>\n </div>\n )\n}\n\nexport default UserIcon\n","import * as React from \"react\";\nconst SvgPhone = (props) => /* @__PURE__ */ React.createElement(\"svg\", { width: 24, height: 24, viewBox: \"0 0 24 24\", fill: \"none\", xmlns: \"http://www.w3.org/2000/svg\", ...props }, /* @__PURE__ */ React.createElement(\"g\", { clipPath: \"url(#clip0_60797_8824)\" }, /* @__PURE__ */ React.createElement(\"path\", { fillRule: \"evenodd\", clipRule: \"evenodd\", d: \"M20.9964 12.5895C21.1528 12.4331 21.2406 12.2211 21.2406 12C21.2406 11.7872 21.1593 11.5829 21.0138 11.4285C18.518 9.23023 15.3059 8.01707 11.9793 8.01707C8.65261 8.01707 5.44055 9.23023 2.94474 11.4285C2.7993 11.5829 2.71797 11.7872 2.71797 12C2.71797 12.2211 2.8058 12.4331 2.96214 12.5895L5.07653 14.7039L8.20945 13.3612L7.76772 11.5943C7.6415 11.0894 7.92363 10.5721 8.41645 10.4048C10.7269 9.62055 13.2316 9.62055 15.5421 10.4048C16.0349 10.5721 16.3171 11.0894 16.1908 11.5943L15.7491 13.3612L18.882 14.7039L20.9964 12.5895ZM23.2406 12C23.2406 12.7515 22.942 13.4723 22.4106 14.0037L19.8175 16.5968C19.5284 16.8859 19.0923 16.9699 18.7165 16.8088L14.1785 14.864C13.7274 14.6707 13.4832 14.1785 13.6023 13.7023L14.0159 12.0478C12.6758 11.7395 11.2828 11.7395 9.94266 12.0478L10.3563 13.7023C10.4753 14.1785 10.2312 14.6707 9.78006 14.864L5.24208 16.8088C4.86624 16.9699 4.43019 16.8859 4.14106 16.5968L1.54792 14.0037C1.01651 13.4723 0.717975 12.7515 0.717976 12C0.717975 11.2485 1.01651 10.5277 1.54792 9.99633C1.56223 9.98202 1.57697 9.96815 1.59212 9.95474C4.45744 7.41772 8.1522 6.01707 11.9793 6.01707C15.8064 6.01707 19.5011 7.41772 22.3664 9.95474C22.3816 9.96815 22.3963 9.98202 22.4106 9.99633C22.942 10.5277 23.2406 11.2485 23.2406 12Z\", fill: \"currentColor\" })), /* @__PURE__ */ React.createElement(\"defs\", null, /* @__PURE__ */ React.createElement(\"clipPath\", { id: \"clip0_60797_8824\" }, /* @__PURE__ */ React.createElement(\"rect\", { width: 24, height: 24, fill: \"white\" }))));\nexport default SvgPhone;\n","import type { ComponentPropsWithoutRef } from 'react'\nimport clsx from 'clsx'\nimport Button from '@/components/Button'\nimport PhoneIcon from '@/icons/phone.svg?react'\nimport { useTranslation } from '@/i18n'\nimport styles from './CancelButton.module.css'\n\nexport interface CancelButtonProps extends ComponentPropsWithoutRef<'button'> {}\n\nconst CancelButton = ({ type = 'button', className, children, ...props }: CancelButtonProps) => {\n const { t } = useTranslation()\n\n return (\n <Button\n type={type}\n aria-label={t('Cancel')}\n className={clsx(styles.root, className)}\n {...props}\n >\n {children ?? <PhoneIcon />}\n </Button>\n )\n}\n\nexport default CancelButton\n","import type { ReactNode } from 'react'\nimport { useTranslation } from '@/i18n'\nimport styles from './BlockingError.module.css'\n\nexport interface BlockingErrorProps {\n heading?: string\n message?: string\n children?: ReactNode\n}\n\nconst BlockingError = ({ heading, message, children }: BlockingErrorProps) => {\n const { t } = useTranslation()\n\n return (\n <div className={styles.root}>\n <p className={styles.heading}>{heading ?? t('Sorry, something went wrong.')}</p>\n {message && <p className={styles.message}>{message}</p>}\n {children}\n </div>\n )\n}\n\nexport default BlockingError\n","import { createContext, use, type ReactNode } from 'react'\nimport type CobrowseAPI from 'cobrowse-agent-sdk'\n\nconst CobrowseContext = createContext<CobrowseAPI | null>(null)\n\nexport interface CobrowseProviderProps {\n cobrowse: CobrowseAPI\n children?: ReactNode\n}\n\nexport const CobrowseProvider = ({ cobrowse, children }: CobrowseProviderProps) => (\n <CobrowseContext.Provider value={cobrowse}>{children}</CobrowseContext.Provider>\n)\n\nexport const useCobrowseValue = () => use(CobrowseContext)\n\nexport const useCobrowse = () => {\n const cobrowse = useCobrowseValue()\n\n if (!cobrowse) {\n throw new Error('CobrowseProvider is required to use this component.')\n }\n\n return cobrowse\n}\n\nexport default CobrowseProvider\n","import { createContext, use, useEffect, useState } from 'react'\nimport type { RemoteContext as CobrowseRemoteContext } from 'cobrowse-agent-sdk'\nimport { useCobrowseValue } from '@/components/CobrowseProvider'\n\nconst RemoteContext = createContext<CobrowseRemoteContext | null>(null)\n\nexport function useRemoteContext(target?: HTMLIFrameElement | null): CobrowseRemoteContext | null {\n const providedRemoteContext = use(RemoteContext)\n const cobrowse = useCobrowseValue()\n const [remoteContext, setRemoteContext] = useState<CobrowseRemoteContext | null>(null)\n\n useEffect(() => {\n if (target === undefined) {\n return\n }\n\n if (!target || !cobrowse) {\n return\n }\n\n let cancelled = false\n let attachedContext: CobrowseRemoteContext | null = null\n\n const attachContext = async () => {\n attachedContext = await cobrowse.attachContext(target)\n\n if (cancelled) {\n attachedContext.destroy()\n attachedContext = null\n\n return\n }\n\n setRemoteContext(attachedContext)\n }\n\n void attachContext()\n\n return () => {\n cancelled = true\n setRemoteContext(null)\n\n if (attachedContext) {\n attachedContext.destroy()\n attachedContext = null\n }\n }\n }, [cobrowse, target])\n\n if (target === undefined) {\n return providedRemoteContext\n }\n\n if (!target || !cobrowse) {\n return null\n }\n\n return remoteContext\n}\n\nexport default RemoteContext\n","import { useCallback, useEffect, useRef } from 'react'\n\nconst useStableCallback = <TArgs extends unknown[], TResult>(callback?: (...args: TArgs) => TResult) => {\n const callbackRef = useRef(callback)\n\n useEffect(() => {\n callbackRef.current = callback\n }, [callback])\n\n return useCallback((...args: TArgs): TResult | undefined => (\n callbackRef.current?.(...args)\n ), [])\n}\n\nexport default useStableCallback\n","import { useCallback, useEffect, useState, type ComponentPropsWithoutRef, type ReactNode } from 'react'\nimport RemoteContextProvider, { useRemoteContext } from './RemoteContext'\nimport useStableCallback from '@/hooks/useStableCallback'\n\ntype IframeProps = Omit<ComponentPropsWithoutRef<'iframe'>, 'frameBorder' | 'onError' | 'src'>\n\nexport interface FrameProps extends IframeProps {\n src: string\n children?: ReactNode\n onError?: (error: unknown) => void\n}\n\nconst Frame = ({\n src,\n onError,\n title = 'Frame',\n width = '100%',\n height = '100%',\n style,\n children,\n ...props\n}: FrameProps) => {\n const [iframe, setIframe] = useState<HTMLIFrameElement | null>(null)\n const onErrorCallback = useStableCallback(onError)\n const remoteContext = useRemoteContext(iframe)\n\n const handleIframeRef = useCallback((element: HTMLIFrameElement | null) => {\n setIframe(element)\n }, [])\n\n useEffect(() => {\n if (!remoteContext) {\n return\n }\n\n const handleError = (error: unknown) => {\n onErrorCallback(error)\n }\n\n remoteContext.on('error', handleError)\n\n return () => {\n remoteContext.off('error', handleError)\n }\n }, [remoteContext, onErrorCallback])\n\n return (\n <RemoteContextProvider.Provider value={remoteContext}>\n <iframe\n ref={handleIframeRef}\n title={title}\n width={width}\n height={height}\n src={src}\n style={{ border: 0, ...style }}\n {...props}\n />\n {children}\n </RemoteContextProvider.Provider>\n )\n}\n\nexport { useRemoteContext }\nexport default Frame\n","import { useEffect, useState } from 'react'\nimport { RemoteContext, type Session } from 'cobrowse-agent-sdk'\n\nconst isRemoteContext = (source: RemoteContext | Session): source is RemoteContext => (\n source instanceof RemoteContext\n)\n\nconst hasSessionProperty = (target: Session, property: PropertyKey): property is keyof Session => property in target\n\nconst createReactiveSession = (session: Session | null) => {\n if (!session) {\n return null\n }\n\n return new Proxy(session, {\n get: (target, property) => hasSessionProperty(target, property) ? target[property] : undefined\n })\n}\n\nconst useSession = (source: RemoteContext | Session | null) => {\n const remoteContext = source && isRemoteContext(source) ? source : null\n const sessionSource = source && !isRemoteContext(source) ? source : null\n const [sessionState, setSessionState] = useState(sessionSource)\n\n useEffect(() => {\n if (!remoteContext) {\n return\n }\n\n const handleSessionChange = (session: Session) => {\n setSessionState(createReactiveSession(session))\n }\n\n remoteContext.on('session.loaded', handleSessionChange)\n remoteContext.on('session.updated', handleSessionChange)\n\n return () => {\n remoteContext.off('session.loaded', handleSessionChange)\n remoteContext.off('session.updated', handleSessionChange)\n\n setSessionState(null)\n }\n }, [remoteContext])\n\n useEffect(() => {\n if (!sessionSource) {\n return\n }\n\n const handleSessionChange = () => {\n setSessionState(createReactiveSession(sessionSource))\n }\n\n sessionSource.on('updated', handleSessionChange)\n sessionSource.on('ended', handleSessionChange)\n\n return () => {\n sessionSource.off('updated', handleSessionChange)\n sessionSource.off('ended', handleSessionChange)\n\n setSessionState(null)\n }\n }, [sessionSource])\n\n return sessionState ?? sessionSource\n}\n\nexport default useSession\n","import { useRemoteContext } from '@/components/Frame'\nimport useSession from '@/hooks/useSession'\nimport styles from './Overlay.module.css'\nimport type { SessionEmbedOverlayProps } from './types'\n\nconst Overlay = ({ state, children }: SessionEmbedOverlayProps) => {\n const remoteContext = useRemoteContext()\n const session = useSession(remoteContext)\n const sessionState = session?.state\n\n const shouldRender = state === 'loading'\n ? sessionState === undefined\n : sessionState === state\n\n if (!shouldRender) {\n return null\n }\n\n return (\n <div className={styles.root}>\n <div className={styles.content}>\n {children}\n </div>\n </div>\n )\n}\n\nexport default Overlay\n","import { useMemo } from 'react'\nimport { useCobrowse } from '@/components/CobrowseProvider'\nimport type { SessionEmbedProps } from './types'\nimport { useTranslation } from '@/i18n'\n\ninterface UseSessionUrlProps {\n id: string\n endAction?: SessionEmbedProps['endAction']\n popout?: SessionEmbedProps['popout']\n agentTools?: SessionEmbedProps['agentTools']\n deviceControls?: SessionEmbedProps['deviceControls']\n sessionDetails?: SessionEmbedProps['sessionDetails']\n messages?: SessionEmbedProps['messages']\n}\n\nexport const useSessionUrl = ({\n id,\n endAction,\n popout,\n agentTools,\n deviceControls,\n sessionDetails,\n messages\n}: UseSessionUrlProps) => {\n const cobrowse = useCobrowse()\n const { i18n: { language } } = useTranslation()\n\n return useMemo(() => {\n const paramEntries = Object.entries({\n end_action: endAction,\n popout,\n agent_tools: agentTools,\n device_controls: deviceControls,\n session_details: sessionDetails,\n messages,\n token_source: 'postMessage',\n lng: language\n }).flatMap(([name, value]) => value === undefined ? [] : [[name, value]])\n\n const query = new URLSearchParams(paramEntries)\n\n return `${cobrowse.api}/session/${encodeURIComponent(id)}?${query.toString()}`\n }, [\n cobrowse.api,\n id,\n endAction,\n popout,\n agentTools,\n deviceControls,\n sessionDetails,\n messages,\n language\n ])\n}\n","import { useEffect, useRef } from 'react'\nimport type { Session } from 'cobrowse-agent-sdk'\nimport Frame, { useRemoteContext } from '@/components/Frame'\nimport useStableCallback from '@/hooks/useStableCallback'\nimport Overlay from './Overlay'\nimport type { SessionEmbedProps } from './types'\nimport { useSessionUrl } from './useSessionUrl'\nimport styles from './SessionEmbed.module.css'\n\nexport type { SessionEmbedOverlay, SessionEmbedOverlayProps, SessionEmbedOverlayState, SessionEmbedProps } from './types'\n\ntype SessionEmbedComponent = typeof SessionEmbedBase & {\n Overlay: typeof Overlay\n}\n\nconst SessionEventObserver = ({ onLoaded, onUpdated, onActivated, onEnded }: Pick<SessionEmbedProps, 'onLoaded' | 'onUpdated' | 'onActivated' | 'onEnded'>) => {\n const remoteContext = useRemoteContext()\n const onLoadedCallback = useStableCallback(onLoaded)\n const onUpdatedCallback = useStableCallback(onUpdated)\n const onActivatedCallback = useStableCallback(onActivated)\n const onEndedCallback = useStableCallback(onEnded)\n const sessionActivatedRef = useRef(false)\n const sessionEndedRef = useRef(false)\n\n useEffect(() => {\n if (!remoteContext) {\n sessionActivatedRef.current = false\n sessionEndedRef.current = false\n\n return\n }\n\n const handleSessionLoaded = (session: Session) => {\n sessionActivatedRef.current = session.isActive()\n sessionEndedRef.current = false\n onLoadedCallback(session)\n }\n\n const handleSessionUpdated = (session: Session) => {\n onUpdatedCallback(session)\n\n if (session.isActive() && !sessionActivatedRef.current) {\n sessionActivatedRef.current = true\n onActivatedCallback(session)\n }\n\n if (session.isEnded() && !sessionEndedRef.current) {\n sessionEndedRef.current = true\n onEndedCallback(session)\n }\n }\n\n remoteContext.on('session.loaded', handleSessionLoaded)\n remoteContext.on('session.updated', handleSessionUpdated)\n\n return () => {\n remoteContext.off('session.loaded', handleSessionLoaded)\n remoteContext.off('session.updated', handleSessionUpdated)\n sessionActivatedRef.current = false\n sessionEndedRef.current = false\n }\n }, [onActivatedCallback, onEndedCallback, onLoadedCallback, onUpdatedCallback, remoteContext])\n\n return null\n}\n\nconst SessionEmbedBase = ({\n id,\n endAction,\n popout,\n agentTools,\n deviceControls,\n sessionDetails,\n messages,\n onError,\n onLoaded,\n onUpdated,\n onActivated,\n onEnded,\n className,\n children,\n ...props\n}: SessionEmbedProps) => {\n const url = useSessionUrl({\n id,\n endAction,\n popout,\n agentTools,\n deviceControls,\n sessionDetails,\n messages\n })\n\n return (\n <div className={styles.root}>\n <Frame\n src={url}\n className={className}\n onError={onError}\n {...props}\n >\n <SessionEventObserver\n onLoaded={onLoaded}\n onUpdated={onUpdated}\n onActivated={onActivated}\n onEnded={onEnded}\n />\n {children}\n </Frame>\n </div>\n )\n}\n\nconst SessionEmbed: SessionEmbedComponent = Object.assign(SessionEmbedBase, {\n Overlay\n})\nexport default SessionEmbed\n","import { useCallback, useEffect, useRef } from 'react'\nimport type { Device, Session } from 'cobrowse-agent-sdk'\nimport useStableCallback from '@/hooks/useStableCallback'\nimport { useCobrowse } from '@/components/CobrowseProvider'\n\nexport const MAX_PUSH_ATTEMPTS = 5\nexport const PUSH_RETRY_MS = 4000\nexport const ERROR_PUSH_ERROR = 'push_error'\nexport const ERROR_PUSH_ATTEMPT_LIMIT_REACHED = 'push_attempt_limit_reached'\nexport const ERROR_DEVICE_NOT_FOUND = 'device_not_found'\nexport const ERROR_SESSION_NOT_FOUND = 'session_not_found'\nexport const ERROR_SESSION_ERROR = 'session_error'\n\nconst isAbortError = (error: unknown): boolean => {\n if (!(error instanceof Error)) {\n return false\n }\n\n return error.name === 'AbortError'\n}\n\nexport interface UseConnectDeviceOptions {\n deviceId: string\n onConnectAttempt?: (attempt: number) => void\n onConnected?: (session: Session) => void\n onCancelled?: (session: Session) => void\n onEnded?: (session: Session) => void\n onError?: (error: unknown) => void\n maxPushAttempts?: number\n pushRetryMs?: number\n}\n\nconst useConnectDevice = ({\n deviceId,\n onConnectAttempt,\n onConnected,\n onCancelled,\n onEnded,\n onError,\n maxPushAttempts = MAX_PUSH_ATTEMPTS,\n pushRetryMs = PUSH_RETRY_MS\n}: UseConnectDeviceOptions) => {\n const cobrowse = useCobrowse()\n const deviceRef = useRef<Device>(null)\n const sessionRef = useRef<Session>(null)\n const sessionConnectedRef = useRef(false)\n const sessionEndedRef = useRef(false)\n const pushTimerRef = useRef(0)\n const onConnectAttemptCallback = useStableCallback(onConnectAttempt)\n const onConnectedCallback = useStableCallback(onConnected)\n const onCancelledCallback = useStableCallback(onCancelled)\n const onEndedCallback = useStableCallback(onEnded)\n const onErrorCallback = useStableCallback(onError)\n\n const stopPush = useCallback(() => {\n clearTimeout(pushTimerRef.current)\n }, [])\n\n const handleSessionUpdated = useCallback((session: Session) => {\n if (!['pending', 'ended'].includes(session.state) && !sessionConnectedRef.current) {\n stopPush()\n onConnectedCallback(session)\n sessionConnectedRef.current = true\n }\n }, [onConnectedCallback, stopPush])\n\n const handleSessionEnded = useCallback((session: Session) => {\n if (!sessionEndedRef.current) {\n onEndedCallback(session)\n sessionEndedRef.current = true\n void sessionRef.current?.end()\n }\n }, [onEndedCallback])\n\n const triggerPushError = useCallback((error: unknown) => {\n if (isAbortError(error)) {\n return\n }\n\n if (error instanceof Error) {\n onErrorCallback({ id: ERROR_PUSH_ERROR, message: error.message })\n } else {\n onErrorCallback(error)\n }\n }, [onErrorCallback])\n\n const sendPush = useCallback(async function send (attempt = 1, abortController: AbortController) {\n onConnectAttemptCallback(attempt)\n\n if (attempt >= maxPushAttempts) {\n triggerPushError({ id: ERROR_PUSH_ATTEMPT_LIMIT_REACHED, message: 'Push attempt limit reached.' })\n\n return\n }\n\n if (!deviceRef.current) {\n triggerPushError({ id: ERROR_DEVICE_NOT_FOUND, message: 'Device not found.' })\n\n return\n }\n\n if (!sessionRef.current) {\n triggerPushError({ id: ERROR_SESSION_NOT_FOUND, message: 'Session not found.' })\n\n return\n }\n\n try {\n await deviceRef.current.notify({ session: sessionRef.current, attempt }, undefined, { signal: abortController.signal })\n } catch (error) {\n triggerPushError(error)\n }\n\n pushTimerRef.current = setTimeout(() => {\n void send(attempt + 1, abortController)\n }, pushRetryMs)\n }, [maxPushAttempts, onConnectAttemptCallback, pushRetryMs, triggerPushError])\n\n const createSession = useCallback(async (abortController: AbortController) => {\n const { signal } = abortController\n\n try {\n deviceRef.current = null\n sessionRef.current = null\n sessionConnectedRef.current = false\n sessionEndedRef.current = false\n\n const [region, device] = await Promise.all([\n cobrowse.regions.closest(undefined, { signal }),\n cobrowse.devices.get(deviceId, undefined, { signal })\n ])\n\n deviceRef.current = device\n\n const session = await cobrowse.sessions.create({\n custom_data: device.custom_data,\n region: region.id,\n agent: 'me'\n }, undefined, { signal })\n\n sessionRef.current = session\n\n session.on('updated', handleSessionUpdated)\n session.on('ended', handleSessionEnded)\n\n await session.subscribe()\n } catch (error) {\n if (isAbortError(error)) {\n return\n }\n\n if (error instanceof Error) {\n onErrorCallback({ id: ERROR_SESSION_ERROR, message: error.message })\n } else {\n onErrorCallback({ id: ERROR_SESSION_ERROR, message: 'The session could not be created.' })\n }\n }\n }, [cobrowse, deviceId, handleSessionEnded, handleSessionUpdated, onErrorCallback])\n\n const cancel = useCallback(async () => {\n stopPush()\n\n const session = sessionRef.current\n\n if (session) {\n await session.end()\n onCancelledCallback(session)\n }\n }, [onCancelledCallback, stopPush])\n\n useEffect(() => {\n const abortController = new AbortController()\n\n const runEffect = async () => {\n await createSession(abortController)\n\n if (abortController.signal.aborted) {\n return\n }\n\n await sendPush(1, abortController)\n }\n\n void runEffect()\n\n return () => {\n abortController.abort()\n stopPush()\n }\n }, [createSession, sendPush, stopPush])\n\n return { cancel }\n}\n\nexport default useConnectDevice\n","import { useState, type ReactNode } from 'react'\nimport type { Session } from 'cobrowse-agent-sdk'\nimport clsx from 'clsx'\nimport BaseLoader from '@/components/Loader'\nimport CancelButton, { type CancelButtonProps } from '@/components/CancelButton'\nimport { useTranslation } from '@/i18n'\nimport useConnectDevice, {\n ERROR_DEVICE_NOT_FOUND,\n ERROR_PUSH_ATTEMPT_LIMIT_REACHED,\n ERROR_PUSH_ERROR,\n ERROR_SESSION_ERROR,\n ERROR_SESSION_NOT_FOUND,\n MAX_PUSH_ATTEMPTS,\n PUSH_RETRY_MS\n} from './useConnectDevice'\nimport styles from './ConnectDevice.module.css'\n\nexport {\n ERROR_DEVICE_NOT_FOUND,\n ERROR_PUSH_ATTEMPT_LIMIT_REACHED,\n ERROR_PUSH_ERROR,\n ERROR_SESSION_ERROR,\n ERROR_SESSION_NOT_FOUND,\n MAX_PUSH_ATTEMPTS,\n PUSH_RETRY_MS\n}\n\nexport interface ConnectDeviceStatusMessageProps {\n attempt: number\n maxPushAttempts?: number\n className?: string\n}\n\nexport interface ConnectDeviceLoaderProps {\n attempt: number\n maxPushAttempts?: number\n}\n\nexport interface ConnectDeviceProps {\n deviceId: string,\n onConnectAttempt?: (attempt: number) => void\n onConnected?: (session: Session) => void\n onCancelled?: (session: Session) => void\n onEnded?: (session: Session) => void\n onError?: (error: unknown) => void\n maxPushAttempts?: number,\n pushRetryMs?: number\n className?: string\n children: (attempt: number, cancel: () => void) => ReactNode\n}\n\nconst StatusMessage = ({ attempt, maxPushAttempts = MAX_PUSH_ATTEMPTS, className }: ConnectDeviceStatusMessageProps) => {\n const { t } = useTranslation()\n let message = t('Contacting device')\n\n if (attempt >= maxPushAttempts) {\n message = t('Device not responding')\n } else if (attempt >= maxPushAttempts - 1) {\n message = t('Trying once more')\n } else if (attempt > 2) {\n message = t('Retrying connection')\n }\n\n return (\n <div className={clsx(styles.statusMessage, className)}>\n {message}\n </div>\n )\n}\n\nconst Loader = ({ attempt, maxPushAttempts = MAX_PUSH_ATTEMPTS }: ConnectDeviceLoaderProps) => {\n if (attempt >= maxPushAttempts) {\n return null\n }\n\n return <BaseLoader />\n}\n\ntype ConnectDeviceComponent = ((props: ConnectDeviceProps) => ReactNode) & {\n StatusMessage: (props: ConnectDeviceStatusMessageProps) => ReactNode\n Loader: (props: ConnectDeviceLoaderProps) => ReactNode\n CancelButton: (props: CancelButtonProps) => ReactNode\n}\n\nconst ConnectDeviceBase = ({\n deviceId,\n onConnectAttempt,\n onConnected,\n onCancelled,\n onEnded,\n onError,\n maxPushAttempts = MAX_PUSH_ATTEMPTS,\n pushRetryMs = PUSH_RETRY_MS,\n className,\n children\n}: ConnectDeviceProps) => {\n const [attempt, setAttempt] = useState(1)\n\n const handleConnectAttempt = (currentAttempt: number) => {\n setAttempt(currentAttempt)\n onConnectAttempt?.(currentAttempt)\n }\n\n const { cancel } = useConnectDevice({\n deviceId,\n onConnectAttempt: handleConnectAttempt,\n onConnected,\n onCancelled,\n onEnded,\n onError,\n maxPushAttempts,\n pushRetryMs\n })\n\n const handleCancel = () => {\n void cancel()\n }\n\n return (\n <div className={clsx(styles.root, className)}>\n {children(attempt, handleCancel)}\n </div>\n )\n}\n\nconst ConnectDevice: ConnectDeviceComponent = Object.assign(ConnectDeviceBase, {\n StatusMessage,\n Loader,\n CancelButton\n})\n\nexport default ConnectDevice\n","import CodeEntryComponent from '@/components/CodeEntry'\nimport ButtonComponent from '@/components/Button'\nimport ExternalLinkComponent from '@/components/ExternalLink'\nimport PlatformIconComponent from '@/components/PlatformIcon'\nimport DeviceComponent from '@/components/Device'\nimport SessionComponent from '@/components/Session'\nimport SmartConnectButtonComponent from '@/components/SmartConnectButton'\nimport UserIconComponent from '@/components/UserIcon'\nimport RefreshButtonComponent from '@/components/RefreshButton'\nimport CancelButtonComponent from '@/components/CancelButton'\nimport BlockingErrorComponent from '@/components/BlockingError'\nimport LoaderComponent from '@/components/Loader'\nimport FrameComponent, { useRemoteContext as useRemoteContextHook } from '@/components/Frame'\nimport SessionEmbedComponent from '@/components/SessionEmbed'\nimport ConnectDeviceComponent from '@/components/ConnectDevice'\nimport CobrowseProviderComponent, { useCobrowse as useCobrowseHook } from '@/components/CobrowseProvider'\nimport useSessionHook from '@/hooks/useSession'\nimport i18nInstance, { bindI18n as bindI18nHelper } from '@/i18n'\n\nexport type { CodeEntryProps } from '@/components/CodeEntry'\nexport type { ButtonProps } from '@/components/Button'\nexport type { ExternalLinkProps } from '@/components/ExternalLink'\nexport type { DeviceData, DeviceProps } from '@/components/Device'\nexport type { SessionData, SessionProps } from '@/components/Session'\nexport type { SmartConnectButtonProps } from '@/components/SmartConnectButton'\nexport type { RefreshButtonProps } from '@/components/RefreshButton'\nexport type { CancelButtonProps } from '@/components/CancelButton'\nexport type { BlockingErrorProps } from '@/components/BlockingError'\nexport type { LoaderProps } from '@/components/Loader'\nexport type { FrameProps } from '@/components/Frame'\nexport type { SessionEmbedProps } from '@/components/SessionEmbed'\nexport type { ConnectDeviceProps } from '@/components/ConnectDevice'\nexport type { CobrowseProviderProps } from '@/components/CobrowseProvider'\n\nexport const CodeEntry = CodeEntryComponent\nexport const Button = ButtonComponent\nexport const ExternalLink = ExternalLinkComponent\nexport const PlatformIcon = PlatformIconComponent\nexport const Device = DeviceComponent\nexport const Session = SessionComponent\nexport const SmartConnectButton = SmartConnectButtonComponent\nexport const UserIcon = UserIconComponent\nexport const RefreshButton = RefreshButtonComponent\nexport const CancelButton = CancelButtonComponent\nexport const BlockingError = BlockingErrorComponent\nexport const Loader = LoaderComponent\nexport const Frame = FrameComponent\nexport const SessionEmbed = SessionEmbedComponent\nexport const ConnectDevice = ConnectDeviceComponent\nexport const CobrowseProvider = CobrowseProviderComponent\nexport const useCobrowse = useCobrowseHook\nexport const useRemoteContext = useRemoteContextHook\nexport const useSession = useSessionHook\nexport const bindI18n = bindI18nHelper\nexport const i18n = i18nInstance\n"],"names":["getLanguage","resolvedLanguage","language","bindI18n","consumerI18n","syncLanguage","i18n","handleLanguageChanged","SvgExternalLink","props","React","__spreadValues","ExternalLink","href","children","jsxs","styles","IconExternalLink","UserIcon","user","className","initials","part","jsx","clsx","SvgPhone","CancelButton","_a","_b","type","__objRest","t","useTranslation","Button","__spreadProps","PhoneIcon","BlockingError","heading","message","CobrowseContext","createContext","CobrowseProvider","cobrowse","useCobrowseValue","use","useCobrowse","RemoteContext","useRemoteContext","target","providedRemoteContext","remoteContext","setRemoteContext","useState","useEffect","cancelled","attachedContext","__async","useStableCallback","callback","callbackRef","useRef","useCallback","args","Frame","src","onError","title","width","height","style","iframe","setIframe","onErrorCallback","handleIframeRef","element","handleError","error","RemoteContextProvider","isRemoteContext","source","hasSessionProperty","property","createReactiveSession","session","useSession","sessionSource","sessionState","setSessionState","handleSessionChange","Overlay","state","useSessionUrl","id","endAction","popout","agentTools","deviceControls","sessionDetails","messages","useMemo","paramEntries","name","value","query","SessionEventObserver","onLoaded","onUpdated","onActivated","onEnded","onLoadedCallback","onUpdatedCallback","onActivatedCallback","onEndedCallback","sessionActivatedRef","sessionEndedRef","handleSessionLoaded","handleSessionUpdated","SessionEmbedBase","url","SessionEmbed","MAX_PUSH_ATTEMPTS","PUSH_RETRY_MS","ERROR_PUSH_ERROR","ERROR_PUSH_ATTEMPT_LIMIT_REACHED","ERROR_DEVICE_NOT_FOUND","ERROR_SESSION_NOT_FOUND","ERROR_SESSION_ERROR","isAbortError","useConnectDevice","deviceId","onConnectAttempt","onConnected","onCancelled","maxPushAttempts","pushRetryMs","deviceRef","sessionRef","sessionConnectedRef","pushTimerRef","onConnectAttemptCallback","onConnectedCallback","onCancelledCallback","stopPush","handleSessionEnded","triggerPushError","sendPush","send","attempt","abortController","createSession","signal","region","device","cancel","StatusMessage","Loader","BaseLoader","ConnectDeviceBase","setAttempt","handleConnectAttempt","currentAttempt","handleCancel","ConnectDevice","CodeEntry","CodeEntryComponent","ButtonComponent","ExternalLinkComponent","PlatformIcon","PlatformIconComponent","Device","DeviceComponent","Session","SessionComponent","SmartConnectButton","SmartConnectButtonComponent","UserIconComponent","RefreshButton","RefreshButtonComponent","CancelButtonComponent","BlockingErrorComponent","LoaderComponent","FrameComponent","SessionEmbedComponent","ConnectDeviceComponent","CobrowseProviderComponent","useCobrowseHook","useRemoteContextHook","useSessionHook","bindI18nHelper","i18nInstance"],"mappings":"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"}