@mieweb/ui 0.11.0-dev.7 → 0.11.0-dev.8

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 (52) hide show
  1. package/dist/brands/index.cjs +12 -12
  2. package/dist/brands/index.js +3 -3
  3. package/dist/chunk-3TUULOTW.cjs +333 -0
  4. package/dist/chunk-3TUULOTW.cjs.map +1 -0
  5. package/dist/{chunk-OODVC2UD.cjs → chunk-AWSSWNJY.cjs} +2 -2
  6. package/dist/{chunk-OODVC2UD.cjs.map → chunk-AWSSWNJY.cjs.map} +1 -1
  7. package/dist/{chunk-QJ2L5RU6.js → chunk-DSQCYX7L.js} +2 -2
  8. package/dist/{chunk-QJ2L5RU6.js.map → chunk-DSQCYX7L.js.map} +1 -1
  9. package/dist/{chunk-JTSKPDPH.cjs → chunk-HIYQ3M5V.cjs} +4 -3
  10. package/dist/chunk-HIYQ3M5V.cjs.map +1 -0
  11. package/dist/chunk-IZY4CMOO.js +715 -0
  12. package/dist/chunk-IZY4CMOO.js.map +1 -0
  13. package/dist/{chunk-753ENNB6.js → chunk-J3QEMZCH.js} +2 -2
  14. package/dist/{chunk-753ENNB6.js.map → chunk-J3QEMZCH.js.map} +1 -1
  15. package/dist/{chunk-VNWJTCBQ.js → chunk-MQOYDQTF.js} +4 -3
  16. package/dist/chunk-MQOYDQTF.js.map +1 -0
  17. package/dist/{chunk-NAH65KPK.cjs → chunk-TOJ56HKQ.cjs} +2 -2
  18. package/dist/{chunk-NAH65KPK.cjs.map → chunk-TOJ56HKQ.cjs.map} +1 -1
  19. package/dist/chunk-TRZLN32I.cjs +740 -0
  20. package/dist/chunk-TRZLN32I.cjs.map +1 -0
  21. package/dist/chunk-XQIQX5OB.js +309 -0
  22. package/dist/chunk-XQIQX5OB.js.map +1 -0
  23. package/dist/components/DictationButton/index.cjs +23 -0
  24. package/dist/components/DictationButton/index.cjs.map +1 -0
  25. package/dist/components/DictationButton/index.d.cts +67 -0
  26. package/dist/components/DictationButton/index.d.ts +67 -0
  27. package/dist/components/DictationButton/index.js +6 -0
  28. package/dist/components/DictationButton/index.js.map +1 -0
  29. package/dist/components/Markdown/index.cjs +10 -10
  30. package/dist/components/Markdown/index.js +2 -2
  31. package/dist/components/RecordButton/index.cjs +4 -4
  32. package/dist/components/RecordButton/index.js +1 -1
  33. package/dist/components/SuperChat/index.d.cts +2 -2
  34. package/dist/components/SuperChat/index.d.ts +2 -2
  35. package/dist/components/SuperChat/plugins/index.d.cts +2 -2
  36. package/dist/components/SuperChat/plugins/index.d.ts +2 -2
  37. package/dist/index.cjs +221 -844
  38. package/dist/index.cjs.map +1 -1
  39. package/dist/index.d.cts +63 -1
  40. package/dist/index.d.ts +63 -1
  41. package/dist/index.js +25 -716
  42. package/dist/index.js.map +1 -1
  43. package/dist/styles.css +1 -1
  44. package/dist/{types-Cx1FHLq2.d.cts → types-DSWbrVkM.d.cts} +1 -1
  45. package/dist/{types-Cx1FHLq2.d.ts → types-DSWbrVkM.d.ts} +1 -1
  46. package/dist/whisperTranscribe-AV752TZI.cjs +81 -0
  47. package/dist/whisperTranscribe-AV752TZI.cjs.map +1 -0
  48. package/dist/whisperTranscribe-UBNUWXUQ.js +4 -0
  49. package/dist/whisperTranscribe-UBNUWXUQ.js.map +1 -0
  50. package/package.json +1 -1
  51. package/dist/chunk-JTSKPDPH.cjs.map +0 -1
  52. package/dist/chunk-VNWJTCBQ.js.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-IZY4CMOO.js","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"]}
@@ -11,5 +11,5 @@ var brands = {
11
11
  };
12
12
 
13
13
  export { brands };
