@alfadocs/ui-kit-debug 1.7.0 → 1.9.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/{actions-cell-renderer-ALEAGO3j.js → actions-cell-renderer-B2pw6iH8.js} +2 -2
- package/dist/_chunks/{actions-cell-renderer-ALEAGO3j.js.map → actions-cell-renderer-B2pw6iH8.js.map} +1 -1
- 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/{file-manager-Cc_upjZX.js → file-manager-Crg5dKez.js} +2 -2
- package/dist/_chunks/{file-manager-Cc_upjZX.js.map → file-manager-Crg5dKez.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-ChXM2K7H.js} +11 -7
- package/dist/_chunks/patient-table-ChXM2K7H.js.map +1 -0
- 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/cell-renderers/actions-cell-renderer.d.ts.map +1 -1
- package/dist/components/data-table/index.js +2 -2
- 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/file-manager/index.js +1 -1
- package/dist/components/gestational-age-calculator/index.js +1 -1
- package/dist/components/hcg-doubling/index.js +1 -1
- package/dist/components/index.d.ts +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/columns.d.ts.map +1 -1
- package/dist/components/patient-table/index.js +1 -1
- package/dist/components/patient-table/patient-table.d.ts +5 -4
- package/dist/components/patient-table/patient-table.d.ts.map +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 +41 -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/patient-table-DwshfVsQ.js.map +0 -1
- package/dist/_chunks/payment-automation-upsell-BBIG7NFL.js.map +0 -1
- package/dist/_chunks/subDays-CAUv47M1.js +0 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alfadocs/ui-kit-debug",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.9.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AlfaDocs shared design system — tokens, components, patterns, and translations for platform, booking, and alfascribe. (debug build — identical runtime to @alfadocs/ui-kit, ships source maps for symbolication).",
|
|
6
6
|
"license": "BUSL-1.1",
|
|
@@ -569,6 +569,10 @@
|
|
|
569
569
|
"types": "./dist/components/reviews-panel/index.d.ts",
|
|
570
570
|
"import": "./dist/components/reviews-panel/index.js"
|
|
571
571
|
},
|
|
572
|
+
"./resource-chip": {
|
|
573
|
+
"types": "./dist/components/resource-chip/index.d.ts",
|
|
574
|
+
"import": "./dist/components/resource-chip/index.js"
|
|
575
|
+
},
|
|
572
576
|
"./rich-text-editor": {
|
|
573
577
|
"types": "./dist/components/rich-text-editor/index.d.ts",
|
|
574
578
|
"import": "./dist/components/rich-text-editor/index.js"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"appointment-card-BhcPJpXh.js","sources":["../../node_modules/lucide-react/dist/esm/icons/armchair.mjs","../../node_modules/lucide-react/dist/esm/icons/clipboard-plus.mjs","../../src/components/appointment-card/appointment-card.tsx"],"sourcesContent":["/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"path\", { d: \"M19 9V6a2 2 0 0 0-2-2H7a2 2 0 0 0-2 2v3\", key: \"irtipd\" }],\n [\n \"path\",\n {\n d: \"M3 16a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-5a2 2 0 0 0-4 0v1.5a.5.5 0 0 1-.5.5h-9a.5.5 0 0 1-.5-.5V11a2 2 0 0 0-4 0z\",\n key: \"1qyhux\"\n }\n ],\n [\"path\", { d: \"M5 18v2\", key: \"ppbyun\" }],\n [\"path\", { d: \"M19 18v2\", key: \"gy7782\" }]\n];\nconst Armchair = createLucideIcon(\"armchair\", __iconNode);\n\nexport { __iconNode, Armchair as default };\n//# sourceMappingURL=armchair.mjs.map\n","/**\n * @license lucide-react v1.22.0 - ISC\n *\n * This source code is licensed under the ISC license.\n * See the LICENSE file in the root directory of this source tree.\n */\n\nimport createLucideIcon from '../createLucideIcon.mjs';\n\nconst __iconNode = [\n [\"rect\", { width: \"8\", height: \"4\", x: \"8\", y: \"2\", rx: \"1\", ry: \"1\", key: \"tgr4d6\" }],\n [\n \"path\",\n {\n d: \"M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2\",\n key: \"116196\"\n }\n ],\n [\"path\", { d: \"M9 14h6\", key: \"159ibu\" }],\n [\"path\", { d: \"M12 17v-6\", key: \"1y8rbf\" }]\n];\nconst ClipboardPlus = createLucideIcon(\"clipboard-plus\", __iconNode);\n\nexport { __iconNode, ClipboardPlus as default };\n//# sourceMappingURL=clipboard-plus.mjs.map\n","import { forwardRef, type HTMLAttributes, type ReactNode } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport {\n Armchair,\n ChevronRight,\n ClipboardPlus,\n Globe,\n MapPin,\n Star,\n Video,\n} from 'lucide-react';\nimport { Avatar } from '../avatar/avatar';\nimport { Badge } from '../badge/badge';\nimport { Tag } from '../tag/tag';\nimport { Timestamp } from '../timestamp/timestamp';\nimport { TransactionChip } from '../transaction-chip/transaction-chip';\nimport {\n appointmentStateBadge,\n colorIdToToken,\n colorIdToAvatarToken,\n isSafeEntityUrl,\n} from '../_shared/entity-card';\nimport type { AppointmentState } from '../_shared/entity-card';\n\n/*\n * Closed colour-dot class map. `colorIdToToken` resolves the operator's\n * numeric colour id to one of a fixed set of palette tokens; the operator\n * dot needs a *static* Tailwind class for each so the compiler can emit it\n * (dynamic `ds:bg-[…]` strings are not seen by the JIT). The keys mirror the\n * exact token strings the shared helper returns.\n */\nconst OPERATOR_DOT_CLASS: Record<string, string> = {\n 'var(--color-violet-500)': 'ds:bg-[var(--color-violet-500)]',\n 'var(--color-purple-500)': 'ds:bg-[var(--color-purple-500)]',\n 'var(--color-magenta-500)': 'ds:bg-[var(--color-magenta-500)]',\n 'var(--color-blue-500)': 'ds:bg-[var(--color-blue-500)]',\n 'var(--color-green-500)': 'ds:bg-[var(--color-green-500)]',\n 'var(--color-red-500)': 'ds:bg-[var(--color-red-500)]',\n 'var(--color-yellow-500)': 'ds:bg-[var(--color-yellow-500)]',\n 'var(--color-indigo-500)': 'ds:bg-[var(--color-indigo-500)]',\n 'var(--color-orange-500)': 'ds:bg-[var(--color-orange-500)]',\n 'var(--color-fuchsia-500)': 'ds:bg-[var(--color-fuchsia-500)]',\n 'var(--color-grey-700)': 'ds:bg-[var(--color-grey-700)]',\n};\n\nfunction operatorDotClass(colorId: number | string | undefined): string {\n return (\n OPERATOR_DOT_CLASS[colorIdToToken(colorId)] ??\n 'ds:bg-[var(--color-grey-700)]'\n );\n}\n\n/* -------------------------------------------------------------------- */\n/* AppointmentCard */\n/* */\n/* Single-row appointment surface — sibling of AgendaCard, but richer: */\n/* leading timestamp, operator + patient avatars with the operator */\n/* colour dot, a lifecycle-state Badge (announced by label, never colour */\n/* alone), treatment / tooth Tags, and an optional advance-deposit */\n/* TransactionChip. State→Badge-variant + colour-id→token + URL-safety */\n/* come from the shared `_shared/entity-card` helpers. */\n/* */\n/* All visible text flows through useTranslation('ui') against the */\n/* `appointmentCard.*` namespace (plus shared `financial.*` for money). */\n/* -------------------------------------------------------------------- */\n\n// Back-compat / one-stop import — the URL guard lives in the shared helper.\nexport { isSafeEntityUrl as isSafeAppointmentUrl } from '../_shared/is-safe-url';\n\n/* -------------------------------------------------------------------- */\n/* Types */\n/* -------------------------------------------------------------------- */\n\n/** Appointment delivery channel. */\nexport type AppointmentType = 'inPractice' | 'telehealth';\n\n/** First-visit tri-state flag. */\nexport type AppointmentFirstVisit = 'yes' | 'no' | 'unknown';\n\n/** Operator (clinician) summary — name + optional palette colour id. */\nexport interface AppointmentOperator {\n /** Operator display name — drives the avatar initials + accessible name. */\n name: string;\n /** Numeric palette colour id, resolved to a kit token for the colour dot. */\n colorId?: number | string;\n}\n\n/** Patient summary — identity only, drives the avatar. */\nexport interface AppointmentPatient {\n /** Patient display name. */\n name: string;\n /** Optional avatar image URL. */\n avatarUrl?: string;\n}\n\n/** One treatment line within the appointment. */\nexport interface AppointmentTreatment {\n /** Localised care / treatment name. */\n careName: string;\n /** Optional tooth elements (e.g. FDI ids) the treatment targets. */\n elements?: string[];\n}\n\n/** Booking-reason metadata captured at online-booking time. */\nexport interface AppointmentBookingReason {\n /** Localised booking-reason description. */\n description: string;\n /** Expected duration in minutes. */\n durationMin?: number;\n /** Advance / deposit amount in cents (non-negative). */\n advanceAmountCents?: number;\n /** Localised specialty label. */\n specialty?: string;\n}\n\n/** Boolean appointment flags surfaced as chips / indicators. */\nexport interface AppointmentFlags {\n bookedOnline?: boolean;\n noPatientAssigned?: boolean;\n highlightedAnamnesis?: boolean;\n billable?: boolean;\n}\n\nexport interface AppointmentItem {\n /** Stable appointment identifier. */\n id: string;\n /** ISO-8601 start instant. */\n startIso: string;\n /** Duration in minutes. */\n durationMin: number;\n /** Lifecycle state — drives the Badge variant + label. */\n state: AppointmentState;\n /** Delivery channel — drives the leading type glyph. */\n type: AppointmentType;\n /** First-visit flag. */\n firstVisit?: AppointmentFirstVisit;\n /** Assigned operator. */\n operator?: AppointmentOperator;\n /** Chair / room label — surfaced as a chip. */\n chair?: string;\n /**\n * The care plan this appointment belongs to, when any — surfaced as a chip\n * (`Care plan {number}`). `url` is the deep link the consumer may use for\n * navigation; the chip itself is non-interactive so it never nests an anchor\n * inside the row's own stretched link.\n */\n carePlan?: { number: string; url?: string };\n /** Patient identity. */\n patient?: AppointmentPatient;\n /** Treatment lines. */\n treatments?: AppointmentTreatment[];\n /** Online booking-reason metadata. */\n bookingReason?: AppointmentBookingReason;\n /** Boolean flags. */\n flags?: AppointmentFlags;\n /** Optional deep link — when present (and safe) the row renders as an anchor. */\n url?: string;\n}\n\n/* -------------------------------------------------------------------- */\n/* CVA — row */\n/* -------------------------------------------------------------------- */\n\nconst appointmentCardVariants = cva(\n [\n 'ds:relative ds:flex ds:items-start ds:gap-[var(--spacing-sm)]',\n 'ds:rounded-[var(--radius-md)]',\n 'ds:text-start ds:group',\n 'ds:bg-[var(--card)] ds:text-[color:var(--card-foreground)]',\n 'ds:transition-colors ds:duration-[var(--animation-duration)]',\n 'ds:motion-reduce:transition-none',\n 'ds:forced-colors:border ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:p-[var(--spacing-sm)]',\n md: 'ds:p-[var(--spacing-md)]',\n },\n interactive: {\n true: 'ds:hover:bg-[color:var(--muted)]/40 ds:cursor-pointer',\n false: '',\n },\n surface: {\n // `flat` (default) is the chrome-less row used inside a bordered\n // AppointmentTray. `elevated` gives each row its own card chrome\n // (border + shadow) for use directly on a rail, e.g. AppointmentTimeline.\n // Uses `--shadow-sm` (a row lift), not `--shadow-card`/`--shadow-lg`:\n // the rail's `overflow-y:auto` scroll region clips `overflow-x` at a\n // narrow gutter, so a wide 30px-blur shadow gets a hard-edged clip.\n flat: '',\n elevated:\n 'ds:border ds:border-[color:var(--card-border)] ds:[.theme-accessible_&]:border-2 ds:shadow-[var(--shadow-sm)]',\n },\n },\n defaultVariants: {\n size: 'sm',\n interactive: false,\n surface: 'flat',\n },\n },\n);\n\nconst stretchedLinkClass = [\n 'ds:focus-visible:outline-none',\n \"ds:after:content-[''] ds:after:absolute ds:after:inset-0 ds:after:rounded-[var(--radius-md)]\",\n 'ds:after:pointer-events-auto',\n 'ds:focus-visible:after:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:after:outline-solid',\n 'ds:focus-visible:after:outline-[color:var(--ring)]',\n 'ds:focus-visible:after:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:after:outline-[CanvasText]',\n].join(' ');\n\nconst TYPE_ICON: Record<AppointmentType, typeof MapPin> = {\n inPractice: MapPin,\n telehealth: Video,\n};\n\n/* -------------------------------------------------------------------- */\n/* Props */\n/* -------------------------------------------------------------------- */\n\nexport interface AppointmentCardProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'onClick' | 'role' | 'title'>,\n VariantProps<typeof appointmentCardVariants> {\n /** The appointment to render. */\n item: AppointmentItem;\n /** Visual density. */\n size?: 'sm' | 'md';\n /**\n * `'flat'` (default) — chrome-less row for use inside a bordered\n * `AppointmentTray`. `'elevated'` — each row carries its own card chrome\n * (border + shadow), for placing rows directly on a rail (AppointmentTimeline).\n */\n surface?: 'flat' | 'elevated';\n /** BCP-47 locale override for the timestamp + currency. */\n locale?: string;\n /** ISO-4217 currency code for the advance-deposit chip. Defaults to `EUR`. */\n currency?: string;\n /**\n * Show the patient identity (avatar + name as the row title). Default `true`.\n * Set `false` in single-patient surfaces (e.g. a patient's own\n * `AppointmentTimeline`) where repeating the name is redundant — the row then\n * leads with the operator as its title, falling back to a generic label.\n */\n showPatient?: boolean;\n /** Fires when the row is activated. */\n onActivate?: (item: AppointmentItem) => void;\n}\n\n/* -------------------------------------------------------------------- */\n/* Component */\n/* -------------------------------------------------------------------- */\n\nexport const AppointmentCard = forwardRef<HTMLDivElement, AppointmentCardProps>(\n (\n {\n item,\n size = 'sm',\n surface = 'flat',\n locale,\n currency = 'EUR',\n showPatient = true,\n onActivate,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n const interactive = !!onActivate;\n const hasSafeUrl = !!item.url && isSafeEntityUrl(item.url);\n\n const patientName = item.patient?.name ?? t('appointmentCard.noPatient');\n const operatorName = item.operator?.name;\n const stateLabel = t(`appointmentCard.state.${item.state}`);\n\n const avatarSize = size === 'md' ? 'md' : 'sm';\n const TypeIcon = TYPE_ICON[item.type];\n\n // In single-patient context the patient name is redundant, so the row leads\n // with the operator (the \"who am I seeing\") and falls back to a generic\n // label when no operator is set.\n const title = showPatient\n ? patientName\n : (operatorName ?? t('appointmentCard.appointment'));\n\n const ariaLabel = showPatient\n ? t('appointmentCard.itemLabel', {\n patient: patientName,\n state: stateLabel,\n })\n : t('appointmentCard.itemLabelGeneric', { title, state: stateLabel });\n\n const titleNode = (\n <span className=\"ds:min-w-0 ds:truncate type-title-item ds:text-[color:var(--foreground)]\">\n {title}\n </span>\n );\n\n let activator: ReactNode;\n if (interactive && hasSafeUrl) {\n activator = (\n <a\n href={item.url}\n aria-label={ariaLabel}\n className={stretchedLinkClass + ' ds:contents'}\n onClick={(e) => {\n if (e.defaultPrevented || e.metaKey || e.ctrlKey || e.shiftKey)\n return;\n onActivate?.(item);\n }}\n >\n {titleNode}\n </a>\n );\n } else if (interactive) {\n activator = (\n <button\n type=\"button\"\n aria-label={ariaLabel}\n className={\n stretchedLinkClass +\n ' ds:contents ds:bg-transparent ds:border-0 ds:p-0 ds:text-start'\n }\n onClick={() => onActivate?.(item)}\n >\n {titleNode}\n </button>\n );\n } else {\n activator = titleNode;\n }\n\n // Treatment / tooth-element Tags. Each treatment becomes one Tag; the\n // tooth elements (when present) are appended to the visible label.\n const treatmentTags = (item.treatments ?? []).map((tx, index) => {\n const label =\n tx.elements && tx.elements.length > 0\n ? t('appointmentCard.treatmentWithElements', {\n care: tx.careName,\n elements: tx.elements.join(', '),\n })\n : tx.careName;\n return (\n <Tag\n key={`${tx.careName}-${index}`}\n label={label}\n variant=\"neutral\"\n fill=\"outline\"\n size=\"sm\"\n maxInlineSize=\"12rem\"\n />\n );\n });\n\n const advanceCents = item.bookingReason?.advanceAmountCents;\n const hasAdvance = typeof advanceCents === 'number' && advanceCents > 0;\n\n return (\n <div\n ref={ref}\n role=\"listitem\"\n data-component=\"appointment-card\"\n data-component-id={item.id}\n data-state={item.state}\n data-type={item.type}\n className={appointmentCardVariants({\n size,\n interactive,\n surface,\n className,\n })}\n {...rest}\n >\n {/* Leading rail: type glyph + start time + duration */}\n <span className=\"ds:flex ds:w-16 ds:shrink-0 ds:flex-col ds:items-start ds:gap-[var(--spacing-2xs)]\">\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)] ds:text-[color:var(--muted-foreground)]\">\n <TypeIcon aria-hidden=\"true\" className=\"ds:size-3.5 ds:shrink-0\" />\n <span className=\"ds:sr-only\">\n {t(`appointmentCard.type.${item.type}`)}\n </span>\n <Timestamp\n value={item.startIso}\n format=\"absolute\"\n shape=\"bare\"\n locale={locale}\n absoluteFormat={{ hour: 'numeric', minute: '2-digit' }}\n className=\"type-body-sm ds:font-medium ds:text-[color:var(--foreground)] ds:tabular-nums\"\n />\n </span>\n <span className=\"type-eyebrow ds:text-[color:var(--muted-foreground)]\">\n {t('appointmentCard.duration', { count: item.durationMin })}\n </span>\n </span>\n\n {/* Operator avatar with colour dot */}\n {operatorName ? (\n <span className=\"ds:relative ds:shrink-0\">\n <Avatar\n name={operatorName}\n color={colorIdToAvatarToken(item.operator?.colorId)}\n size={avatarSize}\n aria-hidden=\"true\"\n role=\"presentation\"\n aria-label={undefined}\n />\n <span\n aria-hidden=\"true\"\n className={\n 'ds:absolute ds:bottom-0 ds:end-0 ds:size-2.5 ds:rounded-[var(--radius-full)] ds:border ds:border-[color:var(--card)] ' +\n operatorDotClass(item.operator?.colorId)\n }\n />\n </span>\n ) : null}\n\n {/* Main content column */}\n <div className=\"ds:flex-1 ds:min-w-0 ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <div className=\"ds:flex ds:items-start ds:gap-[var(--spacing-sm)]\">\n <div className=\"ds:flex-1 ds:min-w-0 ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n {showPatient && item.patient?.avatarUrl ? (\n <Avatar\n name={patientName}\n src={item.patient.avatarUrl}\n size={avatarSize}\n className=\"ds:shrink-0\"\n aria-hidden=\"true\"\n role=\"presentation\"\n aria-label={undefined}\n />\n ) : null}\n {activator}\n </div>\n <Badge\n variant={appointmentStateBadge(item.state)}\n size=\"sm\"\n withDot\n className=\"ds:shrink-0\"\n >\n {stateLabel}\n </Badge>\n </div>\n\n {/* Meta line: operator name · specialty · first visit\n (chair moved to a chip below). When the patient is hidden the\n operator is promoted to the title, so it drops out of the meta. */}\n {(showPatient && operatorName) ||\n item.bookingReason?.specialty ||\n item.firstVisit === 'yes' ? (\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-x-[var(--spacing-sm)] ds:gap-y-[var(--spacing-2xs)] type-eyebrow ds:text-[color:var(--muted-foreground)]\">\n {showPatient && operatorName ? <span>{operatorName}</span> : null}\n {item.bookingReason?.specialty ? (\n <span>{item.bookingReason.specialty}</span>\n ) : null}\n {item.firstVisit === 'yes' ? (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-2xs)]\">\n <Star aria-hidden=\"true\" className=\"ds:size-3 ds:shrink-0\" />\n {t('appointmentCard.firstVisit')}\n </span>\n ) : null}\n </div>\n ) : null}\n\n {/* Booking reason */}\n {item.bookingReason?.description ? (\n <span className=\"type-body-sm ds:text-[color:var(--foreground)] ds:truncate\">\n {item.bookingReason.description}\n </span>\n ) : null}\n\n {/* Treatment / tooth Tags */}\n {treatmentTags.length > 0 ? (\n <div className=\"ds:flex ds:flex-wrap ds:gap-[var(--spacing-2xs)]\">\n {treatmentTags}\n </div>\n ) : null}\n\n {/* Chips: care plan · chair · flags · advance-deposit */}\n {item.carePlan ||\n item.chair ||\n item.flags?.bookedOnline ||\n item.flags?.highlightedAnamnesis ||\n hasAdvance ? (\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)]\">\n {item.carePlan ? (\n <Badge\n variant=\"accentSoft\"\n size=\"sm\"\n leading={<ClipboardPlus />}\n >\n {t('appointmentCard.carePlan', {\n number: item.carePlan.number,\n })}\n </Badge>\n ) : null}\n {item.chair ? (\n <Badge variant=\"neutral\" size=\"sm\" leading={<Armchair />}>\n {t('appointmentCard.chair', { chair: item.chair })}\n </Badge>\n ) : null}\n {item.flags?.bookedOnline ? (\n <Badge variant=\"info\" size=\"sm\" leading={<Globe />}>\n {t('appointmentCard.flag.bookedOnline')}\n </Badge>\n ) : null}\n {item.flags?.highlightedAnamnesis ? (\n <Badge variant=\"warning\" size=\"sm\" withDot>\n {t('appointmentCard.flag.highlightedAnamnesis')}\n </Badge>\n ) : null}\n {hasAdvance ? (\n <TransactionChip\n state=\"to-invoice\"\n amount={(advanceCents as number) / 100}\n currency={currency}\n locale={locale}\n size=\"sm\"\n showLabel\n />\n ) : null}\n </div>\n ) : null}\n </div>\n\n {interactive ? (\n <ChevronRight\n aria-hidden=\"true\"\n className=\"ds:size-4 ds:shrink-0 ds:self-center ds:text-[color:var(--muted-foreground)] ds:opacity-0 ds:transition-opacity ds:motion-reduce:transition-none ds:group-hover:opacity-100 ds:group-focus-within:opacity-100 ds:rtl:rotate-180\"\n />\n ) : null}\n </div>\n );\n },\n);\n\nAppointmentCard.displayName = 'AppointmentCard';\n"],"names":["__iconNode","Armchair","createLucideIcon","ClipboardPlus","OPERATOR_DOT_CLASS","operatorDotClass","colorId","colorIdToToken","appointmentCardVariants","cva","stretchedLinkClass","TYPE_ICON","MapPin","Video","AppointmentCard","forwardRef","item","size","surface","locale","currency","showPatient","onActivate","className","rest","ref","t","useTranslation","interactive","hasSafeUrl","isSafeEntityUrl","patientName","_a","operatorName","_b","stateLabel","avatarSize","TypeIcon","title","ariaLabel","titleNode","jsx","activator","e","treatmentTags","tx","index","label","Tag","advanceCents","_c","hasAdvance","jsxs","Timestamp","Avatar","colorIdToAvatarToken","_d","_e","_f","Badge","appointmentStateBadge","_g","_h","Star","_i","_j","_k","_l","Globe","_m","TransactionChip","ChevronRight"],"mappings":"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","x_google_ignoreList":[0,1]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"calendar-4dXTvsCz.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 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.',\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 DateSelectArg,\n EventInput,\n FormatterInput,\n} from '@fullcalendar/core';\nimport { 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 { 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 | '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 '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 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 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 isRecurrenceParent?: boolean;\n /** Rendered as a background event; not clickable. */\n isInternal?: 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 /** Initials for the compact \"avatar\" label (e.g. \"MR\"). */\n shortTitle?: string;\n /** Hex background colour for the dot or initials circle. */\n color?: string;\n /** Hex text colour for the initials circle. */\n shortTitleTextColor?: 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 * 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 /** 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 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 /** 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 * Render the decorative status accent bar on event cards.\n * The platform's model (colour = picker choice, status = icons) passes\n * false. @default true\n */\n eventStatusAccent?: boolean;\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 /** 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 * When true, render a round initials avatar (using\n * `resource.shortTitle` + `resource.color` + `resource.shortTitleTextColor`)\n * in the resource label. When false (default), a small coloured dot\n * prefixes the title when `resource.color` is set.\n */\n showResourceInitials?: 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 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 onDateSelect,\n onDatesSet,\n onDateClick,\n editable = false,\n eventDurationEditable,\n selectable = false,\n height,\n className,\n privacyMode = false,\n eventStatusAccent = true,\n mode = 'default',\n modeLabel,\n modeBannerColor,\n modeBannerTextColor,\n onModeCancel,\n alertBanner,\n hiddenDays,\n slotMinTime,\n slotMaxTime,\n slotDuration,\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 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 /* ---- 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\"`. */\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>('.fc-daygrid-more-link')\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 ...(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 isRecurrenceParent: event.isRecurrenceParent ?? false,\n isInternal: event.isInternal ?? 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: 'numeric' as const,\n minute: '2-digit' as const,\n }),\n [],\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 isRecurrenceParent: ext.isRecurrenceParent,\n isInternal: ext.isInternal,\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 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 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 if (ext.isInternal) return; // background events are not clickable\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 }\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 shortTitle = ext.shortTitle;\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 (showResourceInitials && shortTitle && color) {\n /* DEV-only guardrail: the initials circle is the one resource\n branch that actually paints text over the caller-supplied\n colour. Warn when the pair falls below WCAG AA. */\n warnLowContrast(color, textColor, `resource ${arg.resource.id}`);\n const initialsClass = [\n 'resource-initials',\n 'ds:[background-color:var(--resource-color)]',\n textColor ? 'ds:[color:var(--resource-initials-text-color)]' : null,\n ]\n .filter(Boolean)\n .join(' ');\n return (\n <span className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <span\n className={initialsClass}\n // eslint-disable-next-line react/forbid-dom-props -- caller-supplied resource colours injected via CSS variables\n style={swatchStyle}\n aria-hidden=\"true\"\n >\n {shortTitle}\n </span>\n <span className=\"ds:truncate ds:text-start\">{title}</span>\n </span>\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],\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 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 const wrapperClassName = [\n 'fc-theme-alfadocs',\n zebraRows ? 'calendar-zebra-rows' : 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 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 {...(maskClassList ? { eventClassNames: maskClassList } : {})}\n headerToolbar={false}\n allDayText={t('calendar.allDay')}\n noEventsText={t('calendar.noEvents')}\n titleFormat={titleFormat}\n dayHeaderFormat={dayHeaderFormat}\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 // 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 return (\n <CalendarEventCard\n eventId={arg.event.id}\n title={\n privacyMode\n ? (ext.privacyModeTitle ?? '•••')\n : arg.event.title\n }\n suffix={ext.suffix}\n rangeText={formatRangeText(arg, locale)}\n showTime={showTime}\n allDay={arg.event.allDay}\n status={ext.status}\n statusAccent={eventStatusAccent}\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 resourceLabel={\n ext.resourceId\n ? (resources ?? []).find((r) => r.id === ext.resourceId)\n ?.title\n : undefined\n }\n />\n );\n }}\n eventClick={handleEventClick}\n eventDrop={handleEventDrop}\n eventResize={handleEventResize}\n eventDragStart={onEventDragStart}\n eventResizeStart={onEventResizeStart}\n select={handleDateSelect}\n dateClick={handleDateClick}\n datesSet={handleDatesSet}\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","onDateSelect","onDatesSet","onDateClick","editable","eventDurationEditable","selectable","height","privacyMode","eventStatusAccent","mode","modeLabel","modeBannerColor","modeBannerTextColor","onModeCancel","alertBanner","hiddenDays","slotMinTime","slotMaxTime","slotDuration","showTime","slotEventOverlap","stickyHeaderDates","nowIndicator","dayMaxEvents","schedulerLicenseKey","toolbar","toolbarEnd","showResourceInitials","resourceAreaWidth","resourceAreaHeader","defaultTimedEventDuration","zebraRows","fcRef","useRef","rootRef","liveRegionRef","focusTimerRef","focusedElRef","lastNativeEventClickRef","gestureRef","nativeDateClickGestureRef","synthDateClickGestureRef","direction","setDirection","timer","api","root","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","fcDefaultTimedEventDuration","maskClassList","resourceAreaHeaderContent","perDateHiding","perDateHidingRef","colSpanTouchedRef","dayCellClassNames","useCallback","hiding","resourceLabelClassNames","dayHeaderClassNames","handleDayHeaderDidMount","iso","span","syncDateHeaderColSpans","adaptEvent","fcEvent","ext","handleEventDrop","oldStart","handleEventResize","oldEnd","newEnd","newStart","duration","handleEventClick","handleDateSelect","handleDateClick","gestureId","handleDatesSet","firstDay","plugins","dayGridPlugin","timeGridPlugin","listPlugin","interactionPlugin","resourcePlugin","resourceTimeGridPlugin","resourceTimelinePlugin","timelinePlugin","resolvedView","handlePointerDown","handleRootClick","target","gesture","cell","cardEl","anchorEl","dateAttr","renderResourceLabel","shortTitle","color","textColor","swatchStyle","warnLowContrast","initialsClass","fcResources","raf","handleToolbarToday","_b","handleToolbarPrev","handleToolbarNext","wrapperClassName","modeBannerStyle","resolvedModeLabel","modeBannerClassName","modeCancelClassName","FullCalendar","CalendarEventCard","r","Calendar"],"mappings":";;;;;;;;;;;;;;;;;AAWO,MAAMA,KAA8C;AAAA,EACzD,IAAI;AAAA,EACJ,cAAc,CAAC,eAAe,kBAAkB,MAAM;AAAA,EACtD,OAAO;AAAA,IACL,aAAa;AAAA,MACX,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,MAAM,CAACC,MAAWA,EAAO,oBAAoB;AAAA,IAAA;AAAA,IAE/C,aAAa;AAAA,MACX,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,MAAM,CAACA,MAAA;;AAAW,iBAAAC,IAAAD,EAAO,eAAA,MAAP,gBAAAC,EAAyB,kBAAiB;AAAA;AAAA,IAAA;AAAA,IAE9D,cAAc;AAAA,MACZ,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,MAAM,CAACD,MAAWA,EAAO,SAAA;AAAA,IAAS;AAAA,EACpC;AAAA,EAEF,SAAS;AAAA,IACP,OAAO;AAAA,MACL,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CAACA,MAAW;AAClB,QAAAA,EAAO,MAAA;AAAA,MACT;AAAA,IAAA;AAAA,IAEF,MAAM;AAAA;AAAA,MAEJ,QAAQ;AAAA,MACR,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CAACA,MAAW;AAClB,QAAAA,EAAO,KAAA;AAAA,MACT;AAAA,IAAA;AAAA,IAEF,MAAM;AAAA;AAAA,MAEJ,QAAQ;AAAA,MACR,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CAACA,MAAW;AAClB,QAAAA,EAAO,KAAA;AAAA,MACT;AAAA,IAAA;AAAA,IAEF,WAAW;AAAA,MACT,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY;AAAA,UACV,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,QAAQ;AAAA,YACR,aAAa;AAAA,UAAA;AAAA,QACf;AAAA,QAEF,UAAU,CAAC,MAAM;AAAA,MAAA;AAAA,MAEnB,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,UAAU;AAAA,QACR,EAAE,MAAM,EAAE,MAAM,aAAA,GAAgB,MAAM,yBAAA;AAAA,MAAyB;AAAA,MAEjE,QAAQ,CAACA,GAAQE,MAAkC;AACjD,QAAAF,EAAO,SAASE,EAAK,IAAI;AAAA,MAC3B;AAAA,IAAA;AAAA,IAEF,aAAa;AAAA,MACX,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY;AAAA,UACV,MAAM;AAAA,YACJ,MAAM;AAAA,YACN,MAAM;AAAA,cACJ;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,YAAA;AAAA,YAEF,aAAa;AAAA,UAAA;AAAA,QACf;AAAA,QAEF,UAAU,CAAC,MAAM;AAAA,MAAA;AAAA,MAEnB,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,UAAU;AAAA,QACR,EAAE,MAAM,EAAE,MAAM,eAAA,GAAkB,MAAM,2BAAA;AAAA,MAA2B;AAAA,MAErE,QAAQ,CAACF,GAAQE,MAAiC;AAChD,QAAAF,EAAO,WAAWE,EAAK,IAAI;AAAA,MAC7B;AAAA,IAAA;AAAA,IAEF,aAAa;AAAA;AAAA;AAAA,MAGX,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY;AAAA,UACV,SAAS;AAAA,YACP,MAAM;AAAA,YACN,aAAa;AAAA,UAAA;AAAA,QACf;AAAA,QAEF,UAAU,CAAC,SAAS;AAAA,MAAA;AAAA,MAEtB,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CAAC,iDAAiD;AAAA,MAC1D,QAAQ,CAACF,GAAQE,MAA8B;AAC7C,QAAAF,EAAO,WAAWE,EAAK,OAAO;AAAA,MAChC;AAAA,IAAA;AAAA,EACF;AAAA,EAEF,UAAU;AAAA,IACR,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aAAa;AAAA,IAAA;AAAA,IAEf,YAAY;AAAA,MACV,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,aAAa;AAAA,IAAA;AAAA,IAEf,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,aACE;AAAA,IAAA;AAAA,EACJ;AAEJ,GCrEMC,KAAoB;AAAA,EACxB,UAAU;AAAA,IACR,KAAK;AAAA,IACL,WAAW;AAAA,IACX,MAAM;AAAA,EAAA;AAAA,EAER,YAAY;AAAA,IACV,KAAK;AAAA,IACL,WAAW;AAAA,IACX,MAAM;AAAA,EAAA;AAEV,GAOMC,yBAAqB,IAAkB;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC,GASKC,KAAsE;AAAA,EAC1E,aAAa;AAAA,EACb,cAAc;AAChB;AAWO,SAASC,GACdC,GACAC,IAA4C,YACpC;AACR,MAAIJ,GAAe,IAAIG,CAAI;AACzB,WAAIC,MAAmB,eACdH,GAA6BE,CAAI,KAAKA,IAExCA;AAKT,QAAME,IADgBF,EAAK,QAAQ,qBAAqB,EAAE,EAC/B;AAAA,IACzB;AAAA,IACA;AAAA,EAAA;AAEF,SAAOJ,GAAkBK,CAAc,EAAEC,CAAI;AAC/C;AAKA,MAAMC,KAAmC;AAAA,EACvC,SAAS;AAAA,EACT,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM;AACR,GAKMC,KAA+C;AAAA,EACnD,EAAE,SAAS,SAAS,KAAK,WAAW,OAAO,QAAA;AAAA,EAC3C,EAAE,MAAM,WAAW,QAAQ,UAAA;AAC7B,GASMC,KAAkD;AAAA,EACtD,2BAA2B;AAAA,IACzB,MAAM;AAAA,IACN,UAAU,EAAE,MAAM,EAAA;AAAA,EAAE;AAAA,EAEtB,2BAA2B;AAAA,IACzB,MAAM;AAAA,IACN,UAAU,EAAE,MAAM,EAAA;AAAA,EAAE;AAAA,EAEtB,UAAU,EAAE,iBAAiBD,GAAA;AAAA,EAC7B,aAAa,EAAE,aAAaD,GAAA;AAAA,EAC5B,qBAAqB,EAAE,aAAaA,GAAA;AAAA,EACpC,aAAa,EAAE,aAAaA,GAAA;AAAA,EAC5B,qBAAqB,EAAE,aAAaA,GAAA;AACtC,GA8dMG,KAA0B,GAI1BC,KAAqE;AAAA,EACzE,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,MAAM;AACR;AAoBO,SAASC,GAAgBC,GAAwB;AACtD,MAAI;AACF,UAAMC,IAAa,IAAI,KAAK,OAAOD,CAAM,GACnCE,IACJ,OAAOD,EAAW,eAAgB,aAC9BA,EAAW,gBACXA,EAAW;AACjB,QAAIC,KAAQ,OAAOA,EAAK,YAAa;AACnC,aAAOA,EAAK,WAAW;AAAA,EAE3B,QAAQ;AAAA,EAER;AACA,SACEF,EAAO,WAAW,OAAO,KACzBA,EAAO,WAAW,IAAI,KACtBA,EAAO,WAAW,OAAO,IAElB,IAEF;AACT;AAQA,MAAMG,KAAmB;AAKzB,SAASC,GAAmBC,GAAoB;AAC9C,QAAMC,IAAID,EAAK,YAAA,GACTE,IAAI,OAAOF,EAAK,SAAA,IAAa,CAAC,EAAE,SAAS,GAAG,GAAG,GAC/C,IAAI,OAAOA,EAAK,QAAA,CAAS,EAAE,SAAS,GAAG,GAAG;AAChD,SAAO,GAAGC,CAAC,IAAIC,CAAC,IAAI,CAAC;AACvB;AAsBO,SAASC,GACdC,GACAC,GACe;AACf,QAAMC,wBAAkB,IAAA,GAClBC,wBAAwB,IAAA,GACxBC,KAAgBJ,KAAA,gBAAAA,EAAW,WAAU;AAI3C,MAAIA,KAAaC;AACf,eAAWI,KAAYL;AACrB,UAAKK,EAAS;AACd,mBAAWT,KAAQS,EAAS,aAAa;AACvC,gBAAMC,IAAM,GAAGD,EAAS,EAAE,IAAIT,CAAI;AAClC,UAAIM,EAAY,IAAII,CAAG,MACvBJ,EAAY,IAAII,CAAG,GACnBH,EAAkB,IAAIP,IAAOO,EAAkB,IAAIP,CAAI,KAAK,KAAK,CAAC;AAAA,QACpE;AAAA;AAGJ,SAAO;AAAA,IACL,aAAAM;AAAA,IACA,mBAAAC;AAAA,IACA,eAAAC;AAAA,IACA,QAAQF,EAAY,OAAO;AAAA,EAAA;AAE/B;AAQA,SAASK,KAAoB;AAC3B,QAAM,EAAE,MAAAC,EAAA,IAASC,GAAA,GACX,CAACC,GAAOC,CAAQ,IAAIC,GAAkB,MAAM;AAChD,QAAI,OAAO,WAAa,IAAa,QAAO;AAC5C,UAAMC,IAAS,SAAS,gBAAgB,aAAa,KAAK,GACpDC,IAAU,OAAON,EAAK,OAAQ,aAAaA,EAAK,QAAQ;AAC9D,WAAOK,MAAW,SAASC,MAAY;AAAA,EACzC,CAAC;AAED,SAAAC,EAAU,MAAM;AACd,QAAI,OAAO,WAAa,IAAa;AACrC,UAAMC,IAAW,IAAI,iBAAiB,MAAM;AAC1C,YAAMH,IAAS,SAAS,gBAAgB,aAAa,KAAK,GACpDC,IAAU,OAAON,EAAK,OAAQ,aAAaA,EAAK,QAAQ;AAC9D,MAAAG,EAASE,MAAW,SAASC,MAAY,KAAK;AAAA,IAChD,CAAC;AACD,WAAAE,EAAS,QAAQ,SAAS,iBAAiB;AAAA,MACzC,YAAY;AAAA,MACZ,iBAAiB,CAAC,OAAO,MAAM;AAAA,IAAA,CAChC,GACM,MAAMA,EAAS,WAAA;AAAA,EACxB,GAAG,CAACR,CAAI,CAAC,GAEFE;AACT;AAwBA,SAASO,GACPC,GACA3B,GACoB;AACpB,QAAM4B,IAAQD,EAAI,MAAM,OAClBE,IAAMF,EAAI,MAAM,OAAOA,EAAI,MAAM;AACvC,MAAI,GAACC,KAAS,CAACC;AACf,QAAI;AACF,YAAMC,IAAM,IAAI,KAAK,eAAe9B,GAAQ;AAAA,QAC1C,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,QAAQ;AAAA,MAAA,CACT;AACD,aAAO,OAAO8B,EAAI,eAAgB,aAC9BA,EAAI,YAAYF,GAAOC,CAAG,IAC1B,GAAGC,EAAI,OAAOF,CAAK,CAAC,MAAME,EAAI,OAAOD,CAAG,CAAC;AAAA,IAC/C,QAAQ;AACN;AAAA,IACF;AACF;AA+BA,MAAME,KAAyB;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,EAAE,KAAK,GAAG,GAEJC,KAAyB;AAAA,EAC7BD;AAAA,EACA;AACF,EAAE,KAAK,GAAG,GAEJE,KAAyB;AAAA,EAC7BF;AAAA,EACA;AACF,EAAE,KAAK,GAAG,GAEGG,KAAkBC;AAAA,EAC7B,CAAC,EAAE,OAAAC,GAAO,SAAAC,GAAS,QAAAC,GAAQ,QAAAC,GAAQ,KAAAV,GAAK,WAAAW,GAAW,eAAAC,EAAA,GAAiBC,MAAQ;AAC1E,UAAM,EAAE,GAAAC,EAAA,IAAMzB,GAAA,GACRC,IAAQH,GAAA,GACR4B,IAAWzB,IAAQ0B,KAAeC,IAClCC,IAAW5B,IAAQ2B,KAAcD,IAEjCG,IAAgB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACAR;AAAA,IAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG,GAMLS,IAAwB,CAACjB,IAAwBS,CAAa,EACjE,OAAO,OAAO,EACd,KAAK,GAAG,GACLS,IAAwB,CAACjB,IAAwBQ,CAAa,EACjE,OAAO,OAAO,EACd,KAAK,GAAG,GACLU,KAAiB;AAAA,MACrB;AAAA,MACAV;AAAA,IAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG,GACLW,KAAkB,CAAC,4BAA4BX,CAAa,EAC/D,OAAO,OAAO,EACd,KAAK,GAAG;AAEX,6BACG,OAAA,EAAI,KAAAC,GAAU,WAAWM,GACxB,UAAA;AAAA,MAAA,gBAAAK,EAAC,OAAA,EAAI,WAAU,sDACb,UAAA;AAAA,QAAA,gBAAAC;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAASjB;AAAA,YACT,WAAWY;AAAA,YAEV,YAAE,gBAAgB;AAAA,UAAA;AAAA,QAAA;AAAA,QAErB,gBAAAK;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAShB;AAAA,YACT,cAAYK,EAAE,yBAAyB;AAAA,YACvC,WAAWO;AAAA,YAEX,4BAACN,GAAA,EAAS,MAAM,IAAI,eAAY,QAAO;AAAA,UAAA;AAAA,QAAA;AAAA,QAEzC,gBAAAU;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAASf;AAAA,YACT,cAAYI,EAAE,qBAAqB;AAAA,YACnC,WAAWO;AAAA,YAEX,4BAACH,GAAA,EAAS,MAAM,IAAI,eAAY,QAAO;AAAA,UAAA;AAAA,QAAA;AAAA,MACzC,GACF;AAAA,MACCX,IACC,gBAAAkB,EAAC,MAAA,EAAG,aAAU,UAAS,WAAWH,IAC/B,UAAAf,GACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAOC,OAAA,EAAI,eAAY,QAAO,WAAWgB,IAAiB;AAAA;AAAA,MAErDvB,sBACE,OAAA,EAAI,WAAU,sDACZ,aACH,IACE;AAAA,IAAA,GACN;AAAA,EAEJ;AACF;AACAK,GAAgB,cAAc;AAM9B,MAAMqB,KAAgBpB;AAAA,EACpB,CACE;AAAA,IACE,IAAAqB;AAAA,IACA,QAAAC;AAAA,IACA,WAAAhD;AAAA,IACA,MAAAlB,IAAO;AAAA,IACP,aAAAmE;AAAA,IACA,QAAQC;AAAA,IACR,aAAAC;AAAA,IACA,eAAAC;AAAA,IACA,kBAAAC;AAAA,IACA,oBAAAC;AAAA,IACA,cAAAC;AAAA,IACA,cAAAC;AAAA,IACA,YAAAC;AAAA,IACA,aAAAC;AAAA,IACA,UAAAC,IAAW;AAAA,IACX,uBAAAC;AAAA,IACA,YAAAC,KAAa;AAAA,IACb,QAAAC;AAAA,IACA,WAAA/B;AAAA,IACA,aAAAgC,IAAc;AAAA,IACd,mBAAAC,KAAoB;AAAA,IACpB,MAAAC,IAAO;AAAA,IACP,WAAAC;AAAA,IACA,iBAAAC;AAAA,IACA,qBAAAC;AAAA,IACA,cAAAC;AAAA,IACA,aAAAC;AAAA,IACA,YAAAC;AAAA,IACA,aAAAC;AAAA,IACA,aAAAC;AAAA,IACA,cAAAC;AAAA,IACA,UAAAC,KAAW;AAAA,IACX,qBAAA1E,KAAsB;AAAA,IACtB,kBAAA2E,KAAmB;AAAA,IACnB,mBAAAC,KAAoB;AAAA,IACpB,cAAAC,KAAe;AAAA,IACf,cAAAC,KAAe;AAAA,IACf,qBAAAC,KAAsB;AAAA,IACtB,SAAAC,KAAU;AAAA,IACV,YAAAC;AAAA,IACA,gBAAAnG,IAAiB;AAAA,IACjB,sBAAAoG,KAAuB;AAAA,IACvB,mBAAAC;AAAA,IACA,oBAAAC;AAAA,IACA,2BAAAC;AAAA,IACA,WAAAC,KAAY;AAAA,IACZ,eAAAvD;AAAA,EAAA,GAEFC,OACG;AACH,UAAM,EAAE,GAAAC,GAAG,MAAA1B,EAAA,IAASC,GAAA,GACd+E,IAAQC,EAA4B,IAAI,GACxCC,IAAUD,EAAuB,IAAI,GACrCE,IAAgBF,EAAuB,IAAI,GAC3CG,IAAgBH,EAA6C,IAAI,GACjEI,IAAeJ,EAA2B,IAAI,GAY9CK,KAA0BL,EAA0B,IAAI,GASxDM,IAAaN,EAA6C;AAAA,MAC9D,IAAI;AAAA,MACJ,GAAG;AAAA,MACH,GAAG;AAAA,IAAA,CACJ,GACKO,KAA4BP,EAAO,CAAC,GACpCQ,KAA2BR,EAAO,CAAC,GAEnClG,IAAS2D,KAAc1C,EAAK,YAAY;AAO9C,IAAAO,EAAU,MAAM;AAAA,IAahB,GAAG,CAACwD,EAAU,CAAC,GAMfxD,EAAU,MAAM;AAAA,IAkBhB,GAAG,CAACuE,CAAyB,CAAC;AAG9B,UAAM,CAACY,IAAWC,EAAY,IAAIvF,GAAwB,MAAM;AAC9D,UAAI,OAAO,WAAa,IAAa,QAAO;AAC5C,YAAMC,IAAS,SAAS,gBAAgB,aAAa,KAAK,GACpDC,IAAU,OAAON,EAAK,OAAQ,aAAaA,EAAK,QAAQ;AAC9D,aAAOK,MAAW,SAASC,MAAY,QAAQ,QAAQ;AAAA,IACzD,CAAC;AAED,IAAAC,EAAU,MAAM;AACd,UAAI,OAAO,WAAa,IAAa;AACrC,YAAMC,IAAW,IAAI,iBAAiB,MAAM;AAC1C,cAAMH,IAAS,SAAS,gBAAgB,aAAa,KAAK,GACpDC,IAAU,OAAON,EAAK,OAAQ,aAAaA,EAAK,QAAQ;AAC9D,QAAA2F,GAAatF,MAAW,SAASC,MAAY,QAAQ,QAAQ,KAAK;AAAA,MACpE,CAAC;AACD,aAAAE,EAAS,QAAQ,SAAS,iBAAiB;AAAA,QACzC,YAAY;AAAA,QACZ,iBAAiB,CAAC,OAAO,MAAM;AAAA,MAAA,CAChC,GACM,MAAMA,EAAS,WAAA;AAAA,IACxB,GAAG,CAACR,CAAI,CAAC,GAGTO,EAAU,MAAM;AACd,UAAI,OAAO,WAAa,IAAa;AACrC,UAAIqF;AACJ,YAAMpF,IAAW,IAAI,iBAAiB,MAAM;AAC1C,qBAAaoF,CAAK,GAClBA,IAAQ,WAAW,MAAM;;AACvB,gBAAMC,KAAM7H,IAAAgH,EAAM,YAAN,gBAAAhH,EAAe;AAC3B,UACE6H,KACA,OAAQA,EAAgC,UAAW,cAElDA,EAA+B,OAAA;AAAA,QAEpC,GAAG,EAAE;AAAA,MACP,CAAC;AACD,aAAArF,EAAS,QAAQ,SAAS,iBAAiB;AAAA,QACzC,YAAY;AAAA,QACZ,iBAAiB,CAAC,OAAO;AAAA,MAAA,CAC1B,GACM,MAAM;AACX,qBAAaoF,CAAK,GAClBpF,EAAS,WAAA;AAAA,MACX;AAAA,IACF,GAAG,CAAA,CAAE,GAkBLD,EAAU,MAAM;AACd,UAAI,OAAO,WAAa,IAAa;AACrC,YAAMuF,IAAOZ,EAAQ;AACrB,UAAI,CAACY,EAAM;AAEX,YAAMC,IAAc,MAAM;AACxB,QAAAD,EACG,iBAAoC,uBAAuB,EAC3D,QAAQ,CAACE,MAAS;AACjB,UAAKA,EAAK,aAAa,MAAM,KAC3BA,EAAK,aAAa,QAAQ,QAAQ;AAAA,QAEtC,CAAC,GAYHF,EACG,iBAA8B,sBAAsB,EACpD,QAAQ,CAACG,MAAW;AACnB,UAAAA,EACG;AAAA,YACC;AAAA,UAAA,EAED,QAAQ,CAACC,MAAO;AACf,YAAAA,EAAG,aAAa,YAAY,IAAI;AAAA,UAClC,CAAC;AAAA,QACL,CAAC;AAAA,MACL;AAEA,MAAAH,EAAA;AACA,YAAMvF,IAAW,IAAI,iBAAiBuF,CAAW;AACjD,aAAAvF,EAAS,QAAQsF,GAAM;AAAA,QACrB,WAAW;AAAA,QACX,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,iBAAiB,CAAC,aAAa;AAAA,MAAA,CAChC,GACM,MAAMtF,EAAS,WAAA;AAAA,IACxB,GAAG,CAACkB,CAAC,CAAC;AAGN,UAAMyE,IAAgBC,GAAA,GAGhB,CAACC,IAAcC,EAAe,IAAIlG,GAAS,EAAE,GAQ7C,CAACmG,GAAkBC,EAAmB,IAAIpG;AAAA,MAAiB,MAC/D/B,GAAwBC,GAAMC,CAAc;AAAA,IAAA,GAKxCkI,KAAsBxB,EAAOsB,CAAgB;AACnD,IAAAE,GAAoB,UAAUF;AAG9B,UAAMxI,KAAS2I,EAAwB,MAAM;AAC3C,YAAMC,IAAY,MAAA;;AAChB,gBAAA3I,IAAAgH,EAAM,YAAN,gBAAAhH,EAAe;AAAA;AAEjB,aAAO;AAAA,QACL,QAAQ,MAAA;;AAAM,kBAAAA,IAAAgH,EAAM,YAAN,gBAAAhH,EAAe;AAAA;AAAA,QAC7B,OAAO,MAAM;;AACX,WAAAA,IAAA2I,EAAA,MAAA,QAAA3I,EAAa;AAAA,QACf;AAAA,QACA,MAAM,MAAM;;AACV,WAAAA,IAAA2I,EAAA,MAAA,QAAA3I,EAAa;AAAA,QACf;AAAA,QACA,MAAM,MAAM;;AACV,WAAAA,IAAA2I,EAAA,MAAA,QAAA3I,EAAa;AAAA,QACf;AAAA,QACA,UAAU,CAACoB,MAAwB;;AACjC,WAAApB,IAAA2I,EAAA,MAAA,QAAA3I,EAAa,SAASoB;AAAA,QACxB;AAAA,QACA,YAAY,CAACwH,MAA2B;;AACtC,WAAA5I,IAAA2I,EAAA,MAAA,QAAA3I,EAAa;AAAA,YACXK,GAAwBuI,GAAUrI,CAAc;AAAA;AAAA,QAEpD;AAAA,QACA,UAAU,MAAA;;AAAM,mBAAAP,IAAA2I,EAAA,MAAA,gBAAA3I,EAAa,KAAK,UAAS;AAAA;AAAA,QAC3C,gBAAgB,MAAM;;AAEpB,kBADaA,IAAA2I,QAAA,gBAAA3I,EAAa,KAAK;AAAA,QAEjC;AAAA,QACA,gBAAgB,MAAA;;AAAM,kBAAAA,IAAA2I,EAAA,MAAA,gBAAA3I,EAAa;AAAA;AAAA,QACnC,YAAY,CAAC6I,MAAoB;AAC/B,gBAAMf,IAAOZ,EAAQ;AACrB,cAAI,CAACY,EAAM;AACX,gBAAMgB,IAAW,mBAAmB,IAAI,OAAOD,CAAO,CAAC,MACjDE,IAAUjB,EAAK,cAA2BgB,CAAQ;AACxD,cAAKC,GA4BL;AAAA,gBAjBI3B,EAAc,YAChB,aAAaA,EAAc,OAAO,GAClCA,EAAc,UAAU,OAEtBC,EAAa,WAAWA,EAAa,YAAY0B,KACnD1B,EAAa,QAAQ,UAAU,OAAO,wBAAwB,GAGhE0B,EAAQ,eAAe;AAAA,cACrB,UAAUZ,IAAgB,SAAS;AAAA,cACnC,OAAO;AAAA,YAAA,CACR,GACDY,EAAQ,UAAU,IAAI,wBAAwB,GAC9C1B,EAAa,UAAU0B,GAInB5B,EAAc,SAAS;AACzB,oBAAM6B,IAAYD,EAAQ,aAAa,YAAY,KAAKF,GAClDI,IAAiB1D,IAAc,QAAQyD;AAC7C,cAAA7B,EAAc,QAAQ,cAAczD,EAAE,yBAAyB;AAAA,gBAC7D,OAAOuF;AAAA,cAAA,CACR;AAAA,YACH;AAEA,YAAA7B,EAAc,UAAU,WAAW,MAAM;AACvC,cAAA2B,EAAQ,UAAU,OAAO,wBAAwB,GAC7C1B,EAAa,YAAY0B,MAC3B1B,EAAa,UAAU,OAEzBD,EAAc,UAAU;AAAA,YAC1B,GAAG,GAAI;AAAA;AAAA,QACT;AAAA,MAAA;AAAA,IAEJ,GAAG,CAACe,GAAe5C,GAAa7B,GAAGnD,CAAc,CAAC;AAElD,IAAA2I,GAAoBzF,IAAK,MAAM1D,IAAQ,CAACA,EAAM,CAAC,GAC/CoJ,GAAqBrJ,IAAeC,IAAQwE,CAAE,GAG9ChC;AAAA,MACE,MAAM,MAAM;AACV,QAAI6E,EAAc,YAChB,aAAaA,EAAc,OAAO,GAClCA,EAAc,UAAU;AAAA,MAE5B;AAAA,MACA,CAAA;AAAA,IAAC;AAIH,UAAMgC,KAAkBnC,EAAO,EAAI;AACnC,IAAA1E,EAAU,MAAM;AACd,UAAI6G,GAAgB,SAAS;AAC3B,QAAAA,GAAgB,UAAU;AAC1B;AAAA,MACF;AACA,MAAIjC,EAAc,YAChBA,EAAc,QAAQ,cAClBzD,EADgC6B,IAC9B,2BACA,yBADwB;AAAA,IAGlC,GAAG,CAACA,GAAa7B,CAAC,CAAC;AAGnB,UAAM2F,KAAWX;AAAA,MACf,MACElE,EAAO,IAAI,CAAC8E,OAAW;AAAA,QACrB,IAAIA,EAAM;AAAA,QACV,OAAOA,EAAM;AAAA,QACb,OAAOA,EAAM;AAAA,QACb,KAAKA,EAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAWX,GAAIA,EAAM,WAAW,SAAY,EAAE,QAAQA,EAAM,OAAA,IAAW,CAAA;AAAA,QAC5D,GAAIA,EAAM,eAAe,SACrB,EAAE,YAAYA,EAAM,WAAA,IACpB,CAAA;AAAA,QACJ,GAAIA,EAAM,aAAa,EAAE,SAAS,aAAA,IAA0B,CAAA;AAAA,QAC5D,GAAIA,EAAM,aAAa,SAAY,EAAE,UAAUA,EAAM,SAAA,IAAa,CAAA;AAAA,QAClE,GAAIA,EAAM,kBAAkB,SACxB,EAAE,eAAeA,EAAM,cAAA,IACvB,CAAA;AAAA,QACJ,eAAe;AAAA,UACb,QAAQA,EAAM;AAAA,UACd,YAAYA,EAAM;AAAA;AAAA;AAAA;AAAA;AAAA,UAKlB,UAAUA,EAAM;AAAA,UAChB,eAAeA,EAAM;AAAA,UACrB,iBAAiBA,EAAM;AAAA,UACvB,WAAWA,EAAM;AAAA,UACjB,aAAaA,EAAM;AAAA,UACnB,QAAQA,EAAM;AAAA,UACd,kBAAkBA,EAAM;AAAA,UACxB,gBAAgBA,EAAM,kBAAkB;AAAA,UACxC,sBAAsBA,EAAM,wBAAwB;AAAA,UACpD,yBAAyBA,EAAM,2BAA2B;AAAA,UAC1D,mBAAmBA,EAAM,qBAAqB;AAAA,UAC9C,cAAcA,EAAM,gBAAgB;AAAA,UACpC,oBAAoBA,EAAM,sBAAsB;AAAA,UAChD,YAAYA,EAAM,cAAc;AAAA,UAChC,WAAWA,EAAM;AAAA,UACjB,YAAYA,EAAM;AAAA,QAAA;AAAA,MACpB,EACA;AAAA,MACJ,CAAC9E,CAAM;AAAA,IAAA,GAIH+E,KAAcb;AAAA,MAClB,OAAO;AAAA,QACL,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,MAET,CAAA;AAAA,IAAC,GAEGc,KAAkBd;AAAA,MACtB,OAAO;AAAA,QACL,SAAS;AAAA,MAAA;AAAA,MAEX,CAAA;AAAA,IAAC,GAEGe,KAAkBf;AAAA,MACtB,OAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,MAAA;AAAA,MAEV,CAAA;AAAA,IAAC,GAEGgB,KAAkBhB;AAAA,MACtB,OAAO;AAAA,QACL,MAAM;AAAA,QACN,QAAQ;AAAA,MAAA;AAAA,MAEV,CAAA;AAAA,IAAC,GAOGiB,KAA8BjB;AAAA,MAClC,MACE,OAAO5B,KAA8B,WACjC,EAAE,SAASA,MACXA;AAAA,MACN,CAACA,CAAyB;AAAA,IAAA,GAMtB8C,IAAgBlB;AAAA,MACpB,MACElF,IAAgBA,EAAc,MAAM,KAAK,EAAE,OAAO,OAAO,IAAI;AAAA,MAC/D,CAACA,CAAa;AAAA,IAAA,GASVqG,KAA4BnB,EAAQ,MAAM;AAC9C,UAAI7B,MAAuB;AAC3B,eAAIA,MAAuB,WAClBnD,EAAE,+BAA+B,IAEtCmD,MAAuB,cAClBnD,EAAE,kCAAkC,IAEtCmD;AAAA,IACT,GAAG,CAACA,GAAoBnD,CAAC,CAAC,GAepBoG,IAAgBpB;AAAA,MACpB,MAAMnH,GAAmBC,GAAWC,EAAmB;AAAA,MACvD,CAACD,GAAWC,EAAmB;AAAA,IAAA,GAG3BsI,IAAmB9C,EAAO6C,CAAa;AAC7C,IAAAC,EAAiB,UAAUD;AAG3B,UAAME,KAAoB/C,EAAO,EAAK,GAEhCgD,KAAoBC;AAAA,MACxB,CAACxH,MAAqC;AACpC,cAAMyH,IAASJ,EAAiB;AAChC,YAAI,CAACI,EAAO,UAAU,CAACzH,EAAI,KAAK,KAAK,WAAW,kBAAkB;AAChE,iBAAO,CAAA;AAOT,cAAMb,IAAYa,EACf;AACH,eAAKb,KAAA,QAAAA,EAAU,KACRsI,EAAO,YAAY;AAAA,UACxB,GAAGtI,EAAS,EAAE,IAAIV,GAAmBuB,EAAI,IAAI,CAAC;AAAA,QAAA,IAE5C,CAACxB,EAAgB,IACjB,CAAA,IALsB,CAAA;AAAA,MAM5B;AAAA,MACA,CAAA;AAAA,IAAC,GAGGkJ,KAA0BF;AAAA,MAC9B,CAACxH,MAA2C;AAC1C,cAAMyH,IAASJ,EAAiB;AAKhC,YAAI,CAACI,EAAO,UAAU,CAACzH,EAAI,KAAK,KAAK,WAAW,kBAAkB;AAChE,iBAAO,CAAA;AAST,cAAMtB,IAAOsB,EAAI,QAAQA,EAAI,KAAK;AAClC,eAAOyH,EAAO,YAAY;AAAA,UACxB,GAAGzH,EAAI,SAAS,EAAE,IAAIvB,GAAmBC,CAAI,CAAC;AAAA,QAAA,IAE5C,CAACF,EAAgB,IACjB,CAAA;AAAA,MACN;AAAA,MACA,CAAA;AAAA,IAAC,GAGGmJ,KAAsBH;AAAA,MAC1B,CAACxH,MAAuC;AAItC,cAAMyH,IAASJ,EAAiB;AAChC,eAAI,CAACI,EAAO,UAAU,CAACzH,EAAI,KAAK,KAAK,WAAW,kBAAkB,IACzD,CAAA,KAGPyH,EAAO,kBAAkB,IAAIhJ,GAAmBuB,EAAI,IAAI,CAAC,KAAK,MAC/CyH,EAAO,gBAAgB,CAACjJ,EAAgB,IAAI,CAAA;AAAA,MAC/D;AAAA,MACA,CAAA;AAAA,IAAC,GAOGoJ,KAA0BJ,EAAY,CAACxH,MAA2B;AACtE,YAAMyH,IAASJ,EAAiB;AAChC,UAAI,CAACI,EAAO,UAAU,CAACzH,EAAI,KAAK,KAAK,WAAW,kBAAkB;AAChE;AAEF,YAAMwF,IAAKxF,EAAI;AAEf,UADI,EAAEwF,aAAc,yBAChB,CAACA,EAAG,UAAU,SAAS,QAAQ,EAAG;AACtC,YAAMqC,IAAMrC,EAAG,aAAa,WAAW;AACvC,UAAI,CAACqC,EAAK;AACV,YAAMtC,IAASkC,EAAO,kBAAkB,IAAII,CAAG,KAAK,GAI9CC,IAAO,KAAK,IAAI,GAAGL,EAAO,gBAAgBlC,CAAM;AACtD,MAAIC,EAAG,YAAYsC,MACjBtC,EAAG,UAAUsC,GACbR,GAAkB,UAAU;AAAA,IAEhC,GAAG,CAAA,CAAE,GAMCS,IAAyBP,EAAY,MAAM;AAC/C,YAAMpC,IAAOZ,EAAQ;AAErB,UADI,CAACY,KACD,CAACW,GAAoB,QAAQ,WAAW,kBAAkB,EAAG;AACjE,YAAM0B,IAASJ,EAAiB;AAChC,MAAI,CAACI,EAAO,UAAU,CAACH,GAAkB,YACzClC,EACG;AAAA,QACC;AAAA,MAAA,EAED,QAAQ,CAACI,MAAO;AACf,cAAMqC,IAAMrC,EAAG,aAAa,WAAW;AACvC,YAAI,CAACqC,EAAK;AACV,cAAMtC,IAASkC,EAAO,SACjBA,EAAO,kBAAkB,IAAII,CAAG,KAAK,IACtC,GACEC,IAAO,KAAK,IAAI,GAAGL,EAAO,gBAAgBlC,CAAM;AACtD,QAAIC,EAAG,YAAYsC,MAAMtC,EAAG,UAAUsC;AAAA,MACxC,CAAC,GACHR,GAAkB,UAAUG,EAAO;AAAA,IACrC,GAAG,CAAA,CAAE;AAQL,IAAA5H,EAAU,MAAM;AAAA,IAwChB,GAAG,CAACiC,GAAQsF,CAAa,CAAC;AAG1B,UAAMY,IAAa,CACjBC,MACkB;AAClB,YAAMC,IAAOD,EAAQ,iBAAiB,CAAA;AACtC,aAAO;AAAA,QACL,IAAIA,EAAQ;AAAA,QACZ,OAAOA,EAAQ;AAAA,QACf,OAAOA,EAAQ,SAAS,oBAAI,KAAA;AAAA,QAC5B,KAAKA,EAAQ,OAAO;AAAA,QACpB,YAAYC,EAAI;AAAA,QAChB,QAAQA,EAAI;AAAA,QACZ,QAAQD,EAAQ;AAAA,QAChB,iBAAiBC,EAAI;AAAA,QACrB,WAAWA,EAAI;AAAA,QACf,aAAaA,EAAI;AAAA,QACjB,QAAQA,EAAI;AAAA,QACZ,kBAAkBA,EAAI;AAAA,QACtB,gBAAgBA,EAAI;AAAA,QACpB,sBAAsBA,EAAI;AAAA,QAC1B,yBAAyBA,EAAI;AAAA,QAC7B,mBAAmBA,EAAI;AAAA,QACvB,cAAcA,EAAI;AAAA,QAClB,oBAAoBA,EAAI;AAAA,QACxB,YAAYA,EAAI;AAAA,QAChB,UAAUA,EAAI;AAAA,QACd,eAAeA,EAAI;AAAA,QACnB,WAAWA,EAAI;AAAA,QACf,YAAYA,EAAI;AAAA,MAAA;AAAA,IAEpB,GAGMC,KAAkBnC,EAAQ,MAAM;AACpC,UAAK/D;AACL,eAAO,CAAC1D,MAAuB;AAC7B,cAAI,CAACA,EAAK,MAAM,MAAO;AAQvB,gBAAM6J,IAAW7J,EAAK,SAAS;AAC/B,cAAK6J,MAQLnG,EAAY;AAAA,YACV,OAAO+F,EAAWzJ,EAAK,KAAK;AAAA,YAC5B,UAAA6J;AAAA,YACA,UAAU7J,EAAK,MAAM;AAAA,YACrB,QAAQA,EAAK;AAAA,UAAA,CACd,GAKGkG,EAAc,UAAS;AACzB,kBAAMyD,IAAO3J,EAAK,MAAM,iBAAiB,CAAA,GACnCgI,IAAiB1D,IAClBqF,EAAI,oBAAoB,QACzB3J,EAAK,MAAM;AACf,YAAAkG,EAAc,QAAQ,cAAczD,EAAE,uBAAuB;AAAA,cAC3D,OAAOuF;AAAA,YAAA,CACR;AAAA,UACH;AAAA,QACF;AAAA,IACF,GAAG,CAACtE,GAAaY,GAAa7B,CAAC,CAAC,GAE1BqH,KAAoBrC,EAAQ,MAAM;AACtC,UAAK9D;AACL,eAAO,CAAC3D,MAA6B;AACnC,cAAI,CAACA,EAAK,MAAM,IAAK;AAGrB,gBAAM+J,IAAS/J,EAAK,SAAS;AAC7B,cAAI,CAAC+J;AAMH;AAEF,gBAAMC,IAAShK,EAAK,MAAM,KAIpBiK,IAAWjK,EAAK,MAAM,SAASA,EAAK,SAAS,SAAS+J;AAO5D,cANApG,EAAc;AAAA,YACZ,OAAO8F,EAAWzJ,EAAK,KAAK;AAAA,YAC5B,QAAA+J;AAAA,YACA,QAAAC;AAAA,YACA,QAAQhK,EAAK;AAAA,UAAA,CACd,GACGkG,EAAc,SAAS;AACzB,kBAAMgE,IAAW,KAAK;AAAA,eACnBF,EAAO,QAAA,IAAYC,EAAS,aAAa;AAAA,YAAA,GAGtCN,IAAO3J,EAAK,MAAM,iBAAiB,CAAA,GACnCgI,IAAiB1D,IAClBqF,EAAI,oBAAoB,QACzB3J,EAAK,MAAM;AACf,YAAAkG,EAAc,QAAQ,cAAczD,EAAE,yBAAyB;AAAA,cAC7D,OAAOuF;AAAA,cACP,UAAAkC;AAAA,YAAA,CACD;AAAA,UACH;AAAA,QACF;AAAA,IACF,GAAG,CAACvG,GAAeW,GAAa7B,CAAC,CAAC,GAE5B0H,KAAmB1C,EAAQ,MAAM;AACrC,UAAK3D;AACL,eAAO,CAAC9D,MAAwB;AAC9B,UAAKA,EAAK,MAAM,UAKhBqG,GAAwB,UAAUrG,EAAK,SACvC8D,EAAa2F,EAAWzJ,EAAK,KAAK,GAAG;AAAA,YACnC,IAAIA,EAAK;AAAA,YACT,SAASA,EAAK;AAAA,UAAA,CACf;AAAA,QACH;AAAA,IACF,GAAG,CAAC8D,CAAY,CAAC,GAEXsG,KAAmB3C,EAAQ,MAAM;AACrC,UAAK1D;AACL,eAAO,CAAC/D,MAAwB;;AAM9B,UAAA+D,EAAa;AAAA,YACX,OAAO/D,EAAK;AAAA,YACZ,KAAKA,EAAK;AAAA,YACV,QAAQA,EAAK;AAAA,YACb,aAAYjB,IAAAiB,EAAK,aAAL,gBAAAjB,EAAe;AAAA,UAAA,CAC5B;AAAA,QACH;AAAA,IACF,GAAG,CAACgF,CAAY,CAAC,GAEXsG,KAAkB5C,EAAQ,MAAM;AACpC,UAAKxD;AACL,eAAO,CAACjE,MAAuB;;AAS7B,gBAAMsK,IAAYhE,EAAW,QAAQ;AACrC,UAAIgE,MAAc,KAAK9D,GAAyB,YAAY8D,MAGxDA,MAAc,MAAG/D,GAA0B,UAAU+D,IACzDrG,EAAY;AAAA,YACV,MAAMjE,EAAK;AAAA,YACX,QAAQA,EAAK;AAAA,YACb,aAAYjB,IAAAiB,EAAK,aAAL,gBAAAjB,EAAe;AAAA,UAAA,CAC5B;AAAA,QACH;AAAA,IACF,GAAG,CAACkF,CAAW,CAAC,GAMVsG,KAAiBtB;AAAA,MACrB,CAACjJ,MAAsB;AACrB,QAAAqH,GAAgBrH,EAAK,KAAK,KAAK,GAC/BuH,GAAoBvH,EAAK,KAAK,IAAI,GAClCgE,KAAA,QAAAA,EAAa;AAAA,UACX,MAAA3E;AAAA,UACA,cAAcW,EAAK,KAAK;AAAA,UACxB,OAAOA,EAAK;AAAA,UACZ,KAAKA,EAAK;AAAA;AAAA;AAAA,UAGV,aAAaA,EAAK,KAAK,SAAS,QAAA;AAAA,UAChC,OAAOA,EAAK,KAAK;AAAA,QAAA,IAOnBwJ,EAAA;AAAA,MACF;AAAA,MACA,CAACxF,GAAY3E,GAAMmK,CAAsB;AAAA,IAAA,GAIrCgB,KAAW/C,EAAQ,MAAM5H,GAAgBC,CAAM,GAAG,CAACA,CAAM,CAAC,GAG1D2K,KAAUhD;AAAA,MACd,MAAM;AAAA,QACJiD;AAAA,QACAC;AAAA,QACAC;AAAA,QACAC;AAAA,QACAC;AAAA,QACAC;AAAA,QACAC;AAAA,QACAC;AAAA,MAAA;AAAA,MAEF,CAAA;AAAA,IAAC,GAIGC,KAAezD;AAAA,MACnB,MAAMrI,GAAwBC,GAAMC,CAAc;AAAA,MAClD,CAACD,GAAMC,CAAc;AAAA,IAAA;AAOvB,IAAAgC,EAAU,MAAM;AACd,YAAMuF,IAAOZ,EAAQ;AACrB,UAAI,CAACY,EAAM;AACX,YAAMsE,IAAoB,CAAC9C,MAAwB;AACjD,QAAA/B,EAAW,UAAU;AAAA,UACnB,IAAIA,EAAW,QAAQ,KAAK;AAAA,UAC5B,GAAG+B,EAAM;AAAA,UACT,GAAGA,EAAM;AAAA,QAAA;AAAA,MAEb;AACA,aAAAxB,EAAK,iBAAiB,eAAesE,GAAmB,EAAI,GACrD,MACLtE,EAAK,oBAAoB,eAAesE,GAAmB,EAAI;AAAA,IACnE,GAAG,CAAA,CAAE,GAmCL7J,EAAU,MAAM;AACd,YAAMuF,IAAOZ,EAAQ;AAGrB,UAFI,CAACY,KACD,CAACS,EAAiB,WAAW,kBAAkB,KAC/C,CAACrD,KAAe,CAACH,EAAc;AAEnC,YAAMsH,IAAkB,CAAC/C,MAAsB;;AAC7C,YAAIA,MAAUhC,GAAwB,QAAS;AAC/C,cAAMgF,IAAShD,EAAM;AAQrB,YAPI,EAAEgD,aAAkB,YAQtBA,EAAO;AAAA,UACL;AAAA,QAAA;AAGF;AAOF,cAAMC,IAAUhF,EAAW;AAC3B,YACEgF,EAAQ,OAAO,MACd,KAAK,IAAIjD,EAAM,UAAUiD,EAAQ,CAAC,IAAI3L,MACrC,KAAK,IAAI0I,EAAM,UAAUiD,EAAQ,CAAC,IAAI3L;AAExC;AAGF,cAAM4L,IAAOF,EAAO,QAAQ,8BAA8B;AAC1D,YAAI,CAACE,EAAM;AAEX,cAAMC,IAASH,EAAO,QAAqB,iBAAiB;AAC5D,YAAIG,GAAQ;AAEV,cAAI,CAAC1H,EAAc;AACnB,gBAAM8D,KAAU4D,EAAO,aAAa,eAAe,GAC7C5E,MAAM7H,KAAAgH,EAAM,YAAN,gBAAAhH,GAAe,UACrB2K,IAAU9B,KAAUhB,MAAA,gBAAAA,GAAK,aAAagB,MAAW;AAGvD,cAFI,CAAC8B,KAAW,CAACA,EAAQ,UACZA,EAAQ,iBAAiB,CAAA,GAC9B,WAAY;AACpB,gBAAM+B,KAAWJ,EAAO,QAAqB,WAAW,KAAKG;AAC7D,UAAA1H,EAAa2F,EAAWC,CAAO,GAAG,EAAE,IAAI+B,IAAU,SAASpD,GAAO;AAClE;AAAA,QACF;AAIA,YAFI,CAACpE,KAGHqH,EAAQ,OAAO,KACf/E,GAA0B,YAAY+E,EAAQ;AAE9C;AAEF,cAAMI,IAAWH,EAAK,aAAa,WAAW;AAC9C,YAAI,CAACG,EAAU;AAIf,cAAMvL,KAAO,oBAAI,KAAK,GAAGuL,CAAQ,WAAW;AAC5C,QAAI,OAAO,MAAMvL,GAAK,QAAA,CAAS,MAC3BmL,EAAQ,OAAO,MAAG9E,GAAyB,UAAU8E,EAAQ,KACjErH,EAAY;AAAA,UACV,MAAA9D;AAAA,UACA,QAAQ;AAAA,UACR,YAAYoL,EAAK,aAAa,kBAAkB,KAAK;AAAA,QAAA,CACtD;AAAA,MACH;AAEA,aAAA1E,EAAK,iBAAiB,SAASuE,CAAe,GACvC,MAAMvE,EAAK,oBAAoB,SAASuE,CAAe;AAAA,IAChE,GAAG,CAAC9D,GAAkBrD,GAAaH,CAAY,CAAC;AAchD,UAAM6H,KAAsB1C;AAAA,MAC1B,CAACxH,MAA+C;AAC9C,cAAMkI,IAAMlI,EAAI,SACb,eACGS,IAAQT,EAAI,SAAS,OACrBmK,IAAajC,EAAI,YACjBkC,IAAQlC,EAAI,OACZmC,IAAYnC,EAAI,qBAWhBoC,IACJF,KAASC,IACL;AAAA,UACE,GAAID,IACC,EAAE,oBAAoBA,EAAA,IACvB,CAAA;AAAA,UACJ,GAAIC,IACC;AAAA,YACC,kCAAkCA;AAAA,UAAA,IAEpC,CAAA;AAAA,QAAC,IAEP;AAEN,YAAIpG,MAAwBkG,KAAcC,GAAO;AAI/C,UAAAG,GAAgBH,GAAOC,GAAW,YAAYrK,EAAI,SAAS,EAAE,EAAE;AAC/D,gBAAMwK,IAAgB;AAAA,YACpB;AAAA,YACA;AAAA,YACAH,IAAY,mDAAmD;AAAA,UAAA,EAE9D,OAAO,OAAO,EACd,KAAK,GAAG;AACX,iBACE,gBAAA3I,EAAC,QAAA,EAAK,WAAU,sDACd,UAAA;AAAA,YAAA,gBAAAC;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAW6I;AAAA,gBAEX,OAAOF;AAAA,gBACP,eAAY;AAAA,gBAEX,UAAAH;AAAA,cAAA;AAAA,YAAA;AAAA,8BAEF,QAAA,EAAK,WAAU,6BAA6B,UAAA1J,GAAM;AAAA,UAAA,GACrD;AAAA,QAEJ;AAEA,eAAI2J,KAKEA,KAASC,KACXE,GAAgBH,GAAOC,GAAW,YAAYrK,EAAI,SAAS,EAAE,EAAE,GAG/D,gBAAA0B,EAAC,QAAA,EAAK,WAAU,sDACd,UAAA;AAAA,UAAA,gBAAAC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cAEV,OAAO2I;AAAA,cACP,eAAY;AAAA,YAAA;AAAA,UAAA;AAAA,4BAEb,QAAA,EAAK,WAAU,6BAA6B,UAAA7J,GAAM;AAAA,QAAA,GACrD,KAKF,gBAAAkB,EAAC,UAAK,WAAU,sDACd,4BAAC,QAAA,EAAK,WAAU,6BAA6B,UAAAlB,EAAA,CAAM,GACrD;AAAA,MAEJ;AAAA,MACA,CAACwD,EAAoB;AAAA,IAAA,GAIjBwG,KAAczE;AAAA,MAClB,MACElH,KAAA,gBAAAA,EAAW,IAAI,CAACK,OAAc;AAAA,QAC5B,IAAIA,EAAS;AAAA,QACb,OAAOA,EAAS;AAAA,QAChB,gBAAgBA,EAAS;AAAA,QACzB,eAAe;AAAA,UACb,YAAYA,EAAS;AAAA,UACrB,OAAOA,EAAS;AAAA,UAChB,qBAAqBA,EAAS;AAAA,UAC9B,gBAAgBA,EAAS;AAAA,QAAA;AAAA,MAC3B;AAAA,MAEJ,CAACL,CAAS;AAAA,IAAA;AAWZ,IAAAe,EAAU,MAAM;AACd,MAAAkI,EAAA;AACA,YAAM2C,IAAM,sBAAsB3C,CAAsB;AACxD,aAAO,MAAM,qBAAqB2C,CAAG;AAAA,IACvC,GAAG,CAACtD,GAAeqD,IAAa5E,GAAkBkC,CAAsB,CAAC;AAGzE,UAAM4C,KAAqBnD,EAAY,MAAM;;AAC1C,OAAAoD,KAAAtN,IAAAgH,EAAM,YAAN,gBAAAhH,EAAe,aAAf,QAAAsN,EAA+C;AAAA,IAClD,GAAG,CAAA,CAAE,GACCC,KAAoBrD,EAAY,MAAM;;AACzC,OAAAoD,KAAAtN,IAAAgH,EAAM,YAAN,gBAAAhH,EAAe,aAAf,QAAAsN,EAA+C;AAAA,IAClD,GAAG,CAAA,CAAE,GACCE,KAAoBtD,EAAY,MAAM;;AACzC,OAAAoD,KAAAtN,IAAAgH,EAAM,YAAN,gBAAAhH,EAAe,aAAf,QAAAsN,EAA+C;AAAA,IAClD,GAAG,CAAA,CAAE,GAECG,KAAmB;AAAA,MACvB;AAAA,MACA1G,KAAY,wBAAwB;AAAA,MACpC;AAAA,MACA;AAAA,MACAxD;AAAA,IAAA,EAEC,OAAO,OAAO,EACd,KAAK,GAAG,GAOLmK,KACJ/H,KAAmBC,IACf;AAAA,MACE,GAAID,IACC,EAAE,sBAAsBA,EAAA,IACzB,CAAA;AAAA,MACJ,GAAIC,IACC,EAAE,sBAAsBA,MACzB,CAAA;AAAA,IAAC,IAEP,QAYA+H,KACJlI,MAAS,YAAaC,MAAahC,EAAE7C,GAAiB4E,CAAI,CAAC,IAAK,IAE5DmI,KAAsB;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA;AAAA;AAAA;AAAA,MAIAjI,IACI,kDACA;AAAA,MACJC,IACI,uCACA;AAAA,IAAA,EAEH,OAAO,OAAO,EACd,KAAK,GAAG,GAELiI,KAAsB;AAAA,MAC1B;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA,EACA,KAAK,GAAG;AAEV,WACE,gBAAAzJ;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAK8C;AAAA,QACL,WAAWuG;AAAA,QACX,MAAK;AAAA,QACL,cAAY/J,EAAE,oBAAoB;AAAA,QAClC,kBAAe;AAAA,QACf,qBAAmBa;AAAA,QACnB,aAAWkB;AAAA,QAEX,UAAA;AAAA,UAAA,gBAAApB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,KAAK8C;AAAA,cACL,aAAU;AAAA,cACV,eAAY;AAAA,cAGZ,WAAW,CAAC,cAAc3D,CAAa,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAAA,YAAA;AAAA,UAAA;AAAA,UAElEsC;AAAA,UAIAL,MAAS,YACR,gBAAArB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAWwJ;AAAA,cAEX,OAAOF;AAAA,cACP,MAAK;AAAA,cAIL,UAAA;AAAA,gBAAA,gBAAArJ;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,WAAW,CAAC,2BAA2Bb,CAAa,EACjD,OAAO,OAAO,EACd,KAAK,GAAG;AAAA,oBAEV,UAAAmK;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAEF9H,KACC,gBAAAxB;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAASwB;AAAA,oBACT,WAAWgI;AAAA,oBAEV,YAAE,4BAA4B;AAAA,kBAAA;AAAA,gBAAA,IAE/B;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA,IAEJ;AAAA,UACHpH,OAAY,KACX,gBAAApC;AAAA,YAACpB;AAAA,YAAA;AAAA,cACC,OAAOoF;AAAA,cACP,SAASgF;AAAA,cACT,QAAQE;AAAA,cACR,QAAQC;AAAA,cACR,KAAK9G;AAAA,cACL,eAAAlD;AAAA,YAAA;AAAA,UAAA,IAEA;AAAA,UACJ,gBAAAa;AAAA,YAACyJ;AAAA,YAAA;AAAA,cACC,KAAK9G;AAAA,cACL,SAAA0E;AAAA,cACA,qBAAAlF;AAAA,cACA,aAAa2F;AAAA,cACb,OAAOxL;AAAA,cACP,aAAA8D;AAAA,cACA,QAAA1D;AAAA,cACA,WAAA2G;AAAA,cACA,UAAA+D;AAAA,cACA,UAAAtG;AAAA,cACA,uBAAuBC,MAAyBD;AAAA,cAChD,YAAAE;AAAA,cACA,WAAWF;AAAA,cACX,cAAAoB;AAAA,cACA,QAAAjB;AAAA,cACA,QAAQ+D;AAAA,cACR,WAAW8D;AAAA,cACX,eAAc;AAAA,cACd,sBAAsBP;AAAA,cACtB,mBAAAhG;AAAA,cACA,2BAAAiD;AAAA,cAIA,mBAAAI;AAAA,cACA,qBAAAI;AAAA,cACA,yBAAAD;AAAA,cACA,mBAAmBE;AAAA,cAKlB,GAAIV,IAAgB,EAAE,oBAAoBA,EAAA,IAAkB,CAAA;AAAA,cAC5D,GAAIA,IAAgB,EAAE,iBAAiBA,EAAA,IAAkB,CAAA;AAAA,cAC1D,eAAe;AAAA,cACf,YAAYlG,EAAE,iBAAiB;AAAA,cAC/B,cAAcA,EAAE,mBAAmB;AAAA,cACnC,aAAA6F;AAAA,cACA,iBAAAC;AAAA,cACA,iBAAAC;AAAA,cACA,iBAAAC;AAAA,cACA,aAAa1D,MAAe;AAAA,cAC5B,aAAaC,MAAe;AAAA,cAC5B,cAAcC,MAAgB;AAAA,cAQ9B,mBAAkB;AAAA,cAIjB,GAAIyD,OAAgC,SACjC,EAAE,2BAA2BA,GAAA,IAC7B,CAAA;AAAA,cACJ,YAAA5D;AAAA,cACA,qBAAAtE;AAAA,cACA,kBAAA2E;AAAA,cACA,mBAAAC;AAAA,cACA,cAAAC;AAAA,cACA,qBAAqB6B,IAAgB,IAAI;AAAA,cACzC,sBAAsBA,IAAgB,IAAIvH;AAAA,cAC1C,cAAc,CAAC8B,MAAQ;;AACrB,sBAAMkI,IAAOlI,EAAI,MAAM,iBAAiB,CAAA;AACxC,uBACE,gBAAA2B;AAAA,kBAAC0J;AAAA,kBAAA;AAAA,oBACC,SAASrL,EAAI,MAAM;AAAA,oBACnB,OACE6C,IACKqF,EAAI,oBAAoB,QACzBlI,EAAI,MAAM;AAAA,oBAEhB,QAAQkI,EAAI;AAAA,oBACZ,WAAWnI,GAAgBC,GAAK3B,CAAM;AAAA,oBACtC,UAAAoF;AAAA,oBACA,QAAQzD,EAAI,MAAM;AAAA,oBAClB,QAAQkI,EAAI;AAAA,oBACZ,cAAcpF;AAAA,oBACd,iBAAiBoF,EAAI;AAAA,oBACrB,WAAWA,EAAI;AAAA,oBACf,aAAaA,EAAI;AAAA,oBACjB,gBAAgBA,EAAI;AAAA,oBACpB,sBAAsBA,EAAI;AAAA,oBAC1B,yBAAyBA,EAAI;AAAA,oBAC7B,mBAAmBA,EAAI;AAAA,oBACvB,cAAcA,EAAI;AAAA,oBAClB,eACEA,EAAI,cACC5K,KAAAwB,KAAa,CAAA,GAAI,KAAK,CAACwM,MAAMA,EAAE,OAAOpD,EAAI,UAAU,MAApD,gBAAA5K,EACG,QACJ;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAIZ;AAAA,cACA,YAAYoL;AAAA,cACZ,WAAWP;AAAA,cACX,aAAaE;AAAA,cACb,gBAAgBlG;AAAA,cAChB,kBAAkBC;AAAA,cAClB,QAAQuG;AAAA,cACR,WAAWC;AAAA,cACX,UAAUE;AAAA,YAAA;AAAA,UAAA;AAAA,QACZ;AAAA,MAAA;AAAA,IAAA;AAAA,EAGN;AACF;AACAlH,GAAc,cAAc;AAUrB,MAAM2J,KAAW3J;AACxB2J,GAAS,UAAUhL;"}
|