@coventia/softphone 0.2.1 → 0.4.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.
- package/dist/{call-VKq1I8yP.d.cts → call-C6YpT6uR.d.cts} +107 -1
- package/dist/{call-VKq1I8yP.d.ts → call-C6YpT6uR.d.ts} +107 -1
- package/dist/chunk-5E5OEXS2.js +14 -0
- package/dist/chunk-5E5OEXS2.js.map +1 -0
- package/dist/{chunk-LMJXX4YM.js → chunk-UHNLEBBO.js} +4 -2
- package/dist/chunk-UHNLEBBO.js.map +1 -0
- package/dist/element/index.d.ts +124 -9
- package/dist/element/index.js +1837 -413
- package/dist/element/index.js.map +1 -1
- package/dist/{engine-BlQBo2Ys.d.cts → engine-CDdaSojx.d.cts} +1 -1
- package/dist/{engine-C0BOkIcW.d.ts → engine-DPft99Wj.d.ts} +1 -1
- package/dist/index.cjs +213 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +16 -6
- package/dist/index.d.ts +16 -6
- package/dist/index.js +75 -10
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs +2 -0
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +2 -2
- package/dist/react/index.d.ts +2 -2
- package/dist/react/index.js +1 -1
- package/dist/{softphone-DlGV12Xp.d.cts → softphone-CY5d2WWY.d.cts} +28 -10
- package/dist/{softphone-Cyq3hiIM.d.ts → softphone-DXgmTyrX.d.ts} +28 -10
- package/dist/softphone.css +364 -35
- package/dist/{sources-IRKNQPWW.js → sources-ONYQW733.js} +125 -6
- package/dist/sources-ONYQW733.js.map +1 -0
- package/dist/testing/index.d.cts +2 -2
- package/dist/testing/index.d.ts +2 -2
- package/dist/ui/index.cjs +1450 -33
- package/dist/ui/index.cjs.map +1 -1
- package/dist/ui/index.d.cts +25 -3
- package/dist/ui/index.d.ts +25 -3
- package/dist/ui/index.js +1445 -36
- package/dist/ui/index.js.map +1 -1
- package/dist/zadarma/index.d.cts +2 -2
- package/dist/zadarma/index.d.ts +2 -2
- package/package.json +1 -1
- package/dist/chunk-LMJXX4YM.js.map +0 -1
- package/dist/sources-IRKNQPWW.js.map +0 -1
package/dist/ui/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../node_modules/shared/src/utils.ts","../../../../node_modules/lucide-react/src/defaultAttributes.ts","../../../../node_modules/lucide-react/src/Icon.ts","../../../../node_modules/lucide-react/src/createLucideIcon.ts","../../../../node_modules/lucide-react/src/icons/arrow-left-right.ts","../../../../node_modules/lucide-react/src/icons/arrow-left.ts","../../../../node_modules/lucide-react/src/icons/arrow-right.ts","../../../../node_modules/lucide-react/src/icons/calendar-clock.ts","../../../../node_modules/lucide-react/src/icons/check.ts","../../../../node_modules/lucide-react/src/icons/chevron-down.ts","../../../../node_modules/lucide-react/src/icons/chevron-right.ts","../../../../node_modules/lucide-react/src/icons/circle-help.ts","../../../../node_modules/lucide-react/src/icons/clock.ts","../../../../node_modules/lucide-react/src/icons/delete.ts","../../../../node_modules/lucide-react/src/icons/external-link.ts","../../../../node_modules/lucide-react/src/icons/grid-3x3.ts","../../../../node_modules/lucide-react/src/icons/hash.ts","../../../../node_modules/lucide-react/src/icons/headphones.ts","../../../../node_modules/lucide-react/src/icons/loader-circle.ts","../../../../node_modules/lucide-react/src/icons/mic-off.ts","../../../../node_modules/lucide-react/src/icons/mic.ts","../../../../node_modules/lucide-react/src/icons/monitor-smartphone.ts","../../../../node_modules/lucide-react/src/icons/pause.ts","../../../../node_modules/lucide-react/src/icons/phone-incoming.ts","../../../../node_modules/lucide-react/src/icons/phone-missed.ts","../../../../node_modules/lucide-react/src/icons/phone-off.ts","../../../../node_modules/lucide-react/src/icons/phone-outgoing.ts","../../../../node_modules/lucide-react/src/icons/phone.ts","../../../../node_modules/lucide-react/src/icons/play.ts","../../../../node_modules/lucide-react/src/icons/search.ts","../../../../node_modules/lucide-react/src/icons/settings.ts","../../../../node_modules/lucide-react/src/icons/timer.ts","../../../../node_modules/lucide-react/src/icons/triangle-alert.ts","../../../../node_modules/lucide-react/src/icons/user.ts","../../../../node_modules/lucide-react/src/icons/users.ts","../../../../node_modules/lucide-react/src/icons/x.ts","../../src/ui/dialing/countries.ts","../../src/ui/dialing/CountryPicker.tsx","../../src/ui/dialing/format-number.ts","../../src/ui/dialing/keys.ts","../../src/ui/audio/audio.ts","../../src/ui/views/Dialpad.tsx","../../src/ui/lib/format.ts","../../src/ui/lib/error-text.ts","../../src/ui/lib/useTicker.ts","../../src/ui/views/DevicePicker.tsx","../../src/ui/views/CallScreen.tsx","../../src/ui/views/DetailRow.tsx","../../src/ui/views/ContactDetail.tsx","../../src/ui/lib/useInfiniteList.ts","../../src/ui/views/ContactsTab.tsx","../../src/ui/views/history-format.tsx","../../src/ui/views/HistoryDetail.tsx","../../src/ui/views/HistoryTab.tsx","../../src/ui/views/SettingsSection.tsx","../../src/ui/views/SettingsTab.tsx","../../src/ui/permission/useMicPermission.ts","../../src/ui/permission/unblock-mic.ts","../../src/ui/permission/MicPermissionGate.tsx","../../src/ui/permission/ErrorGate.tsx","../../src/ui/permission/LeaderGate.tsx","../../src/ui/lib/useCallOutcome.ts","../../src/ui/audio/useCallAudio.ts","../../src/ui/notices/TransferNotices.tsx","../../src/ui/notices/useTransferNotices.ts","../../src/ui/SoftphoneWidget.tsx"],"names":["forwardRef","createElement","useState","useEffect","useRef","jsxs","jsx","Icon","Fragment","formatIntl","loading","useCallback","PAGE"],"mappings":"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","file":"index.js","sourcesContent":["import { CamelToPascal } from './utility-types';\n\n/**\n * Converts string to kebab case\n *\n * @param {string} string\n * @returns {string} A kebabized string\n */\nexport const toKebabCase = (string: string) =>\n string.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();\n\n/**\n * Converts string to pascal case\n *\n * @param {string} string\n * @returns {string} A pascalized string\n */\nexport const toPascalCase = <T extends string>(string: T): CamelToPascal<T> => {\n const camelCase = string.replace(/^([A-Z])|[\\s-_]+(\\w)/g, (match, p1, p2) =>\n p2 ? p2.toUpperCase() : p1.toLowerCase(),\n );\n\n return (camelCase.charAt(0).toUpperCase() + camelCase.slice(1)) as CamelToPascal<T>;\n};\n\n/**\n * Merges classes into a single string\n *\n * @param {array} classes\n * @returns {string} A string of classes\n */\nexport const mergeClasses = <ClassType = string | undefined | null>(...classes: ClassType[]) =>\n classes\n .filter((className, index, array) => {\n return Boolean(className) && array.indexOf(className) === index;\n })\n .join(' ');\n","export default {\n xmlns: 'http://www.w3.org/2000/svg',\n width: 24,\n height: 24,\n viewBox: '0 0 24 24',\n fill: 'none',\n stroke: 'currentColor',\n strokeWidth: 2,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n};\n","import { createElement, forwardRef } from 'react';\nimport defaultAttributes from './defaultAttributes';\nimport { IconNode, LucideProps } from './types';\nimport { mergeClasses } from '@lucide/shared';\n\ninterface IconComponentProps extends LucideProps {\n iconNode: IconNode;\n}\n\n/**\n * Lucide icon component\n *\n * @component Icon\n * @param {object} props\n * @param {string} props.color - The color of the icon\n * @param {number} props.size - The size of the icon\n * @param {number} props.strokeWidth - The stroke width of the icon\n * @param {boolean} props.absoluteStrokeWidth - Whether to use absolute stroke width\n * @param {string} props.className - The class name of the icon\n * @param {IconNode} props.children - The children of the icon\n * @param {IconNode} props.iconNode - The icon node of the icon\n *\n * @returns {ForwardRefExoticComponent} LucideIcon\n */\nconst Icon = forwardRef<SVGSVGElement, IconComponentProps>(\n (\n {\n color = 'currentColor',\n size = 24,\n strokeWidth = 2,\n absoluteStrokeWidth,\n className = '',\n children,\n iconNode,\n ...rest\n },\n ref,\n ) => {\n return createElement(\n 'svg',\n {\n ref,\n ...defaultAttributes,\n width: size,\n height: size,\n stroke: color,\n strokeWidth: absoluteStrokeWidth ? (Number(strokeWidth) * 24) / Number(size) : strokeWidth,\n className: mergeClasses('lucide', className),\n ...rest,\n },\n [\n ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...(Array.isArray(children) ? children : [children]),\n ],\n );\n },\n);\n\nexport default Icon;\n","import { createElement, forwardRef } from 'react';\nimport { mergeClasses, toKebabCase } from '@lucide/shared';\nimport { IconNode, LucideProps } from './types';\nimport Icon from './Icon';\n\n/**\n * Create a Lucide icon component\n * @param {string} iconName\n * @param {array} iconNode\n * @returns {ForwardRefExoticComponent} LucideIcon\n */\nconst createLucideIcon = (iconName: string, iconNode: IconNode) => {\n const Component = forwardRef<SVGSVGElement, LucideProps>(({ className, ...props }, ref) =>\n createElement(Icon, {\n ref,\n iconNode,\n className: mergeClasses(`lucide-${toKebabCase(iconName)}`, className),\n ...props,\n }),\n );\n\n Component.displayName = `${iconName}`;\n\n return Component;\n};\n\nexport default createLucideIcon;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name ArrowLeftRight\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/arrow-left-right\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst ArrowLeftRight = createLucideIcon('ArrowLeftRight', [\n ['path', { d: 'M8 3 4 7l4 4', key: '9rb6wj' }],\n ['path', { d: 'M4 7h16', key: '6tx8e3' }],\n ['path', { d: 'm16 21 4-4-4-4', key: 'siv7j2' }],\n ['path', { d: 'M20 17H4', key: 'h6l3hr' }],\n]);\n\nexport default ArrowLeftRight;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name ArrowLeft\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/arrow-left\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst ArrowLeft = createLucideIcon('ArrowLeft', [\n ['path', { d: 'm12 19-7-7 7-7', key: '1l729n' }],\n ['path', { d: 'M19 12H5', key: 'x3x0zl' }],\n]);\n\nexport default ArrowLeft;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name ArrowRight\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/arrow-right\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst ArrowRight = createLucideIcon('ArrowRight', [\n ['path', { d: 'M5 12h14', key: '1ays0h' }],\n ['path', { d: 'm12 5 7 7-7 7', key: 'xquz4c' }],\n]);\n\nexport default ArrowRight;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name CalendarClock\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/calendar-clock\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst CalendarClock = createLucideIcon('CalendarClock', [\n ['path', { d: 'M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5', key: '1osxxc' }],\n ['path', { d: 'M16 2v4', key: '4m81vk' }],\n ['path', { d: 'M8 2v4', key: '1cmpym' }],\n ['path', { d: 'M3 10h5', key: 'r794hk' }],\n ['path', { d: 'M17.5 17.5 16 16.3V14', key: 'akvzfd' }],\n ['circle', { cx: '16', cy: '16', r: '6', key: 'qoo3c4' }],\n]);\n\nexport default CalendarClock;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Check\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/check\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Check = createLucideIcon('Check', [['path', { d: 'M20 6 9 17l-5-5', key: '1gmf2c' }]]);\n\nexport default Check;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name ChevronDown\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/chevron-down\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst ChevronDown = createLucideIcon('ChevronDown', [\n ['path', { d: 'm6 9 6 6 6-6', key: 'qrunsl' }],\n]);\n\nexport default ChevronDown;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name ChevronRight\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/chevron-right\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst ChevronRight = createLucideIcon('ChevronRight', [\n ['path', { d: 'm9 18 6-6-6-6', key: 'mthhwq' }],\n]);\n\nexport default ChevronRight;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name CircleHelp\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/circle-help\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst CircleHelp = createLucideIcon('CircleHelp', [\n ['circle', { cx: '12', cy: '12', r: '10', key: '1mglay' }],\n ['path', { d: 'M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3', key: '1u773s' }],\n ['path', { d: 'M12 17h.01', key: 'p32p05' }],\n]);\n\nexport default CircleHelp;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Clock\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/clock\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Clock = createLucideIcon('Clock', [\n ['circle', { cx: '12', cy: '12', r: '10', key: '1mglay' }],\n ['polyline', { points: '12 6 12 12 16 14', key: '68esgv' }],\n]);\n\nexport default Clock;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Delete\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/delete\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Delete = createLucideIcon('Delete', [\n [\n 'path',\n {\n d: 'M10 5a2 2 0 0 0-1.344.519l-6.328 5.74a1 1 0 0 0 0 1.481l6.328 5.741A2 2 0 0 0 10 19h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2z',\n key: '1yo7s0',\n },\n ],\n ['path', { d: 'm12 9 6 6', key: 'anjzzh' }],\n ['path', { d: 'm18 9-6 6', key: '1fp51s' }],\n]);\n\nexport default Delete;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name ExternalLink\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/external-link\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst ExternalLink = createLucideIcon('ExternalLink', [\n ['path', { d: 'M15 3h6v6', key: '1q9fwt' }],\n ['path', { d: 'M10 14 21 3', key: 'gplh6r' }],\n ['path', { d: 'M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6', key: 'a6xqqp' }],\n]);\n\nexport default ExternalLink;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Grid3x3\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/grid-3x3\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Grid3x3 = createLucideIcon('Grid3x3', [\n ['rect', { width: '18', height: '18', x: '3', y: '3', rx: '2', key: 'afitv7' }],\n ['path', { d: 'M3 9h18', key: '1pudct' }],\n ['path', { d: 'M3 15h18', key: '5xshup' }],\n ['path', { d: 'M9 3v18', key: 'fh3hqa' }],\n ['path', { d: 'M15 3v18', key: '14nvp0' }],\n]);\n\nexport default Grid3x3;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Hash\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/hash\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Hash = createLucideIcon('Hash', [\n ['line', { x1: '4', x2: '20', y1: '9', y2: '9', key: '4lhtct' }],\n ['line', { x1: '4', x2: '20', y1: '15', y2: '15', key: 'vyu0kd' }],\n ['line', { x1: '10', x2: '8', y1: '3', y2: '21', key: '1ggp8o' }],\n ['line', { x1: '16', x2: '14', y1: '3', y2: '21', key: 'weycgp' }],\n]);\n\nexport default Hash;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Headphones\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/headphones\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Headphones = createLucideIcon('Headphones', [\n [\n 'path',\n {\n d: 'M3 14h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7a9 9 0 0 1 18 0v7a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3',\n key: '1xhozi',\n },\n ],\n]);\n\nexport default Headphones;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name LoaderCircle\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/loader-circle\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst LoaderCircle = createLucideIcon('LoaderCircle', [\n ['path', { d: 'M21 12a9 9 0 1 1-6.219-8.56', key: '13zald' }],\n]);\n\nexport default LoaderCircle;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name MicOff\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/mic-off\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst MicOff = createLucideIcon('MicOff', [\n ['line', { x1: '2', x2: '22', y1: '2', y2: '22', key: 'a6p6uj' }],\n ['path', { d: 'M18.89 13.23A7.12 7.12 0 0 0 19 12v-2', key: '80xlxr' }],\n ['path', { d: 'M5 10v2a7 7 0 0 0 12 5', key: 'p2k8kg' }],\n ['path', { d: 'M15 9.34V5a3 3 0 0 0-5.68-1.33', key: '1gzdoj' }],\n ['path', { d: 'M9 9v3a3 3 0 0 0 5.12 2.12', key: 'r2i35w' }],\n ['line', { x1: '12', x2: '12', y1: '19', y2: '22', key: 'x3vr5v' }],\n]);\n\nexport default MicOff;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Mic\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/mic\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Mic = createLucideIcon('Mic', [\n ['path', { d: 'M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z', key: '131961' }],\n ['path', { d: 'M19 10v2a7 7 0 0 1-14 0v-2', key: '1vc78b' }],\n ['line', { x1: '12', x2: '12', y1: '19', y2: '22', key: 'x3vr5v' }],\n]);\n\nexport default Mic;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name MonitorSmartphone\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/monitor-smartphone\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst MonitorSmartphone = createLucideIcon('MonitorSmartphone', [\n ['path', { d: 'M18 8V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h8', key: '10dyio' }],\n ['path', { d: 'M10 19v-3.96 3.15', key: '1irgej' }],\n ['path', { d: 'M7 19h5', key: 'qswx4l' }],\n ['rect', { width: '6', height: '10', x: '16', y: '12', rx: '2', key: '1egngj' }],\n]);\n\nexport default MonitorSmartphone;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Pause\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/pause\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Pause = createLucideIcon('Pause', [\n ['rect', { x: '14', y: '4', width: '4', height: '16', rx: '1', key: 'zuxfzm' }],\n ['rect', { x: '6', y: '4', width: '4', height: '16', rx: '1', key: '1okwgv' }],\n]);\n\nexport default Pause;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name PhoneIncoming\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/phone-incoming\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst PhoneIncoming = createLucideIcon('PhoneIncoming', [\n ['polyline', { points: '16 2 16 8 22 8', key: '1ygljm' }],\n ['line', { x1: '22', x2: '16', y1: '2', y2: '8', key: '1xzwqn' }],\n [\n 'path',\n {\n d: 'M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z',\n key: 'foiqr5',\n },\n ],\n]);\n\nexport default PhoneIncoming;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name PhoneMissed\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/phone-missed\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst PhoneMissed = createLucideIcon('PhoneMissed', [\n ['line', { x1: '22', x2: '16', y1: '2', y2: '8', key: '1xzwqn' }],\n ['line', { x1: '16', x2: '22', y1: '2', y2: '8', key: '13zxdn' }],\n [\n 'path',\n {\n d: 'M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z',\n key: 'foiqr5',\n },\n ],\n]);\n\nexport default PhoneMissed;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name PhoneOff\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/phone-off\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst PhoneOff = createLucideIcon('PhoneOff', [\n [\n 'path',\n {\n d: 'M10.68 13.31a16 16 0 0 0 3.41 2.6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7 2 2 0 0 1 1.72 2v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.42 19.42 0 0 1-3.33-2.67m-2.67-3.34a19.79 19.79 0 0 1-3.07-8.63A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91',\n key: 'z86iuo',\n },\n ],\n ['line', { x1: '22', x2: '2', y1: '2', y2: '22', key: '11kh81' }],\n]);\n\nexport default PhoneOff;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name PhoneOutgoing\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/phone-outgoing\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst PhoneOutgoing = createLucideIcon('PhoneOutgoing', [\n ['polyline', { points: '22 8 22 2 16 2', key: '1g204g' }],\n ['line', { x1: '16', x2: '22', y1: '8', y2: '2', key: '1ggias' }],\n [\n 'path',\n {\n d: 'M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z',\n key: 'foiqr5',\n },\n ],\n]);\n\nexport default PhoneOutgoing;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Phone\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/phone\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Phone = createLucideIcon('Phone', [\n [\n 'path',\n {\n d: 'M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z',\n key: 'foiqr5',\n },\n ],\n]);\n\nexport default Phone;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Play\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/play\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Play = createLucideIcon('Play', [\n ['polygon', { points: '6 3 20 12 6 21 6 3', key: '1oa8hb' }],\n]);\n\nexport default Play;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Search\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/search\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Search = createLucideIcon('Search', [\n ['circle', { cx: '11', cy: '11', r: '8', key: '4ej97u' }],\n ['path', { d: 'm21 21-4.3-4.3', key: '1qie3q' }],\n]);\n\nexport default Search;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Settings\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/settings\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Settings = createLucideIcon('Settings', [\n [\n 'path',\n {\n d: 'M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z',\n key: '1qme2f',\n },\n ],\n ['circle', { cx: '12', cy: '12', r: '3', key: '1v7zrd' }],\n]);\n\nexport default Settings;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Timer\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/timer\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Timer = createLucideIcon('Timer', [\n ['line', { x1: '10', x2: '14', y1: '2', y2: '2', key: '14vaq8' }],\n ['line', { x1: '12', x2: '15', y1: '14', y2: '11', key: '17fdiu' }],\n ['circle', { cx: '12', cy: '14', r: '8', key: '1e1u0o' }],\n]);\n\nexport default Timer;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name TriangleAlert\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/triangle-alert\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst TriangleAlert = createLucideIcon('TriangleAlert', [\n [\n 'path',\n {\n d: 'm21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3',\n key: 'wmoenq',\n },\n ],\n ['path', { d: 'M12 9v4', key: 'juzpu7' }],\n ['path', { d: 'M12 17h.01', key: 'p32p05' }],\n]);\n\nexport default TriangleAlert;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name User\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/user\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst User = createLucideIcon('User', [\n ['path', { d: 'M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2', key: '975kel' }],\n ['circle', { cx: '12', cy: '7', r: '4', key: '17ys0d' }],\n]);\n\nexport default User;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Users\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/users\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Users = createLucideIcon('Users', [\n ['path', { d: 'M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2', key: '1yyitq' }],\n ['circle', { cx: '9', cy: '7', r: '4', key: 'nufk8' }],\n ['path', { d: 'M22 21v-2a4 4 0 0 0-3-3.87', key: 'kshegd' }],\n ['path', { d: 'M16 3.13a4 4 0 0 1 0 7.75', key: '1da9ce' }],\n]);\n\nexport default Users;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name X\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/x\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst X = createLucideIcon('X', [\n ['path', { d: 'M18 6 6 18', key: '1bl5f8' }],\n ['path', { d: 'm6 6 12 12', key: 'd8bk6v' }],\n]);\n\nexport default X;\n","/**\r\n * Country → dial code, flags and names — **data and platform APIs, not a dependency** (SPEC §11).\r\n *\r\n * The CRM reached all of this through `react-phone-number-input` + its flag SVGs: **82 kB brotli,\r\n * measured**. Everything below costs **~1 kB**, because the expensive parts are already in the\r\n * browser:\r\n *\r\n * - **names** → `Intl.DisplayNames`, localised, shipped with the runtime\r\n * - **codes** → the table below, 245 regions in 1,364 characters\r\n *\r\n * Flags are the exception and live in `CountryPicker`: real SVGs from `country-flag-icons`, 40 kB\r\n * brotli for all 245, **lazily imported** so they cost nothing until someone opens the picker. An\r\n * earlier cut used flag EMOJI (free, but Windows ships none and degrades to stray letters) — that is\r\n * gone: an SVG renders the same everywhere, and the emoji-support probe it needed went with it.\r\n *\r\n * What we give up is libphonenumber's parsing and validation — deliberately. A dialer must let you\r\n * dial anything: refusing a call because a number looks wrong for a region is a bug, not a feature.\r\n * We compose `+<code><digits>` and let the PBX decide.\r\n */\r\n\r\n/**\r\n * ISO 3166-1 alpha-2 immediately followed by its E.164 calling code, space-separated.\r\n *\r\n * Packed as one string rather than an object literal: no quotes, no colons, no commas — it compresses\r\n * to **729 bytes brotli**, and it parses once at module load into the Map below.\r\n *\r\n * GENERATED — do not hand-edit. Regenerate against a real source with:\r\n *\r\n * node -e \"const{getCountries,getCountryCallingCode}=require('libphonenumber-js/min');\\\r\n * console.log(getCountries().map(c=>c+getCountryCallingCode(c)).join(' '))\"\r\n */\r\nconst PACKED =\r\n 'AC247 AD376 AE971 AF93 AG1 AI1 AL355 AM374 AO244 AR54 AS1 AT43 AU61 AW297 AX358 AZ994 ' +\r\n 'BA387 BB1 BD880 BE32 BF226 BG359 BH973 BI257 BJ229 BL590 BM1 BN673 BO591 BQ599 BR55 BS1 ' +\r\n 'BT975 BW267 BY375 BZ501 CA1 CC61 CD243 CF236 CG242 CH41 CI225 CK682 CL56 CM237 CN86 CO57 ' +\r\n 'CR506 CU53 CV238 CW599 CX61 CY357 CZ420 DE49 DJ253 DK45 DM1 DO1 DZ213 EC593 EE372 EG20 ' +\r\n 'EH212 ER291 ES34 ET251 FI358 FJ679 FK500 FM691 FO298 FR33 GA241 GB44 GD1 GE995 GF594 ' +\r\n 'GG44 GH233 GI350 GL299 GM220 GN224 GP590 GQ240 GR30 GT502 GU1 GW245 GY592 HK852 HN504 ' +\r\n 'HR385 HT509 HU36 ID62 IE353 IL972 IM44 IN91 IO246 IQ964 IR98 IS354 IT39 JE44 JM1 JO962 ' +\r\n 'JP81 KE254 KG996 KH855 KI686 KM269 KN1 KP850 KR82 KW965 KY1 KZ7 LA856 LB961 LC1 LI423 ' +\r\n 'LK94 LR231 LS266 LT370 LU352 LV371 LY218 MA212 MC377 MD373 ME382 MF590 MG261 MH692 MK389 ' +\r\n 'ML223 MM95 MN976 MO853 MP1 MQ596 MR222 MS1 MT356 MU230 MV960 MW265 MX52 MY60 MZ258 NA264 ' +\r\n 'NC687 NE227 NF672 NG234 NI505 NL31 NO47 NP977 NR674 NU683 NZ64 OM968 PA507 PE51 PF689 ' +\r\n 'PG675 PH63 PK92 PL48 PM508 PR1 PS970 PT351 PW680 PY595 QA974 RE262 RO40 RS381 RU7 RW250 ' +\r\n 'SA966 SB677 SC248 SD249 SE46 SG65 SH290 SI386 SJ47 SK421 SL232 SM378 SN221 SO252 SR597 ' +\r\n 'SS211 ST239 SV503 SX1 SY963 SZ268 TA290 TC1 TD235 TG228 TH66 TJ992 TK690 TL670 TM993 ' +\r\n 'TN216 TO676 TR90 TT1 TV688 TW886 TZ255 UA380 UG256 US1 UY598 UZ998 VA39 VC1 VE58 VG1 VI1 ' +\r\n 'VN84 VU678 WF681 WS685 XK383 YE967 YT262 ZA27 ZM260 ZW263';\r\n\r\n/** ISO alpha-2 → calling code, e.g. `'ES' → 34`. */\r\nexport const DIAL_CODES: ReadonlyMap<string, number> = new Map(\r\n PACKED.split(' ').map((token) => [token.slice(0, 2), Number(token.slice(2))]),\r\n);\r\n\r\n/** The picker's default. Coventia is Spanish and so is the UI (SPEC §2.4). */\r\nexport const DEFAULT_COUNTRY = 'ES';\r\n\r\n// Built once, not per render — `Intl.DisplayNames` construction is not free, and this module is\r\n// imported by a component that re-renders on every keystroke.\r\nconst REGION_NAMES = (() => {\r\n try {\r\n return new Intl.DisplayNames(['es'], { type: 'region' });\r\n } catch {\r\n return null; // ancient runtime — fall back to the code\r\n }\r\n})();\r\n\r\n/** `'ES'` → `'España'`, localised by the platform. Falls back to the code. */\r\nexport function countryName(country: string): string {\r\n try {\r\n return REGION_NAMES?.of(country) ?? country;\r\n } catch {\r\n return country; // `of()` throws on codes it does not know (e.g. 'TA', 'XK')\r\n }\r\n}\r\n\r\nexport interface CountryOption {\r\n readonly code: string;\r\n readonly name: string;\r\n readonly dial: number;\r\n}\r\n\r\n/** Every country, sorted by localised name — the picker's list. Computed once. */\r\nexport const COUNTRIES: readonly CountryOption[] = [...DIAL_CODES.entries()]\r\n .map(([code, dial]) => ({ code, name: countryName(code), dial }))\r\n .sort((a, b) => a.name.localeCompare(b.name, 'es'));\r\n\r\n/**\r\n * Compose what the user sees into what the PBX gets: `('ES', '600 111 222')` → `'+34600111222'`.\r\n *\r\n * No validation, on purpose (see the module header). Two rules earn their place:\r\n * - a national number written with a trunk `0` (`06 12 34 56 78` in FR) must lose it, or the PBX\r\n * receives a number with a digit that only means something domestically;\r\n * - if the user typed a full international number themselves, respect it and do not prepend a\r\n * second country code.\r\n */\r\nexport function toE164(country: string, national: string): string {\r\n const typed = String(national ?? '').trim();\r\n if (typed.startsWith('+')) return '+' + typed.slice(1).replace(/\\D/g, '');\r\n\r\n const digits = typed.replace(/\\D/g, '').replace(/^0+/, '');\r\n if (!digits) return '';\r\n const dial = DIAL_CODES.get(country);\r\n return dial === undefined ? `+${digits}` : `+${dial}${digits}`;\r\n}\r\n","import { useEffect, useMemo, useRef, useState, type ComponentType } from 'react';\r\nimport { Check, ChevronDown } from 'lucide-react';\r\nimport { COUNTRIES, DIAL_CODES, countryName } from './countries.js';\r\n\r\ntype FlagSet = Readonly<Record<string, ComponentType<{ className?: string }> | undefined>>;\r\n\r\n/**\r\n * Real SVG flags, fetched once, on nobody's critical path.\r\n *\r\n * All 245 are **40 kB brotli** and cannot tree-shake (the picker looks them up by code), which is a\r\n * lot to put in front of every consumer for a chip most never open. Named imports shake to ~350 B\r\n * each, so this is the one place the cost is unavoidable — and the one place it is easy to defer.\r\n *\r\n * Module-level, not per component: the chip and 245 rows share one import and one chunk. tsup emits\r\n * it as a relative chunk, so `/element` stays self-contained (`verify-static` walks relative imports)\r\n * and a CDN `<script type=\"module\">` resolves it fine.\r\n */\r\nlet FLAGS: FlagSet | null = null;\r\nlet flagsPromise: Promise<FlagSet> | null = null;\r\n\r\nfunction loadFlags(): Promise<FlagSet> {\r\n flagsPromise ??= import('country-flag-icons/react/3x2')\r\n .then((m) => (FLAGS = m as FlagSet))\r\n .catch(() => (FLAGS = {})); // offline / blocked: keep the plates, never break the dialer\r\n return flagsPromise;\r\n}\r\n\r\nfunction useFlags(): FlagSet | null {\r\n const [flags, setFlags] = useState<FlagSet | null>(FLAGS);\r\n useEffect(() => {\r\n if (flags) return;\r\n let alive = true;\r\n void loadFlags().then((f) => {\r\n if (alive) setFlags(f);\r\n });\r\n return () => {\r\n alive = false;\r\n };\r\n }, [flags]);\r\n return flags;\r\n}\r\n\r\n/**\r\n * The country mark: a flag, or the ISO code set into a plate.\r\n *\r\n * **Both are designed states in one 20×14 box** — a flag's own 3:2 — so the chip and every row keep\r\n * their rhythm regardless of which is showing. Nothing reflows when the flags arrive.\r\n *\r\n * The plate is the LOADING state (and the offline state), not a fallback. That distinction is the\r\n * whole design: there is no flash of something broken, only a designed plate becoming a designed flag\r\n * once, on the first widget of the session.\r\n */\r\nfunction CountryMark({ code }: Readonly<{ code: string }>) {\r\n const flags = useFlags();\r\n const Flag = flags?.[code];\r\n return (\r\n <span className=\"cv-mark\" data-plate={!Flag} aria-hidden part=\"country-mark\">\r\n {Flag ? <Flag className=\"cv-mark-svg\" /> : code}\r\n </span>\r\n );\r\n}\r\n\r\n/**\r\n * The prefix chip: flag + dial code, opening a searchable country list.\r\n *\r\n * Own combobox — no `cmdk`, no Radix `Popover`, no `ScrollArea` (S7 dropped those with the rest of\r\n * shadcn). It is a `<button>` and a positioned `<div>`, which is all the CRM's version was underneath.\r\n *\r\n * Search matches the localised NAME, the ISO code, and the dial code, so \"esp\", \"ES\" and \"+34\" all\r\n * find Spain — the CRM's `CommandItem value={`${name} ${code} +${calling}`}` did the same thing, and\r\n * it is the difference between a picker you can use and one you scroll for twenty seconds.\r\n */\r\nexport function CountryPicker({\r\n value,\r\n onChange,\r\n}: Readonly<{ value: string; onChange: (code: string) => void }>) {\r\n const [open, setOpen] = useState(false);\r\n const [query, setQuery] = useState('');\r\n const rootRef = useRef<HTMLDivElement>(null);\r\n const inputRef = useRef<HTMLInputElement>(null);\r\n\r\n const results = useMemo(() => {\r\n const q = query.trim().toLowerCase().replace(/^\\+/, '');\r\n if (!q) return COUNTRIES;\r\n return COUNTRIES.filter(\r\n (c) =>\r\n c.name.toLowerCase().includes(q) ||\r\n c.code.toLowerCase().includes(q) ||\r\n String(c.dial).startsWith(q),\r\n );\r\n }, [query]);\r\n\r\n // Close on outside click / Escape. Deliberately on the SHADOW ROOT's node when there is one:\r\n // inside a shadow tree, `document` click targets are retargeted to the host, so `contains()`\r\n // against the host would report every internal click as \"outside\" and the list would never open.\r\n useEffect(() => {\r\n if (!open) return;\r\n const root = rootRef.current?.getRootNode() ?? document;\r\n const onDown = (e: Event) => {\r\n if (!rootRef.current?.contains(e.target as Node)) setOpen(false);\r\n };\r\n const onKey = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') setOpen(false);\r\n };\r\n root.addEventListener('pointerdown', onDown);\r\n document.addEventListener('keydown', onKey);\r\n return () => {\r\n root.removeEventListener('pointerdown', onDown);\r\n document.removeEventListener('keydown', onKey);\r\n };\r\n }, [open]);\r\n\r\n useEffect(() => {\r\n if (open) inputRef.current?.focus();\r\n else setQuery('');\r\n }, [open]);\r\n\r\n const dial = DIAL_CODES.get(value);\r\n\r\n return (\r\n <div className=\"cv-cp\" ref={rootRef}>\r\n <button\r\n type=\"button\"\r\n className=\"cv-cp-chip\"\r\n onClick={() => setOpen((o) => !o)}\r\n aria-haspopup=\"listbox\"\r\n aria-expanded={open}\r\n // The mark is aria-hidden — a flag glyph reads as \"flag of Spain\" or, on a plate, as the bare\r\n // letters \"ES\". Neither is what a screen-reader user needs, so the name carries it instead.\r\n aria-label={`Prefijo: ${countryName(value)} (+${dial ?? '?'}). Cambiar país`}\r\n part=\"country-chip\"\r\n >\r\n <CountryMark code={value} />\r\n <span className=\"cv-cp-dial\">+{dial ?? '?'}</span>\r\n <ChevronDown size={13} className=\"cv-cp-caret\" data-open={open} />\r\n </button>\r\n\r\n {open ? (\r\n <div className=\"cv-cp-pop\" role=\"dialog\" part=\"country-list\">\r\n <input\r\n ref={inputRef}\r\n className=\"cv-cp-search\"\r\n value={query}\r\n onChange={(e) => setQuery(e.target.value)}\r\n placeholder=\"Buscar país…\"\r\n aria-label=\"Buscar país\"\r\n />\r\n <div className=\"cv-cp-list\" role=\"listbox\">\r\n {results.length === 0 ? (\r\n <p className=\"cv-cp-empty\">No se encontró ningún país.</p>\r\n ) : (\r\n results.map((c) => (\r\n <button\r\n key={c.code}\r\n type=\"button\"\r\n role=\"option\"\r\n aria-selected={c.code === value}\r\n className=\"cv-cp-item\"\r\n onClick={() => {\r\n onChange(c.code);\r\n setOpen(false);\r\n }}\r\n >\r\n <CountryMark code={c.code} />\r\n <span className=\"cv-cp-name\">{c.name}</span>\r\n <span className=\"cv-cp-dial\">+{c.dial}</span>\r\n <Check size={14} className=\"cv-cp-check\" data-on={c.code === value} />\r\n </button>\r\n ))\r\n )}\r\n </div>\r\n </div>\r\n ) : null}\r\n </div>\r\n );\r\n}\r\n","/**\r\n * As-you-type national grouping — `600111222` → `600 11 12 22`.\r\n *\r\n * **Lazily imported, like the flags.** `libphonenumber-js/min` is 27 kB brotli, which is 3× the whole\r\n * `/ui` entry, and it is needed only once someone actually types. Preloaded on mount so it is there\r\n * before a human can reach the keypad; until then digits render unformatted and then snap into\r\n * groups, which is a far better failure than blocking first paint on a formatting table.\r\n *\r\n * **Why a library at all**, when `countries.ts` deliberately avoids one: there is no universal rule.\r\n *\r\n * ES 600111222 → 600 11 12 22 (3-2-2-2)\r\n * FR 0612345678 → 06 12 34 56 78 (2-2-2-2-2)\r\n * GB 07911123456 → 07911 123456 (5-6)\r\n * DE 01701234567 → 0170 1234567 (4-7)\r\n *\r\n * GB and DE group differently again for landlines. A hand-rolled table would be wrong for most of the\r\n * world, and wrong grouping reads as broken rather than as a simplification. This is grouping ONLY —\r\n * we still do not validate, and `toE164` is still the thing that decides what gets dialled.\r\n */\r\nimport { useEffect, useState } from 'react';\r\n\r\ntype AsYouTypeCtor = new (country?: string) => { input(text: string): string };\r\ntype ParseIntl = (text: string) => { formatInternational(): string } | undefined;\r\n\r\nlet AsYouType: AsYouTypeCtor | null = null;\r\nlet parseIntl: ParseIntl | null = null;\r\nlet loading: Promise<void> | null = null;\r\n\r\n/**\r\n * Fetch the metadata once per page. Safe to call repeatedly; resolves immediately once loaded.\r\n *\r\n * One shared load for BOTH formatters this file exports (`formatNational` for as-you-type in the\r\n * dialer, `formatIntl` for a full E.164 number on the contact detail page) — same 27 kB chunk either\r\n * way, so a second consumer must not pay for it twice or drift onto a second copy of the metadata.\r\n */\r\nexport function loadNumberFormatter(): Promise<void> {\r\n loading ??= import('libphonenumber-js/min')\r\n .then((m) => {\r\n AsYouType = m.AsYouType as unknown as AsYouTypeCtor;\r\n parseIntl = m.parsePhoneNumberFromString as unknown as ParseIntl;\r\n })\r\n .catch(() => {\r\n // Offline, blocked, or a bundler that could not fetch the chunk: keep dialing with plain\r\n // digits. Formatting is a nicety; the dialer is not.\r\n });\r\n return loading;\r\n}\r\n\r\n/**\r\n * A full E.164 number (`+34600111222`) as it is normally written (`+34 600 11 12 22`). Same\r\n * never-empty-never-mangled contract as `formatNational`: the raw number until metadata loads or on\r\n * any parse failure — a contact's own phone number is never worth blocking on or hiding behind a\r\n * formatting error.\r\n */\r\nexport function formatIntl(e164: string): string {\r\n if (!parseIntl) return e164;\r\n try {\r\n return parseIntl(e164)?.formatInternational() ?? e164;\r\n } catch {\r\n return e164;\r\n }\r\n}\r\n\r\n/** Subscribe a component to the formatter, the same way `useNumberFormatter` does for typing. */\r\nexport function useIntlFormatter(): typeof formatIntl {\r\n const [, bump] = useState(0);\r\n useEffect(() => {\r\n if (parseIntl) return;\r\n let alive = true;\r\n void loadNumberFormatter().then(() => {\r\n if (alive) bump((n) => n + 1);\r\n });\r\n return () => {\r\n alive = false;\r\n };\r\n }, []);\r\n return formatIntl;\r\n}\r\n\r\n/**\r\n * Group `digits` the way `country` writes them. Returns the input unchanged until the metadata has\r\n * loaded, and on any parse failure — so the display is always *at worst* the digits the user typed,\r\n * never empty and never mangled.\r\n */\r\nexport function formatNational(country: string, digits: string): string {\r\n if (!AsYouType || !digits) return digits;\r\n try {\r\n return new AsYouType(country).input(digits);\r\n } catch {\r\n return digits;\r\n }\r\n}\r\n\r\n/**\r\n * Subscribe a component to the formatter. Returns `formatNational`, re-rendering once when the\r\n * metadata lands so an already-typed number regroups itself.\r\n */\r\nexport function useNumberFormatter(): typeof formatNational {\r\n const [, bump] = useState(0);\r\n useEffect(() => {\r\n if (AsYouType) return;\r\n let alive = true;\r\n void loadNumberFormatter().then(() => {\r\n if (alive) bump((n) => n + 1);\r\n });\r\n return () => {\r\n alive = false;\r\n };\r\n }, []);\r\n return formatNational;\r\n}\r\n\r\n/**\r\n * Where the caret belongs after reformatting, counted in DIGITS rather than characters.\r\n *\r\n * Without this, inserting a digit mid-number reformats the string, the caret snaps to the end, and\r\n * the next keystroke lands somewhere the user did not choose. Counting digits is the only stable\r\n * anchor, because the separators are exactly what moves.\r\n */\r\nexport function caretAfterDigits(formatted: string, digitsBefore: number): number {\r\n if (digitsBefore <= 0) return 0;\r\n let seen = 0;\r\n for (let i = 0; i < formatted.length; i++) {\r\n if (/\\d/.test(formatted[i]!)) seen++;\r\n if (seen === digitsBefore) return i + 1;\r\n }\r\n return formatted.length;\r\n}\r\n\r\n/** Digits appearing before `caret` in `text` — the position we must preserve across a reformat. */\r\nexport function digitsBeforeCaret(text: string, caret: number): number {\r\n return (text.slice(0, caret).match(/\\d/g) ?? []).length;\r\n}\r\n","/**\r\n * The 3×4 grid every phone has — shared between the pre-call dialer (`Dialpad`) and the in-call DTMF\r\n * panel (`CallScreen`). One types a number, the other sends tones, but it's the same physical pad\r\n * either way, so the layout lives once.\r\n */\r\nexport const KEYPAD_KEYS: ReadonlyArray<readonly [key: string, letters: string]> = [\r\n ['1', ''],\r\n ['2', 'ABC'],\r\n ['3', 'DEF'],\r\n ['4', 'GHI'],\r\n ['5', 'JKL'],\r\n ['6', 'MNO'],\r\n ['7', 'PQRS'],\r\n ['8', 'TUV'],\r\n ['9', 'WXYZ'],\r\n ['*', ''],\r\n ['0', '+'],\r\n ['#', ''],\r\n];\r\n","/**\r\n * Everything the softphone plays: the remote party, the inbound ring, the outbound ringback, the\r\n * end-of-call cue, and the keypad's key tones.\r\n *\r\n * Framework-free and lazy — nothing here touches `AudioContext`, `Audio` or `URL.createObjectURL`\r\n * at module scope, so importing it under SSR is safe (SPEC §10.2). The legacy code built the ringback\r\n * blob at module scope, which would have thrown on any server render.\r\n *\r\n * `core/` deliberately does not create audio elements: it hands the stream out and the UI attaches it\r\n * (see `CallEvent.RemoteStream`). This is the UI half of that contract.\r\n */\r\n\r\n/** 425 Hz — the EU/ES call-progress tone. Both the ring and the ringback are built on it. */\r\nconst TONE_HZ = 425;\r\n\r\n// ── Remote party ────────────────────────────────────────────────────────────\r\n\r\nexport interface RemoteAudio {\r\n attach(stream: MediaStream): void;\r\n detach(): void;\r\n destroy(): void;\r\n /**\r\n * Route the remote party to a specific output device, or `null` for the browser's own default\r\n * (SPEC §7 Phase 2 — device management). A no-op when the browser has no `setSinkId` (Safari, most\r\n * of Firefox — see `AudioDevices.canSelectOutput`), and swallows a rejection from an\r\n * already-unplugged device rather than throwing into a caller that has no useful recovery for it.\r\n */\r\n setOutputDevice(deviceId: string | null): Promise<void>;\r\n}\r\n\r\n/**\r\n * The `<audio>` element that plays the person on the other end.\r\n *\r\n * **Without this there is no call audio at all** — a `MediaStream` from `ontrack` is silent until it\r\n * is attached to a media element. The SDK exposed `call.remoteStream` and nothing consumed it.\r\n *\r\n * A media element rather than Web Audio, for the same reason as the ringback below: it follows the OS\r\n * default output device and survives Bluetooth A2DP↔HFP transitions.\r\n */\r\nexport function createRemoteAudio(): RemoteAudio {\r\n const el = document.createElement('audio');\r\n el.autoplay = true;\r\n // Off-screen but IN the document: some browsers will not play a detached element.\r\n el.style.display = 'none';\r\n document.body.appendChild(el);\r\n\r\n return {\r\n attach(stream) {\r\n el.srcObject = stream;\r\n // Rejects only under autoplay policy, which the dial/answer click already satisfied.\r\n void el.play().catch(() => {});\r\n },\r\n detach() {\r\n el.srcObject = null;\r\n },\r\n destroy() {\r\n el.srcObject = null;\r\n el.remove();\r\n },\r\n async setOutputDevice(deviceId) {\r\n if (typeof el.setSinkId !== 'function') return;\r\n try {\r\n // `''` is the spec's own way of saying \"the default device\" — the same meaning `null` carries\r\n // on this method's own signature, translated at this one boundary rather than asking every\r\n // caller to know the DOM's convention.\r\n await el.setSinkId(deviceId ?? '');\r\n } catch {\r\n // A device that vanished between selection and this call landing (unplugged, or a stale ID\r\n // from a previous session) — nothing useful to do beyond leaving the previous route in place.\r\n }\r\n },\r\n };\r\n}\r\n\r\n// ── Inbound ring ────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * ONE `AudioContext` for the page, created on demand and never closed.\r\n *\r\n * Ringing used to build a fresh context per call and close it on hangup. That produced three Firefox\r\n * warnings on every inbound call — *\"An AudioContext was prevented from starting automatically…\"* —\r\n * because an INVITE is not a user gesture, so the context, its oscillator and its `resume()` were all\r\n * created outside one. The ring still played (the user had clicked something earlier in the session),\r\n * but a console that cries wolf on a healthy path is how real warnings get ignored.\r\n *\r\n * Sharing it also avoids a limit worth knowing about: Chrome caps a page at ~6 live `AudioContext`s,\r\n * and `close()` is asynchronous — so a burst of short calls could reach it and leave the phone silent.\r\n *\r\n * Not closed on teardown deliberately: a suspended context costs nothing, and the next ring needs it\r\n * ready before any gesture is available.\r\n */\r\nlet shared: AudioContext | null = null;\r\n\r\nfunction sharedContext(): AudioContext | null {\r\n if (shared) return shared;\r\n const Ctor: typeof AudioContext | undefined =\r\n typeof AudioContext !== 'undefined'\r\n ? AudioContext\r\n : (globalThis as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\r\n if (!Ctor) return null;\r\n shared = new Ctor();\r\n return shared;\r\n}\r\n\r\n/**\r\n * Build the shared context **inside a user gesture**, so it starts `running` and nothing later has to\r\n * ask for permission it cannot get.\r\n *\r\n * Call from a click/keydown handler. Idempotent and safe to call when audio is already unlocked; on a\r\n * browser with no Web Audio it is a no-op.\r\n */\r\nexport function primeAudio(): void {\r\n const ctx = sharedContext();\r\n if (ctx && ctx.state === 'suspended') void ctx.resume?.().catch(() => {});\r\n}\r\n\r\n/** @internal — tests only: forget the shared context so each case starts clean. */\r\nexport function __resetSharedAudioForTests(): void {\r\n shared = null;\r\n}\r\n\r\nexport interface Tone {\r\n stop(): void;\r\n}\r\n\r\n/**\r\n * The inbound ring: a synthesised EU double-burst, looping until answered or gone.\r\n *\r\n * Web Audio rather than a file: there is no asset to ship or license, and during INBOUND ringing the\r\n * microphone is not open — so the tone is not subject to the OS \"communications\" ducking that would\r\n * silence a locally generated tone while a mic is live. (Outbound is the opposite case; see below.)\r\n *\r\n * **The look-ahead scheduler is not premature optimisation.** Scheduling each cycle at\r\n * `ctx.currentTime` from a chained `setTimeout` lands the rising ramp at or behind the live audio\r\n * clock on Chrome, which silently drops the cycle — the symptom is \"it rings once, then nothing\"\r\n * (Firefox tolerates it, so it looks fine in one browser). Instead the audio clock is kept ~0.5 s\r\n * filled, topped up every 150 ms, always scheduling on a future-dated accumulator.\r\n *\r\n * **Loud — the loudest tone this file plays, on purpose.** This first shipped at `LEVEL = 0.18`\r\n * (\"gentle — a ring should not startle\"), the exact same wrong instinct the end-of-call cue also\r\n * shipped with (see `playCallEndedTone`'s own comment): quiet-by-default was never examined against\r\n * what a ring is actually FOR. Every platform treats it as its own, separately loud category —\r\n * iOS/CallKit gives incoming calls a higher ceiling than a normal audio session, and RingCentral\r\n * exposes ringtone loudness as its own dedicated control, distinct from in-call volume — because a\r\n * missed call is the one failure mode you cannot recover from by just looking at the screen a moment\r\n * later. `LEVEL` here sits above even `playCallEndedTone`'s own boosted level for the same reason:\r\n * ringing has to compete with a genuinely noisy room in a way a goodbye click, glanced at on screen,\r\n * does not. The attack (`RAMP`) stays soft, unlike the goodbye click's sharp one — this repeats every\r\n * 3 seconds for as long as the phone rings, and a percussive click that many times in a row reads as\r\n * harsh rather than urgent; loudness carries the urgency here, not the envelope shape.\r\n */\r\nexport function playRingtone(): Tone {\r\n const ctx = sharedContext();\r\n if (!ctx) return { stop() {} };\r\n\r\n const gain = ctx.createGain();\r\n gain.gain.value = 0;\r\n gain.connect(ctx.destination);\r\n\r\n const osc = ctx.createOscillator();\r\n osc.type = 'sine';\r\n osc.frequency.value = TONE_HZ;\r\n osc.connect(gain);\r\n osc.start();\r\n\r\n const LEVEL = 0.8; // louder than the end-of-call cue (0.55) — has to cut through a noisy room\r\n const RAMP = 0.02; // short fades, or the bursts click — soft on purpose, see this function's comment\r\n\r\n const burst = (at: number, dur: number): void => {\r\n gain.gain.setValueAtTime(0, at);\r\n gain.gain.linearRampToValueAtTime(LEVEL, at + RAMP);\r\n gain.gain.setValueAtTime(LEVEL, at + dur - RAMP);\r\n gain.gain.linearRampToValueAtTime(0, at + dur);\r\n };\r\n\r\n /** One EU cadence: two 0.4 s rings 0.2 s apart, then ~2 s of silence. 3 s total. */\r\n const scheduleCycle = (at: number): number => {\r\n burst(at, 0.4);\r\n burst(at + 0.6, 0.4);\r\n return 3.0;\r\n };\r\n\r\n const LOOKAHEAD = 0.5;\r\n const TICK_MS = 150;\r\n const LEAD = 0.08; // so the first cycle is never scheduled at exactly \"now\"\r\n\r\n let stopped = false;\r\n let timer: ReturnType<typeof setInterval> | null = null;\r\n let nextAt = 0;\r\n\r\n const pump = (): void => {\r\n while (nextAt < ctx.currentTime + LOOKAHEAD) nextAt += scheduleCycle(nextAt);\r\n };\r\n\r\n // Resume first: a fresh context may be suspended by autoplay policy. By the time a call rings the\r\n // user has interacted with the softphone, so this succeeds; if not, it degrades to silence.\r\n void Promise.resolve(ctx.resume?.())\r\n .catch(() => {})\r\n .finally(() => {\r\n if (stopped) return;\r\n nextAt = ctx.currentTime + LEAD;\r\n pump();\r\n timer = setInterval(pump, TICK_MS);\r\n });\r\n\r\n return {\r\n stop() {\r\n stopped = true;\r\n if (timer) clearInterval(timer);\r\n try {\r\n osc.stop();\r\n } catch {\r\n /* already stopped */\r\n }\r\n try {\r\n gain.disconnect();\r\n } catch {\r\n /* ignore */\r\n }\r\n // The context is SHARED and outlives the ring — see `sharedContext`. Closing it here is what\r\n // forced a new one per call, and a context built outside a user gesture is what Firefox warns\r\n // about. Only the nodes are disposable.\r\n },\r\n };\r\n}\r\n\r\n// ── Call ended ──────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * The \"call has ended\" cue: ONE short 425 Hz beep, fired once a LIVE call is hung up — by either\r\n * side. Without it the call screen just disappears, which reads as a dropped connection rather than\r\n * an ordinary goodbye; a real phone always gives you SOMETHING before it goes back to the dial tone.\r\n *\r\n * A single beep, not a repeating pattern — this is a device-level confirmation click, not one of the\r\n * network's own call-progress tones (the ring and ringback ARE those, which is why they alone match\r\n * the ETSI/Telefónica cadence: 425 Hz, 1.5 s on, 3 s off). Spain has no standardised \"call ended\"\r\n * network tone to replicate; the closest real-world precedent is each platform's own end-of-call\r\n * click — iOS plays three short 425 Hz bursts, Android a single soft one. A single beep is what\r\n * Spanish users actually expect here, so that is what this plays, kept on the same 425 Hz the rest of\r\n * this file already uses for consistency.\r\n *\r\n * **Loud and sharp, NOT gentle** — this first shipped at the ringtone's own `LEVEL`/`RAMP`, on the\r\n * unexamined assumption that \"quiet and soft\" was a safe default throughout this file. It is the\r\n * wrong instinct here: a ring is heard from across a room and must not startle, but a goodbye click\r\n * is a confirmation the user is already looking at their screen for and expects to be unmistakable —\r\n * \"you notice that sound immediately\" was the actual bar. `LEVEL` now sits above even the ringback's\r\n * own 0.5 amp, and `RAMP` is a fraction of the ringtone's — an audible, percussive click rather than\r\n * a fade-in a quiet room can still miss.\r\n *\r\n * Web Audio, like the ringtone, not a media element like the ringback: this fires as the call is\r\n * already tearing down, so — unlike the ringback — there is no still-open microphone to route around\r\n * a Bluetooth profile switch for. A fire-and-forget cue on the shared context is simpler than a WAV\r\n * blob for something this short.\r\n *\r\n * Deliberately NOT looping and NOT cancellable — one beep and it is done on its own. Nothing in\r\n * `useCallAudio` needs to stop this mid-flight the way the ring/ringback do, so it does not return a\r\n * `Tone`.\r\n */\r\nexport function playCallEndedTone(): void {\r\n const ctx = sharedContext();\r\n if (!ctx) return;\r\n\r\n const gain = ctx.createGain();\r\n gain.gain.value = 0;\r\n gain.connect(ctx.destination);\r\n\r\n const osc = ctx.createOscillator();\r\n osc.type = 'sine';\r\n osc.frequency.value = TONE_HZ;\r\n osc.connect(gain);\r\n osc.start();\r\n\r\n const LEVEL = 0.55; // louder than the ringback (0.5) — a deliberate goodbye click, not a background tone\r\n const RAMP = 0.008; // sharp, percussive attack — long enough not to click, short enough to feel instant\r\n const BEEP = 0.25; // long enough to register as a deliberate signal, short enough to stay \"a beep\"\r\n\r\n void Promise.resolve(ctx.resume?.())\r\n .catch(() => {})\r\n .finally(() => {\r\n const at = ctx.currentTime + 0.02;\r\n gain.gain.setValueAtTime(0, at);\r\n gain.gain.linearRampToValueAtTime(LEVEL, at + RAMP);\r\n gain.gain.setValueAtTime(LEVEL, at + BEEP - RAMP);\r\n gain.gain.linearRampToValueAtTime(0, at + BEEP);\r\n\r\n const totalMs = (at + BEEP - ctx.currentTime) * 1000;\r\n setTimeout(() => {\r\n try {\r\n osc.stop();\r\n } catch {\r\n /* already stopped */\r\n }\r\n try {\r\n gain.disconnect();\r\n } catch {\r\n /* ignore */\r\n }\r\n }, totalMs);\r\n });\r\n}\r\n\r\n// ── Key tones ───────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * The keypad's own sound: each key is the SUM of one row tone and one column tone (ITU-T Q.23 — the\r\n * same pairs every phone on earth uses). The frequencies, not a recording, so there is nothing to\r\n * ship or license; Zadarma's own widget bundles proprietary `.wav` tones that are not ours to reuse.\r\n *\r\n * Rows are listed as the keypad is drawn (1-2-3 / 4-5-6 / 7-8-9 / *-0-#), so a key's position IS its\r\n * pair. The fourth column (A–D, 1633 Hz) is not on a phone keypad and is deliberately absent.\r\n */\r\nconst DTMF_ROWS_HZ = [697, 770, 852, 941] as const;\r\nconst DTMF_COLS_HZ = [1209, 1336, 1477] as const;\r\nconst DTMF_LAYOUT = ['123', '456', '789', '*0#'] as const;\r\n\r\n/** The two frequencies for a keypad key, or `null` for anything that is not one of the 12 keys. */\r\nexport function dtmfFrequencies(key: string): readonly [number, number] | null {\r\n if (key.length !== 1) return null; // `indexOf('')` is 0 — \"no key\" must not read as the first key\r\n for (let row = 0; row < DTMF_LAYOUT.length; row++) {\r\n const col = DTMF_LAYOUT[row]!.indexOf(key);\r\n if (col !== -1) return [DTMF_ROWS_HZ[row]!, DTMF_COLS_HZ[col]!];\r\n }\r\n return null;\r\n}\r\n\r\n/**\r\n * A short local tone for a keypad press — what every phone plays so you KNOW the key registered.\r\n *\r\n * Without it the keypad is silent, and mid-call that costs more than it looks: DTMF goes out as a SIP\r\n * INFO message, which the far end acts on but which the local user never hears, so an agent keying an\r\n * IVR menu option has no feedback at all that the digit went anywhere.\r\n *\r\n * Fire-and-forget on the shared context, like `playCallEndedTone` — nothing here needs to be stopped\r\n * early. Presses overlap rather than queue, as on a real phone: a fast run of digits each gets its\r\n * own tone instead of a backlog that plays on after the user has stopped typing.\r\n *\r\n * Plays on the page's default output, not the device chosen in Dispositivos — the same as the\r\n * ring and the end-of-call cue (only the remote party's `<audio>` element follows that selection).\r\n *\r\n * `LEVEL` is the gain node's own peak; two unit sines sum to 2, so the signal peaks at 0.4 of full\r\n * scale — firmly audible, a notch under the end-of-call cue's 0.55, and not tiring across the ten or\r\n * more presses of a phone number. It is one constant: retune it by ear.\r\n */\r\nexport function playKeyTone(key: string): void {\r\n const hz = dtmfFrequencies(key);\r\n if (!hz) return;\r\n const ctx = sharedContext();\r\n if (!ctx) return;\r\n\r\n const LEVEL = 0.2;\r\n const RAMP = 0.006; // long enough not to click, short enough to feel instant\r\n const DURATION = 0.12; // the 100 ms JsSIP puts on the wire, plus the fades\r\n const LEAD = 0.01; // a ramp at or behind the live clock is dropped on Chrome — see `playRingtone`\r\n\r\n const gain = ctx.createGain();\r\n gain.gain.value = 0;\r\n gain.connect(ctx.destination);\r\n\r\n const oscillators = hz.map((freq) => {\r\n const osc = ctx.createOscillator();\r\n osc.type = 'sine';\r\n osc.frequency.value = freq;\r\n osc.connect(gain);\r\n osc.start();\r\n return osc;\r\n });\r\n\r\n const fire = (): void => {\r\n const at = ctx.currentTime + LEAD;\r\n gain.gain.setValueAtTime(0, at);\r\n gain.gain.linearRampToValueAtTime(LEVEL, at + RAMP);\r\n gain.gain.setValueAtTime(LEVEL, at + DURATION - RAMP);\r\n gain.gain.linearRampToValueAtTime(0, at + DURATION);\r\n for (const osc of oscillators) osc.stop(at + DURATION);\r\n // The nodes are disposable; the context is shared and outlives them (see `sharedContext`).\r\n oscillators[0]!.onended = () => gain.disconnect();\r\n };\r\n\r\n // Already unlocked (the first gesture on the page primes it — see `primeAudio`): play NOW, with no\r\n // promise hop in front of a key press. Otherwise resume first — this click is itself a gesture.\r\n if (ctx.state === 'running') fire();\r\n else void Promise.resolve(ctx.resume?.()).catch(() => {}).finally(fire);\r\n}\r\n\r\n// ── Outbound ringback ───────────────────────────────────────────────────────\r\n\r\nlet ringbackUrl: string | null = null;\r\n\r\n/**\r\n * The EU/ES ringback loop as a WAV blob: 425 Hz, 1.5 s tone, 3 s silence.\r\n *\r\n * **Stereo 48 kHz 16-bit PCM, deliberately.** A mono 8 kHz source went silent on a device configured\r\n * for a single channel — Chrome's mono-source→mono-endpoint path drops it. Stereo plays directly on\r\n * stereo devices and downmixes cleanly on mono ones.\r\n *\r\n * A Blob URL rather than a `data:` URI: Chrome treats a Blob URL as a real media resource, while\r\n * `data:` URIs stall when looped.\r\n */\r\nfunction ringbackSource(): string {\r\n if (ringbackUrl) return ringbackUrl;\r\n\r\n const sampleRate = 48_000;\r\n const channels = 2;\r\n const bytesPerSample = 2;\r\n const amp = 0.5;\r\n const toneSec = 1.5;\r\n const silenceSec = 3;\r\n const totalFrames = Math.round((toneSec + silenceSec) * sampleRate);\r\n const toneFrames = Math.round(toneSec * sampleRate);\r\n const ramp = Math.round(0.02 * sampleRate); // 20 ms fades, or it clicks\r\n\r\n const blockAlign = channels * bytesPerSample;\r\n const dataSize = totalFrames * blockAlign;\r\n const buffer = new ArrayBuffer(44 + dataSize);\r\n const view = new DataView(buffer);\r\n const str = (off: number, s: string): void => {\r\n for (let i = 0; i < s.length; i++) view.setUint8(off + i, s.charCodeAt(i));\r\n };\r\n\r\n str(0, 'RIFF');\r\n view.setUint32(4, 36 + dataSize, true);\r\n str(8, 'WAVE');\r\n str(12, 'fmt ');\r\n view.setUint32(16, 16, true); // PCM chunk size\r\n view.setUint16(20, 1, true); // PCM\r\n view.setUint16(22, channels, true);\r\n view.setUint32(24, sampleRate, true);\r\n view.setUint32(28, sampleRate * blockAlign, true); // byte rate\r\n view.setUint16(32, blockAlign, true);\r\n view.setUint16(34, bytesPerSample * 8, true);\r\n str(36, 'data');\r\n view.setUint32(40, dataSize, true);\r\n\r\n for (let i = 0; i < totalFrames; i++) {\r\n let sample = 0;\r\n if (i < toneFrames) {\r\n let env = 1;\r\n if (i < ramp) env = i / ramp;\r\n else if (i > toneFrames - ramp) env = Math.max(0, (toneFrames - i) / ramp);\r\n sample = Math.sin(2 * Math.PI * TONE_HZ * (i / sampleRate)) * amp * env;\r\n }\r\n const s16 = Math.round(sample * 32767);\r\n const off = 44 + i * blockAlign;\r\n for (let c = 0; c < channels; c++) view.setInt16(off + c * bytesPerSample, s16, true);\r\n }\r\n\r\n ringbackUrl = URL.createObjectURL(new Blob([buffer], { type: 'audio/wav' }));\r\n return ringbackUrl;\r\n}\r\n\r\n/**\r\n * Outbound ringback, played the way production softphones do it: a looping `HTMLAudioElement`, NOT\r\n * the Web Audio API.\r\n *\r\n * A media element follows the OS default output device when it changes, and Chrome re-routes it\r\n * across Bluetooth A2DP↔HFP transitions. An `AudioContext` binds to whichever endpoint existed when\r\n * it was created and gets stranded on a stale one after the headset cycles profiles — which made a\r\n * Web Audio ringback miss intermittently on back-to-back calls.\r\n *\r\n * A media element rather than Web Audio for a second reason too: JsSIP opens the real microphone when\r\n * an outbound call is placed, so on Bluetooth the headset switches to HFP as the ringback starts. An\r\n * element follows the OS default endpoint across that switch; a Web Audio graph would stay bound to\r\n * the one that existed when it was built.\r\n */\r\nexport function playRingback(): Tone {\r\n const el = document.createElement('audio');\r\n el.src = ringbackSource();\r\n el.loop = true;\r\n el.style.display = 'none';\r\n document.body.appendChild(el);\r\n void el.play().catch(() => {});\r\n\r\n return {\r\n stop() {\r\n el.pause();\r\n el.remove();\r\n },\r\n };\r\n}\r\n","import { useLayoutEffect, useRef, useState } from 'react';\r\nimport { Phone, Delete } from 'lucide-react';\r\nimport { useSoftphone, useSoftphoneState } from '../../react/index.js';\r\nimport { CountryPicker } from '../dialing/CountryPicker.js';\r\nimport { DEFAULT_COUNTRY, toE164 } from '../dialing/countries.js';\r\nimport { caretAfterDigits, digitsBeforeCaret, useNumberFormatter } from '../dialing/format-number.js';\r\nimport { KEYPAD_KEYS } from '../dialing/keys.js';\r\nimport { playKeyTone } from '../audio/audio.js';\r\n\r\n/**\r\n * `*` and `#` render here but are **not dialable**: `toE164` keeps digits only, so a number carrying\r\n * them would lose them silently at dial time and the display would have lied.\r\n *\r\n * The CRM has the same keys and the same rule (`IdleView.setNational` runs `replace(/\\D/g,'')`, so a\r\n * `*` press is swallowed before it is ever shown). This states it instead of leaving it to a regex\r\n * three functions away: they are DTMF tones for an ACTIVE call (CallScreen's own keypad), not part of\r\n * a number.\r\n */\r\nconst NOT_DIALABLE = new Set(['*', '#']);\r\n\r\n/**\r\n * The keypad view (legacy IdleView). Strings are Spanish (SPEC §2.4).\r\n *\r\n * Layout is three flex rows — head (fixed) / keypad (flex:1) / foot (fixed) — so the keypad absorbs\r\n * whatever height is left. Sizing keys by aspect-ratio instead would overflow the shell and push the\r\n * call button under the tab bar.\r\n */\r\nexport interface DialpadProps {\r\n /** The outcome of the last attempt — \"Sin respuesta\", \"Llamada rechazada\". Non-fatal only. */\r\n readonly outcome?: { readonly code: string; readonly text: string } | null;\r\n /** Called on any action that supersedes that outcome: a digit, a backspace, a dial. */\r\n readonly onIntent?: () => void;\r\n /**\r\n * Play a key tone when a digit is pressed. **On by default**; `SoftphoneWidget` passes its own\r\n * `sounds` flag, so a host that silences the widget silences this too.\r\n */\r\n readonly keyTones?: boolean;\r\n}\r\n\r\nexport function Dialpad({ outcome = null, onIntent, keyTones = true }: DialpadProps = {}) {\r\n const softphone = useSoftphone();\r\n const state = useSoftphoneState();\r\n // The NATIONAL number, as the CRM's IdleView held it: the prefix lives in the chip, so the user\r\n // types what they would read off a business card. `toE164` composes the two at dial time.\r\n //\r\n // State holds RAW DIGITS; the input displays them GROUPED. Keeping the raw digits as the source of\r\n // truth means the separators are pure presentation — nothing downstream ever has to un-format, and\r\n // `toE164` sees exactly what was typed.\r\n const [value, setValue] = useState('');\r\n const [country, setCountry] = useState(DEFAULT_COUNTRY);\r\n const format = useNumberFormatter();\r\n const inputRef = useRef<HTMLInputElement>(null);\r\n const caretRef = useRef<number | null>(null);\r\n\r\n const display = format(country, value);\r\n const target = toE164(country, value);\r\n const canCall = state === 'online' && target.length > 1;\r\n\r\n // Restore the caret AFTER React paints the regrouped string, or inserting a digit mid-number would\r\n // throw it to the end and the next keystroke would land in the wrong place. Layout effect, not\r\n // effect: the caret must not be visibly wrong for a frame.\r\n useLayoutEffect(() => {\r\n const caret = caretRef.current;\r\n if (caret === null || !inputRef.current) return;\r\n caretRef.current = null;\r\n const pos = caretAfterDigits(display, caret);\r\n inputRef.current.setSelectionRange(pos, pos);\r\n }, [display]);\r\n\r\n const append = (key: string) => {\r\n onIntent?.();\r\n setValue((v) => v + key);\r\n // Only for a key that did something: `*` and `#` are inert here (see `NOT_DIALABLE`) and never\r\n // reach this, because a tone on a key that does nothing would tell the user it worked. Backspace\r\n // is silent too — it is not a keypad key and has no DTMF tone.\r\n if (keyTones) playKeyTone(key);\r\n };\r\n const backspace = () => {\r\n onIntent?.();\r\n setValue((v) => v.slice(0, -1));\r\n };\r\n const call = () => {\r\n if (!canCall) return;\r\n onIntent?.();\r\n void softphone.call(target);\r\n };\r\n\r\n return (\r\n <div className=\"cv-view\">\r\n {/*\r\n The prefix sits on its OWN row, above the number — as the CRM's IdleView always did.\r\n\r\n Sharing one line reads fine at 340px and starves the number at 310: the chip and the erase\r\n button each take a fixed ~36-70px out of the middle, so \"Número\" gets whatever is left, and a\r\n formatted international number (`+34 600 11 12 22`) is exactly when there is least of it. The\r\n number is the content; the prefix is a setting you touch once a week. Give the content the\r\n full width.\r\n */}\r\n <div className=\"cv-dial-prefix\">\r\n <CountryPicker value={country} onChange={setCountry} />\r\n </div>\r\n\r\n <div className=\"cv-dial-head\">\r\n {/* Mirrors the erase button so the number stays optically centred. */}\r\n <span className=\"cv-dial-side\" aria-hidden />\r\n <input\r\n ref={inputRef}\r\n className=\"cv-display\"\r\n value={display}\r\n onChange={(e) => {\r\n onIntent?.();\r\n // Remember the caret in DIGITS before reformatting — see `caretAfterDigits`.\r\n caretRef.current = digitsBeforeCaret(e.target.value, e.target.selectionStart ?? 0);\r\n // Digits and a leading `+` only, matching what `toE164` will actually honour. This used\r\n // to accept `*#`, so a typed `*` displayed fine and then vanished at dial time.\r\n setValue(e.target.value.replace(/[^\\d+]/g, ''));\r\n }}\r\n onKeyDown={(e) => e.key === 'Enter' && call()}\r\n placeholder=\"Número\"\r\n aria-label=\"Número a marcar\"\r\n inputMode=\"tel\"\r\n />\r\n <button\r\n type=\"button\"\r\n className=\"cv-dial-side\"\r\n data-hidden={value.length === 0}\r\n onClick={backspace}\r\n aria-label=\"Borrar\"\r\n >\r\n <Delete size={19} />\r\n </button>\r\n </div>\r\n\r\n {/*\r\n What happened to the last attempt, under the number it was dialled from. Muted and inline\r\n rather than a banner: the phone still works, so nothing here should block or alarm.\r\n\r\n `role=\"status\"` and not `alert` — an alert interrupts a screen reader mid-sentence, and\r\n \"Sin respuesta\" is not worth interrupting for. Always rendered so the region exists before the\r\n text arrives; an aria-live region inserted at the same moment as its content is not announced.\r\n */}\r\n <p className=\"cv-dial-outcome\" role=\"status\" part=\"error\" data-shown={outcome !== null}>\r\n {outcome?.text ?? ''}\r\n </p>\r\n\r\n <div className=\"cv-keypad\">\r\n {KEYPAD_KEYS.map(([key, letters]) => {\r\n const dialable = !NOT_DIALABLE.has(key);\r\n return (\r\n <button\r\n key={key}\r\n type=\"button\"\r\n className=\"cv-key\"\r\n data-dialable={dialable}\r\n onClick={() => dialable && append(key)}\r\n aria-disabled={!dialable}\r\n // Not `disabled`: the key must stay in the grid and stay legible. It does nothing here\r\n // because `*`/`#` are DTMF for a live call, not digits in a number.\r\n title={dialable ? undefined : 'Solo disponible durante una llamada'}\r\n >\r\n <b>{key}</b>\r\n {letters ? <small>{letters}</small> : null}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n\r\n <div className=\"cv-dial-foot\">\r\n <button\r\n type=\"button\"\r\n className=\"cv-round cv-round--answer\"\r\n onClick={call}\r\n disabled={!canCall}\r\n aria-label=\"Llamar\"\r\n part=\"call-button\"\r\n >\r\n <Phone size={26} />\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","/** Small presentational helpers. Pure — no React, no DOM. */\r\n\r\n/** `93` → `1:33`, `3725` → `1:02:05`. */\r\nexport function formatDuration(totalSeconds: number): string {\r\n const s = Math.max(0, Math.floor(totalSeconds));\r\n const hh = Math.floor(s / 3600);\r\n const mm = Math.floor((s % 3600) / 60);\r\n const ss = s % 60;\r\n const pad = (n: number) => String(n).padStart(2, '0');\r\n return hh > 0 ? `${hh}:${pad(mm)}:${pad(ss)}` : `${mm}:${pad(ss)}`;\r\n}\r\n\r\n/** `\"Ana García\"` → `\"AG\"`, `\"+34600111222\"` → `\"#\"`. */\r\nexport function initials(name: string | null | undefined): string {\r\n if (!name) return '#';\r\n const words = name.trim().split(/\\s+/).filter(Boolean);\r\n if (words.length === 0 || /^\\+?\\d/.test(words[0]!)) return '#';\r\n return words\r\n .slice(0, 2)\r\n .map((w) => w[0]!.toUpperCase())\r\n .join('');\r\n}\r\n\r\n/** Seconds elapsed since a start Date, as a live-timer-friendly integer. */\r\nexport function elapsedSeconds(since: Date | null, now: number): number {\r\n if (!since) return 0;\r\n return Math.floor((now - since.getTime()) / 1000);\r\n}\r\n\r\n/**\r\n * A notice's age, coarse and relative — `\"justo ahora\"`, `\"hace 1 min\"`, `\"hace 2 h\"`. Deliberately\r\n * never seconds: a notice worth keeping this long (no auto-dismiss — spec §5.5) is never worth timing\r\n * to the second, and a number that changes every tick reads as more urgent than the notice actually is.\r\n */\r\nexport function formatAge(totalSeconds: number): string {\r\n const s = Math.max(0, Math.floor(totalSeconds));\r\n if (s < 60) return 'justo ahora';\r\n const mm = Math.floor(s / 60);\r\n if (mm < 60) return `hace ${mm} min`;\r\n const hh = Math.floor(mm / 60);\r\n return `hace ${hh} h`;\r\n}\r\n","import type { SoftphoneErrorCode } from '../../core/errors.js';\r\n\r\n/**\r\n * What the USER reads when something fails. Spanish, because the widget is.\r\n *\r\n * **Deliberately not in the catalogue.** `ERROR_CATALOGUE.message` is documented as *\"what went\r\n * wrong, for a developer\"* and lands on `Error.message` — the string a host logs, and the one Sentry\r\n * groups by. Translating it would hand an English-speaking partner integrator Spanish stack traces,\r\n * and would put a locale into a `core/` that currently has no user-facing string in it at all.\r\n *\r\n * So the split is: the catalogue explains the failure to whoever is debugging it, and this explains\r\n * it to whoever is trying to make a call. They are different audiences and different sentences.\r\n *\r\n * `Record<SoftphoneErrorCode, ErrorText>` is what keeps them in step: a missing code will not\r\n * compile, and neither will one that no longer exists. Annotated rather than `as const satisfies`\r\n * deliberately — the literal types buy nothing, and they make `body` unreachable on the entries that\r\n * omit it, which is every call outcome.\r\n */\r\nexport interface ErrorText {\r\n /** The headline. For a non-fatal outcome this is the whole message — \"No contestaron\". */\r\n readonly title: string;\r\n /** One line of what to do. Fatal errors always have one; a call outcome rarely needs it. */\r\n readonly body?: string;\r\n}\r\n\r\nexport const ERROR_TEXT: Record<SoftphoneErrorCode, ErrorText> = {\r\n // ── Engine lifecycle ────────────────────────────────────────────────────────\r\n // Integrator mistakes rather than user-facing failures, but they must still read as something\r\n // rather than as a blank panel if one ever reaches the UI.\r\n 'engine/duplicate-instance': {\r\n title: 'Teléfono duplicado',\r\n body: 'Hay otro teléfono abierto en esta página. Cierra uno y vuelve a cargar.',\r\n },\r\n 'engine/not-started': { title: 'El teléfono aún no está listo' },\r\n 'engine/destroyed': {\r\n title: 'Teléfono cerrado',\r\n body: 'Vuelve a cargar la página para usarlo de nuevo.',\r\n },\r\n\r\n // ── Auth ────────────────────────────────────────────────────────────────────\r\n // Never \"token\": the user has no idea what one is. What they can act on is the session.\r\n 'auth/token-fetch-failed': {\r\n title: 'Sin conexión con el servidor',\r\n body: 'No se ha podido activar el teléfono. Reinténtalo en unos segundos.',\r\n },\r\n 'auth/token-rejected': {\r\n title: 'Sesión caducada',\r\n body: 'Vuelve a iniciar sesión para poder llamar.',\r\n },\r\n\r\n // ── Media ───────────────────────────────────────────────────────────────────\r\n // Verbatim from MicPermissionGate, which already says these well and says them first.\r\n //\r\n // NEVER ACTUALLY SHOWN via this table — these four codes (through `media/playback-blocked`, below)\r\n // are never raised as a `SoftphoneError` at all. See the fuller comment on each in `core/errors.ts`\r\n // for why. Copy kept here anyway so the catalogue and this file stay the same shape as every other\r\n // code — `error-text.test.ts` would fail the build the moment they drifted.\r\n 'media/permission-denied': {\r\n title: 'Micrófono bloqueado',\r\n body: 'Permítelo en tu navegador para poder llamar.',\r\n },\r\n 'media/no-input-device': {\r\n title: 'Sin micrófono',\r\n body: 'Conecta un micrófono y vuelve a intentarlo.',\r\n },\r\n 'media/webrtc-unsupported': {\r\n title: 'Llamadas no disponibles',\r\n body: 'Este navegador no admite llamadas. Prueba con Chrome, Edge o Firefox.',\r\n },\r\n 'media/playback-blocked': { title: 'Toca la pantalla para activar el sonido' },\r\n\r\n // ── Network / signalling ────────────────────────────────────────────────────\r\n // \"Centralita\" rather than \"SIP\" or \"registro\": the user knows what a phone system is.\r\n 'net/registration-failed': {\r\n title: 'No se pudo conectar',\r\n body: 'No hemos podido conectar con la centralita. Reintenta en unos segundos.',\r\n },\r\n 'net/transport-failed': {\r\n title: 'Conexión perdida',\r\n body: 'Se ha perdido la conexión con la centralita.',\r\n },\r\n // NEVER ACTUALLY SHOWN either — CallScreen's own \"Reconectando…\" already covers this, off the\r\n // call's `reconnecting` state rather than this channel. See the comment in `core/errors.ts`.\r\n 'net/ice-failed': { title: 'Recuperando el audio…' },\r\n\r\n // ── Call ────────────────────────────────────────────────────────────────────\r\n /*\r\n THE VOICE RULE FOR THIS BLOCK: say what HAPPENED, not what it is called.\r\n\r\n These were status labels — \"Llamada perdida\", \"Llamada rechazada\", \"Sin respuesta\". Each is a\r\n name for a category rather than an account of an event, which is why they read as a database enum\r\n someone forgot to translate into human. Worse, a label hides the ACTOR: \"Llamada rechazada\" never\r\n says who rejected what, so the user reading it after declining a call and the user reading it\r\n after being declined see the same three words.\r\n\r\n So each one is a short sentence about what the other person, or the phone, did — the form\r\n `call/busy` already had, and the reason it was the only one here that read clearly.\r\n\r\n Impersonal third-person plural (\"contestaron\", \"colgaron\") throughout: the user does not know who\r\n is at the other end, and it is what Spanish uses when the subject is unknown. Mixing it with the\r\n singular across neighbouring lines reads as carelessness.\r\n\r\n LENGTH IS A HARD CONSTRAINT, not a preference. `.cv-dial-outcome` is one line at a fixed\r\n `1.15rem`, and the keypad below it is `flex: 1` — a title that wraps resizes every key and shifts\r\n the grid under a finger already reaching for it. `error-text.test.ts` caps this at 48 characters.\r\n */\r\n 'call/not-answerable': { title: 'Esa llamada ya ha terminado' },\r\n /*\r\n NOT \"Comunicando\", which is what this said and what sent us looking. SIP 486 is both \"the line is\r\n engaged\" AND what almost every endpoint sends when a person presses decline — including our own\r\n `reject()`. One code, two events, no way to tell them apart, so the copy has to hold both rather\r\n than assert the less likely one. `call/rejected` can be definite: an endpoint sending 603 Decline\r\n means exactly that.\r\n */\r\n 'call/busy': { title: 'No contestaron o la línea estaba ocupada' },\r\n 'call/no-answer': { title: 'No contestaron' },\r\n 'call/rejected': { title: 'No aceptaron tu llamada' },\r\n /*\r\n The legacy CRM said \"La persona que llamaba colgó antes de que pudieras contestar.\" — the right\r\n fact, at three times the width of the line that has to hold it. This keeps the fact and drops the\r\n words: the user needs to know the call was FOR them and that nobody is waiting on the line.\r\n \"Llamada perdida\" alone tested badly for exactly the label reason above — it names the category\r\n without saying anyone rang.\r\n */\r\n 'call/missed': { title: 'Colgaron antes de que pudieras contestar' },\r\n // \"No se pudo completar la llamada\" was our own \"something went wrong\": true of every failure and\r\n // useful for none. The number is what the user can actually act on.\r\n 'call/failed': { title: 'No se pudo conectar con ese número' },\r\n // The load-bearing half is the SECOND sentence: the original call is still up, and a user who\r\n // thinks they dropped it will hang up on a client to \"fix\" it.\r\n 'call/transfer-failed': { title: 'No se pudo transferir. Sigues en la llamada' },\r\n 'call/unsupported': { title: 'Esta función no está disponible' },\r\n\r\n // ── Provider ────────────────────────────────────────────────────────────────\r\n 'provider/provision-failed': {\r\n title: 'No se pudo activar el teléfono',\r\n body: 'Si el problema continúa, contacta con soporte.',\r\n },\r\n};\r\n","import { useEffect, useState } from 'react';\r\n\r\n/**\r\n * `Date.now()`, updated every `intervalMs` while `enabled`. For the live call timer.\r\n *\r\n * Kept as its own hook so only the timer text re-renders on each tick, not the whole widget.\r\n */\r\nexport function useTicker(enabled: boolean, intervalMs = 1000): number {\r\n const [now, setNow] = useState(() => Date.now());\r\n useEffect(() => {\r\n if (!enabled) return;\r\n setNow(Date.now());\r\n const id = setInterval(() => setNow(Date.now()), intervalMs);\r\n return () => clearInterval(id);\r\n }, [enabled, intervalMs]);\r\n return now;\r\n}\r\n","import { useEffect } from 'react';\r\nimport { Headphones, Mic } from 'lucide-react';\r\nimport { useDevices, useSoftphone } from '../../react/index.js';\r\nimport type { ContactActionIcon } from '../types.js';\r\n\r\n/**\r\n * A device's own label, or a numbered fallback.\r\n *\r\n * `enumerateDevices()` returns an EMPTY `label` until the microphone has been granted at least once\r\n * (a browser privacy measure — see `AudioDevices.refresh`'s own comment) — a blank row in a picker\r\n * reads as broken, not as \"permission pending\", so this names it something a user can still pick.\r\n */\r\nfunction deviceLabel(device: MediaDeviceInfo, index: number, kind: 'input' | 'output'): string {\r\n if (device.label) return device.label;\r\n return kind === 'input' ? `Micrófono ${index + 1}` : `Altavoz ${index + 1}`;\r\n}\r\n\r\n/** `''` is the DOM's own spelling of \"system default\" on a `<select>`; `null` is this SDK's. */\r\nconst DEFAULT_OPTION = '';\r\n\r\nfunction DevicePicker({\r\n icon: Icon,\r\n label,\r\n kind,\r\n options,\r\n value,\r\n onChange,\r\n emptyText,\r\n}: Readonly<{\r\n icon: ContactActionIcon;\r\n label: string;\r\n kind: 'input' | 'output';\r\n options: readonly MediaDeviceInfo[];\r\n value: string | null;\r\n onChange: (deviceId: string | null) => void;\r\n emptyText: string;\r\n}>) {\r\n return (\r\n <div className=\"cv-settings-row\">\r\n <span className=\"cv-settings-row-icon\" aria-hidden>\r\n <Icon size={16} />\r\n </span>\r\n <span className=\"cv-settings-row-text\">\r\n <span className=\"cv-settings-row-label\" id={`cv-settings-label-${kind}`}>\r\n {label}\r\n </span>\r\n {options.length > 0 ? (\r\n <select\r\n className=\"cv-settings-select\"\r\n aria-labelledby={`cv-settings-label-${kind}`}\r\n value={value ?? DEFAULT_OPTION}\r\n onChange={(e) => onChange(e.target.value === DEFAULT_OPTION ? null : e.target.value)}\r\n >\r\n <option value={DEFAULT_OPTION}>Predeterminado del sistema</option>\r\n {options.map((d, i) => (\r\n <option key={d.deviceId} value={d.deviceId}>\r\n {deviceLabel(d, i, kind)}\r\n </option>\r\n ))}\r\n </select>\r\n ) : (\r\n <span className=\"cv-settings-empty\">{emptyText}</span>\r\n )}\r\n </span>\r\n </div>\r\n );\r\n}\r\n\r\n/**\r\n * Both device pickers (microphone + speaker), self-contained: reads `useDevices()` itself and\r\n * re-scans on mount. Shared between the Ajustes tab and the in-call quick-switch popover\r\n * (`CallScreen`) so the two surfaces show the same devices under the same labels and can't drift\r\n * apart — there is exactly one place that knows what a device row looks like.\r\n */\r\nexport function DevicePickers() {\r\n const softphone = useSoftphone();\r\n const devices = useDevices();\r\n\r\n // Labels enumerate blank until the microphone has been granted at least once, and a permission\r\n // grant fires no `devicechange` — so every surface that shows device NAMES re-scans on mount\r\n // rather than trusting whatever `BrowserAudioDevices` happened to see when the softphone was\r\n // first constructed. `softphone`, not `devices`, is the dependency: `devices` is a fresh object\r\n // every time it changes (see `useDevices`), and depending on it here would re-trigger this effect\r\n // on its own refresh.\r\n useEffect(() => {\r\n void softphone.audio.refresh();\r\n }, [softphone]);\r\n\r\n return (\r\n <>\r\n <DevicePicker\r\n icon={Mic}\r\n label=\"Micrófono\"\r\n kind=\"input\"\r\n options={devices.inputs}\r\n value={devices.currentInputId}\r\n onChange={(id) => void devices.setInput(id)}\r\n emptyText=\"No se encontró ningún micrófono\"\r\n />\r\n {devices.canSelectOutput ? (\r\n <DevicePicker\r\n icon={Headphones}\r\n label=\"Altavoces\"\r\n kind=\"output\"\r\n options={devices.outputs}\r\n value={devices.currentOutputId}\r\n onChange={(id) => void devices.setOutput(id)}\r\n emptyText=\"No se encontró ningún altavoz\"\r\n />\r\n ) : (\r\n // Safari and most of Firefox have no `setSinkId` at all — nothing here would do anything,\r\n // and offering a picker that silently fails is worse than not offering one.\r\n <p className=\"cv-settings-note\">\r\n Tu navegador no permite elegir el altavoz desde aquí — cámbialo en los ajustes del\r\n sistema.\r\n </p>\r\n )}\r\n </>\r\n );\r\n}\r\n","import { useEffect, useRef, useState } from 'react';\r\nimport {\r\n Phone,\r\n PhoneOff,\r\n Mic,\r\n MicOff,\r\n Pause,\r\n Play,\r\n ArrowLeft,\r\n ArrowLeftRight,\r\n ExternalLink,\r\n Grid3x3,\r\n Headphones,\r\n type LucideIcon,\r\n} from 'lucide-react';\r\nimport { useCall, usePresence, useSoftphone } from '../../react/index.js';\r\nimport type { CallView } from '../../react/index.js';\r\nimport { CallEvent } from '../../core/events.js';\r\nimport type { Call, HangupReason } from '../../core/call.js';\r\nimport type { SoftphoneErrorCode } from '../../core/errors.js';\r\nimport { formatDuration, elapsedSeconds, initials } from '../lib/format.js';\r\nimport { ERROR_TEXT } from '../lib/error-text.js';\r\nimport { useTicker } from '../lib/useTicker.js';\r\nimport { DevicePickers } from './DevicePicker.js';\r\nimport { KEYPAD_KEYS } from '../dialing/keys.js';\r\nimport { playKeyTone } from '../audio/audio.js';\r\nimport type { ContactAction, PresenceEntry, PresenceState } from '../types.js';\r\n\r\n/**\r\n * A secondary control: the button and the word for it.\r\n *\r\n * **The label is not decoration.** These were icon-only, and an icon-only control is a quiz — `⇄` is\r\n * transfer or swap or call-waiting depending on who you ask, and you are asking someone mid-call. The\r\n * CRM labels every one of these (`Silenciar` / `Colgar` / `Transferir`) and it is right to.\r\n *\r\n * `tone` carries the ON state's meaning rather than a colour, so muted reads as *danger* and held\r\n * reads as *held* — using the same `--cv-*` tokens the rest of the widget themes with.\r\n */\r\nfunction Control({\r\n icon: Icon,\r\n label,\r\n pressed = false,\r\n tone,\r\n onClick,\r\n disabled = false,\r\n title,\r\n}: Readonly<{\r\n icon: LucideIcon;\r\n label: string;\r\n pressed?: boolean;\r\n tone?: 'danger' | 'hold' | 'accent';\r\n onClick: () => void;\r\n disabled?: boolean;\r\n title?: string | undefined;\r\n}>) {\r\n return (\r\n <div className=\"cv-ctrl-item\">\r\n <button\r\n type=\"button\"\r\n className=\"cv-ctrl\"\r\n data-tone={pressed ? tone : undefined}\r\n aria-pressed={pressed}\r\n aria-label={label}\r\n onClick={onClick}\r\n disabled={disabled}\r\n title={title}\r\n >\r\n <Icon size={19} />\r\n </button>\r\n {/* aria-hidden: the button's own name already says this — do not announce it twice. */}\r\n <span className=\"cv-ctrl-label\" aria-hidden>\r\n {label}\r\n </span>\r\n </div>\r\n );\r\n}\r\n\r\nconst STATUS_LABEL: Record<string, string> = {\r\n ringing: 'Llamada entrante',\r\n dialing: 'Llamando…',\r\n early: 'Llamando…',\r\n answering: 'Conectando…',\r\n reconnecting: 'Reconectando…',\r\n held: 'En espera',\r\n};\r\n\r\n/**\r\n * A consult leg (attended transfer, SPEC §5.6) that ends without being completed reports a REAL\r\n * reason — it's an ordinary outbound call, not the REFER black box blind `transfer()` is\r\n * (`docs/specs/transfer-availability.md` §2). Reusing `ERROR_TEXT`'s existing call-outcome copy\r\n * rather than inventing new strings; `call/transfer-failed` is the fallback for a reason this table\r\n * doesn't otherwise name — it should be unreachable in practice, but a consult leg has more possible\r\n * `HangupReason`s than this maps, and staying exhaustive costs four lines.\r\n */\r\nconst CONSULT_FAIL_CODE: Partial<Record<HangupReason, SoftphoneErrorCode>> = {\r\n busy: 'call/busy',\r\n 'no-answer': 'call/no-answer',\r\n rejected: 'call/rejected',\r\n failed: 'call/failed',\r\n};\r\n\r\nfunction consultFailText(reason: HangupReason): string {\r\n return ERROR_TEXT[CONSULT_FAIL_CODE[reason] ?? 'call/transfer-failed'].title;\r\n}\r\n\r\n/**\r\n * Found live (plan T5, 2026-09-28): completing a consulted transfer via `ConsultScreen`'s own\r\n * \"Completar\" within ~1-2s of the consult answering can drop the caller entirely — `REFER` gets\r\n * accepted and the agent's own leg gets a clean \"Normal Clearing\" `BYE`, wire-identical to a genuine\r\n * success (`transfer-availability.md` §15 item 5's own evidence table), but the target's line was never\r\n * actually ready for the immediately-following fresh INVITE. Reusing `consultView.answeredAt` and the\r\n * existing ticker, no new tracking state. Same \"observed starting point, tune if real usage shows\r\n * otherwise\" posture this codebase's own `POST_CALL_COOLDOWN_MS` (5s, presence) was set with, not a\r\n * rigorously derived number — and it needed tuning twice: 3s (real margin above the ~1-2s that actually\r\n * failed) turned out live not to be enough; 6s STILL failed intermittently in further live testing;\r\n * raised to 10s, which live re-testing then confirmed reliable for THIS path. Exported so\r\n * `CallScreen.test.tsx` references this value directly instead of a duplicated literal.\r\n *\r\n * This same gate used to ALSO cover \"Transferir directo\" — the auto-handoff path completed the\r\n * identical warm-blind-transfer automatically, the instant this same minimum passed. That path kept\r\n * dropping calls even at 10s, live, while manual stayed reliable at the same value — an automated\r\n * completion apparently races Zadarma's own readiness signal harder than a human's incidental\r\n * reaction-time delay ever did, for reasons never root-caused. Rather than keep chasing a bigger\r\n * number on a mechanism that had already needed two rounds of \"still sometimes fails,\" \"Transferir\r\n * directo\" was redesigned (2026-09-28) into a literal, immediate blind transfer with no consult at\r\n * all — see `selectPresenceAgentAuto`'s own comment. This constant now only gates the manual path.\r\n */\r\nexport const MIN_CONSULT_HOLD_SECONDS = 10;\r\n\r\n/**\r\n * Full takeover while a consult is in progress (SPEC §5.6) — not a panel bolted onto the caller's own\r\n * screen, which is what this replaced. Two real calls exist simultaneously the whole time this is on\r\n * screen: the caller, silently on hold, and the consult target, who is who the agent is actually\r\n * talking to. Showing the CALLER's own screen with a collapsible transfer panel made that easy to\r\n * lose track of — found live: an agent reached for the ordinary \"Reanudar\" hold toggle without\r\n * realising the consult leg was still up, unholding the caller INTO a second already-live call and\r\n * putting both ends within earshot of each other at once. This screen removes that toggle from reach\r\n * entirely (it doesn't exist here) and makes \"go back to the caller\" a single, impossible-to-miss\r\n * action instead of something buried behind a panel someone could forget was open.\r\n */\r\nfunction ConsultScreen({\r\n mainName,\r\n consultView,\r\n now,\r\n onReturn,\r\n onComplete,\r\n onHangupAll,\r\n}: Readonly<{\r\n /** The ORIGINAL caller's name — for the \"who's waiting\" banner, not this screen's own subject. */\r\n mainName: string;\r\n consultView: CallView;\r\n now: number;\r\n /** Ends the consult leg and un-holds the caller — \"Cancelar\" and the return banner do the same thing. */\r\n onReturn: () => void;\r\n onComplete: () => void;\r\n /** Ends BOTH legs — the one true \"I'm done with all of this\" escape hatch. */\r\n onHangupAll: () => void;\r\n}>) {\r\n const s = consultView.state;\r\n const answered = s === 'active';\r\n const name = consultView.remote.displayName;\r\n const number = consultView.remote.number;\r\n const showNumber = number !== name;\r\n const heldSeconds = elapsedSeconds(consultView.answeredAt, now);\r\n const [rawM = '0', ss = '00'] = formatDuration(heldSeconds).split(':');\r\n const mm = rawM.padStart(2, '0');\r\n // See MIN_CONSULT_HOLD_SECONDS's own comment — a real, live-found gap, not a guess.\r\n const canComplete = heldSeconds >= MIN_CONSULT_HOLD_SECONDS;\r\n\r\n return (\r\n <div className=\"cv-view\">\r\n <div className=\"cv-call\">\r\n {/* The one fact that matters most on this whole screen: someone is still waiting. Full-width\r\n and tappable, not a passive status line — reads the return action as its own affordance. */}\r\n <button type=\"button\" className=\"cv-consult-hold-banner\" onClick={onReturn}>\r\n <Pause size={13} aria-hidden />\r\n {mainName} en espera · Volver\r\n </button>\r\n\r\n <div className=\"cv-avatar-wrap\">\r\n <div className=\"cv-avatar\" aria-hidden>\r\n {initials(name)}\r\n </div>\r\n {answered ? <span className=\"cv-avatar-dot\" aria-hidden /> : null}\r\n </div>\r\n <div className=\"cv-call-name\">{name}</div>\r\n {showNumber ? <div className=\"cv-call-number\">{number}</div> : null}\r\n\r\n {answered ? (\r\n <div className=\"cv-timer\" aria-label=\"Duración de la llamada\">\r\n <b>{mm}</b>\r\n <i>:</i>\r\n <b>{ss}</b>\r\n </div>\r\n ) : (\r\n <div className=\"cv-call-status\">{STATUS_LABEL[s] ?? ''}</div>\r\n )}\r\n </div>\r\n\r\n <div className=\"cv-controls\">\r\n <div className=\"cv-transfer-actions\">\r\n {answered ? (\r\n <button className=\"cv-btn cv-btn--accent\" onClick={onComplete} disabled={!canComplete}>\r\n Completar\r\n </button>\r\n ) : null}\r\n <button className=\"cv-btn\" onClick={onReturn}>\r\n Cancelar\r\n </button>\r\n </div>\r\n <div className=\"cv-controls-primary\">\r\n <div className=\"cv-ctrl-item\">\r\n <button\r\n type=\"button\"\r\n className=\"cv-round cv-round--hangup\"\r\n onClick={onHangupAll}\r\n aria-label=\"Colgar todo\"\r\n >\r\n <PhoneOff size={26} />\r\n </button>\r\n <span className=\"cv-ctrl-label\" aria-hidden>\r\n Colgar todo\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nconst PRESENCE_LABEL: Record<PresenceState, string> = {\r\n disponible: 'Disponible',\r\n en_llamada: 'En llamada',\r\n desconectado: 'Desconectado',\r\n};\r\n\r\nconst PRESENCE_RANK: Record<PresenceState, number> = {\r\n disponible: 0,\r\n en_llamada: 1,\r\n desconectado: 2,\r\n};\r\n\r\n/** *Disponible* → *En llamada* → *Desconectado*, then by name (spec §4.5). Self-exclusion happens in\r\n * the caller, not here — `TransferPicker` needs the pre-exclusion count too, to tell \"empty org\" (no\r\n * picker at all) apart from \"no match for what's typed\" (an empty-state row inside one). */\r\nfunction filterAgents(agents: readonly PresenceEntry[], query: string): readonly PresenceEntry[] {\r\n const q = query.trim().toLowerCase();\r\n return agents\r\n .filter((a) => !q || (a.name ?? '').toLowerCase().includes(q) || a.extension.includes(q))\r\n .sort(\r\n (a, b) =>\r\n PRESENCE_RANK[a.state] - PRESENCE_RANK[b.state] ||\r\n (a.name ?? a.extension).localeCompare(b.name ?? b.extension),\r\n );\r\n}\r\n\r\n/** Bounds the \"Llamar a {typed}\" button's own content size — a long paste must not force the\r\n * input+button row wider than the ~340 px embed (the exact class of bug `.cv-transfer-notice`\r\n * already hit once this widget, see that component's own history). */\r\nfunction truncateForButton(text: string, max = 16): string {\r\n return text.length > max ? `${text.slice(0, max)}…` : text;\r\n}\r\n\r\n/**\r\n * The agent list under the transfer input (spec §4.5, plan T7) — the \"one control instead of two\":\r\n * the existing input/button stay the free-text fallback, this is the new part. Renders nothing at\r\n * all once `myUserId` is excluded and no one else is left — an empty org, no `PresenceSource`\r\n * configured, or this tab not currently `online && isLeader` all look identical from here (spec\r\n * §4.4's success criterion: no error, just nothing to show) — the caller falls straight back to\r\n * today's free-text-only field, unchanged.\r\n */\r\nfunction TransferPicker({\r\n agents,\r\n myUserId,\r\n query,\r\n onSelect,\r\n}: Readonly<{\r\n agents: readonly PresenceEntry[];\r\n myUserId: string | null;\r\n query: string;\r\n onSelect: (extension: string) => void;\r\n}>) {\r\n const others = agents.filter((a) => a.userId !== myUserId);\r\n if (others.length === 0) return null;\r\n const filtered = filterAgents(others, query);\r\n\r\n return (\r\n <div className=\"cv-presence\">\r\n <div className=\"cv-presence-list\" role=\"listbox\" aria-label=\"Compañeros\">\r\n {filtered.length === 0 ? (\r\n <p className=\"cv-presence-empty\">Sin coincidencias</p>\r\n ) : (\r\n filtered.map((agent) => {\r\n // Found live (2026-09-28): transferring (either path) to a colleague who is genuinely\r\n // `en_llamada` — mid-call, or still inside Zadarma's own post-call settling window\r\n // (backend `POST_CALL_COOLDOWN_MS`, `redisPubSub/index.js`) — can leave the call a silent\r\n // ghost: the target's phone never rings, the caller just waits with no failure signal at\r\n // all, not even the \"busy\" a normal consult would surface. Unlike *Desconectado* (§4.6: a\r\n // HINT, since presence only sees our own web softphone and a colleague could be reachable\r\n // elsewhere), `en_llamada` is a real, currently-true signal we already have and were simply\r\n // not acting on — so this one is a hard block, not a hint: the row stays visible (an agent\r\n // should still see who's busy) but isn't selectable. It un-blocks itself the moment presence\r\n // reports them free again — no separate retry affordance needed. Free text remains a\r\n // deliberate escape hatch (spec §4: presence is what justifies this restriction too, and\r\n // free text has no presence behind it).\r\n const isBusy = agent.state === 'en_llamada';\r\n return (\r\n <button\r\n key={agent.userId}\r\n type=\"button\"\r\n role=\"option\"\r\n className=\"cv-presence-item\"\r\n disabled={isBusy}\r\n onClick={() => onSelect(agent.extension)}\r\n >\r\n <span className=\"cv-presence-dot\" data-state={agent.state} aria-hidden />\r\n <span className=\"cv-presence-name\">{agent.name ?? agent.extension}</span>\r\n <span className=\"cv-presence-meta\">\r\n {agent.extension} · {PRESENCE_LABEL[agent.state]}\r\n </span>\r\n </button>\r\n );\r\n })\r\n )}\r\n </div>\r\n {/* Decided 2026-09-21 (spec §4.6): *Desconectado* is a HINT, never \"can't transfer\" — presence\r\n only sees our own web softphone, so a colleague on a desk phone or Zadarma's own app reads\r\n Desconectado while genuinely reachable. This is what keeps that from being misread. */}\r\n <p className=\"cv-presence-legend\">\r\n Desconectado: sin conexión en el softphone web. Puede atender desde otro dispositivo.\r\n </p>\r\n </div>\r\n );\r\n}\r\n\r\n/** The active-call view: incoming, outgoing and in-call in one, switched on call.state. */\r\nexport function CallScreen({\r\n call,\r\n incomingCallAction,\r\n keyTones = true,\r\n}: Readonly<{\r\n call: Call;\r\n incomingCallAction?: ContactAction;\r\n /**\r\n * Play a tone for each keypad press. **On by default**; `SoftphoneWidget` passes its own `sounds`\r\n * flag, so a host that silences the widget silences this too.\r\n */\r\n keyTones?: boolean;\r\n}>) {\r\n const view = useCall(call);\r\n const softphone = useSoftphone();\r\n // ONE panel at a time. These were three independent booleans, and two of them could be open at once —\r\n // found live (2026-10-06): the keypad popover opened over the transfer panel and hid its input and\r\n // agent list entirely. One value makes that state unrepresentable instead of guarding against it in\r\n // each click handler.\r\n const [panel, setPanel] = useState<'transfer' | 'keypad' | 'devices' | null>(null);\r\n const showTransfer = panel === 'transfer';\r\n const showKeypad = panel === 'keypad';\r\n const showDevices = panel === 'devices';\r\n const togglePanel = (p: 'transfer' | 'keypad') => setPanel((cur) => (cur === p ? null : p));\r\n const [transferTo, setTransferTo] = useState('');\r\n const [consultCall, setConsultCall] = useState<Call | null>(null);\r\n const [consultOutcome, setConsultOutcome] = useState<HangupReason | null>(null);\r\n const [myUserId, setMyUserId] = useState<string | null>(null);\r\n const consultView = useCall(consultCall);\r\n // Set right before completeTransfer()/cancelConsult() so the Ended listener below can tell \"we just\r\n // ended this ourselves\" apart from \"the target hung up on us\" — the same event fires either way, and\r\n // only the second case is a failure worth showing.\r\n const consultIntentRef = useRef<'complete' | 'cancel' | null>(null);\r\n const controlsRef = useRef<HTMLDivElement>(null);\r\n const now = useTicker(view?.state === 'active');\r\n // `ConsultScreen` needs its OWN timer — the consult leg answers, and stays live, independently of\r\n // whatever the main call's own state is doing underneath it.\r\n const consultNow = useTicker(consultView?.state === 'active');\r\n // Needed ahead of the early-return guard below, since the outside-click effect depends on it and\r\n // hooks can't follow a conditional return.\r\n const isConnected = view ? view.state === 'active' || view.state === 'held' || view.state === 'reconnecting' : false;\r\n // Same reasoning — `usePresence` is a hook too. Mirrors `inCall && showTransfer && !consultCall`\r\n // below exactly (`inCall` is this same value under a different name, post-early-return).\r\n const transferPickerActive = isConnected && showTransfer && !consultCall;\r\n // Subscribes only while the transfer step is open (spec §4.5) — the CONNECTION itself stays\r\n // governed by `online && isLeader` regardless (`usePresence`'s own doc comment); this only scopes\r\n // which component bothers re-rendering on an update.\r\n const presence = usePresence(transferPickerActive);\r\n\r\n // The org's phone directory, fetched once — same source, same \"absent ⇒ feature quietly does not\r\n // render\" shape `HistoryTab`'s own `PersonFilter` already uses. `me.userId` is the ONE piece needed\r\n // here: excluding the agent from their own transfer picker (spec §4.5).\r\n useEffect(() => {\r\n const listAgents = softphone.sources?.listAgents;\r\n if (!listAgents) return;\r\n let cancelled = false;\r\n void listAgents()\r\n .then((d) => !cancelled && setMyUserId(d.me?.userId ?? null))\r\n .catch(() => {});\r\n return () => {\r\n cancelled = true;\r\n };\r\n }, [softphone]);\r\n\r\n // The consult leg's terminal event — NOT unsubscribed on anything UI-side: `ConsultScreen` is on\r\n // screen for exactly as long as `consultCall` is non-null, so there is no \"panel closed but the\r\n // call is still ringing\" state left to strand (there was, before this was its own screen — see that\r\n // component's own comment).\r\n useEffect(() => {\r\n if (!consultCall) return;\r\n return consultCall.on(CallEvent.Ended, ({ reason }) => {\r\n const intent = consultIntentRef.current;\r\n consultIntentRef.current = null;\r\n setConsultCall(null);\r\n if (!intent) {\r\n // Ended on its own — busy/no-answer/rejected/failed. Plan T2: recover the caller automatically\r\n // instead of leaving them silently held until the agent notices this notice and resumes them by\r\n // hand — a real gap that existed before this fix.\r\n setConsultOutcome(reason);\r\n // Guard against the MAIN call having ALSO already ended by now (spec §5.3/plan §10 Q5) — found\r\n // to be a REAL, reachable ordering, not just a theoretical one: `CallImpl#end()`'s own\r\n // consult-leg cleanup fires `consult.hangup()` without awaiting it, so this listener can still\r\n // run — the component hasn't unmounted yet — before React processes the main call's own `ended`\r\n // state. Caught directly by a spy in the \"caller hangs up first\" test, which failed on the first\r\n // attempt without this guard: `unhold()` doesn't throw when called on an ended call (its own\r\n // `!this.#onHold` short-circuit doesn't help here, since the caller genuinely WAS on hold right\r\n // up to that point), but calling it on a dead session is still wrong to do on purpose. `call.state`\r\n // is `CallImpl`'s own live getter, not a React-closure value — reading it fresh here, not `view`.\r\n if (call.state !== 'ended') void call.unhold();\r\n }\r\n // else: we ended it ourselves (bridged by completeTransfer, or hung up by cancelConsult) —\r\n // nothing failed, nothing to show.\r\n });\r\n }, [consultCall, call]);\r\n\r\n /**\r\n * `target` overrides `transferTo` — needed when a `TransferPicker` row is clicked (plan T7):\r\n * `setTransferTo` is async (React state), so a caller that set it and immediately called this\r\n * without the override would still read the PREVIOUS render's `transferTo` here, off by one click.\r\n * Free text (the button) omits it and falls back to the input's own current value, unchanged.\r\n */\r\n const startConsult = async (target?: string) => {\r\n const t = (target ?? transferTo).trim();\r\n if (!t) return;\r\n setConsultOutcome(null);\r\n setConsultCall(await call.startConsult(t));\r\n };\r\n const selectPresenceAgent = (extension: string) => {\r\n setTransferTo(extension);\r\n void startConsult(extension);\r\n };\r\n // Which of the two paths (spec §5.4) a picker row click starts — \"Hablar primero\" (the consult flow\r\n // above, unchanged) by default, or \"Transferir directo\" once switched. Free text (the `Llamar` button\r\n // below) always uses `startConsult` directly, unaffected either way — presence is what justifies a\r\n // one-click transfer at all, and free text has no presence behind it.\r\n const [quickTransfer, setQuickTransfer] = useState(false);\r\n /**\r\n * \"Transferir directo\": a literal, immediate blind transfer — no consult, no ring-first confirmation,\r\n * no hold-timer gate. This replaces an earlier design (plan `transfer-auto-handoff-plan.md` T1–T5)\r\n * that reused the \"warm blind transfer\" pattern automatically — consult the target, wait for it to\r\n * answer, hold `MIN_CONSULT_HOLD_SECONDS`, then bridge — the exact same mechanism `ConsultScreen`'s\r\n * manual \"Completar\" still uses. That approach kept dropping the caller live even after the hold was\r\n * raised to 10s (found reliable for the MANUAL path at that value), for reasons never root-caused —\r\n * an automated completion apparently doesn't get the same margin a human's incidental reaction-time\r\n * delay was providing. Found live, 2026-09-28: \"Sometimes it still fails at 6s... [still] fails\" even\r\n * at 10s, direct transfer only — the consult-first path was confirmed reliable at 10s in the same\r\n * round of testing.\r\n *\r\n * Rather than keep tuning an interval that had already needed three rounds, this path now does what\r\n * its label says: an honest, single-step blind transfer, same call as a fresh cold transfer to any\r\n * number would be. The trade-off is real and accepted, not hidden — a failed transfer here drops the\r\n * caller with no recovery on screen, same as any blind transfer (`transfer-availability.md` §2's own\r\n * foundational finding: success and failure are indistinguishable at the SIP layer). The existing\r\n * outcome-relay (`transfer-outcome-relay.md`, Phase A, already live) catches it roughly a minute later\r\n * and offers the agent a callback — the accepted safety net. \"Hablar primero\" remains the path for an\r\n * agent who wants certainty over speed; this one is for speed.\r\n */\r\n const selectPresenceAgentAuto = (extension: string) => {\r\n void call.transfer(extension);\r\n };\r\n /**\r\n * NOT `call.completeTransfer()` (REFER…Replaces) — confirmed dead against Zadarma, three times, live\r\n * (`docs/specs/transfer-availability.md` §12.3): Zadarma accepts the REFER, drops the caller's leg\r\n * the same way it does for blind transfer, and never bridges anything — the consult leg is simply\r\n * orphaned. What actually works: hang up the consult leg (freeing the target's line) and then blind-\r\n * transfer the caller to that SAME target — the \"warm blind transfer\" pattern (§15 item 5's chosen\r\n * fix). Blind transfer to a target that's already known to be there and answering is exactly Phase\r\n * 0's capture 2, which worked. The one honest cost: the target's phone rings a SECOND time (once for\r\n * the consult, once for the actual transferred call) — REFER always triggers a fresh INVITE, there is\r\n * no seamless hand-off available here. They just confirmed they're expecting it, so this reads as\r\n * \"the call is coming through now,\" not a mystery second ring.\r\n */\r\n const completeTransfer = async () => {\r\n if (!consultCall) return;\r\n const target = transferTo.trim();\r\n consultIntentRef.current = 'complete';\r\n await consultCall.hangup();\r\n await call.transfer(target);\r\n };\r\n const cancelConsult = async () => {\r\n consultIntentRef.current = 'cancel';\r\n await call.cancelConsult();\r\n };\r\n\r\n // Dispositivos is inline content swapped into `.cv-call` in EVERY state now (see that JSX's own\r\n // comment for why) — once connected it used to be a floating popover. Inline content has no\r\n // \"outside\" to click away from (a stray tap on Silenciar must not dismiss it), so the only ways\r\n // out are its own back button, Escape, or opening another panel.\r\n useEffect(() => {\r\n if (!showDevices) return;\r\n const onKey = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') setPanel(null);\r\n };\r\n document.addEventListener('keydown', onKey);\r\n return () => document.removeEventListener('keydown', onKey);\r\n }, [showDevices]);\r\n\r\n // The keypad is the one popover left on this screen, so it is the one panel that closes on outside\r\n // click / Escape — same shape as `PersonFilter`'s own (HistoryTab.tsx), not shared: duplicating this\r\n // dozen lines is cheaper than coupling two unrelated pickers through an abstraction neither needs.\r\n useEffect(() => {\r\n if (!showKeypad) return;\r\n const onKey = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') setPanel(null);\r\n };\r\n document.addEventListener('keydown', onKey);\r\n if (!isConnected) return () => document.removeEventListener('keydown', onKey);\r\n // On the SHADOW ROOT's node when there is one — inside a shadow tree, `document` click targets\r\n // are retargeted to the host, so `contains()` against the host would report every internal click\r\n // as \"outside\" and the popover would never open.\r\n const root = controlsRef.current?.getRootNode() ?? document;\r\n const onDown = (e: Event) => {\r\n if (!controlsRef.current?.contains(e.target as Node)) setPanel(null);\r\n };\r\n root.addEventListener('pointerdown', onDown);\r\n return () => {\r\n document.removeEventListener('keydown', onKey);\r\n root.removeEventListener('pointerdown', onDown);\r\n };\r\n }, [showKeypad, isConnected]);\r\n\r\n // DTMF only means anything with live media flowing both ways — held and reconnecting don't qualify\r\n // (see the control's own `disabled` below). Leaving the panel open over a disabled trigger would\r\n // read as broken, so it closes the moment the call leaves 'active'. Only the keypad: another panel\r\n // that happens to be open (Transferir, Dispositivos) has nothing to do with media state.\r\n useEffect(() => {\r\n if (view && view.state !== 'active') setPanel((cur) => (cur === 'keypad' ? null : cur));\r\n }, [view?.state]);\r\n\r\n if (!view || view.state === 'ended') return null;\r\n\r\n const s = view.state;\r\n const isRinging = s === 'ringing';\r\n const inCall = isConnected;\r\n const name = view.remote.displayName;\r\n const number = view.remote.number;\r\n const showNumber = number !== name;\r\n\r\n // Full takeover, not a branch further down inside the normal layout — see `ConsultScreen`'s own\r\n // comment for why the caller's screen with a bolted-on panel was the wrong shape for this. Only\r\n // \"Hablar primero\" ever creates a consult call now — \"Transferir directo\" bypasses this entirely\r\n // (see `selectPresenceAgentAuto`'s own comment).\r\n if (consultCall && consultView) {\r\n return (\r\n <ConsultScreen\r\n mainName={name}\r\n consultView={consultView}\r\n now={consultNow}\r\n onReturn={() => void cancelConsult()}\r\n onComplete={() => void completeTransfer()}\r\n onHangupAll={() => void call.hangup()}\r\n />\r\n );\r\n }\r\n\r\n // Incoming calls only (matches the legacy softphone's own `IncomingCallView`, a screen distinct\r\n // from outbound/in-call) — and only once `resolveContact` has actually matched this number to a\r\n // real contact, the same \"known contacts only\" gate the legacy's own \"Ver mensajes\" button used.\r\n // Independent of `contactAction` (the Contactos-tab detail page's own action): same TYPE, a\r\n // DIFFERENT host-supplied instance, because what's useful to offer while someone is ringing you\r\n // is not necessarily what belongs on a contact's static detail page.\r\n const incomingAction = isRinging && view.remote.contact && incomingCallAction ? incomingCallAction : null;\r\n const IncomingActionIcon = incomingAction?.icon ?? ExternalLink;\r\n\r\n // The call timer is always MM:SS (zero-padded), matching the product. formatDuration is left\r\n // unpadded because the history list reads better as \"1:33\" than \"01:33\".\r\n const [rawM = '0', ss = '00'] = formatDuration(elapsedSeconds(view.answeredAt, now)).split(':');\r\n const mm = rawM.padStart(2, '0');\r\n\r\n return (\r\n <div className=\"cv-view\">\r\n <div className=\"cv-call\">\r\n {/*\r\n Before a call connects, Colgar (or Rechazar/Contestar) is the ONLY other control on screen —\r\n a Dispositivos popover anchored anywhere near it, even spaced out, either overlapped those\r\n buttons or had to clamp itself down to something cramped and scrolly for just two rows (this\r\n SDK's actual production embed — a 310×520 host panel with its own header eating further into\r\n that — leaves very little free room around a trigger sitting in vertically-centred content).\r\n Swapping the call info for the picker in the SAME space sidesteps the problem rather than\r\n measuring around it: the picker gets the full `.cv-call` box, not a leftover sliver of it.\r\n\r\n Once connected it is the same swap, not a popover: the control row below stays put and fully\r\n usable (mute, hold and hang up all work with this open), and Dispositivos moved out of that\r\n row into this same chip so the row could go back to four controls at a size a thumb can hit.\r\n */}\r\n {showDevices ? (\r\n <div className=\"cv-call-devices-inline\">\r\n <div className=\"cv-call-devices-header\">\r\n {/* Same chip as the entry point below, not an icon-only ghost button — an icon alone\r\n here read as decoration, not a way out, which is exactly the mistake `.cv-cp-chip`\r\n (CountryPicker) already made and fixed once: \"invisible until hover... nothing says\r\n you can change this.\" A visible \"Volver\" fixes it the same way that one was fixed. */}\r\n <button type=\"button\" className=\"cv-call-devices-chip\" onClick={() => setPanel(null)}>\r\n <ArrowLeft size={13} aria-hidden />\r\n Volver\r\n </button>\r\n <span className=\"cv-call-devices-title\">Dispositivos</span>\r\n </div>\r\n {/* Who's calling doesn't disappear just because you're checking your mic — and once\r\n connected, neither does how long you have been on the call. */}\r\n <p className=\"cv-call-devices-context\">\r\n {showNumber ? `${number} · ` : ''}\r\n {s === 'active' ? `${mm}:${ss}` : (STATUS_LABEL[s] ?? '')}\r\n </p>\r\n <div className=\"cv-settings-section-body\">\r\n <DevicePickers />\r\n </div>\r\n </div>\r\n ) : transferPickerActive ? (\r\n /*\r\n Found live (2026-09-29): the agent list a moment ago picked between showing ONE agent row\r\n or forcing a scroll — `.cv-presence-list`'s own `max-height` had already been trimmed twice\r\n (T7, then T3) chasing that, and both times the room it was chasing lived somewhere else.\r\n The full avatar/name/giant-timer block above stayed on screen, unconditionally, the WHOLE\r\n time the picker was open — exactly the anti-pattern `.cv-call-devices-inline` (above) was\r\n already built to avoid for the pre-connect device picker: \"an inline swap, not an overlay,\r\n so it gets the full box, not a leftover sliver.\" The picker never got that same treatment.\r\n Measured live (a temporary harness, `playground/react/picker-harness.*`, real Chromium at\r\n this SDK's own real embed footprint, 310×520): the avatar+name+timer block alone cost\r\n ~150px of `.cv-call`'s ~340px of usable height — more than the entire agent list, the mode\r\n toggle, and the free-text row combined. Reusing `.cv-call-devices-inline`'s OWN \"who's\r\n calling doesn't disappear\" compact context line (below) instead of the full block gives\r\n that ~150px back to the one thing this screen is actually for right now: the list.\r\n */\r\n <div className=\"cv-transfer\">\r\n <div className=\"cv-transfer-context\">\r\n <span className=\"cv-call-devices-title\">{name}</span>\r\n <p className=\"cv-call-devices-context\">\r\n {showNumber ? `${number} · ` : ''}\r\n {s === 'active' ? `${mm}:${ss}` : (STATUS_LABEL[s] ?? '')}\r\n </p>\r\n </div>\r\n {consultOutcome ? (\r\n <p className=\"cv-dial-outcome\" role=\"status\" data-shown=\"true\">\r\n {consultFailText(consultOutcome)}\r\n </p>\r\n ) : null}\r\n {/*\r\n Attended-first by default (SPEC §5.6, `docs/specs/transfer-availability.md` §5): free\r\n text always consults first — its target is unconfirmed, and a blind transfer's REFER\r\n outcome is unknowable against Zadarma (§2). A presence-picked colleague under\r\n \"Transferir directo\" (below) is the one deliberate exception — see\r\n `selectPresenceAgentAuto`'s own comment for why that one-click blind transfer is\r\n accepted there.\r\n */}\r\n <div className=\"cv-transfer-row\">\r\n <input\r\n className=\"cv-search\"\r\n value={transferTo}\r\n onChange={(e) => setTransferTo(e.target.value)}\r\n placeholder=\"Nombre, ext. o número\"\r\n aria-label=\"Transferir a\"\r\n autoFocus\r\n />\r\n <button\r\n className=\"cv-btn cv-btn--accent\"\r\n disabled={!transferTo.trim()}\r\n onClick={() => void startConsult()}\r\n >\r\n {transferTo.trim() ? `Llamar a ${truncateForButton(transferTo.trim())}` : 'Llamar'}\r\n </button>\r\n </div>\r\n {/* Plan T3 (spec §5.4/§10.1): reuses `HistoryTab`'s own `.cv-segmented` filter-toggle\r\n pattern verbatim — same tablist semantics, same already-styled look — rather than\r\n inventing a second segmented-control design for the same widget. */}\r\n <div className=\"cv-segmented\" role=\"tablist\" aria-label=\"Modo de transferencia\">\r\n {(\r\n [\r\n { key: 'consult', label: 'Hablar primero' },\r\n { key: 'auto', label: 'Transferir directo' },\r\n ] as const\r\n ).map(({ key, label }) => (\r\n <button\r\n key={key}\r\n type=\"button\"\r\n role=\"tab\"\r\n aria-selected={quickTransfer === (key === 'auto')}\r\n className=\"cv-segmented-btn\"\r\n onClick={() => setQuickTransfer(key === 'auto')}\r\n >\r\n {label}\r\n </button>\r\n ))}\r\n </div>\r\n <TransferPicker\r\n agents={presence}\r\n myUserId={myUserId}\r\n query={transferTo}\r\n onSelect={quickTransfer ? selectPresenceAgentAuto : selectPresenceAgent}\r\n />\r\n </div>\r\n ) : (\r\n <>\r\n <div className=\"cv-avatar-wrap\">\r\n {/* The halo is the one moment worth animating — it reads as \"ringing\" at a glance. */}\r\n {isRinging ? <span className=\"cv-avatar-ping\" aria-hidden /> : null}\r\n <div className=\"cv-avatar\" aria-hidden>\r\n {initials(name)}\r\n </div>\r\n {s === 'active' ? <span className=\"cv-avatar-dot\" aria-hidden /> : null}\r\n </div>\r\n\r\n <div className=\"cv-call-name\">{name}</div>\r\n {showNumber ? <div className=\"cv-call-number\">{number}</div> : null}\r\n\r\n {s === 'active' ? (\r\n <div className=\"cv-timer\" aria-label=\"Duración de la llamada\">\r\n <b>{mm}</b>\r\n <i>:</i>\r\n <b>{ss}</b>\r\n </div>\r\n ) : (\r\n <div className=\"cv-call-status\">\r\n {s === 'held' ? <span className=\"cv-badge-hold\">{STATUS_LABEL[s]}</span> : (STATUS_LABEL[s] ?? '')}\r\n </div>\r\n )}\r\n\r\n {/* Present in every state: it is the one way to reach the device picker, and is no longer a\r\n control in the row below (that row is four controls now — see `.cv-controls-row`). */}\r\n <div className=\"cv-call-chips\">\r\n {/* The caller-specific action comes first — it is about who is calling, which\r\n outranks a phone-utility setting. Wraps onto its own line rather than forcing\r\n both chips into a fixed row: a host's label is arbitrary text, not something\r\n this component can assume is short. (`incomingAction` is only ever set while\r\n ringing, so once connected this row is Dispositivos alone.) */}\r\n {incomingAction ? (\r\n <button\r\n type=\"button\"\r\n className=\"cv-call-devices-chip\"\r\n onClick={() => incomingAction.onClick(view.remote.contact!)}\r\n >\r\n <IncomingActionIcon size={13} aria-hidden />\r\n {incomingAction.label}\r\n </button>\r\n ) : null}\r\n <button type=\"button\" className=\"cv-call-devices-chip\" onClick={() => setPanel('devices')}>\r\n <Headphones size={13} aria-hidden />\r\n Dispositivos\r\n </button>\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n\r\n {/*\r\n Two tiers, not one row. Hang up is the ONE action that must never be hunted for, so it sits\r\n alone, centred and largest — the anchor the eye lands on. The secondaries flank above it.\r\n Previously all four shared a row and hang up was simply the last of them, the same visual\r\n weight as \"transfer\", off to one side. On a live call that is the wrong hierarchy.\r\n */}\r\n <div className=\"cv-controls\" ref={controlsRef}>\r\n {isRinging ? (\r\n <div className=\"cv-controls-primary\">\r\n <div className=\"cv-ctrl-item\">\r\n <button\r\n type=\"button\"\r\n className=\"cv-round cv-round--hangup\"\r\n onClick={() => void call.reject()}\r\n aria-label=\"Rechazar\"\r\n >\r\n <PhoneOff size={26} />\r\n </button>\r\n <span className=\"cv-ctrl-label\" aria-hidden>\r\n Rechazar\r\n </span>\r\n </div>\r\n <div className=\"cv-ctrl-item\">\r\n <button\r\n type=\"button\"\r\n className=\"cv-round cv-round--answer\"\r\n onClick={() => void call.answer()}\r\n aria-label=\"Contestar\"\r\n part=\"answer-button\"\r\n >\r\n <Phone size={26} />\r\n </button>\r\n <span className=\"cv-ctrl-label\" aria-hidden>\r\n Contestar\r\n </span>\r\n </div>\r\n </div>\r\n ) : (\r\n <>\r\n {inCall ? (\r\n <div className=\"cv-controls-row\">\r\n <Control\r\n icon={view.isMuted ? MicOff : Mic}\r\n label={view.isMuted ? 'Activar' : 'Silenciar'}\r\n pressed={view.isMuted}\r\n tone=\"danger\"\r\n onClick={() => call.mute(!view.isMuted)}\r\n />\r\n <Control\r\n icon={view.isOnHold ? Play : Pause}\r\n label={view.isOnHold ? 'Reanudar' : 'Espera'}\r\n pressed={view.isOnHold}\r\n tone=\"hold\"\r\n onClick={() => (view.isOnHold ? void call.unhold() : void call.hold())}\r\n />\r\n <Control\r\n icon={ArrowLeftRight}\r\n label=\"Transferir\"\r\n pressed={showTransfer}\r\n tone=\"accent\"\r\n onClick={() => togglePanel('transfer')}\r\n />\r\n <Control\r\n icon={Grid3x3}\r\n label=\"Teclado\"\r\n pressed={showKeypad}\r\n tone=\"accent\"\r\n disabled={s !== 'active'}\r\n title={\r\n s === 'held'\r\n ? 'Reanuda la llamada para usar el teclado'\r\n : s === 'reconnecting'\r\n ? 'No disponible mientras se reconecta'\r\n : undefined\r\n }\r\n onClick={() => togglePanel('keypad')}\r\n />\r\n </div>\r\n ) : null}\r\n <div className=\"cv-controls-primary\">\r\n <div className=\"cv-ctrl-item\">\r\n <button\r\n type=\"button\"\r\n className=\"cv-round cv-round--hangup\"\r\n onClick={() => void call.hangup()}\r\n aria-label=\"Colgar\"\r\n part=\"hangup-button\"\r\n >\r\n <PhoneOff size={26} />\r\n </button>\r\n <span className=\"cv-ctrl-label\" aria-hidden>\r\n Colgar\r\n </span>\r\n </div>\r\n </div>\r\n {/*\r\n Anchored to `.cv-controls` (position:relative, spanning the full row) rather than to\r\n the Teclado trigger's own small wrapper — the same fix `.cv-cp`/CountryPicker already\r\n needed (see its own comment): anchoring to a narrow, off-centre trigger let the\r\n popover's edge reach `.cv-softphone`'s `overflow:hidden` and get clipped. A full-width\r\n anchor makes that arithmetically impossible.\r\n */}\r\n {inCall && showKeypad ? (\r\n <div className=\"cv-keypad-popover cv-keypad-popover--above\" role=\"dialog\" aria-label=\"Teclado\">\r\n {KEYPAD_KEYS.map(([key, letters]) => (\r\n <button\r\n key={key}\r\n type=\"button\"\r\n className=\"cv-key\"\r\n onClick={() => {\r\n call.sendDigits(key);\r\n // AFTER the send, so the tone confirms the digit actually went out — if\r\n // `sendDigits` throws (the session is not in a state that can carry DTMF),\r\n // silence is the honest feedback. The far end gets the digit as a SIP INFO\r\n // message the local user never hears, which is why this tone exists at all.\r\n if (keyTones) playKeyTone(key);\r\n }}\r\n >\r\n <b>{key}</b>\r\n {letters ? <small>{letters}</small> : null}\r\n </button>\r\n ))}\r\n </div>\r\n ) : null}\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { ChevronRight } from 'lucide-react';\r\nimport type { ReactNode } from 'react';\r\nimport type { ContactActionIcon } from '../types.js';\r\n\r\n/**\r\n * One row on a detail page (contact or call). `eyebrow` is the informational shape (a field: Teléfono,\r\n * its value below) — `onClick` is the action shape (one line, a chevron, something happens). A row is\r\n * never both: the legacy's \"Conversación\" row forced an ACTION into a field's label/value layout,\r\n * which is why it read as an odd, oversized field rather than as a button. Splitting the two here is\r\n * what fixes that.\r\n *\r\n * Shared between `ContactDetail` and `HistoryDetail` rather than duplicated — the two pages show\r\n * different fields, but the ROW itself (icon + eyebrow + value, optionally a chevron) is one thing.\r\n */\r\nexport function DetailRow({\r\n icon: Icon,\r\n eyebrow,\r\n text,\r\n onClick,\r\n}: Readonly<{\r\n icon: ContactActionIcon;\r\n eyebrow?: string;\r\n text: ReactNode;\r\n onClick?: () => void;\r\n}>) {\r\n const inner = (\r\n <>\r\n <span className=\"cv-detail-row-icon\" aria-hidden>\r\n <Icon size={16} />\r\n </span>\r\n <span className=\"cv-detail-row-text\">\r\n {eyebrow ? <span className=\"cv-detail-row-eyebrow\">{eyebrow}</span> : null}\r\n <span className=\"cv-detail-row-value\">{text}</span>\r\n </span>\r\n {onClick ? <ChevronRight size={16} className=\"cv-detail-row-chevron\" aria-hidden /> : null}\r\n </>\r\n );\r\n return onClick ? (\r\n <button type=\"button\" className=\"cv-detail-row cv-detail-row--action\" onClick={onClick}>\r\n {inner}\r\n </button>\r\n ) : (\r\n <div className=\"cv-detail-row\">{inner}</div>\r\n );\r\n}\r\n","import { ArrowLeft, ExternalLink, Phone } from 'lucide-react';\r\nimport { useSoftphone } from '../../react/index.js';\r\nimport { useIntlFormatter } from '../dialing/format-number.js';\r\nimport { initials } from '../lib/format.js';\r\nimport { DetailRow } from './DetailRow.js';\r\nimport type { Contact } from '../../core/types.js';\r\nimport type { ContactAction } from '../types.js';\r\n\r\n/**\r\n * A contact's detail page — avatar, name, phone, one optional host-defined action, and the call\r\n * button. Opens over the list when a contact is tapped (`ContactsTab` owns that transition); this\r\n * component only knows how to show ONE contact and get back out.\r\n */\r\nexport function ContactDetail({\r\n contact,\r\n onBack,\r\n contactAction,\r\n}: Readonly<{\r\n contact: Contact;\r\n onBack: () => void;\r\n contactAction?: ContactAction;\r\n}>) {\r\n const softphone = useSoftphone();\r\n const formatIntl = useIntlFormatter();\r\n const formatted = formatIntl(contact.phone);\r\n const name = contact.name ?? formatted;\r\n\r\n return (\r\n <div className=\"cv-detail\" role=\"region\" aria-label={name}>\r\n <div className=\"cv-detail-head\">\r\n <button type=\"button\" className=\"cv-detail-back\" onClick={onBack}>\r\n <ArrowLeft size={16} aria-hidden />\r\n Contactos\r\n </button>\r\n </div>\r\n\r\n <div className=\"cv-detail-body\">\r\n <div className=\"cv-detail-identity\">\r\n <span className=\"cv-detail-avatar\" aria-hidden>\r\n {initials(contact.name)}\r\n </span>\r\n <h2 className=\"cv-detail-name\">{name}</h2>\r\n </div>\r\n\r\n <div className=\"cv-detail-rows\">\r\n <DetailRow icon={Phone} eyebrow=\"Teléfono\" text={formatted} />\r\n {contactAction ? (\r\n <DetailRow\r\n icon={contactAction.icon ?? ExternalLink}\r\n text={contactAction.label}\r\n onClick={() => contactAction.onClick(contact)}\r\n />\r\n ) : null}\r\n </div>\r\n </div>\r\n\r\n <div className=\"cv-detail-foot\">\r\n <button\r\n type=\"button\"\r\n className=\"cv-btn cv-btn--accent cv-detail-call\"\r\n onClick={() => void softphone.call(contact.phone)}\r\n >\r\n <Phone size={16} aria-hidden />\r\n Llamar\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { useCallback, useEffect, useRef, useState } from 'react';\r\n\r\nexport interface InfiniteListPage<T> {\r\n readonly items: readonly T[];\r\n /** Whether another page exists beyond this one. */\r\n readonly hasMore: boolean;\r\n}\r\n\r\nexport interface InfiniteListResult<T> {\r\n readonly items: readonly T[];\r\n /** True only while the FIRST page (for the current `loadPage`) is in flight. */\r\n readonly loading: boolean;\r\n /** True while a SUBSEQUENT page is in flight — kept separate from `loading` so the list doesn't\r\n * drop back to the full empty/spinner state on every scroll-triggered fetch. */\r\n readonly loadingMore: boolean;\r\n readonly hasMore: boolean;\r\n /** The first page failed. Subsequent-page failures are not surfaced here — see `loadMore` below. */\r\n readonly error: boolean;\r\n /** Attach to the scrollable list element — the `IntersectionObserver`'s `root`. */\r\n readonly containerRef: (node: HTMLElement | null) => void;\r\n /** Attach to a marker rendered after the last row, only while `hasMore`. */\r\n readonly sentinelRef: (node: HTMLElement | null) => void;\r\n}\r\n\r\n/**\r\n * Pages a list on scroll. `loadPage(skip)` fetches one page; the hook appends it and arms a\r\n * sentinel row, observed with a plain `IntersectionObserver` against the scrollable container, to\r\n * fetch the next one as it nears the bottom. No virtualization, no extra dependency — proportionate\r\n * to the list sizes a softphone panel holds (a CRM's contacts, a call history), where scrolling\r\n * itself is the cost, not rendering N rows of DOM.\r\n *\r\n * `root` is set explicitly to the scroll container rather than left as the default (browser\r\n * viewport), because the widget can sit anywhere on a host's page — a panel that is itself fully\r\n * on-screen but taller than the visible viewport would otherwise never fire.\r\n *\r\n * `loadPage`'s IDENTITY is the reset signal: give it a new one (`useCallback`, keyed on whatever\r\n * should restart the list — a changed `source` prop, a changed search term) and the hook drops the\r\n * current items and fetches page one again. A page landing after a newer `loadPage` has already\r\n * superseded it is discarded via `seqRef`, the same race the legacy CRM's `ContactsTab` guarded\r\n * against with its own `seqRef` bumped per search.\r\n */\r\nexport function useInfiniteList<T>(loadPage: (skip: number) => Promise<InfiniteListPage<T>>): InfiniteListResult<T> {\r\n const [items, setItems] = useState<readonly T[]>([]);\r\n const [loading, setLoading] = useState(true);\r\n const [loadingMore, setLoadingMore] = useState(false);\r\n const [hasMore, setHasMore] = useState(true);\r\n const [error, setError] = useState(false);\r\n\r\n const seqRef = useRef(0);\r\n const itemsRef = useRef<readonly T[]>(items);\r\n itemsRef.current = items;\r\n const loadingMoreRef = useRef(false);\r\n const hasMoreRef = useRef(true);\r\n\r\n useEffect(() => {\r\n const seq = ++seqRef.current;\r\n loadingMoreRef.current = false;\r\n hasMoreRef.current = true;\r\n setItems([]);\r\n setHasMore(true);\r\n setError(false);\r\n setLoading(true);\r\n void loadPage(0)\r\n .then((page) => {\r\n if (seq !== seqRef.current) return;\r\n setItems(page.items);\r\n setHasMore(page.hasMore);\r\n hasMoreRef.current = page.hasMore;\r\n })\r\n .catch(() => {\r\n if (seq !== seqRef.current) return;\r\n setItems([]);\r\n setHasMore(false);\r\n hasMoreRef.current = false;\r\n setError(true);\r\n })\r\n .finally(() => {\r\n if (seq === seqRef.current) setLoading(false);\r\n });\r\n }, [loadPage]);\r\n\r\n const loadMore = useCallback(() => {\r\n if (loadingMoreRef.current || !hasMoreRef.current) return;\r\n const seq = seqRef.current;\r\n loadingMoreRef.current = true;\r\n setLoadingMore(true);\r\n void loadPage(itemsRef.current.length)\r\n .then((page) => {\r\n if (seq !== seqRef.current) return;\r\n setItems((prev) => [...prev, ...page.items]);\r\n setHasMore(page.hasMore);\r\n hasMoreRef.current = page.hasMore;\r\n })\r\n .catch(() => {\r\n // Left `hasMore`/`hasMoreRef` untouched deliberately — a transient failure should not\r\n // permanently stop pagination. The sentinel stays armed, and scrolling away and back\r\n // (a real change in its intersection state) retries, mirroring the legacy CRM's\r\n // `react-window-infinite-loader` comment: \"ignore — retries on further scroll.\"\r\n })\r\n .finally(() => {\r\n loadingMoreRef.current = false;\r\n if (seq === seqRef.current) setLoadingMore(false);\r\n });\r\n }, [loadPage]);\r\n\r\n const [containerEl, setContainerEl] = useState<HTMLElement | null>(null);\r\n const [sentinelEl, setSentinelEl] = useState<HTMLElement | null>(null);\r\n // Refs, not the `loadMore`/`hasMore` values directly, so the observer effect below does not\r\n // need to re-run (tear down and recreate the observer) every time either one changes.\r\n const loadMoreRef = useRef(loadMore);\r\n loadMoreRef.current = loadMore;\r\n\r\n useEffect(() => {\r\n if (!containerEl || !sentinelEl) return;\r\n const observer = new IntersectionObserver(\r\n ([entry]) => {\r\n if (entry?.isIntersecting) loadMoreRef.current();\r\n },\r\n { root: containerEl, rootMargin: '160px' },\r\n );\r\n observer.observe(sentinelEl);\r\n return () => observer.disconnect();\r\n }, [containerEl, sentinelEl]);\r\n\r\n return {\r\n items,\r\n loading,\r\n loadingMore,\r\n hasMore,\r\n error,\r\n containerRef: setContainerEl,\r\n sentinelRef: setSentinelEl,\r\n };\r\n}\r\n","import { useCallback, useEffect, useState } from 'react';\r\nimport { Loader2, Phone, Search, User, Users, X } from 'lucide-react';\r\nimport { useSoftphone } from '../../react/index.js';\r\nimport { ContactDetail } from './ContactDetail.js';\r\nimport { useInfiniteList } from '../lib/useInfiniteList.js';\r\nimport type { Contact } from '../../core/types.js';\r\nimport type { ContactAction, ContactsSource } from '../types.js';\r\nimport { initials } from '../lib/format.js';\r\n\r\nconst PAGE = 50;\r\n\r\n/**\r\n * The Contactos tab — decoupled. Data comes from an injected `ContactsSource`; contacts are\r\n * `Contact { id, name, phone }` (never `wa_id`, SPEC §4). Tapping a contact always opens its detail\r\n * page (`ContactDetail`) — `contactAction` customises the ONE extra row on it, not what tapping the\r\n * list itself does; there is no bypass of the detail page from here.\r\n */\r\nexport function ContactsTab({\r\n source,\r\n contactAction,\r\n}: Readonly<{\r\n source: ContactsSource;\r\n contactAction?: ContactAction;\r\n}>) {\r\n const softphone = useSoftphone();\r\n const [search, setSearch] = useState('');\r\n const [debouncedSearch, setDebouncedSearch] = useState('');\r\n const [selected, setSelected] = useState<Contact | null>(null);\r\n\r\n useEffect(() => {\r\n const t = setTimeout(() => setDebouncedSearch(search), 200);\r\n return () => clearTimeout(t);\r\n }, [search]);\r\n\r\n // `loadPage`'s identity is `useInfiniteList`'s reset signal — it must only change once the\r\n // DEBOUNCED term changes, or every keystroke would restart the list instead of the fetch it\r\n // triggers being debounced.\r\n const loadPage = useCallback(\r\n (skip: number) =>\r\n source({ search: debouncedSearch, skip, limit: PAGE }).then((page) => ({\r\n items: page.items,\r\n hasMore: skip + page.items.length < page.total,\r\n })),\r\n [source, debouncedSearch],\r\n );\r\n const {\r\n items,\r\n loading: loadingPage,\r\n loadingMore,\r\n hasMore,\r\n containerRef,\r\n sentinelRef,\r\n } = useInfiniteList(loadPage);\r\n // The 200ms debounce above delays `debouncedSearch` (and with it `loadPage`'s identity), so the\r\n // very first keystroke would otherwise keep showing the PREVIOUS term's results for up to 200ms\r\n // with no loading indicator. Comparing the two search values catches exactly that window.\r\n const loading = loadingPage || search !== debouncedSearch;\r\n\r\n return (\r\n <div className=\"cv-view\">\r\n <div className=\"cv-list-head\">\r\n {/*\r\n A wrapper, not a change to `.cv-search` itself — that class is shared with the transfer\r\n input in CallScreen, which wants none of this (no icon, no clear button, a different\r\n affordance entirely). The icon and clear button are additive, scoped to this field only.\r\n */}\r\n <div className=\"cv-search-field\">\r\n <Search className=\"cv-search-icon\" size={15} aria-hidden />\r\n <input\r\n className=\"cv-search cv-search--icon\"\r\n value={search}\r\n onChange={(e) => setSearch(e.target.value)}\r\n placeholder=\"Buscar contactos\"\r\n aria-label=\"Buscar contactos\"\r\n />\r\n {search ? (\r\n <button\r\n type=\"button\"\r\n className=\"cv-search-clear\"\r\n onClick={() => setSearch('')}\r\n aria-label=\"Limpiar búsqueda\"\r\n >\r\n <X size={14} />\r\n </button>\r\n ) : null}\r\n </div>\r\n </div>\r\n\r\n <div className=\"cv-list\" ref={containerRef}>\r\n {loading ? (\r\n // The spinner alone was silent to a screen reader — nothing else on this state carries\r\n // the word \"loading\" for it to announce. `role=\"status\"` + real text fixes both the\r\n // accessibility gap and, incidentally, gives the icon something to be decorative NEXT TO\r\n // rather than being the sole carrier of the information itself.\r\n <div className=\"cv-empty\" role=\"status\">\r\n <Loader2 className=\"cv-empty-spinner\" size={18} aria-hidden />\r\n <span className=\"cv-empty-title\">Cargando…</span>\r\n </div>\r\n ) : items.length === 0 ? (\r\n <div className=\"cv-empty\">\r\n <span className=\"cv-empty-icon\" aria-hidden>\r\n <Users size={20} />\r\n </span>\r\n <p className=\"cv-empty-title\">{search ? 'Sin resultados' : 'No tienes contactos'}</p>\r\n <p className=\"cv-empty-sub\">\r\n {search ? `Nada coincide con «${search}».` : 'Tus contactos con teléfono aparecerán aquí.'}\r\n </p>\r\n </div>\r\n ) : (\r\n <>\r\n {items.map((c) => (\r\n // A row, not a button: the name area and the call action are separate controls, so\r\n // neither is nested inside the other (nested interactives are invalid + inaccessible).\r\n <div key={c.id} className=\"cv-item\">\r\n <span className=\"cv-item-avatar\" aria-hidden>\r\n {initials(c.name) === '#' ? <User size={17} /> : initials(c.name)}\r\n </span>\r\n {/* Always enabled — tapping a contact opens its detail page unconditionally now.\r\n `contactAction` decides whether THAT page has an extra row, not whether this does\r\n anything at all. */}\r\n <button type=\"button\" className=\"cv-item-main\" onClick={() => setSelected(c)}>\r\n <span className=\"cv-item-name\">{c.name ?? c.phone}</span>\r\n <span className=\"cv-item-sub\">{c.phone}</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n className=\"cv-item-action\"\r\n data-tone=\"accent\"\r\n aria-label={`Llamar a ${c.name ?? c.phone}`}\r\n onClick={() => void softphone.call(c.phone)}\r\n >\r\n <Phone size={16} />\r\n </button>\r\n </div>\r\n ))}\r\n {/* The scroll-triggered \"load more\" marker — only rendered while there IS more, so the\r\n observer (see `useInfiniteList`) naturally stops firing once the list is exhausted. */}\r\n {hasMore ? <div ref={sentinelRef} className=\"cv-list-sentinel\" aria-hidden /> : null}\r\n {loadingMore ? (\r\n <div className=\"cv-list-loading-more\" role=\"status\" aria-label=\"Cargando más contactos\">\r\n <Loader2 className=\"cv-list-loading-more-spinner\" size={14} aria-hidden />\r\n </div>\r\n ) : null}\r\n </>\r\n )}\r\n </div>\r\n\r\n {/* Kept mounted underneath the list, not swapped in its place — so the list's own scroll\r\n position and size measurements survive a round trip through the detail page and back. */}\r\n {selected ? (\r\n <ContactDetail\r\n contact={selected}\r\n onBack={() => setSelected(null)}\r\n {...(contactAction ? { contactAction } : {})}\r\n />\r\n ) : null}\r\n </div>\r\n );\r\n}\r\n","import { PhoneIncoming, PhoneMissed, PhoneOutgoing } from 'lucide-react';\r\nimport type { CallHistoryEntry, CallOutcome, ContactActionIcon } from '../types.js';\r\n\r\n/** The SDK's own vocabulary (never the PBX's raw disposition string — see `coventia/sources.ts`). */\r\nexport const OUTCOME_LABELS: Record<CallOutcome, string> = {\r\n 'no-answer': 'No contestada',\r\n busy: 'Ocupada',\r\n cancelled: 'Cancelada',\r\n failed: 'Fallida',\r\n unavailable: 'No disponible',\r\n};\r\n\r\n/** A literal clock time — callers that also show the date (a day header, a full timestamp) say it\r\n * separately rather than repeating it here. */\r\nexport function timeLabel(at: Date): string {\r\n return at.toLocaleTimeString('es-ES', { hour: '2-digit', minute: '2-digit' });\r\n}\r\n\r\n/** Date AND time together, spelled out — the call detail page's own \"Fecha y hora\" row, which has no\r\n * day-group header above it to lean on the way a list row does. */\r\nexport function fullDateLabel(at: Date): string {\r\n return at.toLocaleString('es-ES', {\r\n day: '2-digit',\r\n month: 'long',\r\n year: 'numeric',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n });\r\n}\r\n\r\nexport function Icon({ entry }: Readonly<{ entry: CallHistoryEntry }>) {\r\n if (entry.missed) return <PhoneMissed size={16} />;\r\n return entry.direction === 'inbound' ? <PhoneIncoming size={16} /> : <PhoneOutgoing size={16} />;\r\n}\r\n\r\n/**\r\n * The same icon `Icon` renders, but as a bare component reference rather than a rendered element —\r\n * what `DetailRow`'s `icon` prop needs (it renders the icon itself, at its own size). Kept separate\r\n * from `Icon` rather than having `Icon` take an optional `size` and reusing it two ways: `Icon` is a\r\n * component meant to be written as `<Icon entry={e} />`; this is a value meant to be passed around.\r\n */\r\nexport function statusIcon(entry: CallHistoryEntry): ContactActionIcon {\r\n if (entry.missed) return PhoneMissed;\r\n return entry.direction === 'inbound' ? PhoneIncoming : PhoneOutgoing;\r\n}\r\n\r\n/**\r\n * Three status hues, not two — matching the legacy CRM's own split (emerald/sky/rose) rather than\r\n * collapsing an answered outgoing call into the same colour as an answered incoming one. Direction\r\n * is already the icon's shape; this is a SEPARATE signal (did it connect) that direction alone can't\r\n * carry once \"connected\" itself gets a colour at all.\r\n */\r\nexport function statusTone(entry: CallHistoryEntry): 'accent' | 'info' | 'danger' {\r\n if (entry.missed) return 'danger';\r\n return entry.direction === 'inbound' ? 'accent' : 'info';\r\n}\r\n","import { useEffect, useState } from 'react';\r\nimport { ArrowLeft, ArrowRight, CalendarClock, Hash, Loader2, Mic, Phone, Timer, User } from 'lucide-react';\r\nimport { useSoftphone } from '../../react/index.js';\r\nimport { useIntlFormatter } from '../dialing/format-number.js';\r\nimport { DetailRow } from './DetailRow.js';\r\nimport { Icon, OUTCOME_LABELS, statusIcon, statusTone, timeLabel, fullDateLabel } from './history-format.js';\r\nimport { formatDuration } from '../lib/format.js';\r\nimport type { CallDetail, CallHandler, CallHistoryEntry } from '../types.js';\r\n\r\n/**\r\n * Who handled the call, in order — \"Ana · 102 → Bruno · 100\", the LAST hop (the one it ended with)\r\n * highlighted. A hop whose extension never resolved to an org member falls back to \"Ext. 102\" rather\r\n * than disappearing — unifying `CallHandler`'s two sources (a real handler, a bare extension) into one\r\n * rendering, since both are the same shape by the time they reach here (see `toHandledBy`).\r\n */\r\nfunction HandlerChain({ handlers }: Readonly<{ handlers: readonly CallHandler[] }>) {\r\n return (\r\n <span className=\"cv-detail-handlers\">\r\n {handlers.map((h, i) => {\r\n const isLast = i === handlers.length - 1;\r\n const label = h.name ?? `Ext. ${h.extension}`;\r\n return (\r\n <span key={`${h.extension}-${i}`} className=\"cv-detail-handler-hop\">\r\n {i > 0 ? <ArrowRight size={12} className=\"cv-detail-handler-arrow\" aria-hidden /> : null}\r\n <span className=\"cv-detail-handler-chip\" data-tone={isLast ? 'accent' : undefined}>\r\n {label}\r\n {h.name ? <span className=\"cv-detail-handler-ext\">· {h.extension}</span> : null}\r\n </span>\r\n </span>\r\n );\r\n })}\r\n </span>\r\n );\r\n}\r\n\r\n/**\r\n * A call's detail page — identity, its recording(s) if any, and the metadata the legacy CRM's own\r\n * `CallDetail` showed. Ported close to that implementation on purpose: unlike `contactAction`, there\r\n * is no partner customisation point here to design around — the Historial tab is Coventia's data,\r\n * always, so this is a direct port rather than a generalised API.\r\n *\r\n * Opens over the list when a row is tapped (`HistoryTab` owns that transition); this component only\r\n * knows how to show ONE call and get back out.\r\n */\r\nexport function HistoryDetail({\r\n entry,\r\n onBack,\r\n}: Readonly<{\r\n entry: CallHistoryEntry;\r\n onBack: () => void;\r\n}>) {\r\n const softphone = useSoftphone();\r\n const formatIntl = useIntlFormatter();\r\n const [detail, setDetail] = useState<CallDetail | null>(null);\r\n const [loadingDetail, setLoadingDetail] = useState(false);\r\n\r\n // The enriched fetch — signed recording URLs, and the SAME handler chain with names resolved. Only\r\n // when there is something to enrich: `entry.loadDetail` is absent otherwise (see `CallHistoryEntry`).\r\n useEffect(() => {\r\n const load = entry.loadDetail;\r\n if (!load) return;\r\n let cancelled = false;\r\n setLoadingDetail(true);\r\n void load()\r\n .then((d) => !cancelled && setDetail(d))\r\n .catch(() => {\r\n // Kept as the list's own (unenriched) data — `loadingDetail` still clears, so the recording\r\n // section's own \"couldn't load\" state renders instead of spinning forever.\r\n })\r\n .finally(() => !cancelled && setLoadingDetail(false));\r\n return () => {\r\n cancelled = true;\r\n };\r\n }, [entry]);\r\n\r\n const formatted = formatIntl(entry.number);\r\n const name = entry.name ?? formatted;\r\n const handledBy = detail?.handledBy ?? entry.handledBy;\r\n const recordingUrls = detail?.recordingUrls ?? [];\r\n const loadingRecording = entry.recorded && loadingDetail && recordingUrls.length === 0;\r\n const statusText = entry.missed ? (entry.outcome ? OUTCOME_LABELS[entry.outcome] : 'Perdida') : 'Contestada';\r\n const handlerLabel =\r\n handledBy.length > 1 ? 'Ruta de la llamada' : entry.direction === 'outbound' ? 'Realizada por' : 'Atendida por';\r\n\r\n return (\r\n <div className=\"cv-detail\" role=\"region\" aria-label={name}>\r\n <div className=\"cv-detail-head\">\r\n <button type=\"button\" className=\"cv-detail-back\" onClick={onBack}>\r\n <ArrowLeft size={16} aria-hidden />\r\n Historial\r\n </button>\r\n </div>\r\n\r\n <div className=\"cv-detail-body\">\r\n <div className=\"cv-detail-identity\">\r\n <span className=\"cv-detail-avatar\" data-tone={statusTone(entry)} aria-hidden>\r\n <Icon entry={entry} />\r\n </span>\r\n <h2 className=\"cv-detail-name\" data-tone={entry.missed ? 'danger' : undefined}>\r\n {name}\r\n </h2>\r\n <p className=\"cv-detail-meta\">\r\n {statusText} · {timeLabel(entry.at)}\r\n </p>\r\n </div>\r\n\r\n {entry.recorded ? (\r\n <div className=\"cv-detail-recording\">\r\n {loadingRecording ? (\r\n <div className=\"cv-detail-recording-status\">\r\n <Loader2 size={14} className=\"cv-detail-recording-spinner\" aria-hidden />\r\n Cargando grabación…\r\n </div>\r\n ) : recordingUrls.length > 0 ? (\r\n <>\r\n <p className=\"cv-detail-recording-label\">\r\n {recordingUrls.length === 1 ? 'Grabación' : 'Grabaciones'}\r\n </p>\r\n {recordingUrls.map((url) => (\r\n <audio key={url} controls src={url} className=\"cv-detail-audio\" preload=\"metadata\" />\r\n ))}\r\n </>\r\n ) : (\r\n <p className=\"cv-detail-recording-status cv-detail-recording-status--warn\">\r\n No se pudo cargar la grabación ahora. Inténtalo de nuevo más tarde.\r\n </p>\r\n )}\r\n </div>\r\n ) : (\r\n <p className=\"cv-detail-recording-status\">\r\n <Mic size={14} aria-hidden />\r\n Esta llamada no se grabó.\r\n </p>\r\n )}\r\n\r\n <div className=\"cv-detail-rows\">\r\n <DetailRow icon={statusIcon(entry)} eyebrow=\"Estado\" text={statusText} />\r\n <DetailRow icon={CalendarClock} eyebrow=\"Fecha y hora\" text={fullDateLabel(entry.at)} />\r\n {entry.durationSec > 0 ? (\r\n <DetailRow icon={Timer} eyebrow=\"Duración\" text={formatDuration(entry.durationSec)} />\r\n ) : null}\r\n <DetailRow icon={Phone} eyebrow=\"Número\" text={formatted} />\r\n {handledBy.length > 0 ? (\r\n <DetailRow icon={User} eyebrow={handlerLabel} text={<HandlerChain handlers={handledBy} />} />\r\n ) : null}\r\n {entry.direction === 'inbound' && entry.did ? (\r\n <DetailRow icon={Hash} eyebrow=\"Número marcado (DID)\" text={formatIntl(entry.did)} />\r\n ) : null}\r\n </div>\r\n </div>\r\n\r\n <div className=\"cv-detail-foot\">\r\n <button\r\n type=\"button\"\r\n className=\"cv-btn cv-btn--accent cv-detail-call\"\r\n onClick={() => void softphone.call(entry.number)}\r\n >\r\n <Phone size={16} aria-hidden />\r\n Llamar\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { useCallback, useEffect, useRef, useState } from 'react';\r\nimport { Check, ChevronDown, Loader2, Mic, Phone, Users } from 'lucide-react';\r\nimport { useSoftphone } from '../../react/index.js';\r\nimport { useInfiniteList } from '../lib/useInfiniteList.js';\r\nimport { useIntlFormatter } from '../dialing/format-number.js';\r\nimport { HistoryDetail } from './HistoryDetail.js';\r\nimport { Icon, OUTCOME_LABELS, statusTone, timeLabel } from './history-format.js';\r\nimport type { AgentsDirectory, CallHistoryEntry, HistorySource } from '../types.js';\r\nimport { formatDuration } from '../lib/format.js';\r\n\r\nconst PAGE = 30;\r\ntype StatusFilter = 'all' | 'missed';\r\n\r\nfunction startOfDay(at: Date): number {\r\n return new Date(at.getFullYear(), at.getMonth(), at.getDate()).getTime();\r\n}\r\n\r\nfunction dayLabel(at: Date, now: number): string {\r\n const diffDays = Math.round((startOfDay(new Date(now)) - startOfDay(at)) / 86_400_000);\r\n if (diffDays === 0) return 'Hoy';\r\n if (diffDays === 1) return 'Ayer';\r\n return at.toLocaleDateString('es-ES', { day: 'numeric', month: 'long' });\r\n}\r\n\r\n/** Consecutive rows sharing a day label, newest-first — the server already sorts that way. */\r\nfunction groupByDay(\r\n entries: readonly CallHistoryEntry[],\r\n now: number,\r\n): ReadonlyArray<{ readonly label: string; readonly rows: readonly CallHistoryEntry[] }> {\r\n const groups: Array<{ label: string; rows: CallHistoryEntry[] }> = [];\r\n for (const e of entries) {\r\n const label = dayLabel(e.at, now);\r\n const last = groups.at(-1);\r\n if (last && last.label === label) last.rows.push(e);\r\n else groups.push({ label, rows: [e] });\r\n }\r\n return groups;\r\n}\r\n\r\n/**\r\n * \"Todas las personas\" / \"Mis llamadas · X\" / a specific person — the Historial tab's filter by who\r\n * handled the call. Own combobox, same shape as `CountryPicker`'s (a `<button>` + a positioned\r\n * `<div>`, no external popover lib) but not sharing its code: the two pickers have no reason to\r\n * change together, and duplicating this little outside-click/Escape handling is cheaper than coupling\r\n * them through a shared abstraction neither actually needs.\r\n */\r\nfunction PersonFilter({\r\n value,\r\n directory,\r\n onChange,\r\n}: Readonly<{\r\n /** '' means everyone. */\r\n value: string;\r\n directory: AgentsDirectory;\r\n onChange: (userId: string) => void;\r\n}>) {\r\n const [open, setOpen] = useState(false);\r\n const rootRef = useRef<HTMLDivElement>(null);\r\n\r\n // Close on outside click / Escape. On the SHADOW ROOT's node when there is one — inside a shadow\r\n // tree, `document` click targets are retargeted to the host, so `contains()` against the host would\r\n // report every internal click as \"outside\" and the popover would never open (see CountryPicker).\r\n useEffect(() => {\r\n if (!open) return;\r\n const root = rootRef.current?.getRootNode() ?? document;\r\n const onDown = (e: Event) => {\r\n if (!rootRef.current?.contains(e.target as Node)) setOpen(false);\r\n };\r\n const onKey = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') setOpen(false);\r\n };\r\n root.addEventListener('pointerdown', onDown);\r\n document.addEventListener('keydown', onKey);\r\n return () => {\r\n root.removeEventListener('pointerdown', onDown);\r\n document.removeEventListener('keydown', onKey);\r\n };\r\n }, [open]);\r\n\r\n const options: ReadonlyArray<{ readonly v: string; readonly label: string }> = [\r\n { v: '', label: 'Todas las personas' },\r\n ...(directory.me ? [{ v: directory.me.userId, label: `Mis llamadas · ${directory.me.name ?? 'Yo'}` }] : []),\r\n ...directory.people\r\n .filter((p) => !directory.me || p.userId !== directory.me.userId)\r\n .map((p) => ({ v: p.userId, label: p.name ?? 'Sin nombre' })),\r\n ];\r\n const label = options.find((o) => o.v === value)?.label ?? 'Todas las personas';\r\n\r\n return (\r\n <div className=\"cv-person-filter\" ref={rootRef}>\r\n <button\r\n type=\"button\"\r\n className=\"cv-person-filter-chip\"\r\n onClick={() => setOpen((o) => !o)}\r\n aria-haspopup=\"listbox\"\r\n aria-expanded={open}\r\n >\r\n <Users size={13} aria-hidden />\r\n <span className=\"cv-person-filter-label\">{label}</span>\r\n <ChevronDown size={13} className=\"cv-person-filter-caret\" data-open={open} aria-hidden />\r\n </button>\r\n {open ? (\r\n <div className=\"cv-person-filter-pop\" role=\"listbox\">\r\n {options.map((opt) => (\r\n <button\r\n key={opt.v || 'all'}\r\n type=\"button\"\r\n role=\"option\"\r\n aria-selected={opt.v === value}\r\n className=\"cv-person-filter-item\"\r\n onClick={() => {\r\n onChange(opt.v);\r\n setOpen(false);\r\n }}\r\n >\r\n <span className=\"cv-person-filter-name\">{opt.label}</span>\r\n <Check size={14} className=\"cv-person-filter-check\" data-on={opt.v === value} aria-hidden />\r\n </button>\r\n ))}\r\n </div>\r\n ) : null}\r\n </div>\r\n );\r\n}\r\n\r\n/**\r\n * The Historial tab — decoupled. Entries come from an injected `HistorySource` (SPEC §4). Tapping a\r\n * row always opens its detail page (`HistoryDetail`) — the row's own call button places a call\r\n * directly, without opening it. Same split `ContactsTab`/`ContactDetail` already settled on, for the\r\n * same reason: a row-wide tap target and a specific, separate action live at different button.\r\n *\r\n * The two filters (status, person) are local UI state — `HistorySource` merely accepts them as\r\n * optional params, same as `ContactsSource` accepts `search`, so a host's own override can honour\r\n * them or ignore them. The person directory behind the second filter is different: it is always\r\n * Coventia's own org membership (there is no partner override point for it, unlike `contacts`), so\r\n * it is read straight off `softphone.sources` rather than threaded through as a prop.\r\n */\r\nexport function HistoryTab({ source }: Readonly<{ source: HistorySource }>) {\r\n const softphone = useSoftphone();\r\n const formatIntl = useIntlFormatter();\r\n const now = Date.now();\r\n const [status, setStatus] = useState<StatusFilter>('all');\r\n const [agentId, setAgentId] = useState(''); // '' = everyone\r\n const [directory, setDirectory] = useState<AgentsDirectory | null>(null);\r\n const [selected, setSelected] = useState<CallHistoryEntry | null>(null);\r\n\r\n // Fetched once, not paginated — an org's phone members, not its calls. Absent (and the person\r\n // filter simply does not render) when there is no Coventia backend at all: a bare dialer, or a\r\n // host-supplied `history` override with nothing behind `softphone.sources`.\r\n useEffect(() => {\r\n const listAgents = softphone.sources?.listAgents;\r\n if (!listAgents) return;\r\n let cancelled = false;\r\n void listAgents()\r\n .then((d) => !cancelled && setDirectory(d))\r\n .catch(() => {});\r\n return () => {\r\n cancelled = true;\r\n };\r\n }, [softphone]);\r\n\r\n /**\r\n * `HistorySource` has no `total` (unlike `ContactsSource`), so \"is there another page\" is read\r\n * off the page itself: a page shorter than what was asked for is the last one. A page exactly\r\n * `PAGE` long that happens to be the last one costs one extra request that returns zero rows —\r\n * an acceptable trade for not having to widen the source contract just for this.\r\n */\r\n const loadPage = useCallback(\r\n (skip: number) =>\r\n source({\r\n skip,\r\n limit: PAGE,\r\n missed: status === 'missed',\r\n ...(agentId ? { userId: agentId } : {}),\r\n }).then((rows) => ({ items: rows, hasMore: rows.length === PAGE })),\r\n [source, status, agentId],\r\n );\r\n const { items: entries, loading, loadingMore, hasMore, containerRef, sentinelRef } = useInfiniteList(loadPage);\r\n const groups = groupByDay(entries, now);\r\n\r\n return (\r\n <div className=\"cv-view\">\r\n <div className=\"cv-list-head\">\r\n <div className=\"cv-segmented\" role=\"tablist\" aria-label=\"Filtrar por estado\">\r\n {(['all', 'missed'] as const satisfies readonly StatusFilter[]).map((key) => (\r\n <button\r\n key={key}\r\n type=\"button\"\r\n role=\"tab\"\r\n aria-selected={status === key}\r\n className=\"cv-segmented-btn\"\r\n onClick={() => setStatus(key)}\r\n >\r\n {key === 'all' ? 'Todas' : 'Perdidas'}\r\n </button>\r\n ))}\r\n </div>\r\n {directory ? <PersonFilter value={agentId} directory={directory} onChange={setAgentId} /> : null}\r\n </div>\r\n\r\n <div className=\"cv-list\" ref={containerRef}>\r\n {loading && <div className=\"cv-empty\">Cargando…</div>}\r\n {!loading && entries.length === 0 && (\r\n <div className=\"cv-empty\">\r\n {status === 'missed' ? 'Sin llamadas perdidas' : 'Sin llamadas recientes'}\r\n </div>\r\n )}\r\n {!loading &&\r\n groups.map((group) => (\r\n <div key={group.label}>\r\n <div className=\"cv-history-day\">{group.label}</div>\r\n {group.rows.map((e) => (\r\n <div key={e.id} className=\"cv-item\">\r\n <span className=\"cv-item-avatar\" data-tone={statusTone(e)} aria-hidden>\r\n <Icon entry={e} />\r\n </span>\r\n {/* Always enabled — tapping a call opens its detail page unconditionally, the same\r\n way a contact row does. The call button beside it is the only way to call from\r\n here now; recordings/handler info live on the detail page, not the list. */}\r\n <button\r\n type=\"button\"\r\n className=\"cv-item-main\"\r\n onClick={() => setSelected(e)}\r\n >\r\n <span className=\"cv-item-name\" data-tone={e.missed ? 'danger' : undefined}>\r\n {e.name ?? formatIntl(e.number)}\r\n </span>\r\n <span className=\"cv-item-sub\">\r\n <span className=\"tabular-nums\">{timeLabel(e.at)}</span>\r\n {e.missed ? (\r\n <span className=\"cv-item-sub-outcome\">\r\n {' '}\r\n · {e.outcome ? OUTCOME_LABELS[e.outcome] : 'Perdida'}\r\n </span>\r\n ) : (\r\n e.durationSec > 0 && ` · ${formatDuration(e.durationSec)}`\r\n )}\r\n {/* Informational only — the recording itself plays from the detail page now.\r\n A hint that opening the row is worth it, not an action of its own. */}\r\n {e.recorded ? <Mic size={11} className=\"cv-item-sub-rec\" aria-label=\"Grabada\" /> : null}\r\n </span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n className=\"cv-item-action\"\r\n data-tone=\"accent\"\r\n aria-label={`Llamar a ${e.name ?? e.number}`}\r\n onClick={() => void softphone.call(e.number)}\r\n >\r\n <Phone size={16} />\r\n </button>\r\n </div>\r\n ))}\r\n </div>\r\n ))}\r\n {!loading && hasMore ? <div ref={sentinelRef} className=\"cv-list-sentinel\" aria-hidden /> : null}\r\n {loadingMore ? (\r\n <div className=\"cv-list-loading-more\" role=\"status\" aria-label=\"Cargando más llamadas\">\r\n <Loader2 className=\"cv-list-loading-more-spinner\" size={14} aria-hidden />\r\n </div>\r\n ) : null}\r\n </div>\r\n\r\n {/* Kept mounted underneath the list, not swapped in its place — so the list's own scroll\r\n position and size measurements survive a round trip through the detail page and back. */}\r\n {selected ? <HistoryDetail entry={selected} onBack={() => setSelected(null)} /> : null}\r\n </div>\r\n );\r\n}\r\n","import type { ReactNode } from 'react';\r\n\r\n/**\r\n * One labeled group on the Ajustes tab — a title, and a bordered body holding its rows (dividers\r\n * between them, no border of their own; see `.cv-settings-section-body`'s own CSS comment for why).\r\n *\r\n * Ajustes started as a flat list of two rows (Micrófono, Altavoces) with no grouping at all — fine\r\n * for two rows, unreadable the moment a third, unrelated setting arrives with nothing to tell it\r\n * apart from the device rows above it. This is the container every future settings group reuses, so\r\n * \"add a setting\" never again means \"invent a new layout for it.\"\r\n */\r\nexport function SettingsSection({\r\n title,\r\n children,\r\n}: Readonly<{\r\n title: string;\r\n children: ReactNode;\r\n}>) {\r\n return (\r\n <section className=\"cv-settings-section\">\r\n <h3 className=\"cv-settings-section-title\">{title}</h3>\r\n <div className=\"cv-settings-section-body\">{children}</div>\r\n </section>\r\n );\r\n}\r\n","import { DevicePickers } from './DevicePicker.js';\r\nimport { SettingsSection } from './SettingsSection.js';\r\n\r\n/**\r\n * The Ajustes tab: choose the microphone and the speaker (SPEC §7 Phase 2 — device management).\r\n *\r\n * Always rendered — unlike Contactos/Historial, it needs no host-supplied data source. A microphone\r\n * and a speaker are not optional parts of a phone.\r\n *\r\n * Grouped into `SettingsSection`s rather than one flat list — see that component's own comment. When\r\n * the next setting arrives, it gets its own `<SettingsSection title=\"…\">`, not a third row bolted\r\n * onto \"Dispositivos\".\r\n *\r\n * The closing note is deliberate, not filler: with a single section this tab reads as unfinished\r\n * rather than minimal, and says so — a roadmap hint, not an apology — rather than leaving the rest\r\n * of the tab blank.\r\n */\r\nexport function SettingsTab() {\r\n return (\r\n <div className=\"cv-view cv-settings\">\r\n <div className=\"cv-settings-body\">\r\n <SettingsSection title=\"Dispositivos\">\r\n <DevicePickers />\r\n </SettingsSection>\r\n <p className=\"cv-settings-more\">Más ajustes se irán añadiendo próximamente.</p>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { useCallback, useEffect, useState } from 'react';\r\nimport { isWebRtcSupported } from '../../core/env.js';\r\n\r\nexport type MicState = 'checking' | 'prompting' | 'warming' | 'ready' | 'denied' | 'unsupported';\r\n\r\n/**\r\n * Microphone permission, as a state machine.\r\n *\r\n * Extracted from `MicPermissionGate` so `SoftphoneWidget` can gate itself: a softphone without a\r\n * microphone is not a softphone, so asking every integrator to remember a wrapper component is\r\n * asking them to remember not to ship something broken.\r\n *\r\n * **`warming` is the part that matters, and the part the SDK had lost.**\r\n *\r\n * `navigator.permissions.query({name:'microphone'})` saying `granted` is NOT enough. Several\r\n * browsers still prompt on the first `getUserMedia` of a page session, so a gate that trusts the\r\n * query and skips straight to `ready` moves the prompt from panel-open time — where the user is\r\n * looking at a phone and expects it — to **the middle of the first call**, where a modal steals\r\n * focus from a ringing conversation.\r\n *\r\n * So `getUserMedia` runs on EVERY mount, even when already granted. It verifies the mic works in\r\n * this session and primes the track, which is why the old CRM gate did it and why dropping it during\r\n * the port was a silent regression: it only shows up on a real call, on a real machine, once.\r\n *\r\n * The tracks are stopped immediately — we wanted the grant, not the microphone. Holding them open is\r\n * the documented Twilio mic-leak (the browser tab shows a recording indicator forever).\r\n */\r\nexport function useMicPermission(): { state: MicState; request: () => Promise<void> } {\r\n const [state, setState] = useState<MicState>('checking');\r\n\r\n /** Take the mic, confirm it opens, give it straight back. */\r\n const warm = useCallback(async () => {\r\n try {\r\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\r\n for (const track of stream.getTracks()) track.stop();\r\n setState('ready');\r\n } catch {\r\n setState('denied');\r\n }\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (!isWebRtcSupported()) {\r\n setState('unsupported');\r\n return;\r\n }\r\n\r\n let cancelled = false;\r\n let status: PermissionStatus | null = null;\r\n\r\n const apply = (permission: PermissionState): void => {\r\n if (cancelled) return;\r\n if (permission === 'denied') {\r\n setState('denied');\r\n } else if (permission === 'granted') {\r\n // Granted, and STILL warm it — see the note above.\r\n setState('warming');\r\n void warm();\r\n } else {\r\n setState('prompting');\r\n }\r\n };\r\n\r\n void (async () => {\r\n try {\r\n status = await navigator.permissions.query({ name: 'microphone' as PermissionName });\r\n if (cancelled) return;\r\n apply(status.state);\r\n // The user can revoke mid-session from the browser's own UI; without this the widget keeps\r\n // offering a dialer that cannot open a microphone.\r\n status.onchange = () => status && apply(status.state);\r\n } catch {\r\n // Firefox has historically not supported querying 'microphone'. Not knowing is fine — ask.\r\n if (!cancelled) setState('prompting');\r\n }\r\n })();\r\n\r\n return () => {\r\n cancelled = true;\r\n if (status) status.onchange = null;\r\n };\r\n }, [warm]);\r\n\r\n return { state, request: warm };\r\n}\r\n","/**\r\n * How to un-block the microphone, per browser.\r\n *\r\n * **Steps in the widget rather than a link out**, which was the first instinct and is worse:\r\n *\r\n * - A support URL is somebody else's contract. Chrome's article checks out\r\n * (\"Utilizar la cámara y el micrófono en Chrome\"), but Mozilla's site answers every request —\r\n * including a deliberately fake slug — with a bot-challenge page, so no Firefox URL can be\r\n * verified, and every Edge slug tried returned 404. Shipping a link that might 404 is a dead end\r\n * inside a dead end.\r\n * - It is three clicks away in the browser the user is already looking at. Sending them to a\r\n * support site to read the same three clicks is a context switch that solves nothing.\r\n * - Our copy is Spanish-only by design (SPEC §2.4); a support page follows its own locale rules.\r\n *\r\n * The verified Chrome article is still offered where it applies, as a last resort rather than the\r\n * first answer.\r\n */\r\n\r\nexport interface UnblockGuide {\r\n readonly steps: readonly string[];\r\n /** Only present where the URL has been verified to exist and to be about microphone permission. */\r\n readonly url?: string;\r\n}\r\n\r\ntype BrowserId = 'firefox' | 'edge' | 'chromium' | 'safari' | 'unknown';\r\n\r\n/**\r\n * Which browser is this, for help purposes only.\r\n *\r\n * UA sniffing, knowingly: it decides which three sentences to show, so being wrong costs a slightly\r\n * off instruction, not a broken feature. Order matters — Edge and most Chromium forks put \"Chrome\"\r\n * in their UA, and Chrome puts \"Safari\" in its.\r\n */\r\nfunction detectBrowser(ua: string): BrowserId {\r\n if (/firefox|fxios/i.test(ua)) return 'firefox';\r\n if (/edg\\//i.test(ua)) return 'edge';\r\n if (/chrome|chromium|crios/i.test(ua)) return 'chromium';\r\n if (/safari/i.test(ua)) return 'safari';\r\n return 'unknown';\r\n}\r\n\r\n/** Verified: returns \"Utilizar la cámara y el micrófono en Chrome\" in Spanish. */\r\nconst CHROME_HELP = 'https://support.google.com/chrome/answer/2693767?hl=es';\r\n\r\nconst GUIDES: Record<BrowserId, UnblockGuide> = {\r\n chromium: {\r\n steps: [\r\n 'Haz clic en el icono 🔒 a la izquierda de la dirección web.',\r\n 'Busca «Micrófono» y cámbialo a «Permitir».',\r\n 'Recarga la página.',\r\n ],\r\n url: CHROME_HELP,\r\n },\r\n // Edge is Chromium: same padlock, same panel. The article is Chrome's, so it is offered but not\r\n // led with — the steps above match what an Edge user actually sees.\r\n edge: {\r\n steps: [\r\n 'Haz clic en el icono 🔒 a la izquierda de la dirección web.',\r\n 'Busca «Micrófono» y cámbialo a «Permitir».',\r\n 'Recarga la página.',\r\n ],\r\n },\r\n firefox: {\r\n steps: [\r\n 'Haz clic en el icono de micrófono tachado en la barra de direcciones.',\r\n 'Pulsa la «✕» junto a «Bloqueado» para quitar el bloqueo.',\r\n 'Recarga la página.',\r\n ],\r\n },\r\n safari: {\r\n steps: [\r\n 'Abre «Safari» → «Ajustes para este sitio web».',\r\n 'En «Micrófono», elige «Permitir».',\r\n 'Recarga la página.',\r\n ],\r\n },\r\n unknown: {\r\n steps: [\r\n 'Abre los permisos de este sitio en tu navegador.',\r\n 'Cambia el micrófono a «Permitir».',\r\n 'Recarga la página.',\r\n ],\r\n },\r\n};\r\n\r\n/** The guide for the current browser. SSR-safe: no `navigator` at module scope (SPEC §10.2). */\r\nexport function unblockGuide(): UnblockGuide {\r\n const ua = typeof navigator === 'undefined' ? '' : navigator.userAgent;\r\n return GUIDES[detectBrowser(ua)];\r\n}\r\n\r\n/** @internal — tests drive the detection without stubbing a global. */\r\nexport function __guideFor(ua: string): UnblockGuide {\r\n return GUIDES[detectBrowser(ua)];\r\n}\r\n","import type { ReactNode } from 'react';\r\nimport { Mic, MicOff, HelpCircle, ExternalLink } from 'lucide-react';\r\nimport { useMicPermission, type MicState } from './useMicPermission.js';\r\nimport { unblockGuide } from './unblock-mic.js';\r\n\r\n/**\r\n * What the user sees while the mic is not available yet. Body content only — no shell — so the\r\n * widget can render it inside its own `.cv-body` instead of nesting a second `.cv-softphone`.\r\n */\r\nexport function MicPrompt({\r\n state,\r\n onRequest,\r\n}: Readonly<{ state: MicState; onRequest: () => void }>) {\r\n if (state === 'unsupported') {\r\n return (\r\n <div className=\"cv-gate\" data-state={state} data-tone=\"danger\">\r\n <span className=\"cv-gate-mark\">\r\n <MicOff size={22} />\r\n </span>\r\n <h3 className=\"cv-gate-title\">Llamadas no disponibles</h3>\r\n <p>Este navegador no admite llamadas. Prueba con Chrome, Edge o Firefox.</p>\r\n </div>\r\n );\r\n }\r\n\r\n if (state === 'denied') {\r\n const guide = unblockGuide();\r\n return (\r\n <div className=\"cv-gate\" data-state={state} data-tone=\"danger\">\r\n <span className=\"cv-gate-mark\">\r\n <MicOff size={22} />\r\n </span>\r\n <h3 className=\"cv-gate-title\">Micrófono bloqueado</h3>\r\n <p>Permítelo en tu navegador para poder llamar.</p>\r\n\r\n {/*\r\n A dead end needs a way out, and the way out is three clicks away in the browser they are\r\n already looking at — so the steps are HERE, not behind a link to a support site.\r\n `<details>` is the disclosure: native, keyboard-accessible, no JS, collapsed by default so\r\n the panel is not a wall of text for the people who already know.\r\n */}\r\n <details className=\"cv-help\">\r\n <summary>\r\n <HelpCircle size={13} aria-hidden />\r\n Cómo permitirlo\r\n </summary>\r\n <ol>\r\n {guide.steps.map((step) => (\r\n <li key={step}>{step}</li>\r\n ))}\r\n </ol>\r\n {guide.url ? (\r\n <a href={guide.url} target=\"_blank\" rel=\"noreferrer noopener\">\r\n Guía del navegador\r\n <ExternalLink size={11} aria-hidden />\r\n </a>\r\n ) : null}\r\n </details>\r\n </div>\r\n );\r\n }\r\n\r\n /*\r\n * `warming` — `getUserMedia()` is running, and the browser may be showing its OWN permission\r\n * prompt on top of us.\r\n *\r\n * We cannot know which: the API returns one promise and signals nothing either way. **Timing\r\n * separates them.** A silent grant resolves in tens of milliseconds; a prompt waits on a human.\r\n * Since the CSS holds this state back 450 ms, the rule falls out of the delay: if this is visible\r\n * at all, somebody is being asked something.\r\n *\r\n * So it points at the browser's prompt instead of narrating ours. \"Preparando el micrófono…\" was\r\n * true and useless — it described our internals while the actual question sat unanswered in the\r\n * corner of the screen.\r\n */\r\n if (state === 'warming') {\r\n return (\r\n <div className=\"cv-gate\" data-state={state}>\r\n <span className=\"cv-gate-mark\">\r\n <Mic size={22} />\r\n </span>\r\n <h3 className=\"cv-gate-title\">Permite el micrófono</h3>\r\n <p>Acepta el aviso que muestra el navegador para continuar.</p>\r\n </div>\r\n );\r\n }\r\n\r\n /*\r\n * `checking` — querying `permissions.query()`. No browser UI can appear during this, so there is\r\n * nothing to point at and nothing for the user to do. Also delayed 450 ms, and in practice never\r\n * painted at all.\r\n */\r\n if (state === 'checking') {\r\n return (\r\n <div className=\"cv-gate\" data-state={state}>\r\n <span className=\"cv-gate-mark\">\r\n <Mic size={22} />\r\n </span>\r\n <p>Preparando el micrófono…</p>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"cv-gate\" data-state={state}>\r\n <span className=\"cv-gate-mark\">\r\n <Mic size={22} />\r\n </span>\r\n <h3 className=\"cv-gate-title\">Permite el micrófono</h3>\r\n {/* Says WHY before asking. A permission request with no reason is the one people decline. */}\r\n <p>Lo necesitamos para que puedas hablar durante las llamadas.</p>\r\n <button className=\"cv-btn cv-btn--accent\" onClick={onRequest}>\r\n Permitir micrófono\r\n </button>\r\n </div>\r\n );\r\n}\r\n\r\n/**\r\n * Gate arbitrary children on microphone permission.\r\n *\r\n * **`SoftphoneWidget` now gates itself** (`requireMic`, on by default), so most integrations need\r\n * nothing here — a softphone without a microphone is not a softphone, and making the gate opt-in\r\n * meant every integrator had to know to opt in or ship something that fails mid-call.\r\n *\r\n * This stays exported for hosts that want the prompt somewhere else: their own modal, a page-level\r\n * onboarding step, or wrapping something larger than the widget.\r\n */\r\nexport function MicPermissionGate({ children }: Readonly<{ children: ReactNode }>) {\r\n const { state, request } = useMicPermission();\r\n if (state === 'ready') return <>{children}</>;\r\n return (\r\n <div className=\"cv-softphone\">\r\n <MicPrompt state={state} onRequest={() => void request()} />\r\n </div>\r\n );\r\n}\r\n","import { TriangleAlert } from 'lucide-react';\r\nimport { ERROR_TEXT } from '../lib/error-text.js';\r\nimport type { FatalSoftphoneError } from '../../core/errors.js';\r\n\r\n/**\r\n * Why the phone cannot be used, and the one thing worth trying.\r\n *\r\n * **Deliberately the same `.cv-gate` as `MicPrompt`**, not a banner. The widget already had this\r\n * affordance for \"something is wrong, here is why, here is what to do\", and it earns its shape: it\r\n * REPLACES the body rather than sitting above it. A fatal error means calling is impossible, so\r\n * leaving a dialpad visible under a warning invites the user to try anyway and learn nothing.\r\n *\r\n * No dismissal — no close button, no timer. The condition is still true; hiding the explanation would\r\n * leave a phone that silently refuses. It goes when the softphone reaches `online`, which is the only\r\n * evidence available that whatever was wrong no longer is.\r\n */\r\nexport function ErrorGate({\r\n error,\r\n onRetry,\r\n}: Readonly<{ error: FatalSoftphoneError; onRetry: () => void }>) {\r\n const text = ERROR_TEXT[error.code];\r\n\r\n return (\r\n /*\r\n `part` on all four, because this is the most intrusive thing the SDK draws — it replaces the\r\n whole dialpad — and inside `<coventia-softphone>` a shadow root makes it otherwise unreachable\r\n from the host's CSS. Custom properties alone only let a host recolour what we chose to draw.\r\n\r\n `data-code` is NOT a substitute: it is inside the shadow root, so `[data-code=…]` selectors\r\n cannot cross the boundary either. It stays for the light-DOM `/ui` path and for debugging.\r\n */\r\n <div className=\"cv-gate\" data-tone=\"danger\" data-code={error.code} part=\"error-gate\">\r\n <span className=\"cv-gate-mark\">\r\n <TriangleAlert size={22} />\r\n </span>\r\n <h3 className=\"cv-gate-title\" part=\"error-title\">\r\n {text.title}\r\n </h3>\r\n {/* Every fatal code has a body — `error-text.test.ts` fails the build otherwise. */}\r\n {text.body === undefined ? null : <p part=\"error-body\">{text.body}</p>}\r\n {/*\r\n `start()` re-provisions, and every fatal code we raise is recoverable by re-provisioning:\r\n a stale key is re-fetched, a refused token is re-minted, a dead socket is rebuilt. If it\r\n fails again the gate simply stays — which is the honest outcome, not a silent one.\r\n */}\r\n <button className=\"cv-btn cv-btn--accent\" onClick={onRetry} part=\"error-retry\">\r\n Reintentar\r\n </button>\r\n </div>\r\n );\r\n}\r\n","import { MonitorSmartphone } from 'lucide-react';\r\n\r\n/**\r\n * Shown instead of the dialpad when ANOTHER open tab holds the extension\r\n * (`multi-tab-leader-election.md`).\r\n *\r\n * **Not `ErrorGate` re-skinned.** `ErrorGate`'s whole shape is welded to `FatalSoftphoneError` — it\r\n * reads `ERROR_TEXT[error.code]` and always offers a \"Reintentar\" action wired to `stop()` + `start()`.\r\n * Neither fits: nothing is broken here, there is nothing to retry, and inventing a fake catalogue code\r\n * for a condition that was never a failure would be worse than a second small component. What IS\r\n * reused is `.cv-gate` itself — the same primitive `MicPrompt`'s non-error states already render with\r\n * no `data-tone=\"danger\"`.\r\n *\r\n * No dismissal, same reasoning as `ErrorGate`: it clears itself the instant the other tab closes,\r\n * reloads, or crashes (Web Locks' own guarantee — no polling, no user action).\r\n */\r\nexport function LeaderGate() {\r\n return (\r\n <div className=\"cv-gate\" part=\"leader-gate\">\r\n <span className=\"cv-gate-mark\">\r\n <MonitorSmartphone size={22} />\r\n </span>\r\n <h3 className=\"cv-gate-title\" part=\"leader-title\">\r\n Teléfono activo en otra pestaña\r\n </h3>\r\n <p part=\"leader-body\">Solo una pestaña puede usar el teléfono a la vez. Cierra la otra para activar esta.</p>\r\n </div>\r\n );\r\n}\r\n","import { useCallback, useEffect, useRef, useState } from 'react';\r\nimport { useSoftphone } from '../../react/index.js';\r\nimport { SoftphoneEvent } from '../../core/events.js';\r\nimport { ERROR_TEXT } from './error-text.js';\r\nimport type { SoftphoneErrorCode } from '../../core/errors.js';\r\n\r\n/** How long an unattended outcome stays before it becomes furniture. */\r\nconst BACKSTOP_MS = 6_000;\r\n\r\n/**\r\n * The outcome of the last attempt — \"Sin respuesta\", \"Llamada rechazada\".\r\n *\r\n * **Non-fatal errors only.** A fatal one is a condition and belongs in the gate; this is an *event*,\r\n * a fact about a call that already ended, and it must not persist as though the phone were broken.\r\n *\r\n * **Cleared by the user's next intent**, which is what the previous CRM did — it called\r\n * `setError(null)` on dial, answer, reject, and on an inbound INVITE. The reasoning holds: the moment\r\n * you dial again, what happened to the last call stops being relevant. A timer alone would clear at\r\n * an arbitrary moment unrelated to what the user is doing; it is only the backstop, for when intent\r\n * never comes because the user read it and walked away.\r\n *\r\n * **Lives above the dialpad.** The outcome is raised as the call ENDS — the exact moment the widget\r\n * swaps the call screen back for the dialpad. Held inside `Dialpad` it would be born into a component\r\n * that is remounting, and lost.\r\n */\r\nexport function useCallOutcome(): {\r\n readonly outcome: { readonly code: SoftphoneErrorCode; readonly text: string } | null;\r\n readonly clear: () => void;\r\n} {\r\n const softphone = useSoftphone();\r\n const [code, setCode] = useState<SoftphoneErrorCode | null>(null);\r\n const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\r\n\r\n const clear = useCallback(() => {\r\n clearTimeout(timer.current);\r\n setCode(null);\r\n }, []);\r\n\r\n useEffect(() => {\r\n const off = softphone.on(SoftphoneEvent.Error, (error) => {\r\n // Fatal errors are the gate's business. Showing them here too would say the same thing twice,\r\n // in the smaller and more dismissible of the two places.\r\n if (error.fatal) return;\r\n clearTimeout(timer.current);\r\n setCode(error.code);\r\n timer.current = setTimeout(() => setCode(null), BACKSTOP_MS);\r\n });\r\n return () => {\r\n off();\r\n clearTimeout(timer.current);\r\n };\r\n }, [softphone]);\r\n\r\n // An inbound call is intent too: the user is being asked something new, and last call's outcome is\r\n // no longer what they need to read.\r\n useEffect(() => softphone.on(SoftphoneEvent.IncomingCall, () => clear()), [softphone, clear]);\r\n\r\n return {\r\n outcome: code === null ? null : { code, text: ERROR_TEXT[code].title },\r\n clear,\r\n };\r\n}\r\n","import { useEffect, useRef } from 'react';\r\nimport { useSoftphone } from '../../react/index.js';\r\nimport { CallEvent, SoftphoneEvent } from '../../core/events.js';\r\nimport {\r\n createRemoteAudio,\r\n playCallEndedTone,\r\n playRingback,\r\n playRingtone,\r\n primeAudio,\r\n type RemoteAudio,\r\n type Tone,\r\n} from './audio.js';\r\nimport type { Call } from '../../core/call.js';\r\n\r\n/**\r\n * Wires the softphone's audio to call state: the remote party, the inbound ring, the outbound\r\n * ringback, and the end-of-call cue. Mounted by `SoftphoneWidget`, so a host gets all of it without\r\n * knowing it exists.\r\n *\r\n * **The remote stream is attached only on `active`, never before**, and that one rule does two jobs:\r\n *\r\n * 1. It IS the call audio. Nothing else attaches the stream, so without this a connected call is\r\n * silent in both directions.\r\n * 2. It prevents a doubled ringback. Firefox plays the carrier's early media; routing the remote\r\n * stream during outbound ringing would layer that on top of our local tone. The legacy code\r\n * carried a `suppressRemoteAudioRef` flag cleared on `accepted` — attaching on `active` is the\r\n * same rule with nothing to forget to clear.\r\n */\r\nexport function useCallAudio(enabled: boolean): void {\r\n const softphone = useSoftphone();\r\n const remote = useRef<RemoteAudio | null>(null);\r\n const tone = useRef<Tone | null>(null);\r\n\r\n useEffect(() => {\r\n if (!enabled || typeof document === 'undefined') return;\r\n\r\n /*\r\n * Unlock audio on the first interaction anywhere on the page, whatever it is — a tab, a dialpad\r\n * key, the mic-permission button.\r\n *\r\n * An inbound INVITE is not a user gesture, so a context first built when the phone rings is\r\n * created under the autoplay policy and Firefox warns about it three times. Building it during\r\n * an ordinary click costs nothing and means ringing never touches the policy at all.\r\n *\r\n * `capture` so it fires even if something calls `stopPropagation`, and it listens on the document\r\n * rather than the widget because the events that escape our shadow root are the composed ones.\r\n */\r\n const prime = (): void => primeAudio();\r\n const gestures = ['pointerdown', 'keydown'] as const;\r\n for (const type of gestures) {\r\n document.addEventListener(type, prime, { once: true, capture: true });\r\n }\r\n\r\n remote.current = createRemoteAudio();\r\n // Apply whatever output is already selected (a Settings change made before this call, or before\r\n // the widget even mounted) — `null` is a real, explicit value here (\"system default\"), not\r\n // \"nothing to do\", so this always runs rather than only when a device is chosen.\r\n void remote.current.setOutputDevice(softphone.audio.currentOutputId);\r\n // …and keep it applied if the selection changes WHILE this element is live — output routing is\r\n // meant to be instant, live call or not (see `AudioDevices.setOutput`'s own comment).\r\n const offDeviceChange = softphone.on(SoftphoneEvent.DeviceChange, () => {\r\n void remote.current?.setOutputDevice(softphone.audio.currentOutputId);\r\n });\r\n\r\n const stopTone = (): void => {\r\n tone.current?.stop();\r\n tone.current = null;\r\n };\r\n\r\n /** One tone at a time: switching states must never leave the previous one running. */\r\n const setTone = (next: 'ringtone' | 'ringback' | null): void => {\r\n stopTone();\r\n if (next === 'ringtone') tone.current = playRingtone();\r\n else if (next === 'ringback') tone.current = playRingback();\r\n };\r\n\r\n const perCall: Array<() => void> = [];\r\n // An inbound call fires BOTH `ActiveCallChanged` and `IncomingCall` for the same `Call`\r\n // (`softphone-impl.ts#adopt` emits the former, `#onIncoming` the latter, right after) — both\r\n // wired to `follow` below. That double subscription was harmless while every handler here was\r\n // idempotent (stop a tone that is already stopped, detach an already-detached stream); it stops\r\n // being harmless the moment a handler has a real one-shot side effect, like the end-of-call tone.\r\n const followedCalls = new Set<Call>();\r\n\r\n const follow = (call: Call): void => {\r\n if (followedCalls.has(call)) return;\r\n followedCalls.add(call);\r\n\r\n // Whether this call ever actually connected — the end-of-call cue is for a conversation that\r\n // was really happening, not for a ring that got cancelled or a dial that never picked up.\r\n // Tracked per-call rather than read off `call.state` at `Ended` time because by then the state\r\n // machine has already moved to 'ended' and the history is gone.\r\n let wasConnected = call.state === 'active' || call.state === 'held';\r\n\r\n const apply = (state: string): void => {\r\n if (state === 'active' || state === 'held') wasConnected = true;\r\n if (state === 'ringing') setTone('ringtone'); // inbound: they are calling us\r\n else if (state === 'dialing' || state === 'early') setTone('ringback'); // outbound\r\n else setTone(null); // answering / active / held / ended — silence\r\n };\r\n apply(call.state);\r\n\r\n perCall.push(\r\n call.on(CallEvent.StateChanged, ({ state }) => apply(state)),\r\n // Attach on `active` only — see the note above. `remoteStream` is usually already set by\r\n // then, since media arrives before the 200 OK.\r\n call.on(CallEvent.Accepted, () => {\r\n if (call.remoteStream) remote.current?.attach(call.remoteStream);\r\n }),\r\n // …but if it arrives late, take it then — as long as we are past ringing.\r\n call.on(CallEvent.RemoteStream, ({ stream }) => {\r\n if (call.state === 'active' || call.state === 'held') remote.current?.attach(stream);\r\n }),\r\n call.on(CallEvent.Ended, ({ reason }) => {\r\n followedCalls.delete(call);\r\n stopTone();\r\n remote.current?.detach();\r\n // 'local' and 'remote' are BOTH ordinary hangups — either side ending a real conversation\r\n // is the same cue. Never for 'busy' / 'rejected' / 'no-answer' / 'failed': the call never\r\n // connected, and a \"goodbye\" tone on a call nobody answered would be actively misleading.\r\n // Not for 'transferred' either — that call keeps going, just without this leg.\r\n if (wasConnected && (reason === 'local' || reason === 'remote')) playCallEndedTone();\r\n }),\r\n );\r\n };\r\n\r\n const offIncoming = softphone.on(SoftphoneEvent.IncomingCall, follow);\r\n const offActive = softphone.on(SoftphoneEvent.ActiveCallChanged, ({ call }) => {\r\n if (call) follow(call);\r\n else {\r\n stopTone();\r\n remote.current?.detach();\r\n }\r\n });\r\n if (softphone.activeCall) follow(softphone.activeCall);\r\n\r\n return () => {\r\n for (const type of gestures) document.removeEventListener(type, prime, { capture: true });\r\n offIncoming();\r\n offActive();\r\n offDeviceChange();\r\n for (const off of perCall) off();\r\n stopTone();\r\n remote.current?.destroy();\r\n remote.current = null;\r\n };\r\n }, [softphone, enabled]);\r\n}\r\n","import { Phone, PhoneMissed, X } from 'lucide-react';\r\nimport { useSoftphone } from '../../react/index.js';\r\nimport { useTicker } from '../lib/useTicker.js';\r\nimport { elapsedSeconds, formatAge } from '../lib/format.js';\r\nimport type { TransferNotice } from './useTransferNotices.js';\r\n\r\n/**\r\n * \"El traspaso a 101 no se conectó\" — spec §5.5. Persistent, dismissable, no timer.\r\n *\r\n * **Purely presentational — takes `notices`/`dismiss` as props rather than calling\r\n * `useTransferNotices()` itself.** The SUBSCRIPTION that hook owns has to stay alive for the whole time\r\n * the widget is mounted, not just while this component happens to be on screen: an outcome for an\r\n * earlier transfer can arrive while the agent is on a brand new, unrelated call, and if nobody were\r\n * listening at that moment it would be gone for good (the same class of gap `useTransferNotices`'s own\r\n * comment already accepts for a fully unmounted widget — this is what keeps it from also happening\r\n * every time a call is merely in progress). So `SoftphoneWidget` calls the hook once, unconditionally,\r\n * the same placement `useCallOutcome` already uses and for the same reason; only the RENDERING of this\r\n * component is conditional on being in a state where the widget isn't using the screen for something\r\n * higher-priority (a live call, the mic gate, a fatal error, a follower tab).\r\n *\r\n * **Always rendered when mounted, `role=\"status\"`, even with nothing to show** — the same reason\r\n * `Dialpad`'s own outcome line always exists: an aria-live region inserted at the same moment as its\r\n * first content is not reliably announced. Left visually empty (no padding of its own) when there is\r\n * nothing waiting, so this costs no layout space either.\r\n */\r\nexport function TransferNotices({\r\n notices,\r\n dismiss,\r\n}: Readonly<{ notices: readonly TransferNotice[]; dismiss: (id: number) => void }>) {\r\n const softphone = useSoftphone();\r\n // Only while there's something to age, and coarsely: `formatAge` never changes output more often\r\n // than once a minute, so a 1 s tick would just be wasted re-renders on a possibly long-lived notice.\r\n const now = useTicker(notices.length > 0, 15_000);\r\n\r\n const callBack = (notice: TransferNotice): void => {\r\n dismiss(notice.id); // clears itself on press (spec §5.5) — not conditional on the call succeeding\r\n if (notice.caller) void softphone.call(notice.caller).catch(() => {});\r\n };\r\n\r\n return (\r\n <div\r\n className=\"cv-transfer-notices\"\r\n role=\"status\"\r\n part=\"transfer-notices\"\r\n // Explicit, rather than leaning on a `:empty` CSS selector's assumptions about how React\r\n // renders `null`/an empty array — this is what CSS actually keys off to stay visually\r\n // zero-footprint while there is nothing waiting.\r\n data-has-notices={notices.length > 0}\r\n >\r\n {notices.length > 1 ? (\r\n <p className=\"cv-transfer-notices-count\">{notices.length} traspasos sin conectar</p>\r\n ) : null}\r\n {notices.map((notice) => (\r\n <div key={notice.id} className=\"cv-transfer-notice\" part=\"transfer-notice\">\r\n <span className=\"cv-transfer-notice-mark\" aria-hidden>\r\n <PhoneMissed size={16} />\r\n </span>\r\n <div className=\"cv-transfer-notice-body\">\r\n {/* Title and dismiss share only THIS row — not the whole card, and not the callback\r\n button below. Squeezing icon + title + subtitle + a full \"Llamar de vuelta\" button\r\n into one flex row left the title as little as ~80px to wrap into at the real ~340px\r\n embed width, breaking nearly every word onto its own line. */}\r\n <div className=\"cv-transfer-notice-header\">\r\n <p className=\"cv-transfer-notice-title\">El traspaso a {notice.target} no se conectó</p>\r\n <button\r\n type=\"button\"\r\n className=\"cv-transfer-notice-dismiss\"\r\n onClick={() => dismiss(notice.id)}\r\n aria-label=\"Descartar aviso\"\r\n part=\"transfer-notice-dismiss\"\r\n >\r\n <X size={14} />\r\n </button>\r\n </div>\r\n {/* Absent, not \"número desconocido\" — spec §7's outside-number case and a genuinely\r\n unresolved caller both leave this null, and there is nothing actionable to say either\r\n way beyond the title above. */}\r\n {notice.caller ? (\r\n <p className=\"cv-transfer-notice-subtitle\">{notice.caller} se ha desconectado.</p>\r\n ) : null}\r\n <div className=\"cv-transfer-notice-footer\">\r\n <p className=\"cv-transfer-notice-age\">{formatAge(elapsedSeconds(notice.at, now))}</p>\r\n {/* Absent when the caller's number is unknown (plan T6's own acceptance) — nothing to dial. */}\r\n {notice.caller ? (\r\n <button\r\n type=\"button\"\r\n className=\"cv-btn cv-btn--accent cv-transfer-notice-callback\"\r\n onClick={() => callBack(notice)}\r\n part=\"transfer-notice-callback\"\r\n >\r\n <Phone size={14} aria-hidden />\r\n Llamar de vuelta\r\n </button>\r\n ) : null}\r\n </div>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n}\r\n","import { useCallback, useEffect, useRef, useState } from 'react';\r\nimport { useSoftphone } from '../../react/index.js';\r\nimport { SoftphoneEvent } from '../../core/events.js';\r\n\r\n/**\r\n * One transfer that didn't connect, waiting for the agent to see it. The `id` is local to this hook —\r\n * `TransferOutcomeEvent` carries no id of its own (the source's own `id`, on `TransferOutcomeEntry`, is\r\n * a polling-internal concern the watch never exposes) — so a simple incrementing counter is enough; it\r\n * only ever needs to be unique within one mounted widget.\r\n */\r\nexport interface TransferNotice {\r\n readonly id: number;\r\n readonly target: string;\r\n /** Null when the caller's number was never known — the notice still shows, with no call-back action. */\r\n readonly caller: string | null;\r\n readonly at: Date;\r\n}\r\n\r\n/**\r\n * Accumulates `SoftphoneEvent.TransferOutcome`'s `'not-connected'` outcomes into a dismissable list —\r\n * `docs/specs/transfer-outcome-relay.md` §5.5, plan T6.\r\n *\r\n * **Deliberately NOT `useCallOutcome`'s shape.** That hook holds one value, auto-clears after a\r\n * backstop timer, and clears on the next dial/incoming intent — right for \"what just happened on the\r\n * call you're looking at now.\" A transfer notice is about a DIFFERENT, now-absent customer, arrives\r\n * roughly a minute after the agent has already moved on, and must not vanish because something else\r\n * happened in between: no backstop timer (spec §5.5's UX research — a timed notice here is one the\r\n * agent never had a fair chance to read), no clearing on intent, and more than one can be true at once.\r\n *\r\n * **A real, accepted gap:** this only sees outcomes that arrive while a widget instance is mounted and\r\n * listening. The softphone itself (not the widget) owns the watch's lifecycle, so an outcome that\r\n * lands while no widget happens to be mounted is emitted to nobody and is gone — the same category of\r\n * gap the spec already accepts for a closed tab (§7), just one level narrower. Fixing it would mean the\r\n * softphone itself holding pending notices, which is a bigger change than this task's own scope.\r\n */\r\nexport function useTransferNotices(): {\r\n readonly notices: readonly TransferNotice[];\r\n readonly dismiss: (id: number) => void;\r\n} {\r\n const softphone = useSoftphone();\r\n const [notices, setNotices] = useState<readonly TransferNotice[]>([]);\r\n const nextId = useRef(0);\r\n\r\n const dismiss = useCallback((id: number) => {\r\n setNotices((prev) => prev.filter((n) => n.id !== id));\r\n }, []);\r\n\r\n useEffect(\r\n () =>\r\n softphone.on(SoftphoneEvent.TransferOutcome, (payload) => {\r\n // The event fires for BOTH outcomes (spec §4 D2) so a host can react to a success too; the\r\n // widget itself stays silent for one. An explicit equality check, not `!== 'connected'`: an\r\n // unrecognised future status should fail toward silence, not toward showing something.\r\n if (payload.status === 'not-connected') {\r\n const id = nextId.current++;\r\n setNotices((prev) => [...prev, { id, target: payload.target, caller: payload.caller, at: payload.at }]);\r\n }\r\n }),\r\n [softphone],\r\n );\r\n\r\n return { notices, dismiss };\r\n}\r\n","import { useState } from 'react';\r\nimport { Grid3x3, Users, Clock, Settings } from 'lucide-react';\r\nimport {\r\n useActiveCall,\r\n useIsLeader,\r\n useLastError,\r\n useSoftphone,\r\n useSoftphoneState,\r\n} from '../react/index.js';\r\nimport { Dialpad } from './views/Dialpad.js';\r\nimport { CallScreen } from './views/CallScreen.js';\r\nimport { ContactsTab } from './views/ContactsTab.js';\r\nimport { HistoryTab } from './views/HistoryTab.js';\r\nimport { SettingsTab } from './views/SettingsTab.js';\r\nimport { MicPrompt } from './permission/MicPermissionGate.js';\r\nimport { ErrorGate } from './permission/ErrorGate.js';\r\nimport { LeaderGate } from './permission/LeaderGate.js';\r\nimport { useCallOutcome } from './lib/useCallOutcome.js';\r\nimport { useMicPermission } from './permission/useMicPermission.js';\r\nimport { useCallAudio } from './audio/useCallAudio.js';\r\nimport { TransferNotices } from './notices/TransferNotices.js';\r\nimport { useTransferNotices } from './notices/useTransferNotices.js';\r\nimport type { SoftphoneWidgetProps } from './types.js';\r\n\r\ntype TabId = 'dialer' | 'contacts' | 'history' | 'settings';\r\n\r\n/**\r\n * The softphone widget (legacy ZadarmaWidget) — the drop-in call UI. Wrap it in a\r\n * `<SoftphoneProvider softphone={…}>` and that is all: it asks for the microphone ITSELF\r\n * (`requireMic`, on by default), so no integrator has to know that a phone needs one.\r\n *\r\n * When a call is live, the call screen takes the whole body and the tabs hide. Otherwise the tabbed\r\n * interface (Teclado / Contactos / Historial) shows. Contactos/Historial appear only when their data\r\n * source is provided — the widget stays useful as a bare dialer with no backend at all.\r\n */\r\nexport function SoftphoneWidget(props: SoftphoneWidgetProps) {\r\n const {\r\n contacts,\r\n history,\r\n contactAction,\r\n incomingCallAction,\r\n className,\r\n theme = 'system',\r\n requireMic = true,\r\n sounds = true,\r\n } = props;\r\n const softphone = useSoftphone();\r\n\r\n /*\r\n * The sources come from the SOFTPHONE, not from a prop.\r\n *\r\n * `createSoftphone({ coventia })` builds them once, because caller ID has to work when an INVITE\r\n * lands — which can be before any UI is mounted. Reading them back here means one instance and one\r\n * name cache, and a host never imports an adapter or repeats a config to wire the tabs.\r\n *\r\n * An explicit `contacts`/`history` prop still wins, for a host driving the UI from somewhere else.\r\n */\r\n const fallback = softphone.sources;\r\n const contactsSource = contacts ?? fallback?.contacts;\r\n const historySource = history ?? fallback?.history;\r\n const [tab, setTab] = useState<TabId>('dialer');\r\n const call = useActiveCall();\r\n const isLeader = useIsLeader();\r\n const softphoneState = useSoftphoneState();\r\n // `isLeader` alone cannot tell \"never started\" from \"started, currently a follower\" — both are\r\n // `isLeader === false`. `state === 'starting'` is the disambiguator: it now covers the whole\r\n // in-progress window, including waiting behind another tab (SPEC — `softphone-impl.ts#start()`,\r\n // `multi-tab-leader-election.md` §3.4). A phone that was simply never `start()`-ed must fall\r\n // through to the mic gate / dialer exactly as before this feature existed.\r\n const isFollower = !isLeader && softphoneState === 'starting';\r\n // Always called — hooks cannot be conditional — but ignored when the host opted out.\r\n const mic = useMicPermission();\r\n // The remote party, the ring, the ringback. Without it a connected call is silent.\r\n useCallAudio(sounds);\r\n const blocked = requireMic && mic.state !== 'ready';\r\n const fatal = useLastError();\r\n // Shared by the tab bar (below) and `TransferNotices`: both are lower-priority than whatever else\r\n // the widget might be showing, and both simply don't render — never hidden, never queued behind —\r\n // while a call, the mic gate, a fatal error, or another tab's leadership owns the screen instead.\r\n const screenIsFree = !call && !blocked && !fatal && !isFollower;\r\n // Held HERE, not in the dialpad: the outcome is raised as the call ends, which is the same moment\r\n // the dialpad remounts — it would be born into a remounting component and lost.\r\n const { outcome, clear: clearOutcome } = useCallOutcome();\r\n // Held HERE too, and for a stronger version of the same reason: an outcome for an EARLIER transfer\r\n // can arrive while the agent is on a brand new, unrelated call — `TransferNotices` below is only\r\n // ever RENDERED once the screen is free, but the SUBSCRIPTION must stay alive the whole time the\r\n // widget is mounted, or that outcome reaches nobody (`useTransferNotices`'s own comment).\r\n const { notices: transferNotices, dismiss: dismissTransferNotice } = useTransferNotices();\r\n\r\n /*\r\n * `stop()` then `start()`, not `start()` alone — `start()` early-returns once the softphone has\r\n * been started, so on its own it would be a button that visibly does nothing.\r\n *\r\n * The round trip is also what makes recovery observable: it tears the signal channel down and\r\n * builds it again with fresh credentials, producing a real `offline → online` transition, which is\r\n * what clears `lastError` and takes the gate away. If it fails the same way, the error is\r\n * re-emitted and the gate returns — which is the honest outcome.\r\n */\r\n const retry = () => {\r\n void (async () => {\r\n try {\r\n await softphone.stop();\r\n await softphone.start();\r\n } catch {\r\n // Already reported through the error channel; the gate simply stays.\r\n }\r\n })();\r\n };\r\n\r\n const tabs = [\r\n { id: 'dialer' as const, icon: Grid3x3, label: 'Teclado', show: true },\r\n { id: 'contacts' as const, icon: Users, label: 'Contactos', show: !!contactsSource },\r\n { id: 'history' as const, icon: Clock, label: 'Historial', show: !!historySource },\r\n // Unlike Contactos/Historial, needs no host-supplied source — a microphone and a speaker are not\r\n // optional parts of a phone, so this is never conditionally hidden.\r\n { id: 'settings' as const, icon: Settings, label: 'Ajustes', show: true },\r\n ].filter((t) => t.show);\r\n\r\n return (\r\n <div\r\n className={className ? `cv-softphone ${className}` : 'cv-softphone'}\r\n // 'system' omits the attribute entirely, letting the prefers-color-scheme media query decide.\r\n {...(theme === 'system' ? {} : { 'data-cv-theme': theme })}\r\n >\r\n {/*\r\n A sibling of `.cv-body`, not inside it: a persistent notice must never scroll away with a long\r\n Contactos/Historial list, and must stay put across every tab. It OVERLAYS `.cv-body` (CSS —\r\n `position: absolute`) rather than pushing it down, so the widget's overall height never changes\r\n just because a notice appeared or was dismissed. `screenIsFree` gates it the same way it gates\r\n the tab bar below — it simply doesn't render, rather than queuing, while a call, the mic gate, a\r\n fatal error or another tab's leadership needs the screen instead.\r\n */}\r\n {screenIsFree ? (\r\n <TransferNotices notices={transferNotices} dismiss={dismissTransferNotice} />\r\n ) : null}\r\n <div className=\"cv-body\">\r\n {/*\r\n Order matters. `isFollower` comes FIRST, ahead even of the mic gate: another open tab\r\n holding this extension is a structural reason this tab cannot call, and asking for\r\n microphone permission somewhere that can never place or receive a call would be pure\r\n friction (`multi-tab-leader-election.md`). It clears on its own — no user action here helps\r\n it along. (A phone that was simply never `start()`-ed is NOT a follower — `isFollower`\r\n requires `state === 'starting'` too — so it falls through to the checks below, unchanged.)\r\n\r\n The mic gate comes next because it IS the precondition once leadership is not in question: no\r\n microphone means no call regardless of anything else, and it is the one thing here the user\r\n can complete right now. A fatal error outlives it — `lastError` persists — so nothing is lost\r\n by showing the actionable thing first.\r\n\r\n The call screen outranks the error gate, which is how \"suppress during a call\" is enforced:\r\n a live call is the highest-value state the widget has and nothing may cover it.\r\n */}\r\n {isFollower ? (\r\n <LeaderGate />\r\n ) : blocked ? (\r\n <MicPrompt state={mic.state} onRequest={() => void mic.request()} />\r\n ) : call ? (\r\n <CallScreen call={call} keyTones={sounds} {...(incomingCallAction ? { incomingCallAction } : {})} />\r\n ) : fatal ? (\r\n <ErrorGate error={fatal} onRetry={retry} />\r\n ) : tab === 'contacts' && contactsSource ? (\r\n <ContactsTab source={contactsSource} {...(contactAction ? { contactAction } : {})} />\r\n ) : tab === 'history' && historySource ? (\r\n <HistoryTab source={historySource} />\r\n ) : tab === 'settings' ? (\r\n <SettingsTab />\r\n ) : (\r\n <Dialpad outcome={outcome} onIntent={clearOutcome} keyTones={sounds} />\r\n )}\r\n </div>\r\n\r\n {/* No tabs while the mic is pending: Contactos and Historial would work, but offering them\r\n implies the phone is usable, and it is not until the mic is granted. Same reasoning extends\r\n to `isFollower` — a follower tab has nothing behind any of these tabs to be usable at all. */}\r\n {screenIsFree ? (\r\n <div className=\"cv-tabs\" role=\"tablist\">\r\n {tabs.map(({ id, icon: Icon, label }) => (\r\n <button\r\n key={id}\r\n role=\"tab\"\r\n aria-selected={tab === id}\r\n className=\"cv-tab\"\r\n onClick={() => setTab(id)}\r\n >\r\n <Icon size={20} />\r\n <span>{label}</span>\r\n </button>\r\n ))}\r\n </div>\r\n ) : null}\r\n </div>\r\n );\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../../node_modules/shared/src/utils.ts","../../../../node_modules/lucide-react/src/defaultAttributes.ts","../../../../node_modules/lucide-react/src/Icon.ts","../../../../node_modules/lucide-react/src/createLucideIcon.ts","../../../../node_modules/lucide-react/src/icons/arrow-left-right.ts","../../../../node_modules/lucide-react/src/icons/arrow-left.ts","../../../../node_modules/lucide-react/src/icons/arrow-right.ts","../../../../node_modules/lucide-react/src/icons/bell-ring.ts","../../../../node_modules/lucide-react/src/icons/calendar-clock.ts","../../../../node_modules/lucide-react/src/icons/check.ts","../../../../node_modules/lucide-react/src/icons/chevron-down.ts","../../../../node_modules/lucide-react/src/icons/chevron-right.ts","../../../../node_modules/lucide-react/src/icons/circle-help.ts","../../../../node_modules/lucide-react/src/icons/clock.ts","../../../../node_modules/lucide-react/src/icons/delete.ts","../../../../node_modules/lucide-react/src/icons/external-link.ts","../../../../node_modules/lucide-react/src/icons/grid-3x3.ts","../../../../node_modules/lucide-react/src/icons/hash.ts","../../../../node_modules/lucide-react/src/icons/headphones.ts","../../../../node_modules/lucide-react/src/icons/loader-circle.ts","../../../../node_modules/lucide-react/src/icons/mic-off.ts","../../../../node_modules/lucide-react/src/icons/mic.ts","../../../../node_modules/lucide-react/src/icons/monitor-smartphone.ts","../../../../node_modules/lucide-react/src/icons/music.ts","../../../../node_modules/lucide-react/src/icons/pause.ts","../../../../node_modules/lucide-react/src/icons/phone-incoming.ts","../../../../node_modules/lucide-react/src/icons/phone-missed.ts","../../../../node_modules/lucide-react/src/icons/phone-off.ts","../../../../node_modules/lucide-react/src/icons/phone-outgoing.ts","../../../../node_modules/lucide-react/src/icons/phone.ts","../../../../node_modules/lucide-react/src/icons/play.ts","../../../../node_modules/lucide-react/src/icons/search.ts","../../../../node_modules/lucide-react/src/icons/settings.ts","../../../../node_modules/lucide-react/src/icons/timer.ts","../../../../node_modules/lucide-react/src/icons/triangle-alert.ts","../../../../node_modules/lucide-react/src/icons/user.ts","../../../../node_modules/lucide-react/src/icons/users.ts","../../../../node_modules/lucide-react/src/icons/volume-2.ts","../../../../node_modules/lucide-react/src/icons/x.ts","../../src/ui/dialing/countries.ts","../../src/ui/dialing/CountryPicker.tsx","../../src/ui/dialing/format-number.ts","../../src/ui/dialing/keys.ts","../../src/ui/audio/classic-ring.ts","../../src/ui/audio/audio.ts","../../src/ui/outbound/outbound-number-store.ts","../../src/ui/outbound/outbound-change.ts","../../src/ui/outbound/OutboundNumberPicker.tsx","../../src/ui/views/Dialpad.tsx","../../src/ui/lib/format.ts","../../src/ui/lib/error-text.ts","../../src/ui/lib/useTicker.ts","../../src/ui/views/DevicePicker.tsx","../../src/ui/views/CallScreen.tsx","../../src/ui/views/DetailRow.tsx","../../src/ui/views/ContactDetail.tsx","../../src/ui/lib/useInfiniteList.ts","../../src/ui/views/ContactsTab.tsx","../../src/ui/views/history-format.tsx","../../src/ui/views/HistoryDetail.tsx","../../src/ui/views/HistoryTab.tsx","../../src/ui/audio/ringtone-store.ts","../../src/ui/views/SettingsSection.tsx","../../src/ui/views/settings/SettingsNavRow.tsx","../../src/ui/views/settings/ChoiceList.tsx","../../src/ui/views/settings/SettingsPage.tsx","../../src/ui/views/settings/DevicePage.tsx","../../src/ui/audio/preview.ts","../../src/ui/views/settings/ringtone-state.ts","../../src/ui/views/settings/RingtonePage.tsx","../../src/ui/views/settings/OutboundNumberPage.tsx","../../src/ui/views/SettingsTab.tsx","../../src/ui/permission/useMicPermission.ts","../../src/ui/permission/unblock-mic.ts","../../src/ui/permission/MicPermissionGate.tsx","../../src/ui/permission/ErrorGate.tsx","../../src/ui/permission/LeaderGate.tsx","../../src/ui/lib/useCallOutcome.ts","../../src/ui/audio/useCallAudio.ts","../../src/ui/notices/TransferNotices.tsx","../../src/ui/notices/useTransferNotices.ts","../../src/ui/SoftphoneWidget.tsx"],"names":["forwardRef","createElement","useState","useEffect","formatIntl","useRef","jsxs","jsx","Icon","Fragment","loading","useCallback","PAGE","stores","useId","noSubscribe","noSettings","useSyncExternalStore","ORG_DEFAULT","KEYBOARD_SETTLE_MS","choicesFor","currentValue"],"mappings":"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","file":"index.js","sourcesContent":["import { CamelToPascal } from './utility-types';\n\n/**\n * Converts string to kebab case\n *\n * @param {string} string\n * @returns {string} A kebabized string\n */\nexport const toKebabCase = (string: string) =>\n string.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();\n\n/**\n * Converts string to pascal case\n *\n * @param {string} string\n * @returns {string} A pascalized string\n */\nexport const toPascalCase = <T extends string>(string: T): CamelToPascal<T> => {\n const camelCase = string.replace(/^([A-Z])|[\\s-_]+(\\w)/g, (match, p1, p2) =>\n p2 ? p2.toUpperCase() : p1.toLowerCase(),\n );\n\n return (camelCase.charAt(0).toUpperCase() + camelCase.slice(1)) as CamelToPascal<T>;\n};\n\n/**\n * Merges classes into a single string\n *\n * @param {array} classes\n * @returns {string} A string of classes\n */\nexport const mergeClasses = <ClassType = string | undefined | null>(...classes: ClassType[]) =>\n classes\n .filter((className, index, array) => {\n return Boolean(className) && array.indexOf(className) === index;\n })\n .join(' ');\n","export default {\n xmlns: 'http://www.w3.org/2000/svg',\n width: 24,\n height: 24,\n viewBox: '0 0 24 24',\n fill: 'none',\n stroke: 'currentColor',\n strokeWidth: 2,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n};\n","import { createElement, forwardRef } from 'react';\nimport defaultAttributes from './defaultAttributes';\nimport { IconNode, LucideProps } from './types';\nimport { mergeClasses } from '@lucide/shared';\n\ninterface IconComponentProps extends LucideProps {\n iconNode: IconNode;\n}\n\n/**\n * Lucide icon component\n *\n * @component Icon\n * @param {object} props\n * @param {string} props.color - The color of the icon\n * @param {number} props.size - The size of the icon\n * @param {number} props.strokeWidth - The stroke width of the icon\n * @param {boolean} props.absoluteStrokeWidth - Whether to use absolute stroke width\n * @param {string} props.className - The class name of the icon\n * @param {IconNode} props.children - The children of the icon\n * @param {IconNode} props.iconNode - The icon node of the icon\n *\n * @returns {ForwardRefExoticComponent} LucideIcon\n */\nconst Icon = forwardRef<SVGSVGElement, IconComponentProps>(\n (\n {\n color = 'currentColor',\n size = 24,\n strokeWidth = 2,\n absoluteStrokeWidth,\n className = '',\n children,\n iconNode,\n ...rest\n },\n ref,\n ) => {\n return createElement(\n 'svg',\n {\n ref,\n ...defaultAttributes,\n width: size,\n height: size,\n stroke: color,\n strokeWidth: absoluteStrokeWidth ? (Number(strokeWidth) * 24) / Number(size) : strokeWidth,\n className: mergeClasses('lucide', className),\n ...rest,\n },\n [\n ...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),\n ...(Array.isArray(children) ? children : [children]),\n ],\n );\n },\n);\n\nexport default Icon;\n","import { createElement, forwardRef } from 'react';\nimport { mergeClasses, toKebabCase } from '@lucide/shared';\nimport { IconNode, LucideProps } from './types';\nimport Icon from './Icon';\n\n/**\n * Create a Lucide icon component\n * @param {string} iconName\n * @param {array} iconNode\n * @returns {ForwardRefExoticComponent} LucideIcon\n */\nconst createLucideIcon = (iconName: string, iconNode: IconNode) => {\n const Component = forwardRef<SVGSVGElement, LucideProps>(({ className, ...props }, ref) =>\n createElement(Icon, {\n ref,\n iconNode,\n className: mergeClasses(`lucide-${toKebabCase(iconName)}`, className),\n ...props,\n }),\n );\n\n Component.displayName = `${iconName}`;\n\n return Component;\n};\n\nexport default createLucideIcon;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name ArrowLeftRight\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/arrow-left-right\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst ArrowLeftRight = createLucideIcon('ArrowLeftRight', [\n ['path', { d: 'M8 3 4 7l4 4', key: '9rb6wj' }],\n ['path', { d: 'M4 7h16', key: '6tx8e3' }],\n ['path', { d: 'm16 21 4-4-4-4', key: 'siv7j2' }],\n ['path', { d: 'M20 17H4', key: 'h6l3hr' }],\n]);\n\nexport default ArrowLeftRight;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name ArrowLeft\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/arrow-left\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst ArrowLeft = createLucideIcon('ArrowLeft', [\n ['path', { d: 'm12 19-7-7 7-7', key: '1l729n' }],\n ['path', { d: 'M19 12H5', key: 'x3x0zl' }],\n]);\n\nexport default ArrowLeft;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name ArrowRight\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/arrow-right\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst ArrowRight = createLucideIcon('ArrowRight', [\n ['path', { d: 'M5 12h14', key: '1ays0h' }],\n ['path', { d: 'm12 5 7 7-7 7', key: 'xquz4c' }],\n]);\n\nexport default ArrowRight;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name BellRing\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/bell-ring\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst BellRing = createLucideIcon('BellRing', [\n ['path', { d: 'M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9', key: '1qo2s2' }],\n ['path', { d: 'M10.3 21a1.94 1.94 0 0 0 3.4 0', key: 'qgo35s' }],\n ['path', { d: 'M4 2C2.8 3.7 2 5.7 2 8', key: 'tap9e0' }],\n ['path', { d: 'M22 8c0-2.3-.8-4.3-2-6', key: '5bb3ad' }],\n]);\n\nexport default BellRing;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name CalendarClock\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/calendar-clock\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst CalendarClock = createLucideIcon('CalendarClock', [\n ['path', { d: 'M21 7.5V6a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h3.5', key: '1osxxc' }],\n ['path', { d: 'M16 2v4', key: '4m81vk' }],\n ['path', { d: 'M8 2v4', key: '1cmpym' }],\n ['path', { d: 'M3 10h5', key: 'r794hk' }],\n ['path', { d: 'M17.5 17.5 16 16.3V14', key: 'akvzfd' }],\n ['circle', { cx: '16', cy: '16', r: '6', key: 'qoo3c4' }],\n]);\n\nexport default CalendarClock;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Check\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/check\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Check = createLucideIcon('Check', [['path', { d: 'M20 6 9 17l-5-5', key: '1gmf2c' }]]);\n\nexport default Check;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name ChevronDown\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/chevron-down\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst ChevronDown = createLucideIcon('ChevronDown', [\n ['path', { d: 'm6 9 6 6 6-6', key: 'qrunsl' }],\n]);\n\nexport default ChevronDown;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name ChevronRight\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/chevron-right\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst ChevronRight = createLucideIcon('ChevronRight', [\n ['path', { d: 'm9 18 6-6-6-6', key: 'mthhwq' }],\n]);\n\nexport default ChevronRight;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name CircleHelp\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/circle-help\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst CircleHelp = createLucideIcon('CircleHelp', [\n ['circle', { cx: '12', cy: '12', r: '10', key: '1mglay' }],\n ['path', { d: 'M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3', key: '1u773s' }],\n ['path', { d: 'M12 17h.01', key: 'p32p05' }],\n]);\n\nexport default CircleHelp;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Clock\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/clock\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Clock = createLucideIcon('Clock', [\n ['circle', { cx: '12', cy: '12', r: '10', key: '1mglay' }],\n ['polyline', { points: '12 6 12 12 16 14', key: '68esgv' }],\n]);\n\nexport default Clock;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Delete\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/delete\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Delete = createLucideIcon('Delete', [\n [\n 'path',\n {\n d: 'M10 5a2 2 0 0 0-1.344.519l-6.328 5.74a1 1 0 0 0 0 1.481l6.328 5.741A2 2 0 0 0 10 19h10a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2z',\n key: '1yo7s0',\n },\n ],\n ['path', { d: 'm12 9 6 6', key: 'anjzzh' }],\n ['path', { d: 'm18 9-6 6', key: '1fp51s' }],\n]);\n\nexport default Delete;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name ExternalLink\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/external-link\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst ExternalLink = createLucideIcon('ExternalLink', [\n ['path', { d: 'M15 3h6v6', key: '1q9fwt' }],\n ['path', { d: 'M10 14 21 3', key: 'gplh6r' }],\n ['path', { d: 'M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6', key: 'a6xqqp' }],\n]);\n\nexport default ExternalLink;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Grid3x3\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/grid-3x3\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Grid3x3 = createLucideIcon('Grid3x3', [\n ['rect', { width: '18', height: '18', x: '3', y: '3', rx: '2', key: 'afitv7' }],\n ['path', { d: 'M3 9h18', key: '1pudct' }],\n ['path', { d: 'M3 15h18', key: '5xshup' }],\n ['path', { d: 'M9 3v18', key: 'fh3hqa' }],\n ['path', { d: 'M15 3v18', key: '14nvp0' }],\n]);\n\nexport default Grid3x3;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Hash\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/hash\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Hash = createLucideIcon('Hash', [\n ['line', { x1: '4', x2: '20', y1: '9', y2: '9', key: '4lhtct' }],\n ['line', { x1: '4', x2: '20', y1: '15', y2: '15', key: 'vyu0kd' }],\n ['line', { x1: '10', x2: '8', y1: '3', y2: '21', key: '1ggp8o' }],\n ['line', { x1: '16', x2: '14', y1: '3', y2: '21', key: 'weycgp' }],\n]);\n\nexport default Hash;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Headphones\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/headphones\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Headphones = createLucideIcon('Headphones', [\n [\n 'path',\n {\n d: 'M3 14h3a2 2 0 0 1 2 2v3a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7a9 9 0 0 1 18 0v7a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3',\n key: '1xhozi',\n },\n ],\n]);\n\nexport default Headphones;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name LoaderCircle\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/loader-circle\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst LoaderCircle = createLucideIcon('LoaderCircle', [\n ['path', { d: 'M21 12a9 9 0 1 1-6.219-8.56', key: '13zald' }],\n]);\n\nexport default LoaderCircle;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name MicOff\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/mic-off\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst MicOff = createLucideIcon('MicOff', [\n ['line', { x1: '2', x2: '22', y1: '2', y2: '22', key: 'a6p6uj' }],\n ['path', { d: 'M18.89 13.23A7.12 7.12 0 0 0 19 12v-2', key: '80xlxr' }],\n ['path', { d: 'M5 10v2a7 7 0 0 0 12 5', key: 'p2k8kg' }],\n ['path', { d: 'M15 9.34V5a3 3 0 0 0-5.68-1.33', key: '1gzdoj' }],\n ['path', { d: 'M9 9v3a3 3 0 0 0 5.12 2.12', key: 'r2i35w' }],\n ['line', { x1: '12', x2: '12', y1: '19', y2: '22', key: 'x3vr5v' }],\n]);\n\nexport default MicOff;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Mic\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/mic\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Mic = createLucideIcon('Mic', [\n ['path', { d: 'M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z', key: '131961' }],\n ['path', { d: 'M19 10v2a7 7 0 0 1-14 0v-2', key: '1vc78b' }],\n ['line', { x1: '12', x2: '12', y1: '19', y2: '22', key: 'x3vr5v' }],\n]);\n\nexport default Mic;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name MonitorSmartphone\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/monitor-smartphone\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst MonitorSmartphone = createLucideIcon('MonitorSmartphone', [\n ['path', { d: 'M18 8V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h8', key: '10dyio' }],\n ['path', { d: 'M10 19v-3.96 3.15', key: '1irgej' }],\n ['path', { d: 'M7 19h5', key: 'qswx4l' }],\n ['rect', { width: '6', height: '10', x: '16', y: '12', rx: '2', key: '1egngj' }],\n]);\n\nexport default MonitorSmartphone;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Music\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/music\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Music = createLucideIcon('Music', [\n ['path', { d: 'M9 18V5l12-2v13', key: '1jmyc2' }],\n ['circle', { cx: '6', cy: '18', r: '3', key: 'fqmcym' }],\n ['circle', { cx: '18', cy: '16', r: '3', key: '1hluhg' }],\n]);\n\nexport default Music;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Pause\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/pause\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Pause = createLucideIcon('Pause', [\n ['rect', { x: '14', y: '4', width: '4', height: '16', rx: '1', key: 'zuxfzm' }],\n ['rect', { x: '6', y: '4', width: '4', height: '16', rx: '1', key: '1okwgv' }],\n]);\n\nexport default Pause;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name PhoneIncoming\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/phone-incoming\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst PhoneIncoming = createLucideIcon('PhoneIncoming', [\n ['polyline', { points: '16 2 16 8 22 8', key: '1ygljm' }],\n ['line', { x1: '22', x2: '16', y1: '2', y2: '8', key: '1xzwqn' }],\n [\n 'path',\n {\n d: 'M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z',\n key: 'foiqr5',\n },\n ],\n]);\n\nexport default PhoneIncoming;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name PhoneMissed\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/phone-missed\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst PhoneMissed = createLucideIcon('PhoneMissed', [\n ['line', { x1: '22', x2: '16', y1: '2', y2: '8', key: '1xzwqn' }],\n ['line', { x1: '16', x2: '22', y1: '2', y2: '8', key: '13zxdn' }],\n [\n 'path',\n {\n d: 'M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z',\n key: 'foiqr5',\n },\n ],\n]);\n\nexport default PhoneMissed;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name PhoneOff\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/phone-off\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst PhoneOff = createLucideIcon('PhoneOff', [\n [\n 'path',\n {\n d: 'M10.68 13.31a16 16 0 0 0 3.41 2.6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7 2 2 0 0 1 1.72 2v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.42 19.42 0 0 1-3.33-2.67m-2.67-3.34a19.79 19.79 0 0 1-3.07-8.63A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91',\n key: 'z86iuo',\n },\n ],\n ['line', { x1: '22', x2: '2', y1: '2', y2: '22', key: '11kh81' }],\n]);\n\nexport default PhoneOff;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name PhoneOutgoing\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/phone-outgoing\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst PhoneOutgoing = createLucideIcon('PhoneOutgoing', [\n ['polyline', { points: '22 8 22 2 16 2', key: '1g204g' }],\n ['line', { x1: '16', x2: '22', y1: '8', y2: '2', key: '1ggias' }],\n [\n 'path',\n {\n d: 'M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z',\n key: 'foiqr5',\n },\n ],\n]);\n\nexport default PhoneOutgoing;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Phone\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/phone\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Phone = createLucideIcon('Phone', [\n [\n 'path',\n {\n d: 'M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07 19.5 19.5 0 0 1-6-6 19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 4.11 2h3a2 2 0 0 1 2 1.72 12.84 12.84 0 0 0 .7 2.81 2 2 0 0 1-.45 2.11L8.09 9.91a16 16 0 0 0 6 6l1.27-1.27a2 2 0 0 1 2.11-.45 12.84 12.84 0 0 0 2.81.7A2 2 0 0 1 22 16.92z',\n key: 'foiqr5',\n },\n ],\n]);\n\nexport default Phone;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Play\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/play\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Play = createLucideIcon('Play', [\n ['polygon', { points: '6 3 20 12 6 21 6 3', key: '1oa8hb' }],\n]);\n\nexport default Play;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Search\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/search\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Search = createLucideIcon('Search', [\n ['circle', { cx: '11', cy: '11', r: '8', key: '4ej97u' }],\n ['path', { d: 'm21 21-4.3-4.3', key: '1qie3q' }],\n]);\n\nexport default Search;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Settings\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/settings\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Settings = createLucideIcon('Settings', [\n [\n 'path',\n {\n d: 'M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z',\n key: '1qme2f',\n },\n ],\n ['circle', { cx: '12', cy: '12', r: '3', key: '1v7zrd' }],\n]);\n\nexport default Settings;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Timer\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/timer\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Timer = createLucideIcon('Timer', [\n ['line', { x1: '10', x2: '14', y1: '2', y2: '2', key: '14vaq8' }],\n ['line', { x1: '12', x2: '15', y1: '14', y2: '11', key: '17fdiu' }],\n ['circle', { cx: '12', cy: '14', r: '8', key: '1e1u0o' }],\n]);\n\nexport default Timer;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name TriangleAlert\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/triangle-alert\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst TriangleAlert = createLucideIcon('TriangleAlert', [\n [\n 'path',\n {\n d: 'm21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3',\n key: 'wmoenq',\n },\n ],\n ['path', { d: 'M12 9v4', key: 'juzpu7' }],\n ['path', { d: 'M12 17h.01', key: 'p32p05' }],\n]);\n\nexport default TriangleAlert;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name User\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/user\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst User = createLucideIcon('User', [\n ['path', { d: 'M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2', key: '975kel' }],\n ['circle', { cx: '12', cy: '7', r: '4', key: '17ys0d' }],\n]);\n\nexport default User;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Users\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/users\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Users = createLucideIcon('Users', [\n ['path', { d: 'M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2', key: '1yyitq' }],\n ['circle', { cx: '9', cy: '7', r: '4', key: 'nufk8' }],\n ['path', { d: 'M22 21v-2a4 4 0 0 0-3-3.87', key: 'kshegd' }],\n ['path', { d: 'M16 3.13a4 4 0 0 1 0 7.75', key: '1da9ce' }],\n]);\n\nexport default Users;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name Volume2\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/volume-2\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Volume2 = createLucideIcon('Volume2', [\n [\n 'path',\n {\n d: 'M11 4.702a.705.705 0 0 0-1.203-.498L6.413 7.587A1.4 1.4 0 0 1 5.416 8H3a1 1 0 0 0-1 1v6a1 1 0 0 0 1 1h2.416a1.4 1.4 0 0 1 .997.413l3.383 3.384A.705.705 0 0 0 11 19.298z',\n key: 'uqj9uw',\n },\n ],\n ['path', { d: 'M16 9a5 5 0 0 1 0 6', key: '1q6k2b' }],\n ['path', { d: 'M19.364 18.364a9 9 0 0 0 0-12.728', key: 'ijwkga' }],\n]);\n\nexport default Volume2;\n","import createLucideIcon from '../createLucideIcon';\n\n/**\n * @component @name X\n * @description Lucide SVG icon component, renders SVG Element with children.\n *\n * @preview  - https://lucide.dev/icons/x\n * @see https://lucide.dev/guide/packages/lucide-react - Documentation\n *\n * @param {Object} props - Lucide icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst X = createLucideIcon('X', [\n ['path', { d: 'M18 6 6 18', key: '1bl5f8' }],\n ['path', { d: 'm6 6 12 12', key: 'd8bk6v' }],\n]);\n\nexport default X;\n","/**\r\n * Country → dial code, flags and names — **data and platform APIs, not a dependency** (SPEC §11).\r\n *\r\n * The CRM reached all of this through `react-phone-number-input` + its flag SVGs: **82 kB brotli,\r\n * measured**. Everything below costs **~1 kB**, because the expensive parts are already in the\r\n * browser:\r\n *\r\n * - **names** → `Intl.DisplayNames`, localised, shipped with the runtime\r\n * - **codes** → the table below, 245 regions in 1,364 characters\r\n *\r\n * Flags are the exception and live in `CountryPicker`: real SVGs from `country-flag-icons`, 40 kB\r\n * brotli for all 245, **lazily imported** so they cost nothing until someone opens the picker. An\r\n * earlier cut used flag EMOJI (free, but Windows ships none and degrades to stray letters) — that is\r\n * gone: an SVG renders the same everywhere, and the emoji-support probe it needed went with it.\r\n *\r\n * What we give up is libphonenumber's parsing and validation — deliberately. A dialer must let you\r\n * dial anything: refusing a call because a number looks wrong for a region is a bug, not a feature.\r\n * We compose `+<code><digits>` and let the PBX decide.\r\n */\r\n\r\n/**\r\n * ISO 3166-1 alpha-2 immediately followed by its E.164 calling code, space-separated.\r\n *\r\n * Packed as one string rather than an object literal: no quotes, no colons, no commas — it compresses\r\n * to **729 bytes brotli**, and it parses once at module load into the Map below.\r\n *\r\n * GENERATED — do not hand-edit. Regenerate against a real source with:\r\n *\r\n * node -e \"const{getCountries,getCountryCallingCode}=require('libphonenumber-js/min');\\\r\n * console.log(getCountries().map(c=>c+getCountryCallingCode(c)).join(' '))\"\r\n */\r\nconst PACKED =\r\n 'AC247 AD376 AE971 AF93 AG1 AI1 AL355 AM374 AO244 AR54 AS1 AT43 AU61 AW297 AX358 AZ994 ' +\r\n 'BA387 BB1 BD880 BE32 BF226 BG359 BH973 BI257 BJ229 BL590 BM1 BN673 BO591 BQ599 BR55 BS1 ' +\r\n 'BT975 BW267 BY375 BZ501 CA1 CC61 CD243 CF236 CG242 CH41 CI225 CK682 CL56 CM237 CN86 CO57 ' +\r\n 'CR506 CU53 CV238 CW599 CX61 CY357 CZ420 DE49 DJ253 DK45 DM1 DO1 DZ213 EC593 EE372 EG20 ' +\r\n 'EH212 ER291 ES34 ET251 FI358 FJ679 FK500 FM691 FO298 FR33 GA241 GB44 GD1 GE995 GF594 ' +\r\n 'GG44 GH233 GI350 GL299 GM220 GN224 GP590 GQ240 GR30 GT502 GU1 GW245 GY592 HK852 HN504 ' +\r\n 'HR385 HT509 HU36 ID62 IE353 IL972 IM44 IN91 IO246 IQ964 IR98 IS354 IT39 JE44 JM1 JO962 ' +\r\n 'JP81 KE254 KG996 KH855 KI686 KM269 KN1 KP850 KR82 KW965 KY1 KZ7 LA856 LB961 LC1 LI423 ' +\r\n 'LK94 LR231 LS266 LT370 LU352 LV371 LY218 MA212 MC377 MD373 ME382 MF590 MG261 MH692 MK389 ' +\r\n 'ML223 MM95 MN976 MO853 MP1 MQ596 MR222 MS1 MT356 MU230 MV960 MW265 MX52 MY60 MZ258 NA264 ' +\r\n 'NC687 NE227 NF672 NG234 NI505 NL31 NO47 NP977 NR674 NU683 NZ64 OM968 PA507 PE51 PF689 ' +\r\n 'PG675 PH63 PK92 PL48 PM508 PR1 PS970 PT351 PW680 PY595 QA974 RE262 RO40 RS381 RU7 RW250 ' +\r\n 'SA966 SB677 SC248 SD249 SE46 SG65 SH290 SI386 SJ47 SK421 SL232 SM378 SN221 SO252 SR597 ' +\r\n 'SS211 ST239 SV503 SX1 SY963 SZ268 TA290 TC1 TD235 TG228 TH66 TJ992 TK690 TL670 TM993 ' +\r\n 'TN216 TO676 TR90 TT1 TV688 TW886 TZ255 UA380 UG256 US1 UY598 UZ998 VA39 VC1 VE58 VG1 VI1 ' +\r\n 'VN84 VU678 WF681 WS685 XK383 YE967 YT262 ZA27 ZM260 ZW263';\r\n\r\n/** ISO alpha-2 → calling code, e.g. `'ES' → 34`. */\r\nexport const DIAL_CODES: ReadonlyMap<string, number> = new Map(\r\n PACKED.split(' ').map((token) => [token.slice(0, 2), Number(token.slice(2))]),\r\n);\r\n\r\n/** Calling code → the regions that share it (`44 → ['GB','GG','IM','JE']`). */\r\nconst REGIONS_BY_CODE: ReadonlyMap<number, readonly string[]> = (() => {\r\n const map = new Map<number, string[]>();\r\n for (const [region, code] of DIAL_CODES) map.set(code, [...(map.get(code) ?? []), region]);\r\n return map;\r\n})();\r\n\r\n/** For a calling code several regions share, the one a number with it most likely belongs to. */\r\nconst MAIN_REGION: Readonly<Record<number, string>> = {\r\n 1: 'US', 7: 'RU', 39: 'IT', 44: 'GB', 47: 'NO', 61: 'AU', 212: 'MA', 262: 'RE', 290: 'SH', 358: 'FI', 590: 'GP',\r\n 599: 'CW',\r\n};\r\n\r\n/**\r\n * The region of a number typed in full international form — `'+44 20 7946 0958'` → `'GB'` — or `null` when it is\r\n * not one, or its calling code is not complete yet (`'+'`, `'+4'`). Calling codes are prefix-free (E.164), so the\r\n * first 1–3 digits that match one ARE the code.\r\n *\r\n * For the prefix chip to SHOW what the number already says (outbound-number-per-agent.md §5.5, 2026-10-26): display\r\n * only. The number is still dialled exactly as typed (`toE164`).\r\n */\r\nexport function regionOfInternational(typed: string): string | null {\r\n const text = String(typed ?? '').trim();\r\n if (!text.startsWith('+')) return null;\r\n const digits = text.slice(1).replace(/\\D/g, '');\r\n for (let length = 1; length <= Math.min(3, digits.length); length++) {\r\n const code = Number(digits.slice(0, length));\r\n const regions = REGIONS_BY_CODE.get(code);\r\n if (regions) return MAIN_REGION[code] ?? regions[0] ?? null;\r\n }\r\n return null;\r\n}\r\n\r\n/** The picker's default. Coventia is Spanish and so is the UI (SPEC §2.4). */\r\nexport const DEFAULT_COUNTRY = 'ES';\r\n\r\n// Built once, not per render — `Intl.DisplayNames` construction is not free, and this module is\r\n// imported by a component that re-renders on every keystroke.\r\nconst REGION_NAMES = (() => {\r\n try {\r\n return new Intl.DisplayNames(['es'], { type: 'region' });\r\n } catch {\r\n return null; // ancient runtime — fall back to the code\r\n }\r\n})();\r\n\r\n/** `'ES'` → `'España'`, localised by the platform. Falls back to the code. */\r\nexport function countryName(country: string): string {\r\n try {\r\n return REGION_NAMES?.of(country) ?? country;\r\n } catch {\r\n return country; // `of()` throws on codes it does not know (e.g. 'TA', 'XK')\r\n }\r\n}\r\n\r\nexport interface CountryOption {\r\n readonly code: string;\r\n readonly name: string;\r\n readonly dial: number;\r\n}\r\n\r\n/** Every country, sorted by localised name — the picker's list. Computed once. */\r\nexport const COUNTRIES: readonly CountryOption[] = [...DIAL_CODES.entries()]\r\n .map(([code, dial]) => ({ code, name: countryName(code), dial }))\r\n .sort((a, b) => a.name.localeCompare(b.name, 'es'));\r\n\r\n/**\r\n * Compose what the user sees into what the PBX gets: `('ES', '600 111 222')` → `'+34600111222'`.\r\n *\r\n * No validation, on purpose (see the module header). Two rules earn their place:\r\n * - a national number written with a trunk `0` (`06 12 34 56 78` in FR) must lose it, or the PBX\r\n * receives a number with a digit that only means something domestically;\r\n * - if the user typed a full international number themselves, respect it and do not prepend a\r\n * second country code.\r\n */\r\nexport function toE164(country: string, national: string): string {\r\n const typed = String(national ?? '').trim();\r\n if (typed.startsWith('+')) return '+' + typed.slice(1).replace(/\\D/g, '');\r\n\r\n const digits = typed.replace(/\\D/g, '').replace(/^0+/, '');\r\n if (!digits) return '';\r\n const dial = DIAL_CODES.get(country);\r\n return dial === undefined ? `+${digits}` : `+${dial}${digits}`;\r\n}\r\n","import { useEffect, useMemo, useRef, useState, type ComponentType } from 'react';\r\nimport { Check, ChevronDown } from 'lucide-react';\r\nimport { COUNTRIES, DIAL_CODES, countryName } from './countries.js';\r\n\r\ntype FlagSet = Readonly<Record<string, ComponentType<{ className?: string }> | undefined>>;\r\n\r\n/**\r\n * Real SVG flags, fetched once, on nobody's critical path.\r\n *\r\n * All 245 are **40 kB brotli** and cannot tree-shake (the picker looks them up by code), which is a\r\n * lot to put in front of every consumer for a chip most never open. Named imports shake to ~350 B\r\n * each, so this is the one place the cost is unavoidable — and the one place it is easy to defer.\r\n *\r\n * Module-level, not per component: the chip and 245 rows share one import and one chunk. tsup emits\r\n * it as a relative chunk, so `/element` stays self-contained (`verify-static` walks relative imports)\r\n * and a CDN `<script type=\"module\">` resolves it fine.\r\n */\r\nlet FLAGS: FlagSet | null = null;\r\nlet flagsPromise: Promise<FlagSet> | null = null;\r\n\r\nfunction loadFlags(): Promise<FlagSet> {\r\n flagsPromise ??= import('country-flag-icons/react/3x2')\r\n .then((m) => (FLAGS = m as FlagSet))\r\n .catch(() => (FLAGS = {})); // offline / blocked: keep the plates, never break the dialer\r\n return flagsPromise;\r\n}\r\n\r\nfunction useFlags(): FlagSet | null {\r\n const [flags, setFlags] = useState<FlagSet | null>(FLAGS);\r\n useEffect(() => {\r\n if (flags) return;\r\n let alive = true;\r\n void loadFlags().then((f) => {\r\n if (alive) setFlags(f);\r\n });\r\n return () => {\r\n alive = false;\r\n };\r\n }, [flags]);\r\n return flags;\r\n}\r\n\r\n/**\r\n * The country mark: a flag, or the ISO code set into a plate.\r\n *\r\n * **Both are designed states in one 20×14 box** — a flag's own 3:2 — so the chip and every row keep\r\n * their rhythm regardless of which is showing. Nothing reflows when the flags arrive.\r\n *\r\n * The plate is the LOADING state (and the offline state), not a fallback. That distinction is the\r\n * whole design: there is no flash of something broken, only a designed plate becoming a designed flag\r\n * once, on the first widget of the session.\r\n */\r\nfunction CountryMark({ code }: Readonly<{ code: string }>) {\r\n const flags = useFlags();\r\n const Flag = flags?.[code];\r\n return (\r\n <span className=\"cv-mark\" data-plate={!Flag} aria-hidden part=\"country-mark\">\r\n {Flag ? <Flag className=\"cv-mark-svg\" /> : code}\r\n </span>\r\n );\r\n}\r\n\r\n/**\r\n * The prefix chip: flag + dial code, opening a searchable country list.\r\n *\r\n * Own combobox — no `cmdk`, no Radix `Popover`, no `ScrollArea` (S7 dropped those with the rest of\r\n * shadcn). It is a `<button>` and a positioned `<div>`, which is all the CRM's version was underneath.\r\n *\r\n * Search matches the localised NAME, the ISO code, and the dial code, so \"esp\", \"ES\" and \"+34\" all\r\n * find Spain — the CRM's `CommandItem value={`${name} ${code} +${calling}`}` did the same thing, and\r\n * it is the difference between a picker you can use and one you scroll for twenty seconds.\r\n *\r\n * `fromNumber`: the number being dialled is typed in full (\"+44 …\"), so IT says the country and the chip only\r\n * shows it — read-only, not a choice (it used to keep showing +34 against a \"+44\" number). `value` is then the\r\n * number's region, or `''` while its calling code is still incomplete (\"+4\").\r\n */\r\nexport function CountryPicker({\r\n value,\r\n onChange,\r\n fromNumber = false,\r\n}: Readonly<{ value: string; onChange: (code: string) => void; fromNumber?: boolean }>) {\r\n const [open, setOpen] = useState(false);\r\n const [query, setQuery] = useState('');\r\n const rootRef = useRef<HTMLDivElement>(null);\r\n const inputRef = useRef<HTMLInputElement>(null);\r\n\r\n // A number typed in full while the list is open makes the choice moot: close it.\r\n useEffect(() => {\r\n if (fromNumber) setOpen(false);\r\n }, [fromNumber]);\r\n\r\n const results = useMemo(() => {\r\n const q = query.trim().toLowerCase().replace(/^\\+/, '');\r\n if (!q) return COUNTRIES;\r\n return COUNTRIES.filter(\r\n (c) =>\r\n c.name.toLowerCase().includes(q) ||\r\n c.code.toLowerCase().includes(q) ||\r\n String(c.dial).startsWith(q),\r\n );\r\n }, [query]);\r\n\r\n // Close on outside click / Escape. Deliberately on the SHADOW ROOT's node when there is one:\r\n // inside a shadow tree, `document` click targets are retargeted to the host, so `contains()`\r\n // against the host would report every internal click as \"outside\" and the list would never open.\r\n useEffect(() => {\r\n if (!open) return;\r\n const root = rootRef.current?.getRootNode() ?? document;\r\n const onDown = (e: Event) => {\r\n if (!rootRef.current?.contains(e.target as Node)) setOpen(false);\r\n };\r\n const onKey = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') setOpen(false);\r\n };\r\n root.addEventListener('pointerdown', onDown);\r\n document.addEventListener('keydown', onKey);\r\n return () => {\r\n root.removeEventListener('pointerdown', onDown);\r\n document.removeEventListener('keydown', onKey);\r\n };\r\n }, [open]);\r\n\r\n useEffect(() => {\r\n if (open) inputRef.current?.focus();\r\n else setQuery('');\r\n }, [open]);\r\n\r\n const dial = DIAL_CODES.get(value);\r\n\r\n if (fromNumber) {\r\n return (\r\n <div className=\"cv-cp\" ref={rootRef}>\r\n {/* The flag only: the number beside it already spells out its \"+44\". */}\r\n <span className=\"cv-cp-chip\" data-from-number title=\"El prefijo viene del número marcado\" part=\"country-chip\">\r\n <CountryMark code={value || '+'} />\r\n <span className=\"cv-sr-only\">\r\n {dial ? `Prefijo del número marcado: ${countryName(value)} (+${dial})` : 'Prefijo del número marcado'}\r\n </span>\r\n </span>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"cv-cp\" ref={rootRef}>\r\n <button\r\n type=\"button\"\r\n className=\"cv-cp-chip\"\r\n onClick={() => setOpen((o) => !o)}\r\n aria-haspopup=\"listbox\"\r\n aria-expanded={open}\r\n // The mark is aria-hidden — a flag glyph reads as \"flag of Spain\" or, on a plate, as the bare\r\n // letters \"ES\". Neither is what a screen-reader user needs, so the name carries it instead.\r\n aria-label={`Prefijo: ${countryName(value)} (+${dial ?? '?'}). Cambiar país`}\r\n part=\"country-chip\"\r\n >\r\n <CountryMark code={value} />\r\n <span className=\"cv-cp-dial\">+{dial ?? '?'}</span>\r\n <ChevronDown size={13} className=\"cv-cp-caret\" data-open={open} />\r\n </button>\r\n\r\n {open ? (\r\n <div className=\"cv-cp-pop\" role=\"dialog\" part=\"country-list\">\r\n <input\r\n ref={inputRef}\r\n className=\"cv-cp-search\"\r\n value={query}\r\n onChange={(e) => setQuery(e.target.value)}\r\n placeholder=\"Buscar país…\"\r\n aria-label=\"Buscar país\"\r\n />\r\n <div className=\"cv-cp-list\" role=\"listbox\">\r\n {results.length === 0 ? (\r\n <p className=\"cv-cp-empty\">No se encontró ningún país.</p>\r\n ) : (\r\n results.map((c) => (\r\n <button\r\n key={c.code}\r\n type=\"button\"\r\n role=\"option\"\r\n aria-selected={c.code === value}\r\n className=\"cv-cp-item\"\r\n onClick={() => {\r\n onChange(c.code);\r\n setOpen(false);\r\n }}\r\n >\r\n <CountryMark code={c.code} />\r\n <span className=\"cv-cp-name\">{c.name}</span>\r\n <span className=\"cv-cp-dial\">+{c.dial}</span>\r\n <Check size={14} className=\"cv-cp-check\" data-on={c.code === value} />\r\n </button>\r\n ))\r\n )}\r\n </div>\r\n </div>\r\n ) : null}\r\n </div>\r\n );\r\n}\r\n","/**\r\n * As-you-type national grouping — `600111222` → `600 11 12 22`.\r\n *\r\n * **Lazily imported, like the flags.** `libphonenumber-js/min` is 27 kB brotli, which is 3× the whole\r\n * `/ui` entry, and it is needed only once someone actually types. Preloaded on mount so it is there\r\n * before a human can reach the keypad; until then digits render unformatted and then snap into\r\n * groups, which is a far better failure than blocking first paint on a formatting table.\r\n *\r\n * **Why a library at all**, when `countries.ts` deliberately avoids one: there is no universal rule.\r\n *\r\n * ES 600111222 → 600 11 12 22 (3-2-2-2)\r\n * FR 0612345678 → 06 12 34 56 78 (2-2-2-2-2)\r\n * GB 07911123456 → 07911 123456 (5-6)\r\n * DE 01701234567 → 0170 1234567 (4-7)\r\n *\r\n * GB and DE group differently again for landlines. A hand-rolled table would be wrong for most of the\r\n * world, and wrong grouping reads as broken rather than as a simplification. This is grouping ONLY —\r\n * we still do not validate, and `toE164` is still the thing that decides what gets dialled.\r\n */\r\nimport { useEffect, useState } from 'react';\r\n\r\ntype AsYouTypeCtor = new (country?: string) => { input(text: string): string };\r\ntype ParseIntl = (text: string) => { formatInternational(): string } | undefined;\r\n\r\nlet AsYouType: AsYouTypeCtor | null = null;\r\nlet parseIntl: ParseIntl | null = null;\r\nlet loading: Promise<void> | null = null;\r\n\r\n/**\r\n * Fetch the metadata once per page. Safe to call repeatedly; resolves immediately once loaded.\r\n *\r\n * One shared load for BOTH formatters this file exports (`formatNational` for as-you-type in the\r\n * dialer, `formatIntl` for a full E.164 number on the contact detail page) — same 27 kB chunk either\r\n * way, so a second consumer must not pay for it twice or drift onto a second copy of the metadata.\r\n */\r\nexport function loadNumberFormatter(): Promise<void> {\r\n loading ??= import('libphonenumber-js/min')\r\n .then((m) => {\r\n AsYouType = m.AsYouType as unknown as AsYouTypeCtor;\r\n parseIntl = m.parsePhoneNumberFromString as unknown as ParseIntl;\r\n })\r\n .catch(() => {\r\n // Offline, blocked, or a bundler that could not fetch the chunk: keep dialing with plain\r\n // digits. Formatting is a nicety; the dialer is not.\r\n });\r\n return loading;\r\n}\r\n\r\n/**\r\n * A full E.164 number (`+34600111222`) as it is normally written (`+34 600 11 12 22`). Same\r\n * never-empty-never-mangled contract as `formatNational`: the raw number until metadata loads or on\r\n * any parse failure — a contact's own phone number is never worth blocking on or hiding behind a\r\n * formatting error.\r\n */\r\nexport function formatIntl(e164: string): string {\r\n if (!parseIntl) return e164;\r\n try {\r\n return parseIntl(e164)?.formatInternational() ?? e164;\r\n } catch {\r\n return e164;\r\n }\r\n}\r\n\r\n/** Subscribe a component to the formatter, the same way `useNumberFormatter` does for typing. */\r\nexport function useIntlFormatter(): typeof formatIntl {\r\n const [, bump] = useState(0);\r\n useEffect(() => {\r\n if (parseIntl) return;\r\n let alive = true;\r\n void loadNumberFormatter().then(() => {\r\n if (alive) bump((n) => n + 1);\r\n });\r\n return () => {\r\n alive = false;\r\n };\r\n }, []);\r\n return formatIntl;\r\n}\r\n\r\n/**\r\n * Group `digits` the way `country` writes them. Returns the input unchanged until the metadata has\r\n * loaded, and on any parse failure — so the display is always *at worst* the digits the user typed,\r\n * never empty and never mangled.\r\n */\r\nexport function formatNational(country: string, digits: string): string {\r\n if (!AsYouType || !digits) return digits;\r\n try {\r\n return new AsYouType(country).input(digits);\r\n } catch {\r\n return digits;\r\n }\r\n}\r\n\r\n/**\r\n * Subscribe a component to the formatter. Returns `formatNational`, re-rendering once when the\r\n * metadata lands so an already-typed number regroups itself.\r\n */\r\nexport function useNumberFormatter(): typeof formatNational {\r\n const [, bump] = useState(0);\r\n useEffect(() => {\r\n if (AsYouType) return;\r\n let alive = true;\r\n void loadNumberFormatter().then(() => {\r\n if (alive) bump((n) => n + 1);\r\n });\r\n return () => {\r\n alive = false;\r\n };\r\n }, []);\r\n return formatNational;\r\n}\r\n\r\n/**\r\n * Where the caret belongs after reformatting, counted in DIGITS rather than characters.\r\n *\r\n * Without this, inserting a digit mid-number reformats the string, the caret snaps to the end, and\r\n * the next keystroke lands somewhere the user did not choose. Counting digits is the only stable\r\n * anchor, because the separators are exactly what moves.\r\n */\r\nexport function caretAfterDigits(formatted: string, digitsBefore: number): number {\r\n if (digitsBefore <= 0) return 0;\r\n let seen = 0;\r\n for (let i = 0; i < formatted.length; i++) {\r\n if (/\\d/.test(formatted[i]!)) seen++;\r\n if (seen === digitsBefore) return i + 1;\r\n }\r\n return formatted.length;\r\n}\r\n\r\n/** Digits appearing before `caret` in `text` — the position we must preserve across a reformat. */\r\nexport function digitsBeforeCaret(text: string, caret: number): number {\r\n return (text.slice(0, caret).match(/\\d/g) ?? []).length;\r\n}\r\n","/**\r\n * The 3×4 grid every phone has — shared between the pre-call dialer (`Dialpad`) and the in-call DTMF\r\n * panel (`CallScreen`). One types a number, the other sends tones, but it's the same physical pad\r\n * either way, so the layout lives once.\r\n */\r\nexport const KEYPAD_KEYS: ReadonlyArray<readonly [key: string, letters: string]> = [\r\n ['1', ''],\r\n ['2', 'ABC'],\r\n ['3', 'DEF'],\r\n ['4', 'GHI'],\r\n ['5', 'JKL'],\r\n ['6', 'MNO'],\r\n ['7', 'PQRS'],\r\n ['8', 'TUV'],\r\n ['9', 'WXYZ'],\r\n ['*', ''],\r\n ['0', '+'],\r\n ['#', ''],\r\n];\r\n","/**\r\n * The built-in ringtone, \"Clásico\" — redesigned 2026-10-15 (custom-ringtone.md §4.5).\r\n *\r\n * It is both a ringtone users can pick and the fallback whenever a chosen file is not ready, so it has to be\r\n * generated in code (no file, no download, nothing that can fail) AND sound like the rest of the catalogue.\r\n *\r\n * The old Clásico was a pure 425 Hz sine. Matched to the catalogue's −16 LUFS it all but vanished on laptop\r\n * speakers: 100 % of its energy sat below 500 Hz, exactly where small speakers roll off, with no harmonics to\r\n * carry it. It was only ever audible because it played at −8 LUFS, 8 dB louder than anything else.\r\n *\r\n * This is the classic telephone double ring — ring (0.4 s), 0.2 s, ring (0.4 s), silence, every 3 s — played as\r\n * a fast FM-mallet tremolo on a major third (C6/E6, 20 strikes per second): the same recipe as the catalogue's\r\n * mallet ringtones (an FM pair with harmonicity 4 and an index that decays in ~60 ms; the deviation follows\r\n * Tone.js's FMSynth, index × the note's frequency). Measured with ITU-R BS.1770 on an offline render of this\r\n * exact graph: −16.0 LUFS at `CLASSIC_GAIN`, true peak −5.8 dBTP, 98 % of its energy in 1–4 kHz.\r\n */\r\n\r\nconst C6 = 1046.5;\r\nconst E6 = 1318.51;\r\nconst HARMONICITY = 4;\r\nconst INDEX = 1.8;\r\n\r\n/** One cycle: two rings and the silence after them. */\r\nexport const CLASSIC_CYCLE_SECONDS = 3;\r\n/** Output gain that puts this graph at −16 LUFS (measured, see above). Retune only by re-measuring. */\r\nexport const CLASSIC_GAIN = 0.3841;\r\n\r\n/**\r\n * The fixed part of the graph: high-pass 250 Hz and low-pass 7.5 kHz (24 dB/oct each — the catalogue's band),\r\n * then the output gain, into `dest`. Returns where strikes connect, and the output (to disconnect on stop).\r\n */\r\nexport function classicRingGraph(ctx: BaseAudioContext, dest: AudioNode): { input: AudioNode; output: GainNode } {\r\n const output = ctx.createGain();\r\n output.gain.value = CLASSIC_GAIN;\r\n const chain = (['highpass', 'highpass', 'lowpass', 'lowpass'] as const).map((type) => {\r\n const f = ctx.createBiquadFilter();\r\n f.type = type;\r\n f.frequency.value = type === 'highpass' ? 250 : 7500;\r\n f.Q.value = 0.707;\r\n return f;\r\n });\r\n for (let i = 0; i < chain.length - 1; i++) chain[i]!.connect(chain[i + 1]!);\r\n chain[chain.length - 1]!.connect(output);\r\n output.connect(dest);\r\n return { input: chain[0]!, output };\r\n}\r\n\r\n/** One mallet strike at `t`: FM pair + amplitude envelope (5 ms attack, short decay, a ~0.35 s release). */\r\nfunction strike(ctx: BaseAudioContext, input: AudioNode, t: number, freq: number, vel: number, track: (o: OscillatorNode) => void): void {\r\n const carrier = ctx.createOscillator();\r\n carrier.frequency.value = freq;\r\n const modulator = ctx.createOscillator();\r\n modulator.frequency.value = freq * HARMONICITY;\r\n const depth = ctx.createGain(); // frequency deviation, in Hz\r\n depth.gain.setValueAtTime(0, t);\r\n depth.gain.linearRampToValueAtTime(INDEX * freq, t + 0.004);\r\n depth.gain.setTargetAtTime(0, t + 0.004, 0.02); // the bright attack fades in ~60 ms\r\n modulator.connect(depth);\r\n depth.connect(carrier.frequency);\r\n\r\n const amp = ctx.createGain();\r\n amp.gain.setValueAtTime(0, t);\r\n amp.gain.linearRampToValueAtTime(vel, t + 0.005);\r\n amp.gain.setTargetAtTime(0, t + 0.005, 0.15); // decay\r\n amp.gain.setTargetAtTime(0, t + 0.045, 0.08); // note off after 45 ms → release\r\n carrier.connect(amp);\r\n amp.connect(input);\r\n\r\n for (const o of [carrier, modulator]) {\r\n o.start(t);\r\n o.stop(t + 0.7);\r\n track(o);\r\n }\r\n}\r\n\r\n/**\r\n * Schedules one cycle starting at `t0` (context time) into `input` (from `classicRingGraph`). `track` receives\r\n * every oscillator created, so a caller can stop the ones still scheduled. Returns the cycle length.\r\n */\r\nexport function scheduleClassicCycle(ctx: BaseAudioContext, input: AudioNode, t0: number, track: (o: OscillatorNode) => void): number {\r\n for (const ring of [0, 0.6]) {\r\n for (let i = 0; i < 8; i++) strike(ctx, input, t0 + ring + i * 0.05, i % 2 ? E6 : C6, 0.55 + 0.1 * (i % 2), track);\r\n }\r\n return CLASSIC_CYCLE_SECONDS;\r\n}\r\n","import { classicRingGraph, scheduleClassicCycle } from './classic-ring.js';\r\n\r\n/**\r\n * Everything the softphone plays: the remote party, the inbound ring, the outbound ringback, the\r\n * end-of-call cue, and the keypad's key tones.\r\n *\r\n * Framework-free and lazy — nothing here touches `AudioContext`, `Audio` or `URL.createObjectURL`\r\n * at module scope, so importing it under SSR is safe (SPEC §10.2). The legacy code built the ringback\r\n * blob at module scope, which would have thrown on any server render.\r\n *\r\n * `core/` deliberately does not create audio elements: it hands the stream out and the UI attaches it\r\n * (see `CallEvent.RemoteStream`). This is the UI half of that contract.\r\n */\r\n\r\n/** 425 Hz — the EU/ES call-progress tone. Both the ring and the ringback are built on it. */\r\nconst TONE_HZ = 425;\r\n\r\n// ── Remote party ────────────────────────────────────────────────────────────\r\n\r\nexport interface RemoteAudio {\r\n attach(stream: MediaStream): void;\r\n detach(): void;\r\n destroy(): void;\r\n /**\r\n * Route the remote party to a specific output device, or `null` for the browser's own default\r\n * (SPEC §7 Phase 2 — device management). A no-op when the browser has no `setSinkId` (Safari, most\r\n * of Firefox — see `AudioDevices.canSelectOutput`), and swallows a rejection from an\r\n * already-unplugged device rather than throwing into a caller that has no useful recovery for it.\r\n */\r\n setOutputDevice(deviceId: string | null): Promise<void>;\r\n}\r\n\r\n/**\r\n * The `<audio>` element that plays the person on the other end.\r\n *\r\n * **Without this there is no call audio at all** — a `MediaStream` from `ontrack` is silent until it\r\n * is attached to a media element. The SDK exposed `call.remoteStream` and nothing consumed it.\r\n *\r\n * A media element rather than Web Audio, for the same reason as the ringback below: it follows the OS\r\n * default output device and survives Bluetooth A2DP↔HFP transitions.\r\n */\r\nexport function createRemoteAudio(): RemoteAudio {\r\n const el = document.createElement('audio');\r\n el.autoplay = true;\r\n // Off-screen but IN the document: some browsers will not play a detached element.\r\n el.style.display = 'none';\r\n document.body.appendChild(el);\r\n\r\n return {\r\n attach(stream) {\r\n el.srcObject = stream;\r\n // Rejects only under autoplay policy, which the dial/answer click already satisfied.\r\n void el.play().catch(() => {});\r\n },\r\n detach() {\r\n el.srcObject = null;\r\n },\r\n destroy() {\r\n el.srcObject = null;\r\n el.remove();\r\n },\r\n async setOutputDevice(deviceId) {\r\n if (typeof el.setSinkId !== 'function') return;\r\n try {\r\n // `''` is the spec's own way of saying \"the default device\" — the same meaning `null` carries\r\n // on this method's own signature, translated at this one boundary rather than asking every\r\n // caller to know the DOM's convention.\r\n await el.setSinkId(deviceId ?? '');\r\n } catch {\r\n // A device that vanished between selection and this call landing (unplugged, or a stale ID\r\n // from a previous session) — nothing useful to do beyond leaving the previous route in place.\r\n }\r\n },\r\n };\r\n}\r\n\r\n// ── Inbound ring ────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * ONE `AudioContext` for the page, created on demand and never closed.\r\n *\r\n * Ringing used to build a fresh context per call and close it on hangup. That produced three Firefox\r\n * warnings on every inbound call — *\"An AudioContext was prevented from starting automatically…\"* —\r\n * because an INVITE is not a user gesture, so the context, its oscillator and its `resume()` were all\r\n * created outside one. The ring still played (the user had clicked something earlier in the session),\r\n * but a console that cries wolf on a healthy path is how real warnings get ignored.\r\n *\r\n * Sharing it also avoids a limit worth knowing about: Chrome caps a page at ~6 live `AudioContext`s,\r\n * and `close()` is asynchronous — so a burst of short calls could reach it and leave the phone silent.\r\n *\r\n * Not closed on teardown deliberately: a suspended context costs nothing, and the next ring needs it\r\n * ready before any gesture is available.\r\n */\r\nlet shared: AudioContext | null = null;\r\n\r\nfunction sharedContext(): AudioContext | null {\r\n if (shared) return shared;\r\n const Ctor: typeof AudioContext | undefined =\r\n typeof AudioContext !== 'undefined'\r\n ? AudioContext\r\n : (globalThis as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\r\n if (!Ctor) return null;\r\n shared = new Ctor();\r\n return shared;\r\n}\r\n\r\n/**\r\n * Build the shared context **inside a user gesture**, so it starts `running` and nothing later has to\r\n * ask for permission it cannot get.\r\n *\r\n * Call from a click/keydown handler. Idempotent and safe to call when audio is already unlocked; on a\r\n * browser with no Web Audio it is a no-op.\r\n */\r\nexport function primeAudio(): void {\r\n const ctx = sharedContext();\r\n if (ctx && ctx.state === 'suspended') void ctx.resume?.().catch(() => {});\r\n}\r\n\r\n/** @internal — tests only: forget the shared context so each case starts clean. */\r\nexport function __resetSharedAudioForTests(): void {\r\n shared = null;\r\n}\r\n\r\nexport interface Tone {\r\n stop(): void;\r\n}\r\n\r\n/**\r\n * The inbound ring: the chosen ringtone file, or the built-in \"Clásico\" (`classic-ring.ts`), looping until\r\n * answered or gone.\r\n *\r\n * Web Audio rather than a file: there is no asset to ship or license, and during INBOUND ringing the\r\n * microphone is not open — so the tone is not subject to the OS \"communications\" ducking that would\r\n * silence a locally generated tone while a mic is live. (Outbound is the opposite case; see below.)\r\n *\r\n * **The look-ahead scheduler is not premature optimisation.** Scheduling each cycle at\r\n * `ctx.currentTime` from a chained `setTimeout` lands the rising ramp at or behind the live audio\r\n * clock on Chrome, which silently drops the cycle — the symptom is \"it rings once, then nothing\"\r\n * (Firefox tolerates it, so it looks fine in one browser). Instead the audio clock is kept ~0.5 s\r\n * filled, topped up every 150 ms, always scheduling on a future-dated accumulator.\r\n *\r\n * **Level and sound: matched to the ringtone catalogue — revised 2026-10-15.** The history matters here. The\r\n * built-in ring was a pure 425 Hz sine: shipped at gain 0.18 (\"gentle\"), raised to 0.8 (−8 LUFS) because a\r\n * missed call is the one failure you cannot recover from by looking at the screen later, then lowered to the\r\n * catalogue's −16 LUFS so that choosing a ringtone or falling back never changes the volume — at which point\r\n * it all but vanished on laptop speakers (all of its energy below 500 Hz, where they roll off). It is now an\r\n * FM-mallet version of the same double ring, in the catalogue's 1–4 kHz band, at the same measured −16 LUFS\r\n * (`classic-ring.ts`). The end-of-call cue and the ringback keep their 425 Hz sines at their louder levels —\r\n * quieter, they would vanish the same way (decided 2026-10-15).\r\n */\r\nexport function playRingtone(options: RingtonePlayback = {}): Tone {\r\n const ctx = sharedContext();\r\n if (!ctx) return { stop() {} };\r\n\r\n // The ring's own bus: whatever voice rings feeds it, and `routeToDevice` decides where it is heard.\r\n const bus = ctx.createGain();\r\n const route = routeToDevice(ctx, bus, options.sinkId ?? null);\r\n const voice = options.buffer ? fileVoice(ctx, bus, options.buffer, options.loop ?? null) : synthesisedVoice(ctx, bus);\r\n return {\r\n stop() {\r\n voice.stop();\r\n route.stop();\r\n },\r\n };\r\n}\r\n\r\n/** What `playRingtone` rings, and where (custom-ringtone.md §4.5). Both optional: today's tone, default output. */\r\nexport interface RingtonePlayback {\r\n /**\r\n * A decoded ringtone file, looped. Absent or `null` = the built-in synthesised tone below — which is also\r\n * what rings whenever the chosen file is not decoded yet: the choice is made once, when ringing starts, and\r\n * held for the whole ring (switching sounds mid-ring reads as a glitch).\r\n */\r\n readonly buffer?: AudioBuffer | null;\r\n /**\r\n * Where the music sits inside `buffer` (seconds): looped between these points rather than over the whole\r\n * buffer, which would include the MP3's start delay and end padding — a stumble at every restart of a\r\n * continuous ringtone. `null`/absent = loop the whole buffer.\r\n */\r\n readonly loop?: { readonly start: number; readonly end: number } | null;\r\n /** The ringtone output device (`AudioDevices.currentRingtoneOutputId`), or `null` for the default output. */\r\n readonly sinkId?: string | null;\r\n}\r\n\r\n/**\r\n * A chosen ringtone file, looped until stopped.\r\n *\r\n * Starts on a short future-dated fade-in, like the synthesised tone, so the first sample is never scheduled\r\n * at or behind the live clock (see the look-ahead note above) and never starts with a click. The level is\r\n * the file's own: catalogue files are normalised when they are added (custom-ringtone.md §4.1), so they need\r\n * no per-file gain here.\r\n */\r\nfunction fileVoice(\r\n ctx: AudioContext,\r\n bus: AudioNode,\r\n buffer: AudioBuffer,\r\n loop: { readonly start: number; readonly end: number } | null,\r\n): Tone {\r\n const FILE_LEVEL = 1;\r\n const RAMP = 0.02;\r\n const LEAD = 0.08;\r\n\r\n const gain = ctx.createGain();\r\n gain.gain.value = 0;\r\n gain.connect(bus);\r\n const src = ctx.createBufferSource();\r\n src.buffer = buffer;\r\n src.loop = true;\r\n // Loop points only if they fit inside this buffer; otherwise loop all of it (never a broken loop).\r\n const points = loop && loop.start >= 0 && loop.end > loop.start && loop.end <= buffer.duration + 0.001 ? loop : null;\r\n if (points) {\r\n src.loopStart = points.start;\r\n src.loopEnd = points.end;\r\n }\r\n src.connect(gain);\r\n\r\n let stopped = false;\r\n void Promise.resolve(ctx.resume?.())\r\n .catch(() => {})\r\n .finally(() => {\r\n if (stopped) return;\r\n const at = ctx.currentTime + LEAD;\r\n gain.gain.setValueAtTime(0, at);\r\n gain.gain.linearRampToValueAtTime(FILE_LEVEL, at + RAMP);\r\n // Start where the music starts — skipping the MP3's start delay the first time round too.\r\n src.start(at, points?.start ?? 0);\r\n });\r\n\r\n return {\r\n stop() {\r\n stopped = true;\r\n try {\r\n src.stop();\r\n } catch {\r\n /* never started, or already stopped */\r\n }\r\n try {\r\n gain.disconnect();\r\n } catch {\r\n /* ignore */\r\n }\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Where a locally generated sound is heard — the ring, and the speaker test.\r\n *\r\n * - **No device chosen:** straight to the shared context's own output — exactly what the ring always did.\r\n * - **A device chosen:** the bus feeds a `MediaStreamAudioDestinationNode`, played by a hidden `<audio>` whose\r\n * `setSinkId` picks the device. A media element because it is the routing both Chrome and Firefox have —\r\n * `AudioContext.setSinkId` failed outright in the T1 spike on real hardware (custom-ringtone-plan.md) — and\r\n * because, like the ringback's element, it follows a device across Bluetooth profile switches instead of\r\n * being stranded on a stale endpoint. Only this bus goes there: the shared context's own output — the\r\n * end-of-call cue, the key tones — is untouched.\r\n *\r\n * **Never silence.** If the element cannot be routed or cannot play (an unplugged device, a browser without\r\n * `setSinkId`, an autoplay refusal), the sound falls back to the default output, mid-play if need be.\r\n */\r\nfunction routeToDevice(ctx: AudioContext, bus: GainNode, sinkId: string | null): Tone {\r\n const toDefault = (): void => {\r\n bus.connect(ctx.destination);\r\n };\r\n const el = sinkId && typeof document !== 'undefined' ? document.createElement('audio') : null;\r\n const dest = el && typeof ctx.createMediaStreamDestination === 'function' ? ctx.createMediaStreamDestination() : null;\r\n const canRoute = el && dest && typeof (el as { setSinkId?: unknown }).setSinkId === 'function';\r\n\r\n if (!canRoute || !sinkId) {\r\n toDefault();\r\n return { stop: () => safeDisconnect(bus) };\r\n }\r\n\r\n let stopped = false;\r\n el.style.display = 'none';\r\n el.srcObject = dest.stream;\r\n document.body.appendChild(el);\r\n bus.connect(dest);\r\n void (el as HTMLAudioElement & { setSinkId(id: string): Promise<void> })\r\n .setSinkId(sinkId)\r\n .then(() => el.play())\r\n .catch((error: unknown) => {\r\n if (stopped) return;\r\n console.warn('[softphone] sound could not be sent to the chosen device; using the default output', error);\r\n safeDisconnect(bus);\r\n teardown(el);\r\n toDefault();\r\n });\r\n\r\n return {\r\n stop() {\r\n stopped = true;\r\n safeDisconnect(bus);\r\n teardown(el);\r\n },\r\n };\r\n}\r\n\r\nfunction safeDisconnect(node: AudioNode): void {\r\n try {\r\n node.disconnect();\r\n } catch {\r\n /* ignore */\r\n }\r\n}\r\n\r\nfunction teardown(el: HTMLAudioElement): void {\r\n el.pause();\r\n el.srcObject = null;\r\n el.remove();\r\n}\r\n\r\n/** How long `playTestTone` lasts, for a caller that shows \"playing\" while it does. */\r\nexport const TEST_TONE_MS = 900;\r\n\r\n/**\r\n * Ajustes → Altavoces → \"Probar altavoz\" (custom-ringtone.md §4.6): two short rising notes on the chosen call\r\n * output, so a user can hear where call audio will come out before a call. Same device routing as the ring.\r\n * Stops on its own after `TEST_TONE_MS`; `stop()` cuts it short (leaving the page).\r\n */\r\nexport function playTestTone(sinkId: string | null): Tone {\r\n const ctx = sharedContext();\r\n if (!ctx) return { stop() {} };\r\n const bus = ctx.createGain();\r\n const route = routeToDevice(ctx, bus, sinkId);\r\n\r\n const LEVEL = 0.5;\r\n const NOTES = [\r\n { hz: 660, at: 0.05 },\r\n { hz: 880, at: 0.4 },\r\n ];\r\n const oscs: OscillatorNode[] = [];\r\n let stopped = false;\r\n let timer: ReturnType<typeof setTimeout> | null = null;\r\n\r\n const stop = (): void => {\r\n if (stopped) return;\r\n stopped = true;\r\n if (timer) clearTimeout(timer);\r\n for (const o of oscs) {\r\n try {\r\n o.stop();\r\n } catch {\r\n /* never started, or already over */\r\n }\r\n }\r\n route.stop();\r\n };\r\n\r\n void Promise.resolve(ctx.resume?.())\r\n .catch(() => {})\r\n .finally(() => {\r\n if (stopped) return;\r\n const t0 = ctx.currentTime;\r\n for (const { hz, at } of NOTES) {\r\n const gain = ctx.createGain();\r\n gain.gain.value = 0;\r\n gain.connect(bus);\r\n const osc = ctx.createOscillator();\r\n osc.type = 'sine';\r\n osc.frequency.value = hz;\r\n osc.connect(gain);\r\n const start = t0 + at;\r\n gain.gain.setValueAtTime(0, start);\r\n gain.gain.linearRampToValueAtTime(LEVEL, start + 0.015);\r\n gain.gain.setValueAtTime(LEVEL, start + 0.25);\r\n gain.gain.linearRampToValueAtTime(0, start + 0.32);\r\n osc.start(start);\r\n osc.stop(start + 0.34);\r\n oscs.push(osc);\r\n }\r\n timer = setTimeout(stop, TEST_TONE_MS);\r\n });\r\n\r\n return { stop };\r\n}\r\n\r\n/**\r\n * The built-in ring, \"Clásico\": the classic double ring as an FM-mallet tremolo (`classic-ring.ts` — the sound,\r\n * and why it replaced the 425 Hz sine). This function only drives it: the look-ahead scheduler below keeps the\r\n * audio clock filled with whole cycles, and `stop()` silences the output and stops every oscillator already\r\n * scheduled.\r\n */\r\nfunction synthesisedVoice(ctx: AudioContext, bus: AudioNode): Tone {\r\n const { input, output } = classicRingGraph(ctx, bus);\r\n const scheduled = new Set<OscillatorNode>();\r\n const track = (o: OscillatorNode): void => {\r\n scheduled.add(o);\r\n o.onended = () => scheduled.delete(o);\r\n };\r\n\r\n const LOOKAHEAD = 0.5;\r\n const TICK_MS = 150;\r\n const LEAD = 0.08; // so the first cycle is never scheduled at exactly \"now\"\r\n\r\n let stopped = false;\r\n let timer: ReturnType<typeof setInterval> | null = null;\r\n let nextAt = 0;\r\n\r\n const pump = (): void => {\r\n while (nextAt < ctx.currentTime + LOOKAHEAD) nextAt += scheduleClassicCycle(ctx, input, nextAt, track);\r\n };\r\n\r\n // Resume first: a fresh context may be suspended by autoplay policy. By the time a call rings the\r\n // user has interacted with the softphone, so this succeeds; if not, it degrades to silence.\r\n void Promise.resolve(ctx.resume?.())\r\n .catch(() => {})\r\n .finally(() => {\r\n if (stopped) return;\r\n nextAt = ctx.currentTime + LEAD;\r\n pump();\r\n timer = setInterval(pump, TICK_MS);\r\n });\r\n\r\n return {\r\n stop() {\r\n stopped = true;\r\n if (timer) clearInterval(timer);\r\n for (const o of scheduled) {\r\n try {\r\n o.stop();\r\n } catch {\r\n /* never started, or already over */\r\n }\r\n }\r\n scheduled.clear();\r\n try {\r\n output.disconnect();\r\n } catch {\r\n /* ignore */\r\n }\r\n // The context is SHARED and outlives the ring — see `sharedContext`. Closing it here is what\r\n // forced a new one per call, and a context built outside a user gesture is what Firefox warns\r\n // about. Only the nodes are disposable.\r\n },\r\n };\r\n}\r\n\r\n// ── Call ended ──────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * The \"call has ended\" cue: ONE short 425 Hz beep, fired once a LIVE call is hung up — by either\r\n * side. Without it the call screen just disappears, which reads as a dropped connection rather than\r\n * an ordinary goodbye; a real phone always gives you SOMETHING before it goes back to the dial tone.\r\n *\r\n * A single beep, not a repeating pattern — this is a device-level confirmation click, not one of the\r\n * network's own call-progress tones (the ring and ringback ARE those, which is why they alone match\r\n * the ETSI/Telefónica cadence: 425 Hz, 1.5 s on, 3 s off). Spain has no standardised \"call ended\"\r\n * network tone to replicate; the closest real-world precedent is each platform's own end-of-call\r\n * click — iOS plays three short 425 Hz bursts, Android a single soft one. A single beep is what\r\n * Spanish users actually expect here, so that is what this plays, kept on the same 425 Hz the rest of\r\n * this file already uses for consistency.\r\n *\r\n * **Loud and sharp, NOT gentle** — this first shipped at the ringtone's own `LEVEL`/`RAMP`, on the\r\n * unexamined assumption that \"quiet and soft\" was a safe default throughout this file. It is the\r\n * wrong instinct here: a ring is heard from across a room and must not startle, but a goodbye click\r\n * is a confirmation the user is already looking at their screen for and expects to be unmistakable —\r\n * \"you notice that sound immediately\" was the actual bar. `LEVEL` now sits above even the ringback's\r\n * own 0.5 amp, and `RAMP` is a fraction of the ringtone's — an audible, percussive click rather than\r\n * a fade-in a quiet room can still miss.\r\n *\r\n * Web Audio, like the ringtone, not a media element like the ringback: this fires as the call is\r\n * already tearing down, so — unlike the ringback — there is no still-open microphone to route around\r\n * a Bluetooth profile switch for. A fire-and-forget cue on the shared context is simpler than a WAV\r\n * blob for something this short.\r\n *\r\n * Deliberately NOT looping and NOT cancellable — one beep and it is done on its own. Nothing in\r\n * `useCallAudio` needs to stop this mid-flight the way the ring/ringback do, so it does not return a\r\n * `Tone`.\r\n */\r\nexport function playCallEndedTone(): void {\r\n const ctx = sharedContext();\r\n if (!ctx) return;\r\n\r\n const gain = ctx.createGain();\r\n gain.gain.value = 0;\r\n gain.connect(ctx.destination);\r\n\r\n const osc = ctx.createOscillator();\r\n osc.type = 'sine';\r\n osc.frequency.value = TONE_HZ;\r\n osc.connect(gain);\r\n osc.start();\r\n\r\n const LEVEL = 0.55; // louder than the ringback (0.5) — a deliberate goodbye click, not a background tone\r\n const RAMP = 0.008; // sharp, percussive attack — long enough not to click, short enough to feel instant\r\n const BEEP = 0.25; // long enough to register as a deliberate signal, short enough to stay \"a beep\"\r\n\r\n void Promise.resolve(ctx.resume?.())\r\n .catch(() => {})\r\n .finally(() => {\r\n const at = ctx.currentTime + 0.02;\r\n gain.gain.setValueAtTime(0, at);\r\n gain.gain.linearRampToValueAtTime(LEVEL, at + RAMP);\r\n gain.gain.setValueAtTime(LEVEL, at + BEEP - RAMP);\r\n gain.gain.linearRampToValueAtTime(0, at + BEEP);\r\n\r\n const totalMs = (at + BEEP - ctx.currentTime) * 1000;\r\n setTimeout(() => {\r\n try {\r\n osc.stop();\r\n } catch {\r\n /* already stopped */\r\n }\r\n try {\r\n gain.disconnect();\r\n } catch {\r\n /* ignore */\r\n }\r\n }, totalMs);\r\n });\r\n}\r\n\r\n// ── Key tones ───────────────────────────────────────────────────────────────\r\n\r\n/**\r\n * The keypad's own sound: each key is the SUM of one row tone and one column tone (ITU-T Q.23 — the\r\n * same pairs every phone on earth uses). The frequencies, not a recording, so there is nothing to\r\n * ship or license; Zadarma's own widget bundles proprietary `.wav` tones that are not ours to reuse.\r\n *\r\n * Rows are listed as the keypad is drawn (1-2-3 / 4-5-6 / 7-8-9 / *-0-#), so a key's position IS its\r\n * pair. The fourth column (A–D, 1633 Hz) is not on a phone keypad and is deliberately absent.\r\n */\r\nconst DTMF_ROWS_HZ = [697, 770, 852, 941] as const;\r\nconst DTMF_COLS_HZ = [1209, 1336, 1477] as const;\r\nconst DTMF_LAYOUT = ['123', '456', '789', '*0#'] as const;\r\n\r\n/** The two frequencies for a keypad key, or `null` for anything that is not one of the 12 keys. */\r\nexport function dtmfFrequencies(key: string): readonly [number, number] | null {\r\n if (key.length !== 1) return null; // `indexOf('')` is 0 — \"no key\" must not read as the first key\r\n for (let row = 0; row < DTMF_LAYOUT.length; row++) {\r\n const col = DTMF_LAYOUT[row]!.indexOf(key);\r\n if (col !== -1) return [DTMF_ROWS_HZ[row]!, DTMF_COLS_HZ[col]!];\r\n }\r\n return null;\r\n}\r\n\r\n/**\r\n * A short local tone for a keypad press — what every phone plays so you KNOW the key registered.\r\n *\r\n * Without it the keypad is silent, and mid-call that costs more than it looks: DTMF goes out as a SIP\r\n * INFO message, which the far end acts on but which the local user never hears, so an agent keying an\r\n * IVR menu option has no feedback at all that the digit went anywhere.\r\n *\r\n * Fire-and-forget on the shared context, like `playCallEndedTone` — nothing here needs to be stopped\r\n * early. Presses overlap rather than queue, as on a real phone: a fast run of digits each gets its\r\n * own tone instead of a backlog that plays on after the user has stopped typing.\r\n *\r\n * Plays on the page's default output, not the device chosen in Dispositivos — the same as the\r\n * ring and the end-of-call cue (only the remote party's `<audio>` element follows that selection).\r\n *\r\n * `LEVEL` is the gain node's own peak; two unit sines sum to 2, so the signal peaks at 0.4 of full\r\n * scale — firmly audible, a notch under the end-of-call cue's 0.55, and not tiring across the ten or\r\n * more presses of a phone number. It is one constant: retune it by ear.\r\n */\r\nexport function playKeyTone(key: string): void {\r\n const hz = dtmfFrequencies(key);\r\n if (!hz) return;\r\n const ctx = sharedContext();\r\n if (!ctx) return;\r\n\r\n const LEVEL = 0.2;\r\n const RAMP = 0.006; // long enough not to click, short enough to feel instant\r\n const DURATION = 0.12; // the 100 ms JsSIP puts on the wire, plus the fades\r\n const LEAD = 0.01; // a ramp at or behind the live clock is dropped on Chrome — see `playRingtone`\r\n\r\n const gain = ctx.createGain();\r\n gain.gain.value = 0;\r\n gain.connect(ctx.destination);\r\n\r\n const oscillators = hz.map((freq) => {\r\n const osc = ctx.createOscillator();\r\n osc.type = 'sine';\r\n osc.frequency.value = freq;\r\n osc.connect(gain);\r\n osc.start();\r\n return osc;\r\n });\r\n\r\n const fire = (): void => {\r\n const at = ctx.currentTime + LEAD;\r\n gain.gain.setValueAtTime(0, at);\r\n gain.gain.linearRampToValueAtTime(LEVEL, at + RAMP);\r\n gain.gain.setValueAtTime(LEVEL, at + DURATION - RAMP);\r\n gain.gain.linearRampToValueAtTime(0, at + DURATION);\r\n for (const osc of oscillators) osc.stop(at + DURATION);\r\n // The nodes are disposable; the context is shared and outlives them (see `sharedContext`).\r\n oscillators[0]!.onended = () => gain.disconnect();\r\n };\r\n\r\n // Already unlocked (the first gesture on the page primes it — see `primeAudio`): play NOW, with no\r\n // promise hop in front of a key press. Otherwise resume first — this click is itself a gesture.\r\n if (ctx.state === 'running') fire();\r\n else void Promise.resolve(ctx.resume?.()).catch(() => {}).finally(fire);\r\n}\r\n\r\n// ── Outbound ringback ───────────────────────────────────────────────────────\r\n\r\nlet ringbackUrl: string | null = null;\r\n\r\n/**\r\n * The EU/ES ringback loop as a WAV blob: 425 Hz, 1.5 s tone, 3 s silence.\r\n *\r\n * **Stereo 48 kHz 16-bit PCM, deliberately.** A mono 8 kHz source went silent on a device configured\r\n * for a single channel — Chrome's mono-source→mono-endpoint path drops it. Stereo plays directly on\r\n * stereo devices and downmixes cleanly on mono ones.\r\n *\r\n * A Blob URL rather than a `data:` URI: Chrome treats a Blob URL as a real media resource, while\r\n * `data:` URIs stall when looped.\r\n */\r\nfunction ringbackSource(): string {\r\n if (ringbackUrl) return ringbackUrl;\r\n\r\n const sampleRate = 48_000;\r\n const channels = 2;\r\n const bytesPerSample = 2;\r\n const amp = 0.5;\r\n const toneSec = 1.5;\r\n const silenceSec = 3;\r\n const totalFrames = Math.round((toneSec + silenceSec) * sampleRate);\r\n const toneFrames = Math.round(toneSec * sampleRate);\r\n const ramp = Math.round(0.02 * sampleRate); // 20 ms fades, or it clicks\r\n\r\n const blockAlign = channels * bytesPerSample;\r\n const dataSize = totalFrames * blockAlign;\r\n const buffer = new ArrayBuffer(44 + dataSize);\r\n const view = new DataView(buffer);\r\n const str = (off: number, s: string): void => {\r\n for (let i = 0; i < s.length; i++) view.setUint8(off + i, s.charCodeAt(i));\r\n };\r\n\r\n str(0, 'RIFF');\r\n view.setUint32(4, 36 + dataSize, true);\r\n str(8, 'WAVE');\r\n str(12, 'fmt ');\r\n view.setUint32(16, 16, true); // PCM chunk size\r\n view.setUint16(20, 1, true); // PCM\r\n view.setUint16(22, channels, true);\r\n view.setUint32(24, sampleRate, true);\r\n view.setUint32(28, sampleRate * blockAlign, true); // byte rate\r\n view.setUint16(32, blockAlign, true);\r\n view.setUint16(34, bytesPerSample * 8, true);\r\n str(36, 'data');\r\n view.setUint32(40, dataSize, true);\r\n\r\n for (let i = 0; i < totalFrames; i++) {\r\n let sample = 0;\r\n if (i < toneFrames) {\r\n let env = 1;\r\n if (i < ramp) env = i / ramp;\r\n else if (i > toneFrames - ramp) env = Math.max(0, (toneFrames - i) / ramp);\r\n sample = Math.sin(2 * Math.PI * TONE_HZ * (i / sampleRate)) * amp * env;\r\n }\r\n const s16 = Math.round(sample * 32767);\r\n const off = 44 + i * blockAlign;\r\n for (let c = 0; c < channels; c++) view.setInt16(off + c * bytesPerSample, s16, true);\r\n }\r\n\r\n ringbackUrl = URL.createObjectURL(new Blob([buffer], { type: 'audio/wav' }));\r\n return ringbackUrl;\r\n}\r\n\r\n/**\r\n * Outbound ringback, played the way production softphones do it: a looping `HTMLAudioElement`, NOT\r\n * the Web Audio API.\r\n *\r\n * A media element follows the OS default output device when it changes, and Chrome re-routes it\r\n * across Bluetooth A2DP↔HFP transitions. An `AudioContext` binds to whichever endpoint existed when\r\n * it was created and gets stranded on a stale one after the headset cycles profiles — which made a\r\n * Web Audio ringback miss intermittently on back-to-back calls.\r\n *\r\n * A media element rather than Web Audio for a second reason too: JsSIP opens the real microphone when\r\n * an outbound call is placed, so on Bluetooth the headset switches to HFP as the ringback starts. An\r\n * element follows the OS default endpoint across that switch; a Web Audio graph would stay bound to\r\n * the one that existed when it was built.\r\n */\r\nexport function playRingback(): Tone {\r\n const el = document.createElement('audio');\r\n el.src = ringbackSource();\r\n el.loop = true;\r\n el.style.display = 'none';\r\n document.body.appendChild(el);\r\n void el.play().catch(() => {});\r\n\r\n return {\r\n stop() {\r\n el.pause();\r\n el.remove();\r\n },\r\n };\r\n}\r\n","import { useCallback, useEffect, useState, useSyncExternalStore } from 'react';\r\nimport type { Softphone } from '../../core/softphone.js';\r\nimport type { OutboundNumber, OutboundNumberSettings, OutboundNumbersSource } from '../../core/types.js';\r\nimport { formatIntl } from '../dialing/format-number.js';\r\n\r\n/**\r\n * The agent's outbound number (outbound-number-per-agent.md §5.5).\r\n *\r\n * ONE per softphone, shared by every place that shows or changes it — the dialpad's \"Llamar desde\", the call\r\n * screen's \"Desde …\" and Ajustes — so a change made in one is what the others show, with one fetch between them.\r\n *\r\n * **Nothing here runs when a call is placed.** The number lives on the agent's extension at Zadarma; placing a call\r\n * never asks for it. Settings are fetched when the dialpad opens (the store is shared, so overlapping triggers cost\r\n * one request).\r\n */\r\nexport interface OutboundNumberStore {\r\n /** As last fetched, or `null` before the first successful fetch. */\r\n getSettings(): OutboundNumberSettings | null;\r\n /** Re-fetches. Never rejects. The first refresh starts from what this device remembers, if anything. */\r\n refresh(): Promise<void>;\r\n /** Changes the choice. REJECTS on failure (a refusal is recognisable with `isOutboundNumberRefused`). */\r\n setMine(id: string | null): Promise<void>;\r\n subscribe(listener: () => void): () => void;\r\n}\r\n\r\nconst stores = new WeakMap<Softphone, OutboundNumberStore>();\r\n\r\n/** The store for `softphone`, or `null` when it has no Coventia backend (no outbound numbers at all). */\r\nexport function outboundNumberStore(softphone: Softphone): OutboundNumberStore | null {\r\n const source = softphone.sources?.outboundNumbers;\r\n if (!source) return null;\r\n let store = stores.get(softphone);\r\n if (!store) {\r\n store = createOutboundNumberStore(source);\r\n stores.set(softphone, store);\r\n }\r\n return store;\r\n}\r\n\r\n/** Exported for tests; production code goes through `outboundNumberStore(softphone)`. */\r\nexport function createOutboundNumberStore(source: OutboundNumbersSource): OutboundNumberStore {\r\n let settings: OutboundNumberSettings | null = null;\r\n let inFlight: Promise<void> | null = null;\r\n const listeners = new Set<() => void>();\r\n\r\n const apply = (next: OutboundNumberSettings): void => {\r\n settings = next;\r\n for (const l of listeners) l();\r\n };\r\n\r\n return {\r\n getSettings: () => settings,\r\n\r\n refresh() {\r\n inFlight ??= (async () => {\r\n if (!settings && source.cached) {\r\n const early = await source.cached().catch(() => null);\r\n if (early && !settings) apply(early);\r\n }\r\n try {\r\n apply(await source.get());\r\n } catch (error) {\r\n console.warn('[softphone] outbound numbers could not be loaded; keeping the previous ones', error);\r\n } finally {\r\n inFlight = null;\r\n }\r\n })();\r\n return inFlight;\r\n },\r\n\r\n async setMine(id) {\r\n apply(await source.setMine(id));\r\n },\r\n\r\n subscribe(listener) {\r\n listeners.add(listener);\r\n return () => listeners.delete(listener);\r\n },\r\n };\r\n}\r\n\r\nconst noSubscribe = () => () => {};\r\nconst noSettings = () => null;\r\n\r\n/** The settings for a view, fetched when it mounts. `failed`: the first fetch failed and nothing is known. */\r\nexport function useOutboundNumbers(store: OutboundNumberStore | null) {\r\n const settings = useSyncExternalStore(store?.subscribe ?? noSubscribe, store?.getSettings ?? noSettings);\r\n const [failed, setFailed] = useState(false);\r\n\r\n const load = useCallback(() => {\r\n if (!store) return () => {};\r\n let live = true;\r\n setFailed(false);\r\n void store.refresh().then(() => {\r\n if (live) setFailed(store.getSettings() === null);\r\n });\r\n return () => {\r\n live = false;\r\n };\r\n }, [store]);\r\n\r\n useEffect(load, [load]);\r\n return { settings, failed, retry: load };\r\n}\r\n\r\n/** The settings as already known, WITHOUT fetching — for views that only label a number (e.g. the call history). */\r\nexport function useKnownOutboundNumbers(store: OutboundNumberStore | null): OutboundNumberSettings | null {\r\n return useSyncExternalStore(store?.subscribe ?? noSubscribe, store?.getSettings ?? noSettings);\r\n}\r\n\r\n/** Whole seconds left until `until` (epoch ms), ticking once a second; 0 once it has passed (or `null`). */\r\nexport function useCountdown(until: number | null): number {\r\n // Computed on every render, not held in state: a state copy is stale on the render right after `until` changes\r\n // (it would read 0 for one frame, which is \"the wait is over\"). The timer only makes it render once a second.\r\n const [, setTick] = useState(0);\r\n useEffect(() => {\r\n if (!until) return undefined;\r\n const timer = setInterval(() => {\r\n setTick((n) => n + 1);\r\n if (secondsLeft(until) === 0) clearInterval(timer);\r\n }, 1000);\r\n return () => clearInterval(timer);\r\n }, [until]);\r\n return secondsLeft(until);\r\n}\r\n\r\nfunction secondsLeft(until: number | null): number {\r\n return until ? Math.max(0, Math.ceil((until - Date.now()) / 1000)) : 0;\r\n}\r\n\r\n/**\r\n * How a number is named in the UI: its label, else the formatted number. Views pass `useIntlFormatter()`'s\r\n * formatter, so they re-render with the grouped number once the phone metadata has loaded.\r\n */\r\nexport function numberName(n: OutboundNumber | undefined | null, format: (n: string) => string = formatIntl): string {\r\n if (!n) return 'Número de la organización';\r\n return n.label || format(`+${n.number}`);\r\n}\r\n\r\n/** The number the agent's calls show, as an object (or `undefined` when none is known). */\r\nexport function effectiveNumber(settings: OutboundNumberSettings | null): OutboundNumber | undefined {\r\n return settings?.numbers.find((n) => n.id === settings.effective);\r\n}\r\n","import { useEffect, useState } from 'react';\r\nimport { isOutboundNumberRefused } from '../../core/outbound-numbers.js';\r\nimport type { OutboundNumber, OutboundNumberSettings } from '../../core/types.js';\r\nimport { useCountdown, type OutboundNumberStore } from './outbound-number-store.js';\r\n\r\n/** The usage rule shown under a number whose kind needs care (Orden TDF/149/2025 art. 9; BOE-A-2026-8409). */\r\nexport const KIND_TAG: Readonly<\r\n Partial<Record<OutboundNumber['kind'], { readonly tag: string; readonly hint: string }>>\r\n> = {\r\n mobile: { tag: 'Móvil', hint: 'No usar para atención al cliente ni para llamadas comerciales no solicitadas.' },\r\n commercial: { tag: 'Comercial (400)', hint: 'Solo para llamadas comerciales. No recibe llamadas.' },\r\n};\r\n\r\ntype Notice =\r\n | { readonly kind: 'refused'; readonly reason: 'platform' | 'user'; readonly until: number }\r\n | { readonly kind: 'error'; readonly text: string };\r\n\r\n/**\r\n * The words for each situation (outbound-number-per-agent.md §5.5). They describe what happens and what the\r\n * agent can do — never that the agent did something wrong: the usual cause is the shared limit on number\r\n * changes, which nothing the agent did can explain (decided 2026-10-21).\r\n */\r\nexport function noticeText(\r\n situation: 'platform' | 'user' | 'wait' | 'pending',\r\n seconds: number,\r\n current: string,\r\n): string {\r\n switch (situation) {\r\n case 'platform':\r\n return `El cambio de número de salida no está disponible temporalmente. Vuelve a intentarlo en ${seconds} s. Hasta entonces, tus llamadas seguirán saliendo desde ${current}.`;\r\n case 'user':\r\n return `Acabas de cambiar el número de salida. Podrás cambiarlo de nuevo en ${seconds} s. Hasta entonces, tus llamadas saldrán desde ${current}.`;\r\n case 'wait':\r\n return `Podrás cambiar el número de salida en ${seconds} s.`;\r\n case 'pending':\r\n return seconds > 0\r\n ? `Tu número de salida todavía no se ha aplicado. Podrás volver a elegirlo en ${seconds} s.`\r\n : 'Tu número de salida todavía no se ha aplicado. Vuelve a elegirlo para aplicarlo.';\r\n }\r\n}\r\n\r\n/**\r\n * Changing the agent's outbound number — shared by the dialpad's \"Llamar desde\" and Ajustes → Número de salida, so\r\n * both lock, count down and word things the same way (outbound-number-per-agent.md §5.5). One change in flight at a\r\n * time; a refusal locks the choice until its `retryAfterSeconds` have passed, counting down live.\r\n *\r\n * `current` is how the number the agent's calls show right now is named — the refusal messages say it.\r\n */\r\nexport function useOutboundNumberChange(\r\n store: OutboundNumberStore | null,\r\n settings: OutboundNumberSettings | null,\r\n current: string,\r\n) {\r\n const [busy, setBusy] = useState(false);\r\n const [notice, setNotice] = useState<Notice | null>(null);\r\n const [waitUntil, setWaitUntil] = useState<number | null>(null);\r\n\r\n // The backend says when the next change could go out (the shared limit or this agent's own recent change).\r\n useEffect(() => {\r\n const s = settings?.changeAvailableInSeconds ?? 0;\r\n setWaitUntil(s > 0 ? Date.now() + s * 1000 : null);\r\n }, [settings]);\r\n\r\n const refusedUntil = notice?.kind === 'refused' ? notice.until : null;\r\n const blockedFor = useCountdown(refusedUntil ?? waitUntil);\r\n\r\n useEffect(() => {\r\n if (notice?.kind === 'refused' && blockedFor === 0) setNotice(null);\r\n }, [notice, blockedFor]);\r\n\r\n const locked = busy || blockedFor > 0;\r\n\r\n /** Applies `id` (`null` = the organization's default). `true` once it is the agent's choice; `false` otherwise. */\r\n const choose = async (id: string | null): Promise<boolean> => {\r\n if (!store || !settings || locked) return false;\r\n if (id === settings.mine) return true;\r\n setBusy(true);\r\n setNotice(null);\r\n try {\r\n await store.setMine(id);\r\n return true;\r\n } catch (error) {\r\n setNotice(\r\n isOutboundNumberRefused(error)\r\n ? { kind: 'refused', reason: error.refusal.reason, until: Date.now() + error.refusal.retryAfterSeconds * 1000 }\r\n : { kind: 'error', text: errorText(error) },\r\n );\r\n return false;\r\n } finally {\r\n setBusy(false);\r\n }\r\n };\r\n\r\n return {\r\n busy,\r\n locked,\r\n choose,\r\n /** What to say about the choice right now, if anything. */\r\n message: settings ? currentMessage(notice, settings.state, blockedFor, current) : null,\r\n /** The message is an error (the change failed), not information (wait, pending). */\r\n isError: notice?.kind === 'error',\r\n };\r\n}\r\n\r\n/** A refusal or error first, then the extension's state. */\r\nfunction currentMessage(\r\n notice: Notice | null,\r\n state: OutboundNumberSettings['state'],\r\n blockedFor: number,\r\n current: string,\r\n): string | null {\r\n if (notice?.kind === 'refused') return blockedFor > 0 ? noticeText(notice.reason, blockedFor, current) : null;\r\n if (notice?.kind === 'error') return notice.text;\r\n if (state === 'pending' || state === 'failed') return noticeText('pending', blockedFor, current);\r\n return blockedFor > 0 ? noticeText('wait', blockedFor, current) : null;\r\n}\r\n\r\n/** The backend's own Spanish message when it sent one; never a raw \"HTTP 502\". */\r\nfunction errorText(error: unknown): string {\r\n const message = error instanceof Error ? error.message : '';\r\n return message && !/HTTP \\d+/.test(message)\r\n ? message\r\n : 'No se ha podido cambiar el número de salida. Inténtalo de nuevo.';\r\n}\r\n","import { useEffect, useRef, useState, type KeyboardEvent } from 'react';\r\nimport { Check, ChevronDown, Loader2 } from 'lucide-react';\r\nimport { useSoftphone } from '../../react/index.js';\r\nimport { useIntlFormatter } from '../dialing/format-number.js';\r\nimport { KIND_TAG, useOutboundNumberChange } from './outbound-change.js';\r\nimport { effectiveNumber, numberName, outboundNumberStore, useOutboundNumbers } from './outbound-number-store.js';\r\n\r\n/** How long the \"did not go through\" callout stays under the \"Llamar desde\" strip (exported for tests). */\r\nexport const CALLOUT_MS = 6_000;\r\n\r\n/**\r\n * \"Llamar desde\": which of the organization's numbers this agent's calls show. A light \"Llamar desde: X ▾\" line right\r\n * above the number field — the FROM of the call, before the number it goes TO — opening the organization's numbers\r\n * under it, as the providers' dialers do (outbound-number-per-agent.md §5.5, 2026-10-26).\r\n *\r\n * Hidden when there is nothing to choose — no Coventia backend, or fewer than two numbers.\r\n *\r\n * **Optimistic** (decided 2026-10-23): choosing closes the list at once and the chip shows the new number with a\r\n * spinner while Zadarma applies it — but the call button stays disabled until it has (`onBusyChange`), so a call\r\n * never goes out from a number the screen shows and Zadarma does not. A refusal or error puts the chip back and says\r\n * why in a callout under it, counting down; reopening the list shows the same words. Still one request per change.\r\n *\r\n * Keyboard: the list opens on the selected number; arrows, Home/End and type-ahead move through it (WAI-ARIA\r\n * listbox); Escape or a choice closes it and puts focus back on the strip.\r\n */\r\nexport function OutboundNumberPicker({ onBusyChange }: Readonly<{ onBusyChange?: (busy: boolean) => void }>) {\r\n const softphone = useSoftphone();\r\n const store = outboundNumberStore(softphone);\r\n const { settings } = useOutboundNumbers(store);\r\n const formatIntl = useIntlFormatter();\r\n const current = settings ? numberName(effectiveNumber(settings), formatIntl) : '';\r\n const { busy, locked, choose: apply, message, isError } = useOutboundNumberChange(store, settings, current);\r\n const [open, setOpen] = useState(false);\r\n /** The choice being applied, shown at once: `undefined` = none, `null` = the organization's default. */\r\n const [applying, setApplying] = useState<string | null | undefined>(undefined);\r\n /** A change just did not go through: its reason shows under the strip until it passes or is dismissed. */\r\n const [callout, setCallout] = useState(false);\r\n const rootRef = useRef<HTMLDivElement>(null);\r\n const chipRef = useRef<HTMLButtonElement>(null);\r\n const keys = useListKeyboard(open);\r\n\r\n useEffect(() => onBusyChange?.(busy), [busy, onBusyChange]);\r\n\r\n // The refusal's countdown ran out (or the next change cleared it): nothing left to say.\r\n useEffect(() => {\r\n if (!message) setCallout(false);\r\n }, [message]);\r\n\r\n // It sits over the number being dialled: gone after a few seconds even if the wait is longer. The wait itself\r\n // stays — the reopened list still says it, counting down — and placing a call is never blocked by a refusal.\r\n useEffect(() => {\r\n if (!callout) return undefined;\r\n const timer = setTimeout(() => setCallout(false), CALLOUT_MS);\r\n return () => clearTimeout(timer);\r\n }, [callout]);\r\n\r\n // Close on outside click / Escape — on the SHADOW ROOT's node when there is one (see CountryPicker).\r\n const floating = open || callout;\r\n useEffect(() => {\r\n if (!floating) return;\r\n const close = () => {\r\n setOpen(false);\r\n setCallout(false);\r\n };\r\n const root = rootRef.current?.getRootNode() ?? document;\r\n const onDown = (e: Event) => {\r\n if (!rootRef.current?.contains(e.target as Node)) close();\r\n };\r\n const onKey = (e: globalThis.KeyboardEvent) => {\r\n if (e.key !== 'Escape') return;\r\n if (rootRef.current?.contains(e.target as Node)) chipRef.current?.focus();\r\n close();\r\n };\r\n root.addEventListener('pointerdown', onDown);\r\n document.addEventListener('keydown', onKey);\r\n return () => {\r\n root.removeEventListener('pointerdown', onDown);\r\n document.removeEventListener('keydown', onKey);\r\n };\r\n }, [floating]);\r\n\r\n if (!store || !settings || settings.numbers.length < 2) return null;\r\n\r\n const orgDefault = settings.numbers.find((n) => n.id === settings.orgDefault);\r\n const applyingNumber = applying === null ? orgDefault : settings.numbers.find((n) => n.id === applying);\r\n const shown = applying === undefined ? current : numberName(applyingNumber, formatIntl);\r\n\r\n const choose = async (id: string | null): Promise<void> => {\r\n if (locked) return; // the list says why\r\n setOpen(false);\r\n chipRef.current?.focus();\r\n if (id === settings.mine) return;\r\n setCallout(false);\r\n setApplying(id);\r\n const applied = await apply(id);\r\n setApplying(undefined); // applied → the settings now say it; not → back to the number still in use\r\n if (!applied) setCallout(true);\r\n };\r\n\r\n return (\r\n <div className=\"cv-on\" ref={rootRef}>\r\n {/* A labelled line, not a pill like the prefix: what it is says itself (\"Llamar desde:\"). */}\r\n <button\r\n ref={chipRef}\r\n type=\"button\"\r\n className=\"cv-on-chip\"\r\n onClick={() => {\r\n setCallout(false);\r\n setOpen((o) => !o);\r\n }}\r\n aria-haspopup=\"listbox\"\r\n aria-expanded={open}\r\n aria-label={`Llamar desde: ${shown}${busy ? ' (aplicando)' : ''}. Cambiar número de salida`}\r\n aria-busy={busy}\r\n part=\"outbound-number-chip\"\r\n >\r\n <span className=\"cv-on-label\">Llamar desde:</span>\r\n {busy ? <Loader2 size={13} className=\"cv-on-icon cv-on-spin\" aria-hidden /> : null}\r\n <span className=\"cv-on-current\">{shown}</span>\r\n <ChevronDown size={13} className=\"cv-cp-caret\" data-open={open} aria-hidden />\r\n </button>\r\n\r\n {open ? (\r\n <div\r\n className=\"cv-cp-pop cv-on-pop\"\r\n role=\"dialog\"\r\n aria-label=\"Llamar desde\"\r\n part=\"outbound-number-list\"\r\n // Tabbing out of the list closes it, as a click elsewhere does.\r\n onBlur={(e) => {\r\n if (!e.currentTarget.contains(e.relatedTarget as Node | null)) setOpen(false);\r\n }}\r\n >\r\n <p className=\"cv-on-title\">Llamar desde</p>\r\n <div className=\"cv-cp-list\" role=\"listbox\" aria-disabled={locked} ref={keys.listRef} onKeyDown={keys.onKeyDown}>\r\n <OptionRow\r\n selected={settings.mine === null}\r\n disabled={locked}\r\n title=\"Por defecto de la organización\"\r\n sub={orgDefault ? numberName(orgDefault, formatIntl) : 'Sin número por defecto'}\r\n onSelect={() => void choose(null)}\r\n />\r\n {settings.numbers.map((n) => (\r\n <OptionRow\r\n key={n.id}\r\n selected={settings.mine === n.id}\r\n disabled={locked}\r\n title={numberName(n, formatIntl)}\r\n sub={n.label ? formatIntl(`+${n.number}`) : null}\r\n tag={KIND_TAG[n.kind]}\r\n onSelect={() => void choose(n.id)}\r\n />\r\n ))}\r\n </div>\r\n {message ? (\r\n <p className=\"cv-on-notice\" role=\"status\" data-kind={isError ? 'error' : 'info'}>\r\n {message}\r\n </p>\r\n ) : null}\r\n </div>\r\n ) : null}\r\n\r\n {callout && !open && message ? (\r\n <p className=\"cv-on-callout\" role=\"status\" data-kind={isError ? 'error' : 'info'} part=\"outbound-number-notice\">\r\n {message}\r\n </p>\r\n ) : null}\r\n </div>\r\n );\r\n}\r\n\r\nfunction OptionRow({\r\n selected,\r\n disabled,\r\n title,\r\n sub,\r\n tag,\r\n onSelect,\r\n}: Readonly<{\r\n selected: boolean;\r\n disabled: boolean;\r\n title: string;\r\n sub: string | null;\r\n tag?: { readonly tag: string; readonly hint: string } | undefined;\r\n onSelect: () => void;\r\n}>) {\r\n return (\r\n <button\r\n type=\"button\"\r\n role=\"option\"\r\n aria-selected={selected}\r\n aria-disabled={disabled}\r\n className=\"cv-cp-item cv-on-item\"\r\n // Not in the tab order: the arrows move through the list, Tab leaves it (WAI-ARIA listbox).\r\n tabIndex={-1}\r\n onClick={onSelect}\r\n >\r\n <span className=\"cv-on-text\">\r\n <span className=\"cv-on-line\">\r\n <span className=\"cv-cp-name\">{title}</span>\r\n {tag ? <span className=\"cv-on-tag\">{tag.tag}</span> : null}\r\n </span>\r\n {sub ? <span className=\"cv-on-sub\">{sub}</span> : null}\r\n {tag ? <span className=\"cv-on-hint\">{tag.hint}</span> : null}\r\n </span>\r\n <Check size={14} className=\"cv-cp-check\" data-on={selected} aria-hidden />\r\n </button>\r\n );\r\n}\r\n\r\nconst optionsOf = (list: HTMLElement | null): HTMLElement[] =>\r\n list ? [...list.querySelectorAll<HTMLElement>('[role=\"option\"]')] : [];\r\n\r\nconst fold = (text: string): string => text.normalize('NFD').replace(/\\p{Diacritic}/gu, '').toLowerCase();\r\n\r\n/** How long typed letters keep adding to one type-ahead search. */\r\nconst TYPEAHEAD_MS = 700;\r\n\r\n/**\r\n * Arrow keys, Home/End and type-ahead over the list's options (WAI-ARIA listbox): opening focuses the selected\r\n * option, so the arrows start from it; letters jump to the first number whose name starts with them.\r\n */\r\nfunction useListKeyboard(open: boolean) {\r\n const listRef = useRef<HTMLDivElement>(null);\r\n const typed = useRef({ text: '', at: 0 });\r\n\r\n useEffect(() => {\r\n if (!open) return;\r\n const options = optionsOf(listRef.current);\r\n (options.find((o) => o.getAttribute('aria-selected') === 'true') ?? options[0])?.focus();\r\n }, [open]);\r\n\r\n const onKeyDown = (e: KeyboardEvent<HTMLDivElement>): void => {\r\n const options = optionsOf(listRef.current);\r\n const at = options.indexOf(e.target as HTMLElement);\r\n const move: Record<string, number> = {\r\n ArrowDown: Math.min(at + 1, options.length - 1),\r\n ArrowUp: Math.max(at - 1, 0),\r\n Home: 0,\r\n End: options.length - 1,\r\n };\r\n let next = move[e.key];\r\n if (next === undefined && e.key.length === 1 && !e.ctrlKey && !e.metaKey && !e.altKey) {\r\n const now = Date.now();\r\n const text = now - typed.current.at < TYPEAHEAD_MS ? typed.current.text + e.key : e.key;\r\n typed.current = { text, at: now };\r\n const wanted = fold(text);\r\n const match = options.findIndex((o) => fold(o.querySelector('.cv-cp-name')?.textContent ?? '').startsWith(wanted));\r\n next = match >= 0 ? match : undefined;\r\n }\r\n if (next === undefined) return;\r\n e.preventDefault();\r\n options[next]?.focus();\r\n };\r\n\r\n return { listRef, onKeyDown };\r\n}\r\n","import { useLayoutEffect, useRef, useState } from 'react';\r\nimport { Phone, Delete } from 'lucide-react';\r\nimport { useSoftphone, useSoftphoneState } from '../../react/index.js';\r\nimport { CountryPicker } from '../dialing/CountryPicker.js';\r\nimport { DEFAULT_COUNTRY, regionOfInternational, toE164 } from '../dialing/countries.js';\r\nimport { caretAfterDigits, digitsBeforeCaret, useNumberFormatter } from '../dialing/format-number.js';\r\nimport { KEYPAD_KEYS } from '../dialing/keys.js';\r\nimport { playKeyTone } from '../audio/audio.js';\r\nimport { OutboundNumberPicker } from '../outbound/OutboundNumberPicker.js';\r\n\r\n/**\r\n * `*` and `#` render here but are **not dialable**: `toE164` keeps digits only, so a number carrying\r\n * them would lose them silently at dial time and the display would have lied.\r\n *\r\n * The CRM has the same keys and the same rule (`IdleView.setNational` runs `replace(/\\D/g,'')`, so a\r\n * `*` press is swallowed before it is ever shown). This states it instead of leaving it to a regex\r\n * three functions away: they are DTMF tones for an ACTIVE call (CallScreen's own keypad), not part of\r\n * a number.\r\n */\r\nconst NOT_DIALABLE = new Set(['*', '#']);\r\n\r\n/**\r\n * The number shares its row with the prefix chip, so it starts at a size read at a glance and steps down until it\r\n * fits — a long international number shrinks instead of being clipped (outbound-number-per-agent.md §5.5).\r\n */\r\nconst DISPLAY_SIZES = ['1.375rem', '1.25rem', '1.125rem', '1rem'];\r\n\r\n/**\r\n * The keypad view (legacy IdleView). Strings are Spanish (SPEC §2.4).\r\n *\r\n * Layout is three flex rows — head (fixed) / keypad (flex:1) / foot (fixed) — so the keypad absorbs\r\n * whatever height is left. Sizing keys by aspect-ratio instead would overflow the shell and push the\r\n * call button under the tab bar.\r\n */\r\nexport interface DialpadProps {\r\n /** The outcome of the last attempt — \"Sin respuesta\", \"Llamada rechazada\". Non-fatal only. */\r\n readonly outcome?: { readonly code: string; readonly text: string } | null;\r\n /** Called on any action that supersedes that outcome: a digit, a backspace, a dial. */\r\n readonly onIntent?: () => void;\r\n /**\r\n * Play a key tone when a digit is pressed. **On by default**; `SoftphoneWidget` passes its own\r\n * `sounds` flag, so a host that silences the widget silences this too.\r\n */\r\n readonly keyTones?: boolean;\r\n}\r\n\r\nexport function Dialpad({ outcome = null, onIntent, keyTones = true }: DialpadProps = {}) {\r\n const softphone = useSoftphone();\r\n const state = useSoftphoneState();\r\n // The NATIONAL number, as the CRM's IdleView held it: the prefix lives in the chip, so the user\r\n // types what they would read off a business card. `toE164` composes the two at dial time.\r\n //\r\n // State holds RAW DIGITS; the input displays them GROUPED. Keeping the raw digits as the source of\r\n // truth means the separators are pure presentation — nothing downstream ever has to un-format, and\r\n // `toE164` sees exactly what was typed.\r\n const [value, setValue] = useState('');\r\n const [country, setCountry] = useState(DEFAULT_COUNTRY);\r\n // While \"Llamar desde\" is applying a change, a call would go out from the number being replaced — so none goes\r\n // out until it settles (outbound-number-per-agent.md §5.5).\r\n const [changingNumber, setChangingNumber] = useState(false);\r\n const format = useNumberFormatter();\r\n const inputRef = useRef<HTMLInputElement>(null);\r\n const caretRef = useRef<number | null>(null);\r\n\r\n const display = format(country, value);\r\n const target = toE164(country, value);\r\n const canCall = state === 'online' && target.length > 1 && !changingNumber;\r\n // A number typed in full (\"+44 …\") carries its own country: the chip SHOWS that one, read-only, instead of\r\n // contradicting it with the chosen +34. Display only — `toE164` already dials a \"+\" number exactly as typed.\r\n const typedInternational = value.trim().startsWith('+');\r\n const numberRegion = regionOfInternational(value);\r\n\r\n // Restore the caret AFTER React paints the regrouped string, or inserting a digit mid-number would\r\n // throw it to the end and the next keystroke would land in the wrong place. Layout effect, not\r\n // effect: the caret must not be visibly wrong for a frame.\r\n useLayoutEffect(() => {\r\n const caret = caretRef.current;\r\n if (caret === null || !inputRef.current) return;\r\n caretRef.current = null;\r\n const pos = caretAfterDigits(display, caret);\r\n inputRef.current.setSelectionRange(pos, pos);\r\n }, [display]);\r\n\r\n // Largest size that fits (see `DISPLAY_SIZES`). Imperative on purpose: it depends on the rendered width, and a\r\n // state round-trip would paint the clipped size for a frame first.\r\n useLayoutEffect(() => {\r\n const input = inputRef.current;\r\n if (!input) return;\r\n for (const size of DISPLAY_SIZES) {\r\n input.style.fontSize = size;\r\n if (input.scrollWidth <= input.clientWidth) break;\r\n }\r\n }, [display]);\r\n\r\n const append = (key: string) => {\r\n onIntent?.();\r\n setValue((v) => v + key);\r\n // Only for a key that did something: `*` and `#` are inert here (see `NOT_DIALABLE`) and never\r\n // reach this, because a tone on a key that does nothing would tell the user it worked. Backspace\r\n // is silent too — it is not a keypad key and has no DTMF tone.\r\n if (keyTones) playKeyTone(key);\r\n };\r\n const backspace = () => {\r\n onIntent?.();\r\n setValue((v) => v.slice(0, -1));\r\n };\r\n const call = () => {\r\n if (!canCall) return;\r\n onIntent?.();\r\n void softphone.call(target);\r\n };\r\n\r\n return (\r\n <div className=\"cv-view\">\r\n {/*\r\n Read top to bottom in the order of a call, as the providers' dialers lay it out (outbound-number-per-agent.md\r\n §5.5, 2026-10-26): FROM — a light \"Llamar desde: X ▾\" line, only when the org has numbers to choose from —\r\n then TO — one bordered field with the prefix inside it, as the prefix is part of the number — then the\r\n keypad and the call button.\r\n\r\n The prefix used to have a row of its own (a chip beside the number starved it at 310px). It shares the\r\n row again because the number now shrinks to fit (`DISPLAY_SIZES`), and the row it had is what the\r\n caller-ID strip costs — the keys keep their height.\r\n */}\r\n <OutboundNumberPicker onBusyChange={setChangingNumber} />\r\n\r\n <div className=\"cv-dial-head\">\r\n <CountryPicker\r\n value={numberRegion ?? country}\r\n onChange={setCountry}\r\n fromNumber={typedInternational}\r\n />\r\n <input\r\n ref={inputRef}\r\n className=\"cv-display\"\r\n value={display}\r\n onChange={(e) => {\r\n onIntent?.();\r\n // Remember the caret in DIGITS before reformatting — see `caretAfterDigits`.\r\n caretRef.current = digitsBeforeCaret(e.target.value, e.target.selectionStart ?? 0);\r\n // Digits and a leading `+` only, matching what `toE164` will actually honour. This used\r\n // to accept `*#`, so a typed `*` displayed fine and then vanished at dial time.\r\n setValue(e.target.value.replace(/[^\\d+]/g, ''));\r\n }}\r\n onKeyDown={(e) => e.key === 'Enter' && call()}\r\n placeholder=\"Número\"\r\n aria-label=\"Número a marcar\"\r\n inputMode=\"tel\"\r\n />\r\n <button\r\n type=\"button\"\r\n className=\"cv-dial-side\"\r\n data-hidden={value.length === 0}\r\n // Invisible with nothing to erase — so not a tab stop, nor announced, either.\r\n tabIndex={value.length === 0 ? -1 : undefined}\r\n aria-hidden={value.length === 0 || undefined}\r\n onClick={backspace}\r\n aria-label=\"Borrar\"\r\n >\r\n <Delete size={19} />\r\n </button>\r\n </div>\r\n\r\n {/*\r\n What happened to the last attempt, under the number it was dialled from. Muted and inline\r\n rather than a banner: the phone still works, so nothing here should block or alarm.\r\n\r\n `role=\"status\"` and not `alert` — an alert interrupts a screen reader mid-sentence, and\r\n \"Sin respuesta\" is not worth interrupting for. Always rendered so the region exists before the\r\n text arrives; an aria-live region inserted at the same moment as its content is not announced.\r\n */}\r\n <p className=\"cv-dial-outcome\" role=\"status\" part=\"error\" data-shown={outcome !== null}>\r\n {outcome?.text ?? ''}\r\n </p>\r\n\r\n <div className=\"cv-keypad\">\r\n {KEYPAD_KEYS.map(([key, letters]) => {\r\n const dialable = !NOT_DIALABLE.has(key);\r\n return (\r\n <button\r\n key={key}\r\n type=\"button\"\r\n className=\"cv-key\"\r\n data-dialable={dialable}\r\n onClick={() => dialable && append(key)}\r\n aria-disabled={!dialable}\r\n // Not `disabled`: the key must stay in the grid and stay legible. It does nothing here\r\n // because `*`/`#` are DTMF for a live call, not digits in a number.\r\n title={dialable ? undefined : 'Solo disponible durante una llamada'}\r\n >\r\n <b>{key}</b>\r\n {letters ? <small>{letters}</small> : null}\r\n </button>\r\n );\r\n })}\r\n </div>\r\n\r\n <div className=\"cv-dial-foot\">\r\n <button\r\n type=\"button\"\r\n className=\"cv-round cv-round--answer\"\r\n onClick={call}\r\n disabled={!canCall}\r\n aria-label=\"Llamar\"\r\n part=\"call-button\"\r\n >\r\n <Phone size={26} />\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","/** Small presentational helpers. Pure — no React, no DOM. */\r\n\r\n/** `93` → `1:33`, `3725` → `1:02:05`. */\r\nexport function formatDuration(totalSeconds: number): string {\r\n const s = Math.max(0, Math.floor(totalSeconds));\r\n const hh = Math.floor(s / 3600);\r\n const mm = Math.floor((s % 3600) / 60);\r\n const ss = s % 60;\r\n const pad = (n: number) => String(n).padStart(2, '0');\r\n return hh > 0 ? `${hh}:${pad(mm)}:${pad(ss)}` : `${mm}:${pad(ss)}`;\r\n}\r\n\r\n/** `\"Ana García\"` → `\"AG\"`, `\"+34600111222\"` → `\"#\"`. */\r\nexport function initials(name: string | null | undefined): string {\r\n if (!name) return '#';\r\n const words = name.trim().split(/\\s+/).filter(Boolean);\r\n if (words.length === 0 || /^\\+?\\d/.test(words[0]!)) return '#';\r\n return words\r\n .slice(0, 2)\r\n .map((w) => w[0]!.toUpperCase())\r\n .join('');\r\n}\r\n\r\n/** Seconds elapsed since a start Date, as a live-timer-friendly integer. */\r\nexport function elapsedSeconds(since: Date | null, now: number): number {\r\n if (!since) return 0;\r\n return Math.floor((now - since.getTime()) / 1000);\r\n}\r\n\r\n/**\r\n * A notice's age, coarse and relative — `\"justo ahora\"`, `\"hace 1 min\"`, `\"hace 2 h\"`. Deliberately\r\n * never seconds: a notice worth keeping this long (no auto-dismiss — spec §5.5) is never worth timing\r\n * to the second, and a number that changes every tick reads as more urgent than the notice actually is.\r\n */\r\nexport function formatAge(totalSeconds: number): string {\r\n const s = Math.max(0, Math.floor(totalSeconds));\r\n if (s < 60) return 'justo ahora';\r\n const mm = Math.floor(s / 60);\r\n if (mm < 60) return `hace ${mm} min`;\r\n const hh = Math.floor(mm / 60);\r\n return `hace ${hh} h`;\r\n}\r\n","import type { SoftphoneErrorCode } from '../../core/errors.js';\r\n\r\n/**\r\n * What the USER reads when something fails. Spanish, because the widget is.\r\n *\r\n * **Deliberately not in the catalogue.** `ERROR_CATALOGUE.message` is documented as *\"what went\r\n * wrong, for a developer\"* and lands on `Error.message` — the string a host logs, and the one Sentry\r\n * groups by. Translating it would hand an English-speaking partner integrator Spanish stack traces,\r\n * and would put a locale into a `core/` that currently has no user-facing string in it at all.\r\n *\r\n * So the split is: the catalogue explains the failure to whoever is debugging it, and this explains\r\n * it to whoever is trying to make a call. They are different audiences and different sentences.\r\n *\r\n * `Record<SoftphoneErrorCode, ErrorText>` is what keeps them in step: a missing code will not\r\n * compile, and neither will one that no longer exists. Annotated rather than `as const satisfies`\r\n * deliberately — the literal types buy nothing, and they make `body` unreachable on the entries that\r\n * omit it, which is every call outcome.\r\n */\r\nexport interface ErrorText {\r\n /** The headline. For a non-fatal outcome this is the whole message — \"No contestaron\". */\r\n readonly title: string;\r\n /** One line of what to do. Fatal errors always have one; a call outcome rarely needs it. */\r\n readonly body?: string;\r\n}\r\n\r\nexport const ERROR_TEXT: Record<SoftphoneErrorCode, ErrorText> = {\r\n // ── Engine lifecycle ────────────────────────────────────────────────────────\r\n // Integrator mistakes rather than user-facing failures, but they must still read as something\r\n // rather than as a blank panel if one ever reaches the UI.\r\n 'engine/duplicate-instance': {\r\n title: 'Teléfono duplicado',\r\n body: 'Hay otro teléfono abierto en esta página. Cierra uno y vuelve a cargar.',\r\n },\r\n 'engine/not-started': { title: 'El teléfono aún no está listo' },\r\n 'engine/destroyed': {\r\n title: 'Teléfono cerrado',\r\n body: 'Vuelve a cargar la página para usarlo de nuevo.',\r\n },\r\n\r\n // ── Auth ────────────────────────────────────────────────────────────────────\r\n // Never \"token\": the user has no idea what one is. What they can act on is the session.\r\n 'auth/token-fetch-failed': {\r\n title: 'Sin conexión con el servidor',\r\n body: 'No se ha podido activar el teléfono. Reinténtalo en unos segundos.',\r\n },\r\n 'auth/token-rejected': {\r\n title: 'Sesión caducada',\r\n body: 'Vuelve a iniciar sesión para poder llamar.',\r\n },\r\n\r\n // ── Media ───────────────────────────────────────────────────────────────────\r\n // Verbatim from MicPermissionGate, which already says these well and says them first.\r\n //\r\n // NEVER ACTUALLY SHOWN via this table — these four codes (through `media/playback-blocked`, below)\r\n // are never raised as a `SoftphoneError` at all. See the fuller comment on each in `core/errors.ts`\r\n // for why. Copy kept here anyway so the catalogue and this file stay the same shape as every other\r\n // code — `error-text.test.ts` would fail the build the moment they drifted.\r\n 'media/permission-denied': {\r\n title: 'Micrófono bloqueado',\r\n body: 'Permítelo en tu navegador para poder llamar.',\r\n },\r\n 'media/no-input-device': {\r\n title: 'Sin micrófono',\r\n body: 'Conecta un micrófono y vuelve a intentarlo.',\r\n },\r\n 'media/webrtc-unsupported': {\r\n title: 'Llamadas no disponibles',\r\n body: 'Este navegador no admite llamadas. Prueba con Chrome, Edge o Firefox.',\r\n },\r\n 'media/playback-blocked': { title: 'Toca la pantalla para activar el sonido' },\r\n\r\n // ── Network / signalling ────────────────────────────────────────────────────\r\n // \"Centralita\" rather than \"SIP\" or \"registro\": the user knows what a phone system is.\r\n 'net/registration-failed': {\r\n title: 'No se pudo conectar',\r\n body: 'No hemos podido conectar con la centralita. Reintenta en unos segundos.',\r\n },\r\n 'net/transport-failed': {\r\n title: 'Conexión perdida',\r\n body: 'Se ha perdido la conexión con la centralita.',\r\n },\r\n // NEVER ACTUALLY SHOWN either — CallScreen's own \"Reconectando…\" already covers this, off the\r\n // call's `reconnecting` state rather than this channel. See the comment in `core/errors.ts`.\r\n 'net/ice-failed': { title: 'Recuperando el audio…' },\r\n\r\n // ── Call ────────────────────────────────────────────────────────────────────\r\n /*\r\n THE VOICE RULE FOR THIS BLOCK: say what HAPPENED, not what it is called.\r\n\r\n These were status labels — \"Llamada perdida\", \"Llamada rechazada\", \"Sin respuesta\". Each is a\r\n name for a category rather than an account of an event, which is why they read as a database enum\r\n someone forgot to translate into human. Worse, a label hides the ACTOR: \"Llamada rechazada\" never\r\n says who rejected what, so the user reading it after declining a call and the user reading it\r\n after being declined see the same three words.\r\n\r\n So each one is a short sentence about what the other person, or the phone, did — the form\r\n `call/busy` already had, and the reason it was the only one here that read clearly.\r\n\r\n Impersonal third-person plural (\"contestaron\", \"colgaron\") throughout: the user does not know who\r\n is at the other end, and it is what Spanish uses when the subject is unknown. Mixing it with the\r\n singular across neighbouring lines reads as carelessness.\r\n\r\n LENGTH IS A HARD CONSTRAINT, not a preference. `.cv-dial-outcome` is one line at a fixed\r\n `1.15rem`, and the keypad below it is `flex: 1` — a title that wraps resizes every key and shifts\r\n the grid under a finger already reaching for it. `error-text.test.ts` caps this at 48 characters.\r\n */\r\n 'call/not-answerable': { title: 'Esa llamada ya ha terminado' },\r\n /*\r\n NOT \"Comunicando\", which is what this said and what sent us looking. SIP 486 is both \"the line is\r\n engaged\" AND what almost every endpoint sends when a person presses decline — including our own\r\n `reject()`. One code, two events, no way to tell them apart, so the copy has to hold both rather\r\n than assert the less likely one. `call/rejected` can be definite: an endpoint sending 603 Decline\r\n means exactly that.\r\n */\r\n 'call/busy': { title: 'No contestaron o la línea estaba ocupada' },\r\n 'call/no-answer': { title: 'No contestaron' },\r\n 'call/rejected': { title: 'No aceptaron tu llamada' },\r\n /*\r\n The legacy CRM said \"La persona que llamaba colgó antes de que pudieras contestar.\" — the right\r\n fact, at three times the width of the line that has to hold it. This keeps the fact and drops the\r\n words: the user needs to know the call was FOR them and that nobody is waiting on the line.\r\n \"Llamada perdida\" alone tested badly for exactly the label reason above — it names the category\r\n without saying anyone rang.\r\n */\r\n 'call/missed': { title: 'Colgaron antes de que pudieras contestar' },\r\n // \"No se pudo completar la llamada\" was our own \"something went wrong\": true of every failure and\r\n // useful for none. The number is what the user can actually act on.\r\n 'call/failed': { title: 'No se pudo conectar con ese número' },\r\n // The load-bearing half is the SECOND sentence: the original call is still up, and a user who\r\n // thinks they dropped it will hang up on a client to \"fix\" it.\r\n 'call/transfer-failed': { title: 'No se pudo transferir. Sigues en la llamada' },\r\n 'call/unsupported': { title: 'Esta función no está disponible' },\r\n\r\n // ── Provider ────────────────────────────────────────────────────────────────\r\n 'provider/provision-failed': {\r\n title: 'No se pudo activar el teléfono',\r\n body: 'Si el problema continúa, contacta con soporte.',\r\n },\r\n};\r\n","import { useEffect, useState } from 'react';\r\n\r\n/**\r\n * `Date.now()`, updated every `intervalMs` while `enabled`. For the live call timer.\r\n *\r\n * Kept as its own hook so only the timer text re-renders on each tick, not the whole widget.\r\n */\r\nexport function useTicker(enabled: boolean, intervalMs = 1000): number {\r\n const [now, setNow] = useState(() => Date.now());\r\n useEffect(() => {\r\n if (!enabled) return;\r\n setNow(Date.now());\r\n const id = setInterval(() => setNow(Date.now()), intervalMs);\r\n return () => clearInterval(id);\r\n }, [enabled, intervalMs]);\r\n return now;\r\n}\r\n","import { useEffect } from 'react';\r\nimport { Headphones, Mic } from 'lucide-react';\r\nimport { useDevices, useSoftphone } from '../../react/index.js';\r\nimport type { ContactActionIcon } from '../types.js';\r\n\r\n/**\r\n * A device's own label, or a numbered fallback.\r\n *\r\n * `enumerateDevices()` returns an EMPTY `label` until the microphone has been granted at least once\r\n * (a browser privacy measure — see `AudioDevices.refresh`'s own comment) — a blank row in a picker\r\n * reads as broken, not as \"permission pending\", so this names it something a user can still pick.\r\n */\r\nexport function deviceLabel(device: MediaDeviceInfo, index: number, kind: DeviceKind): string {\r\n if (device.label) return device.label;\r\n return kind === 'input' ? `Micrófono ${index + 1}` : `Altavoz ${index + 1}`;\r\n}\r\n\r\n/** `ringtone` is an OUTPUT device too — the one the ring plays on (custom-ringtone.md §4.6). */\r\nexport type DeviceKind = 'input' | 'output' | 'ringtone';\r\n\r\n/** `''` is the DOM's own spelling of \"system default\" on a `<select>`; `null` is this SDK's. */\r\nconst DEFAULT_OPTION = '';\r\n\r\n/** One device row. Exported for the ringtone section's \"Salida del tono\", which is the same row. */\r\nexport function DevicePicker({\r\n icon: Icon,\r\n label,\r\n kind,\r\n options,\r\n value,\r\n onChange,\r\n emptyText,\r\n}: Readonly<{\r\n icon: ContactActionIcon;\r\n label: string;\r\n kind: DeviceKind;\r\n options: readonly MediaDeviceInfo[];\r\n value: string | null;\r\n onChange: (deviceId: string | null) => void;\r\n emptyText: string;\r\n}>) {\r\n return (\r\n <div className=\"cv-settings-row\">\r\n <span className=\"cv-settings-row-icon\" aria-hidden>\r\n <Icon size={16} />\r\n </span>\r\n <span className=\"cv-settings-row-text\">\r\n <span className=\"cv-settings-row-label\" id={`cv-settings-label-${kind}`}>\r\n {label}\r\n </span>\r\n {options.length > 0 ? (\r\n <select\r\n className=\"cv-settings-select\"\r\n aria-labelledby={`cv-settings-label-${kind}`}\r\n value={value ?? DEFAULT_OPTION}\r\n onChange={(e) => onChange(e.target.value === DEFAULT_OPTION ? null : e.target.value)}\r\n >\r\n <option value={DEFAULT_OPTION}>Predeterminado del sistema</option>\r\n {options.map((d, i) => (\r\n <option key={d.deviceId} value={d.deviceId}>\r\n {deviceLabel(d, i, kind)}\r\n </option>\r\n ))}\r\n </select>\r\n ) : (\r\n <span className=\"cv-settings-empty\">{emptyText}</span>\r\n )}\r\n </span>\r\n </div>\r\n );\r\n}\r\n\r\n/**\r\n * Both device pickers (microphone + speaker), self-contained: reads `useDevices()` itself and\r\n * re-scans on mount. Shared between the Ajustes tab and the in-call quick-switch popover\r\n * (`CallScreen`) so the two surfaces show the same devices under the same labels and can't drift\r\n * apart — there is exactly one place that knows what a device row looks like.\r\n */\r\nexport function DevicePickers() {\r\n const softphone = useSoftphone();\r\n const devices = useDevices();\r\n\r\n // Labels enumerate blank until the microphone has been granted at least once, and a permission\r\n // grant fires no `devicechange` — so every surface that shows device NAMES re-scans on mount\r\n // rather than trusting whatever `BrowserAudioDevices` happened to see when the softphone was\r\n // first constructed. `softphone`, not `devices`, is the dependency: `devices` is a fresh object\r\n // every time it changes (see `useDevices`), and depending on it here would re-trigger this effect\r\n // on its own refresh.\r\n useEffect(() => {\r\n void softphone.audio.refresh();\r\n }, [softphone]);\r\n\r\n return (\r\n <>\r\n <DevicePicker\r\n icon={Mic}\r\n label=\"Micrófono\"\r\n kind=\"input\"\r\n options={devices.inputs}\r\n value={devices.currentInputId}\r\n onChange={(id) => void devices.setInput(id)}\r\n emptyText=\"No se encontró ningún micrófono\"\r\n />\r\n {devices.canSelectOutput ? (\r\n <DevicePicker\r\n icon={Headphones}\r\n label=\"Altavoces\"\r\n kind=\"output\"\r\n options={devices.outputs}\r\n value={devices.currentOutputId}\r\n onChange={(id) => void devices.setOutput(id)}\r\n emptyText=\"No se encontró ningún altavoz\"\r\n />\r\n ) : (\r\n // Safari and most of Firefox have no `setSinkId` at all — nothing here would do anything,\r\n // and offering a picker that silently fails is worse than not offering one.\r\n <p className=\"cv-settings-note\">\r\n Tu navegador no permite elegir el altavoz desde aquí — cámbialo en los ajustes del\r\n sistema.\r\n </p>\r\n )}\r\n </>\r\n );\r\n}\r\n","import { useEffect, useRef, useState } from 'react';\r\nimport {\r\n Phone,\r\n PhoneOff,\r\n Mic,\r\n MicOff,\r\n Pause,\r\n Play,\r\n ArrowLeft,\r\n ArrowLeftRight,\r\n ExternalLink,\r\n Grid3x3,\r\n Headphones,\r\n PhoneOutgoing,\r\n type LucideIcon,\r\n} from 'lucide-react';\r\nimport { useCall, usePresence, useSoftphone } from '../../react/index.js';\r\nimport { effectiveNumber, numberName, outboundNumberStore, useOutboundNumbers } from '../outbound/outbound-number-store.js';\r\nimport { useIntlFormatter } from '../dialing/format-number.js';\r\nimport type { CallView } from '../../react/index.js';\r\nimport { CallEvent } from '../../core/events.js';\r\nimport type { Call, HangupReason } from '../../core/call.js';\r\nimport type { SoftphoneErrorCode } from '../../core/errors.js';\r\nimport { formatDuration, elapsedSeconds, initials } from '../lib/format.js';\r\nimport { ERROR_TEXT } from '../lib/error-text.js';\r\nimport { useTicker } from '../lib/useTicker.js';\r\nimport { DevicePickers } from './DevicePicker.js';\r\nimport { KEYPAD_KEYS } from '../dialing/keys.js';\r\nimport { playKeyTone } from '../audio/audio.js';\r\nimport type { ContactAction, PresenceEntry, PresenceState } from '../types.js';\r\n\r\n/**\r\n * A secondary control: the button and the word for it.\r\n *\r\n * **The label is not decoration.** These were icon-only, and an icon-only control is a quiz — `⇄` is\r\n * transfer or swap or call-waiting depending on who you ask, and you are asking someone mid-call. The\r\n * CRM labels every one of these (`Silenciar` / `Colgar` / `Transferir`) and it is right to.\r\n *\r\n * `tone` carries the ON state's meaning rather than a colour, so muted reads as *danger* and held\r\n * reads as *held* — using the same `--cv-*` tokens the rest of the widget themes with.\r\n */\r\nfunction Control({\r\n icon: Icon,\r\n label,\r\n pressed = false,\r\n tone,\r\n onClick,\r\n disabled = false,\r\n title,\r\n}: Readonly<{\r\n icon: LucideIcon;\r\n label: string;\r\n pressed?: boolean;\r\n tone?: 'danger' | 'hold' | 'accent';\r\n onClick: () => void;\r\n disabled?: boolean;\r\n title?: string | undefined;\r\n}>) {\r\n return (\r\n <div className=\"cv-ctrl-item\">\r\n <button\r\n type=\"button\"\r\n className=\"cv-ctrl\"\r\n data-tone={pressed ? tone : undefined}\r\n aria-pressed={pressed}\r\n aria-label={label}\r\n onClick={onClick}\r\n disabled={disabled}\r\n title={title}\r\n >\r\n <Icon size={19} />\r\n </button>\r\n {/* aria-hidden: the button's own name already says this — do not announce it twice. */}\r\n <span className=\"cv-ctrl-label\" aria-hidden>\r\n {label}\r\n </span>\r\n </div>\r\n );\r\n}\r\n\r\nconst STATUS_LABEL: Record<string, string> = {\r\n ringing: 'Llamada entrante',\r\n dialing: 'Llamando…',\r\n early: 'Llamando…',\r\n answering: 'Conectando…',\r\n reconnecting: 'Reconectando…',\r\n held: 'En espera',\r\n};\r\n\r\n/**\r\n * A consult leg (attended transfer, SPEC §5.6) that ends without being completed reports a REAL\r\n * reason — it's an ordinary outbound call, not the REFER black box blind `transfer()` is\r\n * (`docs/specs/transfer-availability.md` §2). Reusing `ERROR_TEXT`'s existing call-outcome copy\r\n * rather than inventing new strings; `call/transfer-failed` is the fallback for a reason this table\r\n * doesn't otherwise name — it should be unreachable in practice, but a consult leg has more possible\r\n * `HangupReason`s than this maps, and staying exhaustive costs four lines.\r\n */\r\nconst CONSULT_FAIL_CODE: Partial<Record<HangupReason, SoftphoneErrorCode>> = {\r\n busy: 'call/busy',\r\n 'no-answer': 'call/no-answer',\r\n rejected: 'call/rejected',\r\n failed: 'call/failed',\r\n};\r\n\r\nfunction consultFailText(reason: HangupReason): string {\r\n return ERROR_TEXT[CONSULT_FAIL_CODE[reason] ?? 'call/transfer-failed'].title;\r\n}\r\n\r\n/**\r\n * Found live (plan T5, 2026-09-28): completing a consulted transfer via `ConsultScreen`'s own\r\n * \"Completar\" within ~1-2s of the consult answering can drop the caller entirely — `REFER` gets\r\n * accepted and the agent's own leg gets a clean \"Normal Clearing\" `BYE`, wire-identical to a genuine\r\n * success (`transfer-availability.md` §15 item 5's own evidence table), but the target's line was never\r\n * actually ready for the immediately-following fresh INVITE. Reusing `consultView.answeredAt` and the\r\n * existing ticker, no new tracking state. Same \"observed starting point, tune if real usage shows\r\n * otherwise\" posture this codebase's own `POST_CALL_COOLDOWN_MS` (5s, presence) was set with, not a\r\n * rigorously derived number — and it needed tuning twice: 3s (real margin above the ~1-2s that actually\r\n * failed) turned out live not to be enough; 6s STILL failed intermittently in further live testing;\r\n * raised to 10s, which live re-testing then confirmed reliable for THIS path. Exported so\r\n * `CallScreen.test.tsx` references this value directly instead of a duplicated literal.\r\n *\r\n * This same gate used to ALSO cover \"Transferir directo\" — the auto-handoff path completed the\r\n * identical warm-blind-transfer automatically, the instant this same minimum passed. That path kept\r\n * dropping calls even at 10s, live, while manual stayed reliable at the same value — an automated\r\n * completion apparently races Zadarma's own readiness signal harder than a human's incidental\r\n * reaction-time delay ever did, for reasons never root-caused. Rather than keep chasing a bigger\r\n * number on a mechanism that had already needed two rounds of \"still sometimes fails,\" \"Transferir\r\n * directo\" was redesigned (2026-09-28) into a literal, immediate blind transfer with no consult at\r\n * all — see `selectPresenceAgentAuto`'s own comment. This constant now only gates the manual path.\r\n */\r\nexport const MIN_CONSULT_HOLD_SECONDS = 10;\r\n\r\n/**\r\n * Full takeover while a consult is in progress (SPEC §5.6) — not a panel bolted onto the caller's own\r\n * screen, which is what this replaced. Two real calls exist simultaneously the whole time this is on\r\n * screen: the caller, silently on hold, and the consult target, who is who the agent is actually\r\n * talking to. Showing the CALLER's own screen with a collapsible transfer panel made that easy to\r\n * lose track of — found live: an agent reached for the ordinary \"Reanudar\" hold toggle without\r\n * realising the consult leg was still up, unholding the caller INTO a second already-live call and\r\n * putting both ends within earshot of each other at once. This screen removes that toggle from reach\r\n * entirely (it doesn't exist here) and makes \"go back to the caller\" a single, impossible-to-miss\r\n * action instead of something buried behind a panel someone could forget was open.\r\n */\r\nfunction ConsultScreen({\r\n mainName,\r\n consultView,\r\n now,\r\n onReturn,\r\n onComplete,\r\n onHangupAll,\r\n}: Readonly<{\r\n /** The ORIGINAL caller's name — for the \"who's waiting\" banner, not this screen's own subject. */\r\n mainName: string;\r\n consultView: CallView;\r\n now: number;\r\n /** Ends the consult leg and un-holds the caller — \"Cancelar\" and the return banner do the same thing. */\r\n onReturn: () => void;\r\n onComplete: () => void;\r\n /** Ends BOTH legs — the one true \"I'm done with all of this\" escape hatch. */\r\n onHangupAll: () => void;\r\n}>) {\r\n const s = consultView.state;\r\n const answered = s === 'active';\r\n const name = consultView.remote.displayName;\r\n const number = consultView.remote.number;\r\n const showNumber = number !== name;\r\n const heldSeconds = elapsedSeconds(consultView.answeredAt, now);\r\n const [rawM = '0', ss = '00'] = formatDuration(heldSeconds).split(':');\r\n const mm = rawM.padStart(2, '0');\r\n // See MIN_CONSULT_HOLD_SECONDS's own comment — a real, live-found gap, not a guess.\r\n const canComplete = heldSeconds >= MIN_CONSULT_HOLD_SECONDS;\r\n\r\n return (\r\n <div className=\"cv-view\">\r\n <div className=\"cv-call\">\r\n {/* The one fact that matters most on this whole screen: someone is still waiting. Full-width\r\n and tappable, not a passive status line — reads the return action as its own affordance. */}\r\n <button type=\"button\" className=\"cv-consult-hold-banner\" onClick={onReturn}>\r\n <Pause size={13} aria-hidden />\r\n {mainName} en espera · Volver\r\n </button>\r\n\r\n <div className=\"cv-avatar-wrap\">\r\n <div className=\"cv-avatar\" aria-hidden>\r\n {initials(name)}\r\n </div>\r\n {answered ? <span className=\"cv-avatar-dot\" aria-hidden /> : null}\r\n </div>\r\n <div className=\"cv-call-name\">{name}</div>\r\n {showNumber ? <div className=\"cv-call-number\">{number}</div> : null}\r\n\r\n {answered ? (\r\n <div className=\"cv-timer\" aria-label=\"Duración de la llamada\">\r\n <b>{mm}</b>\r\n <i>:</i>\r\n <b>{ss}</b>\r\n </div>\r\n ) : (\r\n <div className=\"cv-call-status\">{STATUS_LABEL[s] ?? ''}</div>\r\n )}\r\n </div>\r\n\r\n <div className=\"cv-controls\">\r\n <div className=\"cv-transfer-actions\">\r\n {answered ? (\r\n <button className=\"cv-btn cv-btn--accent\" onClick={onComplete} disabled={!canComplete}>\r\n Completar\r\n </button>\r\n ) : null}\r\n <button className=\"cv-btn\" onClick={onReturn}>\r\n Cancelar\r\n </button>\r\n </div>\r\n <div className=\"cv-controls-primary\">\r\n <div className=\"cv-ctrl-item\">\r\n <button\r\n type=\"button\"\r\n className=\"cv-round cv-round--hangup\"\r\n onClick={onHangupAll}\r\n aria-label=\"Colgar todo\"\r\n >\r\n <PhoneOff size={26} />\r\n </button>\r\n <span className=\"cv-ctrl-label\" aria-hidden>\r\n Colgar todo\r\n </span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n\r\nconst PRESENCE_LABEL: Record<PresenceState, string> = {\r\n disponible: 'Disponible',\r\n en_llamada: 'En llamada',\r\n desconectado: 'Desconectado',\r\n};\r\n\r\nconst PRESENCE_RANK: Record<PresenceState, number> = {\r\n disponible: 0,\r\n en_llamada: 1,\r\n desconectado: 2,\r\n};\r\n\r\n/** *Disponible* → *En llamada* → *Desconectado*, then by name (spec §4.5). Self-exclusion happens in\r\n * the caller, not here — `TransferPicker` needs the pre-exclusion count too, to tell \"empty org\" (no\r\n * picker at all) apart from \"no match for what's typed\" (an empty-state row inside one). */\r\nfunction filterAgents(agents: readonly PresenceEntry[], query: string): readonly PresenceEntry[] {\r\n const q = query.trim().toLowerCase();\r\n return agents\r\n .filter((a) => !q || (a.name ?? '').toLowerCase().includes(q) || a.extension.includes(q))\r\n .sort(\r\n (a, b) =>\r\n PRESENCE_RANK[a.state] - PRESENCE_RANK[b.state] ||\r\n (a.name ?? a.extension).localeCompare(b.name ?? b.extension),\r\n );\r\n}\r\n\r\n/** Bounds the \"Llamar a {typed}\" button's own content size — a long paste must not force the\r\n * input+button row wider than the ~340 px embed (the exact class of bug `.cv-transfer-notice`\r\n * already hit once this widget, see that component's own history). */\r\nfunction truncateForButton(text: string, max = 16): string {\r\n return text.length > max ? `${text.slice(0, max)}…` : text;\r\n}\r\n\r\n/**\r\n * The agent list under the transfer input (spec §4.5, plan T7) — the \"one control instead of two\":\r\n * the existing input/button stay the free-text fallback, this is the new part. Renders nothing at\r\n * all once `myUserId` is excluded and no one else is left — an empty org, no `PresenceSource`\r\n * configured, or this tab not currently `online && isLeader` all look identical from here (spec\r\n * §4.4's success criterion: no error, just nothing to show) — the caller falls straight back to\r\n * today's free-text-only field, unchanged.\r\n */\r\nfunction TransferPicker({\r\n agents,\r\n myUserId,\r\n query,\r\n onSelect,\r\n}: Readonly<{\r\n agents: readonly PresenceEntry[];\r\n myUserId: string | null;\r\n query: string;\r\n onSelect: (extension: string) => void;\r\n}>) {\r\n const others = agents.filter((a) => a.userId !== myUserId);\r\n if (others.length === 0) return null;\r\n const filtered = filterAgents(others, query);\r\n\r\n return (\r\n <div className=\"cv-presence\">\r\n <div className=\"cv-presence-list\" role=\"listbox\" aria-label=\"Compañeros\">\r\n {filtered.length === 0 ? (\r\n <p className=\"cv-presence-empty\">Sin coincidencias</p>\r\n ) : (\r\n filtered.map((agent) => {\r\n // Found live (2026-09-28): transferring (either path) to a colleague who is genuinely\r\n // `en_llamada` — mid-call, or still inside Zadarma's own post-call settling window\r\n // (backend `POST_CALL_COOLDOWN_MS`, `redisPubSub/index.js`) — can leave the call a silent\r\n // ghost: the target's phone never rings, the caller just waits with no failure signal at\r\n // all, not even the \"busy\" a normal consult would surface. Unlike *Desconectado* (§4.6: a\r\n // HINT, since presence only sees our own web softphone and a colleague could be reachable\r\n // elsewhere), `en_llamada` is a real, currently-true signal we already have and were simply\r\n // not acting on — so this one is a hard block, not a hint: the row stays visible (an agent\r\n // should still see who's busy) but isn't selectable. It un-blocks itself the moment presence\r\n // reports them free again — no separate retry affordance needed. Free text remains a\r\n // deliberate escape hatch (spec §4: presence is what justifies this restriction too, and\r\n // free text has no presence behind it).\r\n const isBusy = agent.state === 'en_llamada';\r\n return (\r\n <button\r\n key={agent.userId}\r\n type=\"button\"\r\n role=\"option\"\r\n className=\"cv-presence-item\"\r\n disabled={isBusy}\r\n onClick={() => onSelect(agent.extension)}\r\n >\r\n <span className=\"cv-presence-dot\" data-state={agent.state} aria-hidden />\r\n <span className=\"cv-presence-name\">{agent.name ?? agent.extension}</span>\r\n <span className=\"cv-presence-meta\">\r\n {agent.extension} · {PRESENCE_LABEL[agent.state]}\r\n </span>\r\n </button>\r\n );\r\n })\r\n )}\r\n </div>\r\n {/* Decided 2026-09-21 (spec §4.6): *Desconectado* is a HINT, never \"can't transfer\" — presence\r\n only sees our own web softphone, so a colleague on a desk phone or Zadarma's own app reads\r\n Desconectado while genuinely reachable. This is what keeps that from being misread. */}\r\n <p className=\"cv-presence-legend\">\r\n Desconectado: sin conexión en el softphone web. Puede atender desde otro dispositivo.\r\n </p>\r\n </div>\r\n );\r\n}\r\n\r\n/** The active-call view: incoming, outgoing and in-call in one, switched on call.state. */\r\nexport function CallScreen({\r\n call,\r\n incomingCallAction,\r\n keyTones = true,\r\n}: Readonly<{\r\n call: Call;\r\n incomingCallAction?: ContactAction;\r\n /**\r\n * Play a tone for each keypad press. **On by default**; `SoftphoneWidget` passes its own `sounds`\r\n * flag, so a host that silences the widget silences this too.\r\n */\r\n keyTones?: boolean;\r\n}>) {\r\n const view = useCall(call);\r\n const softphone = useSoftphone();\r\n // Which of the org's numbers this outbound call shows (outbound-number-per-agent.md §5.5). Read from the shared\r\n // store — refreshed in the background, never awaited: the call is already on its way. Shown only when the org has\r\n // numbers to choose from; with one there is nothing worth saying.\r\n const outbound = useOutboundNumbers(call.direction === 'outbound' ? outboundNumberStore(softphone) : null).settings;\r\n const formatIntl = useIntlFormatter();\r\n const fromName = outbound && outbound.numbers.length > 1 ? numberName(effectiveNumber(outbound), formatIntl) : null;\r\n // ONE panel at a time. These were three independent booleans, and two of them could be open at once —\r\n // found live (2026-10-06): the keypad popover opened over the transfer panel and hid its input and\r\n // agent list entirely. One value makes that state unrepresentable instead of guarding against it in\r\n // each click handler.\r\n const [panel, setPanel] = useState<'transfer' | 'keypad' | 'devices' | null>(null);\r\n const showTransfer = panel === 'transfer';\r\n const showKeypad = panel === 'keypad';\r\n const showDevices = panel === 'devices';\r\n const togglePanel = (p: 'transfer' | 'keypad') => setPanel((cur) => (cur === p ? null : p));\r\n const [transferTo, setTransferTo] = useState('');\r\n const [consultCall, setConsultCall] = useState<Call | null>(null);\r\n const [consultOutcome, setConsultOutcome] = useState<HangupReason | null>(null);\r\n const [myUserId, setMyUserId] = useState<string | null>(null);\r\n const consultView = useCall(consultCall);\r\n // Set right before completeTransfer()/cancelConsult() so the Ended listener below can tell \"we just\r\n // ended this ourselves\" apart from \"the target hung up on us\" — the same event fires either way, and\r\n // only the second case is a failure worth showing.\r\n const consultIntentRef = useRef<'complete' | 'cancel' | null>(null);\r\n const controlsRef = useRef<HTMLDivElement>(null);\r\n const now = useTicker(view?.state === 'active');\r\n // `ConsultScreen` needs its OWN timer — the consult leg answers, and stays live, independently of\r\n // whatever the main call's own state is doing underneath it.\r\n const consultNow = useTicker(consultView?.state === 'active');\r\n // Needed ahead of the early-return guard below, since the outside-click effect depends on it and\r\n // hooks can't follow a conditional return.\r\n const isConnected = view ? view.state === 'active' || view.state === 'held' || view.state === 'reconnecting' : false;\r\n // Same reasoning — `usePresence` is a hook too. Mirrors `inCall && showTransfer && !consultCall`\r\n // below exactly (`inCall` is this same value under a different name, post-early-return).\r\n const transferPickerActive = isConnected && showTransfer && !consultCall;\r\n // Subscribes only while the transfer step is open (spec §4.5) — the CONNECTION itself stays\r\n // governed by `online && isLeader` regardless (`usePresence`'s own doc comment); this only scopes\r\n // which component bothers re-rendering on an update.\r\n const presence = usePresence(transferPickerActive);\r\n\r\n // The org's phone directory, fetched once — same source, same \"absent ⇒ feature quietly does not\r\n // render\" shape `HistoryTab`'s own `PersonFilter` already uses. `me.userId` is the ONE piece needed\r\n // here: excluding the agent from their own transfer picker (spec §4.5).\r\n useEffect(() => {\r\n const listAgents = softphone.sources?.listAgents;\r\n if (!listAgents) return;\r\n let cancelled = false;\r\n void listAgents()\r\n .then((d) => !cancelled && setMyUserId(d.me?.userId ?? null))\r\n .catch(() => {});\r\n return () => {\r\n cancelled = true;\r\n };\r\n }, [softphone]);\r\n\r\n // The consult leg's terminal event — NOT unsubscribed on anything UI-side: `ConsultScreen` is on\r\n // screen for exactly as long as `consultCall` is non-null, so there is no \"panel closed but the\r\n // call is still ringing\" state left to strand (there was, before this was its own screen — see that\r\n // component's own comment).\r\n useEffect(() => {\r\n if (!consultCall) return;\r\n return consultCall.on(CallEvent.Ended, ({ reason }) => {\r\n const intent = consultIntentRef.current;\r\n consultIntentRef.current = null;\r\n setConsultCall(null);\r\n if (!intent) {\r\n // Ended on its own — busy/no-answer/rejected/failed. Plan T2: recover the caller automatically\r\n // instead of leaving them silently held until the agent notices this notice and resumes them by\r\n // hand — a real gap that existed before this fix.\r\n setConsultOutcome(reason);\r\n // Guard against the MAIN call having ALSO already ended by now (spec §5.3/plan §10 Q5) — found\r\n // to be a REAL, reachable ordering, not just a theoretical one: `CallImpl#end()`'s own\r\n // consult-leg cleanup fires `consult.hangup()` without awaiting it, so this listener can still\r\n // run — the component hasn't unmounted yet — before React processes the main call's own `ended`\r\n // state. Caught directly by a spy in the \"caller hangs up first\" test, which failed on the first\r\n // attempt without this guard: `unhold()` doesn't throw when called on an ended call (its own\r\n // `!this.#onHold` short-circuit doesn't help here, since the caller genuinely WAS on hold right\r\n // up to that point), but calling it on a dead session is still wrong to do on purpose. `call.state`\r\n // is `CallImpl`'s own live getter, not a React-closure value — reading it fresh here, not `view`.\r\n if (call.state !== 'ended') void call.unhold();\r\n }\r\n // else: we ended it ourselves (bridged by completeTransfer, or hung up by cancelConsult) —\r\n // nothing failed, nothing to show.\r\n });\r\n }, [consultCall, call]);\r\n\r\n /**\r\n * `target` overrides `transferTo` — needed when a `TransferPicker` row is clicked (plan T7):\r\n * `setTransferTo` is async (React state), so a caller that set it and immediately called this\r\n * without the override would still read the PREVIOUS render's `transferTo` here, off by one click.\r\n * Free text (the button) omits it and falls back to the input's own current value, unchanged.\r\n */\r\n const startConsult = async (target?: string) => {\r\n const t = (target ?? transferTo).trim();\r\n if (!t) return;\r\n setConsultOutcome(null);\r\n setConsultCall(await call.startConsult(t));\r\n };\r\n const selectPresenceAgent = (extension: string) => {\r\n setTransferTo(extension);\r\n void startConsult(extension);\r\n };\r\n // Which of the two paths (spec §5.4) a picker row click starts — \"Hablar primero\" (the consult flow\r\n // above, unchanged) by default, or \"Transferir directo\" once switched. Free text (the `Llamar` button\r\n // below) always uses `startConsult` directly, unaffected either way — presence is what justifies a\r\n // one-click transfer at all, and free text has no presence behind it.\r\n const [quickTransfer, setQuickTransfer] = useState(false);\r\n /**\r\n * \"Transferir directo\": a literal, immediate blind transfer — no consult, no ring-first confirmation,\r\n * no hold-timer gate. This replaces an earlier design (plan `transfer-auto-handoff-plan.md` T1–T5)\r\n * that reused the \"warm blind transfer\" pattern automatically — consult the target, wait for it to\r\n * answer, hold `MIN_CONSULT_HOLD_SECONDS`, then bridge — the exact same mechanism `ConsultScreen`'s\r\n * manual \"Completar\" still uses. That approach kept dropping the caller live even after the hold was\r\n * raised to 10s (found reliable for the MANUAL path at that value), for reasons never root-caused —\r\n * an automated completion apparently doesn't get the same margin a human's incidental reaction-time\r\n * delay was providing. Found live, 2026-09-28: \"Sometimes it still fails at 6s... [still] fails\" even\r\n * at 10s, direct transfer only — the consult-first path was confirmed reliable at 10s in the same\r\n * round of testing.\r\n *\r\n * Rather than keep tuning an interval that had already needed three rounds, this path now does what\r\n * its label says: an honest, single-step blind transfer, same call as a fresh cold transfer to any\r\n * number would be. The trade-off is real and accepted, not hidden — a failed transfer here drops the\r\n * caller with no recovery on screen, same as any blind transfer (`transfer-availability.md` §2's own\r\n * foundational finding: success and failure are indistinguishable at the SIP layer). The existing\r\n * outcome-relay (`transfer-outcome-relay.md`, Phase A, already live) catches it roughly a minute later\r\n * and offers the agent a callback — the accepted safety net. \"Hablar primero\" remains the path for an\r\n * agent who wants certainty over speed; this one is for speed.\r\n */\r\n const selectPresenceAgentAuto = (extension: string) => {\r\n void call.transfer(extension);\r\n };\r\n /**\r\n * NOT `call.completeTransfer()` (REFER…Replaces) — confirmed dead against Zadarma, three times, live\r\n * (`docs/specs/transfer-availability.md` §12.3): Zadarma accepts the REFER, drops the caller's leg\r\n * the same way it does for blind transfer, and never bridges anything — the consult leg is simply\r\n * orphaned. What actually works: hang up the consult leg (freeing the target's line) and then blind-\r\n * transfer the caller to that SAME target — the \"warm blind transfer\" pattern (§15 item 5's chosen\r\n * fix). Blind transfer to a target that's already known to be there and answering is exactly Phase\r\n * 0's capture 2, which worked. The one honest cost: the target's phone rings a SECOND time (once for\r\n * the consult, once for the actual transferred call) — REFER always triggers a fresh INVITE, there is\r\n * no seamless hand-off available here. They just confirmed they're expecting it, so this reads as\r\n * \"the call is coming through now,\" not a mystery second ring.\r\n */\r\n const completeTransfer = async () => {\r\n if (!consultCall) return;\r\n const target = transferTo.trim();\r\n consultIntentRef.current = 'complete';\r\n await consultCall.hangup();\r\n await call.transfer(target);\r\n };\r\n const cancelConsult = async () => {\r\n consultIntentRef.current = 'cancel';\r\n await call.cancelConsult();\r\n };\r\n\r\n // Dispositivos is inline content swapped into `.cv-call` in EVERY state now (see that JSX's own\r\n // comment for why) — once connected it used to be a floating popover. Inline content has no\r\n // \"outside\" to click away from (a stray tap on Silenciar must not dismiss it), so the only ways\r\n // out are its own back button, Escape, or opening another panel.\r\n useEffect(() => {\r\n if (!showDevices) return;\r\n const onKey = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') setPanel(null);\r\n };\r\n document.addEventListener('keydown', onKey);\r\n return () => document.removeEventListener('keydown', onKey);\r\n }, [showDevices]);\r\n\r\n // The keypad is the one popover left on this screen, so it is the one panel that closes on outside\r\n // click / Escape — same shape as `PersonFilter`'s own (HistoryTab.tsx), not shared: duplicating this\r\n // dozen lines is cheaper than coupling two unrelated pickers through an abstraction neither needs.\r\n useEffect(() => {\r\n if (!showKeypad) return;\r\n const onKey = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') setPanel(null);\r\n };\r\n document.addEventListener('keydown', onKey);\r\n if (!isConnected) return () => document.removeEventListener('keydown', onKey);\r\n // On the SHADOW ROOT's node when there is one — inside a shadow tree, `document` click targets\r\n // are retargeted to the host, so `contains()` against the host would report every internal click\r\n // as \"outside\" and the popover would never open.\r\n const root = controlsRef.current?.getRootNode() ?? document;\r\n const onDown = (e: Event) => {\r\n if (!controlsRef.current?.contains(e.target as Node)) setPanel(null);\r\n };\r\n root.addEventListener('pointerdown', onDown);\r\n return () => {\r\n document.removeEventListener('keydown', onKey);\r\n root.removeEventListener('pointerdown', onDown);\r\n };\r\n }, [showKeypad, isConnected]);\r\n\r\n // DTMF only means anything with live media flowing both ways — held and reconnecting don't qualify\r\n // (see the control's own `disabled` below). Leaving the panel open over a disabled trigger would\r\n // read as broken, so it closes the moment the call leaves 'active'. Only the keypad: another panel\r\n // that happens to be open (Transferir, Dispositivos) has nothing to do with media state.\r\n useEffect(() => {\r\n if (view && view.state !== 'active') setPanel((cur) => (cur === 'keypad' ? null : cur));\r\n }, [view?.state]);\r\n\r\n if (!view || view.state === 'ended') return null;\r\n\r\n const s = view.state;\r\n const isRinging = s === 'ringing';\r\n const inCall = isConnected;\r\n const name = view.remote.displayName;\r\n const number = view.remote.number;\r\n const showNumber = number !== name;\r\n\r\n // Full takeover, not a branch further down inside the normal layout — see `ConsultScreen`'s own\r\n // comment for why the caller's screen with a bolted-on panel was the wrong shape for this. Only\r\n // \"Hablar primero\" ever creates a consult call now — \"Transferir directo\" bypasses this entirely\r\n // (see `selectPresenceAgentAuto`'s own comment).\r\n if (consultCall && consultView) {\r\n return (\r\n <ConsultScreen\r\n mainName={name}\r\n consultView={consultView}\r\n now={consultNow}\r\n onReturn={() => void cancelConsult()}\r\n onComplete={() => void completeTransfer()}\r\n onHangupAll={() => void call.hangup()}\r\n />\r\n );\r\n }\r\n\r\n // Incoming calls only (matches the legacy softphone's own `IncomingCallView`, a screen distinct\r\n // from outbound/in-call) — and only once `resolveContact` has actually matched this number to a\r\n // real contact, the same \"known contacts only\" gate the legacy's own \"Ver mensajes\" button used.\r\n // Independent of `contactAction` (the Contactos-tab detail page's own action): same TYPE, a\r\n // DIFFERENT host-supplied instance, because what's useful to offer while someone is ringing you\r\n // is not necessarily what belongs on a contact's static detail page.\r\n const incomingAction = isRinging && view.remote.contact && incomingCallAction ? incomingCallAction : null;\r\n const IncomingActionIcon = incomingAction?.icon ?? ExternalLink;\r\n\r\n // The call timer is always MM:SS (zero-padded), matching the product. formatDuration is left\r\n // unpadded because the history list reads better as \"1:33\" than \"01:33\".\r\n const [rawM = '0', ss = '00'] = formatDuration(elapsedSeconds(view.answeredAt, now)).split(':');\r\n const mm = rawM.padStart(2, '0');\r\n\r\n return (\r\n <div className=\"cv-view\">\r\n <div className=\"cv-call\">\r\n {/*\r\n Before a call connects, Colgar (or Rechazar/Contestar) is the ONLY other control on screen —\r\n a Dispositivos popover anchored anywhere near it, even spaced out, either overlapped those\r\n buttons or had to clamp itself down to something cramped and scrolly for just two rows (this\r\n SDK's actual production embed — a 310×520 host panel with its own header eating further into\r\n that — leaves very little free room around a trigger sitting in vertically-centred content).\r\n Swapping the call info for the picker in the SAME space sidesteps the problem rather than\r\n measuring around it: the picker gets the full `.cv-call` box, not a leftover sliver of it.\r\n\r\n Once connected it is the same swap, not a popover: the control row below stays put and fully\r\n usable (mute, hold and hang up all work with this open), and Dispositivos moved out of that\r\n row into this same chip so the row could go back to four controls at a size a thumb can hit.\r\n */}\r\n {showDevices ? (\r\n <div className=\"cv-call-devices-inline\">\r\n <div className=\"cv-call-devices-header\">\r\n {/* Same chip as the entry point below, not an icon-only ghost button — an icon alone\r\n here read as decoration, not a way out, which is exactly the mistake `.cv-cp-chip`\r\n (CountryPicker) already made and fixed once: \"invisible until hover... nothing says\r\n you can change this.\" A visible \"Volver\" fixes it the same way that one was fixed. */}\r\n <button type=\"button\" className=\"cv-call-devices-chip\" onClick={() => setPanel(null)}>\r\n <ArrowLeft size={13} aria-hidden />\r\n Volver\r\n </button>\r\n <span className=\"cv-call-devices-title\">Dispositivos</span>\r\n </div>\r\n {/* Who's calling doesn't disappear just because you're checking your mic — and once\r\n connected, neither does how long you have been on the call. */}\r\n <p className=\"cv-call-devices-context\">\r\n {showNumber ? `${number} · ` : ''}\r\n {s === 'active' ? `${mm}:${ss}` : (STATUS_LABEL[s] ?? '')}\r\n </p>\r\n <div className=\"cv-settings-section-body\">\r\n <DevicePickers />\r\n </div>\r\n </div>\r\n ) : transferPickerActive ? (\r\n /*\r\n Found live (2026-09-29): the agent list a moment ago picked between showing ONE agent row\r\n or forcing a scroll — `.cv-presence-list`'s own `max-height` had already been trimmed twice\r\n (T7, then T3) chasing that, and both times the room it was chasing lived somewhere else.\r\n The full avatar/name/giant-timer block above stayed on screen, unconditionally, the WHOLE\r\n time the picker was open — exactly the anti-pattern `.cv-call-devices-inline` (above) was\r\n already built to avoid for the pre-connect device picker: \"an inline swap, not an overlay,\r\n so it gets the full box, not a leftover sliver.\" The picker never got that same treatment.\r\n Measured live (a temporary harness, `playground/react/picker-harness.*`, real Chromium at\r\n this SDK's own real embed footprint, 310×520): the avatar+name+timer block alone cost\r\n ~150px of `.cv-call`'s ~340px of usable height — more than the entire agent list, the mode\r\n toggle, and the free-text row combined. Reusing `.cv-call-devices-inline`'s OWN \"who's\r\n calling doesn't disappear\" compact context line (below) instead of the full block gives\r\n that ~150px back to the one thing this screen is actually for right now: the list.\r\n */\r\n <div className=\"cv-transfer\">\r\n <div className=\"cv-transfer-context\">\r\n <span className=\"cv-call-devices-title\">{name}</span>\r\n <p className=\"cv-call-devices-context\">\r\n {showNumber ? `${number} · ` : ''}\r\n {s === 'active' ? `${mm}:${ss}` : (STATUS_LABEL[s] ?? '')}\r\n </p>\r\n </div>\r\n {consultOutcome ? (\r\n <p className=\"cv-dial-outcome\" role=\"status\" data-shown=\"true\">\r\n {consultFailText(consultOutcome)}\r\n </p>\r\n ) : null}\r\n {/*\r\n Attended-first by default (SPEC §5.6, `docs/specs/transfer-availability.md` §5): free\r\n text always consults first — its target is unconfirmed, and a blind transfer's REFER\r\n outcome is unknowable against Zadarma (§2). A presence-picked colleague under\r\n \"Transferir directo\" (below) is the one deliberate exception — see\r\n `selectPresenceAgentAuto`'s own comment for why that one-click blind transfer is\r\n accepted there.\r\n */}\r\n <div className=\"cv-transfer-row\">\r\n <input\r\n className=\"cv-search\"\r\n value={transferTo}\r\n onChange={(e) => setTransferTo(e.target.value)}\r\n placeholder=\"Nombre, ext. o número\"\r\n aria-label=\"Transferir a\"\r\n autoFocus\r\n />\r\n <button\r\n className=\"cv-btn cv-btn--accent\"\r\n disabled={!transferTo.trim()}\r\n onClick={() => void startConsult()}\r\n >\r\n {transferTo.trim() ? `Llamar a ${truncateForButton(transferTo.trim())}` : 'Llamar'}\r\n </button>\r\n </div>\r\n {/* Plan T3 (spec §5.4/§10.1): reuses `HistoryTab`'s own `.cv-segmented` filter-toggle\r\n pattern verbatim — same tablist semantics, same already-styled look — rather than\r\n inventing a second segmented-control design for the same widget. */}\r\n <div className=\"cv-segmented\" role=\"tablist\" aria-label=\"Modo de transferencia\">\r\n {(\r\n [\r\n { key: 'consult', label: 'Hablar primero' },\r\n { key: 'auto', label: 'Transferir directo' },\r\n ] as const\r\n ).map(({ key, label }) => (\r\n <button\r\n key={key}\r\n type=\"button\"\r\n role=\"tab\"\r\n aria-selected={quickTransfer === (key === 'auto')}\r\n className=\"cv-segmented-btn\"\r\n onClick={() => setQuickTransfer(key === 'auto')}\r\n >\r\n {label}\r\n </button>\r\n ))}\r\n </div>\r\n <TransferPicker\r\n agents={presence}\r\n myUserId={myUserId}\r\n query={transferTo}\r\n onSelect={quickTransfer ? selectPresenceAgentAuto : selectPresenceAgent}\r\n />\r\n </div>\r\n ) : (\r\n <>\r\n <div className=\"cv-avatar-wrap\">\r\n {/* The halo is the one moment worth animating — it reads as \"ringing\" at a glance. */}\r\n {isRinging ? <span className=\"cv-avatar-ping\" aria-hidden /> : null}\r\n <div className=\"cv-avatar\" aria-hidden>\r\n {initials(name)}\r\n </div>\r\n {s === 'active' ? <span className=\"cv-avatar-dot\" aria-hidden /> : null}\r\n </div>\r\n\r\n <div className=\"cv-call-name\">{name}</div>\r\n {showNumber ? <div className=\"cv-call-number\">{number}</div> : null}\r\n {fromName ? (\r\n <div className=\"cv-call-from\">\r\n <PhoneOutgoing size={11} aria-hidden />\r\n <span>Desde {fromName}</span>\r\n </div>\r\n ) : null}\r\n\r\n {s === 'active' ? (\r\n <div className=\"cv-timer\" aria-label=\"Duración de la llamada\">\r\n <b>{mm}</b>\r\n <i>:</i>\r\n <b>{ss}</b>\r\n </div>\r\n ) : (\r\n <div className=\"cv-call-status\">\r\n {s === 'held' ? <span className=\"cv-badge-hold\">{STATUS_LABEL[s]}</span> : (STATUS_LABEL[s] ?? '')}\r\n </div>\r\n )}\r\n\r\n {/* Present in every state: it is the one way to reach the device picker, and is no longer a\r\n control in the row below (that row is four controls now — see `.cv-controls-row`). */}\r\n <div className=\"cv-call-chips\">\r\n {/* The caller-specific action comes first — it is about who is calling, which\r\n outranks a phone-utility setting. Wraps onto its own line rather than forcing\r\n both chips into a fixed row: a host's label is arbitrary text, not something\r\n this component can assume is short. (`incomingAction` is only ever set while\r\n ringing, so once connected this row is Dispositivos alone.) */}\r\n {incomingAction ? (\r\n <button\r\n type=\"button\"\r\n className=\"cv-call-devices-chip\"\r\n onClick={() => incomingAction.onClick(view.remote.contact!)}\r\n >\r\n <IncomingActionIcon size={13} aria-hidden />\r\n {incomingAction.label}\r\n </button>\r\n ) : null}\r\n <button type=\"button\" className=\"cv-call-devices-chip\" onClick={() => setPanel('devices')}>\r\n <Headphones size={13} aria-hidden />\r\n Dispositivos\r\n </button>\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n\r\n {/*\r\n Two tiers, not one row. Hang up is the ONE action that must never be hunted for, so it sits\r\n alone, centred and largest — the anchor the eye lands on. The secondaries flank above it.\r\n Previously all four shared a row and hang up was simply the last of them, the same visual\r\n weight as \"transfer\", off to one side. On a live call that is the wrong hierarchy.\r\n */}\r\n <div className=\"cv-controls\" ref={controlsRef}>\r\n {isRinging ? (\r\n <div className=\"cv-controls-primary\">\r\n <div className=\"cv-ctrl-item\">\r\n <button\r\n type=\"button\"\r\n className=\"cv-round cv-round--hangup\"\r\n onClick={() => void call.reject()}\r\n aria-label=\"Rechazar\"\r\n >\r\n <PhoneOff size={26} />\r\n </button>\r\n <span className=\"cv-ctrl-label\" aria-hidden>\r\n Rechazar\r\n </span>\r\n </div>\r\n <div className=\"cv-ctrl-item\">\r\n <button\r\n type=\"button\"\r\n className=\"cv-round cv-round--answer\"\r\n onClick={() => void call.answer()}\r\n aria-label=\"Contestar\"\r\n part=\"answer-button\"\r\n >\r\n <Phone size={26} />\r\n </button>\r\n <span className=\"cv-ctrl-label\" aria-hidden>\r\n Contestar\r\n </span>\r\n </div>\r\n </div>\r\n ) : (\r\n <>\r\n {inCall ? (\r\n <div className=\"cv-controls-row\">\r\n <Control\r\n icon={view.isMuted ? MicOff : Mic}\r\n label={view.isMuted ? 'Activar' : 'Silenciar'}\r\n pressed={view.isMuted}\r\n tone=\"danger\"\r\n onClick={() => call.mute(!view.isMuted)}\r\n />\r\n <Control\r\n icon={view.isOnHold ? Play : Pause}\r\n label={view.isOnHold ? 'Reanudar' : 'Espera'}\r\n pressed={view.isOnHold}\r\n tone=\"hold\"\r\n onClick={() => (view.isOnHold ? void call.unhold() : void call.hold())}\r\n />\r\n <Control\r\n icon={ArrowLeftRight}\r\n label=\"Transferir\"\r\n pressed={showTransfer}\r\n tone=\"accent\"\r\n onClick={() => togglePanel('transfer')}\r\n />\r\n <Control\r\n icon={Grid3x3}\r\n label=\"Teclado\"\r\n pressed={showKeypad}\r\n tone=\"accent\"\r\n disabled={s !== 'active'}\r\n title={\r\n s === 'held'\r\n ? 'Reanuda la llamada para usar el teclado'\r\n : s === 'reconnecting'\r\n ? 'No disponible mientras se reconecta'\r\n : undefined\r\n }\r\n onClick={() => togglePanel('keypad')}\r\n />\r\n </div>\r\n ) : null}\r\n <div className=\"cv-controls-primary\">\r\n <div className=\"cv-ctrl-item\">\r\n <button\r\n type=\"button\"\r\n className=\"cv-round cv-round--hangup\"\r\n onClick={() => void call.hangup()}\r\n aria-label=\"Colgar\"\r\n part=\"hangup-button\"\r\n >\r\n <PhoneOff size={26} />\r\n </button>\r\n <span className=\"cv-ctrl-label\" aria-hidden>\r\n Colgar\r\n </span>\r\n </div>\r\n </div>\r\n {/*\r\n Anchored to `.cv-controls` (position:relative, spanning the full row) rather than to\r\n the Teclado trigger's own small wrapper — the same fix `.cv-cp`/CountryPicker already\r\n needed (see its own comment): anchoring to a narrow, off-centre trigger let the\r\n popover's edge reach `.cv-softphone`'s `overflow:hidden` and get clipped. A full-width\r\n anchor makes that arithmetically impossible.\r\n */}\r\n {inCall && showKeypad ? (\r\n <div className=\"cv-keypad-popover cv-keypad-popover--above\" role=\"dialog\" aria-label=\"Teclado\">\r\n {KEYPAD_KEYS.map(([key, letters]) => (\r\n <button\r\n key={key}\r\n type=\"button\"\r\n className=\"cv-key\"\r\n onClick={() => {\r\n call.sendDigits(key);\r\n // AFTER the send, so the tone confirms the digit actually went out — if\r\n // `sendDigits` throws (the session is not in a state that can carry DTMF),\r\n // silence is the honest feedback. The far end gets the digit as a SIP INFO\r\n // message the local user never hears, which is why this tone exists at all.\r\n if (keyTones) playKeyTone(key);\r\n }}\r\n >\r\n <b>{key}</b>\r\n {letters ? <small>{letters}</small> : null}\r\n </button>\r\n ))}\r\n </div>\r\n ) : null}\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { ChevronRight } from 'lucide-react';\r\nimport type { ReactNode } from 'react';\r\nimport type { ContactActionIcon } from '../types.js';\r\n\r\n/**\r\n * One row on a detail page (contact or call). `eyebrow` is the informational shape (a field: Teléfono,\r\n * its value below) — `onClick` is the action shape (one line, a chevron, something happens). A row is\r\n * never both: the legacy's \"Conversación\" row forced an ACTION into a field's label/value layout,\r\n * which is why it read as an odd, oversized field rather than as a button. Splitting the two here is\r\n * what fixes that.\r\n *\r\n * Shared between `ContactDetail` and `HistoryDetail` rather than duplicated — the two pages show\r\n * different fields, but the ROW itself (icon + eyebrow + value, optionally a chevron) is one thing.\r\n */\r\nexport function DetailRow({\r\n icon: Icon,\r\n eyebrow,\r\n text,\r\n onClick,\r\n}: Readonly<{\r\n icon: ContactActionIcon;\r\n eyebrow?: string;\r\n text: ReactNode;\r\n onClick?: () => void;\r\n}>) {\r\n const inner = (\r\n <>\r\n <span className=\"cv-detail-row-icon\" aria-hidden>\r\n <Icon size={16} />\r\n </span>\r\n <span className=\"cv-detail-row-text\">\r\n {eyebrow ? <span className=\"cv-detail-row-eyebrow\">{eyebrow}</span> : null}\r\n <span className=\"cv-detail-row-value\">{text}</span>\r\n </span>\r\n {onClick ? <ChevronRight size={16} className=\"cv-detail-row-chevron\" aria-hidden /> : null}\r\n </>\r\n );\r\n return onClick ? (\r\n <button type=\"button\" className=\"cv-detail-row cv-detail-row--action\" onClick={onClick}>\r\n {inner}\r\n </button>\r\n ) : (\r\n <div className=\"cv-detail-row\">{inner}</div>\r\n );\r\n}\r\n","import { ArrowLeft, ExternalLink, Phone } from 'lucide-react';\r\nimport { useSoftphone } from '../../react/index.js';\r\nimport { useIntlFormatter } from '../dialing/format-number.js';\r\nimport { initials } from '../lib/format.js';\r\nimport { DetailRow } from './DetailRow.js';\r\nimport type { Contact } from '../../core/types.js';\r\nimport type { ContactAction } from '../types.js';\r\n\r\n/**\r\n * A contact's detail page — avatar, name, phone, one optional host-defined action, and the call\r\n * button. Opens over the list when a contact is tapped (`ContactsTab` owns that transition); this\r\n * component only knows how to show ONE contact and get back out.\r\n */\r\nexport function ContactDetail({\r\n contact,\r\n onBack,\r\n contactAction,\r\n}: Readonly<{\r\n contact: Contact;\r\n onBack: () => void;\r\n contactAction?: ContactAction;\r\n}>) {\r\n const softphone = useSoftphone();\r\n const formatIntl = useIntlFormatter();\r\n const formatted = formatIntl(contact.phone);\r\n const name = contact.name ?? formatted;\r\n\r\n return (\r\n <div className=\"cv-detail\" role=\"region\" aria-label={name}>\r\n <div className=\"cv-detail-head\">\r\n <button type=\"button\" className=\"cv-detail-back\" onClick={onBack}>\r\n <ArrowLeft size={16} aria-hidden />\r\n Contactos\r\n </button>\r\n </div>\r\n\r\n <div className=\"cv-detail-body\">\r\n <div className=\"cv-detail-identity\">\r\n <span className=\"cv-detail-avatar\" aria-hidden>\r\n {initials(contact.name)}\r\n </span>\r\n <h2 className=\"cv-detail-name\">{name}</h2>\r\n </div>\r\n\r\n <div className=\"cv-detail-rows\">\r\n <DetailRow icon={Phone} eyebrow=\"Teléfono\" text={formatted} />\r\n {contactAction ? (\r\n <DetailRow\r\n icon={contactAction.icon ?? ExternalLink}\r\n text={contactAction.label}\r\n onClick={() => contactAction.onClick(contact)}\r\n />\r\n ) : null}\r\n </div>\r\n </div>\r\n\r\n <div className=\"cv-detail-foot\">\r\n <button\r\n type=\"button\"\r\n className=\"cv-btn cv-btn--accent cv-detail-call\"\r\n onClick={() => void softphone.call(contact.phone)}\r\n >\r\n <Phone size={16} aria-hidden />\r\n Llamar\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { useCallback, useEffect, useRef, useState } from 'react';\r\n\r\nexport interface InfiniteListPage<T> {\r\n readonly items: readonly T[];\r\n /** Whether another page exists beyond this one. */\r\n readonly hasMore: boolean;\r\n}\r\n\r\nexport interface InfiniteListResult<T> {\r\n readonly items: readonly T[];\r\n /** True only while the FIRST page (for the current `loadPage`) is in flight. */\r\n readonly loading: boolean;\r\n /** True while a SUBSEQUENT page is in flight — kept separate from `loading` so the list doesn't\r\n * drop back to the full empty/spinner state on every scroll-triggered fetch. */\r\n readonly loadingMore: boolean;\r\n readonly hasMore: boolean;\r\n /** The first page failed. Subsequent-page failures are not surfaced here — see `loadMore` below. */\r\n readonly error: boolean;\r\n /** Attach to the scrollable list element — the `IntersectionObserver`'s `root`. */\r\n readonly containerRef: (node: HTMLElement | null) => void;\r\n /** Attach to a marker rendered after the last row, only while `hasMore`. */\r\n readonly sentinelRef: (node: HTMLElement | null) => void;\r\n}\r\n\r\n/**\r\n * Pages a list on scroll. `loadPage(skip)` fetches one page; the hook appends it and arms a\r\n * sentinel row, observed with a plain `IntersectionObserver` against the scrollable container, to\r\n * fetch the next one as it nears the bottom. No virtualization, no extra dependency — proportionate\r\n * to the list sizes a softphone panel holds (a CRM's contacts, a call history), where scrolling\r\n * itself is the cost, not rendering N rows of DOM.\r\n *\r\n * `root` is set explicitly to the scroll container rather than left as the default (browser\r\n * viewport), because the widget can sit anywhere on a host's page — a panel that is itself fully\r\n * on-screen but taller than the visible viewport would otherwise never fire.\r\n *\r\n * `loadPage`'s IDENTITY is the reset signal: give it a new one (`useCallback`, keyed on whatever\r\n * should restart the list — a changed `source` prop, a changed search term) and the hook drops the\r\n * current items and fetches page one again. A page landing after a newer `loadPage` has already\r\n * superseded it is discarded via `seqRef`, the same race the legacy CRM's `ContactsTab` guarded\r\n * against with its own `seqRef` bumped per search.\r\n */\r\nexport function useInfiniteList<T>(loadPage: (skip: number) => Promise<InfiniteListPage<T>>): InfiniteListResult<T> {\r\n const [items, setItems] = useState<readonly T[]>([]);\r\n const [loading, setLoading] = useState(true);\r\n const [loadingMore, setLoadingMore] = useState(false);\r\n const [hasMore, setHasMore] = useState(true);\r\n const [error, setError] = useState(false);\r\n\r\n const seqRef = useRef(0);\r\n const itemsRef = useRef<readonly T[]>(items);\r\n itemsRef.current = items;\r\n const loadingMoreRef = useRef(false);\r\n const hasMoreRef = useRef(true);\r\n\r\n useEffect(() => {\r\n const seq = ++seqRef.current;\r\n loadingMoreRef.current = false;\r\n hasMoreRef.current = true;\r\n setItems([]);\r\n setHasMore(true);\r\n setError(false);\r\n setLoading(true);\r\n void loadPage(0)\r\n .then((page) => {\r\n if (seq !== seqRef.current) return;\r\n setItems(page.items);\r\n setHasMore(page.hasMore);\r\n hasMoreRef.current = page.hasMore;\r\n })\r\n .catch(() => {\r\n if (seq !== seqRef.current) return;\r\n setItems([]);\r\n setHasMore(false);\r\n hasMoreRef.current = false;\r\n setError(true);\r\n })\r\n .finally(() => {\r\n if (seq === seqRef.current) setLoading(false);\r\n });\r\n }, [loadPage]);\r\n\r\n const loadMore = useCallback(() => {\r\n if (loadingMoreRef.current || !hasMoreRef.current) return;\r\n const seq = seqRef.current;\r\n loadingMoreRef.current = true;\r\n setLoadingMore(true);\r\n void loadPage(itemsRef.current.length)\r\n .then((page) => {\r\n if (seq !== seqRef.current) return;\r\n setItems((prev) => [...prev, ...page.items]);\r\n setHasMore(page.hasMore);\r\n hasMoreRef.current = page.hasMore;\r\n })\r\n .catch(() => {\r\n // Left `hasMore`/`hasMoreRef` untouched deliberately — a transient failure should not\r\n // permanently stop pagination. The sentinel stays armed, and scrolling away and back\r\n // (a real change in its intersection state) retries, mirroring the legacy CRM's\r\n // `react-window-infinite-loader` comment: \"ignore — retries on further scroll.\"\r\n })\r\n .finally(() => {\r\n loadingMoreRef.current = false;\r\n if (seq === seqRef.current) setLoadingMore(false);\r\n });\r\n }, [loadPage]);\r\n\r\n const [containerEl, setContainerEl] = useState<HTMLElement | null>(null);\r\n const [sentinelEl, setSentinelEl] = useState<HTMLElement | null>(null);\r\n // Refs, not the `loadMore`/`hasMore` values directly, so the observer effect below does not\r\n // need to re-run (tear down and recreate the observer) every time either one changes.\r\n const loadMoreRef = useRef(loadMore);\r\n loadMoreRef.current = loadMore;\r\n\r\n useEffect(() => {\r\n if (!containerEl || !sentinelEl) return;\r\n const observer = new IntersectionObserver(\r\n ([entry]) => {\r\n if (entry?.isIntersecting) loadMoreRef.current();\r\n },\r\n { root: containerEl, rootMargin: '160px' },\r\n );\r\n observer.observe(sentinelEl);\r\n return () => observer.disconnect();\r\n }, [containerEl, sentinelEl]);\r\n\r\n return {\r\n items,\r\n loading,\r\n loadingMore,\r\n hasMore,\r\n error,\r\n containerRef: setContainerEl,\r\n sentinelRef: setSentinelEl,\r\n };\r\n}\r\n","import { useCallback, useEffect, useState } from 'react';\r\nimport { Loader2, Phone, Search, User, Users, X } from 'lucide-react';\r\nimport { useSoftphone } from '../../react/index.js';\r\nimport { ContactDetail } from './ContactDetail.js';\r\nimport { useInfiniteList } from '../lib/useInfiniteList.js';\r\nimport type { Contact } from '../../core/types.js';\r\nimport type { ContactAction, ContactsSource } from '../types.js';\r\nimport { initials } from '../lib/format.js';\r\n\r\nconst PAGE = 50;\r\n\r\n/**\r\n * The Contactos tab — decoupled. Data comes from an injected `ContactsSource`; contacts are\r\n * `Contact { id, name, phone }` (never `wa_id`, SPEC §4). Tapping a contact always opens its detail\r\n * page (`ContactDetail`) — `contactAction` customises the ONE extra row on it, not what tapping the\r\n * list itself does; there is no bypass of the detail page from here.\r\n */\r\nexport function ContactsTab({\r\n source,\r\n contactAction,\r\n}: Readonly<{\r\n source: ContactsSource;\r\n contactAction?: ContactAction;\r\n}>) {\r\n const softphone = useSoftphone();\r\n const [search, setSearch] = useState('');\r\n const [debouncedSearch, setDebouncedSearch] = useState('');\r\n const [selected, setSelected] = useState<Contact | null>(null);\r\n\r\n useEffect(() => {\r\n const t = setTimeout(() => setDebouncedSearch(search), 200);\r\n return () => clearTimeout(t);\r\n }, [search]);\r\n\r\n // `loadPage`'s identity is `useInfiniteList`'s reset signal — it must only change once the\r\n // DEBOUNCED term changes, or every keystroke would restart the list instead of the fetch it\r\n // triggers being debounced.\r\n const loadPage = useCallback(\r\n (skip: number) =>\r\n source({ search: debouncedSearch, skip, limit: PAGE }).then((page) => ({\r\n items: page.items,\r\n hasMore: skip + page.items.length < page.total,\r\n })),\r\n [source, debouncedSearch],\r\n );\r\n const {\r\n items,\r\n loading: loadingPage,\r\n loadingMore,\r\n hasMore,\r\n containerRef,\r\n sentinelRef,\r\n } = useInfiniteList(loadPage);\r\n // The 200ms debounce above delays `debouncedSearch` (and with it `loadPage`'s identity), so the\r\n // very first keystroke would otherwise keep showing the PREVIOUS term's results for up to 200ms\r\n // with no loading indicator. Comparing the two search values catches exactly that window.\r\n const loading = loadingPage || search !== debouncedSearch;\r\n\r\n return (\r\n <div className=\"cv-view\">\r\n <div className=\"cv-list-head\">\r\n {/*\r\n A wrapper, not a change to `.cv-search` itself — that class is shared with the transfer\r\n input in CallScreen, which wants none of this (no icon, no clear button, a different\r\n affordance entirely). The icon and clear button are additive, scoped to this field only.\r\n */}\r\n <div className=\"cv-search-field\">\r\n <Search className=\"cv-search-icon\" size={15} aria-hidden />\r\n <input\r\n className=\"cv-search cv-search--icon\"\r\n value={search}\r\n onChange={(e) => setSearch(e.target.value)}\r\n placeholder=\"Buscar contactos\"\r\n aria-label=\"Buscar contactos\"\r\n />\r\n {search ? (\r\n <button\r\n type=\"button\"\r\n className=\"cv-search-clear\"\r\n onClick={() => setSearch('')}\r\n aria-label=\"Limpiar búsqueda\"\r\n >\r\n <X size={14} />\r\n </button>\r\n ) : null}\r\n </div>\r\n </div>\r\n\r\n <div className=\"cv-list\" ref={containerRef}>\r\n {loading ? (\r\n // The spinner alone was silent to a screen reader — nothing else on this state carries\r\n // the word \"loading\" for it to announce. `role=\"status\"` + real text fixes both the\r\n // accessibility gap and, incidentally, gives the icon something to be decorative NEXT TO\r\n // rather than being the sole carrier of the information itself.\r\n <div className=\"cv-empty\" role=\"status\">\r\n <Loader2 className=\"cv-empty-spinner\" size={18} aria-hidden />\r\n <span className=\"cv-empty-title\">Cargando…</span>\r\n </div>\r\n ) : items.length === 0 ? (\r\n <div className=\"cv-empty\">\r\n <span className=\"cv-empty-icon\" aria-hidden>\r\n <Users size={20} />\r\n </span>\r\n <p className=\"cv-empty-title\">{search ? 'Sin resultados' : 'No tienes contactos'}</p>\r\n <p className=\"cv-empty-sub\">\r\n {search ? `Nada coincide con «${search}».` : 'Tus contactos con teléfono aparecerán aquí.'}\r\n </p>\r\n </div>\r\n ) : (\r\n <>\r\n {items.map((c) => (\r\n // A row, not a button: the name area and the call action are separate controls, so\r\n // neither is nested inside the other (nested interactives are invalid + inaccessible).\r\n <div key={c.id} className=\"cv-item\">\r\n <span className=\"cv-item-avatar\" aria-hidden>\r\n {initials(c.name) === '#' ? <User size={17} /> : initials(c.name)}\r\n </span>\r\n {/* Always enabled — tapping a contact opens its detail page unconditionally now.\r\n `contactAction` decides whether THAT page has an extra row, not whether this does\r\n anything at all. */}\r\n <button type=\"button\" className=\"cv-item-main\" onClick={() => setSelected(c)}>\r\n <span className=\"cv-item-name\">{c.name ?? c.phone}</span>\r\n <span className=\"cv-item-sub\">{c.phone}</span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n className=\"cv-item-action\"\r\n data-tone=\"accent\"\r\n aria-label={`Llamar a ${c.name ?? c.phone}`}\r\n onClick={() => void softphone.call(c.phone)}\r\n >\r\n <Phone size={16} />\r\n </button>\r\n </div>\r\n ))}\r\n {/* The scroll-triggered \"load more\" marker — only rendered while there IS more, so the\r\n observer (see `useInfiniteList`) naturally stops firing once the list is exhausted. */}\r\n {hasMore ? <div ref={sentinelRef} className=\"cv-list-sentinel\" aria-hidden /> : null}\r\n {loadingMore ? (\r\n <div className=\"cv-list-loading-more\" role=\"status\" aria-label=\"Cargando más contactos\">\r\n <Loader2 className=\"cv-list-loading-more-spinner\" size={14} aria-hidden />\r\n </div>\r\n ) : null}\r\n </>\r\n )}\r\n </div>\r\n\r\n {/* Kept mounted underneath the list, not swapped in its place — so the list's own scroll\r\n position and size measurements survive a round trip through the detail page and back. */}\r\n {selected ? (\r\n <ContactDetail\r\n contact={selected}\r\n onBack={() => setSelected(null)}\r\n {...(contactAction ? { contactAction } : {})}\r\n />\r\n ) : null}\r\n </div>\r\n );\r\n}\r\n","import { PhoneIncoming, PhoneMissed, PhoneOutgoing } from 'lucide-react';\r\nimport type { CallHistoryEntry, CallOutcome, ContactActionIcon } from '../types.js';\r\n\r\n/** The SDK's own vocabulary (never the PBX's raw disposition string — see `coventia/sources.ts`). */\r\nexport const OUTCOME_LABELS: Record<CallOutcome, string> = {\r\n 'no-answer': 'No contestada',\r\n busy: 'Ocupada',\r\n cancelled: 'Cancelada',\r\n failed: 'Fallida',\r\n unavailable: 'No disponible',\r\n};\r\n\r\n/** A literal clock time — callers that also show the date (a day header, a full timestamp) say it\r\n * separately rather than repeating it here. */\r\nexport function timeLabel(at: Date): string {\r\n return at.toLocaleTimeString('es-ES', { hour: '2-digit', minute: '2-digit' });\r\n}\r\n\r\n/** Date AND time together, spelled out — the call detail page's own \"Fecha y hora\" row, which has no\r\n * day-group header above it to lean on the way a list row does. */\r\nexport function fullDateLabel(at: Date): string {\r\n return at.toLocaleString('es-ES', {\r\n day: '2-digit',\r\n month: 'long',\r\n year: 'numeric',\r\n hour: '2-digit',\r\n minute: '2-digit',\r\n });\r\n}\r\n\r\nexport function Icon({ entry }: Readonly<{ entry: CallHistoryEntry }>) {\r\n if (entry.missed) return <PhoneMissed size={16} />;\r\n return entry.direction === 'inbound' ? <PhoneIncoming size={16} /> : <PhoneOutgoing size={16} />;\r\n}\r\n\r\n/**\r\n * The same icon `Icon` renders, but as a bare component reference rather than a rendered element —\r\n * what `DetailRow`'s `icon` prop needs (it renders the icon itself, at its own size). Kept separate\r\n * from `Icon` rather than having `Icon` take an optional `size` and reusing it two ways: `Icon` is a\r\n * component meant to be written as `<Icon entry={e} />`; this is a value meant to be passed around.\r\n */\r\nexport function statusIcon(entry: CallHistoryEntry): ContactActionIcon {\r\n if (entry.missed) return PhoneMissed;\r\n return entry.direction === 'inbound' ? PhoneIncoming : PhoneOutgoing;\r\n}\r\n\r\n/**\r\n * Three status hues, not two — matching the legacy CRM's own split (emerald/sky/rose) rather than\r\n * collapsing an answered outgoing call into the same colour as an answered incoming one. Direction\r\n * is already the icon's shape; this is a SEPARATE signal (did it connect) that direction alone can't\r\n * carry once \"connected\" itself gets a colour at all.\r\n */\r\nexport function statusTone(entry: CallHistoryEntry): 'accent' | 'info' | 'danger' {\r\n if (entry.missed) return 'danger';\r\n return entry.direction === 'inbound' ? 'accent' : 'info';\r\n}\r\n","import { useEffect, useState, type ReactNode } from 'react';\r\nimport { ArrowLeft, ArrowRight, CalendarClock, Hash, Loader2, Mic, Phone, PhoneOutgoing, Timer, User } from 'lucide-react';\r\nimport { useSoftphone } from '../../react/index.js';\r\nimport { outboundNumberStore, useKnownOutboundNumbers } from '../outbound/outbound-number-store.js';\r\nimport { useIntlFormatter } from '../dialing/format-number.js';\r\nimport { DetailRow } from './DetailRow.js';\r\nimport { Icon, OUTCOME_LABELS, statusIcon, statusTone, timeLabel, fullDateLabel } from './history-format.js';\r\nimport { formatDuration } from '../lib/format.js';\r\nimport type { CallDetail, CallHandler, CallHistoryEntry } from '../types.js';\r\nimport type { OutboundNumberSettings } from '../../core/types.js';\r\n\r\n/**\r\n * Who handled the call, in order — \"Ana · 102 → Bruno · 100\", the LAST hop (the one it ended with)\r\n * highlighted. A hop whose extension never resolved to an org member falls back to \"Ext. 102\" rather\r\n * than disappearing — unifying `CallHandler`'s two sources (a real handler, a bare extension) into one\r\n * rendering, since both are the same shape by the time they reach here (see `toHandledBy`).\r\n */\r\nfunction HandlerChain({ handlers }: Readonly<{ handlers: readonly CallHandler[] }>) {\r\n return (\r\n <span className=\"cv-detail-handlers\">\r\n {handlers.map((h, i) => {\r\n const isLast = i === handlers.length - 1;\r\n const label = h.name ?? `Ext. ${h.extension}`;\r\n return (\r\n <span key={`${h.extension}-${i}`} className=\"cv-detail-handler-hop\">\r\n {i > 0 ? <ArrowRight size={12} className=\"cv-detail-handler-arrow\" aria-hidden /> : null}\r\n <span className=\"cv-detail-handler-chip\" data-tone={isLast ? 'accent' : undefined}>\r\n {label}\r\n {h.name ? <span className=\"cv-detail-handler-ext\">· {h.extension}</span> : null}\r\n </span>\r\n </span>\r\n );\r\n })}\r\n </span>\r\n );\r\n}\r\n\r\n/**\r\n * The number an OUTBOUND call showed — under the name the org gave it when the dialpad already knows the org's\r\n * numbers (never fetched just for this: the number alone is a complete answer). Two lines, not \"name · number\": on\r\n * one line the number, the part that matters, was the part cut off. `null` when the call is inbound or the backend\r\n * did not record it (calls placed before it started recording `from_number`).\r\n */\r\nfunction outboundFrom(\r\n entry: CallHistoryEntry,\r\n known: OutboundNumberSettings | null,\r\n formatIntl: (n: string) => string,\r\n): ReactNode {\r\n if (entry.direction !== 'outbound' || !entry.from) return null;\r\n const number = formatIntl(`+${entry.from}`);\r\n const label = known?.numbers.find((n) => n.number === entry.from)?.label;\r\n if (!label) return number;\r\n return (\r\n <>\r\n {label}\r\n <span className=\"cv-detail-row-sub\">{number}</span>\r\n </>\r\n );\r\n}\r\n\r\n/**\r\n * A call's detail page — identity, its recording(s) if any, and the metadata the legacy CRM's own\r\n * `CallDetail` showed. Ported close to that implementation on purpose: unlike `contactAction`, there\r\n * is no partner customisation point here to design around — the Historial tab is Coventia's data,\r\n * always, so this is a direct port rather than a generalised API.\r\n *\r\n * Opens over the list when a row is tapped (`HistoryTab` owns that transition); this component only\r\n * knows how to show ONE call and get back out.\r\n */\r\nexport function HistoryDetail({\r\n entry,\r\n onBack,\r\n}: Readonly<{\r\n entry: CallHistoryEntry;\r\n onBack: () => void;\r\n}>) {\r\n const softphone = useSoftphone();\r\n const formatIntl = useIntlFormatter();\r\n const knownNumbers = useKnownOutboundNumbers(outboundNumberStore(softphone));\r\n const [detail, setDetail] = useState<CallDetail | null>(null);\r\n const [loadingDetail, setLoadingDetail] = useState(false);\r\n\r\n // The enriched fetch — signed recording URLs, and the SAME handler chain with names resolved. Only\r\n // when there is something to enrich: `entry.loadDetail` is absent otherwise (see `CallHistoryEntry`).\r\n useEffect(() => {\r\n const load = entry.loadDetail;\r\n if (!load) return;\r\n let cancelled = false;\r\n setLoadingDetail(true);\r\n void load()\r\n .then((d) => !cancelled && setDetail(d))\r\n .catch(() => {\r\n // Kept as the list's own (unenriched) data — `loadingDetail` still clears, so the recording\r\n // section's own \"couldn't load\" state renders instead of spinning forever.\r\n })\r\n .finally(() => !cancelled && setLoadingDetail(false));\r\n return () => {\r\n cancelled = true;\r\n };\r\n }, [entry]);\r\n\r\n const formatted = formatIntl(entry.number);\r\n const name = entry.name ?? formatted;\r\n const from = outboundFrom(entry, knownNumbers, formatIntl);\r\n const handledBy = detail?.handledBy ?? entry.handledBy;\r\n const recordingUrls = detail?.recordingUrls ?? [];\r\n const loadingRecording = entry.recorded && loadingDetail && recordingUrls.length === 0;\r\n const statusText = entry.missed ? (entry.outcome ? OUTCOME_LABELS[entry.outcome] : 'Perdida') : 'Contestada';\r\n const handlerLabel =\r\n handledBy.length > 1 ? 'Ruta de la llamada' : entry.direction === 'outbound' ? 'Realizada por' : 'Atendida por';\r\n\r\n return (\r\n <div className=\"cv-detail\" role=\"region\" aria-label={name}>\r\n <div className=\"cv-detail-head\">\r\n <button type=\"button\" className=\"cv-detail-back\" onClick={onBack}>\r\n <ArrowLeft size={16} aria-hidden />\r\n Historial\r\n </button>\r\n </div>\r\n\r\n <div className=\"cv-detail-body\">\r\n <div className=\"cv-detail-identity\">\r\n <span className=\"cv-detail-avatar\" data-tone={statusTone(entry)} aria-hidden>\r\n <Icon entry={entry} />\r\n </span>\r\n <h2 className=\"cv-detail-name\" data-tone={entry.missed ? 'danger' : undefined}>\r\n {name}\r\n </h2>\r\n <p className=\"cv-detail-meta\">\r\n {statusText} · {timeLabel(entry.at)}\r\n </p>\r\n </div>\r\n\r\n {entry.recorded ? (\r\n <div className=\"cv-detail-recording\">\r\n {loadingRecording ? (\r\n <div className=\"cv-detail-recording-status\">\r\n <Loader2 size={14} className=\"cv-detail-recording-spinner\" aria-hidden />\r\n Cargando grabación…\r\n </div>\r\n ) : recordingUrls.length > 0 ? (\r\n <>\r\n <p className=\"cv-detail-recording-label\">\r\n {recordingUrls.length === 1 ? 'Grabación' : 'Grabaciones'}\r\n </p>\r\n {recordingUrls.map((url) => (\r\n <audio key={url} controls src={url} className=\"cv-detail-audio\" preload=\"metadata\" />\r\n ))}\r\n </>\r\n ) : (\r\n <p className=\"cv-detail-recording-status cv-detail-recording-status--warn\">\r\n No se pudo cargar la grabación ahora. Inténtalo de nuevo más tarde.\r\n </p>\r\n )}\r\n </div>\r\n ) : (\r\n <p className=\"cv-detail-recording-status\">\r\n <Mic size={14} aria-hidden />\r\n Esta llamada no se grabó.\r\n </p>\r\n )}\r\n\r\n <div className=\"cv-detail-rows\">\r\n <DetailRow icon={statusIcon(entry)} eyebrow=\"Estado\" text={statusText} />\r\n <DetailRow icon={CalendarClock} eyebrow=\"Fecha y hora\" text={fullDateLabel(entry.at)} />\r\n {entry.durationSec > 0 ? (\r\n <DetailRow icon={Timer} eyebrow=\"Duración\" text={formatDuration(entry.durationSec)} />\r\n ) : null}\r\n <DetailRow icon={Phone} eyebrow=\"Número\" text={formatted} />\r\n {handledBy.length > 0 ? (\r\n <DetailRow icon={User} eyebrow={handlerLabel} text={<HandlerChain handlers={handledBy} />} />\r\n ) : null}\r\n {entry.direction === 'inbound' && entry.did ? (\r\n <DetailRow icon={Hash} eyebrow=\"Número marcado (DID)\" text={formatIntl(entry.did)} />\r\n ) : null}\r\n {from ? <DetailRow icon={PhoneOutgoing} eyebrow=\"Llamada desde\" text={from} /> : null}\r\n </div>\r\n </div>\r\n\r\n <div className=\"cv-detail-foot\">\r\n <button\r\n type=\"button\"\r\n className=\"cv-btn cv-btn--accent cv-detail-call\"\r\n onClick={() => void softphone.call(entry.number)}\r\n >\r\n <Phone size={16} aria-hidden />\r\n Llamar\r\n </button>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { useCallback, useEffect, useRef, useState } from 'react';\r\nimport { Check, ChevronDown, Loader2, Mic, Phone, Users } from 'lucide-react';\r\nimport { useSoftphone } from '../../react/index.js';\r\nimport { useInfiniteList } from '../lib/useInfiniteList.js';\r\nimport { useIntlFormatter } from '../dialing/format-number.js';\r\nimport { HistoryDetail } from './HistoryDetail.js';\r\nimport { Icon, OUTCOME_LABELS, statusTone, timeLabel } from './history-format.js';\r\nimport type { AgentsDirectory, CallHistoryEntry, HistorySource } from '../types.js';\r\nimport { formatDuration } from '../lib/format.js';\r\n\r\nconst PAGE = 30;\r\ntype StatusFilter = 'all' | 'missed';\r\n\r\nfunction startOfDay(at: Date): number {\r\n return new Date(at.getFullYear(), at.getMonth(), at.getDate()).getTime();\r\n}\r\n\r\nfunction dayLabel(at: Date, now: number): string {\r\n const diffDays = Math.round((startOfDay(new Date(now)) - startOfDay(at)) / 86_400_000);\r\n if (diffDays === 0) return 'Hoy';\r\n if (diffDays === 1) return 'Ayer';\r\n return at.toLocaleDateString('es-ES', { day: 'numeric', month: 'long' });\r\n}\r\n\r\n/** Consecutive rows sharing a day label, newest-first — the server already sorts that way. */\r\nfunction groupByDay(\r\n entries: readonly CallHistoryEntry[],\r\n now: number,\r\n): ReadonlyArray<{ readonly label: string; readonly rows: readonly CallHistoryEntry[] }> {\r\n const groups: Array<{ label: string; rows: CallHistoryEntry[] }> = [];\r\n for (const e of entries) {\r\n const label = dayLabel(e.at, now);\r\n const last = groups.at(-1);\r\n if (last && last.label === label) last.rows.push(e);\r\n else groups.push({ label, rows: [e] });\r\n }\r\n return groups;\r\n}\r\n\r\n/**\r\n * \"Todas las personas\" / \"Mis llamadas · X\" / a specific person — the Historial tab's filter by who\r\n * handled the call. Own combobox, same shape as `CountryPicker`'s (a `<button>` + a positioned\r\n * `<div>`, no external popover lib) but not sharing its code: the two pickers have no reason to\r\n * change together, and duplicating this little outside-click/Escape handling is cheaper than coupling\r\n * them through a shared abstraction neither actually needs.\r\n */\r\nfunction PersonFilter({\r\n value,\r\n directory,\r\n onChange,\r\n}: Readonly<{\r\n /** '' means everyone. */\r\n value: string;\r\n directory: AgentsDirectory;\r\n onChange: (userId: string) => void;\r\n}>) {\r\n const [open, setOpen] = useState(false);\r\n const rootRef = useRef<HTMLDivElement>(null);\r\n\r\n // Close on outside click / Escape. On the SHADOW ROOT's node when there is one — inside a shadow\r\n // tree, `document` click targets are retargeted to the host, so `contains()` against the host would\r\n // report every internal click as \"outside\" and the popover would never open (see CountryPicker).\r\n useEffect(() => {\r\n if (!open) return;\r\n const root = rootRef.current?.getRootNode() ?? document;\r\n const onDown = (e: Event) => {\r\n if (!rootRef.current?.contains(e.target as Node)) setOpen(false);\r\n };\r\n const onKey = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') setOpen(false);\r\n };\r\n root.addEventListener('pointerdown', onDown);\r\n document.addEventListener('keydown', onKey);\r\n return () => {\r\n root.removeEventListener('pointerdown', onDown);\r\n document.removeEventListener('keydown', onKey);\r\n };\r\n }, [open]);\r\n\r\n const options: ReadonlyArray<{ readonly v: string; readonly label: string }> = [\r\n { v: '', label: 'Todas las personas' },\r\n ...(directory.me ? [{ v: directory.me.userId, label: `Mis llamadas · ${directory.me.name ?? 'Yo'}` }] : []),\r\n ...directory.people\r\n .filter((p) => !directory.me || p.userId !== directory.me.userId)\r\n .map((p) => ({ v: p.userId, label: p.name ?? 'Sin nombre' })),\r\n ];\r\n const label = options.find((o) => o.v === value)?.label ?? 'Todas las personas';\r\n\r\n return (\r\n <div className=\"cv-person-filter\" ref={rootRef}>\r\n <button\r\n type=\"button\"\r\n className=\"cv-person-filter-chip\"\r\n onClick={() => setOpen((o) => !o)}\r\n aria-haspopup=\"listbox\"\r\n aria-expanded={open}\r\n >\r\n <Users size={13} aria-hidden />\r\n <span className=\"cv-person-filter-label\">{label}</span>\r\n <ChevronDown size={13} className=\"cv-person-filter-caret\" data-open={open} aria-hidden />\r\n </button>\r\n {open ? (\r\n <div className=\"cv-person-filter-pop\" role=\"listbox\">\r\n {options.map((opt) => (\r\n <button\r\n key={opt.v || 'all'}\r\n type=\"button\"\r\n role=\"option\"\r\n aria-selected={opt.v === value}\r\n className=\"cv-person-filter-item\"\r\n onClick={() => {\r\n onChange(opt.v);\r\n setOpen(false);\r\n }}\r\n >\r\n <span className=\"cv-person-filter-name\">{opt.label}</span>\r\n <Check size={14} className=\"cv-person-filter-check\" data-on={opt.v === value} aria-hidden />\r\n </button>\r\n ))}\r\n </div>\r\n ) : null}\r\n </div>\r\n );\r\n}\r\n\r\n/**\r\n * The Historial tab — decoupled. Entries come from an injected `HistorySource` (SPEC §4). Tapping a\r\n * row always opens its detail page (`HistoryDetail`) — the row's own call button places a call\r\n * directly, without opening it. Same split `ContactsTab`/`ContactDetail` already settled on, for the\r\n * same reason: a row-wide tap target and a specific, separate action live at different button.\r\n *\r\n * The two filters (status, person) are local UI state — `HistorySource` merely accepts them as\r\n * optional params, same as `ContactsSource` accepts `search`, so a host's own override can honour\r\n * them or ignore them. The person directory behind the second filter is different: it is always\r\n * Coventia's own org membership (there is no partner override point for it, unlike `contacts`), so\r\n * it is read straight off `softphone.sources` rather than threaded through as a prop.\r\n */\r\nexport function HistoryTab({ source }: Readonly<{ source: HistorySource }>) {\r\n const softphone = useSoftphone();\r\n const formatIntl = useIntlFormatter();\r\n const now = Date.now();\r\n const [status, setStatus] = useState<StatusFilter>('all');\r\n const [agentId, setAgentId] = useState(''); // '' = everyone\r\n const [directory, setDirectory] = useState<AgentsDirectory | null>(null);\r\n const [selected, setSelected] = useState<CallHistoryEntry | null>(null);\r\n\r\n // Fetched once, not paginated — an org's phone members, not its calls. Absent (and the person\r\n // filter simply does not render) when there is no Coventia backend at all: a bare dialer, or a\r\n // host-supplied `history` override with nothing behind `softphone.sources`.\r\n useEffect(() => {\r\n const listAgents = softphone.sources?.listAgents;\r\n if (!listAgents) return;\r\n let cancelled = false;\r\n void listAgents()\r\n .then((d) => !cancelled && setDirectory(d))\r\n .catch(() => {});\r\n return () => {\r\n cancelled = true;\r\n };\r\n }, [softphone]);\r\n\r\n /**\r\n * `HistorySource` has no `total` (unlike `ContactsSource`), so \"is there another page\" is read\r\n * off the page itself: a page shorter than what was asked for is the last one. A page exactly\r\n * `PAGE` long that happens to be the last one costs one extra request that returns zero rows —\r\n * an acceptable trade for not having to widen the source contract just for this.\r\n */\r\n const loadPage = useCallback(\r\n (skip: number) =>\r\n source({\r\n skip,\r\n limit: PAGE,\r\n missed: status === 'missed',\r\n ...(agentId ? { userId: agentId } : {}),\r\n }).then((rows) => ({ items: rows, hasMore: rows.length === PAGE })),\r\n [source, status, agentId],\r\n );\r\n const { items: entries, loading, loadingMore, hasMore, containerRef, sentinelRef } = useInfiniteList(loadPage);\r\n const groups = groupByDay(entries, now);\r\n\r\n return (\r\n <div className=\"cv-view\">\r\n <div className=\"cv-list-head\">\r\n <div className=\"cv-segmented\" role=\"tablist\" aria-label=\"Filtrar por estado\">\r\n {(['all', 'missed'] as const satisfies readonly StatusFilter[]).map((key) => (\r\n <button\r\n key={key}\r\n type=\"button\"\r\n role=\"tab\"\r\n aria-selected={status === key}\r\n className=\"cv-segmented-btn\"\r\n onClick={() => setStatus(key)}\r\n >\r\n {key === 'all' ? 'Todas' : 'Perdidas'}\r\n </button>\r\n ))}\r\n </div>\r\n {directory ? <PersonFilter value={agentId} directory={directory} onChange={setAgentId} /> : null}\r\n </div>\r\n\r\n <div className=\"cv-list\" ref={containerRef}>\r\n {loading && <div className=\"cv-empty\">Cargando…</div>}\r\n {!loading && entries.length === 0 && (\r\n <div className=\"cv-empty\">\r\n {status === 'missed' ? 'Sin llamadas perdidas' : 'Sin llamadas recientes'}\r\n </div>\r\n )}\r\n {!loading &&\r\n groups.map((group) => (\r\n <div key={group.label}>\r\n <div className=\"cv-history-day\">{group.label}</div>\r\n {group.rows.map((e) => (\r\n <div key={e.id} className=\"cv-item\">\r\n <span className=\"cv-item-avatar\" data-tone={statusTone(e)} aria-hidden>\r\n <Icon entry={e} />\r\n </span>\r\n {/* Always enabled — tapping a call opens its detail page unconditionally, the same\r\n way a contact row does. The call button beside it is the only way to call from\r\n here now; recordings/handler info live on the detail page, not the list. */}\r\n <button\r\n type=\"button\"\r\n className=\"cv-item-main\"\r\n onClick={() => setSelected(e)}\r\n >\r\n <span className=\"cv-item-name\" data-tone={e.missed ? 'danger' : undefined}>\r\n {e.name ?? formatIntl(e.number)}\r\n </span>\r\n <span className=\"cv-item-sub\">\r\n <span className=\"tabular-nums\">{timeLabel(e.at)}</span>\r\n {e.missed ? (\r\n <span className=\"cv-item-sub-outcome\">\r\n {' '}\r\n · {e.outcome ? OUTCOME_LABELS[e.outcome] : 'Perdida'}\r\n </span>\r\n ) : (\r\n e.durationSec > 0 && ` · ${formatDuration(e.durationSec)}`\r\n )}\r\n {/* Informational only — the recording itself plays from the detail page now.\r\n A hint that opening the row is worth it, not an action of its own. */}\r\n {e.recorded ? <Mic size={11} className=\"cv-item-sub-rec\" aria-label=\"Grabada\" /> : null}\r\n </span>\r\n </button>\r\n <button\r\n type=\"button\"\r\n className=\"cv-item-action\"\r\n data-tone=\"accent\"\r\n aria-label={`Llamar a ${e.name ?? e.number}`}\r\n onClick={() => void softphone.call(e.number)}\r\n >\r\n <Phone size={16} />\r\n </button>\r\n </div>\r\n ))}\r\n </div>\r\n ))}\r\n {!loading && hasMore ? <div ref={sentinelRef} className=\"cv-list-sentinel\" aria-hidden /> : null}\r\n {loadingMore ? (\r\n <div className=\"cv-list-loading-more\" role=\"status\" aria-label=\"Cargando más llamadas\">\r\n <Loader2 className=\"cv-list-loading-more-spinner\" size={14} aria-hidden />\r\n </div>\r\n ) : null}\r\n </div>\r\n\r\n {/* Kept mounted underneath the list, not swapped in its place — so the list's own scroll\r\n position and size measurements survive a round trip through the detail page and back. */}\r\n {selected ? <HistoryDetail entry={selected} onBack={() => setSelected(null)} /> : null}\r\n </div>\r\n );\r\n}\r\n","import type { Softphone } from '../../core/softphone.js';\r\nimport type { RingtoneSettings, RingtoneSource } from '../../core/types.js';\r\n\r\n/**\r\n * The ringtone settings and the decoded audio of the ringtone that should ring (custom-ringtone.md §4.4–4.5).\r\n *\r\n * ONE per softphone, shared by the two places that need it — `useCallAudio` (which rings) and the Ajustes\r\n * section (which shows and changes the choice) — so a change made in Ajustes is what the next call plays,\r\n * with no second fetch and no prop plumbing between them.\r\n *\r\n * **Nothing here ever runs at ring time.** Settings and audio are fetched on the triggers the caller chooses\r\n * (becoming the leader tab, opening Ajustes, after a call ends) and the ring only ever reads what is already\r\n * in memory: `readyBuffer()` is synchronous. A ringtone that is not decoded yet simply isn't ready, and the\r\n * built-in tone rings instead — never silence, never a wait.\r\n */\r\nexport interface RingtoneStore {\r\n /** As last fetched, or `null` before the first successful fetch. */\r\n getSettings(): RingtoneSettings | null;\r\n /**\r\n * The decoded audio of the EFFECTIVE ringtone, when it is decoded and still the effective one. `null` means\r\n * \"ring the built-in tone\": the effective ringtone is the built-in one, or its file is not loaded (yet, or\r\n * at all).\r\n */\r\n readyBuffer(): AudioBuffer | null;\r\n /** The loop points of what `readyBuffer()` returns (seconds), or `null` = loop the whole buffer. */\r\n readyLoop(): { readonly start: number; readonly end: number } | null;\r\n /**\r\n * Re-fetches the settings, then (if audio is wanted) loads the effective ringtone. Never rejects. The very\r\n * first refresh also starts from the settings remembered on this device (if any), so the likely ringtone is\r\n * already loading — typically from the browser's HTTP cache — while the backend answers.\r\n */\r\n refresh(): Promise<void>;\r\n /** Saves this user's choice. REJECTS on failure — the caller reverts its UI. */\r\n setMine(id: string | null): Promise<void>;\r\n /**\r\n * Whether to keep the effective ringtone decoded. On while a widget with sounds is mounted; off releases\r\n * the buffer. A host with `sounds={false}` therefore never downloads any audio.\r\n */\r\n wantAudio(on: boolean): void;\r\n /** Decodes any ringtone file on demand — for a preview. Not kept. */\r\n decode(url: string): Promise<AudioBuffer>;\r\n /** Called after every change to settings or to the ready buffer. */\r\n subscribe(listener: () => void): () => void;\r\n}\r\n\r\nconst stores = new WeakMap<Softphone, RingtoneStore>();\r\n\r\n/** The store for `softphone`, or `null` when it has no Coventia backend (no ringtone settings at all). */\r\nexport function ringtoneStore(softphone: Softphone): RingtoneStore | null {\r\n const source = softphone.sources?.ringtones;\r\n if (!source) return null;\r\n let store = stores.get(softphone);\r\n if (!store) {\r\n store = createRingtoneStore(source);\r\n stores.set(softphone, store);\r\n }\r\n return store;\r\n}\r\n\r\n/** Exported for tests; production code goes through `ringtoneStore(softphone)`. */\r\nexport function createRingtoneStore(\r\n source: RingtoneSource,\r\n decodeImpl: (url: string) => Promise<AudioBuffer> = decodeRingtone,\r\n): RingtoneStore {\r\n let settings: RingtoneSettings | null = null;\r\n let audioWanted = false;\r\n /** What is decoded: always for one URL. `readyBuffer()` checks it is still the effective one. */\r\n let loaded: { readonly url: string; readonly buffer: AudioBuffer } | null = null;\r\n /** The URL currently being decoded, so overlapping refreshes do not decode the same file twice. */\r\n let loading: string | null = null;\r\n let inFlight: Promise<void> | null = null;\r\n const listeners = new Set<() => void>();\r\n\r\n const notify = (): void => {\r\n for (const l of listeners) l();\r\n };\r\n\r\n const effectiveUrl = (): string | null => {\r\n if (!settings) return null;\r\n return settings.catalogue.find((r) => r.id === settings!.effective)?.url ?? null;\r\n };\r\n\r\n const loadEffective = async (): Promise<void> => {\r\n const url = effectiveUrl();\r\n if (!audioWanted || !url || loaded?.url === url || loading === url) return;\r\n loading = url;\r\n try {\r\n const buffer = await decodeImpl(url);\r\n // Only keep it if nothing changed meanwhile: a newer choice wins over a slow older download.\r\n if (audioWanted && effectiveUrl() === url) {\r\n loaded = { url, buffer };\r\n notify();\r\n }\r\n } catch (error) {\r\n // The built-in tone rings instead; the next refresh (next call, Ajustes) tries again.\r\n console.warn(`[softphone] ringtone could not be loaded, using the built-in tone: ${url}`, error);\r\n } finally {\r\n if (loading === url) loading = null;\r\n }\r\n };\r\n\r\n const apply = (next: RingtoneSettings): void => {\r\n settings = next;\r\n // The old buffer is released once it is no longer the effective one — one decoded ringtone held, not two.\r\n if (loaded && loaded.url !== effectiveUrl()) loaded = null;\r\n notify();\r\n };\r\n\r\n return {\r\n getSettings: () => settings,\r\n\r\n readyBuffer: () => (loaded && loaded.url === effectiveUrl() ? loaded.buffer : null),\r\n\r\n readyLoop: () => {\r\n if (!loaded || loaded.url !== effectiveUrl() || !settings) return null;\r\n return settings.catalogue.find((r) => r.id === settings!.effective)?.loop ?? null;\r\n },\r\n\r\n refresh() {\r\n // One fetch at a time: a burst of triggers (leader + call end + Ajustes) costs one request.\r\n inFlight ??= (async () => {\r\n // First time only: what this device remembers, so loading starts before the backend answers.\r\n if (!settings && source.cached) {\r\n const early = await source.cached().catch(() => null);\r\n if (early && !settings) {\r\n apply(early);\r\n void loadEffective();\r\n }\r\n }\r\n try {\r\n apply(await source.get());\r\n } catch (error) {\r\n console.warn('[softphone] ringtone settings could not be loaded; keeping the previous ones', error);\r\n } finally {\r\n inFlight = null;\r\n }\r\n await loadEffective();\r\n })();\r\n return inFlight;\r\n },\r\n\r\n async setMine(id) {\r\n apply(await source.setMine(id));\r\n void loadEffective();\r\n },\r\n\r\n wantAudio(on) {\r\n if (audioWanted === on) return;\r\n audioWanted = on;\r\n if (!on) {\r\n loaded = null;\r\n notify();\r\n } else {\r\n void loadEffective();\r\n }\r\n },\r\n\r\n decode: (url) => decodeImpl(url),\r\n\r\n subscribe(listener) {\r\n listeners.add(listener);\r\n return () => listeners.delete(listener);\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Download and decode one ringtone file.\r\n *\r\n * Decoded on an `OfflineAudioContext`, NOT the shared playback context: this runs at startup, before any\r\n * user gesture, and building the real context then is exactly what the autoplay policy objects to (see\r\n * `sharedContext` in audio.ts). An `AudioBuffer` is not tied to the context that decoded it, so the ring\r\n * plays it on the shared one later. No credentials: the files are public (backend `ringtone-files.js`).\r\n */\r\nexport async function decodeRingtone(url: string): Promise<AudioBuffer> {\r\n const Offline: typeof OfflineAudioContext | undefined =\r\n typeof OfflineAudioContext !== 'undefined'\r\n ? OfflineAudioContext\r\n : (globalThis as { webkitOfflineAudioContext?: typeof OfflineAudioContext }).webkitOfflineAudioContext;\r\n if (!Offline) throw new Error('this browser cannot decode audio files');\r\n const res = await fetch(url, { credentials: 'omit' });\r\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\r\n const bytes = await res.arrayBuffer();\r\n return new Offline(1, 1, 48_000).decodeAudioData(bytes);\r\n}\r\n","import type { ReactNode } from 'react';\r\n\r\n/**\r\n * One labeled group on the Ajustes tab — a title, and a bordered body holding its rows (dividers\r\n * between them, no border of their own; see `.cv-settings-section-body`'s own CSS comment for why).\r\n *\r\n * Ajustes started as a flat list of two rows (Micrófono, Altavoces) with no grouping at all — fine\r\n * for two rows, unreadable the moment a third, unrelated setting arrives with nothing to tell it\r\n * apart from the device rows above it. This is the container every future settings group reuses, so\r\n * \"add a setting\" never again means \"invent a new layout for it.\"\r\n */\r\nexport function SettingsSection({\r\n title,\r\n children,\r\n}: Readonly<{\r\n title: string;\r\n children: ReactNode;\r\n}>) {\r\n return (\r\n <section className=\"cv-settings-section\">\r\n <h3 className=\"cv-settings-section-title\">{title}</h3>\r\n <div className=\"cv-settings-section-body\">{children}</div>\r\n </section>\r\n );\r\n}\r\n","import { ChevronRight } from 'lucide-react';\r\nimport type { ReactNode } from 'react';\r\nimport type { ContactActionIcon } from '../../types.js';\r\n\r\n/**\r\n * One entry of the Ajustes list (custom-ringtone.md §4.6): icon, the setting's name, its CURRENT value under it,\r\n * and a chevron that opens its page. The value sits under the name, not beside it — a device name like\r\n * \"Auriculares USB (Jabra Evolve2 65)\" does not fit next to \"Altavoces\" in a 310px widget.\r\n *\r\n * Without `onOpen` it is a plain row (no chevron, not focusable): a setting that exists but cannot be changed\r\n * here, which says why in `value`.\r\n */\r\nexport function SettingsNavRow({\r\n icon: Icon,\r\n title,\r\n value,\r\n onOpen,\r\n rowRef,\r\n}: Readonly<{\r\n icon: ContactActionIcon;\r\n title: string;\r\n value: ReactNode;\r\n onOpen?: () => void;\r\n /** So the list can put focus back on this row when its page closes. */\r\n rowRef?: (el: HTMLButtonElement | null) => void;\r\n}>) {\r\n const inner = (\r\n <>\r\n <span className=\"cv-settings-row-icon\" aria-hidden>\r\n <Icon size={16} />\r\n </span>\r\n <span className=\"cv-settings-nav-text\">\r\n <span className=\"cv-settings-nav-title\">{title}</span>\r\n <span className=\"cv-settings-nav-value\">{value}</span>\r\n </span>\r\n {onOpen ? <ChevronRight size={16} className=\"cv-settings-nav-chevron\" aria-hidden /> : null}\r\n </>\r\n );\r\n return onOpen ? (\r\n <button type=\"button\" className=\"cv-settings-nav\" onClick={onOpen} ref={rowRef}>\r\n {inner}\r\n </button>\r\n ) : (\r\n <div className=\"cv-settings-nav cv-settings-nav--static\">{inner}</div>\r\n );\r\n}\r\n","import { useId, useRef, type ReactNode } from 'react';\r\nimport { Check } from 'lucide-react';\r\n\r\nexport interface Choice {\r\n readonly value: string;\r\n readonly label: string;\r\n /** A second line, muted — e.g. which ringtone \"the organization's default\" currently is. */\r\n readonly sub?: string;\r\n /** A short tag beside the label, and a usage rule under it — e.g. \"Móvil\" and when not to call from it. */\r\n readonly tag?: string;\r\n readonly hint?: string;\r\n /** Shown at the end of the row, before the checkmark — e.g. a \"playing\" mark. */\r\n readonly trailing?: ReactNode;\r\n}\r\n\r\n/** How a choice was made: a tap/click is deliberate; arrowing through the list passes over choices. */\r\nexport type ChoiceVia = 'pointer' | 'keyboard';\r\n\r\n/**\r\n * A single-choice list with a checkmark (custom-ringtone.md §4.6) — what settings use instead of a dropdown when\r\n * a choice has a page of its own.\r\n *\r\n * Built on NATIVE radio inputs, visually replaced by the row and its checkmark, so the keyboard behaviour\r\n * (arrows move the choice, Tab leaves the group) and the screen-reader semantics (\"3 of 5, selected\") are the\r\n * browser's own rather than re-implemented.\r\n *\r\n * `onSelect` says HOW the choice was made, because arrows check every radio they pass: a caller that does\r\n * something audible or costly per choice (the ringtone page plays and saves) waits for the keyboard to settle.\r\n * `onReselect` is a press on the row that is already chosen — no change, but a real action (replay a sound).\r\n *\r\n * `disabled` locks the choice while it cannot change (a change in flight, a wait) WITHOUT disabling the radios: a\r\n * disabled radio drops keyboard focus, and the agent would lose their place in the list. Presses do nothing and the\r\n * checkmark stays where it is.\r\n */\r\nexport function ChoiceList({\r\n label,\r\n choices,\r\n value,\r\n onSelect,\r\n onReselect,\r\n disabled = false,\r\n}: Readonly<{\r\n /** The group's accessible name — usually the page title. */\r\n label: string;\r\n choices: readonly Choice[];\r\n value: string;\r\n onSelect: (value: string, via: ChoiceVia) => void;\r\n onReselect?: (value: string) => void;\r\n disabled?: boolean;\r\n}>) {\r\n const name = useId();\r\n // Set by a pointer press on a row, consumed by the change it causes. Arrow keys never set it.\r\n const pointer = useRef(false);\r\n\r\n return (\r\n <div className=\"cv-choices\" role=\"radiogroup\" aria-label={label} aria-disabled={disabled || undefined}>\r\n {choices.map((c) => {\r\n const checked = c.value === value;\r\n return (\r\n <label\r\n key={c.value}\r\n className=\"cv-choice\"\r\n data-checked={checked || undefined}\r\n data-disabled={disabled || undefined}\r\n onPointerDown={() => {\r\n pointer.current = true;\r\n }}\r\n >\r\n <input\r\n type=\"radio\"\r\n className=\"cv-choice-input\"\r\n name={name}\r\n value={c.value}\r\n checked={checked}\r\n onChange={() => {\r\n const via: ChoiceVia = pointer.current ? 'pointer' : 'keyboard';\r\n pointer.current = false;\r\n if (!disabled) onSelect(c.value, via);\r\n }}\r\n // A press on the row that is ALREADY chosen changes nothing, so no `change` fires — only this.\r\n // `value` is still the choice from before this press, which is how the two cases are told apart.\r\n onClick={() => {\r\n if (c.value === value) {\r\n pointer.current = false;\r\n if (!disabled) onReselect?.(c.value);\r\n }\r\n }}\r\n />\r\n <span className=\"cv-choice-text\">\r\n {c.tag ? (\r\n <span className=\"cv-choice-line\">\r\n <span className=\"cv-choice-label\">{c.label}</span>\r\n <span className=\"cv-choice-tag\">{c.tag}</span>\r\n </span>\r\n ) : (\r\n <span className=\"cv-choice-label\">{c.label}</span>\r\n )}\r\n {c.sub ? <span className=\"cv-choice-sub\">{c.sub}</span> : null}\r\n {c.hint ? <span className=\"cv-choice-hint\">{c.hint}</span> : null}\r\n </span>\r\n {c.trailing}\r\n <Check size={16} className=\"cv-choice-check\" aria-hidden />\r\n </label>\r\n );\r\n })}\r\n </div>\r\n );\r\n}\r\n","import { useEffect, useId, useRef, type ReactNode } from 'react';\r\nimport { ArrowLeft } from 'lucide-react';\r\n\r\n/**\r\n * One Ajustes page (custom-ringtone.md §4.6): the same overlay, back button and entrance as the contact and\r\n * call detail pages (`.cv-detail`), so the widget has ONE way of going one level deeper, not two.\r\n *\r\n * On open, focus moves to the title — keyboard and screen-reader users land where the new content starts\r\n * instead of on a row now covered by this page. Escape goes back, as the arrow does.\r\n */\r\nexport function SettingsPage({\r\n title,\r\n intro,\r\n onBack,\r\n children,\r\n}: Readonly<{\r\n title: string;\r\n intro?: string;\r\n onBack: () => void;\r\n children: ReactNode;\r\n}>) {\r\n const titleId = useId();\r\n const heading = useRef<HTMLHeadingElement>(null);\r\n useEffect(() => heading.current?.focus(), []);\r\n\r\n return (\r\n <div\r\n className=\"cv-detail cv-settings-page\"\r\n role=\"region\"\r\n aria-labelledby={titleId}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Escape') {\r\n e.stopPropagation();\r\n onBack();\r\n }\r\n }}\r\n >\r\n <div className=\"cv-detail-head\">\r\n <button type=\"button\" className=\"cv-detail-back\" onClick={onBack}>\r\n <ArrowLeft size={16} aria-hidden />\r\n Ajustes\r\n </button>\r\n </div>\r\n <div className=\"cv-settings-page-body\">\r\n <h2 className=\"cv-settings-page-title\" id={titleId} tabIndex={-1} ref={heading}>\r\n {title}\r\n </h2>\r\n {intro ? <p className=\"cv-settings-page-intro\">{intro}</p> : null}\r\n {children}\r\n </div>\r\n </div>\r\n );\r\n}\r\n","import { useEffect, useRef, useState } from 'react';\r\nimport { Volume2 } from 'lucide-react';\r\nimport { useDevices } from '../../../react/index.js';\r\nimport { playTestTone, primeAudio, TEST_TONE_MS, type Tone } from '../../audio/audio.js';\r\nimport { deviceLabel, type DeviceKind } from '../DevicePicker.js';\r\nimport { ChoiceList, type Choice } from './ChoiceList.js';\r\nimport { SettingsPage } from './SettingsPage.js';\r\n\r\n/** `''` in the list = \"the system default\" (`null` in the SDK). */\r\nconst SYSTEM_DEFAULT = '';\r\n\r\nconst PAGES: Record<DeviceKind, { title: string; intro: string; empty: string }> = {\r\n input: {\r\n title: 'Micrófono',\r\n intro: 'El micrófono que usa el teléfono en las llamadas.',\r\n empty: 'No se encontró ningún micrófono.',\r\n },\r\n output: {\r\n title: 'Altavoces',\r\n intro: 'Dónde oyes a la otra persona durante una llamada.',\r\n empty: 'No se encontró ningún altavoz.',\r\n },\r\n ringtone: {\r\n title: 'Salida del tono',\r\n intro: 'Dónde suena el tono cuando entra una llamada. La llamada se oye por «Altavoces».',\r\n empty: 'No se encontró ningún altavoz.',\r\n },\r\n};\r\n\r\n/** The value a device row shows: that device's name, or the system default. */\r\nexport function deviceSummary(kind: DeviceKind, list: readonly MediaDeviceInfo[], id: string | null): string {\r\n const i = id ? list.findIndex((d) => d.deviceId === id) : -1;\r\n return i >= 0 ? deviceLabel(list[i]!, i, kind) : 'Predeterminado del sistema';\r\n}\r\n\r\n/**\r\n * Ajustes → Micrófono / Altavoces / Salida del tono (custom-ringtone.md §4.6): a checkmark list of the devices,\r\n * applied on tap — a local choice, nothing to save or wait for. Altavoces also offers a speaker test.\r\n */\r\nexport function DevicePage({ kind, onBack }: Readonly<{ kind: DeviceKind; onBack: () => void }>) {\r\n const devices = useDevices();\r\n const page = PAGES[kind];\r\n const list = kind === 'input' ? devices.inputs : devices.outputs;\r\n const current =\r\n kind === 'input'\r\n ? devices.currentInputId\r\n : kind === 'output'\r\n ? devices.currentOutputId\r\n : devices.currentRingtoneOutputId;\r\n const apply = (id: string | null): Promise<void> =>\r\n kind === 'input' ? devices.setInput(id) : kind === 'output' ? devices.setOutput(id) : devices.setRingtoneOutput(id);\r\n\r\n const choices: Choice[] = [\r\n { value: SYSTEM_DEFAULT, label: 'Predeterminado del sistema' },\r\n ...list.map((d, i) => ({ value: d.deviceId, label: deviceLabel(d, i, kind) })),\r\n ];\r\n\r\n return (\r\n <SettingsPage title={page.title} intro={page.intro} onBack={onBack}>\r\n {list.length > 0 ? (\r\n <ChoiceList\r\n label={page.title}\r\n choices={choices}\r\n value={current ?? SYSTEM_DEFAULT}\r\n onSelect={(v) => void apply(v === SYSTEM_DEFAULT ? null : v)}\r\n />\r\n ) : (\r\n <p className=\"cv-settings-page-empty\">{page.empty}</p>\r\n )}\r\n {kind === 'output' ? <SpeakerTest sinkId={devices.currentOutputId} /> : null}\r\n </SettingsPage>\r\n );\r\n}\r\n\r\n/** \"Probar altavoz\" — decided 2026-10-14: hear where call audio will come out, before a call. */\r\nfunction SpeakerTest({ sinkId }: Readonly<{ sinkId: string | null }>) {\r\n const [testing, setTesting] = useState(false);\r\n const tone = useRef<Tone | null>(null);\r\n const timer = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n\r\n useEffect(\r\n () => () => {\r\n tone.current?.stop();\r\n if (timer.current) clearTimeout(timer.current);\r\n },\r\n [],\r\n );\r\n\r\n const test = (): void => {\r\n primeAudio();\r\n tone.current?.stop();\r\n tone.current = playTestTone(sinkId);\r\n setTesting(true);\r\n if (timer.current) clearTimeout(timer.current);\r\n timer.current = setTimeout(() => setTesting(false), TEST_TONE_MS);\r\n };\r\n\r\n return (\r\n <button type=\"button\" className=\"cv-btn cv-settings-test\" onClick={test} disabled={testing}>\r\n <Volume2 size={16} aria-hidden />\r\n {testing ? 'Sonando…' : 'Probar altavoz'}\r\n </button>\r\n );\r\n}\r\n","import { playRingtone, primeAudio, type Tone } from './audio.js';\r\nimport { decodeRingtone } from './ringtone-store.js';\r\nimport type { RingtoneOption } from '../../core/types.js';\r\n\r\n/** A preview is a taste, not a ring: one pass of the file, at most this long. */\r\nexport const PREVIEW_MAX_MS = 10_000;\r\n/** The built-in tone has no file length to go by — two of its 3 s cycles. */\r\nexport const BUILT_IN_PREVIEW_MS = 6_000;\r\n\r\n/**\r\n * How long a preview plays: one pass of the music (between its loop points when it has them), capped; the\r\n * built-in tone (`buffer` null) for two cycles.\r\n */\r\nexport function previewDurationMs(buffer: AudioBuffer | null, loop: RingtoneOption['loop']): number {\r\n if (!buffer) return BUILT_IN_PREVIEW_MS;\r\n const seconds = loop ? loop.end - loop.start : buffer.duration;\r\n return Math.min(seconds * 1000, PREVIEW_MAX_MS);\r\n}\r\n\r\n/** A running preview. */\r\nexport interface RingtonePreview {\r\n /** Stops it now. Safe to call more than once, and after it ended. */\r\n stop(): void;\r\n /**\r\n * Settles once the preview is over — played to its end, or `stop()` called. Rejects only when the file\r\n * could not be downloaded or decoded (a `stop()` before that resolves it instead).\r\n */\r\n readonly done: Promise<void>;\r\n}\r\n\r\n/**\r\n * Plays one ringtone briefly, the way the softphone's Ajustes does — same sound, level, loop points and\r\n * length. For a host's own ringtone picker where no softphone is involved, such as an organization-default\r\n * setting (custom-ringtone.md §4.7): the built-in \"Clásico\" (`url: null`) is generated in code, so there is\r\n * no file such a page could play by itself.\r\n *\r\n * Call it from a user gesture (a click): that is when a browser lets audio start.\r\n */\r\nexport function previewRingtone(\r\n ringtone: Pick<RingtoneOption, 'url'> & Partial<Pick<RingtoneOption, 'loop'>>,\r\n options: { readonly sinkId?: string | null } = {},\r\n): RingtonePreview {\r\n primeAudio();\r\n let tone: Tone | null = null;\r\n let timer: ReturnType<typeof setTimeout> | null = null;\r\n let over = false;\r\n let settle!: () => void;\r\n let fail!: (error: unknown) => void;\r\n const done = new Promise<void>((resolve, reject) => {\r\n settle = resolve;\r\n fail = reject;\r\n });\r\n // A host that only calls stop() never sees a rejection it did not ask for.\r\n done.catch(() => {});\r\n\r\n const stop = (): void => {\r\n if (over) return;\r\n over = true;\r\n if (timer) clearTimeout(timer);\r\n tone?.stop();\r\n settle();\r\n };\r\n\r\n const play = (buffer: AudioBuffer | null): void => {\r\n if (over) return;\r\n const loop = buffer ? (ringtone.loop ?? null) : null;\r\n tone = playRingtone({ buffer, loop, sinkId: options.sinkId ?? null });\r\n timer = setTimeout(stop, previewDurationMs(buffer, loop));\r\n };\r\n\r\n if (!ringtone.url) {\r\n play(null);\r\n } else {\r\n decodeRingtone(ringtone.url).then(play, (error: unknown) => {\r\n if (over) return;\r\n over = true;\r\n fail(error);\r\n });\r\n }\r\n return { stop, done };\r\n}\r\n","import { useCallback, useEffect, useRef, useState, useSyncExternalStore } from 'react';\r\nimport { playRingtone, primeAudio, type Tone } from '../../audio/audio.js';\r\nimport type { RingtoneStore } from '../../audio/ringtone-store.js';\r\nimport { previewDurationMs } from '../../audio/preview.js';\r\nimport type { RingtoneSettings } from '../../../core/types.js';\r\n\r\nconst noSubscribe = () => () => {};\r\nconst noSettings = () => null;\r\n\r\n/**\r\n * The ringtone settings as Ajustes shows them, fetched when the tab opens — one of the refresh triggers\r\n * (custom-ringtone.md §4.4): it is where a user expects to see the current org default. Settings only; the\r\n * audio is the ringing side's business.\r\n */\r\nexport function useRingtoneSettings(store: RingtoneStore | null) {\r\n const settings = useSyncExternalStore(store?.subscribe ?? noSubscribe, store?.getSettings ?? noSettings);\r\n const [failed, setFailed] = useState(false);\r\n\r\n const load = useCallback(() => {\r\n if (!store) return () => {};\r\n let live = true;\r\n setFailed(false);\r\n void store.refresh().then(() => {\r\n if (live) setFailed(store.getSettings() === null);\r\n });\r\n return () => {\r\n live = false;\r\n };\r\n }, [store]);\r\n\r\n useEffect(load, [load]);\r\n return { settings, failed, retry: load };\r\n}\r\n\r\n/** The list row's value: what rings for me, and whether it is my own choice or the organization's. */\r\nexport function ringtoneSummary(settings: RingtoneSettings | null, failed: boolean): string {\r\n if (!settings) return failed ? 'No disponible' : 'Cargando…';\r\n const byId = (id: string | null) => (id ? settings.catalogue.find((r) => r.id === id) : undefined);\r\n const mine = byId(settings.mine);\r\n if (mine) return mine.name;\r\n const org = byId(settings.orgDefault);\r\n if (org) return `${org.name} · organización`;\r\n return settings.catalogue.find((r) => r.url === null)?.name ?? 'Predeterminado';\r\n}\r\n\r\n/**\r\n * Plays one ringtone briefly, on the ringtone output — what a call would sound like. `playing` names WHICH\r\n * choice is playing ('' = the organization's default entry), so the list can mark that row.\r\n */\r\nexport function useRingtonePreview(store: RingtoneStore, sinkId: string | null) {\r\n const [playing, setPlaying] = useState<string | null>(null);\r\n const [error, setError] = useState<string | null>(null);\r\n const current = useRef<{ tone: Tone | null; timer: ReturnType<typeof setTimeout> | null } | null>(null);\r\n /** Bumped on every start/stop, so a download that finishes after the user moved on plays nothing. */\r\n const generation = useRef(0);\r\n\r\n const stop = useCallback(() => {\r\n generation.current += 1;\r\n const c = current.current;\r\n current.current = null;\r\n if (c?.timer) clearTimeout(c.timer);\r\n c?.tone?.stop();\r\n setPlaying(null);\r\n }, []);\r\n\r\n useEffect(() => stop, [stop]);\r\n\r\n /** `choice` is the list value: a ringtone id, or '' for \"the organization's default\". */\r\n const start = (settings: RingtoneSettings, choice: string): void => {\r\n stop();\r\n primeAudio(); // a tap is a user gesture — the moment the shared audio context may start\r\n setError(null);\r\n const gen = generation.current;\r\n const orgDefault = settings.catalogue.some((r) => r.id === settings.orgDefault) ? settings.orgDefault : null;\r\n const id = choice || orgDefault;\r\n const option = settings.catalogue.find((r) => r.id === id) ?? settings.catalogue.find((r) => r.url === null);\r\n setPlaying(choice);\r\n current.current = { tone: null, timer: null };\r\n\r\n const play = (buffer: AudioBuffer | null): void => {\r\n if (gen !== generation.current) return;\r\n const loop = buffer ? (option?.loop ?? null) : null;\r\n const tone = playRingtone({ buffer, loop, sinkId });\r\n // The same length as a host's `previewRingtone`: one pass of the music, capped.\r\n current.current = { tone, timer: setTimeout(stop, previewDurationMs(buffer, loop)) };\r\n };\r\n\r\n if (!option?.url) {\r\n play(null);\r\n return;\r\n }\r\n store.decode(option.url).then(play, () => {\r\n if (gen !== generation.current) return;\r\n stop();\r\n setError('No se pudo reproducir el tono.');\r\n });\r\n };\r\n\r\n return { playing, error, start, stop };\r\n}\r\n","import { useEffect, useRef, useState } from 'react';\r\nimport { Loader2, Volume2 } from 'lucide-react';\r\nimport { useDevices, useSoftphone } from '../../../react/index.js';\r\nimport { SoftphoneEvent } from '../../../core/events.js';\r\nimport { ChoiceList, type Choice, type ChoiceVia } from './ChoiceList.js';\r\nimport { SettingsPage } from './SettingsPage.js';\r\nimport { useRingtonePreview } from './ringtone-state.js';\r\nimport type { RingtoneStore } from '../../audio/ringtone-store.js';\r\nimport type { RingtoneSettings } from '../../../core/types.js';\r\n\r\n/** '' in the list = \"follow the organization's default\" (`mine: null`). */\r\nconst ORG_DEFAULT = '';\r\n/** Arrowing through the list checks every ringtone it passes: wait this long after the last move. */\r\nconst KEYBOARD_SETTLE_MS = 300;\r\n\r\n/**\r\n * Ajustes → Tono de llamada (custom-ringtone.md §4.6). Tapping a ringtone chooses it, saves it and plays it —\r\n * the iOS model; no separate Guardar (decided 2026-10-14). The keyboard does the same once it settles.\r\n */\r\nexport function RingtonePage({\r\n store,\r\n settings,\r\n failed,\r\n onRetry,\r\n onBack,\r\n}: Readonly<{\r\n store: RingtoneStore;\r\n settings: RingtoneSettings | null;\r\n failed: boolean;\r\n onRetry: () => void;\r\n onBack: () => void;\r\n}>) {\r\n const softphone = useSoftphone();\r\n const devices = useDevices();\r\n const preview = useRingtonePreview(store, devices.canSelectRingtoneOutput ? devices.currentRingtoneOutputId : null);\r\n /** The value just chosen, shown at once while its save is in flight; `undefined` = none. */\r\n const [pending, setPending] = useState<string | undefined>(undefined);\r\n const [error, setError] = useState<string | null>(null);\r\n const save = useSerialSave(store, {\r\n onSettled: () => setPending(undefined),\r\n onFailed: () => {\r\n setPending(undefined); // back to what is really saved\r\n setError('No se pudo guardar el tono. Inténtalo de nuevo.');\r\n },\r\n });\r\n\r\n // Always the latest settings for a deferred (keyboard) commit, without restarting its timer.\r\n const latest = useRef(settings);\r\n latest.current = settings;\r\n const settle = useRef<{ timer: ReturnType<typeof setTimeout>; value: string } | null>(null);\r\n\r\n const { stop: stopPreview } = preview;\r\n // A call coming in always wins over a preview. (The tab also unmounts when the call screen takes over.)\r\n useEffect(() => softphone.on(SoftphoneEvent.IncomingCall, stopPreview), [softphone, stopPreview]);\r\n\r\n // Leaving mid-settle: the checkmark already moved, so keep that choice — save it, without playing it.\r\n useEffect(\r\n () => () => {\r\n if (settle.current) {\r\n clearTimeout(settle.current.timer);\r\n save(settle.current.value || null);\r\n }\r\n },\r\n [save],\r\n );\r\n\r\n const commit = (value: string): void => {\r\n save(value || null);\r\n if (latest.current) preview.start(latest.current, value);\r\n };\r\n\r\n const onSelect = (value: string, via: ChoiceVia): void => {\r\n setError(null);\r\n setPending(value);\r\n if (settle.current) clearTimeout(settle.current.timer);\r\n settle.current = null;\r\n if (via === 'pointer') {\r\n commit(value);\r\n return;\r\n }\r\n preview.stop();\r\n settle.current = {\r\n value,\r\n timer: setTimeout(() => {\r\n settle.current = null;\r\n commit(value);\r\n }, KEYBOARD_SETTLE_MS),\r\n };\r\n };\r\n\r\n const onReselect = (value: string): void => {\r\n if (!settings) return;\r\n if (preview.playing === value) preview.stop();\r\n else preview.start(settings, value);\r\n };\r\n\r\n return (\r\n <SettingsPage\r\n title=\"Tono de llamada\"\r\n intro=\"Lo que suena cuando entra una llamada. Se guarda en tu cuenta, así que es el mismo en todos tus dispositivos.\"\r\n onBack={onBack}\r\n >\r\n {settings ? (\r\n <>\r\n <ChoiceList\r\n label=\"Tono de llamada\"\r\n choices={choicesFor(settings, preview.playing)}\r\n value={pending !== undefined ? pending : currentValue(settings)}\r\n onSelect={onSelect}\r\n onReselect={onReselect}\r\n />\r\n {error ?? preview.error ? (\r\n <p className=\"cv-settings-error\" role=\"alert\">\r\n {error ?? preview.error}\r\n </p>\r\n ) : null}\r\n </>\r\n ) : failed ? (\r\n <div className=\"cv-empty\">\r\n <p className=\"cv-empty-title\">No se pudieron cargar los tonos.</p>\r\n <button type=\"button\" className=\"cv-btn cv-settings-retry\" onClick={onRetry}>\r\n Reintentar\r\n </button>\r\n </div>\r\n ) : (\r\n <div className=\"cv-empty\" role=\"status\">\r\n <Loader2 className=\"cv-empty-spinner\" size={18} aria-hidden />\r\n <span className=\"cv-empty-title\">Cargando…</span>\r\n </div>\r\n )}\r\n </SettingsPage>\r\n );\r\n}\r\n\r\n/** My own choice when it still exists, else the org-default entry. */\r\nfunction currentValue(settings: RingtoneSettings): string {\r\n return settings.mine && settings.catalogue.some((r) => r.id === settings.mine) ? settings.mine : ORG_DEFAULT;\r\n}\r\n\r\nfunction choicesFor(settings: RingtoneSettings, playing: string | null): Choice[] {\r\n const org = settings.orgDefault ? settings.catalogue.find((r) => r.id === settings.orgDefault) : undefined;\r\n const builtIn = settings.catalogue.find((r) => r.url === null);\r\n const mark = (value: string) =>\r\n playing === value ? (\r\n <span className=\"cv-choice-playing\">\r\n <Volume2 size={15} aria-hidden />\r\n <span className=\"cv-sr-only\">Sonando</span>\r\n </span>\r\n ) : undefined;\r\n const orgChoice: Choice = {\r\n value: ORG_DEFAULT,\r\n label: org ? 'Predeterminado de la organización' : 'Predeterminado',\r\n sub: (org ?? builtIn)?.name ?? '',\r\n trailing: mark(ORG_DEFAULT),\r\n };\r\n return [orgChoice, ...settings.catalogue.map((r) => ({ value: r.id, label: r.name, trailing: mark(r.id) }))];\r\n}\r\n\r\n/**\r\n * Saves one at a time, always ending on the LATEST choice: a burst of taps sends at most one request in flight\r\n * plus the newest waiting one, so a slow earlier reply can never land after — and overwrite — a later choice.\r\n */\r\nfunction useSerialSave(\r\n store: RingtoneStore,\r\n handlers: { readonly onSettled: () => void; readonly onFailed: () => void },\r\n) {\r\n const wanted = useRef<{ id: string | null } | null>(null);\r\n const busy = useRef(false);\r\n const on = useRef(handlers);\r\n on.current = handlers;\r\n\r\n const [save] = useState(() => (id: string | null) => {\r\n wanted.current = { id };\r\n if (busy.current) return;\r\n busy.current = true;\r\n void (async () => {\r\n while (wanted.current) {\r\n const { id: next } = wanted.current;\r\n wanted.current = null;\r\n try {\r\n await store.setMine(next);\r\n if (!wanted.current) on.current.onSettled();\r\n } catch {\r\n if (!wanted.current) on.current.onFailed();\r\n }\r\n }\r\n busy.current = false;\r\n })();\r\n });\r\n return save;\r\n}\r\n","import { useEffect, useRef, useState } from 'react';\r\nimport { Loader2 } from 'lucide-react';\r\nimport { ChoiceList, type Choice, type ChoiceVia } from './ChoiceList.js';\r\nimport { SettingsPage } from './SettingsPage.js';\r\nimport { useIntlFormatter } from '../../dialing/format-number.js';\r\nimport { KIND_TAG, useOutboundNumberChange } from '../../outbound/outbound-change.js';\r\nimport { effectiveNumber, numberName, type OutboundNumberStore } from '../../outbound/outbound-number-store.js';\r\nimport type { OutboundNumberSettings } from '../../../core/types.js';\r\n\r\n/** '' in the list = \"follow the organization's default\" (`mine: null`). */\r\nconst ORG_DEFAULT = '';\r\n/**\r\n * Arrowing through the list passes over every number: wait this long after the last move before applying. Longer\r\n * than the ringtone page's — each change here is a request to the telephony provider, under a shared limit.\r\n */\r\nconst KEYBOARD_SETTLE_MS = 800;\r\n\r\n/**\r\n * Ajustes → Número de salida (outbound-number-per-agent.md §5.5, PROVISIONAL — the user decides keep or drop after\r\n * comparing it with the dialpad's \"Llamar desde\"). The same numbers, tags, locks and messages as the dialpad, through\r\n * the same store; tapping a number applies it at once, as the ringtone page saves at once.\r\n *\r\n * The message sits ABOVE the list, where the agent reads first, and is scrolled into view when a change does not go\r\n * through — with many numbers, the row just tapped can be far below it.\r\n */\r\nexport function OutboundNumberPage({\r\n store,\r\n settings,\r\n onBack,\r\n}: Readonly<{\r\n store: OutboundNumberStore;\r\n settings: OutboundNumberSettings;\r\n onBack: () => void;\r\n}>) {\r\n const formatIntl = useIntlFormatter();\r\n const current = numberName(effectiveNumber(settings), formatIntl);\r\n const change = useOutboundNumberChange(store, settings, current);\r\n /** The value just chosen, checked at once while it is applied; `undefined` = none. */\r\n const [pending, setPending] = useState<string | undefined>(undefined);\r\n const settle = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n // The latest `choose` for a deferred (keyboard) apply — it checks the lock and the choice as they are then.\r\n const choose = useRef(change.choose);\r\n choose.current = change.choose;\r\n\r\n // Leaving mid-settle drops it: nothing was applied, and the list shows the real choice next time.\r\n useEffect(\r\n () => () => {\r\n if (settle.current) clearTimeout(settle.current);\r\n },\r\n [],\r\n );\r\n\r\n const notice = useRef<HTMLParagraphElement>(null);\r\n\r\n const apply = async (value: string): Promise<void> => {\r\n setPending(value);\r\n const applied = await choose.current(value || null);\r\n setPending(undefined); // applied → the settings say so; refused → back to what is really applied\r\n // The reason sits above the list; the row tapped may be far down a long one. Once it has rendered, bring it in.\r\n if (!applied) requestAnimationFrame(() => notice.current?.scrollIntoView?.({ block: 'nearest' }));\r\n };\r\n\r\n const onSelect = (value: string, via: ChoiceVia): void => {\r\n if (settle.current) clearTimeout(settle.current);\r\n settle.current = null;\r\n if (via === 'pointer') {\r\n void apply(value);\r\n return;\r\n }\r\n setPending(value);\r\n settle.current = setTimeout(() => {\r\n settle.current = null;\r\n void apply(value);\r\n }, KEYBOARD_SETTLE_MS);\r\n };\r\n\r\n return (\r\n <SettingsPage\r\n title=\"Número de salida\"\r\n intro=\"El número que ve la persona a la que llamas. Es el mismo en todos tus dispositivos y también puedes cambiarlo desde el teclado.\"\r\n onBack={onBack}\r\n >\r\n {change.message ? (\r\n <p className=\"cv-settings-notice\" role=\"status\" data-kind={change.isError ? 'error' : 'info'} ref={notice}>\r\n {change.message}\r\n </p>\r\n ) : null}\r\n <ChoiceList\r\n label=\"Número de salida\"\r\n choices={choicesFor(settings, formatIntl, change.busy ? pending : undefined)}\r\n value={pending ?? currentValue(settings)}\r\n onSelect={onSelect}\r\n disabled={change.locked}\r\n />\r\n </SettingsPage>\r\n );\r\n}\r\n\r\n/** My own choice when it is still one of the organization's numbers, else the org-default entry. */\r\nfunction currentValue(settings: OutboundNumberSettings): string {\r\n return settings.mine && settings.numbers.some((n) => n.id === settings.mine) ? settings.mine : ORG_DEFAULT;\r\n}\r\n\r\nfunction choicesFor(\r\n settings: OutboundNumberSettings,\r\n formatIntl: (n: string) => string,\r\n applying: string | undefined,\r\n): Choice[] {\r\n const orgDefault = settings.numbers.find((n) => n.id === settings.orgDefault);\r\n const spinner = (value: string) =>\r\n applying === value ? (\r\n <span className=\"cv-choice-applying\">\r\n <Loader2 size={15} className=\"cv-choice-applying-icon\" aria-hidden />\r\n <span className=\"cv-sr-only\">Aplicando</span>\r\n </span>\r\n ) : undefined;\r\n return [\r\n {\r\n value: ORG_DEFAULT,\r\n label: 'Por defecto de la organización',\r\n sub: orgDefault ? numberName(orgDefault, formatIntl) : 'Sin número por defecto',\r\n trailing: spinner(ORG_DEFAULT),\r\n },\r\n ...settings.numbers.map((n) => {\r\n const kind = KIND_TAG[n.kind];\r\n return {\r\n value: n.id,\r\n label: numberName(n, formatIntl),\r\n ...(n.label ? { sub: formatIntl(`+${n.number}`) } : {}),\r\n ...(kind ? { tag: kind.tag, hint: kind.hint } : {}),\r\n trailing: spinner(n.id),\r\n };\r\n }),\r\n ];\r\n}\r\n\r\n/** The Ajustes row's value: the number my calls show, and whether it is my own choice or the organization's. */\r\nexport function outboundSummary(settings: OutboundNumberSettings, formatIntl: (n: string) => string): string {\r\n const effective = effectiveNumber(settings);\r\n const name = numberName(effective, formatIntl);\r\n return settings.mine || !effective ? name : `${name} · organización`;\r\n}\r\n","import { useEffect, useRef, useState } from 'react';\r\nimport { BellRing, Headphones, Mic, Music, PhoneOutgoing } from 'lucide-react';\r\nimport { useDevices, useSoftphone } from '../../react/index.js';\r\nimport { ringtoneStore } from '../audio/ringtone-store.js';\r\nimport { outboundNumberStore, useOutboundNumbers } from '../outbound/outbound-number-store.js';\r\nimport { useIntlFormatter } from '../dialing/format-number.js';\r\nimport { SettingsSection } from './SettingsSection.js';\r\nimport { SettingsNavRow } from './settings/SettingsNavRow.js';\r\nimport { DevicePage, deviceSummary } from './settings/DevicePage.js';\r\nimport { RingtonePage } from './settings/RingtonePage.js';\r\nimport { OutboundNumberPage, outboundSummary } from './settings/OutboundNumberPage.js';\r\nimport { ringtoneSummary, useRingtoneSettings } from './settings/ringtone-state.js';\r\nimport type { DeviceKind } from './DevicePicker.js';\r\n\r\n/**\r\n * `tone` is the ringtone picker, `outbound` the outbound number; the device kinds are the device pages (`ringtone` =\r\n * the ring OUTPUT device).\r\n */\r\ntype Page = 'tone' | 'outbound' | DeviceKind;\r\n\r\n/**\r\n * The Ajustes tab — a list of settings, each opening its own page (custom-ringtone.md §4.6, revised 2026-10-14).\r\n *\r\n * It used to stack every control inline, which read fine with one section and stopped reading at two. This is\r\n * the pattern settings use on narrow surfaces (iOS, Android, Zoom/WhatsApp mobile): each row names a setting\r\n * and shows its CURRENT value; its page holds the choices. One level deep only — every page is a leaf.\r\n *\r\n * The open page is plain component state: leaving the tab, or a call taking over the screen, unmounts this and\r\n * the next visit starts on the list.\r\n */\r\nexport function SettingsTab() {\r\n const softphone = useSoftphone();\r\n const devices = useDevices();\r\n const store = ringtoneStore(softphone);\r\n const ringtone = useRingtoneSettings(store);\r\n // Número de salida (outbound-number-per-agent.md §5.5, provisional): only when there is something to choose.\r\n const outStore = outboundNumberStore(softphone);\r\n const outbound = useOutboundNumbers(outStore).settings;\r\n const formatIntl = useIntlFormatter();\r\n const [page, setPage] = useState<Page | null>(null);\r\n const list = useRef<HTMLDivElement>(null);\r\n const rows = useRef<Partial<Record<Page, HTMLButtonElement | null>>>({});\r\n const returnTo = useRef<Page | null>(null);\r\n\r\n // Device names enumerate blank until the mic has been granted, and a grant fires no `devicechange` — so the\r\n // tab that shows device NAMES re-scans when it opens (see `AudioDevices.refresh`).\r\n useEffect(() => {\r\n void softphone.audio.refresh();\r\n }, [softphone]);\r\n\r\n // The list stays mounted under an open page (so its scroll survives the round trip), but must not be\r\n // reachable by Tab or a screen reader while covered. `inert` is set directly: React 18 and 19 disagree on\r\n // how to spell it as a prop.\r\n useEffect(() => {\r\n list.current?.toggleAttribute('inert', page !== null);\r\n if (page === null && returnTo.current) {\r\n rows.current[returnTo.current]?.focus();\r\n returnTo.current = null;\r\n }\r\n }, [page]);\r\n\r\n const open = (p: Page) => () => {\r\n returnTo.current = p;\r\n setPage(p);\r\n };\r\n const back = () => setPage(null);\r\n const rowRef = (p: Page) => (el: HTMLButtonElement | null) => {\r\n rows.current[p] = el;\r\n };\r\n\r\n return (\r\n <div className=\"cv-view cv-settings\">\r\n <div className=\"cv-settings-body\" ref={list}>\r\n {store ? (\r\n <SettingsSection title=\"Llamadas entrantes\">\r\n <SettingsNavRow\r\n icon={Music}\r\n title=\"Tono de llamada\"\r\n value={ringtoneSummary(ringtone.settings, ringtone.failed)}\r\n onOpen={open('tone')}\r\n rowRef={rowRef('tone')}\r\n />\r\n </SettingsSection>\r\n ) : null}\r\n {outStore && outbound && outbound.numbers.length > 1 ? (\r\n <SettingsSection title=\"Llamadas salientes\">\r\n <SettingsNavRow\r\n icon={PhoneOutgoing}\r\n title=\"Número de salida\"\r\n value={outboundSummary(outbound, formatIntl)}\r\n onOpen={open('outbound')}\r\n rowRef={rowRef('outbound')}\r\n />\r\n </SettingsSection>\r\n ) : null}\r\n <SettingsSection title=\"Dispositivos\">\r\n <SettingsNavRow\r\n icon={Mic}\r\n title=\"Micrófono\"\r\n value={deviceSummary('input', devices.inputs, devices.currentInputId)}\r\n onOpen={open('input')}\r\n rowRef={rowRef('input')}\r\n />\r\n {devices.canSelectOutput ? (\r\n <SettingsNavRow\r\n icon={Headphones}\r\n title=\"Altavoces\"\r\n value={deviceSummary('output', devices.outputs, devices.currentOutputId)}\r\n onOpen={open('output')}\r\n rowRef={rowRef('output')}\r\n />\r\n ) : (\r\n // Safari and most of Firefox have no `setSinkId`: offering a page whose choice silently does\r\n // nothing is worse than saying where the choice really lives.\r\n <SettingsNavRow\r\n icon={Headphones}\r\n title=\"Altavoces\"\r\n value=\"Tu navegador no permite elegirlos desde aquí — cámbialos en los ajustes del sistema.\"\r\n />\r\n )}\r\n {devices.canSelectRingtoneOutput ? (\r\n <SettingsNavRow\r\n icon={BellRing}\r\n title=\"Salida del tono\"\r\n value={deviceSummary('ringtone', devices.outputs, devices.currentRingtoneOutputId)}\r\n onOpen={open('ringtone')}\r\n rowRef={rowRef('ringtone')}\r\n />\r\n ) : null}\r\n </SettingsSection>\r\n </div>\r\n\r\n {page === 'tone' && store ? (\r\n <RingtonePage\r\n store={store}\r\n settings={ringtone.settings}\r\n failed={ringtone.failed}\r\n onRetry={ringtone.retry}\r\n onBack={back}\r\n />\r\n ) : page === 'outbound' && outStore && outbound ? (\r\n <OutboundNumberPage store={outStore} settings={outbound} onBack={back} />\r\n ) : page !== null && page !== 'tone' && page !== 'outbound' ? (\r\n <DevicePage kind={page} onBack={back} />\r\n ) : null}\r\n </div>\r\n );\r\n}\r\n","import { useCallback, useEffect, useState } from 'react';\r\nimport { isWebRtcSupported } from '../../core/env.js';\r\n\r\nexport type MicState = 'checking' | 'prompting' | 'warming' | 'ready' | 'denied' | 'unsupported';\r\n\r\n/**\r\n * Microphone permission, as a state machine.\r\n *\r\n * Extracted from `MicPermissionGate` so `SoftphoneWidget` can gate itself: a softphone without a\r\n * microphone is not a softphone, so asking every integrator to remember a wrapper component is\r\n * asking them to remember not to ship something broken.\r\n *\r\n * **`warming` is the part that matters, and the part the SDK had lost.**\r\n *\r\n * `navigator.permissions.query({name:'microphone'})` saying `granted` is NOT enough. Several\r\n * browsers still prompt on the first `getUserMedia` of a page session, so a gate that trusts the\r\n * query and skips straight to `ready` moves the prompt from panel-open time — where the user is\r\n * looking at a phone and expects it — to **the middle of the first call**, where a modal steals\r\n * focus from a ringing conversation.\r\n *\r\n * So `getUserMedia` runs on EVERY mount, even when already granted. It verifies the mic works in\r\n * this session and primes the track, which is why the old CRM gate did it and why dropping it during\r\n * the port was a silent regression: it only shows up on a real call, on a real machine, once.\r\n *\r\n * The tracks are stopped immediately — we wanted the grant, not the microphone. Holding them open is\r\n * the documented Twilio mic-leak (the browser tab shows a recording indicator forever).\r\n */\r\nexport function useMicPermission(): { state: MicState; request: () => Promise<void> } {\r\n const [state, setState] = useState<MicState>('checking');\r\n\r\n /** Take the mic, confirm it opens, give it straight back. */\r\n const warm = useCallback(async () => {\r\n try {\r\n const stream = await navigator.mediaDevices.getUserMedia({ audio: true });\r\n for (const track of stream.getTracks()) track.stop();\r\n setState('ready');\r\n } catch {\r\n setState('denied');\r\n }\r\n }, []);\r\n\r\n useEffect(() => {\r\n if (!isWebRtcSupported()) {\r\n setState('unsupported');\r\n return;\r\n }\r\n\r\n let cancelled = false;\r\n let status: PermissionStatus | null = null;\r\n\r\n const apply = (permission: PermissionState): void => {\r\n if (cancelled) return;\r\n if (permission === 'denied') {\r\n setState('denied');\r\n } else if (permission === 'granted') {\r\n // Granted, and STILL warm it — see the note above.\r\n setState('warming');\r\n void warm();\r\n } else {\r\n setState('prompting');\r\n }\r\n };\r\n\r\n void (async () => {\r\n try {\r\n status = await navigator.permissions.query({ name: 'microphone' as PermissionName });\r\n if (cancelled) return;\r\n apply(status.state);\r\n // The user can revoke mid-session from the browser's own UI; without this the widget keeps\r\n // offering a dialer that cannot open a microphone.\r\n status.onchange = () => status && apply(status.state);\r\n } catch {\r\n // Firefox has historically not supported querying 'microphone'. Not knowing is fine — ask.\r\n if (!cancelled) setState('prompting');\r\n }\r\n })();\r\n\r\n return () => {\r\n cancelled = true;\r\n if (status) status.onchange = null;\r\n };\r\n }, [warm]);\r\n\r\n return { state, request: warm };\r\n}\r\n","/**\r\n * How to un-block the microphone, per browser.\r\n *\r\n * **Steps in the widget rather than a link out**, which was the first instinct and is worse:\r\n *\r\n * - A support URL is somebody else's contract. Chrome's article checks out\r\n * (\"Utilizar la cámara y el micrófono en Chrome\"), but Mozilla's site answers every request —\r\n * including a deliberately fake slug — with a bot-challenge page, so no Firefox URL can be\r\n * verified, and every Edge slug tried returned 404. Shipping a link that might 404 is a dead end\r\n * inside a dead end.\r\n * - It is three clicks away in the browser the user is already looking at. Sending them to a\r\n * support site to read the same three clicks is a context switch that solves nothing.\r\n * - Our copy is Spanish-only by design (SPEC §2.4); a support page follows its own locale rules.\r\n *\r\n * The verified Chrome article is still offered where it applies, as a last resort rather than the\r\n * first answer.\r\n */\r\n\r\nexport interface UnblockGuide {\r\n readonly steps: readonly string[];\r\n /** Only present where the URL has been verified to exist and to be about microphone permission. */\r\n readonly url?: string;\r\n}\r\n\r\ntype BrowserId = 'firefox' | 'edge' | 'chromium' | 'safari' | 'unknown';\r\n\r\n/**\r\n * Which browser is this, for help purposes only.\r\n *\r\n * UA sniffing, knowingly: it decides which three sentences to show, so being wrong costs a slightly\r\n * off instruction, not a broken feature. Order matters — Edge and most Chromium forks put \"Chrome\"\r\n * in their UA, and Chrome puts \"Safari\" in its.\r\n */\r\nfunction detectBrowser(ua: string): BrowserId {\r\n if (/firefox|fxios/i.test(ua)) return 'firefox';\r\n if (/edg\\//i.test(ua)) return 'edge';\r\n if (/chrome|chromium|crios/i.test(ua)) return 'chromium';\r\n if (/safari/i.test(ua)) return 'safari';\r\n return 'unknown';\r\n}\r\n\r\n/** Verified: returns \"Utilizar la cámara y el micrófono en Chrome\" in Spanish. */\r\nconst CHROME_HELP = 'https://support.google.com/chrome/answer/2693767?hl=es';\r\n\r\nconst GUIDES: Record<BrowserId, UnblockGuide> = {\r\n chromium: {\r\n steps: [\r\n 'Haz clic en el icono 🔒 a la izquierda de la dirección web.',\r\n 'Busca «Micrófono» y cámbialo a «Permitir».',\r\n 'Recarga la página.',\r\n ],\r\n url: CHROME_HELP,\r\n },\r\n // Edge is Chromium: same padlock, same panel. The article is Chrome's, so it is offered but not\r\n // led with — the steps above match what an Edge user actually sees.\r\n edge: {\r\n steps: [\r\n 'Haz clic en el icono 🔒 a la izquierda de la dirección web.',\r\n 'Busca «Micrófono» y cámbialo a «Permitir».',\r\n 'Recarga la página.',\r\n ],\r\n },\r\n firefox: {\r\n steps: [\r\n 'Haz clic en el icono de micrófono tachado en la barra de direcciones.',\r\n 'Pulsa la «✕» junto a «Bloqueado» para quitar el bloqueo.',\r\n 'Recarga la página.',\r\n ],\r\n },\r\n safari: {\r\n steps: [\r\n 'Abre «Safari» → «Ajustes para este sitio web».',\r\n 'En «Micrófono», elige «Permitir».',\r\n 'Recarga la página.',\r\n ],\r\n },\r\n unknown: {\r\n steps: [\r\n 'Abre los permisos de este sitio en tu navegador.',\r\n 'Cambia el micrófono a «Permitir».',\r\n 'Recarga la página.',\r\n ],\r\n },\r\n};\r\n\r\n/** The guide for the current browser. SSR-safe: no `navigator` at module scope (SPEC §10.2). */\r\nexport function unblockGuide(): UnblockGuide {\r\n const ua = typeof navigator === 'undefined' ? '' : navigator.userAgent;\r\n return GUIDES[detectBrowser(ua)];\r\n}\r\n\r\n/** @internal — tests drive the detection without stubbing a global. */\r\nexport function __guideFor(ua: string): UnblockGuide {\r\n return GUIDES[detectBrowser(ua)];\r\n}\r\n","import type { ReactNode } from 'react';\r\nimport { Mic, MicOff, HelpCircle, ExternalLink } from 'lucide-react';\r\nimport { useMicPermission, type MicState } from './useMicPermission.js';\r\nimport { unblockGuide } from './unblock-mic.js';\r\n\r\n/**\r\n * What the user sees while the mic is not available yet. Body content only — no shell — so the\r\n * widget can render it inside its own `.cv-body` instead of nesting a second `.cv-softphone`.\r\n */\r\nexport function MicPrompt({\r\n state,\r\n onRequest,\r\n}: Readonly<{ state: MicState; onRequest: () => void }>) {\r\n if (state === 'unsupported') {\r\n return (\r\n <div className=\"cv-gate\" data-state={state} data-tone=\"danger\">\r\n <span className=\"cv-gate-mark\">\r\n <MicOff size={22} />\r\n </span>\r\n <h3 className=\"cv-gate-title\">Llamadas no disponibles</h3>\r\n <p>Este navegador no admite llamadas. Prueba con Chrome, Edge o Firefox.</p>\r\n </div>\r\n );\r\n }\r\n\r\n if (state === 'denied') {\r\n const guide = unblockGuide();\r\n return (\r\n <div className=\"cv-gate\" data-state={state} data-tone=\"danger\">\r\n <span className=\"cv-gate-mark\">\r\n <MicOff size={22} />\r\n </span>\r\n <h3 className=\"cv-gate-title\">Micrófono bloqueado</h3>\r\n <p>Permítelo en tu navegador para poder llamar.</p>\r\n\r\n {/*\r\n A dead end needs a way out, and the way out is three clicks away in the browser they are\r\n already looking at — so the steps are HERE, not behind a link to a support site.\r\n `<details>` is the disclosure: native, keyboard-accessible, no JS, collapsed by default so\r\n the panel is not a wall of text for the people who already know.\r\n */}\r\n <details className=\"cv-help\">\r\n <summary>\r\n <HelpCircle size={13} aria-hidden />\r\n Cómo permitirlo\r\n </summary>\r\n <ol>\r\n {guide.steps.map((step) => (\r\n <li key={step}>{step}</li>\r\n ))}\r\n </ol>\r\n {guide.url ? (\r\n <a href={guide.url} target=\"_blank\" rel=\"noreferrer noopener\">\r\n Guía del navegador\r\n <ExternalLink size={11} aria-hidden />\r\n </a>\r\n ) : null}\r\n </details>\r\n </div>\r\n );\r\n }\r\n\r\n /*\r\n * `warming` — `getUserMedia()` is running, and the browser may be showing its OWN permission\r\n * prompt on top of us.\r\n *\r\n * We cannot know which: the API returns one promise and signals nothing either way. **Timing\r\n * separates them.** A silent grant resolves in tens of milliseconds; a prompt waits on a human.\r\n * Since the CSS holds this state back 450 ms, the rule falls out of the delay: if this is visible\r\n * at all, somebody is being asked something.\r\n *\r\n * So it points at the browser's prompt instead of narrating ours. \"Preparando el micrófono…\" was\r\n * true and useless — it described our internals while the actual question sat unanswered in the\r\n * corner of the screen.\r\n */\r\n if (state === 'warming') {\r\n return (\r\n <div className=\"cv-gate\" data-state={state}>\r\n <span className=\"cv-gate-mark\">\r\n <Mic size={22} />\r\n </span>\r\n <h3 className=\"cv-gate-title\">Permite el micrófono</h3>\r\n <p>Acepta el aviso que muestra el navegador para continuar.</p>\r\n </div>\r\n );\r\n }\r\n\r\n /*\r\n * `checking` — querying `permissions.query()`. No browser UI can appear during this, so there is\r\n * nothing to point at and nothing for the user to do. Also delayed 450 ms, and in practice never\r\n * painted at all.\r\n */\r\n if (state === 'checking') {\r\n return (\r\n <div className=\"cv-gate\" data-state={state}>\r\n <span className=\"cv-gate-mark\">\r\n <Mic size={22} />\r\n </span>\r\n <p>Preparando el micrófono…</p>\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <div className=\"cv-gate\" data-state={state}>\r\n <span className=\"cv-gate-mark\">\r\n <Mic size={22} />\r\n </span>\r\n <h3 className=\"cv-gate-title\">Permite el micrófono</h3>\r\n {/* Says WHY before asking. A permission request with no reason is the one people decline. */}\r\n <p>Lo necesitamos para que puedas hablar durante las llamadas.</p>\r\n <button className=\"cv-btn cv-btn--accent\" onClick={onRequest}>\r\n Permitir micrófono\r\n </button>\r\n </div>\r\n );\r\n}\r\n\r\n/**\r\n * Gate arbitrary children on microphone permission.\r\n *\r\n * **`SoftphoneWidget` now gates itself** (`requireMic`, on by default), so most integrations need\r\n * nothing here — a softphone without a microphone is not a softphone, and making the gate opt-in\r\n * meant every integrator had to know to opt in or ship something that fails mid-call.\r\n *\r\n * This stays exported for hosts that want the prompt somewhere else: their own modal, a page-level\r\n * onboarding step, or wrapping something larger than the widget.\r\n */\r\nexport function MicPermissionGate({ children }: Readonly<{ children: ReactNode }>) {\r\n const { state, request } = useMicPermission();\r\n if (state === 'ready') return <>{children}</>;\r\n return (\r\n <div className=\"cv-softphone\">\r\n <MicPrompt state={state} onRequest={() => void request()} />\r\n </div>\r\n );\r\n}\r\n","import { TriangleAlert } from 'lucide-react';\r\nimport { ERROR_TEXT } from '../lib/error-text.js';\r\nimport type { FatalSoftphoneError } from '../../core/errors.js';\r\n\r\n/**\r\n * Why the phone cannot be used, and the one thing worth trying.\r\n *\r\n * **Deliberately the same `.cv-gate` as `MicPrompt`**, not a banner. The widget already had this\r\n * affordance for \"something is wrong, here is why, here is what to do\", and it earns its shape: it\r\n * REPLACES the body rather than sitting above it. A fatal error means calling is impossible, so\r\n * leaving a dialpad visible under a warning invites the user to try anyway and learn nothing.\r\n *\r\n * No dismissal — no close button, no timer. The condition is still true; hiding the explanation would\r\n * leave a phone that silently refuses. It goes when the softphone reaches `online`, which is the only\r\n * evidence available that whatever was wrong no longer is.\r\n */\r\nexport function ErrorGate({\r\n error,\r\n onRetry,\r\n}: Readonly<{ error: FatalSoftphoneError; onRetry: () => void }>) {\r\n const text = ERROR_TEXT[error.code];\r\n\r\n return (\r\n /*\r\n `part` on all four, because this is the most intrusive thing the SDK draws — it replaces the\r\n whole dialpad — and inside `<coventia-softphone>` a shadow root makes it otherwise unreachable\r\n from the host's CSS. Custom properties alone only let a host recolour what we chose to draw.\r\n\r\n `data-code` is NOT a substitute: it is inside the shadow root, so `[data-code=…]` selectors\r\n cannot cross the boundary either. It stays for the light-DOM `/ui` path and for debugging.\r\n */\r\n <div className=\"cv-gate\" data-tone=\"danger\" data-code={error.code} part=\"error-gate\">\r\n <span className=\"cv-gate-mark\">\r\n <TriangleAlert size={22} />\r\n </span>\r\n <h3 className=\"cv-gate-title\" part=\"error-title\">\r\n {text.title}\r\n </h3>\r\n {/* Every fatal code has a body — `error-text.test.ts` fails the build otherwise. */}\r\n {text.body === undefined ? null : <p part=\"error-body\">{text.body}</p>}\r\n {/*\r\n `start()` re-provisions, and every fatal code we raise is recoverable by re-provisioning:\r\n a stale key is re-fetched, a refused token is re-minted, a dead socket is rebuilt. If it\r\n fails again the gate simply stays — which is the honest outcome, not a silent one.\r\n */}\r\n <button className=\"cv-btn cv-btn--accent\" onClick={onRetry} part=\"error-retry\">\r\n Reintentar\r\n </button>\r\n </div>\r\n );\r\n}\r\n","import { MonitorSmartphone } from 'lucide-react';\r\n\r\n/**\r\n * Shown instead of the dialpad when ANOTHER open tab holds the extension\r\n * (`multi-tab-leader-election.md`).\r\n *\r\n * **Not `ErrorGate` re-skinned.** `ErrorGate`'s whole shape is welded to `FatalSoftphoneError` — it\r\n * reads `ERROR_TEXT[error.code]` and always offers a \"Reintentar\" action wired to `stop()` + `start()`.\r\n * Neither fits: nothing is broken here, there is nothing to retry, and inventing a fake catalogue code\r\n * for a condition that was never a failure would be worse than a second small component. What IS\r\n * reused is `.cv-gate` itself — the same primitive `MicPrompt`'s non-error states already render with\r\n * no `data-tone=\"danger\"`.\r\n *\r\n * No dismissal, same reasoning as `ErrorGate`: it clears itself the instant the other tab closes,\r\n * reloads, or crashes (Web Locks' own guarantee — no polling, no user action).\r\n */\r\nexport function LeaderGate() {\r\n return (\r\n <div className=\"cv-gate\" part=\"leader-gate\">\r\n <span className=\"cv-gate-mark\">\r\n <MonitorSmartphone size={22} />\r\n </span>\r\n <h3 className=\"cv-gate-title\" part=\"leader-title\">\r\n Teléfono activo en otra pestaña\r\n </h3>\r\n <p part=\"leader-body\">Solo una pestaña puede usar el teléfono a la vez. Cierra la otra para activar esta.</p>\r\n </div>\r\n );\r\n}\r\n","import { useCallback, useEffect, useRef, useState } from 'react';\r\nimport { useSoftphone } from '../../react/index.js';\r\nimport { SoftphoneEvent } from '../../core/events.js';\r\nimport { ERROR_TEXT } from './error-text.js';\r\nimport type { SoftphoneErrorCode } from '../../core/errors.js';\r\n\r\n/** How long an unattended outcome stays before it becomes furniture. */\r\nconst BACKSTOP_MS = 6_000;\r\n\r\n/**\r\n * The outcome of the last attempt — \"Sin respuesta\", \"Llamada rechazada\".\r\n *\r\n * **Non-fatal errors only.** A fatal one is a condition and belongs in the gate; this is an *event*,\r\n * a fact about a call that already ended, and it must not persist as though the phone were broken.\r\n *\r\n * **Cleared by the user's next intent**, which is what the previous CRM did — it called\r\n * `setError(null)` on dial, answer, reject, and on an inbound INVITE. The reasoning holds: the moment\r\n * you dial again, what happened to the last call stops being relevant. A timer alone would clear at\r\n * an arbitrary moment unrelated to what the user is doing; it is only the backstop, for when intent\r\n * never comes because the user read it and walked away.\r\n *\r\n * **Lives above the dialpad.** The outcome is raised as the call ENDS — the exact moment the widget\r\n * swaps the call screen back for the dialpad. Held inside `Dialpad` it would be born into a component\r\n * that is remounting, and lost.\r\n */\r\nexport function useCallOutcome(): {\r\n readonly outcome: { readonly code: SoftphoneErrorCode; readonly text: string } | null;\r\n readonly clear: () => void;\r\n} {\r\n const softphone = useSoftphone();\r\n const [code, setCode] = useState<SoftphoneErrorCode | null>(null);\r\n const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\r\n\r\n const clear = useCallback(() => {\r\n clearTimeout(timer.current);\r\n setCode(null);\r\n }, []);\r\n\r\n useEffect(() => {\r\n const off = softphone.on(SoftphoneEvent.Error, (error) => {\r\n // Fatal errors are the gate's business. Showing them here too would say the same thing twice,\r\n // in the smaller and more dismissible of the two places.\r\n if (error.fatal) return;\r\n clearTimeout(timer.current);\r\n setCode(error.code);\r\n timer.current = setTimeout(() => setCode(null), BACKSTOP_MS);\r\n });\r\n return () => {\r\n off();\r\n clearTimeout(timer.current);\r\n };\r\n }, [softphone]);\r\n\r\n // An inbound call is intent too: the user is being asked something new, and last call's outcome is\r\n // no longer what they need to read.\r\n useEffect(() => softphone.on(SoftphoneEvent.IncomingCall, () => clear()), [softphone, clear]);\r\n\r\n return {\r\n outcome: code === null ? null : { code, text: ERROR_TEXT[code].title },\r\n clear,\r\n };\r\n}\r\n","import { useEffect, useRef } from 'react';\r\nimport { useSoftphone } from '../../react/index.js';\r\nimport { CallEvent, SoftphoneEvent } from '../../core/events.js';\r\nimport {\r\n createRemoteAudio,\r\n playCallEndedTone,\r\n playRingback,\r\n playRingtone,\r\n primeAudio,\r\n type RemoteAudio,\r\n type Tone,\r\n} from './audio.js';\r\nimport { ringtoneStore } from './ringtone-store.js';\r\nimport type { Call } from '../../core/call.js';\r\n\r\n/**\r\n * Wires the softphone's audio to call state: the remote party, the inbound ring, the outbound\r\n * ringback, and the end-of-call cue. Mounted by `SoftphoneWidget`, so a host gets all of it without\r\n * knowing it exists.\r\n *\r\n * **The remote stream is attached only on `active`, never before**, and that one rule does two jobs:\r\n *\r\n * 1. It IS the call audio. Nothing else attaches the stream, so without this a connected call is\r\n * silent in both directions.\r\n * 2. It prevents a doubled ringback. Firefox plays the carrier's early media; routing the remote\r\n * stream during outbound ringing would layer that on top of our local tone. The legacy code\r\n * carried a `suppressRemoteAudioRef` flag cleared on `accepted` — attaching on `active` is the\r\n * same rule with nothing to forget to clear.\r\n */\r\nexport function useCallAudio(enabled: boolean): void {\r\n const softphone = useSoftphone();\r\n const remote = useRef<RemoteAudio | null>(null);\r\n const tone = useRef<Tone | null>(null);\r\n\r\n useEffect(() => {\r\n if (!enabled || typeof document === 'undefined') return;\r\n\r\n /*\r\n * Unlock audio on the first interaction anywhere on the page, whatever it is — a tab, a dialpad\r\n * key, the mic-permission button.\r\n *\r\n * An inbound INVITE is not a user gesture, so a context first built when the phone rings is\r\n * created under the autoplay policy and Firefox warns about it three times. Building it during\r\n * an ordinary click costs nothing and means ringing never touches the policy at all.\r\n *\r\n * `capture` so it fires even if something calls `stopPropagation`, and it listens on the document\r\n * rather than the widget because the events that escape our shadow root are the composed ones.\r\n */\r\n const prime = (): void => primeAudio();\r\n const gestures = ['pointerdown', 'keydown'] as const;\r\n for (const type of gestures) {\r\n document.addEventListener(type, prime, { once: true, capture: true });\r\n }\r\n\r\n remote.current = createRemoteAudio();\r\n // Apply whatever output is already selected (a Settings change made before this call, or before\r\n // the widget even mounted) — `null` is a real, explicit value here (\"system default\"), not\r\n // \"nothing to do\", so this always runs rather than only when a device is chosen.\r\n void remote.current.setOutputDevice(softphone.audio.currentOutputId);\r\n // …and keep it applied if the selection changes WHILE this element is live — output routing is\r\n // meant to be instant, live call or not (see `AudioDevices.setOutput`'s own comment).\r\n const offDeviceChange = softphone.on(SoftphoneEvent.DeviceChange, () => {\r\n void remote.current?.setOutputDevice(softphone.audio.currentOutputId);\r\n });\r\n\r\n /*\r\n * The chosen ringtone (custom-ringtone.md §4.4). Fetched — settings, then the file — only by the LEADER\r\n * tab, the only one that can ring, and only on these triggers: becoming the leader, and after each call\r\n * ends (how an admin's new org default reaches a running softphone). Never when a call arrives: the\r\n * ring reads only what is already decoded.\r\n */\r\n const ringtones = ringtoneStore(softphone);\r\n ringtones?.wantAudio(true);\r\n const refreshRingtone = (): void => {\r\n if (softphone.isLeader) void ringtones?.refresh();\r\n };\r\n refreshRingtone();\r\n const offLeader = softphone.on(SoftphoneEvent.LeaderChanged, ({ isLeader }) => {\r\n if (isLeader) refreshRingtone();\r\n });\r\n\r\n const stopTone = (): void => {\r\n tone.current?.stop();\r\n tone.current = null;\r\n };\r\n\r\n /** One tone at a time: switching states must never leave the previous one running. */\r\n const setTone = (next: 'ringtone' | 'ringback' | null): void => {\r\n stopTone();\r\n if (next === 'ringtone') {\r\n // Decided once, here, and held for the whole ring: the chosen file if it is decoded right now,\r\n // otherwise the built-in tone — even if the file finishes loading a second later.\r\n const audio = softphone.audio;\r\n tone.current = playRingtone({\r\n buffer: ringtones?.readyBuffer() ?? null,\r\n loop: ringtones?.readyLoop() ?? null,\r\n sinkId: audio.canSelectRingtoneOutput ? audio.currentRingtoneOutputId : null,\r\n });\r\n } else if (next === 'ringback') tone.current = playRingback();\r\n };\r\n\r\n const perCall: Array<() => void> = [];\r\n // An inbound call fires BOTH `ActiveCallChanged` and `IncomingCall` for the same `Call`\r\n // (`softphone-impl.ts#adopt` emits the former, `#onIncoming` the latter, right after) — both\r\n // wired to `follow` below. That double subscription was harmless while every handler here was\r\n // idempotent (stop a tone that is already stopped, detach an already-detached stream); it stops\r\n // being harmless the moment a handler has a real one-shot side effect, like the end-of-call tone.\r\n const followedCalls = new Set<Call>();\r\n\r\n const follow = (call: Call): void => {\r\n if (followedCalls.has(call)) return;\r\n followedCalls.add(call);\r\n\r\n // Whether this call ever actually connected — the end-of-call cue is for a conversation that\r\n // was really happening, not for a ring that got cancelled or a dial that never picked up.\r\n // Tracked per-call rather than read off `call.state` at `Ended` time because by then the state\r\n // machine has already moved to 'ended' and the history is gone.\r\n let wasConnected = call.state === 'active' || call.state === 'held';\r\n\r\n const apply = (state: string): void => {\r\n if (state === 'active' || state === 'held') wasConnected = true;\r\n if (state === 'ringing') setTone('ringtone'); // inbound: they are calling us\r\n else if (state === 'dialing' || state === 'early') setTone('ringback'); // outbound\r\n else setTone(null); // answering / active / held / ended — silence\r\n };\r\n apply(call.state);\r\n\r\n perCall.push(\r\n call.on(CallEvent.StateChanged, ({ state }) => apply(state)),\r\n // Attach on `active` only — see the note above. `remoteStream` is usually already set by\r\n // then, since media arrives before the 200 OK.\r\n call.on(CallEvent.Accepted, () => {\r\n if (call.remoteStream) remote.current?.attach(call.remoteStream);\r\n }),\r\n // …but if it arrives late, take it then — as long as we are past ringing.\r\n call.on(CallEvent.RemoteStream, ({ stream }) => {\r\n if (call.state === 'active' || call.state === 'held') remote.current?.attach(stream);\r\n }),\r\n call.on(CallEvent.Ended, ({ reason }) => {\r\n followedCalls.delete(call);\r\n stopTone();\r\n remote.current?.detach();\r\n // 'local' and 'remote' are BOTH ordinary hangups — either side ending a real conversation\r\n // is the same cue. Never for 'busy' / 'rejected' / 'no-answer' / 'failed': the call never\r\n // connected, and a \"goodbye\" tone on a call nobody answered would be actively misleading.\r\n // Not for 'transferred' either — that call keeps going, just without this leg.\r\n if (wasConnected && (reason === 'local' || reason === 'remote')) playCallEndedTone();\r\n // Off the critical path: the phone is idle now, and the next ring needs current settings.\r\n refreshRingtone();\r\n }),\r\n );\r\n };\r\n\r\n const offIncoming = softphone.on(SoftphoneEvent.IncomingCall, follow);\r\n const offActive = softphone.on(SoftphoneEvent.ActiveCallChanged, ({ call }) => {\r\n if (call) follow(call);\r\n else {\r\n stopTone();\r\n remote.current?.detach();\r\n }\r\n });\r\n if (softphone.activeCall) follow(softphone.activeCall);\r\n\r\n return () => {\r\n for (const type of gestures) document.removeEventListener(type, prime, { capture: true });\r\n offIncoming();\r\n offActive();\r\n offDeviceChange();\r\n offLeader();\r\n ringtones?.wantAudio(false);\r\n for (const off of perCall) off();\r\n stopTone();\r\n remote.current?.destroy();\r\n remote.current = null;\r\n };\r\n }, [softphone, enabled]);\r\n}\r\n","import { Phone, PhoneMissed, X } from 'lucide-react';\r\nimport { useSoftphone } from '../../react/index.js';\r\nimport { useTicker } from '../lib/useTicker.js';\r\nimport { elapsedSeconds, formatAge } from '../lib/format.js';\r\nimport type { TransferNotice } from './useTransferNotices.js';\r\n\r\n/**\r\n * \"El traspaso a 101 no se conectó\" — spec §5.5. Persistent, dismissable, no timer.\r\n *\r\n * **Purely presentational — takes `notices`/`dismiss` as props rather than calling\r\n * `useTransferNotices()` itself.** The SUBSCRIPTION that hook owns has to stay alive for the whole time\r\n * the widget is mounted, not just while this component happens to be on screen: an outcome for an\r\n * earlier transfer can arrive while the agent is on a brand new, unrelated call, and if nobody were\r\n * listening at that moment it would be gone for good (the same class of gap `useTransferNotices`'s own\r\n * comment already accepts for a fully unmounted widget — this is what keeps it from also happening\r\n * every time a call is merely in progress). So `SoftphoneWidget` calls the hook once, unconditionally,\r\n * the same placement `useCallOutcome` already uses and for the same reason; only the RENDERING of this\r\n * component is conditional on being in a state where the widget isn't using the screen for something\r\n * higher-priority (a live call, the mic gate, a fatal error, a follower tab).\r\n *\r\n * **Always rendered when mounted, `role=\"status\"`, even with nothing to show** — the same reason\r\n * `Dialpad`'s own outcome line always exists: an aria-live region inserted at the same moment as its\r\n * first content is not reliably announced. Left visually empty (no padding of its own) when there is\r\n * nothing waiting, so this costs no layout space either.\r\n */\r\nexport function TransferNotices({\r\n notices,\r\n dismiss,\r\n}: Readonly<{ notices: readonly TransferNotice[]; dismiss: (id: number) => void }>) {\r\n const softphone = useSoftphone();\r\n // Only while there's something to age, and coarsely: `formatAge` never changes output more often\r\n // than once a minute, so a 1 s tick would just be wasted re-renders on a possibly long-lived notice.\r\n const now = useTicker(notices.length > 0, 15_000);\r\n\r\n const callBack = (notice: TransferNotice): void => {\r\n dismiss(notice.id); // clears itself on press (spec §5.5) — not conditional on the call succeeding\r\n if (notice.caller) void softphone.call(notice.caller).catch(() => {});\r\n };\r\n\r\n return (\r\n <div\r\n className=\"cv-transfer-notices\"\r\n role=\"status\"\r\n part=\"transfer-notices\"\r\n // Explicit, rather than leaning on a `:empty` CSS selector's assumptions about how React\r\n // renders `null`/an empty array — this is what CSS actually keys off to stay visually\r\n // zero-footprint while there is nothing waiting.\r\n data-has-notices={notices.length > 0}\r\n >\r\n {notices.length > 1 ? (\r\n <p className=\"cv-transfer-notices-count\">{notices.length} traspasos sin conectar</p>\r\n ) : null}\r\n {notices.map((notice) => (\r\n <div key={notice.id} className=\"cv-transfer-notice\" part=\"transfer-notice\">\r\n <span className=\"cv-transfer-notice-mark\" aria-hidden>\r\n <PhoneMissed size={16} />\r\n </span>\r\n <div className=\"cv-transfer-notice-body\">\r\n {/* Title and dismiss share only THIS row — not the whole card, and not the callback\r\n button below. Squeezing icon + title + subtitle + a full \"Llamar de vuelta\" button\r\n into one flex row left the title as little as ~80px to wrap into at the real ~340px\r\n embed width, breaking nearly every word onto its own line. */}\r\n <div className=\"cv-transfer-notice-header\">\r\n <p className=\"cv-transfer-notice-title\">El traspaso a {notice.target} no se conectó</p>\r\n <button\r\n type=\"button\"\r\n className=\"cv-transfer-notice-dismiss\"\r\n onClick={() => dismiss(notice.id)}\r\n aria-label=\"Descartar aviso\"\r\n part=\"transfer-notice-dismiss\"\r\n >\r\n <X size={14} />\r\n </button>\r\n </div>\r\n {/* Absent, not \"número desconocido\" — spec §7's outside-number case and a genuinely\r\n unresolved caller both leave this null, and there is nothing actionable to say either\r\n way beyond the title above. */}\r\n {notice.caller ? (\r\n <p className=\"cv-transfer-notice-subtitle\">{notice.caller} se ha desconectado.</p>\r\n ) : null}\r\n <div className=\"cv-transfer-notice-footer\">\r\n <p className=\"cv-transfer-notice-age\">{formatAge(elapsedSeconds(notice.at, now))}</p>\r\n {/* Absent when the caller's number is unknown (plan T6's own acceptance) — nothing to dial. */}\r\n {notice.caller ? (\r\n <button\r\n type=\"button\"\r\n className=\"cv-btn cv-btn--accent cv-transfer-notice-callback\"\r\n onClick={() => callBack(notice)}\r\n part=\"transfer-notice-callback\"\r\n >\r\n <Phone size={14} aria-hidden />\r\n Llamar de vuelta\r\n </button>\r\n ) : null}\r\n </div>\r\n </div>\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n}\r\n","import { useCallback, useEffect, useRef, useState } from 'react';\r\nimport { useSoftphone } from '../../react/index.js';\r\nimport { SoftphoneEvent } from '../../core/events.js';\r\n\r\n/**\r\n * One transfer that didn't connect, waiting for the agent to see it. The `id` is local to this hook —\r\n * `TransferOutcomeEvent` carries no id of its own (the source's own `id`, on `TransferOutcomeEntry`, is\r\n * a polling-internal concern the watch never exposes) — so a simple incrementing counter is enough; it\r\n * only ever needs to be unique within one mounted widget.\r\n */\r\nexport interface TransferNotice {\r\n readonly id: number;\r\n readonly target: string;\r\n /** Null when the caller's number was never known — the notice still shows, with no call-back action. */\r\n readonly caller: string | null;\r\n readonly at: Date;\r\n}\r\n\r\n/**\r\n * Accumulates `SoftphoneEvent.TransferOutcome`'s `'not-connected'` outcomes into a dismissable list —\r\n * `docs/specs/transfer-outcome-relay.md` §5.5, plan T6.\r\n *\r\n * **Deliberately NOT `useCallOutcome`'s shape.** That hook holds one value, auto-clears after a\r\n * backstop timer, and clears on the next dial/incoming intent — right for \"what just happened on the\r\n * call you're looking at now.\" A transfer notice is about a DIFFERENT, now-absent customer, arrives\r\n * roughly a minute after the agent has already moved on, and must not vanish because something else\r\n * happened in between: no backstop timer (spec §5.5's UX research — a timed notice here is one the\r\n * agent never had a fair chance to read), no clearing on intent, and more than one can be true at once.\r\n *\r\n * **A real, accepted gap:** this only sees outcomes that arrive while a widget instance is mounted and\r\n * listening. The softphone itself (not the widget) owns the watch's lifecycle, so an outcome that\r\n * lands while no widget happens to be mounted is emitted to nobody and is gone — the same category of\r\n * gap the spec already accepts for a closed tab (§7), just one level narrower. Fixing it would mean the\r\n * softphone itself holding pending notices, which is a bigger change than this task's own scope.\r\n */\r\nexport function useTransferNotices(): {\r\n readonly notices: readonly TransferNotice[];\r\n readonly dismiss: (id: number) => void;\r\n} {\r\n const softphone = useSoftphone();\r\n const [notices, setNotices] = useState<readonly TransferNotice[]>([]);\r\n const nextId = useRef(0);\r\n\r\n const dismiss = useCallback((id: number) => {\r\n setNotices((prev) => prev.filter((n) => n.id !== id));\r\n }, []);\r\n\r\n useEffect(\r\n () =>\r\n softphone.on(SoftphoneEvent.TransferOutcome, (payload) => {\r\n // The event fires for BOTH outcomes (spec §4 D2) so a host can react to a success too; the\r\n // widget itself stays silent for one. An explicit equality check, not `!== 'connected'`: an\r\n // unrecognised future status should fail toward silence, not toward showing something.\r\n if (payload.status === 'not-connected') {\r\n const id = nextId.current++;\r\n setNotices((prev) => [...prev, { id, target: payload.target, caller: payload.caller, at: payload.at }]);\r\n }\r\n }),\r\n [softphone],\r\n );\r\n\r\n return { notices, dismiss };\r\n}\r\n","import { useState } from 'react';\r\nimport { Grid3x3, Users, Clock, Settings } from 'lucide-react';\r\nimport {\r\n useActiveCall,\r\n useIsLeader,\r\n useLastError,\r\n useSoftphone,\r\n useSoftphoneState,\r\n} from '../react/index.js';\r\nimport { Dialpad } from './views/Dialpad.js';\r\nimport { CallScreen } from './views/CallScreen.js';\r\nimport { ContactsTab } from './views/ContactsTab.js';\r\nimport { HistoryTab } from './views/HistoryTab.js';\r\nimport { SettingsTab } from './views/SettingsTab.js';\r\nimport { MicPrompt } from './permission/MicPermissionGate.js';\r\nimport { ErrorGate } from './permission/ErrorGate.js';\r\nimport { LeaderGate } from './permission/LeaderGate.js';\r\nimport { useCallOutcome } from './lib/useCallOutcome.js';\r\nimport { useMicPermission } from './permission/useMicPermission.js';\r\nimport { useCallAudio } from './audio/useCallAudio.js';\r\nimport { TransferNotices } from './notices/TransferNotices.js';\r\nimport { useTransferNotices } from './notices/useTransferNotices.js';\r\nimport type { SoftphoneWidgetProps } from './types.js';\r\n\r\ntype TabId = 'dialer' | 'contacts' | 'history' | 'settings';\r\n\r\n/**\r\n * The softphone widget (legacy ZadarmaWidget) — the drop-in call UI. Wrap it in a\r\n * `<SoftphoneProvider softphone={…}>` and that is all: it asks for the microphone ITSELF\r\n * (`requireMic`, on by default), so no integrator has to know that a phone needs one.\r\n *\r\n * When a call is live, the call screen takes the whole body and the tabs hide. Otherwise the tabbed\r\n * interface (Teclado / Contactos / Historial) shows. Contactos/Historial appear only when their data\r\n * source is provided — the widget stays useful as a bare dialer with no backend at all.\r\n */\r\nexport function SoftphoneWidget(props: SoftphoneWidgetProps) {\r\n const {\r\n contacts,\r\n history,\r\n contactAction,\r\n incomingCallAction,\r\n className,\r\n theme = 'system',\r\n requireMic = true,\r\n sounds = true,\r\n } = props;\r\n const softphone = useSoftphone();\r\n\r\n /*\r\n * The sources come from the SOFTPHONE, not from a prop.\r\n *\r\n * `createSoftphone({ coventia })` builds them once, because caller ID has to work when an INVITE\r\n * lands — which can be before any UI is mounted. Reading them back here means one instance and one\r\n * name cache, and a host never imports an adapter or repeats a config to wire the tabs.\r\n *\r\n * An explicit `contacts`/`history` prop still wins, for a host driving the UI from somewhere else.\r\n */\r\n const fallback = softphone.sources;\r\n const contactsSource = contacts ?? fallback?.contacts;\r\n const historySource = history ?? fallback?.history;\r\n const [tab, setTab] = useState<TabId>('dialer');\r\n const call = useActiveCall();\r\n const isLeader = useIsLeader();\r\n const softphoneState = useSoftphoneState();\r\n // `isLeader` alone cannot tell \"never started\" from \"started, currently a follower\" — both are\r\n // `isLeader === false`. `state === 'starting'` is the disambiguator: it now covers the whole\r\n // in-progress window, including waiting behind another tab (SPEC — `softphone-impl.ts#start()`,\r\n // `multi-tab-leader-election.md` §3.4). A phone that was simply never `start()`-ed must fall\r\n // through to the mic gate / dialer exactly as before this feature existed.\r\n const isFollower = !isLeader && softphoneState === 'starting';\r\n // Always called — hooks cannot be conditional — but ignored when the host opted out.\r\n const mic = useMicPermission();\r\n // The remote party, the ring, the ringback. Without it a connected call is silent.\r\n useCallAudio(sounds);\r\n const blocked = requireMic && mic.state !== 'ready';\r\n const fatal = useLastError();\r\n // Shared by the tab bar (below) and `TransferNotices`: both are lower-priority than whatever else\r\n // the widget might be showing, and both simply don't render — never hidden, never queued behind —\r\n // while a call, the mic gate, a fatal error, or another tab's leadership owns the screen instead.\r\n const screenIsFree = !call && !blocked && !fatal && !isFollower;\r\n // Held HERE, not in the dialpad: the outcome is raised as the call ends, which is the same moment\r\n // the dialpad remounts — it would be born into a remounting component and lost.\r\n const { outcome, clear: clearOutcome } = useCallOutcome();\r\n // Held HERE too, and for a stronger version of the same reason: an outcome for an EARLIER transfer\r\n // can arrive while the agent is on a brand new, unrelated call — `TransferNotices` below is only\r\n // ever RENDERED once the screen is free, but the SUBSCRIPTION must stay alive the whole time the\r\n // widget is mounted, or that outcome reaches nobody (`useTransferNotices`'s own comment).\r\n const { notices: transferNotices, dismiss: dismissTransferNotice } = useTransferNotices();\r\n\r\n /*\r\n * `stop()` then `start()`, not `start()` alone — `start()` early-returns once the softphone has\r\n * been started, so on its own it would be a button that visibly does nothing.\r\n *\r\n * The round trip is also what makes recovery observable: it tears the signal channel down and\r\n * builds it again with fresh credentials, producing a real `offline → online` transition, which is\r\n * what clears `lastError` and takes the gate away. If it fails the same way, the error is\r\n * re-emitted and the gate returns — which is the honest outcome.\r\n */\r\n const retry = () => {\r\n void (async () => {\r\n try {\r\n await softphone.stop();\r\n await softphone.start();\r\n } catch {\r\n // Already reported through the error channel; the gate simply stays.\r\n }\r\n })();\r\n };\r\n\r\n const tabs = [\r\n { id: 'dialer' as const, icon: Grid3x3, label: 'Teclado', show: true },\r\n { id: 'contacts' as const, icon: Users, label: 'Contactos', show: !!contactsSource },\r\n { id: 'history' as const, icon: Clock, label: 'Historial', show: !!historySource },\r\n // Unlike Contactos/Historial, needs no host-supplied source — a microphone and a speaker are not\r\n // optional parts of a phone, so this is never conditionally hidden.\r\n { id: 'settings' as const, icon: Settings, label: 'Ajustes', show: true },\r\n ].filter((t) => t.show);\r\n\r\n return (\r\n <div\r\n className={className ? `cv-softphone ${className}` : 'cv-softphone'}\r\n // 'system' omits the attribute entirely, letting the prefers-color-scheme media query decide.\r\n {...(theme === 'system' ? {} : { 'data-cv-theme': theme })}\r\n >\r\n {/*\r\n A sibling of `.cv-body`, not inside it: a persistent notice must never scroll away with a long\r\n Contactos/Historial list, and must stay put across every tab. It OVERLAYS `.cv-body` (CSS —\r\n `position: absolute`) rather than pushing it down, so the widget's overall height never changes\r\n just because a notice appeared or was dismissed. `screenIsFree` gates it the same way it gates\r\n the tab bar below — it simply doesn't render, rather than queuing, while a call, the mic gate, a\r\n fatal error or another tab's leadership needs the screen instead.\r\n */}\r\n {screenIsFree ? (\r\n <TransferNotices notices={transferNotices} dismiss={dismissTransferNotice} />\r\n ) : null}\r\n <div className=\"cv-body\">\r\n {/*\r\n Order matters. `isFollower` comes FIRST, ahead even of the mic gate: another open tab\r\n holding this extension is a structural reason this tab cannot call, and asking for\r\n microphone permission somewhere that can never place or receive a call would be pure\r\n friction (`multi-tab-leader-election.md`). It clears on its own — no user action here helps\r\n it along. (A phone that was simply never `start()`-ed is NOT a follower — `isFollower`\r\n requires `state === 'starting'` too — so it falls through to the checks below, unchanged.)\r\n\r\n The mic gate comes next because it IS the precondition once leadership is not in question: no\r\n microphone means no call regardless of anything else, and it is the one thing here the user\r\n can complete right now. A fatal error outlives it — `lastError` persists — so nothing is lost\r\n by showing the actionable thing first.\r\n\r\n The call screen outranks the error gate, which is how \"suppress during a call\" is enforced:\r\n a live call is the highest-value state the widget has and nothing may cover it.\r\n */}\r\n {isFollower ? (\r\n <LeaderGate />\r\n ) : blocked ? (\r\n <MicPrompt state={mic.state} onRequest={() => void mic.request()} />\r\n ) : call ? (\r\n <CallScreen call={call} keyTones={sounds} {...(incomingCallAction ? { incomingCallAction } : {})} />\r\n ) : fatal ? (\r\n <ErrorGate error={fatal} onRetry={retry} />\r\n ) : tab === 'contacts' && contactsSource ? (\r\n <ContactsTab source={contactsSource} {...(contactAction ? { contactAction } : {})} />\r\n ) : tab === 'history' && historySource ? (\r\n <HistoryTab source={historySource} />\r\n ) : tab === 'settings' ? (\r\n <SettingsTab />\r\n ) : (\r\n <Dialpad outcome={outcome} onIntent={clearOutcome} keyTones={sounds} />\r\n )}\r\n </div>\r\n\r\n {/* No tabs while the mic is pending: Contactos and Historial would work, but offering them\r\n implies the phone is usable, and it is not until the mic is granted. Same reasoning extends\r\n to `isFollower` — a follower tab has nothing behind any of these tabs to be usable at all. */}\r\n {screenIsFree ? (\r\n <div className=\"cv-tabs\" role=\"tablist\">\r\n {tabs.map(({ id, icon: Icon, label }) => (\r\n <button\r\n key={id}\r\n role=\"tab\"\r\n aria-selected={tab === id}\r\n className=\"cv-tab\"\r\n onClick={() => setTab(id)}\r\n >\r\n <Icon size={20} />\r\n <span>{label}</span>\r\n </button>\r\n ))}\r\n </div>\r\n ) : null}\r\n </div>\r\n );\r\n}\r\n"]}
|