@alfadocs/ui-kit-debug 1.41.0 → 1.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/dist/_chunks/{calendar-workspace-UllCER2k.js → calendar-workspace-qlxrxCqm.js} +1980 -1967
  2. package/dist/_chunks/calendar-workspace-qlxrxCqm.js.map +1 -0
  3. package/dist/_chunks/{help-me-write-templates-GB70jnV9.js → help-me-write-templates-B-m7zgJa.js} +242 -231
  4. package/dist/_chunks/help-me-write-templates-B-m7zgJa.js.map +1 -0
  5. package/dist/_chunks/{notes-panel-_diLt8Cj.js → notes-panel-CRAovkjx.js} +84 -68
  6. package/dist/_chunks/notes-panel-CRAovkjx.js.map +1 -0
  7. package/dist/_chunks/{rich-text-editor-D7AKKAQ2.js → rich-text-editor-DUMeifwc.js} +1195 -1138
  8. package/dist/_chunks/rich-text-editor-DUMeifwc.js.map +1 -0
  9. package/dist/agent-catalog.json +1 -1
  10. package/dist/components/notes-panel/index.js +1 -1
  11. package/dist/components/notes-panel/notes-panel.d.ts +32 -0
  12. package/dist/components/notes-panel/notes-panel.d.ts.map +1 -1
  13. package/dist/components/rich-text-editor/index.js +1 -1
  14. package/dist/components/rich-text-editor/rich-text-editor.d.ts.map +1 -1
  15. package/dist/i18n/locales/ar.d.ts +1 -0
  16. package/dist/i18n/locales/ar.d.ts.map +1 -1
  17. package/dist/i18n/locales/ar.js +2 -1
  18. package/dist/i18n/locales/ar.js.map +1 -1
  19. package/dist/i18n/locales/de.d.ts +1 -0
  20. package/dist/i18n/locales/de.d.ts.map +1 -1
  21. package/dist/i18n/locales/de.js +2 -1
  22. package/dist/i18n/locales/de.js.map +1 -1
  23. package/dist/i18n/locales/el.d.ts +1 -0
  24. package/dist/i18n/locales/el.d.ts.map +1 -1
  25. package/dist/i18n/locales/el.js +2 -1
  26. package/dist/i18n/locales/el.js.map +1 -1
  27. package/dist/i18n/locales/en.d.ts +1 -0
  28. package/dist/i18n/locales/en.d.ts.map +1 -1
  29. package/dist/i18n/locales/en.js +2 -1
  30. package/dist/i18n/locales/en.js.map +1 -1
  31. package/dist/i18n/locales/es.d.ts +1 -0
  32. package/dist/i18n/locales/es.d.ts.map +1 -1
  33. package/dist/i18n/locales/es.js +2 -1
  34. package/dist/i18n/locales/es.js.map +1 -1
  35. package/dist/i18n/locales/fr.d.ts +1 -0
  36. package/dist/i18n/locales/fr.d.ts.map +1 -1
  37. package/dist/i18n/locales/fr.js +2 -1
  38. package/dist/i18n/locales/fr.js.map +1 -1
  39. package/dist/i18n/locales/hi.d.ts +1 -0
  40. package/dist/i18n/locales/hi.d.ts.map +1 -1
  41. package/dist/i18n/locales/hi.js +2 -1
  42. package/dist/i18n/locales/hi.js.map +1 -1
  43. package/dist/i18n/locales/it.d.ts +1 -0
  44. package/dist/i18n/locales/it.d.ts.map +1 -1
  45. package/dist/i18n/locales/it.js +2 -1
  46. package/dist/i18n/locales/it.js.map +1 -1
  47. package/dist/i18n/locales/ja.d.ts +1 -0
  48. package/dist/i18n/locales/ja.d.ts.map +1 -1
  49. package/dist/i18n/locales/ja.js +2 -1
  50. package/dist/i18n/locales/ja.js.map +1 -1
  51. package/dist/i18n/locales/nl.d.ts +1 -0
  52. package/dist/i18n/locales/nl.d.ts.map +1 -1
  53. package/dist/i18n/locales/nl.js +2 -1
  54. package/dist/i18n/locales/nl.js.map +1 -1
  55. package/dist/i18n/locales/pl.d.ts +1 -0
  56. package/dist/i18n/locales/pl.d.ts.map +1 -1
  57. package/dist/i18n/locales/pl.js +2 -1
  58. package/dist/i18n/locales/pl.js.map +1 -1
  59. package/dist/i18n/locales/pt.d.ts +1 -0
  60. package/dist/i18n/locales/pt.d.ts.map +1 -1
  61. package/dist/i18n/locales/pt.js +2 -1
  62. package/dist/i18n/locales/pt.js.map +1 -1
  63. package/dist/i18n/locales/ro.d.ts +1 -0
  64. package/dist/i18n/locales/ro.d.ts.map +1 -1
  65. package/dist/i18n/locales/ro.js +2 -1
  66. package/dist/i18n/locales/ro.js.map +1 -1
  67. package/dist/i18n/locales/ru.d.ts +1 -0
  68. package/dist/i18n/locales/ru.d.ts.map +1 -1
  69. package/dist/i18n/locales/ru.js +2 -1
  70. package/dist/i18n/locales/ru.js.map +1 -1
  71. package/dist/i18n/locales/sq.d.ts +1 -0
  72. package/dist/i18n/locales/sq.d.ts.map +1 -1
  73. package/dist/i18n/locales/sq.js +2 -1
  74. package/dist/i18n/locales/sq.js.map +1 -1
  75. package/dist/i18n/locales/sv.d.ts +1 -0
  76. package/dist/i18n/locales/sv.d.ts.map +1 -1
  77. package/dist/i18n/locales/sv.js +2 -1
  78. package/dist/i18n/locales/sv.js.map +1 -1
  79. package/dist/i18n/locales/tr.d.ts +1 -0
  80. package/dist/i18n/locales/tr.d.ts.map +1 -1
  81. package/dist/i18n/locales/tr.js +2 -1
  82. package/dist/i18n/locales/tr.js.map +1 -1
  83. package/dist/i18n/locales/zh.d.ts +1 -0
  84. package/dist/i18n/locales/zh.d.ts.map +1 -1
  85. package/dist/i18n/locales/zh.js +2 -1
  86. package/dist/i18n/locales/zh.js.map +1 -1
  87. package/dist/index.js +4 -4
  88. package/dist/locales/ar.json +2 -1
  89. package/dist/locales/de.json +2 -1
  90. package/dist/locales/el.json +2 -1
  91. package/dist/locales/en.json +2 -1
  92. package/dist/locales/es.json +2 -1
  93. package/dist/locales/fr.json +2 -1
  94. package/dist/locales/hi.json +2 -1
  95. package/dist/locales/it.json +2 -1
  96. package/dist/locales/ja.json +2 -1
  97. package/dist/locales/nl.json +2 -1
  98. package/dist/locales/pl.json +2 -1
  99. package/dist/locales/pt.json +2 -1
  100. package/dist/locales/ro.json +2 -1
  101. package/dist/locales/ru.json +2 -1
  102. package/dist/locales/sq.json +2 -1
  103. package/dist/locales/sv.json +2 -1
  104. package/dist/locales/tr.json +2 -1
  105. package/dist/locales/zh.json +2 -1
  106. package/dist/patterns/calendar/calendar.journey.d.ts +11 -0
  107. package/dist/patterns/calendar/calendar.journey.d.ts.map +1 -1
  108. package/dist/patterns/calendar/calendar.sheets.d.ts +20 -0
  109. package/dist/patterns/calendar/calendar.sheets.d.ts.map +1 -1
  110. package/dist/patterns/calendar/index.js +1 -1
  111. package/dist/patterns/help-me-write-templates/help-me-write-templates.d.ts.map +1 -1
  112. package/dist/patterns/help-me-write-templates/index.js +1 -1
  113. package/package.json +1 -1
  114. package/dist/_chunks/calendar-workspace-UllCER2k.js.map +0 -1
  115. package/dist/_chunks/help-me-write-templates-GB70jnV9.js.map +0 -1
  116. package/dist/_chunks/notes-panel-_diLt8Cj.js.map +0 -1
  117. package/dist/_chunks/rich-text-editor-D7AKKAQ2.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"help-me-write-templates-B-m7zgJa.js","sources":["../../src/patterns/help-me-write-templates/help-me-write-templates.tsx"],"sourcesContent":["/**\n * Help me write templates (HTP-6383) — practice-shared AI templates inside the\n * RichTextEditor's \"Help me write\".\n *\n * Runtime pattern: real consuming apps mount this in production (surfaced via\n * `src/patterns/index.ts` and the `./patterns/help-me-write-templates`\n * subpath). It plugs into the editor through `renderHelpMeWrite`, so the kit\n * editor keeps its own AI pill, the patient AI-consent gate and the\n * resume-after-grant; this pattern supplies the bar that opens from it.\n *\n * Parts, usable on their own or wired together by `useHelpMeWriteTemplates`:\n * - `HelpMeWriteTemplatesBar` — the docked bar: free prompt with an optional\n * mic, a Templates menu, a side-by-side compare, Replace / Insert below.\n * - `AiTemplateManager` — the dialog to list, create, edit and delete\n * templates and pick the default.\n * - `AiCreditsExhaustedNotice` — the out-of-credits state the bar shows when\n * `onGenerate` rejects with `AiCreditsExhaustedError`.\n * - `HelpMeWriteUndoNotice` — the success notice with Undo after a template\n * rewrote the note.\n *\n * The host owns the templates (list + persistence) and the AI call. The kit\n * never talks to a backend.\n */\nimport {\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n ArrowLeft,\n Astroid,\n ChevronDown,\n Mic,\n Pencil,\n Plus,\n RotateCcw,\n Send,\n Settings,\n Square,\n Trash2,\n TrendingUp,\n WandSparkles,\n X,\n} from 'lucide-react';\n\nimport { Alert } from '../../components/alert';\nimport { Badge } from '../../components/badge';\nimport { Button, IconButton } from '../../components/button';\nimport { Dialog } from '../../components/dialog';\nimport { DropdownMenu } from '../../components/dropdown-menu';\nimport { EditorOverlay } from '../../components/editor-overlay';\nimport { EmptyState } from '../../components/empty-state';\nimport { FormField } from '../../components/form-field';\nimport { Progress } from '../../components/progress';\nimport type { HelpMeWriteRenderContext } from '../../components/rich-text-editor';\nimport { Spinner } from '../../components/spinner';\nimport { Switch } from '../../components/switch';\nimport { TextArea } from '../../components/text-area';\nimport { TextInput } from '../../components/text-input';\nimport { SafeHtml } from '../../components/_shared/safe-html';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\n/** A practice-shared AI template. */\nexport interface AiTemplate {\n id: string;\n /** Up to 100 characters, unique within the practice. */\n name: string;\n /** One line under the name in the Templates menu. */\n description?: string;\n /** The instructions sent to the AI, up to 4000 characters. */\n prompt: string;\n /** At most one per practice; listed first with a Default badge. */\n isDefault: boolean;\n}\n\n/** What the manager hands `onSaveTemplate`: `id` is absent for a new one. */\nexport type AiTemplateDraft = Omit<AiTemplate, 'id'> & { id?: string };\n\n/** One Help-me-write request. `template` is absent for a free prompt. */\nexport interface HelpMeWriteRequest {\n template?: AiTemplate;\n /** The free prompt, or extra instructions for a template. May be ''. */\n prompt: string;\n /** Plain text the template rewrites: the selection, else the whole note. */\n sourceText: string;\n signal: AbortSignal;\n}\n\n/**\n * Throw (or reject with) this from `onGenerate` when the practice is out of\n * AI credits (the platform endpoint's 402), and the bar shows the\n * out-of-credits notice instead of a generic error.\n */\nexport class AiCreditsExhaustedError extends Error {\n constructor(message = 'AI credits exhausted') {\n super(message);\n this.name = 'AiCreditsExhaustedError';\n }\n}\n\n/** The practice's allowance, for the out-of-credits notice. All optional. */\nexport interface AiCreditsInfo {\n remaining?: number;\n limit?: number;\n /** When the monthly allowance returns. */\n resetsOn?: Date;\n /**\n * Shows a \"Buy AI credits\" button and \"add credits\" wording. Omit while\n * credits cannot be bought: the notice then only says when AI returns.\n */\n onBuyCredits?: () => void;\n /** Shows a \"See what each action costs\" link. */\n onSeeCosts?: () => void;\n}\n\nexport type HelpMeWriteApplyMode = 'replace' | 'below' | 'insert';\n\n/** Fired after a draft lands in the editor. */\nexport interface HelpMeWriteApplied {\n mode: HelpMeWriteApplyMode;\n template?: AiTemplate;\n /** The editor's HTML before the change. */\n previousHtml: string;\n /** Puts `previousHtml` back in the editor (what Undo does). */\n undo: () => void;\n}\n\n/* ------------------------------------------------------------------ */\n/* Shared classes */\n/* ------------------------------------------------------------------ */\n\n// Match the composer's input height (--min-target-size), like the kit bar.\nconst ACTION_SIZE = 'ds:!size-[var(--min-target-size)]';\nconst MENU_TRIGGER = 'ds:!h-[var(--min-target-size)] ds:shrink-0';\nconst BRAND_ACTION = `${ACTION_SIZE} ds:bg-[image:var(--gradient-brand)] ds:rounded-full`;\n// The recording mic goes solid destructive, as in the kit's own bar.\nconst RECORDING_MIC =\n 'ds:aria-pressed:!bg-[var(--destructive)] ds:aria-pressed:!text-[var(--destructive-foreground)]';\nconst metaClass =\n 'ds:m-0 ds:text-[length:var(--font-size-sm)] ds:text-[color:var(--muted-foreground)]';\nconst eyebrowClass =\n 'type-eyebrow ds:m-0 ds:text-[color:var(--muted-foreground)]';\nconst previewClass = [\n 'ds:rounded-[var(--radius-md)] ds:border ds:border-[color:var(--border)]',\n 'ds:bg-[color-mix(in_srgb,var(--background)_70%,transparent)]',\n 'ds:p-[var(--spacing-sm)] ds:[max-block-size:14rem] ds:overflow-y-auto',\n 'ds:text-[length:var(--font-size-sm)] ds:text-[color:var(--foreground)]',\n 'ds:[&_ul]:list-disc ds:[&_ul]:ps-[var(--spacing-md)]',\n 'ds:[&_h3]:font-medium ds:[&_h3]:[margin-block-start:var(--spacing-xs)]',\n 'ds:[&_p]:[margin-block-end:var(--spacing-xs)]',\n 'ds:[&>:first-child]:[margin-block-start:0]',\n].join(' ');\n// Side by side, both boxes take the same fixed height (each scrolls), so the\n// note and the draft line up whatever their length.\nconst compareBoxClass = 'ds:[block-size:14rem]';\n\n/* ------------------------------------------------------------------ */\n/* Helpers */\n/* ------------------------------------------------------------------ */\n\n// Default template first, then the rest in their saved order.\nfunction orderTemplates(templates: AiTemplate[]): AiTemplate[] {\n return [...templates].sort(\n (a, b) => Number(b.isDefault) - Number(a.isDefault),\n );\n}\n\n// Join dictated text onto the prompt with a single space.\nfunction joinWith(base: string, extra: string): string {\n if (!extra) return base;\n if (!base) return extra;\n return /\\s$/.test(base) ? `${base}${extra}` : `${base} ${extra}`;\n}\n\nfunction isAbort(err: unknown): boolean {\n return (\n typeof err === 'object' &&\n err !== null &&\n 'name' in err &&\n (err as { name?: string }).name === 'AbortError'\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* AiCreditsExhaustedNotice */\n/* ------------------------------------------------------------------ */\n\nexport interface AiCreditsExhaustedNoticeProps {\n credits?: AiCreditsInfo;\n /** Shows a Back button (the bar uses it to return to the prompt). */\n onBack?: () => void;\n}\n\n/** The out-of-credits state: what happened, the allowance, and the ways on. */\nexport function AiCreditsExhaustedNotice({\n credits,\n onBack,\n}: AiCreditsExhaustedNoticeProps): React.JSX.Element {\n const { t, i18n } = useTranslation();\n const limit = credits?.limit;\n const remaining = credits?.remaining ?? 0;\n const remainingText =\n limit !== undefined\n ? t('helpMeWriteTemplates.credits.remaining', { remaining, limit })\n : undefined;\n const resetsOn = credits?.resetsOn\n ? new Intl.DateTimeFormat(i18n.language, {\n day: 'numeric',\n month: 'long',\n }).format(credits.resetsOn)\n : undefined;\n return (\n <div\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\"\n data-component=\"ai-credits-exhausted-notice\"\n >\n <Alert variant=\"promo\" icon={<Astroid aria-hidden=\"true\" />}>\n <Alert.Title as=\"h2\">\n {t('helpMeWriteTemplates.credits.title')}\n </Alert.Title>\n <Alert.Description>\n {/* Without a way to buy credits, only say when AI comes back. */}\n {credits?.onBuyCredits\n ? resetsOn\n ? t('helpMeWriteTemplates.credits.bodyResets', { date: resetsOn })\n : t('helpMeWriteTemplates.credits.body')\n : resetsOn\n ? t('helpMeWriteTemplates.credits.bodyWaitResets', {\n date: resetsOn,\n })\n : t('helpMeWriteTemplates.credits.bodyWait')}\n </Alert.Description>\n {limit !== undefined && remainingText ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)] ds:[margin-block-start:var(--spacing-sm)]\">\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <span className=\"type-label\">\n {t('helpMeWriteTemplates.credits.meterLabel')}\n </span>\n <span className=\"type-label ds:ms-auto ds:tabular-nums\">\n {remainingText}\n </span>\n </div>\n <Progress\n value={Math.max(0, limit - remaining)}\n max={limit}\n size=\"sm\"\n ariaLabel={t('helpMeWriteTemplates.credits.meterLabel')}\n ariaValueText={remainingText}\n />\n </div>\n ) : null}\n {credits?.onBuyCredits || credits?.onSeeCosts ? (\n <Alert.Action>\n {credits.onBuyCredits ? (\n <Button\n intent=\"tonal\"\n size=\"sm\"\n startIcon={<TrendingUp aria-hidden=\"true\" />}\n onClick={credits.onBuyCredits}\n >\n {t('helpMeWriteTemplates.credits.cta')}\n </Button>\n ) : null}\n {credits.onSeeCosts ? (\n <Button intent=\"link\" size=\"sm\" onClick={credits.onSeeCosts}>\n {t('helpMeWriteTemplates.credits.secondary')}\n </Button>\n ) : null}\n </Alert.Action>\n ) : null}\n </Alert>\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n {onBack ? (\n <Button intent=\"ghost\" startIcon={<ArrowLeft />} onClick={onBack}>\n {t('helpMeWriteTemplates.credits.back')}\n </Button>\n ) : null}\n <p className={metaClass}>{t('helpMeWriteTemplates.credits.kept')}</p>\n </div>\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* HelpMeWriteTemplatesBar */\n/* ------------------------------------------------------------------ */\n\nexport interface HelpMeWriteTemplatesBarProps {\n /** What `RichTextEditor`'s `renderHelpMeWrite` hands its host. */\n context: HelpMeWriteRenderContext;\n templates: AiTemplate[];\n /** The AI call. Reject with `AiCreditsExhaustedError` when out of credits. */\n onGenerate: (request: HelpMeWriteRequest) => Promise<string>;\n /**\n * Opens the template manager. Omit to hide \"Manage templates\" and\n * \"Create your first template\" (e.g. for readers who may not manage).\n */\n onManageTemplates?: (mode: 'list' | 'create') => void;\n /** After a draft lands; the hook uses it for Undo. */\n onApplied?: (applied: HelpMeWriteApplied) => void;\n /** Shown in the out-of-credits notice. */\n credits?: AiCreditsInfo;\n /** Show the mic in the prompt when the editor has `onDictate`. Default true. */\n enableDictation?: boolean;\n /** Ignore Escape (e.g. while the manager dialog above it is open). */\n suspendClose?: boolean;\n}\n\ninterface SourceInfo {\n kind: 'selection' | 'document';\n words: number;\n text: string;\n}\n\n/** The Help-me-write bar with templates, docked in the editor's AI slot. */\nexport function HelpMeWriteTemplatesBar({\n context,\n templates,\n onGenerate,\n onManageTemplates,\n onApplied,\n credits,\n enableDictation = true,\n suspendClose = false,\n}: HelpMeWriteTemplatesBarProps): React.JSX.Element {\n const { t } = useTranslation();\n const { open } = context;\n const sourceId = useId();\n const errorId = useId();\n const [prompt, setPrompt] = useState('');\n // `undefined` = free prompt running; a template = that template is running.\n const [running, setRunning] = useState<AiTemplate | undefined | null>(null);\n const [errored, setErrored] = useState(false);\n const [outOfCredits, setOutOfCredits] = useState(false);\n const [result, setResult] = useState<{\n draft: string;\n template?: AiTemplate;\n } | null>(null);\n const [source, setSource] = useState<SourceInfo>({\n kind: 'document',\n words: 0,\n text: '',\n });\n const abortRef = useRef<AbortController | null>(null);\n const loading = running !== null;\n const onDictate = enableDictation ? context.onDictate : undefined;\n\n /* ---- Mic in the prompt (the editor's own dictation seam) ---- */\n const [isDictating, setIsDictating] = useState(false);\n const [interim, setInterim] = useState('');\n const [announcement, setAnnouncement] = useState('');\n const dictateAbortRef = useRef<AbortController | null>(null);\n const stopDictation = useCallback(() => dictateAbortRef.current?.abort(), []);\n const toggleDictation = useCallback(() => {\n if (isDictating) {\n stopDictation();\n return;\n }\n if (!onDictate) return;\n const controller = new AbortController();\n dictateAbortRef.current = controller;\n setIsDictating(true);\n setAnnouncement(t('helpMeWriteTemplates.bar.listening'));\n onDictate({\n signal: controller.signal,\n onPartialTranscript: (text) => {\n if (!controller.signal.aborted) setInterim(text);\n },\n onFinalTranscript: (text) => {\n if (controller.signal.aborted) return;\n setInterim('');\n const trimmed = text.trim();\n if (trimmed) {\n setPrompt((p) => joinWith(p, trimmed));\n setAnnouncement(trimmed);\n }\n },\n })\n .catch((err: unknown) => {\n // Out of credits shows the notice; other dictation errors are\n // non-fatal (the user can type instead).\n if (err instanceof AiCreditsExhaustedError) setOutOfCredits(true);\n })\n .finally(() => {\n setInterim('');\n if (dictateAbortRef.current === controller) {\n dictateAbortRef.current = null;\n setIsDictating(false);\n setAnnouncement('');\n }\n });\n }, [isDictating, onDictate, stopDictation, t]);\n\n // Each open starts fresh and reads what a template would rewrite.\n useEffect(() => {\n if (open) {\n setPrompt('');\n setRunning(null);\n setErrored(false);\n // Opened by a dictation that ran out of credits: start on the notice.\n setOutOfCredits(context.creditsExhausted);\n setResult(null);\n const selection = context.selectionText.trim();\n const text = selection || context.getText();\n setSource({\n kind: selection ? 'selection' : 'document',\n words: text.split(/\\s+/).filter(Boolean).length,\n text,\n });\n } else {\n abortRef.current?.abort();\n dictateAbortRef.current?.abort();\n }\n // Only on open/close; `context` is a fresh object every editor render.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n\n useEffect(\n () => () => {\n abortRef.current?.abort();\n dictateAbortRef.current?.abort();\n },\n [],\n );\n\n const run = useCallback(\n (template: AiTemplate | undefined) => {\n if (loading) return;\n if (template ? source.words === 0 : !prompt.trim()) return;\n stopDictation();\n abortRef.current?.abort();\n const controller = new AbortController();\n abortRef.current = controller;\n setErrored(false);\n setRunning(template);\n onGenerate({\n template,\n prompt: prompt.trim(),\n sourceText: template ? source.text : '',\n signal: controller.signal,\n })\n .then((draft) => {\n if (controller.signal.aborted) return;\n setResult({ draft, template });\n setRunning(null);\n })\n .catch((err: unknown) => {\n if (controller.signal.aborted || isAbort(err)) return;\n if (err instanceof AiCreditsExhaustedError) setOutOfCredits(true);\n else setErrored(true);\n setRunning(null);\n });\n },\n [loading, source, prompt, onGenerate, stopDictation],\n );\n\n const { onClose: contextClose } = context;\n const close = useCallback(() => {\n if (suspendClose) return;\n contextClose();\n }, [suspendClose, contextClose]);\n\n const apply = (mode: HelpMeWriteApplyMode) => {\n if (!result) return;\n const { draft, template } = result;\n const previousHtml = context.getHTML();\n const selected = source.kind === 'selection';\n if (mode === 'insert') {\n context.insertAtSelection(draft);\n } else if (mode === 'replace') {\n if (selected) context.insertAtSelection(draft);\n else context.setContent(draft);\n } else if (selected) {\n context.insertAfterSelection(draft);\n } else {\n context.setContent(`${previousHtml}${draft}`);\n }\n context.onClose();\n const { setContent } = context;\n onApplied?.({\n mode,\n template,\n previousHtml,\n undo: () => setContent(previousHtml),\n });\n };\n\n const sourceLine =\n source.words === 0\n ? t('helpMeWriteTemplates.bar.sourceEmpty')\n : source.kind === 'selection'\n ? t('helpMeWriteTemplates.bar.sourceSelection')\n : t('helpMeWriteTemplates.bar.sourceDocument');\n\n let body: ReactNode;\n if (outOfCredits) {\n body = (\n <AiCreditsExhaustedNotice\n credits={credits}\n onBack={() => setOutOfCredits(false)}\n />\n );\n } else if (result) {\n const compare = Boolean(result.template);\n body = (\n <>\n <div\n className={\n compare\n ? 'ds:grid ds:grid-cols-1 ds:gap-[var(--spacing-sm)] ds:lg:grid-cols-2'\n : 'ds:grid ds:grid-cols-1'\n }\n >\n {compare ? (\n <section\n aria-labelledby={`${sourceId}-before`}\n className=\"ds:flex ds:min-w-0 ds:flex-col ds:gap-[var(--spacing-2xs)]\"\n >\n <h2 id={`${sourceId}-before`} className={eyebrowClass}>\n {source.kind === 'selection'\n ? t('helpMeWriteTemplates.bar.beforeSelection')\n : t('helpMeWriteTemplates.bar.beforeDocument')}\n </h2>\n <p\n className={`${previewClass} ${compareBoxClass} ds:text-[color:var(--muted-foreground)]`}\n // Focusable so a keyboard user can scroll a long note.\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n tabIndex={0}\n >\n {source.text}\n </p>\n </section>\n ) : null}\n <section\n aria-labelledby={`${sourceId}-after`}\n className=\"ds:flex ds:min-w-0 ds:flex-col ds:gap-[var(--spacing-2xs)]\"\n >\n <h2 id={`${sourceId}-after`} className={eyebrowClass}>\n {result.template\n ? `${t('helpMeWriteTemplates.bar.after')} · ${result.template.name}`\n : t('helpMeWriteTemplates.bar.after')}\n </h2>\n <SafeHtml\n html={result.draft}\n profile=\"rich-text\"\n className={\n compare ? `${previewClass} ${compareBoxClass}` : previewClass\n }\n tabIndex={0}\n />\n </section>\n </div>\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Button intent=\"ghost\" startIcon={<X />} onClick={context.onClose}>\n {t('helpMeWriteTemplates.bar.discard')}\n </Button>\n <Button\n intent=\"ghost\"\n startIcon={<RotateCcw />}\n onClick={() => {\n setResult(null);\n run(result.template);\n }}\n >\n {t('helpMeWriteTemplates.bar.retry')}\n </Button>\n <span className=\"ds:flex-1\" aria-hidden=\"true\" />\n {compare ? (\n <>\n <Button intent=\"outline\" onClick={() => apply('below')}>\n {t('helpMeWriteTemplates.bar.insertBelow')}\n </Button>\n <Button intent=\"primary\" onClick={() => apply('replace')}>\n {t('helpMeWriteTemplates.bar.replace')}\n </Button>\n </>\n ) : (\n <Button intent=\"primary\" onClick={() => apply('insert')}>\n {t('helpMeWriteTemplates.bar.insert')}\n </Button>\n )}\n </div>\n </>\n );\n } else {\n const ordered = orderTemplates(templates);\n // While dictating the field shows the committed prompt plus live interim\n // text, read-only so the stream is not fought over by typing.\n const fieldValue = isDictating ? joinWith(prompt, interim) : prompt;\n const showTemplatesMenu = templates.length > 0 || onManageTemplates;\n body = (\n <>\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <IconButton\n size=\"md\"\n intent=\"outline\"\n className={ACTION_SIZE}\n icon={<X />}\n aria-label={t('helpMeWriteTemplates.bar.close')}\n onClick={context.onClose}\n />\n <div className=\"ds:min-w-0 ds:flex-1\">\n <TextArea\n size=\"md\"\n value={fieldValue}\n onChange={(event) => setPrompt(event.target.value)}\n placeholder={t('helpMeWriteTemplates.bar.prompt')}\n aria-label={t('helpMeWriteTemplates.bar.prompt')}\n autoResize\n minRows={1}\n maxRows={3}\n readOnly={loading || isDictating}\n tone={errored ? 'error' : 'default'}\n aria-describedby={errored ? errorId : undefined}\n />\n </div>\n {onDictate ? (\n <IconButton\n size=\"md\"\n intent=\"outline\"\n className={\n isDictating ? `${ACTION_SIZE} ${RECORDING_MIC}` : ACTION_SIZE\n }\n icon={\n isDictating ? <Square className=\"ds:fill-current\" /> : <Mic />\n }\n aria-pressed={isDictating}\n aria-label={\n isDictating\n ? t('helpMeWriteTemplates.bar.dictateStop')\n : t('helpMeWriteTemplates.bar.dictateStart')\n }\n disabled={loading}\n onClick={toggleDictation}\n />\n ) : null}\n {showTemplatesMenu ? (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button\n intent=\"outline\"\n size=\"md\"\n className={MENU_TRIGGER}\n startIcon={\n running ? (\n <Spinner size=\"sm\" variant=\"pulse\" />\n ) : (\n <WandSparkles aria-hidden=\"true\" />\n )\n }\n endIcon={<ChevronDown aria-hidden=\"true\" />}\n aria-haspopup=\"menu\"\n aria-busy={running ? true : undefined}\n disabled={loading}\n aria-describedby={sourceId}\n >\n {t('helpMeWriteTemplates.bar.templatesMenu')}\n </Button>\n </DropdownMenu.Trigger>\n {/* The bar is docked at the editor's bottom edge, so the menu opens upward. */}\n <DropdownMenu.Content side=\"top\" align=\"end\" sideOffset={8}>\n <DropdownMenu.Label>\n {t('helpMeWriteTemplates.bar.templatesGroup')}\n </DropdownMenu.Label>\n {ordered.map((tpl) => (\n <DropdownMenu.Item\n key={tpl.id}\n startIcon={<WandSparkles />}\n description={tpl.description || undefined}\n // Only the run items disable on an empty note; the\n // library itself stays readable.\n disabled={loading || source.words === 0}\n onSelect={() => run(tpl)}\n >\n {/* The badge sits in the label, not `endIcon`: that slot\n is a 16px aria-hidden box, which would clip the badge\n and hide \"Default\" from screen readers. */}\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n {tpl.name}\n {tpl.isDefault ? (\n <Badge variant=\"brand\" size=\"sm\">\n {t('helpMeWriteTemplates.bar.defaultBadge')}\n </Badge>\n ) : null}\n </span>\n </DropdownMenu.Item>\n ))}\n {onManageTemplates && templates.length === 0 ? (\n <DropdownMenu.Item\n startIcon={<Plus />}\n onSelect={() => onManageTemplates('create')}\n >\n {t('helpMeWriteTemplates.bar.createFirst')}\n </DropdownMenu.Item>\n ) : null}\n {onManageTemplates && templates.length > 0 ? (\n <>\n <DropdownMenu.Separator />\n <DropdownMenu.Item\n startIcon={<Settings />}\n onSelect={() => onManageTemplates('list')}\n >\n {t('helpMeWriteTemplates.bar.manage')}\n </DropdownMenu.Item>\n </>\n ) : null}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n ) : null}\n <IconButton\n size=\"md\"\n intent=\"primary\"\n className={BRAND_ACTION}\n icon={\n running === undefined ? (\n <Spinner size=\"sm\" variant=\"pulse\" />\n ) : (\n <Send />\n )\n }\n disabled={loading || !prompt.trim()}\n aria-busy={running === undefined || undefined}\n aria-label={t('helpMeWriteTemplates.bar.write')}\n onClick={() => run(undefined)}\n />\n </div>\n {onDictate ? (\n <p className=\"ds:sr-only\" role=\"status\" aria-live=\"polite\">\n {announcement}\n </p>\n ) : null}\n {errored ? (\n <p id={errorId} role=\"alert\" className={metaClass}>\n {t('helpMeWriteTemplates.bar.error')}\n </p>\n ) : null}\n <p id={sourceId} className={metaClass}>\n {sourceLine} {context.privacyNotice}\n </p>\n </>\n );\n }\n\n return (\n <EditorOverlay\n open={open}\n onClose={close}\n ariaLabel={t('editor.ai.helpMeWrite')}\n >\n <div className=\"ds:contents\" data-component=\"help-me-write-templates-bar\">\n {body}\n </div>\n </EditorOverlay>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* AiTemplateManager */\n/* ------------------------------------------------------------------ */\n\nexport interface AiTemplateManagerProps {\n open: boolean;\n onOpenChange: (open: boolean) => void;\n /** Open on the list (default) or straight on a new-template form. */\n initialMode?: 'list' | 'create';\n templates: AiTemplate[];\n /** Persist a new (no `id`) or edited template. A rejection keeps the form open. */\n onSaveTemplate: (draft: AiTemplateDraft) => void | Promise<void>;\n /** Omit to hide Delete. */\n onDeleteTemplate?: (id: string) => void | Promise<void>;\n}\n\ninterface FormState {\n id?: string;\n name: string;\n description: string;\n prompt: string;\n isDefault: boolean;\n submitted: boolean;\n}\n\nconst EMPTY_FORM: FormState = {\n name: '',\n description: '',\n prompt: '',\n isDefault: false,\n submitted: false,\n};\n\n/** List, create, edit and delete the practice's templates. */\nexport function AiTemplateManager({\n open,\n onOpenChange,\n initialMode = 'list',\n templates,\n onSaveTemplate,\n onDeleteTemplate,\n}: AiTemplateManagerProps): React.JSX.Element {\n const { t } = useTranslation();\n const [form, setForm] = useState<FormState | null>(null);\n const [saving, setSaving] = useState(false);\n const [saveFailed, setSaveFailed] = useState(false);\n const [pendingDelete, setPendingDelete] = useState<AiTemplate | null>(null);\n const [deleting, setDeleting] = useState(false);\n const [deleteFailed, setDeleteFailed] = useState(false);\n\n // Wait for the host: the confirmation stays open (busy) until the delete\n // settles, and shows an error if it fails.\n const confirmDelete = async () => {\n if (!pendingDelete || deleting) return;\n setDeleting(true);\n setDeleteFailed(false);\n try {\n await onDeleteTemplate?.(pendingDelete.id);\n setPendingDelete(null);\n } catch {\n setDeleteFailed(true);\n } finally {\n setDeleting(false);\n }\n };\n\n useEffect(() => {\n if (open) {\n setSaveFailed(false);\n setForm(\n initialMode === 'create'\n ? { ...EMPTY_FORM, isDefault: templates.length === 0 }\n : null,\n );\n }\n // Only when it opens; `templates` changing mid-edit keeps the form.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [open]);\n\n const nameTaken = (name: string, id?: string): boolean =>\n templates.some(\n (tpl) => tpl.id !== id && tpl.name.toLowerCase() === name.toLowerCase(),\n );\n\n const nameError = (() => {\n if (!form?.submitted) return undefined;\n const name = form.name.trim();\n if (!name) return t('helpMeWriteTemplates.manager.nameRequired');\n return nameTaken(name, form.id)\n ? t('helpMeWriteTemplates.manager.nameTaken')\n : undefined;\n })();\n const promptError =\n form?.submitted && !form.prompt.trim()\n ? t('helpMeWriteTemplates.manager.promptRequired')\n : undefined;\n\n const save = async () => {\n if (!form || saving) return;\n const next = { ...form, submitted: true };\n setForm(next);\n const name = next.name.trim();\n const prompt = next.prompt.trim();\n if (!name || !prompt || nameTaken(name, next.id)) return;\n setSaving(true);\n setSaveFailed(false);\n try {\n await onSaveTemplate({\n id: next.id,\n name,\n description: next.description.trim() || undefined,\n prompt,\n isDefault: next.isDefault,\n });\n setForm(null);\n } catch {\n setSaveFailed(true);\n } finally {\n setSaving(false);\n }\n };\n\n const title = form\n ? form.id\n ? t('helpMeWriteTemplates.manager.formEdit')\n : t('helpMeWriteTemplates.manager.formNew')\n : t('helpMeWriteTemplates.manager.title');\n\n return (\n <>\n <Dialog open={open} onOpenChange={onOpenChange}>\n <Dialog.Content size=\"lg\">\n <div className=\"ds:contents\" data-component=\"ai-template-manager\">\n <Dialog.Header>\n <Dialog.Title>{title}</Dialog.Title>\n <Dialog.Description>\n {t('helpMeWriteTemplates.manager.description')}\n </Dialog.Description>\n </Dialog.Header>\n <Dialog.Body>\n {form ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n {saveFailed ? (\n <Alert variant=\"error\">\n {t('helpMeWriteTemplates.manager.saveError')}\n </Alert>\n ) : null}\n <FormField\n label={t('helpMeWriteTemplates.manager.name')}\n error={nameError}\n required\n >\n <TextInput\n value={form.name}\n maxLength={100}\n placeholder={t(\n 'helpMeWriteTemplates.manager.namePlaceholder',\n )}\n onChange={(event) =>\n setForm({ ...form, name: event.target.value })\n }\n />\n </FormField>\n <FormField\n label={t('helpMeWriteTemplates.manager.descLabel')}\n description={t('helpMeWriteTemplates.manager.descHint')}\n optional\n >\n <TextInput\n value={form.description}\n maxLength={120}\n onChange={(event) =>\n setForm({ ...form, description: event.target.value })\n }\n />\n </FormField>\n <FormField\n label={t('helpMeWriteTemplates.manager.prompt')}\n description={t(\n 'helpMeWriteTemplates.manager.promptDescription',\n )}\n error={promptError}\n required\n >\n <TextArea\n value={form.prompt}\n maxLength={4000}\n autoResize\n minRows={4}\n maxRows={10}\n onChange={(event) =>\n setForm({ ...form, prompt: event.target.value })\n }\n />\n </FormField>\n <Switch\n label={t('helpMeWriteTemplates.manager.isDefault')}\n checked={form.isDefault}\n onCheckedChange={(checked) =>\n setForm({ ...form, isDefault: checked })\n }\n />\n </div>\n ) : templates.length === 0 ? (\n <EmptyState\n variant=\"first-use\"\n size=\"sm\"\n title={t('helpMeWriteTemplates.manager.emptyTitle')}\n description={t(\n 'helpMeWriteTemplates.manager.emptyDescription',\n )}\n primaryAction={{\n label: t('helpMeWriteTemplates.manager.new'),\n onClick: () => setForm({ ...EMPTY_FORM, isDefault: true }),\n }}\n />\n ) : (\n <ul\n aria-label={t('helpMeWriteTemplates.manager.listLabel')}\n className=\"ds:m-0 ds:flex ds:list-none ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-0\"\n >\n {orderTemplates(templates).map((tpl) => (\n <li\n key={tpl.id}\n className=\"ds:flex ds:items-start ds:gap-[var(--spacing-sm)] ds:rounded-[var(--radius-md)] ds:border ds:border-[color:var(--border)] ds:p-[var(--spacing-sm)]\"\n >\n <div className=\"ds:flex ds:min-w-0 ds:flex-1 ds:flex-col ds:gap-[var(--spacing-2xs)]\">\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)]\">\n <span className=\"type-title-item ds:text-[color:var(--foreground)]\">\n {tpl.name}\n </span>\n {tpl.isDefault ? (\n <Badge variant=\"brand\" size=\"sm\">\n {t('helpMeWriteTemplates.bar.defaultBadge')}\n </Badge>\n ) : null}\n </div>\n <p className={`${metaClass} ds:line-clamp-2`}>\n {tpl.description || tpl.prompt}\n </p>\n </div>\n <IconButton\n size=\"sm\"\n intent=\"ghost\"\n icon={<Pencil />}\n aria-label={t('helpMeWriteTemplates.manager.edit', {\n name: tpl.name,\n })}\n onClick={() =>\n setForm({\n id: tpl.id,\n name: tpl.name,\n description: tpl.description ?? '',\n prompt: tpl.prompt,\n isDefault: tpl.isDefault,\n submitted: false,\n })\n }\n />\n {onDeleteTemplate ? (\n <IconButton\n size=\"sm\"\n intent=\"ghost\"\n icon={<Trash2 />}\n aria-label={t('helpMeWriteTemplates.manager.delete', {\n name: tpl.name,\n })}\n onClick={() => setPendingDelete(tpl)}\n />\n ) : null}\n </li>\n ))}\n </ul>\n )}\n </Dialog.Body>\n <Dialog.Footer>\n {form ? (\n <>\n <Button intent=\"secondary\" onClick={() => setForm(null)}>\n {t('helpMeWriteTemplates.manager.cancel')}\n </Button>\n <Button\n intent=\"primary\"\n loading={saving}\n onClick={() => void save()}\n >\n {t('helpMeWriteTemplates.manager.save')}\n </Button>\n </>\n ) : (\n <>\n {templates.length > 0 ? (\n <Button\n intent=\"outline\"\n startIcon={<Plus />}\n onClick={() => setForm({ ...EMPTY_FORM })}\n >\n {t('helpMeWriteTemplates.manager.new')}\n </Button>\n ) : null}\n <Dialog.Close asChild>\n <Button intent=\"primary\">\n {t('helpMeWriteTemplates.manager.done')}\n </Button>\n </Dialog.Close>\n </>\n )}\n </Dialog.Footer>\n </div>\n </Dialog.Content>\n </Dialog>\n <Dialog\n open={pendingDelete != null}\n onOpenChange={(next) => {\n if (!next && !deleting) {\n setPendingDelete(null);\n setDeleteFailed(false);\n }\n }}\n >\n <Dialog.Content size=\"sm\" variant=\"alert\">\n <Dialog.Header>\n <Dialog.Title>\n {t('helpMeWriteTemplates.manager.deleteTitle', {\n name: pendingDelete?.name ?? '',\n })}\n </Dialog.Title>\n <Dialog.Description>\n {t('helpMeWriteTemplates.manager.deleteDescription')}\n </Dialog.Description>\n </Dialog.Header>\n {deleteFailed ? (\n <Dialog.Body>\n <Alert variant=\"error\">\n {t('helpMeWriteTemplates.manager.deleteError')}\n </Alert>\n </Dialog.Body>\n ) : null}\n <Dialog.Footer>\n <Dialog.Close asChild>\n <Button intent=\"secondary\" disabled={deleting}>\n {t('helpMeWriteTemplates.manager.cancel')}\n </Button>\n </Dialog.Close>\n <Button\n intent=\"destructive\"\n loading={deleting}\n onClick={() => void confirmDelete()}\n >\n {t('helpMeWriteTemplates.manager.deleteConfirm')}\n </Button>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog>\n </>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* HelpMeWriteUndoNotice */\n/* ------------------------------------------------------------------ */\n\nexport interface HelpMeWriteUndoNoticeProps {\n /** The change to offer Undo for; `null` hides the notice. */\n applied: HelpMeWriteApplied | null;\n onUndo: () => void;\n onDismiss: () => void;\n}\n\n/** \"Note rewritten with …\" plus Undo; takes focus when it appears. */\nexport function HelpMeWriteUndoNotice({\n applied,\n onUndo,\n onDismiss,\n}: HelpMeWriteUndoNoticeProps): React.JSX.Element | null {\n const { t } = useTranslation();\n const undoRef = useRef<HTMLButtonElement>(null);\n useEffect(() => {\n if (applied) undoRef.current?.focus();\n }, [applied]);\n if (!applied?.template) return null;\n const name = applied.template.name;\n return (\n <Alert\n variant=\"success\"\n dismissible\n onOpenChange={(isOpen) => {\n if (!isOpen) onDismiss();\n }}\n data-component=\"help-me-write-undo-notice\"\n >\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n <span>\n {applied.mode === 'below'\n ? t('helpMeWriteTemplates.undo.addedBelow', { name })\n : t('helpMeWriteTemplates.undo.replaced', { name })}\n </span>\n <Button ref={undoRef} intent=\"outline\" size=\"sm\" onClick={onUndo}>\n {t('helpMeWriteTemplates.undo.undo')}\n </Button>\n </div>\n </Alert>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* useHelpMeWriteTemplates — the whole thing in one call */\n/* ------------------------------------------------------------------ */\n\nexport interface UseHelpMeWriteTemplatesOptions {\n templates: AiTemplate[];\n onGenerate: HelpMeWriteTemplatesBarProps['onGenerate'];\n /** Enables the manager (create / edit). Omit for read-only template users. */\n onSaveTemplate?: AiTemplateManagerProps['onSaveTemplate'];\n /** Enables Delete in the manager. */\n onDeleteTemplate?: AiTemplateManagerProps['onDeleteTemplate'];\n credits?: AiCreditsInfo;\n /** Mic in the bar's prompt when the editor has `onDictate`. Default true. */\n enableDictation?: boolean;\n /** Also told about every applied draft (e.g. for analytics). */\n onApplied?: (applied: HelpMeWriteApplied) => void;\n}\n\nexport interface UseHelpMeWriteTemplatesResult {\n /** Pass to `RichTextEditor`'s `renderHelpMeWrite`. */\n renderHelpMeWrite: (context: HelpMeWriteRenderContext) => ReactNode;\n /** Mount once, anywhere (a portalled dialog); `null` without `onSaveTemplate`. */\n manager: ReactNode;\n /** Place where the Undo notice should show, e.g. above the editor. */\n undoNotice: ReactNode;\n openManager: (mode?: 'list' | 'create') => void;\n}\n\n/**\n * Wires the bar, the manager and Undo together. Usage:\n *\n * const hmw = useHelpMeWriteTemplates({ templates, onGenerate, onSaveTemplate });\n * {hmw.undoNotice}\n * <RichTextEditor renderHelpMeWrite={hmw.renderHelpMeWrite} … />\n * {hmw.manager}\n */\nexport function useHelpMeWriteTemplates({\n templates,\n onGenerate,\n onSaveTemplate,\n onDeleteTemplate,\n credits,\n enableDictation,\n onApplied,\n}: UseHelpMeWriteTemplatesOptions): UseHelpMeWriteTemplatesResult {\n const [manager, setManager] = useState<{\n open: boolean;\n mode: 'list' | 'create';\n }>({ open: false, mode: 'list' });\n const [applied, setApplied] = useState<HelpMeWriteApplied | null>(null);\n const openManager = useCallback(\n (mode: 'list' | 'create' = 'list') => setManager({ open: true, mode }),\n [],\n );\n\n const renderHelpMeWrite = useCallback(\n (context: HelpMeWriteRenderContext): ReactNode => {\n return (\n <HelpMeWriteTemplatesBar\n context={context}\n templates={templates}\n onGenerate={onGenerate}\n onManageTemplates={onSaveTemplate ? openManager : undefined}\n credits={credits}\n enableDictation={enableDictation}\n suspendClose={manager.open}\n onApplied={(event) => {\n setApplied(event.template ? event : null);\n onApplied?.(event);\n }}\n />\n );\n },\n [\n templates,\n onGenerate,\n onSaveTemplate,\n openManager,\n credits,\n enableDictation,\n manager.open,\n onApplied,\n ],\n );\n\n const managerNode = useMemo(\n () =>\n onSaveTemplate ? (\n <AiTemplateManager\n open={manager.open}\n initialMode={manager.mode}\n onOpenChange={(isOpen) => setManager((m) => ({ ...m, open: isOpen }))}\n templates={templates}\n onSaveTemplate={onSaveTemplate}\n onDeleteTemplate={onDeleteTemplate}\n />\n ) : null,\n [manager, templates, onSaveTemplate, onDeleteTemplate],\n );\n\n const undoNotice = (\n <HelpMeWriteUndoNotice\n applied={applied}\n onUndo={() => {\n applied?.undo();\n setApplied(null);\n }}\n onDismiss={() => setApplied(null)}\n />\n );\n\n return {\n renderHelpMeWrite,\n manager: managerNode,\n undoNotice,\n openManager,\n };\n}\n"],"names":["AiCreditsExhaustedError","message","ACTION_SIZE","MENU_TRIGGER","BRAND_ACTION","RECORDING_MIC","metaClass","eyebrowClass","previewClass","compareBoxClass","orderTemplates","templates","a","b","joinWith","base","extra","isAbort","err","AiCreditsExhaustedNotice","credits","onBack","t","i18n","useTranslation","limit","remaining","remainingText","resetsOn","jsxs","Alert","Astroid","jsx","Progress","Button","TrendingUp","ArrowLeft","HelpMeWriteTemplatesBar","context","onGenerate","onManageTemplates","onApplied","enableDictation","suspendClose","open","sourceId","useId","errorId","prompt","setPrompt","useState","running","setRunning","errored","setErrored","outOfCredits","setOutOfCredits","result","setResult","source","setSource","abortRef","useRef","loading","onDictate","isDictating","setIsDictating","interim","setInterim","announcement","setAnnouncement","dictateAbortRef","stopDictation","useCallback","_a","toggleDictation","controller","text","trimmed","p","useEffect","selection","_b","run","template","draft","contextClose","close","apply","mode","previousHtml","selected","setContent","sourceLine","body","compare","Fragment","SafeHtml","X","RotateCcw","ordered","fieldValue","showTemplatesMenu","IconButton","TextArea","event","Square","Mic","DropdownMenu","Spinner","WandSparkles","ChevronDown","tpl","Badge","Plus","Settings","Send","EditorOverlay","EMPTY_FORM","AiTemplateManager","onOpenChange","initialMode","onSaveTemplate","onDeleteTemplate","form","setForm","saving","setSaving","saveFailed","setSaveFailed","pendingDelete","setPendingDelete","deleting","setDeleting","deleteFailed","setDeleteFailed","confirmDelete","nameTaken","name","id","nameError","promptError","save","next","title","Dialog","FormField","TextInput","Switch","checked","EmptyState","Pencil","Trash2","HelpMeWriteUndoNotice","applied","onUndo","onDismiss","undoRef","isOpen","useHelpMeWriteTemplates","manager","setManager","setApplied","openManager","renderHelpMeWrite","managerNode","useMemo","m"],"mappings":"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"}
