@ephia/dova-sdk 1.0.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 (247) hide show
  1. package/README.md +89 -0
  2. package/dist/EphiaBinding-BvRmlqqC.d.ts +36 -0
  3. package/dist/EphiaFloatingButton-CxiF86VW.d.ts +65 -0
  4. package/dist/EphiaTextarea-B4_CAVUg.d.ts +183 -0
  5. package/dist/NativeBinding-ChG0GeSz.d.ts +53 -0
  6. package/dist/TargetBinding-BKGQwUMc.d.ts +89 -0
  7. package/dist/TiptapBinding-B-agfV2H.d.ts +45 -0
  8. package/dist/Transport-zdeA4Pou.d.ts +63 -0
  9. package/dist/audio-state-kZ3KSvux.d.ts +39 -0
  10. package/dist/chunk-35AJK2IO.js +1 -0
  11. package/dist/chunk-35AJK2IO.js.map +1 -0
  12. package/dist/chunk-3LXZODL4.js +886 -0
  13. package/dist/chunk-3LXZODL4.js.map +1 -0
  14. package/dist/chunk-5IK5TLSK.js +67 -0
  15. package/dist/chunk-5IK5TLSK.js.map +1 -0
  16. package/dist/chunk-7E43RY75.js +9 -0
  17. package/dist/chunk-7E43RY75.js.map +1 -0
  18. package/dist/chunk-A5UEXJ5R.js +183 -0
  19. package/dist/chunk-A5UEXJ5R.js.map +1 -0
  20. package/dist/chunk-AEE554FT.js +51 -0
  21. package/dist/chunk-AEE554FT.js.map +1 -0
  22. package/dist/chunk-DIEWY3IT.js +1332 -0
  23. package/dist/chunk-DIEWY3IT.js.map +1 -0
  24. package/dist/chunk-EGIAN7FH.js +18 -0
  25. package/dist/chunk-EGIAN7FH.js.map +1 -0
  26. package/dist/chunk-EMOEAPVU.js +486 -0
  27. package/dist/chunk-EMOEAPVU.js.map +1 -0
  28. package/dist/chunk-IDC7FHIZ.js +40 -0
  29. package/dist/chunk-IDC7FHIZ.js.map +1 -0
  30. package/dist/chunk-ITJFN3VM.js +601 -0
  31. package/dist/chunk-ITJFN3VM.js.map +1 -0
  32. package/dist/chunk-K24GNU27.js +22 -0
  33. package/dist/chunk-K24GNU27.js.map +1 -0
  34. package/dist/chunk-LXMCRXXF.js +778 -0
  35. package/dist/chunk-LXMCRXXF.js.map +1 -0
  36. package/dist/chunk-MJCEOOLW.js +122 -0
  37. package/dist/chunk-MJCEOOLW.js.map +1 -0
  38. package/dist/chunk-N7U5M3VZ.js +33 -0
  39. package/dist/chunk-N7U5M3VZ.js.map +1 -0
  40. package/dist/chunk-PSYX674B.js +27 -0
  41. package/dist/chunk-PSYX674B.js.map +1 -0
  42. package/dist/chunk-RFQRV7ML.js +33 -0
  43. package/dist/chunk-RFQRV7ML.js.map +1 -0
  44. package/dist/chunk-THNHRV2B.js +18 -0
  45. package/dist/chunk-THNHRV2B.js.map +1 -0
  46. package/dist/chunk-VSLGR64U.js +62 -0
  47. package/dist/chunk-VSLGR64U.js.map +1 -0
  48. package/dist/chunk-W2ZP674X.js +346 -0
  49. package/dist/chunk-W2ZP674X.js.map +1 -0
  50. package/dist/chunk-YWZUMUYE.js +695 -0
  51. package/dist/chunk-YWZUMUYE.js.map +1 -0
  52. package/dist/client-options-Uo6jXO8k.d.ts +64 -0
  53. package/dist/connection-state-Bk33YprE.d.ts +32 -0
  54. package/dist/core/bindings/index.d.ts +24 -0
  55. package/dist/core/bindings/index.js +1025 -0
  56. package/dist/core/bindings/index.js.map +1 -0
  57. package/dist/core/index.d.ts +383 -0
  58. package/dist/core/index.js +1284 -0
  59. package/dist/core/index.js.map +1 -0
  60. package/dist/createEphiaClient-BhdZ183V.d.ts +69 -0
  61. package/dist/devices/speechmike/index.d.ts +148 -0
  62. package/dist/devices/speechmike/index.js +40 -0
  63. package/dist/devices/speechmike/index.js.map +1 -0
  64. package/dist/headless/index.d.ts +10 -0
  65. package/dist/headless/index.js +25 -0
  66. package/dist/headless/index.js.map +1 -0
  67. package/dist/index.d.ts +18 -0
  68. package/dist/index.js +119 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/react/index.d.ts +38 -0
  71. package/dist/react/index.js +70 -0
  72. package/dist/react/index.js.map +1 -0
  73. package/dist/rich-editor/index.d.ts +46 -0
  74. package/dist/rich-editor/index.js +13 -0
  75. package/dist/rich-editor/index.js.map +1 -0
  76. package/dist/schema-B2ycPlNB.d.ts +87 -0
  77. package/dist/session-APaXR48R.d.ts +12 -0
  78. package/dist/shared/index.d.ts +16 -0
  79. package/dist/shared/index.js +30 -0
  80. package/dist/shared/index.js.map +1 -0
  81. package/dist/style.css +1093 -0
  82. package/dist/testing/index.d.ts +84 -0
  83. package/dist/testing/index.js +36 -0
  84. package/dist/testing/index.js.map +1 -0
  85. package/dist/types-D5SXPSwR.d.ts +32 -0
  86. package/dist/ui/index.d.ts +30 -0
  87. package/dist/ui/index.js +34 -0
  88. package/dist/ui/index.js.map +1 -0
  89. package/dist/useEphiaSpeechMike-CjD7DWnh.d.ts +64 -0
  90. package/package.json +110 -0
  91. package/src/core/audio/audio-worklet-source.ts +30 -0
  92. package/src/core/audio/index.ts +3 -0
  93. package/src/core/audio/voice-level-meter.test.ts +27 -0
  94. package/src/core/audio/voice-level-meter.ts +270 -0
  95. package/src/core/bindings/EphiaBinding.ts +41 -0
  96. package/src/core/bindings/SegmentBindingBridge.test.ts +422 -0
  97. package/src/core/bindings/SegmentBindingBridge.ts +377 -0
  98. package/src/core/bindings/TargetBinding.ts +142 -0
  99. package/src/core/bindings/adapters/NativeAdapter.test.ts +85 -0
  100. package/src/core/bindings/adapters/NativeAdapter.ts +216 -0
  101. package/src/core/bindings/adapters/ProseMirrorAdapter.ts +231 -0
  102. package/src/core/bindings/adapters/index.ts +2 -0
  103. package/src/core/bindings/binding-factory.ts +78 -0
  104. package/src/core/bindings/detect-editor-type.ts +87 -0
  105. package/src/core/bindings/index.ts +13 -0
  106. package/src/core/bindings/insertion-boundary.test.ts +38 -0
  107. package/src/core/bindings/insertion-boundary.ts +26 -0
  108. package/src/core/bindings/native/NativeBinding.test.ts +277 -0
  109. package/src/core/bindings/native/NativeBinding.ts +239 -0
  110. package/src/core/bindings/resolver.ts +18 -0
  111. package/src/core/bindings/targets/codemirror.binding.ts +293 -0
  112. package/src/core/bindings/targets/contenteditable.binding.ts +452 -0
  113. package/src/core/bindings/targets/index.ts +10 -0
  114. package/src/core/bindings/targets/monaco.binding.ts +315 -0
  115. package/src/core/bindings/targets/tiptap.binding.test.ts +417 -0
  116. package/src/core/bindings/targets/tiptap.binding.ts +1192 -0
  117. package/src/core/bindings/tiptap/TiptapBinding.test.ts +63 -0
  118. package/src/core/bindings/tiptap/TiptapBinding.ts +464 -0
  119. package/src/core/bindings/types.ts +41 -0
  120. package/src/core/client/EphiaAudioClient.ts +654 -0
  121. package/src/core/client/audio-capture.ts +263 -0
  122. package/src/core/client/client-options.ts +39 -0
  123. package/src/core/client/client-state.ts +18 -0
  124. package/src/core/client/constants.ts +23 -0
  125. package/src/core/client/session-api.ts +415 -0
  126. package/src/core/connection/connection-state.ts +78 -0
  127. package/src/core/connection/index.ts +6 -0
  128. package/src/core/index.ts +47 -0
  129. package/src/core/operations/textToDocumentOperations.test.ts +69 -0
  130. package/src/core/operations/textToDocumentOperations.ts +92 -0
  131. package/src/core/runtime/DictationRuntime.test.ts +578 -0
  132. package/src/core/runtime/DictationRuntime.ts +434 -0
  133. package/src/core/runtime/TranscriptApplier.test.ts +355 -0
  134. package/src/core/runtime/TranscriptApplier.ts +229 -0
  135. package/src/core/runtime/index.ts +18 -0
  136. package/src/core/session/index.ts +2 -0
  137. package/src/core/session/session-machine.test.ts +16 -0
  138. package/src/core/session/session-machine.ts +59 -0
  139. package/src/core/targets/EditorContextCollector.ts +71 -0
  140. package/src/core/targets/TargetManager.test.ts +194 -0
  141. package/src/core/targets/TargetManager.ts +194 -0
  142. package/src/core/targets/index.ts +10 -0
  143. package/src/core/text-processing/index.ts +11 -0
  144. package/src/core/text-processing/overlap.test.ts +35 -0
  145. package/src/core/text-processing/overlap.ts +101 -0
  146. package/src/core/text-processing/voice-formatting.normalizer.test.ts +132 -0
  147. package/src/core/text-processing/voice-formatting.normalizer.ts +284 -0
  148. package/src/core/transcript/client-transcript.reducer.ts +366 -0
  149. package/src/core/transcript/client-transcript.state.ts +25 -0
  150. package/src/core/transcript/index.ts +19 -0
  151. package/src/core/transcript/transcript.assembler.test.ts +205 -0
  152. package/src/core/transcript/transcript.assembler.ts +152 -0
  153. package/src/core/transcript/transcript.reducer.test.ts +199 -0
  154. package/src/core/transcript/transcript.reducer.ts +771 -0
  155. package/src/core/transcript/transcript.state.ts +123 -0
  156. package/src/core/transport/LiveKitTransport.publish.test.ts +226 -0
  157. package/src/core/transport/LiveKitTransport.ts +459 -0
  158. package/src/core/transport/MockTransport.ts +231 -0
  159. package/src/core/transport/Transport.ts +82 -0
  160. package/src/debug/sdk-debug-collector.ts +79 -0
  161. package/src/devices/index.ts +2 -0
  162. package/src/devices/speechmike/__tests__/EphiaSpeechMikeProvider.test.tsx +99 -0
  163. package/src/devices/speechmike/__tests__/speechmike-audio-resolver.test.ts +96 -0
  164. package/src/devices/speechmike/__tests__/speechmike-button-router.test.ts +66 -0
  165. package/src/devices/speechmike/__tests__/speechmike-device-manager.test.ts +201 -0
  166. package/src/devices/speechmike/__tests__/speechmike-led-controller.test.ts +68 -0
  167. package/src/devices/speechmike/browser.ts +80 -0
  168. package/src/devices/speechmike/constants.ts +74 -0
  169. package/src/devices/speechmike/dictation-support-loader.ts +81 -0
  170. package/src/devices/speechmike/index.ts +11 -0
  171. package/src/devices/speechmike/react/EphiaSpeechMikeContext.ts +34 -0
  172. package/src/devices/speechmike/react/EphiaSpeechMikeProvider.tsx +287 -0
  173. package/src/devices/speechmike/react/useEphiaSpeechMike.ts +26 -0
  174. package/src/devices/speechmike/speechmike-audio-resolver.ts +58 -0
  175. package/src/devices/speechmike/speechmike-button-router.ts +73 -0
  176. package/src/devices/speechmike/speechmike-device-manager.ts +461 -0
  177. package/src/devices/speechmike/speechmike-led-controller.ts +78 -0
  178. package/src/devices/speechmike/types.ts +96 -0
  179. package/src/dictation_support.d.ts +31 -0
  180. package/src/global.d.ts +10 -0
  181. package/src/headless/createEphiaClient.ts +220 -0
  182. package/src/headless/index.ts +18 -0
  183. package/src/index.ts +89 -0
  184. package/src/react/EphiaAuto.tsx +87 -0
  185. package/src/react/components/EphiaDictationButton.tsx +88 -0
  186. package/src/react/components/EphiaStatusBar.tsx +59 -0
  187. package/src/react/components/EphiaTextarea.tsx +295 -0
  188. package/src/react/ephia-react.css +318 -0
  189. package/src/react/hooks/targets/index.ts +3 -0
  190. package/src/react/hooks/targets/useEphiaCodemirror.ts +35 -0
  191. package/src/react/hooks/targets/useEphiaMonaco.ts +35 -0
  192. package/src/react/hooks/targets/useEphiaTiptap.ts +23 -0
  193. package/src/react/hooks/useEphia.lifecycle.test.tsx +389 -0
  194. package/src/react/hooks/useEphia.ts +367 -0
  195. package/src/react/hooks/useEphiaDiscardTarget.ts +53 -0
  196. package/src/react/hooks/useEphiaServerEvent.ts +33 -0
  197. package/src/react/hooks/useEphiaTarget.ts +47 -0
  198. package/src/react/hooks/useEphiaTranscript.ts +22 -0
  199. package/src/react/index.ts +58 -0
  200. package/src/react/provider/EphiaContext.ts +63 -0
  201. package/src/react/provider/EphiaInternalContext.ts +32 -0
  202. package/src/react/provider/EphiaProvider.tsx +373 -0
  203. package/src/react/registry/binding-factory.ts +7 -0
  204. package/src/react/registry/detect-editor-type.ts +2 -0
  205. package/src/react/registry/events.ts +37 -0
  206. package/src/react/registry/registries/CodeMirrorInstanceRegistry.ts +24 -0
  207. package/src/react/registry/registries/MonacoInstanceRegistry.ts +23 -0
  208. package/src/react/registry/registries/TargetRegistry.ts +327 -0
  209. package/src/react/registry/registries/TiptapInstanceRegistry.ts +43 -0
  210. package/src/react/registry/registries/index.ts +5 -0
  211. package/src/react/store/create-ephia-store.ts +36 -0
  212. package/src/react/store/types.ts +41 -0
  213. package/src/react/utils/flash-range.ts +24 -0
  214. package/src/react/utils/index.ts +1 -0
  215. package/src/rich-editor/adapters/tiptap.test.ts +86 -0
  216. package/src/rich-editor/adapters/tiptap.ts +23 -0
  217. package/src/rich-editor/index.ts +3 -0
  218. package/src/rich-editor/types.ts +24 -0
  219. package/src/rich-editor/use-ephia-rich-editor.test.tsx +202 -0
  220. package/src/rich-editor/use-ephia-rich-editor.ts +47 -0
  221. package/src/shared/config/endpoint.test.ts +45 -0
  222. package/src/shared/config/endpoint.ts +39 -0
  223. package/src/shared/config/schema.ts +32 -0
  224. package/src/shared/effective-text.ts +13 -0
  225. package/src/shared/errors/EphiaSdkError.ts +54 -0
  226. package/src/shared/errors/messages.ts +40 -0
  227. package/src/shared/index.ts +27 -0
  228. package/src/shared/state/audio-state.ts +45 -0
  229. package/src/shared/state/index.ts +2 -0
  230. package/src/shared/store/document-store.ts +32 -0
  231. package/src/shared/store/index.ts +2 -0
  232. package/src/shared/types/editors.ts +28 -0
  233. package/src/shared/types/session.ts +12 -0
  234. package/src/style.css +2 -0
  235. package/src/testing/index.tsx +60 -0
  236. package/src/ui/assets/ephia-logo.svg +4 -0
  237. package/src/ui/components/EphiaLogo.tsx +77 -0
  238. package/src/ui/index.ts +24 -0
  239. package/src/ui/primitives/Button.tsx +53 -0
  240. package/src/ui/primitives/Spinner.tsx +21 -0
  241. package/src/ui/primitives/index.ts +5 -0
  242. package/src/ui/recorder/EphiaFloatingButton.tsx +489 -0
  243. package/src/ui/recorder/MinimalProcessingBars.tsx +122 -0
  244. package/src/ui/recorder/StandardIntensityVisualizer.tsx +148 -0
  245. package/src/ui/recorder/appearance.ts +9 -0
  246. package/src/ui/recorder/index.ts +8 -0
  247. package/src/ui/theme.css +775 -0
