@alfadocs/ui-kit-debug 0.69.0 → 0.70.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.
- package/dist/_chunks/{agenda-card-BxSFkqgY.js → agenda-card-BQ-IKAru.js} +2 -2
- package/dist/_chunks/{agenda-card-BxSFkqgY.js.map → agenda-card-BQ-IKAru.js.map} +1 -1
- package/dist/_chunks/{agenda-tray-g0kg7HwB.js → agenda-tray-CGXRk58j.js} +2 -2
- package/dist/_chunks/{agenda-tray-g0kg7HwB.js.map → agenda-tray-CGXRk58j.js.map} +1 -1
- package/dist/_chunks/{ai-consent-banner-CXlsNX1c.js → ai-consent-banner-Be-h9mRI.js} +3 -3
- package/dist/_chunks/{ai-consent-banner-CXlsNX1c.js.map → ai-consent-banner-Be-h9mRI.js.map} +1 -1
- package/dist/_chunks/ai-tools-rail-B5NEghsp.js +511 -0
- package/dist/_chunks/ai-tools-rail-B5NEghsp.js.map +1 -0
- package/dist/_chunks/{alert-_mUKLmwA.js → alert-CHYZ96tR.js} +150 -96
- package/dist/_chunks/alert-CHYZ96tR.js.map +1 -0
- package/dist/_chunks/{anamnesis-card-DRmE24OQ.js → anamnesis-card-DvYCa16e.js} +2 -2
- package/dist/_chunks/{anamnesis-card-DRmE24OQ.js.map → anamnesis-card-DvYCa16e.js.map} +1 -1
- package/dist/_chunks/anatomy-scheme-CJB6dI6p.js +2445 -0
- package/dist/_chunks/anatomy-scheme-CJB6dI6p.js.map +1 -0
- package/dist/_chunks/annotation-marker-qt5R9WZX.js +120 -0
- package/dist/_chunks/annotation-marker-qt5R9WZX.js.map +1 -0
- package/dist/_chunks/{antenatal-schedule-timeline-35ebkcZT.js → antenatal-schedule-timeline-CwXrQRm1.js} +2 -2
- package/dist/_chunks/{antenatal-schedule-timeline-35ebkcZT.js.map → antenatal-schedule-timeline-CwXrQRm1.js.map} +1 -1
- package/dist/_chunks/appointment-card-C06aZqA7.js +310 -0
- package/dist/_chunks/appointment-card-C06aZqA7.js.map +1 -0
- package/dist/_chunks/appointment-timeline-BJM0S_Fg.js +386 -0
- package/dist/_chunks/appointment-timeline-BJM0S_Fg.js.map +1 -0
- package/dist/_chunks/appointment-tray-DRRw5ROi.js +193 -0
- package/dist/_chunks/appointment-tray-DRRw5ROi.js.map +1 -0
- package/dist/_chunks/{audio-recorder-DYXXnGug.js → audio-recorder-Cpdk5qpQ.js} +2 -2
- package/dist/_chunks/{audio-recorder-DYXXnGug.js.map → audio-recorder-Cpdk5qpQ.js.map} +1 -1
- package/dist/_chunks/{badge-CqGsX32l.js → badge-DCOqV9mI.js} +32 -27
- package/dist/_chunks/badge-DCOqV9mI.js.map +1 -0
- package/dist/_chunks/{bishop-score-PJI3AXzA.js → bishop-score-DnYWtZa_.js} +2 -2
- package/dist/_chunks/{bishop-score-PJI3AXzA.js.map → bishop-score-DnYWtZa_.js.map} +1 -1
- package/dist/_chunks/{bmi-calculator-BZtIJ53x.js → bmi-calculator-zjeY4E7J.js} +2 -2
- package/dist/_chunks/{bmi-calculator-BZtIJ53x.js.map → bmi-calculator-zjeY4E7J.js.map} +1 -1
- package/dist/_chunks/{booking-C3VqFReX.js → booking-DUBI0oqt.js} +4 -4
- package/dist/_chunks/{booking-C3VqFReX.js.map → booking-DUBI0oqt.js.map} +1 -1
- package/dist/_chunks/{care-plan-card-CvFGXa2z.js → care-plan-card-C5sTfY9G.js} +5 -5
- package/dist/_chunks/{care-plan-card-CvFGXa2z.js.map → care-plan-card-C5sTfY9G.js.map} +1 -1
- package/dist/_chunks/{care-plan-entry-card-C3E_gClk.js → care-plan-entry-card-CXnxGCWA.js} +5 -5
- package/dist/_chunks/{care-plan-entry-card-C3E_gClk.js.map → care-plan-entry-card-CXnxGCWA.js.map} +1 -1
- package/dist/_chunks/care-plan-header-BUwqDTtz.js +206 -0
- package/dist/_chunks/care-plan-header-BUwqDTtz.js.map +1 -0
- package/dist/_chunks/clinical-note-card-BUvNMNGL.js +436 -0
- package/dist/_chunks/clinical-note-card-BUvNMNGL.js.map +1 -0
- package/dist/_chunks/{contact-profile-card-Dramqa9C.js → contact-profile-card-DDPwRFiP.js} +2 -2
- package/dist/_chunks/{contact-profile-card-Dramqa9C.js.map → contact-profile-card-DDPwRFiP.js.map} +1 -1
- package/dist/_chunks/control-room-rail-Y8ryLYsP.js +229 -0
- package/dist/_chunks/control-room-rail-Y8ryLYsP.js.map +1 -0
- package/dist/_chunks/{cycle-calculator-DmRGJNaT.js → cycle-calculator-CCmPwcBl.js} +2 -2
- package/dist/_chunks/{cycle-calculator-DmRGJNaT.js.map → cycle-calculator-CCmPwcBl.js.map} +1 -1
- package/dist/_chunks/{dependent-selector-CG_FOHya.js → dependent-selector-DUV4thxX.js} +2 -2
- package/dist/_chunks/{dependent-selector-CG_FOHya.js.map → dependent-selector-DUV4thxX.js.map} +1 -1
- package/dist/_chunks/{document-scanner-CTubA0-N.js → document-scanner-C_AxLooF.js} +3 -3
- package/dist/_chunks/{document-scanner-CTubA0-N.js.map → document-scanner-C_AxLooF.js.map} +1 -1
- package/dist/_chunks/{due-date-calculator-BTmsIQqD.js → due-date-calculator-Brdj-euS.js} +3 -3
- package/dist/_chunks/{due-date-calculator-BTmsIQqD.js.map → due-date-calculator-Brdj-euS.js.map} +1 -1
- package/dist/_chunks/editable-currency-cell-renderer-C9twtALM.js +328 -0
- package/dist/_chunks/editable-currency-cell-renderer-C9twtALM.js.map +1 -0
- package/dist/_chunks/email-input-DJ7EXklP.js +397 -0
- package/dist/_chunks/{email-input-B_Y55f5G.js.map → email-input-DJ7EXklP.js.map} +1 -1
- package/dist/_chunks/{entity-card-COhmqHly.js → entity-card-9_62gY7l.js} +38 -20
- package/dist/_chunks/{entity-card-COhmqHly.js.map → entity-card-9_62gY7l.js.map} +1 -1
- package/dist/_chunks/entity-summary-BxRjFh_4.js +138 -0
- package/dist/_chunks/entity-summary-BxRjFh_4.js.map +1 -0
- package/dist/_chunks/{fetal-weight-CRz7KE2D.js → fetal-weight-DNCkyeVo.js} +2 -2
- package/dist/_chunks/{fetal-weight-CRz7KE2D.js.map → fetal-weight-DNCkyeVo.js.map} +1 -1
- package/dist/_chunks/field-value-NXYczdpO.js +415 -0
- package/dist/_chunks/field-value-NXYczdpO.js.map +1 -0
- package/dist/_chunks/{file-upload-5ScQd4fE.js → file-upload-DwZcAK8D.js} +2 -1
- package/dist/_chunks/{file-upload-5ScQd4fE.js.map → file-upload-DwZcAK8D.js.map} +1 -1
- package/dist/_chunks/{freemium-paywall-DZ2mBS3w.js → freemium-paywall-WYlNO7yT.js} +2 -2
- package/dist/_chunks/{freemium-paywall-DZ2mBS3w.js.map → freemium-paywall-WYlNO7yT.js.map} +1 -1
- package/dist/_chunks/{gestational-age-calculator-BleUdhbI.js → gestational-age-calculator-CF2ISaYQ.js} +3 -3
- package/dist/_chunks/{gestational-age-calculator-BleUdhbI.js.map → gestational-age-calculator-CF2ISaYQ.js.map} +1 -1
- package/dist/_chunks/hash-CysBBS_N.js +17 -0
- package/dist/_chunks/hash-CysBBS_N.js.map +1 -0
- package/dist/_chunks/{hcg-doubling-CnjDXX6U.js → hcg-doubling-C7bmuaU3.js} +2 -2
- package/dist/_chunks/{hcg-doubling-CnjDXX6U.js.map → hcg-doubling-C7bmuaU3.js.map} +1 -1
- package/dist/_chunks/{actions-cell-renderer-DrcaxB0w.js → link-cell-renderer-CTXqtXV-.js} +715 -592
- package/dist/_chunks/link-cell-renderer-CTXqtXV-.js.map +1 -0
- package/dist/_chunks/lock-CKOIn0IK.js +15 -0
- package/dist/_chunks/lock-CKOIn0IK.js.map +1 -0
- package/dist/_chunks/{marketplace-app-shell-6T9W4Knl.js → marketplace-app-shell-Skhfp6vK.js} +3 -3
- package/dist/_chunks/{marketplace-app-shell-6T9W4Knl.js.map → marketplace-app-shell-Skhfp6vK.js.map} +1 -1
- package/dist/_chunks/notes-panel-ay8_lPrA.js +158 -0
- package/dist/_chunks/notes-panel-ay8_lPrA.js.map +1 -0
- package/dist/_chunks/{notification-card-BiESdm8q.js → notification-card-D2jiKSJJ.js} +27 -23
- package/dist/_chunks/notification-card-D2jiKSJJ.js.map +1 -0
- package/dist/_chunks/{notification-tray-Btb9oQeZ.js → notification-tray-AEun6DN2.js} +2 -2
- package/dist/_chunks/{notification-tray-Btb9oQeZ.js.map → notification-tray-AEun6DN2.js.map} +1 -1
- package/dist/_chunks/{operator-hero-CP2Nhupm.js → operator-hero-CR0Rqh4-.js} +3 -3
- package/dist/_chunks/{operator-hero-CP2Nhupm.js.map → operator-hero-CR0Rqh4-.js.map} +1 -1
- package/dist/_chunks/patient-details-Dlhqb5ig.js +675 -0
- package/dist/_chunks/patient-details-Dlhqb5ig.js.map +1 -0
- package/dist/_chunks/{patient-search-CBC_ySF6.js → patient-search-Be6cLrHR.js} +2 -2
- package/dist/_chunks/{patient-search-CBC_ySF6.js.map → patient-search-Be6cLrHR.js.map} +1 -1
- package/dist/_chunks/patient-summary-card-WySCMwwA.js +437 -0
- package/dist/_chunks/patient-summary-card-WySCMwwA.js.map +1 -0
- package/dist/_chunks/patient-table-CHxf3Oqk.js +1110 -0
- package/dist/_chunks/patient-table-CHxf3Oqk.js.map +1 -0
- package/dist/_chunks/{payment-form-DvjwYVIT.js → payment-form-CxqIXqw7.js} +2 -2
- package/dist/_chunks/{payment-form-DvjwYVIT.js.map → payment-form-CxqIXqw7.js.map} +1 -1
- package/dist/_chunks/{payment-request-card-DioWKBUq.js → payment-request-card-BcZJwu9z.js} +125 -136
- package/dist/_chunks/payment-request-card-BcZJwu9z.js.map +1 -0
- package/dist/_chunks/{pdf-viewer-D6BPfW2D.js → pdf-viewer-QfebdLOd.js} +192 -214
- package/dist/_chunks/pdf-viewer-QfebdLOd.js.map +1 -0
- package/dist/_chunks/{periodontal-chart-card-BuDEMbHE.js → periodontal-chart-card-hRRJY1NN.js} +2 -2
- package/dist/_chunks/{periodontal-chart-card-BuDEMbHE.js.map → periodontal-chart-card-hRRJY1NN.js.map} +1 -1
- package/dist/_chunks/{practice-results-KrTHqZua.js → practice-results-C6qDfxos.js} +3 -3
- package/dist/_chunks/{practice-results-KrTHqZua.js.map → practice-results-C6qDfxos.js.map} +1 -1
- package/dist/_chunks/{pregnancy-dating-DORUAOHB.js → pregnancy-dating-CRVWswD-.js} +3 -3
- package/dist/_chunks/{pregnancy-dating-DORUAOHB.js.map → pregnancy-dating-CRVWswD-.js.map} +1 -1
- package/dist/_chunks/{pregnancy-weight-gain-DVz4rr7-.js → pregnancy-weight-gain-BUNpTsH-.js} +2 -2
- package/dist/_chunks/{pregnancy-weight-gain-DVz4rr7-.js.map → pregnancy-weight-gain-BUNpTsH-.js.map} +1 -1
- package/dist/_chunks/radiograph-panel.agent-CAX-C3g3.js +558 -0
- package/dist/_chunks/radiograph-panel.agent-CAX-C3g3.js.map +1 -0
- package/dist/_chunks/{rich-text-editor-BsV7zUdg.js → rich-text-editor-DlCqPixb.js} +410 -394
- package/dist/_chunks/{rich-text-editor-BsV7zUdg.js.map → rich-text-editor-DlCqPixb.js.map} +1 -1
- package/dist/_chunks/{sign-document-B4DeRhTe.js → sign-document-By6hMOra.js} +2 -2
- package/dist/_chunks/{sign-document-B4DeRhTe.js.map → sign-document-By6hMOra.js.map} +1 -1
- package/dist/_chunks/{stepper-accordion-Dki6r9ZE.js → stepper-accordion-DC-H-8v4.js} +38 -48
- package/dist/_chunks/stepper-accordion-DC-H-8v4.js.map +1 -0
- package/dist/_chunks/tab-bar-Bv9nGNdO.js +262 -0
- package/dist/_chunks/tab-bar-Bv9nGNdO.js.map +1 -0
- package/dist/_chunks/tooth-scheme-BhQoPNBD.js +2131 -0
- package/dist/_chunks/tooth-scheme-BhQoPNBD.js.map +1 -0
- package/dist/_chunks/{transaction-chip-DK84XCBU.js → transaction-chip-CscoQbxF.js} +88 -61
- package/dist/_chunks/transaction-chip-CscoQbxF.js.map +1 -0
- package/dist/_chunks/use-clamp-overflow-DQE2kwZ9.js +20 -0
- package/dist/_chunks/use-clamp-overflow-DQE2kwZ9.js.map +1 -0
- package/dist/_chunks/use-overflow-collapse-BIOzKbni.js +32 -0
- package/dist/_chunks/use-overflow-collapse-BIOzKbni.js.map +1 -0
- package/dist/_chunks/use-persistent-state-nZwZAnE9.js +24 -0
- package/dist/_chunks/use-persistent-state-nZwZAnE9.js.map +1 -0
- package/dist/_chunks/{warning-stack-BsgaEbL8.js → warning-stack--sTrrBDA.js} +86 -101
- package/dist/_chunks/warning-stack--sTrrBDA.js.map +1 -0
- package/dist/_chunks/{workflow-map-Bdam9pGp.js → workflow-map-Dy8mLCqF.js} +3 -3
- package/dist/_chunks/{workflow-map-Bdam9pGp.js.map → workflow-map-Dy8mLCqF.js.map} +1 -1
- package/dist/_chunks/zoom-out-CgVtf2Wx.js +29 -0
- package/dist/_chunks/zoom-out-CgVtf2Wx.js.map +1 -0
- package/dist/agent/index.js +5 -4
- package/dist/agent/index.js.map +1 -1
- package/dist/agent/types.d.ts +19 -2
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/agent-catalog.json +1253 -86
- package/dist/agent-i18n/en.json +108 -6
- package/dist/components/_shared/entity-card/entity-card.d.ts +6 -0
- package/dist/components/_shared/entity-card/entity-card.d.ts.map +1 -1
- package/dist/components/_shared/entity-card/index.d.ts +1 -1
- package/dist/components/_shared/entity-card/index.d.ts.map +1 -1
- package/dist/components/_shared/field-value.d.ts +21 -0
- package/dist/components/_shared/field-value.d.ts.map +1 -0
- package/dist/components/_shared/field-visibility-cog.d.ts +20 -0
- package/dist/components/_shared/field-visibility-cog.d.ts.map +1 -0
- package/dist/components/_shared/field-visibility.d.ts +36 -0
- package/dist/components/_shared/field-visibility.d.ts.map +1 -0
- package/dist/components/_shared/patient-fields.d.ts +119 -0
- package/dist/components/_shared/patient-fields.d.ts.map +1 -0
- package/dist/components/agenda-card/index.js +1 -1
- package/dist/components/agenda-tray/index.js +1 -1
- package/dist/components/ai-consent-banner/index.js +1 -1
- package/dist/components/ai-tools-rail/ai-tools-rail.d.ts +75 -0
- package/dist/components/ai-tools-rail/ai-tools-rail.d.ts.map +1 -1
- package/dist/components/ai-tools-rail/index.js +1 -1
- package/dist/components/alert/alert.d.ts +5 -0
- package/dist/components/alert/alert.d.ts.map +1 -1
- package/dist/components/alert/index.js +1 -1
- package/dist/components/anamnesis-card/index.js +1 -1
- package/dist/components/anatomy-scheme/anatomy-face-paths.d.ts +15 -0
- package/dist/components/anatomy-scheme/anatomy-face-paths.d.ts.map +1 -0
- package/dist/components/anatomy-scheme/anatomy-muscle-paths.d.ts +20 -0
- package/dist/components/anatomy-scheme/anatomy-muscle-paths.d.ts.map +1 -0
- package/dist/components/anatomy-scheme/anatomy-scheme-data.d.ts +121 -0
- package/dist/components/anatomy-scheme/anatomy-scheme-data.d.ts.map +1 -0
- package/dist/components/anatomy-scheme/anatomy-scheme.agent.d.ts +6 -0
- package/dist/components/anatomy-scheme/anatomy-scheme.agent.d.ts.map +1 -0
- package/dist/components/anatomy-scheme/anatomy-scheme.d.ts +69 -0
- package/dist/components/anatomy-scheme/anatomy-scheme.d.ts.map +1 -0
- package/dist/components/anatomy-scheme/index.d.ts +6 -0
- package/dist/components/anatomy-scheme/index.d.ts.map +1 -0
- package/dist/components/anatomy-scheme/index.js +17 -0
- package/dist/components/anatomy-scheme/index.js.map +1 -0
- package/dist/components/annotation-marker/annotation-marker.d.ts +33 -0
- package/dist/components/annotation-marker/annotation-marker.d.ts.map +1 -0
- package/dist/components/annotation-marker/index.d.ts +3 -0
- package/dist/components/annotation-marker/index.d.ts.map +1 -0
- package/dist/components/annotation-marker/index.js +7 -0
- package/dist/components/annotation-marker/index.js.map +1 -0
- package/dist/components/appointment-card/appointment-card.d.ts +25 -1
- package/dist/components/appointment-card/appointment-card.d.ts.map +1 -1
- package/dist/components/appointment-card/index.js +6 -5
- package/dist/components/appointment-card/index.js.map +1 -1
- package/dist/components/appointment-timeline/appointment-timeline.agent.d.ts +4 -0
- package/dist/components/appointment-timeline/appointment-timeline.agent.d.ts.map +1 -0
- package/dist/components/appointment-timeline/appointment-timeline.d.ts +66 -0
- package/dist/components/appointment-timeline/appointment-timeline.d.ts.map +1 -0
- package/dist/components/appointment-timeline/index.d.ts +4 -0
- package/dist/components/appointment-timeline/index.d.ts.map +1 -0
- package/dist/components/appointment-timeline/index.js +6 -0
- package/dist/components/appointment-timeline/index.js.map +1 -0
- package/dist/components/audio-recorder/index.js +1 -1
- package/dist/components/badge/badge.d.ts +6 -2
- package/dist/components/badge/badge.d.ts.map +1 -1
- package/dist/components/badge/index.js +1 -1
- package/dist/components/bishop-score/index.js +1 -1
- package/dist/components/bmi-calculator/index.js +1 -1
- package/dist/components/booking/index.js +1 -1
- package/dist/components/care-plan-card/index.js +1 -1
- package/dist/components/care-plan-entry-card/index.js +1 -1
- package/dist/components/care-plan-header/care-plan-header.agent.d.ts +4 -0
- package/dist/components/care-plan-header/care-plan-header.agent.d.ts.map +1 -0
- package/dist/components/care-plan-header/care-plan-header.d.ts +100 -0
- package/dist/components/care-plan-header/care-plan-header.d.ts.map +1 -0
- package/dist/components/care-plan-header/index.d.ts +4 -0
- package/dist/components/care-plan-header/index.d.ts.map +1 -0
- package/dist/components/care-plan-header/index.js +6 -0
- package/dist/components/care-plan-header/index.js.map +1 -0
- package/dist/components/clinical-note-card/clinical-note-card.d.ts +21 -1
- package/dist/components/clinical-note-card/clinical-note-card.d.ts.map +1 -1
- package/dist/components/clinical-note-card/index.js +1 -1
- package/dist/components/contact-profile-card/index.js +1 -1
- package/dist/components/control-room-rail/control-room-context.d.ts +53 -0
- package/dist/components/control-room-rail/control-room-context.d.ts.map +1 -0
- package/dist/components/control-room-rail/control-room-rail.d.ts +35 -0
- package/dist/components/control-room-rail/control-room-rail.d.ts.map +1 -0
- package/dist/components/control-room-rail/index.d.ts +5 -0
- package/dist/components/control-room-rail/index.d.ts.map +1 -0
- package/dist/components/control-room-rail/index.js +9 -0
- package/dist/components/control-room-rail/index.js.map +1 -0
- package/dist/components/cycle-calculator/index.js +1 -1
- package/dist/components/data-table/cell-renderers/actions-cell-renderer.d.ts +18 -0
- package/dist/components/data-table/cell-renderers/actions-cell-renderer.d.ts.map +1 -1
- package/dist/components/data-table/index.d.ts +1 -1
- package/dist/components/data-table/index.d.ts.map +1 -1
- package/dist/components/data-table/index.js +32 -31
- package/dist/components/dependent-selector/index.js +1 -1
- package/dist/components/document-scanner/index.js +1 -1
- package/dist/components/due-date-calculator/index.js +2 -2
- package/dist/components/email-input/email-input.d.ts.map +1 -1
- package/dist/components/email-input/index.js +1 -1
- package/dist/components/entity-summary/entity-summary.d.ts +43 -0
- package/dist/components/entity-summary/entity-summary.d.ts.map +1 -0
- package/dist/components/entity-summary/index.d.ts +3 -0
- package/dist/components/entity-summary/index.d.ts.map +1 -0
- package/dist/components/entity-summary/index.js +5 -0
- package/dist/components/entity-summary/index.js.map +1 -0
- package/dist/components/fetal-weight/index.js +1 -1
- package/dist/components/file-upload/index.js +1 -1
- package/dist/components/freemium-paywall/index.js +1 -1
- package/dist/components/gestational-age-calculator/index.js +1 -1
- package/dist/components/hcg-doubling/index.js +1 -1
- package/dist/components/index.d.ts +9 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/notes-panel/index.d.ts +3 -0
- package/dist/components/notes-panel/index.d.ts.map +1 -0
- package/dist/components/notes-panel/index.js +5 -0
- package/dist/components/notes-panel/index.js.map +1 -0
- package/dist/components/notes-panel/notes-panel.d.ts +64 -0
- package/dist/components/notes-panel/notes-panel.d.ts.map +1 -0
- package/dist/components/notification-card/index.js +1 -1
- package/dist/components/notification-card/notification-card.d.ts.map +1 -1
- package/dist/components/notification-tray/index.js +1 -1
- package/dist/components/operator-hero/index.js +1 -1
- package/dist/components/patient-details/index.d.ts +5 -0
- package/dist/components/patient-details/index.d.ts.map +1 -0
- package/dist/components/patient-details/index.js +6 -0
- package/dist/components/patient-details/index.js.map +1 -0
- package/dist/components/patient-details/patient-details.agent.d.ts +4 -0
- package/dist/components/patient-details/patient-details.agent.d.ts.map +1 -0
- package/dist/components/patient-details/patient-details.d.ts +96 -0
- package/dist/components/patient-details/patient-details.d.ts.map +1 -0
- package/dist/components/patient-search/index.js +1 -1
- package/dist/components/patient-summary-card/index.js +1 -1
- package/dist/components/patient-summary-card/patient-summary-card.agent.d.ts.map +1 -1
- package/dist/components/patient-summary-card/patient-summary-card.d.ts +40 -1
- package/dist/components/patient-summary-card/patient-summary-card.d.ts.map +1 -1
- package/dist/components/patient-table/columns.d.ts +69 -40
- package/dist/components/patient-table/columns.d.ts.map +1 -1
- package/dist/components/patient-table/index.d.ts +2 -6
- package/dist/components/patient-table/index.d.ts.map +1 -1
- package/dist/components/patient-table/index.js +8 -9
- package/dist/components/patient-table/patient-table.d.ts +38 -4
- package/dist/components/patient-table/patient-table.d.ts.map +1 -1
- package/dist/components/patient-table/types.d.ts +52 -2
- package/dist/components/patient-table/types.d.ts.map +1 -1
- package/dist/components/patient-table/use-responsive-columns.d.ts +8 -6
- package/dist/components/patient-table/use-responsive-columns.d.ts.map +1 -1
- package/dist/components/payment-card/index.js +1 -1
- package/dist/components/payment-form/index.js +1 -1
- package/dist/components/pdf-viewer/index.js +1 -1
- package/dist/components/periodontal-chart-card/index.js +1 -1
- package/dist/components/practice-results/index.js +1 -1
- package/dist/components/pregnancy-dating/index.js +1 -1
- package/dist/components/pregnancy-weight-gain/index.js +1 -1
- package/dist/components/radiograph-panel/index.d.ts +4 -0
- package/dist/components/radiograph-panel/index.d.ts.map +1 -0
- package/dist/components/radiograph-panel/index.js +7 -0
- package/dist/components/radiograph-panel/index.js.map +1 -0
- package/dist/components/radiograph-panel/radiograph-panel.agent.d.ts +13 -0
- package/dist/components/radiograph-panel/radiograph-panel.agent.d.ts.map +1 -0
- package/dist/components/radiograph-panel/radiograph-panel.d.ts +36 -0
- package/dist/components/radiograph-panel/radiograph-panel.d.ts.map +1 -0
- package/dist/components/rich-text-editor/index.js +1 -1
- package/dist/components/rich-text-editor/rich-text-editor.d.ts.map +1 -1
- package/dist/components/sidebar/index.js +1 -1
- package/dist/components/sign-document/index.js +1 -1
- package/dist/components/stepper-accordion/index.js +1 -1
- package/dist/components/tab-bar/index.js +1 -1
- package/dist/components/tab-bar/tab-bar.d.ts +18 -1
- package/dist/components/tab-bar/tab-bar.d.ts.map +1 -1
- package/dist/components/tooth-scheme/index.d.ts +2 -2
- package/dist/components/tooth-scheme/index.d.ts.map +1 -1
- package/dist/components/tooth-scheme/index.js +30 -23
- package/dist/components/tooth-scheme/tooth-data.d.ts +112 -1
- package/dist/components/tooth-scheme/tooth-data.d.ts.map +1 -1
- package/dist/components/tooth-scheme/tooth-scheme.agent.d.ts +2 -2
- package/dist/components/tooth-scheme/tooth-scheme.agent.d.ts.map +1 -1
- package/dist/components/tooth-scheme/tooth-scheme.d.ts +75 -11
- package/dist/components/tooth-scheme/tooth-scheme.d.ts.map +1 -1
- package/dist/components/transaction-chip/index.js +1 -1
- package/dist/components/transaction-chip/transaction-chip.d.ts +2 -2
- package/dist/components/transaction-chip/transaction-chip.d.ts.map +1 -1
- package/dist/components/warning-stack/index.js +1 -1
- package/dist/components/warning-stack/warning-stack.d.ts +10 -7
- package/dist/components/warning-stack/warning-stack.d.ts.map +1 -1
- package/dist/components/workflow/index.js +1 -1
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +24 -22
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/use-clamp-overflow.d.ts +19 -0
- package/dist/hooks/use-clamp-overflow.d.ts.map +1 -0
- package/dist/hooks/use-overflow-collapse.d.ts +46 -0
- package/dist/hooks/use-overflow-collapse.d.ts.map +1 -0
- package/dist/hooks/use-persistent-state.d.ts +7 -1
- package/dist/hooks/use-persistent-state.d.ts.map +1 -1
- package/dist/hooks/use-scroll-overflow.d.ts +36 -0
- package/dist/hooks/use-scroll-overflow.d.ts.map +1 -0
- package/dist/i18n/locales/ar.d.ts +308 -24
- package/dist/i18n/locales/ar.d.ts.map +1 -1
- package/dist/i18n/locales/ar.js +322 -27
- package/dist/i18n/locales/ar.js.map +1 -1
- package/dist/i18n/locales/de.d.ts +308 -24
- package/dist/i18n/locales/de.d.ts.map +1 -1
- package/dist/i18n/locales/de.js +322 -27
- package/dist/i18n/locales/de.js.map +1 -1
- package/dist/i18n/locales/el.d.ts +308 -24
- package/dist/i18n/locales/el.d.ts.map +1 -1
- package/dist/i18n/locales/el.js +322 -27
- package/dist/i18n/locales/el.js.map +1 -1
- package/dist/i18n/locales/en.d.ts +309 -32
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/en.js +323 -35
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +308 -24
- package/dist/i18n/locales/es.d.ts.map +1 -1
- package/dist/i18n/locales/es.js +322 -27
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +308 -24
- package/dist/i18n/locales/fr.d.ts.map +1 -1
- package/dist/i18n/locales/fr.js +322 -27
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hi.d.ts +308 -24
- package/dist/i18n/locales/hi.d.ts.map +1 -1
- package/dist/i18n/locales/hi.js +322 -27
- package/dist/i18n/locales/hi.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +308 -24
- package/dist/i18n/locales/it.d.ts.map +1 -1
- package/dist/i18n/locales/it.js +322 -27
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/ja.d.ts +308 -24
- package/dist/i18n/locales/ja.d.ts.map +1 -1
- package/dist/i18n/locales/ja.js +322 -27
- package/dist/i18n/locales/ja.js.map +1 -1
- package/dist/i18n/locales/nl.d.ts +308 -24
- package/dist/i18n/locales/nl.d.ts.map +1 -1
- package/dist/i18n/locales/nl.js +322 -27
- package/dist/i18n/locales/nl.js.map +1 -1
- package/dist/i18n/locales/pl.d.ts +308 -24
- package/dist/i18n/locales/pl.d.ts.map +1 -1
- package/dist/i18n/locales/pl.js +322 -27
- package/dist/i18n/locales/pl.js.map +1 -1
- package/dist/i18n/locales/pt.d.ts +308 -24
- package/dist/i18n/locales/pt.d.ts.map +1 -1
- package/dist/i18n/locales/pt.js +322 -27
- package/dist/i18n/locales/pt.js.map +1 -1
- package/dist/i18n/locales/ro.d.ts +308 -24
- package/dist/i18n/locales/ro.d.ts.map +1 -1
- package/dist/i18n/locales/ro.js +322 -27
- package/dist/i18n/locales/ro.js.map +1 -1
- package/dist/i18n/locales/ru.d.ts +308 -24
- package/dist/i18n/locales/ru.d.ts.map +1 -1
- package/dist/i18n/locales/ru.js +322 -27
- package/dist/i18n/locales/ru.js.map +1 -1
- package/dist/i18n/locales/sq.d.ts +308 -24
- package/dist/i18n/locales/sq.d.ts.map +1 -1
- package/dist/i18n/locales/sq.js +322 -27
- package/dist/i18n/locales/sq.js.map +1 -1
- package/dist/i18n/locales/sv.d.ts +308 -24
- package/dist/i18n/locales/sv.d.ts.map +1 -1
- package/dist/i18n/locales/sv.js +322 -27
- package/dist/i18n/locales/sv.js.map +1 -1
- package/dist/i18n/locales/tr.d.ts +308 -24
- package/dist/i18n/locales/tr.d.ts.map +1 -1
- package/dist/i18n/locales/tr.js +322 -27
- package/dist/i18n/locales/tr.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +308 -24
- package/dist/i18n/locales/zh.d.ts.map +1 -1
- package/dist/i18n/locales/zh.js +322 -27
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/index.js +672 -623
- package/dist/index.js.map +1 -1
- package/dist/locales/ar.json +311 -27
- package/dist/locales/de.json +311 -27
- package/dist/locales/el.json +311 -27
- package/dist/locales/en.json +311 -27
- package/dist/locales/es.json +311 -27
- package/dist/locales/fr.json +311 -27
- package/dist/locales/hi.json +311 -27
- package/dist/locales/it.json +311 -27
- package/dist/locales/ja.json +311 -27
- package/dist/locales/nl.json +311 -27
- package/dist/locales/pl.json +311 -27
- package/dist/locales/pt.json +311 -27
- package/dist/locales/ro.json +311 -27
- package/dist/locales/ru.json +311 -27
- package/dist/locales/sq.json +311 -27
- package/dist/locales/sv.json +311 -27
- package/dist/locales/tr.json +311 -27
- package/dist/locales/zh.json +311 -27
- package/dist/patterns/marketplace-app-shell/index.js +1 -1
- package/dist/tokens.css +1 -1
- package/package.json +37 -1
- package/dist/_chunks/actions-cell-renderer-DrcaxB0w.js.map +0 -1
- package/dist/_chunks/ai-tools-rail-BA_sqy1A.js +0 -373
- package/dist/_chunks/ai-tools-rail-BA_sqy1A.js.map +0 -1
- package/dist/_chunks/alert-_mUKLmwA.js.map +0 -1
- package/dist/_chunks/appointment-tray-CZtvtaH-.js +0 -431
- package/dist/_chunks/appointment-tray-CZtvtaH-.js.map +0 -1
- package/dist/_chunks/badge-CqGsX32l.js.map +0 -1
- package/dist/_chunks/clinical-note-card-DqQYf_D4.js +0 -333
- package/dist/_chunks/clinical-note-card-DqQYf_D4.js.map +0 -1
- package/dist/_chunks/editable-currency-cell-renderer-kgqp_mIw.js +0 -448
- package/dist/_chunks/editable-currency-cell-renderer-kgqp_mIw.js.map +0 -1
- package/dist/_chunks/email-input-B_Y55f5G.js +0 -396
- package/dist/_chunks/notification-card-BiESdm8q.js.map +0 -1
- package/dist/_chunks/patient-summary-card-B836_fDB.js +0 -435
- package/dist/_chunks/patient-summary-card-B836_fDB.js.map +0 -1
- package/dist/_chunks/patient-table-CDuosVru.js +0 -889
- package/dist/_chunks/patient-table-CDuosVru.js.map +0 -1
- package/dist/_chunks/payment-request-card-DioWKBUq.js.map +0 -1
- package/dist/_chunks/pdf-viewer-D6BPfW2D.js.map +0 -1
- package/dist/_chunks/stepper-accordion-Dki6r9ZE.js.map +0 -1
- package/dist/_chunks/tab-bar-B1ovILzh.js +0 -105
- package/dist/_chunks/tab-bar-B1ovILzh.js.map +0 -1
- package/dist/_chunks/tooth-scheme-yBr53cvv.js +0 -1330
- package/dist/_chunks/tooth-scheme-yBr53cvv.js.map +0 -1
- package/dist/_chunks/transaction-chip-DK84XCBU.js.map +0 -1
- package/dist/_chunks/use-persistent-state-i23OWy6G.js +0 -24
- package/dist/_chunks/use-persistent-state-i23OWy6G.js.map +0 -1
- package/dist/_chunks/warning-stack-BsgaEbL8.js.map +0 -1
- package/dist/components/patient-table/cell-renderers/contact-cell.d.ts +0 -45
- package/dist/components/patient-table/cell-renderers/contact-cell.d.ts.map +0 -1
- package/dist/components/patient-table/cell-renderers/patient-identity-cell.d.ts +0 -26
- package/dist/components/patient-table/cell-renderers/patient-identity-cell.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rich-text-editor-BsV7zUdg.js","sources":["../../node_modules/lucide-react/dist/esm/icons/between-horizontal-end.js","../../node_modules/lucide-react/dist/esm/icons/between-horizontal-start.js","../../node_modules/lucide-react/dist/esm/icons/between-vertical-end.js","../../node_modules/lucide-react/dist/esm/icons/between-vertical-start.js","../../node_modules/lucide-react/dist/esm/icons/bold.js","../../node_modules/lucide-react/dist/esm/icons/heading-2.js","../../node_modules/lucide-react/dist/esm/icons/heading-3.js","../../node_modules/lucide-react/dist/esm/icons/highlighter.js","../../node_modules/lucide-react/dist/esm/icons/italic.js","../../node_modules/lucide-react/dist/esm/icons/link.js","../../node_modules/lucide-react/dist/esm/icons/list-ordered.js","../../node_modules/lucide-react/dist/esm/icons/list.js","../../node_modules/lucide-react/dist/esm/icons/paint-bucket.js","../../node_modules/lucide-react/dist/esm/icons/paint-roller.js","../../node_modules/lucide-react/dist/esm/icons/palette.js","../../node_modules/lucide-react/dist/esm/icons/panel-top-dashed.js","../../node_modules/lucide-react/dist/esm/icons/panel-top.js","../../node_modules/lucide-react/dist/esm/icons/pilcrow.js","../../node_modules/lucide-react/dist/esm/icons/quote.js","../../node_modules/lucide-react/dist/esm/icons/rows-2.js","../../node_modules/lucide-react/dist/esm/icons/spell-check.js","../../node_modules/lucide-react/dist/esm/icons/strikethrough.js","../../node_modules/lucide-react/dist/esm/icons/table.js","../../node_modules/lucide-react/dist/esm/icons/underline.js","../../node_modules/lucide-react/dist/esm/icons/wand-sparkles.js","../../node_modules/lucide-react/dist/esm/icons/wrench.js","../../src/components/rich-text-editor/rich-text-editor.agent.ts","../../src/components/rich-text-editor/help-me-write-overlay.tsx","../../src/components/rich-text-editor/editor-toolbar.tsx","../../src/components/rich-text-editor/rich-text-editor.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"13\", height: \"7\", x: \"3\", y: \"3\", rx: \"1\", key: \"11xb64\" }],\n [\"path\", { d: \"m22 15-3-3 3-3\", key: \"26chmm\" }],\n [\"rect\", { width: \"13\", height: \"7\", x: \"3\", y: \"14\", rx: \"1\", key: \"k6ky7n\" }]\n];\nconst BetweenHorizontalEnd = createLucideIcon(\"between-horizontal-end\", __iconNode);\n\nexport { __iconNode, BetweenHorizontalEnd as default };\n//# sourceMappingURL=between-horizontal-end.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"13\", height: \"7\", x: \"8\", y: \"3\", rx: \"1\", key: \"pkso9a\" }],\n [\"path\", { d: \"m2 9 3 3-3 3\", key: \"1agib5\" }],\n [\"rect\", { width: \"13\", height: \"7\", x: \"8\", y: \"14\", rx: \"1\", key: \"1q5fc1\" }]\n];\nconst BetweenHorizontalStart = createLucideIcon(\"between-horizontal-start\", __iconNode);\n\nexport { __iconNode, BetweenHorizontalStart as default };\n//# sourceMappingURL=between-horizontal-start.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"7\", height: \"13\", x: \"3\", y: \"3\", rx: \"1\", key: \"1fdu0f\" }],\n [\"path\", { d: \"m9 22 3-3 3 3\", key: \"17z65a\" }],\n [\"rect\", { width: \"7\", height: \"13\", x: \"14\", y: \"3\", rx: \"1\", key: \"1squn4\" }]\n];\nconst BetweenVerticalEnd = createLucideIcon(\"between-vertical-end\", __iconNode);\n\nexport { __iconNode, BetweenVerticalEnd as default };\n//# sourceMappingURL=between-vertical-end.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"7\", height: \"13\", x: \"3\", y: \"8\", rx: \"1\", key: \"1fjrkv\" }],\n [\"path\", { d: \"m15 2-3 3-3-3\", key: \"1uh6eb\" }],\n [\"rect\", { width: \"7\", height: \"13\", x: \"14\", y: \"8\", rx: \"1\", key: \"w3fjg8\" }]\n];\nconst BetweenVerticalStart = createLucideIcon(\"between-vertical-start\", __iconNode);\n\nexport { __iconNode, BetweenVerticalStart as default };\n//# sourceMappingURL=between-vertical-start.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n { d: \"M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8\", key: \"mg9rjx\" }\n ]\n];\nconst Bold = createLucideIcon(\"bold\", __iconNode);\n\nexport { __iconNode, Bold as default };\n//# sourceMappingURL=bold.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M4 12h8\", key: \"17cfdx\" }],\n [\"path\", { d: \"M4 18V6\", key: \"1rz3zl\" }],\n [\"path\", { d: \"M12 18V6\", key: \"zqpxq5\" }],\n [\"path\", { d: \"M21 18h-4c0-4 4-3 4-6 0-1.5-2-2.5-4-1\", key: \"9jr5yi\" }]\n];\nconst Heading2 = createLucideIcon(\"heading-2\", __iconNode);\n\nexport { __iconNode, Heading2 as default };\n//# sourceMappingURL=heading-2.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M4 12h8\", key: \"17cfdx\" }],\n [\"path\", { d: \"M4 18V6\", key: \"1rz3zl\" }],\n [\"path\", { d: \"M12 18V6\", key: \"zqpxq5\" }],\n [\"path\", { d: \"M17.5 10.5c1.7-1 3.5 0 3.5 1.5a2 2 0 0 1-2 2\", key: \"68ncm8\" }],\n [\"path\", { d: \"M17 17.5c2 1.5 4 .3 4-1.5a2 2 0 0 0-2-2\", key: \"1ejuhz\" }]\n];\nconst Heading3 = createLucideIcon(\"heading-3\", __iconNode);\n\nexport { __iconNode, Heading3 as default };\n//# sourceMappingURL=heading-3.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"m9 11-6 6v3h9l3-3\", key: \"1a3l36\" }],\n [\"path\", { d: \"m22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4\", key: \"14a9rk\" }]\n];\nconst Highlighter = createLucideIcon(\"highlighter\", __iconNode);\n\nexport { __iconNode, Highlighter as default };\n//# sourceMappingURL=highlighter.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"line\", { x1: \"19\", x2: \"10\", y1: \"4\", y2: \"4\", key: \"15jd3p\" }],\n [\"line\", { x1: \"14\", x2: \"5\", y1: \"20\", y2: \"20\", key: \"bu0au3\" }],\n [\"line\", { x1: \"15\", x2: \"9\", y1: \"4\", y2: \"20\", key: \"uljnxc\" }]\n];\nconst Italic = createLucideIcon(\"italic\", __iconNode);\n\nexport { __iconNode, Italic as default };\n//# sourceMappingURL=italic.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\", key: \"1cjeqo\" }],\n [\"path\", { d: \"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\", key: \"19qd67\" }]\n];\nconst Link = createLucideIcon(\"link\", __iconNode);\n\nexport { __iconNode, Link as default };\n//# sourceMappingURL=link.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M11 5h10\", key: \"1cz7ny\" }],\n [\"path\", { d: \"M11 12h10\", key: \"1438ji\" }],\n [\"path\", { d: \"M11 19h10\", key: \"11t30w\" }],\n [\"path\", { d: \"M4 4h1v5\", key: \"10yrso\" }],\n [\"path\", { d: \"M4 9h2\", key: \"r1h2o0\" }],\n [\"path\", { d: \"M6.5 20H3.4c0-1 2.6-1.925 2.6-3.5a1.5 1.5 0 0 0-2.6-1.02\", key: \"xtkcd5\" }]\n];\nconst ListOrdered = createLucideIcon(\"list-ordered\", __iconNode);\n\nexport { __iconNode, ListOrdered as default };\n//# sourceMappingURL=list-ordered.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M3 5h.01\", key: \"18ugdj\" }],\n [\"path\", { d: \"M3 12h.01\", key: \"nlz23k\" }],\n [\"path\", { d: \"M3 19h.01\", key: \"noohij\" }],\n [\"path\", { d: \"M8 5h13\", key: \"1pao27\" }],\n [\"path\", { d: \"M8 12h13\", key: \"1za7za\" }],\n [\"path\", { d: \"M8 19h13\", key: \"m83p4d\" }]\n];\nconst List = createLucideIcon(\"list\", __iconNode);\n\nexport { __iconNode, List as default };\n//# sourceMappingURL=list.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M11 7 6 2\", key: \"1jwth8\" }],\n [\"path\", { d: \"M18.992 12H2.041\", key: \"xw1gg\" }],\n [\n \"path\",\n {\n d: \"M21.145 18.38A3.34 3.34 0 0 1 20 16.5a3.3 3.3 0 0 1-1.145 1.88c-.575.46-.855 1.02-.855 1.595A2 2 0 0 0 20 22a2 2 0 0 0 2-2.025c0-.58-.285-1.13-.855-1.595\",\n key: \"1nkol4\"\n }\n ],\n [\n \"path\",\n {\n d: \"m8.5 4.5 2.148-2.148a1.205 1.205 0 0 1 1.704 0l7.296 7.296a1.205 1.205 0 0 1 0 1.704l-7.592 7.592a3.615 3.615 0 0 1-5.112 0l-3.888-3.888a3.615 3.615 0 0 1 0-5.112L5.67 7.33\",\n key: \"1nk1rd\"\n }\n ]\n];\nconst PaintBucket = createLucideIcon(\"paint-bucket\", __iconNode);\n\nexport { __iconNode, PaintBucket as default };\n//# sourceMappingURL=paint-bucket.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"16\", height: \"6\", x: \"2\", y: \"2\", rx: \"2\", key: \"jcyz7m\" }],\n [\"path\", { d: \"M10 16v-2a2 2 0 0 1 2-2h8a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2\", key: \"1b9h7c\" }],\n [\"rect\", { width: \"4\", height: \"6\", x: \"8\", y: \"16\", rx: \"1\", key: \"d6e7yl\" }]\n];\nconst PaintRoller = createLucideIcon(\"paint-roller\", __iconNode);\n\nexport { __iconNode, PaintRoller as default };\n//# sourceMappingURL=paint-roller.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M12 22a1 1 0 0 1 0-20 10 9 0 0 1 10 9 5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z\",\n key: \"e79jfc\"\n }\n ],\n [\"circle\", { cx: \"13.5\", cy: \"6.5\", r: \".5\", fill: \"currentColor\", key: \"1okk4w\" }],\n [\"circle\", { cx: \"17.5\", cy: \"10.5\", r: \".5\", fill: \"currentColor\", key: \"f64h9f\" }],\n [\"circle\", { cx: \"6.5\", cy: \"12.5\", r: \".5\", fill: \"currentColor\", key: \"qy21gx\" }],\n [\"circle\", { cx: \"8.5\", cy: \"7.5\", r: \".5\", fill: \"currentColor\", key: \"fotxhn\" }]\n];\nconst Palette = createLucideIcon(\"palette\", __iconNode);\n\nexport { __iconNode, Palette as default };\n//# sourceMappingURL=palette.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M14 9h1\", key: \"l0svgy\" }],\n [\"path\", { d: \"M19 9h2\", key: \"te2zfg\" }],\n [\"path\", { d: \"M3 9h2\", key: \"1h4ldw\" }],\n [\"path\", { d: \"M9 9h1\", key: \"15jzuz\" }]\n];\nconst PanelTopDashed = createLucideIcon(\"panel-top-dashed\", __iconNode);\n\nexport { __iconNode, PanelTopDashed as default };\n//# sourceMappingURL=panel-top-dashed.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M3 9h18\", key: \"1pudct\" }]\n];\nconst PanelTop = createLucideIcon(\"panel-top\", __iconNode);\n\nexport { __iconNode, PanelTop as default };\n//# sourceMappingURL=panel-top.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M13 4v16\", key: \"8vvj80\" }],\n [\"path\", { d: \"M17 4v16\", key: \"7dpous\" }],\n [\"path\", { d: \"M19 4H9.5a4.5 4.5 0 0 0 0 9H13\", key: \"sh4n9v\" }]\n];\nconst Pilcrow = createLucideIcon(\"pilcrow\", __iconNode);\n\nexport { __iconNode, Pilcrow as default };\n//# sourceMappingURL=pilcrow.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M16 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z\",\n key: \"rib7q0\"\n }\n ],\n [\n \"path\",\n {\n d: \"M5 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z\",\n key: \"1ymkrd\"\n }\n ]\n];\nconst Quote = createLucideIcon(\"quote\", __iconNode);\n\nexport { __iconNode, Quote as default };\n//# sourceMappingURL=quote.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M3 12h18\", key: \"1i2n21\" }]\n];\nconst Rows2 = createLucideIcon(\"rows-2\", __iconNode);\n\nexport { __iconNode, Rows2 as default };\n//# sourceMappingURL=rows-2.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"m6 16 6-12 6 12\", key: \"1b4byz\" }],\n [\"path\", { d: \"M8 12h8\", key: \"1wcyev\" }],\n [\"path\", { d: \"m16 20 2 2 4-4\", key: \"13tcca\" }]\n];\nconst SpellCheck = createLucideIcon(\"spell-check\", __iconNode);\n\nexport { __iconNode, SpellCheck as default };\n//# sourceMappingURL=spell-check.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M16 4H9a3 3 0 0 0-2.83 4\", key: \"43sutm\" }],\n [\"path\", { d: \"M14 12a4 4 0 0 1 0 8H6\", key: \"nlfj13\" }],\n [\"line\", { x1: \"4\", x2: \"20\", y1: \"12\", y2: \"12\", key: \"1e0a9i\" }]\n];\nconst Strikethrough = createLucideIcon(\"strikethrough\", __iconNode);\n\nexport { __iconNode, Strikethrough as default };\n//# sourceMappingURL=strikethrough.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 3v18\", key: \"108xh3\" }],\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M3 9h18\", key: \"1pudct\" }],\n [\"path\", { d: \"M3 15h18\", key: \"5xshup\" }]\n];\nconst Table = createLucideIcon(\"table\", __iconNode);\n\nexport { __iconNode, Table as default };\n//# sourceMappingURL=table.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M6 4v6a6 6 0 0 0 12 0V4\", key: \"9kb039\" }],\n [\"line\", { x1: \"4\", x2: \"20\", y1: \"20\", y2: \"20\", key: \"nun2al\" }]\n];\nconst Underline = createLucideIcon(\"underline\", __iconNode);\n\nexport { __iconNode, Underline as default };\n//# sourceMappingURL=underline.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72\",\n key: \"ul74o6\"\n }\n ],\n [\"path\", { d: \"m14 7 3 3\", key: \"1r5n42\" }],\n [\"path\", { d: \"M5 6v4\", key: \"ilb8ba\" }],\n [\"path\", { d: \"M19 14v4\", key: \"blhpug\" }],\n [\"path\", { d: \"M10 2v2\", key: \"7u0qdc\" }],\n [\"path\", { d: \"M7 8H3\", key: \"zfb6yr\" }],\n [\"path\", { d: \"M21 16h-4\", key: \"1cnmox\" }],\n [\"path\", { d: \"M11 3H9\", key: \"1obp7u\" }]\n];\nconst WandSparkles = createLucideIcon(\"wand-sparkles\", __iconNode);\n\nexport { __iconNode, WandSparkles as default };\n//# sourceMappingURL=wand-sparkles.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z\",\n key: \"1ngwbx\"\n }\n ]\n];\nconst Wrench = createLucideIcon(\"wrench\", __iconNode);\n\nexport { __iconNode, Wrench as default };\n//# sourceMappingURL=wrench.js.map\n","import type { AgentAdapter } from '../../agent/types';\nimport type { EditorFormat, RichTextEditorHandle } from './rich-text-editor';\n\nexport const richTextEditorAgent: AgentAdapter<RichTextEditorHandle> = {\n id: 'rich-text-editor',\n capabilities: ['edit_inline'],\n state: {\n html: {\n type: 'string',\n descriptionKey: 'ui.agent.richTextEditor.state.html',\n description: 'Sanitised HTML representation of the editor content.',\n read: (handle) => handle.getHTML(),\n },\n text: {\n type: 'string',\n descriptionKey: 'ui.agent.richTextEditor.state.text',\n description: 'Plain-text content of the editor (tags stripped).',\n read: (handle) => handle.getText(),\n },\n markdown: {\n type: 'string',\n descriptionKey: 'ui.agent.richTextEditor.state.markdown',\n description:\n 'Markdown representation of the editor content. The Redactor engine has no native Markdown serialiser, so this is always empty — read `html` instead.',\n read: (handle) => handle.getMarkdown(),\n },\n },\n actions: {\n set_content: {\n // Replaces the whole document — discards whatever the user had typed.\n safety: 'destructive',\n argsType: '{ html: string }',\n argsSchema: {\n type: 'object',\n properties: {\n html: {\n type: 'string',\n description: 'Replacement HTML (sanitised via DOMPurify).',\n },\n },\n required: ['html'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.richTextEditor.actions.setContent',\n description: 'Replace the editor content. Loses unsaved input.',\n invoke: (handle, args: { html: string }) => {\n handle.setContent(args.html);\n },\n },\n insert_at_cursor: {\n // Reversible via the editor's own undo stack — write, not destructive.\n safety: 'write',\n argsType: '{ content: string; asHtml?: boolean }',\n argsSchema: {\n type: 'object',\n properties: {\n content: {\n type: 'string',\n description: 'Content to insert at the caret.',\n },\n asHtml: {\n type: 'boolean',\n description:\n 'Treat content as HTML (sanitised). Pass false for plain text. Defaults to true.',\n },\n },\n required: ['content'],\n },\n descriptionKey: 'ui.agent.richTextEditor.actions.insertAtCursor',\n description:\n 'Insert content at the caret (replacing any selection). HTML is sanitised; pass asHtml:false for plain text. Seam for merge/template variables and AI-generated drafts.',\n examples: [\n {\n args: { content: '{{patient.firstName}}', asHtml: false },\n note: 'Insert a merge variable as plain text.',\n },\n ],\n invoke: (handle, args: { content: string; asHtml?: boolean }) => {\n handle.insertAtCursor(args.content, { asHtml: args.asHtml });\n },\n },\n apply_format: {\n // Reversible via undo — write, not destructive.\n safety: 'write',\n argsType:\n \"{ format: 'bold' | 'italic' | 'strikethrough' | 'bulletedList' | 'numberedList' | 'heading' | 'quote' | 'paragraph' }\",\n argsSchema: {\n type: 'object',\n properties: {\n format: {\n type: 'string',\n enum: [\n 'bold',\n 'italic',\n 'strikethrough',\n 'bulletedList',\n 'numberedList',\n 'heading',\n 'quote',\n 'paragraph',\n ],\n description: 'Block or inline format to toggle/apply.',\n },\n },\n required: ['format'],\n },\n descriptionKey: 'ui.agent.richTextEditor.actions.applyFormat',\n description:\n 'Toggle/apply a block or inline format on the current selection (bold, italic, strikethrough, bulleted/numbered list, heading, quote, paragraph).',\n examples: [{ args: { format: 'bold' }, note: 'Bold the selection.' }],\n invoke: (handle, args: { format: EditorFormat }) => {\n handle.applyFormat(args.format);\n },\n },\n clear: {\n // Empties the document — loses unsaved input.\n safety: 'destructive',\n idempotent: true,\n descriptionKey: 'ui.agent.richTextEditor.actions.clear',\n description: 'Empty the editor. Loses unsaved input.',\n invoke: (handle) => {\n handle.clear();\n },\n },\n focus: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.richTextEditor.actions.focus',\n description: 'Move keyboard focus to the editor surface.',\n invoke: (handle) => {\n handle.focus();\n },\n },\n },\n domHooks: {\n root: { attr: 'data-component', value: 'rich-text-editor' },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","/* ------------------------------------------------------------------ */\n/* HelpMeWriteOverlay — the \"Help me write\" flow on the non-modal */\n/* EditorOverlay (Gemini / Mac Mail style): a slim docked bar with a */\n/* one-row composer (mic · prompt · Write) → a preview of the draft with */\n/* Discard / Try again / Insert. */\n/* */\n/* The kit owns the UI; the backend call is the consumer's */\n/* `onRequestAiDraft({ prompt, signal })`. When `onDictate` is supplied */\n/* the composer grows a mic that streams transcripts INTO the prompt */\n/* (the same consumer dictation seam the editor FAB uses). The returned */\n/* draft is previewed (sanitised via SafeHtml) and only inserted on */\n/* confirm — sanitisation of the inserted value happens again at the */\n/* editor seam. */\n/* ------------------------------------------------------------------ */\n\nimport {\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Check, Mic, RotateCcw, Send, Square, X } from 'lucide-react';\n\nimport { IconButton } from '../button';\nimport { Spinner } from '../spinner';\nimport { TextArea } from '../text-area';\nimport { SafeHtml } from '../_shared/safe-html';\nimport { EditorOverlay } from '../editor-overlay';\n\nexport interface HelpMeWriteOverlayProps {\n open: boolean;\n onClose: () => void;\n onRequestAiDraft: (ctx: {\n prompt: string;\n signal: AbortSignal;\n }) => Promise<string>;\n onInsert: (draft: string) => void;\n /** Preview + insert the draft as HTML (default) or plain text. */\n previewAsHtml?: boolean;\n privacyNotice?: ReactNode;\n /**\n * Voice dictation into the prompt. Same seam as the editor's `onDictate`:\n * the consumer runs mic + transcription and pushes text back; the kit appends\n * finals to the prompt. When omitted, the composer shows no mic.\n */\n onDictate?: (ctx: {\n signal: AbortSignal;\n onPartialTranscript: (text: string) => void;\n onFinalTranscript: (text: string) => void;\n }) => Promise<void>;\n}\n\n// Force the recording mic solid-destructive (red). IconButton's base\n// `aria-pressed:bg-muted` (for IconButtonGroup toggles) would otherwise\n// out-specify the intent fill, so the override is marked important.\nconst RECORDING_MIC =\n 'ds:aria-pressed:!bg-[var(--destructive)] ds:aria-pressed:!text-[var(--destructive-foreground)]';\n\n// Pin the action buttons to the input's height (--min-target-size, 44/48px) so\n// the composer's input + mic + send line up exactly. IconButton md is h-10\n// (40px), below the TextArea md min-height, so force the match (important wins\n// over the size variant). Scales with the accessible theme for free.\nconst ACTION_SIZE = 'ds:!size-[var(--min-target-size)]';\n\nconst noticeClass =\n 'ds:text-[length:var(--font-size-sm)] ds:text-[color:var(--muted-foreground)]';\nconst errorClass =\n 'ds:text-[length:var(--font-size-sm)] ds:text-[color:var(--destructive)]';\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:10rem] ds:overflow-y-auto',\n 'ds:text-[length:var(--font-size-sm)] ds:text-[color:var(--foreground)]',\n].join(' ');\n\n// Join a base string with appended dictation text, inserting a single space\n// only when the base doesn't already end in whitespace.\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\nexport function HelpMeWriteOverlay({\n open,\n onClose,\n onRequestAiDraft,\n onInsert,\n previewAsHtml = true,\n privacyNotice,\n onDictate,\n}: HelpMeWriteOverlayProps): React.JSX.Element {\n const { t } = useTranslation();\n const promptId = useId();\n const errorId = useId();\n const [prompt, setPrompt] = useState('');\n const [loading, setLoading] = useState(false);\n const [errored, setErrored] = useState(false);\n const [draft, setDraft] = useState<string | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n\n /* ---- In-prompt voice dictation (consumer runs mic + STT) ---- */\n const [isDictating, setIsDictating] = useState(false);\n const [interim, setInterim] = useState('');\n // Drives the visually-hidden live region: announces the listening status on\n // start and each committed phrase as it lands. The interim text shows in the\n // read-only field, but SR users can't perceive a read-only value change, so\n // the polite region gives them the same feedback.\n const [dictationAnnouncement, setDictationAnnouncement] = useState('');\n const dictateAbortRef = useRef<AbortController | null>(null);\n\n const stopDictation = useCallback(() => {\n dictateAbortRef.current?.abort();\n }, []);\n\n const startDictation = useCallback(() => {\n if (!onDictate) return;\n const controller = new AbortController();\n dictateAbortRef.current = controller;\n setIsDictating(true);\n setInterim('');\n setDictationAnnouncement(t('editor.ai.listening'));\n onDictate({\n signal: controller.signal,\n onPartialTranscript: (text: string): void => {\n if (controller.signal.aborted) return;\n setInterim(text);\n },\n onFinalTranscript: (text: string): void => {\n if (controller.signal.aborted) return;\n const trimmed = text.trim();\n setInterim('');\n if (trimmed) {\n setPrompt((p) => joinWith(p, trimmed));\n setDictationAnnouncement(trimmed);\n }\n },\n })\n .catch(() => {\n /* dictation errors are non-fatal here — the user can type instead */\n })\n .finally(() => {\n setInterim('');\n if (dictateAbortRef.current === controller) {\n dictateAbortRef.current = null;\n setIsDictating(false);\n setDictationAnnouncement('');\n }\n });\n }, [onDictate, t]);\n\n const toggleDictation = useCallback(() => {\n if (isDictating) stopDictation();\n else startDictation();\n }, [isDictating, startDictation, stopDictation]);\n\n // Fresh state each time it opens; abort any in-flight request/dictation on close.\n useEffect(() => {\n if (open) {\n setPrompt('');\n setLoading(false);\n setErrored(false);\n setDraft(null);\n setInterim('');\n setDictationAnnouncement('');\n } else {\n abortRef.current?.abort();\n abortRef.current = null;\n dictateAbortRef.current?.abort();\n }\n }, [open]);\n useEffect(\n () => () => {\n abortRef.current?.abort();\n dictateAbortRef.current?.abort();\n },\n [],\n );\n\n const generate = useCallback(() => {\n const trimmed = prompt.trim();\n if (!trimmed || loading) return;\n stopDictation();\n abortRef.current?.abort();\n const controller = new AbortController();\n abortRef.current = controller;\n setErrored(false);\n setLoading(true);\n onRequestAiDraft({ prompt: trimmed, signal: controller.signal })\n .then((result) => {\n if (controller.signal.aborted) return;\n setDraft(result);\n setLoading(false);\n })\n .catch((err: unknown) => {\n if (\n controller.signal.aborted ||\n (err &&\n typeof err === 'object' &&\n 'name' in err &&\n (err as { name?: string }).name === 'AbortError')\n ) {\n return;\n }\n setErrored(true);\n setLoading(false);\n });\n }, [prompt, loading, onRequestAiDraft, stopDictation]);\n\n const insert = useCallback(() => {\n if (draft == null) return;\n onInsert(draft);\n onClose();\n }, [draft, onInsert, onClose]);\n\n const hasDraft = draft != null;\n // While dictating, show committed prompt + live interim; the field is\n // read-only so the streamed text isn't fought over by onChange.\n const fieldValue = isDictating ? joinWith(prompt, interim) : prompt;\n\n return (\n <EditorOverlay\n open={open}\n onClose={onClose}\n ariaLabel={t('editor.ai.dialogTitle')}\n >\n {hasDraft ? (\n <div className=\"ds:flex ds:items-end ds:gap-[var(--spacing-sm)]\">\n <IconButton\n size=\"md\"\n intent=\"outline\"\n className={ACTION_SIZE}\n icon={<X />}\n aria-label={t('common.close')}\n onClick={onClose}\n />\n <div className=\"ds:min-w-0 ds:flex-1\">\n {previewAsHtml ? (\n <SafeHtml\n html={draft as string}\n profile=\"rich-text\"\n className={previewClass}\n tabIndex={0}\n aria-label={t('editor.ai.dialogTitle')}\n />\n ) : (\n // Focusable so a keyboard user can scroll a long draft preview\n // (mirrors the SafeHtml preview branch above). The lint rule's\n // tabIndex allowlist doesn't cover a scrollable, non-interactive\n // text region.\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n <p className={previewClass} tabIndex={0}>\n {draft}\n </p>\n )}\n </div>\n <IconButton\n size=\"md\"\n intent=\"outline\"\n className={`${ACTION_SIZE} ds:rounded-full`}\n icon={<RotateCcw />}\n aria-label={t('editor.ai.retry')}\n onClick={() => setDraft(null)}\n />\n <IconButton\n size=\"md\"\n intent=\"primary\"\n className={`${ACTION_SIZE} ds:bg-[image:var(--gradient-brand)] ds:rounded-full`}\n icon={<Check />}\n aria-label={t('common.confirm')}\n onClick={insert}\n />\n </div>\n ) : (\n <>\n <div className=\"ds:flex ds:items-end ds:gap-[var(--spacing-sm)]\">\n <IconButton\n size=\"md\"\n intent=\"outline\"\n className={ACTION_SIZE}\n icon={<X />}\n aria-label={t('common.close')}\n onClick={onClose}\n />\n <div className=\"ds:min-w-0 ds:flex-1\">\n <TextArea\n id={promptId}\n size=\"md\"\n // Centre a single line within the min-height; when it grows to\n // multiple rows autoResize removes the slack so text fills from\n // the top as usual.\n className=\"ds:content-center\"\n value={fieldValue}\n onChange={(event) => setPrompt(event.target.value)}\n placeholder={t('editor.ai.promptPlaceholder')}\n aria-label={t('editor.ai.promptLabel')}\n autoResize\n minRows={1}\n maxRows={3}\n readOnly={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('editor.ai.dictateStop')\n : t('editor.ai.dictateStart')\n }\n onClick={toggleDictation}\n />\n ) : null}\n <IconButton\n size=\"md\"\n intent=\"primary\"\n icon={loading ? <Spinner size=\"sm\" variant=\"pulse\" /> : <Send />}\n className={`${ACTION_SIZE} ds:bg-[image:var(--gradient-brand)] ds:rounded-full`}\n disabled={loading || !prompt.trim()}\n aria-busy={loading || undefined}\n aria-label={t('editor.ai.generate')}\n onClick={generate}\n />\n </div>\n {onDictate ? (\n <p className=\"ds:sr-only\" role=\"status\" aria-live=\"polite\">\n {dictationAnnouncement}\n </p>\n ) : null}\n {errored ? (\n <p id={errorId} role=\"alert\" className={errorClass}>\n {t('editor.ai.error')}\n </p>\n ) : privacyNotice ? (\n <p className={noticeClass}>{privacyNotice}</p>\n ) : null}\n </>\n )}\n </EditorOverlay>\n );\n}\n","/* ------------------------------------------------------------------ */\n/* EditorToolbar — the kit's OWN toolbar for RichTextEditor. */\n/* */\n/* Redactor renders with `toolbar: false` (no native toolbar); this DS */\n/* toolbar drives the editor through Redactor's command API via `run` */\n/* and, for surfaces that would otherwise use Redactor's own modals */\n/* (link, image), through DS Dialogs + the `insertHtml` seam so EVERY */\n/* interactive surface is a kit component. Colour uses the DS */\n/* ColorPicker; the style menu is a labelled menu button; table offers */\n/* a size-grid insert + contextual row/column/header ops. */\n/* ------------------------------------------------------------------ */\n\nimport {\n Fragment,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type ReactNode,\n type RefObject,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n BetweenHorizontalEnd,\n BetweenHorizontalStart,\n BetweenVerticalEnd,\n BetweenVerticalStart,\n Bold,\n ChevronDown,\n Columns2,\n Heading2,\n Heading3,\n Highlighter,\n Image as ImageIcon,\n Italic,\n Link as LinkIcon,\n List,\n ListOrdered,\n PaintBucket,\n PaintRoller,\n PanelTop,\n PanelTopDashed,\n Palette,\n Pilcrow,\n Quote,\n Rows2,\n Strikethrough,\n Table as TableIcon,\n Trash2,\n Underline,\n Wrench,\n} from 'lucide-react';\nimport { cva } from 'class-variance-authority';\n\nimport { Button, IconButton } from '../button';\nimport { TooltipProvider } from '../tooltip';\nimport { Popover } from '../popover';\nimport { DropdownMenu } from '../dropdown-menu';\nimport { Dialog } from '../dialog';\nimport { ColorPicker } from '../color-picker';\nimport { TextInput } from '../text-input';\nimport { Checkbox } from '../checkbox';\nimport { FileUpload } from '../file-upload';\n\nexport type EditorToolbarPreset = 'minimal' | 'standard' | 'full';\n\nexport interface EditorToolbarProps {\n /** Dispatch a Redactor command (and refresh active state). */\n run: (command: string, ...args: unknown[]) => void;\n /** Active formats at the caret — toggle buttons render pressed. */\n active: ReadonlySet<string>;\n preset: EditorToolbarPreset;\n /** Insert sanitised HTML at the caret (link / image / table). */\n insertHtml: (html: string) => void;\n /** Insert a table — list-aware (drops it after a list, never inside an <li>). */\n insertTable: (html: string) => void;\n /** Save the editor selection before a DS popover/dialog takes focus. */\n saveSelection: () => void;\n /** Restore the saved selection before applying. */\n restoreSelection: () => void;\n /** Current selected text — prefills the link dialog's text field. */\n getSelectedText: () => string;\n /** Upload an image file and resolve its URL (image dialog's upload area). */\n uploadImage?: (file: File, signal?: AbortSignal) => Promise<string>;\n /** Show the text-colour control. */\n enableColor?: boolean;\n /** Show the image control (consumer set an image-upload URL). */\n enableImage?: boolean;\n /** Show the table control (consumer loaded the table plugin). */\n enableTable?: boolean;\n /**\n * Show an \"Editor extensions\" tools affordance (marketplace tools), placed\n * inline at the end of the toolbar. Currently a visual placeholder — not\n * wired to a menu.\n */\n showExtensions?: boolean;\n}\n\n/** i18n key + English fallback (for keys not yet in every locale). */\ntype L = [string, string];\n\ninterface ToolbarItem {\n id: string;\n icon: ReactNode;\n label: L;\n command: [string, ...unknown[]];\n /** When set, the button is a toggle and presses when `active` has this key. */\n toggle?: string;\n}\n\nconst ITEMS: Record<string, ToolbarItem> = {\n bold: {\n id: 'bold',\n icon: <Bold />,\n label: ['editor.bold', 'Bold'],\n command: ['module.inline.format', { tag: 'b' }],\n toggle: 'bold',\n },\n italic: {\n id: 'italic',\n icon: <Italic />,\n label: ['editor.italic', 'Italic'],\n command: ['module.inline.format', { tag: 'i' }],\n toggle: 'italic',\n },\n underline: {\n id: 'underline',\n icon: <Underline />,\n label: ['editor.underline', 'Underline'],\n command: ['module.inline.format', { tag: 'u' }],\n toggle: 'underline',\n },\n strike: {\n id: 'strike',\n icon: <Strikethrough />,\n label: ['editor.strike', 'Strikethrough'],\n command: ['module.inline.format', { tag: 'del' }],\n toggle: 'strike',\n },\n ul: {\n id: 'ul',\n icon: <List />,\n label: ['editor.list.bullet', 'Bulleted list'],\n command: ['module.list.toggle', 'ul'],\n toggle: 'ul',\n },\n ol: {\n id: 'ol',\n icon: <ListOrdered />,\n label: ['editor.list.ordered', 'Numbered list'],\n command: ['module.list.toggle', 'ol'],\n toggle: 'ol',\n },\n};\n\n// Block-format options. `id` matches the active token emitted by the editor\n// (paragraph / h2 / h3 / quote) so the labelled button shows the active style.\nconst FORMAT_OPTIONS: { id: string; tag: string; icon: ReactNode; label: L }[] =\n [\n {\n id: 'paragraph',\n tag: 'p',\n icon: <Pilcrow />,\n label: ['editor.paragraph', 'Paragraph'],\n },\n {\n id: 'h2',\n tag: 'h2',\n icon: <Heading2 />,\n label: ['editor.heading2', 'Heading 2'],\n },\n {\n id: 'h3',\n tag: 'h3',\n icon: <Heading3 />,\n label: ['editor.heading3', 'Heading 3'],\n },\n {\n id: 'quote',\n tag: 'blockquote',\n icon: <Quote />,\n label: ['editor.quote', 'Quote'],\n },\n ];\n\nconst PRESETS: Record<EditorToolbarPreset, string[]> = {\n minimal: ['bold', 'italic', 'underline', 'link'],\n standard: [\n 'format',\n 'bold',\n 'italic',\n 'underline',\n 'strike',\n 'ul',\n 'ol',\n 'link',\n ],\n full: ['format', 'bold', 'italic', 'underline', 'strike', 'ul', 'ol', 'link'],\n};\n\n// Table ops mirror EXACTLY the commands platform's Redactor table plugin\n// exposes (verified against platform/web/static/redactor/_plugins/table) — it\n// has no merge/split/align commands, so neither do we.\nconst TABLE_OPS: { id: string; command: string; icon: ReactNode; label: L }[] =\n [\n {\n id: 'rowAbove',\n command: 'plugin.table.addRowAbove',\n icon: <BetweenHorizontalStart />,\n label: ['editor.table.rowAbove', 'Add row above'],\n },\n {\n id: 'rowBelow',\n command: 'plugin.table.addRowBelow',\n icon: <BetweenHorizontalEnd />,\n label: ['editor.table.rowBelow', 'Add row below'],\n },\n {\n id: 'colLeft',\n command: 'plugin.table.addColumnLeft',\n icon: <BetweenVerticalStart />,\n label: ['editor.table.columnLeft', 'Add column left'],\n },\n {\n id: 'colRight',\n command: 'plugin.table.addColumnRight',\n icon: <BetweenVerticalEnd />,\n label: ['editor.table.columnRight', 'Add column right'],\n },\n {\n id: 'addHead',\n command: 'plugin.table.addHead',\n icon: <PanelTop />,\n label: ['editor.table.addHeader', 'Add header row'],\n },\n {\n id: 'deleteHead',\n command: 'plugin.table.deleteHead',\n icon: <PanelTopDashed />,\n label: ['editor.table.deleteHeader', 'Remove header row'],\n },\n {\n id: 'deleteRow',\n command: 'plugin.table.deleteRow',\n icon: <Rows2 />,\n label: ['editor.table.deleteRow', 'Delete row'],\n },\n {\n id: 'deleteColumn',\n command: 'plugin.table.deleteColumn',\n icon: <Columns2 />,\n label: ['editor.table.deleteColumn', 'Delete column'],\n },\n {\n id: 'deleteTable',\n command: 'plugin.table.deleteTable',\n icon: <Trash2 />,\n label: ['editor.table.deleteTable', 'Delete table'],\n },\n ];\n\nconst TABLE_GRID = 6; // max rows/cols offered by the size picker\n\nconst toolbarClass = cva(\n [\n 'ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)]',\n 'ds:rounded-[var(--radius-md)] ds:border ds:border-[color:var(--border)]',\n 'ds:bg-[var(--background)] ds:p-[var(--spacing-xs)]',\n 'ds:shadow-[var(--shadow-md)]',\n ].join(' '),\n);\n\nconst dividerClass =\n 'ds:self-stretch ds:[inline-size:var(--border-width-sm)] ds:bg-[var(--border)] ds:[margin-inline:var(--spacing-2xs)]';\n\nconst fieldLabelClass =\n 'ds:text-[length:var(--font-size-sm)] ds:font-medium ds:text-[color:var(--foreground)]';\n\n// Escape a string for safe interpolation; insertHtml re-sanitises via DOMPurify,\n// but encoding here keeps the constructed markup well-formed first.\nfunction esc(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n\n/* ------------------------------------------------------------------ */\n/* Style — labelled menu button */\n/* ------------------------------------------------------------------ */\n\nfunction StyleMenu({\n run,\n active,\n onTriggerDown,\n}: {\n run: EditorToolbarProps['run'];\n active: ReadonlySet<string>;\n onTriggerDown: (event: { preventDefault: () => void }) => void;\n}): React.JSX.Element {\n const { t } = useTranslation();\n const current =\n FORMAT_OPTIONS.find((o) => active.has(o.id)) ?? FORMAT_OPTIONS[0];\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button\n size=\"sm\"\n intent=\"ghost\"\n startIcon={current.icon}\n endIcon={<ChevronDown />}\n aria-label={t('editor.format', 'Paragraph style')}\n onMouseDown={onTriggerDown}\n >\n {t(current.label[0], current.label[1])}\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"start\">\n {FORMAT_OPTIONS.map((opt) => (\n <DropdownMenu.Item\n key={opt.id}\n startIcon={opt.icon}\n onSelect={() => run('module.block.format', { tag: opt.tag })}\n >\n {t(opt.label[0], opt.label[1])}\n </DropdownMenu.Item>\n ))}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Link — DS Dialog */\n/* ------------------------------------------------------------------ */\n\nfunction LinkDialog({\n insertHtml,\n saveSelection,\n restoreSelection,\n getSelectedText,\n}: Pick<\n EditorToolbarProps,\n 'insertHtml' | 'saveSelection' | 'restoreSelection' | 'getSelectedText'\n>): React.JSX.Element {\n const { t } = useTranslation();\n const [open, setOpen] = useState(false);\n const [url, setUrl] = useState('');\n const [text, setText] = useState('');\n const [newTab, setNewTab] = useState(false);\n const urlId = useId();\n const textId = useId();\n\n const reset = (): void => {\n setUrl('');\n setText('');\n setNewTab(false);\n };\n\n const handleInsert = (): void => {\n const href = url.trim();\n if (!href) return;\n const label = text.trim() || href;\n const tab = newTab ? ' target=\"_blank\" rel=\"noopener noreferrer\"' : '';\n const html = `<a href=\"${esc(href)}\"${tab}>${esc(label)}</a>`;\n setOpen(false);\n reset();\n window.requestAnimationFrame(() => {\n restoreSelection();\n insertHtml(html);\n });\n };\n\n return (\n <Dialog.Root open={open} onOpenChange={setOpen}>\n <Dialog.Trigger asChild>\n <IconButton\n size=\"sm\"\n intent=\"ghost\"\n icon={<LinkIcon />}\n aria-label={t('editor.link.insert', 'Insert link')}\n // Save the selection synchronously (before focus leaves the editor);\n // no preventDefault — the modal Dialog needs normal focus handling.\n onMouseDown={() => {\n saveSelection();\n setText(getSelectedText());\n }}\n />\n </Dialog.Trigger>\n <Dialog.Content>\n <Dialog.Header>\n <Dialog.Title>{t('editor.link.insert', 'Insert link')}</Dialog.Title>\n </Dialog.Header>\n <Dialog.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <label htmlFor={urlId} className={fieldLabelClass}>\n {t('editor.link.url', 'URL')}\n </label>\n <TextInput\n id={urlId}\n type=\"url\"\n value={url}\n onChange={(event) => setUrl(event.target.value)}\n placeholder=\"https://…\"\n />\n </div>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <label htmlFor={textId} className={fieldLabelClass}>\n {t('editor.link.text', 'Text to display')}\n </label>\n <TextInput\n id={textId}\n value={text}\n onChange={(event) => setText(event.target.value)}\n placeholder={t('editor.link.textPlaceholder', 'Link text')}\n />\n </div>\n <Checkbox\n checked={newTab}\n onCheckedChange={(checked) => setNewTab(checked === true)}\n label={t('editor.link.newTab', 'Open in new tab')}\n />\n </Dialog.Body>\n <Dialog.Footer>\n <Dialog.Close asChild>\n <Button intent=\"secondary\">{t('common.cancel')}</Button>\n </Dialog.Close>\n <Button onClick={handleInsert} disabled={!url.trim()}>\n {t('editor.link.insertAction', 'Insert')}\n </Button>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Image — DS Dialog */\n/* ------------------------------------------------------------------ */\n\nfunction ImageDialog({\n insertHtml,\n saveSelection,\n restoreSelection,\n uploadImage,\n}: Pick<\n EditorToolbarProps,\n 'insertHtml' | 'saveSelection' | 'restoreSelection' | 'uploadImage'\n>): React.JSX.Element {\n const { t } = useTranslation();\n const [open, setOpen] = useState(false);\n const [src, setSrc] = useState('');\n const [alt, setAlt] = useState('');\n const srcId = useId();\n const altId = useId();\n\n const insertImage = (url: string, altText: string): void => {\n const html = `<img src=\"${esc(url)}\" alt=\"${esc(altText)}\" loading=\"lazy\">`;\n setOpen(false);\n setSrc('');\n setAlt('');\n window.requestAnimationFrame(() => {\n restoreSelection();\n insertHtml(html);\n });\n };\n\n const handleInsert = (): void => {\n const url = src.trim();\n if (url) insertImage(url, alt.trim());\n };\n\n return (\n <Dialog.Root open={open} onOpenChange={setOpen}>\n <Dialog.Trigger asChild>\n <IconButton\n size=\"sm\"\n intent=\"ghost\"\n icon={<ImageIcon />}\n aria-label={t('editor.image.insert', 'Insert image')}\n // No preventDefault — the modal Dialog needs normal focus handling.\n onMouseDown={() => saveSelection()}\n />\n </Dialog.Trigger>\n <Dialog.Content>\n <Dialog.Header>\n <Dialog.Title>\n {t('editor.image.insert', 'Insert image')}\n </Dialog.Title>\n </Dialog.Header>\n <Dialog.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n {uploadImage ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <span className={fieldLabelClass}>\n {t('editor.image.upload', 'Upload')}\n </span>\n <FileUpload\n variant=\"dropzone\"\n accept={{\n 'image/*': ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg'],\n }}\n maxFiles={1}\n onUpload={async (file, { signal }) => {\n const url = await uploadImage(file, signal);\n insertImage(url, file.name);\n }}\n />\n <span className=\"ds:text-[length:var(--font-size-sm)] ds:text-[color:var(--muted-foreground)]\">\n {t('editor.image.orUrl', 'Or paste an image URL')}\n </span>\n </div>\n ) : null}\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <label htmlFor={srcId} className={fieldLabelClass}>\n {t('editor.image.url', 'Image URL')}\n </label>\n <TextInput\n id={srcId}\n type=\"url\"\n value={src}\n onChange={(event) => setSrc(event.target.value)}\n placeholder=\"https://…\"\n />\n </div>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <label htmlFor={altId} className={fieldLabelClass}>\n {t('editor.image.alt', 'Alt text')}\n </label>\n <TextInput\n id={altId}\n value={alt}\n onChange={(event) => setAlt(event.target.value)}\n placeholder={t(\n 'editor.image.altPlaceholder',\n 'Describe the image',\n )}\n />\n </div>\n </Dialog.Body>\n <Dialog.Footer>\n <Dialog.Close asChild>\n <Button intent=\"secondary\">{t('common.cancel')}</Button>\n </Dialog.Close>\n <Button onClick={handleInsert} disabled={!src.trim()}>\n {t('editor.image.insertAction', 'Insert')}\n </Button>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Colour — DS ColorPicker */\n/* ------------------------------------------------------------------ */\n\nfunction ColourControl({\n run,\n saveSelection,\n restoreSelection,\n}: Pick<\n EditorToolbarProps,\n 'run' | 'saveSelection' | 'restoreSelection'\n>): React.JSX.Element {\n const { t } = useTranslation();\n // Colour-picker seed value: a text-colour picker emits arbitrary, user-chosen\n // colours, so a literal hex default (rather than a brand token) is correct.\n // eslint-disable-next-line no-restricted-syntax\n const [colour, setColour] = useState('#1f2a5c');\n\n // Apply on pick — a colour control shouldn't need a separate \"Apply\" step.\n // The picker is compact (swatch-only), so onChange fires once per swatch\n // click; mirror Redactor's fontcolor plugin (toggle <span> with a colour\n // style — `type: 'toggle'` is required for the format to apply).\n const applyColour = (hex: string): void => {\n setColour(hex);\n restoreSelection();\n run('module.inline.format', {\n tag: 'span',\n style: { color: hex },\n type: 'toggle',\n });\n };\n const removeColour = (): void => {\n restoreSelection();\n run('module.inline.remove', { style: 'color' });\n };\n\n return (\n <Popover onOpenChange={(o) => o && saveSelection()}>\n <Popover.Trigger asChild>\n <IconButton\n size=\"sm\"\n intent=\"ghost\"\n icon={<Palette />}\n aria-label={t('editor.textColor', 'Text colour')}\n onMouseDown={(event) => {\n event.preventDefault();\n saveSelection();\n }}\n />\n </Popover.Trigger>\n <Popover.Content side=\"bottom\" align=\"start\">\n <Popover.Heading>\n {t('editor.textColor', 'Text colour')}\n </Popover.Heading>\n <div className=\"ds:pt-[var(--spacing-sm)]\">\n <ColorPicker\n variant=\"inline\"\n size=\"sm\"\n value={colour}\n onChange={applyColour}\n />\n </div>\n <div className=\"ds:mt-[var(--spacing-sm)] ds:flex ds:items-center ds:justify-end\">\n <Button size=\"sm\" intent=\"secondary\" onClick={removeColour}>\n {t('editor.color.remove', 'Remove colour')}\n </Button>\n </div>\n </Popover.Content>\n </Popover>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Highlight — DS ColorPicker applied as a text background */\n/* ------------------------------------------------------------------ */\n\nfunction HighlightControl({\n run,\n saveSelection,\n restoreSelection,\n}: Pick<\n EditorToolbarProps,\n 'run' | 'saveSelection' | 'restoreSelection'\n>): React.JSX.Element {\n const { t } = useTranslation();\n // Highlight seed value: a highlight picker emits arbitrary, user-chosen\n // colours, so a literal hex default (rather than a brand token) is correct.\n // eslint-disable-next-line no-restricted-syntax\n const [colour, setColour] = useState('#fff3a3');\n\n // Apply on pick. Highlight is the same inline <span> as text colour, but the\n // style key is `background-color` (mirrors Redactor's fontcolor \"Highlight\").\n const applyHighlight = (hex: string): void => {\n setColour(hex);\n restoreSelection();\n run('module.inline.format', {\n tag: 'span',\n style: { 'background-color': hex },\n type: 'toggle',\n });\n };\n const removeHighlight = (): void => {\n restoreSelection();\n run('module.inline.remove', { style: 'background-color' });\n };\n\n return (\n <Popover onOpenChange={(o) => o && saveSelection()}>\n <Popover.Trigger asChild>\n <IconButton\n size=\"sm\"\n intent=\"ghost\"\n icon={<Highlighter />}\n aria-label={t('editor.highlightColor', 'Highlight')}\n onMouseDown={(event) => {\n event.preventDefault();\n saveSelection();\n }}\n />\n </Popover.Trigger>\n <Popover.Content side=\"bottom\" align=\"start\">\n <Popover.Heading>\n {t('editor.highlightColor', 'Highlight')}\n </Popover.Heading>\n <div className=\"ds:pt-[var(--spacing-sm)]\">\n <ColorPicker\n variant=\"inline\"\n size=\"sm\"\n value={colour}\n onChange={applyHighlight}\n />\n </div>\n <div className=\"ds:mt-[var(--spacing-sm)] ds:flex ds:items-center ds:justify-end\">\n <Button size=\"sm\" intent=\"secondary\" onClick={removeHighlight}>\n {t('editor.highlight.remove', 'Remove highlight')}\n </Button>\n </div>\n </Popover.Content>\n </Popover>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Table — size-grid insert + contextual ops */\n/* ------------------------------------------------------------------ */\n\nfunction buildTable(rows: number, cols: number): string {\n const cells = Array.from({ length: cols }, () => '<td><br></td>').join('');\n const body = Array.from({ length: rows }, () => `<tr>${cells}</tr>`).join('');\n return `<table><tbody>${body}</tbody></table>`;\n}\n\nfunction TableControl({\n run,\n insertTable,\n active,\n}: Pick<\n EditorToolbarProps,\n 'run' | 'insertTable' | 'active'\n>): React.JSX.Element {\n const { t } = useTranslation();\n const [hover, setHover] = useState<{ r: number; c: number }>({ r: 0, c: 0 });\n const inTable = active.has('table');\n\n return (\n <Popover onOpenChange={(o) => !o && setHover({ r: 0, c: 0 })}>\n <Popover.Trigger asChild>\n <IconButton\n size=\"sm\"\n intent=\"ghost\"\n icon={<TableIcon />}\n aria-label={t('editor.table.insert', 'Insert table')}\n onMouseDown={(event) => event.preventDefault()}\n />\n </Popover.Trigger>\n <Popover.Content side=\"bottom\" align=\"start\">\n {inTable ? (\n // Caret is already inside a table — offer the manage ops only, never\n // a nested-table insert (mirrors Redactor's native dropdown, which\n // disables \"insert table\" while the caret is in a table).\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)]\">\n {TABLE_OPS.map((op) => (\n <button\n key={op.id}\n type=\"button\"\n onClick={() => run(op.command)}\n className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)] ds:rounded-[var(--radius-sm)] ds:px-[var(--spacing-sm)] ds:py-[var(--spacing-2xs)] ds:text-start ds:text-[length:var(--font-size-sm)] ds:text-[color:var(--foreground)] ds:hover:bg-[var(--muted)]\"\n >\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-flex ds:size-4 ds:shrink-0 ds:items-center ds:justify-center ds:text-[color:var(--muted-foreground)]\"\n >\n {op.icon}\n </span>\n {t(op.label[0], op.label[1])}\n </button>\n ))}\n </div>\n ) : (\n <>\n <Popover.Heading>\n {t('editor.table.insert', 'Insert table')}\n </Popover.Heading>\n <div\n role=\"group\"\n aria-label={t('editor.table.sizePicker', 'Table size')}\n className=\"ds:mt-[var(--spacing-sm)] ds:grid ds:w-fit ds:grid-cols-6 ds:gap-[var(--spacing-2xs)]\"\n onMouseLeave={() => setHover({ r: 0, c: 0 })}\n >\n {Array.from({ length: TABLE_GRID * TABLE_GRID }, (_, i) => {\n const r = Math.floor(i / TABLE_GRID) + 1;\n const c = (i % TABLE_GRID) + 1;\n const on = r <= hover.r && c <= hover.c;\n return (\n <button\n key={i}\n type=\"button\"\n aria-label={t('editor.table.sizeCell', '{{r}}×{{c}}', {\n r,\n c,\n })}\n onMouseEnter={() => setHover({ r, c })}\n onClick={() => insertTable(buildTable(r, c))}\n className={`ds:size-5 ds:rounded-[var(--radius-sm)] ds:border ds:border-[color:var(--border)] ${\n on ? 'ds:bg-[var(--primary)]' : 'ds:bg-[var(--muted)]'\n }`}\n />\n );\n })}\n </div>\n <p className=\"ds:mt-[var(--spacing-xs)] ds:text-[length:var(--font-size-sm)] ds:text-[color:var(--muted-foreground)]\">\n {hover.r > 0\n ? t('editor.table.sizeCell', '{{r}}×{{c}}', {\n r: hover.r,\n c: hover.c,\n })\n : t('editor.table.sizeHint', 'Pick a size')}\n </p>\n </>\n )}\n </Popover.Content>\n </Popover>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Floating in-cell table toolbar */\n/* */\n/* Appears anchored above the table whenever the caret is inside one, */\n/* so the common row/column ops are one click away without opening the */\n/* toolbar menu. Dispatches the same `plugin.table.*` commands via the */\n/* shared `run` seam; the toolbar TableControl menu stays as the place */\n/* for inserting tables and header ops. */\n/* ------------------------------------------------------------------ */\n\nconst TABLE_OP_BY_ID: Record<string, (typeof TABLE_OPS)[number]> =\n Object.fromEntries(TABLE_OPS.map((op) => [op.id, op]));\n\nconst tableFloatClass = [\n 'ds:absolute ds:z-20 ds:flex ds:items-center ds:gap-[var(--spacing-2xs)]',\n 'ds:[inset-block-start:var(--rte-tt-top)] ds:[inset-inline-start:var(--rte-tt-start)]',\n 'ds:rounded-[var(--radius-md)] ds:border ds:border-[color:var(--border)]',\n 'ds:bg-[var(--popover)] ds:p-[var(--spacing-2xs)] ds:shadow-[var(--shadow-lg)]',\n].join(' ');\n\nexport interface TableFloatingToolbarProps {\n active: ReadonlySet<string>;\n run: EditorToolbarProps['run'];\n /** Positioned container the bar is absolutely placed within. */\n areaRef: RefObject<HTMLDivElement | null>;\n /** The <table> the caret is currently inside (relative to this editor). */\n getActiveTableEl: () => HTMLElement | null;\n /** Show the cell/row background-colour controls (fontcolor plugin loaded). */\n enableColor?: boolean;\n /** Snapshot the current cell before a colour popover takes focus. */\n saveTableCell: () => void;\n /** Set/clear a background colour on the current cell or its row. */\n applyTableBackground: (scope: 'cell' | 'row', colour: string | null) => void;\n}\n\n// Colour-control seed: an arbitrary user-chosen background, so a literal hex\n// default is correct (mirrors ColourControl / HighlightControl).\n// eslint-disable-next-line no-restricted-syntax\nconst TABLE_BG_SEED = '#fde68a';\n\n// One cell/row background-colour control: an icon trigger → compact ColorPicker\n// (applies on pick) + a clear action. The cell is captured on open (saveTableCell)\n// because the popover takes focus; `onOpenChange` lets the bar stay mounted.\nfunction TableBgColourControl({\n scope,\n icon,\n label,\n onOpenChange,\n saveTableCell,\n applyTableBackground,\n}: {\n scope: 'cell' | 'row';\n icon: ReactNode;\n label: string;\n onOpenChange: (open: boolean) => void;\n saveTableCell: () => void;\n applyTableBackground: (scope: 'cell' | 'row', colour: string | null) => void;\n}): React.JSX.Element {\n const { t } = useTranslation();\n const [colour, setColour] = useState(TABLE_BG_SEED);\n return (\n <Popover\n onOpenChange={(open) => {\n onOpenChange(open);\n if (open) saveTableCell();\n }}\n >\n <Popover.Trigger asChild>\n <IconButton\n size=\"sm\"\n intent=\"ghost\"\n icon={icon}\n tooltip={label}\n onMouseDown={(event) => event.preventDefault()}\n />\n </Popover.Trigger>\n <Popover.Content side=\"bottom\" align=\"center\">\n <ColorPicker\n variant=\"inline\"\n size=\"sm\"\n value={colour}\n onChange={(hex) => {\n setColour(hex);\n applyTableBackground(scope, hex);\n }}\n />\n <Button\n size=\"sm\"\n intent=\"ghost\"\n className=\"ds:mt-[var(--spacing-xs)] ds:w-full\"\n onClick={() => applyTableBackground(scope, null)}\n >\n {t('editor.table.clearColor', 'Clear colour')}\n </Button>\n </Popover.Content>\n </Popover>\n );\n}\n\nexport function TableFloatingToolbar({\n active,\n run,\n areaRef,\n getActiveTableEl,\n enableColor = false,\n saveTableCell,\n applyTableBackground,\n}: TableFloatingToolbarProps): React.JSX.Element | null {\n const { t } = useTranslation();\n const inTable = active.has('table');\n const [pos, setPos] = useState<{\n top: number;\n start: number;\n rtl: boolean;\n } | null>(null);\n\n // Keep the bar mounted while a colour popover is open: opening it can move\n // focus out of the editor, dropping `table` from `active`, which would\n // otherwise unmount the bar (and close the popover) mid-interaction.\n const colourOpenCount = useRef(0);\n const [colourOpen, setColourOpen] = useState(false);\n const handleColourOpenChange = useCallback((open: boolean): void => {\n colourOpenCount.current = Math.max(\n 0,\n colourOpenCount.current + (open ? 1 : -1),\n );\n setColourOpen(colourOpenCount.current > 0);\n }, []);\n\n useEffect(() => {\n // Freeze tracking while a colour popover is open (the caret may have left\n // the editor); resume when it closes.\n if (colourOpen) return;\n if (!inTable || typeof window === 'undefined') {\n setPos(null);\n return;\n }\n const recompute = (): void => {\n const area = areaRef.current;\n const table = getActiveTableEl();\n if (!area || !table) {\n setPos(null);\n return;\n }\n const a = area.getBoundingClientRect();\n const r = table.getBoundingClientRect();\n const rtl = getComputedStyle(area).direction === 'rtl';\n // Float just above the table's block-start edge, clamped to the container\n // top so it never renders above the editing surface. 44 ≈ the bar's own\n // height (one --min-target-size row) plus a small gap.\n const top = Math.max(0, r.top - a.top - 44);\n // Anchor `start` to the table's inline CENTRE; the render translates the\n // bar back by half its own width so it sits centred over the table.\n const center = rtl\n ? a.right - r.right + r.width / 2\n : r.left - a.left + r.width / 2;\n setPos({ top, start: Math.max(0, center), rtl });\n };\n recompute();\n // While the caret stays in the table the bar must track it: cell edits and\n // add-row/column grow the table (ResizeObserver), and the surface or the\n // viewport can scroll/resize.\n const ro = new ResizeObserver(recompute);\n const area = areaRef.current;\n const table = getActiveTableEl();\n if (area) ro.observe(area);\n if (table) ro.observe(table);\n window.addEventListener('scroll', recompute, true);\n window.addEventListener('resize', recompute);\n return () => {\n ro.disconnect();\n window.removeEventListener('scroll', recompute, true);\n window.removeEventListener('resize', recompute);\n };\n }, [inTable, colourOpen, areaRef, getActiveTableEl]);\n\n if ((!inTable && !colourOpen) || !pos) return null;\n\n // Ordered render groups; 'colour' is the cell/row background controls.\n const groups: (string[] | 'colour')[] = [\n ['rowAbove', 'rowBelow'],\n ['colLeft', 'colRight'],\n ['addHead'],\n ...(enableColor ? (['colour'] as const) : []),\n ['deleteRow', 'deleteColumn'],\n ['deleteTable'],\n ];\n\n return (\n // Tooltips disambiguate the icon-only ops on hover (and provide each\n // button's accessible name via IconButton's `tooltip` prop). Radix Tooltip\n // needs a provider ancestor, so scope one to the bar.\n <TooltipProvider>\n <div\n // role=\"group\", not \"toolbar\": these controls are independent tab\n // stops with no roving-focus / arrow-key navigation, so advertising the\n // WAI-ARIA toolbar contract would be a false promise. role=\"group\" keeps\n // the labelled grouping without committing to single-tab-stop semantics.\n role=\"group\"\n aria-label={t('editor.table.toolbar', 'Table tools')}\n // Centre on the table: --rte-tt-start is the table's inline centre, so\n // pull back by half the bar's width (mirrored for RTL).\n className={`${tableFloatClass} ${pos.rtl ? 'ds:translate-x-1/2' : 'ds:-translate-x-1/2'}`}\n // eslint-disable-next-line react/forbid-dom-props -- runtime-computed position injected via CSS custom properties (23-constraints §Runtime-computed dimensions); the inset rules live in the class\n style={{\n ['--rte-tt-top' as string]: `${pos.top}px`,\n ['--rte-tt-start' as string]: `${pos.start}px`,\n }}\n >\n {groups.map((group, gi) => (\n <Fragment key={group === 'colour' ? 'colour' : group[0]}>\n {gi > 0 ? (\n <span aria-hidden=\"true\" className={dividerClass} />\n ) : null}\n {group === 'colour' ? (\n <>\n <TableBgColourControl\n scope=\"cell\"\n icon={<PaintBucket />}\n label={t('editor.table.cellColor', 'Cell colour')}\n onOpenChange={handleColourOpenChange}\n saveTableCell={saveTableCell}\n applyTableBackground={applyTableBackground}\n />\n <TableBgColourControl\n scope=\"row\"\n icon={<PaintRoller />}\n label={t('editor.table.rowColor', 'Row colour')}\n onOpenChange={handleColourOpenChange}\n saveTableCell={saveTableCell}\n applyTableBackground={applyTableBackground}\n />\n </>\n ) : (\n group.map((opId) => {\n const op = TABLE_OP_BY_ID[opId];\n return (\n <IconButton\n key={opId}\n size=\"sm\"\n intent=\"ghost\"\n icon={op.icon}\n tooltip={t(op.label[0], op.label[1])}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => run(op.command)}\n />\n );\n })\n )}\n </Fragment>\n ))}\n </div>\n </TooltipProvider>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Toolbar */\n/* ------------------------------------------------------------------ */\n\nexport function EditorToolbar({\n run,\n active,\n preset,\n insertHtml,\n insertTable,\n saveSelection,\n restoreSelection,\n getSelectedText,\n uploadImage,\n enableColor = false,\n enableImage = false,\n enableTable = false,\n showExtensions = false,\n}: EditorToolbarProps): React.JSX.Element {\n const { t } = useTranslation();\n // Keep toolbar clicks from stealing the editor's selection.\n const keepSelection = (event: { preventDefault: () => void }): void =>\n event.preventDefault();\n\n // Render a simple command button by id, gated by the active preset.\n const has = (id: string): boolean => PRESETS[preset].includes(id);\n const btn = (id: string): React.JSX.Element | null => {\n if (!has(id)) return null;\n const item = ITEMS[id];\n return (\n <IconButton\n key={item.id}\n size=\"sm\"\n intent=\"ghost\"\n icon={item.icon}\n aria-label={t(item.label[0], item.label[1])}\n aria-pressed={item.toggle ? active.has(item.toggle) : undefined}\n onMouseDown={keepSelection}\n onClick={() => run(...item.command)}\n />\n );\n };\n const Divider = (): React.JSX.Element => (\n <span aria-hidden=\"true\" className={dividerClass} />\n );\n\n // Standard toolbar grouping (matches Google Docs / Word / TinyMCE order):\n // style ▸ inline (B/I/U/S + colour/highlight) ▸ lists ▸ insert ▸ extensions.\n const styleGroup = has('format');\n const inlineGroup =\n has('bold') ||\n has('italic') ||\n has('underline') ||\n has('strike') ||\n enableColor;\n const listsGroup = has('ul') || has('ol');\n const insertGroup = has('link') || enableImage || enableTable;\n\n return (\n <div\n // role=\"group\", not \"toolbar\": every control is its own tab stop with no\n // roving focus / arrow-key handling, so the toolbar contract would be\n // false. role=\"group\" keeps the labelled grouping without the single-\n // tab-stop + arrow-navigation promise.\n role=\"group\"\n aria-label={t('editor.toolbarLabel')}\n className={toolbarClass()}\n data-component=\"editor-toolbar\"\n >\n {/* Block style */}\n {styleGroup ? (\n <StyleMenu run={run} active={active} onTriggerDown={keepSelection} />\n ) : null}\n\n {/* Inline formatting */}\n {styleGroup && inlineGroup ? <Divider /> : null}\n {btn('bold')}\n {btn('italic')}\n {btn('underline')}\n {btn('strike')}\n {enableColor ? (\n <ColourControl\n run={run}\n saveSelection={saveSelection}\n restoreSelection={restoreSelection}\n />\n ) : null}\n {enableColor ? (\n <HighlightControl\n run={run}\n saveSelection={saveSelection}\n restoreSelection={restoreSelection}\n />\n ) : null}\n\n {/* Lists */}\n {(styleGroup || inlineGroup) && listsGroup ? <Divider /> : null}\n {btn('ul')}\n {btn('ol')}\n\n {/* Insert */}\n {(styleGroup || inlineGroup || listsGroup) && insertGroup ? (\n <Divider />\n ) : null}\n {has('link') ? (\n <LinkDialog\n insertHtml={insertHtml}\n saveSelection={saveSelection}\n restoreSelection={restoreSelection}\n getSelectedText={getSelectedText}\n />\n ) : null}\n {enableImage ? (\n <ImageDialog\n insertHtml={insertHtml}\n saveSelection={saveSelection}\n restoreSelection={restoreSelection}\n uploadImage={uploadImage}\n />\n ) : null}\n {enableTable ? (\n <TableControl run={run} insertTable={insertTable} active={active} />\n ) : null}\n\n {/* Editor extensions (marketplace tools) — inline placeholder */}\n {showExtensions &&\n (styleGroup || inlineGroup || listsGroup || insertGroup) ? (\n <Divider />\n ) : null}\n {showExtensions ? (\n <IconButton\n size=\"sm\"\n intent=\"ghost\"\n icon={<Wrench />}\n aria-label={t('editor.extensions', 'Editor extensions')}\n // Placeholder affordance: no handler is wired yet, so the control\n // must not be operable — an enabled button with no onClick fails\n // SC 4.1.2. Disable it until a marketplace handler is connected.\n disabled\n onMouseDown={keepSelection}\n />\n ) : null}\n </div>\n );\n}\n","/* ------------------------------------------------------------------ */\n/* RichTextEditor — thin, secure wrapper over Redactor (Imperavi). */\n/* */\n/* LICENCE-SAFETY MODEL (read first): */\n/* Redactor is a COMMERCIAL editor and `@alfadocs/ui-kit` publishes */\n/* to PUBLIC npm — so redactor.js bytes MUST NOT enter `dist/`. This */\n/* wrapper never imports Redactor; it resolves a Redactor factory at */\n/* runtime from a `redactor` prop or the UMD globals `window.$R` / */\n/* `window.Redactor` that the CONSUMER's licensed build sets */\n/* (platform ships `web/static/redactor/redactor.js`). With no */\n/* factory found, the editor renders a graceful plain <textarea>. */\n/* Storybook loads a vendored dev-only build via preview-head.html. */\n/* */\n/* - Toolbar/buttons/dropdowns/shortcuts are owned entirely by Redactor */\n/* itself. The kit only skins them via `redactor-theme.css` and feeds */\n/* button presets + lang strings. */\n/* - Security: all inbound HTML (value/defaultValue/setContent) and the */\n/* editor's outbound `changed` HTML run through DOMPurify with an */\n/* explicit FORBID list. Outbound HTML also gets `loading=\"lazy\"` on */\n/* images and platform's empty-placeholder normalisation. */\n/* - Backend-coupled features (image upload, help-me-write, */\n/* voice-recording) are CONSUMER-PROVIDED via `imageUploadUrl` / */\n/* `plugins` / `options`; the kit never bakes a backend route in. */\n/* - i18n: placeholder/aria via `t('editor.placeholder')`; Redactor's */\n/* own `lang` is derived from the active locale (not hardcoded). */\n/* ------------------------------------------------------------------ */\n\nimport {\n Fragment,\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type ReactNode,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Mic, SpellCheck, Sparkles, Square, WandSparkles } from 'lucide-react';\n\nimport '../../tokens/themes/bridges/redactor-theme.css';\n\nimport { sanitiseHtml as sanitiseShared } from '../_shared/safe-html';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { Spinner } from '../spinner';\nimport { richTextEditorAgent } from './rich-text-editor.agent';\nimport { HelpMeWriteOverlay } from './help-me-write-overlay';\nimport { EditorToolbar, TableFloatingToolbar } from './editor-toolbar';\n\n/* ------------------------------------------------------------------ */\n/* Sanitisation */\n/* ------------------------------------------------------------------ */\n\n// Single sanitiser surface (constraints §8): the editor routes every inbound\n// and outbound HTML string through the shared `rich-text` DOMPurify profile in\n// `_shared/safe-html.tsx`, so one audit covers the whole kit. The wrapper adds\n// only editor-specific shaping (normalizeEditorValue + withLazyImages) around it.\nfunction sanitiseHtml(input: string): string {\n return sanitiseShared(input, 'rich-text');\n}\n\n// Mirror platform's RedactorWysiwyg `normalizeEditorValue` (RedactorWysiwyg.js\n// :26-44): map Redactor's empty placeholders to '' for the emptiness test, but\n// preserve image-only HTML so embedded-image notes aren't dropped on save.\nfunction normalizeEditorValue(html = ''): string {\n const normalized = String(html).trim();\n if (\n normalized === '' ||\n normalized === '<p><br></p>' ||\n normalized === '<p> </p>'\n ) {\n return '';\n }\n const contentWithoutTags = normalized\n .replace(/<br\\s*\\/?>/gi, '')\n .replace(/ /gi, '')\n .replace(/<[^>]+>/g, '')\n .trim();\n if (contentWithoutTags === '' && /<img\\b[^>]*>/i.test(normalized)) {\n return normalized;\n }\n return contentWithoutTags === '' ? '' : normalized;\n}\n\n// Inject `loading=\"lazy\"` on any <img> lacking it (platform parity).\nfunction withLazyImages(html: string): string {\n return html.replace(\n /<img(?![^>]*\\sloading=)([^>]*)>/gi,\n '<img loading=\"lazy\"$1>',\n );\n}\n\n// Pull the uploaded image URL out of a Redactor-style imageUpload response.\n// Handles the common shapes: `{ file: { url } }`, `{ url }`, `{ data: { url } }`,\n// and the multi-file map `{ \"1\": { url }, … }`.\nfunction extractUploadedUrl(data: unknown): string | undefined {\n if (!data || typeof data !== 'object') return undefined;\n const rec = data as Record<string, unknown>;\n const fromNode = (node: unknown): string | undefined => {\n if (node && typeof node === 'object' && 'url' in node) {\n const url = (node as { url?: unknown }).url;\n return typeof url === 'string' ? url : undefined;\n }\n return undefined;\n };\n if (typeof rec.url === 'string') return rec.url;\n return (\n fromNode(rec.file) ??\n fromNode(rec.data) ??\n Object.values(rec).map(fromNode).find(Boolean)\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Redactor factory resolution (external — never bundled) */\n/* ------------------------------------------------------------------ */\n\nexport type RedactorFactory = (\n selector: string | HTMLElement,\n command?: unknown,\n ...args: unknown[]\n) => unknown;\n\nfunction resolveRedactor(injected?: RedactorFactory): RedactorFactory | null {\n if (injected) return injected;\n if (typeof window === 'undefined') return null;\n const w = window as unknown as {\n $R?: RedactorFactory;\n Redactor?: RedactorFactory;\n };\n return w.$R ?? w.Redactor ?? null;\n}\n\n/* ------------------------------------------------------------------ */\n/* Public types */\n/* ------------------------------------------------------------------ */\n\nexport type RichTextEditorToolbar = 'minimal' | 'standard' | 'full';\n\nexport interface RichTextEditorProps {\n /** Opaque instance id — emitted as `data-component-id` for the agent registry. */\n id?: string;\n /** HTML initial value (uncontrolled). Runs through DOMPurify. */\n defaultValue?: string;\n /** Controlled value (HTML). Sanitised; synced with a skip-once caret guard. */\n value?: string;\n /** Emits on every change — debounced 100ms. `markdown` is '' (Redactor has no serializer). */\n onChange?: (payload: { html: string; markdown: string }) => void;\n /** Toolbar preset → Redactor `buttons`. */\n toolbar?: RichTextEditorToolbar;\n /** Placeholder text — translates via useTranslation if omitted. */\n placeholder?: string;\n /** Read-only mode. */\n readOnly?: boolean;\n /** Accessible name for the editing region. */\n ariaLabel?: string;\n /** Size variant for the minimum block-size of the editing region. */\n minHeight?: 'sm' | 'md' | 'lg';\n /** Show a right-aligned editor-extensions affordance (visual placeholder). */\n showExtensions?: boolean;\n /** Extra class names on the wrapper. */\n className?: string;\n\n /* --- Redactor-specific seams (all CONSUMER-PROVIDED) --- */\n /** Inject the Redactor factory explicitly; else `window.$R` / `window.Redactor`. */\n redactor?: RedactorFactory;\n /** Raw Redactor options, deep-merged LAST over the kit defaults (callbacks reserved). */\n options?: Record<string, unknown>;\n /** Redactor plugin names to enable (the consumer must register/load them). */\n plugins?: string[];\n /** Redactor lang code; default derived from the active i18n locale. */\n lang?: string;\n /** Consumer image-upload endpoint → Redactor `imageUpload`. Omitted if absent. */\n imageUploadUrl?: string;\n /** App keyboard-shortcut seam (e.g. Ctrl/Cmd+Enter to save). */\n onKeyDown?: (event: KeyboardEvent) => void;\n\n /* --- AI assistance (DS-native UI; backend stays consumer-provided) --- */\n /**\n * Help-me-write. When provided, a DS \"Help me write\" action appears; the kit\n * opens a dialog, calls this with the prompt + an AbortSignal, sanitises the\n * returned draft and inserts it at the caret. The backend call / auth /\n * practiceId all live in the consumer's implementation — never in the kit.\n */\n onRequestAiDraft?: (ctx: {\n prompt: string;\n signal: AbortSignal;\n }) => Promise<string>;\n /** Whether `onRequestAiDraft` returns HTML (default) or plain text. */\n aiDraftFormat?: 'html' | 'text';\n /** Override the compliance notice shown in the Help-me-write dialog. */\n aiPrivacyNotice?: ReactNode;\n /**\n * Voice dictation. When provided, a DS mic toggle + live-transcript region\n * appear. The kit owns the UI; the consumer runs mic capture + transcription\n * inside the callback and pushes text back via `onPartialTranscript` (drives\n * the live region) and `onFinalTranscript` (sanitised + inserted at the\n * caret). Resolve when the session ends; honour `signal` to stop. All\n * mic / transcription / backend logic stays consumer-side.\n */\n onDictate?: (ctx: {\n signal: AbortSignal;\n onPartialTranscript: (text: string) => void;\n onFinalTranscript: (text: string) => void;\n }) => Promise<void>;\n /**\n * One-shot AI document actions (CONSUMER-PROVIDED backend). Each gets the\n * current HTML + an AbortSignal and resolves with rewritten HTML; while one\n * runs the editor is disabled with a spinner and the result replaces the whole\n * document. `onProofread` corrects spelling/grammar; `onAutoFormat` tidies the\n * document's structure/formatting. Each adds a FAB segment when provided.\n */\n onProofread?: (ctx: { html: string; signal: AbortSignal }) => Promise<string>;\n onAutoFormat?: (ctx: {\n html: string;\n signal: AbortSignal;\n }) => Promise<string>;\n}\n\n/** Block/inline formats the editor can toggle via `applyFormat`. */\nexport type EditorFormat =\n | 'bold'\n | 'italic'\n | 'strikethrough'\n | 'bulletedList'\n | 'numberedList'\n | 'heading'\n | 'quote'\n | 'paragraph';\n\n// Maps each format to its Redactor command (shared with the toolbar).\nconst FORMAT_COMMANDS: Record<EditorFormat, [string, ...unknown[]]> = {\n bold: ['module.inline.format', { tag: 'b' }],\n italic: ['module.inline.format', { tag: 'i' }],\n strikethrough: ['module.inline.format', { tag: 'del' }],\n bulletedList: ['module.list.toggle', 'ul'],\n numberedList: ['module.list.toggle', 'ol'],\n heading: ['module.block.format', { tag: 'h2' }],\n quote: ['module.block.format', { tag: 'blockquote' }],\n paragraph: ['module.block.format', { tag: 'p' }],\n};\n\nexport interface RichTextEditorHandle {\n getHTML: () => string;\n /** Plain-text content of the editor (tags stripped). */\n getText: () => string;\n /** Always '' — Redactor has no native Markdown serializer (see MDX). */\n getMarkdown: () => string;\n /** HTML goes through DOMPurify before reaching Redactor. */\n setContent: (html: string) => void;\n /**\n * Insert content at the caret (replacing any selection). HTML is\n * DOMPurify-sanitised; pass `{ asHtml: false }` for a plain-text insert.\n * Works with the degraded <textarea> too. This is the seam for inserting\n * merge/template variables and AI-generated drafts.\n */\n insertAtCursor: (content: string, opts?: { asHtml?: boolean }) => void;\n /** Toggle/apply a block or inline format on the current selection. */\n applyFormat: (format: EditorFormat) => void;\n focus: () => void;\n clear: () => void;\n}\n\n// Map the kit's locale codes to Redactor's lang-file codes where they differ\n// (Redactor ships zh_cn / zh_tw / pt_br; the kit uses zh / pt). RTL (ar/fa/he)\n// pass through — direction is handled by the document dir, not the lang code.\nconst REDACTOR_LANG: Record<string, string> = {\n zh: 'zh_cn',\n pt: 'pt_br',\n};\n\nfunction toRedactorLang(locale: string): string {\n const base = locale.split('-')[0];\n return REDACTOR_LANG[base] ?? base ?? 'en';\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst wrapperVariants = cva(\n 'redactor-theme-alfadocs ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]',\n);\n\n// Degraded-mode plain textarea (Redactor not found) — looks like a kit field.\nconst degradedTextareaVariants = cva(\n [\n 'ds:block ds:[inline-size:100%]',\n 'ds:rounded-[var(--radius-md)] ds:border ds:border-[color:var(--border)]',\n 'ds:bg-[var(--background)] ds:text-[var(--foreground)]',\n 'ds:shadow-[var(--shadow-md)]',\n 'ds:font-[family-name:var(--font-sans)] ds:text-[length:var(--font-size-base)]',\n 'ds:p-[var(--spacing-md)] ds:[min-block-size:var(--rich-text-editor-min-block-size)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[var(--ring)]',\n 'ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n ].join(' '),\n);\n\n// Split-FAB segment: an icon button inside the primary pill (record |\n// help-me-write). Transparent on the pill with an INSET focus ring (the pill\n// clips overflow, so the ring must be inset).\nconst fabSegmentBase = [\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:[min-block-size:var(--min-target-size)] ds:[min-inline-size:var(--min-target-size)]',\n 'ds:text-[color:var(--primary-foreground)]',\n 'ds:transition-colors',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[var(--primary-foreground)]',\n 'ds:focus-visible:[outline-offset:calc(var(--focus-ring-width)*-1)]',\n].join(' ');\n\n// Idle segment: a translucent-white hover overlay over the pill.\nconst fabSegmentIdle = `${fabSegmentBase} ds:hover:bg-[color-mix(in_srgb,var(--primary-foreground)_15%,transparent)]`;\n\n// Recording mic: a solid destructive (red) fill that stays red on hover so the\n// \"stop\" state reads as live recording. Deliberately no aria-pressed translucent\n// overlay — its attribute selector out-specifies the red and would wash it out.\nconst fabSegmentRecording = `${fabSegmentBase} ds:bg-[var(--destructive)] ds:hover:bg-[color-mix(in_srgb,var(--destructive)_88%,var(--primary-foreground))]`;\n\n/* ------------------------------------------------------------------ */\n/* RichTextEditor */\n/* ------------------------------------------------------------------ */\n\nexport const RichTextEditor = forwardRef<\n RichTextEditorHandle,\n RichTextEditorProps\n>(\n (\n {\n id,\n defaultValue,\n value,\n onChange,\n toolbar = 'standard',\n placeholder,\n readOnly = false,\n ariaLabel,\n minHeight,\n showExtensions,\n className,\n redactor,\n options,\n plugins,\n lang,\n imageUploadUrl,\n onKeyDown,\n onRequestAiDraft,\n aiDraftFormat = 'html',\n aiPrivacyNotice,\n onDictate,\n onProofread,\n onAutoFormat,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n const rawId = useId();\n const editorId = useMemo(\n () => `rte-${rawId.replace(/[^a-zA-Z0-9-_]/g, '')}`,\n [rawId],\n );\n const selector = `#${editorId}`;\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const redactorRef = useRef<RedactorFactory | null>(null);\n // Skip-once guard: Redactor's `changed` already pushed this value out via\n // onChange, so the controlled-value effect must not echo it back with\n // setCode (which resets the caret to position 0). Mirrors platform.\n const skipNextPropSyncRef = useRef(false);\n // Mirrors the live readOnly state for imperative ops: Redactor blocks every\n // command except `disableReadOnly` while read-only, so writes (setContent /\n // clear / insertAtCursor / controlled-value sync) must lift it first.\n const readOnlyRef = useRef(readOnly);\n const wrapperRef = useRef<HTMLDivElement>(null);\n // The positioned editing-surface container — the floating table toolbar is\n // absolutely placed within it.\n const editorAreaRef = useRef<HTMLDivElement>(null);\n const [degraded, setDegraded] = useState(false);\n const [aiOpen, setAiOpen] = useState(false);\n // Active formats at the caret (bold/italic/strike/ul/ol/heading) — drives\n // the custom toolbar's pressed state; refreshed on Redactor's `observe`.\n const [activeFormats, setActiveFormats] = useState<ReadonlySet<string>>(\n () => new Set(),\n );\n\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const onChangeRef = useRef<RichTextEditorProps['onChange']>(onChange);\n const onKeyDownRef = useRef<RichTextEditorProps['onKeyDown']>(onKeyDown);\n useEffect(() => {\n onChangeRef.current = onChange;\n onKeyDownRef.current = onKeyDown;\n }, [onChange, onKeyDown]);\n\n // Initial content is computed once (controlled `value` is then synced by\n // the effect below). Sanitised before it ever reaches Redactor.\n const initialContentRef = useRef<string>(\n (() => {\n const raw = value ?? defaultValue ?? '';\n return raw ? sanitiseHtml(raw) : '';\n })(),\n );\n\n // Read the current editor HTML. Redactor's `source.getCode` is blocked while\n // read-only (returns undefined), so fall back to the synced source textarea\n // — never toggle read-only just to read.\n const readCode = useCallback((): string => {\n const R = redactorRef.current;\n if (R) {\n try {\n const code = R(selector, 'source.getCode');\n if (typeof code === 'string') return code;\n } catch {\n /* fall through to the source textarea */\n }\n }\n return textareaRef.current?.value ?? '';\n }, [selector]);\n\n // Dispatch a mutating Redactor command, transparently lifting read-only\n // (which blocks every command but `disableReadOnly`) and restoring it after.\n // Returns false when Redactor is absent or the call failed so the caller can\n // fall back to the degraded <textarea>.\n const dispatchWrite = useCallback(\n (command: string, ...args: unknown[]): boolean => {\n const R = redactorRef.current;\n if (!R) return false;\n const wasReadOnly = readOnlyRef.current;\n if (wasReadOnly) {\n try {\n R(selector, 'disableReadOnly');\n } catch {\n /* ignore */\n }\n }\n try {\n R(selector, command, ...args);\n return true;\n } catch {\n return false;\n } finally {\n if (wasReadOnly) {\n try {\n R(selector, 'enableReadOnly');\n } catch {\n // Restore failed — the editor may be left editable. Surface it in\n // DEV; the next readOnly-sync tick re-asserts it on a prop change.\n if (import.meta.env.DEV) {\n console.warn(\n '[RichTextEditor] failed to restore read-only after a write; the editor may be left editable.',\n );\n }\n }\n }\n }\n },\n [selector],\n );\n\n // Insert content at the caret, sanitised, with a degraded <textarea> splice\n // fallback. Shared by the imperative handle (merge variables) and the\n // Help-me-write dialog (AI drafts).\n const insertAtCursor = useCallback(\n (content: string, opts?: { asHtml?: boolean }): void => {\n const asHtml = opts?.asHtml ?? true;\n const payload = asHtml ? sanitiseHtml(content) : content;\n const command = asHtml\n ? 'insertion.insertHtml'\n : 'insertion.insertText';\n if (dispatchWrite(command, payload)) return;\n const ta = textareaRef.current;\n if (!ta) return;\n const start = ta.selectionStart ?? ta.value.length;\n const end = ta.selectionEnd ?? ta.value.length;\n ta.value = ta.value.slice(0, start) + payload + ta.value.slice(end);\n const caret = start + payload.length;\n try {\n ta.setSelectionRange(caret, caret);\n } catch {\n /* selection API unavailable */\n }\n onChangeRef.current?.({ html: sanitiseHtml(ta.value), markdown: '' });\n },\n [dispatchWrite],\n );\n\n // Last in-editor selection range — see updateActiveFormats / restoreSelection.\n const lastRangeRef = useRef<Range | null>(null);\n\n // Recompute the active inline/block formats at the caret (scoped to THIS\n // editor's `.redactor-in`) for the custom toolbar's pressed state.\n const updateActiveFormats = useCallback((): void => {\n const root = wrapperRef.current?.querySelector('.redactor-in');\n const selection =\n typeof window !== 'undefined' ? window.getSelection() : null;\n const next = new Set<string>();\n if (\n root &&\n selection &&\n selection.anchorNode &&\n root.contains(selection.anchorNode) &&\n typeof document.queryCommandState === 'function'\n ) {\n // Track the live in-editor range so a focus-stealing DS popover/dialog\n // can restore EXACTLY here — needed because Redactor's insertHtml wraps\n // the insert in a fresh <p> when no selection is active at insert time.\n if (selection.rangeCount > 0) {\n lastRangeRef.current = selection.getRangeAt(0).cloneRange();\n }\n // queryCommandState reads the selection's EFFECTIVE format (it handles\n // range boundaries + nesting), unlike walking the anchor's ancestors —\n // which misses a format when the anchor sits just outside the wrapper.\n try {\n if (document.queryCommandState('bold')) next.add('bold');\n if (document.queryCommandState('italic')) next.add('italic');\n if (document.queryCommandState('underline')) next.add('underline');\n if (document.queryCommandState('strikeThrough')) next.add('strike');\n if (document.queryCommandState('insertUnorderedList')) next.add('ul');\n if (document.queryCommandState('insertOrderedList')) next.add('ol');\n const block = String(\n document.queryCommandValue('formatBlock') || '',\n ).toLowerCase();\n // Add both the generic 'heading' token and the specific block tag\n // (h2/h3/quote/paragraph) so the toolbar's labelled style button can\n // show the active style by name.\n if (/^h[1-6]$/.test(block)) {\n next.add('heading');\n next.add(block);\n } else if (block === 'blockquote') {\n next.add('quote');\n } else {\n next.add('paragraph');\n }\n // Table context — drives the contextual table ops in the toolbar.\n const anchorEl =\n selection.anchorNode.nodeType === Node.TEXT_NODE\n ? selection.anchorNode.parentElement\n : (selection.anchorNode as Element | null);\n if (\n anchorEl &&\n root.contains(anchorEl) &&\n anchorEl.closest('table')\n ) {\n next.add('table');\n }\n } catch {\n /* queryCommand unsupported in this environment */\n }\n }\n setActiveFormats((prev) =>\n prev.size === next.size && [...next].every((f) => prev.has(f))\n ? prev\n : next,\n );\n }, []);\n\n // Run a Redactor command from the custom toolbar, then refresh active state.\n const runCommand = useCallback(\n (command: string, ...args: unknown[]): void => {\n dispatchWrite(command, ...args);\n // Defer the active-state read: let Redactor finish applying the command\n // and the selection settle first, otherwise un-toggling a format reads\n // the stale pre-change DOM and the button stays pressed.\n if (typeof window !== 'undefined') {\n window.requestAnimationFrame(() => updateActiveFormats());\n } else {\n updateActiveFormats();\n }\n },\n [dispatchWrite, updateActiveFormats],\n );\n\n // Inline-format keyboard shortcuts (Cmd/Ctrl + B/I/U). Redactor ships these\n // natively, but with `toolbar: false` its shortcut fires yet silently no-ops\n // (it preventDefaults the key, then its inline.format applies nothing). So\n // the kit owns them: intercept on the editor in the capture phase — before\n // Redactor's own keydown listener — and route through the SAME runCommand\n // path the toolbar uses (which works). stopImmediatePropagation suppresses\n // Redactor's dead handler; preventDefault suppresses the browser's native\n // execCommand so the format applies exactly once.\n useEffect(() => {\n const wrapper = wrapperRef.current;\n if (!wrapper) return undefined;\n // Local key→command map (the same inline commands the toolbar buttons\n // fire) so this owns nothing on the public format API.\n const SHORTCUT_COMMANDS: Record<string, [string, ...unknown[]]> = {\n b: ['module.inline.format', { tag: 'b' }],\n i: ['module.inline.format', { tag: 'i' }],\n u: ['module.inline.format', { tag: 'u' }],\n };\n const onKeyDownCapture = (event: KeyboardEvent): void => {\n if (!(event.metaKey || event.ctrlKey) || event.altKey || event.shiftKey)\n return;\n if (event.isComposing) return;\n const command = SHORTCUT_COMMANDS[event.key.toLowerCase()];\n if (!command) return;\n // Only when the caret is in this editor's editable, and it's writable.\n const editable = wrapper.querySelector('.redactor-in');\n if (\n !editable ||\n !(event.target instanceof Node) ||\n !editable.contains(event.target) ||\n readOnlyRef.current\n )\n return;\n event.preventDefault();\n event.stopImmediatePropagation();\n runCommand(...command);\n };\n wrapper.addEventListener('keydown', onKeyDownCapture, true);\n return () =>\n wrapper.removeEventListener('keydown', onKeyDownCapture, true);\n }, [runCommand]);\n\n // Insert sanitised HTML at the caret — the toolbar's link/image dialogs use\n // this (DOMPurify runs inside insertAtCursor) instead of Redactor's native\n // modals.\n const insertHtml = useCallback(\n (html: string): void => {\n insertAtCursor(html, { asHtml: true });\n if (typeof window !== 'undefined') {\n window.requestAnimationFrame(() => updateActiveFormats());\n }\n },\n [insertAtCursor, updateActiveFormats],\n );\n\n // Save / restore the editor selection around a DS popover/dialog (which\n // takes focus and would otherwise collapse the caret). Backed by Redactor's\n // selection module; no-ops in the degraded textarea.\n const saveSelection = useCallback((): void => {\n // Snapshot the current in-editor range synchronously (before a trigger's\n // focus move can collapse it), in addition to the observe-driven tracking.\n if (typeof window !== 'undefined') {\n const root = wrapperRef.current?.querySelector('.redactor-in');\n const sel = window.getSelection();\n if (\n root &&\n sel &&\n sel.rangeCount > 0 &&\n sel.anchorNode &&\n root.contains(sel.anchorNode)\n ) {\n lastRangeRef.current = sel.getRangeAt(0).cloneRange();\n }\n }\n const R = redactorRef.current;\n if (R) {\n try {\n R(selector, 'selection.save');\n } catch {\n /* selection module unavailable */\n }\n }\n }, [selector]);\n\n const restoreSelection = useCallback((): void => {\n const R = redactorRef.current;\n if (!R) return;\n // Re-focus the editor, then re-apply the tracked DOM range. This is more\n // reliable than Redactor's marker-based restore when a modal's focus trap\n // moved focus before the markers were set — without an active selection\n // Redactor's insertHtml wraps the insert in a new <p> (the link/image\n // \"block\" bug). Fall back to the marker restore if no range was tracked.\n // Capture the tracked range BEFORE editor.focus: focusing fires Redactor's\n // `observe`, which runs updateActiveFormats and overwrites lastRangeRef with\n // the post-focus caret (editor start). Reading it first preserves the\n // user's real selection (otherwise colour/link land at the top of the doc).\n const range = lastRangeRef.current;\n try {\n R(selector, 'editor.focus');\n } catch {\n /* ignore */\n }\n if (range && typeof window !== 'undefined') {\n const sel = window.getSelection();\n if (sel) {\n try {\n sel.removeAllRanges();\n sel.addRange(range);\n return;\n } catch {\n /* range no longer valid — fall through to marker restore */\n }\n }\n }\n try {\n R(selector, 'selection.restore');\n } catch {\n /* selection module unavailable */\n }\n }, [selector]);\n\n // Current selected text (for prefilling the link dialog's text field).\n const getSelectedText = useCallback((): string => {\n if (typeof window === 'undefined') return '';\n const root = wrapperRef.current?.querySelector('.redactor-in');\n const selection = window.getSelection();\n if (\n !root ||\n !selection ||\n !selection.anchorNode ||\n !root.contains(selection.anchorNode)\n ) {\n return '';\n }\n return selection.toString();\n }, []);\n\n // The <table> the caret is currently inside (scoped to THIS editor's\n // `.redactor-in`), or null — drives the floating in-cell table toolbar's\n // visibility + anchor. Mirrors the table detection in updateActiveFormats.\n const getActiveTableEl = useCallback((): HTMLElement | null => {\n if (typeof window === 'undefined') return null;\n const root = wrapperRef.current?.querySelector('.redactor-in');\n const selection = window.getSelection();\n if (!root || !selection || selection.rangeCount === 0) return null;\n const node = selection.anchorNode;\n const el =\n node && node.nodeType === Node.TEXT_NODE\n ? node.parentElement\n : (node as Element | null);\n if (!el || !root.contains(el)) return null;\n return el.closest('table');\n }, []);\n\n // The <td>/<th> the caret is in (scoped to this editor) — backs the table\n // background-colour controls.\n const lastCellRef = useRef<HTMLElement | null>(null);\n const getActiveCellEl = useCallback((): HTMLElement | null => {\n if (typeof window === 'undefined') return null;\n const root = wrapperRef.current?.querySelector('.redactor-in');\n const selection = window.getSelection();\n if (!root || !selection || selection.rangeCount === 0) return null;\n const node = selection.anchorNode;\n const el =\n node && node.nodeType === Node.TEXT_NODE\n ? node.parentElement\n : (node as Element | null);\n if (!el || !root.contains(el)) return null;\n return el.closest('td,th') as HTMLElement | null;\n }, []);\n\n // Snapshot the current cell before a colour popover steals focus.\n const saveTableCell = useCallback((): void => {\n lastCellRef.current = getActiveCellEl();\n }, [getActiveCellEl]);\n\n // Apply (colour) or clear (colour === null) a background on the saved cell,\n // or every cell in its row. Redactor has no cell-styling command, so this\n // mutates the editable DOM directly, takes a best-effort undo snapshot, then\n // hard-syncs so the change lands in the source + fires `changed` → onChange.\n const applyTableBackground = useCallback(\n (scope: 'cell' | 'row', colour: string | null): void => {\n const cell = lastCellRef.current ?? getActiveCellEl();\n if (!cell) return;\n const targets: HTMLElement[] =\n scope === 'row'\n ? Array.from(cell.closest('tr')?.children ?? [cell]).filter(\n (n): n is HTMLElement =>\n n instanceof HTMLElement &&\n (n.tagName === 'TD' || n.tagName === 'TH'),\n )\n : [cell];\n const R = redactorRef.current;\n if (R) {\n try {\n R(selector, 'module.buffer.trigger');\n } catch {\n /* undo buffer unavailable — colour still applies */\n }\n }\n for (const el of targets) {\n if (colour) el.style.setProperty('background-color', colour);\n else el.style.removeProperty('background-color');\n }\n if (R) {\n try {\n R(selector, 'broadcast', 'hardsync');\n } catch {\n /* sync unavailable */\n }\n }\n if (typeof window !== 'undefined') {\n window.requestAnimationFrame(() => updateActiveFormats());\n }\n },\n [getActiveCellEl, selector, updateActiveFormats],\n );\n\n // Insert a table, but never inside a list item — tables can't live in an\n // <li> and the nested markup hides the table UI. When the caret is in a\n // list, drop it after the whole list so the table lands as its own block.\n const insertTable = useCallback(\n (html: string): void => {\n const R = redactorRef.current;\n if (R && typeof window !== 'undefined') {\n const root = wrapperRef.current?.querySelector('.redactor-in');\n const selection = window.getSelection();\n const node = selection?.anchorNode;\n const el =\n node && node.nodeType === Node.TEXT_NODE\n ? node.parentElement\n : (node as Element | null);\n const list = el && root?.contains(el) ? el.closest('ul,ol') : null;\n if (list) {\n try {\n R(selector, 'caret.setAfter', list);\n } catch {\n /* caret module unavailable — falls back to cursor insert */\n }\n }\n }\n insertHtml(html);\n // Redactor's insertion leaves a stray trailing whitespace text node in\n // the final cell (<td><br> </td>); that space renders as a second line\n // and makes the last row taller WHILE EDITING. The saved source is\n // already clean (cleaner.output strips it), so just tidy the live\n // editable so every row renders at one line.\n if (typeof window !== 'undefined') {\n window.requestAnimationFrame(() => {\n const root = wrapperRef.current?.querySelector('.redactor-in');\n root?.querySelectorAll('table td, table th').forEach((cell) => {\n let last = cell.lastChild;\n while (\n last &&\n last.nodeType === Node.TEXT_NODE &&\n !(last.textContent ?? '').trim()\n ) {\n const prev = last.previousSibling;\n cell.removeChild(last);\n last = prev;\n }\n });\n });\n }\n },\n [insertHtml, selector],\n );\n\n // Upload an image file to the consumer's endpoint (mirrors Redactor's\n // imageUpload config) and resolve the stored URL — the image dialog's\n // upload tab uses this so users can upload, not just paste a URL.\n const uploadImage = useCallback(\n async (file: File, signal?: AbortSignal): Promise<string> => {\n if (!imageUploadUrl) throw new Error('No image upload URL configured.');\n const form = new FormData();\n form.append('file', file);\n const res = await fetch(imageUploadUrl, {\n method: 'POST',\n body: form,\n credentials: 'same-origin',\n signal,\n });\n if (!res.ok) throw new Error(`Image upload failed (${res.status}).`);\n const url = extractUploadedUrl(await res.json());\n if (!url) throw new Error('Image upload response contained no URL.');\n return url;\n },\n [imageUploadUrl],\n );\n\n /* ---- Voice dictation (DS UI; consumer runs mic + transcription) - */\n const dictateAbortRef = useRef<AbortController | null>(null);\n const interimRef = useRef<HTMLElement | null>(null);\n const [isDictating, setIsDictating] = useState(false);\n const [dictationErrored, setDictationErrored] = useState(false);\n // Drives the visually-hidden live region: announces the listening status on\n // start and each committed phrase as it lands, so screen-reader users get\n // the same feedback sighted users get from the grey interim span + caret.\n const [dictationAnnouncement, setDictationAnnouncement] = useState('');\n\n // Live (interim) speech shown in the editor as a grey, non-editable span\n // with a blinking caret; replaced by committed text on each final phrase.\n const clearInterim = useCallback((): void => {\n const el = interimRef.current;\n if (el?.parentNode) el.parentNode.removeChild(el);\n interimRef.current = null;\n }, []);\n\n const showInterim = useCallback((text: string): void => {\n const root = wrapperRef.current?.querySelector(\n '.redactor-in',\n ) as HTMLElement | null;\n if (!root) return;\n let el = interimRef.current;\n if (!el || !root.contains(el)) {\n el = document.createElement('span');\n el.setAttribute('data-rte-interim', '');\n el.setAttribute('contenteditable', 'false');\n const selection = window.getSelection();\n if (\n selection &&\n selection.rangeCount > 0 &&\n root.contains(selection.anchorNode)\n ) {\n const range = selection.getRangeAt(0);\n range.collapse(false);\n range.insertNode(el);\n } else {\n root.appendChild(el);\n }\n interimRef.current = el;\n }\n el.textContent = text;\n }, []);\n\n const stopDictation = useCallback(() => {\n // Abort but keep the ref: the in-flight session's `.finally` clears it\n // (and resets state) only when it's still the current session, so a normal\n // stop resets while a stale settle after a newer start does not.\n dictateAbortRef.current?.abort();\n }, []);\n\n const startDictation = useCallback(() => {\n if (!onDictate) return;\n const controller = new AbortController();\n dictateAbortRef.current = controller;\n setDictationErrored(false);\n setIsDictating(true);\n setDictationAnnouncement(t('editor.ai.listening'));\n clearInterim();\n onDictate({\n signal: controller.signal,\n // Interim text shows live in the editor (grey + caret); each final\n // replaces it with committed text at the caret.\n onPartialTranscript: (text: string): void => {\n if (controller.signal.aborted) return;\n showInterim(text);\n },\n onFinalTranscript: (text: string): void => {\n if (controller.signal.aborted) return;\n clearInterim();\n const trimmed = text.trim();\n if (trimmed) {\n insertAtCursor(`${trimmed} `, { asHtml: false });\n // Announce the committed phrase; it replaces the interim text the\n // SR could not perceive (the grey span is aria-hidden DOM injected\n // outside React's tree).\n setDictationAnnouncement(trimmed);\n }\n },\n })\n .catch((err: unknown) => {\n if (\n controller.signal.aborted ||\n (err &&\n typeof err === 'object' &&\n 'name' in err &&\n (err as { name?: string }).name === 'AbortError')\n ) {\n return;\n }\n setDictationErrored(true);\n })\n .finally(() => {\n clearInterim();\n // Only the session that still owns the ref resets state — a stale\n // settle (a newer session already started) must not clobber it.\n if (dictateAbortRef.current === controller) {\n dictateAbortRef.current = null;\n setIsDictating(false);\n setDictationAnnouncement('');\n }\n });\n }, [onDictate, insertAtCursor, clearInterim, showInterim, t]);\n\n const toggleDictation = useCallback(() => {\n if (isDictating) stopDictation();\n else startDictation();\n }, [isDictating, startDictation, stopDictation]);\n\n // Abort dictation on unmount.\n useEffect(() => () => dictateAbortRef.current?.abort(), []);\n\n /* ---- One-shot AI document actions (proofread / auto-format) ---- */\n // Which one-shot action is running (drives the FAB spinner + the editor's\n // disabled scrim); only one runs at a time.\n const [oneShot, setOneShot] = useState<'proofread' | 'format' | null>(null);\n const oneShotAbortRef = useRef<AbortController | null>(null);\n const runOneShot = useCallback(\n (\n kind: 'proofread' | 'format',\n fn: (ctx: { html: string; signal: AbortSignal }) => Promise<string>,\n ): void => {\n if (oneShotAbortRef.current) return; // one at a time\n const controller = new AbortController();\n oneShotAbortRef.current = controller;\n setOneShot(kind);\n const html = readCode();\n Promise.resolve(fn({ html, signal: controller.signal }))\n .then((result) => {\n if (controller.signal.aborted) return;\n // Replace the whole document with the rewritten HTML (re-sanitised\n // at the editor seam) and notify the consumer.\n const safe = sanitiseHtml(String(result ?? ''));\n dispatchWrite('source.setCode', safe);\n onChangeRef.current?.({ html: safe, markdown: '' });\n })\n .catch(() => {\n /* abort / backend error — leave the document unchanged */\n })\n .finally(() => {\n if (oneShotAbortRef.current === controller) {\n oneShotAbortRef.current = null;\n setOneShot(null);\n }\n });\n },\n [readCode, dispatchWrite],\n );\n\n // Cancel a running one-shot. Clears the UI immediately (and aborts the\n // signal) rather than waiting on the promise, so the user always recovers\n // even if the consumer's call ignores the signal / hangs — the settle\n // guards (aborted + ref identity) then make the late result a no-op.\n const cancelOneShot = useCallback((): void => {\n oneShotAbortRef.current?.abort();\n oneShotAbortRef.current = null;\n setOneShot(null);\n }, []);\n\n // Abort an in-flight one-shot on unmount.\n useEffect(() => () => oneShotAbortRef.current?.abort(), []);\n\n /* ---- Init Redactor once (or degrade gracefully) -------------- */\n useEffect(() => {\n const ta = textareaRef.current;\n if (!ta) return undefined;\n // Seed the host textarea imperatively: Redactor reads it on init, and in\n // degraded mode it stays as the textarea's shown value. (Done here, not\n // via `defaultValue`, because `degraded` flips after mount so a\n // `defaultValue` prop would never apply.)\n ta.value = initialContentRef.current;\n const R = resolveRedactor(redactor);\n if (!R) {\n setDegraded(true);\n if (import.meta.env.DEV) {\n console.warn(\n '[RichTextEditor] Redactor not found on window.$R / window.Redactor and no `redactor` prop supplied; rendering a plain textarea.',\n );\n }\n return undefined;\n }\n redactorRef.current = R;\n\n const kitDefaults: Record<string, unknown> = {\n lang: lang ?? toRedactorLang(i18n.language || 'en'),\n // The kit renders its OWN toolbar (EditorToolbar) and drives Redactor\n // via the command API, so Redactor's native toolbar is suppressed.\n toolbar: false,\n plugins: plugins ?? [],\n placeholder: placeholder ?? t('editor.placeholder'),\n toolbarFixed: false,\n // Platform parity (RedactorWysiwyg.js:84): no inline shortcode expansion.\n shortcodes: false,\n imageEditable: false,\n imageResizable: true,\n };\n const imageUploadOption = imageUploadUrl\n ? { imageUpload: imageUploadUrl }\n : {};\n\n const consumerCallbacks =\n (options?.callbacks as Record<string, unknown> | undefined) ?? {};\n\n const finalOptions: Record<string, unknown> = {\n ...kitDefaults,\n ...imageUploadOption,\n ...(options ?? {}),\n // Re-pin safety-critical keys LAST so consumer `options` can't override\n // the sanitising change handler, re-enable image editing, or turn off\n // drag-resize (platform re-pins both image flags — RedactorWysiwyg.js:115-116).\n imageEditable: false,\n imageResizable: true,\n callbacks: {\n ...consumerCallbacks,\n changed(html: string): void {\n const normalized = normalizeEditorValue(withLazyImages(html));\n const safe = sanitiseHtml(normalized);\n skipNextPropSyncRef.current = true;\n if (!onChangeRef.current) return;\n if (debounceRef.current) clearTimeout(debounceRef.current);\n debounceRef.current = setTimeout(() => {\n onChangeRef.current?.({ html: safe, markdown: '' });\n }, 100);\n },\n keydown(event: KeyboardEvent): void {\n onKeyDownRef.current?.(event);\n },\n observe(): void {\n updateActiveFormats();\n },\n },\n };\n\n try {\n R(selector, finalOptions);\n // Redactor's read-only commands are camel-cased `enableReadOnly` /\n // `disableReadOnly` in this build (lower-case `enableReadonly` is a\n // silent no-op). Guarded so an unknown command stays inert.\n if (readOnly) {\n try {\n R(selector, 'enableReadOnly');\n } catch {\n /* readonly command unsupported in this Redactor build */\n }\n }\n } catch {\n setDegraded(true);\n }\n\n return () => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n try {\n // Platform forgets to destroy and leaks; we clean up on unmount.\n R(selector, 'destroy');\n } catch {\n /* already torn down */\n }\n redactorRef.current = null;\n };\n // Init once — option changes after mount are not re-applied (matches the\n // editor's uncontrolled-internals model); value/readOnly sync below.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n /* ---- Keep controlled `value` in sync (skip-once caret guard) - */\n useEffect(() => {\n if (!redactorRef.current || value === undefined) return;\n if (skipNextPropSyncRef.current) {\n skipNextPropSyncRef.current = false;\n return;\n }\n const safe = sanitiseHtml(normalizeEditorValue(value));\n const current = normalizeEditorValue(readCode());\n if (current !== safe) dispatchWrite('source.setCode', safe);\n }, [value, readCode, dispatchWrite]);\n\n /* ---- Keep readOnly in sync ----------------------------------- */\n useEffect(() => {\n readOnlyRef.current = readOnly;\n const R = redactorRef.current;\n if (!R) return;\n try {\n R(selector, readOnly ? 'enableReadOnly' : 'disableReadOnly');\n } catch {\n /* readonly command unsupported in this Redactor build */\n }\n }, [readOnly, selector]);\n\n /* ---- Degraded fallback: reflect controlled `value` ----------- */\n // Without Redactor the host textarea is uncontrolled (seeded once on init),\n // so it would otherwise ignore external `value` updates. Sync imperatively\n // (a controlled `value=` would warn when `degraded` flips after mount), and\n // skip while focused so we never reset the user's caret mid-type.\n useEffect(() => {\n if (!degraded || value === undefined) return;\n const ta = textareaRef.current;\n if (!ta) return;\n const safe = sanitiseHtml(value);\n if (ta.value !== safe && document.activeElement !== ta) {\n ta.value = safe;\n }\n }, [degraded, value]);\n\n /* ---- Imperative handle --------------------------------------- */\n const handle = useMemo<RichTextEditorHandle>(\n () => ({\n getHTML(): string {\n return readCode();\n },\n getText(): string {\n return readCode()\n .replace(/<[^>]*>/g, ' ')\n .replace(/ /gi, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n },\n getMarkdown(): string {\n return '';\n },\n setContent(html: string): void {\n const safe = sanitiseHtml(html);\n if (dispatchWrite('source.setCode', safe)) return;\n if (textareaRef.current) textareaRef.current.value = safe;\n },\n insertAtCursor,\n applyFormat(format): void {\n const command = FORMAT_COMMANDS[format];\n if (command) runCommand(...command);\n },\n focus(): void {\n const R = redactorRef.current;\n if (R) {\n try {\n R(selector, 'editor.focus');\n return;\n } catch {\n /* fall through */\n }\n }\n textareaRef.current?.focus();\n },\n clear(): void {\n if (dispatchWrite('source.setCode', '')) return;\n if (textareaRef.current) textareaRef.current.value = '';\n },\n }),\n [selector, readCode, dispatchWrite, insertAtCursor, runCommand],\n );\n useImperativeHandle(ref, () => handle, [handle]);\n useAgentRegistration(richTextEditorAgent, handle, id);\n\n /* ---- Degraded-mode change handler ---------------------------- */\n const handleDegradedChange = useCallback(\n (event: ChangeEvent<HTMLTextAreaElement>): void => {\n onChangeRef.current?.({\n html: sanitiseHtml(event.target.value),\n markdown: '',\n });\n },\n [],\n );\n\n // Accessible name for the editing region — a dedicated label, not the\n // placeholder, so the region's name and its placeholder hint don't collide.\n const resolvedLabel = ariaLabel ?? t('editor.regionLabel');\n const resolvedPlaceholder = placeholder ?? t('editor.placeholder');\n\n // AI FAB segments — rendered as one pill in this order: dictation · spelling\n // & grammar · auto-format · Alia. The two one-shot actions show a spinner\n // while running; everything else is disabled meanwhile.\n const busy = oneShot !== null;\n const fabSegments: {\n key: string;\n icon: ReactNode;\n label: string;\n onClick: () => void;\n recording?: boolean;\n running?: boolean;\n }[] = [];\n if (onDictate) {\n fabSegments.push({\n key: 'dictate',\n icon: isDictating ? (\n <Square aria-hidden=\"true\" className=\"ds:size-5 ds:fill-current\" />\n ) : (\n <Mic aria-hidden=\"true\" className=\"ds:size-5\" />\n ),\n label: isDictating\n ? t('editor.ai.dictateStop')\n : t('editor.ai.dictateStart'),\n onClick: toggleDictation,\n recording: isDictating,\n });\n }\n if (onProofread) {\n fabSegments.push({\n key: 'proofread',\n // While running, the segment becomes a STOP/cancel button (progress is\n // shown by the scrim spinner).\n icon:\n oneShot === 'proofread' ? (\n <Square aria-hidden=\"true\" className=\"ds:size-5 ds:fill-current\" />\n ) : (\n <SpellCheck aria-hidden=\"true\" className=\"ds:size-5\" />\n ),\n label:\n oneShot === 'proofread'\n ? t('common.cancel')\n : t('editor.ai.proofread', 'Check spelling & grammar'),\n onClick:\n oneShot === 'proofread'\n ? cancelOneShot\n : () => runOneShot('proofread', onProofread),\n running: oneShot === 'proofread',\n });\n }\n if (onAutoFormat) {\n fabSegments.push({\n key: 'format',\n icon:\n oneShot === 'format' ? (\n <Square aria-hidden=\"true\" className=\"ds:size-5 ds:fill-current\" />\n ) : (\n <WandSparkles aria-hidden=\"true\" className=\"ds:size-5\" />\n ),\n label:\n oneShot === 'format'\n ? t('common.cancel')\n : t('editor.ai.autoFormat', 'Auto-format document'),\n onClick:\n oneShot === 'format'\n ? cancelOneShot\n : () => runOneShot('format', onAutoFormat),\n running: oneShot === 'format',\n });\n }\n if (onRequestAiDraft) {\n fabSegments.push({\n key: 'write',\n icon: <Sparkles aria-hidden=\"true\" className=\"ds:size-5\" />,\n label: t('editor.ai.helpMeWrite'),\n onClick: () => {\n saveSelection();\n setAiOpen(true);\n },\n });\n }\n\n return (\n <div\n ref={wrapperRef}\n className={[wrapperVariants(), className].filter(Boolean).join(' ')}\n data-component=\"rich-text-editor\"\n data-component-id={id}\n data-min-height={minHeight}\n >\n {!degraded && !readOnly ? (\n <EditorToolbar\n run={runCommand}\n active={activeFormats}\n preset={toolbar}\n insertHtml={insertHtml}\n insertTable={insertTable}\n saveSelection={saveSelection}\n restoreSelection={restoreSelection}\n getSelectedText={getSelectedText}\n uploadImage={imageUploadUrl ? uploadImage : undefined}\n enableColor={plugins?.includes('fontcolor') ?? false}\n enableImage={Boolean(imageUploadUrl)}\n enableTable={plugins?.includes('table') ?? false}\n showExtensions={showExtensions}\n />\n ) : null}\n <div className=\"ds:relative\" ref={editorAreaRef}>\n <textarea\n ref={textareaRef}\n id={editorId}\n aria-label={resolvedLabel}\n aria-multiline=\"true\"\n aria-busy={busy || undefined}\n placeholder={resolvedPlaceholder}\n onChange={degraded ? handleDegradedChange : undefined}\n readOnly={degraded ? readOnly : undefined}\n className={degraded ? degradedTextareaVariants() : undefined}\n />\n {/* While a one-shot AI action runs, dim + block the editor (it's being\n rewritten) with a centred spinner; the running FAB segment turns\n into a Stop/Cancel button. */}\n {busy ? (\n <div\n aria-hidden=\"true\"\n className=\"ds:absolute ds:inset-0 ds:z-[5] ds:flex ds:items-center ds:justify-center ds:cursor-wait ds:rounded-[var(--radius-md)] ds:bg-[color-mix(in_srgb,var(--background)_40%,transparent)]\"\n >\n <Spinner size=\"lg\" variant=\"prism\" />\n </div>\n ) : null}\n {/* AI affordances — the FAB + Alia popout. Wrapped in a zero-height\n STICKY dock (its only children are absolute) so in a long document\n they ride the viewport's block-end instead of scrolling off at the\n editor's bottom; the FAB/overlay keep their absolute positioning,\n now anchored to this dock. */}\n <div className=\"ds:sticky ds:bottom-0 ds:z-10\">\n {fabSegments.length > 0 ? (\n <div className=\"ds:absolute ds:[inset-block-end:var(--spacing-md)] ds:[inset-inline-end:var(--spacing-md)] ds:z-10 ds:flex ds:items-center ds:overflow-hidden ds:rounded-full ds:bg-[var(--primary)] ds:bg-[image:var(--gradient-brand)] ds:shadow-[0_8px_24px_color-mix(in_srgb,var(--primary)_35%,transparent)]\">\n {fabSegments.map((seg, i) => (\n <Fragment key={seg.key}>\n {i > 0 ? (\n <span\n aria-hidden=\"true\"\n className=\"ds:self-stretch ds:[inline-size:var(--border-width-sm)] ds:bg-[color-mix(in_srgb,var(--primary-foreground)_35%,transparent)]\"\n />\n ) : null}\n <button\n type=\"button\"\n onClick={seg.onClick}\n aria-pressed={seg.recording || undefined}\n aria-busy={seg.running || undefined}\n disabled={(busy && !seg.running) || undefined}\n aria-label={seg.label}\n title={seg.label}\n className={\n seg.recording ? fabSegmentRecording : fabSegmentIdle\n }\n >\n {seg.icon}\n </button>\n </Fragment>\n ))}\n </div>\n ) : null}\n {onRequestAiDraft ? (\n <HelpMeWriteOverlay\n open={aiOpen}\n onClose={() => setAiOpen(false)}\n onRequestAiDraft={onRequestAiDraft}\n onInsert={(draft) => {\n // Restore the caret saved when the FAB opened the overlay, so\n // the draft lands where the user was, not at the doc start.\n restoreSelection();\n insertAtCursor(draft, { asHtml: aiDraftFormat !== 'text' });\n }}\n previewAsHtml={aiDraftFormat !== 'text'}\n privacyNotice={aiPrivacyNotice}\n onDictate={onDictate}\n />\n ) : null}\n </div>\n {/* Rendered LAST inside the positioned container (after the Redactor-\n managed textarea/box) so its conditional mount never asks React to\n insertBefore the textarea, which Redactor moves into its own box\n (that would throw \"node ... is not a child of this node\"). */}\n {!degraded && !readOnly && (plugins?.includes('table') ?? false) ? (\n <TableFloatingToolbar\n active={activeFormats}\n run={runCommand}\n areaRef={editorAreaRef}\n getActiveTableEl={getActiveTableEl}\n enableColor={plugins?.includes('fontcolor') ?? false}\n saveTableCell={saveTableCell}\n applyTableBackground={applyTableBackground}\n />\n ) : null}\n </div>\n {onDictate ? (\n <p className=\"ds:sr-only\" role=\"status\" aria-live=\"polite\">\n {dictationAnnouncement}\n </p>\n ) : null}\n {onDictate && dictationErrored ? (\n <p\n role=\"alert\"\n className=\"ds:text-[length:var(--font-size-sm)] ds:text-[color:var(--destructive)]\"\n >\n {t('editor.ai.dictationError')}\n </p>\n ) : null}\n </div>\n );\n },\n);\n\nRichTextEditor.displayName = 'RichTextEditor';\n\nexport { wrapperVariants };\n"],"names":["__iconNode","BetweenHorizontalEnd","createLucideIcon","BetweenHorizontalStart","BetweenVerticalEnd","BetweenVerticalStart","Bold","Heading2","Heading3","Highlighter","Italic","Link","ListOrdered","List","PaintBucket","PaintRoller","Palette","PanelTopDashed","PanelTop","Pilcrow","Quote","Rows2","SpellCheck","Strikethrough","Table","Underline","WandSparkles","Wrench","richTextEditorAgent","handle","args","RECORDING_MIC","ACTION_SIZE","noticeClass","errorClass","previewClass","joinWith","base","extra","HelpMeWriteOverlay","open","onClose","onRequestAiDraft","onInsert","previewAsHtml","privacyNotice","onDictate","t","useTranslation","promptId","useId","errorId","prompt","setPrompt","useState","loading","setLoading","errored","setErrored","draft","setDraft","abortRef","useRef","isDictating","setIsDictating","interim","setInterim","dictationAnnouncement","setDictationAnnouncement","dictateAbortRef","stopDictation","useCallback","_a","startDictation","controller","text","trimmed","p","toggleDictation","useEffect","_b","generate","result","err","insert","hasDraft","fieldValue","jsx","EditorOverlay","jsxs","IconButton","X","SafeHtml","RotateCcw","Check","Fragment","TextArea","event","Square","Mic","Spinner","Send","ITEMS","FORMAT_OPTIONS","PRESETS","TABLE_OPS","Columns2","Trash2","TABLE_GRID","toolbarClass","cva","dividerClass","fieldLabelClass","esc","value","StyleMenu","run","active","onTriggerDown","current","o","DropdownMenu","Button","ChevronDown","opt","LinkDialog","insertHtml","saveSelection","restoreSelection","getSelectedText","setOpen","url","setUrl","setText","newTab","setNewTab","urlId","textId","reset","handleInsert","href","label","tab","html","Dialog","LinkIcon","TextInput","Checkbox","checked","ImageDialog","uploadImage","src","setSrc","alt","setAlt","srcId","altId","insertImage","altText","ImageIcon","FileUpload","file","signal","ColourControl","colour","setColour","applyColour","hex","removeColour","Popover","ColorPicker","HighlightControl","applyHighlight","removeHighlight","buildTable","rows","cols","cells","TableControl","insertTable","hover","setHover","inTable","TableIcon","op","_","i","r","c","on","TABLE_OP_BY_ID","tableFloatClass","TABLE_BG_SEED","TableBgColourControl","scope","icon","onOpenChange","saveTableCell","applyTableBackground","TableFloatingToolbar","areaRef","getActiveTableEl","enableColor","pos","setPos","colourOpenCount","colourOpen","setColourOpen","handleColourOpenChange","recompute","area","table","a","rtl","top","center","ro","groups","TooltipProvider","group","gi","opId","EditorToolbar","preset","enableImage","enableTable","showExtensions","keepSelection","has","id","btn","item","Divider","styleGroup","inlineGroup","listsGroup","insertGroup","sanitiseHtml","input","sanitiseShared","normalizeEditorValue","normalized","contentWithoutTags","withLazyImages","extractUploadedUrl","data","rec","fromNode","node","resolveRedactor","injected","w","FORMAT_COMMANDS","REDACTOR_LANG","toRedactorLang","locale","wrapperVariants","degradedTextareaVariants","fabSegmentBase","fabSegmentIdle","fabSegmentRecording","RichTextEditor","forwardRef","defaultValue","onChange","toolbar","placeholder","readOnly","ariaLabel","minHeight","className","redactor","options","plugins","lang","imageUploadUrl","onKeyDown","aiDraftFormat","aiPrivacyNotice","onProofread","onAutoFormat","ref","i18n","rawId","editorId","useMemo","selector","textareaRef","redactorRef","skipNextPropSyncRef","readOnlyRef","wrapperRef","editorAreaRef","degraded","setDegraded","aiOpen","setAiOpen","activeFormats","setActiveFormats","debounceRef","onChangeRef","onKeyDownRef","initialContentRef","raw","readCode","R","code","dispatchWrite","command","wasReadOnly","insertAtCursor","content","opts","asHtml","payload","ta","start","end","caret","lastRangeRef","updateActiveFormats","root","selection","next","block","anchorEl","prev","f","runCommand","wrapper","SHORTCUT_COMMANDS","onKeyDownCapture","editable","sel","range","el","lastCellRef","getActiveCellEl","cell","targets","n","list","last","form","res","interimRef","dictationErrored","setDictationErrored","clearInterim","showInterim","oneShot","setOneShot","oneShotAbortRef","runOneShot","kind","fn","safe","cancelOneShot","kitDefaults","imageUploadOption","consumerCallbacks","finalOptions","format","useImperativeHandle","useAgentRegistration","handleDegradedChange","resolvedLabel","resolvedPlaceholder","busy","fabSegments","Sparkles","seg"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]}
|
|
1
|
+
{"version":3,"file":"rich-text-editor-DlCqPixb.js","sources":["../../node_modules/lucide-react/dist/esm/icons/between-horizontal-end.js","../../node_modules/lucide-react/dist/esm/icons/between-horizontal-start.js","../../node_modules/lucide-react/dist/esm/icons/between-vertical-end.js","../../node_modules/lucide-react/dist/esm/icons/between-vertical-start.js","../../node_modules/lucide-react/dist/esm/icons/bold.js","../../node_modules/lucide-react/dist/esm/icons/heading-2.js","../../node_modules/lucide-react/dist/esm/icons/heading-3.js","../../node_modules/lucide-react/dist/esm/icons/highlighter.js","../../node_modules/lucide-react/dist/esm/icons/italic.js","../../node_modules/lucide-react/dist/esm/icons/link.js","../../node_modules/lucide-react/dist/esm/icons/list-ordered.js","../../node_modules/lucide-react/dist/esm/icons/list.js","../../node_modules/lucide-react/dist/esm/icons/paint-bucket.js","../../node_modules/lucide-react/dist/esm/icons/paint-roller.js","../../node_modules/lucide-react/dist/esm/icons/palette.js","../../node_modules/lucide-react/dist/esm/icons/panel-top-dashed.js","../../node_modules/lucide-react/dist/esm/icons/panel-top.js","../../node_modules/lucide-react/dist/esm/icons/pilcrow.js","../../node_modules/lucide-react/dist/esm/icons/quote.js","../../node_modules/lucide-react/dist/esm/icons/rows-2.js","../../node_modules/lucide-react/dist/esm/icons/spell-check.js","../../node_modules/lucide-react/dist/esm/icons/strikethrough.js","../../node_modules/lucide-react/dist/esm/icons/table.js","../../node_modules/lucide-react/dist/esm/icons/underline.js","../../node_modules/lucide-react/dist/esm/icons/wand-sparkles.js","../../node_modules/lucide-react/dist/esm/icons/wrench.js","../../src/components/rich-text-editor/rich-text-editor.agent.ts","../../src/components/rich-text-editor/help-me-write-overlay.tsx","../../src/components/rich-text-editor/editor-toolbar.tsx","../../src/components/rich-text-editor/rich-text-editor.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"13\", height: \"7\", x: \"3\", y: \"3\", rx: \"1\", key: \"11xb64\" }],\n [\"path\", { d: \"m22 15-3-3 3-3\", key: \"26chmm\" }],\n [\"rect\", { width: \"13\", height: \"7\", x: \"3\", y: \"14\", rx: \"1\", key: \"k6ky7n\" }]\n];\nconst BetweenHorizontalEnd = createLucideIcon(\"between-horizontal-end\", __iconNode);\n\nexport { __iconNode, BetweenHorizontalEnd as default };\n//# sourceMappingURL=between-horizontal-end.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"13\", height: \"7\", x: \"8\", y: \"3\", rx: \"1\", key: \"pkso9a\" }],\n [\"path\", { d: \"m2 9 3 3-3 3\", key: \"1agib5\" }],\n [\"rect\", { width: \"13\", height: \"7\", x: \"8\", y: \"14\", rx: \"1\", key: \"1q5fc1\" }]\n];\nconst BetweenHorizontalStart = createLucideIcon(\"between-horizontal-start\", __iconNode);\n\nexport { __iconNode, BetweenHorizontalStart as default };\n//# sourceMappingURL=between-horizontal-start.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"7\", height: \"13\", x: \"3\", y: \"3\", rx: \"1\", key: \"1fdu0f\" }],\n [\"path\", { d: \"m9 22 3-3 3 3\", key: \"17z65a\" }],\n [\"rect\", { width: \"7\", height: \"13\", x: \"14\", y: \"3\", rx: \"1\", key: \"1squn4\" }]\n];\nconst BetweenVerticalEnd = createLucideIcon(\"between-vertical-end\", __iconNode);\n\nexport { __iconNode, BetweenVerticalEnd as default };\n//# sourceMappingURL=between-vertical-end.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"7\", height: \"13\", x: \"3\", y: \"8\", rx: \"1\", key: \"1fjrkv\" }],\n [\"path\", { d: \"m15 2-3 3-3-3\", key: \"1uh6eb\" }],\n [\"rect\", { width: \"7\", height: \"13\", x: \"14\", y: \"8\", rx: \"1\", key: \"w3fjg8\" }]\n];\nconst BetweenVerticalStart = createLucideIcon(\"between-vertical-start\", __iconNode);\n\nexport { __iconNode, BetweenVerticalStart as default };\n//# sourceMappingURL=between-vertical-start.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n { d: \"M6 12h9a4 4 0 0 1 0 8H7a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h7a4 4 0 0 1 0 8\", key: \"mg9rjx\" }\n ]\n];\nconst Bold = createLucideIcon(\"bold\", __iconNode);\n\nexport { __iconNode, Bold as default };\n//# sourceMappingURL=bold.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M4 12h8\", key: \"17cfdx\" }],\n [\"path\", { d: \"M4 18V6\", key: \"1rz3zl\" }],\n [\"path\", { d: \"M12 18V6\", key: \"zqpxq5\" }],\n [\"path\", { d: \"M21 18h-4c0-4 4-3 4-6 0-1.5-2-2.5-4-1\", key: \"9jr5yi\" }]\n];\nconst Heading2 = createLucideIcon(\"heading-2\", __iconNode);\n\nexport { __iconNode, Heading2 as default };\n//# sourceMappingURL=heading-2.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M4 12h8\", key: \"17cfdx\" }],\n [\"path\", { d: \"M4 18V6\", key: \"1rz3zl\" }],\n [\"path\", { d: \"M12 18V6\", key: \"zqpxq5\" }],\n [\"path\", { d: \"M17.5 10.5c1.7-1 3.5 0 3.5 1.5a2 2 0 0 1-2 2\", key: \"68ncm8\" }],\n [\"path\", { d: \"M17 17.5c2 1.5 4 .3 4-1.5a2 2 0 0 0-2-2\", key: \"1ejuhz\" }]\n];\nconst Heading3 = createLucideIcon(\"heading-3\", __iconNode);\n\nexport { __iconNode, Heading3 as default };\n//# sourceMappingURL=heading-3.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"m9 11-6 6v3h9l3-3\", key: \"1a3l36\" }],\n [\"path\", { d: \"m22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4\", key: \"14a9rk\" }]\n];\nconst Highlighter = createLucideIcon(\"highlighter\", __iconNode);\n\nexport { __iconNode, Highlighter as default };\n//# sourceMappingURL=highlighter.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"line\", { x1: \"19\", x2: \"10\", y1: \"4\", y2: \"4\", key: \"15jd3p\" }],\n [\"line\", { x1: \"14\", x2: \"5\", y1: \"20\", y2: \"20\", key: \"bu0au3\" }],\n [\"line\", { x1: \"15\", x2: \"9\", y1: \"4\", y2: \"20\", key: \"uljnxc\" }]\n];\nconst Italic = createLucideIcon(\"italic\", __iconNode);\n\nexport { __iconNode, Italic as default };\n//# sourceMappingURL=italic.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71\", key: \"1cjeqo\" }],\n [\"path\", { d: \"M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71\", key: \"19qd67\" }]\n];\nconst Link = createLucideIcon(\"link\", __iconNode);\n\nexport { __iconNode, Link as default };\n//# sourceMappingURL=link.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M11 5h10\", key: \"1cz7ny\" }],\n [\"path\", { d: \"M11 12h10\", key: \"1438ji\" }],\n [\"path\", { d: \"M11 19h10\", key: \"11t30w\" }],\n [\"path\", { d: \"M4 4h1v5\", key: \"10yrso\" }],\n [\"path\", { d: \"M4 9h2\", key: \"r1h2o0\" }],\n [\"path\", { d: \"M6.5 20H3.4c0-1 2.6-1.925 2.6-3.5a1.5 1.5 0 0 0-2.6-1.02\", key: \"xtkcd5\" }]\n];\nconst ListOrdered = createLucideIcon(\"list-ordered\", __iconNode);\n\nexport { __iconNode, ListOrdered as default };\n//# sourceMappingURL=list-ordered.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M3 5h.01\", key: \"18ugdj\" }],\n [\"path\", { d: \"M3 12h.01\", key: \"nlz23k\" }],\n [\"path\", { d: \"M3 19h.01\", key: \"noohij\" }],\n [\"path\", { d: \"M8 5h13\", key: \"1pao27\" }],\n [\"path\", { d: \"M8 12h13\", key: \"1za7za\" }],\n [\"path\", { d: \"M8 19h13\", key: \"m83p4d\" }]\n];\nconst List = createLucideIcon(\"list\", __iconNode);\n\nexport { __iconNode, List as default };\n//# sourceMappingURL=list.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M11 7 6 2\", key: \"1jwth8\" }],\n [\"path\", { d: \"M18.992 12H2.041\", key: \"xw1gg\" }],\n [\n \"path\",\n {\n d: \"M21.145 18.38A3.34 3.34 0 0 1 20 16.5a3.3 3.3 0 0 1-1.145 1.88c-.575.46-.855 1.02-.855 1.595A2 2 0 0 0 20 22a2 2 0 0 0 2-2.025c0-.58-.285-1.13-.855-1.595\",\n key: \"1nkol4\"\n }\n ],\n [\n \"path\",\n {\n d: \"m8.5 4.5 2.148-2.148a1.205 1.205 0 0 1 1.704 0l7.296 7.296a1.205 1.205 0 0 1 0 1.704l-7.592 7.592a3.615 3.615 0 0 1-5.112 0l-3.888-3.888a3.615 3.615 0 0 1 0-5.112L5.67 7.33\",\n key: \"1nk1rd\"\n }\n ]\n];\nconst PaintBucket = createLucideIcon(\"paint-bucket\", __iconNode);\n\nexport { __iconNode, PaintBucket as default };\n//# sourceMappingURL=paint-bucket.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"16\", height: \"6\", x: \"2\", y: \"2\", rx: \"2\", key: \"jcyz7m\" }],\n [\"path\", { d: \"M10 16v-2a2 2 0 0 1 2-2h8a2 2 0 0 0 2-2V7a2 2 0 0 0-2-2h-2\", key: \"1b9h7c\" }],\n [\"rect\", { width: \"4\", height: \"6\", x: \"8\", y: \"16\", rx: \"1\", key: \"d6e7yl\" }]\n];\nconst PaintRoller = createLucideIcon(\"paint-roller\", __iconNode);\n\nexport { __iconNode, PaintRoller as default };\n//# sourceMappingURL=paint-roller.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M12 22a1 1 0 0 1 0-20 10 9 0 0 1 10 9 5 5 0 0 1-5 5h-2.25a1.75 1.75 0 0 0-1.4 2.8l.3.4a1.75 1.75 0 0 1-1.4 2.8z\",\n key: \"e79jfc\"\n }\n ],\n [\"circle\", { cx: \"13.5\", cy: \"6.5\", r: \".5\", fill: \"currentColor\", key: \"1okk4w\" }],\n [\"circle\", { cx: \"17.5\", cy: \"10.5\", r: \".5\", fill: \"currentColor\", key: \"f64h9f\" }],\n [\"circle\", { cx: \"6.5\", cy: \"12.5\", r: \".5\", fill: \"currentColor\", key: \"qy21gx\" }],\n [\"circle\", { cx: \"8.5\", cy: \"7.5\", r: \".5\", fill: \"currentColor\", key: \"fotxhn\" }]\n];\nconst Palette = createLucideIcon(\"palette\", __iconNode);\n\nexport { __iconNode, Palette as default };\n//# sourceMappingURL=palette.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M14 9h1\", key: \"l0svgy\" }],\n [\"path\", { d: \"M19 9h2\", key: \"te2zfg\" }],\n [\"path\", { d: \"M3 9h2\", key: \"1h4ldw\" }],\n [\"path\", { d: \"M9 9h1\", key: \"15jzuz\" }]\n];\nconst PanelTopDashed = createLucideIcon(\"panel-top-dashed\", __iconNode);\n\nexport { __iconNode, PanelTopDashed as default };\n//# sourceMappingURL=panel-top-dashed.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M3 9h18\", key: \"1pudct\" }]\n];\nconst PanelTop = createLucideIcon(\"panel-top\", __iconNode);\n\nexport { __iconNode, PanelTop as default };\n//# sourceMappingURL=panel-top.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M13 4v16\", key: \"8vvj80\" }],\n [\"path\", { d: \"M17 4v16\", key: \"7dpous\" }],\n [\"path\", { d: \"M19 4H9.5a4.5 4.5 0 0 0 0 9H13\", key: \"sh4n9v\" }]\n];\nconst Pilcrow = createLucideIcon(\"pilcrow\", __iconNode);\n\nexport { __iconNode, Pilcrow as default };\n//# sourceMappingURL=pilcrow.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M16 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z\",\n key: \"rib7q0\"\n }\n ],\n [\n \"path\",\n {\n d: \"M5 3a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2 1 1 0 0 1 1 1v1a2 2 0 0 1-2 2 1 1 0 0 0-1 1v2a1 1 0 0 0 1 1 6 6 0 0 0 6-6V5a2 2 0 0 0-2-2z\",\n key: \"1ymkrd\"\n }\n ]\n];\nconst Quote = createLucideIcon(\"quote\", __iconNode);\n\nexport { __iconNode, Quote as default };\n//# sourceMappingURL=quote.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M3 12h18\", key: \"1i2n21\" }]\n];\nconst Rows2 = createLucideIcon(\"rows-2\", __iconNode);\n\nexport { __iconNode, Rows2 as default };\n//# sourceMappingURL=rows-2.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"m6 16 6-12 6 12\", key: \"1b4byz\" }],\n [\"path\", { d: \"M8 12h8\", key: \"1wcyev\" }],\n [\"path\", { d: \"m16 20 2 2 4-4\", key: \"13tcca\" }]\n];\nconst SpellCheck = createLucideIcon(\"spell-check\", __iconNode);\n\nexport { __iconNode, SpellCheck as default };\n//# sourceMappingURL=spell-check.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M16 4H9a3 3 0 0 0-2.83 4\", key: \"43sutm\" }],\n [\"path\", { d: \"M14 12a4 4 0 0 1 0 8H6\", key: \"nlfj13\" }],\n [\"line\", { x1: \"4\", x2: \"20\", y1: \"12\", y2: \"12\", key: \"1e0a9i\" }]\n];\nconst Strikethrough = createLucideIcon(\"strikethrough\", __iconNode);\n\nexport { __iconNode, Strikethrough as default };\n//# sourceMappingURL=strikethrough.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M12 3v18\", key: \"108xh3\" }],\n [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M3 9h18\", key: \"1pudct\" }],\n [\"path\", { d: \"M3 15h18\", key: \"5xshup\" }]\n];\nconst Table = createLucideIcon(\"table\", __iconNode);\n\nexport { __iconNode, Table as default };\n//# sourceMappingURL=table.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\"path\", { d: \"M6 4v6a6 6 0 0 0 12 0V4\", key: \"9kb039\" }],\n [\"line\", { x1: \"4\", x2: \"20\", y1: \"20\", y2: \"20\", key: \"nun2al\" }]\n];\nconst Underline = createLucideIcon(\"underline\", __iconNode);\n\nexport { __iconNode, Underline as default };\n//# sourceMappingURL=underline.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"m21.64 3.64-1.28-1.28a1.21 1.21 0 0 0-1.72 0L2.36 18.64a1.21 1.21 0 0 0 0 1.72l1.28 1.28a1.2 1.2 0 0 0 1.72 0L21.64 5.36a1.2 1.2 0 0 0 0-1.72\",\n key: \"ul74o6\"\n }\n ],\n [\"path\", { d: \"m14 7 3 3\", key: \"1r5n42\" }],\n [\"path\", { d: \"M5 6v4\", key: \"ilb8ba\" }],\n [\"path\", { d: \"M19 14v4\", key: \"blhpug\" }],\n [\"path\", { d: \"M10 2v2\", key: \"7u0qdc\" }],\n [\"path\", { d: \"M7 8H3\", key: \"zfb6yr\" }],\n [\"path\", { d: \"M21 16h-4\", key: \"1cnmox\" }],\n [\"path\", { d: \"M11 3H9\", key: \"1obp7u\" }]\n];\nconst WandSparkles = createLucideIcon(\"wand-sparkles\", __iconNode);\n\nexport { __iconNode, WandSparkles as default };\n//# sourceMappingURL=wand-sparkles.js.map\n","/**\n * @license lucide-react v1.8.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.js';\n\nconst __iconNode = [\n [\n \"path\",\n {\n d: \"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z\",\n key: \"1ngwbx\"\n }\n ]\n];\nconst Wrench = createLucideIcon(\"wrench\", __iconNode);\n\nexport { __iconNode, Wrench as default };\n//# sourceMappingURL=wrench.js.map\n","import type { AgentAdapter } from '../../agent/types';\nimport type { EditorFormat, RichTextEditorHandle } from './rich-text-editor';\n\nexport const richTextEditorAgent: AgentAdapter<RichTextEditorHandle> = {\n id: 'rich-text-editor',\n capabilities: ['edit_inline'],\n state: {\n html: {\n type: 'string',\n descriptionKey: 'ui.agent.richTextEditor.state.html',\n description: 'Sanitised HTML representation of the editor content.',\n read: (handle) => handle.getHTML(),\n },\n text: {\n type: 'string',\n descriptionKey: 'ui.agent.richTextEditor.state.text',\n description: 'Plain-text content of the editor (tags stripped).',\n read: (handle) => handle.getText(),\n },\n markdown: {\n type: 'string',\n descriptionKey: 'ui.agent.richTextEditor.state.markdown',\n description:\n 'Markdown representation of the editor content. The Redactor engine has no native Markdown serialiser, so this is always empty — read `html` instead.',\n read: (handle) => handle.getMarkdown(),\n },\n },\n actions: {\n set_content: {\n // Replaces the whole document — discards whatever the user had typed.\n safety: 'destructive',\n argsType: '{ html: string }',\n argsSchema: {\n type: 'object',\n properties: {\n html: {\n type: 'string',\n description: 'Replacement HTML (sanitised via DOMPurify).',\n },\n },\n required: ['html'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.richTextEditor.actions.setContent',\n description: 'Replace the editor content. Loses unsaved input.',\n invoke: (handle, args: { html: string }) => {\n handle.setContent(args.html);\n },\n },\n insert_at_cursor: {\n // Reversible via the editor's own undo stack — write, not destructive.\n safety: 'write',\n argsType: '{ content: string; asHtml?: boolean }',\n argsSchema: {\n type: 'object',\n properties: {\n content: {\n type: 'string',\n description: 'Content to insert at the caret.',\n },\n asHtml: {\n type: 'boolean',\n description:\n 'Treat content as HTML (sanitised). Pass false for plain text. Defaults to true.',\n },\n },\n required: ['content'],\n },\n descriptionKey: 'ui.agent.richTextEditor.actions.insertAtCursor',\n description:\n 'Insert content at the caret (replacing any selection). HTML is sanitised; pass asHtml:false for plain text. Seam for merge/template variables and AI-generated drafts.',\n examples: [\n {\n args: { content: '{{patient.firstName}}', asHtml: false },\n note: 'Insert a merge variable as plain text.',\n },\n ],\n invoke: (handle, args: { content: string; asHtml?: boolean }) => {\n handle.insertAtCursor(args.content, { asHtml: args.asHtml });\n },\n },\n apply_format: {\n // Reversible via undo — write, not destructive.\n safety: 'write',\n argsType:\n \"{ format: 'bold' | 'italic' | 'strikethrough' | 'bulletedList' | 'numberedList' | 'heading' | 'quote' | 'paragraph' }\",\n argsSchema: {\n type: 'object',\n properties: {\n format: {\n type: 'string',\n enum: [\n 'bold',\n 'italic',\n 'strikethrough',\n 'bulletedList',\n 'numberedList',\n 'heading',\n 'quote',\n 'paragraph',\n ],\n description: 'Block or inline format to toggle/apply.',\n },\n },\n required: ['format'],\n },\n descriptionKey: 'ui.agent.richTextEditor.actions.applyFormat',\n description:\n 'Toggle/apply a block or inline format on the current selection (bold, italic, strikethrough, bulleted/numbered list, heading, quote, paragraph).',\n examples: [{ args: { format: 'bold' }, note: 'Bold the selection.' }],\n invoke: (handle, args: { format: EditorFormat }) => {\n handle.applyFormat(args.format);\n },\n },\n clear: {\n // Empties the document — loses unsaved input.\n safety: 'destructive',\n idempotent: true,\n descriptionKey: 'ui.agent.richTextEditor.actions.clear',\n description: 'Empty the editor. Loses unsaved input.',\n invoke: (handle) => {\n handle.clear();\n },\n },\n focus: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.richTextEditor.actions.focus',\n description: 'Move keyboard focus to the editor surface.',\n invoke: (handle) => {\n handle.focus();\n },\n },\n },\n domHooks: {\n root: { attr: 'data-component', value: 'rich-text-editor' },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n },\n};\n","/* ------------------------------------------------------------------ */\n/* HelpMeWriteOverlay — the \"Help me write\" flow on the non-modal */\n/* EditorOverlay (Gemini / Mac Mail style): a slim docked bar with a */\n/* one-row composer (mic · prompt · Write) → a preview of the draft with */\n/* Discard / Try again / Insert. */\n/* */\n/* The kit owns the UI; the backend call is the consumer's */\n/* `onRequestAiDraft({ prompt, signal })`. When `onDictate` is supplied */\n/* the composer grows a mic that streams transcripts INTO the prompt */\n/* (the same consumer dictation seam the editor FAB uses). The returned */\n/* draft is previewed (sanitised via SafeHtml) and only inserted on */\n/* confirm — sanitisation of the inserted value happens again at the */\n/* editor seam. */\n/* ------------------------------------------------------------------ */\n\nimport {\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { Check, Mic, RotateCcw, Send, Square, X } from 'lucide-react';\n\nimport { IconButton } from '../button';\nimport { Spinner } from '../spinner';\nimport { TextArea } from '../text-area';\nimport { SafeHtml } from '../_shared/safe-html';\nimport { EditorOverlay } from '../editor-overlay';\n\nexport interface HelpMeWriteOverlayProps {\n open: boolean;\n onClose: () => void;\n onRequestAiDraft: (ctx: {\n prompt: string;\n signal: AbortSignal;\n }) => Promise<string>;\n onInsert: (draft: string) => void;\n /** Preview + insert the draft as HTML (default) or plain text. */\n previewAsHtml?: boolean;\n privacyNotice?: ReactNode;\n /**\n * Voice dictation into the prompt. Same seam as the editor's `onDictate`:\n * the consumer runs mic + transcription and pushes text back; the kit appends\n * finals to the prompt. When omitted, the composer shows no mic.\n */\n onDictate?: (ctx: {\n signal: AbortSignal;\n onPartialTranscript: (text: string) => void;\n onFinalTranscript: (text: string) => void;\n }) => Promise<void>;\n}\n\n// Force the recording mic solid-destructive (red). IconButton's base\n// `aria-pressed:bg-muted` (for IconButtonGroup toggles) would otherwise\n// out-specify the intent fill, so the override is marked important.\nconst RECORDING_MIC =\n 'ds:aria-pressed:!bg-[var(--destructive)] ds:aria-pressed:!text-[var(--destructive-foreground)]';\n\n// Pin the action buttons to the input's height (--min-target-size, 44/48px) so\n// the composer's input + mic + send line up exactly. IconButton md is h-10\n// (40px), below the TextArea md min-height, so force the match (important wins\n// over the size variant). Scales with the accessible theme for free.\nconst ACTION_SIZE = 'ds:!size-[var(--min-target-size)]';\n\nconst noticeClass =\n 'ds:text-[length:var(--font-size-sm)] ds:text-[color:var(--muted-foreground)]';\nconst errorClass =\n 'ds:text-[length:var(--font-size-sm)] ds:text-[color:var(--destructive)]';\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:10rem] ds:overflow-y-auto',\n 'ds:text-[length:var(--font-size-sm)] ds:text-[color:var(--foreground)]',\n].join(' ');\n\n// Join a base string with appended dictation text, inserting a single space\n// only when the base doesn't already end in whitespace.\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\nexport function HelpMeWriteOverlay({\n open,\n onClose,\n onRequestAiDraft,\n onInsert,\n previewAsHtml = true,\n privacyNotice,\n onDictate,\n}: HelpMeWriteOverlayProps): React.JSX.Element {\n const { t } = useTranslation();\n const promptId = useId();\n const errorId = useId();\n const [prompt, setPrompt] = useState('');\n const [loading, setLoading] = useState(false);\n const [errored, setErrored] = useState(false);\n const [draft, setDraft] = useState<string | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n\n /* ---- In-prompt voice dictation (consumer runs mic + STT) ---- */\n const [isDictating, setIsDictating] = useState(false);\n const [interim, setInterim] = useState('');\n // Drives the visually-hidden live region: announces the listening status on\n // start and each committed phrase as it lands. The interim text shows in the\n // read-only field, but SR users can't perceive a read-only value change, so\n // the polite region gives them the same feedback.\n const [dictationAnnouncement, setDictationAnnouncement] = useState('');\n const dictateAbortRef = useRef<AbortController | null>(null);\n\n const stopDictation = useCallback(() => {\n dictateAbortRef.current?.abort();\n }, []);\n\n const startDictation = useCallback(() => {\n if (!onDictate) return;\n const controller = new AbortController();\n dictateAbortRef.current = controller;\n setIsDictating(true);\n setInterim('');\n setDictationAnnouncement(t('editor.ai.listening'));\n onDictate({\n signal: controller.signal,\n onPartialTranscript: (text: string): void => {\n if (controller.signal.aborted) return;\n setInterim(text);\n },\n onFinalTranscript: (text: string): void => {\n if (controller.signal.aborted) return;\n const trimmed = text.trim();\n setInterim('');\n if (trimmed) {\n setPrompt((p) => joinWith(p, trimmed));\n setDictationAnnouncement(trimmed);\n }\n },\n })\n .catch(() => {\n /* dictation errors are non-fatal here — the user can type instead */\n })\n .finally(() => {\n setInterim('');\n if (dictateAbortRef.current === controller) {\n dictateAbortRef.current = null;\n setIsDictating(false);\n setDictationAnnouncement('');\n }\n });\n }, [onDictate, t]);\n\n const toggleDictation = useCallback(() => {\n if (isDictating) stopDictation();\n else startDictation();\n }, [isDictating, startDictation, stopDictation]);\n\n // Fresh state each time it opens; abort any in-flight request/dictation on close.\n useEffect(() => {\n if (open) {\n setPrompt('');\n setLoading(false);\n setErrored(false);\n setDraft(null);\n setInterim('');\n setDictationAnnouncement('');\n } else {\n abortRef.current?.abort();\n abortRef.current = null;\n dictateAbortRef.current?.abort();\n }\n }, [open]);\n useEffect(\n () => () => {\n abortRef.current?.abort();\n dictateAbortRef.current?.abort();\n },\n [],\n );\n\n const generate = useCallback(() => {\n const trimmed = prompt.trim();\n if (!trimmed || loading) return;\n stopDictation();\n abortRef.current?.abort();\n const controller = new AbortController();\n abortRef.current = controller;\n setErrored(false);\n setLoading(true);\n onRequestAiDraft({ prompt: trimmed, signal: controller.signal })\n .then((result) => {\n if (controller.signal.aborted) return;\n setDraft(result);\n setLoading(false);\n })\n .catch((err: unknown) => {\n if (\n controller.signal.aborted ||\n (err &&\n typeof err === 'object' &&\n 'name' in err &&\n (err as { name?: string }).name === 'AbortError')\n ) {\n return;\n }\n setErrored(true);\n setLoading(false);\n });\n }, [prompt, loading, onRequestAiDraft, stopDictation]);\n\n const insert = useCallback(() => {\n if (draft == null) return;\n onInsert(draft);\n onClose();\n }, [draft, onInsert, onClose]);\n\n const hasDraft = draft != null;\n // While dictating, show committed prompt + live interim; the field is\n // read-only so the streamed text isn't fought over by onChange.\n const fieldValue = isDictating ? joinWith(prompt, interim) : prompt;\n\n return (\n <EditorOverlay\n open={open}\n onClose={onClose}\n ariaLabel={t('editor.ai.dialogTitle')}\n >\n {hasDraft ? (\n <div className=\"ds:flex ds:items-end ds:gap-[var(--spacing-sm)]\">\n <IconButton\n size=\"md\"\n intent=\"outline\"\n className={ACTION_SIZE}\n icon={<X />}\n aria-label={t('common.close')}\n onClick={onClose}\n />\n <div className=\"ds:min-w-0 ds:flex-1\">\n {previewAsHtml ? (\n <SafeHtml\n html={draft as string}\n profile=\"rich-text\"\n className={previewClass}\n tabIndex={0}\n aria-label={t('editor.ai.dialogTitle')}\n />\n ) : (\n // Focusable so a keyboard user can scroll a long draft preview\n // (mirrors the SafeHtml preview branch above). The lint rule's\n // tabIndex allowlist doesn't cover a scrollable, non-interactive\n // text region.\n // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex\n <p className={previewClass} tabIndex={0}>\n {draft}\n </p>\n )}\n </div>\n <IconButton\n size=\"md\"\n intent=\"outline\"\n className={`${ACTION_SIZE} ds:rounded-full`}\n icon={<RotateCcw />}\n aria-label={t('editor.ai.retry')}\n onClick={() => setDraft(null)}\n />\n <IconButton\n size=\"md\"\n intent=\"primary\"\n className={`${ACTION_SIZE} ds:bg-[image:var(--gradient-brand)] ds:rounded-full`}\n icon={<Check />}\n aria-label={t('common.confirm')}\n onClick={insert}\n />\n </div>\n ) : (\n <>\n <div className=\"ds:flex ds:items-end ds:gap-[var(--spacing-sm)]\">\n <IconButton\n size=\"md\"\n intent=\"outline\"\n className={ACTION_SIZE}\n icon={<X />}\n aria-label={t('common.close')}\n onClick={onClose}\n />\n <div className=\"ds:min-w-0 ds:flex-1\">\n <TextArea\n id={promptId}\n size=\"md\"\n // Centre a single line within the min-height; when it grows to\n // multiple rows autoResize removes the slack so text fills from\n // the top as usual.\n className=\"ds:content-center\"\n value={fieldValue}\n onChange={(event) => setPrompt(event.target.value)}\n placeholder={t('editor.ai.promptPlaceholder')}\n aria-label={t('editor.ai.promptLabel')}\n autoResize\n minRows={1}\n maxRows={3}\n readOnly={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('editor.ai.dictateStop')\n : t('editor.ai.dictateStart')\n }\n onClick={toggleDictation}\n />\n ) : null}\n <IconButton\n size=\"md\"\n intent=\"primary\"\n icon={loading ? <Spinner size=\"sm\" variant=\"pulse\" /> : <Send />}\n className={`${ACTION_SIZE} ds:bg-[image:var(--gradient-brand)] ds:rounded-full`}\n disabled={loading || !prompt.trim()}\n aria-busy={loading || undefined}\n aria-label={t('editor.ai.generate')}\n onClick={generate}\n />\n </div>\n {onDictate ? (\n <p className=\"ds:sr-only\" role=\"status\" aria-live=\"polite\">\n {dictationAnnouncement}\n </p>\n ) : null}\n {errored ? (\n <p id={errorId} role=\"alert\" className={errorClass}>\n {t('editor.ai.error')}\n </p>\n ) : privacyNotice ? (\n <p className={noticeClass}>{privacyNotice}</p>\n ) : null}\n </>\n )}\n </EditorOverlay>\n );\n}\n","/* ------------------------------------------------------------------ */\n/* EditorToolbar — the kit's OWN toolbar for RichTextEditor. */\n/* */\n/* Redactor renders with `toolbar: false` (no native toolbar); this DS */\n/* toolbar drives the editor through Redactor's command API via `run` */\n/* and, for surfaces that would otherwise use Redactor's own modals */\n/* (link, image), through DS Dialogs + the `insertHtml` seam so EVERY */\n/* interactive surface is a kit component. Colour uses the DS */\n/* ColorPicker; the style menu is a labelled menu button; table offers */\n/* a size-grid insert + contextual row/column/header ops. */\n/* ------------------------------------------------------------------ */\n\nimport {\n Fragment,\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type ReactNode,\n type RefObject,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport {\n BetweenHorizontalEnd,\n BetweenHorizontalStart,\n BetweenVerticalEnd,\n BetweenVerticalStart,\n Bold,\n ChevronDown,\n Columns2,\n Heading2,\n Heading3,\n Highlighter,\n Image as ImageIcon,\n Italic,\n Link as LinkIcon,\n List,\n ListOrdered,\n PaintBucket,\n PaintRoller,\n PanelTop,\n PanelTopDashed,\n Palette,\n Pilcrow,\n Quote,\n Rows2,\n Strikethrough,\n Table as TableIcon,\n Trash2,\n Underline,\n Wrench,\n} from 'lucide-react';\nimport { cva } from 'class-variance-authority';\n\nimport { Button, IconButton } from '../button';\nimport { TooltipProvider } from '../tooltip';\nimport { Popover } from '../popover';\nimport { DropdownMenu } from '../dropdown-menu';\nimport { Dialog } from '../dialog';\nimport { ColorPicker } from '../color-picker';\nimport { TextInput } from '../text-input';\nimport { Checkbox } from '../checkbox';\nimport { FileUpload } from '../file-upload';\n\nexport type EditorToolbarPreset = 'minimal' | 'standard' | 'full';\n\nexport interface EditorToolbarProps {\n /** Dispatch a Redactor command (and refresh active state). */\n run: (command: string, ...args: unknown[]) => void;\n /** Active formats at the caret — toggle buttons render pressed. */\n active: ReadonlySet<string>;\n preset: EditorToolbarPreset;\n /** Insert sanitised HTML at the caret (link / image / table). */\n insertHtml: (html: string) => void;\n /** Insert a table — list-aware (drops it after a list, never inside an <li>). */\n insertTable: (html: string) => void;\n /** Save the editor selection before a DS popover/dialog takes focus. */\n saveSelection: () => void;\n /** Restore the saved selection before applying. */\n restoreSelection: () => void;\n /** Current selected text — prefills the link dialog's text field. */\n getSelectedText: () => string;\n /** Upload an image file and resolve its URL (image dialog's upload area). */\n uploadImage?: (file: File, signal?: AbortSignal) => Promise<string>;\n /** Show the text-colour control. */\n enableColor?: boolean;\n /** Show the image control (consumer set an image-upload URL). */\n enableImage?: boolean;\n /** Show the table control (consumer loaded the table plugin). */\n enableTable?: boolean;\n /**\n * Show an \"Editor extensions\" tools affordance (marketplace tools), placed\n * inline at the end of the toolbar. Currently a visual placeholder — not\n * wired to a menu.\n */\n showExtensions?: boolean;\n}\n\n/** i18n key + English fallback (for keys not yet in every locale). */\ntype L = [string, string];\n\ninterface ToolbarItem {\n id: string;\n icon: ReactNode;\n label: L;\n command: [string, ...unknown[]];\n /** When set, the button is a toggle and presses when `active` has this key. */\n toggle?: string;\n}\n\nconst ITEMS: Record<string, ToolbarItem> = {\n bold: {\n id: 'bold',\n icon: <Bold />,\n label: ['editor.bold', 'Bold'],\n command: ['module.inline.format', { tag: 'b' }],\n toggle: 'bold',\n },\n italic: {\n id: 'italic',\n icon: <Italic />,\n label: ['editor.italic', 'Italic'],\n command: ['module.inline.format', { tag: 'i' }],\n toggle: 'italic',\n },\n underline: {\n id: 'underline',\n icon: <Underline />,\n label: ['editor.underline', 'Underline'],\n command: ['module.inline.format', { tag: 'u' }],\n toggle: 'underline',\n },\n strike: {\n id: 'strike',\n icon: <Strikethrough />,\n label: ['editor.strike', 'Strikethrough'],\n command: ['module.inline.format', { tag: 'del' }],\n toggle: 'strike',\n },\n ul: {\n id: 'ul',\n icon: <List />,\n label: ['editor.list.bullet', 'Bulleted list'],\n command: ['module.list.toggle', 'ul'],\n toggle: 'ul',\n },\n ol: {\n id: 'ol',\n icon: <ListOrdered />,\n label: ['editor.list.ordered', 'Numbered list'],\n command: ['module.list.toggle', 'ol'],\n toggle: 'ol',\n },\n};\n\n// Block-format options. `id` matches the active token emitted by the editor\n// (paragraph / h2 / h3 / quote) so the labelled button shows the active style.\nconst FORMAT_OPTIONS: { id: string; tag: string; icon: ReactNode; label: L }[] =\n [\n {\n id: 'paragraph',\n tag: 'p',\n icon: <Pilcrow />,\n label: ['editor.paragraph', 'Paragraph'],\n },\n {\n id: 'h2',\n tag: 'h2',\n icon: <Heading2 />,\n label: ['editor.heading2', 'Heading 2'],\n },\n {\n id: 'h3',\n tag: 'h3',\n icon: <Heading3 />,\n label: ['editor.heading3', 'Heading 3'],\n },\n {\n id: 'quote',\n tag: 'blockquote',\n icon: <Quote />,\n label: ['editor.quote', 'Quote'],\n },\n ];\n\nconst PRESETS: Record<EditorToolbarPreset, string[]> = {\n minimal: ['bold', 'italic', 'underline', 'link'],\n standard: [\n 'format',\n 'bold',\n 'italic',\n 'underline',\n 'strike',\n 'ul',\n 'ol',\n 'link',\n ],\n full: ['format', 'bold', 'italic', 'underline', 'strike', 'ul', 'ol', 'link'],\n};\n\n// Table ops mirror EXACTLY the commands platform's Redactor table plugin\n// exposes (verified against platform/web/static/redactor/_plugins/table) — it\n// has no merge/split/align commands, so neither do we.\nconst TABLE_OPS: { id: string; command: string; icon: ReactNode; label: L }[] =\n [\n {\n id: 'rowAbove',\n command: 'plugin.table.addRowAbove',\n icon: <BetweenHorizontalStart />,\n label: ['editor.table.rowAbove', 'Add row above'],\n },\n {\n id: 'rowBelow',\n command: 'plugin.table.addRowBelow',\n icon: <BetweenHorizontalEnd />,\n label: ['editor.table.rowBelow', 'Add row below'],\n },\n {\n id: 'colLeft',\n command: 'plugin.table.addColumnLeft',\n icon: <BetweenVerticalStart />,\n label: ['editor.table.columnLeft', 'Add column left'],\n },\n {\n id: 'colRight',\n command: 'plugin.table.addColumnRight',\n icon: <BetweenVerticalEnd />,\n label: ['editor.table.columnRight', 'Add column right'],\n },\n {\n id: 'addHead',\n command: 'plugin.table.addHead',\n icon: <PanelTop />,\n label: ['editor.table.addHeader', 'Add header row'],\n },\n {\n id: 'deleteHead',\n command: 'plugin.table.deleteHead',\n icon: <PanelTopDashed />,\n label: ['editor.table.deleteHeader', 'Remove header row'],\n },\n {\n id: 'deleteRow',\n command: 'plugin.table.deleteRow',\n icon: <Rows2 />,\n label: ['editor.table.deleteRow', 'Delete row'],\n },\n {\n id: 'deleteColumn',\n command: 'plugin.table.deleteColumn',\n icon: <Columns2 />,\n label: ['editor.table.deleteColumn', 'Delete column'],\n },\n {\n id: 'deleteTable',\n command: 'plugin.table.deleteTable',\n icon: <Trash2 />,\n label: ['editor.table.deleteTable', 'Delete table'],\n },\n ];\n\nconst TABLE_GRID = 6; // max rows/cols offered by the size picker\n\nconst toolbarClass = cva(\n [\n 'ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)]',\n 'ds:rounded-[var(--radius-md)] ds:border ds:border-[color:var(--border)]',\n 'ds:bg-[var(--background)] ds:p-[var(--spacing-xs)]',\n 'ds:shadow-[var(--shadow-md)]',\n ].join(' '),\n);\n\nconst dividerClass =\n 'ds:self-stretch ds:[inline-size:var(--border-width-sm)] ds:bg-[var(--border)] ds:[margin-inline:var(--spacing-2xs)]';\n\nconst fieldLabelClass =\n 'ds:text-[length:var(--font-size-sm)] ds:font-medium ds:text-[color:var(--foreground)]';\n\n// Escape a string for safe interpolation; insertHtml re-sanitises via DOMPurify,\n// but encoding here keeps the constructed markup well-formed first.\nfunction esc(value: string): string {\n return value\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n\n/* ------------------------------------------------------------------ */\n/* Style — labelled menu button */\n/* ------------------------------------------------------------------ */\n\nfunction StyleMenu({\n run,\n active,\n onTriggerDown,\n}: {\n run: EditorToolbarProps['run'];\n active: ReadonlySet<string>;\n onTriggerDown: (event: { preventDefault: () => void }) => void;\n}): React.JSX.Element {\n const { t } = useTranslation();\n const current =\n FORMAT_OPTIONS.find((o) => active.has(o.id)) ?? FORMAT_OPTIONS[0];\n return (\n <DropdownMenu.Root>\n <DropdownMenu.Trigger asChild>\n <Button\n size=\"sm\"\n intent=\"ghost\"\n startIcon={current.icon}\n endIcon={<ChevronDown />}\n aria-label={t('editor.format', 'Paragraph style')}\n onMouseDown={onTriggerDown}\n >\n {t(current.label[0], current.label[1])}\n </Button>\n </DropdownMenu.Trigger>\n <DropdownMenu.Content align=\"start\">\n {FORMAT_OPTIONS.map((opt) => (\n <DropdownMenu.Item\n key={opt.id}\n startIcon={opt.icon}\n onSelect={() => run('module.block.format', { tag: opt.tag })}\n >\n {t(opt.label[0], opt.label[1])}\n </DropdownMenu.Item>\n ))}\n </DropdownMenu.Content>\n </DropdownMenu.Root>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Link — DS Dialog */\n/* ------------------------------------------------------------------ */\n\nfunction LinkDialog({\n insertHtml,\n saveSelection,\n restoreSelection,\n getSelectedText,\n}: Pick<\n EditorToolbarProps,\n 'insertHtml' | 'saveSelection' | 'restoreSelection' | 'getSelectedText'\n>): React.JSX.Element {\n const { t } = useTranslation();\n const [open, setOpen] = useState(false);\n const [url, setUrl] = useState('');\n const [text, setText] = useState('');\n const [newTab, setNewTab] = useState(false);\n const urlId = useId();\n const textId = useId();\n\n const reset = (): void => {\n setUrl('');\n setText('');\n setNewTab(false);\n };\n\n const handleInsert = (): void => {\n const href = url.trim();\n if (!href) return;\n const label = text.trim() || href;\n const tab = newTab ? ' target=\"_blank\" rel=\"noopener noreferrer\"' : '';\n const html = `<a href=\"${esc(href)}\"${tab}>${esc(label)}</a>`;\n setOpen(false);\n reset();\n window.requestAnimationFrame(() => {\n restoreSelection();\n insertHtml(html);\n });\n };\n\n return (\n <Dialog.Root open={open} onOpenChange={setOpen}>\n <Dialog.Trigger asChild>\n <IconButton\n size=\"sm\"\n intent=\"ghost\"\n icon={<LinkIcon />}\n aria-label={t('editor.link.insert', 'Insert link')}\n // Save the selection synchronously (before focus leaves the editor);\n // no preventDefault — the modal Dialog needs normal focus handling.\n onMouseDown={() => {\n saveSelection();\n setText(getSelectedText());\n }}\n />\n </Dialog.Trigger>\n <Dialog.Content>\n <Dialog.Header>\n <Dialog.Title>{t('editor.link.insert', 'Insert link')}</Dialog.Title>\n </Dialog.Header>\n <Dialog.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <label htmlFor={urlId} className={fieldLabelClass}>\n {t('editor.link.url', 'URL')}\n </label>\n <TextInput\n id={urlId}\n type=\"url\"\n value={url}\n onChange={(event) => setUrl(event.target.value)}\n placeholder=\"https://…\"\n />\n </div>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <label htmlFor={textId} className={fieldLabelClass}>\n {t('editor.link.text', 'Text to display')}\n </label>\n <TextInput\n id={textId}\n value={text}\n onChange={(event) => setText(event.target.value)}\n placeholder={t('editor.link.textPlaceholder', 'Link text')}\n />\n </div>\n <Checkbox\n checked={newTab}\n onCheckedChange={(checked) => setNewTab(checked === true)}\n label={t('editor.link.newTab', 'Open in new tab')}\n />\n </Dialog.Body>\n <Dialog.Footer>\n <Dialog.Close asChild>\n <Button intent=\"secondary\">{t('common.cancel')}</Button>\n </Dialog.Close>\n <Button onClick={handleInsert} disabled={!url.trim()}>\n {t('editor.link.insertAction', 'Insert')}\n </Button>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Image — DS Dialog */\n/* ------------------------------------------------------------------ */\n\nfunction ImageDialog({\n insertHtml,\n saveSelection,\n restoreSelection,\n uploadImage,\n}: Pick<\n EditorToolbarProps,\n 'insertHtml' | 'saveSelection' | 'restoreSelection' | 'uploadImage'\n>): React.JSX.Element {\n const { t } = useTranslation();\n const [open, setOpen] = useState(false);\n const [src, setSrc] = useState('');\n const [alt, setAlt] = useState('');\n const srcId = useId();\n const altId = useId();\n\n const insertImage = (url: string, altText: string): void => {\n const html = `<img src=\"${esc(url)}\" alt=\"${esc(altText)}\" loading=\"lazy\">`;\n setOpen(false);\n setSrc('');\n setAlt('');\n window.requestAnimationFrame(() => {\n restoreSelection();\n insertHtml(html);\n });\n };\n\n const handleInsert = (): void => {\n const url = src.trim();\n if (url) insertImage(url, alt.trim());\n };\n\n return (\n <Dialog.Root open={open} onOpenChange={setOpen}>\n <Dialog.Trigger asChild>\n <IconButton\n size=\"sm\"\n intent=\"ghost\"\n icon={<ImageIcon />}\n aria-label={t('editor.image.insert', 'Insert image')}\n // No preventDefault — the modal Dialog needs normal focus handling.\n onMouseDown={() => saveSelection()}\n />\n </Dialog.Trigger>\n <Dialog.Content>\n <Dialog.Header>\n <Dialog.Title>\n {t('editor.image.insert', 'Insert image')}\n </Dialog.Title>\n </Dialog.Header>\n <Dialog.Body className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-md)]\">\n {uploadImage ? (\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <span className={fieldLabelClass}>\n {t('editor.image.upload', 'Upload')}\n </span>\n <FileUpload\n variant=\"dropzone\"\n accept={{\n 'image/*': ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.svg'],\n }}\n maxFiles={1}\n onUpload={async (file, { signal }) => {\n const url = await uploadImage(file, signal);\n insertImage(url, file.name);\n }}\n />\n <span className=\"ds:text-[length:var(--font-size-sm)] ds:text-[color:var(--muted-foreground)]\">\n {t('editor.image.orUrl', 'Or paste an image URL')}\n </span>\n </div>\n ) : null}\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <label htmlFor={srcId} className={fieldLabelClass}>\n {t('editor.image.url', 'Image URL')}\n </label>\n <TextInput\n id={srcId}\n type=\"url\"\n value={src}\n onChange={(event) => setSrc(event.target.value)}\n placeholder=\"https://…\"\n />\n </div>\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <label htmlFor={altId} className={fieldLabelClass}>\n {t('editor.image.alt', 'Alt text')}\n </label>\n <TextInput\n id={altId}\n value={alt}\n onChange={(event) => setAlt(event.target.value)}\n placeholder={t(\n 'editor.image.altPlaceholder',\n 'Describe the image',\n )}\n />\n </div>\n </Dialog.Body>\n <Dialog.Footer>\n <Dialog.Close asChild>\n <Button intent=\"secondary\">{t('common.cancel')}</Button>\n </Dialog.Close>\n <Button onClick={handleInsert} disabled={!src.trim()}>\n {t('editor.image.insertAction', 'Insert')}\n </Button>\n </Dialog.Footer>\n </Dialog.Content>\n </Dialog.Root>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Colour — DS ColorPicker */\n/* ------------------------------------------------------------------ */\n\nfunction ColourControl({\n run,\n saveSelection,\n restoreSelection,\n}: Pick<\n EditorToolbarProps,\n 'run' | 'saveSelection' | 'restoreSelection'\n>): React.JSX.Element {\n const { t } = useTranslation();\n // Colour-picker seed value: a text-colour picker emits arbitrary, user-chosen\n // colours, so a literal hex default (rather than a brand token) is correct.\n // eslint-disable-next-line no-restricted-syntax\n const [colour, setColour] = useState('#1f2a5c');\n\n // Apply on pick — a colour control shouldn't need a separate \"Apply\" step.\n // The picker is compact (swatch-only), so onChange fires once per swatch\n // click; mirror Redactor's fontcolor plugin (toggle <span> with a colour\n // style — `type: 'toggle'` is required for the format to apply).\n const applyColour = (hex: string): void => {\n setColour(hex);\n restoreSelection();\n run('module.inline.format', {\n tag: 'span',\n style: { color: hex },\n type: 'toggle',\n });\n };\n const removeColour = (): void => {\n restoreSelection();\n run('module.inline.remove', { style: 'color' });\n };\n\n return (\n <Popover onOpenChange={(o) => o && saveSelection()}>\n <Popover.Trigger asChild>\n <IconButton\n size=\"sm\"\n intent=\"ghost\"\n icon={<Palette />}\n aria-label={t('editor.textColor', 'Text colour')}\n onMouseDown={(event) => {\n event.preventDefault();\n saveSelection();\n }}\n />\n </Popover.Trigger>\n <Popover.Content side=\"bottom\" align=\"start\">\n <Popover.Heading>\n {t('editor.textColor', 'Text colour')}\n </Popover.Heading>\n <div className=\"ds:pt-[var(--spacing-sm)]\">\n <ColorPicker\n variant=\"inline\"\n size=\"sm\"\n value={colour}\n onChange={applyColour}\n />\n </div>\n <div className=\"ds:mt-[var(--spacing-sm)] ds:flex ds:items-center ds:justify-end\">\n <Button size=\"sm\" intent=\"secondary\" onClick={removeColour}>\n {t('editor.color.remove', 'Remove colour')}\n </Button>\n </div>\n </Popover.Content>\n </Popover>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Highlight — DS ColorPicker applied as a text background */\n/* ------------------------------------------------------------------ */\n\nfunction HighlightControl({\n run,\n saveSelection,\n restoreSelection,\n}: Pick<\n EditorToolbarProps,\n 'run' | 'saveSelection' | 'restoreSelection'\n>): React.JSX.Element {\n const { t } = useTranslation();\n // Highlight seed value: a highlight picker emits arbitrary, user-chosen\n // colours, so a literal hex default (rather than a brand token) is correct.\n // eslint-disable-next-line no-restricted-syntax\n const [colour, setColour] = useState('#fff3a3');\n\n // Apply on pick. Highlight is the same inline <span> as text colour, but the\n // style key is `background-color` (mirrors Redactor's fontcolor \"Highlight\").\n const applyHighlight = (hex: string): void => {\n setColour(hex);\n restoreSelection();\n run('module.inline.format', {\n tag: 'span',\n style: { 'background-color': hex },\n type: 'toggle',\n });\n };\n const removeHighlight = (): void => {\n restoreSelection();\n run('module.inline.remove', { style: 'background-color' });\n };\n\n return (\n <Popover onOpenChange={(o) => o && saveSelection()}>\n <Popover.Trigger asChild>\n <IconButton\n size=\"sm\"\n intent=\"ghost\"\n icon={<Highlighter />}\n aria-label={t('editor.highlightColor', 'Highlight')}\n onMouseDown={(event) => {\n event.preventDefault();\n saveSelection();\n }}\n />\n </Popover.Trigger>\n <Popover.Content side=\"bottom\" align=\"start\">\n <Popover.Heading>\n {t('editor.highlightColor', 'Highlight')}\n </Popover.Heading>\n <div className=\"ds:pt-[var(--spacing-sm)]\">\n <ColorPicker\n variant=\"inline\"\n size=\"sm\"\n value={colour}\n onChange={applyHighlight}\n />\n </div>\n <div className=\"ds:mt-[var(--spacing-sm)] ds:flex ds:items-center ds:justify-end\">\n <Button size=\"sm\" intent=\"secondary\" onClick={removeHighlight}>\n {t('editor.highlight.remove', 'Remove highlight')}\n </Button>\n </div>\n </Popover.Content>\n </Popover>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Table — size-grid insert + contextual ops */\n/* ------------------------------------------------------------------ */\n\nfunction buildTable(rows: number, cols: number): string {\n const cells = Array.from({ length: cols }, () => '<td><br></td>').join('');\n const body = Array.from({ length: rows }, () => `<tr>${cells}</tr>`).join('');\n return `<table><tbody>${body}</tbody></table>`;\n}\n\nfunction TableControl({\n run,\n insertTable,\n active,\n}: Pick<\n EditorToolbarProps,\n 'run' | 'insertTable' | 'active'\n>): React.JSX.Element {\n const { t } = useTranslation();\n const [hover, setHover] = useState<{ r: number; c: number }>({ r: 0, c: 0 });\n const inTable = active.has('table');\n\n return (\n <Popover onOpenChange={(o) => !o && setHover({ r: 0, c: 0 })}>\n <Popover.Trigger asChild>\n <IconButton\n size=\"sm\"\n intent=\"ghost\"\n icon={<TableIcon />}\n aria-label={t('editor.table.insert', 'Insert table')}\n onMouseDown={(event) => event.preventDefault()}\n />\n </Popover.Trigger>\n <Popover.Content side=\"bottom\" align=\"start\">\n {inTable ? (\n // Caret is already inside a table — offer the manage ops only, never\n // a nested-table insert (mirrors Redactor's native dropdown, which\n // disables \"insert table\" while the caret is in a table).\n <div className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-2xs)]\">\n {TABLE_OPS.map((op) => (\n <button\n key={op.id}\n type=\"button\"\n onClick={() => run(op.command)}\n className=\"ds:flex ds:items-center ds:gap-[var(--spacing-sm)] ds:rounded-[var(--radius-sm)] ds:px-[var(--spacing-sm)] ds:py-[var(--spacing-2xs)] ds:text-start ds:text-[length:var(--font-size-sm)] ds:text-[color:var(--foreground)] ds:hover:bg-[var(--muted)]\"\n >\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-flex ds:size-4 ds:shrink-0 ds:items-center ds:justify-center ds:text-[color:var(--muted-foreground)]\"\n >\n {op.icon}\n </span>\n {t(op.label[0], op.label[1])}\n </button>\n ))}\n </div>\n ) : (\n <>\n <Popover.Heading>\n {t('editor.table.insert', 'Insert table')}\n </Popover.Heading>\n <div\n role=\"group\"\n aria-label={t('editor.table.sizePicker', 'Table size')}\n className=\"ds:mt-[var(--spacing-sm)] ds:grid ds:w-fit ds:grid-cols-6 ds:gap-[var(--spacing-2xs)]\"\n onMouseLeave={() => setHover({ r: 0, c: 0 })}\n >\n {Array.from({ length: TABLE_GRID * TABLE_GRID }, (_, i) => {\n const r = Math.floor(i / TABLE_GRID) + 1;\n const c = (i % TABLE_GRID) + 1;\n const on = r <= hover.r && c <= hover.c;\n return (\n <button\n key={i}\n type=\"button\"\n aria-label={t('editor.table.sizeCell', '{{r}}×{{c}}', {\n r,\n c,\n })}\n onMouseEnter={() => setHover({ r, c })}\n onClick={() => insertTable(buildTable(r, c))}\n className={`ds:size-5 ds:rounded-[var(--radius-sm)] ds:border ds:border-[color:var(--border)] ${\n on ? 'ds:bg-[var(--primary)]' : 'ds:bg-[var(--muted)]'\n }`}\n />\n );\n })}\n </div>\n <p className=\"ds:mt-[var(--spacing-xs)] ds:text-[length:var(--font-size-sm)] ds:text-[color:var(--muted-foreground)]\">\n {hover.r > 0\n ? t('editor.table.sizeCell', '{{r}}×{{c}}', {\n r: hover.r,\n c: hover.c,\n })\n : t('editor.table.sizeHint', 'Pick a size')}\n </p>\n </>\n )}\n </Popover.Content>\n </Popover>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Floating in-cell table toolbar */\n/* */\n/* Appears anchored above the table whenever the caret is inside one, */\n/* so the common row/column ops are one click away without opening the */\n/* toolbar menu. Dispatches the same `plugin.table.*` commands via the */\n/* shared `run` seam; the toolbar TableControl menu stays as the place */\n/* for inserting tables and header ops. */\n/* ------------------------------------------------------------------ */\n\nconst TABLE_OP_BY_ID: Record<string, (typeof TABLE_OPS)[number]> =\n Object.fromEntries(TABLE_OPS.map((op) => [op.id, op]));\n\nconst tableFloatClass = [\n 'ds:absolute ds:z-20 ds:flex ds:items-center ds:gap-[var(--spacing-2xs)]',\n 'ds:[inset-block-start:var(--rte-tt-top)] ds:[inset-inline-start:var(--rte-tt-start)]',\n 'ds:rounded-[var(--radius-md)] ds:border ds:border-[color:var(--border)]',\n 'ds:bg-[var(--popover)] ds:p-[var(--spacing-2xs)] ds:shadow-[var(--shadow-lg)]',\n].join(' ');\n\nexport interface TableFloatingToolbarProps {\n active: ReadonlySet<string>;\n run: EditorToolbarProps['run'];\n /** Positioned container the bar is absolutely placed within. */\n areaRef: RefObject<HTMLDivElement | null>;\n /** The <table> the caret is currently inside (relative to this editor). */\n getActiveTableEl: () => HTMLElement | null;\n /** Show the cell/row background-colour controls (fontcolor plugin loaded). */\n enableColor?: boolean;\n /** Snapshot the current cell before a colour popover takes focus. */\n saveTableCell: () => void;\n /** Set/clear a background colour on the current cell or its row. */\n applyTableBackground: (scope: 'cell' | 'row', colour: string | null) => void;\n}\n\n// Colour-control seed: an arbitrary user-chosen background, so a literal hex\n// default is correct (mirrors ColourControl / HighlightControl).\n// eslint-disable-next-line no-restricted-syntax\nconst TABLE_BG_SEED = '#fde68a';\n\n// One cell/row background-colour control: an icon trigger → compact ColorPicker\n// (applies on pick) + a clear action. The cell is captured on open (saveTableCell)\n// because the popover takes focus; `onOpenChange` lets the bar stay mounted.\nfunction TableBgColourControl({\n scope,\n icon,\n label,\n onOpenChange,\n saveTableCell,\n applyTableBackground,\n}: {\n scope: 'cell' | 'row';\n icon: ReactNode;\n label: string;\n onOpenChange: (open: boolean) => void;\n saveTableCell: () => void;\n applyTableBackground: (scope: 'cell' | 'row', colour: string | null) => void;\n}): React.JSX.Element {\n const { t } = useTranslation();\n const [colour, setColour] = useState(TABLE_BG_SEED);\n return (\n <Popover\n onOpenChange={(open) => {\n onOpenChange(open);\n if (open) saveTableCell();\n }}\n >\n <Popover.Trigger asChild>\n <IconButton\n size=\"sm\"\n intent=\"ghost\"\n icon={icon}\n tooltip={label}\n onMouseDown={(event) => event.preventDefault()}\n />\n </Popover.Trigger>\n <Popover.Content side=\"bottom\" align=\"center\">\n <ColorPicker\n variant=\"inline\"\n size=\"sm\"\n value={colour}\n onChange={(hex) => {\n setColour(hex);\n applyTableBackground(scope, hex);\n }}\n />\n <Button\n size=\"sm\"\n intent=\"ghost\"\n className=\"ds:mt-[var(--spacing-xs)] ds:w-full\"\n onClick={() => applyTableBackground(scope, null)}\n >\n {t('editor.table.clearColor', 'Clear colour')}\n </Button>\n </Popover.Content>\n </Popover>\n );\n}\n\nexport function TableFloatingToolbar({\n active,\n run,\n areaRef,\n getActiveTableEl,\n enableColor = false,\n saveTableCell,\n applyTableBackground,\n}: TableFloatingToolbarProps): React.JSX.Element | null {\n const { t } = useTranslation();\n const inTable = active.has('table');\n const [pos, setPos] = useState<{\n top: number;\n start: number;\n rtl: boolean;\n } | null>(null);\n\n // Keep the bar mounted while a colour popover is open: opening it can move\n // focus out of the editor, dropping `table` from `active`, which would\n // otherwise unmount the bar (and close the popover) mid-interaction.\n const colourOpenCount = useRef(0);\n const [colourOpen, setColourOpen] = useState(false);\n const handleColourOpenChange = useCallback((open: boolean): void => {\n colourOpenCount.current = Math.max(\n 0,\n colourOpenCount.current + (open ? 1 : -1),\n );\n setColourOpen(colourOpenCount.current > 0);\n }, []);\n\n useEffect(() => {\n // Freeze tracking while a colour popover is open (the caret may have left\n // the editor); resume when it closes.\n if (colourOpen) return;\n if (!inTable || typeof window === 'undefined') {\n setPos(null);\n return;\n }\n const recompute = (): void => {\n const area = areaRef.current;\n const table = getActiveTableEl();\n if (!area || !table) {\n setPos(null);\n return;\n }\n const a = area.getBoundingClientRect();\n const r = table.getBoundingClientRect();\n const rtl = getComputedStyle(area).direction === 'rtl';\n // Float just above the table's block-start edge, clamped to the container\n // top so it never renders above the editing surface. 44 ≈ the bar's own\n // height (one --min-target-size row) plus a small gap.\n const top = Math.max(0, r.top - a.top - 44);\n // Anchor `start` to the table's inline CENTRE; the render translates the\n // bar back by half its own width so it sits centred over the table.\n const center = rtl\n ? a.right - r.right + r.width / 2\n : r.left - a.left + r.width / 2;\n setPos({ top, start: Math.max(0, center), rtl });\n };\n recompute();\n // While the caret stays in the table the bar must track it: cell edits and\n // add-row/column grow the table (ResizeObserver), and the surface or the\n // viewport can scroll/resize.\n const ro = new ResizeObserver(recompute);\n const area = areaRef.current;\n const table = getActiveTableEl();\n if (area) ro.observe(area);\n if (table) ro.observe(table);\n window.addEventListener('scroll', recompute, true);\n window.addEventListener('resize', recompute);\n return () => {\n ro.disconnect();\n window.removeEventListener('scroll', recompute, true);\n window.removeEventListener('resize', recompute);\n };\n }, [inTable, colourOpen, areaRef, getActiveTableEl]);\n\n if ((!inTable && !colourOpen) || !pos) return null;\n\n // Ordered render groups; 'colour' is the cell/row background controls.\n const groups: (string[] | 'colour')[] = [\n ['rowAbove', 'rowBelow'],\n ['colLeft', 'colRight'],\n ['addHead'],\n ...(enableColor ? (['colour'] as const) : []),\n ['deleteRow', 'deleteColumn'],\n ['deleteTable'],\n ];\n\n return (\n // Tooltips disambiguate the icon-only ops on hover (and provide each\n // button's accessible name via IconButton's `tooltip` prop). Radix Tooltip\n // needs a provider ancestor, so scope one to the bar.\n <TooltipProvider>\n <div\n // role=\"group\", not \"toolbar\": these controls are independent tab\n // stops with no roving-focus / arrow-key navigation, so advertising the\n // WAI-ARIA toolbar contract would be a false promise. role=\"group\" keeps\n // the labelled grouping without committing to single-tab-stop semantics.\n role=\"group\"\n aria-label={t('editor.table.toolbar', 'Table tools')}\n // Centre on the table: --rte-tt-start is the table's inline centre, so\n // pull back by half the bar's width (mirrored for RTL).\n className={`${tableFloatClass} ${pos.rtl ? 'ds:translate-x-1/2' : 'ds:-translate-x-1/2'}`}\n // eslint-disable-next-line react/forbid-dom-props -- runtime-computed position injected via CSS custom properties (23-constraints §Runtime-computed dimensions); the inset rules live in the class\n style={{\n ['--rte-tt-top' as string]: `${pos.top}px`,\n ['--rte-tt-start' as string]: `${pos.start}px`,\n }}\n >\n {groups.map((group, gi) => (\n <Fragment key={group === 'colour' ? 'colour' : group[0]}>\n {gi > 0 ? (\n <span aria-hidden=\"true\" className={dividerClass} />\n ) : null}\n {group === 'colour' ? (\n <>\n <TableBgColourControl\n scope=\"cell\"\n icon={<PaintBucket />}\n label={t('editor.table.cellColor', 'Cell colour')}\n onOpenChange={handleColourOpenChange}\n saveTableCell={saveTableCell}\n applyTableBackground={applyTableBackground}\n />\n <TableBgColourControl\n scope=\"row\"\n icon={<PaintRoller />}\n label={t('editor.table.rowColor', 'Row colour')}\n onOpenChange={handleColourOpenChange}\n saveTableCell={saveTableCell}\n applyTableBackground={applyTableBackground}\n />\n </>\n ) : (\n group.map((opId) => {\n const op = TABLE_OP_BY_ID[opId];\n return (\n <IconButton\n key={opId}\n size=\"sm\"\n intent=\"ghost\"\n icon={op.icon}\n tooltip={t(op.label[0], op.label[1])}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => run(op.command)}\n />\n );\n })\n )}\n </Fragment>\n ))}\n </div>\n </TooltipProvider>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Toolbar */\n/* ------------------------------------------------------------------ */\n\nexport function EditorToolbar({\n run,\n active,\n preset,\n insertHtml,\n insertTable,\n saveSelection,\n restoreSelection,\n getSelectedText,\n uploadImage,\n enableColor = false,\n enableImage = false,\n enableTable = false,\n showExtensions = false,\n}: EditorToolbarProps): React.JSX.Element {\n const { t } = useTranslation();\n // Keep toolbar clicks from stealing the editor's selection.\n const keepSelection = (event: { preventDefault: () => void }): void =>\n event.preventDefault();\n\n // Render a simple command button by id, gated by the active preset.\n const has = (id: string): boolean => PRESETS[preset].includes(id);\n const btn = (id: string): React.JSX.Element | null => {\n if (!has(id)) return null;\n const item = ITEMS[id];\n return (\n <IconButton\n key={item.id}\n size=\"sm\"\n intent=\"ghost\"\n icon={item.icon}\n aria-label={t(item.label[0], item.label[1])}\n aria-pressed={item.toggle ? active.has(item.toggle) : undefined}\n onMouseDown={keepSelection}\n onClick={() => run(...item.command)}\n />\n );\n };\n const Divider = (): React.JSX.Element => (\n <span aria-hidden=\"true\" className={dividerClass} />\n );\n\n // Standard toolbar grouping (matches Google Docs / Word / TinyMCE order):\n // style ▸ inline (B/I/U/S + colour/highlight) ▸ lists ▸ insert ▸ extensions.\n const styleGroup = has('format');\n const inlineGroup =\n has('bold') ||\n has('italic') ||\n has('underline') ||\n has('strike') ||\n enableColor;\n const listsGroup = has('ul') || has('ol');\n const insertGroup = has('link') || enableImage || enableTable;\n\n return (\n <div\n // role=\"group\", not \"toolbar\": every control is its own tab stop with no\n // roving focus / arrow-key handling, so the toolbar contract would be\n // false. role=\"group\" keeps the labelled grouping without the single-\n // tab-stop + arrow-navigation promise.\n role=\"group\"\n aria-label={t('editor.toolbarLabel')}\n className={toolbarClass()}\n data-component=\"editor-toolbar\"\n >\n {/* Block style */}\n {styleGroup ? (\n <StyleMenu run={run} active={active} onTriggerDown={keepSelection} />\n ) : null}\n\n {/* Inline formatting */}\n {styleGroup && inlineGroup ? <Divider /> : null}\n {btn('bold')}\n {btn('italic')}\n {btn('underline')}\n {btn('strike')}\n {enableColor ? (\n <ColourControl\n run={run}\n saveSelection={saveSelection}\n restoreSelection={restoreSelection}\n />\n ) : null}\n {enableColor ? (\n <HighlightControl\n run={run}\n saveSelection={saveSelection}\n restoreSelection={restoreSelection}\n />\n ) : null}\n\n {/* Lists */}\n {(styleGroup || inlineGroup) && listsGroup ? <Divider /> : null}\n {btn('ul')}\n {btn('ol')}\n\n {/* Insert */}\n {(styleGroup || inlineGroup || listsGroup) && insertGroup ? (\n <Divider />\n ) : null}\n {has('link') ? (\n <LinkDialog\n insertHtml={insertHtml}\n saveSelection={saveSelection}\n restoreSelection={restoreSelection}\n getSelectedText={getSelectedText}\n />\n ) : null}\n {enableImage ? (\n <ImageDialog\n insertHtml={insertHtml}\n saveSelection={saveSelection}\n restoreSelection={restoreSelection}\n uploadImage={uploadImage}\n />\n ) : null}\n {enableTable ? (\n <TableControl run={run} insertTable={insertTable} active={active} />\n ) : null}\n\n {/* Editor extensions (marketplace tools) — inline placeholder */}\n {showExtensions &&\n (styleGroup || inlineGroup || listsGroup || insertGroup) ? (\n <Divider />\n ) : null}\n {showExtensions ? (\n <IconButton\n size=\"sm\"\n intent=\"ghost\"\n icon={<Wrench />}\n aria-label={t('editor.extensions', 'Editor extensions')}\n // Placeholder affordance: no handler is wired yet, so the control\n // must not be operable — an enabled button with no onClick fails\n // SC 4.1.2. Disable it until a marketplace handler is connected.\n disabled\n onMouseDown={keepSelection}\n />\n ) : null}\n </div>\n );\n}\n","/* ------------------------------------------------------------------ */\n/* RichTextEditor — thin, secure wrapper over Redactor (Imperavi). */\n/* */\n/* LICENCE-SAFETY MODEL (read first): */\n/* Redactor is a COMMERCIAL editor and `@alfadocs/ui-kit` publishes */\n/* to PUBLIC npm — so redactor.js bytes MUST NOT enter `dist/`. This */\n/* wrapper never imports Redactor; it resolves a Redactor factory at */\n/* runtime from a `redactor` prop or the UMD globals `window.$R` / */\n/* `window.Redactor` that the CONSUMER's licensed build sets */\n/* (platform ships `web/static/redactor/redactor.js`). With no */\n/* factory found, the editor renders a graceful plain <textarea>. */\n/* Storybook loads a vendored dev-only build via preview-head.html. */\n/* */\n/* - Toolbar/buttons/dropdowns/shortcuts are owned entirely by Redactor */\n/* itself. The kit only skins them via `redactor-theme.css` and feeds */\n/* button presets + lang strings. */\n/* - Security: all inbound HTML (value/defaultValue/setContent) and the */\n/* editor's outbound `changed` HTML run through DOMPurify with an */\n/* explicit FORBID list. Outbound HTML also gets `loading=\"lazy\"` on */\n/* images and platform's empty-placeholder normalisation. */\n/* - Backend-coupled features (image upload, help-me-write, */\n/* voice-recording) are CONSUMER-PROVIDED via `imageUploadUrl` / */\n/* `plugins` / `options`; the kit never bakes a backend route in. */\n/* - i18n: placeholder/aria via `t('editor.placeholder')`; Redactor's */\n/* own `lang` is derived from the active locale (not hardcoded). */\n/* ------------------------------------------------------------------ */\n\nimport {\n Fragment,\n forwardRef,\n useCallback,\n useEffect,\n useId,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type ChangeEvent,\n type ReactNode,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Mic, SpellCheck, Sparkles, Square, WandSparkles } from 'lucide-react';\n\nimport '../../tokens/themes/bridges/redactor-theme.css';\n\nimport { sanitiseHtml as sanitiseShared } from '../_shared/safe-html';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { Spinner } from '../spinner';\nimport { richTextEditorAgent } from './rich-text-editor.agent';\nimport { HelpMeWriteOverlay } from './help-me-write-overlay';\nimport { EditorToolbar, TableFloatingToolbar } from './editor-toolbar';\n\n/* ------------------------------------------------------------------ */\n/* Sanitisation */\n/* ------------------------------------------------------------------ */\n\n// Single sanitiser surface (constraints §8): the editor routes every inbound\n// and outbound HTML string through the shared `rich-text` DOMPurify profile in\n// `_shared/safe-html.tsx`, so one audit covers the whole kit. The wrapper adds\n// only editor-specific shaping (normalizeEditorValue + withLazyImages) around it.\nfunction sanitiseHtml(input: string): string {\n return sanitiseShared(input, 'rich-text');\n}\n\n// Mirror platform's RedactorWysiwyg `normalizeEditorValue` (RedactorWysiwyg.js\n// :26-44): map Redactor's empty placeholders to '' for the emptiness test, but\n// preserve image-only HTML so embedded-image notes aren't dropped on save.\nfunction normalizeEditorValue(html = ''): string {\n const normalized = String(html).trim();\n if (\n normalized === '' ||\n normalized === '<p><br></p>' ||\n normalized === '<p> </p>'\n ) {\n return '';\n }\n const contentWithoutTags = normalized\n .replace(/<br\\s*\\/?>/gi, '')\n .replace(/ /gi, '')\n .replace(/<[^>]+>/g, '')\n .trim();\n if (contentWithoutTags === '' && /<img\\b[^>]*>/i.test(normalized)) {\n return normalized;\n }\n return contentWithoutTags === '' ? '' : normalized;\n}\n\n// Inject `loading=\"lazy\"` on any <img> lacking it (platform parity).\nfunction withLazyImages(html: string): string {\n return html.replace(\n /<img(?![^>]*\\sloading=)([^>]*)>/gi,\n '<img loading=\"lazy\"$1>',\n );\n}\n\n// Pull the uploaded image URL out of a Redactor-style imageUpload response.\n// Handles the common shapes: `{ file: { url } }`, `{ url }`, `{ data: { url } }`,\n// and the multi-file map `{ \"1\": { url }, … }`.\nfunction extractUploadedUrl(data: unknown): string | undefined {\n if (!data || typeof data !== 'object') return undefined;\n const rec = data as Record<string, unknown>;\n const fromNode = (node: unknown): string | undefined => {\n if (node && typeof node === 'object' && 'url' in node) {\n const url = (node as { url?: unknown }).url;\n return typeof url === 'string' ? url : undefined;\n }\n return undefined;\n };\n if (typeof rec.url === 'string') return rec.url;\n return (\n fromNode(rec.file) ??\n fromNode(rec.data) ??\n Object.values(rec).map(fromNode).find(Boolean)\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Redactor factory resolution (external — never bundled) */\n/* ------------------------------------------------------------------ */\n\nexport type RedactorFactory = (\n selector: string | HTMLElement,\n command?: unknown,\n ...args: unknown[]\n) => unknown;\n\nfunction resolveRedactor(injected?: RedactorFactory): RedactorFactory | null {\n if (injected) return injected;\n if (typeof window === 'undefined') return null;\n const w = window as unknown as {\n $R?: RedactorFactory;\n Redactor?: RedactorFactory;\n };\n return w.$R ?? w.Redactor ?? null;\n}\n\n/* ------------------------------------------------------------------ */\n/* Public types */\n/* ------------------------------------------------------------------ */\n\nexport type RichTextEditorToolbar = 'minimal' | 'standard' | 'full';\n\nexport interface RichTextEditorProps {\n /** Opaque instance id — emitted as `data-component-id` for the agent registry. */\n id?: string;\n /** HTML initial value (uncontrolled). Runs through DOMPurify. */\n defaultValue?: string;\n /** Controlled value (HTML). Sanitised; synced with a skip-once caret guard. */\n value?: string;\n /** Emits on every change — debounced 100ms. `markdown` is '' (Redactor has no serializer). */\n onChange?: (payload: { html: string; markdown: string }) => void;\n /** Toolbar preset → Redactor `buttons`. */\n toolbar?: RichTextEditorToolbar;\n /** Placeholder text — translates via useTranslation if omitted. */\n placeholder?: string;\n /** Read-only mode. */\n readOnly?: boolean;\n /** Accessible name for the editing region. */\n ariaLabel?: string;\n /** Size variant for the minimum block-size of the editing region. */\n minHeight?: 'sm' | 'md' | 'lg';\n /** Show a right-aligned editor-extensions affordance (visual placeholder). */\n showExtensions?: boolean;\n /** Extra class names on the wrapper. */\n className?: string;\n\n /* --- Redactor-specific seams (all CONSUMER-PROVIDED) --- */\n /** Inject the Redactor factory explicitly; else `window.$R` / `window.Redactor`. */\n redactor?: RedactorFactory;\n /** Raw Redactor options, deep-merged LAST over the kit defaults (callbacks reserved). */\n options?: Record<string, unknown>;\n /** Redactor plugin names to enable (the consumer must register/load them). */\n plugins?: string[];\n /** Redactor lang code; default derived from the active i18n locale. */\n lang?: string;\n /** Consumer image-upload endpoint → Redactor `imageUpload`. Omitted if absent. */\n imageUploadUrl?: string;\n /** App keyboard-shortcut seam (e.g. Ctrl/Cmd+Enter to save). */\n onKeyDown?: (event: KeyboardEvent) => void;\n\n /* --- AI assistance (DS-native UI; backend stays consumer-provided) --- */\n /**\n * Help-me-write. When provided, a DS \"Help me write\" action appears; the kit\n * opens a dialog, calls this with the prompt + an AbortSignal, sanitises the\n * returned draft and inserts it at the caret. The backend call / auth /\n * practiceId all live in the consumer's implementation — never in the kit.\n */\n onRequestAiDraft?: (ctx: {\n prompt: string;\n signal: AbortSignal;\n }) => Promise<string>;\n /** Whether `onRequestAiDraft` returns HTML (default) or plain text. */\n aiDraftFormat?: 'html' | 'text';\n /** Override the compliance notice shown in the Help-me-write dialog. */\n aiPrivacyNotice?: ReactNode;\n /**\n * Voice dictation. When provided, a DS mic toggle + live-transcript region\n * appear. The kit owns the UI; the consumer runs mic capture + transcription\n * inside the callback and pushes text back via `onPartialTranscript` (drives\n * the live region) and `onFinalTranscript` (sanitised + inserted at the\n * caret). Resolve when the session ends; honour `signal` to stop. All\n * mic / transcription / backend logic stays consumer-side.\n */\n onDictate?: (ctx: {\n signal: AbortSignal;\n onPartialTranscript: (text: string) => void;\n onFinalTranscript: (text: string) => void;\n }) => Promise<void>;\n /**\n * One-shot AI document actions (CONSUMER-PROVIDED backend). Each gets the\n * current HTML + an AbortSignal and resolves with rewritten HTML; while one\n * runs the editor is disabled with a spinner and the result replaces the whole\n * document. `onProofread` corrects spelling/grammar; `onAutoFormat` tidies the\n * document's structure/formatting. Each adds a FAB segment when provided.\n */\n onProofread?: (ctx: { html: string; signal: AbortSignal }) => Promise<string>;\n onAutoFormat?: (ctx: {\n html: string;\n signal: AbortSignal;\n }) => Promise<string>;\n}\n\n/** Block/inline formats the editor can toggle via `applyFormat`. */\nexport type EditorFormat =\n | 'bold'\n | 'italic'\n | 'strikethrough'\n | 'bulletedList'\n | 'numberedList'\n | 'heading'\n | 'quote'\n | 'paragraph';\n\n// Maps each format to its Redactor command (shared with the toolbar).\nconst FORMAT_COMMANDS: Record<EditorFormat, [string, ...unknown[]]> = {\n bold: ['module.inline.format', { tag: 'b' }],\n italic: ['module.inline.format', { tag: 'i' }],\n strikethrough: ['module.inline.format', { tag: 'del' }],\n bulletedList: ['module.list.toggle', 'ul'],\n numberedList: ['module.list.toggle', 'ol'],\n heading: ['module.block.format', { tag: 'h2' }],\n quote: ['module.block.format', { tag: 'blockquote' }],\n paragraph: ['module.block.format', { tag: 'p' }],\n};\n\nexport interface RichTextEditorHandle {\n getHTML: () => string;\n /** Plain-text content of the editor (tags stripped). */\n getText: () => string;\n /** Always '' — Redactor has no native Markdown serializer (see MDX). */\n getMarkdown: () => string;\n /** HTML goes through DOMPurify before reaching Redactor. */\n setContent: (html: string) => void;\n /**\n * Insert content at the caret (replacing any selection). HTML is\n * DOMPurify-sanitised; pass `{ asHtml: false }` for a plain-text insert.\n * Works with the degraded <textarea> too. This is the seam for inserting\n * merge/template variables and AI-generated drafts.\n */\n insertAtCursor: (content: string, opts?: { asHtml?: boolean }) => void;\n /** Toggle/apply a block or inline format on the current selection. */\n applyFormat: (format: EditorFormat) => void;\n focus: () => void;\n clear: () => void;\n}\n\n// Map the kit's locale codes to Redactor's lang-file codes where they differ\n// (Redactor ships zh_cn / zh_tw / pt_br; the kit uses zh / pt). RTL (ar/fa/he)\n// pass through — direction is handled by the document dir, not the lang code.\nconst REDACTOR_LANG: Record<string, string> = {\n zh: 'zh_cn',\n pt: 'pt_br',\n};\n\nfunction toRedactorLang(locale: string): string {\n const base = locale.split('-')[0];\n return REDACTOR_LANG[base] ?? base ?? 'en';\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst wrapperVariants = cva(\n 'redactor-theme-alfadocs ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]',\n);\n\n// Degraded-mode plain textarea (Redactor not found) — looks like a kit field.\nconst degradedTextareaVariants = cva(\n [\n 'ds:block ds:[inline-size:100%]',\n 'ds:rounded-[var(--radius-md)] ds:border ds:border-[color:var(--border)]',\n 'ds:bg-[var(--background)] ds:text-[var(--foreground)]',\n 'ds:shadow-[var(--shadow-md)]',\n 'ds:font-[family-name:var(--font-sans)] ds:text-[length:var(--font-size-base)]',\n 'ds:p-[var(--spacing-md)] ds:[min-block-size:var(--rich-text-editor-min-block-size)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[var(--ring)]',\n 'ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n ].join(' '),\n);\n\n// Split-FAB segment: an icon button inside the primary pill (record |\n// help-me-write). Transparent on the pill with an INSET focus ring (the pill\n// clips overflow, so the ring must be inset).\nconst fabSegmentBase = [\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:[min-block-size:var(--min-target-size)] ds:[min-inline-size:var(--min-target-size)]',\n 'ds:text-[color:var(--primary-foreground)]',\n 'ds:transition-colors',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[var(--primary-foreground)]',\n 'ds:focus-visible:[outline-offset:calc(var(--focus-ring-width)*-1)]',\n].join(' ');\n\n// Idle segment: a translucent-white hover overlay over the pill.\nconst fabSegmentIdle = `${fabSegmentBase} ds:hover:bg-[color-mix(in_srgb,var(--primary-foreground)_15%,transparent)]`;\n\n// Recording mic: a solid destructive (red) fill that stays red on hover so the\n// \"stop\" state reads as live recording. Deliberately no aria-pressed translucent\n// overlay — its attribute selector out-specifies the red and would wash it out.\nconst fabSegmentRecording = `${fabSegmentBase} ds:bg-[var(--destructive)] ds:hover:bg-[color-mix(in_srgb,var(--destructive)_88%,var(--primary-foreground))]`;\n\n/* ------------------------------------------------------------------ */\n/* RichTextEditor */\n/* ------------------------------------------------------------------ */\n\nexport const RichTextEditor = forwardRef<\n RichTextEditorHandle,\n RichTextEditorProps\n>(\n (\n {\n id,\n defaultValue,\n value,\n onChange,\n toolbar = 'standard',\n placeholder,\n readOnly = false,\n ariaLabel,\n minHeight,\n showExtensions,\n className,\n redactor,\n options,\n plugins,\n lang,\n imageUploadUrl,\n onKeyDown,\n onRequestAiDraft,\n aiDraftFormat = 'html',\n aiPrivacyNotice,\n onDictate,\n onProofread,\n onAutoFormat,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n const rawId = useId();\n const editorId = useMemo(\n () => `rte-${rawId.replace(/[^a-zA-Z0-9-_]/g, '')}`,\n [rawId],\n );\n const selector = `#${editorId}`;\n\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const redactorRef = useRef<RedactorFactory | null>(null);\n // Skip-once guard: Redactor's `changed` already pushed this value out via\n // onChange, so the controlled-value effect must not echo it back with\n // setCode (which resets the caret to position 0). Mirrors platform.\n const skipNextPropSyncRef = useRef(false);\n // Mirrors the live readOnly state for imperative ops: Redactor blocks every\n // command except `disableReadOnly` while read-only, so writes (setContent /\n // clear / insertAtCursor / controlled-value sync) must lift it first.\n const readOnlyRef = useRef(readOnly);\n const wrapperRef = useRef<HTMLDivElement>(null);\n // The positioned editing-surface container — the floating table toolbar is\n // absolutely placed within it.\n const editorAreaRef = useRef<HTMLDivElement>(null);\n const [degraded, setDegraded] = useState(false);\n const [aiOpen, setAiOpen] = useState(false);\n // Active formats at the caret (bold/italic/strike/ul/ol/heading) — drives\n // the custom toolbar's pressed state; refreshed on Redactor's `observe`.\n const [activeFormats, setActiveFormats] = useState<ReadonlySet<string>>(\n () => new Set(),\n );\n\n const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const onChangeRef = useRef<RichTextEditorProps['onChange']>(onChange);\n const onKeyDownRef = useRef<RichTextEditorProps['onKeyDown']>(onKeyDown);\n useEffect(() => {\n onChangeRef.current = onChange;\n onKeyDownRef.current = onKeyDown;\n }, [onChange, onKeyDown]);\n\n // Initial content is computed once (controlled `value` is then synced by\n // the effect below). Sanitised before it ever reaches Redactor.\n const initialContentRef = useRef<string>(\n (() => {\n const raw = value ?? defaultValue ?? '';\n return raw ? sanitiseHtml(raw) : '';\n })(),\n );\n\n // Read the current editor HTML. Redactor's `source.getCode` is blocked while\n // read-only (returns undefined), so fall back to the synced source textarea\n // — never toggle read-only just to read.\n const readCode = useCallback((): string => {\n const R = redactorRef.current;\n if (R) {\n try {\n const code = R(selector, 'source.getCode');\n if (typeof code === 'string') return code;\n } catch {\n /* fall through to the source textarea */\n }\n }\n return textareaRef.current?.value ?? '';\n }, [selector]);\n\n // Dispatch a mutating Redactor command, transparently lifting read-only\n // (which blocks every command but `disableReadOnly`) and restoring it after.\n // Returns false when Redactor is absent or the call failed so the caller can\n // fall back to the degraded <textarea>.\n const dispatchWrite = useCallback(\n (command: string, ...args: unknown[]): boolean => {\n const R = redactorRef.current;\n if (!R) return false;\n const wasReadOnly = readOnlyRef.current;\n if (wasReadOnly) {\n try {\n R(selector, 'disableReadOnly');\n } catch {\n /* ignore */\n }\n }\n try {\n R(selector, command, ...args);\n return true;\n } catch {\n return false;\n } finally {\n if (wasReadOnly) {\n try {\n R(selector, 'enableReadOnly');\n } catch {\n // Restore failed — the editor may be left editable. Surface it in\n // DEV; the next readOnly-sync tick re-asserts it on a prop change.\n if (import.meta.env.DEV) {\n console.warn(\n '[RichTextEditor] failed to restore read-only after a write; the editor may be left editable.',\n );\n }\n }\n }\n }\n },\n [selector],\n );\n\n // Insert content at the caret, sanitised, with a degraded <textarea> splice\n // fallback. Shared by the imperative handle (merge variables) and the\n // Help-me-write dialog (AI drafts).\n const insertAtCursor = useCallback(\n (content: string, opts?: { asHtml?: boolean }): void => {\n const asHtml = opts?.asHtml ?? true;\n const payload = asHtml ? sanitiseHtml(content) : content;\n const command = asHtml\n ? 'insertion.insertHtml'\n : 'insertion.insertText';\n if (dispatchWrite(command, payload)) return;\n const ta = textareaRef.current;\n if (!ta) return;\n const start = ta.selectionStart ?? ta.value.length;\n const end = ta.selectionEnd ?? ta.value.length;\n ta.value = ta.value.slice(0, start) + payload + ta.value.slice(end);\n const caret = start + payload.length;\n try {\n ta.setSelectionRange(caret, caret);\n } catch {\n /* selection API unavailable */\n }\n onChangeRef.current?.({ html: sanitiseHtml(ta.value), markdown: '' });\n },\n [dispatchWrite],\n );\n\n // Last in-editor selection range — see updateActiveFormats / restoreSelection.\n const lastRangeRef = useRef<Range | null>(null);\n\n // Recompute the active inline/block formats at the caret (scoped to THIS\n // editor's `.redactor-in`) for the custom toolbar's pressed state.\n const updateActiveFormats = useCallback((): void => {\n const root = wrapperRef.current?.querySelector('.redactor-in');\n const selection =\n typeof window !== 'undefined' ? window.getSelection() : null;\n const next = new Set<string>();\n if (\n root &&\n selection &&\n selection.anchorNode &&\n root.contains(selection.anchorNode) &&\n typeof document.queryCommandState === 'function'\n ) {\n // Track the live in-editor range so a focus-stealing DS popover/dialog\n // can restore EXACTLY here — needed because Redactor's insertHtml wraps\n // the insert in a fresh <p> when no selection is active at insert time.\n if (selection.rangeCount > 0) {\n lastRangeRef.current = selection.getRangeAt(0).cloneRange();\n }\n // queryCommandState reads the selection's EFFECTIVE format (it handles\n // range boundaries + nesting), unlike walking the anchor's ancestors —\n // which misses a format when the anchor sits just outside the wrapper.\n try {\n if (document.queryCommandState('bold')) next.add('bold');\n if (document.queryCommandState('italic')) next.add('italic');\n if (document.queryCommandState('underline')) next.add('underline');\n if (document.queryCommandState('strikeThrough')) next.add('strike');\n if (document.queryCommandState('insertUnorderedList')) next.add('ul');\n if (document.queryCommandState('insertOrderedList')) next.add('ol');\n const block = String(\n document.queryCommandValue('formatBlock') || '',\n ).toLowerCase();\n // Add both the generic 'heading' token and the specific block tag\n // (h2/h3/quote/paragraph) so the toolbar's labelled style button can\n // show the active style by name.\n if (/^h[1-6]$/.test(block)) {\n next.add('heading');\n next.add(block);\n } else if (block === 'blockquote') {\n next.add('quote');\n } else {\n next.add('paragraph');\n }\n // Table context — drives the contextual table ops in the toolbar.\n const anchorEl =\n selection.anchorNode.nodeType === Node.TEXT_NODE\n ? selection.anchorNode.parentElement\n : (selection.anchorNode as Element | null);\n if (\n anchorEl &&\n root.contains(anchorEl) &&\n anchorEl.closest('table')\n ) {\n next.add('table');\n }\n } catch {\n /* queryCommand unsupported in this environment */\n }\n }\n setActiveFormats((prev) =>\n prev.size === next.size && [...next].every((f) => prev.has(f))\n ? prev\n : next,\n );\n }, []);\n\n // Run a Redactor command from the custom toolbar, then refresh active state.\n const runCommand = useCallback(\n (command: string, ...args: unknown[]): void => {\n dispatchWrite(command, ...args);\n // Defer the active-state read: let Redactor finish applying the command\n // and the selection settle first, otherwise un-toggling a format reads\n // the stale pre-change DOM and the button stays pressed.\n if (typeof window !== 'undefined') {\n window.requestAnimationFrame(() => updateActiveFormats());\n } else {\n updateActiveFormats();\n }\n },\n [dispatchWrite, updateActiveFormats],\n );\n\n // Inline-format keyboard shortcuts (Cmd/Ctrl + B/I/U). Redactor ships these\n // natively, but with `toolbar: false` its shortcut fires yet silently no-ops\n // (it preventDefaults the key, then its inline.format applies nothing). So\n // the kit owns them: intercept on the editor in the capture phase — before\n // Redactor's own keydown listener — and route through the SAME runCommand\n // path the toolbar uses (which works). stopImmediatePropagation suppresses\n // Redactor's dead handler; preventDefault suppresses the browser's native\n // execCommand so the format applies exactly once.\n useEffect(() => {\n const wrapper = wrapperRef.current;\n if (!wrapper) return undefined;\n // Local key→command map (the same inline commands the toolbar buttons\n // fire) so this owns nothing on the public format API.\n const SHORTCUT_COMMANDS: Record<string, [string, ...unknown[]]> = {\n b: ['module.inline.format', { tag: 'b' }],\n i: ['module.inline.format', { tag: 'i' }],\n u: ['module.inline.format', { tag: 'u' }],\n };\n const onKeyDownCapture = (event: KeyboardEvent): void => {\n if (!(event.metaKey || event.ctrlKey) || event.altKey || event.shiftKey)\n return;\n if (event.isComposing) return;\n const command = SHORTCUT_COMMANDS[event.key.toLowerCase()];\n if (!command) return;\n // Only when the caret is in this editor's editable, and it's writable.\n const editable = wrapper.querySelector('.redactor-in');\n if (\n !editable ||\n !(event.target instanceof Node) ||\n !editable.contains(event.target) ||\n readOnlyRef.current\n )\n return;\n event.preventDefault();\n event.stopImmediatePropagation();\n runCommand(...command);\n };\n wrapper.addEventListener('keydown', onKeyDownCapture, true);\n return () =>\n wrapper.removeEventListener('keydown', onKeyDownCapture, true);\n }, [runCommand]);\n\n // Insert sanitised HTML at the caret — the toolbar's link/image dialogs use\n // this (DOMPurify runs inside insertAtCursor) instead of Redactor's native\n // modals.\n const insertHtml = useCallback(\n (html: string): void => {\n insertAtCursor(html, { asHtml: true });\n if (typeof window !== 'undefined') {\n window.requestAnimationFrame(() => updateActiveFormats());\n }\n },\n [insertAtCursor, updateActiveFormats],\n );\n\n // Save / restore the editor selection around a DS popover/dialog (which\n // takes focus and would otherwise collapse the caret). Backed by Redactor's\n // selection module; no-ops in the degraded textarea.\n const saveSelection = useCallback((): void => {\n // Snapshot the current in-editor range synchronously (before a trigger's\n // focus move can collapse it), in addition to the observe-driven tracking.\n if (typeof window !== 'undefined') {\n const root = wrapperRef.current?.querySelector('.redactor-in');\n const sel = window.getSelection();\n if (\n root &&\n sel &&\n sel.rangeCount > 0 &&\n sel.anchorNode &&\n root.contains(sel.anchorNode)\n ) {\n lastRangeRef.current = sel.getRangeAt(0).cloneRange();\n }\n }\n const R = redactorRef.current;\n if (R) {\n try {\n R(selector, 'selection.save');\n } catch {\n /* selection module unavailable */\n }\n }\n }, [selector]);\n\n const restoreSelection = useCallback((): void => {\n const R = redactorRef.current;\n if (!R) return;\n // Re-focus the editor, then re-apply the tracked DOM range. This is more\n // reliable than Redactor's marker-based restore when a modal's focus trap\n // moved focus before the markers were set — without an active selection\n // Redactor's insertHtml wraps the insert in a new <p> (the link/image\n // \"block\" bug). Fall back to the marker restore if no range was tracked.\n // Capture the tracked range BEFORE editor.focus: focusing fires Redactor's\n // `observe`, which runs updateActiveFormats and overwrites lastRangeRef with\n // the post-focus caret (editor start). Reading it first preserves the\n // user's real selection (otherwise colour/link land at the top of the doc).\n const range = lastRangeRef.current;\n try {\n R(selector, 'editor.focus');\n } catch {\n /* ignore */\n }\n if (range && typeof window !== 'undefined') {\n const sel = window.getSelection();\n if (sel) {\n try {\n sel.removeAllRanges();\n sel.addRange(range);\n return;\n } catch {\n /* range no longer valid — fall through to marker restore */\n }\n }\n }\n try {\n R(selector, 'selection.restore');\n } catch {\n /* selection module unavailable */\n }\n }, [selector]);\n\n // Current selected text (for prefilling the link dialog's text field).\n const getSelectedText = useCallback((): string => {\n if (typeof window === 'undefined') return '';\n const root = wrapperRef.current?.querySelector('.redactor-in');\n const selection = window.getSelection();\n if (\n !root ||\n !selection ||\n !selection.anchorNode ||\n !root.contains(selection.anchorNode)\n ) {\n return '';\n }\n return selection.toString();\n }, []);\n\n // The <table> the caret is currently inside (scoped to THIS editor's\n // `.redactor-in`), or null — drives the floating in-cell table toolbar's\n // visibility + anchor. Mirrors the table detection in updateActiveFormats.\n const getActiveTableEl = useCallback((): HTMLElement | null => {\n if (typeof window === 'undefined') return null;\n const root = wrapperRef.current?.querySelector('.redactor-in');\n const selection = window.getSelection();\n if (!root || !selection || selection.rangeCount === 0) return null;\n const node = selection.anchorNode;\n const el =\n node && node.nodeType === Node.TEXT_NODE\n ? node.parentElement\n : (node as Element | null);\n if (!el || !root.contains(el)) return null;\n return el.closest('table');\n }, []);\n\n // The <td>/<th> the caret is in (scoped to this editor) — backs the table\n // background-colour controls.\n const lastCellRef = useRef<HTMLElement | null>(null);\n const getActiveCellEl = useCallback((): HTMLElement | null => {\n if (typeof window === 'undefined') return null;\n const root = wrapperRef.current?.querySelector('.redactor-in');\n const selection = window.getSelection();\n if (!root || !selection || selection.rangeCount === 0) return null;\n const node = selection.anchorNode;\n const el =\n node && node.nodeType === Node.TEXT_NODE\n ? node.parentElement\n : (node as Element | null);\n if (!el || !root.contains(el)) return null;\n return el.closest('td,th') as HTMLElement | null;\n }, []);\n\n // Snapshot the current cell before a colour popover steals focus.\n const saveTableCell = useCallback((): void => {\n lastCellRef.current = getActiveCellEl();\n }, [getActiveCellEl]);\n\n // Apply (colour) or clear (colour === null) a background on the saved cell,\n // or every cell in its row. Redactor has no cell-styling command, so this\n // mutates the editable DOM directly, takes a best-effort undo snapshot, then\n // hard-syncs so the change lands in the source + fires `changed` → onChange.\n const applyTableBackground = useCallback(\n (scope: 'cell' | 'row', colour: string | null): void => {\n const cell = lastCellRef.current ?? getActiveCellEl();\n if (!cell) return;\n const targets: HTMLElement[] =\n scope === 'row'\n ? Array.from(cell.closest('tr')?.children ?? [cell]).filter(\n (n): n is HTMLElement =>\n n instanceof HTMLElement &&\n (n.tagName === 'TD' || n.tagName === 'TH'),\n )\n : [cell];\n const R = redactorRef.current;\n if (R) {\n try {\n R(selector, 'module.buffer.trigger');\n } catch {\n /* undo buffer unavailable — colour still applies */\n }\n }\n for (const el of targets) {\n if (colour) el.style.setProperty('background-color', colour);\n else el.style.removeProperty('background-color');\n }\n if (R) {\n try {\n R(selector, 'broadcast', 'hardsync');\n } catch {\n /* sync unavailable */\n }\n }\n if (typeof window !== 'undefined') {\n window.requestAnimationFrame(() => updateActiveFormats());\n }\n },\n [getActiveCellEl, selector, updateActiveFormats],\n );\n\n // Insert a table, but never inside a list item — tables can't live in an\n // <li> and the nested markup hides the table UI. When the caret is in a\n // list, drop it after the whole list so the table lands as its own block.\n const insertTable = useCallback(\n (html: string): void => {\n const R = redactorRef.current;\n if (R && typeof window !== 'undefined') {\n const root = wrapperRef.current?.querySelector('.redactor-in');\n const selection = window.getSelection();\n const node = selection?.anchorNode;\n const el =\n node && node.nodeType === Node.TEXT_NODE\n ? node.parentElement\n : (node as Element | null);\n const list = el && root?.contains(el) ? el.closest('ul,ol') : null;\n if (list) {\n try {\n R(selector, 'caret.setAfter', list);\n } catch {\n /* caret module unavailable — falls back to cursor insert */\n }\n }\n }\n insertHtml(html);\n // Redactor's insertion leaves a stray trailing whitespace text node in\n // the final cell (<td><br> </td>); that space renders as a second line\n // and makes the last row taller WHILE EDITING. The saved source is\n // already clean (cleaner.output strips it), so just tidy the live\n // editable so every row renders at one line.\n if (typeof window !== 'undefined') {\n window.requestAnimationFrame(() => {\n const root = wrapperRef.current?.querySelector('.redactor-in');\n root?.querySelectorAll('table td, table th').forEach((cell) => {\n let last = cell.lastChild;\n while (\n last &&\n last.nodeType === Node.TEXT_NODE &&\n !(last.textContent ?? '').trim()\n ) {\n const prev = last.previousSibling;\n cell.removeChild(last);\n last = prev;\n }\n });\n });\n }\n },\n [insertHtml, selector],\n );\n\n // Upload an image file to the consumer's endpoint (mirrors Redactor's\n // imageUpload config) and resolve the stored URL — the image dialog's\n // upload tab uses this so users can upload, not just paste a URL.\n const uploadImage = useCallback(\n async (file: File, signal?: AbortSignal): Promise<string> => {\n if (!imageUploadUrl) throw new Error('No image upload URL configured.');\n const form = new FormData();\n form.append('file', file);\n const res = await fetch(imageUploadUrl, {\n method: 'POST',\n body: form,\n credentials: 'same-origin',\n signal,\n });\n if (!res.ok) throw new Error(`Image upload failed (${res.status}).`);\n const url = extractUploadedUrl(await res.json());\n if (!url) throw new Error('Image upload response contained no URL.');\n return url;\n },\n [imageUploadUrl],\n );\n\n /* ---- Voice dictation (DS UI; consumer runs mic + transcription) - */\n const dictateAbortRef = useRef<AbortController | null>(null);\n const interimRef = useRef<HTMLElement | null>(null);\n const [isDictating, setIsDictating] = useState(false);\n const [dictationErrored, setDictationErrored] = useState(false);\n // Drives the visually-hidden live region: announces the listening status on\n // start and each committed phrase as it lands, so screen-reader users get\n // the same feedback sighted users get from the grey interim span + caret.\n const [dictationAnnouncement, setDictationAnnouncement] = useState('');\n\n // Live (interim) speech shown in the editor as a grey, non-editable span\n // with a blinking caret; replaced by committed text on each final phrase.\n const clearInterim = useCallback((): void => {\n const el = interimRef.current;\n if (el?.parentNode) el.parentNode.removeChild(el);\n interimRef.current = null;\n }, []);\n\n const showInterim = useCallback((text: string): void => {\n const root = wrapperRef.current?.querySelector(\n '.redactor-in',\n ) as HTMLElement | null;\n if (!root) return;\n let el = interimRef.current;\n if (!el || !root.contains(el)) {\n el = document.createElement('span');\n el.setAttribute('data-rte-interim', '');\n el.setAttribute('contenteditable', 'false');\n const selection = window.getSelection();\n if (\n selection &&\n selection.rangeCount > 0 &&\n root.contains(selection.anchorNode)\n ) {\n const range = selection.getRangeAt(0);\n range.collapse(false);\n range.insertNode(el);\n } else {\n root.appendChild(el);\n }\n interimRef.current = el;\n }\n el.textContent = text;\n }, []);\n\n const stopDictation = useCallback(() => {\n // Abort but keep the ref: the in-flight session's `.finally` clears it\n // (and resets state) only when it's still the current session, so a normal\n // stop resets while a stale settle after a newer start does not.\n dictateAbortRef.current?.abort();\n }, []);\n\n const startDictation = useCallback(() => {\n if (!onDictate) return;\n const controller = new AbortController();\n dictateAbortRef.current = controller;\n setDictationErrored(false);\n setIsDictating(true);\n setDictationAnnouncement(t('editor.ai.listening'));\n clearInterim();\n onDictate({\n signal: controller.signal,\n // Interim text shows live in the editor (grey + caret); each final\n // replaces it with committed text at the caret.\n onPartialTranscript: (text: string): void => {\n if (controller.signal.aborted) return;\n showInterim(text);\n },\n onFinalTranscript: (text: string): void => {\n if (controller.signal.aborted) return;\n clearInterim();\n const trimmed = text.trim();\n if (trimmed) {\n insertAtCursor(`${trimmed} `, { asHtml: false });\n // Announce the committed phrase; it replaces the interim text the\n // SR could not perceive (the grey span is aria-hidden DOM injected\n // outside React's tree).\n setDictationAnnouncement(trimmed);\n }\n },\n })\n .catch((err: unknown) => {\n if (\n controller.signal.aborted ||\n (err &&\n typeof err === 'object' &&\n 'name' in err &&\n (err as { name?: string }).name === 'AbortError')\n ) {\n return;\n }\n setDictationErrored(true);\n })\n .finally(() => {\n clearInterim();\n // Only the session that still owns the ref resets state — a stale\n // settle (a newer session already started) must not clobber it.\n if (dictateAbortRef.current === controller) {\n dictateAbortRef.current = null;\n setIsDictating(false);\n setDictationAnnouncement('');\n }\n });\n }, [onDictate, insertAtCursor, clearInterim, showInterim, t]);\n\n const toggleDictation = useCallback(() => {\n if (isDictating) stopDictation();\n else startDictation();\n }, [isDictating, startDictation, stopDictation]);\n\n // Abort dictation on unmount.\n useEffect(() => () => dictateAbortRef.current?.abort(), []);\n\n /* ---- One-shot AI document actions (proofread / auto-format) ---- */\n // Which one-shot action is running (drives the FAB spinner + the editor's\n // disabled scrim); only one runs at a time.\n const [oneShot, setOneShot] = useState<'proofread' | 'format' | null>(null);\n const oneShotAbortRef = useRef<AbortController | null>(null);\n const runOneShot = useCallback(\n (\n kind: 'proofread' | 'format',\n fn: (ctx: { html: string; signal: AbortSignal }) => Promise<string>,\n ): void => {\n if (oneShotAbortRef.current) return; // one at a time\n const controller = new AbortController();\n oneShotAbortRef.current = controller;\n setOneShot(kind);\n const html = readCode();\n Promise.resolve(fn({ html, signal: controller.signal }))\n .then((result) => {\n if (controller.signal.aborted) return;\n // Replace the whole document with the rewritten HTML (re-sanitised\n // at the editor seam) and notify the consumer.\n const safe = sanitiseHtml(String(result ?? ''));\n dispatchWrite('source.setCode', safe);\n onChangeRef.current?.({ html: safe, markdown: '' });\n })\n .catch(() => {\n /* abort / backend error — leave the document unchanged */\n })\n .finally(() => {\n if (oneShotAbortRef.current === controller) {\n oneShotAbortRef.current = null;\n setOneShot(null);\n }\n });\n },\n [readCode, dispatchWrite],\n );\n\n // Cancel a running one-shot. Clears the UI immediately (and aborts the\n // signal) rather than waiting on the promise, so the user always recovers\n // even if the consumer's call ignores the signal / hangs — the settle\n // guards (aborted + ref identity) then make the late result a no-op.\n const cancelOneShot = useCallback((): void => {\n oneShotAbortRef.current?.abort();\n oneShotAbortRef.current = null;\n setOneShot(null);\n }, []);\n\n // Abort an in-flight one-shot on unmount.\n useEffect(() => () => oneShotAbortRef.current?.abort(), []);\n\n /* ---- Init Redactor once (or degrade gracefully) -------------- */\n useEffect(() => {\n const ta = textareaRef.current;\n if (!ta) return undefined;\n // Seed the host textarea imperatively: Redactor reads it on init, and in\n // degraded mode it stays as the textarea's shown value. (Done here, not\n // via `defaultValue`, because `degraded` flips after mount so a\n // `defaultValue` prop would never apply.)\n ta.value = initialContentRef.current;\n const R = resolveRedactor(redactor);\n if (!R) {\n setDegraded(true);\n if (import.meta.env.DEV) {\n console.warn(\n '[RichTextEditor] Redactor not found on window.$R / window.Redactor and no `redactor` prop supplied; rendering a plain textarea.',\n );\n }\n return undefined;\n }\n redactorRef.current = R;\n\n const kitDefaults: Record<string, unknown> = {\n lang: lang ?? toRedactorLang(i18n.language || 'en'),\n // The kit renders its OWN toolbar (EditorToolbar) and drives Redactor\n // via the command API, so Redactor's native toolbar is suppressed.\n toolbar: false,\n plugins: plugins ?? [],\n placeholder: placeholder ?? t('editor.placeholder'),\n toolbarFixed: false,\n // Platform parity (RedactorWysiwyg.js:84): no inline shortcode expansion.\n shortcodes: false,\n imageEditable: false,\n imageResizable: true,\n };\n const imageUploadOption = imageUploadUrl\n ? { imageUpload: imageUploadUrl }\n : {};\n\n const consumerCallbacks =\n (options?.callbacks as Record<string, unknown> | undefined) ?? {};\n\n const finalOptions: Record<string, unknown> = {\n ...kitDefaults,\n ...imageUploadOption,\n ...(options ?? {}),\n // Re-pin safety-critical keys LAST so consumer `options` can't override\n // the sanitising change handler, re-enable image editing, or turn off\n // drag-resize (platform re-pins both image flags — RedactorWysiwyg.js:115-116).\n imageEditable: false,\n imageResizable: true,\n callbacks: {\n ...consumerCallbacks,\n changed(html: string): void {\n const normalized = normalizeEditorValue(withLazyImages(html));\n const safe = sanitiseHtml(normalized);\n skipNextPropSyncRef.current = true;\n if (!onChangeRef.current) return;\n if (debounceRef.current) clearTimeout(debounceRef.current);\n debounceRef.current = setTimeout(() => {\n onChangeRef.current?.({ html: safe, markdown: '' });\n }, 100);\n },\n keydown(event: KeyboardEvent): void {\n onKeyDownRef.current?.(event);\n },\n observe(): void {\n updateActiveFormats();\n },\n },\n };\n\n try {\n R(selector, finalOptions);\n // Redactor's read-only commands are camel-cased `enableReadOnly` /\n // `disableReadOnly` in this build (lower-case `enableReadonly` is a\n // silent no-op). Guarded so an unknown command stays inert.\n if (readOnly) {\n try {\n R(selector, 'enableReadOnly');\n } catch {\n /* readonly command unsupported in this Redactor build */\n }\n }\n } catch {\n setDegraded(true);\n }\n\n return () => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n try {\n // Platform forgets to destroy and leaks; we clean up on unmount.\n R(selector, 'destroy');\n } catch {\n /* already torn down */\n }\n redactorRef.current = null;\n };\n // Init once — option changes after mount are not re-applied (matches the\n // editor's uncontrolled-internals model); value/readOnly sync below.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n /* ---- Keep controlled `value` in sync (skip-once caret guard) - */\n useEffect(() => {\n if (!redactorRef.current || value === undefined) return;\n if (skipNextPropSyncRef.current) {\n skipNextPropSyncRef.current = false;\n return;\n }\n const safe = sanitiseHtml(normalizeEditorValue(value));\n const current = normalizeEditorValue(readCode());\n if (current !== safe) dispatchWrite('source.setCode', safe);\n }, [value, readCode, dispatchWrite]);\n\n /* ---- Keep readOnly in sync ----------------------------------- */\n useEffect(() => {\n readOnlyRef.current = readOnly;\n const R = redactorRef.current;\n if (!R) return;\n try {\n R(selector, readOnly ? 'enableReadOnly' : 'disableReadOnly');\n } catch {\n /* readonly command unsupported in this Redactor build */\n }\n }, [readOnly, selector]);\n\n /* ---- Degraded fallback: reflect controlled `value` ----------- */\n // Without Redactor the host textarea is uncontrolled (seeded once on init),\n // so it would otherwise ignore external `value` updates. Sync imperatively\n // (a controlled `value=` would warn when `degraded` flips after mount), and\n // skip while focused so we never reset the user's caret mid-type.\n useEffect(() => {\n if (!degraded || value === undefined) return;\n const ta = textareaRef.current;\n if (!ta) return;\n const safe = sanitiseHtml(value);\n if (ta.value !== safe && document.activeElement !== ta) {\n ta.value = safe;\n }\n }, [degraded, value]);\n\n /* ---- Imperative handle --------------------------------------- */\n const handle = useMemo<RichTextEditorHandle>(\n () => ({\n getHTML(): string {\n return readCode();\n },\n getText(): string {\n return readCode()\n .replace(/<[^>]*>/g, ' ')\n .replace(/ /gi, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n },\n getMarkdown(): string {\n return '';\n },\n setContent(html: string): void {\n const safe = sanitiseHtml(html);\n if (dispatchWrite('source.setCode', safe)) return;\n if (textareaRef.current) textareaRef.current.value = safe;\n },\n insertAtCursor,\n applyFormat(format): void {\n const command = FORMAT_COMMANDS[format];\n if (command) runCommand(...command);\n },\n focus(): void {\n const R = redactorRef.current;\n if (R) {\n try {\n R(selector, 'editor.focus');\n return;\n } catch {\n /* fall through */\n }\n }\n textareaRef.current?.focus();\n },\n clear(): void {\n if (dispatchWrite('source.setCode', '')) return;\n if (textareaRef.current) textareaRef.current.value = '';\n },\n }),\n [selector, readCode, dispatchWrite, insertAtCursor, runCommand],\n );\n useImperativeHandle(ref, () => handle, [handle]);\n useAgentRegistration(richTextEditorAgent, handle, id);\n\n /* ---- Degraded-mode change handler ---------------------------- */\n const handleDegradedChange = useCallback(\n (event: ChangeEvent<HTMLTextAreaElement>): void => {\n onChangeRef.current?.({\n html: sanitiseHtml(event.target.value),\n markdown: '',\n });\n },\n [],\n );\n\n // Accessible name for the editing region — a dedicated label, not the\n // placeholder, so the region's name and its placeholder hint don't collide.\n const resolvedLabel = ariaLabel ?? t('editor.regionLabel');\n const resolvedPlaceholder = placeholder ?? t('editor.placeholder');\n\n /* ---- Normalise Redactor's editing-surface ARIA --------------- */\n // Redactor renders the surface as a role=\"presentation\" contenteditable and,\n // while empty, points aria-labelledby at its hidden voice region — invalid\n // ARIA (axe: aria-prohibited-attr, since aria-labelledby can't sit on a\n // presentational node). Promote it to a properly-named textbox and keep it\n // that way as Redactor toggles the placeholder state. Redactor's own kit\n // usages never hit this because they all seed content (no empty placeholder).\n useEffect(() => {\n if (degraded) return undefined;\n const editable = wrapperRef.current?.querySelector('.redactor-in');\n if (!editable) return undefined;\n const normalise = () => {\n if (editable.getAttribute('role') !== 'textbox')\n editable.setAttribute('role', 'textbox');\n if (editable.getAttribute('aria-multiline') !== 'true')\n editable.setAttribute('aria-multiline', 'true');\n if (editable.getAttribute('aria-label') !== resolvedLabel)\n editable.setAttribute('aria-label', resolvedLabel);\n if (editable.hasAttribute('aria-labelledby'))\n editable.removeAttribute('aria-labelledby');\n };\n normalise();\n const observer = new MutationObserver(normalise);\n observer.observe(editable, {\n attributes: true,\n attributeFilter: ['role', 'aria-labelledby'],\n });\n return () => observer.disconnect();\n }, [degraded, resolvedLabel]);\n\n // AI FAB segments — rendered as one pill in this order: dictation · spelling\n // & grammar · auto-format · Alia. The two one-shot actions show a spinner\n // while running; everything else is disabled meanwhile.\n const busy = oneShot !== null;\n const fabSegments: {\n key: string;\n icon: ReactNode;\n label: string;\n onClick: () => void;\n recording?: boolean;\n running?: boolean;\n }[] = [];\n if (onDictate) {\n fabSegments.push({\n key: 'dictate',\n icon: isDictating ? (\n <Square aria-hidden=\"true\" className=\"ds:size-5 ds:fill-current\" />\n ) : (\n <Mic aria-hidden=\"true\" className=\"ds:size-5\" />\n ),\n label: isDictating\n ? t('editor.ai.dictateStop')\n : t('editor.ai.dictateStart'),\n onClick: toggleDictation,\n recording: isDictating,\n });\n }\n if (onProofread) {\n fabSegments.push({\n key: 'proofread',\n // While running, the segment becomes a STOP/cancel button (progress is\n // shown by the scrim spinner).\n icon:\n oneShot === 'proofread' ? (\n <Square aria-hidden=\"true\" className=\"ds:size-5 ds:fill-current\" />\n ) : (\n <SpellCheck aria-hidden=\"true\" className=\"ds:size-5\" />\n ),\n label:\n oneShot === 'proofread'\n ? t('common.cancel')\n : t('editor.ai.proofread', 'Check spelling & grammar'),\n onClick:\n oneShot === 'proofread'\n ? cancelOneShot\n : () => runOneShot('proofread', onProofread),\n running: oneShot === 'proofread',\n });\n }\n if (onAutoFormat) {\n fabSegments.push({\n key: 'format',\n icon:\n oneShot === 'format' ? (\n <Square aria-hidden=\"true\" className=\"ds:size-5 ds:fill-current\" />\n ) : (\n <WandSparkles aria-hidden=\"true\" className=\"ds:size-5\" />\n ),\n label:\n oneShot === 'format'\n ? t('common.cancel')\n : t('editor.ai.autoFormat', 'Auto-format document'),\n onClick:\n oneShot === 'format'\n ? cancelOneShot\n : () => runOneShot('format', onAutoFormat),\n running: oneShot === 'format',\n });\n }\n if (onRequestAiDraft) {\n fabSegments.push({\n key: 'write',\n icon: <Sparkles aria-hidden=\"true\" className=\"ds:size-5\" />,\n label: t('editor.ai.helpMeWrite'),\n onClick: () => {\n saveSelection();\n setAiOpen(true);\n },\n });\n }\n\n return (\n <div\n ref={wrapperRef}\n className={[wrapperVariants(), className].filter(Boolean).join(' ')}\n data-component=\"rich-text-editor\"\n data-component-id={id}\n data-min-height={minHeight}\n >\n {!degraded && !readOnly ? (\n <EditorToolbar\n run={runCommand}\n active={activeFormats}\n preset={toolbar}\n insertHtml={insertHtml}\n insertTable={insertTable}\n saveSelection={saveSelection}\n restoreSelection={restoreSelection}\n getSelectedText={getSelectedText}\n uploadImage={imageUploadUrl ? uploadImage : undefined}\n enableColor={plugins?.includes('fontcolor') ?? false}\n enableImage={Boolean(imageUploadUrl)}\n enableTable={plugins?.includes('table') ?? false}\n showExtensions={showExtensions}\n />\n ) : null}\n <div className=\"ds:relative\" ref={editorAreaRef}>\n <textarea\n ref={textareaRef}\n id={editorId}\n aria-label={resolvedLabel}\n aria-multiline=\"true\"\n aria-busy={busy || undefined}\n placeholder={resolvedPlaceholder}\n onChange={degraded ? handleDegradedChange : undefined}\n readOnly={degraded ? readOnly : undefined}\n className={degraded ? degradedTextareaVariants() : undefined}\n />\n {/* While a one-shot AI action runs, dim + block the editor (it's being\n rewritten) with a centred spinner; the running FAB segment turns\n into a Stop/Cancel button. */}\n {busy ? (\n <div\n aria-hidden=\"true\"\n className=\"ds:absolute ds:inset-0 ds:z-[5] ds:flex ds:items-center ds:justify-center ds:cursor-wait ds:rounded-[var(--radius-md)] ds:bg-[color-mix(in_srgb,var(--background)_40%,transparent)]\"\n >\n <Spinner size=\"lg\" variant=\"prism\" />\n </div>\n ) : null}\n {/* AI affordances — the FAB + Alia popout. Wrapped in a zero-height\n STICKY dock (its only children are absolute) so in a long document\n they ride the viewport's block-end instead of scrolling off at the\n editor's bottom; the FAB/overlay keep their absolute positioning,\n now anchored to this dock. */}\n <div className=\"ds:sticky ds:bottom-0 ds:z-10\">\n {fabSegments.length > 0 ? (\n <div className=\"ds:absolute ds:[inset-block-end:var(--spacing-md)] ds:[inset-inline-end:var(--spacing-md)] ds:z-10 ds:flex ds:items-center ds:overflow-hidden ds:rounded-full ds:bg-[var(--primary)] ds:bg-[image:var(--gradient-brand)] ds:shadow-[0_8px_24px_color-mix(in_srgb,var(--primary)_35%,transparent)]\">\n {fabSegments.map((seg, i) => (\n <Fragment key={seg.key}>\n {i > 0 ? (\n <span\n aria-hidden=\"true\"\n className=\"ds:self-stretch ds:[inline-size:var(--border-width-sm)] ds:bg-[color-mix(in_srgb,var(--primary-foreground)_35%,transparent)]\"\n />\n ) : null}\n <button\n type=\"button\"\n onClick={seg.onClick}\n aria-pressed={seg.recording || undefined}\n aria-busy={seg.running || undefined}\n disabled={(busy && !seg.running) || undefined}\n aria-label={seg.label}\n title={seg.label}\n className={\n seg.recording ? fabSegmentRecording : fabSegmentIdle\n }\n >\n {seg.icon}\n </button>\n </Fragment>\n ))}\n </div>\n ) : null}\n {onRequestAiDraft ? (\n <HelpMeWriteOverlay\n open={aiOpen}\n onClose={() => setAiOpen(false)}\n onRequestAiDraft={onRequestAiDraft}\n onInsert={(draft) => {\n // Restore the caret saved when the FAB opened the overlay, so\n // the draft lands where the user was, not at the doc start.\n restoreSelection();\n insertAtCursor(draft, { asHtml: aiDraftFormat !== 'text' });\n }}\n previewAsHtml={aiDraftFormat !== 'text'}\n privacyNotice={aiPrivacyNotice}\n onDictate={onDictate}\n />\n ) : null}\n </div>\n {/* Rendered LAST inside the positioned container (after the Redactor-\n managed textarea/box) so its conditional mount never asks React to\n insertBefore the textarea, which Redactor moves into its own box\n (that would throw \"node ... is not a child of this node\"). */}\n {!degraded && !readOnly && (plugins?.includes('table') ?? false) ? (\n <TableFloatingToolbar\n active={activeFormats}\n run={runCommand}\n areaRef={editorAreaRef}\n getActiveTableEl={getActiveTableEl}\n enableColor={plugins?.includes('fontcolor') ?? false}\n saveTableCell={saveTableCell}\n applyTableBackground={applyTableBackground}\n />\n ) : null}\n </div>\n {onDictate ? (\n <p className=\"ds:sr-only\" role=\"status\" aria-live=\"polite\">\n {dictationAnnouncement}\n </p>\n ) : null}\n {onDictate && dictationErrored ? (\n <p\n role=\"alert\"\n className=\"ds:text-[length:var(--font-size-sm)] ds:text-[color:var(--destructive)]\"\n >\n {t('editor.ai.dictationError')}\n </p>\n ) : null}\n </div>\n );\n },\n);\n\nRichTextEditor.displayName = 'RichTextEditor';\n\nexport { wrapperVariants };\n"],"names":["__iconNode","BetweenHorizontalEnd","createLucideIcon","BetweenHorizontalStart","BetweenVerticalEnd","BetweenVerticalStart","Bold","Heading2","Heading3","Highlighter","Italic","Link","ListOrdered","List","PaintBucket","PaintRoller","Palette","PanelTopDashed","PanelTop","Pilcrow","Quote","Rows2","SpellCheck","Strikethrough","Table","Underline","WandSparkles","Wrench","richTextEditorAgent","handle","args","RECORDING_MIC","ACTION_SIZE","noticeClass","errorClass","previewClass","joinWith","base","extra","HelpMeWriteOverlay","open","onClose","onRequestAiDraft","onInsert","previewAsHtml","privacyNotice","onDictate","t","useTranslation","promptId","useId","errorId","prompt","setPrompt","useState","loading","setLoading","errored","setErrored","draft","setDraft","abortRef","useRef","isDictating","setIsDictating","interim","setInterim","dictationAnnouncement","setDictationAnnouncement","dictateAbortRef","stopDictation","useCallback","_a","startDictation","controller","text","trimmed","p","toggleDictation","useEffect","_b","generate","result","err","insert","hasDraft","fieldValue","jsx","EditorOverlay","jsxs","IconButton","X","SafeHtml","RotateCcw","Check","Fragment","TextArea","event","Square","Mic","Spinner","Send","ITEMS","FORMAT_OPTIONS","PRESETS","TABLE_OPS","Columns2","Trash2","TABLE_GRID","toolbarClass","cva","dividerClass","fieldLabelClass","esc","value","StyleMenu","run","active","onTriggerDown","current","o","DropdownMenu","Button","ChevronDown","opt","LinkDialog","insertHtml","saveSelection","restoreSelection","getSelectedText","setOpen","url","setUrl","setText","newTab","setNewTab","urlId","textId","reset","handleInsert","href","label","tab","html","Dialog","LinkIcon","TextInput","Checkbox","checked","ImageDialog","uploadImage","src","setSrc","alt","setAlt","srcId","altId","insertImage","altText","ImageIcon","FileUpload","file","signal","ColourControl","colour","setColour","applyColour","hex","removeColour","Popover","ColorPicker","HighlightControl","applyHighlight","removeHighlight","buildTable","rows","cols","cells","TableControl","insertTable","hover","setHover","inTable","TableIcon","op","_","i","r","c","on","TABLE_OP_BY_ID","tableFloatClass","TABLE_BG_SEED","TableBgColourControl","scope","icon","onOpenChange","saveTableCell","applyTableBackground","TableFloatingToolbar","areaRef","getActiveTableEl","enableColor","pos","setPos","colourOpenCount","colourOpen","setColourOpen","handleColourOpenChange","recompute","area","table","a","rtl","top","center","ro","groups","TooltipProvider","group","gi","opId","EditorToolbar","preset","enableImage","enableTable","showExtensions","keepSelection","has","id","btn","item","Divider","styleGroup","inlineGroup","listsGroup","insertGroup","sanitiseHtml","input","sanitiseShared","normalizeEditorValue","normalized","contentWithoutTags","withLazyImages","extractUploadedUrl","data","rec","fromNode","node","resolveRedactor","injected","w","FORMAT_COMMANDS","REDACTOR_LANG","toRedactorLang","locale","wrapperVariants","degradedTextareaVariants","fabSegmentBase","fabSegmentIdle","fabSegmentRecording","RichTextEditor","forwardRef","defaultValue","onChange","toolbar","placeholder","readOnly","ariaLabel","minHeight","className","redactor","options","plugins","lang","imageUploadUrl","onKeyDown","aiDraftFormat","aiPrivacyNotice","onProofread","onAutoFormat","ref","i18n","rawId","editorId","useMemo","selector","textareaRef","redactorRef","skipNextPropSyncRef","readOnlyRef","wrapperRef","editorAreaRef","degraded","setDegraded","aiOpen","setAiOpen","activeFormats","setActiveFormats","debounceRef","onChangeRef","onKeyDownRef","initialContentRef","raw","readCode","R","code","dispatchWrite","command","wasReadOnly","insertAtCursor","content","opts","asHtml","payload","ta","start","end","caret","lastRangeRef","updateActiveFormats","root","selection","next","block","anchorEl","prev","f","runCommand","wrapper","SHORTCUT_COMMANDS","onKeyDownCapture","editable","sel","range","el","lastCellRef","getActiveCellEl","cell","targets","n","list","last","form","res","interimRef","dictationErrored","setDictationErrored","clearInterim","showInterim","oneShot","setOneShot","oneShotAbortRef","runOneShot","kind","fn","safe","cancelOneShot","kitDefaults","imageUploadOption","consumerCallbacks","finalOptions","format","useImperativeHandle","useAgentRegistration","handleDegradedChange","resolvedLabel","resolvedPlaceholder","normalise","observer","busy","fabSegments","Sparkles","seg"],"mappings":"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","x_google_ignoreList":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25]}
|