@@ -1,28 +1,28 @@
1
- import { jsxs as o, jsx as n, Fragment as Ue } from "react/jsx-runtime";
2
- import { forwardRef as Xe, useRef as f, useState as w, useId as Ze, useCallback as T, useEffect as me, useImperativeHandle as et, useMemo as tt } from "react";
1
+ import { jsxs as o, jsx as n, Fragment as st } from "react/jsx-runtime";
2
+ import { forwardRef as lt, useRef as f, useState as w, useId as rt, useCallback as T, useEffect as me, useImperativeHandle as ot, useMemo as dt } from "react";
3
3
  import { c as Ce } from "./index-D2ZczOXr.js";
4
- import { useTranslation as nt } from "react-i18next";
5
- import { u as at } from "./registry-DvAUVLHh.js";
6
- import { C as it } from "./clinical-note-card-DdsGYMmI.js";
7
- import { R as st } from "./rich-text-editor-D7AKKAQ2.js";
8
- import { T as lt } from "./text-area-Bt3p7Pt0.js";
4
+ import { useTranslation as ct } from "react-i18next";
5
+ import { u as ut } from "./registry-DvAUVLHh.js";
6
+ import { C as ft } from "./clinical-note-card-DdsGYMmI.js";
7
+ import { R as pt } from "./rich-text-editor-DUMeifwc.js";
8
+ import { T as mt } from "./text-area-Bt3p7Pt0.js";
9
9
  import { A as I } from "./alert-CiQ5Pa3Q.js";