@@ -0,0 +1,695 @@
1
+ import {
2
+ EphiaProvider,
3
+ useEphia,
4
+ useEphiaAudioLevel
5
+ } from "./chunk-ITJFN3VM.js";
6
+ import {
7
+ useOptionalEphiaContext
8
+ } from "./chunk-K24GNU27.js";
9
+
10
+ // src/ui/components/EphiaLogo.tsx
11
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
12
+ var EPHIA_LOGO_VIEWBOX = "0 0 220 207";
13
+ var EPHIA_LOGO_ASPECT = 220 / 207;
14
+ var EPHIA_BRAND_PURPLE = "#723ADE";
15
+ var EPHIA_BRAND_TEAL = "#00EBD0";
16
+ var LOGO_PURPLE_PATH = "M130.184 22.8784C110.496 11.7584 85.4808 18.5556 74.1504 38.1772C66.8151 50.8807 67.004 65.8635 73.334 77.9663C76.4886 83.9978 77.6606 91.3208 74.2568 97.2153C70.8529 103.109 63.9255 105.756 57.1241 106.04C55.4205 106.111 53.7254 106.287 52.0498 106.566C51.9939 106.576 51.9377 106.586 51.8818 106.596C51.8243 106.606 51.7665 106.615 51.709 106.625C47.369 107.377 43.2604 108.806 39.4981 110.8C34.2218 113.586 29.4987 117.542 25.7589 122.554C25.7424 122.576 25.7254 122.598 25.709 122.62C25.6788 122.661 25.6482 122.701 25.6182 122.742C21.6987 128.032 19.015 134.293 17.9923 141.097C17.9778 141.192 17.964 141.289 17.9502 141.385C17.9421 141.442 17.9337 141.499 17.9258 141.556C17.6653 143.422 17.5345 145.296 17.5312 147.163V147.28C17.5314 157.14 20.9911 166.192 26.7617 173.29C26.796 173.332 26.8307 173.375 26.8652 173.417C26.928 173.494 26.9915 173.57 27.0548 173.646C27.1098 173.713 27.1653 173.779 27.2207 173.845C27.255 173.885 27.2898 173.927 27.3242 173.968C27.6222 174.319 27.9266 174.666 28.2374 175.009C28.2534 175.026 28.2701 175.044 28.2861 175.061C28.3779 175.162 28.4706 175.263 28.5635 175.363C28.5869 175.388 28.6114 175.413 28.6349 175.438C28.7264 175.536 28.8185 175.635 28.9111 175.732C28.9284 175.75 28.9456 175.769 28.9629 175.787C29.1492 175.982 29.3377 176.176 29.5283 176.367L29.6191 176.458C29.6653 176.504 29.7125 176.55 29.7589 176.596C29.8119 176.648 29.8646 176.702 29.918 176.754C36.4444 183.148 45.0865 187.393 54.6963 188.342C54.7093 188.343 54.7223 188.344 54.7354 188.346C55.0558 188.377 55.3777 188.405 55.7002 188.429C55.7229 188.43 55.746 188.432 55.7687 188.434C55.8996 188.443 56.031 188.452 56.1622 188.46C57.0288 188.515 57.8957 188.543 58.7607 188.543C58.774 188.543 58.7875 188.543 58.8008 188.543C58.8551 188.543 58.9096 188.542 58.9639 188.542C59.0597 188.542 59.1561 188.541 59.252 188.54C66.9707 188.457 74.1811 186.256 80.3292 182.49C80.3971 182.449 80.4656 182.407 80.5333 182.365C80.5789 182.337 80.6245 182.308 80.6699 182.279C85.3019 179.393 89.4161 175.551 92.6865 170.84C92.7302 170.777 92.7741 170.714 92.8174 170.651C92.8427 170.614 92.8684 170.577 92.8936 170.54C94.8281 167.711 96.419 164.628 97.6074 161.353C99.3661 156.525 100.166 151.511 100.075 146.558C100.266 130.196 106.911 115.387 117.584 104.555C120.604 101.544 123.936 98.8469 127.529 96.5151C128.082 96.1565 127.539 96.5073 129.953 95.0288C135.565 91.8709 140.505 87.373 144.245 81.6763C144.281 81.623 144.315 81.5686 144.351 81.5151C144.368 81.489 144.385 81.4622 144.402 81.436C144.828 80.7863 145.239 80.1208 145.632 79.4399C155.114 63.0194 152.024 42.7913 139.35 29.896C136.719 27.1793 133.672 24.7768 130.236 22.7886L130.184 22.8784Z";
17
+ var LOGO_TEAL_PATH = "M151.646 107.073C154.645 106.38 157.768 106.016 160.977 106.016C183.769 106.016 202.246 124.49 202.246 147.278C202.246 167.41 187.826 184.171 168.751 187.807C167.995 187.951 167.233 188.074 166.463 188.177C166.383 188.187 166.304 188.201 166.224 188.211C164.503 188.43 162.749 188.543 160.969 188.543C138.176 188.543 119.699 170.069 119.699 147.28C119.699 127.697 133.344 111.298 151.646 107.073Z";
18
+ function logoWidthFromHeight(heightPx) {
19
+ return Math.round(heightPx * EPHIA_LOGO_ASPECT);
20
+ }
21
+ function EphiaLogo({
22
+ height,
23
+ width,
24
+ className,
25
+ style,
26
+ variant = "color",
27
+ fill = "currentColor",
28
+ isRecording = false
29
+ }) {
30
+ const resolvedHeight = height ?? (width != null ? Math.round(width / EPHIA_LOGO_ASPECT) : 24);
31
+ const resolvedWidth = width ?? logoWidthFromHeight(resolvedHeight);
32
+ const svgClass = [
33
+ "ephia-transcribe-logo-svg",
34
+ isRecording ? "ephia-transcribe-logo-svg--recording" : "",
35
+ className ?? ""
36
+ ].filter(Boolean).join(" ");
37
+ return /* @__PURE__ */ jsx(
38
+ "svg",
39
+ {
40
+ viewBox: EPHIA_LOGO_VIEWBOX,
41
+ className: svgClass,
42
+ style: { height: resolvedHeight, width: resolvedWidth, ...style },
43
+ fill: "none",
44
+ xmlns: "http://www.w3.org/2000/svg",
45
+ "aria-hidden": true,
46
+ children: variant === "color" ? /* @__PURE__ */ jsxs(Fragment, { children: [
47
+ /* @__PURE__ */ jsx("path", { d: LOGO_PURPLE_PATH, fill: EPHIA_BRAND_PURPLE }),
48
+ /* @__PURE__ */ jsx("path", { d: LOGO_TEAL_PATH, fill: EPHIA_BRAND_TEAL })
49
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
50
+ /* @__PURE__ */ jsx("path", { d: LOGO_PURPLE_PATH, fill }),
51
+ /* @__PURE__ */ jsx("path", { d: LOGO_TEAL_PATH, fill })
52
+ ] })
53
+ }
54
+ );
55
+ }
56
+
57
+ // src/ui/primitives/Button.tsx
58
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
59
+ function Button({
60
+ variant = "primary",
61
+ size = "md",
62
+ isLoading,
63
+ children,
64
+ className = "",
65
+ disabled,
66
+ ...rest
67
+ }) {
68
+ const base = "inline-flex items-center justify-center font-medium rounded-full transition focus:outline-none focus:ring-2 focus:ring-offset-1";
69
+ const variants = {
70
+ primary: "bg-[var(--ephia-primary)] text-white hover:opacity-90 focus:ring-[var(--ephia-primary)]",
71
+ danger: "bg-[var(--ephia-danger)] text-white hover:opacity-90 focus:ring-[var(--ephia-danger)]",
72
+ ghost: "bg-transparent text-neutral-700 hover:bg-neutral-100 focus:ring-neutral-300",
73
+ outline: "border border-neutral-200 bg-white text-neutral-700 hover:bg-neutral-50 focus:ring-neutral-300"
74
+ };
75
+ const sizes = {
76
+ sm: "px-3 py-1.5 text-xs",
77
+ md: "px-4 py-2 text-sm",
78
+ lg: "px-6 py-3 text-base"
79
+ };
80
+ return /* @__PURE__ */ jsxs2(
81
+ "button",
82
+ {
83
+ className: `${base} ${variants[variant]} ${sizes[size]} ${className}`,
84
+ disabled: disabled || isLoading,
85
+ ...rest,
86
+ children: [
87
+ isLoading ? /* @__PURE__ */ jsx2("span", { className: "mr-2 inline-block h-4 w-4 animate-spin rounded-full border-2 border-white/30 border-t-white" }) : null,
88
+ children
89
+ ]
90
+ }
91
+ );
92
+ }
93
+
94
+ // src/ui/primitives/Spinner.tsx
95
+ import { jsx as jsx3 } from "react/jsx-runtime";
96
+ function Spinner({ size = "md", className = "" }) {
97
+ const sizes = {
98
+ sm: "h-3 w-3 border-2",
99
+ md: "h-5 w-5 border-2",
100
+ lg: "h-8 w-8 border-[3px]"
101
+ };
102
+ return /* @__PURE__ */ jsx3(
103
+ "span",
104
+ {
105
+ className: `inline-block animate-spin rounded-full border-neutral-300 border-t-[var(--ephia-primary)] ${sizes[size]} ${className}`,
106
+ "aria-label": "Chargement"
107
+ }
108
+ );
109
+ }
110
+
111
+ // src/ui/recorder/EphiaFloatingButton.tsx
112
+ import { useEffect as useEffect3, useLayoutEffect as useLayoutEffect2, useMemo, useRef as useRef3, useState } from "react";
113
+
114
+ // src/ui/recorder/appearance.ts
115
+ var EPHIA_FLOATING_BUTTON_RADIUS_CSS = {
116
+ sm: "0.375rem",
117
+ md: "0.625rem",
118
+ lg: "1rem",
119
+ full: "9999px"
120
+ };
121
+
122
+ // src/ui/recorder/MinimalProcessingBars.tsx
123
+ import { useEffect, useRef } from "react";
124
+ import { jsx as jsx4 } from "react/jsx-runtime";
125
+ var BAR_LAYOUT = {
126
+ S: { barWidthPx: 3, gapPx: 2.5 },
127
+ M: { barWidthPx: 3.5, gapPx: 3 },
128
+ L: { barWidthPx: 4, gapPx: 3.5 }
129
+ };
130
+ var TAU = Math.PI * 2;
131
+ var BAR_MOTION = [
132
+ { base: 0.62, a1: 0.14, a2: 0.09, f1: 1.25, f2: 2.05, p1: 0, p2: 0.7 },
133
+ { base: 0.64, a1: 0.15, a2: 0.07, f1: 1.65, f2: 2.35, p1: 1.4, p2: 2.2 },
134
+ { base: 0.6, a1: 0.12, a2: 0.1, f1: 1.05, f2: 1.85, p1: 2.5, p2: 0.4 }
135
+ ];
136
+ var LERP = 0.14;
137
+ function clamp01(x) {
138
+ return Math.max(0.36, Math.min(0.9, x));
139
+ }
140
+ function targetHeight(phaseSec, spec) {
141
+ const t = phaseSec;
142
+ const v = spec.base + spec.a1 * Math.sin(t * spec.f1 * TAU + spec.p1) + spec.a2 * Math.sin(t * spec.f2 * TAU + spec.p2);
143
+ return clamp01(v);
144
+ }
145
+ function MinimalProcessingBars({
146
+ active,
147
+ size = "M",
148
+ color
149
+ }) {
150
+ const rootRef = useRef(null);
151
+ const heightsRef = useRef([0.55, 0.58, 0.54]);
152
+ const layout = BAR_LAYOUT[size] ?? BAR_LAYOUT.M;
153
+ useEffect(() => {
154
+ const root = rootRef.current;
155
+ if (!root) return;
156
+ const applyHeights = (h) => {
157
+ root.style.setProperty("--ephia-bar-0", String(h[0]));
158
+ root.style.setProperty("--ephia-bar-1", String(h[1]));
159
+ root.style.setProperty("--ephia-bar-2", String(h[2]));
160
+ };
161
+ if (!active) {
162
+ heightsRef.current = [0.52, 0.56, 0.54];
163
+ applyHeights(heightsRef.current);
164
+ return;
165
+ }
166
+ const reducedMotion = typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
167
+ if (reducedMotion) {
168
+ applyHeights([0.55, 0.58, 0.54]);
169
+ return;
170
+ }
171
+ let raf = 0;
172
+ const start = performance.now();
173
+ const tick = (now) => {
174
+ const phase = (now - start) / 1e3;
175
+ const current = heightsRef.current;
176
+ for (let i = 0; i < 3; i++) {
177
+ const target = targetHeight(phase, BAR_MOTION[i]);
178
+ current[i] += (target - current[i]) * LERP;
179
+ }
180
+ applyHeights(current);
181
+ raf = requestAnimationFrame(tick);
182
+ };
183
+ raf = requestAnimationFrame(tick);
184
+ return () => cancelAnimationFrame(raf);
185
+ }, [active]);
186
+ return /* @__PURE__ */ jsx4(
187
+ "span",
188
+ {
189
+ ref: rootRef,
190
+ className: "ephia-transcribe-minimal-bars",
191
+ style: {
192
+ ["--ephia-minimal-bar-gap"]: `${layout.gapPx}px`
193
+ },
194
+ "aria-hidden": true,
195
+ children: BAR_MOTION.map((_, i) => /* @__PURE__ */ jsx4(
196
+ "span",
197
+ {
198
+ className: "ephia-transcribe-minimal-bar",
199
+ style: {
200
+ width: layout.barWidthPx,
201
+ backgroundColor: color,
202
+ ["--ephia-bar-scale"]: `var(--ephia-bar-${i}, 0.5)`
203
+ }
204
+ },
205
+ i
206
+ ))
207
+ }
208
+ );
209
+ }
210
+
211
+ // src/ui/recorder/StandardIntensityVisualizer.tsx
212
+ import { useEffect as useEffect2, useLayoutEffect, useReducer, useRef as useRef2 } from "react";
213
+ import { jsx as jsx5 } from "react/jsx-runtime";
214
+ var INTENSITY_SAMPLE_MS = 300;
215
+ var BAR_WIDTH_PX = 3;
216
+ var BAR_GAP_PX = 2;
217
+ var MIN_BAR_HEIGHT_RATIO = 0.1;
218
+ function clamp012(value) {
219
+ return Math.max(0, Math.min(1, value));
220
+ }
221
+ function barHeightRatio(level) {
222
+ const v = clamp012(level);
223
+ return MIN_BAR_HEIGHT_RATIO + v * (1 - MIN_BAR_HEIGHT_RATIO);
224
+ }
225
+ function barStepPx() {
226
+ return BAR_WIDTH_PX + BAR_GAP_PX;
227
+ }
228
+ function scrollSpeedPxPerSec() {
229
+ return barStepPx() / (INTENSITY_SAMPLE_MS / 1e3);
230
+ }
231
+ function StandardIntensityVisualizer({ enabled, level }) {
232
+ const rectRef = useRef2(null);
233
+ const trackRef = useRef2(null);
234
+ const bucketRef = useRef2({ sum: 0, count: 0 });
235
+ const scrollOffsetRef = useRef2(0);
236
+ const barsRef = useRef2([]);
237
+ const maxBarsRef = useRef2(48);
238
+ const [barRevision, bumpBars] = useReducer((n) => n + 1, 0);
239
+ useEffect2(() => {
240
+ if (!enabled) return;
241
+ const v = clamp012(level);
242
+ bucketRef.current.sum += v;
243
+ bucketRef.current.count += 1;
244
+ }, [enabled, level]);
245
+ useLayoutEffect(() => {
246
+ const rect = rectRef.current;
247
+ if (!rect) return;
248
+ const updateMax = () => {
249
+ const w = rect.clientWidth;
250
+ if (w > 0) {
251
+ maxBarsRef.current = Math.max(12, Math.ceil(w / barStepPx()) + 4);
252
+ }
253
+ };
254
+ updateMax();
255
+ const ro = new ResizeObserver(updateMax);
256
+ ro.observe(rect);
257
+ return () => ro.disconnect();
258
+ }, [enabled]);
259
+ useEffect2(() => {
260
+ if (!enabled) {
261
+ barsRef.current = [];
262
+ bucketRef.current = { sum: 0, count: 0 };
263
+ scrollOffsetRef.current = 0;
264
+ if (trackRef.current) trackRef.current.style.transform = "translateX(0)";
265
+ return;
266
+ }
267
+ let rafId = 0;
268
+ let lastTs = performance.now();
269
+ const consumeBucket = () => {
270
+ const { sum, count } = bucketRef.current;
271
+ bucketRef.current = { sum: 0, count: 0 };
272
+ return count > 0 ? sum / count : 0;
273
+ };
274
+ const pushBar = () => {
275
+ const avg = consumeBucket();
276
+ const next = [...barsRef.current, avg];
277
+ const max = maxBarsRef.current;
278
+ barsRef.current = next.length > max ? next.slice(-max) : next;
279
+ bumpBars();
280
+ };
281
+ const tick = (now) => {
282
+ const track = trackRef.current;
283
+ if (!track) {
284
+ rafId = requestAnimationFrame(tick);
285
+ return;
286
+ }
287
+ const dt = Math.min(0.05, (now - lastTs) / 1e3);
288
+ lastTs = now;
289
+ const step = barStepPx();
290
+ scrollOffsetRef.current += scrollSpeedPxPerSec() * dt;
291
+ while (scrollOffsetRef.current >= step) {
292
+ scrollOffsetRef.current -= step;
293
+ pushBar();
294
+ }
295
+ track.style.transform = `translate3d(${-scrollOffsetRef.current}px, 0, 0)`;
296
+ rafId = requestAnimationFrame(tick);
297
+ };
298
+ rafId = requestAnimationFrame(tick);
299
+ return () => {
300
+ cancelAnimationFrame(rafId);
301
+ barsRef.current = [];
302
+ bucketRef.current = { sum: 0, count: 0 };
303
+ scrollOffsetRef.current = 0;
304
+ if (trackRef.current) trackRef.current.style.transform = "translateX(0)";
305
+ };
306
+ }, [enabled]);
307
+ if (!enabled) return null;
308
+ const bars = barsRef.current;
309
+ return /* @__PURE__ */ jsx5("span", { className: "ephia-transcribe-standard-placeholder", "data-ephia-ui": "standard-intensity", "aria-hidden": true, children: /* @__PURE__ */ jsx5("span", { ref: rectRef, className: "ephia-transcribe-standard-placeholder__rect", children: /* @__PURE__ */ jsx5("span", { className: "ephia-transcribe-standard-placeholder__viewport", children: /* @__PURE__ */ jsx5("span", { ref: trackRef, className: "ephia-transcribe-standard-placeholder__track", children: bars.map((barLevel, index) => /* @__PURE__ */ jsx5(
310
+ "span",
311
+ {
312
+ className: "ephia-transcribe-standard-placeholder__history-bar",
313
+ style: { height: `${barHeightRatio(barLevel) * 100}%` }
314
+ },
315
+ `${barRevision}-${index}`
316
+ )) }) }) }) });
317
+ }
318
+
319
+ // src/ui/recorder/EphiaFloatingButton.tsx
320
+ import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
321
+ var EPHIA_APP_URL = "https://ephia.app";
322
+ function EphiaExternalLinkIcon() {
323
+ return /* @__PURE__ */ jsxs3(
324
+ "svg",
325
+ {
326
+ className: "ephia-transcribe-poweredby-icon",
327
+ viewBox: "0 0 24 24",
328
+ "aria-hidden": true,
329
+ focusable: "false",
330
+ children: [
331
+ /* @__PURE__ */ jsx6("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }),
332
+ /* @__PURE__ */ jsx6("path", { d: "M15 3h6v6" }),
333
+ /* @__PURE__ */ jsx6("path", { d: "M10 14 21 3" })
334
+ ]
335
+ }
336
+ );
337
+ }
338
+ var SIZE_CONFIG = {
339
+ S: { logoHeightPx: 24 },
340
+ M: { logoHeightPx: 32 },
341
+ L: { logoHeightPx: 44 }
342
+ };
343
+ var LOGO_SCALE_WHEN_RADIUS_FULL = 0.92;
344
+ var POSITION_STYLE = {
345
+ "bottom-right": { bottom: 24, right: 24 },
346
+ "bottom-left": { bottom: 24, left: 24 },
347
+ "bottom-center": { bottom: 24, left: "50%", transform: "translateX(-50%)" },
348
+ "top-right": { top: 24, right: 24 },
349
+ "top-left": { top: 24, left: 24 },
350
+ "top-center": { top: 24, left: "50%", transform: "translateX(-50%)" }
351
+ };
352
+ function EphiaFloatingButtonInner({
353
+ position,
354
+ theme,
355
+ size,
356
+ variant,
357
+ borderRadius,
358
+ interactionMode,
359
+ colors,
360
+ className,
361
+ style,
362
+ onError,
363
+ onStatusChange
364
+ }) {
365
+ const { status, isRecording, isProcessing, start, stop, error, activeTargetId } = useEphia();
366
+ const audio = useEphiaAudioLevel();
367
+ const isArming = isProcessing;
368
+ const voiceLevel = Math.min(1, Math.max(0, audio?.level ?? audio?.rms ?? 0));
369
+ const isLiveSession = isRecording || !!audio?.localAudioPublished && !!audio?.micReady;
370
+ const lastErrorRef = useRef3(null);
371
+ useEffect3(() => {
372
+ if (error && (lastErrorRef.current?.code !== error.code || lastErrorRef.current?.message !== error.message)) {
373
+ lastErrorRef.current = error;
374
+ onError?.(error);
375
+ }
376
+ }, [error, onError]);
377
+ const lastStatusRef = useRef3(status);
378
+ useEffect3(() => {
379
+ if (status !== lastStatusRef.current) {
380
+ lastStatusRef.current = status;
381
+ onStatusChange?.(status);
382
+ }
383
+ }, [status, onStatusChange]);
384
+ const statusAnnouncement = isLiveSession ? "Dict\xE9e en cours" : status === "processing" ? "Traitement" : status === "error" ? "Erreur de dict\xE9e" : "";
385
+ const isLight = theme === "light";
386
+ const isValidColor = (c) => Boolean(c?.trim());
387
+ const hasCustomColors = isValidColor(colors?.primary) && isValidColor(colors?.secondary);
388
+ const swapForLight = hasCustomColors && isLight;
389
+ const effectivePrimary = hasCustomColors ? swapForLight ? colors.secondary.trim() : colors.primary.trim() : isLight ? "#ffffff" : "#262626";
390
+ const effectiveSecondary = hasCustomColors ? swapForLight ? colors.primary.trim() : colors.secondary.trim() : null;
391
+ const safeSize = size && size in SIZE_CONFIG ? size : "M";
392
+ const { logoHeightPx: baseLogoHeightPx } = SIZE_CONFIG[safeSize];
393
+ const logoHeightPx = borderRadius === "full" ? Math.round(baseLogoHeightPx * LOGO_SCALE_WHEN_RADIUS_FULL) : baseLogoHeightPx;
394
+ const logoWidthPx = logoWidthFromHeight(logoHeightPx);
395
+ const isStandardVariant = variant === "standard";
396
+ const showTimer = isStandardVariant && isRecording;
397
+ const showProcessing = isStandardVariant && isArming && !isRecording;
398
+ const showStandardPrompt = isStandardVariant && !isRecording && !isArming;
399
+ const [sessionElapsedMs, setSessionElapsedMs] = useState(0);
400
+ const sessionStartRef = useRef3(null);
401
+ const timerMeasureRef = useRef3(null);
402
+ const [logoSlotWidthPx, setLogoSlotWidthPx] = useState(logoHeightPx);
403
+ useEffect3(() => {
404
+ if (showTimer) {
405
+ sessionStartRef.current = Date.now();
406
+ setSessionElapsedMs(0);
407
+ const id = setInterval(() => {
408
+ if (sessionStartRef.current != null) setSessionElapsedMs(Date.now() - sessionStartRef.current);
409
+ }, 200);
410
+ return () => clearInterval(id);
411
+ }
412
+ sessionStartRef.current = null;
413
+ }, [showTimer]);
414
+ const timerLabel = useMemo(() => {
415
+ const s = Math.max(0, Math.floor(sessionElapsedMs / 1e3));
416
+ return `${Math.floor(s / 60).toString().padStart(2, "0")}:${(s % 60).toString().padStart(2, "0")}`;
417
+ }, [sessionElapsedMs]);
418
+ useLayoutEffect2(() => {
419
+ if (!showTimer) {
420
+ setLogoSlotWidthPx(logoHeightPx);
421
+ return;
422
+ }
423
+ const el = timerMeasureRef.current;
424
+ const measured = el ? Math.ceil(el.getBoundingClientRect().width) : 0;
425
+ setLogoSlotWidthPx(Math.max(logoHeightPx, measured + 12));
426
+ }, [showTimer, timerLabel, logoHeightPx]);
427
+ const logoVariant = hasCustomColors ? "mono" : "color";
428
+ const waveformColor = hasCustomColors ? effectivePrimary : EPHIA_BRAND_PURPLE;
429
+ const radiusCss = EPHIA_FLOATING_BUTTON_RADIUS_CSS[borderRadius] ?? EPHIA_FLOATING_BUTTON_RADIUS_CSS.md;
430
+ const [reducedMotion] = useState(
431
+ () => typeof window !== "undefined" && window.matchMedia("(prefers-reduced-motion: reduce)").matches
432
+ );
433
+ return /* @__PURE__ */ jsxs3(
434
+ "div",
435
+ {
436
+ className: "ephia-transcribe-floating-root",
437
+ "data-ephia-control": "true",
438
+ style: { ...POSITION_STYLE[position], ...style },
439
+ children: [
440
+ /* @__PURE__ */ jsx6(
441
+ "div",
442
+ {
443
+ role: "status",
444
+ "aria-live": "polite",
445
+ "aria-atomic": "true",
446
+ style: { position: "absolute", width: 1, height: 1, overflow: "hidden", clip: "rect(0,0,0,0)", whiteSpace: "nowrap" },
447
+ children: statusAnnouncement
448
+ }
449
+ ),
450
+ /* @__PURE__ */ jsxs3(
451
+ "div",
452
+ {
453
+ className: `ephia-transcribe-root ephia-transcribe-root--${theme} ephia-transcribe-size--${size} ephia-transcribe-radius--${borderRadius}${className ? ` ${className}` : ""}`,
454
+ style: {
455
+ ["--ephia-transcribe-radius"]: radiusCss,
456
+ ...hasCustomColors ? {
457
+ backgroundColor: effectiveSecondary ?? void 0,
458
+ ["--ephia-transcribe-ink"]: effectivePrimary
459
+ } : {}
460
+ },
461
+ children: [
462
+ /* @__PURE__ */ jsxs3("div", { className: `ephia-transcribe-poweredby ephia-transcribe-poweredby--${theme}`, children: [
463
+ /* @__PURE__ */ jsx6(
464
+ "a",
465
+ {
466
+ href: EPHIA_APP_URL,
467
+ target: "_blank",
468
+ rel: "noopener noreferrer",
469
+ className: "ephia-transcribe-poweredby-btn",
470
+ "aria-label": "En savoir plus sur Ephia \u2014 ouvre ephia.app dans un nouvel onglet",
471
+ onClick: (e) => e.stopPropagation(),
472
+ onPointerDown: (e) => e.stopPropagation(),
473
+ children: /* @__PURE__ */ jsx6(EphiaExternalLinkIcon, {})
474
+ }
475
+ ),
476
+ /* @__PURE__ */ jsx6("div", { className: "ephia-transcribe-poweredby-tooltip", children: "ephia.app" })
477
+ ] }),
478
+ isLiveSession && !reducedMotion && /* @__PURE__ */ jsx6(
479
+ "div",
480
+ {
481
+ className: "ephia-transcribe-ring",
482
+ style: hasCustomColors ? {
483
+ boxShadow: `0 0 20px color-mix(in srgb, ${effectivePrimary} 55%, transparent)`
484
+ } : {
485
+ boxShadow: "0 0 24px rgba(114, 58, 222, 0.55), 0 0 14px rgba(0, 235, 208, 0.45)"
486
+ }
487
+ }
488
+ ),
489
+ /* @__PURE__ */ jsx6(
490
+ "button",
491
+ {
492
+ type: "button",
493
+ ...interactionMode === "push-to-talk" ? {
494
+ onPointerDown: (e) => {
495
+ e.preventDefault();
496
+ if (typeof window !== "undefined") {
497
+ window.__ephia_record_click_ts = Date.now();
498
+ window.dispatchEvent(
499
+ new CustomEvent("ephia:sdk-debug", {
500
+ detail: {
501
+ type: "sdk.record.click",
502
+ sessionId: null,
503
+ payload: { message: "Push-to-talk press", ts: Date.now() }
504
+ }
505
+ })
506
+ );
507
+ }
508
+ if (!isLiveSession && !isArming) void start(activeTargetId ?? void 0, { startupBufferMs: 5e3 });
509
+ },
510
+ onPointerUp: () => {
511
+ if (isLiveSession) void stop();
512
+ },
513
+ onPointerLeave: () => {
514
+ if (isLiveSession) void stop();
515
+ }
516
+ } : {
517
+ onClick: () => {
518
+ if (isArming) return;
519
+ if (typeof window !== "undefined") {
520
+ window.__ephia_record_click_ts = Date.now();
521
+ window.dispatchEvent(
522
+ new CustomEvent("ephia:sdk-debug", {
523
+ detail: {
524
+ type: "sdk.record.click",
525
+ sessionId: null,
526
+ payload: { message: "Clic sur Record", ts: Date.now() }
527
+ }
528
+ })
529
+ );
530
+ }
531
+ if (isLiveSession) {
532
+ void stop();
533
+ } else {
534
+ void start(activeTargetId ?? void 0, { startupBufferMs: 5e3 });
535
+ }
536
+ }
537
+ },
538
+ disabled: isArming,
539
+ className: "ephia-transcribe-btn",
540
+ "aria-pressed": isLiveSession,
541
+ "aria-busy": isArming,
542
+ "aria-label": isLiveSession ? "Arr\xEAter la dict\xE9e" : isArming ? "Traitement en cours\u2026" : "D\xE9marrer la dict\xE9e",
543
+ children: /* @__PURE__ */ jsxs3(
544
+ "span",
545
+ {
546
+ className: `ephia-transcribe-btn-inner${isStandardVariant ? " ephia-transcribe-btn-inner--standard" : ""}${showProcessing ? " ephia-transcribe-btn-inner--processing" : ""}`,
547
+ children: [
548
+ variant === "minimal" ? /* @__PURE__ */ jsxs3(
549
+ "span",
550
+ {
551
+ className: `ephia-transcribe-minimal-swap${isRecording || isArming ? " ephia-transcribe-minimal-swap--recording" : ""}`,
552
+ style: { width: logoWidthPx, height: logoHeightPx },
553
+ children: [
554
+ /* @__PURE__ */ jsx6("span", { className: "ephia-transcribe-minimal-swap-layer ephia-transcribe-minimal-swap-layer--logo", "aria-hidden": true, children: /* @__PURE__ */ jsx6("span", { className: "ephia-transcribe-logo-clip ephia-transcribe-logo-slot", style: { width: logoWidthPx, height: logoHeightPx }, children: /* @__PURE__ */ jsx6("span", { className: "ephia-transcribe-logo-slot-layer ephia-transcribe-logo-slot-layer--logo", "aria-hidden": true, children: /* @__PURE__ */ jsx6(
555
+ EphiaLogo,
556
+ {
557
+ height: logoHeightPx,
558
+ width: logoWidthPx,
559
+ variant: logoVariant,
560
+ fill: effectivePrimary,
561
+ isRecording: isLiveSession
562
+ }
563
+ ) }) }) }),
564
+ /* @__PURE__ */ jsx6("span", { className: "ephia-transcribe-minimal-swap-layer ephia-transcribe-minimal-swap-layer--activity", "aria-hidden": true, children: /* @__PURE__ */ jsx6(
565
+ MinimalProcessingBars,
566
+ {
567
+ active: isRecording || isArming,
568
+ size: safeSize,
569
+ color: waveformColor
570
+ }
571
+ ) })
572
+ ]
573
+ }
574
+ ) : (
575
+ // standard variant
576
+ /* @__PURE__ */ jsxs3(
577
+ "span",
578
+ {
579
+ className: `ephia-transcribe-logo-clip ephia-transcribe-logo-slot${showTimer ? " ephia-transcribe-logo-slot--recording" : ""}`,
580
+ style: { width: logoSlotWidthPx, height: logoHeightPx },
581
+ children: [
582
+ /* @__PURE__ */ jsx6("span", { className: "ephia-transcribe-logo-slot-layer ephia-transcribe-logo-slot-layer--logo", "aria-hidden": true, children: /* @__PURE__ */ jsx6(
583
+ EphiaLogo,
584
+ {
585
+ height: logoHeightPx,
586
+ width: logoWidthPx,
587
+ variant: logoVariant,
588
+ fill: effectivePrimary,
589
+ isRecording: isLiveSession
590
+ }
591
+ ) }),
592
+ showTimer && /* @__PURE__ */ jsxs3(Fragment2, { children: [
593
+ /* @__PURE__ */ jsx6("span", { className: "ephia-transcribe-logo-slot-layer ephia-transcribe-logo-slot-layer--timer", "aria-hidden": true, children: /* @__PURE__ */ jsx6("span", { className: "ephia-transcribe-session-timer", children: timerLabel }) }),
594
+ /* @__PURE__ */ jsx6("span", { className: "ephia-transcribe-session-timer ephia-transcribe-session-timer--measure", ref: timerMeasureRef, children: timerLabel })
595
+ ] })
596
+ ]
597
+ }
598
+ )
599
+ ),
600
+ isStandardVariant && /* @__PURE__ */ jsxs3(
601
+ "span",
602
+ {
603
+ className: `ephia-transcribe-standard-right-swap${showStandardPrompt ? " ephia-transcribe-standard-right-swap--prompt" : showProcessing ? " ephia-transcribe-standard-right-swap--processing" : " ephia-transcribe-standard-right-swap--waveform"}`,
604
+ "aria-hidden": true,
605
+ children: [
606
+ /* @__PURE__ */ jsx6("span", { className: "ephia-transcribe-standard-right-layer ephia-transcribe-standard-right-layer--prompt", children: "Commencer \xE0 dicter" }),
607
+ /* @__PURE__ */ jsx6("span", { className: "ephia-transcribe-standard-right-layer ephia-transcribe-standard-right-layer--processing", children: "Traitement\u2026" }),
608
+ !showProcessing ? /* @__PURE__ */ jsx6("span", { className: "ephia-transcribe-standard-right-layer ephia-transcribe-standard-right-layer--waveform", children: /* @__PURE__ */ jsx6(
609
+ StandardIntensityVisualizer,
610
+ {
611
+ enabled: isRecording,
612
+ level: voiceLevel
613
+ }
614
+ ) }) : null
615
+ ]
616
+ }
617
+ )
618
+ ]
619
+ }
620
+ )
621
+ }
622
+ )
623
+ ]
624
+ }
625
+ )
626
+ ]
627
+ }
628
+ );
629
+ }
630
+ function EphiaFloatingButton({
631
+ apiUrl,
632
+ apiKey,
633
+ bearerToken,
634
+ clientType,
635
+ transport,
636
+ position = "bottom-center",
637
+ theme = "light",
638
+ size = "M",
639
+ variant = "standard",
640
+ borderRadius = "lg",
641
+ interactionMode = "toggle",
642
+ colors,
643
+ className,
644
+ style,
645
+ sessionOptions,
646
+ onError,
647
+ onStatusChange
648
+ }) {
649
+ const ctx = useOptionalEphiaContext();
650
+ const safeRadius = borderRadius && borderRadius in EPHIA_FLOATING_BUTTON_RADIUS_CSS ? borderRadius : "lg";
651
+ const innerProps = useMemo(() => ({
652
+ position,
653
+ theme,
654
+ size,
655
+ variant,
656
+ borderRadius: safeRadius,
657
+ interactionMode,
658
+ colors,
659
+ className,
660
+ style,
661
+ onError,
662
+ onStatusChange
663
+ }), [position, theme, size, variant, safeRadius, interactionMode, colors, className, style, onError, onStatusChange]);
664
+ if (ctx) {
665
+ return /* @__PURE__ */ jsx6(EphiaFloatingButtonInner, { ...innerProps });
666
+ }
667
+ return /* @__PURE__ */ jsx6(
668
+ EphiaProvider,
669
+ {
670
+ apiUrl,
671
+ apiKey,
672
+ bearerToken,
673
+ clientType,
674
+ transport,
675
+ options: {
676
+ language: sessionOptions?.language,
677
+ sessionOptions
678
+ },
679
+ children: /* @__PURE__ */ jsx6(EphiaFloatingButtonInner, { ...innerProps })
680
+ }
681
+ );
682
+ }
683
+
684
+ export {
685
+ EPHIA_LOGO_VIEWBOX,
686
+ EPHIA_LOGO_ASPECT,
687
+ EPHIA_BRAND_PURPLE,
688
+ EPHIA_BRAND_TEAL,
689
+ logoWidthFromHeight,
690
+ EphiaLogo,
691
+ Button,
692
+ Spinner,
693
+ EphiaFloatingButton
694
+ };
695
+ //# sourceMappingURL=chunk-YWZUMUYE.js.map