@refraction-ui/react 0.19.1 → 0.20.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 (342) hide show
  1. package/dist/chunk-533MCMSU.js +2355 -0
  2. package/dist/chunk-533MCMSU.js.map +7 -0
  3. package/dist/chunk-AMK4VCBG.js +250 -0
  4. package/dist/chunk-AMK4VCBG.js.map +7 -0
  5. package/dist/chunk-BOLFYVI6.js +90 -0
  6. package/dist/chunk-BOLFYVI6.js.map +7 -0
  7. package/dist/chunk-F7B64KT3.js +187 -0
  8. package/dist/chunk-F7B64KT3.js.map +7 -0
  9. package/dist/chunk-FD37DFCC.js +77 -0
  10. package/dist/chunk-FD37DFCC.js.map +7 -0
  11. package/dist/chunk-H54FLNAF.js +132 -0
  12. package/dist/chunk-H54FLNAF.js.map +7 -0
  13. package/dist/chunk-INP46354.js +664 -0
  14. package/dist/chunk-INP46354.js.map +7 -0
  15. package/dist/chunk-ONACRMG4.js +116 -0
  16. package/dist/chunk-ONACRMG4.js.map +7 -0
  17. package/dist/chunk-SDZ3LROZ.js +7 -0
  18. package/dist/chunk-SDZ3LROZ.js.map +7 -0
  19. package/dist/chunk-TOZBR4GL.js +154 -0
  20. package/dist/chunk-TOZBR4GL.js.map +7 -0
  21. package/dist/chunk-UNEM2TRI.js +225 -0
  22. package/dist/chunk-UNEM2TRI.js.map +7 -0
  23. package/dist/chunk-VK3EQ34F.js +92 -0
  24. package/dist/chunk-VK3EQ34F.js.map +7 -0
  25. package/dist/chunk-WK2IIUFO.js +316 -0
  26. package/dist/chunk-WK2IIUFO.js.map +7 -0
  27. package/dist/chunk-WSPJTQAV.js +59 -0
  28. package/dist/chunk-WSPJTQAV.js.map +7 -0
  29. package/dist/chunk-XWP763SH.js +3 -2
  30. package/dist/chunk-XWP763SH.js.map +7 -1
  31. package/dist/chunk-Y2FNNAIL.js +80 -0
  32. package/dist/chunk-Y2FNNAIL.js.map +1 -0
  33. package/dist/{chunk-4A4BW3GR.js → chunk-ZF3OHCGV.js} +28 -5
  34. package/dist/chunk-ZF3OHCGV.js.map +7 -0
  35. package/dist/form.cjs +5 -11
  36. package/dist/form.cjs.map +1 -1
  37. package/dist/form.js +6 -12
  38. package/dist/form.js.map +1 -1
  39. package/dist/index.cjs +2879 -33936
  40. package/dist/index.cjs.map +1 -1
  41. package/dist/index.d.cts +1 -0
  42. package/dist/index.d.ts +1 -0
  43. package/dist/index.js +126 -28780
  44. package/dist/internal/react-app-shell/index.d.cts +2 -22
  45. package/dist/internal/react-app-shell/index.d.ts +2 -22
  46. package/dist/internal/react-badge/index.d.cts +5 -0
  47. package/dist/internal/react-badge/index.d.ts +5 -0
  48. package/dist/internal/react-callout/index.d.cts +4 -0
  49. package/dist/internal/react-callout/index.d.ts +4 -0
  50. package/dist/internal/react-card/index.d.cts +8 -1
  51. package/dist/internal/react-card/index.d.ts +8 -1
  52. package/dist/internal/react-collapsible/index.d.cts +0 -3
  53. package/dist/internal/react-collapsible/index.d.ts +0 -3
  54. package/dist/internal/react-combobox/index.d.cts +0 -3
  55. package/dist/internal/react-combobox/index.d.ts +0 -3
  56. package/dist/internal/react-command/index.d.cts +0 -3
  57. package/dist/internal/react-command/index.d.ts +0 -3
  58. package/dist/internal/react-data-table/index.d.cts +0 -3
  59. package/dist/internal/react-data-table/index.d.ts +0 -3
  60. package/dist/internal/react-dialog/index.d.cts +0 -3
  61. package/dist/internal/react-dialog/index.d.ts +0 -3
  62. package/dist/internal/react-dropdown-menu/index.d.cts +0 -3
  63. package/dist/internal/react-dropdown-menu/index.d.ts +0 -3
  64. package/dist/internal/react-feedback-dialog/index.d.cts +0 -3
  65. package/dist/internal/react-feedback-dialog/index.d.ts +0 -3
  66. package/dist/internal/react-form/index.d.cts +2 -21
  67. package/dist/internal/react-form/index.d.ts +2 -21
  68. package/dist/internal/react-keyboard-shortcut/index.d.cts +0 -6
  69. package/dist/internal/react-keyboard-shortcut/index.d.ts +0 -6
  70. package/dist/internal/react-link-card/index.d.cts +8 -2
  71. package/dist/internal/react-link-card/index.d.ts +8 -2
  72. package/dist/internal/react-popover/index.d.cts +0 -3
  73. package/dist/internal/react-popover/index.d.ts +0 -3
  74. package/dist/internal/react-sheet/index.d.cts +0 -3
  75. package/dist/internal/react-sheet/index.d.ts +0 -3
  76. package/dist/internal/react-slot/index.d.cts +23 -0
  77. package/dist/internal/react-slot/index.d.ts +23 -0
  78. package/dist/internal/react-toast/index.d.cts +0 -3
  79. package/dist/internal/react-toast/index.d.ts +0 -3
  80. package/dist/internal/react-tooltip/index.d.cts +0 -3
  81. package/dist/internal/react-tooltip/index.d.ts +0 -3
  82. package/dist/react-accordion.js +125 -0
  83. package/dist/react-accordion.js.map +7 -0
  84. package/dist/react-ai.js +257 -0
  85. package/dist/react-ai.js.map +7 -0
  86. package/dist/react-analytics.js +1698 -0
  87. package/dist/react-analytics.js.map +7 -0
  88. package/dist/react-animated-text.js +164 -0
  89. package/dist/react-animated-text.js.map +7 -0
  90. package/dist/react-app-shell.js +631 -0
  91. package/dist/react-app-shell.js.map +7 -0
  92. package/dist/react-audience-feature-card.js +53 -0
  93. package/dist/react-audience-feature-card.js.map +7 -0
  94. package/dist/react-audio-room.js +166 -0
  95. package/dist/react-audio-room.js.map +7 -0
  96. package/dist/react-auth.js +211 -0
  97. package/dist/react-auth.js.map +7 -0
  98. package/dist/react-avatar-group.js +154 -0
  99. package/dist/react-avatar-group.js.map +7 -0
  100. package/dist/react-avatar.js +168 -0
  101. package/dist/react-avatar.js.map +7 -0
  102. package/dist/react-badge.js +86 -0
  103. package/dist/react-badge.js.map +7 -0
  104. package/dist/react-bottom-nav.js +67 -0
  105. package/dist/react-bottom-nav.js.map +7 -0
  106. package/dist/react-brand-network-cell.js +92 -0
  107. package/dist/react-brand-network-cell.js.map +7 -0
  108. package/dist/react-breadcrumbs.js +104 -0
  109. package/dist/react-breadcrumbs.js.map +7 -0
  110. package/dist/react-browser-chrome-mock.js +89 -0
  111. package/dist/react-browser-chrome-mock.js.map +7 -0
  112. package/dist/react-button.js +13 -0
  113. package/dist/react-button.js.map +7 -0
  114. package/dist/react-calendar.js +301 -0
  115. package/dist/react-calendar.js.map +7 -0
  116. package/dist/react-call-controls.js +113 -0
  117. package/dist/react-call-controls.js.map +7 -0
  118. package/dist/react-callout.js +152 -0
  119. package/dist/react-callout.js.map +7 -0
  120. package/dist/react-card-grid.js +34 -0
  121. package/dist/react-card-grid.js.map +7 -0
  122. package/dist/react-card.js +200 -0
  123. package/dist/react-card.js.map +7 -0
  124. package/dist/react-carousel.js +132 -0
  125. package/dist/react-carousel.js.map +7 -0
  126. package/dist/react-charts.js +509 -0
  127. package/dist/react-charts.js.map +7 -0
  128. package/dist/react-checkbox.js +156 -0
  129. package/dist/react-checkbox.js.map +7 -0
  130. package/dist/react-checklist.js +168 -0
  131. package/dist/react-checklist.js.map +7 -0
  132. package/dist/react-code-block.js +78 -0
  133. package/dist/react-code-block.js.map +7 -0
  134. package/dist/react-code-editor.js +184 -0
  135. package/dist/react-code-editor.js.map +7 -0
  136. package/dist/react-collapsible.js +192 -0
  137. package/dist/react-collapsible.js.map +7 -0
  138. package/dist/react-combobox.js +609 -0
  139. package/dist/react-combobox.js.map +7 -0
  140. package/dist/react-command-input.js +202 -0
  141. package/dist/react-command-input.js.map +7 -0
  142. package/dist/react-command.js +364 -0
  143. package/dist/react-command.js.map +7 -0
  144. package/dist/react-composer.js +2036 -0
  145. package/dist/react-composer.js.map +7 -0
  146. package/dist/react-content-protection.js +133 -0
  147. package/dist/react-content-protection.js.map +7 -0
  148. package/dist/react-conversation.js +1226 -0
  149. package/dist/react-conversation.js.map +7 -0
  150. package/dist/react-cookie-consent.js +291 -0
  151. package/dist/react-cookie-consent.js.map +7 -0
  152. package/dist/react-data-table.js +310 -0
  153. package/dist/react-data-table.js.map +7 -0
  154. package/dist/react-date-picker.js +95 -0
  155. package/dist/react-date-picker.js.map +7 -0
  156. package/dist/react-device-frame.js +137 -0
  157. package/dist/react-device-frame.js.map +7 -0
  158. package/dist/react-dialog.js +218 -0
  159. package/dist/react-dialog.js.map +7 -0
  160. package/dist/react-diff-viewer.js +460 -0
  161. package/dist/react-diff-viewer.js.map +7 -0
  162. package/dist/react-dropdown-menu.js +292 -0
  163. package/dist/react-dropdown-menu.js.map +7 -0
  164. package/dist/react-editor-status-bar.js +148 -0
  165. package/dist/react-editor-status-bar.js.map +7 -0
  166. package/dist/react-editor-tabs.js +159 -0
  167. package/dist/react-editor-tabs.js.map +7 -0
  168. package/dist/react-emoji-picker.js +238 -0
  169. package/dist/react-emoji-picker.js.map +7 -0
  170. package/dist/react-empty-state.js +90 -0
  171. package/dist/react-empty-state.js.map +7 -0
  172. package/dist/react-feedback-dialog.js +275 -0
  173. package/dist/react-feedback-dialog.js.map +7 -0
  174. package/dist/react-file-tree.js +376 -0
  175. package/dist/react-file-tree.js.map +7 -0
  176. package/dist/react-file-upload.js +360 -0
  177. package/dist/react-file-upload.js.map +7 -0
  178. package/dist/react-floating-reactions.js +124 -0
  179. package/dist/react-floating-reactions.js.map +7 -0
  180. package/dist/react-flow-editor.js +198 -0
  181. package/dist/react-flow-editor.js.map +7 -0
  182. package/dist/react-footer.js +67 -0
  183. package/dist/react-footer.js.map +7 -0
  184. package/dist/react-graph-view.js +197 -0
  185. package/dist/react-graph-view.js.map +7 -0
  186. package/dist/react-icon-system.js +9 -0
  187. package/dist/react-icon-system.js.map +7 -0
  188. package/dist/react-infinite-canvas.js +8 -0
  189. package/dist/react-infinite-canvas.js.map +7 -0
  190. package/dist/react-inline-editor.js +216 -0
  191. package/dist/react-inline-editor.js.map +7 -0
  192. package/dist/react-input-group.js +150 -0
  193. package/dist/react-input-group.js.map +7 -0
  194. package/dist/react-input.js +10 -0
  195. package/dist/react-input.js.map +7 -0
  196. package/dist/react-install-prompt.js +132 -0
  197. package/dist/react-install-prompt.js.map +7 -0
  198. package/dist/react-kanban-board.js +198 -0
  199. package/dist/react-kanban-board.js.map +7 -0
  200. package/dist/react-keyboard-shortcut.js +36 -0
  201. package/dist/react-keyboard-shortcut.js.map +7 -0
  202. package/dist/react-language-selector.js +311 -0
  203. package/dist/react-language-selector.js.map +7 -0
  204. package/dist/react-link-card.js +48 -0
  205. package/dist/react-link-card.js.map +7 -0
  206. package/dist/react-live-captions.js +92 -0
  207. package/dist/react-live-captions.js.map +7 -0
  208. package/dist/react-live-cursors.js +145 -0
  209. package/dist/react-live-cursors.js.map +7 -0
  210. package/dist/react-live-transcript.js +117 -0
  211. package/dist/react-live-transcript.js.map +7 -0
  212. package/dist/react-location-selector.js +252 -0
  213. package/dist/react-location-selector.js.map +7 -0
  214. package/dist/react-logger.js +415 -0
  215. package/dist/react-logger.js.map +7 -0
  216. package/dist/react-markdown-renderer.js +12 -0
  217. package/dist/react-markdown-renderer.js.map +7 -0
  218. package/dist/react-marquee-strip.js +62 -0
  219. package/dist/react-marquee-strip.js.map +7 -0
  220. package/dist/react-mascot.js +367 -0
  221. package/dist/react-mascot.js.map +7 -0
  222. package/dist/react-mastery-bar.js +97 -0
  223. package/dist/react-mastery-bar.js.map +7 -0
  224. package/dist/react-mini-map.js +207 -0
  225. package/dist/react-mini-map.js.map +7 -0
  226. package/dist/react-mobile-nav.js +216 -0
  227. package/dist/react-mobile-nav.js.map +7 -0
  228. package/dist/react-navbar.js +96 -0
  229. package/dist/react-navbar.js.map +7 -0
  230. package/dist/react-numbered-steps.js +67 -0
  231. package/dist/react-numbered-steps.js.map +7 -0
  232. package/dist/react-otp-input.js +318 -0
  233. package/dist/react-otp-input.js.map +7 -0
  234. package/dist/react-pagination.js +199 -0
  235. package/dist/react-pagination.js.map +7 -0
  236. package/dist/react-password-input.js +104 -0
  237. package/dist/react-password-input.js.map +7 -0
  238. package/dist/react-payment.js +81 -0
  239. package/dist/react-payment.js.map +7 -0
  240. package/dist/react-popover.js +176 -0
  241. package/dist/react-popover.js.map +7 -0
  242. package/dist/react-pre-call-lobby.js +309 -0
  243. package/dist/react-pre-call-lobby.js.map +7 -0
  244. package/dist/react-presence-indicator.js +86 -0
  245. package/dist/react-presence-indicator.js.map +7 -0
  246. package/dist/react-pricing-card.js +142 -0
  247. package/dist/react-pricing-card.js.map +7 -0
  248. package/dist/react-progress-display.js +188 -0
  249. package/dist/react-progress-display.js.map +7 -0
  250. package/dist/react-radial-gauge.js +193 -0
  251. package/dist/react-radial-gauge.js.map +7 -0
  252. package/dist/react-radio.js +169 -0
  253. package/dist/react-radio.js.map +7 -0
  254. package/dist/react-rating-scale.js +171 -0
  255. package/dist/react-rating-scale.js.map +7 -0
  256. package/dist/react-reaction-bar.js +111 -0
  257. package/dist/react-reaction-bar.js.map +7 -0
  258. package/dist/react-resizable-layout.js +298 -0
  259. package/dist/react-resizable-layout.js.map +7 -0
  260. package/dist/react-rich-editor.js +1 -0
  261. package/dist/react-rich-editor.js.map +7 -0
  262. package/dist/react-search-bar.js +285 -0
  263. package/dist/react-search-bar.js.map +7 -0
  264. package/dist/react-section-head.js +65 -0
  265. package/dist/react-section-head.js.map +7 -0
  266. package/dist/react-segmented-control.js +215 -0
  267. package/dist/react-segmented-control.js.map +7 -0
  268. package/dist/react-select.js +389 -0
  269. package/dist/react-select.js.map +7 -0
  270. package/dist/react-separator.js +86 -0
  271. package/dist/react-separator.js.map +7 -0
  272. package/dist/react-sheet.js +310 -0
  273. package/dist/react-sheet.js.map +7 -0
  274. package/dist/react-sidebar.js +100 -0
  275. package/dist/react-sidebar.js.map +7 -0
  276. package/dist/react-skeleton.js +91 -0
  277. package/dist/react-skeleton.js.map +7 -0
  278. package/dist/react-skip-to-content.js +38 -0
  279. package/dist/react-skip-to-content.js.map +7 -0
  280. package/dist/react-slide-viewer.js +264 -0
  281. package/dist/react-slide-viewer.js.map +7 -0
  282. package/dist/react-slider.js +105 -0
  283. package/dist/react-slider.js.map +7 -0
  284. package/dist/react-slot-picker.js +184 -0
  285. package/dist/react-slot-picker.js.map +7 -0
  286. package/dist/react-slot.js +7 -0
  287. package/dist/react-slot.js.map +7 -0
  288. package/dist/react-social-auth-button.js +169 -0
  289. package/dist/react-social-auth-button.js.map +7 -0
  290. package/dist/react-sortable-list.js +204 -0
  291. package/dist/react-sortable-list.js.map +7 -0
  292. package/dist/react-stat-grid.js +69 -0
  293. package/dist/react-stat-grid.js.map +7 -0
  294. package/dist/react-status-indicator.js +117 -0
  295. package/dist/react-status-indicator.js.map +7 -0
  296. package/dist/react-steps.js +167 -0
  297. package/dist/react-steps.js.map +7 -0
  298. package/dist/react-sticky-note.js +131 -0
  299. package/dist/react-sticky-note.js.map +7 -0
  300. package/dist/react-switch.js +139 -0
  301. package/dist/react-switch.js.map +7 -0
  302. package/dist/react-table-of-contents.js +80 -0
  303. package/dist/react-table-of-contents.js.map +7 -0
  304. package/dist/react-tabs.js +230 -0
  305. package/dist/react-tabs.js.map +7 -0
  306. package/dist/react-terminal.js +101 -0
  307. package/dist/react-terminal.js.map +7 -0
  308. package/dist/react-test-results.js +158 -0
  309. package/dist/react-test-results.js.map +7 -0
  310. package/dist/react-textarea.js +89 -0
  311. package/dist/react-textarea.js.map +7 -0
  312. package/dist/react-thread-view.js +139 -0
  313. package/dist/react-thread-view.js.map +7 -0
  314. package/dist/react-timeline.js +153 -0
  315. package/dist/react-timeline.js.map +7 -0
  316. package/dist/react-toast.js +253 -0
  317. package/dist/react-toast.js.map +7 -0
  318. package/dist/react-tooltip.js +221 -0
  319. package/dist/react-tooltip.js.map +7 -0
  320. package/dist/react-version-selector.js +270 -0
  321. package/dist/react-version-selector.js.map +7 -0
  322. package/dist/react-video-grid.js +129 -0
  323. package/dist/react-video-grid.js.map +7 -0
  324. package/dist/react-video-player.js +206 -0
  325. package/dist/react-video-player.js.map +7 -0
  326. package/dist/react-video-tile.js +8 -0
  327. package/dist/react-video-tile.js.map +7 -0
  328. package/dist/react-voice-pill.js +314 -0
  329. package/dist/react-voice-pill.js.map +7 -0
  330. package/dist/react-waveform.js +558 -0
  331. package/dist/react-waveform.js.map +7 -0
  332. package/dist/react-wizard.js +337 -0
  333. package/dist/react-wizard.js.map +7 -0
  334. package/dist/styles.css +7 -0
  335. package/dist/theme.js +1 -1
  336. package/package.json +3 -2
  337. package/dist/applicationinsights-web-H7OBLIVJ.js +0 -23393
  338. package/dist/applicationinsights-web-H7OBLIVJ.js.map +0 -1
  339. package/dist/chunk-4A4BW3GR.js.map +0 -1
  340. package/dist/index.js.map +0 -1
  341. package/dist/module-X3HTTRQK.js +0 -6438
  342. package/dist/module-X3HTTRQK.js.map +0 -1
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../conversation/src/selectors.ts", "../../conversation/src/conversation.ts", "../../react-conversation/src/use-conversation.ts", "../../react-conversation/src/composer.tsx", "../../react-conversation/src/chat.tsx"],
4
+ "sourcesContent": ["import type { ChatMessage, ConversationState, ThreadingMode } from './types.js'\n\n/** Sort by timestamp ascending (oldest first). */\nfunction byTime(a: ChatMessage, b: ChatMessage): number {\n return a.timestamp.getTime() - b.timestamp.getTime()\n}\n\n/** Find a message by id. */\nexport function findMessage(messages: ChatMessage[], id: string): ChatMessage | undefined {\n return messages.find((m) => m.id === id)\n}\n\n/** Resolve a message id to its thread root (itself if it's already a root). */\nexport function rootIdOf(messages: ChatMessage[], id: string): string {\n const m = findMessage(messages, id)\n if (!m) return id\n return m.parentId ?? m.id\n}\n\n/** Root (main-timeline) messages — those not belonging to a reply-thread. */\nexport function selectRoots(messages: ChatMessage[]): ChatMessage[] {\n return messages.filter((m) => !m.parentId).sort(byTime)\n}\n\n/** Replies belonging to a thread root, oldest first (excludes the root itself). */\nexport function selectReplies(messages: ChatMessage[], rootId: string): ChatMessage[] {\n return messages.filter((m) => m.parentId === rootId).sort(byTime)\n}\n\n/** A full thread: root message followed by its replies. */\nexport function selectThreadMessages(messages: ChatMessage[], rootId: string): ChatMessage[] {\n const root = findMessage(messages, rootId)\n const replies = selectReplies(messages, rootId)\n return root ? [root, ...replies] : replies\n}\n\n/** Number of replies in a thread. */\nexport function getReplyCount(messages: ChatMessage[], rootId: string): number {\n return messages.reduce((n, m) => (m.parentId === rootId ? n + 1 : n), 0)\n}\n\n/**\n * The main timeline for the active conversation, honoring the threading mode:\n * - `'inline'`: every message in chronological order (replies included).\n * - `'panel'`: only root messages (replies hidden behind their thread).\n */\nexport function selectMainTimeline(\n messages: ChatMessage[],\n mode: ThreadingMode,\n): ChatMessage[] {\n if (mode === 'panel') return selectRoots(messages)\n return [...messages].sort(byTime)\n}\n\n/** Convenience: main timeline from a store snapshot. */\nexport function selectTimelineFromState(state: ConversationState): ChatMessage[] {\n return selectMainTimeline(state.messages, state.threadingMode)\n}\n", "import { generateId } from '@refraction-ui/shared'\nimport { rootIdOf, selectRoots, selectThreadMessages } from './selectors.js'\nimport type {\n ChatAuthor,\n ChatMessage,\n Conversation,\n ConversationAPI,\n ConversationConfig,\n ConversationState,\n SendOptions,\n ThreadingMode,\n} from './types.js'\n\nconst DEFAULT_ASSISTANT: ChatAuthor = { id: 'assistant', name: 'Assistant' }\nconst DEFAULT_USER: ChatAuthor = { id: 'user', name: 'You' }\nconst DEFAULT_TITLE = 'New conversation'\n\n/** Default title: first line, trimmed to ~48 chars. */\nfunction defaultGenerateTitle(firstMessage: string): string {\n const firstLine = firstMessage.split('\\n', 1)[0]!.trim()\n if (firstLine.length <= 48) return firstLine || DEFAULT_TITLE\n return `${firstLine.slice(0, 47).trimEnd()}…`\n}\n\n/**\n * createConversation — headless multi-conversation chat store with reply-threads,\n * reactions, edit/delete, and streaming. Backend-agnostic: provide a\n * {@link ChatTransport} and `sendMessage` will optimistically append the user\n * message, stream the reply, and expose retry/stop. Without a transport it is a\n * pure local message log.\n */\nexport function createConversation(config: ConversationConfig = {}): ConversationAPI {\n const assistant = config.assistant ?? DEFAULT_ASSISTANT\n const currentUser = config.currentUser ?? DEFAULT_USER\n const generateTitle = config.generateTitle ?? defaultGenerateTitle\n // Injection boundary: ambient time is the default; inject `now` for deterministic timestamps.\n const now = config.now ?? (() => new Date())\n\n let transport = config.transport\n let threadingMode: ThreadingMode = config.threadingMode ?? 'inline'\n const conversations = new Map<string, Conversation>()\n const messagesByConv = new Map<string, ChatMessage[]>()\n let activeConversationId: string | null = config.activeConversationId ?? null\n let openThreadRootId: string | null = null\n let replyTarget: string | null = null\n let status: ConversationState['status'] = 'idle'\n let error: string | null = null\n let abortController: AbortController | null = null\n\n // Seed\n for (const c of config.conversations ?? []) {\n conversations.set(c.id, c)\n messagesByConv.set(c.id, [])\n }\n for (const [conversationId, msgs] of Object.entries(config.messages ?? {})) {\n messagesByConv.set(conversationId, [...msgs])\n }\n if (activeConversationId === null && config.conversations?.length) {\n activeConversationId = config.conversations[0]!.id\n }\n\n // — subscription —\n const listeners = new Set<() => void>()\n let snapshot: ConversationState = buildSnapshot()\n\n function buildSnapshot(): ConversationState {\n return {\n conversations: orderedConversations(),\n activeConversationId,\n messages: activeConversationId ? (messagesByConv.get(activeConversationId) ?? []) : [],\n openThreadRootId,\n replyTarget,\n threadingMode,\n status,\n error,\n }\n }\n\n function emit(): void {\n snapshot = buildSnapshot()\n for (const l of listeners) l()\n }\n\n function orderedConversations(): Conversation[] {\n return [...conversations.values()].sort(\n (a, b) => b.updatedAt.getTime() - a.updatedAt.getTime(),\n )\n }\n\n function touch(conversationId: string): void {\n const c = conversations.get(conversationId)\n if (c) conversations.set(conversationId, { ...c, updatedAt: now() })\n }\n\n function ensureActiveConversation(opts?: SendOptions): string {\n if (opts?.conversationId) {\n if (!conversations.has(opts.conversationId)) createConversationInternal({}, opts.conversationId)\n return opts.conversationId\n }\n if (activeConversationId && conversations.has(activeConversationId)) return activeConversationId\n return createConversationInternal({}).id\n }\n\n function createConversationInternal(\n opts: { title?: string; metadata?: Record<string, unknown> },\n id?: string,\n ): Conversation {\n const timestamp = now()\n const conversation: Conversation = {\n id: id ?? generateId('rfr-conv'),\n title: opts.title ?? DEFAULT_TITLE,\n createdAt: timestamp,\n updatedAt: timestamp,\n metadata: opts.metadata,\n }\n conversations.set(conversation.id, conversation)\n messagesByConv.set(conversation.id, [])\n activeConversationId = conversation.id\n return conversation\n }\n\n /** Run a transport stream into the given assistant message. */\n async function streamReply(\n conversationId: string,\n assistantMsg: ChatMessage,\n userMsg: ChatMessage,\n history: ChatMessage[],\n ): Promise<void> {\n abortController = new AbortController()\n status = 'streaming'\n emit()\n\n try {\n const stream = transport!.send({\n conversationId,\n message: userMsg,\n history,\n parentId: assistantMsg.parentId,\n signal: abortController.signal,\n })\n for await (const chunk of stream) {\n // Apply the delivered chunk before honoring an abort, so a `stop()` mid\n // stream keeps the partial reply rather than discarding the last token.\n if (chunk.content !== undefined) assistantMsg.content = chunk.content\n if (chunk.delta) assistantMsg.content += chunk.delta\n if (chunk.metadata) {\n assistantMsg.metadata = { ...assistantMsg.metadata, ...chunk.metadata }\n }\n emit()\n if (abortController.signal.aborted) break\n }\n assistantMsg.status = 'sent'\n status = 'idle'\n error = null\n } catch (err) {\n if (abortController.signal.aborted) {\n assistantMsg.status = 'sent'\n status = 'idle'\n } else {\n const message = err instanceof Error ? err.message : String(err)\n assistantMsg.status = 'error'\n assistantMsg.error = message\n status = 'error'\n error = message\n }\n } finally {\n abortController = null\n touch(conversationId)\n emit()\n }\n }\n\n /** History the transport sees: the thread when replying, else the main timeline. */\n function historyFor(list: ChatMessage[], parentId: string | undefined): ChatMessage[] {\n const scope = parentId\n ? selectThreadMessages(list, parentId)\n : selectRoots(list)\n return scope.filter((m) => m.status !== 'error')\n }\n\n const api: ConversationAPI = {\n getState() {\n return snapshot\n },\n\n subscribe(listener) {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n\n newConversation(opts) {\n const conversation = createConversationInternal(opts ?? {})\n openThreadRootId = null\n replyTarget = null\n emit()\n return conversation\n },\n\n selectConversation(conversationId) {\n if (!conversations.has(conversationId) || activeConversationId === conversationId) return\n activeConversationId = conversationId\n openThreadRootId = null\n replyTarget = null\n emit()\n },\n\n deleteConversation(conversationId) {\n if (!conversations.has(conversationId)) return\n conversations.delete(conversationId)\n messagesByConv.delete(conversationId)\n if (activeConversationId === conversationId) {\n activeConversationId = orderedConversations()[0]?.id ?? null\n openThreadRootId = null\n replyTarget = null\n }\n emit()\n },\n\n renameConversation(conversationId, title) {\n const c = conversations.get(conversationId)\n if (!c) return\n conversations.set(conversationId, { ...c, title })\n emit()\n },\n\n appendMessage(message) {\n const list = messagesByConv.get(message.conversationId)\n if (!list) return\n list.push(message)\n touch(message.conversationId)\n emit()\n },\n\n editMessage(messageId, content) {\n if (!activeConversationId) return\n const list = messagesByConv.get(activeConversationId)!\n const msg = list.find((m) => m.id === messageId)\n if (!msg) return\n msg.content = content\n msg.edited = true\n emit()\n },\n\n deleteMessage(messageId) {\n if (!activeConversationId) return\n const list = messagesByConv.get(activeConversationId)!\n const msg = list.find((m) => m.id === messageId)\n if (!msg) return\n const removeIds = new Set<string>([messageId])\n // Deleting a thread root removes its replies too.\n if (!msg.parentId) for (const r of list) if (r.parentId === messageId) removeIds.add(r.id)\n const next = list.filter((m) => !removeIds.has(m.id))\n messagesByConv.set(activeConversationId, next)\n if (openThreadRootId && removeIds.has(openThreadRootId)) openThreadRootId = null\n if (replyTarget && removeIds.has(replyTarget)) replyTarget = openThreadRootId\n emit()\n },\n\n react(messageId, emoji) {\n if (!activeConversationId) return\n const list = messagesByConv.get(activeConversationId)!\n const msg = list.find((m) => m.id === messageId)\n if (!msg) return\n const reactions = [...(msg.reactions ?? [])]\n const idx = reactions.findIndex((r) => r.emoji === emoji)\n if (idx === -1) {\n reactions.push({ emoji, count: 1, userReacted: true })\n } else {\n const r = reactions[idx]!\n if (r.userReacted) {\n const count = r.count - 1\n if (count <= 0) reactions.splice(idx, 1)\n else reactions[idx] = { ...r, count, userReacted: false }\n } else {\n reactions[idx] = { ...r, count: r.count + 1, userReacted: true }\n }\n }\n msg.reactions = reactions\n emit()\n },\n\n async sendMessage(content, opts) {\n const trimmed = content.trim()\n if (!trimmed && !opts?.attachments?.length) return\n\n const conversationId = ensureActiveConversation(opts)\n const list = messagesByConv.get(conversationId)!\n // Group under the originating root, but remember the specific message replied to.\n const parentId = opts?.replyTo ? rootIdOf(list, opts.replyTo) : undefined\n const replyToId = opts?.replyTo\n const isFirstRoot = !parentId && selectRoots(list).length === 0\n\n const userMsg: ChatMessage = {\n id: generateId('rfr-msg'),\n conversationId,\n role: 'user',\n author: currentUser,\n content: trimmed,\n timestamp: now(),\n status: 'sent',\n parentId,\n replyToId,\n attachments: opts?.attachments,\n metadata: opts?.metadata,\n }\n list.push(userMsg)\n\n const conversation = conversations.get(conversationId)!\n if (isFirstRoot && conversation.title === DEFAULT_TITLE) {\n conversations.set(conversationId, { ...conversation, title: generateTitle(trimmed) })\n }\n touch(conversationId)\n\n if (!transport) {\n status = 'idle'\n emit()\n return\n }\n\n // history excludes the just-pushed user message\n const history = historyFor(list, parentId).filter((m) => m.id !== userMsg.id)\n const assistantMsg: ChatMessage = {\n id: generateId('rfr-msg'),\n conversationId,\n role: 'assistant',\n author: assistant,\n content: '',\n timestamp: now(),\n status: 'streaming',\n parentId,\n }\n list.push(assistantMsg)\n await streamReply(conversationId, assistantMsg, userMsg, history)\n },\n\n async retryLast() {\n if (!activeConversationId || !transport) return\n const list = messagesByConv.get(activeConversationId)!\n const last = list[list.length - 1]\n const parentId = last?.parentId\n // Drop a trailing failed assistant message, if any.\n if (last && last.role === 'assistant' && last.status === 'error') list.pop()\n\n const scope = parentId ? selectThreadMessages(list, parentId) : selectRoots(list)\n const lastUser = [...scope].reverse().find((m) => m.role === 'user')\n if (!lastUser) return\n\n const history = historyFor(list, parentId)\n const assistantMsg: ChatMessage = {\n id: generateId('rfr-msg'),\n conversationId: activeConversationId,\n role: 'assistant',\n author: assistant,\n content: '',\n timestamp: now(),\n status: 'streaming',\n parentId,\n }\n list.push(assistantMsg)\n await streamReply(activeConversationId, assistantMsg, lastUser, history)\n },\n\n stop() {\n abortController?.abort()\n },\n\n openThread(rootId) {\n openThreadRootId = rootId\n replyTarget = rootId // reply to the root by default\n emit()\n },\n\n replyTo(messageId) {\n if (!activeConversationId) return\n const list = messagesByConv.get(activeConversationId)!\n // Open the originating thread, but target the specific message replied to.\n openThreadRootId = rootIdOf(list, messageId)\n replyTarget = messageId\n emit()\n },\n\n closeThread() {\n if (openThreadRootId === null && replyTarget === null) return\n openThreadRootId = null\n replyTarget = null\n emit()\n },\n\n setThreadingMode(mode) {\n if (threadingMode === mode) return\n threadingMode = mode\n emit()\n },\n\n setTransport(next) {\n transport = next\n },\n }\n\n return api\n}\n", "import * as React from 'react'\nimport { createConversation } from '@refraction-ui/conversation'\nimport type {\n ConversationAPI,\n ConversationConfig,\n ConversationState,\n} from '@refraction-ui/conversation'\n\nexport interface UseConversationResult {\n /** Live store snapshot (re-renders on change) */\n state: ConversationState\n /** The underlying store, for advanced/imperative use */\n api: ConversationAPI\n // Bound actions (stable references)\n sendMessage: ConversationAPI['sendMessage']\n newConversation: ConversationAPI['newConversation']\n selectConversation: ConversationAPI['selectConversation']\n deleteConversation: ConversationAPI['deleteConversation']\n renameConversation: ConversationAPI['renameConversation']\n editMessage: ConversationAPI['editMessage']\n deleteMessage: ConversationAPI['deleteMessage']\n react: ConversationAPI['react']\n retryLast: ConversationAPI['retryLast']\n stop: ConversationAPI['stop']\n openThread: ConversationAPI['openThread']\n replyTo: ConversationAPI['replyTo']\n closeThread: ConversationAPI['closeThread']\n setThreadingMode: ConversationAPI['setThreadingMode']\n}\n\n/**\n * useConversation — binds the headless `createConversation` store to React via\n * `useSyncExternalStore`. The store is created once; a changing `config.transport`\n * is hot-swapped so consumers can wire the backend after mount.\n */\nexport function useConversation(config?: ConversationConfig): UseConversationResult {\n const apiRef = React.useRef<ConversationAPI | null>(null)\n if (apiRef.current === null) {\n apiRef.current = createConversation(config)\n }\n const api = apiRef.current\n\n const state = React.useSyncExternalStore(api.subscribe, api.getState, api.getState)\n\n const transport = config?.transport\n React.useEffect(() => {\n if (transport) api.setTransport(transport)\n }, [api, transport])\n\n return {\n state,\n api,\n sendMessage: api.sendMessage,\n newConversation: api.newConversation,\n selectConversation: api.selectConversation,\n deleteConversation: api.deleteConversation,\n renameConversation: api.renameConversation,\n editMessage: api.editMessage,\n deleteMessage: api.deleteMessage,\n react: api.react,\n retryLast: api.retryLast,\n stop: api.stop,\n openThread: api.openThread,\n replyTo: api.replyTo,\n closeThread: api.closeThread,\n setThreadingMode: api.setThreadingMode,\n }\n}\n", "import * as React from 'react'\nimport { cn } from '@refraction-ui/shared'\nimport type { MessageAttachment } from '@refraction-ui/conversation'\nimport { detectTriggerInText } from '@refraction-ui/rich-editor'\n\nconst h = React.createElement\n\n// ── icons (inline Lucide-style SVGs, currentColor + stroke 2) ────────────────\nconst svg = (children: React.ReactNode, size = 16) =>\n h(\n 'svg',\n {\n xmlns: 'http://www.w3.org/2000/svg',\n viewBox: '0 0 24 24',\n width: size,\n height: size,\n fill: 'none',\n stroke: 'currentColor',\n strokeWidth: 2,\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n 'aria-hidden': true,\n },\n children,\n )\nconst IconAttach = () =>\n svg(h('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 17.93 8.81l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48' }))\nconst IconBold = () =>\n svg([\n h('path', { key: 'a', d: 'M6 4h8a4 4 0 0 1 0 8H6z' }),\n h('path', { key: 'b', d: 'M6 12h9a4 4 0 0 1 0 8H6z' }),\n ])\nconst IconItalic = () =>\n svg([\n h('line', { key: 'a', x1: 19, y1: 4, x2: 10, y2: 4 }),\n h('line', { key: 'b', x1: 14, y1: 20, x2: 5, y2: 20 }),\n h('line', { key: 'c', x1: 15, y1: 4, x2: 9, y2: 20 }),\n ])\nconst IconCode = () =>\n svg([\n h('polyline', { key: 'a', points: '16 18 22 12 16 6' }),\n h('polyline', { key: 'b', points: '8 6 2 12 8 18' }),\n ])\nconst IconLink = () =>\n svg([\n h('path', { key: 'a', d: 'M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71' }),\n h('path', { key: 'b', d: 'M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71' }),\n ])\nconst IconQuote = () =>\n svg([\n h('path', { key: 'a', d: 'M3 21c3 0 7-1 7-8V5c0-1.25-.756-2.017-2-2H4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2 1 0 1 0 1 1v1c0 1-1 2-2 2s-1 .008-1 1.031V20c0 1 0 1 1 1z' }),\n h('path', { key: 'b', d: 'M15 21c3 0 7-1 7-8V5c0-1.25-.757-2.017-2-2h-4c-1.25 0-2 .75-2 1.972V11c0 1.25.75 2 2 2h.75c0 2.25.25 4-2.75 4v3c0 1 0 1 1 1z' }),\n ])\nconst IconListUl = () =>\n svg([\n h('line', { key: 'a', x1: 8, y1: 6, x2: 21, y2: 6 }),\n h('line', { key: 'b', x1: 8, y1: 12, x2: 21, y2: 12 }),\n h('line', { key: 'c', x1: 8, y1: 18, x2: 21, y2: 18 }),\n h('line', { key: 'd', x1: 3, y1: 6, x2: 3.01, y2: 6 }),\n h('line', { key: 'e', x1: 3, y1: 12, x2: 3.01, y2: 12 }),\n h('line', { key: 'f', x1: 3, y1: 18, x2: 3.01, y2: 18 }),\n ])\nconst IconListOl = () =>\n svg([\n h('line', { key: 'a', x1: 10, y1: 6, x2: 21, y2: 6 }),\n h('line', { key: 'b', x1: 10, y1: 12, x2: 21, y2: 12 }),\n h('line', { key: 'c', x1: 10, y1: 18, x2: 21, y2: 18 }),\n h('path', { key: 'd', d: 'M4 6h1v4' }),\n h('path', { key: 'e', d: 'M4 10h2' }),\n h('path', { key: 'f', d: 'M6 18H4c0-1 2-2 2-3s-1-1.5-2-1' }),\n ])\nconst IconArrowUp = () =>\n svg([\n h('path', { key: 'a', d: 'M12 19V5' }),\n h('path', { key: 'b', d: 'm5 12 7-7 7 7' }),\n ])\nconst IconStop = () => svg(h('rect', { x: 7, y: 7, width: 10, height: 10, rx: 1.5 }))\n\n/** A `/` command entry. */\nexport interface SlashCommand {\n id: string\n label: string\n description?: string\n icon?: string\n /** Text inserted into the composer when chosen. If omitted, `onSlashCommand` fires and the trigger is removed. */\n insertText?: string\n}\n\n/** An `@` mention candidate. */\nexport interface Mention {\n id: string\n label: string\n avatarUrl?: string\n}\n\nexport interface ComposerProps {\n placeholder?: string\n busy?: boolean\n /** `/` command palette entries */\n slashCommands?: SlashCommand[]\n /** `@` mention candidates — array or (async) resolver of a query */\n mentions?: Mention[] | ((query: string) => Mention[] | Promise<Mention[]>)\n /** Show the markdown formatting toolbar (default true) */\n toolbar?: boolean\n /** Enable `:` emoji autocomplete (default true) */\n emoji?: boolean\n /** Enable the attach button (default true) */\n attachments?: boolean\n /** Error to surface above the input (with a Retry button) */\n error?: string | null\n onRetry?: () => void\n onSubmit: (content: string, attachments?: MessageAttachment[]) => void\n onStop?: () => void\n /** Called when a `/` command without `insertText` is chosen */\n onSlashCommand?: (cmd: SlashCommand) => void\n autoFocus?: boolean\n}\n\n/** Common :shortcode: → emoji. Small, dependency-free set covering the usual ones. */\nconst EMOJI: Record<string, string> = {\n smile: '😄', grin: '😁', joy: '😂', rofl: '🤣', wink: '😉', heart_eyes: '😍',\n thinking: '🤔', neutral: '😐', sob: '😭', scream: '😱', tada: '🎉', fire: '🔥',\n heart: '❤️', thumbsup: '👍', thumbsdown: '👎', clap: '👏', pray: '🙏', eyes: '👀',\n rocket: '🚀', sparkles: '✨', star: '⭐', check: '✅', x: '❌', warning: '⚠️',\n bulb: '💡', bug: '🐛', wave: '👋', ok_hand: '👌', muscle: '💪', '100': '💯',\n poop: '💩', ghost: '👻', robot: '🤖', cat: '🐱', dog: '🐶', coffee: '☕',\n pizza: '🍕', beer: '🍺', sun: '☀️', moon: '🌙', zap: '⚡',\n}\n\ninterface TriggerState {\n type: '/' | '@' | ':'\n query: string\n start: number // index of the trigger char in the value\n end: number // caret position\n}\n\nconst TRIGGER_CHARS: readonly TriggerState['type'][] = ['/', '@', ':']\n/** Queries are word-ish (`[\\w+-]*`) — a query hitting other punctuation closes the trigger. */\nconst TRIGGER_QUERY_PATTERN = /^[\\w+-]*$/\n\n/**\n * Detect an active `/`, `@`, or `:` trigger immediately before the caret.\n * Delegates the boundary/backward-scan rules to rich-editor's shared\n * `detectTriggerInText` and picks the trigger nearest the caret.\n */\nfunction detectTrigger(text: string, caret: number): TriggerState | null {\n let best: TriggerState | null = null\n for (const type of TRIGGER_CHARS) {\n const hit = detectTriggerInText(text, caret, type)\n if (!hit || !TRIGGER_QUERY_PATTERN.test(hit.query)) continue\n if (!best || hit.start > best.start) {\n best = { type, query: hit.query, start: hit.start, end: caret }\n }\n }\n return best\n}\n\n/**\n * Composer — rich message input: markdown formatting toolbar + Cmd/Ctrl shortcuts,\n * and `/` command, `@` mention, and `:` emoji autocomplete menus.\n */\nexport const Composer = React.forwardRef<HTMLDivElement, ComposerProps>(\n function Composer({ placeholder = 'Send a message…', busy = false, slashCommands = [], mentions, toolbar = true, emoji = true, attachments = true, error, onRetry, onSubmit, onStop, onSlashCommand, autoFocus }: ComposerProps, ref) {\n const [value, setValue] = React.useState('')\n const [pending, setPending] = React.useState<MessageAttachment[]>([])\n const [trigger, setTrigger] = React.useState<TriggerState | null>(null)\n const [active, setActive] = React.useState(0)\n const [mentionItems, setMentionItems] = React.useState<Mention[]>([])\n const textareaRef = React.useRef<HTMLTextAreaElement>(null)\n const fileRef = React.useRef<HTMLInputElement>(null)\n\n // Resolve `@` mentions for the current query.\n React.useEffect(() => {\n if (trigger?.type !== '@' || !mentions) {\n setMentionItems([])\n return\n }\n if (Array.isArray(mentions)) {\n const q = trigger.query.toLowerCase()\n setMentionItems(mentions.filter((m) => m.label.toLowerCase().includes(q)).slice(0, 8))\n return\n }\n let cancelled = false\n Promise.resolve(mentions(trigger.query)).then((res) => {\n if (!cancelled) setMentionItems(res.slice(0, 8))\n })\n return () => {\n cancelled = true\n }\n }, [trigger, mentions])\n\n // Items for the active trigger menu.\n const items: { key: string; primary: string; secondary?: string; icon?: string; apply: string; runCmd?: SlashCommand }[] =\n React.useMemo(() => {\n if (!trigger) return []\n const q = trigger.query.toLowerCase()\n if (trigger.type === '/') {\n return slashCommands\n .filter((c) => c.label.toLowerCase().includes(q) || c.id.toLowerCase().includes(q))\n .slice(0, 8)\n .map((c) => ({ key: c.id, primary: c.label, secondary: c.description, icon: c.icon, apply: c.insertText ?? '', runCmd: c }))\n }\n if (trigger.type === '@') {\n return mentionItems.map((m) => ({ key: m.id, primary: m.label, icon: m.avatarUrl ? '' : '@', apply: `@${m.label} ` }))\n }\n if (trigger.type === ':' && emoji) {\n return Object.entries(EMOJI)\n .filter(([name]) => name.includes(q))\n .slice(0, 8)\n .map(([name, char]) => ({ key: name, primary: `${char} :${name}:`, apply: char }))\n }\n return []\n }, [trigger, slashCommands, mentionItems, emoji])\n\n const menuOpen = trigger !== null && items.length > 0\n\n React.useEffect(() => setActive(0), [trigger?.type, trigger?.query])\n\n function syncFromTextarea(el: HTMLTextAreaElement) {\n setValue(el.value)\n setTrigger(detectTrigger(el.value, el.selectionStart ?? el.value.length))\n }\n\n function selectItem(i: number) {\n const item = items[i]\n if (!item || !trigger) return\n if (trigger.type === '/' && !item.apply && item.runCmd) {\n // Run-style command: drop the trigger text, fire the callback.\n const next = value.slice(0, trigger.start) + value.slice(trigger.end)\n setValue(next)\n setTrigger(null)\n onSlashCommand?.(item.runCmd)\n queueCaret(trigger.start)\n return\n }\n const next = value.slice(0, trigger.start) + item.apply + value.slice(trigger.end)\n setValue(next)\n setTrigger(null)\n queueCaret(trigger.start + item.apply.length)\n }\n\n function queueCaret(pos: number) {\n requestAnimationFrame(() => {\n const el = textareaRef.current\n if (!el) return\n el.focus()\n el.setSelectionRange(pos, pos)\n })\n }\n\n /** Wrap or prefix the current selection for a toolbar action. */\n function format(kind: 'bold' | 'italic' | 'code' | 'link' | 'quote' | 'ul' | 'ol') {\n const el = textareaRef.current\n if (!el) return\n const start = el.selectionStart ?? 0\n const end = el.selectionEnd ?? 0\n const sel = value.slice(start, end)\n let replacement = sel\n let caretOffset = 0\n if (kind === 'bold') replacement = `**${sel || 'bold'}**`\n else if (kind === 'italic') replacement = `*${sel || 'italic'}*`\n else if (kind === 'code') replacement = sel.includes('\\n') ? `\\n\\`\\`\\`\\n${sel}\\n\\`\\`\\`\\n` : `\\`${sel || 'code'}\\``\n else if (kind === 'link') {\n replacement = `[${sel || 'text'}](url)`\n caretOffset = replacement.length - 4 // place caret at \"url\"\n } else if (kind === 'quote' || kind === 'ul' || kind === 'ol') {\n const prefix = kind === 'quote' ? '> ' : kind === 'ul' ? '- ' : '1. '\n const block = (sel || 'item').split('\\n').map((l) => prefix + l).join('\\n')\n replacement = (start > 0 && value[start - 1] !== '\\n' ? '\\n' : '') + block\n }\n const next = value.slice(0, start) + replacement + value.slice(end)\n setValue(next)\n const caret = caretOffset ? start + caretOffset : start + replacement.length\n queueCaret(caret)\n }\n\n function submit() {\n const text = value.trim()\n if ((!text && pending.length === 0) || busy) return\n onSubmit(text, pending.length ? pending : undefined)\n setValue('')\n setPending([])\n setTrigger(null)\n }\n\n function onFiles(files: FileList | null) {\n if (!files) return\n setPending((p) => [\n ...p,\n ...Array.from(files).map((f) => ({\n id: `${f.name}-${f.size}-${f.lastModified}`,\n name: f.name,\n url: URL.createObjectURL(f),\n type: f.type || 'application/octet-stream',\n size: f.size,\n })),\n ])\n }\n\n function onKeyDown(e: React.KeyboardEvent<HTMLTextAreaElement>) {\n if (menuOpen) {\n if (e.key === 'ArrowDown') return (e.preventDefault(), setActive((a) => (a + 1) % items.length))\n if (e.key === 'ArrowUp') return (e.preventDefault(), setActive((a) => (a - 1 + items.length) % items.length))\n if (e.key === 'Enter' || e.key === 'Tab') return (e.preventDefault(), selectItem(active))\n if (e.key === 'Escape') return (e.preventDefault(), setTrigger(null))\n }\n const mod = e.metaKey || e.ctrlKey\n if (mod && e.key.toLowerCase() === 'b') return (e.preventDefault(), format('bold'))\n if (mod && e.key.toLowerCase() === 'i') return (e.preventDefault(), format('italic'))\n if (mod && e.key.toLowerCase() === 'e') return (e.preventDefault(), format('code'))\n if (mod && e.key.toLowerCase() === 'k') return (e.preventDefault(), format('link'))\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n submit()\n }\n }\n\n const iconBtn = 'flex h-8 w-8 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:bg-accent hover:text-foreground'\n const toolbarBtn = (icon: React.ReactNode, title: string, kind: Parameters<typeof format>[0]) =>\n h(\n 'button',\n {\n key: kind,\n type: 'button',\n title,\n 'aria-label': title,\n className: iconBtn,\n onMouseDown: (e: React.MouseEvent) => e.preventDefault(), // keep textarea selection\n onClick: () => format(kind),\n },\n icon,\n )\n const divider = () => h('span', { className: 'mx-1 h-5 w-px bg-border', 'aria-hidden': true })\n\n const menu = menuOpen\n ? h(\n 'div',\n {\n className:\n 'absolute bottom-full left-0 z-20 mb-2 w-72 overflow-hidden rounded-xl border border-border bg-popover shadow-lg',\n role: 'listbox',\n },\n h(\n 'div',\n { className: 'border-b border-border px-3 py-1.5 text-[10px] font-medium uppercase tracking-wide text-muted-foreground' },\n trigger?.type === '/' ? 'Commands' : trigger?.type === '@' ? 'Mentions' : 'Emoji',\n ),\n ...items.map((it, i) =>\n h(\n 'button',\n {\n key: it.key,\n type: 'button',\n role: 'option',\n 'aria-selected': i === active,\n className: cn(\n 'flex w-full items-center gap-2 px-3 py-2 text-left text-sm',\n i === active ? 'bg-accent' : 'hover:bg-accent/50',\n ),\n onMouseEnter: () => setActive(i),\n onMouseDown: (e: React.MouseEvent) => e.preventDefault(),\n onClick: () => selectItem(i),\n },\n it.icon ? h('span', { className: 'w-4 text-center text-muted-foreground' }, it.icon) : null,\n h('span', { className: 'flex-1 truncate' }, it.primary),\n it.secondary ? h('span', { className: 'truncate text-xs text-muted-foreground' }, it.secondary) : null,\n ),\n ),\n )\n : null\n\n return h(\n 'div',\n { ref, className: 'p-3' },\n h(\n 'div',\n { className: 'relative' },\n menu,\n // unified input card\n h(\n 'div',\n {\n className:\n // Subtle focus: slight border darkening + a soft shadow lift — no\n // bright colored ring (matches Claude/ChatGPT).\n 'overflow-hidden rounded-2xl border border-border bg-background shadow-sm transition-shadow focus-within:border-foreground/25 focus-within:shadow-md',\n },\n // error banner\n error\n ? h(\n 'div',\n { className: 'flex items-center gap-2 border-b border-border bg-destructive/5 px-3 py-2 text-xs text-destructive', role: 'alert' },\n h('span', { className: 'flex-1 truncate' }, error),\n onRetry ? h('button', { type: 'button', className: 'font-medium underline', onClick: () => onRetry() }, 'Retry') : null,\n )\n : null,\n // attachment chips\n pending.length > 0\n ? h(\n 'div',\n { className: 'flex flex-wrap gap-2 px-3 pt-3' },\n ...pending.map((a) =>\n h(\n 'span',\n { key: a.id, className: 'inline-flex items-center gap-1 rounded-md bg-muted px-2 py-0.5 text-xs' },\n a.name,\n h(\n 'button',\n { type: 'button', className: 'text-muted-foreground hover:text-destructive', onClick: () => setPending((p) => p.filter((x) => x.id !== a.id)) },\n '✕',\n ),\n ),\n ),\n )\n : null,\n // textarea (borderless)\n h('textarea', {\n ref: textareaRef,\n className: 'block max-h-40 w-full resize-none bg-transparent px-3.5 py-3 text-sm placeholder:text-muted-foreground focus:outline-none',\n rows: 1,\n value,\n placeholder,\n autoFocus,\n 'aria-label': 'Message',\n onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => syncFromTextarea(e.target),\n onClick: (e: React.MouseEvent<HTMLTextAreaElement>) => syncFromTextarea(e.currentTarget),\n onKeyUp: (e: React.KeyboardEvent<HTMLTextAreaElement>) => syncFromTextarea(e.currentTarget),\n onKeyDown,\n onBlur: () => setTimeout(() => setTrigger(null), 120),\n }),\n // bottom action bar\n h(\n 'div',\n { className: 'flex items-center gap-0.5 px-2 pb-2' },\n attachments\n ? h(\n React.Fragment,\n null,\n h('input', {\n ref: fileRef,\n type: 'file',\n accept: 'image/*',\n multiple: true,\n className: 'hidden',\n onChange: (e: React.ChangeEvent<HTMLInputElement>) => {\n onFiles(e.target.files)\n e.target.value = ''\n },\n }),\n h('button', { type: 'button', className: iconBtn, 'aria-label': 'Attach image or GIF', onClick: () => fileRef.current?.click() }, h(IconAttach)),\n )\n : null,\n attachments && toolbar ? divider() : null,\n toolbar\n ? h(\n React.Fragment,\n null,\n toolbarBtn(h(IconBold), 'Bold (⌘B)', 'bold'),\n toolbarBtn(h(IconItalic), 'Italic (⌘I)', 'italic'),\n toolbarBtn(h(IconCode), 'Code (⌘E)', 'code'),\n toolbarBtn(h(IconLink), 'Link (⌘K)', 'link'),\n divider(),\n toolbarBtn(h(IconQuote), 'Quote', 'quote'),\n toolbarBtn(h(IconListUl), 'Bulleted list', 'ul'),\n toolbarBtn(h(IconListOl), 'Numbered list', 'ol'),\n )\n : null,\n h('div', { className: 'flex-1' }),\n busy\n ? h(\n 'button',\n { type: 'button', 'aria-label': 'Stop', className: 'flex h-9 w-9 items-center justify-center rounded-full bg-primary text-primary-foreground transition hover:opacity-90', onClick: () => onStop?.() },\n h(IconStop),\n )\n : h(\n 'button',\n {\n type: 'button',\n 'aria-label': 'Send',\n className: 'flex h-9 w-9 items-center justify-center rounded-full bg-primary text-primary-foreground transition hover:opacity-90 disabled:bg-muted disabled:text-muted-foreground disabled:opacity-100',\n disabled: !value.trim() && pending.length === 0,\n onClick: submit,\n },\n h(IconArrowUp),\n ),\n ),\n ),\n ),\n )\n },\n)\n", "import * as React from 'react'\nimport { cn } from '@refraction-ui/shared'\nimport { MarkdownRenderer } from '@refraction-ui/react-markdown-renderer'\nimport { formatTimestamp, formatRelativeTime } from '@refraction-ui/thread-view'\nimport {\n selectMainTimeline,\n selectThreadMessages,\n getReplyCount,\n findMessage,\n rootIdOf,\n type ChatMessage,\n type MessageAttachment,\n type ThreadingMode,\n} from '@refraction-ui/conversation'\nimport { Composer, type SlashCommand, type Mention } from './composer.js'\nimport type { UseConversationResult } from './use-conversation.js'\n\nconst h = React.createElement\n\nconst QUICK_EMOJIS = ['👍', '❤️', '😂', '🎉', '👀', '🙏']\n\n/** Chat-tuned markdown: kills article-sized prose margins/headings inside messages. */\nconst chatMd = cn(\n 'max-w-none text-sm',\n '[&_p]:my-1 [&_p:first-child]:mt-0 [&_p:last-child]:mb-0',\n '[&_pre]:my-2 [&_pre]:rounded-md [&_pre]:text-xs [&_pre]:leading-relaxed',\n '[&_ul]:my-1 [&_ol]:my-1 [&_li]:my-0.5',\n '[&_h1]:text-base [&_h1]:font-semibold [&_h1]:mt-2 [&_h1]:mb-1',\n '[&_h2]:text-sm [&_h2]:font-semibold [&_h2]:mt-2 [&_h2]:mb-1',\n '[&_h3]:text-sm [&_h3]:font-semibold',\n '[&_blockquote]:my-1 [&_blockquote]:border-l-2 [&_blockquote]:pl-2 [&_blockquote]:not-italic [&_blockquote]:text-muted-foreground',\n '[&_img]:my-1 [&_img]:max-h-60 [&_img]:rounded-md',\n '[&_code]:text-[0.85em]',\n)\n\nexport interface ChatProps {\n conversation: UseConversationResult\n showConversationList?: boolean\n showModeToggle?: boolean\n placeholder?: string\n currentUserId?: string\n emptyState?: React.ReactNode\n className?: string\n // composer extras\n slashCommands?: SlashCommand[]\n mentions?: Mention[] | ((query: string) => Mention[] | Promise<Mention[]>)\n onSlashCommand?: (cmd: SlashCommand) => void\n composerToolbar?: boolean\n}\n\nfunction Avatar({ name, avatarUrl, size = 8 }: { name: string; avatarUrl?: string; size?: number }) {\n return h(\n 'div',\n {\n className: cn(\n 'flex-shrink-0 overflow-hidden rounded-full bg-muted flex items-center justify-center text-xs font-medium',\n size === 8 ? 'h-8 w-8' : 'h-7 w-7',\n ),\n },\n avatarUrl\n ? h('img', { src: avatarUrl, alt: name, className: 'h-full w-full object-cover' })\n : (name.charAt(0) || '?').toUpperCase(),\n )\n}\n\nfunction TypingDots() {\n return h(\n 'div',\n { className: 'flex items-center gap-1 py-1.5', 'aria-label': 'Assistant is typing' },\n ...[0, 150, 300].map((delay) =>\n h('span', {\n key: delay,\n className: 'h-1.5 w-1.5 rounded-full bg-muted-foreground/60 animate-bounce',\n style: { animationDelay: `${delay}ms` },\n }),\n ),\n )\n}\n\nfunction Attachments({ attachments }: { attachments: MessageAttachment[] }) {\n return h(\n 'div',\n { className: 'mt-2 flex flex-wrap gap-2' },\n ...attachments.map((a) =>\n a.type.startsWith('image/')\n ? h('img', { key: a.id, src: a.url, alt: a.name, className: 'max-h-60 rounded-md border border-border object-contain' })\n : h(\n 'a',\n {\n key: a.id,\n href: a.url,\n target: '_blank',\n rel: 'noreferrer',\n className: 'inline-flex items-center gap-2 rounded-md border border-border bg-background/60 px-2 py-1 text-xs',\n },\n '📎 ',\n a.name,\n ),\n ),\n )\n}\n\nfunction MessageBody({ message }: { message: ChatMessage }) {\n if (message.status === 'streaming' && message.content === '') return h(TypingDots)\n return h(\n React.Fragment,\n null,\n message.content ? h(MarkdownRenderer, { content: message.content, size: 'sm', className: chatMd }) : null,\n message.attachments && message.attachments.length > 0 ? h(Attachments, { attachments: message.attachments }) : null,\n message.status === 'error'\n ? h('div', { className: 'mt-1 text-xs text-destructive', role: 'alert' }, message.error ?? 'Failed to send.')\n : null,\n )\n}\n\nfunction Reactions({ message, onReact, align }: { message: ChatMessage; onReact: (e: string) => void; align: 'start' | 'end' }) {\n if (!message.reactions || message.reactions.length === 0) return null\n return h(\n 'div',\n { className: cn('mt-1 flex flex-wrap gap-1', align === 'end' && 'justify-end') },\n ...message.reactions.map((r) =>\n h(\n 'button',\n {\n key: r.emoji,\n type: 'button',\n onClick: () => onReact(r.emoji),\n className: cn(\n 'inline-flex items-center gap-1 rounded-full border px-1.5 py-0.5 text-xs',\n r.userReacted ? 'border-primary bg-primary/10' : 'border-border bg-background',\n ),\n },\n `${r.emoji} ${r.count}`,\n ),\n ),\n )\n}\n\nfunction QuotedParent({ parent, onClick }: { parent: ChatMessage; onClick: () => void }) {\n const snippet = parent.content.length > 80 ? `${parent.content.slice(0, 80)}…` : parent.content\n return h(\n 'button',\n {\n type: 'button',\n onClick,\n className:\n 'mb-1 flex max-w-full items-start gap-2 rounded-md border-l-2 border-primary/50 bg-muted/50 px-2 py-1 text-left text-xs text-muted-foreground hover:bg-muted',\n },\n h('span', { className: 'font-medium' }, parent.author.name),\n h('span', { className: 'truncate' }, snippet),\n )\n}\n\nfunction HoverActions({\n message,\n conversation,\n isOwn,\n onEdit,\n onToggleEmojis,\n align,\n}: {\n message: ChatMessage\n conversation: UseConversationResult\n isOwn: boolean\n onEdit: () => void\n onToggleEmojis: () => void\n align: 'start' | 'end'\n}) {\n const { replyTo, deleteMessage } = conversation\n return h(\n 'div',\n {\n className: cn(\n 'mt-1 flex items-center gap-3 text-xs text-muted-foreground opacity-0 transition-opacity group-hover:opacity-100',\n align === 'end' && 'justify-end',\n ),\n },\n // Reply targets this specific message but groups under the originating root.\n h('button', { type: 'button', className: 'hover:text-foreground', onClick: () => replyTo(message.id) }, 'Reply'),\n h('button', { type: 'button', className: 'hover:text-foreground', onClick: onToggleEmojis }, 'React'),\n isOwn ? h('button', { type: 'button', className: 'hover:text-foreground', onClick: onEdit }, 'Edit') : null,\n isOwn ? h('button', { type: 'button', className: 'hover:text-destructive', onClick: () => deleteMessage(message.id) }, 'Delete') : null,\n )\n}\n\nfunction EmojiRow({ onPick, align }: { onPick: (e: string) => void; align: 'start' | 'end' }) {\n return h(\n 'div',\n { className: cn('mt-1 flex gap-1', align === 'end' && 'justify-end') },\n ...QUICK_EMOJIS.map((emoji) =>\n h('button', { key: emoji, type: 'button', className: 'rounded px-1 text-base hover:bg-accent', onClick: () => onPick(emoji) }, emoji),\n ),\n )\n}\n\nfunction EditField({ message, conversation, onDone }: { message: ChatMessage; conversation: UseConversationResult; onDone: () => void }) {\n const [draft, setDraft] = React.useState(message.content)\n function save() {\n const t = draft.trim()\n if (t && t !== message.content) conversation.editMessage(message.id, t)\n onDone()\n }\n return h(\n 'div',\n { className: 'mt-1' },\n h('textarea', {\n className: 'w-full resize-none rounded-md border border-border bg-background px-2 py-1 text-sm',\n value: draft,\n autoFocus: true,\n onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => setDraft(e.target.value),\n onKeyDown: (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault()\n save()\n }\n if (e.key === 'Escape') onDone()\n },\n }),\n h(\n 'div',\n { className: 'mt-1 flex gap-2 text-xs' },\n h('button', { type: 'button', className: 'text-primary', onClick: save }, 'Save'),\n h('button', { type: 'button', className: 'text-muted-foreground', onClick: onDone }, 'Cancel'),\n ),\n )\n}\n\nfunction MessageRow({\n message,\n conversation,\n currentUserId,\n showThreadAffordance,\n quotedParent,\n}: {\n message: ChatMessage\n conversation: UseConversationResult\n currentUserId?: string\n showThreadAffordance: boolean\n quotedParent?: ChatMessage\n}) {\n const { state, react, openThread } = conversation\n const [showEmojis, setShowEmojis] = React.useState(false)\n const [editing, setEditing] = React.useState(false)\n\n const isUser = currentUserId ? message.author.id === currentUserId : message.role === 'user'\n const replyCount = getReplyCount(state.messages, message.id)\n const align = isUser ? 'end' : 'start'\n\n const inner = h(\n React.Fragment,\n null,\n quotedParent ? h(QuotedParent, { parent: quotedParent, onClick: () => openThread(rootIdOf(state.messages, quotedParent.id)) }) : null,\n editing\n ? h(EditField, { message, conversation, onDone: () => setEditing(false) })\n : isUser\n ? h('div', { className: 'inline-block rounded-2xl rounded-br-sm bg-primary/10 px-3 py-2 text-left' }, h(MessageBody, { message }))\n : h(MessageBody, { message }),\n h(Reactions, { message, onReact: (e: string) => react(message.id, e), align }),\n showThreadAffordance && replyCount > 0\n ? h(\n 'button',\n { type: 'button', className: cn('mt-1 text-xs font-medium text-primary hover:underline', align === 'end' && 'self-end'), onClick: () => openThread(message.id) },\n `💬 ${replyCount} ${replyCount === 1 ? 'reply' : 'replies'}`,\n )\n : null,\n h(HoverActions, { message, conversation, isOwn: isUser, onEdit: () => setEditing(true), onToggleEmojis: () => setShowEmojis((v) => !v), align }),\n showEmojis\n ? h(EmojiRow, {\n onPick: (e: string) => {\n react(message.id, e)\n setShowEmojis(false)\n },\n align,\n })\n : null,\n )\n\n // Assistant / system: full-width flat row with avatar + name.\n if (!isUser) {\n return h(\n 'div',\n { className: 'group flex gap-3 rounded-md px-3 py-2 hover:bg-accent/30', role: 'article', 'aria-label': `Message from ${message.author.name}`, 'data-message-id': message.id },\n h(Avatar, { name: message.author.name, avatarUrl: message.author.avatarUrl }),\n h(\n 'div',\n { className: 'min-w-0 flex-1' },\n h(\n 'div',\n { className: 'flex items-baseline gap-2' },\n h('span', { className: 'text-sm font-semibold' }, message.author.name),\n h('span', { className: 'text-xs text-muted-foreground', title: message.timestamp.toISOString() }, formatTimestamp(message.timestamp)),\n message.edited ? h('span', { className: 'text-xs text-muted-foreground' }, '(edited)') : null,\n ),\n inner,\n ),\n )\n }\n\n // User: right-aligned bubble column.\n return h(\n 'div',\n { className: 'group flex flex-col items-end px-3 py-1.5', role: 'article', 'aria-label': `Message from ${message.author.name}`, 'data-message-id': message.id },\n h(\n 'div',\n { className: 'flex items-baseline gap-2' },\n message.edited ? h('span', { className: 'text-xs text-muted-foreground' }, '(edited)') : null,\n h('span', { className: 'text-xs text-muted-foreground', title: message.timestamp.toISOString() }, formatTimestamp(message.timestamp)),\n h('span', { className: 'text-sm font-semibold' }, message.author.name),\n ),\n h('div', { className: 'mt-0.5 flex max-w-[80%] flex-col items-end' }, inner),\n )\n}\n\nfunction ConversationSidebar({ conversation }: { conversation: UseConversationResult }) {\n const { state, newConversation, selectConversation, deleteConversation } = conversation\n return h(\n 'aside',\n { className: 'flex w-56 flex-col gap-1 overflow-y-auto border-r border-border bg-muted/20 p-2', 'aria-label': 'Conversations' },\n h(\n 'button',\n { type: 'button', className: 'mb-1 w-full rounded-md bg-primary px-3 py-2 text-sm font-medium text-primary-foreground hover:opacity-90', onClick: () => newConversation() },\n '+ New chat',\n ),\n ...state.conversations.map((conv) =>\n h(\n 'div',\n {\n key: conv.id,\n role: 'button',\n 'aria-current': conv.id === state.activeConversationId,\n onClick: () => selectConversation(conv.id),\n className: cn(\n 'group flex items-center justify-between gap-2 rounded-md px-2 py-1.5 text-sm hover:bg-accent/60',\n conv.id === state.activeConversationId && 'bg-accent font-medium',\n ),\n },\n h(\n 'div',\n { className: 'min-w-0' },\n h('div', { className: 'truncate' }, conv.title),\n h('div', { className: 'truncate text-xs text-muted-foreground' }, formatRelativeTime(conv.updatedAt)),\n ),\n h(\n 'button',\n {\n type: 'button',\n className: 'text-xs text-muted-foreground opacity-0 hover:text-destructive group-hover:opacity-100',\n 'aria-label': `Delete ${conv.title}`,\n onClick: (e: React.MouseEvent) => {\n e.stopPropagation()\n deleteConversation(conv.id)\n },\n },\n '✕',\n ),\n ),\n ),\n )\n}\n\nfunction ThreadPanel({ conversation, currentUserId, composer }: { conversation: UseConversationResult; currentUserId?: string; composer: React.ReactNode }) {\n const { state } = conversation\n const rootId = state.openThreadRootId\n if (!rootId) return null\n const messages = selectThreadMessages(state.messages, rootId)\n // Hint when the next reply targets a specific mid-thread message rather than the root.\n const target = state.replyTarget && state.replyTarget !== rootId ? findMessage(state.messages, state.replyTarget) : undefined\n return h(\n 'aside',\n { className: 'flex w-80 flex-col border-l border-border', 'aria-label': 'Thread' },\n h(\n 'div',\n { className: 'flex items-center justify-between border-b border-border px-3 py-2' },\n h('span', { className: 'text-sm font-semibold' }, `Thread · ${messages.length - 1} ${messages.length - 1 === 1 ? 'reply' : 'replies'}`),\n h('button', { type: 'button', className: 'text-muted-foreground hover:text-foreground', 'aria-label': 'Close thread', onClick: () => conversation.closeThread() }, '✕'),\n ),\n h(\n 'div',\n { className: 'flex-1 overflow-y-auto p-1' },\n ...messages.map((m) => h(MessageRow, { key: m.id, message: m, conversation, currentUserId, showThreadAffordance: false })),\n ),\n target\n ? h(\n 'div',\n { className: 'flex items-center justify-between gap-2 border-t border-border bg-muted/40 px-3 py-1 text-xs text-muted-foreground' },\n h('span', { className: 'truncate' }, `↳ Replying to ${target.author.name}`),\n h('button', { type: 'button', className: 'hover:text-foreground', onClick: () => conversation.openThread(rootId) }, 'Reply to thread instead'),\n )\n : null,\n composer,\n )\n}\n\nfunction ModeToggle({ conversation }: { conversation: UseConversationResult }) {\n const { state, setThreadingMode } = conversation\n const opt = (mode: ThreadingMode, label: string) =>\n h(\n 'button',\n {\n type: 'button',\n onClick: () => setThreadingMode(mode),\n className: cn('rounded px-2 py-0.5 text-xs', state.threadingMode === mode ? 'bg-background shadow-sm' : 'text-muted-foreground'),\n },\n label,\n )\n return h(\n 'div',\n { className: 'inline-flex rounded-md bg-muted p-0.5', role: 'group', 'aria-label': 'Threading mode' },\n opt('inline', 'Inline'),\n opt('panel', 'Threads'),\n )\n}\n\n/**\n * Chat — batteries-included composite over `useConversation()`:\n * conversation sidebar + main timeline + rich composer + thread side panel.\n * Hybrid layout: assistant replies full-width, user messages in a right-aligned\n * bubble. Markdown/code/gifs, reactions, edit/delete, streaming, and a composer\n * with `/` commands, `@` mentions, `:` emoji, and a formatting toolbar.\n */\nexport const Chat = React.forwardRef<HTMLDivElement, ChatProps>(\n function Chat({ conversation, showConversationList = true, showModeToggle = true, placeholder, currentUserId, emptyState, className, slashCommands, mentions, onSlashCommand, composerToolbar = true }: ChatProps, ref) {\n const { state, sendMessage } = conversation\n const timeline = selectMainTimeline(state.messages, state.threadingMode)\n const activeConv = state.conversations.find((c) => c.id === state.activeConversationId)\n const busy = state.status === 'sending' || state.status === 'streaming'\n const error = state.status === 'error' ? state.error : null\n const onRetry = () => void conversation.retryLast()\n\n const mainComposer = h(Composer, {\n placeholder,\n busy,\n error,\n onRetry,\n slashCommands,\n mentions,\n onSlashCommand,\n toolbar: composerToolbar,\n onSubmit: (content: string, atts?: MessageAttachment[]) => void sendMessage(content, { attachments: atts }),\n onStop: () => conversation.stop(),\n })\n\n const threadComposer = state.openThreadRootId\n ? h(Composer, {\n placeholder: 'Reply…',\n busy,\n error,\n onRetry,\n slashCommands,\n mentions,\n onSlashCommand,\n toolbar: composerToolbar,\n onSubmit: (content: string, atts?: MessageAttachment[]) =>\n void sendMessage(content, { replyTo: state.replyTarget ?? state.openThreadRootId!, attachments: atts }),\n onStop: () => conversation.stop(),\n })\n : null\n\n const body =\n timeline.length === 0\n ? h('div', { className: 'flex flex-1 items-center justify-center p-6 text-sm text-muted-foreground' }, emptyState ?? 'No messages yet. Say hello 👋')\n : h(\n 'div',\n { className: 'flex-1 space-y-0.5 overflow-y-auto p-2' },\n ...timeline.map((m) =>\n h(MessageRow, {\n key: m.id,\n message: m,\n conversation,\n currentUserId,\n // Show the \"N replies\" count on originating messages in BOTH modes.\n showThreadAffordance: true,\n // Inline: quote the specific message replied to (falls back to the root).\n quotedParent: state.threadingMode === 'inline' && m.parentId ? findMessage(state.messages, m.replyToId ?? m.parentId) : undefined,\n }),\n ),\n )\n\n return h(\n 'div',\n { ref, className: cn('flex h-full min-h-0 overflow-hidden rounded-xl border border-border bg-background', className) },\n showConversationList ? h(ConversationSidebar, { conversation }) : null,\n h(\n 'div',\n { className: 'flex min-w-0 flex-1 flex-col' },\n h(\n 'div',\n { className: 'flex items-center justify-between border-b border-border px-3 py-2' },\n h('span', { className: 'truncate text-sm font-semibold' }, activeConv?.title ?? 'Chat'),\n showModeToggle ? h(ModeToggle, { conversation }) : null,\n ),\n body,\n mainComposer,\n ),\n h(ThreadPanel, { conversation, currentUserId, composer: threadComposer }),\n )\n },\n)\n"],
5
+ "mappings": "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",
6
+ "names": ["React", "Composer", "next", "h", "cn", "React3", "Chat"]
7
+ }
@@ -0,0 +1,291 @@
1
+ import {
2
+ cn
3
+ } from "./chunk-ZF3OHCGV.js";
4
+
5
+ // ../react-cookie-consent/dist/index.js
6
+ import * as React2 from "react";
7
+
8
+ // ../cookie-consent/dist/index.js
9
+ var DEFAULT_KEY = "rfr-cookie-consent";
10
+ var DEFAULT_CATEGORIES = [
11
+ { id: "necessary", label: "Strictly necessary", description: "Required for the site to function. Always on.", required: true },
12
+ { id: "preferences", label: "Preferences", description: "Remembers your settings and choices." },
13
+ { id: "analytics", label: "Analytics", description: "Helps us understand how the site is used." },
14
+ { id: "marketing", label: "Marketing", description: "Used to personalize ads and measure campaigns." }
15
+ ];
16
+ function baseline(categories) {
17
+ const p = {};
18
+ for (const c of categories) p[c.id] = !!c.required;
19
+ return p;
20
+ }
21
+ function createCookieConsent(config = {}) {
22
+ const categories = config.categories ?? DEFAULT_CATEGORIES;
23
+ const storage = config.storage;
24
+ const key = config.storageKey ?? DEFAULT_KEY;
25
+ const version = config.version;
26
+ let preferences = baseline(categories);
27
+ let consented = false;
28
+ const raw = storage?.get(key) ?? null;
29
+ if (raw) {
30
+ try {
31
+ const parsed = JSON.parse(raw);
32
+ if ((parsed.version ?? void 0) === version) {
33
+ preferences = { ...baseline(categories), ...parsed.preferences };
34
+ for (const c of categories) if (c.required) preferences[c.id] = true;
35
+ consented = true;
36
+ }
37
+ } catch {
38
+ }
39
+ }
40
+ let open = !consented;
41
+ const listeners = /* @__PURE__ */ new Set();
42
+ let snapshot = build();
43
+ function build() {
44
+ return { consented, preferences: { ...preferences }, open, categories };
45
+ }
46
+ function emit() {
47
+ snapshot = build();
48
+ for (const l of listeners) l();
49
+ }
50
+ function persist() {
51
+ storage?.set(key, JSON.stringify({ version, preferences }));
52
+ config.onChange?.({ ...preferences });
53
+ }
54
+ function save(next) {
55
+ const merged = { ...baseline(categories), ...next };
56
+ for (const c of categories) if (c.required) merged[c.id] = true;
57
+ preferences = merged;
58
+ consented = true;
59
+ open = false;
60
+ persist();
61
+ emit();
62
+ }
63
+ return {
64
+ getState() {
65
+ return snapshot;
66
+ },
67
+ subscribe(listener) {
68
+ listeners.add(listener);
69
+ return () => listeners.delete(listener);
70
+ },
71
+ acceptAll() {
72
+ const all = {};
73
+ for (const c of categories) all[c.id] = true;
74
+ save(all);
75
+ },
76
+ rejectAll() {
77
+ save(baseline(categories));
78
+ },
79
+ savePreferences(prefs) {
80
+ save(prefs);
81
+ },
82
+ setPreference(id, value) {
83
+ const cat = categories.find((c) => c.id === id);
84
+ if (!cat || cat.required) return;
85
+ preferences = { ...preferences, [id]: value };
86
+ emit();
87
+ },
88
+ reset() {
89
+ storage?.remove(key);
90
+ preferences = baseline(categories);
91
+ consented = false;
92
+ open = true;
93
+ emit();
94
+ },
95
+ openSettings() {
96
+ if (open) return;
97
+ open = true;
98
+ emit();
99
+ },
100
+ close() {
101
+ if (!open) return;
102
+ open = false;
103
+ emit();
104
+ }
105
+ };
106
+ }
107
+
108
+ // ../react-cookie-consent/dist/index.js
109
+ var localStorageAdapter = {
110
+ get(k) {
111
+ try {
112
+ return typeof localStorage !== "undefined" ? localStorage.getItem(k) : null;
113
+ } catch {
114
+ return null;
115
+ }
116
+ },
117
+ set(k, v) {
118
+ try {
119
+ localStorage?.setItem(k, v);
120
+ } catch {
121
+ }
122
+ },
123
+ remove(k) {
124
+ try {
125
+ localStorage?.removeItem(k);
126
+ } catch {
127
+ }
128
+ }
129
+ };
130
+ function useCookieConsent(config) {
131
+ const apiRef = React2.useRef(null);
132
+ if (apiRef.current === null) {
133
+ apiRef.current = createCookieConsent({ storage: localStorageAdapter, ...config });
134
+ }
135
+ const api = apiRef.current;
136
+ const state = React2.useSyncExternalStore(api.subscribe, api.getState, api.getState);
137
+ return {
138
+ state,
139
+ api,
140
+ acceptAll: api.acceptAll,
141
+ rejectAll: api.rejectAll,
142
+ savePreferences: api.savePreferences,
143
+ setPreference: api.setPreference,
144
+ reset: api.reset,
145
+ openSettings: api.openSettings,
146
+ close: api.close
147
+ };
148
+ }
149
+ var h = React2.createElement;
150
+ var btnBase = "inline-flex items-center justify-center rounded-lg px-3.5 py-2 text-sm font-medium transition-colors";
151
+ var btnPrimary = cn(btnBase, "bg-primary text-primary-foreground hover:opacity-90");
152
+ var btnGhost = cn(btnBase, "border border-border hover:bg-accent");
153
+ var btnLink = "text-sm font-medium text-muted-foreground underline-offset-4 hover:text-foreground hover:underline";
154
+ function Toggle({
155
+ checked,
156
+ disabled,
157
+ onChange,
158
+ label
159
+ }) {
160
+ if (disabled) {
161
+ return h(
162
+ "span",
163
+ { className: "rounded-full bg-muted px-2 py-0.5 text-xs font-medium text-muted-foreground" },
164
+ "Always on"
165
+ );
166
+ }
167
+ return h(
168
+ "button",
169
+ {
170
+ type: "button",
171
+ role: "switch",
172
+ "aria-checked": checked,
173
+ "aria-label": label,
174
+ onClick: () => onChange(!checked),
175
+ className: cn(
176
+ "relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-colors",
177
+ checked ? "bg-primary" : "bg-muted"
178
+ )
179
+ },
180
+ h("span", {
181
+ className: cn(
182
+ "inline-block h-4 w-4 transform rounded-full bg-background shadow transition-transform",
183
+ checked ? "translate-x-[1.125rem]" : "translate-x-0.5"
184
+ )
185
+ })
186
+ );
187
+ }
188
+ function CookieIcon() {
189
+ return h(
190
+ "div",
191
+ { className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-accent text-xl", "aria-hidden": true },
192
+ "\u{1F36A}"
193
+ );
194
+ }
195
+ var CookieConsent = React2.forwardRef(
196
+ function CookieConsent2({
197
+ consent,
198
+ position = "bottom",
199
+ title = "We use cookies",
200
+ description = "We use cookies to run the site, remember your preferences, and measure traffic. Choose which to allow.",
201
+ policyUrl,
202
+ policyLabel = "Cookie policy",
203
+ className
204
+ }, ref) {
205
+ const { state, acceptAll, rejectAll, savePreferences, setPreference } = consent;
206
+ const [settings, setSettings] = React2.useState(false);
207
+ if (!state.open) return null;
208
+ const wrapper = cn("fixed inset-x-0 z-50 p-4", position === "bottom" ? "bottom-0" : "top-0", className);
209
+ const panel = "mx-auto max-w-2xl overflow-hidden rounded-2xl border border-border bg-background shadow-lg";
210
+ const policy = policyUrl ? h("a", { href: policyUrl, target: "_blank", rel: "noreferrer", className: cn(btnLink, "whitespace-nowrap") }, policyLabel) : null;
211
+ const promptView = h(
212
+ "div",
213
+ { className: "flex flex-col gap-4 p-5 sm:flex-row sm:items-center" },
214
+ h(CookieIcon),
215
+ h(
216
+ "div",
217
+ { className: "min-w-0 flex-1" },
218
+ h("p", { className: "text-sm font-semibold" }, title),
219
+ h(
220
+ "p",
221
+ { className: "mt-0.5 text-sm leading-relaxed text-muted-foreground" },
222
+ description,
223
+ policy ? h(React2.Fragment, null, " ", policy) : null
224
+ )
225
+ ),
226
+ h(
227
+ "div",
228
+ { className: "flex flex-wrap items-center gap-2 sm:shrink-0" },
229
+ h("button", { type: "button", className: btnLink, onClick: () => setSettings(true) }, "Customize"),
230
+ h("button", { type: "button", className: btnGhost, onClick: () => rejectAll() }, "Reject all"),
231
+ h("button", { type: "button", className: btnPrimary, onClick: () => acceptAll() }, "Accept all")
232
+ )
233
+ );
234
+ const settingsView = h(
235
+ "div",
236
+ { className: "p-5" },
237
+ h(
238
+ "div",
239
+ { className: "flex items-center gap-3" },
240
+ h(CookieIcon),
241
+ h(
242
+ "div",
243
+ null,
244
+ h("p", { className: "text-sm font-semibold" }, "Cookie preferences"),
245
+ h("p", { className: "text-xs text-muted-foreground" }, "Toggle the categories you want to allow.")
246
+ )
247
+ ),
248
+ h(
249
+ "div",
250
+ { className: "mt-4 space-y-2" },
251
+ ...state.categories.map(
252
+ (cat) => h(
253
+ "div",
254
+ { key: cat.id, className: "flex items-center justify-between gap-4 rounded-xl border border-border p-3" },
255
+ h(
256
+ "div",
257
+ { className: "min-w-0" },
258
+ h("p", { className: "text-sm font-medium" }, cat.label),
259
+ cat.description ? h("p", { className: "mt-0.5 text-xs text-muted-foreground" }, cat.description) : null
260
+ ),
261
+ h(Toggle, {
262
+ checked: !!state.preferences[cat.id],
263
+ disabled: cat.required,
264
+ label: cat.label,
265
+ onChange: (v) => setPreference(cat.id, v)
266
+ })
267
+ )
268
+ )
269
+ ),
270
+ h(
271
+ "div",
272
+ { className: "mt-4 flex flex-wrap items-center gap-2" },
273
+ h("button", { type: "button", className: btnLink, onClick: () => setSettings(false) }, "\u2190 Back"),
274
+ h("button", { type: "button", className: cn(btnGhost, "sm:ml-auto"), onClick: () => acceptAll() }, "Accept all"),
275
+ h("button", { type: "button", className: btnPrimary, onClick: () => savePreferences(state.preferences) }, "Save preferences")
276
+ )
277
+ );
278
+ return h(
279
+ "div",
280
+ { ref, className: wrapper, role: "dialog", "aria-label": "Cookie consent", "aria-modal": false },
281
+ h("div", { className: panel }, settings ? settingsView : promptView)
282
+ );
283
+ }
284
+ );
285
+ export {
286
+ CookieConsent,
287
+ DEFAULT_CATEGORIES,
288
+ createCookieConsent,
289
+ useCookieConsent
290
+ };
291
+ //# sourceMappingURL=react-cookie-consent.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../cookie-consent/src/cookie-consent.ts", "../../react-cookie-consent/src/use-cookie-consent.ts", "../../react-cookie-consent/src/cookie-consent.tsx"],
4
+ "sourcesContent": ["import type {\n CookieCategory,\n CookieConsentAPI,\n CookieConsentConfig,\n CookieConsentState,\n ConsentPreferences,\n} from './types.js'\n\nconst DEFAULT_KEY = 'rfr-cookie-consent'\n\n/** Popular default GDPR-style categories. */\nexport const DEFAULT_CATEGORIES: CookieCategory[] = [\n { id: 'necessary', label: 'Strictly necessary', description: 'Required for the site to function. Always on.', required: true },\n { id: 'preferences', label: 'Preferences', description: 'Remembers your settings and choices.' },\n { id: 'analytics', label: 'Analytics', description: 'Helps us understand how the site is used.' },\n { id: 'marketing', label: 'Marketing', description: 'Used to personalize ads and measure campaigns.' },\n]\n\ninterface Persisted {\n version?: string\n preferences: ConsentPreferences\n}\n\n/** Preferences with only required categories granted. */\nfunction baseline(categories: CookieCategory[]): ConsentPreferences {\n const p: ConsentPreferences = {}\n for (const c of categories) p[c.id] = !!c.required\n return p\n}\n\n/**\n * createCookieConsent — headless consent store. Reads any persisted choice on\n * init (re-prompting if the `version` changed), and exposes accept/reject/save\n * plus banner visibility. Persistence is via the optional storage adapter.\n */\nexport function createCookieConsent(config: CookieConsentConfig = {}): CookieConsentAPI {\n const categories = config.categories ?? DEFAULT_CATEGORIES\n const storage = config.storage\n const key = config.storageKey ?? DEFAULT_KEY\n const version = config.version\n\n let preferences = baseline(categories)\n let consented = false\n\n // Hydrate from storage.\n const raw = storage?.get(key) ?? null\n if (raw) {\n try {\n const parsed = JSON.parse(raw) as Persisted\n if ((parsed.version ?? undefined) === version) {\n preferences = { ...baseline(categories), ...parsed.preferences }\n // required stay on regardless of stored value\n for (const c of categories) if (c.required) preferences[c.id] = true\n consented = true\n }\n } catch {\n // ignore corrupt storage\n }\n }\n\n let open = !consented\n\n const listeners = new Set<() => void>()\n let snapshot = build()\n\n function build(): CookieConsentState {\n return { consented, preferences: { ...preferences }, open, categories }\n }\n function emit(): void {\n snapshot = build()\n for (const l of listeners) l()\n }\n\n function persist(): void {\n storage?.set(key, JSON.stringify({ version, preferences } satisfies Persisted))\n config.onChange?.({ ...preferences })\n }\n\n function save(next: ConsentPreferences): void {\n const merged = { ...baseline(categories), ...next }\n for (const c of categories) if (c.required) merged[c.id] = true\n preferences = merged\n consented = true\n open = false\n persist()\n emit()\n }\n\n return {\n getState() {\n return snapshot\n },\n subscribe(listener) {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n acceptAll() {\n const all: ConsentPreferences = {}\n for (const c of categories) all[c.id] = true\n save(all)\n },\n rejectAll() {\n save(baseline(categories))\n },\n savePreferences(prefs) {\n save(prefs)\n },\n setPreference(id, value) {\n const cat = categories.find((c) => c.id === id)\n if (!cat || cat.required) return\n preferences = { ...preferences, [id]: value }\n emit()\n },\n reset() {\n storage?.remove(key)\n preferences = baseline(categories)\n consented = false\n open = true\n emit()\n },\n openSettings() {\n if (open) return\n open = true\n emit()\n },\n close() {\n if (!open) return\n open = false\n emit()\n },\n }\n}\n", "import * as React from 'react'\nimport {\n createCookieConsent,\n type CookieConsentAPI,\n type CookieConsentConfig,\n type CookieConsentState,\n type CookieStorage,\n} from '@refraction-ui/cookie-consent'\n\n/** Default browser persistence (SSR-safe — guards localStorage access). */\nconst localStorageAdapter: CookieStorage = {\n get(k) {\n try {\n return typeof localStorage !== 'undefined' ? localStorage.getItem(k) : null\n } catch {\n return null\n }\n },\n set(k, v) {\n try {\n localStorage?.setItem(k, v)\n } catch {\n /* ignore */\n }\n },\n remove(k) {\n try {\n localStorage?.removeItem(k)\n } catch {\n /* ignore */\n }\n },\n}\n\nexport interface UseCookieConsentResult {\n state: CookieConsentState\n api: CookieConsentAPI\n acceptAll: CookieConsentAPI['acceptAll']\n rejectAll: CookieConsentAPI['rejectAll']\n savePreferences: CookieConsentAPI['savePreferences']\n setPreference: CookieConsentAPI['setPreference']\n reset: CookieConsentAPI['reset']\n openSettings: CookieConsentAPI['openSettings']\n close: CookieConsentAPI['close']\n}\n\n/**\n * useCookieConsent — binds the headless cookie-consent store to React via\n * `useSyncExternalStore`, defaulting persistence to localStorage.\n */\nexport function useCookieConsent(config?: CookieConsentConfig): UseCookieConsentResult {\n const apiRef = React.useRef<CookieConsentAPI | null>(null)\n if (apiRef.current === null) {\n apiRef.current = createCookieConsent({ storage: localStorageAdapter, ...config })\n }\n const api = apiRef.current\n const state = React.useSyncExternalStore(api.subscribe, api.getState, api.getState)\n return {\n state,\n api,\n acceptAll: api.acceptAll,\n rejectAll: api.rejectAll,\n savePreferences: api.savePreferences,\n setPreference: api.setPreference,\n reset: api.reset,\n openSettings: api.openSettings,\n close: api.close,\n }\n}\n", "import * as React from 'react'\nimport { cn } from '@refraction-ui/shared'\nimport type { UseCookieConsentResult } from './use-cookie-consent.js'\n\nconst h = React.createElement\n\nexport interface CookieConsentProps {\n /** Result of `useCookieConsent()` */\n consent: UseCookieConsentResult\n /** Banner position (default 'bottom') */\n position?: 'bottom' | 'top'\n title?: string\n description?: React.ReactNode\n /** Link to the full cookie/privacy policy */\n policyUrl?: string\n policyLabel?: string\n className?: string\n}\n\nconst btnBase = 'inline-flex items-center justify-center rounded-lg px-3.5 py-2 text-sm font-medium transition-colors'\nconst btnPrimary = cn(btnBase, 'bg-primary text-primary-foreground hover:opacity-90')\nconst btnGhost = cn(btnBase, 'border border-border hover:bg-accent')\nconst btnLink = 'text-sm font-medium text-muted-foreground underline-offset-4 hover:text-foreground hover:underline'\n\n/** A compact switch toggle. Required categories render a static \"Always on\". */\nfunction Toggle({\n checked,\n disabled,\n onChange,\n label,\n}: {\n checked: boolean\n disabled?: boolean\n onChange: (v: boolean) => void\n label: string\n}) {\n if (disabled) {\n return h(\n 'span',\n { className: 'rounded-full bg-muted px-2 py-0.5 text-xs font-medium text-muted-foreground' },\n 'Always on',\n )\n }\n return h(\n 'button',\n {\n type: 'button',\n role: 'switch',\n 'aria-checked': checked,\n 'aria-label': label,\n onClick: () => onChange(!checked),\n className: cn(\n 'relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-colors',\n checked ? 'bg-primary' : 'bg-muted',\n ),\n },\n h('span', {\n className: cn(\n 'inline-block h-4 w-4 transform rounded-full bg-background shadow transition-transform',\n checked ? 'translate-x-[1.125rem]' : 'translate-x-0.5',\n ),\n }),\n )\n}\n\nfunction CookieIcon() {\n return h(\n 'div',\n { className: 'flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-accent text-xl', 'aria-hidden': true },\n '🍪',\n )\n}\n\n/**\n * CookieConsent — batteries-included consent banner over `useCookieConsent()`.\n * Renders nothing once the user has consented.\n */\nexport const CookieConsent = React.forwardRef<HTMLDivElement, CookieConsentProps>(\n function CookieConsent({\n consent,\n position = 'bottom',\n title = 'We use cookies',\n description = 'We use cookies to run the site, remember your preferences, and measure traffic. Choose which to allow.',\n policyUrl,\n policyLabel = 'Cookie policy',\n className,\n }: CookieConsentProps, ref) {\n const { state, acceptAll, rejectAll, savePreferences, setPreference } = consent\n const [settings, setSettings] = React.useState(false)\n\n if (!state.open) return null\n\n const wrapper = cn('fixed inset-x-0 z-50 p-4', position === 'bottom' ? 'bottom-0' : 'top-0', className)\n const panel = 'mx-auto max-w-2xl overflow-hidden rounded-2xl border border-border bg-background shadow-lg'\n\n const policy = policyUrl\n ? h('a', { href: policyUrl, target: '_blank', rel: 'noreferrer', className: cn(btnLink, 'whitespace-nowrap') }, policyLabel)\n : null\n\n // — compact prompt —\n const promptView = h(\n 'div',\n { className: 'flex flex-col gap-4 p-5 sm:flex-row sm:items-center' },\n h(CookieIcon),\n h(\n 'div',\n { className: 'min-w-0 flex-1' },\n h('p', { className: 'text-sm font-semibold' }, title),\n h(\n 'p',\n { className: 'mt-0.5 text-sm leading-relaxed text-muted-foreground' },\n description,\n policy ? h(React.Fragment, null, ' ', policy) : null,\n ),\n ),\n h(\n 'div',\n { className: 'flex flex-wrap items-center gap-2 sm:shrink-0' },\n h('button', { type: 'button', className: btnLink, onClick: () => setSettings(true) }, 'Customize'),\n h('button', { type: 'button', className: btnGhost, onClick: () => rejectAll() }, 'Reject all'),\n h('button', { type: 'button', className: btnPrimary, onClick: () => acceptAll() }, 'Accept all'),\n ),\n )\n\n // — settings —\n const settingsView = h(\n 'div',\n { className: 'p-5' },\n h(\n 'div',\n { className: 'flex items-center gap-3' },\n h(CookieIcon),\n h(\n 'div',\n null,\n h('p', { className: 'text-sm font-semibold' }, 'Cookie preferences'),\n h('p', { className: 'text-xs text-muted-foreground' }, 'Toggle the categories you want to allow.'),\n ),\n ),\n h(\n 'div',\n { className: 'mt-4 space-y-2' },\n ...state.categories.map((cat) =>\n h(\n 'div',\n { key: cat.id, className: 'flex items-center justify-between gap-4 rounded-xl border border-border p-3' },\n h(\n 'div',\n { className: 'min-w-0' },\n h('p', { className: 'text-sm font-medium' }, cat.label),\n cat.description ? h('p', { className: 'mt-0.5 text-xs text-muted-foreground' }, cat.description) : null,\n ),\n h(Toggle, {\n checked: !!state.preferences[cat.id],\n disabled: cat.required,\n label: cat.label,\n onChange: (v: boolean) => setPreference(cat.id, v),\n }),\n ),\n ),\n ),\n h(\n 'div',\n { className: 'mt-4 flex flex-wrap items-center gap-2' },\n h('button', { type: 'button', className: btnLink, onClick: () => setSettings(false) }, '← Back'),\n h('button', { type: 'button', className: cn(btnGhost, 'sm:ml-auto'), onClick: () => acceptAll() }, 'Accept all'),\n h('button', { type: 'button', className: btnPrimary, onClick: () => savePreferences(state.preferences) }, 'Save preferences'),\n ),\n )\n\n return h(\n 'div',\n { ref, className: wrapper, role: 'dialog', 'aria-label': 'Cookie consent', 'aria-modal': false },\n h('div', { className: panel }, settings ? settingsView : promptView),\n )\n },\n)\n"],
5
+ "mappings": "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",
6
+ "names": ["React", "CookieConsent"]
7
+ }