10
10
  import { B as z } from "./button-CaUe1uyd.js";
11
11
  import { I as ge } from "./icon-button-CehAeZoP.js";
12
- import { C as rt } from "./checkbox-CZkipDn7.js";
12
+ import { C as gt } from "./checkbox-CZkipDn7.js";
13
13
  import { C as he } from "./card-DPmk26CL.js";
14
- import { C as ot, S as M } from "./skeleton-B1KTdJ4N.js";
14
+ import { C as ht, S as M } from "./skeleton-B1KTdJ4N.js";
15
15
  import { D as v } from "./dialog-BJiLqhx6.js";
16
- import { P as dt } from "./panel-header-D_mTdhUp.js";
17
- import { a as ct, u as ut, R as ft } from "./use-list-reflow-Cw43nxw5.js";
18
- import { u as pt } from "./use-theme-CAuo6EYT.js";
19
- import { N as mt } from "./notebook-pen-CO7HoM-W.js";
20
- import { P as gt } from "./pencil-B1sKKyuT.js";
21
- import { T as ht } from "./trash-2-uumy3fy1.js";
16
+ import { P as vt } from "./panel-header-D_mTdhUp.js";
17
+ import { a as yt, u as bt, R as Ct } from "./use-list-reflow-Cw43nxw5.js";
18
+ import { u as Pt } from "./use-theme-CAuo6EYT.js";
19
+ import { N as xt } from "./notebook-pen-CO7HoM-W.js";
20
+ import { P as wt } from "./pencil-B1sKKyuT.js";
21
+ import { T as Tt } from "./trash-2-uumy3fy1.js";
22
22
  function ve(i, c) {
23
23
  return typeof i == "object" && i !== null && "message" in i && typeof i.message == "string" && i.message.trim() ? i.message : c;
24
24
  }
