@aparte/core 0.2.0-alpha.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 (175) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +53 -0
  3. package/dist/client/aparte-client.d.ts +326 -0
  4. package/dist/client/aparte-client.d.ts.map +1 -0
  5. package/dist/client/stream-adapter.d.ts +197 -0
  6. package/dist/client/stream-adapter.d.ts.map +1 -0
  7. package/dist/components/bubble/aparte-chat-bubble.d.ts +153 -0
  8. package/dist/components/bubble/aparte-chat-bubble.d.ts.map +1 -0
  9. package/dist/components/bubble/bubble-sync.d.ts +44 -0
  10. package/dist/components/bubble/bubble-sync.d.ts.map +1 -0
  11. package/dist/components/bubble/index.d.ts +4 -0
  12. package/dist/components/bubble/index.d.ts.map +1 -0
  13. package/dist/components/chat/aparte-chat.d.ts +49 -0
  14. package/dist/components/chat/aparte-chat.d.ts.map +1 -0
  15. package/dist/components/chat/index.d.ts +2 -0
  16. package/dist/components/chat/index.d.ts.map +1 -0
  17. package/dist/components/composer/aparte-composer-action.d.ts +37 -0
  18. package/dist/components/composer/aparte-composer-action.d.ts.map +1 -0
  19. package/dist/components/composer/aparte-composer-add-attachment.d.ts +27 -0
  20. package/dist/components/composer/aparte-composer-add-attachment.d.ts.map +1 -0
  21. package/dist/components/composer/aparte-composer-attachments.d.ts +26 -0
  22. package/dist/components/composer/aparte-composer-attachments.d.ts.map +1 -0
  23. package/dist/components/composer/aparte-composer-cancel.d.ts +21 -0
  24. package/dist/components/composer/aparte-composer-cancel.d.ts.map +1 -0
  25. package/dist/components/composer/aparte-composer-input.d.ts +63 -0
  26. package/dist/components/composer/aparte-composer-input.d.ts.map +1 -0
  27. package/dist/components/composer/aparte-composer-send.d.ts +25 -0
  28. package/dist/components/composer/aparte-composer-send.d.ts.map +1 -0
  29. package/dist/components/composer/aparte-composer.d.ts +150 -0
  30. package/dist/components/composer/aparte-composer.d.ts.map +1 -0
  31. package/dist/components/composer/index.d.ts +9 -0
  32. package/dist/components/composer/index.d.ts.map +1 -0
  33. package/dist/components/conversation-list/aparte-conversation-list.d.ts +50 -0
  34. package/dist/components/conversation-list/aparte-conversation-list.d.ts.map +1 -0
  35. package/dist/components/conversation-list/index.d.ts +2 -0
  36. package/dist/components/conversation-list/index.d.ts.map +1 -0
  37. package/dist/components/elicitation/aparte-elicitation.d.ts +29 -0
  38. package/dist/components/elicitation/aparte-elicitation.d.ts.map +1 -0
  39. package/dist/components/index.d.ts +10 -0
  40. package/dist/components/index.d.ts.map +1 -0
  41. package/dist/components/status/aparte-chat-status.d.ts +34 -0
  42. package/dist/components/status/aparte-chat-status.d.ts.map +1 -0
  43. package/dist/components/status/index.d.ts +2 -0
  44. package/dist/components/status/index.d.ts.map +1 -0
  45. package/dist/components/viewport/aparte-chat-viewport.d.ts +358 -0
  46. package/dist/components/viewport/aparte-chat-viewport.d.ts.map +1 -0
  47. package/dist/components/viewport/index.d.ts +2 -0
  48. package/dist/components/viewport/index.d.ts.map +1 -0
  49. package/dist/config/action-provider.d.ts +59 -0
  50. package/dist/config/action-provider.d.ts.map +1 -0
  51. package/dist/config/aparte-config.d.ts +490 -0
  52. package/dist/config/aparte-config.d.ts.map +1 -0
  53. package/dist/config/attachment-renderer.d.ts +28 -0
  54. package/dist/config/attachment-renderer.d.ts.map +1 -0
  55. package/dist/config/avatar-provider.d.ts +35 -0
  56. package/dist/config/avatar-provider.d.ts.map +1 -0
  57. package/dist/config/bubble-shell-renderer.d.ts +41 -0
  58. package/dist/config/bubble-shell-renderer.d.ts.map +1 -0
  59. package/dist/config/config-context.d.ts +47 -0
  60. package/dist/config/config-context.d.ts.map +1 -0
  61. package/dist/config/error-renderer.d.ts +26 -0
  62. package/dist/config/error-renderer.d.ts.map +1 -0
  63. package/dist/config/icon-provider.d.ts +63 -0
  64. package/dist/config/icon-provider.d.ts.map +1 -0
  65. package/dist/config/index.d.ts +19 -0
  66. package/dist/config/index.d.ts.map +1 -0
  67. package/dist/config/locale.d.ts +60 -0
  68. package/dist/config/locale.d.ts.map +1 -0
  69. package/dist/config/sanitize.d.ts +31 -0
  70. package/dist/config/sanitize.d.ts.map +1 -0
  71. package/dist/config/sibling-nav-renderer.d.ts +27 -0
  72. package/dist/config/sibling-nav-renderer.d.ts.map +1 -0
  73. package/dist/config/skeleton-provider.d.ts +26 -0
  74. package/dist/config/skeleton-provider.d.ts.map +1 -0
  75. package/dist/config/status-renderer.d.ts +23 -0
  76. package/dist/config/status-renderer.d.ts.map +1 -0
  77. package/dist/conversations/conversation-controller.d.ts +126 -0
  78. package/dist/conversations/conversation-controller.d.ts.map +1 -0
  79. package/dist/conversations/conversation-manager.d.ts +98 -0
  80. package/dist/conversations/conversation-manager.d.ts.map +1 -0
  81. package/dist/conversations/index.d.ts +5 -0
  82. package/dist/conversations/index.d.ts.map +1 -0
  83. package/dist/conversations/types.d.ts +172 -0
  84. package/dist/conversations/types.d.ts.map +1 -0
  85. package/dist/custom-elements.json +15833 -0
  86. package/dist/elicitation/index.d.ts +20 -0
  87. package/dist/elicitation/index.d.ts.map +1 -0
  88. package/dist/elicitation/panel.d.ts +18 -0
  89. package/dist/elicitation/panel.d.ts.map +1 -0
  90. package/dist/elicitation/types.d.ts +98 -0
  91. package/dist/elicitation/types.d.ts.map +1 -0
  92. package/dist/host/aparte-chat-host.d.ts +176 -0
  93. package/dist/host/aparte-chat-host.d.ts.map +1 -0
  94. package/dist/host/index.d.ts +2 -0
  95. package/dist/host/index.d.ts.map +1 -0
  96. package/dist/index-D89k-n2Q.js +6294 -0
  97. package/dist/index-D89k-n2Q.js.map +1 -0
  98. package/dist/index.css +2554 -0
  99. package/dist/index.d.ts +62 -0
  100. package/dist/index.d.ts.map +1 -0
  101. package/dist/index.js +3763 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/index.node.d.ts +53 -0
  104. package/dist/index.node.d.ts.map +1 -0
  105. package/dist/index.node.js +49 -0
  106. package/dist/index.node.js.map +1 -0
  107. package/dist/interop/element-props.d.ts +23 -0
  108. package/dist/interop/element-props.d.ts.map +1 -0
  109. package/dist/parsers/aparte-event-stream.d.ts +13 -0
  110. package/dist/parsers/aparte-event-stream.d.ts.map +1 -0
  111. package/dist/parsers/aparte-stream-parser.d.ts +137 -0
  112. package/dist/parsers/aparte-stream-parser.d.ts.map +1 -0
  113. package/dist/parsers/index.d.ts +4 -0
  114. package/dist/parsers/index.d.ts.map +1 -0
  115. package/dist/primitives/index.d.ts +8 -0
  116. package/dist/primitives/index.d.ts.map +1 -0
  117. package/dist/primitives/progress-spinner/aparte-progress-spinner.d.ts +25 -0
  118. package/dist/primitives/progress-spinner/aparte-progress-spinner.d.ts.map +1 -0
  119. package/dist/primitives/progress-spinner/index.d.ts +2 -0
  120. package/dist/primitives/progress-spinner/index.d.ts.map +1 -0
  121. package/dist/primitives/select/aparte-optgroup.d.ts +32 -0
  122. package/dist/primitives/select/aparte-optgroup.d.ts.map +1 -0
  123. package/dist/primitives/select/aparte-option.d.ts +30 -0
  124. package/dist/primitives/select/aparte-option.d.ts.map +1 -0
  125. package/dist/primitives/select/aparte-select.d.ts +74 -0
  126. package/dist/primitives/select/aparte-select.d.ts.map +1 -0
  127. package/dist/primitives/select/index.d.ts +9 -0
  128. package/dist/primitives/select/index.d.ts.map +1 -0
  129. package/dist/renderers/index.d.ts +5 -0
  130. package/dist/renderers/index.d.ts.map +1 -0
  131. package/dist/renderers/segment-renderers.d.ts +31 -0
  132. package/dist/renderers/segment-renderers.d.ts.map +1 -0
  133. package/dist/runtime/message-repository.d.ts +111 -0
  134. package/dist/runtime/message-repository.d.ts.map +1 -0
  135. package/dist/transport/backend-handler.d.ts +50 -0
  136. package/dist/transport/backend-handler.d.ts.map +1 -0
  137. package/dist/transport/backend-transport.d.ts +39 -0
  138. package/dist/transport/backend-transport.d.ts.map +1 -0
  139. package/dist/transport/direct-transport.d.ts +36 -0
  140. package/dist/transport/direct-transport.d.ts.map +1 -0
  141. package/dist/transport/index.d.ts +6 -0
  142. package/dist/transport/index.d.ts.map +1 -0
  143. package/dist/transport/types.d.ts +73 -0
  144. package/dist/transport/types.d.ts.map +1 -0
  145. package/dist/types/chat.d.ts +223 -0
  146. package/dist/types/chat.d.ts.map +1 -0
  147. package/dist/types/errors.d.ts +25 -0
  148. package/dist/types/errors.d.ts.map +1 -0
  149. package/dist/types/event-map.d.ts +41 -0
  150. package/dist/types/event-map.d.ts.map +1 -0
  151. package/dist/types/events.d.ts +290 -0
  152. package/dist/types/events.d.ts.map +1 -0
  153. package/dist/types/imperative-api.d.ts +38 -0
  154. package/dist/types/imperative-api.d.ts.map +1 -0
  155. package/dist/types/index.d.ts +22 -0
  156. package/dist/types/index.d.ts.map +1 -0
  157. package/dist/types/model-provider.d.ts +229 -0
  158. package/dist/types/model-provider.d.ts.map +1 -0
  159. package/dist/types/models.d.ts +173 -0
  160. package/dist/types/models.d.ts.map +1 -0
  161. package/dist/types/parsers.d.ts +42 -0
  162. package/dist/types/parsers.d.ts.map +1 -0
  163. package/dist/types/providers.d.ts +93 -0
  164. package/dist/types/providers.d.ts.map +1 -0
  165. package/dist/types/segments.d.ts +221 -0
  166. package/dist/types/segments.d.ts.map +1 -0
  167. package/dist/types/theming.d.ts +44 -0
  168. package/dist/types/theming.d.ts.map +1 -0
  169. package/dist/types/tools.d.ts +98 -0
  170. package/dist/types/tools.d.ts.map +1 -0
  171. package/dist/utils/assert-never.d.ts +9 -0
  172. package/dist/utils/assert-never.d.ts.map +1 -0
  173. package/dist/utils/css-escape.d.ts +15 -0
  174. package/dist/utils/css-escape.d.ts.map +1 -0
  175. package/package.json +68 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/primitives/select/aparte-option.ts","../src/primitives/select/aparte-optgroup.ts","../src/primitives/select/aparte-select.ts","../src/primitives/progress-spinner/aparte-progress-spinner.ts","../src/components/chat/aparte-chat.ts","../src/utils/css-escape.ts","../src/components/bubble/aparte-chat-bubble.ts","../src/components/status/aparte-chat-status.ts","../src/components/viewport/aparte-chat-viewport.ts","../src/components/composer/aparte-composer.ts","../src/components/composer/aparte-composer-input.ts","../src/components/composer/aparte-composer-send.ts","../src/components/composer/aparte-composer-cancel.ts","../src/components/composer/aparte-composer-attachments.ts","../src/components/composer/aparte-composer-add-attachment.ts","../src/components/composer/aparte-composer-action.ts","../src/components/conversation-list/aparte-conversation-list.ts","../src/components/elicitation/aparte-elicitation.ts","../src/index.ts"],"sourcesContent":["/**\n * AparteOption\n * \n * Option element for aparte-select dropdown.\n * \n * @element aparte-option\n * @attr {string} value - Option value\n * @attr {boolean} disabled - Disabled state\n * @attr {boolean} selected - Selected state\n */\n\nexport class AparteOption extends HTMLElement {\n static get observedAttributes(): string[] {\n return ['value', 'disabled', 'selected', 'data-status'];\n }\n\n connectedCallback(): void {\n this.setAttribute('role', 'option');\n this._updateAriaSelected();\n this._updateStatusDot();\n }\n\n attributeChangedCallback(name: string): void {\n if (name === 'selected') {\n this._updateAriaSelected();\n }\n if (name === 'disabled') {\n this.setAttribute('aria-disabled', this.hasAttribute('disabled') ? 'true' : 'false');\n }\n if (name === 'data-status') {\n this._updateStatusDot();\n }\n }\n\n get value(): string {\n return this.getAttribute('value') || this.textContent?.trim() || '';\n }\n\n set value(val: string) {\n this.setAttribute('value', val);\n }\n\n get label(): string {\n // Use only the first text node, ignoring injected spans (e.g. status dot)\n const textNode = Array.from(this.childNodes).find(n => n.nodeType === Node.TEXT_NODE);\n return textNode?.textContent?.trim() || this.value;\n }\n\n get disabled(): boolean {\n return this.hasAttribute('disabled');\n }\n\n set disabled(val: boolean) {\n if (val) {\n this.setAttribute('disabled', '');\n } else {\n this.removeAttribute('disabled');\n }\n }\n\n get selected(): boolean {\n return this.hasAttribute('selected');\n }\n\n set selected(val: boolean) {\n if (val) {\n this.setAttribute('selected', '');\n } else {\n this.removeAttribute('selected');\n }\n }\n\n private _updateAriaSelected(): void {\n this.setAttribute('aria-selected', this.selected ? 'true' : 'false');\n }\n\n private _updateStatusDot(): void {\n const status = this.getAttribute('data-status');\n let dot = this.querySelector<HTMLSpanElement>('.aparte-status-dot');\n\n if (!status) {\n dot?.remove();\n return;\n }\n\n if (!dot) {\n dot = document.createElement('span');\n dot.className = 'aparte-status-dot';\n dot.setAttribute('aria-hidden', 'true');\n this.appendChild(dot);\n }\n\n dot.setAttribute('data-status', status);\n }\n}\n\n// Register\nif (!customElements.get('aparte-option')) {\n customElements.define('aparte-option', AparteOption);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'aparte-option': AparteOption;\n }\n}\n","/**\n * AparteOptgroup\n * \n * Option group element for aparte-select dropdown.\n * \n * @element aparte-optgroup\n * @attr {string} label - Group label\n * @attr {boolean} collapsible - Allow collapse/expand\n * @attr {boolean} collapsed - Collapsed state\n */\n\nexport class AparteOptgroup extends HTMLElement {\n static get observedAttributes(): string[] {\n return ['label', 'collapsible', 'collapsed', 'loading'];\n }\n\n connectedCallback(): void {\n this.setAttribute('role', 'group');\n this._render();\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n\n if (name === 'collapsed') {\n this._updateCollapsedState();\n }\n\n if (this.isConnected) {\n this._render();\n }\n }\n\n get label(): string {\n return this.getAttribute('label') || '';\n }\n\n set label(val: string) {\n this.setAttribute('label', val);\n }\n\n get collapsible(): boolean {\n return this.hasAttribute('collapsible');\n }\n\n get collapsed(): boolean {\n return this.hasAttribute('collapsed');\n }\n\n set collapsed(val: boolean) {\n if (val) {\n this.setAttribute('collapsed', '');\n } else {\n this.removeAttribute('collapsed');\n }\n }\n\n get loading(): boolean {\n return this.hasAttribute('loading');\n }\n\n set loading(val: boolean) {\n if (val) this.setAttribute('loading', '');\n else this.removeAttribute('loading');\n }\n\n private _render(): void {\n // Only render header if we have a label\n if (this.label) {\n const existingHeader = this.querySelector('.aparte-optgroup-header');\n if (!existingHeader) {\n const header = document.createElement('div');\n header.className = 'aparte-optgroup-header';\n header.setAttribute('aria-label', this.label);\n // `label` is an attribute value — with the model-selector it carries a\n // provider-supplied name — so it goes through textContent, never\n // innerHTML (a hostile name would otherwise inject here).\n const labelSpan = document.createElement('span');\n labelSpan.className = 'aparte-optgroup-label';\n labelSpan.textContent = this.label;\n header.appendChild(labelSpan);\n\n if (this.collapsible) {\n const chevron = document.createElement('span');\n chevron.className = 'aparte-optgroup-chevron';\n header.appendChild(chevron);\n header.style.cursor = 'pointer';\n header.addEventListener('click', (e) => {\n e.stopPropagation();\n this._toggleCollapse();\n });\n }\n\n this.insertBefore(header, this.firstChild);\n }\n }\n\n // Update loading state\n this._updateLoadingState();\n\n // Update collapsed state\n this._updateCollapsedState();\n }\n\n private _updateLoadingState(): void {\n let loader = this.querySelector('.aparte-optgroup-loader');\n if (this.loading) {\n if (!loader) {\n loader = document.createElement('div');\n loader.className = 'aparte-optgroup-loader';\n loader.innerHTML = '<span class=\"aparte-spinner-small\"></span> Fetching models...';\n this.appendChild(loader);\n }\n } else if (loader) {\n loader.remove();\n }\n }\n\n private _toggleCollapse(): void {\n this.collapsed = !this.collapsed;\n\n // Dispatch event before updating UI to allow parent to react (e.g. fetch data)\n this.dispatchEvent(new CustomEvent('aparte-optgroup-toggle', {\n bubbles: true,\n composed: true,\n detail: {\n label: this.label,\n collapsed: this.collapsed\n }\n }));\n\n this._updateCollapsedState();\n }\n\n private _updateCollapsedState(): void {\n const options = this.querySelectorAll('aparte-option');\n options.forEach(opt => {\n (opt as HTMLElement).style.display = this.collapsed ? 'none' : '';\n });\n }\n}\n\n// Register\nif (!customElements.get('aparte-optgroup')) {\n customElements.define('aparte-optgroup', AparteOptgroup);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'aparte-optgroup': AparteOptgroup;\n }\n}\n","/**\n * AparteSelect\n * \n * Dropdown select component for AparteCore.\n * Vanilla Web Component with configurable features.\n * \n * @element aparte-select\n * @attr {string} value - Selected value\n * @attr {string} placeholder - Placeholder text\n * @attr {boolean} disabled - Disabled state\n * @attr {boolean} grouped - Enable optgroup mode\n * @attr {boolean} searchable - Enable search filter\n * @attr {boolean} open - Dropdown open state\n * \n * @fires aparte-select-change - Fired when selection changes\n * @fires aparte-select-open - Fired when dropdown opens\n * @fires aparte-select-close - Fired when dropdown closes\n */\n\nimport './aparte-option.js';\nimport './aparte-optgroup.js';\n\nexport interface AparteSelectChangeDetail {\n value: string;\n label: string;\n previousValue: string;\n}\n\nexport class AparteSelect extends HTMLElement {\n private static _optIdSeq = 0;\n\n private _value = '';\n private _isOpen = false;\n private _activeIndex = -1;\n private _trigger: HTMLElement | null = null;\n private _dropdown: HTMLElement | null = null;\n private _searchInput: HTMLInputElement | null = null;\n private _observer: MutationObserver | null = null;\n\n // Bound handlers for cleanup\n private _boundHandleDocumentClick = this._handleDocumentClick.bind(this);\n private _boundHandleKeydown = this._handleKeydown.bind(this);\n\n static get observedAttributes(): string[] {\n return ['value', 'placeholder', 'disabled', 'grouped', 'searchable', 'open'];\n }\n\n connectedCallback(): void {\n this._value = this.getAttribute('value') || '';\n this._isOpen = this.hasAttribute('open');\n this._render();\n this._setupEventListeners();\n this._setupMutationObserver();\n }\n\n disconnectedCallback(): void {\n document.removeEventListener('click', this._boundHandleDocumentClick);\n document.removeEventListener('keydown', this._boundHandleKeydown);\n this._observer?.disconnect();\n }\n\n attributeChangedCallback(name: string, oldValue: string, newValue: string): void {\n if (!this.isConnected) return;\n\n if (name === 'value' && oldValue !== newValue && newValue !== this._value) {\n this._value = newValue || '';\n this._updateTriggerLabel();\n }\n if (name === 'open') {\n this._isOpen = this.hasAttribute('open');\n if (this._isOpen) {\n this._dropdown?.removeAttribute('hidden');\n this._searchInput?.focus();\n } else {\n this._dropdown?.setAttribute('hidden', '');\n }\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Public API\n // ─────────────────────────────────────────────────────────────────────────\n\n get value(): string {\n return this._value;\n }\n\n set value(val: string) {\n if (val === this._value) return;\n const previousValue = this._value;\n this._value = val;\n this.setAttribute('value', val);\n this._updateTriggerLabel();\n this._emitChange(previousValue);\n }\n\n get open(): boolean {\n return this._isOpen;\n }\n\n set open(val: boolean) {\n if (val) {\n this.setAttribute('open', '');\n } else {\n this.removeAttribute('open');\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Rendering\n // ─────────────────────────────────────────────────────────────────────────\n\n private _render(): void {\n const placeholder = this.getAttribute('placeholder') || 'Select...';\n const searchable = this.hasAttribute('searchable');\n\n // Check if already rendered (has dropdown structure)\n if (this.querySelector('.aparte-select-dropdown')) {\n this._updateTriggerLabel();\n return;\n }\n\n // First render: capture any slotted children before modifying DOM\n const slottedChildren = Array.from(this.children);\n\n // Create wrapper structure\n const trigger = document.createElement('div');\n trigger.className = 'aparte-select-trigger';\n trigger.setAttribute('tabindex', '0');\n trigger.setAttribute('role', 'combobox');\n trigger.setAttribute('aria-haspopup', 'listbox');\n trigger.setAttribute('aria-expanded', 'false');\n // The label is placeholder text (consumer/attribute-supplied) → textContent,\n // same path as _updateTriggerLabel(), never innerHTML. Only the static SVG\n // chevron uses innerHTML.\n const labelSpan = document.createElement('span');\n labelSpan.className = 'aparte-select-label';\n labelSpan.textContent = placeholder;\n const chevronSpan = document.createElement('span');\n chevronSpan.className = 'aparte-select-chevron';\n chevronSpan.innerHTML = `<svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"currentColor\"><path d=\"M2.5 4.5L6 8L9.5 4.5\" stroke=\"currentColor\" stroke-width=\"1.5\" fill=\"none\" stroke-linecap=\"round\"/></svg>`;\n trigger.append(labelSpan, chevronSpan);\n\n const dropdown = document.createElement('div');\n dropdown.className = 'aparte-select-dropdown';\n dropdown.setAttribute('role', 'listbox');\n dropdown.hidden = !this._isOpen;\n\n if (searchable) {\n const searchInput = document.createElement('input');\n searchInput.type = 'text';\n searchInput.className = 'aparte-select-search';\n searchInput.placeholder = 'Search...';\n dropdown.appendChild(searchInput);\n }\n\n const optionsContainer = document.createElement('div');\n optionsContainer.className = 'aparte-select-options';\n\n // Move slotted children (aparte-option, aparte-optgroup) into options container\n slottedChildren.forEach(child => {\n if (child.tagName === 'APARTE-OPTION' || child.tagName === 'APARTE-OPTGROUP') {\n optionsContainer.appendChild(child);\n }\n });\n\n dropdown.appendChild(optionsContainer);\n\n // Clear and rebuild DOM\n this._observer?.disconnect();\n this.innerHTML = '';\n this.appendChild(trigger);\n this.appendChild(dropdown);\n\n this._trigger = trigger;\n this._dropdown = dropdown;\n this._searchInput = dropdown.querySelector('.aparte-select-search');\n\n if (this.isConnected) {\n this._setupMutationObserver();\n }\n\n // Update label based on current value\n this._updateTriggerLabel();\n }\n\n private _setupMutationObserver(): void {\n this._observer = new MutationObserver(() => {\n this._updateDropdownContent();\n });\n\n this._observer.observe(this, { childList: true });\n }\n\n private _updateDropdownContent(): void {\n // If trigger is gone, the component was likely wiped by innerHTML\n if (!this._trigger || !this.contains(this._trigger)) {\n this._render();\n return;\n }\n\n const optionsContainer = this.querySelector('.aparte-select-options');\n if (!optionsContainer) {\n // If internal UI is present but container is gone\n this._render();\n return;\n }\n\n // Collect all potential options from light DOM\n // (those aren't internal UI elements)\n const lightChildren = Array.from(this.children).filter(child =>\n child.className !== 'aparte-select-trigger' &&\n child.className !== 'aparte-select-dropdown'\n );\n\n if (lightChildren.length === 0) return;\n\n // Pause observer to prevent self-triggering loop\n this._observer?.disconnect();\n\n // Clear container (but keep internal stuff if any)\n optionsContainer.innerHTML = '';\n\n // Move/Append children to container\n lightChildren.forEach(child => {\n optionsContainer.appendChild(child);\n });\n\n // Resume observer\n if (this.isConnected) {\n this._observer?.observe(this, { childList: true });\n }\n\n this._updateTriggerLabel();\n }\n\n private _setupEventListeners(): void {\n // Trigger click\n this._trigger?.addEventListener('click', () => this._toggle());\n\n // Trigger keyboard\n this._trigger?.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n // When open, Enter/Space selects the active option — handled by\n // the document-level nav handler. Only toggle when closed, so we\n // don't close the dropdown on the very keystroke meant to select.\n if (this._isOpen) return;\n e.preventDefault();\n this._toggle();\n }\n if (e.key === 'ArrowDown' && !this._isOpen) {\n e.preventDefault();\n this._openDropdown();\n }\n });\n\n // Option selection\n this.addEventListener('click', (e) => {\n const option = (e.target as HTMLElement).closest('aparte-option');\n if (option && !option.hasAttribute('disabled')) {\n this._selectOption(option as HTMLElement);\n }\n });\n\n // Search filter\n this._searchInput?.addEventListener('input', (e) => {\n const query = (e.target as HTMLInputElement).value.toLowerCase();\n this._filterOptions(query);\n });\n\n // Close on outside click\n document.addEventListener('click', this._boundHandleDocumentClick);\n\n // Keyboard navigation\n document.addEventListener('keydown', this._boundHandleKeydown);\n }\n\n private _handleDocumentClick(e: Event): void {\n if (!this.contains(e.target as Node)) {\n this._closeDropdown();\n }\n }\n\n private _handleKeydown(e: KeyboardEvent): void {\n if (!this._isOpen) return;\n\n // Home/End move the caret when typing in the search box; only hijack\n // them for option navigation when focus is not in the search field.\n const inSearch = document.activeElement === this._searchInput;\n\n switch (e.key) {\n case 'Escape':\n e.preventDefault();\n this._closeDropdown();\n this._trigger?.focus();\n break;\n case 'ArrowDown':\n e.preventDefault();\n this._moveActive(1);\n break;\n case 'ArrowUp':\n e.preventDefault();\n this._moveActive(-1);\n break;\n case 'Home':\n if (inSearch) break;\n e.preventDefault();\n this._setActive(0);\n break;\n case 'End':\n if (inSearch) break;\n e.preventDefault();\n this._setActive(this._visibleOptions().length - 1);\n break;\n case 'Enter': {\n const active = this._visibleOptions()[this._activeIndex];\n if (active) {\n e.preventDefault();\n this._selectOption(active);\n }\n break;\n }\n }\n }\n\n /** Non-disabled, non-filtered options in DOM order. */\n private _visibleOptions(): HTMLElement[] {\n return Array.from(this.querySelectorAll<HTMLElement>('aparte-option')).filter(\n opt => !opt.hasAttribute('disabled') && opt.style.display !== 'none',\n );\n }\n\n /** Move the active (keyboard-highlighted) option by `delta`, clamped. */\n private _moveActive(delta: number): void {\n const opts = this._visibleOptions();\n if (opts.length === 0) return;\n const base = this._activeIndex < 0 ? (delta > 0 ? -1 : 0) : this._activeIndex;\n this._setActive(base + delta);\n }\n\n /** Highlight the option at `index` (clamped) and point aria-activedescendant at it. */\n private _setActive(index: number): void {\n const all = this.querySelectorAll<HTMLElement>('aparte-option');\n all.forEach(o => o.removeAttribute('data-active'));\n\n const opts = this._visibleOptions();\n if (opts.length === 0) {\n this._activeIndex = -1;\n this._trigger?.removeAttribute('aria-activedescendant');\n return;\n }\n const clamped = Math.max(0, Math.min(index, opts.length - 1));\n this._activeIndex = clamped;\n\n const active = opts[clamped]!;\n if (!active.id) active.id = `aparte-option-${++AparteSelect._optIdSeq}`;\n active.setAttribute('data-active', '');\n this._trigger?.setAttribute('aria-activedescendant', active.id);\n active.scrollIntoView?.({ block: 'nearest' });\n }\n\n /** Clear the keyboard highlight (on close). */\n private _clearActive(): void {\n this._activeIndex = -1;\n this._trigger?.removeAttribute('aria-activedescendant');\n this.querySelectorAll('aparte-option').forEach(o => o.removeAttribute('data-active'));\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Actions\n // ─────────────────────────────────────────────────────────────────────────\n\n private _toggle(): void {\n if (this._isOpen) {\n this._closeDropdown();\n } else {\n this._openDropdown();\n }\n }\n\n private _openDropdown(): void {\n if (this.hasAttribute('disabled')) return;\n\n this._isOpen = true;\n this._dropdown?.removeAttribute('hidden');\n this._trigger?.setAttribute('aria-expanded', 'true');\n this.setAttribute('open', '');\n\n // Smart Positioning\n this._updatePosition();\n\n // Focus search if available\n this._searchInput?.focus();\n\n // Seed the keyboard highlight on the current selection (or the first\n // option) so ArrowUp/Down have an anchor and screen readers announce it.\n const opts = this._visibleOptions();\n const selectedIdx = opts.findIndex(o => o.getAttribute('value') === this._value);\n this._setActive(selectedIdx >= 0 ? selectedIdx : 0);\n\n this.dispatchEvent(new CustomEvent('aparte-select-open', { bubbles: true }));\n }\n\n private _closeDropdown(): void {\n this._isOpen = false;\n this._clearActive();\n this._dropdown?.setAttribute('hidden', '');\n this._trigger?.setAttribute('aria-expanded', 'false');\n this.removeAttribute('open');\n this.removeAttribute('position'); // Reset position attribute\n\n // Clear position styles set by _updatePosition\n if (this._dropdown) {\n this._dropdown.style.top = '';\n this._dropdown.style.bottom = '';\n this._dropdown.style.left = '';\n this._dropdown.style.width = '';\n }\n\n // Clear search\n if (this._searchInput) {\n this._searchInput.value = '';\n this._filterOptions('');\n }\n\n this.dispatchEvent(new CustomEvent('aparte-select-close', { bubbles: true }));\n }\n\n private _updatePosition(): void {\n if (!this._dropdown || !this._trigger) return;\n\n const rect = this._trigger.getBoundingClientRect();\n const dropdownHeight = this._dropdown.offsetHeight || 300;\n const viewportHeight = window.innerHeight;\n const spaceBelow = viewportHeight - rect.bottom;\n const GAP = 4; // px gap between trigger and dropdown\n\n // Always size to trigger width\n this._dropdown.style.left = `${rect.left}px`;\n this._dropdown.style.width = `${rect.width}px`;\n\n // Decide whether to open upward or downward\n if (spaceBelow < dropdownHeight && rect.top > dropdownHeight) {\n // Open upward\n this._dropdown.style.top = '';\n this._dropdown.style.bottom = `${viewportHeight - rect.top + GAP}px`;\n this.setAttribute('position', 'top');\n } else {\n // Open downward\n this._dropdown.style.top = `${rect.bottom + GAP}px`;\n this._dropdown.style.bottom = '';\n this.removeAttribute('position');\n }\n }\n\n private _selectOption(option: HTMLElement): void {\n const value = option.getAttribute('value') || option.textContent?.trim() || '';\n const previousValue = this._value;\n\n this._value = value;\n this.setAttribute('value', value);\n this._updateTriggerLabel();\n this._closeDropdown();\n this._emitChange(previousValue);\n this._trigger?.focus();\n }\n\n private _updateTriggerLabel(): void {\n const labelEl = this._trigger?.querySelector('.aparte-select-label');\n if (labelEl) {\n const selectedLabel = this._getSelectedLabel();\n labelEl.textContent = selectedLabel || this.getAttribute('placeholder') || 'Select...';\n }\n\n // Update selected state on options\n const options = this.querySelectorAll('aparte-option');\n options.forEach(opt => {\n const isSelected = opt.getAttribute('value') === this._value;\n if (isSelected) {\n opt.setAttribute('selected', '');\n } else {\n opt.removeAttribute('selected');\n }\n });\n }\n\n private _getSelectedLabel(): string {\n // Match by property, not an interpolated attribute selector — a value with\n // `\"`/`]` (e.g. a remote model id) would make querySelector throw SyntaxError.\n for (const opt of this.querySelectorAll('aparte-option')) {\n if (opt.getAttribute('value') === this._value) return opt.textContent?.trim() || '';\n }\n return '';\n }\n\n private _filterOptions(query: string): void {\n const options = this.querySelectorAll('aparte-option');\n options.forEach(opt => {\n const label = opt.textContent?.toLowerCase() || '';\n const matches = label.includes(query);\n (opt as HTMLElement).style.display = matches ? '' : 'none';\n });\n // Re-anchor the keyboard highlight on the first still-visible option.\n if (this._isOpen) this._setActive(0);\n }\n\n private _emitChange(previousValue: string): void {\n const detail: AparteSelectChangeDetail = {\n value: this._value,\n label: this._getSelectedLabel(),\n previousValue\n };\n\n this.dispatchEvent(new CustomEvent<AparteSelectChangeDetail>('aparte-select-change', {\n bubbles: true,\n composed: true,\n detail\n }));\n }\n}\n\n// Register\nif (!customElements.get('aparte-select')) {\n customElements.define('aparte-select', AparteSelect);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'aparte-select': AparteSelect;\n }\n}\n","/**\n * AparteProgressSpinner\n *\n * Circular progress spinner web component.\n * - Indeterminate (no `value` attribute): continuous rotation animation\n * - Determinate (`value=\"0–100\"`): fills the arc proportionally\n *\n * @element aparte-progress-spinner\n * @attr {number} value - Progress percentage 0–100 (omit for indeterminate)\n *\n * @cssvar --aparte-spinner-size Size of the spinner. Default: 14px\n * @cssvar --aparte-spinner-stroke Stroke width in SVG units. Default: 2.5\n * @cssvar --aparte-spinner-color Fill arc stroke color. Default: currentColor\n * @cssvar --aparte-spinner-track Track arc stroke color. Default: 15% currentColor\n */\nexport class AparteProgressSpinner extends HTMLElement {\n static get observedAttributes(): string[] { return ['value']; }\n\n /** Radius of the SVG circle (viewBox is 0 0 24 24, center at 12,12) */\n private readonly _r = 9;\n private get _circ(): number { return 2 * Math.PI * this._r; }\n\n connectedCallback(): void { this._render(); }\n attributeChangedCallback(): void { this._render(); }\n\n private _render(): void {\n const raw = this.getAttribute('value');\n const value = raw !== null\n ? Math.min(100, Math.max(0, parseFloat(raw) || 0))\n : null;\n\n this.setAttribute('role', 'progressbar');\n this.setAttribute('aria-valuemin', '0');\n this.setAttribute('aria-valuemax', '100');\n if (value !== null) {\n this.setAttribute('aria-valuenow', String(value));\n } else {\n this.removeAttribute('aria-valuenow');\n }\n\n // Determinate: dashoffset shrinks from circ→0 as value goes 0→100\n const dashoffset = value !== null ? this._circ * (1 - value / 100) : 0;\n // Indeterminate: fixed partial arc (~72% of circumference)\n const dasharray = value !== null\n ? `${this._circ.toFixed(2)}`\n : `${(this._circ * 0.72).toFixed(2)} ${(this._circ * 0.28).toFixed(2)}`;\n\n this.innerHTML = `<svg viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\"><circle class=\"aparte-spinner-track\" cx=\"12\" cy=\"12\" r=\"${this._r}\"/><circle class=\"aparte-spinner-fill\" cx=\"12\" cy=\"12\" r=\"${this._r}\" stroke-dasharray=\"${dasharray}\" stroke-dashoffset=\"${dashoffset.toFixed(2)}\"/></svg>`;\n }\n}\n\nif (!customElements.get('aparte-progress-spinner')) {\n customElements.define('aparte-progress-spinner', AparteProgressSpinner);\n}\n","import type { AparteChatViewport } from '../viewport/aparte-chat-viewport.js';\nimport type { AparteComposer } from '../composer/aparte-composer.js';\n\n/**\n * AparteChat - The Shell\n *\n * The container element for a chat. Wrap a `<aparte-chat-viewport>` and a\n * `<aparte-composer>` in it and it lays them out as a flex column — the viewport\n * grows and scrolls, the composer sits below. Provide your own children for full\n * control (custom composer, extra buttons), or leave it empty and it fills in a\n * sensible default composition. Uses Light DOM for global CSS styling.\n *\n * Being a component (not a bare `<div>`), it also owns behaviour a wrapper div\n * can't: with `center-empty`, it watches its own viewport and keeps the composer\n * centered as a welcome state until the first message, then slides to the normal\n * layout — no external JavaScript.\n *\n * Presentational only: it does NOT wire a transport/client. Attach an\n * `AparteClient`, or handle `aparte-send` yourself, as with the primitives.\n * Size the element via CSS (a height, or let it fill a sized parent).\n *\n * @element aparte-chat\n * @attr placeholder - Placeholder for the composer input (default composition)\n * @attr disabled - Disables the composer\n * @attr center-empty - Center the composer as a welcome state until the first message, then slide to the normal layout\n */\nexport class AparteChat extends HTMLElement {\n static get observedAttributes(): string[] {\n return ['placeholder', 'disabled', 'center-empty'];\n }\n\n private _observer: MutationObserver | null = null;\n\n connectedCallback(): void {\n this._render();\n this._forwardAttr('placeholder');\n this._forwardAttr('disabled');\n this._syncEmptyWatch();\n }\n\n disconnectedCallback(): void {\n this._observer?.disconnect();\n this._observer = null;\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n if (name === 'center-empty') {\n this._syncEmptyWatch();\n return;\n }\n // placeholder / disabled forward to the inner composer. An explicit removal\n // mirrors through; a never-set attribute is left alone (so a caller-provided\n // composer keeps its own).\n const composer = this.querySelector('aparte-composer');\n if (!composer) return;\n if (newValue !== null) composer.setAttribute(name, newValue);\n else composer.removeAttribute(name);\n }\n\n /** The message viewport (yours or the default), or `null` before connect. */\n get viewport(): AparteChatViewport | null {\n return this.querySelector('aparte-chat-viewport');\n }\n\n /** The composer (yours or the default), or `null` before connect. */\n get composer(): AparteComposer | null {\n return this.querySelector('aparte-composer');\n }\n\n private _render(): void {\n // A framework wrapper renders the composition itself — and its children do not\n // exist yet when this runs (the element is upgraded on insert, before the\n // framework's template renders), so the viewport check below can't see them.\n // `framework-managed` is the wrapper's explicit \"hands off\" signal: without it\n // the default composition below would be injected UNDER the framework's own.\n if (this.hasAttribute('framework-managed')) return;\n\n // Author-provided composition wins — if a viewport is already inside, use the\n // children as given and only lay them out (via CSS). Otherwise fill in a\n // default viewport + composer so the empty tag \"just works\".\n if (this.querySelector('aparte-chat-viewport')) return;\n\n // The composer's `placeholder` is read by its input via `closest()` at upgrade\n // time (no event), so it must be on the element in the initial markup.\n const placeholder = this.getAttribute('placeholder');\n const composerAttrs =\n (placeholder !== null ? ` placeholder=\"${this._escapeAttr(placeholder)}\"` : '') +\n (this.hasAttribute('disabled') ? ' disabled' : '');\n\n this.innerHTML = `\n <aparte-chat-viewport></aparte-chat-viewport>\n <aparte-composer${composerAttrs}>\n <div class=\"aparte-composer-shell\">\n <div class=\"aparte-composer-row\">\n <aparte-composer-input></aparte-composer-input>\n <aparte-composer-send></aparte-composer-send>\n </div>\n </div>\n </aparte-composer>\n `;\n }\n\n /** Set an attribute on the inner composer only when the shell carries it. */\n private _forwardAttr(name: string): void {\n if (!this.hasAttribute(name)) return;\n this.querySelector('aparte-composer')?.setAttribute(name, this.getAttribute(name) ?? '');\n }\n\n /** Start/stop watching the viewport so `center-empty` toggles itself. */\n private _syncEmptyWatch(): void {\n this._observer?.disconnect();\n this._observer = null;\n\n if (!this.hasAttribute('center-empty')) {\n this.removeAttribute('data-empty');\n return;\n }\n\n const viewport = this.querySelector('aparte-chat-viewport');\n if (!viewport) return;\n\n this._updateEmpty();\n // A message is an <aparte-chat-bubble>; watch the viewport for the first one.\n this._observer = new MutationObserver(() => this._updateEmpty());\n this._observer.observe(viewport, { childList: true, subtree: true });\n }\n\n private _updateEmpty(): void {\n const viewport = this.querySelector('aparte-chat-viewport');\n const empty = !viewport || !viewport.querySelector('aparte-chat-bubble');\n this.toggleAttribute('data-empty', empty);\n }\n\n private _escapeAttr(value: string): string {\n return value.replace(/&/g, '&amp;').replace(/\"/g, '&quot;').replace(/</g, '&lt;');\n }\n}\n\n// Register the custom element\nif (!customElements.get('aparte-chat')) {\n customElements.define('aparte-chat', AparteChat);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'aparte-chat': AparteChat;\n }\n}\n","/**\n * Escape a value for safe interpolation into a DOUBLE-QUOTED CSS attribute\n * selector: `[attr=\"${cssEscape(value)}\"]`. Inside a quoted CSS string only `\"`\n * (which would end the string) and `\\` (the escape char) are special, so escaping\n * those two is sufficient AND correct here — unlike `CSS.escape`, which targets the\n * UNquoted identifier context and over-escapes inside quotes (breaking the match),\n * and which also needs the `CSS` global (absent in SSR / some test runtimes).\n *\n * Segment/message ids are random UUIDs in the default flow, so this is\n * defense-in-depth: a hostile, stream-supplied id containing `\"` (e.g. a tool-call\n * id) can no longer break out of the selector into a `SyntaxError` or a\n * selector-list that mis-targets another element.\n */\nexport function cssEscape(value: string): string {\n return value.replace(/[\"\\\\]/g, '\\\\$&');\n}\n","import type {\n AparteBubbleRole,\n AparteSegment,\n AparteAttachment,\n AparteBranchNavigateEventDetail,\n AparteRetryEventDetail,\n AparteEditEventDetail,\n AparteFeedbackEventDetail,\n AparteActionEventDetail,\n AparteMessageInfoEventDetail,\n AparteUsage,\n AparteMessage,\n} from '../../types/index.js';\nimport { getSegmentRenderer } from '../../renderers/index.js';\nimport { AparteConfigClass } from '../../config/aparte-config.js';\nimport { resolveConfig, runWithConfig } from '../../config/config-context.js';\nimport { cssEscape } from '../../utils/css-escape.js';\nimport type { AparteComposerInput } from '../composer/aparte-composer-input.js';\n\n/**\n * Warn ONCE when a segment has no registered renderer — the classic\n * \"I forgot registerDefaultRenderers()\" trap that otherwise fails silently as a\n * `[Unknown segment type]` box.\n */\nlet _warnedNoRenderer = false;\nfunction warnMissingRenderer(type: string): void {\n if (_warnedNoRenderer) return;\n _warnedNoRenderer = true;\n console.warn(`[aparte] No renderer for segment \"${type}\". Did you call registerDefaultRenderers() from @aparte/core?`);\n}\n\n/**\n * Normalize a segment renderer's output to a single element. Renderers may return\n * an HTML **string** (parsed via innerHTML — the built-in renderers) or a ready\n * **HTMLElement** (used directly, so custom renderers can wire event listeners /\n * framework nodes with no innerHTML XSS surface). See {@link AparteSegmentRenderer}.\n */\nfunction segmentRenderResultToElement(result: string | HTMLElement): HTMLElement | null {\n if (result instanceof HTMLElement) return result;\n const wrapper = document.createElement('div');\n wrapper.innerHTML = result;\n return wrapper.firstElementChild as HTMLElement | null;\n}\n\n/** Lucide \"info\" glyph — inline so the action bar needs no icon-provider key. */\nconst INFO_ICON_SVG =\n '<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"15\" height=\"15\" viewBox=\"0 0 24 24\" ' +\n 'fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" ' +\n 'stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"/><path d=\"M12 16v-4\"/>' +\n '<path d=\"M12 8h.01\"/></svg>';\n\n/**\n * AparteChatBubble - The Render\n * \n * Message component supporting both simple content and rich segments.\n * Uses Light DOM for global CSS styling.\n */\nexport class AparteChatBubble extends HTMLElement {\n private _contentEl: HTMLDivElement | null = null;\n private _segmentsEl: HTMLDivElement | null = null;\n private _attachmentsEl: HTMLDivElement | null = null;\n private _actionBarEl: HTMLDivElement | null = null;\n private _branchPickerEl: HTMLDivElement | null = null;\n private _content = '';\n private _streaming = false;\n private _segments: AparteSegment[] = [];\n private _role: AparteBubbleRole = 'assistant';\n private _attachments: AparteAttachment[] = [];\n private _usage: AparteUsage | null = null;\n /** Cleanup returned by the avatar provider — called on disconnect/re-render. */\n private _avatarCleanup: (() => void) | null = null;\n /** Sibling count for tree-based branch navigation (set by setSiblings()) */\n private _siblingCount = 1;\n /** Sibling index for tree-based branch navigation (set by setSiblings()) */\n private _siblingIndex = 0;\n /** True while the user-message inline editor is open. */\n private _editing = false;\n /** The live inline editor (the composer's contenteditable primitive), present only while `_editing`. */\n private _editInput: AparteComposerInput | null = null;\n\n static get observedAttributes(): string[] {\n // Both `data-role` (preferred, set by Angular wrapper) and `role` (legacy\n // / direct usage) feed into the same _role state. The host element gets\n // its own `role=\"article\"` set in _render() for ARIA compliance — that\n // is filtered in attributeChangedCallback so it doesn't loop back as a\n // bubble role of \"article\".\n return ['role', 'data-role', 'content', 'timestamp', 'message-id', 'streaming', 'name'];\n }\n\n constructor() {\n super();\n }\n\n // Rebuild the action bar when the global config changes (e.g. a live skin\n // switch calling setBubbleActions / setIconProvider) so already-rendered\n // bubbles pick up the new per-role actions + icons without being re-created.\n private _onConfigChange = (e: Event): void => {\n // Only rebuild for OUR config. An instance-scoped change on another chat —\n // or a global change while we resolve to an instance — must not touch us.\n // A bare dispatch (no detail.config) always rebuilds (e.g. manual notify).\n const detail = (e as CustomEvent).detail as { config?: unknown } | undefined;\n if (detail?.config && detail.config !== this._cfg) return;\n this._updateActionBar();\n };\n\n /**\n * Config governing this bubble: the instance config of the nearest\n * `[data-aparte-host]` boundary, else the global singleton. Resolved live\n * (a single `closest()`) rather than cached — the boundary may be attached\n * AFTER this bubble mounts (AparteChatHost.bind() runs post-mount), so a\n * connect-time cache would freeze the wrong config.\n */\n private get _cfg(): AparteConfigClass {\n return resolveConfig(this);\n }\n\n connectedCallback(): void {\n this._render();\n this._updateContent();\n // Populate the timestamp from the current attribute. Frameworks that set\n // attributes BEFORE the element is connected (e.g. the Svelte wrapper) fire\n // attributeChangedCallback while _render() hasn't created `.aparte-timestamp`\n // yet, so the initial time would otherwise stay blank. No-ops when the\n // attribute is absent (set later → attributeChangedCallback handles it).\n this._updateTimestamp(this.getAttribute('timestamp'));\n window.addEventListener('aparte-config-change', this._onConfigChange);\n }\n\n disconnectedCallback(): void {\n window.removeEventListener('aparte-config-change', this._onConfigChange);\n if (this._avatarCleanup) {\n try { this._avatarCleanup(); } catch { /* ignore */ }\n this._avatarCleanup = null;\n }\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n\n switch (name) {\n case 'role':\n case 'data-role':\n // Skip the ARIA-compliance value we set ourselves in _render().\n // Real bubble roles are 'user' or 'assistant'; anything else is\n // either the 'article' we wrote for accessibility or stale.\n if (newValue === 'article') return;\n if (newValue === 'user' || newValue === 'assistant') {\n this._role = newValue as AparteBubbleRole;\n this._updateRole();\n }\n break;\n case 'content':\n this._content = newValue || '';\n this._updateContent();\n break;\n case 'timestamp':\n this._updateTimestamp(newValue);\n break;\n case 'streaming':\n this._updateStreaming(newValue !== null && newValue !== 'false');\n break;\n case 'name':\n this._updateName();\n break;\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Public API\n // ─────────────────────────────────────────────────────────────────────────\n\n /** Append a token chunk (for streaming) */\n appendToken(chunk: string): void {\n this._content += chunk;\n this._updateContent();\n }\n\n /** Set content directly */\n setContent(content: string): void {\n this._content = content;\n this.setAttribute('content', content);\n this._updateContent();\n }\n\n /** Get current content */\n getContent(): string {\n return this._content;\n }\n\n /** Set segments for rich content */\n setSegments(segments: AparteSegment[]): void {\n this._segments = segments;\n this._renderSegments();\n }\n\n /** Add a segment */\n addSegment(segment: AparteSegment): void {\n this._segments.push(segment);\n this._appendSegmentEl(segment);\n }\n\n /** Update a specific segment */\n updateSegment(segmentId: string, updates: Partial<AparteSegment>): void {\n const index = this._segments.findIndex(s => s.id === segmentId);\n if (index !== -1) {\n const updated = { ...this._segments[index], ...updates } as AparteSegment;\n this._segments[index] = updated;\n this._applySegmentUpdate(segmentId, updated, updates);\n }\n }\n\n /** Append content to a segment */\n appendToSegment(segmentId: string, content: string): void {\n const segment = this._segments.find(s => s.id === segmentId);\n if (segment && 'content' in segment) {\n (segment as { content: string }).content += content;\n this._applySegmentUpdate(segmentId, segment, { content: (segment as AparteSegment & { content: string }).content });\n }\n }\n\n /** Get all segments */\n getSegments(): AparteSegment[] {\n return [...this._segments];\n }\n\n /** Remove a segment by id (e.g. to discard a transient waiting indicator) */\n removeSegment(segmentId: string): void {\n const index = this._segments.findIndex(s => s.id === segmentId);\n if (index !== -1) {\n this._segments.splice(index, 1);\n }\n const el = this._segmentsEl?.querySelector(`[data-segment-id=\"${cssEscape(segmentId)}\"]`);\n el?.remove();\n }\n\n /** Set attachments (chips shown above message content, user role only) */\n setAttachments(attachments: AparteAttachment[]): void {\n this._attachments = attachments;\n this._updateAttachments();\n }\n\n /**\n * Set token usage + timing for this message (assistant only).\n * Renders the info (\"i\") action in the action bar; clicking it opens\n * the app-owned stats popover (`aparte-message-info`).\n */\n setUsage(usage: AparteUsage | null | undefined): void {\n this._usage = usage ?? null;\n this._updateActionBar();\n }\n\n /**\n * Update the branch picker UI for tree-based navigation.\n * The viewport calls this after a branch switch or re-render.\n * Prev/Next clicks dispatch `aparte-branch-navigate` (bubbles: true) so\n * the viewport can handle the actual tree switch.\n */\n setSiblings(count: number, index: number): void {\n this._siblingCount = count;\n this._siblingIndex = index;\n this._updateBranchPicker();\n }\n\n /**\n * Atomic update for the message\n */\n updateMessage(updates: Partial<AparteMessage>): void {\n if ('role' in updates) {\n this._role = updates.role!;\n this._updateRole();\n }\n if ('content' in updates) {\n this._content = updates.content!;\n this._updateContent();\n }\n if ('segments' in updates) {\n this._segments = updates.segments!;\n this._renderSegments();\n }\n if ('timestamp' in updates) {\n this._updateTimestamp(updates.timestamp!);\n }\n if ('status' in updates) {\n const isStreaming = updates.status === 'streaming' || updates.status === 'pending';\n this._updateStreaming(isStreaming);\n }\n if ('attachments' in updates) {\n this._attachments = updates.attachments ?? [];\n this._updateAttachments();\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Private Methods\n // ─────────────────────────────────────────────────────────────────────────\n\n private _appendSegmentEl(segment: AparteSegment): void {\n if (!this._segmentsEl) {\n console.warn(`[AparteChatBubble] _appendSegmentEl ABORT: _segmentsEl is null`);\n return;\n }\n const renderer = getSegmentRenderer(segment.type);\n if (renderer) {\n // Renderers are plain functions with no element to resolve from — expose\n // this bubble's config as the ambient render config for the duration.\n const el = segmentRenderResultToElement(runWithConfig(this._cfg, () => renderer.render(segment)));\n if (el) {\n this._segmentsEl.appendChild(el);\n runWithConfig(this._cfg, () => renderer.setup?.(el, segment));\n }\n } else {\n warnMissingRenderer(segment.type);\n const fallback = document.createElement('div');\n fallback.className = 'segment segment-unknown';\n fallback.textContent = `[Unknown segment type: ${segment.type}]`;\n this._segmentsEl.appendChild(fallback);\n }\n if (this._contentEl) this._contentEl.style.display = 'none';\n this._reflectError();\n }\n\n private _applySegmentUpdate(segmentId: string, segment: AparteSegment, updates: Partial<AparteSegment>): void {\n const el = this._segmentsEl?.querySelector(`[data-segment-id=\"${cssEscape(segmentId)}\"]`) as HTMLElement | null;\n if (!el) {\n this._renderSegments();\n return;\n }\n const renderer = getSegmentRenderer(segment.type);\n if (!renderer) return;\n\n if (renderer.update) {\n runWithConfig(this._cfg, () => renderer.update!(el, segment));\n } else {\n const newEl = segmentRenderResultToElement(runWithConfig(this._cfg, () => renderer.render(segment)));\n if (newEl) {\n el.replaceWith(newEl);\n runWithConfig(this._cfg, () => renderer.setup?.(newEl, segment));\n }\n }\n\n // Handle collapsed state only when explicitly provided in the update —\n // never override a state the user set by clicking <summary>.\n if ('collapsed' in updates) {\n if ((updates as { collapsed?: boolean }).collapsed) {\n el.removeAttribute('open');\n } else {\n el.setAttribute('open', '');\n }\n }\n }\n\n private _getDisplayName(): string {\n const nameAttr = this.getAttribute('name');\n if (nameAttr) return nameAttr;\n const locale = this._cfg.getLocale();\n return this._role === 'user'\n ? (locale.roleNameUser ?? 'You')\n : (locale.roleNameAssistant ?? 'Assistant');\n }\n\n private _getAvatarInitial(): string {\n const name = this._getDisplayName();\n return name.length > 0 ? name[0]! : (this._role === 'user' ? 'U' : 'A');\n }\n\n private _render(): void {\n // Read the bubble's logical role from `data-role` (preferred — written\n // by the Angular wrapper) or the legacy `role` attribute, then set the\n // host's actual `role` attribute to a valid ARIA value. \"user\" and\n // \"assistant\" are NOT valid ARIA roles and would trigger accessibility\n // warnings in browsers / Lighthouse. The role-based styling lives on\n // inner `data-role` markers, so this swap is transparent to CSS.\n const dataRole = this.getAttribute('data-role');\n const legacyRole = this.getAttribute('role');\n const role = (dataRole && dataRole !== 'article') ? dataRole\n : (legacyRole && legacyRole !== 'article') ? legacyRole\n : 'assistant';\n this._role = role as AparteBubbleRole;\n if (this.getAttribute('role') !== 'article') {\n this.setAttribute('role', 'article');\n }\n if (!this.hasAttribute('data-role')) {\n this.setAttribute('data-role', role);\n }\n\n // Ensure we don't overwrite if already rendered (re-entrancy check)\n if (this.querySelector('.aparte-message')) return;\n\n const displayName = this._getDisplayName();\n const initial = this._getAvatarInitial();\n\n // Custom structural shell (AparteConfig.setBubbleShellRenderer). Must root at\n // .aparte-message + carry the region hooks; the queries below are null-guarded\n // so a partial shell degrades gracefully. See AparteBubbleShellRenderer.\n const shell = this._cfg.getBubbleShellRenderer?.();\n if (shell) {\n const out = runWithConfig(this._cfg, () => shell({ role: this._role, name: displayName, avatarInitial: initial }));\n if (out instanceof HTMLElement) this.replaceChildren(out);\n else this.innerHTML = out;\n } else {\n this.innerHTML = `\n <div class=\"aparte-message\" data-role=\"${role}\" role=\"article\" aria-label=\"${this._getAriaLabel()}\">\n <div class=\"aparte-avatar\" data-role=\"${role}\"></div>\n <div class=\"aparte-body\">\n <div class=\"aparte-header\">\n <span class=\"aparte-name\">${this._escapeHtml(displayName)}</span>\n <span class=\"aparte-timestamp\"></span>\n </div>\n <div class=\"aparte-attachments\" hidden></div>\n <div class=\"aparte-message-content\">\n <div class=\"aparte-segments\"></div>\n <div class=\"aparte-content\"></div>\n </div>\n <div class=\"aparte-footer\">\n <div class=\"aparte-branch-picker\" hidden>\n <button class=\"aparte-branch-prev\" aria-label=\"${this._cfg.getLocale().previousResponse ?? 'Previous response'}\">&#8249;</button>\n <span class=\"aparte-branch-label\">1 / 1</span>\n <button class=\"aparte-branch-next\" aria-label=\"${this._cfg.getLocale().nextResponse ?? 'Next response'}\">&#8250;</button>\n </div>\n <div class=\"aparte-action-bar\" role=\"toolbar\" aria-label=\"${this._cfg.getLocale().messageActions ?? 'Message actions'}\"></div>\n </div>\n </div>\n </div>\n `;\n }\n\n this._contentEl = this.querySelector('.aparte-content');\n this._segmentsEl = this.querySelector('.aparte-segments');\n this._attachmentsEl = this.querySelector('.aparte-attachments');\n this._actionBarEl = this.querySelector('.aparte-action-bar');\n this._branchPickerEl = this.querySelector('.aparte-branch-picker');\n\n this._setupBranchPickerListeners();\n this._updateActionBar();\n this._renderAvatar();\n }\n\n /**\n * Hand the avatar host element off to the registered AvatarProvider, if\n * any. Falls back to the default initial / image rendered by `_render()`\n * when no provider is set.\n */\n private _renderAvatar(): void {\n const avatar = this.querySelector('.aparte-avatar') as HTMLElement | null;\n if (!avatar) return;\n\n // Tear down any previously-mounted live component before re-rendering.\n if (this._avatarCleanup) {\n try { this._avatarCleanup(); } catch { /* ignore */ }\n this._avatarCleanup = null;\n }\n\n const provider = this._cfg.getAvatarProvider();\n if (!provider) return; // keep the default text initial from _render()\n\n avatar.textContent = '';\n const cleanup = provider.render(this._role, avatar);\n if (typeof cleanup === 'function') this._avatarCleanup = cleanup;\n }\n\n private _updateRole(): void {\n const message = this.querySelector('.aparte-message');\n const avatar = this.querySelector('.aparte-avatar');\n const nameEl = this.querySelector('.aparte-name');\n\n if (message) {\n message.setAttribute('data-role', this._role);\n message.setAttribute('aria-label', this._getAriaLabel());\n }\n if (avatar) {\n avatar.setAttribute('data-role', this._role);\n // Default initial — overridden below by the avatar provider if any.\n avatar.textContent = this._getAvatarInitial();\n }\n if (nameEl) {\n nameEl.textContent = this._getDisplayName();\n }\n // Re-render the action bar so buttons match the correct role\n // (critical when the role attribute is set after connectedCallback)\n this._updateActionBar();\n this._renderAvatar();\n }\n\n private _updateName(): void {\n const avatar = this.querySelector('.aparte-avatar') as HTMLElement | null;\n const nameEl = this.querySelector('.aparte-name');\n // Only refresh the initial when no provider owns the avatar — otherwise\n // we'd wipe the live component on every name change.\n if (avatar && !this._cfg.getAvatarProvider()) avatar.textContent = this._getAvatarInitial();\n if (nameEl) nameEl.textContent = this._getDisplayName();\n }\n\n private _updateContent(): void {\n if (!this._contentEl) return;\n\n // If we have segments, don't render simple content\n if (this._segments.length > 0) {\n this._contentEl.style.display = 'none';\n return;\n }\n\n this._contentEl.style.display = '';\n this._contentEl.innerHTML = this._cfg.renderMarkdown(this._content);\n // The Markdown provider only emits plain <pre><code>; apply the registered\n // syntax highlighter (if any) to those blocks. Skipped while streaming —\n // re-run once on completion (see _updateStreaming) to avoid per-token churn.\n if (!this._streaming) this._highlightContentCode();\n }\n\n /**\n * Apply the registered syntax-highlight provider to the code blocks produced\n * by the Markdown provider in the simple-content path. Provider-agnostic: a\n * full-block provider (e.g. Shiki) returns `<pre>…</pre>` so we replace the\n * element; a token provider (e.g. Prism, highlight.js) returns inner HTML so\n * we fill the existing `<code>`. No-op when no highlighter is installed.\n */\n private _highlightContentCode(): void {\n if (!this._contentEl || !this._cfg.hasHighlightProvider()) return;\n this._contentEl.querySelectorAll('pre > code').forEach((codeEl) => {\n const code = codeEl.textContent ?? '';\n if (!code.trim()) return;\n const match = codeEl.className.match(/language-([\\w+#-]+)/i);\n const lang = match?.[1] ?? '';\n const pre = codeEl.parentElement;\n Promise.resolve(this._cfg.highlightCode(code, lang)).then((html) => {\n const out = (html ?? '').trim();\n if (!out || !pre || !pre.isConnected) return;\n if (/^<pre[\\s>]/i.test(out)) {\n pre.outerHTML = out; // full block (Shiki)\n } else {\n (codeEl as HTMLElement).innerHTML = out; // inner tokens (Prism, hljs)\n }\n }).catch(() => { /* keep the plain block on failure */ });\n });\n }\n\n private _renderSegments(): void {\n if (!this._segmentsEl) return;\n\n // Clear existing segments\n this._segmentsEl.innerHTML = '';\n\n for (const segment of this._segments) {\n const renderer = getSegmentRenderer(segment.type);\n if (renderer) {\n const el = segmentRenderResultToElement(runWithConfig(this._cfg, () => renderer.render(segment)));\n if (el) {\n this._segmentsEl.appendChild(el);\n runWithConfig(this._cfg, () => renderer.setup?.(el, segment));\n }\n } else {\n // Fallback for unknown segment types\n warnMissingRenderer(segment.type);\n const fallback = document.createElement('div');\n fallback.className = 'segment segment-unknown';\n fallback.textContent = `[Unknown segment type: ${segment.type}]`;\n this._segmentsEl.appendChild(fallback);\n }\n }\n\n // Hide simple content when segments are present\n if (this._contentEl) {\n this._contentEl.style.display = this._segments.length > 0 ? 'none' : '';\n }\n this._reflectError();\n }\n\n /**\n * Reflect the error state on the bubble: `data-error` on `.aparte-message` while\n * an error segment is present. Derived from segments (not the message `status`\n * attribute) so it works identically in vanilla and in every wrapper — the\n * error segment flows through the reactive list in all of them. CSS themes\n * `.aparte-message[data-error]`; custom error content is via setErrorRenderer.\n */\n private _reflectError(): void {\n const message = this.querySelector('.aparte-message');\n if (!message) return;\n const hasError = this._segments.some(s => s.type === 'error');\n if (hasError) message.setAttribute('data-error', '');\n else message.removeAttribute('data-error');\n }\n\n private _updateTimestamp(value: string | number | null): void {\n const timestampEl = this.querySelector('.aparte-timestamp');\n if (!timestampEl || !value) return;\n\n try {\n const date = new Date(isNaN(Number(value)) ? value : Number(value));\n timestampEl.textContent = date.toLocaleTimeString(undefined, {\n hour: '2-digit',\n minute: '2-digit'\n });\n } catch {\n timestampEl.textContent = '';\n }\n }\n\n private _getAriaLabel(): string {\n const locale = this._cfg.getLocale();\n return this._role === 'user'\n ? (locale.yourMessage ?? 'Your message')\n : (locale.assistantResponse ?? 'Assistant response');\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Attachments\n // ─────────────────────────────────────────────────────────────────────────\n\n private _updateAttachments(): void {\n if (!this._attachmentsEl) return;\n\n if (this._role !== 'user' || this._attachments.length === 0) {\n this._attachmentsEl.hidden = true;\n this._attachmentsEl.innerHTML = '';\n return;\n }\n\n this._attachmentsEl.hidden = false;\n\n // Custom attachment chips (AparteConfig.setAttachmentRenderer) — one node per\n // attachment; the consumer owns markup + interactions (no default preview wiring).\n const customAttachment = this._cfg.getAttachmentRenderer?.();\n if (customAttachment) {\n this._attachmentsEl.replaceChildren();\n for (const a of this._attachments) {\n const el = segmentRenderResultToElement(runWithConfig(this._cfg, () => customAttachment(a)));\n if (el) this._attachmentsEl.appendChild(el);\n }\n return;\n }\n\n this._attachmentsEl.innerHTML = this._attachments.map(a => {\n const name = this._escapeHtml(a.name);\n if (a.type.startsWith('image/')) {\n return `<div class=\"aparte-thumb aparte-thumb--image\" title=\"${name}\">`\n + `<img class=\"aparte-thumb__img\" src=\"${this._escapeHtml(a.url)}\" alt=\"${name}\" loading=\"lazy\" />`\n + `<span class=\"aparte-thumb__name\">${name}</span></div>`;\n }\n return `<div class=\"aparte-thumb aparte-thumb--file\" title=\"${name}\">`\n + `<span class=\"aparte-thumb__ext\">${this._escapeHtml(this._fileExt(a.name))}</span>`\n + `<span class=\"aparte-thumb__name\">${name}</span></div>`;\n }).join('');\n\n // Image tiles open the full-size preview lightbox (app-owned modal).\n this._attachmentsEl.querySelectorAll('.aparte-thumb--image').forEach(tile => {\n tile.addEventListener('click', () => {\n const img = tile.querySelector('.aparte-thumb__img') as HTMLImageElement | null;\n if (!img) return;\n this.dispatchEvent(new CustomEvent('aparte-attachment-preview', {\n bubbles: true, composed: true,\n detail: { url: img.src, name: tile.getAttribute('title') ?? '' },\n }));\n });\n });\n }\n\n /** Uppercased file extension (≤4 chars), or 'FILE' when there is none. */\n private _fileExt(filename: string): string {\n const dot = filename.lastIndexOf('.');\n return dot > 0 ? filename.slice(dot + 1).toUpperCase().slice(0, 4) : 'FILE';\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Branch Picker\n // ─────────────────────────────────────────────────────────────────────────\n\n private _setupBranchPickerListeners(): void {\n const prevBtn = this._branchPickerEl?.querySelector('.aparte-branch-prev');\n const nextBtn = this._branchPickerEl?.querySelector('.aparte-branch-next');\n\n const dispatchNav = (direction: 'prev' | 'next') => {\n const messageId = this.getAttribute('message-id');\n if (!messageId) return;\n const detail: AparteBranchNavigateEventDetail = { messageId, direction };\n // Tree-based navigation: let the viewport handle the branch switch\n this.dispatchEvent(new CustomEvent<AparteBranchNavigateEventDetail>('aparte-branch-navigate', {\n bubbles: true,\n composed: true,\n detail,\n }));\n };\n\n prevBtn?.addEventListener('click', () => dispatchNav('prev'));\n nextBtn?.addEventListener('click', () => dispatchNav('next'));\n }\n\n private _updateBranchPicker(): void {\n if (!this._branchPickerEl) return;\n if (this._siblingCount <= 1 || this._role !== 'assistant') {\n this._branchPickerEl.hidden = true;\n return;\n }\n this._branchPickerEl.hidden = false;\n const label = this._branchPickerEl.querySelector('.aparte-branch-label');\n if (label) {\n // Custom position indicator (AparteConfig.setSiblingNavRenderer) — e.g. dots —\n // fills the label between the arrows; the arrows keep their behavior.\n const customNav = this._cfg.getSiblingNavRenderer?.();\n if (customNav) {\n const out = runWithConfig(this._cfg, () => customNav({ count: this._siblingCount, index: this._siblingIndex }));\n if (out instanceof HTMLElement) label.replaceChildren(out);\n else label.innerHTML = out;\n } else {\n label.textContent = `${this._siblingIndex + 1} / ${this._siblingCount}`;\n }\n }\n\n const prevBtn = this._branchPickerEl.querySelector('.aparte-branch-prev') as HTMLButtonElement | null;\n const nextBtn = this._branchPickerEl.querySelector('.aparte-branch-next') as HTMLButtonElement | null;\n if (prevBtn) prevBtn.disabled = this._siblingIndex === 0;\n if (nextBtn) nextBtn.disabled = this._siblingIndex === this._siblingCount - 1;\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Action Bar\n // ─────────────────────────────────────────────────────────────────────────\n\n private _updateActionBar(): void {\n if (!this._actionBarEl) return;\n // While the inline editor is open the bar shows save (✓) / cancel (✗).\n if (this._editing) {\n this._renderEditActions();\n return;\n }\n const config = this._cfg.getBubbleActions();\n const icons = this._cfg.getIconProvider();\n const locale = this._cfg.getLocale();\n const buttons: string[] = [];\n\n if (this._role === 'user') {\n if (config.user) {\n // Explicit ordered set replaces the flag defaults for user bubbles.\n for (const a of config.user) buttons.push(this._actionButtonHtml(a, icons, locale));\n } else {\n // Default user set: copy + edit.\n if (config.copy) buttons.push(this._actionButtonHtml('copy', icons, locale));\n if (config.edit) buttons.push(this._actionButtonHtml('edit', icons, locale));\n }\n } else if (this._role === 'assistant') {\n if (config.assistant) {\n // Explicit ordered set replaces the flag defaults (incl. the info button).\n for (const a of config.assistant) buttons.push(this._actionButtonHtml(a, icons, locale));\n } else {\n // Default assistant set: copy + retry + feedback (+ info when usage present).\n if (config.copy) buttons.push(this._actionButtonHtml('copy', icons, locale));\n if (config.retry) buttons.push(this._actionButtonHtml('retry', icons, locale));\n if (config.feedback) {\n buttons.push(this._actionButtonHtml('thumbUp', icons, locale));\n buttons.push(this._actionButtonHtml('thumbDown', icons, locale));\n }\n\n // Info button — opens the stats popover. The popover UI itself is\n // owned by the app layer (it listens for `aparte-message-info`); the\n // bubble only renders the trigger and forwards the usage payload.\n if (this._usage) {\n const infoLabel = locale.messageInfo ?? 'Details';\n buttons.push(`<button class=\"aparte-action-btn aparte-action-info\" data-action=\"info\" aria-label=\"${infoLabel}\" title=\"${infoLabel}\">\n ${INFO_ICON_SVG}\n </button>`);\n }\n }\n }\n\n this._actionBarEl.innerHTML = buttons.join('');\n\n // Custom actions registered via AparteConfig.registerAction — appended\n // after the built-ins, built as DOM (label goes to attributes, never\n // interpolated into innerHTML) so a consumer label can't inject markup.\n this._appendCustomActions(icons);\n\n // Wire up button handlers — messageId read dynamically at click time\n // so it's always correct even when Angular sets the attribute after connectedCallback\n this._actionBarEl.querySelectorAll('.aparte-action-btn').forEach(btn => {\n btn.addEventListener('click', (e) => this._handleActionClick(e as MouseEvent));\n });\n }\n\n /** Append the registered custom action buttons for this bubble's role. */\n private _appendCustomActions(icons: ReturnType<AparteConfigClass['getIconProvider']>): void {\n if (!this._actionBarEl) return;\n for (const a of this._cfg.getActions('bubble')) {\n const roles = a.bubble?.roles ?? ['user', 'assistant'];\n if (!roles.includes(this._role)) continue;\n const btn = document.createElement('button');\n btn.className = 'aparte-action-btn aparte-action-custom';\n btn.dataset['action'] = `custom:${a.id}`;\n // aria-label/title via setAttribute — safe for consumer-provided strings.\n btn.setAttribute('aria-label', a.label);\n btn.setAttribute('title', a.label);\n // Icon: raw inline SVG/HTML, else an icon-provider key (trusted output).\n const fromProvider = (icons as unknown as Record<string, (() => string) | undefined>)[a.icon];\n btn.innerHTML = a.icon.startsWith('<')\n ? a.icon\n : (typeof fromProvider === 'function' ? fromProvider() : (a.iconFallback ?? ''));\n this._actionBarEl.appendChild(btn);\n }\n }\n\n /** Build the `<button>` HTML for a single named action (shared by flag + per-role rendering). */\n private _actionButtonHtml(\n action: string,\n icons: ReturnType<AparteConfigClass['getIconProvider']>,\n locale: ReturnType<AparteConfigClass['getLocale']>,\n ): string {\n switch (action) {\n case 'copy': {\n const l = locale.copy ?? 'Copy';\n return `<button class=\"aparte-action-btn aparte-action-copy\" data-action=\"copy\" aria-label=\"${l}\" title=\"${l}\">${icons.copy()}</button>`;\n }\n case 'edit': {\n const l = locale.edit ?? 'Edit message';\n return `<button class=\"aparte-action-btn aparte-action-edit\" data-action=\"edit\" aria-label=\"${l}\" title=\"${l}\">${icons.edit()}</button>`;\n }\n case 'retry': {\n const l = locale.retry ?? 'Retry';\n return `<button class=\"aparte-action-btn aparte-action-retry\" data-action=\"retry\" aria-label=\"${l}\" title=\"${l}\">${icons.retry()}</button>`;\n }\n case 'thumbUp': {\n const l = locale.feedbackPositive ?? 'Good response';\n return `<button class=\"aparte-action-btn aparte-action-feedback-pos\" data-action=\"feedback-positive\" aria-label=\"${l}\" title=\"${l}\">${icons.thumbUp()}</button>`;\n }\n case 'thumbDown': {\n const l = locale.feedbackNegative ?? 'Bad response';\n return `<button class=\"aparte-action-btn aparte-action-feedback-neg\" data-action=\"feedback-negative\" aria-label=\"${l}\" title=\"${l}\">${icons.thumbDown()}</button>`;\n }\n default:\n return '';\n }\n }\n\n /** Render the edit-mode action bar: ✓ save (green) + ✗ cancel (red). */\n private _renderEditActions(): void {\n if (!this._actionBarEl) return;\n const locale = this._cfg.getLocale();\n const saveLabel = locale.editConfirm ?? 'Save';\n const cancelLabel = locale.editCancel ?? 'Cancel';\n this._actionBarEl.innerHTML =\n `<button class=\"aparte-action-btn aparte-action-edit-save\" data-action=\"edit-save\" ` +\n `aria-label=\"${saveLabel}\" title=\"${saveLabel}\">${this._cfg.getIcon('check')}</button>` +\n `<button class=\"aparte-action-btn aparte-action-edit-cancel\" data-action=\"edit-cancel\" ` +\n `aria-label=\"${cancelLabel}\" title=\"${cancelLabel}\">${this._cfg.getIcon('close')}</button>`;\n this._actionBarEl.querySelectorAll('.aparte-action-btn').forEach(btn => {\n btn.addEventListener('click', (e) => this._handleActionClick(e as MouseEvent));\n });\n }\n\n private _handleActionClick(e: MouseEvent): void {\n const btn = (e.currentTarget as HTMLElement);\n const action = btn.dataset['action'];\n // Read dynamically — attribute may not be set yet at render time\n const messageId = this.getAttribute('message-id');\n\n // Custom actions (AparteConfig.registerAction) emit a generic aparte-action\n // event carrying the action id — same DOM-event contract as retry/feedback.\n if (action?.startsWith('custom:') && messageId) {\n const actionId = action.slice('custom:'.length);\n const detail: AparteActionEventDetail = {\n actionId,\n zone: 'bubble',\n messageId,\n role: this._role,\n targetId: this._resolveTargetId(),\n };\n this.dispatchEvent(new CustomEvent<AparteActionEventDetail>('aparte-action', {\n bubbles: true, composed: true, detail,\n }));\n this._cfg.getActions('bubble').find(x => x.id === actionId)?.onClick?.(e);\n return;\n }\n\n switch (action) {\n case 'copy': {\n const text = this._content || this._segments.map(s => (s as { content?: string }).content ?? '').join('\\n');\n const icons = this._cfg.getIconProvider();\n const locale = this._cfg.getLocale();\n navigator.clipboard.writeText(text).then(() => {\n btn.innerHTML = icons.check();\n btn.setAttribute('data-copied', '');\n const copiedLabel = locale.copied ?? locale.copy ?? 'Copied';\n btn.setAttribute('title', copiedLabel);\n btn.setAttribute('aria-label', copiedLabel);\n setTimeout(() => {\n btn.removeAttribute('data-copied');\n btn.innerHTML = icons.copy();\n const copyLabel = locale.copy ?? 'Copy';\n btn.setAttribute('title', copyLabel);\n btn.setAttribute('aria-label', copyLabel);\n }, 2000);\n }).catch(() => {\n console.warn('[aparte] Clipboard write failed');\n });\n break;\n }\n case 'retry': {\n if (!messageId) break;\n const targetId = this._resolveTargetId();\n const detail: AparteRetryEventDetail = { messageId, targetId };\n this.dispatchEvent(new CustomEvent<AparteRetryEventDetail>('aparte-retry', {\n bubbles: true, composed: true,\n detail,\n }));\n break;\n }\n case 'edit': {\n this._enterEditMode();\n break;\n }\n case 'edit-save': {\n this._exitEditMode(true);\n break;\n }\n case 'edit-cancel': {\n this._exitEditMode(false);\n break;\n }\n case 'feedback-positive':\n case 'feedback-negative': {\n if (!messageId) break;\n const value: AparteFeedbackEventDetail['value'] = action === 'feedback-positive' ? 'positive' : 'negative';\n btn.setAttribute('data-submitted', '');\n const detail: AparteFeedbackEventDetail = { messageId, value };\n this.dispatchEvent(new CustomEvent<AparteFeedbackEventDetail>('aparte-feedback', {\n bubbles: true, composed: true,\n detail,\n }));\n break;\n }\n case 'info': {\n if (!messageId) break;\n const detail: AparteMessageInfoEventDetail = {\n messageId,\n usage: this._usage ?? undefined,\n };\n this.dispatchEvent(new CustomEvent<AparteMessageInfoEventDetail>('aparte-message-info', {\n bubbles: true, composed: true,\n detail,\n }));\n break;\n }\n }\n }\n\n /**\n * Open the inline editor for a user message. Idempotent — a second `edit`\n * click while already editing is a no-op (no stacked editors).\n *\n * The editor reuses the composer's contenteditable primitive\n * (`<aparte-composer-input>`) so editing is iso with composing: same autosize,\n * IME, paste and styling. With no `<aparte-composer>` root it runs standalone —\n * `Enter` (Shift+Enter = newline) surfaces as `aparte-composer-submit`, which we\n * treat as save; `Esc` cancels.\n */\n private _enterEditMode(): void {\n if (this._editing || !this._contentEl) return;\n this._editing = true;\n this.querySelector('.aparte-message')?.setAttribute('data-editing', '');\n\n const input = document.createElement('aparte-composer-input') as AparteComposerInput;\n input.setAttribute('placeholder', this._cfg.getLocale().edit ?? 'Edit message');\n this._editInput = input;\n\n this._contentEl.style.display = 'none';\n this._contentEl.insertAdjacentElement('afterend', input);\n // `insertAdjacentElement` upgrades + connects synchronously, so the editor is\n // ready — seed it with the current text (autosizes to fit).\n input.setValue(this._content);\n\n // Enter (via the primitive's standalone submit event) saves; Esc cancels.\n input.addEventListener('aparte-composer-submit', () => this._exitEditMode(true));\n input.addEventListener('keydown', (e) => {\n if (e.key === 'Escape' && !e.isComposing) {\n e.preventDefault();\n this._exitEditMode(false);\n }\n });\n\n // Swap the action bar over to ✓ / ✗.\n this._updateActionBar();\n\n input.focusEnd();\n }\n\n /**\n * Leave edit mode. When `save` is true and the text actually changed, emits\n * `aparte-edit`; otherwise restores the original message untouched. Always\n * restores the normal action bar and removes the inline editor.\n */\n private _exitEditMode(save: boolean): void {\n if (!this._editing) return;\n const newContent = this._editInput?.getValue() ?? '';\n const original = this._content;\n\n this._editInput?.remove();\n this._editInput = null;\n if (this._contentEl) this._contentEl.style.display = '';\n this.querySelector('.aparte-message')?.removeAttribute('data-editing');\n this._editing = false;\n this._updateActionBar();\n\n if (save && newContent && newContent !== original) {\n const messageId = this.getAttribute('message-id');\n if (messageId) {\n const detail: AparteEditEventDetail = {\n messageId,\n content: newContent,\n targetId: this._resolveTargetId(),\n };\n this.dispatchEvent(new CustomEvent<AparteEditEventDetail>('aparte-edit', {\n bubbles: true, composed: true,\n detail,\n }));\n }\n }\n }\n\n private _resolveTargetId(): string | undefined {\n // Walk up to the chat host element with an id. Angular's wrapper root IS the\n // `<aparte-chat>` element (its component selector); the plain-root wrappers\n // (React/Vue/Svelte) render a `<div class=\"aparte-chat-container\" data-aparte-chat\n // id=\"…\">` instead — so match `[data-aparte-chat]` too. Without this, retry/edit\n // resolved to `undefined` outside Angular and AparteClient's fallback hit the\n // bare `<aparte-chat-viewport>` (a different message store) → retry regenerated\n // into the void.\n let el: HTMLElement | null = this.parentElement;\n while (el) {\n const tag = el.tagName?.toLowerCase();\n const isHost = tag === 'aparte-chat' || tag === 'aparte-chat-component' || el.hasAttribute?.('data-aparte-chat');\n if (isHost && el.id) return el.id;\n el = el.parentElement;\n }\n return undefined;\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Utilities\n // ─────────────────────────────────────────────────────────────────────────\n\n private _escapeHtml(str: string): string {\n return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;').replace(/'/g, '&#039;');\n }\n\n private _updateStreaming(streaming: boolean): void {\n const wasStreaming = this._streaming;\n this._streaming = streaming;\n const message = this.querySelector('.aparte-message');\n if (message) {\n message.setAttribute('data-streaming', String(streaming));\n if (streaming) {\n // Signal \"in progress\" to assistive tech; clearing it on completion\n // cues screen readers (via the viewport's aria-live region) to read\n // the finished response.\n message.setAttribute('aria-busy', 'true');\n message.classList.add('aparte-message-streaming');\n } else {\n message.removeAttribute('aria-busy');\n message.classList.remove('aparte-message-streaming');\n }\n }\n // Streaming just finished: highlight the final content once (skipped during\n // streaming to avoid re-highlighting on every token).\n if (wasStreaming && !streaming) this._highlightContentCode();\n }\n}\n\n// Register the custom element\nif (!customElements.get('aparte-chat-bubble')) {\n customElements.define('aparte-chat-bubble', AparteChatBubble);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'aparte-chat-bubble': AparteChatBubble;\n }\n}\n","/**\n * AparteChatStatus - The Indicator\n * \n * Lightweight typing indicator with elegant animation.\n * Uses Light DOM for global CSS styling.\n * \n * @element aparte-chat-status\n * @attr {boolean} visible - Show/hide the indicator\n * @attr {string} text - Custom text (default: \"Typing...\")\n */\nimport { AparteConfigClass } from '../../config/aparte-config.js';\nimport { resolveConfig, runWithConfig } from '../../config/config-context.js';\n\nexport class AparteChatStatus extends HTMLElement {\n static get observedAttributes(): string[] {\n return ['visible', 'text'];\n }\n\n private _cfg!: AparteConfigClass;\n\n constructor() {\n super();\n }\n\n connectedCallback(): void {\n // Cache the resolved config (instance boundary or global fallback), like the\n // other Aparte elements — so a scoped setStatusRenderer applies here too.\n this._cfg = resolveConfig(this);\n this._render();\n // Re-render on a live config change (e.g. setStatusRenderer called after this\n // element already upgraded — it self-registers on import, so a persistent\n // <aparte-chat-status> in the page mounts before any config runs). Mirrors the\n // bubble's config-change subscription.\n window.addEventListener('aparte-config-change', this._onConfigChange);\n }\n\n disconnectedCallback(): void {\n window.removeEventListener('aparte-config-change', this._onConfigChange);\n }\n\n private _onConfigChange = (e: Event): void => {\n // Only react to OUR config (an instance-scoped change elsewhere must not touch\n // us). A bare notify (no detail.config) always re-renders.\n const detail = (e as CustomEvent).detail as { config?: unknown } | undefined;\n if (detail?.config && detail.config !== this._cfg) return;\n // Clear so _render's re-entrancy guard doesn't bail; visible/text are read\n // from attributes, so the shown state is preserved across the re-render.\n this.innerHTML = '';\n this._render();\n };\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n\n switch (name) {\n case 'visible':\n this._updateVisibility(newValue !== null);\n break;\n case 'text':\n this._updateText(newValue);\n break;\n }\n }\n\n /**\n * Show the typing indicator\n */\n show(): void {\n this.setAttribute('visible', '');\n }\n\n /**\n * Hide the typing indicator\n */\n hide(): void {\n this.removeAttribute('visible');\n }\n\n /**\n * Toggle visibility\n */\n toggle(): void {\n if (this.hasAttribute('visible')) {\n this.hide();\n } else {\n this.show();\n }\n }\n\n /**\n * Check if visible\n */\n isVisible(): boolean {\n return this.hasAttribute('visible');\n }\n\n private _render(): void {\n const text = this.getAttribute('text') || 'Typing';\n const visible = this.hasAttribute('visible');\n\n // Re-entrancy check\n if (this.querySelector('.aparte-status-container')) return;\n\n // Custom typing indicator (charter §6 render hook): replace the inner markup\n // while the container keeps owning show/hide (data-visible) + accessible name.\n const custom = this._cfg?.getStatusRenderer?.();\n if (custom) {\n this.innerHTML =\n `<div class=\"aparte-message aparte-status-container\" data-visible=\"${visible}\" role=\"status\" aria-live=\"polite\"></div>`;\n const container = this.querySelector('.aparte-status-container') as HTMLElement;\n // `text` set via setAttribute, never interpolated — a `\"` would break out.\n container.setAttribute('aria-label', text);\n const result = runWithConfig(this._cfg, () => custom(text));\n if (result instanceof HTMLElement) container.appendChild(result);\n else container.innerHTML = result;\n return;\n }\n\n this.innerHTML = `\n <div\n class=\"aparte-message aparte-status-container\"\n data-visible=\"${visible}\"\n role=\"status\"\n aria-live=\"polite\"\n >\n <div class=\"aparte-avatar\" data-role=\"assistant\" style=\"visibility: hidden\"></div>\n <div class=\"aparte-body\">\n <div class=\"aparte-status-content\">\n <div class=\"aparte-dots\" aria-hidden=\"true\">\n <span class=\"aparte-dot\"></span>\n </div>\n <span class=\"aparte-status-text\"></span>\n </div>\n </div>\n </div>\n `;\n // Set the (public, attacker-controllable) `text` via setAttribute/textContent\n // rather than interpolating it into the innerHTML template — a `\"` in the\n // attribute would otherwise break out and inject arbitrary attributes.\n this.querySelector('.aparte-status-container')?.setAttribute('aria-label', text);\n // Visible text only when explicitly requested — the default stays dots-only\n // (the aria-label above always carries the accessible name).\n if (this.hasAttribute('text')) {\n const textEl = this.querySelector('.aparte-status-text');\n if (textEl) textEl.textContent = text;\n }\n }\n\n private _updateVisibility(visible: boolean): void {\n const container = this.querySelector('.aparte-status-container');\n if (container) {\n container.setAttribute('data-visible', String(visible));\n }\n }\n\n private _updateText(text: string | null): void {\n const textEl = this.querySelector('.aparte-status-text');\n const container = this.querySelector('.aparte-status-container');\n if (!container) return; // not rendered yet — _render() reads the attribute\n // Removing the attribute restores the dots-only default (empty visible\n // text); the aria-label always keeps an accessible name.\n if (textEl) textEl.textContent = text ?? '';\n container.setAttribute('aria-label', text || 'Typing');\n }\n}\n\n// Register the custom element\nif (!customElements.get('aparte-chat-status')) {\n customElements.define('aparte-chat-status', AparteChatStatus);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'aparte-chat-status': AparteChatStatus;\n }\n}\n","import type {\n AparteMessage,\n AparteViewportConfig,\n AparteSegment,\n AparteSegmentUpdateEvent,\n ApartePathChangedEventDetail,\n AparteSiblingInfo,\n AparteUsage,\n} from '../../types/index.js';\nimport { resolveConfig } from '../../config/index.js';\nimport { MessageRepository } from '../../runtime/message-repository.js';\nimport type { ExportedMessageRepository } from '../../runtime/message-repository.js';\nimport { populateBubbleFromMessage, type SyncableBubble } from '../bubble/bubble-sync.js';\nimport { cssEscape } from '../../utils/css-escape.js';\n\n/**\n * AparteChatViewport - The Core\n * \n * Container component with smart scroll, streaming, and segment support.\n * Uses Light DOM for global CSS styling.\n * \n * @element aparte-chat-viewport\n * \n * Features:\n * - Smart Scroll: Sticks to bottom when user is at bottom, stops on manual scroll up\n * - appendToken(): For simple content streaming\n * - appendToSegment(): For segment-aware streaming (thinking, code, etc.)\n * - Internal message registry for memory management\n */\nexport class AparteChatViewport extends HTMLElement {\n // The scroll surface: an internal `.aparte-viewport-container` div (core mode)\n // or the host element itself (framework-managed mode). HTMLElement covers both.\n private _container: HTMLElement | null = null;\n private _scrollBtn: HTMLButtonElement | null = null;\n private _bottomSpacer: HTMLDivElement | null = null;\n /**\n * In framework-managed mode there is no spacer ELEMENT (an extra child would\n * collide with the framework's own DOM reconciliation). The spacer is an\n * additive `padding-bottom` on the host, tracked here so `_recalculateSpacer`\n * can read the current value without measuring an element.\n */\n private _fwSpacerHeight = 0;\n private _spacerRafId: number | null = null;\n private _spacerFrozenUntil: number = 0;\n private _layoutTransitionMs: number = 0;\n private _repo = new MessageRepository();\n private _isAutoScrollEnabled: boolean = true;\n private _scrollThreshold: number = 50;\n /** When true, the next _autoScroll() call uses smooth instead of instant, then resets. */\n private _smoothScrollOnce: boolean = false;\n /**\n * DOM render cap: the max number of `<aparte-chat-bubble>` elements kept in the\n * DOM at once (a perf ceiling for very long conversations). This NEVER evicts\n * messages from the repository — the full conversation tree and its persistence\n * snapshot stay intact; only the oldest rendered bubbles are dropped from view.\n */\n private _maxRenderedBubbles: number = 1000;\n /** One-time guard for the deprecated `maxMessages` warning. */\n private _warnedMaxMessagesDeprecation = false;\n private _resizeObserver: ResizeObserver | null = null;\n private _mutationObserver: MutationObserver | null = null;\n private _boundResetHandler: (() => void) | null = null;\n /**\n * When true, _reRenderActivePath() only dispatches aparte-path-changed without\n * touching the DOM. Set via setFrameworkManagedDOM(true) when a framework\n * (e.g. Angular) owns the bubble elements.\n */\n private _frameworkManagedDOM = false;\n\n static get observedAttributes(): string[] {\n return ['scroll-threshold', 'max-rendered-bubbles', 'max-messages'];\n }\n\n constructor() {\n super();\n this._handleScroll = this._handleScroll.bind(this);\n }\n\n connectedCallback(): void {\n // Framework wrappers set `framework-managed` DECLARATIVELY so the flag is\n // known BEFORE _render() builds the DOM. Otherwise _render()'s child\n // relocation runs at connect — before the host's setFrameworkManagedDOM()\n // call — moving the framework's bubbles into an internal wrapper and\n // breaking its reconciliation (insertBefore NotFoundError on the next\n // append). See _setupFrameworkDOM().\n if (this.hasAttribute('framework-managed')) this._frameworkManagedDOM = true;\n this._render();\n this._setupEventListeners();\n this._setupObservers();\n this._boundResetHandler = () => this.clearAll();\n window.addEventListener('aparte-reset', this._boundResetHandler);\n }\n\n disconnectedCallback(): void {\n if (this._boundResetHandler) {\n window.removeEventListener('aparte-reset', this._boundResetHandler);\n this._boundResetHandler = null;\n }\n this._cleanup();\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n\n switch (name) {\n case 'scroll-threshold':\n this._scrollThreshold = parseInt(newValue || '50', 10);\n break;\n case 'max-rendered-bubbles':\n this._maxRenderedBubbles = parseInt(newValue || '1000', 10);\n this._pruneRenderedBubbles();\n break;\n case 'max-messages':\n // Deprecated alias. It used to evict messages from the tree\n // (destructive, silent data loss); it now only caps rendered\n // bubbles in the DOM. Use `max-rendered-bubbles` instead.\n this._warnMaxMessagesDeprecated();\n this._maxRenderedBubbles = parseInt(newValue || '1000', 10);\n this._pruneRenderedBubbles();\n break;\n }\n }\n\n /**\n * Configure viewport with options\n */\n configure(config: AparteViewportConfig): void {\n if (config.scrollThreshold !== undefined) {\n this._scrollThreshold = config.scrollThreshold;\n }\n if (config.maxRenderedBubbles !== undefined) {\n this._maxRenderedBubbles = config.maxRenderedBubbles;\n this._pruneRenderedBubbles();\n }\n if (config.maxMessages !== undefined) {\n // Deprecated alias (see attributeChangedCallback).\n this._warnMaxMessagesDeprecated();\n this._maxRenderedBubbles = config.maxMessages;\n this._pruneRenderedBubbles();\n }\n if (config.layoutTransitionMs !== undefined) {\n this._layoutTransitionMs = config.layoutTransitionMs;\n }\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Simple Content Streaming\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Append a token chunk to a message's content (simple text streaming)\n * @param messageId - Unique identifier for the message\n * @param chunk - Token chunk to append\n */\n appendToken(messageId: string, chunk: string): void {\n const message = this._getOrCreateMessage(messageId);\n\n // Append to simple content\n message.content = (message.content || '') + chunk;\n\n // Notify bubble\n this._notifyBubble(messageId, 'appendToken', chunk);\n this._autoScroll();\n this._scheduleSpacerUpdate();\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Segment-Aware Streaming\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Append content to a specific segment within a message\n * @param messageId - Message containing the segment\n * @param segmentId - Target segment ID\n * @param chunk - Content to append\n */\n appendToSegment(messageId: string, segmentId: string, chunk: string): void {\n const message = this._getOrCreateMessage(messageId);\n\n // Find or create segment\n if (!message.segments) {\n message.segments = [];\n }\n\n const segment = message.segments.find(s => s.id === segmentId);\n if (segment && 'content' in segment) {\n (segment as { content: string }).content += chunk;\n }\n\n // Dispatch segment update event\n this.dispatchEvent(new CustomEvent<AparteSegmentUpdateEvent>('aparte-segment-update', {\n bubbles: true,\n composed: true,\n detail: { messageId, segmentId, content: chunk, append: true }\n }));\n\n // Notify bubble\n this._notifyBubble(messageId, 'appendToSegment', chunk, segmentId);\n this._autoScroll();\n }\n\n /**\n * The active (head) message id — the target of `AparteClient`'s 1-argument\n * streaming convention (`addSegment(segment)`, `updateSegment(segmentId,\n * updates)`, …) which operates on \"the current message\". Lets a bare\n * `<aparte-chat-viewport>` be a valid `AparteClient` target, exactly like a\n * framework wrapper's host element.\n */\n private _activeMessageId(): string | null {\n return this._repo.headId;\n }\n\n /**\n * Add a new segment. Two calling conventions are accepted:\n * - `addSegment(segment)` — AparteClient's 1-arg \"operate on the current\n * (head) message\" convention (also what a wrapper host installs);\n * - `addSegment(messageId, segment)` — explicit standalone form.\n * The first argument's type disambiguates (string = messageId, object =\n * segment), so a raw viewport driven by `AparteClient` no longer drops text\n * (the args used to bind one position short, creating a phantom message).\n */\n addSegment(segment: AparteSegment): void;\n addSegment(messageId: string, segment: AparteSegment): void;\n addSegment(messageIdOrSegment: string | AparteSegment, maybeSegment?: AparteSegment): void {\n const messageId = typeof messageIdOrSegment === 'string' ? messageIdOrSegment : this._activeMessageId();\n const segment = typeof messageIdOrSegment === 'string' ? maybeSegment : messageIdOrSegment;\n if (!messageId || !segment) return;\n\n const message = this._getOrCreateMessage(messageId);\n if (!message.segments) {\n message.segments = [];\n }\n message.segments.push(segment);\n\n // Notify bubble to render the new segment\n this._notifyBubble(messageId, 'addSegment', segment);\n this._autoScroll();\n }\n\n /**\n * Update a segment. `updateSegment(segmentId, updates)` (1-arg client\n * convention → current message) or `updateSegment(messageId, segmentId,\n * updates)` (explicit). Disambiguated by arity: the 3rd arg is absent and\n * the 2nd is the `updates` object in the 1-arg form.\n */\n updateSegment(segmentId: string, updates: Partial<AparteSegment>): void;\n updateSegment(messageId: string, segmentId: string, updates: Partial<AparteSegment>): void;\n updateSegment(a: string, b: string | Partial<AparteSegment>, c?: Partial<AparteSegment>): void {\n const clientForm = c === undefined && typeof b === 'object';\n const messageId = clientForm ? this._activeMessageId() : a;\n const segmentId = clientForm ? a : (b as string);\n const updates = clientForm ? (b as Partial<AparteSegment>) : (c as Partial<AparteSegment>);\n if (!messageId) return;\n\n const message = this._repo.getMessageById(messageId);\n if (!message?.segments) return;\n\n const segmentIndex = message.segments.findIndex(s => s.id === segmentId);\n if (segmentIndex !== -1) {\n message.segments[segmentIndex] = {\n ...message.segments[segmentIndex],\n ...updates\n } as AparteSegment;\n\n this._notifyBubble(messageId, 'updateSegment', { segmentId, updates });\n }\n }\n\n /**\n * Remove a segment. `removeSegment(segmentId)` (1-arg client convention →\n * current message) or `removeSegment(messageId, segmentId)` (explicit).\n */\n removeSegment(segmentId: string): void;\n removeSegment(messageId: string, segmentId: string): void;\n removeSegment(a: string, b?: string): void {\n const clientForm = b === undefined;\n const messageId = clientForm ? this._activeMessageId() : a;\n const segmentId = clientForm ? a : b;\n if (!messageId || !segmentId) return;\n\n const message = this._repo.getMessageById(messageId);\n if (message?.segments) {\n const idx = message.segments.findIndex(s => s.id === segmentId);\n if (idx !== -1) message.segments.splice(idx, 1);\n }\n this._notifyBubble(messageId, 'removeSegment', segmentId);\n }\n\n /**\n * Start a new streaming segment (e.g., thinking or code block)\n * Creates the segment and marks it as streaming\n */\n startSegment(messageId: string, segment: AparteSegment): void {\n const streamingSegment = { ...segment, isStreaming: true };\n this.addSegment(messageId, streamingSegment);\n }\n\n /**\n * Complete a streaming segment\n */\n completeSegment(messageId: string, segmentId: string): void {\n this.updateSegment(messageId, segmentId, { isStreaming: false });\n }\n\n /**\n * Persist token usage on a message and propagate to the live bubble so the\n * perf chip (tokens/sec) renders in the action bar.\n */\n setUsage(messageId: string, usage: AparteUsage): void {\n const message = this._repo.getMessageById(messageId);\n if (message) message.usage = usage;\n this._notifyBubble(messageId, 'setUsage', usage);\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Message Management\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * Mark a message as finished streaming\n */\n completeMessage(messageId: string): void {\n const message = this._repo.getMessageById(messageId);\n if (message) {\n message.isStreaming = false;\n message.status = 'completed';\n\n // Mark all segments as complete\n message.segments?.forEach(s => {\n (s as { isStreaming?: boolean }).isStreaming = false;\n });\n\n this._notifyBubble(messageId, 'complete', { status: 'completed' });\n this._recalculateSpacer();\n }\n }\n\n /**\n * Atomic update for a message by ID\n * Supports updating content, status, segments, and other metadata\n */\n updateMessage(messageId: string, updates: Partial<AparteMessage>): void {\n const message = this._repo.getMessageById(messageId);\n if (!message) return;\n\n // Apply updates to internal state\n Object.assign(message, updates);\n\n // Map AparteStatus to isStreaming for legacy bubble support\n if (updates.status) {\n message.isStreaming = updates.status === 'streaming' || updates.status === 'pending';\n }\n\n // Notify bubble\n this._notifyBubble(messageId, 'update', updates);\n this._autoScroll();\n }\n\n /**\n * Add a complete message to the message registry.\n *\n * @remarks\n * **Framework-managed DOM only.** Records the message in the tree but does NOT\n * paint a bubble on its own (a framework wrapper reconciles the DOM from the\n * list). For standalone / vanilla usage call {@link appendMessage} instead,\n * which both records the message and creates its bubble element.\n */\n addMessage(message: AparteMessage): void {\n this._repo.addOrUpdateMessage(this._repo.headId, { ...message });\n this._pruneRenderedBubbles();\n this._autoScroll();\n }\n\n /**\n * Append a new message and create its bubble in the DOM.\n * Implements the same contract as the Angular wrapper's appendMessage(),\n * making aparte-chat-viewport a fully standalone target for aparte-client.\n * When `_frameworkManagedDOM` is true, only the internal repo is updated —\n * the framework owns the DOM and will create the bubble element itself.\n */\n appendMessage(message: AparteMessage): void {\n this._repo.addOrUpdateMessage(this._repo.headId, { ...message });\n if (!this._frameworkManagedDOM) {\n const wrapper = this.querySelector('.aparte-messages-wrapper');\n if (wrapper) {\n const bubble = document.createElement('aparte-chat-bubble') as HTMLElement;\n bubble.setAttribute('message-id', message.id);\n bubble.setAttribute('role', message.role);\n if (message.timestamp) bubble.setAttribute('timestamp', String(message.timestamp));\n if (message.content) bubble.setAttribute('content', message.content);\n if (message.status === 'streaming' || message.status === 'pending') {\n bubble.setAttribute('streaming', '');\n }\n // Insert before spacer so spacer stays last\n if (this._bottomSpacer && this._bottomSpacer.parentNode === wrapper) {\n wrapper.insertBefore(bubble, this._bottomSpacer);\n } else {\n wrapper.appendChild(bubble);\n }\n }\n }\n this._pruneRenderedBubbles();\n this._recalculateSpacer();\n // User sending always anchors to bottom regardless of scroll position.\n if (message.role === 'user') {\n this._isAutoScrollEnabled = true;\n // Smooth scroll for user-initiated sends. Streaming auto-scroll stays\n // instant (via _autoScroll) so it can keep up with rapid token bursts.\n requestAnimationFrame(() => this._smoothScrollToBottom());\n } else {\n this._autoScroll();\n }\n }\n\n /**\n * Update the last message content, optionally appending.\n * Implements the same contract as the Angular wrapper's updateLastMessage(),'\n * making aparte-chat-viewport a fully standalone streaming target for aparte-client.\n */\n updateLastMessage(content: string, options?: { append?: boolean }): void {\n const lastId = this._repo.headId;\n if (!lastId) return;\n if (options?.append) {\n this.appendToken(lastId, content);\n } else {\n const message = this._repo.getMessageById(lastId);\n if (message) message.content = content;\n this._notifyBubble(lastId, 'appendToken', content);\n }\n }\n\n /**\n * Add a new sibling branch to an assistant message (retry flow).\n * Creates a new empty assistant message as a sibling of `messageId`\n * under the same parent, switches the active branch to it, and\n * re-renders the active path.\n * @returns The index of the new branch in the siblings array, or 0 on failure.\n */\n addBranch(messageId: string): number {\n const meta = this._repo.getMessage(messageId);\n if (!meta) return 0;\n\n const newMsg: AparteMessage = {\n id: crypto.randomUUID(),\n role: 'assistant',\n content: '',\n status: 'pending',\n timestamp: Date.now(),\n };\n this._repo.addOrUpdateMessage(meta.parentId, newMsg);\n this._repo.switchToBranch(newMsg.id);\n this._reRenderActivePath();\n\n const siblings = this._repo.getBranches(newMsg.id);\n return siblings.indexOf(newMsg.id);\n }\n\n /**\n * Add a new message relative to `existingId`, switch to it, and re-render.\n *\n * Role-aware semantics:\n * - existingId is an **assistant** message → create a sibling (same parent),\n * so the active path replaces the old response with the new one.\n * - existingId is a **user** message → create a child of that message,\n * so the user message stays on the active path and the new response follows it.\n *\n * Returns the new message's ID, or null if `existingId` is not found.\n */\n addSiblingOf(existingId: string, newMessage: AparteMessage): string | null {\n const meta = this._repo.getMessage(existingId);\n if (!meta) return null;\n\n // User messages: new response is a child (keep user on active path).\n // Assistant messages: new response is a sibling (replace old response).\n const parentId = meta.message.role === 'user'\n ? existingId\n : meta.parentId;\n this._repo.addOrUpdateMessage(parentId, { ...newMessage });\n this._repo.switchToBranch(newMessage.id);\n this._reRenderActivePath();\n return newMessage.id;\n }\n\n /**\n * Navigate to the previous or next sibling branch of a message.\n * Triggers a full re-render of the active path.\n */\n navigateBranch(messageId: string, direction: 'prev' | 'next'): void {\n const siblings = this._repo.getBranches(messageId);\n const currentIdx = siblings.indexOf(messageId);\n if (currentIdx === -1) return;\n\n const targetIdx = direction === 'prev' ? currentIdx - 1 : currentIdx + 1;\n if (targetIdx < 0 || targetIdx >= siblings.length) return;\n\n // Branch navigation is a deliberate user action — do not scroll to the\n // bottom. Disable auto-scroll so neither the spacer recalculation nor\n // the MutationObserver callback fires _scrollToBottom() after the DOM\n // rebuilds. The user can re-enable auto-scroll by scrolling to the bottom.\n this._isAutoScrollEnabled = false;\n this._updateScrollButton();\n\n this._repo.switchToBranch(siblings[targetIdx]!);\n this._reRenderActivePath();\n }\n\n /**\n * Remove ALL responses to a user message (every child branch) and set head\n * back to `userMessageId`. Cleaner than `truncateFrom` for edit flows: it\n * discards stale sibling branches so the regenerated response starts alone.\n */\n truncateResponsesAfter(userMessageId: string): void {\n const prevMessages = this._repo.getMessages();\n this._repo.clearChildren(userMessageId);\n\n // In framework-managed mode the host (Angular @for, React, etc.) owns\n // the bubble DOM. Removing nodes from under it triggers\n // `NotFoundError: Failed to execute 'insertBefore'` on the next change\n // detection cycle because the framework's view tree no longer matches\n // the actual DOM. Skip the manual cleanup and let the framework\n // reconcile when the consumer updates its message array.\n if (!this._frameworkManagedDOM) {\n const wrapper = this.querySelector('.aparte-messages-wrapper');\n if (wrapper) {\n const startIdx = prevMessages.findIndex(m => m.id === userMessageId);\n const toRemove = startIdx >= 0 ? prevMessages.slice(startIdx + 1) : [];\n for (const m of toRemove) {\n wrapper.querySelector(`aparte-chat-bubble[message-id=\"${cssEscape(m.id)}\"]`)?.remove();\n }\n }\n }\n }\n\n /**\n * Remove all messages from `messageId` onwards (inclusive) from state and DOM.\n * Used by edit to truncate history before re-generating.\n */\n truncateFrom(messageId: string): void {\n const allMsgs = this._repo.getMessages();\n const startIdx = allMsgs.findIndex(m => m.id === messageId);\n if (startIdx === -1) return;\n\n const toRemove = allMsgs.slice(startIdx).map(m => m.id);\n this._repo.resetHead(messageId);\n\n // See the note in truncateResponsesAfter: skip DOM ops when a framework\n // owns the bubble elements.\n if (!this._frameworkManagedDOM) {\n const wrapper = this.querySelector('.aparte-messages-wrapper');\n for (const id of toRemove) {\n wrapper?.querySelector(`aparte-chat-bubble[message-id=\"${cssEscape(id)}\"]`)?.remove();\n }\n }\n }\n\n /**\n * Get a message by ID\n */\n getMessage(messageId: string): AparteMessage | undefined {\n return this._repo.getMessageById(messageId);\n }\n\n getMessages(): AparteMessage[] {\n return this._repo.getMessages();\n }\n\n /**\n * Export the full conversation tree (all branches, not just the active path).\n * The returned snapshot can be persisted and restored via `importTree()`.\n */\n exportTree(): ExportedMessageRepository {\n return this._repo.export();\n }\n\n /**\n * Import a previously-exported tree snapshot, restoring the full branch\n * topology and the active head. Replaces any existing repo content.\n *\n * Always calls `_reRenderActivePath()`:\n * - In native DOM mode: rebuilds bubble elements.\n * - In framework-managed mode: skips DOM manipulation but dispatches\n * `aparte-path-changed` with sibling metadata so the wrapper can update\n * branch arrows on already-rendered bubbles.\n */\n importTree(tree: ExportedMessageRepository): void {\n this.clearAll();\n this._repo.import(tree);\n this._reRenderActivePath();\n }\n\n /**\n * Clear all messages and remove all bubble elements from the DOM.\n * Also dispatches a aparte-reset-done event.\n *\n * In framework-managed mode the DOM is owned by the host framework\n * (Angular @for, React, etc.) and we must not clear `innerHTML` — doing\n * so desynchronises the framework's view tree from the live DOM and the\n * next change-detection pass throws `NotFoundError` on insertBefore.\n */\n clearAll(): void {\n this._repo.clear();\n if (!this._frameworkManagedDOM) {\n const wrapper = this.querySelector('.aparte-messages-wrapper');\n if (wrapper) {\n // Remove bubbles individually so the spacer div is preserved.\n Array.from(wrapper.querySelectorAll('aparte-chat-bubble')).forEach(b => b.remove());\n }\n }\n // Reset spacer and scroll button regardless of mode\n this._setSpacerHeight(0);\n this._isAutoScrollEnabled = true;\n this._updateScrollButton();\n this.dispatchEvent(new CustomEvent('aparte-reset-done', { bubbles: true, composed: true }));\n }\n\n /**\n * Clear all messages\n * @deprecated Use clearAll() to also remove DOM bubbles\n */\n clearMessages(): void {\n this._repo.clear();\n }\n\n /**\n * Replace the entire message list in one shot. Used when switching\n * conversations: clears existing repo + DOM, then appends each message.\n *\n * In framework-managed mode the framework re-renders the bubble DOM\n * itself; we only update the internal repo (used by aparte-client to\n * build chat history).\n */\n setMessages(messages: AparteMessage[]): void {\n this.clearAll();\n for (const m of messages) {\n this.appendMessage(m);\n }\n }\n\n /**\n * Scroll to bottom of viewport\n */\n scrollToBottom(): void {\n this._scrollToBottom();\n }\n\n /**\n * Reset the bottom spacer to 0 height immediately and freeze it for\n * 350 ms so the host-app layout transition (e.g. flex: 0→1 animation)\n * does not trigger a premature recalculation with mid-animation geometry.\n * Call before a full messages swap.\n */\n resetSpacer(): void {\n this._setSpacerHeight(0);\n // Freeze spacer recalculation for the duration of any host layout\n // transition (configured via `layoutTransitionMs`). Without this,\n // ResizeObserver fires on every animation frame while the container\n // is still growing, producing incorrect spacer values.\n if (this._layoutTransitionMs > 0) {\n this._spacerFrozenUntil = Date.now() + this._layoutTransitionMs;\n }\n }\n\n /**\n * Enable or disable auto-scroll\n */\n setAutoScroll(enabled: boolean): void {\n this._isAutoScrollEnabled = enabled;\n }\n\n /**\n * Signal that a framework (e.g. Angular) manages the bubble DOM.\n * When true, branch navigation dispatches `aparte-path-changed` without\n * clearing/rebuilding the messages wrapper — the framework re-renders instead.\n */\n setFrameworkManagedDOM(managed: boolean): void {\n this._frameworkManagedDOM = managed;\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Private Helpers\n // ─────────────────────────────────────────────────────────────────────────\n\n private _getOrCreateMessage(messageId: string): AparteMessage {\n const existing = this._repo.getMessageById(messageId);\n if (existing) return existing;\n\n const message: AparteMessage = {\n id: messageId,\n role: 'assistant',\n content: '',\n timestamp: Date.now(),\n isStreaming: true,\n status: 'streaming'\n };\n this._repo.addOrUpdateMessage(this._repo.headId, message);\n return message;\n }\n\n private _notifyBubble(messageId: string, action: string, payload?: unknown, segmentId?: string): void {\n // Find the bubble element — the native `<aparte-chat-bubble>` OR a custom\n // element opting into live streaming via `data-aparte-bubble` (so a raw-core\n // consumer can replace the bubble tag and still receive token/segment\n // pushes, not just a CSS restyle).\n const bubble = this.querySelector(\n `aparte-chat-bubble[message-id=\"${cssEscape(messageId)}\"], [data-aparte-bubble][message-id=\"${cssEscape(messageId)}\"]`,\n ) as HTMLElement & {\n appendToken?: (chunk: string) => void;\n appendToSegment?: (segmentId: string, chunk: string) => void;\n addSegment?: (segment: AparteSegment) => void;\n updateSegment?: (segmentId: string, updates: Partial<AparteSegment>) => void;\n removeSegment?: (segmentId: string) => void;\n setUsage?: (usage: AparteUsage) => void;\n updateMessage?: (updates: Partial<AparteMessage>) => void;\n };\n\n if (!bubble) return;\n\n switch (action) {\n case 'appendToken':\n bubble.appendToken?.(payload as string);\n break;\n case 'appendToSegment':\n bubble.appendToSegment?.(segmentId!, payload as string);\n break;\n case 'addSegment':\n bubble.addSegment?.(payload as AparteSegment);\n break;\n case 'updateSegment': {\n const { segmentId: sid, updates: segUpdates } = payload as { segmentId: string; updates: Partial<AparteSegment> };\n bubble.updateSegment?.(sid, segUpdates);\n break;\n }\n case 'removeSegment':\n bubble.removeSegment?.(payload as string);\n break;\n case 'setUsage':\n bubble.setUsage?.(payload as AparteUsage);\n break;\n case 'update':\n // New atomic update for bubble\n if ('status' in (payload as Record<string, unknown>) || 'segments' in (payload as Record<string, unknown>)) {\n bubble.updateMessage?.(payload as Partial<AparteMessage>);\n }\n break;\n case 'complete':\n bubble.updateMessage?.(payload as Partial<AparteMessage>);\n break;\n }\n }\n\n /**\n * Re-render the active path: clears the messages wrapper and rebuilds bubbles\n * for every message on the current active branch path (root → head).\n * Calls `setSiblings(count, index)` on each bubble that has siblings, and\n * dispatches `aparte-path-changed` so Angular wrapper can sync its signal.\n *\n * When `_frameworkManagedDOM` is true (set via setFrameworkManagedDOM), the DOM\n * manipulation is skipped — only `aparte-path-changed` is dispatched so the\n * framework can re-render from updated signal state.\n */\n private _reRenderActivePath(): void {\n const activeMessages = this._repo.getMessages();\n\n // Compute sibling metadata once and reuse — keeps the event payload\n // identical between framework-managed and default DOM modes.\n const siblingsInfo: AparteSiblingInfo[] = activeMessages.map(m => {\n const sibs = this._repo.getBranches(m.id);\n return { id: m.id, count: sibs.length, index: sibs.indexOf(m.id) };\n });\n\n if (this._frameworkManagedDOM) {\n this._dispatchPathChanged(activeMessages, siblingsInfo);\n return;\n }\n\n const wrapper = this.querySelector('.aparte-messages-wrapper');\n if (!wrapper) return;\n wrapper.innerHTML = '';\n\n // Only materialise the last N messages of the active path (DOM render cap).\n // The repository keeps the full path; this is a perf ceiling, not eviction.\n const startIdx = Math.max(0, activeMessages.length - this._maxRenderedBubbles);\n for (let i = startIdx; i < activeMessages.length; i++) {\n const message = activeMessages[i]!;\n const sibInfo = siblingsInfo[i];\n\n const bubble = document.createElement('aparte-chat-bubble');\n bubble.setAttribute('message-id', message.id);\n bubble.setAttribute('role', message.role);\n if (message.timestamp) bubble.setAttribute('timestamp', String(message.timestamp));\n if (message.status === 'streaming' || message.status === 'pending') {\n bubble.setAttribute('streaming', '');\n }\n wrapper.appendChild(bubble);\n\n // Reconcile content / segments / attachments / sibling-picker via\n // the shared helper — same code path the framework wrappers use,\n // so the contract stays in lockstep.\n populateBubbleFromMessage(bubble as unknown as SyncableBubble, message, sibInfo);\n }\n\n this._dispatchPathChanged(activeMessages, siblingsInfo);\n this._recalculateSpacer();\n\n // The path swap rebuilt the DOM without firing a `scroll` event, so the\n // auto-scroll flag (and the scroll-to-bottom button that mirrors it) can\n // be stale — e.g. navigating from a long branch to one that fits entirely\n // would leave the button showing with nothing to scroll. Re-derive both\n // from the real post-layout geometry.\n requestAnimationFrame(() => this._handleScroll());\n }\n\n private _dispatchPathChanged(messages: AparteMessage[], siblings: AparteSiblingInfo[]): void {\n const detail: ApartePathChangedEventDetail = { messages, siblings };\n this.dispatchEvent(new CustomEvent<ApartePathChangedEventDetail>('aparte-path-changed', {\n bubbles: true,\n composed: true,\n detail,\n }));\n }\n\n private _autoScroll(): void {\n if (this._isAutoScrollEnabled) {\n if (this._smoothScrollOnce) {\n this._smoothScrollOnce = false;\n requestAnimationFrame(() => this._smoothScrollToBottom());\n } else {\n requestAnimationFrame(() => this._scrollToBottom());\n }\n }\n this._pruneRenderedBubbles();\n }\n\n /**\n * Request that the next auto-scroll triggered by a DOM mutation uses\n * smooth behaviour instead of instant. Call this just before adding a\n * user message bubble so the viewport animates down rather than jumping.\n * Resets automatically after the first auto-scroll fires.\n */\n requestSmoothScroll(): void {\n this._smoothScrollOnce = true;\n }\n\n private _render(): void {\n // Framework-managed: the framework owns the bubble children directly.\n // Do NOT build the internal container/wrapper or relocate children.\n if (this._frameworkManagedDOM) {\n this._setupFrameworkDOM();\n return;\n }\n // Light DOM rendering\n // Preserving existing children in render allows framework composition\n if (!this.querySelector('.aparte-viewport-container')) {\n const container = document.createElement('div');\n container.className = 'aparte-viewport-container';\n\n // Set direction based on current locale\n const locale = resolveConfig(this).getLocale();\n if (locale.direction) {\n container.setAttribute('dir', locale.direction);\n }\n\n container.setAttribute('role', 'log');\n container.setAttribute('aria-live', 'polite');\n container.setAttribute('aria-atomic', 'false');\n container.setAttribute('aria-relevant', 'additions');\n\n const wrapper = document.createElement('div');\n wrapper.className = 'aparte-messages-wrapper';\n\n // Move existing children (bubbles) into wrapper\n while (this.firstChild) {\n wrapper.appendChild(this.firstChild);\n }\n\n // Bottom spacer — always last in wrapper, height driven by _recalculateSpacer()\n this._bottomSpacer = document.createElement('div');\n this._bottomSpacer.className = 'aparte-bottom-spacer';\n this._bottomSpacer.setAttribute('aria-hidden', 'true');\n wrapper.appendChild(this._bottomSpacer);\n\n container.appendChild(wrapper);\n this.appendChild(container);\n\n this._container = container;\n\n // Scroll-to-bottom button — absolutely positioned over the viewport\n this._scrollBtn = document.createElement('button');\n this._scrollBtn.className = 'aparte-scroll-btn aparte-scroll-btn--hidden';\n this._scrollBtn.setAttribute('type', 'button');\n this._scrollBtn.setAttribute('aria-label', 'Scroll to bottom');\n const scrollIcon = resolveConfig(this).getIcon('scrollDown');\n this._scrollBtn.innerHTML = scrollIcon\n || `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"/><polyline points=\"19 12 12 19 5 12\"/></svg>`;\n this.appendChild(this._scrollBtn);\n } else {\n this._container = this.querySelector('.aparte-viewport-container');\n this._scrollBtn = this.querySelector('.aparte-scroll-btn');\n this._bottomSpacer = this.querySelector('.aparte-bottom-spacer');\n }\n }\n\n /**\n * DOM setup for framework-managed mode. The framework (React/Vue/Svelte/\n * Angular) renders the bubble elements as DIRECT children of the host, so we\n * must NOT relocate them into an internal wrapper — that desyncs the\n * framework's virtual DOM from the real DOM and throws NotFoundError on the\n * next append. Instead the HOST itself is the scroll surface, the spacer is\n * additive `padding-bottom` (no element), and the scroll button is a\n * `position: sticky` TRAILING foreign child (kept last by the framework\n * MutationObserver). A present foreign node is still a valid `insertBefore`\n * reference for the framework — the crash came from a RELOCATED node, not a\n * foreign one.\n */\n private _setupFrameworkDOM(): void {\n this._container = this;\n this._bottomSpacer = null;\n if (this.classList.contains('aparte-viewport--framework')) {\n this._scrollBtn = this.querySelector(':scope > .aparte-scroll-btn') as HTMLButtonElement | null;\n return; // already set up (re-entrant _render)\n }\n this.classList.add('aparte-viewport--framework');\n\n const scrollBtn = document.createElement('button');\n scrollBtn.className = 'aparte-scroll-btn aparte-scroll-btn--hidden';\n scrollBtn.setAttribute('type', 'button');\n scrollBtn.setAttribute('aria-label', 'Scroll to bottom');\n const scrollIcon = resolveConfig(this).getIcon('scrollDown');\n scrollBtn.innerHTML = scrollIcon\n || `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><line x1=\"12\" y1=\"5\" x2=\"12\" y2=\"19\"/><polyline points=\"19 12 12 19 5 12\"/></svg>`;\n this.appendChild(scrollBtn);\n this._scrollBtn = scrollBtn;\n }\n\n /**\n * Keep the sticky scroll button as the last child in framework-managed mode.\n * The framework usually inserts bubbles before its own trailing nodes (so the\n * button stays last), but a plain `appendChild` at the very end (e.g. some\n * Angular @for paths) can land a bubble after it — move it back. Idempotent:\n * a no-op when already last, so it never loops the MutationObserver.\n */\n private _keepScrollButtonLast(): void {\n if (!this._scrollBtn) return;\n if (this.lastElementChild !== this._scrollBtn) {\n this.appendChild(this._scrollBtn);\n }\n }\n\n /** Current spacer height — a padding value (framework) or the element's height (core). */\n private _getSpacerHeight(): number {\n if (this._frameworkManagedDOM) return this._fwSpacerHeight;\n return this._bottomSpacer?.offsetHeight ?? 0;\n }\n\n /** Set the spacer — host padding (framework, additive to base padding) or element height (core). */\n private _setSpacerHeight(px: number): void {\n if (this._frameworkManagedDOM) {\n this._fwSpacerHeight = px;\n this.style.setProperty('--aparte-fw-spacer', `${px}px`);\n } else if (this._bottomSpacer) {\n this._bottomSpacer.style.height = `${px}px`;\n }\n }\n\n private _setupEventListeners(): void {\n this._container?.addEventListener('scroll', this._handleScroll, { passive: true });\n this._scrollBtn?.addEventListener('click', () => {\n this._isAutoScrollEnabled = true;\n this._smoothScrollToBottom();\n this._updateScrollButton();\n });\n this.addEventListener('aparte-branch-navigate', (e: Event) => {\n const evt = e as CustomEvent<{ messageId: string; direction: 'prev' | 'next' }>;\n evt.stopPropagation();\n this.navigateBranch(evt.detail.messageId, evt.detail.direction);\n });\n }\n\n private _setupObservers(): void {\n this._resizeObserver = new ResizeObserver(() => {\n if (this._isAutoScrollEnabled) {\n this._scrollToBottom();\n }\n this._recalculateSpacer();\n });\n\n const wrapper = this.querySelector('.aparte-messages-wrapper');\n\n if (this._container) {\n // Fires on window/viewport resize and when the composer grows.\n // NOTE: we intentionally do NOT observe .aparte-messages-wrapper here.\n // The wrapper contains the spacer div — observing it would create a\n // feedback loop: spacer changes → wrapper resizes → ResizeObserver →\n // _recalculateSpacer → spacer changes → … → height grows unbounded.\n // Streaming content growth is handled by direct _scheduleSpacerUpdate()\n // calls from appendToken(). New bubbles are handled by MutationObserver.\n // Framework-managed: _container IS the host, whose `padding-bottom`\n // carries the spacer — observe the BORDER box (fixed host size) so a\n // spacer/padding change does NOT re-trigger _recalculateSpacer and\n // loop. Core mode observes the container (no dynamic padding).\n if (this._frameworkManagedDOM) {\n this._resizeObserver.observe(this._container, { box: 'border-box' });\n } else {\n this._resizeObserver.observe(this._container);\n }\n }\n\n this._mutationObserver = new MutationObserver(() => {\n // Keep the sticky scroll button trailing after framework appends.\n if (this._frameworkManagedDOM) this._keepScrollButtonLast();\n if (this._isAutoScrollEnabled) {\n requestAnimationFrame(() => this._scrollToBottom());\n }\n // Recalculate spacer when DOM mutates (new bubble added, Angular re-render).\n this._scheduleSpacerUpdate();\n });\n\n // Framework-managed: bubbles are direct children of the host (no wrapper).\n const observeTarget = this._frameworkManagedDOM ? this : wrapper;\n if (observeTarget) {\n this._mutationObserver.observe(observeTarget, {\n childList: true,\n subtree: true\n });\n }\n }\n\n private _handleScroll(): void {\n if (!this._container) return;\n\n const { scrollTop, scrollHeight, clientHeight } = this._container;\n const distanceFromBottom = scrollHeight - scrollTop - clientHeight;\n\n this._isAutoScrollEnabled = distanceFromBottom <= this._scrollThreshold;\n this._updateScrollButton();\n }\n\n private _scrollToBottom(): void {\n if (!this._container) return;\n this._container.scrollTop = this._container.scrollHeight;\n }\n\n private _smoothScrollToBottom(): void {\n if (!this._container) return;\n // scrollTo with behavior:'smooth' is not available in all environments (e.g. jsdom).\n // Fall back to instant scroll so tests and SSR environments stay safe.\n // Reduced-motion users get the instant path too — the CSS\n // prefers-reduced-motion block cannot reach a JS-driven smooth scroll.\n if (typeof this._container.scrollTo === 'function' && !this._prefersReducedMotion()) {\n this._container.scrollTo({ top: this._container.scrollHeight, behavior: 'smooth' });\n } else {\n this._container.scrollTop = this._container.scrollHeight;\n }\n }\n\n private _prefersReducedMotion(): boolean {\n return typeof matchMedia === 'function'\n && matchMedia('(prefers-reduced-motion: reduce)').matches;\n }\n\n /**\n * Show/hide the scroll-to-bottom button based on the current auto-scroll state.\n * Hidden when already at bottom (_isAutoScrollEnabled = true).\n */\n private _updateScrollButton(): void {\n this._scrollBtn?.classList.toggle('aparte-scroll-btn--hidden', this._isAutoScrollEnabled);\n }\n\n /**\n * Recalculate the bottom spacer height so the last user message is always\n * pinned to the top of the scroll area when a response is being generated.\n *\n * spacer = max(0, viewportHeight - lastUserBubble.offsetHeight - lastAssistantBubble.offsetHeight)\n *\n * The spacer shrinks progressively as the assistant streams content, eventually\n * reaching 0 when the combined height fills the viewport.\n */\n private _recalculateSpacer(): void {\n // Core mode needs the spacer element; framework mode uses host padding\n // (no element) — both need the scroll container.\n if (!this._container) return;\n if (!this._frameworkManagedDOM && !this._bottomSpacer) return;\n // Skip while the host layout is still animating (e.g. the flex transition\n // that moves the composer from the center of the screen to the bottom).\n // Without this guard, every ResizeObserver tick during the transition\n // reads a partially-grown clientHeight and writes an incorrect spacer\n // height that may reach the clientHeight cap and lock the spacer there.\n if (Date.now() < this._spacerFrozenUntil) return;\n\n const allBubbles = Array.from(\n this.querySelectorAll('aparte-chat-bubble')\n ) as HTMLElement[];\n\n if (allBubbles.length === 0) {\n this._setSpacerHeight(0);\n return;\n }\n\n const lastUserBubble = [...allBubbles]\n .reverse()\n .find(b => b.getAttribute('role') === 'user');\n\n if (!lastUserBubble) {\n this._setSpacerHeight(0);\n return;\n }\n\n // Read the current spacer height (may be non-zero during a CSS transition\n // or a previous non-zero value). Subtract it from scrollHeight to get the\n // true content height WITHOUT the spacer — no need to zero-then-reflow,\n // which would both fight the CSS transition and force an extra synchronous\n // layout that could read a stale animated value.\n const currentSpacerH = this._getSpacerHeight();\n\n // Use getBoundingClientRect so gaps, padding, and all children are\n // automatically accounted for — no need to manually sum heights.\n const containerRect = this._container.getBoundingClientRect();\n const userRect = lastUserBubble.getBoundingClientRect();\n\n // Absolute Y position of the user bubble's top within the full scrollable content\n const userTopInContent = userRect.top - containerRect.top + this._container.scrollTop;\n\n // Height of content from user bubble top to end, excluding the spacer\n const scrollHeightWithoutSpacer = this._container.scrollHeight - currentSpacerH;\n\n // If all content already fits in the viewport, no spacer is needed.\n if (scrollHeightWithoutSpacer <= this._container.clientHeight) {\n this._setSpacerHeight(0);\n return;\n }\n\n const contentBelowUserTop = scrollHeightWithoutSpacer - userTopInContent;\n\n const needed = this._container.clientHeight - contentBelowUserTop;\n // Hard cap: the spacer can never exceed the visible viewport height.\n // This acts as a safety net against stale layout reads (e.g. mid-swap)\n // that could produce an astronomical value and push content off-screen.\n const maxSpacer = this._container.clientHeight;\n this._setSpacerHeight(Math.min(Math.max(0, needed), maxSpacer));\n\n // Re-scroll after the spacer height changes so scrollTop is always\n // consistent with the new scrollHeight. Without this, the MutationObserver\n // schedules _scrollToBottom() one RAF *before* _recalculateSpacer() runs,\n // leaving scrollTop based on the pre-spacer scrollHeight. On the next\n // recalculation (e.g. from syncMessagesWithBubbles or a resize) the formula\n // reads a stale scrollTop and may grow the spacer to the clientHeight cap.\n if (this._isAutoScrollEnabled) {\n this._scrollToBottom();\n }\n }\n\n /**\n * Schedule a spacer recalculation on the next animation frame.\n * Batches multiple rapid calls (e.g. during token streaming) into one.\n *\n * Single-RAF intentional: both the scroll-to-bottom queued by MutationObserver\n * and this spacer recalculation must land in the *same* frame so the browser\n * paints exactly once — with the correct scroll position *and* the correct\n * spacer height. A double-RAF would put the spacer shrink one frame after the\n * scroll, causing a 1-frame layout jump during streaming.\n */\n private _scheduleSpacerUpdate(): void {\n if (this._spacerRafId !== null) return;\n this._spacerRafId = requestAnimationFrame(() => {\n this._spacerRafId = null;\n this._recalculateSpacer();\n });\n }\n\n /**\n * Cap the number of rendered bubbles in the DOM (perf ceiling only).\n *\n * Drops the oldest `<aparte-chat-bubble>` elements beyond `_maxRenderedBubbles`\n * from the DOM. It **never** touches the MessageRepository — the conversation\n * model and its persistence snapshot stay complete (retention/eviction is a\n * consumer/persistence concern, not the viewport's). No-op when a framework\n * owns the DOM.\n */\n private _pruneRenderedBubbles(): void {\n if (this._frameworkManagedDOM) return;\n const wrapper = this.querySelector('.aparte-messages-wrapper');\n if (!wrapper) return;\n const bubbles = wrapper.querySelectorAll('aparte-chat-bubble');\n const excess = bubbles.length - this._maxRenderedBubbles;\n for (let i = 0; i < excess; i++) {\n bubbles[i]?.remove();\n }\n }\n\n private _warnMaxMessagesDeprecated(): void {\n if (this._warnedMaxMessagesDeprecation) return;\n this._warnedMaxMessagesDeprecation = true;\n console.warn(\n '[Aparte] `maxMessages` / `max-messages` on aparte-chat-viewport is deprecated: ' +\n 'it used to silently evict messages from the conversation model. It now only ' +\n 'caps rendered bubbles in the DOM — use `maxRenderedBubbles` / `max-rendered-bubbles`. ' +\n 'For actual history retention, configure it on your ConversationManager instead.',\n );\n }\n\n private _cleanup(): void {\n this._container?.removeEventListener('scroll', this._handleScroll);\n this._resizeObserver?.disconnect();\n this._mutationObserver?.disconnect();\n this._resizeObserver = null;\n this._mutationObserver = null;\n if (this._spacerRafId !== null) {\n cancelAnimationFrame(this._spacerRafId);\n this._spacerRafId = null;\n }\n }\n}\n\n// Register the custom element\nif (!customElements.get('aparte-chat-viewport')) {\n customElements.define('aparte-chat-viewport', AparteChatViewport);\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n 'aparte-chat-viewport': AparteChatViewport;\n }\n}\n","import type { AparteSendEventDetail } from '../../types/index.js';\nimport { AparteConfig, type AparteConfigClass } from '../../config/aparte-config.js';\nimport { resolveConfig } from '../../config/config-context.js';\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Event map for internal pub/sub between primitives\n// ─────────────────────────────────────────────────────────────────────────────\nexport interface AparteComposerEventMap {\n 'value-change': { value: string };\n 'streaming-change': { streaming: boolean };\n 'disabled-change': { disabled: boolean };\n 'attachments-change': { attachments: File[] };\n 'submit': { value: string; attachments: File[] };\n 'cancel': Record<string, never>;\n 'panel-change': { active: boolean; submitEnabled: boolean };\n}\n\nexport type AparteComposerEventType = keyof AparteComposerEventMap;\n\n/**\n * Public snapshot of the composer's observable state. Delivered on every\n * `aparte-composer-change` DOM event and available synchronously via\n * {@link AparteComposer.getState}. Lets an element OUTSIDE the composer package\n * (a custom send button, a footer control) mirror the composer's live state\n * without the internal `_on`/`_emit` bus.\n */\nexport interface AparteComposerState {\n value: string;\n streaming: boolean;\n disabled: boolean;\n attachments: File[];\n /** A panel (e.g. an elicitation form) is showing in place of the input. */\n panelActive: boolean;\n /** Whether the send button should act as \"submit\" while a panel is active. */\n submitEnabled: boolean;\n}\n\n/** Detail of the public `aparte-composer-change` DOM event. */\nexport interface AparteComposerChangeEventDetail {\n state: AparteComposerState;\n composer: AparteComposer;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// AparteComposer — root context provider\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * @element aparte-composer\n *\n * Root context for all `aparte-composer-*` primitives.\n * Does NOT impose any visual layout — the consumer controls structure.\n *\n * @attr placeholder - Forwarded to aparte-composer-input via event\n * @attr disabled - Disables the whole composer\n * @attr target - ID of the <aparte-chat> target element\n *\n * @fires aparte-send - Fired when a message is submitted\n */\nexport class AparteComposer extends HTMLElement {\n private _value = '';\n private _streaming = false;\n private _attachments: File[] = [];\n private _listeners = new Map<string, Set<(payload: unknown) => void>>();\n private _panelActive = false;\n private _panelSubmitEnabled = false;\n private _panelOnSubmit: (() => void) | null = null;\n\n // Internal bus events that represent an observable STATE change — these are\n // mirrored to the public `aparte-composer-change` DOM event. `submit`/`cancel`\n // are actions, not state, and are covered by `aparte-send`/`aparte-cancel`.\n private static readonly _STATE_EVENTS: ReadonlySet<AparteComposerEventType> = new Set([\n 'value-change', 'streaming-change', 'disabled-change', 'attachments-change', 'panel-change',\n ]);\n\n // Window event bindings\n private _onMessageStart = this._handleMessageStart.bind(this);\n private _onMessageDone = this._handleMessageDone.bind(this);\n\n /** Config governing THIS composer (nearest instance boundary, else global). */\n private _cfg: AparteConfigClass = AparteConfig;\n private _configUnsub: (() => void) | null = null;\n /** True while `requireModelSelection` is on AND no model is selected — blocks send. */\n private _modelGated = false;\n private _onConfigChange = (): void => { this._evaluateModelGate(); };\n\n static get observedAttributes(): string[] {\n return ['placeholder', 'disabled', 'target'];\n }\n\n connectedCallback(): void {\n window.addEventListener('aparte-message-start', this._onMessageStart);\n window.addEventListener('aparte-message-done', this._onMessageDone);\n window.addEventListener('aparte-message-error', this._onMessageDone);\n window.addEventListener('aparte-message-aborted', this._onMessageDone);\n // Model-selection gate (opt-in via AparteConfig.setRequireModelSelection).\n this._cfg = resolveConfig(this);\n this._configUnsub = this._cfg.subscribe(this._onConfigChange);\n this._evaluateModelGate();\n }\n\n disconnectedCallback(): void {\n window.removeEventListener('aparte-message-start', this._onMessageStart);\n window.removeEventListener('aparte-message-done', this._onMessageDone);\n window.removeEventListener('aparte-message-error', this._onMessageDone);\n window.removeEventListener('aparte-message-aborted', this._onMessageDone);\n this._configUnsub?.();\n this._configUnsub = null;\n this._listeners.clear();\n }\n\n attributeChangedCallback(name: string, _old: string | null, value: string | null): void {\n if (name === 'disabled') {\n this._emit('disabled-change', { disabled: value !== null });\n }\n if (name === 'placeholder') {\n // Primitives read this directly via closest() — no event needed\n }\n }\n\n // ── Public API ─────────────────────────────────────────────────────────\n\n get value(): string { return this._value; }\n get streaming(): boolean { return this._streaming; }\n get disabled(): boolean { return this.hasAttribute('disabled'); }\n /**\n * When false, Shift+Enter submits and a bare Enter inserts a newline —\n * the inverse of the default. Driven by the `submit-on-enter` attribute.\n */\n get submitOnEnter(): boolean { return this.getAttribute('submit-on-enter') !== 'false'; }\n get attachments(): File[] { return this._attachments; }\n get placeholder(): string { return this.getAttribute('placeholder') ?? ''; }\n get targetId(): string | null { return this.getAttribute('target'); }\n\n /**\n * Snapshot of the composer's observable state. Pair with the\n * `aparte-composer-change` DOM event to drive a custom send button or footer\n * control that lives outside the composer package:\n *\n * @example\n * // A custom send button. Keep it CLICKABLE while streaming — submit()\n * // routes to cancel() when a response is in flight, so one button is\n * // Send/Stop. Disabling it on `streaming` would make \"stop\" unreachable.\n * composer.addEventListener('aparte-composer-change', (e) => {\n * const { streaming, disabled, value, attachments } = e.detail.state;\n * myButton.textContent = streaming ? 'Stop' : 'Send';\n * myButton.disabled = disabled || (!streaming && !value.trim() && attachments.length === 0);\n * });\n * myButton.addEventListener('click', () => composer.submit()); // send or stop\n */\n getState(): AparteComposerState {\n return {\n value: this._value,\n streaming: this._streaming,\n disabled: this.disabled,\n attachments: [...this._attachments],\n panelActive: this._panelActive,\n submitEnabled: this._panelSubmitEnabled,\n };\n }\n\n setValue(value: string): void {\n this._value = value;\n this._emit('value-change', { value });\n }\n\n addAttachments(files: FileList | File[]): void {\n this._attachments = [...this._attachments, ...Array.from(files)];\n this._emit('attachments-change', { attachments: this._attachments });\n }\n\n removeAttachment(file: File): void {\n this._attachments = this._attachments.filter(f => f !== file);\n this._emit('attachments-change', { attachments: this._attachments });\n }\n\n clearAttachments(): void {\n this._attachments = [];\n this._emit('attachments-change', { attachments: [] });\n }\n\n /** Inject a panel into the composer, hiding the text input. The send button calls onSubmit when clicked. */\n showPanel(panel: HTMLElement, options?: { submitEnabled?: boolean; onSubmit?: () => void }): void {\n this.hidePanel();\n const inputEl = this.querySelector('aparte-composer-input') as HTMLElement | null;\n if (inputEl) inputEl.style.display = 'none';\n panel.dataset['apartePanel'] = 'true';\n if (inputEl) {\n inputEl.insertAdjacentElement('afterend', panel);\n } else {\n this.appendChild(panel);\n }\n this._panelActive = true;\n this._panelSubmitEnabled = options?.submitEnabled ?? false;\n this._panelOnSubmit = options?.onSubmit ?? null;\n this._emit('panel-change', { active: true, submitEnabled: this._panelSubmitEnabled });\n }\n\n /** Remove the panel and restore the text input. */\n hidePanel(): void {\n const existing = this.querySelector('[data-aparte-panel]') as HTMLElement | null;\n if (existing) existing.remove();\n const inputEl = this.querySelector('aparte-composer-input') as HTMLElement | null;\n if (inputEl) inputEl.style.display = '';\n this._panelActive = false;\n this._panelSubmitEnabled = false;\n this._panelOnSubmit = null;\n this._emit('panel-change', { active: false, submitEnabled: false });\n this.focus();\n }\n\n /** Update the send button enabled state while a panel is active. */\n setPanelSubmitEnabled(enabled: boolean): void {\n if (!this._panelActive) return;\n this._panelSubmitEnabled = enabled;\n this._emit('panel-change', { active: true, submitEnabled: enabled });\n }\n\n get panelActive(): boolean { return this._panelActive; }\n\n /**\n * Recompute the model gate from the resolved config. When\n * `requireModelSelection` is on and no model is selected, block sending and\n * reflect `data-model-gated` so the shipped CSS greys the composer. Re-runs on\n * every config change (e.g. the model selector's auto-select firing).\n */\n private _evaluateModelGate(): void {\n const gated = this._cfg.getRequireModelSelection() && !this._cfg.hasSelectedModel();\n if (gated === this._modelGated) return;\n this._modelGated = gated;\n this.toggleAttribute('data-model-gated', gated);\n }\n\n /** Submit the current value. Called by aparte-composer-send or programmatically. */\n submit(): void {\n if (this._panelActive) {\n if (this._panelSubmitEnabled) this._panelOnSubmit?.();\n return;\n }\n if (this._streaming) {\n this.cancel();\n return;\n }\n const value = this._value.trim();\n if (!value && this._attachments.length === 0) return;\n if (this.disabled) return;\n if (this._modelGated) return; // no model selected yet (require-model gate)\n\n this._emit('submit', { value, attachments: this._attachments });\n\n const detail: AparteSendEventDetail = {\n content: value,\n timestamp: Date.now(),\n targetId: this.targetId ?? undefined,\n files: this._attachments.length > 0 ? [...this._attachments] : undefined,\n };\n\n this.dispatchEvent(new CustomEvent<AparteSendEventDetail>('aparte-send', {\n bubbles: true,\n composed: true,\n detail,\n }));\n\n // Clear after send\n this.setValue('');\n this.clearAttachments();\n }\n\n /** Cancel the current streaming response. */\n cancel(): void {\n this._emit('cancel', {});\n // Public, element-scoped signal — symmetric with `aparte-send` on submit,\n // for consumers that want to observe cancel on the composer itself.\n this.dispatchEvent(new CustomEvent('aparte-cancel', { bubbles: true, composed: true }));\n // aparte-abort → tells AparteClient to actually stop the stream\n // aparte-message-aborted → resets the composer's own streaming state\n // Scope the abort to this composer's host so cancelling one chat doesn't\n // abort every scoped client / reset every composer on the page.\n const abortDetail = { targetId: this.targetId ?? undefined };\n window.dispatchEvent(new CustomEvent('aparte-abort', { bubbles: false, detail: abortDetail }));\n window.dispatchEvent(new CustomEvent('aparte-message-aborted', { bubbles: false, detail: abortDetail }));\n }\n\n /**\n * Reset the composer to its initial state.\n * Clears value, attachments, and hides any active panel.\n * Call this when switching conversations.\n */\n reset(): void {\n this.setValue('');\n this.clearAttachments();\n if (this._panelActive) this.hidePanel();\n }\n\n /** Focus the input primitive inside this composer. */\n override focus(): void {\n const input = this.querySelector('aparte-composer-input') as HTMLElement | null;\n input?.focus();\n }\n\n // ── Internal pub/sub ────────────────────────────────────────────────────\n\n _emit<K extends AparteComposerEventType>(event: K, payload: AparteComposerEventMap[K]): void {\n this._listeners.get(event)?.forEach(cb => cb(payload));\n // Mirror state changes to a public DOM event so elements outside the\n // composer package can observe them without the private bus.\n if (AparteComposer._STATE_EVENTS.has(event)) {\n this.dispatchEvent(new CustomEvent<AparteComposerChangeEventDetail>('aparte-composer-change', {\n bubbles: true,\n composed: true,\n detail: { state: this.getState(), composer: this },\n }));\n }\n }\n\n _on<K extends AparteComposerEventType>(event: K, cb: (payload: AparteComposerEventMap[K]) => void): () => void {\n if (!this._listeners.has(event)) this._listeners.set(event, new Set());\n this._listeners.get(event)!.add(cb as unknown as (payload: unknown) => void);\n return () => this._listeners.get(event)?.delete(cb as unknown as (payload: unknown) => void);\n }\n\n // ── Window events ───────────────────────────────────────────────────────\n\n /** A window lifecycle event is for THIS composer when neither side is scoped\n * (single-instance broadcast) or the target ids match (multi-chat page).\n * Without this filter, streaming in one chat flips every composer's state. */\n private _isForThisComposer(e: Event): boolean {\n const evtTargetId = (e as CustomEvent).detail?.targetId as string | undefined;\n return !evtTargetId || !this.targetId || evtTargetId === this.targetId;\n }\n\n private _handleMessageStart(e: Event): void {\n if (!this._isForThisComposer(e)) return;\n this._streaming = true;\n this._emit('streaming-change', { streaming: true });\n }\n\n private _handleMessageDone(e: Event): void {\n if (!this._isForThisComposer(e)) return;\n this._streaming = false;\n this._emit('streaming-change', { streaming: false });\n // Always hide any active panel when a message lifecycle ends\n if (this._panelActive) this.hidePanel();\n }\n}\n\nif (!customElements.get('aparte-composer')) {\n customElements.define('aparte-composer', AparteComposer);\n}\n","import { resolveConfig } from '../../config/index.js';\nimport type { AparteComposer } from './aparte-composer.js';\n\n/**\n * @element aparte-composer-input\n *\n * Contenteditable text input primitive.\n * Must be a descendant of <aparte-composer>.\n *\n * Behaviour: Enter submits (calls root.submit()), Shift+Enter inserts newline.\n * Auto-expands up to max-height. Paste strips HTML, handles image paste.\n *\n * @attr placeholder - Placeholder text (fallback: reads from aparte-composer)\n * @attr max-height - Max height in px before scroll (default: 200)\n * @attr min-height - Min height in px. When omitted, the stylesheet's\n * min-height governs (44px in aparte.css) — so themes can\n * resize the editor in pure CSS without being fought by\n * an inline height.\n */\nexport class AparteComposerInput extends HTMLElement {\n private _editor: HTMLDivElement | null = null;\n private _maxHeight = 200;\n private _minHeight = 44;\n private _unsubscribes: (() => void)[] = [];\n\n // Bound handlers\n private _onInput = this._handleInput.bind(this);\n private _onKeydown = this._handleKeydown.bind(this);\n private _onFocus = this._handleFocus.bind(this);\n private _onBlur = this._handleBlur.bind(this);\n private _onPaste = this._handlePaste.bind(this);\n\n static get observedAttributes(): string[] {\n return ['placeholder', 'max-height', 'min-height', 'disabled'];\n }\n\n connectedCallback(): void {\n this._render();\n this._connectToRoot();\n this._scheduleInitialReflow();\n }\n\n disconnectedCallback(): void {\n this._editor?.removeEventListener('input', this._onInput);\n this._editor?.removeEventListener('keydown', this._onKeydown);\n this._editor?.removeEventListener('focus', this._onFocus);\n this._editor?.removeEventListener('blur', this._onBlur);\n this._editor?.removeEventListener('paste', this._onPaste);\n this._unsubscribes.forEach(fn => fn());\n this._unsubscribes = [];\n }\n\n attributeChangedCallback(name: string, _old: string | null, value: string | null): void {\n if (name === 'placeholder') this._updatePlaceholder();\n if (name === 'max-height') this._maxHeight = parseInt(value || '200', 10);\n if (name === 'min-height') this._minHeight = parseInt(value || '44', 10);\n if (name === 'disabled') this._updateDisabled(value !== null);\n }\n\n // ── Public API ──────────────────────────────────────────────────────────\n\n getValue(): string {\n // `textContent` drops `<br>`, so multi-line content would collapse onto one\n // line. Serialize the editor ourselves: text nodes as-is, `<br>` → newline.\n // We keep the editor flat (text + <br>, see _handleKeydown), but descend into\n // any stray wrapper for safety.\n if (!this._editor) return '';\n let out = '';\n const walk = (node: Node): void => {\n node.childNodes.forEach(child => {\n if (child.nodeType === Node.TEXT_NODE) out += child.textContent ?? '';\n else if (child.nodeName === 'BR') out += '\\n';\n else walk(child);\n });\n };\n walk(this._editor);\n return out.trim();\n }\n\n setValue(value: string): void {\n if (!this._editor) return;\n this._editor.textContent = value;\n this._updatePlaceholderVisibility();\n this._adjustHeight();\n this._getRoot()?.setValue(value);\n }\n\n clear(): void {\n if (!this._editor) return;\n this._editor.innerHTML = '';\n this._updatePlaceholderVisibility();\n this._adjustHeight();\n this._getRoot()?.setValue('');\n }\n\n override focus(): void { this._editor?.focus(); }\n override blur(): void { this._editor?.blur(); }\n\n /** Focus the editor and place the caret at the very end of its content. */\n focusEnd(): void {\n if (!this._editor) return;\n this._editor.focus();\n const sel = this.ownerDocument?.getSelection();\n if (!sel) return;\n const range = this.ownerDocument.createRange();\n range.selectNodeContents(this._editor);\n range.collapse(false);\n sel.removeAllRanges();\n sel.addRange(range);\n }\n\n // ── Private ─────────────────────────────────────────────────────────────\n\n private _getRoot(): AparteComposer | null {\n return this.closest('aparte-composer') as AparteComposer | null;\n }\n\n private _getPlaceholder(): string {\n return this.getAttribute('placeholder')\n || this._getRoot()?.placeholder\n || resolveConfig(this).t('inputPlaceholder')\n || 'Type a message...';\n }\n\n private _render(): void {\n if (this.querySelector('.aparte-ci-editor')) return;\n\n const disabled = this.hasAttribute('disabled') || this._getRoot()?.disabled || false;\n // `placeholder` may come straight from a host attribute (often bound to\n // dynamic/translated text) — escape before it lands in a double-quoted\n // attribute so a stray `\"` can't break out and inject markup.\n const placeholder = this._escapeAttr(this._getPlaceholder());\n\n this.innerHTML = `<div\n class=\"aparte-ci-editor\"\n contenteditable=\"${!disabled}\"\n role=\"textbox\"\n aria-multiline=\"true\"\n aria-label=\"${placeholder}\"\n tabindex=\"0\"\n aria-disabled=\"${disabled}\"\n data-placeholder=\"${placeholder}\"\n ></div>`;\n\n this._editor = this.querySelector('.aparte-ci-editor');\n this._editor?.addEventListener('input', this._onInput);\n this._editor?.addEventListener('keydown', this._onKeydown);\n this._editor?.addEventListener('focus', this._onFocus);\n this._editor?.addEventListener('blur', this._onBlur);\n this._editor?.addEventListener('paste', this._onPaste);\n\n this._adjustHeight();\n }\n\n private _connectToRoot(): void {\n const root = this._getRoot();\n if (!root) return;\n\n // Sync disabled state from root\n this._unsubscribes.push(\n root._on('disabled-change', ({ disabled }) => this._updateDisabled(disabled))\n );\n\n // When root clears value (after submit), clear our editor\n this._unsubscribes.push(\n root._on('value-change', ({ value }) => {\n if (value === '' && this.getValue() !== '') this.clear();\n })\n );\n\n // Sync streaming state — disable input while streaming\n this._unsubscribes.push(\n root._on('streaming-change', ({ streaming }) => {\n this._updateDisabled(streaming || root.disabled);\n })\n );\n }\n\n private _handleInput(): void {\n this._adjustHeight();\n // After a delete-all, contenteditable leaves residual `<br>` tags\n // (Chromium especially) so the `:empty` CSS pseudo-class no longer\n // matches and the placeholder stays hidden. Force-clear when text\n // content reduces to whitespace so the placeholder reappears.\n if (this._editor && !this._editor.textContent?.trim() && this._editor.innerHTML !== '') {\n this._editor.innerHTML = '';\n }\n this._updatePlaceholderVisibility();\n const value = this.getValue();\n this._getRoot()?.setValue(value);\n }\n\n private _handleKeydown(e: KeyboardEvent): void {\n // During IME composition (CJK/Japanese/Korean), Enter confirms the\n // candidate — it must never submit. `keyCode === 229` is the legacy\n // signal for engines that don't set `isComposing`.\n if (e.isComposing || e.keyCode === 229) return;\n if (e.key !== 'Enter') return;\n // `submit-on-enter` (default true): Enter submits, Shift+Enter inserts\n // a newline. When false the mapping inverts — Shift+Enter submits and\n // a bare Enter inserts a newline (lets the user author multi-line).\n const submitOnEnter = this._getRoot()?.submitOnEnter ?? true;\n const submits = submitOnEnter ? !e.shiftKey : e.shiftKey;\n if (submits) {\n e.preventDefault();\n const root = this._getRoot();\n if (root) {\n root.submit();\n } else {\n // Standalone (no <aparte-composer> parent, e.g. the bubble's inline\n // editor): there is no root to submit to, so surface the intent as a\n // DOM event the host can act on. Keeps this primitive reusable on its\n // own — the IME guard + submitOnEnter mapping above stay the single\n // source of truth for \"when to submit\".\n this.dispatchEvent(new CustomEvent('aparte-composer-submit', { bubbles: true }));\n }\n } else {\n // Newline branch. Take control instead of the browser's contenteditable\n // default, which inserts <div>/<br> wrappers that resist deletion.\n // `insertLineBreak` inserts a single <br> and manages the trailing bogus\n // <br> so backspace removes it cleanly (the \"can't delete the newline\" bug).\n e.preventDefault();\n // Nothing to break on an empty field — don't seed a leading blank line.\n if (!this._editor?.textContent) return;\n this.ownerDocument?.execCommand('insertLineBreak');\n }\n }\n\n private _handleFocus(): void {\n this.classList.add('is-focused');\n }\n\n private _handleBlur(): void {\n this.classList.remove('is-focused');\n }\n\n private _handlePaste(e: ClipboardEvent): void {\n e.preventDefault();\n const cd = e.clipboardData;\n if (!cd) return;\n\n // Image paste → push to root attachments\n const imageFile = Array.from(cd.items).find(i => i.type.startsWith('image/'))?.getAsFile();\n if (imageFile) {\n this._getRoot()?.addAttachments([imageFile]);\n return;\n }\n\n // Plain text paste\n const text = cd.getData('text/plain');\n if (text) {\n document.execCommand('insertText', false, text);\n }\n }\n\n private _adjustHeight(): void {\n if (!this._editor) return;\n // Measure with height:0 (not auto): an explicit height opts the editor\n // OUT of any parent flex `align-items: stretch`, so scrollHeight reflects\n // the real content — not the (taller) row it may be stretched into. With\n // `auto`, a stretching parent inflates scrollHeight and the editor gets\n // stuck tall until the next reflow.\n this._editor.style.height = '0px';\n // Floor: the `min-height` ATTRIBUTE when explicitly set; otherwise defer\n // to the stylesheet (CSS min-height caps an inline height anyway). A\n // hardcoded JS floor would override theme CSS with an inline style and\n // break editor/controls alignment in restyled composers.\n const floor = this.hasAttribute('min-height') ? this._minHeight : 0;\n const contentHeight = this._editor.scrollHeight;\n const h = Math.min(Math.max(contentHeight, floor), this._maxHeight);\n this._editor.style.height = `${h}px`;\n this._editor.style.overflowY = contentHeight > this._maxHeight ? 'auto' : 'hidden';\n }\n\n /**\n * The first `_adjustHeight()` runs synchronously in `_render()` on connect —\n * before the stylesheet, flex layout and web fonts have necessarily settled.\n * On an unstabilized layout `scrollHeight` can read inflated, leaving the\n * editor stuck tall (misaligned with the composer controls) until the first\n * keystroke re-measures it. Re-measure once the layout is ready so it's\n * correct from the first paint.\n */\n private _scheduleInitialReflow(): void {\n if (typeof requestAnimationFrame === 'function') {\n requestAnimationFrame(() => this._adjustHeight());\n }\n const fonts = (document as Document & { fonts?: { ready?: Promise<unknown> } }).fonts;\n fonts?.ready?.then(() => this._adjustHeight()).catch(() => { /* fonts unavailable — rAF path covers it */ });\n }\n\n private _updatePlaceholder(): void {\n if (this._editor) {\n const p = this._getPlaceholder();\n this._editor.setAttribute('data-placeholder', p);\n this._editor.setAttribute('aria-label', p);\n }\n }\n\n private _updatePlaceholderVisibility(): void {\n // Handled by CSS :empty — nothing to do\n }\n\n private _updateDisabled(disabled: boolean): void {\n if (!this._editor) return;\n this._editor.setAttribute('contenteditable', String(!disabled));\n this._editor.setAttribute('aria-disabled', String(disabled));\n }\n\n /** Escape a value before it lands in a double-quoted HTML attribute. */\n private _escapeAttr(str: string): string {\n return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;').replace(/'/g, '&#039;');\n }\n}\n\nif (!customElements.get('aparte-composer-input')) {\n customElements.define('aparte-composer-input', AparteComposerInput);\n}\n","import { resolveConfig } from '../../config/index.js';\nimport type { AparteComposer } from './aparte-composer.js';\n\n/**\n * @element aparte-composer-send\n *\n * Submit button primitive for <aparte-composer>.\n * Must be a descendant of <aparte-composer>.\n *\n * - Disabled when composer value is empty, composer is disabled, or streaming\n * - While streaming: shows stop icon and acts as cancel button\n */\nexport class AparteComposerSend extends HTMLElement {\n private _button: HTMLButtonElement | null = null;\n private _unsubscribes: (() => void)[] = [];\n\n // Bound handler\n private _onClick = this._handleClick.bind(this);\n\n connectedCallback(): void {\n this._render();\n this._connectToRoot();\n }\n\n disconnectedCallback(): void {\n this._button?.removeEventListener('click', this._onClick);\n this._unsubscribes.forEach(fn => fn());\n this._unsubscribes = [];\n }\n\n // ── Private ─────────────────────────────────────────────────────────────\n\n private _getRoot(): AparteComposer | null {\n return this.closest('aparte-composer') as AparteComposer | null;\n }\n\n private _render(): void {\n if (this.querySelector('.aparte-cs-button')) return;\n\n const label = resolveConfig(this).t('sendButton') || 'Send';\n const icon = this._getSendIcon();\n const root = this._getRoot();\n const disabled = !root || root.disabled || root.value.trim() === '';\n\n this.innerHTML = `<button\n class=\"aparte-cs-button aparte-send-button\"\n aria-label=\"${label}\"\n title=\"${label}\"\n ${disabled ? 'disabled' : ''}\n >${icon}</button>`;\n\n this._button = this.querySelector('.aparte-cs-button');\n this._button?.addEventListener('click', this._onClick);\n }\n\n private _connectToRoot(): void {\n const root = this._getRoot();\n if (!root) return;\n\n this._unsubscribes.push(\n root._on('value-change', () => this._syncState())\n );\n this._unsubscribes.push(\n root._on('disabled-change', () => this._syncState())\n );\n this._unsubscribes.push(\n root._on('streaming-change', ({ streaming }) => {\n // If panel is active, streaming state change doesn't affect the button —\n // the panel controls it (submit answer, not stop stream)\n if (this._getRoot()?.panelActive) return;\n this._syncStreamingState(streaming);\n })\n );\n this._unsubscribes.push(\n root._on('attachments-change', () => this._syncState())\n );\n this._unsubscribes.push(\n root._on('panel-change', ({ active, submitEnabled }) => {\n if (!this._button) return;\n if (active) {\n // Panel is shown — override to \"Submit answer\" state regardless of streaming\n this._button.disabled = !submitEnabled;\n this._button.innerHTML = this._getSendIcon();\n const label = resolveConfig(this).t('submitButton') || 'Submit';\n this._button.setAttribute('aria-label', label);\n this._button.setAttribute('title', label);\n this._button.classList.remove('is-streaming');\n } else {\n // Panel closed — restore state based on current streaming\n const root = this._getRoot();\n if (root?.streaming) {\n this._syncStreamingState(true);\n } else {\n this._syncState();\n }\n }\n })\n );\n }\n\n private _handleClick(e: MouseEvent): void {\n e.preventDefault();\n this._getRoot()?.submit();\n }\n\n private _syncState(): void {\n const root = this._getRoot();\n if (!root || !this._button) return;\n if (root.streaming) return; // streaming state managed separately\n\n const isEmpty = root.value.trim() === '' && root.attachments.length === 0;\n this._button.disabled = root.disabled || isEmpty;\n this._button.innerHTML = this._getSendIcon();\n const label = resolveConfig(this).t('sendButton') || 'Send';\n this._button.setAttribute('aria-label', label);\n this._button.setAttribute('title', label);\n this._button.classList.remove('is-streaming');\n }\n\n private _syncStreamingState(streaming: boolean): void {\n if (!this._button) return;\n if (streaming) {\n this._button.disabled = false;\n this._button.innerHTML = this._getStopIcon();\n this._button.setAttribute('aria-label', 'Stop');\n this._button.setAttribute('title', 'Stop');\n this._button.classList.add('is-streaming');\n } else {\n this._syncState();\n }\n }\n\n private _getSendIcon(): string {\n return resolveConfig(this).getIcon('send') || 'Send';\n }\n\n private _getStopIcon(): string {\n return resolveConfig(this).getIcon('stop');\n }\n}\n\nif (!customElements.get('aparte-composer-send')) {\n customElements.define('aparte-composer-send', AparteComposerSend);\n}\n","import { resolveConfig } from '../../config/index.js';\nimport type { AparteComposer } from './aparte-composer.js';\n\n/**\n * @element aparte-composer-cancel\n *\n * Cancel/stop streaming button primitive for <aparte-composer>.\n * Must be a descendant of <aparte-composer>.\n *\n * Hidden when not streaming. Visible only during active streaming.\n */\nexport class AparteComposerCancel extends HTMLElement {\n private _button: HTMLButtonElement | null = null;\n private _unsubscribes: (() => void)[] = [];\n\n // Bound handler\n private _onClick = this._handleClick.bind(this);\n\n connectedCallback(): void {\n this._render();\n this._connectToRoot();\n }\n\n disconnectedCallback(): void {\n this._button?.removeEventListener('click', this._onClick);\n this._unsubscribes.forEach(fn => fn());\n this._unsubscribes = [];\n }\n\n // ── Private ─────────────────────────────────────────────────────────────\n\n private _getRoot(): AparteComposer | null {\n return this.closest('aparte-composer') as AparteComposer | null;\n }\n\n private _render(): void {\n if (this.querySelector('.aparte-cc-button')) return;\n\n const label = resolveConfig(this).t('stopButton') || 'Stop';\n const icon = this._getStopIcon();\n\n this.innerHTML = `<button\n class=\"aparte-cc-button\"\n aria-label=\"${label}\"\n title=\"${label}\"\n hidden\n >${icon}</button>`;\n\n this._button = this.querySelector('.aparte-cc-button');\n this._button?.addEventListener('click', this._onClick);\n }\n\n private _connectToRoot(): void {\n const root = this._getRoot();\n if (!root) return;\n\n this._unsubscribes.push(\n root._on('streaming-change', ({ streaming }) => {\n if (this._button) this._button.hidden = !streaming;\n })\n );\n\n // Sync initial state\n if (root.streaming && this._button) this._button.hidden = false;\n }\n\n private _handleClick(e: MouseEvent): void {\n e.preventDefault();\n this._getRoot()?.cancel();\n }\n\n private _getStopIcon(): string {\n return resolveConfig(this).getIcon('stop');\n }\n}\n\nif (!customElements.get('aparte-composer-cancel')) {\n customElements.define('aparte-composer-cancel', AparteComposerCancel);\n}\n","import type { AparteComposer } from './aparte-composer.js';\n\n/** ✗ glyph for the hover remove button. */\nconst REMOVE_ICON =\n '<svg width=\"10\" height=\"10\" viewBox=\"0 0 12 12\" fill=\"currentColor\" aria-hidden=\"true\">' +\n '<path d=\"M9.5 3.205 8.795 2.5 6 5.295 3.205 2.5 2.5 3.205 5.295 6 2.5 8.795l.705.705' +\n 'L6 6.705l2.795 2.795.705-.705L6.705 6z\"/></svg>';\n\n/**\n * @element aparte-composer-attachments\n *\n * Renders a square thumbnail tile for each file attached to the root composer.\n * Image files show the actual picture; other files show an extension badge.\n * The filename and a remove (✗) button surface on hover; clicking an image\n * opens it full-size (dispatches `aparte-attachment-preview`).\n * Automatically hidden when there are no attachments.\n * Must be a descendant of <aparte-composer>.\n */\nexport class AparteComposerAttachments extends HTMLElement {\n private _unsubscribes: (() => void)[] = [];\n /** Object URLs minted for image previews — revoked on re-render/disconnect. */\n private _objectUrls: string[] = [];\n\n connectedCallback(): void {\n this._render([]);\n this._connectToRoot();\n }\n\n disconnectedCallback(): void {\n this._unsubscribes.forEach(fn => fn());\n this._unsubscribes = [];\n this._revokeUrls();\n }\n\n // ── Private ─────────────────────────────────────────────────────────────\n\n private _getRoot(): AparteComposer | null {\n return this.closest('aparte-composer') as AparteComposer | null;\n }\n\n private _connectToRoot(): void {\n const root = this._getRoot();\n if (!root) return;\n\n this._unsubscribes.push(\n root._on('attachments-change', ({ attachments }) => this._render(attachments))\n );\n\n // Sync initial state\n this._render(root.attachments);\n }\n\n /** Release the previous render's blob URLs so they don't leak. */\n private _revokeUrls(): void {\n this._objectUrls.forEach(url => URL.revokeObjectURL(url));\n this._objectUrls = [];\n }\n\n private _render(files: File[]): void {\n this.hidden = files.length === 0;\n // Free the previous render's preview URLs before minting new ones.\n this._revokeUrls();\n\n this.innerHTML = files.map((file) => {\n const name = this._escape(file.name);\n const remove =\n `<button class=\"aparte-thumb__remove\" type=\"button\" ` +\n `aria-label=\"Remove ${name}\">${REMOVE_ICON}</button>`;\n\n if (file.type.startsWith('image/')) {\n const url = URL.createObjectURL(file);\n this._objectUrls.push(url);\n return `<div class=\"aparte-thumb aparte-thumb--image\" title=\"${name}\">` +\n `<img class=\"aparte-thumb__img\" src=\"${url}\" alt=\"${name}\" />` +\n `<span class=\"aparte-thumb__name\">${name}</span>${remove}</div>`;\n }\n return `<div class=\"aparte-thumb aparte-thumb--file\" title=\"${name}\">` +\n `<span class=\"aparte-thumb__ext\">${this._escape(this._ext(file.name))}</span>` +\n `<span class=\"aparte-thumb__name\">${name}</span>${remove}</div>`;\n }).join('');\n\n // Remove buttons — every file has exactly one tile, so the button\n // index lines up with the attachments index.\n this.querySelectorAll('.aparte-thumb__remove').forEach((btn, i) => {\n btn.addEventListener('click', (e) => {\n e.stopPropagation();\n const root = this._getRoot();\n if (root) root.removeAttachment(root.attachments[i]!);\n });\n });\n\n // Image tiles → open the full-size preview lightbox.\n this.querySelectorAll('.aparte-thumb--image').forEach(tile => {\n tile.addEventListener('click', () => {\n const img = tile.querySelector('.aparte-thumb__img') as HTMLImageElement | null;\n if (!img) return;\n this.dispatchEvent(new CustomEvent('aparte-attachment-preview', {\n bubbles: true,\n composed: true,\n detail: { url: img.src, name: tile.getAttribute('title') ?? '' },\n }));\n });\n });\n }\n\n /** Uppercased file extension (≤4 chars), or 'FILE' when there is none. */\n private _ext(filename: string): string {\n const dot = filename.lastIndexOf('.');\n return dot > 0 ? filename.slice(dot + 1).toUpperCase().slice(0, 4) : 'FILE';\n }\n\n private _escape(str: string): string {\n return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;').replace(/'/g, '&#039;');\n }\n}\n\nif (!customElements.get('aparte-composer-attachments')) {\n customElements.define('aparte-composer-attachments', AparteComposerAttachments);\n}\n","import { resolveConfig } from '../../config/index.js';\nimport type { AparteComposer } from './aparte-composer.js';\n\n/**\n * @element aparte-composer-add-attachment\n *\n * File picker button for <aparte-composer>.\n * Opens a native file picker on click, then pushes picked files to root.addAttachments().\n * Also sets up drag & drop on the nearest <aparte-composer> root.\n *\n * @attr accept - MIME types / extensions passed to the file input (e.g. \"image/*,.pdf\")\n * @attr multiple - Allow multiple file selection (default: true)\n */\nexport class AparteComposerAddAttachment extends HTMLElement {\n private _button: HTMLButtonElement | null = null;\n private _dragCleanup: (() => void) | null = null;\n private _unsubscribes: (() => void)[] = [];\n\n // Bound handler\n private _onClick = this._handleClick.bind(this);\n\n static get observedAttributes(): string[] {\n return ['accept', 'multiple', 'disabled'];\n }\n\n connectedCallback(): void {\n this._render();\n this._connectToRoot();\n this._setupDragDrop();\n }\n\n disconnectedCallback(): void {\n this._button?.removeEventListener('click', this._onClick);\n this._dragCleanup?.();\n this._unsubscribes.forEach(fn => fn());\n this._unsubscribes = [];\n }\n\n attributeChangedCallback(name: string, _old: string | null, value: string | null): void {\n if (name === 'disabled' && this._button) {\n this._button.disabled = value !== null;\n }\n }\n\n // ── Private ─────────────────────────────────────────────────────────────\n\n private _getRoot(): AparteComposer | null {\n return this.closest('aparte-composer') as AparteComposer | null;\n }\n\n private _render(): void {\n if (this.querySelector('.aparte-caa-button')) return;\n\n const label = resolveConfig(this).t('actionUpload') || 'Attach file';\n const icon = resolveConfig(this).getIcon('paperclip') || this._defaultIcon();\n const disabled = this.hasAttribute('disabled') || this._getRoot()?.disabled || false;\n\n this.innerHTML = `<button\n class=\"aparte-caa-button aparte-action-button\"\n aria-label=\"${label}\"\n title=\"${label}\"\n type=\"button\"\n ${disabled ? 'disabled' : ''}\n >${icon}</button>`;\n\n this._button = this.querySelector('.aparte-caa-button');\n this._button?.addEventListener('click', this._onClick);\n }\n\n private _connectToRoot(): void {\n const root = this._getRoot();\n if (!root) return;\n\n this._unsubscribes.push(\n root._on('disabled-change', ({ disabled }) => {\n if (this._button) this._button.disabled = disabled;\n })\n );\n this._unsubscribes.push(\n root._on('streaming-change', ({ streaming }) => {\n if (this._button) this._button.disabled = streaming || root.disabled;\n })\n );\n }\n\n private _handleClick(): void {\n const input = document.createElement('input');\n input.type = 'file';\n input.multiple = !this.hasAttribute('multiple') || this.getAttribute('multiple') !== 'false';\n const accept = this.getAttribute('accept');\n if (accept) input.accept = accept;\n input.style.display = 'none';\n\n document.body.appendChild(input);\n input.addEventListener('change', () => {\n if (input.files?.length) this._getRoot()?.addAttachments(input.files);\n document.body.removeChild(input);\n }, { once: true });\n input.click();\n }\n\n private _setupDragDrop(): void {\n const root = this._getRoot();\n if (!root) return;\n\n const prevent = (e: Event) => { e.preventDefault(); e.stopPropagation(); };\n const onDragOver = (e: Event) => {\n if (root.disabled) return; // no drop target while disabled (e.g. streaming)\n prevent(e);\n root.classList.add('is-dragover');\n };\n const onDragLeave = (e: Event) => { prevent(e); root.classList.remove('is-dragover'); };\n const onDrop = (e: DragEvent) => {\n prevent(e); // always block the browser from navigating to the dropped file\n root.classList.remove('is-dragover');\n if (root.disabled) return; // don't attach while disabled (the add button is blocked too)\n const files = e.dataTransfer?.files;\n if (files?.length) this._getRoot()?.addAttachments(files);\n };\n\n root.addEventListener('dragover', onDragOver);\n root.addEventListener('dragleave', onDragLeave);\n root.addEventListener('drop', onDrop);\n\n this._dragCleanup = () => {\n root.removeEventListener('dragover', onDragOver);\n root.removeEventListener('dragleave', onDragLeave);\n root.removeEventListener('drop', onDrop);\n };\n }\n\n private _defaultIcon(): string {\n return `<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48\"/></svg>`;\n }\n}\n\nif (!customElements.get('aparte-composer-add-attachment')) {\n customElements.define('aparte-composer-add-attachment', AparteComposerAddAttachment);\n}\n","import { resolveConfig, type AparteIconName } from '../../config/index.js';\nimport type { AparteComposer } from './aparte-composer.js';\n\n/**\n * @element aparte-composer-action\n *\n * Generic action button primitive for <aparte-composer>.\n * The consumer declares it directly in markup — no global registration needed.\n *\n * @attr icon - Icon key for AparteConfig.getIcon(), or raw SVG/HTML starting with `<`\n * @attr label - Accessible label (also used as tooltip)\n * @attr disabled - Disables the button\n *\n * @fires aparte-action-click - Bubbles up when the button is clicked\n * detail: { actionId: string, composer: AparteComposer | null }\n *\n * @slot default - Optional: override button content entirely\n *\n * @example\n * <aparte-composer-action icon=\"star\" label=\"Favourite\"\n * (click)=\"onFavourite()\">\n * </aparte-composer-action>\n */\nexport class AparteComposerAction extends HTMLElement {\n private _button: HTMLButtonElement | null = null;\n private _unsubscribes: (() => void)[] = [];\n\n // Bound handler\n private _onClick = this._handleClick.bind(this);\n\n static get observedAttributes(): string[] {\n return ['icon', 'label', 'disabled'];\n }\n\n connectedCallback(): void {\n this._render();\n this._connectToRoot();\n }\n\n disconnectedCallback(): void {\n this._button?.removeEventListener('click', this._onClick);\n this._unsubscribes.forEach(fn => fn());\n this._unsubscribes = [];\n }\n\n attributeChangedCallback(name: string, _old: string | null, value: string | null): void {\n if (!this._button) return;\n if (name === 'disabled') {\n this._button.disabled = value !== null;\n }\n if (name === 'label') {\n this._button.setAttribute('aria-label', value ?? '');\n this._button.setAttribute('title', value ?? '');\n }\n if (name === 'icon') {\n this._button.innerHTML = this._resolveIcon(value ?? '');\n }\n }\n\n // ── Private ─────────────────────────────────────────────────────────────\n\n private _getRoot(): AparteComposer | null {\n return this.closest('aparte-composer') as AparteComposer | null;\n }\n\n private _render(): void {\n if (this.querySelector('.aparte-cact-button')) return;\n\n // `label` is a host-set attribute (often bound to dynamic/translated\n // text by the consumer) — escape before it lands in a double-quoted\n // attribute so a stray `\"` can't break out and inject markup.\n const label = this._escapeAttr(this.getAttribute('label') ?? '');\n const icon = this._resolveIcon(this.getAttribute('icon') ?? '');\n const disabled = this.hasAttribute('disabled') || this._getRoot()?.disabled || false;\n\n this.innerHTML = `<button\n class=\"aparte-cact-button aparte-action-button\"\n aria-label=\"${label}\"\n title=\"${label}\"\n type=\"button\"\n ${disabled ? 'disabled' : ''}\n >${icon}</button>`;\n\n this._button = this.querySelector('.aparte-cact-button');\n this._button?.addEventListener('click', this._onClick);\n }\n\n private _connectToRoot(): void {\n const root = this._getRoot();\n if (!root) return;\n\n this._unsubscribes.push(\n root._on('disabled-change', ({ disabled }) => {\n if (this._button) this._button.disabled = disabled || this.hasAttribute('disabled');\n })\n );\n this._unsubscribes.push(\n root._on('streaming-change', ({ streaming }) => {\n if (this._button) this._button.disabled = streaming || root.disabled || this.hasAttribute('disabled');\n })\n );\n }\n\n private _handleClick(_e: MouseEvent): void {\n this.dispatchEvent(new CustomEvent('aparte-action-click', {\n bubbles: true,\n composed: true,\n detail: { actionId: this.getAttribute('action-id') ?? '', composer: this._getRoot() },\n }));\n }\n\n private _resolveIcon(icon: string): string {\n if (!icon) return '';\n if (icon.trimStart().startsWith('<')) return icon;\n return resolveConfig(this).getIcon(icon as AparteIconName) ?? icon;\n }\n\n /** Escape a value before it lands in a double-quoted HTML attribute. */\n private _escapeAttr(str: string): string {\n return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;').replace(/'/g, '&#039;');\n }\n}\n\nif (!customElements.get('aparte-composer-action')) {\n customElements.define('aparte-composer-action', AparteComposerAction);\n}\n","/**\n * AparteConversationList — conversation history sidebar primitive\n *\n * Framework-agnostic web component. The host sets the `conversations`\n * JS property and the `active-id` attribute; the component renders the\n * list and fires events for user interactions.\n *\n * @fires {CustomEvent<AparteConversationSelectDetail>} aparte-select-conversation\n * @fires {CustomEvent<AparteConversationDeleteDetail>} aparte-delete-conversation\n * @fires {CustomEvent<AparteConversationArchiveDetail>} aparte-archive-conversation\n * @fires {CustomEvent<AparteConversationUnarchiveDetail>} aparte-unarchive-conversation\n */\n\nimport { resolveConfig } from '../../config/index.js';\n\nexport interface AparteConversationListItem {\n id: string;\n title: string;\n updatedAt?: number;\n /** When set, the item renders the unarchive action instead of archive. */\n archivedAt?: number;\n}\n\nexport interface AparteConversationSelectDetail {\n id: string;\n}\n\nexport interface AparteConversationDeleteDetail {\n id: string;\n}\n\nexport interface AparteConversationArchiveDetail {\n id: string;\n}\n\nexport interface AparteConversationUnarchiveDetail {\n id: string;\n}\n\nexport class AparteConversationList extends HTMLElement {\n private _conversations: AparteConversationListItem[] = [];\n private _activeId: string | null = null;\n\n static get observedAttributes(): string[] {\n return ['active-id'];\n }\n\n // ─── Lifecycle ────────────────────────────────────────────────────────\n\n connectedCallback(): void {\n if (!this.classList.contains('aparte-conv-list')) {\n this.classList.add('aparte-conv-list');\n }\n if (!this.getAttribute('role')) {\n this.setAttribute('role', 'navigation');\n }\n this._render();\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (oldValue === newValue) return;\n if (name === 'active-id') {\n this._activeId = newValue;\n this._updateActiveState();\n }\n }\n\n // ─── Public API ───────────────────────────────────────────────────────\n\n /** Set the list of conversations to display. Triggers a re-render. */\n set conversations(items: AparteConversationListItem[]) {\n this._conversations = Array.isArray(items) ? items : [];\n this._render();\n }\n\n get conversations(): AparteConversationListItem[] {\n return this._conversations;\n }\n\n // ─── Rendering ────────────────────────────────────────────────────────\n\n private _render(): void {\n this.innerHTML = this._conversations\n .map(conv => this._renderItem(conv))\n .join('');\n this._bindEvents();\n }\n\n private _renderItem(conv: AparteConversationListItem): string {\n const locale = resolveConfig(this).getLocale();\n const isActive = conv.id === this._activeId;\n const isArchived = !!conv.archivedAt;\n const activeClass = isActive ? ' aparte-conv-item--active' : '';\n const archivedClass = isArchived ? ' aparte-conv-item--archived' : '';\n const escapedId = this._esc(conv.id);\n const escapedTitle = this._esc(conv.title || locale.newChat);\n const deleteLabel = this._esc(locale.deleteConversation);\n const archiveLabel = this._esc(locale['archiveConversation'] ?? 'Archive conversation');\n const unarchiveLabel = this._esc(locale['unarchiveConversation'] ?? 'Unarchive conversation');\n const archiveAction = isArchived ? 'unarchive' : 'archive';\n const archiveAriaLabel = isArchived ? unarchiveLabel : archiveLabel;\n // Distinct icons: a downward tray for archive, an upward tray for unarchive.\n const archiveIcon = isArchived\n ? `<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"3 8 21 8\"/><path d=\"M5 8v11a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8\"/><polyline points=\"9 14 12 11 15 14\"/><line x1=\"12\" y1=\"11\" x2=\"12\" y2=\"19\"/></svg>`\n : `<svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\"><polyline points=\"3 8 21 8\"/><path d=\"M5 8v11a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V8\"/><polyline points=\"9 14 12 17 15 14\"/><line x1=\"12\" y1=\"11\" x2=\"12\" y2=\"17\"/></svg>`;\n return `\n<div\n class=\"aparte-conv-item${activeClass}${archivedClass}\"\n role=\"button\"\n tabindex=\"0\"\n data-conv-id=\"${escapedId}\"\n aria-current=\"${isActive ? 'page' : 'false'}\"\n>\n <span class=\"aparte-conv-item__title\">${escapedTitle}</span>\n <button\n class=\"aparte-conv-item__archive\"\n type=\"button\"\n data-archive-id=\"${escapedId}\"\n data-archive-action=\"${archiveAction}\"\n aria-label=\"${archiveAriaLabel}\"\n tabindex=\"0\"\n >${archiveIcon}</button>\n <button\n class=\"aparte-conv-item__delete\"\n type=\"button\"\n data-delete-id=\"${escapedId}\"\n aria-label=\"${deleteLabel}\"\n tabindex=\"0\"\n >\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.5\"\n stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\">\n <path d=\"M18 6L6 18M6 6l12 12\"/>\n </svg>\n </button>\n</div>`;\n }\n\n private _bindEvents(): void {\n this.addEventListener('click', this._onClick);\n this.addEventListener('keydown', this._onKeydown);\n }\n\n private _onClick = (e: Event): void => {\n const target = e.target as HTMLElement;\n const archiveBtn = target.closest('[data-archive-id]') as HTMLElement | null;\n if (archiveBtn) {\n e.stopPropagation();\n const id = archiveBtn.dataset['archiveId']!;\n const action = archiveBtn.dataset['archiveAction'];\n const eventName = action === 'unarchive'\n ? 'aparte-unarchive-conversation'\n : 'aparte-archive-conversation';\n this.dispatchEvent(new CustomEvent<AparteConversationArchiveDetail>(\n eventName,\n { detail: { id }, bubbles: true, composed: true }\n ));\n return;\n }\n const deleteBtn = target.closest('[data-delete-id]') as HTMLElement | null;\n if (deleteBtn) {\n e.stopPropagation();\n const id = deleteBtn.dataset['deleteId']!;\n this.dispatchEvent(new CustomEvent<AparteConversationDeleteDetail>(\n 'aparte-delete-conversation',\n { detail: { id }, bubbles: true, composed: true }\n ));\n return;\n }\n const item = target.closest('[data-conv-id]') as HTMLElement | null;\n if (item) {\n const id = item.dataset['convId']!;\n this.dispatchEvent(new CustomEvent<AparteConversationSelectDetail>(\n 'aparte-select-conversation',\n { detail: { id }, bubbles: true, composed: true }\n ));\n }\n };\n\n private _onKeydown = (e: KeyboardEvent): void => {\n if (e.key !== 'Enter' && e.key !== ' ') return;\n const item = (e.target as HTMLElement).closest('[data-conv-id]') as HTMLElement | null;\n if (item) {\n e.preventDefault();\n item.click();\n }\n };\n\n /** Update active class without full re-render (perf optimisation). */\n private _updateActiveState(): void {\n const items = this.querySelectorAll<HTMLElement>('[data-conv-id]');\n items.forEach(el => {\n const isActive = el.dataset['convId'] === this._activeId;\n el.classList.toggle('aparte-conv-item--active', isActive);\n el.setAttribute('aria-current', isActive ? 'page' : 'false');\n });\n }\n\n // ─── Helpers ──────────────────────────────────────────────────────────\n\n private _esc(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/\"/g, '&quot;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/'/g, '&#039;');\n }\n}\n\nif (!customElements.get('aparte-conversation-list')) customElements.define('aparte-conversation-list', AparteConversationList);\n","/**\n * <aparte-elicitation> — the default elicitation presenter.\n *\n * Registers itself as the presenter for the config governing its subtree\n * (`resolveConfig(this)`), so `requestUserInput()` from a tool handler is routed\n * here WITHOUT any window events — the typed presenter contract replaces the\n * stringly-typed `aparte-ask-question-*` events that drifted in Phase 1.\n *\n * On a request it builds the schema-appropriate panel (enum / boolean / string /\n * object) and mounts it inside the nearest `<aparte-composer>` via its\n * `showPanel` API, resolving:\n * - accept — the send button (panel submit), when all fields are complete\n * - decline — the inline \"Skip\" affordance\n * - cancel — the assistant turn was stopped/errored while pending\n *\n * Place anywhere inside the chat (it renders nothing itself):\n * <aparte-elicitation></aparte-elicitation>\n */\n\nimport { resolveConfig } from '../../config/config-context.js';\nimport { buildElicitationPanel, type BuiltElicitationPanel } from '../../elicitation/panel.js';\nimport type { AparteElicitationRequest, AparteElicitationResult, AparteElicitationPresenter } from '../../elicitation/types.js';\n\ntype ComposerEl = HTMLElement & {\n showPanel(panel: HTMLElement, options?: { submitEnabled?: boolean; onSubmit?: () => void }): void;\n hidePanel(): void;\n setPanelSubmitEnabled(enabled: boolean): void;\n};\n\ninterface Pending {\n settle(result: AparteElicitationResult): void;\n composer: ComposerEl;\n}\n\nexport class AparteElicitation extends HTMLElement {\n private _pending: Pending | null = null;\n private _onTurnEnd = (): void => this._cancelPending();\n\n connectedCallback(): void {\n this.style.display = 'none';\n this._injectStyles();\n // Become the presenter for this instance's config (or the global one).\n resolveConfig(this).setElicitationPresenter(this._present);\n // Safety net: if the turn is stopped/errored while a request is open,\n // resolve it as cancelled so the client loop unblocks and the composer\n // input is restored.\n window.addEventListener('aparte-message-aborted', this._onTurnEnd);\n window.addEventListener('aparte-message-error', this._onTurnEnd);\n }\n\n disconnectedCallback(): void {\n const cfg = resolveConfig(this);\n if (cfg.getElicitationPresenter() === this._present) cfg.setElicitationPresenter(null);\n window.removeEventListener('aparte-message-aborted', this._onTurnEnd);\n window.removeEventListener('aparte-message-error', this._onTurnEnd);\n this._cancelPending();\n }\n\n private _present: AparteElicitationPresenter = (request: AparteElicitationRequest) => {\n // One request at a time — a concurrent request is declined rather than\n // clobbering the open panel.\n if (this._pending) return Promise.resolve<AparteElicitationResult>({ action: 'cancel' });\n const composer = this._getComposer();\n if (!composer) return Promise.resolve<AparteElicitationResult>({ action: 'cancel' });\n\n return new Promise<AparteElicitationResult>((resolve) => {\n let done = false;\n const settle = (result: AparteElicitationResult): void => {\n if (done) return;\n done = true;\n this._pending = null;\n composer.hidePanel();\n resolve(result);\n };\n\n // Caller-side cancellation (tool handler signal: timeout / turn abort).\n if (request.signal) {\n if (request.signal.aborted) { settle({ action: 'cancel' }); return; }\n request.signal.addEventListener('abort', () => settle({ action: 'cancel' }), { once: true });\n }\n\n const panel: BuiltElicitationPanel = buildElicitationPanel(request.message, request.schema, () => {\n composer.setPanelSubmitEnabled(panel.isComplete());\n });\n\n // Inline \"Skip\" → decline (MCP's decline: the user chose not to answer).\n const footer = document.createElement('div');\n footer.className = 'aparte-elic-footer';\n const skip = document.createElement('button');\n skip.type = 'button';\n skip.className = 'aparte-elic-skip';\n skip.textContent = 'Skip';\n skip.addEventListener('click', () => settle({ action: 'decline' }));\n footer.appendChild(skip);\n panel.el.appendChild(footer);\n\n this._pending = { settle, composer };\n composer.showPanel(panel.el, {\n submitEnabled: panel.isComplete(),\n onSubmit: () => {\n if (panel.isComplete()) settle({ action: 'accept', content: panel.getContent() });\n },\n });\n panel.focus();\n });\n };\n\n private _cancelPending(): void {\n this._pending?.settle({ action: 'cancel' });\n }\n\n private _getComposer(): ComposerEl | null {\n // Nearest composer/input in an ancestor subtree, then any in the document.\n let node: Element | null = this.parentElement;\n while (node) {\n const composer = node.querySelector('aparte-composer') as ComposerEl | null;\n if (composer && typeof composer.showPanel === 'function') return composer;\n node = node.parentElement;\n }\n const doc = document.querySelector('aparte-composer') as ComposerEl | null;\n return doc && typeof doc.showPanel === 'function' ? doc : null;\n }\n\n private _injectStyles(): void {\n const id = 'aparte-elicitation-styles';\n if (document.getElementById(id)) return;\n const style = document.createElement('style');\n style.id = id;\n style.textContent = `\n.aparte-elic-panel { display:flex; flex-direction:column; gap:6px; padding:6px 4px; width:100%; box-sizing:border-box; max-height:50vh; overflow-y:auto; }\n.aparte-elic-message { margin:0 6px 6px; font-size:.82rem; font-weight:600; color:var(--aparte-text); line-height:1.4; }\n.aparte-elic-field + .aparte-elic-field { margin-top:8px; padding-top:8px; border-top:1px solid var(--aparte-border, rgba(128,128,128,0.12)); }\n.aparte-elic-title { margin:0 6px 4px; font-size:.8rem; font-weight:600; color:var(--aparte-text); }\n.aparte-elic-desc { margin:0 6px 6px; font-size:.76rem; color:var(--aparte-text-muted, rgba(128,128,128,0.75)); }\n.aparte-elic-options { display:flex; flex-direction:column; gap:1px; }\n.aparte-elic-option { display:flex; align-items:flex-start; gap:10px; padding:7px 10px; border-radius:8px; cursor:pointer; border:1px solid transparent; transition:background .12s,border-color .12s; }\n.aparte-elic-option:hover { background:var(--aparte-surface-2, rgba(128,128,128,0.08)); border-color:var(--aparte-border, rgba(128,128,128,0.15)); }\n.aparte-elic-control { margin-top:3px; flex-shrink:0; accent-color:var(--aparte-primary, #6366f1); width:15px; height:15px; cursor:pointer; }\n.aparte-elic-option-body { display:flex; flex-direction:column; gap:2px; flex:1; }\n.aparte-elic-option-title { font-size:.875rem; font-weight:500; color:var(--aparte-text, inherit); line-height:1.4; }\n.aparte-elic-option-desc { font-size:.78rem; color:var(--aparte-text-muted, rgba(128,128,128,0.75)); line-height:1.4; }\n.aparte-elic-other-input, .aparte-elic-text { margin-top:4px; width:100%; padding:6px 8px; border:1px solid var(--aparte-border, rgba(128,128,128,0.2)); border-radius:6px; font-size:.875rem; background:var(--aparte-surface-2, rgba(128,128,128,0.06)); color:var(--aparte-text, inherit); outline:none; box-sizing:border-box; font-family:inherit; }\ntextarea.aparte-elic-text { min-height:64px; resize:vertical; }\n.aparte-elic-other-input:focus, .aparte-elic-text:focus { border-color:var(--aparte-primary, #6366f1); }\n.aparte-elic-option--recommended { border-color:var(--aparte-primary, #6366f1) !important; background:color-mix(in srgb, var(--aparte-primary, #6366f1) 6%, transparent); }\n.aparte-elic-footer { display:flex; justify-content:flex-end; margin-top:6px; }\n.aparte-elic-skip { border:none; background:transparent; color:var(--aparte-text-muted, rgba(128,128,128,0.75)); font-size:.8rem; cursor:pointer; padding:4px 8px; border-radius:6px; font-family:inherit; }\n.aparte-elic-skip:hover { background:var(--aparte-surface-2, rgba(128,128,128,0.08)); color:var(--aparte-text); }\n`;\n document.head.appendChild(style);\n }\n}\n\nif (typeof customElements !== 'undefined' && !customElements.get('aparte-elicitation')) {\n customElements.define('aparte-elicitation', AparteElicitation);\n}\n","/**\n * Aparte\n * High-performance AI conversation engine in Vanilla TypeScript\n * Zero-dependency Web Components for LLM streaming\n * \n * @packageDocumentation\n */\nimport './styles/aparte.css';\nimport './primitives/select/select.css';\nimport './primitives/progress-spinner/progress-spinner.css';\n\n// Global HTMLElementEventMap augmentation — typed `e.detail` for aparté events.\nimport './types/event-map.js';\n\n// Export primitives\nexport { AparteSelect, AparteOption, AparteOptgroup, type AparteSelectChangeDetail, AparteProgressSpinner } from './primitives/index.js';\n\n// Export types\nexport type {\n AparteBubbleRole,\n AparteMessage,\n AparteContentParser,\n AparteSendEventDetail,\n AparteTokenEventDetail,\n AparteViewportConfig,\n AparteInputConfig,\n AparteThemeVariables,\n AparteStatus,\n AparteAttachment,\n AparteMessageBranch,\n AparteBubbleActionsConfig,\n AparteBubbleActionName,\n AparteSegment,\n AparteSegmentType,\n AparteTextSegment,\n AparteThinkingSegment,\n AparteCodeSegment,\n AparteTerminalSegment,\n AparteSegmentRenderer,\n AparteCustomSegment,\n AparteToolCallSegment,\n AparteArtifactSegment,\n // AI Provider types (BYORK)\n AparteAIProvider,\n AparteAIModel,\n AparteAIProviderConfigField,\n AparteAIProviderConfigSchema,\n AparteModelConfig,\n ModelStatus,\n ModelLoadProgress,\n AparteModelChangeEventDetail,\n AparteMessageDoneEventDetail,\n AparteMessageInfoEventDetail,\n AparteSiblingInfo,\n AparteBranchNavigateEventDetail,\n ApartePathChangedEventDetail,\n AparteRetryEventDetail,\n AparteEditEventDetail,\n AparteFeedbackEventDetail,\n AparteActionEventDetail,\n AparteArtifactStartEventDetail,\n AparteArtifactDeltaEventDetail,\n AparteArtifactReadyEventDetail,\n AparteArtifactOpenEventDetail,\n // Chat types\n AparteChatRequest,\n AparteChatResponse,\n AparteChatMessage,\n AparteContentPart,\n AparteTextPart,\n AparteImagePart,\n AparteFilePart,\n AparteStreamEvent,\n AparteStreamEventMap,\n AparteUsage,\n // Tool types\n AparteTool,\n AparteToolCall,\n AparteToolResult,\n AparteToolHandler,\n AparteToolRenderer,\n AparteToolDecisionDetail,\n AparteToolApprovalRequestDetail,\n AparteToolActionDetail,\n // Canonical imperative surface (aliased by every wrapper's handle type).\n AparteChatImperativeApi\n} from './types/index.js';\n\nexport { AparteErrorCode, AparteError, contentToText } from './types/index.js';\n\n// Export renderers\nexport {\n registerSegmentRenderer,\n unregisterSegmentRenderer,\n getSegmentRenderer,\n collectRendererStyles,\n registerDefaultRenderers\n} from './renderers/index.js';\n\n// Export components\nexport { AparteChat } from './components/index.js';\nexport { AparteChatBubble, populateBubbleFromMessage } from './components/index.js';\nexport type { SyncableBubble } from './components/index.js';\nexport { AparteChatStatus } from './components/index.js';\nexport { AparteChatViewport } from './components/index.js';\n\n// Export composer primitives\nexport { AparteComposer, AparteComposerInput, AparteComposerSend, AparteComposerCancel, AparteComposerAttachments, AparteComposerAddAttachment, AparteComposerAction } from './components/index.js';\nexport type { AparteComposerEventMap, AparteComposerEventType, AparteComposerState, AparteComposerChangeEventDetail } from './components/index.js';\n\n// Export conversation list primitive\nexport { AparteConversationList } from './components/index.js';\nexport type { AparteConversationListItem, AparteConversationSelectDetail, AparteConversationDeleteDetail } from './components/index.js';\n\n// Export conversations (types, adapter contract, manager)\nexport type {\n AparteConversation,\n AparteConversationMeta,\n AparteStorageAdapter,\n AparteMemoryFact,\n AparteArtifactRow,\n AparteAttachmentRow,\n} from './conversations/index.js';\nexport { APARTE_CONVERSATION_SCHEMA_VERSION } from './conversations/index.js';\nexport { ConversationManager, type ConversationManagerOptions } from './conversations/index.js';\nexport {\n AparteConversationController,\n type AparteChatBinding,\n type AparteConversationControllerOptions,\n} from './conversations/index.js';\n\n// Export the framework-agnostic chat-host orchestrator (streaming/branch/\n// host-method layer that every framework wrapper binds to).\nexport {\n AparteChatHost,\n type AparteChatHostBinding,\n type AparteChatHostOptions,\n} from './host/index.js';\n\n// Export parsers\nexport { AparteStreamParser, parseMarkdownToSegments, deriveArtifactKind } from './parsers/index.js';\nexport type { AparteStreamParserOptions, AparteThinkingDelimiterPair, AparteParserState, AparteParserResult } from './parsers/index.js';\nexport { parseAparteEventStream } from './parsers/index.js';\n\n// Export config\nexport { AparteConfig, AparteConfigClass } from './config/index.js';\nexport { resolveConfig, attachConfig, detachConfig, runWithConfig, contextConfig, APARTE_HOST_ATTR } from './config/index.js';\nexport type { AparteMarkdownProvider, AparteStreamingMarkdownProvider, AparteStreamingMarkdownRenderer, AparteHighlightProvider, AparteSystemPromptVarsProvider, AparteSkeletonProvider, AparteSkeletonType, AparteLocale, AparteAction, AparteActionZone, AparteIconProvider, AparteIconName, AparteAvatarProvider, AparteStatusRenderer, AparteErrorRenderer, AparteAttachmentRenderer, AparteSiblingNavRenderer, AparteBubbleShellRenderer, AparteModelPreference, AparteModelPreferenceProvider, AparteArtifactPreviewBuilder, AparteSanitizer } from './config/index.js';\nexport { DEFAULT_ICON_FALLBACKS, DEFAULT_SKELETON_FALLBACKS, DEFAULT_LOCALE, defaultSanitizer, isSafeUrl } from './config/index.js';\n\n// Export Client\nexport { AparteClient } from './client/aparte-client.js';\n\n// Custom-element interop helpers shared by the framework wrappers' AparteUi.\nexport { applyElementProps, DEFAULT_UI_EVENTS } from './interop/element-props.js';\nexport type { AparteClientOptions, AparteToolApprovalResolver, AparteCompactionSelector } from './client/aparte-client.js';\n// Structured-stream adapter — DOM half of the runStreamAgent loop (see stream-adapter.ts).\nexport { createStreamAdapter, readableToAsyncIterable } from './client/stream-adapter.js';\nexport type { AparteStreamRunEvent, AparteStreamRunEmitter, StreamAdapterTarget, CreateStreamAdapterOptions, AparteStreamRunner, AparteStreamRunOptions } from './client/stream-adapter.js';\n\n// Export transport seam (where chat requests go + how auth is handled)\nexport { DirectTransport, BackendTransport, createAparteChatHandler, isFormatAdapter } from './transport/index.js';\nexport type { AparteTransport, AparteTransportContext, AparteFormatAdapter, AparteVendorRequest, BackendTransportOptions, DirectTransportOptions, AparteChatHandlerOptions } from './transport/index.js';\n\n// Export runtime utilities\nexport { MessageRepository } from './runtime/message-repository.js';\nexport type { ExportedMessageRepository } from './runtime/message-repository.js';\n\n// Export elicitation (human-in-the-loop typed input)\nexport { requestUserInput, buildElicitationPanel } from './elicitation/index.js';\nexport type {\n AparteElicitationSchema,\n AparteElicitationField,\n AparteElicitationEnumField,\n AparteElicitationBooleanField,\n AparteElicitationStringField,\n AparteElicitationObjectSchema,\n AparteElicitationRequest,\n AparteElicitationResult,\n AparteElicitationPresenter,\n BuiltElicitationPanel,\n} from './elicitation/index.js';\n\n// Export the default elicitation presenter Web Component\nexport { AparteElicitation } from './components/elicitation/aparte-elicitation.js';\n\n// Auto-register components when module is imported\n// Components register themselves in their files\nimport './components/chat/aparte-chat.js';\nimport './components/bubble/aparte-chat-bubble.js';\nimport './components/status/aparte-chat-status.js';\nimport './components/viewport/aparte-chat-viewport.js';\nimport './components/elicitation/aparte-elicitation.js';\n// Import primitives to auto-register\nimport './primitives/select/aparte-select.js';\nimport './primitives/select/aparte-option.js';\nimport './primitives/select/aparte-optgroup.js';\n\n/**\n * Utility to ensure all components are registered\n * Call this if using dynamic imports\n */\nexport function registerAllComponents(): void {\n // Components self-register, but this ensures imports are not tree-shaken\n const _chat = customElements.get('aparte-chat');\n const _viewport = customElements.get('aparte-chat-viewport');\n const _bubble = customElements.get('aparte-chat-bubble');\n const _status = customElements.get('aparte-chat-status');\n\n if (!_chat || !_viewport || !_bubble || !_status) {\n console.warn('[Aparte] Some components may not be registered. Ensure all component files are imported.');\n }\n}\n"],"names":["n","e","o","s","a","l","x","b","c","m","i","f","h","root"],"mappings":"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"}