@alfadocs/ui-kit-debug 1.7.0 → 1.8.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/{anamnesis-summary-rows-F-cCmFAn.js → anamnesis-summary-rows-d44s_whc.js} +2 -2
- package/dist/_chunks/{anamnesis-summary-rows-F-cCmFAn.js.map → anamnesis-summary-rows-d44s_whc.js.map} +1 -1
- package/dist/_chunks/{antenatal-schedule-timeline-BjlF2rTz.js → antenatal-schedule-timeline-B1k8QkA6.js} +3 -3
- package/dist/_chunks/{antenatal-schedule-timeline-BjlF2rTz.js.map → antenatal-schedule-timeline-B1k8QkA6.js.map} +1 -1
- package/dist/_chunks/{appointment-card-BhcPJpXh.js → appointment-card-Dzr3GeVz.js} +73 -90
- package/dist/_chunks/appointment-card-Dzr3GeVz.js.map +1 -0
- package/dist/_chunks/{appointment-timeline-CMPvzlGZ.js → appointment-timeline-0mwtpErq.js} +3 -3
- package/dist/_chunks/{appointment-timeline-CMPvzlGZ.js.map → appointment-timeline-0mwtpErq.js.map} +1 -1
- package/dist/_chunks/{appointment-tray-3c_FLxXJ.js → appointment-tray-4FUu_5NX.js} +2 -2
- package/dist/_chunks/{appointment-tray-3c_FLxXJ.js.map → appointment-tray-4FUu_5NX.js.map} +1 -1
- package/dist/_chunks/armchair-BaLDW6Hz.js +23 -0
- package/dist/_chunks/armchair-BaLDW6Hz.js.map +1 -0
- package/dist/_chunks/{booking-CQMJUFG-.js → booking-DHkKcUIl.js} +4 -4
- package/dist/_chunks/{booking-CQMJUFG-.js.map → booking-DHkKcUIl.js.map} +1 -1
- package/dist/_chunks/{calendar-4dXTvsCz.js → calendar-B4Gnyu1C.js} +553 -437
- package/dist/_chunks/calendar-B4Gnyu1C.js.map +1 -0
- package/dist/_chunks/calendar-event-card-Bjdbik8G.js +425 -0
- package/dist/_chunks/calendar-event-card-Bjdbik8G.js.map +1 -0
- package/dist/_chunks/{care-plan-card-DQjVRDxO.js → care-plan-card-aDN4oem9.js} +3 -3
- package/dist/_chunks/{care-plan-card-DQjVRDxO.js.map → care-plan-card-aDN4oem9.js.map} +1 -1
- package/dist/_chunks/{care-plan-entry-card-CMpoeNkb.js → care-plan-entry-card-BEhANdBE.js} +2 -2
- package/dist/_chunks/{care-plan-entry-card-CMpoeNkb.js.map → care-plan-entry-card-BEhANdBE.js.map} +1 -1
- package/dist/_chunks/{care-plan-header-CxYoq23f.js → care-plan-header-CkpPyQqG.js} +2 -2
- package/dist/_chunks/{care-plan-header-CxYoq23f.js.map → care-plan-header-CkpPyQqG.js.map} +1 -1
- package/dist/_chunks/{color-picker-D-tUwxxT.js → color-picker-oZ6zYks8.js} +164 -151
- package/dist/_chunks/color-picker-oZ6zYks8.js.map +1 -0
- package/dist/_chunks/control-room-rail-Cj2iX9h_.js +337 -0
- package/dist/_chunks/control-room-rail-Cj2iX9h_.js.map +1 -0
- package/dist/_chunks/{cycle-calculator-DzgO1vzP.js → cycle-calculator-DmtYGhqq.js} +3 -3
- package/dist/_chunks/{cycle-calculator-DzgO1vzP.js.map → cycle-calculator-DmtYGhqq.js.map} +1 -1
- package/dist/_chunks/{date-picker-Bp64zk2p.js → date-picker-CepI_oI2.js} +77 -74
- package/dist/_chunks/date-picker-CepI_oI2.js.map +1 -0
- package/dist/_chunks/{date-picker-variants-pKAJfnWr.js → date-picker-variants-DfuooXEK.js} +7 -2
- package/dist/_chunks/{date-picker-variants-pKAJfnWr.js.map → date-picker-variants-DfuooXEK.js.map} +1 -1
- package/dist/_chunks/{date-range-picker-CDrZ8Zh0.js → date-range-picker-BD8P_rJq.js} +46 -45
- package/dist/_chunks/{date-range-picker-CDrZ8Zh0.js.map → date-range-picker-BD8P_rJq.js.map} +1 -1
- package/dist/_chunks/{date-time-picker-DVETwpzc.js → date-time-picker-3I2vVKGV.js} +2 -2
- package/dist/_chunks/{date-time-picker-DVETwpzc.js.map → date-time-picker-3I2vVKGV.js.map} +1 -1
- package/dist/_chunks/{due-date-calculator-wK8Tajzz.js → due-date-calculator-BF_Ikofx.js} +4 -4
- package/dist/_chunks/{due-date-calculator-wK8Tajzz.js.map → due-date-calculator-BF_Ikofx.js.map} +1 -1
- package/dist/_chunks/{entity-card-9_62gY7l.js → entity-card-DmrgYSEX.js} +4 -4
- package/dist/_chunks/{entity-card-9_62gY7l.js.map → entity-card-DmrgYSEX.js.map} +1 -1
- package/dist/_chunks/{gestational-age-calculator-C_uDAeP_.js → gestational-age-calculator-CxZelpu2.js} +5 -5
- package/dist/_chunks/{gestational-age-calculator-C_uDAeP_.js.map → gestational-age-calculator-CxZelpu2.js.map} +1 -1
- package/dist/_chunks/{hcg-doubling-BaXkJhT-.js → hcg-doubling-CpU7H5rQ.js} +3 -3
- package/dist/_chunks/{hcg-doubling-BaXkJhT-.js.map → hcg-doubling-CpU7H5rQ.js.map} +1 -1
- package/dist/_chunks/{link-cell-renderer-DH4JYpKU.js → link-cell-renderer-BZQtsuFz.js} +2 -2
- package/dist/_chunks/{link-cell-renderer-DH4JYpKU.js.map → link-cell-renderer-BZQtsuFz.js.map} +1 -1
- package/dist/_chunks/{notes-panel-DlnENphf.js → notes-panel-e9cJWVRg.js} +2 -2
- package/dist/_chunks/{notes-panel-DlnENphf.js.map → notes-panel-e9cJWVRg.js.map} +1 -1
- package/dist/_chunks/{operator-hero-CCDnIa1S.js → operator-hero-BnFv-Uef.js} +2 -2
- package/dist/_chunks/{operator-hero-CCDnIa1S.js.map → operator-hero-BnFv-Uef.js.map} +1 -1
- package/dist/_chunks/{parse-JqixfsU0.js → parse-MN9bGkrY.js} +2 -2
- package/dist/_chunks/{parse-JqixfsU0.js.map → parse-MN9bGkrY.js.map} +1 -1
- package/dist/_chunks/{patient-details-qnsqYBGQ.js → patient-details-xrqe13az.js} +160 -159
- package/dist/_chunks/patient-details-xrqe13az.js.map +1 -0
- package/dist/_chunks/{patient-table-DwshfVsQ.js → patient-table-BqYomX50.js} +2 -2
- package/dist/_chunks/{patient-table-DwshfVsQ.js.map → patient-table-BqYomX50.js.map} +1 -1
- package/dist/_chunks/{payment-automation-upsell-BBIG7NFL.js → payment-automation-upsell-DwQW2fRp.js} +52 -63
- package/dist/_chunks/payment-automation-upsell-DwQW2fRp.js.map +1 -0
- package/dist/_chunks/{payment-request-card-BjjBMdsp.js → payment-request-card-YVCcCZ25.js} +2 -2
- package/dist/_chunks/{payment-request-card-BjjBMdsp.js.map → payment-request-card-YVCcCZ25.js.map} +1 -1
- package/dist/_chunks/{pregnancy-dating-BVS_9YU2.js → pregnancy-dating-DtToyMyc.js} +5 -5
- package/dist/_chunks/{pregnancy-dating-BVS_9YU2.js.map → pregnancy-dating-DtToyMyc.js.map} +1 -1
- package/dist/_chunks/{radiograph-panel.agent-CiHwgISa.js → radiograph-panel.agent-C3trfWqB.js} +3 -3
- package/dist/_chunks/{radiograph-panel.agent-CiHwgISa.js.map → radiograph-panel.agent-C3trfWqB.js.map} +1 -1
- package/dist/_chunks/repeat-CvQa5rZt.js +17 -0
- package/dist/_chunks/repeat-CvQa5rZt.js.map +1 -0
- package/dist/_chunks/resource-chip-DYTG0IQQ.js +83 -0
- package/dist/_chunks/resource-chip-DYTG0IQQ.js.map +1 -0
- package/dist/_chunks/{rich-text-editor-DARnq_6N.js → rich-text-editor-BDfFtK4H.js} +2 -2
- package/dist/_chunks/{rich-text-editor-DARnq_6N.js.map → rich-text-editor-BDfFtK4H.js.map} +1 -1
- package/dist/_chunks/subDays-BLl3y3pd.js +8 -0
- package/dist/_chunks/{subDays-CAUv47M1.js.map → subDays-BLl3y3pd.js.map} +1 -1
- package/dist/agent-catalog.json +2 -2
- package/dist/components/_shared/date-picker-variants.d.ts.map +1 -1
- package/dist/components/appointment-card/index.js +2 -2
- package/dist/components/appointment-timeline/index.js +1 -1
- package/dist/components/booking/index.js +1 -1
- package/dist/components/calendar/calendar.agent.d.ts.map +1 -1
- package/dist/components/calendar/calendar.d.ts +138 -12
- package/dist/components/calendar/calendar.d.ts.map +1 -1
- package/dist/components/calendar/index.js +1 -1
- package/dist/components/calendar-event-card/calendar-event-card.d.ts +48 -11
- package/dist/components/calendar-event-card/calendar-event-card.d.ts.map +1 -1
- package/dist/components/calendar-event-card/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/index.js +1 -1
- package/dist/components/color-picker/index.d.ts +1 -1
- package/dist/components/color-picker/index.d.ts.map +1 -1
- package/dist/components/color-picker/index.js +4 -3
- package/dist/components/color-picker/palettes.d.ts +10 -0
- package/dist/components/color-picker/palettes.d.ts.map +1 -1
- package/dist/components/control-room-rail/control-room-rail.d.ts +9 -0
- package/dist/components/control-room-rail/control-room-rail.d.ts.map +1 -1
- package/dist/components/control-room-rail/index.js +1 -1
- package/dist/components/cycle-calculator/index.js +1 -1
- package/dist/components/data-table/index.js +1 -1
- package/dist/components/date-picker/date-picker.d.ts +11 -0
- package/dist/components/date-picker/date-picker.d.ts.map +1 -1
- package/dist/components/date-picker/index.js +1 -1
- package/dist/components/date-range-picker/date-range-picker.d.ts.map +1 -1
- package/dist/components/date-range-picker/index.js +1 -1
- package/dist/components/date-time-picker/index.js +1 -1
- package/dist/components/due-date-calculator/index.js +2 -2
- 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 +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/notes-panel/index.js +1 -1
- package/dist/components/operator-hero/index.js +1 -1
- package/dist/components/patient-details/index.js +1 -1
- package/dist/components/patient-details/patient-details.d.ts +8 -0
- package/dist/components/patient-details/patient-details.d.ts.map +1 -1
- package/dist/components/patient-table/index.js +1 -1
- package/dist/components/payment-card/index.js +1 -1
- package/dist/components/pregnancy-dating/index.js +1 -1
- package/dist/components/radiograph-panel/index.js +1 -1
- package/dist/components/resource-chip/index.d.ts +3 -0
- package/dist/components/resource-chip/index.d.ts.map +1 -0
- package/dist/components/resource-chip/index.js +5 -0
- package/dist/components/resource-chip/index.js.map +1 -0
- package/dist/components/resource-chip/resource-chip.d.ts +26 -0
- package/dist/components/resource-chip/resource-chip.d.ts.map +1 -0
- package/dist/components/rich-text-editor/index.js +1 -1
- package/dist/host-compat.css +7 -1
- package/dist/i18n/locales/ar.d.ts +4 -0
- package/dist/i18n/locales/ar.d.ts.map +1 -1
- package/dist/i18n/locales/ar.js +4 -0
- package/dist/i18n/locales/ar.js.map +1 -1
- package/dist/i18n/locales/de.d.ts +4 -0
- package/dist/i18n/locales/de.d.ts.map +1 -1
- package/dist/i18n/locales/de.js +4 -0
- package/dist/i18n/locales/de.js.map +1 -1
- package/dist/i18n/locales/el.d.ts +4 -0
- package/dist/i18n/locales/el.d.ts.map +1 -1
- package/dist/i18n/locales/el.js +4 -0
- package/dist/i18n/locales/el.js.map +1 -1
- package/dist/i18n/locales/en.d.ts +4 -0
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/en.js +4 -0
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +4 -0
- package/dist/i18n/locales/es.d.ts.map +1 -1
- package/dist/i18n/locales/es.js +4 -0
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +4 -0
- package/dist/i18n/locales/fr.d.ts.map +1 -1
- package/dist/i18n/locales/fr.js +4 -0
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hi.d.ts +4 -0
- package/dist/i18n/locales/hi.d.ts.map +1 -1
- package/dist/i18n/locales/hi.js +4 -0
- package/dist/i18n/locales/hi.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +4 -0
- package/dist/i18n/locales/it.d.ts.map +1 -1
- package/dist/i18n/locales/it.js +4 -0
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/ja.d.ts +4 -0
- package/dist/i18n/locales/ja.d.ts.map +1 -1
- package/dist/i18n/locales/ja.js +4 -0
- package/dist/i18n/locales/ja.js.map +1 -1
- package/dist/i18n/locales/nl.d.ts +4 -0
- package/dist/i18n/locales/nl.d.ts.map +1 -1
- package/dist/i18n/locales/nl.js +4 -0
- package/dist/i18n/locales/nl.js.map +1 -1
- package/dist/i18n/locales/pl.d.ts +4 -0
- package/dist/i18n/locales/pl.d.ts.map +1 -1
- package/dist/i18n/locales/pl.js +4 -0
- package/dist/i18n/locales/pl.js.map +1 -1
- package/dist/i18n/locales/pt.d.ts +4 -0
- package/dist/i18n/locales/pt.d.ts.map +1 -1
- package/dist/i18n/locales/pt.js +4 -0
- package/dist/i18n/locales/pt.js.map +1 -1
- package/dist/i18n/locales/ro.d.ts +4 -0
- package/dist/i18n/locales/ro.d.ts.map +1 -1
- package/dist/i18n/locales/ro.js +4 -0
- package/dist/i18n/locales/ro.js.map +1 -1
- package/dist/i18n/locales/ru.d.ts +4 -0
- package/dist/i18n/locales/ru.d.ts.map +1 -1
- package/dist/i18n/locales/ru.js +4 -0
- package/dist/i18n/locales/ru.js.map +1 -1
- package/dist/i18n/locales/sq.d.ts +4 -0
- package/dist/i18n/locales/sq.d.ts.map +1 -1
- package/dist/i18n/locales/sq.js +4 -0
- package/dist/i18n/locales/sq.js.map +1 -1
- package/dist/i18n/locales/sv.d.ts +4 -0
- package/dist/i18n/locales/sv.d.ts.map +1 -1
- package/dist/i18n/locales/sv.js +4 -0
- package/dist/i18n/locales/sv.js.map +1 -1
- package/dist/i18n/locales/tr.d.ts +4 -0
- package/dist/i18n/locales/tr.d.ts.map +1 -1
- package/dist/i18n/locales/tr.js +4 -0
- package/dist/i18n/locales/tr.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +4 -0
- package/dist/i18n/locales/zh.d.ts.map +1 -1
- package/dist/i18n/locales/zh.js +4 -0
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/index.js +961 -958
- package/dist/index.js.map +1 -1
- package/dist/locales/ar.json +4 -0
- package/dist/locales/de.json +4 -0
- package/dist/locales/el.json +4 -0
- package/dist/locales/en.json +4 -0
- package/dist/locales/es.json +4 -0
- package/dist/locales/fr.json +4 -0
- package/dist/locales/hi.json +4 -0
- package/dist/locales/it.json +4 -0
- package/dist/locales/ja.json +4 -0
- package/dist/locales/nl.json +4 -0
- package/dist/locales/pl.json +4 -0
- package/dist/locales/pt.json +4 -0
- package/dist/locales/ro.json +4 -0
- package/dist/locales/ru.json +4 -0
- package/dist/locales/sq.json +4 -0
- package/dist/locales/sv.json +4 -0
- package/dist/locales/tr.json +4 -0
- package/dist/locales/zh.json +4 -0
- package/dist/patterns/anamnesis/index.js +1 -1
- package/dist/patterns/payment-automation-upsell/index.js +1 -1
- package/dist/tokens.css +40 -24
- package/package.json +5 -1
- package/dist/_chunks/appointment-card-BhcPJpXh.js.map +0 -1
- package/dist/_chunks/calendar-4dXTvsCz.js.map +0 -1
- package/dist/_chunks/calendar-event-card-C6qGtywL.js +0 -257
- package/dist/_chunks/calendar-event-card-C6qGtywL.js.map +0 -1
- package/dist/_chunks/color-picker-D-tUwxxT.js.map +0 -1
- package/dist/_chunks/control-room-rail-IH1eBjrK.js +0 -333
- package/dist/_chunks/control-room-rail-IH1eBjrK.js.map +0 -1
- package/dist/_chunks/date-picker-Bp64zk2p.js.map +0 -1
- package/dist/_chunks/patient-details-qnsqYBGQ.js.map +0 -1
- package/dist/_chunks/payment-automation-upsell-BBIG7NFL.js.map +0 -1
- package/dist/_chunks/subDays-CAUv47M1.js +0 -8
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar-B4Gnyu1C.js","sources":["../../src/components/calendar/calendar.agent.ts","../../src/components/calendar/calendar.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — Calendar. */\n/* */\n/* Calendar's existing `CalendarHandle` is the canonical shape for an */\n/* agent-friendly third-party wrapper — see `26-agent-readiness.mdx` */\n/* §15. The handle methods translate directly into adapter actions. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { CalendarHandle, CalendarView } from './calendar';\n\nexport const calendarAgent: AgentAdapter<CalendarHandle> = {\n id: 'calendar',\n capabilities: ['view_change', 'range_navigate', 'pick'],\n state: {\n currentView: {\n type: 'CalendarView',\n descriptionKey: 'ui.agent.calendar.state.currentView',\n description: 'Active view name (e.g. dayGridMonth, timeGridWeek).',\n read: (handle) => handle.getCurrentView() ?? null,\n },\n currentDate: {\n type: 'iso-date',\n descriptionKey: 'ui.agent.calendar.state.currentDate',\n description: 'ISO date anchor of the visible range.',\n read: (handle) => handle.getCurrentDate()?.toISOString() ?? null,\n },\n currentTitle: {\n type: 'string',\n descriptionKey: 'ui.agent.calendar.state.currentTitle',\n description: 'Human title of the current range (e.g. \"April 2026\").',\n read: (handle) => handle.getTitle(),\n },\n },\n actions: {\n today: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.calendar.actions.today',\n description: 'Jump to the current day.',\n invoke: (handle) => {\n handle.today();\n },\n },\n prev: {\n // Not idempotent: each call steps one range further back.\n safety: 'read',\n descriptionKey: 'ui.agent.calendar.actions.prev',\n description: 'Move to the previous range.',\n invoke: (handle) => {\n handle.prev();\n },\n },\n next: {\n // Not idempotent: each call steps one range further forward.\n safety: 'read',\n descriptionKey: 'ui.agent.calendar.actions.next',\n description: 'Move to the next range.',\n invoke: (handle) => {\n handle.next();\n },\n },\n goto_date: {\n safety: 'read',\n argsType: '{ date: string | Date }',\n argsSchema: {\n type: 'object',\n properties: {\n date: {\n type: 'string',\n format: 'date',\n description: 'Target date — ISO 8601 string (or Date at runtime).',\n },\n },\n required: ['date'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.calendar.actions.gotoDate',\n description: 'Navigate to a specific date.',\n examples: [\n { args: { date: '2026-04-15' }, note: 'Jump to 15 April 2026.' },\n ],\n invoke: (handle, args: { date: string | Date }) => {\n handle.gotoDate(args.date);\n },\n },\n change_view: {\n safety: 'read',\n argsType: '{ view: CalendarView }',\n argsSchema: {\n type: 'object',\n properties: {\n view: {\n type: 'string',\n enum: [\n 'dayGridMonth',\n 'timeGridWeek',\n 'timeGridDay',\n 'listWeek',\n 'resourceTimeGridDayChair',\n 'resourceTimeGridThreeDaysChair',\n 'resourceTimeGridWeekChair',\n 'resourceTimeGridDayOperator',\n 'resourceTimeGridThreeDaysOperator',\n 'resourceTimeGridWeekOperator',\n ],\n description: 'Target view name.',\n },\n },\n required: ['view'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.calendar.actions.changeView',\n description: 'Switch the calendar to the given view.',\n examples: [\n { args: { view: 'timeGridWeek' }, note: 'Switch to the week view.' },\n ],\n invoke: (handle, args: { view: CalendarView }) => {\n handle.changeView(args.view);\n },\n },\n focus_event: {\n // pick: transient focus + highlight of an event — no persisted selection.\n // Not idempotent: each call re-triggers the flash highlight.\n safety: 'read',\n argsType: '{ eventId: string }',\n argsSchema: {\n type: 'object',\n properties: {\n eventId: {\n type: 'string',\n description: 'Stable event id (matches a data-event-id node).',\n },\n },\n required: ['eventId'],\n },\n descriptionKey: 'ui.agent.calendar.actions.focusEvent',\n description: 'Scroll an event into view and briefly highlight it.',\n errors: ['No DOM node matches the given event id — no-op.'],\n invoke: (handle, args: { eventId: string }) => {\n handle.focusEvent(args.eventId);\n },\n },\n },\n /* Day-number nav links (`a[data-navlink]`, via onNavLinkDayClick) are\n FullCalendar markup, not a hook: an agent drills into a day through\n the host's own view change, never by clicking the number. */\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'calendar',\n description: 'Marks the Calendar wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop.',\n },\n item: {\n attr: 'data-event-id',\n description:\n 'Emitted on every rendered FullCalendar event by the kit event renderer. Used by focusEvent. Cards also carry data-kind=\"task\"|\"draft\"|\"appointment\" and data-status for classification.',\n },\n },\n};\n","/* ------------------------------------------------------------------ */\n/* Calendar — a thin, typed wrapper over FullCalendar. */\n/* */\n/* - Plugins are registered once internally so consumers never import */\n/* `@fullcalendar/core` / plugins directly (08-third-party §Calendar).*/\n/* - Chrome is styled entirely from `fullcalendar-theme.css` via the */\n/* `.fc-theme-alfadocs` root class — no inline styles anywhere. */\n/* - Locale, week-start, date formats, and direction all flow from the */\n/* active i18next language (06-i18n.mdx). */\n/* */\n/* TODO (deferred, per implementation plan): */\n/* - Virtualised resource timeline with @tanstack/react-virtual for */\n/* > 50 resources (performance user story) — go/no-go from the */\n/* measured PerformanceEnvelope numbers (story + calendar.test.tsx).*/\n/* - Protanopia screenshot stories (colour-blind story acceptance). */\n/* ------------------------------------------------------------------ */\n\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport { useTranslation } from 'react-i18next';\nimport FullCalendar from '@fullcalendar/react';\nimport dayGridPlugin from '@fullcalendar/daygrid';\nimport timeGridPlugin from '@fullcalendar/timegrid';\nimport listPlugin from '@fullcalendar/list';\nimport resourcePlugin from '@fullcalendar/resource';\nimport type { ResourceLabelContentArg } from '@fullcalendar/resource';\nimport resourceTimeGridPlugin from '@fullcalendar/resource-timegrid';\nimport resourceTimelinePlugin from '@fullcalendar/resource-timeline';\nimport timelinePlugin from '@fullcalendar/timeline';\nimport interactionPlugin from '@fullcalendar/interaction';\nimport type {\n DateClickArg,\n EventResizeDoneArg,\n} from '@fullcalendar/interaction';\nimport type {\n CalendarOptions,\n DatesSetArg,\n DayCellContentArg,\n DayHeaderContentArg,\n DayHeaderMountArg,\n EventClickArg,\n EventContentArg,\n EventDropArg,\n EventHoveringArg,\n DateSelectArg,\n EventInput,\n FormatterInput,\n} from '@fullcalendar/core';\nimport { Check, ChevronLeft, ChevronRight } from 'lucide-react';\nimport '../../tokens/themes/bridges/fullcalendar-theme.css';\n\nimport { usePrefersReducedMotion } from '../../hooks';\nimport { useAgentRegistration } from '../../agent';\nimport { warnLowContrast } from '../_shared/contrast-warning';\nimport { Avatar } from '../avatar/avatar';\nimport { ResourceChip } from '../resource-chip/resource-chip';\nimport { Tooltip } from '../tooltip';\nimport { CalendarEventCard } from '../calendar-event-card';\nimport { calendarAgent } from './calendar.agent';\n\n/* ------------------------------------------------------------------ */\n/* Public types */\n/* ------------------------------------------------------------------ */\n\nexport type CalendarView =\n // Standard views\n | 'dayGridMonth'\n | 'timeGridWeek'\n | 'timeGridThreeDays'\n | 'timeGridDay'\n | 'listWeek'\n // Chair resource views\n | 'resourceTimeGridDayChair'\n | 'resourceTimeGridThreeDaysChair'\n | 'resourceTimeGridWeekChair'\n // Operator resource views\n | 'resourceTimeGridDayOperator'\n | 'resourceTimeGridThreeDaysOperator'\n | 'resourceTimeGridWeekOperator';\n\n/**\n * View-name mapping table — maps the DS public view name (with the\n * Chair/Operator semantic suffix stripped) onto the internal FullCalendar\n * view name for each `resourceLayout` orientation. The table is exported\n * via `resolveFullCalendarView`; invalid combinations are caught at\n * compile time because the `CalendarView` union is exhaustive.\n */\nconst RESOURCE_VIEW_MAP = {\n vertical: {\n Day: 'resourceTimeGridDay',\n ThreeDays: 'resourceTimeGridThreeDays',\n Week: 'resourceTimeGridWeek',\n },\n horizontal: {\n Day: 'resourceTimelineDay',\n ThreeDays: 'resourceTimelineThreeDays',\n Week: 'resourceTimelineWeek',\n },\n} as const satisfies Record<\n 'vertical' | 'horizontal',\n Record<'Day' | 'ThreeDays' | 'Week', string>\n>;\n\ntype ResourceViewStem = keyof (typeof RESOURCE_VIEW_MAP)['vertical'];\n\nconst STANDARD_VIEWS = new Set<CalendarView>([\n 'dayGridMonth',\n 'timeGridWeek',\n 'timeGridThreeDays',\n 'timeGridDay',\n 'listWeek',\n]);\n\n/**\n * Horizontal counterparts of the plain (non-resource) time views —\n * mirrors the platform's per-user calendarResourceView='horizontal'\n * setting (NewCalendar/Library.js translateView): agendaDay→timelineDay,\n * agendaWeek→timelineWeek. dayGridMonth and listWeek have no horizontal\n * counterpart on the platform either.\n */\nconst STANDARD_HORIZONTAL_VIEW_MAP: Partial<Record<CalendarView, string>> = {\n timeGridDay: 'timelineDay',\n timeGridThreeDays: 'timelineThreeDays',\n timeGridWeek: 'timelineWeek',\n};\n\n/**\n * Maps a public `CalendarView` name to the internal FullCalendar view\n * name. `resourceLayout` selects between `resourceTimeGrid*` (vertical)\n * and `resourceTimeline*` (horizontal) for the 6 resource views. The\n * 4 standard views resolve as-is under `vertical`; under `horizontal`,\n * `timeGridDay` / `timeGridWeek` resolve to the plain `timelineDay` /\n * `timelineWeek` timelines (platform calendarResourceView parity), while\n * `dayGridMonth` / `listWeek` are orientation-free and pass through.\n */\nexport function resolveFullCalendarView(\n view: CalendarView,\n resourceLayout: 'vertical' | 'horizontal' = 'vertical',\n): string {\n if (STANDARD_VIEWS.has(view)) {\n if (resourceLayout === 'horizontal') {\n return STANDARD_HORIZONTAL_VIEW_MAP[view] ?? view;\n }\n return view;\n }\n // Strip the trailing Chair / Operator suffix — the DS maps both to the\n // same internal FC view name. The suffix is semantic only.\n const withoutPrefix = view.replace(/^resourceTimeGrid/, '');\n const stem = withoutPrefix.replace(\n /(Chair|Operator)$/,\n '',\n ) as ResourceViewStem;\n return RESOURCE_VIEW_MAP[resourceLayout][stem];\n}\n\n/* Day-level views title as a full date (platform Toolbar.js — computed\n there from the middle of the range with moment 'dddd DD. MMMM YYYY';\n here FC's native range titling + Intl, locale-correct, no moment). */\nconst DAY_TITLE_FORMAT: FormatterInput = {\n weekday: 'long',\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n};\n\n/* Two-row header for horizontal timeline views — top row: date, bottom\n row: time (platform App.js:762). Vertical views keep the single-object\n top-level slotLabelFormat. */\nconst TIMELINE_SLOT_LABEL_FORMAT: FormatterInput[] = [\n { weekday: 'short', day: 'numeric', month: 'short' },\n { hour: 'numeric', minute: '2-digit' },\n];\n\n/**\n * Per-view FullCalendar config: the two custom 3-day views, the\n * timeline-wide two-row slot labels (inherited by every timeline view\n * incl. resourceTimeline* via FC's superType chain), and the day-level\n * full-date titles. Views-hash entries take precedence over the\n * top-level titleFormat / slotLabelFormat props (FC option merge order).\n */\nconst CALENDAR_VIEW_OPTIONS: CalendarOptions['views'] = {\n resourceTimeGridThreeDays: {\n type: 'resourceTimeGrid',\n duration: { days: 3 },\n },\n resourceTimelineThreeDays: {\n type: 'resourceTimeline',\n duration: { days: 3 },\n },\n /* Plain (non-resource) 3-day counterparts — the standard calendar\n experience's Day / 3 days / Week range set without an axis. */\n timeGridThreeDays: {\n type: 'timeGrid',\n duration: { days: 3 },\n },\n timelineThreeDays: {\n type: 'timeline',\n duration: { days: 3 },\n },\n timeline: { slotLabelFormat: TIMELINE_SLOT_LABEL_FORMAT },\n timeGridDay: { titleFormat: DAY_TITLE_FORMAT },\n resourceTimeGridDay: { titleFormat: DAY_TITLE_FORMAT },\n timelineDay: { titleFormat: DAY_TITLE_FORMAT },\n resourceTimelineDay: { titleFormat: DAY_TITLE_FORMAT },\n};\n\nexport type CalendarEventStatus =\n | 'confirmed'\n | 'waiting'\n | 'in_care'\n | 'done'\n | 'cancelled'\n | 'absent';\n\nexport type CalendarMode = 'default' | 'create' | 'move' | 'copy';\n\nexport interface CalendarEvent {\n id: string;\n title: string;\n start: string | Date;\n end?: string | Date;\n resourceId?: string;\n allDay?: boolean;\n\n /* Appointment-specific (all optional) */\n status?: CalendarEventStatus;\n /** Hex colour from the consumer's colour picker — paints the card surface. */\n backgroundColor?: string;\n /** Hex colour paired with `backgroundColor` — paints the card text. */\n textColor?: string;\n /**\n * Optional hex border for light backgrounds. The platform emits\n * '#cccccc' when backgroundColor is '#ffffff' and omits it otherwise.\n * Pass together with backgroundColor.\n */\n borderColor?: string;\n /** Extra description rendered after the title in normal weight. */\n suffix?: string;\n /** Masked title shown when `privacyMode` is true. */\n privacyModeTitle?: string;\n /** Shows a Globe icon + zebra overlay. */\n isBookedOnline?: boolean;\n /** Shows an AlertTriangle icon. */\n hasUnassignedPatient?: boolean;\n /** Shows a HeartPulse icon. */\n hasHighlightedAnamnesis?: boolean;\n /** Shows a Euro icon. */\n hasBillableAmount?: boolean;\n /** Shows a Video icon. */\n isTelehealth?: boolean;\n /**\n * Shows a Repeat icon — this event belongs to a repeating series. Set\n * it on EVERY occurrence: it answers \"does moving or deleting this\n * touch other appointments?\", which holds for a modified occurrence\n * too. Distinct from `isRecurrenceParent`, which is the series ROLE.\n */\n isRecurring?: boolean;\n /**\n * Series ROLE — this row owns the recurrence rule (the others are\n * generated from it, or are overrides of one occurrence). Carried\n * through `onEventClick` so a consumer can branch its\n * this / this-and-following / all dialog on it. Renders nothing on its\n * own: use `isRecurring` for the grid indicator.\n */\n isRecurrenceParent?: boolean;\n /** Rendered as a background event; not clickable. */\n isInternal?: boolean;\n /**\n * Renders the card as a TASK rather than an appointment — calendar-scheduled\n * to-dos get their own treatment: dashed outline, muted default surface\n * (explicit `backgroundColor`/`textColor` still win), a leading clipboard\n * glyph, and a localised \"task\" word in the accessible name. Emitted as\n * `data-kind=\"task\"` on the card for DOM hooks.\n */\n isTask?: boolean;\n /**\n * Draft placeholder — an appointment being COMPOSED, not yet saved.\n * Renders with the card's dashed primary-tinted draft treatment\n * (`data-kind=\"draft\"`) and is inert: no click, no hover callback, and\n * never draggable, so a mirrored slot cannot be mistaken for a booking\n * or dragged around. Use it to show which slot an open editor is\n * filling.\n */\n isDraft?: boolean;\n /**\n * Per-event master switch for drag AND resize. Overrides the\n * calendar-level `editable` for this event only (true enables even when\n * the calendar is not editable; false disables both gestures).\n * Leave undefined to inherit the calendar-level setting.\n * Precedence: per-event `startEditable` > per-event `editable` >\n * calendar-level `editable`. Background events (`isInternal: true`)\n * are never draggable regardless.\n */\n editable?: boolean;\n /**\n * Per-event drag (start-time) editability. `false` pins the event in\n * place while the rest of the calendar stays draggable — the platform's\n * closed-day / holiday / operator-absence all-day events use exactly\n * this. Does not affect resize. Leave undefined to inherit.\n */\n startEditable?: boolean;\n patientId?: string | number;\n operatorId?: string | number;\n}\n\nexport interface CalendarResource {\n id: string;\n title: string;\n /** @deprecated Unused by the label renderer — the person treatment now\n * derives initials from `title` via the kit Avatar. Kept for API\n * compatibility. */\n shortTitle?: string;\n /** Hex colour for the dot (text variant) / ResourceChip glyph circle. */\n color?: string;\n /** @deprecated Unused — the Avatar derives its own accessible ink. */\n shortTitleTextColor?: string;\n /**\n * Person photo for the Avatar treatment (`showResourceInitials`). Falls\n * back to the deterministic initials circle when omitted.\n */\n avatarSrc?: string;\n /** Numeric ordering — passed to FullCalendar's `resourceOrder`. */\n sequenceNumber?: number;\n /**\n * ISO local dates ('YYYY-MM-DD') on which this resource's column is\n * hidden in VERTICAL resource views — visible Monday, hidden Tuesday,\n * within one multi-day view (the platform's show-only-available-\n * operators feature: `operatorDatesToHide` maps here 1:1). The column\n * (header cell, all-day cell, timed body column) is removed from\n * layout, hit-testing, and the accessibility tree for those dates\n * only; remaining columns share the freed width, and the date-header\n * cell's span is adjusted internally. When EVERY resource hides a\n * date, the whole date column collapses. Omitted / empty = always\n * visible — an available-but-empty resource keeps its column simply\n * by being in `resources` (no dummy events needed).\n *\n * Scope: `resourceTimeGrid*` views with `datesAboveResources` (the\n * default) only. Documented no-op for `resourceLayout='horizontal'`\n * (a timeline row spans all dates — no per-date geometry; matches the\n * platform, where the feature is inert in timelines) and for\n * non-resource views. `hiddenDays` wins: entries on never-rendered\n * weekdays are silently ignored.\n *\n * Update this atomically with `events`/`resources` (one commit) —\n * the kit derives everything else, so there is no loading-flash\n * window to suppress.\n */\n hiddenDates?: readonly string[];\n}\n\nexport interface CalendarEventDropInfo {\n event: CalendarEvent;\n oldStart: Date;\n newStart: Date;\n /**\n * Resource the event sat on before and after the drop, in resource\n * views. Read these for cross-column moves — `event.resourceId` comes\n * from `extendedProps`, which FullCalendar does NOT rewrite on a\n * resource change, so it still reports the ORIGINAL column.\n * Both are undefined in non-resource views.\n */\n oldResourceId?: string;\n newResourceId?: string;\n /**\n * Restores FullCalendar's optimistic move — the platform's\n * confirm-modal pattern calls this on Cancel instead of committing.\n * Typed optional for backward compatibility of consumer-constructed\n * literals; the kit ALWAYS supplies it at runtime.\n * Lifetime: call at most once, and only BEFORE you replace the\n * `events` prop — once new event data re-parses, `revert()` refers to\n * a stale store and must not be called.\n */\n revert?: () => void;\n}\n\nexport interface CalendarEventResizeInfo {\n event: CalendarEvent;\n oldEnd: Date;\n newEnd: Date;\n /** Same contract as `CalendarEventDropInfo.revert`. */\n revert?: () => void;\n}\n\nexport interface CalendarDateSelectInfo {\n start: Date;\n end: Date;\n allDay: boolean;\n resourceId?: string;\n}\n\n/**\n * Payload for `onDatesSet` — fired whenever the visible date range changes:\n * initial mount, prev/next/today, `gotoDate`, `changeView`, and any option\n * change that re-windows the range (e.g. `hiddenDays`). Everything a\n * data-pipeline consumer needs (range-scoped refetch, slot re-windowing,\n * per-user view persistence, analytics) without touching FullCalendar types.\n */\nexport interface CalendarDatesSetInfo {\n /**\n * The public view name — echoes the `view` prop as currently rendered.\n * Caveat: if you switch views through the imperative handle\n * (`changeView`) without updating the `view` prop, this echo goes stale;\n * use `internalView` (always live) or `handle.getCurrentView()` instead.\n */\n view: CalendarView;\n /**\n * The live internal FullCalendar view name (e.g. `'resourceTimeGridDay'`,\n * `'dayGridMonth'`). Always reflects what is actually rendered. Note the\n * Chair/Operator suffix of the public union does not exist here — both\n * map to the same internal view.\n */\n internalView: string;\n /** Inclusive start of the visible range. */\n start: Date;\n /** EXCLUSIVE end of the visible range (FullCalendar convention). */\n end: Date;\n /** The calendar's current date anchor (`getDate()`), i.e. the focused day. */\n currentDate: Date;\n /**\n * Localised human title of the range (e.g. \"April 2026\", or\n * \"Wednesday, April 15, 2026\" in day-level views).\n */\n title: string;\n}\n\n/**\n * Payload for `onDateClick` — a SINGLE click on a date/slot, distinct\n * from the click-drag range selection delivered via `onDateSelect`.\n */\nexport interface CalendarDateClickInfo {\n /**\n * The clicked date-time. For all-day cells this is local midnight of\n * the clicked day.\n */\n date: Date;\n /** True when the click landed on an all-day cell / whole-day slot. */\n allDay: boolean;\n /** Resource id when the click landed inside a resource column/lane. */\n resourceId?: string;\n}\n\n/**\n * DOM metadata delivered as the optional second argument of\n * `onEventClick` — the anchor surface for detail popovers.\n */\nexport interface CalendarEventClickMeta {\n /**\n * The event's rendered root element (FullCalendar's `a.fc-event`\n * harness). OWNED BY FULLCALENDAR: it is destroyed and re-created on\n * every re-render — range navigation, `events` prop changes, theme\n * repaints, polling refreshes. Do not hold it across renders. Anchor\n * a popover to it for the current render only, and re-anchor (or\n * close) on `onDatesSet` and whenever the `events` prop changes; to\n * re-find the element later use\n * `rootElement.querySelector('[data-event-id=\"<id>\"]')` or\n * `handle.focusEvent(id)`.\n */\n el: HTMLElement;\n /**\n * The native event that triggered the click. Caveat: FullCalendar\n * types this `MouseEvent` but delivers the raw `KeyboardEvent` when\n * an event card is activated with Enter/Space — do not position by\n * `clientX`/`clientY`; anchor to `el` instead (always safe).\n */\n jsEvent: MouseEvent;\n}\n\nexport interface CalendarProps {\n /**\n * Stable identifier for this calendar instance. Used for the agent-readiness\n * `data-component-id` attribute and the agent registry. Required only when\n * the consuming app expects an MCP / agent integration to address this\n * specific calendar.\n */\n id?: string;\n /** Events to render on the calendar. */\n events: CalendarEvent[];\n /** Resources for `resourceTimeline` view. */\n resources?: CalendarResource[];\n /** Active view. */\n view?: CalendarView;\n /** Initial date (string or Date). */\n initialDate?: string | Date;\n /** Locale override — defaults to the active i18next language. */\n locale?: string;\n /** Fires when an event is dragged to a new slot. */\n onEventDrop?: (info: CalendarEventDropInfo) => void;\n /** Fires when an event is resized. */\n onEventResize?: (info: CalendarEventResizeInfo) => void;\n /**\n * Fires when an event drag gesture begins — before any drop/revert\n * decision. Mirror of `onEventResizeStart`. Use it to pause polling /\n * auto-refresh and dismiss anchored popovers while the user is dragging.\n * Caveat: the kit does not currently expose a \"drag stopped\" callback\n * (FullCalendar has one — `eventDragStop`, which fires even for drags\n * aborted with Escape or dropped on an invalid slot — it is just not\n * surfaced yet). A cancelled drag never reaches `onEventDrop`, so\n * consumers pausing auto-refresh here should also resume it from\n * `onDatesSet` / a timeout fallback, not only from `onEventDrop`.\n */\n onEventDragStart?: () => void;\n /** Fires when an event resize gesture begins. */\n onEventResizeStart?: () => void;\n /**\n * Fires when an event is clicked. The optional second argument exposes\n * the event's DOM element and the native mouse event for popover\n * anchoring — see `CalendarEventClickMeta` for the anchor-lifetime\n * caveat. Existing one-argument handlers keep working unchanged.\n */\n onEventClick?: (event: CalendarEvent, meta?: CalendarEventClickMeta) => void;\n /**\n * Fires when the pointer enters an event's rendered surface — the anchor\n * seam for hover \"peek\" cards. Skipped for background events\n * (`isInternal`). The meta carries the same anchor-lifetime caveats as\n * `onEventClick` — see `CalendarEventClickMeta`. Pointer-only by nature:\n * pair any hover surface with a click/focus path (`onEventClick`) so the\n * same information stays reachable by keyboard.\n */\n onEventMouseEnter?: (\n event: CalendarEvent,\n meta: CalendarEventClickMeta,\n ) => void;\n /**\n * Fires when the pointer leaves an event's rendered surface. Skipped for\n * background events, mirroring `onEventMouseEnter`.\n */\n onEventMouseLeave?: (event: CalendarEvent) => void;\n /** Fires when the user click-drags a range to create a new event. */\n onDateSelect?: (range: CalendarDateSelectInfo) => void;\n /**\n * Fires whenever the visible date range changes — on mount, on every\n * prev/next/today/gotoDate/changeView, and when options re-window the\n * range. This is the hook for range-scoped data fetching (fetch events\n * for [start, end) and abort the previous request), view persistence,\n * and analytics. Fires once on initial render.\n *\n * Caveat: FullCalendar can RE-FIRE this with an IDENTICAL range when a\n * parent re-render reaches its option diff (render-prop identities\n * churn). Key side effects on the range actually changing — e.g. compare\n * `start`/`end`/`internalView` against the last invocation — and never\n * feed each `currentDate` back into `initialDate` (a fresh Date identity\n * per echo loops the render).\n */\n onDatesSet?: (info: CalendarDatesSetInfo) => void;\n /**\n * Fires on a single click on an empty date/slot (the platform's\n * \"click to create appointment\" entry point). Distinct from\n * `onDateSelect`, which fires for click-drag range selection.\n * Works in every view INCLUDING the all-day lane of vertical resource\n * views — FullCalendar's native `dateClick` does not fire there, so the\n * wrapper synthesizes the payload internally; consumers never need the\n * native-listener workaround the platform carries.\n */\n onDateClick?: (info: CalendarDateClickInfo) => void;\n /**\n * Day-number nav links (FullCalendar `navLinks`). When set, every\n * daygrid day number renders as a keyboard-reachable control (Tab,\n * Enter / Space, click) that fires this handler instead of\n * FullCalendar's own day zoom — the host switches its view, so\n * a Month → Day drill-down needs no pointer.\n */\n onNavLinkDayClick?: (date: Date, jsEvent: UIEvent) => void;\n /** Allow drag-drop rescheduling. */\n editable?: boolean;\n /** Allow resize gestures on events. Defaults to `editable`. */\n eventDurationEditable?: boolean;\n /** Allow click-drag to create. */\n selectable?: boolean;\n /** Height of the calendar. */\n height?: number | string;\n /** Extra class names on the wrapper. */\n className?: string;\n /** Mask patient titles — announces state changes via aria-live. */\n privacyMode?: boolean;\n /**\n * Colour scheme for event cards. `'solid'` (default, platform parity)\n * paints the picker hex across the whole card with auto-derived ink;\n * `'tinted'` renders the chip-family scheme — the picker colour as a\n * SOLID BORDER over a light tint of itself, text on foreground tokens.\n * Forwarded to every `CalendarEventCard`; tasks keep their muted\n * treatment regardless.\n */\n eventColorStyle?: 'solid' | 'tinted';\n /** Interaction mode — renders a sticky banner when not `'default'`. */\n mode?: CalendarMode;\n /** Override text for the mode banner. */\n modeLabel?: string;\n /** Hex background colour for the mode banner (consuming-app supplied). */\n modeBannerColor?: string;\n /** Hex text colour for the mode banner. */\n modeBannerTextColor?: string;\n /** Cancel handler wired to the mode banner button. */\n onModeCancel?: () => void;\n /** Optional alert banner rendered above the mode banner. */\n alertBanner?: ReactNode;\n /**\n * Weekdays to hide entirely, in JavaScript day numbering:\n * 0 = Sunday … 6 = Saturday (e.g. `[0]` hides Sundays — the AlfaDocs\n * platform default for every practice user). NOTE: the platform stores\n * ISO day numbers (1 = Monday … 7 = Sunday) per user and converts to JS\n * numbering consumer-side (`Settings.php` does `$day % 7`) — this prop\n * takes the JS-numbered result only; the kit performs no conversion.\n * Omitted / empty array shows all seven days.\n */\n hiddenDays?: number[];\n /** Lower bound of the time axis (e.g. '07:00'). */\n slotMinTime?: string;\n /** Upper bound of the time axis (e.g. '23:00'). */\n slotMaxTime?: string;\n /** Slot duration (e.g. '00:15'). */\n slotDuration?: string;\n /**\n * Granularity drag and resize SNAP to, independent of the visual slot\n * height (e.g. a 30-minute grid that still edits in 15-minute steps —\n * the convention in Google Calendar and Outlook). Defaults to\n * `slotDuration` when omitted, which is FullCalendar's own default.\n */\n snapDuration?: string;\n /** When false, hides the inline time pill on events. */\n showTime?: boolean;\n /** Place date headers above the resource axis. */\n datesAboveResources?: boolean;\n /** Allow overlapping events in the same slot. */\n slotEventOverlap?: boolean;\n /** Keep date headers pinned during scroll. */\n stickyHeaderDates?: boolean;\n /** Show a now-indicator line on time-grid views. */\n nowIndicator?: boolean;\n /** Collapse overflow events into \"+N more\" links. */\n dayMaxEvents?: boolean | number;\n /**\n * FullCalendar Scheduler premium license key. Required for the\n * `resourceTimeline` view. Defaults to `VITE_FULLCALENDAR_LICENSE_KEY`\n * from the environment; consumers can override per-instance.\n */\n schedulerLicenseKey?: string;\n /**\n * Show the built-in toolbar. Default true. Pass false to hide it\n * entirely (e.g. when the consuming app renders its own\n * `<Calendar.Toolbar ... />` elsewhere on the page).\n */\n toolbar?: boolean;\n /**\n * Extra controls rendered at the inline-end of the default toolbar —\n * commonly a view switcher, a privacy toggle, or an \"add appointment\"\n * button. Ignored when `toolbar` is false.\n */\n toolbarEnd?: ReactNode;\n /**\n * Orientation for resource views. `vertical` (default) uses\n * `resourceTimeGrid` — resources as columns, time as rows.\n * `horizontal` uses `resourceTimeline` — resources as rows, time as columns.\n * Also applies to the plain `timeGridDay` / `timeGridWeek` views:\n * under `horizontal` they render as the plain `timelineDay` /\n * `timelineWeek` timelines (no resources), mirroring the platform's\n * per-user calendarResourceView='horizontal' setting.\n * `dayGridMonth` / `listWeek` are orientation-free. Timeline rendering\n * requires the Scheduler license (already covered by\n * `schedulerLicenseKey`).\n */\n resourceLayout?: 'vertical' | 'horizontal';\n /**\n * Marks the resource axis as PEOPLE (operators): each label renders the\n * kit `Avatar` primitive ONLY — the photo when `resource.avatarSrc` is\n * set, the deterministic initials circle otherwise — with the full name\n * on hover (Tooltip) and in the a11y tree. Requires a `TooltipProvider`\n * in the app/Storybook root (already standard). When false (default),\n * place labels render text with a coloured dot — or the `ResourceChip`\n * under `resourceLabelVariant=\"chip\"`.\n */\n showResourceInitials?: boolean;\n /**\n * Presentation of PLACE resource labels (chairs, rooms). `'text'`\n * (default) keeps the plain coloured-dot treatment; `'chip'` renders\n * the kit's `ResourceChip` primitive — the same chip display used\n * everywhere, with its own vertical variant under\n * `verticalResourceLabels`. People are never chips: a person axis\n * (`showResourceInitials`) always renders the Avatar-style initials\n * treatment, the kit's person primitive.\n */\n resourceLabelVariant?: 'text' | 'chip';\n /**\n * Rotate the per-resource column labels (chairs / operators) to\n * vertical, bottom-to-top text in resource time-grid COLUMN HEADERS.\n * Meant for the narrow columns of week × resource views, where a\n * horizontal label truncates after a few characters. No-op in the\n * timeline datagrid (its resource rows stay horizontal) and in\n * non-resource views. Long labels still ellipsise, capped by the\n * bridge sheet so the header row cannot grow unbounded.\n */\n verticalResourceLabels?: boolean;\n /**\n * Id of the SELECTED event — the one whose details the host has open\n * (a docked rail panel, an inspector). The matching card gets a token\n * focus-ring outline (`calendar-event-selected` on the FC harness) so\n * users can see WHICH appointment they are acting on. `null`/omitted =\n * no selection. Purely visual — selection state lives with the host.\n */\n selectedEventId?: string | null;\n /**\n * Availability projection — dims regular event cards so BACKGROUND\n * events (`isInternal: true`) read as the foreground layer. Made for\n * \"show free slots in the calendar\": the host supplies the free\n * ranges as background events and flips this on; booked cards fade,\n * free ranges glow (success tint via the theme bridge). The selected\n * event (`selectedEventId`) stays at full strength.\n */\n availabilityMode?: boolean;\n /**\n * Width of the resource-name column (\"resource area\") in horizontal\n * timeline views. Any CSS dimension — the platform passes '14%'.\n * No-op in vertical and non-resource views (no resource area exists).\n * Defaults to FullCalendar's own 30%.\n */\n resourceAreaWidth?: string | number;\n /**\n * Header label above the resource area of horizontal timeline views.\n * The reserved values 'chairs' and 'operators' render the kit's\n * localised strings (calendar.resourceLabel.*, all 18 locales — the\n * platform's hardcoded 'Poltrone'/'Operatori', localised). Any other\n * string renders verbatim: pass an app-translated string, never a raw\n * literal. No-op in vertical and non-resource views. Default: empty.\n */\n resourceAreaHeader?: 'chairs' | 'operators' | (string & {});\n /**\n * Assumed duration for events that have a `start` but no `end` — the\n * platform passes the per-user default appointment length here\n * (NewCalendar `defaultAppointmentDuration`). Two shapes:\n * - a FullCalendar duration string — `'00:30'` / `'00:30:00'`;\n * - a number of MINUTES (the shape the platform stores per user,\n * 1–1439). Numbers are converted internally to `{ minutes: n }` and\n * are NEVER forwarded raw — FullCalendar would misread a bare number\n * as milliseconds.\n * Omitted = FullCalendar's default of 1 hour. Affects rendered height /\n * span and drag/resize geometry of end-less timed events only; all-day\n * events use FullCalendar's separate 1-day default.\n */\n defaultTimedEventDuration?: string | number;\n /**\n * Shade alternate time-slot rows in time-grid views — a per-user\n * readability aid (the platform's `showZebraRowsInCalendar` setting).\n * Token-based tint that adapts to all four themes. Applies to the\n * vertical `timeGrid*` / `resourceTimeGrid*` slot body only; no-op in\n * month, list, and timeline views (same surface the platform shades).\n * @default false\n */\n zebraRows?: boolean;\n /**\n * Privacy / observability seam — NOT a styling hook. When set, the kit\n * stamps this class (space-separated classes allowed) on every\n * patient-bearing internal surface so session-replay / analytics\n * tooling can mask them in one move: time-slot lanes, event harnesses\n * (all views, including drag mirrors, the \"+N more\" popover, and\n * background events), the built-in toolbar's navigation buttons and\n * title, the mode-banner label, and the aria-live announcement region\n * (drop/resize/focus announcements carry patient titles). The\n * reference consumer passes PostHog's marker so session replay masks\n * the agenda: `maskClassName=\"ph-no-capture\"`. Resource labels\n * (staff names, not patient data) and time-axis labels are\n * deliberately not stamped — matching the platform. Consumer-provided\n * slots (`alertBanner`, `toolbarEnd`) are not stamped either — the kit\n * cannot reach inside arbitrary JSX, so stamp your own node if its\n * content can carry patient data. Trade-off: markers like\n * `ph-no-capture` suppress analytics autocapture as well as replay on\n * stamped elements (toolbar navigation clicks included) — instrument\n * such interactions explicitly if you need them in analytics.\n */\n maskClassName?: string;\n}\n\nexport interface CalendarHandle {\n /** Returns the internal FullCalendar instance for advanced use. */\n getApi: () => unknown;\n /** Jump to today. */\n today: () => void;\n /** Navigate to the previous period. */\n prev: () => void;\n /** Navigate to the next period. */\n next: () => void;\n /** Navigate to an arbitrary date. */\n gotoDate: (date: Date | string) => void;\n /** Switch the active view. */\n changeView: (view: CalendarView) => void;\n /** Current view title (e.g. \"April 2026\") — reflects the FC API getter. */\n getTitle: () => string;\n /** Currently active view name. */\n getCurrentView: () => CalendarView | undefined;\n /** Currently focused date — the anchor of the visible range. */\n getCurrentDate: () => Date | undefined;\n /** Scroll to an event by id and briefly highlight it. */\n focusEvent: (eventId: string) => void;\n}\n\n/* Narrow structural interface for the subset of the FullCalendar API\n we actually invoke. Keeps the handle methods typed without pulling\n `@fullcalendar/core` types across the public boundary. */\ninterface FcApi {\n today: () => void;\n prev: () => void;\n next: () => void;\n gotoDate: (date: Date | string) => void;\n changeView: (view: string) => void;\n render: () => void;\n updateSize: () => void;\n getDate: () => Date;\n getEventById: (id: string) => EventClickArg['event'] | null;\n view: { title: string; type: string };\n}\n\n/* Pointer-movement threshold (CSS px) separating a click from a drag\n gesture — shared between FC's `eventDragMinDistance` and the all-day-\n lane click synthesis so both classify gestures identically. */\nconst CLICK_MOVE_THRESHOLD_PX = 5;\n\n/* Mode banner → i18n key lookup. Kept as a literal object (not a\n template) so static-analysis extractors can find every key. */\nconst MODE_BANNER_KEYS: Record<Exclude<CalendarMode, 'default'>, string> = {\n create: 'calendar.modeBanner.create',\n move: 'calendar.modeBanner.move',\n copy: 'calendar.modeBanner.copy',\n};\n\n/* ------------------------------------------------------------------ */\n/* Helpers */\n/* ------------------------------------------------------------------ */\n\ninterface LocaleWeekInfo {\n firstDay?: number;\n}\n\ninterface LocaleWithWeekInfo {\n getWeekInfo?: () => LocaleWeekInfo;\n weekInfo?: LocaleWeekInfo;\n}\n\n/**\n * Resolve the first day of the week for a locale using the modern\n * `Intl.Locale.getWeekInfo()` API when available, falling back to Monday\n * for EU-leaning locales and Sunday for en-US / he-IL / ar-SA.\n */\nexport function resolveFirstDay(locale: string): number {\n try {\n const intlLocale = new Intl.Locale(locale) as unknown as LocaleWithWeekInfo;\n const info =\n typeof intlLocale.getWeekInfo === 'function'\n ? intlLocale.getWeekInfo()\n : intlLocale.weekInfo;\n if (info && typeof info.firstDay === 'number') {\n return info.firstDay % 7;\n }\n } catch {\n /* no-op — fall through to heuristic */\n }\n if (\n locale.startsWith('en-US') ||\n locale.startsWith('he') ||\n locale.startsWith('ar-SA')\n ) {\n return 0;\n }\n return 1;\n}\n\n/* ------------------------------------------------------------------ */\n/* Per-date resource column hiding — pure derivation layer */\n/* ------------------------------------------------------------------ */\n\n/** Cell-hiding class stamped by the classNames generators below; styled\n * (display:none) in fullcalendar-theme.css. */\nconst HIDDEN_COL_CLASS = 'calendar-col-hidden';\n\n/** Local calendar-day ISO string — matches FC's own data-date\n * (formatDayString, local) and the platform's format('Y-m-d'). NEVER\n * toISOString() (TZ shift). */\nfunction formatLocalIsoDate(date: Date): string {\n const y = date.getFullYear();\n const m = String(date.getMonth() + 1).padStart(2, '0');\n const d = String(date.getDate()).padStart(2, '0');\n return `${y}-${m}-${d}`;\n}\n\nexport interface PerDateHiding {\n /** `${resourceId}:${YYYY-MM-DD}` membership set (O(1) lookups — the\n * generators run at high volume during FC's sizing passes). */\n hiddenCells: ReadonlySet<string>;\n /** date → count of resources hidden on that date. */\n hiddenCountByDate: ReadonlyMap<string, number>;\n /** Column count per date when nothing is hidden. */\n resourceCount: number;\n /** False when no resource carries hiddenDates OR datesAboveResources\n * is false — every hiding hook is an O(1) no-op then. */\n active: boolean;\n}\n\n/**\n * Pure derivation of the per-date hiding lookups from the `resources`\n * prop — the kit-internal counterpart of the platform's server-computed\n * `operatorDatesToHide` / `datesToHide` / `dateColSpans` triple (the\n * latter two are derived here, never supplied). Exported for unit tests\n * (same precedent as `resolveFullCalendarView`).\n */\nexport function buildPerDateHiding(\n resources: readonly CalendarResource[] | undefined,\n datesAboveResources: boolean,\n): PerDateHiding {\n const hiddenCells = new Set<string>();\n const hiddenCountByDate = new Map<string, number>();\n const resourceCount = resources?.length ?? 0;\n /* Hard-disabled in the inverted-header layout (datesAboveResources\n false) — the surgery target flips to resource th cells there;\n deferred, DEV-warned in the component. */\n if (resources && datesAboveResources) {\n for (const resource of resources) {\n if (!resource.hiddenDates) continue;\n for (const date of resource.hiddenDates) {\n const key = `${resource.id}:${date}`;\n if (hiddenCells.has(key)) continue; // duplicate dates counted once\n hiddenCells.add(key);\n hiddenCountByDate.set(date, (hiddenCountByDate.get(date) ?? 0) + 1);\n }\n }\n }\n return {\n hiddenCells,\n hiddenCountByDate,\n resourceCount,\n active: hiddenCells.size > 0,\n };\n}\n\n/**\n * Small hook that mirrors the parent Calendar's document-dir observer\n * so sub-components can swap physical icons for logical direction\n * without threading a prop through. Returns true when the effective\n * document direction is RTL.\n */\nfunction useIsRtl(): boolean {\n const { i18n } = useTranslation();\n const [isRtl, setIsRtl] = useState<boolean>(() => {\n if (typeof document === 'undefined') return false;\n const docDir = document.documentElement.getAttribute('dir');\n const i18nDir = typeof i18n.dir === 'function' ? i18n.dir() : 'ltr';\n return docDir === 'rtl' || i18nDir === 'rtl';\n });\n\n useEffect(() => {\n if (typeof document === 'undefined') return undefined;\n const observer = new MutationObserver(() => {\n const docDir = document.documentElement.getAttribute('dir');\n const i18nDir = typeof i18n.dir === 'function' ? i18n.dir() : 'ltr';\n setIsRtl(docDir === 'rtl' || i18nDir === 'rtl');\n });\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['dir', 'lang'],\n });\n return () => observer.disconnect();\n }, [i18n]);\n\n return isRtl;\n}\n\n/* ------------------------------------------------------------------ */\n/* Event content — thin adapter over CalendarEventCard */\n/* */\n/* The card (src/components/calendar-event-card/) owns everything */\n/* inside the FC harness: colours + ink derivation, status icon/accent, */\n/* indicator icons, truncation, and the composed aria-label. The */\n/* Calendar adapter's job is to unpack the FC arg, mask the title */\n/* under privacy mode, format the time range, and resolve the resource */\n/* label — the card never sees a Date, a locale, or an unmasked name. */\n/* ------------------------------------------------------------------ */\n\ntype EventExtendedProps = Omit<\n CalendarEvent,\n 'id' | 'title' | 'start' | 'end' | 'allDay'\n>;\n\n/**\n * Pre-formats the localised time range for the card. Preserves the\n * historical behaviour verbatim: the range is computed unconditionally\n * (the card weaves it into the aria-label even when the visual time\n * line is hidden), and any Intl failure degrades to no range at all.\n */\nfunction formatRangeText(\n arg: EventContentArg,\n locale: string,\n): string | undefined {\n const start = arg.event.start;\n const end = arg.event.end ?? arg.event.start;\n if (!start || !end) return undefined;\n try {\n const fmt = new Intl.DateTimeFormat(locale, {\n hour: '2-digit',\n minute: '2-digit',\n hour12: false,\n });\n return typeof fmt.formatRange === 'function'\n ? fmt.formatRange(start, end)\n : `${fmt.format(start)} – ${fmt.format(end)}`;\n } catch {\n return undefined;\n }\n}\n\n/* ------------------------------------------------------------------ */\n/* CalendarToolbar — compound sub-component */\n/* */\n/* Renders the DS-styled prev/today/next controls + a centered <h2> */\n/* title (aria-live so navigation updates announce politely) plus an */\n/* optional inline-end slot. Logical properties only; physical icons */\n/* (ChevronLeft / ChevronRight) are swapped in RTL so the pair always */\n/* points in the expected reading direction. */\n/* ------------------------------------------------------------------ */\n\nexport interface CalendarToolbarProps {\n /** Title shown in the toolbar (e.g. \"April 2026\"). Typically\n * produced by `calendarHandle.getTitle()`. */\n title?: string;\n /** Jump to today. */\n onToday: () => void;\n /** Navigate to the previous period. */\n onPrev: () => void;\n /** Navigate to the next period. */\n onNext: () => void;\n /** Extra controls rendered at the inline-end. */\n end?: ReactNode;\n /** Additional className. */\n className?: string;\n /** Same contract as `CalendarProps.maskClassName` — stamped on the\n * today/prev/next buttons and the title. */\n maskClassName?: string;\n}\n\nconst toolbarButtonBaseClass = [\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:min-h-[var(--min-target-size)]',\n 'ds:bg-[var(--background)] ds:text-[var(--foreground)]',\n 'ds:border ds:border-[var(--border)]',\n 'ds:rounded-[var(--radius-full)]',\n 'ds:font-[var(--font-weight-medium)] ds:text-[length:var(--font-size-sm)]',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:ease-[var(--ease-out)]',\n 'ds:hover:bg-[var(--muted)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:outline-[var(--ring)]',\n 'ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:motion-reduce:transition-none',\n].join(' ');\n\nconst toolbarTextButtonClass = [\n toolbarButtonBaseClass,\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]',\n].join(' ');\n\nconst toolbarIconButtonClass = [\n toolbarButtonBaseClass,\n 'ds:min-w-[var(--min-target-size)]',\n].join(' ');\n\nexport const CalendarToolbar = forwardRef<HTMLDivElement, CalendarToolbarProps>(\n ({ title, onToday, onPrev, onNext, end, className, maskClassName }, ref) => {\n const { t } = useTranslation();\n const isRtl = useIsRtl();\n const PrevIcon = isRtl ? ChevronRight : ChevronLeft;\n const NextIcon = isRtl ? ChevronLeft : ChevronRight;\n\n const rootClassName = [\n 'ds:calendar-toolbar',\n 'ds:sticky ds:top-0 ds:z-20',\n 'ds:flex ds:items-center ds:gap-[var(--spacing-sm)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]',\n 'ds:py-[var(--spacing-sm)]',\n 'ds:bg-[var(--background)]',\n 'ds:border-b ds:border-[var(--border)]',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n /* Session-replay masking: the nav buttons lead to (and the title\n describes) patient-bearing date ranges — stamp the seam class on\n them when the consumer sets it. Raw string append — browsers split\n class attributes on whitespace, so multi-class values work as-is. */\n const maskedTextButtonClass = [toolbarTextButtonClass, maskClassName]\n .filter(Boolean)\n .join(' ');\n const maskedIconButtonClass = [toolbarIconButtonClass, maskClassName]\n .filter(Boolean)\n .join(' ');\n const titleClassName = [\n 'ds:flex-1 ds:text-center ds:truncate type-title-card',\n maskClassName,\n ]\n .filter(Boolean)\n .join(' ');\n const spacerClassName = ['ds:flex-1 ds:text-center', maskClassName]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div ref={ref} className={rootClassName}>\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <button\n type=\"button\"\n onClick={onToday}\n className={maskedTextButtonClass}\n >\n {t('calendar.today')}\n </button>\n <button\n type=\"button\"\n onClick={onPrev}\n aria-label={t('calendar.previousPeriod')}\n className={maskedIconButtonClass}\n >\n <PrevIcon size={16} aria-hidden=\"true\" />\n </button>\n <button\n type=\"button\"\n onClick={onNext}\n aria-label={t('calendar.nextPeriod')}\n className={maskedIconButtonClass}\n >\n <NextIcon size={16} aria-hidden=\"true\" />\n </button>\n </div>\n {title ? (\n <h2 aria-live=\"polite\" className={titleClassName}>\n {title}\n </h2>\n ) : (\n /* Keep the centering slot stable even before the first\n `datesSet` populates the title — an empty <h2> would trip\n axe's `empty-heading` rule, so we substitute a decorative\n spacer that matches the h2's flex sizing. Once `title` is\n non-empty the h2 renders in the same slot. */\n <div aria-hidden=\"true\" className={spacerClassName} />\n )}\n {end ? (\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n {end}\n </div>\n ) : null}\n </div>\n );\n },\n);\nCalendarToolbar.displayName = 'Calendar.Toolbar';\n\n/* ------------------------------------------------------------------ */\n/* Calendar component */\n/* ------------------------------------------------------------------ */\n\nconst CalendarInner = forwardRef<CalendarHandle, CalendarProps>(\n (\n {\n id,\n events,\n resources,\n view = 'dayGridMonth',\n initialDate,\n locale: localeProp,\n onEventDrop,\n onEventResize,\n onEventDragStart,\n onEventResizeStart,\n onEventClick,\n onEventMouseEnter,\n onEventMouseLeave,\n onDateSelect,\n onDatesSet,\n onDateClick,\n onNavLinkDayClick,\n editable = false,\n eventDurationEditable,\n selectable = false,\n height,\n className,\n privacyMode = false,\n eventColorStyle = 'solid',\n mode = 'default',\n modeLabel,\n modeBannerColor,\n modeBannerTextColor,\n onModeCancel,\n alertBanner,\n hiddenDays,\n slotMinTime,\n slotMaxTime,\n slotDuration,\n snapDuration,\n showTime = true,\n datesAboveResources = true,\n slotEventOverlap = false,\n stickyHeaderDates = true,\n nowIndicator = true,\n dayMaxEvents = true,\n schedulerLicenseKey = import.meta.env.VITE_FULLCALENDAR_LICENSE_KEY,\n toolbar = true,\n toolbarEnd,\n resourceLayout = 'vertical',\n showResourceInitials = false,\n resourceLabelVariant = 'text',\n verticalResourceLabels = false,\n selectedEventId,\n availabilityMode = false,\n resourceAreaWidth,\n resourceAreaHeader,\n defaultTimedEventDuration,\n zebraRows = false,\n maskClassName,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n const fcRef = useRef<FullCalendar | null>(null);\n const rootRef = useRef<HTMLDivElement>(null);\n const liveRegionRef = useRef<HTMLDivElement>(null);\n const focusTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const focusedElRef = useRef<HTMLElement | null>(null);\n /* Native-eventClick dedupe channel for the all-day-lane synthesis\n listener (see the synthesis effect below). FC's eventClick is a real\n delegated `click` listener on a descendant of rootRef, so during a\n single native click dispatch it runs BEFORE the wrapper's\n bubble-phase root listener and receives the SAME MouseEvent object —\n recording its identity here lets the synthesis skip clicks FC\n already handled. NOTE: identity dedupe only works for eventClick.\n FC delivers dateClick/select with the gesture's mouseup — sometimes\n asynchronously, from its drag system's dragend — never with the\n browser `click` event this component's root listener receives, so\n the dateClick channel dedupes per GESTURE via the refs below. */\n const lastNativeEventClickRef = useRef<MouseEvent | null>(null);\n /* Gesture bookkeeping for the synthesis listener: a monotonically\n increasing id per pointerdown on the calendar root plus the\n pointer-down coordinates (drag detection), and the gesture ids of\n the last natively / synthetically delivered date click so the two\n channels can never both fire for one gesture regardless of FC's\n internal callback timing. id 0 = no pointer gesture observed\n (e.g. programmatic clicks in tests) — all guards treat 0 as \"no\n information\" and stand down. */\n const gestureRef = useRef<{ id: number; x: number; y: number }>({\n id: 0,\n x: 0,\n y: 0,\n });\n const nativeDateClickGestureRef = useRef(0);\n const synthDateClickGestureRef = useRef(0);\n\n const locale = localeProp ?? i18n.language ?? 'en';\n\n /* ---- dev-only hiddenDays misuse guard --------------------------- */\n /* FullCalendar builds its hidden-day hash for values 0–6 only — an\n out-of-range entry (typically an unconverted ISO 7 = Sunday, the\n exact value the platform stores per user) is a silent no-op.\n Same dev-warning precedent as warnLowContrast. */\n useEffect(() => {\n if (!import.meta.env.DEV) return;\n if (!hiddenDays) return;\n const invalid = hiddenDays.filter(\n (day) => !Number.isInteger(day) || day < 0 || day > 6,\n );\n if (invalid.length > 0) {\n console.warn(\n `[Calendar] hiddenDays takes JavaScript day numbers 0 (Sunday) – 6 (Saturday); ` +\n `got [${invalid.join(', ')}], which FullCalendar silently ignores. ` +\n `Convert ISO day numbers (1–7) consumer-side, e.g. \\`day % 7\\`.`,\n );\n }\n }, [hiddenDays]);\n\n /* ---- dev-only defaultTimedEventDuration misuse guard ------------ */\n /* Same precedent as the hiddenDays guard: numbers must be positive\n integer MINUTES (the platform's per-user shape, 1–1439); strings\n must be an 'HH:mm' / 'HH:mm:ss' duration. */\n useEffect(() => {\n if (!import.meta.env.DEV) return;\n if (defaultTimedEventDuration === undefined) return;\n const invalidNumber =\n typeof defaultTimedEventDuration === 'number' &&\n (!Number.isFinite(defaultTimedEventDuration) ||\n defaultTimedEventDuration <= 0 ||\n !Number.isInteger(defaultTimedEventDuration));\n const invalidString =\n typeof defaultTimedEventDuration === 'string' &&\n !/^\\d{1,2}:\\d{2}(:\\d{2})?$/.test(defaultTimedEventDuration);\n if (invalidNumber || invalidString) {\n console.warn(\n `[Calendar] defaultTimedEventDuration takes 'HH:mm' / 'HH:mm:ss' or a ` +\n `positive integer number of MINUTES; got ` +\n `${JSON.stringify(defaultTimedEventDuration)}.`,\n );\n }\n }, [defaultTimedEventDuration]);\n\n /* ---- direction reacts to dir attribute changes ----------------- */\n const [direction, setDirection] = useState<'ltr' | 'rtl'>(() => {\n if (typeof document === 'undefined') return 'ltr';\n const docDir = document.documentElement.getAttribute('dir');\n const i18nDir = typeof i18n.dir === 'function' ? i18n.dir() : 'ltr';\n return docDir === 'rtl' || i18nDir === 'rtl' ? 'rtl' : 'ltr';\n });\n\n useEffect(() => {\n if (typeof document === 'undefined') return undefined;\n const observer = new MutationObserver(() => {\n const docDir = document.documentElement.getAttribute('dir');\n const i18nDir = typeof i18n.dir === 'function' ? i18n.dir() : 'ltr';\n setDirection(docDir === 'rtl' || i18nDir === 'rtl' ? 'rtl' : 'ltr');\n });\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['dir', 'lang'],\n });\n return () => observer.disconnect();\n }, [i18n]);\n\n /* ---- theme class-change observer → forces FullCalendar repaint - */\n useEffect(() => {\n if (typeof document === 'undefined') return undefined;\n let timer: ReturnType<typeof setTimeout>;\n const observer = new MutationObserver(() => {\n clearTimeout(timer);\n timer = setTimeout(() => {\n const api = fcRef.current?.getApi() as unknown;\n if (\n api &&\n typeof (api as { render?: () => void }).render === 'function'\n ) {\n (api as { render: () => void }).render();\n }\n }, 50);\n });\n observer.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['class'],\n });\n return () => {\n clearTimeout(timer);\n observer.disconnect();\n };\n }, []);\n\n /* FC re-measures only on window resize; a container that grows or\n shrinks on its own (a side rail collapsing) leaves the grid at its\n old width. Observe the root's inline size and re-measure. */\n useEffect(() => {\n const root = rootRef.current;\n if (!root || typeof ResizeObserver === 'undefined') return undefined;\n let frame = 0;\n let lastInlineSize = root.getBoundingClientRect().width;\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0];\n const inlineSize =\n entry?.borderBoxSize?.[0]?.inlineSize ??\n entry?.contentRect.width ??\n root.getBoundingClientRect().width;\n if (inlineSize === lastInlineSize) return;\n lastInlineSize = inlineSize;\n cancelAnimationFrame(frame);\n frame = requestAnimationFrame(() => {\n (fcRef.current?.getApi() as FcApi | undefined)?.updateSize();\n });\n });\n observer.observe(root);\n return () => {\n cancelAnimationFrame(frame);\n observer.disconnect();\n };\n }, []);\n\n /* ---- FullCalendar markup a11y patches --------------------------- */\n /* */\n /* FullCalendar emits a few markup patterns that axe (correctly) */\n /* flags but we cannot fix without forking FC. Patching at */\n /* render-time via MutationObserver keeps the fix scoped: */\n /* */\n /* 1. `<a aria-expanded aria-controls>` for the daygrid \"+N more\" */\n /* trigger has no `role` — `aria-expanded` is not allowed on a */\n /* bare anchor. Add `role=\"button\"`. Day-number nav links are */\n /* the same href-less, tabbable anchor — same patch. */\n /* 2. `.fc-scroller` is a scrollable region with no keyboard */\n /* access — give it `tabindex=\"0\"` and `role=\"region\"` so */\n /* keyboard users can scroll it. */\n /* 3. `.fc-bg-event` (background events used for highlight ranges) */\n /* is rendered with `aria-hidden=\"true\"` ancestor + an inner */\n /* `<a tabindex=\"0\">` — strip the focusability when */\n /* `aria-hidden` is in effect. */\n useEffect(() => {\n if (typeof document === 'undefined') return undefined;\n const root = rootRef.current;\n if (!root) return undefined;\n\n const patchMarkup = () => {\n root\n .querySelectorAll<HTMLAnchorElement>(\n '.fc-daygrid-more-link, a[data-navlink]',\n )\n .forEach((link) => {\n if (!link.getAttribute('role')) {\n link.setAttribute('role', 'button');\n }\n });\n // `.fc-scroller` cannot be patched — adding `tabindex=\"0\"`\n // makes it a focusable direct child of FC's `<table\n // role=\"grid\">`, which axe (correctly) flags as a violation of\n // `aria-required-children` (a grid expects only `role=\"row\"`\n // children). The `scrollable-region-focusable` rule will need\n // an upstream FC fix or per-story override; for now we accept\n // it. (Tracked: deferred.)\n // Inside any aria-hidden subtree, force focusable descendants to\n // tabindex=\"-1\" so they leave the tab sequence (axe\n // aria-hidden-focus). FC marks decorative rows / mirror events\n // aria-hidden but leaves the inner anchors focusable.\n root\n .querySelectorAll<HTMLElement>('[aria-hidden=\"true\"]')\n .forEach((hidden) => {\n hidden\n .querySelectorAll<HTMLElement>(\n 'a[href], button, [tabindex]:not([tabindex=\"-1\"])',\n )\n .forEach((el) => {\n el.setAttribute('tabindex', '-1');\n });\n });\n };\n\n patchMarkup();\n const observer = new MutationObserver(patchMarkup);\n observer.observe(root, {\n childList: true,\n subtree: true,\n attributes: true,\n attributeFilter: ['aria-hidden'],\n });\n return () => observer.disconnect();\n }, [t]);\n\n /* ---- reduced-motion gate --------------------------------------- */\n const reducedMotion = usePrefersReducedMotion();\n\n /* ---- current title (synced from FC via datesSet) --------------- */\n const [currentTitle, setCurrentTitle] = useState('');\n\n /* ---- live rendered FC view name (synced from datesSet) ---------- */\n /* The `view` PROP only feeds FC's `initialView`; runtime switches\n flow through `handle.changeView` and never touch the prop. Any\n logic gated on the rendered view (the all-day-lane click\n synthesis below) must therefore follow FC's own datesSet, not the\n prop, or it goes stale after the first `changeView`. */\n const [liveInternalView, setLiveInternalView] = useState<string>(() =>\n resolveFullCalendarView(view, resourceLayout),\n );\n /* Render-synchronous mirror so stable FC callbacks (the per-date\n hiding colSpan sync below) read the live view name without\n re-binding — same latest-ref pattern as perDateHidingRef. */\n const liveInternalViewRef = useRef(liveInternalView);\n liveInternalViewRef.current = liveInternalView;\n\n /* ---- imperative handle ----------------------------------------- */\n const handle = useMemo<CalendarHandle>(() => {\n const getRawApi = (): FcApi | undefined =>\n fcRef.current?.getApi() as FcApi | undefined;\n\n return {\n getApi: () => fcRef.current?.getApi(),\n today: () => {\n getRawApi()?.today();\n },\n prev: () => {\n getRawApi()?.prev();\n },\n next: () => {\n getRawApi()?.next();\n },\n gotoDate: (date: Date | string) => {\n getRawApi()?.gotoDate(date);\n },\n changeView: (nextView: CalendarView) => {\n getRawApi()?.changeView(\n resolveFullCalendarView(nextView, resourceLayout),\n );\n },\n getTitle: () => getRawApi()?.view.title ?? '',\n getCurrentView: () => {\n const type = getRawApi()?.view.type;\n return type as CalendarView | undefined;\n },\n getCurrentDate: () => getRawApi()?.getDate(),\n focusEvent: (eventId: string) => {\n const root = rootRef.current;\n if (!root) return;\n const selector = `[data-event-id=\"${CSS.escape(eventId)}\"]`;\n const element = root.querySelector<HTMLElement>(selector);\n if (!element) {\n if (import.meta.env.DEV) {\n console.warn(\n `[Calendar] focusEvent: no DOM node matches event id \"${eventId}\".`,\n );\n }\n return;\n }\n /* Clear any previous highlight still in-flight before\n starting a new one — prevents overlapping timers from\n removing the className mid-animation. */\n if (focusTimerRef.current) {\n clearTimeout(focusTimerRef.current);\n focusTimerRef.current = null;\n }\n if (focusedElRef.current && focusedElRef.current !== element) {\n focusedElRef.current.classList.remove('calendar-event-focused');\n }\n\n element.scrollIntoView({\n behavior: reducedMotion ? 'auto' : 'smooth',\n block: 'center',\n });\n element.classList.add('calendar-event-focused');\n focusedElRef.current = element;\n\n /* Announce via aria-live, masking the title under privacy\n mode the same way drop/resize do. */\n if (liveRegionRef.current) {\n const titleAttr = element.getAttribute('aria-label') ?? eventId;\n const announcedTitle = privacyMode ? '•••' : titleAttr;\n liveRegionRef.current.textContent = t('calendar.focusedEvent', {\n title: announcedTitle,\n });\n }\n\n focusTimerRef.current = setTimeout(() => {\n element.classList.remove('calendar-event-focused');\n if (focusedElRef.current === element) {\n focusedElRef.current = null;\n }\n focusTimerRef.current = null;\n }, 3000);\n },\n };\n }, [reducedMotion, privacyMode, t, resourceLayout]);\n\n useImperativeHandle(ref, () => handle, [handle]);\n useAgentRegistration(calendarAgent, handle, id);\n\n /* Clean up any pending focus timer on unmount. */\n useEffect(\n () => () => {\n if (focusTimerRef.current) {\n clearTimeout(focusTimerRef.current);\n focusTimerRef.current = null;\n }\n },\n [],\n );\n\n /* ---- privacy-mode announcer (skip initial render) --------------- */\n const privacyFirstRun = useRef(true);\n useEffect(() => {\n if (privacyFirstRun.current) {\n privacyFirstRun.current = false;\n return;\n }\n if (liveRegionRef.current) {\n liveRegionRef.current.textContent = privacyMode\n ? t('calendar.privacyModeOn')\n : t('calendar.privacyModeOff');\n }\n }, [privacyMode, t]);\n\n /* ---- adapt events for FullCalendar ----------------------------- */\n const fcEvents = useMemo<EventInput[]>(\n () =>\n events.map((event) => ({\n id: event.id,\n title: event.title,\n start: event.start,\n end: event.end,\n /* Conditional spreads — FC refines PRESENT-but-undefined keys\n (`'propName' in input`), so undefined must mean ABSENT:\n - editable: Boolean(undefined) === false would pin every\n ordinary event non-draggable;\n - display: String(undefined) === 'undefined' breaks month-\n view dot/block classification and leaks via EventApi;\n - allDay: Boolean(undefined) === false disables FC's\n all-day inference for date-only starts;\n - resourceId: String(undefined) puts 'undefined' into\n def.resourceIds → getResources() returns [null]. */\n ...(event.allDay !== undefined ? { allDay: event.allDay } : {}),\n ...(event.resourceId !== undefined\n ? { resourceId: event.resourceId }\n : {}),\n ...(event.isInternal ? { display: 'background' as const } : {}),\n /* A draft is the user's own composition: dragging or resizing it\n IS how they pick the slot, so it stays editable even on a\n read-only calendar. The consumer's own `editable` still wins. */\n ...(event.isDraft ? { editable: true as const } : {}),\n ...(event.editable !== undefined ? { editable: event.editable } : {}),\n ...(event.startEditable !== undefined\n ? { startEditable: event.startEditable }\n : {}),\n extendedProps: {\n status: event.status,\n resourceId: event.resourceId,\n /* Mirror the raw per-event editability values so adaptEvent\n can round-trip them — EventImpl's `startEditable` getter\n resolves the COMBINED ui (incl. calendar-level fallback)\n and must not be used for round-tripping. */\n editable: event.editable,\n startEditable: event.startEditable,\n backgroundColor: event.backgroundColor,\n textColor: event.textColor,\n borderColor: event.borderColor,\n suffix: event.suffix,\n privacyModeTitle: event.privacyModeTitle,\n isBookedOnline: event.isBookedOnline ?? false,\n hasUnassignedPatient: event.hasUnassignedPatient ?? false,\n hasHighlightedAnamnesis: event.hasHighlightedAnamnesis ?? false,\n hasBillableAmount: event.hasBillableAmount ?? false,\n isTelehealth: event.isTelehealth ?? false,\n isRecurring: event.isRecurring ?? false,\n isRecurrenceParent: event.isRecurrenceParent ?? false,\n isInternal: event.isInternal ?? false,\n isTask: event.isTask ?? false,\n isDraft: event.isDraft ?? false,\n patientId: event.patientId,\n operatorId: event.operatorId,\n },\n })),\n [events],\n );\n\n /* ---- formatters (Intl, never literal format strings) ----------- */\n const titleFormat = useMemo(\n () => ({\n year: 'numeric' as const,\n month: 'long' as const,\n }),\n [],\n );\n const dayHeaderFormat = useMemo(\n () => ({\n weekday: 'short' as const,\n }),\n [],\n );\n const eventTimeFormat = useMemo(\n () => ({\n hour: 'numeric' as const,\n minute: '2-digit' as const,\n }),\n [],\n );\n const slotLabelFormat = useMemo(\n () => ({\n hour: '2-digit' as const,\n minute: '2-digit' as const,\n /* 24-hour axis — matches the event cards' range text (hour12\n false there too) and the platform's EU clock. */\n hour12: false,\n }),\n [],\n );\n\n /* ---- day header render prop ------------------------------------- */\n /* Weekday eyebrow over a prominent day number (today = a filled\n primary circle) — the standard calendar header treatment, instead\n of a bare weekday string. Month and list views keep the\n weekday-only label: their surfaces carry the date elsewhere. */\n const renderDayHeader = useCallback(\n (arg: DayHeaderContentArg): ReactElement | string => {\n const weekday = new Intl.DateTimeFormat(locale, {\n weekday: 'short',\n }).format(arg.date);\n if (\n arg.view.type === 'dayGridMonth' ||\n arg.view.type.startsWith('list')\n ) {\n return weekday;\n }\n const dayNumber = new Intl.DateTimeFormat(locale, {\n day: 'numeric',\n }).format(arg.date);\n return (\n <span className=\"ds:flex ds:flex-col ds:items-center ds:gap-[var(--spacing-2xs)] ds:py-[var(--spacing-2xs)]\">\n <span className=\"type-eyebrow ds:text-[color:var(--muted-foreground)]\">\n {weekday}\n </span>\n <span\n className={\n arg.isToday\n ? 'ds:flex ds:size-7 ds:items-center ds:justify-center ds:rounded-full ds:bg-[var(--primary)] ds:text-[length:var(--font-size-sm)] ds:font-[var(--font-weight-semibold)] ds:leading-none ds:text-[color:var(--primary-foreground)]'\n : 'ds:text-[length:var(--font-size-sm)] ds:font-[var(--font-weight-semibold)] ds:leading-none'\n }\n >\n {dayNumber}\n </span>\n </span>\n );\n },\n [locale],\n );\n\n /* ---- default timed-event duration (platform per-user minutes) ---- */\n /* Numbers are minutes (the platform's stored shape) — convert to a\n Duration object; a bare number would be read by FullCalendar as\n MILLISECONDS (createDuration, internal-common.js). */\n const fcDefaultTimedEventDuration = useMemo(\n () =>\n typeof defaultTimedEventDuration === 'number'\n ? { minutes: defaultTimedEventDuration }\n : defaultTimedEventDuration,\n [defaultTimedEventDuration],\n );\n\n /* ---- session-replay mask classes --------------------------------- */\n /* Split once for FC's ClassNamesGenerator options (they take a\n string[]); kit-owned surfaces append the raw string instead. */\n const maskClassList = useMemo(\n () =>\n maskClassName ? maskClassName.split(/\\s+/).filter(Boolean) : undefined,\n [maskClassName],\n );\n\n /* ---- resource-area header (horizontal timeline views) ----------- */\n /* The reserved 'chairs' / 'operators' values resolve to the kit's\n localised calendar.resourceLabel.* strings (present in all 18\n locale bundles); any other string renders verbatim (consumers pass\n an app-translated string). undefined passes through — FC's option\n refiners skip undefined, leaving the header empty (FC default). */\n const resourceAreaHeaderContent = useMemo(() => {\n if (resourceAreaHeader === undefined) return undefined;\n if (resourceAreaHeader === 'chairs') {\n return t('calendar.resourceLabel.chairs');\n }\n if (resourceAreaHeader === 'operators') {\n return t('calendar.resourceLabel.operators');\n }\n return resourceAreaHeader;\n }, [resourceAreaHeader, t]);\n\n /* ---- per-date resource column hiding ---------------------------- */\n /* CalendarResource.hiddenDates → declarative cell hiding. */\n /* Layer A: three stable classNames generators stamp */\n /* HIDDEN_COL_CLASS (display:none in the theme bridge) — self- */\n /* healing on every FC Preact render, zero DOM surgery. */\n /* Layer B: the one unavoidable mutation — the date-header colSpan, */\n /* which has no CSS equivalent under table-layout:fixed with an */\n /* axis-only colgroup — is synced event-driven: dayHeaderDidMount */\n /* (date-header cells are keyed by date and recreated on every */\n /* navigation / changeView) + a kit-render effect (below, after */\n /* fcResources: covers hidden-map prop changes that do not recreate */\n /* cells, the resources-length Preact-clobber path, and restore-on- */\n /* deactivate) + a defensive datesSet tail call. NO polling loop. */\n const perDateHiding = useMemo(\n () => buildPerDateHiding(resources, datesAboveResources),\n [resources, datesAboveResources],\n );\n /* Latest-ref so the stable FC callbacks below never go stale. */\n const perDateHidingRef = useRef(perDateHiding);\n perDateHidingRef.current = perDateHiding;\n /* Restore-on-deactivate tracker: true while any date-header colSpan\n may differ from FC's own render output. */\n const colSpanTouchedRef = useRef(false);\n\n const dayCellClassNames = useCallback(\n (arg: DayCellContentArg): string[] => {\n const hiding = perDateHidingRef.current;\n if (!hiding.active || !arg.view.type.startsWith('resourceTimeGrid')) {\n return [];\n }\n /* `resource` arrives via DayCellContentArg's index signature —\n pivot through unknown to stay `any`-free (same pattern as\n ResourceExtendedProps below). Fires for BOTH td.fc-timegrid-col\n and td.fc-daygrid-day (TimeCol renders through\n DayCellContainer). */\n const resource = (arg as unknown as { resource?: { id?: string } })\n .resource;\n if (!resource?.id) return [];\n return hiding.hiddenCells.has(\n `${resource.id}:${formatLocalIsoDate(arg.date)}`,\n )\n ? [HIDDEN_COL_CLASS]\n : [];\n },\n [],\n );\n\n const resourceLabelClassNames = useCallback(\n (arg: ResourceLabelContentArg): string[] => {\n const hiding = perDateHidingRef.current;\n /* The view guard is critical: this generator also fires for\n timeline datagrid rows, where `date` is undefined — without it\n the currentStart fallback would wrongly hide a whole timeline\n row. */\n if (!hiding.active || !arg.view.type.startsWith('resourceTimeGrid')) {\n return [];\n }\n /* arg.date is populated in both header shapes we support\n (FC 6.1.20: renderResourceRow passes `date` for single-day\n views; renderDayAndResourceRows passes it per (resource, date)\n cell). The fallback is defensive only — the one shape where FC\n omits it (datesAboveResources=false, resource th spanning all\n dates) is hard-disabled via `active: false`, so the fallback\n can never mis-hide a spanning cell. */\n const date = arg.date ?? arg.view.currentStart;\n return hiding.hiddenCells.has(\n `${arg.resource.id}:${formatLocalIsoDate(date)}`,\n )\n ? [HIDDEN_COL_CLASS]\n : [];\n },\n [],\n );\n\n const dayHeaderClassNames = useCallback(\n (arg: DayHeaderContentArg): string[] => {\n /* Whole-date collapse: the date-row th disappears when every\n resource hides that date (the platform's `datesToHide`,\n derived here rather than supplied). */\n const hiding = perDateHidingRef.current;\n if (!hiding.active || !arg.view.type.startsWith('resourceTimeGrid')) {\n return [];\n }\n const hidden =\n hiding.hiddenCountByDate.get(formatLocalIsoDate(arg.date)) ?? 0;\n return hidden >= hiding.resourceCount ? [HIDDEN_COL_CLASS] : [];\n },\n [],\n );\n\n /* colSpan sync — trigger 1: cell creation. Date-header cells are\n keyed by date and destroyed+recreated on every navigation /\n changeView, so this re-applies automatically; it runs within FC's\n commit — no misaligned frame. */\n const handleDayHeaderDidMount = useCallback((arg: DayHeaderMountArg) => {\n const hiding = perDateHidingRef.current;\n if (!hiding.active || !arg.view.type.startsWith('resourceTimeGrid')) {\n return;\n }\n const el = arg.el;\n if (!(el instanceof HTMLTableCellElement)) return;\n if (!el.classList.contains('fc-day')) return; // date row only\n const iso = el.getAttribute('data-date');\n if (!iso) return;\n const hidden = hiding.hiddenCountByDate.get(iso) ?? 0;\n /* Clamp ≥ 1 — colSpan 0 is invalid HTML (platform quirk, banned);\n a fully hidden date's cell is display:none'd by\n dayHeaderClassNames anyway. */\n const span = Math.max(1, hiding.resourceCount - hidden);\n if (el.colSpan !== span) {\n el.colSpan = span;\n colSpanTouchedRef.current = true;\n }\n }, []);\n\n /* colSpan sync — shared body for trigger 2 (kit-render effect below,\n after fcResources) and trigger 3 (defensive datesSet tail call).\n Fast path: a consumer that never uses hiddenDates pays one boolean\n check. */\n const syncDateHeaderColSpans = useCallback(() => {\n const root = rootRef.current;\n if (!root) return;\n if (!liveInternalViewRef.current.startsWith('resourceTimeGrid')) return;\n const hiding = perDateHidingRef.current;\n if (!hiding.active && !colSpanTouchedRef.current) return;\n root\n .querySelectorAll<HTMLTableCellElement>(\n 'th.fc-col-header-cell.fc-day[data-date]',\n )\n .forEach((el) => {\n const iso = el.getAttribute('data-date');\n if (!iso) return;\n const hidden = hiding.active\n ? (hiding.hiddenCountByDate.get(iso) ?? 0)\n : 0;\n const span = Math.max(1, hiding.resourceCount - hidden);\n if (el.colSpan !== span) el.colSpan = span;\n });\n colSpanTouchedRef.current = hiding.active;\n }, []);\n\n /* ---- dev-only hiddenDates misuse guards -------------------------- */\n /* Same precedent as the hiddenDays guard above. Three warnings:\n malformed date strings, the unsupported inverted-header layout,\n and a visible event targeting a hidden cell (the platform server\n guarantees hidden cells are event-free — a violation is a consumer\n data bug the kit surfaces rather than swallows). */\n useEffect(() => {\n if (!import.meta.env.DEV) return;\n const malformed = (resources ?? []).flatMap((resource) =>\n (resource.hiddenDates ?? []).filter(\n (date) => !/^\\d{4}-\\d{2}-\\d{2}$/.test(date),\n ),\n );\n if (malformed.length > 0) {\n console.warn(\n `[Calendar] hiddenDates takes local ISO 'YYYY-MM-DD' strings ` +\n `(matching FullCalendar's data-date); got ` +\n `[${malformed.join(', ')}], which can never match a cell.`,\n );\n }\n const anyHidden = (resources ?? []).some(\n (resource) => (resource.hiddenDates?.length ?? 0) > 0,\n );\n if (anyHidden && !datesAboveResources) {\n console.warn(\n '[Calendar] hiddenDates is inert when datesAboveResources is ' +\n 'false — per-date hiding supports the dates-above-resources ' +\n 'header layout only, so no column will be hidden.',\n );\n }\n if (perDateHiding.active) {\n for (const event of events) {\n if (event.isInternal || !event.resourceId) continue;\n const start =\n event.start instanceof Date ? event.start : new Date(event.start);\n if (Number.isNaN(start.getTime())) continue;\n const iso = formatLocalIsoDate(start);\n if (perDateHiding.hiddenCells.has(`${event.resourceId}:${iso}`)) {\n console.warn(\n `[Calendar] event \"${event.id}\" starts on a hidden ` +\n `(resource, date) cell (${event.resourceId}, ${iso}) — ` +\n `hidden cells must be event-free; the event cannot render.`,\n );\n }\n }\n }\n }, [events, perDateHiding]);\n\n /* ---- helper: adapt FC event to CalendarEvent -------------------- */\n const adaptEvent = (\n fcEvent: EventDropArg['event'] | EventClickArg['event'],\n ): CalendarEvent => {\n const ext = (fcEvent.extendedProps ?? {}) as EventExtendedProps;\n return {\n id: fcEvent.id,\n title: fcEvent.title,\n start: fcEvent.start ?? new Date(),\n end: fcEvent.end ?? undefined,\n resourceId: ext.resourceId,\n status: ext.status,\n allDay: fcEvent.allDay,\n backgroundColor: ext.backgroundColor,\n textColor: ext.textColor,\n borderColor: ext.borderColor,\n suffix: ext.suffix,\n privacyModeTitle: ext.privacyModeTitle,\n isBookedOnline: ext.isBookedOnline,\n hasUnassignedPatient: ext.hasUnassignedPatient,\n hasHighlightedAnamnesis: ext.hasHighlightedAnamnesis,\n hasBillableAmount: ext.hasBillableAmount,\n isTelehealth: ext.isTelehealth,\n isRecurring: ext.isRecurring,\n isRecurrenceParent: ext.isRecurrenceParent,\n isInternal: ext.isInternal,\n isTask: ext.isTask,\n editable: ext.editable,\n startEditable: ext.startEditable,\n patientId: ext.patientId,\n operatorId: ext.operatorId,\n };\n };\n\n /* ---- callbacks ------------------------------------------------- */\n const handleEventDrop = useMemo(() => {\n if (!onEventDrop) return undefined;\n return (info: EventDropArg) => {\n if (!info.event.start) return;\n // `info.oldEvent.start` is the only reliable source for the pre-drag\n // time — FullCalendar guarantees it is non-null for a drop on an\n // event that had a start. The `delta` field is unsafe to subtract\n // because it reports calendrical components (years/months/days +\n // sub-day ms), not a single ms offset, and month/year reconstruction\n // is ambiguous across boundaries. If oldStart is somehow missing we\n // bail rather than produce a silently-wrong value.\n const oldStart = info.oldEvent.start;\n if (!oldStart) {\n if (import.meta.env.DEV) {\n console.warn(\n '[Calendar] handleEventDrop: oldEvent.start was null — dropping the event-drop callback rather than emitting wrong oldStart data.',\n );\n }\n return;\n }\n onEventDrop({\n event: adaptEvent(info.event),\n oldStart,\n newStart: info.event.start,\n oldResourceId: info.oldResource?.id,\n newResourceId: info.newResource?.id,\n revert: info.revert,\n });\n /* Announce via aria-live. The announced title must honour\n privacyMode — the event card's aria-label already masks, but\n the live-region text is a separate codepath that would leak\n the raw name on drop if not masked here too. */\n if (liveRegionRef.current) {\n const ext = (info.event.extendedProps ?? {}) as EventExtendedProps;\n const announcedTitle = privacyMode\n ? (ext.privacyModeTitle ?? '•••')\n : info.event.title;\n liveRegionRef.current.textContent = t('calendar.eventMoved', {\n title: announcedTitle,\n });\n }\n };\n }, [onEventDrop, privacyMode, t]);\n\n const handleEventResize = useMemo(() => {\n if (!onEventResize) return undefined;\n return (info: EventResizeDoneArg) => {\n if (!info.event.end) return;\n // Mirror the drop path: rely on `info.oldEvent.end` for the pre-resize\n // boundary. Bail on null rather than fabricating a value from deltas.\n const oldEnd = info.oldEvent.end;\n if (!oldEnd) {\n if (import.meta.env.DEV) {\n console.warn(\n '[Calendar] handleEventResize: oldEvent.end was null — dropping the resize callback rather than emitting wrong oldEnd data.',\n );\n }\n return;\n }\n const newEnd = info.event.end;\n // Fall back to the pre-resize start (info.oldEvent.start), not\n // oldEnd — using oldEnd collapses cancelled drags to a zero-minute\n // duration in the live-region announcement.\n const newStart = info.event.start ?? info.oldEvent.start ?? oldEnd;\n onEventResize({\n event: adaptEvent(info.event),\n oldEnd,\n newEnd,\n revert: info.revert,\n });\n if (liveRegionRef.current) {\n const duration = Math.round(\n (newEnd.getTime() - newStart.getTime()) / 60000,\n );\n /* Mirror the drop path: mask the title when privacyMode is on. */\n const ext = (info.event.extendedProps ?? {}) as EventExtendedProps;\n const announcedTitle = privacyMode\n ? (ext.privacyModeTitle ?? '•••')\n : info.event.title;\n liveRegionRef.current.textContent = t('calendar.eventResized', {\n title: announcedTitle,\n duration,\n });\n }\n };\n }, [onEventResize, privacyMode, t]);\n\n const handleEventClick = useMemo(() => {\n if (!onEventClick) return undefined;\n return (info: EventClickArg) => {\n if (!info.event.start) return;\n /* FC's eventClick is a delegated native `click` listener, so\n info.jsEvent IS the click event that will bubble to the\n synthesis root listener — identity dedupe is sound here (and\n only here; see the ref's comment). */\n lastNativeEventClickRef.current = info.jsEvent;\n onEventClick(adaptEvent(info.event), {\n el: info.el,\n jsEvent: info.jsEvent,\n });\n };\n }, [onEventClick]);\n\n /* Hover pair — FC's eventMouseEnter/eventMouseLeave are plain delegated\n pointer listeners with no gesture system attached, so no dedupe\n bookkeeping is needed here. Background events (isInternal) are\n non-interactive surfaces — no peek. */\n const handleEventMouseEnter = useMemo(() => {\n if (!onEventMouseEnter) return undefined;\n return (info: EventHoveringArg) => {\n if (!info.event.start) return;\n if (info.event.display === 'background') return;\n /* A draft has no saved record to preview. */\n if ((info.event.extendedProps as EventExtendedProps)?.isDraft) return;\n onEventMouseEnter(adaptEvent(info.event), {\n el: info.el,\n jsEvent: info.jsEvent,\n });\n };\n }, [onEventMouseEnter]);\n\n const handleEventMouseLeave = useMemo(() => {\n if (!onEventMouseLeave) return undefined;\n return (info: EventHoveringArg) => {\n if (!info.event.start) return;\n if (info.event.display === 'background') return;\n onEventMouseLeave(adaptEvent(info.event));\n };\n }, [onEventMouseLeave]);\n\n const handleDateSelect = useMemo(() => {\n if (!onDateSelect) return undefined;\n return (info: DateSelectArg) => {\n /* No dedupe recording here: info.jsEvent is the gesture's\n mouseup, never the browser `click` the synthesis listener\n sees, so identity recording is provably inert. Drag-select\n gestures are excluded from the synthesis by its pointer-\n movement guard instead. */\n onDateSelect({\n start: info.start,\n end: info.end,\n allDay: info.allDay,\n resourceId: info.resource?.id,\n });\n };\n }, [onDateSelect]);\n\n const handleDateClick = useMemo(() => {\n if (!onDateClick) return undefined;\n return (info: DateClickArg) => {\n /* Cross-channel dedupe with the all-day-lane synthesis, per\n GESTURE rather than event identity — info.jsEvent is the\n gesture's mouseup, delivered from FC's drag system and\n sometimes AFTER the browser `click` has already been\n processed, so no event-object comparison can ever match.\n Whichever channel delivers first stamps the gesture id; the\n other stands down. Gesture id 0 = no pointer gesture\n observed — skip the guard entirely. */\n const gestureId = gestureRef.current.id;\n if (gestureId !== 0 && synthDateClickGestureRef.current === gestureId) {\n return;\n }\n if (gestureId !== 0) nativeDateClickGestureRef.current = gestureId;\n onDateClick({\n date: info.date,\n allDay: info.allDay,\n resourceId: info.resource?.id,\n });\n };\n }, [onDateClick]);\n\n /* Kept unconditional — it also feeds the toolbar title. The dep\n change (was []) is safe: unlike the platform, the kit feeds events\n via the controlled `events` prop, so FC listener-identity changes\n cannot trigger event re-fetches. */\n const handleDatesSet = useCallback(\n (info: DatesSetArg) => {\n setCurrentTitle(info.view.title);\n setLiveInternalView(info.view.type);\n onDatesSet?.({\n view,\n internalView: info.view.type,\n start: info.start,\n end: info.end,\n /* info.view.calendar is available even on the very first datesSet\n tick, which fires before fcRef is guaranteed to be assigned. */\n currentDate: info.view.calendar.getDate(),\n title: info.view.title,\n });\n /* Per-date hiding colSpan sync — trigger 3 (defensive tail call):\n catches any FC-internal commit that lands after triggers 1+2\n (deferred CustomRenderingStore flush racing the React effect).\n O(visible dates); a true no-op unless per-date hiding is (or\n just was) active. */\n syncDateHeaderColSpans();\n },\n [onDatesSet, view, syncDateHeaderColSpans],\n );\n\n /* ---- firstDay from locale -------------------------------------- */\n const firstDay = useMemo(() => resolveFirstDay(locale), [locale]);\n\n /* ---- plugins --------------------------------------------------- */\n const plugins = useMemo(\n () => [\n dayGridPlugin,\n timeGridPlugin,\n listPlugin,\n interactionPlugin,\n resourcePlugin,\n resourceTimeGridPlugin,\n resourceTimelinePlugin,\n timelinePlugin,\n ],\n [],\n );\n\n /* ---- resolved internal FC view name ---------------------------- */\n const resolvedView = useMemo(\n () => resolveFullCalendarView(view, resourceLayout),\n [view, resourceLayout],\n );\n\n /* ---- gesture tracking for the click synthesis ------------------ */\n /* Always attached (independent of the rendered view) so gesture ids */\n /* stay monotonic across changeView switches — a stale stamp from a */\n /* previous view can then never match a later gesture's id. */\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return undefined;\n const handlePointerDown = (event: PointerEvent) => {\n gestureRef.current = {\n id: gestureRef.current.id + 1,\n x: event.clientX,\n y: event.clientY,\n };\n };\n root.addEventListener('pointerdown', handlePointerDown, true);\n return () =>\n root.removeEventListener('pointerdown', handlePointerDown, true);\n }, []);\n\n /* ---- all-day-lane click synthesis (vertical resource views) ----- */\n /* */\n /* FullCalendar's dateClick does not fire for the all-day daygrid */\n /* cells of resourceTimeGrid views (the platform patches this with a */\n /* native listener — NewCalendar/App.js:224-290). We own the */\n /* workaround here so consumers never have to. */\n /* */\n /* Gated on liveInternalView — the view actually rendered, tracked */\n /* from FC's datesSet — NOT on the `view` prop, which is initial- */\n /* only: runtime switches flow through handle.changeView and would */\n /* leave a prop-derived gate stale in both directions (listener */\n /* still attached in a standard view where native dateClick fires = */\n /* double delivery; listener never attached after switching INTO a */\n /* resource view = seam silently dead). */\n /* */\n /* Selector contract (FC v6, verified): */\n /* - all-day lane cells: td.fc-daygrid-day[data-date] */\n /* (the timegrid all-day slot is rendered by daygrid's DayTable) */\n /* - resource id: data-resource-id on the same td */\n /* (added by @fullcalendar/resource's day-cell renderer) */\n /* */\n /* Dedupe — two mechanisms, per channel: */\n /* - eventClick: FC's is a real delegated `click` listener that */\n /* runs before this bubble-phase root listener with the SAME */\n /* event object → identity check via lastNativeEventClickRef. */\n /* - dateClick: FC delivers it with the gesture's mouseup (from */\n /* its drag system, sometimes asynchronously AFTER this click), */\n /* so identity can never match → per-gesture stamps instead */\n /* (whichever channel fires first for a pointerdown wins). */\n /* Plus FC's own dateClick validity rules (isValidDateDownEl / */\n /* isValidSegDownEl): more-links, nav links, the overflow popover */\n /* and drag mirrors are excluded, and clicks concluding a moved- */\n /* pointer gesture (drag-select, aborted event drag) are ignored. */\n useEffect(() => {\n const root = rootRef.current;\n if (!root) return undefined;\n if (!liveInternalView.startsWith('resourceTimeGrid')) return undefined;\n if (!onDateClick && !onEventClick) return undefined;\n\n const handleRootClick = (event: MouseEvent) => {\n if (event === lastNativeEventClickRef.current) return;\n const target = event.target;\n if (!(target instanceof Element)) return;\n\n /* Mirror FC's isValidDateDownEl / isValidSegDownEl exclusions:\n the \"+N more\" overflow link, anything inside the overflow\n popover, nav links, and drag mirrors are FC's own\n interactions — never a click-to-create or a missed\n eventClick. */\n if (\n target.closest(\n '.fc-more-link, a[data-navlink], .fc-popover, .fc-event-mirror',\n )\n ) {\n return;\n }\n\n /* A drag gesture (drag-select, aborted event drag) still\n concludes with a browser `click` on the common ancestor —\n skip clicks whose pointer moved since pointerdown. Threshold\n matches the eventDragMinDistance passed to FC below. */\n const gesture = gestureRef.current;\n if (\n gesture.id !== 0 &&\n (Math.abs(event.clientX - gesture.x) > CLICK_MOVE_THRESHOLD_PX ||\n Math.abs(event.clientY - gesture.y) > CLICK_MOVE_THRESHOLD_PX)\n ) {\n return;\n }\n\n const cell = target.closest('td.fc-daygrid-day[data-date]');\n if (!cell) return; // timed grid — native handlers own it\n\n const cardEl = target.closest<HTMLElement>('[data-event-id]');\n if (cardEl) {\n /* An all-day event whose native eventClick did not fire. */\n if (!onEventClick) return;\n const eventId = cardEl.getAttribute('data-event-id');\n const api = fcRef.current?.getApi() as FcApi | undefined;\n const fcEvent = eventId ? api?.getEventById(eventId) : null;\n if (!fcEvent || !fcEvent.start) return;\n const ext = (fcEvent.extendedProps ?? {}) as EventExtendedProps;\n // Background events are painted surfaces; a draft has no record\n // behind it yet. Neither is clickable.\n if (ext.isInternal || ext.isDraft) return;\n const anchorEl = target.closest<HTMLElement>('.fc-event') ?? cardEl;\n onEventClick(adaptEvent(fcEvent), { el: anchorEl, jsEvent: event });\n return;\n }\n\n if (!onDateClick) return;\n /* Per-gesture dedupe vs native dateClick (see the handler). */\n if (\n gesture.id !== 0 &&\n nativeDateClickGestureRef.current === gesture.id\n ) {\n return;\n }\n const dateAttr = cell.getAttribute('data-date');\n if (!dateAttr) return;\n /* 'YYYY-MM-DD' alone parses as UTC midnight in JS — append a local\n time so the Date is local midnight, matching FC's own dateClick\n payloads (and the platform's moment(dateAttr) behaviour). */\n const date = new Date(`${dateAttr}T00:00:00`);\n if (Number.isNaN(date.getTime())) return;\n if (gesture.id !== 0) synthDateClickGestureRef.current = gesture.id;\n onDateClick({\n date,\n allDay: true,\n resourceId: cell.getAttribute('data-resource-id') ?? undefined,\n });\n };\n\n root.addEventListener('click', handleRootClick);\n return () => root.removeEventListener('click', handleRootClick);\n }, [liveInternalView, onDateClick, onEventClick]);\n\n /* ---- resource label render prop -------------------------------- */\n /* FC's `resourceLabelContent` supplies a `ResourceApi` whose\n `extendedProps` is typed as `{ [k: string]: any }`. We narrow to\n just the fields we pushed through `fcResources` via a local\n interface reached by an `unknown` pivot — keeps the DS body free\n of `any` while accepting FC's runtime shape. */\n interface ResourceExtendedProps {\n shortTitle?: string;\n color?: string;\n shortTitleTextColor?: string;\n avatarSrc?: string;\n }\n\n const renderResourceLabel = useCallback(\n (arg: ResourceLabelContentArg): ReactElement => {\n const ext = arg.resource\n .extendedProps as unknown as ResourceExtendedProps;\n const title = arg.resource.title;\n const color = ext.color;\n const textColor = ext.shortTitleTextColor;\n\n /* Runtime caller-supplied hex values flow through inline CSS\n custom properties only; the consuming `background-color` /\n `color` references live in the className as Tailwind arbitrary\n values, matching the event/mode-banner pattern (see\n 23-constraints §Runtime-computed dimensions).\n\n Inline style — permitted per 23-constraints §Runtime-computed\n dimensions (CSS custom property setters for --resource-color /\n --resource-initials-text-color). */\n const swatchStyle: CSSProperties | undefined =\n color || textColor\n ? {\n ...(color\n ? ({ '--resource-color': color } as CSSProperties)\n : {}),\n ...(textColor\n ? ({\n '--resource-initials-text-color': textColor,\n } as CSSProperties)\n : {}),\n }\n : undefined;\n\n if (resourceLabelVariant === 'chip' && !showResourceInitials) {\n /* Places (chairs, rooms) render the kit's ResourceChip primitive\n — one chip display everywhere. PEOPLE are deliberately not\n chips: a person axis (`showResourceInitials`) falls through to\n the Avatar-style initials treatment below, the kit's existing\n person primitive. The chip owns its vertical variant, so the\n cushion-level label rotation excludes it. */\n return (\n <ResourceChip\n label={title}\n color={color}\n orientation={verticalResourceLabels ? 'vertical' : 'horizontal'}\n />\n );\n }\n\n if (showResourceInitials) {\n /* People render the kit Avatar primitive ONLY — the photo when\n `resource.avatarSrc` is set, the deterministic initials circle\n otherwise — with the full name on hover (Tooltip) and in the\n a11y tree (Avatar's role=\"img\" aria-label carries the name).\n No name string in the narrow column, and no rotation: the\n vertical-labels CSS excludes avatar cells. Supersedes the old\n shortTitle/colour circle so the SAME operator avatar renders\n here as everywhere else in the kit. */\n return (\n <Tooltip label={title}>\n <Avatar size=\"sm\" name={title} src={ext.avatarSrc} />\n </Tooltip>\n );\n }\n\n if (color) {\n /* Dot branch has no text, but callers may still pass both halves\n of the pair in anticipation of flipping `showResourceInitials`.\n Only warn when both are defined — otherwise we'd noisily\n suggest a textColor that the dot renderer ignores. */\n if (color && textColor) {\n warnLowContrast(color, textColor, `resource ${arg.resource.id}`);\n }\n return (\n <span className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <span\n className=\"resource-dot ds:[background-color:var(--resource-color)]\"\n // eslint-disable-next-line react/forbid-dom-props -- caller-supplied resource colour injected via CSS variable\n style={swatchStyle}\n aria-hidden=\"true\"\n />\n <span className=\"ds:truncate ds:text-start\">{title}</span>\n </span>\n );\n }\n\n return (\n <span className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <span className=\"ds:truncate ds:text-start\">{title}</span>\n </span>\n );\n },\n [showResourceInitials, resourceLabelVariant, verticalResourceLabels],\n );\n\n /* ---- resources adapted for FC with extendedProps --------------- */\n const fcResources = useMemo(\n () =>\n resources?.map((resource) => ({\n id: resource.id,\n title: resource.title,\n sequenceNumber: resource.sequenceNumber,\n extendedProps: {\n shortTitle: resource.shortTitle,\n color: resource.color,\n shortTitleTextColor: resource.shortTitleTextColor,\n avatarSrc: resource.avatarSrc,\n sequenceNumber: resource.sequenceNumber,\n },\n })),\n [resources],\n );\n\n /* ---- per-date hiding colSpan sync — trigger 2 -------------------- */\n /* Kit-prop-driven renders. Covers (a) hidden-map changes that do NOT\n recreate header cells, (b) a resources-length change, where FC's\n Preact rewrites the vdom colSpan WITHOUT refiring didMount, and\n (c) restore-on-deactivate. The rAF re-run covers\n @fullcalendar/react's deferred CustomRenderingStore flush racing\n this effect. Escalation path (if a stale frame is ever caught):\n double-rAF — never an interval. */\n useEffect(() => {\n syncDateHeaderColSpans();\n const raf = requestAnimationFrame(syncDateHeaderColSpans);\n return () => cancelAnimationFrame(raf);\n }, [perDateHiding, fcResources, liveInternalView, syncDateHeaderColSpans]);\n\n /* ---- default-toolbar button handlers --------------------------- */\n const handleToolbarToday = useCallback(() => {\n (fcRef.current?.getApi() as FcApi | undefined)?.today();\n }, []);\n const handleToolbarPrev = useCallback(() => {\n (fcRef.current?.getApi() as FcApi | undefined)?.prev();\n }, []);\n const handleToolbarNext = useCallback(() => {\n (fcRef.current?.getApi() as FcApi | undefined)?.next();\n }, []);\n\n /* A draft on the grid means an editor is composing: everything else\n recedes so the slot being placed reads as the subject. */\n const hasDraft = useMemo(\n () => events.some((event) => event.isDraft),\n [events],\n );\n\n const wrapperClassName = [\n 'fc-theme-alfadocs',\n zebraRows ? 'calendar-zebra-rows' : null,\n verticalResourceLabels ? 'calendar-vertical-resource-labels' : null,\n availabilityMode ? 'calendar-availability-mode' : null,\n /* Composing: derived from the events themselves rather than a prop,\n so the dim can never disagree with what is on the grid. */\n hasDraft ? 'calendar-composing-mode' : null,\n 'ds:bg-background ds:text-foreground',\n 'ds:rounded-[var(--radius-md)]',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n /* Mode banner style — runtime caller-supplied hex values flow through\n inline CSS-variable assignments only. The consuming\n `background-color` / `color` references live in the className as\n Tailwind arbitrary values, same justification as the event\n colour overrides above. */\n const modeBannerStyle: CSSProperties | undefined =\n modeBannerColor || modeBannerTextColor\n ? {\n ...(modeBannerColor\n ? ({ '--calendar-mode-bg': modeBannerColor } as CSSProperties)\n : {}),\n ...(modeBannerTextColor\n ? ({ '--calendar-mode-fg': modeBannerTextColor } as CSSProperties)\n : {}),\n }\n : undefined;\n\n /* DEV-only guardrail: warn when the caller-supplied mode-banner\n bg/fg hex pair falls below WCAG AA. No-op when either half is\n missing — the component falls back to --muted / --muted-foreground\n which are already calibrated to AA. */\n if (mode !== 'default' && (modeBannerColor || modeBannerTextColor)) {\n warnLowContrast(modeBannerColor, modeBannerTextColor, 'mode banner');\n }\n\n /* Static key map — keeps i18n-extraction tools (i18next-parser, etc.)\n happy, since they can't resolve template-literal keys. */\n const resolvedModeLabel =\n mode !== 'default' ? (modeLabel ?? t(MODE_BANNER_KEYS[mode])) : '';\n\n const modeBannerClassName = [\n 'ds:sticky ds:top-0 ds:z-10',\n 'ds:flex ds:items-center ds:gap-[var(--spacing-sm)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]',\n 'ds:py-[var(--spacing-sm)]',\n /* Caller-supplied colours flow through CSS custom properties set\n in `modeBannerStyle`; fallback tokens apply when the caller\n doesn't supply a hex. */\n modeBannerColor\n ? 'ds:[background-color:var(--calendar-mode-bg)]'\n : 'ds:bg-[var(--muted)]',\n modeBannerTextColor\n ? 'ds:[color:var(--calendar-mode-fg)]'\n : 'ds:text-[var(--muted-foreground)]',\n ]\n .filter(Boolean)\n .join(' ');\n\n const modeCancelClassName = [\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:min-h-[var(--min-target-size)]',\n 'ds:ps-[var(--spacing-md)] ds:pe-[var(--spacing-md)]',\n 'ds:rounded-[var(--radius-full)]',\n 'ds:bg-[var(--background)] ds:text-[var(--foreground)]',\n 'ds:border ds:border-[var(--border)]',\n 'ds:font-[var(--font-weight-medium)] ds:text-[length:var(--font-size-sm)]',\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:ease-[var(--ease-out)]',\n 'ds:hover:bg-[var(--muted)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:outline-[var(--ring)]',\n 'ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:motion-reduce:transition-none',\n ].join(' ');\n\n return (\n <div\n ref={rootRef}\n className={wrapperClassName}\n role=\"region\"\n aria-label={t('calendar.ariaLabel')}\n data-component=\"calendar\"\n data-component-id={id}\n data-mode={mode}\n >\n <div\n ref={liveRegionRef}\n aria-live=\"polite\"\n aria-atomic=\"true\"\n /* Masked: drop/resize/focus announcements interpolate event\n (patient) titles. */\n className={['ds:sr-only', maskClassName].filter(Boolean).join(' ')}\n />\n {alertBanner}\n {/* role=\"status\" already implies aria-live=\"polite\" +\n aria-atomic=\"true\"; setting the live attributes explicitly\n causes double announcements in some AT combinations. */}\n {mode !== 'default' ? (\n <div\n className={modeBannerClassName}\n // eslint-disable-next-line react/forbid-dom-props -- caller-supplied mode banner colours injected via CSS variables\n style={modeBannerStyle}\n role=\"status\"\n >\n {/* Masked: `modeLabel` is consumer text that can carry a\n patient name (\"Moving appointment: …\"). */}\n <span\n className={['ds:flex-1 ds:text-start', maskClassName]\n .filter(Boolean)\n .join(' ')}\n >\n {resolvedModeLabel}\n </span>\n {onModeCancel ? (\n <button\n type=\"button\"\n onClick={onModeCancel}\n className={modeCancelClassName}\n >\n {t('calendar.modeBanner.cancel')}\n </button>\n ) : null}\n </div>\n ) : null}\n {toolbar !== false ? (\n <CalendarToolbar\n title={currentTitle}\n onToday={handleToolbarToday}\n onPrev={handleToolbarPrev}\n onNext={handleToolbarNext}\n end={toolbarEnd}\n maskClassName={maskClassName}\n />\n ) : null}\n <FullCalendar\n ref={fcRef}\n plugins={plugins}\n schedulerLicenseKey={schedulerLicenseKey}\n initialView={resolvedView}\n views={CALENDAR_VIEW_OPTIONS}\n initialDate={initialDate}\n locale={locale}\n direction={direction}\n firstDay={firstDay}\n editable={editable}\n eventDurationEditable={eventDurationEditable ?? editable}\n selectable={selectable}\n droppable={editable}\n dayMaxEvents={dayMaxEvents}\n height={height}\n /* Fewer slot rows (e.g. 60-min precision) must mean TALLER rows\n filling the given height, not a short grid over dead space —\n FC's compat default (false) leaves each row at its natural\n ~24px. No-op when rows overflow the height (scrolls as usual)\n or when height is unset. */\n expandRows\n events={fcEvents}\n resources={fcResources}\n resourceOrder=\"sequenceNumber\"\n resourceLabelContent={renderResourceLabel}\n resourceAreaWidth={resourceAreaWidth}\n resourceAreaHeaderContent={resourceAreaHeaderContent}\n /* Per-date hiding hooks — attached unconditionally but O(1)\n no-ops (return []) when no resource carries hiddenDates, so\n existing renders see zero DOM diff. */\n dayCellClassNames={dayCellClassNames}\n dayHeaderClassNames={dayHeaderClassNames}\n resourceLabelClassNames={resourceLabelClassNames}\n dayHeaderDidMount={handleDayHeaderDidMount}\n /* Session-replay masking — conditional spreads so consumers not\n using the seam pass FC a byte-identical options object. FC's\n ClassNamesGenerator accepts a plain string[]; a present-but-\n undefined key would still count as \"present\" to refineProps. */\n {...(maskClassList ? { slotLaneClassNames: maskClassList } : {})}\n eventClassNames={(arg) => [\n ...(maskClassList ?? []),\n ...(selectedEventId && arg.event.id === selectedEventId\n ? ['calendar-event-selected']\n : []),\n ...((arg.event.extendedProps as EventExtendedProps)?.isDraft\n ? ['calendar-event-draft']\n : []),\n ]}\n headerToolbar={false}\n allDayText={t('calendar.allDay')}\n noEventsText={t('calendar.noEvents')}\n titleFormat={titleFormat}\n dayHeaderFormat={dayHeaderFormat}\n dayHeaderContent={renderDayHeader}\n eventTimeFormat={eventTimeFormat}\n slotLabelFormat={slotLabelFormat}\n slotMinTime={slotMinTime ?? '00:00:00'}\n slotMaxTime={slotMaxTime ?? '24:00:00'}\n slotDuration={slotDuration ?? '00:30:00'}\n {...(snapDuration ? { snapDuration } : {})}\n // Explicit `slotLabelInterval` — FullCalendar 6.1.x crashes\n // inside `wholeDivideDurations` / `addDurations` when its\n // internal default computation produces an undefined Duration\n // (`Cannot read properties of undefined (reading 'years')`).\n // Passing all three slot props as explicit strings bypasses\n // the fragile default-resolution path. 1h matches FC's\n // documented default for day/week views.\n slotLabelInterval=\"01:00:00\"\n /* Conditional spread — the refiner is createDuration, so a\n present-but-undefined key would shadow FC's '01:00:00' base\n default and refine to null, breaking end-less event geometry. */\n {...(fcDefaultTimedEventDuration !== undefined\n ? { defaultTimedEventDuration: fcDefaultTimedEventDuration }\n : {})}\n hiddenDays={hiddenDays}\n datesAboveResources={datesAboveResources}\n slotEventOverlap={slotEventOverlap}\n stickyHeaderDates={stickyHeaderDates}\n nowIndicator={nowIndicator}\n eventLongPressDelay={reducedMotion ? 0 : 1000}\n eventDragMinDistance={reducedMotion ? 0 : CLICK_MOVE_THRESHOLD_PX}\n eventContent={(arg) => {\n const ext = (arg.event.extendedProps ?? {}) as EventExtendedProps;\n /* Background events (isInternal) are painted surfaces, not\n cards. With a title (e.g. a host-localised \"Free\" for\n availability ranges) they get a check-marked chip so the\n range reads as BOOKABLE, not disabled; untitled ones fall\n back to FullCalendar's bare tinted block (`true` = default\n rendering). */\n if (ext.isInternal) {\n return arg.event.title ? (\n <span className=\"calendar-bg-event-label\">\n <Check size={12} aria-hidden=\"true\" />\n {arg.event.title}\n </span>\n ) : (\n true\n );\n }\n return (\n <CalendarEventCard\n eventId={arg.event.id}\n title={\n privacyMode\n ? (ext.privacyModeTitle ?? '•••')\n : arg.event.title\n }\n privacyMasked={privacyMode}\n suffix={ext.suffix}\n rangeText={formatRangeText(arg, locale)}\n showTime={showTime}\n allDay={arg.event.allDay}\n status={ext.status}\n colorStyle={eventColorStyle}\n backgroundColor={ext.backgroundColor}\n textColor={ext.textColor}\n borderColor={ext.borderColor}\n isBookedOnline={ext.isBookedOnline}\n hasUnassignedPatient={ext.hasUnassignedPatient}\n hasHighlightedAnamnesis={ext.hasHighlightedAnamnesis}\n hasBillableAmount={ext.hasBillableAmount}\n isTelehealth={ext.isTelehealth}\n isRecurring={ext.isRecurring}\n isTask={ext.isTask}\n isDraft={ext.isDraft}\n resourceLabel={\n ext.resourceId\n ? (resources ?? []).find((r) => r.id === ext.resourceId)\n ?.title\n : undefined\n }\n />\n );\n }}\n eventClick={handleEventClick}\n eventMouseEnter={handleEventMouseEnter}\n eventMouseLeave={handleEventMouseLeave}\n eventDrop={handleEventDrop}\n eventResize={handleEventResize}\n eventDragStart={onEventDragStart}\n eventResizeStart={onEventResizeStart}\n select={handleDateSelect}\n dateClick={handleDateClick}\n datesSet={handleDatesSet}\n /* Conditional spread — hosts without the seam pass FC a\n byte-identical options object (no nav-link markup). */\n {...(onNavLinkDayClick\n ? {\n navLinks: true,\n navLinkDayClick: (date: Date, jsEvent: UIEvent) =>\n onNavLinkDayClick(date, jsEvent),\n }\n : {})}\n />\n </div>\n );\n },\n);\nCalendarInner.displayName = 'Calendar';\n\n/* Compound attachment — exposes `<Calendar.Toolbar />` so consumers can\n render a standalone toolbar bound to their own handle-driven handlers\n when they hide the built-in toolbar via `toolbar={false}`. The\n `typeof CalendarInner & { Toolbar }` widening is the single acceptable\n cast called out in the implementation plan. */\ntype CalendarComponent = typeof CalendarInner & {\n Toolbar: typeof CalendarToolbar;\n};\nexport const Calendar = CalendarInner as CalendarComponent;\nCalendar.Toolbar = CalendarToolbar;\n"],"names":["calendarAgent","handle","_a","args","RESOURCE_VIEW_MAP","STANDARD_VIEWS","STANDARD_HORIZONTAL_VIEW_MAP","resolveFullCalendarView","view","resourceLayout","stem","DAY_TITLE_FORMAT","TIMELINE_SLOT_LABEL_FORMAT","CALENDAR_VIEW_OPTIONS","CLICK_MOVE_THRESHOLD_PX","MODE_BANNER_KEYS","resolveFirstDay","locale","intlLocale","info","HIDDEN_COL_CLASS","formatLocalIsoDate","date","y","m","buildPerDateHiding","resources","datesAboveResources","hiddenCells","hiddenCountByDate","resourceCount","resource","key","useIsRtl","i18n","useTranslation","isRtl","setIsRtl","useState","docDir","i18nDir","useEffect","observer","formatRangeText","arg","start","end","fmt","toolbarButtonBaseClass","toolbarTextButtonClass","toolbarIconButtonClass","CalendarToolbar","forwardRef","title","onToday","onPrev","onNext","className","maskClassName","ref","t","PrevIcon","ChevronRight","ChevronLeft","NextIcon","rootClassName","maskedTextButtonClass","maskedIconButtonClass","titleClassName","spacerClassName","jsxs","jsx","CalendarInner","id","events","initialDate","localeProp","onEventDrop","onEventResize","onEventDragStart","onEventResizeStart","onEventClick","onEventMouseEnter","onEventMouseLeave","onDateSelect","onDatesSet","onDateClick","onNavLinkDayClick","editable","eventDurationEditable","selectable","height","privacyMode","eventColorStyle","mode","modeLabel","modeBannerColor","modeBannerTextColor","onModeCancel","alertBanner","hiddenDays","slotMinTime","slotMaxTime","slotDuration","snapDuration","showTime","slotEventOverlap","stickyHeaderDates","nowIndicator","dayMaxEvents","schedulerLicenseKey","toolbar","toolbarEnd","showResourceInitials","resourceLabelVariant","verticalResourceLabels","selectedEventId","availabilityMode","resourceAreaWidth","resourceAreaHeader","defaultTimedEventDuration","zebraRows","fcRef","useRef","rootRef","liveRegionRef","focusTimerRef","focusedElRef","lastNativeEventClickRef","gestureRef","nativeDateClickGestureRef","synthDateClickGestureRef","direction","setDirection","timer","api","root","frame","lastInlineSize","entries","entry","inlineSize","_b","patchMarkup","link","hidden","el","reducedMotion","usePrefersReducedMotion","currentTitle","setCurrentTitle","liveInternalView","setLiveInternalView","liveInternalViewRef","useMemo","getRawApi","nextView","eventId","selector","element","titleAttr","announcedTitle","useImperativeHandle","useAgentRegistration","privacyFirstRun","fcEvents","event","titleFormat","dayHeaderFormat","eventTimeFormat","slotLabelFormat","renderDayHeader","useCallback","weekday","dayNumber","fcDefaultTimedEventDuration","maskClassList","resourceAreaHeaderContent","perDateHiding","perDateHidingRef","colSpanTouchedRef","dayCellClassNames","hiding","resourceLabelClassNames","dayHeaderClassNames","handleDayHeaderDidMount","iso","span","syncDateHeaderColSpans","adaptEvent","fcEvent","ext","handleEventDrop","oldStart","handleEventResize","oldEnd","newEnd","newStart","duration","handleEventClick","handleEventMouseEnter","handleEventMouseLeave","handleDateSelect","handleDateClick","gestureId","handleDatesSet","firstDay","plugins","dayGridPlugin","timeGridPlugin","listPlugin","interactionPlugin","resourcePlugin","resourceTimeGridPlugin","resourceTimelinePlugin","timelinePlugin","resolvedView","handlePointerDown","handleRootClick","target","gesture","cell","cardEl","anchorEl","dateAttr","renderResourceLabel","color","textColor","swatchStyle","ResourceChip","Tooltip","Avatar","warnLowContrast","fcResources","raf","handleToolbarToday","handleToolbarPrev","handleToolbarNext","hasDraft","wrapperClassName","modeBannerStyle","resolvedModeLabel","modeBannerClassName","modeCancelClassName","FullCalendar","Check","CalendarEventCard","r","jsEvent","Calendar"],"mappings":"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"}
|