25
- const vt = {
25
+ const Et = {
26
26
  id: "notes-panel",
27
27
  // 'submit' backs add_note (compose + commit a note). pin / flag are toggles
28
28
  // with no dedicated capability in the closed vocabulary.
@@ -121,7 +121,7 @@ const vt = {
121
121
  description: "Sourced from the id prop. Required to address a specific notes panel from the agent."
122
122
  }
123
123
  }
124
- }, yt = "ds:isolate ds:[&_[data-component=card]>*]:relative ds:[&_[data-component=card]>*]:z-[1]", bt = Ce(
124
+ }, Nt = "ds:isolate ds:[&_[data-component=card]>*]:relative ds:[&_[data-component=card]>*]:z-[1]", Vt = Ce(
125
125
  "ds:relative ds:flex ds:flex-col ds:rounded-[var(--radius-lg)]",
126
126
  {
127
127
  variants: {
@@ -129,7 +129,7 @@ const vt = {
129
129
  true: "ds:focus:outline-[length:var(--focus-ring-width)] ds:focus:outline-solid ds:focus:outline-[color:var(--ring)] ds:focus:outline-offset-[length:var(--focus-ring-offset)]",
130
130
  false: ""
131
131
  },
132
- washed: { true: yt, false: "" }
132
+ washed: { true: Nt, false: "" }
133
133
  },
134
134
  defaultVariants: { current: !1, washed: !1 }
135
135
  }
@@ -148,14 +148,14 @@ const vt = {
148
148
  }
149
149
  }
