@mieweb/ui 0.11.0-dev.1 → 0.11.0-dev.11

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 (172) hide show
  1. package/dist/ag-grid.cjs +11 -2
  2. package/dist/ag-grid.cjs.map +1 -1
  3. package/dist/ag-grid.d.cts +8 -0
  4. package/dist/ag-grid.d.ts +8 -0
  5. package/dist/ag-grid.js +11 -2
  6. package/dist/ag-grid.js.map +1 -1
  7. package/dist/brands/index.cjs +12 -12
  8. package/dist/brands/index.js +3 -3
  9. package/dist/{chunk-U2RS574O.cjs → chunk-2GBVJHWN.cjs} +120 -63
  10. package/dist/chunk-2GBVJHWN.cjs.map +1 -0
  11. package/dist/{chunk-7UTBDFFL.cjs → chunk-2S76TRBJ.cjs} +4 -4
  12. package/dist/{chunk-7UTBDFFL.cjs.map → chunk-2S76TRBJ.cjs.map} +1 -1
  13. package/dist/{chunk-IJYTASQQ.cjs → chunk-3AD4HFYI.cjs} +15 -7
  14. package/dist/chunk-3AD4HFYI.cjs.map +1 -0
  15. package/dist/{chunk-CFI3TQMA.cjs → chunk-56C7K4MV.cjs} +9 -4
  16. package/dist/chunk-56C7K4MV.cjs.map +1 -0
  17. package/dist/{chunk-TNUL4LGG.js → chunk-5ILCNY74.js} +15 -7
  18. package/dist/chunk-5ILCNY74.js.map +1 -0
  19. package/dist/{chunk-AFDW64EF.cjs → chunk-5K7PRPSV.cjs} +30 -2
  20. package/dist/chunk-5K7PRPSV.cjs.map +1 -0
  21. package/dist/{chunk-QQCHM7BZ.cjs → chunk-5VA2HJ5B.cjs} +6 -6
  22. package/dist/{chunk-QQCHM7BZ.cjs.map → chunk-5VA2HJ5B.cjs.map} +1 -1
  23. package/dist/{chunk-PJ6CC53R.cjs → chunk-AKMTPCLC.cjs} +13 -8
  24. package/dist/chunk-AKMTPCLC.cjs.map +1 -0
  25. package/dist/{chunk-OODVC2UD.cjs → chunk-AWSSWNJY.cjs} +2 -2
  26. package/dist/{chunk-OODVC2UD.cjs.map → chunk-AWSSWNJY.cjs.map} +1 -1
  27. package/dist/chunk-BFVYM6IT.cjs +345 -0
  28. package/dist/chunk-BFVYM6IT.cjs.map +1 -0
  29. package/dist/{chunk-VVDE4CHU.js → chunk-C4GEPUE7.js} +13 -8
  30. package/dist/chunk-C4GEPUE7.js.map +1 -0
  31. package/dist/{chunk-TJ4GWQPM.js → chunk-DAAJ3B2T.js} +121 -65
  32. package/dist/chunk-DAAJ3B2T.js.map +1 -0
  33. package/dist/{chunk-QJ2L5RU6.js → chunk-DSQCYX7L.js} +2 -2
  34. package/dist/{chunk-QJ2L5RU6.js.map → chunk-DSQCYX7L.js.map} +1 -1
  35. package/dist/{chunk-NUB5HRKS.js → chunk-DT3X3RBM.js} +3 -3
  36. package/dist/{chunk-NUB5HRKS.js.map → chunk-DT3X3RBM.js.map} +1 -1
  37. package/dist/{chunk-AG5EKCE4.js → chunk-EBQG3NGT.js} +30 -2
  38. package/dist/chunk-EBQG3NGT.js.map +1 -0
  39. package/dist/{chunk-MYAU2ZUC.cjs → chunk-GDKOYVX3.cjs} +14 -10
  40. package/dist/chunk-GDKOYVX3.cjs.map +1 -0
  41. package/dist/{chunk-JTSKPDPH.cjs → chunk-HIYQ3M5V.cjs} +4 -3
  42. package/dist/chunk-HIYQ3M5V.cjs.map +1 -0
  43. package/dist/{chunk-7IBZA7G6.js → chunk-I6Y2KLTZ.js} +5 -2
  44. package/dist/chunk-I6Y2KLTZ.js.map +1 -0
  45. package/dist/chunk-IZY4CMOO.js +715 -0
  46. package/dist/chunk-IZY4CMOO.js.map +1 -0
  47. package/dist/{chunk-753ENNB6.js → chunk-J3QEMZCH.js} +2 -2
  48. package/dist/{chunk-753ENNB6.js.map → chunk-J3QEMZCH.js.map} +1 -1
  49. package/dist/{chunk-S2JZL4JC.js → chunk-JM4YFLO4.js} +22 -15
  50. package/dist/chunk-JM4YFLO4.js.map +1 -0
  51. package/dist/{chunk-QX6AAVDE.cjs → chunk-L4APW65W.cjs} +15 -6
  52. package/dist/chunk-L4APW65W.cjs.map +1 -0
  53. package/dist/{chunk-OHKO5THF.cjs → chunk-MGFRGPWI.cjs} +3 -2
  54. package/dist/chunk-MGFRGPWI.cjs.map +1 -0
  55. package/dist/{chunk-RM2HPQIC.js → chunk-MQ5WJ3NO.js} +4 -4
  56. package/dist/chunk-MQ5WJ3NO.js.map +1 -0
  57. package/dist/{chunk-VNWJTCBQ.js → chunk-MQOYDQTF.js} +4 -3
  58. package/dist/chunk-MQOYDQTF.js.map +1 -0
  59. package/dist/chunk-MZA2LDS4.js +321 -0
  60. package/dist/chunk-MZA2LDS4.js.map +1 -0
  61. package/dist/{chunk-VYNFJVRZ.js → chunk-N6XBE47W.js} +3 -3
  62. package/dist/{chunk-VYNFJVRZ.js.map → chunk-N6XBE47W.js.map} +1 -1
  63. package/dist/{chunk-T5BBZQ66.js → chunk-OTIKWEFZ.js} +9 -4
  64. package/dist/chunk-OTIKWEFZ.js.map +1 -0
  65. package/dist/{chunk-YZCM7CXK.js → chunk-OZKJYLN6.js} +3 -3
  66. package/dist/{chunk-YZCM7CXK.js.map → chunk-OZKJYLN6.js.map} +1 -1
  67. package/dist/{chunk-ZSGEGISB.cjs → chunk-PHUTJKHL.cjs} +5 -2
  68. package/dist/chunk-PHUTJKHL.cjs.map +1 -0
  69. package/dist/{chunk-FMEA6WAY.cjs → chunk-Q6QLGCL7.cjs} +9 -9
  70. package/dist/{chunk-FMEA6WAY.cjs.map → chunk-Q6QLGCL7.cjs.map} +1 -1
  71. package/dist/{chunk-XOIIUO6O.js → chunk-QDNHN7R2.js} +3 -2
  72. package/dist/chunk-QDNHN7R2.js.map +1 -0
  73. package/dist/{chunk-XRVMYT5G.cjs → chunk-QKW2QCGI.cjs} +5 -5
  74. package/dist/chunk-QKW2QCGI.cjs.map +1 -0
  75. package/dist/{chunk-NAH65KPK.cjs → chunk-TOJ56HKQ.cjs} +2 -2
  76. package/dist/{chunk-NAH65KPK.cjs.map → chunk-TOJ56HKQ.cjs.map} +1 -1
  77. package/dist/chunk-TRZLN32I.cjs +740 -0
  78. package/dist/chunk-TRZLN32I.cjs.map +1 -0
  79. package/dist/{chunk-O6XDA3SI.js → chunk-UY2EZYIC.js} +15 -6
  80. package/dist/chunk-UY2EZYIC.js.map +1 -0
  81. package/dist/{chunk-2BPIVWAK.js → chunk-V5VPECJI.js} +14 -10
  82. package/dist/chunk-V5VPECJI.js.map +1 -0
  83. package/dist/{chunk-O6BJMVGT.cjs → chunk-XZNHS7YQ.cjs} +24 -17
  84. package/dist/chunk-XZNHS7YQ.cjs.map +1 -0
  85. package/dist/components/AudioPlayer/index.cjs +7 -6
  86. package/dist/components/AudioPlayer/index.js +2 -1
  87. package/dist/components/CollabStatus/index.cjs +5 -4
  88. package/dist/components/CollabStatus/index.js +2 -1
  89. package/dist/components/CountryCodeDropdown/index.cjs +4 -4
  90. package/dist/components/CountryCodeDropdown/index.js +1 -1
  91. package/dist/components/DateInput/index.cjs +2 -2
  92. package/dist/components/DateInput/index.js +1 -1
  93. package/dist/components/DictationButton/index.cjs +23 -0
  94. package/dist/components/DictationButton/index.cjs.map +1 -0
  95. package/dist/components/DictationButton/index.d.cts +78 -0
  96. package/dist/components/DictationButton/index.d.ts +78 -0
  97. package/dist/components/DictationButton/index.js +6 -0
  98. package/dist/components/DictationButton/index.js.map +1 -0
  99. package/dist/components/Markdown/index.cjs +10 -10
  100. package/dist/components/Markdown/index.js +2 -2
  101. package/dist/components/MediaEditor/index.cjs +8 -7
  102. package/dist/components/MediaEditor/index.js +3 -2
  103. package/dist/components/PhoneInput/index.cjs +3 -3
  104. package/dist/components/PhoneInput/index.js +1 -1
  105. package/dist/components/RecordButton/index.cjs +4 -4
  106. package/dist/components/RecordButton/index.js +1 -1
  107. package/dist/components/Slider/index.cjs +6 -5
  108. package/dist/components/Slider/index.js +2 -1
  109. package/dist/components/SliderCalculator/index.cjs +5 -4
  110. package/dist/components/SliderCalculator/index.js +3 -2
  111. package/dist/components/SuperChat/index.cjs +14 -14
  112. package/dist/components/SuperChat/index.cjs.map +1 -1
  113. package/dist/components/SuperChat/index.d.cts +10 -6
  114. package/dist/components/SuperChat/index.d.ts +10 -6
  115. package/dist/components/SuperChat/index.js +4 -4
  116. package/dist/components/SuperChat/index.js.map +1 -1
  117. package/dist/components/SuperChat/plugins/index.cjs +3 -3
  118. package/dist/components/SuperChat/plugins/index.d.cts +2 -2
  119. package/dist/components/SuperChat/plugins/index.d.ts +2 -2
  120. package/dist/components/SuperChat/plugins/index.js +2 -2
  121. package/dist/components/Table/index.cjs +9 -9
  122. package/dist/components/Table/index.d.cts +17 -1
  123. package/dist/components/Table/index.d.ts +17 -1
  124. package/dist/components/Table/index.js +1 -1
  125. package/dist/deck.cjs +1 -1
  126. package/dist/deck.cjs.map +1 -1
  127. package/dist/deck.js +1 -1
  128. package/dist/deck.js.map +1 -1
  129. package/dist/esheet.cjs +5 -5
  130. package/dist/esheet.js +2 -2
  131. package/dist/index.cjs +600 -1134
  132. package/dist/index.cjs.map +1 -1
  133. package/dist/index.d.cts +154 -14
  134. package/dist/index.d.ts +154 -14
  135. package/dist/index.js +230 -834
  136. package/dist/index.js.map +1 -1
  137. package/dist/kerebron.css +42 -0
  138. package/dist/styles/init.css +39 -0
  139. package/dist/styles.css +1 -1
  140. package/dist/tailwind-preset.cjs +4 -4
  141. package/dist/tailwind-preset.js +1 -1
  142. package/dist/{types-Cx1FHLq2.d.ts → types-DSWbrVkM.d.cts} +1 -1
  143. package/dist/{types-Cx1FHLq2.d.cts → types-DSWbrVkM.d.ts} +1 -1
  144. package/dist/whisperTranscribe-AV752TZI.cjs +81 -0
  145. package/dist/whisperTranscribe-AV752TZI.cjs.map +1 -0
  146. package/dist/whisperTranscribe-UBNUWXUQ.js +4 -0
  147. package/dist/whisperTranscribe-UBNUWXUQ.js.map +1 -0
  148. package/package.json +1 -1
  149. package/dist/chunk-2BPIVWAK.js.map +0 -1
  150. package/dist/chunk-7IBZA7G6.js.map +0 -1
  151. package/dist/chunk-AFDW64EF.cjs.map +0 -1
  152. package/dist/chunk-AG5EKCE4.js.map +0 -1
  153. package/dist/chunk-CFI3TQMA.cjs.map +0 -1
  154. package/dist/chunk-IJYTASQQ.cjs.map +0 -1
  155. package/dist/chunk-JTSKPDPH.cjs.map +0 -1
  156. package/dist/chunk-MYAU2ZUC.cjs.map +0 -1
  157. package/dist/chunk-O6BJMVGT.cjs.map +0 -1
  158. package/dist/chunk-O6XDA3SI.js.map +0 -1
  159. package/dist/chunk-OHKO5THF.cjs.map +0 -1
  160. package/dist/chunk-PJ6CC53R.cjs.map +0 -1
  161. package/dist/chunk-QX6AAVDE.cjs.map +0 -1
  162. package/dist/chunk-RM2HPQIC.js.map +0 -1
  163. package/dist/chunk-S2JZL4JC.js.map +0 -1
  164. package/dist/chunk-T5BBZQ66.js.map +0 -1
  165. package/dist/chunk-TJ4GWQPM.js.map +0 -1
  166. package/dist/chunk-TNUL4LGG.js.map +0 -1
  167. package/dist/chunk-U2RS574O.cjs.map +0 -1
  168. package/dist/chunk-VNWJTCBQ.js.map +0 -1
  169. package/dist/chunk-VVDE4CHU.js.map +0 -1
  170. package/dist/chunk-XOIIUO6O.js.map +0 -1
  171. package/dist/chunk-XRVMYT5G.cjs.map +0 -1
  172. package/dist/chunk-ZSGEGISB.cjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/AI/modelCache.ts","../src/components/AI/ozwellChat.ts","../src/components/AI/whisperTranscribe.ts"],"names":["o"],"mappings":"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","file":"chunk-TRZLN32I.cjs","sourcesContent":["/**\n * Registers the model-cache service worker. In this repo the SW file lives at\n * `.storybook/public/ozwell-model-sw.js` and is served at `/ozwell-model-sw.js` by Storybook only — a\n * consumer that wants caching outside Storybook must serve/copy the SW at the `swUrl` path passed below.\n *\n * Why: cache the wake-word + speaker-verification model assets across app opens so a returning user\n * loads them from disk instead of re-downloading. The service worker fetches the full file itself and\n * serves a complete copy on later opens.\n * NOTE: Whisper turbo caching is handled SEPARATELY by transformers.js (it streams the model into the\n * Cache API, and the model is hosted on Cloudflare R2 which sends Content-Length) — the SW intentionally\n * does NOT intercept the Whisper weight files. See ozwell-model-sw.js / AI/MODEL-HOSTING.md.\n *\n * Idempotent and best-effort: safe to call from multiple mount points; no-ops without SW support.\n * The SW intercepts on the NEXT load (it activates + claims after first registration), so the very\n * first visit still downloads normally; subsequent opens are cache hits.\n */\nconst registered = new Set<string>();\n\nexport function registerModelServiceWorker(\n swUrl = '/ozwell-model-sw.js'\n): void {\n // Bail BEFORE memoizing if SW is unavailable (SSR / unsupported), so we don't mark the URL \"registered\"\n // and then skip the real registration once running in a proper browser.\n if (typeof navigator === 'undefined' || !('serviceWorker' in navigator))\n return;\n if (registered.has(swUrl)) return; // memoize per-URL, so a different swUrl isn't silently ignored\n registered.add(swUrl);\n navigator.serviceWorker.register(swUrl).then(\n () => console.log('[modelCache] model service worker registered'),\n (e) => {\n // Un-memoize on failure (404 in local dev, transient offline/CSP) so a later call can retry this\n // session instead of caching staying disabled until a full reload.\n registered.delete(swUrl);\n console.warn(\n '[modelCache] SW registration failed (models will still load, just not cached):',\n e\n );\n }\n );\n}\n","/**\n * Ozwell chat backend — the real call that replaces the demo stub.\n *\n * Mirrors the ozwellai-api TypeScript SDK (clients/typescript/src/index.ts) with plain `fetch`,\n * so there's no SDK dependency to install: OpenAI-compatible POST /v1/chat/completions, Bearer auth,\n * `messages` array in / `choices[0].message.content` (or streamed `delta.content`) out.\n *\n * KEY HANDLING (deliberate): the API key is NEVER hardcoded or committed. It's read at runtime from\n * - `window.__ozwell` (e.g. `window.__ozwell = { apiKey: 'sk-...' }` in the console), or\n * - `localStorage['ozwellConfig']` (JSON, survives reloads).\n * If no key is configured, `isOzwellConfigured()` is false and the chat falls back to its canned reply —\n * so this file is always safe to push and the demo still works keyless. For a PUBLIC deploy the key\n * should live server-side behind a proxy (a browser-direct Bearer key is visible to anyone with the page);\n * point `baseURL` at that proxy then. See AI/MODEL-HOSTING.md / the hosted-demo plan.\n */\n\nexport interface OzwellMessage {\n role: 'system' | 'user' | 'assistant';\n content: string;\n}\n\nexport interface OzwellConfig {\n /** API base. Defaults to https://api.ozwell.ai (or http://localhost:11434 when apiKey === 'ollama'). */\n baseURL: string;\n /** Bearer key. Empty = not configured → callers fall back to the stub. */\n apiKey: string;\n /** Model id. */\n model: string;\n /** System prompt prepended to the conversation (omit by setting to ''). */\n system: string;\n /** Sampling temperature. */\n temperature: number;\n}\n\nconst DEFAULT_BASE = 'https://api.ozwell.ai';\nconst OLLAMA_BASE = 'http://localhost:11434';\nconst DEFAULTS = {\n model: 'gpt-4o-mini',\n system:\n 'You are Ozwell, a concise and helpful clinical assistant. Answer briefly and clearly.',\n temperature: 0.7,\n};\n\n// Storybook renders each story in an IFRAME, so a console-set `window.__ozwell` usually lands on the\n// parent frame, not the story's. Check current → parent → top (all same-origin, so safe). localStorage\n// is shared across same-origin frames, so the localStorage form always works regardless of frame.\nfunction readWindowGlobal(): Partial<OzwellConfig> {\n if (typeof window === 'undefined') return {}; // SSR / Node — no window\n const get = (w?: Window | null): Partial<OzwellConfig> | undefined => {\n try {\n return (w as unknown as { __ozwell?: Partial<OzwellConfig> })?.__ozwell;\n } catch {\n return undefined;\n }\n };\n return get(window) || get(window.parent) || get(window.top) || {};\n}\n// Copy only safe, own keys from parsed/external config (drop __proto__/constructor/prototype). Object\n// spread alone can't pollute Object.prototype (CreateDataProperty semantics), but the rest of this PR's\n// config parsers (voiceprintStore, diarize) filter dangerous keys — keep this one consistent.\nfunction sanitizeConfig(o: unknown): Partial<OzwellConfig> {\n if (!o || typeof o !== 'object') return {};\n const out: Record<string, unknown> = {};\n for (const k of Object.keys(o)) {\n if (k === '__proto__' || k === 'constructor' || k === 'prototype') continue;\n out[k] = (o as Record<string, unknown>)[k];\n }\n return out as Partial<OzwellConfig>;\n}\nfunction readRaw(): Partial<OzwellConfig> {\n let stored: Partial<OzwellConfig> = {};\n try {\n stored = sanitizeConfig(\n JSON.parse(localStorage.getItem('ozwellConfig') || '{}')\n );\n } catch {\n /* ignore bad JSON */\n }\n return { ...stored, ...sanitizeConfig(readWindowGlobal()) }; // window override wins over localStorage\n}\n\n/** Resolve the effective config from runtime sources + defaults. */\nexport function getOzwellConfig(): OzwellConfig {\n const c = readRaw();\n const apiKey = c.apiKey || '';\n const baseURL =\n c.baseURL || (apiKey === 'ollama' ? OLLAMA_BASE : DEFAULT_BASE);\n return {\n baseURL,\n apiKey,\n model: c.model || DEFAULTS.model,\n system: c.system ?? DEFAULTS.system,\n // Coerce: temperature set via console/localStorage often arrives as a string; a string in the request\n // body can be rejected by OpenAI-compatible servers. Fall back to the default if it's not a real number —\n // and guard the empty/whitespace string explicitly, since Number('') is 0 (a valid-looking temperature)\n // and would silently pin sampling to 0 instead of using the default.\n temperature:\n c.temperature != null &&\n String(c.temperature).trim() !== '' &&\n Number.isFinite(Number(c.temperature))\n ? Number(c.temperature)\n : DEFAULTS.temperature,\n };\n}\n\n/** True once a key is configured — gate the real call on this; otherwise keep the stub reply. */\nexport function isOzwellConfigured(): boolean {\n return !!getOzwellConfig().apiKey;\n}\n\n/** Map AIChat's message blocks to the API's role/content shape (user+assistant text only) for multi-turn. */\nexport function toOzwellMessages(\n msgs: { role: string; content: { type?: string; text?: string }[] }[]\n): OzwellMessage[] {\n const out: OzwellMessage[] = [];\n for (const m of msgs) {\n if (m.role !== 'user' && m.role !== 'assistant') continue;\n const text = (m.content || [])\n .map((c) => c.text || '')\n .join(' ')\n .trim();\n if (text) out.push({ role: m.role, content: text });\n }\n return out;\n}\n\nfunction withSystem(\n messages: OzwellMessage[],\n system: string\n): OzwellMessage[] {\n if (!system || messages.some((m) => m.role === 'system')) return messages;\n return [{ role: 'system', content: system }, ...messages];\n}\n\nfunction buildRequest(\n messages: OzwellMessage[] | string,\n cfg: OzwellConfig,\n stream: boolean\n) {\n const msgs =\n typeof messages === 'string'\n ? [{ role: 'user' as const, content: messages }]\n : messages;\n return {\n url: `${cfg.baseURL.replace(/\\/$/, '')}/v1/chat/completions`,\n headers: {\n 'Content-Type': 'application/json',\n // 'ollama' is a sentinel that points baseURL at the local Ollama server, not a real credential —\n // don't send it as a Bearer token (some local OpenAI-compatible servers reject unexpected auth).\n ...(cfg.apiKey && cfg.apiKey !== 'ollama'\n ? { Authorization: `Bearer ${cfg.apiKey}` }\n : {}),\n } as Record<string, string>,\n body: JSON.stringify({\n model: cfg.model,\n messages: withSystem(msgs, cfg.system),\n temperature: cfg.temperature,\n stream,\n }),\n };\n}\n\nexport interface AskOpts extends Partial<OzwellConfig> {\n signal?: AbortSignal;\n}\n\n/**\n * Merge call-time opts over the runtime config. The `apiKey: 'ollama'` sentinel switches baseURL to the\n * local Ollama server inside getOzwellConfig(); honor it when the caller passes it via opts too (without\n * also passing a baseURL), so the request doesn't target the non-Ollama default.\n */\nfunction resolveConfig(opts: AskOpts): OzwellConfig {\n const cfg = { ...getOzwellConfig(), ...opts };\n // When the caller overrides the apiKey but not the baseURL (and there's no explicit baseURL in the\n // runtime config either), re-derive the baseURL from the EFFECTIVE apiKey. Otherwise a runtime config\n // using the 'ollama' sentinel would keep a real key pointed at the Ollama server (and vice-versa). An\n // explicit baseURL — from opts or the runtime config — is always respected.\n if (opts.apiKey && !opts.baseURL && !readRaw().baseURL) {\n cfg.baseURL = cfg.apiKey === 'ollama' ? OLLAMA_BASE : DEFAULT_BASE;\n }\n return cfg;\n}\n\n/** One-shot (non-streaming) completion → the answer text. Throws on HTTP error. */\nexport async function askOzwell(\n messages: OzwellMessage[] | string,\n opts: AskOpts = {}\n): Promise<string> {\n const cfg = resolveConfig(opts);\n const req = buildRequest(messages, cfg, false);\n const res = await fetch(req.url, {\n method: 'POST',\n headers: req.headers,\n body: req.body,\n signal: opts.signal,\n });\n if (!res.ok) throw new Error(`Ozwell API ${res.status}: ${res.statusText}`);\n const data = await res.json();\n return (data?.choices?.[0]?.message?.content ?? '').trim();\n}\n\n/**\n * Streaming completion (SSE). Calls `onToken(delta, full)` as text arrives and resolves with the full text.\n * Token-by-token is the natural fit for a spoken/hands-free reply. Throws on HTTP error.\n */\nexport async function askOzwellStream(\n messages: OzwellMessage[] | string,\n onToken: (delta: string, full: string) => void,\n opts: AskOpts = {}\n): Promise<string> {\n const cfg = resolveConfig(opts);\n const req = buildRequest(messages, cfg, true);\n const res = await fetch(req.url, {\n method: 'POST',\n headers: req.headers,\n body: req.body,\n signal: opts.signal,\n });\n if (!res.ok || !res.body)\n throw new Error(`Ozwell API ${res.status}: ${res.statusText}`);\n\n const reader = res.body.getReader();\n const decoder = new TextDecoder();\n let buf = '';\n let full = '';\n // Process one SSE event's `data:` lines; returns true once the terminal [DONE] frame is seen.\n const processEvent = (ev: string): boolean => {\n for (const line of ev.split(/\\r?\\n/)) {\n if (!line.startsWith('data:')) continue;\n const payload = line.slice(5).trim();\n if (payload === '[DONE]') return true;\n try {\n const json = JSON.parse(payload);\n const delta: string = json?.choices?.[0]?.delta?.content || '';\n if (delta) {\n full += delta;\n onToken(delta, full);\n }\n } catch {\n /* keep-alive / partial line — ignore */\n }\n }\n return false;\n };\n try {\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n buf += decoder.decode(value, { stream: true });\n const events = buf.split(/\\r?\\n\\r?\\n/); // SSE events are separated by a blank line (handle CRLF too)\n buf = events.pop() || ''; // keep the trailing partial event for the next chunk\n for (const ev of events) if (processEvent(ev)) return full;\n }\n // Stream ended: flush the decoder (a final multi-byte UTF-8 char can be split across chunks) and\n // process any trailing event that arrived WITHOUT a blank line, so the last token(s) aren't dropped.\n buf += decoder.decode();\n if (buf.trim()) processEvent(buf);\n } finally {\n // Release the connection promptly on BOTH normal completion and the early `[DONE]` return, so we\n // don't hold the socket open or fight a caller's AbortController. cancel() also releases the lock.\n try {\n await reader.cancel();\n } catch {\n /* stream already closed/errored — nothing to release */\n }\n }\n return full;\n}\n","/**\n * On-device Whisper transcription (Transformers.js from CDN, no install).\n * Shared by the AIChat voice story and the hands-free composition.\n *\n * Whisper runs in a dedicated Web Worker (see WORKER_SRC below) so its heavy download + model\n * instantiation + inference never runs on the main thread. That matters because the on-device WAKE\n * detector runs its ONNX inference on the main thread (single-threaded WASM); before this, loading the\n * ~1.3 GB turbo model starved the wake loop and \"hey ozwell\" wasn't detected until Whisper had loaded.\n * The worker relocates the compute only — same models, same output, same PHI-safe on-device path (audio\n * never leaves the page). The public API here is unchanged; callers don't know a worker exists.\n *\n * transcribeBlob(blob) — decode a recorded blob → 16 kHz mono → transcribe in the worker → text.\n * transcribeGate(samples) — a SECOND, fast (base.en) model used only for the hands-free \"stop-confirm\"\n * check. Independent of the dictation model so the heavy turbo stays the final-transcription path.\n */\nimport { registerModelServiceWorker } from './modelCache';\nimport { getOzwellConfig } from './ozwellChat';\nimport type { TranscriptSegment } from './diarize';\n\nconst HF_HOST = 'https://huggingface.co';\nconst HF_PATH = '{model}/resolve/{revision}/';\n// turbo's weights are served from our Cloudflare R2 bucket, which sends a Content-Length header so\n// transformers.js can stream it into the Cache API (HuggingFace Xet doesn't → re-downloads ~1.3GB each\n// open). This is the DEFAULT; it's runtime-overridable (see whisperHost) so the hosting cutover is a\n// pure-config swap, consistent with the wake/speaker assets and the transformers CDN. See MODEL-HOSTING.md.\nconst R2_HOST = 'https://pub-64db68afc2cb4e108ff06e7e583f09d1.r2.dev';\n\n// Where the turbo Whisper weights load from. Defaults to R2_HOST, overridable at runtime so a consumer can\n// repoint EVERY model to a mieweb-owned host with zero source edits — mirrors `window.__ozwellAssets`\n// (wake/speaker) and `window.__ozwellTransformersUrl` (the ESM). Checks current → parent → top frame\n// (Storybook iframe) → localStorage `ozwellConfig.whisperHost`. Trailing slash trimmed (the worker adds it).\nfunction whisperHost(): string {\n if (typeof window === 'undefined') return R2_HOST;\n const fromWin = (w?: Window | null): string | undefined => {\n try {\n return (w as unknown as { __ozwellWhisperHost?: string })\n ?.__ozwellWhisperHost;\n } catch {\n return undefined;\n }\n };\n const win = fromWin(window) || fromWin(window.parent) || fromWin(window.top);\n if (win) return win.replace(/\\/$/, '');\n try {\n const h = JSON.parse(\n localStorage.getItem('ozwellConfig') || '{}'\n ).whisperHost;\n if (h) return String(h).replace(/\\/$/, '');\n } catch {\n /* ignore */\n }\n return R2_HOST;\n}\n\nconst SMALL_MODELS: Record<string, string> = {\n tiny: 'Xenova/whisper-tiny.en',\n 'tiny.en': 'Xenova/whisper-tiny.en',\n base: 'Xenova/whisper-base.en',\n 'base.en': 'Xenova/whisper-base.en',\n small: 'Xenova/whisper-small.en',\n 'small.en': 'Xenova/whisper-small.en',\n};\nconst GATE_MODEL = 'Xenova/whisper-base.en'; // stop-confirm: fast + reliable on the single word \"done\"\n\n// Optional model override, read from the same ozwellConfig used by the chat. Set\n// `{ ..., whisper: 'base.en' }` to force the small (~75 MB) English model instead of the heavy turbo\n// one — much faster to download and runs even when browser storage is tight/over-quota. Checks current →\n// parent → top frame (Storybook iframe) and localStorage. Resolved HERE (main thread) and passed into the\n// worker, which can't read window/localStorage.\nfunction whisperPref(): string | null {\n if (typeof window === 'undefined') return null; // SSR / Node — no window/localStorage\n const fromWin = (w?: Window | null): string | undefined => {\n try {\n return (w as unknown as { __ozwell?: { whisper?: string } })?.__ozwell\n ?.whisper;\n } catch {\n return undefined;\n }\n };\n const win = fromWin(window) || fromWin(window.parent) || fromWin(window.top);\n if (win) return win;\n try {\n return (\n JSON.parse(localStorage.getItem('ozwellConfig') || '{}').whisper || null\n );\n } catch {\n return null;\n }\n}\n\n// Optional inference-device override for the small English models: set\n// `window.__ozwell.whisperDevice = 'wasm'` (or `ozwellConfig.whisperDevice` in localStorage) to skip the\n// WebGPU attempt. WebGPU on software/broken adapters (headless & automation browsers, some VMs) can\n// \"succeed\" while computing garbage tokens — wasm is slower but always correct. Same window→parent→top→\n// localStorage resolution as the model pref.\nfunction whisperDevice(): string | null {\n if (typeof window === 'undefined') return null;\n const fromWin = (w?: Window | null): string | undefined => {\n try {\n return (w as unknown as { __ozwell?: { whisperDevice?: string } })\n ?.__ozwell?.whisperDevice;\n } catch {\n return undefined;\n }\n };\n const win = fromWin(window) || fromWin(window.parent) || fromWin(window.top);\n if (win) return win;\n try {\n return (\n JSON.parse(localStorage.getItem('ozwellConfig') || '{}').whisperDevice ||\n null\n );\n } catch {\n return null;\n }\n}\n\n// Optional dtype override for the small English models' WebGPU attempt (default 'q8'). The q8 WebGPU\n// kernels miscompute on some Chrome/driver combos while fp16/fp32 work (turbo's fp16/q4 path is fine on\n// the same machines) — set `window.__ozwell.whisperDtype = 'fp16'` to trade a larger download for\n// correct GPU inference. The wasm fallback always uses q8 (CPU arithmetic is deterministic).\nfunction whisperDtype(): string | null {\n if (typeof window === 'undefined') return null;\n const fromWin = (w?: Window | null): string | undefined => {\n try {\n return (w as unknown as { __ozwell?: { whisperDtype?: string } })\n ?.__ozwell?.whisperDtype;\n } catch {\n return undefined;\n }\n };\n const win = fromWin(window) || fromWin(window.parent) || fromWin(window.top);\n if (win) return win;\n try {\n return (\n JSON.parse(localStorage.getItem('ozwellConfig') || '{}').whisperDtype ||\n null\n );\n } catch {\n return null;\n }\n}\n\n// Pinned to an EXACT validated version (a floating `@3` lets jsDelivr serve newer 3.x that can break at\n// runtime). Override the ESM URL for strict-CSP / offline / self-hosted setups via\n// `window.__ozwellTransformersUrl` or `localStorage['ozwellTransformersUrl']`.\nconst DEFAULT_TRANSFORMERS_URL =\n 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.8.1';\nfunction transformersUrl(): string {\n try {\n const w = (window as unknown as { __ozwellTransformersUrl?: string })\n .__ozwellTransformersUrl;\n if (w) return w;\n const ls = localStorage.getItem('ozwellTransformersUrl');\n if (ls) return ls;\n } catch {\n /* ignore */\n }\n return DEFAULT_TRANSFORMERS_URL;\n}\n\n// --- dictation-model load progress, surfaced to the UI (the ~1.3GB turbo download is the slow one) ---\nexport interface WhisperLoadState {\n /** A load is in flight. */ active: boolean;\n /** Overall fraction 0..1 (averaged over the model's files). */ progress: number;\n /** The model is loaded. */ done: boolean;\n}\nlet dictationLoad: WhisperLoadState = {\n active: false,\n progress: 0,\n done: false,\n};\nconst loadListeners = new Set<() => void>();\nfunction setDictationLoad(patch: Partial<WhisperLoadState>): void {\n dictationLoad = { ...dictationLoad, ...patch };\n loadListeners.forEach((l) => l());\n}\n/** Current dictation-model load state (for a progress indicator). */\nexport function getDictationLoad(): WhisperLoadState {\n return dictationLoad;\n}\n/** Subscribe to dictation-model load changes; returns an unsubscribe. Pair with getDictationLoad in\n * React.useSyncExternalStore. */\nexport function subscribeDictationLoad(cb: () => void): () => void {\n loadListeners.add(cb);\n return () => {\n loadListeners.delete(cb);\n };\n}\n\n// ---------------------------------------------------------------------------------------------------------\n// The Whisper worker. Inlined as a string + spawned from a Blob URL so it bundles cleanly in the tsup-built\n// library (no reliance on the consumer's bundler handling worker URLs). It's a MODULE worker so it can\n// `import()` transformers.js from the CDN. Config (URLs, model prefs) is passed in via the 'init' message\n// because a worker can't read window/localStorage. Message protocol:\n// main→worker: {type:'init', cfg} · {type:'warm'} · {type:'warmGate'} · {type:'transcribe', id, want, samples}\n// worker→main: {type:'loadState', patch} · {type:'progress', frac} · {type:'result', id, text, chunks} · {type:'error', id, message}\n// A model load mutates the SHARED env.remoteHost (turbo→whisperHost, english→HF), read per-file as\n// transformers.js fetches — so every load is serialized through one chain to avoid mid-download clobber.\nconst WORKER_SRC = `\nlet cfg = null, modP = null, pipeP = null, gateP = null, isMulti = false;\nlet chain = Promise.resolve();\nconst serialize = (fn) => { const r = chain.then(fn, fn); chain = r.then(() => {}, () => {}); return r; };\n\nfunction getMod() {\n if (modP) return modP;\n modP = (async () => {\n const mod = await import(cfg.transformersUrl);\n mod.env.allowLocalModels = false;\n // transformers.js's OWN cache STREAMS the model straight to the Cache API (how whisper-web caches this\n // 1.2GB turbo model). A hand-rolled SW that buffers the whole file chokes (QuotaExceeded).\n mod.env.useBrowserCache = true;\n mod.env.backends.onnx.wasm.numThreads = 1;\n try { if (navigator.storage && navigator.storage.persist) await navigator.storage.persist(); } catch (e) {}\n return mod;\n })();\n return modP;\n}\n\nfunction progressCb() {\n const frac = {};\n const report = () => {\n const v = Object.values(frac);\n self.postMessage({ type: 'progress', frac: v.length ? v.reduce((a, b) => a + b, 0) / v.length : 0 });\n };\n return (p) => {\n if (!p || !p.file) return;\n if (p.status === 'initiate') { frac[p.file] = frac[p.file] || 0; report(); }\n else if (p.status === 'done') { frac[p.file] = 1; report(); }\n else if (p.status === 'progress' && typeof p.progress === 'number') { frac[p.file] = p.progress / 100; report(); }\n };\n}\n\nasync function buildEnglish(modelId) {\n const mod = await getMod();\n mod.env.remoteHost = cfg.hfHost;\n mod.env.remotePathTemplate = cfg.hfPath;\n if ((cfg.whisperDevice || '').toLowerCase() !== 'wasm') {\n try {\n const gpuDtype = cfg.whisperDtype || 'q8';\n const pipe = await mod.pipeline('automatic-speech-recognition', modelId, { device: 'webgpu', dtype: gpuDtype, progress_callback: progressCb() });\n console.log('[whisper] ready (' + modelId + ' / WebGPU ' + gpuDtype + ', worker)');\n return pipe;\n } catch (e) { /* fall through to wasm */ }\n }\n const pipe = await mod.pipeline('automatic-speech-recognition', modelId, { dtype: 'q8', progress_callback: progressCb() });\n console.log('[whisper] ready (' + modelId + ' / wasm, worker)');\n return pipe;\n}\n\nasync function buildTurbo() {\n const mod = await getMod();\n mod.env.remoteHost = cfg.whisperHost;\n mod.env.remotePathTemplate = '{model}/';\n const pipe = await mod.pipeline('automatic-speech-recognition', 'whisper-turbo', {\n device: 'webgpu',\n dtype: { encoder_model: 'fp16', decoder_model_merged: 'q4' },\n progress_callback: progressCb(),\n });\n isMulti = true;\n console.log('[whisper] ready (turbo / worker)');\n return pipe;\n}\n\nfunction loadWhisper() {\n if (pipeP) return pipeP;\n self.postMessage({ type: 'loadState', patch: { active: true, progress: 0, done: false } });\n pipeP = (async () => {\n const pref = (cfg.whisperPref || '').toLowerCase();\n if (pref && pref !== 'turbo' && cfg.smallModels[pref]) {\n console.log('[whisper] loading ' + pref + ' (forced via ozwellConfig.whisper)…');\n return serialize(() => buildEnglish(cfg.smallModels[pref]));\n }\n console.log('[whisper] loading turbo…');\n try { return await serialize(() => buildTurbo()); }\n catch (e) {\n console.log('[whisper] turbo unavailable (' + (e && e.message ? e.message : e) + ') → base.en fallback');\n return serialize(() => buildEnglish(cfg.gateModel));\n }\n })();\n pipeP.then(\n () => self.postMessage({ type: 'loadState', patch: { active: false, progress: 1, done: true } }),\n () => { pipeP = null; self.postMessage({ type: 'loadState', patch: { active: false } }); }\n );\n return pipeP;\n}\n\nfunction loadGate() {\n if (gateP) return gateP;\n console.log('[whisper] loading stop-confirm gate (base.en)…');\n gateP = serialize(() => buildEnglish(cfg.gateModel));\n gateP.catch(() => { gateP = null; });\n return gateP;\n}\n\nself.onmessage = async (e) => {\n const m = e.data;\n if (!m) return;\n if (m.type === 'init') { cfg = m.cfg; return; }\n if (m.type === 'warm') { loadWhisper().catch(() => {}); return; }\n if (m.type === 'warmGate') { loadGate().catch(() => {}); return; }\n if (m.type === 'transcribe') {\n try {\n let pipe, opts;\n if (m.want === 'gate') { pipe = await loadGate(); opts = { chunk_length_s: 30 }; }\n else {\n pipe = await loadWhisper();\n if (m.want === 'segments' || m.want === 'words') opts = Object.assign({ chunk_length_s: 30, return_timestamps: m.want === 'words' ? 'word' : true }, isMulti ? { language: 'english', task: 'transcribe' } : {});\n else opts = isMulti ? { chunk_length_s: 30, language: 'english', task: 'transcribe' } : { chunk_length_s: 30 };\n }\n const out = await pipe(m.samples, opts);\n self.postMessage({ type: 'result', id: m.id, text: (out && out.text ? out.text : '').trim(), chunks: (out && out.chunks) || null });\n } catch (err) {\n self.postMessage({ type: 'error', id: m.id, message: err && err.message ? err.message : String(err) });\n }\n }\n};\n`;\n\ntype WorkerResult = {\n text: string;\n chunks: { timestamp: [number, number | null]; text?: string }[] | null;\n};\nlet worker: Worker | null = null;\nlet reqId = 0;\nconst pending = new Map<\n number,\n { resolve: (r: WorkerResult) => void; reject: (e: Error) => void }\n>();\n\nfunction buildWorkerCfg() {\n return {\n transformersUrl: transformersUrl(),\n whisperHost: whisperHost(),\n whisperPref: whisperPref(),\n whisperDevice: whisperDevice(),\n whisperDtype: whisperDtype(),\n hfHost: HF_HOST,\n hfPath: HF_PATH,\n smallModels: SMALL_MODELS,\n gateModel: GATE_MODEL,\n };\n}\n\nfunction getWorker(): Worker {\n if (worker) return worker;\n registerModelServiceWorker(); // main-thread SW registration (caches the wake/sherpa models)\n const url = URL.createObjectURL(\n new Blob([WORKER_SRC], { type: 'application/javascript' })\n );\n const w = new Worker(url, { type: 'module' });\n w.onmessage = (e: MessageEvent) => {\n const m = e.data;\n if (!m) return;\n if (m.type === 'loadState') {\n setDictationLoad(m.patch);\n return;\n }\n if (m.type === 'progress') {\n setDictationLoad({ progress: m.frac });\n return;\n }\n if (m.type === 'result') {\n const p = pending.get(m.id);\n if (p) {\n pending.delete(m.id);\n p.resolve({ text: m.text, chunks: m.chunks });\n }\n return;\n }\n if (m.type === 'error') {\n const p = pending.get(m.id);\n if (p) {\n pending.delete(m.id);\n p.reject(new Error(m.message));\n }\n return;\n }\n };\n w.onerror = (e) => {\n // A worker-level failure (e.g. the transformers.js import blocked by CSP) — fail any in-flight calls so\n // callers fall back instead of hanging, and reset the load indicator.\n const err = new Error(\n `whisper worker error: ${e.message || 'failed to load'}`\n );\n pending.forEach((p) => p.reject(err));\n pending.clear();\n setDictationLoad({ active: false });\n };\n w.postMessage({ type: 'init', cfg: buildWorkerCfg() });\n worker = w;\n return worker;\n}\n\n// Post a transcribe request to the worker; the 16 kHz mono samples are TRANSFERRED (zero-copy). Resolves\n// with the worker's { text, chunks }.\nfunction callWorker(\n want: 'text' | 'segments' | 'words' | 'gate',\n samples: Float32Array\n): Promise<WorkerResult> {\n const w = getWorker();\n const id = ++reqId;\n return new Promise<WorkerResult>((resolve, reject) => {\n pending.set(id, { resolve, reject });\n w.postMessage({ type: 'transcribe', id, want, samples }, [samples.buffer]);\n });\n}\n\n/** True only once the dictation model has actually finished loading (not merely started, not rejected). */\nexport function isWhisperLoaded(): boolean {\n return getDictationLoad().done;\n}\n\n/** Terminate the whisper worker so the next call spawns a fresh one with current config\n * (model pref / device / hosts re-read from window+localStorage). Model weights stay in the\n * browser Cache API, so a respawn re-instantiates in seconds rather than re-downloading.\n * Lets callers switch models/devices at runtime or recover from a bad pipeline (e.g. WebGPU\n * computing garbage on a broken adapter). In-flight requests are rejected. */\nexport function resetWhisperWorker(): void {\n if (!worker) return;\n const err = new Error('whisper worker reset');\n pending.forEach((p) => p.reject(err));\n pending.clear();\n worker.terminate();\n worker = null;\n setDictationLoad({ active: false, progress: 0, done: false });\n}\n\n/** Start loading the dictation model NOW (in the worker) so the first dictation doesn't pay the load. */\nexport function warmWhisper(): void {\n getWorker().postMessage({ type: 'warm' });\n}\n\n/** Start loading the stop-confirm gate model (base.en) in the worker. Warm this BEFORE warmWhisper so the\n * fast model isn't queued behind slow turbo. */\nexport function warmStopGate(): void {\n getWorker().postMessage({ type: 'warmGate' });\n}\n\n// Downmix all channels of a decoded buffer to mono (average), so stereo recordings don't lose half the\n// signal. Single-channel buffers pass through.\nfunction downmixToMono(audio: AudioBuffer): Float32Array {\n if (audio.numberOfChannels <= 1) return audio.getChannelData(0);\n const n = audio.length;\n const out = new Float32Array(n);\n for (let ch = 0; ch < audio.numberOfChannels; ch++) {\n const data = audio.getChannelData(ch);\n for (let i = 0; i < n; i++) out[i] += data[i];\n }\n for (let i = 0; i < n; i++) out[i] /= audio.numberOfChannels;\n return out;\n}\n\n// Linear-resample mono audio to 16 kHz (what Whisper wants). Shared by the blob + raw-samples paths. Always\n// returns a fresh, standalone Float32Array (safe to transfer to the worker).\nfunction resampleTo16kMono(\n src: Float32Array,\n sampleRate: number\n): Float32Array {\n const ratio = 16000 / sampleRate;\n const n = Math.round(src.length * ratio);\n const out = new Float32Array(n);\n for (let i = 0; i < n; i++) {\n const t = i / ratio;\n const i0 = Math.floor(t);\n const i1 = Math.min(i0 + 1, src.length - 1);\n out[i] = src[i0] + (src[i1] - src[i0]) * (t - i0);\n }\n return out;\n}\n\n// Decode a recorded Blob → 16 kHz mono Float32 (what Whisper + TitaNet want). decodeAudioData needs the\n// main thread (no AudioContext in workers), but it's cheap; the heavy inference is what moved off-thread.\n// try/finally so a failed decode still closes the AudioContext (they'd otherwise leak across retries).\nexport async function decodeTo16kMono(blob: Blob): Promise<Float32Array> {\n const Ctx =\n window.AudioContext ||\n (window as unknown as { webkitAudioContext: typeof AudioContext })\n .webkitAudioContext;\n const ctx = new Ctx();\n try {\n const audio = await ctx.decodeAudioData(await blob.arrayBuffer());\n return resampleTo16kMono(downmixToMono(audio), audio.sampleRate);\n } finally {\n void ctx.close();\n }\n}\n\n/** Encode 16 kHz mono Float32 samples as a 16-bit PCM WAV blob, so a trimmed clip can flow back through the\n * existing blob-based transcribe/diarize/server paths (which decode it). */\nfunction encodeWav16kMono(samples: Float32Array): Blob {\n const sr = 16000;\n const buf = new ArrayBuffer(44 + samples.length * 2);\n const view = new DataView(buf);\n const str = (o: number, s: string) => {\n for (let i = 0; i < s.length; i++) view.setUint8(o + i, s.charCodeAt(i));\n };\n str(0, 'RIFF');\n view.setUint32(4, 36 + samples.length * 2, true);\n str(8, 'WAVE');\n str(12, 'fmt ');\n view.setUint32(16, 16, true);\n view.setUint16(20, 1, true);\n view.setUint16(22, 1, true);\n view.setUint32(24, sr, true);\n view.setUint32(28, sr * 2, true);\n view.setUint16(32, 2, true);\n view.setUint16(34, 16, true);\n str(36, 'data');\n view.setUint32(40, samples.length * 2, true);\n let o = 44;\n for (let i = 0; i < samples.length; i++) {\n const s = Math.max(-1, Math.min(1, samples[i]));\n view.setInt16(o, s < 0 ? s * 0x8000 : s * 0x7fff, true);\n o += 2;\n }\n return new Blob([buf], { type: 'audio/wav' });\n}\n\n/**\n * Trim the spoken \"ozwell i'm done\" off the END of a clip BEFORE it reaches ASR. Whisper mishears the phrase\n * differently every time (\"all was well\" / \"I was long done\" / …), so stripping the transcript text can\n * never catch them all — the reliable fix is to cut the audio so the phrase is never transcribed.\n *\n * `phraseHintSec` (from the wake detector's detection run) is an estimate of the phrase's length. When\n * given, the cut is anchored at `end - phraseHintSec` and snapped to the nearest pause within ~0.35 s — so\n * it works whether or not the speaker paused (the pause-independent case that pure energy can't handle).\n * Without a hint, it walks back from the end to the last natural pause (energy only). Capped so it never\n * removes too much. Returns a trimmed WAV blob (or the original on failure / nothing sensible to cut). Only\n * call on a PHRASE-triggered stop — not a manual button stop, where there's no phrase to remove.\n */\nexport async function trimTrailingStopPhrase(\n blob: Blob,\n phraseHintSec = 0\n): Promise<Blob> {\n let samples: Float32Array;\n try {\n samples = await decodeTo16kMono(blob);\n } catch {\n return blob;\n }\n const SR = 16000;\n const n = samples.length;\n if (n < SR * 0.8) return blob; // too short to safely trim\n\n // Short-time energy (RMS) per 30 ms frame.\n const fr = Math.round(SR * 0.03);\n const nf = Math.ceil(n / fr);\n const e = new Float32Array(nf);\n let peak = 0;\n for (let f = 0; f < nf; f++) {\n const a = f * fr,\n b = Math.min(n, a + fr);\n let s = 0;\n for (let i = a; i < b; i++) s += samples[i] * samples[i];\n e[f] = Math.sqrt(s / (b - a));\n if (e[f] > peak) peak = e[f];\n }\n const sil = Math.max(0.008, peak * 0.15); // \"silence\" threshold, adaptive to the clip's level\n const minGap = Math.max(1, Math.round((0.15 * SR) / fr)); // a real pause = >= ~150 ms of silence\n const maxTrimFrames = Math.round((2.2 * SR) / fr); // never cut more than ~2.2 s\n const floor = Math.max(0, nf - maxTrimFrames);\n\n let cutFrame: number;\n if (phraseHintSec > 0.2) {\n // Detector-anchored: the phrase is the last ~phraseHintSec. Snap to the nearest quiet frame within a\n // window of that anchor (catches the pause/word-boundary before the phrase even when it's very brief);\n // if none is near, cut at the anchor itself. Pause-independent.\n const anchor = Math.max(0, nf - Math.round((phraseHintSec * SR) / fr));\n const win = Math.round((0.35 * SR) / fr);\n let best = -1,\n bestDist = Infinity;\n for (\n let f = Math.max(0, anchor - win);\n f <= Math.min(nf - 1, anchor + win);\n f++\n ) {\n if (e[f] < sil) {\n const dist = Math.abs(f - anchor);\n if (dist < bestDist) {\n bestDist = dist;\n best = f;\n }\n }\n }\n cutFrame = best >= 0 ? best : anchor;\n } else {\n // Energy-only fallback: walk back from the end to the last sustained pause.\n let k = nf - 1;\n while (k >= floor && e[k] < sil) k--; // skip any trailing quiet after \"done\"\n cutFrame = -1;\n while (k >= floor) {\n if (e[k] < sil) {\n let m = k;\n while (m >= floor && e[m] < sil) m--; // measure this silence run\n if (k - m >= minGap) {\n cutFrame = k + 1;\n break;\n } // sustained pause → the phrase starts after it\n k = m; // micro-pause inside the phrase → keep going back\n } else k--;\n }\n if (cutFrame < 0) cutFrame = Math.max(0, nf - Math.round((1.1 * SR) / fr)); // no pause → conservative fixed trim\n }\n cutFrame = Math.max(cutFrame, floor); // enforce the max-trim cap\n const cutSample = Math.min(n, cutFrame * fr);\n if (cutSample < SR * 0.2) return blob; // would leave almost nothing — bail (text-strip covers it)\n return encodeWav16kMono(samples.subarray(0, cutSample));\n}\n\nexport async function transcribeBlob(\n blob: Blob,\n trimEndSeconds = 0\n): Promise<string> {\n let samples = await decodeTo16kMono(blob);\n if (trimEndSeconds > 0) {\n const cut = Math.round(trimEndSeconds * 16000);\n if (samples.length > cut + 16000)\n samples = samples.slice(0, samples.length - cut); // keep >=1s (slice = standalone buffer)\n }\n const out = await callWorker('text', samples);\n return (out.text ?? '').trim();\n}\n\n/** Transcribe raw mono samples (any sample rate) → text. For the live dictation caption, where we re-run\n * the growing utterance every couple seconds; the FINAL send still uses transcribeBlob. */\nexport async function transcribeSamples(\n samples: Float32Array,\n sampleRate: number\n): Promise<string> {\n const out = await callWorker('text', resampleTo16kMono(samples, sampleRate));\n return (out.text ?? '').trim();\n}\n\n/** Map raw worker chunks (`{ timestamp: [s, e], text }`) to TranscriptSegments in seconds. */\nfunction chunksToSegments(chunks: WorkerResult['chunks']): TranscriptSegment[] {\n return (chunks ?? [])\n .map((c) => ({\n start: c.timestamp?.[0] ?? 0,\n end: c.timestamp?.[1] ?? c.timestamp?.[0] ?? 0,\n text: (c.text ?? '').trim(),\n }))\n .filter((s) => s.text);\n}\n\n/** Transcribe with timestamps → segments `[{ start, end, text }]`, for diarization (align speaker turns to\n * text). Returns 16 kHz-relative seconds. See `useDiarization`. */\nexport async function transcribeSegments(\n blob: Blob\n): Promise<TranscriptSegment[]> {\n const samples = await decodeTo16kMono(blob);\n const out = await callWorker('segments', samples);\n return chunksToSegments(out.chunks);\n}\n\n/** Transcribe with WORD-level timestamps → `[{ start, end, text }]` (seconds), one entry per word — the\n * shape word-level editors (MediaEditor) need. Uses transformers.js `return_timestamps: 'word'`\n * (cross-attention alignment). Some models/runtimes reject word-level alignment — callers should catch\n * and fall back to `transcribeSegments`. */\nexport async function transcribeWords(\n blob: Blob\n): Promise<TranscriptSegment[]> {\n return transcribeWordsFromSamples(await decodeTo16kMono(blob));\n}\n\n/** Word-level transcription from already-decoded 16 kHz mono samples. Lets callers decode once (with\n * their own status/timeout handling) and retry/fall back without re-decoding. NOTE: samples are\n * transferred to the worker — pass a copy (`samples.slice()`) if you need them again. */\nexport async function transcribeWordsFromSamples(\n samples: Float32Array\n): Promise<TranscriptSegment[]> {\n const out = await callWorker('words', samples);\n return chunksToSegments(out.chunks);\n}\n\n/** Segment-level transcription from already-decoded 16 kHz mono samples (see transcribeWordsFromSamples). */\nexport async function transcribeSegmentsFromSamples(\n samples: Float32Array\n): Promise<TranscriptSegment[]> {\n const out = await callWorker('segments', samples);\n return chunksToSegments(out.chunks);\n}\n\n// Server-ASR model id (override via localStorage ozwellConfig.serverWhisper); defaults to the\n// OpenAI-compatible 'whisper-1'.\nfunction serverAsrModel(): string {\n try {\n return (\n JSON.parse(localStorage.getItem('ozwellConfig') || '{}').serverWhisper ||\n 'whisper-1'\n );\n } catch {\n return 'whisper-1';\n }\n}\n\n/** Server-side transcription: POST the recorded audio to the OpenAI-compatible /v1/audio/transcriptions\n * endpoint (same baseURL/apiKey as the chat). NOTE: audio LEAVES the browser — the on-device path\n * (transcribeBlob) is the PHI-safe default; this is the experiment alternative. Throws on HTTP error so\n * the caller can fall back to on-device. */\nexport async function transcribeServer(blob: Blob): Promise<string> {\n const cfg = getOzwellConfig();\n const form = new FormData();\n form.append('file', blob, 'audio.webm');\n form.append('model', serverAsrModel());\n const url = `${cfg.baseURL.replace(/\\/$/, '')}/v1/audio/transcriptions`;\n const headers: Record<string, string> = {};\n if (cfg.apiKey && cfg.apiKey !== 'ollama')\n headers.Authorization = `Bearer ${cfg.apiKey}`;\n const res = await fetch(url, { method: 'POST', headers, body: form });\n if (!res.ok) {\n // statusText is often empty — include a short body snippet so the failure is actionable (the caller\n // still catches this and falls back to on-device transcription).\n const body = await res.text().catch(() => '');\n throw new Error(\n `Server ASR ${res.status}: ${res.statusText || body.slice(0, 200) || 'request failed'}`\n );\n }\n const data = await res.json();\n return (typeof data?.text === 'string' ? data.text : '').trim();\n}\n\n/** Stop-confirm gate: transcribe a short raw-sample window (e.g. the rolling recorder's last ~2s) with the\n * FAST model and return the text. Used to verify a \"ozwell i'm done\" wake actually ended with \"done\"\n * before committing the stop. Cheap — accuracy on the lone word \"done\" is all it needs. */\nexport async function transcribeGate(\n samples: Float32Array,\n sampleRate: number\n): Promise<string> {\n const out = await callWorker('gate', resampleTo16kMono(samples, sampleRate));\n return (out.text ?? '').trim();\n}\n\n/** Peel a trailing \"ozwell i'm done\"-style stop phrase off the end of a transcript. Mirrors the\n * standalone demo: handles Whisper's mishearings (Ozwell / As well / All('s/was) well / Also / Oswald /\n * \"I am done\") including the bare word alone. Bare \"as well\" is NOT stripped (too common) unless joined\n * to \"i'm done\". */\nexport function stripStopPhrase(text: string): string {\n // All whitespace quantifiers are BOUNDED ({0,4}/{1,4}) so backtracking through the optional groups\n // stays constant — ReDoS hardening (transcript words are never separated by more than a couple of\n // spaces, so behavior is unchanged). The trailing-junk trim below uses a linear char walk for the\n // same reason (see trimTrailingPunct — the actual CodeQL js/polynomial-redos finding).\n const tail =\n /(?:\\b(?:oz\\s{0,4}well|all(?:['’]?s|\\s{1,4}was)?\\s{0,4}well|as\\s{0,4}well|also|oswald)\\b[\\s,]{0,6}i(?:['’]?m|\\s{1,4}am)\\s{1,4}done\\b|\\b(?:oz\\s{0,4}well|all(?:['’]?s|\\s{1,4}was)?\\s{0,4}well|oswald)\\b|\\bi(?:['’]?m|\\s{1,4}am)\\s{1,4}done\\b|\\b(?:that\\s{1,4}was\\s{1,4}|was\\s{1,4})?well\\s{1,4}done\\b|\\bthat['’]?s?\\s{1,4}(?:was\\s{1,4})?all\\b|\\bthank(?:s|\\s{1,4}you)(?:\\s{1,4}for\\s{1,4}watching)?\\b|\\bbye\\b)[\\s.,!?-]{0,24}$/i;\n let prev: string | null = null;\n let t = text;\n while (t !== prev && t) {\n prev = t;\n t = trimTrailingPunct(t.replace(tail, ''));\n }\n return t.trim();\n}\n\n/** Strip trailing whitespace/punctuation with a linear char walk. The regex form `/[\\s.,!?-]+$/` restarts\n * its scan at every position of a long trailing run (quadratic on adversarial input — the CodeQL\n * js/polynomial-redos finding on stripStopPhrase). Testing one char at a time can't backtrack. */\nfunction trimTrailingPunct(s: string): string {\n let end = s.length;\n while (end > 0 && /[\\s.,!?-]/.test(s[end - 1])) end--;\n return end === s.length ? s : s.slice(0, end);\n}\n\n/** True if a transcript ENDS with a clear \"done\" stop (\"…done\" / \"…I'm done\" / \"…all done\" / \"…well done\"),\n * tolerating trailing punctuation. Deliberately STRICTER than stripStopPhrase: the stop-confirm gate must\n * NOT fire on a bare \"ozwell\" or a mid-sentence \"done\" — \"we're almost done here\" ends on \"here\", so no\n * match. Favors precision: a missed real stop just means \"say it again\"; a false stop loses dictation. */\nexport function endsWithDone(text: string): boolean {\n // Whitespace bounded for the same polynomial-backtracking reason as stripStopPhrase's tail regex.\n return /\\b(?:i(?:['’]?m|\\s{1,4}am)\\s{1,4}|all\\s{1,4}|well\\s{1,4})?done\\b[\\s.,!?-]{0,24}$/i.test(\n text\n );\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import { AvatarGroup } from './chunk-DVDT7TX7.js';
2
+ import { useDirection } from './chunk-YVKBXNPK.js';
2
3
  import { cn } from './chunk-TQONQSJO.js';
3
4
  import * as React2 from 'react';
4
5
  import { createPortal } from 'react-dom';
@@ -42,6 +43,7 @@ function peerLabels(peers) {
42
43
  var PANEL_OFFSET = 6;
43
44
  var VIEWPORT_PADDING = 8;
44
45
  function useAnchoredPanel(open, anchorRef, panelRef) {
46
+ const direction = useDirection(anchorRef);
45
47
  const [pos, setPos] = React2.useState(
46
48
  null
47
49
  );
@@ -56,10 +58,11 @@ function useAnchoredPanel(open, anchorRef, panelRef) {
56
58
  if (!anchor || !panel) return;
57
59
  const a = anchor.getBoundingClientRect();
58
60
  const { offsetWidth: width, offsetHeight: height } = panel;
61
+ const anchoredLeft = direction === "rtl" ? a.left : a.right - width;
59
62
  const maxLeft = window.innerWidth - width - VIEWPORT_PADDING;
60
63
  const left = Math.max(
61
64
  VIEWPORT_PADDING,
62
- Math.min(a.right - width, Math.max(VIEWPORT_PADDING, maxLeft))
65
+ Math.min(anchoredLeft, Math.max(VIEWPORT_PADDING, maxLeft))
63
66
  );
64
67
  let top = a.bottom + PANEL_OFFSET;
65
68
  if (top + height > window.innerHeight - VIEWPORT_PADDING) {
@@ -75,8 +78,8 @@ function useAnchoredPanel(open, anchorRef, panelRef) {
75
78
  window.removeEventListener("scroll", update, true);
76
79
  window.removeEventListener("resize", update);
77
80
  };
78
- }, [open, anchorRef, panelRef]);
79
- return pos;
81
+ }, [open, anchorRef, panelRef, direction]);
82
+ return { pos, direction };
80
83
  }