14
- //# sourceMappingURL=chunk-753ENNB6.js.map
15
- //# sourceMappingURL=chunk-753ENNB6.js.map
14
+ //# sourceMappingURL=chunk-J3QEMZCH.js.map
15
+ //# sourceMappingURL=chunk-J3QEMZCH.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/brands/index.ts"],"names":[],"mappings":";AAkCO,IAAM,MAAA,GAAS;AAAA,EACpB,QAAA,EAAU,MAAM,OAAO,sBAAY,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,CAAA;AAAA,EAChE,IAAA,EAAM,MAAM,OAAO,kBAAQ,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,CAAA;AAAA,EACpD,OAAA,EAAS,MAAM,OAAO,uBAAW,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,YAAY,CAAA;AAAA,EAC7D,mBAAA,EAAqB,MACnB,OAAO,iCAAqB,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,qBAAqB,CAAA;AAAA,EACnE,MAAA,EAAQ,MAAM,OAAO,sBAAU,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,CAAA;AAAA,EAC1D,MAAA,EAAQ,MAAM,OAAO,oBAAU,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,CAAA;AAAA,EAC1D,UAAA,EAAY,MAAM,OAAO,0BAAc,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,eAAe,CAAA;AAAA,EACtE,QAAA,EAAU,MAAM,OAAO,wBAAY,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa;AAClE","file":"chunk-753ENNB6.js","sourcesContent":["/**\n * @mieweb/ui Brand System\n *\n * Export all brand-related types, utilities, and configurations.\n */\n\n// Types and utilities\nexport type {\n BrandConfig,\n BrandColors,\n BrandTypography,\n BrandBorderRadius,\n BrandBoxShadow,\n ColorScale,\n SemanticColors,\n} from './types';\n\nexport {\n generateBrandCSS,\n generateTailwindTheme,\n createBrandPreset,\n} from './types';\n\n// Brand configurations\nexport { bluehiveBrand } from './bluehive';\nexport { ccmeBrand } from './ccme';\nexport { defaultBrand } from './default';\nexport { enterpriseHealthBrand } from './enterprise-health';\nexport { miewebBrand } from './mieweb';\nexport { ozwellBrand } from './ozwell';\nexport { wagglelineBrand } from './waggleline';\nexport { webchartBrand } from './webchart';\n\n// All brands for iteration\nexport const brands = {\n bluehive: () => import('./bluehive').then((m) => m.bluehiveBrand),\n ccme: () => import('./ccme').then((m) => m.ccmeBrand),\n default: () => import('./default').then((m) => m.defaultBrand),\n 'enterprise-health': () =>\n import('./enterprise-health').then((m) => m.enterpriseHealthBrand),\n mieweb: () => import('./mieweb').then((m) => m.miewebBrand),\n ozwell: () => import('./ozwell').then((m) => m.ozwellBrand),\n waggleline: () => import('./waggleline').then((m) => m.wagglelineBrand),\n webchart: () => import('./webchart').then((m) => m.webchartBrand),\n} as const;\n"]}
1
+ {"version":3,"sources":["../src/brands/index.ts"],"names":[],"mappings":";AAkCO,IAAM,MAAA,GAAS;AAAA,EACpB,QAAA,EAAU,MAAM,OAAO,sBAAY,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa,CAAA;AAAA,EAChE,IAAA,EAAM,MAAM,OAAO,kBAAQ,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,SAAS,CAAA;AAAA,EACpD,OAAA,EAAS,MAAM,OAAO,uBAAW,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,YAAY,CAAA;AAAA,EAC7D,mBAAA,EAAqB,MACnB,OAAO,iCAAqB,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,qBAAqB,CAAA;AAAA,EACnE,MAAA,EAAQ,MAAM,OAAO,sBAAU,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,CAAA;AAAA,EAC1D,MAAA,EAAQ,MAAM,OAAO,oBAAU,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,CAAA;AAAA,EAC1D,UAAA,EAAY,MAAM,OAAO,0BAAc,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,eAAe,CAAA;AAAA,EACtE,QAAA,EAAU,MAAM,OAAO,wBAAY,EAAE,IAAA,CAAK,CAAC,CAAA,KAAM,CAAA,CAAE,aAAa;AAClE","file":"chunk-J3QEMZCH.js","sourcesContent":["/**\n * @mieweb/ui Brand System\n *\n * Export all brand-related types, utilities, and configurations.\n */\n\n// Types and utilities\nexport type {\n BrandConfig,\n BrandColors,\n BrandTypography,\n BrandBorderRadius,\n BrandBoxShadow,\n ColorScale,\n SemanticColors,\n} from './types';\n\nexport {\n generateBrandCSS,\n generateTailwindTheme,\n createBrandPreset,\n} from './types';\n\n// Brand configurations\nexport { bluehiveBrand } from './bluehive';\nexport { ccmeBrand } from './ccme';\nexport { defaultBrand } from './default';\nexport { enterpriseHealthBrand } from './enterprise-health';\nexport { miewebBrand } from './mieweb';\nexport { ozwellBrand } from './ozwell';\nexport { wagglelineBrand } from './waggleline';\nexport { webchartBrand } from './webchart';\n\n// All brands for iteration\nexport const brands = {\n bluehive: () => import('./bluehive').then((m) => m.bluehiveBrand),\n ccme: () => import('./ccme').then((m) => m.ccmeBrand),\n default: () => import('./default').then((m) => m.defaultBrand),\n 'enterprise-health': () =>\n import('./enterprise-health').then((m) => m.enterpriseHealthBrand),\n mieweb: () => import('./mieweb').then((m) => m.miewebBrand),\n ozwell: () => import('./ozwell').then((m) => m.ozwellBrand),\n waggleline: () => import('./waggleline').then((m) => m.wagglelineBrand),\n webchart: () => import('./webchart').then((m) => m.webchartBrand),\n} as const;\n"]}
@@ -265,6 +265,7 @@ var RecordButton = React.forwardRef(
265
265
  maxDuration = 0,
266
266
  mimeType = "audio/webm",
267
267
  onClick,
268
+ "aria-label": ariaLabel,
268
269
  ...props
269
270
  }, ref) => {
270
271
  const [internalState, setInternalState] = React.useState("idle");
@@ -475,7 +476,7 @@ var RecordButton = React.forwardRef(
475
476
  getStateStyles(effectiveState, variant),
476
477
  className
477
478
  ),
478
- "aria-label": getAriaLabel(),
479
+ "aria-label": ariaLabel ?? getAriaLabel(),
479
480
  "aria-pressed": effectiveState === "recording" ? true : void 0,
480
481
  "aria-busy": effectiveState === "processing" ? true : void 0,
481
482
  children: [
@@ -508,5 +509,5 @@ var RecordButton = React.forwardRef(
508
509
  RecordButton.displayName = "RecordButton";
509
510
 
510
511
  export { RecordButton, formatDuration, recordButtonVariants };
511
- //# sourceMappingURL=chunk-VNWJTCBQ.js.map
512
- //# sourceMappingURL=chunk-VNWJTCBQ.js.map
512
+ //# sourceMappingURL=chunk-MQOYDQTF.js.map
513
+ //# sourceMappingURL=chunk-MQOYDQTF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/RecordButton/RecordButton.tsx"],"names":[],"mappings":"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","file":"chunk-MQOYDQTF.js","sourcesContent":["import * as React from 'react';\nimport { cva } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type RecordButtonState =\n | 'idle'\n | 'recording'\n | 'processing'\n | 'disabled'\n | 'error'\n | 'success';\n\nexport type RecordButtonVariant = 'default' | 'outline' | 'ghost' | 'minimal';\nexport type RecordButtonSize = 'sm' | 'md' | 'lg';\n\n/** Transcription state for integration with transcription services */\nexport type TranscriptionState =\n | 'idle'\n | 'recording'\n | 'transcribing'\n | 'streaming'\n | 'complete'\n | 'error';\n\nexport interface TranscriptionResult {\n /** The transcribed text */\n text: string;\n /** Whether this is a partial (streaming) or final result */\n isFinal: boolean;\n /** Confidence score (0-1) if available */\n confidence?: number;\n}\n\nexport interface RecordButtonProps extends Omit<\n React.ButtonHTMLAttributes<HTMLButtonElement>,\n 'children'\n> {\n /** Current state of the button */\n state?: RecordButtonState;\n /** Size of the button */\n size?: RecordButtonSize;\n /** Visual style variant */\n variant?: RecordButtonVariant;\n /** Show waveform bars when recording (instead of stop icon) */\n showWaveform?: boolean;\n /** Show pulse rings when recording */\n showPulse?: boolean;\n /** Show recording duration while recording */\n showDuration?: boolean;\n /** Custom idle icon */\n idleIcon?: React.ReactNode;\n /** Custom recording icon */\n recordingIcon?: React.ReactNode;\n /** Current transcription state (for external control) */\n transcriptionState?: TranscriptionState;\n /** Show transcription state indicator */\n showTranscriptionState?: boolean;\n\n // Recording callbacks (for uncontrolled usage)\n /** Callback when recording is complete with the audio blob */\n onRecordingComplete?: (blob: Blob, duration: number) => void;\n /** Callback when recording starts */\n onRecordingStart?: () => void;\n /** Callback when a recording error occurs */\n onRecordingError?: (error: Error) => void;\n /** Maximum recording duration in seconds (0 for unlimited) */\n maxDuration?: number;\n /** Audio MIME type */\n mimeType?: string;\n}\n\n// ============================================================================\n// Icons\n// ============================================================================\n\nfunction MicIcon({\n className,\n size = 20,\n}: {\n className?: string;\n size?: number;\n}) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <path d=\"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z\" />\n <path d=\"M19 10v2a7 7 0 0 1-14 0v-2\" />\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\" />\n </svg>\n );\n}\n\nfunction MicOffIcon({\n className,\n size = 20,\n}: {\n className?: string;\n size?: number;\n}) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <line x1=\"2\" x2=\"22\" y1=\"2\" y2=\"22\" />\n <path d=\"M18.89 13.23A7.12 7.12 0 0 0 19 12v-2\" />\n <path d=\"M5 10v2a7 7 0 0 0 12 5\" />\n <path d=\"M15 9.34V5a3 3 0 0 0-5.68-1.33\" />\n <path d=\"M9 9v3a3 3 0 0 0 5.12 2.12\" />\n <line x1=\"12\" x2=\"12\" y1=\"19\" y2=\"22\" />\n </svg>\n );\n}\n\nfunction StopIcon({\n className,\n size = 20,\n}: {\n className?: string;\n size?: number;\n}) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill=\"currentColor\"\n className={className}\n aria-hidden=\"true\"\n >\n <rect x=\"6\" y=\"6\" width=\"12\" height=\"12\" rx=\"2\" />\n </svg>\n );\n}\n\nfunction CheckIcon({\n className,\n size = 20,\n}: {\n className?: string;\n size?: number;\n}) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n aria-hidden=\"true\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n );\n}\n\nfunction LoadingSpinner({\n className,\n size = 20,\n}: {\n className?: string;\n size?: number;\n}) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 24 24\"\n width={size}\n height={size}\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={cn('animate-spin', className)}\n aria-hidden=\"true\"\n >\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n );\n}\n\n// ============================================================================\n// Pulse Ring Animation (for recording state)\n// ============================================================================\n\nfunction PulseRings({ variant }: { variant: RecordButtonVariant }) {\n const ringColor = variant === 'minimal' ? 'bg-red-500/30' : 'bg-red-400/40';\n\n return (\n <>\n <span\n data-slot=\"record-button-pulse\"\n className={cn('absolute inset-0 animate-ping rounded-full', ringColor)}\n style={{ animationDuration: '1.5s' }}\n />\n <span\n data-slot=\"record-button-pulse\"\n className={cn('absolute inset-0 animate-ping rounded-full', ringColor)}\n style={{ animationDuration: '1.5s', animationDelay: '0.5s' }}\n />\n </>\n );\n}\n\n// ============================================================================\n// Waveform Animation (for recording state)\n// ============================================================================\n\nfunction WaveformBars({ size }: { size: RecordButtonSize }) {\n const barHeight = size === 'sm' ? 'h-2' : size === 'md' ? 'h-3' : 'h-4';\n // rem fallback (matching the Tailwind utility values: h-2/h-3/h-4) so the\n // bars still render if the consuming app's CSS build does not include these\n // size utilities. Using rem (not px) keeps scaling consistent with the\n // utilities and lets condensed `!important` overrides still win.\n const barHeightRem =\n size === 'sm' ? '0.5rem' : size === 'md' ? '0.75rem' : '1rem';\n\n return (\n <div\n data-slot=\"record-button-waveform\"\n className=\"flex items-center gap-0.5\"\n >\n {[0, 1, 2, 3, 4].map((i) => (\n <span\n key={i}\n className={cn(\n 'animate-waveform w-0.5 rounded-full bg-current',\n barHeight\n )}\n style={{\n width: '0.125rem',\n height: barHeightRem,\n animationDelay: `${i * 0.1}s`,\n }}\n />\n ))}\n </div>\n );\n}\n\n// ============================================================================\n// Style Variants\n// ============================================================================\n\nconst recordButtonVariants = cva(\n [\n 'relative inline-flex items-center justify-center rounded-full',\n 'transition-all duration-200',\n 'outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background',\n ],\n {\n variants: {\n variant: {\n default: '',\n outline: 'border-2',\n ghost: '',\n minimal: '',\n },\n size: {\n sm: 'size-10',\n md: 'size-12',\n lg: 'size-14',\n },\n },\n defaultVariants: {\n variant: 'default',\n size: 'md',\n },\n }\n);\n\nconst iconSizes: Record<RecordButtonSize, string> = {\n sm: 'size-4',\n md: 'size-5',\n lg: 'size-6',\n};\n\n// Intrinsic px sizes mirroring `iconSizes`, applied as width/height attributes\n// so the icons render at the correct size even when a consuming app's CSS build\n// does not include the Tailwind size utilities (e.g. it only scans its own\n// source and not node_modules/@mieweb/ui).\nconst iconPxSizes: Record<RecordButtonSize, number> = {\n sm: 16,\n md: 20,\n lg: 24,\n};\n\n// ============================================================================\n// State Styles\n// ============================================================================\n\nfunction getStateStyles(\n state: RecordButtonState,\n variant: RecordButtonVariant\n): string {\n const styles: Record<\n RecordButtonVariant,\n Record<RecordButtonState, string>\n > = {\n default: {\n idle: 'bg-primary/10 text-primary hover:bg-primary/20',\n recording: 'bg-red-500/10 text-red-500 hover:bg-red-500/20',\n processing: 'bg-primary/10 text-primary cursor-wait',\n disabled: 'bg-muted text-muted-foreground cursor-not-allowed opacity-50',\n error: 'bg-destructive/10 text-destructive',\n success: 'bg-success/10 text-success',\n },\n outline: {\n idle: 'border-primary/50 text-primary bg-transparent hover:bg-primary/10 hover:border-primary',\n recording:\n 'border-red-500/50 text-red-500 bg-transparent hover:bg-red-500/10 hover:border-red-500',\n processing: 'border-primary/50 text-primary bg-transparent cursor-wait',\n disabled:\n 'border-muted text-muted-foreground bg-transparent cursor-not-allowed opacity-50',\n error: 'border-destructive/50 text-destructive bg-transparent',\n success: 'border-success/50 text-success bg-transparent',\n },\n ghost: {\n idle: 'text-primary hover:bg-primary/10',\n recording: 'text-red-500 hover:bg-red-500/10',\n processing: 'text-primary bg-primary/5 cursor-wait',\n disabled: 'text-muted-foreground cursor-not-allowed opacity-50',\n error: 'text-destructive',\n success: 'text-success',\n },\n minimal: {\n idle: 'text-primary hover:text-primary/80',\n recording: 'text-red-500 hover:text-red-500/80',\n processing: 'text-primary cursor-wait',\n disabled: 'text-muted-foreground/40 cursor-not-allowed',\n error: 'text-destructive',\n success: 'text-success',\n },\n };\n\n return styles[variant][state];\n}\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\nfunction formatDuration(seconds: number): string {\n const mins = Math.floor(seconds / 60);\n const secs = Math.floor(seconds % 60);\n return `${mins}:${secs.toString().padStart(2, '0')}`;\n}\n\n// ============================================================================\n// Main Component\n// ============================================================================\n\n/**\n * A voice recording button with 6 states and 4 visual variants.\n * Supports pulse animations, waveform visualization, and transcription integration.\n *\n * ## Controlled vs Uncontrolled Mode\n *\n * **Uncontrolled mode** (default): The component manages its own recording state.\n * Use `onRecordingComplete`, `onRecordingStart`, and `onRecordingError` callbacks.\n *\n * **Controlled mode**: When the `state` prop is provided, the component becomes\n * controlled and you must manage state changes externally. Note: In controlled mode,\n * the internal MediaRecorder functionality is disabled - you must implement your own\n * recording logic.\n *\n * ## State Precedence\n *\n * When multiple state-controlling props are provided, they follow this precedence:\n * 1. `disabled` prop (highest priority)\n * 2. `transcriptionState` prop\n * 3. `state` prop\n * 4. Internal state (uncontrolled)\n *\n * @example\n * ```tsx\n * // Uncontrolled with recording callbacks\n * <RecordButton\n * onRecordingComplete={(blob, duration) => console.log('Recorded:', blob)}\n * onRecordingError={(error) => console.error('Recording failed:', error)}\n * />\n *\n * // Controlled state (requires external recording implementation)\n * <RecordButton state=\"idle\" onClick={handleClick} />\n *\n * // Different variants\n * <RecordButton variant=\"outline\" size=\"lg\" />\n *\n * // With waveform animation\n * <RecordButton state=\"recording\" showWaveform showPulse />\n * ```\n */\nconst RecordButton = React.forwardRef<HTMLButtonElement, RecordButtonProps>(\n (\n {\n className,\n variant = 'default',\n size = 'md',\n state: controlledState,\n showWaveform = false,\n showPulse = true,\n disabled,\n showDuration = false,\n idleIcon,\n recordingIcon,\n transcriptionState,\n showTranscriptionState = false,\n onRecordingComplete,\n onRecordingStart,\n onRecordingError,\n maxDuration = 0,\n mimeType = 'audio/webm',\n onClick,\n 'aria-label': ariaLabel,\n ...props\n },\n ref\n ) => {\n // Internal state for uncontrolled usage\n const [internalState, setInternalState] =\n React.useState<RecordButtonState>('idle');\n const [duration, setDuration] = React.useState(0);\n\n const mediaRecorderRef = React.useRef<MediaRecorder | null>(null);\n const streamRef = React.useRef<MediaStream | null>(null);\n const chunksRef = React.useRef<Blob[]>([]);\n const timerRef = React.useRef<number | undefined>(undefined);\n const startTimeRef = React.useRef<number>(0);\n const timeoutsRef = React.useRef<NodeJS.Timeout[]>([]);\n\n // Helper to track and manage timeouts\n const addTimeout = (callback: () => void, delay: number) => {\n const id = setTimeout(() => {\n callback();\n // Remove from tracking after execution\n timeoutsRef.current = timeoutsRef.current.filter((t) => t !== id);\n }, delay);\n timeoutsRef.current.push(id);\n return id;\n };\n\n const clearAllTimeouts = () => {\n timeoutsRef.current.forEach(clearTimeout);\n timeoutsRef.current = [];\n };\n\n // Use controlled state if provided, otherwise internal state\n const isControlled = controlledState !== undefined;\n const currentState = isControlled ? controlledState : internalState;\n\n // Map transcription state to button state if provided\n // Precedence: disabled prop → transcriptionState → state prop → internal state\n const effectiveState: RecordButtonState = disabled\n ? 'disabled'\n : transcriptionState === 'error'\n ? 'error'\n : transcriptionState === 'transcribing' ||\n transcriptionState === 'streaming'\n ? 'processing'\n : transcriptionState === 'complete'\n ? 'success'\n : currentState;\n\n // Dev mode warnings for conflicting states\n React.useEffect(() => {\n // Only warn in development\n if (typeof window === 'undefined') return;\n\n // Warn when disabled is true but other state props suggest a different visual state\n if (\n disabled &&\n ((controlledState && controlledState !== 'disabled') ||\n transcriptionState)\n ) {\n console.warn(\n '[RecordButton]: `disabled` prop takes precedence over both `state` and `transcriptionState`. ' +\n 'When `disabled` is true, the button will always appear disabled.'\n );\n }\n\n // Warn when both controlled state and transcriptionState are provided and conflict\n if (controlledState !== undefined && transcriptionState !== undefined) {\n const mappedTranscriptionState: RecordButtonState | undefined =\n transcriptionState === 'error'\n ? 'error'\n : transcriptionState === 'transcribing' ||\n transcriptionState === 'streaming'\n ? 'processing'\n : transcriptionState === 'complete'\n ? 'success'\n : undefined;\n\n if (\n mappedTranscriptionState !== undefined &&\n mappedTranscriptionState !== controlledState\n ) {\n console.warn(\n '[RecordButton]: `transcriptionState` takes precedence over `state`. ' +\n `Received state=\"${controlledState}\" and transcriptionState=\"${transcriptionState}\". ` +\n 'This may lead to unexpected visual states.'\n );\n }\n }\n }, [disabled, controlledState, transcriptionState]);\n\n const iconSize = iconSizes[size];\n const iconPx = iconPxSizes[size];\n const isRecording = effectiveState === 'recording';\n const isDisabled =\n effectiveState === 'disabled' || effectiveState === 'processing';\n\n // Cleanup on unmount\n React.useEffect(() => {\n return () => {\n if (timerRef.current) {\n clearInterval(timerRef.current);\n }\n clearAllTimeouts();\n if (streamRef.current) {\n streamRef.current.getTracks().forEach((track) => track.stop());\n }\n };\n }, []);\n\n const stopRecording = React.useCallback(() => {\n if (timerRef.current) {\n clearInterval(timerRef.current);\n }\n\n if (\n mediaRecorderRef.current &&\n mediaRecorderRef.current.state !== 'inactive'\n ) {\n mediaRecorderRef.current.stop();\n }\n\n if (streamRef.current) {\n streamRef.current.getTracks().forEach((track) => track.stop());\n }\n }, []);\n\n const startRecording = React.useCallback(async () => {\n // Guard: don't start if disabled, already recording, or processing\n if (\n disabled ||\n effectiveState === 'recording' ||\n effectiveState === 'processing'\n )\n return;\n\n try {\n const stream = await navigator.mediaDevices.getUserMedia({\n audio: true,\n });\n streamRef.current = stream;\n\n const options = { mimeType };\n if (!MediaRecorder.isTypeSupported(mimeType)) {\n mediaRecorderRef.current = new MediaRecorder(stream);\n } else {\n mediaRecorderRef.current = new MediaRecorder(stream, options);\n }\n\n chunksRef.current = [];\n\n mediaRecorderRef.current.ondataavailable = (e) => {\n if (e.data.size > 0) {\n chunksRef.current.push(e.data);\n }\n };\n\n mediaRecorderRef.current.onstop = () => {\n if (!isControlled) {\n setInternalState('processing');\n }\n\n const blob = new Blob(chunksRef.current, { type: mimeType });\n const finalDuration = duration;\n\n // Small delay to show processing state\n addTimeout(() => {\n onRecordingComplete?.(blob, finalDuration);\n if (!isControlled) {\n setInternalState('success');\n // Reset to idle after showing success\n addTimeout(() => {\n setInternalState('idle');\n }, 1500);\n }\n setDuration(0);\n }, 200);\n };\n\n mediaRecorderRef.current.start(100);\n startTimeRef.current = Date.now();\n\n if (!isControlled) {\n setInternalState('recording');\n }\n onRecordingStart?.();\n\n timerRef.current = window.setInterval(() => {\n const elapsed = (Date.now() - startTimeRef.current) / 1000;\n setDuration(elapsed);\n\n if (maxDuration > 0 && elapsed >= maxDuration) {\n stopRecording();\n }\n }, 100);\n } catch (error) {\n onRecordingError?.(error as Error);\n if (!isControlled) {\n setInternalState('error');\n // Reset to idle after showing error\n addTimeout(() => {\n setInternalState('idle');\n }, 2000);\n }\n }\n }, [\n disabled,\n effectiveState,\n isControlled,\n mimeType,\n maxDuration,\n duration,\n onRecordingComplete,\n onRecordingStart,\n onRecordingError,\n stopRecording,\n ]);\n\n const handleClick = React.useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n // Call external onClick if provided\n onClick?.(e);\n\n // Handle internal recording logic only if not fully controlled\n if (!isControlled) {\n if (effectiveState === 'recording') {\n stopRecording();\n } else if (effectiveState === 'idle') {\n startRecording();\n }\n }\n },\n [onClick, isControlled, effectiveState, startRecording, stopRecording]\n );\n\n // Determine which icon to show\n const renderIcon = () => {\n switch (effectiveState) {\n case 'recording':\n if (showWaveform) {\n return <WaveformBars size={size} />;\n }\n return (\n recordingIcon || <StopIcon className={iconSize} size={iconPx} />\n );\n case 'processing':\n return <LoadingSpinner className={iconSize} size={iconPx} />;\n case 'disabled':\n case 'error':\n return <MicOffIcon className={iconSize} size={iconPx} />;\n case 'success':\n return <CheckIcon className={iconSize} size={iconPx} />;\n default:\n return idleIcon || <MicIcon className={iconSize} size={iconPx} />;\n }\n };\n\n const getAriaLabel = () => {\n switch (effectiveState) {\n case 'recording':\n return 'Stop recording';\n case 'processing':\n return 'Processing recording';\n case 'disabled':\n return 'Recording unavailable';\n case 'error':\n return 'Recording failed';\n case 'success':\n return 'Recording complete';\n default:\n return 'Start recording';\n }\n };\n\n const getTranscriptionLabel = () => {\n if (transcriptionState === 'streaming') return 'Listening...';\n if (transcriptionState === 'transcribing') return 'Transcribing...';\n return null;\n };\n\n return (\n <div\n data-slot=\"record-button\"\n className=\"relative inline-flex items-center gap-2\"\n >\n <button\n ref={ref}\n type=\"button\"\n disabled={isDisabled}\n onClick={handleClick}\n {...props}\n data-slot=\"record-button-trigger\"\n className={cn(\n recordButtonVariants({ variant, size }),\n getStateStyles(effectiveState, variant),\n className\n )}\n aria-label={ariaLabel ?? getAriaLabel()}\n aria-pressed={effectiveState === 'recording' ? true : undefined}\n aria-busy={effectiveState === 'processing' ? true : undefined}\n >\n {/* Pulse animation for recording state */}\n {effectiveState === 'recording' && showPulse && (\n <PulseRings variant={variant} />\n )}\n\n {/* Icon */}\n <span data-slot=\"record-button-icon\" className=\"relative z-10\">\n {renderIcon()}\n </span>\n </button>\n\n {/* Duration display */}\n {showDuration && isRecording && (\n <span\n data-slot=\"record-button-duration\"\n className=\"text-destructive font-mono text-xs tabular-nums\"\n >\n {formatDuration(duration)}\n </span>\n )}\n\n {/* Transcription state label */}\n {showTranscriptionState && getTranscriptionLabel() && (\n <span\n data-slot=\"record-button-transcription\"\n className=\"text-primary text-xs font-medium\"\n >\n {getTranscriptionLabel()}\n </span>\n )}\n </div>\n );\n }\n);\n\nRecordButton.displayName = 'RecordButton';\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport { RecordButton, recordButtonVariants, formatDuration };\n"]}
@@ -343,5 +343,5 @@ exports.CodeBlock = CodeBlock;
343
343
  exports.MarkdownRenderer = MarkdownRenderer;
344
344
  exports.highlightCode = highlightCode;
345
345
  exports.useMarkdown = useMarkdown;
346
- //# sourceMappingURL=chunk-NAH65KPK.cjs.map
347
- //# sourceMappingURL=chunk-NAH65KPK.cjs.map
346
+ //# sourceMappingURL=chunk-TOJ56HKQ.cjs.map
347
+ //# sourceMappingURL=chunk-TOJ56HKQ.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/Markdown/useMarkdown.ts","../src/components/Markdown/CodeBlock.tsx","../src/components/Markdown/MarkdownRenderer.tsx"],"names":["hljs","javascript","typescript","python","json","xml","css","bash","sql","yaml","markdown","DOMPurify","marked","useRef","useCallback","useMemo","jsx","FenceBlock","lazy","Suspense","useState","useEffect"],"mappings":"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","file":"chunk-NAH65KPK.cjs","sourcesContent":["/** useMarkdown — converts markdown to sanitised HTML with hljs highlighting and special fence blocks. */\nimport DOMPurify from 'dompurify';\nimport hljs from 'highlight.js/lib/core';\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n}\nimport bash from 'highlight.js/lib/languages/bash';\nimport css from 'highlight.js/lib/languages/css';\nimport javascript from 'highlight.js/lib/languages/javascript';\nimport json from 'highlight.js/lib/languages/json';\nimport markdown from 'highlight.js/lib/languages/markdown';\nimport python from 'highlight.js/lib/languages/python';\nimport sql from 'highlight.js/lib/languages/sql';\nimport typescript from 'highlight.js/lib/languages/typescript';\nimport xml from 'highlight.js/lib/languages/xml';\nimport yaml from 'highlight.js/lib/languages/yaml';\nimport { marked, type MarkedOptions, type Tokens } from 'marked';\nimport { useCallback, useMemo, useRef } from 'react';\n\nhljs.registerLanguage('javascript', javascript);\nhljs.registerLanguage('typescript', typescript);\nhljs.registerLanguage('python', python);\nhljs.registerLanguage('json', json);\nhljs.registerLanguage('xml', xml);\nhljs.registerLanguage('html', xml);\nhljs.registerLanguage('css', css);\nhljs.registerLanguage('bash', bash);\nhljs.registerLanguage('shell', bash);\nhljs.registerLanguage('sql', sql);\nhljs.registerLanguage('yaml', yaml);\nhljs.registerLanguage('yml', yaml);\nhljs.registerLanguage('markdown', markdown);\nhljs.registerLanguage('md', markdown);\n\nconst lazyLanguages: Record<string, () => Promise<unknown>> = {\n java: () => import('highlight.js/lib/languages/java'),\n cpp: () => import('highlight.js/lib/languages/cpp'),\n 'c++': () => import('highlight.js/lib/languages/cpp'),\n c: () => import('highlight.js/lib/languages/c'),\n csharp: () => import('highlight.js/lib/languages/csharp'),\n php: () => import('highlight.js/lib/languages/php'),\n ruby: () => import('highlight.js/lib/languages/ruby'),\n go: () => import('highlight.js/lib/languages/go'),\n rust: () => import('highlight.js/lib/languages/rust'),\n perl: () => import('highlight.js/lib/languages/perl'),\n r: () => import('highlight.js/lib/languages/r'),\n makefile: () => import('highlight.js/lib/languages/makefile'),\n dockerfile: () => import('highlight.js/lib/languages/dockerfile'),\n};\n\nconst loadedLanguages = new Set<string>([\n 'javascript',\n 'typescript',\n 'python',\n 'json',\n 'xml',\n 'html',\n 'css',\n 'bash',\n 'shell',\n 'sql',\n 'yaml',\n 'yml',\n 'markdown',\n 'md',\n]);\n\nasync function ensureLanguage(lang: string): Promise<boolean> {\n const key = lang.toLowerCase();\n if (loadedLanguages.has(key)) return true;\n const loader = lazyLanguages[key];\n if (!loader) return false;\n try {\n const mod = (await loader()) as { default: unknown };\n hljs.registerLanguage(\n key,\n mod.default as Parameters<typeof hljs.registerLanguage>[1]\n );\n loadedLanguages.add(key);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function highlightCode(code: string, lang?: string): string {\n if (lang && loadedLanguages.has(lang.toLowerCase())) {\n try {\n return hljs.highlight(code, { language: lang.toLowerCase() }).value;\n } catch {\n /* fall through */\n }\n }\n try {\n const result = hljs.highlightAuto(code);\n if (result.relevance > 5) return result.value;\n } catch {\n /* fall through */\n }\n return escapeHtml(code);\n}\n\nfunction sanitise(html: string): string {\n return DOMPurify.sanitize(html, {\n ADD_ATTR: [\n 'target',\n 'rel',\n 'data-block-type',\n 'data-block-id',\n 'data-code',\n 'data-lang',\n 'data-md-fence',\n ],\n }) as string;\n}\n\n// Use globalThis to prevent duplicate DOMPurify hook registration across HMR reloads.\nconst _g = globalThis as unknown as Record<string, boolean>;\n// Guard against SSR: DOMPurify hooks operate on the DOM, so only register in the browser.\nif (typeof document !== 'undefined' && !_g.__markdownAnchorHookInstalled) {\n _g.__markdownAnchorHookInstalled = true;\n DOMPurify.addHook('afterSanitizeAttributes', (node: Element) => {\n const isAnchor =\n (typeof HTMLAnchorElement !== 'undefined' &&\n node instanceof HTMLAnchorElement) ||\n node.nodeName === 'A';\n if (isAnchor) {\n node.setAttribute('target', '_blank');\n node.setAttribute('rel', 'noopener noreferrer');\n }\n });\n}\n\nlet blockCounter = 0;\n\nfunction createRenderer() {\n const renderer = new marked.Renderer();\n\n renderer.code = function (this: unknown, token: Tokens.Code) {\n const { text: code, lang = '' } = token;\n const normalised = lang.toLowerCase().trim();\n const blockId = `block-${++blockCounter}`;\n const encodedCode = encodeURIComponent(code);\n const sentinel = 'data-md-fence=\"1\"';\n\n switch (normalised) {\n case 'mermaid':\n return `<div data-block-type=\"mermaid\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" ${sentinel}></div>`;\n case 'csv':\n return `<div data-block-type=\"csv\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" ${sentinel}></div>`;\n case 'survey':\n return `<div data-block-type=\"survey\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" ${sentinel}></div>`;\n case 'html':\n return `<div data-block-type=\"html-preview\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" ${sentinel}></div>`;\n default:\n return `<div data-block-type=\"code\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" data-lang=\"${escapeHtml(normalised)}\" ${sentinel}></div>`;\n }\n };\n\n renderer.link = function (this: unknown, token: Tokens.Link) {\n const { href, title, tokens } = token;\n const text =\n this && typeof (this as Record<string, unknown>).parser === 'object'\n ? (\n this as {\n parser: { parseInline: (t: Tokens.Link['tokens']) => string };\n }\n ).parser.parseInline(tokens)\n : token.text;\n const titleAttr = title ? ` title=\"${escapeHtml(title)}\"` : '';\n return `<a href=\"${escapeHtml(href)}\" target=\"_blank\" rel=\"noopener noreferrer\"${titleAttr}>${text}</a>`;\n };\n\n renderer.table = function (this: unknown, token: Tokens.Table) {\n const headerCells = token.header\n .map((cell) => {\n const content =\n this && typeof (this as Record<string, unknown>).parser === 'object'\n ? (\n this as {\n parser: {\n parseInline: (t: Tokens.TableCell['tokens']) => string;\n };\n }\n ).parser.parseInline(cell.tokens)\n : cell.text;\n return `<th>${content}</th>`;\n })\n .join('');\n\n const bodyRows = token.rows\n .map((row) => {\n const cells = row\n .map((cell) => {\n const content =\n this &&\n typeof (this as Record<string, unknown>).parser === 'object'\n ? (\n this as {\n parser: {\n parseInline: (t: Tokens.TableCell['tokens']) => string;\n };\n }\n ).parser.parseInline(cell.tokens)\n : cell.text;\n return `<td>${content}</td>`;\n })\n .join('');\n return `<tr>${cells}</tr>`;\n })\n .join('');\n\n return `<div class=\"overflow-x-auto\"><table class=\"min-w-full divide-y divide-neutral-200 dark:divide-neutral-700\"><thead><tr>${headerCells}</tr></thead><tbody class=\"divide-y divide-neutral-200 dark:divide-neutral-700\">${bodyRows}</tbody></table></div>`;\n };\n\n return renderer;\n}\n\nfunction makeMarkedOptions(): MarkedOptions {\n return { gfm: true, breaks: true, renderer: createRenderer() };\n}\n\nconst CACHE_MAX = 100;\nconst renderCache = new Map<string, string>();\nfunction cacheSet(key: string, value: string) {\n if (renderCache.size >= CACHE_MAX) {\n renderCache.delete(renderCache.keys().next().value as string);\n }\n renderCache.set(key, value);\n}\n\nexport interface UseMarkdownResult {\n /** Render markdown text to sanitised HTML string */\n render: (text: string, cacheKey?: string) => string;\n /** Async-render that lazy-loads needed languages first */\n renderAsync: (text: string, cacheKey?: string) => Promise<string>;\n /** Clear the render cache */\n clearCache: () => void;\n}\n\nexport function useMarkdown(): UseMarkdownResult {\n const cacheRef = useRef(renderCache);\n\n const render = useCallback((text: string, cacheKey?: string): string => {\n if (!text) return '';\n const key = cacheKey ?? text;\n const cached = cacheRef.current.get(key);\n if (cached) return cached;\n\n const raw = marked.parse(text, {\n ...makeMarkedOptions(),\n async: false,\n }) as string;\n const clean = sanitise(raw);\n cacheSet(key, clean);\n return clean;\n }, []);\n\n const renderAsync = useCallback(\n async (text: string, cacheKey?: string): Promise<string> => {\n if (!text) return '';\n const key = cacheKey ?? text;\n const cached = cacheRef.current.get(key);\n if (cached) return cached;\n\n // Allow `+`, `-`, `.` in language identifiers (c++, objective-c, bash-session, etc.)\n const fenceRegex = /^```([\\w+\\-.]+)\\s*$/gm;\n let match: RegExpExecArray | null;\n const langs: string[] = [];\n while ((match = fenceRegex.exec(text)) !== null) {\n langs.push(match[1]);\n }\n await Promise.all(langs.map((l) => ensureLanguage(l)));\n\n const raw = await marked.parse(text, makeMarkedOptions());\n const clean = sanitise(raw);\n cacheSet(key, clean);\n return clean;\n },\n []\n );\n\n const clearCache = useCallback(() => {\n cacheRef.current.clear();\n }, []);\n\n return useMemo(\n () => ({ render, renderAsync, clearCache }),\n [render, renderAsync, clearCache]\n );\n}\n","/**\n * CodeBlock — Renders a syntax-highlighted code fence using FenceBlock.\n *\n * Used by `MarkdownRenderer` for plain (non-special) fenced code blocks.\n * Highlighting is performed synchronously via the `highlightCode` helper from\n * `useMarkdown`; if the language was not pre-registered with highlight.js the\n * helper falls back to escaped raw text.\n */\nimport React, { useMemo } from 'react';\n\nimport { FenceBlock } from './FenceBlock';\nimport { highlightCode } from './useMarkdown';\n\ninterface CodeBlockProps {\n code: string;\n language?: string;\n}\n\nexport const CodeBlock: React.FC<CodeBlockProps> = ({ code, language }) => {\n const html = useMemo(() => highlightCode(code, language), [code, language]);\n\n return (\n <FenceBlock code={code} language={language}>\n {/* Focusable so keyboard users can horizontally scroll long lines\n (axe: scrollable-region-focusable). */}\n <pre\n className=\"m-0 overflow-x-auto !bg-transparent p-3 text-sm\"\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex -- scrollable code needs keyboard focus\n tabIndex={0}\n role=\"region\"\n aria-label={language ? `${language} code` : 'Code'}\n >\n <code\n className=\"hljs bg-transparent p-0\"\n dangerouslySetInnerHTML={{ __html: html }}\n />\n </pre>\n </FenceBlock>\n );\n};\n","/**\n * MarkdownRenderer — renders markdown with React components for special fence blocks.\n */\nimport React, { Suspense, lazy, useEffect, useState } from 'react';\n\nimport './styles.css';\nimport { CodeBlock } from './CodeBlock';\nimport { useMarkdown } from './useMarkdown';\n\n// Block components are lazy-loaded so optional peer deps (papaparse, js-yaml, mermaid)\n// aren't bundled unless actually rendered.\nconst CsvBlock = lazy(() =>\n import('./CsvBlock').then((m) => ({ default: m.CsvBlock }))\n);\nconst HtmlPreviewBlock = lazy(() =>\n import('./HtmlPreviewBlock').then((m) => ({ default: m.HtmlPreviewBlock }))\n);\nconst MermaidBlock = lazy(() =>\n import('./MermaidBlock').then((m) => ({ default: m.MermaidBlock }))\n);\nconst SurveyBlock = lazy(() =>\n import('./SurveyBlock').then((m) => ({ default: m.SurveyBlock }))\n);\n\nconst BlockFallback: React.FC = () => (\n <div className=\"flex items-center justify-center p-4 text-sm text-neutral-500\">\n Loading…\n </div>\n);\n\nexport interface MarkdownRendererProps {\n /** Raw markdown text */\n text: string;\n /** Cache key (e.g., message._id + revisionNumber) */\n cacheKey?: string;\n /** Additional CSS classes */\n className?: string;\n /** Whether the message is still streaming (may have incomplete blocks) */\n streaming?: boolean;\n}\n\n// Matches fence block markers emitted by useMarkdown (sentinel data-md-fence prevents raw-HTML injection)\nconst BLOCK_RE =\n /<div data-block-type=\"([^\"]+)\" data-block-id=\"([^\"]+)\" data-code=\"([^\"]*)\"([^>]*\\bdata-md-fence=\"1\"[^>]*)><\\/div>/g;\n\ninterface HtmlSegment {\n html: string;\n}\ninterface BlockSegment {\n type: string;\n id: string;\n code: string;\n lang?: string;\n}\ntype Segment = HtmlSegment | BlockSegment;\n\nfunction splitHtml(html: string): Segment[] {\n const segments: Segment[] = [];\n let last = 0;\n for (const m of html.matchAll(BLOCK_RE)) {\n if (m.index > last) segments.push({ html: html.slice(last, m.index) });\n const langMatch = m[4]?.match(/data-lang=\"([^\"]*)\"/)?.[1];\n segments.push({\n type: m[1],\n id: m[2],\n code: (() => {\n try {\n return decodeURIComponent(m[3]);\n } catch {\n return m[3];\n }\n })(),\n lang: langMatch ?? undefined,\n });\n last = m.index + m[0].length;\n }\n if (last < html.length) segments.push({ html: html.slice(last) });\n return segments;\n}\n\nfunction renderBlock(seg: BlockSegment): React.ReactNode {\n const wrap = (node: React.ReactNode) => (\n <Suspense key={seg.id} fallback={<BlockFallback />}>\n {node}\n </Suspense>\n );\n switch (seg.type) {\n case 'mermaid':\n return wrap(<MermaidBlock code={seg.code} id={seg.id} />);\n case 'csv':\n return wrap(<CsvBlock code={seg.code} id={seg.id} />);\n case 'survey':\n return wrap(<SurveyBlock code={seg.code} id={seg.id} />);\n case 'html-preview':\n return wrap(<HtmlPreviewBlock code={seg.code} id={seg.id} />);\n case 'code':\n return wrap(\n <CodeBlock code={seg.code} language={seg.lang || undefined} />\n );\n default:\n return null;\n }\n}\n\nexport const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({\n text,\n cacheKey,\n className = '',\n streaming = false,\n}) => {\n const { render, renderAsync } = useMarkdown();\n const [html, setHtml] = useState('');\n\n useEffect(() => {\n let cancelled = false;\n\n // While streaming, append text length to the cache key so each delta\n // produces a fresh render rather than a stale hit on the messageId.\n const effectiveKey = streaming\n ? cacheKey\n ? `${cacheKey}::${text.length}`\n : undefined\n : cacheKey;\n\n async function doRender() {\n const rendered = await renderAsync(text, effectiveKey);\n if (!cancelled) setHtml(rendered);\n }\n\n if (streaming) {\n setHtml(render(text, effectiveKey));\n } else {\n void doRender();\n }\n\n return () => {\n cancelled = true;\n };\n }, [text, cacheKey, streaming, render, renderAsync]);\n\n const segments = splitHtml(html);\n const proseClass = `md-prose ${className}`.trim();\n\n return (\n <div className={proseClass}>\n {segments.map((seg, i) =>\n 'html' in seg ? (\n <div key={i} dangerouslySetInnerHTML={{ __html: seg.html }} />\n ) : (\n renderBlock(seg)\n )\n )}\n </div>\n );\n};\n"]}
1
+ {"version":3,"sources":["../src/components/Markdown/useMarkdown.ts","../src/components/Markdown/CodeBlock.tsx","../src/components/Markdown/MarkdownRenderer.tsx"],"names":["hljs","javascript","typescript","python","json","xml","css","bash","sql","yaml","markdown","DOMPurify","marked","useRef","useCallback","useMemo","jsx","FenceBlock","lazy","Suspense","useState","useEffect"],"mappings":"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","file":"chunk-TOJ56HKQ.cjs","sourcesContent":["/** useMarkdown — converts markdown to sanitised HTML with hljs highlighting and special fence blocks. */\nimport DOMPurify from 'dompurify';\nimport hljs from 'highlight.js/lib/core';\n\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n}\nimport bash from 'highlight.js/lib/languages/bash';\nimport css from 'highlight.js/lib/languages/css';\nimport javascript from 'highlight.js/lib/languages/javascript';\nimport json from 'highlight.js/lib/languages/json';\nimport markdown from 'highlight.js/lib/languages/markdown';\nimport python from 'highlight.js/lib/languages/python';\nimport sql from 'highlight.js/lib/languages/sql';\nimport typescript from 'highlight.js/lib/languages/typescript';\nimport xml from 'highlight.js/lib/languages/xml';\nimport yaml from 'highlight.js/lib/languages/yaml';\nimport { marked, type MarkedOptions, type Tokens } from 'marked';\nimport { useCallback, useMemo, useRef } from 'react';\n\nhljs.registerLanguage('javascript', javascript);\nhljs.registerLanguage('typescript', typescript);\nhljs.registerLanguage('python', python);\nhljs.registerLanguage('json', json);\nhljs.registerLanguage('xml', xml);\nhljs.registerLanguage('html', xml);\nhljs.registerLanguage('css', css);\nhljs.registerLanguage('bash', bash);\nhljs.registerLanguage('shell', bash);\nhljs.registerLanguage('sql', sql);\nhljs.registerLanguage('yaml', yaml);\nhljs.registerLanguage('yml', yaml);\nhljs.registerLanguage('markdown', markdown);\nhljs.registerLanguage('md', markdown);\n\nconst lazyLanguages: Record<string, () => Promise<unknown>> = {\n java: () => import('highlight.js/lib/languages/java'),\n cpp: () => import('highlight.js/lib/languages/cpp'),\n 'c++': () => import('highlight.js/lib/languages/cpp'),\n c: () => import('highlight.js/lib/languages/c'),\n csharp: () => import('highlight.js/lib/languages/csharp'),\n php: () => import('highlight.js/lib/languages/php'),\n ruby: () => import('highlight.js/lib/languages/ruby'),\n go: () => import('highlight.js/lib/languages/go'),\n rust: () => import('highlight.js/lib/languages/rust'),\n perl: () => import('highlight.js/lib/languages/perl'),\n r: () => import('highlight.js/lib/languages/r'),\n makefile: () => import('highlight.js/lib/languages/makefile'),\n dockerfile: () => import('highlight.js/lib/languages/dockerfile'),\n};\n\nconst loadedLanguages = new Set<string>([\n 'javascript',\n 'typescript',\n 'python',\n 'json',\n 'xml',\n 'html',\n 'css',\n 'bash',\n 'shell',\n 'sql',\n 'yaml',\n 'yml',\n 'markdown',\n 'md',\n]);\n\nasync function ensureLanguage(lang: string): Promise<boolean> {\n const key = lang.toLowerCase();\n if (loadedLanguages.has(key)) return true;\n const loader = lazyLanguages[key];\n if (!loader) return false;\n try {\n const mod = (await loader()) as { default: unknown };\n hljs.registerLanguage(\n key,\n mod.default as Parameters<typeof hljs.registerLanguage>[1]\n );\n loadedLanguages.add(key);\n return true;\n } catch {\n return false;\n }\n}\n\nexport function highlightCode(code: string, lang?: string): string {\n if (lang && loadedLanguages.has(lang.toLowerCase())) {\n try {\n return hljs.highlight(code, { language: lang.toLowerCase() }).value;\n } catch {\n /* fall through */\n }\n }\n try {\n const result = hljs.highlightAuto(code);\n if (result.relevance > 5) return result.value;\n } catch {\n /* fall through */\n }\n return escapeHtml(code);\n}\n\nfunction sanitise(html: string): string {\n return DOMPurify.sanitize(html, {\n ADD_ATTR: [\n 'target',\n 'rel',\n 'data-block-type',\n 'data-block-id',\n 'data-code',\n 'data-lang',\n 'data-md-fence',\n ],\n }) as string;\n}\n\n// Use globalThis to prevent duplicate DOMPurify hook registration across HMR reloads.\nconst _g = globalThis as unknown as Record<string, boolean>;\n// Guard against SSR: DOMPurify hooks operate on the DOM, so only register in the browser.\nif (typeof document !== 'undefined' && !_g.__markdownAnchorHookInstalled) {\n _g.__markdownAnchorHookInstalled = true;\n DOMPurify.addHook('afterSanitizeAttributes', (node: Element) => {\n const isAnchor =\n (typeof HTMLAnchorElement !== 'undefined' &&\n node instanceof HTMLAnchorElement) ||\n node.nodeName === 'A';\n if (isAnchor) {\n node.setAttribute('target', '_blank');\n node.setAttribute('rel', 'noopener noreferrer');\n }\n });\n}\n\nlet blockCounter = 0;\n\nfunction createRenderer() {\n const renderer = new marked.Renderer();\n\n renderer.code = function (this: unknown, token: Tokens.Code) {\n const { text: code, lang = '' } = token;\n const normalised = lang.toLowerCase().trim();\n const blockId = `block-${++blockCounter}`;\n const encodedCode = encodeURIComponent(code);\n const sentinel = 'data-md-fence=\"1\"';\n\n switch (normalised) {\n case 'mermaid':\n return `<div data-block-type=\"mermaid\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" ${sentinel}></div>`;\n case 'csv':\n return `<div data-block-type=\"csv\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" ${sentinel}></div>`;\n case 'survey':\n return `<div data-block-type=\"survey\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" ${sentinel}></div>`;\n case 'html':\n return `<div data-block-type=\"html-preview\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" ${sentinel}></div>`;\n default:\n return `<div data-block-type=\"code\" data-block-id=\"${blockId}\" data-code=\"${encodedCode}\" data-lang=\"${escapeHtml(normalised)}\" ${sentinel}></div>`;\n }\n };\n\n renderer.link = function (this: unknown, token: Tokens.Link) {\n const { href, title, tokens } = token;\n const text =\n this && typeof (this as Record<string, unknown>).parser === 'object'\n ? (\n this as {\n parser: { parseInline: (t: Tokens.Link['tokens']) => string };\n }\n ).parser.parseInline(tokens)\n : token.text;\n const titleAttr = title ? ` title=\"${escapeHtml(title)}\"` : '';\n return `<a href=\"${escapeHtml(href)}\" target=\"_blank\" rel=\"noopener noreferrer\"${titleAttr}>${text}</a>`;\n };\n\n renderer.table = function (this: unknown, token: Tokens.Table) {\n const headerCells = token.header\n .map((cell) => {\n const content =\n this && typeof (this as Record<string, unknown>).parser === 'object'\n ? (\n this as {\n parser: {\n parseInline: (t: Tokens.TableCell['tokens']) => string;\n };\n }\n ).parser.parseInline(cell.tokens)\n : cell.text;\n return `<th>${content}</th>`;\n })\n .join('');\n\n const bodyRows = token.rows\n .map((row) => {\n const cells = row\n .map((cell) => {\n const content =\n this &&\n typeof (this as Record<string, unknown>).parser === 'object'\n ? (\n this as {\n parser: {\n parseInline: (t: Tokens.TableCell['tokens']) => string;\n };\n }\n ).parser.parseInline(cell.tokens)\n : cell.text;\n return `<td>${content}</td>`;\n })\n .join('');\n return `<tr>${cells}</tr>`;\n })\n .join('');\n\n return `<div class=\"overflow-x-auto\"><table class=\"min-w-full divide-y divide-neutral-200 dark:divide-neutral-700\"><thead><tr>${headerCells}</tr></thead><tbody class=\"divide-y divide-neutral-200 dark:divide-neutral-700\">${bodyRows}</tbody></table></div>`;\n };\n\n return renderer;\n}\n\nfunction makeMarkedOptions(): MarkedOptions {\n return { gfm: true, breaks: true, renderer: createRenderer() };\n}\n\nconst CACHE_MAX = 100;\nconst renderCache = new Map<string, string>();\nfunction cacheSet(key: string, value: string) {\n if (renderCache.size >= CACHE_MAX) {\n renderCache.delete(renderCache.keys().next().value as string);\n }\n renderCache.set(key, value);\n}\n\nexport interface UseMarkdownResult {\n /** Render markdown text to sanitised HTML string */\n render: (text: string, cacheKey?: string) => string;\n /** Async-render that lazy-loads needed languages first */\n renderAsync: (text: string, cacheKey?: string) => Promise<string>;\n /** Clear the render cache */\n clearCache: () => void;\n}\n\nexport function useMarkdown(): UseMarkdownResult {\n const cacheRef = useRef(renderCache);\n\n const render = useCallback((text: string, cacheKey?: string): string => {\n if (!text) return '';\n const key = cacheKey ?? text;\n const cached = cacheRef.current.get(key);\n if (cached) return cached;\n\n const raw = marked.parse(text, {\n ...makeMarkedOptions(),\n async: false,\n }) as string;\n const clean = sanitise(raw);\n cacheSet(key, clean);\n return clean;\n }, []);\n\n const renderAsync = useCallback(\n async (text: string, cacheKey?: string): Promise<string> => {\n if (!text) return '';\n const key = cacheKey ?? text;\n const cached = cacheRef.current.get(key);\n if (cached) return cached;\n\n // Allow `+`, `-`, `.` in language identifiers (c++, objective-c, bash-session, etc.)\n const fenceRegex = /^```([\\w+\\-.]+)\\s*$/gm;\n let match: RegExpExecArray | null;\n const langs: string[] = [];\n while ((match = fenceRegex.exec(text)) !== null) {\n langs.push(match[1]);\n }\n await Promise.all(langs.map((l) => ensureLanguage(l)));\n\n const raw = await marked.parse(text, makeMarkedOptions());\n const clean = sanitise(raw);\n cacheSet(key, clean);\n return clean;\n },\n []\n );\n\n const clearCache = useCallback(() => {\n cacheRef.current.clear();\n }, []);\n\n return useMemo(\n () => ({ render, renderAsync, clearCache }),\n [render, renderAsync, clearCache]\n );\n}\n","/**\n * CodeBlock — Renders a syntax-highlighted code fence using FenceBlock.\n *\n * Used by `MarkdownRenderer` for plain (non-special) fenced code blocks.\n * Highlighting is performed synchronously via the `highlightCode` helper from\n * `useMarkdown`; if the language was not pre-registered with highlight.js the\n * helper falls back to escaped raw text.\n */\nimport React, { useMemo } from 'react';\n\nimport { FenceBlock } from './FenceBlock';\nimport { highlightCode } from './useMarkdown';\n\ninterface CodeBlockProps {\n code: string;\n language?: string;\n}\n\nexport const CodeBlock: React.FC<CodeBlockProps> = ({ code, language }) => {\n const html = useMemo(() => highlightCode(code, language), [code, language]);\n\n return (\n <FenceBlock code={code} language={language}>\n {/* Focusable so keyboard users can horizontally scroll long lines\n (axe: scrollable-region-focusable). */}\n <pre\n className=\"m-0 overflow-x-auto !bg-transparent p-3 text-sm\"\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex -- scrollable code needs keyboard focus\n tabIndex={0}\n role=\"region\"\n aria-label={language ? `${language} code` : 'Code'}\n >\n <code\n className=\"hljs bg-transparent p-0\"\n dangerouslySetInnerHTML={{ __html: html }}\n />\n </pre>\n </FenceBlock>\n );\n};\n","/**\n * MarkdownRenderer — renders markdown with React components for special fence blocks.\n */\nimport React, { Suspense, lazy, useEffect, useState } from 'react';\n\nimport './styles.css';\nimport { CodeBlock } from './CodeBlock';\nimport { useMarkdown } from './useMarkdown';\n\n// Block components are lazy-loaded so optional peer deps (papaparse, js-yaml, mermaid)\n// aren't bundled unless actually rendered.\nconst CsvBlock = lazy(() =>\n import('./CsvBlock').then((m) => ({ default: m.CsvBlock }))\n);\nconst HtmlPreviewBlock = lazy(() =>\n import('./HtmlPreviewBlock').then((m) => ({ default: m.HtmlPreviewBlock }))\n);\nconst MermaidBlock = lazy(() =>\n import('./MermaidBlock').then((m) => ({ default: m.MermaidBlock }))\n);\nconst SurveyBlock = lazy(() =>\n import('./SurveyBlock').then((m) => ({ default: m.SurveyBlock }))\n);\n\nconst BlockFallback: React.FC = () => (\n <div className=\"flex items-center justify-center p-4 text-sm text-neutral-500\">\n Loading…\n </div>\n);\n\nexport interface MarkdownRendererProps {\n /** Raw markdown text */\n text: string;\n /** Cache key (e.g., message._id + revisionNumber) */\n cacheKey?: string;\n /** Additional CSS classes */\n className?: string;\n /** Whether the message is still streaming (may have incomplete blocks) */\n streaming?: boolean;\n}\n\n// Matches fence block markers emitted by useMarkdown (sentinel data-md-fence prevents raw-HTML injection)\nconst BLOCK_RE =\n /<div data-block-type=\"([^\"]+)\" data-block-id=\"([^\"]+)\" data-code=\"([^\"]*)\"([^>]*\\bdata-md-fence=\"1\"[^>]*)><\\/div>/g;\n\ninterface HtmlSegment {\n html: string;\n}\ninterface BlockSegment {\n type: string;\n id: string;\n code: string;\n lang?: string;\n}\ntype Segment = HtmlSegment | BlockSegment;\n\nfunction splitHtml(html: string): Segment[] {\n const segments: Segment[] = [];\n let last = 0;\n for (const m of html.matchAll(BLOCK_RE)) {\n if (m.index > last) segments.push({ html: html.slice(last, m.index) });\n const langMatch = m[4]?.match(/data-lang=\"([^\"]*)\"/)?.[1];\n segments.push({\n type: m[1],\n id: m[2],\n code: (() => {\n try {\n return decodeURIComponent(m[3]);\n } catch {\n return m[3];\n }\n })(),\n lang: langMatch ?? undefined,\n });\n last = m.index + m[0].length;\n }\n if (last < html.length) segments.push({ html: html.slice(last) });\n return segments;\n}\n\nfunction renderBlock(seg: BlockSegment): React.ReactNode {\n const wrap = (node: React.ReactNode) => (\n <Suspense key={seg.id} fallback={<BlockFallback />}>\n {node}\n </Suspense>\n );\n switch (seg.type) {\n case 'mermaid':\n return wrap(<MermaidBlock code={seg.code} id={seg.id} />);\n case 'csv':\n return wrap(<CsvBlock code={seg.code} id={seg.id} />);\n case 'survey':\n return wrap(<SurveyBlock code={seg.code} id={seg.id} />);\n case 'html-preview':\n return wrap(<HtmlPreviewBlock code={seg.code} id={seg.id} />);\n case 'code':\n return wrap(\n <CodeBlock code={seg.code} language={seg.lang || undefined} />\n );\n default:\n return null;\n }\n}\n\nexport const MarkdownRenderer: React.FC<MarkdownRendererProps> = ({\n text,\n cacheKey,\n className = '',\n streaming = false,\n}) => {\n const { render, renderAsync } = useMarkdown();\n const [html, setHtml] = useState('');\n\n useEffect(() => {\n let cancelled = false;\n\n // While streaming, append text length to the cache key so each delta\n // produces a fresh render rather than a stale hit on the messageId.\n const effectiveKey = streaming\n ? cacheKey\n ? `${cacheKey}::${text.length}`\n : undefined\n : cacheKey;\n\n async function doRender() {\n const rendered = await renderAsync(text, effectiveKey);\n if (!cancelled) setHtml(rendered);\n }\n\n if (streaming) {\n setHtml(render(text, effectiveKey));\n } else {\n void doRender();\n }\n\n return () => {\n cancelled = true;\n };\n }, [text, cacheKey, streaming, render, renderAsync]);\n\n const segments = splitHtml(html);\n const proseClass = `md-prose ${className}`.trim();\n\n return (\n <div className={proseClass}>\n {segments.map((seg, i) =>\n 'html' in seg ? (\n <div key={i} dangerouslySetInnerHTML={{ __html: seg.html }} />\n ) : (\n renderBlock(seg)\n )\n )}\n </div>\n );\n};\n"]}