150
150
  }
151
- ), Ct = "ds:opacity-0", Pt = [
151
+ ), Rt = "ds:opacity-0", kt = [
152
152
  "ds:transition-opacity ds:duration-[var(--animation-duration)]",
153
153
  "ds:ease-[var(--ease-out)] ds:motion-reduce:transition-none"
154
- ].join(" "), xt = [3, 2, 3];
154
+ ].join(" "), _t = [3, 2, 3];
155
155
  function be(i) {
156
156
  return i ? /<img\b/i.test(i) ? !0 : i.replace(/<[^>]*>/g, "").replace(/&nbsp;/gi, " ").trim().length > 0 : !1;
157
157
  }
158
- const Kt = Xe(
158
+ const Xt = lt(
159
159
  function({
160
160
  id: c,
161
161
  notes: j,
@@ -179,24 +179,32 @@ const Kt = Xe(
179
179
  onProofread: _e,
180
180
  onAutoFormat: Se,
181
181
  aiConsent: Ie,
182
+ variables: ze,
183
+ validateVariable: je,
184
+ onVariableValidityChange: Ae,
185
+ renderHelpMeWrite: Le,
186
+ onUploadImage: He,
187
+ onAiCreditsExhausted: Oe,
188
+ composerBefore: Be,
189
+ composerAfter: We,
182
190
  onTogglePin: L,
183
191
  onToggleFlag: H,
184
192
  noteActions: ee,
185
193
  onEditNote: N,
186
- editClinical: ze = !1,
194
+ editClinical: De = !1,
187
195
  onDeleteNote: h,
188
196
  confirmDelete: $ = !0,
189
- title: je,
190
- composerPlaceholder: Ae,
191
- addNoteLabel: Le,
192
- emptyState: He,
193
- className: Oe,
197
+ title: qe,
198
+ composerPlaceholder: Fe,
199
+ addNoteLabel: Ke,
200
+ emptyState: Me,
201
+ className: $e,
194
202
  "aria-label": G,
195
- ...Be
196
- }, We) {
197
- const { t: a, i18n: te } = nt(), b = f(null), [P, V] = w(""), [O, B] = w(E), [u, ne] = w(!1), [ae, R] = w(null), [r, Y] = w(null), ie = f(!1);
203
+ ...Ge
204
+ }, Ye) {
205
+ const { t: a, i18n: te } = ct(), b = f(null), [P, V] = w(""), [O, B] = w(E), [u, ne] = w(!1), [ae, R] = w(null), [r, Y] = w(null), ie = f(!1);
198
206
  C === "loading" && (ie.current = !0);
199
- const De = ie.current ? ot : "", qe = je ?? a("notesPanel.title", { defaultValue: "Notes" }), se = Ze(), le = Ae ?? a("notesPanel.placeholder", { defaultValue: "Add a note…" }), re = r !== null ? a("notesPanel.edit", { defaultValue: "Edit note" }) : a("notesPanel.composerLabel", { defaultValue: "New note" }), Fe = g === "rich" ? be(P) : P.trim().length > 0, Ke = T(() => {
207
+ const Je = ie.current ? ht : "", Qe = qe ?? a("notesPanel.title", { defaultValue: "Notes" }), se = rt(), le = Fe ?? a("notesPanel.placeholder", { defaultValue: "Add a note…" }), re = r !== null ? a("notesPanel.edit", { defaultValue: "Edit note" }) : a("notesPanel.composerLabel", { defaultValue: "New note" }), Ue = g === "rich" ? be(P) : P.trim().length > 0, Xe = T(() => {
200
208
  var x;
201
209
  if (!(r !== null ? N : m) || u) return;
202
210
  const t = g === "rich", d = t ? ((x = b.current) == null ? void 0 : x.getHTML()) ?? P : P.trim();
@@ -228,7 +236,7 @@ const Kt = Xe(
228
236
  N,
229
237
  u,
230
238
  a
231
- ]), oe = Te && (r === null || ze), de = T(
239
+ ]), oe = Te && (r === null || De), de = T(
232
240
  (e) => {
233
241
  try {
234
242
  return new Intl.DateTimeFormat(te.language, {
@@ -243,7 +251,7 @@ const Kt = Xe(
243
251
  }
244
252
  },
245
253
  [te.language]
246
- ), Me = T(
254
+ ), Ze = T(
247
255
  (e) => {
248
256
  var d, l, s;
249
257
  if (!e.id || u) return;
@@ -260,15 +268,15 @@ const Kt = Xe(
260
268
  }, [ce, W]);
261
269
  const k = [...j].sort(
262
270
  (e, t) => Number(t.pinned ?? !1) - Number(e.pinned ?? !1)
263
- ), { resolvedTheme: $e } = pt(), ue = $e.endsWith("-accessible") || void 0, { containerRef: Ge } = ct({
271
+ ), { resolvedTheme: et } = Pt(), ue = et.endsWith("-accessible") || void 0, { containerRef: tt } = yt({
264
272
  key: k.map((e) => e.id).join(),
265
273
  reduceMotion: ue
266
- }), _ = ut({ reduceMotion: ue }), [D, q] = w(null), Ye = T(
274
+ }), _ = bt({ reduceMotion: ue }), [D, q] = w(null), nt = T(
267
275
  (e) => {
268
276
  h && ($ ? q(e) : _.leave(e, () => h(e)));
269
277
  },
270
278
  [$, _, h]
271
- ), Je = T(() => {
279
+ ), at = T(() => {
272
280
  if (!D || !h) return;
273
281
  const e = D;
274
282
  q(null), _.leave(e, () => h(e));
@@ -290,8 +298,8 @@ const Kt = Xe(
290
298
  const fe = f(y);
291
299
  fe.current = y;
292
300
  const pe = f(null);
293
- et(We, () => pe.current, []);
294
- const Qe = tt(
301
+ ot(Ye, () => pe.current, []);
302
+ const it = dt(
295
303
  () => ({
296
304
  // Ids + flags only — never the note body or author (both PHI).
297
305
  getNotes: () => Q.current.map((e) => ({
@@ -320,7 +328,7 @@ const Kt = Xe(
320
328
  }),
321
329
  []
322
330
  );
323
- return at(vt, Qe, c), /* @__PURE__ */ o(
331
+ return ut(Et, it, c), /* @__PURE__ */ o(
324
332
  "section",
325
333
  {
326
334
  ref: pe,
@@ -328,14 +336,14 @@ const Kt = Xe(
328
336
  "data-component-id": c,
329
337
  "aria-labelledby": G ? void 0 : se,
330
338
  "aria-label": G,
331
- className: ["ds:flex ds:flex-col", Oe].filter(Boolean).join(" "),
332
- ...Be,
339
+ className: ["ds:flex ds:flex-col", $e].filter(Boolean).join(" "),
340
+ ...Ge,
333
341
  children: [
334
342
  /* @__PURE__ */ n(
335
- dt,
343
+ vt,
336
344
  {
337
- title: qe,
338
- icon: /* @__PURE__ */ n(mt, { "aria-hidden": "true" }),
345
+ title: Qe,
346
+ icon: /* @__PURE__ */ n(xt, { "aria-hidden": "true" }),
339
347
  headingId: G ? void 0 : se,
340
348
  sticky: !0,
341
349
  divider: !0
@@ -348,8 +356,9 @@ const Kt = Xe(
348
356
  "data-notes-panel-composer": r !== null ? "edit" : "add",
349
357
  className: "ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]",
350
358
  children: [
359
+ Be,
351
360
  g === "rich" ? /* @__PURE__ */ n(
352
- st,
361
+ pt,
353
362
  {
354
363
  ref: b,
355
364
  ariaLabel: re,
@@ -367,10 +376,16 @@ const Kt = Xe(
367
376
  onProofread: _e,
368
377
  onAutoFormat: Se,
369
378
  aiConsent: Ie,
379
+ variables: ze,
380
+ validateVariable: je,
381
+ onVariableValidityChange: Ae,
382
+ renderHelpMeWrite: Le,
383
+ onUploadImage: He,
384
+ onAiCreditsExhausted: Oe,
370
385
  aiConsentHeadingLevel: 3
371
386
  }
372
387
  ) : /* @__PURE__ */ n(
373
- lt,
388
+ mt,
374
389
  {
375
390
  value: P,
376
391
  readOnly: u,
@@ -391,7 +406,7 @@ const Kt = Xe(
391
406
  ].join(" "),
392
407
  children: [
393
408
  oe ? /* @__PURE__ */ n(
394
- rt,
409
+ gt,
395
410
  {
396
411
  size: "sm",
397
412
  label: a("notesPanel.clinicalToggle", {
@@ -422,17 +437,18 @@ const Kt = Xe(
422
437
  {
423
438
  type: "button",
424
439
  size: "sm",
425
- onClick: Ke,
426
- disabled: !Fe,
440
+ onClick: Xe,
441
+ disabled: !Ue,
427
442
  loading: u,
428
- children: r !== null ? a("notesPanel.saveEdit", { defaultValue: "Save note" }) : Le ?? a("notesPanel.add", { defaultValue: "Add note" })
443
+ children: r !== null ? a("notesPanel.saveEdit", { defaultValue: "Save note" }) : Ke ?? a("notesPanel.add", { defaultValue: "Add note" })
429
444
  }
430
445
  )
431
446
  ] })
432
447
  ]
433
448
  }
434
449
  ),
435
- ae ? /* @__PURE__ */ n(I, { variant: "error", children: /* @__PURE__ */ n(I.Description, { children: ae }) }) : null
450
+ ae ? /* @__PURE__ */ n(I, { variant: "error", children: /* @__PURE__ */ n(I.Description, { children: ae }) }) : null,
451
+ We
436
452
  ]
437
453
  }
438
454
  ) : null,
@@ -448,7 +464,7 @@ const Kt = Xe(
448
464
  className: "ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]",
449
465
  children: [
450
466
  /* @__PURE__ */ n("span", { role: "status", className: "ds:sr-only", children: a("notesPanel.loading") }),
451
- xt.map((e, t) => /* @__PURE__ */ n(he, { variant: "elevated", "aria-hidden": "true", children: /* @__PURE__ */ n(he.Body, { children: /* @__PURE__ */ o("div", { className: "ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]", children: [
467
+ _t.map((e, t) => /* @__PURE__ */ n(he, { variant: "elevated", "aria-hidden": "true", children: /* @__PURE__ */ n(he.Body, { children: /* @__PURE__ */ o("div", { className: "ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]", children: [
452
468
  /* @__PURE__ */ o("div", { className: "ds:flex ds:items-center ds:gap-[var(--spacing-sm)]", children: [
453
469
  /* @__PURE__ */ n(
454
470
  M,
@@ -500,9 +516,9 @@ const Kt = Xe(
500
516
  k.length > 0 ? /* @__PURE__ */ n(
501
517
  "ul",
502
518
  {
503
- ref: Ge,
519
+ ref: tt,
504
520
  "aria-busy": C === "loading" || void 0,
505
- className: `ds:m-0 ds:flex ds:list-none ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-0 ${De}`.trim(),
521
+ className: `ds:m-0 ds:flex ds:list-none ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-0 ${Je}`.trim(),
506
522
  children: k.map(({ actions: e, ...t }, d) => {
507
523
  const l = y != null && t.id === y, s = t.id, x = s != null && r === s, p = s != null && _.isLeaving(s);
508
524
  return /* @__PURE__ */ o(
@@ -515,13 +531,13 @@ const Kt = Xe(
515
531
  "data-leaving": p ? "" : void 0,
516
532
  "data-editing": x ? "" : void 0,
517
533
  className: [
518
- bt({
534
+ Vt({
519
535
  current: l,
520
536
  washed: l || x
521
537
  }),
522
- Pt,
523
- ft,
524
- p ? Ct : ""
538
+ kt,
539
+ Ct,
540
+ p ? Rt : ""
525
541
  ].filter(Boolean).join(" "),
526
542
  children: [
527
543
  l ? /* @__PURE__ */ n("span", { className: "ds:sr-only", children: a("notesPanel.current", {
@@ -544,16 +560,16 @@ const Kt = Xe(
544
560
  `${y}:${Z ?? ""}`
545
561
  ) : null,
546
562
  /* @__PURE__ */ n(
547
- it,
563
+ ft,
548
564
  {
549
565
  surface: "elevated",
550
566
  truncate: !l,
551
- headerActions: /* @__PURE__ */ o(Ue, { children: [
567
+ headerActions: /* @__PURE__ */ o(st, { children: [
552
568
  ee ? ee({ ...t, actions: e }) : null,
553
569
  N && s && !t.deleted && (e == null ? void 0 : e.edit) !== !1 ? /* @__PURE__ */ n(
554
570
  ge,
555
571
  {
556
- icon: /* @__PURE__ */ n(gt, {}),
572
+ icon: /* @__PURE__ */ n(wt, {}),
557
573
  intent: "ghost",
558
574
  size: "sm",
559
575
  "aria-label": a("notesPanel.editNamed", {
@@ -566,13 +582,13 @@ const Kt = Xe(
566
582
  "aria-pressed": r === s,
567
583
  disabled: u,
568
584
  "data-notes-panel-edit": "",
569
- onClick: () => r === s ? W() : Me(t)
585
+ onClick: () => r === s ? W() : Ze(t)
570
586
  }
571
587
  ) : null,
572
588
  h && s && !t.deleted ? /* @__PURE__ */ n(
573
589
  ge,
574
590
  {
575
- icon: /* @__PURE__ */ n(ht, {}),
591
+ icon: /* @__PURE__ */ n(Tt, {}),
576
592
  intent: "ghost",
577
593
  size: "sm",
578
594
  "aria-label": a("notesPanel.deleteNamed", {
@@ -582,7 +598,7 @@ const Kt = Xe(
582
598
  tooltip: a("notesPanel.delete", {
583
599
  defaultValue: "Delete note"
584
600
  }),
585
- onClick: () => Ye(s)
601
+ onClick: () => nt(s)
586
602
  }
587
603
  ) : null
588
604
  ] }),
@@ -597,7 +613,7 @@ const Kt = Xe(
597
613
  );
598
614
  })
599
615
  }
600
- ) : C !== "ready" ? null : He ?? /* @__PURE__ */ n("p", { className: "ds:m-0 type-body-sm ds:text-[color:var(--muted-foreground)]", children: a("notesPanel.empty", { defaultValue: "No notes yet." }) })
616
+ ) : C !== "ready" ? null : Me ?? /* @__PURE__ */ n("p", { className: "ds:m-0 type-body-sm ds:text-[color:var(--muted-foreground)]", children: a("notesPanel.empty", { defaultValue: "No notes yet." }) })
601
617
  ] }),
602
618
  h && $ ? /* @__PURE__ */ n(
603
619
  v,
@@ -628,7 +644,7 @@ const Kt = Xe(
628
644
  {
629
645
  intent: "destructive",
630
646
  size: "sm",
631
- onClick: Je,
647
+ onClick: at,
632
648
  children: a("notesPanel.deleteConfirmAction", {
633
649
  defaultValue: "Delete"
634
650
  })
@@ -644,7 +660,7 @@ const Kt = Xe(
644
660
  }
645
661
  );
646
662
  export {
647
- Kt as N,
663
+ Xt as N,
648
664
  ve as g
649
665
  };
650
- //# sourceMappingURL=notes-panel-_diLt8Cj.js.map
666
+ //# sourceMappingURL=notes-panel-CRAovkjx.js.map