@opencx/widget-react 5.2.0 → 5.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.
Files changed (29) hide show
  1. package/dist/{Chart.impl-BY-Rn08r.cjs → Chart.impl-BLTobbyF.cjs} +2 -2
  2. package/dist/{Chart.impl-BY-Rn08r.cjs.map → Chart.impl-BLTobbyF.cjs.map} +1 -1
  3. package/dist/{Chart.impl-Bcv3wlQu.js → Chart.impl-C6jESAyh.js} +2 -2
  4. package/dist/{Chart.impl-Bcv3wlQu.js.map → Chart.impl-C6jESAyh.js.map} +1 -1
  5. package/dist/{index-CqYheBap.js → index-DBNYdRSl.js} +4938 -4807
  6. package/dist/index-DBNYdRSl.js.map +1 -0
  7. package/dist/index-DFDJp9mO.cjs +390 -0
  8. package/dist/index-DFDJp9mO.cjs.map +1 -0
  9. package/dist/index.cjs +1 -1
  10. package/dist/index.js +1 -1
  11. package/dist/package.json.d.ts +1 -1
  12. package/dist/src/WidgetPopoverTrigger.d.ts.map +1 -1
  13. package/dist/src/companion/RestingPill.d.ts +4 -1
  14. package/dist/src/companion/RestingPill.d.ts.map +1 -1
  15. package/dist/src/companion/WidgetCompanion.d.ts.map +1 -1
  16. package/dist/src/components/UnreadBadge.d.ts +42 -0
  17. package/dist/src/components/UnreadBadge.d.ts.map +1 -0
  18. package/dist/src/components/UnreadViewing.d.ts +8 -0
  19. package/dist/src/components/UnreadViewing.d.ts.map +1 -0
  20. package/dist/src/index.d.ts.map +1 -1
  21. package/dist/src/screens/chat/ChatInput.d.ts.map +1 -1
  22. package/dist/src/screens/chat/usePageMarkComposer.d.ts.map +1 -1
  23. package/dist/src/screens/sessions/index.d.ts.map +1 -1
  24. package/dist/src/utils/render-custom-trigger.d.ts +1 -1
  25. package/dist/src/utils/render-custom-trigger.d.ts.map +1 -1
  26. package/package.json +3 -3
  27. package/dist/index-9Z5RGuSA.cjs +0 -375
  28. package/dist/index-9Z5RGuSA.cjs.map +0 -1
  29. package/dist/index-CqYheBap.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-9Z5RGuSA.cjs","sources":["../../../node_modules/.pnpm/@json-render+core@0.19.0_zod@4.5.4/node_modules/@json-render/core/dist/chunk-AFLK3Q4T.mjs","../../../node_modules/.pnpm/@json-render+core@0.19.0_zod@4.5.4/node_modules/@json-render/core/dist/index.mjs","../../../node_modules/.pnpm/@json-render+react@0.19.0_react@19.2.8_zod@4.5.4/node_modules/@json-render/react/dist/chunk-WYDS23XB.mjs","../../../node_modules/.pnpm/@json-render+react@0.19.0_react@19.2.8_zod@4.5.4/node_modules/@json-render/react/dist/index.mjs","../src/hooks/useTranslation.ts","../src/json-render/host.tsx","../src/json-render/JsonRenderErrorBoundary.tsx","../src/json-render/normalize-spec.ts","../src/components/lib/utils/cn.ts","../src/json-render/Chart.tsx","../src/json-render/props.ts","../src/json-render/catalog.ts","../src/json-render/StreamingShimmer.tsx","../src/json-render/registry.tsx","../src/json-render/SpecRenderer.tsx","../src/json-render/segment-content.ts","../src/json-render/index.ts","../src/utils/data-component.ts","../src/utils/attachment-kind.ts","../src/hooks/useCanHover.ts","../src/components/lib/wobble.tsx","../src/motion.ts","../src/components/lib/MotionDiv.tsx","../src/components/lib/button.tsx","../src/components/Dialoger.tsx","../src/components/ZoomableImage.tsx","../src/components/AttachmentPreview.tsx","../src/components/ReplyQuote.tsx","../src/components/MemoizedReactMarkdown.tsx","../src/components/configured-text-styles.ts","../src/utils/strip-citation-refs.ts","../src/components/RichText.tsx","../src/hooks/useComponentContext.ts","../src/components/custom-components/MessageAfterComponent.tsx","../src/components/MessageOptions.tsx","../src/components/custom-components/AgentMessageDefaultComponent.tsx","../src/components/custom-components/FallbackDefaultComponent.tsx","../src/components/lib/avatar.tsx","../src/components/AgentAvatar.tsx","../src/components/custom-components/LoadingDefaultComponent.tsx","../src/utils/resolve-trigger-side.ts","../src/hooks/useIsSmallScreen.ts","../src/hooks/useTheme.ts","../src/components/lib/tooltip.tsx","../src/components/FrameDocument.tsx","../src/hooks/useSetWidgetSize.ts","../src/components/lib/DynamicIcon.tsx","../src/companion/useSessionIdentity.ts","../src/companion/useChatPicker.ts","../src/companion/CompanionControlStyles.tsx","../src/companion/ChatPicker.tsx","../src/companion/useHostPortal.ts","../src/companion/ConversationTitle.tsx","../src/components/custom-components/HeaderBottomComponent.tsx","../src/components/custom-components/HeaderTitleComponent.tsx","../src/components/Header.tsx","../src/components/lib/LoadingSpinner.tsx","../src/hooks/useCanvas.ts","../src/components/AgentMessage.tsx","../src/components/SuggestedReplyButton.tsx","../src/components/GroupTimestamp.tsx","../src/components/MessageActions.tsx","../src/components/AgentMessageGroup.tsx","../src/components/lib/BrailleSpinner.tsx","../src/components/StreamingTurn.tsx","../src/components/TaskPlan.tsx","../src/components/custom-components/SessionResolvedComponent.tsx","../src/components/custom-components/ChatBottomComponents.tsx","../src/utils/group-messages-by-type.ts","../src/screens/chat/ChatBannerItems.tsx","../src/utils/svg-mask-url.ts","../src/components/lib/badge.tsx","../src/components/CustomStatus.tsx","../src/screens/chat/ChatCustomStatus.tsx","../src/screens/chat/InitialMessages.tsx","../src/page-marks/MarkThumbnail.tsx","../src/page-privacy.ts","../src/page-marks/mark-thumbnail.ts","../src/page-marks/useMarkThumbnail.ts","../src/page-marks/SentMarkChip.tsx","../src/screens/chat/useMentions.ts","../src/screens/chat/MentionText.tsx","../src/components/UserMessage.tsx","../src/components/UserMessageGroup.tsx","../src/screens/chat/MessageGroups.tsx","../src/screens/chat/agent/scroll-follow.utils.ts","../src/screens/chat/agent/useStreamFollow.ts","../src/screens/chat/agent/AgentChatMain.tsx","../src/screens/chat/ChatCanvas.tsx","../src/hooks/useInitialQuestionRequired.ts","../src/components/lib/MotionDiv__VerticalReveal.tsx","../src/components/CsatSurvey.tsx","../src/components/MightSolveUserIssueSuggestedReplies.tsx","../src/screens/chat/ChatFooterItems.tsx","../src/components/lib/McpIcon.tsx","../src/components/ElicitationForm.tsx","../src/components/ConnectionCard.tsx","../src/page-marks/page-mark.ts","../src/page-marks/page-element.ts","../src/page-marks/mark-source.ts","../src/page-controls/accessible-name.ts","../src/page-controls/act-types.ts","../src/page-controls/action-meaning.ts","../src/page-controls/control-ref.ts","../src/page-controls/types.ts","../src/page-controls/off-limits.ts","../src/page-controls/read-controls.ts","../src/page-controls/send-context.ts","../src/components/PageActionCard.tsx","../src/screens/chat/composer-styles.ts","../src/page-context/PageContextPill.tsx","../src/page-context/usePageEntity.ts","../src/page-marks/page-mark-theme.ts","../src/page-marks/PageMarkOverlay.tsx","../src/page-marks/PageMarkPill.tsx","../src/utils/keybindings.ts","../src/screens/chat/UploadPreview.tsx","../src/screens/chat/agent/QueuedSendsPill.tsx","../src/screens/chat/DictationMicButton.tsx","../src/screens/chat/caret-position.ts","../src/screens/chat/MentionPicker.tsx","../src/page-marks/PageMarksProvider.tsx","../src/page-marks/usePageMarking.ts","../src/screens/chat/usePageMarkComposer.ts","../src/screens/chat/useSentTextRecall.ts","../src/screens/chat/ChatInput.tsx","../src/screens/chat/ChatFooter.tsx","../src/screens/chat/ChatMain.tsx","../src/screens/chat/index.tsx","../src/components/ConnectionsSettings.tsx","../src/components/lib/skeleton.tsx","../src/components/svg/OpenLogoSvg.tsx","../src/components/PoweredByOpen.tsx","../src/screens/sessions/index.tsx","../src/components/lib/input.tsx","../src/hooks/useWidgetContentHeight.tsx","../src/screens/welcome/index.tsx","../src/screens/index.tsx","../src/WidgetPopoverContent.tsx","../src/components/svg/ChatBubbleSvg.tsx","../src/hooks/useTriggerLabel.ts","../src/utils/render-custom-trigger.ts","../src/WidgetPopoverTrigger.tsx","../src/WidgetPopoverAnchor.tsx","../src/companion/companion-keyboard.ts","../src/companion/CompanionQuestions.tsx","../src/page-controls/pointer-sequence.ts","../src/companion/FrameIconButton.tsx","../src/companion/companion-geometry.ts","../src/companion/message-styles.ts","../src/companion/layout-glyphs.tsx","../src/companion/SidebarSubmenu.tsx","../src/companion/LayoutPicker.tsx","../src/companion/PanelControls.tsx","../src/companion/CompanionContent.tsx","../src/companion/CompanionFrame.tsx","../src/companion/CompanionFaceIcon.tsx","../src/companion/RestingPill.tsx","../src/companion/SessionCircles.tsx","../src/companion/useCompanionOpenSync.ts","../src/companion/app-frame.ts","../src/companion/host-scroll-lock.ts","../src/companion/useCompanionHostEffects.ts","../src/companion/useCompanionMeasurements.ts","../src/companion/usePersistedPillDrag.ts","../src/companion/companion-dismissal.ts","../src/companion/WidgetCompanion.tsx","../src/page-controls/guard.ts","../src/page-controls/native-setter.ts","../src/page-controls/select-option.ts","../src/page-controls/act.ts","../src/page-controls/cursor.ts","../src/page-controls/act-input.ts","../src/screens/chat/agent/use-page-effect-is-current.ts","../src/screens/chat/agent/AgentChatPageActions.tsx","../src/page-marks/agent-mark.ts","../src/screens/chat/agent/AgentChatPageEffects.tsx","../src/utils/strip-inline-markdown.ts","../src/components/StepsGroup.tsx","../src/components/ClarificationQuestions.tsx","../src/WidgetImperativeHandler.tsx","../src/index.tsx"],"sourcesContent":["// src/types.ts\nimport { z } from \"zod\";\nvar DynamicValueSchema = z.union([\n z.string(),\n z.number(),\n z.boolean(),\n z.null(),\n z.object({ $state: z.string() })\n]);\nvar DynamicStringSchema = z.union([\n z.string(),\n z.object({ $state: z.string() })\n]);\nvar DynamicNumberSchema = z.union([\n z.number(),\n z.object({ $state: z.string() })\n]);\nvar DynamicBooleanSchema = z.union([\n z.boolean(),\n z.object({ $state: z.string() })\n]);\nfunction resolveDynamicValue(value, stateModel) {\n if (value === null || value === void 0) {\n return void 0;\n }\n if (typeof value === \"object\" && \"$state\" in value) {\n return getByPath(stateModel, value.$state);\n }\n return value;\n}\nfunction unescapeJsonPointer(token) {\n return token.replace(/~1/g, \"/\").replace(/~0/g, \"~\");\n}\nfunction parseJsonPointer(path) {\n const raw = path.startsWith(\"/\") ? path.slice(1).split(\"/\") : path.split(\"/\");\n return raw.map(unescapeJsonPointer);\n}\nfunction getByPath(obj, path) {\n if (!path || path === \"/\") {\n return obj;\n }\n const segments = parseJsonPointer(path);\n let current = obj;\n for (const segment of segments) {\n if (current === null || current === void 0) {\n return void 0;\n }\n if (Array.isArray(current)) {\n const index = parseInt(segment, 10);\n current = current[index];\n } else if (typeof current === \"object\") {\n current = current[segment];\n } else {\n return void 0;\n }\n }\n return current;\n}\nfunction isNumericIndex(str) {\n return /^\\d+$/.test(str);\n}\nfunction setByPath(obj, path, value) {\n const segments = parseJsonPointer(path);\n if (segments.length === 0) return;\n let current = obj;\n for (let i = 0; i < segments.length - 1; i++) {\n const segment = segments[i];\n const nextSegment = segments[i + 1];\n const nextIsNumeric = nextSegment !== void 0 && (isNumericIndex(nextSegment) || nextSegment === \"-\");\n if (Array.isArray(current)) {\n const index = parseInt(segment, 10);\n if (current[index] === void 0 || typeof current[index] !== \"object\") {\n current[index] = nextIsNumeric ? [] : {};\n }\n current = current[index];\n } else {\n if (!(segment in current) || typeof current[segment] !== \"object\") {\n current[segment] = nextIsNumeric ? [] : {};\n }\n current = current[segment];\n }\n }\n const lastSegment = segments[segments.length - 1];\n if (Array.isArray(current)) {\n if (lastSegment === \"-\") {\n current.push(value);\n } else {\n const index = parseInt(lastSegment, 10);\n current[index] = value;\n }\n } else {\n current[lastSegment] = value;\n }\n}\nfunction addByPath(obj, path, value) {\n const segments = parseJsonPointer(path);\n if (segments.length === 0) return;\n let current = obj;\n for (let i = 0; i < segments.length - 1; i++) {\n const segment = segments[i];\n const nextSegment = segments[i + 1];\n const nextIsNumeric = nextSegment !== void 0 && (isNumericIndex(nextSegment) || nextSegment === \"-\");\n if (Array.isArray(current)) {\n const index = parseInt(segment, 10);\n if (current[index] === void 0 || typeof current[index] !== \"object\") {\n current[index] = nextIsNumeric ? [] : {};\n }\n current = current[index];\n } else {\n if (!(segment in current) || typeof current[segment] !== \"object\") {\n current[segment] = nextIsNumeric ? [] : {};\n }\n current = current[segment];\n }\n }\n const lastSegment = segments[segments.length - 1];\n if (Array.isArray(current)) {\n if (lastSegment === \"-\") {\n current.push(value);\n } else {\n const index = parseInt(lastSegment, 10);\n current.splice(index, 0, value);\n }\n } else {\n current[lastSegment] = value;\n }\n}\nfunction removeByPath(obj, path) {\n const segments = parseJsonPointer(path);\n if (segments.length === 0) return;\n let current = obj;\n for (let i = 0; i < segments.length - 1; i++) {\n const segment = segments[i];\n if (Array.isArray(current)) {\n const index = parseInt(segment, 10);\n if (current[index] === void 0 || typeof current[index] !== \"object\") {\n return;\n }\n current = current[index];\n } else {\n if (!(segment in current) || typeof current[segment] !== \"object\") {\n return;\n }\n current = current[segment];\n }\n }\n const lastSegment = segments[segments.length - 1];\n if (Array.isArray(current)) {\n const index = parseInt(lastSegment, 10);\n if (index >= 0 && index < current.length) {\n current.splice(index, 1);\n }\n } else {\n delete current[lastSegment];\n }\n}\nfunction deepEqual(a, b) {\n if (a === b) return true;\n if (a === null || b === null) return false;\n if (typeof a !== typeof b) return false;\n if (typeof a !== \"object\") return false;\n if (Array.isArray(a)) {\n if (!Array.isArray(b)) return false;\n if (a.length !== b.length) return false;\n return a.every((item, i) => deepEqual(item, b[i]));\n }\n const aObj = a;\n const bObj = b;\n const aKeys = Object.keys(aObj);\n const bKeys = Object.keys(bObj);\n if (aKeys.length !== bKeys.length) return false;\n return aKeys.every((key) => deepEqual(aObj[key], bObj[key]));\n}\nfunction findFormValue(fieldName, params, state) {\n if (params?.[fieldName] !== void 0) {\n const val = params[fieldName];\n if (typeof val !== \"string\" || !val.includes(\".\")) {\n return val;\n }\n }\n if (params) {\n for (const key of Object.keys(params)) {\n if (key.endsWith(`.${fieldName}`)) {\n const val = params[key];\n if (typeof val !== \"string\" || !val.includes(\".\")) {\n return val;\n }\n }\n }\n }\n if (state) {\n for (const key of Object.keys(state)) {\n if (key === fieldName || key.endsWith(`.${fieldName}`)) {\n return state[key];\n }\n }\n const val = getByPath(state, fieldName);\n if (val !== void 0) {\n return val;\n }\n }\n return void 0;\n}\nfunction parseSpecStreamLine(line) {\n const trimmed = line.trim();\n if (!trimmed || !trimmed.startsWith(\"{\")) return null;\n try {\n const patch = JSON.parse(trimmed);\n if (patch.op && patch.path !== void 0) {\n return patch;\n }\n return null;\n } catch {\n return null;\n }\n}\nfunction applySpecStreamPatch(obj, patch) {\n switch (patch.op) {\n case \"add\":\n addByPath(obj, patch.path, patch.value);\n break;\n case \"replace\":\n setByPath(obj, patch.path, patch.value);\n break;\n case \"remove\":\n removeByPath(obj, patch.path);\n break;\n case \"move\": {\n if (!patch.from) break;\n const moveValue = getByPath(obj, patch.from);\n removeByPath(obj, patch.from);\n addByPath(obj, patch.path, moveValue);\n break;\n }\n case \"copy\": {\n if (!patch.from) break;\n const copyValue = getByPath(obj, patch.from);\n addByPath(obj, patch.path, copyValue);\n break;\n }\n case \"test\": {\n const actual = getByPath(obj, patch.path);\n if (!deepEqual(actual, patch.value)) {\n throw new Error(\n `Test operation failed: value at \"${patch.path}\" does not match`\n );\n }\n break;\n }\n }\n return obj;\n}\nfunction applySpecPatch(spec, patch) {\n applySpecStreamPatch(spec, patch);\n return spec;\n}\nfunction nestedToFlat(nested) {\n const elements = {};\n let counter = 0;\n function walk(node) {\n const key = `el-${counter++}`;\n const { type, props, children: rawChildren, ...rest } = node;\n const childKeys = [];\n if (Array.isArray(rawChildren)) {\n for (const child of rawChildren) {\n if (child && typeof child === \"object\" && \"type\" in child) {\n childKeys.push(walk(child));\n }\n }\n }\n const element = {\n type: type ?? \"unknown\",\n props: props ?? {},\n children: childKeys\n };\n for (const [k, v] of Object.entries(rest)) {\n if (k !== \"state\" && v !== void 0) {\n element[k] = v;\n }\n }\n elements[key] = element;\n return key;\n }\n const root = walk(nested);\n const spec = { root, elements };\n if (nested.state && typeof nested.state === \"object\" && !Array.isArray(nested.state)) {\n spec.state = nested.state;\n }\n return spec;\n}\nfunction compileSpecStream(stream, initial = {}) {\n const lines = stream.split(\"\\n\");\n const result = { ...initial };\n for (const line of lines) {\n const patch = parseSpecStreamLine(line);\n if (patch) {\n applySpecStreamPatch(result, patch);\n }\n }\n return result;\n}\nfunction createSpecStreamCompiler(initial = {}) {\n let result = { ...initial };\n let buffer = \"\";\n const appliedPatches = [];\n const processedLines = /* @__PURE__ */ new Set();\n return {\n push(chunk) {\n buffer += chunk;\n const newPatches = [];\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || processedLines.has(trimmed)) continue;\n processedLines.add(trimmed);\n const patch = parseSpecStreamLine(trimmed);\n if (patch) {\n applySpecStreamPatch(result, patch);\n appliedPatches.push(patch);\n newPatches.push(patch);\n }\n }\n if (newPatches.length > 0) {\n result = { ...result };\n }\n return { result, newPatches };\n },\n getResult() {\n if (buffer.trim()) {\n const patch = parseSpecStreamLine(buffer);\n if (patch && !processedLines.has(buffer.trim())) {\n processedLines.add(buffer.trim());\n applySpecStreamPatch(result, patch);\n appliedPatches.push(patch);\n result = { ...result };\n }\n buffer = \"\";\n }\n return result;\n },\n getPatches() {\n return [...appliedPatches];\n },\n reset(newInitial = {}) {\n result = { ...newInitial };\n buffer = \"\";\n appliedPatches.length = 0;\n processedLines.clear();\n }\n };\n}\nfunction createMixedStreamParser(callbacks) {\n let buffer = \"\";\n let inSpecFence = false;\n function processLine(line) {\n const trimmed = line.trim();\n if (!inSpecFence && trimmed.startsWith(\"```spec\")) {\n inSpecFence = true;\n return;\n }\n if (inSpecFence && trimmed === \"```\") {\n inSpecFence = false;\n return;\n }\n if (!trimmed) return;\n if (inSpecFence) {\n const patch2 = parseSpecStreamLine(trimmed);\n if (patch2) {\n callbacks.onPatch(patch2);\n }\n return;\n }\n const patch = parseSpecStreamLine(trimmed);\n if (patch) {\n callbacks.onPatch(patch);\n } else {\n callbacks.onText(line);\n }\n }\n return {\n push(chunk) {\n buffer += chunk;\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() || \"\";\n for (const line of lines) {\n processLine(line);\n }\n },\n flush() {\n if (buffer.trim()) {\n processLine(buffer);\n }\n buffer = \"\";\n }\n };\n}\nvar SPEC_FENCE_OPEN = \"```spec\";\nvar SPEC_FENCE_CLOSE = \"```\";\nfunction createJsonRenderTransform() {\n let lineBuffer = \"\";\n let currentTextId = \"\";\n let buffering = false;\n let inSpecFence = false;\n let inTextBlock = false;\n let textIdCounter = 0;\n function closeTextBlock(controller) {\n if (inTextBlock) {\n controller.enqueue({ type: \"text-end\", id: currentTextId });\n inTextBlock = false;\n }\n }\n function ensureTextBlock(controller) {\n if (!inTextBlock) {\n textIdCounter++;\n currentTextId = String(textIdCounter);\n controller.enqueue({ type: \"text-start\", id: currentTextId });\n inTextBlock = true;\n }\n }\n function emitTextDelta(delta, controller) {\n ensureTextBlock(controller);\n controller.enqueue({ type: \"text-delta\", id: currentTextId, delta });\n }\n function emitPatch(patch, controller) {\n closeTextBlock(controller);\n controller.enqueue({\n type: SPEC_DATA_PART_TYPE,\n data: { type: \"patch\", patch }\n });\n }\n function flushBuffer(controller) {\n if (!lineBuffer) return;\n const trimmed = lineBuffer.trim();\n if (inSpecFence) {\n if (trimmed) {\n const patch = parseSpecStreamLine(trimmed);\n if (patch) emitPatch(patch, controller);\n }\n lineBuffer = \"\";\n buffering = false;\n return;\n }\n if (trimmed) {\n const patch = parseSpecStreamLine(trimmed);\n if (patch) {\n emitPatch(patch, controller);\n } else {\n emitTextDelta(lineBuffer, controller);\n }\n } else {\n emitTextDelta(lineBuffer, controller);\n }\n lineBuffer = \"\";\n buffering = false;\n }\n function processCompleteLine(line, controller) {\n const trimmed = line.trim();\n if (!inSpecFence && trimmed.startsWith(SPEC_FENCE_OPEN)) {\n inSpecFence = true;\n return;\n }\n if (inSpecFence && trimmed === SPEC_FENCE_CLOSE) {\n inSpecFence = false;\n return;\n }\n if (inSpecFence) {\n if (trimmed) {\n const patch2 = parseSpecStreamLine(trimmed);\n if (patch2) emitPatch(patch2, controller);\n }\n return;\n }\n if (!trimmed) {\n emitTextDelta(\"\\n\", controller);\n return;\n }\n const patch = parseSpecStreamLine(trimmed);\n if (patch) {\n emitPatch(patch, controller);\n } else {\n emitTextDelta(line + \"\\n\", controller);\n }\n }\n return new TransformStream({\n transform(chunk, controller) {\n switch (chunk.type) {\n case \"text-start\": {\n const id = chunk.id;\n const idNum = parseInt(id, 10);\n if (!isNaN(idNum) && idNum >= textIdCounter) {\n textIdCounter = idNum;\n }\n currentTextId = id;\n inTextBlock = true;\n controller.enqueue(chunk);\n break;\n }\n case \"text-delta\": {\n const delta = chunk;\n const text = delta.delta;\n for (let i = 0; i < text.length; i++) {\n const ch = text.charAt(i);\n if (ch === \"\\n\") {\n if (buffering) {\n processCompleteLine(lineBuffer, controller);\n lineBuffer = \"\";\n buffering = false;\n } else {\n if (!inSpecFence) {\n emitTextDelta(\"\\n\", controller);\n }\n }\n } else if (lineBuffer.length === 0 && !buffering) {\n if (inSpecFence || ch === \"{\" || ch === \"`\") {\n buffering = true;\n lineBuffer += ch;\n } else {\n emitTextDelta(ch, controller);\n }\n } else if (buffering) {\n lineBuffer += ch;\n } else {\n emitTextDelta(ch, controller);\n }\n }\n break;\n }\n case \"text-end\": {\n flushBuffer(controller);\n if (inTextBlock) {\n controller.enqueue({ type: \"text-end\", id: currentTextId });\n inTextBlock = false;\n }\n break;\n }\n default: {\n controller.enqueue(chunk);\n break;\n }\n }\n },\n flush(controller) {\n flushBuffer(controller);\n closeTextBlock(controller);\n }\n });\n}\nvar SPEC_DATA_PART = \"spec\";\nvar SPEC_DATA_PART_TYPE = `data-${SPEC_DATA_PART}`;\nfunction pipeJsonRender(stream) {\n return stream.pipeThrough(\n createJsonRenderTransform()\n );\n}\n\n// src/state-store.ts\nfunction immutableSetByPath(root, path, value) {\n const segments = parseJsonPointer(path);\n if (segments.length === 0) return root;\n const result = { ...root };\n let current = result;\n for (let i = 0; i < segments.length - 1; i++) {\n const seg = segments[i];\n const child = current[seg];\n if (Array.isArray(child)) {\n current[seg] = [...child];\n } else if (child !== null && typeof child === \"object\") {\n current[seg] = { ...child };\n } else {\n const nextSeg = segments[i + 1];\n current[seg] = nextSeg !== void 0 && /^\\d+$/.test(nextSeg) ? [] : {};\n }\n current = current[seg];\n }\n const lastSeg = segments[segments.length - 1];\n if (Array.isArray(current)) {\n if (lastSeg === \"-\") {\n current.push(value);\n } else {\n current[parseInt(lastSeg, 10)] = value;\n }\n } else {\n current[lastSeg] = value;\n }\n return result;\n}\nfunction createStateStore(initialState = {}) {\n let state = { ...initialState };\n const listeners = /* @__PURE__ */ new Set();\n function notify() {\n for (const listener of listeners) {\n listener();\n }\n }\n return {\n get(path) {\n return getByPath(state, path);\n },\n set(path, value) {\n if (getByPath(state, path) === value) return;\n state = immutableSetByPath(state, path, value);\n notify();\n },\n update(updates) {\n let changed = false;\n let next = state;\n for (const [path, value] of Object.entries(updates)) {\n if (getByPath(next, path) !== value) {\n next = immutableSetByPath(next, path, value);\n changed = true;\n }\n }\n if (!changed) return;\n state = next;\n notify();\n },\n getSnapshot() {\n return state;\n },\n getServerSnapshot() {\n return state;\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n }\n };\n}\nfunction createStoreAdapter(config) {\n return {\n get(path) {\n return getByPath(config.getSnapshot(), path);\n },\n set(path, value) {\n const current = config.getSnapshot();\n if (getByPath(current, path) === value) return;\n config.setSnapshot(immutableSetByPath(current, path, value));\n },\n update(updates) {\n let next = config.getSnapshot();\n let changed = false;\n for (const [path, value] of Object.entries(updates)) {\n if (getByPath(next, path) !== value) {\n next = immutableSetByPath(next, path, value);\n changed = true;\n }\n }\n if (!changed) return;\n config.setSnapshot(next);\n },\n getSnapshot: config.getSnapshot,\n getServerSnapshot: config.getSnapshot,\n subscribe: config.subscribe\n };\n}\nvar MAX_FLATTEN_DEPTH = 20;\nfunction flattenToPointers(obj, prefix = \"\", _depth = 0, _seen, _warned) {\n const seen = _seen ?? /* @__PURE__ */ new Set();\n const warned = _warned ?? { current: false };\n const result = {};\n for (const [key, value] of Object.entries(obj)) {\n const pointer = `${prefix}/${key}`;\n if (_depth < MAX_FLATTEN_DEPTH && value !== null && typeof value === \"object\" && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype && !seen.has(value)) {\n seen.add(value);\n Object.assign(\n result,\n flattenToPointers(\n value,\n pointer,\n _depth + 1,\n seen,\n warned\n )\n );\n } else {\n if (process.env.NODE_ENV !== \"production\" && !warned.current && _depth >= MAX_FLATTEN_DEPTH && value !== null && typeof value === \"object\" && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype && !seen.has(value)) {\n warned.current = true;\n console.warn(\n `flattenToPointers: depth limit (${MAX_FLATTEN_DEPTH}) reached. Nested state beyond this depth will be treated as a leaf value.`\n );\n }\n result[pointer] = value;\n }\n }\n return result;\n}\n\nexport {\n DynamicValueSchema,\n DynamicStringSchema,\n DynamicNumberSchema,\n DynamicBooleanSchema,\n resolveDynamicValue,\n getByPath,\n setByPath,\n addByPath,\n removeByPath,\n findFormValue,\n parseSpecStreamLine,\n applySpecStreamPatch,\n applySpecPatch,\n nestedToFlat,\n compileSpecStream,\n createSpecStreamCompiler,\n createMixedStreamParser,\n createJsonRenderTransform,\n SPEC_DATA_PART,\n SPEC_DATA_PART_TYPE,\n pipeJsonRender,\n immutableSetByPath,\n createStateStore,\n createStoreAdapter,\n flattenToPointers\n};\n//# sourceMappingURL=chunk-AFLK3Q4T.mjs.map","import {\n DynamicBooleanSchema,\n DynamicNumberSchema,\n DynamicStringSchema,\n DynamicValueSchema,\n SPEC_DATA_PART,\n SPEC_DATA_PART_TYPE,\n addByPath,\n applySpecPatch,\n applySpecStreamPatch,\n compileSpecStream,\n createJsonRenderTransform,\n createMixedStreamParser,\n createSpecStreamCompiler,\n createStateStore,\n findFormValue,\n getByPath,\n nestedToFlat,\n parseSpecStreamLine,\n pipeJsonRender,\n removeByPath,\n resolveDynamicValue,\n setByPath\n} from \"./chunk-AFLK3Q4T.mjs\";\n\n// src/visibility.ts\nimport { z } from \"zod\";\nvar numericOrStateRef = z.union([\n z.number(),\n z.object({ $state: z.string() })\n]);\nvar comparisonOps = {\n eq: z.unknown().optional(),\n neq: z.unknown().optional(),\n gt: numericOrStateRef.optional(),\n gte: numericOrStateRef.optional(),\n lt: numericOrStateRef.optional(),\n lte: numericOrStateRef.optional(),\n not: z.literal(true).optional()\n};\nvar StateConditionSchema = z.object({\n $state: z.string(),\n ...comparisonOps\n});\nvar ItemConditionSchema = z.object({\n $item: z.string(),\n ...comparisonOps\n});\nvar IndexConditionSchema = z.object({\n $index: z.literal(true),\n ...comparisonOps\n});\nvar SingleConditionSchema = z.union([\n StateConditionSchema,\n ItemConditionSchema,\n IndexConditionSchema\n]);\nvar VisibilityConditionSchema = z.lazy(\n () => z.union([\n z.boolean(),\n SingleConditionSchema,\n z.array(SingleConditionSchema),\n z.object({ $and: z.array(VisibilityConditionSchema) }),\n z.object({ $or: z.array(VisibilityConditionSchema) })\n ])\n);\nfunction resolveComparisonValue(value, ctx) {\n if (typeof value === \"object\" && value !== null) {\n if (\"$state\" in value && typeof value.$state === \"string\") {\n return getByPath(ctx.stateModel, value.$state);\n }\n }\n return value;\n}\nfunction isItemCondition(cond) {\n return \"$item\" in cond;\n}\nfunction isIndexCondition(cond) {\n return \"$index\" in cond;\n}\nfunction resolveConditionValue(cond, ctx) {\n if (isIndexCondition(cond)) {\n return ctx.repeatIndex;\n }\n if (isItemCondition(cond)) {\n if (ctx.repeatItem === void 0) return void 0;\n return cond.$item === \"\" ? ctx.repeatItem : getByPath(ctx.repeatItem, cond.$item);\n }\n return getByPath(ctx.stateModel, cond.$state);\n}\nfunction evaluateCondition(cond, ctx) {\n const value = resolveConditionValue(cond, ctx);\n let result;\n if (cond.eq !== void 0) {\n const rhs = resolveComparisonValue(cond.eq, ctx);\n result = value === rhs;\n } else if (cond.neq !== void 0) {\n const rhs = resolveComparisonValue(cond.neq, ctx);\n result = value !== rhs;\n } else if (cond.gt !== void 0) {\n const rhs = resolveComparisonValue(cond.gt, ctx);\n result = typeof value === \"number\" && typeof rhs === \"number\" ? value > rhs : false;\n } else if (cond.gte !== void 0) {\n const rhs = resolveComparisonValue(cond.gte, ctx);\n result = typeof value === \"number\" && typeof rhs === \"number\" ? value >= rhs : false;\n } else if (cond.lt !== void 0) {\n const rhs = resolveComparisonValue(cond.lt, ctx);\n result = typeof value === \"number\" && typeof rhs === \"number\" ? value < rhs : false;\n } else if (cond.lte !== void 0) {\n const rhs = resolveComparisonValue(cond.lte, ctx);\n result = typeof value === \"number\" && typeof rhs === \"number\" ? value <= rhs : false;\n } else {\n result = Boolean(value);\n }\n return cond.not === true ? !result : result;\n}\nfunction isAndCondition(condition) {\n return typeof condition === \"object\" && condition !== null && !Array.isArray(condition) && \"$and\" in condition;\n}\nfunction isOrCondition(condition) {\n return typeof condition === \"object\" && condition !== null && !Array.isArray(condition) && \"$or\" in condition;\n}\nfunction evaluateVisibility(condition, ctx) {\n if (condition === void 0) {\n return true;\n }\n if (typeof condition === \"boolean\") {\n return condition;\n }\n if (Array.isArray(condition)) {\n return condition.every((c) => evaluateCondition(c, ctx));\n }\n if (isAndCondition(condition)) {\n return condition.$and.every((child) => evaluateVisibility(child, ctx));\n }\n if (isOrCondition(condition)) {\n return condition.$or.some((child) => evaluateVisibility(child, ctx));\n }\n return evaluateCondition(condition, ctx);\n}\nvar visibility = {\n /** Always visible */\n always: true,\n /** Never visible */\n never: false,\n /** Visible when state path is truthy */\n when: (path) => ({ $state: path }),\n /** Visible when state path is falsy */\n unless: (path) => ({ $state: path, not: true }),\n /** Equality check */\n eq: (path, value) => ({\n $state: path,\n eq: value\n }),\n /** Not equal check */\n neq: (path, value) => ({\n $state: path,\n neq: value\n }),\n /** Greater than */\n gt: (path, value) => ({\n $state: path,\n gt: value\n }),\n /** Greater than or equal */\n gte: (path, value) => ({\n $state: path,\n gte: value\n }),\n /** Less than */\n lt: (path, value) => ({\n $state: path,\n lt: value\n }),\n /** Less than or equal */\n lte: (path, value) => ({\n $state: path,\n lte: value\n }),\n /** AND multiple conditions */\n and: (...conditions) => ({\n $and: conditions\n }),\n /** OR multiple conditions */\n or: (...conditions) => ({\n $or: conditions\n })\n};\n\n// src/directives.ts\nvar BUILT_IN_KEYS = /* @__PURE__ */ new Set([\n \"$state\",\n \"$item\",\n \"$index\",\n \"$bindState\",\n \"$bindItem\",\n \"$cond\",\n \"$computed\",\n \"$template\"\n]);\nfunction defineDirective(definition) {\n if (!definition.name.startsWith(\"$\")) {\n throw new Error(\n `Directive name must start with \"$\": got \"${definition.name}\"`\n );\n }\n if (BUILT_IN_KEYS.has(definition.name)) {\n throw new Error(\n `Directive name \"${definition.name}\" conflicts with a built-in prop expression key`\n );\n }\n return definition;\n}\nfunction createDirectiveRegistry(directives) {\n const registry = /* @__PURE__ */ new Map();\n for (const d of directives) {\n registry.set(d.name, d);\n }\n return registry;\n}\nfunction findDirective(value, directives) {\n if (!directives || directives.size === 0) return void 0;\n let match;\n for (const [key, def] of directives) {\n if (key in value) {\n if (match) {\n throw new Error(\n `Ambiguous directive: object has multiple directive keys (\"${match.name}\" and \"${key}\")`\n );\n }\n match = def;\n }\n }\n return match;\n}\n\n// src/props.ts\nfunction isStateExpression(value) {\n return typeof value === \"object\" && value !== null && \"$state\" in value && typeof value.$state === \"string\";\n}\nfunction isItemExpression(value) {\n return typeof value === \"object\" && value !== null && \"$item\" in value && typeof value.$item === \"string\";\n}\nfunction isIndexExpression(value) {\n return typeof value === \"object\" && value !== null && \"$index\" in value && value.$index === true;\n}\nfunction isBindStateExpression(value) {\n return typeof value === \"object\" && value !== null && \"$bindState\" in value && typeof value.$bindState === \"string\";\n}\nfunction isBindItemExpression(value) {\n return typeof value === \"object\" && value !== null && \"$bindItem\" in value && typeof value.$bindItem === \"string\";\n}\nfunction isCondExpression(value) {\n return typeof value === \"object\" && value !== null && \"$cond\" in value && \"$then\" in value && \"$else\" in value;\n}\nfunction isComputedExpression(value) {\n return typeof value === \"object\" && value !== null && \"$computed\" in value && typeof value.$computed === \"string\";\n}\nfunction isTemplateExpression(value) {\n return typeof value === \"object\" && value !== null && \"$template\" in value && typeof value.$template === \"string\";\n}\nvar WARNED_COMPUTED_MAX = 100;\nvar warnedComputedFns = /* @__PURE__ */ new Set();\nfunction resolveBindItemPath(itemPath, ctx) {\n if (ctx.repeatBasePath == null) {\n console.warn(`$bindItem used outside repeat scope: \"${itemPath}\"`);\n return void 0;\n }\n if (itemPath === \"\") return ctx.repeatBasePath;\n return ctx.repeatBasePath + \"/\" + itemPath;\n}\nfunction resolvePropValue(value, ctx) {\n if (value === null || value === void 0) {\n return value;\n }\n if (isStateExpression(value)) {\n return getByPath(ctx.stateModel, value.$state);\n }\n if (isItemExpression(value)) {\n if (ctx.repeatItem === void 0) return void 0;\n return value.$item === \"\" ? ctx.repeatItem : getByPath(ctx.repeatItem, value.$item);\n }\n if (isIndexExpression(value)) {\n return ctx.repeatIndex;\n }\n if (isBindStateExpression(value)) {\n return getByPath(ctx.stateModel, value.$bindState);\n }\n if (isBindItemExpression(value)) {\n const resolvedPath = resolveBindItemPath(value.$bindItem, ctx);\n if (resolvedPath === void 0) return void 0;\n return getByPath(ctx.stateModel, resolvedPath);\n }\n if (isCondExpression(value)) {\n const result = evaluateVisibility(value.$cond, ctx);\n return resolvePropValue(result ? value.$then : value.$else, ctx);\n }\n if (isComputedExpression(value)) {\n const fn = ctx.functions?.[value.$computed];\n if (!fn) {\n if (!warnedComputedFns.has(value.$computed)) {\n if (warnedComputedFns.size < WARNED_COMPUTED_MAX) {\n warnedComputedFns.add(value.$computed);\n }\n console.warn(`Unknown $computed function: \"${value.$computed}\"`);\n }\n return void 0;\n }\n const resolvedArgs = {};\n if (value.args) {\n for (const [key, arg] of Object.entries(value.args)) {\n resolvedArgs[key] = resolvePropValue(arg, ctx);\n }\n }\n return fn(resolvedArgs);\n }\n if (isTemplateExpression(value)) {\n return value.$template.replace(\n /\\$\\{([^}]+)\\}/g,\n (_match, rawPath) => {\n if (rawPath.startsWith(\"/\")) {\n const resolved2 = getByPath(ctx.stateModel, rawPath);\n return resolved2 != null ? String(resolved2) : \"\";\n }\n if (ctx.repeatItem !== void 0) {\n const fromItem = getByPath(ctx.repeatItem, rawPath);\n if (fromItem != null) return String(fromItem);\n }\n const resolved = getByPath(ctx.stateModel, \"/\" + rawPath);\n return resolved != null ? String(resolved) : \"\";\n }\n );\n }\n if (Array.isArray(value)) {\n return value.map((item) => resolvePropValue(item, ctx));\n }\n if (typeof value === \"object\") {\n const directive = findDirective(\n value,\n ctx.directives\n );\n if (directive) {\n return directive.resolve(value, ctx);\n }\n const resolved = {};\n for (const [key, val] of Object.entries(value)) {\n resolved[key] = resolvePropValue(val, ctx);\n }\n return resolved;\n }\n return value;\n}\nfunction resolveElementProps(props, ctx) {\n const resolved = {};\n for (const [key, value] of Object.entries(props)) {\n resolved[key] = resolvePropValue(value, ctx);\n }\n return resolved;\n}\nfunction resolveBindings(props, ctx) {\n let bindings;\n for (const [key, value] of Object.entries(props)) {\n if (isBindStateExpression(value)) {\n if (!bindings) bindings = {};\n bindings[key] = value.$bindState;\n } else if (isBindItemExpression(value)) {\n const resolved = resolveBindItemPath(value.$bindItem, ctx);\n if (resolved !== void 0) {\n if (!bindings) bindings = {};\n bindings[key] = resolved;\n }\n }\n }\n return bindings;\n}\nfunction resolveActionParam(value, ctx) {\n if (isItemExpression(value)) {\n return resolveBindItemPath(value.$item, ctx);\n }\n if (isIndexExpression(value)) {\n return ctx.repeatIndex;\n }\n return resolvePropValue(value, ctx);\n}\n\n// src/action-observer.ts\nvar observers = /* @__PURE__ */ new Set();\nfunction registerActionObserver(observer) {\n observers.add(observer);\n return () => {\n observers.delete(observer);\n };\n}\nfunction notifyActionDispatch(evt) {\n for (const o of observers) {\n const fn = o.onDispatch;\n if (!fn) continue;\n try {\n fn(evt);\n } catch (err) {\n if (process.env.NODE_ENV !== \"production\") {\n console.error(\n \"[json-render] action observer threw in onDispatch:\",\n err\n );\n }\n }\n }\n}\nfunction notifyActionSettle(evt) {\n for (const o of observers) {\n const fn = o.onSettle;\n if (!fn) continue;\n try {\n fn(evt);\n } catch (err) {\n if (process.env.NODE_ENV !== \"production\") {\n console.error(\"[json-render] action observer threw in onSettle:\", err);\n }\n }\n }\n}\nvar dispatchCounter = 0;\nfunction nextActionDispatchId() {\n dispatchCounter += 1;\n return `${Date.now()}-${dispatchCounter}`;\n}\n\n// src/devtools-flag.ts\nvar activeCount = 0;\nvar listeners = /* @__PURE__ */ new Set();\nfunction markDevtoolsActive() {\n activeCount += 1;\n notifyDevtoolsActiveChange();\n let released = false;\n return () => {\n if (released) return;\n released = true;\n activeCount = Math.max(0, activeCount - 1);\n notifyDevtoolsActiveChange();\n };\n}\nfunction isDevtoolsActive() {\n return activeCount > 0;\n}\nfunction subscribeDevtoolsActive(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\nfunction notifyDevtoolsActiveChange() {\n for (const l of listeners) {\n try {\n l();\n } catch (err) {\n if (process.env.NODE_ENV !== \"production\") {\n console.error(\"[json-render] devtools-active listener threw:\", err);\n }\n }\n }\n}\n\n// src/actions.ts\nimport { z as z2 } from \"zod\";\nvar ActionConfirmSchema = z2.object({\n title: z2.string(),\n message: z2.string(),\n confirmLabel: z2.string().optional(),\n cancelLabel: z2.string().optional(),\n variant: z2.enum([\"default\", \"danger\"]).optional()\n});\nvar ActionOnSuccessSchema = z2.union([\n z2.object({ navigate: z2.string() }),\n z2.object({ set: z2.record(z2.string(), z2.unknown()) }),\n z2.object({ action: z2.string() })\n]);\nvar ActionOnErrorSchema = z2.union([\n z2.object({ set: z2.record(z2.string(), z2.unknown()) }),\n z2.object({ action: z2.string() })\n]);\nvar ActionBindingSchema = z2.object({\n action: z2.string(),\n params: z2.record(z2.string(), DynamicValueSchema).optional(),\n confirm: ActionConfirmSchema.optional(),\n onSuccess: ActionOnSuccessSchema.optional(),\n onError: ActionOnErrorSchema.optional(),\n preventDefault: z2.boolean().optional()\n});\nvar ActionSchema = ActionBindingSchema;\nfunction resolveAction(binding, stateModel) {\n const resolvedParams = {};\n if (binding.params) {\n for (const [key, value] of Object.entries(binding.params)) {\n resolvedParams[key] = resolveDynamicValue(value, stateModel);\n }\n }\n let confirm = binding.confirm;\n if (confirm) {\n confirm = {\n ...confirm,\n message: interpolateString(confirm.message, stateModel),\n title: interpolateString(confirm.title, stateModel)\n };\n }\n return {\n action: binding.action,\n params: resolvedParams,\n confirm,\n onSuccess: binding.onSuccess,\n onError: binding.onError\n };\n}\nfunction interpolateString(template, stateModel) {\n return template.replace(/\\$\\{([^}]+)\\}/g, (_, path) => {\n const value = resolveDynamicValue({ $state: path }, stateModel);\n return String(value ?? \"\");\n });\n}\nasync function executeAction(ctx) {\n const { action: action2, handler, setState, navigate, executeAction: executeAction2 } = ctx;\n try {\n await handler(action2.params);\n if (action2.onSuccess) {\n if (\"navigate\" in action2.onSuccess && navigate) {\n navigate(action2.onSuccess.navigate);\n } else if (\"set\" in action2.onSuccess) {\n for (const [path, value] of Object.entries(action2.onSuccess.set)) {\n setState(path, value);\n }\n } else if (\"action\" in action2.onSuccess && executeAction2) {\n await executeAction2(action2.onSuccess.action);\n }\n }\n } catch (error) {\n if (action2.onError) {\n if (\"set\" in action2.onError) {\n for (const [path, value] of Object.entries(action2.onError.set)) {\n const resolvedValue = typeof value === \"string\" && value === \"$error.message\" ? error.message : value;\n setState(path, resolvedValue);\n }\n } else if (\"action\" in action2.onError && executeAction2) {\n await executeAction2(action2.onError.action);\n }\n } else {\n throw error;\n }\n }\n}\nvar actionBinding = {\n /** Create a simple action binding */\n simple: (actionName, params) => ({\n action: actionName,\n params\n }),\n /** Create an action binding with confirmation */\n withConfirm: (actionName, confirm, params) => ({\n action: actionName,\n params,\n confirm\n }),\n /** Create an action binding with success handler */\n withSuccess: (actionName, onSuccess, params) => ({\n action: actionName,\n params,\n onSuccess\n })\n};\nvar action = actionBinding;\n\n// src/validation.ts\nimport { z as z3 } from \"zod\";\nvar ValidationCheckSchema = z3.object({\n type: z3.string(),\n args: z3.record(z3.string(), DynamicValueSchema).optional(),\n message: z3.string()\n});\nvar ValidationConfigSchema = z3.object({\n checks: z3.array(ValidationCheckSchema).optional(),\n validateOn: z3.enum([\"change\", \"blur\", \"submit\"]).optional(),\n enabled: VisibilityConditionSchema.optional()\n});\nvar matchesImpl = (value, args) => {\n const other = args?.other;\n return value === other;\n};\nvar builtInValidationFunctions = {\n /**\n * Check if value is not null, undefined, or empty string\n */\n required: (value) => {\n if (value === null || value === void 0) return false;\n if (typeof value === \"string\") return value.trim().length > 0;\n if (Array.isArray(value)) return value.length > 0;\n return true;\n },\n /**\n * Check if value is a valid email address\n */\n email: (value) => {\n if (typeof value !== \"string\") return false;\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(value);\n },\n /**\n * Check minimum string length\n */\n minLength: (value, args) => {\n if (typeof value !== \"string\") return false;\n const min = args?.min;\n if (typeof min !== \"number\") return false;\n return value.length >= min;\n },\n /**\n * Check maximum string length\n */\n maxLength: (value, args) => {\n if (typeof value !== \"string\") return false;\n const max = args?.max;\n if (typeof max !== \"number\") return false;\n return value.length <= max;\n },\n /**\n * Check if string matches a regex pattern\n */\n pattern: (value, args) => {\n if (typeof value !== \"string\") return false;\n const pattern = args?.pattern;\n if (typeof pattern !== \"string\") return false;\n try {\n return new RegExp(pattern).test(value);\n } catch {\n return false;\n }\n },\n /**\n * Check minimum numeric value\n */\n min: (value, args) => {\n if (typeof value !== \"number\") return false;\n const min = args?.min;\n if (typeof min !== \"number\") return false;\n return value >= min;\n },\n /**\n * Check maximum numeric value\n */\n max: (value, args) => {\n if (typeof value !== \"number\") return false;\n const max = args?.max;\n if (typeof max !== \"number\") return false;\n return value <= max;\n },\n /**\n * Check if value is a number\n */\n numeric: (value) => {\n if (typeof value === \"number\") return !isNaN(value);\n if (typeof value === \"string\") return !isNaN(parseFloat(value));\n return false;\n },\n /**\n * Check if value is a valid URL\n */\n url: (value) => {\n if (typeof value !== \"string\") return false;\n try {\n new URL(value);\n return true;\n } catch {\n return false;\n }\n },\n /**\n * Check if value matches another field\n */\n matches: matchesImpl,\n /**\n * Alias for matches with a more descriptive name for cross-field equality\n */\n equalTo: matchesImpl,\n /**\n * Check if value is less than another field's value.\n * Supports numbers, strings (useful for ISO date comparison), and\n * cross-type numeric coercion (e.g. string \"3\" vs number 5).\n */\n lessThan: (value, args) => {\n const other = args?.other;\n if (value == null || other == null || value === \"\" || other === \"\")\n return false;\n if (typeof value === \"number\" && typeof other === \"number\")\n return value < other;\n if (typeof value === \"string\" && typeof other === \"string\")\n return value < other;\n const numVal = Number(value);\n const numOther = Number(other);\n if (!isNaN(numVal) && !isNaN(numOther)) return numVal < numOther;\n return false;\n },\n /**\n * Check if value is greater than another field's value.\n * Supports numbers, strings (useful for ISO date comparison), and\n * cross-type numeric coercion (e.g. string \"7\" vs number 5).\n */\n greaterThan: (value, args) => {\n const other = args?.other;\n if (value == null || other == null || value === \"\" || other === \"\")\n return false;\n if (typeof value === \"number\" && typeof other === \"number\")\n return value > other;\n if (typeof value === \"string\" && typeof other === \"string\")\n return value > other;\n const numVal = Number(value);\n const numOther = Number(other);\n if (!isNaN(numVal) && !isNaN(numOther)) return numVal > numOther;\n return false;\n },\n /**\n * Required only when a condition is met.\n * Uses JS truthiness: 0, false, \"\", null, and undefined are all\n * treated as \"condition not met\" (field not required), matching\n * the visibility system's bare-condition semantics.\n */\n requiredIf: (value, args) => {\n const condition = args?.field;\n if (!condition) return true;\n if (value === null || value === void 0) return false;\n if (typeof value === \"string\") return value.trim().length > 0;\n if (Array.isArray(value)) return value.length > 0;\n return true;\n }\n};\nfunction runValidationCheck(check2, ctx) {\n const { value, stateModel, customFunctions } = ctx;\n const resolvedArgs = {};\n if (check2.args) {\n for (const [key, argValue] of Object.entries(check2.args)) {\n resolvedArgs[key] = resolvePropValue(argValue, { stateModel });\n }\n }\n const validationFn = builtInValidationFunctions[check2.type] ?? customFunctions?.[check2.type];\n if (!validationFn) {\n console.warn(`Unknown validation function: ${check2.type}`);\n return {\n type: check2.type,\n valid: true,\n // Don't fail on unknown functions\n message: check2.message\n };\n }\n const valid = validationFn(value, resolvedArgs);\n return {\n type: check2.type,\n valid,\n message: check2.message\n };\n}\nfunction runValidation(config, ctx) {\n const checks = [];\n const errors = [];\n if (config.enabled) {\n const enabled = evaluateVisibility(config.enabled, {\n stateModel: ctx.stateModel\n });\n if (!enabled) {\n return { valid: true, errors: [], checks: [] };\n }\n }\n if (config.checks) {\n for (const check2 of config.checks) {\n const result = runValidationCheck(check2, ctx);\n checks.push(result);\n if (!result.valid) {\n errors.push(result.message);\n }\n }\n }\n return {\n valid: errors.length === 0,\n errors,\n checks\n };\n}\nvar check = {\n required: (message = \"This field is required\") => ({\n type: \"required\",\n message\n }),\n email: (message = \"Invalid email address\") => ({\n type: \"email\",\n message\n }),\n minLength: (min, message) => ({\n type: \"minLength\",\n args: { min },\n message: message ?? `Must be at least ${min} characters`\n }),\n maxLength: (max, message) => ({\n type: \"maxLength\",\n args: { max },\n message: message ?? `Must be at most ${max} characters`\n }),\n pattern: (pattern, message = \"Invalid format\") => ({\n type: \"pattern\",\n args: { pattern },\n message\n }),\n min: (min, message) => ({\n type: \"min\",\n args: { min },\n message: message ?? `Must be at least ${min}`\n }),\n max: (max, message) => ({\n type: \"max\",\n args: { max },\n message: message ?? `Must be at most ${max}`\n }),\n url: (message = \"Invalid URL\") => ({\n type: \"url\",\n message\n }),\n numeric: (message = \"Must be a number\") => ({\n type: \"numeric\",\n message\n }),\n matches: (otherPath, message = \"Fields must match\") => ({\n type: \"matches\",\n args: { other: { $state: otherPath } },\n message\n }),\n equalTo: (otherPath, message = \"Fields must match\") => ({\n type: \"equalTo\",\n args: { other: { $state: otherPath } },\n message\n }),\n lessThan: (otherPath, message) => ({\n type: \"lessThan\",\n args: { other: { $state: otherPath } },\n message: message ?? \"Must be less than the compared field\"\n }),\n greaterThan: (otherPath, message) => ({\n type: \"greaterThan\",\n args: { other: { $state: otherPath } },\n message: message ?? \"Must be greater than the compared field\"\n }),\n requiredIf: (fieldPath, message = \"This field is required\") => ({\n type: \"requiredIf\",\n args: { field: { $state: fieldPath } },\n message\n })\n};\n\n// src/spec-validator.ts\nfunction validateSpec(spec, options = {}) {\n const { checkOrphans = false } = options;\n const issues = [];\n if (!spec.root) {\n issues.push({\n severity: \"error\",\n message: \"Spec has no root element defined.\",\n code: \"missing_root\"\n });\n return { valid: false, issues };\n }\n if (!spec.elements[spec.root]) {\n issues.push({\n severity: \"error\",\n message: `Root element \"${spec.root}\" not found in elements map.`,\n code: \"root_not_found\"\n });\n }\n if (Object.keys(spec.elements).length === 0) {\n issues.push({\n severity: \"error\",\n message: \"Spec has no elements.\",\n code: \"empty_spec\"\n });\n return { valid: false, issues };\n }\n for (const [key, element] of Object.entries(spec.elements)) {\n if (element.children) {\n for (const childKey of element.children) {\n if (!spec.elements[childKey]) {\n issues.push({\n severity: \"error\",\n message: `Element \"${key}\" references child \"${childKey}\" which does not exist in the elements map.`,\n elementKey: key,\n code: \"missing_child\"\n });\n }\n }\n }\n const props = element.props;\n if (props && \"visible\" in props && props.visible !== void 0) {\n issues.push({\n severity: \"error\",\n message: `Element \"${key}\" has \"visible\" inside \"props\". It should be a top-level field on the element (sibling of type/props/children).`,\n elementKey: key,\n code: \"visible_in_props\"\n });\n }\n if (props && \"on\" in props && props.on !== void 0) {\n issues.push({\n severity: \"error\",\n message: `Element \"${key}\" has \"on\" inside \"props\". It should be a top-level field on the element (sibling of type/props/children).`,\n elementKey: key,\n code: \"on_in_props\"\n });\n }\n if (props && \"repeat\" in props && props.repeat !== void 0) {\n issues.push({\n severity: \"error\",\n message: `Element \"${key}\" has \"repeat\" inside \"props\". It should be a top-level field on the element (sibling of type/props/children).`,\n elementKey: key,\n code: \"repeat_in_props\"\n });\n }\n if (props && \"watch\" in props && props.watch !== void 0) {\n issues.push({\n severity: \"error\",\n message: `Element \"${key}\" has \"watch\" inside \"props\". It should be a top-level field on the element (sibling of type/props/children).`,\n elementKey: key,\n code: \"watch_in_props\"\n });\n }\n }\n if (checkOrphans) {\n const reachable = /* @__PURE__ */ new Set();\n const walk = (key) => {\n if (reachable.has(key)) return;\n reachable.add(key);\n const el = spec.elements[key];\n if (el?.children) {\n for (const childKey of el.children) {\n if (spec.elements[childKey]) {\n walk(childKey);\n }\n }\n }\n };\n if (spec.elements[spec.root]) {\n walk(spec.root);\n }\n for (const key of Object.keys(spec.elements)) {\n if (!reachable.has(key)) {\n issues.push({\n severity: \"warning\",\n message: `Element \"${key}\" is not reachable from root \"${spec.root}\".`,\n elementKey: key,\n code: \"orphaned_element\"\n });\n }\n }\n }\n const hasErrors = issues.some((i) => i.severity === \"error\");\n return { valid: !hasErrors, issues };\n}\nfunction autoFixSpec(spec) {\n const fixes = [];\n const fixedElements = {};\n for (const [key, element] of Object.entries(spec.elements)) {\n const props = element.props;\n let fixed = element;\n if (props && \"visible\" in props && props.visible !== void 0) {\n const { visible, ...restProps } = fixed.props;\n fixed = {\n ...fixed,\n props: restProps,\n visible\n };\n fixes.push(`Moved \"visible\" from props to element level on \"${key}\".`);\n }\n let currentProps = fixed.props;\n if (currentProps && \"on\" in currentProps && currentProps.on !== void 0) {\n const { on, ...restProps } = currentProps;\n fixed = {\n ...fixed,\n props: restProps,\n on\n };\n fixes.push(`Moved \"on\" from props to element level on \"${key}\".`);\n }\n currentProps = fixed.props;\n if (currentProps && \"repeat\" in currentProps && currentProps.repeat !== void 0) {\n const { repeat, ...restProps } = currentProps;\n fixed = {\n ...fixed,\n props: restProps,\n repeat\n };\n fixes.push(`Moved \"repeat\" from props to element level on \"${key}\".`);\n }\n currentProps = fixed.props;\n if (currentProps && \"watch\" in currentProps && currentProps.watch !== void 0) {\n const { watch, ...restProps } = currentProps;\n fixed = {\n ...fixed,\n props: restProps,\n watch\n };\n fixes.push(`Moved \"watch\" from props to element level on \"${key}\".`);\n }\n fixedElements[key] = fixed;\n }\n return {\n spec: { root: spec.root, elements: fixedElements, state: spec.state },\n fixes\n };\n}\nfunction formatSpecIssues(issues) {\n const errors = issues.filter((i) => i.severity === \"error\");\n if (errors.length === 0) return \"\";\n const lines = [\"The generated UI spec has the following errors:\"];\n for (const issue of errors) {\n lines.push(`- ${issue.message}`);\n }\n return lines.join(\"\\n\");\n}\n\n// src/schema.ts\nimport { z as z4 } from \"zod\";\n\n// src/edit-modes.ts\nvar DEFAULT_MODES = [\"patch\"];\nfunction normalizeModes(config) {\n if (!config?.modes?.length) return DEFAULT_MODES;\n return config.modes;\n}\nfunction jsonPatchInstructions() {\n return [\n \"PATCH MODE (RFC 6902 JSON Patch):\",\n \"Output one JSON object per line. Each line is a patch operation.\",\n '- Add: {\"op\":\"add\",\"path\":\"/elements/new-key\",\"value\":{...}}',\n '- Replace: {\"op\":\"replace\",\"path\":\"/elements/existing-key\",\"value\":{...}}',\n '- Remove: {\"op\":\"remove\",\"path\":\"/elements/old-key\"}',\n \"Only output patches for what needs to change.\"\n ].join(\"\\n\");\n}\nfunction jsonMergeInstructions() {\n return [\n \"MERGE MODE (RFC 7396 JSON Merge Patch):\",\n \"Output a single JSON object on one line with __json_edit set to true.\",\n \"Include only the keys that changed. Unmentioned keys are preserved.\",\n \"Set a key to null to delete it.\",\n \"\",\n \"Example (update a title and add an element):\",\n '{\"__json_edit\":true,\"elements\":{\"main\":{\"props\":{\"title\":\"New Title\"}},\"new-el\":{\"type\":\"Card\",\"props\":{},\"children\":[]}}}',\n \"\",\n \"Example (delete an element):\",\n '{\"__json_edit\":true,\"elements\":{\"old-widget\":null}}'\n ].join(\"\\n\");\n}\nfunction jsonDiffInstructions() {\n return [\n \"DIFF MODE (unified diff):\",\n \"Output a unified diff inside a ```diff code fence.\",\n \"The diff applies against the JSON-serialized current spec.\",\n \"\",\n \"Example:\",\n \"```diff\",\n \"--- a/spec.json\",\n \"+++ b/spec.json\",\n \"@@ -3,1 +3,1 @@\",\n '- \"title\": \"Login\"',\n '+ \"title\": \"Welcome Back\"',\n \"```\"\n ].join(\"\\n\");\n}\nfunction yamlPatchInstructions() {\n return [\n \"PATCH MODE (RFC 6902 JSON Patch):\",\n \"Output RFC 6902 JSON Patch lines inside a ```yaml-patch code fence.\",\n \"Each line is one JSON patch operation.\",\n \"\",\n \"Example:\",\n \"```yaml-patch\",\n '{\"op\":\"replace\",\"path\":\"/elements/main/props/title\",\"value\":\"New Title\"}',\n '{\"op\":\"add\",\"path\":\"/elements/new-el\",\"value\":{\"type\":\"Card\",\"props\":{},\"children\":[]}}',\n \"```\"\n ].join(\"\\n\");\n}\nfunction yamlMergeInstructions() {\n return [\n \"MERGE MODE (RFC 7396 JSON Merge Patch):\",\n \"Output only the changed parts in a ```yaml-edit code fence.\",\n \"Uses deep merge semantics: only keys you include are updated. Unmentioned elements and props are preserved.\",\n \"Set a key to null to delete it.\",\n \"\",\n \"Example edit (update title, add a new element):\",\n \"```yaml-edit\",\n \"elements:\",\n \" main:\",\n \" props:\",\n \" title: Updated Title\",\n \" new-chart:\",\n \" type: Card\",\n \" props: {}\",\n \" children: []\",\n \"```\",\n \"\",\n \"Example deletion:\",\n \"```yaml-edit\",\n \"elements:\",\n \" old-widget: null\",\n \"```\"\n ].join(\"\\n\");\n}\nfunction yamlDiffInstructions() {\n return [\n \"DIFF MODE (unified diff):\",\n \"Output a unified diff inside a ```diff code fence.\",\n \"The diff applies against the YAML-serialized current spec.\",\n \"\",\n \"Example:\",\n \"```diff\",\n \"--- a/spec.yaml\",\n \"+++ b/spec.yaml\",\n \"@@ -6,1 +6,1 @@\",\n \"- title: Login\",\n \"+ title: Welcome Back\",\n \"```\"\n ].join(\"\\n\");\n}\nfunction modeSelectionGuidance(modes) {\n if (modes.length === 1) return \"\";\n const parts = [\"Choose the best edit strategy for the requested change:\"];\n if (modes.includes(\"patch\")) {\n parts.push(\"- PATCH: best for precise, targeted single-field updates\");\n }\n if (modes.includes(\"merge\")) {\n parts.push(\n \"- MERGE: best for structural changes (add/remove elements, reparent children, update multiple props at once)\"\n );\n }\n if (modes.includes(\"diff\")) {\n parts.push(\n \"- DIFF: best for small text-level changes when you can see the exact lines to change\"\n );\n }\n return parts.join(\"\\n\");\n}\nfunction buildEditInstructions(config, format) {\n const modes = normalizeModes(config);\n const sections = [];\n sections.push(\"EDITING EXISTING SPECS:\");\n sections.push(\"\");\n const guidance = modeSelectionGuidance(modes);\n if (guidance) {\n sections.push(guidance);\n sections.push(\"\");\n }\n for (const mode of modes) {\n if (format === \"json\") {\n switch (mode) {\n case \"patch\":\n sections.push(jsonPatchInstructions());\n break;\n case \"merge\":\n sections.push(jsonMergeInstructions());\n break;\n case \"diff\":\n sections.push(jsonDiffInstructions());\n break;\n }\n } else {\n switch (mode) {\n case \"patch\":\n sections.push(yamlPatchInstructions());\n break;\n case \"merge\":\n sections.push(yamlMergeInstructions());\n break;\n case \"diff\":\n sections.push(yamlDiffInstructions());\n break;\n }\n }\n sections.push(\"\");\n }\n return sections.join(\"\\n\");\n}\nfunction addLineNumbers(text) {\n const lines = text.split(\"\\n\");\n const width = String(lines.length).length;\n return lines.map((line, i) => `${String(i + 1).padStart(width)}| ${line}`).join(\"\\n\");\n}\nfunction isNonEmptySpec(spec) {\n if (!spec || typeof spec !== \"object\") return false;\n const s = spec;\n return typeof s.root === \"string\" && typeof s.elements === \"object\" && s.elements !== null && Object.keys(s.elements).length > 0;\n}\nfunction buildEditUserPrompt(options) {\n const { prompt, currentSpec, config, format, maxPromptLength, serializer } = options;\n let userText = String(prompt || \"\");\n if (maxPromptLength !== void 0 && maxPromptLength > 0) {\n userText = userText.slice(0, maxPromptLength);\n }\n if (!isNonEmptySpec(currentSpec)) {\n return userText;\n }\n const modes = normalizeModes(config);\n const showLineNumbers = modes.includes(\"diff\");\n const serialize = serializer ?? ((s) => JSON.stringify(s, null, 2));\n const specText = serialize(currentSpec);\n const parts = [];\n if (showLineNumbers) {\n parts.push(\"CURRENT UI STATE (line numbers for reference):\");\n parts.push(\"```\");\n parts.push(addLineNumbers(specText));\n parts.push(\"```\");\n } else {\n parts.push(\n \"CURRENT UI STATE (already loaded, DO NOT recreate existing elements):\"\n );\n parts.push(\"```\");\n parts.push(specText);\n parts.push(\"```\");\n }\n parts.push(\"\");\n parts.push(`USER REQUEST: ${userText}`);\n parts.push(\"\");\n if (modes.length === 1) {\n const mode = modes[0];\n switch (mode) {\n case \"patch\":\n parts.push(\n format === \"yaml\" ? \"Output ONLY the patches in a ```yaml-patch fence.\" : \"Output ONLY the JSON Patch lines needed for the change.\"\n );\n break;\n case \"merge\":\n parts.push(\n format === \"yaml\" ? \"Output ONLY the changes in a ```yaml-edit fence. Include only keys that need to change.\" : \"Output ONLY a single JSON merge line with __json_edit set to true. Include only keys that need to change.\"\n );\n break;\n case \"diff\":\n parts.push(\"Output ONLY the unified diff in a ```diff fence.\");\n break;\n }\n } else {\n const modeNames = modes.map((m) => {\n switch (m) {\n case \"patch\":\n return format === \"yaml\" ? \"```yaml-patch fence\" : \"JSON Patch lines\";\n case \"merge\":\n return format === \"yaml\" ? \"```yaml-edit fence\" : \"JSON merge line (__json_edit)\";\n case \"diff\":\n return \"```diff fence\";\n }\n });\n parts.push(\n `Choose the best edit strategy and output using one of: ${modeNames.join(\", \")}`\n );\n }\n return parts.join(\"\\n\");\n}\n\n// src/schema.ts\nfunction createBuilder() {\n return {\n string: () => ({ kind: \"string\" }),\n number: () => ({ kind: \"number\" }),\n boolean: () => ({ kind: \"boolean\" }),\n array: (item) => ({ kind: \"array\", inner: item }),\n object: (shape) => ({ kind: \"object\", inner: shape }),\n record: (value) => ({ kind: \"record\", inner: value }),\n any: () => ({ kind: \"any\" }),\n zod: () => ({ kind: \"zod\" }),\n ref: (path) => ({ kind: \"ref\", inner: path }),\n propsOf: (path) => ({ kind: \"propsOf\", inner: path }),\n map: (entryShape) => ({ kind: \"map\", inner: entryShape }),\n optional: () => ({ optional: true })\n };\n}\nfunction defineSchema(builder, options) {\n const s = createBuilder();\n const definition = builder(s);\n return {\n definition,\n promptTemplate: options?.promptTemplate,\n defaultRules: options?.defaultRules,\n builtInActions: options?.builtInActions,\n createCatalog(catalog) {\n return createCatalogFromSchema(this, catalog);\n }\n };\n}\nfunction createCatalogFromSchema(schema, catalogData) {\n const components = catalogData.components;\n const actions = catalogData.actions;\n const componentNames = components ? Object.keys(components) : [];\n const actionNames = actions ? Object.keys(actions) : [];\n const zodSchema = buildZodSchemaFromDefinition(\n schema.definition,\n catalogData\n );\n return {\n schema,\n data: catalogData,\n componentNames,\n actionNames,\n prompt(options = {}) {\n return generatePrompt(this, options);\n },\n jsonSchema(options = {}) {\n return zodToJsonSchema(zodSchema, options.strict ?? false);\n },\n validate(spec) {\n const result = zodSchema.safeParse(spec);\n if (result.success) {\n return {\n success: true,\n data: result.data\n };\n }\n return { success: false, error: result.error };\n },\n zodSchema() {\n return zodSchema;\n },\n get _specType() {\n throw new Error(\"_specType is only for type inference\");\n }\n };\n}\nfunction buildZodSchemaFromDefinition(definition, catalogData) {\n return buildZodType(definition.spec, catalogData);\n}\nfunction buildZodType(schemaType, catalogData) {\n switch (schemaType.kind) {\n case \"string\":\n return z4.string();\n case \"number\":\n return z4.number();\n case \"boolean\":\n return z4.boolean();\n case \"any\":\n return z4.any();\n case \"array\": {\n const inner = buildZodType(schemaType.inner, catalogData);\n return z4.array(inner);\n }\n case \"object\": {\n const shape = schemaType.inner;\n const zodShape = {};\n for (const [key, value] of Object.entries(shape)) {\n let zodType = buildZodType(value, catalogData);\n if (value.optional) {\n zodType = zodType.optional();\n }\n zodShape[key] = zodType;\n }\n return z4.object(zodShape);\n }\n case \"record\": {\n const inner = buildZodType(schemaType.inner, catalogData);\n return z4.record(z4.string(), inner);\n }\n case \"ref\": {\n const path = schemaType.inner;\n const keys = getKeysFromPath(path, catalogData);\n if (keys.length === 0) {\n return z4.string();\n }\n if (keys.length === 1) {\n return z4.literal(keys[0]);\n }\n return z4.enum(keys);\n }\n case \"propsOf\": {\n const path = schemaType.inner;\n const propsSchemas = getPropsFromPath(path, catalogData);\n if (propsSchemas.length === 0) {\n return z4.record(z4.string(), z4.unknown());\n }\n if (propsSchemas.length === 1) {\n return propsSchemas[0];\n }\n return z4.record(z4.string(), z4.unknown());\n }\n default:\n return z4.unknown();\n }\n}\nfunction getKeysFromPath(path, catalogData) {\n const parts = path.split(\".\");\n let current = { catalog: catalogData };\n for (const part of parts) {\n if (current && typeof current === \"object\") {\n current = current[part];\n } else {\n return [];\n }\n }\n if (current && typeof current === \"object\") {\n return Object.keys(current);\n }\n return [];\n}\nfunction getPropsFromPath(path, catalogData) {\n const parts = path.split(\".\");\n let current = { catalog: catalogData };\n for (const part of parts) {\n if (current && typeof current === \"object\") {\n current = current[part];\n } else {\n return [];\n }\n }\n if (current && typeof current === \"object\") {\n return Object.values(current).map((entry) => entry.props).filter((props) => props !== void 0);\n }\n return [];\n}\nfunction generatePrompt(catalog, options) {\n if (catalog.schema.promptTemplate) {\n const context = {\n catalog: catalog.data,\n componentNames: catalog.componentNames,\n actionNames: catalog.actionNames,\n options,\n formatZodType\n };\n return catalog.schema.promptTemplate(context);\n }\n const {\n system = \"You are a UI generator that outputs JSON.\",\n customRules = [],\n mode: rawMode = \"standalone\"\n } = options;\n const mode = rawMode === \"chat\" ? (console.warn(\n '[json-render] mode \"chat\" is deprecated, use \"inline\" instead'\n ), \"inline\") : rawMode === \"generate\" ? (console.warn(\n '[json-render] mode \"generate\" is deprecated, use \"standalone\" instead'\n ), \"standalone\") : rawMode;\n const lines = [];\n lines.push(system);\n lines.push(\"\");\n if (mode === \"inline\") {\n lines.push(\"OUTPUT FORMAT (text + JSONL, RFC 6902 JSON Patch):\");\n lines.push(\n \"You respond conversationally. When generating UI, first write a brief explanation (1-3 sentences), then output JSONL patch lines wrapped in a ```spec code fence.\"\n );\n lines.push(\n \"The JSONL lines use RFC 6902 JSON Patch operations to build a UI tree. Always wrap them in a ```spec fence block:\"\n );\n lines.push(\" ```spec\");\n lines.push(' {\"op\":\"add\",\"path\":\"/root\",\"value\":\"main\"}');\n lines.push(\n ' {\"op\":\"add\",\"path\":\"/elements/main\",\"value\":{\"type\":\"Card\",\"props\":{\"title\":\"Hello\"},\"children\":[]}}'\n );\n lines.push(\" ```\");\n lines.push(\n \"If the user's message does not require a UI (e.g. a greeting or clarifying question), respond with text only \\u2014 no JSONL.\"\n );\n } else {\n lines.push(\"OUTPUT FORMAT (JSONL, RFC 6902 JSON Patch):\");\n lines.push(\n \"Output JSONL (one JSON object per line) using RFC 6902 JSON Patch operations to build a UI tree.\"\n );\n }\n lines.push(\n \"Each line is a JSON patch operation (add, remove, replace). Start with /root, then stream /elements and /state patches interleaved so the UI fills in progressively as it streams.\"\n );\n lines.push(\"\");\n lines.push(\"Example output (each line is a separate JSON object):\");\n lines.push(\"\");\n const allComponents = catalog.data.components;\n const cn = catalog.componentNames;\n const comp1 = cn[0] || \"Component\";\n const comp2 = cn.length > 1 ? cn[1] : comp1;\n const comp1Def = allComponents?.[comp1];\n const comp2Def = allComponents?.[comp2];\n const comp1Props = comp1Def ? getExampleProps(comp1Def) : {};\n const comp2Props = comp2Def ? getExampleProps(comp2Def) : {};\n const dynamicPropName = comp2Def?.props ? findFirstStringProp(comp2Def.props) : null;\n const dynamicProps = dynamicPropName ? { ...comp2Props, [dynamicPropName]: { $item: \"title\" } } : comp2Props;\n const exampleOutput = [\n JSON.stringify({ op: \"add\", path: \"/root\", value: \"main\" }),\n JSON.stringify({\n op: \"add\",\n path: \"/elements/main\",\n value: {\n type: comp1,\n props: comp1Props,\n children: [\"child-1\", \"list\"]\n }\n }),\n JSON.stringify({\n op: \"add\",\n path: \"/elements/child-1\",\n value: { type: comp2, props: comp2Props, children: [] }\n }),\n JSON.stringify({\n op: \"add\",\n path: \"/elements/list\",\n value: {\n type: comp1,\n props: comp1Props,\n repeat: { statePath: \"/items\", key: \"id\" },\n children: [\"item\"]\n }\n }),\n JSON.stringify({\n op: \"add\",\n path: \"/elements/item\",\n value: { type: comp2, props: dynamicProps, children: [] }\n }),\n JSON.stringify({ op: \"add\", path: \"/state/items\", value: [] }),\n JSON.stringify({\n op: \"add\",\n path: \"/state/items/0\",\n value: { id: \"1\", title: \"First Item\" }\n }),\n JSON.stringify({\n op: \"add\",\n path: \"/state/items/1\",\n value: { id: \"2\", title: \"Second Item\" }\n })\n ].join(\"\\n\");\n lines.push(`${exampleOutput}\n\nNote: state patches appear right after the elements that use them, so the UI fills in as it streams. ONLY use component types from the AVAILABLE COMPONENTS list below.`);\n lines.push(\"\");\n lines.push(\"INITIAL STATE:\");\n lines.push(\n \"Specs include a /state field to seed the state model. Components with { $bindState } or { $bindItem } read from and write to this state, and $state expressions read from it.\"\n );\n lines.push(\n \"CRITICAL: You MUST include state patches whenever your UI displays data via $state, $bindState, $bindItem, $item, or $index expressions, or uses repeat to iterate over arrays. Without state, these references resolve to nothing and repeat lists render zero items.\"\n );\n lines.push(\n \"Output state patches right after the elements that reference them, so the UI fills in progressively as it streams.\"\n );\n lines.push(\n \"Stream state progressively - output one patch per array item instead of one giant blob:\"\n );\n lines.push(\n ' For arrays: {\"op\":\"add\",\"path\":\"/state/posts/0\",\"value\":{\"id\":\"1\",\"title\":\"First Post\",...}} then /state/posts/1, /state/posts/2, etc.'\n );\n lines.push(\n ' For scalars: {\"op\":\"add\",\"path\":\"/state/newTodoText\",\"value\":\"\"}'\n );\n lines.push(\n ' Initialize the array first if needed: {\"op\":\"add\",\"path\":\"/state/posts\",\"value\":[]}'\n );\n lines.push(\n 'When content comes from the state model, use { \"$state\": \"/some/path\" } dynamic props to display it instead of hardcoding the same value in both state and props. The state model is the single source of truth.'\n );\n lines.push(\n \"Include realistic sample data in state. For blogs: 3-4 posts with titles, excerpts, authors, dates. For product lists: 3-5 items with names, prices, descriptions. Never leave arrays empty.\"\n );\n lines.push(\"\");\n lines.push(\"DYNAMIC LISTS (repeat field):\");\n lines.push(\n 'Any element can have a top-level \"repeat\" field to render its children once per item in a state array: { \"repeat\": { \"statePath\": \"/arrayPath\", \"key\": \"id\" } }.'\n );\n lines.push(\n 'The element itself renders once (as the container), and its children are expanded once per array item. \"statePath\" is the state array path. \"key\" is an optional field name on each item for stable React keys.'\n );\n lines.push(\n `Example: ${JSON.stringify({ type: comp1, props: comp1Props, repeat: { statePath: \"/todos\", key: \"id\" }, children: [\"todo-item\"] })}`\n );\n lines.push(\n 'Inside children of a repeated element, use { \"$item\": \"field\" } to read a field from the current item, and { \"$index\": true } to get the current array index. For two-way binding to an item field use { \"$bindItem\": \"completed\" } on the appropriate prop.'\n );\n lines.push(\n \"ALWAYS use the repeat field for lists backed by state arrays. NEVER hardcode individual elements for each array item.\"\n );\n lines.push(\n 'IMPORTANT: \"repeat\" is a top-level field on the element (sibling of type/props/children), NOT inside props.'\n );\n lines.push(\"\");\n lines.push(\"ARRAY STATE ACTIONS:\");\n lines.push(\n 'Use action \"pushState\" to append items to arrays. Params: { statePath: \"/arrayPath\", value: { ...item }, clearStatePath: \"/inputPath\" }.'\n );\n lines.push(\n 'Values inside pushState can contain { \"$state\": \"/statePath\" } references to read current state (e.g. the text from an input field).'\n );\n lines.push(\n 'Use \"$id\" inside a pushState value to auto-generate a unique ID.'\n );\n lines.push(\n 'Example: on: { \"press\": { \"action\": \"pushState\", \"params\": { \"statePath\": \"/todos\", \"value\": { \"id\": \"$id\", \"title\": { \"$state\": \"/newTodoText\" }, \"completed\": false }, \"clearStatePath\": \"/newTodoText\" } } }'\n );\n lines.push(\n `Use action \"removeState\" to remove items from arrays by index. Params: { statePath: \"/arrayPath\", index: N }. Inside a repeated element's children, use { \"$index\": true } for the current item index. Action params support the same expressions as props: { \"$item\": \"field\" } resolves to the absolute state path, { \"$index\": true } resolves to the index number, and { \"$state\": \"/path\" } reads a value from state.`\n );\n lines.push(\n \"For lists where users can add/remove items (todos, carts, etc.), use pushState and removeState instead of hardcoding with setState.\"\n );\n lines.push(\"\");\n lines.push(\n 'IMPORTANT: State paths use RFC 6901 JSON Pointer syntax (e.g. \"/todos/0/title\"). Do NOT use JavaScript-style dot notation (e.g. \"/todos.length\" is WRONG). To generate unique IDs for new items, use \"$id\" instead of trying to read array length.'\n );\n lines.push(\"\");\n const components = allComponents;\n if (components) {\n lines.push(`AVAILABLE COMPONENTS (${catalog.componentNames.length}):`);\n lines.push(\"\");\n for (const [name, def] of Object.entries(components)) {\n const propsStr = def.props ? formatZodType(def.props) : \"{}\";\n const hasChildren = def.slots && def.slots.length > 0;\n const childrenStr = hasChildren ? \" [accepts children]\" : \"\";\n const eventsStr = def.events && def.events.length > 0 ? ` [events: ${def.events.join(\", \")}]` : \"\";\n const descStr = def.description ? ` - ${def.description}` : \"\";\n lines.push(`- ${name}: ${propsStr}${descStr}${childrenStr}${eventsStr}`);\n }\n lines.push(\"\");\n }\n const actions = catalog.data.actions;\n const builtInActions = catalog.schema.builtInActions ?? [];\n const hasCustomActions = actions && catalog.actionNames.length > 0;\n const hasBuiltInActions = builtInActions.length > 0;\n if (hasCustomActions || hasBuiltInActions) {\n lines.push(\"AVAILABLE ACTIONS:\");\n lines.push(\"\");\n for (const action2 of builtInActions) {\n lines.push(`- ${action2.name}: ${action2.description} [built-in]`);\n }\n if (hasCustomActions) {\n for (const [name, def] of Object.entries(actions)) {\n lines.push(`- ${name}${def.description ? `: ${def.description}` : \"\"}`);\n }\n }\n lines.push(\"\");\n }\n lines.push(\"EVENTS (the `on` field):\");\n lines.push(\n \"Elements can have an optional `on` field to bind events to actions. The `on` field is a top-level field on the element (sibling of type/props/children), NOT inside props.\"\n );\n lines.push(\n 'Each key in `on` is an event name (from the component\\'s supported events), and the value is an action binding: `{ \"action\": \"<actionName>\", \"params\": { ... } }`.'\n );\n lines.push(\"\");\n lines.push(\"Example:\");\n lines.push(\n ` ${JSON.stringify({ type: comp1, props: comp1Props, on: { press: { action: \"setState\", params: { statePath: \"/saved\", value: true } } }, children: [] })}`\n );\n lines.push(\"\");\n lines.push(\n 'Action params can use dynamic references to read from state: { \"$state\": \"/statePath\" }.'\n );\n lines.push(\n \"IMPORTANT: Do NOT put action/actionParams inside props. Always use the `on` field for event bindings.\"\n );\n lines.push(\"\");\n lines.push(\"VISIBILITY CONDITIONS:\");\n lines.push(\n \"Elements can have an optional `visible` field to conditionally show/hide based on state. IMPORTANT: `visible` is a top-level field on the element object (sibling of type/props/children), NOT inside props.\"\n );\n lines.push(\n `Correct: ${JSON.stringify({ type: comp1, props: comp1Props, visible: { $state: \"/activeTab\", eq: \"home\" }, children: [\"...\"] })}`\n );\n lines.push(\n '- `{ \"$state\": \"/path\" }` - visible when state at path is truthy'\n );\n lines.push(\n '- `{ \"$state\": \"/path\", \"not\": true }` - visible when state at path is falsy'\n );\n lines.push(\n '- `{ \"$state\": \"/path\", \"eq\": \"value\" }` - visible when state equals value'\n );\n lines.push(\n '- `{ \"$state\": \"/path\", \"neq\": \"value\" }` - visible when state does not equal value'\n );\n lines.push(\n '- `{ \"$state\": \"/path\", \"gt\": N }` / `gte` / `lt` / `lte` - numeric comparisons'\n );\n lines.push(\n \"- Use ONE operator per condition (eq, neq, gt, gte, lt, lte). Do not combine multiple operators.\"\n );\n lines.push('- Any condition can add `\"not\": true` to invert its result');\n lines.push(\n \"- `[condition, condition]` - all conditions must be true (implicit AND)\"\n );\n lines.push(\n '- `{ \"$and\": [condition, condition] }` - explicit AND (use when nesting inside $or)'\n );\n lines.push(\n '- `{ \"$or\": [condition, condition] }` - at least one must be true (OR)'\n );\n lines.push(\"- `true` / `false` - always visible/hidden\");\n lines.push(\"\");\n lines.push(\n \"Use a component with on.press bound to setState to update state and drive visibility.\"\n );\n lines.push(\n `Example: A ${comp1} with on: { \"press\": { \"action\": \"setState\", \"params\": { \"statePath\": \"/activeTab\", \"value\": \"home\" } } } sets state, then a container with visible: { \"$state\": \"/activeTab\", \"eq\": \"home\" } shows only when that tab is active.`\n );\n lines.push(\"\");\n lines.push(\n 'For tab patterns where the first/default tab should be visible when no tab is selected yet, use $or to handle both cases: visible: { \"$or\": [{ \"$state\": \"/activeTab\", \"eq\": \"home\" }, { \"$state\": \"/activeTab\", \"not\": true }] }. This ensures the first tab is visible both when explicitly selected AND when /activeTab is not yet set.'\n );\n lines.push(\"\");\n lines.push(\"DYNAMIC PROPS:\");\n lines.push(\n \"Any prop value can be a dynamic expression that resolves based on state. Three forms are supported:\"\n );\n lines.push(\"\");\n lines.push(\n '1. Read-only state: `{ \"$state\": \"/statePath\" }` - resolves to the value at that state path (one-way read).'\n );\n lines.push(\n ' Example: `\"color\": { \"$state\": \"/theme/primary\" }` reads the color from state.'\n );\n lines.push(\"\");\n lines.push(\n '2. Two-way binding: `{ \"$bindState\": \"/statePath\" }` - resolves to the value at the state path AND enables write-back. Use on form input props (value, checked, pressed, etc.).'\n );\n lines.push(\n ' Example: `\"value\": { \"$bindState\": \"/form/email\" }` binds the input value to /form/email.'\n );\n lines.push(\n ' Inside repeat scopes: `\"checked\": { \"$bindItem\": \"completed\" }` binds to the current item\\'s completed field.'\n );\n lines.push(\"\");\n lines.push(\n '3. Conditional: `{ \"$cond\": <condition>, \"$then\": <value>, \"$else\": <value> }` - evaluates the condition (same syntax as visibility conditions) and picks the matching value.'\n );\n lines.push(\n ' Example: `\"color\": { \"$cond\": { \"$state\": \"/activeTab\", \"eq\": \"home\" }, \"$then\": \"#007AFF\", \"$else\": \"#8E8E93\" }`'\n );\n lines.push(\"\");\n lines.push(\n \"Use $bindState for form inputs (text fields, checkboxes, selects, sliders, etc.) and $state for read-only data display. Inside repeat scopes, use $bindItem for form inputs bound to the current item. Use dynamic props instead of duplicating elements with opposing visible conditions when only prop values differ.\"\n );\n lines.push(\"\");\n lines.push(\n '4. Template: `{ \"$template\": \"Hello, ${/name}!\" }` - interpolates references in the string. Absolute paths like `${/path}` resolve against the state model. Bare names like `${field}` resolve against the current repeat item first, then fall back to the state model at `/<field>`.'\n );\n lines.push(\n ' Example: `\"label\": { \"$template\": \"Items: ${/cart/count} | Total: ${/cart/total}\" }` renders \"Items: 3 | Total: 42.00\" when /cart/count is 3 and /cart/total is 42.00. Inside a repeat, `{ \"$template\": \"${name} - ${email}\" }` reads name and email from each item.'\n );\n lines.push(\"\");\n const catalogFunctions = catalog.data.functions;\n if (catalogFunctions && Object.keys(catalogFunctions).length > 0) {\n lines.push(\n '5. Computed: `{ \"$computed\": \"<functionName>\", \"args\": { \"key\": <expression> } }` - calls a registered function with resolved args and returns the result.'\n );\n lines.push(\n ' Example: `\"value\": { \"$computed\": \"fullName\", \"args\": { \"first\": { \"$state\": \"/form/firstName\" }, \"last\": { \"$state\": \"/form/lastName\" } } }`'\n );\n lines.push(\" Available functions:\");\n for (const name of Object.keys(\n catalogFunctions\n )) {\n lines.push(` - ${name}`);\n }\n lines.push(\"\");\n }\n const directives = options.directives;\n if (directives && directives.length > 0) {\n lines.push(\"CUSTOM DYNAMIC VALUES:\");\n lines.push(\"\");\n for (const d of directives) {\n const desc = d.description ? ` (${d.description})` : \"\";\n lines.push(`- ${d.name}${desc}: ${formatZodType(d.schema)}`);\n }\n lines.push(\"\");\n lines.push(\n \"Directives compose: any value field can contain another directive or a $state expression, resolved inside-out.\"\n );\n lines.push(\"\");\n }\n const hasChecksComponents = allComponents ? Object.entries(allComponents).some(([, def]) => {\n if (!def.props) return false;\n const formatted = formatZodType(def.props);\n return formatted.includes(\"checks\");\n }) : false;\n if (hasChecksComponents) {\n lines.push(\"VALIDATION:\");\n lines.push(\n \"Form components that accept a `checks` prop support client-side validation.\"\n );\n lines.push(\n 'Each check is an object: { \"type\": \"<name>\", \"message\": \"...\", \"args\": { ... } }'\n );\n lines.push(\"\");\n lines.push(\"Built-in validation types:\");\n lines.push(\" - required \\u2014 value must be non-empty\");\n lines.push(\" - email \\u2014 valid email format\");\n lines.push(' - minLength \\u2014 minimum string length (args: { \"min\": N })');\n lines.push(' - maxLength \\u2014 maximum string length (args: { \"max\": N })');\n lines.push(' - pattern \\u2014 match a regex (args: { \"pattern\": \"regex\" })');\n lines.push(' - min \\u2014 minimum numeric value (args: { \"min\": N })');\n lines.push(' - max \\u2014 maximum numeric value (args: { \"max\": N })');\n lines.push(\" - numeric \\u2014 value must be a number\");\n lines.push(\" - url \\u2014 valid URL format\");\n lines.push(\n ' - matches \\u2014 must equal another field (args: { \"other\": { \"$state\": \"/path\" } })'\n );\n lines.push(\n ' - equalTo \\u2014 alias for matches (args: { \"other\": { \"$state\": \"/path\" } })'\n );\n lines.push(\n ' - lessThan \\u2014 value must be less than another field (args: { \"other\": { \"$state\": \"/path\" } })'\n );\n lines.push(\n ' - greaterThan \\u2014 value must be greater than another field (args: { \"other\": { \"$state\": \"/path\" } })'\n );\n lines.push(\n ' - requiredIf \\u2014 required only when another field is truthy (args: { \"field\": { \"$state\": \"/path\" } })'\n );\n lines.push(\"\");\n lines.push(\"Example:\");\n lines.push(\n ' \"checks\": [{ \"type\": \"required\", \"message\": \"Email is required\" }, { \"type\": \"email\", \"message\": \"Invalid email\" }]'\n );\n lines.push(\"\");\n lines.push(\n \"IMPORTANT: When using checks, the component must also have a { $bindState } or { $bindItem } on its value/checked prop for two-way binding.\"\n );\n lines.push(\n \"Always include validation checks on form inputs for a good user experience (e.g. required, email, minLength).\"\n );\n lines.push(\"\");\n }\n if (hasCustomActions || hasBuiltInActions) {\n lines.push(\"STATE WATCHERS:\");\n lines.push(\n \"Elements can have an optional `watch` field to react to state changes and trigger actions. The `watch` field is a top-level field on the element (sibling of type/props/children), NOT inside props.\"\n );\n lines.push(\n \"Maps state paths (JSON Pointers) to action bindings. When the value at a watched path changes, the bound actions fire automatically.\"\n );\n lines.push(\"\");\n lines.push(\n \"Example (cascading select \\u2014 country changes trigger city loading):\"\n );\n lines.push(\n ` ${JSON.stringify({ type: \"Select\", props: { value: { $bindState: \"/form/country\" }, options: [\"US\", \"Canada\", \"UK\"] }, watch: { \"/form/country\": { action: \"loadCities\", params: { country: { $state: \"/form/country\" } } } }, children: [] })}`\n );\n lines.push(\"\");\n lines.push(\n \"Use `watch` for cascading dependencies where changing one field should trigger side effects (loading data, resetting dependent fields, computing derived values).\"\n );\n lines.push(\n \"IMPORTANT: `watch` is a top-level field on the element (sibling of type/props/children), NOT inside props. Watchers only fire when the value changes, not on initial render.\"\n );\n lines.push(\"\");\n }\n const editModes = options.editModes;\n if (editModes && editModes.length > 0) {\n lines.push(buildEditInstructions({ modes: editModes }, \"json\"));\n }\n lines.push(\"RULES:\");\n const baseRules = mode === \"inline\" ? [\n \"When generating UI, wrap all JSONL patches in a ```spec code fence - one JSON object per line inside the fence\",\n \"Write a brief conversational response before any JSONL output\",\n 'First set root: {\"op\":\"add\",\"path\":\"/root\",\"value\":\"<root-key>\"}',\n 'Then add each element: {\"op\":\"add\",\"path\":\"/elements/<key>\",\"value\":{...}}',\n \"Output /state patches right after the elements that use them, one per array item for progressive loading. REQUIRED whenever using $state, $bindState, $bindItem, $item, $index, or repeat.\",\n \"ONLY use components listed above\",\n \"Each element value needs: type, props, children (array of child keys)\",\n \"Use unique keys for the element map entries (e.g., 'header', 'metric-1', 'chart-revenue')\"\n ] : [\n \"Output ONLY JSONL patches - one JSON object per line, no markdown, no code fences\",\n 'First set root: {\"op\":\"add\",\"path\":\"/root\",\"value\":\"<root-key>\"}',\n 'Then add each element: {\"op\":\"add\",\"path\":\"/elements/<key>\",\"value\":{...}}',\n \"Output /state patches right after the elements that use them, one per array item for progressive loading. REQUIRED whenever using $state, $bindState, $bindItem, $item, $index, or repeat.\",\n \"ONLY use components listed above\",\n \"Each element value needs: type, props, children (array of child keys)\",\n \"Use unique keys for the element map entries (e.g., 'header', 'metric-1', 'chart-revenue')\"\n ];\n const schemaRules = catalog.schema.defaultRules ?? [];\n const allRules = [...baseRules, ...schemaRules, ...customRules];\n allRules.forEach((rule, i) => {\n lines.push(`${i + 1}. ${rule}`);\n });\n return lines.join(\"\\n\");\n}\nfunction getExampleProps(def) {\n if (def.example && Object.keys(def.example).length > 0) {\n return def.example;\n }\n if (def.props) {\n return generateExamplePropsFromZod(def.props);\n }\n return {};\n}\nfunction generateExamplePropsFromZod(schema) {\n if (!schema || !schema._def) return {};\n const def = schema._def;\n const typeName = getZodTypeName(schema);\n if (typeName !== \"ZodObject\" && typeName !== \"object\") return {};\n const shape = typeof def.shape === \"function\" ? def.shape() : def.shape;\n if (!shape) return {};\n const result = {};\n for (const [key, value] of Object.entries(shape)) {\n const innerTypeName = getZodTypeName(value);\n if (innerTypeName === \"ZodOptional\" || innerTypeName === \"optional\" || innerTypeName === \"ZodNullable\" || innerTypeName === \"nullable\") {\n continue;\n }\n result[key] = generateExampleValue(value);\n }\n return result;\n}\nfunction generateExampleValue(schema) {\n if (!schema || !schema._def) return \"...\";\n const def = schema._def;\n const typeName = getZodTypeName(schema);\n switch (typeName) {\n case \"ZodString\":\n case \"string\":\n return \"example\";\n case \"ZodNumber\":\n case \"number\":\n return 0;\n case \"ZodBoolean\":\n case \"boolean\":\n return true;\n case \"ZodLiteral\":\n case \"literal\":\n return def.value;\n case \"ZodEnum\":\n case \"enum\": {\n if (Array.isArray(def.values) && def.values.length > 0)\n return def.values[0];\n if (def.entries && typeof def.entries === \"object\") {\n const values = Object.values(def.entries);\n return values.length > 0 ? values[0] : \"example\";\n }\n return \"example\";\n }\n case \"ZodOptional\":\n case \"optional\":\n case \"ZodNullable\":\n case \"nullable\":\n case \"ZodDefault\":\n case \"default\": {\n const inner = def.innerType ?? def.wrapped;\n return inner ? generateExampleValue(inner) : null;\n }\n case \"ZodArray\":\n case \"array\":\n return [];\n case \"ZodObject\":\n case \"object\":\n return generateExamplePropsFromZod(schema);\n case \"ZodUnion\":\n case \"union\": {\n const options = def.options;\n return options && options.length > 0 ? generateExampleValue(options[0]) : \"...\";\n }\n default:\n return \"...\";\n }\n}\nfunction findFirstStringProp(schema) {\n if (!schema || !schema._def) return null;\n const def = schema._def;\n const typeName = getZodTypeName(schema);\n if (typeName !== \"ZodObject\" && typeName !== \"object\") return null;\n const shape = typeof def.shape === \"function\" ? def.shape() : def.shape;\n if (!shape) return null;\n for (const [key, value] of Object.entries(shape)) {\n const innerTypeName = getZodTypeName(value);\n if (innerTypeName === \"ZodOptional\" || innerTypeName === \"optional\" || innerTypeName === \"ZodNullable\" || innerTypeName === \"nullable\") {\n continue;\n }\n if (innerTypeName === \"ZodString\" || innerTypeName === \"string\") {\n return key;\n }\n }\n return null;\n}\nfunction getZodTypeName(schema) {\n if (!schema || !schema._def) return \"\";\n const def = schema._def;\n return def.typeName ?? def.type ?? \"\";\n}\nfunction formatZodType(schema) {\n if (!schema || !schema._def) return \"unknown\";\n const def = schema._def;\n const typeName = getZodTypeName(schema);\n switch (typeName) {\n case \"ZodString\":\n case \"string\":\n return \"string\";\n case \"ZodNumber\":\n case \"number\":\n return \"number\";\n case \"ZodBoolean\":\n case \"boolean\":\n return \"boolean\";\n case \"ZodLiteral\":\n case \"literal\": {\n const litValues = def.values;\n const litValue = litValues?.[0] ?? def.value;\n return JSON.stringify(litValue);\n }\n case \"ZodEnum\":\n case \"enum\": {\n let values;\n if (Array.isArray(def.values)) {\n values = def.values;\n } else if (def.entries && typeof def.entries === \"object\") {\n values = Object.values(def.entries);\n } else {\n return \"enum\";\n }\n return values.map((v) => `\"${v}\"`).join(\" | \");\n }\n case \"ZodArray\":\n case \"array\": {\n const inner = typeof def.element === \"object\" ? def.element : typeof def.type === \"object\" ? def.type : void 0;\n return inner ? `Array<${formatZodType(inner)}>` : \"Array<unknown>\";\n }\n case \"ZodObject\":\n case \"object\": {\n const shape = typeof def.shape === \"function\" ? def.shape() : def.shape;\n if (!shape) return \"object\";\n const props = Object.entries(shape).map(([key, value]) => {\n const innerTypeName = getZodTypeName(value);\n const isOptional = innerTypeName === \"ZodOptional\" || innerTypeName === \"ZodNullable\" || innerTypeName === \"optional\" || innerTypeName === \"nullable\";\n return `${key}${isOptional ? \"?\" : \"\"}: ${formatZodType(value)}`;\n }).join(\", \");\n return `{ ${props} }`;\n }\n case \"ZodOptional\":\n case \"optional\":\n case \"ZodNullable\":\n case \"nullable\": {\n const inner = def.innerType ?? def.wrapped;\n return inner ? formatZodType(inner) : \"unknown\";\n }\n case \"ZodUnion\":\n case \"union\": {\n const options = def.options;\n return options ? options.map((opt) => formatZodType(opt)).join(\" | \") : \"unknown\";\n }\n case \"ZodRecord\":\n case \"record\": {\n const keyType = def.keyType ?? void 0;\n const valueType = def.valueType ?? def.element ?? void 0;\n const keyStr = keyType ? formatZodType(keyType) : \"string\";\n const valueStr = valueType ? formatZodType(valueType) : \"unknown\";\n return `Record<${keyStr}, ${valueStr}>`;\n }\n case \"ZodDefault\":\n case \"default\": {\n const inner = def.innerType ?? def.wrapped;\n return inner ? formatZodType(inner) : \"unknown\";\n }\n default:\n return \"unknown\";\n }\n}\nfunction zodTypeName(def) {\n if (typeof def.type === \"string\") return def.type;\n if (typeof def.typeName === \"string\") return def.typeName;\n return \"\";\n}\nfunction normalizeTypeName(raw) {\n if (raw.startsWith(\"Zod\")) {\n return raw.slice(3).toLowerCase();\n }\n return raw.toLowerCase();\n}\nfunction zodToJsonSchema(schema, strict = false) {\n const def = schema._def;\n const kind = normalizeTypeName(zodTypeName(def));\n switch (kind) {\n case \"string\":\n return { type: \"string\" };\n case \"number\":\n return { type: \"number\" };\n case \"boolean\":\n return { type: \"boolean\" };\n case \"literal\": {\n const values = def.values;\n const value = values ? values[0] : def.value;\n return { const: value };\n }\n case \"enum\": {\n const entries = def.entries;\n const values = entries ? Object.values(entries) : def.values;\n return { enum: values ?? [] };\n }\n case \"array\": {\n const inner = def.element ?? def.type;\n return {\n type: \"array\",\n items: inner ? zodToJsonSchema(inner, strict) : {}\n };\n }\n case \"object\": {\n const rawShape = def.shape;\n const shape = typeof rawShape === \"function\" ? rawShape() : rawShape;\n if (!shape) {\n if (strict) {\n return {\n type: \"object\",\n properties: {},\n required: [],\n additionalProperties: false\n };\n }\n return { type: \"object\" };\n }\n const properties = {};\n const required = [];\n for (const [key, value] of Object.entries(shape)) {\n const innerDef = value._def;\n const innerKind = normalizeTypeName(zodTypeName(innerDef));\n const isOptional = innerKind === \"optional\" || innerKind === \"nullable\";\n if (strict) {\n required.push(key);\n if (isOptional) {\n const unwrapped = zodToJsonSchema(value, strict);\n properties[key] = { anyOf: [unwrapped, { type: \"null\" }] };\n } else {\n properties[key] = zodToJsonSchema(value, strict);\n }\n } else {\n properties[key] = zodToJsonSchema(value);\n if (!isOptional) {\n required.push(key);\n }\n }\n }\n return {\n type: \"object\",\n properties,\n required: required.length > 0 ? required : void 0,\n additionalProperties: false\n };\n }\n case \"record\": {\n const valueType = def.valueType;\n if (strict) {\n return {\n type: \"object\",\n properties: {},\n required: [],\n additionalProperties: false\n };\n }\n return {\n type: \"object\",\n additionalProperties: valueType ? zodToJsonSchema(valueType) : true\n };\n }\n case \"optional\":\n case \"nullable\": {\n const inner = def.innerType;\n return inner ? zodToJsonSchema(inner, strict) : {};\n }\n case \"union\": {\n const options = def.options;\n return options ? { anyOf: options.map((o) => zodToJsonSchema(o, strict)) } : {};\n }\n case \"any\":\n case \"unknown\":\n if (strict) {\n return {\n type: \"object\",\n properties: {},\n required: [],\n additionalProperties: false\n };\n }\n return {};\n default:\n return {};\n }\n}\nfunction defineCatalog(schema, catalog) {\n return schema.createCatalog(catalog);\n}\n\n// src/prompt.ts\nfunction buildUserPrompt(options) {\n const {\n prompt,\n currentSpec,\n state,\n maxPromptLength,\n editModes,\n format,\n serializer\n } = options;\n let userText = String(prompt || \"\");\n if (maxPromptLength !== void 0 && maxPromptLength > 0) {\n userText = userText.slice(0, maxPromptLength);\n }\n if (isNonEmptySpec(currentSpec)) {\n const editPrompt = buildEditUserPrompt({\n prompt: userText,\n currentSpec,\n config: { modes: editModes ?? [\"patch\"] },\n format: format ?? \"json\",\n serializer\n });\n if (state && Object.keys(state).length > 0) {\n return `${editPrompt}\n\nAVAILABLE STATE:\n${JSON.stringify(state, null, 2)}`;\n }\n return editPrompt;\n }\n const parts = [userText];\n if (state && Object.keys(state).length > 0) {\n parts.push(`\nAVAILABLE STATE:\n${JSON.stringify(state, null, 2)}`);\n }\n if (format === \"yaml\") {\n parts.push(\n `\nOutput the full spec in a \\`\\`\\`yaml-spec fence. Stream progressively \\u2014 output elements one at a time.`\n );\n } else {\n parts.push(\n `\nRemember: Output /root first, then interleave /elements and /state patches so the UI fills in progressively as it streams. Output each state patch right after the elements that use it, one per array item.`\n );\n }\n return parts.join(\"\\n\");\n}\n\n// src/merge.ts\nfunction isPlainObject(value) {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\nfunction deepMergeSpec(base, patch) {\n const result = { ...base };\n for (const key of Object.keys(patch)) {\n const patchVal = patch[key];\n if (patchVal === null) {\n delete result[key];\n continue;\n }\n const baseVal = result[key];\n if (isPlainObject(patchVal) && isPlainObject(baseVal)) {\n result[key] = deepMergeSpec(baseVal, patchVal);\n } else {\n result[key] = patchVal;\n }\n }\n return result;\n}\n\n// src/diff.ts\nfunction escapeToken(token) {\n return token.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n}\nfunction buildPath(basePath, key) {\n return `${basePath}/${escapeToken(key)}`;\n}\nfunction isPlainObject2(value) {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\nfunction arraysEqual(a, b) {\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i++) {\n if (a[i] !== b[i]) return false;\n }\n return true;\n}\nfunction diffToPatches(oldObj, newObj, basePath = \"\") {\n const patches = [];\n for (const key of Object.keys(newObj)) {\n const path = buildPath(basePath, key);\n const oldVal = oldObj[key];\n const newVal = newObj[key];\n if (!(key in oldObj)) {\n patches.push({ op: \"add\", path, value: newVal });\n continue;\n }\n if (isPlainObject2(oldVal) && isPlainObject2(newVal)) {\n patches.push(...diffToPatches(oldVal, newVal, path));\n } else if (Array.isArray(oldVal) && Array.isArray(newVal)) {\n if (!arraysEqual(oldVal, newVal)) {\n patches.push({ op: \"replace\", path, value: newVal });\n }\n } else if (oldVal !== newVal) {\n patches.push({ op: \"replace\", path, value: newVal });\n }\n }\n for (const key of Object.keys(oldObj)) {\n if (!(key in newObj)) {\n patches.push({ op: \"remove\", path: buildPath(basePath, key) });\n }\n }\n return patches;\n}\nexport {\n ActionBindingSchema,\n ActionConfirmSchema,\n ActionOnErrorSchema,\n ActionOnSuccessSchema,\n ActionSchema,\n DynamicBooleanSchema,\n DynamicNumberSchema,\n DynamicStringSchema,\n DynamicValueSchema,\n SPEC_DATA_PART,\n SPEC_DATA_PART_TYPE,\n ValidationCheckSchema,\n ValidationConfigSchema,\n VisibilityConditionSchema,\n action,\n actionBinding,\n addByPath,\n applySpecPatch,\n applySpecStreamPatch,\n autoFixSpec,\n buildEditInstructions,\n buildEditUserPrompt,\n buildUserPrompt,\n builtInValidationFunctions,\n check,\n compileSpecStream,\n createDirectiveRegistry,\n createJsonRenderTransform,\n createMixedStreamParser,\n createSpecStreamCompiler,\n createStateStore,\n deepMergeSpec,\n defineCatalog,\n defineDirective,\n defineSchema,\n diffToPatches,\n evaluateVisibility,\n executeAction,\n findDirective,\n findFormValue,\n formatSpecIssues,\n getByPath,\n interpolateString,\n isDevtoolsActive,\n isNonEmptySpec,\n markDevtoolsActive,\n nestedToFlat,\n nextActionDispatchId,\n notifyActionDispatch,\n notifyActionSettle,\n parseSpecStreamLine,\n pipeJsonRender,\n registerActionObserver,\n removeByPath,\n resolveAction,\n resolveActionParam,\n resolveBindings,\n resolveDynamicValue,\n resolveElementProps,\n resolvePropValue,\n runValidation,\n runValidationCheck,\n setByPath,\n subscribeDevtoolsActive,\n validateSpec,\n visibility\n};\n//# sourceMappingURL=index.mjs.map","// src/schema.ts\nimport { defineSchema } from \"@json-render/core\";\nvar schema = defineSchema(\n (s) => ({\n // What the AI-generated SPEC looks like\n spec: s.object({\n /** Root element key */\n root: s.string(),\n /** Flat map of elements by key */\n elements: s.record(\n s.object({\n /** Component type from catalog */\n type: s.ref(\"catalog.components\"),\n /** Component props */\n props: s.propsOf(\"catalog.components\"),\n /** Child element keys (flat reference) */\n children: s.array(s.string()),\n /** Visibility condition */\n visible: s.any()\n })\n )\n }),\n // What the CATALOG must provide\n catalog: s.object({\n /** Component definitions */\n components: s.map({\n /** Zod schema for component props */\n props: s.zod(),\n /** Slots for this component. Use ['default'] for children, or named slots like ['header', 'footer'] */\n slots: s.array(s.string()),\n /** Description for AI generation hints */\n description: s.string(),\n /** Example prop values used in prompt examples (auto-generated from Zod schema if omitted) */\n example: s.any()\n }),\n /** Action definitions (optional) */\n actions: s.map({\n /** Zod schema for action params */\n params: s.zod(),\n /** Description for AI generation hints */\n description: s.string()\n })\n })\n }),\n {\n builtInActions: [\n {\n name: \"setState\",\n description: \"Update a value in the state model at the given statePath. Params: { statePath: string, value: any }\"\n },\n {\n name: \"pushState\",\n description: 'Append an item to an array in state. Params: { statePath: string, value: any, clearStatePath?: string }. Value can contain {\"$state\":\"/path\"} refs and \"$id\" for auto IDs.'\n },\n {\n name: \"removeState\",\n description: \"Remove an item from an array in state by index. Params: { statePath: string, index: number }\"\n },\n {\n name: \"validateForm\",\n description: \"Validate all registered form fields and write the result to state. Params: { statePath?: string }. Defaults to /formValidation. Result: { valid: boolean, errors: Record<string, string[]> }.\"\n }\n ],\n defaultRules: [\n // Element integrity\n \"CRITICAL INTEGRITY CHECK: Before outputting ANY element that references children, you MUST have already output (or will output) each child as its own element. If an element has children: ['a', 'b'], then elements 'a' and 'b' MUST exist. A missing child element causes that entire branch of the UI to be invisible.\",\n \"SELF-CHECK: After generating all elements, mentally walk the tree from root. Every key in every children array must resolve to a defined element. If you find a gap, output the missing element immediately.\",\n // Field placement\n 'CRITICAL: The \"visible\" field goes on the ELEMENT object, NOT inside \"props\". Correct: {\"type\":\"<ComponentName>\",\"props\":{},\"visible\":{\"$state\":\"/tab\",\"eq\":\"home\"},\"children\":[...]}.',\n 'CRITICAL: The \"on\" field goes on the ELEMENT object, NOT inside \"props\". Use on.press, on.change, on.submit etc. NEVER put action/actionParams inside props.',\n // State and data\n \"When the user asks for a UI that displays data (e.g. blog posts, products, users), ALWAYS include a state field with realistic sample data. The state field is a top-level field on the spec (sibling of root/elements).\",\n 'When building repeating content backed by a state array (e.g. posts, products, items), use the \"repeat\" field on a container element. Example: { \"type\": \"<ContainerComponent>\", \"props\": {}, \"repeat\": { \"statePath\": \"/posts\", \"key\": \"id\" }, \"children\": [\"post-card\"] }. Replace <ContainerComponent> with an appropriate component from the AVAILABLE COMPONENTS list. Inside repeated children, use { \"$item\": \"field\" } to read a field from the current item, and { \"$index\": true } for the current array index. For two-way binding to an item field use { \"$bindItem\": \"completed\" }. Do NOT hardcode individual elements for each array item.',\n // Design quality\n \"Design with visual hierarchy: use container components to group content, heading components for section titles, proper spacing, and status indicators. ONLY use components from the AVAILABLE COMPONENTS list.\",\n \"For data-rich UIs, use multi-column layout components if available. For forms and single-column content, use vertical layout components. ONLY use components from the AVAILABLE COMPONENTS list.\",\n \"Always include realistic, professional-looking sample data. For blogs include 3-4 posts with varied titles, authors, dates, categories. For products include names, prices, images. Never leave data empty.\"\n ]\n }\n);\nvar elementTreeSchema = schema;\n\nexport {\n schema,\n elementTreeSchema\n};\n//# sourceMappingURL=chunk-WYDS23XB.mjs.map","import {\n elementTreeSchema,\n schema\n} from \"./chunk-WYDS23XB.mjs\";\n\n// ../react-state/dist/index.mjs\nimport {\n createContext,\n useContext,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useSyncExternalStore\n} from \"react\";\nimport {\n getByPath,\n createStateStore\n} from \"@json-render/core\";\nimport { flattenToPointers } from \"@json-render/core/store-utils\";\nimport { jsx } from \"react/jsx-runtime\";\nvar StateContext = createContext(null);\nfunction computeInitialFlat(isControlled, initialState) {\n if (isControlled) return null;\n if (Object.keys(initialState).length === 0) return {};\n return flattenToPointers(initialState);\n}\nfunction StateProvider({\n store: externalStore,\n initialState = {},\n onStateChange,\n children\n}) {\n const internalStoreRef = useRef(void 0);\n if (!externalStore && !internalStoreRef.current) {\n internalStoreRef.current = createStateStore(initialState);\n }\n const store = externalStore ?? internalStoreRef.current;\n const storeRef = useRef(store);\n storeRef.current = store;\n const isControlledRef = useRef(!!externalStore);\n isControlledRef.current = !!externalStore;\n const initialModeRef = useRef(externalStore ? \"controlled\" : \"uncontrolled\");\n const modeWarnedRef = useRef(false);\n if (process.env.NODE_ENV !== \"production\") {\n const currentMode = externalStore ? \"controlled\" : \"uncontrolled\";\n if (currentMode !== initialModeRef.current && !modeWarnedRef.current) {\n modeWarnedRef.current = true;\n console.warn(\n `StateProvider: switching from ${initialModeRef.current} to ${currentMode} mode is not supported.`\n );\n }\n }\n const prevInitialStateRef = useRef(initialState);\n const prevFlatRef = useRef(\n computeInitialFlat(!!externalStore, initialState)\n );\n useEffect(() => {\n if (externalStore) return;\n if (initialState === prevInitialStateRef.current) return;\n prevInitialStateRef.current = initialState;\n const nextFlat = initialState && Object.keys(initialState).length > 0 ? flattenToPointers(initialState) : {};\n const prevFlat = prevFlatRef.current ?? {};\n const allKeys = /* @__PURE__ */ new Set([\n ...Object.keys(prevFlat),\n ...Object.keys(nextFlat)\n ]);\n const updates = {};\n for (const key of allKeys) {\n if (prevFlat[key] !== nextFlat[key]) {\n updates[key] = key in nextFlat ? nextFlat[key] : void 0;\n }\n }\n prevFlatRef.current = nextFlat;\n if (Object.keys(updates).length > 0) {\n store.update(updates);\n }\n }, [externalStore, initialState, store]);\n const state = useSyncExternalStore(\n store.subscribe,\n store.getSnapshot,\n store.getServerSnapshot ?? store.getSnapshot\n );\n const onStateChangeRef = useRef(onStateChange);\n onStateChangeRef.current = onStateChange;\n const set = useCallback((path, value2) => {\n const s = storeRef.current;\n const prev = s.getSnapshot();\n s.set(path, value2);\n if (!isControlledRef.current && s.getSnapshot() !== prev) {\n onStateChangeRef.current?.([{ path, value: value2 }]);\n }\n }, []);\n const update = useCallback((updates) => {\n const s = storeRef.current;\n const prev = s.getSnapshot();\n s.update(updates);\n if (!isControlledRef.current && s.getSnapshot() !== prev) {\n const changes = [];\n for (const [path, value2] of Object.entries(updates)) {\n if (getByPath(prev, path) !== value2) {\n changes.push({ path, value: value2 });\n }\n }\n if (changes.length > 0) {\n onStateChangeRef.current?.(changes);\n }\n }\n }, []);\n const get = useCallback((path) => storeRef.current.get(path), []);\n const getSnapshot = useCallback(() => storeRef.current.getSnapshot(), []);\n const value = useMemo(\n () => ({ state, get, set, update, getSnapshot }),\n [state, get, set, update, getSnapshot]\n );\n return /* @__PURE__ */ jsx(StateContext.Provider, { value, children });\n}\nfunction useStateStore() {\n const ctx = useContext(StateContext);\n if (!ctx) {\n throw new Error(\"useStateStore must be used within a StateProvider\");\n }\n return ctx;\n}\nfunction useStateValue(path) {\n const { state } = useStateStore();\n return getByPath(state, path);\n}\nfunction useStateBinding(path) {\n const { state, set } = useStateStore();\n const value = getByPath(state, path);\n const setValue = useCallback(\n (newValue) => set(path, newValue),\n [path, set]\n );\n return [value, setValue];\n}\n\n// src/contexts/visibility.tsx\nimport {\n createContext as createContext2,\n useContext as useContext2,\n useMemo as useMemo2\n} from \"react\";\nimport {\n evaluateVisibility\n} from \"@json-render/core\";\nimport { jsx as jsx2 } from \"react/jsx-runtime\";\nvar VisibilityContext = createContext2(null);\nfunction VisibilityProvider({ children }) {\n const { state } = useStateStore();\n const ctx = useMemo2(\n () => ({\n stateModel: state\n }),\n [state]\n );\n const isVisible = useMemo2(\n () => (condition) => evaluateVisibility(condition, ctx),\n [ctx]\n );\n const value = useMemo2(\n () => ({ isVisible, ctx }),\n [isVisible, ctx]\n );\n return /* @__PURE__ */ jsx2(VisibilityContext.Provider, { value, children });\n}\nfunction useVisibility() {\n const ctx = useContext2(VisibilityContext);\n if (!ctx) {\n throw new Error(\"useVisibility must be used within a VisibilityProvider\");\n }\n return ctx;\n}\nfunction useIsVisible(condition) {\n const { isVisible } = useVisibility();\n return isVisible(condition);\n}\n\n// src/contexts/actions.tsx\nimport {\n createContext as createContext4,\n useContext as useContext4,\n useState as useState2,\n useCallback as useCallback3,\n useMemo as useMemo4\n} from \"react\";\nimport {\n resolveAction,\n executeAction,\n nextActionDispatchId,\n notifyActionDispatch,\n notifyActionSettle\n} from \"@json-render/core\";\n\n// src/contexts/validation.tsx\nimport React2, {\n createContext as createContext3,\n useContext as useContext3,\n useRef as useRef2,\n useState,\n useCallback as useCallback2,\n useMemo as useMemo3\n} from \"react\";\nimport {\n runValidation\n} from \"@json-render/core\";\nimport { jsx as jsx3 } from \"react/jsx-runtime\";\nvar ValidationContext = createContext3(null);\nfunction dynamicArgsEqual(a, b) {\n if (a === b) return true;\n if (!a || !b) return false;\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n if (keysA.length !== keysB.length) return false;\n for (const key of keysA) {\n const va = a[key];\n const vb = b[key];\n if (va === vb) continue;\n if (typeof va === \"object\" && va !== null && typeof vb === \"object\" && vb !== null) {\n const sa = va.$state;\n const sb = vb.$state;\n if (typeof sa === \"string\" && sa === sb) continue;\n }\n return false;\n }\n return true;\n}\nfunction validationConfigEqual(a, b) {\n if (a === b) return true;\n if (a.validateOn !== b.validateOn) return false;\n const ac = a.checks ?? [];\n const bc = b.checks ?? [];\n if (ac.length !== bc.length) return false;\n for (let i = 0; i < ac.length; i++) {\n const ca = ac[i];\n const cb = bc[i];\n if (ca.type !== cb.type) return false;\n if (ca.message !== cb.message) return false;\n if (!dynamicArgsEqual(ca.args, cb.args)) return false;\n }\n return true;\n}\nfunction ValidationProvider({\n customFunctions = {},\n children\n}) {\n const { state, getSnapshot } = useStateStore();\n const [fieldStates, setFieldStates] = useState({});\n const fieldStatesRef = useRef2({});\n const [fieldConfigs, setFieldConfigs] = useState({});\n const registerField = useCallback2(\n (path, config) => {\n setFieldConfigs((prev) => {\n const existing = prev[path];\n if (existing && validationConfigEqual(existing, config)) {\n return prev;\n }\n return { ...prev, [path]: config };\n });\n },\n []\n );\n const validate = useCallback2(\n (path, config) => {\n const currentState = getSnapshot();\n const segments = path.split(\"/\").filter(Boolean);\n let value2 = currentState;\n for (const seg of segments) {\n if (value2 != null && typeof value2 === \"object\") {\n value2 = value2[seg];\n } else {\n value2 = void 0;\n break;\n }\n }\n const result = runValidation(config, {\n value: value2,\n stateModel: currentState,\n customFunctions\n });\n const newFieldState = {\n touched: fieldStatesRef.current[path]?.touched ?? true,\n validated: true,\n result\n };\n fieldStatesRef.current = {\n ...fieldStatesRef.current,\n [path]: newFieldState\n };\n setFieldStates(fieldStatesRef.current);\n return result;\n },\n [customFunctions, getSnapshot]\n );\n const touch = useCallback2((path) => {\n fieldStatesRef.current = {\n ...fieldStatesRef.current,\n [path]: {\n ...fieldStatesRef.current[path],\n touched: true,\n validated: fieldStatesRef.current[path]?.validated ?? false,\n result: fieldStatesRef.current[path]?.result ?? null\n }\n };\n setFieldStates(fieldStatesRef.current);\n }, []);\n const clear = useCallback2((path) => {\n const { [path]: _, ...rest } = fieldStatesRef.current;\n fieldStatesRef.current = rest;\n setFieldStates(rest);\n }, []);\n const validateAll = useCallback2(() => {\n let allValid = true;\n for (const [path, config] of Object.entries(fieldConfigs)) {\n const result = validate(path, config);\n if (!result.valid) {\n allValid = false;\n }\n }\n return allValid;\n }, [fieldConfigs, validate]);\n const value = useMemo3(\n () => ({\n customFunctions,\n // Getter returns the mutable ref so callers that read fieldStates\n // synchronously after validateAll() see the latest values.\n get fieldStates() {\n return fieldStatesRef.current;\n },\n validate,\n touch,\n clear,\n validateAll,\n registerField\n }),\n [\n customFunctions,\n // fieldStates (React state) stays in deps so the context value object\n // is recreated on re-render, triggering downstream consumers.\n fieldStates,\n validate,\n touch,\n clear,\n validateAll,\n registerField\n ]\n );\n return /* @__PURE__ */ jsx3(ValidationContext.Provider, { value, children });\n}\nfunction useValidation() {\n const ctx = useContext3(ValidationContext);\n if (!ctx) {\n throw new Error(\"useValidation must be used within a ValidationProvider\");\n }\n return ctx;\n}\nfunction useOptionalValidation() {\n return useContext3(ValidationContext);\n}\nfunction useFieldValidation(path, config) {\n const {\n fieldStates,\n validate: validateField,\n touch: touchField,\n clear: clearField,\n registerField\n } = useValidation();\n React2.useEffect(() => {\n if (path && config) {\n registerField(path, config);\n }\n }, [path, config, registerField]);\n const state = fieldStates[path] ?? {\n touched: false,\n validated: false,\n result: null\n };\n const validate = useCallback2(\n () => validateField(path, config ?? { checks: [] }),\n [path, config, validateField]\n );\n const touch = useCallback2(() => touchField(path), [path, touchField]);\n const clear = useCallback2(() => clearField(path), [path, clearField]);\n return {\n state,\n validate,\n touch,\n clear,\n errors: state.result?.errors ?? [],\n isValid: state.result?.valid ?? true\n };\n}\n\n// src/contexts/actions.tsx\nimport { jsx as jsx4, jsxs } from \"react/jsx-runtime\";\nvar idCounter = 0;\nfunction generateUniqueId() {\n idCounter += 1;\n return `${Date.now()}-${idCounter}`;\n}\nfunction deepResolveValue(value, get) {\n if (value === null || value === void 0) return value;\n if (value === \"$id\") {\n return generateUniqueId();\n }\n if (typeof value === \"object\" && !Array.isArray(value)) {\n const obj = value;\n const keys = Object.keys(obj);\n if (keys.length === 1 && typeof obj.$state === \"string\") {\n return get(obj.$state);\n }\n if (keys.length === 1 && \"$id\" in obj) {\n return generateUniqueId();\n }\n }\n if (Array.isArray(value)) {\n return value.map((item) => deepResolveValue(item, get));\n }\n if (typeof value === \"object\") {\n const resolved = {};\n for (const [key, val] of Object.entries(value)) {\n resolved[key] = deepResolveValue(val, get);\n }\n return resolved;\n }\n return value;\n}\nvar ActionContext = createContext4(null);\nfunction ActionProvider({\n handlers: initialHandlers = {},\n navigate,\n children\n}) {\n const { get, set, getSnapshot } = useStateStore();\n const validation = useOptionalValidation();\n const [handlers, setHandlers] = useState2(initialHandlers);\n const [loadingActions, setLoadingActions] = useState2(/* @__PURE__ */ new Set());\n const [pendingConfirmation, setPendingConfirmation] = useState2(null);\n const registerHandler = useCallback3(\n (name, handler) => {\n setHandlers((prev) => ({ ...prev, [name]: handler }));\n },\n []\n );\n const execute = useCallback3(\n async (binding) => {\n const resolved = resolveAction(binding, getSnapshot());\n const dispatchId = nextActionDispatchId();\n const dispatchedAt = Date.now();\n notifyActionDispatch({\n id: dispatchId,\n name: resolved.action,\n params: resolved.params,\n at: dispatchedAt\n });\n let __ok = true;\n let __error = void 0;\n try {\n if (resolved.action === \"setState\" && resolved.params) {\n const statePath = resolved.params.statePath;\n const value2 = resolved.params.value;\n if (statePath) {\n set(statePath, value2);\n }\n return;\n }\n if (resolved.action === \"pushState\" && resolved.params) {\n const statePath = resolved.params.statePath;\n const rawValue = resolved.params.value;\n if (statePath) {\n const resolvedValue = deepResolveValue(rawValue, get);\n const arr = get(statePath) ?? [];\n set(statePath, [...arr, resolvedValue]);\n const clearStatePath = resolved.params.clearStatePath;\n if (clearStatePath) {\n set(clearStatePath, \"\");\n }\n }\n return;\n }\n if (resolved.action === \"removeState\" && resolved.params) {\n const statePath = resolved.params.statePath;\n const index = resolved.params.index;\n if (statePath !== void 0 && index !== void 0) {\n const arr = get(statePath) ?? [];\n set(\n statePath,\n arr.filter((_, i) => i !== index)\n );\n }\n return;\n }\n if (resolved.action === \"push\" && resolved.params) {\n const screen = resolved.params.screen;\n if (screen) {\n const currentScreen = get(\"/currentScreen\");\n const navStack = get(\"/navStack\") ?? [];\n if (currentScreen) {\n set(\"/navStack\", [...navStack, currentScreen]);\n } else {\n set(\"/navStack\", [...navStack, \"\"]);\n }\n set(\"/currentScreen\", screen);\n }\n return;\n }\n if (resolved.action === \"pop\") {\n const navStack = get(\"/navStack\") ?? [];\n if (navStack.length > 0) {\n const previousScreen = navStack[navStack.length - 1];\n set(\"/navStack\", navStack.slice(0, -1));\n if (previousScreen) {\n set(\"/currentScreen\", previousScreen);\n } else {\n set(\"/currentScreen\", void 0);\n }\n }\n return;\n }\n if (resolved.action === \"validateForm\") {\n const validateAll = validation?.validateAll;\n if (!validateAll) {\n console.warn(\n \"validateForm action was dispatched but no ValidationProvider is connected. Ensure ValidationProvider is rendered inside the provider tree.\"\n );\n return;\n }\n const valid = validateAll();\n const errors = {};\n for (const [path, fs] of Object.entries(validation.fieldStates)) {\n if (fs.result && !fs.result.valid) {\n errors[path] = fs.result.errors;\n }\n }\n const statePath = resolved.params?.statePath || \"/formValidation\";\n set(statePath, { valid, errors });\n return;\n }\n const handler = handlers[resolved.action];\n if (!handler) {\n console.warn(`No handler registered for action: ${resolved.action}`);\n return;\n }\n if (resolved.confirm) {\n return new Promise((resolve, reject) => {\n setPendingConfirmation({\n action: resolved,\n handler,\n resolve: () => {\n setPendingConfirmation(null);\n resolve();\n },\n reject: () => {\n setPendingConfirmation(null);\n reject(new Error(\"Action cancelled\"));\n }\n });\n }).then(async () => {\n setLoadingActions((prev) => new Set(prev).add(resolved.action));\n try {\n await executeAction({\n action: resolved,\n handler,\n setState: set,\n navigate,\n executeAction: async (name) => {\n const subBinding = { action: name };\n await execute(subBinding);\n }\n });\n } finally {\n setLoadingActions((prev) => {\n const next = new Set(prev);\n next.delete(resolved.action);\n return next;\n });\n }\n });\n }\n setLoadingActions((prev) => new Set(prev).add(resolved.action));\n try {\n await executeAction({\n action: resolved,\n handler,\n setState: set,\n navigate,\n executeAction: async (name) => {\n const subBinding = { action: name };\n await execute(subBinding);\n }\n });\n } finally {\n setLoadingActions((prev) => {\n const next = new Set(prev);\n next.delete(resolved.action);\n return next;\n });\n }\n } catch (err) {\n __ok = false;\n __error = err;\n throw err;\n } finally {\n const now = Date.now();\n notifyActionSettle({\n id: dispatchId,\n name: resolved.action,\n ok: __ok,\n at: now,\n durationMs: now - dispatchedAt,\n error: __error\n });\n }\n },\n [handlers, get, set, getSnapshot, navigate, validation]\n );\n const confirm = useCallback3(() => {\n pendingConfirmation?.resolve();\n }, [pendingConfirmation]);\n const cancel = useCallback3(() => {\n pendingConfirmation?.reject();\n }, [pendingConfirmation]);\n const value = useMemo4(\n () => ({\n handlers,\n loadingActions,\n pendingConfirmation,\n execute,\n confirm,\n cancel,\n registerHandler\n }),\n [\n handlers,\n loadingActions,\n pendingConfirmation,\n execute,\n confirm,\n cancel,\n registerHandler\n ]\n );\n return /* @__PURE__ */ jsx4(ActionContext.Provider, { value, children });\n}\nfunction useActions() {\n const ctx = useContext4(ActionContext);\n if (!ctx) {\n throw new Error(\"useActions must be used within an ActionProvider\");\n }\n return ctx;\n}\nfunction useAction(binding) {\n const { execute, loadingActions } = useActions();\n const isLoading = loadingActions.has(binding.action);\n const executeAction2 = useCallback3(() => execute(binding), [execute, binding]);\n return { execute: executeAction2, isLoading };\n}\nfunction ConfirmDialog({\n confirm,\n onConfirm,\n onCancel\n}) {\n const isDanger = confirm.variant === \"danger\";\n return /* @__PURE__ */ jsx4(\n \"div\",\n {\n style: {\n position: \"fixed\",\n inset: 0,\n backgroundColor: \"rgba(0, 0, 0, 0.5)\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n zIndex: 50\n },\n onClick: onCancel,\n children: /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n backgroundColor: \"white\",\n borderRadius: \"8px\",\n padding: \"24px\",\n maxWidth: \"400px\",\n width: \"100%\",\n boxShadow: \"0 20px 25px -5px rgba(0, 0, 0, 0.1)\"\n },\n onClick: (e) => e.stopPropagation(),\n children: [\n /* @__PURE__ */ jsx4(\n \"h3\",\n {\n style: {\n margin: \"0 0 8px 0\",\n fontSize: \"18px\",\n fontWeight: 600\n },\n children: confirm.title\n }\n ),\n /* @__PURE__ */ jsx4(\n \"p\",\n {\n style: {\n margin: \"0 0 24px 0\",\n color: \"#6b7280\"\n },\n children: confirm.message\n }\n ),\n /* @__PURE__ */ jsxs(\n \"div\",\n {\n style: {\n display: \"flex\",\n gap: \"12px\",\n justifyContent: \"flex-end\"\n },\n children: [\n /* @__PURE__ */ jsx4(\n \"button\",\n {\n onClick: onCancel,\n style: {\n padding: \"8px 16px\",\n borderRadius: \"6px\",\n border: \"1px solid #d1d5db\",\n backgroundColor: \"white\",\n cursor: \"pointer\"\n },\n children: confirm.cancelLabel ?? \"Cancel\"\n }\n ),\n /* @__PURE__ */ jsx4(\n \"button\",\n {\n onClick: onConfirm,\n style: {\n padding: \"8px 16px\",\n borderRadius: \"6px\",\n border: \"none\",\n backgroundColor: isDanger ? \"#dc2626\" : \"#3b82f6\",\n color: \"white\",\n cursor: \"pointer\"\n },\n children: confirm.confirmLabel ?? \"Confirm\"\n }\n )\n ]\n }\n )\n ]\n }\n )\n }\n );\n}\n\n// src/contexts/repeat-scope.tsx\nimport { createContext as createContext5, useContext as useContext5 } from \"react\";\nimport { jsx as jsx5 } from \"react/jsx-runtime\";\nvar RepeatScopeContext = createContext5(null);\nfunction RepeatScopeProvider({\n item,\n index,\n basePath,\n children\n}) {\n return /* @__PURE__ */ jsx5(RepeatScopeContext.Provider, { value: { item, index, basePath }, children });\n}\nfunction useRepeatScope() {\n return useContext5(RepeatScopeContext);\n}\n\n// src/index.ts\nimport { createStateStore as createStateStore2 } from \"@json-render/core\";\n\n// src/renderer.tsx\nimport React5, {\n useCallback as useCallback4,\n useEffect as useEffect2,\n useMemo as useMemo5,\n useRef as useRef3\n} from \"react\";\nimport {\n resolveElementProps,\n resolveBindings,\n resolveActionParam,\n evaluateVisibility as evaluateVisibility2,\n getByPath as getByPath2,\n isDevtoolsActive,\n subscribeDevtoolsActive,\n createDirectiveRegistry\n} from \"@json-render/core\";\nimport { Fragment, jsx as jsx6, jsxs as jsxs2 } from \"react/jsx-runtime\";\nvar ElementErrorBoundary = class extends React5.Component {\n constructor(props) {\n super(props);\n this.state = { hasError: false };\n }\n static getDerivedStateFromError() {\n return { hasError: true };\n }\n componentDidCatch(error, info) {\n console.error(\n `[json-render] Rendering error in <${this.props.elementType}>:`,\n error,\n info.componentStack\n );\n }\n render() {\n if (this.state.hasError) {\n return null;\n }\n return this.props.children;\n }\n};\nvar EMPTY_FUNCTIONS = {};\nvar FunctionsContext = React5.createContext(EMPTY_FUNCTIONS);\nfunction useFunctions() {\n return React5.useContext(FunctionsContext);\n}\nvar DirectivesContext = React5.createContext(\n void 0\n);\nfunction useDirectives() {\n return React5.useContext(DirectivesContext);\n}\nfunction useDevtoolsActive() {\n return React5.useSyncExternalStore(\n subscribeDevtoolsActive,\n isDevtoolsActive,\n () => false\n );\n}\nvar ElementRenderer = React5.memo(function ElementRenderer2({\n element,\n elementKey,\n spec,\n registry,\n loading,\n fallback\n}) {\n const devtoolsActive = useDevtoolsActive();\n const repeatScope = useRepeatScope();\n const { ctx } = useVisibility();\n const { execute } = useActions();\n const { getSnapshot, state: watchState } = useStateStore();\n const functions = useFunctions();\n const directives = useDirectives();\n const fullCtx = useMemo5(() => {\n const base = repeatScope ? {\n ...ctx,\n repeatItem: repeatScope.item,\n repeatIndex: repeatScope.index,\n repeatBasePath: repeatScope.basePath\n } : { ...ctx };\n base.functions = functions;\n base.directives = directives;\n return base;\n }, [ctx, repeatScope, functions, directives]);\n const isVisible = element.visible === void 0 ? true : evaluateVisibility2(element.visible, fullCtx);\n const onBindings = element.on;\n const emit = useCallback4(\n async (eventName) => {\n const binding = onBindings?.[eventName];\n if (!binding) return;\n const actionBindings = Array.isArray(binding) ? binding : [binding];\n for (const b of actionBindings) {\n if (!b.params) {\n await execute(b);\n continue;\n }\n const liveCtx = {\n ...fullCtx,\n stateModel: getSnapshot()\n };\n const resolved = {};\n for (const [key, val] of Object.entries(b.params)) {\n resolved[key] = resolveActionParam(val, liveCtx);\n }\n await execute({ ...b, params: resolved });\n }\n },\n [onBindings, execute, fullCtx, getSnapshot]\n );\n const on = useCallback4(\n (eventName) => {\n const binding = onBindings?.[eventName];\n if (!binding) {\n return { emit: () => {\n }, shouldPreventDefault: false, bound: false };\n }\n const actionBindings = Array.isArray(binding) ? binding : [binding];\n const shouldPreventDefault = actionBindings.some((b) => b.preventDefault);\n return {\n emit: () => emit(eventName),\n shouldPreventDefault,\n bound: true\n };\n },\n [onBindings, emit]\n );\n const watchConfig = element.watch;\n const prevWatchValues = useRef3(null);\n const stableWatchRef = useRef3(void 0);\n const watchedValues = useMemo5(() => {\n if (!watchConfig) return void 0;\n const values = {};\n for (const path of Object.keys(watchConfig)) {\n values[path] = getByPath2(watchState, path);\n }\n const prev = stableWatchRef.current;\n if (prev) {\n const keys = Object.keys(values);\n if (keys.length === Object.keys(prev).length && keys.every((k) => values[k] === prev[k])) {\n return prev;\n }\n }\n stableWatchRef.current = values;\n return values;\n }, [watchConfig, watchState]);\n useEffect2(() => {\n if (!watchConfig || !watchedValues) return;\n const paths = Object.keys(watchConfig);\n if (paths.length === 0) return;\n const prev = prevWatchValues.current;\n prevWatchValues.current = watchedValues;\n if (prev === null) return;\n let cancelled = false;\n void (async () => {\n for (const path of paths) {\n if (cancelled) break;\n if (watchedValues[path] !== prev[path]) {\n const binding = watchConfig[path];\n if (!binding) continue;\n const bindings = Array.isArray(binding) ? binding : [binding];\n for (const b of bindings) {\n if (cancelled) break;\n if (!b.params) {\n await execute(b);\n if (cancelled) break;\n continue;\n }\n const liveCtx = {\n ...fullCtx,\n stateModel: getSnapshot()\n };\n const resolved = {};\n for (const [key, val] of Object.entries(b.params)) {\n resolved[key] = resolveActionParam(val, liveCtx);\n }\n await execute({ ...b, params: resolved });\n if (cancelled) break;\n }\n }\n }\n })().catch(console.error);\n return () => {\n cancelled = true;\n };\n }, [watchConfig, watchedValues, execute, fullCtx, getSnapshot]);\n if (!isVisible) {\n return null;\n }\n const rawProps = element.props;\n const elementBindings = resolveBindings(rawProps, fullCtx);\n const resolvedProps = resolveElementProps(rawProps, fullCtx);\n const resolvedElement = resolvedProps !== element.props ? { ...element, props: resolvedProps } : element;\n const Component = registry[resolvedElement.type] ?? fallback;\n if (!Component) {\n console.warn(`No renderer for component type: ${resolvedElement.type}`);\n return null;\n }\n const children = resolvedElement.repeat ? /* @__PURE__ */ jsx6(\n RepeatChildren,\n {\n element: resolvedElement,\n spec,\n registry,\n loading,\n fallback\n }\n ) : resolvedElement.children?.map((childKey) => {\n const childElement = spec.elements[childKey];\n if (!childElement) {\n if (!loading) {\n console.warn(\n `[json-render] Missing element \"${childKey}\" referenced as child of \"${resolvedElement.type}\". This element will not render.`\n );\n }\n return null;\n }\n return /* @__PURE__ */ jsx6(\n ElementRenderer2,\n {\n element: childElement,\n elementKey: childKey,\n spec,\n registry,\n loading,\n fallback\n },\n childKey\n );\n });\n const rendered = /* @__PURE__ */ jsx6(\n Component,\n {\n element: resolvedElement,\n emit,\n on,\n bindings: elementBindings,\n loading,\n children\n }\n );\n const tagged = devtoolsActive && elementKey ? /* @__PURE__ */ jsx6(\"span\", { \"data-jr-key\": elementKey, style: { display: \"contents\" }, children: rendered }) : rendered;\n return /* @__PURE__ */ jsx6(ElementErrorBoundary, { elementType: resolvedElement.type, children: tagged });\n});\nfunction RepeatChildren({\n element,\n spec,\n registry,\n loading,\n fallback\n}) {\n const { state } = useStateStore();\n const repeat = element.repeat;\n const statePath = repeat.statePath;\n const items = getByPath2(state, statePath) ?? [];\n return /* @__PURE__ */ jsx6(Fragment, { children: items.map((itemValue, index) => {\n const key = repeat.key && typeof itemValue === \"object\" && itemValue !== null ? String(\n itemValue[repeat.key] ?? index\n ) : String(index);\n return /* @__PURE__ */ jsx6(\n RepeatScopeProvider,\n {\n item: itemValue,\n index,\n basePath: `${statePath}/${index}`,\n children: element.children?.map((childKey) => {\n const childElement = spec.elements[childKey];\n if (!childElement) {\n if (!loading) {\n console.warn(\n `[json-render] Missing element \"${childKey}\" referenced as child of \"${element.type}\" (repeat). This element will not render.`\n );\n }\n return null;\n }\n return /* @__PURE__ */ jsx6(\n ElementRenderer,\n {\n element: childElement,\n elementKey: childKey,\n spec,\n registry,\n loading,\n fallback\n },\n childKey\n );\n })\n },\n key\n );\n }) });\n}\nfunction Renderer({ spec, registry, loading, fallback }) {\n if (!spec || !spec.root) {\n return null;\n }\n const rootElement = spec.elements[spec.root];\n if (!rootElement) {\n return null;\n }\n return /* @__PURE__ */ jsx6(\n ElementRenderer,\n {\n element: rootElement,\n elementKey: spec.root,\n spec,\n registry,\n loading,\n fallback\n }\n );\n}\nfunction JSONUIProvider({\n registry,\n store,\n initialState,\n handlers,\n navigate,\n validationFunctions,\n functions,\n directives,\n onStateChange,\n children\n}) {\n const directiveRegistry = useMemo5(\n () => directives ? createDirectiveRegistry(directives) : void 0,\n [directives]\n );\n return /* @__PURE__ */ jsx6(\n StateProvider,\n {\n store,\n initialState,\n onStateChange,\n children: /* @__PURE__ */ jsx6(VisibilityProvider, { children: /* @__PURE__ */ jsx6(ValidationProvider, { customFunctions: validationFunctions, children: /* @__PURE__ */ jsx6(ActionProvider, { handlers, navigate, children: /* @__PURE__ */ jsx6(FunctionsContext.Provider, { value: functions ?? EMPTY_FUNCTIONS, children: /* @__PURE__ */ jsxs2(DirectivesContext.Provider, { value: directiveRegistry, children: [\n children,\n /* @__PURE__ */ jsx6(ConfirmationDialogManager, {})\n ] }) }) }) }) })\n }\n );\n}\nfunction ConfirmationDialogManager() {\n const { pendingConfirmation, confirm, cancel } = useActions();\n if (!pendingConfirmation?.action.confirm) {\n return null;\n }\n return /* @__PURE__ */ jsx6(\n ConfirmDialog,\n {\n confirm: pendingConfirmation.action.confirm,\n onConfirm: confirm,\n onCancel: cancel\n }\n );\n}\nfunction defineRegistry(_catalog, options) {\n const registry = {};\n if (options.components) {\n for (const [name, componentFn] of Object.entries(options.components)) {\n registry[name] = ({\n element,\n children,\n emit,\n on,\n bindings,\n loading\n }) => {\n return componentFn({\n props: element.props,\n children,\n emit,\n on,\n bindings,\n loading\n });\n };\n }\n }\n const actionMap = options.actions ? Object.entries(options.actions) : [];\n const handlers = (getSetState, getState) => {\n const result = {};\n for (const [name, actionFn] of actionMap) {\n result[name] = async (params) => {\n const setState = getSetState();\n const state = getState();\n if (setState) {\n await actionFn(params, setState, state);\n }\n };\n }\n return result;\n };\n const executeAction2 = async (actionName, params, setState, state = {}) => {\n const entry = actionMap.find(([name]) => name === actionName);\n if (entry) {\n await entry[1](params, setState, state);\n } else {\n console.warn(`Unknown action: ${actionName}`);\n }\n };\n return { registry, handlers, executeAction: executeAction2 };\n}\nfunction createRenderer(catalog, components) {\n const registry = components;\n return function CatalogRenderer({\n spec,\n store,\n state,\n onAction,\n onStateChange,\n functions,\n directives,\n loading,\n fallback\n }) {\n const directiveRegistry = useMemo5(\n () => directives ? createDirectiveRegistry(directives) : void 0,\n [directives]\n );\n const actionHandlers = onAction ? new Proxy(\n {},\n {\n get: (_target, prop) => {\n return (params) => onAction(prop, params);\n },\n has: () => true\n }\n ) : void 0;\n return /* @__PURE__ */ jsx6(\n StateProvider,\n {\n store,\n initialState: state,\n onStateChange,\n children: /* @__PURE__ */ jsx6(VisibilityProvider, { children: /* @__PURE__ */ jsx6(ValidationProvider, { children: /* @__PURE__ */ jsx6(ActionProvider, { handlers: actionHandlers, children: /* @__PURE__ */ jsx6(FunctionsContext.Provider, { value: functions ?? EMPTY_FUNCTIONS, children: /* @__PURE__ */ jsxs2(DirectivesContext.Provider, { value: directiveRegistry, children: [\n /* @__PURE__ */ jsx6(\n Renderer,\n {\n spec,\n registry,\n loading,\n fallback\n }\n ),\n /* @__PURE__ */ jsx6(ConfirmationDialogManager, {})\n ] }) }) }) }) })\n }\n );\n };\n}\n\n// src/hooks.ts\nimport { useState as useState3, useCallback as useCallback5, useRef as useRef4, useEffect as useEffect3 } from \"react\";\nimport {\n setByPath,\n getByPath as getByPath3,\n removeByPath,\n createMixedStreamParser,\n applySpecPatch,\n nestedToFlat,\n SPEC_DATA_PART_TYPE\n} from \"@json-render/core\";\nfunction parseLine(line) {\n try {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"//\")) {\n return null;\n }\n const parsed = JSON.parse(trimmed);\n if (parsed.__meta === \"usage\") {\n return {\n type: \"usage\",\n usage: {\n promptTokens: parsed.promptTokens ?? 0,\n completionTokens: parsed.completionTokens ?? 0,\n totalTokens: parsed.totalTokens ?? 0\n }\n };\n }\n return { type: \"patch\", patch: parsed };\n } catch {\n return null;\n }\n}\nfunction setSpecValue(newSpec, path, value) {\n if (path === \"/root\") {\n newSpec.root = value;\n return;\n }\n if (path === \"/state\") {\n newSpec.state = value;\n return;\n }\n if (path.startsWith(\"/state/\")) {\n if (!newSpec.state) newSpec.state = {};\n const statePath = path.slice(\"/state\".length);\n setByPath(newSpec.state, statePath, value);\n return;\n }\n if (path.startsWith(\"/elements/\")) {\n const pathParts = path.slice(\"/elements/\".length).split(\"/\");\n const elementKey = pathParts[0];\n if (!elementKey) return;\n if (pathParts.length === 1) {\n newSpec.elements[elementKey] = value;\n } else {\n const element = newSpec.elements[elementKey];\n if (element) {\n const propPath = \"/\" + pathParts.slice(1).join(\"/\");\n const newElement = { ...element };\n setByPath(\n newElement,\n propPath,\n value\n );\n newSpec.elements[elementKey] = newElement;\n }\n }\n }\n}\nfunction removeSpecValue(newSpec, path) {\n if (path === \"/state\") {\n delete newSpec.state;\n return;\n }\n if (path.startsWith(\"/state/\") && newSpec.state) {\n const statePath = path.slice(\"/state\".length);\n removeByPath(newSpec.state, statePath);\n return;\n }\n if (path.startsWith(\"/elements/\")) {\n const pathParts = path.slice(\"/elements/\".length).split(\"/\");\n const elementKey = pathParts[0];\n if (!elementKey) return;\n if (pathParts.length === 1) {\n const { [elementKey]: _, ...rest } = newSpec.elements;\n newSpec.elements = rest;\n } else {\n const element = newSpec.elements[elementKey];\n if (element) {\n const propPath = \"/\" + pathParts.slice(1).join(\"/\");\n const newElement = { ...element };\n removeByPath(\n newElement,\n propPath\n );\n newSpec.elements[elementKey] = newElement;\n }\n }\n }\n}\nfunction getSpecValue(spec, path) {\n if (path === \"/root\") return spec.root;\n if (path === \"/state\") return spec.state;\n if (path.startsWith(\"/state/\") && spec.state) {\n const statePath = path.slice(\"/state\".length);\n return getByPath3(spec.state, statePath);\n }\n return getByPath3(spec, path);\n}\nfunction applyPatch(spec, patch) {\n const newSpec = {\n ...spec,\n elements: { ...spec.elements },\n ...spec.state ? { state: { ...spec.state } } : {}\n };\n switch (patch.op) {\n case \"add\":\n case \"replace\": {\n setSpecValue(newSpec, patch.path, patch.value);\n break;\n }\n case \"remove\": {\n removeSpecValue(newSpec, patch.path);\n break;\n }\n case \"move\": {\n if (!patch.from) break;\n const moveValue = getSpecValue(newSpec, patch.from);\n removeSpecValue(newSpec, patch.from);\n setSpecValue(newSpec, patch.path, moveValue);\n break;\n }\n case \"copy\": {\n if (!patch.from) break;\n const copyValue = getSpecValue(newSpec, patch.from);\n setSpecValue(newSpec, patch.path, copyValue);\n break;\n }\n case \"test\": {\n break;\n }\n }\n return newSpec;\n}\nfunction useUIStream({\n api,\n onComplete,\n onError\n}) {\n const [spec, setSpec] = useState3(null);\n const [isStreaming, setIsStreaming] = useState3(false);\n const [error, setError] = useState3(null);\n const [usage, setUsage] = useState3(null);\n const [rawLines, setRawLines] = useState3([]);\n const abortControllerRef = useRef4(null);\n const onCompleteRef = useRef4(onComplete);\n onCompleteRef.current = onComplete;\n const onErrorRef = useRef4(onError);\n onErrorRef.current = onError;\n const clear = useCallback5(() => {\n setSpec(null);\n setError(null);\n }, []);\n const send = useCallback5(\n async (prompt, context) => {\n abortControllerRef.current?.abort();\n abortControllerRef.current = new AbortController();\n setIsStreaming(true);\n setError(null);\n setUsage(null);\n setRawLines([]);\n const previousSpec = context?.previousSpec;\n let currentSpec = previousSpec && previousSpec.root ? { ...previousSpec, elements: { ...previousSpec.elements } } : { root: \"\", elements: {} };\n setSpec(currentSpec);\n try {\n const response = await fetch(api, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n prompt,\n context,\n currentSpec\n }),\n signal: abortControllerRef.current.signal\n });\n if (!response.ok) {\n let errorMessage = `HTTP error: ${response.status}`;\n try {\n const errorData = await response.json();\n if (errorData.message) {\n errorMessage = errorData.message;\n } else if (errorData.error) {\n errorMessage = errorData.error;\n }\n } catch {\n }\n throw new Error(errorMessage);\n }\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"No response body\");\n }\n const decoder = new TextDecoder();\n let buffer = \"\";\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n const result = parseLine(trimmed);\n if (!result) continue;\n if (result.type === \"usage\") {\n setUsage(result.usage);\n } else {\n setRawLines((prev) => [...prev, trimmed]);\n currentSpec = applyPatch(currentSpec, result.patch);\n setSpec({ ...currentSpec });\n }\n }\n }\n if (buffer.trim()) {\n const trimmed = buffer.trim();\n const result = parseLine(trimmed);\n if (result) {\n if (result.type === \"usage\") {\n setUsage(result.usage);\n } else {\n setRawLines((prev) => [...prev, trimmed]);\n currentSpec = applyPatch(currentSpec, result.patch);\n setSpec({ ...currentSpec });\n }\n }\n }\n onCompleteRef.current?.(currentSpec);\n } catch (err) {\n if (err.name === \"AbortError\") {\n return;\n }\n const error2 = err instanceof Error ? err : new Error(String(err));\n setError(error2);\n onErrorRef.current?.(error2);\n } finally {\n setIsStreaming(false);\n }\n },\n [api]\n );\n useEffect3(() => {\n return () => {\n abortControllerRef.current?.abort();\n };\n }, []);\n return {\n spec,\n isStreaming,\n error,\n usage,\n rawLines,\n send,\n clear\n };\n}\nfunction flatToTree(elements) {\n const elementMap = {};\n let root = \"\";\n for (const element of elements) {\n elementMap[element.key] = {\n type: element.type,\n props: element.props,\n children: [],\n visible: element.visible\n };\n }\n for (const element of elements) {\n if (element.parentKey) {\n const parent = elementMap[element.parentKey];\n if (parent) {\n if (!parent.children) {\n parent.children = [];\n }\n parent.children.push(element.key);\n }\n } else {\n root = element.key;\n }\n }\n return { root, elements: elementMap };\n}\nfunction useBoundProp(propValue, bindingPath) {\n const { set } = useStateStore();\n const setValue = useCallback5(\n (value) => {\n if (bindingPath) set(bindingPath, value);\n },\n [bindingPath, set]\n );\n return [propValue, setValue];\n}\nfunction isSpecDataPart(data) {\n if (typeof data !== \"object\" || data === null) return false;\n const obj = data;\n switch (obj.type) {\n case \"patch\":\n return typeof obj.patch === \"object\" && obj.patch !== null;\n case \"flat\":\n case \"nested\":\n return typeof obj.spec === \"object\" && obj.spec !== null;\n default:\n return false;\n }\n}\nfunction buildSpecFromParts(parts) {\n const spec = { root: \"\", elements: {} };\n let hasSpec = false;\n for (const part of parts) {\n if (part.type === SPEC_DATA_PART_TYPE) {\n if (!isSpecDataPart(part.data)) continue;\n const payload = part.data;\n if (payload.type === \"patch\") {\n hasSpec = true;\n applySpecPatch(spec, payload.patch);\n } else if (payload.type === \"flat\") {\n hasSpec = true;\n Object.assign(spec, payload.spec);\n } else if (payload.type === \"nested\") {\n hasSpec = true;\n const flat = nestedToFlat(payload.spec);\n Object.assign(spec, flat);\n }\n }\n }\n return hasSpec ? spec : null;\n}\nfunction getTextFromParts(parts) {\n return parts.filter(\n (p) => p.type === \"text\" && typeof p.text === \"string\"\n ).map((p) => p.text.trim()).filter(Boolean).join(\"\\n\\n\");\n}\nfunction useJsonRenderMessage(parts) {\n const prevPartsRef = useRef4([]);\n const prevResultRef = useRef4({\n spec: null,\n text: \"\"\n });\n const partsChanged = parts !== prevPartsRef.current && (parts.length !== prevPartsRef.current.length || parts[parts.length - 1] !== prevPartsRef.current[prevPartsRef.current.length - 1]);\n if (partsChanged || prevPartsRef.current.length === 0) {\n prevPartsRef.current = parts;\n prevResultRef.current = {\n spec: buildSpecFromParts(parts),\n text: getTextFromParts(parts)\n };\n }\n const { spec, text } = prevResultRef.current;\n const hasSpec = spec !== null && Object.keys(spec.elements || {}).length > 0;\n return { spec, text, hasSpec };\n}\nvar chatMessageIdCounter = 0;\nfunction generateChatId() {\n if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") {\n return crypto.randomUUID();\n }\n chatMessageIdCounter += 1;\n return `msg-${Date.now()}-${chatMessageIdCounter}`;\n}\nfunction useChatUI({\n api,\n onComplete,\n onError\n}) {\n const [messages, setMessages] = useState3([]);\n const [isStreaming, setIsStreaming] = useState3(false);\n const [error, setError] = useState3(null);\n const abortControllerRef = useRef4(null);\n const messagesRef = useRef4(messages);\n messagesRef.current = messages;\n const onCompleteRef = useRef4(onComplete);\n onCompleteRef.current = onComplete;\n const onErrorRef = useRef4(onError);\n onErrorRef.current = onError;\n const clear = useCallback5(() => {\n setMessages([]);\n setError(null);\n }, []);\n const send = useCallback5(\n async (text) => {\n if (!text.trim()) return;\n abortControllerRef.current?.abort();\n abortControllerRef.current = new AbortController();\n const userMessage = {\n id: generateChatId(),\n role: \"user\",\n text: text.trim(),\n spec: null\n };\n const assistantId = generateChatId();\n const assistantMessage = {\n id: assistantId,\n role: \"assistant\",\n text: \"\",\n spec: null\n };\n setMessages((prev) => [...prev, userMessage, assistantMessage]);\n setIsStreaming(true);\n setError(null);\n const historyForApi = [\n ...messagesRef.current.map((m) => ({\n role: m.role,\n content: m.text\n })),\n { role: \"user\", content: text.trim() }\n ];\n let accumulatedText = \"\";\n let currentSpec = { root: \"\", elements: {} };\n let hasSpec = false;\n try {\n const response = await fetch(api, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ messages: historyForApi }),\n signal: abortControllerRef.current.signal\n });\n if (!response.ok) {\n let errorMessage = `HTTP error: ${response.status}`;\n try {\n const errorData = await response.json();\n if (errorData.message) {\n errorMessage = errorData.message;\n } else if (errorData.error) {\n errorMessage = errorData.error;\n }\n } catch {\n }\n throw new Error(errorMessage);\n }\n const reader = response.body?.getReader();\n if (!reader) {\n throw new Error(\"No response body\");\n }\n const decoder = new TextDecoder();\n const parser = createMixedStreamParser({\n onPatch(patch) {\n hasSpec = true;\n applySpecPatch(currentSpec, patch);\n setMessages(\n (prev) => prev.map(\n (m) => m.id === assistantId ? {\n ...m,\n spec: {\n root: currentSpec.root,\n elements: { ...currentSpec.elements },\n ...currentSpec.state ? { state: { ...currentSpec.state } } : {}\n }\n } : m\n )\n );\n },\n onText(line) {\n accumulatedText += (accumulatedText ? \"\\n\" : \"\") + line;\n setMessages(\n (prev) => prev.map(\n (m) => m.id === assistantId ? { ...m, text: accumulatedText } : m\n )\n );\n }\n });\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n parser.push(decoder.decode(value, { stream: true }));\n }\n parser.flush();\n const finalMessage = {\n id: assistantId,\n role: \"assistant\",\n text: accumulatedText,\n spec: hasSpec ? {\n root: currentSpec.root,\n elements: { ...currentSpec.elements },\n ...currentSpec.state ? { state: { ...currentSpec.state } } : {}\n } : null\n };\n onCompleteRef.current?.(finalMessage);\n } catch (err) {\n if (err.name === \"AbortError\") {\n return;\n }\n const resolvedError = err instanceof Error ? err : new Error(String(err));\n setError(resolvedError);\n setMessages(\n (prev) => prev.filter((m) => m.id !== assistantId || m.text.length > 0)\n );\n onErrorRef.current?.(resolvedError);\n } finally {\n setIsStreaming(false);\n }\n },\n [api]\n );\n useEffect3(() => {\n return () => {\n abortControllerRef.current?.abort();\n };\n }, []);\n return {\n messages,\n isStreaming,\n error,\n send,\n clear\n };\n}\nexport {\n ActionProvider,\n ConfirmDialog,\n JSONUIProvider,\n Renderer,\n RepeatScopeProvider,\n StateProvider,\n ValidationProvider,\n VisibilityProvider,\n buildSpecFromParts,\n createRenderer,\n createStateStore2 as createStateStore,\n defineRegistry,\n elementTreeSchema,\n flatToTree,\n getTextFromParts,\n schema,\n useAction,\n useActions,\n useBoundProp,\n useChatUI,\n useFieldValidation,\n useIsVisible,\n useJsonRenderMessage,\n useOptionalValidation,\n useRepeatScope,\n useStateBinding,\n useStateStore,\n useStateValue,\n useUIStream,\n useValidation,\n useVisibility\n};\n//# sourceMappingURL=index.mjs.map","import { useConfig, useDocumentDir } from '@opencx/widget-react-headless';\nimport { useMemo } from 'react';\nimport {\n getTranslation,\n isRtlLanguage,\n resolveLanguage,\n type TranslationKeyU,\n} from '@opencx/widget-core';\n\nexport type Translate = (\n key: TranslationKeyU,\n params?: Record<string, string | number>,\n) => string;\n\nexport function useTranslation() {\n const { dir: hostDocumentDir } = useDocumentDir();\n const config = useConfig();\n\n return useMemo(() => {\n const language = resolveLanguage(config.language);\n const t: Translate = (key, params) =>\n getTranslation(key, language, config.translationOverrides, params);\n return {\n t,\n language,\n dir: isRtlLanguage(language) ? 'rtl' : 'ltr',\n hostDocumentDir,\n };\n }, [config.language, config.translationOverrides, hostDocumentDir]);\n}\n","import {\n getTranslation,\n resolveLanguage,\n type TranslationKeyU,\n type WidgetUiAction,\n} from '@opencx/widget-core';\nimport React, { createContext, useContext, useMemo } from 'react';\n\n/**\n * What the json-render registry needs from whoever mounts it. Inside the\n * widget that is the widget config; on a host page that shows the same\n * transcripts (the OpenCX inbox) it is a few props. One renderer, one\n * catalog, two hosts — the registry never reaches for widget context itself.\n */\nexport type JsonRenderHost = {\n t: (key: TranslationKeyU, params?: Record<string, string | number>) => string;\n /** Where List links open — the embed's configured anchor target. */\n anchorTarget: string;\n /** Completes card actions the renderer cannot (e.g. test a phone agent). */\n onUiAction?: (action: WidgetUiAction) => void;\n};\n\n/** A translator for a host page that only knows the language (no overrides). */\nfunction translatorFor(language: string | undefined): JsonRenderHost['t'] {\n const resolved = resolveLanguage(language);\n return (key, params) => getTranslation(key, resolved, undefined, params);\n}\n\nconst defaultHost: JsonRenderHost = {\n t: translatorFor('en'),\n anchorTarget: '_blank',\n};\n\nconst JsonRenderHostContext = createContext<JsonRenderHost>(defaultHost);\n\nexport function JsonRenderHostProvider({\n host,\n children,\n}: {\n host: JsonRenderHost;\n children: React.ReactNode;\n}) {\n return (\n <JsonRenderHostContext.Provider value={host}>\n {children}\n </JsonRenderHostContext.Provider>\n );\n}\n\nexport function useJsonRenderHost(): JsonRenderHost {\n return useContext(JsonRenderHostContext);\n}\n\n/** A host built from plain props — memoized so the tree does not re-render per keystroke. */\nexport function useHostFromProps({\n language,\n onUiAction,\n anchorTarget = '_blank',\n}: {\n language?: string;\n onUiAction?: (action: WidgetUiAction) => void;\n anchorTarget?: string;\n}): JsonRenderHost {\n return useMemo(\n () => ({ t: translatorFor(language), anchorTarget, onUiAction }),\n [language, anchorTarget, onUiAction],\n );\n}\n","import React from 'react';\nimport { log } from '@opencx/widget-core';\n\n/**\n * Last-resort guard around a rendered spec. json-render validates props at the\n * registry boundary (`parseProps`), but a genuinely broken tree (e.g. a cyclic\n * `children` ref) could still throw during render — this keeps that from taking\n * down the whole chat transcript. On error we render nothing (the prose in the\n * same message still shows) and log once for diagnosis.\n */\nexport class JsonRenderErrorBoundary extends React.Component<\n { children: React.ReactNode; resetKey: unknown },\n { hasError: boolean }\n> {\n override state = { hasError: false };\n\n static getDerivedStateFromError() {\n return { hasError: true };\n }\n\n override componentDidCatch(error: unknown) {\n log.error('json-render: spec failed to render', {\n _e: error instanceof Error ? error.message : String(error),\n });\n }\n\n override componentDidUpdate(prevProps: Readonly<{ resetKey: unknown }>) {\n // Streaming specs are partial by definition. A broken intermediate tree\n // may become valid after the next patch, so retry only when the caller\n // supplies a new spec revision. Healthy renders never take this state path.\n if (this.state.hasError && prevProps.resetKey !== this.props.resetKey) {\n this.setState({ hasError: false });\n }\n }\n\n override render() {\n if (this.state.hasError) return null;\n return this.props.children;\n }\n}\n","import { getByPath, type Spec, type UIElement } from '@json-render/core';\nimport { isRecord } from '@opencx/widget-core';\n\n/**\n * Recover List rows the model parked behind a `repeat`.\n *\n * The slim widget prompt documents no `repeat` directive, but models that know\n * the full json-render contract sometimes invent one anyway (bind a container's\n * children to a `/state` array) and apply it to a `List` — a leaf that renders\n * `props.items` and ignores `children` — producing\n * `{ type: 'List', props: { items: [] }, repeat: { statePath } }` with the real\n * rows sitting in `state`. That renders an invisible empty list.\n *\n * This detects a `List` with empty `items` + a `repeat`, resolves the state\n * array, inlines it into `props.items`, and drops the `repeat`. Scoped to `List`\n * on purpose: List items are 1:1 with state objects (lossless to inline). Table\n * rows are positional `string[]` (can't inline) and an empty Table already shows\n * a visible empty state, so it's not a silent failure there.\n *\n * Returns the SAME spec reference when nothing changed, to keep React identity\n * stable across streaming re-renders.\n */\nexport function inlineRepeatLeaves(spec: Spec): Spec {\n if (!spec.elements) return spec;\n\n let changed = false;\n const elements: Record<string, UIElement> = {};\n\n for (const [id, element] of Object.entries(spec.elements)) {\n const recovered = recoverListRepeat(element, spec);\n if (recovered !== element) changed = true;\n elements[id] = recovered;\n }\n\n return changed ? { ...spec, elements } : spec;\n}\n\nfunction recoverListRepeat(element: UIElement, spec: Spec): UIElement {\n if (element.type !== 'List') return element;\n\n const repeat = element.repeat;\n if (!repeat || typeof repeat.statePath !== 'string') return element;\n\n const props = isRecord(element.props) ? element.props : {};\n const items = props.items;\n const alreadyHasItems = Array.isArray(items) && items.length > 0;\n if (alreadyHasItems) return element;\n\n const resolved = getByPath(spec.state ?? {}, repeat.statePath);\n if (!Array.isArray(resolved) || resolved.length === 0) return element;\n\n const { repeat: _dropped, ...rest } = element;\n return { ...rest, props: { ...props, items: resolved } };\n}\n","import { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import React, { Suspense } from 'react';\nimport type { ChartProps } from './props';\n\n/**\n * Lazy boundary for the chart renderer. `recharts` (+ its d3 deps) is the only\n * heavy thing in the registry, so it lives behind `React.lazy` — the base\n * widget bundle stays light and the chunk downloads only when a spec contains a\n * Chart. A shimmer holds the space while it loads (and while the chart's own\n * data streams in).\n *\n * This only pays off if the consuming build can code-split, which is why the\n * embed ships as an ES module behind a classic-script loader (see\n * `packages/embed/vite.config.ts`): an `iife` bundle cannot split, and inlined\n * this chunk into every page view.\n */\nconst ChartImpl = React.lazy(() => import('./Chart.impl'));\n\nexport function Chart(props: ChartProps) {\n const height = props.height ?? 220;\n return (\n <Suspense fallback={<ChartShimmer height={height} />}>\n <ChartImpl {...props} />\n </Suspense>\n );\n}\n\nfunction ChartShimmer({ height }: { height: number }) {\n return (\n <div\n className=\"w-full animate-pulse rounded-lg bg-muted-foreground/10\"\n style={{ height }}\n aria-hidden\n />\n );\n}\n","import { z } from 'zod';\n\n/**\n * Runtime prop schemas for every json-render component the widget agent can\n * emit, plus a defensive parser. These are the single source of truth: the\n * catalog (`catalog.ts`) feeds them to the model prompt, and the registry\n * (`registry.tsx`) parses streamed props through them before rendering.\n *\n * Optional props use `.nullish()` (null OR absent) rather than `.optional()` so\n * a prop the model omits — or hasn't finished streaming — never fails the parse.\n * Required props that ARE malformed fall back to a typed default (see\n * `parseProps`), so a bad prop degrades one component to a safe empty state\n * instead of throwing and tearing down the whole spec.\n */\n\n// ── Layout / structure ──────────────────────────────────────────────────────\n\nexport const cardPropsSchema = z.object({\n title: z.string().nullish(),\n description: z.string().nullish(),\n});\n\nexport const stackPropsSchema = z.object({\n direction: z.enum(['row', 'column']).nullish(),\n gap: z.enum(['sm', 'md', 'lg']).nullish(),\n align: z.enum(['start', 'center', 'end', 'stretch']).nullish(),\n justify: z.enum(['start', 'center', 'end', 'between']).nullish(),\n});\n\nexport const gridPropsSchema = z.object({\n // The prompt's contract is \"Grid columns max 3\" — this renders in a compact\n // chat widget, so wider grids are rejected at the schema.\n columns: z.union([z.literal(1), z.literal(2), z.literal(3)]).nullish(),\n gap: z.enum(['sm', 'md', 'lg']).nullish(),\n});\n\n// ── Content ─────────────────────────────────────────────────────────────────\n\nexport const headingPropsSchema = z.object({\n text: z.string(),\n level: z\n .union([z.literal(1), z.literal(2), z.literal(3), z.literal(4)])\n .nullish(),\n});\n\nexport const textPropsSchema = z.object({\n text: z.string(),\n variant: z.enum(['body', 'caption', 'muted', 'code']).nullish(),\n});\n\nexport const badgePropsSchema = z.object({\n text: z.string(),\n variant: z\n .enum(['default', 'secondary', 'success', 'warning', 'destructive'])\n .nullish(),\n});\n\n// ── Data display ────────────────────────────────────────────────────────────\n\n/**\n * Web-linkable protocols. Everything else — `javascript:`, `data:`, `blob:`,\n * `file:`, custom app schemes — is dropped.\n */\nconst SAFE_LINK_PROTOCOLS = new Set(['http:', 'https:', 'mailto:']);\n\n/**\n * A link the MODEL authored, so it is untrusted input: a poisoned knowledge-base\n * article or a crafted customer message can put any string here, and the anchor\n * renders inside the host page's realm. An unsafe value degrades to `null` (the\n * item renders as plain text) rather than failing the parse, matching this\n * file's \"one bad prop never tears down the spec\" contract.\n *\n * `javascript:` is the sharp edge: React 19 refuses it, but this package's peer\n * range still admits React 18, which does not — there it would be script\n * execution in the embedder's origin. Relative URLs are dropped too; they would\n * resolve against whatever page the widget happens to be embedded on, which the\n * model cannot know.\n */\nconst modelAuthoredHrefSchema = z\n .string()\n .nullish()\n .transform((value) => {\n if (!value) return null;\n try {\n return SAFE_LINK_PROTOCOLS.has(new URL(value).protocol) ? value : null;\n } catch {\n // Not an absolute URL — includes every relative form.\n return null;\n }\n });\n\nexport const listItemSchema = z.object({\n id: z.string().nullish(),\n label: z.string(),\n secondary: z.string().nullish(),\n badge: z.string().nullish(),\n status: z.enum(['success', 'warning', 'error', 'info', 'neutral']).nullish(),\n href: modelAuthoredHrefSchema,\n});\n\nexport const listPropsSchema = z.object({\n items: z.array(listItemSchema),\n /** Show first N items with a \"See X more\" expand control. Default 10. */\n maxVisible: z.number().int().positive().nullish(),\n});\n\n/**\n * The List schema the CATALOG (and so the generated model prompt) sees. The\n * `href` transform above is opaque to json-render's prompt printer, which\n * renders it as a required `href: unknown` — so the prompt declares the plain\n * `string?` shape the model should write, and the registry keeps parsing with\n * the sanitizing schema.\n */\nexport const listPropsPromptSchema = z.object({\n items: z.array(listItemSchema.extend({ href: z.string().nullish() })),\n maxVisible: listPropsSchema.shape.maxVisible,\n});\n\nexport const tablePropsSchema = z.object({\n columns: z.array(z.string()),\n rows: z.array(z.array(z.string())),\n caption: z.string().nullish(),\n});\n\n/** Period-over-period change on a Metric (KPI delta). */\nexport const metricDeltaSchema = z.object({\n /** Formatted change, e.g. \"+4.2 pts\" or \"-8%\". */\n value: z.string(),\n /** Change direction — colours the delta (up=green, down=red, flat=muted). */\n direction: z.enum(['up', 'down', 'flat']),\n /** Comparison context, e.g. \"vs previous 30d\". */\n label: z.string().nullish(),\n});\n\nexport const metricPropsSchema = z.object({\n label: z.string(),\n value: z.string(),\n description: z.string().nullish(),\n trend: z.enum(['up', 'down', 'neutral']).nullish(),\n delta: metricDeltaSchema.nullish(),\n});\n\nexport const calloutPropsSchema = z.object({\n type: z.enum(['info', 'tip', 'warning', 'important']).nullish(),\n title: z.string().nullish(),\n content: z.string(),\n});\n\nconst chartDatumSchema = z.object({\n label: z.string(),\n value: z.number(),\n});\n\nexport const chartPropsSchema = z.object({\n type: z.enum(['bar', 'line', 'pie']),\n data: z.array(chartDatumSchema),\n title: z.string().nullish(),\n height: z.number().int().positive().nullish(),\n /** Pie only: big number/text shown in the donut hole (e.g. the total). */\n centerLabel: z.string().nullish(),\n});\n\n// ── Tool-built cards ────────────────────────────────────────────────────────\n\n/**\n * A phone agent the OpenCX companion just created or re-presented. The model\n * never authors this itself — the `present_phone_agent` tool returns the whole\n * spec, which the reply carries verbatim.\n */\nexport const phoneAgentCardPropsSchema = z.object({\n agentId: z.string(),\n agentName: z.string(),\n model: z.string().nullish(),\n});\n\nexport type ListItem = z.infer<typeof listItemSchema>;\nexport type MetricDelta = z.infer<typeof metricDeltaSchema>;\nexport type ChartProps = z.infer<typeof chartPropsSchema>;\n\n/**\n * Parse streamed props against a schema, returning a typed `fallback` on\n * failure instead of throwing. Failures are EXPECTED during streaming (a prop\n * arrives half-formed, then completes on the next patch) and on the occasional\n * model mistake — neither is an error worth surfacing, so we degrade quietly to\n * the fallback and let the next patch re-render. This is the widget's first line\n * of defense: one bad prop can never crash the whole spec render.\n */\nexport function parseProps<Schema extends z.ZodType>(\n schema: Schema,\n raw: unknown,\n fallback: z.output<Schema>,\n): z.output<Schema> {\n const result = schema.safeParse(raw);\n return result.success ? result.data : fallback;\n}\n","import { defineCatalog } from '@json-render/core';\nimport { schema } from '@json-render/react/schema';\nimport {\n badgePropsSchema,\n calloutPropsSchema,\n cardPropsSchema,\n chartPropsSchema,\n gridPropsSchema,\n headingPropsSchema,\n listPropsPromptSchema,\n metricPropsSchema,\n phoneAgentCardPropsSchema,\n stackPropsSchema,\n tablePropsSchema,\n textPropsSchema,\n} from './props';\n\n/**\n * The widget's json-render catalog — the closed set of components the agent may\n * emit. It is the single source of truth in two directions: `registry.tsx`\n * binds each name to a React renderer, and the backend prompt is generated from\n * this same catalog (see `ui-prompt.ts`, codegen-only — never imported by the\n * shipped widget), so the model can never emit a component the widget can't\n * render.\n *\n * Kept deliberately small and embed-light (no per-org customization in v1):\n * layout primitives + list / table / metric / callout / chart. `description`\n * and `example` are the model's only guidance — they steer generation, so keep\n * them tight.\n */\nexport const widgetCatalog = defineCatalog(schema, {\n components: {\n Card: {\n props: cardPropsSchema,\n slots: ['default'],\n description:\n 'Container card with an optional title/description. Group related content.',\n example: { title: 'Order summary', description: 'Placed 2 days ago' },\n },\n Stack: {\n props: stackPropsSchema,\n slots: ['default'],\n description:\n 'Flex layout. Use direction=\"row\" for side-by-side, \"column\" (default) to stack.',\n },\n Grid: {\n props: gridPropsSchema,\n slots: ['default'],\n description:\n 'Column grid that wraps on narrow screens. columns=2 for side-by-side metrics or cards; columns=3 only for three short metrics — the chat panel is about 400px wide, so three wide cells wrap.',\n },\n Heading: {\n props: headingPropsSchema,\n description: 'Section heading. level 1 (largest) to 4.',\n example: { text: 'Your orders', level: 3 },\n },\n Text: {\n props: textPropsSchema,\n description:\n 'A paragraph of text. variant \"muted\"/\"caption\" for secondary text, \"code\" for monospace.',\n },\n Badge: {\n props: badgePropsSchema,\n description:\n 'Small status pill. Use variant to convey state (success/warning/destructive).',\n example: { text: 'Delivered', variant: 'success' },\n },\n List: {\n props: listPropsPromptSchema,\n description:\n 'A vertical list of items, each with a label and optional secondary text, badge, and status dot. Pass the full array in `items` — do NOT use repeat/state for the rows.',\n example: {\n items: [\n { label: 'Order #1024', secondary: 'Shipped', status: 'success' },\n { label: 'Order #1025', secondary: 'Processing', status: 'warning' },\n ],\n },\n },\n Table: {\n props: tablePropsSchema,\n description:\n 'A data table. `columns` are header strings; `rows` is a 2D array of cell strings (each row same length as columns).',\n example: {\n columns: ['Item', 'Qty', 'Price'],\n rows: [\n ['Widget', '2', '$20'],\n ['Gadget', '1', '$15'],\n ],\n },\n },\n Metric: {\n props: metricPropsSchema,\n description:\n 'A single key figure (KPI / insight card) with a label, big value, optional description, trend arrow, and an optional period-over-period delta ({ value, direction, label }).',\n example: {\n label: 'Total spent',\n value: '$1,240',\n description: 'Last 30 days',\n trend: 'up',\n delta: { value: '+8%', direction: 'up', label: 'vs previous 30d' },\n },\n },\n Callout: {\n props: calloutPropsSchema,\n description:\n 'A highlighted info / tip / warning box for a single important note. Use for one call-out, not for long prose.',\n example: {\n type: 'tip',\n title: 'Heads up',\n content: 'Free shipping over $50.',\n },\n },\n PhoneAgentCard: {\n props: phoneAgentCardPropsSchema,\n description:\n 'A phone agent card with a \"Test via web\" action. NEVER author this yourself: it only comes back, already fenced, from the phone-agent tools — carry that fence verbatim.',\n example: {\n agentId: '00000000-0000-4000-8000-000000000000',\n agentName: 'Support line',\n model: 'oppie-vox-livekit',\n },\n },\n Chart: {\n props: chartPropsSchema,\n description:\n 'A bar, line, or pie (donut) chart. `data` is an array of { label, value } points. Choose by the question: line = trend over time, bar = comparison across categories, pie = share of a total (optional `centerLabel` shows a big number in the donut hole). Use for trends or distributions, not for a handful of numbers (use Metric for those). Colours, axes, legend, and tooltips are handled for you.',\n example: {\n type: 'bar',\n title: 'Orders per month',\n data: [\n { label: 'Jan', value: 12 },\n { label: 'Feb', value: 18 },\n ],\n },\n },\n },\n actions: {},\n});\n","import React from 'react';\n\n/**\n * The placeholder a container shows while its spec is still streaming and it\n * has nothing to paint yet — the same pulse the lazy Chart holds its space\n * with (`ChartShimmer` in `Chart.tsx`), so an empty Card, List, Table, Grid or\n * Stack mid-stream reads as \"loading\" rather than as a bare frame or an \"empty\"\n * message that flips to content a moment later.\n */\nexport function StreamingShimmer({ height = 64 }: { height?: number }) {\n return (\n <div\n className=\"w-full animate-pulse rounded-lg bg-muted-foreground/10\"\n style={{ height }}\n aria-hidden\n />\n );\n}\n","import { defineRegistry, type ComponentRenderer } from '@json-render/react';\nimport {\n AlertCircle,\n AlertTriangle,\n ChevronDown,\n ChevronUp,\n Info,\n Lightbulb,\n Phone,\n Play,\n} from 'lucide-react';\nimport React, { useState } from 'react';\nimport { cn } from '../components/lib/utils/cn';\nimport { useJsonRenderHost } from './host';\nimport { Chart as ChartView } from './Chart';\nimport { widgetCatalog } from './catalog';\nimport { StreamingShimmer } from './StreamingShimmer';\nimport {\n badgePropsSchema,\n calloutPropsSchema,\n cardPropsSchema,\n chartPropsSchema,\n gridPropsSchema,\n headingPropsSchema,\n listPropsSchema,\n metricPropsSchema,\n parseProps,\n phoneAgentCardPropsSchema,\n stackPropsSchema,\n tablePropsSchema,\n textPropsSchema,\n type ListItem,\n type MetricDelta,\n} from './props';\n\n/**\n * Binds every catalog component to a widget React renderer. Built on the\n * widget's own primitives (tailwind semantic tokens + lucide) — no @open/hoose,\n * tanstack-table, or eager recharts — so the embed stays light. Every render fn\n * re-parses its streamed props through the schema (`parseProps`) so a malformed\n * or half-streamed prop degrades to a safe default instead of throwing.\n *\n * `defineRegistry`'s type checking makes this map exhaustive against the\n * catalog: renderer and catalog can't drift.\n *\n * `loading` is the renderer's \"this spec is still streaming\" flag\n * (`SpecRenderer`'s `active`). A container whose content has not arrived yet\n * shows the shimmer instead of a bare frame or its settled empty state — a\n * Card's children, a List's items and a Table's rows all land patches after\n * the container itself.\n */\n\nconst GAP_CLASS = { sm: 'gap-1.5', md: 'gap-3', lg: 'gap-4' } as const;\n// The prompt's contract is \"Grid columns max 3\" (compact chat widget).\n/**\n * Narrowest a grid cell may get before the row wraps. A metric card needs\n * about this much for its label, number and caption to stay readable.\n */\nconst GRID_MIN_COLUMN = '10rem';\n\n/**\n * `columns` is a CEILING, not a promise: the model asks for up to three\n * side-by-side cells, the container decides how many actually fit. Each cell\n * is at least a third/half of the width (so never more columns than asked)\n * and at least `GRID_MIN_COLUMN` (so a 400px compact panel wraps a\n * three-up into two and one). Column count is schema-clamped to 1–3.\n */\nfunction gridColumns(columns: 1 | 2 | 3): string {\n if (columns === 1) return 'minmax(0, 1fr)';\n return `repeat(auto-fit, minmax(max(${GRID_MIN_COLUMN}, calc(100% / ${columns} - 1rem)), 1fr))`;\n}\n\nexport const { registry } = defineRegistry(widgetCatalog, {\n components: {\n Card: ({ props, children, loading }) => {\n const p = parseProps(cardPropsSchema, props, {});\n return (\n <div className=\"flex flex-col gap-2 rounded-xl border border-muted-foreground/15 p-3\">\n {(p.title || p.description) && (\n <div className=\"flex flex-col gap-0.5\">\n {p.title && (\n <div className=\"text-sm font-semibold text-foreground\">\n {p.title}\n </div>\n )}\n {p.description && (\n <div className=\"text-xs text-muted-foreground\">\n {p.description}\n </div>\n )}\n </div>\n )}\n {containerBody(children, loading)}\n </div>\n );\n },\n\n Stack: ({ props, children, loading }) => {\n const p = parseProps(stackPropsSchema, props, {});\n const align = {\n start: 'items-start',\n center: 'items-center',\n end: 'items-end',\n stretch: 'items-stretch',\n }[p.align ?? 'stretch'];\n const justify = {\n start: 'justify-start',\n center: 'justify-center',\n end: 'justify-end',\n between: 'justify-between',\n }[p.justify ?? 'start'];\n return (\n <div\n className={cn(\n 'flex',\n p.direction === 'row' ? 'flex-row' : 'flex-col',\n GAP_CLASS[p.gap ?? 'md'],\n align,\n justify,\n )}\n >\n {containerBody(children, loading)}\n </div>\n );\n },\n\n Grid: ({ props, children, loading }) => {\n const p = parseProps(gridPropsSchema, props, {});\n return (\n <div\n className={cn('grid', GAP_CLASS[p.gap ?? 'md'])}\n style={{ gridTemplateColumns: gridColumns(p.columns ?? 1) }}\n >\n {containerBody(children, loading)}\n </div>\n );\n },\n\n Heading: ({ props }) => {\n const p = parseProps(headingPropsSchema, props, { text: '' });\n const level = p.level ?? 3;\n const size =\n {\n 1: 'text-xl font-bold',\n 2: 'text-lg font-bold',\n 3: 'text-base font-semibold',\n 4: 'text-sm font-semibold',\n }[level] ?? 'text-base font-semibold';\n return React.createElement(\n `h${level}`,\n { className: cn('text-foreground', size) },\n p.text,\n );\n },\n\n Text: ({ props }) => {\n const p = parseProps(textPropsSchema, props, { text: '' });\n if (p.variant === 'code') {\n return (\n <code className=\"rounded bg-muted px-1.5 py-0.5 font-mono text-xs text-foreground\">\n {p.text}\n </code>\n );\n }\n const muted = p.variant === 'muted' || p.variant === 'caption';\n return (\n <p\n className={cn(\n 'whitespace-pre-wrap',\n muted ? 'text-xs text-muted-foreground' : 'text-sm text-foreground',\n )}\n >\n {p.text}\n </p>\n );\n },\n\n Badge: ({ props }) => {\n const p = parseProps(badgePropsSchema, props, { text: '' });\n const variant = {\n default: 'bg-primary text-primary-foreground',\n secondary: 'bg-secondary text-secondary-foreground',\n success: 'bg-emerald-500/15 text-emerald-600 dark:text-emerald-400',\n warning: 'bg-amber-500/15 text-amber-600 dark:text-amber-400',\n destructive: 'bg-destructive/15 text-destructive',\n }[p.variant ?? 'secondary'];\n return (\n <span\n className={cn(\n 'inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium',\n variant,\n )}\n >\n {p.text}\n </span>\n );\n },\n\n List: ({ props, loading }) => {\n const p = parseProps(listPropsSchema, props, { items: [] });\n if (p.items.length === 0) {\n return loading ? (\n <StreamingShimmer />\n ) : (\n <EmptyState translationKey=\"json_no_items\" />\n );\n }\n return <CompactList items={p.items} maxVisible={p.maxVisible} />;\n },\n\n Table: ({ props, loading }) => {\n const p = parseProps(tablePropsSchema, props, { columns: [], rows: [] });\n // Header-only mid-stream is still \"nothing to read yet\".\n if (loading && p.rows.length === 0) return <StreamingShimmer />;\n if (p.columns.length === 0) {\n return <EmptyState translationKey=\"json_no_data\" />;\n }\n return (\n <div className=\"overflow-x-auto rounded-lg border border-muted-foreground/15\">\n <table className=\"w-full text-sm\">\n {p.caption && (\n <caption className=\"px-3 py-2 text-start text-xs text-muted-foreground\">\n {p.caption}\n </caption>\n )}\n <thead>\n <tr className=\"border-b border-muted-foreground/15 bg-muted/40\">\n {p.columns.map((c, i) => (\n <th\n key={i}\n className=\"px-3 py-2 text-start font-medium text-foreground\"\n >\n {c}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {p.rows.map((row, ri) => (\n <tr\n key={ri}\n className=\"border-b border-muted-foreground/10 last:border-0\"\n >\n {row.map((cell, ci) => (\n <td key={ci} className=\"px-3 py-2 text-muted-foreground\">\n {cell}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n },\n\n Metric: ({ props }) => {\n const p = parseProps(metricPropsSchema, props, { label: '', value: '' });\n return (\n <MetricCard\n label={p.label}\n value={p.value}\n description={p.description}\n trend={p.trend}\n delta={p.delta}\n />\n );\n },\n\n Callout: ({ props }) => {\n const p = parseProps(calloutPropsSchema, props, { content: '' });\n const style = CALLOUT_STYLES[p.type ?? 'info'];\n const Icon = style.Icon;\n return (\n <div className={cn('flex gap-2 rounded-lg border-l-2 p-3', style.cls)}>\n <Icon className=\"mt-0.5 size-4 shrink-0\" />\n <div className=\"flex flex-col gap-0.5\">\n {p.title && (\n <span className=\"text-sm font-semibold\">{p.title}</span>\n )}\n <span className=\"text-sm\">{p.content}</span>\n </div>\n </div>\n );\n },\n\n PhoneAgentCard: ({ props }) => {\n const p = parseProps(phoneAgentCardPropsSchema, props, {\n agentId: '',\n agentName: '',\n });\n return <PhoneAgentCard {...p} />;\n },\n\n Chart: ({ props }) => {\n const p = parseProps(chartPropsSchema, props, { type: 'bar', data: [] });\n return (\n <div className=\"flex flex-col gap-1\">\n {p.title && (\n <span className=\"text-xs font-medium text-muted-foreground\">\n {p.title}\n </span>\n )}\n <ChartView {...p} />\n </div>\n );\n },\n },\n});\n\n/** Rendered for any element whose `type` isn't in the registry. */\nexport const JsonRenderFallback: ComponentRenderer = ({ element }) => {\n const { t } = useJsonRenderHost();\n return (\n <div className=\"rounded-lg border border-dashed border-muted-foreground/30 px-2 py-1.5 text-xs text-muted-foreground\">\n {t('json_unsupported', { type: element.type })}\n </div>\n );\n};\n\nconst CALLOUT_STYLES = {\n info: { Icon: Info, cls: 'border-l-blue-500 bg-blue-500/5 text-foreground' },\n tip: {\n Icon: Lightbulb,\n cls: 'border-l-emerald-500 bg-emerald-500/5 text-foreground',\n },\n warning: {\n Icon: AlertTriangle,\n cls: 'border-l-amber-500 bg-amber-500/5 text-foreground',\n },\n important: {\n Icon: AlertCircle,\n cls: 'border-l-red-500 bg-red-500/5 text-foreground',\n },\n} as const;\n\n/**\n * A layout container's body: its rendered children, or the shimmer while the\n * spec is still streaming and none have landed. `toArray` drops the `null`\n * the renderer emits for a child key whose element has not arrived yet, so a\n * `Card` whose first patch already names its children still counts as empty.\n */\nfunction containerBody(\n children: React.ReactNode,\n loading: boolean | undefined,\n): React.ReactNode {\n if (React.Children.toArray(children).length > 0) return children;\n return loading ? <StreamingShimmer /> : null;\n}\n\nfunction EmptyState({\n translationKey,\n}: {\n translationKey: 'json_no_items' | 'json_no_data';\n}) {\n const { t } = useJsonRenderHost();\n return (\n <div className=\"rounded-lg border border-muted-foreground/15 px-3 py-2 text-xs text-muted-foreground\">\n {t(translationKey)}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// PhoneAgentCard — tool-built card; the action is the host's to complete\n// (`onUiAction`), so without a handler it is a plain summary card.\nconst TESTABLE_PHONE_AGENT_MODEL = 'oppie-vox-livekit';\n\nfunction PhoneAgentCard({\n agentId,\n agentName,\n model,\n}: {\n agentId: string;\n agentName: string;\n model?: string | null;\n}) {\n const { t, onUiAction } = useJsonRenderHost();\n const canTest =\n Boolean(onUiAction) &&\n Boolean(agentId) &&\n model === TESTABLE_PHONE_AGENT_MODEL;\n return (\n <div className=\"flex w-full flex-col gap-3 rounded-xl border border-muted-foreground/15 p-3\">\n <div className=\"flex items-center gap-3\">\n <div className=\"flex size-8 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-primary\">\n <Phone className=\"size-4\" aria-hidden />\n </div>\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-sm font-medium text-foreground\">\n {agentName}\n </div>\n <div className=\"text-xs text-muted-foreground\">\n {t('json_phone_agent')}\n </div>\n </div>\n </div>\n {canTest && (\n <button\n type=\"button\"\n className=\"flex w-full items-center justify-center gap-2 rounded-lg bg-secondary px-3 py-2 text-sm font-medium text-secondary-foreground hover:bg-secondary/80\"\n onClick={() =>\n onUiAction?.({\n type: 'test-phone-agent',\n payload: { agentId, model: model ?? null },\n })\n }\n >\n <Play className=\"size-4\" aria-hidden />\n {t('json_phone_agent_test')}\n </button>\n )}\n </div>\n );\n}\n\n// Metric — KPI card (text arrows + delta)\n// ---------------------------------------------------------------------------\n\nconst TREND_ICONS = {\n up: '\\u2191',\n down: '\\u2193',\n neutral: '\\u2192',\n} as const;\nconst TREND_COLORS = {\n up: 'text-emerald-600 dark:text-emerald-400',\n down: 'text-red-600 dark:text-red-400',\n neutral: 'text-muted-foreground',\n} as const;\n// KPI delta: direction is the change direction (not good/bad). flat = no change.\nconst DELTA_ICONS = { up: '\\u2191', down: '\\u2193', flat: '\\u2192' } as const;\nconst DELTA_COLORS = {\n up: 'text-emerald-600 dark:text-emerald-400',\n down: 'text-red-600 dark:text-red-400',\n flat: 'text-muted-foreground',\n} as const;\n\nfunction MetricCard({\n label,\n value,\n description,\n trend,\n delta,\n}: {\n label: string;\n value: string;\n description?: string | null;\n trend?: 'up' | 'down' | 'neutral' | null;\n delta?: MetricDelta | null;\n}) {\n return (\n <div className=\"min-w-[140px] space-y-1 rounded-xl border border-muted-foreground/15 p-3\">\n <span className=\"text-xs font-medium text-muted-foreground\">{label}</span>\n <div className=\"flex items-baseline gap-2\">\n <span className=\"text-2xl font-medium tracking-tight text-foreground\">\n {value}\n </span>\n {trend ? (\n <span className={cn('text-sm font-medium', TREND_COLORS[trend])}>\n {TREND_ICONS[trend]}\n </span>\n ) : null}\n </div>\n {delta ? (\n <div className=\"flex items-baseline gap-1 text-xs\">\n <span className={cn('font-medium', DELTA_COLORS[delta.direction])}>\n {DELTA_ICONS[delta.direction]} {delta.value}\n </span>\n {delta.label ? (\n <span className=\"text-muted-foreground\">{delta.label}</span>\n ) : null}\n </div>\n ) : null}\n {description ? (\n <span className=\"block text-xs text-muted-foreground\">\n {description}\n </span>\n ) : null}\n </div>\n );\n}\n\n// ---------------------------------------------------------------------------\n// List — compact item list (aligned subgrid columns: badge | label |\n// secondary | status, with a \"See X more\" expander)\n// ---------------------------------------------------------------------------\n\nconst STATUS_COLORS = {\n success: 'bg-emerald-500',\n warning: 'bg-amber-500',\n error: 'bg-red-500',\n info: 'bg-blue-500',\n neutral: 'bg-muted-foreground/40',\n} as const;\n\nfunction ListItemContent({\n item,\n showBadge,\n showSecondary,\n showStatus,\n}: {\n item: ListItem;\n showBadge: boolean;\n showSecondary: boolean;\n showStatus: boolean;\n}) {\n return (\n <>\n {showBadge &&\n (item.badge ? (\n <span\n className=\"block min-w-0 truncate text-xs font-medium\"\n title={item.badge}\n >\n {item.badge}\n </span>\n ) : (\n <span />\n ))}\n <span className=\"block min-w-0 truncate\" title={item.label}>\n {item.label}\n </span>\n {showSecondary &&\n (item.secondary ? (\n <span\n className=\"block min-w-0 truncate text-xs text-muted-foreground\"\n title={item.secondary}\n >\n {item.secondary}\n </span>\n ) : (\n <span />\n ))}\n {showStatus &&\n (item.status ? (\n <span\n className={cn('size-2 rounded-full', STATUS_COLORS[item.status])}\n aria-hidden\n />\n ) : (\n <span />\n ))}\n </>\n );\n}\n\n/**\n * One CSS grid so badge/label/secondary/status columns align across rows\n * (subgrid rows), link rows for `href`, and a \"See X more\" expander past\n * `maxVisible` (default 10). Dashboard-only affordances (audio preview,\n * send-message actions) are intentionally not carried over.\n */\nfunction CompactList({\n items,\n maxVisible,\n}: {\n items: ListItem[];\n maxVisible?: number | null;\n}) {\n const limit = maxVisible ?? 10;\n // Same configured link target as RichText anchors — the embed decides where\n // links open (defaulting to the host page's top frame).\n const { anchorTarget, t } = useJsonRenderHost();\n const [expanded, setExpanded] = useState(false);\n const showExpand = items.length > limit;\n const visible = expanded ? items : items.slice(0, limit);\n\n const hasBadge = visible.some((it) => Boolean(it.badge));\n const hasSecondary = visible.some((it) => Boolean(it.secondary));\n const hasStatus = visible.some((it) => Boolean(it.status));\n\n const gridCols = [\n hasBadge && 'auto',\n 'minmax(0,1fr)',\n hasSecondary && 'minmax(0,2fr)',\n hasStatus && 'auto',\n ]\n .filter(Boolean)\n .join(' ');\n\n const rowClass =\n 'grid min-w-0 grid-cols-[subgrid] col-span-full items-center gap-x-2.5 px-3 py-2 text-sm text-foreground';\n\n return (\n <div\n className=\"grid overflow-hidden rounded-lg border border-muted-foreground/15\"\n style={{ gridTemplateColumns: gridCols }}\n >\n {visible.map((item, i) => {\n const rowKey = item.id ?? `row-${i}`;\n const content = (\n <ListItemContent\n item={item}\n showBadge={hasBadge}\n showSecondary={hasSecondary}\n showStatus={hasStatus}\n />\n );\n return item.href ? (\n <a\n key={rowKey}\n href={item.href}\n target={anchorTarget || '_top'}\n rel=\"noopener noreferrer\"\n className={cn(\n rowClass,\n 'transition-colors hover:bg-muted/50',\n i > 0 && 'border-t border-muted-foreground/10',\n )}\n >\n {content}\n </a>\n ) : (\n <div\n key={rowKey}\n className={cn(\n rowClass,\n i > 0 && 'border-t border-muted-foreground/10',\n )}\n >\n {content}\n </div>\n );\n })}\n {showExpand && (\n <button\n type=\"button\"\n className=\"col-span-full flex w-full items-center justify-center gap-1 border-t border-muted-foreground/10 py-2 text-xs text-muted-foreground transition-colors hover:bg-muted/50\"\n onClick={() => setExpanded((v) => !v)}\n >\n {expanded ? (\n <>\n <ChevronUp className=\"size-3\" />\n {t('json_see_less')}\n </>\n ) : (\n <>\n <ChevronDown className=\"size-3\" />\n {t('json_see_more', { count: items.length - limit })}\n </>\n )}\n </button>\n )}\n </div>\n );\n}\n","import { isNonEmptySpec, type Spec } from '@json-render/core';\nimport { JSONUIProvider, Renderer } from '@json-render/react';\nimport type { WidgetUiAction } from '@opencx/widget-core';\nimport { useConfig } from '@opencx/widget-react-headless';\nimport React, { useMemo } from 'react';\nimport { useTranslation } from '../hooks/useTranslation';\nimport {\n JsonRenderHostProvider,\n useHostFromProps,\n type JsonRenderHost,\n} from './host';\nimport { JsonRenderErrorBoundary } from './JsonRenderErrorBoundary';\nimport { inlineRepeatLeaves } from './normalize-spec';\nimport { JsonRenderFallback, registry } from './registry';\n\n/**\n * The single seam every json-render spec funnels through — both the live\n * streamed turn and persisted (fence-parsed) history go through here, so both\n * get the same recovery + defenses.\n *\n * Applies leaf-`repeat` recovery, guards empty/partial specs, and renders under\n * a per-spec state provider (so `{ \"$state\": \"/path\" }` refs resolve against\n * THIS spec's own state) wrapped in an error boundary.\n *\n * `active` says the spec is still being streamed: containers with nothing to\n * paint yet show a shimmer instead of their settled empty state. History and\n * settled turns leave it off.\n */\nexport function SpecRenderer({\n spec,\n active = false,\n}: {\n spec: Spec | null;\n active?: boolean;\n}) {\n const { anchorTarget, onUiAction } = useConfig();\n const { t } = useTranslation();\n const host = useMemo<JsonRenderHost>(\n () => ({ t, anchorTarget: anchorTarget ?? '_blank', onUiAction }),\n [t, anchorTarget, onUiAction],\n );\n return <HostedSpec spec={spec} host={host} active={active} />;\n}\n\n/**\n * The same renderer for a page that is not the widget but shows what the\n * widget showed — the OpenCX inbox. The host supplies what the widget would\n * have read from its config; nothing else about rendering differs, so a\n * customer and the agent reading their session see one and the same card.\n */\nexport function HostedSpecRenderer({\n spec,\n language,\n onUiAction,\n anchorTarget,\n}: {\n spec: Spec | null;\n language?: string;\n onUiAction?: (action: WidgetUiAction) => void;\n anchorTarget?: string;\n}) {\n const host = useHostFromProps({ language, onUiAction, anchorTarget });\n return <HostedSpec spec={spec} host={host} />;\n}\n\nfunction HostedSpec({\n spec,\n host,\n active = false,\n}: {\n spec: Spec | null;\n host: JsonRenderHost;\n active?: boolean;\n}) {\n return (\n <JsonRenderHostProvider host={host}>\n <JsonRenderErrorBoundary resetKey={spec}>\n <NormalizedSpec spec={spec} active={active} />\n </JsonRenderErrorBoundary>\n </JsonRenderHostProvider>\n );\n}\n\nfunction NormalizedSpec({\n spec,\n active,\n}: {\n spec: Spec | null;\n active: boolean;\n}) {\n const normalized = useMemo(\n () => (spec ? inlineRepeatLeaves(spec) : null),\n [spec],\n );\n\n // Nothing to show until the spec has at least a root + one element. Guards the\n // gap between \"spec object exists\" and \"first patch applied\" during streaming.\n if (!normalized || !isNonEmptySpec(normalized)) return null;\n\n return (\n <JSONUIProvider registry={registry} initialState={normalized.state}>\n <Renderer\n spec={normalized}\n registry={registry}\n loading={active}\n fallback={JsonRenderFallback}\n />\n </JSONUIProvider>\n );\n}\n","import {\n compileSpecStream,\n isNonEmptySpec,\n parseSpecStreamLine,\n type Spec,\n} from '@json-render/core';\n\nexport type ContentSegment =\n | { type: 'markdown'; content: string }\n | { type: 'ui'; spec: Spec };\n\n/**\n * Segment persisted AI output into markdown prose and compiled UI specs.\n *\n * The agent chat stream transforms ` ```spec ` fences into `data-spec` parts\n * ONLY on the client-facing SSE — the persisted assistant text keeps the raw\n * fence (persist raw, transform on serve). So the history path re-derives the\n * spec from the stored text here.\n *\n * There is exactly ONE spec format: JSONL patch lines — what the prompt\n * instructs the model to emit inside a ` ```spec ` fence and what every tool\n * that hands back a card emits. A model that forgets the fence still emits the\n * same lines, and the live stream renders them as UI regardless (its transform\n * drains every patch-shaped line, fenced or not), so a run of consecutive bare\n * patch lines outside any fence is a spec block too — otherwise a reloaded\n * transcript shows raw JSON where the customer watched a card.\n *\n * Everything else is markdown. A spec block (fenced or bare) is consumed only\n * after its patches compile to renderable UI; malformed, unsupported, empty,\n * and incomplete-only blocks remain visible as their original text. An\n * unclosed fence (turn cut mid-stream) still compiles when enough valid\n * patches arrived, and a cut-off patch line ending a bare run at the very end\n * of the text is the run's tail, never a stray `{\"op\":...` bubble.\n */\nexport function segmentContent(text: string): ContentSegment[] {\n if (!text) return [];\n\n const lines = text.split('\\n');\n const segments: ContentSegment[] = [];\n\n let markdownLines: string[] = [];\n // The spec block being gathered (a fence or a bare run): every raw line it\n // covers, restored verbatim when it does not compile, and the subset that\n // parsed as patches.\n let blockLines: string[] = [];\n let patchLines: string[] = [];\n let inFence = false;\n let inBareRun = false;\n\n function flushMarkdown() {\n if (markdownLines.length === 0) return;\n const content = markdownLines.join('\\n');\n if (content.trim()) {\n segments.push({ type: 'markdown', content });\n }\n markdownLines = [];\n }\n\n function flushSpecBlock() {\n if (blockLines.length === 0) return;\n\n let compiled: Spec | null = null;\n if (patchLines.length > 0) {\n try {\n compiled = compileSpecStream(patchLines.join('\\n'), {\n root: '',\n elements: {},\n });\n } catch {\n // A syntactically parseable but unsupported patch must not erase the\n // agent's source. The raw block is restored below.\n }\n }\n\n if (compiled && isRenderableSpec(compiled)) {\n flushMarkdown();\n segments.push({ type: 'ui', spec: compiled });\n } else {\n markdownLines.push(...blockLines);\n }\n\n patchLines = [];\n blockLines = [];\n }\n\n function endBareRun() {\n if (!inBareRun) return;\n flushSpecBlock();\n inBareRun = false;\n }\n\n for (let index = 0; index < lines.length; index += 1) {\n const line = lines[index] ?? '';\n const trimmed = line.trim();\n const isLast = index === lines.length - 1;\n\n // ```spec fence open\n if (!inFence && trimmed === '```spec') {\n endBareRun();\n inFence = true;\n blockLines = [line];\n continue;\n }\n\n // ``` fence close\n if (inFence && trimmed === '```') {\n blockLines.push(line);\n flushSpecBlock();\n inFence = false;\n continue;\n }\n\n // Inside the fence: keep parseable patch lines, skip everything else\n // (malformed JSON, an incomplete trailing line mid-stream).\n if (inFence) {\n blockLines.push(line);\n if (trimmed !== '' && parseSpecStreamLine(line)) {\n patchLines.push(line);\n }\n continue;\n }\n\n // Outside any fence: a patch-shaped line starts or extends a bare run.\n if (trimmed !== '' && parseSpecStreamLine(line)) {\n inBareRun = true;\n blockLines.push(line);\n patchLines.push(line);\n continue;\n }\n\n if (inBareRun) {\n // Blank lines between patches stay in the run (the fence path skips\n // them the same way); a cut-off patch line at the very end of the text\n // is the run's tail. Both restore with the run when it does not compile.\n if (trimmed === '' || (isLast && isCutPatchLine(trimmed))) {\n blockLines.push(line);\n continue;\n }\n endBareRun();\n }\n\n markdownLines.push(line);\n }\n\n // Unclosed fence or trailing bare run (turn cut mid-stream): compile what\n // arrived.\n flushSpecBlock();\n flushMarkdown();\n\n return segments;\n}\n\n/**\n * A spec the renderer can actually paint: nonempty AND its root element\n * present. A block that compiles to elements without a root (or a root whose\n * element never arrived) would be consumed and then render nothing — the\n * agent's source must stay visible instead.\n */\nfunction isRenderableSpec(spec: Spec): boolean {\n return isNonEmptySpec(spec) && spec.elements[spec.root] !== undefined;\n}\n\n/** How every patch line opens, the yardstick a cut fragment is measured against. */\nconst PATCH_LINE_OPENING = '{\"op\":';\n\n/**\n * A JSON line the stream cut before its closing brace — and only one that\n * could still have become a patch: it already names `op`, or it stopped\n * inside the opening `{\"op\":` itself. Something else the model started on its\n * own line (`{\"explanation\":`) is its own text and stays visible.\n */\nfunction isCutPatchLine(trimmed: string): boolean {\n if (!trimmed.startsWith('{') || trimmed.endsWith('}')) return false;\n if (/\"op\"\\s*:/.test(trimmed)) return true;\n return PATCH_LINE_OPENING.startsWith(trimmed.replace(/\\s+/g, ''));\n}\n","/**\n * Widget json-render module — renders the agent chat stream's composable UI\n * (list / table / chart / metric) from json-render `data-spec` parts. Built on\n * bundled `@json-render/core` + `@json-render/react` implementations pinned at\n * 0.19.0. They stay behind this module instead of becoming peer requirements\n * for widget consumers.\n *\n * This barrel is the module's render seam:\n * - `SpecRenderer` — the in-widget render seam (streaming + history).\n * - `HostedSpecRenderer` + `segmentContent` — the same renderer and the same\n * fence parser for a host page that shows widget transcripts (the OpenCX\n * inbox), so there is one catalog and one implementation of every card.\n * - `buildSpec` — assemble a spec from a message's `data-spec` parts.\n *\n * The catalog, registry, and normalizer stay internal; in-module consumers\n * import those files directly.\n */\nimport { type Spec } from '@json-render/core';\nimport { buildSpecFromParts, type DataPart } from '@json-render/react';\n\nexport { HostedSpecRenderer, SpecRenderer } from './SpecRenderer';\nexport { segmentContent, type ContentSegment } from './segment-content';\n\n/**\n * Assemble the accumulated element-tree spec from a message's `data-spec` parts\n * (the json-render patches `pipeJsonRender` emitted server-side). Returns `null`\n * when the message carries no spec parts. Thin wrapper over `buildSpecFromParts`\n * so the stream-mapping layer depends on this module, not the library directly.\n */\nexport function buildSpec(parts: DataPart[]): Spec | null {\n return buildSpecFromParts(parts);\n}\n","import type { OpenCxComponentNameU } from '@opencx/widget-core';\n\n/**\n * A silly util to help with the component name type safety.\n */\nexport function dc(componentName: OpenCxComponentNameU) {\n return { 'data-component': componentName };\n}\n","export type SpreadsheetKind = 'csv' | 'excel';\n\nexport type Spreadsheet = {\n kind: SpreadsheetKind;\n label: string;\n mimes: string[];\n extensions: string[];\n};\n\n// Browsers report spreadsheets inconsistently (a .csv can arrive as\n// application/vnd.ms-excel or application/octet-stream), so match on file\n// extension before MIME.\nconst SPREADSHEETS: Spreadsheet[] = [\n {\n kind: 'csv',\n label: 'CSV',\n mimes: ['text/csv', 'application/csv'],\n extensions: ['csv'],\n },\n {\n kind: 'excel',\n label: 'Excel',\n mimes: [\n 'application/vnd.ms-excel',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',\n ],\n extensions: ['xls', 'xlsx'],\n },\n];\n\n// react-dropzone accept map (MIME → dotted extensions), derived so the\n// accepted types stay defined in one place.\nexport const SPREADSHEET_ACCEPT: Record<string, string[]> = Object.fromEntries(\n SPREADSHEETS.flatMap((sheet) =>\n sheet.mimes.map((mime) => [mime, sheet.extensions.map((ext) => `.${ext}`)]),\n ),\n);\n\n// react-dropzone accept map for videos (screen recordings and the like).\nexport const VIDEO_ACCEPT: Record<string, string[]> = {\n 'video/mp4': ['.mp4'],\n 'video/webm': ['.webm'],\n 'video/quicktime': ['.mov'],\n};\n\nexport function getSpreadsheet({\n type,\n name,\n}: {\n type: string;\n name: string;\n}): Spreadsheet | null {\n const ext = name.split('.').pop()?.toLowerCase() ?? '';\n const mime = type.toLowerCase().split(';')[0]?.trim() ?? '';\n // Extension wins over MIME, so check every extension before any MIME.\n return (\n SPREADSHEETS.find((sheet) => ext && sheet.extensions.includes(ext)) ??\n SPREADSHEETS.find((sheet) => mime && sheet.mimes.includes(mime)) ??\n null\n );\n}\n","import { useState } from 'react';\n\n/**\n * Whether the visitor's primary input can hover. Hover-driven motion (pill\n * label reveal, submenu on hover) is gated off coarse pointers, where a tap\n * fires the hover events first and reads as a phantom wiggle before every\n * open. Detected once: an input modality does not change mid-session.\n */\nexport function useCanHover(): boolean {\n const [canHover] = useState(\n () =>\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(hover: hover) and (pointer: fine)').matches,\n );\n return canHover;\n}\n","import React, {\n cloneElement,\n forwardRef,\n type ReactElement,\n useState,\n} from 'react';\nimport { memo } from 'react';\nimport { useReducedMotion } from 'framer-motion';\nimport { useCanHover } from '../../hooks/useCanHover';\nimport { cn } from './utils/cn';\n\n/**\n * The maximum number of pixels the element can move in the x and y directions\n *\n * This would make very small elements wobble more visibly, and large elements would wobble more subtly\n */\nexport const WOBBLE_MAX_MOVEMENT_PIXELS = {\n x: 2,\n y: 2,\n};\n\nconst INVERSE_SCALE = true;\n\ntype ChildProps = {\n onMouseMove?: React.MouseEventHandler<HTMLElement>;\n onMouseEnter?: React.MouseEventHandler<HTMLElement>;\n onMouseLeave?: React.MouseEventHandler<HTMLElement>;\n style?: React.CSSProperties;\n className?: string;\n ref: React.ForwardedRef<HTMLElement>;\n};\n\nexport interface WobbleProps {\n children: ReactElement<ChildProps>;\n className?: string;\n scale?: number;\n off?: boolean;\n}\n\nconst Wobble = memo(\n forwardRef<HTMLElement, WobbleProps>(\n ({ children, className, scale = 1.02, off = false }, ref) => {\n const [isHovering, setIsHovering] = useState(false);\n const [movement, setMovement] = useState({ x: 0, y: 0 });\n const canHover = useCanHover();\n const shouldReduceMotion = useReducedMotion();\n\n if (off || !canHover || shouldReduceMotion) {\n return cloneElement(children, { ref: ref ?? children.props.ref });\n }\n\n const hasTranslateClass = /translate/.test(\n children.props.className || '',\n );\n if (hasTranslateClass) return children;\n\n /**\n * Thanks Mr. ChatGippity for refactoring this function\n */\n const handleMouseMove = (event: React.MouseEvent<HTMLElement>) => {\n const { clientX, clientY } = event;\n const rect = event.currentTarget.getBoundingClientRect();\n\n // Calculate mouse position relative to the center of the element\n const offsetX = clientX - (rect.left + rect.width / 2);\n const offsetY = clientY - (rect.top + rect.height / 2);\n\n // Normalize offset values to the range [-1, 1]\n const normalizedX = Math.max(\n -1,\n Math.min(1, offsetX / (rect.width / 2)),\n );\n const normalizedY = Math.max(\n -1,\n Math.min(1, offsetY / (rect.height / 2)),\n );\n\n // Scale normalized values to the desired range\n const x = normalizedX * WOBBLE_MAX_MOVEMENT_PIXELS.x;\n const y = normalizedY * WOBBLE_MAX_MOVEMENT_PIXELS.y;\n\n setMovement({ x, y });\n children.props.onMouseMove?.(event);\n };\n\n const handleMouseEnter = (event: React.MouseEvent<HTMLElement>) => {\n setIsHovering(true);\n children.props.onMouseEnter?.(event);\n };\n const handleMouseLeave = (event: React.MouseEvent<HTMLElement>) => {\n setIsHovering(false);\n setMovement({ x: 0, y: 0 });\n children.props.onMouseLeave?.(event);\n };\n\n const childStyles = {\n '--wobble-x': isHovering ? `${movement.x}px` : '0px',\n '--wobble-y': isHovering ? `${movement.y}px` : '0px',\n '--scale': INVERSE_SCALE\n ? 1 - (scale - 1) // if scale is 1.02, it becomes 0.98\n : scale,\n } as React.CSSProperties;\n\n return cloneElement(children, {\n ref,\n onMouseMove: handleMouseMove,\n onMouseEnter: handleMouseEnter,\n onMouseLeave: handleMouseLeave,\n style: {\n ...childStyles,\n ...children.props.style,\n },\n className: cn(\n 'translate-x-[var(--wobble-x)]',\n 'translate-y-[var(--wobble-y)]',\n 'hover:scale-[var(--scale)] active:hover:scale-[calc(var(--scale)-0.02)]',\n className,\n children.props.className,\n 'transition-transform duration-150 ease-[cubic-bezier(0.23,1,0.32,1)]',\n ),\n });\n },\n ),\n);\n\nWobble.displayName = 'Wobble';\n\nexport { Wobble };\n","/**\n * The widget's motion tokens (see MOTION.md) and the companion's shadow\n * materials. Surfaces are theme tokens (palette / primaryColor via cssVars\n * on the host shell) so embedder customizations apply to companion chrome\n * exactly like popover; only the shadows live here. There is no frosted\n * glass — a filter inside the iframe can only sample the iframe's own\n * document, never the host page.\n *\n * Rings and rim highlights stay whisper-faint: bright white edges read as\n * \"weird white borders\" on dark host pages.\n */\n\n/** Strong ease-out for entering/exiting chrome (fades, veils, headers). */\nexport const EASE_OUT = [0.23, 1, 0.32, 1] as const;\nexport const EASE_OUT_CSS = `cubic-bezier(${EASE_OUT.join(', ')})`;\n\n/** The default enter: a 200ms fade on `EASE_OUT`. */\nexport const FADE_TRANSITION = { duration: 0.2, ease: EASE_OUT } as const;\n\n/**\n * The 150ms micro-feedback tween: exits (50ms snappier than the enter, a\n * sanctioned asymmetry), reduced-motion stand-ins for the morph spring, and\n * the pill settling after a drag.\n */\nexport const QUICK_TWEEN = { duration: 0.15, ease: EASE_OUT } as const;\n\n/**\n * The shared morph spring: near-critically damped (ratio ≈ 1.0 at stiffness\n * 500 / mass 1), so the morph stays snappy but never overshoots. An\n * underdamped spring (damping 40 → ratio 0.89) made the companion input bar's\n * height bounce every time it settled — reads as jitter on a text composer,\n * which should feel crisp, not springy. The popover open/close rides the same\n * curve so both shells share one motion signature.\n */\nexport const MORPH_SPRING = {\n type: 'spring',\n stiffness: 500,\n damping: 45,\n mass: 1,\n} as const;\n\n/**\n * The app-frame's inset transition curve — a settling ease-out with a hint of\n * deceleration. The frame animates via a CSS transition (app-frame.ts), so\n * only the `cubic-bezier(…)` form is exported; the control points stay\n * private. The frame deliberately shares this one curve everywhere it moves\n * so the host page and the panel read as one choreography.\n */\nconst APP_FRAME_EASE = [0.32, 0.72, 0.24, 1] as const;\nexport const APP_FRAME_EASE_CSS = `cubic-bezier(${APP_FRAME_EASE.join(', ')})`;\n\n/**\n * The shell spring-interpolates between these shadows during the morph, and\n * complex values only interpolate when their structure matches — a mismatched\n * shadow count or length count makes the whole shadow snap mid-morph instead.\n * So every constant fills the same four slots (large soft, small soft, ring,\n * inset top highlight), all with explicit spread, padding unused slots with\n * transparent zero-size entries (same trick as app-frame's transparent ring).\n */\nexport const PILL_SHADOW =\n '0 2px 12px 0 rgba(0,0,0,0.18), 0 1px 4px 0 rgba(0,0,0,0), 0 0 0 1px rgba(255,255,255,0.08), inset 0 1px 0 0 rgba(255,255,255,0)';\n\nexport const DOCK_SHADOW =\n '0 8px 28px 0 rgba(0,0,0,0.10), 0 1px 4px 0 rgba(0,0,0,0), 0 0 0 1px rgba(0,0,0,0.05), inset 0 1px 0 0 rgba(255,255,255,0.5)';\n\nexport const INPUT_SHADOW =\n '0 12px 40px 0 rgba(0,0,0,0.12), 0 2px 8px 0 rgba(0,0,0,0.04), 0 0 0 1px rgba(0,0,0,0.05), inset 0 1px 0 0 rgba(255,255,255,0.5)';\n\nexport const CHAT_SHADOW =\n '0 24px 48px -16px rgba(0,0,0,0.18), 0 4px 16px 0 rgba(0,0,0,0.05), 0 0 0 1px rgba(0,0,0,0.05), inset 0 1px 0 0 rgba(255,255,255,0.5)';\n","import React from 'react';\nimport { motion, type Target } from 'framer-motion';\nimport { type ComponentProps, forwardRef } from 'react';\nimport { FADE_TRANSITION, QUICK_TWEEN } from '../../motion';\n\ntype MotionProps = ComponentProps<typeof motion.div>;\ntype AnimationDirection = 'right' | 'left' | 'up' | 'down';\nexport type MotionDivProps = MotionProps & {\n fadeIn?: AnimationDirection;\n distance?: number;\n snapExit?: boolean;\n overrides?: Overrides;\n delay?: number;\n};\n\ntype Overrides = {\n initial?: Target;\n animate?: Target;\n exit?: Target;\n};\n\nexport const ANIMATION_DISTANCE_PX = 10;\n\nconst fadeInRight = (\n distance: number,\n overrides: Overrides,\n delay: number,\n): MotionProps => ({\n initial: { opacity: 0, x: -distance, ...overrides.initial },\n animate: {\n opacity: 1,\n x: 0,\n ...overrides.animate,\n transition: { ...FADE_TRANSITION, delay },\n },\n exit: {\n opacity: 0,\n x: distance,\n ...overrides.exit,\n transition: QUICK_TWEEN,\n },\n transition: FADE_TRANSITION,\n});\n\nconst fadeInLeft = (\n distance: number,\n overrides: Overrides,\n delay: number,\n): MotionProps => ({\n initial: { opacity: 0, x: distance, ...overrides.initial },\n animate: {\n opacity: 1,\n x: 0,\n ...overrides.animate,\n transition: { ...FADE_TRANSITION, delay },\n },\n exit: {\n opacity: 0,\n x: -distance,\n ...overrides.exit,\n transition: QUICK_TWEEN,\n },\n transition: FADE_TRANSITION,\n});\n\nconst fadeInUp = (\n distance: number,\n overrides: Overrides,\n delay: number,\n): MotionProps => ({\n initial: { opacity: 0, y: distance, ...overrides.initial },\n animate: {\n opacity: 1,\n y: 0,\n ...overrides.animate,\n transition: { ...FADE_TRANSITION, delay },\n },\n exit: {\n opacity: 0,\n y: -distance,\n ...overrides.exit,\n transition: QUICK_TWEEN,\n },\n transition: FADE_TRANSITION,\n});\n\nconst fadeInDown = (\n distance: number,\n overrides: Overrides,\n delay: number,\n): MotionProps => ({\n initial: { opacity: 0, y: -distance, ...overrides.initial },\n animate: {\n opacity: 1,\n y: 0,\n ...overrides.animate,\n transition: { ...FADE_TRANSITION, delay },\n },\n exit: {\n opacity: 0,\n y: distance,\n ...overrides.exit,\n transition: QUICK_TWEEN,\n },\n transition: FADE_TRANSITION,\n});\n\nconst treasureMap: Record<\n AnimationDirection,\n (distance: number, overrides: Overrides, delay: number) => MotionProps\n> = {\n right: fadeInRight,\n left: fadeInLeft,\n up: fadeInUp,\n down: fadeInDown,\n};\n\nconst MotionDiv = forwardRef<HTMLDivElement, MotionDivProps>(\n (\n {\n fadeIn = 'down',\n distance = ANIMATION_DISTANCE_PX,\n children,\n snapExit = false,\n overrides = {},\n delay = 0,\n ...props\n },\n ref,\n ) => {\n const fadeInProps: MotionProps = fadeIn\n ? treasureMap[fadeIn](distance, overrides, delay)\n : {};\n\n if (\n snapExit &&\n fadeInProps.exit &&\n typeof fadeInProps.exit === 'object' &&\n !Array.isArray(fadeInProps.exit)\n ) {\n fadeInProps.exit.transition = { duration: 0 };\n }\n\n return (\n <motion.div ref={ref} {...props} {...fadeInProps}>\n {children}\n </motion.div>\n );\n },\n);\nMotionDiv.displayName = 'MotionDiv';\n\nexport { MotionDiv };\n","import * as React from 'react';\nimport { Slot } from '@radix-ui/react-slot';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Wobble } from './wobble';\nimport { cn } from './utils/cn';\nimport { dc } from '../../utils/data-component';\n\nconst buttonVariants = cva(\n cn(\n 'inline-flex shrink-0 items-center justify-center gap-2',\n 'text-sm font-medium whitespace-nowrap',\n 'ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n 'disabled:pointer-events-none disabled:opacity-50',\n 'active:scale-[0.97] motion-reduce:active:scale-100',\n 'rounded-xl',\n 'transition-transform duration-150 ease-[cubic-bezier(0.23,1,0.32,1)]',\n ),\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground',\n destructive: 'bg-destructive text-destructive-foreground',\n outline: 'bg-background border',\n secondary: 'bg-secondary text-secondary-foreground',\n ghost: 'hover:bg-secondary',\n link: 'text-primary underline-offset-4 hover:underline',\n },\n size: {\n default: 'h-10 px-4 py-2',\n sm: 'py-2 px-3.5 text-xs',\n /**\n * This size is useful for top level buttons that needs to sit nicely inside the iframe's border radius.\n * Having the minimum height higher than usual (the `default` variant) will make the border radius look just right.\n */\n lg: 'min-h-12 px-4 rounded-[20px]',\n icon: 'h-10 w-10',\n fit: 'size-fit p-2',\n free: 'p-2',\n selfless: 'p-0',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'default',\n },\n },\n);\n\nexport interface ButtonProps\n extends React.ButtonHTMLAttributes<HTMLButtonElement>,\n VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n /** Disable decorative pointer-follow movement for stable action targets. */\n wobble?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n variant = 'default',\n size,\n asChild = false,\n wobble = true,\n ...props\n },\n ref,\n ) => {\n const Comp = asChild ? Slot : 'button';\n return (\n <Wobble ref={ref} off={!wobble}>\n <Comp\n {...dc('ui_lib/btn')}\n data-variant={variant}\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n </Wobble>\n );\n },\n);\nButton.displayName = 'Button';\n\nexport { Button, buttonVariants };\n","import { AnimatePresence } from 'framer-motion';\nimport React, {\n cloneElement,\n createContext,\n useCallback,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport { MotionDiv } from './lib/MotionDiv';\nimport { cn } from './lib/utils/cn';\nimport { Button } from './lib/button';\nimport { X } from 'lucide-react';\nimport { useWidget } from '@opencx/widget-react-headless';\nimport { log } from '@opencx/widget-core';\nimport { useTranslation } from '../hooks/useTranslation';\n\ninterface DialogerProviderValue {\n open: (content: React.ReactNode) => void;\n close: () => void;\n isOpen: boolean;\n content: React.ReactNode | null;\n}\n\nconst context = createContext<DialogerProviderValue | null>(null);\n\nexport function DialogerProvider({ children }: { children: React.ReactNode }) {\n const [isOpen, setIsOpen] = useState(false);\n const [content, setContent] = useState<React.ReactNode | null>(null);\n\n const openDialog = (content: React.ReactNode) => {\n setContent(content);\n setIsOpen(true);\n };\n\n const closeDialog = useCallback(() => {\n setIsOpen(false);\n setTimeout(() => {\n setContent(null);\n }, 200);\n }, []);\n\n return (\n <context.Provider\n value={{ open: openDialog, close: closeDialog, isOpen, content }}\n >\n <DialogerPortal />\n {children}\n </context.Provider>\n );\n}\n\nexport function useDialoger(): DialogerProviderValue {\n const dialoger = useContext(context);\n\n if (!dialoger) {\n log.error('useDialoger must be used within a DialogerProvider');\n return {\n open: () => {},\n close: () => {},\n isOpen: false,\n content: null,\n };\n }\n\n return dialoger;\n}\n\nfunction DialogerPortal() {\n const { contentIframeRef } = useWidget();\n const { isOpen, content, close } = useDialoger();\n\n // Bound only while a dialog is actually up. A permanently-installed\n // listener swallowed EVERY Escape in the widget iframe — it called\n // preventDefault() before closing nothing — so the companion's own\n // `handleCompanionFrameKeyDown` (which stands down on `defaultPrevented`)\n // never saw the key and Escape stopped dismissing the panel.\n useEffect(() => {\n if (!isOpen) return;\n const handleEscape = (e: KeyboardEvent) => {\n if (e.defaultPrevented || e.key !== 'Escape') return;\n e.preventDefault();\n close();\n };\n\n const contentDocument = contentIframeRef?.current?.contentWindow?.document;\n contentDocument?.addEventListener('keydown', handleEscape);\n return () => contentDocument?.removeEventListener('keydown', handleEscape);\n }, [close, contentIframeRef, isOpen]);\n\n return (\n <AnimatePresence mode=\"wait\">\n {isOpen && content && (\n <MotionDiv\n overrides={{\n initial: { y: 0 },\n exit: { y: 0 },\n }}\n key=\"dialog-content\"\n className=\"fixed inset-0 z-50 bg-black/60 backdrop-blur-sm\"\n tabIndex={-1}\n onClick={close}\n >\n {content}\n </MotionDiv>\n )}\n </AnimatePresence>\n );\n}\n\nexport function DialogerContent({\n children,\n className,\n withClose = false,\n}: {\n children: React.ReactNode;\n className?: string;\n withClose?: boolean;\n}) {\n const { close } = useDialoger();\n const { t } = useTranslation();\n return (\n <div\n data-opencx-escape-scope\n className={cn(\n 'fixed left-[50%] top-[50%] z-50 flex flex-col gap-4 w-full max-w-[61.8%] translate-x-[-50%] translate-y-[-50%] border bg-background p-4 rounded-3xl',\n className,\n )}\n onClick={(e) => e.stopPropagation()}\n >\n {children}\n {withClose && (\n <Button\n size=\"fit\"\n className=\"rounded-full absolute top-4 right-4 opacity-50 hover:opacity-100\"\n onClick={close}\n >\n <X className=\"h-4 w-4\" />\n <span className=\"sr-only\">{t('dialog_close')}</span>\n </Button>\n )}\n </div>\n );\n}\n\nexport const DialogerHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn('flex flex-col gap-2 text-center pt-2', className)}\n {...props}\n />\n);\nDialogerHeader.displayName = 'DialogerHeader';\n\nexport const DialogerBody = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn('flex flex-col gap-2 text-center', className)}\n {...props}\n />\n);\nDialogerBody.displayName = 'DialogerBody';\n\nexport const DialogerFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div className={cn('flex flex-col gap-2', className)} {...props} />\n);\nDialogerFooter.displayName = 'DialogerFooter';\n\nexport const DialogerTitle = React.forwardRef<\n React.ElementRef<'p'>,\n React.ComponentPropsWithoutRef<'p'>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn(\n 'text-lg font-semibold leading-none tracking-tight',\n className,\n )}\n {...props}\n />\n));\nDialogerTitle.displayName = 'DialogerTitle';\n\nexport const DialogerDescription = React.forwardRef<\n React.ElementRef<'p'>,\n React.ComponentPropsWithoutRef<'p'>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn('text-sm text-muted-foreground', className)}\n {...props}\n />\n));\nDialogerDescription.displayName = 'DialogerDescription';\n\nexport function Dialoger({\n children,\n trigger,\n}: {\n children: React.ReactNode;\n trigger: React.ReactElement<{ onClick?: () => void }>;\n}) {\n const { open } = useDialoger();\n const clonedTrigger = cloneElement(trigger, {\n onClick: () => {\n open(children);\n trigger.props.onClick?.();\n },\n });\n\n return clonedTrigger;\n}\n","import React, { useCallback, useRef, useState } from 'react';\nimport { ZoomIn, ZoomOut, RotateCcw } from 'lucide-react';\nimport { cn } from './lib/utils/cn';\nimport { useTranslation } from '../hooks/useTranslation';\n\nconst MIN_SCALE = 1;\nconst MAX_SCALE = 5;\nconst ZOOM_STEP = 0.5;\nconst CLICK_ZOOM_SCALE = 2.5;\n\ntype Point = { x: number; y: number };\n\nfunction clampTranslate(\n translate: Point,\n scale: number,\n container: HTMLDivElement | null,\n image: HTMLImageElement | null,\n): Point {\n if (!container || !image || scale <= 1) return { x: 0, y: 0 };\n\n const containerRect = container.getBoundingClientRect();\n const imgW = image.offsetWidth;\n const imgH = image.offsetHeight;\n\n const maxX = Math.max(0, (imgW * scale - containerRect.width) / (2 * scale));\n const maxY = Math.max(0, (imgH * scale - containerRect.height) / (2 * scale));\n\n return {\n x: Math.min(maxX, Math.max(-maxX, translate.x)),\n y: Math.min(maxY, Math.max(-maxY, translate.y)),\n };\n}\n\nexport function ZoomableImage({ src, alt }: { src: string; alt?: string }) {\n const { t } = useTranslation();\n const [scale, setScale] = useState(1);\n const [translate, setTranslate] = useState<Point>({ x: 0, y: 0 });\n const [isDragging, setIsDragging] = useState(false);\n const dragStart = useRef<Point>({ x: 0, y: 0 });\n const translateStart = useRef<Point>({ x: 0, y: 0 });\n const containerRef = useRef<HTMLDivElement>(null);\n const imgRef = useRef<HTMLImageElement>(null);\n const pointerMovedRef = useRef(false);\n\n const clampScale = (s: number) => Math.min(MAX_SCALE, Math.max(MIN_SCALE, s));\n\n const reset = useCallback(() => {\n setScale(1);\n setTranslate({ x: 0, y: 0 });\n }, []);\n\n const zoomIn = useCallback(() => {\n setScale((s) => clampScale(s + ZOOM_STEP));\n }, []);\n\n const zoomOut = useCallback(() => {\n setScale((prev) => {\n const next = clampScale(prev - ZOOM_STEP);\n if (next <= 1) setTranslate({ x: 0, y: 0 });\n return next;\n });\n }, []);\n\n const handlePointerDown = useCallback(\n (e: React.PointerEvent) => {\n e.preventDefault();\n pointerMovedRef.current = false;\n setIsDragging(true);\n dragStart.current = { x: e.clientX, y: e.clientY };\n translateStart.current = { ...translate };\n (e.target as HTMLElement).setPointerCapture(e.pointerId);\n },\n [translate],\n );\n\n const handlePointerMove = useCallback(\n (e: React.PointerEvent) => {\n if (!isDragging) return;\n const dx = e.clientX - dragStart.current.x;\n const dy = e.clientY - dragStart.current.y;\n if (Math.abs(dx) > 3 || Math.abs(dy) > 3) {\n pointerMovedRef.current = true;\n }\n if (scale <= 1) return;\n const raw = {\n x: translateStart.current.x + dx / scale,\n y: translateStart.current.y + dy / scale,\n };\n setTranslate(\n clampTranslate(raw, scale, containerRef.current, imgRef.current),\n );\n },\n [isDragging, scale],\n );\n\n const handlePointerUp = useCallback(() => {\n const didDrag = pointerMovedRef.current;\n setIsDragging(false);\n if (didDrag) return;\n\n setScale((prev) => {\n if (prev > 1) {\n setTranslate({ x: 0, y: 0 });\n return 1;\n }\n return CLICK_ZOOM_SCALE;\n });\n }, []);\n\n const isZoomed = scale > 1;\n\n return (\n <div\n className=\"relative size-full flex items-center justify-center select-none\"\n onClick={(e) => e.stopPropagation()}\n >\n <div\n ref={containerRef}\n className={cn(\n 'overflow-hidden max-h-full max-w-full rounded-2xl flex items-center justify-center',\n isZoomed && 'size-full',\n )}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n style={{\n cursor: isDragging ? 'grabbing' : isZoomed ? 'grab' : 'zoom-in',\n touchAction: 'none',\n }}\n >\n <img\n ref={imgRef}\n src={src}\n alt={alt}\n className=\"block max-w-full object-contain pointer-events-none\"\n draggable={false}\n style={{\n maxHeight: '100vh',\n transform: `scale(${scale}) translate(${translate.x}px, ${translate.y}px)`,\n transformOrigin: 'center center',\n // transition: isDragging ? 'none' : 'all 0.2s ease-out',\n }}\n />\n </div>\n\n <div className=\"absolute bottom-3 left-1/2 -translate-x-1/2 flex items-center gap-1 bg-black/60 backdrop-blur-sm rounded-full px-1.5 py-1 transition opacity-50 hover:opacity-100\">\n <ControlButton\n onClick={zoomOut}\n label={t('zoom_out')}\n disabled={scale <= MIN_SCALE}\n >\n <ZoomOut className=\"size-3.5\" />\n </ControlButton>\n <span className=\"text-white text-xs font-medium min-w-[3ch] text-center tabular-nums\">\n {Math.round(scale * 100)}%\n </span>\n <ControlButton\n onClick={zoomIn}\n label={t('zoom_in')}\n disabled={scale >= MAX_SCALE}\n >\n <ZoomIn className=\"size-3.5\" />\n </ControlButton>\n {isZoomed && (\n <>\n <div className=\"w-px h-4 bg-white/30 mx-0.5\" />\n <ControlButton onClick={reset} label={t('reset_zoom')}>\n <RotateCcw className=\"size-3.5\" />\n </ControlButton>\n </>\n )}\n </div>\n </div>\n );\n}\n\nfunction ControlButton({\n onClick,\n label,\n children,\n disabled,\n}: {\n onClick: () => void;\n label: string;\n children: React.ReactNode;\n disabled?: boolean;\n}) {\n return (\n <button\n onClick={onClick}\n aria-label={label}\n disabled={disabled}\n className=\"text-white/80 hover:text-white disabled:text-white/30 disabled:hover:bg-transparent p-1.5 rounded-full hover:bg-white/15 transition-colors\"\n >\n {children}\n </button>\n );\n}\n","import type { MessageAttachmentType } from '@opencx/widget-core';\nimport { FileSpreadsheet, FileText } from 'lucide-react';\nimport React from 'react';\nimport { getSpreadsheet } from '../utils/attachment-kind';\nimport { cn } from './lib/utils/cn';\nimport { Wobble } from './lib/wobble';\nimport { Dialoger, DialogerContent } from './Dialoger';\nimport { ZoomableImage } from './ZoomableImage';\n\ntype Props = {\n attachment: MessageAttachmentType;\n};\n\n// Downloadable file chip (icon + name + \"size · label\"), used for PDFs and\n// spreadsheets that render as a card rather than inline.\nfunction FileCard({\n url,\n name,\n size,\n icon,\n label,\n}: {\n url: string;\n name: string;\n size: number;\n icon: React.ReactNode;\n label: string;\n}) {\n return (\n <Wobble>\n <a\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={cn(\n 'block size-fit max-w-[min(100%,16rem)] shrink-0 rounded-2xl border',\n 'bg-background/80 transition-colors hover:bg-accent/60',\n 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n )}\n >\n <div className=\"flex items-center gap-3 p-3 min-w-0\">\n <div\n className={cn(\n 'flex size-10 shrink-0 items-center justify-center rounded-xl',\n 'bg-secondary text-muted-foreground',\n )}\n aria-hidden\n >\n {icon}\n </div>\n <div className=\"min-w-0 flex-1 flex flex-col gap-0.5 text-left\">\n <span\n className={cn(\n 'text-xs font-medium text-foreground line-clamp-1',\n 'break-words [word-break:break-word]', // `[word-break:break-word]` is deprecated but works in the browser, while `break-words` which is `[overflow-wrap: break-word]` does not work\n )}\n >\n {name}\n </span>\n <span className=\"text-xs text-muted-foreground tabular-nums\">\n {(size / 1024).toFixed(2)} KB · {label}\n </span>\n </div>\n </div>\n </a>\n </Wobble>\n );\n}\n\nexport function AttachmentPreview({ attachment }: Props) {\n const { name, size, type, url } = attachment;\n\n const isImage = type.startsWith('image/');\n const isVideo = type.startsWith('video/');\n const isAudio = type.startsWith('audio/');\n const isPdf = type === 'application/pdf';\n\n if (isAudio) {\n return (\n <Wobble>\n <div className=\"w-full shrink-0 overflow-hidden\">\n <audio controls className=\"w-full\">\n <source src={url} type={type} />\n Your browser does not support the audio tag.\n </audio>\n </div>\n </Wobble>\n );\n }\n\n if (isVideo) {\n return (\n <Wobble>\n <div className=\"w-full border shrink-0 rounded-2xl overflow-hidden\">\n <video controls>\n <source src={url} type={type} />\n Your browser does not support the video tag.\n </video>\n </div>\n </Wobble>\n );\n }\n\n if (isImage) {\n return (\n <Dialoger\n trigger={\n <div>\n <Wobble>\n <div className=\"size-fit border shrink-0 rounded-2xl overflow-hidden\">\n <img src={url} className=\"object-cover size-16\" alt={name} />\n </div>\n </Wobble>\n </div>\n }\n >\n <DialogerContent\n className=\"size-full max-w-full rounded-3xl flex items-center justify-center bg-transparent border-none gap-0\"\n withClose\n >\n <ZoomableImage src={url} alt={name} />\n </DialogerContent>\n </Dialoger>\n );\n }\n\n if (isPdf) {\n return (\n <FileCard\n url={url}\n name={name}\n size={size}\n icon={<FileText className=\"size-5\" strokeWidth={1.75} />}\n label=\"PDF\"\n />\n );\n }\n\n const spreadsheet = getSpreadsheet({ type, name });\n if (spreadsheet) {\n return (\n <FileCard\n url={url}\n name={name}\n size={size}\n icon={<FileSpreadsheet className=\"size-5\" strokeWidth={1.75} />}\n label={spreadsheet.label}\n />\n );\n }\n\n return (\n <Wobble>\n <div className=\"size-fit border shrink-0 rounded-2xl overflow-hidden\">\n <div className=\"flex items-end gap-2 p-2\">\n <a\n href={url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={cn(\n 'text-xs text-blue-500 line-clamp-2 underline hover:text-blue-600',\n 'break-words [word-break:break-word]', // `[word-break:break-word]` is deprecated but works in the browser, while `break-words` which is `[overflow-wrap: break-word]` does not work\n )}\n >\n {name}\n </a>\n <span className=\"text-xs text-muted-foreground whitespace-nowrap\">\n {(size / 1024).toFixed(2)} KB\n </span>\n </div>\n </div>\n </Wobble>\n );\n}\n","import type { WidgetAgentMessage } from '@opencx/widget-core';\nimport React from 'react';\nimport { useBot, useConfig } from '@opencx/widget-react-headless';\nimport { dc } from '../utils/data-component';\nimport { cn } from './lib/utils/cn';\n\n/** An in-bubble quote that links to its original message. */\nexport function ReplyQuote({\n replyTo,\n}: {\n replyTo: NonNullable<WidgetAgentMessage['replyTo']>;\n}) {\n const bot = useBot();\n const { humanAgent } = useConfig();\n const { sender } = replyTo;\n const senderName =\n sender.kind === 'user'\n ? 'You'\n : sender.kind === 'ai'\n ? bot.name\n : sender.kind === 'agent'\n ? humanAgent?.name || sender.name || 'Team'\n : sender.name;\n\n return (\n <button\n {...dc('chat/agent_msg/reply_to')}\n type=\"button\"\n onClick={(event) => {\n const original = event.currentTarget.ownerDocument.querySelector(\n `[data-message-id=\"${CSS.escape(replyTo.id)}\"]`,\n );\n original?.scrollIntoView({ behavior: 'smooth', block: 'center' });\n // Already on screen means no scroll: flash it so the jump always lands\n // somewhere visible.\n original?.animate([{ opacity: 0.35 }, { opacity: 1 }], {\n duration: 900,\n easing: 'ease-out',\n });\n }}\n className={cn(\n 'not-prose mb-2 block w-full min-w-0 text-start',\n 'rounded-xl border-s-2 border-primary/50 bg-primary/[0.07] ps-2.5 pe-2 py-1.5',\n 'text-xs leading-snug text-muted-foreground',\n 'transition-colors hover:bg-primary/10 hover:text-foreground',\n )}\n >\n {senderName && (\n <span className=\"block font-medium text-foreground/80\">\n {senderName}\n </span>\n )}\n <span className=\"line-clamp-2 break-words\">{replyTo.text}</span>\n </button>\n );\n}\n","import React from 'react';\nimport ReactMarkdown from 'react-markdown';\n\nexport const MemoizedReactMarkdown = React.memo(\n ReactMarkdown,\n (prev, next) =>\n prev.children === next.children && prev.className === next.className,\n);\n","import { defaultSchema } from 'rehype-sanitize';\n\n// This schema is only used for host-configured content. Message HTML continues\n// to use the stricter RichText schema, which drops style attributes entirely.\nexport const configuredTextSchema: typeof defaultSchema = {\n ...defaultSchema,\n attributes: {\n ...defaultSchema.attributes,\n '*': [...(defaultSchema.attributes?.['*'] ?? []), 'style'],\n code: [...(defaultSchema.attributes?.code ?? []), 'className'],\n pre: [...(defaultSchema.attributes?.pre ?? []), 'className'],\n },\n};\n\nconst allowedProperty =\n /^(color|background-color|font-(family|size|style|weight)|text-(align|decoration|transform)|line-height|letter-spacing|white-space|display|width|height|max-width|min-width|margin(-top|-right|-bottom|-left)?|padding(-top|-right|-bottom|-left)?|border(-width|-style|-color|-radius)?)$/i;\nconst allowedValue = /^[\\w\\s#.,%()'\"+-]+$/;\nconst unsafeFunction = /\\b(url|expression|var|attr)\\s*\\(/i;\n\ntype HtmlNode = {\n type: string;\n properties?: Record<string, unknown>;\n children?: HtmlNode[];\n};\n\n/** Allow presentation styles without URL loads, CSS escapes or positioning. */\nexport function filterConfiguredStyles() {\n return function visit(node: HtmlNode): void {\n const style = node.properties?.style;\n if (typeof style === 'string' && node.properties) {\n node.properties.style = style\n .split(';')\n .filter((declaration) => {\n const colon = declaration.indexOf(':');\n if (colon < 0) return false;\n const property = declaration.slice(0, colon).trim();\n const value = declaration.slice(colon + 1).trim();\n return (\n allowedProperty.test(property) &&\n allowedValue.test(value) &&\n !unsafeFunction.test(value)\n );\n })\n .join(';');\n }\n node.children?.forEach(visit);\n };\n}\n","/**\n * Agent replies may carry invisible citation tags (`<ref id=\"knowledge:2\"/>`\n * and the resolved `<ref type=\"knowledge\" id=\"…\"/>` form). The backend strips\n * them from every PERSISTED row, but live stream deltas arrive raw — and\n * RichText renders with rehype-raw, which would otherwise inject the tag as a\n * real DOM element. Strip complete tags plus a trailing PARTIAL tag (a tag\n * still being streamed char-by-char), so nothing citation-shaped ever flashes.\n */\nexport function stripCitationRefs(text: string): string {\n return (\n text\n // The end-of-message citation REPORT block (which-part/why/useful) —\n // complete, then an unterminated one still streaming in.\n .replace(/<citations>[\\s\\S]*?<\\/citations>/g, '')\n .replace(/<citations[\\s\\S]*$/, '')\n // Complete tags — the model-facing ref form, the resolved typed form,\n // and stray <cite/> lines outside a block.\n .replace(/<(?:ref|cite)\\s[^>]*?\\/?>/g, '')\n // A tag cut mid-stream at the end of the buffer (\"<re\", \"<ref id=\\\"kno…,\n // \"<citation\"). A bare trailing \"<\" is left alone — it may be legitimate\n // text and only flashes for one frame while streaming.\n .replace(/<r(?:e(?:f[^>]*)?)?$/, '')\n .replace(\n /<c(?:i(?:t(?:a(?:t(?:i(?:o(?:n(?:s)?)?)?)?)?)?(?:e[^>]*)?)?)?$/,\n '',\n )\n .trimEnd()\n );\n}\n","import React from 'react';\nimport remarkGfm from 'remark-gfm';\nimport { MemoizedReactMarkdown } from './MemoizedReactMarkdown';\nimport rehypeRaw from 'rehype-raw';\nimport rehypeSanitize, { defaultSchema } from 'rehype-sanitize';\nimport { useConfig } from '@opencx/widget-react-headless';\nimport { Dialoger, DialogerContent } from './Dialoger';\nimport { ZoomableImage } from './ZoomableImage';\nimport {\n configuredTextSchema,\n filterConfiguredStyles,\n} from './configured-text-styles';\nimport { stripCitationRefs } from '../utils/strip-citation-refs';\n\n/**\n * Everything rendered here is UNTRUSTED: AI replies, agent messages and\n * knowledge-base content all reach `RichText`, and the widget's React runs in\n * the embedder's realm — so raw HTML here executes on the customer's own site.\n *\n * `rehypeRaw` exists so authored HTML in a reply still renders, which means a\n * sanitizer is not optional. It MUST run after `rehypeRaw`: raw parses the HTML\n * string into real nodes, and only then is there a tree to strip. Reversing the\n * order silently sanitizes nothing.\n *\n * The base is `rehype-sanitize`'s GitHub schema (safe markdown-shaped HTML,\n * no `script`, no `on*` handlers, no `javascript:` URLs). The one addition is\n * `className` on `code`/`pre`, which `remark-gfm` emits for fenced code blocks\n * and the default schema would otherwise drop, breaking code formatting.\n */\nconst richTextSanitizeSchema = {\n ...defaultSchema,\n attributes: {\n ...defaultSchema.attributes,\n code: [...(defaultSchema.attributes?.code ?? []), 'className'],\n pre: [...(defaultSchema.attributes?.pre ?? []), 'className'],\n },\n};\n\ntype RichTextProps = {\n children: string;\n messageType?: string;\n messageId?: string;\n};\n\nexport function RichText(props: RichTextProps) {\n return <RichTextContent {...props} />;\n}\n\n/** Host-authored footer HTML can keep safe typography and spacing. */\nexport function ConfiguredRichText(props: RichTextProps) {\n return <RichTextContent {...props} configuredStyles />;\n}\n\nfunction RichTextContent({\n children,\n messageType,\n messageId,\n configuredStyles = false,\n}: RichTextProps & { configuredStyles?: boolean }) {\n const { anchorTarget } = useConfig();\n\n return (\n <MemoizedReactMarkdown\n data-type={messageType}\n data-id={messageId}\n remarkPlugins={[remarkGfm]}\n rehypePlugins={\n configuredStyles\n ? [\n rehypeRaw,\n filterConfiguredStyles,\n [rehypeSanitize, configuredTextSchema],\n ]\n : [rehypeRaw, [rehypeSanitize, richTextSanitizeSchema]]\n }\n components={{\n a: ({ children, ...props }) => {\n return (\n <a target={props.target || anchorTarget || '_top'} {...props}>\n {children}\n </a>\n );\n },\n img: ({ src, alt, ...props }) => {\n if (!src) return <img src={src} alt={alt} {...props} />;\n return (\n <Dialoger\n trigger={\n <img\n src={src}\n alt={alt}\n {...props}\n className=\"cursor-pointer rounded-xl\"\n />\n }\n >\n <DialogerContent\n className=\"size-full max-w-full rounded-3xl flex items-center justify-center bg-transparent border-none gap-0\"\n withClose\n >\n <ZoomableImage src={src} alt={alt} />\n </DialogerContent>\n </Dialoger>\n );\n },\n }}\n // Do not pass className directly to ReactMarkdown component because that will create a container div wrapping the rich text\n >\n {stripCitationRefs(children)}\n </MemoizedReactMarkdown>\n );\n}\n","import type { ComponentContext } from '@opencx/widget-core';\nimport {\n useSessions,\n useConfig,\n useWidget,\n useMessages,\n useWidgetRouter,\n} from '@opencx/widget-react-headless';\nimport React from 'react';\n\nexport function useComponentContext(): ComponentContext {\n const {\n widgetCtx: { org },\n } = useWidget();\n const {\n sessionState: { session },\n } = useSessions();\n const config = useConfig();\n const {\n messagesState: { messages },\n } = useMessages();\n const {\n routerState: { screen },\n } = useWidgetRouter();\n\n return {\n react: React,\n org,\n session,\n config,\n messages,\n currentScreen: screen,\n };\n}\n","import React from 'react';\nimport { useComponentContext } from '../../hooks/useComponentContext';\nimport type { WidgetMessageU } from '@opencx/widget-core';\n\nexport function MessageAfterComponent({\n currentMessage,\n}: {\n currentMessage: WidgetMessageU;\n}) {\n const props = useComponentContext();\n\n const Component = props.config.customComponents?.['message::after'];\n if (!Component) return null;\n\n return <Component {...props} currentMessage={currentMessage} />;\n}\n","import type { WidgetMessageOptions } from '@opencx/widget-core';\nimport { useMessages, useSessions } from '@opencx/widget-react-headless';\nimport { CheckIcon } from 'lucide-react';\nimport React from 'react';\nimport { dc } from '../utils/data-component.js';\nimport { Button } from './lib/button.js';\n\n/**\n * Only the first tap on the newest options message of an open session counts,\n * so only it shows the options. After a tap only the picked one stays, as a\n * receipt; options that can no longer be tapped are not shown.\n */\nexport function MessageOptions({\n messageId,\n messageOptions,\n}: {\n messageId: string;\n messageOptions: WidgetMessageOptions;\n}) {\n const { messagesState, sendMessage } = useMessages();\n const { sessionState } = useSessions();\n\n const newestWithOptions = messagesState.messages.findLast(\n (message) => message.type === 'AGENT' && message.messageOptions,\n );\n const { pickedOptionId } = messageOptions;\n const tappable =\n pickedOptionId === null &&\n newestWithOptions?.id === messageId &&\n sessionState.session?.isOpened !== false;\n const picked = messageOptions.options.find(\n (option) => option.id === pickedOptionId,\n );\n\n if (picked) {\n return (\n <div {...dc('chat/agent_msg/options')} className=\"flex\">\n <Button\n {...dc('chat/agent_msg/option_btn')}\n data-picked\n aria-pressed\n size=\"sm\"\n variant=\"outline\"\n className=\"w-fit pl-2 text-sm text-muted-foreground disabled:opacity-100\"\n disabled\n >\n <CheckIcon aria-hidden=\"true\" className=\"size-3.5 shrink-0\" />\n {picked.label}\n </Button>\n </div>\n );\n }\n\n if (!tappable) return null;\n\n return (\n <div\n {...dc('chat/agent_msg/options')}\n role=\"group\"\n // Rows sit far enough apart on touch screens that the 48px tap areas never overlap.\n className=\"flex flex-row flex-wrap gap-1.5 [@media(pointer:coarse)]:gap-y-3\"\n >\n {messageOptions.options.map((option) => (\n <Button\n key={option.id}\n {...dc('chat/agent_msg/option_btn')}\n size=\"sm\"\n variant=\"outline\"\n className=\"relative w-fit text-sm hover:bg-secondary\"\n onClick={() =>\n sendMessage({\n content: option.label,\n optionReply: { messageId, optionId: option.id },\n })\n }\n >\n {/* 48×48 tap area on touch screens, without changing the layout. */}\n <span\n aria-hidden=\"true\"\n className=\"absolute top-1/2 left-1/2 size-[max(100%,3rem)] -translate-x-1/2 -translate-y-1/2 [@media(pointer:fine)]:hidden\"\n />\n {option.label}\n </Button>\n ))}\n </div>\n );\n}\n","import type { OpenCxComponentNameU } from '@opencx/widget-core';\nimport type { WidgetComponentProps } from '@opencx/widget-react-headless';\nimport React, { useMemo } from 'react';\nimport { SpecRenderer } from '../../json-render/index.js';\nimport { segmentContent } from '../../json-render/segment-content.js';\nimport { dc } from '../../utils/data-component.js';\nimport { AttachmentPreview } from '../AttachmentPreview.js';\nimport { cn } from '../lib/utils/cn.js';\nimport { ReplyQuote } from '../ReplyQuote.js';\nimport { RichText } from '../RichText.js';\nimport { MessageAfterComponent } from './MessageAfterComponent.js';\nimport { MessageOptions } from '../MessageOptions.js';\n\n/**\n * `prose` ships its own gray palette; repoint every color it paints (body,\n * links, inline code, bullets, rules, code blocks) at the widget's theme\n * tokens so a dark scheme — or an embedder's palette — carries into replies.\n */\nconst MESSAGE_PROSE_TOKENS = [\n '[--tw-prose-body:hsl(var(--opencx-secondary-foreground))]',\n '[--tw-prose-headings:hsl(var(--opencx-secondary-foreground))]',\n '[--tw-prose-lead:hsl(var(--opencx-secondary-foreground))]',\n '[--tw-prose-bold:hsl(var(--opencx-secondary-foreground))]',\n '[--tw-prose-links:hsl(var(--opencx-secondary-foreground))]',\n '[--tw-prose-code:hsl(var(--opencx-secondary-foreground))]',\n '[--tw-prose-counters:hsl(var(--opencx-muted-foreground))]',\n '[--tw-prose-bullets:hsl(var(--opencx-muted-foreground))]',\n '[--tw-prose-quotes:hsl(var(--opencx-muted-foreground))]',\n '[--tw-prose-quote-borders:hsl(var(--opencx-border))]',\n '[--tw-prose-hr:hsl(var(--opencx-border))]',\n '[--tw-prose-th-borders:hsl(var(--opencx-border))]',\n '[--tw-prose-td-borders:hsl(var(--opencx-border))]',\n '[--tw-prose-pre-bg:hsl(var(--opencx-muted))]',\n '[--tw-prose-pre-code:hsl(var(--opencx-foreground))]',\n].join(' ');\n\nexport function AgentMessageDefaultComponent(\n props: WidgetComponentProps & {\n isFirstInGroup: boolean;\n isLastInGroup: boolean;\n isAloneInGroup: boolean;\n dataComponentNames?: {\n messageContainer?: OpenCxComponentNameU;\n message?: OpenCxComponentNameU;\n };\n classNames?: {\n messageContainer?: string;\n message?: string;\n };\n },\n) {\n const {\n data,\n id,\n type,\n attachments,\n isFirstInGroup,\n isLastInGroup,\n isAloneInGroup,\n dataComponentNames,\n classNames,\n } = props;\n\n const message = type === 'AI' || type === 'AGENT' ? data.message : '';\n\n // Persisted AI rows keep the raw ` ```spec ` fence (the live stream transforms\n // it to `data-spec` parts on the SSE only — persist raw, transform on serve).\n // Segment the stored text so the fenced JSONL renders as UI here too, giving\n // streamed and reloaded transcripts the same look. AGENT (human) messages\n // never carry specs and skip the parse entirely.\n const segments = useMemo(\n () => (type === 'AI' ? segmentContent(message) : null),\n [type, message],\n );\n\n if (type !== 'AI' && type !== 'AGENT') return null;\n\n const { variant = 'default' } = data;\n\n // The quoted message lives INSIDE the bubble, like every chat app: the\n // bubble grows around it, so quote and reply read as one unit instead of a\n // stray full-width paragraph above a short bubble. Both a teammate's reply\n // and the AI's own follow-up (after it asked the team) carry one.\n const quote = props.replyTo ? <ReplyQuote replyTo={props.replyTo} /> : null;\n\n const bubble = (\n text: string,\n key?: string,\n withAfter = true,\n withQuote = true,\n ) => (\n <div key={key} className=\"flex flex-row gap-2\">\n <div\n {...dc(dataComponentNames?.message ?? 'chat/agent_msg/msg')}\n // Expose these data attributes for external styling customization\n data-first={isFirstInGroup}\n data-last={isLastInGroup}\n data-alone={isAloneInGroup}\n data-variant={variant}\n className={cn(\n 'transition-all',\n 'w-fit py-3 px-4 rounded-3xl bg-secondary text-secondary-foreground',\n 'leading-snug text-sm prose prose-sm prose-a:decoration-primary prose-a:underline',\n MESSAGE_PROSE_TOKENS,\n 'break-words [word-break:break-word]', // `[word-break:break-word]` is deprecated but works in the browser, while `break-words` which is `[overflow-wrap: break-word]` does not work\n // No need to add \"whitespace-pre-wrap\" in the agent or bot message because it is markup and content appear on separate lines as expected\n // Adding \"whitespace-pre-wrap\" will result in unnecessarily huge line breaks\n\n variant === 'error' && 'bg-destructive/15 text-destructive',\n\n // We're using the booleans directly here, not the data attributes, to make any external styling more specific than this\n isFirstInGroup && !isAloneInGroup && 'rounded-bl-md',\n isLastInGroup && !isAloneInGroup && 'rounded-tl-md',\n !isFirstInGroup &&\n !isLastInGroup &&\n !isAloneInGroup &&\n 'rounded-l-md',\n classNames?.message,\n )}\n >\n {withQuote && quote}\n <RichText messageType={type} messageId={id}>\n {text}\n </RichText>\n </div>\n {withAfter && <MessageAfterComponent currentMessage={props} />}\n </div>\n );\n\n // Specs render OUTSIDE the bubble, full width — identical placement to the\n // live streamed turn.\n const hasUiSegments = segments?.some((s) => s.type === 'ui') ?? false;\n const lastMarkdownIndex =\n segments?.reduce((last, s, i) => (s.type === 'markdown' ? i : last), -1) ??\n -1;\n // The quote answers the whole reply, so it belongs to the first prose bubble\n // only — not repeated above every segment of a multi-part turn.\n const firstMarkdownIndex =\n segments?.findIndex((s) => s.type === 'markdown') ?? -1;\n\n return (\n <div\n {...dc(dataComponentNames?.messageContainer ?? 'chat/agent_msg/root')}\n data-message-id={id}\n className={cn(\n 'w-5/6 flex flex-col items-start gap-1',\n classNames?.messageContainer,\n )}\n >\n {attachments && attachments.length > 0 && (\n <div className=\"w-full gap-1 flex flex-row flex-wrap items-center justify-start\">\n {attachments?.map((attachment) => (\n <AttachmentPreview attachment={attachment} key={attachment.id} />\n ))}\n </div>\n )}\n {hasUiSegments && segments\n ? segments.map((segment, i) => {\n if (segment.type === 'markdown') {\n // `message::after` (copy button etc.) attaches once, to the\n // final prose bubble — not to every segment.\n return bubble(\n segment.content,\n `md-${i}`,\n i === lastMarkdownIndex,\n i === firstMarkdownIndex,\n );\n }\n return (\n <div key={`ui-${i}`} className=\"w-full\">\n <SpecRenderer spec={segment.spec} />\n </div>\n );\n })\n : message.length > 0 && bubble(message)}\n {type === 'AGENT' && props.messageOptions && (\n <MessageOptions messageId={id} messageOptions={props.messageOptions} />\n )}\n </div>\n );\n}\n","import type { WidgetComponentProps } from '@opencx/widget-react-headless';\nimport React from 'react';\n\n/**\n * The Basic Fallback component (Rendered when Debug is True and the component key is not found)\n */\nexport function FallbackDefaultComponent(props: WidgetComponentProps) {\n return (\n <div className=\"w-full max-w-full overflow-auto shrink-0\">\n <pre className=\"text-xs leading-tight whitespace-pre-wrap break-word\">\n {JSON.stringify(props, null, 1)}\n </pre>\n </div>\n );\n}\n","import * as React from 'react';\nimport * as AvatarPrimitive from '@radix-ui/react-avatar';\nimport { cn } from './utils/cn';\n\nconst Avatar = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Root\n ref={ref}\n className={cn(\n 'relative flex size-6 aspect-square shrink-0 overflow-hidden rounded-full bg-secondary',\n // 'border',\n className,\n )}\n {...props}\n />\n));\nAvatar.displayName = AvatarPrimitive.Root.displayName;\n\nconst AvatarImage = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Image>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Image\n ref={ref}\n className={cn('aspect-square h-full w-full', className)}\n {...props}\n />\n));\nAvatarImage.displayName = AvatarPrimitive.Image.displayName;\n\nconst AvatarFallback = React.forwardRef<\n React.ElementRef<typeof AvatarPrimitive.Fallback>,\n React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>\n>(({ className, ...props }, ref) => (\n <AvatarPrimitive.Fallback\n ref={ref}\n className={cn(\n 'flex size-full text-xs items-center justify-center rounded-lg',\n className,\n )}\n {...props}\n />\n));\nAvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;\n\nexport { Avatar, AvatarImage, AvatarFallback };\n","import type { Agent } from '@opencx/widget-core';\nimport React from 'react';\nimport { Avatar, AvatarFallback, AvatarImage } from './lib/avatar';\nimport type { AvatarProps } from '@radix-ui/react-avatar';\n\nexport function AgentAvatar({\n agent,\n ...props\n}: AvatarProps & {\n agent: Agent | undefined;\n}) {\n return (\n <Avatar {...props}>\n <AvatarImage\n src={agent?.avatarUrl || agent?.avatar || ''}\n alt=\"Agent Icon\"\n />\n {agent?.name && (\n <AvatarFallback>\n {agent?.name?.slice(0, 1)?.toUpperCase()}\n </AvatarFallback>\n )}\n </Avatar>\n );\n}\n","import { type Agent } from '@opencx/widget-core';\nimport { AnimatePresence, motion } from 'framer-motion';\nimport React from 'react';\nimport { dc } from '../../utils/data-component';\nimport { AgentAvatar } from '../AgentAvatar';\nimport { MotionDiv } from '../lib/MotionDiv';\nimport { cn } from '../lib/utils/cn';\n\nexport type LoadingComponentProps = {\n agent: Agent | undefined;\n};\n\nexport function LoadingDefaultComponent({ agent }: LoadingComponentProps) {\n return (\n <AnimatePresence>\n <MotionDiv\n {...dc('chat/bot_loading/root')}\n className=\"flex flex-row items-end w-full gap-2 animate-pulse\"\n >\n <AgentAvatar agent={agent} />\n <div\n {...dc('chat/bot_loading/bouncing_dots_container')}\n className={cn(\n 'flex items-center [&_span]:bg-secondary-foreground [&_span]:size-1 gap-1 p-2 rounded-xl bg-secondary',\n // 'border',\n )}\n >\n <motion.span className=\"rounded-full animate-bounce [animation-delay:-0.3s]\" />\n <motion.span className=\"rounded-full animate-bounce [animation-delay:-0.15s]\" />\n <motion.span className=\"rounded-full animate-bounce\" />\n </div>\n </MotionDiv>\n </AnimatePresence>\n );\n}\n","import type { WidgetConfig } from '@opencx/widget-core';\n\ntype TriggerOffsetConfig = NonNullable<\n NonNullable<NonNullable<WidgetConfig['theme']>['widgetTrigger']>['offset']\n>;\n\nexport type TriggerSide = 'left' | 'right';\n\n/**\n * Resolves which horizontal side the whole widget (trigger button, popover\n * anchor, and content alignment) lives on.\n *\n * An explicit numeric offset in the user config wins over the host document\n * direction, so `offset: { right: 20 }` pins the widget to the right even on\n * an RTL page. When both or neither side is numeric, the host document\n * direction decides (LTR → right, RTL → left).\n */\nexport function resolveTriggerSide(\n offset: TriggerOffsetConfig | undefined,\n dir: string,\n): TriggerSide {\n const rightIsNumber = typeof offset?.right === 'number';\n const leftIsNumber = typeof offset?.left === 'number';\n if (rightIsNumber && !leftIsNumber) return 'right';\n if (leftIsNumber && !rightIsNumber) return 'left';\n return dir === 'rtl' ? 'left' : 'right';\n}\n","import React from 'react';\n\nconst THRESHOLD_PIXELS = 450;\n\nexport function useIsSmallScreen() {\n const [isSmallScreen, setIsSmallScreen] = React.useState(() => {\n return (window.top || window).innerWidth < THRESHOLD_PIXELS;\n });\n\n React.useEffect(() => {\n const topWindow = window.top || window;\n\n const checkScreenSize = () => {\n setIsSmallScreen(topWindow.innerWidth < THRESHOLD_PIXELS);\n };\n\n checkScreenSize();\n\n topWindow.addEventListener('resize', checkScreenSize);\n\n return () => {\n topWindow.removeEventListener('resize', checkScreenSize);\n };\n }, []);\n\n return { isSmallScreen };\n}\n","import tc from 'tinycolor2';\nimport { isExhaustive, type WidgetConfig } from '@opencx/widget-core';\nimport { useConfig, useDocumentDir } from '@opencx/widget-react-headless';\nimport { WOBBLE_MAX_MOVEMENT_PIXELS } from '../components/lib/wobble';\nimport { resolveTriggerSide } from '../utils/resolve-trigger-side';\nimport { useIsSmallScreen } from './useIsSmallScreen';\n\ntype DeepRequired<T> = {\n [K in keyof T]-?: DeepRequired<T[K]>;\n};\n\nconst DEFAULTS = {\n transitionTimingFunction: 'cubic-bezier(0.16, 1, 0.3, 1)',\n transitionDuration: '1000ms',\n};\n\ntype WidgetCssVariables = {\n [name: `--opencx-${string}`]: string;\n};\n\n/**\n * @returns The widget config theme with fallback default value\n */\nexport function useTheme() {\n const { dir } = useDocumentDir();\n const { isSmallScreen } = useIsSmallScreen();\n const { theme, inline } = useConfig();\n\n const withInlineDefault = (v: string) => {\n return inline ? '100%' : v;\n };\n\n const withSmallScreenDefault = (target: 'w' | 'h', v: string) => {\n return isSmallScreen ? `100dv${target}` : v;\n };\n\n const withDefaults = (target: 'w' | 'h', v: string) => {\n return withInlineDefault(withSmallScreenDefault(target, v));\n };\n\n const triggerSide = resolveTriggerSide(theme?.widgetTrigger?.offset, dir);\n\n const widgetTrigger = {\n zIndex: theme?.widgetTrigger?.zIndex ?? 10_000_000,\n offset: {\n bottom: theme?.widgetTrigger?.offset?.bottom ?? 20,\n right:\n theme?.widgetTrigger?.offset?.right ??\n (triggerSide === 'right' ? 20 : 'initial'),\n left:\n theme?.widgetTrigger?.offset?.left ??\n (triggerSide === 'left' ? 20 : 'initial'),\n },\n size: {\n button: theme?.widgetTrigger?.size?.button ?? 48,\n icon: theme?.widgetTrigger?.size?.icon ?? 24,\n },\n } satisfies NonNullable<DeepRequired<WidgetConfig['theme']>>['widgetTrigger'];\n\n const triggerOffset = (() => {\n const v =\n triggerSide === 'right'\n ? widgetTrigger.offset.right\n : widgetTrigger.offset.left;\n if (typeof v !== 'number') return 0;\n return v;\n })();\n\n const themeWithFallbacks = {\n palette: theme?.palette ?? 'neutral',\n primaryColor: theme?.primaryColor ?? 'hsl(0 0% 9%)',\n widgetTrigger,\n widgetContentContainer: {\n borderRadius: isSmallScreen\n ? '0px'\n : (theme?.widgetContentContainer?.borderRadius ?? '32px'),\n zIndex: theme?.widgetContentContainer?.zIndex ?? widgetTrigger.zIndex + 1,\n outline: theme?.widgetContentContainer?.outline ?? 'none', // was: '1px solid'\n outlineColor:\n theme?.widgetContentContainer?.outlineColor ?? 'hsl(0 0% 50% / .5)',\n boxShadow:\n theme?.widgetContentContainer?.boxShadow ??\n '0 0px 100px 0px rgb(0 0 0 / 0.25)',\n transitionProperty:\n theme?.widgetContentContainer?.transitionProperty ?? 'all',\n transitionTimingFunction:\n theme?.widgetContentContainer?.transitionTimingFunction ??\n DEFAULTS.transitionTimingFunction,\n transitionDuration:\n theme?.widgetContentContainer?.transitionDuration ??\n DEFAULTS.transitionDuration,\n offset: {\n side: isSmallScreen\n ? 0\n : widgetTrigger.offset.bottom +\n widgetTrigger.size.button +\n WOBBLE_MAX_MOVEMENT_PIXELS.y * 2 +\n (theme?.widgetContentContainer?.offset?.side ?? 10),\n align: isSmallScreen\n ? 0\n : triggerOffset + (theme?.widgetContentContainer?.offset?.align ?? 0),\n },\n },\n screens: {\n welcome: {\n width: withDefaults('w', theme?.screens?.welcome?.width ?? '400px'),\n // By setting minHeight to 1px, a nice animation will play from 1px to the dynamic height of the content of the screen\n minHeight: withDefaults(\n 'h',\n theme?.screens?.welcome?.minHeight ?? '1px',\n ),\n },\n sessions: {\n width: withDefaults('w', theme?.screens?.sessions?.width ?? '450px'),\n height: withDefaults('h', theme?.screens?.sessions?.height ?? '600px'),\n },\n chat: {\n width: withDefaults('w', theme?.screens?.chat?.width ?? '525px'),\n height: withDefaults('h', theme?.screens?.chat?.height ?? '700px'),\n withCanvas: {\n width: withDefaults(\n 'w',\n theme?.screens?.chat?.withCanvas?.width ?? 'min(1050px, 100vw)',\n ),\n height: withDefaults(\n 'h',\n theme?.screens?.chat?.withCanvas?.height ?? 'min(800px, 100vh)',\n ),\n transitionTimingFunction:\n theme?.screens?.chat?.withCanvas?.transitionTimingFunction ??\n DEFAULTS.transitionTimingFunction,\n transitionDuration:\n theme?.screens?.chat?.withCanvas?.transitionDuration ??\n DEFAULTS.transitionDuration,\n },\n },\n },\n } satisfies NonNullable<DeepRequired<WidgetConfig['theme']>>;\n\n const computed = {\n // Subtract the offset.bottom twice so that it adds a bit of padding to the top\n // Subtract the distance between the trigger and the widget content container\n // Subtract the invisible padding of the trigger (for the wobble effect)\n maxHeight: withDefaults(\n 'h',\n `calc(\n 100vh \n - ${themeWithFallbacks.widgetTrigger.offset.bottom}px\n - ${themeWithFallbacks.widgetContentContainer.offset.side}px\n - ${WOBBLE_MAX_MOVEMENT_PIXELS.y * 2}px\n )`,\n ),\n // Subtract the offset.right twice so that it adds a bit of padding to the left\n maxWidth: withDefaults(\n 'w',\n `calc(\n 100vw \n - ${triggerOffset * 2}px\n )`,\n ),\n\n minHeight: withDefaults(\n 'h',\n `min(\n ${themeWithFallbacks.screens.welcome.minHeight}, \n ${themeWithFallbacks.screens.sessions.height}, \n ${themeWithFallbacks.screens.chat.height}\n )`,\n ),\n minWidth: withDefaults(\n 'w',\n `min(\n ${themeWithFallbacks.screens.welcome.width}, \n ${themeWithFallbacks.screens.sessions.width}, \n ${themeWithFallbacks.screens.chat.width}\n )`,\n ),\n };\n\n return {\n theme: themeWithFallbacks,\n triggerSide,\n computed,\n cssVars: cssVars({\n palette: themeWithFallbacks.palette,\n primary: themeWithFallbacks.primaryColor,\n }),\n };\n}\n\nfunction cssVars({\n palette: paletteName,\n primary,\n}: {\n palette: NonNullable<NonNullable<WidgetConfig['theme']>['palette']>;\n primary: string;\n}) {\n const palette = getPaletteColors(paletteName);\n const _primary = tc(primary).toHsl();\n const primaryForeground = tc(primary).isLight()\n ? palette['950']\n : palette['50'];\n\n /**\n * Spread the primary color without the `hsl()` call so that we can use tailwind opacity classes on it\n */\n const primitivePrimary = `${_primary.h} ${_primary.s * 100}% ${_primary.l * 100}%`;\n\n return {\n '--opencx-primary': primitivePrimary,\n '--opencx-primary-foreground': primaryForeground,\n\n '--opencx-background': palette['100'],\n '--opencx-foreground': palette['950'],\n\n '--opencx-destructive': '0 72.2% 50.6%',\n '--opencx-destructive-foreground': palette['50'],\n\n '--opencx-accent': palette['200'],\n '--opencx-accent-foreground': 'var(--opencx-foreground)',\n\n '--opencx-secondary': palette['200'],\n '--opencx-secondary-foreground': 'var(--opencx-foreground)',\n\n '--opencx-muted': palette['200'],\n '--opencx-muted-foreground': palette['500'],\n\n '--opencx-input': palette['300'],\n '--opencx-border': palette['300'],\n '--opencx-ring': 'var(--opencx-foreground)',\n } satisfies WidgetCssVariables;\n}\n\ntype PaletteValues = {\n '50': string;\n '100': string;\n '200': string;\n '300': string;\n '400': string;\n '500': string;\n '600': string;\n '700': string;\n '800': string;\n '900': string;\n '950': string;\n};\n/**\n * @returns A palette object with HSL values\n */\nfunction getPaletteColors(\n palette: NonNullable<NonNullable<WidgetConfig['theme']>['palette']>,\n): PaletteValues {\n const neutral: PaletteValues = {\n '50': '0 0% 98%',\n '100': '0 0% 96.1%',\n '200': '0 0% 89.8%',\n '300': '0 0% 83.1%',\n '400': '0 0% 63.9%',\n '500': '0 0% 45.1%',\n '600': '0 0% 32.2%',\n '700': '0 0% 25.1%',\n '800': '0 0% 14.9%',\n '900': '0 0% 9%',\n '950': '0 0% 3.9%',\n };\n\n const stone: PaletteValues = {\n '50': '60 9.1% 97.8%',\n '100': '60 4.8% 95.9%',\n '200': '20 5.9% 90%',\n '300': '24 5.7% 82.9%',\n '400': '24 5.4% 63.9%',\n '500': '25 5.3% 44.7%',\n '600': '33.3 5.5% 32.4%',\n '700': '30 6.3% 25.1%',\n '800': '12 6.5% 15.1%',\n '900': '24 9.8% 10%',\n '950': '20 14.3% 4.1%',\n };\n\n const zinc: PaletteValues = {\n '50': '0 0% 98%',\n '100': '240 4.8% 95.9%',\n '200': '240 5.9% 90%',\n '300': '240 4.9% 83.9%',\n '400': '240 5% 64.9%',\n '500': '240 3.8% 46.1%',\n '600': '240 5.2% 33.9%',\n '700': '240 5.3% 26.1%',\n '800': '240 3.7% 15.9%',\n '900': '240 5.9% 10%',\n '950': '240 10% 3.9%',\n };\n\n const slate: PaletteValues = {\n '50': '210 40% 98%',\n '100': '210 40% 96.1%',\n '200': '214.3 31.8% 91.4%',\n '300': '212.7 26.8% 83.9%',\n '400': '215 20.2% 65.1%',\n '500': '215.4 16.3% 46.9%',\n '600': '215.3 19.3% 34.5%',\n '700': '215.3 25% 26.7%',\n '800': '217.2 32.6% 17.5%',\n '900': '222.2 47.4% 11.2%',\n '950': '222.2 84% 4.9%',\n };\n\n switch (palette) {\n case 'neutral':\n return neutral;\n case 'stone':\n return stone;\n case 'zinc':\n return zinc;\n case 'slate':\n return slate;\n default:\n isExhaustive(palette, getPaletteColors.name);\n return neutral;\n }\n}\n","import * as TooltipPrimitive from '@radix-ui/react-tooltip';\nimport * as React from 'react';\nimport { cn } from './utils/cn.js';\nimport { useConfig } from '@opencx/widget-react-headless';\n\nconst TooltipProvider = TooltipPrimitive.Provider;\n\nconst Tooltip = TooltipPrimitive.Root;\n\nconst TooltipTrigger = TooltipPrimitive.Trigger;\n\nconst TooltipContent = React.forwardRef<\n React.ElementRef<typeof TooltipPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <TooltipPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n 'z-50 overflow-hidden max-w-xs rounded-xl bg-primary border text-primary-foreground p-2 text-center align-middle text-xs origin-[var(--radix-tooltip-content-transform-origin)] animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className,\n )}\n {...props}\n />\n));\n\nTooltipContent.displayName = TooltipPrimitive.Content.displayName;\n\nconst TooltipsSuppressed = React.createContext(false);\n\n/**\n * Silences every tooltip rendered inside. Companion's quick-ask bar wraps the\n * composer in it: the shell clips that composer to a thin strip, so a\n * `side=\"top\"` tooltip bleeds above the bar as a dark sliver. Stated once for\n * the whole subtree, so no control inside has to be told individually.\n */\nfunction SuppressTooltips({ children }: { children: React.ReactNode }) {\n return (\n <TooltipsSuppressed.Provider value>{children}</TooltipsSuppressed.Provider>\n );\n}\n\nfunction Tooltippy({\n children,\n content,\n side,\n align,\n shortcut,\n}: {\n children: React.ReactNode;\n content: React.ReactNode;\n side?: TooltipPrimitive.TooltipContentProps['side'];\n align?: TooltipPrimitive.TooltipContentProps['align'];\n /**\n * Display form of the action's keyboard shortcut (e.g. \"⌘⇧F\", \"Esc\"),\n * rendered as a fainter chip after the label. Always produce it with\n * `formatBinding(WIDGET_KEYBINDINGS[action])` so the hint can never drift\n * from the binding the handler actually matches.\n */\n shortcut?: string;\n}) {\n const { disableTooltips } = useConfig();\n const suppressed = React.useContext(TooltipsSuppressed);\n if (!content || disableTooltips || suppressed) return children;\n return (\n <Tooltip>\n <TooltipTrigger asChild>{children}</TooltipTrigger>\n <TooltipContent\n side={side}\n align={align}\n collisionPadding={8}\n avoidCollisions\n >\n {content}\n {shortcut && (\n <span className=\"ms-1.5 whitespace-nowrap text-primary-foreground/60\">\n {shortcut}\n </span>\n )}\n </TooltipContent>\n </Tooltip>\n );\n}\n\nexport { TooltipProvider, Tooltippy, SuppressTooltips };\n","import React from 'react';\nimport { useConfig } from '@opencx/widget-react-headless';\nimport styles from '../../index.css?inline.css';\nimport { version } from '../../package.json';\nimport { useTheme } from '../hooks/useTheme';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { DialogerProvider } from './Dialoger';\nimport { TooltipProvider } from './lib/tooltip';\nimport { cn } from './lib/utils/cn';\n\n/**\n * Every display mode renders the widget UI inside an iframe so host-page CSS\n * can't leak in. This module is the single source for that document:\n * `buildFrameHtml` is the iframe's initial markup and `FrameDocument` is the\n * inner wrapper. Style order is the contract that keeps embedder\n * customizations working across `displayMode` switches: mode-specific\n * `overrides` first, the embedder's `cssOverrides` after (so theirs always\n * win), then the theme variables (palette/primaryColor) + language direction\n * on the root element — identical wiring in popover, companion, and sidebar.\n */\n\n/** Accessible title of the widget content iframe, every display mode. */\nexport const WIDGET_FRAME_TITLE = 'OpenCX Live Chat';\n\nexport function buildFrameHtml({\n transparent = false,\n}: { transparent?: boolean } = {}) {\n return `<!DOCTYPE html>\n<html>\n<head>\n<style>\n${styles}\nhtml, body {\n height: 100%;\n width: 100%;\n margin: 0;\n padding: 0;\n font-size: 16px;${transparent ? '\\n background: transparent;' : ''}\n}\n</style>\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, interactive-widget=resizes-content\">\n</head>\n<body>\n</body>\n</html>`;\n}\n\nexport function FrameDocument({\n overrides,\n rootRef,\n style,\n shellRadius,\n children,\n}: {\n /** Mode-specific restyle of the stock screens; `cssOverrides` inject after */\n overrides?: string;\n rootRef?: React.Ref<HTMLDivElement>;\n style?: React.CSSProperties;\n /**\n * The outer corner radius of the shell this document fills, as a CSS\n * length. Nested surfaces (the composer card) derive their own radius from\n * it so corners stay concentric: inner = outer − the gap between the edges.\n * @default the popover container's radius\n */\n shellRadius?: string;\n children: React.ReactNode;\n}) {\n const { cssOverrides } = useConfig();\n const { cssVars, theme } = useTheme();\n const { dir } = useTranslation();\n const radiusVars = {\n ['--opencx-shell-radius' as string]:\n shellRadius ?? theme.widgetContentContainer.borderRadius,\n // The concentric radius for any card the screens inset by their 8px\n // padding — the composer and the session-closed card both wear it, so\n // neither can drift from the shell or from each other. Floored at 12px so\n // a square-cornered small-screen shell still gets a soft card.\n ['--opencx-inset-radius' as string]:\n 'max(0.75rem, calc(var(--opencx-shell-radius) - 0.5rem))',\n };\n\n return (\n <>\n {overrides ? <style>{overrides}</style> : null}\n {cssOverrides ? <style>{cssOverrides}</style> : null}\n <div\n ref={rootRef}\n style={{ ...cssVars, ...radiusVars, ...style }}\n data-version={version}\n dir={dir}\n className={cn(\n 'antialiased font-sans size-full overflow-hidden relative text-secondary-foreground isolate',\n )}\n >\n <TooltipProvider\n delayDuration={200}\n // this is important, because without it, the tooltip remains even after moving the mouse away from trigger\n disableHoverableContent\n >\n <DialogerProvider>{children}</DialogerProvider>\n </TooltipProvider>\n </div>\n </>\n );\n}\n","import { useEffect } from 'react';\nimport { useIsSmallScreen } from './useIsSmallScreen';\nimport { useConfig, useWidget } from '@opencx/widget-react-headless';\n\nexport function useSetWidgetSizeFn() {\n const { contentIframeRef } = useWidget();\n const { inline } = useConfig();\n\n return {\n setWidth: (width: string) => {\n contentIframeRef?.current?.style.setProperty(\n '--opencx-widget-width',\n inline ? '100%' : width,\n );\n },\n setHeight: (height: string) => {\n contentIframeRef?.current?.style.setProperty(\n '--opencx-widget-height',\n inline ? '100%' : height,\n );\n },\n };\n}\n\nexport function useSetWidgetSize({\n width,\n height,\n}: {\n width?: string;\n height?: string;\n}) {\n const { isSmallScreen } = useIsSmallScreen();\n const { setWidth, setHeight } = useSetWidgetSizeFn();\n\n useEffect(() => {\n if (width) setWidth(width);\n\n if (height) setHeight(height);\n }, [isSmallScreen, height, width, setWidth, setHeight]);\n}\n","import { isExhaustive, type IconNameU } from '@opencx/widget-core';\nimport {\n AtSignIcon,\n BotIcon,\n BookIcon,\n BookOpenIcon,\n Building2Icon,\n CalendarIcon,\n CreditCardIcon,\n DatabaseIcon,\n FileTextIcon,\n FolderIcon,\n GlobeIcon,\n LinkIcon,\n MailIcon,\n PackageIcon,\n PlugIcon,\n SettingsIcon,\n ShoppingCartIcon,\n TagIcon,\n TicketIcon,\n UserIcon,\n UsersIcon,\n WorkflowIcon,\n ZapIcon,\n CheckCheckIcon,\n CheckIcon,\n CircleCheckBigIcon,\n CircleCheckIcon,\n CircleDashedIcon,\n CircleXIcon,\n ExpandIcon,\n Maximize2Icon,\n MaximizeIcon,\n Minimize2Icon,\n MinimizeIcon,\n ShrinkIcon,\n SquareCheckBigIcon,\n SquareCheckIcon,\n SquareXIcon,\n XIcon,\n type LucideIcon,\n} from 'lucide-react';\nimport React from 'react';\nimport { cn } from './utils/cn';\n\nconst FallbackIcon = CircleDashedIcon;\n\nexport function DynamicIcon({\n name,\n className,\n}: {\n name: IconNameU | undefined;\n className?: string;\n}) {\n const Icon: LucideIcon = (() => {\n switch (name) {\n case 'Check':\n return CheckIcon;\n case 'CheckCheck':\n return CheckCheckIcon;\n case 'CircleCheck':\n return CircleCheckIcon;\n case 'CircleCheckBig':\n return CircleCheckBigIcon;\n case 'CircleX':\n return CircleXIcon;\n case 'Expand':\n return ExpandIcon;\n case 'Maximize':\n return MaximizeIcon;\n case 'Maximize2':\n return Maximize2Icon;\n case 'Minimize':\n return MinimizeIcon;\n case 'Minimize2':\n return Minimize2Icon;\n case 'Shrink':\n return ShrinkIcon;\n case 'SquareCheck':\n return SquareCheckIcon;\n case 'SquareCheckBig':\n return SquareCheckBigIcon;\n case 'SquareX':\n return SquareXIcon;\n case 'X':\n return XIcon;\n case 'AtSign':\n return AtSignIcon;\n case 'Bot':\n return BotIcon;\n case 'Book':\n return BookIcon;\n case 'BookOpen':\n return BookOpenIcon;\n case 'Building2':\n return Building2Icon;\n case 'Calendar':\n return CalendarIcon;\n case 'CreditCard':\n return CreditCardIcon;\n case 'Database':\n return DatabaseIcon;\n case 'FileText':\n return FileTextIcon;\n case 'Folder':\n return FolderIcon;\n case 'Globe':\n return GlobeIcon;\n case 'Link':\n return LinkIcon;\n case 'Mail':\n return MailIcon;\n case 'Package':\n return PackageIcon;\n case 'Plug':\n return PlugIcon;\n case 'Settings':\n return SettingsIcon;\n case 'ShoppingCart':\n return ShoppingCartIcon;\n case 'Tag':\n return TagIcon;\n case 'Ticket':\n return TicketIcon;\n case 'User':\n return UserIcon;\n case 'Users':\n return UsersIcon;\n case 'Workflow':\n return WorkflowIcon;\n case 'Zap':\n return ZapIcon;\n\n case undefined:\n return FallbackIcon;\n\n default:\n isExhaustive(name, DynamicIcon.name);\n return FallbackIcon;\n }\n })();\n\n return <Icon className={cn('size-4', className)} />;\n}\n","import {\n usePrimitiveState,\n type useCompanionChats,\n} from '@opencx/widget-react-headless';\nimport { useTranslation } from '../hooks/useTranslation';\n\n/** The same conversation name and preview wherever a session is selected. */\nexport function useSessionIdentity(\n chat: ReturnType<typeof useCompanionChats>['chats'][number],\n) {\n const { t } = useTranslation();\n const { session } = usePrimitiveState(chat.ctx.sessionCtx.sessionState);\n const { messages } = usePrimitiveState(chat.ctx.messageCtx.state);\n const draft = usePrimitiveState(chat.ctx.messageCtx.draftState);\n const title =\n chat.title ||\n session?.title ||\n t('companion_chat_number', { count: chat.id });\n let preview = session?.lastMessage ?? draft.text ?? '';\n for (let i = messages.length - 1; i >= 0; i--) {\n const message = messages[i]!;\n const text =\n message.type === 'USER'\n ? message.content\n : message.type === 'SYSTEM'\n ? ''\n : message.data.message;\n if (text.trim()) {\n preview = text;\n break;\n }\n }\n const status = chat.working\n ? t('companion_working')\n : session?.isOpened\n ? t('companion_open')\n : session\n ? t('companion_closed')\n : t('companion_draft');\n const empty =\n !chat.hasDraft &&\n !chat.hasSession &&\n !chat.working &&\n !session &&\n !chat.title &&\n !messages.length &&\n !draft.text &&\n !draft.mentions.length;\n return {\n title: empty ? t('new_conversation') : title,\n preview: preview.replace(/\\s+/g, ' ').trim(),\n status,\n };\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport { useCanHover } from '../hooks/useCanHover';\n\n/** Hover intent only; Radix owns menu focus, navigation, placement and dismissal. */\nexport function useChatPicker() {\n const canHover = useCanHover();\n const [anchor, setAnchor] = useState<HTMLElement | null>(null);\n const [open, setOpen] = useState(false);\n const [animate, setAnimate] = useState(false);\n const [autoFocus, setAutoFocus] = useState(false);\n const pinned = useRef(false);\n const timer = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n const clear = useCallback(() => clearTimeout(timer.current), []);\n useEffect(() => clear, [clear]);\n const close = useCallback(\n (instant = false) => {\n clear();\n pinned.current = false;\n if (instant) setAnimate(false);\n setOpen(false);\n },\n [clear],\n );\n return {\n anchor,\n open,\n animate,\n autoFocus,\n close,\n toggle(target: HTMLElement, pointer = false) {\n clear();\n if (open && pinned.current) {\n close(!pointer);\n return;\n }\n pinned.current = true;\n setAnchor(target);\n setAnimate(pointer);\n setAutoFocus(true);\n setOpen(true);\n },\n hover(target: HTMLElement) {\n clear();\n if (!canHover || open) return;\n timer.current = setTimeout(() => {\n pinned.current = false;\n setAnchor(target);\n setAnimate(true);\n setAutoFocus(false);\n setOpen(true);\n }, 100);\n },\n enter: clear,\n leave() {\n clear();\n if (!pinned.current) timer.current = setTimeout(() => close(), 200);\n },\n };\n}\n","import React from 'react';\n\n/** The host portal sits outside the iframe stylesheet; reuse Button's Wobble variables there. */\nexport function CompanionControlStyles() {\n return (\n <style>{`\n [data-companion-action] {\n transition: transform 150ms ease-out, background-color 150ms ease-out, color 150ms ease-out, opacity 100ms ease-out;\n }\n @media (hover: hover) and (pointer: fine) and (prefers-reduced-motion: no-preference) {\n [data-companion-action] { transform: translate(var(--wobble-x, 0px), var(--wobble-y, 0px)); }\n [data-companion-action]:hover { transform: translate(var(--wobble-x, 0px), var(--wobble-y, 0px)) scale(var(--scale, .98)); }\n [data-companion-action]:hover:active { transform: translate(var(--wobble-x, 0px), var(--wobble-y, 0px)) scale(calc(var(--scale, .98) - .02)); }\n }\n @media (prefers-reduced-motion: reduce), (pointer: coarse) {\n [data-companion-action] { transform: none !important; transition: none; }\n }\n `}</style>\n );\n}\n","import React, {\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport * as Menu from '@radix-ui/react-menu';\nimport { useCompanionChats, useSessions } from '@opencx/widget-react-headless';\nimport { CheckIcon, LoaderCircleIcon, PlusIcon, XIcon } from 'lucide-react';\nimport {\n Button,\n buttonVariants,\n type ButtonProps,\n} from '../components/lib/button';\nimport { Wobble } from '../components/lib/wobble';\nimport { useTheme } from '../hooks/useTheme';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { EASE_OUT_CSS, QUICK_TWEEN } from '../motion';\nimport { useSessionIdentity } from './useSessionIdentity';\nimport { type useChatPicker } from './useChatPicker';\nimport { CompanionControlStyles } from './CompanionControlStyles';\n\ntype Chat = ReturnType<typeof useCompanionChats>['chats'][number];\n\nexport function ChatPickerTrigger({\n picker,\n ...props\n}: ButtonProps & {\n picker: ReturnType<typeof useChatPicker>;\n}) {\n return (\n <>\n <CompanionControlStyles />\n <Button\n {...props}\n variant=\"ghost\"\n size=\"selfless\"\n type=\"button\"\n data-companion-action=\"\"\n aria-haspopup=\"menu\"\n aria-expanded={picker.open}\n onPointerEnter={(event) => picker.hover(event.currentTarget)}\n onPointerLeave={picker.leave}\n onPointerDown={(event) => {\n // Keep focus in the host menu until click toggles it. Focusing the\n // iframe trigger first dismisses the menu and makes click reopen it.\n if (picker.open) event.preventDefault();\n }}\n onClick={(event) => {\n event.stopPropagation();\n picker.toggle(event.currentTarget, event.detail > 0);\n }}\n onKeyDown={(event) => {\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n picker.toggle(event.currentTarget);\n }\n }}\n />\n </>\n );\n}\n\nfunction ChatRow({\n chat,\n selected,\n onSelect,\n onClose,\n}: {\n chat: Chat;\n selected: boolean;\n onSelect: () => void;\n onClose: () => void;\n}) {\n const { t } = useTranslation();\n const { title, preview, status } = useSessionIdentity(chat);\n return (\n <Wobble>\n <div\n data-chat-row=\"\"\n data-companion-action=\"\"\n data-selected={selected || undefined}\n >\n <Menu.RadioItem\n asChild\n value={String(chat.id)}\n textValue={title}\n onSelect={(event) => {\n event.preventDefault();\n onSelect();\n }}\n >\n <button\n className={buttonVariants({\n size: 'selfless',\n className: 'bg-transparent',\n })}\n type=\"button\"\n data-companion-action=\"\"\n aria-description={preview || undefined}\n aria-label={`${title} — ${status}${selected ? ` — ${t('companion_viewing')}` : ''}`}\n data-chat-select={chat.id}\n >\n <span data-chat-indicator=\"\" aria-hidden>\n <Menu.ItemIndicator>\n <CheckIcon size={14} />\n </Menu.ItemIndicator>\n </span>\n <span data-chat-title=\"\">{title}</span>\n {chat.working && (\n <LoaderCircleIcon size={14} data-working=\"\" aria-hidden />\n )}\n </button>\n </Menu.RadioItem>\n <Menu.Item\n asChild\n textValue={t('companion_close_chat', { title })}\n onSelect={(event) => {\n event.preventDefault();\n onClose();\n }}\n >\n <button\n className={buttonVariants({\n size: 'selfless',\n className: 'bg-transparent',\n })}\n type=\"button\"\n data-companion-action=\"\"\n aria-label={t('companion_close_chat', { title })}\n data-chat-close={chat.id}\n >\n <XIcon size={14} aria-hidden />\n </button>\n </Menu.Item>\n </div>\n </Wobble>\n );\n}\n\ntype ChatPickerProps = {\n picker: ReturnType<typeof useChatPicker>;\n portalTarget: HTMLElement | null;\n placement: 'above' | 'below';\n onSelected?: () => void;\n};\n\n/** One controller owns hover intent and opening state at every entry point. */\nexport function ChatPicker(props: ChatPickerProps) {\n const { picker, portalTarget } = props;\n return picker.anchor && portalTarget ? (\n <ChatPickerContent\n {...props}\n anchor={picker.anchor}\n portalTarget={portalTarget}\n />\n ) : null;\n}\n\n/** Radix handles placement and focus; the bridge crosses the widget iframe. */\nfunction ChatPickerContent({\n picker,\n anchor,\n portalTarget: container,\n placement,\n onSelected,\n}: ChatPickerProps & { anchor: HTMLElement; portalTarget: HTMLElement }) {\n const {\n open,\n animate,\n autoFocus,\n close: onClose,\n enter: onPointerEnter,\n leave: onPointerLeave,\n } = picker;\n const {\n chats: activeChats,\n activeId,\n selectChat,\n newChat,\n closeChat,\n } = useCompanionChats();\n const { canCreateNewSession } = useSessions();\n const { t, dir } = useTranslation();\n const { cssVars, theme } = useTheme();\n const menuRef = useRef<HTMLDivElement>(null);\n const previousFocus = useRef(\n anchor.ownerDocument.activeElement as HTMLElement | null,\n );\n const setMenuRef = useCallback(\n (node: HTMLDivElement | null) => {\n if (node && !menuRef.current)\n previousFocus.current = anchor.ownerDocument\n .activeElement as HTMLElement | null;\n menuRef.current = node;\n },\n [anchor],\n );\n const restoringHoverFocus = useRef(false);\n const callbacks = useRef({ onClose, onSelected });\n callbacks.current = { onClose, onSelected };\n const virtualAnchor = useMemo(\n () => ({\n current: {\n getBoundingClientRect() {\n let rect = anchor.getBoundingClientRect();\n let view = anchor.ownerDocument.defaultView;\n const hostWindow = container.ownerDocument.defaultView;\n // Only coordinate conversion is widget-specific. Radix handles collisions,\n // scrolling, direction and popup placement in the host document.\n while (view && view !== hostWindow) {\n const frame = view.frameElement as HTMLIFrameElement | null;\n if (!frame) break;\n const outer = frame.getBoundingClientRect();\n const sx = outer.width / frame.offsetWidth || 1;\n const sy = outer.height / frame.offsetHeight || 1;\n rect = new DOMRect(\n outer.left + rect.left * sx,\n outer.top + rect.top * sy,\n rect.width * sx,\n rect.height * sy,\n );\n view = frame.ownerDocument.defaultView;\n }\n return rect;\n },\n },\n }),\n [anchor, container],\n );\n const workingCount = activeChats.filter((chat) => chat.working).length;\n\n useEffect(() => {\n if (!open || anchor.ownerDocument === container.ownerDocument) return;\n // Events inside an iframe don't bubble to the host's Radix dismissable layer.\n const outside = (event: Event) => {\n if (event.composedPath().includes(anchor)) return;\n if (\n event.type === 'focusin' &&\n !autoFocus &&\n event.target === previousFocus.current\n )\n return;\n callbacks.current.onClose(event.type === 'focusin');\n };\n const doc = anchor.ownerDocument;\n doc.addEventListener('pointerdown', outside, true);\n doc.addEventListener('focusin', outside);\n return () => {\n doc.removeEventListener('pointerdown', outside, true);\n doc.removeEventListener('focusin', outside);\n };\n }, [anchor, container, open, autoFocus]);\n\n useLayoutEffect(() => {\n menuRef.current?.toggleAttribute('inert', !open);\n if (open && autoFocus)\n menuRef.current\n ?.querySelector<HTMLElement>('[aria-checked=\"true\"]')\n ?.focus({ preventScroll: true });\n }, [open, autoFocus]);\n\n function choose(id?: number) {\n anchor.focus({ preventScroll: true });\n if (id === undefined) newChat();\n else selectChat(id);\n callbacks.current.onClose(true);\n callbacks.current.onSelected?.();\n }\n function dismissChat(id: number) {\n const index = activeChats.findIndex((chat) => chat.id === id);\n const next = activeChats[index + 1] ?? activeChats[index - 1];\n if (id === activeId) {\n anchor.focus({ preventScroll: true });\n callbacks.current.onClose(true);\n } else\n menuRef.current\n ?.querySelector<HTMLElement>(\n next ? `[data-chat-select=\"${next.id}\"]` : '[data-new-chat]',\n )\n ?.focus({ preventScroll: true });\n closeChat(id);\n if (id === activeId) callbacks.current.onSelected?.();\n }\n return createPortal(\n <Menu.Root\n open={open}\n onOpenChange={(next) => {\n if (!next && !restoringHoverFocus.current) callbacks.current.onClose();\n }}\n modal={false}\n dir={dir === 'rtl' ? 'rtl' : 'ltr'}\n >\n <Menu.Anchor virtualRef={virtualAnchor} />\n <Menu.Content\n ref={setMenuRef}\n loop\n side={placement === 'above' ? 'top' : 'bottom'}\n align={placement === 'below' ? 'start' : 'center'}\n sideOffset={6}\n collisionPadding={12}\n updatePositionStrategy=\"always\"\n aria-label={t('companion_chats')}\n data-companion-chat-picker=\"\"\n data-motion={animate ? 'pointer' : 'instant'}\n onEntryFocus={(event) => {\n event.preventDefault();\n if (autoFocus)\n menuRef.current\n ?.querySelector<HTMLElement>('[aria-checked=\"true\"]')\n ?.focus({ preventScroll: true });\n else {\n // Focusing the composer iframe blurs the host window. Radix normally\n // dismisses on window blur; this one synchronous focus restoration\n // belongs to opening the hover preview, not leaving the menu.\n restoringHoverFocus.current = true;\n previousFocus.current?.focus({ preventScroll: true });\n restoringHoverFocus.current = false;\n }\n }}\n onCloseAutoFocus={(event) => {\n event.preventDefault();\n }}\n onEscapeKeyDown={(event) => {\n event.preventDefault();\n anchor.focus({ preventScroll: true });\n callbacks.current.onClose(true);\n }}\n onFocusOutside={(event) => {\n if (\n menuRef.current?.contains(\n event.detail.originalEvent.target as Node,\n ) ||\n event.detail.originalEvent.target === anchor ||\n event.detail.originalEvent.target ===\n anchor.ownerDocument.defaultView?.frameElement ||\n (!autoFocus &&\n event.detail.originalEvent.target === previousFocus.current)\n )\n event.preventDefault();\n }}\n onInteractOutside={(event) => {\n if (event.detail.originalEvent.composedPath().includes(anchor))\n event.preventDefault();\n }}\n onPointerEnter={onPointerEnter}\n onPointerLeave={onPointerLeave}\n onPointerDown={(event) => event.stopPropagation()}\n onMouseDown={(event) => event.stopPropagation()}\n onClick={(event) => event.stopPropagation()}\n onKeyDown={(event) => {\n if (event.key === 'Tab') {\n event.preventDefault();\n anchor.focus({ preventScroll: true });\n callbacks.current.onClose(true);\n }\n }}\n style={{\n ...cssVars,\n zIndex: theme.widgetContentContainer.zIndex + 1,\n boxSizing: 'border-box',\n width: 'min(248px, calc(100vw - 24px))',\n maxHeight: 'min(360px, var(--radix-popper-available-height))',\n padding: 6,\n borderRadius: 10,\n border: '1px solid hsl(var(--opencx-border) / .5)',\n background: 'hsl(var(--opencx-background))',\n color: 'hsl(var(--opencx-foreground))',\n boxShadow: '0 4px 16px rgb(0 0 0 / .08), 0 1px 3px rgb(0 0 0 / .06)',\n font: '13px/1.4 ui-sans-serif, system-ui, sans-serif',\n overflowY: 'auto',\n outline: 'none',\n }}\n >\n <CompanionControlStyles />\n <style>{`\n [data-companion-chat-picker] {\n transform-origin: var(--radix-popper-transform-origin);\n animation: opencx-menu-in ${QUICK_TWEEN.duration * 1000}ms ${EASE_OUT_CSS};\n }\n [data-companion-chat-picker][data-state=\"closed\"] { animation-name: opencx-menu-out; pointer-events: none; }\n [data-companion-chat-picker][data-motion=\"instant\"] { animation: none; }\n @media (prefers-reduced-motion: reduce) {\n [data-companion-chat-picker] { animation: none !important; }\n }\n @keyframes opencx-menu-in { from { opacity: 0; transform: scale(.96); } to { opacity: 1; transform: scale(1); } }\n @keyframes opencx-menu-out { from { opacity: 1; transform: scale(1); } to { opacity: 0; transform: scale(.96); } }\n [data-companion-chat-picker] button {\n display: flex; align-items: center; justify-content: flex-start; gap: 8px; width: 100%; min-height: 34px;\n padding: 7px 8px; border: 0; border-radius: 7px; background: transparent;\n color: inherit; font: inherit; text-align: start; cursor: pointer; box-sizing: border-box;\n }\n [data-companion-chat-picker] [data-chat-row] { display: flex; align-items: center; border-radius: 7px; }\n [data-companion-chat-picker] [data-chat-row] + [data-chat-row] { margin-top: 4px; }\n [data-companion-chat-picker] [data-chat-select] { flex: 1; min-width: 0; min-height: 36px; color: hsl(var(--opencx-foreground) / .8); }\n [data-companion-chat-picker] [data-selected] [data-chat-select] { color: hsl(var(--opencx-foreground)); }\n [data-companion-chat-picker] [data-chat-indicator] { width: 14px; height: 14px; display: flex; align-items: center; flex-shrink: 0; color: hsl(var(--opencx-muted-foreground)); }\n [data-companion-chat-picker] [data-selected] [data-chat-indicator],\n [data-companion-chat-picker] [data-working] { color: hsl(var(--opencx-foreground)); }\n [data-companion-chat-picker] [data-chat-title] { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 13px; line-height: 20px; }\n [data-companion-chat-picker] [data-chat-close] { width: 28px; min-height: 28px; padding: 0; margin-inline-end: 4px; flex-shrink: 0; justify-content: center; color: hsl(var(--opencx-muted-foreground)); }\n [data-companion-chat-picker] [data-chat-row]:focus-within { background: hsl(var(--opencx-secondary)); }\n @media (hover: hover) and (pointer: fine) {\n [data-companion-chat-picker] [data-chat-row]:hover,\n [data-companion-chat-picker] [data-new-chat][data-highlighted] { background: hsl(var(--opencx-secondary)); }\n [data-companion-chat-picker] [data-chat-close]:hover { color: hsl(var(--opencx-foreground)); }\n }\n [data-companion-chat-picker] [data-chat-row] button {\n background: transparent; transform: none;\n }\n [data-companion-chat-picker] [data-chat-close][data-highlighted] { color: hsl(var(--opencx-foreground)); }\n [data-companion-chat-picker] button:active { background: hsl(var(--opencx-foreground) / .065); }\n [data-companion-chat-picker] button:focus { outline: none; }\n [data-companion-chat-picker] button:disabled { opacity: .45; cursor: default; }\n @media (pointer: coarse) {\n [data-companion-chat-picker] button, [data-companion-chat-picker] [data-chat-select] { min-height: 48px; }\n [data-companion-chat-picker] [data-chat-close] { width: 48px; min-height: 48px; }\n [data-companion-chat-picker] [data-chat-title], [data-companion-chat-picker] [data-new-chat] { font-size: 16px; }\n }\n [data-companion-chat-picker] svg { flex-shrink: 0; }\n [data-companion-chat-picker] [data-working] { animation: opencx-picker-spin 1.2s linear infinite; }\n @keyframes opencx-picker-spin { to { transform: rotate(360deg); } }\n @media (prefers-reduced-motion: reduce) { [data-companion-chat-picker] [data-working] { animation: none; } }\n `}</style>\n <Menu.Label\n style={{\n display: 'flex',\n justifyContent: 'space-between',\n gap: 8,\n padding: '5px 8px 7px',\n fontSize: 12,\n color: 'hsl(var(--opencx-muted-foreground))',\n }}\n >\n <span>{t('companion_chats')}</span>\n {workingCount > 0 && (\n <span role=\"status\">\n {t('companion_working_chats', { count: workingCount })}\n </span>\n )}\n </Menu.Label>\n <Menu.RadioGroup value={String(activeId)}>\n {activeChats.map((chat) => (\n <ChatRow\n key={chat.id}\n chat={chat}\n selected={chat.id === activeId}\n onSelect={() => choose(chat.id)}\n onClose={() => dismissChat(chat.id)}\n />\n ))}\n </Menu.RadioGroup>\n <Menu.Separator\n style={{\n height: 1,\n background: 'hsl(var(--opencx-border) / .4)',\n margin: '5px 4px',\n }}\n />\n <Menu.Group>\n <Menu.Item\n asChild\n disabled={!canCreateNewSession}\n onSelect={(event) => {\n event.preventDefault();\n choose();\n }}\n >\n <Button\n variant=\"ghost\"\n size=\"selfless\"\n type=\"button\"\n data-companion-action=\"\"\n data-new-chat=\"\"\n disabled={!canCreateNewSession}\n >\n <PlusIcon size={14} aria-hidden />\n {t('new_conversation')}\n </Button>\n </Menu.Item>\n </Menu.Group>\n </Menu.Content>\n </Menu.Root>,\n container,\n );\n}\n","import { useEffect, useState } from 'react';\n\n/**\n * A document-root mount point for host-DOM overlays — the companion shell\n * and the page-mark overlays: <Widget> may render arbitrarily deep in\n * the host app (shadow roots, transformed or stacking-context ancestors)\n * where position:fixed breaks. Root-level mounting is the same guarantee\n * the embed script provides.\n *\n * The mount point must sit ABOVE body, not in it: the companion's sidebar\n * layout turns body into the page frame (contain: strict — see\n * app-frame.ts), and containment would trap body-portaled fixed elements\n * inside the framed page.\n *\n * It also can't be document.documentElement itself: React 19 treats\n * <html>/<head>/<body> as singleton host components, and a portal whose\n * container is the <html> singleton gets its children redirected into\n * body (observed under Next.js App Router, where React renders the whole\n * document) — right back inside the containment. So we create our OWN\n * div, append it to <html> with raw DOM (which browsers honor and no\n * framework touches), and portal into that.\n */\nexport function useHostPortal(): HTMLElement | null {\n const [target, setTarget] = useState<HTMLElement | null>(null);\n useEffect(() => {\n const host = document.createElement('div');\n host.setAttribute('data-opencx-root', '');\n // Layout-neutral: children are position:fixed; the wrapper itself must\n // never add a box to <html>'s flow.\n host.style.display = 'contents';\n document.documentElement.appendChild(host);\n setTarget(host);\n return () => {\n host.remove();\n setTarget(null);\n };\n }, []);\n return target;\n}\n","import React from 'react';\nimport { useCompanionChats } from '@opencx/widget-react-headless';\nimport { ChevronsUpDownIcon, LoaderCircleIcon } from 'lucide-react';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { ChatPicker, ChatPickerTrigger } from './ChatPicker';\nimport { useChatPicker } from './useChatPicker';\nimport { useHostPortal } from './useHostPortal';\nimport { useSessionIdentity } from './useSessionIdentity';\n\n/** Uses the existing title slot so switching never adds another row to the panel. */\nexport function ConversationTitle() {\n const { chats, openChats, activeId } = useCompanionChats();\n const chat = chats.find((item) => item.id === activeId)!;\n const identity = useSessionIdentity(chat);\n const { t } = useTranslation();\n const picker = useChatPicker();\n const portalTarget = useHostPortal();\n const title = identity.title;\n const otherSessions = openChats.filter((item) => item.id !== activeId);\n const otherWorkingCount = otherSessions.filter((item) => item.working).length;\n const otherSessionsLabel = `${t('companion_other_sessions', { count: otherSessions.length })}${otherWorkingCount ? ` · ${t('companion_working_chats', { count: otherWorkingCount })}` : ''}`;\n const switchLabel = `${t('companion_switch_chat')}: ${title}${otherSessions.length ? ` · ${otherSessionsLabel}` : ''}`;\n return (\n <>\n <ChatPickerTrigger\n picker={picker}\n data-companion-conversation-title=\"\"\n className=\"flex h-8 min-w-0 max-w-full items-center gap-1.5 rounded-md px-1 text-[13px] leading-5 text-start hover:bg-muted aria-expanded:bg-muted focus-visible:outline focus-visible:outline-2 focus-visible:outline-ring\"\n aria-label={switchLabel}\n >\n {chat.working && (\n <LoaderCircleIcon\n aria-label={t('companion_working')}\n className=\"size-3.5 shrink-0 animate-spin motion-reduce:animate-none\"\n />\n )}\n <span className=\"truncate font-medium\">{title}</span>\n {otherSessions.length > 0 && (\n <span\n data-other-session-count=\"\"\n role=\"status\"\n aria-atomic=\"true\"\n className=\"flex shrink-0 items-center gap-1 text-[11px] font-normal text-muted-foreground\"\n >\n <span className=\"sr-only\">{otherSessionsLabel}</span>\n {otherWorkingCount > 0 && (\n <LoaderCircleIcon\n data-other-sessions-working=\"\"\n aria-hidden\n className=\"size-3 animate-spin motion-reduce:animate-none\"\n />\n )}\n <span aria-hidden className=\"tabular-nums\">\n +{otherSessions.length}\n </span>\n </span>\n )}\n <ChevronsUpDownIcon\n aria-hidden\n className=\"size-3 shrink-0 text-muted-foreground\"\n />\n </ChatPickerTrigger>\n {picker.anchor && portalTarget && (\n <ChatPicker\n picker={picker}\n portalTarget={portalTarget}\n placement=\"below\"\n />\n )}\n </>\n );\n}\n","import React from 'react';\nimport { useComponentContext } from '../../hooks/useComponentContext';\n\nexport function HeaderBottomComponent() {\n const props = useComponentContext();\n const Component = props.config.customComponents?.headerBottom;\n\n if (!Component) return null;\n\n return <Component {...props} />;\n}\n","import React, { type ReactNode } from 'react';\nimport { useComponentContext } from '../../hooks/useComponentContext';\n\nexport function HeaderTitleComponent({ fallback }: { fallback: ReactNode }) {\n const props = useComponentContext();\n const Component = props.config.customComponents?.headerTitle;\n\n if (!Component) return fallback;\n\n return <Component {...props} />;\n}\n","import {\n isExhaustive,\n type HeaderButtonU,\n type SafeExtract,\n type ScreenU,\n type WidgetConfig,\n log,\n} from '@opencx/widget-core';\nimport {\n useConfig,\n useSessions,\n useWidget,\n useWidgetRouter,\n useWidgetTrigger,\n} from '@opencx/widget-react-headless';\nimport { ChevronLeftIcon } from 'lucide-react';\nimport React, { useState } from 'react';\nimport { useComponentContext } from '../hooks/useComponentContext';\nimport { useIsSmallScreen } from '../hooks/useIsSmallScreen';\nimport { useSetWidgetSizeFn } from '../hooks/useSetWidgetSize';\nimport { useTheme } from '../hooks/useTheme';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { dc } from '../utils/data-component';\nimport {\n Dialoger,\n DialogerBody,\n DialogerContent,\n DialogerDescription,\n DialogerFooter,\n DialogerHeader,\n DialogerTitle,\n useDialoger,\n} from './Dialoger';\nimport { Button } from './lib/button';\nimport { DynamicIcon } from './lib/DynamicIcon';\nimport { cn } from './lib/utils/cn';\nimport { ConversationTitle } from '../companion/ConversationTitle';\nimport { HeaderBottomComponent } from './custom-components/HeaderBottomComponent';\nimport { HeaderTitleComponent } from './custom-components/HeaderTitleComponent';\n\n/**\n * The header names the ORGANIZATION (v4 behavior) unless the embed overrides\n * it per screen; the agent's name brands the reply bubbles (`useBot`), not\n * the chrome.\n */\nexport function resolveHeaderTitle(\n screen: ScreenU,\n textContent: WidgetConfig['textContent'],\n orgName: string,\n): string {\n switch (screen) {\n case 'chat':\n return textContent?.chatScreen?.headerTitle ?? orgName;\n case 'sessions':\n return textContent?.sessionsScreen?.headerTitle ?? orgName;\n case 'welcome':\n return orgName;\n default:\n isExhaustive(screen, resolveHeaderTitle.name);\n return orgName;\n }\n}\n\nfunction useGetHeaderTitle() {\n const {\n widgetCtx: { org },\n } = useWidget();\n const {\n routerState: { screen },\n } = useWidgetRouter();\n const { textContent } = useConfig();\n return resolveHeaderTitle(screen, textContent, org.name);\n}\n\nfunction useGetHeaderDataComponentProp(\n screen: ScreenU,\n): ReturnType<typeof dc> | undefined {\n switch (screen) {\n case 'chat':\n return dc('chat/header');\n case 'sessions':\n return dc('sessions/header');\n case 'welcome':\n return undefined;\n default:\n isExhaustive(screen, useGetHeaderTitle.name);\n return undefined;\n }\n}\n\nfunction Header__BackToSessionsScreenButton() {\n const { router } = useConfig();\n const {\n routerState: { screen },\n toSessionsScreen,\n } = useWidgetRouter();\n\n if (screen !== 'chat') return null;\n if (router?.chatScreenOnly) return null;\n\n return (\n <Button\n variant=\"ghost\"\n size=\"fit\"\n className=\"rounded-full\"\n onClick={toSessionsScreen}\n >\n <ChevronLeftIcon className=\"size-4 rtl:-scale-100\" />\n </Button>\n );\n}\n\nfunction Header__Buttons__Item__CloseWidget({\n button,\n}: {\n button: SafeExtract<HeaderButtonU, { functionality: 'close-widget' }>;\n}) {\n const { setIsOpen } = useWidgetTrigger();\n const { isSmallScreen } = useIsSmallScreen();\n const componentCtx = useComponentContext();\n\n if (isSmallScreen && button.hideOnSmallScreen) return null;\n if (!isSmallScreen && button.hideOnLargeScreen) return null;\n\n const handleClick = () => {\n if (button.handleClick) {\n button.handleClick();\n } else {\n setIsOpen(false);\n }\n button.onClicked?.(componentCtx);\n };\n\n return (\n <Button\n variant=\"ghost\"\n size=\"fit\"\n className=\"rounded-full\"\n onClick={handleClick}\n >\n <DynamicIcon name={button.icon} />\n </Button>\n );\n}\n\nfunction Header__Buttons__Item__ExpandShrink({\n button,\n}: {\n button: SafeExtract<HeaderButtonU, { functionality: 'expand-shrink' }>;\n}) {\n const [expanded, setExpanded] = useState(false);\n\n const {\n routerState: { screen },\n } = useWidgetRouter();\n const { isSmallScreen } = useIsSmallScreen();\n const { theme } = useTheme();\n const { setWidth, setHeight } = useSetWidgetSizeFn();\n const componentCtx = useComponentContext();\n\n if (screen !== 'chat' && screen !== 'sessions') return null;\n\n const screenHeight = (() => {\n switch (screen) {\n case 'chat':\n return theme.screens.chat.height;\n case 'sessions':\n return theme.screens.sessions.height;\n default:\n isExhaustive(screen, Header__Buttons__Item__ExpandShrink.name);\n return theme.screens.chat.height;\n }\n })();\n const screenWidth = (() => {\n switch (screen) {\n case 'chat':\n return theme.screens.chat.width;\n case 'sessions':\n return theme.screens.sessions.width;\n default:\n isExhaustive(screen, Header__Buttons__Item__ExpandShrink.name);\n return theme.screens.chat.width;\n }\n })();\n\n const handleClick = () => {\n setExpanded((prev) => {\n const isExpanded = !prev;\n setHeight(isExpanded ? '100vh' : screenHeight);\n setWidth(isExpanded ? `max(40vw, ${screenWidth})` : screenWidth);\n\n return isExpanded;\n });\n button.onClicked?.(componentCtx);\n };\n\n if (isSmallScreen && button.hideOnSmallScreen) return null;\n if (!isSmallScreen && button.hideOnLargeScreen) return null;\n\n return (\n <Button\n variant=\"ghost\"\n size=\"fit\"\n className=\"rounded-full\"\n onClick={handleClick}\n >\n <DynamicIcon\n name={button.icon || (expanded ? button.shrinkIcon : button.expandIcon)}\n />\n </Button>\n );\n}\n\nfunction Header__Buttons__Item__ResolveSession({\n button,\n}: {\n button: SafeExtract<HeaderButtonU, { functionality: 'resolve-session' }>;\n}) {\n const { close: closeDialog } = useDialoger();\n const { widgetCtx } = useWidget();\n const { setIsOpen } = useWidgetTrigger();\n const { resolveSession, sessionState } = useSessions();\n const { isSmallScreen } = useIsSmallScreen();\n const componentCtx = useComponentContext();\n const { t } = useTranslation();\n\n const isNoSession = !sessionState.session;\n const isResolved = sessionState.session?.isOpened === false;\n const onResolved: NonNullable<typeof button.onResolved> =\n button.onResolved || 'stay-in-chat';\n const behaviorBeforeSessionCreation: NonNullable<\n typeof button.behaviorBeforeSessionCreation\n > = button.behaviorBeforeSessionCreation || 'disabled';\n const behaviorIfSessionIsResolved: NonNullable<\n typeof button.behaviorIfSessionIsResolved\n > = button.behaviorIfSessionIsResolved || 'disabled';\n\n const isDisabled = (() => {\n if (sessionState.isResolvingSession) return true;\n if (isNoSession && behaviorBeforeSessionCreation === 'disabled')\n return true;\n if (isResolved && behaviorIfSessionIsResolved === 'disabled') return true;\n return false;\n })();\n\n const handleResolve = async () => {\n const { success, error } = await resolveSession();\n closeDialog();\n if (!success) {\n log.error('failed to resolve session', error);\n return false;\n }\n\n switch (onResolved) {\n case 'stay-in-chat':\n break;\n case 'close-widget':\n setIsOpen(false);\n break;\n case 'reset-chat':\n widgetCtx.resetChat();\n break;\n case 'reset-chat-and-close-widget':\n setIsOpen(false);\n widgetCtx.resetChat();\n break;\n default:\n isExhaustive(onResolved, Header__Buttons__Item__ResolveSession.name);\n break;\n }\n\n return true;\n };\n\n const handleResolveAlternative = () => {\n if (isNoSession) {\n switch (behaviorBeforeSessionCreation) {\n case 'disabled':\n return;\n case 'close-widget':\n setIsOpen(false);\n break;\n default:\n isExhaustive(\n behaviorBeforeSessionCreation,\n handleResolveAlternative.name,\n );\n }\n }\n\n if (isResolved) {\n switch (behaviorIfSessionIsResolved) {\n case 'disabled':\n return;\n case 'close-widget':\n setIsOpen(false);\n break;\n case 'reset-chat':\n widgetCtx.resetChat();\n break;\n case 'reset-chat-and-close-widget':\n setIsOpen(false);\n setTimeout(() => {\n widgetCtx.resetChat();\n }, 200);\n break;\n default:\n isExhaustive(\n behaviorIfSessionIsResolved,\n handleResolveAlternative.name,\n );\n }\n }\n };\n\n if (isSmallScreen && button.hideOnSmallScreen) return null;\n if (!isSmallScreen && button.hideOnLargeScreen) return null;\n\n // TODO: add translations for fallbacks\n if (button.confirmation?.type === 'modal' && !isResolved && !isNoSession) {\n return (\n <Dialoger\n trigger={\n <Button\n variant=\"ghost\"\n size=\"fit\"\n className=\"rounded-full\"\n disabled={isDisabled}\n onClick={() => button.onClicked?.(componentCtx)}\n >\n <DynamicIcon name={button.icon} />\n </Button>\n }\n >\n <DialogerContent>\n <DialogerHeader>\n <DialogerTitle>\n {button.confirmation.title || t('close_conversation_title')}\n </DialogerTitle>\n </DialogerHeader>\n <DialogerBody>\n <DialogerDescription>\n {button.confirmation.description ||\n t('close_conversation_description')}\n </DialogerDescription>\n </DialogerBody>\n <DialogerFooter>\n <Button\n variant=\"secondary\"\n onClick={closeDialog}\n disabled={sessionState.isResolvingSession}\n >\n {button.confirmation.cancelButtonText ||\n t('close_conversation_cancel')}\n </Button>\n <Button\n variant=\"destructive\"\n onClick={async () => {\n const success = await handleResolve();\n if (success) button.confirmation?.onResolved?.(componentCtx);\n }}\n disabled={sessionState.isResolvingSession}\n >\n {button.confirmation.confirmButtonText ||\n t('close_conversation_confirm')}\n </Button>\n </DialogerFooter>\n </DialogerContent>\n </Dialoger>\n );\n }\n\n return (\n <Button\n variant=\"ghost\"\n size=\"fit\"\n className=\"rounded-full\"\n onClick={() => {\n if (isResolved || isNoSession) {\n handleResolveAlternative();\n } else {\n void handleResolve();\n }\n button.onClicked?.(componentCtx);\n }}\n disabled={isDisabled}\n >\n <DynamicIcon name={button.icon} />\n </Button>\n );\n}\n\nfunction Header__Buttons__Item({ button }: { button: HeaderButtonU }) {\n switch (button.functionality) {\n case 'close-widget':\n return <Header__Buttons__Item__CloseWidget button={button} />;\n case 'expand-shrink':\n return <Header__Buttons__Item__ExpandShrink button={button} />;\n case 'resolve-session':\n return <Header__Buttons__Item__ResolveSession button={button} />;\n default:\n isExhaustive(button, Header__Buttons__Item.name);\n return null;\n }\n}\n\nconst defaultCloseWidgetButton = {\n functionality: 'close-widget',\n hideOnLargeScreen: true,\n icon: 'X',\n} satisfies HeaderButtonU;\n\nexport function Header__Buttons() {\n const {\n routerState: { screen },\n } = useWidgetRouter();\n const { headerButtons } = useConfig();\n\n const buttons =\n screen === 'chat'\n ? headerButtons?.chatScreen\n : screen === 'sessions'\n ? headerButtons?.sessionsScreen\n : [];\n\n if (!buttons || buttons.length === 0) {\n return <Header__Buttons__Item button={defaultCloseWidgetButton} />;\n }\n\n return (\n <>\n {buttons.map((button) => (\n <Header__Buttons__Item\n key={`${button.functionality}-${button.icon}`}\n button={button}\n />\n ))}\n </>\n );\n}\n\nexport function Header() {\n const config = useConfig();\n const isCompanion = config.displayMode === 'companion' && !config.inline;\n const {\n routerState: { screen },\n } = useWidgetRouter();\n const dataComponentProp = useGetHeaderDataComponentProp(screen);\n const title = useGetHeaderTitle();\n\n return (\n <header {...dataComponentProp} className=\"py-2 px-4 shrink-0\">\n <div\n className=\"flex items-center gap-2\"\n // Companion's overlaid controls need space after the whole row,\n // including configured actions, rather than just after the title.\n style={{ paddingInlineEnd: isCompanion ? 64 : undefined }}\n >\n <Header__BackToSessionsScreenButton />\n <div\n className={cn(\n 'min-w-0 flex-1 h-8 flex items-center',\n screen === 'sessions' && 'ps-2',\n )}\n >\n <HeaderTitleComponent\n fallback={\n isCompanion && screen !== 'sessions' ? (\n <ConversationTitle />\n ) : (\n <h2 className=\"font-semibold\">{title}</h2>\n )\n }\n />\n </div>\n <Header__Buttons />\n </div>\n <HeaderBottomComponent />\n </header>\n );\n}\n","import React from 'react';\nimport { LoaderIcon } from 'lucide-react';\nimport { cn } from './utils/cn';\n\nexport function LoadingSpinner({ className }: { className?: string }) {\n return <LoaderIcon className={cn('size-4 animate-spin', className)} />;\n}\n","import { useMessages } from '@opencx/widget-react-headless';\nimport { useIsSmallScreen } from './useIsSmallScreen';\nimport { useModes } from '@opencx/widget-react-headless';\n\nexport function useCanvas() {\n const {\n messagesState: { isInitialFetchLoading },\n } = useMessages();\n const { isSmallScreen } = useIsSmallScreen();\n const { activeMode, Component } = useModes();\n\n const isCanvasOpen =\n !isInitialFetchLoading && !isSmallScreen && !!activeMode && !!Component;\n\n return {\n isCanvasOpen,\n };\n}\n","import {\n useWidget,\n type WidgetComponentProps,\n} from '@opencx/widget-react-headless';\nimport React from 'react';\nimport { AgentMessageDefaultComponent } from './custom-components/AgentMessageDefaultComponent';\n\nexport function AgentMessage({\n isFirstInGroup,\n isLastInGroup,\n isAloneInGroup,\n ...props\n}: WidgetComponentProps & {\n isFirstInGroup: boolean;\n isLastInGroup: boolean;\n isAloneInGroup: boolean;\n}) {\n const { componentStore } = useWidget();\n if (props.type !== 'AGENT' && props.type !== 'AI') return null;\n\n // Try to use custom components first\n if (props.data.action) {\n const Component = componentStore.getComponent(props.data.action.name);\n if (Component) {\n return (\n <Component\n {...props}\n id={props.id}\n isFirstInGroup={isFirstInGroup}\n isLastInGroup={isLastInGroup}\n isAloneInGroup={isAloneInGroup}\n />\n );\n }\n }\n\n const Component = componentStore.getComponent(props.component);\n\n if (!Component) {\n // Fallback... just in case\n return (\n <AgentMessageDefaultComponent\n {...props}\n isFirstInGroup={isFirstInGroup}\n isLastInGroup={isLastInGroup}\n isAloneInGroup={isAloneInGroup}\n />\n );\n }\n\n return (\n <Component\n {...props}\n id={props.id}\n isFirstInGroup={isFirstInGroup}\n isLastInGroup={isLastInGroup}\n isAloneInGroup={isAloneInGroup}\n />\n );\n}\n","import { useMessages } from '@opencx/widget-react-headless';\nimport React from 'react';\nimport { dc } from '../utils/data-component.js';\nimport { Button, type ButtonProps } from './lib/button.js';\nimport { cn } from './lib/utils/cn.js';\n\nexport function SuggestedReplyButton({\n suggestion,\n className,\n ...props\n}: ButtonProps & { suggestion: string }) {\n const { sendMessage } = useMessages();\n\n const handleSend = () => {\n const trimmed = suggestion.trim();\n if (!trimmed) return;\n sendMessage({ content: trimmed });\n };\n\n return (\n <Button\n {...dc('chat/suggested_reply_btn')}\n size=\"sm\"\n className={cn('rounded-xl w-fit', className)}\n {...props}\n onClick={handleSend}\n >\n {suggestion}\n </Button>\n );\n}\n","import React from 'react';\nimport { log } from '@opencx/widget-core';\nimport type {\n WidgetAiMessage,\n WidgetAgentMessage,\n WidgetUserMessage,\n} from '@opencx/widget-core';\nimport { useConfig } from '@opencx/widget-react-headless';\nimport { cn } from './lib/utils/cn';\n\nexport function GroupTimestamp({\n messages,\n className,\n containerClassName,\n}: {\n messages: WidgetAiMessage[] | WidgetAgentMessage[] | WidgetUserMessage[];\n className?: string;\n containerClassName?: string;\n}) {\n const { timestamps } = useConfig();\n\n if (!timestamps?.perMessageGroup?.enabled) {\n return null;\n }\n\n const lastMessageTimestamp = messages[messages.length - 1]?.timestamp;\n if (!lastMessageTimestamp) return null;\n\n const formattedTimestamp = (() => {\n try {\n return new Date(lastMessageTimestamp).toLocaleTimeString([], {\n hour: '2-digit',\n minute: '2-digit',\n hour12: true,\n });\n } catch (error) {\n log.error('failed to format timestamp', error);\n return null;\n }\n })();\n if (!formattedTimestamp) return null;\n\n return (\n <div className={containerClassName}>\n <span className={cn('text-xs text-muted-foreground', className)}>\n {formattedTimestamp}\n </span>\n </div>\n );\n}\n","import { log, type WidgetAiMessage } from '@opencx/widget-core';\nimport { useConfig, useDisplayMode } from '@opencx/widget-react-headless';\nimport { CheckIcon, CopyIcon } from 'lucide-react';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { dc } from '../utils/data-component';\nimport { stripCitationRefs } from '../utils/strip-citation-refs';\nimport { Tooltippy } from './lib/tooltip';\nimport { cn } from './lib/utils/cn';\n\n/** How long the button reads \"Copied\" before it offers to copy again. */\nconst COPIED_FEEDBACK_MS = 2000;\n\n/** The reply as text: every message of the group, citation tags removed. */\nexport function replyText(\n messages: readonly Pick<WidgetAiMessage, 'data'>[],\n): string {\n return messages\n .map((message) => stripCitationRefs(message.data.message).trim())\n .filter((text) => text.length > 0)\n .join('\\n\\n');\n}\n\n/**\n * Whether the copy button shows. The companion is the v5-native surface and\n * gets it out of the box; the popover is what a v4 embed upgrades into and\n * must look the same until the embed asks (`messageActions.copy`).\n */\nexport function useShowsCopyAction(): boolean {\n const { messageActions } = useConfig();\n const displayMode = useDisplayMode();\n return messageActions?.copy ?? displayMode === 'companion';\n}\n\n/**\n * The quiet action row under an AI reply group. By default hidden until the\n * group is hovered on pointer devices and always visible on touch screens\n * (there is no hover to reveal it); `messageActions.display: 'always'` keeps\n * it visible everywhere. Skipped when the clipboard is unavailable — an\n * insecure-origin host page — rather than showing a button that fails.\n */\nexport function MessageActions({\n messages,\n}: {\n messages: readonly Pick<WidgetAiMessage, 'data'>[];\n}) {\n const { t } = useTranslation();\n const { messageActions } = useConfig();\n const alwaysVisible = messageActions?.display === 'always';\n const [copied, setCopied] = useState(false);\n const resetRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(\n () => () => {\n if (resetRef.current) clearTimeout(resetRef.current);\n },\n [],\n );\n\n const text = replyText(messages);\n const clipboard =\n typeof navigator !== 'undefined' ? navigator.clipboard : undefined;\n if (!clipboard || text.length === 0) return null;\n\n const copy = () => {\n clipboard.writeText(text).then(\n () => {\n setCopied(true);\n if (resetRef.current) clearTimeout(resetRef.current);\n resetRef.current = setTimeout(\n () => setCopied(false),\n COPIED_FEEDBACK_MS,\n );\n },\n (error: unknown) => log.warn('copying the reply failed', error),\n );\n };\n\n const label = copied ? t('copied') : t('copy_reply');\n return (\n <div\n {...dc('chat/agent_msg_group/actions')}\n className={cn(\n 'flex items-center gap-1 -mt-0.5 transition-opacity duration-150',\n alwaysVisible\n ? 'opacity-100'\n : cn(\n 'opacity-0 group-hover:opacity-100 focus-within:opacity-100',\n '[@media(hover:none)]:opacity-100',\n ),\n )}\n >\n <Tooltippy content={label} side=\"bottom\" align=\"start\">\n <button\n {...dc('chat/agent_msg_group/actions/copy')}\n type=\"button\"\n aria-label={label}\n aria-live=\"polite\"\n onClick={copy}\n className={cn(\n 'flex size-6 items-center justify-center rounded-md',\n 'text-muted-foreground/70 hover:bg-muted hover:text-foreground',\n 'transition-colors active:scale-95',\n )}\n >\n {copied ? (\n <CheckIcon className=\"size-3.5\" />\n ) : (\n <CopyIcon className=\"size-3.5\" />\n )}\n </button>\n </Tooltippy>\n </div>\n );\n}\n","import {\n type WidgetAgentMessage,\n type Agent,\n type WidgetAiMessage,\n} from '@opencx/widget-core';\nimport React from 'react';\nimport { dc } from '../utils/data-component';\nimport { AgentAvatar } from './AgentAvatar';\nimport { AgentMessage } from './AgentMessage';\nimport { Tooltippy } from './lib/tooltip';\nimport { cn } from './lib/utils/cn';\nimport { SuggestedReplyButton } from './SuggestedReplyButton';\nimport { GroupTimestamp } from './GroupTimestamp';\nimport { MessageActions, useShowsCopyAction } from './MessageActions';\n\n/** Reply actions apply to the AI's replies, not a human agent's. */\nfunction isAiMessage(\n message: WidgetAiMessage | WidgetAgentMessage,\n): message is WidgetAiMessage {\n return message.type === 'AI' && message.data.variant !== 'error';\n}\n\nexport function AgentMessageGroup({\n messages,\n agent,\n suggestedReplies,\n actions = true,\n}: {\n messages: WidgetAiMessage[] | WidgetAgentMessage[];\n agent: Agent | undefined;\n suggestedReplies?: string[];\n /**\n * Offer the reply actions (copy) only when its text is final.\n */\n actions?: boolean;\n}) {\n const showsCopy = useShowsCopyAction();\n const aiMessages = messages.filter(isAiMessage);\n return (\n <div\n {...dc('chat/agent_msg_group/root')}\n className={cn('group flex items-end gap-2')}\n >\n <Tooltippy content={agent?.name} side=\"right\" align=\"end\">\n <AgentAvatar\n {...dc('chat/agent_msg_group/root/avatar')}\n agent={agent}\n className=\"hidden\"\n />\n </Tooltippy>\n\n <div className={cn('flex-1 flex flex-col gap-1')}>\n <div\n {...dc('chat/agent_msg_group/avatar_and_msgs/root')}\n className={cn('flex items-end gap-2')}\n >\n <Tooltippy content={agent?.name} side=\"right\" align=\"end\">\n <AgentAvatar\n {...dc('chat/agent_msg_group/avatar_and_msgs/avatar')}\n agent={agent}\n />\n </Tooltippy>\n <div\n {...dc('chat/agent_msg_group/avatar_and_msgs/msgs')}\n className={cn('flex-1 flex flex-col gap-1')}\n >\n {messages.map((message, index, array) => (\n <AgentMessage\n key={message.id}\n isFirstInGroup={index === 0}\n isLastInGroup={index === array.length - 1}\n isAloneInGroup={array.length === 1}\n {...message}\n />\n ))}\n <GroupTimestamp messages={messages} />\n {actions && showsCopy && aiMessages.length > 0 && (\n <MessageActions messages={aiMessages} />\n )}\n </div>\n </div>\n\n {suggestedReplies && suggestedReplies.length > 0 && (\n <div\n {...dc('chat/agent_msg_group/suggestions')}\n className={cn('flex flex-col gap-1 ps-8')}\n >\n {suggestedReplies?.map((suggestion, index) => (\n <SuggestedReplyButton\n key={`${suggestion}-${index}`}\n suggestion={suggestion}\n />\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n","import { useReducedMotion } from 'framer-motion';\nimport React, { useEffect, useState } from 'react';\nimport { cn } from './utils/cn';\n\nconst SNAKE_FRAMES = ['⠏', '⠗', '⠧', '⠷', '⠾', '⠽', '⠻', '⠟'];\n\n/**\n * The braille \"snake\": the widget's indeterminate-progress glyph for agent\n * work (live reasoning, a turn still producing). One static frame under\n * reduced motion.\n */\nexport function BrailleSpinner({ className }: { className?: string }) {\n const shouldReduceMotion = useReducedMotion();\n const [frame, setFrame] = useState(0);\n useEffect(() => {\n if (shouldReduceMotion) return;\n const id = setInterval(\n () => setFrame((f) => (f + 1) % SNAKE_FRAMES.length),\n 80,\n );\n return () => clearInterval(id);\n }, [shouldReduceMotion]);\n return (\n <span className={cn('select-none', className)} aria-hidden>\n {SNAKE_FRAMES[frame]}\n </span>\n );\n}\n","import {\n resolveClientPresentation,\n type WidgetAiMessage,\n} from '@opencx/widget-core';\nimport type {\n SpecDataPart,\n StreamingTurnItem,\n StreamingTurnState,\n} from '@opencx/widget-react-headless';\nimport { applyPresentation, useWidget } from '@opencx/widget-react-headless';\nimport React, { useMemo, useState } from 'react';\nimport { buildSpec, SpecRenderer } from '../json-render';\nimport { dc } from '../utils/data-component';\nimport { AgentMessageGroup } from './AgentMessageGroup';\nimport { BrailleSpinner } from './lib/BrailleSpinner';\nimport { MessageActions, useShowsCopyAction } from './MessageActions';\n\n/**\n * The live streamed turn (streaming engine): rendered in STREAM ORDER —\n * top-to-bottom is time. Narration text renders through the STOCK\n * AgentMessageGroup (identical to persisted messages) at its true position,\n * each run of consecutive activity (reasoning/tools) renders as a collapsible\n * steps group right where it happened, and the turn's streamed json-render\n * spec (`data-spec` patches) renders progressively through `SpecRenderer` at\n * its true position. Unmounts when the stream ends and the canonical rows\n * take over.\n */\nexport function StreamingTurn({\n turn,\n agent,\n timestamp,\n}: {\n turn: StreamingTurnState;\n agent: WidgetAiMessage['agent'];\n /**\n * The turn's persisted timestamp, when it has one — finished turns rendered\n * as the transcript's source for their rows pass the covered row's stamp so\n * a reloaded session shows real times, not the mount time.\n */\n timestamp?: string | null;\n}) {\n // Registered by `Widget` (`agent_chat_steps` / `agent_chat_spec`) and\n // replaceable through the `components` prop.\n const { componentStore, config, widgetCtx } = useWidget();\n const showsCopy = useShowsCopyAction();\n const StepsComponent = componentStore.getComponent('agent_chat_steps');\n const SpecComponent = componentStore.getComponent('agent_chat_spec');\n const LoadingComponent = componentStore.getComponent('loading');\n // Fixed for the life of the turn. A fresh `new Date()` per render would make\n // the group timestamp tick with every streamed token and then jump when the\n // persisted row (stamped once, server-side) takes over at the handoff.\n const [startedAt] = useState(() => new Date().toISOString());\n const groupTimestamp = timestamp ?? startedAt;\n const presentation = resolveClientPresentation(\n widgetCtx.agent.presentation,\n config.presentation,\n );\n const items = applyPresentation(turn.items, presentation);\n const typing =\n turn.active &&\n presentation?.streaming === false &&\n !items.some((item) => item.kind === 'questions');\n\n // Plans live once above the composer; updates do not leave stale checklists\n // in each turn. `questions` also renders NOTHING in the transcript. A pending clarification\n // takes the composer's place instead (`ChatInput`), so the customer answers\n // where they would otherwise type — and a questionnaire the conversation\n // has moved past leaves no dead card behind.\n return (\n <div\n {...dc('chat/streaming_turn/root')}\n className=\"group flex flex-col gap-2\"\n >\n {items.map((item, index) =>\n item.kind === 'text' ? (\n <AgentMessageGroup\n key={`text-${index}`}\n messages={[\n {\n id: `streaming-${index}`,\n type: 'AI',\n component: 'bot_message',\n timestamp: groupTimestamp,\n data: { message: item.text },\n agent,\n },\n ]}\n agent={agent}\n actions={false}\n />\n ) : item.kind === 'spec' ? (\n SpecComponent && (\n <SpecComponent\n key={`spec-${index}`}\n parts={item.parts}\n active={turn.active}\n />\n )\n ) : item.kind === 'questions' ||\n item.kind === 'plan' ||\n item.kind === 'connection' ? null : (\n StepsComponent && (\n <StepsComponent\n key={`steps-${index}`}\n active={turn.active}\n steps={item.steps}\n />\n )\n ),\n )}\n {/* \"Still working\": a turn that has shown something and is still\n streaming keeps a spinner at its tail — a slow tool call or a large\n UI spec can take seconds with no new text, and silence reads as a\n stall. A running steps group carries its own loader, so the tail\n stays quiet while one is the last item. */}\n {typing && LoadingComponent ? (\n <LoadingComponent agent={agent} />\n ) : (\n turn.active &&\n !endsWithRunningSteps(items) && (\n <div\n {...dc('chat/streaming_turn/working')}\n className=\"flex h-5 items-center ps-1\"\n >\n <BrailleSpinner className=\"text-[14px] leading-none text-primary/70\" />\n </div>\n )\n )}\n {!turn.active && showsCopy && (\n <MessageActions\n messages={items.flatMap((item) =>\n item.kind === 'text' ? [{ data: { message: item.text } }] : [],\n )}\n />\n )}\n </div>\n );\n}\n\nfunction endsWithRunningSteps(items: readonly StreamingTurnItem[]): boolean {\n const last = items.at(-1);\n return last?.kind === 'steps' && last.steps.some((step) => !step.done);\n}\n\n/**\n * Assembles the accumulating spec from the turn's `data-spec` patches and\n * renders it through the shared `SpecRenderer` seam (same defenses as the\n * persisted-history path).\n *\n * `active` is the turn's own flag: while it streams, containers whose content\n * has not arrived show a shimmer; once the turn settles they show their\n * ordinary empty state. Optional so an embedder's custom spec component (and\n * a direct render) keeps compiling without it.\n */\nexport type StreamingSpecComponentProps = {\n parts: SpecDataPart[];\n active?: boolean;\n};\n\nexport function StreamingSpec({\n parts,\n active = false,\n}: StreamingSpecComponentProps) {\n // `mapUiPartsToItems` produces a fresh parts array on every stream\n // snapshot, so the reference itself is the change signal.\n const spec = useMemo(() => buildSpec(parts), [parts]);\n return <SpecRenderer spec={spec} active={active} />;\n}\n","import type { StreamingTurnItem } from '@opencx/widget-react-headless';\nimport { AnimatePresence, motion, useReducedMotion } from 'framer-motion';\nimport { Check, ChevronUp, CircleDashed, Loader2 } from 'lucide-react';\nimport React, { useId, useState } from 'react';\nimport { FADE_TRANSITION, QUICK_TWEEN } from '../motion';\nimport { cn } from './lib/utils/cn';\n\ntype PlanStep = Extract<StreamingTurnItem, { kind: 'plan' }>['plan'][number];\n\n/** The assistant supplies plan state; layout and progress indicators belong to the widget. */\nexport function TaskPlan({\n plan,\n active,\n}: {\n plan: PlanStep[];\n active: boolean;\n}) {\n const [expanded, setExpanded] = useState(false);\n const panelId = useId();\n const reduceMotion = useReducedMotion();\n const completed = plan.filter((step) => step.status === 'completed').length;\n const currentStep =\n plan.find((step) => step.status === 'in_progress') ??\n plan.find((step) => step.status === 'pending') ??\n plan[0];\n const circumference = 2 * Math.PI * 8;\n const progressOffset =\n circumference * (1 - (plan.length > 0 ? completed / plan.length : 0));\n\n return (\n <div\n className=\"overflow-hidden rounded-xl border border-primary/10 bg-background shadow-sm\"\n data-task-plan\n >\n <button\n type=\"button\"\n onClick={() => setExpanded((value) => !value)}\n aria-expanded={expanded}\n aria-controls={panelId}\n className=\"flex w-full cursor-pointer items-center gap-3 px-3.5 py-2.5 text-start hover:bg-primary/[0.02] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-primary/40\"\n >\n <svg\n aria-hidden=\"true\"\n className=\"size-5 shrink-0 -rotate-90\"\n viewBox=\"0 0 20 20\"\n >\n <circle\n cx=\"10\"\n cy=\"10\"\n r=\"8\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n className=\"text-primary/10\"\n />\n <motion.circle\n cx=\"10\"\n cy=\"10\"\n r=\"8\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeDasharray={circumference}\n initial={false}\n animate={{ strokeDashoffset: progressOffset }}\n transition={reduceMotion ? { duration: 0 } : FADE_TRANSITION}\n className=\"text-emerald-600 dark:text-emerald-400\"\n />\n </svg>\n <span className=\"min-w-0 flex-1 truncate text-sm text-primary\">\n {currentStep?.step}\n </span>\n <span className=\"shrink-0 text-[0.8125rem] tabular-nums text-primary/50\">\n {completed}/{plan.length}\n </span>\n <motion.span\n aria-hidden=\"true\"\n className=\"flex size-3.5 shrink-0 items-center justify-center text-primary/50\"\n initial={false}\n animate={{ rotate: expanded ? 0 : 180 }}\n transition={reduceMotion ? { duration: 0 } : QUICK_TWEEN}\n >\n <ChevronUp className=\"size-3.5\" />\n </motion.span>\n </button>\n\n <div id={panelId} aria-hidden={!expanded}>\n <AnimatePresence initial={false}>\n {expanded && (\n // Height makes room for the list without scaling its text. Reduced\n // motion keeps only the fade; ordinary updates retain this panel.\n <motion.div\n key=\"plan-steps\"\n initial={{ height: reduceMotion ? 'auto' : 0, opacity: 0 }}\n animate={{ height: 'auto', opacity: 1 }}\n exit={{\n height: reduceMotion ? 'auto' : 0,\n opacity: 0,\n transition: QUICK_TWEEN,\n }}\n transition={reduceMotion ? QUICK_TWEEN : FADE_TRANSITION}\n className=\"overflow-hidden\"\n >\n <ol className=\"max-h-60 overflow-y-auto border-t border-primary/10 px-3.5 py-2\">\n {plan.map((step, index) => (\n <li\n key={index}\n className=\"flex items-start gap-2.5 py-1.5 text-sm\"\n data-plan-status={step.status}\n >\n <span\n aria-hidden=\"true\"\n className={cn(\n 'relative mt-0.5 size-4 shrink-0',\n !active && '[&_.animate-spin]:animate-none',\n )}\n >\n <AnimatePresence initial={false}>\n <motion.span\n key={step.status}\n className=\"absolute inset-0 flex items-center justify-center\"\n initial={{ opacity: 0 }}\n animate={{ opacity: 1 }}\n exit={{ opacity: 0 }}\n transition={QUICK_TWEEN}\n >\n {step.status === 'completed' ? (\n <span className=\"flex size-4 items-center justify-center rounded-full bg-emerald-500/10\">\n <Check className=\"size-2.5 text-emerald-600 dark:text-emerald-400\" />\n </span>\n ) : step.status === 'in_progress' ? (\n active ? (\n <Loader2 className=\"size-4 animate-spin text-primary/60 motion-reduce:animate-none\" />\n ) : (\n <CircleDashed className=\"size-4 text-primary/40\" />\n )\n ) : (\n <span className=\"size-1.5 rounded-full bg-primary/25\" />\n )}\n </motion.span>\n </AnimatePresence>\n </span>\n <span\n className={cn(\n step.status === 'completed'\n ? 'text-primary/50 line-through'\n : step.status === 'in_progress'\n ? 'font-medium text-primary'\n : 'text-primary/60',\n )}\n >\n {step.step}\n </span>\n </li>\n ))}\n </ol>\n </motion.div>\n )}\n </AnimatePresence>\n </div>\n </div>\n );\n}\n","import React from 'react';\nimport { useComponentContext } from '../../hooks/useComponentContext';\n\nexport function SessionResolvedComponent() {\n const props = useComponentContext();\n\n if (props.session?.isOpened || !props.session) return null;\n\n const Component = props.config.customComponents?.onSessionResolved;\n if (!Component) return null;\n\n return <Component {...props} />;\n}\n","import React from 'react';\nimport { useComponentContext } from '../../hooks/useComponentContext';\n\nexport function ChatBottomComponents() {\n const props = useComponentContext();\n const components = props.config.customComponents?.chatBottomComponents;\n\n if (!components) return null;\n\n return (\n <div>\n {components.map(({ key, component: Component }) => (\n <Component key={key} {...props} />\n ))}\n </div>\n );\n}\n","import {\n type WidgetAgentMessage,\n type WidgetAiMessage,\n type WidgetMessageU,\n type WidgetUserMessage,\n} from '@opencx/widget-core';\n\nexport function groupMessagesByType(\n messages: WidgetMessageU[],\n): WidgetMessageU[][] {\n const result: WidgetMessageU[][] = [];\n let currentGroup: WidgetMessageU[] | null = null;\n\n messages.forEach((message) => {\n if (\n // Start a new group if the type changes\n currentGroup?.[0]?.type !== message.type ||\n // Start a new group if the agent changes\n (currentGroup[0]?.type === 'AGENT' &&\n message.type === 'AGENT' &&\n (message.agent?.id !== currentGroup[0].agent?.id ||\n message.agent?.name !== currentGroup[0].agent?.name))\n ) {\n currentGroup = [];\n result.push(currentGroup);\n }\n\n currentGroup.push(message);\n });\n\n return result;\n}\n\nexport function isUserMessageGroup(\n messages: WidgetMessageU[],\n): messages is WidgetUserMessage[] {\n return messages?.[0]?.type === 'USER';\n}\n\nexport function isBotMessageGroup(\n messages: WidgetMessageU[],\n): messages is WidgetAiMessage[] {\n return messages?.[0]?.type === 'AI';\n}\n\nexport function isAgentMessageGroup(\n messages: WidgetMessageU[],\n): messages is WidgetAgentMessage[] {\n return messages?.[0]?.type === 'AGENT';\n}\n","import React from 'react';\nimport { useMessages, useConfig } from '@opencx/widget-react-headless';\nimport { RichText } from '../../components/RichText';\n\nexport function ChatBannerItems() {\n const {\n messagesState: { messages },\n } = useMessages();\n const { chatBannerItems } = useConfig();\n\n if (!chatBannerItems?.length) return null;\n if (\n messages.length > 0 &&\n chatBannerItems.every((item) => !item.persistent)\n ) {\n return null;\n }\n\n return (\n <div className=\"w-full text-center text-xs\">\n {chatBannerItems.map(({ message, persistent }, index) =>\n messages.length > 0 && !persistent ? null : (\n <div key={`${message}-${index}`}>\n <RichText>{message}</RichText>\n </div>\n ),\n )}\n </div>\n );\n}\n","/**\n * The SVG markup is untrusted (org-authored, delivered by the backend). It is\n * therefore never mounted into the DOM — it is only ever rendered through CSS\n * `mask-image`, an image context where scripts cannot execute and external\n * resources cannot load. Validation here is about renderability, not safety.\n */\nconst MAX_SVG_ICON_LENGTH = 10 * 1024;\n\nconst cache = new Map<string, string | null>();\n\n/**\n * Turns a raw `<svg>` string into a `data:` URL for CSS `mask-image`.\n * Returns null when the string is not a parseable standalone SVG document.\n */\nexport function svgToMaskUrl(svg: string): string | null {\n const cached = cache.get(svg);\n if (cached !== undefined) return cached;\n\n const url = toMaskUrl(svg);\n cache.set(svg, url);\n return url;\n}\n\nfunction toMaskUrl(svg: string): string | null {\n const trimmed = svg.trim();\n if (!trimmed || trimmed.length > MAX_SVG_ICON_LENGTH) return null;\n if (typeof DOMParser === 'undefined') return null;\n\n const doc = new DOMParser().parseFromString(trimmed, 'image/svg+xml');\n const root = doc.documentElement;\n if (\n root.localName !== 'svg' ||\n root.namespaceURI !== 'http://www.w3.org/2000/svg' ||\n doc.getElementsByTagName('parsererror').length > 0\n ) {\n return null;\n }\n\n return `data:image/svg+xml,${encodeURIComponent(trimmed)}`;\n}\n","import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from './utils/cn';\n\nconst badgeVariants = cva(\n 'inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-xs font-medium transition-colors',\n {\n variants: {\n variant: {\n default: 'bg-primary text-primary-foreground',\n secondary: 'bg-secondary text-secondary-foreground',\n outline: 'border text-foreground',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n },\n);\n\nexport interface BadgeProps\n extends React.HTMLAttributes<HTMLDivElement>,\n VariantProps<typeof badgeVariants> {}\n\nfunction Badge({ className, variant, ...props }: BadgeProps) {\n return (\n <div className={cn(badgeVariants({ variant }), className)} {...props} />\n );\n}\n\nexport { Badge, badgeVariants };\n","import { type SessionDto } from '@opencx/widget-core';\nimport React from 'react';\nimport { svgToMaskUrl } from '../utils/svg-mask-url';\nimport { Badge } from './lib/badge';\nimport { cn } from './lib/utils/cn';\n\nexport type CustomStatus = NonNullable<SessionDto['customStatus']>;\n\nexport function CustomStatusIcon({\n customStatus,\n className,\n dotClassName,\n}: {\n customStatus: CustomStatus;\n className?: string;\n dotClassName?: string;\n}) {\n const maskUrl = customStatus.icon ? svgToMaskUrl(customStatus.icon) : null;\n const color = customStatus.color || 'currentColor';\n\n if (maskUrl) {\n return (\n <span\n aria-hidden\n className={cn('size-3.5 shrink-0', className)}\n style={{\n backgroundColor: color,\n // Sized by this element's box, not by the svg's own dimensions\n maskImage: `url(\"${maskUrl}\")`,\n maskSize: 'contain',\n maskRepeat: 'no-repeat',\n maskPosition: 'center',\n WebkitMaskImage: `url(\"${maskUrl}\")`,\n WebkitMaskSize: 'contain',\n WebkitMaskRepeat: 'no-repeat',\n WebkitMaskPosition: 'center',\n }}\n />\n );\n }\n\n return (\n <span\n aria-hidden\n className={cn('size-2 shrink-0 rounded-full', dotClassName)}\n style={{ backgroundColor: color }}\n />\n );\n}\n\nexport function CustomStatusBadge({\n customStatus,\n className,\n}: {\n customStatus: CustomStatus;\n className?: string;\n}) {\n return (\n <Badge\n variant=\"secondary\"\n className={cn(\n 'relative isolate overflow-hidden max-w-full text-primary',\n className,\n )}\n title={customStatus.description || undefined}\n style={\n customStatus.color\n ? {\n // A stronger shade of the status color: darker on light themes,\n // lighter on dark themes. Unsupported browsers fall back to text-primary.\n color: `color-mix(in srgb, ${customStatus.color} 55%, hsl(var(--opencx-foreground)))`,\n }\n : undefined\n }\n >\n {customStatus.color && (\n // A soft uniform wash of the status color over the badge background\n <span\n aria-hidden\n className=\"absolute inset-0 -z-10 opacity-20\"\n style={{ backgroundColor: customStatus.color }}\n />\n )}\n <CustomStatusIcon customStatus={customStatus} />\n <span className=\"truncate\">{customStatus.name}</span>\n </Badge>\n );\n}\n","import { useSessions } from '@opencx/widget-react-headless';\nimport { AnimatePresence } from 'framer-motion';\nimport React from 'react';\nimport {\n CustomStatusBadge,\n CustomStatusIcon,\n} from '../../components/CustomStatus';\nimport {\n Dialoger,\n DialogerBody,\n DialogerContent,\n DialogerDescription,\n DialogerHeader,\n DialogerTitle,\n} from '../../components/Dialoger';\nimport { Button } from '../../components/lib/button';\nimport { MotionDiv } from '../../components/lib/MotionDiv';\n\nexport function ChatCustomStatus() {\n const {\n sessionState: { session },\n } = useSessions();\n const customStatus = session?.customStatus;\n\n return (\n <AnimatePresence mode=\"wait\">\n {customStatus && (\n <MotionDiv\n key={customStatus.id}\n className=\"sticky top-2 z-10 self-center max-w-full\"\n snapExit\n >\n <Dialoger\n trigger={\n <Button variant=\"ghost\" size=\"selfless\" className=\"rounded-full\">\n <CustomStatusBadge customStatus={customStatus} />\n </Button>\n }\n >\n <DialogerContent withClose>\n <DialogerHeader>\n <CustomStatusIcon\n customStatus={customStatus}\n className=\"size-8 mx-auto\"\n dotClassName=\"size-3 mx-auto\"\n />\n <DialogerTitle>{customStatus.name}</DialogerTitle>\n </DialogerHeader>\n {customStatus.description && (\n <DialogerBody>\n <DialogerDescription>\n {customStatus.description}\n </DialogerDescription>\n </DialogerBody>\n )}\n </DialogerContent>\n </Dialoger>\n </MotionDiv>\n )}\n </AnimatePresence>\n );\n}\n","import React from 'react';\nimport type { WidgetAiMessage } from '@opencx/widget-core';\nimport { useBot, useMessages, useConfig } from '@opencx/widget-react-headless';\nimport { AgentMessageGroup } from '../../components/AgentMessageGroup';\n\n/**\n * The greeting shown at the top of a fresh conversation.\n * `advancedInitialMessages` wins over the plain `initialMessages` strings;\n * with neither configured, a default greeting shows. Renders nothing once the\n * conversation has real messages.\n */\nexport function InitialMessages() {\n const {\n messagesState: { messages },\n } = useMessages();\n const config = useConfig();\n const bot = useBot();\n const {\n advancedInitialMessages = [],\n initialQuestions,\n initialQuestionsPosition,\n } = config;\n\n if (messages.length > 0) return null;\n\n const texts = advancedInitialMessages.length\n ? advancedInitialMessages.map((m) => m.message)\n : config.initialMessages?.length\n ? config.initialMessages\n : // TODO translate default welcome message\n ['Hello, how can I help you?'];\n\n return (\n <AgentMessageGroup\n messages={texts.map(\n (m, index) =>\n ({\n component: 'bot_message',\n data: { message: m },\n id: `${index}-${m}`,\n type: 'AI',\n timestamp: null,\n }) satisfies WidgetAiMessage,\n )}\n suggestedReplies={\n initialQuestionsPosition === 'below-initial-messages'\n ? initialQuestions\n : undefined\n }\n agent={bot}\n />\n );\n}\n","import React from 'react';\nimport { cn } from '../components/lib/utils/cn';\n\n/**\n * The region's actual pixels with the visitor's note captioned over them —\n * the one presentation a page mark has. Two shapes: a `tile` is the same\n * 48px square a file preview gets, for the composer's attachments row; a\n * `strip` keeps the region's own proportions, for the sent bubble where\n * there is room to read it. Children (the pill's remove button) overlay the\n * picture.\n */\nexport function MarkThumbnail({\n src,\n alt,\n title,\n note,\n shape = 'strip',\n className,\n children,\n ...rest\n}: {\n src: string;\n alt: string;\n title: string;\n note?: string | undefined;\n shape?: 'tile' | 'strip';\n className?: string;\n children?: React.ReactNode;\n} & Record<`data-${string}`, string>) {\n const tile = shape === 'tile';\n return (\n <div\n {...rest}\n className={cn(\n 'relative overflow-hidden bg-background ring-1 ring-border',\n tile ? 'size-12 shrink-0 rounded-2xl' : 'max-w-full rounded-xl',\n className,\n )}\n >\n <img\n src={src}\n alt={alt}\n title={title}\n draggable={false}\n className={cn(\n 'block object-cover object-left-top',\n tile ? 'size-full' : 'h-10 w-auto max-w-40',\n )}\n />\n {note && (\n <div\n className={cn(\n 'absolute inset-x-0 bottom-0 truncate px-1.5 py-0.5',\n 'bg-gradient-to-t from-foreground/70 to-foreground/0',\n 'text-[10px] font-medium leading-tight text-background',\n )}\n >\n {note}\n </div>\n )}\n {children}\n </div>\n );\n}\n","/** Shared privacy boundary for page names, marks and captures. */\nexport const WIDGET_OWNED_SELECTOR = [\n '#opencx-root',\n '[data-opencx-root]',\n '[data-opencx-overlay]',\n] as const;\n\nexport const PAGE_VALUE_SELECTOR =\n 'input,textarea,select,[contenteditable]:not([contenteditable=\"false\"]),[role=\"textbox\"],[role=\"searchbox\"],[role=\"combobox\"]';\n\nconst PRIVATE_SELECTOR = [\n ...WIDGET_OWNED_SELECTOR,\n '[data-opencx-private]',\n '[aria-hidden=\"true\"]',\n '[hidden]',\n 'script',\n 'style',\n 'noscript',\n].join(',');\n\nfunction isSelfPrivate(el: Element): boolean {\n if (el.matches(PRIVATE_SELECTOR)) return true;\n const style = el.ownerDocument.defaultView?.getComputedStyle(el);\n return (\n style?.display === 'none' ||\n style?.visibility === 'hidden' ||\n style?.visibility === 'collapse' ||\n style?.opacity === '0'\n );\n}\n\nexport function isPageElementPrivate(el: Element): boolean {\n for (\n let current: Element | null = el;\n current;\n current = current.parentElement\n ) {\n if (isSelfPrivate(current)) return true;\n }\n return false;\n}\n\n/** Read from live nodes so CSS and private ancestors/referenced labels apply. */\nexport function safePageText(el: Element): string {\n if (isPageElementPrivate(el) || el.closest(PAGE_VALUE_SELECTOR)) return '';\n const chunks: string[] = [];\n const visit = (node: Node) => {\n if (node instanceof Element) {\n // Ancestors were checked on entry; private subtrees are never visited.\n // Each style is read once, with no cache surviving this live traversal.\n if (\n (node !== el && isSelfPrivate(node)) ||\n node.matches(PAGE_VALUE_SELECTOR)\n )\n return;\n const block =\n /^(ADDRESS|ARTICLE|ASIDE|BLOCKQUOTE|BR|DD|DETAILS|DIV|DL|DT|FIELDSET|FIGCAPTION|FIGURE|FOOTER|FORM|H[1-6]|HEADER|HR|LI|MAIN|NAV|OL|P|PRE|SECTION|SUMMARY|TABLE|TD|TH|TR|UL)$/.test(\n node.tagName,\n );\n if (block) chunks.push(' ');\n node.childNodes.forEach(visit);\n if (block) chunks.push(' ');\n } else if (node.nodeType === Node.TEXT_NODE)\n chunks.push(node.textContent ?? '');\n };\n visit(el);\n return chunks.join('').replace(/\\s+/g, ' ').trim();\n}\n\n/** URL metadata never includes credentials, query parameters or fragments. */\nexport function safePageUrl(value: string): string {\n try {\n const url = new URL(value, window.location.href);\n return url.protocol === 'http:' || url.protocol === 'https:'\n ? `${url.origin}${url.pathname}`\n : '';\n } catch {\n return '';\n }\n}\n\n/** Form values and opaque embedded pixels cannot be reliably redacted. */\nexport function canCapturePageElement(el: Element): boolean {\n return (\n el.getRootNode() === document &&\n !isPageElementPrivate(el) &&\n !el.closest(PAGE_VALUE_SELECTOR) &&\n !el.matches('canvas,iframe,video,object,embed') &&\n !Array.from(el.querySelectorAll('*')).some(\n (node) =>\n isPageElementPrivate(node) ||\n node.matches(`${PAGE_VALUE_SELECTOR},canvas,iframe,video,object,embed`),\n )\n );\n}\n","import { toJpeg } from 'html-to-image';\nimport { canCapturePageElement } from '../page-privacy';\n\n/**\n * Pill thumbnails for marked regions: the region's focus element is\n * rasterized (html-to-image, foreignObject + canvas) so the composer pill can\n * show the actual pixels the visitor marked instead of a tag name. The base64\n * rides a WeakMap beside the annotation, exactly like the ink registry, and is\n * NEVER serialized into the send payload (a screenshot in `clientContext`\n * would bloat every send). What outlives the composer is the UPLOAD: the\n * thumbnail goes up as a message file only when the visitor sends, and its URL is\n * written onto the mark (`snapshotUrl`) so the sent bubble after a reload and\n * the inbox show the same picture the composer did.\n *\n * The widget's own overlays (marks, editor chrome) are SIBLINGS or portals,\n * never descendants of host elements — and widget-owned nodes are filtered\n * out of the clone as a second guard — so a snapshot never photographs the\n * widget itself.\n */\n\n/** Longest thumbnail edge, in CSS px — pills render at ~2.5rem tall. */\nconst MAX_EDGE_PX = 480;\n/** A snapshot that can't land quickly shouldn't hold the pill hostage. */\nconst CAPTURE_TIMEOUT_MS = 3000;\n\nconst thumbnails = new WeakMap<object, Promise<string | null>>();\nconst captureElements = new WeakMap<object, HTMLElement>();\n\n/**\n * Rasterize an element to a JPEG data URL, or null when it can't be done\n * (cross-origin resources, zero-size rects, timeouts). Never throws — the\n * pill falls back to its text form on null.\n */\nasync function captureThumbnail(el: HTMLElement): Promise<string | null> {\n if (!canCapturePageElement(el)) return null;\n const rect = el.getBoundingClientRect();\n if (rect.width < 1 || rect.height < 1) return null;\n\n // Scale so the longest edge lands at thumbnail size: big regions shrink,\n // small controls keep (at most) retina density.\n const pixelRatio = Math.min(\n 2,\n Math.max(0.5, MAX_EDGE_PX / Math.max(rect.width, rect.height)),\n );\n\n const capture = toJpeg(el, {\n quality: 0.85,\n pixelRatio,\n backgroundColor: '#ffffff',\n // Never let the widget photograph itself (ink SVGs, portaled chrome, the\n // embed root inside a picked ancestor).\n filter: (node) => !(node instanceof Element) || canCapturePageElement(node),\n });\n const timeout = new Promise<null>((resolve) =>\n setTimeout(() => resolve(null), CAPTURE_TIMEOUT_MS),\n );\n try {\n return await Promise.race([capture, timeout]);\n } catch {\n return null;\n }\n}\n\n/** Kick off (and register) a snapshot keyed by its annotation object. */\nexport function beginThumbnail(key: object, el: HTMLElement) {\n captureElements.set(key, el);\n thumbnails.set(key, captureThumbnail(el));\n}\n\nconst snapshotUploads = new WeakMap<object, Promise<string | null>>();\n\n/**\n * Upload the mark's thumbnail once it settles and write the resulting URL\n * onto the mark. Registered like the thumbnail so a send can wait for an\n * upload still in flight (`awaitSnapshotUrl`). A failed capture or upload\n * resolves null and leaves the mark without a snapshot — never throws.\n */\nexport function beginSnapshotUpload(\n mark: { snapshotUrl?: string },\n upload: (file: File) => Promise<string | null>,\n) {\n if (snapshotUploads.has(mark)) return;\n const thumbnail = thumbnails.get(mark);\n if (!thumbnail) return;\n const uploaded = thumbnail\n .then((dataUrl) => {\n const element = captureElements.get(mark);\n if (!element?.isConnected || !canCapturePageElement(element)) return null;\n const file = dataUrl ? fileFromDataUrl(dataUrl, 'page-mark.jpg') : null;\n return file ? upload(file) : null;\n })\n .catch(() => null)\n .then((url) => {\n const element = captureElements.get(mark);\n if (!element?.isConnected || !canCapturePageElement(element)) return null;\n if (url) mark.snapshotUrl = url;\n return url;\n });\n snapshotUploads.set(mark, uploaded);\n}\n\n/**\n * The mark's snapshot URL, waiting at most `maxWaitMs` for an in-flight\n * upload. A send must not hang on a slow upload: past the cap the mark goes\n * out without its picture (text fallback), and the URL, if it lands later,\n * is simply never persisted.\n */\nexport async function awaitSnapshotUrl(\n mark: { snapshotUrl?: string },\n maxWaitMs: number,\n): Promise<string | null> {\n if (mark.snapshotUrl) return mark.snapshotUrl;\n const pending = snapshotUploads.get(mark);\n if (!pending) return null;\n const timeout = new Promise<null>((resolve) =>\n setTimeout(() => resolve(null), maxWaitMs),\n );\n return Promise.race([pending, timeout]);\n}\n\n/** A `data:` URL (as `toJpeg` returns) as an uploadable File. */\nexport function fileFromDataUrl(dataUrl: string, name: string): File | null {\n const match = /^data:([^;,]+);base64,([\\s\\S]*)$/.exec(dataUrl);\n if (!match) return null;\n const [, type, base64] = match;\n if (!type || base64 === undefined) return null;\n try {\n const binary = atob(base64);\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return new File([bytes], name, { type });\n } catch {\n return null;\n }\n}\n\n/** The key's in-flight/settled snapshot, if one was started. */\nexport function getThumbnail(key: object): Promise<string | null> | undefined {\n return thumbnails.get(key);\n}\n\n/** Preserve a validated mark's local preview without sharing mutable metadata. */\nexport function copyThumbnail(source: object, target: object) {\n const thumbnail = thumbnails.get(source);\n if (thumbnail) thumbnails.set(target, thumbnail);\n}\n","import { useEffect, useState } from 'react';\nimport { getThumbnail } from './mark-thumbnail';\n\n/**\n * The snapshot taken for a mark, once it lands. Keyed by the mark OBJECT, so\n * the composer pill and the sent bubble — which carries the same reference —\n * resolve the very same capture. Null until (or unless) it settles; every\n * caller has a text form to fall back on.\n */\nexport function useMarkThumbnail(mark: object | undefined): string | null {\n const [thumb, setThumb] = useState<string | null>(null);\n\n useEffect(() => {\n setThumb(null);\n if (!mark) return;\n let cancelled = false;\n void getThumbnail(mark)?.then((dataUrl) => {\n if (!cancelled && dataUrl) setThumb(dataUrl);\n });\n return () => {\n cancelled = true;\n };\n }, [mark]);\n\n return thumb;\n}\n","import type { MarkedElementRef } from '@opencx/widget-core';\nimport { PenLineIcon } from 'lucide-react';\nimport React from 'react';\nimport { cn } from '../components/lib/utils/cn';\nimport { MarkThumbnail } from './MarkThumbnail';\nimport { useMarkThumbnail } from './useMarkThumbnail';\n\n/**\n * A page mark on the SENT user bubble — the composer pill's presentation\n * without its remove affordance: the region's actual pixels, the note\n * captioned over them, and the element name only as the fallback when no\n * snapshot exists. The message carries the mark object itself, so the\n * thumbnail taken in the composer survives the send instead of collapsing\n * back into a bare tag name; after a reload the uploaded snapshot's URL takes\n * its place.\n */\nexport function SentMarkChip({ element }: { element: MarkedElementRef }) {\n // The composer's in-memory capture while it exists, else the persisted\n // upload — a reload has only the latter.\n const thumb = useMarkThumbnail(element.mark) ?? element.snapshotUrl ?? null;\n const label = element.note ?? element.name;\n\n if (thumb) {\n return (\n <MarkThumbnail\n src={thumb}\n alt={label}\n title={element.name}\n note={element.note}\n />\n );\n }\n\n return (\n <span\n className={cn(\n 'inline-flex items-center gap-1.5 max-w-48',\n 'rounded-full py-1 ps-2 pe-2.5',\n 'bg-background ring-1 ring-border',\n 'text-xs text-foreground',\n )}\n title={element.name}\n >\n <PenLineIcon className=\"size-3 shrink-0 text-primary\" />\n <span className=\"truncate\">{label}</span>\n </span>\n );\n}\n","import { log, type WidgetMention } from '@opencx/widget-core';\nimport {\n useComposerDraft,\n useConfig,\n useWidget,\n} from '@opencx/widget-react-headless';\nimport {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type RefObject,\n} from 'react';\n\n/** How long the picker waits after a keystroke before asking the host. */\nconst SEARCH_DEBOUNCE_MS = 150;\n/** The picker holds this many at most; the host ranks, the widget trims. */\nconst MAX_MENTION_RESULTS = 40;\n/** A group shows this many before its \"See N more\" row. */\nconst GROUP_PREVIEW_COUNT = 3;\n\n/** One type's slice of the results, as the picker lists it. */\nexport type MentionGroup = {\n type: string;\n /** The rows shown: every item once expanded, else the first few. */\n items: WidgetMention[];\n /** How many the \"See N more\" row stands for; 0 hides the row. */\n hidden: number;\n};\n\n/**\n * Results in the order the picker lists them: grouped by type (in first-seen\n * order), each group cut to its preview unless expanded. The flat `visible`\n * list is the same rows top to bottom, so keyboard ↑/↓ and the highlighted\n * index walk exactly what is on screen.\n */\nfunction groupMentions(\n results: readonly WidgetMention[],\n expanded: ReadonlySet<string>,\n): { groups: MentionGroup[]; visible: WidgetMention[] } {\n const byType = new Map<string, WidgetMention[]>();\n for (const item of results) {\n const list = byType.get(item.type);\n if (list) list.push(item);\n else byType.set(item.type, [item]);\n }\n const groups: MentionGroup[] = [];\n const visible: WidgetMention[] = [];\n for (const [type, all] of Array.from(byType)) {\n const items = expanded.has(type) ? all : all.slice(0, GROUP_PREVIEW_COUNT);\n groups.push({ type, items, hidden: all.length - items.length });\n visible.push(...items);\n }\n return { groups, visible };\n}\n\n/**\n * The `@query` the caret is in, if any: an `@` at the start of the text or\n * after whitespace, then anything but whitespace up to the caret. Typing a\n * space or moving the caret out of it closes the picker.\n */\nexport function activeMentionQuery(\n text: string,\n caret: number,\n): { start: number; query: string } | null {\n const before = text.slice(0, caret);\n const match = /(?:^|\\s)@(\\S*)$/.exec(before);\n if (!match) return null;\n return { start: caret - match[1]!.length - 1, query: match[1]! };\n}\n\n/**\n * The widget's own filter for a fixed list: title matches first (prefix\n * before substring), description matches after; an empty query lists all.\n */\nexport function filterMentions(\n items: readonly WidgetMention[],\n query: string,\n): WidgetMention[] {\n const needle = query.trim().toLowerCase();\n if (!needle) return [...items];\n const rank = (item: WidgetMention): number => {\n const title = item.title.toLowerCase();\n if (title.startsWith(needle)) return 0;\n if (title.includes(needle)) return 1;\n if (item.description?.toLowerCase().includes(needle)) return 2;\n return -1;\n };\n return items\n .map((item, index) => ({ item, index, rank: rank(item) }))\n .filter((entry) => entry.rank >= 0)\n .sort((a, b) => a.rank - b.rank || a.index - b.index)\n .map((entry) => entry.item);\n}\n\n/** The text a picked mention occupies in the composer. */\nexport const mentionText = (item: WidgetMention): string => `@${item.title}`;\n\n/** Every `[start, end)` span a picked mention occupies in the text. */\nfunction mentionRanges(\n text: string,\n picked: readonly WidgetMention[],\n): { start: number; end: number }[] {\n const ranges: { start: number; end: number }[] = [];\n for (const item of picked) {\n const token = mentionText(item);\n let from = 0;\n for (;;) {\n const at = text.indexOf(token, from);\n if (at === -1) break;\n ranges.push({ start: at, end: at + token.length });\n from = at + token.length;\n }\n }\n return ranges;\n}\n\n/**\n * @-mentions for the composer: watches the text for an `@query` at the caret,\n * asks the host's `config.mentions.search`, and keeps the list of picked\n * items in step with the text — a picked item lives in the text as its\n * `@Title` (highlighted there), and deleting that text drops the item.\n * Nothing happens unless the host configured `mentions` and the org's\n * page-context feature is on.\n */\nexport function useMentions({\n text,\n setText,\n inputRef,\n}: {\n text: string;\n setText: (next: string) => void;\n inputRef: RefObject<HTMLTextAreaElement | null>;\n}) {\n const { mentions: mentionsConfig } = useConfig();\n const { widgetCtx } = useWidget();\n // One search either way: a fixed list is filtered here, a search function\n // is the host's own lookup.\n const items = mentionsConfig?.items;\n const hostSearch = mentionsConfig?.search;\n const search = useMemo(() => {\n if (hostSearch) return hostSearch;\n if (items) return (query: string) => filterMentions(items, query);\n return undefined;\n }, [hostSearch, items]);\n const enabled = Boolean(search) && widgetCtx.features.pageContext;\n\n const { mentions: picked, setMentions: setPicked } = useComposerDraft();\n const [active, setActive] = useState<{ start: number; query: string } | null>(\n null,\n );\n const [results, setResults] = useState<WidgetMention[]>([]);\n const [expanded, setExpanded] = useState<ReadonlySet<string>>(\n () => new Set(),\n );\n const [highlighted, setHighlighted] = useState(0);\n const [searching, setSearching] = useState(false);\n const { groups, visible } = useMemo(\n () => groupMentions(results, expanded),\n [expanded, results],\n );\n\n // Picked items whose `@Title` the visitor deleted from the text are gone.\n useEffect(() => {\n setPicked((current) => {\n const kept = current.filter((item) => text.includes(mentionText(item)));\n return kept.length === current.length ? current : kept;\n });\n }, [text, setPicked]);\n\n // Re-read the caret on every text change (typing moves it) and on caret\n // moves without typing (arrow keys, clicks), through `onCaretMove`.\n const readActive = useCallback(\n (direction: 'forward' | 'backward' | 'nearest' = 'nearest') => {\n if (!enabled) return;\n const input = inputRef.current;\n let caret = input?.selectionStart ?? text.length;\n // A mention is one unit: a caret that lands inside its `@Title` (a\n // click, an arrow key) is moved to the edge it came from — past the\n // whole token going forward, before it going back, the nearer edge\n // for a click — so it can never be edited from the middle.\n if (input && input.selectionStart === input.selectionEnd) {\n const inside = mentionRanges(text, picked).find(\n (range) => caret > range.start && caret < range.end,\n );\n if (inside) {\n caret =\n direction === 'forward'\n ? inside.end\n : direction === 'backward'\n ? inside.start\n : caret - inside.start < inside.end - caret\n ? inside.start\n : inside.end;\n input.setSelectionRange(caret, caret);\n }\n }\n const found = activeMentionQuery(text, caret);\n // The caret sitting right after a picked `@Title` reads as a query for\n // that title; it is not one.\n const next =\n found &&\n picked.some((item) => text.startsWith(mentionText(item), found.start))\n ? null\n : found;\n setActive((current) =>\n current?.start === next?.start && current?.query === next?.query\n ? current\n : next,\n );\n },\n [enabled, inputRef, picked, text],\n );\n useEffect(() => readActive(), [readActive]);\n\n // Debounced host search for the active query; stale answers are dropped.\n const requestRef = useRef(0);\n useEffect(() => {\n if (!active || !search) {\n setResults([]);\n setSearching(false);\n return;\n }\n const request = ++requestRef.current;\n setSearching(true);\n const timer = setTimeout(() => {\n Promise.resolve()\n .then(() => search(active.query))\n .then(\n (items) => {\n if (request !== requestRef.current) return;\n setResults(items.slice(0, MAX_MENTION_RESULTS));\n setExpanded(new Set());\n setHighlighted(0);\n setSearching(false);\n },\n (error: unknown) => {\n if (request !== requestRef.current) return;\n log.warn('mentions search failed', error);\n setResults([]);\n setSearching(false);\n },\n );\n }, SEARCH_DEBOUNCE_MS);\n return () => clearTimeout(timer);\n }, [active, search]);\n\n const close = useCallback(() => {\n requestRef.current += 1;\n setActive(null);\n setResults([]);\n setSearching(false);\n }, []);\n\n /** Replace the `@query` at the caret with `@Title ` and remember the item. */\n const pick = useCallback(\n (item: WidgetMention) => {\n if (!active) return;\n const end = active.start + 1 + active.query.length;\n const inserted = `${mentionText(item)} `;\n const next = text.slice(0, active.start) + inserted + text.slice(end);\n setText(next);\n setPicked((current) =>\n current.some((p) => p.type === item.type && p.id === item.id)\n ? current\n : [...current, item],\n );\n close();\n const caret = active.start + inserted.length;\n requestAnimationFrame(() => {\n const input = inputRef.current;\n if (!input) return;\n input.focus();\n input.setSelectionRange(caret, caret);\n });\n },\n [active, close, inputRef, setText, setPicked, text],\n );\n\n /** Show every item of one type; the highlight stays where it was. */\n const expandGroup = useCallback((type: string) => {\n setExpanded((current) => new Set(current).add(type));\n }, []);\n\n const isOpen = enabled && active !== null;\n\n /**\n * Keys the mentions own: Backspace/Delete against a mention's edge removes\n * the whole `@Title`, and while the menu is open ↑/↓/Enter/Tab/Escape\n * drive it. Returns true when it handled the key.\n */\n const onKeyDown = useCallback(\n (event: { key: string; preventDefault: () => void }): boolean => {\n const input = inputRef.current;\n if (\n enabled &&\n input &&\n input.selectionStart === input.selectionEnd &&\n (event.key === 'Backspace' || event.key === 'Delete')\n ) {\n const caret = input.selectionStart;\n const hit = mentionRanges(text, picked).find((range) =>\n event.key === 'Backspace'\n ? range.end === caret\n : range.start === caret,\n );\n if (hit) {\n event.preventDefault();\n // Take the space the pick added after the token with it.\n const end = text[hit.end] === ' ' ? hit.end + 1 : hit.end;\n setText(text.slice(0, hit.start) + text.slice(end));\n requestAnimationFrame(() =>\n input.setSelectionRange(hit.start, hit.start),\n );\n return true;\n }\n }\n if (!isOpen) return false;\n if (event.key === 'Escape') {\n event.preventDefault();\n close();\n return true;\n }\n if (visible.length === 0) return false;\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n setHighlighted((i) => (i + 1) % visible.length);\n return true;\n }\n if (event.key === 'ArrowUp') {\n event.preventDefault();\n setHighlighted((i) => (i - 1 + visible.length) % visible.length);\n return true;\n }\n if (event.key === 'Enter' || event.key === 'Tab') {\n event.preventDefault();\n const item = visible[highlighted];\n if (item) pick(item);\n return true;\n }\n return false;\n },\n [\n close,\n enabled,\n highlighted,\n inputRef,\n isOpen,\n pick,\n picked,\n setText,\n text,\n visible,\n ],\n );\n\n /** Cleared after a send is accepted. */\n const reset = useCallback(() => {\n setPicked([]);\n close();\n }, [close, setPicked]);\n\n return useMemo(\n () => ({\n picked,\n isOpen,\n /** Index of the `@` the open menu belongs to; the menu sits beside it. */\n anchorIndex: active?.start ?? null,\n /** Show the highlighted item's description beside the menu. */\n preview: mentionsConfig?.preview !== false,\n groups,\n visible,\n expandGroup,\n searching,\n highlighted,\n setHighlighted,\n pick,\n onKeyDown,\n onCaretMove: readActive,\n reset,\n }),\n [\n picked,\n isOpen,\n active,\n mentionsConfig?.preview,\n groups,\n visible,\n expandGroup,\n searching,\n highlighted,\n pick,\n onKeyDown,\n readActive,\n reset,\n ],\n );\n}\n","import type { WidgetMention } from '@opencx/widget-core';\nimport React from 'react';\nimport { cn } from '../../components/lib/utils/cn';\nimport { dc } from '../../utils/data-component';\nimport { mentionText } from './useMentions';\n\n/**\n * Text with its `@Title` mentions highlighted in place — the composer's\n * mirror layer and the sent bubble both read the same way, so a mention\n * looks like one thing from typing to transcript. Longer titles are matched\n * first so `@Ann` never claims the front of `@Anna Lee`. Text without\n * mentions comes back as-is.\n */\nexport function MentionText({\n text,\n mentions,\n tokenClassName,\n}: {\n text: string;\n mentions: readonly WidgetMention[] | undefined;\n /** The token's look on this surface (ink on the composer, on primary in the bubble). */\n tokenClassName: string;\n}) {\n if (!mentions || mentions.length === 0) return <>{text}</>;\n const tokens = Array.from(new Set(mentions.map(mentionText))).sort(\n (a, b) => b.length - a.length,\n );\n const nodes: React.ReactNode[] = [];\n let rest = text;\n let key = 0;\n while (rest.length > 0) {\n let at = -1;\n let hit = '';\n for (const token of tokens) {\n const index = rest.indexOf(token);\n if (index !== -1 && (at === -1 || index < at)) {\n at = index;\n hit = token;\n }\n }\n if (at === -1) {\n nodes.push(rest);\n break;\n }\n if (at > 0) nodes.push(rest.slice(0, at));\n nodes.push(\n <span\n {...dc('chat/mention')}\n key={key++}\n className={cn('rounded-sm px-0.5 -mx-0.5', tokenClassName)}\n >\n {hit}\n </span>,\n );\n rest = rest.slice(at + hit.length);\n }\n return <>{nodes}</>;\n}\n","import type { WidgetUserMessage } from '@opencx/widget-core';\nimport React from 'react';\nimport { SentMarkChip } from '../page-marks/SentMarkChip';\nimport { MentionText } from '../screens/chat/MentionText';\nimport { dc } from '../utils/data-component';\nimport { AttachmentPreview } from './AttachmentPreview';\nimport { cn } from './lib/utils/cn';\n\nexport function UserMessage({\n message,\n isFirstInGroup,\n isLastInGroup,\n isAloneInGroup,\n}: {\n message: WidgetUserMessage;\n isFirstInGroup: boolean;\n isLastInGroup: boolean;\n isAloneInGroup: boolean;\n}) {\n return (\n <div\n {...dc('chat/user_msg/root')}\n data-message-id={message.id}\n className=\"w-5/6 flex flex-col items-end gap-1\"\n >\n {message.markedElements && message.markedElements.length > 0 && (\n <div\n {...dc('chat/user_msg/marked_elements')}\n className=\"w-full flex gap-1 flex-wrap justify-end\"\n >\n {message.markedElements.map((el, i) => (\n <SentMarkChip key={`${el.name}-${i}`} element={el} />\n ))}\n </div>\n )}\n {message.attachments && message.attachments.length > 0 && (\n <div className=\"w-full flex gap-1 flex-wrap justify-end\">\n {message.attachments?.map((attachment) => (\n <AttachmentPreview attachment={attachment} key={attachment.id} />\n ))}\n </div>\n )}\n {message.content.length > 0 && (\n <div\n {...dc('chat/user_msg/msg')}\n // Expose these data attributes for external styling customization\n data-first={isFirstInGroup}\n data-last={isLastInGroup}\n data-alone={isAloneInGroup}\n data-pending={message.pending === true}\n className={cn(\n 'transition-all',\n 'w-fit py-3 px-4 rounded-3xl text-sm',\n 'bg-primary text-primary-foreground',\n // Pending: sent but its answer hasn't started streaming yet.\n message.pending && 'opacity-60',\n 'break-words [word-break:break-word]', // `[word-break:break-word]` is deprecated but works in the browser, while `break-words` which is `[overflow-wrap: break-word]` does not work\n 'whitespace-pre-wrap',\n\n // We're using the booleans directly here, not the data attributes, to make any external styling more specific than this\n isFirstInGroup && !isAloneInGroup && 'rounded-br-md',\n isLastInGroup && !isAloneInGroup && 'rounded-tr-md',\n !isFirstInGroup &&\n !isLastInGroup &&\n !isAloneInGroup &&\n 'rounded-r-md',\n )}\n >\n <MentionText\n text={message.content}\n mentions={message.mentions}\n tokenClassName=\"bg-primary-foreground/20 font-medium\"\n />\n </div>\n )}\n </div>\n );\n}\n","import type { WidgetUserMessage } from '@opencx/widget-core';\nimport React from 'react';\nimport { dc } from '../utils/data-component';\nimport { cn } from './lib/utils/cn';\nimport { UserMessage } from './UserMessage';\nimport { GroupTimestamp } from './GroupTimestamp';\n\nexport function UserMessageGroup({\n messages,\n}: {\n messages: WidgetUserMessage[];\n}) {\n return (\n <div\n {...dc('chat/user_msg_group/root')}\n className={cn('group', 'flex flex-col gap-1 justify-end items-end')}\n >\n {messages.map((message, index, array) => (\n <UserMessage\n key={message.id}\n message={message}\n isFirstInGroup={index === 0}\n isLastInGroup={index === array.length - 1}\n isAloneInGroup={array.length === 1}\n />\n ))}\n <GroupTimestamp messages={messages} containerClassName=\"ms-auto\" />\n </div>\n );\n}\n","import type { WidgetMessageU } from '@opencx/widget-core';\nimport { useBot, useConfig } from '@opencx/widget-react-headless';\nimport React from 'react';\nimport { AgentMessageGroup } from '../../components/AgentMessageGroup';\nimport { UserMessageGroup } from '../../components/UserMessageGroup';\nimport {\n isAgentMessageGroup,\n isBotMessageGroup,\n isUserMessageGroup,\n} from '../../utils/group-messages-by-type';\n\n/**\n * Renders grouped transcript messages — the rule shared by the bot-chat and\n * agent-chat lists. Bot (AI) groups carry the configured bot identity\n * (server-resolved agent branding wins); human-agent groups prefer the\n * server-provided sender, patched by the `humanAgent` config override.\n */\nexport function MessageGroups({\n groups,\n pendingReply = false,\n}: {\n groups: WidgetMessageU[][];\n /** The latest reply is still being prepared, including between polled updates. */\n pendingReply?: boolean;\n}) {\n const { humanAgent } = useConfig();\n const bot = useBot();\n\n return (\n <>\n {groups.map((group, index) => {\n const firstIdInGroup = group[0]?.id;\n if (!firstIdInGroup) return null;\n\n if (isUserMessageGroup(group)) {\n return <UserMessageGroup key={firstIdInGroup} messages={group} />;\n }\n\n if (isBotMessageGroup(group)) {\n return (\n <AgentMessageGroup\n key={firstIdInGroup}\n messages={group}\n agent={bot}\n actions={!pendingReply || index !== groups.length - 1}\n />\n );\n }\n\n if (isAgentMessageGroup(group)) {\n const agent = group[0]?.agent;\n return (\n <AgentMessageGroup\n key={firstIdInGroup}\n messages={group}\n agent={\n agent\n ? {\n ...agent,\n name: humanAgent?.name || agent.name || '',\n avatarUrl:\n humanAgent?.avatarUrl || agent.avatarUrl || null,\n }\n : humanAgent\n ? {\n isAi: false,\n id: null,\n name: humanAgent.name || '',\n avatarUrl: humanAgent.avatarUrl || null,\n }\n : undefined\n }\n />\n );\n }\n\n return null;\n })}\n </>\n );\n}\n","/** Distance from the bottom (px) within which the stream keeps auto-following\n * and the scroll-to-bottom button stays hidden. */\nexport const SCROLL_NEAR_BOTTOM_PX = 150;\n\n/** The subset of a scroll container's geometry the follow decision reads. */\nexport type ScrollMetrics = {\n scrollHeight: number;\n scrollTop: number;\n clientHeight: number;\n};\n\n/**\n * True when the viewport is within `threshold` px of the bottom — i.e. the\n * user is effectively pinned, so the stream should keep following and the\n * scroll-to-bottom button stays hidden. A container that can't scroll\n * (content fits: `scrollHeight <= clientHeight`) is always \"near bottom\".\n */\nexport function isNearBottom(\n { scrollHeight, scrollTop, clientHeight }: ScrollMetrics,\n threshold: number = SCROLL_NEAR_BOTTOM_PX,\n): boolean {\n return scrollHeight - scrollTop - clientHeight < threshold;\n}\n","import {\n type DependencyList,\n type RefObject,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport { isNearBottom } from './scroll-follow.utils';\n\nexport type StreamFollow = {\n /** Attach to the scroll container. */\n containerRef: RefObject<HTMLDivElement | null>;\n /** Attach to the container's `onScroll`. */\n handleScroll: () => void;\n /** True while the user has scrolled away from the bottom — drives the\n * scroll-to-bottom button's visibility. */\n showScrollDown: boolean;\n /** Smooth-scroll to the bottom and re-arm auto-follow (button onClick). */\n scrollToBottom: () => void;\n};\n\n/**\n * Streaming scroll behavior: the container follows the bottom as content\n * streams in ONLY while the user is pinned near it. The moment they scroll up,\n * `autoFollowRef` releases so new tokens no longer yank the viewport down and\n * the scroll-to-bottom button surfaces instead.\n *\n * `followKey` is the dependency list whose changes represent \"new content\"\n * (e.g. `[messages, liveItems]`); the follow effect re-runs on each change.\n * Content that grows WITHOUT a `followKey` change — a lazily loaded chart\n * chunk resolving, an image decoding, a reopened session's historical turn\n * source landing from its own fetch — is followed through a `ResizeObserver`\n * on the container's rows (below), never through timers.\n */\nexport function useStreamFollow(followKey: DependencyList): StreamFollow {\n const containerRef = useRef<HTMLDivElement | null>(null);\n // Intent flag, not a derived position read: a sudden content jump can push\n // the layout past the threshold in a single render even though the user\n // never scrolled. Driven off real scroll events only, it stays armed in\n // that case.\n const autoFollowRef = useRef(true);\n const [showScrollDown, setShowScrollDown] = useState(false);\n const observerRef = useRef<ResizeObserver | null>(null);\n // One Set for the hook's life: which rows the observer currently watches.\n const [observedRows] = useState(() => new Set<Element>());\n\n const handleScroll = useCallback(() => {\n const el = containerRef.current;\n const nearBottom = el ? isNearBottom(el) : true;\n autoFollowRef.current = nearBottom;\n setShowScrollDown(!nearBottom);\n }, []);\n\n const scrollToBottom = useCallback(() => {\n const el = containerRef.current;\n if (!el) return;\n el.scrollTo({ top: el.scrollHeight, behavior: 'smooth' });\n autoFollowRef.current = true;\n setShowScrollDown(false);\n }, []);\n\n useEffect(() => {\n if (!autoFollowRef.current) return;\n // Defer a frame so the just-rendered content is measured before we pin.\n const timeout = setTimeout(() => {\n const el = containerRef.current;\n if (el) el.scrollTop = el.scrollHeight;\n }, 0);\n return () => clearTimeout(timeout);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, followKey);\n\n // Late growth keeps a pinned list at the bottom. The scroll container's own\n // box never changes when its content grows, so the observer watches the\n // rows (its direct children): any descendant getting taller — a chart chunk\n // mounting inside a turn — grows its row's box, and the callback re-pins.\n // Fires after layout, before paint, so the pin lands in the same frame; a\n // released viewport (`autoFollowRef` false) is never yanked.\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n const observer = new ResizeObserver(() => {\n if (!autoFollowRef.current) return;\n el.scrollTop = el.scrollHeight;\n });\n observerRef.current = observer;\n return () => {\n observer.disconnect();\n observerRef.current = null;\n observedRows.clear();\n };\n }, [observedRows]);\n\n // Rows mount and unmount on renders that leave `followKey` untouched (a\n // historical turn source landing after the transcript), so the observed set\n // is reconciled after EVERY commit: new rows observed, detached rows\n // released. Idempotent and a handful of elements — cheap at stream rate.\n useEffect(() => {\n const el = containerRef.current;\n const observer = observerRef.current;\n if (!el || !observer) return;\n observedRows.forEach((row) => {\n if (row.isConnected) return;\n observer.unobserve(row);\n observedRows.delete(row);\n });\n Array.from(el.children).forEach((row) => {\n if (observedRows.has(row)) return;\n observer.observe(row);\n observedRows.add(row);\n });\n });\n\n return { containerRef, handleScroll, showScrollDown, scrollToBottom };\n}\n","import {\n type LiteralWidgetComponentKey,\n type SafeExtract,\n type WidgetMessageU,\n} from '@opencx/widget-core';\nimport {\n type TurnRenderSource,\n sessionPlan,\n useAgentChatUi,\n useBot,\n useMessages,\n useSessions,\n useWidget,\n} from '@opencx/widget-react-headless';\nimport { AnimatePresence, motion } from 'framer-motion';\nimport { ArrowDown } from 'lucide-react';\nimport React, { useMemo } from 'react';\nimport { StreamingTurn } from '../../../components/StreamingTurn';\nimport { TaskPlan } from '../../../components/TaskPlan';\nimport { SessionResolvedComponent } from '../../../components/custom-components/SessionResolvedComponent';\nimport { ChatBottomComponents } from '../../../components/custom-components/ChatBottomComponents';\nimport { useTranslation } from '../../../hooks/useTranslation';\nimport { dc } from '../../../utils/data-component';\nimport {\n groupMessagesByType,\n isUserMessageGroup,\n} from '../../../utils/group-messages-by-type';\nimport { ChatBannerItems } from '../ChatBannerItems';\nimport { ChatCustomStatus } from '../ChatCustomStatus';\nimport { InitialMessages } from '../InitialMessages';\nimport { MessageGroups } from '../MessageGroups';\nimport { useStreamFollow } from './useStreamFollow';\n\n/**\n * The agent-chat message list, rendered as ONE keyed sequence so a turn's\n * node keeps its React identity through every phase of its life:\n *\n * - Rows covered by a turn render source (`turnSources`) render through the\n * streaming renderer (`StreamingTurn`) at their transcript position — the\n * retained live message for a turn that just finished (no swap, no flash,\n * chips stay) and the server's persisted `ui_parts` for historical turns\n * (reload fidelity). Their plain bubbles are suppressed.\n * - Uncovered rows render exactly as before (shared `MessageGroups` rule).\n * - The IN-FLIGHT turn renders last, under the same key its retained source\n * will use — the live→retained promotion moves data, never the node.\n */\nexport function AgentChatMain() {\n const {\n messagesState: { messages },\n } = useMessages();\n const {\n isStreaming,\n liveItems,\n turnSources,\n liveTurnKey,\n turnFailed,\n retryFailedTurn,\n } = useAgentChatUi();\n const { componentStore } = useWidget();\n const { t } = useTranslation();\n const bot = useBot();\n const {\n sessionState: { session },\n } = useSessions();\n const plan = useMemo(\n () => sessionPlan({ liveItems, turnSources }),\n [liveItems, turnSources],\n );\n\n const groupedMessages = useMemo(\n () => groupMessagesByType(messages),\n [messages],\n );\n\n const sourceByRowId = useMemo(() => {\n const map = new Map<string, TurnRenderSource>();\n for (const source of turnSources) {\n for (const rowId of source.rowIds) map.set(rowId, source);\n }\n return map;\n }, [turnSources]);\n\n // While the overlay has content it is the SOLE renderer of the current turn:\n // the turn's rows land in the polled transcript mid-stream and must not\n // render a second copy above it. Everything assistant-side after the LAST\n // user group that is not already covered by a finished turn's source is the\n // current turn's region.\n const lastUserGroupIndex = useMemo(() => {\n for (let i = groupedMessages.length - 1; i >= 0; i -= 1) {\n const group = groupedMessages[i];\n if (group && isUserMessageGroup(group)) return i;\n }\n return -1;\n }, [groupedMessages]);\n\n // A boolean, not the array: `liveItems` gets a fresh identity on every\n // throttled stream tick, and this memo only cares whether the overlay owns\n // the trailing region — depending on the array would rebuild every finished\n // turn's node ~20×/sec for the whole reply.\n const hasLiveItems = liveItems.length > 0;\n\n const { nodes: transcriptNodes, renderedSourceKeys } = useMemo(() => {\n const nodes: React.ReactNode[] = [];\n const renderedSourceKeys = new Set<string>();\n groupedMessages.forEach((group, groupIndex) => {\n const firstIdInGroup = group[0]?.id;\n if (!firstIdInGroup) return;\n if (isUserMessageGroup(group)) {\n nodes.push(<MessageGroups key={firstIdInGroup} groups={[group]} />);\n return;\n }\n // Assistant-side group: rows covered by a turn source render through\n // that source's StreamingTurn (once per source); uncovered rows keep\n // the stock rendering, in runs so grouping visuals survive.\n let run: WidgetMessageU[] = [];\n const flushRun = () => {\n const runFirstId = run[0]?.id;\n if (runFirstId) {\n nodes.push(<MessageGroups key={runFirstId} groups={[run]} />);\n }\n run = [];\n };\n for (const message of group) {\n const source = sourceByRowId.get(message.id);\n if (source) {\n flushRun();\n if (!renderedSourceKeys.has(source.key)) {\n renderedSourceKeys.add(source.key);\n nodes.push(\n <StreamingTurn\n key={source.key}\n turn={{ active: false, items: source.items }}\n agent={bot}\n timestamp={message.timestamp}\n />,\n );\n }\n } else if (hasLiveItems && groupIndex > lastUserGroupIndex) {\n // The live overlay owns this region — suppress the plain copy.\n } else {\n run.push(message);\n }\n }\n flushRun();\n });\n return { nodes, renderedSourceKeys };\n }, [groupedMessages, sourceByRowId, hasLiveItems, lastUserGroupIndex, bot]);\n\n // One owner per node key: a finished turn is retained into `turnSources` at\n // the stream boundary, BEFORE its rows land — the overlay keeps rendering\n // it until then. The commit where the rows arrive renders the source, so\n // the overlay must stand down in that same commit (the release effect only\n // flips state afterwards).\n const showLiveTurn =\n liveTurnKey !== null &&\n liveItems.length > 0 &&\n !renderedSourceKeys.has(liveTurnKey);\n\n const LoadingComponent = componentStore.getComponent(\n 'loading' satisfies SafeExtract<LiteralWidgetComponentKey, 'loading'>,\n );\n\n // Streaming scroll: follow the bottom only while pinned;\n // once the user scrolls up, release and surface the scroll-to-bottom button.\n const { containerRef, handleScroll, showScrollDown, scrollToBottom } =\n useStreamFollow([messages, liveItems]);\n\n return (\n <>\n <div\n {...dc('chat/msgs/wrapper')}\n className=\"relative flex flex-1 flex-col min-h-0\"\n >\n <div\n {...dc('chat/msgs/root')}\n ref={containerRef}\n onScroll={handleScroll}\n className=\"max-h-full relative flex-1 py-2 px-4 flex flex-col gap-2 overflow-auto\"\n >\n <ChatCustomStatus />\n <ChatBannerItems />\n <InitialMessages />\n\n {[\n ...transcriptNodes,\n /* The live turn, streamed from useChat. Rendered in the SAME keyed\n sequence as the finished turns so its promotion to a retained\n source (same key) is a data move, never an unmount — the reply\n and its tool chips never blink. `active` follows the real stream,\n so shimmers and in-progress steps settle the moment it ends. */\n ...(showLiveTurn\n ? [\n <StreamingTurn\n key={liveTurnKey}\n turn={{ active: isStreaming, items: liveItems }}\n agent={bot}\n />,\n ]\n : []),\n ]}\n {/* Typing indicator until the stream's FIRST visible item arrives — a\n silent early stream must never look like a dead widget. */}\n {isStreaming && liveItems.length === 0 && LoadingComponent && (\n <LoadingComponent agent={bot} />\n )}\n {/* A failed turn must be VISIBLE: without this row the user sees a\n dimmed bubble and silence forever. Retry re-sends the same message\n under a fresh wire uuid through the normal queue. */}\n {turnFailed && !isStreaming && (\n <div\n {...dc('chat/turn_failed/root')}\n className=\"flex items-center gap-2 self-start rounded-xl border border-destructive/30 bg-destructive/10 px-3 py-2 text-sm text-destructive\"\n >\n <span>{t('turn_failed_message')}</span>\n <button\n {...dc('chat/turn_failed/retry')}\n type=\"button\"\n onClick={retryFailedTurn}\n className=\"font-medium underline underline-offset-2 hover:opacity-80\"\n >\n {t('turn_failed_retry')}\n </button>\n </div>\n )}\n\n <ChatBottomComponents />\n <SessionResolvedComponent />\n </div>\n\n <AnimatePresence>\n {showScrollDown && (\n <motion.button\n {...dc('chat/msgs/scroll-to-bottom')}\n key=\"scroll-to-bottom\"\n type=\"button\"\n initial={{ opacity: 0, scale: 0.8 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.8 }}\n transition={{ duration: 0.15 }}\n onClick={scrollToBottom}\n aria-label={t('scroll_to_bottom')}\n className=\"absolute bottom-3 left-1/2 z-20 flex size-8 -translate-x-1/2 items-center justify-center rounded-full border border-border bg-background text-muted-foreground shadow-lg transition-colors hover:text-foreground\"\n >\n <ArrowDown className=\"size-4\" />\n </motion.button>\n )}\n </AnimatePresence>\n </div>\n {plan && plan.length > 0 && (\n <div {...dc('chat/session-plan')} className=\"shrink-0 px-4 pb-2\">\n <TaskPlan\n key={session?.id ?? 'new-session'}\n plan={plan}\n active={isStreaming}\n />\n </div>\n )}\n </>\n );\n}\n","import React, { useState } from 'react';\nimport {\n useMessages,\n useModes,\n useSessions,\n} from '@opencx/widget-react-headless';\nimport { useComponentContext } from '../../hooks/useComponentContext';\nimport { log } from '@opencx/widget-core';\n\nexport function ChatCanvas() {\n const props = useComponentContext();\n const { activeMode, Component } = useModes();\n const { sendMessage } = useMessages();\n const { createStateCheckpoint } = useSessions();\n\n const [isSendingMessage, setIsSendingMessage] = useState(false);\n\n const handleSendMessage = async (args: Parameters<typeof sendMessage>[0]) => {\n try {\n setIsSendingMessage(true);\n await sendMessage(args);\n } catch (error) {\n log.error('mode component send failed', error);\n } finally {\n setIsSendingMessage(false);\n }\n };\n\n if (!activeMode || !Component) return null;\n\n return (\n <Component\n {...props}\n mode={activeMode}\n createStateCheckpoint={createStateCheckpoint}\n sendMessage={handleSendMessage}\n isSendingMessage={isSendingMessage}\n />\n );\n}\n","import { useConfig, useMessages } from '@opencx/widget-react-headless';\n\n/** Share the first-message requirement between the composer and its launcher. */\nexport function useInitialQuestionRequired() {\n const { requireInitialQuestion, initialQuestions } = useConfig();\n const { messagesState } = useMessages();\n\n return (\n requireInitialQuestion === true &&\n messagesState.messages.length === 0 &&\n initialQuestions?.some((question) => question.trim().length > 0) === true\n );\n}\n","import React from 'react';\nimport { MotionDiv, type MotionDivProps } from './MotionDiv';\nimport { cn } from './utils/cn';\n\nexport const MotionDiv__VerticalReveal = React.forwardRef<\n HTMLDivElement,\n MotionDivProps\n>((props, ref) => {\n return (\n <MotionDiv\n {...props}\n ref={ref}\n className={cn('overflow-hidden', props.className)}\n overrides={{\n initial: { height: 0, opacity: 0, ...props.overrides?.initial },\n animate: { height: 'auto', opacity: 1, ...props.overrides?.animate },\n exit: { height: 0, opacity: 0, ...props.overrides?.exit },\n }}\n />\n );\n});\nMotionDiv__VerticalReveal.displayName = 'MotionDiv__VerticalReveal';\n","import { useCsat } from '@opencx/widget-react-headless';\nimport { AnimatePresence } from 'framer-motion';\nimport { ArrowUpIcon } from 'lucide-react';\nimport React, { useState } from 'react';\nimport { useIsSmallScreen } from '../hooks/useIsSmallScreen';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { Button } from './lib/button';\nimport { MotionDiv__VerticalReveal } from './lib/MotionDiv__VerticalReveal';\nimport { cn } from './lib/utils/cn';\n\nconst CSAT_SCORES = [\n {\n label: 'Terrible',\n value: 1,\n emoji: '😡',\n },\n {\n label: 'Poor',\n value: 2,\n emoji: '😞',\n },\n {\n label: 'Okay',\n value: 3,\n emoji: '😐',\n },\n {\n label: 'Good',\n value: 4,\n emoji: '😊',\n },\n {\n label: 'Great',\n value: 5,\n emoji: '😍',\n },\n];\n\nexport function CsatSurvey() {\n const { isSmallScreen } = useIsSmallScreen();\n const { t } = useTranslation();\n const {\n submitCsat,\n isCsatRequested,\n isCsatSubmitted,\n submittedScore,\n submittedFeedback,\n } = useCsat();\n\n const [score, setScore] = useState<number | null>(null);\n const [feedback, setFeedback] = useState<string | null>(null);\n\n const handleRatingClick = (value: number) => {\n setScore((prev) => (prev === value ? null : value));\n };\n\n const handleSubmit = () => {\n if (!score) return;\n void submitCsat({\n score: score,\n feedback: feedback || undefined,\n });\n };\n\n if (!isCsatRequested && !isCsatSubmitted) return null;\n\n return (\n <div className=\"w-1/2 min-w-80 max-w-96 mx-auto overflow-hidden\">\n {/* ------------------------ TITLE ----------------------- */}\n <AnimatePresence mode=\"wait\">\n {isCsatRequested && !score ? (\n <MotionDiv__VerticalReveal key=\"csat-requested-title\">\n <p className=\"text-sm text-muted-foreground text-center pt-2\">\n {t('csat_title')}\n </p>\n </MotionDiv__VerticalReveal>\n ) : isCsatSubmitted ? (\n <MotionDiv__VerticalReveal key=\"csat-submitted-title\">\n <p className=\"text-sm text-muted-foreground text-center pt-2\">\n {t('csat_submitted_title')}\n </p>\n </MotionDiv__VerticalReveal>\n ) : null}\n </AnimatePresence>\n\n {/* ------------------------ EMOJI ----------------------- */}\n {/*\n Force LTR so the rating scale always renders 😡(left) → 😍(right),\n independent of the widget's language direction. In RTL (e.g. Arabic)\n an inherited `dir=rtl` would reverse the flex row and surface 😡 first\n to a right-to-left reader, skewing CSAT toward negative scores.\n */}\n <div\n dir=\"ltr\"\n className={cn(\n 'flex gap-4 justify-between pt-2 px-2 pb-2',\n 'transition-all',\n isCsatSubmitted && 'gap-0 justify-center',\n )}\n >\n {CSAT_SCORES.map((s) => (\n <Button\n variant={s.value === score ? 'secondary' : 'ghost'}\n size=\"selfless\"\n className={cn(\n 'transition-all overflow-hidden',\n 'text-2xl size-8 rounded-full',\n 'opacity-35',\n 'hover:opacity-100',\n !score && 'opacity-100',\n s.value === score && 'opacity-100',\n isCsatSubmitted &&\n s.value !== submittedScore &&\n 'opacity-0 size-0',\n isCsatSubmitted &&\n s.value === submittedScore &&\n 'opacity-100 size-fit text-4xl',\n )}\n key={s.value}\n onClick={\n isCsatRequested ? () => handleRatingClick(s.value) : undefined\n }\n >\n {s.emoji}\n </Button>\n ))}\n </div>\n\n {/* ------------------------ FEEDBACK ----------------------- */}\n <AnimatePresence mode=\"wait\">\n {(score || submittedScore) && (\n <MotionDiv__VerticalReveal key=\"feedback-box\">\n <div className=\"pb-2 px-2 flex items-end\">\n <textarea\n // Thw `rows` attribute will take effect in browsers that do not support [field-sizing:content;] (Firefox and Safari as of now)\n rows={3}\n className={cn(\n 'transition-all',\n 'max-h-40 [field-sizing:content]',\n 'w-full resize-none',\n 'bg-transparent outline-none',\n 'placeholder:text-muted-foreground',\n // 16px on mobiles prevents auto-zoom on the input when focused\n isSmallScreen ? 'text-[16px]' : 'text-sm',\n isCsatSubmitted && 'text-center',\n )}\n value={\n isCsatSubmitted ? submittedFeedback || '' : feedback || ''\n }\n onChange={\n isCsatRequested\n ? (e) => setFeedback(e.target.value)\n : undefined\n }\n readOnly={isCsatSubmitted}\n placeholder={\n isCsatRequested ? t('csat_feedback_placeholder') : undefined\n }\n />\n <Button\n size=\"fit\"\n onClick={handleSubmit}\n disabled={!score}\n className={cn(\n 'transition-all overflow-hidden',\n 'rounded-full size-8 flex items-center justify-center p-0',\n isCsatSubmitted && 'opacity-0 size-0',\n )}\n >\n <ArrowUpIcon className=\"size-4\" />\n </Button>\n </div>\n </MotionDiv__VerticalReveal>\n )}\n </AnimatePresence>\n\n {/* ----------------------- SPACER ----------------------- */}\n <div\n className={cn('h-0 transition-[height]', isCsatSubmitted && 'h-4')}\n />\n </div>\n );\n}\n","import React from 'react';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { SuggestedReplyButton } from './SuggestedReplyButton';\nimport { dc } from '../utils/data-component';\n\nexport function MightSolveUserIssueSuggestedReplies() {\n const { t } = useTranslation();\n const options = [t('i_need_more_help'), t('this_was_helpful')];\n\n return (\n <div\n {...dc('chat/might_solve_user_issue_suggested_replies_container')}\n className=\"flex items-center gap-2 p-2 pb-0 flex-wrap\"\n >\n {options.map((option) => (\n <SuggestedReplyButton\n key={option}\n suggestion={option}\n className=\"flex-1\"\n />\n ))}\n </div>\n );\n}\n","import React from 'react';\nimport { useConfig, useSessions } from '@opencx/widget-react-headless';\nimport { AnimatePresence } from 'framer-motion';\nimport { MotionDiv__VerticalReveal } from '../../components/lib/MotionDiv__VerticalReveal';\nimport { ConfiguredRichText } from '../../components/RichText';\n\nexport function ChatFooterItems() {\n const { sessionState } = useSessions();\n const { chatFooterItems } = useConfig();\n\n const isSessionResolved =\n !!sessionState.session && !sessionState.session.isOpened;\n const isSessionOpen = !isSessionResolved;\n\n return (\n <AnimatePresence mode=\"wait\">\n {chatFooterItems?.map((item, i) => {\n if (item.showWhenSessionIsOpen === false && isSessionOpen) {\n return null;\n }\n if (item.showWhenSessionIsResolved === false && isSessionResolved) {\n return null;\n }\n\n return (\n <MotionDiv__VerticalReveal key={`${item.message}-${i}`}>\n <div className=\"pb-2 text-center text-xs\">\n <ConfiguredRichText>{item.message}</ConfiguredRichText>\n </div>\n </MotionDiv__VerticalReveal>\n );\n })}\n </AnimatePresence>\n );\n}\n","/*!\nMIT License\n\nCopyright (c) 2024–2025 Anthropic, PBC and contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n*/\nimport React from 'react';\n\n/** Official MCP mark: https://github.com/modelcontextprotocol/docs/blob/main/favicon.svg */\nexport function McpIcon() {\n return (\n <svg\n viewBox=\"0 0 180 180\"\n fill=\"none\"\n className=\"size-5 shrink-0 stroke-current\"\n strokeWidth=\"12\"\n strokeLinecap=\"round\"\n aria-hidden\n data-mcp-icon\n >\n <path d=\"M18 84.8528L85.8822 16.9706C95.2548 7.59798 110.451 7.59798 119.823 16.9706V16.9706C129.196 26.3431 129.196 41.5391 119.823 50.9117L68.5581 102.177\" />\n <path d=\"M69.2652 101.47L119.823 50.9117C129.196 41.5391 144.392 41.5391 153.765 50.9117L154.118 51.2652C163.491 60.6378 163.491 75.8338 154.118 85.2063L92.7248 146.6C89.6006 149.724 89.6006 154.789 92.7248 157.913L105.331 170.52\" />\n <path d=\"M102.853 33.9411L52.6482 84.1457C43.2756 93.5183 43.2756 108.714 52.6482 118.087V118.087C62.0208 127.459 77.2167 127.459 86.5893 118.087L136.794 67.8822\" />\n </svg>\n );\n}\n","import React, { useEffect, useState } from 'react';\nimport { useWidget } from '@opencx/widget-react-headless';\nimport type {\n ElicitationRequest,\n ElicitationResponse,\n} from '@opencx/widget-core';\nimport { X } from 'lucide-react';\nimport { McpIcon } from './lib/McpIcon';\nimport { Button } from './lib/button';\n\nexport function ElicitationForm({\n sessionId,\n active,\n}: {\n sessionId: string;\n active: boolean;\n}) {\n const { widgetCtx, config } = useWidget();\n const [pending, setPending] = useState<ElicitationRequest | null>(null);\n useEffect(() => {\n setPending(null);\n if (!active || config.capabilities?.connections !== true) return;\n const controller = new AbortController();\n let timer: ReturnType<typeof setTimeout>;\n const poll = async () => {\n try {\n const requests = await widgetCtx.api.listElicitations(\n sessionId,\n controller.signal,\n );\n if (!controller.signal.aborted) setPending(requests[0] ?? null);\n } catch {\n setPending((current) =>\n current && current.expiresAt > Date.now() ? current : null,\n );\n }\n if (!controller.signal.aborted) timer = setTimeout(poll, 1500);\n };\n void poll();\n return () => {\n controller.abort();\n clearTimeout(timer);\n };\n }, [widgetCtx, sessionId, active, config.capabilities?.connections]);\n return (\n <>\n {' '}\n {pending && pending.expiresAt > Date.now() ? (\n <RequestForm\n key={pending.id}\n request={pending}\n onAnswer={async (answer) => {\n await widgetCtx.api.answerElicitation(\n sessionId,\n pending.id,\n answer,\n );\n setPending(null);\n }}\n />\n ) : null}\n </>\n );\n}\n\nexport function RequestForm({\n request,\n onAnswer,\n}: {\n request: ElicitationRequest;\n onAnswer: (answer: ElicitationResponse) => Promise<void>;\n}) {\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState('');\n const respond = async (answer: ElicitationResponse) => {\n if (busy) return;\n setBusy(true);\n setError('');\n try {\n await onAnswer(answer);\n } catch (cause) {\n setError(\n cause instanceof Error ? cause.message : 'Could not submit. Try again.',\n );\n } finally {\n setBusy(false);\n }\n };\n const fields = request.form.requestedSchema.properties;\n const approval =\n Object.keys(fields).length === 1 &&\n fields.approve?.type === 'boolean' &&\n request.form.requestedSchema.required?.includes('approve');\n const inputClass =\n 'w-full rounded-lg border border-foreground/15 bg-background px-2 py-1.5 text-base sm:text-sm';\n return (\n <form\n aria-label={`Request from ${request.serverName}`}\n className={`min-w-0 rounded-2xl border border-foreground/10 bg-background p-2 space-y-2 text-foreground ${approval ? 'overflow-visible' : 'max-h-[50vh] overflow-y-auto'}`}\n onSubmit={(event) => {\n event.preventDefault();\n if (approval) {\n void respond({ action: 'accept', content: { approve: true } });\n return;\n }\n const data = new FormData(event.currentTarget);\n const content: NonNullable<ElicitationResponse['content']> = {};\n for (const [name, field] of Object.entries(fields)) {\n const value = data.get(name);\n if (field.type === 'boolean') content[name] = value === 'on';\n else if (field.type === 'array') {\n const selected = data\n .getAll(name)\n .filter((item): item is string => typeof item === 'string');\n if (\n field.minItems !== undefined &&\n selected.length < field.minItems\n ) {\n setError(\n `${field.title ?? name}: select at least ${field.minItems} options.`,\n );\n return;\n }\n if (\n field.maxItems !== undefined &&\n selected.length > field.maxItems\n ) {\n setError(\n `${field.title ?? name}: select no more than ${field.maxItems} options.`,\n );\n return;\n }\n content[name] = selected;\n } else if (typeof value === 'string' && value !== '')\n content[name] =\n field.type === 'number' || field.type === 'integer'\n ? Number(value)\n : value;\n }\n void respond({ action: 'accept', content });\n }}\n >\n <div className=\"flex items-start gap-2\">\n <div\n className=\"mt-0.5 size-4 shrink-0 text-foreground/50\"\n title={request.serverName}\n >\n <McpIcon />\n </div>\n <p className=\"min-w-0 flex-1 text-sm leading-5 break-words\">\n {request.form.message}\n </p>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-6 shrink-0 text-foreground/50\"\n wobble={false}\n aria-label=\"Cancel request\"\n disabled={busy}\n onClick={() => void respond({ action: 'cancel' })}\n >\n <X className=\"size-3.5\" />\n </Button>\n </div>\n {!approval && (\n <fieldset disabled={busy} className=\"space-y-3\">\n {Object.entries(fields).map(([name, field]) => {\n const id = `${request.id}-${name}`;\n const choices =\n field.oneOf ??\n field.enum?.map((value) => ({ const: value, title: value })) ??\n field.items?.anyOf ??\n field.items?.enum?.map((value) => ({\n const: value,\n title: value,\n }));\n const required =\n request.form.requestedSchema.required?.includes(name);\n return (\n <div key={name}>\n <label htmlFor={id} className=\"block text-sm font-medium mb-1\">\n {field.title ?? name}\n {required ? ' *' : ''}\n </label>\n {field.description && (\n <p className=\"text-sm text-foreground/60 mb-1\">\n {field.description}\n </p>\n )}\n {field.type === 'boolean' ? (\n <input\n id={id}\n name={name}\n type=\"checkbox\"\n defaultChecked={field.default === true}\n className=\"size-5 accent-current\"\n />\n ) : choices ? (\n <select\n id={id}\n name={name}\n multiple={field.type === 'array'}\n required={required}\n className={inputClass}\n defaultValue={\n typeof field.default === 'string' ||\n Array.isArray(field.default)\n ? field.default\n : field.type === 'array'\n ? []\n : ''\n }\n >\n {field.type !== 'array' && (\n <option value=\"\">Choose…</option>\n )}\n {choices.map((choice) => (\n <option key={choice.const} value={choice.const}>\n {choice.title ?? choice.const}\n </option>\n ))}\n </select>\n ) : (\n <input\n id={id}\n name={name}\n className={inputClass}\n type={\n field.type === 'number' || field.type === 'integer'\n ? 'number'\n : field.format === 'email'\n ? 'email'\n : field.format === 'uri'\n ? 'url'\n : field.format === 'date'\n ? 'date'\n : 'text'\n }\n required={required}\n min={field.minimum}\n max={field.maximum}\n step={field.type === 'integer' ? 1 : 'any'}\n minLength={field.minLength}\n maxLength={field.maxLength}\n defaultValue={\n typeof field.default === 'string' ||\n typeof field.default === 'number'\n ? field.default\n : ''\n }\n />\n )}\n </div>\n );\n })}\n </fieldset>\n )}\n {error && (\n <p role=\"alert\" className=\"text-sm text-destructive\">\n {error}\n </p>\n )}\n <div className=\"flex flex-wrap items-center gap-2 pl-6\">\n <Button\n type=\"submit\"\n size=\"sm\"\n className=\"h-7 rounded-lg px-2.5 py-0 text-xs\"\n wobble={false}\n disabled={busy}\n >\n {busy ? 'Submitting…' : approval ? 'Approve once' : 'Submit'}\n </Button>\n {approval && request.approvalKey && (\n <Button\n type=\"button\"\n size=\"sm\"\n variant=\"secondary\"\n className=\"h-7 rounded-lg px-2.5 py-0 text-xs\"\n wobble={false}\n disabled={busy}\n title=\"Allow the same tool, account and inputs. Reset anytime.\"\n onClick={() =>\n void respond({\n action: 'accept',\n content: { approve: true },\n remember: true,\n })\n }\n >\n Always allow\n </Button>\n )}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-7 rounded-lg px-2.5 py-0 text-xs\"\n wobble={false}\n disabled={busy}\n onClick={() => void respond({ action: 'decline' })}\n >\n Decline\n </Button>\n </div>\n </form>\n );\n}\n","import {\n useConnection,\n type ConnectionRequest,\n} from '@opencx/widget-react-headless';\nimport React from 'react';\nimport { Button } from './lib/button';\nimport { BrailleSpinner } from './lib/BrailleSpinner';\nimport { McpIcon } from './lib/McpIcon';\n\nexport function ConnectionCard({ request }: { request: ConnectionRequest }) {\n const connection = useConnection(request);\n const { phase, authorization, continuation, error } = connection;\n const starting = phase === 'loading' || phase === 'waiting';\n const busy = starting || continuation !== null;\n const finished = phase === 'connected' || phase === 'external';\n const expired = error?.toLowerCase().includes('expired') ?? false;\n const status = continuation\n ? continuation === 'renew'\n ? 'Preparing a new connection request'\n : 'Continuing your request'\n : phase === 'waiting'\n ? 'Waiting for approval'\n : phase === 'loading'\n ? 'Preparing connection'\n : phase === 'connected'\n ? 'Connected'\n : phase === 'external'\n ? 'Setup page completed'\n : 'Not connected';\n const actionLabel = continuation\n ? continuation === 'renew'\n ? 'Requesting…'\n : 'Continuing…'\n : phase === 'loading'\n ? 'Preparing…'\n : phase === 'waiting'\n ? 'Waiting…'\n : expired\n ? 'Reconnect'\n : error\n ? 'Try again'\n : finished\n ? 'Continue'\n : 'Connect';\n const action = () =>\n error || finished ? connection.retryContinuation() : connection.start();\n\n return (\n <section\n aria-label={`Connect ${request.name}`}\n data-component=\"chat/connection\"\n className=\"min-w-0 rounded-2xl border border-foreground/10 bg-background p-2 text-foreground\"\n >\n <div className=\"flex min-w-0 items-center gap-2\">\n <span className=\"flex size-9 shrink-0 items-center justify-center rounded-lg bg-secondary p-2\">\n <McpIcon />\n </span>\n <div className=\"min-w-0 flex-1\">\n <p\n className=\"truncate text-sm font-medium\"\n title={authorization?.host ?? request.name}\n >\n {request.name}\n </p>\n <p className=\"text-xs text-muted-foreground\">\n Connect your account to continue.\n </p>\n </div>\n <p role=\"status\" aria-live=\"polite\" className=\"sr-only\">\n {request.name}: {status}\n </p>\n {phase === 'ready' && authorization && !continuation ? (\n <Button\n asChild\n wobble={false}\n size=\"sm\"\n className=\"h-7 shrink-0 px-2.5 text-xs order-2\"\n >\n <a\n href={authorization.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onClick={connection.opened}\n aria-label={`Connect on ${authorization.host} (opens in a new tab)`}\n >\n Connect\n </a>\n </Button>\n ) : (\n <Button\n type=\"button\"\n wobble={false}\n size=\"sm\"\n className=\"h-7 shrink-0 px-2.5 text-xs order-2\"\n disabled={busy}\n aria-busy={busy}\n title={\n expired\n ? 'Your access expired. Connect again to continue.'\n : undefined\n }\n onClick={() => void action()}\n >\n {busy && <BrailleSpinner />}\n {actionLabel}\n </Button>\n )}\n <Button\n type=\"button\"\n wobble={false}\n variant=\"ghost\"\n size=\"fit\"\n className=\"h-7 shrink-0 px-2 text-xs order-1\"\n aria-label=\"Not now\"\n title=\"Not now\"\n disabled={continuation !== null}\n onClick={() => void connection.cancel()}\n >\n Not now\n </Button>\n </div>\n {error && (\n <p\n role=\"alert\"\n className=\"px-1 pt-2 text-sm text-pretty text-destructive\"\n >\n {error}\n </p>\n )}\n </section>\n );\n}\n","import { annotate, type Annotation } from '@shardsui/notation';\nimport type { MarkedElement, Rect } from './page-element';\nimport { log } from '@opencx/widget-core';\n\n/**\n * A mark the visitor put on the host page to ask about: a hand-drawn shape\n * around a region, an optional note, and the elements it covers.\n *\n * Every mark on the page — the visitor's here, the agent's in `agent-mark.ts`\n * — is drawn by the same pen (`@shardsui/notation`), so the conversation has\n * one visual language.\n */\n\n/**\n * The mark shapes the visitor can choose. The full notation set: a mark can\n * point at a thing (`arrow`), enclose it (`box`, `circle`, `bracket`),\n * emphasize a line of text (`underline`, `highlight`), or say it is wrong\n * (`strike-through`, `crossed-off`) — all of which are real things people\n * mean when they mark up a page to ask about it.\n *\n * `highlight` is safe here (it is not on the agent's pen) because a visitor\n * mark is anchored to the widget's OWN placeholder, never to a customer\n * element — the one type that writes `position`/`z-index` onto its target\n * can only ever write them onto ours.\n */\nexport const MARK_SHAPES = [\n 'box',\n 'circle',\n 'arrow',\n 'bracket',\n 'underline',\n 'highlight',\n 'strike-through',\n 'crossed-off',\n] as const;\n\nexport type MarkShape = (typeof MARK_SHAPES)[number];\n\n/**\n * Serialized as `clientContext.page_marks` on the send payload — every field\n * must be JSON-safe. The ink handle stays in the Widget-scoped page-mark\n * provider and the pill thumbnail's base64 in a WeakMap, never in the\n * payload; only the uploaded snapshot's URL rides along.\n */\nexport type PageMark = {\n /** The shape the visitor chose (boxed it / circled it / struck it out). */\n shape: MarkShape;\n /** The visitor's note, when they wrote one. */\n note?: string;\n /** Page URL at mark time. */\n pageUrl: string;\n /** Viewport bounding box of the marked region. */\n rect: Rect;\n /** Elements inside the region (deduped, focus element first, capped). */\n elements: MarkedElement[];\n /**\n * The region's pixels as a message file, once the thumbnail's upload lands\n * (`mark-thumbnail.ts` writes it onto the very object the composer holds,\n * so the send carries it and reloads show the image, not the tag names).\n * Absent when the capture or upload failed — surfaces fall back to text.\n */\n snapshotUrl?: string;\n};\n\n/**\n * One marked element as the BACKEND has understood it since the element\n * picker: an entry of `clientContext.picked_elements`.\n */\nexport type PickedElement = MarkedElement & {\n /** The note written on the mark this element came from, if any. */\n note?: string;\n};\n\n/**\n * The marks' elements under the key the backend actually reads and KEEPS.\n * `page_marks` is the richer payload (shape, note, region) but it is only\n * rendered into the current turn's client-context block; what the backend\n * re-surfaces on later turns — and what customer-facing surfaces read back —\n * is `picked_elements`. So both ride along: the marks for this turn's\n * reasoning, the flat elements for everything that outlives it.\n *\n * Deduped across marks (two marks on the same control are one element), and\n * the visitor's note travels on the element it was placed on, so a follow-up\n * turn still knows what was asked, not just what was clicked.\n */\nexport function pickedElementsFromMarks(marks: PageMark[]): PickedElement[] {\n const byKey = new Map<string, PickedElement>();\n const picked: PickedElement[] = [];\n for (const mark of marks) {\n // The first element this mark contributes carries its note — an existing\n // entry when every element was already picked, so marking the same control\n // twice keeps both questions instead of dropping the second.\n let noteTarget: PickedElement | undefined;\n for (const element of mark.elements) {\n const key = element.selector || element.name;\n const existing = byKey.get(key);\n if (existing) {\n noteTarget ??= existing;\n continue;\n }\n const entry: PickedElement = { ...element };\n byKey.set(key, entry);\n picked.push(entry);\n noteTarget ??= entry;\n }\n if (mark.note && noteTarget) {\n noteTarget.note = noteTarget.note\n ? `${noteTarget.note}\\n${mark.note}`\n : mark.note;\n }\n }\n return picked;\n}\n\n/** A region can never be resized smaller than this, per side. */\nexport const MIN_REGION_SIZE_PX = 20;\n/** Frozen-timeline backstop (hidden tab): never leak nodes forever. */\nconst UNDRAW_BACKSTOP_MS = 4000;\n\n/**\n * Post-`show()` dressing for notation's sibling-inserted SVGs: mark them\n * widget-owned (no mark may ever target the widget's own ink) and keep the\n * stroke legible over any host page — the faint white drop-shadow is what\n * saves a near-black theme color on a dark page.\n */\nexport function adoptNotationInk(target: Element, zIndex: number) {\n for (\n let node = target.nextElementSibling;\n node instanceof SVGSVGElement && node.classList.contains('notation');\n node = node.nextElementSibling\n ) {\n node.setAttribute('data-opencx-overlay', '');\n node.style.zIndex = String(zIndex);\n node.style.filter = 'drop-shadow(0 0 1px rgb(255 255 255 / 0.85))';\n }\n}\n\nexport type MarkInk = {\n /**\n * Re-anchor the mark to a new PAGE rect (live move/resize). Notation\n * redraws with the mark's stable seed — same hand, new place.\n */\n setRect(pageRect: Rect): void;\n /** Switch the mark shape in place. */\n setShape(shape: MarkShape): void;\n /** Reverse-plays the mark off the page, then releases it. */\n undraw(): void;\n /** Immediate teardown. */\n remove(): void;\n};\n\n/**\n * Ink a region as a hand-drawn mark, anchored to a widget-owned PLACEHOLDER\n * positioned at the region's page coordinates. Notation needs a target\n * element and a bare region has none — the placeholder gives it one without\n * touching a single node of the customer's DOM, and because it lives in page\n * coordinates the mark scrolls with the content for free.\n *\n * Never throws: a mark is decoration, and a draw failure must not break the\n * composer.\n */\nexport function createMarkInk(\n pageRect: Rect,\n shape: MarkShape,\n color: string,\n zIndex: number,\n): MarkInk {\n const anchor = document.createElement('div');\n anchor.setAttribute('data-opencx-overlay', '');\n Object.assign(anchor.style, {\n position: 'absolute',\n left: `${pageRect.x}px`,\n top: `${pageRect.y}px`,\n width: `${pageRect.width}px`,\n height: `${pageRect.height}px`,\n pointerEvents: 'none',\n zIndex: String(zIndex),\n } satisfies Partial<CSSStyleDeclaration>);\n document.documentElement.appendChild(anchor);\n\n let marker: Annotation | null = null;\n try {\n marker = annotate(anchor, {\n type: shape,\n color,\n strokeWidth: 2,\n wobble: 0.8,\n });\n marker.show();\n adoptNotationInk(anchor, zIndex);\n } catch (err) {\n log.warn('page mark: could not be drawn', err);\n }\n\n let gone = false;\n const remove = () => {\n if (gone) return;\n gone = true;\n try {\n marker?.remove();\n } catch {\n // Already torn down.\n }\n anchor.remove();\n };\n /** Redraw in place after the anchor or the options changed. */\n const redraw = (options: Parameters<Annotation['update']>[0]) => {\n if (gone) return;\n try {\n marker?.update(options);\n adoptNotationInk(anchor, zIndex);\n } catch {\n // Decoration only.\n }\n };\n\n return {\n setRect(nextRect) {\n if (gone) return;\n anchor.style.left = `${nextRect.x}px`;\n anchor.style.top = `${nextRect.y}px`;\n anchor.style.width = `${nextRect.width}px`;\n anchor.style.height = `${nextRect.height}px`;\n redraw({});\n },\n setShape(nextShape) {\n redraw({ type: nextShape });\n },\n undraw() {\n if (gone) return;\n if (!marker) return remove();\n try {\n marker.hide();\n void marker.finished.then(remove);\n } catch {\n return remove();\n }\n window.setTimeout(remove, UNDRAW_BACKSTOP_MS);\n },\n remove,\n };\n}\n","import {\n isPageElementPrivate,\n safePageText,\n safePageUrl,\n PAGE_VALUE_SELECTOR,\n WIDGET_OWNED_SELECTOR,\n} from '../page-privacy';\nexport { WIDGET_OWNED_SELECTOR } from '../page-privacy';\n/**\n * The page vocabulary shared by every mark on the host page — the visitor's\n * (`page-mark.ts`) and the agent's (`agent-mark.ts`).\n *\n * The widget's React code runs in the HOST page realm (only the chat UI is\n * portaled into a same-origin iframe), so `document` here is the host page\n * document — these helpers read the customer's page directly.\n */\n\n/** A viewport-relative box, rounded to whole pixels. */\nexport type Rect = {\n x: number;\n y: number;\n width: number;\n height: number;\n};\n\n/**\n * How one host-page element is described to the AI. Deliberately the minimum\n * that carries meaning: a name to reason about, a selector to point back at\n * (`highlight_element`), the tag, and the visible text.\n */\nexport type MarkedElement = {\n /** Human-readable name, e.g. `button \"Create Key\"`. */\n name: string;\n /** Resolvable CSS selector (verified unique against the document). */\n selector: string;\n /** Lowercased tag name. */\n tag: string;\n /** The element's own visible text, truncated. */\n text?: string;\n};\n\nconst TEXT_TRUNCATE = 60;\n\nfunction truncate(text: string, max: number): string {\n return text.length > max ? `${text.slice(0, max)}…` : text;\n}\n\nfunction cleanText(el: HTMLElement): string {\n return safePageText(el);\n}\n\n/**\n * A utility class says nothing about what a thing IS — `p-0!` and `flex-1`\n * are how it is drawn. They surfaced as the visitor-facing name of a marked\n * region (\"p-0!\" in the composer pill), so anything shaped like one is\n * rejected here and the caller falls back to the tag.\n */\nfunction isUtilityClass(cls: string): boolean {\n return (\n // Tailwind's important suffix, arbitrary values, variants, opacity:\n // `p-0!`, `w-[32px]`, `hover:bg-red`, `bg-black/50`.\n /[!/[\\]():]/.test(cls) ||\n // A short prefix plus a size/scale token: `p-0`, `gap-1.5`, `mt-12`.\n /^-?[a-z]{1,6}-\\d/.test(cls) ||\n // The bare layout vocabulary.\n /^(flex|grid|block|inline|hidden|absolute|relative|fixed|sticky|static|truncate|container)$/.test(\n cls,\n )\n );\n}\n\n/** First class name that looks authored (not a hash, not a utility). */\nfunction meaningfulClass(el: HTMLElement): string | null {\n const className = el.getAttribute('class');\n if (!className) return null;\n const cls = className\n .split(/\\s+/)\n .map((c) => c.replace(/[_-][a-zA-Z0-9]{5,}.*$/, ''))\n .find(\n (c) =>\n c.length > 2 &&\n !/^[a-z]{1,2}$/.test(c) &&\n !/[A-Z0-9]{5,}/.test(c) &&\n !isUtilityClass(c),\n );\n return cls ?? null;\n}\n\n/**\n * Human-readable name for an element — what the context pill shows and what\n * the LLM reads. Buttons are named by their text, inputs by placeholder/name,\n * images by alt.\n */\nexport function identifyElementName(el: HTMLElement): string {\n if (isPageElementPrivate(el)) return 'private region';\n const tag = el.tagName.toLowerCase();\n const aria = el.getAttribute('aria-label');\n const text = cleanText(el);\n\n if (tag === 'button' || el.getAttribute('role') === 'button') {\n if (aria) return `button [${aria}]`;\n return text ? `button \"${truncate(text, 30)}\"` : 'button';\n }\n if (tag === 'a') {\n if (text) return `link \"${truncate(text, 30)}\"`;\n const rawHref = el.getAttribute('href');\n const safeHref = rawHref ? safePageUrl(rawHref) : '';\n const href =\n rawHref?.startsWith('/') && !rawHref.startsWith('//') && safeHref\n ? new URL(safeHref).pathname\n : safeHref;\n return href ? `link to ${truncate(href, 40)}` : 'link';\n }\n if (tag === 'input' || tag === 'textarea' || tag === 'select') {\n const placeholder = el.getAttribute('placeholder');\n const name = el.getAttribute('name');\n if (placeholder) return `${tag} \"${truncate(placeholder, 30)}\"`;\n if (aria) return `${tag} [${aria}]`;\n if (name) return `${tag} [${name}]`;\n if (tag === 'input') return `${el.getAttribute('type') ?? 'text'} input`;\n return tag;\n }\n if (/^h[1-6]$/.test(tag))\n return text ? `${tag} \"${truncate(text, 40)}\"` : tag;\n if (tag === 'img') {\n const alt = el.getAttribute('alt');\n return alt ? `image \"${truncate(alt, 30)}\"` : 'image';\n }\n if (tag === 'svg') return 'icon';\n if (aria) return `${tag} [${aria}]`;\n if (text && text.length <= TEXT_TRUNCATE)\n return `${tag} \"${truncate(text, 40)}\"`;\n const cls = meaningfulClass(el);\n if (cls) return cls;\n return tag === 'div' ? 'container' : tag;\n}\n\n/**\n * Belt-and-braces uniqueness probe: `CSS.escape` output is always a valid\n * selector, but an invalid one must degrade to \"not unique\", never throw.\n */\nfunction isUniqueInDocument(doc: Document, selector: string): boolean {\n try {\n return doc.querySelectorAll(selector).length === 1;\n } catch {\n return false;\n }\n}\n\n/**\n * A CSS selector that resolves back to `el`. Prefers a unique `#id`; otherwise\n * builds a `:nth-of-type` chain upward, stopping as soon as the partial chain\n * is unique in the document.\n */\nexport function computeUniqueSelector(el: HTMLElement): string {\n const doc = el.ownerDocument;\n if (el.id) {\n const byId = `#${CSS.escape(el.id)}`;\n if (isUniqueInDocument(doc, byId)) return byId;\n }\n\n const segments: string[] = [];\n let current: HTMLElement | null = el;\n while (current && current.tagName.toLowerCase() !== 'html') {\n const tag = current.tagName.toLowerCase();\n if (current.id) {\n segments.unshift(`${tag}#${CSS.escape(current.id)}`);\n break;\n }\n let segment = tag;\n const parent: HTMLElement | null = current.parentElement;\n if (parent) {\n const sameTagSiblings = Array.from(parent.children).filter(\n (child) => child.tagName === current?.tagName,\n );\n if (sameTagSiblings.length > 1) {\n segment += `:nth-of-type(${sameTagSiblings.indexOf(current) + 1})`;\n }\n }\n segments.unshift(segment);\n const candidate = segments.join(' > ');\n if (isUniqueInDocument(doc, candidate)) return candidate;\n current = parent;\n }\n return segments.join(' > ');\n}\n\n/** The element's viewport-relative bounding box, rounded to whole pixels. */\nexport function rectOf(el: Element): Rect {\n const rect = el.getBoundingClientRect();\n return {\n x: Math.round(rect.x),\n y: Math.round(rect.y),\n width: Math.round(rect.width),\n height: Math.round(rect.height),\n };\n}\n\n/**\n * Breathing room kept between a mark's box and the viewport edge: the hover\n * frame inflates the rect by 4px and paints a ~4px ring outside that, which\n * is also enough for the ink's stroke and its wobble.\n */\nexport const VIEWPORT_MARGIN_PX = 8;\n\n/**\n * Clamp a viewport rect so everything drawn around it stays on the page. An\n * element taller or wider than the viewport — a full-height sidebar, a wide\n * table — otherwise gets a frame whose edges land outside the visible page,\n * and the visitor sees a border running off the screen instead of a box.\n */\nexport function clampRectToViewport(\n rect: Rect,\n margin: number = VIEWPORT_MARGIN_PX,\n): Rect {\n // `clientWidth` excludes the scrollbar (and is 0 in layout-less\n // environments, where `innerWidth` is the only answer available).\n const viewportWidth =\n document.documentElement.clientWidth || window.innerWidth;\n const viewportHeight =\n document.documentElement.clientHeight || window.innerHeight;\n const left = Math.max(rect.x, margin);\n const top = Math.max(rect.y, margin);\n const right = Math.min(rect.x + rect.width, viewportWidth - margin);\n const bottom = Math.min(rect.y + rect.height, viewportHeight - margin);\n return {\n x: Math.round(left),\n y: Math.round(top),\n width: Math.round(Math.max(0, right - left)),\n height: Math.round(Math.max(0, bottom - top)),\n };\n}\n\n/** Describe an element for the AI. */\nexport function describeElement(el: HTMLElement): MarkedElement {\n if (isPageElementPrivate(el) || el.closest(PAGE_VALUE_SELECTOR))\n return { name: 'private region', selector: '', tag: 'div' };\n const text = cleanText(el);\n return {\n name: identifyElementName(el),\n selector: computeUniqueSelector(el),\n tag: el.tagName.toLowerCase(),\n text: text ? truncate(text, 200) : undefined,\n };\n}\n\n/**\n * The single source of truth for \"this node belongs to the widget\": the embed\n * root, host-portaled chrome, and every mark overlay. Both the `closest()`\n * ownership check below and the mark-mode cursor's injected `:not()` chain\n * derive from this list — add new widget-owned markers HERE.\n */\nconst WIDGET_OWNED_CLOSEST = WIDGET_OWNED_SELECTOR.join(', ');\n\n/**\n * True for nodes that belong to the widget itself — no mark may ever target\n * the widget's own UI.\n */\nexport function isWidgetOwned(el: Element): boolean {\n return el.closest(WIDGET_OWNED_CLOSEST) !== null;\n}\n\n/**\n * The markable element under a viewport point. Keep the hit in the document\n * tree: selectors serialized into page-mark context must resolve through\n * `document.querySelector`, so piercing a shadow root would create an element\n * the selector contract cannot point back to. SVG children normalize to their\n * nearest semantic HTML control (or nearest HTML owner).\n */\nexport function elementAt(x: number, y: number): HTMLElement | null {\n let hit = document.elementFromPoint(x, y);\n if (!hit) return null;\n const root = hit.getRootNode();\n if (typeof ShadowRoot !== 'undefined' && root instanceof ShadowRoot) {\n hit = root.host;\n }\n const semanticOwner = hit.closest(\n 'button, a, input, textarea, select, [role=\"button\"], [role=\"link\"]',\n );\n let element: Element | null = semanticOwner ?? hit;\n while (element && !(element instanceof HTMLElement)) {\n element = element.parentElement;\n }\n if (!(element instanceof HTMLElement)) return null;\n if (\n isPageElementPrivate(hit) ||\n isPageElementPrivate(element) ||\n element.closest(PAGE_VALUE_SELECTOR)\n )\n return null;\n const tag = element.tagName.toLowerCase();\n if (tag === 'html' || tag === 'body') return null;\n return element;\n}\n\n/**\n * Find an element again from an LLM-provided hint: try the CSS selector first\n * (invalid model-authored selectors are non-fatal), then fall back to the\n * smallest element whose text contains the hint text.\n */\nexport function resolveElementByHint(hint: {\n selector?: string;\n text?: string;\n}): HTMLElement | null {\n if (hint.selector) {\n try {\n const el = document.querySelector(hint.selector);\n if (el instanceof HTMLElement && !isWidgetOwned(el)) return el;\n } catch {\n // Model-authored selector didn't parse — fall through to text search.\n }\n }\n\n const needle = hint.text?.replace(/\\s+/g, ' ').trim().toLowerCase();\n if (!needle) return null;\n\n let best: HTMLElement | null = null;\n let bestLength = Number.POSITIVE_INFINITY;\n const all = Array.from(document.body.querySelectorAll<HTMLElement>('*'));\n for (const el of all) {\n const tag = el.tagName.toLowerCase();\n if (tag === 'script' || tag === 'style' || tag === 'noscript') continue;\n if (isWidgetOwned(el)) continue;\n const text = cleanText(el).toLowerCase();\n if (!text.includes(needle)) continue;\n // `<=` so the DEEPEST element wins ties (querySelectorAll is document\n // order, parents before children with identical text).\n if (text.length <= bestLength) {\n best = el;\n bestLength = text.length;\n }\n }\n return best;\n}\n","import type { PageMark } from './page-mark';\nimport { describeElement } from './page-element';\nimport {\n canCapturePageElement,\n isPageElementPrivate,\n PAGE_VALUE_SELECTOR,\n safePageUrl,\n} from '../page-privacy';\nimport { copyThumbnail } from './mark-thumbnail';\n\n// DOM identity stays local. A reused selector must not authorize an old mark.\nconst sources = new WeakMap<PageMark, readonly HTMLElement[]>();\n\nexport function registerPageMarkSources(\n mark: PageMark,\n elements: readonly HTMLElement[],\n) {\n sources.set(mark, [...elements]);\n}\n\nexport function isPageMarkShareable(mark: PageMark): boolean {\n const elements = sources.get(mark);\n return (\n elements !== undefined &&\n mark.pageUrl === safePageUrl(window.location.href) &&\n elements.every(\n (element) =>\n element.isConnected &&\n element.getRootNode() === document &&\n !isPageElementPrivate(element) &&\n !element.closest(PAGE_VALUE_SELECTOR),\n )\n );\n}\n\n/** Refresh both serialized mark representations from the original live nodes. */\nexport function pageMarkForSend(mark: PageMark): PageMark | null {\n const elements = sources.get(mark);\n if (!elements || !isPageMarkShareable(mark)) return null;\n const descriptions = elements.map(describeElement);\n const snapshotSafe =\n elements.length > 0 &&\n elements.every(canCapturePageElement) &&\n JSON.stringify(descriptions) === JSON.stringify(mark.elements);\n const copy = { ...mark, elements: descriptions };\n if (snapshotSafe) copyThumbnail(mark, copy);\n else delete copy.snapshotUrl;\n // Keep the captured payload independent of late snapshot completion.\n return copy;\n}\n","import { isPageElementPrivate, safePageText } from '../page-privacy';\n/**\n * The accessible name of a control — the words a screen reader would say.\n *\n * This is the whole point of reading the page: a customer says \"the Change\n * plan button\", and the only way that matches a node is if we resolved the\n * name the same way their browser does. A CSS class or a tag name is not a\n * name; `aria-label`, a `<label>`, a `placeholder` and the visible text are.\n *\n * A trimmed-down accname resolution, in spec order for the cases that occur\n * on real pages: aria-labelledby → aria-label → the native label (label\n * element, legend, alt, title-of-image) → visible text → placeholder →\n * title. `value` is NEVER a name source, even where the spec allows it for\n * buttons, because an `<input type=\"submit\" value=\"…\">` is the one place\n * where a field's value and its name are the same string, and letting it\n * through would make \"no values\" depend on an input type.\n */\n\nconst NAME_MAX = 120;\n\nconst collapse = (text: string): string => text.replace(/\\s+/g, ' ').trim();\n\nconst truncate = (text: string): string =>\n text.length > NAME_MAX ? `${text.slice(0, NAME_MAX)}…` : text;\n\n/**\n * Text content, minus anything explicitly hidden from assistive tech, with\n * block boundaries kept as spaces.\n *\n * `textContent` concatenates with nothing between, so a real dashboard's\n * banner read as \"2 open disputesRespond before the deadline…\" — one word\n * where a person sees two lines, and a name the agent cannot match against\n * anything the customer would say. Browsers insert a space at a block\n * boundary when they compute a name; so does this.\n */\nconst visibleText = safePageText;\n\n/** The `<label>`s a form control is wired to, native or `for`-attached. */\nfunction labelText(el: HTMLElement): string {\n const labelled =\n el instanceof HTMLInputElement ||\n el instanceof HTMLSelectElement ||\n el instanceof HTMLTextAreaElement\n ? el.labels\n : null;\n const text = labelled\n ? Array.from(labelled)\n .map((label) => visibleText(label))\n .join(' ')\n : '';\n if (text) return collapse(text);\n const fieldset = el.closest('fieldset');\n const legend = fieldset?.querySelector('legend');\n return legend ? visibleText(legend) : '';\n}\n\n/**\n * Resolve the name. Returns '' when the control has none — a nameless\n * control is one the agent cannot talk about, so the reader drops it rather\n * than inventing a name out of markup.\n */\nexport function accessibleName(el: HTMLElement): string {\n if (isPageElementPrivate(el)) return '';\n const labelledBy = el.getAttribute('aria-labelledby');\n if (labelledBy) {\n const text = labelledBy\n .split(/\\s+/)\n .map((id) => el.ownerDocument.getElementById(id))\n .filter((node): node is HTMLElement => node !== null)\n .map((node) => visibleText(node))\n .filter(Boolean)\n .join(' ');\n if (text) return truncate(collapse(text));\n }\n\n const ariaLabel = el.getAttribute('aria-label');\n if (ariaLabel?.trim()) return truncate(collapse(ariaLabel));\n\n const tag = el.tagName.toLowerCase();\n\n if (tag === 'img') {\n const alt = el.getAttribute('alt');\n if (alt?.trim()) return truncate(collapse(alt));\n }\n\n if (tag === 'input' || tag === 'select' || tag === 'textarea') {\n const label = labelText(el);\n if (label) return truncate(label);\n const placeholder = el.getAttribute('placeholder');\n if (placeholder?.trim()) return truncate(collapse(placeholder));\n const title = el.getAttribute('title');\n if (title?.trim()) return truncate(collapse(title));\n return '';\n }\n\n const text = visibleText(el);\n if (text) return truncate(text);\n\n const title = el.getAttribute('title');\n if (title?.trim()) return truncate(collapse(title));\n\n return '';\n}\n","/**\n * Doing something on the customer's page, and knowing whether it happened.\n *\n * The rule that shapes all of this: the agent may only report what the page\n * actually did. Firing a click is easy; knowing whether the click DID\n * anything is the work, and it is the difference between \"I've cancelled\n * your subscription\" and the truth.\n */\n\n/** What the agent can do to a control. Deliberately small. */\nexport const PAGE_ACTIONS = [\n 'click',\n 'fill',\n 'select',\n 'check',\n 'uncheck',\n] as const;\nexport type PageAction = (typeof PAGE_ACTIONS)[number];\n\n/** The answer, in the same words the server and the agent use. */\nexport type ActOutcome =\n | 'done'\n | 'covered'\n | 'gone'\n | 'hidden'\n | 'unsupported'\n | 'no_change'\n | 'declined';\n\nexport type ActResult = {\n outcome: ActOutcome;\n /** One short sentence for the agent to pass on. Never page text. */\n detail?: string;\n};\n\n/** Maximum observation window; visible aria-busy regions defer quiet completion. */\nexport const SETTLE_MS = 3_000;\n\n/**\n * Controls the widget will never act on, whatever the agent asks and\n * whatever the visitor allows. A password or a file picker is not something\n * an agent types into, and a control inside a cross-origin frame is not\n * something this page can honestly report on.\n */\nexport const NEVER_ACT_INPUT_TYPES = new Set(['password', 'file', 'hidden']);\n","import { NEVER_ACT_INPUT_TYPES } from './act-types';\n\n/**\n * Recheck native action meaning before dispatch. These values stay local: URLs\n * and form metadata must not be copied into the agent's tool reply.\n * Host JavaScript is still responsible for its own event-handler behavior.\n */\nexport function captureActionMeaning(element: HTMLElement): () => boolean {\n const reference = new WeakRef(element);\n const approved = activationTargets(element).map((node) => {\n const target = readTarget(node);\n return {\n ...target,\n element: new WeakRef(target.element),\n form: target.form ? new WeakRef(target.form) : null,\n labelControl: target.labelControl\n ? new WeakRef(target.labelControl)\n : null,\n };\n });\n return () => {\n const element = reference.deref();\n if (!element) return false;\n if (!element.isConnected || element.getRootNode() !== document)\n return false;\n const current = activationTargets(element).map(readTarget);\n return (\n current.length === approved.length &&\n current.every((target, index) => {\n const before = approved[index]!;\n return (\n target.allowed &&\n target.element === before.element.deref() &&\n target.form === (before.form?.deref() ?? null) &&\n target.labelControl === (before.labelControl?.deref() ?? null) &&\n target.semantics === before.semantics\n );\n })\n );\n };\n}\n\nfunction activationTargets(element: HTMLElement): Element[] {\n // A role-button can activate a native ancestor; a label can forward its\n // click to another control. Bind those actual activation owners too.\n const targets: Element[] = [];\n const visited = new Set<Element>();\n const visit = (start: Element) => {\n for (let node: Element | null = start; node; node = node.parentElement) {\n if (visited.has(node)) break;\n visited.add(node);\n if (\n node === element ||\n node.matches('a[href],area[href],button,input,select,textarea,label')\n )\n targets.push(node);\n if (node instanceof HTMLLabelElement && node.control) visit(node.control);\n }\n };\n visit(element);\n return targets;\n}\n\nfunction readTarget(element: Element) {\n const link =\n element instanceof HTMLAnchorElement || element instanceof HTMLAreaElement\n ? element\n : null;\n const control =\n element instanceof HTMLButtonElement ||\n element instanceof HTMLInputElement ||\n element instanceof HTMLSelectElement ||\n element instanceof HTMLTextAreaElement\n ? element\n : null;\n const form = control?.form ?? null;\n const baseTarget = element.ownerDocument\n .querySelector('base[target]')\n ?.getAttribute('target');\n return {\n element,\n form,\n labelControl: element instanceof HTMLLabelElement ? element.control : null,\n allowed: !(\n element instanceof HTMLInputElement &&\n NEVER_ACT_INPUT_TYPES.has(element.type)\n ),\n semantics: JSON.stringify([\n element.tagName,\n element.getAttribute('role'),\n control?.type,\n control?.name,\n element instanceof HTMLButtonElement ||\n (element instanceof HTMLInputElement &&\n ['submit', 'image', 'reset'].includes(element.type))\n ? element.value\n : null,\n link?.href,\n link?.getAttribute('target') ?? baseTarget,\n link?.getAttribute('download'),\n link?.getAttribute('rel'),\n link?.getAttribute('ping'),\n form?.action,\n form?.method,\n form?.getAttribute('target') ?? baseTarget,\n form?.enctype,\n form?.noValidate,\n ...[\n 'formaction',\n 'formmethod',\n 'formtarget',\n 'formenctype',\n 'formnovalidate',\n ].map((name) => element.getAttribute(name)),\n // Resolved URL properties catch a changed <base href> as well.\n element instanceof HTMLButtonElement ||\n element instanceof HTMLInputElement\n ? [\n element.formAction,\n element.formMethod,\n element.formTarget,\n element.formEnctype,\n element.formNoValidate,\n ]\n : null,\n ]),\n };\n}\n","import { isWidgetOwned } from '../page-marks/page-element';\nimport { accessibleName } from './accessible-name';\nimport { captureActionMeaning } from './action-meaning';\n\n/**\n * The table behind the references — held here, in the page, never sent.\n *\n * Every control the agent can talk about is one the reader put in this table\n * in this turn. The wire carries `c7`; only this module knows which node\n * that is. Three properties fall out of that, and they are the reason the\n * table exists instead of the agent authoring CSS selectors:\n *\n * - The agent cannot reach a node we did not offer it. There is no selector\n * to widen, no text to guess at, no way to name the password field we\n * skipped.\n * - A reference is checkable. Before drawing or clicking, `resolve` says\n * whether that exact node is still in the document — a stale reference\n * after a re-render is a \"no\", not a click on whatever moved into place.\n * - The nodes are held weakly, so a table entry never keeps a detached\n * subtree of the customer's page alive.\n */\n\n/** Keep two readings. Controls present in each new reading renew their handles;\n * absent controls expire without ever assigning their handles to another node. */\nconst GENERATIONS_KEPT = 2;\n\ntype ControlReference = {\n element: WeakRef<HTMLElement>;\n sameContext: () => boolean;\n name: string;\n url: string;\n sameMeaning: () => boolean;\n valid: boolean;\n};\ntype Generation = Map<string, ControlReference>;\n\nconst generations: Generation[] = [];\nlet sequence = 0;\nlet elementRefs = new WeakMap<HTMLElement, string>();\nlet observer: MutationObserver | undefined;\nlet observedDocument: Document | undefined;\n\n// Mutation callbacks advance shared counters, never scan retained references.\n// Entries hold counters rather than nodes, so detached host trees stay collectible.\ntype Revision = { value: number };\nlet subtreeRevisions = new WeakMap<Node, Revision>();\nlet recordRevisions = new WeakMap<Node, Revision>();\nlet lineageRevisions = new WeakMap<Node, Revision>();\n\n// Keep record identity local. A top-level button has no containing record;\n// treating the document body as one makes a clock anywhere cancel its click.\nconst CONTEXT_SELECTOR =\n 'tr,li,article,form,fieldset,section,dialog,aside,nav,main,header,footer,[role=\"row\"],[role=\"listitem\"],[role=\"group\"],[role=\"region\"],[role=\"dialog\"],[role=\"tooltip\"]';\nconst RECORD_SELECTOR = 'tr,li,article,[role=\"row\"],[role=\"listitem\"]';\nconst GROUP_SELECTOR =\n 'section,form,fieldset,dialog,[role=\"group\"],[role=\"region\"],[role=\"dialog\"]';\nconst PRESENTATION_ATTRIBUTES = new Set(['class', 'style', 'aria-busy']);\n\nfunction contextRoot(element: HTMLElement): Element {\n const record = element.closest(RECORD_SELECTOR);\n if (record) return record;\n // A layout wrapper around the button does not detach it from its outer\n // item label. Without an explicit record, conservatively bind the enclosing\n // group, including nested groups in either direction. Never fall back to body.\n let group = element.closest(GROUP_SELECTOR);\n if (group) {\n let outer = group.parentElement?.closest(GROUP_SELECTOR);\n while (outer) {\n group = outer;\n outer = group.parentElement?.closest(GROUP_SELECTOR);\n }\n return group;\n }\n const region = element.closest(CONTEXT_SELECTOR);\n if (region) return region;\n const parent = element.parentElement;\n return parent &&\n parent !== element.ownerDocument.body &&\n parent !== element.ownerDocument.documentElement\n ? parent\n : element;\n}\n\nfunction transient(node: Element): boolean {\n return isWidgetOwned(node) || node.closest('[role=\"tooltip\"]') !== null;\n}\n\nfunction recordIsRelevant(record: MutationRecord): boolean {\n const node =\n record.target.nodeType === 1\n ? (record.target as Element)\n : record.target.parentElement;\n if (node && isWidgetOwned(node)) return false;\n if (\n record.type === 'attributes' &&\n PRESENTATION_ATTRIBUTES.has(record.attributeName ?? '')\n )\n return false;\n if (record.type === 'childList') {\n const changed = [\n ...Array.from(record.addedNodes),\n ...Array.from(record.removedNodes),\n ];\n if (\n changed.length &&\n changed.every((node) => node.nodeType === 1 && transient(node as Element))\n )\n return false;\n }\n return true;\n}\n\nfunction advance(records: MutationRecord[]) {\n const changed = new Set<Revision>();\n for (const record of records) {\n // Removal/reparenting must invalidate even if the node is now inside an\n // ignored tooltip or the widget. Every observed control tracks its lineage.\n for (const node of Array.from(record.removedNodes)) {\n const revision = lineageRevisions.get(node);\n if (revision) changed.add(revision);\n }\n if (!recordIsRelevant(record)) continue;\n if (record.type === 'attributes') {\n const revision = lineageRevisions.get(record.target);\n if (revision) changed.add(revision);\n }\n let withinRecord = true;\n for (let node: Node | null = record.target; node; node = node.parentNode) {\n const subtree = subtreeRevisions.get(node);\n if (subtree) changed.add(subtree);\n if (withinRecord) {\n const ownContent = recordRevisions.get(node);\n if (ownContent) changed.add(ownContent);\n }\n if (!(node instanceof Element)) continue;\n // A control's own scope includes nested groups: their label may identify\n // its action. Only ancestor-record identity excludes sibling child items.\n if (node.matches(RECORD_SELECTOR)) withinRecord = false;\n // Transient tooltip content is not the enclosing record's identity.\n // Changing an existing node's role is itself a semantic change.\n if (\n node.matches('[role=\"tooltip\"]') &&\n !(record.type === 'attributes' && record.attributeName === 'role')\n )\n break;\n }\n }\n changed.forEach((revision) => revision.value++);\n}\n\nfunction captureContext(element: HTMLElement): () => boolean {\n const captured: { revision: Revision; value: number }[] = [];\n const track = (node: Node, revisions: WeakMap<Node, Revision>) => {\n let revision = revisions.get(node);\n if (!revision) {\n revision = { value: 0 };\n revisions.set(node, revision);\n }\n captured.push({ revision, value: revision.value });\n };\n const root = contextRoot(element);\n track(root, subtreeRevisions);\n // Bind the complete local scope. Ancestor records contribute their own\n // identity, excluding sibling records. This preserves nested Order/Item\n // ownership without treating another item's updates as this item's identity.\n for (let node: Node | null = element; node; node = node.parentNode) {\n track(node, lineageRevisions);\n if (\n node !== root &&\n node instanceof Element &&\n node.matches(RECORD_SELECTOR)\n )\n track(node, recordRevisions);\n }\n return () =>\n captured.every(({ revision, value }) => revision.value === value);\n}\n\nfunction flushMutations() {\n if (observer) advance(observer.takeRecords());\n}\n\nfunction observe(doc: Document) {\n if (observedDocument === doc) return;\n observer?.disconnect();\n // References from another document cannot authorize actions here.\n for (const generation of generations)\n for (const entry of Array.from(generation.values())) entry.valid = false;\n observedDocument = doc;\n subtreeRevisions = new WeakMap();\n recordRevisions = new WeakMap();\n lineageRevisions = new WeakMap();\n observer = new MutationObserver(advance);\n observer.observe(doc.documentElement, {\n childList: true,\n subtree: true,\n attributes: true,\n characterData: true,\n });\n}\n\nfunction current(\n entry: ControlReference,\n element: HTMLElement,\n name = accessibleName(element),\n) {\n entry.valid &&=\n element.isConnected &&\n entry.url === element.ownerDocument.location.href &&\n entry.name === name &&\n entry.sameContext() &&\n entry.sameMeaning();\n return entry.valid;\n}\n\n/** Open a new reading. Returns the mint function for its references. */\nexport function beginSnapshot(): (el: HTMLElement, name?: string) => string {\n flushMutations();\n const generation: Generation = new Map();\n generations.unshift(generation);\n generations.length = Math.min(generations.length, GENERATIONS_KEPT);\n let n = 0;\n // References must never alias a newer control during a long-lived SPA visit.\n const prefix = `s${++sequence}`;\n return (el: HTMLElement, name = accessibleName(el)) => {\n observe(el.ownerDocument);\n flushMutations();\n const previous = elementRefs.get(el);\n const prior = previous\n ? generations\n .map((reading) => reading.get(previous))\n .find((entry) => entry !== undefined)\n : undefined;\n // Renew a live handle for a control included in consecutive readings.\n // Expired handles are never resurrected, and replacement nodes get new IDs.\n const ref =\n previous && prior && current(prior, el, name)\n ? previous\n : `${prefix}c${(n += 1)}`;\n const entry =\n ref === previous && prior\n ? prior\n : {\n element: new WeakRef(el),\n sameContext: captureContext(el),\n name,\n url: el.ownerDocument.location.href,\n sameMeaning: captureActionMeaning(el),\n valid: true,\n };\n generation.set(ref, entry);\n elementRefs.set(el, ref);\n return ref;\n };\n}\n\n/**\n * The element behind a reference, or null — gone from the table, collected,\n * or no longer in the document. \"No longer the same node\" and \"not found\"\n * are deliberately the same answer: both mean do not act.\n */\nexport function resolveRef(ref: string): HTMLElement | null {\n const entry = inspectRef(ref);\n return entry?.isCurrent ? entry.element : null;\n}\n\n/** Guard-only inspection: a stale element must never be authorized to act.\n * Keeping its identity status separate lets the guard report a more specific\n * privacy/visibility refusal before returning \"gone\" for a changed operation. */\nexport function inspectRef(\n ref: string,\n): { element: HTMLElement; isCurrent: boolean } | null {\n flushMutations();\n for (const generation of generations) {\n const entry = generation.get(ref);\n if (!entry) continue;\n const el = entry.element.deref();\n if (el && el.isConnected)\n return { element: el, isCurrent: current(entry, el) };\n }\n return null;\n}\n\n/** Test seam: forget every reading. */\nexport function resetRefsForTest(): void {\n generations.length = 0;\n sequence = 0;\n elementRefs = new WeakMap();\n observer?.disconnect();\n observer = undefined;\n observedDocument = undefined;\n subtreeRevisions = new WeakMap();\n recordRevisions = new WeakMap();\n lineageRevisions = new WeakMap();\n}\n","/**\n * What the agent knows about the controls on the customer's page.\n *\n * The widget reads the page itself and sends NAMES. The elements never\n * leave the browser: each one is held here behind an opaque reference, and\n * every later instruction — point at this, click that — comes back as one of\n * those references. Nothing the agent says can name a node we did not offer\n * it in this turn.\n *\n * What is deliberately absent: values. Not the text in a field, not the\n * option a select is on, not a password, not a file name. A support agent\n * needs to know that a \"Change plan\" button exists and is greyed out; it\n * never needs to know what the visitor typed into \"Card number\".\n */\n\n/** One control on the host page, as the agent reads it. */\nexport type PageControl = {\n /** Opaque handle for this turn. The agent points with it; only we resolve it. */\n ref: string;\n /** What the control IS: button, link, textbox, checkbox, … (ARIA role). */\n role: string;\n /** The control's accessible name — the words a screen reader would say. */\n name: string;\n /** Present and true only when the control cannot be used right now. */\n disabled?: true;\n};\n\n/** One turn's reading of the page: the controls, and the table behind them. */\nexport type PageControlSnapshot = {\n controls: PageControl[];\n /** Whether the page had more controls than the cap allowed us to send. */\n truncated: boolean;\n};\n\n/**\n * Attribute a customer puts on any part of their page the agent must never\n * read. Everything inside is skipped whole — the control, its name, its\n * existence. The one thing a page owner can say that the reader obeys\n * without interpretation.\n */\nexport const PRIVATE_REGION_ATTRIBUTE = 'data-opencx-private';\n\n/**\n * Input types the reader refuses on sight, whatever else is true about them:\n * a password is never described, and a file picker's name can carry the\n * visitor's own file names.\n */\nexport const NEVER_READ_INPUT_TYPES = new Set(['password', 'file', 'hidden']);\n\n/**\n * How many controls one message carries. A page with more than this is read\n * in full (so the cap applies to the busiest part, not a random prefix) but\n * sends only the first `MAX_CONTROLS` in document order, and says so.\n * Chosen against the prompt, not the DOM: 300 names is roughly 3k tokens.\n */\nexport const MAX_CONTROLS = 300;\n","import { isWidgetOwned } from '../page-marks/page-element';\nimport { NEVER_READ_INPUT_TYPES, PRIVATE_REGION_ATTRIBUTE } from './types';\n\n/**\n * The one list of things the agent may never read, point at or touch —\n * checked when the page is read AND again in the instant before anything\n * happens.\n *\n * Twice, because the two moments are not the same moment. An application\n * marks its card form private when that form mounts, which can be after the\n * message was sent; a dialog becomes `aria-hidden` behind a newer one. A\n * reference minted before any of that still resolves, so a rule enforced\n * only at read time is a rule with a window in it.\n */\nexport type OffLimitsReason =\n | 'private'\n | 'hidden-from-assistive-tech'\n | 'credential-field'\n | 'widget-owned';\n\nexport function offLimitsReason(el: HTMLElement): OffLimitsReason | null {\n if (isWidgetOwned(el)) return 'widget-owned';\n if (el.closest(`[${PRIVATE_REGION_ATTRIBUTE}]`)) return 'private';\n if (el.getAttribute('aria-hidden') === 'true')\n return 'hidden-from-assistive-tech';\n if (el.closest('[aria-hidden=\"true\"]')) return 'hidden-from-assistive-tech';\n if (el.tagName.toLowerCase() === 'input') {\n const type = (el.getAttribute('type') ?? 'text').toLowerCase();\n if (NEVER_READ_INPUT_TYPES.has(type)) return 'credential-field';\n }\n return null;\n}\n\n/** What to tell the agent, without describing what it was kept away from. */\nexport const OFF_LIMITS_DETAIL: Record<OffLimitsReason, string> = {\n private:\n 'That part of the page is marked private and the agent never reads or uses it.',\n 'hidden-from-assistive-tech':\n 'That control is hidden from assistive technology, so it is not treated as being on the page.',\n 'credential-field':\n 'Password and file fields are never filled or clicked by the agent.',\n 'widget-owned': 'That is part of the chat widget, not the page.',\n};\n","import { accessibleName } from './accessible-name';\nimport { beginSnapshot } from './control-ref';\nimport { offLimitsReason } from './off-limits';\nimport {\n MAX_CONTROLS,\n type PageControl,\n type PageControlSnapshot,\n} from './types';\n\n/**\n * Read the controls the visitor can actually see and use, once, at send time.\n *\n * \"Can see and use\" is the whole filter, and it is what keeps this honest:\n * a control behind `display:none`, a password field, anything inside a\n * region the customer marked private, and the widget's own UI are not on the\n * page as far as the agent is concerned. A nameless control is dropped too —\n * the agent can only talk about what it can name.\n *\n * Runs on the send path, so it must not cost a frame: one selector query,\n * one visibility check and one name resolution per hit, no layout thrash,\n * and a hard stop once the cap is reached.\n */\n\n/**\n * Everything a person can operate. Roles are included as well as tags,\n * because a real application's \"button\" is as often a `div[role=button]`.\n */\nconst INTERACTIVE_SELECTOR = [\n 'a[href]',\n 'button',\n 'input',\n 'select',\n 'textarea',\n 'summary',\n '[contenteditable=\"\"]',\n '[contenteditable=\"true\"]',\n '[role=\"button\"]',\n '[role=\"link\"]',\n '[role=\"checkbox\"]',\n '[role=\"radio\"]',\n '[role=\"switch\"]',\n '[role=\"tab\"]',\n '[role=\"menuitem\"]',\n '[role=\"menuitemcheckbox\"]',\n '[role=\"menuitemradio\"]',\n '[role=\"option\"]',\n '[role=\"combobox\"]',\n '[role=\"slider\"]',\n '[role=\"textbox\"]',\n '[role=\"searchbox\"]',\n].join(',');\n\n/**\n * Rows, cards and list items that a page has made clickable without saying\n * so in its markup.\n *\n * A React `onClick` on a `<tr>` cannot be seen from the DOM — there is no\n * API for it — so a table of settlements looks exactly like a table of\n * text, and an agent asked to open one has nothing to offer but the\n * navigation. That is not a hypothetical: it is what happens on the first\n * real screen this was pointed at.\n *\n * `cursor: pointer` is the signal, and it is not a guess. It is the page\n * telling the visitor, in the only way a page can, that this responds to a\n * click — the same thing a sighted person reads before they click it. We\n * take the page at its word rather than inferring anything about handlers.\n *\n * Bounded on purpose: only containers that hold a row of content, and only\n * when they contain no real control of their own, because then the control\n * is what should be offered, not its wrapper.\n */\nconst CLICKABLE_CONTAINER_SELECTOR = [\n 'tr',\n 'li',\n '[role=\"row\"]',\n '[role=\"listitem\"]',\n '[role=\"gridcell\"]',\n '[tabindex]',\n '[onclick]',\n].join(',');\n\n/** A cap on style reads, so a huge table cannot cost the send path a frame. */\nconst MAX_STYLE_PROBES = 400;\n\nfunction looksClickable(el: HTMLElement): boolean {\n try {\n return (\n el.ownerDocument.defaultView?.getComputedStyle(el).cursor === 'pointer'\n );\n } catch {\n return false;\n }\n}\n\n/** Tag → the role a browser would report, for the elements we collect. */\nfunction roleOf(el: HTMLElement): string {\n const explicit = el.getAttribute('role');\n if (explicit?.trim()) return explicit.trim().toLowerCase();\n const tag = el.tagName.toLowerCase();\n if (tag === 'a') return 'link';\n if (tag === 'button' || tag === 'summary') return 'button';\n if (tag === 'select') return 'combobox';\n if (tag === 'textarea') return 'textbox';\n if (tag === 'input') {\n const type = (el.getAttribute('type') ?? 'text').toLowerCase();\n if (type === 'checkbox') return 'checkbox';\n if (type === 'radio') return 'radio';\n if (type === 'submit' || type === 'button' || type === 'reset') {\n return 'button';\n }\n if (type === 'range') return 'slider';\n if (type === 'search') return 'searchbox';\n return 'textbox';\n }\n return 'textbox';\n}\n\n/**\n * What to call a clickable container. A row is a row; calling it a button\n * would tell the agent it is something it is not.\n */\nfunction containerRoleOf(el: HTMLElement): string {\n const explicit = el.getAttribute('role');\n if (explicit?.trim()) return explicit.trim().toLowerCase();\n const tag = el.tagName.toLowerCase();\n if (tag === 'tr') return 'row';\n if (tag === 'li') return 'listitem';\n return 'button';\n}\n\n/**\n * Is this control on screen? `checkVisibility` answers the CSS half\n * natively and cheaply; a zero-area box catches the rest (a control clipped\n * to nothing, or in a collapsed container).\n */\nfunction isVisible(el: HTMLElement): boolean {\n if (typeof el.checkVisibility === 'function') {\n if (\n !el.checkVisibility({\n checkOpacity: true,\n checkVisibilityCSS: true,\n })\n ) {\n return false;\n }\n } else if (!el.isConnected) {\n return false;\n }\n const rect = el.getBoundingClientRect();\n return rect.width > 0 && rect.height > 0;\n}\n\nfunction isDisabled(el: HTMLElement): boolean {\n if ('disabled' in el && el.disabled === true) return true;\n return el.getAttribute('aria-disabled') === 'true';\n}\n\n/** Read the host page's controls for this turn. Never throws. */\nexport function readPageControls(\n doc: Document = document,\n): PageControlSnapshot {\n const controls: PageControl[] = [];\n const seen = new Set<HTMLElement>();\n let truncated = false;\n try {\n const mint = beginSnapshot();\n const candidates = Array.from(\n doc.querySelectorAll<HTMLElement>(INTERACTIVE_SELECTOR),\n );\n for (const el of candidates) {\n if (offLimitsReason(el)) continue;\n if (!isVisible(el)) continue;\n const name = accessibleName(el);\n if (!name) continue;\n if (controls.length >= MAX_CONTROLS) {\n truncated = true;\n break;\n }\n const control: PageControl = {\n ref: mint(el, name),\n role: roleOf(el),\n name,\n };\n if (isDisabled(el)) control.disabled = true;\n controls.push(control);\n seen.add(el);\n }\n\n // Second pass: the rows and cards the page made clickable with style\n // rather than with markup. Cheap checks first, the style read last.\n let probes = 0;\n if (!truncated) {\n const containers = Array.from(\n doc.querySelectorAll<HTMLElement>(CLICKABLE_CONTAINER_SELECTOR),\n );\n for (const el of containers) {\n if (controls.length >= MAX_CONTROLS) {\n truncated = true;\n break;\n }\n if (probes >= MAX_STYLE_PROBES) break;\n if (seen.has(el)) continue;\n if (offLimitsReason(el)) continue;\n // A wrapper around a real control is not itself the control: offer\n // the button, not the cell it sits in.\n if (el.querySelector(INTERACTIVE_SELECTOR)) continue;\n if (!isVisible(el)) continue;\n const name = accessibleName(el);\n if (!name) continue;\n probes += 1;\n if (!looksClickable(el)) continue;\n controls.push({ ref: mint(el, name), role: containerRoleOf(el), name });\n seen.add(el);\n }\n }\n } catch {\n // Reading the page is a courtesy; a hostile or exotic DOM must never\n // stop the customer's message from being sent.\n return { controls: [], truncated: false };\n }\n return { controls, truncated };\n}\n","import {\n pickedElementsFromMarks,\n type PageMark,\n} from '../page-marks/page-mark';\nimport { readPageControls } from './read-controls';\nimport { pageMarkForSend } from '../page-marks/mark-source';\n\n/**\n * Everything about the customer's page that rides with one message.\n *\n * Two different things, sent together because they answer two different\n * questions. The marks are what the visitor pointed at — deliberate, a\n * gesture. The controls are what is simply THERE, read fresh at send time,\n * so the agent can answer \"where do I turn that off\" without the visitor\n * having to find and circle the switch first.\n *\n * Only the names go on the wire; the elements behind the references stay in\n * the page (`control-ref.ts`). Reading happens at send time and nowhere\n * else, which is what keeps a page turn free of an extra round trip.\n */\nexport function buildPageClientContext({\n marks,\n readsPage,\n}: {\n marks: PageMark[];\n /** The org's page-context feature as the embed narrowed it. */\n readsPage: boolean;\n}): Record<string, unknown> | undefined {\n if (!readsPage) return undefined;\n\n const context: Record<string, unknown> = {};\n\n const currentMarks = marks.flatMap((mark) => {\n const current = pageMarkForSend(mark);\n return current ? [current] : [];\n });\n if (currentMarks.length > 0) {\n // `page_marks` is the rich payload for THIS turn; `picked_elements` is\n // the key the backend persists and re-surfaces on later turns.\n context['page_marks'] = currentMarks;\n context['picked_elements'] = pickedElementsFromMarks(currentMarks);\n }\n\n const { controls, truncated } = readPageControls();\n if (controls.length > 0) {\n context['page_controls'] = controls;\n if (truncated) context['page_controls_truncated'] = true;\n }\n\n return Object.keys(context).length > 0 ? context : undefined;\n}\n","import {\n useAgentChatUi,\n type PendingPageAction,\n} from '@opencx/widget-react-headless';\nimport React from 'react';\nimport { Button } from './lib/button';\n\n/** What the agent is about to do, said plainly. */\nconst VERBS: Record<string, string> = {\n click: 'click',\n fill: 'type into',\n select: 'change',\n check: 'switch on',\n uncheck: 'switch off',\n};\n\n/**\n * The moment the visitor decides.\n *\n * It names the control — the control's own name, read off their page, not\n * anything the agent wrote — because \"Allow this action?\" is a question\n * nobody reads, and \"Allow the agent to click Cancel subscription?\" is a\n * question everybody reads.\n *\n * One request at a time. No declines this call; any later request must ask\n * for its own confirmation before touching the page.\n */\nexport function PageActionCard({ request }: { request: PendingPageAction }) {\n const { resolvePageAction } = useAgentChatUi();\n const verb = VERBS[request.action] ?? request.action;\n const proposedValue =\n request.action === 'select'\n ? (request.valueLabel ?? request.value)\n : request.value;\n\n return (\n <section\n aria-label={`Allow the agent to ${verb} ${request.controlName}`}\n data-component=\"chat/page_action\"\n className=\"min-w-0 rounded-2xl border border-foreground/10 bg-background p-2 text-foreground\"\n >\n <p className=\"px-1 pb-2 text-sm\">\n Let the agent {verb}{' '}\n <span className=\"font-medium\">{request.controlName}</span> on this page?\n </p>\n {(request.action === 'fill' || request.action === 'select') &&\n request.value !== undefined && (\n <div className=\"mb-2 max-h-40 overflow-auto rounded-lg bg-foreground/5 px-2 py-1 text-sm\">\n <span className=\"font-medium\">New value: </span>\n <span className=\"whitespace-pre-wrap break-words\">\n {proposedValue === '' ? '(empty)' : proposedValue}\n </span>\n </div>\n )}\n <div className=\"flex gap-2\">\n <Button\n size=\"sm\"\n className=\"flex-1\"\n onClick={() => resolvePageAction(request.callId, true)}\n >\n Allow\n </Button>\n <Button\n size=\"sm\"\n variant=\"outline\"\n className=\"flex-1\"\n onClick={() => resolvePageAction(request.callId, false)}\n >\n No\n </Button>\n </div>\n </section>\n );\n}\n","import { cn } from '../../components/lib/utils/cn';\n\n/**\n * The composer's tool row. Every control in it — attach, dictate, mark page,\n * send, and whatever a shell slots in through `trailingActions` — is the same\n * round 32px button, so the row reads as one set of tools rather than as\n * buttons that happen to sit next to each other. `Button` already carries the\n * press scale and the transition, so this is only the shape.\n */\nexport const COMPOSER_TOOL_BUTTON =\n 'rounded-full size-8 flex items-center justify-center p-0 overflow-hidden';\n\n/**\n * A tool currently armed — dictation listening, mark mode waiting for a click.\n * Filled like the send button so the mode is unmistakable, and identical\n * across the tools so \"armed\" looks like one state, not two.\n */\nexport const COMPOSER_TOOL_ARMED =\n 'bg-primary text-primary-foreground hover:bg-primary/90 hover:text-primary-foreground';\n\n/**\n * The remove (×) control on the page pill in the composer's attached-context\n * tray. Marks are tiles in the attachments row and carry their own overlay\n * control, like a file preview does.\n */\nexport const CONTEXT_CHIP_REMOVE = cn(\n 'rounded-full p-0.5 text-muted-foreground',\n 'hover:bg-muted hover:text-foreground',\n 'transition-transform active:scale-90',\n);\n","import { FileTextIcon, XIcon } from 'lucide-react';\nimport React from 'react';\nimport { cn } from '../components/lib/utils/cn';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { dc } from '../utils/data-component';\nimport { CONTEXT_CHIP_REMOVE } from '../screens/chat/composer-styles';\nimport type { PageEntity } from './usePageEntity';\n\n/**\n * The composer's page-context pill: the one thing on the host page the\n * visitor is looking at (Linear-style), so they can see what \"this\" will\n * mean to the agent before they send. Removable for a message that is not\n * about it.\n *\n * Flat, with no surface of its own: it sits in the composer's attached-context\n * tray, and the tray is already a surface. Marks are not here — they are\n * pictures, so they preview with the files.\n */\nexport function PageContextPill({\n entity,\n onRemove,\n}: {\n entity: PageEntity;\n onRemove: () => void;\n}) {\n const { t } = useTranslation();\n return (\n <div\n {...dc('chat/input_box/page_context_pill')}\n className={cn(\n 'flex items-center gap-1.5 max-w-full',\n 'rounded-full py-0.5 pe-1',\n 'text-xs text-foreground',\n )}\n title={`${entity.type}: ${entity.title}`}\n >\n <FileTextIcon className=\"size-3 shrink-0 text-primary\" />\n <span className=\"truncate max-w-48 font-medium\">{entity.title}</span>\n <button\n type=\"button\"\n aria-label={t('page_context_remove')}\n className={CONTEXT_CHIP_REMOVE}\n onClick={onRemove}\n >\n <XIcon className=\"size-3\" />\n </button>\n </div>\n );\n}\n","import {\n resolveConfigContext,\n type WidgetPageContext,\n} from '@opencx/widget-core';\nimport {\n useConfig,\n useHostLocation,\n useWidget,\n} from '@opencx/widget-react-headless';\nimport { z } from 'zod';\n\nconst entitySchema = z.object({\n type: z.string().min(1),\n id: z.string().min(1),\n title: z.string().min(1),\n meta: z.record(z.string(), z.unknown()).optional(),\n});\n\nexport type PageEntity = NonNullable<WidgetPageContext['entity']>;\n\n/**\n * The entity the host says the visitor is looking at, read the same way the\n * send reads it (`resolveConfigContext`, so a function-form `context` is\n * live). Null when the host set none or set something malformed — the pill\n * simply does not show, and the send still carries whatever the host sent.\n * Also null when page context is off for this embed (org feature narrowed\n * by `config.features.pageContext`): the agent will not read the page, so\n * the pill must not promise it. Re-read when the host navigates, so a\n * function-form `context` that follows the route is reflected in the pill\n * without a reload.\n */\nexport function usePageEntity(): PageEntity | null {\n const config = useConfig();\n const { widgetCtx } = useWidget();\n useHostLocation();\n if (!widgetCtx.features.pageContext) return null;\n const parsed = entitySchema.safeParse(\n resolveConfigContext(config)?.['entity'],\n );\n return parsed.success ? parsed.data : null;\n}\n","import type { CSSProperties } from 'react';\n\nexport type PageMarkTheme = {\n accent: string;\n surface: string;\n foreground: string;\n mutedForeground: string;\n border: string;\n /**\n * Document layers, relative to the widget's own. Drawn marks and the hover\n * frame sit just UNDER the widget: they belong to the page, and a mark\n * that runs beneath the panel reads as the page being marked, not as\n * scribble on the chat. The note editor alone sits above, so it can be\n * typed into wherever the mark landed.\n */\n inkZIndex: number;\n chromeZIndex: number;\n editorZIndex: number;\n};\n\ntype PageMarkCssVars =\n | CSSProperties\n | { [key: `--opencx-${string}`]: string | number | undefined };\n\nfunction readColor(\n cssVars: PageMarkCssVars,\n name: `--opencx-${string}`,\n): string {\n const value = Object.entries(cssVars).find(([key]) => key === name)?.[1];\n return typeof value === 'string' ? `hsl(${value})` : 'currentColor';\n}\n\n/** Concrete colors and document layers for page-mark UI, which is portaled\n * outside the iframe and therefore cannot inherit the widget's CSS variables. */\nexport function resolvePageMarkTheme({\n cssVars,\n primaryColor,\n contentZIndex,\n}: {\n cssVars: PageMarkCssVars;\n primaryColor: string;\n contentZIndex: number;\n}): PageMarkTheme {\n return {\n accent: primaryColor,\n surface: readColor(cssVars, '--opencx-background'),\n foreground: readColor(cssVars, '--opencx-foreground'),\n mutedForeground: readColor(cssVars, '--opencx-muted-foreground'),\n border: readColor(cssVars, '--opencx-border'),\n inkZIndex: contentZIndex - 2,\n chromeZIndex: contentZIndex - 1,\n editorZIndex: contentZIndex + 1,\n };\n}\n","import type { TranslationKeyU } from '@opencx/widget-core';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useHostPortal } from '../companion/useHostPortal';\nimport { useTheme } from '../hooks/useTheme';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { MARK_SHAPES, type MarkShape } from './page-mark';\nimport { resolvePageMarkTheme, type PageMarkTheme } from './page-mark-theme';\nimport type { MarkDraft, MarkHover } from './usePageMarking';\n\n/**\n * Mark-mode visuals, rendered on the HOST page: a hint bar while armed, a\n * hover frame over the element under the cursor, and — once a mark is placed\n * — its editor: corner handles showing where to grab, plus one card carrying\n * the shape palette and the note. The mark itself is notation ink anchored in\n * page coordinates, so it scrolls with the content.\n *\n * Everything here is pointer-inert except the editor card: the gestures live\n * on the host document (see `usePageMarking`), and an overlay that swallowed\n * pointer events would blind them.\n */\nexport function PageMarkOverlay({\n isActive,\n draft,\n hover,\n onShapeChange,\n onAttach,\n onDiscard,\n}: {\n isActive: boolean;\n draft: MarkDraft | null;\n hover: MarkHover | null;\n onShapeChange: (shape: MarkShape) => void;\n onAttach: (note: string) => void;\n onDiscard: () => void;\n}) {\n const target = useHostPortal();\n const { theme, cssVars } = useTheme();\n const { t } = useTranslation();\n if (!target || !isActive) return null;\n\n const markTheme = resolvePageMarkTheme({\n cssVars,\n primaryColor: theme.primaryColor,\n contentZIndex: theme.widgetContentContainer.zIndex,\n });\n const { accent } = markTheme;\n\n return createPortal(\n <div data-opencx-overlay=\"\" style={{ pointerEvents: 'none' }}>\n <style>{`\n @keyframes opencx-mark-hint-in {\n from { opacity: 0; transform: translateX(-50%) translateY(-6px); }\n to { opacity: 1; transform: translateX(-50%) translateY(0); }\n }\n @keyframes opencx-mark-editor-in {\n from { opacity: 0; transform: translateY(4px); }\n to { opacity: 1; transform: translateY(0); }\n }\n @keyframes opencx-mark-frame-in {\n from { opacity: 0; transform: scale(1.015); }\n to { opacity: 1; transform: scale(1); }\n }\n @media (prefers-reduced-motion: reduce) {\n [data-opencx-mark-hint], [data-opencx-mark-editor],\n [data-opencx-mark-frame] { animation: none !important; }\n }\n `}</style>\n\n {!draft && (\n <>\n <div\n data-opencx-mark-hint=\"\"\n style={{\n position: 'fixed',\n top: 16,\n left: '50%',\n transform: 'translateX(-50%)',\n zIndex: markTheme.chromeZIndex,\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n background: `color-mix(in srgb, ${markTheme.surface} 92%, transparent)`,\n backdropFilter: 'blur(8px)',\n WebkitBackdropFilter: 'blur(8px)',\n color: markTheme.foreground,\n font: '500 12px/1.4 system-ui, sans-serif',\n padding: '7px 12px 7px 10px',\n borderRadius: 999,\n whiteSpace: 'nowrap',\n boxShadow: `0 0 0 1px ${markTheme.border}, 0 8px 24px color-mix(in srgb, ${markTheme.foreground} 14%, transparent)`,\n animation:\n 'opencx-mark-hint-in 200ms cubic-bezier(0.23, 1, 0.32, 1)',\n }}\n >\n <span\n style={{\n width: 7,\n height: 7,\n borderRadius: 999,\n background: accent,\n }}\n />\n {t('page_mark_hint')}\n <KeyCap theme={markTheme}>{t('page_mark_escape')}</KeyCap>\n </div>\n\n {/* Hover frame, keyed per hovered ELEMENT so switching targets\n remounts crisply instead of morph-tweening across the screen. */}\n {hover && (\n <div\n key={hover.key}\n data-opencx-mark-frame=\"\"\n style={{\n position: 'fixed',\n left: hover.rect.x - 4,\n top: hover.rect.y - 4,\n width: hover.rect.width + 8,\n height: hover.rect.height + 8,\n zIndex: markTheme.chromeZIndex,\n borderRadius: 10,\n boxShadow: `0 0 0 2px ${markTheme.surface}, 0 0 0 3.5px ${accent}, 0 12px 32px color-mix(in srgb, ${markTheme.foreground} 16%, transparent)`,\n animation:\n 'opencx-mark-frame-in 140ms cubic-bezier(0.23, 1, 0.32, 1)',\n transitionProperty: 'left, top, width, height',\n transitionDuration: '90ms',\n transitionTimingFunction: 'cubic-bezier(0.23, 1, 0.32, 1)',\n pointerEvents: 'none',\n }}\n />\n )}\n </>\n )}\n\n {draft && (\n <>\n {/* Corner handles — affordance only; the grab logic hit-tests the\n same corners on the host document, and the cursor changes there. */}\n {(\n [\n [draft.rect.x, draft.rect.y],\n [draft.rect.x + draft.rect.width, draft.rect.y],\n [draft.rect.x, draft.rect.y + draft.rect.height],\n [\n draft.rect.x + draft.rect.width,\n draft.rect.y + draft.rect.height,\n ],\n ] as const\n ).map(([x, y], i) => (\n <div\n key={i}\n style={{\n position: 'fixed',\n left: x - 5,\n top: y - 5,\n width: 10,\n height: 10,\n borderRadius: 999,\n background: markTheme.surface,\n boxShadow: `0 0 0 2px ${accent}, 0 2px 6px color-mix(in srgb, ${markTheme.foreground} 25%, transparent)`,\n zIndex: markTheme.chromeZIndex,\n pointerEvents: 'none',\n }}\n />\n ))}\n <MarkEditorCard\n key=\"editor\"\n draft={draft}\n theme={markTheme}\n onShapeChange={onShapeChange}\n onAttach={onAttach}\n onDiscard={onDiscard}\n />\n </>\n )}\n </div>,\n target,\n );\n}\n\nfunction KeyCap({\n children,\n theme,\n}: {\n children: React.ReactNode;\n theme: PageMarkTheme;\n}) {\n return (\n <span\n style={{\n font: '600 10px/1 system-ui, sans-serif',\n color: theme.mutedForeground,\n background: `color-mix(in srgb, ${theme.foreground} 7%, transparent)`,\n border: `1px solid ${theme.border}`,\n borderRadius: 5,\n padding: '3px 5px 2px',\n }}\n >\n {children}\n </span>\n );\n}\n\n/**\n * Each shape as the mark it makes, drawn rather than lettered — a palette of\n * glyphs reads at a glance where eight text labels would not.\n */\nconst SHAPE_GLYPH: Record<MarkShape, React.ReactNode> = {\n box: <rect x=\"3\" y=\"5\" width=\"14\" height=\"10\" rx=\"1\" />,\n circle: <ellipse cx=\"10\" cy=\"10\" rx=\"7\" ry=\"5.5\" />,\n arrow: (\n <>\n <path d=\"M3 10h13\" />\n <path d=\"M12 6l4 4-4 4\" />\n </>\n ),\n bracket: <path d=\"M7 4H4v12h3\" />,\n underline: (\n <>\n <path d=\"M5 8h10\" opacity=\"0.35\" />\n <path d=\"M4 14h12\" />\n </>\n ),\n highlight: (\n <>\n <rect\n x=\"3\"\n y=\"7\"\n width=\"14\"\n height=\"6\"\n rx=\"1\"\n fill=\"currentColor\"\n opacity=\"0.3\"\n stroke=\"none\"\n />\n <path d=\"M5 10h10\" />\n </>\n ),\n 'strike-through': (\n <>\n <path d=\"M6 6h8\" opacity=\"0.35\" />\n <path d=\"M6 14h8\" opacity=\"0.35\" />\n <path d=\"M4 10h12\" />\n </>\n ),\n 'crossed-off': (\n <>\n <path d=\"M4 5l12 10\" />\n <path d=\"M16 5L4 15\" />\n </>\n ),\n};\n\nconst SHAPE_LABEL_KEY = {\n box: 'page_mark_shape_box',\n circle: 'page_mark_shape_circle',\n arrow: 'page_mark_shape_arrow',\n bracket: 'page_mark_shape_bracket',\n underline: 'page_mark_shape_underline',\n highlight: 'page_mark_shape_highlight',\n 'strike-through': 'page_mark_shape_strike_through',\n 'crossed-off': 'page_mark_shape_crossed_off',\n} as const satisfies Record<MarkShape, TranslationKeyU>;\n\n/**\n * The editor card: the shape palette on top, the note below. Anchored under\n * the mark (clamped into the viewport) and following it as it moves. Enter\n * attaches — with or without a note — Esc discards the mark. The overlay root\n * is pointer-inert, so the card re-enables pointer events for itself only.\n */\nfunction MarkEditorCard({\n draft,\n theme,\n onShapeChange,\n onAttach,\n onDiscard,\n}: {\n draft: MarkDraft;\n theme: PageMarkTheme;\n onShapeChange: (shape: MarkShape) => void;\n onAttach: (note: string) => void;\n onDiscard: () => void;\n}) {\n const { accent } = theme;\n const { t } = useTranslation();\n const [note, setNote] = useState('');\n const inputRef = useRef<HTMLInputElement>(null);\n useEffect(() => {\n inputRef.current?.focus();\n }, []);\n\n const CARD_W = 320;\n const vw = window.innerWidth;\n const vh = window.innerHeight;\n const { rect } = draft;\n const left = Math.max(\n 12,\n Math.min(rect.x + rect.width / 2 - CARD_W / 2, vw - CARD_W - 12),\n );\n const below = rect.y + rect.height + 16;\n const top = below + 120 > vh ? Math.max(12, rect.y - 116) : below;\n\n return (\n <div\n data-opencx-mark-editor=\"\"\n style={{\n position: 'fixed',\n left,\n top,\n width: CARD_W,\n zIndex: theme.editorZIndex,\n pointerEvents: 'auto',\n display: 'flex',\n flexDirection: 'column',\n gap: 6,\n background: `color-mix(in srgb, ${theme.surface} 96%, transparent)`,\n backdropFilter: 'blur(8px)',\n WebkitBackdropFilter: 'blur(8px)',\n padding: 8,\n borderRadius: 14,\n boxShadow: `0 0 0 1px ${theme.border}, 0 12px 32px color-mix(in srgb, ${theme.foreground} 18%, transparent)`,\n animation: 'opencx-mark-editor-in 180ms cubic-bezier(0.23, 1, 0.32, 1)',\n }}\n >\n <div style={{ display: 'flex', gap: 2, justifyContent: 'space-between' }}>\n {MARK_SHAPES.map((shape) => {\n const selected = shape === draft.shape;\n const shapeLabel = t(SHAPE_LABEL_KEY[shape]);\n return (\n <button\n key={shape}\n type=\"button\"\n title={shapeLabel}\n aria-label={t('page_mark_shape_aria', { shape: shapeLabel })}\n aria-pressed={selected}\n onClick={() => onShapeChange(shape)}\n style={{\n border: 'none',\n cursor: 'pointer',\n borderRadius: 8,\n width: 32,\n height: 28,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: selected ? accent : 'transparent',\n color: selected ? theme.surface : theme.mutedForeground,\n }}\n >\n <svg\n width=\"20\"\n height=\"20\"\n viewBox=\"0 0 20 20\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"1.6\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n {SHAPE_GLYPH[shape]}\n </svg>\n </button>\n );\n })}\n </div>\n\n <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>\n <input\n ref={inputRef}\n value={note}\n onChange={(e) => setNote(e.target.value)}\n onKeyDown={(e) => {\n if (e.key === 'Enter') {\n e.preventDefault();\n onAttach(note);\n } else if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n onDiscard();\n }\n }}\n placeholder={t('page_mark_note_placeholder')}\n style={{\n flex: 1,\n minWidth: 0,\n border: 'none',\n outline: 'none',\n background: 'transparent',\n color: theme.foreground,\n font: '500 13px/1.4 system-ui, sans-serif',\n paddingInlineStart: 4,\n }}\n />\n <button\n type=\"button\"\n aria-label={t('page_mark_attach')}\n onClick={() => onAttach(note)}\n style={{\n border: 'none',\n borderRadius: 999,\n width: 26,\n height: 26,\n flexShrink: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: accent,\n color: theme.surface,\n font: '600 13px/1 system-ui, sans-serif',\n cursor: 'pointer',\n }}\n >\n ↑\n </button>\n </div>\n </div>\n );\n}\n","import { PenLineIcon, XIcon } from 'lucide-react';\nimport React from 'react';\nimport { cn } from '../components/lib/utils/cn';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { dc } from '../utils/data-component';\nimport type { PageMark } from './page-mark';\nimport { MarkThumbnail } from './MarkThumbnail';\nimport { useMarkThumbnail } from './useMarkThumbnail';\n\n/**\n * One page mark previewed in the composer's attachment row — the same square\n * tile a file gets, because a mark IS a picture the message carries. Shows\n * the region's actual pixels (the focus element's snapshot, rasterized at\n * commit) the moment it lands, with the visitor's note captioned over them;\n * until then — and whenever a snapshot isn't possible — the pen glyph stands\n * in, with the label captioned the same way so the tile still says what it\n * is. Removing it un-draws the mark from the host page.\n */\nexport function PageMarkPill({\n mark,\n onRemove,\n}: {\n mark: PageMark;\n onRemove: () => void;\n}) {\n const { t } = useTranslation();\n const thumb = useMarkThumbnail(mark);\n\n const label = mark.note ?? mark.elements[0]?.name ?? t('page_mark_region');\n const removeLabel = t('page_mark_remove', { label });\n const hoverTitle = mark.elements.map((el) => el.name).join(', ');\n\n if (thumb) {\n return (\n <MarkThumbnail\n {...dc('chat/input_box/page_mark_pill')}\n className=\"group\"\n shape=\"tile\"\n src={thumb}\n alt={label}\n title={hoverTitle}\n note={mark.note}\n >\n <button\n type=\"button\"\n aria-label={removeLabel}\n className={cn(\n 'absolute top-1 end-1 rounded-full p-0.5',\n 'bg-foreground/60 text-background backdrop-blur-sm',\n 'opacity-0 group-hover:opacity-100 focus-visible:opacity-100',\n 'transition-opacity active:scale-90',\n )}\n onClick={onRemove}\n >\n <XIcon className=\"size-3\" />\n </button>\n </MarkThumbnail>\n );\n }\n\n // No picture (yet, or ever): the same tile with the pen glyph standing in\n // and the label captioned where the note would be, so the row keeps one\n // shape whatever a mark managed to capture.\n return (\n <div\n {...dc('chat/input_box/page_mark_pill')}\n title={hoverTitle}\n className={cn(\n 'group relative size-12 shrink-0 overflow-hidden',\n 'flex items-center justify-center',\n 'rounded-2xl bg-background ring-1 ring-border',\n )}\n >\n <PenLineIcon className=\"size-4 shrink-0 text-primary\" />\n <span\n className={cn(\n 'absolute inset-x-0 bottom-0 truncate px-1.5 py-0.5',\n 'bg-gradient-to-t from-foreground/70 to-foreground/0',\n 'text-[10px] font-medium leading-tight text-background',\n )}\n >\n {label}\n </span>\n <button\n type=\"button\"\n aria-label={removeLabel}\n className={cn(\n 'absolute top-1 end-1 rounded-full p-0.5',\n 'bg-foreground/60 text-background backdrop-blur-sm',\n 'opacity-0 group-hover:opacity-100 focus-visible:opacity-100',\n 'transition-opacity active:scale-90',\n )}\n onClick={onRemove}\n >\n <XIcon className=\"size-3\" />\n </button>\n </div>\n );\n}\n","/**\n * The widget's keyboard shortcuts, as data. Every shortcut is a named action\n * here; handlers match events with `matchesBinding(event, WIDGET_KEYBINDINGS[a])`\n * and buttons render hints with `formatBinding(WIDGET_KEYBINDINGS[a])` — never\n * a hardcoded key check or a literal \"⌘…\" string in a component, so a binding\n * can never drift from the hint that advertises it.\n *\n * `Mod` resolves per platform: ⌘ on Apple devices, Ctrl everywhere else — the\n * widget runs on whatever machine the host page is viewed on.\n *\n * Scope rule for an EMBEDDED widget: bindings with modifiers are only\n * listened for while the panel is open, and single-key bindings only inside\n * the widget's own iframe/composer. The host page's shortcuts are not ours\n * to shadow.\n */\n\nexport type WidgetActionId =\n | 'close-panel'\n | 'toggle-fullscreen'\n | 'send'\n | 'send-alt'\n | 'history-prev'\n | 'history-next';\n\nexport const WIDGET_KEYBINDINGS: Record<WidgetActionId, string> = {\n /** Dismiss the companion panel: fullscreen drops back to its layout, anything else goes to the pill. */\n 'close-panel': 'Escape',\n /** Toggle the companion chat panel between fullscreen and its prior layout. */\n 'toggle-fullscreen': 'Mod+Shift+F',\n /** Send the composed message (Shift+Enter inserts a newline). */\n send: 'Enter',\n /**\n * Muscle-memory alias for `send`, from every other chat app. Deliberately\n * NOT advertised in the send button's hint — that shows the primary\n * binding — but it lives here so the handler never hardcodes it.\n */\n 'send-alt': 'Mod+Enter',\n /**\n * Start walking sent-message history backwards (only from an empty\n * composer, or with the caret at the very start), and keep walking once in.\n */\n 'history-prev': 'ArrowUp',\n /** Walk recall forward; past the newest entry the stashed draft returns. */\n 'history-next': 'ArrowDown',\n};\n\nexport function isApplePlatform(): boolean {\n if (typeof navigator === 'undefined') return false;\n return /Mac|iPhone|iPad|iPod/.test(navigator.platform || navigator.userAgent);\n}\n\n/** True when the event matches a \"Mod+Shift+F\"-style binding exactly —\n * extra held modifiers disqualify, so bindings never fire by accident. */\nexport function matchesBinding(\n event: Pick<\n KeyboardEvent,\n 'key' | 'metaKey' | 'ctrlKey' | 'altKey' | 'shiftKey'\n >,\n binding: string,\n apple: boolean = isApplePlatform(),\n): boolean {\n const parts = binding.split('+');\n const key = parts.at(-1) ?? '';\n const mods = new Set(parts.slice(0, -1));\n const wantMeta = mods.has('Cmd') || (mods.has('Mod') && apple);\n const wantCtrl = mods.has('Ctrl') || (mods.has('Mod') && !apple);\n if (event.metaKey !== wantMeta) return false;\n if (event.ctrlKey !== wantCtrl) return false;\n if (event.altKey !== mods.has('Alt')) return false;\n if (event.shiftKey !== mods.has('Shift')) return false;\n return event.key.toLowerCase() === key.toLowerCase();\n}\n\nconst APPLE_MOD_SYMBOLS: Record<string, string> = {\n Mod: '⌘',\n Cmd: '⌘',\n Ctrl: '⌃',\n Alt: '⌥',\n Shift: '⇧',\n};\n\n/** Keys whose display form is a compact symbol on every platform. */\nconst KEY_SYMBOLS: Record<string, string> = {\n Escape: 'Esc',\n Enter: '⏎',\n ArrowUp: '↑',\n ArrowDown: '↓',\n ArrowLeft: '←',\n ArrowRight: '→',\n};\n\n/** \"Mod+Shift+F\" → \"⌘⇧F\" on Apple platforms, \"Ctrl+Shift+F\" elsewhere. */\nexport function formatBinding(\n binding: string,\n apple: boolean = isApplePlatform(),\n): string {\n const parts = binding.split('+');\n const key = parts.at(-1) ?? '';\n const mods = parts.slice(0, -1);\n const keyLabel =\n KEY_SYMBOLS[key] ?? (key.length === 1 ? key.toUpperCase() : key);\n if (apple) {\n return [...mods.map((m) => APPLE_MOD_SYMBOLS[m] ?? m), keyLabel].join('');\n }\n return [...mods.map((m) => (m === 'Mod' ? 'Ctrl' : m)), keyLabel].join('+');\n}\n","import { log } from '@opencx/widget-core';\nimport type { FileWithProgress } from '@opencx/widget-react-headless';\nimport {\n AlertCircle,\n FileAudio2Icon,\n FileIcon,\n FileSpreadsheet,\n FileText,\n FileVideo2Icon,\n Loader2,\n XIcon,\n} from 'lucide-react';\nimport React, { useEffect, useState } from 'react';\nimport type { Accept } from 'react-dropzone';\nimport { Tooltippy } from '../../components/lib/tooltip';\nimport { cn } from '../../components/lib/utils/cn';\nimport { useTranslation } from '../../hooks/useTranslation';\nimport {\n getSpreadsheet,\n SPREADSHEET_ACCEPT,\n VIDEO_ACCEPT,\n} from '../../utils/attachment-kind';\n\n// Mirrors the server-side MAX_WIDGET_UPLOAD_BYTES cap on /widget/v2/upload.\nexport const MAX_FILE_BYTES = 25 * 1024 * 1024;\n\n// Attachment formats every chat accepts, regardless of assignee.\nexport const BASE_FILE_ACCEPT = {\n 'application/pdf': ['.pdf'],\n ...SPREADSHEET_ACCEPT,\n ...VIDEO_ACCEPT,\n} satisfies Accept;\n\nexport const HANDED_OFF_FILE_ACCEPT = {\n 'text/*': ['.txt'],\n 'image/*': ['.png', '.jpg', '.jpeg', '.gif'],\n ...BASE_FILE_ACCEPT,\n} satisfies Accept;\n\nexport const AI_FILE_ACCEPT = {\n 'image/png': ['.png'],\n 'image/jpeg': ['.jpg', '.jpeg'],\n 'image/gif': ['.gif'],\n 'image/webp': ['.webp'],\n ...BASE_FILE_ACCEPT,\n} satisfies Accept;\n\nfunction UploadStatusIcon({ status }: { status: FileWithProgress['status'] }) {\n switch (status) {\n case 'uploading':\n return <Loader2 className=\"size-4 animate-spin\" />;\n case 'error':\n return <AlertCircle className=\"size-4 text-destructive\" />;\n default:\n return null;\n }\n}\n\nfunction UploadFileContent({\n file,\n fileContent,\n}: {\n file: File;\n fileContent: string | ArrayBuffer | null;\n}) {\n const fileType = file.type.split('/')[0];\n\n if (fileType === 'image' && fileContent) {\n return (\n <img\n src={typeof fileContent === 'string' ? fileContent : ''}\n className=\"object-cover bg-secondary size-full\"\n alt={file.name}\n />\n );\n }\n if (fileType === 'audio') {\n return <FileAudio2Icon className=\"size-4 text-muted-foreground\" />;\n }\n if (fileType === 'video') {\n return <FileVideo2Icon className=\"size-4 text-muted-foreground\" />;\n }\n if (file.type === 'application/pdf') {\n return <FileText className=\"size-4 text-muted-foreground\" />;\n }\n if (getSpreadsheet({ type: file.type, name: file.name })) {\n return <FileSpreadsheet className=\"size-4 text-muted-foreground\" />;\n }\n return <FileIcon className=\"size-4 text-muted-foreground\" />;\n}\n\nexport function UploadPreview({\n file: { status, file, error },\n onCancel,\n}: {\n file: FileWithProgress;\n onCancel: () => void;\n}) {\n const { t } = useTranslation();\n const [fileContent, setFileContent] = useState<string | ArrayBuffer | null>(\n null,\n );\n\n useEffect(() => {\n if (!file.type.startsWith('image/')) return;\n\n const reader = new FileReader();\n reader.onload = () => setFileContent(reader.result as string);\n reader.onerror = () => log.error('failed to read file for preview');\n reader.readAsDataURL(file);\n\n return () => reader.abort();\n }, [file]);\n\n return (\n <Tooltippy\n side=\"bottom\"\n content={\n status === 'error' ? (\n <span className=\"text-destructive\">\n {t('upload_failed', { error: error ?? '' })}\n </span>\n ) : (\n file.name\n )\n }\n >\n <div\n className={cn(\n status === 'uploading' && 'opacity-50',\n 'group',\n 'size-12 border rounded-2xl overflow-hidden relative',\n 'flex items-center justify-center shrink-0',\n )}\n >\n <div className=\"absolute inset-0 flex items-center justify-center\">\n <UploadStatusIcon status={status} />\n </div>\n <button\n type=\"button\"\n className={cn(\n 'absolute bg-foreground/50 inset-0 size-full z-10',\n 'flex items-center justify-center',\n 'opacity-0 group-hover:opacity-100 transition',\n )}\n onClick={onCancel}\n aria-label={t('remove_attachment')}\n >\n <XIcon className=\"size-4 text-primary-foreground\" />\n </button>\n <UploadFileContent file={file} fileContent={fileContent} />\n </div>\n </Tooltippy>\n );\n}\n","import { useAgentChatUi, useMessages } from '@opencx/widget-react-headless';\nimport { AnimatePresence } from 'framer-motion';\nimport { CornerDownLeftIcon, XIcon } from 'lucide-react';\nimport React, { useMemo } from 'react';\nimport { MotionDiv__VerticalReveal } from '../../../components/lib/MotionDiv__VerticalReveal';\nimport { useTranslation } from '../../../hooks/useTranslation';\nimport { dc } from '../../../utils/data-component';\n\n/**\n * The multi-send queue pill (Cursor-style), docked above the composer.\n *\n * Messages sent while a turn is streaming wait here — NOT in the transcript —\n * until their own turn starts (when the live turn finishes, errors, or is\n * stopped), at which point they move into the message list right above the\n * response they're about to get. Each row can be removed before it's sent.\n *\n * A click on the header's ↵ or on a queued row sends the queue now: it\n * stops the live turn, and the queue drains into the next one — the same\n * thing Enter on an empty composer does.\n *\n * Renders nothing outside an agent surface (bot-chat embeds: the default context\n * has no queued messages) or when the queue is empty.\n */\nexport function QueuedSendsPill() {\n const { queuedUserMessages, removeQueued, stop } = useAgentChatUi();\n const {\n messagesState: { messages },\n } = useMessages();\n const { t } = useTranslation();\n\n // Guard against the one-frame overlap where a message was just drained into\n // the transcript but the queue snapshot hasn't recomputed yet.\n const pending = useMemo(\n () =>\n queuedUserMessages.filter((q) => !messages.some((m) => m.id === q.id)),\n [queuedUserMessages, messages],\n );\n\n return (\n <AnimatePresence>\n {pending.length > 0 && (\n <MotionDiv__VerticalReveal key=\"queued-sends-pill\">\n <div\n {...dc('chat/queued_sends/root')}\n className=\"mb-1 rounded-2xl border border-muted-foreground/15 bg-background shadow-sm\"\n >\n <div\n {...dc('chat/queued_sends/header')}\n className=\"flex items-center justify-between px-3 pt-2 pb-1\"\n >\n <span className=\"text-[11px] font-medium uppercase tracking-wide text-muted-foreground\">\n {t('queued_label', { count: pending.length })}\n </span>\n <button\n type=\"button\"\n {...dc('chat/queued_sends/send_now')}\n aria-label={t('send_queued_now')}\n title={t('send_queued_now')}\n onClick={stop}\n className=\"rounded-md p-0.5 text-muted-foreground/60 transition-colors hover:text-foreground hover:bg-muted\"\n >\n <CornerDownLeftIcon className=\"size-3\" />\n </button>\n </div>\n <ul\n {...dc('chat/queued_sends/list')}\n className=\"flex flex-col pb-1\"\n >\n {pending.map((message) => (\n <li\n key={message.id}\n {...dc('chat/queued_sends/item')}\n className=\"group flex items-center gap-2 px-3 py-1\"\n >\n <button\n type=\"button\"\n title={t('send_queued_now')}\n onClick={stop}\n className=\"min-w-0 flex-1 truncate text-start text-xs text-foreground/80 hover:text-foreground\"\n >\n {message.content}\n </button>\n <button\n type=\"button\"\n {...dc('chat/queued_sends/remove')}\n aria-label={t('remove_queued_message')}\n onClick={() => removeQueued(message.id)}\n className=\"shrink-0 rounded-md p-0.5 text-muted-foreground/60 transition-colors hover:text-foreground hover:bg-muted\"\n >\n <XIcon className=\"size-3.5\" />\n </button>\n </li>\n ))}\n </ul>\n </div>\n </MotionDiv__VerticalReveal>\n )}\n </AnimatePresence>\n );\n}\n","import { DictationLevelSmoother } from '@opencx/widget-core';\nimport type { DictationStatus } from '@opencx/widget-core';\nimport { AnimatePresence } from 'framer-motion';\nimport { MicIcon } from 'lucide-react';\nimport React, { useEffect, useRef } from 'react';\nimport { MotionDiv } from '../../components/lib/MotionDiv';\nimport { Button } from '../../components/lib/button';\nimport { Tooltippy } from '../../components/lib/tooltip';\nimport { cn } from '../../components/lib/utils/cn';\nimport { useTranslation } from '../../hooks/useTranslation';\nimport { dc } from '../../utils/data-component';\nimport { COMPOSER_TOOL_ARMED, COMPOSER_TOOL_BUTTON } from './composer-styles';\n\n/**\n * Compact 4-bar voice meter driven by the smoothed mic level (rAF, no\n * re-renders). The moving bars ARE the \"it's live\" signal.\n */\nfunction DictationLevelBars({ levelRef }: { levelRef: { current: number } }) {\n const barsRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n let raf = 0;\n const smoother = new DictationLevelSmoother({ attack: 0.2, release: 0.07 });\n const lastWritten: string[] = [];\n const tick = () => {\n const bars = barsRef.current?.children;\n if (bars) {\n const smoothed = smoother.next(levelRef.current);\n for (let i = 0; i < bars.length; i++) {\n const bar = bars[i];\n if (bar instanceof HTMLElement) {\n const sway = 0.75 + 0.25 * Math.sin(Date.now() / 260 + i * 1.7);\n const next = `scaleY(${Math.max(0.25, Math.min(1, smoothed * 1.8 * sway)).toFixed(3)})`;\n // Skip identical writes — silence otherwise churns style attrs 60x/s.\n if (lastWritten[i] !== next) {\n bar.style.transform = next;\n lastWritten[i] = next;\n }\n }\n }\n }\n raf = requestAnimationFrame(tick);\n };\n raf = requestAnimationFrame(tick);\n return () => cancelAnimationFrame(raf);\n }, [levelRef]);\n\n return (\n <div\n ref={barsRef}\n aria-hidden=\"true\"\n className=\"flex h-3.5 shrink-0 items-center gap-[3px]\"\n >\n {[0, 1, 2, 3].map((i) => (\n <span\n key={i}\n className=\"h-full w-[3px] origin-center scale-y-50 rounded-full bg-current transition-transform duration-100 ease-out\"\n />\n ))}\n </div>\n );\n}\n\n/**\n * Composer microphone toggle, mirroring the attach button. States:\n * idle → quiet mic glyph\n * connecting → spinning arc around the mic\n * listening → the mic crossfades into live voice bars that move as you talk\n */\nexport function DictationMicButton({\n status,\n levelRef,\n onToggle,\n onPrewarm,\n}: {\n status: DictationStatus;\n levelRef: { current: number };\n onToggle: () => void;\n /** Hover/focus pre-mints the session token so the click starts instantly. */\n onPrewarm: () => void;\n}) {\n const { t } = useTranslation();\n const listening = status === 'listening';\n const connecting = status === 'connecting';\n const label = listening || connecting ? t('stop_dictation') : t('dictate');\n\n return (\n <Tooltippy side=\"top\" align=\"start\" content={label}>\n <Button\n {...dc('chat/input_box/dictate_btn')}\n onClick={onToggle}\n // Never blur the textarea: dictation appends at the visitor's text.\n onPointerDown={(event) => event.preventDefault()}\n onPointerEnter={onPrewarm}\n onFocus={onPrewarm}\n aria-pressed={listening || connecting}\n aria-label={label}\n size=\"fit\"\n variant=\"ghost\"\n className={cn(\n 'relative',\n COMPOSER_TOOL_BUTTON,\n listening && COMPOSER_TOOL_ARMED,\n )}\n >\n {connecting && (\n <span\n aria-hidden=\"true\"\n className=\"pointer-events-none absolute inset-0.5 animate-spin rounded-full border-[1.5px] border-current/20 border-t-current\"\n />\n )}\n <AnimatePresence mode=\"wait\">\n {listening ? (\n <MotionDiv key=\"bars\" distance={0}>\n <DictationLevelBars levelRef={levelRef} />\n </MotionDiv>\n ) : (\n <MotionDiv key=\"mic\" distance={0}>\n <MicIcon className={cn('size-4', connecting && 'opacity-60')} />\n </MotionDiv>\n )}\n </AnimatePresence>\n </Button>\n </Tooltippy>\n );\n}\n","/**\n * Where a character index sits inside a textarea, in the textarea's own\n * coordinates. Textareas expose no caret geometry, so the text up to the\n * index is laid out again in a throwaway element wearing the same font,\n * padding, width and wrapping rules; a marker at its end is where the\n * character would be. Returns null when there is no layout (tests, SSR).\n */\nexport function caretPositionInTextarea(\n textarea: HTMLTextAreaElement,\n index: number,\n): { left: number; top: number } | null {\n const doc = textarea.ownerDocument;\n const view = doc.defaultView;\n if (!view) return null;\n const mirror = doc.createElement('div');\n copyTextLayoutStyles(textarea, mirror);\n Object.assign(mirror.style, {\n position: 'absolute',\n visibility: 'hidden',\n top: '0',\n left: '-9999px',\n height: 'auto',\n overflow: 'hidden',\n whiteSpace: 'pre-wrap',\n overflowWrap: 'break-word',\n width: `${textarea.clientWidth}px`,\n } satisfies Partial<CSSStyleDeclaration>);\n mirror.textContent = textarea.value.slice(0, index);\n const marker = doc.createElement('span');\n marker.textContent = '​';\n mirror.appendChild(marker);\n doc.body.appendChild(mirror);\n const left = marker.offsetLeft;\n const top = marker.offsetTop - textarea.scrollTop;\n mirror.remove();\n return { left, top };\n}\n\n/**\n * Give `target` the font, spacing and padding `textarea` resolved to — the\n * embedder's `cssOverrides` included — so text laid out in it lands where\n * the textarea lays it out. The composer's mention mirror needs this on every\n * render, the caret probe once.\n */\nexport function copyTextLayoutStyles(\n textarea: HTMLTextAreaElement,\n target: HTMLElement,\n): void {\n const view = textarea.ownerDocument.defaultView;\n if (!view) return;\n const style = view.getComputedStyle(textarea);\n for (const prop of MIRRORED_STYLES) {\n target.style.setProperty(prop, style.getPropertyValue(prop));\n }\n}\n\nconst MIRRORED_STYLES = [\n 'box-sizing',\n 'font-family',\n 'font-size',\n 'font-weight',\n 'font-style',\n 'letter-spacing',\n 'line-height',\n 'text-transform',\n 'text-indent',\n 'word-spacing',\n 'tab-size',\n 'padding-top',\n 'padding-right',\n 'padding-bottom',\n 'padding-left',\n 'border-top-width',\n 'border-right-width',\n 'border-bottom-width',\n 'border-left-width',\n] as const;\n","import type { WidgetMention } from '@opencx/widget-core';\nimport React, { useLayoutEffect, useState, type RefObject } from 'react';\nimport { createPortal } from 'react-dom';\nimport { DynamicIcon } from '../../components/lib/DynamicIcon';\nimport { cn } from '../../components/lib/utils/cn';\nimport { useTranslation } from '../../hooks/useTranslation';\nimport { dc } from '../../utils/data-component';\nimport { caretPositionInTextarea } from './caret-position';\nimport type { MentionGroup } from './useMentions';\n\n/** The menu's width; narrower when the composer is. */\nconst MENU_WIDTH = 300;\n/** The detail card beside the menu, when the frame has room for it. */\nconst DETAIL_WIDTH = 260;\nconst GAP = 8;\n/** The menu and its detail card are one surface, split in two. */\nconst MENU_SURFACE = 'rounded-xl border border-border bg-background shadow-lg';\n\n/**\n * The @-mention menu, sitting right above the `@` it belongs to (its start\n * edge on the `@`, its bottom edge on that line): results grouped by type under a small header, one line\n * per item (icon + title), a \"See N more\" row where a group is cut, and —\n * when `mentions.preview` is on and the frame is wide enough — the\n * highlighted item's description in a card beside the menu. Keyboard-driven\n * from the textarea (the hook handles ↑/↓/Enter/Tab/Escape there, so focus\n * never leaves the text); the mouse hovers to highlight and clicks to pick.\n *\n * Portaled to the frame's themed root and positioned against the composer:\n * the composer sits inside a footer that clips its overflow, so a menu that\n * grew upward in place was cut off at the footer's top edge. The root (not\n * the body) is the host because it carries the palette variables the menu's\n * colors resolve from — outside it `bg-background` paints nothing. The\n * composer changes height as pills and files come and go, so the placement\n * follows the anchor's size, not just the result list.\n */\nexport function MentionPicker({\n anchorRef,\n inputRef,\n anchorIndex,\n preview,\n groups,\n visible,\n searching,\n highlighted,\n onHighlight,\n onPick,\n onExpand,\n}: {\n /** The composer root the menu sits above. */\n anchorRef: RefObject<HTMLElement | null>;\n /** The textarea holding the `@`; the menu's start edge lines up with it. */\n inputRef: RefObject<HTMLTextAreaElement | null>;\n /** Index of that `@` in the text. */\n anchorIndex: number | null;\n /** Show the highlighted item's description beside the menu. */\n preview: boolean;\n groups: MentionGroup[];\n /** The rows top to bottom; `highlighted` indexes into it. */\n visible: WidgetMention[];\n searching: boolean;\n highlighted: number;\n onHighlight: (index: number) => void;\n onPick: (item: WidgetMention) => void;\n onExpand: (type: string) => void;\n}) {\n const { t } = useTranslation();\n const [placement, setPlacement] = useState<{\n left: number;\n width: number;\n top: number;\n detailBeside: boolean;\n } | null>(null);\n useLayoutEffect(() => {\n const anchor = anchorRef.current;\n if (!anchor) return;\n const view = anchor.ownerDocument.defaultView;\n // Anchored by its BOTTOM edge to the composer's top through a translate:\n // the frame document can be taller than the visible panel, so its inner\n // height is not a safe base for a `bottom` offset.\n const place = () => {\n const rect = anchor.getBoundingClientRect();\n const frameWidth = view?.innerWidth ?? rect.right;\n const width = Math.min(MENU_WIDTH, Math.max(0, frameWidth - 16));\n // Start under the `@` itself, pulled back only as far as the frame\n // edge demands.\n const input = inputRef.current;\n const at =\n input && anchorIndex !== null\n ? caretPositionInTextarea(input, anchorIndex)\n : null;\n const inputRect = input?.getBoundingClientRect();\n const wanted = at && inputRect ? inputRect.left + at.left : rect.left + 8;\n const left = Math.max(8, Math.min(wanted, frameWidth - 8 - width));\n // Its bottom edge hugs the line the `@` is on — not the composer card,\n // whose context tray would otherwise hold the menu a row too high.\n const top = at && inputRect ? inputRect.top + at.top - 4 : rect.top - 4;\n setPlacement({\n left,\n width,\n top,\n detailBeside:\n preview && left + width + GAP + DETAIL_WIDTH <= frameWidth - 8,\n });\n };\n place();\n view?.addEventListener('resize', place);\n const observer =\n typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(place);\n observer?.observe(anchor);\n return () => {\n view?.removeEventListener('resize', place);\n observer?.disconnect();\n };\n }, [anchorIndex, anchorRef, inputRef, preview, visible.length]);\n\n const host = anchorRef.current?.closest<HTMLElement>('[data-version]');\n if (!host || !placement) return null;\n if (visible.length === 0 && searching) return null;\n\n const current = visible[highlighted];\n const detail = current?.description ? current : null;\n let rowIndex = -1;\n\n return createPortal(\n <div\n {...dc('chat/input_box/mention_picker')}\n style={{\n position: 'fixed',\n left: placement.left,\n top: placement.top,\n transform: 'translateY(-100%)',\n }}\n className=\"z-50 flex items-end gap-2\"\n >\n <div\n role=\"listbox\"\n style={{ width: placement.width }}\n className={cn('flex max-h-72 flex-col overflow-hidden', MENU_SURFACE)}\n >\n <div className=\"min-h-0 flex-1 overflow-auto p-1\">\n {visible.length === 0 ? (\n <div className=\"px-2 py-1.5 text-xs text-muted-foreground\">\n {t('mentions_empty')}\n </div>\n ) : (\n groups.map((group) => (\n <div\n {...dc('chat/input_box/mention_picker/group')}\n key={group.type}\n role=\"group\"\n aria-label={group.type}\n >\n <div className=\"px-2 pb-0.5 pt-1.5 text-xs capitalize text-muted-foreground\">\n {group.type}\n </div>\n {group.items.map((item) => {\n const index = ++rowIndex;\n return (\n <button\n {...dc('chat/input_box/mention_picker/option')}\n key={`${item.type}:${item.id}`}\n type=\"button\"\n role=\"option\"\n aria-selected={index === highlighted}\n // Keep the textarea focused: a mousedown on the row\n // would blur it and close the menu before the click.\n onMouseDown={(event) => event.preventDefault()}\n onMouseEnter={() => onHighlight(index)}\n onClick={() => onPick(item)}\n className={cn(\n 'flex w-full items-center gap-2 rounded-lg px-2 py-1.5 text-start text-sm',\n index === highlighted\n ? 'bg-muted'\n : 'hover:bg-muted/60',\n )}\n >\n <MentionIcon item={item} />\n <span className=\"min-w-0 flex-1 truncate text-foreground\">\n {item.title}\n </span>\n </button>\n );\n })}\n {group.hidden > 0 && (\n <button\n {...dc('chat/input_box/mention_picker/more')}\n type=\"button\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => onExpand(group.type)}\n className={cn(\n 'w-full rounded-lg px-2 py-1 text-start text-xs',\n 'text-muted-foreground hover:bg-muted/60 hover:text-foreground',\n )}\n >\n {t('json_see_more', { count: String(group.hidden) })}\n </button>\n )}\n </div>\n ))\n )}\n </div>\n </div>\n {detail && placement.detailBeside && <MentionDetail item={detail} />}\n </div>,\n host,\n );\n}\n\n/** The preview card: icon tile, type, title, description. */\nfunction MentionDetail({ item }: { item: WidgetMention }) {\n return (\n <div\n {...dc('chat/input_box/mention_picker/detail')}\n style={{ width: DETAIL_WIDTH }}\n className={cn('flex gap-3 p-3', MENU_SURFACE)}\n >\n <span className=\"flex size-8 shrink-0 items-center justify-center rounded-lg bg-muted\">\n <MentionIcon item={item} className=\"size-4\" />\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"block text-[10px] uppercase tracking-wide text-muted-foreground\">\n {item.type}\n </span>\n <span className=\"block truncate text-sm font-medium text-foreground\">\n {item.title}\n </span>\n <span className=\"mt-0.5 line-clamp-3 text-xs text-muted-foreground\">\n {item.description}\n </span>\n </span>\n </div>\n );\n}\n\n/** A mention's icon: the host's URL, else a built-in name, else the @ glyph. */\nfunction MentionIcon({\n item,\n className,\n}: {\n item: WidgetMention;\n className?: string;\n}) {\n if (item.icon) {\n return (\n <img\n src={item.icon}\n alt=\"\"\n className={cn('size-4 shrink-0 rounded-sm object-contain', className)}\n />\n );\n }\n return (\n <DynamicIcon\n name={item.iconName ?? 'AtSign'}\n className={cn('size-3.5 shrink-0 text-primary', className)}\n />\n );\n}\n","import React, {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport type { MarkInk, PageMark } from './page-mark';\n\ntype PageMarksContextValue = {\n marks: readonly PageMark[];\n isArmed: boolean;\n setArmed(armed: boolean): void;\n attach(mark: PageMark, ink: MarkInk): void;\n detach(mark: PageMark): void;\n detachAll(): void;\n};\n\nconst PageMarksContext = createContext<PageMarksContextValue | null>(null);\n\n/**\n * One page-mark owner per Widget. It sits above shell/composer swaps so marks\n * survive those swaps, but below WidgetProvider so separate Widget instances\n * never share marks or armed state.\n */\nexport function PageMarksProvider({ children }: { children: React.ReactNode }) {\n const [marks, setMarks] = useState<readonly PageMark[]>([]);\n const [isArmed, setIsArmed] = useState(false);\n const inksRef = useRef(new Map<PageMark, MarkInk>());\n\n const setArmed = useCallback((armed: boolean) => {\n setIsArmed(armed);\n }, []);\n\n const attach = useCallback((mark: PageMark, ink: MarkInk) => {\n inksRef.current.set(mark, ink);\n setMarks((current) => [...current, mark]);\n }, []);\n\n const detach = useCallback((mark: PageMark) => {\n const ink = inksRef.current.get(mark);\n if (ink) {\n inksRef.current.delete(mark);\n ink.undraw();\n }\n setMarks((current) => current.filter((candidate) => candidate !== mark));\n }, []);\n\n const detachAll = useCallback(() => {\n const inks = Array.from(inksRef.current.values());\n inksRef.current.clear();\n for (const ink of inks) ink.undraw();\n setMarks([]);\n }, []);\n\n // A Widget unmount is final ownership teardown. Remove synchronously rather\n // than playing exit ink that could outlive the Widget on the host page.\n useEffect(\n () => () => {\n inksRef.current.forEach((ink) => ink.remove());\n inksRef.current.clear();\n },\n [],\n );\n\n const value = useMemo<PageMarksContextValue>(\n () => ({ marks, isArmed, setArmed, attach, detach, detachAll }),\n [marks, isArmed, setArmed, attach, detach, detachAll],\n );\n\n return (\n <PageMarksContext.Provider value={value}>\n {children}\n </PageMarksContext.Provider>\n );\n}\n\nexport function usePageMarks(): PageMarksContextValue {\n const value = useContext(PageMarksContext);\n if (!value) {\n throw new Error('usePageMarks must be used within a PageMarksProvider');\n }\n return value;\n}\n","import { safePageUrl } from '../page-privacy';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n clampRectToViewport,\n describeElement,\n elementAt,\n isWidgetOwned,\n rectOf,\n WIDGET_OWNED_SELECTOR,\n type Rect,\n} from './page-element';\nimport {\n createMarkInk,\n MIN_REGION_SIZE_PX,\n type MarkInk,\n type MarkShape,\n type PageMark,\n} from './page-mark';\nimport { usePageMarks } from './PageMarksProvider';\nimport { beginThumbnail } from './mark-thumbnail';\nimport { registerPageMarkSources } from './mark-source';\n\nconst CURSOR_STYLE_ATTR = 'data-opencx-mark-cursor';\n/** Elements a mark carries to the AI. */\nconst MAX_MARK_ELEMENTS = 5;\n/** Hit-test grid across the region (per axis). */\nconst SAMPLE_GRID = 4;\n/** Breathing room around a snapped element. */\nconst SNAP_PADDING_PX = 6;\n/** The region a click on empty page opens with. */\nconst DEFAULT_REGION = { width: 160, height: 100 };\n/** How close to a corner a press counts as grabbing its resize handle. */\nconst HANDLE_GRAB_PX = 10;\n\nconst NOT_WIDGET_OWNED = WIDGET_OWNED_SELECTOR.map(\n (marker) => `:not(${marker}):not(${marker} *)`,\n).join('');\n\n/** The corner being dragged; also the handle the cursor is over. */\ntype Corner = 'nw' | 'ne' | 'sw' | 'se';\n\n/** The live, editable mark — everything the overlay renders. */\nexport type MarkDraft = {\n /** Viewport rect (state-driven; the ink mirrors it in page coords). */\n rect: Rect;\n shape: MarkShape;\n};\n\n/** The element under the cursor while armed and nothing is placed yet. */\nexport type MarkHover = {\n rect: Rect;\n /** Changes per hovered ELEMENT — the overlay keys the frame on it. */\n key: number;\n};\n\n/** What the cursor says the visitor can do right here. */\ntype MarkCursor = 'crosshair' | 'move' | 'nwse-resize' | 'nesw-resize';\n\nconst cornerCursor = (corner: Corner): MarkCursor =>\n corner === 'nw' || corner === 'se' ? 'nwse-resize' : 'nesw-resize';\n\n/**\n * The composer's page-marking tool: while armed, a hover frame tracks the\n * element under the cursor and a CLICK lands a box mark snapped around it.\n * The mark is then an editable object — drag inside to move, drag a corner to\n * resize, switch shapes, type a note — and the cursor says which of those the\n * pointer is currently on. Clicking somewhere else re-places the mark there\n * (pointing at a different thing is the common case, not an accident); Enter\n * attaches it; Esc drops it, and Esc again disarms.\n *\n * All pointer listeners are capture-phase on the HOST document (the widget's\n * React code runs in the host realm), widget-owned nodes are exempt so the\n * editor card stays usable, and the complete pointer/click sequence is\n * swallowed so marking a button never activates it.\n */\nexport function usePageMarking({\n enabled,\n onAttach,\n accentColor,\n zIndex,\n}: {\n /** Whether this composer currently exposes page marking. */\n enabled: boolean;\n /** Notification only — the provider owns the mark either way. */\n onAttach?: (mark: PageMark) => void;\n accentColor: string;\n /** Host-page ink layer, normally resolved from the configured widget z-index. */\n zIndex: number;\n}) {\n const { isArmed, setArmed, attach: attachPageMark } = usePageMarks();\n // Gate render/listener state immediately. The provider is synchronized below\n // so a hidden tool cannot remain armed across config or viewport changes.\n const isActive = enabled && isArmed;\n const [draft, setDraft] = useState<MarkDraft | null>(null);\n const [hover, setHover] = useState<MarkHover | null>(null);\n\n const inkRef = useRef<MarkInk | null>(null);\n const draftRef = useRef<MarkDraft | null>(null);\n draftRef.current = draft;\n\n const dropDraft = useCallback(() => {\n inkRef.current?.undraw();\n inkRef.current = null;\n setDraft(null);\n }, []);\n\n const disarm = useCallback(() => setArmed(false), [setArmed]);\n\n const applyRect = useCallback((rect: Rect) => {\n setDraft((prev) => (prev ? { ...prev, rect } : prev));\n inkRef.current?.setRect({\n x: rect.x + window.scrollX,\n y: rect.y + window.scrollY,\n width: rect.width,\n height: rect.height,\n });\n }, []);\n\n const setShape = useCallback((shape: MarkShape) => {\n setDraft((prev) => (prev ? { ...prev, shape } : prev));\n inkRef.current?.setShape(shape);\n }, []);\n\n useEffect(() => {\n if (!enabled && isArmed) setArmed(false);\n }, [enabled, isArmed, setArmed]);\n\n useEffect(() => {\n if (!isActive) return;\n\n // One injected rule, rewritten as the affordance under the pointer\n // changes: the cursor is the only thing telling the visitor that this\n // spot moves the mark, that one resizes it, and out there places a new\n // one. Widget-owned nodes keep their own cursors.\n const style = document.createElement('style');\n style.setAttribute(CURSOR_STYLE_ATTR, '');\n let cursor: MarkCursor | null = null;\n const setCursor = (next: MarkCursor) => {\n if (next === cursor) return;\n cursor = next;\n style.textContent = `*${NOT_WIDGET_OWNED} { cursor: ${next} !important; }`;\n };\n setCursor('crosshair');\n document.head.appendChild(style);\n\n /** In-flight gesture on the existing draft. */\n let gesture:\n | { kind: 'move'; grabX: number; grabY: number }\n | { kind: 'resize'; corner: Corner }\n | null = null;\n\n const isWidgetTarget = (e: Event) =>\n e.target instanceof Element && isWidgetOwned(e.target);\n\n // Claim the full host-page gesture before it reaches the target. Stopping\n // only pointerdown is insufficient: pointerup/click handlers on a host\n // control can still submit, navigate, toggle, or delete independently.\n const claimHostEvent = (e: Event) => {\n if (isWidgetTarget(e)) return false;\n e.preventDefault();\n e.stopPropagation();\n e.stopImmediatePropagation();\n return true;\n };\n\n const cornerAt = (rect: Rect, x: number, y: number): Corner | null => {\n const corners: Array<[Corner, number, number]> = [\n ['nw', rect.x, rect.y],\n ['ne', rect.x + rect.width, rect.y],\n ['sw', rect.x, rect.y + rect.height],\n ['se', rect.x + rect.width, rect.y + rect.height],\n ];\n for (const [corner, cx, cy] of corners) {\n if (Math.hypot(x - cx, y - cy) <= HANDLE_GRAB_PX) return corner;\n }\n return null;\n };\n\n const isInside = (rect: Rect, x: number, y: number) =>\n x >= rect.x &&\n x <= rect.x + rect.width &&\n y >= rect.y &&\n y <= rect.y + rect.height;\n\n const placeRegion = (x: number, y: number) => {\n const el = elementAt(x, y);\n // Clamped: an element that runs past the viewport (a full-height nav,\n // a wide table) must still be marked with a box the visitor can SEE —\n // ink drawn off the page reads as a broken border, not as a mark.\n const rect: Rect = clampRectToViewport(\n el\n ? (() => {\n const r = el.getBoundingClientRect();\n return {\n x: r.left - SNAP_PADDING_PX,\n y: r.top - SNAP_PADDING_PX,\n width: r.width + SNAP_PADDING_PX * 2,\n height: r.height + SNAP_PADDING_PX * 2,\n };\n })()\n : {\n x: x - DEFAULT_REGION.width / 2,\n y: y - DEFAULT_REGION.height / 2,\n ...DEFAULT_REGION,\n },\n );\n // Always a BOX: one predictable default, and the chips do the rest.\n const shape: MarkShape = draftRef.current?.shape ?? 'box';\n setHover(null);\n inkRef.current = createMarkInk(\n {\n x: rect.x + window.scrollX,\n y: rect.y + window.scrollY,\n width: rect.width,\n height: rect.height,\n },\n shape,\n accentColor,\n zIndex,\n );\n setDraft({ rect, shape });\n };\n\n const handlePointerDown = (e: PointerEvent) => {\n if (!claimHostEvent(e)) return;\n // Right/middle clicks are swallowed but do not create or edit a mark.\n if (e.button !== 0) return;\n const current = draftRef.current;\n if (!current) {\n placeRegion(e.clientX, e.clientY);\n return;\n }\n const corner = cornerAt(current.rect, e.clientX, e.clientY);\n if (corner) {\n gesture = { kind: 'resize', corner };\n return;\n }\n if (isInside(current.rect, e.clientX, e.clientY)) {\n gesture = {\n kind: 'move',\n grabX: e.clientX - current.rect.x,\n grabY: e.clientY - current.rect.y,\n };\n return;\n }\n // Somewhere else on the page: re-place. The visitor is pointing at a\n // different thing, and the note they have typed rides along (the editor\n // card is not remounted) — the current shape does too.\n inkRef.current?.undraw();\n inkRef.current = null;\n placeRegion(e.clientX, e.clientY);\n };\n\n let lastHoverEl: HTMLElement | null = null;\n let hoverKey = 0;\n const handlePointerMove = (e: PointerEvent) => {\n if (!claimHostEvent(e)) return;\n const current = draftRef.current;\n if (!current) {\n // Armed, nothing placed: track the element under the cursor.\n setCursor('crosshair');\n const el = elementAt(e.clientX, e.clientY);\n if (!el) {\n lastHoverEl = null;\n setHover(null);\n return;\n }\n if (el !== lastHoverEl) {\n lastHoverEl = el;\n hoverKey += 1;\n }\n setHover({ rect: clampRectToViewport(rectOf(el)), key: hoverKey });\n return;\n }\n\n if (!gesture) {\n // Idle over a draft: the cursor advertises move / resize / re-place.\n const corner = cornerAt(current.rect, e.clientX, e.clientY);\n setCursor(\n corner\n ? cornerCursor(corner)\n : isInside(current.rect, e.clientX, e.clientY)\n ? 'move'\n : 'crosshair',\n );\n return;\n }\n\n const { rect } = current;\n if (gesture.kind === 'move') {\n applyRect({\n ...rect,\n x: e.clientX - gesture.grabX,\n y: e.clientY - gesture.grabY,\n });\n return;\n }\n // Resize: the dragged corner follows the cursor, its opposite stays put.\n const anchorX = gesture.corner.includes('w')\n ? rect.x + rect.width\n : rect.x;\n const anchorY = gesture.corner.includes('n')\n ? rect.y + rect.height\n : rect.y;\n const x1 = Math.min(anchorX, e.clientX);\n const x2 = Math.max(anchorX, e.clientX);\n const y1 = Math.min(anchorY, e.clientY);\n const y2 = Math.max(anchorY, e.clientY);\n applyRect({\n x: x1,\n y: y1,\n width: Math.max(MIN_REGION_SIZE_PX, x2 - x1),\n height: Math.max(MIN_REGION_SIZE_PX, y2 - y1),\n });\n };\n\n const handlePointerUp = (e: PointerEvent) => {\n if (!claimHostEvent(e)) return;\n gesture = null;\n };\n\n const handlePointerCancel = (e: PointerEvent) => {\n if (!isWidgetTarget(e)) claimHostEvent(e);\n gesture = null;\n };\n\n // Swallow clicks so marking a link never navigates the host page.\n const swallow = (e: MouseEvent) => {\n claimHostEvent(e);\n };\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key !== 'Escape') return;\n e.preventDefault();\n e.stopPropagation();\n gesture = null;\n if (draftRef.current) {\n inkRef.current?.undraw();\n inkRef.current = null;\n setDraft(null);\n setCursor('crosshair');\n return;\n }\n setArmed(false);\n };\n\n // Ink is anchored in page coordinates; editor chrome is viewport-fixed.\n // Shift the draft by the scroll delta so handles/editor remain glued to\n // the same ink instead of drifting away from it.\n let previousScrollX = window.scrollX;\n let previousScrollY = window.scrollY;\n const handleScroll = () => {\n setHover(null);\n const deltaX = window.scrollX - previousScrollX;\n const deltaY = window.scrollY - previousScrollY;\n previousScrollX = window.scrollX;\n previousScrollY = window.scrollY;\n if (deltaX === 0 && deltaY === 0) return;\n setDraft((current) =>\n current\n ? {\n ...current,\n rect: {\n ...current.rect,\n x: current.rect.x - deltaX,\n y: current.rect.y - deltaY,\n },\n }\n : current,\n );\n };\n\n document.addEventListener('pointerdown', handlePointerDown, true);\n document.addEventListener('pointermove', handlePointerMove, true);\n document.addEventListener('pointerup', handlePointerUp, true);\n document.addEventListener('pointercancel', handlePointerCancel, true);\n document.addEventListener('click', swallow, true);\n document.addEventListener('keydown', handleKeyDown, true);\n document.addEventListener('scroll', handleScroll, true);\n\n return () => {\n style.remove();\n document.removeEventListener('pointerdown', handlePointerDown, true);\n document.removeEventListener('pointermove', handlePointerMove, true);\n document.removeEventListener('pointerup', handlePointerUp, true);\n document.removeEventListener('pointercancel', handlePointerCancel, true);\n document.removeEventListener('click', swallow, true);\n document.removeEventListener('keydown', handleKeyDown, true);\n document.removeEventListener('scroll', handleScroll, true);\n setHover(null);\n };\n }, [isActive, accentColor, zIndex, applyRect, setArmed]);\n\n // Disarming with a draft open (toggle, unmount) must not leak its ink.\n useEffect(() => {\n if (!isActive && draftRef.current) dropDraft();\n }, [isActive, dropDraft]);\n // Unmounting releases only the UNATTACHED draft (its editor card is gone\n // with the composer, so it could never be finished). Attached marks belong\n // to the provider and are deliberately left inked on the page.\n useEffect(\n () => () => {\n inkRef.current?.remove();\n inkRef.current = null;\n },\n [],\n );\n\n /** Attach the draft with the note (empty note = no note). */\n const attach = useCallback(\n (note: string) => {\n if (!enabled) return;\n const current = draftRef.current;\n const ink = inkRef.current;\n if (!current || !ink) return;\n const trimmed = note.trim();\n // Sampled from the FINAL rect — the region may have moved since it was\n // placed, and what is under it now is what the visitor means.\n const sampled = sampleRegion(current.rect);\n const mark: PageMark = {\n shape: current.shape,\n ...(trimmed ? { note: trimmed } : {}),\n pageUrl: safePageUrl(window.location.href),\n rect: current.rect,\n elements: sampled.map(describeElement),\n };\n registerPageMarkSources(mark, sampled);\n // Thumbnail for the pill: the region's focus element (center-first\n // sampling puts it first). Rides a WeakMap, never the payload.\n if (sampled[0]) {\n beginThumbnail(mark, sampled[0]);\n }\n inkRef.current = null;\n setDraft(null);\n setArmed(false);\n attachPageMark(mark, ink);\n onAttach?.(mark);\n },\n [attachPageMark, enabled, onAttach, setArmed],\n );\n\n const toggle = useCallback(() => {\n if (enabled) setArmed(!isArmed);\n }, [enabled, isArmed, setArmed]);\n\n return {\n isActive,\n draft,\n hover,\n setShape,\n attach,\n /** Esc-equivalent for the editor card's discard affordance. */\n dropDraft,\n disarm,\n toggle,\n };\n}\n\n/**\n * Elements inside the region: hit-test the center first (the region's focus\n * element, which the pill thumbnails), then a coarse grid, dedupe in\n * encounter order, cap. Grid sampling beats geometric intersection because it\n * sees exactly what a click there would see — including overlays and stacking.\n * The mark's own ink and editor are widget-owned and pointer-inert, so they\n * never shadow the page.\n */\nfunction sampleRegion(rect: Rect): HTMLElement[] {\n const found = new Set<HTMLElement>();\n const probe = (x: number, y: number) => {\n const el = elementAt(x, y);\n if (el) found.add(el);\n };\n probe(rect.x + rect.width / 2, rect.y + rect.height / 2);\n for (let i = 0; i <= SAMPLE_GRID; i++) {\n for (let j = 0; j <= SAMPLE_GRID; j++) {\n probe(\n rect.x + (rect.width * i) / SAMPLE_GRID,\n rect.y + (rect.height * j) / SAMPLE_GRID,\n );\n }\n }\n return Array.from(found).slice(0, MAX_MARK_ELEMENTS);\n}\n","import { log } from '@opencx/widget-core';\nimport { useWidget } from '@opencx/widget-react-headless';\nimport { useCallback, type RefObject } from 'react';\nimport { useTheme } from '../../hooks/useTheme';\nimport { usePageMarks } from '../../page-marks/PageMarksProvider';\nimport { resolvePageMarkTheme } from '../../page-marks/page-mark-theme';\nimport { usePageMarking } from '../../page-marks/usePageMarking';\n\n/**\n * The composer's side of page marking: the widget-themed marking tool, the\n * attached marks (held by the Widget-scoped `PageMarksProvider`, so they\n * survive the composer unmounting), and the snapshot upload that lets a\n * mark's picture persist exactly like a dropped file.\n */\nexport function usePageMarkComposer({\n enabled,\n inputRef,\n}: {\n enabled: boolean;\n inputRef: RefObject<HTMLTextAreaElement | null>;\n}) {\n const { widgetCtx } = useWidget();\n const { theme, cssVars } = useTheme();\n const pageMarkTheme = resolvePageMarkTheme({\n cssVars,\n primaryColor: theme.primaryColor,\n contentZIndex: theme.widgetContentContainer.zIndex,\n });\n const { marks, detach } = usePageMarks();\n const onMarkAttached = useCallback(() => {\n // Bring the visitor back to their question after the mark lands.\n inputRef.current?.focus();\n }, [inputRef]);\n const uploadSnapshot = useCallback(\n async (file: File): Promise<string | null> => {\n if (!widgetCtx.features.pageContext) return null;\n try {\n const { fileUrl } = await widgetCtx.api.uploadFile({\n file,\n abortSignal: new AbortController().signal,\n });\n return fileUrl ?? null;\n } catch (error) {\n log.warn('page mark snapshot upload failed', error);\n return null;\n }\n },\n [widgetCtx],\n );\n const marking = usePageMarking({\n enabled,\n onAttach: onMarkAttached,\n accentColor: pageMarkTheme.accent,\n zIndex: pageMarkTheme.inkZIndex,\n });\n return { marks, detach, marking, uploadSnapshot };\n}\n","import React, { useRef } from 'react';\nimport { matchesBinding, WIDGET_KEYBINDINGS } from '../../utils/keybindings';\n\n/** Parts of a keydown this hook reads. */\nexport type RecallKeyEvent = Pick<\n KeyboardEvent,\n 'key' | 'metaKey' | 'ctrlKey' | 'altKey' | 'shiftKey' | 'repeat'\n> & { preventDefault: () => void };\n\n/**\n * Shell-style ↑/↓ recall of previously sent messages in the composer.\n *\n * The walk position lives in a ref, not state: nothing renders it, and the\n * keydown handler must read the position it just wrote when a held key\n * auto-repeats. `index === null` means \"typing a fresh draft\" — the first ↑\n * stashes that draft so walking ↓ back past the newest entry restores it.\n *\n * The history itself is NOT owned here. It comes from `MessageCtx`, so it is\n * scoped to one widget instance and one conversation, and survives this\n * component unmounting when the companion morphs between its quick-ask bar\n * and the full chat panel.\n */\nexport function useSentTextRecall({\n inputText,\n setInputText,\n inputRef,\n getSentTextHistory,\n}: {\n inputText: string;\n setInputText: (text: string) => void;\n inputRef: React.RefObject<HTMLTextAreaElement | null>;\n getSentTextHistory: () => readonly string[];\n}) {\n const indexRef = useRef<number | null>(null);\n const draftRef = useRef('');\n\n /** Replay the recall settle on the textarea. Imperative classList, not\n * React state: restarting a CSS animation on rapid successive recalls\n * needs remove → forced reflow → re-add, and React leaves classes it\n * didn't render alone, so the two never fight. */\n const playRecallAnimation = () => {\n const el = inputRef.current;\n if (!el) return;\n el.classList.remove('opencx-input-recall');\n void el.offsetWidth;\n el.classList.add('opencx-input-recall');\n };\n\n const applyRecall = (text: string, { animate = true } = {}) => {\n setInputText(text);\n // Held-key auto-repeat walks entries every ~35ms — replaying the pulse\n // each step reads as flicker, so only a discrete press animates.\n if (animate) playRecallAnimation();\n // Caret lands at the end of the recalled text, after React commits it.\n requestAnimationFrame(() =>\n inputRef.current?.setSelectionRange(text.length, text.length),\n );\n };\n\n /** Any edit makes the buffer a fresh draft — the next ↑ resumes from the\n * newest entry, like a shell. */\n const onEdit = () => {\n indexRef.current = null;\n };\n\n /** After a send: recall restarts from the newest entry, no draft stashed. */\n const onSent = () => {\n indexRef.current = null;\n draftRef.current = '';\n };\n\n /**\n * Handle ↑/↓. Returns true when the event was consumed, so the composer's\n * own keydown chain can stop there.\n */\n const onKeyDown = (event: RecallKeyEvent): boolean => {\n if (matchesBinding(event, WIDGET_KEYBINDINGS['history-prev'])) {\n const history = getSentTextHistory();\n if (history.length === 0) return false;\n const index = indexRef.current;\n if (index === null) {\n // ENTERING a walk is the only moment the caret matters: mid-text ↑ is\n // line navigation in a multi-line box, not history. Once walking, the\n // box holds a recalled entry the user hasn't touched, so ↑/↓ belong to\n // the walk wherever `applyRecall` parked the caret — and any edit\n // hands them straight back (`onEdit`).\n const el = inputRef.current;\n const atStart = el?.selectionStart === 0 && el?.selectionEnd === 0;\n if (!atStart && inputText !== '') return false;\n draftRef.current = inputText;\n indexRef.current = history.length - 1;\n } else {\n if (index === 0) return false; // already at the oldest entry\n indexRef.current = index - 1;\n }\n event.preventDefault();\n applyRecall(history[indexRef.current]!, { animate: !event.repeat });\n return true;\n }\n\n if (matchesBinding(event, WIDGET_KEYBINDINGS['history-next'])) {\n const index = indexRef.current;\n if (index === null) return false; // not walking history\n event.preventDefault();\n const history = getSentTextHistory();\n if (index >= history.length - 1) {\n // Walked past the newest entry — the stashed draft returns.\n indexRef.current = null;\n applyRecall(draftRef.current, { animate: !event.repeat });\n draftRef.current = '';\n } else {\n indexRef.current = index + 1;\n applyRecall(history[indexRef.current]!, { animate: !event.repeat });\n }\n return true;\n }\n\n return false;\n };\n\n return { onKeyDown, onEdit, onSent };\n}\n","import { ElicitationForm } from '../../components/ElicitationForm';\nimport { ConnectionCard } from '../../components/ConnectionCard';\nimport { type SendMessageDto, log } from '@opencx/widget-core';\nimport {\n useAgentChatUi,\n useComposerDraft,\n useDictation,\n useIsAwaitingBotReply,\n useMessages,\n useSessions,\n useUploadFiles,\n useWidget,\n} from '@opencx/widget-react-headless';\nimport { AnimatePresence } from 'framer-motion';\nimport {\n ArrowUpIcon,\n CircleDashed,\n MousePointerClickIcon,\n PaperclipIcon,\n SquareIcon,\n} from 'lucide-react';\nimport React, { useEffect, useLayoutEffect, useRef, useState } from 'react';\nimport { useDropzone } from 'react-dropzone';\nimport { MotionDiv } from '../../components/lib/MotionDiv';\nimport { MotionDiv__VerticalReveal } from '../../components/lib/MotionDiv__VerticalReveal';\nimport { Button } from '../../components/lib/button';\nimport { Tooltippy } from '../../components/lib/tooltip';\nimport { cn } from '../../components/lib/utils/cn';\nimport { useIsSmallScreen } from '../../hooks/useIsSmallScreen';\nimport { useTranslation } from '../../hooks/useTranslation';\nimport { type PageMark } from '../../page-marks/page-mark';\nimport { isPageMarkShareable } from '../../page-marks/mark-source';\nimport {\n awaitSnapshotUrl,\n beginSnapshotUpload,\n} from '../../page-marks/mark-thumbnail';\nimport { buildPageClientContext } from '../../page-controls/send-context';\nimport { PageActionCard } from '../../components/PageActionCard';\nimport { PageContextPill } from '../../page-context/PageContextPill';\nimport { usePageEntity } from '../../page-context/usePageEntity';\nimport { PageMarkOverlay } from '../../page-marks/PageMarkOverlay';\nimport { PageMarkPill } from '../../page-marks/PageMarkPill';\nimport { dc } from '../../utils/data-component';\nimport {\n formatBinding,\n matchesBinding,\n WIDGET_KEYBINDINGS,\n} from '../../utils/keybindings';\nimport {\n AI_FILE_ACCEPT,\n HANDED_OFF_FILE_ACCEPT,\n MAX_FILE_BYTES,\n UploadPreview,\n} from './UploadPreview';\nimport { QueuedSendsPill } from './agent/QueuedSendsPill';\nimport { COMPOSER_TOOL_ARMED, COMPOSER_TOOL_BUTTON } from './composer-styles';\nimport { DictationMicButton } from './DictationMicButton';\nimport { MentionPicker } from './MentionPicker';\nimport { MentionText } from './MentionText';\nimport { copyTextLayoutStyles } from './caret-position';\nimport { useMentions } from './useMentions';\nimport { usePageMarkComposer } from './usePageMarkComposer';\nimport { useSentTextRecall } from './useSentTextRecall';\n\n/**\n * The textarea's box, shared with the mirror that highlights mentions under\n * it: both must wrap the same text at the same places, so width, padding\n * and the growth limit are declared once.\n */\nconst TEXTAREA_BOX_CLASS = 'max-h-16 [field-sizing:content] w-full px-2';\n\n/**\n * The stock composer — white card, multi-line textarea, attach + send.\n * Exported so companion's quick-ask state renders the exact same composer\n * (not a bespoke bar), inheriting every customization automatically.\n */\nexport function ChatInput({\n trailingActions,\n placeholder,\n hideAttachTools,\n disabled = false,\n}: {\n /** Keep the composer visible while a required starter must be chosen. */\n disabled?: boolean;\n /**\n * Extra controls rendered in the composer's action row, just before the\n * send button. Companion uses it to slot a conversation-history button into\n * the quick-ask bar; popover mode passes nothing.\n */\n trailingActions?: React.ReactNode;\n /**\n * Override the composer placeholder. Companion's quick-ask bar uses it to\n * read \"Follow up…\" while continuing an open conversation. Defaults to the\n * localized \"Write a message…\".\n */\n placeholder?: string;\n /**\n * Hide the attach + page-mark buttons. Companion's docked quick-ask\n * bar sets it so the resting composer carries ONLY the history control —\n * the full tool row lives in the expanded chat panel.\n */\n hideAttachTools?: boolean;\n} = {}) {\n const { isSmallScreen } = useIsSmallScreen();\n const inputRef = useRef<HTMLTextAreaElement>(null);\n const composerRootRef = useRef<HTMLDivElement>(null);\n const mirrorRef = useRef<HTMLDivElement>(null);\n const mountedRef = useRef(true);\n const { sendMessage, rememberSentText, getSentTextHistory } = useMessages();\n const { widgetCtx, componentStore } = useWidget();\n // Org features narrowed by the embed: no attachments → no paperclip, no\n // drop, no paste; no page marks → no mark button.\n const { attachments: canAttach, pageContext: pageMarksEnabled } =\n widgetCtx.features;\n // Agent-chat streaming state — no-op defaults for bot-chat embeds.\n const {\n isStreaming,\n stop,\n queuedUserMessages,\n pendingClarification,\n pendingConnection,\n pendingPageAction,\n } = useAgentChatUi();\n const { sessionState } = useSessions();\n const { t } = useTranslation();\n const {\n text: inputText,\n setText: setInputText,\n clearSubmitted,\n } = useComposerDraft();\n // The host page's entity (\"this\" to the agent). Dismissing the pill drops\n // it from the NEXT send only; it comes back for the message after.\n const pageEntity = usePageEntity();\n // @-mentions: things on the host the visitor names in the message.\n const mentions = useMentions({\n text: inputText,\n setText: setInputText,\n inputRef,\n });\n const hasMentionsInDraft = mentions.picked.length > 0;\n // The mirror wears the textarea's resolved font and padding, not the\n // classes it was written with: an embedder's `cssOverrides` on the\n // textarea (a 13px composer, say) must move the highlight with the text.\n useLayoutEffect(() => {\n const input = inputRef.current;\n const mirror = mirrorRef.current;\n if (!input || !mirror) return;\n copyTextLayoutStyles(input, mirror);\n }, [hasMentionsInDraft, inputText]);\n const [pageEntityDismissed, setPageEntityDismissed] = useState(false);\n // Dismissal is per entity: a new page brings its own \"this\" back.\n const pageEntityKey = pageEntity ? `${pageEntity.type}:${pageEntity.id}` : '';\n useEffect(() => {\n setPageEntityDismissed(false);\n }, [pageEntityKey]);\n const [fileSelectionError, setFileSelectionError] = useState<string | null>(\n null,\n );\n // Dictation reads/writes the composer between renders, so it goes through\n // a ref that mirrors state synchronously (the drip must see its own write).\n const inputTextRef = useRef(inputText);\n inputTextRef.current = inputText;\n const handleSubmitRef = useRef<() => void>(() => undefined);\n const dictation = useDictation({\n getValue: () => inputTextRef.current,\n setValue: (value) => {\n inputTextRef.current = value;\n setInputText(value);\n },\n onSend: () => handleSubmitRef.current(),\n });\n const { stop: stopDictation } = dictation;\n useEffect(() => {\n if (disabled) stopDictation({ executeFinalCommand: false });\n }, [disabled, stopDictation]);\n\n useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n };\n }, []);\n\n // ↑/↓ recall of previously sent messages. The history lives on MessageCtx\n // (one widget instance, cleared with the conversation); the walk position\n // lives in the hook.\n const recall = useSentTextRecall({\n inputText,\n setInputText,\n inputRef,\n getSentTextHistory,\n });\n\n // Page marks: hover an element, click to land an editable mark, attach it\n // as context. Attached marks live OUTSIDE this component — collapsing the\n // panel unmounts the composer.\n const showPageMarks = pageMarksEnabled && !isSmallScreen;\n const pageMarkingEnabled =\n !disabled && showPageMarks && hideAttachTools !== true;\n const { marks, detach, marking, uploadSnapshot } = usePageMarkComposer({\n enabled: pageMarkingEnabled,\n inputRef,\n });\n\n useEffect(() => {\n if (!pageMarksEnabled) marks.forEach(detach);\n }, [pageMarksEnabled, marks, detach]);\n\n const {\n allFiles,\n handleCancelUpload,\n appendFiles,\n isUploading,\n successFiles,\n } = useUploadFiles();\n\n const isHandedOff = !!sessionState.session?.isHandedOff;\n\n const { isAwaitingBotReply } = useIsAwaitingBotReply();\n // The awaiting-AI gate is the non-streaming engine's: a mid-turn send has\n // nowhere to go there, so it is blocked (unless the embedder opts out).\n // The streaming agent surface never blocks — a send mid-turn is queued\n // (multi-send) and drains when the live turn ends or is stopped.\n const shouldBlockSending =\n widgetCtx.messageCtx.blocksSendWhileAwaitingReply && isAwaitingBotReply;\n\n const handleFileDrop = (acceptedFiles: File[]) => {\n // Drop and paste both land here: nothing is accepted when the org has no\n // attachments (the dropzone is disabled too, this guards the paste path).\n if (disabled || !canAttach) return;\n setFileSelectionError(null);\n appendFiles(acceptedFiles);\n };\n\n // An attached mark is a message on its own — the visitor already said what\n // they mean by drawing on the page and (usually) writing on it, so the\n // composer must not demand the same question typed a second time.\n // The tray above the composer carries the page alone. Marks are pictures\n // of the page, so they preview inside the composer with the files.\n const hasAttachedContext = pageEntity !== null && !pageEntityDismissed;\n const hasPreviews = allFiles.length > 0 || marks.length > 0;\n\n const cannotSend =\n !inputText.trim() &&\n successFiles.length === 0 &&\n (!pageMarksEnabled || !marks.some(isPageMarkShareable));\n\n // The send button's single decision: an empty box mid-stream offers stop;\n // anything typed mid-stream sends (queues). Otherwise the button sends,\n // subject to uploads and the non-streaming awaiting-reply gate.\n const showStop = isStreaming && cannotSend;\n // Enter on an EMPTY composer is the queue's flush: stopping the live turn is\n // what starts the next queued message, which is exactly what the ⏎ hint on\n // the queue pill advertises. Gated on a non-empty queue so a stray Enter\n // never kills a response nobody is waiting to follow up on — the send\n // button keeps offering stop unconditionally, a click being deliberate in a\n // way a keystroke is not.\n const flushQueueOnEnter = showStop && queuedUserMessages.length > 0;\n const sendDisabled =\n disabled || isUploading || shouldBlockSending || cannotSend;\n\n const handleSubmit = () => {\n // A spoken \"send it\" must not send half a phrase.\n dictation.stop({ executeFinalCommand: false });\n if (disabled || shouldBlockSending) return;\n\n // Sending now would silently drop files still uploading (only\n // `successFiles` ride the payload).\n if (isUploading) return;\n // Everything the send carries is captured NOW: the snapshot wait below\n // yields to the event loop, and the composer may change underneath it.\n const submittedText = inputTextRef.current;\n const isCurrentConversation = widgetCtx.messageCtx.captureConversation();\n const submittedDraft = widgetCtx.messageCtx.draftState.get();\n const submittedMarks = marks.filter((mark) => {\n if (widgetCtx.features.pageContext && isPageMarkShareable(mark))\n return true;\n detach(mark);\n return false;\n });\n const submittedFiles = [...successFiles];\n if (\n !submittedText.trim() &&\n submittedFiles.length === 0 &&\n submittedMarks.length === 0\n )\n return;\n const submittedFileIds = allFiles.map((file) => file.id);\n // Upload only after Send. Attaching or discarding a mark stays local.\n submittedMarks.forEach((mark) => beginSnapshotUpload(mark, uploadSnapshot));\n void Promise.all(\n submittedMarks.map((mark) =>\n awaitSnapshotUrl(mark, SNAPSHOT_UPLOAD_GRACE_MS),\n ),\n ).then(() =>\n submit({\n isCurrentConversation,\n submittedText,\n submittedDraft,\n submittedMarks,\n submittedFiles,\n submittedFileIds,\n }),\n );\n };\n\n const submit = ({\n isCurrentConversation,\n submittedText,\n submittedDraft,\n submittedMarks,\n submittedFiles,\n submittedFileIds,\n }: {\n isCurrentConversation: () => boolean;\n submittedText: string;\n submittedDraft: ReturnType<typeof widgetCtx.messageCtx.draftState.get>;\n submittedMarks: PageMark[];\n submittedFiles: typeof successFiles;\n submittedFileIds: string[];\n }) => {\n // A reset can reuse this MessageCtx for another session or visitor. Do not\n // send or clear their state when an earlier snapshot upload finishes.\n if (!isCurrentConversation()) return;\n // Upload preparation yields: permissions or the marked DOM may have changed.\n const readsPage = widgetCtx.features.pageContext;\n const currentMarks = submittedMarks.filter((mark) => {\n if (readsPage && isPageMarkShareable(mark)) return true;\n detach(mark);\n return false;\n });\n if (\n !submittedText.trim() &&\n submittedFiles.length === 0 &&\n currentMarks.length === 0\n )\n return;\n // Nothing typed but marks attached: their notes ARE the question, and a\n // note-less mark still asks the one thing the tool exists for. Files keep\n // sending with no text at all, as they always have.\n const trimmed =\n submittedText.trim() ||\n (currentMarks.length > 0\n ? (markNotes(currentMarks) ?? t('page_mark_default_message'))\n : '');\n let didAccept = false;\n const submittedMentions = mentions.picked;\n\n // Do not await this\n void sendMessage({\n content: trimmed,\n withPageEntity: !pageEntityDismissed,\n mentions: submittedMentions.length > 0 ? submittedMentions : undefined,\n attachments: submittedFiles.flatMap((f) =>\n f.fileUrl\n ? [\n {\n url: f.fileUrl,\n type: f.file.type,\n name: f.file.name,\n id: f.id,\n size: f.file.size,\n } satisfies NonNullable<SendMessageDto['attachments']>[number],\n ]\n : [],\n ),\n // Page marks ride as AI-visible context, not message text. `page_marks`\n // is the rich payload for THIS turn; `picked_elements` is the key the\n // backend persists, re-surfaces on later turns, and hands back to the\n // surfaces that show the message afterwards.\n clientContext: buildPageClientContext({\n marks: currentMarks,\n readsPage,\n }),\n onAccepted: () => {\n if (didAccept || !isCurrentConversation()) return;\n didAccept = true;\n\n rememberSentText(trimmed);\n // Page marks live outside this component, so detach the exact marks\n // that rode the accepted send even if the composer has unmounted.\n submittedMarks.forEach((mark) => detach(mark));\n submittedFileIds.forEach((fileId) => handleCancelUpload(fileId));\n\n const cleared = clearSubmitted(submittedDraft);\n if (!mountedRef.current) return;\n recall.onSent();\n setPageEntityDismissed(false);\n if (cleared) mentions.reset();\n },\n }).catch((error: unknown) => {\n log.error('failed to send message', error);\n });\n };\n\n const {\n getRootProps: dropzone__getRootProps,\n getInputProps: dropzone__getInputProps,\n open: dropzone__openFileSelect,\n } = useDropzone({\n onDrop: handleFileDrop,\n noClick: true,\n disabled: disabled || !canAttach,\n onDropRejected() {\n setFileSelectionError(t('file_rejected'));\n },\n maxSize: MAX_FILE_BYTES,\n // Handed-off (human agent) chats accept a wider net of images plus plain\n // text; AI chats take only the formats the models consume.\n accept: isHandedOff ? HANDED_OFF_FILE_ACCEPT : AI_FILE_ACCEPT,\n });\n\n const handlePaste = (event: React.ClipboardEvent<HTMLTextAreaElement>) => {\n const clipboardData = event.clipboardData;\n if (!clipboardData) return;\n if (clipboardData.files.length > 0) {\n handleFileDrop(Array.from(clipboardData.files));\n }\n };\n\n handleSubmitRef.current = handleSubmit;\n\n // The agent asked something and is waiting on the answer: the questionnaire\n // TAKES THE COMPOSER'S PLACE, so the customer answers where they would\n // otherwise type. It lives here rather than in `ChatFooter` because the\n // companion shell renders `ChatInput` directly and never mounts that footer\n // — one composer, one rule, every surface.\n const QuestionsComponent = componentStore.getComponent(\n 'agent_chat_questions',\n );\n if (!pendingConnection && pendingClarification && QuestionsComponent) {\n return (\n <div {...dc('chat/input_box/root')} className=\"p-2 relative space-y-1\">\n <QuestionsComponent request={pendingClarification} />\n </div>\n );\n }\n\n return (\n <div\n {...dc('chat/input_box/root')}\n className=\"p-2 relative space-y-1\"\n {...dropzone__getRootProps({ ref: composerRootRef })}\n >\n {sessionState.session && (\n <ElicitationForm\n key={sessionState.session.id}\n sessionId={sessionState.session.id}\n active={isStreaming || isAwaitingBotReply}\n />\n )}\n {pendingConnection && (\n <ConnectionCard\n key={pendingConnection.request_id}\n request={pendingConnection}\n />\n )}\n {pendingPageAction && (\n <PageActionCard\n key={pendingPageAction.callId}\n request={pendingPageAction}\n />\n )}\n <input {...dropzone__getInputProps()} />\n {mentions.isOpen && (\n <MentionPicker\n anchorRef={composerRootRef}\n inputRef={inputRef}\n anchorIndex={mentions.anchorIndex}\n preview={mentions.preview}\n groups={mentions.groups}\n visible={mentions.visible}\n searching={mentions.searching}\n highlighted={mentions.highlighted}\n onHighlight={mentions.setHighlighted}\n onPick={mentions.pick}\n onExpand={mentions.expandGroup}\n />\n )}\n {/* Mark-mode visuals (hint bar + hover frame + region editor) —\n portaled to the HOST page, not this iframe. */}\n {pageMarkingEnabled && (\n <PageMarkOverlay\n isActive={marking.isActive}\n draft={marking.draft}\n hover={marking.hover}\n onShapeChange={marking.setShape}\n onAttach={marking.attach}\n onDiscard={marking.dropDraft}\n />\n )}\n {/* Multi-send queue: messages waiting for their turn, docked above the\n input (Cursor-style). Renders nothing when the queue is empty. */}\n <QueuedSendsPill />\n {fileSelectionError && (\n <p role=\"alert\" className=\"px-2 text-xs text-destructive\">\n {fileSelectionError}\n </p>\n )}\n {dictation.error && (\n <p role=\"alert\" className=\"px-2 text-xs text-destructive\">\n {dictation.error === 'microphone'\n ? t('dictation_mic_blocked')\n : t('dictation_unavailable')}\n </p>\n )}\n {/* Attached context fused to the composer (Linear-style): one tray\n holds the context row and the composer card, so what the message is\n about reads as part of the thing you type into rather than as a chip\n floating above it. The tray only exists when something is attached —\n with nothing to show it collapses to the bare composer, unchanged.\n\n Concentric radii by calc so no frame can drift from the one outside\n it: the composer wears the shared `--opencx-inset-radius` (the\n shell's radius minus this root's padding, declared once in\n `FrameDocument`) and the tray's is the composer's plus the tray\n padding. `ps-3` puts the context title on the composer's TEXT inset\n (4px tray + 12px = the composer's 8px padding + the textarea's 8px),\n not on its edge.\n\n Crucially the context lives OUTSIDE the composer's border: inside it\n the box grew on every page change, pushing the transcript up and\n moving the send button under the visitor's cursor. */}\n <div\n {...dc('chat/input_box/attached_context_tray')}\n style={{ '--cx-p': '0.25rem' } as React.CSSProperties}\n className={cn(\n 'flex flex-col',\n // The tray's BOX is permanent — only its colour changes. Toggling\n // the padding with the content made attach and detach asymmetric:\n // the 4px snapped on in one frame on the way in, and on the way out\n // it snapped OFF while the row above was still collapsing, so the\n // composer jumped before the animation had finished. A box that is\n // always there has nothing to snap; the only thing that moves is\n // the row's height, and the only thing that changes is a colour.\n 'rounded-[calc(var(--opencx-inset-radius)+var(--cx-p))] p-[var(--cx-p)]',\n // 200ms matches MotionDiv's FADE_TRANSITION, so the grey arrives\n // and leaves with the row rather than racing it.\n 'transition-colors duration-200 ease-opencx',\n hasAttachedContext ? 'bg-muted' : 'bg-transparent',\n )}\n >\n {/* The row GROWS the tray rather than appearing at full height: an\n instant 28px row shoved the composer down a whole line in one\n frame, exactly the teleport `QueuedSendsPill` already solved a rung\n above with the same reveal. Height + opacity (the sanctioned\n accordion exception — there is no transform equivalent for a box\n that has to make room), on the shared FADE/EXIT transitions, so\n attaching and detaching mirror. */}\n <AnimatePresence>\n {hasAttachedContext && (\n <MotionDiv__VerticalReveal key=\"attached-context\">\n <div\n {...dc('chat/input_box/page_context_container')}\n className=\"flex items-center gap-1 flex-wrap ps-3 pe-1 py-1\"\n >\n <AnimatePresence mode=\"popLayout\">\n {pageEntity && !pageEntityDismissed && (\n <MotionDiv key=\"page-entity\" snapExit>\n <PageContextPill\n entity={pageEntity}\n onRemove={() => setPageEntityDismissed(true)}\n />\n </MotionDiv>\n )}\n </AnimatePresence>\n </div>\n </MotionDiv__VerticalReveal>\n )}\n </AnimatePresence>\n <div\n {...dc('chat/input_box/inner_root')}\n className={cn(\n 'transition-colors',\n 'bg-background',\n // The composer sits on the same background token as the message\n // list, so without an edge it reads as part of the transcript\n // rather than as the thing you type into. That hairline is the\n // WHOLE affordance: one edge, one weight, in every state.\n //\n // No hover or focus accent. The composer takes the caret the moment\n // a panel opens, so a focus-driven edge is not feedback — it is what\n // the composer looks like at rest, a second outline competing with\n // the shell's own frame around it. `:focus-visible` does not save\n // this either: browsers match it on text-editing elements however\n // they were focused (mouse and programmatic focus included), so a\n // \"keyboard-only\" ring on a textarea is the same always-on ring by\n // another name. A text field already indicates focus — the caret.\n 'border border-border',\n 'relative rounded-[var(--opencx-inset-radius)] flex flex-col gap-2 p-2',\n )}\n >\n <div\n {...dc('chat/input_box/textarea_and_attachments_container')}\n className=\"flex flex-col gap-2\"\n >\n {hasPreviews && (\n <div\n {...dc('chat/input_box/attachments_container')}\n className=\"flex items-center gap-1 overflow-x-auto\"\n >\n <AnimatePresence mode=\"popLayout\">\n {allFiles.map((file) => (\n <MotionDiv key={file.id} snapExit>\n <UploadPreview\n onCancel={() => handleCancelUpload(file.id)}\n file={file}\n />\n </MotionDiv>\n ))}\n {marks.map((mark, index) => (\n <MotionDiv\n key={`mark-${index}-${mark.note ?? ''}`}\n snapExit\n >\n <PageMarkPill mark={mark} onRemove={() => detach(mark)} />\n </MotionDiv>\n ))}\n </AnimatePresence>\n </div>\n )}\n {/* Picked mentions are highlighted IN the text: a mirror of the\n textarea's content sits under it, in the same box, with the\n `@Title` tokens tinted, and the textarea paints only its caret\n over that while a mention is in the draft. */}\n <div className=\"relative\">\n {hasMentionsInDraft && (\n <div\n ref={mirrorRef}\n aria-hidden\n className={cn(\n TEXTAREA_BOX_CLASS,\n 'pointer-events-none absolute inset-0 overflow-hidden',\n 'whitespace-pre-wrap break-words text-foreground',\n !hasPreviews && 'pt-1',\n isSmallScreen ? 'text-[16px]' : 'text-sm',\n )}\n >\n <MentionText\n text={inputText}\n mentions={mentions.picked}\n tokenClassName=\"bg-primary/10 text-primary\"\n />\n </div>\n )}\n <textarea\n {...dc('chat/input_box/textarea')}\n disabled={disabled}\n onPaste={handlePaste}\n ref={inputRef}\n id=\"chat-input\"\n value={inputText}\n // Thw `rows` attribute will take effect in browsers that do not support [field-sizing:content;] (Firefox and Safari as of now)\n rows={3}\n className={cn(\n TEXTAREA_BOX_CLASS,\n 'relative resize-none',\n !hasPreviews && 'pt-1',\n 'bg-transparent outline-none',\n 'placeholder:text-muted-foreground',\n hasMentionsInDraft && 'text-transparent caret-foreground',\n // 16px on mobiles prevents auto-zoom on the input when focused\n isSmallScreen ? 'text-[16px]' : 'text-sm',\n )}\n onScroll={(e) => {\n if (mirrorRef.current)\n mirrorRef.current.scrollTop = e.currentTarget.scrollTop;\n }}\n onChange={(e) => {\n recall.onEdit();\n setInputText(e.target.value);\n }}\n onClick={() => mentions.onCaretMove('nearest')}\n onKeyUp={(event) => {\n if (event.key === 'ArrowRight' || event.key === 'ArrowDown')\n mentions.onCaretMove('forward');\n else if (event.key === 'ArrowLeft' || event.key === 'ArrowUp')\n mentions.onCaretMove('backward');\n else if (event.key === 'Home' || event.key === 'End')\n mentions.onCaretMove('nearest');\n }}\n onKeyDown={(event) => {\n if (event.nativeEvent.isComposing) return;\n // An open mention picker owns ↑/↓/Enter/Tab/Escape.\n if (mentions.onKeyDown(event)) return;\n // Mod+Enter sends too — muscle memory from every other\n // composer; plain Shift+Enter stays a newline.\n if (\n matchesBinding(event, WIDGET_KEYBINDINGS.send) ||\n matchesBinding(event, WIDGET_KEYBINDINGS['send-alt'])\n ) {\n event.preventDefault();\n if (flushQueueOnEnter) stop();\n else handleSubmit();\n return;\n }\n // Mark-mode's own Esc listener lives on the HOST document;\n // keystrokes inside the chat iframe never reach it.\n if (event.key === 'Escape' && marking.isActive) {\n marking.disarm();\n return;\n }\n recall.onKeyDown(event);\n }}\n placeholder={placeholder ?? t('write_a_message_placeholder')}\n />\n </div>\n </div>\n <div className=\"gap-2 flex justify-between\">\n {/* Left group: composer inputs (attach + page marks). Hidden\n entirely on the docked quick-ask bar (history-only there). */}\n <div className=\"flex items-center gap-1\">\n {!disabled && !hideAttachTools && (\n <>\n {canAttach && (\n <Tooltippy\n side=\"top\"\n align=\"start\"\n content={t('attach_files')}\n >\n <Button\n onClick={dropzone__openFileSelect}\n aria-label={t('attach_files')}\n size=\"fit\"\n variant=\"ghost\"\n className={COMPOSER_TOOL_BUTTON}\n >\n <AnimatePresence mode=\"wait\">\n {!shouldBlockSending ? (\n <MotionDiv key=\"paper-clip\" distance={0}>\n <PaperclipIcon className=\"size-4\" />\n </MotionDiv>\n ) : (\n <MotionDiv key=\"paper-clip-disabled\" distance={0}>\n <PaperclipIcon className=\"size-4 opacity-50\" />\n </MotionDiv>\n )}\n </AnimatePresence>\n </Button>\n </Tooltippy>\n )}\n\n {dictation.enabled && (\n <DictationMicButton\n status={dictation.status}\n levelRef={dictation.levelRef}\n onToggle={dictation.toggle}\n onPrewarm={dictation.prewarm}\n />\n )}\n\n {showPageMarks && (\n <Tooltippy\n side=\"top\"\n align=\"start\"\n content={\n marking.isActive\n ? t('mark_page_active')\n : t('mark_page')\n }\n >\n <Button\n {...dc('chat/input_box/page_mark_btn')}\n onClick={marking.toggle}\n aria-label={\n marking.isActive\n ? t('mark_page_active')\n : t('mark_page')\n }\n size=\"fit\"\n variant=\"ghost\"\n className={cn(\n COMPOSER_TOOL_BUTTON,\n // Armed: click again (or Esc) to disarm.\n marking.isActive && COMPOSER_TOOL_ARMED,\n )}\n >\n <MousePointerClickIcon className=\"size-4\" />\n </Button>\n </Tooltippy>\n )}\n </>\n )}\n </div>\n\n {/* Right group: extra controls (e.g. quick-ask history) + send. */}\n <div className=\"flex items-center gap-1\">\n {trailingActions}\n\n <Tooltippy\n // While streaming: typing a new message queues it (send); an empty\n // box stops the current response — the next queued message (if\n // any) then starts its own turn immediately.\n content={showStop ? t('stop_response') : t('send_message')}\n shortcut={\n showStop ? undefined : formatBinding(WIDGET_KEYBINDINGS.send)\n }\n side=\"top\"\n align=\"end\"\n >\n <Button\n size=\"fit\"\n onClick={showStop ? stop : handleSubmit}\n aria-label={showStop ? t('stop_response') : t('send_message')}\n // Stop is always available; sending obeys `sendDisabled`.\n disabled={disabled || (!showStop && sendDisabled)}\n className={COMPOSER_TOOL_BUTTON}\n >\n <AnimatePresence mode=\"wait\">\n {showStop ? (\n <MotionDiv key=\"stop\" snapExit distance={0}>\n <SquareIcon className=\"size-3 fill-current\" />\n </MotionDiv>\n ) : !isStreaming && (shouldBlockSending || isUploading) ? (\n <MotionDiv key=\"loading\" snapExit distance={0}>\n <CircleDashed className=\"size-4 animate-spin animate-iteration-infinite\" />\n </MotionDiv>\n ) : (\n <MotionDiv key=\"send\" snapExit distance={0}>\n <ArrowUpIcon className=\"size-4\" />\n </MotionDiv>\n )}\n </AnimatePresence>\n </Button>\n </Tooltippy>\n </div>\n </div>\n </div>\n </div>\n </div>\n );\n}\n\n/** How long a send waits for a mark's snapshot upload still in flight. */\nconst SNAPSHOT_UPLOAD_GRACE_MS = 1500;\n\n/**\n * What the visitor wrote on their marks, as the message text for a send that\n * carries no typed message. One note per line, in the order they were\n * attached; null when nobody wrote anything.\n */\nfunction markNotes(marks: PageMark[]): string | null {\n const notes = marks.flatMap((mark) => {\n const note = mark.note?.trim();\n return note ? [note] : [];\n });\n return notes.length > 0 ? notes.join('\\n') : null;\n}\n","import { cn } from '../../components/lib/utils/cn';\nimport { useInitialQuestionRequired } from '../../hooks/useInitialQuestionRequired';\nimport {\n useConfig,\n useCsat,\n useMessages,\n useSessions,\n useWidget,\n useWidgetRouter,\n} from '@opencx/widget-react-headless';\nimport { AnimatePresence } from 'framer-motion';\nimport { CircleCheckIcon } from 'lucide-react';\nimport React from 'react';\nimport { CsatSurvey } from '../../components/CsatSurvey';\nimport { MightSolveUserIssueSuggestedReplies } from '../../components/MightSolveUserIssueSuggestedReplies';\nimport { SuggestedReplyButton } from '../../components/SuggestedReplyButton';\nimport { MotionDiv__VerticalReveal } from '../../components/lib/MotionDiv__VerticalReveal';\nimport { Button } from '../../components/lib/button';\nimport { useTranslation } from '../../hooks/useTranslation';\nimport { ChatFooterItems } from './ChatFooterItems';\nimport { ChatInput } from './ChatInput';\n\nfunction NewConvOrBackToConvsButton() {\n const { widgetCtx } = useWidget();\n const { router } = useConfig();\n const { canCreateNewSession } = useSessions();\n const { toSessionsScreen } = useWidgetRouter();\n const { t } = useTranslation();\n\n return (\n <>\n {canCreateNewSession || !!router?.chatScreenOnly ? (\n <Button onClick={widgetCtx.resetChat} className=\"rounded-2xl w-full\">\n {t('new_conversation')}\n </Button>\n ) : (\n <Button onClick={toSessionsScreen} className=\"rounded-2xl w-full\">\n {t('back_to_conversations')}\n </Button>\n )}\n </>\n );\n}\n\nfunction SessionClosedSection() {\n const { t } = useTranslation();\n const { isCsatRequested, isCsatSubmitted } = useCsat();\n\n return (\n <div className=\"p-2\">\n <div className=\"p-2 bg-muted rounded-[var(--opencx-inset-radius)]\">\n <AnimatePresence mode=\"wait\">\n {isCsatRequested || isCsatSubmitted ? (\n <MotionDiv__VerticalReveal key=\"csat\">\n <CsatSurvey />\n <AnimatePresence mode=\"wait\">\n {isCsatSubmitted && (\n <MotionDiv__VerticalReveal key=\"new-conv-or-back-to-convs-button\">\n <NewConvOrBackToConvsButton />\n </MotionDiv__VerticalReveal>\n )}\n </AnimatePresence>\n </MotionDiv__VerticalReveal>\n ) : (\n <MotionDiv__VerticalReveal key=\"session-closed\">\n <div className=\"ps-2 flex items-center gap-1 pb-2\">\n <CircleCheckIcon className=\"size-4 text-emerald-600\" />\n <h2 className=\"text-sm font-medium\">\n {t('your_issue_has_been_resolved')}\n </h2>\n </div>\n <NewConvOrBackToConvsButton />\n </MotionDiv__VerticalReveal>\n )}\n </AnimatePresence>\n </div>\n </div>\n );\n}\n\nexport function ChatFooter() {\n const { initialQuestions, initialQuestionsPosition, thisWasHelpfulOrNot } =\n useConfig();\n const { sessionState } = useSessions();\n const { messagesState } = useMessages();\n\n const noMessages = messagesState.messages.length === 0;\n const initialQuestionRequired = useInitialQuestionRequired();\n\n return (\n <footer>\n <AnimatePresence mode=\"wait\">\n {sessionState.session && !sessionState.session?.isOpened ? (\n <MotionDiv__VerticalReveal key=\"session-closed\">\n <SessionClosedSection />\n <ChatFooterItems />\n </MotionDiv__VerticalReveal>\n ) : (\n <MotionDiv__VerticalReveal key=\"chat-input\">\n {messagesState.lastAIResMightSolveUserIssue &&\n thisWasHelpfulOrNot?.enabled !== false && (\n <MightSolveUserIssueSuggestedReplies />\n )}\n\n {noMessages &&\n initialQuestions &&\n initialQuestionsPosition !== 'below-initial-messages' && (\n <div\n className={cn(\n 'flex items-center flex-row justify-end gap-2 flex-wrap px-2',\n initialQuestionRequired && 'pb-4',\n )}\n >\n {initialQuestions?.map((iq, index) => (\n <SuggestedReplyButton\n key={`${iq}-${index}`}\n suggestion={iq}\n />\n ))}\n </div>\n )}\n\n {!initialQuestionRequired && <ChatInput />}\n <ChatFooterItems />\n </MotionDiv__VerticalReveal>\n )}\n </AnimatePresence>\n </footer>\n );\n}\n","import {\n type LiteralWidgetComponentKey,\n type SafeExtract,\n} from '@opencx/widget-core';\nimport {\n useBot,\n useIsAwaitingBotReply,\n useMessages,\n useWidget,\n} from '@opencx/widget-react-headless';\nimport React, { useEffect, useMemo, useRef, useState } from 'react';\nimport { SessionResolvedComponent } from '../../components/custom-components/SessionResolvedComponent';\nimport { dc } from '../../utils/data-component';\nimport { groupMessagesByType } from '../../utils/group-messages-by-type';\nimport { ChatBannerItems } from './ChatBannerItems';\nimport { ChatCustomStatus } from './ChatCustomStatus';\nimport { InitialMessages } from './InitialMessages';\nimport { MessageGroups } from './MessageGroups';\nimport { ChatBottomComponents } from '../../components/custom-components/ChatBottomComponents';\n\nexport function ChatMain() {\n const {\n messagesState: { messages },\n } = useMessages();\n const { isAwaitingBotReply } = useIsAwaitingBotReply();\n const { componentStore } = useWidget();\n const bot = useBot();\n\n const groupedMessages = useMemo(\n () => groupMessagesByType(messages),\n [messages],\n );\n\n const lastMessage = messages.at(-1);\n const lastMessageId = lastMessage?.id;\n const lastMessageType = lastMessage?.type;\n const previousMessageId = useRef(lastMessageId);\n const [typingPaused, setTypingPaused] = useState(false);\n const showTypingIndicator = isAwaitingBotReply && !typingPaused;\n\n useEffect(() => {\n const receivedMessage = previousMessageId.current !== lastMessageId;\n previousMessageId.current = lastMessageId;\n if (!isAwaitingBotReply || lastMessageType !== 'AI') {\n setTypingPaused(false);\n return;\n }\n if (!receivedMessage) return;\n\n // Let each completed update land before showing that more is coming.\n setTypingPaused(true);\n const resumeTyping = setTimeout(() => setTypingPaused(false), 600);\n return () => clearTimeout(resumeTyping);\n }, [isAwaitingBotReply, lastMessageId, lastMessageType]);\n\n const LoadingComponent = componentStore.getComponent(\n 'loading' satisfies SafeExtract<LiteralWidgetComponentKey, 'loading'>,\n );\n\n /* ------------------------------------------------------ */\n /* Auto Scroller */\n /* ------------------------------------------------------ */\n const messagesContainerRef = useRef<HTMLDivElement>(null);\n function handleNewMessage() {\n setTimeout(() => {\n const container_ = messagesContainerRef.current;\n if (container_) {\n container_.scrollTop = container_.scrollHeight;\n }\n }, 0);\n }\n\n useEffect(() => {\n handleNewMessage();\n }, [messages, showTypingIndicator]);\n\n return (\n <div\n {...dc('chat/msgs/root')}\n ref={messagesContainerRef}\n className=\"max-h-full scroll-smooth relative flex-1 py-2 px-4 flex flex-col gap-2 overflow-auto\"\n >\n <ChatCustomStatus />\n <ChatBannerItems />\n <InitialMessages />\n\n <MessageGroups\n groups={groupedMessages}\n pendingReply={isAwaitingBotReply}\n />\n\n {/* Typing indicator while awaiting the (blocking) bot reply. */}\n {showTypingIndicator && LoadingComponent && (\n <LoadingComponent agent={bot} />\n )}\n\n <ChatBottomComponents />\n <SessionResolvedComponent />\n </div>\n );\n}\n","import {\n useMessages,\n useSessions,\n useWidget,\n} from '@opencx/widget-react-headless';\nimport { AnimatePresence } from 'framer-motion';\nimport React, { useRef } from 'react';\nimport { Header } from '../../components/Header';\nimport { LoadingSpinner } from '../../components/lib/LoadingSpinner';\nimport { MotionDiv } from '../../components/lib/MotionDiv';\nimport { cn } from '../../components/lib/utils/cn';\nimport { useCanvas } from '../../hooks/useCanvas';\nimport { useSetWidgetSize } from '../../hooks/useSetWidgetSize';\nimport { useTheme } from '../../hooks/useTheme';\nimport { dc } from '../../utils/data-component';\nimport { AgentChatMain } from './agent/AgentChatMain';\nimport { ChatCanvas } from './ChatCanvas';\nimport { ChatFooter } from './ChatFooter';\nimport { ChatMain } from './ChatMain';\n\nexport function ChatScreen() {\n const {\n messagesState: { isInitialFetchLoading },\n } = useMessages();\n // Streaming orgs get the useChat-based surface; others keep the blocking\n // bot-chat engine. The server decides at init — a per-instance constant,\n // resolved before the chat renders.\n const { widgetCtx } = useWidget();\n const isStreamingEngine = widgetCtx.streaming;\n const {\n sessionState: { session },\n } = useSessions();\n const { isCanvasOpen } = useCanvas();\n const { theme } = useTheme();\n\n useSetWidgetSize({\n width: isCanvasOpen\n ? theme.screens.chat.withCanvas.width\n : theme.screens.chat.width,\n height: isCanvasOpen\n ? theme.screens.chat.withCanvas.height\n : theme.screens.chat.height,\n });\n\n // The key is the session id, so that when chat is reset, the animation replays\n const chatContentKeyRef = useRef(session?.id || 'chat').current;\n\n return (\n <div\n {...dc('chat/root')}\n className={cn('flex flex-col overflow-hidden')}\n style={{\n width: '100vw', // Relative to the iframe\n maxWidth: '100vw', // Relative to the iframe\n height: '100vh', // Relative to the iframe\n maxHeight: '100vh', // Relative to the iframe\n }}\n >\n <div className=\"relative size-full justify-between flex flex-col\">\n <Header />\n <AnimatePresence mode=\"wait\">\n {isInitialFetchLoading ? (\n <MotionDiv\n key=\"loading\"\n className=\"flex flex-col items-center justify-center w-full flex-1\"\n >\n <LoadingSpinner />\n </MotionDiv>\n ) : (\n <MotionDiv\n key={chatContentKeyRef}\n className=\"flex items-start h-full flex-1 overflow-auto\"\n // If we don't snap exit, the initial questions will show before the animation starts\n snapExit\n >\n <div\n {...dc('chat/main/root')}\n className={cn(\n 'flex flex-col h-full overflow-auto transition-all',\n isCanvasOpen ? 'w-2/5' : 'w-full',\n )}\n style={{\n transitionTimingFunction:\n theme.screens.chat.withCanvas.transitionTimingFunction,\n transitionDuration:\n theme.screens.chat.withCanvas.transitionDuration,\n }}\n >\n {isStreamingEngine ? <AgentChatMain /> : <ChatMain />}\n <ChatFooter />\n </div>\n <div\n {...dc('chat/canvas/root')}\n className={cn(\n 'h-full overflow-auto transition-all',\n isCanvasOpen ? 'w-3/5' : 'w-0',\n )}\n style={{\n transitionTimingFunction:\n theme.screens.chat.withCanvas.transitionTimingFunction,\n transitionDuration:\n theme.screens.chat.withCanvas.transitionDuration,\n }}\n >\n <ChatCanvas />\n </div>\n </MotionDiv>\n )}\n </AnimatePresence>\n </div>\n </div>\n );\n}\n","import React, { useEffect, useState } from 'react';\nimport { useWidget } from '@opencx/widget-react-headless';\nimport type { ApprovalPreference } from '@opencx/widget-core';\nimport { ArrowLeft, ChevronRight, Unplug } from 'lucide-react';\nimport { Button } from './lib/button';\nimport { Header } from './Header';\nimport { McpIcon } from './lib/McpIcon';\n\ntype Connection = Awaited<\n ReturnType<\n ReturnType<typeof useWidget>['widgetCtx']['api']['listConnections']\n >\n>[number];\n\nexport function ConnectionsSettings({\n children,\n}: {\n children: React.ReactNode;\n}) {\n const { widgetCtx, config } = useWidget();\n const [open, setOpen] = useState(false);\n const [selectedId, setSelectedId] = useState<string | null>(null);\n const [search, setSearch] = useState('');\n const [connections, setConnections] = useState<Connection[]>([]);\n const [rules, setRules] = useState<ApprovalPreference[]>([]);\n const [busy, setBusy] = useState(false);\n const [error, setError] = useState('');\n useEffect(() => {\n let cancelled = false;\n if (config.capabilities?.connections !== true) return;\n void Promise.all([\n widgetCtx.api.listConnections(),\n widgetCtx.api.listApprovalPreferences(),\n ])\n .then(([items, permissions]) => {\n if (cancelled) return;\n setConnections(items.filter((item) => item.status !== 'not_connected'));\n setRules(permissions);\n })\n .catch(() => {\n /* Unauthenticated visitors have no personal connections. */\n });\n return () => {\n cancelled = true;\n };\n }, [widgetCtx, config.capabilities?.connections]);\n const change = async (operation: () => Promise<void>) => {\n setBusy(true);\n setError('');\n try {\n await operation();\n } catch {\n setError('Could not save the change. Try again.');\n } finally {\n setBusy(false);\n }\n };\n if (!open || config.capabilities?.connections !== true)\n return (\n <>\n <Header />\n {config.capabilities?.connections === true &&\n connections.length > 0 && (\n <Button\n variant=\"ghost\"\n className=\"mx-3 my-1 h-9 justify-start gap-2 text-sm\"\n onClick={() => setOpen(true)}\n >\n <Unplug className=\"size-4\" /> Connections{' '}\n <ChevronRight className=\"ml-auto size-4\" />\n </Button>\n )}\n {children}\n </>\n );\n return (\n <section\n className=\"flex-1 overflow-y-auto px-4 pb-4 pt-3 space-y-5\"\n aria-label=\"Connections\"\n >\n <div className=\"flex h-8 items-center gap-2 pr-16\">\n <Button\n variant=\"ghost\"\n size=\"icon\"\n className=\"size-7\"\n aria-label={selectedId ? 'Back to connections' : 'Back to sessions'}\n onClick={() => (selectedId ? setSelectedId(null) : setOpen(false))}\n >\n <ArrowLeft className=\"size-4\" />\n </Button>\n <h2 className=\"text-sm font-medium\">Connections</h2>\n </div>\n {!connections.length && (\n <p className=\"text-sm text-muted-foreground\">No connected services.</p>\n )}\n {!selectedId && (\n <>\n <input\n type=\"search\"\n aria-label=\"Search connections\"\n placeholder=\"Search connections\"\n value={search}\n onChange={(event) => setSearch(event.target.value)}\n className=\"h-8 w-full rounded-full border border-foreground/15 bg-transparent px-3 text-sm outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n />\n <div className=\"space-y-1\">\n <h3 className=\"border-b border-foreground/10 pb-2 text-xs font-medium\">\n Connected services\n </h3>\n {connections\n .filter((item) =>\n item.name.toLowerCase().includes(search.toLowerCase()),\n )\n .map((item) => (\n <button\n key={item.server_id}\n type=\"button\"\n onClick={() => setSelectedId(item.server_id)}\n className=\"flex w-full items-center gap-3 rounded-xl px-2 py-3 text-left hover:bg-secondary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring\"\n >\n <span className=\"flex size-9 shrink-0 items-center justify-center rounded-xl border border-foreground/10 bg-background p-2\">\n <McpIcon />\n </span>\n <span className=\"min-w-0 flex-1\">\n <span className=\"block text-sm font-medium\">\n {item.name}\n </span>\n <span className=\"block text-xs text-muted-foreground\">\n {item.status === 'connected'\n ? 'Connected'\n : 'Reconnect required'}\n </span>\n </span>\n <ChevronRight className=\"size-4 text-muted-foreground\" />\n </button>\n ))}\n {connections.length > 0 &&\n !connections.some((item) =>\n item.name.toLowerCase().includes(search.toLowerCase()),\n ) && (\n <p className=\"py-3 text-xs text-muted-foreground\">\n No matching connections.\n </p>\n )}\n </div>\n </>\n )}\n {connections\n .filter((connection) => connection.server_id === selectedId)\n .map((connection) => (\n <div\n key={connection.server_id}\n className=\"border-b border-foreground/10 pb-5 space-y-3 last:border-0\"\n >\n <div className=\"flex size-12 items-center justify-center rounded-xl border border-foreground/10 bg-background p-3\">\n <McpIcon />\n </div>\n <div className=\"flex items-center gap-3\">\n <div className=\"flex-1 min-w-0\">\n <p className=\"text-sm font-medium\">{connection.name}</p>\n <p className=\"text-xs text-muted-foreground\">\n {connection.status === 'connected'\n ? 'Connected'\n : 'Reconnect required'}\n </p>\n </div>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"h-7 px-2 text-xs\"\n disabled={busy}\n onClick={() =>\n void change(async () => {\n await widgetCtx.api.disconnectConnection(\n connection.server_id,\n );\n setSelectedId(null);\n setConnections((items) =>\n items.filter(\n (item) => item.server_id !== connection.server_id,\n ),\n );\n setRules((items) =>\n items.filter(\n (item) => item.serverId !== connection.server_id,\n ),\n );\n })\n }\n >\n Disconnect\n </Button>\n </div>\n {rules.some((rule) => rule.serverId === connection.server_id) ? (\n <div className=\"space-y-2\">\n <h3 className=\"text-xs font-medium\">\n Saved approvals (\n {\n rules.filter(\n (rule) => rule.serverId === connection.server_id,\n ).length\n }\n )\n </h3>\n <p className=\"text-xs text-muted-foreground\">\n Removing an approval makes the widget ask again next time.\n </p>\n <ul\n className=\"max-h-64 overflow-y-auto divide-y divide-foreground/10 rounded-xl border border-foreground/10\"\n aria-label={`${connection.name} saved approvals`}\n >\n {rules\n .filter((rule) => rule.serverId === connection.server_id)\n .map((rule) => (\n <li key={rule.key} className=\"flex items-start gap-3 p-3\">\n <div className=\"flex-1 min-w-0 space-y-1\">\n <p className=\"text-xs font-medium break-words\">\n {rule.toolName.replace(/[_-]+/g, ' ')}\n </p>\n <p className=\"text-xs text-muted-foreground break-words\">\n {rule.message}\n </p>\n </div>\n <Button\n variant=\"secondary\"\n size=\"sm\"\n className=\"h-7 shrink-0 px-2 text-xs\"\n disabled={busy}\n onClick={() =>\n void change(async () => {\n await widgetCtx.api.revokeApprovalPreference(\n rule.serverId,\n rule.key,\n );\n setRules((items) =>\n items.filter(\n (item) =>\n item.serverId !== rule.serverId ||\n item.key !== rule.key,\n ),\n );\n })\n }\n >\n Remove approval\n </Button>\n </li>\n ))}\n </ul>\n </div>\n ) : (\n <p className=\"text-xs text-muted-foreground\">\n No saved approvals\n </p>\n )}\n </div>\n ))}\n {error && (\n <p role=\"alert\" className=\"text-xs text-destructive\">\n {error}\n </p>\n )}\n </section>\n );\n}\n","import React from 'react';\nimport { cn } from './utils/cn';\n\nfunction Skeleton({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={cn('animate-pulse rounded-md bg-secondary', className)}\n {...props}\n />\n );\n}\n\nexport { Skeleton };\n","import React from 'react';\nimport { cn } from '../lib/utils/cn';\n\nexport function OpenLogoSvg({ className }: { className?: string }) {\n return (\n <svg\n width=\"26\"\n height=\"32\"\n viewBox=\"0 0 26 32\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={cn('text-primary-foreground', className)}\n >\n <path\n d=\"M1.34103 25.6132H5.44245C5.74203 25.6228 6.02673 25.7462 6.23867 25.9582C6.45062 26.1703 6.5739 26.4551 6.58348 26.7548V30.8584C6.59305 31.1581 6.71634 31.443 6.92828 31.655C7.14023 31.8671 7.42492 31.9904 7.7245 32H18.2894C18.589 31.9904 18.8737 31.8671 19.0856 31.655C19.2976 31.443 19.4209 31.1581 19.4304 30.8584V26.7548C19.4401 26.4545 19.5638 26.1692 19.7765 25.957C19.9892 25.7449 20.2748 25.6219 20.5749 25.6132H24.659C24.9586 25.6036 25.2433 25.4803 25.4552 25.2682C25.6671 25.0562 25.7904 24.7713 25.8 24.4716V7.52839C25.7904 7.22865 25.6671 6.94381 25.4552 6.73176C25.2433 6.5197 24.9586 6.39635 24.659 6.38677H20.561C20.2603 6.37802 19.9742 6.25457 19.7614 6.04169C19.5487 5.82881 19.4253 5.54261 19.4165 5.24168V1.14161C19.4072 0.84419 19.2858 0.561291 19.0768 0.349589C18.8678 0.137887 18.5865 0.0130193 18.2894 0L7.7245 0C7.42492 0.00957792 7.14023 0.132929 6.92828 0.344983C6.71634 0.557036 6.59305 0.841878 6.58348 1.14161V5.24168C6.57477 5.54203 6.45187 5.82773 6.23983 6.04052C6.0278 6.25331 5.74262 6.37715 5.44245 6.38677H1.34103C1.04144 6.39635 0.756749 6.5197 0.544805 6.73176C0.332861 6.94381 0.209574 7.22865 0.200001 7.52839V24.4716C0.209574 24.7713 0.332861 25.0562 0.544805 25.2682C0.756749 25.4803 1.04144 25.6036 1.34103 25.6132ZM6.58348 24.4716V7.52839C6.59305 7.22865 6.71634 6.94381 6.92828 6.73176C7.14023 6.5197 7.42492 6.39635 7.7245 6.38677H18.2894C18.589 6.39635 18.8737 6.5197 19.0856 6.73176C19.2976 6.94381 19.4209 7.22865 19.4304 7.52839V24.4716C19.4209 24.7713 19.2976 25.0562 19.0856 25.2682C18.8737 25.4803 18.589 25.6036 18.2894 25.6132H7.7245C7.42492 25.6036 7.14023 25.4803 6.92828 25.2682C6.71634 25.0562 6.59305 24.7713 6.58348 24.4716Z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n}\n","import { useConfig } from '@opencx/widget-react-headless';\nimport * as React from 'react';\nimport { cn } from './lib/utils/cn.js';\nimport { Wobble } from './lib/wobble.js';\nimport { OpenLogoSvg } from './svg/OpenLogoSvg.js';\n\nexport function PoweredByOpen({ className }: { className?: string }) {\n const { token } = useConfig();\n\n return (\n <div\n className={cn(\n 'flex items-center justify-center gap-2 p-2 pt-0',\n className,\n )}\n >\n <Wobble>\n <a\n href={`https://open.cx/?ref=${token}`}\n target=\"_blank\"\n rel=\"noreferrer\"\n className={cn(\n 'text-[10px] flex items-center',\n 'text-muted-foreground/70 [&_svg]:text-muted-foreground/70',\n 'hover:text-primary [&_svg]:hover:text-primary',\n )}\n >\n <span>Powered by</span>\n <span>&nbsp;</span>\n <span className=\"flex items-center gap-[1px]\">\n <span>\n <OpenLogoSvg className=\"size-3 inline-block\" />\n </span>\n <span className=\"font-semibold\">open</span>\n </span>\n </a>\n </Wobble>\n </div>\n );\n}\n","import { type SessionDto } from '@opencx/widget-core';\nimport {\n useBot,\n useConfig,\n useSessions,\n useWidgetRouter,\n} from '@opencx/widget-react-headless';\nimport { AnimatePresence } from 'framer-motion';\nimport { ChevronRightIcon, UserRoundIcon } from 'lucide-react';\nimport React from 'react';\nimport rehypeRaw from 'rehype-raw';\nimport remarkGfm from 'remark-gfm';\nimport { ConnectionsSettings } from '../../components/ConnectionsSettings';\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from '../../components/lib/avatar';\nimport { Button } from '../../components/lib/button';\nimport { CustomStatusBadge } from '../../components/CustomStatus';\nimport { LoadingSpinner } from '../../components/lib/LoadingSpinner';\nimport { MotionDiv } from '../../components/lib/MotionDiv';\nimport { Skeleton } from '../../components/lib/skeleton';\nimport { cn } from '../../components/lib/utils/cn';\nimport { MemoizedReactMarkdown } from '../../components/MemoizedReactMarkdown';\nimport { PoweredByOpen } from '../../components/PoweredByOpen';\nimport { useTranslation } from '../../hooks/useTranslation';\nimport { useSetWidgetSize } from '../../hooks/useSetWidgetSize';\nimport { useTheme } from '../../hooks/useTheme';\nimport { dc } from '../../utils/data-component';\n\nfunction SectionTitle({ children }: { children: React.ReactNode }) {\n return (\n <p className=\"ps-4 text-xs text-muted-foreground/75 uppercase font-semibold tracking-tight\">\n {children}\n </p>\n );\n}\n\nfunction SessionCard({\n session,\n className,\n}: {\n session: SessionDto;\n className?: string;\n}) {\n const { humanAgent } = useConfig();\n const bot = useBot();\n const { toChatScreen } = useWidgetRouter();\n\n const assigneeName =\n session.assignee.kind === 'human'\n ? humanAgent?.name || session.assignee.name || 'Support Agent'\n : bot.name;\n const assigneeAvatarUrl =\n session.assignee.kind === 'human'\n ? humanAgent?.avatarUrl || session.assignee.avatarUrl || ''\n : bot.avatarUrl || bot.avatar || '';\n\n return (\n <Button\n variant=\"ghost\"\n size=\"lg\"\n className={cn(\n 'rounded-full p-2 pe-4 flex text-start justify-between w-full whitespace-normal',\n className,\n )}\n onClick={() => toChatScreen(session.id)}\n >\n <div className=\"flex-1 flex gap-2 items-center min-w-0\">\n <AnimatePresence mode=\"wait\">\n <MotionDiv snapExit>\n <Avatar className=\"size-10\">\n <AvatarImage src={assigneeAvatarUrl} alt=\"Agent Icon\" />\n <AvatarFallback>\n <UserRoundIcon className=\"size-4\" />\n </AvatarFallback>\n </Avatar>\n </MotionDiv>\n </AnimatePresence>\n <div className=\"flex-1 min-w-0\">\n <AnimatePresence mode=\"wait\">\n <MotionDiv key={assigneeName} snapExit>\n {assigneeName}\n </MotionDiv>\n </AnimatePresence>\n <AnimatePresence mode=\"wait\">\n {session.lastMessage ? (\n <MotionDiv key={session.lastMessage || 'content'} snapExit>\n <MemoizedReactMarkdown\n remarkPlugins={[remarkGfm]}\n rehypePlugins={[rehypeRaw]}\n // Do not add `prose` styling for last message preview\n className=\"line-clamp-1 overflow-hidden text-ellipsis text-xs text-muted-foreground\"\n >\n {session.lastMessage}\n </MemoizedReactMarkdown>\n </MotionDiv>\n ) : (\n <MotionDiv key=\"skeleton\" className=\"w-1/2\" snapExit>\n <Skeleton className=\"h-4 w-full\" />\n </MotionDiv>\n )}\n </AnimatePresence>\n <AnimatePresence mode=\"wait\">\n {session.customStatus && (\n <MotionDiv\n key={session.customStatus.id}\n className=\"mt-1\"\n snapExit\n >\n <CustomStatusBadge customStatus={session.customStatus} />\n </MotionDiv>\n )}\n </AnimatePresence>\n </div>\n </div>\n <ChevronRightIcon className=\"size-4 text-muted-foreground shrink-0 rtl:-scale-100\" />\n </Button>\n );\n}\n\nfunction SessionsList() {\n const { t } = useTranslation();\n const { toChatScreen } = useWidgetRouter();\n const {\n sessionsState: { data: sessions, isInitialFetchLoading: isLoading },\n openSessions,\n closedSessions,\n canCreateNewSession,\n } = useSessions();\n\n return (\n <div\n {...dc('sessions/list')}\n className=\"flex-1 flex flex-col overflow-scroll py-2 px-2\"\n >\n <AnimatePresence mode=\"wait\">\n {isLoading ? (\n <MotionDiv\n key=\"loading\"\n className=\"flex-1 flex items-center justify-center\"\n >\n <LoadingSpinner />\n </MotionDiv>\n ) : (\n <MotionDiv\n key=\"sessions\"\n className=\"flex-1 flex flex-col gap-2 relative\"\n >\n {sessions.length ? (\n <>\n <AnimatePresence>\n {openSessions.length > 0 && (\n <MotionDiv\n fadeIn=\"up\"\n delay={0.2}\n key=\"open-sessions\"\n className=\"space-y-2\"\n snapExit\n >\n {openSessions.map((s) => (\n <SessionCard key={s.id} session={s} />\n ))}\n </MotionDiv>\n )}\n\n {closedSessions.length > 0 && (\n <MotionDiv\n key=\"closed-sessions\"\n className=\"space-y-2\"\n delay={0.2}\n snapExit\n >\n <SectionTitle>{t('closed_conversations')}</SectionTitle>\n {closedSessions.map((s) => (\n <SessionCard\n key={s.id}\n session={s}\n className=\"opacity-50 hover:opacity-100\"\n />\n ))}\n </MotionDiv>\n )}\n </AnimatePresence>\n\n {canCreateNewSession && (\n <div className=\"mt-auto w-full rounded-3xl sticky bottom-0 outline outline-8 outline-background bg-background\">\n <Button\n {...dc('sessions/new_conversation_btn')}\n size=\"lg\"\n key=\"new-session\"\n className=\"w-full\"\n onClick={() => toChatScreen()}\n >\n {t('new_conversation')}\n </Button>\n </div>\n )}\n </>\n ) : (\n <div className=\"flex-1 flex flex-col gap-2 items-center\">\n <div className=\"flex-1 flex items-center justify-center\">\n <p className=\"text-muted-foreground\">\n {t('no_conversations_yet')}\n </p>\n </div>\n <Button\n {...dc('sessions/new_conversation_btn')}\n size=\"lg\"\n key=\"new-session\"\n className=\"w-full\"\n onClick={() => toChatScreen()}\n >\n {t('new_conversation')}\n </Button>\n </div>\n )}\n </MotionDiv>\n )}\n </AnimatePresence>\n </div>\n );\n}\n\nexport function SessionsScreen() {\n const { theme } = useTheme();\n useSetWidgetSize({\n width: theme.screens.sessions.width,\n height: theme.screens.sessions.height,\n });\n\n return (\n <div\n {...dc('sessions/root')}\n className={cn('flex flex-col overflow-hidden bg-background')}\n style={{\n width: '100vw', // Relative to the iframe\n maxWidth: '100vw', // Relative to the iframe\n height: '100vh', // Relative to the iframe\n maxHeight: '100vh', // Relative to the iframe\n }}\n >\n <div className=\"size-full flex flex-col\">\n <ConnectionsSettings>\n <SessionsList />\n </ConnectionsSettings>\n <PoweredByOpen />\n </div>\n </div>\n );\n}\n","import * as React from 'react';\nimport { useIsSmallScreen } from '../../hooks/useIsSmallScreen.js';\nimport { cn } from './utils/cn.js';\n\nexport type InputProps = React.InputHTMLAttributes<HTMLInputElement>;\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, type, ...props }, ref) => {\n const { isSmallScreen } = useIsSmallScreen();\n\n return (\n <input\n ref={ref}\n type={type}\n className={cn(\n // 16px on mobiles prevents auto-zoom on the input when focused\n isSmallScreen ? 'text-[16px]' : 'text-sm',\n 'flex w-full rounded-xl p-2 ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-primary-foreground placeholder:text-muted-foreground/75 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 transition',\n 'rounded-2xl px-4',\n 'border shadow-sm',\n className,\n )}\n {...props}\n />\n );\n },\n);\nInput.displayName = 'Input';\n\nexport { Input };\n","import { useEffect, useRef } from 'react';\nimport { useConfig, useWidget } from '@opencx/widget-react-headless';\n\nexport function useWidgetContentHeight() {\n const { contentIframeRef } = useWidget();\n const { inline } = useConfig();\n /**\n * This is the element that we will observe for height changes\n */\n const observedElementRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n const contentRoot = contentIframeRef?.current;\n\n if (contentRoot && observedElementRef.current) {\n const observedElement = observedElementRef.current;\n\n let animationFrame: number;\n const observer = new ResizeObserver(() => {\n animationFrame = requestAnimationFrame(() => {\n const height = observedElement.offsetHeight;\n contentRoot.style.setProperty(\n '--opencx-widget-height',\n inline ? '100%' : `${height.toFixed(1)}px`,\n );\n });\n });\n observer.observe(observedElement);\n\n return () => {\n cancelAnimationFrame(animationFrame);\n observer.unobserve(observedElement);\n };\n }\n }, [contentIframeRef, inline]);\n\n return { observedElementRef };\n}\n","import {\n useConfig,\n useContact,\n useWidget,\n useWidgetTrigger,\n} from '@opencx/widget-react-headless';\nimport { SendHorizontal, XIcon } from 'lucide-react';\nimport React, { useState } from 'react';\nimport useAsyncFn from 'react-use/lib/useAsyncFn';\nimport { z } from 'zod';\nimport { Button } from '../../components/lib/button';\nimport { Input } from '../../components/lib/input';\nimport { MotionDiv } from '../../components/lib/MotionDiv';\nimport { cn } from '../../components/lib/utils/cn';\nimport { PoweredByOpen } from '../../components/PoweredByOpen';\nimport { useIsSmallScreen } from '../../hooks/useIsSmallScreen';\nimport { useTranslation } from '../../hooks/useTranslation';\nimport { useSetWidgetSize } from '../../hooks/useSetWidgetSize';\nimport { useTheme } from '../../hooks/useTheme';\nimport { useWidgetContentHeight } from '../../hooks/useWidgetContentHeight';\n\nconst schema = z.object({\n name: z.string().min(2),\n email: z.string().email(),\n});\n\nexport function WelcomeScreen() {\n const {\n widgetCtx: { org },\n } = useWidget();\n const { setIsOpen } = useWidgetTrigger();\n const { createUnverifiedContact } = useContact();\n const { isSmallScreen } = useIsSmallScreen();\n const config = useConfig();\n const { theme } = useTheme();\n const { t } = useTranslation();\n const { observedElementRef } = useWidgetContentHeight();\n\n useSetWidgetSize({\n height: undefined,\n width: theme.screens.welcome.width,\n });\n\n const [name, setName] = useState(config.prefillUserData?.name || '');\n const [email, setEmail] = useState(config.prefillUserData?.email || '');\n\n const extraDataFields = (config.extraDataCollectionFields || []).filter(\n (f) => f !== 'name' && f !== 'email' && !!f,\n );\n\n const [extraData, setExtraData] = useState<Record<string, string>>({});\n\n const [handleSubmitState, handleSubmit] = useAsyncFn(\n async (event: React.FormEvent<HTMLFormElement>) => {\n event.preventDefault();\n\n const result = schema.safeParse({ name, email });\n if (result.success) {\n await createUnverifiedContact(\n {\n email: result.data.email,\n non_verified_name: result.data.name,\n },\n // Only pass extra data if there is any\n Object.values(extraData).filter(Boolean).length\n ? extraData\n : undefined,\n );\n }\n },\n [name, email, extraData],\n );\n\n return (\n <div\n style={{\n width: '100vw', // Relative to the iframe\n maxWidth: '100vw', // Relative to the iframe\n minHeight: theme.screens.welcome.minHeight,\n height: '100vh', // Relative to the iframe\n maxHeight: '100vh', // Relative to the iframe\n overflowY: 'auto',\n }}\n >\n <div\n ref={observedElementRef}\n className={cn(\n 'flex flex-col',\n isSmallScreen && 'h-full',\n 'bg-[radial-gradient(ellipse_at_top_left,hsl(var(--opencx-primary)),transparent),radial-gradient(ellipse_at_top_right,hsl(var(--opencx-primary)),transparent)]',\n )}\n >\n <div\n className={cn(\n 'flex-1 flex flex-col px-4 py-12 text-start space-y-4 relative z-10',\n 'text-primary-foreground',\n )}\n >\n {isSmallScreen && (\n <MotionDiv className=\"absolute top-6 end-6\">\n <Button size=\"selfless\" onClick={() => setIsOpen(false)}>\n <XIcon className=\"size-4\" />\n </Button>\n </MotionDiv>\n )}\n\n <div className=\"flex items-center justify-between w-full mb-2\">\n {config.assets?.organizationLogo ? (\n <img\n src={config.assets?.organizationLogo}\n alt=\"Company Logo\"\n className=\"h-8 w-auto object-contain\"\n />\n ) : (\n <h2 className=\"font-bold text-sm\">{org.name}</h2>\n )}\n </div>\n <div className=\"space-y-2\">\n <h1 className=\"text-[1.75rem] font-semibold tracking-tight leading-none\">\n {config.textContent?.welcomeScreen?.title ||\n t('welcome_screen_title')}\n </h1>\n\n <p className=\"text-sm\">\n {config.textContent?.welcomeScreen?.description ||\n t('welcome_screen_description')}\n </p>\n </div>\n </div>\n\n <div\n className={cn(\n 'z-10 m-2 px-2 pt-2 bp-0 space-y-2',\n 'bg-[white]',\n 'border shadow',\n 'rounded-3xl',\n )}\n >\n <form onSubmit={handleSubmit} className=\"space-y-2\">\n <Input\n value={name}\n onChange={(e) => setName(e.target.value)}\n required\n placeholder={t('your_name_placeholder')}\n name=\"name\"\n />\n <Input\n required\n value={email}\n onChange={(e) => setEmail(e.target.value)}\n type=\"email\"\n placeholder={t('your_email_placeholder')}\n name=\"email\"\n />\n {extraDataFields.map((field) => (\n <Input\n key={field}\n value={extraData[field]}\n onChange={(e) =>\n setExtraData((prev) => ({\n ...prev,\n [field]: e.target.value,\n }))\n }\n placeholder={`${field} (${t('optional')})`}\n />\n ))}\n\n <Button\n disabled={handleSubmitState.loading}\n className=\"w-full\"\n size=\"lg\"\n >\n {handleSubmitState.loading\n ? t('start_chat_button_loading')\n : t('start_chat_button')}\n <SendHorizontal className=\"size-4 rtl:-scale-100\" />\n </Button>\n </form>\n\n <PoweredByOpen />\n </div>\n </div>\n </div>\n );\n}\n","import { isExhaustive } from '@opencx/widget-core';\nimport { useWidgetRouter } from '@opencx/widget-react-headless';\nimport React from 'react';\nimport { MotionDiv } from '../components/lib/MotionDiv';\nimport { ChatScreen } from './chat';\nimport { SessionsScreen } from './sessions';\nimport { WelcomeScreen } from './welcome';\n\nexport function RootScreen() {\n const {\n routerState: { screen },\n } = useWidgetRouter();\n\n return (\n // Route exits are instantaneous. Keep the keyed entry animation, but do not\n // queue old screens while welcome → sessions → chat changes in one frame.\n <div className=\"relative bg-background size-full\">\n {(() => {\n switch (screen) {\n case 'welcome':\n return (\n <MotionDiv\n key={screen}\n fadeIn=\"right\"\n className=\"size-full\"\n snapExit\n >\n <WelcomeScreen />\n </MotionDiv>\n );\n\n case 'sessions':\n return (\n <MotionDiv\n key={screen}\n fadeIn=\"right\"\n className=\"size-full\"\n snapExit\n >\n <SessionsScreen />\n </MotionDiv>\n );\n\n case 'chat':\n return (\n <MotionDiv\n key={screen}\n fadeIn=\"right\"\n className=\"size-full\"\n snapExit\n >\n <ChatScreen />\n </MotionDiv>\n );\n default: {\n isExhaustive(screen, RootScreen.name);\n return null;\n }\n }\n })()}\n </div>\n );\n}\n","import * as PopoverPrimitive from '@radix-ui/react-popover';\nimport IFrame from '@uiw/react-iframe';\nimport { motion } from 'framer-motion';\nimport React, { useEffect } from 'react';\nimport {\n useConfig,\n useDocumentDir,\n useWidget,\n useWidgetTrigger,\n} from '@opencx/widget-react-headless';\nimport {\n buildFrameHtml,\n FrameDocument,\n WIDGET_FRAME_TITLE,\n} from './components/FrameDocument';\nimport { MORPH_SPRING } from './motion';\nimport { useTheme } from './hooks/useTheme';\nimport { useTranslation } from './hooks/useTranslation';\nimport { RootScreen } from './screens';\n\nconst initialContent = buildFrameHtml();\n\n// Framer Motion 11's accelerated opacity animation cancels its WAAPI effect\n// before the final inline opacity/display is painted. Closing can expose the\n// previous opacity:1 for one frame. An update subscriber keeps this wrapper's\n// opacity on the same JS frame loop as its scale/y and transitionEnd, avoiding\n// that handoff without changing the spring or hiding the panel prematurely.\nconst keepShellAnimationSynchronized = () => {};\n\nexport function WidgetContent() {\n const { isOpen } = useWidgetTrigger();\n const { contentIframeRef, widgetCtx } = useWidget();\n const { inline } = useConfig();\n const { theme, computed } = useTheme();\n\n // The popover stays mounted while closed to preserve its conversation and\n // exit animation. Microphone capture must end when it closes, not on unmount.\n useEffect(() => {\n if (!isOpen) widgetCtx.dictationCtx.stop({ executeFinalCommand: false });\n }, [isOpen, widgetCtx]);\n\n return (\n <motion.div\n onUpdate={keepShellAnimationSynchronized}\n animate={isOpen ? 'visible' : 'hidden'}\n initial=\"hidden\"\n // Grow out of the FAB corner (bottom-right, where the trigger sits) so\n // the panel reads as emerging from the button — the companion morph\n // feel. Inline mode keeps its origin (no floating trigger to grow from).\n style={{ transformOrigin: inline ? undefined : 'bottom right' }}\n variants={{\n hidden: {\n opacity: 0,\n // The visible travel: scale up from the corner. Curve-only (opacity\n // + 8px) was imperceptible — the spring needs real distance to feel.\n scale: inline ? 1 : 0.9,\n y: 8,\n transitionEnd: { display: 'none' },\n transition: MORPH_SPRING,\n },\n visible: {\n opacity: 1,\n scale: 1,\n y: 0,\n display: 'block',\n height: inline ? '100%' : undefined,\n // Spring the morph (opacity + scale + y); snap the inline\n // `height: 100%` — a percentage height has no numeric baseline to\n // spring from and would warn / jump. Matches prior height behavior.\n transition: { ...MORPH_SPRING, height: { duration: 0 } },\n },\n }}\n >\n <IFrame\n ref={contentIframeRef}\n initialContent={initialContent}\n allowFullScreen\n title={WIDGET_FRAME_TITLE}\n style={{\n // @ts-expect-error this is a valid css variable\n '--opencx-widget-width': computed.minWidth,\n '--opencx-widget-height': computed.minHeight,\n\n minWidth: computed.minWidth,\n width: 'var(--opencx-widget-width)',\n maxWidth: computed.maxWidth, // Relative to the viewport\n\n minHeight: computed.minHeight,\n height: 'var(--opencx-widget-height)',\n maxHeight: computed.maxHeight, // Relative to the viewport\n\n overflow: 'hidden',\n /** outline is better than border because of box sizing; the outline wouldn't affect the content inside... the border will mess up how the children's border radius sits with the parent */\n outline: theme.widgetContentContainer.outline,\n outlineColor: theme.widgetContentContainer.outlineColor,\n borderRadius: theme.widgetContentContainer.borderRadius,\n boxShadow: theme.widgetContentContainer.boxShadow,\n transitionProperty: theme.widgetContentContainer.transitionProperty,\n transitionTimingFunction:\n theme.widgetContentContainer.transitionTimingFunction,\n transitionDuration: theme.widgetContentContainer.transitionDuration,\n\n // reset iframe defaults\n boxSizing: 'border-box',\n borderWidth: '0px',\n }}\n >\n <FrameDocument style={{ zIndex: theme.widgetContentContainer.zIndex }}>\n <RootScreen />\n </FrameDocument>\n </IFrame>\n </motion.div>\n );\n}\n\nexport function WidgetPopoverContent() {\n const { theme, triggerSide } = useTheme();\n const { dir: hostDocumentDir } = useDocumentDir();\n const { t } = useTranslation();\n\n // Radix/floating-ui resolves `align` logically against the floating element's\n // computed direction (inherited from the host page via the portal): on an RTL\n // host, 'end' means the physical LEFT edge. Map the resolved physical side\n // back to the logical align so the box always opens on the trigger's side.\n const align = (\n hostDocumentDir === 'rtl' ? triggerSide === 'left' : triggerSide === 'right'\n )\n ? 'end'\n : 'start';\n\n return (\n <PopoverPrimitive.Content\n onInteractOutside={(ev) => ev.preventDefault()}\n forceMount\n style={{\n zIndex: theme.widgetContentContainer.zIndex,\n fontSize: '16px',\n }}\n side=\"top\"\n align={align}\n aria-modal=\"false\"\n aria-label={t('support_chat_aria_label')}\n sideOffset={theme.widgetContentContainer.offset.side}\n alignOffset={theme.widgetContentContainer.offset.align}\n avoidCollisions={false}\n // do not use `asChild` as it will mess up setting the zIndex correctly on the top-most div\n >\n <WidgetContent />\n </PopoverPrimitive.Content>\n );\n}\n","import React from 'react';\nimport { cn } from '../lib/utils/cn';\n\nexport function ChatBubbleSvg({\n className,\n style,\n}: {\n className?: string;\n style?: React.CSSProperties;\n}) {\n return (\n <svg\n width=\"32\"\n height=\"30\"\n viewBox=\"0 0 32 30\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={cn('text-primary-foreground', className)}\n style={style}\n >\n <path\n d=\"M0 6.94263C0 3.62892 2.68629 0.942627 6 0.942627H26C29.3137 0.942627 32 3.62892 32 6.94263V17.9426C32 21.2563 29.3137 23.9426 26 23.9426H6C2.68629 23.9426 0 21.2563 0 17.9426V6.94263Z\"\n fill=\"currentColor\"\n />\n <path\n fillRule=\"evenodd\"\n clipRule=\"evenodd\"\n d=\"M19.9945 23.8935L26.237 23.8934C26.1982 24.3557 26.1712 25.2778 26.1704 26.2318C26.1688 28.2839 26.1376 28.7041 25.974 28.868C25.583 29.2598 25.2686 29.0967 24.0616 27.8754C23.4162 27.2222 22.1141 25.9522 21.1682 25.0531L19.9945 23.8935Z\"\n fill=\"currentColor\"\n />\n </svg>\n );\n}\n","import { useConfig } from '@opencx/widget-react-headless';\n\n/**\n * Accessible label for the widget launcher — the popover trigger button and\n * the companion resting pill share this one default.\n */\nexport function useTriggerLabel(): string {\n const { accessibility } = useConfig();\n return accessibility?.widgetTriggerButton?.label ?? 'Chat with us';\n}\n","import React from 'react';\nimport type { WidgetConfig } from '@opencx/widget-core';\n\ntype CustomTrigger = NonNullable<\n NonNullable<WidgetConfig['customComponents']>['widgetTrigger']\n>;\n\n/**\n * Invoke the embedder-supplied `customComponents.widgetTrigger` with the\n * shared contract: it replaces the built-in launcher entirely and drives the\n * widget via `setIsOpen`. One invocation shape for popover and companion.\n */\nexport function renderCustomTrigger(\n customTrigger: CustomTrigger,\n isOpen: boolean,\n setIsOpen: (open: boolean) => void,\n) {\n return customTrigger({\n react: React,\n isOpen,\n setIsOpen: (open: boolean) => setIsOpen(open),\n });\n}\n","import * as PopoverPrimitive from '@radix-ui/react-popover';\nimport IFrame from '@uiw/react-iframe';\nimport { AnimatePresence } from 'framer-motion';\nimport { ChevronDownIcon } from 'lucide-react';\nimport React from 'react';\nimport { useConfig, useWidgetTrigger } from '@opencx/widget-react-headless';\nimport { buildFrameHtml, FrameDocument } from './components/FrameDocument';\nimport { MotionDiv } from './components/lib/MotionDiv';\nimport { cn } from './components/lib/utils/cn';\nimport { Wobble, WOBBLE_MAX_MOVEMENT_PIXELS } from './components/lib/wobble';\nimport { ChatBubbleSvg } from './components/svg/ChatBubbleSvg';\nimport { useTheme } from './hooks/useTheme';\nimport { useTriggerLabel } from './hooks/useTriggerLabel';\nimport { dc } from './utils/data-component';\nimport { renderCustomTrigger } from './utils/render-custom-trigger';\n\nconst initialContent = buildFrameHtml();\n\nfunction WidgetPopoverTrigger() {\n const { isOpen, setIsOpen } = useWidgetTrigger();\n const { assets, customComponents } = useConfig();\n const { theme } = useTheme();\n\n const triggerLabel = useTriggerLabel();\n\n if (customComponents?.widgetTrigger) {\n return renderCustomTrigger(\n customComponents.widgetTrigger,\n isOpen,\n setIsOpen,\n );\n }\n\n return (\n <IFrame\n initialContent={initialContent}\n title=\"OpenCX Live Chat Trigger\"\n style={{\n height: `calc(${theme.widgetTrigger.size.button}px + ${WOBBLE_MAX_MOVEMENT_PIXELS.x * 2}px)`,\n width: `calc(${theme.widgetTrigger.size.button}px + ${WOBBLE_MAX_MOVEMENT_PIXELS.y * 2}px)`,\n fontSize: '16px',\n position: 'fixed',\n zIndex: theme.widgetTrigger.zIndex,\n right: theme.widgetTrigger.offset.right,\n bottom: theme.widgetTrigger.offset.bottom,\n left: theme.widgetTrigger.offset.left,\n\n // reset iframe defaults\n boxSizing: 'border-box',\n borderWidth: '0px',\n\n // A quick fix for the white square background of the iframe when the hosting website switches to dark mode\n borderRadius: '100%',\n }}\n >\n <FrameDocument\n style={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <PopoverPrimitive.PopoverTrigger\n aria-label={triggerLabel}\n title={triggerLabel}\n className={cn(\n 'font-sans flex items-center justify-center rounded-full',\n )}\n style={{\n height: theme.widgetTrigger.size.button,\n width: theme.widgetTrigger.size.button,\n }}\n >\n <Wobble>\n <div\n {...dc('trigger/btn')}\n className={cn(\n 'relative size-full rounded-full',\n 'flex items-center justify-center',\n 'overflow-hidden',\n 'transition-all',\n 'bg-primary',\n 'text-primary-foreground',\n )}\n >\n <AnimatePresence mode=\"wait\">\n {isOpen ? (\n <MotionDiv\n key=\"x-icon\"\n snapExit\n fadeIn=\"up\"\n overrides={{\n initial: { rotate: 45 },\n animate: { rotate: 0 },\n }}\n >\n {assets?.widgetTrigger?.closeIcon ? (\n <img\n src={assets.widgetTrigger.closeIcon}\n alt=\"Widget trigger close icon\"\n style={{\n width: theme.widgetTrigger.size.icon,\n height: theme.widgetTrigger.size.icon,\n }}\n />\n ) : (\n <ChevronDownIcon\n style={{\n width: theme.widgetTrigger.size.icon,\n height: theme.widgetTrigger.size.icon,\n }}\n />\n )}\n </MotionDiv>\n ) : (\n <MotionDiv\n key=\"message-icon\"\n snapExit\n overrides={{\n initial: { rotate: 45 },\n animate: { rotate: 0 },\n }}\n >\n {assets?.widgetTrigger?.openIcon ? (\n <img\n src={assets.widgetTrigger.openIcon}\n alt=\"Widget trigger open icon\"\n style={{\n width: theme.widgetTrigger.size.icon,\n height: theme.widgetTrigger.size.icon,\n }}\n />\n ) : (\n <ChatBubbleSvg\n style={{\n width: theme.widgetTrigger.size.icon,\n height: theme.widgetTrigger.size.icon,\n }}\n className=\"mt-0.5 opacity-95\"\n />\n )}\n </MotionDiv>\n )}\n </AnimatePresence>\n </div>\n </Wobble>\n </PopoverPrimitive.PopoverTrigger>\n </FrameDocument>\n </IFrame>\n );\n}\n\nexport { WidgetPopoverTrigger };\n","import React from 'react';\nimport * as PopoverPrimitive from '@radix-ui/react-popover';\nimport { useTheme } from './hooks/useTheme';\n\nexport function WidgetPopoverAnchor() {\n const { triggerSide } = useTheme();\n\n return (\n <PopoverPrimitive.Anchor\n style={{\n position: 'fixed',\n bottom: 0,\n right: triggerSide === 'right' ? 0 : undefined,\n left: triggerSide === 'left' ? 0 : undefined,\n }}\n />\n );\n}\n","import type { WidgetCompanionLayoutU } from '@opencx/widget-core';\nimport type { PanelState } from './types';\nimport { matchesBinding, WIDGET_KEYBINDINGS } from '../utils/keybindings';\n\nconst NESTED_ESCAPE_SCOPE = '[data-opencx-escape-scope]';\n\nfunction isInsideNestedEscapeScope(event: KeyboardEvent): boolean {\n // Companion content lives in an iframe. Avoid `instanceof Element`: its\n // target belongs to the iframe realm, while this module runs in the host.\n const target = event.target as {\n closest?: (selector: string) => unknown;\n } | null;\n return target?.closest?.(NESTED_ESCAPE_SCOPE) != null;\n}\n\n/** Host-page shortcuts must always be modified chords. A bare Escape belongs\n * to the host page; the iframe handler below owns closing the companion. */\nexport function handleCompanionHostKeyDown(\n event: KeyboardEvent,\n {\n state,\n onToggleFullscreen,\n }: {\n state: PanelState;\n onToggleFullscreen: () => void;\n },\n): void {\n if (event.defaultPrevented || state !== 'chat') return;\n if (!matchesBinding(event, WIDGET_KEYBINDINGS['toggle-fullscreen'])) return;\n event.preventDefault();\n onToggleFullscreen();\n}\n\n/** Shortcuts for the companion iframe. Nested dismissibles get first refusal\n * on Escape; Radix marks the event default-prevented in capture phase, and the\n * explicit scope covers other inline dismissibles using the same convention. */\nexport function handleCompanionFrameKeyDown(\n event: KeyboardEvent,\n {\n state,\n onDismiss,\n onToggleFullscreen,\n }: {\n state: Exclude<PanelState, 'pill'>;\n onDismiss: () => void;\n onToggleFullscreen: () => void;\n },\n): void {\n if (event.defaultPrevented) return;\n if (matchesBinding(event, WIDGET_KEYBINDINGS['close-panel'])) {\n if (!isInsideNestedEscapeScope(event)) onDismiss();\n return;\n }\n if (\n state === 'chat' &&\n matchesBinding(event, WIDGET_KEYBINDINGS['toggle-fullscreen'])\n ) {\n event.preventDefault();\n onToggleFullscreen();\n }\n}\n\n/** What Escape does to an open panel. */\nexport type EscapeAction =\n | { kind: 'layout'; layout: WidgetCompanionLayoutU }\n | { kind: 'close' };\n\n/**\n * Escape reads the panel's LAYOUT, not its state: fullscreen is a mode the\n * visitor entered, so Escape leaves the mode and lands back on the layout they\n * came from — everywhere else Escape means dismiss, straight to the launcher.\n * (The × button keeps its staged collapse: that control is a minimize, this\n * key is a dismissal, and conflating them made Escape feel like it did\n * nothing.)\n *\n * Falls back to the configured resting layout when the one they came from is\n * no longer allowed, and closes outright when every non-fullscreen layout is\n * excluded — a fullscreen-only embed has no mode to fall back to.\n */\nexport function resolveEscapeAction({\n panelLayout,\n previousLayout,\n defaultLayout,\n allowedLayouts,\n}: {\n panelLayout: WidgetCompanionLayoutU;\n /** The non-fullscreen layout the panel was in before going fullscreen. */\n previousLayout: WidgetCompanionLayoutU;\n defaultLayout: WidgetCompanionLayoutU;\n allowedLayouts: ReadonlyArray<WidgetCompanionLayoutU>;\n}): EscapeAction {\n if (panelLayout !== 'fullscreen') return { kind: 'close' };\n const candidates = [previousLayout, defaultLayout];\n for (const layout of candidates) {\n if (layout !== 'fullscreen' && allowedLayouts.includes(layout)) {\n return { kind: 'layout', layout };\n }\n }\n const anyOther = allowedLayouts.find((layout) => layout !== 'fullscreen');\n return anyOther ? { kind: 'layout', layout: anyOther } : { kind: 'close' };\n}\n","import { useConfig } from '@opencx/widget-react-headless';\nimport React, { useLayoutEffect, useRef } from 'react';\nimport { motion, useReducedMotion } from 'framer-motion';\nimport { EASE_OUT } from '../motion';\nimport { handleCompanionFrameKeyDown } from './companion-keyboard';\nimport { FrameDocument } from '../components/FrameDocument';\nimport { SuggestedReplyButton } from '../components/SuggestedReplyButton';\n\n/** A separate surface: questions must never resize the animated composer. */\nexport function CompanionQuestions({\n onHeightChange,\n maxHeight,\n onDismiss,\n onToggleFullscreen,\n}: {\n onHeightChange: (height: number) => void;\n maxHeight: number;\n onDismiss: () => void;\n onToggleFullscreen: () => void;\n}) {\n const ref = useRef<HTMLDivElement>(null);\n useLayoutEffect(() => {\n const node = ref.current;\n if (!node) return;\n const report = () => onHeightChange(node.offsetHeight);\n report();\n const Observer = node.ownerDocument.defaultView?.ResizeObserver;\n if (!Observer) return;\n const observer = new Observer(report);\n observer.observe(node);\n return () => observer.disconnect();\n }, [onHeightChange, maxHeight]);\n\n return (\n <FrameDocument>\n <div\n ref={ref}\n onKeyDown={(event) =>\n handleCompanionFrameKeyDown(event.nativeEvent, {\n state: 'input',\n onDismiss,\n onToggleFullscreen,\n })\n }\n data-companion-questions\n style={{ maxHeight }}\n className=\"flex min-w-0 flex-col items-start gap-2 overflow-y-auto p-1\"\n >\n <CompanionQuestionButtons />\n </div>\n </FrameDocument>\n );\n}\n\n/** Required and optional starters share the same floating presentation. */\nexport function CompanionQuestionButtons() {\n const { initialQuestions } = useConfig();\n const reduceMotion = useReducedMotion();\n return (\n <>\n {initialQuestions\n ?.filter((question) => question.trim().length > 0)\n .map((question, index) => (\n <motion.div\n key={`${question}-${index}`}\n className=\"max-w-full\"\n initial={{ opacity: 0, y: reduceMotion ? 0 : 8 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{\n duration: reduceMotion ? 0 : 0.3,\n delay: reduceMotion ? 0 : 0.2 + Math.min(index, 5) * 0.1,\n ease: EASE_OUT,\n }}\n >\n <SuggestedReplyButton\n suggestion={question}\n type=\"button\"\n variant=\"secondary\"\n wobble={false}\n className=\"max-w-full whitespace-normal break-words rounded-full bg-muted-foreground px-4 py-2 text-start text-base text-background hover:bg-foreground [@media(pointer:coarse)]:min-h-12\"\n />\n </motion.div>\n ))}\n </>\n );\n}\n","const agentPointerEvents = new WeakSet<Event>();\n\n/** Widget dismissal must distinguish our page actions from visitor clicks. */\nexport function isAgentPointerEvent(event: Event): boolean {\n return agentPointerEvents.has(event);\n}\n\n/**\n * Click the way a pointer does, not the way `el.click()` does.\n *\n * `el.click()` dispatches one `click` event. Real interfaces listen for far\n * more than that: a dropdown opens on `pointerdown`, a custom button\n * highlights on `pointerover`, a menu item commits on `mouseup`. Anything\n * built on a component library — which is most of what a support agent is\n * ever asked to help with — simply does not respond to a bare click.\n *\n * So: the full sequence a mouse produces, at the control's own centre,\n * with focus moved first like a real press does.\n */\nexport function firePointerSequence(\n el: HTMLElement,\n mayDispatch: () => boolean = () => true,\n): 'not-started' | 'interrupted' | 'completed' {\n let dispatched = false;\n const result = (completed: boolean) =>\n completed ? 'completed' : dispatched ? 'interrupted' : 'not-started';\n const rect = el.getBoundingClientRect();\n const clientX = rect.left + rect.width / 2;\n const clientY = rect.top + rect.height / 2;\n // No `view`: nothing listens for it, and handing an event a Window from\n // a different realm than the one constructing it is rejected outright —\n // the exact shape of an element inside a same-origin frame.\n const base = {\n bubbles: true,\n cancelable: true,\n composed: true,\n clientX,\n clientY,\n };\n\n const dispatch = (event: Event) => {\n if (!mayDispatch()) return false;\n dispatched = true;\n agentPointerEvents.add(event);\n el.dispatchEvent(event);\n return true;\n };\n const pointer = (type: string) =>\n dispatch(\n new PointerEvent(type, {\n ...base,\n pointerId: 1,\n pointerType: 'mouse',\n isPrimary: true,\n }),\n );\n const mouse = (type: string, detail = 0) =>\n dispatch(new MouseEvent(type, { ...base, detail, button: 0, buttons: 1 }));\n\n if (\n !pointer('pointerover') ||\n !pointer('pointerenter') ||\n !mouse('mouseover') ||\n !mouse('mousemove') ||\n !pointer('pointerdown') ||\n !mouse('mousedown', 1)\n )\n return result(false);\n // Focus before the release, like a real press: a control that commits on\n // blur of the previous field needs that to have happened already.\n if (!mayDispatch()) return result(false);\n el.focus?.();\n return result(\n pointer('pointerup') && mouse('mouseup', 1) && mouse('click', 1),\n );\n}\n","import React from 'react';\nimport { cn } from '../components/lib/utils/cn';\n\n/**\n * Icon button for companion chrome that renders INSIDE the content iframe\n * (panel controls, quick-ask bar) — Tailwind is available there. Size comes\n * from the call site (`size-7`, `size-8`, ...) so the base stays reusable.\n *\n * Forwards its ref so it can be the `asChild` target of Radix wrappers\n * (Popover trigger, `Tooltippy`). Never renders a native `title`: every\n * call site pairs it with the styled tooltip, and a native one would double\n * up with it.\n */\nexport const FrameIconButton = React.forwardRef<\n HTMLButtonElement,\n Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'title'> & {\n label: string;\n }\n>(function FrameIconButton({ label, className, ...props }, ref) {\n return (\n <button\n ref={ref}\n type=\"button\"\n aria-label={label}\n {...props}\n className={cn(\n 'flex shrink-0 items-center justify-center rounded-lg',\n 'text-secondary-foreground/60 hover:text-secondary-foreground hover:bg-muted',\n 'active:scale-[0.97] transition-[background-color,color,transform] duration-150 ease-out',\n className,\n )}\n />\n );\n});\n","import type {\n WidgetCompanionLayoutU,\n WidgetSidebarSideResolvedU,\n} from '@opencx/widget-core';\n\nexport function clamp(value: number, min: number, max: number): number {\n return Math.min(Math.max(value, min), max);\n}\n\n/** Even margin on all four sides for the fullscreen modal window. */\nexport const FULLSCREEN_MARGIN = 16;\n/** Margin around the docked sidebar (top/bottom + its own outer edge). */\nexport const SIDEBAR_MARGIN = 16;\n\n/** The resting disc size. The collapsed round pill's box (WidgetCompanion)\n * and the icon disc inside it (RestingPill) share this constant, so the disc\n * fills the pill exactly — that equality is what lets the pill grow into the\n * dock bar without the icon resizing. 32 in the 44 dock leaves ~6px of\n * breathing room around the disc. */\nexport const PILL_SIZE = 32;\nexport const DOCK_HEIGHT = 44;\n/** Dock bar width until the label content has been measured. */\nexport const DOCK_FALLBACK_WIDTH = 240;\nexport const PANEL_MAX_WIDTH = 440;\nexport const PANEL_HORIZONTAL_MARGIN = 32;\n/** Narrowest the compact card may go on tiny viewports. */\nexport const COMPACT_MIN_WIDTH = 280;\nexport const CHAT_MIN_HEIGHT = 420;\nexport const CHAT_MAX_HEIGHT = 640;\nexport const TOP_MARGIN = 48;\n/** Minimum gap between the shell and the viewport edge (drag bounds). */\nexport const VIEWPORT_EDGE_PADDING = 12;\n\n// Sidebar layout: a drag-resizable panel pinned to one viewport edge\n// (`companion.sidebar.side`, `auto` = the inline-end edge). In `docked` mode\n// it pushes the host page aside via the app-frame; in `floating` mode it\n// overlays the page. These are the drag-resize width bounds; the margins +\n// rects are computed by the pure functions below.\nexport const DEFAULT_SIDEBAR_WIDTH = 400;\nexport const MIN_SIDEBAR_WIDTH = 320;\nexport const MAX_SIDEBAR_WIDTH = 560;\n/** Default canvas color revealed behind the framed host page. */\nexport const SIDEBAR_CANVAS = '#f4f4f5';\n\n/** Keep a visible strip of the website beside the sidebar, even in narrow\n * embedded previews. Three margins separate the page, panel, and edges. */\nconst MIN_HOST_PAGE_WIDTH = 120;\n/** Use the full-width phone layout only when a readable sidebar and the\n * host page can no longer fit together. Shared with app-frame's media query. */\nexport const SIDEBAR_FULL_BLEED_MAX_WIDTH =\n MIN_SIDEBAR_WIDTH + MIN_HOST_PAGE_WIDTH + SIDEBAR_MARGIN * 3;\n\n/** Corner radius per shell state/layout — the single source for every radius\n * the companion draws, including the app-frame's framed-page corners and the\n * quick-ask card inside the iframe (via a CSS custom property). */\nexport const RADII = {\n pill: 999,\n input: 16,\n fullscreen: 16,\n sidebar: 20,\n compact: 20,\n} as const;\n\n/** The browser viewport — the companion always scopes to it. */\nexport type Region = {\n width: number;\n height: number;\n};\ntype ShellDims = { width: number; height: number; borderRadius: number };\nexport type CompactGeometryOptions = {\n maxWidth?: number;\n minWidth?: number;\n minHeight?: number;\n maxHeight?: number;\n viewportHeightRatio?: number;\n borderRadius?: number;\n};\n/** The container anchor: the shell is translateX(-50%)-centered on `centerX`\n * and offset from the viewport bottom by `bottom`. Both animate with the morph\n * spring so a layout switch expands FROM the current rect in place. */\ntype ShellAnchor = { centerX: number; bottom: number };\n\n/** Keep room for the host page above the phone breakpoint. On phones the\n * panel takes the available width, matching app-frame's media query. */\nexport function effectiveSidebarWidth(\n region: Region,\n sidebarWidth: number,\n): number {\n if (region.width <= SIDEBAR_FULL_BLEED_MAX_WIDTH) {\n return Math.max(0, region.width - SIDEBAR_MARGIN * 2);\n }\n const maxWidth = region.width - MIN_HOST_PAGE_WIDTH - SIDEBAR_MARGIN * 3;\n return Math.max(0, Math.min(sidebarWidth, maxWidth));\n}\n\n/** Compact card width: capped at PANEL_MAX_WIDTH, shrinking with a side\n * margin on narrow viewports. COMPACT_MIN_WIDTH is preferred, but the\n * viewport always wins when it is narrower than that floor. */\nfunction finiteAtLeast(value: number | undefined, fallback: number, min = 0) {\n return typeof value === 'number' && Number.isFinite(value)\n ? Math.max(min, value)\n : fallback;\n}\n\nexport function compactWidth(\n region: Region,\n options: CompactGeometryOptions = {},\n): number {\n const viewportWidth = Math.max(0, region.width);\n const maxWidth = finiteAtLeast(options.maxWidth, PANEL_MAX_WIDTH);\n const minWidth = Math.min(\n maxWidth,\n finiteAtLeast(options.minWidth, COMPACT_MIN_WIDTH),\n );\n return Math.min(\n viewportWidth,\n maxWidth,\n Math.max(minWidth, viewportWidth - PANEL_HORIZONTAL_MARGIN),\n );\n}\n\n/** Compact panel height: 65% of the viewport, clamped to the chat bounds\n * and to what fits between the bottom offset and the top margin. */\nexport function chatHeight(\n region: Region,\n bottomOffset: number,\n options: CompactGeometryOptions = {},\n): number {\n const viewportHeight = Math.max(0, region.height);\n const minHeight = finiteAtLeast(options.minHeight, CHAT_MIN_HEIGHT);\n const maxHeight = finiteAtLeast(\n options.maxHeight,\n CHAT_MAX_HEIGHT,\n minHeight,\n );\n const viewportHeightRatio = Math.min(\n 1,\n finiteAtLeast(options.viewportHeightRatio, 0.65),\n );\n const availableHeight = Math.max(\n 0,\n viewportHeight - Math.max(0, bottomOffset) - TOP_MARGIN,\n );\n return Math.min(\n maxHeight,\n availableHeight,\n Math.max(minHeight, viewportHeight * viewportHeightRatio),\n );\n}\n\n/** The open chat panel's box per layout. */\nexport function chatDims(opts: {\n layout: WidgetCompanionLayoutU;\n region: Region;\n sidebarWidth: number;\n bottomOffset: number;\n compact?: CompactGeometryOptions;\n}): ShellDims {\n const { layout, region, sidebarWidth, bottomOffset, compact } = opts;\n if (layout === 'fullscreen') {\n return {\n width: Math.max(0, region.width - FULLSCREEN_MARGIN * 2),\n height: Math.max(0, region.height - FULLSCREEN_MARGIN * 2),\n borderRadius: RADII.fullscreen,\n };\n }\n if (layout === 'sidebar') {\n return {\n width: effectiveSidebarWidth(region, sidebarWidth),\n height: Math.max(0, region.height - SIDEBAR_MARGIN * 2),\n borderRadius: RADII.sidebar,\n };\n }\n return {\n width: compactWidth(region, compact),\n height: chatHeight(region, bottomOffset, compact),\n borderRadius: finiteAtLeast(compact?.borderRadius, RADII.compact),\n };\n}\n\n/**\n * The container anchor (center-x + bottom). The fullscreen/sidebar anchoring\n * applies ONLY when the chat panel is actually open (`isChatOpen`): the\n * resting pill and the quick-ask bar always sit bottom-center, so a sidebar\n * (or fullscreen) layout does NOT drag the pill to the edge. When open,\n * compact/fullscreen center on the viewport and the sidebar pins its far\n * edge to `sidebarSide` — already resolved from config + host dir by the\n * caller, so this stays a pure function of a physical side.\n */\nexport function shellAnchor(opts: {\n isChatOpen: boolean;\n layout: WidgetCompanionLayoutU;\n region: Region;\n sidebarWidth: number;\n sidebarSide: WidgetSidebarSideResolvedU;\n bottomOffset: number;\n}): ShellAnchor {\n const {\n isChatOpen,\n layout,\n region,\n sidebarWidth,\n sidebarSide,\n bottomOffset,\n } = opts;\n // Pill / quick-ask (not open chat) always rest bottom-center, regardless of\n // the layout the panel WILL open into.\n const anchorLayout = isChatOpen ? layout : 'compact';\n const width = effectiveSidebarWidth(region, sidebarWidth);\n const bottom =\n anchorLayout === 'fullscreen'\n ? FULLSCREEN_MARGIN\n : anchorLayout === 'sidebar'\n ? SIDEBAR_MARGIN\n : bottomOffset;\n const centerX =\n anchorLayout === 'sidebar'\n ? sidebarSide === 'left'\n ? SIDEBAR_MARGIN + width / 2\n : region.width - SIDEBAR_MARGIN - width / 2\n : region.width / 2;\n return { centerX, bottom };\n}\n","/**\n * Flat \"document\" message rendering — the agent chat DEFAULT. Agent replies\n * flow as unbubbled text and user messages become quiet chips\n * (Linear/Claude-style reading layout). Avatars are a separate sheet so an\n * embed can keep them without bubbles, or drop them with bubbles.\n *\n * Every rule is scoped to the companion panel root. `companion.bubbles: true`\n * skips FLAT_MESSAGE_CSS; `companion.avatars: true` skips HIDE_AVATARS_CSS.\n */\nconst scope = '[data-companion-root]';\n\nexport const FLAT_MESSAGE_CSS = `\n${scope} [data-component=\"chat/msgs/root\"] {\n overflow-x: hidden !important;\n}\n${scope} [data-component=\"chat/agent_msg_group/root\"],\n${scope} [data-component=\"chat/agent_msg_group/avatar_and_msgs/root\"],\n${scope} [data-component=\"chat/agent_msg_group/avatar_and_msgs/msgs\"] {\n min-width: 0 !important;\n max-width: 100% !important;\n}\n${scope} [data-component=\"chat/agent_msg/msg\"] {\n background: transparent !important;\n padding: 2px 0 !important;\n border-radius: 0 !important;\n max-width: 100% !important;\n min-width: 0 !important;\n overflow-wrap: break-word !important;\n}\n${scope} [data-component=\"chat/agent_msg/msg\"] table {\n display: block;\n max-width: 100%;\n overflow-x: auto;\n border-collapse: collapse;\n}\n${scope} [data-component=\"chat/agent_msg/msg\"] th,\n${scope} [data-component=\"chat/agent_msg/msg\"] td {\n overflow-wrap: normal;\n word-break: normal;\n white-space: normal;\n vertical-align: top;\n text-align: start;\n padding: 4px 10px 4px 0;\n border-bottom: 1px solid hsl(var(--opencx-border));\n}\n${scope} [data-component=\"chat/user_msg/msg\"] {\n background: hsl(var(--opencx-secondary)) !important;\n color: hsl(var(--opencx-secondary-foreground)) !important;\n padding: 8px 12px !important;\n border-radius: 10px !important;\n}\n`;\n\nexport const HIDE_AVATARS_CSS = `\n${scope} [data-component=\"chat/agent_msg_group/root/avatar\"],\n${scope} [data-component=\"chat/agent_msg_group/avatar_and_msgs/avatar\"] {\n display: none !important;\n}\n`;\n\n/**\n * Flat layout WITH avatars: a reply reads as a document, so the avatar marks\n * where it starts — top-aligned with the first line and sized to it — instead\n * of hanging at the bottom beside the actions row like a chat bubble's.\n */\nexport const FLAT_AVATARS_CSS = `\n${scope} [data-component=\"chat/agent_msg_group/avatar_and_msgs/root\"] {\n align-items: flex-start !important;\n}\n${scope} [data-component=\"chat/agent_msg_group/avatar_and_msgs/avatar\"] {\n width: 20px !important;\n height: 20px !important;\n margin-top: 2px !important;\n}\n/* Steps, rendered blocks, the working spinner and the actions row are siblings\n of the text groups in a streamed turn: indent them by the avatar gutter\n (20px avatar + 8px gap) so everything shares the text's left edge. The\n typing row carries its own avatar, so it keeps the gutter instead — indenting\n it would jump the avatar sideways when the reply replaces it. */\n${scope} [data-component=\"chat/streaming_turn/root\"] > :not([data-component=\"chat/agent_msg_group/root\"]):not([data-component=\"chat/bot_loading/root\"]) {\n margin-inline-start: 28px !important;\n}\n${scope} [data-component=\"chat/bot_loading/root\"] {\n align-items: flex-start !important;\n}\n/* Its avatar is the row's first child (LoadingDefaultComponent renders no\n data-component on it), sized to match a reply's. */\n${scope} [data-component=\"chat/bot_loading/root\"] > :first-child {\n width: 20px !important;\n height: 20px !important;\n margin-top: 2px !important;\n}\n`;\n","import React from 'react';\nimport type {\n WidgetCompanionLayoutU,\n WidgetSidebarSideResolvedU,\n} from '@opencx/widget-core';\n\n/** A tiny window diagram per layout, in the macOS tiling-menu idiom. The\n * sidebar tile draws its panel on the side the sidebar actually docks to, so\n * a left-docked companion doesn't advertise a right-hand panel. */\nexport function LayoutGlyph({\n layout,\n sidebarSide,\n}: {\n layout: WidgetCompanionLayoutU;\n sidebarSide: WidgetSidebarSideResolvedU;\n}) {\n const common = {\n width: 18,\n height: 18,\n viewBox: '0 0 18 18',\n fill: 'none',\n 'aria-hidden': true,\n } as const;\n const frame = (\n <rect\n x={2}\n y={2.5}\n width={14}\n height={13}\n rx={2.5}\n stroke=\"currentColor\"\n strokeWidth={1.4}\n />\n );\n if (layout === 'fullscreen') {\n // Framed like its siblings, with the content filling the window (an inset\n // fill) — not a solid black square, which read far heavier than the other\n // two tiles.\n return (\n <svg {...common}>\n {frame}\n <rect x={4.5} y={5} width={9} height={8} rx={1.4} fill=\"currentColor\" />\n </svg>\n );\n }\n if (layout === 'sidebar') {\n // A docked panel on the configured third.\n return (\n <svg {...common}>\n {frame}\n <rect\n x={sidebarSide === 'left' ? 2 : 10.5}\n y={2.5}\n width={5.5}\n height={13}\n rx={2.5}\n fill=\"currentColor\"\n />\n </svg>\n );\n }\n // compact — a small floating card near the bottom center.\n return (\n <svg {...common}>\n {frame}\n <rect x={5} y={9} width={8} height={4.5} rx={1.6} fill=\"currentColor\" />\n </svg>\n );\n}\n\n// Single-word labels so every tile is exactly one line — two-line labels\n// (\"Floating panel\") stretch their tile tall and pad the others out to match.\n// Config owns order; this record only supplies presentation metadata.\n\n/** A window with its panel on one edge — the segmented control's two faces. */\nexport function SidePanelGlyph({ side }: { side: WidgetSidebarSideResolvedU }) {\n return (\n <svg\n width={14}\n height={14}\n viewBox=\"0 0 14 14\"\n fill=\"none\"\n aria-hidden={true}\n >\n <rect\n x={1}\n y={2}\n width={12}\n height={10}\n rx={2}\n stroke=\"currentColor\"\n strokeWidth={1.2}\n opacity={0.5}\n />\n <rect\n x={side === 'left' ? 1 : 8.5}\n y={2}\n width={4.5}\n height={10}\n rx={2}\n fill=\"currentColor\"\n />\n </svg>\n );\n}\n","import { motion } from 'framer-motion';\nimport React from 'react';\nimport type { WidgetSidebarSideResolvedU } from '@opencx/widget-core';\nimport { cn } from '../components/lib/utils/cn';\nimport { dc } from '../utils/data-component';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { EASE_OUT, MORPH_SPRING } from '../motion';\nimport { SidePanelGlyph } from './layout-glyphs';\n\n/**\n * The flyout itself. Positioned off the sidebar tile when there is a tile row\n * to hang from; otherwise it IS the menu and sits inline.\n *\n * The gap between tile and card is padding on the WRAPPER, not a margin —\n * padding keeps the gap inside the flyout's own hit area, so the pointer\n * crossing it never leaves the menu and never closes what it is reaching for.\n * It has to clear the parent menu's own bottom edge first (6px padding + 1px\n * border) before any of it reads as separation, hence 12px rather than the 4px\n * that looked right on paper and overlapped the card in practice.\n */\nexport function SidebarSubmenu({\n anchored,\n side,\n onSelectSide,\n docked,\n onToggleDock,\n}: {\n anchored: boolean;\n side: WidgetSidebarSideResolvedU;\n onSelectSide: (side: WidgetSidebarSideResolvedU) => void;\n docked: boolean;\n onToggleDock: () => void;\n}) {\n const { t } = useTranslation();\n return (\n <motion.div\n {...dc('companion/layout_picker/sidebar_options')}\n initial={{ opacity: 0, scale: 0.96 }}\n animate={{ opacity: 1, scale: 1 }}\n exit={{ opacity: 0, scale: 0.96 }}\n transition={{ duration: 0.18, ease: EASE_OUT }}\n // Centered on the tile it belongs to, so it reads as hanging from that\n // tile rather than drifting off one of its corners. The -50% shift goes\n // through motion's `x` rather than a `-translate-x-1/2` class: motion\n // writes the whole `transform` for the scale animation, so a Tailwind\n // translate would be overwritten the moment it animates. `left: 50%`\n // centers symmetrically, which also holds under RTL.\n style={anchored ? { left: '50%', x: '-50%' } : undefined}\n className={cn('origin-top', anchored && 'absolute top-full z-10 pt-3')}\n >\n <div\n className={cn(\n 'flex flex-col gap-1.5 whitespace-nowrap',\n anchored &&\n 'rounded-[var(--pk-r)] border bg-background p-[var(--pk-p)] shadow-lg',\n )}\n >\n <SubmenuRow label={t('companion_sidebar_dock_label')}>\n <DockSwitch\n label={t('companion_sidebar_dock_label')}\n checked={docked}\n onToggle={onToggleDock}\n />\n </SubmenuRow>\n <SubmenuRow label={t('companion_sidebar_side_label')}>\n <SideSegmented\n label={t('companion_sidebar_side_label')}\n side={side}\n onSelect={onSelectSide}\n />\n </SubmenuRow>\n </div>\n </motion.div>\n );\n}\n\n/** Name on the left, control on the right — the switch-row idiom. */\nfunction SubmenuRow({\n label,\n children,\n}: {\n label: string;\n children: React.ReactNode;\n}) {\n return (\n <div className=\"flex items-center justify-between gap-4 ps-1.5\">\n <span\n aria-hidden\n className=\"text-[11px] font-medium leading-none text-secondary-foreground/70\"\n >\n {label}\n </span>\n {children}\n </div>\n );\n}\n\n/**\n * A real on/off switch: dock is genuinely boolean, so the name stays fixed and\n * the thumb carries the state. The thumb rides MORPH_SPRING — the widget's one\n * morph signature, near-critically damped so it never overshoots its track.\n */\nfunction DockSwitch({\n label,\n checked,\n onToggle,\n}: {\n label: string;\n checked: boolean;\n onToggle: () => void;\n}) {\n return (\n <button\n {...dc('companion/layout_picker/sidebar_option')}\n type=\"button\"\n role=\"switch\"\n aria-checked={checked}\n aria-label={label}\n onClick={onToggle}\n className={cn(\n 'relative flex h-4 w-7 shrink-0 items-center rounded-full px-0.5',\n 'transition-colors duration-150',\n 'active:scale-[0.97]',\n checked ? 'bg-primary' : 'bg-secondary-foreground/20',\n )}\n >\n <motion.span\n aria-hidden\n initial={false}\n animate={{ x: checked ? 12 : 0 }}\n transition={MORPH_SPRING}\n className=\"size-3 rounded-full bg-background shadow-sm\"\n />\n </button>\n );\n}\n\n/**\n * Two mutually exclusive edges, so radio semantics rather than a switch. The\n * highlight is a single shared element (`layoutId`) so it SLIDES between the\n * options instead of blinking off one and on the other.\n */\nfunction SideSegmented({\n label,\n side,\n onSelect,\n}: {\n label: string;\n side: WidgetSidebarSideResolvedU;\n onSelect: (side: WidgetSidebarSideResolvedU) => void;\n}) {\n const { t } = useTranslation();\n const sides = [\n { value: 'left', labelKey: 'companion_sidebar_left' },\n { value: 'right', labelKey: 'companion_sidebar_right' },\n ] as const;\n return (\n <div\n role=\"radiogroup\"\n aria-label={label}\n className=\"flex items-center gap-0.5 rounded-full bg-secondary-foreground/10 p-0.5\"\n >\n {sides.map(({ value, labelKey }) => {\n const selected = value === side;\n return (\n <button\n // `key` must precede the spread: after it, the JSX transform folds\n // it into the props object and React stops seeing it as a key.\n key={value}\n {...dc('companion/layout_picker/sidebar_option')}\n type=\"button\"\n role=\"radio\"\n aria-checked={selected}\n aria-label={t(labelKey)}\n onClick={() => onSelect(value)}\n className={cn(\n 'relative flex items-center justify-center rounded-full p-1',\n 'transition-colors duration-150',\n 'active:scale-[0.97]',\n selected ? 'text-primary' : 'text-secondary-foreground/60',\n )}\n >\n {selected && (\n <motion.span\n aria-hidden\n layoutId=\"opencx-sidebar-side-indicator\"\n transition={MORPH_SPRING}\n className=\"absolute inset-0 rounded-full bg-background shadow-sm\"\n />\n )}\n <span className=\"relative\">\n <SidePanelGlyph side={value} />\n </span>\n </button>\n );\n })}\n </div>\n );\n}\n","import * as PopoverPrimitive from '@radix-ui/react-popover';\nimport { AnimatePresence } from 'framer-motion';\nimport React, { useState } from 'react';\nimport { useWidgetLayout } from '@opencx/widget-react-headless';\nimport type {\n TranslationKeyU,\n WidgetCompanionLayoutU,\n} from '@opencx/widget-core';\nimport { cn } from '../components/lib/utils/cn';\nimport { Tooltippy } from '../components/lib/tooltip';\nimport { dc } from '../utils/data-component';\nimport { formatBinding, WIDGET_KEYBINDINGS } from '../utils/keybindings';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { FrameIconButton } from './FrameIconButton';\nimport { useCanHover } from '../hooks/useCanHover';\nimport { LayoutGlyph } from './layout-glyphs';\nimport { SidebarSubmenu } from './SidebarSubmenu';\n\n/**\n * One control for all three arrangements — a macOS-style layout menu. A single\n * trigger (showing the CURRENT layout as a mini window diagram) opens a popover\n * of tiles, current one highlighted; picking one calls `onSelect`. Close stays\n * a SEPARATE control (rendered by the caller), exactly like macOS keeps the\n * red traffic light apart from the green tiling menu.\n *\n * Hovering the SIDEBAR tile opens a SUBMENU — a small flyout hanging off that\n * tile with the layout's two sub-choices: Dock (push the page aside vs. lie\n * over it) and Side (which edge). It only opens while the sidebar is the\n * ACTIVE layout, so the controls are never offered against a sidebar that\n * isn't on screen.\n *\n * Why a submenu and not another row in this menu: the tiles are nouns naming a\n * destination — click Fullscreen and you go to fullscreen. Dock and Side are\n * switches. Rendered in the same grid they inherit the wrong grammar (\"Dock\"\n * reads as a place to go), and naming their state instead would put a second,\n * unrelated \"Floating\" directly under the Floating tile. A separate surface\n * lets switch controls read as switches, so the names stay fixed and the state\n * rides the control.\n *\n * The popover renders WITHOUT a Radix Portal: companion chrome lives inside the\n * content iframe, and a portal would escape to the host document. Inline\n * content keeps the menu in the iframe where it belongs.\n */\n\nconst LAYOUT_LABELS: Record<WidgetCompanionLayoutU, TranslationKeyU> = {\n compact: 'companion_layout_floating',\n sidebar: 'companion_layout_sidebar',\n fullscreen: 'companion_layout_fullscreen',\n};\n\n/**\n * True only when focus arrived from the keyboard. Clicking a button focuses it\n * as well, and treating that as hover left the submenu open with the pointer\n * nowhere near it. jsdom's selector engine has no `:focus-visible`, so a throw\n * there degrades to \"treat it as keyboard\" rather than breaking the reveal.\n */\nfunction isKeyboardFocus(element: Element): boolean {\n try {\n return element.matches(':focus-visible');\n } catch {\n return true;\n }\n}\n\nexport function LayoutPicker({\n current,\n onSelect,\n}: {\n current: WidgetCompanionLayoutU;\n onSelect: (layout: WidgetCompanionLayoutU) => void;\n}) {\n const { t } = useTranslation();\n const {\n allowedLayouts,\n sidebarSide,\n setSidebarSide,\n sidebarMode,\n setSidebarMode,\n } = useWidgetLayout();\n const [sidebarTileHovered, setSidebarTileHovered] = useState(false);\n // Tap fires pointerenter on touch, so a hover-opened submenu would open on\n // the very tap that closes the menu.\n const canHover = useCanHover();\n\n const options = allowedLayouts.map((layout) => ({\n layout,\n label: LAYOUT_LABELS[layout],\n }));\n\n // Fewer than two layouts means there is nothing to switch BETWEEN, so the\n // tile row goes away — but a locked-to-sidebar companion still has a dock\n // and a side worth offering, so the control itself survives on that alone.\n const showLayoutTiles = options.length >= 2;\n const sidebarAvailable = allowedLayouts.includes('sidebar');\n if (!showLayoutTiles && !sidebarAvailable) return null;\n\n // Hover on the sidebar tile is the ONLY thing that opens the submenu, from\n // any layout. It is not gated on the sidebar being active: a control that\n // only appears once you are already there can't be discovered. What keeps\n // that honest is that the controls activate the sidebar themselves (see\n // `applyFromAnyLayout`), so a click from the floating panel is never a\n // change the visitor can't see.\n const sidebarOptionsShown =\n sidebarAvailable &&\n (!showLayoutTiles\n ? // No tile row means no tile to hover, and the submenu is then the only\n // thing the menu has to say.\n true\n : canHover\n ? sidebarTileHovered\n : // Touch has no hover, and a tap would close the menu. Fall back to\n // the layout the visitor is in so the controls stay reachable.\n current === 'sidebar');\n\n // From another layout a dock/side pick is also a layout decision: apply it\n // AND go there, so the visitor lands in exactly what they chose rather than\n // setting an invisible preference. Adjusting from inside the sidebar leaves\n // the menu open — that is a tweak, not a decision.\n const applyFromAnyLayout = (apply: () => void) => {\n apply();\n if (current !== 'sidebar') onSelect('sidebar');\n };\n\n const submenu = (\n <AnimatePresence initial={false}>\n {sidebarOptionsShown && (\n <SidebarSubmenu\n anchored={showLayoutTiles}\n side={sidebarSide}\n onSelectSide={(next) =>\n applyFromAnyLayout(() => setSidebarSide(next))\n }\n docked={sidebarMode === 'docked'}\n onToggleDock={() =>\n applyFromAnyLayout(() =>\n setSidebarMode(sidebarMode === 'docked' ? 'floating' : 'docked'),\n )\n }\n />\n )}\n </AnimatePresence>\n );\n\n return (\n <PopoverPrimitive.Root onOpenChange={() => setSidebarTileHovered(false)}>\n <Tooltippy content={t('companion_layout_label')} side=\"bottom\">\n <PopoverPrimitive.Trigger asChild>\n <FrameIconButton\n {...dc('companion/layout_picker/trigger')}\n label={t('companion_layout_label')}\n className=\"size-7\"\n >\n <LayoutGlyph layout={current} sidebarSide={sidebarSide} />\n </FrameIconButton>\n </PopoverPrimitive.Trigger>\n </Tooltippy>\n <PopoverPrimitive.Content\n {...dc('companion/layout_picker/menu')}\n data-opencx-escape-scope=\"\"\n side=\"bottom\"\n align=\"end\"\n sideOffset={6}\n collisionPadding={8}\n // Leaving the MENU (not the tile) is what closes the submenu. The\n // flyout is a DOM descendant of this element even though it paints\n // outside it, so travelling onto it never counts as leaving.\n onPointerLeave={() => setSidebarTileHovered(false)}\n // Concentric radii, enforced by calc so the math can't drift:\n // tile radius = popover radius − padding (16 − 6 = 10).\n style={{ '--pk-r': '16px', '--pk-p': '6px' } as React.CSSProperties}\n className={cn(\n 'z-50 flex flex-col rounded-[var(--pk-r)] border bg-background p-[var(--pk-p)] shadow-lg',\n 'origin-[var(--radix-popover-content-transform-origin)]',\n 'animate-in fade-in-0 zoom-in-95',\n 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95',\n )}\n >\n {showLayoutTiles ? (\n <div className=\"flex items-stretch gap-0.5\">\n {options.map(({ layout, label: labelKey }) => {\n const selected = layout === current;\n const label = t(labelKey);\n const isSidebar = layout === 'sidebar';\n const tile = (\n <PopoverPrimitive.Close asChild>\n <button\n {...dc('companion/layout_picker/option')}\n type=\"button\"\n aria-label={label}\n aria-pressed={selected}\n aria-expanded={isSidebar ? sidebarOptionsShown : undefined}\n onClick={() => onSelect(layout)}\n // Every tile reports, not just the sidebar one: without\n // the others clearing it, hovering Sidebar once left the\n // submenu open for as long as the pointer stayed anywhere\n // in the menu.\n onPointerEnter={() => setSidebarTileHovered(isSidebar)}\n // Keyboard reaches the submenu the same way the pointer\n // does — but only a KEYBOARD focus. A click focuses the\n // tile too, and that must not count as hover.\n onFocus={(event) =>\n setSidebarTileHovered(\n isSidebar && isKeyboardFocus(event.currentTarget),\n )\n }\n className={cn(\n 'flex w-14 flex-col items-center gap-1 rounded-[calc(var(--pk-r)-var(--pk-p))] px-1.5 py-1.5',\n 'transition-colors duration-150',\n selected\n ? 'bg-primary/10 text-primary'\n : 'text-secondary-foreground/60 hover:bg-muted hover:text-secondary-foreground',\n )}\n >\n <LayoutGlyph layout={layout} sidebarSide={sidebarSide} />\n <span className=\"whitespace-nowrap text-[10px] font-medium leading-none\">\n {label}\n </span>\n </button>\n </PopoverPrimitive.Close>\n );\n\n // The sidebar tile owns the submenu, so it gets the positioning\n // context the flyout hangs off.\n if (isSidebar) {\n return (\n <div key={layout} className=\"relative flex\">\n {tile}\n {submenu}\n </div>\n );\n }\n // Fullscreen is the one tile with a keyboard shortcut — advertise\n // it (the tile's own label already names the action, so the hint\n // carries the label + key chip like every shortcut button).\n if (layout !== 'fullscreen')\n return <React.Fragment key={layout}>{tile}</React.Fragment>;\n return (\n <Tooltippy\n key={layout}\n content={label}\n shortcut={formatBinding(\n WIDGET_KEYBINDINGS['toggle-fullscreen'],\n )}\n side=\"bottom\"\n >\n {tile}\n </Tooltippy>\n );\n })}\n </div>\n ) : (\n submenu\n )}\n </PopoverPrimitive.Content>\n </PopoverPrimitive.Root>\n );\n}\n","import { XIcon } from 'lucide-react';\nimport React from 'react';\nimport type { WidgetCompanionLayoutU } from '@opencx/widget-core';\nimport { Tooltippy } from '../components/lib/tooltip';\nimport { dc } from '../utils/data-component';\nimport { formatBinding, WIDGET_KEYBINDINGS } from '../utils/keybindings';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { FrameIconButton } from './FrameIconButton';\nimport { LayoutPicker } from './LayoutPicker';\n\n/**\n * Chat-panel corner controls: a single macOS-style layout picker + Close.\n * Overlaid at the panel's top inline-end corner, inside the content iframe —\n * identical in every layout, so the header reads the same as the compact\n * panel. Layout-switching lives entirely in the picker; Close is its own\n * control so the two never read as doing the same thing.\n */\nexport function PanelControls({\n layout,\n onSelectLayout,\n onClose,\n}: {\n layout: WidgetCompanionLayoutU;\n onSelectLayout: (layout: WidgetCompanionLayoutU) => void;\n onClose: () => void;\n}) {\n const { t } = useTranslation();\n return (\n <div\n {...dc('companion/controls/root')}\n className=\"absolute top-2 z-10 flex items-center gap-1\"\n style={{ insetInlineEnd: 8 }}\n >\n <LayoutPicker current={layout} onSelect={onSelectLayout} />\n <Tooltippy\n content={t('companion_close')}\n shortcut={formatBinding(WIDGET_KEYBINDINGS['close-panel'])}\n side=\"bottom\"\n >\n <FrameIconButton\n {...dc('companion/close_btn')}\n label={t('companion_close')}\n onClick={onClose}\n className=\"size-7\"\n >\n <XIcon className=\"size-4\" />\n </FrameIconButton>\n </Tooltippy>\n </div>\n );\n}\n","import { useInitialQuestionRequired } from '../hooks/useInitialQuestionRequired';\nimport { useConfig } from '@opencx/widget-react-headless';\nimport React, { useEffect, useLayoutEffect, useRef } from 'react';\nimport { FrameDocument } from '../components/FrameDocument';\nimport { SuppressTooltips } from '../components/lib/tooltip';\nimport { RootScreen } from '../screens';\nimport { ChatFooterItems } from '../screens/chat/ChatFooterItems';\nimport { XIcon } from 'lucide-react';\nimport { FrameIconButton } from './FrameIconButton';\nimport { ChatInput } from '../screens/chat/ChatInput';\nimport { RADII } from './companion-geometry';\nimport {\n FLAT_AVATARS_CSS,\n FLAT_MESSAGE_CSS,\n HIDE_AVATARS_CSS,\n} from './message-styles';\nimport type { WidgetCompanionLayoutU } from '@opencx/widget-core';\nimport { PanelControls } from './PanelControls';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { handleCompanionFrameKeyDown } from './companion-keyboard';\n\n/**\n * Companion-only restyle of the stock screens — layout rules only, never\n * colors of its own: every color is a theme token (palette / primaryColor),\n * so the embedder's colors and `cssOverrides` apply to the companion exactly\n * as they do to popover (FrameDocument injects `cssOverrides` after this\n * sheet, so their customizations win). The `widgetContentContainer`\n * sizing/radius/shadow keys are popover-only: the companion shell owns its\n * own geometry (companion-geometry).\n */\nconst companionLayoutOverrides = `\n/* Quick-ask (resting) composer: the stock card is a two-row layout (textarea\n over an attach/send row) wrapped in outer padding. In the companion pill it\n reads as a single quick-ask bar, so drop the outer pad and lay the card out\n on ONE row — textarea flex-fills, attach + send sit inline at the end.\n Scoped to the quick-ask pane only; the full chat panel keeps the stock\n two-row composer. */\n[data-companion-input] [data-component=\"chat/input_box/root\"] {\n padding: 0 !important;\n}\n/* The attached-context tray is a FULL-composer affordance. In the one-row\n quick-ask bar it stacks a second row and paints a second surface inside the\n shell — a grey box with its own padding and radius sitting inside the white\n pill, which is not what the resting bar is. Flatten the tray to a pure\n pass-through here and hide its row; the entity still rides the send, and\n the full chat panel (one rung up) is where you see and remove it. */\n[data-companion-input] [data-component=\"chat/input_box/attached_context_tray\"] {\n padding: 0 !important;\n background: transparent !important;\n /* The root's space-y-1 puts a 4px top margin on the tray (its first sibling\n is the hidden dropzone input); with the outer padding gone that margin\n shows as a strip of shell background above the bar. */\n margin-top: 0 !important;\n}\n[data-companion-input]\n [data-component=\"chat/input_box/attached_context_tray\"]\n > *:not([data-component=\"chat/input_box/inner_root\"]) {\n display: none !important;\n}\n[data-companion-input] [data-component=\"chat/input_box/inner_root\"] {\n flex-direction: row !important;\n align-items: center !important;\n margin-top: 0 !important;\n /* The stock card is rounded-3xl (24px), but the companion shell that frames\n it clips at RADII.input in the resting-input state. A mismatch leaves the\n shell's background token peeking out as a two-tone crescent at each\n corner, so the card takes the shell radius via the custom property set on\n the quick-ask pane — one clean rounded bar. */\n border-radius: var(--opencx-companion-input-radius) !important;\n}\n[data-companion-input] [data-component=\"chat/input_box/textarea_and_attachments_container\"] {\n flex: 1 1 auto !important;\n min-width: 0 !important;\n}\n\n/* Fullscreen reading column: the panel is a full-width window, but message\n text across a 1900px panel wraps at ~200 characters. Cap the conversation\n and composer to one centered column; the header and corner controls stay\n full-width window chrome. The messages keep the cap as PADDING on the\n scroll container so the scrollbar stays at the panel edge; the footer gets\n a real max-width (+16px compensates the input card's own p-2) so the\n composer card's edges land exactly on the message column's edges. */\n[data-companion-root][data-layout=\"fullscreen\"] [data-component=\"chat/msgs/root\"] {\n padding-inline: max(16px, calc((100% - var(--opencx-companion-content-max-width)) / 2)) !important;\n}\n[data-companion-root][data-layout=\"fullscreen\"] [data-component=\"chat/main/root\"] > footer {\n width: 100%;\n max-width: calc(var(--opencx-companion-content-max-width) + 16px);\n margin-inline: auto;\n}\n\n/* Sessions (conversation history) gets the same reading column: cards and the\n sticky new-conversation button stretch edge-to-edge otherwise. Padding (not\n max-width) for the same reason as the messages — the list IS the scroll\n container, so the scrollbar stays at the panel edge. */\n[data-companion-root][data-layout=\"fullscreen\"] [data-component=\"sessions/list\"] {\n padding-inline: max(16px, calc((100% - var(--opencx-companion-content-max-width)) / 2)) !important;\n}\n`;\n\nexport function CompanionContent({\n state,\n layout,\n shellRadius,\n onMinimize,\n onDismiss,\n onToggleFullscreen,\n onSelectLayout,\n onExpand,\n canExpand,\n placeholder,\n hideAttachTools,\n onInputHeightChange,\n}: {\n state: 'input' | 'chat';\n layout: WidgetCompanionLayoutU;\n /** The panel's current corner radius in px — nested corners follow it. */\n shellRadius: number;\n /** Quick-ask composer placeholder (e.g. \"Follow up…\" while continuing) */\n placeholder: string;\n /** Hide attach + page-mark tools on the quick-ask composer (default UX:\n * history-only until the panel expands). */\n hideAttachTools: boolean;\n /** Staged collapse, one rung at a time (the × button) */\n onMinimize: () => void;\n /** Outright dismissal (Escape): drop fullscreen, else straight to the pill */\n onDismiss: () => void;\n /** Keyboard toggle between fullscreen and the prior layout (Mod+Shift+F) */\n onToggleFullscreen: () => void;\n /** Switch layout from the corner picker (compact / sidebar / fullscreen) */\n onSelectLayout: (layout: WidgetCompanionLayoutU) => void;\n /** Expand the follow-up bar back up into the open chat panel */\n onExpand: () => void;\n /** There's an open conversation to expand back into — show the expand arrow */\n canExpand: boolean;\n /** Live height of the quick-ask composer, so the shell card grows with it */\n onInputHeightChange: (height: number) => void;\n}) {\n const { companion } = useConfig();\n const initialQuestionRequired = useInitialQuestionRequired();\n const { t } = useTranslation();\n const rootRef = useRef<HTMLDivElement>(null);\n const inputPaneRef = useRef<HTMLDivElement>(null);\n const chatPaneRef = useRef<HTMLDivElement>(null);\n\n // Agent chat default: flat, document-style AI replies (no bubbles) for\n // every companion layout. `companion.bubbles: true` opts back into chat\n // bubbles.\n // `companion.avatars` follows `bubbles` unless set, so existing embeds keep\n // their look.\n const bubbles = companion?.bubbles === true;\n const avatars = companion?.avatars ?? bubbles;\n const overrides =\n companionLayoutOverrides +\n (bubbles ? '' : FLAT_MESSAGE_CSS) +\n (avatars ? '' : HIDE_AVATARS_CSS) +\n (avatars && !bubbles ? FLAT_AVATARS_CSS : '');\n\n // Shortcuts pressed anywhere inside the iframe (message list, chat\n // composer, ...) — the mirror of WidgetCompanion's host-document handler,\n // because keystrokes inside the iframe never reach the host. Both dispatch\n // through the shared registry so the two surfaces cannot drift.\n useEffect(() => {\n const doc = rootRef.current?.ownerDocument;\n if (!doc) return;\n function handleKey(e: KeyboardEvent) {\n handleCompanionFrameKeyDown(e, {\n state,\n onDismiss,\n onToggleFullscreen,\n });\n }\n doc.addEventListener('keydown', handleKey);\n return () => doc.removeEventListener('keydown', handleKey);\n }, [onDismiss, onToggleFullscreen, state]);\n\n // Measure the real composer (it grows as the user types) and drive the\n // shell card height from it. The composer lives in the iframe document, so\n // observe with THAT document's ResizeObserver, not the host window's.\n // Layout effect (not passive): report the true height BEFORE the first\n // paint so the shell morphs straight to it. A passive effect paints one\n // frame at the fallback height first, so the bar opened tall then shrank\n // to fit — a visible wobble on every open.\n useLayoutEffect(() => {\n if (state !== 'input') return;\n const node = inputPaneRef.current;\n const RO = node?.ownerDocument.defaultView?.ResizeObserver;\n if (!node || !RO) return;\n const report = () => onInputHeightChange(node.offsetHeight);\n report();\n const observer = new RO(report);\n observer.observe(node);\n return () => observer.disconnect();\n }, [state, onInputHeightChange]);\n\n // Focus the composer the moment the quick-ask pane mounts: the user's very\n // next keystrokes must land in the textarea, not the host page. Without\n // this, typing that races the expand animation is silently lost — the pill\n // only transferred focus on an explicit click into the input. (Generic\n // querySelector typing, no cast: the iframe's elements belong to another\n // realm, so an instanceof check against the host's HTMLTextAreaElement\n // would be wrong.)\n useLayoutEffect(() => {\n if (state !== 'input' || canExpand || initialQuestionRequired) return;\n focusComposer(inputPaneRef.current);\n }, [state, canExpand, initialQuestionRequired]);\n\n // The same rule one rung up: expanding into the conversation must leave the\n // caret in the composer. Without it the panel opens looking ready to type\n // and swallows every keystroke until the visitor clicks the textarea — the\n // exact bug the quick-ask pane fixed above. Runs on the transition INTO\n // chat only, so switching layouts (or scrolling back through the\n // transcript) never yanks focus away. One retry after paint covers the\n // panel that opens while the screen is still mounting; the sessions screen\n // has no composer, and there the query simply finds nothing.\n useLayoutEffect(() => {\n if (state !== 'chat') return;\n if (focusComposer(chatPaneRef.current)) return;\n const view = chatPaneRef.current?.ownerDocument.defaultView;\n if (!view) return;\n const frame = view.requestAnimationFrame(() =>\n focusComposer(chatPaneRef.current),\n );\n return () => view.cancelAnimationFrame(frame);\n }, [state]);\n\n return (\n <FrameDocument\n overrides={overrides}\n rootRef={rootRef}\n shellRadius={`${shellRadius}px`}\n >\n {/* Exactly ONE pane is mounted at a time. A hidden-but-mounted\n chat screen runs focus/measure logic against display:none\n elements, which can spin into update loops the moment it is\n revealed. Session/message state lives in the provider, so\n unmounting a pane loses nothing. The iframe is always\n chat-sized; the composer is its bottom strip and the shell\n clips everything above it. */}\n {state === 'input' ? (\n // The quick-ask state renders the EXACT stock composer (white card,\n // textarea, attach + send) rather than a bespoke bar, so it inherits\n // every embedder customization. Pinned to the bottom of the chat-tall\n // iframe; the shell clips to the measured composer height.\n <div\n ref={inputPaneRef}\n data-companion-input\n style={{\n position: 'absolute',\n left: 0,\n right: 0,\n bottom: 0,\n // The shell clips the resting input at RADII.input; the stock\n // card inside matches it via this custom property (see the\n // companionLayoutOverrides rule) so the two radii cannot drift.\n ['--opencx-companion-input-radius' as string]: `${RADII.input}px`,\n }}\n >\n <div className=\"relative\">\n {/* The shell clips this composer to a thin strip, so a `side=\"top\"`\n tooltip would bleed above the bar as a dark sliver. */}\n <SuppressTooltips>\n <ChatInput\n disabled={initialQuestionRequired}\n hideAttachTools={hideAttachTools}\n placeholder={placeholder}\n trailingActions={\n initialQuestionRequired ? (\n <FrameIconButton\n label={t('companion_close')}\n onClick={onDismiss}\n className=\"size-8\"\n >\n <XIcon className=\"size-4\" />\n </FrameIconButton>\n ) : undefined\n }\n />\n </SuppressTooltips>\n {canExpand ? (\n // Only the composer expands the minimized conversation. Keep the\n // configured footer outside this overlay so its links stay usable.\n <button\n type=\"button\"\n aria-label={t('companion_expand_chat')}\n onClick={onExpand}\n className=\"absolute inset-0 z-10 cursor-pointer\"\n />\n ) : null}\n </div>\n <ChatFooterItems />\n </div>\n ) : (\n <div\n ref={chatPaneRef}\n data-companion-root\n data-layout={layout}\n style={{\n position: 'absolute',\n inset: 0,\n ['--opencx-companion-content-max-width' as string]:\n companion?.contentMaxWidth ?? '48rem',\n }}\n >\n {/* No inner padding tricks for the fullscreen column: the\n iframe itself is sized to the column (WidgetCompanion) —\n the screens assume they own the iframe viewport. */}\n <RootScreen />\n {/* Same header as compact in every layout: the stock chat header\n (back chevron + title) plus these corner controls. Fullscreen\n just swaps the expand icon for a minimize one. */}\n <PanelControls\n layout={layout}\n onSelectLayout={onSelectLayout}\n onClose={onMinimize}\n />\n </div>\n )}\n </FrameDocument>\n );\n}\n\n/**\n * Put the caret in a pane's composer, reporting whether there was one to\n * focus. Generic `querySelector` typing, no cast: the iframe's elements\n * belong to another realm, so an `instanceof` check against the host's\n * `HTMLTextAreaElement` would be wrong.\n */\nfunction focusComposer(pane: HTMLElement | null): boolean {\n const textarea = pane?.querySelector<HTMLTextAreaElement>('textarea');\n if (!textarea) return false;\n textarea.focus({ preventScroll: true });\n return true;\n}\n","import React, { useCallback, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { WIDGET_FRAME_TITLE } from '../components/FrameDocument';\n\n/**\n * Minimal same-origin iframe portal used by companion mode instead of\n * @uiw/react-iframe. That library recreates its internal iframe callback\n * ref on every render; React 19 re-attaches changed refs each commit, and\n * the attach calls setState — under companion's re-render frequency this\n * spirals into \"Maximum update depth exceeded\" (setState in refContent via\n * commitAttachRef). Here the ref callback is stable (useCallback, no deps),\n * so it runs exactly once per DOM node lifecycle and cannot loop.\n */\nexport function CompanionFrame({\n initialContent,\n title = WIDGET_FRAME_TITLE,\n style,\n iframeRef,\n children,\n}: {\n /** Full HTML document written once into the frame (styles in <head>) */\n initialContent: string;\n title?: string;\n style: React.CSSProperties;\n /** Receives the iframe element (shared widget contentIframeRef) */\n iframeRef?: React.MutableRefObject<HTMLIFrameElement | null>;\n children: React.ReactNode;\n}) {\n const [mountNode, setMountNode] = useState<HTMLElement | null>(null);\n\n const handleRef = useCallback(\n (node: HTMLIFrameElement | null) => {\n if (iframeRef) iframeRef.current = node;\n if (!node) {\n // NO setState here. Detach runs inside React's deletion commit; a\n // setState there feeds the nested-update counter and, under remount\n // storms (HMR, error-boundary retries), stacks into \"Maximum update\n // depth exceeded\". It's also useless: on unmount the state dies with\n // the component, and on node replacement the attach call right after\n // sets the new mount node anyway.\n return;\n }\n const doc = node.contentDocument;\n if (!doc) return;\n doc.open();\n doc.write(initialContent);\n doc.close();\n setMountNode(doc.body);\n },\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [], // stability is the point — see component docblock\n );\n\n return (\n <>\n <iframe ref={handleRef} title={title} style={style} allowFullScreen />\n {mountNode && createPortal(children, mountNode)}\n </>\n );\n}\n","import {\n motion,\n useMotionValue,\n useReducedMotion,\n useSpring,\n useTransform,\n} from 'framer-motion';\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\n\n/**\n * The companion's animated face: two eyes whose pupils track the cursor\n * (spring-smoothed) and blink at random intervals.\n *\n * Rendered in the HOST page DOM (inside the pill, outside any iframe), so it\n * must not rely on Tailwind classes or widget CSS variables — sizing and\n * colors are inline.\n */\nexport function CompanionFaceIcon({\n size,\n headColor,\n eyeColor,\n}: {\n size: number;\n headColor: string;\n eyeColor: string;\n}) {\n const svgRef = useRef<SVGSVGElement>(null);\n const [hovered, setHovered] = useState(false);\n const [blinking, setBlinking] = useState(false);\n const shouldReduceMotion = useReducedMotion();\n\n const rawX = useMotionValue(0);\n const rawY = useMotionValue(0);\n const eyeX = useSpring(rawX, { stiffness: 300, damping: 30 });\n const eyeY = useSpring(rawY, { stiffness: 300, damping: 30 });\n\n // Pupil offset: small shift within the eye socket\n const leftPupilCx = useTransform(eyeX, (v) => 8 + v * 1.2);\n const leftPupilCy = useTransform(eyeY, (v) => 11.5 + v * 1.2);\n const rightPupilCx = useTransform(eyeX, (v) => 16 + v * 1.2);\n const rightPupilCy = useTransform(eyeY, (v) => 11.5 + v * 1.2);\n\n const handleMouseMove = useCallback(\n (e: MouseEvent) => {\n const svg = svgRef.current;\n if (!svg) return;\n const rect = svg.getBoundingClientRect();\n const cx = rect.left + rect.width / 2;\n const cy = rect.top + rect.height / 2;\n const dx = (e.clientX - cx) / (rect.width * 2);\n const dy = (e.clientY - cy) / (rect.height * 2);\n const dist = Math.min(Math.sqrt(dx * dx + dy * dy), 1);\n const angle = Math.atan2(dy, dx);\n rawX.set(Math.cos(angle) * dist);\n rawY.set(Math.sin(angle) * dist);\n },\n [rawX, rawY],\n );\n\n useEffect(() => {\n if (hovered && !shouldReduceMotion) {\n window.addEventListener('mousemove', handleMouseMove);\n } else {\n rawX.set(0);\n rawY.set(0);\n }\n return () => window.removeEventListener('mousemove', handleMouseMove);\n }, [hovered, handleMouseMove, rawX, rawY, shouldReduceMotion]);\n\n // Blink loop pauses under reduced motion and in hidden tabs — this ships\n // embedded on third-party pages, so a perpetual background-tab render\n // loop is real cost multiplied by every embedder.\n useEffect(() => {\n if (shouldReduceMotion) return;\n let tickId: ReturnType<typeof setTimeout>;\n let blinkOffId: ReturnType<typeof setTimeout>;\n function stop() {\n clearTimeout(tickId);\n clearTimeout(blinkOffId);\n }\n function tick() {\n tickId = setTimeout(\n () => {\n setBlinking(true);\n blinkOffId = setTimeout(() => setBlinking(false), 150);\n tick();\n },\n 1200 + Math.random() * 1800,\n );\n }\n function handleVisibility() {\n stop();\n if (document.visibilityState === 'visible') tick();\n }\n if (document.visibilityState === 'visible') tick();\n document.addEventListener('visibilitychange', handleVisibility);\n return () => {\n stop();\n document.removeEventListener('visibilitychange', handleVisibility);\n };\n }, [shouldReduceMotion]);\n\n const eyeScaleY = blinking ? 0.15 : 1;\n\n return (\n <svg\n ref={svgRef}\n viewBox=\"0 0 24 24\"\n style={{ width: size, height: size, flexShrink: 0, display: 'block' }}\n aria-hidden\n onMouseEnter={() => setHovered(true)}\n onMouseLeave={() => setHovered(false)}\n >\n {/* Head */}\n <circle cx={12} cy={12} r={11} fill={headColor} />\n {/* Eye sockets */}\n <circle cx={8} cy={11.5} r={3.2} fill={eyeColor} />\n <circle cx={16} cy={11.5} r={3.2} fill={eyeColor} />\n\n {/* Left pupil */}\n <motion.circle\n cx={leftPupilCx}\n cy={leftPupilCy}\n r={1.4}\n fill={headColor}\n animate={{ scaleY: eyeScaleY }}\n style={{ originX: '8px', originY: '11.5px' }}\n transition={{ duration: 0.08 }}\n />\n\n {/* Right pupil */}\n <motion.circle\n cx={rightPupilCx}\n cy={rightPupilCy}\n r={1.4}\n fill={headColor}\n animate={{ scaleY: eyeScaleY }}\n style={{ originX: '16px', originY: '11.5px' }}\n transition={{ duration: 0.08 }}\n />\n </svg>\n );\n}\n","import { LoaderCircleIcon } from 'lucide-react';\nimport { motion, useReducedMotion } from 'framer-motion';\nimport React from 'react';\nimport { PILL_SIZE } from './companion-geometry';\nimport { CompanionFaceIcon } from './CompanionFaceIcon';\nimport { EASE_OUT, QUICK_TWEEN } from '../motion';\n\n/**\n * The resting look of the companion shell: the icon disc, plus a label that\n * reveals to its inline-end when docked. ONE persistent structure — the icon\n * never cross-fades or moves, so collapsed→docked reads as the bar simply\n * growing out to the side and the label fading in, not a full re-render.\n *\n * `CompanionIcon` is self-contained (it carries its own dark head), so the\n * same disc works as the round pill (shell clipped to disc width) and as the\n * dock bar's left cap (shell grown, light background showing past the disc).\n *\n * Growing to the inline-END rather than from the center is done at the shell\n * level in WidgetCompanion (it pins the shell's inline-start edge while the\n * width springs), so here the icon just stays put at inline-start.\n */\n\n/**\n * The companion's identity mark: the embedder's icon when configured\n * (companion.icon, falling back to their existing trigger icon), the\n * animated face otherwise. Inline-styled so it renders identically in the\n * host DOM (pill, dock) and inside the content iframe (input bar).\n */\nfunction CompanionIcon({\n icon,\n pillBackground,\n size,\n}: {\n icon: string | undefined;\n pillBackground: string;\n size: number;\n}) {\n if (icon) {\n return (\n <img\n src={icon}\n alt=\"\"\n style={{\n width: size,\n height: size,\n objectFit: 'cover',\n borderRadius: 999,\n flexShrink: 0,\n }}\n />\n );\n }\n return (\n <CompanionFaceIcon\n size={size}\n headColor={pillBackground}\n eyeColor=\"hsl(var(--opencx-primary-foreground))\"\n />\n );\n}\n\n/** Fades out immediately on open; on close waits for the shell to shrink. */\nfunction restingFade(visible: boolean) {\n return {\n initial: false as const,\n animate: { opacity: visible ? 1 : 0 },\n transition: { ...QUICK_TWEEN, delay: visible ? 0.25 : 0 },\n };\n}\n\nexport function RestingPill({\n visible,\n docked,\n label,\n icon,\n pillBackground,\n dir,\n measureRef,\n activeCount = 0,\n countLabel,\n onOpenChats,\n pickerOpen = false,\n working = false,\n sessions,\n}: {\n /** The shell is resting as a pill (vs. morphed open) — show this look */\n sessions?: React.ReactNode;\n activeCount?: number;\n countLabel?: string;\n onOpenChats?: (anchor: HTMLButtonElement, pointer: boolean) => void;\n pickerOpen?: boolean;\n working?: boolean;\n visible: boolean;\n /** Expanded into the labeled bar (vs. the icon-only round pill) */\n docked: boolean;\n label: string;\n icon: string | undefined;\n pillBackground: string;\n dir: string;\n /** Measures the natural bar width (disc + label) so the shell springs to it */\n measureRef: (node: HTMLDivElement | null) => void;\n}) {\n const reduceMotion = useReducedMotion();\n return (\n <motion.div\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n borderRadius: 'inherit',\n overflow: 'hidden',\n pointerEvents: 'none',\n userSelect: 'none',\n // Light bar surface; the icon disc carries its own (dark) background,\n // so the collapsed pill — shell clipped to the disc — still reads dark.\n background: 'hsl(var(--opencx-background))',\n }}\n {...restingFade(visible)}\n >\n {visible && !docked && activeCount > 0 && (\n <button\n type=\"button\"\n data-companion-count-trigger=\"\"\n aria-label={countLabel}\n aria-haspopup=\"menu\"\n aria-expanded={pickerOpen}\n onClick={(event) => {\n event.stopPropagation();\n onOpenChats?.(event.currentTarget, event.detail > 0);\n }}\n style={{\n position: 'absolute',\n insetInlineStart: 12,\n top: 0,\n zIndex: 2,\n width: 24,\n height: 24,\n padding: 0,\n border: 0,\n background: 'transparent',\n pointerEvents: 'auto',\n cursor: 'pointer',\n }}\n >\n <span\n aria-hidden\n style={{\n position: 'absolute',\n insetInlineStart: 6,\n top: 0,\n width: 14,\n height: 14,\n display: 'grid',\n placeItems: 'center',\n borderRadius: 999,\n background: 'hsl(var(--opencx-background))',\n color: 'hsl(var(--opencx-foreground))',\n font: '9px ui-sans-serif,system-ui,sans-serif',\n fontVariantNumeric: 'tabular-nums',\n }}\n >\n {activeCount}\n {working && (\n <motion.span\n style={{ position: 'absolute', inset: -2, display: 'flex' }}\n animate={reduceMotion ? undefined : { rotate: 360 }}\n transition={{ duration: 1.2, repeat: Infinity, ease: 'linear' }}\n >\n <LoaderCircleIcon size={18} />\n </motion.span>\n )}\n </span>\n </button>\n )}\n <div\n ref={measureRef}\n dir={dir}\n style={{\n display: 'flex',\n alignItems: 'center',\n gap: 8,\n height: '100%',\n width: 'max-content',\n // No inline-start padding: the disc IS the pill's leading cap, so it\n // fills the round pill exactly when collapsed.\n paddingInlineEnd: 12,\n fontFamily: 'ui-sans-serif, system-ui, sans-serif',\n }}\n >\n <CompanionIcon\n icon={icon}\n pillBackground={pillBackground}\n size={PILL_SIZE}\n />\n <motion.span\n initial={false}\n animate={{ opacity: docked ? 1 : 0 }}\n transition={{ duration: 0.12, ease: EASE_OUT }}\n style={{\n fontSize: 13,\n color: 'hsl(var(--opencx-muted-foreground))',\n whiteSpace: 'nowrap',\n }}\n >\n {label}\n </motion.span>\n {sessions && (\n <div\n style={{\n position: 'relative',\n zIndex: 2,\n paddingInlineStart: 4,\n opacity: docked ? 1 : 0,\n }}\n >\n {sessions}\n </div>\n )}\n </div>\n </motion.div>\n );\n}\n","import React, { useEffect, useState } from 'react';\nimport * as Tooltip from '@radix-ui/react-tooltip';\nimport { useCompanionChats, useSessions } from '@opencx/widget-react-headless';\nimport { LoaderCircleIcon, PlusIcon, XIcon } from 'lucide-react';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { useSessionIdentity } from './useSessionIdentity';\nimport { useTheme } from '../hooks/useTheme';\nimport { useIsSmallScreen } from '../hooks/useIsSmallScreen';\nimport { ChatPicker } from './ChatPicker';\nimport { useChatPicker } from './useChatPicker';\nimport { useHostPortal } from './useHostPortal';\nimport { Button } from '../components/lib/button';\nimport { CompanionControlStyles } from './CompanionControlStyles';\n\ntype Chat = ReturnType<typeof useCompanionChats>['chats'][number];\n\nfunction SessionCircle({\n chat,\n number,\n selected,\n interactive,\n onSelect,\n onClose,\n portalTarget,\n}: {\n chat: Chat;\n number: number;\n selected: boolean;\n interactive: boolean;\n onSelect: () => void;\n onClose: (button: HTMLButtonElement) => void;\n portalTarget: HTMLElement | null;\n}) {\n const { t } = useTranslation();\n const { cssVars, theme } = useTheme();\n const [tooltipOpen, setTooltipOpen] = useState(false);\n useEffect(() => {\n if (!interactive) {\n setTooltipOpen(false);\n }\n }, [interactive]);\n const { title } = useSessionIdentity(chat);\n const label = `${title}${chat.working ? ` — ${t('thinking')}` : ''}`;\n function tooltip(text: string) {\n return (\n portalTarget && (\n <Tooltip.Portal container={portalTarget}>\n <Tooltip.Content\n side=\"top\"\n sideOffset={8}\n collisionPadding={12}\n data-companion-session-tooltip=\"\"\n // Keep the chat title outside the launcher's clipping surface.\n style={{\n ...cssVars,\n zIndex: theme.widgetContentContainer.zIndex + 2,\n maxWidth: 'min(280px, calc(100vw - 24px))',\n padding: '7px 10px',\n borderRadius: 9,\n background: 'hsl(var(--opencx-foreground))',\n color: 'hsl(var(--opencx-background))',\n font: '12px/1.4 ui-sans-serif, system-ui, sans-serif',\n overflowWrap: 'anywhere',\n textAlign: 'center',\n boxShadow: '0 4px 14px rgb(0 0 0 / .12)',\n }}\n >\n {text}\n <Tooltip.Arrow\n width={8}\n height={4}\n style={{ fill: 'hsl(var(--opencx-foreground))' }}\n />\n </Tooltip.Content>\n </Tooltip.Portal>\n )\n );\n }\n const closeLabel = t('companion_close_chat', { title });\n return (\n <div data-session-item=\"\">\n <Tooltip.Root\n open={interactive && tooltipOpen}\n onOpenChange={setTooltipOpen}\n >\n <Tooltip.Trigger asChild>\n <Button\n variant=\"ghost\"\n size=\"selfless\"\n data-companion-action=\"\"\n type=\"button\"\n data-session-circle={chat.id}\n aria-label={label}\n aria-pressed={selected}\n tabIndex={interactive ? 0 : -1}\n onClick={(event) => {\n event.stopPropagation();\n onSelect();\n }}\n >\n {chat.working && (\n <LoaderCircleIcon size={28} aria-hidden data-session-working=\"\" />\n )}\n <span aria-hidden>{number}</span>\n </Button>\n </Tooltip.Trigger>\n {tooltip(label)}\n </Tooltip.Root>\n <Button\n variant=\"ghost\"\n size=\"selfless\"\n data-companion-action=\"\"\n type=\"button\"\n data-session-close={chat.id}\n aria-label={closeLabel}\n tabIndex={interactive ? 0 : -1}\n onClick={(event) => {\n event.stopPropagation();\n setTooltipOpen(false);\n onClose(event.currentTarget);\n }}\n >\n <XIcon size={10} aria-hidden />\n </Button>\n </div>\n );\n}\n\n/** Direct switches; the compact picker handles only overflow. Works in both documents. */\nexport function SessionCircles({\n onSelected = () => {},\n onLastClosed = () => {},\n interactive = true,\n}: {\n onSelected?: () => void;\n onLastClosed?: () => void;\n interactive?: boolean;\n}) {\n const {\n openChats: activeChats,\n activeId,\n selectChat,\n newChat,\n closeChat,\n } = useCompanionChats();\n const { canCreateNewSession } = useSessions();\n const { isSmallScreen } = useIsSmallScreen();\n const { t, dir } = useTranslation();\n const picker = useChatPicker();\n const portalTarget = useHostPortal();\n // Reserve an overflow slot and always keep the current session visible.\n const limit = isSmallScreen ? 2 : 3;\n const visible = activeChats.slice(\n 0,\n activeChats.length > limit ? limit - 1 : limit,\n );\n const current = activeChats.find((chat) => chat.id === activeId);\n if (current && !visible.includes(current))\n visible[visible.length - 1] = current;\n const hiddenCount = activeChats.length - visible.length;\n const hiddenWorking = activeChats.some(\n (chat) => chat.working && !visible.includes(chat),\n );\n const close = React.useRef(picker.close);\n close.current = picker.close;\n useEffect(() => {\n if (!interactive) close.current(true);\n }, [interactive]);\n\n function choose(id?: number) {\n picker.close(true);\n if (id === undefined) newChat();\n else selectChat(id);\n onSelected();\n }\n\n function dismiss(id: number, button: HTMLButtonElement) {\n picker.close(true);\n const index = visible.findIndex((chat) => chat.id === id);\n const next = visible[index + 1] ?? visible[index - 1];\n button\n .closest('[data-companion-session-circles]')\n ?.querySelector<HTMLElement>(\n next ? `[data-session-circle=\"${next.id}\"]` : '[data-new-session]',\n )\n ?.focus({ preventScroll: true });\n closeChat(id);\n if (activeChats.length === 1) onLastClosed();\n }\n\n return (\n <Tooltip.Provider delayDuration={150} skipDelayDuration={300}>\n <div\n role=\"group\"\n aria-label={t('companion_active_chats', { count: activeChats.length })}\n aria-hidden={!interactive || undefined}\n data-companion-session-circles=\"\"\n dir={dir}\n // Session clicks must not start a drag of the resting launcher.\n onPointerDown={(event) => event.stopPropagation()}\n style={{\n position: 'relative',\n // Keep header circles below the overlaid layout menu.\n zIndex: 0,\n display: 'flex',\n alignItems: 'center',\n gap: 4,\n flexShrink: 0,\n pointerEvents: interactive ? 'auto' : 'none',\n }}\n >\n <CompanionControlStyles />\n <style>{`\n [data-companion-session-tooltip][data-state=\"delayed-open\"] { animation: opencx-session-tooltip-in 120ms ease-out; }\n @keyframes opencx-session-tooltip-in { from { opacity: 0; } to { opacity: 1; } }\n @media (prefers-reduced-motion: reduce) { [data-companion-session-tooltip] { animation: none !important; } }\n [data-companion-session-circles] > button,\n [data-companion-session-circles] [data-session-circle] {\n position: relative; display: grid; place-items: center; flex: 0 0 28px;\n width: 28px; height: 28px; padding: 0; border-radius: 50%;\n border: 1px solid hsl(var(--opencx-border));\n background: transparent; color: hsl(var(--opencx-muted-foreground));\n font: 11px ui-sans-serif, system-ui, sans-serif; font-variant-numeric: tabular-nums;\n cursor: pointer;\n }\n [data-companion-session-circles] [data-session-circle][aria-pressed=\"true\"] {\n border-color: hsl(var(--opencx-primary) / .45);\n background: hsl(var(--opencx-primary) / .08);\n color: hsl(var(--opencx-foreground));\n }\n @media (hover: hover) and (pointer: fine) {\n [data-companion-session-circles] > button:hover,\n [data-companion-session-circles] [data-session-item]:hover [data-session-circle] { background: hsl(var(--opencx-muted)); color: hsl(var(--opencx-foreground)); }\n }\n [data-companion-session-circles] button:focus-visible { outline: 2px solid hsl(var(--opencx-ring)); outline-offset: 2px; }\n [data-companion-session-circles] > button:disabled { opacity: .4; cursor: default; }\n [data-companion-session-circles] [data-session-item] { position: relative; display: flex; align-items: center; width: 36px; height: 32px; flex-shrink: 0; }\n [data-companion-session-circles] [data-session-close] {\n position: absolute; inset-inline-end: 0; top: -1px; z-index: 1;\n width: 16px; height: 16px; display: grid; place-items: center; padding: 0;\n border: 1px solid hsl(var(--opencx-border) / .7); border-radius: 50%;\n background: hsl(var(--opencx-background)); color: hsl(var(--opencx-muted-foreground)); cursor: pointer;\n }\n @media (hover: hover) and (pointer: fine) {\n [data-companion-session-circles] [data-session-close] { opacity: 0; pointer-events: none; }\n [data-companion-session-circles] [data-session-item]:hover [data-session-close],\n [data-companion-session-circles] [data-session-item]:focus-within [data-session-close] { opacity: 1; pointer-events: auto; }\n [data-companion-session-circles] [data-session-close]:hover { color: hsl(var(--opencx-foreground)); }\n }\n @media (pointer: coarse) {\n [data-companion-session-circles] [data-session-item] { width: 42px; }\n [data-companion-session-circles] [data-session-close] { width: 24px; height: 24px; top: -3px; }\n [data-companion-session-circles] [data-session-close] svg { width: 12px; height: 12px; }\n }\n [data-companion-session-circles] > button[data-new-session] { border-style: dashed; }\n [data-companion-session-circles] [data-session-working] {\n position: absolute; inset: -1px; color: hsl(var(--opencx-primary));\n animation: opencx-session-spin 1.2s linear infinite;\n }\n @keyframes opencx-session-spin { to { transform: rotate(360deg); } }\n @media (prefers-reduced-motion: reduce) { [data-companion-session-circles] [data-session-working] { animation: none; } }\n `}</style>\n {visible.map((chat) => (\n <SessionCircle\n key={chat.id}\n chat={chat}\n number={chat.id}\n selected={chat.id === activeId}\n interactive={interactive}\n portalTarget={portalTarget}\n onSelect={() => choose(chat.id)}\n onClose={(button) => dismiss(chat.id, button)}\n />\n ))}\n {hiddenCount > 0 && (\n <Button\n variant=\"ghost\"\n size=\"selfless\"\n data-companion-action=\"\"\n type=\"button\"\n aria-label={t('companion_chats')}\n aria-haspopup=\"menu\"\n aria-expanded={picker.open}\n tabIndex={interactive ? 0 : -1}\n onPointerEnter={(event) => picker.hover(event.currentTarget)}\n onPointerLeave={picker.leave}\n onClick={(event) => {\n event.stopPropagation();\n picker.toggle(event.currentTarget, event.detail > 0);\n }}\n >\n {hiddenWorking && (\n <LoaderCircleIcon size={28} aria-hidden data-session-working=\"\" />\n )}\n <span aria-hidden>+{hiddenCount}</span>\n </Button>\n )}\n <Button\n variant=\"ghost\"\n size=\"selfless\"\n data-companion-action=\"\"\n type=\"button\"\n data-new-session=\"\"\n aria-label={t('new_conversation')}\n disabled={!canCreateNewSession}\n tabIndex={interactive ? 0 : -1}\n onClick={(event) => {\n event.stopPropagation();\n choose();\n }}\n >\n <PlusIcon size={14} aria-hidden />\n </Button>\n {picker.anchor && portalTarget && (\n <ChatPicker\n picker={picker}\n portalTarget={portalTarget}\n placement=\"above\"\n onSelected={onSelected}\n />\n )}\n </div>\n </Tooltip.Provider>\n );\n}\n","import { useEffect, useRef } from 'react';\n\n/** Sync shell visibility with the public trigger without treating callback changes as external requests. */\nexport function useCompanionOpenSync({\n panelOpen,\n isOpen,\n setIsOpen,\n onOpen,\n onClose,\n}: {\n panelOpen: boolean;\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n onOpen: () => void;\n onClose: () => void;\n}) {\n const lastPushed = useRef(isOpen);\n const actions = useRef({ onOpen, onClose });\n actions.current = { onOpen, onClose };\n useEffect(() => {\n lastPushed.current = panelOpen;\n setIsOpen(panelOpen);\n }, [panelOpen, setIsOpen]);\n useEffect(() => {\n if (isOpen === lastPushed.current) return;\n lastPushed.current = isOpen;\n if (isOpen) actions.current.onOpen();\n else actions.current.onClose();\n // Changing conversations changes onOpen, but is not an external toggle.\n }, [isOpen]);\n}\n","/**\n * The sidebar's \"app frame\", CSS-only: document.body ITSELF becomes a\n * fixed, full-viewport frame with its own scroller — no host DOM node is\n * ever moved. Opening the sidebar insets body on the inline sides only\n * (16px gap, 20px radius, ring + shadow) so the host page reads as a\n * child window on the canvas, with the wide inset on whichever physical\n * side the panel occupies (`companion.sidebar.side`). The block sides stay flush on purpose:\n * viewport units don't shrink with the frame, so any top/bottom gap makes\n * a 100vh/100dvh host shell overflow by exactly that gap and grow a stray\n * scrollbar. Full height keeps vh-sized apps fitting exactly.\n *\n * Why no reparenting: the previous implementation moved body's children\n * into a widget-owned frame div. That detaches nodes the host framework\n * owns — a React host crashes with \"NotFoundError: removeChild\" the moment\n * it unmounts a body-level portal (Radix menus, tooltips, toasts) that the\n * frame captured. Styling body in place is the same visual with zero DOM\n * mutation.\n *\n * `contain: strict` is still the load-bearing line: it makes body the\n * containing block for the host's OWN fixed/sticky elements (app rails,\n * navbars), so the entire app shrinks as one — while the widget itself,\n * portaled to document.documentElement (see useHostPortal), stays outside\n * the containment and viewport-fixed.\n *\n * html gets overflow:hidden so body's overflow:auto scrolls body itself\n * instead of propagating to the viewport, and the canvas color sits on\n * html (body's own background can't propagate past its paint containment).\n * Everything is attribute-scoped with !important — body is host territory\n * and host CSS must not win while framed. Every mount receives an owner lease;\n * the global attributes reflect the most recently opened owner, and the final\n * release removes every attribute/style and restores scroll.\n */\n\nimport type { WidgetSidebarSideResolvedU } from '@opencx/widget-core';\nimport {\n DEFAULT_SIDEBAR_WIDTH,\n RADII,\n SIDEBAR_FULL_BLEED_MAX_WIDTH,\n SIDEBAR_MARGIN,\n} from './companion-geometry';\nimport { APP_FRAME_EASE_CSS } from '../motion';\n\nconst FRAME_ATTR = 'data-opencx-app-frame';\nconst STYLE_ATTR = 'data-opencx-app-frame-style';\nconst OPEN_ATTR = 'data-opencx-sidebar-open';\nconst NO_ANIM_ATTR = 'data-opencx-frame-no-anim';\nconst FIT_ATTR = 'data-opencx-fixed-fit';\nconst WIDTH_VAR = '--opencx-sidebar-w';\nconst EASE = APP_FRAME_EASE_CSS;\n\nlet styleEl: HTMLStyleElement | null = null;\nlet fitObserver: MutationObserver | null = null;\nlet ownerOrder = 0;\n\ntype AppFrameOwner = {\n canvas: string;\n side: WidgetSidebarSideResolvedU;\n pageBackground: string;\n open: boolean;\n width: number;\n animated: boolean;\n order: number;\n};\n\nconst owners = new Map<symbol, AppFrameOwner>();\n\nexport type AppFrameLease = {\n setOpen: (open: boolean) => void;\n setWidth: (width: number) => void;\n setAnimated: (animated: boolean) => void;\n release: () => void;\n};\n\nconst NOOP_LEASE: AppFrameLease = {\n setOpen: () => {},\n setWidth: () => {},\n setAnimated: () => {},\n release: () => {},\n};\n\nfunction activeOwner(): AppFrameOwner | undefined {\n let latest: AppFrameOwner | undefined;\n let latestOpen: AppFrameOwner | undefined;\n owners.forEach((owner) => {\n if (!latest || owner.order > latest.order) latest = owner;\n if (owner.open && (!latestOpen || owner.order > latestOpen.order)) {\n latestOpen = owner;\n }\n });\n return latestOpen ?? latest;\n}\n\nfunction applyOwnerState(): void {\n const owner = activeOwner();\n if (!owner || !styleEl) return;\n\n styleEl.textContent = buildCss(\n owner.canvas,\n owner.side,\n owner.pageBackground,\n );\n const html = document.documentElement;\n if (owner.open) html.setAttribute(OPEN_ATTR, '');\n else html.removeAttribute(OPEN_ATTR);\n if (owner.animated) html.removeAttribute(NO_ANIM_ATTR);\n else html.setAttribute(NO_ANIM_ATTR, '');\n html.style.setProperty(WIDTH_VAR, `${owner.width}px`);\n}\n\n/**\n * Viewport-unit shells (`position: fixed; width: 100vw` — Tailwind\n * `w-screen`/`w-svw`) don't shrink with the frame, so the framed page grows\n * a horizontal scrollbar instead of narrowing. `contain: strict` already\n * makes body the containing block for every fixed descendant, so a\n * `max-width/max-height: 100%` clamp resolves against the frame — stamped\n * fixed elements shrink with it. Fixed elements only: in-flow wide\n * scrollers (tables, code blocks) must keep their own overflow, and\n * absolute elements resolve % against their positioned ancestor, where the\n * clamp would shrink legitimate popovers. CSS can't select by computed\n * position, hence the attribute stamp.\n */\nfunction stampFixedElements(root: Element): void {\n if (getComputedStyle(root).position === 'fixed') {\n root.setAttribute(FIT_ATTR, '');\n }\n for (const el of Array.from(root.querySelectorAll('*'))) {\n if (getComputedStyle(el).position === 'fixed') {\n el.setAttribute(FIT_ATTR, '');\n }\n }\n}\n\nfunction buildCss(\n canvas: string,\n side: WidgetSidebarSideResolvedU,\n pageBackground: string,\n): string {\n // `side` is the panel's PHYSICAL edge, already resolved from config + host\n // dir by the caller — body's own dir is irrelevant here, and an explicit\n // `sidebar.side` deliberately overrides it.\n const [near, far] = side === 'left' ? ['right', 'left'] : ['left', 'right'];\n return `\nhtml[${FRAME_ATTR}] {\n overflow: hidden !important;\n background: ${canvas} !important;\n}\nhtml[${FRAME_ATTR}] body {\n position: fixed !important;\n inset: 0 !important;\n margin: 0 !important;\n width: auto !important;\n height: auto !important;\n min-width: 0 !important;\n min-height: 0 !important;\n max-width: none !important;\n max-height: none !important;\n overflow: auto !important;\n contain: strict !important;\n background: ${pageBackground} !important;\n border-radius: 0 !important;\n /* Transparent ring+shadow, NOT none — none can't interpolate */\n box-shadow: 0 0 0 1px rgba(0,0,0,0), 0 10px 24px -6px rgba(0,0,0,0) !important;\n}\n@media (prefers-reduced-motion: no-preference) {\n html[${FRAME_ATTR}] body {\n transition:\n top 0.3s ${EASE}, bottom 0.3s ${EASE},\n left 0.3s ${EASE}, right 0.3s ${EASE},\n border-radius 0.3s ${EASE}, box-shadow 0.3s ${EASE} !important;\n }\n}\nhtml[${NO_ANIM_ATTR}] body { transition: none !important; }\nhtml[${FRAME_ATTR}] body [${FIT_ATTR}] {\n max-width: 100% !important;\n max-height: 100% !important;\n}\nhtml[${OPEN_ATTR}] body {\n top: ${SIDEBAR_MARGIN}px !important;\n bottom: ${SIDEBAR_MARGIN}px !important;\n ${near}: ${SIDEBAR_MARGIN}px !important;\n ${far}: calc(var(${WIDTH_VAR}, ${DEFAULT_SIDEBAR_WIDTH}px) + ${SIDEBAR_MARGIN * 2}px) !important;\n border-radius: ${RADII.sidebar}px !important;\n box-shadow: 0 0 0 1px rgba(0,0,0,0.06), 0 10px 24px -6px rgba(0,0,0,0.10) !important;\n}\n@media (max-width: ${SIDEBAR_FULL_BLEED_MAX_WIDTH}px) {\n html[${OPEN_ATTR}] body {\n inset: 0 !important;\n border-radius: 0 !important;\n box-shadow: 0 0 0 1px rgba(0,0,0,0), 0 10px 24px -6px rgba(0,0,0,0) !important;\n }\n}\n`;\n}\n\nexport function mountAppFrame({\n canvas,\n side,\n pageBackground,\n}: {\n canvas: string;\n side: WidgetSidebarSideResolvedU;\n pageBackground: string;\n}): AppFrameLease {\n if (typeof document === 'undefined') return NOOP_LEASE;\n const html = document.documentElement;\n // Respect a frame owned by another script/runtime without claiming it.\n if (!styleEl && html.hasAttribute(FRAME_ATTR)) return NOOP_LEASE;\n\n if (!styleEl) {\n const style = document.createElement('style');\n style.setAttribute(STYLE_ATTR, '');\n document.head.appendChild(style);\n\n const prevScrollY = window.scrollY;\n html.setAttribute(FRAME_ATTR, '');\n document.body.scrollTop = prevScrollY;\n\n // Fit-clamp every fixed element now, and keep stamping ones the host adds\n // while framed (SPA route changes remount shells; menus/toasts portal in).\n stampFixedElements(document.body);\n fitObserver = new MutationObserver((mutations) => {\n for (const mutation of mutations) {\n for (const node of Array.from(mutation.addedNodes)) {\n if (node instanceof Element) stampFixedElements(node);\n }\n }\n });\n fitObserver.observe(document.body, { childList: true, subtree: true });\n styleEl = style;\n }\n\n const ownerId = Symbol('opencx-app-frame-owner');\n const owner: AppFrameOwner = {\n canvas,\n side,\n pageBackground,\n open: false,\n width: DEFAULT_SIDEBAR_WIDTH,\n animated: true,\n order: ++ownerOrder,\n };\n owners.set(ownerId, owner);\n applyOwnerState();\n\n let released = false;\n const update = (change: (current: AppFrameOwner) => void) => {\n if (released) return;\n const current = owners.get(ownerId);\n if (!current) return;\n change(current);\n applyOwnerState();\n };\n return {\n setOpen(open) {\n update((current) => {\n current.open = open;\n if (open) current.order = ++ownerOrder;\n });\n },\n setWidth(width) {\n update((current) => {\n current.width = width;\n });\n },\n setAnimated(animated) {\n update((current) => {\n current.animated = animated;\n });\n },\n release() {\n if (released) return;\n released = true;\n owners.delete(ownerId);\n if (owners.size === 0) teardownAppFrame();\n else applyOwnerState();\n },\n };\n}\n\nfunction teardownAppFrame(): void {\n if (!styleEl) return;\n const prevScrollTop = document.body.scrollTop;\n const html = document.documentElement;\n html.removeAttribute(FRAME_ATTR);\n html.removeAttribute(OPEN_ATTR);\n html.removeAttribute(NO_ANIM_ATTR);\n html.style.removeProperty(WIDTH_VAR);\n fitObserver?.disconnect();\n fitObserver = null;\n for (const el of Array.from(document.querySelectorAll(`[${FIT_ATTR}]`))) {\n el.removeAttribute(FIT_ATTR);\n }\n styleEl.remove();\n styleEl = null;\n window.scrollTo({ top: prevScrollTop });\n}\n","let lockCount = 0;\nlet previousOverflow = '';\n\n/** Acquire a shared host-body scroll lock. The returned release function is\n * idempotent, and one widget cannot unlock the page while another still owns\n * a fullscreen panel. */\nexport function lockHostScroll(): () => void {\n if (typeof document === 'undefined') return () => {};\n if (lockCount === 0) {\n previousOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n lockCount += 1;\n\n let released = false;\n return () => {\n if (released) return;\n released = true;\n lockCount = Math.max(0, lockCount - 1);\n if (lockCount === 0) {\n document.body.style.overflow = previousOverflow;\n previousOverflow = '';\n }\n };\n}\n","import type {\n WidgetCompanionLayoutU,\n WidgetConfig,\n WidgetCtx,\n WidgetSidebarModeU,\n WidgetSidebarSideResolvedU,\n} from '@opencx/widget-core';\nimport React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { mountAppFrame, type AppFrameLease } from './app-frame';\nimport {\n clamp,\n DEFAULT_SIDEBAR_WIDTH,\n effectiveSidebarWidth,\n MAX_SIDEBAR_WIDTH,\n MIN_SIDEBAR_WIDTH,\n type Region,\n SIDEBAR_CANVAS,\n} from './companion-geometry';\nimport { lockHostScroll } from './host-scroll-lock';\nimport type { PanelState } from './types';\n\ntype SidebarWidthStorage = Pick<\n NonNullable<WidgetCtx['storageCtx']>,\n 'getCompanionSidebarWidth' | 'setCompanionSidebarWidth'\n>;\n\nfunction readCssVar(\n vars: Readonly<Record<string, string>>,\n name: string,\n): string {\n return vars[name] ?? '';\n}\n\n/**\n * Owns every effect that mutates the host page: persisted sidebar sizing,\n * pointer/keyboard resize, optional app-frame mounting, and fullscreen scroll\n * locking. The shell receives only the current width and ready-to-spread\n * separator props.\n */\nexport function useCompanionHostEffects({\n companion,\n layout,\n state,\n region,\n sidebarSide,\n sidebarMode,\n cssVars,\n storage,\n resizeLabel,\n}: {\n companion: WidgetConfig['companion'];\n layout: WidgetCompanionLayoutU;\n state: PanelState;\n region: Region;\n /**\n * Already resolved from config + host dir (and the visitor's own pick) by\n * the layout context — everything here works in PHYSICAL terms so an\n * explicit side beats the host document's direction.\n */\n sidebarSide: WidgetSidebarSideResolvedU;\n sidebarMode: WidgetSidebarModeU;\n cssVars: Readonly<Record<string, string>>;\n storage: SidebarWidthStorage | undefined;\n resizeLabel: string;\n}) {\n const minSidebarWidth = Math.max(\n 0,\n companion?.sidebar?.minWidth ?? MIN_SIDEBAR_WIDTH,\n );\n const maxSidebarWidth = Math.max(\n minSidebarWidth,\n companion?.sidebar?.maxWidth ?? MAX_SIDEBAR_WIDTH,\n );\n const [sidebarWidth, setSidebarWidth] = useState(() =>\n clamp(\n companion?.sidebar?.width ?? DEFAULT_SIDEBAR_WIDTH,\n minSidebarWidth,\n maxSidebarWidth,\n ),\n );\n const [sidebarResizing, setSidebarResizing] = useState(false);\n const frameLeaseRef = useRef<AppFrameLease | null>(null);\n\n useEffect(() => {\n setSidebarWidth((current) =>\n clamp(\n companion?.sidebar?.width ?? current,\n minSidebarWidth,\n maxSidebarWidth,\n ),\n );\n }, [companion?.sidebar?.width, maxSidebarWidth, minSidebarWidth]);\n\n useEffect(() => {\n let cancelled = false;\n if (!storage || companion?.sidebar?.width !== undefined) return;\n\n void storage\n .getCompanionSidebarWidth()\n .then((saved) => {\n if (cancelled || saved === null) return;\n setSidebarWidth(clamp(saved, minSidebarWidth, maxSidebarWidth));\n })\n .catch(() => {});\n\n return () => {\n cancelled = true;\n };\n }, [companion?.sidebar?.width, maxSidebarWidth, minSidebarWidth, storage]);\n\n // The handle is on the panel's inner edge, so the width is the distance\n // from the pointer to the panel's OWN viewport edge.\n const widthFromPointer = useCallback(\n (clientX: number) =>\n clamp(\n sidebarSide === 'left' ? clientX : window.innerWidth - clientX,\n minSidebarWidth,\n maxSidebarWidth,\n ),\n [maxSidebarWidth, minSidebarWidth, sidebarSide],\n );\n\n const onPointerDown = useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n event.currentTarget.setPointerCapture(event.pointerId);\n setSidebarResizing(true);\n frameLeaseRef.current?.setAnimated(false);\n },\n [],\n );\n\n const onPointerMove = useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n if (!event.currentTarget.hasPointerCapture(event.pointerId)) return;\n setSidebarWidth(widthFromPointer(event.clientX));\n },\n [widthFromPointer],\n );\n\n const onPointerUp = useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n const finalWidth = widthFromPointer(event.clientX);\n if (event.currentTarget.hasPointerCapture(event.pointerId)) {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n setSidebarWidth(finalWidth);\n setSidebarResizing(false);\n frameLeaseRef.current?.setAnimated(true);\n void storage?.setCompanionSidebarWidth(finalWidth).catch(() => {});\n },\n [storage, widthFromPointer],\n );\n\n const onPointerCancel = useCallback(\n (event: React.PointerEvent<HTMLDivElement>) => {\n if (event.currentTarget.hasPointerCapture(event.pointerId)) {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n setSidebarResizing(false);\n frameLeaseRef.current?.setAnimated(true);\n },\n [],\n );\n\n const onKeyDown = useCallback(\n (event: React.KeyboardEvent<HTMLDivElement>) => {\n let next: number | null = null;\n if (event.key === 'Home') next = minSidebarWidth;\n if (event.key === 'End') next = maxSidebarWidth;\n if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {\n // Growing means moving the handle AWAY from the panel's edge: left\n // for a right-side panel, right for a left-side one.\n const grows =\n event.key === (sidebarSide === 'left' ? 'ArrowRight' : 'ArrowLeft');\n next = clamp(\n sidebarWidth + (grows ? 16 : -16),\n minSidebarWidth,\n maxSidebarWidth,\n );\n }\n if (next === null) return;\n event.preventDefault();\n setSidebarWidth(next);\n void storage?.setCompanionSidebarWidth(next).catch(() => {});\n },\n [maxSidebarWidth, minSidebarWidth, sidebarSide, sidebarWidth, storage],\n );\n\n const isSidebar = layout === 'sidebar';\n const isDocked = sidebarMode === 'docked';\n const frameWidth = effectiveSidebarWidth(region, sidebarWidth);\n const canvas = companion?.sidebar?.canvasColor ?? SIDEBAR_CANVAS;\n const pageBackground = `hsl(${readCssVar(cssVars, '--opencx-background')})`;\n const frameStateRef = useRef({\n open: state !== 'pill',\n width: frameWidth,\n });\n frameStateRef.current = { open: state !== 'pill', width: frameWidth };\n\n useEffect(() => {\n if (!isSidebar || !isDocked) return;\n const lease = mountAppFrame({ canvas, side: sidebarSide, pageBackground });\n frameLeaseRef.current = lease;\n lease.setWidth(frameStateRef.current.width);\n lease.setOpen(frameStateRef.current.open);\n return () => {\n if (frameLeaseRef.current === lease) frameLeaseRef.current = null;\n lease.release();\n };\n }, [canvas, isDocked, isSidebar, pageBackground, sidebarSide]);\n\n useEffect(() => {\n if (isSidebar && isDocked) frameLeaseRef.current?.setWidth(frameWidth);\n }, [frameWidth, isDocked, isSidebar]);\n\n useEffect(() => {\n if (isSidebar && isDocked) {\n frameLeaseRef.current?.setOpen(state !== 'pill');\n }\n }, [isDocked, isSidebar, state]);\n\n const isFullscreenModal = state === 'chat' && layout === 'fullscreen';\n const lockFullscreenScroll = companion?.fullscreen?.lockScroll !== false;\n useEffect(() => {\n if (!isFullscreenModal || !lockFullscreenScroll) return;\n return lockHostScroll();\n }, [isFullscreenModal, lockFullscreenScroll]);\n\n const resizeHandleProps = useMemo(\n () => ({\n role: 'separator' as const,\n tabIndex: 0,\n 'aria-orientation': 'vertical' as const,\n 'aria-label': resizeLabel,\n 'aria-valuemin': minSidebarWidth,\n 'aria-valuemax': maxSidebarWidth,\n 'aria-valuenow': sidebarWidth,\n onPointerDown,\n onPointerMove,\n onPointerUp,\n onPointerCancel,\n onKeyDown,\n }),\n [\n maxSidebarWidth,\n minSidebarWidth,\n onKeyDown,\n onPointerDown,\n onPointerMove,\n onPointerCancel,\n onPointerUp,\n resizeLabel,\n sidebarWidth,\n ],\n );\n\n return { sidebarWidth, sidebarResizing, resizeHandleProps };\n}\n","import { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n DOCK_FALLBACK_WIDTH,\n PANEL_HORIZONTAL_MARGIN,\n type Region,\n} from './companion-geometry';\n\nconst FALLBACK_VIEWPORT: Region = { width: 1440, height: 900 };\n\nfunction getViewportSize(): Region {\n if (typeof window === 'undefined') return FALLBACK_VIEWPORT;\n return { width: window.innerWidth, height: window.innerHeight };\n}\n\n/**\n * Owns every DOM measurement used by the companion shell. Callers only need\n * the current viewport, the resolved dock width, and the ref that measures the\n * dock's real content.\n */\nexport function useCompanionMeasurements() {\n const [region, setRegion] = useState<Region>(getViewportSize);\n const [dockContentWidth, setDockContentWidth] = useState<number | null>(null);\n const dockObserverRef = useRef<ResizeObserver | null>(null);\n\n const dockContentRef = useCallback((node: HTMLDivElement | null) => {\n dockObserverRef.current?.disconnect();\n dockObserverRef.current = null;\n if (!node) return;\n\n const observer = new ResizeObserver(() => {\n setDockContentWidth(node.offsetWidth);\n });\n observer.observe(node);\n dockObserverRef.current = observer;\n }, []);\n\n useEffect(() => {\n function handleResize() {\n setRegion(getViewportSize());\n }\n window.addEventListener('resize', handleResize);\n return () => window.removeEventListener('resize', handleResize);\n }, []);\n\n useEffect(\n () => () => {\n dockObserverRef.current?.disconnect();\n dockObserverRef.current = null;\n },\n [],\n );\n\n const dockWidth = Math.min(\n dockContentWidth ?? DOCK_FALLBACK_WIDTH,\n Math.max(0, region.width - PANEL_HORIZONTAL_MARGIN),\n );\n\n return { region, dockWidth, dockContentRef };\n}\n","import type { WidgetCompanionLayoutU, WidgetCtx } from '@opencx/widget-core';\nimport { animate, useMotionValue } from 'framer-motion';\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport { clamp, VIEWPORT_EDGE_PADDING } from './companion-geometry';\nimport { MORPH_SPRING, QUICK_TWEEN } from '../motion';\nimport type { PanelState } from './types';\n\ntype PillOffsetStorage = Pick<\n NonNullable<WidgetCtx['storageCtx']>,\n 'getCompanionPillOffsetX' | 'setCompanionPillOffsetX'\n>;\n\n/**\n * Owns the launcher pill's motion value, persisted resting offset, viewport\n * clamping, and drag/click arbitration.\n */\nexport function usePersistedPillDrag({\n storage,\n state,\n layout,\n viewportWidth,\n currentWidth,\n restingWidth,\n shouldReduceMotion,\n}: {\n storage: PillOffsetStorage | undefined;\n state: PanelState;\n layout: WidgetCompanionLayoutU;\n viewportWidth: number;\n currentWidth: number;\n restingWidth: number;\n shouldReduceMotion: boolean | null;\n}) {\n const [pillOffsetX, setPillOffsetX] = useState(0);\n const dragX = useMotionValue(0);\n const wasDraggingRef = useRef(false);\n\n useEffect(() => {\n let cancelled = false;\n if (!storage) return;\n\n void storage\n .getCompanionPillOffsetX()\n .then((saved) => {\n if (cancelled || saved === null) return;\n // The saved offset is clamped to the CURRENT viewport by the bounds\n // effect below; here it only has to land somewhere sane.\n setPillOffsetX(saved);\n })\n .catch(() => {});\n\n return () => {\n cancelled = true;\n };\n }, [dragX, storage]);\n\n useEffect(() => {\n const settle = shouldReduceMotion ? QUICK_TWEEN : MORPH_SPRING;\n if (state === 'pill') {\n const bound = Math.max(\n 0,\n viewportWidth / 2 - restingWidth / 2 - VIEWPORT_EDGE_PADDING,\n );\n const target = clamp(pillOffsetX, -bound, bound);\n // A narrower viewport or a wider session strip must stay reachable even\n // when animation frames are paused in a background browser tab.\n if (Math.abs(dragX.get()) > bound) dragX.set(target);\n else animate(dragX, target, settle);\n return;\n }\n\n if (state === 'chat' && (layout === 'fullscreen' || layout === 'sidebar')) {\n animate(dragX, 0, settle);\n return;\n }\n\n const maxOffset = Math.max(\n 0,\n viewportWidth / 2 - currentWidth / 2 - VIEWPORT_EDGE_PADDING,\n );\n animate(dragX, clamp(pillOffsetX, -maxOffset, maxOffset), settle);\n }, [\n currentWidth,\n dragX,\n layout,\n pillOffsetX,\n restingWidth,\n shouldReduceMotion,\n state,\n viewportWidth,\n ]);\n\n const restingBound = Math.max(\n 0,\n viewportWidth / 2 - restingWidth / 2 - VIEWPORT_EDGE_PADDING,\n );\n const dragConstraints = useMemo(\n () => ({ left: -restingBound, right: restingBound, top: 0, bottom: 0 }),\n [restingBound],\n );\n\n const onDragStart = useCallback(() => {\n wasDraggingRef.current = true;\n }, []);\n\n const onDragEnd = useCallback(() => {\n const offset = dragX.get();\n setPillOffsetX((previous) => (previous === offset ? previous : offset));\n void storage?.setCompanionPillOffsetX(offset).catch(() => {});\n requestAnimationFrame(() => {\n wasDraggingRef.current = false;\n });\n }, [dragX, storage]);\n\n const shouldIgnoreLaunch = useCallback(() => wasDraggingRef.current, []);\n\n return {\n dragX,\n dragConstraints,\n onDragStart,\n onDragEnd,\n shouldIgnoreLaunch,\n };\n}\n","import type {\n WidgetCompanionLayoutU,\n WidgetSidebarModeU,\n} from '@opencx/widget-core';\nimport type { PanelState } from './types';\n\n/**\n * Whether a click on the host page dismisses the open panel.\n *\n * The DOCKED sidebar is the one layout that coexists with the page — the host\n * is inset beside it and nothing sits underneath — so page clicks belong to\n * the page, and only its × / Escape close it. A FLOATING sidebar overlays the\n * page edge exactly like the compact panel, so it dismisses the same way.\n *\n * Mark mode is the other exemption: while it is armed, host-page interactions\n * ARE the feature (placing/moving marks, the host-rendered note card), and\n * closing the panel would unmount the composer and destroy the draft mark.\n */\nexport function pageClickDismisses({\n state,\n layout,\n sidebarMode,\n isPageMarkModeArmed,\n}: {\n state: PanelState;\n layout: WidgetCompanionLayoutU;\n sidebarMode: WidgetSidebarModeU;\n isPageMarkModeArmed: boolean;\n}): boolean {\n if (state === 'pill' || isPageMarkModeArmed) return false;\n return !(layout === 'sidebar' && sidebarMode === 'docked');\n}\n","import { CompanionQuestions } from './CompanionQuestions';\nimport { motion, useReducedMotion } from 'framer-motion';\nimport React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport {\n useCompanionChats,\n useConfig,\n useMessages,\n useSessions,\n useWidget,\n useWidgetLayout,\n useWidgetTrigger,\n} from '@opencx/widget-react-headless';\nimport type { WidgetCompanionLayoutU } from '@opencx/widget-core';\nimport { buildFrameHtml } from '../components/FrameDocument';\nimport { usePageMarks } from '../page-marks/PageMarksProvider';\nimport { isAgentPointerEvent } from '../page-controls/pointer-sequence';\nimport { useCanHover } from '../hooks/useCanHover';\nimport { useTheme } from '../hooks/useTheme';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { useTriggerLabel } from '../hooks/useTriggerLabel';\nimport { renderCustomTrigger } from '../utils/render-custom-trigger';\nimport { CompanionContent } from './CompanionContent';\nimport { CompanionFrame } from './CompanionFrame';\nimport {\n chatDims,\n compactWidth as resolveCompactWidth,\n DOCK_HEIGHT,\n PILL_SIZE,\n RADII,\n shellAnchor,\n} from './companion-geometry';\nimport { RestingPill } from './RestingPill';\nimport { ChatPicker } from './ChatPicker';\nimport { SessionCircles } from './SessionCircles';\nimport { useChatPicker } from './useChatPicker';\nimport { useCompanionOpenSync } from './useCompanionOpenSync';\nimport {\n CHAT_SHADOW,\n DOCK_SHADOW,\n FADE_TRANSITION,\n QUICK_TWEEN,\n INPUT_SHADOW,\n MORPH_SPRING,\n PILL_SHADOW,\n} from '../motion';\nimport type { PanelState } from './types';\nimport { useCompanionHostEffects } from './useCompanionHostEffects';\nimport { useCompanionMeasurements } from './useCompanionMeasurements';\nimport { useHostPortal } from './useHostPortal';\nimport { usePersistedPillDrag } from './usePersistedPillDrag';\nimport { pageClickDismisses } from './companion-dismissal';\nimport {\n handleCompanionHostKeyDown,\n resolveEscapeAction,\n} from './companion-keyboard';\n\n/** Quick-ask card seed height until the composer measures itself. */\nconst COMPANION_INPUT_FALLBACK_HEIGHT = 96;\n\nconst initialContent = buildFrameHtml({ transparent: true });\n\nexport function WidgetCompanion() {\n const { isOpen, setIsOpen } = useWidgetTrigger();\n const { openChats, activeId } = useCompanionChats();\n const activeChatCount = openChats.length;\n const workingChatCount = openChats.filter((chat) => chat.working).length;\n const { widgetCtx, contentIframeRef } = useWidget();\n const { companion, assets, customComponents, initialQuestions } = useConfig();\n const { theme, cssVars } = useTheme();\n const { t, dir } = useTranslation();\n const { sessionState } = useSessions();\n const { messagesState } = useMessages();\n const { isArmed: isPageMarkModeArmed } = usePageMarks();\n const { region, dockWidth, dockContentRef } = useCompanionMeasurements();\n\n // Seed from isOpen so a layout swap-in (sidebar → fullscreen/compact) mounts\n // straight into the open chat instead of flashing the resting pill for a\n // frame.\n const [state, setState] = useState<PanelState>(isOpen ? 'chat' : 'pill');\n const {\n layout: panelLayout,\n setLayout: setPanelLayout,\n setLayoutPreference: setPanelLayoutPreference,\n allowedLayouts,\n defaultLayout,\n sidebarSide,\n sidebarMode,\n } = useWidgetLayout();\n // The quick-ask card is the real composer, which grows as the user types;\n // its measured height drives the shell card so the two stay in lockstep.\n const [inputHeight, setInputHeight] = useState(\n COMPANION_INPUT_FALLBACK_HEIGHT,\n );\n\n const { sidebarWidth, sidebarResizing, resizeHandleProps } =\n useCompanionHostEffects({\n companion,\n layout: panelLayout,\n state,\n region,\n sidebarSide,\n sidebarMode,\n cssVars,\n storage: widgetCtx.storageCtx,\n resizeLabel: t('companion_resize_chat'),\n });\n\n const shouldReduceMotion = useReducedMotion();\n // One morph for every path: Escape and the × button perform the identical\n // journey, so the panel never feels different depending on how it was\n // dismissed.\n const morphTransition = sidebarResizing\n ? // Drag-resize is a direct manipulation: the shell must track the pointer\n // 1:1, not spring after it. Restored to MORPH_SPRING on pointer-up.\n { duration: 0 }\n : shouldReduceMotion\n ? // Reduced motion: shorter than the spring, never zero — the panel\n // still has to show where it went.\n QUICK_TWEEN\n : MORPH_SPRING;\n const canHover = useCanHover();\n\n const containerRef = useRef<HTMLDivElement>(null);\n // True once the panel has actually reached the chat state this mount. The\n // layout-reset effect keys off it so a swap-in (which starts in 'pill')\n // can't clobber the fullscreen layout the user just switched to.\n const hasBeenChatRef = useRef(false);\n\n const isPill = state === 'pill';\n const showsQuickQuestions =\n state === 'input' &&\n messagesState.messages.length === 0 &&\n initialQuestions?.some((question) => question.trim().length > 0) === true;\n const [questionsHeight, setQuestionsHeight] = useState(0);\n const hasCountAction = activeChatCount > 0;\n const picker = useChatPicker();\n const closePickerRef = useRef(picker.close);\n closePickerRef.current = picker.close;\n useEffect(() => {\n if (!isPill || !hasCountAction) closePickerRef.current(true);\n }, [isPill, hasCountAction]);\n\n // Existing embedder customizations carry over without new config:\n // their popover trigger icon and bottom offset apply to the pill, and a\n // customComponents.widgetTrigger replaces the pill outright (the panel\n // still opens from the same bottom-center baseline via isOpen).\n const customTrigger = customComponents?.widgetTrigger;\n const hasCustomTrigger = !!customTrigger;\n const pillBackground =\n companion?.pillBackground ?? 'hsl(var(--opencx-primary))';\n const companionIcon = companion?.icon ?? assets?.widgetTrigger?.openIcon;\n /** Every state shares one bottom offset: pill → input is pure horizontal\n * growth and the chat panel grows upward from the same baseline — no\n * vertical jump anywhere in the morph. It is the RESOLVED\n * theme.widgetTrigger.offset.bottom (useTheme supplies the default), so\n * embedders who position the popover trigger keep their offset here. */\n const bottomOffset = theme.widgetTrigger.offset.bottom;\n const pillAriaLabel = useTriggerLabel();\n\n // Resting dock: the pill carries a label bar by default — a bare icon\n // has no affordance. `hover` expands on pointer hover only (icon-only on\n // touch, where hover-reveal is unreachable); `never` opts out entirely.\n // Width follows the measured content.\n // With a live conversation, the resting bar and quick-ask invite a\n // continuation instead of a fresh start.\n const hasActiveSession = !!sessionState.session?.id;\n const continueLabel = hasActiveSession\n ? t('follow_up_placeholder')\n : undefined;\n const dockLabel =\n companion?.pillLabel ??\n companion?.placeholder ??\n continueLabel ??\n t('write_a_message_placeholder');\n const dockLabelDisplay = companion?.pillLabelDisplay ?? 'always';\n // Quick-ask composer placeholder: continuing an open conversation reads\n // \"Follow up…\" unless the embedder supplied an explicit placeholder.\n const quickAskPlaceholder =\n companion?.placeholder ?? continueLabel ?? t('write_a_message_placeholder');\n const [pillHovered, setPillHovered] = useState(false);\n const docked =\n isPill &&\n !hasCustomTrigger &&\n dockLabelDisplay !== 'never' &&\n (dockLabelDisplay === 'always' || (canHover && pillHovered));\n\n const compactWidth = resolveCompactWidth(region, companion?.compact);\n const isSidebar = panelLayout === 'sidebar';\n const resolvedChatDims = chatDims({\n layout: panelLayout,\n region,\n sidebarWidth,\n bottomOffset,\n compact: companion?.compact,\n });\n\n // The content iframe keeps a constant chat-sized footprint for BOTH open\n // states — the input bar is just the bottom strip of it, and the shell\n // clips the rest (overflow hidden). Two reasons:\n // 1. Resizing the iframe would reflow text mid-morph (visible squish).\n // 2. Resizing it in the same commit that reveals the chat screen trips a\n // resize→setState loop inside the chat screen (\"Maximum update depth\").\n // In chat state the iframe fills the whole shell in EVERY layout, so the\n // stock header + composer span the full width — fullscreen is just a bigger\n // panel (a full-width block), not a centered reading column.\n const contentWidth = state === 'chat' ? resolvedChatDims.width : compactWidth;\n // The column owns its full height in every layout — the stock chat header\n // (with PanelControls) lives inside it, so no top strip is reserved.\n const contentHeight = resolvedChatDims.height;\n\n // Container anchor, ANIMATED (px) so every layout morphs its position, not\n // just the inner shell's size: compact/fullscreen center horizontally and\n // grow from the bottom baseline; the sidebar pins to its configured edge and\n // spans the full height. Animating left/bottom (vs. a static style) is what\n // lets sidebar↔fullscreen↔compact spring between rects instead of jumping.\n const { centerX: shellCenterX, bottom: shellBottom } = shellAnchor({\n isChatOpen: state === 'chat',\n layout: panelLayout,\n region,\n sidebarWidth,\n sidebarSide,\n bottomOffset,\n });\n\n const currentDims = useMemo(() => {\n if (state === 'pill') {\n if (docked) {\n return {\n width: dockWidth,\n height: DOCK_HEIGHT,\n borderRadius: RADII.pill,\n };\n }\n return { width: PILL_SIZE, height: PILL_SIZE, borderRadius: RADII.pill };\n }\n if (state === 'input') {\n return {\n width: compactWidth,\n height: inputHeight,\n borderRadius: RADII.input,\n };\n }\n return resolvedChatDims;\n }, [state, docked, dockWidth, compactWidth, resolvedChatDims, inputHeight]);\n\n // Grow-to-the-side anchoring for the expand-on-hover pill: the shell is\n // center-anchored (translateX -50%), so a bare width spring would grow the\n // dock symmetrically from the center and drag the icon inward. Shifting the\n // shell by half the width delta pins its inline-start edge instead, so the\n // icon stays put and only the label bar extends out toward the inline-end.\n // Only for the `hover` mode — the `always` bar has no collapsed state to\n // anchor to and stays centered as before.\n const dockGrowX =\n state === 'pill' && docked && dockLabelDisplay === 'hover'\n ? ((dir === 'rtl' ? -1 : 1) * (dockWidth - PILL_SIZE)) / 2\n : 0;\n\n const { dragX, dragConstraints, onDragStart, onDragEnd, shouldIgnoreLaunch } =\n usePersistedPillDrag({\n storage: widgetCtx.storageCtx,\n state,\n layout: panelLayout,\n viewportWidth: region.width,\n currentWidth: currentDims.width,\n restingWidth: docked ? dockWidth : PILL_SIZE,\n shouldReduceMotion,\n });\n\n // State reads that must not go stale in callbacks come straight from the\n // core contexts instead of render-time snapshots.\n const openPanel = useCallback(() => {\n const screen = widgetCtx.routerCtx.state.get().screen;\n const hasSession = !!widgetCtx.sessionCtx.sessionState.get().session?.id;\n // The welcome (data collection) screen needs the full panel; the bare\n // input bar is only for starting/continuing a conversation.\n setState(screen === 'welcome' || hasSession ? 'chat' : 'input');\n }, [widgetCtx]);\n\n const launchFromPill = useCallback(() => {\n if (shouldIgnoreLaunch()) return;\n closePickerRef.current(true);\n if (panelLayout === 'sidebar') {\n setState('chat');\n return;\n }\n openPanel();\n }, [openPanel, panelLayout, shouldIgnoreLaunch]);\n\n const closePanel = useCallback(() => {\n // Staged collapse, one rung per close: fullscreen → configured resting\n // layout → input bar → pill. Jumping from a large panel straight to the icon\n // reads as the widget vanishing; each stage keeps the user oriented\n // and one step from returning.\n if (panelLayout === 'fullscreen' && defaultLayout !== 'fullscreen') {\n setPanelLayout(defaultLayout);\n return;\n }\n // The docked sidebar has no compact intermediate — it collapses straight\n // to the launcher pill (the app-frame un-insets as the shell shrinks).\n if (panelLayout === 'sidebar') {\n setState('pill');\n return;\n }\n setState((prev) => {\n if (\n prev === 'chat' &&\n widgetCtx.sessionCtx.sessionState.get().session?.id\n ) {\n return 'input';\n }\n return 'pill';\n });\n }, [defaultLayout, panelLayout, setPanelLayout, widgetCtx]);\n\n // Escape is a dismissal, not the × button's staged minimize: from\n // fullscreen it drops the MODE (back to the layout the panel came from),\n // and from every other layout it closes the panel outright.\n const dismissPanel = useCallback(() => {\n const action = resolveEscapeAction({\n panelLayout,\n previousLayout: lastNonFullscreenLayoutRef.current,\n defaultLayout,\n allowedLayouts,\n });\n if (action.kind === 'layout') {\n setPanelLayout(action.layout);\n return;\n }\n setState('pill');\n }, [allowedLayouts, defaultLayout, panelLayout, setPanelLayout]);\n\n /** Straight to pill — used only for external (config/imperative) closes */\n const dismiss = useCallback(() => {\n setState('pill');\n }, []);\n\n useEffect(() => {\n if (state === 'chat') hasBeenChatRef.current = true;\n }, [state]);\n\n // Layouts are a chat-panel concept only. Guard on hasBeenChatRef so this\n // only relaxes fullscreen to the valid default when the panel leaves chat,\n // never on a fresh mount. The sidebar is exempt: it's a persistent docked\n // layout, so closing\n // it must keep the layout as 'sidebar' (reopen returns to the sidebar, not\n // a floating card).\n useEffect(() => {\n if (\n state !== 'chat' &&\n hasBeenChatRef.current &&\n panelLayout === 'fullscreen' &&\n defaultLayout !== 'fullscreen'\n ) {\n setPanelLayout(defaultLayout);\n }\n }, [defaultLayout, panelLayout, setPanelLayout, state]);\n\n const isFullscreenModal = state === 'chat' && panelLayout === 'fullscreen';\n\n useCompanionOpenSync({\n panelOpen: state !== 'pill',\n isOpen,\n setIsOpen,\n onOpen: openPanel,\n onClose: dismiss,\n });\n\n // Click-outside closes. Clicks inside the content iframe never reach the\n // host document, so this only fires for genuine host-page clicks.\n // composedPath, not e.target: when the widget mounts inside a shadow\n // root (e.g. the opencx dashboard playground), document-level listeners\n // see e.target retargeted to the shadow HOST — contains() would report\n // every in-panel click as outside and instantly close the panel.\n useEffect(() => {\n if (\n !pageClickDismisses({\n state,\n layout: panelLayout,\n sidebarMode,\n isPageMarkModeArmed,\n })\n )\n return;\n function handleClick(e: MouseEvent) {\n // An approved page action belongs to this conversation. Its synthetic\n // press must not collapse the panel before the result is shown.\n if (isAgentPointerEvent(e)) return;\n const container = containerRef.current;\n if (!container) return;\n if (!e.composedPath().includes(container)) closePanel();\n }\n document.addEventListener('mousedown', handleClick);\n return () => document.removeEventListener('mousedown', handleClick);\n }, [closePanel, state, panelLayout, sidebarMode, isPageMarkModeArmed]);\n\n // The quick-ask composer IS the stock composer — it already dispatched the\n // message into the CURRENT session context (creating the session if needed).\n // So the shell only flips the router SCREEN to chat and morphs the card into\n // the panel. It must NOT call routerCtx.toChatScreen(): that runs resetChat()\n // first, which wipes the just-sent optimistic message and aborts the in-flight\n // createSession/send (surfacing as an unhandled \"Resetting chat\" rejection and\n // dropping the panel to an empty conversation).\n // A message sent while the panel is collapsed opens the conversation —\n // whether it came from the quick-ask composer or from the host page\n // (`WidgetRef.newChat({ message })`). Keyed on the newest USER row so a\n // reply polled in while minimized never pops the panel open.\n const lastUserMessageId =\n messagesState.messages.findLast((m) => m.type === 'USER')?.id ?? null;\n const userMessageIdOnCollapseRef = useRef<string | null>(null);\n useEffect(() => {\n if (state === 'input')\n userMessageIdOnCollapseRef.current = lastUserMessageId;\n // Only the transition INTO the input state records the baseline.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [state]);\n useEffect(() => {\n if (state !== 'input') return;\n if (lastUserMessageId === userMessageIdOnCollapseRef.current) return;\n if (widgetCtx.routerCtx.state.get().screen !== 'chat') {\n widgetCtx.routerCtx.state.setPartial({ screen: 'chat' });\n }\n setState('chat');\n }, [lastUserMessageId, state, widgetCtx]);\n\n // Pop the follow-up bar back up into the open conversation. The input state\n // with an active session is only ever reached by minimizing an open chat, so\n // the router is already on the chat screen; guard the screen flip anyway.\n const handleExpand = useCallback(() => {\n if (\n widgetCtx.routerCtx.state.get().screen !== 'chat' &&\n widgetCtx.sessionCtx.sessionState.get().session?.id\n ) {\n widgetCtx.routerCtx.state.setPartial({ screen: 'chat' });\n }\n setState('chat');\n }, [widgetCtx]);\n\n // The corner layout picker switches between all arrangements. Every target —\n // compact, fullscreen, sidebar — re-renders THIS shell in place, so the panel\n // morphs from the current rect to the next (no component swap).\n const selectLayout = useCallback(\n (target: WidgetCompanionLayoutU) => {\n if (!allowedLayouts.includes(target)) return;\n // Fullscreen is a conversation stage — the sessions list stays in the\n // compact card (it strands badly in a huge column), so leave it first.\n if (\n target === 'fullscreen' &&\n widgetCtx.routerCtx.state.get().screen === 'sessions'\n ) {\n widgetCtx.routerCtx.toChatScreen(\n widgetCtx.sessionCtx.sessionState.get().session?.id,\n );\n }\n // A pick in the menu is the visitor telling us how they want the\n // companion to sit — remember it for the next visit. Every other\n // setPanelLayout in this file is the shell moving them (leaving\n // fullscreen, opening history) and must not overwrite that.\n setPanelLayoutPreference(target);\n },\n [allowedLayouts, widgetCtx, setPanelLayoutPreference],\n );\n\n // The fullscreen shortcut is a TOGGLE, so it remembers where it came from:\n // pressing it in the sidebar goes fullscreen, pressing it again returns to\n // the sidebar (not to compact, which would silently drop the docked layout).\n const firstNonFullscreenLayout = allowedLayouts.find(\n (layout) => layout !== 'fullscreen',\n );\n const lastNonFullscreenLayoutRef = useRef<WidgetCompanionLayoutU>(\n firstNonFullscreenLayout ?? defaultLayout,\n );\n useEffect(() => {\n if (panelLayout !== 'fullscreen' && allowedLayouts.includes(panelLayout)) {\n lastNonFullscreenLayoutRef.current = panelLayout;\n } else if (\n lastNonFullscreenLayoutRef.current === 'fullscreen' ||\n !allowedLayouts.includes(lastNonFullscreenLayoutRef.current)\n ) {\n lastNonFullscreenLayoutRef.current =\n firstNonFullscreenLayout ?? defaultLayout;\n }\n }, [allowedLayouts, defaultLayout, firstNonFullscreenLayout, panelLayout]);\n\n const handleToggleFullscreen = useCallback(() => {\n if (!allowedLayouts.includes('fullscreen')) return;\n if (panelLayout !== 'fullscreen') {\n selectLayout('fullscreen');\n return;\n }\n const previous = lastNonFullscreenLayoutRef.current;\n if (previous !== 'fullscreen' && allowedLayouts.includes(previous)) {\n selectLayout(previous);\n }\n }, [allowedLayouts, panelLayout, selectLayout]);\n\n // Only the modified fullscreen chord belongs on the HOST document. Bare\n // Escape belongs to the host page; CompanionContent handles it inside the\n // widget iframe, where the panel actually owns keyboard focus.\n useEffect(() => {\n function handleGlobalKey(e: KeyboardEvent) {\n handleCompanionHostKeyDown(e, {\n state,\n onToggleFullscreen: handleToggleFullscreen,\n });\n }\n document.addEventListener('keydown', handleGlobalKey);\n return () => document.removeEventListener('keydown', handleGlobalKey);\n }, [handleToggleFullscreen, state]);\n\n // Portal to document.documentElement: <Widget> may render arbitrarily\n // deep in the host app (shadow roots, transformed/stacking-context\n // ancestors — e.g. the opencx dashboard preview, where an app rail\n // otherwise paints OVER the fullscreen modal). Root-level mounting is\n // the same guarantee the embed script provides; see useHostPortal for\n // why it must sit above body.\n const portalTarget = useHostPortal();\n if (!portalTarget) return null;\n\n return createPortal(\n <>\n {/* Embedder-supplied trigger (same contract as popover mode) — it\n replaces the resting pill entirely and drives the panel via\n setIsOpen; the panel still opens from the bottom-center baseline. */}\n {customTrigger && renderCustomTrigger(customTrigger, isOpen, setIsOpen)}\n\n {isPill && picker.anchor && !hasCustomTrigger && (\n <ChatPicker\n placement=\"above\"\n picker={picker}\n portalTarget={portalTarget}\n onSelected={() => setState('chat')}\n />\n )}\n\n {/* Modal scrim — fully transparent; it never tints, darkens or blurs\n the host page. Its only job is to swallow host-page clicks while\n fullscreen is open (they hit the existing outside-mousedown handler\n → staged close). Lives OUTSIDE the container: position:fixed breaks\n inside a transformed ancestor. Always mounted (no pointer events at\n rest) so there's no exit-animation zombie in hidden tabs. */}\n <motion.div\n aria-hidden\n style={{\n position: 'fixed',\n inset: 0,\n background: 'transparent',\n zIndex: theme.widgetContentContainer.zIndex,\n pointerEvents: isFullscreenModal ? 'auto' : 'none',\n }}\n initial={false}\n animate={{ opacity: isFullscreenModal ? 1 : 0 }}\n transition={FADE_TRANSITION}\n />\n\n <motion.div\n ref={containerRef}\n style={{\n ...cssVars,\n position: 'fixed',\n x: dragX,\n translateX: '-50%',\n zIndex: theme.widgetContentContainer.zIndex,\n // With a custom trigger the shell has no resting look of its own\n visibility: hasCustomTrigger && isPill ? 'hidden' : undefined,\n }}\n // Anchor animates with the morph spring: the shell's center-x and\n // bottom spring between the compact/fullscreen center and the sidebar\n // edge, so a layout switch expands FROM the current rect in place.\n initial={false}\n animate={{ left: shellCenterX, bottom: shellBottom }}\n drag={isPill && !hasCustomTrigger && !picker.open ? 'x' : false}\n dragMomentum={false}\n dragElastic={0.15}\n dragConstraints={dragConstraints}\n onDragStart={onDragStart}\n onDragEnd={onDragEnd}\n transition={morphTransition}\n >\n {/* Suggestions have their own frame above the shell. They never\n participate in its measured height, corners, shadow or spring. */}\n {showsQuickQuestions && (\n <div\n data-companion-starters\n style={{\n position: 'absolute',\n bottom: 'calc(100% + 12px)',\n left: '50%',\n transform: 'translateX(-50%)',\n width: contentWidth,\n height: questionsHeight,\n }}\n >\n <CompanionFrame\n title=\"Suggested questions\"\n initialContent={initialContent}\n style={{\n width: '100%',\n height: '100%',\n border: 0,\n background: 'transparent',\n }}\n >\n <CompanionQuestions\n onHeightChange={setQuestionsHeight}\n onDismiss={dismissPanel}\n onToggleFullscreen={handleToggleFullscreen}\n maxHeight={Math.max(\n 48,\n region.height - currentDims.height - bottomOffset - 32,\n )}\n />\n </CompanionFrame>\n </div>\n )}\n {/* Morphing shell — its surface is the background theme token, so\n palette changes recolor companion chrome like any stock screen */}\n <motion.div\n onPointerEnter={\n isPill && !hasCustomTrigger\n ? (event) => {\n setPillHovered(true);\n const count =\n event.currentTarget.querySelector<HTMLButtonElement>(\n '[data-companion-count-trigger]',\n );\n if (count && !shouldIgnoreLaunch()) picker.hover(count);\n }\n : undefined\n }\n onPointerLeave={() => {\n setPillHovered(false);\n picker.leave();\n }}\n style={{\n position: 'relative',\n overflow: 'hidden',\n transformOrigin: 'center bottom',\n cursor:\n isPill && !hasCustomTrigger\n ? docked\n ? 'pointer'\n : 'grab'\n : 'default',\n // Static surface — spring-interpolating a dark→light background\n // reads as a big dark blob mid-morph. The resting look is a\n // separate overlay (RestingPill) that fades its opacity instead.\n background: 'hsl(var(--opencx-background))',\n }}\n // First paint lands directly on the resting pill; no mount morph\n initial={false}\n animate={{\n x: dockGrowX,\n width: currentDims.width,\n height: currentDims.height,\n borderTopLeftRadius: currentDims.borderRadius,\n borderTopRightRadius: currentDims.borderRadius,\n borderBottomLeftRadius: currentDims.borderRadius,\n borderBottomRightRadius: currentDims.borderRadius,\n boxShadow: isPill\n ? docked\n ? DOCK_SHADOW\n : PILL_SHADOW\n : state === 'input'\n ? INPUT_SHADOW\n : CHAT_SHADOW,\n }}\n // Hover: scale only — animating boxShadow repaints a large region\n // on an interaction that fires tens of times a day. The dock gets\n // a whisper (1.01); the icon pill can afford the playful 1.12.\n whileHover={\n isPill && !hasCustomTrigger && canHover && !shouldReduceMotion\n ? { scale: docked ? 1.01 : 1.12 }\n : undefined\n }\n whileTap={\n isPill && !hasCustomTrigger\n ? { scale: docked ? 0.995 : 0.92 }\n : undefined\n }\n transition={morphTransition}\n >\n {isPill && !hasCustomTrigger && (\n <button\n type=\"button\"\n data-companion-launcher=\"\"\n onClick={launchFromPill}\n aria-label={pillAriaLabel}\n aria-expanded={false}\n style={{\n position: 'absolute',\n inset: 0,\n zIndex: 1,\n border: 0,\n padding: 0,\n background: 'transparent',\n cursor: 'pointer',\n borderRadius: 'inherit',\n }}\n />\n )}\n {!hasCustomTrigger && (\n <RestingPill\n visible={isPill}\n docked={docked}\n label={dockLabel}\n sessions={\n activeChatCount > 0 ? (\n <SessionCircles\n interactive={isPill && docked}\n onSelected={() => setState('chat')}\n onLastClosed={() => {\n // The last circle disappears; return keyboard focus to\n // the resting launcher after its button is restored.\n requestAnimationFrame(() => {\n containerRef.current\n ?.querySelector<HTMLElement>(\n '[data-companion-launcher]',\n )\n ?.focus({ preventScroll: true });\n });\n }}\n />\n ) : undefined\n }\n activeCount={activeChatCount}\n countLabel={`${t('companion_chats')} · ${t('companion_active_chats', { count: activeChatCount })}${workingChatCount ? ` · ${t('companion_working_chats', { count: workingChatCount })}` : ''}`}\n pickerOpen={picker.open}\n onOpenChats={(anchor, pointer) => {\n if (!shouldIgnoreLaunch()) picker.toggle(anchor, pointer);\n }}\n working={workingChatCount > 0}\n icon={companionIcon}\n pillBackground={pillBackground}\n dir={dir}\n measureRef={dockContentRef}\n />\n )}\n\n {/* Content iframe — one instance across input↔chat so the iframe\n survives the staged collapse. Deliberately NOT wrapped in\n AnimatePresence: exit animations depend on rAF, which never\n ticks in hidden/background tabs, so an exiting clone of this\n whole tree (iframe + screens) could stay mounted indefinitely\n and fight the live one over shared refs. The shrinking shell\n covers the instant unmount visually. */}\n {state !== 'pill' && (\n <motion.div\n style={{\n position: 'absolute',\n bottom: 0,\n left: '50%',\n translateX: '-50%',\n width: contentWidth,\n height: contentHeight,\n }}\n initial={{ opacity: 0 }}\n animate={{\n opacity: 1,\n transition: {\n ...QUICK_TWEEN,\n // The fade waits for the shell to arrive first; under\n // reduced motion there is nothing to wait for.\n delay: shouldReduceMotion ? 0 : 0.1,\n },\n }}\n >\n <CompanionFrame\n iframeRef={contentIframeRef}\n initialContent={initialContent}\n style={{\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n backgroundColor: 'transparent',\n boxSizing: 'border-box',\n borderWidth: '0px',\n }}\n >\n <CompanionContent\n key={activeId}\n state={state === 'chat' ? 'chat' : 'input'}\n layout={panelLayout}\n shellRadius={currentDims.borderRadius}\n onMinimize={closePanel}\n onDismiss={dismissPanel}\n onToggleFullscreen={handleToggleFullscreen}\n onSelectLayout={selectLayout}\n onExpand={handleExpand}\n canExpand={hasActiveSession}\n placeholder={quickAskPlaceholder}\n hideAttachTools={\n (companion?.quickAskTools ?? 'history-only') ===\n 'history-only'\n }\n onInputHeightChange={setInputHeight}\n />\n </CompanionFrame>\n </motion.div>\n )}\n\n {/* Drag-resize handle — the sidebar's INNER edge, i.e. the one\n facing the page: right edge for a left-docked panel, left edge\n for a right-docked one. Physical (not inset-inline) because the\n panel's side can be pinned independently of the host's dir.\n Host-DOM (not in the iframe) so the pointer capture spans the\n whole drag. */}\n {isSidebar && state === 'chat' && (\n <div\n {...resizeHandleProps}\n style={{\n position: 'absolute',\n top: 0,\n bottom: 0,\n ...(sidebarSide === 'left' ? { right: 0 } : { left: 0 }),\n width: 8,\n cursor: 'ew-resize',\n zIndex: 2,\n }}\n />\n )}\n </motion.div>\n </motion.div>\n </>,\n portalTarget,\n );\n}\n","import { inspectRef } from './control-ref';\nimport { OFF_LIMITS_DETAIL, offLimitsReason } from './off-limits';\n\n/**\n * The check that runs immediately before the widget touches a control —\n * before it draws a mark, and (later) before it clicks.\n *\n * Between the reading that produced a reference and the tool call that uses\n * it, a page can do anything: re-render, scroll, open a modal over the top.\n * So the reference is not trusted as a permission to act; it is looked up,\n * and then the element itself is asked three questions. Each \"no\" is a\n * distinct answer, because the agent has to be able to say which one\n * happened — \"it is behind the dialog that just opened\" is useful, \"it\n * didn't work\" is not.\n */\nexport type GuardOutcome =\n /** The element is there, visible, and the topmost thing at its own centre. */\n | { ok: true; element: HTMLElement }\n /** The reference means nothing here: never minted, expired, or detached. */\n | { ok: false; reason: 'gone' }\n /** Still in the document, but not on screen. */\n | { ok: false; reason: 'hidden' }\n /** On screen, but something else is in front of it. */\n | { ok: false; reason: 'covered' }\n /**\n * The page says hands off — a region marked private, something hidden\n * from assistive tech, a credential field, our own UI. Re-checked HERE\n * and not only when the page was read, because a page can mark a region\n * private after the reference to it was handed out.\n */\n | { ok: false; reason: 'off-limits'; detail: string };\n\n/**\n * Is this element the thing a visitor would actually hit at that spot? The\n * centre point is the honest probe: it is where a person aims, and what a\n * real click would land on. A hit on a descendant (the label inside the\n * button) or an ancestor that fully contains it counts — that is still the\n * control. Anything else means something is in front.\n */\nfunction isTopmost(el: HTMLElement): boolean {\n const rect = el.getBoundingClientRect();\n const x = rect.left + rect.width / 2;\n const y = rect.top + rect.height / 2;\n // Off-screen (scrolled away) is not covered — nothing is in front of it,\n // it is simply elsewhere, and callers scroll it into view before acting.\n const doc = el.ownerDocument;\n const viewportWidth = doc.documentElement.clientWidth || window.innerWidth;\n const viewportHeight = doc.documentElement.clientHeight || window.innerHeight;\n if (x < 0 || y < 0 || x > viewportWidth || y > viewportHeight) return true;\n\n // Without the probe there is no evidence of anything in front, and\n // absence of evidence must not read as \"covered\" — every real browser\n // has it; layout-less test environments do not.\n if (typeof doc.elementFromPoint !== 'function') return true;\n const hit = doc.elementFromPoint(x, y);\n if (!hit) return true;\n return hit === el || el.contains(hit) || hit.contains(el);\n}\n\n/** Look a reference up and ask the element whether it can be touched. */\nexport function guardRef(ref: string): GuardOutcome {\n const reference = inspectRef(ref);\n if (!reference) return { ok: false, reason: 'gone' };\n const { element } = reference;\n\n // Before anything else: is this still something we are allowed to touch?\n const forbidden = offLimitsReason(element);\n if (forbidden) {\n return {\n ok: false,\n reason: 'off-limits',\n detail: OFF_LIMITS_DETAIL[forbidden],\n };\n }\n\n const visible =\n typeof element.checkVisibility === 'function'\n ? element.checkVisibility({\n checkOpacity: true,\n checkVisibilityCSS: true,\n })\n : element.isConnected;\n const rect = element.getBoundingClientRect();\n if (!visible || rect.width === 0 || rect.height === 0) {\n return { ok: false, reason: 'hidden' };\n }\n\n if (!isTopmost(element)) return { ok: false, reason: 'covered' };\n\n if (!reference.isCurrent) return { ok: false, reason: 'gone' };\n\n return { ok: true, element };\n}\n","/**\n * Write a value the way a person would, so the framework notices.\n *\n * `el.value = x` sets the DOM property and nothing else. React tracks the\n * last value it wrote on the node itself and compares against it, so a\n * direct assignment followed by an `input` event looks to React like \"the\n * value is already what I think it is\" and the change is swallowed — the\n * field shows the new text and the app's state still holds the old one.\n * Vue's v-model has the same shape of problem through its own listener.\n *\n * Going through the PROTOTYPE's setter is what a real keystroke does, and\n * it is what makes the tracker see a change. Then the events: `input` for\n * what is being typed, `change` for what was committed.\n */\nexport function setNativeValue(el: HTMLElement, value: string): boolean {\n const prototype =\n el instanceof HTMLInputElement\n ? HTMLInputElement.prototype\n : el instanceof HTMLTextAreaElement\n ? HTMLTextAreaElement.prototype\n : el instanceof HTMLSelectElement\n ? HTMLSelectElement.prototype\n : null;\n if (!prototype) return false;\n\n const setter = Object.getOwnPropertyDescriptor(prototype, 'value')?.set;\n if (!setter) return false;\n setter.call(el, value);\n\n el.dispatchEvent(new Event('input', { bubbles: true }));\n el.dispatchEvent(new Event('change', { bubbles: true }));\n return true;\n}\n","/** Resolve the same unambiguous, enabled option for consent and execution. */\nexport function resolveSelectOption(\n element: HTMLElement,\n value: string | undefined,\n): HTMLOptionElement | null {\n if (!(element instanceof HTMLSelectElement) || value === undefined)\n return null;\n const options = Array.from(element.options);\n // A value and a visible label must not identify two different options.\n const matches = options.filter(\n (option) =>\n option.value === value ||\n option.label.trim().toLowerCase() === value.trim().toLowerCase(),\n );\n const [option] = matches;\n if (\n matches.length !== 1 ||\n !option ||\n option.disabled ||\n (option.parentElement instanceof HTMLOptGroupElement &&\n option.parentElement.disabled) ||\n // Native value assignment cannot distinguish options sharing a value.\n options.filter((candidate) => candidate.value === option.value).length !== 1\n )\n return null;\n return option;\n}\n","import { isWidgetOwned } from '../page-marks/page-element';\nimport { isPageElementPrivate } from '../page-privacy';\nimport { guardRef } from './guard';\nimport { setNativeValue } from './native-setter';\nimport { firePointerSequence } from './pointer-sequence';\nimport { resolveSelectOption } from './select-option';\nimport {\n NEVER_ACT_INPUT_TYPES,\n SETTLE_MS,\n type ActResult,\n type PageAction,\n} from './act-types';\n\n/**\n * Do one thing on the customer's page, wait for the page to settle, and\n * report what actually happened.\n *\n * The read-back is the part that matters. Anyone can fire a click; the\n * reason this returns `no_change` at all is that an agent which cannot tell\n * a click that worked from a click that went nowhere will confidently tell\n * a customer their subscription is cancelled when nothing happened. So\n * after acting we look: did the value take, did the page change, did the\n * control's own state move. If none of that happened, we say so.\n */\n\n/**\n * Watch the page from BEFORE the action until it stops moving, and say\n * whether it moved.\n *\n * The observer is the evidence, and it has to be attached first. Two\n * earlier versions of this were wrong in opposite ways: comparing a cheap\n * fingerprint — url, child count, text length — missed a component-library\n * menu that opened by flipping one attribute, and attaching the observer\n * after the action missed every synchronous click handler, which is most of\n * them. Watch first, then act, then wait for quiet.\n */\nfunction watchPage(\n el: HTMLElement,\n budgetMs: number,\n isCurrent: () => boolean,\n) {\n const doc = el.ownerDocument;\n // A background region that was already loading is not evidence about this\n // action. Keep busy ancestors/descendants and explicitly controlled regions.\n const isRelated = (node: Element) =>\n node.contains(el) ||\n el.contains(node) ||\n (el.getAttribute('aria-controls') ?? '').split(/\\s+/).some((id) => {\n const region = doc.getElementById(id);\n return (\n region !== null && (node.contains(region) || region.contains(node))\n );\n });\n const unrelatedBusy = Array.from(\n doc.querySelectorAll('[aria-busy=\"true\"]'),\n ).filter((node) => !isPageElementPrivate(node) && !isRelated(node));\n const isBackground = (node: Element) => {\n // A handler may connect the target to an existing loading region. Once\n // related, it belongs to this observation even if the relation later clears.\n for (let index = unrelatedBusy.length - 1; index >= 0; index--)\n if (isRelated(unrelatedBusy[index]!)) unrelatedBusy.splice(index, 1);\n return unrelatedBusy.some((region) => region.contains(node));\n };\n let mutated = false;\n let lastMutation = performance.now();\n let timer: ReturnType<typeof setTimeout> | undefined;\n const observer = new MutationObserver((records) => {\n const pageMoved = records.some((record) => {\n const node =\n record.target instanceof Element\n ? record.target\n : record.target.parentElement;\n return node !== null && !isWidgetOwned(node) && !isBackground(node);\n });\n if (pageMoved) {\n mutated = true;\n lastMutation = performance.now();\n }\n });\n observer.observe(doc.documentElement, {\n subtree: true,\n childList: true,\n attributes: true,\n characterData: true,\n });\n const cancel = () => {\n clearTimeout(timer);\n observer.disconnect();\n };\n return {\n settle: () =>\n new Promise<{ mutated: boolean; loading: boolean }>((resolve) => {\n const deadline = performance.now() + budgetMs;\n const check = () => {\n // Permission or turn changes end observation without reading more DOM.\n if (!isCurrent()) {\n cancel();\n resolve({ mutated, loading: false });\n return;\n }\n const loading = Array.from(\n doc.querySelectorAll('[aria-busy=\"true\"]'),\n ).some((node) => !isBackground(node) && !isPageElementPrivate(node));\n const now = performance.now();\n if (now >= deadline || (!loading && now - lastMutation >= 100)) {\n cancel();\n resolve({ mutated, loading });\n } else timer = setTimeout(check, Math.min(100, deadline - now));\n };\n timer = setTimeout(check, Math.min(100, budgetMs));\n }),\n cancel,\n };\n}\n\n/**\n * What `guardRef`'s shared list does not cover. The credential check is\n * duplicated there deliberately — two independent refusals on the one thing\n * that must never happen is cheap.\n */\nfunction refuseReason(el: HTMLElement): string | null {\n if (el.tagName.toLowerCase() === 'input') {\n const type = (el.getAttribute('type') ?? 'text').toLowerCase();\n if (NEVER_ACT_INPUT_TYPES.has(type)) {\n return 'Password and file fields are never filled or clicked by the agent.';\n }\n }\n // A control inside a frame from another origin cannot be read back\n // honestly — we would be reporting on a page we cannot see.\n if (el.ownerDocument !== document) {\n return 'That control is inside another site embedded in this page.';\n }\n return null;\n}\n\nexport async function actOnPage(input: {\n ref: string;\n action: PageAction;\n value?: string;\n settleMs?: number;\n consentIsCurrent?: () => boolean;\n observationIsCurrent?: () => boolean;\n}): Promise<ActResult> {\n try {\n return await act(input);\n } catch {\n // A turn is waiting on this. An exception must come back as an answer —\n // an unanswered call is silence, and silence is the one thing an agent\n // must never be left to fill in for itself.\n return {\n outcome: 'unsupported',\n // Host code can throw private URLs, field values or account details.\n // Page replies are sent to the agent; never forward exception contents.\n detail: 'That could not be done on this page.',\n };\n }\n}\n\nasync function act({\n ref,\n action,\n value,\n settleMs = SETTLE_MS,\n consentIsCurrent = () => true,\n observationIsCurrent = () => true,\n}: {\n ref: string;\n action: PageAction;\n value?: string;\n settleMs?: number;\n consentIsCurrent?: () => boolean;\n observationIsCurrent?: () => boolean;\n}): Promise<ActResult> {\n if (!consentIsCurrent()) return { outcome: 'declined' };\n const guarded = guardRef(ref);\n if (!guarded.ok) {\n // \"Hands off\" is a refusal, not a failure to find something.\n return guarded.reason === 'off-limits'\n ? { outcome: 'unsupported', detail: guarded.detail }\n : { outcome: guarded.reason };\n }\n\n const el = guarded.element;\n const refused = refuseReason(el);\n if (refused) return { outcome: 'unsupported', detail: refused };\n\n const doc = el.ownerDocument;\n const urlBefore = doc.location.href;\n // Started immediately before the page is touched and never before a\n // validation that might bail out — so nothing is watched that never acts,\n // and nothing acts that is not being watched.\n let watcher: ReturnType<typeof watchPage> | undefined;\n let selectedValue: string | undefined;\n let interrupted = false;\n\n try {\n switch (action) {\n case 'click': {\n watcher = watchPage(el, settleMs, observationIsCurrent);\n const sequence = firePointerSequence(el, consentIsCurrent);\n if (sequence === 'not-started') {\n watcher.cancel();\n return { outcome: 'declined' };\n }\n interrupted = sequence === 'interrupted';\n break;\n }\n case 'fill': {\n if (value === undefined) {\n return {\n outcome: 'unsupported',\n detail: 'No value was given to type.',\n };\n }\n watcher = watchPage(el, settleMs, observationIsCurrent);\n el.focus?.();\n if (!consentIsCurrent()) {\n // Focus/blur handlers may already have saved a value on the host.\n interrupted = true;\n break;\n }\n if (!setNativeValue(el, value)) {\n watcher.cancel();\n return {\n outcome: 'unsupported',\n detail: 'That control is not something text can be typed into.',\n };\n }\n break;\n }\n case 'select': {\n if (!(el instanceof HTMLSelectElement)) {\n return {\n outcome: 'unsupported',\n detail: 'That control is not a dropdown.',\n };\n }\n if (value === undefined) {\n return {\n outcome: 'unsupported',\n detail: 'No option was given to choose.',\n };\n }\n const option = resolveSelectOption(el, value);\n if (!option) {\n return {\n outcome: 'no_change',\n detail:\n 'That option is not in the list or cannot be selected unambiguously.',\n };\n }\n watcher = watchPage(el, settleMs, observationIsCurrent);\n selectedValue = option.value;\n setNativeValue(el, option.value);\n break;\n }\n case 'check':\n case 'uncheck': {\n const wanted = action === 'check';\n const box =\n el instanceof HTMLInputElement &&\n (el.type === 'checkbox' || el.type === 'radio')\n ? el\n : null;\n const ariaState = el.getAttribute('aria-checked');\n if (!box && ariaState === null) {\n return {\n outcome: 'unsupported',\n detail: 'That control is not a checkbox or switch.',\n };\n }\n const already = box ? box.checked : ariaState === 'true';\n if (already === wanted) {\n return {\n outcome: 'no_change',\n detail: `It is already ${wanted ? 'on' : 'off'}.`,\n };\n }\n watcher = watchPage(el, settleMs, observationIsCurrent);\n const sequence = firePointerSequence(el, consentIsCurrent);\n if (sequence === 'not-started') {\n watcher.cancel();\n return { outcome: 'declined' };\n }\n interrupted = sequence === 'interrupted';\n break;\n }\n }\n\n const { mutated, loading } = (await watcher?.settle()) ?? {\n mutated: false,\n loading: false,\n };\n if (interrupted) {\n return {\n outcome: 'no_change',\n detail:\n (mutated || doc.location.href !== urlBefore\n ? 'The page changed. '\n : '') +\n 'The requested action was interrupted after input events were dispatched. Its final result is unknown. Do not repeat it automatically.',\n };\n }\n const pendingDetail = loading\n ? 'The page is still loading. The action was dispatched; its final result is unknown. Do not repeat it automatically.'\n : undefined;\n\n // Did it take? Ask the page, not the code that just ran.\n if (action === 'fill' || action === 'select') {\n const current =\n el instanceof HTMLInputElement ||\n el instanceof HTMLTextAreaElement ||\n el instanceof HTMLSelectElement\n ? el.value\n : null;\n if (action === 'fill' && current !== value) {\n return {\n outcome: 'no_change',\n detail: 'The field did not keep what was typed.',\n };\n }\n if (action === 'select' && current !== selectedValue) {\n return {\n outcome: 'no_change',\n detail: 'The dropdown did not keep the selected option.',\n };\n }\n return {\n outcome: 'done',\n ...(pendingDetail ? { detail: pendingDetail } : {}),\n };\n }\n\n if (action === 'check' || action === 'uncheck') {\n const wanted = action === 'check';\n const box =\n el instanceof HTMLInputElement &&\n (el.type === 'checkbox' || el.type === 'radio')\n ? el\n : null;\n const now = box\n ? box.checked\n : el.getAttribute('aria-checked') === 'true';\n return now === wanted\n ? {\n outcome: 'done',\n ...(pendingDetail ? { detail: pendingDetail } : {}),\n }\n : { outcome: 'no_change', detail: 'It did not change.' };\n }\n\n // A click's only honest evidence is that the page moved: a mutation\n // anywhere outside our own overlays, or a navigation.\n return mutated || doc.location.href !== urlBefore\n ? { outcome: 'done', ...(pendingDetail ? { detail: pendingDetail } : {}) }\n : {\n outcome: 'no_change',\n detail:\n pendingDetail ??\n 'The control was clicked and nothing on the page changed during observation. Its final result is unknown. Do not repeat it automatically.',\n };\n } finally {\n watcher?.cancel();\n }\n}\n","/**\n * The pointer the visitor watches.\n *\n * Without it the page simply changes: a menu opens, a field fills, and the\n * customer is left to work out whether they did that or something did it to\n * them. A cursor that travels to the control and presses it answers that\n * before they have to ask.\n *\n * It is drawn, never simulated input — the real events still come from\n * `firePointerSequence`. The two are kept in step by aiming both at the same\n * point: the control's centre. If the gesture and the event were allowed to\n * drift apart this would be theatre, and theatre about what an agent did to\n * someone's account is worse than no animation at all.\n *\n * Widget-owned and `pointer-events: none` throughout. It lives inside a\n * fixed, clipped, full-viewport layer so travelling near an edge cannot\n * grow the host page's scroll area, and it never touches a customer\n * element or intercepts a click.\n */\n\nconst TRAVEL_EASE = 'cubic-bezier(0.32, 0.72, 0, 1)';\n\nexport const CURSOR_APPEAR_MS = 260;\n/** The long haul. A hand crossing a dashboard takes about this. */\nexport const CURSOR_TRAVEL_MS = 1600;\n/** A hand stops before it presses; without this the two moves read as one jerk. */\nexport const CURSOR_REST_MS = 180;\nexport const CURSOR_PRESS_MS = 240;\n\n/**\n * How far the path bows out of the straight line, as a fraction of the\n * distance travelled. A hand swings; a tween slides. Zero here is the thing\n * that made the first version read as a sprite on a rail.\n */\nconst ARC = 0.13;\n\n/**\n * Minimum-jerk position profile — the one motor control actually produces:\n * still, accelerate, decelerate, still, with no discontinuity at either\n * end. A cubic-bezier on a straight line cannot make this shape.\n */\nconst minimumJerk = (t: number) => t * t * t * (10 - 15 * t + 6 * t * t);\n\n/** One point along a quadratic curve. */\nfunction onCurve(\n from: { x: number; y: number },\n control: { x: number; y: number },\n to: { x: number; y: number },\n t: number,\n): { x: number; y: number } {\n const inv = 1 - t;\n return {\n x: inv * inv * from.x + 2 * inv * t * control.x + t * t * to.x,\n y: inv * inv * from.y + 2 * inv * t * control.y + t * t * to.y,\n };\n}\n\n/**\n * The keyframes for one reach: a bowed path sampled on a minimum-jerk\n * clock, landing on the target and stopping.\n *\n * An earlier version aimed past the target and corrected back, copying the\n * corrective sub-movement people make. On a real reach across a dashboard\n * that is twenty-odd pixels of travelling backwards, and it reads as a\n * bounce — as something going wrong — rather than as a hand. The real\n * version is a few pixels over a few tens of milliseconds, which at this\n * scale is invisible, so it buys nothing and costs the arrival.\n */\nfunction reachFrames(\n from: { x: number; y: number },\n to: { x: number; y: number },\n steps = 48,\n): { transform: string }[] {\n const dx = to.x - from.x;\n const dy = to.y - from.y;\n const distance = Math.hypot(dx, dy) || 1;\n\n // Bow perpendicular to the line of travel, and always the same way round\n // relative to it, so repeated reaches look like one hand rather than a\n // random walk.\n const control = {\n x: from.x + dx / 2 - (dy / distance) * distance * ARC,\n y: from.y + dy / 2 + (dx / distance) * distance * ARC,\n };\n const frames: { transform: string }[] = [];\n for (let i = 0; i <= steps; i += 1) {\n const point = onCurve(from, control, to, minimumJerk(i / steps));\n frames.push({\n transform: `translate(${point.x - HOTSPOT_X}px, ${point.y - HOTSPOT_Y}px)`,\n });\n }\n return frames;\n}\n\n/** The tip, in the glyph's own 14×14 box. Everything aims from here. */\nconst HOTSPOT_X = 2;\nconst HOTSPOT_Y = 1.7;\n\nconst GLYPH = 'M2 1.7 L9.6 8 L6.5 8.4 L7.7 11 L6.3 11.6 L5.1 9 L2.6 10.6 Z';\n\nfunction prefersReducedMotion(): boolean {\n return (\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches\n );\n}\n\nconst wait = (ms: number) =>\n new Promise<void>((resolve) => {\n window.setTimeout(resolve, prefersReducedMotion() ? 0 : ms);\n });\n\ntype Cursor = {\n /** Travel to a viewport point and stop there. */\n moveTo(x: number, y: number): Promise<void>;\n /** The squash and ring that read as a press. */\n press(): Promise<void>;\n /** Fade out and release the node. */\n release(): void;\n};\n\n/**\n * The hand, for as long as it is working.\n *\n * It is deliberately NOT one cursor per action. A flow is several steps —\n * click through, read the new screen, click again — and a pointer that\n * faded out and back in between each one would read as several different\n * things happening rather than one continuous piece of work. It arrives\n * once, stays where it last was, walks to the next control from there, and\n * leaves when the work stops.\n */\nlet active: Cursor | null = null;\n\n/** Pending \"the work seems to have stopped\" release. */\nlet idleTimer: ReturnType<typeof setTimeout> | undefined;\n\n/**\n * How long the pointer waits between steps before deciding the flow is\n * over. Long enough to cover a model thinking between two tool calls,\n * short enough that it is not left sitting on a page nobody is acting on.\n */\nconst CURSOR_IDLE_MS = 4000;\n\n/**\n * Take the pointer off the page NOW.\n *\n * `release` fades, which is right at the end of the work and wrong when\n * something else is starting: the fade outlives the call, so effects in\n * quick succession left ghosts drifting behind the live one. Anything still\n * carrying the marker is removed outright here.\n */\nexport function dismissAgentCursor(): void {\n clearTimeout(idleTimer);\n active?.release();\n active = null;\n document\n .querySelectorAll('[data-opencx-cursor]')\n .forEach((stale) => stale.remove());\n}\n\n/** The flow is still going: hold the pointer where it is. */\nfunction keepAlive(): void {\n clearTimeout(idleTimer);\n idleTimer = setTimeout(dismissAgentCursor, CURSOR_IDLE_MS);\n}\n\n/**\n * Put a pointer on the page, or hand back the one already there.\n *\n * Returns null when the document will not have it — the caller then does\n * its own thing silently, because a missing animation must never stop the\n * actual work.\n */\nexport function showAgentCursor(from?: {\n x: number;\n y: number;\n}): Cursor | null {\n // Already working: the same hand continues from wherever it stopped.\n if (active) {\n keepAlive();\n return active;\n }\n try {\n dismissAgentCursor();\n\n /**\n * A clipping layer, and it is not cosmetic.\n *\n * A fixed-position node on `<html>` still counts towards the document's\n * scrollable area. The reach bows off the straight line, so partway to\n * a control near an edge the cursor goes past the viewport, the host\n * page grows a scrollbar, and everything on it shifts sideways —\n * exactly when the customer is being asked to watch one specific\n * control. `overflow: hidden` on a full-viewport layer means the\n * pointer can travel anywhere without the page knowing it exists.\n */\n const layer = document.createElement('div');\n layer.setAttribute('data-opencx-overlay', '');\n // Its own marker as well as the shared one: the ink and the pointer are\n // both widget overlays, and anything reasoning about \"is the mark still\n // up\" needs to tell them apart.\n layer.setAttribute('data-opencx-cursor', '');\n layer.setAttribute('aria-hidden', 'true');\n Object.assign(layer.style, {\n position: 'fixed',\n inset: '0',\n overflow: 'hidden',\n pointerEvents: 'none',\n zIndex: '2147483646',\n contain: 'strict',\n } satisfies Partial<CSSStyleDeclaration>);\n\n const host = document.createElement('div');\n // The pointer itself, distinct from the layer that clips it.\n host.setAttribute('data-opencx-cursor-tip', '');\n Object.assign(host.style, {\n position: 'absolute',\n left: '0',\n top: '0',\n width: '14px',\n height: '14px',\n pointerEvents: 'none',\n opacity: '0',\n transition: `opacity ${CURSOR_APPEAR_MS}ms ease`,\n willChange: 'transform',\n } satisfies Partial<CSSStyleDeclaration>);\n layer.appendChild(host);\n\n // The rounding is a same-colour stroke with round joins under the fill,\n // not a radius on every vertex: one number to tune, and the silhouette\n // stays a cursor instead of drifting into a blob.\n host.innerHTML = `<svg viewBox=\"0 0 14 14\" width=\"14\" height=\"14\" style=\"display:block\">\n <path d=\"${GLYPH}\" fill=\"currentColor\" stroke=\"currentColor\" stroke-width=\"1.7\"\n stroke-linejoin=\"round\" stroke-linecap=\"round\" paint-order=\"stroke\"\n style=\"transition: transform ${CURSOR_PRESS_MS}ms ${TRAVEL_EASE}; transform-origin: ${HOTSPOT_X}px ${HOTSPOT_Y}px\"/>\n </svg>`;\n\n const start = from ?? {\n x: window.innerWidth - 40,\n y: window.innerHeight - 40,\n };\n // Where the tip currently is. Each reach is sampled from here, so a\n // second one continues the hand's movement instead of restarting it.\n let at = start;\n host.style.transform = `translate(${start.x - HOTSPOT_X}px, ${start.y - HOTSPOT_Y}px)`;\n document.documentElement.appendChild(layer);\n\n const glyph = host.querySelector('path');\n // Read back once so the browser has the start position before the first\n // transition, or the cursor teleports instead of travelling.\n void host.offsetWidth;\n host.style.opacity = '1';\n\n let gone = false;\n const cursor: Cursor = {\n async moveTo(x, y) {\n if (gone) return;\n const land = `translate(${x - HOTSPOT_X}px, ${y - HOTSPOT_Y}px)`;\n\n if (prefersReducedMotion() || typeof host.animate !== 'function') {\n host.style.transform = land;\n return;\n }\n\n // The reach: bowed, minimum-jerk, landing on the target. `linear`\n // on purpose — the whole shape of the motion lives in the sampling,\n // and an easing on top would flatten it back out.\n host.style.transition = `opacity ${CURSOR_APPEAR_MS}ms ease`;\n const frames = reachFrames(at, { x, y });\n // The last frame IS the target, so the animation's held value and\n // the inline style agree and there is nothing left to correct.\n const reach = host.animate(frames, {\n duration: CURSOR_TRAVEL_MS,\n easing: 'linear',\n fill: 'forwards',\n });\n await reach.finished.catch(() => undefined);\n if (gone) return;\n\n host.style.transform = land;\n at = { x, y };\n await wait(CURSOR_REST_MS);\n },\n async press() {\n if (gone || !glyph) return;\n glyph.style.transform = 'scale(0.86)';\n await wait(CURSOR_PRESS_MS);\n glyph.style.transform = '';\n },\n release() {\n if (gone) return;\n gone = true;\n host.style.opacity = '0';\n window.setTimeout(() => layer.remove(), CURSOR_APPEAR_MS + 60);\n },\n };\n\n active = cursor;\n keepAlive();\n return cursor;\n } catch {\n // Decoration. A document that will not take it is not an error.\n return null;\n }\n}\n\n/** The point both the gesture and the real event aim at. */\nexport function centreOf(el: HTMLElement): { x: number; y: number } {\n const rect = el.getBoundingClientRect();\n return { x: rect.left + rect.width / 2, y: rect.top + rect.height / 2 };\n}\n\n/**\n * Bring the control into view and walk the pointer to it.\n *\n * Every failure here is swallowed on purpose. The caller owes the waiting\n * turn an answer, and an animation that cannot run is not a reason to\n * withhold one — the work still happens, it just happens unaccompanied.\n */\nexport async function travelTo(\n el: HTMLElement,\n { press = false }: { press?: boolean } = {},\n): Promise<{ done: () => void }> {\n const cursor = showAgentCursor();\n if (!cursor) return { done: () => {} };\n try {\n el.scrollIntoView?.({\n behavior: prefersReducedMotion() ? 'auto' : 'smooth',\n block: 'center',\n inline: 'nearest',\n });\n const { x, y } = centreOf(el);\n await cursor.moveTo(x, y);\n if (press) await cursor.press();\n } catch {\n // Decoration only.\n }\n // The STEP is done, not the hand. It stays where it is and starts the\n // idle clock; another step within that window picks it up from here.\n return { done: keepAlive };\n}\n","import { z } from 'zod';\nimport { PAGE_ACTIONS } from './act-types';\n\n/**\n * What the agent is allowed to ask for. `ref` is the only way to name a\n * control — there is no selector and no text — and the action set is closed,\n * so an invented verb is refused rather than interpreted.\n */\nexport const actOnPageInputSchema = z.object({\n ref: z.string().min(1),\n action: z.enum(PAGE_ACTIONS),\n /** What to type or which option to choose. Never a password. */\n value: z.string().max(500).optional(),\n});\n","import { useCallback, useEffect, useRef } from 'react';\n\n/** A delayed DOM effect must still belong to this mounted, active turn. */\nexport function usePageEffectIsCurrent(\n effects: readonly { key: string }[],\n isStreaming: boolean,\n) {\n const latest = useRef({ effects, isStreaming });\n latest.current = { effects, isStreaming };\n const mounted = useRef(false);\n useEffect(() => {\n mounted.current = true;\n return () => {\n mounted.current = false;\n };\n }, []);\n return useCallback(\n (key: string) =>\n mounted.current &&\n latest.current.isStreaming &&\n latest.current.effects.some((effect) => effect.key === key),\n [],\n );\n}\n","import { log } from '@opencx/widget-core';\nimport { useAgentChatUi, useWidget } from '@opencx/widget-react-headless';\nimport { useEffect, useRef } from 'react';\nimport { actOnPage } from '../../../page-controls/act';\nimport { travelTo } from '../../../page-controls/cursor';\nimport { actOnPageInputSchema } from '../../../page-controls/act-input';\nimport { accessibleName } from '../../../page-controls/accessible-name';\nimport { captureActionMeaning } from '../../../page-controls/action-meaning';\nimport { resolveRef } from '../../../page-controls/control-ref';\nimport { readPageControls } from '../../../page-controls/read-controls';\nimport { resolveSelectOption } from '../../../page-controls/select-option';\nimport { usePageEffectIsCurrent } from './use-page-effect-is-current';\n\nconst MAX_HANDLED_ACTIONS = 200;\n\n/**\n * The agent's hands on the host page.\n *\n * Three things happen here and nowhere else: the visitor is asked before\n * every action, the action is performed against the element the\n * reference resolves to, and the turn is told what actually happened.\n *\n * Every path answers the waiting call exactly once. A refusal, a decline, a\n * click that changed nothing — all of them are answers, because the one\n * thing the agent must never do is fill a silence with a success.\n */\nexport function AgentChatPageActions() {\n const { widgetCtx } = useWidget();\n const {\n pageEffects,\n replyToPageCall,\n requestPageActionConsent,\n isStreaming,\n } = useAgentChatUi();\n const handledRef = useRef(new Set<string>());\n const isCurrent = usePageEffectIsCurrent(pageEffects, isStreaming);\n\n useEffect(() => {\n const handled = handledRef.current;\n for (const effect of pageEffects) {\n if (effect.type !== 'act-on-page' || handled.has(effect.key)) continue;\n handled.add(effect.key);\n while (handled.size > MAX_HANDLED_ACTIONS) {\n const oldest = handled.values().next().value;\n if (oldest === undefined) break;\n handled.delete(oldest);\n }\n\n const parsed = actOnPageInputSchema.safeParse(effect.input);\n if (!parsed.success) {\n log.warn('act_on_page: invalid tool input', {\n issues: parsed.error.issues,\n });\n replyToPageCall(effect.callId, 'unsupported');\n continue;\n }\n const { ref, action, value } = parsed.data;\n\n void (async () => {\n let cursor: Awaited<ReturnType<typeof travelTo>> | undefined;\n try {\n const enabled = () =>\n isCurrent(effect.key) &&\n widgetCtx.features.pageContext &&\n widgetCtx.features.clientTools &&\n widgetCtx.features.pageActions;\n if (!enabled()) {\n replyToPageCall(effect.callId, 'declined');\n return;\n }\n const element = resolveRef(ref);\n if (!element) {\n replyToPageCall(\n effect.callId,\n 'gone',\n undefined,\n enabled() ? readPageControls() : undefined,\n );\n return;\n }\n\n // Any control can commit through host JavaScript, including fields\n // that auto-save. Labels and form markup cannot establish safety.\n // Name the actual page control and show the proposed value.\n const consentName = accessibleName(element) || 'this control';\n const option =\n action === 'select' ? resolveSelectOption(element, value) : null;\n if (action === 'select' && !option) {\n replyToPageCall(\n effect.callId,\n 'no_change',\n 'That option is unavailable or ambiguous.',\n );\n return;\n }\n const optionValue = option?.value;\n const optionLabel = option?.label.trim();\n const hasSameMeaning = captureActionMeaning(element);\n const consentIsCurrent = () =>\n enabled() &&\n resolveRef(ref) === element &&\n hasSameMeaning() &&\n consentName === (accessibleName(element) || 'this control') &&\n (!option ||\n (resolveSelectOption(element, value) === option &&\n option.value === optionValue &&\n option.label.trim() === optionLabel));\n const allowed = await requestPageActionConsent({\n callId: effect.callId,\n action,\n controlName: consentName,\n ...(action === 'fill' || action === 'select' ? { value } : {}),\n ...(option ? { valueLabel: optionLabel || '(empty option)' } : {}),\n });\n if (!allowed) {\n replyToPageCall(effect.callId, 'declined');\n return;\n }\n\n if (!consentIsCurrent()) {\n replyToPageCall(effect.callId, 'declined');\n return;\n }\n\n // The pointer goes first, and the press lands before the event\n // does. Firing the click while the cursor is still travelling is\n // the one thing that makes this read as fake: the page would move\n // before the hand got there.\n cursor = await travelTo(element, { press: true });\n\n if (!consentIsCurrent()) {\n replyToPageCall(effect.callId, 'declined');\n return;\n }\n const result = await actOnPage({\n ref,\n action,\n value,\n consentIsCurrent,\n observationIsCurrent: enabled,\n });\n\n // Read the page again and send it back with the outcome. An action\n // often lands the visitor somewhere else, and an agent holding\n // references to the screen it just left can only ask them to send\n // another message — which is not a flow.\n const after =\n enabled() &&\n result.outcome !== 'declined' &&\n result.outcome !== 'unsupported'\n ? readPageControls()\n : null;\n replyToPageCall(\n effect.callId,\n result.outcome,\n result.detail,\n after\n ? { controls: after.controls, truncated: after.truncated }\n : undefined,\n );\n } catch {\n replyToPageCall(\n effect.callId,\n 'unsupported',\n 'The page action could not be completed.',\n );\n } finally {\n cursor?.done();\n }\n })();\n }\n }, [\n pageEffects,\n replyToPageCall,\n requestPageActionConsent,\n widgetCtx,\n isCurrent,\n ]);\n\n return null;\n}\n","import { annotate, type AnnotationType } from '@shardsui/notation';\nimport { z } from 'zod';\nimport { adoptNotationInk } from './page-mark';\nimport { log } from '@opencx/widget-core';\n\n/**\n * The AI's browser-effect tool: the backend defines `highlight_element` with an\n * instant server-side ack, and the widget — watching the turn's streamed tool\n * parts — performs the actual highlight on the host page (see\n * `AgentChatPageEffects`).\n *\n * The highlight itself is hand-drawn ink (`@shardsui/notation`): a mark thrown\n * around the element in the widget's theme color, plus an optional pointing\n * callout. Because the ink is an SVG sibling of the target — absolutely\n * positioned, `pointer-events: none`, laid out in PAGE coordinates — it scrolls\n * with the element for free, never traps a click, and never shifts the host\n * page's layout. That deletes the old spotlight's whole failure surface (the\n * four dim panels re-tiled around the element every frame, each re-enabling\n * pointer events). The one trade: an `overflow: hidden` ancestor can clip the\n * mark's padding — acceptable, since the element is scrolled into view first\n * and the ink hugs it closely.\n *\n * Dismisses on click, Esc, or after a few seconds — by UN-drawing itself (the\n * strokes reverse-play), which reads as the hand lifting off the page.\n */\n/**\n * Mark styles the model may request — a deliberate subset of notation's types.\n * `highlight` is excluded because it is the one type that mutates the target's\n * own `position`/`z-index` (never touch a customer's element); the deletion\n * marks (`strike-through`, `crossed-off`) read as \"this is wrong/removed\", the\n * opposite of pointing something out.\n */\nconst HIGHLIGHT_MARK_TYPES = [\n 'circle',\n 'box',\n 'underline',\n 'bracket',\n 'arrow',\n] as const;\n\nexport const highlightElementInputSchema = z.object({\n /**\n * The control to point at, as a reference the widget itself handed out\n * with the customer's message. There is no selector and no text to match:\n * the agent can only ever name something the page reader offered it, and\n * a reference that no longer resolves is a no-op, never a mark thrown\n * around whatever has since moved into that place.\n */\n ref: z.string().min(1),\n label: z.string().optional(),\n /**\n * Optional mark style. `.catch(undefined)` so a model-invented type degrades\n * to the size heuristic instead of failing the whole highlight.\n */\n type: z.enum(HIGHLIGHT_MARK_TYPES).optional().catch(undefined),\n});\n\ntype HighlightElementInput = z.infer<typeof highlightElementInputSchema>;\n\n/** How long a highlight stays before un-drawing itself (`pageMarkHighlightDurationMs`). */\nexport const DEFAULT_HIGHLIGHT_DURATION_MS = 8000;\n\n/**\n * When the model doesn't ask for a mark style, choose like a person with a pen\n * would: underline prose-shaped inlines (links, terms), circle small controls\n * (buttons, icons, menu items), box anything bigger — a circle inflates its\n * box and would swallow the neighbours of a large region.\n */\nfunction autoMarkType(\n rect: DOMRect,\n style: CSSStyleDeclaration,\n fontSize: number,\n): AnnotationType {\n if (style.display === 'inline' && rect.height <= fontSize * 2.5) {\n return 'underline';\n }\n if (rect.width <= 220 && rect.height <= 80) return 'circle';\n return 'box';\n}\n\n/**\n * One highlight at a time: a new call un-draws the one still showing, so\n * consecutive tool calls read as the hand moving from mark to mark instead of\n * ink piling up.\n */\nlet activeDismiss: (() => void) | null = null;\n\n/** Programmatically clear the current highlight (also used by tests). */\nexport function dismissActiveHighlight() {\n activeDismiss?.();\n}\n\n/**\n * Ink a mark on an element of the host page: scroll it into view, hand-draw\n * the mark on it (the ink is glued to the element, so it rides along with the\n * smooth scroll), and float an optional pointing callout. The page stays fully\n * interactive throughout — nothing is dimmed and no click is trapped.\n *\n * Takes the element, not a way of finding one: WHICH element is the caller's\n * decision (`guardRef` — the reference the reader handed out, checked to be\n * the same node, on screen and not covered). The pen only draws. Returns\n * false when the ink could not be laid down at all.\n */\nexport function highlightElementOnHostPage(\n el: HTMLElement,\n input: Omit<HighlightElementInput, 'ref'>,\n {\n accentColor = 'hsl(0 0% 9%)',\n surfaceColor = 'hsl(0 0% 9%)',\n foregroundColor = 'hsl(0 0% 98%)',\n zIndex = 10_000_002,\n durationMs = DEFAULT_HIGHLIGHT_DURATION_MS,\n seed,\n }: {\n accentColor?: string;\n surfaceColor?: string;\n foregroundColor?: string;\n zIndex?: number;\n durationMs?: number | undefined;\n seed?: number;\n } = {},\n): boolean {\n // Notation hangs its ink beside the target, so a detached element has\n // nowhere to draw. The caller already guarded the reference; this is the\n // last instant before the ink, and a mark drawn nowhere must report\n // itself as a miss rather than as a mark.\n if (!el.isConnected) return false;\n\n // The hand moves on: release the previous mark before throwing this one.\n activeDismiss?.();\n\n const prefersReducedMotion =\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n // For reduced-motion users the page-level smooth scroll is the single most\n // motion-sick part of the whole effect — jump-cut instead. (The ink's own\n // draw is already forced instant internally by notation.)\n el.scrollIntoView({\n behavior: prefersReducedMotion ? 'auto' : 'smooth',\n block: 'center',\n inline: 'nearest',\n });\n\n const rect = el.getBoundingClientRect();\n const style = getComputedStyle(el);\n const fontSize = parseFloat(style.fontSize) || 16;\n const small = rect.width < 160 && rect.height < 56;\n\n const marker = annotate(el, {\n type: input.type ?? autoMarkType(rect, style, fontSize),\n color: accentColor,\n // ~0.1em of the target's type size, clamped to stay a pen not a brush.\n strokeWidth: Math.min(3, Math.max(1.6, fontSize * 0.11)),\n // Calmer hand over small, dense UI; a fuller sway on big regions.\n wobble: small ? 0.6 : 0.9,\n // Pen travels with the target's reading direction.\n rtl: style.direction === 'rtl',\n seed,\n });\n\n let dismissed = false;\n const draw = () => {\n if (dismissed) return;\n try {\n marker.show();\n adoptNotationInk(el, zIndex);\n } catch (err) {\n // The mark is decoration — a draw failure must never break the chat.\n log.warn('highlight_element: mark could not be drawn', err);\n }\n };\n // Draw after webfonts settle (a swap reflows text under already-placed ink);\n // where FontFaceSet is missing (jsdom, old webviews) draw immediately.\n const fonts = document.fonts as FontFaceSet | undefined;\n if (fonts?.ready && typeof fonts.ready.then === 'function') {\n void fonts.ready.then(draw);\n } else {\n draw();\n }\n\n // Widget-owned overlay for the callout. Created even without a label so the\n // effect has one consistent, cleanable DOM footprint.\n const container = document.createElement('div');\n container.setAttribute('data-opencx-overlay', '');\n container.style.pointerEvents = 'none';\n\n // Dark pill + arrow, fixed-position and glued to the element's live rect by\n // a per-frame tracker (survives smooth scroll and layout shifts). Revealed\n // once the scroll has visibly begun settling.\n let callout: HTMLDivElement | null = null;\n let arrow: HTMLDivElement | null = null;\n if (input.label) {\n callout = document.createElement('div');\n callout.setAttribute('data-cx-role', 'callout');\n Object.assign(callout.style, {\n position: 'fixed',\n zIndex: String(zIndex + 1),\n background: surfaceColor,\n color: foregroundColor,\n font: '500 13px/1.4 system-ui, sans-serif',\n padding: '9px 13px',\n borderRadius: '11px',\n maxWidth: '240px',\n boxShadow: `0 10px 30px -8px color-mix(in srgb, ${foregroundColor} 35%, transparent)`,\n opacity: '0',\n transform: prefersReducedMotion ? 'none' : 'translateY(4px)',\n transition:\n 'opacity 280ms cubic-bezier(0.23, 1, 0.32, 1), transform 280ms cubic-bezier(0.23, 1, 0.32, 1)',\n pointerEvents: 'none',\n } satisfies Partial<CSSStyleDeclaration>);\n callout.textContent = input.label;\n arrow = document.createElement('div');\n Object.assign(arrow.style, {\n position: 'absolute',\n width: '10px',\n height: '10px',\n background: surfaceColor,\n transform: 'rotate(45deg)',\n } satisfies Partial<CSSStyleDeclaration>);\n callout.appendChild(arrow);\n container.appendChild(callout);\n }\n\n document.documentElement.appendChild(container);\n\n // Track the element only for the callout — the ink follows it natively.\n let rafId = 0;\n if (callout && arrow) {\n const pill = callout;\n const tip = arrow;\n const track = () => {\n const r = el.getBoundingClientRect();\n const vw = window.innerWidth;\n const side = r.top > 90 ? 'top' : 'bottom';\n const cw = Math.min(240, pill.offsetWidth || 240);\n const left = Math.max(\n 12,\n Math.min(r.left + r.width / 2 - cw / 2, vw - cw - 12),\n );\n pill.style.left = `${left}px`;\n pill.style.width = `${cw}px`;\n pill.style.top =\n side === 'top'\n ? `${r.top - pill.offsetHeight - 12}px`\n : `${r.bottom + 12}px`;\n // Arrow tracks the element's centre, clamped inside the pill.\n tip.style.left = `${Math.max(10, Math.min(r.left + r.width / 2 - left - 5, cw - 20))}px`;\n if (side === 'top') {\n tip.style.bottom = '-4px';\n tip.style.top = '';\n } else {\n tip.style.top = '-4px';\n tip.style.bottom = '';\n }\n rafId = requestAnimationFrame(track);\n };\n track();\n }\n\n const calloutTimer = callout\n ? window.setTimeout(() => {\n if (!callout) return;\n callout.style.opacity = '1';\n callout.style.transform = 'translateY(0)';\n }, 350)\n : 0;\n\n const dismiss = () => {\n if (dismissed) return;\n dismissed = true;\n if (activeDismiss === dismiss) activeDismiss = null;\n cancelAnimationFrame(rafId);\n window.clearTimeout(timeoutId);\n window.clearTimeout(calloutTimer);\n document.removeEventListener('click', onInteract, true);\n document.removeEventListener('keydown', onKeyDown, true);\n if (callout) {\n callout.style.opacity = '0';\n callout.style.transform = prefersReducedMotion\n ? 'none'\n : 'translateY(4px)';\n }\n // The hand lifts off: strokes reverse-play, then everything is released.\n try {\n marker.hide();\n void marker.finished.then(() => marker.remove());\n } catch {\n marker.remove();\n }\n window.setTimeout(() => container.remove(), 300);\n };\n\n const onInteract = () => dismiss();\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') dismiss();\n };\n const timeoutId = window.setTimeout(dismiss, Math.max(0, durationMs));\n document.addEventListener('click', onInteract, true);\n document.addEventListener('keydown', onKeyDown, true);\n activeDismiss = dismiss;\n\n return true;\n}\n","import { log } from '@opencx/widget-core';\nimport {\n useAgentChatUi,\n useConfig,\n useWidget,\n} from '@opencx/widget-react-headless';\nimport { useEffect, useRef } from 'react';\nimport { useTheme } from '../../../hooks/useTheme';\nimport {\n dismissActiveHighlight,\n highlightElementInputSchema,\n highlightElementOnHostPage,\n} from '../../../page-marks/agent-mark';\nimport { dismissAgentCursor, travelTo } from '../../../page-controls/cursor';\nimport { guardRef } from '../../../page-controls/guard';\nimport { resolvePageMarkTheme } from '../../../page-marks/page-mark-theme';\nimport { usePageEffectIsCurrent } from './use-page-effect-is-current';\n\nconst MAX_HANDLED_PAGE_EFFECTS = 200;\n\n/**\n * Styled host-page adapter for effects emitted by the headless agent engine.\n * Headless owns turn/lifecycle state and the client-tools gate\n * (`WidgetCtx.features.clientTools`, which needs the embed's page-marks\n * opt-in); this bridge alone owns DOM lookup, widget theme colors, layering,\n * and the hand-drawn page-mark implementation.\n */\nexport function AgentChatPageEffects() {\n const { pageMarkHighlightDurationMs } = useConfig();\n const { pageEffects, replyToPageCall, isStreaming } = useAgentChatUi();\n const { widgetCtx } = useWidget();\n const isCurrent = usePageEffectIsCurrent(pageEffects, isStreaming);\n const { theme, cssVars } = useTheme();\n const pageMarkTheme = resolvePageMarkTheme({\n cssVars,\n primaryColor: theme.primaryColor,\n contentZIndex: theme.widgetContentContainer.zIndex,\n });\n const handledEffectKeysRef = useRef(new Set<string>());\n\n // The ink lives in the HOST document: an unmounting widget takes it along.\n useEffect(\n () => () => {\n dismissActiveHighlight();\n dismissAgentCursor();\n },\n [],\n );\n\n // The hand stays through a whole flow, so something has to tell it the\n // flow is over. The turn settling is that something — the idle timer is\n // only the backstop for a turn that never settles cleanly.\n useEffect(() => {\n if (isStreaming) return;\n dismissAgentCursor();\n }, [isStreaming]);\n\n useEffect(() => {\n const handled = handledEffectKeysRef.current;\n for (const effect of pageEffects) {\n if (effect.type !== 'highlight-element' || handled.has(effect.key)) {\n continue;\n }\n handled.add(effect.key);\n while (handled.size > MAX_HANDLED_PAGE_EFFECTS) {\n const oldest = handled.values().next().value;\n if (oldest === undefined) break;\n handled.delete(oldest);\n }\n\n const enabled = () =>\n isCurrent(effect.key) &&\n widgetCtx.features.pageContext &&\n widgetCtx.features.clientTools;\n if (!enabled()) {\n replyToPageCall(effect.callId, 'declined');\n continue;\n }\n\n const parsed = highlightElementInputSchema.safeParse(effect.input);\n if (!parsed.success) {\n log.warn('highlight_element: invalid tool input', {\n issues: parsed.error.issues,\n });\n replyToPageCall(effect.callId, 'unsupported');\n continue;\n }\n // The reference is looked up and the element re-checked here, in the\n // instant before the ink goes down: still the same node, still on\n // screen, still not behind something. A page can re-render between the\n // reading that minted the ref and this tool call arriving.\n const guarded = guardRef(parsed.data.ref);\n if (!guarded.ok) {\n log.warn('highlight_element: not drawn', {\n ref: parsed.data.ref,\n reason: guarded.reason,\n });\n // The turn is waiting: say WHICH no it was, so the agent can tell\n // the customer to close the dialog rather than \"it didn't work\".\n if (guarded.reason === 'off-limits') {\n replyToPageCall(effect.callId, 'unsupported', guarded.detail);\n } else {\n replyToPageCall(effect.callId, guarded.reason);\n }\n continue;\n }\n // The pointer travels there first, so the mark has a hand behind it\n // instead of appearing out of nowhere. The travel overlaps the turn's\n // own wait, and a document that will not take the cursor simply gets\n // the ink straight away.\n const element = guarded.element;\n const callId = effect.callId;\n const input = parsed.data;\n void (async () => {\n let cursor: Awaited<ReturnType<typeof travelTo>> | undefined;\n try {\n cursor = await travelTo(element);\n if (!enabled()) {\n replyToPageCall(callId, 'declined');\n return;\n }\n const current = guardRef(input.ref);\n if (!current.ok) {\n replyToPageCall(\n callId,\n current.reason === 'off-limits' ? 'unsupported' : current.reason,\n );\n return;\n }\n const found = highlightElementOnHostPage(element, input, {\n accentColor: pageMarkTheme.accent,\n surfaceColor: pageMarkTheme.surface,\n foregroundColor: pageMarkTheme.foreground,\n zIndex: pageMarkTheme.inkZIndex,\n durationMs: pageMarkHighlightDurationMs,\n });\n replyToPageCall(callId, found ? 'done' : 'gone');\n if (!found) {\n log.warn('highlight_element: the mark could not be drawn', input);\n }\n } catch {\n replyToPageCall(\n callId,\n 'unsupported',\n 'The page highlight could not be completed.',\n );\n } finally {\n cursor?.done();\n }\n })();\n }\n }, [\n pageEffects,\n replyToPageCall,\n pageMarkHighlightDurationMs,\n pageMarkTheme.accent,\n pageMarkTheme.surface,\n pageMarkTheme.foreground,\n pageMarkTheme.inkZIndex,\n isCurrent,\n widgetCtx,\n ]);\n\n return null;\n}\n","/**\n * Reasoning arrives as markdown, but the trace's one-line labels (the\n * collapsed breadcrumb, the vanishing current-step name, the row's truncated\n * preview) are plain text nodes — a single ellipsized line has nowhere to put\n * a heading or a list, so `**Clarifying profile check**` would render with its\n * asterisks showing. Flatten the inline syntax to the words it decorates and\n * drop the block markers.\n *\n * This is deliberately NOT a markdown parser: it runs on every stream delta\n * for a label that is about to be cut at 40 characters anyway. The expanded\n * body renders through `RichText`, which is where real markdown belongs.\n */\n\n/** Emphasis, strong, strikethrough and inline code around a non-blank run. */\nconst INLINE_MARKS = /(\\*\\*\\*|\\*\\*|\\*|~~|`+)(?=\\S)([\\s\\S]*?\\S)\\1/g;\n\n/** Underscores get their own pass because, unlike `*`, they do NOT open\n * emphasis inside a word — `get_ai_profile` and `snake_case` are identifiers,\n * not markup, and CommonMark agrees. Both delimiters need a word boundary. */\nconst INLINE_UNDERSCORES = /(^|[^\\w`])(___|__|_)(?=\\S)([\\s\\S]*?\\S)\\2(?!\\w)/g;\n\n/** `**bold with *nested* emphasis**` needs one pass per nesting level. Three\n * is past anything a model writes; the cap keeps this O(1) on pathological\n * input rather than looping on it. */\nconst MAX_UNWRAP_PASSES = 3;\n\nexport function stripInlineMarkdown(text: string): string {\n let out = text\n // Fenced-code fences, then the heading / quote / list markers that only\n // ever lead a line.\n .replace(/^\\s{0,3}(?:```+|~~~+)\\S*\\s*/, '')\n .replace(/^\\s{0,3}(?:#{1,6}\\s+|>\\s?|[-*+]\\s+|\\d+[.)]\\s+)/, '')\n // Images before links, so `![alt](src)` keeps the alt and not a stray `!`.\n .replace(/!\\[([^\\]]*)\\]\\([^)]*\\)/g, '$1')\n .replace(/\\[([^\\]]*)\\]\\([^)]*\\)/g, '$1');\n\n for (let pass = 0; pass < MAX_UNWRAP_PASSES; pass++) {\n const next = out\n .replace(INLINE_MARKS, '$2')\n .replace(INLINE_UNDERSCORES, '$1$3');\n if (next === out) break;\n out = next;\n }\n\n return out.trim();\n}\n","import { resolveClientPresentation } from '@opencx/widget-core';\nimport {\n useConfig,\n useWidget,\n type StreamingStep,\n} from '@opencx/widget-react-headless';\nimport { ChevronDownIcon, ChevronRightIcon } from 'lucide-react';\nimport React, { useEffect, useRef, useState } from 'react';\nimport { dc } from '../utils/data-component';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { stripInlineMarkdown } from '../utils/strip-inline-markdown';\nimport { RichText } from './RichText';\nimport { BrailleSpinner } from './lib/BrailleSpinner';\nimport { cn } from './lib/utils/cn';\n\n/**\n * The agent's steps trace: pixel-mosaic loaders on running steps, a braille\n * snake on live reasoning, shimmering labels, a crossfading current-step name\n * while collapsed, a breadcrumb once done, fade-up row entrances, and\n * auto-collapse when the stream ends. Shared by the LIVE streamed turn and\n * settled turns rebuilt from persisted `ui_parts`, so the transcript looks\n * identical during and after a turn. The animation classes live in\n * `index.css`.\n */\n\n/** 3x3 pixel mosaic loader — random cells light up each tick. */\nfunction PixelLoader({ className }: { className?: string }) {\n const [active, setActive] = useState<Set<number>>(() => new Set());\n\n useEffect(() => {\n const indices = Array.from({ length: 9 }, (_, i) => i);\n const id = setInterval(() => {\n const count = 2 + Math.floor(Math.random() * 3);\n const shuffled = [...indices]\n .sort(() => Math.random() - 0.5)\n .slice(0, count);\n setActive(new Set(shuffled));\n }, 110);\n return () => clearInterval(id);\n }, []);\n\n return (\n <div\n className={cn('inline-grid shrink-0 grid-cols-3', className)}\n style={{ gap: 1, width: 14, height: 14 }}\n >\n {Array.from({ length: 9 }, (_, i) => (\n <div\n key={i}\n className=\"rounded-[1px]\"\n style={{\n width: 4,\n height: 4,\n background: active.has(i)\n ? 'hsl(var(--opencx-foreground))'\n : 'hsl(var(--opencx-border))',\n transition: 'background 66ms ease',\n }}\n />\n ))}\n </div>\n );\n}\n\n/** Crossfades the latest step label while the chain is collapsed + running. */\nfunction VanishingLabel({\n labels,\n active,\n}: {\n labels: string[];\n active: boolean;\n}) {\n const labelsRef = useRef(labels);\n labelsRef.current = labels;\n const [current, setCurrent] = useState(() => labels[labels.length - 1] ?? '');\n const [phase, setPhase] = useState<'in' | 'out'>('in');\n const prevLengthRef = useRef(labels.length);\n\n useEffect(() => {\n const len = labelsRef.current.length;\n if (!active || len <= prevLengthRef.current) {\n prevLengthRef.current = len;\n return;\n }\n prevLengthRef.current = len;\n const latest = labelsRef.current[len - 1] ?? '';\n setPhase('out');\n const tid = setTimeout(() => {\n setCurrent(latest);\n setPhase('in');\n }, 180);\n return () => clearTimeout(tid);\n }, [active, labels.length]);\n\n return (\n <span\n className={cn(\n 'truncate text-[12px] text-muted-foreground/60',\n active &&\n (phase === 'in' ? 'opencx-placeholder-in' : 'opencx-placeholder-out'),\n )}\n >\n {current}\n </span>\n );\n}\n\n/** Reasoning is markdown, so every one-line label is flattened before it is\n * cut — a truncated line cannot render `**bold**`, it can only show the\n * asterisks. The expanded body renders the markdown for real. */\nfunction stepLabel(step: StreamingStep, thinkingLabel: string): string {\n if (step.kind === 'tool') return formatToolLabel(step.label);\n const line = step.label.split('\\n').find((l) => l.trim());\n if (!line) return thinkingLabel;\n const plain = stripInlineMarkdown(line);\n if (!plain) return thinkingLabel;\n return plain.length > 40 ? `${plain.slice(0, 40)}...` : plain;\n}\n\nfunction buildBreadcrumb(\n steps: StreamingStep[],\n thinkingLabel: string,\n maxItems = 3,\n): string {\n const labels = steps\n .filter((step) => step.kind === 'tool')\n .map((step) => formatToolLabel(step.label));\n if (labels.length === 0) {\n const firstThought = steps.find((step) => step.kind === 'reasoning');\n return firstThought\n ? stepLabel(firstThought, thinkingLabel)\n : thinkingLabel;\n }\n if (labels.length <= maxItems) return labels.join(' → ');\n return `${labels.slice(0, maxItems).join(' → ')} → ...`;\n}\n\n/**\n * Typography for the expanded reasoning. `prose` carries its own gray palette\n * and its own margins, both wrong here: the trace is muted-foreground at 13px\n * inside a 160px scroll box, so the palette is repointed at the widget's theme\n * vars (which follow the embedder's colors) and the block rhythm is tightened\n * to something that fits. Edge margins go last — a leading `mt` on the first\n * paragraph reads as a broken gap under the row it belongs to.\n */\nconst THOUGHT_PROSE = [\n 'prose prose-sm max-w-none',\n '[--tw-prose-body:hsl(var(--opencx-muted-foreground))]',\n '[--tw-prose-headings:hsl(var(--opencx-foreground))]',\n '[--tw-prose-bold:hsl(var(--opencx-foreground))]',\n '[--tw-prose-code:hsl(var(--opencx-foreground))]',\n '[--tw-prose-links:hsl(var(--opencx-primary))]',\n '[--tw-prose-bullets:hsl(var(--opencx-muted-foreground))]',\n '[--tw-prose-counters:hsl(var(--opencx-muted-foreground))]',\n '[--tw-prose-quotes:hsl(var(--opencx-muted-foreground))]',\n '[--tw-prose-quote-borders:hsl(var(--opencx-border))]',\n '[--tw-prose-hr:hsl(var(--opencx-border))]',\n '[--tw-prose-pre-bg:hsl(var(--opencx-muted))]',\n '[--tw-prose-pre-code:hsl(var(--opencx-foreground))]',\n 'prose-p:my-1 prose-headings:my-1.5 prose-headings:text-[13px]',\n 'prose-ul:my-1 prose-ol:my-1 prose-li:my-0.5',\n 'prose-pre:my-1.5 prose-pre:p-2 prose-pre:text-[11px] prose-hr:my-2',\n '[&>*:first-child]:mt-0 [&>*:last-child]:mb-0',\n].join(' ');\n\nfunction ThoughtRow({\n step,\n isLive,\n thinkingLabel,\n}: {\n step: StreamingStep;\n isLive: boolean;\n thinkingLabel: string;\n}) {\n const [open, setOpen] = useState(false);\n const label = stepLabel(step, thinkingLabel);\n // Compare against the FLATTENED reasoning: a single-line `**foo**` collapses\n // to the same `foo` the label shows, and offering a disclosure that reveals\n // nothing new (beyond the asterisks) is worse than no disclosure.\n const isTruncated = label !== stripInlineMarkdown(step.label);\n\n const displayLabel = isLive\n ? (() => {\n const lines = step.label.split('\\n').filter((l) => l.trim());\n const last = stripInlineMarkdown(lines[lines.length - 1] ?? '');\n if (!last) return thinkingLabel;\n return last.length > 80 ? `${last.slice(0, 80)}...` : last;\n })()\n : label;\n\n return (\n <div className=\"min-w-0\">\n <div\n className={cn(\n 'flex min-w-0 items-center gap-2.5 py-[3px]',\n isTruncated && 'cursor-pointer',\n )}\n onClick={() => isTruncated && setOpen((v) => !v)}\n >\n <div className=\"relative z-10 flex size-[18px] shrink-0 items-center justify-center rounded-full bg-background\">\n {isLive ? (\n <BrailleSpinner className=\"text-[14px] leading-none text-primary/70\" />\n ) : (\n <span className=\"text-[14px] leading-none text-muted-foreground/40\">\n ⠿\n </span>\n )}\n </div>\n <span\n className={cn(\n 'min-w-0 truncate text-[13px] italic text-muted-foreground/60',\n isLive && 'opencx-text-shimmer',\n )}\n >\n {displayLabel}\n </span>\n {isTruncated && (\n <ChevronRightIcon\n className={cn(\n 'size-2.5 shrink-0 text-muted-foreground/40 transition-transform duration-200',\n open && 'rotate-90',\n )}\n />\n )}\n </div>\n {isTruncated && open && (\n <div className=\"opencx-fade-up ms-[30px]\">\n <div\n className={cn(\n 'max-h-[160px] overflow-y-auto py-1.5 text-[13px] leading-relaxed [overflow-wrap:anywhere]',\n THOUGHT_PROSE,\n )}\n >\n <RichText>{step.label}</RichText>\n </div>\n </div>\n )}\n </div>\n );\n}\n\n/** Longest tool payload rendered, in characters. Debug view, not a data dump:\n * a 200KB tool result belongs in the logs, not in a chat bubble. */\nconst TOOL_IO_MAX_CHARS = 4000;\n\n/** Pretty-print a tool payload for reading, capped. Strings pass through as\n * themselves — JSON-quoting a plain string helps nobody. */\nfunction formatToolPayload(value: unknown): string {\n const text =\n typeof value === 'string' ? value : (safeStringify(value) ?? String(value));\n return text.length > TOOL_IO_MAX_CHARS\n ? `${text.slice(0, TOOL_IO_MAX_CHARS)}…`\n : text;\n}\n\nfunction safeStringify(value: unknown): string | null {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n // Circular / non-serializable payloads must not take the trace down.\n return null;\n }\n}\n\nfunction ToolPayload({ label, value }: { label: string; value: unknown }) {\n return (\n <div className=\"pt-1.5\">\n <div className=\"text-[11px] font-medium uppercase tracking-wide text-muted-foreground/50\">\n {label}\n </div>\n <pre className=\"mt-0.5 max-h-[200px] overflow-auto whitespace-pre-wrap [overflow-wrap:anywhere] rounded-lg bg-muted/40 p-2 font-mono text-[11px] leading-relaxed text-muted-foreground\">\n {formatToolPayload(value)}\n </pre>\n </div>\n );\n}\n\n/**\n * One tool call in the trace. When full details are allowed, the row is a\n * disclosure: it opens onto the call's arguments and its result, which is what\n * you actually need when an agent's answer is wrong and the label (\"Search\n * knowledge base\") tells you nothing about what it searched for. Off — the\n * default, and what customers see — it stays exactly the label row it was.\n */\nfunction ToolRow({ step, showIO }: { step: StreamingStep; showIO: boolean }) {\n const { t } = useTranslation();\n const [open, setOpen] = useState(false);\n const hasIO =\n showIO && (step.input !== undefined || step.output !== undefined);\n\n return (\n <div className=\"min-w-0\">\n <div\n className={cn(\n 'flex min-w-0 items-center gap-2.5 py-[3px]',\n hasIO && 'cursor-pointer',\n )}\n onClick={() => hasIO && setOpen((v) => !v)}\n >\n <div className=\"relative z-10 flex size-[18px] shrink-0 items-center justify-center rounded-full bg-background\">\n {step.done ? (\n <div className=\"size-1.5 rounded-full bg-muted-foreground/30\" />\n ) : (\n <PixelLoader />\n )}\n </div>\n <span\n className={cn(\n 'min-w-0 truncate text-[13px] text-muted-foreground/70',\n !step.done && 'opencx-text-shimmer',\n )}\n >\n {formatToolLabel(step.label)}\n </span>\n {hasIO && (\n <ChevronRightIcon\n className={cn(\n 'size-2.5 shrink-0 text-muted-foreground/40 transition-transform duration-200',\n open && 'rotate-90',\n )}\n />\n )}\n </div>\n {hasIO && open && (\n <div className=\"opencx-fade-up ms-[30px] pb-1\">\n {step.input !== undefined && (\n <ToolPayload label={t('step_arguments')} value={step.input} />\n )}\n {step.output !== undefined && (\n <ToolPayload label={t('step_result')} value={step.output} />\n )}\n </div>\n )}\n </div>\n );\n}\n\n/** What a registered `agent_chat_steps` component receives. */\nexport type StreamingStepsComponentProps = {\n steps: StreamingStep[];\n /** The turn is still streaming; false settles every step as done. */\n active: boolean;\n};\n\nexport function StepsGroup({\n steps: turnSteps,\n active,\n}: StreamingStepsComponentProps) {\n const { t } = useTranslation();\n const { showStepToolIO, presentation } = useConfig();\n const { widgetCtx } = useWidget();\n const activity = resolveClientPresentation(\n widgetCtx.agent.presentation,\n presentation,\n )?.toolActivity;\n const showToolDetails =\n showStepToolIO !== false &&\n (activity === 'details' ||\n (activity === undefined && showStepToolIO === true));\n const thinkingLabel = t('thinking');\n // Once the turn is over nothing is running: a turn that ended with a step\n // unfinished — a stopped turn leaves its last tool call at\n // `input-available` — would otherwise shimmer \"running...\" forever.\n const steps = active\n ? turnSteps\n : turnSteps.map((step) => (step.done ? step : { ...step, done: true }));\n const isStreaming = steps.some((step) => !step.done);\n // Open while the TURN is live, collapsed once it ends. Keyed on the turn,\n // not on the steps: between two tool calls every step is briefly done while\n // the model decides the next one, and collapsing there made the trace\n // fold and unfold on every step. A visitor's own toggle wins until the\n // turn ends.\n const [isOpen, setIsOpen] = useState(active);\n const wasActiveRef = useRef(active);\n useEffect(() => {\n if (wasActiveRef.current && !active) setIsOpen(false);\n else if (!wasActiveRef.current && active) setIsOpen(true);\n wasActiveRef.current = active;\n }, [active]);\n\n if (steps.length === 0) return null;\n\n return (\n <div\n {...dc('chat/streaming_turn/steps')}\n className=\"w-full min-w-0 overflow-hidden\"\n >\n <button\n type=\"button\"\n className=\"flex min-w-0 max-w-full items-center gap-1.5 py-0.5 text-[12px] text-muted-foreground/60 transition-colors duration-150 hover:text-muted-foreground\"\n onClick={() => setIsOpen((v) => !v)}\n >\n {isOpen ? (\n <>\n <ChevronDownIcon className=\"size-2.5 shrink-0\" />\n <span className=\"text-[11px] font-medium tabular-nums\">\n {steps.length}\n </span>\n <span\n className={cn(\n 'text-muted-foreground/40',\n isStreaming && 'opencx-text-shimmer',\n )}\n >\n {isStreaming ? t('running') : t('steps')}\n </span>\n </>\n ) : isStreaming ? (\n <>\n <PixelLoader className=\"opacity-70\" />\n <span className=\"text-[11px] font-medium tabular-nums\">\n {steps.length}\n </span>\n <VanishingLabel\n labels={steps.map((step) => stepLabel(step, thinkingLabel))}\n active={isStreaming}\n />\n </>\n ) : (\n <>\n <ChevronRightIcon className=\"size-2.5 shrink-0\" />\n <span className=\"min-w-0 flex-1 truncate text-start text-[12px] text-muted-foreground/50\">\n {buildBreadcrumb(steps, thinkingLabel)}\n </span>\n </>\n )}\n </button>\n\n {isOpen && (\n <div className=\"relative pt-1\">\n {steps.length > 1 && (\n <div className=\"absolute bottom-3 start-2 top-3 border-s border-dashed border-muted-foreground/20\" />\n )}\n {steps.map((step, index) => (\n <div\n key={index}\n className=\"opencx-fade-up\"\n style={{ animationDelay: `${index * 40}ms` }}\n >\n {step.kind === 'reasoning' ? (\n <ThoughtRow\n step={step}\n isLive={isStreaming && index === steps.length - 1}\n thinkingLabel={thinkingLabel}\n />\n ) : (\n <ToolRow step={step} showIO={showToolDetails} />\n )}\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n\n/** `list_training_scenarios` → \"List training scenarios\". */\nfunction formatToolLabel(toolName: string): string {\n const customerFacingName = toolName.replace(/^mcp_[a-f0-9]{16}__/, '');\n const words = customerFacingName.replaceAll(/[_-]+/g, ' ').trim();\n return words.charAt(0).toUpperCase() + words.slice(1);\n}\n","import {\n formatAskQuestionsAnswers,\n useMessages,\n useWidget,\n type AskQuestionsRequest,\n} from '@opencx/widget-react-headless';\nimport { ChevronLeftIcon, ChevronRightIcon, SparklesIcon } from 'lucide-react';\nimport React, { useCallback, useMemo, useState } from 'react';\nimport { useTranslation } from '../hooks/useTranslation';\nimport { buildPageClientContext } from '../page-controls/send-context';\nimport { dc } from '../utils/data-component';\nimport { cn } from './lib/utils/cn';\n\n/**\n * The `ask_questions` clarification card.\n *\n * The agent asking a question is not activity to trace — it is a message\n * addressed to the customer. So this call never renders in the steps group;\n * the stream mapper lifts it out and this card shows the QUESTION, one at a\n * time, with the offered options as chips and an always-available \"type it\n * yourself\" escape. Answers are submitted as ONE ordinary user message, which\n * is what the agent reads as the tool's result.\n */\nexport type ClarificationQuestionsProps = {\n request: AskQuestionsRequest;\n};\n\ntype Question = AskQuestionsRequest['questions'][number];\n\n/** The answer text for one question, or `undefined` while unanswered. */\nfunction answerFor(params: {\n question: Question;\n manual: boolean;\n manualText: string;\n singleId: string | undefined;\n multiIds: ReadonlySet<string>;\n}): string | undefined {\n if (params.manual) {\n const typed = params.manualText.trim();\n return typed.length > 0 ? typed : undefined;\n }\n if (params.question.selection === 'single') {\n if (!params.singleId) return undefined;\n return params.question.options.find((o) => o.id === params.singleId)?.label;\n }\n const labels = Array.from(params.multiIds)\n .map((id) => params.question.options.find((o) => o.id === id)?.label)\n .filter(\n (label): label is string => typeof label === 'string' && label.length > 0,\n );\n return labels.length > 0 ? labels.join(', ') : undefined;\n}\n\nexport function ClarificationQuestions({\n request,\n}: ClarificationQuestionsProps) {\n const { t } = useTranslation();\n const { sendMessage } = useMessages();\n const { widgetCtx } = useWidget();\n const questions = request.questions;\n\n const [index, setIndex] = useState(0);\n const [submitted, setSubmitted] = useState(false);\n const [manual, setManual] = useState<Record<string, boolean>>({});\n const [manualText, setManualText] = useState<Record<string, string>>({});\n const [singleSel, setSingleSel] = useState<\n Record<string, string | undefined>\n >({});\n const [multiSel, setMultiSel] = useState<Record<string, Set<string>>>({});\n\n const question = questions[index];\n const total = questions.length;\n\n const isAnswered = useCallback(\n (candidate: Question) =>\n answerFor({\n question: candidate,\n manual: Boolean(manual[candidate.id]),\n manualText: manualText[candidate.id] ?? '',\n singleId: singleSel[candidate.id],\n multiIds: multiSel[candidate.id] ?? new Set<string>(),\n }) !== undefined,\n [manual, manualText, multiSel, singleSel],\n );\n\n const currentAnswered = question ? isAnswered(question) : false;\n const allAnswered = useMemo(\n () => questions.every((candidate) => isAnswered(candidate)),\n [isAnswered, questions],\n );\n\n const chooseSingle = useCallback((questionId: string, optionId: string) => {\n setSingleSel((prev) => ({ ...prev, [questionId]: optionId }));\n setManual((prev) => ({ ...prev, [questionId]: false }));\n }, []);\n\n const toggleMulti = useCallback((questionId: string, optionId: string) => {\n setMultiSel((prev) => {\n const set = new Set(prev[questionId] ?? []);\n if (set.has(optionId)) set.delete(optionId);\n else set.add(optionId);\n return { ...prev, [questionId]: set };\n });\n setManual((prev) => ({ ...prev, [questionId]: false }));\n }, []);\n\n const enableManual = useCallback((questionId: string) => {\n setManual((prev) => ({ ...prev, [questionId]: true }));\n setSingleSel((prev) => ({ ...prev, [questionId]: undefined }));\n setMultiSel((prev) => ({ ...prev, [questionId]: new Set<string>() }));\n }, []);\n\n const goNext = useCallback(() => {\n if (!currentAnswered) return;\n setIndex((i) => Math.min(total - 1, i + 1));\n }, [currentAnswered, total]);\n\n const submit = useCallback(() => {\n if (submitted || !allAnswered) return;\n const answers = new Map<string, string>();\n for (const candidate of questions) {\n const text = answerFor({\n question: candidate,\n manual: Boolean(manual[candidate.id]),\n manualText: manualText[candidate.id] ?? '',\n singleId: singleSel[candidate.id],\n multiIds: multiSel[candidate.id] ?? new Set<string>(),\n });\n if (text) answers.set(candidate.id, text);\n }\n const content = formatAskQuestionsAnswers(request, answers);\n if (content.trim().length === 0) return;\n // Locked before the send so a double-click cannot answer the same\n // questionnaire twice; the customer's reply then retires it from the\n // composer (`pendingClarification`).\n setSubmitted(true);\n sendMessage({\n content,\n // The page and its sharing permission may have changed while answering.\n // Use the normal send-time privacy filter; do not replay earlier marks.\n clientContext: buildPageClientContext({\n marks: [],\n readsPage: widgetCtx.features.pageContext,\n }),\n });\n }, [\n allAnswered,\n submitted,\n manual,\n manualText,\n multiSel,\n questions,\n request,\n sendMessage,\n singleSel,\n widgetCtx,\n ]);\n\n if (!question) return null;\n const typing = Boolean(manual[question.id]);\n\n return (\n <div\n {...dc('chat/clarification_questions/root')}\n className={cn(\n 'w-full rounded-2xl border border-border bg-background shadow-sm',\n submitted && 'pointer-events-none opacity-60',\n )}\n >\n <div className=\"flex items-start gap-2.5 px-4 pt-4\">\n <span className=\"mt-0.5 flex size-7 shrink-0 items-center justify-center rounded-md bg-primary text-primary-foreground\">\n <SparklesIcon className=\"size-4\" />\n </span>\n <p\n {...dc('chat/clarification_questions/prompt')}\n className=\"min-w-0 flex-1 text-sm font-medium leading-snug text-foreground\"\n >\n {question.prompt}\n </p>\n </div>\n\n <div className=\"px-4 pb-3 pt-3\">\n {typing ? (\n <textarea\n {...dc('chat/clarification_questions/manual_input')}\n value={manualText[question.id] ?? ''}\n onChange={(e) =>\n setManualText((prev) => ({\n ...prev,\n [question.id]: e.target.value,\n }))\n }\n placeholder={t('questions_answer_placeholder')}\n rows={3}\n className={cn(\n 'w-full resize-none rounded-xl border border-border bg-muted/30 px-3 py-2.5',\n 'text-sm text-foreground placeholder:text-muted-foreground',\n 'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring',\n )}\n onKeyDown={(e) => {\n if (e.key !== 'Enter' || e.shiftKey) return;\n e.preventDefault();\n if (index < total - 1) goNext();\n else submit();\n }}\n />\n ) : (\n <div className=\"flex flex-wrap gap-2\">\n {question.options.map((option) => {\n const active =\n question.selection === 'single'\n ? singleSel[question.id] === option.id\n : (multiSel[question.id]?.has(option.id) ?? false);\n return (\n <button\n {...dc('chat/clarification_questions/option')}\n key={option.id}\n type=\"button\"\n aria-pressed={active}\n onClick={() =>\n question.selection === 'single'\n ? chooseSingle(question.id, option.id)\n : toggleMulti(question.id, option.id)\n }\n className={cn(\n 'rounded-full border px-3 py-1.5 text-sm transition-colors',\n active\n ? 'border-primary bg-primary/10 text-foreground'\n : 'border-border bg-muted/40 text-foreground/90 hover:bg-muted',\n )}\n >\n {option.label}\n </button>\n );\n })}\n <button\n {...dc('chat/clarification_questions/type_it')}\n type=\"button\"\n onClick={() => enableManual(question.id)}\n className={cn(\n 'rounded-full border border-dashed border-border px-3 py-1.5 text-sm',\n 'text-muted-foreground hover:bg-muted hover:text-foreground',\n )}\n >\n {t('questions_type_answer')}\n </button>\n </div>\n )}\n </div>\n\n <div className=\"flex items-center justify-between gap-2 border-t border-border px-3 py-2\">\n <button\n {...dc('chat/clarification_questions/back')}\n type=\"button\"\n onClick={() => setIndex((i) => Math.max(0, i - 1))}\n disabled={index === 0}\n className=\"inline-flex items-center gap-1 rounded-lg px-2 py-1.5 text-xs font-medium text-muted-foreground hover:bg-muted disabled:opacity-40\"\n >\n <ChevronLeftIcon className=\"size-3.5\" />\n {t('questions_back')}\n </button>\n {total > 1 ? (\n <span className=\"text-[11px] tabular-nums text-muted-foreground\">\n {index + 1} / {total}\n </span>\n ) : null}\n {index < total - 1 ? (\n <button\n {...dc('chat/clarification_questions/next')}\n type=\"button\"\n onClick={goNext}\n disabled={!currentAnswered}\n className=\"inline-flex items-center gap-1 rounded-lg px-2 py-1.5 text-xs font-medium text-primary hover:bg-muted disabled:opacity-40\"\n >\n {t('questions_next')}\n <ChevronRightIcon className=\"size-3.5\" />\n </button>\n ) : (\n <button\n {...dc('chat/clarification_questions/send')}\n type=\"button\"\n onClick={submit}\n disabled={!allAnswered}\n className=\"inline-flex items-center gap-1 rounded-lg px-3 py-1.5 text-xs font-medium text-primary hover:bg-muted disabled:opacity-40\"\n >\n {t('questions_send')}\n </button>\n )}\n </div>\n\n <div className=\"h-1 w-full overflow-hidden rounded-b-2xl bg-muted\">\n <div\n className=\"h-full bg-primary transition-[width] duration-300 ease-out\"\n style={{ width: `${((index + 1) / Math.max(1, total)) * 100}%` }}\n />\n </div>\n </div>\n );\n}\n","import { log } from '@opencx/widget-core';\nimport React from 'react';\nimport {\n useContact,\n useWidgetRouter,\n useWidgetTrigger,\n} from '@opencx/widget-react-headless';\n\nexport type WidgetRef = {\n /** Open the widget on a fresh conversation, optionally sending its first message. */\n newChat: (options?: { message?: string }) => Promise<void>;\n};\n\nexport function WidgetImperativeHandler({\n widgetRef,\n}: {\n widgetRef: React.Ref<WidgetRef>;\n}) {\n const { contactState } = useContact();\n const { setIsOpen } = useWidgetTrigger();\n const { toChatScreen } = useWidgetRouter();\n\n React.useImperativeHandle(\n widgetRef,\n () => ({\n newChat: async (options) => {\n if (!contactState.contact?.token) {\n log.warn('cannot start a new chat: contact not yet initialized');\n return;\n }\n setIsOpen(true);\n // Companion navigation selects an independent runtime synchronously;\n // React may not have rendered its hooks yet, so send to that runtime.\n const conversation = toChatScreen();\n if (conversation && options?.message) {\n await conversation.messageCtx.sendMessage({\n content: options.message,\n });\n }\n },\n }),\n [contactState, setIsOpen, toChatScreen],\n );\n\n return null;\n}\n","import * as PopoverPrimitive from '@radix-ui/react-popover';\nimport { MotionConfig } from 'framer-motion';\nimport React from 'react';\nimport type {\n ExternalStorage,\n LiteralWidgetComponentKey,\n WidgetConfig,\n} from '@opencx/widget-core';\nimport {\n useDisplayMode,\n useWidgetTrigger,\n WidgetLayoutProvider,\n WidgetProvider,\n WidgetTriggerProvider,\n type WidgetComponentType,\n} from '@opencx/widget-react-headless';\nimport { AgentMessageDefaultComponent } from './components/custom-components/AgentMessageDefaultComponent';\nimport { FallbackDefaultComponent } from './components/custom-components/FallbackDefaultComponent';\nimport { LoadingDefaultComponent } from './components/custom-components/LoadingDefaultComponent';\nimport { WidgetContent, WidgetPopoverContent } from './WidgetPopoverContent';\nimport { WidgetPopoverTrigger } from './WidgetPopoverTrigger';\nimport { WidgetPopoverAnchor } from './WidgetPopoverAnchor';\nimport { WidgetCompanion } from './companion/WidgetCompanion';\nimport { PageMarksProvider } from './page-marks/PageMarksProvider';\nimport { AgentChatPageActions } from './screens/chat/agent/AgentChatPageActions';\nimport { AgentChatPageEffects } from './screens/chat/agent/AgentChatPageEffects';\nimport {\n StreamingSpec,\n type StreamingSpecComponentProps,\n} from './components/StreamingTurn';\nimport {\n StepsGroup,\n type StreamingStepsComponentProps,\n} from './components/StepsGroup';\nimport {\n ClarificationQuestions,\n type ClarificationQuestionsProps,\n} from './components/ClarificationQuestions';\nimport {\n WidgetImperativeHandler,\n type WidgetRef,\n} from './WidgetImperativeHandler';\n\nfunction WidgetPopoverTriggerAndContent() {\n const { isOpen, setIsOpen } = useWidgetTrigger();\n\n return (\n <PopoverPrimitive.Root open={isOpen} onOpenChange={setIsOpen}>\n <WidgetPopoverAnchor />\n <WidgetPopoverTrigger />\n <WidgetPopoverContent />\n </PopoverPrimitive.Root>\n );\n}\n\n/**\n * Shell picker: the classic popover unless the embed asked for the companion\n * (`displayMode`). Must render INSIDE WidgetProvider. The companion is one\n * shell across every layout (compact, fullscreen, sidebar): it morphs between\n * them in place — no mount/unmount swap — so switching layouts expands FROM\n * the current rect.\n */\nfunction WidgetDisplayRoot() {\n const displayMode = useDisplayMode();\n return displayMode === 'companion' ? (\n // Layout state (compact/sidebar/fullscreen + the visitor's remembered\n // preferences) is a companion concept; the popover never reads it.\n <WidgetLayoutProvider>\n <WidgetCompanion />\n </WidgetLayoutProvider>\n ) : (\n <WidgetPopoverTriggerAndContent />\n );\n}\n\nconst defaultComponents: WidgetComponentType[] = [\n {\n key: 'loading' satisfies LiteralWidgetComponentKey,\n component: LoadingDefaultComponent,\n },\n {\n key: 'fallback' satisfies LiteralWidgetComponentKey,\n component: FallbackDefaultComponent,\n },\n {\n key: 'bot_message' satisfies LiteralWidgetComponentKey,\n component: AgentMessageDefaultComponent,\n },\n {\n key: 'agent_message' satisfies LiteralWidgetComponentKey,\n component: AgentMessageDefaultComponent,\n },\n {\n key: 'agent_chat_steps' satisfies LiteralWidgetComponentKey,\n component: StepsGroup,\n },\n {\n key: 'agent_chat_spec' satisfies LiteralWidgetComponentKey,\n component: StreamingSpec,\n },\n {\n key: 'agent_chat_questions' satisfies LiteralWidgetComponentKey,\n component: ClarificationQuestions,\n },\n];\n\nconst storage: ExternalStorage = {\n get: async (key: string) => {\n return localStorage.getItem(key);\n },\n set: async (key: string, value: string) => {\n localStorage.setItem(key, value);\n },\n remove: async (key: string) => {\n localStorage.removeItem(key);\n },\n};\n\nconst Widget = React.forwardRef<\n WidgetRef,\n {\n options: WidgetConfig;\n components?: WidgetComponentType[];\n loadingComponent?: React.ReactNode;\n errorComponent?: (error: Error) => React.ReactNode;\n }\n>(function Widget(\n { options, components = [], loadingComponent, errorComponent },\n ref,\n) {\n return (\n // reducedMotion=\"user\" makes every descendant motion.* snap its\n // transform/x/y/scale/layout animations when the visitor's OS asks for less\n // motion, while keeping opacity fades. Non-transform values (the companion\n // shell's width/height/borderRadius morph) are untouched, so its own\n // shouldReduceMotion branch still applies — this is purely additive.\n <MotionConfig reducedMotion=\"user\">\n <WidgetProvider\n components={[...defaultComponents, ...components]}\n options={{\n ...options,\n capabilities: {\n ...options.capabilities,\n richReplies:\n options.capabilities?.richReplies ??\n !components.some(({ key }) =>\n ['AGENT_CHAT_SPEC', 'BOT_MESSAGE', 'AGENT_MESSAGE'].includes(\n key.toUpperCase(),\n ),\n ),\n connections: options.capabilities?.connections === true,\n pageEffects: options.capabilities?.pageEffects ?? true,\n structuredQuestions:\n options.capabilities?.structuredQuestions ??\n !components.some(\n ({ key }) => key.toUpperCase() === 'AGENT_CHAT_QUESTIONS',\n ),\n },\n }}\n storage={storage}\n loadingComponent={loadingComponent}\n errorComponent={errorComponent}\n >\n <WidgetTriggerProvider>\n <PageMarksProvider>\n <AgentChatPageEffects />\n <AgentChatPageActions />\n <WidgetImperativeHandler widgetRef={ref} />\n {options.inline ? <WidgetContent /> : <WidgetDisplayRoot />}\n </PageMarksProvider>\n </WidgetTriggerProvider>\n </WidgetProvider>\n </MotionConfig>\n );\n});\nWidget.displayName = 'Widget';\n\nexport { Widget };\n/**\n * The agent's inline UI, for a host page that shows widget transcripts\n * outside the widget (the OpenCX inbox): the same catalog, renderer, and\n * fence parser the widget uses, so what the agent reads is what the customer\n * saw.\n */\nexport {\n HostedSpecRenderer,\n segmentContent,\n type ContentSegment,\n} from './json-render';\nexport type {\n ClarificationQuestionsProps,\n StreamingSpecComponentProps,\n StreamingStepsComponentProps,\n WidgetRef,\n};\n"],"names":["DynamicValueSchema","z","resolveDynamicValue","value","stateModel","getByPath","unescapeJsonPointer","token","parseJsonPointer","path","obj","segments","current","segment","index","isNumericIndex","str","setByPath","i","nextSegment","nextIsNumeric","lastSegment","addByPath","removeByPath","deepEqual","a","b","item","aObj","bObj","aKeys","bKeys","key","parseSpecStreamLine","line","trimmed","patch","applySpecStreamPatch","moveValue","copyValue","actual","applySpecPatch","spec","nestedToFlat","nested","elements","counter","walk","node","type","props","rawChildren","rest","childKeys","child","element","k","v","compileSpecStream","stream","initial","lines","result","SPEC_DATA_PART","SPEC_DATA_PART_TYPE","immutableSetByPath","root","seg","nextSeg","lastSeg","createStateStore","initialState","state","listeners","notify","listener","updates","changed","next","MAX_FLATTEN_DEPTH","flattenToPointers","prefix","_depth","_seen","_warned","seen","warned","pointer","numericOrStateRef","comparisonOps","StateConditionSchema","ItemConditionSchema","IndexConditionSchema","SingleConditionSchema","VisibilityConditionSchema","resolveComparisonValue","ctx","isItemCondition","cond","isIndexCondition","resolveConditionValue","evaluateCondition","rhs","isAndCondition","condition","isOrCondition","evaluateVisibility","c","createDirectiveRegistry","directives","registry","d","findDirective","match","def","isStateExpression","isItemExpression","isIndexExpression","isBindStateExpression","isBindItemExpression","isCondExpression","isComputedExpression","isTemplateExpression","WARNED_COMPUTED_MAX","warnedComputedFns","resolveBindItemPath","itemPath","resolvePropValue","resolvedPath","fn","_a","resolvedArgs","arg","_match","rawPath","resolved2","fromItem","resolved","directive","val","resolveElementProps","resolveBindings","bindings","resolveActionParam","observers","notifyActionDispatch","evt","o","err","notifyActionSettle","dispatchCounter","nextActionDispatchId","activeCount","isDevtoolsActive","subscribeDevtoolsActive","ActionConfirmSchema","z2","ActionOnSuccessSchema","ActionOnErrorSchema","resolveAction","binding","resolvedParams","confirm","interpolateString","template","_","executeAction","action2","handler","setState","navigate","executeAction2","error","resolvedValue","ValidationCheckSchema","z3","matchesImpl","args","other","builtInValidationFunctions","min","max","pattern","numVal","numOther","runValidationCheck","check2","customFunctions","argValue","validationFn","valid","runValidation","config","checks","errors","DEFAULT_MODES","normalizeModes","jsonPatchInstructions","jsonMergeInstructions","jsonDiffInstructions","modeSelectionGuidance","modes","parts","buildEditInstructions","format","sections","guidance","mode","isNonEmptySpec","s","createBuilder","shape","entryShape","defineSchema","builder","options","catalog","createCatalogFromSchema","schema","catalogData","components","actions","componentNames","actionNames","zodSchema","buildZodSchemaFromDefinition","generatePrompt","zodToJsonSchema","definition","buildZodType","schemaType","z4","inner","zodShape","zodType","keys","getKeysFromPath","propsSchemas","getPropsFromPath","part","entry","context","formatZodType","system","customRules","rawMode","allComponents","cn","comp1","comp2","comp1Def","comp2Def","comp1Props","getExampleProps","comp2Props","dynamicPropName","findFirstStringProp","dynamicProps","exampleOutput","name","propsStr","childrenStr","eventsStr","descStr","builtInActions","hasCustomActions","hasBuiltInActions","catalogFunctions","desc","editModes","baseRules","schemaRules","rule","generateExamplePropsFromZod","typeName","getZodTypeName","innerTypeName","generateExampleValue","values","litValues","litValue","opt","keyType","valueType","keyStr","valueStr","zodTypeName","normalizeTypeName","raw","strict","entries","rawShape","properties","required","innerDef","innerKind","isOptional","unwrapped","defineCatalog","StateContext","createContext","computeInitialFlat","isControlled","StateProvider","externalStore","onStateChange","children","internalStoreRef","useRef","store","storeRef","isControlledRef","initialModeRef","modeWarnedRef","currentMode","prevInitialStateRef","prevFlatRef","useEffect","nextFlat","prevFlat","allKeys","useSyncExternalStore","onStateChangeRef","set","useCallback","value2","prev","update","changes","get","getSnapshot","useMemo","jsx","useStateStore","useContext","VisibilityContext","createContext2","VisibilityProvider","useMemo2","isVisible","jsx2","useVisibility","useContext2","ValidationContext","createContext3","dynamicArgsEqual","keysA","keysB","va","vb","sa","sb","validationConfigEqual","ac","bc","ca","cb","ValidationProvider","fieldStates","setFieldStates","useState","fieldStatesRef","useRef2","fieldConfigs","setFieldConfigs","registerField","useCallback2","existing","validate","currentState","newFieldState","touch","_b","clear","validateAll","allValid","useMemo3","jsx3","useOptionalValidation","useContext3","idCounter","generateUniqueId","deepResolveValue","ActionContext","createContext4","ActionProvider","initialHandlers","validation","handlers","setHandlers","useState2","loadingActions","setLoadingActions","pendingConfirmation","setPendingConfirmation","registerHandler","useCallback3","execute","dispatchId","dispatchedAt","__ok","__error","statePath","rawValue","arr","clearStatePath","screen","currentScreen","navStack","previousScreen","fs","resolve","reject","now","cancel","useMemo4","jsx4","useActions","useContext4","ConfirmDialog","onConfirm","onCancel","isDanger","jsxs","e","RepeatScopeContext","createContext5","RepeatScopeProvider","basePath","jsx5","useRepeatScope","useContext5","ElementErrorBoundary","React5","info","EMPTY_FUNCTIONS","FunctionsContext","useFunctions","DirectivesContext","useDirectives","useDevtoolsActive","ElementRenderer","ElementRenderer2","elementKey","loading","fallback","devtoolsActive","repeatScope","watchState","functions","fullCtx","useMemo5","base","evaluateVisibility2","onBindings","emit","useCallback4","eventName","actionBindings","liveCtx","on","shouldPreventDefault","watchConfig","prevWatchValues","useRef3","stableWatchRef","watchedValues","getByPath2","useEffect2","paths","cancelled","rawProps","elementBindings","resolvedProps","resolvedElement","Component","jsx6","RepeatChildren","childKey","childElement","rendered","tagged","repeat","items","Fragment","itemValue","Renderer","rootElement","JSONUIProvider","validationFunctions","directiveRegistry","jsxs2","ConfirmationDialogManager","defineRegistry","_catalog","componentFn","actionMap","getSetState","getState","actionFn","params","actionName","isSpecDataPart","data","buildSpecFromParts","hasSpec","payload","flat","useTranslation","hostDocumentDir","useDocumentDir","useConfig","language","resolveLanguage","getTranslation","isRtlLanguage","translatorFor","defaultHost","JsonRenderHostContext","JsonRenderHostProvider","host","useJsonRenderHost","useHostFromProps","onUiAction","anchorTarget","JsonRenderErrorBoundary","React","__publicField","log","prevProps","inlineRepeatLeaves","id","recovered","recoverListRepeat","isRecord","_dropped","inputs","twMerge","clsx","ChartImpl","Chart","height","Suspense","ChartShimmer","cardPropsSchema","stackPropsSchema","gridPropsSchema","headingPropsSchema","textPropsSchema","badgePropsSchema","SAFE_LINK_PROTOCOLS","modelAuthoredHrefSchema","listItemSchema","listPropsSchema","listPropsPromptSchema","tablePropsSchema","metricDeltaSchema","metricPropsSchema","calloutPropsSchema","chartDatumSchema","chartPropsSchema","phoneAgentCardPropsSchema","parseProps","widgetCatalog","StreamingShimmer","GAP_CLASS","GRID_MIN_COLUMN","gridColumns","columns","p","containerBody","align","justify","level","size","muted","variant","EmptyState","CompactList","row","ri","cell","ci","MetricCard","style","CALLOUT_STYLES","Icon","PhoneAgentCard","ChartView","JsonRenderFallback","Info","Lightbulb","AlertTriangle","AlertCircle","translationKey","TESTABLE_PHONE_AGENT_MODEL","agentId","agentName","model","t","canTest","Phone","Play","TREND_ICONS","TREND_COLORS","DELTA_ICONS","DELTA_COLORS","label","description","trend","delta","STATUS_COLORS","ListItemContent","showBadge","showSecondary","showStatus","maxVisible","limit","expanded","setExpanded","showExpand","visible","hasBadge","it","hasSecondary","hasStatus","gridCols","rowClass","rowKey","content","ChevronUp","ChevronDown","SpecRenderer","active","HostedSpec","HostedSpecRenderer","NormalizedSpec","normalized","segmentContent","text","markdownLines","blockLines","patchLines","inFence","inBareRun","flushMarkdown","flushSpecBlock","compiled","isRenderableSpec","endBareRun","isLast","isCutPatchLine","PATCH_LINE_OPENING","buildSpec","dc","componentName","SPREADSHEETS","SPREADSHEET_ACCEPT","sheet","mime","ext","VIDEO_ACCEPT","getSpreadsheet","useCanHover","canHover","WOBBLE_MAX_MOVEMENT_PIXELS","Wobble","memo","forwardRef","className","scale","off","ref","isHovering","setIsHovering","movement","setMovement","shouldReduceMotion","useReducedMotion","cloneElement","handleMouseMove","event","clientX","clientY","rect","offsetX","offsetY","normalizedX","normalizedY","x","y","handleMouseEnter","handleMouseLeave","childStyles","EASE_OUT","EASE_OUT_CSS","FADE_TRANSITION","QUICK_TWEEN","MORPH_SPRING","APP_FRAME_EASE","APP_FRAME_EASE_CSS","PILL_SHADOW","DOCK_SHADOW","INPUT_SHADOW","CHAT_SHADOW","ANIMATION_DISTANCE_PX","fadeInRight","distance","overrides","delay","fadeInLeft","fadeInUp","fadeInDown","treasureMap","MotionDiv","fadeIn","snapExit","fadeInProps","motion","buttonVariants","cva","Button","asChild","wobble","Comp","Slot","DialogerProvider","isOpen","setIsOpen","setContent","openDialog","closeDialog","DialogerPortal","useDialoger","dialoger","contentIframeRef","useWidget","close","handleEscape","contentDocument","AnimatePresence","DialogerContent","withClose","X","DialogerHeader","DialogerBody","DialogerFooter","DialogerTitle","DialogerDescription","Dialoger","trigger","open","MIN_SCALE","MAX_SCALE","ZOOM_STEP","CLICK_ZOOM_SCALE","clampTranslate","translate","container","image","containerRect","imgW","imgH","maxX","maxY","ZoomableImage","src","alt","setScale","setTranslate","isDragging","setIsDragging","dragStart","translateStart","containerRef","imgRef","pointerMovedRef","clampScale","reset","zoomIn","zoomOut","handlePointerDown","handlePointerMove","dx","dy","handlePointerUp","didDrag","isZoomed","ControlButton","ZoomOut","ZoomIn","RotateCcw","onClick","disabled","FileCard","url","icon","AttachmentPreview","attachment","isImage","isVideo","isAudio","isPdf","FileText","spreadsheet","FileSpreadsheet","ReplyQuote","replyTo","bot","useBot","humanAgent","sender","senderName","original","MemoizedReactMarkdown","ReactMarkdown","configuredTextSchema","defaultSchema","allowedProperty","allowedValue","unsafeFunction","filterConfiguredStyles","visit","declaration","colon","property","stripCitationRefs","richTextSanitizeSchema","RichText","RichTextContent","ConfiguredRichText","messageType","messageId","configuredStyles","remarkGfm","rehypeRaw","rehypeSanitize","useComponentContext","org","session","useSessions","messages","useMessages","useWidgetRouter","MessageAfterComponent","currentMessage","MessageOptions","messageOptions","messagesState","sendMessage","sessionState","newestWithOptions","message","pickedOptionId","tappable","picked","option","CheckIcon","MESSAGE_PROSE_TOKENS","AgentMessageDefaultComponent","attachments","isFirstInGroup","isLastInGroup","isAloneInGroup","dataComponentNames","classNames","quote","bubble","withAfter","withQuote","hasUiSegments","lastMarkdownIndex","last","firstMarkdownIndex","FallbackDefaultComponent","Avatar","AvatarPrimitive","AvatarImage","AvatarFallback","AgentAvatar","agent","LoadingDefaultComponent","resolveTriggerSide","offset","dir","rightIsNumber","leftIsNumber","THRESHOLD_PIXELS","useIsSmallScreen","isSmallScreen","setIsSmallScreen","topWindow","checkScreenSize","DEFAULTS","useTheme","theme","inline","withInlineDefault","withSmallScreenDefault","target","withDefaults","triggerSide","widgetTrigger","_d","_c","_f","_e","_h","_g","_j","_i","_l","_k","triggerOffset","themeWithFallbacks","_m","_n","_o","_p","_q","_r","_s","_t","_v","_u","_x","_w","_z","_y","_B","_A","_D","_C","_F","_E","_H","_G","_J","_I","_M","_L","_K","_P","_O","_N","_S","_R","_Q","_V","_U","_T","computed","cssVars","paletteName","primary","palette","getPaletteColors","_primary","tc","primaryForeground","neutral","stone","zinc","slate","isExhaustive","TooltipProvider","TooltipPrimitive","Tooltip","TooltipTrigger","TooltipContent","sideOffset","TooltipsSuppressed","SuppressTooltips","Tooltippy","side","shortcut","disableTooltips","suppressed","WIDGET_FRAME_TITLE","buildFrameHtml","transparent","styles","FrameDocument","rootRef","shellRadius","cssOverrides","radiusVars","version","useSetWidgetSizeFn","width","useSetWidgetSize","setWidth","setHeight","FallbackIcon","CircleDashedIcon","DynamicIcon","CheckCheckIcon","CircleCheckIcon","CircleCheckBigIcon","CircleXIcon","ExpandIcon","MaximizeIcon","Maximize2Icon","MinimizeIcon","Minimize2Icon","ShrinkIcon","SquareCheckIcon","SquareCheckBigIcon","SquareXIcon","XIcon","AtSignIcon","BotIcon","BookIcon","BookOpenIcon","Building2Icon","CalendarIcon","CreditCardIcon","DatabaseIcon","FileTextIcon","FolderIcon","GlobeIcon","LinkIcon","MailIcon","PackageIcon","PlugIcon","SettingsIcon","ShoppingCartIcon","TagIcon","TicketIcon","UserIcon","UsersIcon","WorkflowIcon","ZapIcon","useSessionIdentity","chat","usePrimitiveState","draft","title","preview","status","useChatPicker","anchor","setAnchor","setOpen","animate","setAnimate","autoFocus","setAutoFocus","pinned","timer","instant","CompanionControlStyles","ChatPickerTrigger","picker","ChatRow","selected","onSelect","onClose","Menu","LoaderCircleIcon","ChatPicker","portalTarget","ChatPickerContent","placement","onSelected","onPointerEnter","onPointerLeave","activeChats","activeId","selectChat","newChat","closeChat","useCompanionChats","canCreateNewSession","menuRef","previousFocus","setMenuRef","restoringHoverFocus","callbacks","virtualAnchor","view","hostWindow","frame","outer","sx","sy","workingCount","outside","doc","useLayoutEffect","choose","dismissChat","createPortal","PlusIcon","useHostPortal","setTarget","ConversationTitle","chats","openChats","identity","otherSessions","otherWorkingCount","otherSessionsLabel","switchLabel","ChevronsUpDownIcon","HeaderBottomComponent","HeaderTitleComponent","resolveHeaderTitle","textContent","orgName","useGetHeaderTitle","useGetHeaderDataComponentProp","Header__BackToSessionsScreenButton","router","toSessionsScreen","ChevronLeftIcon","Header__Buttons__Item__CloseWidget","button","useWidgetTrigger","componentCtx","handleClick","Header__Buttons__Item__ExpandShrink","screenHeight","screenWidth","isExpanded","Header__Buttons__Item__ResolveSession","widgetCtx","resolveSession","isNoSession","isResolved","onResolved","behaviorBeforeSessionCreation","behaviorIfSessionIsResolved","isDisabled","handleResolve","success","handleResolveAlternative","Header__Buttons__Item","defaultCloseWidgetButton","Header__Buttons","headerButtons","buttons","Header","isCompanion","dataComponentProp","LoadingSpinner","LoaderIcon","useCanvas","isInitialFetchLoading","activeMode","useModes","AgentMessage","componentStore","SuggestedReplyButton","suggestion","handleSend","GroupTimestamp","containerClassName","timestamps","lastMessageTimestamp","formattedTimestamp","COPIED_FEEDBACK_MS","replyText","useShowsCopyAction","messageActions","displayMode","useDisplayMode","MessageActions","alwaysVisible","copied","setCopied","resetRef","clipboard","copy","CopyIcon","isAiMessage","AgentMessageGroup","suggestedReplies","showsCopy","aiMessages","array","SNAKE_FRAMES","BrailleSpinner","setFrame","f","StreamingTurn","turn","timestamp","StepsComponent","SpecComponent","LoadingComponent","startedAt","groupTimestamp","presentation","resolveClientPresentation","applyPresentation","typing","endsWithRunningSteps","step","StreamingSpec","TaskPlan","plan","panelId","useId","reduceMotion","completed","currentStep","circumference","progressOffset","Check","Loader2","CircleDashed","SessionResolvedComponent","ChatBottomComponents","groupMessagesByType","currentGroup","isUserMessageGroup","isBotMessageGroup","isAgentMessageGroup","ChatBannerItems","chatBannerItems","persistent","MAX_SVG_ICON_LENGTH","cache","svgToMaskUrl","svg","cached","toMaskUrl","badgeVariants","Badge","CustomStatusIcon","customStatus","dotClassName","maskUrl","color","CustomStatusBadge","ChatCustomStatus","InitialMessages","advancedInitialMessages","initialQuestions","initialQuestionsPosition","texts","m","MarkThumbnail","note","tile","WIDGET_OWNED_SELECTOR","PAGE_VALUE_SELECTOR","PRIVATE_SELECTOR","isSelfPrivate","el","isPageElementPrivate","safePageText","chunks","block","safePageUrl","canCapturePageElement","MAX_EDGE_PX","CAPTURE_TIMEOUT_MS","thumbnails","captureElements","captureThumbnail","pixelRatio","capture","toJpeg","timeout","beginThumbnail","snapshotUploads","beginSnapshotUpload","mark","upload","thumbnail","uploaded","dataUrl","file","fileFromDataUrl","awaitSnapshotUrl","maxWaitMs","pending","base64","binary","bytes","getThumbnail","copyThumbnail","source","useMarkThumbnail","thumb","setThumb","SentMarkChip","PenLineIcon","SEARCH_DEBOUNCE_MS","MAX_MENTION_RESULTS","GROUP_PREVIEW_COUNT","groupMentions","results","byType","list","groups","all","activeMentionQuery","caret","before","filterMentions","query","needle","rank","mentionText","mentionRanges","ranges","from","at","useMentions","setText","inputRef","mentionsConfig","hostSearch","search","enabled","setPicked","useComposerDraft","setActive","setResults","highlighted","setHighlighted","searching","setSearching","kept","readActive","direction","input","inside","range","found","requestRef","request","pick","end","inserted","expandGroup","onKeyDown","hit","MentionText","mentions","tokenClassName","tokens","nodes","createElement","UserMessage","UserMessageGroup","MessageGroups","pendingReply","group","firstIdInGroup","SCROLL_NEAR_BOTTOM_PX","isNearBottom","scrollHeight","scrollTop","clientHeight","threshold","useStreamFollow","followKey","autoFollowRef","showScrollDown","setShowScrollDown","observerRef","observedRows","handleScroll","nearBottom","scrollToBottom","observer","AgentChatMain","isStreaming","liveItems","turnSources","liveTurnKey","turnFailed","retryFailedTurn","useAgentChatUi","sessionPlan","groupedMessages","sourceByRowId","map","rowId","lastUserGroupIndex","hasLiveItems","transcriptNodes","renderedSourceKeys","groupIndex","run","flushRun","runFirstId","showLiveTurn","ArrowDown","ChatCanvas","createStateCheckpoint","isSendingMessage","setIsSendingMessage","handleSendMessage","useInitialQuestionRequired","requireInitialQuestion","question","MotionDiv__VerticalReveal","CSAT_SCORES","CsatSurvey","submitCsat","isCsatRequested","isCsatSubmitted","submittedScore","submittedFeedback","useCsat","score","setScore","feedback","setFeedback","handleRatingClick","handleSubmit","ArrowUpIcon","MightSolveUserIssueSuggestedReplies","ChatFooterItems","chatFooterItems","isSessionResolved","isSessionOpen","McpIcon","ElicitationForm","sessionId","setPending","controller","poll","requests","RequestForm","answer","onAnswer","busy","setBusy","setError","respond","cause","fields","approval","inputClass","field","choices","choice","ConnectionCard","connection","useConnection","phase","authorization","continuation","finished","expired","actionLabel","action","MARK_SHAPES","pickedElementsFromMarks","marks","byKey","noteTarget","MIN_REGION_SIZE_PX","UNDRAW_BACKSTOP_MS","adoptNotationInk","zIndex","createMarkInk","pageRect","marker","annotate","gone","remove","redraw","nextRect","nextShape","TEXT_TRUNCATE","truncate","cleanText","isUtilityClass","cls","meaningfulClass","identifyElementName","tag","aria","rawHref","safeHref","href","placeholder","isUniqueInDocument","selector","computeUniqueSelector","byId","parent","sameTagSiblings","candidate","rectOf","VIEWPORT_MARGIN_PX","clampRectToViewport","margin","viewportWidth","viewportHeight","left","top","right","bottom","describeElement","WIDGET_OWNED_CLOSEST","isWidgetOwned","elementAt","sources","registerPageMarkSources","isPageMarkShareable","pageMarkForSend","descriptions","snapshotSafe","NAME_MAX","collapse","visibleText","labelText","labelled","fieldset","legend","accessibleName","labelledBy","ariaLabel","PAGE_ACTIONS","SETTLE_MS","NEVER_ACT_INPUT_TYPES","captureActionMeaning","reference","approved","activationTargets","readTarget","targets","visited","start","link","control","form","baseTarget","GENERATIONS_KEPT","generations","sequence","elementRefs","observedDocument","subtreeRevisions","recordRevisions","lineageRevisions","CONTEXT_SELECTOR","RECORD_SELECTOR","GROUP_SELECTOR","PRESENTATION_ATTRIBUTES","contextRoot","record","region","transient","recordIsRelevant","advance","records","revision","withinRecord","subtree","ownContent","captureContext","captured","track","revisions","flushMutations","observe","generation","beginSnapshot","n","previous","prior","reading","resolveRef","inspectRef","PRIVATE_REGION_ATTRIBUTE","NEVER_READ_INPUT_TYPES","MAX_CONTROLS","offLimitsReason","OFF_LIMITS_DETAIL","INTERACTIVE_SELECTOR","CLICKABLE_CONTAINER_SELECTOR","MAX_STYLE_PROBES","looksClickable","roleOf","explicit","containerRoleOf","readPageControls","controls","truncated","mint","candidates","probes","containers","buildPageClientContext","readsPage","currentMarks","VERBS","PageActionCard","resolvePageAction","verb","proposedValue","COMPOSER_TOOL_BUTTON","COMPOSER_TOOL_ARMED","CONTEXT_CHIP_REMOVE","PageContextPill","entity","onRemove","entitySchema","usePageEntity","useHostLocation","parsed","resolveConfigContext","readColor","resolvePageMarkTheme","primaryColor","contentZIndex","PageMarkOverlay","isActive","hover","onShapeChange","onAttach","onDiscard","markTheme","accent","KeyCap","MarkEditorCard","SHAPE_GLYPH","SHAPE_LABEL_KEY","setNote","CARD_W","vw","vh","below","shapeLabel","PageMarkPill","removeLabel","hoverTitle","WIDGET_KEYBINDINGS","isApplePlatform","matchesBinding","apple","mods","wantMeta","wantCtrl","APPLE_MOD_SYMBOLS","KEY_SYMBOLS","formatBinding","keyLabel","MAX_FILE_BYTES","BASE_FILE_ACCEPT","HANDED_OFF_FILE_ACCEPT","AI_FILE_ACCEPT","UploadStatusIcon","UploadFileContent","fileContent","fileType","FileAudio2Icon","FileVideo2Icon","FileIcon","UploadPreview","setFileContent","reader","QueuedSendsPill","queuedUserMessages","removeQueued","stop","q","CornerDownLeftIcon","DictationLevelBars","levelRef","barsRef","raf","smoother","DictationLevelSmoother","lastWritten","tick","bars","smoothed","bar","sway","DictationMicButton","onToggle","onPrewarm","listening","connecting","MicIcon","caretPositionInTextarea","textarea","mirror","copyTextLayoutStyles","prop","MIRRORED_STYLES","MENU_WIDTH","DETAIL_WIDTH","GAP","MENU_SURFACE","MentionPicker","anchorRef","anchorIndex","onHighlight","onPick","onExpand","setPlacement","place","frameWidth","inputRect","wanted","detail","rowIndex","MentionIcon","MentionDetail","PageMarksContext","PageMarksProvider","setMarks","isArmed","setIsArmed","inksRef","setArmed","armed","attach","ink","detach","detachAll","inks","usePageMarks","CURSOR_STYLE_ATTR","MAX_MARK_ELEMENTS","SAMPLE_GRID","SNAP_PADDING_PX","DEFAULT_REGION","HANDLE_GRAB_PX","NOT_WIDGET_OWNED","cornerCursor","corner","usePageMarking","accentColor","attachPageMark","setDraft","setHover","inkRef","draftRef","dropDraft","disarm","applyRect","setShape","cursor","setCursor","gesture","isWidgetTarget","claimHostEvent","cornerAt","corners","cx","cy","isInside","placeRegion","r","lastHoverEl","hoverKey","anchorX","anchorY","x1","x2","y1","y2","handlePointerCancel","swallow","handleKeyDown","previousScrollX","previousScrollY","deltaX","deltaY","sampled","sampleRegion","toggle","probe","j","usePageMarkComposer","pageMarkTheme","onMarkAttached","uploadSnapshot","fileUrl","marking","useSentTextRecall","inputText","setInputText","getSentTextHistory","indexRef","playRecallAnimation","applyRecall","history","TEXTAREA_BOX_CLASS","ChatInput","trailingActions","hideAttachTools","composerRootRef","mirrorRef","mountedRef","rememberSentText","canAttach","pageMarksEnabled","pendingClarification","pendingConnection","pendingPageAction","clearSubmitted","pageEntity","hasMentionsInDraft","pageEntityDismissed","setPageEntityDismissed","pageEntityKey","fileSelectionError","setFileSelectionError","inputTextRef","handleSubmitRef","dictation","useDictation","stopDictation","recall","showPageMarks","pageMarkingEnabled","allFiles","handleCancelUpload","appendFiles","isUploading","successFiles","useUploadFiles","isHandedOff","isAwaitingBotReply","useIsAwaitingBotReply","shouldBlockSending","handleFileDrop","acceptedFiles","hasAttachedContext","hasPreviews","cannotSend","showStop","flushQueueOnEnter","sendDisabled","submittedText","isCurrentConversation","submittedDraft","submittedMarks","submittedFiles","submittedFileIds","SNAPSHOT_UPLOAD_GRACE_MS","submit","markNotes","didAccept","submittedMentions","fileId","cleared","dropzone__getRootProps","dropzone__getInputProps","dropzone__openFileSelect","useDropzone","handlePaste","clipboardData","QuestionsComponent","PaperclipIcon","MousePointerClickIcon","SquareIcon","notes","NewConvOrBackToConvsButton","SessionClosedSection","ChatFooter","thisWasHelpfulOrNot","noMessages","initialQuestionRequired","iq","ChatMain","lastMessage","lastMessageId","lastMessageType","previousMessageId","typingPaused","setTypingPaused","showTypingIndicator","receivedMessage","resumeTyping","messagesContainerRef","handleNewMessage","container_","ChatScreen","isStreamingEngine","isCanvasOpen","chatContentKeyRef","ConnectionsSettings","selectedId","setSelectedId","setSearch","connections","setConnections","rules","setRules","permissions","change","operation","Unplug","ChevronRight","ArrowLeft","Skeleton","OpenLogoSvg","PoweredByOpen","SectionTitle","SessionCard","toChatScreen","assigneeName","assigneeAvatarUrl","UserRoundIcon","ChevronRightIcon","SessionsList","sessions","isLoading","openSessions","closedSessions","SessionsScreen","Input","useWidgetContentHeight","observedElementRef","contentRoot","observedElement","animationFrame","WelcomeScreen","createUnverifiedContact","useContact","setName","email","setEmail","extraDataFields","extraData","setExtraData","handleSubmitState","useAsyncFn","SendHorizontal","RootScreen","initialContent","keepShellAnimationSynchronized","WidgetContent","IFrame","WidgetPopoverContent","PopoverPrimitive","ev","ChatBubbleSvg","useTriggerLabel","accessibility","renderCustomTrigger","customTrigger","WidgetPopoverTrigger","assets","customComponents","triggerLabel","ChevronDownIcon","WidgetPopoverAnchor","NESTED_ESCAPE_SCOPE","isInsideNestedEscapeScope","handleCompanionHostKeyDown","onToggleFullscreen","handleCompanionFrameKeyDown","onDismiss","resolveEscapeAction","panelLayout","previousLayout","defaultLayout","allowedLayouts","layout","anyOther","CompanionQuestions","onHeightChange","maxHeight","report","Observer","CompanionQuestionButtons","agentPointerEvents","isAgentPointerEvent","firePointerSequence","mayDispatch","dispatched","dispatch","mouse","FrameIconButton","clamp","FULLSCREEN_MARGIN","SIDEBAR_MARGIN","PILL_SIZE","DOCK_HEIGHT","DOCK_FALLBACK_WIDTH","PANEL_MAX_WIDTH","PANEL_HORIZONTAL_MARGIN","COMPACT_MIN_WIDTH","CHAT_MIN_HEIGHT","CHAT_MAX_HEIGHT","TOP_MARGIN","VIEWPORT_EDGE_PADDING","DEFAULT_SIDEBAR_WIDTH","MIN_SIDEBAR_WIDTH","MAX_SIDEBAR_WIDTH","SIDEBAR_CANVAS","MIN_HOST_PAGE_WIDTH","SIDEBAR_FULL_BLEED_MAX_WIDTH","RADII","effectiveSidebarWidth","sidebarWidth","maxWidth","finiteAtLeast","compactWidth","minWidth","chatHeight","bottomOffset","minHeight","viewportHeightRatio","availableHeight","chatDims","opts","compact","shellAnchor","isChatOpen","sidebarSide","anchorLayout","scope","FLAT_MESSAGE_CSS","HIDE_AVATARS_CSS","FLAT_AVATARS_CSS","LayoutGlyph","common","SidePanelGlyph","SidebarSubmenu","anchored","onSelectSide","docked","onToggleDock","SubmenuRow","DockSwitch","SideSegmented","checked","sides","labelKey","LAYOUT_LABELS","isKeyboardFocus","LayoutPicker","setSidebarSide","sidebarMode","setSidebarMode","useWidgetLayout","sidebarTileHovered","setSidebarTileHovered","showLayoutTiles","sidebarAvailable","sidebarOptionsShown","applyFromAnyLayout","apply","submenu","isSidebar","PanelControls","onSelectLayout","companionLayoutOverrides","CompanionContent","onMinimize","canExpand","onInputHeightChange","companion","inputPaneRef","chatPaneRef","bubbles","avatars","handleKey","RO","focusComposer","pane","CompanionFrame","iframeRef","mountNode","setMountNode","handleRef","CompanionFaceIcon","headColor","eyeColor","svgRef","hovered","setHovered","blinking","setBlinking","rawX","useMotionValue","rawY","eyeX","useSpring","eyeY","leftPupilCx","useTransform","leftPupilCy","rightPupilCx","rightPupilCy","dist","angle","tickId","blinkOffId","handleVisibility","eyeScaleY","CompanionIcon","pillBackground","restingFade","RestingPill","measureRef","countLabel","onOpenChats","pickerOpen","working","SessionCircle","number","interactive","tooltipOpen","setTooltipOpen","tooltip","closeLabel","SessionCircles","onLastClosed","hiddenCount","hiddenWorking","dismiss","useCompanionOpenSync","panelOpen","onOpen","lastPushed","FRAME_ATTR","STYLE_ATTR","OPEN_ATTR","NO_ANIM_ATTR","FIT_ATTR","WIDTH_VAR","EASE","styleEl","fitObserver","ownerOrder","owners","NOOP_LEASE","activeOwner","latest","latestOpen","owner","applyOwnerState","buildCss","html","stampFixedElements","canvas","pageBackground","near","far","mountAppFrame","prevScrollY","mutations","mutation","ownerId","released","animated","teardownAppFrame","prevScrollTop","lockCount","previousOverflow","lockHostScroll","readCssVar","vars","useCompanionHostEffects","storage","resizeLabel","minSidebarWidth","maxSidebarWidth","setSidebarWidth","sidebarResizing","setSidebarResizing","frameLeaseRef","saved","widthFromPointer","onPointerDown","onPointerMove","onPointerUp","finalWidth","onPointerCancel","grows","isDocked","frameStateRef","lease","isFullscreenModal","lockFullscreenScroll","resizeHandleProps","FALLBACK_VIEWPORT","getViewportSize","useCompanionMeasurements","setRegion","dockContentWidth","setDockContentWidth","dockObserverRef","dockContentRef","handleResize","dockWidth","usePersistedPillDrag","currentWidth","restingWidth","pillOffsetX","setPillOffsetX","dragX","wasDraggingRef","settle","bound","maxOffset","restingBound","dragConstraints","onDragStart","onDragEnd","shouldIgnoreLaunch","pageClickDismisses","isPageMarkModeArmed","COMPANION_INPUT_FALLBACK_HEIGHT","WidgetCompanion","activeChatCount","workingChatCount","setPanelLayout","setPanelLayoutPreference","inputHeight","setInputHeight","morphTransition","hasBeenChatRef","isPill","showsQuickQuestions","questionsHeight","setQuestionsHeight","hasCountAction","closePickerRef","hasCustomTrigger","companionIcon","pillAriaLabel","hasActiveSession","continueLabel","dockLabel","dockLabelDisplay","quickAskPlaceholder","pillHovered","setPillHovered","resolveCompactWidth","resolvedChatDims","contentWidth","contentHeight","shellCenterX","shellBottom","currentDims","dockGrowX","openPanel","hasSession","launchFromPill","closePanel","dismissPanel","lastNonFullscreenLayoutRef","lastUserMessageId","userMessageIdOnCollapseRef","handleExpand","selectLayout","firstNonFullscreenLayout","handleToggleFullscreen","handleGlobalKey","count","isTopmost","guardRef","forbidden","setNativeValue","prototype","setter","resolveSelectOption","matches","watchPage","budgetMs","isCurrent","isRelated","unrelatedBusy","isBackground","mutated","lastMutation","deadline","check","refuseReason","actOnPage","act","settleMs","consentIsCurrent","observationIsCurrent","guarded","refused","urlBefore","watcher","selectedValue","interrupted","box","ariaState","pendingDetail","TRAVEL_EASE","CURSOR_APPEAR_MS","CURSOR_TRAVEL_MS","CURSOR_REST_MS","CURSOR_PRESS_MS","ARC","minimumJerk","onCurve","to","inv","reachFrames","steps","frames","point","HOTSPOT_X","HOTSPOT_Y","GLYPH","prefersReducedMotion","wait","ms","idleTimer","CURSOR_IDLE_MS","dismissAgentCursor","stale","keepAlive","showAgentCursor","layer","glyph","land","centreOf","travelTo","press","actOnPageInputSchema","usePageEffectIsCurrent","effects","mounted","effect","MAX_HANDLED_ACTIONS","AgentChatPageActions","pageEffects","replyToPageCall","requestPageActionConsent","handledRef","handled","oldest","consentName","optionValue","optionLabel","hasSameMeaning","after","HIGHLIGHT_MARK_TYPES","highlightElementInputSchema","DEFAULT_HIGHLIGHT_DURATION_MS","autoMarkType","fontSize","activeDismiss","dismissActiveHighlight","highlightElementOnHostPage","surfaceColor","foregroundColor","durationMs","seed","small","dismissed","draw","fonts","callout","arrow","rafId","pill","tip","cw","calloutTimer","timeoutId","onInteract","MAX_HANDLED_PAGE_EFFECTS","AgentChatPageEffects","pageMarkHighlightDurationMs","handledEffectKeysRef","callId","INLINE_MARKS","INLINE_UNDERSCORES","MAX_UNWRAP_PASSES","stripInlineMarkdown","out","pass","PixelLoader","indices","shuffled","VanishingLabel","labels","labelsRef","setCurrent","setPhase","prevLengthRef","len","tid","stepLabel","thinkingLabel","formatToolLabel","l","plain","buildBreadcrumb","maxItems","firstThought","THOUGHT_PROSE","ThoughtRow","isLive","isTruncated","displayLabel","TOOL_IO_MAX_CHARS","formatToolPayload","safeStringify","ToolPayload","ToolRow","showIO","hasIO","StepsGroup","turnSteps","showStepToolIO","activity","showToolDetails","wasActiveRef","toolName","words","answerFor","typed","ClarificationQuestions","questions","setIndex","submitted","setSubmitted","manual","setManual","manualText","setManualText","singleSel","setSingleSel","multiSel","setMultiSel","total","isAnswered","currentAnswered","allAnswered","chooseSingle","questionId","optionId","toggleMulti","enableManual","goNext","answers","formatAskQuestionsAnswers","SparklesIcon","WidgetImperativeHandler","widgetRef","contactState","conversation","WidgetPopoverTriggerAndContent","WidgetDisplayRoot","WidgetLayoutProvider","defaultComponents","Widget","loadingComponent","errorComponent","MotionConfig","WidgetProvider","WidgetTriggerProvider"],"mappings":"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","x_google_ignoreList":[0,1,2,3]}