@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": ["../../video-grid/src/video-grid.ts", "../../video-grid/src/video-grid.styles.ts", "../../react-video-grid/src/video-grid.tsx"],
4
+ "sourcesContent": ["/**\n * Layout mode for a VideoGrid.\n *\n * - 'auto' — choose grid or speaker view based on participant count (≤1 forces speaker)\n * - 'grid' — always render an even CSS grid of tiles\n * - 'speaker' — render one large spotlight tile + a filmstrip row for the rest\n */\nexport type VideoGridLayout = 'auto' | 'grid' | 'speaker'\n\n/**\n * Bucket label that describes the rough meeting size.\n * Useful for analytics and adaptive UI decisions.\n */\nexport type VideoGridBucket =\n | 'solo'\n | 'pair'\n | 'small'\n | 'medium'\n | 'large'\n | 'townhall'\n\nexport interface VideoGridHeadlessProps {\n /** Desired layout mode. */\n layout?: VideoGridLayout\n}\n\nexport interface VideoGridAPI {\n /** ARIA attributes to spread on the grid container. */\n ariaProps: {\n role: 'group'\n }\n /** Data attributes for CSS styling hooks. */\n dataAttributes: {\n 'data-layout': VideoGridLayout\n 'data-count'?: string\n }\n}\n\n/**\n * Compute the number of CSS grid columns for N participants.\n *\n * The responsive rule mirrors easyloops meeting layouts:\n *\n * | count | columns |\n * |-------|---------|\n * | 1 | 1 |\n * | 2 | 2 |\n * | 3–4 | 2 |\n * | 5–9 | 3 |\n * | 10–16 | 4 |\n * | 17–25 | 5 |\n * | 26+ | 6 |\n */\nexport function computeGridColumns(count: number): number {\n if (count <= 1) return 1\n if (count <= 4) return 2\n if (count <= 9) return 3\n if (count <= 16) return 4\n if (count <= 25) return 5\n return 6\n}\n\n/**\n * Label the meeting size as a human-readable bucket.\n *\n * Useful for analytics events and adaptive UI decisions without\n * coupling to the exact column math.\n */\nexport function bucketByCount(count: number): VideoGridBucket {\n if (count <= 1) return 'solo'\n if (count <= 2) return 'pair'\n if (count <= 9) return 'small'\n if (count <= 16) return 'medium'\n if (count <= 25) return 'large'\n return 'townhall'\n}\n\n/**\n * Build the framework-agnostic ARIA and data attributes for a VideoGrid\n * container. Adapters spread these onto their host element.\n */\nexport function createVideoGrid(props: VideoGridHeadlessProps = {}): VideoGridAPI {\n const { layout = 'auto' } = props\n\n return {\n ariaProps: {\n role: 'group',\n },\n dataAttributes: {\n 'data-layout': layout,\n },\n }\n}\n", "import { cva } from '@refraction-ui/shared'\n\n/**\n * Grid container variants.\n *\n * - `layout: 'grid'` — uniform CSS grid; column count is set inline by the\n * adapter using `computeGridColumns` (gridTemplateColumns).\n * - `layout: 'speaker'` — two-row layout: large spotlight on top, filmstrip row\n * below. The adapter renders the spotlight as the first child and a horizontal\n * overflow row for remaining tiles.\n */\nexport const videoGridVariants = cva({\n base: 'w-full h-full gap-2',\n variants: {\n layout: {\n grid: 'grid',\n speaker: 'flex flex-col',\n auto: 'grid',\n },\n },\n defaultVariants: {\n layout: 'auto',\n },\n})\n\n/** Full-bleed spotlight area in speaker view (takes up remaining vertical space). */\nexport const videoGridSpotlightClass = 'relative flex-1 min-h-0 rounded-xl overflow-hidden bg-muted'\n\n/**\n * Horizontal filmstrip row used in speaker view.\n * Each tile in this row is constrained to a fixed width so the row scrolls\n * rather than wraps on large calls.\n */\nexport const videoGridFilmstripClass =\n 'flex flex-row gap-2 overflow-x-auto py-1 shrink-0'\n\n/** Individual filmstrip tile wrapper — fixed width so they don't collapse. */\nexport const videoGridFilmstripTileClass = 'w-36 shrink-0'\n", "import * as React from 'react'\nimport {\n createVideoGrid,\n computeGridColumns,\n videoGridVariants,\n videoGridSpotlightClass,\n videoGridFilmstripClass,\n videoGridFilmstripTileClass,\n type VideoGridLayout,\n} from '@refraction-ui/video-grid'\nimport { cn } from '@refraction-ui/shared'\nimport { VideoTile, type VideoTileData } from '@refraction-ui/react-video-tile'\n\nexport type { VideoGridLayout, VideoTileData }\n\nexport interface VideoGridProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color' | 'content'> {\n /** List of participant data to render as tiles. */\n participants: VideoTileData[]\n /**\n * Grid layout mode.\n * - 'auto' — grid unless ≤1 participant (falls back to speaker)\n * - 'grid' — always uniform CSS grid\n * - 'speaker' — spotlight for `spotlightId` (or first participant) + filmstrip\n */\n layout?: VideoGridLayout\n /**\n * Participant `id` to spotlight in speaker view.\n * Falls back to the first participant when omitted.\n */\n spotlightId?: string\n}\n\n/**\n * VideoGrid — adaptive participant grid for easyloops meetings.\n *\n * Composes `<VideoTile>` tiles in a responsive CSS grid (1→6 columns based on\n * participant count) or a speaker-view layout (spotlight + filmstrip). The\n * column math lives in the headless `@refraction-ui/video-grid` core so it is\n * shared with the Astro adapter.\n */\nexport const VideoGrid = React.forwardRef<HTMLDivElement, VideoGridProps>(\n function VideoGrid(\n {\n participants,\n layout = 'auto',\n spotlightId,\n className,\n style,\n ...props\n },\n ref,\n ) {\n const count = participants.length\n\n // Resolve effective layout: 'auto' with ≤1 participant shows speaker view.\n const effectiveLayout: VideoGridLayout =\n layout === 'auto' ? (count <= 1 ? 'speaker' : 'grid') : layout\n\n const api = createVideoGrid({ layout: effectiveLayout })\n const columns = computeGridColumns(count)\n\n const gridStyle: React.CSSProperties =\n effectiveLayout !== 'speaker'\n ? { gridTemplateColumns: `repeat(${columns}, 1fr)`, ...style }\n : { ...style }\n\n if (effectiveLayout === 'speaker') {\n const spotlightParticipant =\n participants.find((p) => p.id === spotlightId) ?? participants[0]\n const filmstrip = participants.filter(\n (p) => p.id !== spotlightParticipant?.id,\n )\n\n return (\n <div\n ref={ref}\n className={cn(videoGridVariants({ layout: 'speaker' }), className)}\n style={style}\n {...api.ariaProps}\n {...api.dataAttributes}\n {...props}\n >\n <div className={videoGridSpotlightClass}>\n {spotlightParticipant && (\n <VideoTile\n key={spotlightParticipant.id}\n name={spotlightParticipant.name}\n micState={spotlightParticipant.micState ?? 'on'}\n speaking={spotlightParticipant.speaking}\n pinned={spotlightParticipant.pinned}\n />\n )}\n </div>\n {filmstrip.length > 0 && (\n <div className={videoGridFilmstripClass}>\n {filmstrip.map((p) => (\n <div key={p.id} className={videoGridFilmstripTileClass}>\n <VideoTile\n name={p.name}\n micState={p.micState ?? 'on'}\n speaking={p.speaking}\n pinned={p.pinned}\n />\n </div>\n ))}\n </div>\n )}\n </div>\n )\n }\n\n return (\n <div\n ref={ref}\n className={cn(videoGridVariants({ layout: effectiveLayout }), className)}\n style={gridStyle}\n {...api.ariaProps}\n {...api.dataAttributes}\n {...props}\n >\n {participants.map((p) => (\n <VideoTile\n key={p.id}\n name={p.name}\n micState={p.micState ?? 'on'}\n speaking={p.speaking}\n pinned={p.pinned}\n />\n ))}\n </div>\n )\n },\n)\n"],
5
+ "mappings": ";;;;;;;;;;;;AAqDO,SAAS,mBAAmB,OAAuB;AACxD,MAAI,SAAS,EAAG,QAAO;AACvB,MAAI,SAAS,EAAG,QAAO;AACvB,MAAI,SAAS,EAAG,QAAO;AACvB,MAAI,SAAS,GAAI,QAAO;AACxB,MAAI,SAAS,GAAI,QAAO;AACxB,SAAO;AACT;AAqBO,SAAS,gBAAgB,QAAgC,CAAA,GAAkB;AAChF,QAAM,EAAE,SAAS,OAAA,IAAW;AAE5B,SAAO;IACL,WAAW;MACT,MAAM;IAAA;IAER,gBAAgB;MACd,eAAe;IAAA;EACjB;AAEJ;ACjFO,IAAM,oBAAoB,IAAI;EACnC,MAAM;EACN,UAAU;IACR,QAAQ;MACN,MAAM;MACN,SAAS;MACT,MAAM;IAAA;EACR;EAEF,iBAAiB;IACf,QAAQ;EAAA;AAEZ,CAAC;AAGM,IAAM,0BAA0B;AAOhC,IAAM,0BACX;AAGK,IAAM,8BAA8B;;;;ACIpC,IAAM,YAAkB;EAC7B,SAASA,WACP;IACE;IACA,SAAS;IACT;IACA;IACA;IACA,GAAG;EAAA,GAEL,KACA;AACA,UAAM,QAAQ,aAAa;AAG3B,UAAM,kBACJ,WAAW,SAAU,SAAS,IAAI,YAAY,SAAU;AAE1D,UAAM,MAAM,gBAAgB,EAAE,QAAQ,gBAAA,CAAiB;AACvD,UAAM,UAAU,mBAAmB,KAAK;AAExC,UAAM,YACJ,oBAAoB,YAChB,EAAE,qBAAqB,UAAU,OAAO,UAAU,GAAG,MAAA,IACrD,EAAE,GAAG,MAAA;AAEX,QAAI,oBAAoB,WAAW;AACjC,YAAM,uBACJ,aAAa,KAAK,CAAC,MAAM,EAAE,OAAO,WAAW,KAAK,aAAa,CAAC;AAClE,YAAM,YAAY,aAAa;QAC7B,CAAC,MAAM,EAAE,OAAO,sBAAsB;MAAA;AAGxC,aACE;QAAC;QAAA;UACC;UACA,WAAW,GAAG,kBAAkB,EAAE,QAAQ,UAAA,CAAW,GAAG,SAAS;UACjE;UACC,GAAG,IAAI;UACP,GAAG,IAAI;UACP,GAAG;UAEJ,UAAA;YAAA,oBAAC,OAAA,EAAI,WAAW,yBACb,UAAA,wBACC;cAAC;cAAA;gBAEC,MAAM,qBAAqB;gBAC3B,UAAU,qBAAqB,YAAY;gBAC3C,UAAU,qBAAqB;gBAC/B,QAAQ,qBAAqB;cAAA;cAJxB,qBAAqB;YAAA,EAK5B,CAEJ;YACC,UAAU,SAAS,KAClB,oBAAC,OAAA,EAAI,WAAW,yBACb,UAAA,UAAU,IAAI,CAAC,MACd,oBAAC,OAAA,EAAe,WAAW,6BACzB,UAAA;cAAC;cAAA;gBACC,MAAM,EAAE;gBACR,UAAU,EAAE,YAAY;gBACxB,UAAU,EAAE;gBACZ,QAAQ,EAAE;cAAA;YAAA,EACZ,GANQ,EAAE,EAOZ,CACD,EAAA,CACH;UAAA;QAAA;MAAA;IAIR;AAEA,WACE;MAAC;MAAA;QACC;QACA,WAAW,GAAG,kBAAkB,EAAE,QAAQ,gBAAA,CAAiB,GAAG,SAAS;QACvE,OAAO;QACN,GAAG,IAAI;QACP,GAAG,IAAI;QACP,GAAG;QAEH,UAAA,aAAa,IAAI,CAAC,MACjB;UAAC;UAAA;YAEC,MAAM,EAAE;YACR,UAAU,EAAE,YAAY;YACxB,UAAU,EAAE;YACZ,QAAQ,EAAE;UAAA;UAJL,EAAE;QAAA,CAMV;MAAA;IAAA;EAGP;AACF;",
6
+ "names": ["VideoGrid"]
7
+ }
@@ -0,0 +1,206 @@
1
+ import {
2
+ cn,
3
+ cva
4
+ } from "./chunk-ZF3OHCGV.js";
5
+
6
+ // ../react-video-player/dist/index.js
7
+ import * as React from "react";
8
+
9
+ // ../video-player/dist/index.js
10
+ function createVideoPlayer(props = {}) {
11
+ const { muted: initialMuted = false } = props;
12
+ let state = "idle";
13
+ let isMuted = initialMuted;
14
+ function play() {
15
+ if (state === "ended") {
16
+ state = "playing";
17
+ } else if (state !== "playing") {
18
+ state = "playing";
19
+ }
20
+ }
21
+ function pause() {
22
+ if (state === "playing") {
23
+ state = "paused";
24
+ }
25
+ }
26
+ function togglePlay() {
27
+ if (state === "playing") {
28
+ pause();
29
+ } else {
30
+ play();
31
+ }
32
+ }
33
+ function toggleMute() {
34
+ isMuted = !isMuted;
35
+ return isMuted;
36
+ }
37
+ const ariaProps = {
38
+ role: "region",
39
+ "aria-label": "Video player"
40
+ };
41
+ const api = {
42
+ get state() {
43
+ return state;
44
+ },
45
+ play,
46
+ pause,
47
+ togglePlay,
48
+ toggleMute,
49
+ ariaProps,
50
+ get controlAriaProps() {
51
+ return {
52
+ playPause: {
53
+ "aria-label": state === "playing" ? "Pause" : "Play"
54
+ },
55
+ mute: {
56
+ "aria-label": isMuted ? "Unmute" : "Mute"
57
+ }
58
+ };
59
+ },
60
+ get dataAttributes() {
61
+ return {
62
+ "data-state": state
63
+ };
64
+ }
65
+ };
66
+ return api;
67
+ }
68
+ var playerVariants = cva({
69
+ base: "relative overflow-hidden rounded-lg bg-black",
70
+ variants: {
71
+ size: {
72
+ sm: "max-w-sm",
73
+ md: "max-w-2xl",
74
+ lg: "max-w-4xl",
75
+ full: "w-full"
76
+ }
77
+ },
78
+ defaultVariants: {
79
+ size: "full"
80
+ }
81
+ });
82
+ var controlsVariants = cva({
83
+ base: "absolute bottom-0 left-0 right-0 flex items-center gap-2 bg-gradient-to-t from-black/80 to-transparent p-4 transition-opacity",
84
+ variants: {
85
+ visibility: {
86
+ visible: "opacity-100",
87
+ hidden: "opacity-0 pointer-events-none"
88
+ }
89
+ },
90
+ defaultVariants: {
91
+ visibility: "visible"
92
+ }
93
+ });
94
+ var overlayVariants = cva({
95
+ base: "absolute inset-0 flex items-center justify-center bg-black/40 transition-opacity",
96
+ variants: {
97
+ visibility: {
98
+ visible: "opacity-100",
99
+ hidden: "opacity-0 pointer-events-none"
100
+ }
101
+ },
102
+ defaultVariants: {
103
+ visibility: "visible"
104
+ }
105
+ });
106
+
107
+ // ../react-video-player/dist/index.js
108
+ import { jsx, jsxs } from "react/jsx-runtime";
109
+ var VideoPlayer = React.forwardRef(
110
+ function VideoPlayer2({
111
+ src,
112
+ poster,
113
+ autoplay = false,
114
+ muted: initialMuted = false,
115
+ controls = true,
116
+ className,
117
+ ...props
118
+ }, ref) {
119
+ const [, setTick] = React.useState(0);
120
+ const rerender = React.useCallback(() => setTick((t) => t + 1), []);
121
+ const apiRef = React.useRef(
122
+ createVideoPlayer({ src, poster, autoplay, muted: initialMuted, controls })
123
+ );
124
+ const api = apiRef.current;
125
+ if (!src) {
126
+ return /* @__PURE__ */ jsx(
127
+ "div",
128
+ {
129
+ ref,
130
+ className: cn(playerVariants(), "flex items-center justify-center aspect-video", className),
131
+ ...api.ariaProps,
132
+ ...props,
133
+ children: /* @__PURE__ */ jsx("div", { className: "text-center text-muted-foreground", children: /* @__PURE__ */ jsx("p", { className: "text-lg font-medium", children: "Coming soon" }) })
134
+ }
135
+ );
136
+ }
137
+ const handlePlay = () => {
138
+ api.play();
139
+ rerender();
140
+ };
141
+ const handlePause = () => {
142
+ api.pause();
143
+ rerender();
144
+ };
145
+ const handleTogglePlay = () => {
146
+ api.togglePlay();
147
+ rerender();
148
+ };
149
+ const handleToggleMute = () => {
150
+ api.toggleMute();
151
+ rerender();
152
+ };
153
+ const isPlaying = api.state === "playing";
154
+ return /* @__PURE__ */ jsxs(
155
+ "div",
156
+ {
157
+ ref,
158
+ className: cn(playerVariants(), "aspect-video", className),
159
+ ...api.ariaProps,
160
+ ...api.dataAttributes,
161
+ ...props,
162
+ children: [
163
+ /* @__PURE__ */ jsx(
164
+ "video",
165
+ {
166
+ className: "h-full w-full",
167
+ src,
168
+ poster,
169
+ autoPlay: autoplay,
170
+ muted: initialMuted,
171
+ onPlay: handlePlay,
172
+ onPause: handlePause
173
+ }
174
+ ),
175
+ controls && /* @__PURE__ */ jsx("div", { className: overlayVariants({ visibility: isPlaying ? "hidden" : "visible" }), children: /* @__PURE__ */ jsx(
176
+ "button",
177
+ {
178
+ type: "button",
179
+ className: "rounded-full bg-white/90 p-4 text-black shadow-lg",
180
+ onClick: handleTogglePlay,
181
+ ...api.controlAriaProps.playPause,
182
+ children: isPlaying ? "Pause" : "Play"
183
+ }
184
+ ) }),
185
+ controls && /* @__PURE__ */ jsx("div", { className: controlsVariants(), children: /* @__PURE__ */ jsx(
186
+ "button",
187
+ {
188
+ type: "button",
189
+ className: "rounded bg-white/20 px-3 py-1 text-sm text-white",
190
+ onClick: handleToggleMute,
191
+ ...api.controlAriaProps.mute,
192
+ children: api.controlAriaProps.mute["aria-label"]
193
+ }
194
+ ) })
195
+ ]
196
+ }
197
+ );
198
+ }
199
+ );
200
+ export {
201
+ VideoPlayer,
202
+ controlsVariants,
203
+ overlayVariants,
204
+ playerVariants
205
+ };
206
+ //# sourceMappingURL=react-video-player.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../video-player/src/video-player.ts", "../../video-player/src/video-player.styles.ts", "../../react-video-player/src/video-player.tsx"],
4
+ "sourcesContent": ["import type { AccessibilityProps } from '@refraction-ui/shared'\n\nexport interface VideoPlayerProps {\n src?: string\n poster?: string\n autoplay?: boolean\n muted?: boolean\n controls?: boolean\n}\n\nexport type VideoState = 'idle' | 'loading' | 'playing' | 'paused' | 'ended'\n\nexport interface VideoPlayerAPI {\n /** Current player state */\n state: VideoState\n /** Transition to playing state */\n play: () => void\n /** Transition to paused state */\n pause: () => void\n /** Toggle between playing and paused */\n togglePlay: () => void\n /** Toggle mute state */\n toggleMute: () => boolean\n /** ARIA props for the player region */\n ariaProps: Partial<AccessibilityProps>\n /** ARIA props for control buttons */\n controlAriaProps: {\n playPause: Partial<AccessibilityProps>\n mute: Partial<AccessibilityProps>\n }\n /** Data attributes reflecting current state */\n dataAttributes: Record<string, string>\n}\n\nexport function createVideoPlayer(props: VideoPlayerProps = {}): VideoPlayerAPI {\n const { muted: initialMuted = false } = props\n\n let state: VideoState = 'idle'\n let isMuted = initialMuted\n\n function play() {\n if (state === 'ended') {\n state = 'playing'\n } else if (state !== 'playing') {\n state = 'playing'\n }\n }\n\n function pause() {\n if (state === 'playing') {\n state = 'paused'\n }\n }\n\n function togglePlay() {\n if (state === 'playing') {\n pause()\n } else {\n play()\n }\n }\n\n function toggleMute(): boolean {\n isMuted = !isMuted\n return isMuted\n }\n\n const ariaProps: Partial<AccessibilityProps> = {\n role: 'region',\n 'aria-label': 'Video player',\n }\n\n const api: VideoPlayerAPI = {\n get state() {\n return state\n },\n play,\n pause,\n togglePlay,\n toggleMute,\n ariaProps,\n get controlAriaProps() {\n return {\n playPause: {\n 'aria-label': state === 'playing' ? 'Pause' : 'Play',\n },\n mute: {\n 'aria-label': isMuted ? 'Unmute' : 'Mute',\n },\n }\n },\n get dataAttributes() {\n return {\n 'data-state': state,\n }\n },\n }\n\n return api\n}\n", "import { cva } from '@refraction-ui/shared'\n\nexport const playerVariants = cva({\n base: 'relative overflow-hidden rounded-lg bg-black',\n variants: {\n size: {\n sm: 'max-w-sm',\n md: 'max-w-2xl',\n lg: 'max-w-4xl',\n full: 'w-full',\n },\n },\n defaultVariants: {\n size: 'full',\n },\n})\n\nexport const controlsVariants = cva({\n base: 'absolute bottom-0 left-0 right-0 flex items-center gap-2 bg-gradient-to-t from-black/80 to-transparent p-4 transition-opacity',\n variants: {\n visibility: {\n visible: 'opacity-100',\n hidden: 'opacity-0 pointer-events-none',\n },\n },\n defaultVariants: {\n visibility: 'visible',\n },\n})\n\nexport const overlayVariants = cva({\n base: 'absolute inset-0 flex items-center justify-center bg-black/40 transition-opacity',\n variants: {\n visibility: {\n visible: 'opacity-100',\n hidden: 'opacity-0 pointer-events-none',\n },\n },\n defaultVariants: {\n visibility: 'visible',\n },\n})\n", "import * as React from 'react'\nimport {\n createVideoPlayer,\n playerVariants,\n controlsVariants,\n overlayVariants,\n type VideoPlayerProps as CoreVideoPlayerProps,\n} from '@refraction-ui/video-player'\nimport { cn } from '@refraction-ui/shared'\n\nexport interface VideoPlayerProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'src'>,\n CoreVideoPlayerProps {}\n\nexport const VideoPlayer = React.forwardRef<HTMLDivElement, VideoPlayerProps>(\n function VideoPlayer(\n {\n src,\n poster,\n autoplay = false,\n muted: initialMuted = false,\n controls = true,\n className,\n ...props\n },\n ref,\n ) {\n const [, setTick] = React.useState(0)\n const rerender = React.useCallback(() => setTick((t) => t + 1), [])\n\n const apiRef = React.useRef(\n createVideoPlayer({ src, poster, autoplay, muted: initialMuted, controls }),\n )\n const api = apiRef.current\n\n // No src — show placeholder\n if (!src) {\n return (\n <div\n ref={ref}\n className={cn(playerVariants(), 'flex items-center justify-center aspect-video', className)}\n {...api.ariaProps}\n {...props}\n >\n <div className=\"text-center text-muted-foreground\">\n <p className=\"text-lg font-medium\">Coming soon</p>\n </div>\n </div>\n )\n }\n\n const handlePlay = () => {\n api.play()\n rerender()\n }\n\n const handlePause = () => {\n api.pause()\n rerender()\n }\n\n const handleTogglePlay = () => {\n api.togglePlay()\n rerender()\n }\n\n const handleToggleMute = () => {\n api.toggleMute()\n rerender()\n }\n\n const isPlaying = api.state === 'playing'\n\n return (\n <div\n ref={ref}\n className={cn(playerVariants(), 'aspect-video', className)}\n {...api.ariaProps}\n {...api.dataAttributes}\n {...props}\n >\n <video\n className=\"h-full w-full\"\n src={src}\n poster={poster}\n autoPlay={autoplay}\n muted={initialMuted}\n onPlay={handlePlay}\n onPause={handlePause}\n />\n\n {/* Center play/pause overlay */}\n {controls && (\n <div className={overlayVariants({ visibility: isPlaying ? 'hidden' : 'visible' })}>\n <button\n type=\"button\"\n className=\"rounded-full bg-white/90 p-4 text-black shadow-lg\"\n onClick={handleTogglePlay}\n {...api.controlAriaProps.playPause}\n >\n {isPlaying ? 'Pause' : 'Play'}\n </button>\n </div>\n )}\n\n {/* Bottom controls bar */}\n {controls && (\n <div className={controlsVariants()}>\n <button\n type=\"button\"\n className=\"rounded bg-white/20 px-3 py-1 text-sm text-white\"\n onClick={handleToggleMute}\n {...api.controlAriaProps.mute}\n >\n {api.controlAriaProps.mute['aria-label']}\n </button>\n </div>\n )}\n </div>\n )\n },\n)\n"],
5
+ "mappings": "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",
6
+ "names": ["VideoPlayer"]
7
+ }
@@ -0,0 +1,8 @@
1
+ import {
2
+ VideoTile
3
+ } from "./chunk-H54FLNAF.js";
4
+ import "./chunk-ZF3OHCGV.js";
5
+ export {
6
+ VideoTile
7
+ };
8
+ //# sourceMappingURL=react-video-tile.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }
@@ -0,0 +1,314 @@
1
+ import {
2
+ cn,
3
+ cva
4
+ } from "./chunk-ZF3OHCGV.js";
5
+
6
+ // ../react-voice-pill/dist/index.js
7
+ import * as React from "react";
8
+
9
+ // ../voice-pill/dist/index.js
10
+ var DEFAULT_VOICE_PILL_SPEAKER = "ai";
11
+ var DEFAULT_VOICE_PILL_POSITION = "bottom-center";
12
+ function formatNumber(value) {
13
+ return Number(value.toFixed(3)).toString();
14
+ }
15
+ function getRawSpeaker(speaker) {
16
+ const value = String(speaker ?? DEFAULT_VOICE_PILL_SPEAKER).trim();
17
+ return value.length > 0 ? value : DEFAULT_VOICE_PILL_SPEAKER;
18
+ }
19
+ function clampVoicePillIntensity(intensity = 0) {
20
+ const value = Number(intensity);
21
+ if (!Number.isFinite(value)) {
22
+ return 0;
23
+ }
24
+ return Math.min(1, Math.max(0, value));
25
+ }
26
+ function getVoicePillSpeakerKey(speaker) {
27
+ const normalized = getRawSpeaker(speaker).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
28
+ return normalized.length > 0 ? normalized : DEFAULT_VOICE_PILL_SPEAKER;
29
+ }
30
+ function getVoicePillSpeakerLabel(speaker) {
31
+ const raw = getRawSpeaker(speaker);
32
+ const key = getVoicePillSpeakerKey(raw);
33
+ if (key === "ai") return "AI";
34
+ if (key === "user") return "User";
35
+ return raw;
36
+ }
37
+ function getVoicePillInitials(speaker) {
38
+ const key = getVoicePillSpeakerKey(speaker);
39
+ if (key === "ai") return "AI";
40
+ if (key === "user") return "U";
41
+ const initials = getVoicePillSpeakerLabel(speaker).split(/[\s_-]+/).map((part) => part.charAt(0)).filter(Boolean).join("").slice(0, 2).toUpperCase();
42
+ return initials.length > 0 ? initials : "V";
43
+ }
44
+ function getVoicePillPosition(position) {
45
+ return position ?? DEFAULT_VOICE_PILL_POSITION;
46
+ }
47
+ function getVoicePillAriaLabel(props) {
48
+ const parts = [`${getVoicePillSpeakerLabel(props.speaker)}: ${props.label}`];
49
+ if (props.sub) {
50
+ parts.push(props.sub);
51
+ }
52
+ if (props.muted) {
53
+ parts.push("muted");
54
+ }
55
+ return parts.join(", ");
56
+ }
57
+ function getVoicePillPulseStyle(intensity, muted = false) {
58
+ const clamped = clampVoicePillIntensity(intensity);
59
+ const visualIntensity = muted ? 0 : clamped;
60
+ const ringOpacity = visualIntensity === 0 ? 0 : 0.12 + visualIntensity * 0.42;
61
+ const ringScale = 1 + visualIntensity * 0.35;
62
+ const duration = visualIntensity === 0 ? 1800 : Math.round(1700 - visualIntensity * 700);
63
+ return {
64
+ "--rfr-voice-pill-intensity": formatNumber(clamped),
65
+ "--rfr-voice-pill-visual-intensity": formatNumber(visualIntensity),
66
+ "--rfr-voice-pill-ring-opacity": formatNumber(ringOpacity),
67
+ "--rfr-voice-pill-ring-scale": formatNumber(ringScale),
68
+ "--rfr-voice-pill-pulse-duration": `${duration}ms`,
69
+ "--rfr-voice-pill-pulse-delay": `-${Math.round(duration / 2)}ms`
70
+ };
71
+ }
72
+ function createVoicePill(props) {
73
+ const {
74
+ speaker: speakerProp,
75
+ label,
76
+ sub,
77
+ intensity: intensityProp,
78
+ muted: mutedProp = false,
79
+ onToggleMute,
80
+ position: positionProp
81
+ } = props;
82
+ const speaker = getVoicePillSpeakerLabel(speakerProp);
83
+ const speakerKey = getVoicePillSpeakerKey(speakerProp);
84
+ const intensity = clampVoicePillIntensity(intensityProp);
85
+ const muted = Boolean(mutedProp);
86
+ const visualIntensity = muted ? 0 : intensity;
87
+ const position = getVoicePillPosition(positionProp);
88
+ function toggleMute() {
89
+ onToggleMute?.();
90
+ }
91
+ const ariaProps = {
92
+ role: "status",
93
+ "aria-live": "polite",
94
+ "aria-atomic": true,
95
+ "aria-label": getVoicePillAriaLabel({ speaker: speakerProp, label, sub, muted })
96
+ };
97
+ const toggleMuteAriaProps = {
98
+ "aria-label": muted ? "Unmute voice" : "Mute voice",
99
+ "aria-pressed": muted
100
+ };
101
+ const dataAttributes = {
102
+ "data-speaker": speakerKey,
103
+ "data-muted": String(muted),
104
+ "data-position": position,
105
+ "data-intensity": formatNumber(intensity),
106
+ "data-active": String(visualIntensity > 0)
107
+ };
108
+ return {
109
+ speaker,
110
+ speakerKey,
111
+ label,
112
+ sub,
113
+ intensity,
114
+ visualIntensity,
115
+ muted,
116
+ position,
117
+ initials: getVoicePillInitials(speakerProp),
118
+ toggleMute,
119
+ ariaProps,
120
+ toggleMuteAriaProps,
121
+ dataAttributes,
122
+ style: getVoicePillPulseStyle(intensity, muted)
123
+ };
124
+ }
125
+ var voicePillTokens = {
126
+ name: "voice-pill",
127
+ tokens: {
128
+ bg: { variable: "--rfr-voice-pill-bg", fallback: "hsl(var(--background))" },
129
+ fg: { variable: "--rfr-voice-pill-fg", fallback: "hsl(var(--foreground))" },
130
+ border: { variable: "--rfr-voice-pill-border", fallback: "hsl(var(--border))" },
131
+ accent: { variable: "--rfr-voice-pill-accent", fallback: "hsl(var(--primary))" },
132
+ accentFg: {
133
+ variable: "--rfr-voice-pill-accent-foreground",
134
+ fallback: "hsl(var(--primary-foreground))"
135
+ }
136
+ }
137
+ };
138
+ var voicePillRootStyles = "inline-flex min-w-0 max-w-[min(calc(100vw-2rem),22rem)] items-center gap-3 rounded-full border border-border bg-background px-3 py-2 text-foreground shadow-lg ring-1 ring-border/50 transition-opacity data-[muted=true]:opacity-80";
139
+ var voicePillSpeakerStyles = "[--rfr-voice-pill-accent:hsl(var(--primary))] [--rfr-voice-pill-accent-foreground:hsl(var(--primary-foreground))] data-[speaker=user]:[--rfr-voice-pill-accent:hsl(var(--accent-foreground))] data-[speaker=user]:[--rfr-voice-pill-accent-foreground:hsl(var(--accent))] data-[muted=true]:[--rfr-voice-pill-accent:hsl(var(--muted-foreground))]";
140
+ var voicePillPositionVariants = cva({
141
+ base: "z-50",
142
+ variants: {
143
+ position: {
144
+ inline: "relative",
145
+ "top-start": "fixed top-[calc(env(safe-area-inset-top)+1rem)] left-[calc(env(safe-area-inset-left)+1rem)]",
146
+ "top-center": "fixed top-[calc(env(safe-area-inset-top)+1rem)] left-1/2 -translate-x-1/2",
147
+ "top-end": "fixed top-[calc(env(safe-area-inset-top)+1rem)] right-[calc(env(safe-area-inset-right)+1rem)]",
148
+ "bottom-start": "fixed bottom-[calc(env(safe-area-inset-bottom)+1rem)] left-[calc(env(safe-area-inset-left)+1rem)]",
149
+ "bottom-center": "fixed bottom-[calc(env(safe-area-inset-bottom)+1rem)] left-1/2 -translate-x-1/2",
150
+ "bottom-end": "fixed bottom-[calc(env(safe-area-inset-bottom)+1rem)] right-[calc(env(safe-area-inset-right)+1rem)]",
151
+ "left-start": "fixed left-[calc(env(safe-area-inset-left)+1rem)] top-[calc(env(safe-area-inset-top)+1rem)]",
152
+ "left-center": "fixed left-[calc(env(safe-area-inset-left)+1rem)] top-1/2 -translate-y-1/2",
153
+ "left-end": "fixed left-[calc(env(safe-area-inset-left)+1rem)] bottom-[calc(env(safe-area-inset-bottom)+1rem)]",
154
+ "right-start": "fixed right-[calc(env(safe-area-inset-right)+1rem)] top-[calc(env(safe-area-inset-top)+1rem)]",
155
+ "right-center": "fixed right-[calc(env(safe-area-inset-right)+1rem)] top-1/2 -translate-y-1/2",
156
+ "right-end": "fixed right-[calc(env(safe-area-inset-right)+1rem)] bottom-[calc(env(safe-area-inset-bottom)+1rem)]"
157
+ }
158
+ },
159
+ defaultVariants: {
160
+ position: "bottom-center"
161
+ }
162
+ });
163
+ var voicePillAvatarWrapStyles = "relative flex h-10 w-10 shrink-0 items-center justify-center";
164
+ var voicePillPulseRingStyles = "pointer-events-none absolute inset-0 rounded-full border border-[var(--rfr-voice-pill-accent)] opacity-[var(--rfr-voice-pill-ring-opacity)] motion-safe:animate-ping motion-reduce:animate-none";
165
+ var voicePillAvatarStyles = "relative z-10 flex h-10 w-10 items-center justify-center overflow-hidden rounded-full bg-[var(--rfr-voice-pill-accent)] text-[var(--rfr-voice-pill-accent-foreground)] text-xs font-semibold uppercase";
166
+ var voicePillTextStyles = "min-w-0 flex-1";
167
+ var voicePillLabelStyles = "block truncate text-sm font-medium leading-tight";
168
+ var voicePillSubStyles = "block truncate text-xs leading-tight text-muted-foreground";
169
+ var voicePillMuteButtonStyles = "inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full border border-border text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring";
170
+
171
+ // ../react-voice-pill/dist/index.js
172
+ var VoicePill = React.forwardRef(
173
+ function VoicePill2({
174
+ speaker,
175
+ label,
176
+ sub,
177
+ intensity,
178
+ muted,
179
+ onToggleMute,
180
+ position,
181
+ avatar,
182
+ className,
183
+ style,
184
+ ...props
185
+ }, ref) {
186
+ const api = createVoicePill({
187
+ speaker,
188
+ label,
189
+ sub,
190
+ intensity,
191
+ muted,
192
+ onToggleMute,
193
+ position
194
+ });
195
+ const mergedStyle = {
196
+ ...api.style,
197
+ ...style
198
+ };
199
+ const pulseStyle = {
200
+ animationDuration: "var(--rfr-voice-pill-pulse-duration)",
201
+ transform: "scale(var(--rfr-voice-pill-ring-scale))"
202
+ };
203
+ const delayedPulseStyle = {
204
+ ...pulseStyle,
205
+ animationDelay: "var(--rfr-voice-pill-pulse-delay)"
206
+ };
207
+ return React.createElement(
208
+ "div",
209
+ {
210
+ ...props,
211
+ ...api.ariaProps,
212
+ ...api.dataAttributes,
213
+ ref,
214
+ className: cn(
215
+ voicePillPositionVariants({ position: api.position }),
216
+ voicePillRootStyles,
217
+ voicePillSpeakerStyles,
218
+ className
219
+ ),
220
+ style: mergedStyle
221
+ },
222
+ React.createElement(
223
+ "span",
224
+ {
225
+ className: voicePillAvatarWrapStyles,
226
+ "aria-hidden": true
227
+ },
228
+ api.visualIntensity > 0 && React.createElement("span", {
229
+ className: voicePillPulseRingStyles,
230
+ style: pulseStyle
231
+ }),
232
+ api.visualIntensity > 0 && React.createElement("span", {
233
+ className: voicePillPulseRingStyles,
234
+ style: delayedPulseStyle
235
+ }),
236
+ React.createElement(
237
+ "span",
238
+ { className: voicePillAvatarStyles },
239
+ avatar ?? api.initials
240
+ )
241
+ ),
242
+ React.createElement(
243
+ "span",
244
+ { className: voicePillTextStyles },
245
+ React.createElement("span", { className: voicePillLabelStyles }, api.label),
246
+ api.sub && React.createElement("span", { className: voicePillSubStyles }, api.sub)
247
+ ),
248
+ onToggleMute && React.createElement(
249
+ "button",
250
+ {
251
+ type: "button",
252
+ className: voicePillMuteButtonStyles,
253
+ onClick: api.toggleMute,
254
+ ...api.toggleMuteAriaProps
255
+ },
256
+ renderMuteIcon(api.muted)
257
+ )
258
+ );
259
+ }
260
+ );
261
+ function renderMuteIcon(muted) {
262
+ return React.createElement(
263
+ "svg",
264
+ {
265
+ "aria-hidden": true,
266
+ className: "h-4 w-4",
267
+ fill: "none",
268
+ stroke: "currentColor",
269
+ strokeLinecap: "round",
270
+ strokeLinejoin: "round",
271
+ strokeWidth: 2,
272
+ viewBox: "0 0 24 24"
273
+ },
274
+ React.createElement("path", {
275
+ d: "M4 9v6h4l5 4V5L8 9H4Z"
276
+ }),
277
+ muted ? React.createElement(
278
+ React.Fragment,
279
+ null,
280
+ React.createElement("path", { d: "m19 9-4 4" }),
281
+ React.createElement("path", { d: "m15 9 4 4" })
282
+ ) : React.createElement(
283
+ React.Fragment,
284
+ null,
285
+ React.createElement("path", { d: "M16 8.5a4 4 0 0 1 0 7" }),
286
+ React.createElement("path", { d: "M18.5 6a7 7 0 0 1 0 12" })
287
+ )
288
+ );
289
+ }
290
+ export {
291
+ DEFAULT_VOICE_PILL_POSITION,
292
+ DEFAULT_VOICE_PILL_SPEAKER,
293
+ VoicePill,
294
+ clampVoicePillIntensity,
295
+ createVoicePill,
296
+ getVoicePillAriaLabel,
297
+ getVoicePillInitials,
298
+ getVoicePillPosition,
299
+ getVoicePillPulseStyle,
300
+ getVoicePillSpeakerKey,
301
+ getVoicePillSpeakerLabel,
302
+ voicePillAvatarStyles,
303
+ voicePillAvatarWrapStyles,
304
+ voicePillLabelStyles,
305
+ voicePillMuteButtonStyles,
306
+ voicePillPositionVariants,
307
+ voicePillPulseRingStyles,
308
+ voicePillRootStyles,
309
+ voicePillSpeakerStyles,
310
+ voicePillSubStyles,
311
+ voicePillTextStyles,
312
+ voicePillTokens
313
+ };
314
+ //# sourceMappingURL=react-voice-pill.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../voice-pill/src/voice-pill.ts", "../../voice-pill/src/voice-pill.styles.ts", "../../react-voice-pill/src/voice-pill.tsx"],
4
+ "sourcesContent": ["export type VoicePillSpeaker = 'ai' | 'user' | (string & {})\n\nexport type VoicePillPosition =\n | 'inline'\n | 'top-start'\n | 'top-center'\n | 'top-end'\n | 'bottom-start'\n | 'bottom-center'\n | 'bottom-end'\n | 'left-start'\n | 'left-center'\n | 'left-end'\n | 'right-start'\n | 'right-center'\n | 'right-end'\n\nexport interface VoicePillProps {\n /** Speaker identity used for labels and data-speaker theming */\n speaker?: VoicePillSpeaker\n /** Primary voice status text */\n label: string\n /** Optional secondary status text */\n sub?: string\n /** Voice activity intensity, clamped from 0 to 1 */\n intensity?: number\n /** Whether voice output/input is muted */\n muted?: boolean\n /** Callback for the optional mute toggle */\n onToggleMute?: () => void\n /** Viewport position, or inline for embedding inside another layout */\n position?: VoicePillPosition\n}\n\nexport interface VoicePillStyleVars {\n [key: `--${string}`]: string\n}\n\nexport interface VoicePillAPI {\n /** Display speaker label */\n speaker: string\n /** Normalized key for data-speaker */\n speakerKey: string\n /** Primary label */\n label: string\n /** Secondary label */\n sub?: string\n /** Clamped raw intensity */\n intensity: number\n /** Intensity used for visual animation after muted state is applied */\n visualIntensity: number\n /** Muted state */\n muted: boolean\n /** Viewport position, or inline for embedding inside another layout */\n position: VoicePillPosition\n /** Fallback initials for the speaker avatar */\n initials: string\n /** Invoke the mute callback when provided */\n toggleMute(): void\n /** ARIA props for the live status pill */\n ariaProps: Record<string, string | number | boolean>\n /** ARIA props for the mute toggle */\n toggleMuteAriaProps: Record<string, unknown>\n /** Data attributes reflecting speaker/state */\n dataAttributes: Record<string, string>\n /** CSS custom properties that drive pulse visuals */\n style: VoicePillStyleVars\n}\n\nexport const DEFAULT_VOICE_PILL_SPEAKER = 'ai'\nexport const DEFAULT_VOICE_PILL_POSITION: VoicePillPosition = 'bottom-center'\n\nfunction formatNumber(value: number): string {\n return Number(value.toFixed(3)).toString()\n}\n\nfunction getRawSpeaker(speaker?: VoicePillSpeaker): string {\n const value = String(speaker ?? DEFAULT_VOICE_PILL_SPEAKER).trim()\n return value.length > 0 ? value : DEFAULT_VOICE_PILL_SPEAKER\n}\n\nexport function clampVoicePillIntensity(intensity = 0): number {\n const value = Number(intensity)\n\n if (!Number.isFinite(value)) {\n return 0\n }\n\n return Math.min(1, Math.max(0, value))\n}\n\nexport function getVoicePillSpeakerKey(speaker?: VoicePillSpeaker): string {\n const normalized = getRawSpeaker(speaker)\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n\n return normalized.length > 0 ? normalized : DEFAULT_VOICE_PILL_SPEAKER\n}\n\nexport function getVoicePillSpeakerLabel(speaker?: VoicePillSpeaker): string {\n const raw = getRawSpeaker(speaker)\n const key = getVoicePillSpeakerKey(raw)\n\n if (key === 'ai') return 'AI'\n if (key === 'user') return 'User'\n\n return raw\n}\n\nexport function getVoicePillInitials(speaker?: VoicePillSpeaker): string {\n const key = getVoicePillSpeakerKey(speaker)\n\n if (key === 'ai') return 'AI'\n if (key === 'user') return 'U'\n\n const initials = getVoicePillSpeakerLabel(speaker)\n .split(/[\\s_-]+/)\n .map((part) => part.charAt(0))\n .filter(Boolean)\n .join('')\n .slice(0, 2)\n .toUpperCase()\n\n return initials.length > 0 ? initials : 'V'\n}\n\nexport function getVoicePillPosition(\n position?: VoicePillPosition,\n): VoicePillPosition {\n return position ?? DEFAULT_VOICE_PILL_POSITION\n}\n\nexport function getVoicePillAriaLabel(props: {\n speaker?: VoicePillSpeaker\n label: string\n sub?: string\n muted?: boolean\n}): string {\n const parts = [`${getVoicePillSpeakerLabel(props.speaker)}: ${props.label}`]\n\n if (props.sub) {\n parts.push(props.sub)\n }\n\n if (props.muted) {\n parts.push('muted')\n }\n\n return parts.join(', ')\n}\n\nexport function getVoicePillPulseStyle(\n intensity?: number,\n muted = false,\n): VoicePillStyleVars {\n const clamped = clampVoicePillIntensity(intensity)\n const visualIntensity = muted ? 0 : clamped\n const ringOpacity = visualIntensity === 0 ? 0 : 0.12 + visualIntensity * 0.42\n const ringScale = 1 + visualIntensity * 0.35\n const duration = visualIntensity === 0\n ? 1800\n : Math.round(1700 - visualIntensity * 700)\n\n return {\n '--rfr-voice-pill-intensity': formatNumber(clamped),\n '--rfr-voice-pill-visual-intensity': formatNumber(visualIntensity),\n '--rfr-voice-pill-ring-opacity': formatNumber(ringOpacity),\n '--rfr-voice-pill-ring-scale': formatNumber(ringScale),\n '--rfr-voice-pill-pulse-duration': `${duration}ms`,\n '--rfr-voice-pill-pulse-delay': `-${Math.round(duration / 2)}ms`,\n }\n}\n\nexport function createVoicePill(props: VoicePillProps): VoicePillAPI {\n const {\n speaker: speakerProp,\n label,\n sub,\n intensity: intensityProp,\n muted: mutedProp = false,\n onToggleMute,\n position: positionProp,\n } = props\n\n const speaker = getVoicePillSpeakerLabel(speakerProp)\n const speakerKey = getVoicePillSpeakerKey(speakerProp)\n const intensity = clampVoicePillIntensity(intensityProp)\n const muted = Boolean(mutedProp)\n const visualIntensity = muted ? 0 : intensity\n const position = getVoicePillPosition(positionProp)\n\n function toggleMute(): void {\n onToggleMute?.()\n }\n\n const ariaProps: Record<string, string | number | boolean> = {\n role: 'status',\n 'aria-live': 'polite',\n 'aria-atomic': true,\n 'aria-label': getVoicePillAriaLabel({ speaker: speakerProp, label, sub, muted }),\n }\n\n const toggleMuteAriaProps: Record<string, unknown> = {\n 'aria-label': muted ? 'Unmute voice' : 'Mute voice',\n 'aria-pressed': muted,\n }\n\n const dataAttributes: Record<string, string> = {\n 'data-speaker': speakerKey,\n 'data-muted': String(muted),\n 'data-position': position,\n 'data-intensity': formatNumber(intensity),\n 'data-active': String(visualIntensity > 0),\n }\n\n return {\n speaker,\n speakerKey,\n label,\n sub,\n intensity,\n visualIntensity,\n muted,\n position,\n initials: getVoicePillInitials(speakerProp),\n toggleMute,\n ariaProps,\n toggleMuteAriaProps,\n dataAttributes,\n style: getVoicePillPulseStyle(intensity, muted),\n }\n}\n", "import { cva } from '@refraction-ui/shared'\nimport type { TokenContract } from '@refraction-ui/shared'\n\nexport const voicePillTokens: TokenContract = {\n name: 'voice-pill',\n tokens: {\n bg: { variable: '--rfr-voice-pill-bg', fallback: 'hsl(var(--background))' },\n fg: { variable: '--rfr-voice-pill-fg', fallback: 'hsl(var(--foreground))' },\n border: { variable: '--rfr-voice-pill-border', fallback: 'hsl(var(--border))' },\n accent: { variable: '--rfr-voice-pill-accent', fallback: 'hsl(var(--primary))' },\n accentFg: {\n variable: '--rfr-voice-pill-accent-foreground',\n fallback: 'hsl(var(--primary-foreground))',\n },\n },\n}\n\nexport const voicePillRootStyles =\n 'inline-flex min-w-0 max-w-[min(calc(100vw-2rem),22rem)] items-center gap-3 rounded-full border border-border bg-background px-3 py-2 text-foreground shadow-lg ring-1 ring-border/50 transition-opacity data-[muted=true]:opacity-80'\n\nexport const voicePillSpeakerStyles =\n '[--rfr-voice-pill-accent:hsl(var(--primary))] [--rfr-voice-pill-accent-foreground:hsl(var(--primary-foreground))] data-[speaker=user]:[--rfr-voice-pill-accent:hsl(var(--accent-foreground))] data-[speaker=user]:[--rfr-voice-pill-accent-foreground:hsl(var(--accent))] data-[muted=true]:[--rfr-voice-pill-accent:hsl(var(--muted-foreground))]'\n\nexport const voicePillPositionVariants = cva({\n base: 'z-50',\n variants: {\n position: {\n inline: 'relative',\n 'top-start':\n 'fixed top-[calc(env(safe-area-inset-top)+1rem)] left-[calc(env(safe-area-inset-left)+1rem)]',\n 'top-center':\n 'fixed top-[calc(env(safe-area-inset-top)+1rem)] left-1/2 -translate-x-1/2',\n 'top-end':\n 'fixed top-[calc(env(safe-area-inset-top)+1rem)] right-[calc(env(safe-area-inset-right)+1rem)]',\n 'bottom-start':\n 'fixed bottom-[calc(env(safe-area-inset-bottom)+1rem)] left-[calc(env(safe-area-inset-left)+1rem)]',\n 'bottom-center':\n 'fixed bottom-[calc(env(safe-area-inset-bottom)+1rem)] left-1/2 -translate-x-1/2',\n 'bottom-end':\n 'fixed bottom-[calc(env(safe-area-inset-bottom)+1rem)] right-[calc(env(safe-area-inset-right)+1rem)]',\n 'left-start':\n 'fixed left-[calc(env(safe-area-inset-left)+1rem)] top-[calc(env(safe-area-inset-top)+1rem)]',\n 'left-center':\n 'fixed left-[calc(env(safe-area-inset-left)+1rem)] top-1/2 -translate-y-1/2',\n 'left-end':\n 'fixed left-[calc(env(safe-area-inset-left)+1rem)] bottom-[calc(env(safe-area-inset-bottom)+1rem)]',\n 'right-start':\n 'fixed right-[calc(env(safe-area-inset-right)+1rem)] top-[calc(env(safe-area-inset-top)+1rem)]',\n 'right-center':\n 'fixed right-[calc(env(safe-area-inset-right)+1rem)] top-1/2 -translate-y-1/2',\n 'right-end':\n 'fixed right-[calc(env(safe-area-inset-right)+1rem)] bottom-[calc(env(safe-area-inset-bottom)+1rem)]',\n },\n },\n defaultVariants: {\n position: 'bottom-center',\n },\n})\n\nexport const voicePillAvatarWrapStyles =\n 'relative flex h-10 w-10 shrink-0 items-center justify-center'\n\nexport const voicePillPulseRingStyles =\n 'pointer-events-none absolute inset-0 rounded-full border border-[var(--rfr-voice-pill-accent)] opacity-[var(--rfr-voice-pill-ring-opacity)] motion-safe:animate-ping motion-reduce:animate-none'\n\nexport const voicePillAvatarStyles =\n 'relative z-10 flex h-10 w-10 items-center justify-center overflow-hidden rounded-full bg-[var(--rfr-voice-pill-accent)] text-[var(--rfr-voice-pill-accent-foreground)] text-xs font-semibold uppercase'\n\nexport const voicePillTextStyles = 'min-w-0 flex-1'\n\nexport const voicePillLabelStyles =\n 'block truncate text-sm font-medium leading-tight'\n\nexport const voicePillSubStyles =\n 'block truncate text-xs leading-tight text-muted-foreground'\n\nexport const voicePillMuteButtonStyles =\n 'inline-flex h-8 w-8 shrink-0 items-center justify-center rounded-full border border-border text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring'\n", "import * as React from 'react'\nimport {\n createVoicePill,\n voicePillAvatarStyles,\n voicePillAvatarWrapStyles,\n voicePillLabelStyles,\n voicePillMuteButtonStyles,\n voicePillPositionVariants,\n voicePillPulseRingStyles,\n voicePillRootStyles,\n voicePillSpeakerStyles,\n voicePillSubStyles,\n voicePillTextStyles,\n type VoicePillProps as CoreVoicePillProps,\n} from '@refraction-ui/voice-pill'\nimport { cn } from '@refraction-ui/shared'\n\nexport interface VoicePillProps\n extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'>,\n CoreVoicePillProps {\n avatar?: React.ReactNode\n}\n\nexport const VoicePill = React.forwardRef<HTMLDivElement, VoicePillProps>(\n function VoicePill(\n {\n speaker,\n label,\n sub,\n intensity,\n muted,\n onToggleMute,\n position,\n avatar,\n className,\n style,\n ...props\n },\n ref,\n ) {\n const api = createVoicePill({\n speaker,\n label,\n sub,\n intensity,\n muted,\n onToggleMute,\n position,\n })\n\n const mergedStyle = {\n ...api.style,\n ...style,\n } as React.CSSProperties\n\n const pulseStyle = {\n animationDuration: 'var(--rfr-voice-pill-pulse-duration)',\n transform: 'scale(var(--rfr-voice-pill-ring-scale))',\n } as React.CSSProperties\n\n const delayedPulseStyle = {\n ...pulseStyle,\n animationDelay: 'var(--rfr-voice-pill-pulse-delay)',\n } as React.CSSProperties\n\n return React.createElement(\n 'div',\n {\n ...props,\n ...api.ariaProps,\n ...api.dataAttributes,\n ref,\n className: cn(\n voicePillPositionVariants({ position: api.position }),\n voicePillRootStyles,\n voicePillSpeakerStyles,\n className,\n ),\n style: mergedStyle,\n },\n React.createElement(\n 'span',\n {\n className: voicePillAvatarWrapStyles,\n 'aria-hidden': true,\n },\n api.visualIntensity > 0 &&\n React.createElement('span', {\n className: voicePillPulseRingStyles,\n style: pulseStyle,\n }),\n api.visualIntensity > 0 &&\n React.createElement('span', {\n className: voicePillPulseRingStyles,\n style: delayedPulseStyle,\n }),\n React.createElement(\n 'span',\n { className: voicePillAvatarStyles },\n avatar ?? api.initials,\n ),\n ),\n React.createElement(\n 'span',\n { className: voicePillTextStyles },\n React.createElement('span', { className: voicePillLabelStyles }, api.label),\n api.sub &&\n React.createElement('span', { className: voicePillSubStyles }, api.sub),\n ),\n onToggleMute &&\n React.createElement(\n 'button',\n {\n type: 'button',\n className: voicePillMuteButtonStyles,\n onClick: api.toggleMute,\n ...api.toggleMuteAriaProps,\n },\n renderMuteIcon(api.muted),\n ),\n )\n },\n)\n\nfunction renderMuteIcon(muted: boolean): React.ReactElement {\n return React.createElement(\n 'svg',\n {\n 'aria-hidden': true,\n className: 'h-4 w-4',\n fill: 'none',\n stroke: 'currentColor',\n strokeLinecap: 'round',\n strokeLinejoin: 'round',\n strokeWidth: 2,\n viewBox: '0 0 24 24',\n },\n React.createElement('path', {\n d: 'M4 9v6h4l5 4V5L8 9H4Z',\n }),\n muted\n ? React.createElement(\n React.Fragment,\n null,\n React.createElement('path', { d: 'm19 9-4 4' }),\n React.createElement('path', { d: 'm15 9 4 4' }),\n )\n : React.createElement(\n React.Fragment,\n null,\n React.createElement('path', { d: 'M16 8.5a4 4 0 0 1 0 7' }),\n React.createElement('path', { d: 'M18.5 6a7 7 0 0 1 0 12' }),\n ),\n )\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["VoicePill"]
7
+ }