81
84
  var KIND_TONE = {
82
85
  doc: "text-muted-foreground",
@@ -100,7 +103,11 @@ function CollabStatus({
100
103
  const [wrapped, setWrapped] = React2.useState(false);
101
104
  const triggerRef = React2.useRef(null);
102
105
  const panelRef = React2.useRef(null);
103
- const pos = useAnchoredPanel(open && showLog, triggerRef, panelRef);
106
+ const { pos, direction } = useAnchoredPanel(
107
+ open && showLog,
108
+ triggerRef,
109
+ panelRef
110
+ );
104
111
  const titleId = React2.useId();
105
112
  React2.useEffect(() => {
106
113
  if (!open) return;
@@ -189,12 +196,14 @@ function CollabStatus({
189
196
  role: "dialog",
190
197
  "aria-labelledby": titleId,
191
198
  "data-slot": "collab-status-panel",
199
+ dir: direction,
192
200
  className: cn(
193
201
  "bg-card text-card-foreground border-border fixed z-50 w-[26rem] max-w-[calc(100vw-1rem)]",
194
202
  "rounded-lg border p-3 text-xs shadow-xl"
195
203
  ),
196
204
  style: {
197
205
  top: pos?.top ?? 0,
206
+ // rtl-ignore -- fixed viewport coords; direction resolved reactively in useAnchoredPanel
198
207
  left: pos?.left ?? 0,
199
208
  visibility: pos ? void 0 : "hidden"
200
209
  },
@@ -481,5 +490,5 @@ function useYjsCollabStatus({
481
490
  }
482
491
 
483
492
  export { CollabStatus, defaultCollabStatusLabels, useYjsCollabStatus };
484
- //# sourceMappingURL=chunk-O6XDA3SI.js.map
485
- //# sourceMappingURL=chunk-O6XDA3SI.js.map
493
+ //# sourceMappingURL=chunk-UY2EZYIC.js.map
494
+ //# sourceMappingURL=chunk-UY2EZYIC.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/CollabStatus/CollabStatus.tsx","../src/components/CollabStatus/useYjsCollabStatus.ts"],"names":["React"],"mappings":"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","file":"chunk-UY2EZYIC.js","sourcesContent":["import * as React from 'react';\nimport { createPortal } from 'react-dom';\nimport { WrapText, X } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { useDirection } from '../../hooks/useDirection';\nimport { AvatarGroup, type AvatarPresence } from '../AvatarGroup/AvatarGroup';\n\n// =============================================================================\n// Types\n// =============================================================================\n\n/** Another participant currently present in the room. */\nexport interface CollabPeer {\n /** Display name published through presence. */\n name: string;\n /** Optional presence color (cursor/avatar tint). */\n color?: string;\n /**\n * What the peer is doing. Peers without a mode count as editing; `viewing`\n * peers are left out of the \"… are editing\" summary.\n */\n mode?: AvatarPresence;\n /** Avatar image URL. */\n avatarUrl?: string;\n}\n\n/** Static identity of the open collaboration room, shown in the debug panel. */\nexport interface CollabRoomInfo {\n /** Room name on the sync server (e.g. `case/4`). */\n name: string;\n /** Transport URL the client connected to. */\n url?: string;\n /** This window's client id (stable per document), or null before connect. */\n clientId?: number | null;\n /** The acting application user id passed to the sync server. */\n userId?: string;\n}\n\n/** Category of a collaboration event in the debug log. */\nexport type CollabLogKind = 'doc' | 'awareness' | 'sync' | 'patch';\n\n/** A single entry in the collaboration debug log. */\nexport interface CollabLogEntry {\n /** Stable key for rendering. */\n id: number | string;\n /** Wall-clock time of the event (epoch ms). */\n at: number;\n /** Event category. */\n kind: CollabLogKind;\n /** Whether this window or a peer originated it. */\n origin?: 'local' | 'remote';\n /** Human-readable detail line. */\n detail: string;\n}\n\n/** Every user-facing string, so apps can translate the widget. */\nexport interface CollabStatusLabels {\n /** Trigger text once the initial sync completed. */\n live: string;\n /** Trigger text before the initial sync completes. */\n connecting: string;\n /** Summary of who else is editing, e.g. `Ann, Bo are editing`. */\n editing: (names: string[]) => string;\n /** Accessible name / tooltip of the trigger button. */\n triggerLabel: string;\n /** Heading of the room-occupants section. */\n peersTitle: (count: number) => string;\n /** Shown in the occupants section when nobody else is in the room. */\n alone: React.ReactNode;\n /** Accessible name of an occupant with a `mode`, e.g. `Ann is viewing`. */\n presence?: (name: string, mode: AvatarPresence) => string;\n /** Heading of the debug panel. */\n logTitle: (count: number) => string;\n /** Accessible name of the panel close button. */\n close: string;\n /** Accessible name of the toggle that unclips long values. */\n wrap: string;\n /** Shown when the log is empty. */\n empty: React.ReactNode;\n roomTerm: string;\n urlTerm: string;\n clientTerm: string;\n userTerm: string;\n /** Suffix appended to the client id once synced / while connecting. */\n clientSynced: string;\n clientConnecting: string;\n}\n\nexport const defaultCollabStatusLabels: CollabStatusLabels = {\n live: 'Live',\n connecting: 'Connecting…',\n editing: (names) =>\n `${names.join(', ')} ${names.length === 1 ? 'is' : 'are'} editing`,\n triggerLabel: 'Live-sync status — open the update log',\n peersTitle: (count) => `In the room (${count})`,\n alone: 'You are the only one here.',\n logTitle: (count) => `Update log (${count})`,\n close: 'Close update log',\n wrap: 'Wrap long values',\n empty: 'No updates yet.',\n roomTerm: 'Room',\n urlTerm: 'Socket',\n clientTerm: 'Client',\n userTerm: 'User',\n clientSynced: 'synced',\n clientConnecting: 'connecting',\n};\n\nexport interface CollabStatusProps {\n /** True once the room has completed its initial sync with the server. */\n connected: boolean;\n /** Other people in the room right now. */\n peers?: CollabPeer[];\n /** Recent collaboration events, newest first. */\n log?: CollabLogEntry[];\n /** Identity of the open room, shown at the top of the panel. */\n room?: CollabRoomInfo | null;\n /** Set false to render a status-only chip with no debug panel. */\n showLog?: boolean;\n /**\n * Render the trigger as the bare connection dot, moving the status text into\n * its accessible name. For headers with no room for a full chip.\n */\n compact?: boolean;\n /**\n * An app-level condition worth the same glance as the connection state, e.g.\n * `\"Unsaved changes\"`. While set, the dot turns amber and the text joins the\n * trigger's accessible name and heads the panel.\n */\n attention?: React.ReactNode;\n /** Overrides for any user-facing string. */\n labels?: Partial<CollabStatusLabels>;\n /** Additional className for the trigger wrapper. */\n className?: string;\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/** One occupant: a person, however many windows they have open. */\ninterface Occupant extends CollabPeer {\n label: string;\n}\n\n/**\n * Collapse multiple windows of the same person into `Name (N)`; they count as\n * viewing only if every window is explicitly viewing.\n */\nfunction peerLabels(peers: CollabPeer[]): Occupant[] {\n const seen = new Map<string, CollabPeer & { count: number }>();\n for (const p of peers) {\n const entry = seen.get(p.name);\n if (!entry) seen.set(p.name, { ...p, count: 1 });\n else {\n entry.count += 1;\n if (entry.mode === 'viewing' && p.mode !== 'viewing') entry.mode = p.mode;\n entry.avatarUrl ??= p.avatarUrl;\n }\n }\n return [...seen.values()].map(({ count, ...p }) => ({\n ...p,\n label: count > 1 ? `${p.name} (${count})` : p.name,\n }));\n}\n\nconst PANEL_OFFSET = 6;\nconst VIEWPORT_PADDING = 8;\n\n/**\n * Position the panel under the trigger, inline-end-aligned to it (right edge\n * in LTR, left edge in RTL) but clamped to the viewport on both axes (it flips\n * above the trigger when it would overflow the bottom). Direction is reactive\n * (`useDirection`), so an open panel re-anchors when the nearest `dir`\n * changes; the returned `direction` must be restated on the portal root,\n * which cannot inherit a local `dir` from the trigger subtree. Position is\n * null until the panel has been measured.\n */\nfunction useAnchoredPanel(\n open: boolean,\n anchorRef: React.RefObject<HTMLElement | null>,\n panelRef: React.RefObject<HTMLElement | null>\n) {\n const direction = useDirection(anchorRef);\n const [pos, setPos] = React.useState<{ top: number; left: number } | null>(\n null\n );\n\n React.useLayoutEffect(() => {\n if (!open) {\n setPos(null);\n return;\n }\n const update = () => {\n const anchor = anchorRef.current;\n const panel = panelRef.current;\n if (!anchor || !panel) return;\n const a = anchor.getBoundingClientRect();\n const { offsetWidth: width, offsetHeight: height } = panel;\n\n // Hug the trigger's inline-end edge; clamp result to the viewport.\n const anchoredLeft = direction === 'rtl' ? a.left : a.right - width;\n const maxLeft = window.innerWidth - width - VIEWPORT_PADDING;\n const left = Math.max(\n VIEWPORT_PADDING,\n Math.min(anchoredLeft, Math.max(VIEWPORT_PADDING, maxLeft))\n );\n\n let top = a.bottom + PANEL_OFFSET;\n if (top + height > window.innerHeight - VIEWPORT_PADDING) {\n top = Math.max(VIEWPORT_PADDING, a.top - height - PANEL_OFFSET);\n }\n\n setPos({ top, left });\n };\n\n // Measured after the (hidden) panel has been laid out.\n const raf = window.requestAnimationFrame(update);\n window.addEventListener('scroll', update, true);\n window.addEventListener('resize', update);\n return () => {\n window.cancelAnimationFrame(raf);\n window.removeEventListener('scroll', update, true);\n window.removeEventListener('resize', update);\n };\n }, [open, anchorRef, panelRef, direction]);\n\n return { pos, direction };\n}\n\nconst KIND_TONE: Record<CollabLogKind, string> = {\n doc: 'text-muted-foreground',\n awareness: 'text-primary-600 dark:text-primary-400',\n sync: 'text-success-700 dark:text-success-400',\n patch: 'text-muted-foreground',\n};\n\n// =============================================================================\n// Component\n// =============================================================================\n\n/**\n * Live-collaboration status chip: a connection dot, a `Live` / `Connecting…`\n * label, a summary of who else is editing, and a click-to-open panel with the\n * room identity, who is in the room, and a rolling log of collaboration\n * events. Pass `compact` to shrink the trigger down to the dot alone, and\n * `attention` to let an app condition (\"Unsaved changes\") share that dot.\n *\n * Transport-agnostic — it renders whatever presence state you hand it. For a\n * Yjs (`y-websocket`) room, {@link useYjsCollabStatus} produces these props\n * directly:\n *\n * @example\n * ```tsx\n * const doc = React.useMemo(() => new Y.Doc(), []);\n * const provider = React.useMemo(\n * () => new WebsocketProvider('ws://localhost:1234', 'case/4', doc),\n * [doc]\n * );\n * const status = useYjsCollabStatus({ doc, provider, user: { name: 'Ann' } });\n *\n * return <CollabStatus {...status} />;\n * ```\n */\nexport function CollabStatus({\n connected,\n peers = [],\n log = [],\n room = null,\n showLog = true,\n compact = false,\n attention = null,\n labels: labelOverrides,\n className,\n}: CollabStatusProps) {\n const labels = { ...defaultCollabStatusLabels, ...labelOverrides };\n const [open, setOpen] = React.useState(false);\n const [wrapped, setWrapped] = React.useState(false);\n const triggerRef = React.useRef<HTMLButtonElement>(null);\n const panelRef = React.useRef<HTMLDivElement>(null);\n const { pos, direction } = useAnchoredPanel(\n open && showLog,\n triggerRef,\n panelRef\n );\n const titleId = React.useId();\n\n // Escape closes and returns focus; a pointer outside dismisses.\n React.useEffect(() => {\n if (!open) return;\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key !== 'Escape') return;\n setOpen(false);\n triggerRef.current?.focus();\n };\n const onPointerDown = (e: Event) => {\n const target = e.target as Node;\n if (panelRef.current?.contains(target)) return;\n if (triggerRef.current?.contains(target)) return;\n setOpen(false);\n };\n document.addEventListener('keydown', onKeyDown);\n document.addEventListener('pointerdown', onPointerDown);\n return () => {\n document.removeEventListener('keydown', onKeyDown);\n document.removeEventListener('pointerdown', onPointerDown);\n };\n }, [open]);\n\n const occupants = peerLabels(peers);\n const names = occupants\n .filter((p) => p.mode !== 'viewing')\n .map((p) => p.label);\n // Long values are clipped to one line; the panel's wrap toggle unclips them.\n const clip = wrapped ? 'break-all whitespace-pre-wrap' : 'truncate';\n const statusText = connected ? labels.live : labels.connecting;\n const clientLine = `${room?.clientId ?? '—'} · ${\n connected ? labels.clientSynced : labels.clientConnecting\n }`;\n // Compact triggers have no visible text, so the status and who is editing\n // have to reach assistive tech (and the tooltip) through the label.\n const triggerLabel = compact\n ? [\n labels.triggerLabel,\n statusText,\n attention,\n names.length > 0 && labels.editing(names),\n ]\n .filter(Boolean)\n .join(' — ')\n : labels.triggerLabel;\n\n const trigger = (\n <button\n type=\"button\"\n ref={triggerRef}\n className={cn(\n 'text-muted-foreground inline-flex items-center gap-1.5 rounded-md px-1.5 py-0.5 text-xs',\n 'focus-visible:ring-ring focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:outline-none',\n showLog && 'hover:bg-muted cursor-pointer',\n className\n )}\n onClick={showLog ? () => setOpen((v) => !v) : undefined}\n disabled={!showLog}\n title={showLog ? triggerLabel : undefined}\n aria-expanded={showLog ? open : undefined}\n aria-label={showLog ? triggerLabel : undefined}\n data-slot=\"collab-status-trigger\"\n >\n <span\n aria-hidden=\"true\"\n data-slot=\"collab-status-dot\"\n className={cn(\n 'h-2 w-2 shrink-0 rounded-full',\n !connected && 'bg-warning-500 animate-pulse',\n connected && attention && 'bg-warning-500',\n connected && !attention && 'bg-success-500'\n )}\n />\n {!compact && <span>{statusText}</span>}\n {!compact && attention && (\n <span className=\"text-warning-700 dark:text-warning-400 truncate\">\n · {attention}\n </span>\n )}\n {!compact && names.length > 0 && (\n <span className=\"truncate\">{`· ${labels.editing(names)}`}</span>\n )}\n </button>\n );\n\n if (!showLog) return trigger;\n\n return (\n <span\n className=\"relative inline-flex items-center\"\n data-slot=\"collab-status\"\n >\n {trigger}\n {open &&\n typeof document !== 'undefined' &&\n createPortal(\n <div\n ref={panelRef}\n role=\"dialog\"\n aria-labelledby={titleId}\n data-slot=\"collab-status-panel\"\n // Portals under <body> don't inherit a local `dir` from the\n // trigger subtree; restate the resolved direction.\n dir={direction}\n className={cn(\n 'bg-card text-card-foreground border-border fixed z-50 w-[26rem] max-w-[calc(100vw-1rem)]',\n 'rounded-lg border p-3 text-xs shadow-xl'\n )}\n style={{\n top: pos?.top ?? 0,\n // rtl-ignore -- fixed viewport coords; direction resolved reactively in useAnchoredPanel\n left: pos?.left ?? 0,\n visibility: pos ? undefined : 'hidden',\n }}\n >\n <div className=\"mb-2 flex items-center justify-between gap-2\">\n <strong id={titleId} className=\"text-foreground text-sm\">\n {labels.logTitle(log.length)}\n </strong>\n <span className=\"flex items-center gap-0.5\">\n <button\n type=\"button\"\n className={cn(\n 'hover:text-foreground focus-visible:ring-ring rounded p-0.5 focus-visible:ring-2 focus-visible:outline-none',\n wrapped\n ? 'text-foreground bg-muted'\n : 'text-muted-foreground'\n )}\n onClick={() => setWrapped((v) => !v)}\n aria-pressed={wrapped}\n aria-label={labels.wrap}\n title={labels.wrap}\n data-slot=\"collab-status-wrap\"\n >\n <WrapText className=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n className=\"text-muted-foreground hover:text-foreground focus-visible:ring-ring rounded p-0.5 focus-visible:ring-2 focus-visible:outline-none\"\n onClick={() => {\n setOpen(false);\n triggerRef.current?.focus();\n }}\n aria-label={labels.close}\n >\n <X className=\"h-4 w-4\" aria-hidden=\"true\" />\n </button>\n </span>\n </div>\n\n {attention && (\n <p\n data-slot=\"collab-status-attention\"\n className=\"text-warning-700 dark:text-warning-400 mb-2\"\n >\n {attention}\n </p>\n )}\n\n {room && (\n <dl className=\"border-border text-muted-foreground mb-2 grid grid-cols-[auto_1fr] gap-x-3 gap-y-0.5 border-b pb-2\">\n <dt className=\"opacity-70\">{labels.roomTerm}</dt>\n {/* The values are clipped, so hovering must reveal the rest. */}\n <dd className={clip} title={room.name}>\n {room.name}\n </dd>\n {room.url && (\n <>\n <dt className=\"opacity-70\">{labels.urlTerm}</dt>\n <dd className={clip} title={room.url}>\n {room.url}\n </dd>\n </>\n )}\n <dt className=\"opacity-70\">{labels.clientTerm}</dt>\n <dd className={clip} title={clientLine}>\n {clientLine}\n </dd>\n {room.userId && (\n <>\n <dt className=\"opacity-70\">{labels.userTerm}</dt>\n <dd className={clip} title={room.userId}>\n {room.userId}\n </dd>\n </>\n )}\n </dl>\n )}\n\n <section className=\"border-border mb-2 border-b pb-2\">\n <strong className=\"text-foreground mb-1 block\">\n {labels.peersTitle(peers.length)}\n </strong>\n {peers.length === 0 ? (\n <p className=\"text-muted-foreground\">{labels.alone}</p>\n ) : (\n <div data-slot=\"collab-status-peers\">\n <AvatarGroup\n size=\"sm\"\n max={8}\n className=\"flex-wrap ps-0.5\"\n labels={{\n list: labels.peersTitle(peers.length),\n ...(labels.presence && { presence: labels.presence }),\n }}\n items={occupants.map((peer) => ({\n id: peer.name,\n name: peer.name,\n label: peer.label,\n src: peer.avatarUrl,\n presence: peer.mode,\n color: peer.color,\n }))}\n />\n </div>\n )}\n </section>\n\n {log.length === 0 ? (\n <p className=\"text-muted-foreground\">{labels.empty}</p>\n ) : (\n <ul className=\"max-h-72 space-y-0.5 overflow-y-auto font-mono\">\n {log.map((e) => (\n <li\n key={e.id}\n className=\"grid grid-cols-[auto_auto_1fr] gap-2\"\n >\n <span className=\"text-muted-foreground opacity-70\">\n {new Date(e.at).toLocaleTimeString()}\n </span>\n <span\n className={cn(\n 'whitespace-nowrap',\n e.origin === 'remote'\n ? 'text-primary-600 dark:text-primary-400'\n : KIND_TONE[e.kind]\n )}\n >\n {e.kind}\n {e.origin ? `/${e.origin}` : ''}\n </span>\n <span\n className={cn('text-foreground', clip)}\n title={e.detail}\n >\n {e.detail}\n </span>\n </li>\n ))}\n </ul>\n )}\n </div>,\n document.body\n )}\n </span>\n );\n}\n","import * as React from 'react';\nimport type {\n CollabLogEntry,\n CollabPeer,\n CollabRoomInfo,\n} from './CollabStatus';\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\n// =============================================================================\n// Structural Yjs types\n// =============================================================================\n//\n// Declared structurally (as methods, so parameter bivariance applies) rather\n// than imported from `yjs` / `y-protocols`, so `@mieweb/ui` needs no Yjs\n// dependency at all. A real `Y.Doc`, `Awareness` and `WebsocketProvider`\n// satisfy these as-is.\n\n/** The subset of `Y.Doc` this hook observes. */\nexport interface YjsDocLike {\n clientID: number;\n on(event: string, handler: (...args: any[]) => void): void;\n off(event: string, handler: (...args: any[]) => void): void;\n}\n\n/** The subset of `y-protocols/awareness`.`Awareness` this hook uses. */\nexport interface YjsAwarenessLike {\n clientID: number;\n getStates(): Map<number, Record<string, any>>;\n setLocalStateField(field: string, value: unknown): void;\n on(event: string, handler: (...args: any[]) => void): void;\n off(event: string, handler: (...args: any[]) => void): void;\n}\n\n/** The subset of `y-websocket`.`WebsocketProvider` this hook uses. */\nexport interface YjsProviderLike {\n awareness: YjsAwarenessLike;\n /** True once the initial sync completed (y-websocket exposes this). */\n synced?: boolean;\n /** Room name, used as the default label in the debug panel. */\n roomname?: string;\n /** Server URL, used as the default label in the debug panel. */\n url?: string;\n on(event: string, handler: (...args: any[]) => void): void;\n off(event: string, handler: (...args: any[]) => void): void;\n}\n\n/** Awareness payload published whenever this window makes a local edit. */\ninterface EditActivity {\n at: number;\n fields: string[];\n}\n\n/** A remote collaborator's edit that just changed the open document. */\nexport interface CollabRemoteEdit {\n /** Human-readable labels of the fields that changed. */\n fields: string[];\n /** Who made the change, when attributable from presence. */\n by?: string;\n /** Timestamp; a new value signals a fresh growl/toast. */\n at: number;\n}\n\nexport interface UseYjsCollabStatusOptions {\n /** The shared document. Pass null to keep the hook inert. */\n doc: YjsDocLike | null | undefined;\n /** The sync provider (e.g. `y-websocket`). Pass null to keep it inert. */\n provider: YjsProviderLike | null | undefined;\n /**\n * Presence identity published for this window. Defaults to\n * `User <clientID>` so windows are distinguishable without a login.\n */\n user?: { name?: string; color?: string };\n /** Room label for the debug panel. Defaults to `provider.roomname`. */\n roomName?: string;\n /** URL label for the debug panel. Defaults to `provider.url`. */\n url?: string;\n /** Application user id shown in the debug panel. */\n userId?: string;\n /** Maximum log entries kept in memory. Default 100. */\n logCap?: number;\n}\n\nexport interface YjsCollabStatus {\n /** True once the initial server sync completed. */\n connected: boolean;\n /** Other windows currently present in the room. */\n peers: CollabPeer[];\n /** Recent collaboration events, newest first. */\n log: CollabLogEntry[];\n /** Room identity for the debug panel. */\n room: CollabRoomInfo | null;\n /** The most recent remote edit, or null. */\n lastRemoteEdit: CollabRemoteEdit | null;\n /**\n * Announce a local edit and the fields it touched, so other windows can\n * attribute it. Also records a `patch` log entry.\n */\n publishActivity: (fields: string[]) => void;\n}\n\n// =============================================================================\n// Hook\n// =============================================================================\n\n/**\n * Bind {@link CollabStatus} to a Yjs room: tracks initial-sync state, publishes\n * this window's presence, tracks peers joining/leaving, attributes remote edits,\n * and keeps a capped log of document/awareness/sync events.\n *\n * The return value is spreadable straight into the component.\n *\n * @example\n * ```tsx\n * import * as Y from 'yjs';\n * import { WebsocketProvider } from 'y-websocket';\n * import { CollabStatus, useYjsCollabStatus } from '@mieweb/ui';\n *\n * function Header({ caseId }: { caseId: string }) {\n * const doc = React.useMemo(() => new Y.Doc(), []);\n * const provider = React.useMemo(\n * () => new WebsocketProvider('ws://localhost:1234', `case/${caseId}`, doc),\n * [doc, caseId]\n * );\n * React.useEffect(() => () => provider.destroy(), [provider]);\n *\n * const status = useYjsCollabStatus({ doc, provider, user: { name: 'Ann' } });\n * return <CollabStatus {...status} />;\n * }\n * ```\n */\nexport function useYjsCollabStatus({\n doc,\n provider,\n user,\n roomName,\n url,\n userId,\n logCap = 100,\n}: UseYjsCollabStatusOptions): YjsCollabStatus {\n const [connected, setConnected] = React.useState(false);\n const [peers, setPeers] = React.useState<CollabPeer[]>([]);\n const [lastRemoteEdit, setLastRemoteEdit] =\n React.useState<CollabRemoteEdit | null>(null);\n const [log, setLog] = React.useState<CollabLogEntry[]>([]);\n\n const logIdRef = React.useRef(0);\n const awarenessRef = React.useRef<YjsAwarenessLike | null>(null);\n /** Effective display name published to presence. */\n const selfNameRef = React.useRef('');\n /** Last activity timestamp seen per remote client, to detect new edits. */\n const activitySeen = React.useRef(new Map<number, number>());\n /** Names present, keyed by clientID, to detect join/leave. */\n const peerNames = React.useRef(new Map<number, string>());\n\n const pushLog = React.useCallback(\n (entry: Omit<CollabLogEntry, 'id' | 'at'>) => {\n const full: CollabLogEntry = {\n id: ++logIdRef.current,\n at: Date.now(),\n ...entry,\n };\n setLog((prev) => [full, ...prev].slice(0, logCap));\n },\n [logCap]\n );\n\n const selfName = user?.name?.trim();\n const selfColor = user?.color;\n\n React.useEffect(() => {\n if (!doc || !provider) {\n setConnected(false);\n setPeers([]);\n setLastRemoteEdit(null);\n return;\n }\n\n const awareness = provider.awareness;\n awarenessRef.current = awareness;\n activitySeen.current = new Map();\n peerNames.current = new Map();\n setConnected(provider.synced ?? false);\n\n // Remote updates arrive with `origin === provider`; local transactions have\n // a null origin — that is what labels the log entry.\n const onDocUpdate = (update: Uint8Array, origin: unknown) => {\n pushLog({\n kind: 'doc',\n origin: origin === provider ? 'remote' : 'local',\n detail: `doc update · ${update.byteLength} bytes`,\n });\n };\n doc.on('update', onDocUpdate);\n\n const onSync = (isSynced: boolean) => {\n setConnected(isSynced);\n pushLog({\n kind: 'sync',\n detail: isSynced ? 'synced with server' : 'disconnected',\n });\n };\n provider.on('sync', onSync);\n\n const onStatus = (event: { status?: string }) => {\n if (event?.status === 'disconnected') setConnected(false);\n };\n provider.on('status', onStatus);\n\n const onAwareness = () => {\n const others: CollabPeer[] = [];\n const present = new Map<number, string>();\n let freshest: CollabRemoteEdit | null = null;\n\n awareness.getStates().forEach((state, clientId) => {\n if (clientId === awareness.clientID) return; // skip this window\n const peer = state.user as CollabPeer | undefined;\n if (peer?.name) {\n others.push({ name: peer.name, color: peer.color });\n present.set(clientId, peer.name);\n }\n const activity = state.activity as EditActivity | undefined;\n if (\n activity &&\n activity.at > (activitySeen.current.get(clientId) ?? 0)\n ) {\n activitySeen.current.set(clientId, activity.at);\n if (!freshest || activity.at > freshest.at) {\n const sameUser = !!peer?.name && peer.name === selfNameRef.current;\n freshest = {\n fields: activity.fields,\n by: sameUser ? 'You (another window)' : peer?.name,\n at: activity.at,\n };\n }\n }\n });\n\n for (const [clientId, name] of present) {\n if (!peerNames.current.has(clientId)) {\n pushLog({\n kind: 'awareness',\n origin: 'remote',\n detail: `${name} joined the room`,\n });\n }\n }\n for (const [clientId, name] of peerNames.current) {\n if (!present.has(clientId)) {\n pushLog({\n kind: 'awareness',\n origin: 'remote',\n detail: `${name} left the room`,\n });\n }\n }\n peerNames.current = present;\n setPeers(others);\n\n if (freshest) {\n const edit = freshest as CollabRemoteEdit;\n setLastRemoteEdit(edit);\n pushLog({\n kind: 'awareness',\n origin: 'remote',\n detail: `${edit.by ?? 'peer'} edited ${edit.fields.join(', ')}`,\n });\n }\n };\n awareness.on('change', onAwareness);\n\n return () => {\n doc.off('update', onDocUpdate);\n provider.off('sync', onSync);\n provider.off('status', onStatus);\n awareness.off('change', onAwareness);\n awarenessRef.current = null;\n activitySeen.current = new Map();\n peerNames.current = new Map();\n setConnected(false);\n setPeers([]);\n setLastRemoteEdit(null);\n setLog([]);\n };\n }, [doc, provider, pushLog]);\n\n // Publish (and re-publish) this window's presence without tearing the room\n // down when the display name changes. Runs after the room effect above, which\n // is what populates `awarenessRef`.\n React.useEffect(() => {\n const awareness = awarenessRef.current;\n if (!awareness) return;\n const name = selfName || `User ${awareness.clientID}`;\n selfNameRef.current = name;\n awareness.setLocalStateField('user', { name, color: selfColor });\n }, [provider, selfName, selfColor]);\n\n const publishActivity = React.useCallback(\n (fields: string[]) => {\n awarenessRef.current?.setLocalStateField('activity', {\n at: Date.now(),\n fields,\n } satisfies EditActivity);\n pushLog({\n kind: 'patch',\n origin: 'local',\n detail: `edited ${fields.join(', ')}`,\n });\n },\n [pushLog]\n );\n\n const room: CollabRoomInfo | null =\n doc && provider\n ? {\n name: roomName ?? provider.roomname ?? 'room',\n url: url ?? provider.url,\n clientId: doc.clientID,\n userId,\n }\n : null;\n\n return { connected, peers, log, room, lastRemoteEdit, publishActivity };\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import { isRtl } from './chunk-YVKBXNPK.js';
1
2
  import { cn } from './chunk-TQONQSJO.js';
2
3
  import * as React from 'react';
3
4
  import { cva } from 'class-variance-authority';
@@ -24,7 +25,7 @@ var sliderTrackVariants = cva(
24
25
  }
25
26
  );
26
27
  var sliderRangeVariants = cva(
27
- ["absolute h-full rounded-full transition-all duration-75 ease-out"],
28
+ ["absolute start-0 h-full rounded-full transition-all duration-75 ease-out"],
28
29
  {
29
30
  variants: {
30
31
  variant: {
@@ -42,7 +43,7 @@ var sliderRangeVariants = cva(
42
43
  );
43
44
  var sliderThumbVariants = cva(
44
45
  [
45
- "absolute top-1/2 -translate-y-1/2 -translate-x-1/2",
46
+ "absolute top-1/2 -translate-y-1/2 -translate-x-1/2 rtl:translate-x-1/2",
46
47
  "rounded-full border-2 bg-white",
47
48
  "shadow-md transition-shadow duration-150",
48
49
  "cursor-grab active:cursor-grabbing",
@@ -119,10 +120,8 @@ var Slider = React.forwardRef(
119
120
  const track = trackRef.current;
120
121
  if (!track) return clampedValue;
121
122
  const rect = track.getBoundingClientRect();
122
- const ratio = Math.min(
123
- Math.max((clientX - rect.left) / rect.width, 0),
124
- 1
125
- );
123
+ const offset = isRtl(track) ? rect.right - clientX : clientX - rect.left;
124
+ const ratio = Math.min(Math.max(offset / rect.width, 0), 1);
126
125
  const raw = min + ratio * (max - min);
127
126
  const stepped = min + Math.round((raw - min) / safeStep) * safeStep;
128
127
  return Math.min(Math.max(stepped, min), max);
@@ -180,13 +179,18 @@ var Slider = React.forwardRef(
180
179
  const handleKeyDown = React.useCallback(
181
180
  (e) => {
182
181
  if (disabled) return;
182
+ const rtl = isRtl(e.currentTarget);
183
183
  let newValue = null;
184
184
  switch (e.key) {
185
185
  case "ArrowRight":
186
+ case "ArrowLeft": {
187
+ const increase = e.key === "ArrowRight" !== rtl;
188
+ newValue = increase ? Math.min(clampedValue + safeStep, max) : Math.max(clampedValue - safeStep, min);
189
+ break;
190
+ }
186
191
  case "ArrowUp":
187
192
  newValue = Math.min(clampedValue + safeStep, max);
188
193
  break;
189
- case "ArrowLeft":
190
194
  case "ArrowDown":
191
195
  newValue = Math.max(clampedValue - safeStep, min);
192
196
  break;
@@ -308,7 +312,7 @@ var Slider = React.forwardRef(
308
312
  {
309
313
  "data-slot": "slider-thumb",
310
314
  className: sliderThumbVariants({ size, variant }),
311
- style: { left: `${percentage}%` },
315
+ style: { insetInlineStart: `${percentage}%` },
312
316
  "aria-hidden": "true"
313
317
  }
314
318
  )
@@ -355,5 +359,5 @@ var Slider = React.forwardRef(
355
359
  Slider.displayName = "Slider";
356
360
 
357
361
  export { Slider, sliderRangeVariants, sliderThumbVariants, sliderTrackVariants };
358
- //# sourceMappingURL=chunk-2BPIVWAK.js.map
359
- //# sourceMappingURL=chunk-2BPIVWAK.js.map
362
+ //# sourceMappingURL=chunk-V5VPECJI.js.map
363
+ //# sourceMappingURL=chunk-V5VPECJI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/Slider/Slider.tsx"],"names":[],"mappings":"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","file":"chunk-V5VPECJI.js","sourcesContent":["import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { isRtl } from '../../hooks/useDirection';\n\n// ============================================================================\n// Slider Variants\n// ============================================================================\n\nconst sliderTrackVariants = cva(\n [\n 'relative w-full overflow-hidden rounded-full',\n 'bg-neutral-200 dark:bg-neutral-700',\n 'cursor-pointer',\n 'group-data-[disabled=true]:cursor-not-allowed group-data-[disabled=true]:opacity-50',\n ],\n {\n variants: {\n size: {\n sm: 'h-1',\n md: 'h-2',\n lg: 'h-3',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n }\n);\n\nconst sliderRangeVariants = cva(\n ['absolute start-0 h-full rounded-full transition-all duration-75 ease-out'],\n {\n variants: {\n variant: {\n default: 'bg-primary-800',\n success: 'bg-green-500',\n warning: 'bg-yellow-500',\n danger: 'bg-red-500',\n neutral: 'bg-neutral-500',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n }\n);\n\nconst sliderThumbVariants = cva(\n [\n 'absolute top-1/2 -translate-y-1/2 -translate-x-1/2 rtl:translate-x-1/2',\n 'rounded-full border-2 bg-white',\n 'shadow-md transition-shadow duration-150',\n 'cursor-grab active:cursor-grabbing',\n 'hover:shadow-lg',\n 'active:shadow-xl active:scale-110',\n 'group-focus-visible:outline-none group-focus-visible:ring-2 group-focus-visible:ring-ring group-focus-visible:ring-offset-2',\n 'group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50',\n ],\n {\n variants: {\n size: {\n sm: 'h-3.5 w-3.5',\n md: 'h-5 w-5',\n lg: 'h-6 w-6',\n },\n variant: {\n default: 'border-primary-500',\n success: 'border-green-500',\n warning: 'border-yellow-500',\n danger: 'border-red-500',\n neutral: 'border-neutral-500',\n },\n },\n defaultVariants: {\n size: 'md',\n variant: 'default',\n },\n }\n);\n\n// ============================================================================\n// Slider Component\n// ============================================================================\n\nexport interface SliderProps\n extends\n VariantProps<typeof sliderTrackVariants>,\n VariantProps<typeof sliderRangeVariants> {\n /** Current value (controlled) */\n value?: number;\n /** Default value (uncontrolled) */\n defaultValue?: number;\n /** Minimum value */\n min?: number;\n /** Maximum value */\n max?: number;\n /** Step increment */\n step?: number;\n /** Callback when value changes */\n onValueChange?: (value: number) => void;\n /** Callback when interaction ends (mouseup / touchend) */\n onValueCommit?: (value: number) => void;\n /** Whether the slider is disabled */\n disabled?: boolean;\n /** Label for the slider */\n label?: string;\n /** Show the current value */\n showValue?: boolean;\n /** Format the displayed value */\n formatValue?: (value: number) => string;\n /** Description text below the label */\n description?: string;\n /** Min label displayed below the track (left) */\n minLabel?: string;\n /** Max label displayed below the track (right) */\n maxLabel?: string;\n /** Additional class name for the root container */\n className?: string;\n /** Additional class name for the track */\n trackClassName?: string;\n /** ID for the underlying input */\n id?: string;\n /** Name for form submission */\n name?: string;\n /** Accessible label for the slider */\n 'aria-label'?: string;\n /** ID of the element that labels the slider */\n 'aria-labelledby'?: string;\n}\n\n/**\n * A fully branded, accessible slider/range input component.\n *\n * Uses brand design tokens for colors, border-radius, and sizing.\n * Supports controlled and uncontrolled usage, labels, descriptions,\n * min/max labels, value display, and multiple color variants.\n *\n * @example\n * ```tsx\n * <Slider label=\"Volume\" min={0} max={100} defaultValue={50} />\n * <Slider\n * label=\"Border Radius\"\n * min={0}\n * max={32}\n * value={radius}\n * onValueChange={setRadius}\n * showValue\n * formatValue={(v) => `${v}px`}\n * minLabel=\"Square\"\n * maxLabel=\"Rounded\"\n * />\n * ```\n */\nconst Slider = React.forwardRef<HTMLInputElement, SliderProps>(\n (\n {\n value: controlledValue,\n defaultValue = 0,\n min = 0,\n max = 100,\n step = 1,\n onValueChange,\n onValueCommit,\n disabled = false,\n label,\n showValue = false,\n formatValue,\n description,\n minLabel,\n maxLabel,\n variant,\n size,\n className,\n trackClassName,\n id,\n name,\n 'aria-label': ariaLabelProp,\n 'aria-labelledby': ariaLabelledByProp,\n },\n ref\n ) => {\n const hasExplicitLabel = !!label;\n const labelId = React.useId();\n const descriptionId = React.useId();\n const ariaLabelledBy =\n ariaLabelledByProp ?? (hasExplicitLabel ? labelId : undefined);\n const ariaDescribedBy = description ? descriptionId : undefined;\n const ariaLabel =\n ariaLabelProp ??\n (!hasExplicitLabel && !ariaLabelledByProp ? 'Slider' : undefined);\n const [uncontrolledValue, setUncontrolledValue] =\n React.useState(defaultValue);\n const isControlled = controlledValue !== undefined;\n const currentValue = isControlled ? controlledValue : uncontrolledValue;\n\n // Clamp value to min/max\n const clampedValue = Math.min(Math.max(currentValue, min), max);\n\n // Percentage for visual fill\n const percentage =\n max !== min ? ((clampedValue - min) / (max - min)) * 100 : 0;\n\n const generatedId = React.useId();\n const inputId = id ?? generatedId;\n\n const trackRef = React.useRef<HTMLDivElement>(null);\n const latestValueRef = React.useRef(clampedValue);\n latestValueRef.current = clampedValue;\n\n const safeStep = step > 0 ? step : 1;\n\n const computeValueFromPointer = React.useCallback(\n (clientX: number) => {\n const track = trackRef.current;\n if (!track) return clampedValue;\n const rect = track.getBoundingClientRect();\n // Value grows toward the inline-end edge: left→right in LTR,\n // right→left in RTL.\n const offset = isRtl(track)\n ? rect.right - clientX\n : clientX - rect.left;\n const ratio = Math.min(Math.max(offset / rect.width, 0), 1);\n const raw = min + ratio * (max - min);\n // Snap to step relative to min\n const stepped = min + Math.round((raw - min) / safeStep) * safeStep;\n return Math.min(Math.max(stepped, min), max);\n },\n [min, max, safeStep, clampedValue]\n );\n\n const setValue = React.useCallback(\n (newValue: number) => {\n latestValueRef.current = newValue;\n if (!isControlled) {\n setUncontrolledValue(newValue);\n }\n onValueChange?.(newValue);\n },\n [isControlled, onValueChange]\n );\n\n const handlePointerDown = React.useCallback(\n (e: React.PointerEvent) => {\n if (disabled) return;\n e.preventDefault();\n (e.currentTarget as HTMLElement).focus();\n (e.target as HTMLElement).setPointerCapture(e.pointerId);\n const newValue = computeValueFromPointer(e.clientX);\n setValue(newValue);\n },\n [disabled, computeValueFromPointer, setValue]\n );\n\n const handlePointerMove = React.useCallback(\n (e: React.PointerEvent) => {\n if (disabled) return;\n if (!(e.target as HTMLElement).hasPointerCapture(e.pointerId)) return;\n const newValue = computeValueFromPointer(e.clientX);\n setValue(newValue);\n },\n [disabled, computeValueFromPointer, setValue]\n );\n\n const handlePointerUp = React.useCallback(\n (e: React.PointerEvent) => {\n if (disabled) return;\n (e.target as HTMLElement).releasePointerCapture(e.pointerId);\n onValueCommit?.(latestValueRef.current);\n },\n [disabled, onValueCommit]\n );\n\n const handleLostPointerCapture = React.useCallback(() => {\n onValueCommit?.(latestValueRef.current);\n }, [onValueCommit]);\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const newValue = parseFloat(e.target.value);\n if (!isControlled) {\n setUncontrolledValue(newValue);\n }\n onValueChange?.(newValue);\n };\n\n const handleKeyDown = React.useCallback(\n (e: React.KeyboardEvent) => {\n if (disabled) return;\n // Horizontal arrows follow the visual direction: in RTL the slider\n // fills right→left, so ArrowLeft increases and ArrowRight decreases.\n const rtl = isRtl(e.currentTarget);\n let newValue: number | null = null;\n switch (e.key) {\n case 'ArrowRight':\n case 'ArrowLeft': {\n const increase = (e.key === 'ArrowRight') !== rtl;\n newValue = increase\n ? Math.min(clampedValue + safeStep, max)\n : Math.max(clampedValue - safeStep, min);\n break;\n }\n case 'ArrowUp':\n newValue = Math.min(clampedValue + safeStep, max);\n break;\n case 'ArrowDown':\n newValue = Math.max(clampedValue - safeStep, min);\n break;\n case 'Home':\n newValue = min;\n break;\n case 'End':\n newValue = max;\n break;\n default:\n return;\n }\n e.preventDefault();\n setValue(newValue);\n onValueCommit?.(newValue);\n },\n [disabled, clampedValue, safeStep, min, max, setValue, onValueCommit]\n );\n\n const displayValue = formatValue\n ? formatValue(clampedValue)\n : String(clampedValue);\n\n return (\n <div\n data-slot=\"slider\"\n className={cn('relative w-full', className)}\n data-disabled={disabled || undefined}\n >\n {/* Label row */}\n {(label || showValue) && (\n <div\n data-slot=\"slider-label-row\"\n className=\"mb-1.5 flex items-baseline justify-between\"\n >\n {label && (\n <label\n id={labelId}\n htmlFor={inputId}\n data-slot=\"slider-label\"\n className={cn(\n 'text-foreground text-sm font-medium',\n disabled && 'opacity-50'\n )}\n >\n {label}\n {showValue && (\n <span\n data-slot=\"slider-value\"\n className=\"text-muted-foreground ms-1\"\n >\n {displayValue}\n </span>\n )}\n </label>\n )}\n {!label && showValue && (\n <span\n data-slot=\"slider-value\"\n className=\"text-muted-foreground text-sm\"\n >\n {displayValue}\n </span>\n )}\n </div>\n )}\n\n {/* Description */}\n {description && (\n <p\n id={descriptionId}\n data-slot=\"slider-description\"\n className={cn(\n 'text-muted-foreground mb-2 text-xs',\n disabled && 'opacity-50'\n )}\n >\n {description}\n </p>\n )}\n\n {/* Track + Thumb */}\n <div\n ref={trackRef}\n data-slot=\"slider-track-wrapper\"\n className=\"group focus-visible:ring-ring relative rounded py-2 outline-none focus-visible:ring-2 focus-visible:ring-offset-2\"\n style={{ touchAction: disabled ? 'auto' : 'none' }}\n role=\"slider\"\n tabIndex={disabled ? -1 : 0}\n aria-valuemin={min}\n aria-valuemax={max}\n aria-valuenow={clampedValue}\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy}\n aria-describedby={ariaDescribedBy}\n aria-disabled={disabled || undefined}\n data-disabled={disabled || undefined}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onLostPointerCapture={handleLostPointerCapture}\n onKeyDown={handleKeyDown}\n >\n {/* Visual track background */}\n <div\n data-slot=\"slider-track\"\n className={cn(sliderTrackVariants({ size }), trackClassName)}\n >\n {/* Filled range */}\n <div\n data-slot=\"slider-range\"\n className={sliderRangeVariants({ variant })}\n style={{ width: `${percentage}%` }}\n />\n </div>\n\n {/* Thumb indicator */}\n <div\n data-slot=\"slider-thumb\"\n className={sliderThumbVariants({ size, variant })}\n style={{ insetInlineStart: `${percentage}%` }}\n aria-hidden=\"true\"\n />\n </div>\n\n {/* Native range input — for form submission only, rendered outside role=\"slider\" to avoid nested-interactive */}\n <input\n ref={ref}\n type=\"range\"\n className=\"pointer-events-none absolute inset-0 h-full w-full opacity-0\"\n tabIndex={-1}\n aria-hidden=\"true\"\n id={inputId}\n name={name}\n min={min}\n max={max}\n step={step}\n value={clampedValue}\n onChange={handleChange}\n disabled={disabled}\n />\n\n {/* Min / Max labels */}\n {(minLabel || maxLabel) && (\n <div\n data-slot=\"slider-minmax\"\n className={cn(\n 'text-muted-foreground mt-1 flex justify-between text-xs',\n disabled && 'opacity-50'\n )}\n >\n <span>{minLabel}</span>\n <span>{maxLabel}</span>\n </div>\n )}\n </div>\n );\n }\n);\n\nSlider.displayName = 'Slider';\n\nexport {\n Slider,\n sliderTrackVariants,\n sliderRangeVariants,\n sliderThumbVariants,\n};\n"]}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkMYAU2ZUC_cjs = require('./chunk-MYAU2ZUC.cjs');
3
+ var chunkGDKOYVX3_cjs = require('./chunk-GDKOYVX3.cjs');
4
4
  var chunkKQ6GLYFZ_cjs = require('./chunk-KQ6GLYFZ.cjs');
5
5
  var chunk7AECNMYV_cjs = require('./chunk-7AECNMYV.cjs');
6
6
  var chunkNPKPCYAT_cjs = require('./chunk-NPKPCYAT.cjs');
@@ -8,6 +8,7 @@ var chunkNUFUV43P_cjs = require('./chunk-NUFUV43P.cjs');
8
8
  var chunkUPWIJC6I_cjs = require('./chunk-UPWIJC6I.cjs');
9
9
  var chunkLC3JL2HB_cjs = require('./chunk-LC3JL2HB.cjs');
10
10
  var chunkZ5S5JEJD_cjs = require('./chunk-Z5S5JEJD.cjs');
11
+ var chunkZ3WMDVMR_cjs = require('./chunk-Z3WMDVMR.cjs');
11
12
  var chunkANMX7YDL_cjs = require('./chunk-ANMX7YDL.cjs');
12
13
  var React6 = require('react');
13
14
  var classVarianceAuthority = require('class-variance-authority');
@@ -502,7 +503,7 @@ var SilenceSettingsModal = ({
502
503
  /* @__PURE__ */ jsxRuntime.jsxs(chunkLC3JL2HB_cjs.ModalBody, { className: "flex flex-col gap-6", children: [
503
504
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
504
505
  /* @__PURE__ */ jsxRuntime.jsx(
505
- chunkMYAU2ZUC_cjs.Slider,
506
+ chunkGDKOYVX3_cjs.Slider,
506
507
  {
507
508
  label: "Minimum silence duration",
508
509
  min: 0.1,
@@ -519,7 +520,7 @@ var SilenceSettingsModal = ({
519
520
  ] }),
520
521
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1", children: [
521
522
  /* @__PURE__ */ jsxRuntime.jsx(
522
- chunkMYAU2ZUC_cjs.Slider,
523
+ chunkGDKOYVX3_cjs.Slider,
523
524
  {
524
525
  label: "Paragraph break threshold",
525
526
  min: threshold,
@@ -578,7 +579,11 @@ var SpeedMarkerMenu = ({
578
579
  {
579
580
  ref: menuRef,
580
581
  className: "border-border bg-card text-card-foreground fixed z-50 min-w-36 overflow-hidden rounded-lg border shadow-lg",
581
- style: { left: position.x, top: position.y },
582
+ style: {
583
+ // rtl-ignore -- fixed viewport coordinate from the pointer event
584
+ left: position.x,
585
+ top: position.y
586
+ },
582
587
  role: "menu",
583
588
  "aria-label": "Set speed marker",
584
589
  children: [
@@ -1497,18 +1502,20 @@ var MediaEditor = React6__namespace.forwardRef(
1497
1502
  if (canRedoWords) redo();
1498
1503
  else if (canRedo && onRedo) onRedo();
1499
1504
  handled = true;
1500
- } else if (e.key === "ArrowLeft") {
1501
- if (cursorPosition === "after") {
1502
- setCursorPosition("before");
1505
+ } else if (e.key === "ArrowLeft" || e.key === "ArrowRight") {
1506
+ const forward = e.key === "ArrowRight" !== chunkZ3WMDVMR_cjs.isRtl(e.currentTarget);
1507
+ if (forward) {
1508
+ if (cursorIndex === wordCount - 1 && cursorPosition === "before") {
1509
+ setCursorPosition("after");
1510
+ } else if (cursorPosition !== "after") {
1511
+ newIndex = Math.min(wordCount - 1, cursorIndex + 1);
1512
+ }
1503
1513
  } else {
1504
- newIndex = Math.max(0, cursorIndex - 1);
1505
- }
1506
- handled = true;
1507
- } else if (e.key === "ArrowRight") {
1508
- if (cursorIndex === wordCount - 1 && cursorPosition === "before") {
1509
- setCursorPosition("after");
1510
- } else if (cursorPosition !== "after") {
1511
- newIndex = Math.min(wordCount - 1, cursorIndex + 1);
1514
+ if (cursorPosition === "after") {
1515
+ setCursorPosition("before");
1516
+ } else {
1517
+ newIndex = Math.max(0, cursorIndex - 1);
1518
+ }
1512
1519
  }
1513
1520
  handled = true;
1514
1521
  } else if (e.key === "ArrowUp" || e.key === "ArrowDown") {
@@ -2025,5 +2032,5 @@ exports.MediaEditor = MediaEditor;
2025
2032
  exports.SilenceSettingsModal = SilenceSettingsModal;
2026
2033
  exports.SpeedMarkerMenu = SpeedMarkerMenu;
2027
2034
  exports.WordEditorModal = WordEditorModal;
2028
- //# sourceMappingURL=chunk-O6BJMVGT.cjs.map
2029
- //# sourceMappingURL=chunk-O6BJMVGT.cjs.map
2035
+ //# sourceMappingURL=chunk-XZNHS7YQ.cjs.map
2036
+ //# sourceMappingURL=chunk-XZNHS7YQ.cjs.map