@alfadocs/ui-kit-debug 1.56.0 → 1.58.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/{address-fields-BfjxS05Z.js → address-fields-CJtu7LQU.js} +2 -2
- package/dist/_chunks/{address-fields-BfjxS05Z.js.map → address-fields-CJtu7LQU.js.map} +1 -1
- package/dist/_chunks/{ai-credits-notice-BoNJtOuE.js → ai-credits-notice-ktklr8fy.js} +2 -2
- package/dist/_chunks/{ai-credits-notice-BoNJtOuE.js.map → ai-credits-notice-ktklr8fy.js.map} +1 -1
- package/dist/_chunks/ai-permission-notice-DyuEGwAt.js +206 -0
- package/dist/_chunks/ai-permission-notice-DyuEGwAt.js.map +1 -0
- package/dist/_chunks/alia-sidebar-dybRpWml.js +1284 -0
- package/dist/_chunks/alia-sidebar-dybRpWml.js.map +1 -0
- package/dist/_chunks/{anamnesis-summary-rows-CQ-XGr0T.js → anamnesis-summary-rows-M-FUkw9p.js} +6 -6
- package/dist/_chunks/{anamnesis-summary-rows-CQ-XGr0T.js.map → anamnesis-summary-rows-M-FUkw9p.js.map} +1 -1
- package/dist/_chunks/{app-frame-B-0O9CrU.js → app-frame-CqmDh2v5.js} +2 -2
- package/dist/_chunks/{app-frame-B-0O9CrU.js.map → app-frame-CqmDh2v5.js.map} +1 -1
- package/dist/_chunks/{appointment-peek-BIZaDeCi.js → appointment-peek-WvNbE4JG.js} +2 -2
- package/dist/_chunks/{appointment-peek-BIZaDeCi.js.map → appointment-peek-WvNbE4JG.js.map} +1 -1
- package/dist/_chunks/{appointment-timeline-DmqYEIT9.js → appointment-timeline-Z0494xO-.js} +2 -2
- package/dist/_chunks/{appointment-timeline-DmqYEIT9.js.map → appointment-timeline-Z0494xO-.js.map} +1 -1
- package/dist/_chunks/{balance-badge-cell-DmDcXw0c.js → balance-badge-cell-CGoJZlKf.js} +3 -3
- package/dist/_chunks/{balance-badge-cell-DmDcXw0c.js.map → balance-badge-cell-CGoJZlKf.js.map} +1 -1
- package/dist/_chunks/{booking-WyNGKPE2.js → booking-CiFSAMR-.js} +4 -4
- package/dist/_chunks/{booking-WyNGKPE2.js.map → booking-CiFSAMR-.js.map} +1 -1
- package/dist/_chunks/{calculator-dialog-pCPWta7h.js → calculator-dialog-CzQv03p0.js} +2 -2
- package/dist/_chunks/{calculator-dialog-pCPWta7h.js.map → calculator-dialog-CzQv03p0.js.map} +1 -1
- package/dist/_chunks/{calendar-workspace-Du2ryaI-.js → calendar-workspace-DNHzjG7O.js} +19 -19
- package/dist/_chunks/calendar-workspace-DNHzjG7O.js.map +1 -0
- package/dist/_chunks/{care-plan-card-Ddjh5Doc.js → care-plan-card-DxrRLRdW.js} +2 -2
- package/dist/_chunks/{care-plan-card-Ddjh5Doc.js.map → care-plan-card-DxrRLRdW.js.map} +1 -1
- package/dist/_chunks/{care-plan-header-DUX_SVvF.js → care-plan-header-BMwZIgHJ.js} +2 -2
- package/dist/_chunks/{care-plan-header-DUX_SVvF.js.map → care-plan-header-BMwZIgHJ.js.map} +1 -1
- package/dist/_chunks/{chart-HsF1KHbx.js → chart-ZMkX-Gqy.js} +338 -341
- package/dist/_chunks/chart-ZMkX-Gqy.js.map +1 -0
- package/dist/_chunks/{city-input-BC_nYINn.js → city-input-3J3bz9EO.js} +2 -2
- package/dist/_chunks/{city-input-BC_nYINn.js.map → city-input-3J3bz9EO.js.map} +1 -1
- package/dist/_chunks/{clinical-note-card-14JIoUR0.js → clinical-note-card-hx939bvw.js} +2 -2
- package/dist/_chunks/{clinical-note-card-14JIoUR0.js.map → clinical-note-card-hx939bvw.js.map} +1 -1
- package/dist/_chunks/{color-picker-BRQ4Y9SO.js → color-picker-BsggJovx.js} +128 -123
- package/dist/_chunks/color-picker-BsggJovx.js.map +1 -0
- package/dist/_chunks/{contact-card-CmK05vNb.js → contact-card-fHBMwEsx.js} +2 -2
- package/dist/_chunks/{contact-card-CmK05vNb.js.map → contact-card-fHBMwEsx.js.map} +1 -1
- package/dist/_chunks/{contact-profile-card-Ci8lBQ6a.js → contact-profile-card-CMyBYgRR.js} +2 -2
- package/dist/_chunks/{contact-profile-card-Ci8lBQ6a.js.map → contact-profile-card-CMyBYgRR.js.map} +1 -1
- package/dist/_chunks/{control-room-rail-Tx2jW250.js → control-room-rail-CJ85HkS2.js} +2 -2
- package/dist/_chunks/{control-room-rail-Tx2jW250.js.map → control-room-rail-CJ85HkS2.js.map} +1 -1
- package/dist/_chunks/{cycle-calculator-Dgfqr4Q4.js → cycle-calculator-Cww9DzIa.js} +2 -2
- package/dist/_chunks/{cycle-calculator-Dgfqr4Q4.js.map → cycle-calculator-Cww9DzIa.js.map} +1 -1
- package/dist/_chunks/dashboard-grid-Cs7cJAsA.js +933 -0
- package/dist/_chunks/dashboard-grid-Cs7cJAsA.js.map +1 -0
- package/dist/_chunks/{data-table-D8fuhqO1.js → data-table-Yn5xiGzs.js} +3 -3
- package/dist/_chunks/{data-table-D8fuhqO1.js.map → data-table-Yn5xiGzs.js.map} +1 -1
- package/dist/_chunks/{data-table-tabs-Xhg5G0gU.js → data-table-tabs-CHYAAeHy.js} +2 -2
- package/dist/_chunks/{data-table-tabs-Xhg5G0gU.js.map → data-table-tabs-CHYAAeHy.js.map} +1 -1
- package/dist/_chunks/{date-picker-wRAcq2lt.js → date-picker-BSZuKo13.js} +69 -62
- package/dist/_chunks/date-picker-BSZuKo13.js.map +1 -0
- package/dist/_chunks/{date-range-picker-CtUOI38x.js → date-range-picker-CFk-5O3R.js} +176 -171
- package/dist/_chunks/date-range-picker-CFk-5O3R.js.map +1 -0
- package/dist/_chunks/{date-time-picker-CLeLKuv9.js → date-time-picker-CjxTkblD.js} +92 -85
- package/dist/_chunks/date-time-picker-CjxTkblD.js.map +1 -0
- package/dist/_chunks/{dialog-CUzbnKLw.js → dialog-Dn-iQ0Jp.js} +2 -2
- package/dist/_chunks/{dialog-CUzbnKLw.js.map → dialog-Dn-iQ0Jp.js.map} +1 -1
- package/dist/_chunks/{document-preview-uoTekVR7.js → document-preview-CHGGG0l_.js} +2 -2
- package/dist/_chunks/{document-preview-uoTekVR7.js.map → document-preview-CHGGG0l_.js.map} +1 -1
- package/dist/_chunks/{due-date-calculator-CSjklbyw.js → due-date-calculator-D_qFUiHp.js} +2 -2
- package/dist/_chunks/{due-date-calculator-CSjklbyw.js.map → due-date-calculator-D_qFUiHp.js.map} +1 -1
- package/dist/_chunks/{entity-summary-DcB0fIiv.js → entity-summary-CWcCSThK.js} +2 -2
- package/dist/_chunks/{entity-summary-DcB0fIiv.js.map → entity-summary-CWcCSThK.js.map} +1 -1
- package/dist/_chunks/{face-scheme-BicuUA2K.js → face-scheme-DSKDdIsb.js} +2 -2
- package/dist/_chunks/{face-scheme-BicuUA2K.js.map → face-scheme-DSKDdIsb.js.map} +1 -1
- package/dist/_chunks/{file-manager-Cc_uO8r2.js → file-manager-DEtkQR1F.js} +4 -4
- package/dist/_chunks/{file-manager-Cc_uO8r2.js.map → file-manager-DEtkQR1F.js.map} +1 -1
- package/dist/_chunks/{forgot-password-form-DEx-M_QR.js → forgot-password-form-CEqOmNuX.js} +2 -2
- package/dist/_chunks/{forgot-password-form-DEx-M_QR.js.map → forgot-password-form-CEqOmNuX.js.map} +1 -1
- package/dist/_chunks/{gestational-age-calculator-DqVeJke2.js → gestational-age-calculator-CZi43xKG.js} +2 -2
- package/dist/_chunks/{gestational-age-calculator-DqVeJke2.js.map → gestational-age-calculator-CZi43xKG.js.map} +1 -1
- package/dist/_chunks/{hcg-doubling-BIYyI2Yo.js → hcg-doubling-Ccvh7OaU.js} +2 -2
- package/dist/_chunks/{hcg-doubling-BIYyI2Yo.js.map → hcg-doubling-Ccvh7OaU.js.map} +1 -1
- package/dist/_chunks/{header-settings-ge_3gYEq.js → header-settings-BMcCx2LC.js} +2 -2
- package/dist/_chunks/{header-settings-ge_3gYEq.js.map → header-settings-BMcCx2LC.js.map} +1 -1
- package/dist/_chunks/{heatmap-Gf9r7Tn1.js → heatmap-DiyOSQk9.js} +2 -2
- package/dist/_chunks/{heatmap-Gf9r7Tn1.js.map → heatmap-DiyOSQk9.js.map} +1 -1
- package/dist/_chunks/{help-me-write-templates-fV-Apf72.js → help-me-write-templates-CM1p6qkm.js} +3 -3
- package/dist/_chunks/{help-me-write-templates-fV-Apf72.js.map → help-me-write-templates-CM1p6qkm.js.map} +1 -1
- package/dist/_chunks/{hover-card-BnTueNS2.js → hover-card-U_ZYoh1n.js} +201 -187
- package/dist/_chunks/hover-card-U_ZYoh1n.js.map +1 -0
- package/dist/_chunks/{icon-picker-DWrqmI1c.js → icon-picker-rOFTawXk.js} +3 -3
- package/dist/_chunks/{icon-picker-DWrqmI1c.js.map → icon-picker-rOFTawXk.js.map} +1 -1
- package/dist/_chunks/{info-tip-B0jmIt6M.js → info-tip-CJpNpzZe.js} +2 -2
- package/dist/_chunks/{info-tip-B0jmIt6M.js.map → info-tip-CJpNpzZe.js.map} +1 -1
- package/dist/_chunks/{kit-extensions-Byfxy6sy.js → kit-extensions-DYVxWcqv.js} +4 -4
- package/dist/_chunks/{kit-extensions-Byfxy6sy.js.map → kit-extensions-DYVxWcqv.js.map} +1 -1
- package/dist/_chunks/{link-cell-renderer-TeJNvymP.js → link-cell-renderer-C1wOyxDF.js} +3 -3
- package/dist/_chunks/{link-cell-renderer-TeJNvymP.js.map → link-cell-renderer-C1wOyxDF.js.map} +1 -1
- package/dist/_chunks/link-gRw3NtOt.js +137 -0
- package/dist/_chunks/link-gRw3NtOt.js.map +1 -0
- package/dist/_chunks/{list-RRN2TJ_7.js → list-CNnn7DOD.js} +75 -73
- package/dist/_chunks/list-CNnn7DOD.js.map +1 -0
- package/dist/_chunks/{locale-picker-DfNSdOpy.js → locale-picker-BGfrZyTw.js} +2 -2
- package/dist/_chunks/{locale-picker-DfNSdOpy.js.map → locale-picker-BGfrZyTw.js.map} +1 -1
- package/dist/_chunks/{login-dev-card-DmZ1B0lB.js → login-dev-card-CIim81VB.js} +2 -2
- package/dist/_chunks/{login-dev-card-DmZ1B0lB.js.map → login-dev-card-CIim81VB.js.map} +1 -1
- package/dist/_chunks/marketplace-app-shell-CSDmGLPW.js +613 -0
- package/dist/_chunks/marketplace-app-shell-CSDmGLPW.js.map +1 -0
- package/dist/_chunks/{message-tray-BB95DA82.js → message-tray-DmU0poD7.js} +76 -69
- package/dist/_chunks/message-tray-DmU0poD7.js.map +1 -0
- package/dist/_chunks/{nav-grid-BqCPH8sm.js → nav-grid-Byx8PxuB.js} +2 -2
- package/dist/_chunks/{nav-grid-BqCPH8sm.js.map → nav-grid-Byx8PxuB.js.map} +1 -1
- package/dist/_chunks/navigation-dismiss-B1mcW1CT.js +9 -0
- package/dist/_chunks/navigation-dismiss-B1mcW1CT.js.map +1 -0
- package/dist/_chunks/non-modal-tab-exit-j3CPOuE3.js +89 -0
- package/dist/_chunks/non-modal-tab-exit-j3CPOuE3.js.map +1 -0
- package/dist/_chunks/{note-attachment-I1NLoeRZ.js → note-attachment-Bt2cddsZ.js} +2 -2
- package/dist/_chunks/{note-attachment-I1NLoeRZ.js.map → note-attachment-Bt2cddsZ.js.map} +1 -1
- package/dist/_chunks/{note-timeline-CsY8YOE7.js → note-timeline-CX9nAgAR.js} +2 -2
- package/dist/_chunks/{note-timeline-CsY8YOE7.js.map → note-timeline-CX9nAgAR.js.map} +1 -1
- package/dist/_chunks/{notes-panel-DceRhthG.js → notes-panel-DHLHsxpW.js} +4 -4
- package/dist/_chunks/{notes-panel-DceRhthG.js.map → notes-panel-DHLHsxpW.js.map} +1 -1
- package/dist/_chunks/{notification-tray-__sJXnsz.js → notification-tray-DPU-Xg0i.js} +83 -76
- package/dist/_chunks/notification-tray-DPU-Xg0i.js.map +1 -0
- package/dist/_chunks/{panel-subview-BT-Apwgb.js → panel-subview-D4o6ar6_.js} +61 -47
- package/dist/_chunks/panel-subview-D4o6ar6_.js.map +1 -0
- package/dist/_chunks/{patient-details-DsTtjpuX.js → patient-details-BCaVuaXz.js} +2 -2
- package/dist/_chunks/{patient-details-DsTtjpuX.js.map → patient-details-BCaVuaXz.js.map} +1 -1
- package/dist/_chunks/{patient-field-row-BvZ9luz-.js → patient-field-row-jcRSTrp4.js} +7 -7
- package/dist/_chunks/{patient-field-row-BvZ9luz-.js.map → patient-field-row-jcRSTrp4.js.map} +1 -1
- package/dist/_chunks/{patient-summary-card-9nQWTQf6.js → patient-summary-card-kQIfPQOE.js} +4 -4
- package/dist/_chunks/{patient-summary-card-9nQWTQf6.js.map → patient-summary-card-kQIfPQOE.js.map} +1 -1
- package/dist/_chunks/{payment-automation-upsell-DiHovmUL.js → payment-automation-upsell-C4wHOxsp.js} +2 -2
- package/dist/_chunks/{payment-automation-upsell-DiHovmUL.js.map → payment-automation-upsell-C4wHOxsp.js.map} +1 -1
- package/dist/_chunks/{payment-request-card-CwDpwXUC.js → payment-request-card-DAniJNLX.js} +2 -2
- package/dist/_chunks/{payment-request-card-CwDpwXUC.js.map → payment-request-card-DAniJNLX.js.map} +1 -1
- package/dist/_chunks/{pdf-viewer-C3minW5b.js → pdf-viewer-CNQxa4tv.js} +396 -391
- package/dist/_chunks/pdf-viewer-CNQxa4tv.js.map +1 -0
- package/dist/_chunks/{phone-input-DxkHMYmu.js → phone-input-O9camxkq.js} +156 -151
- package/dist/_chunks/phone-input-O9camxkq.js.map +1 -0
- package/dist/_chunks/popover-BG75rYjN.js +367 -0
- package/dist/_chunks/popover-BG75rYjN.js.map +1 -0
- package/dist/_chunks/{practice-results-Dhbo-fc_.js → practice-results-D07wgCqV.js} +2 -2
- package/dist/_chunks/{practice-results-Dhbo-fc_.js.map → practice-results-D07wgCqV.js.map} +1 -1
- package/dist/_chunks/{pregnancy-dating-Bfu0Cq4H.js → pregnancy-dating-BFzv9g1N.js} +2 -2
- package/dist/_chunks/{pregnancy-dating-Bfu0Cq4H.js.map → pregnancy-dating-BFzv9g1N.js.map} +1 -1
- package/dist/_chunks/{product-hub-panel-BSSiGGG4.js → product-hub-panel-DCYX0rPG.js} +103 -96
- package/dist/_chunks/product-hub-panel-DCYX0rPG.js.map +1 -0
- package/dist/_chunks/{public-footer-CxpG6J1M.js → public-footer-ZWTEG1Rq.js} +2 -2
- package/dist/_chunks/{public-footer-CxpG6J1M.js.map → public-footer-ZWTEG1Rq.js.map} +1 -1
- package/dist/_chunks/{public-header.agent-pr2hyiND.js → public-header.agent-C1SlVSYt.js} +2 -2
- package/dist/_chunks/{public-header.agent-pr2hyiND.js.map → public-header.agent-C1SlVSYt.js.map} +1 -1
- package/dist/_chunks/{radiograph-panel.agent-DkUokbEa.js → radiograph-panel.agent-DyqbTECc.js} +4 -4
- package/dist/_chunks/{radiograph-panel.agent-DkUokbEa.js.map → radiograph-panel.agent-DyqbTECc.js.map} +1 -1
- package/dist/_chunks/{registration-form-D7iNqMBF.js → registration-form-DrSR9Sjk.js} +4 -4
- package/dist/_chunks/{registration-form-D7iNqMBF.js.map → registration-form-DrSR9Sjk.js.map} +1 -1
- package/dist/_chunks/{rich-text-editor-CkFfmA3v.js → rich-text-editor-UgXri8h6.js} +490 -485
- package/dist/_chunks/rich-text-editor-UgXri8h6.js.map +1 -0
- package/dist/_chunks/{scroll-area-ZtFCv9K7.js → scroll-area-CY5SLYNw.js} +104 -74
- package/dist/_chunks/scroll-area-CY5SLYNw.js.map +1 -0
- package/dist/_chunks/{search-bar-DQJS0wJN.js → search-bar-mA4bPe3t.js} +294 -255
- package/dist/_chunks/search-bar-mA4bPe3t.js.map +1 -0
- package/dist/_chunks/{sheet-C7SwIxwB.js → sheet-Dtjk0CVv.js} +3 -3
- package/dist/_chunks/{sheet-C7SwIxwB.js.map → sheet-Dtjk0CVv.js.map} +1 -1
- package/dist/_chunks/sidebar-D4Wllqfz.js +2029 -0
- package/dist/_chunks/sidebar-D4Wllqfz.js.map +1 -0
- package/dist/_chunks/{sign-document-B6HlyCGV.js → sign-document-D4iHS_Ug.js} +2 -2
- package/dist/_chunks/{sign-document-B6HlyCGV.js.map → sign-document-D4iHS_Ug.js.map} +1 -1
- package/dist/_chunks/{signature-request-DhbpB9N9.js → signature-request-dAVgE0_5.js} +3 -3
- package/dist/_chunks/{signature-request-DhbpB9N9.js.map → signature-request-dAVgE0_5.js.map} +1 -1
- package/dist/_chunks/{signed-out-frame-B2GTIeqA.js → signed-out-frame-DOJpobp8.js} +3 -3
- package/dist/_chunks/{signed-out-frame-B2GTIeqA.js.map → signed-out-frame-DOJpobp8.js.map} +1 -1
- package/dist/_chunks/{state-backed-text-input-DECQy5aA.js → state-backed-text-input-Cgh4ms3p.js} +2 -2
- package/dist/_chunks/{state-backed-text-input-DECQy5aA.js.map → state-backed-text-input-Cgh4ms3p.js.map} +1 -1
- package/dist/_chunks/{task-editor-ByyRu29Y.js → task-editor-BflEZmcF.js} +7 -6
- package/dist/_chunks/task-editor-BflEZmcF.js.map +1 -0
- package/dist/_chunks/{tool-rail-Bwyuw_Ot.js → tool-rail-CTq1KwxW.js} +115 -114
- package/dist/_chunks/{tool-rail-Bwyuw_Ot.js.map → tool-rail-CTq1KwxW.js.map} +1 -1
- package/dist/_chunks/{use-appointment-details-read-JsDM48tf.js → use-appointment-details-read-izwoXh-G.js} +8 -8
- package/dist/_chunks/{use-appointment-details-read-JsDM48tf.js.map → use-appointment-details-read-izwoXh-G.js.map} +1 -1
- package/dist/_chunks/use-state-backed-input-DhRQo6gM.js +57 -0
- package/dist/_chunks/use-state-backed-input-DhRQo6gM.js.map +1 -0
- package/dist/_chunks/{voice-control-panel-Bg1eklL0.js → voice-control-panel-an-bpQfF.js} +3 -3
- package/dist/_chunks/{voice-control-panel-Bg1eklL0.js.map → voice-control-panel-an-bpQfF.js.map} +1 -1
- package/dist/_chunks/{widget-picker-DXYBMTfe.js → widget-picker-DlJOgYrZ.js} +80 -57
- package/dist/_chunks/widget-picker-DlJOgYrZ.js.map +1 -0
- package/dist/agent-catalog.json +3 -3
- package/dist/agent-i18n/en.json +1 -1
- package/dist/components/_shared/navigation-dismiss.d.ts +8 -0
- package/dist/components/_shared/navigation-dismiss.d.ts.map +1 -0
- package/dist/components/_shared/non-modal-tab-exit.d.ts +15 -4
- package/dist/components/_shared/non-modal-tab-exit.d.ts.map +1 -1
- package/dist/components/_shared/use-state-backed-input.d.ts +3 -2
- package/dist/components/_shared/use-state-backed-input.d.ts.map +1 -1
- package/dist/components/address-fields/index.js +1 -1
- package/dist/components/ai-credits-notice/index.js +1 -1
- package/dist/components/ai-permission-notice/ai-permission-notice.d.ts +32 -0
- package/dist/components/ai-permission-notice/ai-permission-notice.d.ts.map +1 -1
- package/dist/components/ai-permission-notice/index.d.ts +1 -1
- package/dist/components/ai-permission-notice/index.d.ts.map +1 -1
- package/dist/components/ai-permission-notice/index.js +1 -1
- package/dist/components/app-frame/index.js +1 -1
- package/dist/components/appointment-details-panel/index.js +1 -1
- package/dist/components/appointment-peek/index.js +1 -1
- package/dist/components/appointment-timeline/index.js +1 -1
- package/dist/components/booking/index.js +1 -1
- package/dist/components/calculator-dialog/index.js +1 -1
- package/dist/components/care-plan-card/index.js +1 -1
- package/dist/components/care-plan-header/index.js +1 -1
- package/dist/components/chart/chart.d.ts +5 -5
- package/dist/components/chart/chart.d.ts.map +1 -1
- package/dist/components/chart/index.js +1 -1
- package/dist/components/city-input/index.js +1 -1
- package/dist/components/clinical-note-card/index.js +1 -1
- package/dist/components/color-picker/color-picker.d.ts.map +1 -1
- package/dist/components/color-picker/index.js +1 -1
- package/dist/components/contact-card/index.js +1 -1
- package/dist/components/contact-profile-card/index.js +1 -1
- package/dist/components/control-room-rail/index.js +1 -1
- package/dist/components/cycle-calculator/index.js +1 -1
- package/dist/components/dashboard-grid/dashboard-grid.d.ts +33 -8
- package/dist/components/dashboard-grid/dashboard-grid.d.ts.map +1 -1
- package/dist/components/dashboard-grid/index.js +1 -1
- package/dist/components/data-table/index.js +2 -2
- package/dist/components/data-table-tabs/index.js +1 -1
- 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/date-time-picker.d.ts.map +1 -1
- package/dist/components/date-time-picker/index.js +1 -1
- package/dist/components/dialog/index.js +1 -1
- package/dist/components/document-preview/index.js +1 -1
- package/dist/components/due-date-calculator/index.js +1 -1
- package/dist/components/entity-summary/index.js +1 -1
- package/dist/components/face-scheme/index.js +1 -1
- 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/header-settings/index.js +1 -1
- package/dist/components/heatmap/index.js +1 -1
- package/dist/components/hover-card/hover-card.d.ts.map +1 -1
- package/dist/components/hover-card/index.js +1 -1
- package/dist/components/icon-picker/index.js +1 -1
- package/dist/components/info-tip/index.js +1 -1
- package/dist/components/link/index.js +1 -1
- package/dist/components/link/link.d.ts +5 -3
- package/dist/components/link/link.d.ts.map +1 -1
- package/dist/components/list/index.js +1 -1
- package/dist/components/list/list.d.ts.map +1 -1
- package/dist/components/locale-picker/index.js +1 -1
- package/dist/components/message-tray/index.js +1 -1
- package/dist/components/message-tray/message-tray.d.ts.map +1 -1
- package/dist/components/nav-grid/index.js +1 -1
- package/dist/components/note-timeline/index.js +1 -1
- package/dist/components/notes-panel/index.js +1 -1
- package/dist/components/notification-tray/index.js +1 -1
- package/dist/components/notification-tray/notification-tray.d.ts.map +1 -1
- package/dist/components/panel-subview/index.js +1 -1
- package/dist/components/panel-subview/panel-subview.d.ts.map +1 -1
- package/dist/components/patient-details/index.js +1 -1
- package/dist/components/patient-summary-card/index.js +1 -1
- package/dist/components/patient-table/index.js +1 -1
- package/dist/components/payment-card/index.js +1 -1
- package/dist/components/pdf-viewer/index.js +1 -1
- package/dist/components/pdf-viewer/pdf-viewer.d.ts.map +1 -1
- package/dist/components/phone-input/index.js +1 -1
- package/dist/components/phone-input/phone-input.d.ts.map +1 -1
- package/dist/components/popover/index.js +1 -1
- package/dist/components/popover/popover.d.ts +1 -1
- package/dist/components/popover/popover.d.ts.map +1 -1
- package/dist/components/practice-results/index.js +1 -1
- package/dist/components/pregnancy-dating/index.js +1 -1
- package/dist/components/product-hub-tray/index.js +1 -1
- package/dist/components/product-hub-tray/product-hub-tray.d.ts.map +1 -1
- package/dist/components/public-footer/index.js +1 -1
- package/dist/components/public-header/index.js +1 -1
- package/dist/components/radiograph-panel/index.js +1 -1
- package/dist/components/rich-text-editor/editor-toolbar.d.ts.map +1 -1
- package/dist/components/rich-text-editor/index.js +2 -2
- package/dist/components/scroll-area/index.js +1 -1
- package/dist/components/scroll-area/scroll-area.d.ts +6 -5
- package/dist/components/scroll-area/scroll-area.d.ts.map +1 -1
- package/dist/components/search-bar/index.js +1 -1
- package/dist/components/search-bar/search-bar.d.ts +1 -1
- package/dist/components/search-bar/search-bar.d.ts.map +1 -1
- package/dist/components/sheet/index.js +1 -1
- package/dist/components/sidebar/index.d.ts +1 -1
- package/dist/components/sidebar/index.d.ts.map +1 -1
- package/dist/components/sidebar/index.js +1 -1
- package/dist/components/sidebar/sidebar-move.d.ts +88 -0
- package/dist/components/sidebar/sidebar-move.d.ts.map +1 -0
- package/dist/components/sidebar/sidebar.d.ts +26 -1
- package/dist/components/sidebar/sidebar.d.ts.map +1 -1
- package/dist/components/sign-document/index.js +1 -1
- package/dist/components/task-editor/index.js +1 -1
- package/dist/components/task-editor/task-editor.d.ts.map +1 -1
- package/dist/components/tool-rail/index.js +1 -1
- package/dist/components/tool-rail/tool-rail.d.ts.map +1 -1
- package/dist/components/voice-control-panel/index.js +1 -1
- package/dist/components/widget-picker/index.js +1 -1
- package/dist/components/widget-picker/widget-picker.d.ts.map +1 -1
- package/dist/host-compat.css +2 -1
- package/dist/i18n/locales/ar.d.ts +24 -0
- package/dist/i18n/locales/ar.d.ts.map +1 -1
- package/dist/i18n/locales/ar.js +26 -2
- package/dist/i18n/locales/ar.js.map +1 -1
- package/dist/i18n/locales/de.d.ts +24 -0
- package/dist/i18n/locales/de.d.ts.map +1 -1
- package/dist/i18n/locales/de.js +26 -2
- package/dist/i18n/locales/de.js.map +1 -1
- package/dist/i18n/locales/el.d.ts +24 -0
- package/dist/i18n/locales/el.d.ts.map +1 -1
- package/dist/i18n/locales/el.js +26 -2
- package/dist/i18n/locales/el.js.map +1 -1
- package/dist/i18n/locales/en.d.ts +24 -0
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/en.js +26 -2
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +24 -0
- package/dist/i18n/locales/es.d.ts.map +1 -1
- package/dist/i18n/locales/es.js +26 -2
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +24 -0
- package/dist/i18n/locales/fr.d.ts.map +1 -1
- package/dist/i18n/locales/fr.js +26 -2
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hi.d.ts +24 -0
- package/dist/i18n/locales/hi.d.ts.map +1 -1
- package/dist/i18n/locales/hi.js +26 -2
- package/dist/i18n/locales/hi.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +24 -0
- package/dist/i18n/locales/it.d.ts.map +1 -1
- package/dist/i18n/locales/it.js +26 -2
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/ja.d.ts +24 -0
- package/dist/i18n/locales/ja.d.ts.map +1 -1
- package/dist/i18n/locales/ja.js +26 -2
- package/dist/i18n/locales/ja.js.map +1 -1
- package/dist/i18n/locales/nl.d.ts +24 -0
- package/dist/i18n/locales/nl.d.ts.map +1 -1
- package/dist/i18n/locales/nl.js +26 -2
- package/dist/i18n/locales/nl.js.map +1 -1
- package/dist/i18n/locales/pl.d.ts +24 -0
- package/dist/i18n/locales/pl.d.ts.map +1 -1
- package/dist/i18n/locales/pl.js +26 -2
- package/dist/i18n/locales/pl.js.map +1 -1
- package/dist/i18n/locales/pt.d.ts +24 -0
- package/dist/i18n/locales/pt.d.ts.map +1 -1
- package/dist/i18n/locales/pt.js +26 -2
- package/dist/i18n/locales/pt.js.map +1 -1
- package/dist/i18n/locales/ro.d.ts +24 -0
- package/dist/i18n/locales/ro.d.ts.map +1 -1
- package/dist/i18n/locales/ro.js +26 -2
- package/dist/i18n/locales/ro.js.map +1 -1
- package/dist/i18n/locales/ru.d.ts +24 -0
- package/dist/i18n/locales/ru.d.ts.map +1 -1
- package/dist/i18n/locales/ru.js +26 -2
- package/dist/i18n/locales/ru.js.map +1 -1
- package/dist/i18n/locales/sq.d.ts +24 -0
- package/dist/i18n/locales/sq.d.ts.map +1 -1
- package/dist/i18n/locales/sq.js +26 -2
- package/dist/i18n/locales/sq.js.map +1 -1
- package/dist/i18n/locales/sv.d.ts +24 -0
- package/dist/i18n/locales/sv.d.ts.map +1 -1
- package/dist/i18n/locales/sv.js +26 -2
- package/dist/i18n/locales/sv.js.map +1 -1
- package/dist/i18n/locales/tr.d.ts +24 -0
- package/dist/i18n/locales/tr.d.ts.map +1 -1
- package/dist/i18n/locales/tr.js +26 -2
- package/dist/i18n/locales/tr.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +24 -0
- package/dist/i18n/locales/zh.d.ts.map +1 -1
- package/dist/i18n/locales/zh.js +26 -2
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/index.js +204 -203
- package/dist/locales/ar.json +26 -2
- package/dist/locales/de.json +26 -2
- package/dist/locales/el.json +26 -2
- package/dist/locales/en.json +26 -2
- package/dist/locales/es.json +26 -2
- package/dist/locales/fr.json +26 -2
- package/dist/locales/hi.json +26 -2
- package/dist/locales/it.json +26 -2
- package/dist/locales/ja.json +26 -2
- package/dist/locales/nl.json +26 -2
- package/dist/locales/pl.json +26 -2
- package/dist/locales/pt.json +26 -2
- package/dist/locales/ro.json +26 -2
- package/dist/locales/ru.json +26 -2
- package/dist/locales/sq.json +26 -2
- package/dist/locales/sv.json +26 -2
- package/dist/locales/tr.json +26 -2
- package/dist/locales/zh.json +26 -2
- package/dist/patterns/alia-assistant/alia-asteroid-icon.d.ts +10 -13
- package/dist/patterns/alia-assistant/alia-asteroid-icon.d.ts.map +1 -1
- package/dist/patterns/alia-assistant/alia-chat-surface.d.ts.map +1 -1
- package/dist/patterns/alia-assistant/alia-popout.d.ts +5 -3
- package/dist/patterns/alia-assistant/alia-popout.d.ts.map +1 -1
- package/dist/patterns/alia-assistant/index.d.ts +2 -0
- package/dist/patterns/alia-assistant/index.d.ts.map +1 -1
- package/dist/patterns/alia-assistant/index.js +6 -5
- package/dist/patterns/anamnesis/index.js +1 -1
- package/dist/patterns/calendar/index.js +1 -1
- package/dist/patterns/forgot-password-form/index.js +1 -1
- package/dist/patterns/help-me-write-templates/index.js +1 -1
- package/dist/patterns/login-form/index.js +1 -1
- package/dist/patterns/marketplace-app-shell/index.js +1 -1
- package/dist/patterns/marketplace-app-shell/marketplace-app-shell.d.ts +40 -10
- package/dist/patterns/marketplace-app-shell/marketplace-app-shell.d.ts.map +1 -1
- package/dist/patterns/payment-automation-upsell/index.js +1 -1
- package/dist/patterns/registration-form/index.js +1 -1
- package/dist/patterns/signature-request/index.js +1 -1
- package/dist/patterns/signed-out-frame/index.js +1 -1
- package/dist/tokens.css +1 -1
- package/package.json +1 -1
- package/dist/_chunks/ai-permission-notice-5vpblPCx.js +0 -171
- package/dist/_chunks/ai-permission-notice-5vpblPCx.js.map +0 -1
- package/dist/_chunks/alia-sidebar-DOei4Iyu.js +0 -1183
- package/dist/_chunks/alia-sidebar-DOei4Iyu.js.map +0 -1
- package/dist/_chunks/calendar-workspace-Du2ryaI-.js.map +0 -1
- package/dist/_chunks/chart-HsF1KHbx.js.map +0 -1
- package/dist/_chunks/color-picker-BRQ4Y9SO.js.map +0 -1
- package/dist/_chunks/dashboard-grid-DfEY2qci.js +0 -844
- package/dist/_chunks/dashboard-grid-DfEY2qci.js.map +0 -1
- package/dist/_chunks/date-picker-wRAcq2lt.js.map +0 -1
- package/dist/_chunks/date-range-picker-CtUOI38x.js.map +0 -1
- package/dist/_chunks/date-time-picker-CLeLKuv9.js.map +0 -1
- package/dist/_chunks/hover-card-BnTueNS2.js.map +0 -1
- package/dist/_chunks/link-2HokYuIi.js +0 -130
- package/dist/_chunks/link-2HokYuIi.js.map +0 -1
- package/dist/_chunks/list-RRN2TJ_7.js.map +0 -1
- package/dist/_chunks/marketplace-app-shell-Dcx-JEjg.js +0 -541
- package/dist/_chunks/marketplace-app-shell-Dcx-JEjg.js.map +0 -1
- package/dist/_chunks/message-tray-BB95DA82.js.map +0 -1
- package/dist/_chunks/non-modal-tab-exit-D2Bd93Bq.js +0 -65
- package/dist/_chunks/non-modal-tab-exit-D2Bd93Bq.js.map +0 -1
- package/dist/_chunks/notification-tray-__sJXnsz.js.map +0 -1
- package/dist/_chunks/panel-subview-BT-Apwgb.js.map +0 -1
- package/dist/_chunks/pdf-viewer-C3minW5b.js.map +0 -1
- package/dist/_chunks/phone-input-DxkHMYmu.js.map +0 -1
- package/dist/_chunks/popover-BI3oV3eY.js +0 -305
- package/dist/_chunks/popover-BI3oV3eY.js.map +0 -1
- package/dist/_chunks/product-hub-panel-BSSiGGG4.js.map +0 -1
- package/dist/_chunks/rich-text-editor-CkFfmA3v.js.map +0 -1
- package/dist/_chunks/scroll-area-ZtFCv9K7.js.map +0 -1
- package/dist/_chunks/search-bar-DQJS0wJN.js.map +0 -1
- package/dist/_chunks/sidebar-DLsG2AIk.js +0 -1349
- package/dist/_chunks/sidebar-DLsG2AIk.js.map +0 -1
- package/dist/_chunks/task-editor-ByyRu29Y.js.map +0 -1
- package/dist/_chunks/use-state-backed-input-C7ESmxKB.js +0 -59
- package/dist/_chunks/use-state-backed-input-C7ESmxKB.js.map +0 -1
- package/dist/_chunks/widget-picker-DXYBMTfe.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"heatmap-Gf9r7Tn1.js","sources":["../../node_modules/lucide-react/dist/esm/icons/grid-3x3.mjs","../../node_modules/lucide-react/dist/esm/icons/table-2.mjs","../../src/components/heatmap/heatmap.agent.ts","../../src/components/heatmap/heatmap-context.ts","../../src/components/heatmap/heatmap-format.ts","../../src/components/heatmap/heatmap-scale.ts","../../src/components/heatmap/heatmap-model.ts","../../src/components/heatmap/heatmap-tooltip.tsx","../../src/components/heatmap/heatmap-window.ts","../../src/components/heatmap/heatmap-variants.ts","../../src/components/heatmap/heatmap-grid.tsx","../../src/components/heatmap/heatmap-legend.tsx","../../src/components/heatmap/heatmap-table-view.tsx","../../src/components/heatmap/heatmap.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 [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M3 9h18\", key: \"1pudct\" }],\n [\"path\", { d: \"M3 15h18\", key: \"5xshup\" }],\n [\"path\", { d: \"M9 3v18\", key: \"fh3hqa\" }],\n [\"path\", { d: \"M15 3v18\", key: \"14nvp0\" }]\n];\nconst Grid3x3 = createLucideIcon(\"grid-3x3\", __iconNode);\n\nexport { __iconNode, Grid3x3 as default };\n//# sourceMappingURL=grid-3x3.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 [\n \"path\",\n {\n d: \"M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v18m0 0h10a2 2 0 0 0 2-2V9M9 21H5a2 2 0 0 1-2-2V9m0 0h18\",\n key: \"gugj83\"\n }\n ]\n];\nconst Table2 = createLucideIcon(\"table-2\", __iconNode);\n\nexport { __iconNode, Table2 as default };\n//# sourceMappingURL=table-2.mjs.map\n","/* -------------------------------------------------------------------- */\n/* Agent adapter: Heatmap. */\n/* */\n/* Operations go through the curated `HeatmapHandle`. State returns ids, */\n/* numbers and structure only: never a row, column or group label, which */\n/* may name a person (src/docs/26-agent-readiness.mdx §7). The row, */\n/* column and group ids are state so an agent can address any cell, even */\n/* one a virtualised grid has not rendered. Every write rejects an id */\n/* the heatmap does not have before it changes or announces anything. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { HeatmapHandle } from './heatmap';\n\nconst cellSchema = {\n type: 'object',\n properties: {\n rowId: { type: 'string', description: 'Row id, from rowIds.' },\n columnId: {\n type: ['string', 'number'],\n description: 'Column id, from columnIds.',\n },\n },\n required: ['rowId', 'columnId'],\n} as const;\n\nexport const heatmapAgent: AgentAdapter<HeatmapHandle> = {\n id: 'heatmap',\n capabilities: [\n 'select_single',\n 'select_multiple',\n 'range_pick',\n 'expand',\n 'sort',\n 'view_change',\n ],\n state: {\n selection: {\n type: 'Array<{ rowId, columnId }>',\n descriptionKey: 'ui.agent.heatmap.state.selection',\n description: 'Row and column ids of the selected cells.',\n read: (handle) => handle.getSelection(),\n },\n selectionMode: {\n type: \"'none' | 'single' | 'multiple' | 'range'\",\n descriptionKey: 'ui.agent.heatmap.state.selectionMode',\n description: 'How cells can be selected in this heatmap.',\n read: (handle) => handle.getSelectionMode(),\n },\n view: {\n type: \"'heatmap' | 'table'\",\n descriptionKey: 'ui.agent.heatmap.state.view',\n description: 'Whether the heatmap or its table view is showing.',\n read: (handle) => handle.getView(),\n },\n sortRows: {\n type: \"'none' | 'label' | 'total-asc' | 'total-desc'\",\n descriptionKey: 'ui.agent.heatmap.state.sortRows',\n description: 'Current row order.',\n read: (handle) => handle.getSortRows(),\n },\n rowIds: {\n type: 'string[]',\n descriptionKey: 'ui.agent.heatmap.state.rowIds',\n description:\n 'Row ids in display order, every group expanded. Opaque, never a label.',\n read: (handle) => handle.getRowIds(),\n },\n columnIds: {\n type: 'Array<string | number>',\n descriptionKey: 'ui.agent.heatmap.state.columnIds',\n description: 'Column ids in order. Opaque, never a label.',\n read: (handle) => handle.getColumnIds(),\n },\n groupIds: {\n type: 'string[]',\n descriptionKey: 'ui.agent.heatmap.state.groupIds',\n description:\n 'Group ids in display order, empty unless rows are grouped. A group not listed in `groups` shows as group-1, group-2 and so on.',\n read: (handle) => handle.getGroupIds(),\n },\n collapsedGroups: {\n type: 'string[]',\n descriptionKey: 'ui.agent.heatmap.state.collapsedGroups',\n description: 'Ids (as in groupIds) of the row groups that are collapsed.',\n read: (handle) => handle.getCollapsedGroups(),\n },\n },\n actions: {\n select_cell: {\n safety: 'read',\n argsType: '{ rowId: string, columnId: string | number }',\n argsSchema: cellSchema,\n idempotent: true,\n descriptionKey: 'ui.agent.heatmap.actions.selectCell',\n description: 'Make one cell the whole selection.',\n errors: [\n 'Selection is off (selection=\"none\").',\n 'The row or column id does not exist.',\n ],\n examples: [\n {\n args: { rowId: 'chair-1', columnId: 10 },\n note: 'Select chair 1 at 10:00.',\n },\n ],\n invoke: (handle, args: { rowId: string; columnId: string | number }) => {\n handle.selectCells([args]);\n },\n },\n select_cells: {\n safety: 'read',\n argsType: '{ cells: Array<{ rowId, columnId }> }',\n argsSchema: {\n type: 'object',\n properties: {\n cells: {\n type: 'array',\n items: cellSchema,\n description:\n 'Cells to select; replaces the selection. Single mode keeps the first.',\n },\n },\n required: ['cells'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.heatmap.actions.selectCells',\n description: 'Replace the selection with the given cells.',\n errors: [\n 'Selection is off (selection=\"none\").',\n 'A row or column id does not exist; nothing is selected.',\n ],\n invoke: (\n handle,\n args: { cells: { rowId: string; columnId: string | number }[] },\n ) => {\n handle.selectCells(args.cells);\n },\n },\n select_range: {\n safety: 'read',\n argsType: '{ from: { rowId, columnId }, to: { rowId, columnId } }',\n argsSchema: {\n type: 'object',\n properties: {\n from: { ...cellSchema, description: 'One corner, inclusive.' },\n to: { ...cellSchema, description: 'The opposite corner, inclusive.' },\n },\n required: ['from', 'to'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.heatmap.actions.selectRange',\n description:\n 'Select the rectangle of cells between two corners, in the rows as shown.',\n errors: [\n 'Needs selection=\"range\" or \"multiple\".',\n 'A corner names a row or column that does not exist.',\n ],\n invoke: (\n handle,\n args: {\n from: { rowId: string; columnId: string | number };\n to: { rowId: string; columnId: string | number };\n },\n ) => {\n handle.selectRange(args.from, args.to);\n },\n },\n clear_selection: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.heatmap.actions.clearSelection',\n description: 'Deselect every cell.',\n errors: ['Selection is off (selection=\"none\").'],\n invoke: (handle) => {\n handle.clearSelection();\n },\n },\n read_cell: {\n safety: 'read',\n argsType: '{ rowId: string, columnId: string | number }',\n argsSchema: cellSchema,\n returns: '{ value, count, status, step } | null',\n returnsSchema: {\n type: ['object', 'null'],\n properties: {\n value: { type: ['number', 'null'] },\n count: { type: 'number' },\n status: { enum: ['value', 'empty', 'low-sample'] },\n step: { type: ['number', 'null'] },\n },\n },\n idempotent: true,\n descriptionKey: 'ui.agent.heatmap.actions.readCell',\n description:\n \"Read a cell's value, count, status and colour step (no labels).\",\n invoke: (handle, args: { rowId: string; columnId: string | number }) =>\n handle.readCell(args),\n },\n toggle_table_view: {\n safety: 'read',\n descriptionKey: 'ui.agent.heatmap.actions.toggleTableView',\n description: 'Switch between the heatmap and its table view.',\n returns: \"'heatmap' | 'table'\",\n returnsSchema: { enum: ['heatmap', 'table'] },\n invoke: (handle) => {\n const next = handle.getView() === 'table' ? 'heatmap' : 'table';\n handle.setView(next);\n return next;\n },\n },\n set_view: {\n safety: 'read',\n argsType: \"{ view: 'heatmap' | 'table' }\",\n argsSchema: {\n type: 'object',\n properties: {\n view: {\n enum: ['heatmap', 'table'],\n description: 'The coloured grid, or the same data as a table.',\n },\n },\n required: ['view'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.heatmap.actions.setView',\n description: 'Show the heatmap or its table view.',\n invoke: (handle, args: { view: 'heatmap' | 'table' }) => {\n if (handle.getView() !== args.view) handle.setView(args.view);\n },\n },\n sort_rows: {\n safety: 'read',\n argsType: \"{ sort: 'none' | 'label' | 'total-asc' | 'total-desc' }\",\n argsSchema: {\n type: 'object',\n properties: {\n sort: {\n enum: ['none', 'label', 'total-asc', 'total-desc'],\n description:\n 'Row order within each group: as given, by label, or by row total.',\n },\n },\n required: ['sort'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.heatmap.actions.sortRows',\n description: 'Reorder the rows.',\n invoke: (\n handle,\n args: { sort: 'none' | 'label' | 'total-asc' | 'total-desc' },\n ) => {\n handle.setSortRows(args.sort);\n },\n },\n expand_group: {\n safety: 'read',\n argsType: '{ groupId: string }',\n argsSchema: {\n type: 'object',\n properties: {\n groupId: { type: 'string', description: 'Group id, from groupIds.' },\n },\n required: ['groupId'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.heatmap.actions.expandGroup',\n description: \"Show a group's rows.\",\n errors: [\n 'Rows are not grouped (groupRows is off).',\n 'The group id does not exist (see groupIds).',\n ],\n invoke: (handle, args: { groupId: string }) => {\n handle.setGroupCollapsed(args.groupId, false);\n },\n },\n collapse_group: {\n safety: 'read',\n argsType: '{ groupId: string }',\n argsSchema: {\n type: 'object',\n properties: {\n groupId: { type: 'string', description: 'Group id, from groupIds.' },\n },\n required: ['groupId'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.heatmap.actions.collapseGroup',\n description: \"Hide a group's rows, leaving its totals row.\",\n errors: [\n 'Rows are not grouped (groupRows is off).',\n 'The group id does not exist (see groupIds).',\n ],\n invoke: (handle, args: { groupId: string }) => {\n handle.setGroupCollapsed(args.groupId, true);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'heatmap',\n description: 'Marks the Heatmap root.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop on Heatmap.',\n },\n item: {\n attr: 'data-heatmap-cell-id',\n description:\n 'On every data cell: \"<rowId>:<columnId>\", built from the opaque ids, never from labels. A group header row and its cells carry data-heatmap-group-id, the group id as in groupIds.',\n },\n },\n};\n","/* -------------------------------------------------------------------- */\n/* Context shared by the Heatmap root and its compound parts, so */\n/* Heatmap.Legend and Heatmap.Tooltip read the same scale, palette and */\n/* wording as the grid. */\n/* -------------------------------------------------------------------- */\n\nimport { createContext, useContext } from 'react';\nimport type { HeatmapDescriber } from './heatmap-format';\nimport type { HeatmapCellInfo } from './heatmap-model';\nimport type { ResolvedHeatmapScale } from './heatmap-scale';\nimport type { HeatmapPalette } from './heatmap-variants';\n\nexport interface HeatmapContextValue {\n palette: HeatmapPalette;\n scale: ResolvedHeatmapScale;\n describer: HeatmapDescriber;\n /** True when some cells fall below `minCount`, so the legend explains it. */\n hasLowSample: boolean;\n /** True when some cells have no data. */\n hasEmpty: boolean;\n /** The sample threshold, when one is set. */\n minCount?: number;\n /** The tooltip text for a cell: the consumer's, or the default sentence. */\n tooltipText: (cell: HeatmapCellInfo) => string;\n}\n\nexport const HeatmapContext = createContext<HeatmapContextValue | null>(null);\n\n/** The surrounding Heatmap's context, or null outside one. */\nexport function useHeatmapContext(): HeatmapContextValue | null {\n return useContext(HeatmapContext);\n}\n","/* -------------------------------------------------------------------- */\n/* Heatmap text: number formats in the active locale, and the sentences */\n/* the cells, totals, tooltip and table view share, with privacy mode */\n/* applied in one place. */\n/* -------------------------------------------------------------------- */\n\nimport type { TFunction } from 'i18next';\nimport { privacyMask } from '../_shared/privacy-mask';\nimport type {\n HeatmapColumn,\n HeatmapGroup,\n HeatmapRow,\n ModelCell,\n} from './heatmap-model';\nimport type { HeatmapAggregate } from './heatmap-scale';\n\n/** What the values are: plain numbers, or rates between 0 and 1. */\nexport type HeatmapValueType = 'number' | 'rate';\n\n/**\n * What privacy mode masks. `rows`: the row labels, which name people,\n * chairs or patients. `all`: the column and group labels too. The kit rule\n * (src/components/_shared/privacy-mask.tsx) is to mask the identity and keep\n * time, place and status, so columns (hours, days) and groups (practices)\n * stay readable unless the host asks for more.\n */\nexport type HeatmapPrivacyScope = 'rows' | 'all';\n\n/** The default value format: a percentage for rates, a decimal otherwise. */\nexport function defaultValueFormatter(\n locale: string,\n valueType: HeatmapValueType,\n): (value: number) => string {\n const format = new Intl.NumberFormat(\n locale,\n valueType === 'rate'\n ? { style: 'percent', maximumFractionDigits: 0 }\n : { maximumFractionDigits: 2 },\n );\n return (value) => format.format(value);\n}\n\n/** Whole-number format for counts. */\nexport function countFormatter(locale: string): (count: number) => string {\n const format = new Intl.NumberFormat(locale, { maximumFractionDigits: 0 });\n return (count) => format.format(count);\n}\n\n/** Builds every sentence the heatmap speaks or shows. */\nexport interface HeatmapDescriber {\n /** True when privacy mode hides the row labels. */\n masksRows: boolean;\n /** True when privacy mode hides the column labels. */\n masksColumns: boolean;\n /** True when privacy mode hides the group labels. */\n masksGroups: boolean;\n rowLabel: (row: HeatmapRow) => string;\n columnLabel: (column: HeatmapColumn) => string;\n groupLabel: (groupId: string) => string;\n /** A cell by its headers: \"Tuesday, 10:00\". */\n cellName: (rowText: string, columnText: string) => string;\n /** A group header row: \"Mos Eisley (Average)\". */\n groupRowText: (groupText: string, method: HeatmapAggregate) => string;\n /** A cell as the table view shows it: \"26%, 10 of 39\". */\n tableText: (cell: ModelCell) => string;\n /** Label for a margin: \"Total\" for a sum, \"Average\" for a mean. */\n methodLabel: (method: HeatmapAggregate) => string;\n /** The value as text: formatted, a cell label, \"no data\" or \"too few\". */\n valueText: (cell: ModelCell) => string;\n /** The value as shown inside a cell, or '' when the cell shows none. */\n visibleText: (cell: ModelCell) => string;\n /** \"10 of 39\" for a rate, \"39 records\" otherwise; null without a count. */\n countText: (cell: ModelCell) => string | null;\n /** \"Tuesday, 10:00: 26%, 10 of 39\". */\n sentence: (rowText: string, columnText: string, cell: ModelCell) => string;\n /** Format for a raw value, used by the legend. */\n formatValue: (value: number) => string;\n}\n\nexport interface DescriberOptions {\n t: TFunction<'ui'>;\n privacyMode: boolean;\n /** What privacy mode masks. Default `rows`. */\n privacyScope?: HeatmapPrivacyScope;\n valueType: HeatmapValueType;\n formatValue: (value: number) => string;\n formatCount: (count: number) => string;\n groups?: readonly HeatmapGroup[];\n}\n\n/** The glyph an empty cell shows, so \"no data\" never relies on colour. */\nconst EMPTY_GLYPH = '–';\n\nexport function createDescriber({\n t,\n privacyMode,\n privacyScope = 'rows',\n valueType,\n formatValue,\n formatCount,\n groups,\n}: DescriberOptions): HeatmapDescriber {\n const groupNames = new Map(groups?.map((group) => [group.id, group.label]));\n const mask = privacyMask();\n const masksRows = privacyMode;\n const masksColumns = privacyMode && privacyScope === 'all';\n const masksGroups = privacyMode && privacyScope === 'all';\n const valueText = (cell: ModelCell): string => {\n if (cell.status === 'empty') return t('heatmap.noData');\n if (cell.status === 'low-sample') return t('heatmap.lowSample');\n // A cell label is free text, so privacy mode shows the number instead.\n if (cell.label !== undefined && !privacyMode) return cell.label;\n return cell.value === null ? t('heatmap.noData') : formatValue(cell.value);\n };\n const countText = (cell: ModelCell): string | null => {\n if (cell.count === undefined) return null;\n if (\n valueType === 'rate' &&\n cell.status === 'value' &&\n cell.value !== null\n ) {\n return t('heatmap.countOf', {\n part: formatCount(Math.round(cell.value * cell.count)),\n total: formatCount(cell.count),\n });\n }\n return t('heatmap.records', {\n count: cell.count,\n formatted: formatCount(cell.count),\n });\n };\n return {\n masksRows,\n masksColumns,\n masksGroups,\n rowLabel: (row) => (masksRows ? mask : row.label),\n columnLabel: (column) => (masksColumns ? mask : column.label),\n // A group missing from `groups` has only its id to show, which may be a\n // name, so privacy mode masks it whatever the scope.\n groupLabel: (groupId) =>\n masksGroups\n ? mask\n : (groupNames.get(groupId) ?? (privacyMode ? mask : groupId)),\n cellName: (rowText, columnText) =>\n t('heatmap.cellName', { row: rowText, column: columnText }),\n groupRowText: (groupText, method) =>\n t('heatmap.groupRow', {\n group: groupText,\n method:\n method === 'sum' ? t('heatmap.totals.sum') : t('heatmap.totals.mean'),\n }),\n tableText: (cell) => {\n const count = cell.status === 'empty' ? null : countText(cell);\n const value = valueText(cell);\n return count === null\n ? value\n : t('heatmap.valueWithCount', { value, count });\n },\n methodLabel: (method) =>\n method === 'sum' ? t('heatmap.totals.sum') : t('heatmap.totals.mean'),\n valueText,\n visibleText: (cell) =>\n cell.status === 'empty'\n ? EMPTY_GLYPH\n : cell.status === 'low-sample'\n ? ''\n : valueText(cell),\n countText,\n sentence: (rowText, columnText, cell) => {\n const count = countText(cell);\n const value = valueText(cell);\n return count === null || cell.status === 'empty'\n ? t('heatmap.cell', { row: rowText, column: columnText, value })\n : t('heatmap.cellWithCount', {\n row: rowText,\n column: columnText,\n value,\n count,\n });\n },\n formatValue,\n };\n}\n","/* -------------------------------------------------------------------- */\n/* Heatmap scale maths. Pure functions, no React, so they are tested on */\n/* their own (heatmap-scale.test.ts) and shared by the grid, the legend */\n/* and the table view. */\n/* */\n/* Every scale maps a value to one of ten colour steps, 0 to 9. The */\n/* steps are tokens (`--heatmap-<palette>-<step>`), so a scale never */\n/* produces a colour itself. */\n/* -------------------------------------------------------------------- */\n\nimport { isDevelopment } from '../_shared/is-development';\n\n/** Number of colour steps every palette carries. */\nexport const HEATMAP_STEPS = 10;\n\n/** The step a degenerate scale (every value equal) falls back to. */\nconst MIDDLE_STEP = Math.floor(HEATMAP_STEPS / 2);\n\n/** Highest step index. */\nconst TOP_STEP = HEATMAP_STEPS - 1;\n\n/** Steps on each side of a diverging midpoint. */\nconst HALF_STEPS = HEATMAP_STEPS / 2;\n\n/**\n * How values map to colour steps.\n *\n * - `sequential`: low to high. `domain: 'auto'` (the default) uses the min\n * and max of the cells that show a value; a fixed `[min, max]` clamps.\n * - `diverging`: two hues either side of `midpoint`. `auto` makes the\n * domain symmetric around the midpoint, so equal distances either side\n * get equal intensity. The midpoint defaults to 0, or to the centre of a\n * fixed domain that does not include 0.\n * - `quantile`: equal-count buckets (default 10) from the shown values.\n * Repeated values never split: buckets that would cut through a run of\n * equal values merge, so the minimum always takes the first step.\n * - `threshold`: ascending cut points; `n` thresholds make `n + 1`\n * buckets, spread across the ten steps. At most nine; duplicates merge.\n *\n * A fixed domain is `[min, max]`. A reversed pair is put in order, with a\n * warning in development builds.\n */\nexport type HeatmapScale =\n | { type: 'sequential'; domain?: 'auto' | readonly [number, number] }\n | {\n type: 'diverging';\n domain?: 'auto' | readonly [number, number];\n midpoint?: number;\n }\n | { type: 'quantile'; buckets?: number }\n | { type: 'threshold'; thresholds: readonly number[] };\n\n/** A scale with its domain worked out against the data. */\nexport interface ResolvedHeatmapScale {\n type: HeatmapScale['type'];\n /** Low end of the domain, or of the data for quantile and threshold. */\n min: number | null;\n /** High end of the domain, or of the data for quantile and threshold. */\n max: number | null;\n /** Diverging only: the value that separates the two hues. */\n midpoint?: number;\n /** Quantile and threshold: the ascending bucket edges. */\n thresholds: readonly number[];\n /** Maps a value to a step, 0 to 9. */\n stepOf: (value: number) => number;\n}\n\nconst clamp = (value: number, low: number, high: number): number =>\n Math.min(high, Math.max(low, value));\n\n/** Messages already given, so a scale worked out again (each data change,\n * twice in StrictMode) does not repeat them. */\nconst warned = new Set<string>();\n\n/** Says what a scale was given and what it uses instead, in development,\n * once per message. */\nfunction warn(message: string): void {\n if (!isDevelopment() || warned.has(message)) return;\n warned.add(message);\n console.warn(`Heatmap: ${message}`);\n}\n\n/** A fixed domain in ascending order (a reversed one is put in order). */\nfunction orderedDomain(\n domain: readonly [number, number],\n): readonly [number, number] {\n if (domain[0] <= domain[1]) return domain;\n warn(\n `scale domain [${domain[0]}, ${domain[1]}] is reversed; using [${domain[1]}, ${domain[0]}].`,\n );\n return [domain[1], domain[0]];\n}\n\n/** Sorted, distinct, finite values. */\nfunction distinctSorted(values: readonly number[]): number[] {\n const sorted = values.filter(Number.isFinite).sort((a, b) => a - b);\n return sorted.filter((value, i) => i === 0 || value !== sorted[i - 1]);\n}\n\n/** Min and max of the finite values, or null when there are none. */\nexport function extent(values: readonly number[]): [number, number] | null {\n let low = Infinity;\n let high = -Infinity;\n for (const value of values) {\n if (!Number.isFinite(value)) continue;\n if (value < low) low = value;\n if (value > high) high = value;\n }\n return low === Infinity ? null : [low, high];\n}\n\n/**\n * Sequential step: the domain is cut into ten equal bands. A value on a\n * band edge takes the band above; the top edge belongs to the top step.\n * Values outside the domain clamp to the end steps.\n */\nexport function sequentialStep(value: number, low: number, high: number) {\n if (!(high > low)) return MIDDLE_STEP;\n const t = clamp((value - low) / (high - low), 0, 1);\n return Math.min(TOP_STEP, Math.floor(t * HEATMAP_STEPS));\n}\n\n/**\n * Diverging step: steps 0 to 4 sit below the midpoint (0 is the furthest),\n * steps 5 to 9 above it (9 is the furthest). Ten steps have no middle one,\n * so a value exactly on the midpoint takes step 5, the palest step above.\n * It is painted in the neutral midpoint colour instead (see `onMidpoint`).\n */\nexport function divergingStep(\n value: number,\n low: number,\n midpoint: number,\n high: number,\n): number {\n if (value < midpoint) {\n const span = midpoint - low;\n const t = span > 0 ? clamp((midpoint - value) / span, 0, 1) : 1;\n return (\n HALF_STEPS - 1 - Math.min(HALF_STEPS - 1, Math.floor(t * HALF_STEPS))\n );\n }\n const span = high - midpoint;\n const t =\n span > 0\n ? clamp((value - midpoint) / span, 0, 1)\n : value > midpoint\n ? 1\n : 0;\n return HALF_STEPS + Math.min(HALF_STEPS - 1, Math.floor(t * HALF_STEPS));\n}\n\n/**\n * Whether a value sits exactly on a diverging scale's midpoint, so it is\n * painted neutral (`--heatmap-midpoint`) rather than in either hue. Exact\n * up to floating-point rounding, a few units in the last place of the\n * scale's largest magnitude: the centre of [0.1, 0.2] is computed as\n * 0.15000000000000002, and 0.1 + 0.2 - 0.3 is not quite 0. A value that\n * merely rounds to the midpoint when printed keeps its step. Other scale\n * types have no midpoint.\n */\nexport function onMidpoint(\n scale: ResolvedHeatmapScale,\n value: number,\n): boolean {\n if (scale.type !== 'diverging' || scale.midpoint === undefined) return false;\n const magnitude = Math.max(\n Math.abs(scale.midpoint),\n Math.abs(scale.min ?? 0),\n Math.abs(scale.max ?? 0),\n );\n return Math.abs(value - scale.midpoint) <= magnitude * Number.EPSILON * 16;\n}\n\n/**\n * Quantile of a sorted array at `p` (0 to 1), interpolating linearly\n * between neighbours (the R-7 method spreadsheets use).\n */\nexport function quantileSorted(sorted: readonly number[], p: number): number {\n const n = sorted.length;\n if (n === 0) return NaN;\n if (n === 1) return sorted[0];\n const position = clamp(p, 0, 1) * (n - 1);\n const below = Math.floor(position);\n const above = Math.min(n - 1, below + 1);\n return sorted[below] + (sorted[above] - sorted[below]) * (position - below);\n}\n\n/** The `buckets - 1` inner edges that cut sorted values into equal counts. */\nexport function quantileThresholds(\n sorted: readonly number[],\n buckets: number,\n): number[] {\n const count = Math.max(1, Math.round(buckets));\n const edges: number[] = [];\n for (let i = 1; i < count; i += 1) {\n edges.push(quantileSorted(sorted, i / count));\n }\n return edges;\n}\n\n/**\n * Quantile edges that cut something. Each raw edge moves up to the first\n * value at or above it, which puts every value in the same bucket but makes\n * the edge a value the data holds, so no bucket is left empty (an edge\n * between two values could cut a band nothing falls in). Then edges that\n * repeat go: when many values repeat (60% of cells at zero), several raw\n * edges land on the same value, and kept they would put the minimum\n * mid-scale. An edge at the minimum has nothing below it, so it goes too.\n */\nexport function usableQuantileEdges(\n sorted: readonly number[],\n buckets: number,\n): number[] {\n if (sorted.length === 0) return [];\n const min = sorted[0];\n const atOrAbove = (edge: number): number => {\n let low = 0;\n let high = sorted.length - 1;\n while (low < high) {\n const mid = (low + high) >>> 1;\n if (sorted[mid] < edge) low = mid + 1;\n else high = mid;\n }\n return sorted[low];\n };\n return distinctSorted(\n quantileThresholds(sorted, buckets).map(atOrAbove),\n ).filter((edge) => edge > min);\n}\n\n/** How many edges are at or below `value`: its bucket, 0 to edges.length. */\nexport function thresholdBucket(\n value: number,\n thresholds: readonly number[],\n): number {\n let low = 0;\n let high = thresholds.length;\n while (low < high) {\n const mid = (low + high) >>> 1;\n if (thresholds[mid] <= value) low = mid + 1;\n else high = mid;\n }\n return low;\n}\n\n/** Spreads bucket `bucket` of `bucketCount` evenly across the ten steps. */\nexport function bucketStep(bucket: number, bucketCount: number): number {\n if (bucketCount <= 1) return MIDDLE_STEP;\n return Math.round(\n (clamp(bucket, 0, bucketCount - 1) * TOP_STEP) / (bucketCount - 1),\n );\n}\n\n/**\n * Works out a scale against the values that will be shown. Pass only the\n * values of cells that render a colour: empty and low-sample cells must not\n * stretch the domain.\n */\nexport function resolveScale(\n scale: HeatmapScale,\n values: readonly number[],\n): ResolvedHeatmapScale {\n const range = extent(values);\n\n switch (scale.type) {\n case 'diverging': {\n const fixed =\n scale.domain && scale.domain !== 'auto'\n ? orderedDomain(scale.domain)\n : null;\n // Zero is the natural midpoint of a change, but only when the domain\n // reaches it: a fixed domain of [10, 50] would leave the lower hue\n // unused, so its centre divides it instead.\n const midpoint =\n scale.midpoint ??\n (fixed && (fixed[0] > 0 || fixed[1] < 0)\n ? (fixed[0] + fixed[1]) / 2\n : 0);\n let low: number;\n let high: number;\n if (fixed) {\n [low, high] = fixed;\n } else {\n const reach = range\n ? Math.max(\n Math.abs(range[0] - midpoint),\n Math.abs(range[1] - midpoint),\n )\n : 0;\n low = midpoint - reach;\n high = midpoint + reach;\n }\n return {\n type: 'diverging',\n min: low,\n max: high,\n midpoint,\n thresholds: [],\n stepOf: (value) => divergingStep(value, low, midpoint, high),\n };\n }\n case 'quantile': {\n const sorted = values\n .filter(Number.isFinite)\n .slice()\n .sort((a, b) => a - b);\n const buckets = clamp(\n Math.round(scale.buckets ?? HEATMAP_STEPS),\n 2,\n HEATMAP_STEPS,\n );\n // Every value equal leaves no edge: one bucket, on the middle step,\n // as a sequential scale does.\n const thresholds = usableQuantileEdges(sorted, buckets);\n return {\n type: 'quantile',\n min: range?.[0] ?? null,\n max: range?.[1] ?? null,\n thresholds,\n stepOf: (value) =>\n bucketStep(thresholdBucket(value, thresholds), thresholds.length + 1),\n };\n }\n case 'threshold': {\n const given = scale.thresholds.filter(Number.isFinite);\n const distinct = distinctSorted(given);\n if (distinct.length !== given.length) {\n warn('duplicate thresholds merged.');\n }\n if (distinct.length > TOP_STEP) {\n warn(\n `${distinct.length} thresholds given; ten steps take at most ${TOP_STEP}, so the highest ${distinct.length - TOP_STEP} are dropped.`,\n );\n }\n const thresholds = distinct.slice(0, TOP_STEP);\n return {\n type: 'threshold',\n min: range?.[0] ?? null,\n max: range?.[1] ?? null,\n thresholds,\n stepOf: (value) =>\n bucketStep(thresholdBucket(value, thresholds), thresholds.length + 1),\n };\n }\n case 'sequential':\n default: {\n const fixed =\n scale.domain && scale.domain !== 'auto'\n ? orderedDomain(scale.domain)\n : null;\n const low = fixed ? fixed[0] : (range?.[0] ?? null);\n const high = fixed ? fixed[1] : (range?.[1] ?? null);\n return {\n type: 'sequential',\n min: low,\n max: high,\n thresholds: [],\n stepOf: (value) =>\n low === null || high === null\n ? MIDDLE_STEP\n : sequentialStep(value, low, high),\n };\n }\n }\n}\n\n/* -------------------------------------------------------------------- */\n/* Aggregation for row, column and group totals. */\n/* -------------------------------------------------------------------- */\n\n/** How a margin combines its cells. */\nexport type HeatmapAggregate = 'sum' | 'mean';\n\n/** One cell as aggregation sees it. */\nexport interface AggregateInput {\n value: number | null;\n count?: number;\n}\n\n/** A combined value and the count behind it. */\nexport interface AggregateResult {\n value: number | null;\n /** Sum of the counts, when any cell carried one. */\n count?: number;\n}\n\n/** Sum of the values; empty cells are skipped. Null when nothing is left. */\nexport function sumOf(cells: readonly AggregateInput[]): AggregateResult {\n let total = 0;\n let seen = false;\n let count = 0;\n let counted = false;\n for (const cell of cells) {\n if (cell.value === null || !Number.isFinite(cell.value)) continue;\n total += cell.value;\n seen = true;\n if (cell.count !== undefined) {\n count += cell.count;\n counted = true;\n }\n }\n return { value: seen ? total : null, count: counted ? count : undefined };\n}\n\n/**\n * Mean weighted by count: sum(value x count) / sum(count). This is the only\n * correct way to combine rates (26% of 39 and 50% of 2 is 27%, not 38%).\n * A cell without a count weighs 1, so data with no counts at all gets a\n * plain mean. Cells with a count of 0 add nothing.\n */\nexport function weightedMean(\n cells: readonly AggregateInput[],\n): AggregateResult {\n let weighted = 0;\n let weights = 0;\n let count = 0;\n let counted = false;\n for (const cell of cells) {\n if (cell.value === null || !Number.isFinite(cell.value)) continue;\n const weight = cell.count ?? 1;\n weighted += cell.value * weight;\n weights += weight;\n if (cell.count !== undefined) {\n count += cell.count;\n counted = true;\n }\n }\n return {\n value: weights > 0 ? weighted / weights : null,\n count: counted ? count : undefined,\n };\n}\n\n/** Combines cells with the given method. */\nexport function aggregate(\n cells: readonly AggregateInput[],\n method: HeatmapAggregate,\n): AggregateResult {\n return method === 'sum' ? sumOf(cells) : weightedMean(cells);\n}\n","/* -------------------------------------------------------------------- */\n/* Heatmap data model. Pure functions that turn the consumer's rows, */\n/* columns and cells into the matrix the grid, the legend and the table */\n/* view read, plus the grouping, sorting and totals maths. */\n/* -------------------------------------------------------------------- */\n\nimport {\n aggregate,\n type AggregateResult,\n type HeatmapAggregate,\n} from './heatmap-scale';\n\n/** One row of the heatmap. */\nexport interface HeatmapRow {\n /** Stable, opaque id. Emitted in DOM hooks, so never a name. */\n id: string;\n /** Visible label. Masked in privacy mode. */\n label: string;\n /**\n * Group id. Rows that share it are grouped when `groupRows` is on. Without\n * a matching entry in `groups` the id doubles as the visible label, so it\n * may be a name: privacy mode masks it, and DOM hooks and agent state\n * carry an index-based id (`group-1`, `group-2` in order of first\n * appearance), never this one.\n */\n group?: string;\n}\n\n/** One column of the heatmap. */\nexport interface HeatmapColumn {\n /**\n * Stable, opaque id. Emitted in DOM hooks (`data-heatmap-cell-id`) and in\n * agent state, so never a name.\n */\n id: string | number;\n /**\n * Visible label. Masked in privacy mode only with `privacyScope=\"all\"`:\n * columns are usually hours or days, which privacy mode keeps.\n */\n label: string;\n}\n\n/** A group's visible label, keyed by the id rows carry in `group`. */\nexport interface HeatmapGroup {\n /** Stable, opaque id. Emitted in DOM hooks and agent state, so never a name. */\n id: string;\n /**\n * Visible label. Masked in privacy mode only with `privacyScope=\"all\"`:\n * groups are usually practices or sites, which privacy mode keeps.\n */\n label: string;\n}\n\n/**\n * The id each group shows to DOM hooks and agents. A group listed in\n * `groups` keeps its own (opaque) id. One that is not has only its id for a\n * label, which may be a name, so it gets `group-<n>` by order of first\n * appearance instead.\n */\nexport function publicGroupIds(\n rows: readonly HeatmapRow[],\n groups: readonly HeatmapGroup[] | undefined,\n): Map<string, string> {\n const listed = new Set(groups?.map((group) => group.id));\n const taken = new Set(listed);\n const ids = new Map<string, string>();\n let n = 0;\n for (const row of rows) {\n const groupId = row.group;\n if (groupId === undefined || ids.has(groupId)) continue;\n if (listed.has(groupId)) {\n ids.set(groupId, groupId);\n continue;\n }\n let fallback: string;\n do {\n n += 1;\n fallback = `group-${n}`;\n } while (taken.has(fallback));\n taken.add(fallback);\n ids.set(groupId, fallback);\n }\n return ids;\n}\n\n/** The data behind one cell. */\nexport interface HeatmapCellData {\n /** The value to colour. `null` means no data. */\n value: number | null;\n /**\n * How many records the value rests on (the denominator of a rate). Weights\n * the mean totals and drives `minCount`.\n */\n count?: number;\n /**\n * Text shown and announced instead of the formatted value, for example\n * \"Closed\". Replaced by the formatted value in privacy mode.\n */\n label?: string;\n}\n\n/** What `getCell` or the `cells` matrix may hold for a cell. */\nexport type HeatmapCellInput = HeatmapCellData | number | null | undefined;\n\n/** How a cell renders: a coloured value, no data, or too few records. */\nexport type HeatmapCellStatus = 'value' | 'empty' | 'low-sample';\n\n/** Addresses one cell. */\nexport interface HeatmapCellKey {\n rowId: string;\n columnId: string | number;\n}\n\n/** Everything known about one cell, as passed to callbacks. */\nexport interface HeatmapCellInfo extends HeatmapCellKey {\n row: HeatmapRow;\n column: HeatmapColumn;\n /** Index into the `rows` prop. */\n rowIndex: number;\n /** Index into the `columns` prop. */\n columnIndex: number;\n value: number | null;\n count?: number;\n label?: string;\n status: HeatmapCellStatus;\n /**\n * Colour step, 0 to 9, when `status` is `'value'`; otherwise null. On a\n * diverging scale a value exactly on the midpoint keeps step 5 but is\n * painted in the neutral `--heatmap-midpoint` colour: compare `value`\n * with the midpoint to tell it from the palest step above.\n */\n step: number | null;\n}\n\n/** A cell after normalisation. */\nexport interface ModelCell {\n value: number | null;\n count?: number;\n label?: string;\n status: HeatmapCellStatus;\n}\n\n/** How rows are ordered (within their group when grouped). */\nexport type HeatmapSortRows = 'none' | 'label' | 'total-asc' | 'total-desc';\n\n/** Whether a cell or total falls below the sample threshold. */\nexport function isLowSample(\n count: number | undefined,\n minCount: number | undefined,\n): boolean {\n return minCount !== undefined && count !== undefined && count < minCount;\n}\n\n/** Normalises one cell input. */\nexport function toModelCell(\n input: HeatmapCellInput,\n minCount: number | undefined,\n): ModelCell {\n if (input === null || input === undefined) {\n return { value: null, status: 'empty' };\n }\n const data: HeatmapCellData =\n typeof input === 'number' ? { value: input } : input;\n const value =\n data.value === null || !Number.isFinite(data.value) ? null : data.value;\n const status: HeatmapCellStatus =\n value === null\n ? 'empty'\n : isLowSample(data.count, minCount)\n ? 'low-sample'\n : 'value';\n return { value, count: data.count, label: data.label, status };\n}\n\n/** Builds the `[row][column]` matrix in the order of the props. */\nexport function buildMatrix(\n rows: readonly HeatmapRow[],\n columns: readonly HeatmapColumn[],\n getCell:\n | ((\n row: HeatmapRow,\n column: HeatmapColumn,\n rowIndex: number,\n columnIndex: number,\n ) => HeatmapCellInput)\n | undefined,\n cells: readonly (readonly HeatmapCellInput[])[] | undefined,\n minCount: number | undefined,\n): ModelCell[][] {\n return rows.map((row, r) =>\n columns.map((column, c) =>\n toModelCell(\n getCell ? getCell(row, column, r, c) : cells?.[r]?.[c],\n minCount,\n ),\n ),\n );\n}\n\n/** The values that render a colour, for the scale's domain. */\nexport function shownValues(matrix: readonly ModelCell[][]): number[] {\n const values: number[] = [];\n for (const row of matrix) {\n for (const cell of row) {\n if (cell.status === 'value' && cell.value !== null)\n values.push(cell.value);\n }\n }\n return values;\n}\n\n/** Whether at least one cell carries data (a value or a low sample). */\nexport function hasAnyData(matrix: readonly ModelCell[][]): boolean {\n return matrix.some((row) => row.some((cell) => cell.status !== 'empty'));\n}\n\n/* -------------------------------------------------------------------- */\n/* Totals */\n/* -------------------------------------------------------------------- */\n\nexport interface HeatmapTotals {\n /** Per row index (props order), by the row method. */\n rows: AggregateResult[];\n /** Per column index, by the column method. */\n columns: AggregateResult[];\n /** Every cell, by the row method (it sits in the row-totals column). */\n grand: AggregateResult;\n /** Per group id: one result per column, by the group column method. */\n groupColumns: Map<string, AggregateResult[]>;\n /** Per group id: every cell in the group, by the row method (it sits in\n * the row-totals column). */\n groups: Map<string, AggregateResult>;\n}\n\n/**\n * Works out every margin. A total in the row-totals column (a row's, a\n * group's, the grand total) uses the row method, so the column means one\n * thing; a group's per-column totals use the group column method. Low-sample\n * cells count: their data is real, only too thin to show on its own.\n */\nexport function computeTotals(\n matrix: readonly ModelCell[][],\n rows: readonly HeatmapRow[],\n columnCount: number,\n rowMethod: HeatmapAggregate,\n columnMethod: HeatmapAggregate,\n groupColumnMethod: HeatmapAggregate,\n): HeatmapTotals {\n const rowTotals = matrix.map((cells) => aggregate(cells, rowMethod));\n const columnTotals: AggregateResult[] = [];\n for (let c = 0; c < columnCount; c += 1) {\n columnTotals.push(\n aggregate(\n matrix.map((cells) => cells[c]),\n columnMethod,\n ),\n );\n }\n const byGroup = new Map<string, number[]>();\n rows.forEach((row, r) => {\n if (row.group === undefined) return;\n const list = byGroup.get(row.group) ?? [];\n list.push(r);\n byGroup.set(row.group, list);\n });\n const groupColumns = new Map<string, AggregateResult[]>();\n const groups = new Map<string, AggregateResult>();\n for (const [groupId, indexes] of byGroup) {\n const perColumn: AggregateResult[] = [];\n for (let c = 0; c < columnCount; c += 1) {\n perColumn.push(\n aggregate(\n indexes.map((r) => matrix[r][c]),\n groupColumnMethod,\n ),\n );\n }\n groupColumns.set(groupId, perColumn);\n groups.set(\n groupId,\n aggregate(\n indexes.flatMap((r) => matrix[r]),\n rowMethod,\n ),\n );\n }\n return {\n rows: rowTotals,\n columns: columnTotals,\n grand: aggregate(matrix.flat(), rowMethod),\n groupColumns,\n groups,\n };\n}\n\n/* -------------------------------------------------------------------- */\n/* Body rows: grouping, sorting, collapse */\n/* -------------------------------------------------------------------- */\n\n/** A row the grid body renders. */\nexport type BodyRow =\n | {\n kind: 'group';\n /** Navigation key, unique among body rows. */\n key: string;\n groupId: string;\n collapsed: boolean;\n /** Row indexes (props order) in display order. */\n rowIndexes: number[];\n }\n | {\n kind: 'data';\n key: string;\n rowIndex: number;\n groupId?: string;\n };\n\nexport const dataRowKey = (rowId: string): string => `d:${rowId}`;\nexport const groupRowKey = (groupId: string): string => `g:${groupId}`;\nexport const FOOTER_ROW_KEY = 'f';\n\n/** Orders row indexes. Ties keep the props order (a stable sort). */\nexport function sortRowIndexes(\n indexes: readonly number[],\n rows: readonly HeatmapRow[],\n totals: readonly AggregateResult[],\n sort: HeatmapSortRows,\n collator: Intl.Collator,\n): number[] {\n const list = [...indexes];\n if (sort === 'label') {\n return list.sort((a, b) => collator.compare(rows[a].label, rows[b].label));\n }\n if (sort === 'total-asc' || sort === 'total-desc') {\n const direction = sort === 'total-asc' ? 1 : -1;\n return list.sort((a, b) => {\n const left = totals[a]?.value;\n const right = totals[b]?.value;\n // Rows without a total sink to the end in both directions.\n if (left === null || left === undefined) return right == null ? 0 : 1;\n if (right === null || right === undefined) return -1;\n return (left - right) * direction;\n });\n }\n return list;\n}\n\n/** Builds the body: group headers (when grouping) and data rows. */\nexport function buildBodyRows(\n rows: readonly HeatmapRow[],\n sortedIndexes: readonly number[],\n groupRows: boolean,\n collapsed: ReadonlySet<string>,\n): BodyRow[] {\n if (!groupRows) {\n return sortedIndexes.map((r) => ({\n kind: 'data',\n key: dataRowKey(rows[r].id),\n rowIndex: r,\n groupId: rows[r].group,\n }));\n }\n // Groups keep the order in which they first appear in the props, so a sort\n // reorders rows within a group but never moves the groups themselves.\n const order: string[] = [];\n const members = new Map<string, number[]>();\n const loose: number[] = [];\n rows.forEach((row) => {\n if (row.group !== undefined && !members.has(row.group)) {\n members.set(row.group, []);\n order.push(row.group);\n }\n });\n for (const r of sortedIndexes) {\n const groupId = rows[r].group;\n if (groupId === undefined) loose.push(r);\n else members.get(groupId)?.push(r);\n }\n const body: BodyRow[] = [];\n for (const groupId of order) {\n const rowIndexes = members.get(groupId) ?? [];\n const isCollapsed = collapsed.has(groupId);\n body.push({\n kind: 'group',\n key: groupRowKey(groupId),\n groupId,\n collapsed: isCollapsed,\n rowIndexes,\n });\n if (!isCollapsed) {\n for (const r of rowIndexes) {\n body.push({\n kind: 'data',\n key: dataRowKey(rows[r].id),\n rowIndex: r,\n groupId,\n });\n }\n }\n }\n // Rows without a group follow the groups, ungrouped.\n for (const r of loose) {\n body.push({ kind: 'data', key: dataRowKey(rows[r].id), rowIndex: r });\n }\n return body;\n}\n","import type { ReactElement } from 'react';\nimport { Tooltip } from '../tooltip';\nimport { useHeatmapContext } from './heatmap-context';\nimport type { HeatmapCellInfo } from './heatmap-model';\n\nexport interface HeatmapTooltipProps {\n /** The cell the tooltip describes. */\n cell: HeatmapCellInfo;\n /**\n * Tooltip text. Defaults to the Heatmap's `renderTooltip`, or to the\n * sentence every cell is named with (\"Tuesday, 10:00: 26%, 10 of 39\").\n * Plain text only: the kit Tooltip never carries interactive content.\n */\n label?: string;\n /** Controlled open state. */\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Logical side. Default `'top'`. */\n side?: 'top' | 'end' | 'bottom' | 'start';\n /** The trigger. */\n children: ReactElement;\n}\n\n/**\n * Heatmap.Tooltip: the kit Tooltip with a cell's description. The grid uses\n * it for the cell under the pointer or the keyboard focus; a consumer can\n * use it to describe a cell somewhere else, with the same wording and the\n * same privacy masking.\n */\nexport function HeatmapTooltip({\n cell,\n label,\n open,\n onOpenChange,\n side = 'top',\n children,\n}: HeatmapTooltipProps) {\n const context = useHeatmapContext();\n const text = label ?? context?.tooltipText(cell) ?? '';\n return (\n <Tooltip\n label={text}\n open={open}\n onOpenChange={onOpenChange}\n side={side}\n delayDuration={0}\n >\n {children}\n </Tooltip>\n );\n}\n\nHeatmapTooltip.displayName = 'HeatmapTooltip';\n\n/**\n * The anchor the grid hangs a cell's tooltip on: an inert box over the\n * cell, so the cell itself never re-mounts (and never drops focus) when the\n * tooltip moves to it. Takes the text, not a cell, so a group header cell\n * (which has no single row) gets one too.\n */\nexport function HeatmapCellTooltip({\n label,\n onOpenChange,\n}: {\n label: string;\n onOpenChange: (open: boolean) => void;\n}) {\n return (\n <Tooltip label={label} open onOpenChange={onOpenChange} delayDuration={0}>\n <span\n aria-hidden=\"true\"\n data-component=\"heatmap-tooltip\"\n className=\"ds:pointer-events-none ds:absolute ds:inset-0\"\n />\n </Tooltip>\n );\n}\n","/* -------------------------------------------------------------------- */\n/* Heatmap virtualisation. Above VIRTUALISE_CELL_THRESHOLD cells the */\n/* grid renders only the rows and columns in (and just around) the */\n/* viewport, plus the cell that holds the roving focus, so focus is */\n/* never dropped by a scroll. */\n/* */\n/* Every row and column has the same pitch in a virtualised grid, so the */\n/* window is plain arithmetic on the scroll offset; the skipped tracks */\n/* are kept by spacer elements that span them (no pixel offsets, so no */\n/* inline transforms). */\n/* -------------------------------------------------------------------- */\n\n/**\n * Cell count above which the grid virtualises. Measured in Chromium on a\n * production build (heatmap mdx, \"Performance\"): a full render took about\n * 10 ms at 840 cells and 14 ms (p95 18 ms) at 1,200, against the 16 ms\n * budget in src/docs/19-performance.mdx. Above 1,000 cells the window keeps\n * render and hover cost tied to the viewport, not to the data.\n */\nexport const VIRTUALISE_CELL_THRESHOLD = 1000;\n\n/** Rows or columns rendered beyond each edge of the viewport. */\nexport const OVERSCAN = 3;\n\n/** Inputs for one axis. All lengths in CSS pixels. */\nexport interface AxisMetrics {\n /** Scroll offset along the axis (absolute; RTL scrollLeft is negative). */\n offset: number;\n /** Visible length of the scroll container along the axis. */\n viewport: number;\n /** Space before the first item: the sticky header or row header. */\n lead: number;\n /** Item length plus the gap after it. */\n pitch: number;\n /** Number of items on the axis. */\n count: number;\n}\n\n/** Half-open range `[start, end)` of item indexes in view. */\nexport function visibleRange(\n { offset, viewport, lead, pitch, count }: AxisMetrics,\n overscan = OVERSCAN,\n): [number, number] {\n if (count <= 0) return [0, 0];\n if (!(pitch > 0)) return [0, count];\n const from = Math.abs(offset) - lead;\n const first = Math.floor(from / pitch) - overscan;\n const last = Math.ceil((from + viewport) / pitch) + overscan;\n const start = Math.max(0, Math.min(count - 1, first));\n const end = Math.max(start + 1, Math.min(count, last));\n return [start, end];\n}\n\n/** What an axis renders: item indexes and the spans of the gaps. */\nexport interface AxisWindow {\n /** Sorted item indexes to render. */\n indexes: number[];\n /** Items skipped before the first rendered one. */\n lead: number;\n /**\n * Items skipped between the pinned (focused) item and the visible range,\n * when the pinned item lies outside it. Zero otherwise.\n */\n middle: number;\n /** Where the middle gap sits: after this many rendered items. */\n middleAfter: number;\n /** Items skipped after the last rendered one. */\n tail: number;\n}\n\n/** Combines the visible range with the item that must stay rendered. */\nexport function axisWindow(\n range: [number, number],\n count: number,\n pinned: number | null,\n): AxisWindow {\n const [start, end] = range;\n const visible: number[] = [];\n for (let i = start; i < end; i += 1) visible.push(i);\n if (pinned === null || pinned < 0 || pinned >= count) {\n return {\n indexes: visible,\n lead: start,\n middle: 0,\n middleAfter: 0,\n tail: Math.max(0, count - end),\n };\n }\n if (pinned < start) {\n return {\n indexes: [pinned, ...visible],\n lead: pinned,\n middle: start - pinned - 1,\n middleAfter: 1,\n tail: Math.max(0, count - end),\n };\n }\n if (pinned >= end) {\n return {\n indexes: [...visible, pinned],\n lead: start,\n middle: pinned - end,\n middleAfter: visible.length,\n tail: count - pinned - 1,\n };\n }\n return {\n indexes: visible,\n lead: start,\n middle: 0,\n middleAfter: 0,\n tail: Math.max(0, count - end),\n };\n}\n\n/** A window that renders everything (the grid below the threshold). */\nexport function fullWindow(count: number): AxisWindow {\n return {\n indexes: Array.from({ length: count }, (_, i) => i),\n lead: 0,\n middle: 0,\n middleAfter: 0,\n tail: 0,\n };\n}\n\n/**\n * A window with every index at or past `count` dropped: what a window built\n * for more items renders in the one pass before it is worked out again.\n * Returns the same window when nothing is past the end.\n */\nexport function trimWindow(window: AxisWindow, count: number): AxisWindow {\n if (window.indexes.every((index) => index < count)) return window;\n const indexes = window.indexes.filter((index) => index < count);\n return {\n indexes,\n lead: Math.min(window.lead, count),\n middle: 0,\n middleAfter: 0,\n tail: Math.max(0, count - (indexes.length + Math.min(window.lead, count))),\n };\n}\n\n/** Whether two windows render the same items (skips a needless render). */\nexport function sameWindow(a: AxisWindow, b: AxisWindow): boolean {\n if (a.lead !== b.lead || a.tail !== b.tail || a.middle !== b.middle) {\n return false;\n }\n if (a.indexes.length !== b.indexes.length) return false;\n return a.indexes.every((value, i) => value === b.indexes[i]);\n}\n","/* -------------------------------------------------------------------- */\n/* Heatmap class recipes. Every colour is a token; every per-cell */\n/* colour is a CVA variant written out in full so Tailwind generates it. */\n/* -------------------------------------------------------------------- */\n\nimport { cva } from 'class-variance-authority';\n\n/** Palettes, each backed by ten `--heatmap-<palette>-<step>` tokens. */\nexport type HeatmapPalette =\n | 'primary'\n | 'success'\n | 'destructive'\n | 'diverging';\n\n/** One colour step of one palette, the neutral midpoint of a diverging\n * scale, or a cell with no colour of its own. */\nexport type HeatmapTone =\n | `${HeatmapPalette}-${0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}`\n | 'midpoint'\n | 'empty'\n | 'low-sample'\n | 'aggregate';\n\n/** The tone for a palette step. */\nexport const stepTone = (palette: HeatmapPalette, step: number): HeatmapTone =>\n `${palette}-${Math.min(9, Math.max(0, Math.round(step)))}` as HeatmapTone;\n\n/**\n * Background and ink for every tone. Shared by the cells and the legend\n * swatches, and written out in full so Tailwind generates every class.\n */\nconst toneClasses: Record<HeatmapTone, string> = {\n 'primary-0':\n 'ds:bg-[var(--heatmap-primary-0)] ds:text-[color:var(--heatmap-primary-0-foreground)]',\n 'primary-1':\n 'ds:bg-[var(--heatmap-primary-1)] ds:text-[color:var(--heatmap-primary-1-foreground)]',\n 'primary-2':\n 'ds:bg-[var(--heatmap-primary-2)] ds:text-[color:var(--heatmap-primary-2-foreground)]',\n 'primary-3':\n 'ds:bg-[var(--heatmap-primary-3)] ds:text-[color:var(--heatmap-primary-3-foreground)]',\n 'primary-4':\n 'ds:bg-[var(--heatmap-primary-4)] ds:text-[color:var(--heatmap-primary-4-foreground)]',\n 'primary-5':\n 'ds:bg-[var(--heatmap-primary-5)] ds:text-[color:var(--heatmap-primary-5-foreground)]',\n 'primary-6':\n 'ds:bg-[var(--heatmap-primary-6)] ds:text-[color:var(--heatmap-primary-6-foreground)]',\n 'primary-7':\n 'ds:bg-[var(--heatmap-primary-7)] ds:text-[color:var(--heatmap-primary-7-foreground)]',\n 'primary-8':\n 'ds:bg-[var(--heatmap-primary-8)] ds:text-[color:var(--heatmap-primary-8-foreground)]',\n 'primary-9':\n 'ds:bg-[var(--heatmap-primary-9)] ds:text-[color:var(--heatmap-primary-9-foreground)]',\n 'success-0':\n 'ds:bg-[var(--heatmap-success-0)] ds:text-[color:var(--heatmap-success-0-foreground)]',\n 'success-1':\n 'ds:bg-[var(--heatmap-success-1)] ds:text-[color:var(--heatmap-success-1-foreground)]',\n 'success-2':\n 'ds:bg-[var(--heatmap-success-2)] ds:text-[color:var(--heatmap-success-2-foreground)]',\n 'success-3':\n 'ds:bg-[var(--heatmap-success-3)] ds:text-[color:var(--heatmap-success-3-foreground)]',\n 'success-4':\n 'ds:bg-[var(--heatmap-success-4)] ds:text-[color:var(--heatmap-success-4-foreground)]',\n 'success-5':\n 'ds:bg-[var(--heatmap-success-5)] ds:text-[color:var(--heatmap-success-5-foreground)]',\n 'success-6':\n 'ds:bg-[var(--heatmap-success-6)] ds:text-[color:var(--heatmap-success-6-foreground)]',\n 'success-7':\n 'ds:bg-[var(--heatmap-success-7)] ds:text-[color:var(--heatmap-success-7-foreground)]',\n 'success-8':\n 'ds:bg-[var(--heatmap-success-8)] ds:text-[color:var(--heatmap-success-8-foreground)]',\n 'success-9':\n 'ds:bg-[var(--heatmap-success-9)] ds:text-[color:var(--heatmap-success-9-foreground)]',\n 'destructive-0':\n 'ds:bg-[var(--heatmap-destructive-0)] ds:text-[color:var(--heatmap-destructive-0-foreground)]',\n 'destructive-1':\n 'ds:bg-[var(--heatmap-destructive-1)] ds:text-[color:var(--heatmap-destructive-1-foreground)]',\n 'destructive-2':\n 'ds:bg-[var(--heatmap-destructive-2)] ds:text-[color:var(--heatmap-destructive-2-foreground)]',\n 'destructive-3':\n 'ds:bg-[var(--heatmap-destructive-3)] ds:text-[color:var(--heatmap-destructive-3-foreground)]',\n 'destructive-4':\n 'ds:bg-[var(--heatmap-destructive-4)] ds:text-[color:var(--heatmap-destructive-4-foreground)]',\n 'destructive-5':\n 'ds:bg-[var(--heatmap-destructive-5)] ds:text-[color:var(--heatmap-destructive-5-foreground)]',\n 'destructive-6':\n 'ds:bg-[var(--heatmap-destructive-6)] ds:text-[color:var(--heatmap-destructive-6-foreground)]',\n 'destructive-7':\n 'ds:bg-[var(--heatmap-destructive-7)] ds:text-[color:var(--heatmap-destructive-7-foreground)]',\n 'destructive-8':\n 'ds:bg-[var(--heatmap-destructive-8)] ds:text-[color:var(--heatmap-destructive-8-foreground)]',\n 'destructive-9':\n 'ds:bg-[var(--heatmap-destructive-9)] ds:text-[color:var(--heatmap-destructive-9-foreground)]',\n 'diverging-0':\n 'ds:bg-[var(--heatmap-diverging-0)] ds:text-[color:var(--heatmap-diverging-0-foreground)]',\n 'diverging-1':\n 'ds:bg-[var(--heatmap-diverging-1)] ds:text-[color:var(--heatmap-diverging-1-foreground)]',\n 'diverging-2':\n 'ds:bg-[var(--heatmap-diverging-2)] ds:text-[color:var(--heatmap-diverging-2-foreground)]',\n 'diverging-3':\n 'ds:bg-[var(--heatmap-diverging-3)] ds:text-[color:var(--heatmap-diverging-3-foreground)]',\n 'diverging-4':\n 'ds:bg-[var(--heatmap-diverging-4)] ds:text-[color:var(--heatmap-diverging-4-foreground)]',\n 'diverging-5':\n 'ds:bg-[var(--heatmap-diverging-5)] ds:text-[color:var(--heatmap-diverging-5-foreground)]',\n 'diverging-6':\n 'ds:bg-[var(--heatmap-diverging-6)] ds:text-[color:var(--heatmap-diverging-6-foreground)]',\n 'diverging-7':\n 'ds:bg-[var(--heatmap-diverging-7)] ds:text-[color:var(--heatmap-diverging-7-foreground)]',\n 'diverging-8':\n 'ds:bg-[var(--heatmap-diverging-8)] ds:text-[color:var(--heatmap-diverging-8-foreground)]',\n 'diverging-9':\n 'ds:bg-[var(--heatmap-diverging-9)] ds:text-[color:var(--heatmap-diverging-9-foreground)]',\n // A value exactly on a diverging scale's midpoint: neutral, so a cell\n // with no change never looks like one with a small change.\n midpoint:\n 'ds:bg-[var(--heatmap-midpoint)] ds:text-[color:var(--heatmap-midpoint-foreground)]',\n empty:\n 'ds:border ds:border-dashed ds:border-[color:var(--heatmap-empty-border)] ds:bg-[var(--heatmap-empty)] ds:text-[color:var(--heatmap-empty-foreground)]',\n 'low-sample':\n 'ds:border ds:border-[color:var(--heatmap-empty-border)] ds:bg-[var(--heatmap-low-sample-surface)] ds:bg-[image:var(--heatmap-low-sample)] ds:text-[color:var(--heatmap-empty-foreground)]',\n aggregate:\n 'ds:bg-[var(--muted)] ds:text-[color:var(--foreground)] ds:font-semibold',\n};\n\n/** Root: a column of legend bar, grid and live region. Never wider than\n * its container, so the page never scrolls sideways. */\nexport const heatmapRootVariants = cva(\n 'ds:flex ds:min-w-0 ds:max-w-full ds:flex-col ds:gap-[var(--spacing-sm)] ds:text-[color:var(--foreground)]',\n);\n\n/** The bar above the grid: legend at the start, view toggle at the end. */\nexport const heatmapToolbarVariants = cva(\n 'ds:flex ds:flex-wrap ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)]',\n);\n\n/** The scroll box. Only this box scrolls; sticky headers stick to it. */\nexport const heatmapScrollerVariants = cva(\n [\n 'ds:relative ds:max-w-full ds:overflow-auto ds:overscroll-contain',\n 'ds:max-h-[var(--heatmap-max-block-size)]',\n 'ds:bg-[var(--background)]',\n // Keep a cell scrolled into view clear of the sticky header, footer and\n // row-header column. The sizes are measured and set on this element.\n 'ds:scroll-pt-[var(--heatmap-sticky-block-start)] ds:scroll-pb-[var(--heatmap-sticky-block-end)] ds:scroll-ps-[var(--heatmap-sticky-inline-start)]',\n ].join(' '),\n);\n\n/**\n * The table view's box. `fit` lets the DataTable grow with its rows up to\n * the maximum; `capped` holds the maximum and the DataTable fills it,\n * scrolling inside.\n */\nexport const heatmapTableViewVariants = cva(\n // Focusable only to hold focus during a retry; not a control, so no ring.\n 'ds:min-w-0 ds:max-w-full ds:outline-none',\n {\n variants: {\n capped: {\n true: 'ds:flex ds:h-[var(--heatmap-max-block-size)] ds:flex-col',\n false: 'ds:block ds:max-h-[var(--heatmap-max-block-size)]',\n },\n },\n defaultVariants: { capped: false },\n },\n);\n\n/**\n * The grid. Columns come from `--heatmap-columns` (set on the scroll box);\n * rows share the column tracks through subgrid. Size sets the cell box,\n * density the gap, and a virtualised grid pins every track to one size so\n * the window arithmetic holds.\n */\nexport const heatmapGridVariants = cva(\n [\n 'ds:grid ds:w-max ds:min-w-full',\n 'ds:[grid-template-rows:auto] ds:auto-rows-[var(--heatmap-row-track)]',\n 'ds:gap-[var(--heatmap-gap)]',\n 'ds:outline-none',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:[--heatmap-cell-inline:var(--min-target-size)] ds:[--heatmap-cell-block:var(--min-target-size)]',\n md: 'ds:[--heatmap-cell-inline:max(var(--min-target-size),var(--spacing-2xl))] ds:[--heatmap-cell-block:var(--min-target-size)]',\n lg: 'ds:[--heatmap-cell-inline:max(var(--min-target-size),calc(var(--spacing-2xl)_+_var(--spacing-md)))] ds:[--heatmap-cell-block:max(var(--min-target-size),var(--spacing-2xl))]',\n },\n density: {\n default: 'ds:[--heatmap-gap:var(--spacing-2xs)]',\n compact: 'ds:[--heatmap-gap:var(--spacing-none)]',\n },\n virtualised: {\n true: 'ds:[--heatmap-track:var(--heatmap-cell-inline)] ds:[--heatmap-row-track:var(--heatmap-cell-block)]',\n false:\n 'ds:[--heatmap-track:minmax(var(--heatmap-cell-inline),1fr)] ds:[--heatmap-row-track:minmax(var(--heatmap-cell-block),auto)]',\n },\n totalsColumn: {\n true: 'ds:grid-cols-[max-content_repeat(var(--heatmap-columns),var(--heatmap-track))_max-content]',\n false:\n 'ds:grid-cols-[max-content_repeat(var(--heatmap-columns),var(--heatmap-track))]',\n },\n },\n defaultVariants: {\n size: 'md',\n density: 'default',\n virtualised: false,\n totalsColumn: false,\n },\n },\n);\n\n/** A row: spans every column and lines its cells up through subgrid. */\nexport const heatmapRowVariants = cva(\n 'ds:col-span-full ds:grid ds:grid-cols-subgrid',\n {\n variants: {\n position: {\n // The header and footer rows stick to the scroll box's block edges,\n // above the row headers that stick to its inline start.\n // Each also covers the row gap on its inner side, so cells\n // scrolling underneath never show through the gap.\n header:\n \"ds:sticky ds:top-0 ds:z-[calc(var(--z-sticky)+1)] ds:bg-[var(--background)] ds:after:pointer-events-none ds:after:absolute ds:after:inset-x-0 ds:after:top-[calc(100%_-_var(--spacing-2xs))] ds:after:h-[calc(var(--heatmap-gap)_+_var(--spacing-2xs))] ds:after:bg-[var(--background)] ds:after:content-['']\",\n footer:\n \"ds:sticky ds:bottom-0 ds:z-[calc(var(--z-sticky)+1)] ds:bg-[var(--background)] ds:after:pointer-events-none ds:after:absolute ds:after:inset-x-0 ds:after:bottom-[calc(100%_-_var(--spacing-2xs))] ds:after:h-[calc(var(--heatmap-gap)_+_var(--spacing-2xs))] ds:after:bg-[var(--background)] ds:after:content-['']\",\n body: '',\n },\n },\n defaultVariants: { position: 'body' },\n },\n);\n\n/** A spacer standing in for rows or columns the window skipped. */\nexport const heatmapSpacerVariants = cva('ds:pointer-events-none', {\n variants: {\n axis: {\n 'row-lead': 'ds:col-span-full ds:row-span-[var(--heatmap-row-lead)]',\n 'row-middle': 'ds:col-span-full ds:row-span-[var(--heatmap-row-middle)]',\n 'row-tail': 'ds:col-span-full ds:row-span-[var(--heatmap-row-tail)]',\n 'col-lead': 'ds:col-span-[var(--heatmap-col-lead)]',\n 'col-middle': 'ds:col-span-[var(--heatmap-col-middle)]',\n // Holds the skipped columns after the window, so the row-totals cell\n // lands in its own track at the end and never next to the window.\n 'col-tail': 'ds:col-span-[var(--heatmap-col-tail)]',\n },\n },\n});\n\nconst headerHighlight =\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none ds:data-[highlighted=true]:bg-[var(--muted)] ds:data-[highlighted=true]:text-[color:var(--foreground)]';\n\n/** Column header: the hour, day or other column label. */\nexport const heatmapColumnHeaderVariants = cva(\n [\n 'ds:flex ds:min-w-0 ds:items-end ds:justify-center ds:text-center',\n 'ds:rounded-[var(--radius-sm)] ds:px-[var(--spacing-2xs)] ds:py-[var(--spacing-xs)]',\n 'type-meta ds:text-[color:var(--muted-foreground)] ds:break-normal ds:[overflow-wrap:anywhere]',\n headerHighlight,\n ].join(' '),\n {\n variants: {\n corner: {\n // The top-start corner sticks with the row headers below it.\n true: 'ds:sticky ds:start-0 ds:z-[var(--z-sticky)] ds:items-end ds:justify-start ds:text-start ds:bg-[var(--background)] ds:pe-[var(--spacing-sm)]',\n false: '',\n },\n },\n defaultVariants: { corner: false },\n },\n);\n\n/** Row header: the row's label, sticky at the inline start. */\nexport const heatmapRowHeaderVariants = cva(\n [\n 'ds:sticky ds:start-0 ds:z-[var(--z-sticky)] ds:flex ds:min-w-0 ds:items-center',\n 'ds:max-w-[calc(var(--spacing-2xl)*4)] ds:gap-[var(--spacing-xs)]',\n 'ds:bg-[var(--background)] ds:ps-[var(--spacing-xs)] ds:pe-[var(--spacing-sm)]',\n // Cover the gaps at the inline end and below too, so cells scrolling\n // underneath never show through between row headers.\n \"ds:after:pointer-events-none ds:after:absolute ds:after:top-0 ds:after:bottom-[calc(var(--heatmap-gap)*-1)] ds:after:start-full ds:after:w-[var(--heatmap-gap)] ds:after:bg-[var(--background)] ds:after:content-['']\",\n // The strip below overlaps its neighbours slightly so a fractional row\n // position never leaves a hairline seam.\n \"ds:before:pointer-events-none ds:before:absolute ds:before:inset-x-0 ds:before:top-[calc(100%_-_var(--spacing-2xs))] ds:before:h-[calc(var(--heatmap-gap)_+_var(--spacing-2xs)*2)] ds:before:bg-[var(--background)] ds:before:content-['']\",\n 'type-body-sm ds:text-start ds:break-normal ds:[overflow-wrap:anywhere]',\n headerHighlight,\n ].join(' '),\n {\n variants: {\n kind: {\n data: '',\n group: 'ds:font-semibold',\n total: 'ds:font-semibold',\n },\n // A virtualised grid needs every row the same height: no wrapping.\n // The label truncates inside its own span (heatmapRowLabelVariants):\n // overflow on the header itself would clip its gap-covering strips.\n virtualised: {\n true: 'ds:whitespace-nowrap',\n false: '',\n },\n },\n defaultVariants: { kind: 'data', virtualised: false },\n },\n);\n\n/** The label inside a row header. */\nexport const heatmapRowLabelVariants = cva('ds:min-w-0', {\n variants: {\n virtualised: {\n true: 'ds:overflow-hidden ds:text-ellipsis',\n false: '',\n },\n },\n defaultVariants: { virtualised: false },\n});\n\n/**\n * A cell. Colour comes from `tone`; selection, focus and hover come from\n * state attributes so a cell's classes only change when its data does.\n *\n * Focus: an inset ring in `--ring` over an inset band of the page colour,\n * so it reads on every step. Selection: a dark line framed by two light\n * ones, also inset, so it reads on every step too and is a shape, not a\n * colour. On a focused, selected cell the selection lines move inward by\n * `--focus-ring-width`, so the ring (3px in the accessible theme) never\n * covers them. Windows high contrast keeps the cell colours\n * (forced-color-adjust: none) and paints focus in the system Highlight\n * colour.\n */\nexport const heatmapCellVariants = cva(\n [\n 'ds:relative ds:flex ds:min-w-0 ds:items-center ds:justify-center',\n 'ds:min-h-[var(--heatmap-cell-block)] ds:overflow-hidden ds:px-[var(--spacing-2xs)]',\n 'type-meta ds:tabular-nums ds:whitespace-nowrap ds:select-none',\n 'ds:forced-colors:[forced-color-adjust:none]',\n 'ds:focus-visible:outline-solid ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-ring',\n 'ds:focus-visible:outline-offset-[calc(var(--focus-ring-width)*-1)]',\n 'ds:focus-visible:shadow-[inset_0_0_0_calc(var(--focus-ring-width)*2)_var(--background)]',\n 'ds:forced-colors:focus-visible:outline-[Highlight]',\n 'ds:aria-selected:shadow-[inset_0_0_0_var(--spacing-2xs)_var(--background),inset_0_0_0_calc(var(--spacing-2xs)*2)_var(--foreground),inset_0_0_0_calc(var(--spacing-2xs)*3)_var(--background)]',\n 'ds:aria-selected:focus-visible:shadow-[inset_0_0_0_calc(var(--focus-ring-width)_+_var(--spacing-2xs))_var(--background),inset_0_0_0_calc(var(--focus-ring-width)_+_var(--spacing-2xs)*2)_var(--foreground),inset_0_0_0_calc(var(--focus-ring-width)_+_var(--spacing-2xs)*3)_var(--background)]',\n ].join(' '),\n {\n variants: {\n tone: toneClasses,\n interactive: {\n true: 'ds:cursor-pointer',\n false: 'ds:cursor-default',\n },\n },\n defaultVariants: { tone: 'empty', interactive: false },\n },\n);\n\n/** Legend container. */\nexport const heatmapLegendVariants = cva(\n 'ds:flex ds:min-w-0 ds:flex-wrap ds:items-center ds:gap-x-[var(--spacing-md)] ds:gap-y-[var(--spacing-xs)] type-meta ds:text-[color:var(--muted-foreground)]',\n);\n\n/** The bar of colour steps in the legend. It shrinks with its container\n * rather than pushing the page wider. */\nexport const heatmapLegendBarVariants = cva(\n 'ds:flex ds:w-[calc(var(--spacing-xl)*6)] ds:min-w-0 ds:max-w-full ds:shrink ds:items-stretch',\n {\n variants: {\n variant: {\n stepped: 'ds:gap-[var(--spacing-2xs)]',\n continuous: 'ds:overflow-hidden ds:rounded-[var(--radius-sm)]',\n },\n },\n defaultVariants: { variant: 'stepped' },\n },\n);\n\n/** A legend swatch: a step in the bar, the key for an empty or low-sample\n * cell, or the diverging midpoint, which carries its value in its own ink.\n * Same tone classes as the cells. */\nexport const heatmapSwatchVariants = cva(\n 'ds:inline-block ds:forced-colors:[forced-color-adjust:none]',\n {\n variants: {\n tone: toneClasses,\n shape: {\n stepped:\n 'ds:h-[var(--spacing-sm)] ds:min-w-0 ds:flex-1 ds:rounded-[var(--radius-sm)]',\n continuous: 'ds:h-[var(--spacing-sm)] ds:min-w-0 ds:flex-1',\n key: 'ds:size-[var(--spacing-md)] ds:shrink-0 ds:rounded-[var(--radius-sm)]',\n label:\n 'ds:shrink-0 ds:rounded-[var(--radius-sm)] ds:px-[var(--spacing-xs)] ds:whitespace-nowrap',\n },\n },\n defaultVariants: { tone: 'empty', shape: 'key' },\n },\n);\n","import {\n memo,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type KeyboardEvent,\n type PointerEvent,\n type MouseEvent,\n type ReactElement,\n} from 'react';\nimport { ChevronDown } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { useIsomorphicLayoutEffect } from '../../hooks/use-isomorphic-layout-effect';\nimport type { HeatmapDescriber } from './heatmap-format';\nimport {\n FOOTER_ROW_KEY,\n isLowSample,\n type BodyRow,\n type HeatmapCellInfo,\n type HeatmapColumn,\n type HeatmapRow,\n type HeatmapTotals,\n type ModelCell,\n} from './heatmap-model';\nimport {\n onMidpoint,\n type AggregateResult,\n type HeatmapAggregate,\n type ResolvedHeatmapScale,\n} from './heatmap-scale';\nimport { HeatmapCellTooltip } from './heatmap-tooltip';\nimport {\n axisWindow,\n fullWindow,\n sameWindow,\n trimWindow,\n visibleRange,\n type AxisWindow,\n} from './heatmap-window';\nimport {\n heatmapCellVariants,\n heatmapColumnHeaderVariants,\n heatmapGridVariants,\n heatmapRowHeaderVariants,\n heatmapRowLabelVariants,\n heatmapRowVariants,\n heatmapScrollerVariants,\n heatmapSpacerVariants,\n stepTone,\n type HeatmapPalette,\n type HeatmapTone,\n} from './heatmap-variants';\n\n/** How the selection behaves. */\nexport type HeatmapSelectionMode = 'none' | 'single' | 'multiple' | 'range';\n\n/** A position in the navigable matrix: a body or footer row and a column\n * (the last column is the row-totals column when there is one). */\nexport interface GridPosition {\n rowKey: string;\n col: number;\n}\n\nconst KEY_SEPARATOR = '\\u001f';\n\n/** Internal selection key for a data cell: its row id and column id, never\n * its position, so a change to the columns cannot move it. */\nexport const selectionKey = (\n rowId: string,\n columnId: string | number,\n): string => `${rowId}${KEY_SEPARATOR}${String(columnId)}`;\n\n/** The row id and the column id (as a string) a selection key holds. */\nexport const splitSelectionKey = (key: string): [string, string] => {\n const at = key.indexOf(KEY_SEPARATOR);\n return [key.slice(0, at), key.slice(at + 1)];\n};\n\nexport interface HeatmapGridProps {\n title: string;\n rowsLabel?: string;\n rows: readonly HeatmapRow[];\n columns: readonly HeatmapColumn[];\n matrix: readonly ModelCell[][];\n body: readonly BodyRow[];\n scale: ResolvedHeatmapScale;\n palette: HeatmapPalette;\n describer: HeatmapDescriber;\n showValues: boolean;\n totals: HeatmapTotals | null;\n rowTotals: HeatmapAggregate | false;\n columnTotals: HeatmapAggregate | false;\n /** How a group header's per-column totals are worked out. */\n groupColumnMethod: HeatmapAggregate;\n /** Each group's public id: what DOM hooks carry, never a label. */\n groupIds: ReadonlyMap<string, string>;\n minCount?: number;\n selectionMode: HeatmapSelectionMode;\n /** Selection keys (row id + column id) of the selected cells. */\n selected: ReadonlySet<string>;\n /** Column index for the column id a selection key holds. */\n columnIndexOfKey: (columnKey: string) => number | undefined;\n interactive: boolean;\n virtualised: boolean;\n size: 'sm' | 'md' | 'lg';\n density: 'compact' | 'default';\n cellInfo: (rowIndex: number, columnIndex: number) => HeatmapCellInfo;\n /** A data cell's tooltip text. */\n tooltipText: (cell: HeatmapCellInfo) => string;\n /** Describe the focused data cell with its tooltip text (a consumer's\n * renderTooltip says more than the cell's name). */\n describeFocused: boolean;\n /** A data cell was activated by click, Enter or Space. `select` is false\n * for a click that only reports the cell (a range press already chose). */\n onActivate: (rowIndex: number, columnIndex: number, select: boolean) => void;\n /** Range drag or Shift+arrows: select the rectangle anchor to target. */\n onRange: (\n anchor: { rowIndex: number; col: number },\n target: { rowIndex: number; col: number },\n ) => void;\n onToggleGroup: (groupId: string) => void;\n}\n\n/* -------------------------------------------------------------------- */\n/* Per-render context shared by every row (memoised in the grid) */\n/* -------------------------------------------------------------------- */\n\ninterface RowContext {\n rows: readonly HeatmapRow[];\n columns: readonly HeatmapColumn[];\n matrix: readonly ModelCell[][];\n scale: ResolvedHeatmapScale;\n palette: HeatmapPalette;\n describer: HeatmapDescriber;\n showValues: boolean;\n totals: HeatmapTotals | null;\n rowTotals: HeatmapAggregate | false;\n groupColumnMethod: HeatmapAggregate;\n groupIds: ReadonlyMap<string, string>;\n minCount?: number;\n selectable: boolean;\n interactive: boolean;\n virtualised: boolean;\n colWindow: AxisWindow;\n /** Base for the ids that name group row headers. */\n idBase: string;\n /** The id of the focused cell's description, or undefined for none. */\n describedBy: string | undefined;\n cellInfo: (rowIndex: number, columnIndex: number) => HeatmapCellInfo;\n tooltipText: (cell: HeatmapCellInfo) => string;\n onTooltipOpenChange: (open: boolean) => void;\n onToggleGroup: (groupId: string) => void;\n expandLabel: (group: string) => string;\n collapseLabel: (group: string) => string;\n}\n\nfunction toneOf(\n cell: ModelCell,\n scale: ResolvedHeatmapScale,\n palette: HeatmapPalette,\n): HeatmapTone {\n if (cell.status === 'empty' || cell.value === null) return 'empty';\n if (cell.status === 'low-sample') return 'low-sample';\n if (onMidpoint(scale, cell.value)) return 'midpoint';\n return stepTone(palette, scale.stepOf(cell.value));\n}\n\nfunction aggregateCell(\n result: AggregateResult,\n minCount: number | undefined,\n): ModelCell {\n return {\n value: result.value,\n count: result.count,\n status:\n result.value === null\n ? 'empty'\n : isLowSample(result.count, minCount)\n ? 'low-sample'\n : 'value',\n };\n}\n\nconst aggregateTone = (cell: ModelCell): HeatmapTone =>\n cell.status === 'value' ? 'aggregate' : cell.status;\n\n/** Renders the column window: spacers stand in for skipped columns, before,\n * between and after the rendered ones, so whatever follows (the row-totals\n * cell) always sits in its own track at the end. */\nfunction renderColumns(\n window: AxisWindow,\n render: (columnIndex: number) => ReactElement,\n): ReactElement[] {\n const out: ReactElement[] = [];\n if (window.lead > 0) {\n out.push(\n <div\n key=\"lead\"\n aria-hidden=\"true\"\n className={heatmapSpacerVariants({ axis: 'col-lead' })}\n />,\n );\n }\n window.indexes.forEach((columnIndex, i) => {\n if (window.middle > 0 && i === window.middleAfter) {\n out.push(\n <div\n key=\"middle\"\n aria-hidden=\"true\"\n className={heatmapSpacerVariants({ axis: 'col-middle' })}\n />,\n );\n }\n out.push(render(columnIndex));\n });\n if (window.tail > 0) {\n out.push(\n <div\n key=\"tail\"\n aria-hidden=\"true\"\n className={heatmapSpacerVariants({ axis: 'col-tail' })}\n />,\n );\n }\n return out;\n}\n\ninterface BodyRowProps {\n ctx: RowContext;\n row: BodyRow;\n /** 1-based aria-rowindex. */\n ariaRowIndex: number;\n highlighted: boolean;\n /** Column holding the roving tabindex in this row, or -1. */\n activeCol: number;\n /** Column hosting the tooltip in this row, or -1. */\n tooltipCol: number;\n /** Selected column indexes, comma-joined (a string so memo compares by value). */\n selectedCols: string;\n}\n\n/** One body row: a data row or a group header. Memoised, so hover and\n * focus only re-render the rows they touch. */\nconst HeatmapBodyRow = memo(function HeatmapBodyRow({\n ctx,\n row,\n ariaRowIndex,\n highlighted,\n activeCol,\n tooltipCol,\n selectedCols,\n}: BodyRowProps) {\n const columnCount = ctx.columns.length;\n const selected = useMemo(\n () =>\n new Set(selectedCols === '' ? [] : selectedCols.split(',').map(Number)),\n [selectedCols],\n );\n\n if (row.kind === 'group') {\n const groupText = ctx.describer.groupLabel(row.groupId);\n // The public id: the group's own when `groups` lists it, else an\n // index-based one, because an unlisted id doubles as the label.\n const hookId = ctx.groupIds.get(row.groupId);\n const labelId = `${ctx.idBase}-label-${ariaRowIndex}`;\n const perColumn = ctx.totals?.groupColumns.get(row.groupId) ?? [];\n const overall = ctx.totals?.groups.get(row.groupId);\n /** A group's cell. Its value always prints, as a row total's does: the\n * group row is a margin, not a colour scale. */\n const groupCell = (\n result: AggregateResult | undefined,\n c: number,\n label: (cell: ModelCell) => string,\n withTooltip: boolean,\n ) => {\n const cell = aggregateCell(result ?? { value: null }, ctx.minCount);\n const name = label(cell);\n return (\n <div\n key={c}\n role=\"gridcell\"\n aria-colindex={c + 2}\n aria-expanded={!row.collapsed}\n aria-label={name}\n tabIndex={activeCol === c ? 0 : -1}\n data-heatmap-group-id={hookId}\n className={heatmapCellVariants({\n tone: aggregateTone(cell),\n interactive: true,\n })}\n >\n {ctx.describer.visibleText(cell)}\n {withTooltip && tooltipCol === c ? (\n <HeatmapCellTooltip\n label={name}\n onOpenChange={ctx.onTooltipOpenChange}\n />\n ) : null}\n </div>\n );\n };\n const perColumnRowText = ctx.describer.groupRowText(\n groupText,\n ctx.groupColumnMethod,\n );\n return (\n <div\n role=\"row\"\n aria-rowindex={ariaRowIndex}\n data-heatmap-body-row=\"\"\n data-heatmap-group-id={hookId}\n className={heatmapRowVariants({ position: 'body' })}\n >\n <div\n role=\"rowheader\"\n aria-colindex={1}\n // Named by the label alone: the button's own name (\"Collapse …\")\n // would otherwise be read with it, saying the group twice.\n aria-labelledby={labelId}\n data-highlighted={highlighted}\n className={heatmapRowHeaderVariants({\n kind: 'group',\n virtualised: ctx.virtualised,\n })}\n >\n {/*\n * Out of the tab order (tabIndex -1), and it never takes focus on\n * a press: the grid is one tab stop, and every cell of the group\n * row toggles the group with Enter, Space or a click, so the\n * button is a pointer shortcut. Its 24px box meets WCAG 2.5.8\n * (AA). The kit's own 44px target (2.5.5, 48px accessible) is met\n * through the equivalent-control exception: those cells are the\n * same control at full size.\n */}\n <button\n type=\"button\"\n tabIndex={-1}\n aria-expanded={!row.collapsed}\n aria-label={\n row.collapsed\n ? ctx.expandLabel(groupText)\n : ctx.collapseLabel(groupText)\n }\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => ctx.onToggleGroup(row.groupId)}\n className=\"ds:inline-flex ds:size-[var(--spacing-lg)] ds:shrink-0 ds:cursor-pointer ds:items-center ds:justify-center ds:rounded-[var(--radius-sm)] ds:bg-transparent ds:text-[color:inherit] ds:hover:bg-[var(--muted)] ds:focus-visible:outline-solid ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-ring ds:forced-colors:focus-visible:outline-[Highlight]\"\n >\n <ChevronDown\n aria-hidden=\"true\"\n className={[\n 'ds:size-4 ds:transition-transform ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n row.collapsed ? 'ds:-rotate-90 ds:rtl:rotate-90' : '',\n ].join(' ')}\n />\n </button>\n <span\n id={labelId}\n className={heatmapRowLabelVariants({\n virtualised: ctx.virtualised,\n })}\n >\n {groupText}\n </span>\n </div>\n {renderColumns(ctx.colWindow, (c) =>\n groupCell(\n perColumn[c],\n c,\n (cell) =>\n ctx.describer.sentence(\n perColumnRowText,\n ctx.describer.columnLabel(ctx.columns[c]),\n cell,\n ),\n true,\n ),\n )}\n {ctx.rowTotals\n ? groupCell(\n overall,\n columnCount,\n (cell) =>\n ctx.describer.sentence(\n groupText,\n ctx.describer.methodLabel(ctx.rowTotals || 'mean'),\n cell,\n ),\n false,\n )\n : null}\n </div>\n );\n }\n\n const r = row.rowIndex;\n const source = ctx.rows[r];\n const rowText = ctx.describer.rowLabel(source);\n const cells = ctx.matrix[r];\n\n const dataCell = (c: number) => {\n const cell = cells[c];\n const column = ctx.columns[c];\n const isSelected = selected.has(c);\n return (\n <div\n key={c}\n role=\"gridcell\"\n aria-colindex={c + 2}\n aria-label={ctx.describer.sentence(\n rowText,\n ctx.describer.columnLabel(column),\n cell,\n )}\n aria-describedby={activeCol === c ? ctx.describedBy : undefined}\n aria-selected={ctx.selectable ? isSelected : undefined}\n tabIndex={activeCol === c ? 0 : -1}\n data-heatmap-cell-id={`${source.id}:${String(column.id)}`}\n data-status={cell.status}\n className={heatmapCellVariants({\n tone: toneOf(cell, ctx.scale, ctx.palette),\n interactive: ctx.interactive,\n })}\n >\n {ctx.showValues || cell.status === 'empty'\n ? ctx.describer.visibleText(cell)\n : null}\n {tooltipCol === c ? (\n <HeatmapCellTooltip\n label={ctx.tooltipText(ctx.cellInfo(r, c))}\n onOpenChange={ctx.onTooltipOpenChange}\n />\n ) : null}\n </div>\n );\n };\n\n let totalCell: ReactElement | null = null;\n if (ctx.rowTotals && ctx.totals) {\n const cell = aggregateCell(ctx.totals.rows[r], ctx.minCount);\n totalCell = (\n <div\n role=\"gridcell\"\n aria-colindex={columnCount + 2}\n aria-label={ctx.describer.sentence(\n rowText,\n ctx.describer.methodLabel(ctx.rowTotals),\n cell,\n )}\n tabIndex={activeCol === columnCount ? 0 : -1}\n className={heatmapCellVariants({ tone: aggregateTone(cell) })}\n >\n {ctx.describer.visibleText(cell)}\n </div>\n );\n }\n\n return (\n <div\n role=\"row\"\n aria-rowindex={ariaRowIndex}\n data-heatmap-body-row=\"\"\n data-heatmap-row-id={source.id}\n className={heatmapRowVariants({ position: 'body' })}\n >\n <div\n role=\"rowheader\"\n aria-colindex={1}\n data-highlighted={highlighted}\n className={heatmapRowHeaderVariants({\n kind: 'data',\n virtualised: ctx.virtualised,\n })}\n >\n <span\n className={heatmapRowLabelVariants({ virtualised: ctx.virtualised })}\n >\n {rowText}\n </span>\n </div>\n {renderColumns(ctx.colWindow, dataCell)}\n {totalCell}\n </div>\n );\n});\n\n/* -------------------------------------------------------------------- */\n/* Grid */\n/* -------------------------------------------------------------------- */\n\ninterface Metrics {\n headerBlock: number;\n footerBlock: number;\n rowPitch: number;\n leadInline: number;\n colPitch: number;\n viewportBlock: number;\n viewportInline: number;\n}\n\nconst DEFAULT_METRICS: Metrics = {\n headerBlock: 48,\n footerBlock: 0,\n rowPitch: 46,\n leadInline: 120,\n colPitch: 46,\n viewportBlock: 600,\n viewportInline: 900,\n};\n\nconst pageRows = (metrics: Metrics): number =>\n Math.max(\n 1,\n Math.floor(\n (metrics.viewportBlock - metrics.headerBlock - metrics.footerBlock) /\n Math.max(1, metrics.rowPitch),\n ),\n );\n\nexport function HeatmapGrid(props: HeatmapGridProps) {\n const {\n title,\n rowsLabel,\n rows,\n columns,\n matrix,\n body,\n scale,\n palette,\n describer,\n showValues,\n totals,\n rowTotals,\n columnTotals,\n groupColumnMethod,\n groupIds,\n minCount,\n selectionMode,\n selected,\n columnIndexOfKey,\n interactive,\n virtualised,\n size,\n density,\n cellInfo,\n tooltipText,\n describeFocused,\n onActivate,\n onRange,\n onToggleGroup,\n } = props;\n const { t } = useTranslation('ui');\n const idBase = useId();\n const scrollerRef = useRef<HTMLDivElement>(null);\n const gridRef = useRef<HTMLDivElement>(null);\n const headerRef = useRef<HTMLDivElement>(null);\n const footerRef = useRef<HTMLDivElement>(null);\n\n const columnCount = columns.length;\n const navColumnCount = columnCount + (rowTotals ? 1 : 0);\n const hasFooter = Boolean(columnTotals && totals);\n const navRowKeys = useMemo(\n () => [\n ...body.map((row) => row.key),\n ...(hasFooter ? [FOOTER_ROW_KEY] : []),\n ],\n [body, hasFooter],\n );\n const rowIndexOfKey = useMemo(() => {\n const map = new Map<string, number>();\n navRowKeys.forEach((key, i) => map.set(key, i));\n return map;\n }, [navRowKeys]);\n\n /* ---- roving focus -------------------------------------------------- */\n const [active, setActive] = useState<GridPosition>(() => ({\n rowKey: navRowKeys[0] ?? FOOTER_ROW_KEY,\n col: 0,\n }));\n // If the active row disappears (a group collapsed, rows changed), fall\n // back to its group header, else the first row.\n const activeRow = (() => {\n const found = rowIndexOfKey.get(active.rowKey);\n if (found !== undefined) return found;\n const hidden = rows.find((row) => `d:${row.id}` === active.rowKey);\n const header =\n hidden?.group === undefined\n ? undefined\n : rowIndexOfKey.get(`g:${hidden.group}`);\n return header ?? 0;\n })();\n const activeCol = Math.min(\n Math.max(0, active.col),\n Math.max(0, navColumnCount - 1),\n );\n const activeKey = navRowKeys[activeRow];\n\n const pendingFocus = useRef(false);\n const [hasFocus, setHasFocus] = useState(false);\n const hasFocusRef = useRef(false);\n const interaction = useRef<'keyboard' | 'pointer'>('pointer');\n\n /* ---- hover and tooltip --------------------------------------------- */\n const [hover, setHover] = useState<GridPosition | null>(null);\n const hoverRef = useRef<GridPosition | null>(null);\n const [tooltipDismissed, setTooltipDismissed] = useState(false);\n const updateHover = useCallback((next: GridPosition | null) => {\n const current = hoverRef.current;\n if (\n current === next ||\n (current &&\n next &&\n current.rowKey === next.rowKey &&\n current.col === next.col)\n ) {\n return;\n }\n hoverRef.current = next;\n setHover(next);\n setTooltipDismissed(false);\n }, []);\n\n /** The cell whose headers light up: the hovered one, else the focused one. */\n const highlight: GridPosition | null =\n hover ??\n (hasFocus && activeKey ? { rowKey: activeKey, col: activeCol } : null);\n /** The cell that shows the tooltip: hovered, or focused from the keyboard. */\n const tooltipAt: GridPosition | null = tooltipDismissed\n ? null\n : (hover ??\n (hasFocus && interaction.current === 'keyboard' && activeKey\n ? { rowKey: activeKey, col: activeCol }\n : null));\n\n /* ---- measurement and the virtual window ---------------------------- */\n const [metrics, setMetrics] = useState<Metrics>(DEFAULT_METRICS);\n const metricsRef = useRef(metrics);\n metricsRef.current = metrics;\n\n const measure = useCallback(() => {\n const scroller = scrollerRef.current;\n const grid = gridRef.current;\n if (!scroller || !grid) return;\n const style = window.getComputedStyle(grid);\n const rowGap = parseFloat(style.rowGap) || 0;\n const columnGap = parseFloat(style.columnGap) || 0;\n const tracks = style.gridTemplateColumns\n .split(' ')\n .map((track) => parseFloat(track))\n .filter((track) => Number.isFinite(track));\n const headerHeight = headerRef.current?.getBoundingClientRect().height ?? 0;\n const firstBody = grid.querySelector<HTMLElement>(\n '[data-heatmap-body-row]',\n );\n const bodyHeight = firstBody?.getBoundingClientRect().height ?? 0;\n const next: Metrics = {\n headerBlock: headerHeight + rowGap,\n footerBlock: footerRef.current?.getBoundingClientRect().height ?? 0,\n rowPitch:\n (bodyHeight || headerHeight || DEFAULT_METRICS.rowPitch) + rowGap,\n leadInline: (tracks[0] ?? 0) + columnGap,\n colPitch: (tracks[1] ?? DEFAULT_METRICS.colPitch) + columnGap,\n viewportBlock: scroller.clientHeight,\n viewportInline: scroller.clientWidth,\n };\n const current = metricsRef.current;\n if (\n (Object.keys(next) as (keyof Metrics)[]).some(\n (key) => Math.abs(next[key] - current[key]) > 0.5,\n )\n ) {\n setMetrics(next);\n }\n }, []);\n\n useIsomorphicLayoutEffect(() => {\n measure();\n const scroller = scrollerRef.current;\n if (!scroller || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(() => measure());\n observer.observe(scroller);\n if (gridRef.current) observer.observe(gridRef.current);\n return () => observer.disconnect();\n }, [measure, body.length, columnCount, size, density]);\n\n const pinnedRow = activeKey === FOOTER_ROW_KEY ? null : activeRow;\n const pinnedCol = activeCol < columnCount ? activeCol : null;\n\n const computeWindows = useCallback((): {\n rows: AxisWindow;\n cols: AxisWindow;\n } => {\n if (!virtualised) {\n return { rows: fullWindow(body.length), cols: fullWindow(columnCount) };\n }\n const scroller = scrollerRef.current;\n const m = metricsRef.current;\n const rowRange = visibleRange({\n offset: scroller?.scrollTop ?? 0,\n viewport: m.viewportBlock,\n lead: m.headerBlock,\n pitch: m.rowPitch,\n count: body.length,\n });\n const colRange = visibleRange({\n offset: scroller?.scrollLeft ?? 0,\n viewport: m.viewportInline,\n lead: m.leadInline,\n pitch: m.colPitch,\n count: columnCount,\n });\n return {\n rows: axisWindow(rowRange, body.length, pinnedRow),\n cols: axisWindow(colRange, columnCount, pinnedCol),\n };\n }, [virtualised, body.length, columnCount, pinnedRow, pinnedCol]);\n\n const [windowState, setWindows] = useState(computeWindows);\n // Below the threshold every row and column renders, worked out here so a\n // change to the data never meets a window built for the old data. Above\n // it, the window is trimmed to the data until the layout effect below\n // re-syncs it (before paint).\n const fullRows = useMemo(() => fullWindow(body.length), [body.length]);\n const fullCols = useMemo(() => fullWindow(columnCount), [columnCount]);\n const windows = useMemo(\n () =>\n virtualised\n ? {\n rows: trimWindow(windowState.rows, body.length),\n cols: trimWindow(windowState.cols, columnCount),\n }\n : { rows: fullRows, cols: fullCols },\n [virtualised, windowState, body.length, columnCount, fullRows, fullCols],\n );\n const syncWindows = useCallback(() => {\n const next = computeWindows();\n setWindows((current) =>\n sameWindow(current.rows, next.rows) && sameWindow(current.cols, next.cols)\n ? current\n : next,\n );\n }, [computeWindows]);\n useIsomorphicLayoutEffect(() => {\n syncWindows();\n }, [syncWindows, metrics]);\n\n const frame = useRef(0);\n const onScroll = useCallback(() => {\n if (!virtualised || frame.current) return;\n frame.current = window.requestAnimationFrame(() => {\n frame.current = 0;\n syncWindows();\n });\n }, [virtualised, syncWindows]);\n useEffect(() => () => window.cancelAnimationFrame(frame.current), []);\n\n /* ---- focus follows the roving position ----------------------------- */\n // The active row went away (its group collapsed, rows changed): settle the\n // roving position on the row that took its place.\n useIsomorphicLayoutEffect(() => {\n if (activeKey !== undefined && activeKey !== active.rowKey) {\n setActive({ rowKey: activeKey, col: activeCol });\n }\n });\n // If the focused cell itself was removed (an agent collapsed the group\n // holding focus), focus would fall to the page with no blur event: put it\n // back on the active cell, now the group row.\n useIsomorphicLayoutEffect(() => {\n if (!hasFocusRef.current || pendingFocus.current) return;\n const current = document.activeElement;\n if (current && current !== document.body && current.isConnected) return;\n pendingFocus.current = true;\n });\n\n const cellElement = useCallback(\n (rowIndex: number, col: number): HTMLElement | null =>\n gridRef.current?.querySelector<HTMLElement>(\n `[role=\"row\"][aria-rowindex=\"${rowIndex + 2}\"] > [aria-colindex=\"${col + 2}\"]`,\n ) ?? null,\n [],\n );\n\n useIsomorphicLayoutEffect(() => {\n if (!pendingFocus.current) return;\n const element = cellElement(activeRow, activeCol);\n if (!element) return;\n pendingFocus.current = false;\n element.focus({ preventScroll: true });\n element.scrollIntoView?.({ block: 'nearest', inline: 'nearest' });\n });\n\n const isRtl = () =>\n gridRef.current\n ? window.getComputedStyle(gridRef.current).direction === 'rtl'\n : false;\n\n /* ---- range anchor -------------------------------------------------- */\n const anchor = useRef<{ rowIndex: number; col: number } | null>(null);\n const dataRowIndexAt = (navIndex: number): number | null => {\n const row = body[navIndex];\n return row && row.kind === 'data' ? row.rowIndex : null;\n };\n\n /** Set by a range press on the only selected cell: the click that\n * follows (with no drag) clears it, as Enter does. */\n const clearOnClick = useRef(false);\n\n const moveTo = (rowIndex: number, col: number) => {\n const clampedRow = Math.max(0, Math.min(navRowKeys.length - 1, rowIndex));\n const clampedCol = Math.max(0, Math.min(navColumnCount - 1, col));\n pendingFocus.current = true;\n setTooltipDismissed(false);\n setActive({ rowKey: navRowKeys[clampedRow], col: clampedCol });\n return { row: clampedRow, col: clampedCol };\n };\n\n /** Activates the cell at a navigable position (click, Enter, Space). */\n const activate = (navIndex: number, col: number, extend: boolean) => {\n const row = body[navIndex];\n if (!row) return;\n if (row.kind === 'group') {\n onToggleGroup(row.groupId);\n return;\n }\n if (col >= columnCount) return;\n if (selectionMode === 'range' && extend && anchor.current) {\n onRange(anchor.current, { rowIndex: row.rowIndex, col });\n return;\n }\n anchor.current = { rowIndex: row.rowIndex, col };\n onActivate(row.rowIndex, col, true);\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n // A key on the group toggle (if something focused it) keeps its own\n // meaning: Enter on that button toggles the group, never selects the\n // last active cell. Keys on a cell, or on the grid itself (a click on a\n // header focuses it), drive the grid.\n if (event.target instanceof Element && event.target.closest('button')) {\n return;\n }\n interaction.current = 'keyboard';\n const lastRow = navRowKeys.length - 1;\n const lastCol = navColumnCount - 1;\n const forward = isRtl() ? -1 : 1;\n let row = activeRow;\n let col = activeCol;\n const ctrl = event.ctrlKey || event.metaKey;\n switch (event.key) {\n case 'ArrowRight':\n col += forward;\n break;\n case 'ArrowLeft':\n col -= forward;\n break;\n case 'ArrowDown':\n row += 1;\n break;\n case 'ArrowUp':\n row -= 1;\n break;\n case 'Home':\n col = 0;\n if (ctrl) row = 0;\n break;\n case 'End':\n col = lastCol;\n if (ctrl) row = lastRow;\n break;\n case 'PageDown': {\n const nextGroup = body.findIndex(\n (r, i) => i > activeRow && r.kind === 'group',\n );\n const hasGroups = body.some((r) => r.kind === 'group');\n row = hasGroups\n ? nextGroup === -1\n ? lastRow\n : nextGroup\n : activeRow + pageRows(metricsRef.current);\n break;\n }\n case 'PageUp': {\n let previous = -1;\n for (let i = Math.min(activeRow, body.length) - 1; i >= 0; i -= 1) {\n if (body[i].kind === 'group') {\n previous = i;\n break;\n }\n }\n const hasGroups = body.some((r) => r.kind === 'group');\n row = hasGroups\n ? previous === -1\n ? 0\n : previous\n : activeRow - pageRows(metricsRef.current);\n break;\n }\n case 'Enter':\n case ' ':\n event.preventDefault();\n activate(activeRow, activeCol, event.shiftKey);\n return;\n case 'Escape':\n if (tooltipAt) {\n event.preventDefault();\n setTooltipDismissed(true);\n }\n return;\n default:\n return;\n }\n event.preventDefault();\n const moved = moveTo(row, col);\n const isArrow = event.key.startsWith('Arrow');\n if (selectionMode === 'range' && event.shiftKey && isArrow) {\n const target = dataRowIndexAt(moved.row);\n const from =\n anchor.current ??\n (() => {\n const start = dataRowIndexAt(activeRow);\n return start === null || activeCol >= columnCount\n ? null\n : { rowIndex: start, col: activeCol };\n })();\n if (from && target !== null && moved.col < columnCount) {\n anchor.current = from;\n onRange(from, { rowIndex: target, col: moved.col });\n }\n }\n };\n\n /** The navigable position of the cell an event landed on. */\n const positionOf = (\n target: EventTarget | null,\n ): { row: number; col: number } | null => {\n if (!(target instanceof Element)) return null;\n const cell = target.closest<HTMLElement>('[role=\"gridcell\"]');\n const rowElement = cell?.parentElement;\n if (!cell || !rowElement || !gridRef.current?.contains(cell)) return null;\n const rowIndex = Number(rowElement.getAttribute('aria-rowindex')) - 2;\n const col = Number(cell.getAttribute('aria-colindex')) - 2;\n if (!Number.isInteger(rowIndex) || rowIndex < 0 || col < 0) return null;\n return { row: rowIndex, col };\n };\n\n const dragging = useRef(false);\n const lastPointer = useRef<string>('mouse');\n\n const onPointerDown = (event: PointerEvent<HTMLDivElement>) => {\n interaction.current = 'pointer';\n lastPointer.current = event.pointerType;\n if (\n selectionMode !== 'range' ||\n event.pointerType !== 'mouse' ||\n event.button !== 0\n ) {\n return;\n }\n const position = positionOf(event.target);\n clearOnClick.current = false;\n if (!position) return;\n const rowIndex = dataRowIndexAt(position.row);\n if (rowIndex === null || position.col >= columnCount) return;\n if (event.shiftKey && anchor.current) {\n onRange(anchor.current, { rowIndex, col: position.col });\n } else {\n anchor.current = { rowIndex, col: position.col };\n const key = selectionKey(rows[rowIndex].id, columns[position.col].id);\n if (selected.size === 1 && selected.has(key)) {\n // Pressing the only selected cell: a drag still starts a range from\n // it, but a plain click clears it (see onClick), as Enter does.\n clearOnClick.current = true;\n } else {\n onRange(anchor.current, anchor.current);\n }\n }\n dragging.current = true;\n const stop = () => {\n dragging.current = false;\n window.removeEventListener('pointerup', stop);\n window.removeEventListener('pointercancel', stop);\n };\n window.addEventListener('pointerup', stop);\n window.addEventListener('pointercancel', stop);\n };\n\n const onPointerMove = (event: PointerEvent<HTMLDivElement>) => {\n if (event.pointerType !== 'mouse') return;\n const position = positionOf(event.target);\n updateHover(\n position ? { rowKey: navRowKeys[position.row], col: position.col } : null,\n );\n if (dragging.current && position && anchor.current) {\n const rowIndex = dataRowIndexAt(position.row);\n if (rowIndex !== null && position.col < columnCount) {\n if (\n rowIndex !== anchor.current.rowIndex ||\n position.col !== anchor.current.col\n ) {\n clearOnClick.current = false;\n }\n if (!clearOnClick.current) {\n onRange(anchor.current, { rowIndex, col: position.col });\n }\n }\n }\n };\n\n // While the pointer rests on the tooltip, one document listener waits for\n // it to land somewhere else. Kept in a ref so there is never more than one\n // and it goes away with the grid.\n const awayListener = useRef<\n ((event: globalThis.PointerEvent) => void) | null\n >(null);\n const stopAway = useCallback(() => {\n if (!awayListener.current) return;\n document.removeEventListener('pointerover', awayListener.current);\n awayListener.current = null;\n }, []);\n useEffect(() => stopAway, [stopAway]);\n\n const onPointerLeave = (event: PointerEvent<HTMLDivElement>) => {\n // Moving onto the tooltip keeps it open (WCAG 1.4.13, hoverable); it\n // closes once the pointer leaves both.\n stopAway();\n const next = event.relatedTarget;\n if (next instanceof Element && next.closest('[data-component=\"tooltip\"]')) {\n const away = (moved: globalThis.PointerEvent) => {\n const over = moved.target;\n if (\n over instanceof Element &&\n over.closest('[data-component=\"tooltip\"]')\n ) {\n return;\n }\n stopAway();\n if (!(over instanceof Node && gridRef.current?.contains(over))) {\n updateHover(null);\n }\n };\n awayListener.current = away;\n document.addEventListener('pointerover', away);\n return;\n }\n updateHover(null);\n };\n\n const onClick = (event: MouseEvent<HTMLDivElement>) => {\n const button =\n event.target instanceof Element ? event.target.closest('button') : null;\n if (button) {\n // The group toggle has run its own onClick. Grid focus moves to the\n // group row, so the keys carry on from there.\n const navIndex =\n Number(button.closest('[role=\"row\"]')?.getAttribute('aria-rowindex')) -\n 2;\n // Keep the column, so a grid scrolled sideways stays where it is.\n if (Number.isInteger(navIndex) && navIndex >= 0) {\n moveTo(navIndex, activeCol);\n }\n return;\n }\n const position = positionOf(event.target);\n if (!position) return;\n moveTo(position.row, position.col);\n pendingFocus.current = false;\n // Range drags select on pointer down; a click only follows up for touch,\n // except to clear the only selected cell and to toggle a group.\n if (selectionMode === 'range' && lastPointer.current === 'mouse') {\n const row = body[position.row];\n if (row?.kind === 'group') {\n activate(position.row, position.col, false);\n } else if (row?.kind === 'data' && position.col < columnCount) {\n onActivate(row.rowIndex, position.col, clearOnClick.current);\n }\n clearOnClick.current = false;\n return;\n }\n activate(position.row, position.col, event.shiftKey);\n };\n\n /* ---- tooltip and scrolling ------------------------------------------ */\n // Radix closes a tooltip when anything around its trigger scrolls. A key\n // that moves focus scrolls the cell into view, so that close is not the\n // user dismissing it. This listener is added before any tooltip's, so it\n // marks the scroll first and the close below can tell. A hover tooltip\n // still closes on a scroll: the wheel moves the cell from under the\n // pointer without a pointer event.\n const scrolling = useRef(false);\n useEffect(() => {\n let settle = 0;\n const onAnyScroll = () => {\n scrolling.current = true;\n window.cancelAnimationFrame(settle);\n settle = window.requestAnimationFrame(() => {\n scrolling.current = false;\n });\n };\n window.addEventListener('scroll', onAnyScroll, { capture: true });\n return () => {\n window.removeEventListener('scroll', onAnyScroll, { capture: true });\n window.cancelAnimationFrame(settle);\n };\n }, []);\n\n /* ---- row context ---------------------------------------------------- */\n const onTooltipOpenChange = useCallback((open: boolean) => {\n if (open) return;\n // Only the focus tooltip (nothing hovered) outlives a scroll.\n if (scrolling.current && hoverRef.current === null) return;\n setTooltipDismissed(true);\n }, []);\n const expandLabel = useCallback(\n (group: string) => t('heatmap.expandGroup', { group }),\n [t],\n );\n const collapseLabel = useCallback(\n (group: string) => t('heatmap.collapseGroup', { group }),\n [t],\n );\n\n /* ---- the focused cell's description ------------------------------- */\n // A consumer's renderTooltip text reaches screen readers as the focused\n // cell's description; one hidden node, whatever the grid's size.\n const descriptionId = `${idBase}-description`;\n const focusedRow = body[activeRow];\n const description =\n describeFocused && focusedRow?.kind === 'data' && activeCol < columnCount\n ? tooltipText(cellInfo(focusedRow.rowIndex, activeCol))\n : null;\n\n const ctx = useMemo<RowContext>(\n () => ({\n rows,\n columns,\n matrix,\n scale,\n palette,\n describer,\n showValues,\n totals,\n rowTotals,\n groupColumnMethod,\n groupIds,\n minCount,\n selectable: selectionMode !== 'none',\n interactive,\n virtualised,\n colWindow: windows.cols,\n idBase,\n describedBy: describeFocused ? descriptionId : undefined,\n cellInfo,\n tooltipText,\n onTooltipOpenChange,\n onToggleGroup,\n expandLabel,\n collapseLabel,\n }),\n [\n rows,\n columns,\n matrix,\n scale,\n palette,\n describer,\n showValues,\n totals,\n rowTotals,\n groupColumnMethod,\n groupIds,\n minCount,\n selectionMode,\n interactive,\n virtualised,\n windows.cols,\n idBase,\n describeFocused,\n descriptionId,\n cellInfo,\n tooltipText,\n onTooltipOpenChange,\n onToggleGroup,\n expandLabel,\n collapseLabel,\n ],\n );\n\n /** Selected column indexes per data row id, comma-joined. */\n const selectedByRow = useMemo(() => {\n const map = new Map<string, number[]>();\n for (const key of selected) {\n const [rowId, columnKey] = splitSelectionKey(key);\n const col = columnIndexOfKey(columnKey);\n if (col === undefined) continue;\n const list = map.get(rowId) ?? [];\n list.push(col);\n map.set(rowId, list);\n }\n const joined = new Map<string, string>();\n for (const [rowId, list] of map) {\n joined.set(rowId, list.sort((a, b) => a - b).join(','));\n }\n return joined;\n }, [selected, columnIndexOfKey]);\n\n /* ---- header and footer ---------------------------------------------- */\n const highlightCol = highlight?.col ?? -1;\n const header = (\n <div\n ref={headerRef}\n role=\"row\"\n aria-rowindex={1}\n className={heatmapRowVariants({ position: 'header' })}\n >\n <div\n role=\"columnheader\"\n aria-colindex={1}\n className={heatmapColumnHeaderVariants({ corner: true })}\n >\n {rowsLabel ?? (\n <span className=\"ds:sr-only\">{t('heatmap.rowsHeader')}</span>\n )}\n </div>\n {renderColumns(windows.cols, (c) => (\n <div\n key={c}\n role=\"columnheader\"\n aria-colindex={c + 2}\n data-highlighted={highlightCol === c}\n className={heatmapColumnHeaderVariants()}\n >\n {describer.columnLabel(columns[c])}\n </div>\n ))}\n {rowTotals ? (\n <div\n role=\"columnheader\"\n aria-colindex={columnCount + 2}\n data-highlighted={highlightCol === columnCount}\n className={heatmapColumnHeaderVariants()}\n >\n {describer.methodLabel(rowTotals)}\n </div>\n ) : null}\n </div>\n );\n\n let footer: ReactElement | null = null;\n if (columnTotals && totals) {\n const footerIndex = body.length;\n const methodText = describer.methodLabel(columnTotals);\n const footerActive = activeRow === footerIndex;\n const total = (\n result: AggregateResult,\n c: number,\n columnText: string,\n rowText = methodText,\n ) => {\n const cell = aggregateCell(result, minCount);\n return (\n <div\n key={c}\n role=\"gridcell\"\n aria-colindex={c + 2}\n aria-label={describer.sentence(rowText, columnText, cell)}\n tabIndex={footerActive && activeCol === c ? 0 : -1}\n className={heatmapCellVariants({ tone: aggregateTone(cell) })}\n >\n {describer.visibleText(cell)}\n </div>\n );\n };\n footer = (\n <div\n ref={footerRef}\n role=\"row\"\n aria-rowindex={footerIndex + 2}\n className={heatmapRowVariants({ position: 'footer' })}\n >\n <div\n role=\"rowheader\"\n aria-colindex={1}\n data-highlighted={highlight?.rowKey === FOOTER_ROW_KEY}\n className={heatmapRowHeaderVariants({ kind: 'total', virtualised })}\n >\n {methodText}\n </div>\n {renderColumns(windows.cols, (c) =>\n total(totals.columns[c], c, describer.columnLabel(columns[c])),\n )}\n {rowTotals\n ? total(\n totals.grand,\n columnCount,\n describer.methodLabel(rowTotals),\n // The corner aggregates every cell by the row method, so it\n // is named for all cells, not for the footer's own method.\n t('heatmap.allCells'),\n )\n : null}\n </div>\n );\n }\n\n /* ---- body ----------------------------------------------------------- */\n const bodyRows: ReactElement[] = [];\n const rowWindow = windows.rows;\n if (rowWindow.lead > 0) {\n bodyRows.push(\n <div\n key=\"row-lead\"\n aria-hidden=\"true\"\n className={heatmapSpacerVariants({ axis: 'row-lead' })}\n />,\n );\n }\n rowWindow.indexes.forEach((navIndex, i) => {\n if (rowWindow.middle > 0 && i === rowWindow.middleAfter) {\n bodyRows.push(\n <div\n key=\"row-middle\"\n aria-hidden=\"true\"\n className={heatmapSpacerVariants({ axis: 'row-middle' })}\n />,\n );\n }\n const row = body[navIndex];\n if (!row) return;\n const isActiveRow = navIndex === activeRow;\n bodyRows.push(\n <HeatmapBodyRow\n key={row.key}\n ctx={ctx}\n row={row}\n ariaRowIndex={navIndex + 2}\n highlighted={highlight?.rowKey === row.key}\n activeCol={isActiveRow ? activeCol : -1}\n tooltipCol={tooltipAt?.rowKey === row.key ? tooltipAt.col : -1}\n selectedCols={\n row.kind === 'data'\n ? (selectedByRow.get(rows[row.rowIndex].id) ?? '')\n : ''\n }\n />,\n );\n });\n if (rowWindow.tail > 0) {\n bodyRows.push(\n <div\n key=\"row-tail\"\n aria-hidden=\"true\"\n className={heatmapSpacerVariants({ axis: 'row-tail' })}\n />,\n );\n }\n\n // Inline style: permitted per 23-constraints §Runtime-computed dimensions\n // (custom-property setter on the scroll box; the column count comes from\n // the data, the spans from the virtual window and the sticky sizes from\n // measurement. Every rule that reads them lives in CVA).\n const scrollerStyle = {\n '--heatmap-columns': String(Math.max(1, columnCount)),\n '--heatmap-row-lead': String(rowWindow.lead),\n '--heatmap-row-middle': String(rowWindow.middle),\n '--heatmap-row-tail': String(rowWindow.tail),\n '--heatmap-col-lead': String(windows.cols.lead),\n '--heatmap-col-middle': String(windows.cols.middle),\n '--heatmap-col-tail': String(windows.cols.tail),\n '--heatmap-sticky-block-start': `${metrics.headerBlock}px`,\n '--heatmap-sticky-block-end': `${metrics.footerBlock}px`,\n '--heatmap-sticky-inline-start': `${metrics.leadInline}px`,\n } as CSSProperties;\n\n return (\n <div\n ref={scrollerRef}\n onScroll={onScroll}\n // eslint-disable-next-line react/forbid-dom-props -- 23-constraints §Runtime-computed dimensions: custom-property setter only\n style={scrollerStyle}\n data-component=\"heatmap-grid\"\n className={heatmapScrollerVariants()}\n >\n <div\n ref={gridRef}\n role=\"grid\"\n // Focus lives on the cells (roving tabindex); -1 keeps the grid itself\n // out of the tab order while letting it hold focus programmatically.\n tabIndex={-1}\n aria-label={title}\n aria-rowcount={navRowKeys.length + 1}\n aria-colcount={navColumnCount + 1}\n aria-multiselectable={\n selectionMode === 'multiple' || selectionMode === 'range'\n ? true\n : undefined\n }\n data-heatmap-grid=\"\"\n className={heatmapGridVariants({\n size,\n density,\n virtualised,\n totalsColumn: Boolean(rowTotals),\n })}\n onKeyDown={onKeyDown}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerLeave={onPointerLeave}\n onClick={onClick}\n onFocus={(event) => {\n // Tabbing in counts as keyboard use, so the tooltip shows at once.\n if (event.target.matches(':focus-visible')) {\n interaction.current = 'keyboard';\n }\n hasFocusRef.current = true;\n setHasFocus(true);\n }}\n onBlur={(event) => {\n if (\n !event.currentTarget.contains(event.relatedTarget as Node | null)\n ) {\n hasFocusRef.current = false;\n setHasFocus(false);\n }\n }}\n >\n {header}\n {bodyRows}\n {footer}\n </div>\n {description !== null ? (\n <span id={descriptionId} hidden>\n {description}\n </span>\n ) : null}\n </div>\n );\n}\n","import { forwardRef, useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { formatLocale } from '../_shared/intl-locale';\nimport { useHeatmapContext } from './heatmap-context';\nimport { countFormatter, defaultValueFormatter } from './heatmap-format';\nimport {\n HEATMAP_STEPS,\n bucketStep,\n resolveScale,\n type HeatmapScale,\n type ResolvedHeatmapScale,\n} from './heatmap-scale';\nimport {\n heatmapLegendBarVariants,\n heatmapLegendVariants,\n heatmapSwatchVariants,\n stepTone,\n type HeatmapPalette,\n} from './heatmap-variants';\n\nexport interface HeatmapLegendProps {\n /**\n * `stepped` separates the ten steps; `continuous` joins them in a bar.\n * A quantile or threshold scale always shows its bands, one swatch per\n * step it uses, with the cut points between them.\n */\n variant?: 'stepped' | 'continuous';\n /** Palette. Inside a Heatmap it defaults to the Heatmap's. */\n palette?: HeatmapPalette;\n /** Scale. Inside a Heatmap it defaults to the Heatmap's resolved scale. */\n scale?: HeatmapScale;\n /** Values an `auto` or quantile scale is worked out from (outside a Heatmap). */\n values?: readonly number[];\n /** Formats the end labels. Inside a Heatmap it defaults to the Heatmap's. */\n valueFormatter?: (value: number) => string;\n /** Show the key for empty cells. Inside a Heatmap: when any cell is empty. */\n showEmpty?: boolean;\n /** Show the key for low-sample cells. Inside a Heatmap: when any is. */\n showLowSample?: boolean;\n /** The sample threshold, named in the low-sample key. Inside a Heatmap it\n * defaults to the Heatmap's `minCount`. */\n minCount?: number;\n className?: string;\n}\n\nconst STEPS = Array.from({ length: HEATMAP_STEPS }, (_, step) => step);\n\n/** End labels for the bar of a sequential or diverging scale. */\nfunction endLabels(\n scale: ResolvedHeatmapScale,\n format: (value: number) => string,\n): { start: string; end: string; middle?: string } {\n return {\n start: scale.min === null ? '' : format(scale.min),\n end: scale.max === null ? '' : format(scale.max),\n middle:\n scale.type === 'diverging' && scale.midpoint !== undefined\n ? format(scale.midpoint)\n : undefined,\n };\n}\n\n/**\n * Heatmap.Legend: the colour steps with the low and high ends of the scale,\n * plus keys for empty and low-sample cells. A diverging scale shows its\n * midpoint between the two hues as a neutral swatch carrying the midpoint\n * value, the colour of a cell exactly on it. Inside a Heatmap it reads the\n * Heatmap's scale; render it elsewhere with `legend={false}` on the Heatmap\n * and the same `scale`, `palette` and `values` here.\n */\nexport const HeatmapLegend = forwardRef<HTMLDivElement, HeatmapLegendProps>(\n (\n {\n variant = 'stepped',\n palette: paletteProp,\n scale: scaleProp,\n values,\n valueFormatter,\n showEmpty,\n showLowSample,\n minCount: minCountProp,\n className,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation('ui');\n const context = useHeatmapContext();\n const locale = formatLocale(i18n.resolvedLanguage ?? i18n.language);\n\n const scale = useMemo(\n () =>\n scaleProp\n ? resolveScale(scaleProp, values ?? [])\n : (context?.scale ??\n resolveScale({ type: 'sequential' }, values ?? [])),\n [scaleProp, values, context?.scale],\n );\n const palette =\n paletteProp ??\n context?.palette ??\n (scale.type === 'diverging' ? 'diverging' : 'primary');\n const format =\n valueFormatter ??\n context?.describer.formatValue ??\n defaultValueFormatter(locale, 'number');\n\n // A quantile or threshold scale paints only a few steps: one per band.\n // Show those, with each cut point between its two bands, not ten\n // swatches of which most never appear.\n const banded =\n (scale.type === 'quantile' || scale.type === 'threshold') &&\n scale.thresholds.length > 0;\n const bandCount = scale.thresholds.length + 1;\n const bandSteps = banded\n ? Array.from({ length: bandCount }, (_, band) =>\n bucketStep(band, bandCount),\n )\n : [];\n const edges = scale.thresholds.map(format);\n\n const labels = endLabels(scale, format);\n const description = banded\n ? t('heatmap.legend.descriptionBands', {\n count: bandCount,\n formatted: countFormatter(locale)(bandCount),\n edges: new Intl.ListFormat(locale, {\n type: 'conjunction',\n }).format(edges),\n })\n : labels.middle !== undefined\n ? t('heatmap.legend.descriptionDiverging', {\n min: labels.start,\n max: labels.end,\n midpoint: labels.middle,\n })\n : t('heatmap.legend.description', {\n min: labels.start,\n max: labels.end,\n });\n // A banded scale with no cut (every value equal) paints one step.\n const singleStep =\n (scale.type === 'quantile' || scale.type === 'threshold') && !banded\n ? [scale.min === null ? HEATMAP_STEPS / 2 : scale.stepOf(scale.min)]\n : null;\n const withEmpty = showEmpty ?? context?.hasEmpty ?? false;\n const withLowSample = showLowSample ?? context?.hasLowSample ?? false;\n const minCount = minCountProp ?? context?.minCount;\n const shape = variant === 'continuous' ? 'continuous' : 'stepped';\n\n const bar = (steps: readonly number[]) => (\n <span className={heatmapLegendBarVariants({ variant })}>\n {steps.map((step) => (\n <span\n key={step}\n className={heatmapSwatchVariants({\n tone: stepTone(palette, step),\n shape,\n })}\n />\n ))}\n </span>\n );\n\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-label={t('heatmap.legend.label')}\n data-component=\"heatmap-legend\"\n className={heatmapLegendVariants({ className })}\n >\n <span className=\"ds:sr-only\">{description}</span>\n {banded ? (\n <span\n aria-hidden=\"true\"\n data-legend=\"bands\"\n className=\"ds:flex ds:min-w-0 ds:max-w-full ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)] ds:tabular-nums\"\n >\n {bandSteps.map((step, band) => (\n <span\n key={step}\n className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n <span\n data-step={step}\n className={heatmapSwatchVariants({\n tone: stepTone(palette, step),\n shape: 'key',\n })}\n />\n {band < edges.length ? (\n <span className=\"ds:shrink-0\">{edges[band]}</span>\n ) : null}\n </span>\n ))}\n </span>\n ) : (\n <span\n aria-hidden=\"true\"\n className=\"ds:flex ds:min-w-0 ds:max-w-full ds:items-center ds:gap-[var(--spacing-xs)] ds:tabular-nums\"\n >\n <span className=\"ds:shrink-0\">{labels.start}</span>\n {labels.middle !== undefined ? (\n <>\n {bar(STEPS.slice(0, HEATMAP_STEPS / 2))}\n {/* A value exactly on the midpoint is painted neutral, so\n its swatch sits between the hues, carrying the value. */}\n <span\n data-legend=\"midpoint\"\n className={heatmapSwatchVariants({\n tone: 'midpoint',\n shape: 'label',\n })}\n >\n {labels.middle}\n </span>\n {bar(STEPS.slice(HEATMAP_STEPS / 2))}\n </>\n ) : (\n bar(singleStep ?? STEPS)\n )}\n <span className=\"ds:shrink-0\">{labels.end}</span>\n </span>\n )}\n {withEmpty ? (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <span\n aria-hidden=\"true\"\n className={heatmapSwatchVariants({ tone: 'empty' })}\n />\n {t('heatmap.legend.noData')}\n </span>\n ) : null}\n {withLowSample ? (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <span\n aria-hidden=\"true\"\n className={heatmapSwatchVariants({ tone: 'low-sample' })}\n />\n {minCount === undefined\n ? t('heatmap.legend.lowSample')\n : t('heatmap.legend.lowSampleUnder', {\n value: new Intl.NumberFormat(locale).format(minCount),\n })}\n </span>\n ) : null}\n </div>\n );\n },\n);\n\nHeatmapLegend.displayName = 'HeatmapLegend';\n","import {\n lazy,\n Suspense,\n useMemo,\n useRef,\n useState,\n type ComponentType,\n} from 'react';\nimport type { ColDef, GridOptions } from 'ag-grid-community';\nimport { useTranslation } from 'react-i18next';\nimport { useIsomorphicLayoutEffect } from '../../hooks/use-isomorphic-layout-effect';\nimport type { DataTableProps } from '../data-table/data-table';\nimport { ErrorBoundary } from '../error-boundary';\nimport { Skeleton } from '../skeleton';\nimport type { HeatmapDescriber } from './heatmap-format';\nimport type {\n BodyRow,\n HeatmapColumn,\n HeatmapRow,\n HeatmapTotals,\n ModelCell,\n} from './heatmap-model';\nimport { isLowSample } from './heatmap-model';\nimport { heatmapTableViewVariants } from './heatmap-variants';\nimport type { AggregateResult, HeatmapAggregate } from './heatmap-scale';\n\n/** One row of the table view: a data row or a group's totals. */\ninterface HeatmapTableRow {\n id: string;\n group?: string;\n row: string;\n cells: string[];\n total?: string;\n}\n\n/*\n * The DataTable (AG Grid) loads on demand: nothing in the heatmap's own\n * entry imports AG Grid, so a heatmap that never shows its table never\n * downloads it. Every table in the kit is DataTable. The consumer installs\n * ag-grid-community and ag-grid-react (src/docs/25-consuming.mdx).\n */\nconst loadDataTable = () =>\n import('../data-table/data-table').then((module) => ({\n default: module.DataTable as unknown as ComponentType<\n DataTableProps<HeatmapTableRow>\n >,\n }));\nconst LazyDataTable = lazy(loadDataTable);\n\n/** Starts fetching the table chunk ahead of a switch to the table view, so\n * the switch does not wait on the download. Safe to call repeatedly. */\nexport function preloadHeatmapTable(): void {\n loadDataTable().catch(() => {\n /* the switch itself retries and shows the error */\n });\n}\n\nexport interface HeatmapTableViewProps {\n title: string;\n rowsLabel?: string;\n rows: readonly HeatmapRow[];\n columns: readonly HeatmapColumn[];\n matrix: readonly ModelCell[][];\n /** Group headers and rows in display order, every group expanded. */\n body: readonly BodyRow[];\n grouped: boolean;\n /** Each group's public id, for the table's row ids (never a label). */\n groupIds: ReadonlyMap<string, string>;\n describer: HeatmapDescriber;\n totals: HeatmapTotals | null;\n rowTotals: HeatmapAggregate | false;\n columnTotals: HeatmapAggregate | false;\n groupColumnMethod: HeatmapAggregate;\n minCount?: number;\n /** The table failed to load or render (announced by the heatmap). */\n onLoadError?: () => void;\n}\n\nfunction totalCell(\n result: AggregateResult | undefined,\n minCount: number | undefined,\n): ModelCell {\n const value = result?.value ?? null;\n return {\n value,\n count: result?.count,\n status:\n value === null\n ? 'empty'\n : isLowSample(result?.count, minCount)\n ? 'low-sample'\n : 'value',\n };\n}\n\n/**\n * The heatmap's \"View as table\": the same rows, columns, values, counts and\n * totals as a DataTable, so every number is reachable without colour and\n * without a pointer. Group header rows carry their totals, and rows stay in\n * their groups in the grid's order. Labels go through the same privacy\n * masking as the grid.\n */\nexport function HeatmapTableView({\n title,\n rowsLabel,\n rows,\n columns,\n matrix,\n body,\n grouped,\n groupIds,\n describer,\n totals,\n rowTotals,\n columnTotals,\n groupColumnMethod,\n minCount,\n onLoadError,\n}: HeatmapTableViewProps) {\n const { t } = useTranslation('ui');\n\n const columnDefs = useMemo<ColDef<HeatmapTableRow>[]>(\n () => [\n ...(grouped\n ? [\n {\n colId: 'group',\n field: 'group' as const,\n headerName: t('heatmap.table.group'),\n // A sort here would pull rows out of their groups.\n sortable: false,\n },\n ]\n : []),\n {\n colId: 'row',\n field: 'row' as const,\n headerName: rowsLabel ?? t('heatmap.rowsHeader'),\n sortable: !grouped,\n },\n ...columns.map(\n (column, c): ColDef<HeatmapTableRow> => ({\n colId: `c${c}`,\n headerName: describer.columnLabel(column),\n valueGetter: (params) => params.data?.cells[c] ?? '',\n sortable: false,\n }),\n ),\n ...(rowTotals\n ? [\n {\n colId: 'total',\n field: 'total' as const,\n headerName: describer.methodLabel(rowTotals),\n sortable: false,\n },\n ]\n : []),\n ],\n [grouped, rowsLabel, columns, describer, rowTotals, t],\n );\n\n const rowData = useMemo<HeatmapTableRow[]>(\n () =>\n body.map((entry): HeatmapTableRow => {\n if (entry.kind === 'group') {\n const groupText = describer.groupLabel(entry.groupId);\n const perColumn = totals?.groupColumns.get(entry.groupId) ?? [];\n return {\n id: `group:${groupIds.get(entry.groupId) ?? ''}`,\n group: groupText,\n row: describer.groupRowText(groupText, groupColumnMethod),\n cells: columns.map((_, c) =>\n describer.tableText(totalCell(perColumn[c], minCount)),\n ),\n total:\n rowTotals && totals\n ? describer.tableText(\n totalCell(totals.groups.get(entry.groupId), minCount),\n )\n : undefined,\n };\n }\n const r = entry.rowIndex;\n const groupId = rows[r].group;\n return {\n id: `row:${rows[r].id}`,\n group:\n grouped && groupId !== undefined\n ? describer.groupLabel(groupId)\n : undefined,\n row: describer.rowLabel(rows[r]),\n cells: matrix[r].map((cell) => describer.tableText(cell)),\n total:\n rowTotals && totals\n ? describer.tableText(totalCell(totals.rows[r], minCount))\n : undefined,\n };\n }),\n [\n body,\n rows,\n columns,\n matrix,\n grouped,\n groupIds,\n describer,\n rowTotals,\n totals,\n groupColumnMethod,\n minCount,\n ],\n );\n\n const pinnedBottomRowData = useMemo<HeatmapTableRow[] | undefined>(\n () =>\n columnTotals && totals\n ? [\n {\n id: 'heatmap-column-totals',\n row: describer.methodLabel(columnTotals),\n cells: totals.columns.map((result) =>\n describer.tableText(totalCell(result, minCount)),\n ),\n // The grand total, by the row method, as the grid's corner.\n total: rowTotals\n ? describer.tableText(totalCell(totals.grand, minCount))\n : undefined,\n },\n ]\n : undefined,\n [columnTotals, rowTotals, totals, describer, minCount],\n );\n\n /*\n * Height: the table grows with its rows (AG Grid autoHeight) up to\n * --heatmap-max-block-size, so a small grid leaves no empty space. Past\n * that it holds the maximum and scrolls inside, keeping its header in\n * view. AG Grid has no max height for autoHeight, so the wrapper's own\n * max-height detects the overflow and switches the layout. Remembered\n * per row count: new rows fit again from scratch.\n */\n const rowCount = rowData.length + (pinnedBottomRowData?.length ?? 0);\n const rowCountRef = useRef(rowCount);\n rowCountRef.current = rowCount;\n const [cappedAt, setCappedAt] = useState<number | null>(null);\n const capped = cappedAt === rowCount;\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n useIsomorphicLayoutEffect(() => {\n const wrapper = wrapperRef.current;\n if (capped || !wrapper || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(() => {\n if (wrapper.scrollHeight > wrapper.clientHeight + 1) {\n setCappedAt(rowCountRef.current);\n }\n });\n // Watch the content as well as the box: once the box reaches its\n // maximum it stops resizing, but the table inside may still grow.\n const watch = () => {\n observer.observe(wrapper);\n for (const child of Array.from(wrapper.children)) observer.observe(child);\n };\n watch();\n const children = new MutationObserver(watch);\n children.observe(wrapper, { childList: true });\n return () => {\n observer.disconnect();\n children.disconnect();\n };\n }, [capped]);\n\n const gridOptions = useMemo<GridOptions<HeatmapTableRow>>(\n () => ({\n getRowId: (params) => params.data.id,\n domLayout: capped ? 'normal' : 'autoHeight',\n }),\n [capped],\n );\n\n // A failed chunk load stays failed inside one lazy component, so a retry\n // makes a fresh one; the first attempt shares the module-level loader.\n const [attempt, setAttempt] = useState(0);\n const DataTable = useMemo(\n () => (attempt === 0 ? LazyDataTable : lazy(loadDataTable)),\n [attempt],\n );\n\n return (\n <div\n ref={wrapperRef}\n role=\"group\"\n aria-label={title}\n // Holds focus while a retry replaces the error state's button.\n tabIndex={-1}\n data-component=\"heatmap-table\"\n data-layout={capped ? 'capped' : 'fit'}\n className={heatmapTableViewVariants({ capped })}\n >\n <ErrorBoundary\n size=\"sm\"\n onError={() => onLoadError?.()}\n onRetry={() => {\n setAttempt((current) => current + 1);\n wrapperRef.current?.focus();\n }}\n >\n <Suspense\n fallback={\n <div role=\"status\" aria-label={t('heatmap.loadingTable')}>\n <Skeleton\n variant=\"rectangular\"\n className=\"ds:h-[calc(var(--min-target-size)*4)] ds:w-full\"\n />\n </div>\n }\n >\n <DataTable\n columnDefs={columnDefs}\n rowData={rowData}\n pinnedBottomRowData={pinnedBottomRowData}\n density=\"compact\"\n heightClass={capped ? 'ds:min-h-0 ds:flex-1' : ''}\n gridOptions={gridOptions}\n />\n </Suspense>\n </ErrorBoundary>\n </div>\n );\n}\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport { Grid3x3, Table2 } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { useAgentRegistration } from '../../agent';\nimport { formatLocale } from '../_shared/intl-locale';\nimport { Button } from '../button';\nimport { EmptyState } from '../empty-state';\nimport { LiveRegion } from '../live-region';\nimport { Skeleton } from '../skeleton';\nimport { TooltipProvider } from '../tooltip';\nimport { heatmapAgent } from './heatmap.agent';\nimport { HeatmapContext, type HeatmapContextValue } from './heatmap-context';\nimport {\n countFormatter,\n createDescriber,\n defaultValueFormatter,\n type HeatmapPrivacyScope,\n type HeatmapValueType,\n} from './heatmap-format';\nimport {\n HeatmapGrid,\n selectionKey,\n splitSelectionKey,\n type HeatmapSelectionMode,\n} from './heatmap-grid';\nimport { HeatmapLegend } from './heatmap-legend';\nimport {\n buildBodyRows,\n buildMatrix,\n computeTotals,\n hasAnyData,\n publicGroupIds,\n shownValues,\n sortRowIndexes,\n type HeatmapCellInfo,\n type HeatmapCellInput,\n type HeatmapCellKey,\n type HeatmapColumn,\n type HeatmapGroup,\n type HeatmapRow,\n type HeatmapSortRows,\n} from './heatmap-model';\nimport {\n resolveScale,\n type HeatmapAggregate,\n type HeatmapScale,\n} from './heatmap-scale';\nimport { HeatmapTableView, preloadHeatmapTable } from './heatmap-table-view';\nimport { HeatmapTooltip } from './heatmap-tooltip';\nimport {\n heatmapRootVariants,\n heatmapToolbarVariants,\n type HeatmapPalette,\n} from './heatmap-variants';\nimport { VIRTUALISE_CELL_THRESHOLD } from './heatmap-window';\n\nexport type {\n HeatmapCellData,\n HeatmapCellInfo,\n HeatmapCellInput,\n HeatmapCellKey,\n HeatmapCellStatus,\n HeatmapColumn,\n HeatmapGroup,\n HeatmapRow,\n HeatmapSortRows,\n} from './heatmap-model';\nexport type { HeatmapAggregate, HeatmapScale } from './heatmap-scale';\nexport type { HeatmapPalette } from './heatmap-variants';\nexport type { HeatmapPrivacyScope, HeatmapValueType } from './heatmap-format';\nexport type { HeatmapSelectionMode } from './heatmap-grid';\n\n/** What `renderTooltip` is told besides the cell. */\nexport interface HeatmapTooltipContext {\n /**\n * True in privacy mode. The cell's labels are then already masked (and\n * its free-text `label` dropped), so text built from them is safe to show.\n */\n privacyMode: boolean;\n}\n\n/** Which presentation is showing. */\nexport type HeatmapView = 'heatmap' | 'table';\n\n/** What one cell reads back to an agent: structure and numbers, no labels. */\nexport interface HeatmapCellReading {\n value: number | null;\n count?: number;\n status: HeatmapCellInfo['status'];\n /** As `HeatmapCellInfo.step`: a value exactly on a diverging midpoint\n * reads step 5, though it is painted neutral grey. */\n step: number | null;\n}\n\n/**\n * Curated handle for the agent adapter (see heatmap.agent.ts). Ids only,\n * never labels. Group ids are the public ones: a group's own id when it is\n * listed in `groups`, else `group-<n>`. Every write throws on an id the\n * heatmap does not have, before it changes or announces anything.\n */\nexport interface HeatmapHandle {\n getSelection: () => HeatmapCellKey[];\n getSelectionMode: () => HeatmapSelectionMode;\n selectCells: (cells: readonly HeatmapCellKey[]) => void;\n selectRange: (from: HeatmapCellKey, to: HeatmapCellKey) => void;\n clearSelection: () => void;\n readCell: (cell: HeatmapCellKey) => HeatmapCellReading | null;\n getView: () => HeatmapView;\n setView: (view: HeatmapView) => void;\n getSortRows: () => HeatmapSortRows;\n setSortRows: (sort: HeatmapSortRows) => void;\n /** Row ids in display order, every group expanded. */\n getRowIds: () => string[];\n /** Column ids in order. */\n getColumnIds: () => (string | number)[];\n /** Group ids in display order; empty unless `groupRows` is on. */\n getGroupIds: () => string[];\n getCollapsedGroups: () => string[];\n setGroupCollapsed: (groupId: string, collapsed: boolean) => void;\n}\n\n/*\n * Memoisation: `rows`, `columns`, `getCell`, `cells`, `groups` and\n * `valueFormatter` key the cell matrix, the totals and the wording every row\n * renders with. Keep them stable (useMemo, useCallback, or module scope): a\n * new array or an inline function on each parent render rebuilds them all.\n */\nexport interface HeatmapProps {\n /**\n * Required. Names the grid for assistive technology and the table view.\n * Never masked, so it must not name a person.\n */\n title: string;\n /** Rows, top to bottom. Keep the array stable (see Memoisation). */\n rows: readonly HeatmapRow[];\n /** Columns, in reading order. Keep the array stable. */\n columns: readonly HeatmapColumn[];\n /**\n * Returns a cell's data. Use this or `cells`. Keep it stable\n * (`useCallback`): an inline function rebuilds the matrix every render.\n */\n getCell?: (\n row: HeatmapRow,\n column: HeatmapColumn,\n rowIndex: number,\n columnIndex: number,\n ) => HeatmapCellInput;\n /** The cells as a `[row][column]` matrix, in the order of `rows` and `columns`. */\n cells?: readonly (readonly HeatmapCellInput[])[];\n /** Visible labels for the group ids rows carry. Keep the array stable. */\n groups?: readonly HeatmapGroup[];\n /** How values map to colour steps. Default sequential with an auto domain. */\n scale?: HeatmapScale;\n /** Colour palette. Default `diverging` for a diverging scale, else `primary`. */\n palette?: HeatmapPalette;\n /**\n * `rate` for proportions between 0 and 1: formats as a percentage and\n * reads counts as \"10 of 39\". Default `number`.\n */\n valueType?: HeatmapValueType;\n /**\n * Cells with a count below this render as \"too few to show\", hatched.\n * A display rule, not disclosure control: `read_cell`, `onCellClick`,\n * `onSelectionChange` and the totals still carry the value.\n */\n minCount?: number;\n /** Formats a value. Default: Intl in the active locale. Keep it stable. */\n valueFormatter?: (value: number) => string;\n /** Print the value inside each cell. */\n showValues?: boolean;\n /** Built-in legend above the grid, or `false` to place `Heatmap.Legend` yourself. */\n legend?: 'stepped' | 'continuous' | false;\n /**\n * A totals column at the row ends. A mean weights by count. Everything in\n * that column uses this method: each row's total, each group's and the\n * grand total in the corner.\n */\n rowTotals?: HeatmapAggregate | false;\n /**\n * A totals row under the columns. A mean weights by count. A group\n * header's per-column totals use this method too (else `rowTotals`).\n */\n columnTotals?: HeatmapAggregate | false;\n /**\n * Row order (within each group). Controlled when set. In privacy mode\n * `label` keeps the given order: sorting by masked names would reveal\n * their order.\n */\n sortRows?: HeatmapSortRows;\n /** Initial row order when uncontrolled. Default `none`. */\n defaultSortRows?: HeatmapSortRows;\n /** Called when the row order changes (agent `sort_rows`). */\n onSortRowsChange?: (sort: HeatmapSortRows) => void;\n /** Group rows by `row.group`, each group collapsible with its totals. */\n groupRows?: boolean;\n /** Group ids that start collapsed. */\n defaultCollapsedGroups?: readonly string[];\n /** How cells are selected. Default `none`. */\n selection?: HeatmapSelectionMode;\n /** Selected cells. Controlled when set. */\n selectedCells?: readonly HeatmapCellKey[];\n /** Initially selected cells when uncontrolled. */\n defaultSelectedCells?: readonly HeatmapCellKey[];\n /** Called with every cell in the new selection. */\n onSelectionChange?: (cells: HeatmapCellInfo[]) => void;\n /** Called when a cell is clicked, or activated with Enter or Space. */\n onCellClick?: (cell: HeatmapCellInfo) => void;\n /**\n * Tooltip text for a cell. Plain text: the kit Tooltip is text-only. It\n * also describes the focused cell to screen readers (aria-describedby).\n * In privacy mode the cell arrives with its labels masked, its free-text\n * `label` dropped and `row.group` replaced by the public group id, and\n * the context says so.\n */\n renderTooltip?: (\n cell: HeatmapCellInfo,\n context: HeatmapTooltipContext,\n ) => string;\n /** `compact` removes the gap between cells. Cells never shrink below the target size. */\n density?: 'compact' | 'default';\n /** Cell size. Every size keeps cells at least `--min-target-size`. */\n size?: 'sm' | 'md' | 'lg';\n /** Shows a skeleton while data loads. */\n loading?: boolean;\n /**\n * Masks row labels (people, chairs, patients) in the grid, the tooltip,\n * the table view and the announcements, and drops free-text cell labels.\n * Columns and groups stay readable unless `privacyScope=\"all\"`. `title`\n * and `rowsLabel` are never masked.\n */\n privacyMode?: boolean;\n /**\n * What privacy mode masks: `rows` (default) or `all`, which masks column\n * and group labels too.\n */\n privacyScope?: HeatmapPrivacyScope;\n /**\n * Names what the rows are (\"Chair\"): the corner header and the table's\n * first column. Never masked, so it must not name a person.\n */\n rowsLabel?: string;\n /** Initial presentation. Default `heatmap`. */\n defaultView?: HeatmapView;\n /** Called when the view switches between heatmap and table. */\n onViewChange?: (view: HeatmapView) => void;\n /** Instance id: `data-component-id`, and the agent registry key. */\n id?: string;\n className?: string;\n /**\n * Rendered inside the heatmap's context, after the grid (e.g.\n * `Heatmap.Legend`). Also while loading and when empty.\n */\n children?: ReactNode;\n}\n\nconst DEFAULT_SCALE: HeatmapScale = { type: 'sequential', domain: 'auto' };\n\n/** Selection keys for cells, by row id and column id (never by position,\n * so a change to `columns` keeps every selected cell on its own column). */\nconst toKeySet = (cells: readonly HeatmapCellKey[] | undefined): Set<string> =>\n new Set((cells ?? []).map((cell) => selectionKey(cell.rowId, cell.columnId)));\n\n/** What the live region says, and under which privacy setting it was made. */\ninterface Announcement {\n text: string;\n privacyMode: boolean;\n /** Bumped when the same words are said again, so they are heard again. */\n repeat: number;\n}\n\nconst SILENCE: Announcement = { text: '', privacyMode: false, repeat: 0 };\n\nconst HeatmapRoot = forwardRef<HTMLDivElement, HeatmapProps>(\n (\n {\n title,\n rows,\n columns,\n getCell,\n cells,\n groups,\n scale: scaleProp = DEFAULT_SCALE,\n palette: paletteProp,\n valueType = 'number',\n minCount,\n valueFormatter,\n showValues = false,\n legend = 'stepped',\n rowTotals = false,\n columnTotals = false,\n sortRows: sortRowsProp,\n defaultSortRows = 'none',\n onSortRowsChange,\n groupRows = false,\n defaultCollapsedGroups,\n selection = 'none',\n selectedCells,\n defaultSelectedCells,\n onSelectionChange,\n onCellClick,\n renderTooltip,\n density = 'default',\n size = 'md',\n loading = false,\n privacyMode = false,\n privacyScope = 'rows',\n rowsLabel,\n defaultView = 'heatmap',\n onViewChange,\n id,\n className,\n children,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation('ui');\n const locale = formatLocale(i18n.resolvedLanguage ?? i18n.language);\n\n /* ---- data ---------------------------------------------------------- */\n const matrix = useMemo(\n () => buildMatrix(rows, columns, getCell, cells, minCount),\n [rows, columns, getCell, cells, minCount],\n );\n const values = useMemo(() => shownValues(matrix), [matrix]);\n // Consumers often pass the scale inline; key it by content so an equal\n // scale does not re-resolve on every render.\n const scaleKey = JSON.stringify(scaleProp);\n const scale = useMemo(\n () => resolveScale(scaleProp, values),\n // eslint-disable-next-line react-hooks/exhaustive-deps -- keyed by content\n [scaleKey, values],\n );\n const palette: HeatmapPalette =\n paletteProp ?? (scale.type === 'diverging' ? 'diverging' : 'primary');\n\n const formatValue = useMemo(\n () => valueFormatter ?? defaultValueFormatter(locale, valueType),\n [valueFormatter, locale, valueType],\n );\n const formatCount = useMemo(() => countFormatter(locale), [locale]);\n const describer = useMemo(\n () =>\n createDescriber({\n t,\n privacyMode,\n privacyScope,\n valueType,\n formatValue,\n formatCount,\n groups,\n }),\n [\n t,\n privacyMode,\n privacyScope,\n valueType,\n formatValue,\n formatCount,\n groups,\n ],\n );\n const groupIds = useMemo(\n () => publicGroupIds(rows, groups),\n [rows, groups],\n );\n\n // A group header's per-column totals are column margins within the\n // group, so they follow the column method; everything in the row-totals\n // column follows the row method (see computeTotals).\n const groupColumnMethod: HeatmapAggregate =\n columnTotals || rowTotals || 'mean';\n const rowMethod: HeatmapAggregate = rowTotals || 'mean';\n const totals = useMemo(\n () =>\n computeTotals(\n matrix,\n rows,\n columns.length,\n rowMethod,\n columnTotals || 'mean',\n groupColumnMethod,\n ),\n [\n matrix,\n rows,\n columns.length,\n rowMethod,\n columnTotals,\n groupColumnMethod,\n ],\n );\n\n /* ---- announcements ---------------------------------------------------- */\n const [announcement, setAnnouncement] = useState<Announcement>(SILENCE);\n const announceTimer = useRef(0);\n const privacyRef = useRef(privacyMode);\n privacyRef.current = privacyMode;\n const announce = useCallback((message: string, settle = false) => {\n window.clearTimeout(announceTimer.current);\n const madeUnder = privacyRef.current;\n const say = () =>\n setAnnouncement((current) => ({\n text: message,\n privacyMode: madeUnder,\n repeat: current.text === message ? current.repeat + 1 : 0,\n }));\n if (settle) {\n // A drag changes the selection on every cell it crosses; say only\n // where it settles.\n announceTimer.current = window.setTimeout(say, 300);\n } else {\n say();\n }\n }, []);\n useEffect(() => () => window.clearTimeout(announceTimer.current), []);\n // A message made before privacy mode turned on may name a row. Drop it\n // (and any still waiting) when the mode changes; until that lands, the\n // render below already refuses to show it.\n useEffect(() => {\n window.clearTimeout(announceTimer.current);\n setAnnouncement((current) => (current.text === '' ? current : SILENCE));\n }, [privacyMode]);\n const spoken =\n announcement.privacyMode === privacyMode\n ? // The same words twice leave the DOM unchanged and a screen reader\n // silent: a trailing no-break space on every other repeat changes\n // the text without changing what is read.\n `${announcement.text}${announcement.repeat % 2 === 1 ? '\\u00a0' : ''}`\n : '';\n\n /* ---- view, sort and groups ------------------------------------------ */\n const [view, setViewState] = useState<HeatmapView>(defaultView);\n\n const setView = useCallback(\n (next: HeatmapView) => {\n setViewState(next);\n onViewChange?.(next);\n announce(\n next === 'table'\n ? t('heatmap.announce.tableView')\n : t('heatmap.announce.heatmapView'),\n );\n },\n [onViewChange, announce, t],\n );\n\n const [sortInternal, setSortInternal] =\n useState<HeatmapSortRows>(defaultSortRows);\n const sortRows = sortRowsProp ?? sortInternal;\n const setSortRows = useCallback(\n (next: HeatmapSortRows) => {\n if (sortRowsProp === undefined) setSortInternal(next);\n onSortRowsChange?.(next);\n },\n [sortRowsProp, onSortRowsChange],\n );\n\n const [collapsed, setCollapsed] = useState<ReadonlySet<string>>(\n () => new Set(defaultCollapsedGroups ?? []),\n );\n const setGroupCollapsed = useCallback(\n (groupId: string, isCollapsed: boolean) => {\n // Already so: nothing changes, so nothing is said.\n if (collapsed.has(groupId) === isCollapsed) return;\n setCollapsed((current) => {\n if (current.has(groupId) === isCollapsed) return current;\n const next = new Set(current);\n if (isCollapsed) next.add(groupId);\n else next.delete(groupId);\n return next;\n });\n const label = describer.groupLabel(groupId);\n announce(\n isCollapsed\n ? t('heatmap.announce.groupCollapsed', { group: label })\n : t('heatmap.announce.groupExpanded', { group: label }),\n );\n },\n [collapsed, announce, describer, t],\n );\n const toggleGroup = useCallback(\n (groupId: string) => setGroupCollapsed(groupId, !collapsed.has(groupId)),\n [collapsed, setGroupCollapsed],\n );\n\n const collator = useMemo(\n () => new Intl.Collator(locale, { numeric: true, sensitivity: 'base' }),\n [locale],\n );\n // A label sort under masked labels would still order the rows by the\n // hidden names, and so reveal their order: in privacy mode it keeps the\n // given order.\n const appliedSort: HeatmapSortRows =\n sortRows === 'label' && describer.masksRows ? 'none' : sortRows;\n const order = useMemo(\n () =>\n sortRowIndexes(\n rows.map((_, r) => r),\n rows,\n totals.rows,\n appliedSort,\n collator,\n ),\n [rows, totals.rows, appliedSort, collator],\n );\n const body = useMemo(\n () => buildBodyRows(rows, order, groupRows, collapsed),\n [rows, order, groupRows, collapsed],\n );\n /** Every row in display order with every group expanded: the table\n * view's order, and the row ids an agent reads. */\n const expandedBody = useMemo(\n () => buildBodyRows(rows, order, groupRows, new Set()),\n [rows, order, groupRows],\n );\n\n /* ---- cells ---------------------------------------------------------- */\n const rowIndexById = useMemo(\n () => new Map(rows.map((row, r) => [row.id, r])),\n [rows],\n );\n const columnIndexById = useMemo(\n () => new Map(columns.map((column, c) => [String(column.id), c])),\n [columns],\n );\n const columnIndexOfKey = useCallback(\n (columnKey: string) => columnIndexById.get(columnKey),\n [columnIndexById],\n );\n const cellInfo = useCallback(\n (rowIndex: number, columnIndex: number): HeatmapCellInfo => {\n const row = rows[rowIndex];\n const column = columns[columnIndex];\n const cell = matrix[rowIndex][columnIndex];\n return {\n rowId: row.id,\n columnId: column.id,\n row,\n column,\n rowIndex,\n columnIndex,\n value: cell.value,\n count: cell.count,\n label: cell.label,\n status: cell.status,\n step:\n cell.status === 'value' && cell.value !== null\n ? scale.stepOf(cell.value)\n : null,\n };\n },\n [rows, columns, matrix, scale],\n );\n /** The cell as `renderTooltip` may see it in privacy mode: masked\n * labels, no free text, no group id that could be a name. */\n const maskedInfo = useCallback(\n (info: HeatmapCellInfo): HeatmapCellInfo => {\n const group =\n info.row.group === undefined\n ? undefined\n : groupIds.get(info.row.group);\n return {\n rowId: info.rowId,\n columnId: info.columnId,\n row: {\n id: info.row.id,\n label: describer.rowLabel(info.row),\n ...(group === undefined ? {} : { group }),\n },\n column: {\n id: info.column.id,\n label: describer.columnLabel(info.column),\n },\n rowIndex: info.rowIndex,\n columnIndex: info.columnIndex,\n value: info.value,\n count: info.count,\n status: info.status,\n step: info.step,\n };\n },\n [describer, groupIds],\n );\n const tooltipText = useCallback(\n (info: HeatmapCellInfo) =>\n renderTooltip\n ? renderTooltip(privacyMode ? maskedInfo(info) : info, {\n privacyMode,\n })\n : describer.sentence(\n describer.rowLabel(info.row),\n describer.columnLabel(info.column),\n matrix[info.rowIndex][info.columnIndex],\n ),\n [renderTooltip, privacyMode, maskedInfo, describer, matrix],\n );\n\n /* ---- selection ------------------------------------------------------- */\n const isControlled = selectedCells !== undefined;\n const [selectedInternal, setSelectedInternal] = useState<Set<string>>(() =>\n toKeySet(defaultSelectedCells),\n );\n // Keys are row id + column id. Only those naming a current row and\n // column count, so a removed column drops out of the selection instead\n // of pointing at whatever now sits in its place.\n const selected = useMemo(() => {\n const source = isControlled ? toKeySet(selectedCells) : selectedInternal;\n const present = new Set<string>();\n for (const key of source) {\n const [rowId, columnKey] = splitSelectionKey(key);\n if (rowIndexById.has(rowId) && columnIndexById.has(columnKey)) {\n present.add(key);\n }\n }\n return present;\n }, [\n isControlled,\n selectedCells,\n selectedInternal,\n rowIndexById,\n columnIndexById,\n ]);\n\n const infosOf = useCallback(\n (keys: ReadonlySet<string>): HeatmapCellInfo[] => {\n const infos: HeatmapCellInfo[] = [];\n for (const key of keys) {\n const [rowId, columnKey] = splitSelectionKey(key);\n const r = rowIndexById.get(rowId);\n const c = columnIndexById.get(columnKey);\n if (r !== undefined && c !== undefined) infos.push(cellInfo(r, c));\n }\n return infos;\n },\n [rowIndexById, columnIndexById, cellInfo],\n );\n const cellName = useCallback(\n (rowIndex: number, columnIndex: number) =>\n describer.cellName(\n describer.rowLabel(rows[rowIndex]),\n describer.columnLabel(columns[columnIndex]),\n ),\n [describer, rows, columns],\n );\n const commitSelection = useCallback(\n (next: Set<string>, message: string, settle = false) => {\n if (!isControlled) setSelectedInternal(next);\n onSelectionChange?.(infosOf(next));\n announce(message, settle);\n },\n [isControlled, onSelectionChange, infosOf, announce],\n );\n const countMessage = useCallback(\n (count: number) =>\n count === 0\n ? t('heatmap.announce.cleared')\n : t('heatmap.announce.count', {\n count,\n formatted: formatCount(count),\n }),\n [t, formatCount],\n );\n\n /** The visible data rows in display order, for range rectangles. */\n const dataOrder = useMemo(\n () => body.flatMap((row) => (row.kind === 'data' ? [row.rowIndex] : [])),\n [body],\n );\n const rectangle = useCallback(\n (\n from: { rowIndex: number; col: number },\n to: { rowIndex: number; col: number },\n ) => {\n const a = dataOrder.indexOf(from.rowIndex);\n const b = dataOrder.indexOf(to.rowIndex);\n const next = new Set<string>();\n if (a === -1 || b === -1) return next;\n const [top, bottom] = a <= b ? [a, b] : [b, a];\n const [left, right] =\n from.col <= to.col ? [from.col, to.col] : [to.col, from.col];\n for (let i = top; i <= bottom; i += 1) {\n const rowId = rows[dataOrder[i]].id;\n for (let c = left; c <= right; c += 1) {\n next.add(selectionKey(rowId, columns[c].id));\n }\n }\n return next;\n },\n [dataOrder, rows, columns],\n );\n\n const onActivate = useCallback(\n (rowIndex: number, columnIndex: number, select: boolean) => {\n onCellClick?.(cellInfo(rowIndex, columnIndex));\n if (!select || selection === 'none') return;\n const key = selectionKey(rows[rowIndex].id, columns[columnIndex].id);\n const name = cellName(rowIndex, columnIndex);\n if (selection === 'multiple') {\n const next = new Set(selected);\n const adding = !next.has(key);\n if (adding) next.add(key);\n else next.delete(key);\n commitSelection(\n next,\n t(adding ? 'heatmap.announce.added' : 'heatmap.announce.removed', {\n cell: name,\n count: next.size,\n formatted: formatCount(next.size),\n }),\n );\n return;\n }\n // Single and range: the cell becomes the whole selection (a range's\n // anchor); selecting the only selected cell again clears it.\n const clearing = selected.size === 1 && selected.has(key);\n commitSelection(\n clearing ? new Set() : new Set([key]),\n clearing\n ? t('heatmap.announce.cleared')\n : t('heatmap.announce.selected', { cell: name }),\n );\n },\n [\n onCellClick,\n cellInfo,\n selection,\n rows,\n columns,\n cellName,\n selected,\n commitSelection,\n formatCount,\n t,\n ],\n );\n\n const onRange = useCallback(\n (\n from: { rowIndex: number; col: number },\n to: { rowIndex: number; col: number },\n ) => {\n if (selection !== 'range' && selection !== 'multiple') return;\n const next = rectangle(from, to);\n if (\n next.size === selected.size &&\n [...next].every((key) => selected.has(key))\n ) {\n return;\n }\n commitSelection(next, countMessage(next.size), true);\n },\n [selection, rectangle, selected, commitSelection, countMessage],\n );\n\n /* ---- agent handle ------------------------------------------------------ */\n const groupByPublicId = useMemo(\n () => new Map([...groupIds].map(([own, shown]) => [shown, own])),\n [groupIds],\n );\n const agentState = {\n selected,\n selection,\n view,\n sortRows,\n collapsed,\n groupRows,\n rows,\n columns,\n expandedBody,\n groupIds,\n groupByPublicId,\n rowIndexById,\n columnIndexById,\n matrix,\n scale,\n setView,\n setSortRows,\n setGroupCollapsed,\n commitSelection,\n rectangle,\n countMessage,\n };\n const latest = useRef(agentState);\n latest.current = agentState;\n const agentHandle = useMemo<HeatmapHandle>(() => {\n const keysOf = (set: ReadonlySet<string>): HeatmapCellKey[] => {\n const { columns: cols, columnIndexById: byColumn } = latest.current;\n const keys: HeatmapCellKey[] = [];\n for (const key of set) {\n const [rowId, columnKey] = splitSelectionKey(key);\n const c = byColumn.get(columnKey);\n // The column's own id, number or string, as the consumer gave it.\n if (c !== undefined) keys.push({ rowId, columnId: cols[c].id });\n }\n return keys;\n };\n const position = (cell: HeatmapCellKey) => {\n const { rowIndexById: byRow, columnIndexById: byColumn } =\n latest.current;\n const rowIndex = byRow.get(cell.rowId);\n const col = byColumn.get(String(cell.columnId));\n return rowIndex === undefined || col === undefined\n ? null\n : { rowIndex, col };\n };\n /** Throws on an unknown cell, before anything changes or is said. */\n const requireCell = (cell: HeatmapCellKey) => {\n const at = position(cell);\n if (!at) {\n throw new Error(\n `Heatmap: no cell at row \"${cell.rowId}\", column \"${String(cell.columnId)}\".`,\n );\n }\n return at;\n };\n const requireSelection = () => {\n if (latest.current.selection === 'none') {\n throw new Error('Heatmap: selection is off (selection=\"none\").');\n }\n };\n return {\n getSelection: () => keysOf(latest.current.selected),\n getSelectionMode: () => latest.current.selection,\n selectCells: (cellsToSelect) => {\n requireSelection();\n cellsToSelect.forEach(requireCell);\n const { selection: mode } = latest.current;\n const picked =\n mode === 'single' ? cellsToSelect.slice(0, 1) : cellsToSelect;\n const next = toKeySet(picked);\n latest.current.commitSelection(\n next,\n latest.current.countMessage(next.size),\n );\n },\n selectRange: (from, to) => {\n const { selection: mode } = latest.current;\n if (mode !== 'range' && mode !== 'multiple') {\n throw new Error(\n 'Heatmap: select_range needs selection=\"range\" or \"multiple\".',\n );\n }\n const a = requireCell(from);\n const b = requireCell(to);\n const next = latest.current.rectangle(a, b);\n latest.current.commitSelection(\n next,\n latest.current.countMessage(next.size),\n );\n },\n clearSelection: () => {\n requireSelection();\n if (latest.current.selected.size === 0) return;\n latest.current.commitSelection(\n new Set(),\n latest.current.countMessage(0),\n );\n },\n readCell: (cell) => {\n const at = position(cell);\n if (!at) return null;\n const model = latest.current.matrix[at.rowIndex][at.col];\n return {\n value: model.value,\n count: model.count,\n status: model.status,\n step:\n model.status === 'value' && model.value !== null\n ? latest.current.scale.stepOf(model.value)\n : null,\n };\n },\n getView: () => latest.current.view,\n setView: (next) => latest.current.setView(next),\n getSortRows: () => latest.current.sortRows,\n setSortRows: (next) => latest.current.setSortRows(next),\n getRowIds: () => {\n const { expandedBody: shown, rows: all } = latest.current;\n return shown.flatMap((row) =>\n row.kind === 'data' ? [all[row.rowIndex].id] : [],\n );\n },\n getColumnIds: () => latest.current.columns.map((column) => column.id),\n getGroupIds: () => {\n const {\n groupRows: grouped,\n expandedBody: shown,\n groupIds: ids,\n } = latest.current;\n if (!grouped) return [];\n return shown.flatMap((row) =>\n row.kind === 'group' ? [ids.get(row.groupId) ?? ''] : [],\n );\n },\n getCollapsedGroups: () => {\n const { collapsed: hidden, groupIds: ids } = latest.current;\n return [...hidden].flatMap((own) => {\n const shown = ids.get(own);\n return shown === undefined ? [] : [shown];\n });\n },\n setGroupCollapsed: (groupId, isCollapsed) => {\n const { groupRows: grouped, groupByPublicId: byShown } =\n latest.current;\n if (!grouped) {\n throw new Error(\n 'Heatmap: rows are not grouped (groupRows is off).',\n );\n }\n const own = byShown.get(groupId);\n if (own === undefined) {\n throw new Error(`Heatmap: no group \"${groupId}\".`);\n }\n latest.current.setGroupCollapsed(own, isCollapsed);\n },\n };\n }, []);\n useAgentRegistration(heatmapAgent, agentHandle, id);\n\n /* ---- context ----------------------------------------------------------- */\n const hasEmpty = useMemo(\n () => matrix.some((row) => row.some((cell) => cell.status === 'empty')),\n [matrix],\n );\n const hasLowSample = useMemo(\n () =>\n matrix.some((row) => row.some((cell) => cell.status === 'low-sample')),\n [matrix],\n );\n const context = useMemo<HeatmapContextValue>(\n () => ({\n palette,\n scale,\n describer,\n hasEmpty,\n hasLowSample,\n minCount,\n tooltipText,\n }),\n [\n palette,\n scale,\n describer,\n hasEmpty,\n hasLowSample,\n minCount,\n tooltipText,\n ],\n );\n\n /* ---- render ------------------------------------------------------------ */\n const rootClassName = heatmapRootVariants({ className });\n\n if (loading) {\n return (\n <HeatmapContext.Provider value={context}>\n <div\n ref={ref}\n data-component=\"heatmap\"\n data-component-id={id}\n className={rootClassName}\n >\n <div\n role=\"status\"\n aria-label={t('heatmap.loading')}\n aria-busy=\"true\"\n className={heatmapRootVariants()}\n >\n <Skeleton\n variant=\"rectangular\"\n className=\"ds:h-[var(--spacing-md)] ds:w-[calc(var(--spacing-xl)*6)] ds:max-w-full\"\n />\n <Skeleton\n variant=\"rectangular\"\n className=\"ds:h-[calc(var(--min-target-size)*5)] ds:w-full\"\n />\n </div>\n {children}\n </div>\n </HeatmapContext.Provider>\n );\n }\n\n if (rows.length === 0 || columns.length === 0 || !hasAnyData(matrix)) {\n return (\n <HeatmapContext.Provider value={context}>\n <div\n ref={ref}\n data-component=\"heatmap\"\n data-component-id={id}\n className={rootClassName}\n >\n <EmptyState\n variant=\"no-results\"\n size=\"sm\"\n title={t('heatmap.empty.title')}\n description={t('heatmap.empty.description')}\n />\n {children}\n </div>\n </HeatmapContext.Provider>\n );\n }\n\n const virtualised =\n rows.length * columns.length > VIRTUALISE_CELL_THRESHOLD;\n const interactive = selection !== 'none' || onCellClick !== undefined;\n\n return (\n <HeatmapContext.Provider value={context}>\n <div\n ref={ref}\n data-component=\"heatmap\"\n data-component-id={id}\n className={rootClassName}\n >\n <div className={heatmapToolbarVariants()}>\n {legend !== false ? <HeatmapLegend variant={legend} /> : null}\n <Button\n intent=\"outline\"\n size=\"sm\"\n className=\"ds:ms-auto\"\n startIcon={\n view === 'table' ? (\n <Grid3x3 aria-hidden=\"true\" />\n ) : (\n <Table2 aria-hidden=\"true\" />\n )\n }\n // Fetch the table chunk on intent, so the switch rarely waits.\n onPointerEnter={\n view === 'table' ? undefined : preloadHeatmapTable\n }\n onFocus={view === 'table' ? undefined : preloadHeatmapTable}\n onClick={() => setView(view === 'table' ? 'heatmap' : 'table')}\n >\n {view === 'table'\n ? t('heatmap.viewAsHeatmap')\n : t('heatmap.viewAsTable')}\n </Button>\n </div>\n {view === 'table' ? (\n <HeatmapTableView\n // A new table when the privacy setting changes: AG Grid applies\n // new row data a frame later, and the old labels must not\n // show for that frame.\n key={`${privacyMode}-${privacyScope}`}\n onLoadError={() => announce(t('heatmap.announce.tableFailed'))}\n title={title}\n rowsLabel={rowsLabel}\n rows={rows}\n columns={columns}\n matrix={matrix}\n body={expandedBody}\n grouped={groupRows}\n groupIds={groupIds}\n describer={describer}\n totals={totals}\n rowTotals={rowTotals}\n columnTotals={columnTotals}\n groupColumnMethod={groupColumnMethod}\n minCount={minCount}\n />\n ) : (\n <TooltipProvider delayDuration={0}>\n <HeatmapGrid\n title={title}\n rowsLabel={rowsLabel}\n rows={rows}\n columns={columns}\n matrix={matrix}\n body={body}\n scale={scale}\n palette={palette}\n describer={describer}\n showValues={showValues}\n totals={totals}\n rowTotals={rowTotals}\n columnTotals={columnTotals}\n groupColumnMethod={groupColumnMethod}\n groupIds={groupIds}\n minCount={minCount}\n selectionMode={selection}\n selected={selected}\n columnIndexOfKey={columnIndexOfKey}\n interactive={interactive}\n virtualised={virtualised}\n size={size}\n density={density}\n cellInfo={cellInfo}\n tooltipText={tooltipText}\n describeFocused={renderTooltip !== undefined}\n onActivate={onActivate}\n onRange={onRange}\n onToggleGroup={toggleGroup}\n />\n </TooltipProvider>\n )}\n {children}\n {/* A fresh region when the privacy setting changes: LiveRegion\n shows its text from an effect, so a kept one would show a\n message made before privacy mode for one more render. */}\n <LiveRegion key={String(privacyMode)}>{spoken}</LiveRegion>\n </div>\n </HeatmapContext.Provider>\n );\n },\n);\n\nHeatmapRoot.displayName = 'Heatmap';\n\n/**\n * Heatmap: a grid of cells coloured by value on a token scale, for patterns\n * such as chair occupancy by hour or no-shows by weekday and hour. Keyboard,\n * screen reader and table view are built in; see heatmap.mdx.\n */\nexport const Heatmap = Object.assign(HeatmapRoot, {\n Legend: HeatmapLegend,\n Tooltip: HeatmapTooltip,\n});\n"],"names":["__iconNode","Grid3x3","createLucideIcon","Table2","cellSchema","heatmapAgent","handle","args","next","HeatmapContext","createContext","useHeatmapContext","useContext","defaultValueFormatter","locale","valueType","format","value","countFormatter","count","EMPTY_GLYPH","createDescriber","t","privacyMode","privacyScope","formatValue","formatCount","groups","groupNames","group","mask","privacyMask","masksRows","masksColumns","masksGroups","valueText","cell","countText","row","column","groupId","rowText","columnText","groupText","method","HEATMAP_STEPS","MIDDLE_STEP","TOP_STEP","HALF_STEPS","clamp","low","high","warned","warn","message","isDevelopment","orderedDomain","domain","distinctSorted","values","sorted","b","i","extent","sequentialStep","divergingStep","midpoint","span","onMidpoint","scale","magnitude","quantileSorted","p","n","position","below","above","quantileThresholds","buckets","edges","usableQuantileEdges","min","atOrAbove","edge","mid","thresholdBucket","thresholds","bucketStep","bucket","bucketCount","resolveScale","range","fixed","reach","a","given","distinct","sumOf","cells","total","seen","counted","weightedMean","weighted","weights","weight","aggregate","publicGroupIds","rows","listed","taken","ids","fallback","isLowSample","minCount","toModelCell","input","data","status","buildMatrix","columns","getCell","r","c","_a","shownValues","matrix","hasAnyData","computeTotals","columnCount","rowMethod","columnMethod","groupColumnMethod","rowTotals","columnTotals","byGroup","list","groupColumns","indexes","perColumn","dataRowKey","rowId","groupRowKey","FOOTER_ROW_KEY","sortRowIndexes","totals","sort","collator","direction","left","right","_b","buildBodyRows","sortedIndexes","groupRows","collapsed","order","members","loose","body","rowIndexes","isCollapsed","HeatmapTooltip","label","open","onOpenChange","side","children","context","text","jsx","Tooltip","HeatmapCellTooltip","VIRTUALISE_CELL_THRESHOLD","OVERSCAN","visibleRange","offset","viewport","lead","pitch","overscan","from","first","last","start","end","axisWindow","pinned","visible","fullWindow","_","trimWindow","window","index","sameWindow","stepTone","palette","step","toneClasses","heatmapRootVariants","cva","heatmapToolbarVariants","heatmapScrollerVariants","heatmapTableViewVariants","heatmapGridVariants","heatmapRowVariants","heatmapSpacerVariants","headerHighlight","heatmapColumnHeaderVariants","heatmapRowHeaderVariants","heatmapRowLabelVariants","heatmapCellVariants","heatmapLegendVariants","heatmapLegendBarVariants","heatmapSwatchVariants","KEY_SEPARATOR","selectionKey","columnId","splitSelectionKey","key","at","toneOf","aggregateCell","result","aggregateTone","renderColumns","render","out","columnIndex","HeatmapBodyRow","memo","ctx","ariaRowIndex","highlighted","activeCol","tooltipCol","selectedCols","selected","useMemo","hookId","labelId","overall","groupCell","withTooltip","name","jsxs","perColumnRowText","event","ChevronDown","source","dataCell","isSelected","totalCell","DEFAULT_METRICS","pageRows","metrics","HeatmapGrid","props","title","rowsLabel","describer","showValues","groupIds","selectionMode","columnIndexOfKey","interactive","virtualised","size","density","cellInfo","tooltipText","describeFocused","onActivate","onRange","onToggleGroup","useTranslation","idBase","useId","scrollerRef","useRef","gridRef","headerRef","footerRef","navColumnCount","hasFooter","navRowKeys","rowIndexOfKey","map","active","setActive","useState","activeRow","found","hidden","activeKey","pendingFocus","hasFocus","setHasFocus","hasFocusRef","interaction","hover","setHover","hoverRef","tooltipDismissed","setTooltipDismissed","updateHover","useCallback","current","highlight","tooltipAt","setMetrics","metricsRef","measure","scroller","grid","style","rowGap","columnGap","tracks","track","headerHeight","firstBody","bodyHeight","useIsomorphicLayoutEffect","observer","pinnedRow","pinnedCol","computeWindows","m","rowRange","colRange","windowState","setWindows","fullRows","fullCols","windows","syncWindows","frame","onScroll","useEffect","cellElement","rowIndex","col","element","isRtl","anchor","dataRowIndexAt","navIndex","clearOnClick","moveTo","clampedRow","clampedCol","activate","extend","onKeyDown","lastRow","lastCol","forward","ctrl","nextGroup","previous","moved","isArrow","target","positionOf","rowElement","dragging","lastPointer","onPointerDown","stop","onPointerMove","awayListener","stopAway","onPointerLeave","away","over","onClick","button","scrolling","settle","onAnyScroll","onTooltipOpenChange","expandLabel","collapseLabel","descriptionId","focusedRow","description","selectedByRow","columnKey","joined","highlightCol","header","footer","footerIndex","methodText","footerActive","bodyRows","rowWindow","isActiveRow","scrollerStyle","STEPS","endLabels","HeatmapLegend","forwardRef","variant","paletteProp","scaleProp","valueFormatter","showEmpty","showLowSample","minCountProp","className","ref","i18n","formatLocale","banded","bandCount","bandSteps","band","labels","singleStep","withEmpty","withLowSample","shape","bar","steps","Fragment","loadDataTable","module","LazyDataTable","lazy","preloadHeatmapTable","HeatmapTableView","grouped","onLoadError","columnDefs","params","rowData","entry","pinnedBottomRowData","rowCount","rowCountRef","cappedAt","setCappedAt","capped","wrapperRef","wrapper","watch","child","gridOptions","attempt","setAttempt","DataTable","ErrorBoundary","Suspense","Skeleton","DEFAULT_SCALE","toKeySet","SILENCE","HeatmapRoot","legend","sortRowsProp","defaultSortRows","onSortRowsChange","defaultCollapsedGroups","selection","selectedCells","defaultSelectedCells","onSelectionChange","onCellClick","renderTooltip","loading","defaultView","onViewChange","id","scaleKey","announcement","setAnnouncement","announceTimer","privacyRef","announce","madeUnder","say","spoken","view","setViewState","setView","sortInternal","setSortInternal","sortRows","setSortRows","setCollapsed","setGroupCollapsed","toggleGroup","appliedSort","expandedBody","rowIndexById","columnIndexById","maskedInfo","info","isControlled","selectedInternal","setSelectedInternal","present","infosOf","keys","infos","cellName","commitSelection","countMessage","dataOrder","rectangle","to","top","bottom","select","adding","clearing","groupByPublicId","own","shown","agentState","latest","agentHandle","keysOf","set","cols","byColumn","byRow","requireCell","requireSelection","cellsToSelect","mode","picked","model","all","byShown","useAgentRegistration","hasEmpty","hasLowSample","rootClassName","EmptyState","Button","TooltipProvider","LiveRegion","Heatmap"],"mappings":";;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,MAAMA,KAAa;AAAA,EACjB,CAAC,QAAQ,EAAE,OAAO,MAAM,QAAQ,MAAM,GAAG,KAAK,GAAG,KAAK,IAAI,KAAK,KAAK,SAAQ,CAAE;AAAA,EAC9E,CAAC,QAAQ,EAAE,GAAG,WAAW,KAAK,SAAQ,CAAE;AAAA,EACxC,CAAC,QAAQ,EAAE,GAAG,YAAY,KAAK,SAAQ,CAAE;AAAA,EACzC,CAAC,QAAQ,EAAE,GAAG,WAAW,KAAK,SAAQ,CAAE;AAAA,EACxC,CAAC,QAAQ,EAAE,GAAG,YAAY,KAAK,SAAQ,CAAE;AAC3C,GACMC,KAAUC,GAAiB,YAAYF,EAAU;AChBvD;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,MAAMA,KAAa;AAAA,EACjB;AAAA,IACE;AAAA,IACA;AAAA,MACE,GAAG;AAAA,MACH,KAAK;AAAA,IACX;AAAA,EACA;AACA,GACMG,KAASD,GAAiB,WAAWF,EAAU,GCJ/CI,KAAa;AAAA,EACjB,MAAM;AAAA,EACN,YAAY;AAAA,IACV,OAAO,EAAE,MAAM,UAAU,aAAa,uBAAA;AAAA,IACtC,UAAU;AAAA,MACR,MAAM,CAAC,UAAU,QAAQ;AAAA,MACzB,aAAa;AAAA,IAAA;AAAA,EACf;AAAA,EAEF,UAAU,CAAC,SAAS,UAAU;AAChC,GAEaC,KAA4C;AAAA,EACvD,IAAI;AAAA,EACJ,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAAA,EAEF,OAAO;AAAA,IACL,WAAW;AAAA,MACT,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,MAAM,CAACC,MAAWA,EAAO,aAAA;AAAA,IAAa;AAAA,IAExC,eAAe;AAAA,MACb,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,MAAM,CAACA,MAAWA,EAAO,iBAAA;AAAA,IAAiB;AAAA,IAE5C,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,MAAM,CAACA,MAAWA,EAAO,QAAA;AAAA,IAAQ;AAAA,IAEnC,UAAU;AAAA,MACR,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,MAAM,CAACA,MAAWA,EAAO,YAAA;AAAA,IAAY;AAAA,IAEvC,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,MAAM,CAACA,MAAWA,EAAO,UAAA;AAAA,IAAU;AAAA,IAErC,WAAW;AAAA,MACT,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,MAAM,CAACA,MAAWA,EAAO,aAAA;AAAA,IAAa;AAAA,IAExC,UAAU;AAAA,MACR,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,MAAM,CAACA,MAAWA,EAAO,YAAA;AAAA,IAAY;AAAA,IAEvC,iBAAiB;AAAA,MACf,MAAM;AAAA,MACN,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,MAAM,CAACA,MAAWA,EAAO,mBAAA;AAAA,IAAmB;AAAA,EAC9C;AAAA,EAEF,SAAS;AAAA,IACP,aAAa;AAAA,MACX,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAYF;AAAA,MACZ,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,UAAU;AAAA,QACR;AAAA,UACE,MAAM,EAAE,OAAO,WAAW,UAAU,GAAA;AAAA,UACpC,MAAM;AAAA,QAAA;AAAA,MACR;AAAA,MAEF,QAAQ,CAACE,GAAQC,MAAuD;AACtE,QAAAD,EAAO,YAAY,CAACC,CAAI,CAAC;AAAA,MAC3B;AAAA,IAAA;AAAA,IAEF,cAAc;AAAA,MACZ,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY;AAAA,UACV,OAAO;AAAA,YACL,MAAM;AAAA,YACN,OAAOH;AAAA,YACP,aACE;AAAA,UAAA;AAAA,QACJ;AAAA,QAEF,UAAU,CAAC,OAAO;AAAA,MAAA;AAAA,MAEpB,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,QAAQ,CACNE,GACAC,MACG;AACH,QAAAD,EAAO,YAAYC,EAAK,KAAK;AAAA,MAC/B;AAAA,IAAA;AAAA,IAEF,cAAc;AAAA,MACZ,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY;AAAA,UACV,MAAM,EAAE,GAAGH,IAAY,aAAa,yBAAA;AAAA,UACpC,IAAI,EAAE,GAAGA,IAAY,aAAa,kCAAA;AAAA,QAAkC;AAAA,QAEtE,UAAU,CAAC,QAAQ,IAAI;AAAA,MAAA;AAAA,MAEzB,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,QAAQ,CACNE,GACAC,MAIG;AACH,QAAAD,EAAO,YAAYC,EAAK,MAAMA,EAAK,EAAE;AAAA,MACvC;AAAA,IAAA;AAAA,IAEF,iBAAiB;AAAA,MACf,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CAAC,sCAAsC;AAAA,MAC/C,QAAQ,CAACD,MAAW;AAClB,QAAAA,EAAO,eAAA;AAAA,MACT;AAAA,IAAA;AAAA,IAEF,WAAW;AAAA,MACT,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAYF;AAAA,MACZ,SAAS;AAAA,MACT,eAAe;AAAA,QACb,MAAM,CAAC,UAAU,MAAM;AAAA,QACvB,YAAY;AAAA,UACV,OAAO,EAAE,MAAM,CAAC,UAAU,MAAM,EAAA;AAAA,UAChC,OAAO,EAAE,MAAM,SAAA;AAAA,UACf,QAAQ,EAAE,MAAM,CAAC,SAAS,SAAS,YAAY,EAAA;AAAA,UAC/C,MAAM,EAAE,MAAM,CAAC,UAAU,MAAM,EAAA;AAAA,QAAE;AAAA,MACnC;AAAA,MAEF,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aACE;AAAA,MACF,QAAQ,CAACE,GAAQC,MACfD,EAAO,SAASC,CAAI;AAAA,IAAA;AAAA,IAExB,mBAAmB;AAAA,MACjB,QAAQ;AAAA,MACR,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,SAAS;AAAA,MACT,eAAe,EAAE,MAAM,CAAC,WAAW,OAAO,EAAA;AAAA,MAC1C,QAAQ,CAACD,MAAW;AAClB,cAAME,IAAOF,EAAO,QAAA,MAAc,UAAU,YAAY;AACxD,eAAAA,EAAO,QAAQE,CAAI,GACZA;AAAA,MACT;AAAA,IAAA;AAAA,IAEF,UAAU;AAAA,MACR,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY;AAAA,UACV,MAAM;AAAA,YACJ,MAAM,CAAC,WAAW,OAAO;AAAA,YACzB,aAAa;AAAA,UAAA;AAAA,QACf;AAAA,QAEF,UAAU,CAAC,MAAM;AAAA,MAAA;AAAA,MAEnB,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CAACF,GAAQC,MAAwC;AACvD,QAAID,EAAO,cAAcC,EAAK,QAAMD,EAAO,QAAQC,EAAK,IAAI;AAAA,MAC9D;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,CAAC,QAAQ,SAAS,aAAa,YAAY;AAAA,YACjD,aACE;AAAA,UAAA;AAAA,QACJ;AAAA,QAEF,UAAU,CAAC,MAAM;AAAA,MAAA;AAAA,MAEnB,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ,CACND,GACAC,MACG;AACH,QAAAD,EAAO,YAAYC,EAAK,IAAI;AAAA,MAC9B;AAAA,IAAA;AAAA,IAEF,cAAc;AAAA,MACZ,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY;AAAA,UACV,SAAS,EAAE,MAAM,UAAU,aAAa,2BAAA;AAAA,QAA2B;AAAA,QAErE,UAAU,CAAC,SAAS;AAAA,MAAA;AAAA,MAEtB,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,QAAQ,CAACD,GAAQC,MAA8B;AAC7C,QAAAD,EAAO,kBAAkBC,EAAK,SAAS,EAAK;AAAA,MAC9C;AAAA,IAAA;AAAA,IAEF,gBAAgB;AAAA,MACd,QAAQ;AAAA,MACR,UAAU;AAAA,MACV,YAAY;AAAA,QACV,MAAM;AAAA,QACN,YAAY;AAAA,UACV,SAAS,EAAE,MAAM,UAAU,aAAa,2BAAA;AAAA,QAA2B;AAAA,QAErE,UAAU,CAAC,SAAS;AAAA,MAAA;AAAA,MAEtB,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,MAAA;AAAA,MAEF,QAAQ,CAACD,GAAQC,MAA8B;AAC7C,QAAAD,EAAO,kBAAkBC,EAAK,SAAS,EAAI;AAAA,MAC7C;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,GCjSaE,KAAiBC,GAA0C,IAAI;AAGrE,SAASC,KAAgD;AAC9D,SAAOC,GAAWH,EAAc;AAClC;ACFO,SAASI,GACdC,GACAC,GAC2B;AAC3B,QAAMC,IAAS,IAAI,KAAK;AAAA,IACtBF;AAAA,IACAC,MAAc,SACV,EAAE,OAAO,WAAW,uBAAuB,EAAA,IAC3C,EAAE,uBAAuB,EAAA;AAAA,EAAE;AAEjC,SAAO,CAACE,MAAUD,EAAO,OAAOC,CAAK;AACvC;AAGO,SAASC,GAAeJ,GAA2C;AACxE,QAAME,IAAS,IAAI,KAAK,aAAaF,GAAQ,EAAE,uBAAuB,GAAG;AACzE,SAAO,CAACK,MAAUH,EAAO,OAAOG,CAAK;AACvC;AA6CA,MAAMC,KAAc;AAEb,SAASC,GAAgB;AAAA,EAC9B,GAAAC;AAAA,EACA,aAAAC;AAAA,EACA,cAAAC,IAAe;AAAA,EACf,WAAAT;AAAA,EACA,aAAAU;AAAA,EACA,aAAAC;AAAA,EACA,QAAAC;AACF,GAAuC;AACrC,QAAMC,IAAa,IAAI,IAAID,KAAA,gBAAAA,EAAQ,IAAI,CAACE,MAAU,CAACA,EAAM,IAAIA,EAAM,KAAK,EAAE,GACpEC,IAAOC,GAAA,GACPC,IAAYT,GACZU,IAAeV,KAAeC,MAAiB,OAC/CU,IAAcX,KAAeC,MAAiB,OAC9CW,IAAY,CAACC,MACbA,EAAK,WAAW,UAAgBd,EAAE,gBAAgB,IAClDc,EAAK,WAAW,eAAqBd,EAAE,mBAAmB,IAE1Dc,EAAK,UAAU,UAAa,CAACb,IAAoBa,EAAK,QACnDA,EAAK,UAAU,OAAOd,EAAE,gBAAgB,IAAIG,EAAYW,EAAK,KAAK,GAErEC,IAAY,CAACD,MACbA,EAAK,UAAU,SAAkB,OAEnCrB,MAAc,UACdqB,EAAK,WAAW,WAChBA,EAAK,UAAU,OAERd,EAAE,mBAAmB;AAAA,IAC1B,MAAMI,EAAY,KAAK,MAAMU,EAAK,QAAQA,EAAK,KAAK,CAAC;AAAA,IACrD,OAAOV,EAAYU,EAAK,KAAK;AAAA,EAAA,CAC9B,IAEId,EAAE,mBAAmB;AAAA,IAC1B,OAAOc,EAAK;AAAA,IACZ,WAAWV,EAAYU,EAAK,KAAK;AAAA,EAAA,CAClC;AAEH,SAAO;AAAA,IACL,WAAAJ;AAAA,IACA,cAAAC;AAAA,IACA,aAAAC;AAAA,IACA,UAAU,CAACI,MAASN,IAAYF,IAAOQ,EAAI;AAAA,IAC3C,aAAa,CAACC,MAAYN,IAAeH,IAAOS,EAAO;AAAA;AAAA;AAAA,IAGvD,YAAY,CAACC,MACXN,IACIJ,IACCF,EAAW,IAAIY,CAAO,MAAMjB,IAAcO,IAAOU;AAAA,IACxD,UAAU,CAACC,GAASC,MAClBpB,EAAE,oBAAoB,EAAE,KAAKmB,GAAS,QAAQC,GAAY;AAAA,IAC5D,cAAc,CAACC,GAAWC,MACxBtB,EAAE,oBAAoB;AAAA,MACpB,OAAOqB;AAAA,MACP,QACqBrB,EAAnBsB,MAAW,QAAU,uBAA0B,qBAAN;AAAA,IAA2B,CACvE;AAAA,IACH,WAAW,CAACR,MAAS;AACnB,YAAMjB,IAAQiB,EAAK,WAAW,UAAU,OAAOC,EAAUD,CAAI,GACvDnB,IAAQkB,EAAUC,CAAI;AAC5B,aAAOjB,MAAU,OACbF,IACAK,EAAE,0BAA0B,EAAE,OAAAL,GAAO,OAAAE,GAAO;AAAA,IAClD;AAAA,IACA,aAAa,CAACyB,MACOtB,EAAnBsB,MAAW,QAAU,uBAA0B,qBAAN;AAAA,IAC3C,WAAAT;AAAA,IACA,aAAa,CAACC,MACZA,EAAK,WAAW,UACZhB,KACAgB,EAAK,WAAW,eACd,KACAD,EAAUC,CAAI;AAAA,IACtB,WAAAC;AAAA,IACA,UAAU,CAACI,GAASC,GAAYN,MAAS;AACvC,YAAMjB,IAAQkB,EAAUD,CAAI,GACtBnB,IAAQkB,EAAUC,CAAI;AAC5B,aAAOjB,MAAU,QAAQiB,EAAK,WAAW,UACrCd,EAAE,gBAAgB,EAAE,KAAKmB,GAAS,QAAQC,GAAY,OAAAzB,EAAA,CAAO,IAC7DK,EAAE,yBAAyB;AAAA,QACzB,KAAKmB;AAAA,QACL,QAAQC;AAAA,QACR,OAAAzB;AAAA,QACA,OAAAE;AAAA,MAAA,CACD;AAAA,IACP;AAAA,IACA,aAAAM;AAAA,EAAA;AAEJ;ACzKO,MAAMoB,KAAgB,IAGvBC,KAAc,KAAK,MAAMD,KAAgB,CAAC,GAG1CE,KAAWF,KAAgB,GAG3BG,KAAaH,KAAgB,GA6C7BI,KAAQ,CAAChC,GAAeiC,GAAaC,MACzC,KAAK,IAAIA,GAAM,KAAK,IAAID,GAAKjC,CAAK,CAAC,GAI/BmC,yBAAa,IAAA;AAInB,SAASC,GAAKC,GAAuB;AACnC,EAAI,CAACC,GAAA,KAAmBH,GAAO,IAAIE,CAAO,MAC1CF,GAAO,IAAIE,CAAO,GAClB,QAAQ,KAAK,YAAYA,CAAO,EAAE;AACpC;AAGA,SAASE,GACPC,GAC2B;AAC3B,SAAIA,EAAO,CAAC,KAAKA,EAAO,CAAC,IAAUA,KACnCJ;AAAA,IACE,iBAAiBI,EAAO,CAAC,CAAC,KAAKA,EAAO,CAAC,CAAC,yBAAyBA,EAAO,CAAC,CAAC,KAAKA,EAAO,CAAC,CAAC;AAAA,EAAA,GAEnF,CAACA,EAAO,CAAC,GAAGA,EAAO,CAAC,CAAC;AAC9B;AAGA,SAASC,GAAeC,GAAqC;AAC3D,QAAMC,IAASD,EAAO,OAAO,OAAO,QAAQ,EAAE,KAAK,CAAC,GAAGE,MAAM,IAAIA,CAAC;AAClE,SAAOD,EAAO,OAAO,CAAC3C,GAAO6C,MAAMA,MAAM,KAAK7C,MAAU2C,EAAOE,IAAI,CAAC,CAAC;AACvE;AAGO,SAASC,GAAOJ,GAAoD;AACzE,MAAIT,IAAM,OACNC,IAAO;AACX,aAAWlC,KAAS0C;AAClB,IAAK,OAAO,SAAS1C,CAAK,MACtBA,IAAQiC,MAAKA,IAAMjC,IACnBA,IAAQkC,MAAMA,IAAOlC;AAE3B,SAAOiC,MAAQ,QAAW,OAAO,CAACA,GAAKC,CAAI;AAC7C;AAOO,SAASa,GAAe/C,GAAeiC,GAAaC,GAAc;AACvE,MAAI,EAAEA,IAAOD,GAAM,QAAOJ;AAC1B,QAAMxB,IAAI2B,IAAOhC,IAAQiC,MAAQC,IAAOD,IAAM,GAAG,CAAC;AAClD,SAAO,KAAK,IAAIH,IAAU,KAAK,MAAMzB,IAAIuB,EAAa,CAAC;AACzD;AAQO,SAASoB,GACdhD,GACAiC,GACAgB,GACAf,GACQ;AACR,MAAIlC,IAAQiD,GAAU;AACpB,UAAMC,IAAOD,IAAWhB,GAClB5B,IAAI6C,IAAO,IAAIlB,IAAOiB,IAAWjD,KAASkD,GAAM,GAAG,CAAC,IAAI;AAC9D,WACEnB,KAAa,IAAI,KAAK,IAAIA,KAAa,GAAG,KAAK,MAAM1B,IAAI0B,EAAU,CAAC;AAAA,EAExE;AACA,QAAMmB,IAAOhB,IAAOe,GACd5C,IACJ6C,IAAO,IACHlB,IAAOhC,IAAQiD,KAAYC,GAAM,GAAG,CAAC,IACrClD,IAAQiD,IACN,IACA;AACR,SAAOlB,KAAa,KAAK,IAAIA,KAAa,GAAG,KAAK,MAAM1B,IAAI0B,EAAU,CAAC;AACzE;AAWO,SAASoB,GACdC,GACApD,GACS;AACT,MAAIoD,EAAM,SAAS,eAAeA,EAAM,aAAa,OAAW,QAAO;AACvE,QAAMC,IAAY,KAAK;AAAA,IACrB,KAAK,IAAID,EAAM,QAAQ;AAAA,IACvB,KAAK,IAAIA,EAAM,OAAO,CAAC;AAAA,IACvB,KAAK,IAAIA,EAAM,OAAO,CAAC;AAAA,EAAA;AAEzB,SAAO,KAAK,IAAIpD,IAAQoD,EAAM,QAAQ,KAAKC,IAAY,OAAO,UAAU;AAC1E;AAMO,SAASC,GAAeX,GAA2BY,GAAmB;AAC3E,QAAMC,IAAIb,EAAO;AACjB,MAAIa,MAAM,EAAG,QAAO;AACpB,MAAIA,MAAM,EAAG,QAAOb,EAAO,CAAC;AAC5B,QAAMc,IAAWzB,GAAMuB,GAAG,GAAG,CAAC,KAAKC,IAAI,IACjCE,IAAQ,KAAK,MAAMD,CAAQ,GAC3BE,IAAQ,KAAK,IAAIH,IAAI,GAAGE,IAAQ,CAAC;AACvC,SAAOf,EAAOe,CAAK,KAAKf,EAAOgB,CAAK,IAAIhB,EAAOe,CAAK,MAAMD,IAAWC;AACvE;AAGO,SAASE,GACdjB,GACAkB,GACU;AACV,QAAM3D,IAAQ,KAAK,IAAI,GAAG,KAAK,MAAM2D,CAAO,CAAC,GACvCC,IAAkB,CAAA;AACxB,WAASjB,IAAI,GAAGA,IAAI3C,GAAO2C,KAAK;AAC9B,IAAAiB,EAAM,KAAKR,GAAeX,GAAQE,IAAI3C,CAAK,CAAC;AAE9C,SAAO4D;AACT;AAWO,SAASC,GACdpB,GACAkB,GACU;AACV,MAAIlB,EAAO,WAAW,EAAG,QAAO,CAAA;AAChC,QAAMqB,IAAMrB,EAAO,CAAC,GACdsB,IAAY,CAACC,MAAyB;AAC1C,QAAIjC,IAAM,GACNC,IAAOS,EAAO,SAAS;AAC3B,WAAOV,IAAMC,KAAM;AACjB,YAAMiC,IAAOlC,IAAMC,MAAU;AAC7B,MAAIS,EAAOwB,CAAG,IAAID,QAAYC,IAAM,IAC/BjC,IAAOiC;AAAA,IACd;AACA,WAAOxB,EAAOV,CAAG;AAAA,EACnB;AACA,SAAOQ;AAAA,IACLmB,GAAmBjB,GAAQkB,CAAO,EAAE,IAAII,CAAS;AAAA,EAAA,EACjD,OAAO,CAACC,MAASA,IAAOF,CAAG;AAC/B;AAGO,SAASI,GACdpE,GACAqE,GACQ;AACR,MAAIpC,IAAM,GACNC,IAAOmC,EAAW;AACtB,SAAOpC,IAAMC,KAAM;AACjB,UAAMiC,IAAOlC,IAAMC,MAAU;AAC7B,IAAImC,EAAWF,CAAG,KAAKnE,QAAamE,IAAM,IACrCjC,IAAOiC;AAAA,EACd;AACA,SAAOlC;AACT;AAGO,SAASqC,GAAWC,GAAgBC,GAA6B;AACtE,SAAIA,KAAe,IAAU3C,KACtB,KAAK;AAAA,IACTG,GAAMuC,GAAQ,GAAGC,IAAc,CAAC,IAAI1C,MAAa0C,IAAc;AAAA,EAAA;AAEpE;AAOO,SAASC,GACdrB,GACAV,GACsB;AACtB,QAAMgC,IAAQ5B,GAAOJ,CAAM;AAE3B,UAAQU,EAAM,MAAA;AAAA,IACZ,KAAK,aAAa;AAChB,YAAMuB,IACJvB,EAAM,UAAUA,EAAM,WAAW,SAC7Bb,GAAca,EAAM,MAAM,IAC1B,MAIAH,IACJG,EAAM,aACLuB,MAAUA,EAAM,CAAC,IAAI,KAAKA,EAAM,CAAC,IAAI,MACjCA,EAAM,CAAC,IAAIA,EAAM,CAAC,KAAK,IACxB;AACN,UAAI1C,GACAC;AACJ,UAAIyC;AACF,SAAC1C,GAAKC,CAAI,IAAIyC;AAAA,WACT;AACL,cAAMC,IAAQF,IACV,KAAK;AAAA,UACH,KAAK,IAAIA,EAAM,CAAC,IAAIzB,CAAQ;AAAA,UAC5B,KAAK,IAAIyB,EAAM,CAAC,IAAIzB,CAAQ;AAAA,QAAA,IAE9B;AACJ,QAAAhB,IAAMgB,IAAW2B,GACjB1C,IAAOe,IAAW2B;AAAA,MACpB;AACA,aAAO;AAAA,QACL,MAAM;AAAA,QACN,KAAK3C;AAAA,QACL,KAAKC;AAAA,QACL,UAAAe;AAAA,QACA,YAAY,CAAA;AAAA,QACZ,QAAQ,CAACjD,MAAUgD,GAAchD,GAAOiC,GAAKgB,GAAUf,CAAI;AAAA,MAAA;AAAA,IAE/D;AAAA,IACA,KAAK,YAAY;AACf,YAAMS,IAASD,EACZ,OAAO,OAAO,QAAQ,EACtB,MAAA,EACA,KAAK,CAACmC,GAAG,MAAMA,IAAI,CAAC,GACjBhB,IAAU7B;AAAA,QACd,KAAK,MAAMoB,EAAM,WAAWxB,EAAa;AAAA,QACzC;AAAA,QACAA;AAAA,MAAA,GAIIyC,IAAaN,GAAoBpB,GAAQkB,CAAO;AACtD,aAAO;AAAA,QACL,MAAM;AAAA,QACN,MAAKa,KAAA,gBAAAA,EAAQ,OAAM;AAAA,QACnB,MAAKA,KAAA,gBAAAA,EAAQ,OAAM;AAAA,QACnB,YAAAL;AAAA,QACA,QAAQ,CAACrE,MACPsE,GAAWF,GAAgBpE,GAAOqE,CAAU,GAAGA,EAAW,SAAS,CAAC;AAAA,MAAA;AAAA,IAE1E;AAAA,IACA,KAAK,aAAa;AAChB,YAAMS,IAAQ1B,EAAM,WAAW,OAAO,OAAO,QAAQ,GAC/C2B,IAAWtC,GAAeqC,CAAK;AACrC,MAAIC,EAAS,WAAWD,EAAM,UAC5B1C,GAAK,8BAA8B,GAEjC2C,EAAS,SAASjD,MACpBM;AAAA,QACE,GAAG2C,EAAS,MAAM,6CAA6CjD,EAAQ,oBAAoBiD,EAAS,SAASjD,EAAQ;AAAA,MAAA;AAGzH,YAAMuC,IAAaU,EAAS,MAAM,GAAGjD,EAAQ;AAC7C,aAAO;AAAA,QACL,MAAM;AAAA,QACN,MAAK4C,KAAA,gBAAAA,EAAQ,OAAM;AAAA,QACnB,MAAKA,KAAA,gBAAAA,EAAQ,OAAM;AAAA,QACnB,YAAAL;AAAA,QACA,QAAQ,CAACrE,MACPsE,GAAWF,GAAgBpE,GAAOqE,CAAU,GAAGA,EAAW,SAAS,CAAC;AAAA,MAAA;AAAA,IAE1E;AAAA,IACA,KAAK;AAAA,IACL,SAAS;AACP,YAAMM,IACJvB,EAAM,UAAUA,EAAM,WAAW,SAC7Bb,GAAca,EAAM,MAAM,IAC1B,MACAnB,IAAM0C,IAAQA,EAAM,CAAC,KAAKD,KAAA,gBAAAA,EAAQ,OAAM,MACxCxC,IAAOyC,IAAQA,EAAM,CAAC,KAAKD,KAAA,gBAAAA,EAAQ,OAAM;AAC/C,aAAO;AAAA,QACL,MAAM;AAAA,QACN,KAAKzC;AAAA,QACL,KAAKC;AAAA,QACL,YAAY,CAAA;AAAA,QACZ,QAAQ,CAAClC,MACPiC,MAAQ,QAAQC,MAAS,OACrBL,KACAkB,GAAe/C,GAAOiC,GAAKC,CAAI;AAAA,MAAA;AAAA,IAEzC;AAAA,EAAA;AAEJ;AAuBO,SAAS8C,GAAMC,GAAmD;AACvE,MAAIC,IAAQ,GACRC,IAAO,IACPjF,IAAQ,GACRkF,IAAU;AACd,aAAWjE,KAAQ8D;AACjB,IAAI9D,EAAK,UAAU,QAAQ,CAAC,OAAO,SAASA,EAAK,KAAK,MACtD+D,KAAS/D,EAAK,OACdgE,IAAO,IACHhE,EAAK,UAAU,WACjBjB,KAASiB,EAAK,OACdiE,IAAU;AAGd,SAAO,EAAE,OAAOD,IAAOD,IAAQ,MAAM,OAAOE,IAAUlF,IAAQ,OAAA;AAChE;AAQO,SAASmF,GACdJ,GACiB;AACjB,MAAIK,IAAW,GACXC,IAAU,GACVrF,IAAQ,GACRkF,IAAU;AACd,aAAWjE,KAAQ8D,GAAO;AACxB,QAAI9D,EAAK,UAAU,QAAQ,CAAC,OAAO,SAASA,EAAK,KAAK,EAAG;AACzD,UAAMqE,IAASrE,EAAK,SAAS;AAC7B,IAAAmE,KAAYnE,EAAK,QAAQqE,GACzBD,KAAWC,GACPrE,EAAK,UAAU,WACjBjB,KAASiB,EAAK,OACdiE,IAAU;AAAA,EAEd;AACA,SAAO;AAAA,IACL,OAAOG,IAAU,IAAID,IAAWC,IAAU;AAAA,IAC1C,OAAOH,IAAUlF,IAAQ;AAAA,EAAA;AAE7B;AAGO,SAASuF,GACdR,GACAtD,GACiB;AACjB,SAAOA,MAAW,QAAQqD,GAAMC,CAAK,IAAII,GAAaJ,CAAK;AAC7D;AC5XO,SAASS,GACdC,GACAjF,GACqB;AACrB,QAAMkF,IAAS,IAAI,IAAIlF,KAAA,gBAAAA,EAAQ,IAAI,CAACE,MAAUA,EAAM,GAAG,GACjDiF,IAAQ,IAAI,IAAID,CAAM,GACtBE,wBAAU,IAAA;AAChB,MAAItC,IAAI;AACR,aAAWnC,KAAOsE,GAAM;AACtB,UAAMpE,IAAUF,EAAI;AACpB,QAAIE,MAAY,UAAauE,EAAI,IAAIvE,CAAO,EAAG;AAC/C,QAAIqE,EAAO,IAAIrE,CAAO,GAAG;AACvB,MAAAuE,EAAI,IAAIvE,GAASA,CAAO;AACxB;AAAA,IACF;AACA,QAAIwE;AACJ;AACE,MAAAvC,KAAK,GACLuC,IAAW,SAASvC,CAAC;AAAA,WACdqC,EAAM,IAAIE,CAAQ;AAC3B,IAAAF,EAAM,IAAIE,CAAQ,GAClBD,EAAI,IAAIvE,GAASwE,CAAQ;AAAA,EAC3B;AACA,SAAOD;AACT;AA+DO,SAASE,GACd9F,GACA+F,GACS;AACT,SAAOA,MAAa,UAAa/F,MAAU,UAAaA,IAAQ+F;AAClE;AAGO,SAASC,GACdC,GACAF,GACW;AACX,MAAIE,KAAU;AACZ,WAAO,EAAE,OAAO,MAAM,QAAQ,QAAA;AAEhC,QAAMC,IACJ,OAAOD,KAAU,WAAW,EAAE,OAAOA,MAAUA,GAC3CnG,IACJoG,EAAK,UAAU,QAAQ,CAAC,OAAO,SAASA,EAAK,KAAK,IAAI,OAAOA,EAAK,OAC9DC,IACJrG,MAAU,OACN,UACAgG,GAAYI,EAAK,OAAOH,CAAQ,IAC9B,eACA;AACR,SAAO,EAAE,OAAAjG,GAAO,OAAOoG,EAAK,OAAO,OAAOA,EAAK,OAAO,QAAAC,EAAA;AACxD;AAGO,SAASC,GACdX,GACAY,GACAC,GAQAvB,GACAgB,GACe;AACf,SAAON,EAAK;AAAA,IAAI,CAACtE,GAAKoF,MACpBF,EAAQ;AAAA,MAAI,CAACjF,GAAQoF;;AACnB,eAAAR;AAAA,UACEM,IAAUA,EAAQnF,GAAKC,GAAQmF,GAAGC,CAAC,KAAIC,IAAA1B,KAAA,gBAAAA,EAAQwB,OAAR,gBAAAE,EAAaD;AAAA,UACpDT;AAAA,QAAA;AAAA;AAAA,IACF;AAAA,EACF;AAEJ;AAGO,SAASW,GAAYC,GAA0C;AACpE,QAAMnE,IAAmB,CAAA;AACzB,aAAWrB,KAAOwF;AAChB,eAAW1F,KAAQE;AACjB,MAAIF,EAAK,WAAW,WAAWA,EAAK,UAAU,QAC5CuB,EAAO,KAAKvB,EAAK,KAAK;AAG5B,SAAOuB;AACT;AAGO,SAASoE,GAAWD,GAAyC;AAClE,SAAOA,EAAO,KAAK,CAACxF,MAAQA,EAAI,KAAK,CAACF,MAASA,EAAK,WAAW,OAAO,CAAC;AACzE;AA0BO,SAAS4F,GACdF,GACAlB,GACAqB,GACAC,GACAC,GACAC,GACe;AACf,QAAMC,IAAYP,EAAO,IAAI,CAAC5B,MAAUQ,GAAUR,GAAOgC,CAAS,CAAC,GAC7DI,IAAkC,CAAA;AACxC,WAASX,IAAI,GAAGA,IAAIM,GAAaN,KAAK;AACpC,IAAAW,EAAa;AAAA,MACX5B;AAAA,QACEoB,EAAO,IAAI,CAAC5B,MAAUA,EAAMyB,CAAC,CAAC;AAAA,QAC9BQ;AAAA,MAAA;AAAA,IACF;AAGJ,QAAMI,wBAAc,IAAA;AACpB,EAAA3B,EAAK,QAAQ,CAACtE,GAAKoF,MAAM;AACvB,QAAIpF,EAAI,UAAU,OAAW;AAC7B,UAAMkG,IAAOD,EAAQ,IAAIjG,EAAI,KAAK,KAAK,CAAA;AACvC,IAAAkG,EAAK,KAAKd,CAAC,GACXa,EAAQ,IAAIjG,EAAI,OAAOkG,CAAI;AAAA,EAC7B,CAAC;AACD,QAAMC,wBAAmB,IAAA,GACnB9G,wBAAa,IAAA;AACnB,aAAW,CAACa,GAASkG,CAAO,KAAKH,GAAS;AACxC,UAAMI,IAA+B,CAAA;AACrC,aAAShB,IAAI,GAAGA,IAAIM,GAAaN,KAAK;AACpC,MAAAgB,EAAU;AAAA,QACRjC;AAAA,UACEgC,EAAQ,IAAI,CAAChB,MAAMI,EAAOJ,CAAC,EAAEC,CAAC,CAAC;AAAA,UAC/BS;AAAA,QAAA;AAAA,MACF;AAGJ,IAAAK,EAAa,IAAIjG,GAASmG,CAAS,GACnChH,EAAO;AAAA,MACLa;AAAA,MACAkE;AAAA,QACEgC,EAAQ,QAAQ,CAAChB,MAAMI,EAAOJ,CAAC,CAAC;AAAA,QAChCQ;AAAA,MAAA;AAAA,IACF;AAAA,EAEJ;AACA,SAAO;AAAA,IACL,MAAMG;AAAA,IACN,SAASC;AAAA,IACT,OAAO5B,GAAUoB,EAAO,KAAA,GAAQI,CAAS;AAAA,IACzC,cAAAO;AAAA,IACA,QAAA9G;AAAA,EAAA;AAEJ;AAwBO,MAAMiH,KAAa,CAACC,MAA0B,KAAKA,CAAK,IAClDC,KAAc,CAACtG,MAA4B,KAAKA,CAAO,IACvDuG,KAAiB;AAGvB,SAASC,GACdN,GACA9B,GACAqC,GACAC,GACAC,GACU;AACV,QAAMX,IAAO,CAAC,GAAGE,CAAO;AACxB,MAAIQ,MAAS;AACX,WAAOV,EAAK,KAAK,CAAC1C,GAAG,MAAMqD,EAAS,QAAQvC,EAAKd,CAAC,EAAE,OAAOc,EAAK,CAAC,EAAE,KAAK,CAAC;AAE3E,MAAIsC,MAAS,eAAeA,MAAS,cAAc;AACjD,UAAME,IAAYF,MAAS,cAAc,IAAI;AAC7C,WAAOV,EAAK,KAAK,CAAC1C,GAAGjC,MAAM;;AACzB,YAAMwF,KAAOzB,IAAAqB,EAAOnD,CAAC,MAAR,gBAAA8B,EAAW,OAClB0B,KAAQC,IAAAN,EAAOpF,CAAC,MAAR,gBAAA0F,EAAW;AAEzB,aAAIF,KAAS,OAAmCC,KAAS,OAAO,IAAI,IAChEA,KAAU,OAAoC,MAC1CD,IAAOC,KAASF;AAAA,IAC1B,CAAC;AAAA,EACH;AACA,SAAOZ;AACT;AAGO,SAASgB,GACd5C,GACA6C,GACAC,GACAC,GACW;;AACX,MAAI,CAACD;AACH,WAAOD,EAAc,IAAI,CAAC/B,OAAO;AAAA,MAC/B,MAAM;AAAA,MACN,KAAKkB,GAAWhC,EAAKc,CAAC,EAAE,EAAE;AAAA,MAC1B,UAAUA;AAAA,MACV,SAASd,EAAKc,CAAC,EAAE;AAAA,IAAA,EACjB;AAIJ,QAAMkC,IAAkB,CAAA,GAClBC,wBAAc,IAAA,GACdC,IAAkB,CAAA;AACxB,EAAAlD,EAAK,QAAQ,CAACtE,MAAQ;AACpB,IAAIA,EAAI,UAAU,UAAa,CAACuH,EAAQ,IAAIvH,EAAI,KAAK,MACnDuH,EAAQ,IAAIvH,EAAI,OAAO,CAAA,CAAE,GACzBsH,EAAM,KAAKtH,EAAI,KAAK;AAAA,EAExB,CAAC;AACD,aAAWoF,KAAK+B,GAAe;AAC7B,UAAMjH,IAAUoE,EAAKc,CAAC,EAAE;AACxB,IAAIlF,MAAY,SAAWsH,EAAM,KAAKpC,CAAC,KAClCE,IAAAiC,EAAQ,IAAIrH,CAAO,MAAnB,QAAAoF,EAAsB,KAAKF;AAAA,EAClC;AACA,QAAMqC,IAAkB,CAAA;AACxB,aAAWvH,KAAWoH,GAAO;AAC3B,UAAMI,IAAaH,EAAQ,IAAIrH,CAAO,KAAK,CAAA,GACrCyH,IAAcN,EAAU,IAAInH,CAAO;AAQzC,QAPAuH,EAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,KAAKjB,GAAYtG,CAAO;AAAA,MACxB,SAAAA;AAAA,MACA,WAAWyH;AAAA,MACX,YAAAD;AAAA,IAAA,CACD,GACG,CAACC;AACH,iBAAWvC,KAAKsC;AACd,QAAAD,EAAK,KAAK;AAAA,UACR,MAAM;AAAA,UACN,KAAKnB,GAAWhC,EAAKc,CAAC,EAAE,EAAE;AAAA,UAC1B,UAAUA;AAAA,UACV,SAAAlF;AAAA,QAAA,CACD;AAAA,EAGP;AAEA,aAAWkF,KAAKoC;AACd,IAAAC,EAAK,KAAK,EAAE,MAAM,QAAQ,KAAKnB,GAAWhC,EAAKc,CAAC,EAAE,EAAE,GAAG,UAAUA,GAAG;AAEtE,SAAOqC;AACT;ACxXO,SAASG,GAAe;AAAA,EAC7B,MAAA9H;AAAA,EACA,OAAA+H;AAAA,EACA,MAAAC;AAAA,EACA,cAAAC;AAAA,EACA,MAAAC,IAAO;AAAA,EACP,UAAAC;AACF,GAAwB;AACtB,QAAMC,IAAU7J,GAAA,GACV8J,IAAON,MAASK,KAAA,gBAAAA,EAAS,YAAYpI,OAAS;AACpD,SACE,gBAAAsI;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,OAAOF;AAAA,MACP,MAAAL;AAAA,MACA,cAAAC;AAAA,MACA,MAAAC;AAAA,MACA,eAAe;AAAA,MAEd,UAAAC;AAAA,IAAA;AAAA,EAAA;AAGP;AAEAL,GAAe,cAAc;AAQtB,SAASU,GAAmB;AAAA,EACjC,OAAAT;AAAA,EACA,cAAAE;AACF,GAGG;AACD,2BACGM,IAAA,EAAQ,OAAAR,GAAc,MAAI,IAAC,cAAAE,GAA4B,eAAe,GACrE,UAAA,gBAAAK;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,eAAY;AAAA,MACZ,kBAAe;AAAA,MACf,WAAU;AAAA,IAAA;AAAA,EAAA,GAEd;AAEJ;ACzDO,MAAMG,KAA4B,KAG5BC,KAAW;AAiBjB,SAASC,GACd,EAAE,QAAAC,GAAQ,UAAAC,GAAU,MAAAC,GAAM,OAAAC,GAAO,OAAAhK,EAAA,GACjCiK,IAAWN,IACO;AAClB,MAAI3J,KAAS,EAAG,QAAO,CAAC,GAAG,CAAC;AAC5B,MAAI,EAAEgK,IAAQ,GAAI,QAAO,CAAC,GAAGhK,CAAK;AAClC,QAAMkK,IAAO,KAAK,IAAIL,CAAM,IAAIE,GAC1BI,IAAQ,KAAK,MAAMD,IAAOF,CAAK,IAAIC,GACnCG,IAAO,KAAK,MAAMF,IAAOJ,KAAYE,CAAK,IAAIC,GAC9CI,IAAQ,KAAK,IAAI,GAAG,KAAK,IAAIrK,IAAQ,GAAGmK,CAAK,CAAC,GAC9CG,IAAM,KAAK,IAAID,IAAQ,GAAG,KAAK,IAAIrK,GAAOoK,CAAI,CAAC;AACrD,SAAO,CAACC,GAAOC,CAAG;AACpB;AAoBO,SAASC,GACd/F,GACAxE,GACAwK,GACY;AACZ,QAAM,CAACH,GAAOC,CAAG,IAAI9F,GACfiG,IAAoB,CAAA;AAC1B,WAAS9H,IAAI0H,GAAO1H,IAAI2H,GAAK3H,KAAK,EAAG,CAAA8H,EAAQ,KAAK9H,CAAC;AACnD,SAAI6H,MAAW,QAAQA,IAAS,KAAKA,KAAUxK,IACtC;AAAA,IACL,SAASyK;AAAA,IACT,MAAMJ;AAAA,IACN,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,MAAM,KAAK,IAAI,GAAGrK,IAAQsK,CAAG;AAAA,EAAA,IAG7BE,IAASH,IACJ;AAAA,IACL,SAAS,CAACG,GAAQ,GAAGC,CAAO;AAAA,IAC5B,MAAMD;AAAA,IACN,QAAQH,IAAQG,IAAS;AAAA,IACzB,aAAa;AAAA,IACb,MAAM,KAAK,IAAI,GAAGxK,IAAQsK,CAAG;AAAA,EAAA,IAG7BE,KAAUF,IACL;AAAA,IACL,SAAS,CAAC,GAAGG,GAASD,CAAM;AAAA,IAC5B,MAAMH;AAAA,IACN,QAAQG,IAASF;AAAA,IACjB,aAAaG,EAAQ;AAAA,IACrB,MAAMzK,IAAQwK,IAAS;AAAA,EAAA,IAGpB;AAAA,IACL,SAASC;AAAA,IACT,MAAMJ;AAAA,IACN,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,MAAM,KAAK,IAAI,GAAGrK,IAAQsK,CAAG;AAAA,EAAA;AAEjC;AAGO,SAASI,GAAW1K,GAA2B;AACpD,SAAO;AAAA,IACL,SAAS,MAAM,KAAK,EAAE,QAAQA,KAAS,CAAC2K,GAAGhI,MAAMA,CAAC;AAAA,IAClD,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,MAAM;AAAA,EAAA;AAEV;AAOO,SAASiI,GAAWC,GAAoB7K,GAA2B;AACxE,MAAI6K,EAAO,QAAQ,MAAM,CAACC,MAAUA,IAAQ9K,CAAK,EAAG,QAAO6K;AAC3D,QAAMtD,IAAUsD,EAAO,QAAQ,OAAO,CAACC,MAAUA,IAAQ9K,CAAK;AAC9D,SAAO;AAAA,IACL,SAAAuH;AAAA,IACA,MAAM,KAAK,IAAIsD,EAAO,MAAM7K,CAAK;AAAA,IACjC,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,MAAM,KAAK,IAAI,GAAGA,KAASuH,EAAQ,SAAS,KAAK,IAAIsD,EAAO,MAAM7K,CAAK,EAAE;AAAA,EAAA;AAE7E;AAGO,SAAS+K,GAAWpG,GAAejC,GAAwB;AAIhE,SAHIiC,EAAE,SAASjC,EAAE,QAAQiC,EAAE,SAASjC,EAAE,QAAQiC,EAAE,WAAWjC,EAAE,UAGzDiC,EAAE,QAAQ,WAAWjC,EAAE,QAAQ,SAAe,KAC3CiC,EAAE,QAAQ,MAAM,CAAC7E,GAAO6C,MAAM7C,MAAU4C,EAAE,QAAQC,CAAC,CAAC;AAC7D;AC9HO,MAAMqI,KAAW,CAACC,GAAyBC,MAChD,GAAGD,CAAO,IAAI,KAAK,IAAI,GAAG,KAAK,IAAI,GAAG,KAAK,MAAMC,CAAI,CAAC,CAAC,CAAC,IAMpDC,KAA2C;AAAA,EAC/C,aACE;AAAA,EACF,aACE;AAAA,EACF,aACE;AAAA,EACF,aACE;AAAA,EACF,aACE;AAAA,EACF,aACE;AAAA,EACF,aACE;AAAA,EACF,aACE;AAAA,EACF,aACE;AAAA,EACF,aACE;AAAA,EACF,aACE;AAAA,EACF,aACE;AAAA,EACF,aACE;AAAA,EACF,aACE;AAAA,EACF,aACE;AAAA,EACF,aACE;AAAA,EACF,aACE;AAAA,EACF,aACE;AAAA,EACF,aACE;AAAA,EACF,aACE;AAAA,EACF,iBACE;AAAA,EACF,iBACE;AAAA,EACF,iBACE;AAAA,EACF,iBACE;AAAA,EACF,iBACE;AAAA,EACF,iBACE;AAAA,EACF,iBACE;AAAA,EACF,iBACE;AAAA,EACF,iBACE;AAAA,EACF,iBACE;AAAA,EACF,eACE;AAAA,EACF,eACE;AAAA,EACF,eACE;AAAA,EACF,eACE;AAAA,EACF,eACE;AAAA,EACF,eACE;AAAA,EACF,eACE;AAAA,EACF,eACE;AAAA,EACF,eACE;AAAA,EACF,eACE;AAAA;AAAA;AAAA,EAGF,UACE;AAAA,EACF,OACE;AAAA,EACF,cACE;AAAA,EACF,WACE;AACJ,GAIaC,KAAsBC;AAAA,EACjC;AACF,GAGaC,KAAyBD;AAAA,EACpC;AACF,GAGaE,KAA0BF;AAAA,EACrC;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA;AAAA;AAAA,IAGA;AAAA,EAAA,EACA,KAAK,GAAG;AACZ,GAOaG,KAA2BH;AAAA;AAAA,EAEtC;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,IACT;AAAA,IAEF,iBAAiB,EAAE,QAAQ,GAAA;AAAA,EAAM;AAErC,GAQaI,KAAsBJ;AAAA,EACjC;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,EACA,KAAK,GAAG;AAAA,EACV;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,QACJ,IAAI;AAAA,MAAA;AAAA,MAEN,SAAS;AAAA,QACP,SAAS;AAAA,QACT,SAAS;AAAA,MAAA;AAAA,MAEX,aAAa;AAAA,QACX,MAAM;AAAA,QACN,OACE;AAAA,MAAA;AAAA,MAEJ,cAAc;AAAA,QACZ,MAAM;AAAA,QACN,OACE;AAAA,MAAA;AAAA,IACJ;AAAA,IAEF,iBAAiB;AAAA,MACf,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,MACb,cAAc;AAAA,IAAA;AAAA,EAChB;AAEJ,GAGaK,KAAqBL;AAAA,EAChC;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,QAKR,QACE;AAAA,QACF,QACE;AAAA,QACF,MAAM;AAAA,MAAA;AAAA,IACR;AAAA,IAEF,iBAAiB,EAAE,UAAU,OAAA;AAAA,EAAO;AAExC,GAGaM,KAAwBN,GAAI,0BAA0B;AAAA,EACjE,UAAU;AAAA,IACR,MAAM;AAAA,MACJ,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,cAAc;AAAA;AAAA;AAAA,MAGd,YAAY;AAAA,IAAA;AAAA,EACd;AAEJ,CAAC,GAEKO,KACJ,wMAGWC,KAA8BR;AAAA,EACzC;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACAO;AAAA,EAAA,EACA,KAAK,GAAG;AAAA,EACV;AAAA,IACE,UAAU;AAAA,MACR,QAAQ;AAAA;AAAA,QAEN,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,IACT;AAAA,IAEF,iBAAiB,EAAE,QAAQ,GAAA;AAAA,EAAM;AAErC,GAGaE,KAA2BT;AAAA,EACtC;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA;AAAA;AAAA,IAGA;AAAA;AAAA;AAAA,IAGA;AAAA,IACA;AAAA,IACAO;AAAA,EAAA,EACA,KAAK,GAAG;AAAA,EACV;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,OAAO;AAAA,QACP,OAAO;AAAA,MAAA;AAAA;AAAA;AAAA;AAAA,MAKT,aAAa;AAAA,QACX,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,IACT;AAAA,IAEF,iBAAiB,EAAE,MAAM,QAAQ,aAAa,GAAA;AAAA,EAAM;AAExD,GAGaG,KAA0BV,GAAI,cAAc;AAAA,EACvD,UAAU;AAAA,IACR,aAAa;AAAA,MACX,MAAM;AAAA,MACN,OAAO;AAAA,IAAA;AAAA,EACT;AAAA,EAEF,iBAAiB,EAAE,aAAa,GAAA;AAClC,CAAC,GAeYW,KAAsBX;AAAA,EACjC;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA,EACA,KAAK,GAAG;AAAA,EACV;AAAA,IACE,UAAU;AAAA,MACR,MAAMF;AAAA,MACN,aAAa;AAAA,QACX,MAAM;AAAA,QACN,OAAO;AAAA,MAAA;AAAA,IACT;AAAA,IAEF,iBAAiB,EAAE,MAAM,SAAS,aAAa,GAAA;AAAA,EAAM;AAEzD,GAGac,KAAwBZ;AAAA,EACnC;AACF,GAIaa,KAA2Bb;AAAA,EACtC;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,SAAS;AAAA,QACP,SAAS;AAAA,QACT,YAAY;AAAA,MAAA;AAAA,IACd;AAAA,IAEF,iBAAiB,EAAE,SAAS,UAAA;AAAA,EAAU;AAE1C,GAKac,KAAwBd;AAAA,EACnC;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,MAAMF;AAAA,MACN,OAAO;AAAA,QACL,SACE;AAAA,QACF,YAAY;AAAA,QACZ,KAAK;AAAA,QACL,OACE;AAAA,MAAA;AAAA,IACJ;AAAA,IAEF,iBAAiB,EAAE,MAAM,SAAS,OAAO,MAAA;AAAA,EAAM;AAEnD,GCrUMiB,KAAgB,KAITC,KAAe,CAC1B3E,GACA4E,MACW,GAAG5E,CAAK,GAAG0E,EAAa,GAAG,OAAOE,CAAQ,CAAC,IAG3CC,KAAoB,CAACC,MAAkC;AAClE,QAAMC,IAAKD,EAAI,QAAQJ,EAAa;AACpC,SAAO,CAACI,EAAI,MAAM,GAAGC,CAAE,GAAGD,EAAI,MAAMC,IAAK,CAAC,CAAC;AAC7C;AAgFA,SAASC,GACPzL,GACAiC,GACA+H,GACa;AACb,SAAIhK,EAAK,WAAW,WAAWA,EAAK,UAAU,OAAa,UACvDA,EAAK,WAAW,eAAqB,eACrCgC,GAAWC,GAAOjC,EAAK,KAAK,IAAU,aACnC+J,GAASC,GAAS/H,EAAM,OAAOjC,EAAK,KAAK,CAAC;AACnD;AAEA,SAAS0L,GACPC,GACA7G,GACW;AACX,SAAO;AAAA,IACL,OAAO6G,EAAO;AAAA,IACd,OAAOA,EAAO;AAAA,IACd,QACEA,EAAO,UAAU,OACb,UACA9G,GAAY8G,EAAO,OAAO7G,CAAQ,IAChC,eACA;AAAA,EAAA;AAEZ;AAEA,MAAM8G,KAAgB,CAAC5L,MACrBA,EAAK,WAAW,UAAU,cAAcA,EAAK;AAK/C,SAAS6L,GACPjC,GACAkC,GACgB;AAChB,QAAMC,IAAsB,CAAA;AAC5B,SAAInC,EAAO,OAAO,KAChBmC,EAAI;AAAA,IACF,gBAAAzD;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,eAAY;AAAA,QACZ,WAAWoC,GAAsB,EAAE,MAAM,YAAY;AAAA,MAAA;AAAA,MAFjD;AAAA,IAAA;AAAA,EAGN,GAGJd,EAAO,QAAQ,QAAQ,CAACoC,GAAatK,MAAM;AACzC,IAAIkI,EAAO,SAAS,KAAKlI,MAAMkI,EAAO,eACpCmC,EAAI;AAAA,MACF,gBAAAzD;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,eAAY;AAAA,UACZ,WAAWoC,GAAsB,EAAE,MAAM,cAAc;AAAA,QAAA;AAAA,QAFnD;AAAA,MAAA;AAAA,IAGN,GAGJqB,EAAI,KAAKD,EAAOE,CAAW,CAAC;AAAA,EAC9B,CAAC,GACGpC,EAAO,OAAO,KAChBmC,EAAI;AAAA,IACF,gBAAAzD;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,eAAY;AAAA,QACZ,WAAWoC,GAAsB,EAAE,MAAM,YAAY;AAAA,MAAA;AAAA,MAFjD;AAAA,IAAA;AAAA,EAGN,GAGGqB;AACT;AAkBA,MAAME,KAAiBC,GAAK,SAAwB;AAAA,EAClD,KAAAC;AAAA,EACA,KAAAjM;AAAA,EACA,cAAAkM;AAAA,EACA,aAAAC;AAAA,EACA,WAAAC;AAAA,EACA,YAAAC;AAAA,EACA,cAAAC;AACF,GAAiB;;AACf,QAAM3G,IAAcsG,EAAI,QAAQ,QAC1BM,IAAWC;AAAA,IACf,MACE,IAAI,IAAIF,MAAiB,KAAK,CAAA,IAAKA,EAAa,MAAM,GAAG,EAAE,IAAI,MAAM,CAAC;AAAA,IACxE,CAACA,CAAY;AAAA,EAAA;AAGf,MAAItM,EAAI,SAAS,SAAS;AACxB,UAAMK,IAAY4L,EAAI,UAAU,WAAWjM,EAAI,OAAO,GAGhDyM,IAASR,EAAI,SAAS,IAAIjM,EAAI,OAAO,GACrC0M,IAAU,GAAGT,EAAI,MAAM,UAAUC,CAAY,IAC7C7F,MAAYf,IAAA2G,EAAI,WAAJ,gBAAA3G,EAAY,aAAa,IAAItF,EAAI,aAAY,CAAA,GACzD2M,MAAU1F,IAAAgF,EAAI,WAAJ,gBAAAhF,EAAY,OAAO,IAAIjH,EAAI,UAGrC4M,IAAY,CAChBnB,GACApG,GACAwC,IACAgF,OACG;AACH,YAAM/M,IAAO0L,GAAcC,KAAU,EAAE,OAAO,KAAA,GAAQQ,EAAI,QAAQ,GAC5Da,IAAOjF,GAAM/H,CAAI;AACvB,aACE,gBAAAiN;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,MAAK;AAAA,UACL,iBAAe1H,IAAI;AAAA,UACnB,iBAAe,CAACrF,EAAI;AAAA,UACpB,cAAY8M;AAAA,UACZ,UAAUV,MAAc/G,IAAI,IAAI;AAAA,UAChC,yBAAuBoH;AAAA,UACvB,WAAW5B,GAAoB;AAAA,YAC7B,MAAMa,GAAc5L,CAAI;AAAA,YACxB,aAAa;AAAA,UAAA,CACd;AAAA,UAEA,UAAA;AAAA,YAAAmM,EAAI,UAAU,YAAYnM,CAAI;AAAA,YAC9B+M,MAAeR,MAAehH,IAC7B,gBAAA+C;AAAA,cAACE;AAAA,cAAA;AAAA,gBACC,OAAOwE;AAAA,gBACP,cAAcb,EAAI;AAAA,cAAA;AAAA,YAAA,IAElB;AAAA,UAAA;AAAA,QAAA;AAAA,QAlBC5G;AAAA,MAAA;AAAA,IAqBX,GACM2H,IAAmBf,EAAI,UAAU;AAAA,MACrC5L;AAAA,MACA4L,EAAI;AAAA,IAAA;AAEN,WACE,gBAAAc;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,iBAAeb;AAAA,QACf,yBAAsB;AAAA,QACtB,yBAAuBO;AAAA,QACvB,WAAWlC,GAAmB,EAAE,UAAU,QAAQ;AAAA,QAElD,UAAA;AAAA,UAAA,gBAAAwC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,iBAAe;AAAA,cAGf,mBAAiBL;AAAA,cACjB,oBAAkBP;AAAA,cAClB,WAAWxB,GAAyB;AAAA,gBAClC,MAAM;AAAA,gBACN,aAAasB,EAAI;AAAA,cAAA,CAClB;AAAA,cAWD,UAAA;AAAA,gBAAA,gBAAA7D;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,MAAK;AAAA,oBACL,UAAU;AAAA,oBACV,iBAAe,CAACpI,EAAI;AAAA,oBACpB,cACEA,EAAI,YACAiM,EAAI,YAAY5L,CAAS,IACzB4L,EAAI,cAAc5L,CAAS;AAAA,oBAEjC,aAAa,CAAC4M,MAAUA,EAAM,eAAA;AAAA,oBAC9B,SAAS,MAAMhB,EAAI,cAAcjM,EAAI,OAAO;AAAA,oBAC5C,WAAU;AAAA,oBAEV,UAAA,gBAAAoI;AAAA,sBAAC8E;AAAA,sBAAA;AAAA,wBACC,eAAY;AAAA,wBACZ,WAAW;AAAA,0BACT;AAAA,0BACAlN,EAAI,YAAY,mCAAmC;AAAA,wBAAA,EACnD,KAAK,GAAG;AAAA,sBAAA;AAAA,oBAAA;AAAA,kBACZ;AAAA,gBAAA;AAAA,gBAEF,gBAAAoI;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,IAAIsE;AAAA,oBACJ,WAAW9B,GAAwB;AAAA,sBACjC,aAAaqB,EAAI;AAAA,oBAAA,CAClB;AAAA,oBAEA,UAAA5L;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACH;AAAA,YAAA;AAAA,UAAA;AAAA,UAEDsL;AAAA,YAAcM,EAAI;AAAA,YAAW,CAAC5G,MAC7BuH;AAAA,cACEvG,EAAUhB,CAAC;AAAA,cACXA;AAAA,cACA,CAACvF,MACCmM,EAAI,UAAU;AAAA,gBACZe;AAAA,gBACAf,EAAI,UAAU,YAAYA,EAAI,QAAQ5G,CAAC,CAAC;AAAA,gBACxCvF;AAAA,cAAA;AAAA,cAEJ;AAAA,YAAA;AAAA,UACF;AAAA,UAEDmM,EAAI,YACDW;AAAA,YACED;AAAA,YACAhH;AAAA,YACA,CAAC7F,MACCmM,EAAI,UAAU;AAAA,cACZ5L;AAAA,cACA4L,EAAI,UAAU,YAAYA,EAAI,aAAa,MAAM;AAAA,cACjDnM;AAAA,YAAA;AAAA,YAEJ;AAAA,UAAA,IAEF;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGV;AAEA,QAAMsF,IAAIpF,EAAI,UACRmN,IAASlB,EAAI,KAAK7G,CAAC,GACnBjF,IAAU8L,EAAI,UAAU,SAASkB,CAAM,GACvCvJ,IAAQqI,EAAI,OAAO7G,CAAC,GAEpBgI,IAAW,CAAC/H,MAAc;AAC9B,UAAMvF,IAAO8D,EAAMyB,CAAC,GACdpF,IAASgM,EAAI,QAAQ5G,CAAC,GACtBgI,IAAad,EAAS,IAAIlH,CAAC;AACjC,WACE,gBAAA0H;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL,iBAAe1H,IAAI;AAAA,QACnB,cAAY4G,EAAI,UAAU;AAAA,UACxB9L;AAAA,UACA8L,EAAI,UAAU,YAAYhM,CAAM;AAAA,UAChCH;AAAA,QAAA;AAAA,QAEF,oBAAkBsM,MAAc/G,IAAI4G,EAAI,cAAc;AAAA,QACtD,iBAAeA,EAAI,aAAaoB,IAAa;AAAA,QAC7C,UAAUjB,MAAc/G,IAAI,IAAI;AAAA,QAChC,wBAAsB,GAAG8H,EAAO,EAAE,IAAI,OAAOlN,EAAO,EAAE,CAAC;AAAA,QACvD,eAAaH,EAAK;AAAA,QAClB,WAAW+K,GAAoB;AAAA,UAC7B,MAAMU,GAAOzL,GAAMmM,EAAI,OAAOA,EAAI,OAAO;AAAA,UACzC,aAAaA,EAAI;AAAA,QAAA,CAClB;AAAA,QAEA,UAAA;AAAA,UAAAA,EAAI,cAAcnM,EAAK,WAAW,UAC/BmM,EAAI,UAAU,YAAYnM,CAAI,IAC9B;AAAA,UACHuM,MAAehH,IACd,gBAAA+C;AAAA,YAACE;AAAA,YAAA;AAAA,cACC,OAAO2D,EAAI,YAAYA,EAAI,SAAS7G,GAAGC,CAAC,CAAC;AAAA,cACzC,cAAc4G,EAAI;AAAA,YAAA;AAAA,UAAA,IAElB;AAAA,QAAA;AAAA,MAAA;AAAA,MA1BC5G;AAAA,IAAA;AAAA,EA6BX;AAEA,MAAIiI,IAAiC;AACrC,MAAIrB,EAAI,aAAaA,EAAI,QAAQ;AAC/B,UAAMnM,IAAO0L,GAAcS,EAAI,OAAO,KAAK7G,CAAC,GAAG6G,EAAI,QAAQ;AAC3D,IAAAqB,IACE,gBAAAlF;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAK;AAAA,QACL,iBAAezC,IAAc;AAAA,QAC7B,cAAYsG,EAAI,UAAU;AAAA,UACxB9L;AAAA,UACA8L,EAAI,UAAU,YAAYA,EAAI,SAAS;AAAA,UACvCnM;AAAA,QAAA;AAAA,QAEF,UAAUsM,MAAczG,IAAc,IAAI;AAAA,QAC1C,WAAWkF,GAAoB,EAAE,MAAMa,GAAc5L,CAAI,GAAG;AAAA,QAE3D,UAAAmM,EAAI,UAAU,YAAYnM,CAAI;AAAA,MAAA;AAAA,IAAA;AAAA,EAGrC;AAEA,SACE,gBAAAiN;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,iBAAeb;AAAA,MACf,yBAAsB;AAAA,MACtB,uBAAqBiB,EAAO;AAAA,MAC5B,WAAW5C,GAAmB,EAAE,UAAU,QAAQ;AAAA,MAElD,UAAA;AAAA,QAAA,gBAAAnC;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,iBAAe;AAAA,YACf,oBAAkB+D;AAAA,YAClB,WAAWxB,GAAyB;AAAA,cAClC,MAAM;AAAA,cACN,aAAasB,EAAI;AAAA,YAAA,CAClB;AAAA,YAED,UAAA,gBAAA7D;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,WAAWwC,GAAwB,EAAE,aAAaqB,EAAI,aAAa;AAAA,gBAElE,UAAA9L;AAAA,cAAA;AAAA,YAAA;AAAA,UACH;AAAA,QAAA;AAAA,QAEDwL,GAAcM,EAAI,WAAWmB,CAAQ;AAAA,QACrCE;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGP,CAAC,GAgBKC,KAA2B;AAAA,EAC/B,aAAa;AAAA,EACb,aAAa;AAAA,EACb,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,UAAU;AAAA,EACV,eAAe;AAAA,EACf,gBAAgB;AAClB,GAEMC,KAAW,CAACC,MAChB,KAAK;AAAA,EACH;AAAA,EACA,KAAK;AAAA,KACFA,EAAQ,gBAAgBA,EAAQ,cAAcA,EAAQ,eACrD,KAAK,IAAI,GAAGA,EAAQ,QAAQ;AAAA,EAAA;AAElC;AAEK,SAASC,GAAYC,GAAyB;AACnD,QAAM;AAAA,IACJ,OAAAC;AAAA,IACA,WAAAC;AAAA,IACA,MAAAvJ;AAAA,IACA,SAAAY;AAAA,IACA,QAAAM;AAAA,IACA,MAAAiC;AAAA,IACA,OAAA1F;AAAA,IACA,SAAA+H;AAAA,IACA,WAAAgE;AAAA,IACA,YAAAC;AAAA,IACA,QAAApH;AAAA,IACA,WAAAZ;AAAA,IACA,cAAAC;AAAA,IACA,mBAAAF;AAAA,IACA,UAAAkI;AAAA,IACA,UAAApJ;AAAA,IACA,eAAAqJ;AAAA,IACA,UAAA1B;AAAA,IACA,kBAAA2B;AAAA,IACA,aAAAC;AAAA,IACA,aAAAC;AAAA,IACA,MAAAC;AAAA,IACA,SAAAC;AAAA,IACA,UAAAC;AAAA,IACA,aAAAC;AAAA,IACA,iBAAAC;AAAA,IACA,YAAAC;AAAA,IACA,SAAAC;AAAA,IACA,eAAAC;AAAA,EAAA,IACEjB,GACE,EAAE,GAAA3O,EAAA,IAAM6P,GAAe,IAAI,GAC3BC,KAASC,GAAA,GACTC,IAAcC,EAAuB,IAAI,GACzCC,IAAUD,EAAuB,IAAI,GACrCE,KAAYF,EAAuB,IAAI,GACvCG,KAAYH,EAAuB,IAAI,GAEvCtJ,IAAcT,EAAQ,QACtBmK,KAAiB1J,KAAeI,IAAY,IAAI,IAChDuJ,IAAY,GAAQtJ,KAAgBW,IACpC4I,KAAa/C;AAAA,IACjB,MAAM;AAAA,MACJ,GAAG/E,EAAK,IAAI,CAACzH,MAAQA,EAAI,GAAG;AAAA,MAC5B,GAAIsP,IAAY,CAAC7I,EAAc,IAAI,CAAA;AAAA,IAAC;AAAA,IAEtC,CAACgB,GAAM6H,CAAS;AAAA,EAAA,GAEZE,KAAgBhD,EAAQ,MAAM;AAClC,UAAMiD,wBAAU,IAAA;AAChB,WAAAF,GAAW,QAAQ,CAAClE,GAAK7J,MAAMiO,EAAI,IAAIpE,GAAK7J,CAAC,CAAC,GACvCiO;AAAA,EACT,GAAG,CAACF,EAAU,CAAC,GAGT,CAACG,GAAQC,EAAS,IAAIC,GAAuB,OAAO;AAAA,IACxD,QAAQL,GAAW,CAAC,KAAK9I;AAAA,IACzB,KAAK;AAAA,EAAA,EACL,GAGIoJ,MAAa,MAAM;AACvB,UAAMC,IAAQN,GAAc,IAAIE,EAAO,MAAM;AAC7C,QAAII,MAAU,OAAW,QAAOA;AAChC,UAAMC,IAASzL,EAAK,KAAK,CAACtE,MAAQ,KAAKA,EAAI,EAAE,OAAO0P,EAAO,MAAM;AAKjE,aAHEK,KAAA,gBAAAA,EAAQ,WAAU,SACd,SACAP,GAAc,IAAI,KAAKO,EAAO,KAAK,EAAE,MAC1B;AAAA,EACnB,GAAA,GACM3D,IAAY,KAAK;AAAA,IACrB,KAAK,IAAI,GAAGsD,EAAO,GAAG;AAAA,IACtB,KAAK,IAAI,GAAGL,KAAiB,CAAC;AAAA,EAAA,GAE1BW,KAAYT,GAAWM,EAAS,GAEhCI,KAAehB,EAAO,EAAK,GAC3B,CAACiB,IAAUC,CAAW,IAAIP,GAAS,EAAK,GACxCQ,KAAcnB,EAAO,EAAK,GAC1BoB,KAAcpB,EAA+B,SAAS,GAGtD,CAACqB,IAAOC,EAAQ,IAAIX,GAA8B,IAAI,GACtDY,KAAWvB,EAA4B,IAAI,GAC3C,CAACwB,IAAkBC,EAAmB,IAAId,GAAS,EAAK,GACxDe,KAAcC,EAAY,CAAC1S,MAA8B;AAC7D,UAAM2S,IAAUL,GAAS;AACzB,IACEK,MAAY3S,KACX2S,KACC3S,KACA2S,EAAQ,WAAW3S,EAAK,UACxB2S,EAAQ,QAAQ3S,EAAK,QAIzBsS,GAAS,UAAUtS,GACnBqS,GAASrS,CAAI,GACbwS,GAAoB,EAAK;AAAA,EAC3B,GAAG,CAAA,CAAE,GAGCI,IACJR,OACCJ,MAAYF,KAAY,EAAE,QAAQA,IAAW,KAAK5D,EAAA,IAAc,OAE7D2E,KAAiCN,KACnC,OACCH,OACAJ,MAAYG,GAAY,YAAY,cAAcL,KAC/C,EAAE,QAAQA,IAAW,KAAK5D,MAC1B,OAGF,CAACqB,IAASuD,EAAU,IAAIpB,GAAkBrC,EAAe,GACzD0D,KAAahC,EAAOxB,EAAO;AACjC,EAAAwD,GAAW,UAAUxD;AAErB,QAAMyD,KAAUN,EAAY,MAAM;;AAChC,UAAMO,IAAWnC,EAAY,SACvBoC,IAAOlC,EAAQ;AACrB,QAAI,CAACiC,KAAY,CAACC,EAAM;AACxB,UAAMC,IAAQ,OAAO,iBAAiBD,CAAI,GACpCE,IAAS,WAAWD,EAAM,MAAM,KAAK,GACrCE,IAAY,WAAWF,EAAM,SAAS,KAAK,GAC3CG,IAASH,EAAM,oBAClB,MAAM,GAAG,EACT,IAAI,CAACI,OAAU,WAAWA,EAAK,CAAC,EAChC,OAAO,CAACA,OAAU,OAAO,SAASA,EAAK,CAAC,GACrCC,MAAepM,IAAA6J,GAAU,YAAV,gBAAA7J,EAAmB,wBAAwB,WAAU,GACpEqM,KAAYP,EAAK;AAAA,MACrB;AAAA,IAAA,GAEIQ,MAAaD,MAAA,gBAAAA,GAAW,wBAAwB,WAAU,GAC1DzT,KAAgB;AAAA,MACpB,aAAawT,IAAeJ;AAAA,MAC5B,eAAarK,KAAAmI,GAAU,YAAV,gBAAAnI,GAAmB,wBAAwB,WAAU;AAAA,MAClE,WACG2K,MAAcF,KAAgBnE,GAAgB,YAAY+D;AAAA,MAC7D,aAAaE,EAAO,CAAC,KAAK,KAAKD;AAAA,MAC/B,WAAWC,EAAO,CAAC,KAAKjE,GAAgB,YAAYgE;AAAA,MACpD,eAAeJ,EAAS;AAAA,MACxB,gBAAgBA,EAAS;AAAA,IAAA,GAErBN,KAAUI,GAAW;AAC3B,IACG,OAAO,KAAK/S,EAAI,EAAwB;AAAA,MACvC,CAACmN,OAAQ,KAAK,IAAInN,GAAKmN,EAAG,IAAIwF,GAAQxF,EAAG,CAAC,IAAI;AAAA,IAAA,KAGhD2F,GAAW9S,EAAI;AAAA,EAEnB,GAAG,CAAA,CAAE;AAEL,EAAA2T,GAA0B,MAAM;AAC9B,IAAAX,GAAA;AACA,UAAMC,IAAWnC,EAAY;AAC7B,QAAI,CAACmC,KAAY,OAAO,iBAAmB,IAAa;AACxD,UAAMW,IAAW,IAAI,eAAe,MAAMZ,IAAS;AACnD,WAAAY,EAAS,QAAQX,CAAQ,GACrBjC,EAAQ,WAAS4C,EAAS,QAAQ5C,EAAQ,OAAO,GAC9C,MAAM4C,EAAS,WAAA;AAAA,EACxB,GAAG,CAACZ,IAASzJ,EAAK,QAAQ9B,GAAa0I,IAAMC,CAAO,CAAC;AAErD,QAAMyD,KAAY/B,OAAcvJ,KAAiB,OAAOoJ,IAClDmC,KAAY5F,IAAYzG,IAAcyG,IAAY,MAElD6F,KAAiBrB,EAAY,MAG9B;AACH,QAAI,CAACxC;AACH,aAAO,EAAE,MAAM7E,GAAW9B,EAAK,MAAM,GAAG,MAAM8B,GAAW5D,CAAW,EAAA;AAEtE,UAAMwL,IAAWnC,EAAY,SACvBkD,IAAIjB,GAAW,SACfkB,IAAW1J,GAAa;AAAA,MAC5B,SAAQ0I,KAAA,gBAAAA,EAAU,cAAa;AAAA,MAC/B,UAAUe,EAAE;AAAA,MACZ,MAAMA,EAAE;AAAA,MACR,OAAOA,EAAE;AAAA,MACT,OAAOzK,EAAK;AAAA,IAAA,CACb,GACK2K,IAAW3J,GAAa;AAAA,MAC5B,SAAQ0I,KAAA,gBAAAA,EAAU,eAAc;AAAA,MAChC,UAAUe,EAAE;AAAA,MACZ,MAAMA,EAAE;AAAA,MACR,OAAOA,EAAE;AAAA,MACT,OAAOvM;AAAA,IAAA,CACR;AACD,WAAO;AAAA,MACL,MAAMyD,GAAW+I,GAAU1K,EAAK,QAAQsK,EAAS;AAAA,MACjD,MAAM3I,GAAWgJ,GAAUzM,GAAaqM,EAAS;AAAA,IAAA;AAAA,EAErD,GAAG,CAAC5D,GAAa3G,EAAK,QAAQ9B,GAAaoM,IAAWC,EAAS,CAAC,GAE1D,CAACK,IAAaC,EAAU,IAAI1C,GAASqC,EAAc,GAKnDM,KAAW/F,EAAQ,MAAMjD,GAAW9B,EAAK,MAAM,GAAG,CAACA,EAAK,MAAM,CAAC,GAC/D+K,KAAWhG,EAAQ,MAAMjD,GAAW5D,CAAW,GAAG,CAACA,CAAW,CAAC,GAC/D8M,KAAUjG;AAAA,IACd,MACE4B,IACI;AAAA,MACE,MAAM3E,GAAW4I,GAAY,MAAM5K,EAAK,MAAM;AAAA,MAC9C,MAAMgC,GAAW4I,GAAY,MAAM1M,CAAW;AAAA,IAAA,IAEhD,EAAE,MAAM4M,IAAU,MAAMC,GAAA;AAAA,IAC9B,CAACpE,GAAaiE,IAAa5K,EAAK,QAAQ9B,GAAa4M,IAAUC,EAAQ;AAAA,EAAA,GAEnEE,KAAc9B,EAAY,MAAM;AACpC,UAAM1S,IAAO+T,GAAA;AACb,IAAAK;AAAA,MAAW,CAACzB,MACVjH,GAAWiH,EAAQ,MAAM3S,EAAK,IAAI,KAAK0L,GAAWiH,EAAQ,MAAM3S,EAAK,IAAI,IACrE2S,IACA3S;AAAA,IAAA;AAAA,EAER,GAAG,CAAC+T,EAAc,CAAC;AACnB,EAAAJ,GAA0B,MAAM;AAC9B,IAAAa,GAAA;AAAA,EACF,GAAG,CAACA,IAAajF,EAAO,CAAC;AAEzB,QAAMkF,KAAQ1D,EAAO,CAAC,GAChB2D,KAAWhC,EAAY,MAAM;AACjC,IAAI,CAACxC,KAAeuE,GAAM,YAC1BA,GAAM,UAAU,OAAO,sBAAsB,MAAM;AACjD,MAAAA,GAAM,UAAU,GAChBD,GAAA;AAAA,IACF,CAAC;AAAA,EACH,GAAG,CAACtE,GAAasE,EAAW,CAAC;AAC7B,EAAAG,GAAU,MAAM,MAAM,OAAO,qBAAqBF,GAAM,OAAO,GAAG,EAAE,GAKpEd,GAA0B,MAAM;AAC9B,IAAI7B,OAAc,UAAaA,OAAcN,EAAO,UAClDC,GAAU,EAAE,QAAQK,IAAW,KAAK5D,GAAW;AAAA,EAEnD,CAAC,GAIDyF,GAA0B,MAAM;AAC9B,QAAI,CAACzB,GAAY,WAAWH,GAAa,QAAS;AAClD,UAAMY,IAAU,SAAS;AACzB,IAAIA,KAAWA,MAAY,SAAS,QAAQA,EAAQ,gBACpDZ,GAAa,UAAU;AAAA,EACzB,CAAC;AAED,QAAM6C,KAAclC;AAAA,IAClB,CAACmC,GAAkBC;;AACjB,eAAA1N,IAAA4J,EAAQ,YAAR,gBAAA5J,EAAiB;AAAA,QACf,+BAA+ByN,IAAW,CAAC,wBAAwBC,IAAM,CAAC;AAAA,YACvE;AAAA;AAAA,IACP,CAAA;AAAA,EAAC;AAGH,EAAAnB,GAA0B,MAAM;;AAC9B,QAAI,CAAC5B,GAAa,QAAS;AAC3B,UAAMgD,IAAUH,GAAYjD,IAAWzD,CAAS;AAChD,IAAK6G,MACLhD,GAAa,UAAU,IACvBgD,EAAQ,MAAM,EAAE,eAAe,GAAA,CAAM,IACrC3N,IAAA2N,EAAQ,mBAAR,QAAA3N,EAAA,KAAA2N,GAAyB,EAAE,OAAO,WAAW,QAAQ;EACvD,CAAC;AAED,QAAMC,KAAQ,MACZhE,EAAQ,UACJ,OAAO,iBAAiBA,EAAQ,OAAO,EAAE,cAAc,QACvD,IAGAiE,IAASlE,EAAiD,IAAI,GAC9DmE,KAAiB,CAACC,MAAoC;AAC1D,UAAMrT,IAAMyH,EAAK4L,CAAQ;AACzB,WAAOrT,KAAOA,EAAI,SAAS,SAASA,EAAI,WAAW;AAAA,EACrD,GAIMsT,KAAerE,EAAO,EAAK,GAE3BsE,KAAS,CAACR,GAAkBC,MAAgB;AAChD,UAAMQ,IAAa,KAAK,IAAI,GAAG,KAAK,IAAIjE,GAAW,SAAS,GAAGwD,CAAQ,CAAC,GAClEU,IAAa,KAAK,IAAI,GAAG,KAAK,IAAIpE,KAAiB,GAAG2D,CAAG,CAAC;AAChE,WAAA/C,GAAa,UAAU,IACvBS,GAAoB,EAAK,GACzBf,GAAU,EAAE,QAAQJ,GAAWiE,CAAU,GAAG,KAAKC,GAAY,GACtD,EAAE,KAAKD,GAAY,KAAKC,EAAA;AAAA,EACjC,GAGMC,KAAW,CAACL,GAAkBL,GAAaW,MAAoB;AACnE,UAAM3T,IAAMyH,EAAK4L,CAAQ;AACzB,QAAKrT,GACL;AAAA,UAAIA,EAAI,SAAS,SAAS;AACxB,QAAA4O,EAAc5O,EAAI,OAAO;AACzB;AAAA,MACF;AACA,UAAI,EAAAgT,KAAOrN,IACX;AAAA,YAAIsI,MAAkB,WAAW0F,KAAUR,EAAO,SAAS;AACzD,UAAAxE,GAAQwE,EAAO,SAAS,EAAE,UAAUnT,EAAI,UAAU,KAAAgT,GAAK;AACvD;AAAA,QACF;AACA,QAAAG,EAAO,UAAU,EAAE,UAAUnT,EAAI,UAAU,KAAAgT,EAAA,GAC3CtE,GAAW1O,EAAI,UAAUgT,GAAK,EAAI;AAAA;AAAA;AAAA,EACpC,GAEMY,KAAY,CAAC3G,MAAyC;AAK1D,QAAIA,EAAM,kBAAkB,WAAWA,EAAM,OAAO,QAAQ,QAAQ;AAClE;AAEF,IAAAoD,GAAY,UAAU;AACtB,UAAMwD,IAAUtE,GAAW,SAAS,GAC9BuE,IAAUzE,KAAiB,GAC3B0E,IAAUb,OAAU,KAAK;AAC/B,QAAIlT,IAAM6P,IACNmD,IAAM5G;AACV,UAAM4H,IAAO/G,EAAM,WAAWA,EAAM;AACpC,YAAQA,EAAM,KAAA;AAAA,MACZ,KAAK;AACH,QAAA+F,KAAOe;AACP;AAAA,MACF,KAAK;AACH,QAAAf,KAAOe;AACP;AAAA,MACF,KAAK;AACH,QAAA/T,KAAO;AACP;AAAA,MACF,KAAK;AACH,QAAAA,KAAO;AACP;AAAA,MACF,KAAK;AACH,QAAAgT,IAAM,GACFgB,MAAMhU,IAAM;AAChB;AAAA,MACF,KAAK;AACH,QAAAgT,IAAMc,GACFE,MAAMhU,IAAM6T;AAChB;AAAA,MACF,KAAK,YAAY;AACf,cAAMI,KAAYxM,EAAK;AAAA,UACrB,CAACrC,GAAG5D,OAAMA,KAAIqO,MAAazK,EAAE,SAAS;AAAA,QAAA;AAGxC,QAAApF,IADkByH,EAAK,KAAK,CAACrC,MAAMA,EAAE,SAAS,OAAO,IAEjD6O,OAAc,KACZJ,IACAI,KACFpE,KAAYrC,GAASyD,GAAW,OAAO;AAC3C;AAAA,MACF;AAAA,MACA,KAAK,UAAU;AACb,YAAIiD,KAAW;AACf,iBAAS1S,IAAI,KAAK,IAAIqO,IAAWpI,EAAK,MAAM,IAAI,GAAGjG,KAAK,GAAGA,KAAK;AAC9D,cAAIiG,EAAKjG,CAAC,EAAE,SAAS,SAAS;AAC5B,YAAA0S,KAAW1S;AACX;AAAA,UACF;AAGF,QAAAxB,IADkByH,EAAK,KAAK,CAACrC,MAAMA,EAAE,SAAS,OAAO,IAEjD8O,OAAa,KACX,IACAA,KACFrE,KAAYrC,GAASyD,GAAW,OAAO;AAC3C;AAAA,MACF;AAAA,MACA,KAAK;AAAA,MACL,KAAK;AACH,QAAAhE,EAAM,eAAA,GACNyG,GAAS7D,IAAWzD,GAAWa,EAAM,QAAQ;AAC7C;AAAA,MACF,KAAK;AACH,QAAI8D,OACF9D,EAAM,eAAA,GACNyD,GAAoB,EAAI;AAE1B;AAAA,MACF;AACE;AAAA,IAAA;AAEJ,IAAAzD,EAAM,eAAA;AACN,UAAMkH,KAAQZ,GAAOvT,GAAKgT,CAAG,GACvBoB,KAAUnH,EAAM,IAAI,WAAW,OAAO;AAC5C,QAAIgB,MAAkB,WAAWhB,EAAM,YAAYmH,IAAS;AAC1D,YAAMC,KAASjB,GAAee,GAAM,GAAG,GACjCpL,KACJoK,EAAO,YACN,MAAM;AACL,cAAMjK,IAAQkK,GAAevD,EAAS;AACtC,eAAO3G,MAAU,QAAQkD,KAAazG,IAClC,OACA,EAAE,UAAUuD,GAAO,KAAKkD,EAAA;AAAA,MAC9B,GAAA;AACF,MAAIrD,MAAQsL,OAAW,QAAQF,GAAM,MAAMxO,MACzCwN,EAAO,UAAUpK,IACjB4F,GAAQ5F,IAAM,EAAE,UAAUsL,IAAQ,KAAKF,GAAM,KAAK;AAAA,IAEtD;AAAA,EACF,GAGMG,KAAa,CACjBD,MACwC;;AACxC,QAAI,EAAEA,aAAkB,SAAU,QAAO;AACzC,UAAMvU,IAAOuU,EAAO,QAAqB,mBAAmB,GACtDE,IAAazU,KAAA,gBAAAA,EAAM;AACzB,QAAI,CAACA,KAAQ,CAACyU,KAAc,GAACjP,IAAA4J,EAAQ,YAAR,QAAA5J,EAAiB,SAASxF,IAAO,QAAO;AACrE,UAAMiT,IAAW,OAAOwB,EAAW,aAAa,eAAe,CAAC,IAAI,GAC9DvB,IAAM,OAAOlT,EAAK,aAAa,eAAe,CAAC,IAAI;AACzD,WAAI,CAAC,OAAO,UAAUiT,CAAQ,KAAKA,IAAW,KAAKC,IAAM,IAAU,OAC5D,EAAE,KAAKD,GAAU,KAAAC,EAAA;AAAA,EAC1B,GAEMwB,KAAWvF,EAAO,EAAK,GACvBwF,KAAcxF,EAAe,OAAO,GAEpCyF,KAAgB,CAACzH,MAAwC;AAG7D,QAFAoD,GAAY,UAAU,WACtBoE,GAAY,UAAUxH,EAAM,aAE1BgB,MAAkB,WAClBhB,EAAM,gBAAgB,WACtBA,EAAM,WAAW;AAEjB;AAEF,UAAM7K,IAAWkS,GAAWrH,EAAM,MAAM;AAExC,QADAqG,GAAa,UAAU,IACnB,CAAClR,EAAU;AACf,UAAM2Q,IAAWK,GAAehR,EAAS,GAAG;AAC5C,QAAI2Q,MAAa,QAAQ3Q,EAAS,OAAOuD,EAAa;AACtD,QAAIsH,EAAM,YAAYkG,EAAO;AAC3B,MAAAxE,GAAQwE,EAAO,SAAS,EAAE,UAAAJ,GAAU,KAAK3Q,EAAS,KAAK;AAAA,SAClD;AACL,MAAA+Q,EAAO,UAAU,EAAE,UAAAJ,GAAU,KAAK3Q,EAAS,IAAA;AAC3C,YAAMiJ,IAAMH,GAAa5G,EAAKyO,CAAQ,EAAE,IAAI7N,EAAQ9C,EAAS,GAAG,EAAE,EAAE;AACpE,MAAImK,EAAS,SAAS,KAAKA,EAAS,IAAIlB,CAAG,IAGzCiI,GAAa,UAAU,KAEvB3E,GAAQwE,EAAO,SAASA,EAAO,OAAO;AAAA,IAE1C;AACA,IAAAqB,GAAS,UAAU;AACnB,UAAMG,IAAO,MAAM;AACjB,MAAAH,GAAS,UAAU,IACnB,OAAO,oBAAoB,aAAaG,CAAI,GAC5C,OAAO,oBAAoB,iBAAiBA,CAAI;AAAA,IAClD;AACA,WAAO,iBAAiB,aAAaA,CAAI,GACzC,OAAO,iBAAiB,iBAAiBA,CAAI;AAAA,EAC/C,GAEMC,KAAgB,CAAC3H,MAAwC;AAC7D,QAAIA,EAAM,gBAAgB,QAAS;AACnC,UAAM7K,IAAWkS,GAAWrH,EAAM,MAAM;AAIxC,QAHA0D;AAAA,MACEvO,IAAW,EAAE,QAAQmN,GAAWnN,EAAS,GAAG,GAAG,KAAKA,EAAS,QAAQ;AAAA,IAAA,GAEnEoS,GAAS,WAAWpS,KAAY+Q,EAAO,SAAS;AAClD,YAAMJ,IAAWK,GAAehR,EAAS,GAAG;AAC5C,MAAI2Q,MAAa,QAAQ3Q,EAAS,MAAMuD,OAEpCoN,MAAaI,EAAO,QAAQ,YAC5B/Q,EAAS,QAAQ+Q,EAAO,QAAQ,SAEhCG,GAAa,UAAU,KAEpBA,GAAa,WAChB3E,GAAQwE,EAAO,SAAS,EAAE,UAAAJ,GAAU,KAAK3Q,EAAS,KAAK;AAAA,IAG7D;AAAA,EACF,GAKMyS,KAAe5F,EAEnB,IAAI,GACA6F,KAAWlE,EAAY,MAAM;AACjC,IAAKiE,GAAa,YAClB,SAAS,oBAAoB,eAAeA,GAAa,OAAO,GAChEA,GAAa,UAAU;AAAA,EACzB,GAAG,CAAA,CAAE;AACL,EAAAhC,GAAU,MAAMiC,IAAU,CAACA,EAAQ,CAAC;AAEpC,QAAMC,KAAiB,CAAC9H,MAAwC;AAG9D,IAAA6H,GAAA;AACA,UAAM5W,IAAO+O,EAAM;AACnB,QAAI/O,aAAgB,WAAWA,EAAK,QAAQ,4BAA4B,GAAG;AACzE,YAAM8W,IAAO,CAACb,MAAmC;;AAC/C,cAAMc,IAAOd,EAAM;AACnB,QACEc,aAAgB,WAChBA,EAAK,QAAQ,4BAA4B,MAI3CH,GAAA,GACMG,aAAgB,UAAQ3P,IAAA4J,EAAQ,YAAR,QAAA5J,EAAiB,SAAS2P,OACtDtE,GAAY,IAAI;AAAA,MAEpB;AACA,MAAAkE,GAAa,UAAUG,GACvB,SAAS,iBAAiB,eAAeA,CAAI;AAC7C;AAAA,IACF;AACA,IAAArE,GAAY,IAAI;AAAA,EAClB,GAEMuE,KAAU,CAACjI,MAAsC;;AACrD,UAAMkI,IACJlI,EAAM,kBAAkB,UAAUA,EAAM,OAAO,QAAQ,QAAQ,IAAI;AACrE,QAAIkI,GAAQ;AAGV,YAAM9B,IACJ,QAAO/N,IAAA6P,EAAO,QAAQ,cAAc,MAA7B,gBAAA7P,EAAgC,aAAa,gBAAgB,IACpE;AAEF,MAAI,OAAO,UAAU+N,CAAQ,KAAKA,KAAY,KAC5CE,GAAOF,GAAUjH,CAAS;AAE5B;AAAA,IACF;AACA,UAAMhK,IAAWkS,GAAWrH,EAAM,MAAM;AACxC,QAAK7K,GAKL;AAAA,UAJAmR,GAAOnR,EAAS,KAAKA,EAAS,GAAG,GACjC6N,GAAa,UAAU,IAGnBhC,MAAkB,WAAWwG,GAAY,YAAY,SAAS;AAChE,cAAMzU,IAAMyH,EAAKrF,EAAS,GAAG;AAC7B,SAAIpC,KAAA,gBAAAA,EAAK,UAAS,UAChB0T,GAAStR,EAAS,KAAKA,EAAS,KAAK,EAAK,KACjCpC,KAAA,gBAAAA,EAAK,UAAS,UAAUoC,EAAS,MAAMuD,KAChD+I,GAAW1O,EAAI,UAAUoC,EAAS,KAAKkR,GAAa,OAAO,GAE7DA,GAAa,UAAU;AACvB;AAAA,MACF;AACA,MAAAI,GAAStR,EAAS,KAAKA,EAAS,KAAK6K,EAAM,QAAQ;AAAA;AAAA,EACrD,GASMmI,KAAYnG,EAAO,EAAK;AAC9B,EAAA4D,GAAU,MAAM;AACd,QAAIwC,IAAS;AACb,UAAMC,IAAc,MAAM;AACxB,MAAAF,GAAU,UAAU,IACpB,OAAO,qBAAqBC,CAAM,GAClCA,IAAS,OAAO,sBAAsB,MAAM;AAC1C,QAAAD,GAAU,UAAU;AAAA,MACtB,CAAC;AAAA,IACH;AACA,kBAAO,iBAAiB,UAAUE,GAAa,EAAE,SAAS,IAAM,GACzD,MAAM;AACX,aAAO,oBAAoB,UAAUA,GAAa,EAAE,SAAS,IAAM,GACnE,OAAO,qBAAqBD,CAAM;AAAA,IACpC;AAAA,EACF,GAAG,CAAA,CAAE;AAGL,QAAME,KAAsB3E,EAAY,CAAC9I,MAAkB;AACzD,IAAIA,KAEAsN,GAAU,WAAW5E,GAAS,YAAY,QAC9CE,GAAoB,EAAI;AAAA,EAC1B,GAAG,CAAA,CAAE,GACC8E,KAAc5E;AAAA,IAClB,CAACrR,MAAkBP,EAAE,uBAAuB,EAAE,OAAAO,GAAO;AAAA,IACrD,CAACP,CAAC;AAAA,EAAA,GAEEyW,KAAgB7E;AAAA,IACpB,CAACrR,MAAkBP,EAAE,yBAAyB,EAAE,OAAAO,GAAO;AAAA,IACvD,CAACP,CAAC;AAAA,EAAA,GAME0W,IAAgB,GAAG5G,EAAM,gBACzB6G,KAAalO,EAAKoI,EAAS,GAC3B+F,KACJnH,MAAmBkH,MAAA,gBAAAA,GAAY,UAAS,UAAUvJ,IAAYzG,IAC1D6I,EAAYD,EAASoH,GAAW,UAAUvJ,CAAS,CAAC,IACpD,MAEAH,KAAMO;AAAA,IACV,OAAO;AAAA,MACL,MAAAlI;AAAA,MACA,SAAAY;AAAA,MACA,QAAAM;AAAA,MACA,OAAAzD;AAAA,MACA,SAAA+H;AAAA,MACA,WAAAgE;AAAA,MACA,YAAAC;AAAA,MACA,QAAApH;AAAA,MACA,WAAAZ;AAAA,MACA,mBAAAD;AAAA,MACA,UAAAkI;AAAA,MACA,UAAApJ;AAAA,MACA,YAAYqJ,MAAkB;AAAA,MAC9B,aAAAE;AAAA,MACA,aAAAC;AAAA,MACA,WAAWqE,GAAQ;AAAA,MACnB,QAAA3D;AAAA,MACA,aAAaL,IAAkBiH,IAAgB;AAAA,MAC/C,UAAAnH;AAAA,MACA,aAAAC;AAAA,MACA,qBAAA+G;AAAA,MACA,eAAA3G;AAAA,MACA,aAAA4G;AAAA,MACA,eAAAC;AAAA,IAAA;AAAA,IAEF;AAAA,MACEnR;AAAA,MACAY;AAAA,MACAM;AAAA,MACAzD;AAAA,MACA+H;AAAA,MACAgE;AAAA,MACAC;AAAA,MACApH;AAAA,MACAZ;AAAA,MACAD;AAAA,MACAkI;AAAA,MACApJ;AAAA,MACAqJ;AAAA,MACAE;AAAA,MACAC;AAAA,MACAqE,GAAQ;AAAA,MACR3D;AAAA,MACAL;AAAA,MACAiH;AAAA,MACAnH;AAAA,MACAC;AAAA,MACA+G;AAAA,MACA3G;AAAA,MACA4G;AAAA,MACAC;AAAA,IAAA;AAAA,EACF,GAIII,KAAgBrJ,EAAQ,MAAM;AAClC,UAAMiD,wBAAU,IAAA;AAChB,eAAWpE,KAAOkB,GAAU;AAC1B,YAAM,CAAChG,GAAOuP,CAAS,IAAI1K,GAAkBC,CAAG,GAC1C2H,IAAM9E,EAAiB4H,CAAS;AACtC,UAAI9C,MAAQ,OAAW;AACvB,YAAM9M,IAAOuJ,EAAI,IAAIlJ,CAAK,KAAK,CAAA;AAC/B,MAAAL,EAAK,KAAK8M,CAAG,GACbvD,EAAI,IAAIlJ,GAAOL,CAAI;AAAA,IACrB;AACA,UAAM6P,wBAAa,IAAA;AACnB,eAAW,CAACxP,GAAOL,CAAI,KAAKuJ;AAC1B,MAAAsG,EAAO,IAAIxP,GAAOL,EAAK,KAAK,CAAC1C,GAAGjC,MAAMiC,IAAIjC,CAAC,EAAE,KAAK,GAAG,CAAC;AAExD,WAAOwU;AAAA,EACT,GAAG,CAACxJ,GAAU2B,CAAgB,CAAC,GAGzB8H,MAAelF,KAAA,gBAAAA,EAAW,QAAO,IACjCmF,KACJ,gBAAAlJ;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAKoC;AAAA,MACL,MAAK;AAAA,MACL,iBAAe;AAAA,MACf,WAAW5E,GAAmB,EAAE,UAAU,UAAU;AAAA,MAEpD,UAAA;AAAA,QAAA,gBAAAnC;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,iBAAe;AAAA,YACf,WAAWsC,GAA4B,EAAE,QAAQ,IAAM;AAAA,YAEtD,eACC,gBAAAtC,EAAC,QAAA,EAAK,WAAU,cAAc,UAAApJ,EAAE,oBAAoB,EAAA,CAAE;AAAA,UAAA;AAAA,QAAA;AAAA,QAGzD2M,GAAc8G,GAAQ,MAAM,CAACpN,MAC5B,gBAAA+C;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC,MAAK;AAAA,YACL,iBAAe/C,IAAI;AAAA,YACnB,oBAAkB2Q,OAAiB3Q;AAAA,YACnC,WAAWqF,GAAA;AAAA,YAEV,UAAAoD,EAAU,YAAY5I,EAAQG,CAAC,CAAC;AAAA,UAAA;AAAA,UAN5BA;AAAA,QAAA,CAQR;AAAA,QACAU,IACC,gBAAAqC;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,iBAAezC,IAAc;AAAA,YAC7B,oBAAkBqQ,OAAiBrQ;AAAA,YACnC,WAAW+E,GAAA;AAAA,YAEV,UAAAoD,EAAU,YAAY/H,CAAS;AAAA,UAAA;AAAA,QAAA,IAEhC;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAIR,MAAImQ,KAA8B;AAClC,MAAIlQ,KAAgBW,GAAQ;AAC1B,UAAMwP,IAAc1O,EAAK,QACnB2O,IAAatI,EAAU,YAAY9H,CAAY,GAC/CqQ,IAAexG,OAAcsG,GAC7BtS,IAAQ,CACZ4H,GACApG,GACAjF,GACAD,KAAUiW,MACP;AACH,YAAMtW,KAAO0L,GAAcC,GAAQ7G,CAAQ;AAC3C,aACE,gBAAAwD;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,MAAK;AAAA,UACL,iBAAe/C,IAAI;AAAA,UACnB,cAAYyI,EAAU,SAAS3N,IAASC,GAAYN,EAAI;AAAA,UACxD,UAAUuW,KAAgBjK,MAAc/G,IAAI,IAAI;AAAA,UAChD,WAAWwF,GAAoB,EAAE,MAAMa,GAAc5L,EAAI,GAAG;AAAA,UAE3D,UAAAgO,EAAU,YAAYhO,EAAI;AAAA,QAAA;AAAA,QAPtBuF;AAAA,MAAA;AAAA,IAUX;AACA,IAAA6Q,KACE,gBAAAnJ;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAKqC;AAAA,QACL,MAAK;AAAA,QACL,iBAAe+G,IAAc;AAAA,QAC7B,WAAW5L,GAAmB,EAAE,UAAU,UAAU;AAAA,QAEpD,UAAA;AAAA,UAAA,gBAAAnC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,iBAAe;AAAA,cACf,qBAAkB0I,KAAA,gBAAAA,EAAW,YAAWrK;AAAA,cACxC,WAAWkE,GAAyB,EAAE,MAAM,SAAS,aAAAyD,GAAa;AAAA,cAEjE,UAAAgI;AAAA,YAAA;AAAA,UAAA;AAAA,UAEFzK;AAAA,YAAc8G,GAAQ;AAAA,YAAM,CAACpN,MAC5BxB,EAAM8C,EAAO,QAAQtB,CAAC,GAAGA,GAAGyI,EAAU,YAAY5I,EAAQG,CAAC,CAAC,CAAC;AAAA,UAAA;AAAA,UAE9DU,IACGlC;AAAA,YACE8C,EAAO;AAAA,YACPhB;AAAA,YACAmI,EAAU,YAAY/H,CAAS;AAAA;AAAA;AAAA,YAG/B/G,EAAE,kBAAkB;AAAA,UAAA,IAEtB;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGV;AAGA,QAAMsX,IAA2B,CAAA,GAC3BC,IAAY9D,GAAQ;AAC1B,EAAI8D,EAAU,OAAO,KACnBD,EAAS;AAAA,IACP,gBAAAlO;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,eAAY;AAAA,QACZ,WAAWoC,GAAsB,EAAE,MAAM,YAAY;AAAA,MAAA;AAAA,MAFjD;AAAA,IAAA;AAAA,EAGN,GAGJ+L,EAAU,QAAQ,QAAQ,CAAClD,GAAU7R,MAAM;AACzC,IAAI+U,EAAU,SAAS,KAAK/U,MAAM+U,EAAU,eAC1CD,EAAS;AAAA,MACP,gBAAAlO;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,eAAY;AAAA,UACZ,WAAWoC,GAAsB,EAAE,MAAM,cAAc;AAAA,QAAA;AAAA,QAFnD;AAAA,MAAA;AAAA,IAGN;AAGJ,UAAMxK,IAAMyH,EAAK4L,CAAQ;AACzB,QAAI,CAACrT,EAAK;AACV,UAAMwW,IAAcnD,MAAaxD;AACjC,IAAAyG,EAAS;AAAA,MACP,gBAAAlO;AAAA,QAAC2D;AAAA,QAAA;AAAA,UAEC,KAAAE;AAAA,UACA,KAAAjM;AAAA,UACA,cAAcqT,IAAW;AAAA,UACzB,cAAavC,KAAA,gBAAAA,EAAW,YAAW9Q,EAAI;AAAA,UACvC,WAAWwW,IAAcpK,IAAY;AAAA,UACrC,aAAY2E,MAAA,gBAAAA,GAAW,YAAW/Q,EAAI,MAAM+Q,GAAU,MAAM;AAAA,UAC5D,cACE/Q,EAAI,SAAS,SACR6V,GAAc,IAAIvR,EAAKtE,EAAI,QAAQ,EAAE,EAAE,KAAK,KAC7C;AAAA,QAAA;AAAA,QAVDA,EAAI;AAAA,MAAA;AAAA,IAYX;AAAA,EAEJ,CAAC,GACGuW,EAAU,OAAO,KACnBD,EAAS;AAAA,IACP,gBAAAlO;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,eAAY;AAAA,QACZ,WAAWoC,GAAsB,EAAE,MAAM,YAAY;AAAA,MAAA;AAAA,MAFjD;AAAA,IAAA;AAAA,EAGN;AAQJ,QAAMiM,IAAgB;AAAA,IACpB,qBAAqB,OAAO,KAAK,IAAI,GAAG9Q,CAAW,CAAC;AAAA,IACpD,sBAAsB,OAAO4Q,EAAU,IAAI;AAAA,IAC3C,wBAAwB,OAAOA,EAAU,MAAM;AAAA,IAC/C,sBAAsB,OAAOA,EAAU,IAAI;AAAA,IAC3C,sBAAsB,OAAO9D,GAAQ,KAAK,IAAI;AAAA,IAC9C,wBAAwB,OAAOA,GAAQ,KAAK,MAAM;AAAA,IAClD,sBAAsB,OAAOA,GAAQ,KAAK,IAAI;AAAA,IAC9C,gCAAgC,GAAGhF,GAAQ,WAAW;AAAA,IACtD,8BAA8B,GAAGA,GAAQ,WAAW;AAAA,IACpD,iCAAiC,GAAGA,GAAQ,UAAU;AAAA,EAAA;AAGxD,SACE,gBAAAV;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAKiC;AAAA,MACL,UAAA4D;AAAA,MAEA,OAAO6D;AAAA,MACP,kBAAe;AAAA,MACf,WAAWrM,GAAA;AAAA,MAEX,UAAA;AAAA,QAAA,gBAAA2C;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,KAAKmC;AAAA,YACL,MAAK;AAAA,YAGL,UAAU;AAAA,YACV,cAAYtB;AAAA,YACZ,iBAAe2B,GAAW,SAAS;AAAA,YACnC,iBAAeF,KAAiB;AAAA,YAChC,wBACEpB,MAAkB,cAAcA,MAAkB,UAC9C,KACA;AAAA,YAEN,qBAAkB;AAAA,YAClB,WAAW3D,GAAoB;AAAA,cAC7B,MAAA+D;AAAA,cACA,SAAAC;AAAA,cACA,aAAAF;AAAA,cACA,cAAc,EAAQrI;AAAA,YAAS,CAChC;AAAA,YACD,WAAA6N;AAAA,YACA,eAAAc;AAAA,YACA,eAAAE;AAAA,YACA,gBAAAG;AAAA,YACA,SAAAG;AAAA,YACA,SAAS,CAACjI,MAAU;AAElB,cAAIA,EAAM,OAAO,QAAQ,gBAAgB,MACvCoD,GAAY,UAAU,aAExBD,GAAY,UAAU,IACtBD,EAAY,EAAI;AAAA,YAClB;AAAA,YACA,QAAQ,CAAClD,MAAU;AACjB,cACGA,EAAM,cAAc,SAASA,EAAM,aAA4B,MAEhEmD,GAAY,UAAU,IACtBD,EAAY,EAAK;AAAA,YAErB;AAAA,YAEC,UAAA;AAAA,cAAA8F;AAAA,cACAK;AAAA,cACAJ;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAEFN,OAAgB,OACf,gBAAAxN,EAAC,QAAA,EAAK,IAAIsN,GAAe,QAAM,IAC5B,UAAAE,GAAA,CACH,IACE;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGV;ACl3CA,MAAMc,KAAQ,MAAM,KAAK,EAAE,QAAQnW,MAAiB,CAACiJ,GAAGO,MAASA,CAAI;AAGrE,SAAS4M,GACP5U,GACArD,GACiD;AACjD,SAAO;AAAA,IACL,OAAOqD,EAAM,QAAQ,OAAO,KAAKrD,EAAOqD,EAAM,GAAG;AAAA,IACjD,KAAKA,EAAM,QAAQ,OAAO,KAAKrD,EAAOqD,EAAM,GAAG;AAAA,IAC/C,QACEA,EAAM,SAAS,eAAeA,EAAM,aAAa,SAC7CrD,EAAOqD,EAAM,QAAQ,IACrB;AAAA,EAAA;AAEV;AAUO,MAAM6U,KAAgBC;AAAA,EAC3B,CACE;AAAA,IACE,SAAAC,IAAU;AAAA,IACV,SAASC;AAAA,IACT,OAAOC;AAAA,IACP,QAAA3V;AAAA,IACA,gBAAA4V;AAAA,IACA,WAAAC;AAAA,IACA,eAAAC;AAAA,IACA,UAAUC;AAAA,IACV,WAAAC;AAAA,EAAA,GAEFC,MACG;AACH,UAAM,EAAE,GAAAtY,GAAG,MAAAuY,MAAS1I,GAAe,IAAI,GACjC3G,IAAU7J,GAAA,GACVG,IAASgZ,GAAaD,EAAK,oBAAoBA,EAAK,QAAQ,GAE5DxV,IAAQyK;AAAA,MACZ,MACEwK,IACI5T,GAAa4T,GAAW3V,KAAU,CAAA,CAAE,KACnC6G,KAAA,gBAAAA,EAAS,UACV9E,GAAa,EAAE,MAAM,gBAAgB/B,KAAU,CAAA,CAAE;AAAA,MACvD,CAAC2V,GAAW3V,GAAQ6G,KAAA,gBAAAA,EAAS,KAAK;AAAA,IAAA,GAE9B4B,IACJiN,MACA7O,KAAA,gBAAAA,EAAS,aACRnG,EAAM,SAAS,cAAc,cAAc,YACxCrD,IACJuY,MACA/O,KAAA,gBAAAA,EAAS,UAAU,gBACnB3J,GAAsBC,GAAQ,QAAQ,GAKlCiZ,KACH1V,EAAM,SAAS,cAAcA,EAAM,SAAS,gBAC7CA,EAAM,WAAW,SAAS,GACtB2V,IAAY3V,EAAM,WAAW,SAAS,GACtC4V,IAAYF,IACd,MAAM;AAAA,MAAK,EAAE,QAAQC,EAAA;AAAA,MAAa,CAAClO,GAAGoO,MACpC3U,GAAW2U,GAAMF,CAAS;AAAA,IAAA,IAE5B,CAAA,GACEjV,IAAQV,EAAM,WAAW,IAAIrD,CAAM,GAEnCmZ,IAASlB,GAAU5U,GAAOrD,CAAM,GAChCkX,KAAc6B,IAChBzY,EAAE,mCAAmC;AAAA,MACnC,OAAO0Y;AAAA,MACP,WAAW9Y,GAAeJ,CAAM,EAAEkZ,CAAS;AAAA,MAC3C,OAAO,IAAI,KAAK,WAAWlZ,GAAQ;AAAA,QACjC,MAAM;AAAA,MAAA,CACP,EAAE,OAAOiE,CAAK;AAAA,IAAA,CAChB,IACDoV,EAAO,WAAW,SAChB7Y,EAAE,uCAAuC;AAAA,MACvC,KAAK6Y,EAAO;AAAA,MACZ,KAAKA,EAAO;AAAA,MACZ,UAAUA,EAAO;AAAA,IAAA,CAClB,IACD7Y,EAAE,8BAA8B;AAAA,MAC9B,KAAK6Y,EAAO;AAAA,MACZ,KAAKA,EAAO;AAAA,IAAA,CACb,GAEDC,KACH/V,EAAM,SAAS,cAAcA,EAAM,SAAS,gBAAgB,CAAC0V,IAC1D,CAAC1V,EAAM,QAAQ,OAAOxB,KAAgB,IAAIwB,EAAM,OAAOA,EAAM,GAAG,CAAC,IACjE,MACAgW,IAAYb,MAAahP,KAAA,gBAAAA,EAAS,aAAY,IAC9C8P,IAAgBb,MAAiBjP,KAAA,gBAAAA,EAAS,iBAAgB,IAC1DtD,IAAWwS,MAAgBlP,KAAA,gBAAAA,EAAS,WACpC+P,KAAQnB,MAAY,eAAe,eAAe,WAElDoB,KAAM,CAACC,MACX,gBAAA/P,EAAC,UAAK,WAAW2C,GAAyB,EAAE,SAAA+L,EAAA,CAAS,GAClD,UAAAqB,EAAM,IAAI,CAACpO,MACV,gBAAA3B;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,WAAW4C,GAAsB;AAAA,UAC/B,MAAMnB,GAASC,GAASC,CAAI;AAAA,UAC5B,OAAAkO;AAAA,QAAA,CACD;AAAA,MAAA;AAAA,MAJIlO;AAAA,IAAA,CAMR,GACH;AAGF,WACE,gBAAAgD;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAuK;AAAA,QACA,MAAK;AAAA,QACL,cAAYtY,EAAE,sBAAsB;AAAA,QACpC,kBAAe;AAAA,QACf,WAAW8L,GAAsB,EAAE,WAAAuM,GAAW;AAAA,QAE9C,UAAA;AAAA,UAAA,gBAAAjP,EAAC,QAAA,EAAK,WAAU,cAAc,UAAAwN,IAAY;AAAA,UACzC6B,IACC,gBAAArP;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,eAAY;AAAA,cACZ,eAAY;AAAA,cACZ,WAAU;AAAA,cAET,UAAAuP,EAAU,IAAI,CAAC5N,GAAM6N,MACpB,gBAAA7K;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBAEC,WAAU;AAAA,kBAEV,UAAA;AAAA,oBAAA,gBAAA3E;AAAA,sBAAC;AAAA,sBAAA;AAAA,wBACC,aAAW2B;AAAA,wBACX,WAAWiB,GAAsB;AAAA,0BAC/B,MAAMnB,GAASC,GAASC,CAAI;AAAA,0BAC5B,OAAO;AAAA,wBAAA,CACR;AAAA,sBAAA;AAAA,oBAAA;AAAA,oBAEF6N,IAAOnV,EAAM,SACZ,gBAAA2F,EAAC,QAAA,EAAK,WAAU,eAAe,UAAA3F,EAAMmV,CAAI,EAAA,CAAE,IACzC;AAAA,kBAAA;AAAA,gBAAA;AAAA,gBAZC7N;AAAA,cAAA,CAcR;AAAA,YAAA;AAAA,UAAA,IAGH,gBAAAgD;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,eAAY;AAAA,cACZ,WAAU;AAAA,cAEV,UAAA;AAAA,gBAAA,gBAAA3E,EAAC,QAAA,EAAK,WAAU,eAAe,UAAAyP,EAAO,OAAM;AAAA,gBAC3CA,EAAO,WAAW,SACjB,gBAAA9K,EAAAqL,IAAA,EACG,UAAA;AAAA,kBAAAF,GAAIxB,GAAM,MAAM,GAAGnW,KAAgB,CAAC,CAAC;AAAA,kBAGtC,gBAAA6H;AAAA,oBAAC;AAAA,oBAAA;AAAA,sBACC,eAAY;AAAA,sBACZ,WAAW4C,GAAsB;AAAA,wBAC/B,MAAM;AAAA,wBACN,OAAO;AAAA,sBAAA,CACR;AAAA,sBAEA,UAAA6M,EAAO;AAAA,oBAAA;AAAA,kBAAA;AAAA,kBAETK,GAAIxB,GAAM,MAAMnW,KAAgB,CAAC,CAAC;AAAA,gBAAA,EAAA,CACrC,IAEA2X,GAAIJ,KAAcpB,EAAK;AAAA,gBAEzB,gBAAAtO,EAAC,QAAA,EAAK,WAAU,eAAe,YAAO,IAAA,CAAI;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAG7C2P,IACC,gBAAAhL,EAAC,QAAA,EAAK,WAAU,6DACd,UAAA;AAAA,YAAA,gBAAA3E;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAY;AAAA,gBACZ,WAAW4C,GAAsB,EAAE,MAAM,SAAS;AAAA,cAAA;AAAA,YAAA;AAAA,YAEnDhM,EAAE,uBAAuB;AAAA,UAAA,EAAA,CAC5B,IACE;AAAA,UACHgZ,IACC,gBAAAjL,EAAC,QAAA,EAAK,WAAU,6DACd,UAAA;AAAA,YAAA,gBAAA3E;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,eAAY;AAAA,gBACZ,WAAW4C,GAAsB,EAAE,MAAM,cAAc;AAAA,cAAA;AAAA,YAAA;AAAA,YAExDpG,MAAa,SACV5F,EAAE,0BAA0B,IAC5BA,EAAE,iCAAiC;AAAA,cACjC,OAAO,IAAI,KAAK,aAAaR,CAAM,EAAE,OAAOoG,CAAQ;AAAA,YAAA,CACrD;AAAA,UAAA,EAAA,CACP,IACE;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAGV;AACF;AAEAgS,GAAc,cAAc;AClN5B,MAAMyB,KAAgB,MACpB,OAAO,0BAA0B,EAAA,KAAA,CAAAlW,MAAAA,EAAA,CAAA,EAAE,KAAK,CAACmW,OAAY;AAAA,EACnD,SAASA,EAAO;AAGlB,EAAE,GACEC,KAAgBC,GAAKH,EAAa;AAIjC,SAASI,KAA4B;AAC1C,EAAAJ,GAAA,EAAgB,MAAM,MAAM;AAAA,EAE5B,CAAC;AACH;AAuBA,SAAS/K,GACP7B,GACA7G,GACW;AACX,QAAMjG,KAAQ8M,KAAA,gBAAAA,EAAQ,UAAS;AAC/B,SAAO;AAAA,IACL,OAAA9M;AAAA,IACA,OAAO8M,KAAA,gBAAAA,EAAQ;AAAA,IACf,QACE9M,MAAU,OACN,UACAgG,GAAY8G,KAAA,gBAAAA,EAAQ,OAAO7G,CAAQ,IACjC,eACA;AAAA,EAAA;AAEZ;AASO,SAAS8T,GAAiB;AAAA,EAC/B,OAAA9K;AAAA,EACA,WAAAC;AAAA,EACA,MAAAvJ;AAAA,EACA,SAAAY;AAAA,EACA,QAAAM;AAAA,EACA,MAAAiC;AAAA,EACA,SAAAkR;AAAA,EACA,UAAA3K;AAAA,EACA,WAAAF;AAAA,EACA,QAAAnH;AAAA,EACA,WAAAZ;AAAA,EACA,cAAAC;AAAA,EACA,mBAAAF;AAAA,EACA,UAAAlB;AAAA,EACA,aAAAgU;AACF,GAA0B;AACxB,QAAM,EAAE,GAAA5Z,EAAA,IAAM6P,GAAe,IAAI,GAE3BgK,IAAarM;AAAA,IACjB,MAAM;AAAA,MACJ,GAAImM,IACA;AAAA,QACE;AAAA,UACE,OAAO;AAAA,UACP,OAAO;AAAA,UACP,YAAY3Z,EAAE,qBAAqB;AAAA;AAAA,UAEnC,UAAU;AAAA,QAAA;AAAA,MACZ,IAEF,CAAA;AAAA,MACJ;AAAA,QACE,OAAO;AAAA,QACP,OAAO;AAAA,QACP,YAAY6O,KAAa7O,EAAE,oBAAoB;AAAA,QAC/C,UAAU,CAAC2Z;AAAA,MAAA;AAAA,MAEb,GAAGzT,EAAQ;AAAA,QACT,CAACjF,GAAQoF,OAAgC;AAAA,UACvC,OAAO,IAAIA,CAAC;AAAA,UACZ,YAAYyI,EAAU,YAAY7N,CAAM;AAAA,UACxC,aAAa,CAAC6Y;;AAAW,qBAAAxT,IAAAwT,GAAO,SAAP,gBAAAxT,EAAa,MAAMD,OAAM;AAAA;AAAA,UAClD,UAAU;AAAA,QAAA;AAAA,MACZ;AAAA,MAEF,GAAIU,IACA;AAAA,QACE;AAAA,UACE,OAAO;AAAA,UACP,OAAO;AAAA,UACP,YAAY+H,EAAU,YAAY/H,CAAS;AAAA,UAC3C,UAAU;AAAA,QAAA;AAAA,MACZ,IAEF,CAAA;AAAA,IAAC;AAAA,IAEP,CAAC4S,GAAS9K,GAAW3I,GAAS4I,GAAW/H,GAAW/G,CAAC;AAAA,EAAA,GAGjD+Z,IAAUvM;AAAA,IACd,MACE/E,EAAK,IAAI,CAACuR,MAA2B;AACnC,UAAIA,EAAM,SAAS,SAAS;AAC1B,cAAM3Y,IAAYyN,EAAU,WAAWkL,EAAM,OAAO,GAC9C3S,KAAYM,KAAA,gBAAAA,EAAQ,aAAa,IAAIqS,EAAM,aAAY,CAAA;AAC7D,eAAO;AAAA,UACL,IAAI,SAAShL,EAAS,IAAIgL,EAAM,OAAO,KAAK,EAAE;AAAA,UAC9C,OAAO3Y;AAAA,UACP,KAAKyN,EAAU,aAAazN,GAAWyF,CAAiB;AAAA,UACxD,OAAOZ,EAAQ;AAAA,YAAI,CAACsE,IAAGnE,OACrByI,EAAU,UAAUR,GAAUjH,EAAUhB,EAAC,GAAGT,CAAQ,CAAC;AAAA,UAAA;AAAA,UAEvD,OACEmB,KAAaY,IACTmH,EAAU;AAAA,YACRR,GAAU3G,EAAO,OAAO,IAAIqS,EAAM,OAAO,GAAGpU,CAAQ;AAAA,UAAA,IAEtD;AAAA,QAAA;AAAA,MAEV;AACA,YAAMQ,IAAI4T,EAAM,UACV9Y,KAAUoE,EAAKc,CAAC,EAAE;AACxB,aAAO;AAAA,QACL,IAAI,OAAOd,EAAKc,CAAC,EAAE,EAAE;AAAA,QACrB,OACEuT,KAAWzY,OAAY,SACnB4N,EAAU,WAAW5N,EAAO,IAC5B;AAAA,QACN,KAAK4N,EAAU,SAASxJ,EAAKc,CAAC,CAAC;AAAA,QAC/B,OAAOI,EAAOJ,CAAC,EAAE,IAAI,CAACtF,MAASgO,EAAU,UAAUhO,CAAI,CAAC;AAAA,QACxD,OACEiG,KAAaY,IACTmH,EAAU,UAAUR,GAAU3G,EAAO,KAAKvB,CAAC,GAAGR,CAAQ,CAAC,IACvD;AAAA,MAAA;AAAA,IAEV,CAAC;AAAA,IACH;AAAA,MACE6C;AAAA,MACAnD;AAAA,MACAY;AAAA,MACAM;AAAA,MACAmT;AAAA,MACA3K;AAAA,MACAF;AAAA,MACA/H;AAAA,MACAY;AAAA,MACAb;AAAA,MACAlB;AAAA,IAAA;AAAA,EACF,GAGIqU,IAAsBzM;AAAA,IAC1B,MACExG,KAAgBW,IACZ;AAAA,MACE;AAAA,QACE,IAAI;AAAA,QACJ,KAAKmH,EAAU,YAAY9H,CAAY;AAAA,QACvC,OAAOW,EAAO,QAAQ;AAAA,UAAI,CAAC8E,MACzBqC,EAAU,UAAUR,GAAU7B,GAAQ7G,CAAQ,CAAC;AAAA,QAAA;AAAA;AAAA,QAGjD,OAAOmB,IACH+H,EAAU,UAAUR,GAAU3G,EAAO,OAAO/B,CAAQ,CAAC,IACrD;AAAA,MAAA;AAAA,IACN,IAEF;AAAA,IACN,CAACoB,GAAcD,GAAWY,GAAQmH,GAAWlJ,CAAQ;AAAA,EAAA,GAWjDsU,IAAWH,EAAQ,WAAUE,KAAA,gBAAAA,EAAqB,WAAU,IAC5DE,IAAclK,EAAOiK,CAAQ;AACnC,EAAAC,EAAY,UAAUD;AACtB,QAAM,CAACE,GAAUC,EAAW,IAAIzJ,GAAwB,IAAI,GACtD0J,IAASF,MAAaF,GACtBK,IAAatK,EAAuB,IAAI;AAE9C,EAAA4C,GAA0B,MAAM;AAC9B,UAAM2H,IAAUD,EAAW;AAC3B,QAAID,KAAU,CAACE,KAAW,OAAO,iBAAmB,IAAa;AACjE,UAAM1H,IAAW,IAAI,eAAe,MAAM;AACxC,MAAI0H,EAAQ,eAAeA,EAAQ,eAAe,KAChDH,GAAYF,EAAY,OAAO;AAAA,IAEnC,CAAC,GAGKM,KAAQ,MAAM;AAClB,MAAA3H,EAAS,QAAQ0H,CAAO;AACxB,iBAAWE,KAAS,MAAM,KAAKF,EAAQ,QAAQ,EAAG,CAAA1H,EAAS,QAAQ4H,CAAK;AAAA,IAC1E;AACA,IAAAD,GAAA;AACA,UAAMxR,IAAW,IAAI,iBAAiBwR,EAAK;AAC3C,WAAAxR,EAAS,QAAQuR,GAAS,EAAE,WAAW,IAAM,GACtC,MAAM;AACX,MAAA1H,EAAS,WAAA,GACT7J,EAAS,WAAA;AAAA,IACX;AAAA,EACF,GAAG,CAACqR,CAAM,CAAC;AAEX,QAAMK,IAAcnN;AAAA,IAClB,OAAO;AAAA,MACL,UAAU,CAACsM,MAAWA,EAAO,KAAK;AAAA,MAClC,WAAWQ,IAAS,WAAW;AAAA,IAAA;AAAA,IAEjC,CAACA,CAAM;AAAA,EAAA,GAKH,CAACM,GAASC,EAAU,IAAIjK,GAAS,CAAC,GAClCkK,KAAYtN;AAAA,IAChB,MAAOoN,MAAY,IAAIrB,KAAgBC,GAAKH,EAAa;AAAA,IACzD,CAACuB,CAAO;AAAA,EAAA;AAGV,SACE,gBAAAxR;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAKmR;AAAA,MACL,MAAK;AAAA,MACL,cAAY3L;AAAA,MAEZ,UAAU;AAAA,MACV,kBAAe;AAAA,MACf,eAAa0L,IAAS,WAAW;AAAA,MACjC,WAAWjP,GAAyB,EAAE,QAAAiP,GAAQ;AAAA,MAE9C,UAAA,gBAAAlR;AAAA,QAAC2R;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS,MAAMnB,KAAA,gBAAAA;AAAA,UACf,SAAS,MAAM;;AACb,YAAAiB,GAAW,CAAChJ,MAAYA,IAAU,CAAC,IACnCvL,IAAAiU,EAAW,YAAX,QAAAjU,EAAoB;AAAA,UACtB;AAAA,UAEA,UAAA,gBAAA8C;AAAA,YAAC4R;AAAA,YAAA;AAAA,cACC,4BACG,OAAA,EAAI,MAAK,UAAS,cAAYhb,EAAE,sBAAsB,GACrD,UAAA,gBAAAoJ;AAAA,gBAAC6R;AAAA,gBAAA;AAAA,kBACC,SAAQ;AAAA,kBACR,WAAU;AAAA,gBAAA;AAAA,cAAA,GAEd;AAAA,cAGF,UAAA,gBAAA7R;AAAA,gBAAC0R;AAAA,gBAAA;AAAA,kBACC,YAAAjB;AAAA,kBACA,SAAAE;AAAA,kBACA,qBAAAE;AAAA,kBACA,SAAQ;AAAA,kBACR,aAAaK,IAAS,yBAAyB;AAAA,kBAC/C,aAAAK;AAAA,gBAAA;AAAA,cAAA;AAAA,YACF;AAAA,UAAA;AAAA,QACF;AAAA,MAAA;AAAA,IACF;AAAA,EAAA;AAGN;AClEA,MAAMO,KAA8B,EAAE,MAAM,cAAc,QAAQ,OAAA,GAI5DC,KAAW,CAACvW,MAChB,IAAI,KAAKA,KAAS,CAAA,GAAI,IAAI,CAAC9D,MAASoL,GAAapL,EAAK,OAAOA,EAAK,QAAQ,CAAC,CAAC,GAUxEsa,KAAwB,EAAE,MAAM,IAAI,aAAa,IAAO,QAAQ,EAAA,GAEhEC,KAAcxD;AAAA,EAClB,CACE;AAAA,IACE,OAAAjJ;AAAA,IACA,MAAAtJ;AAAA,IACA,SAAAY;AAAA,IACA,SAAAC;AAAA,IACA,OAAAvB;AAAA,IACA,QAAAvE;AAAA,IACA,OAAO2X,IAAYkD;AAAA,IACnB,SAASnD;AAAA,IACT,WAAAtY,IAAY;AAAA,IACZ,UAAAmG;AAAA,IACA,gBAAAqS;AAAA,IACA,YAAAlJ,IAAa;AAAA,IACb,QAAAuM,IAAS;AAAA,IACT,WAAAvU,IAAY;AAAA,IACZ,cAAAC,IAAe;AAAA,IACf,UAAUuU;AAAA,IACV,iBAAAC,IAAkB;AAAA,IAClB,kBAAAC;AAAA,IACA,WAAArT,IAAY;AAAA,IACZ,wBAAAsT;AAAA,IACA,WAAAC,IAAY;AAAA,IACZ,eAAAC;AAAA,IACA,sBAAAC;AAAA,IACA,mBAAAC;AAAA,IACA,aAAAC;AAAA,IACA,eAAAC;AAAA,IACA,SAAA1M,IAAU;AAAA,IACV,MAAAD,KAAO;AAAA,IACP,SAAA4M,KAAU;AAAA,IACV,aAAAhc,IAAc;AAAA,IACd,cAAAC,IAAe;AAAA,IACf,WAAA2O;AAAA,IACA,aAAAqN,IAAc;AAAA,IACd,cAAAC;AAAA,IACA,IAAAC;AAAA,IACA,WAAA/D;AAAA,IACA,UAAApP;AAAA,EAAA,GAEFqP,OACG;AACH,UAAM,EAAE,GAAAtY,GAAG,MAAAuY,OAAS1I,GAAe,IAAI,GACjCrQ,KAASgZ,GAAaD,GAAK,oBAAoBA,GAAK,QAAQ,GAG5D/R,IAASgH;AAAA,MACb,MAAMvH,GAAYX,GAAMY,GAASC,GAASvB,GAAOgB,CAAQ;AAAA,MACzD,CAACN,GAAMY,GAASC,GAASvB,GAAOgB,CAAQ;AAAA,IAAA,GAEpCvD,KAASmL,EAAQ,MAAMjH,GAAYC,CAAM,GAAG,CAACA,CAAM,CAAC,GAGpD6V,KAAW,KAAK,UAAUrE,CAAS,GACnCjV,IAAQyK;AAAA,MACZ,MAAMpJ,GAAa4T,GAAW3V,EAAM;AAAA;AAAA,MAEpC,CAACga,IAAUha,EAAM;AAAA,IAAA,GAEbyI,KACJiN,MAAgBhV,EAAM,SAAS,cAAc,cAAc,YAEvD5C,KAAcqN;AAAA,MAClB,MAAMyK,KAAkB1Y,GAAsBC,IAAQC,CAAS;AAAA,MAC/D,CAACwY,GAAgBzY,IAAQC,CAAS;AAAA,IAAA,GAE9BW,KAAcoN,EAAQ,MAAM5N,GAAeJ,EAAM,GAAG,CAACA,EAAM,CAAC,GAC5DsP,IAAYtB;AAAA,MAChB,MACEzN,GAAgB;AAAA,QACd,GAAAC;AAAA,QACA,aAAAC;AAAA,QACA,cAAAC;AAAA,QACA,WAAAT;AAAA,QACA,aAAAU;AAAA,QACA,aAAAC;AAAA,QACA,QAAAC;AAAA,MAAA,CACD;AAAA,MACH;AAAA,QACEL;AAAA,QACAC;AAAA,QACAC;AAAA,QACAT;AAAA,QACAU;AAAA,QACAC;AAAA,QACAC;AAAA,MAAA;AAAA,IACF,GAEI2O,KAAWxB;AAAA,MACf,MAAMnI,GAAeC,GAAMjF,CAAM;AAAA,MACjC,CAACiF,GAAMjF,CAAM;AAAA,IAAA,GAMTyG,KACJE,KAAgBD,KAAa,QACzBH,KAA8BG,KAAa,QAC3CY,KAAS6F;AAAA,MACb,MACE9G;AAAA,QACEF;AAAA,QACAlB;AAAA,QACAY,EAAQ;AAAA,QACRU;AAAA,QACAI,KAAgB;AAAA,QAChBF;AAAA,MAAA;AAAA,MAEJ;AAAA,QACEN;AAAA,QACAlB;AAAA,QACAY,EAAQ;AAAA,QACRU;AAAA,QACAI;AAAA,QACAF;AAAA,MAAA;AAAA,IACF,GAII,CAACwV,IAAcC,EAAe,IAAI3L,GAAuBwK,EAAO,GAChEoB,KAAgBvM,EAAO,CAAC,GACxBwM,KAAaxM,EAAOhQ,CAAW;AACrC,IAAAwc,GAAW,UAAUxc;AACrB,UAAMyc,IAAW9K,EAAY,CAAC5P,GAAiBqU,IAAS,OAAU;AAChE,aAAO,aAAamG,GAAc,OAAO;AACzC,YAAMG,IAAYF,GAAW,SACvBG,IAAM,MACVL,GAAgB,CAAC1K,OAAa;AAAA,QAC5B,MAAM7P;AAAA,QACN,aAAa2a;AAAA,QACb,QAAQ9K,EAAQ,SAAS7P,IAAU6P,EAAQ,SAAS,IAAI;AAAA,MAAA,EACxD;AACJ,MAAIwE,IAGFmG,GAAc,UAAU,OAAO,WAAWI,GAAK,GAAG,IAElDA,EAAA;AAAA,IAEJ,GAAG,CAAA,CAAE;AACL,IAAA/I,GAAU,MAAM,MAAM,OAAO,aAAa2I,GAAc,OAAO,GAAG,EAAE,GAIpE3I,GAAU,MAAM;AACd,aAAO,aAAa2I,GAAc,OAAO,GACzCD,GAAgB,CAAC1K,MAAaA,EAAQ,SAAS,KAAKA,IAAUuJ,EAAQ;AAAA,IACxE,GAAG,CAACnb,CAAW,CAAC;AAChB,UAAM4c,KACJP,GAAa,gBAAgBrc;AAAA;AAAA;AAAA;AAAA,MAIzB,GAAGqc,GAAa,IAAI,GAAGA,GAAa,SAAS,MAAM,IAAI,MAAW,EAAE;AAAA,QACpE,IAGA,CAACQ,IAAMC,EAAY,IAAInM,GAAsBsL,CAAW,GAExDc,KAAUpL;AAAA,MACd,CAAC1S,MAAsB;AACrB,QAAA6d,GAAa7d,CAAI,GACjBid,KAAA,QAAAA,EAAejd,IACfwd;AAAA,UAEM1c,EADJd,MAAS,UACH,+BACA,8BAD4B;AAAA,QACE;AAAA,MAExC;AAAA,MACA,CAACid,GAAcO,GAAU1c,CAAC;AAAA,IAAA,GAGtB,CAACid,IAAcC,EAAe,IAClCtM,GAA0B4K,CAAe,GACrC2B,KAAW5B,KAAgB0B,IAC3BG,KAAcxL;AAAA,MAClB,CAAC1S,MAA0B;AACzB,QAAIqc,MAAiB,UAAW2B,GAAgBhe,CAAI,GACpDuc,KAAA,QAAAA,EAAmBvc;AAAA,MACrB;AAAA,MACA,CAACqc,GAAcE,CAAgB;AAAA,IAAA,GAG3B,CAACpT,IAAWgV,EAAY,IAAIzM;AAAA,MAChC,MAAM,IAAI,IAAI8K,KAA0B,CAAA,CAAE;AAAA,IAAA,GAEtC4B,KAAoB1L;AAAA,MACxB,CAAC1Q,GAAiByH,MAAyB;AAEzC,YAAIN,GAAU,IAAInH,CAAO,MAAMyH,EAAa;AAC5C,QAAA0U,GAAa,CAACxL,MAAY;AACxB,cAAIA,EAAQ,IAAI3Q,CAAO,MAAMyH,EAAa,QAAOkJ;AACjD,gBAAM3S,IAAO,IAAI,IAAI2S,CAAO;AAC5B,iBAAIlJ,IAAazJ,EAAK,IAAIgC,CAAO,IAC5BhC,EAAK,OAAOgC,CAAO,GACjBhC;AAAA,QACT,CAAC;AACD,cAAM2J,IAAQiG,EAAU,WAAW5N,CAAO;AAC1C,QAAAwb;AAAA,UACE/T,IACI3I,EAAE,mCAAmC,EAAE,OAAO6I,GAAO,IACrD7I,EAAE,kCAAkC,EAAE,OAAO6I,GAAO;AAAA,QAAA;AAAA,MAE5D;AAAA,MACA,CAACR,IAAWqU,GAAU5N,GAAW9O,CAAC;AAAA,IAAA,GAE9Bud,KAAc3L;AAAA,MAClB,CAAC1Q,MAAoBoc,GAAkBpc,GAAS,CAACmH,GAAU,IAAInH,CAAO,CAAC;AAAA,MACvE,CAACmH,IAAWiV,EAAiB;AAAA,IAAA,GAGzBzV,KAAW2F;AAAA,MACf,MAAM,IAAI,KAAK,SAAShO,IAAQ,EAAE,SAAS,IAAM,aAAa,QAAQ;AAAA,MACtE,CAACA,EAAM;AAAA,IAAA,GAKHge,KACJL,OAAa,WAAWrO,EAAU,YAAY,SAASqO,IACnD7U,KAAQkF;AAAA,MACZ,MACE9F;AAAA,QACEpC,EAAK,IAAI,CAACkF,GAAGpE,MAAMA,CAAC;AAAA,QACpBd;AAAA,QACAqC,GAAO;AAAA,QACP6V;AAAA,QACA3V;AAAA,MAAA;AAAA,MAEJ,CAACvC,GAAMqC,GAAO,MAAM6V,IAAa3V,EAAQ;AAAA,IAAA,GAErCY,KAAO+E;AAAA,MACX,MAAMtF,GAAc5C,GAAMgD,IAAOF,GAAWC,EAAS;AAAA,MACrD,CAAC/C,GAAMgD,IAAOF,GAAWC,EAAS;AAAA,IAAA,GAI9BoV,KAAejQ;AAAA,MACnB,MAAMtF,GAAc5C,GAAMgD,IAAOF,GAAW,oBAAI,KAAK;AAAA,MACrD,CAAC9C,GAAMgD,IAAOF,CAAS;AAAA,IAAA,GAInBsV,KAAelQ;AAAA,MACnB,MAAM,IAAI,IAAIlI,EAAK,IAAI,CAACtE,GAAKoF,MAAM,CAACpF,EAAI,IAAIoF,CAAC,CAAC,CAAC;AAAA,MAC/C,CAACd,CAAI;AAAA,IAAA,GAEDqY,IAAkBnQ;AAAA,MACtB,MAAM,IAAI,IAAItH,EAAQ,IAAI,CAACjF,GAAQoF,MAAM,CAAC,OAAOpF,EAAO,EAAE,GAAGoF,CAAC,CAAC,CAAC;AAAA,MAChE,CAACH,CAAO;AAAA,IAAA,GAEJgJ,KAAmB0C;AAAA,MACvB,CAACkF,MAAsB6G,EAAgB,IAAI7G,CAAS;AAAA,MACpD,CAAC6G,CAAe;AAAA,IAAA,GAEZpO,KAAWqC;AAAA,MACf,CAACmC,GAAkBjH,MAAyC;AAC1D,cAAM9L,IAAMsE,EAAKyO,CAAQ,GACnB9S,IAASiF,EAAQ4G,CAAW,GAC5BhM,IAAO0F,EAAOuN,CAAQ,EAAEjH,CAAW;AACzC,eAAO;AAAA,UACL,OAAO9L,EAAI;AAAA,UACX,UAAUC,EAAO;AAAA,UACjB,KAAAD;AAAA,UACA,QAAAC;AAAA,UACA,UAAA8S;AAAA,UACA,aAAAjH;AAAA,UACA,OAAOhM,EAAK;AAAA,UACZ,OAAOA,EAAK;AAAA,UACZ,OAAOA,EAAK;AAAA,UACZ,QAAQA,EAAK;AAAA,UACb,MACEA,EAAK,WAAW,WAAWA,EAAK,UAAU,OACtCiC,EAAM,OAAOjC,EAAK,KAAK,IACvB;AAAA,QAAA;AAAA,MAEV;AAAA,MACA,CAACwE,GAAMY,GAASM,GAAQzD,CAAK;AAAA,IAAA,GAIzB6a,KAAahM;AAAA,MACjB,CAACiM,MAA2C;AAC1C,cAAMtd,IACJsd,EAAK,IAAI,UAAU,SACf,SACA7O,GAAS,IAAI6O,EAAK,IAAI,KAAK;AACjC,eAAO;AAAA,UACL,OAAOA,EAAK;AAAA,UACZ,UAAUA,EAAK;AAAA,UACf,KAAK;AAAA,YACH,IAAIA,EAAK,IAAI;AAAA,YACb,OAAO/O,EAAU,SAAS+O,EAAK,GAAG;AAAA,YAClC,GAAItd,MAAU,SAAY,CAAA,IAAK,EAAE,OAAAA,EAAA;AAAA,UAAM;AAAA,UAEzC,QAAQ;AAAA,YACN,IAAIsd,EAAK,OAAO;AAAA,YAChB,OAAO/O,EAAU,YAAY+O,EAAK,MAAM;AAAA,UAAA;AAAA,UAE1C,UAAUA,EAAK;AAAA,UACf,aAAaA,EAAK;AAAA,UAClB,OAAOA,EAAK;AAAA,UACZ,OAAOA,EAAK;AAAA,UACZ,QAAQA,EAAK;AAAA,UACb,MAAMA,EAAK;AAAA,QAAA;AAAA,MAEf;AAAA,MACA,CAAC/O,GAAWE,EAAQ;AAAA,IAAA,GAEhBQ,KAAcoC;AAAA,MAClB,CAACiM,MACC7B,IACIA,EAAc/b,IAAc2d,GAAWC,CAAI,IAAIA,GAAM;AAAA,QACnD,aAAA5d;AAAA,MAAA,CACD,IACD6O,EAAU;AAAA,QACRA,EAAU,SAAS+O,EAAK,GAAG;AAAA,QAC3B/O,EAAU,YAAY+O,EAAK,MAAM;AAAA,QACjCrX,EAAOqX,EAAK,QAAQ,EAAEA,EAAK,WAAW;AAAA,MAAA;AAAA,MAE9C,CAAC7B,GAAe/b,GAAa2d,IAAY9O,GAAWtI,CAAM;AAAA,IAAA,GAItDsX,KAAelC,MAAkB,QACjC,CAACmC,IAAkBC,EAAmB,IAAIpN;AAAA,MAAsB,MACpEuK,GAASU,EAAoB;AAAA,IAAA,GAKzBtO,KAAWC,EAAQ,MAAM;AAC7B,YAAMW,IAAS2P,KAAe3C,GAASS,CAAa,IAAImC,IAClDE,wBAAc,IAAA;AACpB,iBAAW5R,KAAO8B,GAAQ;AACxB,cAAM,CAAC5G,GAAOuP,CAAS,IAAI1K,GAAkBC,CAAG;AAChD,QAAIqR,GAAa,IAAInW,CAAK,KAAKoW,EAAgB,IAAI7G,CAAS,KAC1DmH,EAAQ,IAAI5R,CAAG;AAAA,MAEnB;AACA,aAAO4R;AAAA,IACT,GAAG;AAAA,MACDH;AAAA,MACAlC;AAAA,MACAmC;AAAA,MACAL;AAAA,MACAC;AAAA,IAAA,CACD,GAEKO,KAAUtM;AAAA,MACd,CAACuM,MAAiD;AAChD,cAAMC,IAA2B,CAAA;AACjC,mBAAW/R,KAAO8R,GAAM;AACtB,gBAAM,CAAC5W,GAAOuP,CAAS,IAAI1K,GAAkBC,CAAG,GAC1CjG,IAAIsX,GAAa,IAAInW,CAAK,GAC1BlB,IAAIsX,EAAgB,IAAI7G,CAAS;AACvC,UAAI1Q,MAAM,UAAaC,MAAM,YAAiB,KAAKkJ,GAASnJ,GAAGC,CAAC,CAAC;AAAA,QACnE;AACA,eAAO+X;AAAA,MACT;AAAA,MACA,CAACV,IAAcC,GAAiBpO,EAAQ;AAAA,IAAA,GAEpC8O,KAAWzM;AAAA,MACf,CAACmC,GAAkBjH,MACjBgC,EAAU;AAAA,QACRA,EAAU,SAASxJ,EAAKyO,CAAQ,CAAC;AAAA,QACjCjF,EAAU,YAAY5I,EAAQ4G,CAAW,CAAC;AAAA,MAAA;AAAA,MAE9C,CAACgC,GAAWxJ,GAAMY,CAAO;AAAA,IAAA,GAErBoY,KAAkB1M;AAAA,MACtB,CAAC1S,GAAmB8C,GAAiBqU,IAAS,OAAU;AACtD,QAAKyH,MAAcE,GAAoB9e,CAAI,GAC3C4c,KAAA,QAAAA,EAAoBoC,GAAQhf,CAAI,IAChCwd,EAAS1a,GAASqU,CAAM;AAAA,MAC1B;AAAA,MACA,CAACyH,IAAchC,GAAmBoC,IAASxB,CAAQ;AAAA,IAAA,GAE/C6B,KAAe3M;AAAA,MACnB,CAAC/R,MACCA,MAAU,IACNG,EAAE,0BAA0B,IAC5BA,EAAE,0BAA0B;AAAA,QAC1B,OAAAH;AAAA,QACA,WAAWO,GAAYP,CAAK;AAAA,MAAA,CAC7B;AAAA,MACP,CAACG,GAAGI,EAAW;AAAA,IAAA,GAIXoe,KAAYhR;AAAA,MAChB,MAAM/E,GAAK,QAAQ,CAACzH,MAASA,EAAI,SAAS,SAAS,CAACA,EAAI,QAAQ,IAAI,CAAA,CAAG;AAAA,MACvE,CAACyH,EAAI;AAAA,IAAA,GAEDgW,KAAY7M;AAAA,MAChB,CACE7H,GACA2U,MACG;AACH,cAAMla,IAAIga,GAAU,QAAQzU,EAAK,QAAQ,GACnCxH,IAAIic,GAAU,QAAQE,EAAG,QAAQ,GACjCxf,wBAAW,IAAA;AACjB,YAAIsF,MAAM,MAAMjC,MAAM,GAAI,QAAOrD;AACjC,cAAM,CAACyf,GAAKC,CAAM,IAAIpa,KAAKjC,IAAI,CAACiC,GAAGjC,CAAC,IAAI,CAACA,GAAGiC,CAAC,GACvC,CAACuD,GAAMC,CAAK,IAChB+B,EAAK,OAAO2U,EAAG,MAAM,CAAC3U,EAAK,KAAK2U,EAAG,GAAG,IAAI,CAACA,EAAG,KAAK3U,EAAK,GAAG;AAC7D,iBAASvH,IAAImc,GAAKnc,KAAKoc,GAAQpc,KAAK,GAAG;AACrC,gBAAM+E,KAAQjC,EAAKkZ,GAAUhc,CAAC,CAAC,EAAE;AACjC,mBAAS6D,KAAI0B,GAAM1B,MAAK2B,GAAO3B,MAAK;AAClC,YAAAnH,EAAK,IAAIgN,GAAa3E,IAAOrB,EAAQG,EAAC,EAAE,EAAE,CAAC;AAAA,QAE/C;AACA,eAAOnH;AAAA,MACT;AAAA,MACA,CAACsf,IAAWlZ,GAAMY,CAAO;AAAA,IAAA,GAGrBwJ,KAAakC;AAAA,MACjB,CAACmC,GAAkBjH,GAAqB+R,MAAoB;AAE1D,YADA9C,KAAA,QAAAA,EAAcxM,GAASwE,GAAUjH,CAAW,IACxC,CAAC+R,KAAUlD,MAAc,OAAQ;AACrC,cAAMtP,IAAMH,GAAa5G,EAAKyO,CAAQ,EAAE,IAAI7N,EAAQ4G,CAAW,EAAE,EAAE,GAC7DgB,IAAOuQ,GAAStK,GAAUjH,CAAW;AAC3C,YAAI6O,MAAc,YAAY;AAC5B,gBAAMzc,IAAO,IAAI,IAAIqO,EAAQ,GACvBuR,IAAS,CAAC5f,EAAK,IAAImN,CAAG;AAC5B,UAAIyS,IAAQ5f,EAAK,IAAImN,CAAG,IACnBnN,EAAK,OAAOmN,CAAG,GACpBiS;AAAA,YACEpf;AAAA,YACAc,EAAE8e,IAAS,2BAA2B,4BAA4B;AAAA,cAChE,MAAMhR;AAAA,cACN,OAAO5O,EAAK;AAAA,cACZ,WAAWkB,GAAYlB,EAAK,IAAI;AAAA,YAAA,CACjC;AAAA,UAAA;AAEH;AAAA,QACF;AAGA,cAAM6f,IAAWxR,GAAS,SAAS,KAAKA,GAAS,IAAIlB,CAAG;AACxD,QAAAiS;AAAA,UACES,wBAAe,IAAA,wBAAY,IAAI,CAAC1S,CAAG,CAAC;AAAA,UACpC0S,IACI/e,EAAE,0BAA0B,IAC5BA,EAAE,6BAA6B,EAAE,MAAM8N,EAAA,CAAM;AAAA,QAAA;AAAA,MAErD;AAAA,MACA;AAAA,QACEiO;AAAA,QACAxM;AAAA,QACAoM;AAAA,QACArW;AAAA,QACAY;AAAA,QACAmY;AAAA,QACA9Q;AAAA,QACA+Q;AAAA,QACAle;AAAA,QACAJ;AAAA,MAAA;AAAA,IACF,GAGI2P,KAAUiC;AAAA,MACd,CACE7H,GACA2U,MACG;AACH,YAAI/C,MAAc,WAAWA,MAAc,WAAY;AACvD,cAAMzc,IAAOuf,GAAU1U,GAAM2U,CAAE;AAC/B,QACExf,EAAK,SAASqO,GAAS,QACvB,CAAC,GAAGrO,CAAI,EAAE,MAAM,CAACmN,MAAQkB,GAAS,IAAIlB,CAAG,CAAC,KAI5CiS,GAAgBpf,GAAMqf,GAAarf,EAAK,IAAI,GAAG,EAAI;AAAA,MACrD;AAAA,MACA,CAACyc,GAAW8C,IAAWlR,IAAU+Q,IAAiBC,EAAY;AAAA,IAAA,GAI1DS,KAAkBxR;AAAA,MACtB,MAAM,IAAI,IAAI,CAAC,GAAGwB,EAAQ,EAAE,IAAI,CAAC,CAACiQ,GAAKC,CAAK,MAAM,CAACA,GAAOD,CAAG,CAAC,CAAC;AAAA,MAC/D,CAACjQ,EAAQ;AAAA,IAAA,GAELmQ,KAAa;AAAA,MACjB,UAAA5R;AAAA,MACA,WAAAoO;AAAA,MACA,MAAAmB;AAAA,MACA,UAAAK;AAAA,MACA,WAAA9U;AAAA,MACA,WAAAD;AAAA,MACA,MAAA9C;AAAA,MACA,SAAAY;AAAA,MACA,cAAAuX;AAAA,MACA,UAAAzO;AAAA,MACA,iBAAAgQ;AAAA,MACA,cAAAtB;AAAA,MACA,iBAAAC;AAAA,MACA,QAAAnX;AAAA,MACA,OAAAzD;AAAA,MACA,SAAAia;AAAA,MACA,aAAAI;AAAA,MACA,mBAAAE;AAAA,MACA,iBAAAgB;AAAA,MACA,WAAAG;AAAA,MACA,cAAAF;AAAA,IAAA,GAEIa,IAASnP,EAAOkP,EAAU;AAChC,IAAAC,EAAO,UAAUD;AACjB,UAAME,KAAc7R,EAAuB,MAAM;AAC/C,YAAM8R,IAAS,CAACC,MAA+C;AAC7D,cAAM,EAAE,SAASC,GAAM,iBAAiBC,EAAA,IAAaL,EAAO,SACtDjB,IAAyB,CAAA;AAC/B,mBAAW9R,KAAOkT,GAAK;AACrB,gBAAM,CAAChY,GAAOuP,EAAS,IAAI1K,GAAkBC,CAAG,GAC1ChG,KAAIoZ,EAAS,IAAI3I,EAAS;AAEhC,UAAIzQ,OAAM,UAAW8X,EAAK,KAAK,EAAE,OAAA5W,GAAO,UAAUiY,EAAKnZ,EAAC,EAAE,GAAA,CAAI;AAAA,QAChE;AACA,eAAO8X;AAAA,MACT,GACM/a,IAAW,CAACtC,MAAyB;AACzC,cAAM,EAAE,cAAc4e,GAAO,iBAAiBD,EAAA,IAC5CL,EAAO,SACHrL,IAAW2L,EAAM,IAAI5e,EAAK,KAAK,GAC/BkT,IAAMyL,EAAS,IAAI,OAAO3e,EAAK,QAAQ,CAAC;AAC9C,eAAOiT,MAAa,UAAaC,MAAQ,SACrC,OACA,EAAE,UAAAD,GAAU,KAAAC,EAAA;AAAA,MAClB,GAEM2L,IAAc,CAAC7e,MAAyB;AAC5C,cAAMwL,IAAKlJ,EAAStC,CAAI;AACxB,YAAI,CAACwL;AACH,gBAAM,IAAI;AAAA,YACR,4BAA4BxL,EAAK,KAAK,cAAc,OAAOA,EAAK,QAAQ,CAAC;AAAA,UAAA;AAG7E,eAAOwL;AAAA,MACT,GACMsT,IAAmB,MAAM;AAC7B,YAAIR,EAAO,QAAQ,cAAc;AAC/B,gBAAM,IAAI,MAAM,+CAA+C;AAAA,MAEnE;AACA,aAAO;AAAA,QACL,cAAc,MAAME,EAAOF,EAAO,QAAQ,QAAQ;AAAA,QAClD,kBAAkB,MAAMA,EAAO,QAAQ;AAAA,QACvC,aAAa,CAACS,MAAkB;AAC9B,UAAAD,EAAA,GACAC,EAAc,QAAQF,CAAW;AACjC,gBAAM,EAAE,WAAWG,EAAA,IAASV,EAAO,SAC7BW,IACJD,MAAS,WAAWD,EAAc,MAAM,GAAG,CAAC,IAAIA,GAC5C3gB,IAAOic,GAAS4E,CAAM;AAC5B,UAAAX,EAAO,QAAQ;AAAA,YACblgB;AAAA,YACAkgB,EAAO,QAAQ,aAAalgB,EAAK,IAAI;AAAA,UAAA;AAAA,QAEzC;AAAA,QACA,aAAa,CAAC6K,GAAM2U,MAAO;AACzB,gBAAM,EAAE,WAAWoB,EAAA,IAASV,EAAO;AACnC,cAAIU,MAAS,WAAWA,MAAS;AAC/B,kBAAM,IAAI;AAAA,cACR;AAAA,YAAA;AAGJ,gBAAMtb,IAAImb,EAAY5V,CAAI,GACpBxH,IAAIod,EAAYjB,CAAE,GAClBxf,IAAOkgB,EAAO,QAAQ,UAAU5a,GAAGjC,CAAC;AAC1C,UAAA6c,EAAO,QAAQ;AAAA,YACblgB;AAAA,YACAkgB,EAAO,QAAQ,aAAalgB,EAAK,IAAI;AAAA,UAAA;AAAA,QAEzC;AAAA,QACA,gBAAgB,MAAM;AAEpB,UADA0gB,EAAA,GACIR,EAAO,QAAQ,SAAS,SAAS,KACrCA,EAAO,QAAQ;AAAA,gCACT,IAAA;AAAA,YACJA,EAAO,QAAQ,aAAa,CAAC;AAAA,UAAA;AAAA,QAEjC;AAAA,QACA,UAAU,CAACte,MAAS;AAClB,gBAAMwL,IAAKlJ,EAAStC,CAAI;AACxB,cAAI,CAACwL,EAAI,QAAO;AAChB,gBAAM0T,IAAQZ,EAAO,QAAQ,OAAO9S,EAAG,QAAQ,EAAEA,EAAG,GAAG;AACvD,iBAAO;AAAA,YACL,OAAO0T,EAAM;AAAA,YACb,OAAOA,EAAM;AAAA,YACb,QAAQA,EAAM;AAAA,YACd,MACEA,EAAM,WAAW,WAAWA,EAAM,UAAU,OACxCZ,EAAO,QAAQ,MAAM,OAAOY,EAAM,KAAK,IACvC;AAAA,UAAA;AAAA,QAEV;AAAA,QACA,SAAS,MAAMZ,EAAO,QAAQ;AAAA,QAC9B,SAAS,CAAClgB,MAASkgB,EAAO,QAAQ,QAAQlgB,CAAI;AAAA,QAC9C,aAAa,MAAMkgB,EAAO,QAAQ;AAAA,QAClC,aAAa,CAAClgB,MAASkgB,EAAO,QAAQ,YAAYlgB,CAAI;AAAA,QACtD,WAAW,MAAM;AACf,gBAAM,EAAE,cAAcggB,GAAO,MAAMe,EAAA,IAAQb,EAAO;AAClD,iBAAOF,EAAM;AAAA,YAAQ,CAACle,MACpBA,EAAI,SAAS,SAAS,CAACif,EAAIjf,EAAI,QAAQ,EAAE,EAAE,IAAI,CAAA;AAAA,UAAC;AAAA,QAEpD;AAAA,QACA,cAAc,MAAMoe,EAAO,QAAQ,QAAQ,IAAI,CAACne,MAAWA,EAAO,EAAE;AAAA,QACpE,aAAa,MAAM;AACjB,gBAAM;AAAA,YACJ,WAAW0Y;AAAA,YACX,cAAcuF;AAAA,YACd,UAAUzZ;AAAA,UAAA,IACR2Z,EAAO;AACX,iBAAKzF,IACEuF,EAAM;AAAA,YAAQ,CAACle,MACpBA,EAAI,SAAS,UAAU,CAACyE,EAAI,IAAIzE,EAAI,OAAO,KAAK,EAAE,IAAI,CAAA;AAAA,UAAC,IAFpC,CAAA;AAAA,QAIvB;AAAA,QACA,oBAAoB,MAAM;AACxB,gBAAM,EAAE,WAAW+P,GAAQ,UAAUtL,EAAA,IAAQ2Z,EAAO;AACpD,iBAAO,CAAC,GAAGrO,CAAM,EAAE,QAAQ,CAACkO,MAAQ;AAClC,kBAAMC,IAAQzZ,EAAI,IAAIwZ,CAAG;AACzB,mBAAOC,MAAU,SAAY,CAAA,IAAK,CAACA,CAAK;AAAA,UAC1C,CAAC;AAAA,QACH;AAAA,QACA,mBAAmB,CAAChe,GAASyH,MAAgB;AAC3C,gBAAM,EAAE,WAAWgR,GAAS,iBAAiBuG,EAAA,IAC3Cd,EAAO;AACT,cAAI,CAACzF;AACH,kBAAM,IAAI;AAAA,cACR;AAAA,YAAA;AAGJ,gBAAMsF,IAAMiB,EAAQ,IAAIhf,CAAO;AAC/B,cAAI+d,MAAQ;AACV,kBAAM,IAAI,MAAM,sBAAsB/d,CAAO,IAAI;AAEnD,UAAAke,EAAO,QAAQ,kBAAkBH,GAAKtW,CAAW;AAAA,QACnD;AAAA,MAAA;AAAA,IAEJ,GAAG,CAAA,CAAE;AACL,IAAAwX,GAAqBphB,IAAcsgB,IAAajD,EAAE;AAGlD,UAAMgE,KAAW5S;AAAA,MACf,MAAMhH,EAAO,KAAK,CAACxF,MAAQA,EAAI,KAAK,CAACF,MAASA,EAAK,WAAW,OAAO,CAAC;AAAA,MACtE,CAAC0F,CAAM;AAAA,IAAA,GAEH6Z,KAAe7S;AAAA,MACnB,MACEhH,EAAO,KAAK,CAACxF,MAAQA,EAAI,KAAK,CAACF,MAASA,EAAK,WAAW,YAAY,CAAC;AAAA,MACvE,CAAC0F,CAAM;AAAA,IAAA,GAEH0C,KAAUsE;AAAA,MACd,OAAO;AAAA,QACL,SAAA1C;AAAA,QACA,OAAA/H;AAAA,QACA,WAAA+L;AAAA,QACA,UAAAsR;AAAA,QACA,cAAAC;AAAA,QACA,UAAAza;AAAA,QACA,aAAA4J;AAAA,MAAA;AAAA,MAEF;AAAA,QACE1E;AAAA,QACA/H;AAAA,QACA+L;AAAA,QACAsR;AAAA,QACAC;AAAA,QACAza;AAAA,QACA4J;AAAA,MAAA;AAAA,IACF,GAII8Q,KAAgBrV,GAAoB,EAAE,WAAAoN,IAAW;AAEvD,QAAI4D;AACF,aACE,gBAAA7S,EAACjK,GAAe,UAAf,EAAwB,OAAO+J,IAC9B,UAAA,gBAAA6E;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAAuK;AAAA,UACA,kBAAe;AAAA,UACf,qBAAmB8D;AAAA,UACnB,WAAWkE;AAAA,UAEX,UAAA;AAAA,YAAA,gBAAAvS;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,cAAY/N,EAAE,iBAAiB;AAAA,gBAC/B,aAAU;AAAA,gBACV,WAAWiL,GAAA;AAAA,gBAEX,UAAA;AAAA,kBAAA,gBAAA7B;AAAA,oBAAC6R;AAAA,oBAAA;AAAA,sBACC,SAAQ;AAAA,sBACR,WAAU;AAAA,oBAAA;AAAA,kBAAA;AAAA,kBAEZ,gBAAA7R;AAAA,oBAAC6R;AAAA,oBAAA;AAAA,sBACC,SAAQ;AAAA,sBACR,WAAU;AAAA,oBAAA;AAAA,kBAAA;AAAA,gBACZ;AAAA,cAAA;AAAA,YAAA;AAAA,YAEDhS;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA,GAEL;AAIJ,QAAI3D,EAAK,WAAW,KAAKY,EAAQ,WAAW,KAAK,CAACO,GAAWD,CAAM;AACjE,aACE,gBAAA4C,EAACjK,GAAe,UAAf,EAAwB,OAAO+J,IAC9B,UAAA,gBAAA6E;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAAuK;AAAA,UACA,kBAAe;AAAA,UACf,qBAAmB8D;AAAA,UACnB,WAAWkE;AAAA,UAEX,UAAA;AAAA,YAAA,gBAAAlX;AAAA,cAACmX;AAAA,cAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,OAAOvgB,EAAE,qBAAqB;AAAA,gBAC9B,aAAaA,EAAE,2BAA2B;AAAA,cAAA;AAAA,YAAA;AAAA,YAE3CiJ;AAAA,UAAA;AAAA,QAAA;AAAA,MAAA,GAEL;AAIJ,UAAMmG,KACJ9J,EAAK,SAASY,EAAQ,SAASqD,IAC3B4F,KAAcwM,MAAc,UAAUI,MAAgB;AAE5D,WACE,gBAAA3S,EAACjK,GAAe,UAAf,EAAwB,OAAO+J,IAC9B,UAAA,gBAAA6E;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAuK;AAAA,QACA,kBAAe;AAAA,QACf,qBAAmB8D;AAAA,QACnB,WAAWkE;AAAA,QAEX,UAAA;AAAA,UAAA,gBAAAvS,EAAC,OAAA,EAAI,WAAW5C,GAAA,GACb,UAAA;AAAA,YAAAmQ,MAAW,KAAQ,gBAAAlS,EAACwO,IAAA,EAAc,SAAS0D,GAAQ,IAAK;AAAA,YACzD,gBAAAlS;AAAA,cAACoX;AAAA,cAAA;AAAA,gBACC,QAAO;AAAA,gBACP,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,WACE1D,OAAS,UACP,gBAAA1T,EAACzK,IAAA,EAAQ,eAAY,OAAA,CAAO,IAE5B,gBAAAyK,EAACvK,IAAA,EAAO,eAAY,OAAA,CAAO;AAAA,gBAI/B,gBACEie,OAAS,UAAU,SAAYrD;AAAA,gBAEjC,SAASqD,OAAS,UAAU,SAAYrD;AAAA,gBACxC,SAAS,MAAMuD,GAAQF,OAAS,UAAU,YAAY,OAAO;AAAA,gBAE5D,UACG9c,SADM,UACJ,0BACA,qBADuB;AAAA,cACF;AAAA,YAAA;AAAA,UAC7B,GACF;AAAA,UACC8c,OAAS,UACR,gBAAA1T;AAAA,YAACsQ;AAAA,YAAA;AAAA,cAKC,aAAa,MAAMgD,EAAS1c,EAAE,8BAA8B,CAAC;AAAA,cAC7D,OAAA4O;AAAA,cACA,WAAAC;AAAA,cACA,MAAAvJ;AAAA,cACA,SAAAY;AAAA,cACA,QAAAM;AAAA,cACA,MAAMiX;AAAA,cACN,SAASrV;AAAA,cACT,UAAA4G;AAAA,cACA,WAAAF;AAAA,cACA,QAAAnH;AAAA,cACA,WAAAZ;AAAA,cACA,cAAAC;AAAA,cACA,mBAAAF;AAAA,cACA,UAAAlB;AAAA,YAAA;AAAA,YAfK,GAAG3F,CAAW,IAAIC,CAAY;AAAA,UAAA,IAkBrC,gBAAAkJ,EAACqX,IAAA,EAAgB,eAAe,GAC9B,UAAA,gBAAArX;AAAA,YAACsF;AAAA,YAAA;AAAA,cACC,OAAAE;AAAA,cACA,WAAAC;AAAA,cACA,MAAAvJ;AAAA,cACA,SAAAY;AAAA,cACA,QAAAM;AAAA,cACA,MAAAiC;AAAA,cACA,OAAA1F;AAAA,cACA,SAAA+H;AAAA,cACA,WAAAgE;AAAA,cACA,YAAAC;AAAA,cACA,QAAApH;AAAA,cACA,WAAAZ;AAAA,cACA,cAAAC;AAAA,cACA,mBAAAF;AAAA,cACA,UAAAkI;AAAA,cACA,UAAApJ;AAAA,cACA,eAAe+V;AAAA,cACf,UAAApO;AAAA,cACA,kBAAA2B;AAAA,cACA,aAAAC;AAAA,cACA,aAAAC;AAAA,cACA,MAAAC;AAAA,cACA,SAAAC;AAAA,cACA,UAAAC;AAAA,cACA,aAAAC;AAAA,cACA,iBAAiBwM,MAAkB;AAAA,cACnC,YAAAtM;AAAA,cACA,SAAAC;AAAA,cACA,eAAe4N;AAAA,YAAA;AAAA,UAAA,GAEnB;AAAA,UAEDtU;AAAA,UAID,gBAAAG,EAACsX,IAAA,EAAsC,UAAA7D,GAAA,GAAtB,OAAO5c,CAAW,CAAW;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA,GAElD;AAAA,EAEJ;AACF;AAEAob,GAAY,cAAc;AAOnB,MAAMsF,KAAU,OAAO,OAAOtF,IAAa;AAAA,EAChD,QAAQzD;AAAA,EACR,SAAShP;AACX,CAAC;","x_google_ignoreList":[0,1]}
|
|
1
|
+
{"version":3,"file":"heatmap-DiyOSQk9.js","sources":["../../node_modules/lucide-react/dist/esm/icons/grid-3x3.mjs","../../node_modules/lucide-react/dist/esm/icons/table-2.mjs","../../src/components/heatmap/heatmap.agent.ts","../../src/components/heatmap/heatmap-context.ts","../../src/components/heatmap/heatmap-format.ts","../../src/components/heatmap/heatmap-scale.ts","../../src/components/heatmap/heatmap-model.ts","../../src/components/heatmap/heatmap-tooltip.tsx","../../src/components/heatmap/heatmap-window.ts","../../src/components/heatmap/heatmap-variants.ts","../../src/components/heatmap/heatmap-grid.tsx","../../src/components/heatmap/heatmap-legend.tsx","../../src/components/heatmap/heatmap-table-view.tsx","../../src/components/heatmap/heatmap.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 [\"rect\", { width: \"18\", height: \"18\", x: \"3\", y: \"3\", rx: \"2\", key: \"afitv7\" }],\n [\"path\", { d: \"M3 9h18\", key: \"1pudct\" }],\n [\"path\", { d: \"M3 15h18\", key: \"5xshup\" }],\n [\"path\", { d: \"M9 3v18\", key: \"fh3hqa\" }],\n [\"path\", { d: \"M15 3v18\", key: \"14nvp0\" }]\n];\nconst Grid3x3 = createLucideIcon(\"grid-3x3\", __iconNode);\n\nexport { __iconNode, Grid3x3 as default };\n//# sourceMappingURL=grid-3x3.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 [\n \"path\",\n {\n d: \"M9 3H5a2 2 0 0 0-2 2v4m6-6h10a2 2 0 0 1 2 2v4M9 3v18m0 0h10a2 2 0 0 0 2-2V9M9 21H5a2 2 0 0 1-2-2V9m0 0h18\",\n key: \"gugj83\"\n }\n ]\n];\nconst Table2 = createLucideIcon(\"table-2\", __iconNode);\n\nexport { __iconNode, Table2 as default };\n//# sourceMappingURL=table-2.mjs.map\n","/* -------------------------------------------------------------------- */\n/* Agent adapter: Heatmap. */\n/* */\n/* Operations go through the curated `HeatmapHandle`. State returns ids, */\n/* numbers and structure only: never a row, column or group label, which */\n/* may name a person (src/docs/26-agent-readiness.mdx §7). The row, */\n/* column and group ids are state so an agent can address any cell, even */\n/* one a virtualised grid has not rendered. Every write rejects an id */\n/* the heatmap does not have before it changes or announces anything. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { HeatmapHandle } from './heatmap';\n\nconst cellSchema = {\n type: 'object',\n properties: {\n rowId: { type: 'string', description: 'Row id, from rowIds.' },\n columnId: {\n type: ['string', 'number'],\n description: 'Column id, from columnIds.',\n },\n },\n required: ['rowId', 'columnId'],\n} as const;\n\nexport const heatmapAgent: AgentAdapter<HeatmapHandle> = {\n id: 'heatmap',\n capabilities: [\n 'select_single',\n 'select_multiple',\n 'range_pick',\n 'expand',\n 'sort',\n 'view_change',\n ],\n state: {\n selection: {\n type: 'Array<{ rowId, columnId }>',\n descriptionKey: 'ui.agent.heatmap.state.selection',\n description: 'Row and column ids of the selected cells.',\n read: (handle) => handle.getSelection(),\n },\n selectionMode: {\n type: \"'none' | 'single' | 'multiple' | 'range'\",\n descriptionKey: 'ui.agent.heatmap.state.selectionMode',\n description: 'How cells can be selected in this heatmap.',\n read: (handle) => handle.getSelectionMode(),\n },\n view: {\n type: \"'heatmap' | 'table'\",\n descriptionKey: 'ui.agent.heatmap.state.view',\n description: 'Whether the heatmap or its table view is showing.',\n read: (handle) => handle.getView(),\n },\n sortRows: {\n type: \"'none' | 'label' | 'total-asc' | 'total-desc'\",\n descriptionKey: 'ui.agent.heatmap.state.sortRows',\n description: 'Current row order.',\n read: (handle) => handle.getSortRows(),\n },\n rowIds: {\n type: 'string[]',\n descriptionKey: 'ui.agent.heatmap.state.rowIds',\n description:\n 'Row ids in display order, every group expanded. Opaque, never a label.',\n read: (handle) => handle.getRowIds(),\n },\n columnIds: {\n type: 'Array<string | number>',\n descriptionKey: 'ui.agent.heatmap.state.columnIds',\n description: 'Column ids in order. Opaque, never a label.',\n read: (handle) => handle.getColumnIds(),\n },\n groupIds: {\n type: 'string[]',\n descriptionKey: 'ui.agent.heatmap.state.groupIds',\n description:\n 'Group ids in display order, empty unless rows are grouped. A group not listed in `groups` shows as group-1, group-2 and so on.',\n read: (handle) => handle.getGroupIds(),\n },\n collapsedGroups: {\n type: 'string[]',\n descriptionKey: 'ui.agent.heatmap.state.collapsedGroups',\n description: 'Ids (as in groupIds) of the row groups that are collapsed.',\n read: (handle) => handle.getCollapsedGroups(),\n },\n },\n actions: {\n select_cell: {\n safety: 'read',\n argsType: '{ rowId: string, columnId: string | number }',\n argsSchema: cellSchema,\n idempotent: true,\n descriptionKey: 'ui.agent.heatmap.actions.selectCell',\n description: 'Make one cell the whole selection.',\n errors: [\n 'Selection is off (selection=\"none\").',\n 'The row or column id does not exist.',\n ],\n examples: [\n {\n args: { rowId: 'chair-1', columnId: 10 },\n note: 'Select chair 1 at 10:00.',\n },\n ],\n invoke: (handle, args: { rowId: string; columnId: string | number }) => {\n handle.selectCells([args]);\n },\n },\n select_cells: {\n safety: 'read',\n argsType: '{ cells: Array<{ rowId, columnId }> }',\n argsSchema: {\n type: 'object',\n properties: {\n cells: {\n type: 'array',\n items: cellSchema,\n description:\n 'Cells to select; replaces the selection. Single mode keeps the first.',\n },\n },\n required: ['cells'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.heatmap.actions.selectCells',\n description: 'Replace the selection with the given cells.',\n errors: [\n 'Selection is off (selection=\"none\").',\n 'A row or column id does not exist; nothing is selected.',\n ],\n invoke: (\n handle,\n args: { cells: { rowId: string; columnId: string | number }[] },\n ) => {\n handle.selectCells(args.cells);\n },\n },\n select_range: {\n safety: 'read',\n argsType: '{ from: { rowId, columnId }, to: { rowId, columnId } }',\n argsSchema: {\n type: 'object',\n properties: {\n from: { ...cellSchema, description: 'One corner, inclusive.' },\n to: { ...cellSchema, description: 'The opposite corner, inclusive.' },\n },\n required: ['from', 'to'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.heatmap.actions.selectRange',\n description:\n 'Select the rectangle of cells between two corners, in the rows as shown.',\n errors: [\n 'Needs selection=\"range\" or \"multiple\".',\n 'A corner names a row or column that does not exist.',\n ],\n invoke: (\n handle,\n args: {\n from: { rowId: string; columnId: string | number };\n to: { rowId: string; columnId: string | number };\n },\n ) => {\n handle.selectRange(args.from, args.to);\n },\n },\n clear_selection: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.heatmap.actions.clearSelection',\n description: 'Deselect every cell.',\n errors: ['Selection is off (selection=\"none\").'],\n invoke: (handle) => {\n handle.clearSelection();\n },\n },\n read_cell: {\n safety: 'read',\n argsType: '{ rowId: string, columnId: string | number }',\n argsSchema: cellSchema,\n returns: '{ value, count, status, step } | null',\n returnsSchema: {\n type: ['object', 'null'],\n properties: {\n value: { type: ['number', 'null'] },\n count: { type: 'number' },\n status: { enum: ['value', 'empty', 'low-sample'] },\n step: { type: ['number', 'null'] },\n },\n },\n idempotent: true,\n descriptionKey: 'ui.agent.heatmap.actions.readCell',\n description:\n \"Read a cell's value, count, status and colour step (no labels).\",\n invoke: (handle, args: { rowId: string; columnId: string | number }) =>\n handle.readCell(args),\n },\n toggle_table_view: {\n safety: 'read',\n descriptionKey: 'ui.agent.heatmap.actions.toggleTableView',\n description: 'Switch between the heatmap and its table view.',\n returns: \"'heatmap' | 'table'\",\n returnsSchema: { enum: ['heatmap', 'table'] },\n invoke: (handle) => {\n const next = handle.getView() === 'table' ? 'heatmap' : 'table';\n handle.setView(next);\n return next;\n },\n },\n set_view: {\n safety: 'read',\n argsType: \"{ view: 'heatmap' | 'table' }\",\n argsSchema: {\n type: 'object',\n properties: {\n view: {\n enum: ['heatmap', 'table'],\n description: 'The coloured grid, or the same data as a table.',\n },\n },\n required: ['view'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.heatmap.actions.setView',\n description: 'Show the heatmap or its table view.',\n invoke: (handle, args: { view: 'heatmap' | 'table' }) => {\n if (handle.getView() !== args.view) handle.setView(args.view);\n },\n },\n sort_rows: {\n safety: 'read',\n argsType: \"{ sort: 'none' | 'label' | 'total-asc' | 'total-desc' }\",\n argsSchema: {\n type: 'object',\n properties: {\n sort: {\n enum: ['none', 'label', 'total-asc', 'total-desc'],\n description:\n 'Row order within each group: as given, by label, or by row total.',\n },\n },\n required: ['sort'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.heatmap.actions.sortRows',\n description: 'Reorder the rows.',\n invoke: (\n handle,\n args: { sort: 'none' | 'label' | 'total-asc' | 'total-desc' },\n ) => {\n handle.setSortRows(args.sort);\n },\n },\n expand_group: {\n safety: 'read',\n argsType: '{ groupId: string }',\n argsSchema: {\n type: 'object',\n properties: {\n groupId: { type: 'string', description: 'Group id, from groupIds.' },\n },\n required: ['groupId'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.heatmap.actions.expandGroup',\n description: \"Show a group's rows.\",\n errors: [\n 'Rows are not grouped (groupRows is off).',\n 'The group id does not exist (see groupIds).',\n ],\n invoke: (handle, args: { groupId: string }) => {\n handle.setGroupCollapsed(args.groupId, false);\n },\n },\n collapse_group: {\n safety: 'read',\n argsType: '{ groupId: string }',\n argsSchema: {\n type: 'object',\n properties: {\n groupId: { type: 'string', description: 'Group id, from groupIds.' },\n },\n required: ['groupId'],\n },\n idempotent: true,\n descriptionKey: 'ui.agent.heatmap.actions.collapseGroup',\n description: \"Hide a group's rows, leaving its totals row.\",\n errors: [\n 'Rows are not grouped (groupRows is off).',\n 'The group id does not exist (see groupIds).',\n ],\n invoke: (handle, args: { groupId: string }) => {\n handle.setGroupCollapsed(args.groupId, true);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'heatmap',\n description: 'Marks the Heatmap root.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop on Heatmap.',\n },\n item: {\n attr: 'data-heatmap-cell-id',\n description:\n 'On every data cell: \"<rowId>:<columnId>\", built from the opaque ids, never from labels. A group header row and its cells carry data-heatmap-group-id, the group id as in groupIds.',\n },\n },\n};\n","/* -------------------------------------------------------------------- */\n/* Context shared by the Heatmap root and its compound parts, so */\n/* Heatmap.Legend and Heatmap.Tooltip read the same scale, palette and */\n/* wording as the grid. */\n/* -------------------------------------------------------------------- */\n\nimport { createContext, useContext } from 'react';\nimport type { HeatmapDescriber } from './heatmap-format';\nimport type { HeatmapCellInfo } from './heatmap-model';\nimport type { ResolvedHeatmapScale } from './heatmap-scale';\nimport type { HeatmapPalette } from './heatmap-variants';\n\nexport interface HeatmapContextValue {\n palette: HeatmapPalette;\n scale: ResolvedHeatmapScale;\n describer: HeatmapDescriber;\n /** True when some cells fall below `minCount`, so the legend explains it. */\n hasLowSample: boolean;\n /** True when some cells have no data. */\n hasEmpty: boolean;\n /** The sample threshold, when one is set. */\n minCount?: number;\n /** The tooltip text for a cell: the consumer's, or the default sentence. */\n tooltipText: (cell: HeatmapCellInfo) => string;\n}\n\nexport const HeatmapContext = createContext<HeatmapContextValue | null>(null);\n\n/** The surrounding Heatmap's context, or null outside one. */\nexport function useHeatmapContext(): HeatmapContextValue | null {\n return useContext(HeatmapContext);\n}\n","/* -------------------------------------------------------------------- */\n/* Heatmap text: number formats in the active locale, and the sentences */\n/* the cells, totals, tooltip and table view share, with privacy mode */\n/* applied in one place. */\n/* -------------------------------------------------------------------- */\n\nimport type { TFunction } from 'i18next';\nimport { privacyMask } from '../_shared/privacy-mask';\nimport type {\n HeatmapColumn,\n HeatmapGroup,\n HeatmapRow,\n ModelCell,\n} from './heatmap-model';\nimport type { HeatmapAggregate } from './heatmap-scale';\n\n/** What the values are: plain numbers, or rates between 0 and 1. */\nexport type HeatmapValueType = 'number' | 'rate';\n\n/**\n * What privacy mode masks. `rows`: the row labels, which name people,\n * chairs or patients. `all`: the column and group labels too. The kit rule\n * (src/components/_shared/privacy-mask.tsx) is to mask the identity and keep\n * time, place and status, so columns (hours, days) and groups (practices)\n * stay readable unless the host asks for more.\n */\nexport type HeatmapPrivacyScope = 'rows' | 'all';\n\n/** The default value format: a percentage for rates, a decimal otherwise. */\nexport function defaultValueFormatter(\n locale: string,\n valueType: HeatmapValueType,\n): (value: number) => string {\n const format = new Intl.NumberFormat(\n locale,\n valueType === 'rate'\n ? { style: 'percent', maximumFractionDigits: 0 }\n : { maximumFractionDigits: 2 },\n );\n return (value) => format.format(value);\n}\n\n/** Whole-number format for counts. */\nexport function countFormatter(locale: string): (count: number) => string {\n const format = new Intl.NumberFormat(locale, { maximumFractionDigits: 0 });\n return (count) => format.format(count);\n}\n\n/** Builds every sentence the heatmap speaks or shows. */\nexport interface HeatmapDescriber {\n /** True when privacy mode hides the row labels. */\n masksRows: boolean;\n /** True when privacy mode hides the column labels. */\n masksColumns: boolean;\n /** True when privacy mode hides the group labels. */\n masksGroups: boolean;\n rowLabel: (row: HeatmapRow) => string;\n columnLabel: (column: HeatmapColumn) => string;\n groupLabel: (groupId: string) => string;\n /** A cell by its headers: \"Tuesday, 10:00\". */\n cellName: (rowText: string, columnText: string) => string;\n /** A group header row: \"Mos Eisley (Average)\". */\n groupRowText: (groupText: string, method: HeatmapAggregate) => string;\n /** A cell as the table view shows it: \"26%, 10 of 39\". */\n tableText: (cell: ModelCell) => string;\n /** Label for a margin: \"Total\" for a sum, \"Average\" for a mean. */\n methodLabel: (method: HeatmapAggregate) => string;\n /** The value as text: formatted, a cell label, \"no data\" or \"too few\". */\n valueText: (cell: ModelCell) => string;\n /** The value as shown inside a cell, or '' when the cell shows none. */\n visibleText: (cell: ModelCell) => string;\n /** \"10 of 39\" for a rate, \"39 records\" otherwise; null without a count. */\n countText: (cell: ModelCell) => string | null;\n /** \"Tuesday, 10:00: 26%, 10 of 39\". */\n sentence: (rowText: string, columnText: string, cell: ModelCell) => string;\n /** Format for a raw value, used by the legend. */\n formatValue: (value: number) => string;\n}\n\nexport interface DescriberOptions {\n t: TFunction<'ui'>;\n privacyMode: boolean;\n /** What privacy mode masks. Default `rows`. */\n privacyScope?: HeatmapPrivacyScope;\n valueType: HeatmapValueType;\n formatValue: (value: number) => string;\n formatCount: (count: number) => string;\n groups?: readonly HeatmapGroup[];\n}\n\n/** The glyph an empty cell shows, so \"no data\" never relies on colour. */\nconst EMPTY_GLYPH = '–';\n\nexport function createDescriber({\n t,\n privacyMode,\n privacyScope = 'rows',\n valueType,\n formatValue,\n formatCount,\n groups,\n}: DescriberOptions): HeatmapDescriber {\n const groupNames = new Map(groups?.map((group) => [group.id, group.label]));\n const mask = privacyMask();\n const masksRows = privacyMode;\n const masksColumns = privacyMode && privacyScope === 'all';\n const masksGroups = privacyMode && privacyScope === 'all';\n const valueText = (cell: ModelCell): string => {\n if (cell.status === 'empty') return t('heatmap.noData');\n if (cell.status === 'low-sample') return t('heatmap.lowSample');\n // A cell label is free text, so privacy mode shows the number instead.\n if (cell.label !== undefined && !privacyMode) return cell.label;\n return cell.value === null ? t('heatmap.noData') : formatValue(cell.value);\n };\n const countText = (cell: ModelCell): string | null => {\n if (cell.count === undefined) return null;\n if (\n valueType === 'rate' &&\n cell.status === 'value' &&\n cell.value !== null\n ) {\n return t('heatmap.countOf', {\n part: formatCount(Math.round(cell.value * cell.count)),\n total: formatCount(cell.count),\n });\n }\n return t('heatmap.records', {\n count: cell.count,\n formatted: formatCount(cell.count),\n });\n };\n return {\n masksRows,\n masksColumns,\n masksGroups,\n rowLabel: (row) => (masksRows ? mask : row.label),\n columnLabel: (column) => (masksColumns ? mask : column.label),\n // A group missing from `groups` has only its id to show, which may be a\n // name, so privacy mode masks it whatever the scope.\n groupLabel: (groupId) =>\n masksGroups\n ? mask\n : (groupNames.get(groupId) ?? (privacyMode ? mask : groupId)),\n cellName: (rowText, columnText) =>\n t('heatmap.cellName', { row: rowText, column: columnText }),\n groupRowText: (groupText, method) =>\n t('heatmap.groupRow', {\n group: groupText,\n method:\n method === 'sum' ? t('heatmap.totals.sum') : t('heatmap.totals.mean'),\n }),\n tableText: (cell) => {\n const count = cell.status === 'empty' ? null : countText(cell);\n const value = valueText(cell);\n return count === null\n ? value\n : t('heatmap.valueWithCount', { value, count });\n },\n methodLabel: (method) =>\n method === 'sum' ? t('heatmap.totals.sum') : t('heatmap.totals.mean'),\n valueText,\n visibleText: (cell) =>\n cell.status === 'empty'\n ? EMPTY_GLYPH\n : cell.status === 'low-sample'\n ? ''\n : valueText(cell),\n countText,\n sentence: (rowText, columnText, cell) => {\n const count = countText(cell);\n const value = valueText(cell);\n return count === null || cell.status === 'empty'\n ? t('heatmap.cell', { row: rowText, column: columnText, value })\n : t('heatmap.cellWithCount', {\n row: rowText,\n column: columnText,\n value,\n count,\n });\n },\n formatValue,\n };\n}\n","/* -------------------------------------------------------------------- */\n/* Heatmap scale maths. Pure functions, no React, so they are tested on */\n/* their own (heatmap-scale.test.ts) and shared by the grid, the legend */\n/* and the table view. */\n/* */\n/* Every scale maps a value to one of ten colour steps, 0 to 9. The */\n/* steps are tokens (`--heatmap-<palette>-<step>`), so a scale never */\n/* produces a colour itself. */\n/* -------------------------------------------------------------------- */\n\nimport { isDevelopment } from '../_shared/is-development';\n\n/** Number of colour steps every palette carries. */\nexport const HEATMAP_STEPS = 10;\n\n/** The step a degenerate scale (every value equal) falls back to. */\nconst MIDDLE_STEP = Math.floor(HEATMAP_STEPS / 2);\n\n/** Highest step index. */\nconst TOP_STEP = HEATMAP_STEPS - 1;\n\n/** Steps on each side of a diverging midpoint. */\nconst HALF_STEPS = HEATMAP_STEPS / 2;\n\n/**\n * How values map to colour steps.\n *\n * - `sequential`: low to high. `domain: 'auto'` (the default) uses the min\n * and max of the cells that show a value; a fixed `[min, max]` clamps.\n * - `diverging`: two hues either side of `midpoint`. `auto` makes the\n * domain symmetric around the midpoint, so equal distances either side\n * get equal intensity. The midpoint defaults to 0, or to the centre of a\n * fixed domain that does not include 0.\n * - `quantile`: equal-count buckets (default 10) from the shown values.\n * Repeated values never split: buckets that would cut through a run of\n * equal values merge, so the minimum always takes the first step.\n * - `threshold`: ascending cut points; `n` thresholds make `n + 1`\n * buckets, spread across the ten steps. At most nine; duplicates merge.\n *\n * A fixed domain is `[min, max]`. A reversed pair is put in order, with a\n * warning in development builds.\n */\nexport type HeatmapScale =\n | { type: 'sequential'; domain?: 'auto' | readonly [number, number] }\n | {\n type: 'diverging';\n domain?: 'auto' | readonly [number, number];\n midpoint?: number;\n }\n | { type: 'quantile'; buckets?: number }\n | { type: 'threshold'; thresholds: readonly number[] };\n\n/** A scale with its domain worked out against the data. */\nexport interface ResolvedHeatmapScale {\n type: HeatmapScale['type'];\n /** Low end of the domain, or of the data for quantile and threshold. */\n min: number | null;\n /** High end of the domain, or of the data for quantile and threshold. */\n max: number | null;\n /** Diverging only: the value that separates the two hues. */\n midpoint?: number;\n /** Quantile and threshold: the ascending bucket edges. */\n thresholds: readonly number[];\n /** Maps a value to a step, 0 to 9. */\n stepOf: (value: number) => number;\n}\n\nconst clamp = (value: number, low: number, high: number): number =>\n Math.min(high, Math.max(low, value));\n\n/** Messages already given, so a scale worked out again (each data change,\n * twice in StrictMode) does not repeat them. */\nconst warned = new Set<string>();\n\n/** Says what a scale was given and what it uses instead, in development,\n * once per message. */\nfunction warn(message: string): void {\n if (!isDevelopment() || warned.has(message)) return;\n warned.add(message);\n console.warn(`Heatmap: ${message}`);\n}\n\n/** A fixed domain in ascending order (a reversed one is put in order). */\nfunction orderedDomain(\n domain: readonly [number, number],\n): readonly [number, number] {\n if (domain[0] <= domain[1]) return domain;\n warn(\n `scale domain [${domain[0]}, ${domain[1]}] is reversed; using [${domain[1]}, ${domain[0]}].`,\n );\n return [domain[1], domain[0]];\n}\n\n/** Sorted, distinct, finite values. */\nfunction distinctSorted(values: readonly number[]): number[] {\n const sorted = values.filter(Number.isFinite).sort((a, b) => a - b);\n return sorted.filter((value, i) => i === 0 || value !== sorted[i - 1]);\n}\n\n/** Min and max of the finite values, or null when there are none. */\nexport function extent(values: readonly number[]): [number, number] | null {\n let low = Infinity;\n let high = -Infinity;\n for (const value of values) {\n if (!Number.isFinite(value)) continue;\n if (value < low) low = value;\n if (value > high) high = value;\n }\n return low === Infinity ? null : [low, high];\n}\n\n/**\n * Sequential step: the domain is cut into ten equal bands. A value on a\n * band edge takes the band above; the top edge belongs to the top step.\n * Values outside the domain clamp to the end steps.\n */\nexport function sequentialStep(value: number, low: number, high: number) {\n if (!(high > low)) return MIDDLE_STEP;\n const t = clamp((value - low) / (high - low), 0, 1);\n return Math.min(TOP_STEP, Math.floor(t * HEATMAP_STEPS));\n}\n\n/**\n * Diverging step: steps 0 to 4 sit below the midpoint (0 is the furthest),\n * steps 5 to 9 above it (9 is the furthest). Ten steps have no middle one,\n * so a value exactly on the midpoint takes step 5, the palest step above.\n * It is painted in the neutral midpoint colour instead (see `onMidpoint`).\n */\nexport function divergingStep(\n value: number,\n low: number,\n midpoint: number,\n high: number,\n): number {\n if (value < midpoint) {\n const span = midpoint - low;\n const t = span > 0 ? clamp((midpoint - value) / span, 0, 1) : 1;\n return (\n HALF_STEPS - 1 - Math.min(HALF_STEPS - 1, Math.floor(t * HALF_STEPS))\n );\n }\n const span = high - midpoint;\n const t =\n span > 0\n ? clamp((value - midpoint) / span, 0, 1)\n : value > midpoint\n ? 1\n : 0;\n return HALF_STEPS + Math.min(HALF_STEPS - 1, Math.floor(t * HALF_STEPS));\n}\n\n/**\n * Whether a value sits exactly on a diverging scale's midpoint, so it is\n * painted neutral (`--heatmap-midpoint`) rather than in either hue. Exact\n * up to floating-point rounding, a few units in the last place of the\n * scale's largest magnitude: the centre of [0.1, 0.2] is computed as\n * 0.15000000000000002, and 0.1 + 0.2 - 0.3 is not quite 0. A value that\n * merely rounds to the midpoint when printed keeps its step. Other scale\n * types have no midpoint.\n */\nexport function onMidpoint(\n scale: ResolvedHeatmapScale,\n value: number,\n): boolean {\n if (scale.type !== 'diverging' || scale.midpoint === undefined) return false;\n const magnitude = Math.max(\n Math.abs(scale.midpoint),\n Math.abs(scale.min ?? 0),\n Math.abs(scale.max ?? 0),\n );\n return Math.abs(value - scale.midpoint) <= magnitude * Number.EPSILON * 16;\n}\n\n/**\n * Quantile of a sorted array at `p` (0 to 1), interpolating linearly\n * between neighbours (the R-7 method spreadsheets use).\n */\nexport function quantileSorted(sorted: readonly number[], p: number): number {\n const n = sorted.length;\n if (n === 0) return NaN;\n if (n === 1) return sorted[0];\n const position = clamp(p, 0, 1) * (n - 1);\n const below = Math.floor(position);\n const above = Math.min(n - 1, below + 1);\n return sorted[below] + (sorted[above] - sorted[below]) * (position - below);\n}\n\n/** The `buckets - 1` inner edges that cut sorted values into equal counts. */\nexport function quantileThresholds(\n sorted: readonly number[],\n buckets: number,\n): number[] {\n const count = Math.max(1, Math.round(buckets));\n const edges: number[] = [];\n for (let i = 1; i < count; i += 1) {\n edges.push(quantileSorted(sorted, i / count));\n }\n return edges;\n}\n\n/**\n * Quantile edges that cut something. Each raw edge moves up to the first\n * value at or above it, which puts every value in the same bucket but makes\n * the edge a value the data holds, so no bucket is left empty (an edge\n * between two values could cut a band nothing falls in). Then edges that\n * repeat go: when many values repeat (60% of cells at zero), several raw\n * edges land on the same value, and kept they would put the minimum\n * mid-scale. An edge at the minimum has nothing below it, so it goes too.\n */\nexport function usableQuantileEdges(\n sorted: readonly number[],\n buckets: number,\n): number[] {\n if (sorted.length === 0) return [];\n const min = sorted[0];\n const atOrAbove = (edge: number): number => {\n let low = 0;\n let high = sorted.length - 1;\n while (low < high) {\n const mid = (low + high) >>> 1;\n if (sorted[mid] < edge) low = mid + 1;\n else high = mid;\n }\n return sorted[low];\n };\n return distinctSorted(\n quantileThresholds(sorted, buckets).map(atOrAbove),\n ).filter((edge) => edge > min);\n}\n\n/** How many edges are at or below `value`: its bucket, 0 to edges.length. */\nexport function thresholdBucket(\n value: number,\n thresholds: readonly number[],\n): number {\n let low = 0;\n let high = thresholds.length;\n while (low < high) {\n const mid = (low + high) >>> 1;\n if (thresholds[mid] <= value) low = mid + 1;\n else high = mid;\n }\n return low;\n}\n\n/** Spreads bucket `bucket` of `bucketCount` evenly across the ten steps. */\nexport function bucketStep(bucket: number, bucketCount: number): number {\n if (bucketCount <= 1) return MIDDLE_STEP;\n return Math.round(\n (clamp(bucket, 0, bucketCount - 1) * TOP_STEP) / (bucketCount - 1),\n );\n}\n\n/**\n * Works out a scale against the values that will be shown. Pass only the\n * values of cells that render a colour: empty and low-sample cells must not\n * stretch the domain.\n */\nexport function resolveScale(\n scale: HeatmapScale,\n values: readonly number[],\n): ResolvedHeatmapScale {\n const range = extent(values);\n\n switch (scale.type) {\n case 'diverging': {\n const fixed =\n scale.domain && scale.domain !== 'auto'\n ? orderedDomain(scale.domain)\n : null;\n // Zero is the natural midpoint of a change, but only when the domain\n // reaches it: a fixed domain of [10, 50] would leave the lower hue\n // unused, so its centre divides it instead.\n const midpoint =\n scale.midpoint ??\n (fixed && (fixed[0] > 0 || fixed[1] < 0)\n ? (fixed[0] + fixed[1]) / 2\n : 0);\n let low: number;\n let high: number;\n if (fixed) {\n [low, high] = fixed;\n } else {\n const reach = range\n ? Math.max(\n Math.abs(range[0] - midpoint),\n Math.abs(range[1] - midpoint),\n )\n : 0;\n low = midpoint - reach;\n high = midpoint + reach;\n }\n return {\n type: 'diverging',\n min: low,\n max: high,\n midpoint,\n thresholds: [],\n stepOf: (value) => divergingStep(value, low, midpoint, high),\n };\n }\n case 'quantile': {\n const sorted = values\n .filter(Number.isFinite)\n .slice()\n .sort((a, b) => a - b);\n const buckets = clamp(\n Math.round(scale.buckets ?? HEATMAP_STEPS),\n 2,\n HEATMAP_STEPS,\n );\n // Every value equal leaves no edge: one bucket, on the middle step,\n // as a sequential scale does.\n const thresholds = usableQuantileEdges(sorted, buckets);\n return {\n type: 'quantile',\n min: range?.[0] ?? null,\n max: range?.[1] ?? null,\n thresholds,\n stepOf: (value) =>\n bucketStep(thresholdBucket(value, thresholds), thresholds.length + 1),\n };\n }\n case 'threshold': {\n const given = scale.thresholds.filter(Number.isFinite);\n const distinct = distinctSorted(given);\n if (distinct.length !== given.length) {\n warn('duplicate thresholds merged.');\n }\n if (distinct.length > TOP_STEP) {\n warn(\n `${distinct.length} thresholds given; ten steps take at most ${TOP_STEP}, so the highest ${distinct.length - TOP_STEP} are dropped.`,\n );\n }\n const thresholds = distinct.slice(0, TOP_STEP);\n return {\n type: 'threshold',\n min: range?.[0] ?? null,\n max: range?.[1] ?? null,\n thresholds,\n stepOf: (value) =>\n bucketStep(thresholdBucket(value, thresholds), thresholds.length + 1),\n };\n }\n case 'sequential':\n default: {\n const fixed =\n scale.domain && scale.domain !== 'auto'\n ? orderedDomain(scale.domain)\n : null;\n const low = fixed ? fixed[0] : (range?.[0] ?? null);\n const high = fixed ? fixed[1] : (range?.[1] ?? null);\n return {\n type: 'sequential',\n min: low,\n max: high,\n thresholds: [],\n stepOf: (value) =>\n low === null || high === null\n ? MIDDLE_STEP\n : sequentialStep(value, low, high),\n };\n }\n }\n}\n\n/* -------------------------------------------------------------------- */\n/* Aggregation for row, column and group totals. */\n/* -------------------------------------------------------------------- */\n\n/** How a margin combines its cells. */\nexport type HeatmapAggregate = 'sum' | 'mean';\n\n/** One cell as aggregation sees it. */\nexport interface AggregateInput {\n value: number | null;\n count?: number;\n}\n\n/** A combined value and the count behind it. */\nexport interface AggregateResult {\n value: number | null;\n /** Sum of the counts, when any cell carried one. */\n count?: number;\n}\n\n/** Sum of the values; empty cells are skipped. Null when nothing is left. */\nexport function sumOf(cells: readonly AggregateInput[]): AggregateResult {\n let total = 0;\n let seen = false;\n let count = 0;\n let counted = false;\n for (const cell of cells) {\n if (cell.value === null || !Number.isFinite(cell.value)) continue;\n total += cell.value;\n seen = true;\n if (cell.count !== undefined) {\n count += cell.count;\n counted = true;\n }\n }\n return { value: seen ? total : null, count: counted ? count : undefined };\n}\n\n/**\n * Mean weighted by count: sum(value x count) / sum(count). This is the only\n * correct way to combine rates (26% of 39 and 50% of 2 is 27%, not 38%).\n * A cell without a count weighs 1, so data with no counts at all gets a\n * plain mean. Cells with a count of 0 add nothing.\n */\nexport function weightedMean(\n cells: readonly AggregateInput[],\n): AggregateResult {\n let weighted = 0;\n let weights = 0;\n let count = 0;\n let counted = false;\n for (const cell of cells) {\n if (cell.value === null || !Number.isFinite(cell.value)) continue;\n const weight = cell.count ?? 1;\n weighted += cell.value * weight;\n weights += weight;\n if (cell.count !== undefined) {\n count += cell.count;\n counted = true;\n }\n }\n return {\n value: weights > 0 ? weighted / weights : null,\n count: counted ? count : undefined,\n };\n}\n\n/** Combines cells with the given method. */\nexport function aggregate(\n cells: readonly AggregateInput[],\n method: HeatmapAggregate,\n): AggregateResult {\n return method === 'sum' ? sumOf(cells) : weightedMean(cells);\n}\n","/* -------------------------------------------------------------------- */\n/* Heatmap data model. Pure functions that turn the consumer's rows, */\n/* columns and cells into the matrix the grid, the legend and the table */\n/* view read, plus the grouping, sorting and totals maths. */\n/* -------------------------------------------------------------------- */\n\nimport {\n aggregate,\n type AggregateResult,\n type HeatmapAggregate,\n} from './heatmap-scale';\n\n/** One row of the heatmap. */\nexport interface HeatmapRow {\n /** Stable, opaque id. Emitted in DOM hooks, so never a name. */\n id: string;\n /** Visible label. Masked in privacy mode. */\n label: string;\n /**\n * Group id. Rows that share it are grouped when `groupRows` is on. Without\n * a matching entry in `groups` the id doubles as the visible label, so it\n * may be a name: privacy mode masks it, and DOM hooks and agent state\n * carry an index-based id (`group-1`, `group-2` in order of first\n * appearance), never this one.\n */\n group?: string;\n}\n\n/** One column of the heatmap. */\nexport interface HeatmapColumn {\n /**\n * Stable, opaque id. Emitted in DOM hooks (`data-heatmap-cell-id`) and in\n * agent state, so never a name.\n */\n id: string | number;\n /**\n * Visible label. Masked in privacy mode only with `privacyScope=\"all\"`:\n * columns are usually hours or days, which privacy mode keeps.\n */\n label: string;\n}\n\n/** A group's visible label, keyed by the id rows carry in `group`. */\nexport interface HeatmapGroup {\n /** Stable, opaque id. Emitted in DOM hooks and agent state, so never a name. */\n id: string;\n /**\n * Visible label. Masked in privacy mode only with `privacyScope=\"all\"`:\n * groups are usually practices or sites, which privacy mode keeps.\n */\n label: string;\n}\n\n/**\n * The id each group shows to DOM hooks and agents. A group listed in\n * `groups` keeps its own (opaque) id. One that is not has only its id for a\n * label, which may be a name, so it gets `group-<n>` by order of first\n * appearance instead.\n */\nexport function publicGroupIds(\n rows: readonly HeatmapRow[],\n groups: readonly HeatmapGroup[] | undefined,\n): Map<string, string> {\n const listed = new Set(groups?.map((group) => group.id));\n const taken = new Set(listed);\n const ids = new Map<string, string>();\n let n = 0;\n for (const row of rows) {\n const groupId = row.group;\n if (groupId === undefined || ids.has(groupId)) continue;\n if (listed.has(groupId)) {\n ids.set(groupId, groupId);\n continue;\n }\n let fallback: string;\n do {\n n += 1;\n fallback = `group-${n}`;\n } while (taken.has(fallback));\n taken.add(fallback);\n ids.set(groupId, fallback);\n }\n return ids;\n}\n\n/** The data behind one cell. */\nexport interface HeatmapCellData {\n /** The value to colour. `null` means no data. */\n value: number | null;\n /**\n * How many records the value rests on (the denominator of a rate). Weights\n * the mean totals and drives `minCount`.\n */\n count?: number;\n /**\n * Text shown and announced instead of the formatted value, for example\n * \"Closed\". Replaced by the formatted value in privacy mode.\n */\n label?: string;\n}\n\n/** What `getCell` or the `cells` matrix may hold for a cell. */\nexport type HeatmapCellInput = HeatmapCellData | number | null | undefined;\n\n/** How a cell renders: a coloured value, no data, or too few records. */\nexport type HeatmapCellStatus = 'value' | 'empty' | 'low-sample';\n\n/** Addresses one cell. */\nexport interface HeatmapCellKey {\n rowId: string;\n columnId: string | number;\n}\n\n/** Everything known about one cell, as passed to callbacks. */\nexport interface HeatmapCellInfo extends HeatmapCellKey {\n row: HeatmapRow;\n column: HeatmapColumn;\n /** Index into the `rows` prop. */\n rowIndex: number;\n /** Index into the `columns` prop. */\n columnIndex: number;\n value: number | null;\n count?: number;\n label?: string;\n status: HeatmapCellStatus;\n /**\n * Colour step, 0 to 9, when `status` is `'value'`; otherwise null. On a\n * diverging scale a value exactly on the midpoint keeps step 5 but is\n * painted in the neutral `--heatmap-midpoint` colour: compare `value`\n * with the midpoint to tell it from the palest step above.\n */\n step: number | null;\n}\n\n/** A cell after normalisation. */\nexport interface ModelCell {\n value: number | null;\n count?: number;\n label?: string;\n status: HeatmapCellStatus;\n}\n\n/** How rows are ordered (within their group when grouped). */\nexport type HeatmapSortRows = 'none' | 'label' | 'total-asc' | 'total-desc';\n\n/** Whether a cell or total falls below the sample threshold. */\nexport function isLowSample(\n count: number | undefined,\n minCount: number | undefined,\n): boolean {\n return minCount !== undefined && count !== undefined && count < minCount;\n}\n\n/** Normalises one cell input. */\nexport function toModelCell(\n input: HeatmapCellInput,\n minCount: number | undefined,\n): ModelCell {\n if (input === null || input === undefined) {\n return { value: null, status: 'empty' };\n }\n const data: HeatmapCellData =\n typeof input === 'number' ? { value: input } : input;\n const value =\n data.value === null || !Number.isFinite(data.value) ? null : data.value;\n const status: HeatmapCellStatus =\n value === null\n ? 'empty'\n : isLowSample(data.count, minCount)\n ? 'low-sample'\n : 'value';\n return { value, count: data.count, label: data.label, status };\n}\n\n/** Builds the `[row][column]` matrix in the order of the props. */\nexport function buildMatrix(\n rows: readonly HeatmapRow[],\n columns: readonly HeatmapColumn[],\n getCell:\n | ((\n row: HeatmapRow,\n column: HeatmapColumn,\n rowIndex: number,\n columnIndex: number,\n ) => HeatmapCellInput)\n | undefined,\n cells: readonly (readonly HeatmapCellInput[])[] | undefined,\n minCount: number | undefined,\n): ModelCell[][] {\n return rows.map((row, r) =>\n columns.map((column, c) =>\n toModelCell(\n getCell ? getCell(row, column, r, c) : cells?.[r]?.[c],\n minCount,\n ),\n ),\n );\n}\n\n/** The values that render a colour, for the scale's domain. */\nexport function shownValues(matrix: readonly ModelCell[][]): number[] {\n const values: number[] = [];\n for (const row of matrix) {\n for (const cell of row) {\n if (cell.status === 'value' && cell.value !== null)\n values.push(cell.value);\n }\n }\n return values;\n}\n\n/** Whether at least one cell carries data (a value or a low sample). */\nexport function hasAnyData(matrix: readonly ModelCell[][]): boolean {\n return matrix.some((row) => row.some((cell) => cell.status !== 'empty'));\n}\n\n/* -------------------------------------------------------------------- */\n/* Totals */\n/* -------------------------------------------------------------------- */\n\nexport interface HeatmapTotals {\n /** Per row index (props order), by the row method. */\n rows: AggregateResult[];\n /** Per column index, by the column method. */\n columns: AggregateResult[];\n /** Every cell, by the row method (it sits in the row-totals column). */\n grand: AggregateResult;\n /** Per group id: one result per column, by the group column method. */\n groupColumns: Map<string, AggregateResult[]>;\n /** Per group id: every cell in the group, by the row method (it sits in\n * the row-totals column). */\n groups: Map<string, AggregateResult>;\n}\n\n/**\n * Works out every margin. A total in the row-totals column (a row's, a\n * group's, the grand total) uses the row method, so the column means one\n * thing; a group's per-column totals use the group column method. Low-sample\n * cells count: their data is real, only too thin to show on its own.\n */\nexport function computeTotals(\n matrix: readonly ModelCell[][],\n rows: readonly HeatmapRow[],\n columnCount: number,\n rowMethod: HeatmapAggregate,\n columnMethod: HeatmapAggregate,\n groupColumnMethod: HeatmapAggregate,\n): HeatmapTotals {\n const rowTotals = matrix.map((cells) => aggregate(cells, rowMethod));\n const columnTotals: AggregateResult[] = [];\n for (let c = 0; c < columnCount; c += 1) {\n columnTotals.push(\n aggregate(\n matrix.map((cells) => cells[c]),\n columnMethod,\n ),\n );\n }\n const byGroup = new Map<string, number[]>();\n rows.forEach((row, r) => {\n if (row.group === undefined) return;\n const list = byGroup.get(row.group) ?? [];\n list.push(r);\n byGroup.set(row.group, list);\n });\n const groupColumns = new Map<string, AggregateResult[]>();\n const groups = new Map<string, AggregateResult>();\n for (const [groupId, indexes] of byGroup) {\n const perColumn: AggregateResult[] = [];\n for (let c = 0; c < columnCount; c += 1) {\n perColumn.push(\n aggregate(\n indexes.map((r) => matrix[r][c]),\n groupColumnMethod,\n ),\n );\n }\n groupColumns.set(groupId, perColumn);\n groups.set(\n groupId,\n aggregate(\n indexes.flatMap((r) => matrix[r]),\n rowMethod,\n ),\n );\n }\n return {\n rows: rowTotals,\n columns: columnTotals,\n grand: aggregate(matrix.flat(), rowMethod),\n groupColumns,\n groups,\n };\n}\n\n/* -------------------------------------------------------------------- */\n/* Body rows: grouping, sorting, collapse */\n/* -------------------------------------------------------------------- */\n\n/** A row the grid body renders. */\nexport type BodyRow =\n | {\n kind: 'group';\n /** Navigation key, unique among body rows. */\n key: string;\n groupId: string;\n collapsed: boolean;\n /** Row indexes (props order) in display order. */\n rowIndexes: number[];\n }\n | {\n kind: 'data';\n key: string;\n rowIndex: number;\n groupId?: string;\n };\n\nexport const dataRowKey = (rowId: string): string => `d:${rowId}`;\nexport const groupRowKey = (groupId: string): string => `g:${groupId}`;\nexport const FOOTER_ROW_KEY = 'f';\n\n/** Orders row indexes. Ties keep the props order (a stable sort). */\nexport function sortRowIndexes(\n indexes: readonly number[],\n rows: readonly HeatmapRow[],\n totals: readonly AggregateResult[],\n sort: HeatmapSortRows,\n collator: Intl.Collator,\n): number[] {\n const list = [...indexes];\n if (sort === 'label') {\n return list.sort((a, b) => collator.compare(rows[a].label, rows[b].label));\n }\n if (sort === 'total-asc' || sort === 'total-desc') {\n const direction = sort === 'total-asc' ? 1 : -1;\n return list.sort((a, b) => {\n const left = totals[a]?.value;\n const right = totals[b]?.value;\n // Rows without a total sink to the end in both directions.\n if (left === null || left === undefined) return right == null ? 0 : 1;\n if (right === null || right === undefined) return -1;\n return (left - right) * direction;\n });\n }\n return list;\n}\n\n/** Builds the body: group headers (when grouping) and data rows. */\nexport function buildBodyRows(\n rows: readonly HeatmapRow[],\n sortedIndexes: readonly number[],\n groupRows: boolean,\n collapsed: ReadonlySet<string>,\n): BodyRow[] {\n if (!groupRows) {\n return sortedIndexes.map((r) => ({\n kind: 'data',\n key: dataRowKey(rows[r].id),\n rowIndex: r,\n groupId: rows[r].group,\n }));\n }\n // Groups keep the order in which they first appear in the props, so a sort\n // reorders rows within a group but never moves the groups themselves.\n const order: string[] = [];\n const members = new Map<string, number[]>();\n const loose: number[] = [];\n rows.forEach((row) => {\n if (row.group !== undefined && !members.has(row.group)) {\n members.set(row.group, []);\n order.push(row.group);\n }\n });\n for (const r of sortedIndexes) {\n const groupId = rows[r].group;\n if (groupId === undefined) loose.push(r);\n else members.get(groupId)?.push(r);\n }\n const body: BodyRow[] = [];\n for (const groupId of order) {\n const rowIndexes = members.get(groupId) ?? [];\n const isCollapsed = collapsed.has(groupId);\n body.push({\n kind: 'group',\n key: groupRowKey(groupId),\n groupId,\n collapsed: isCollapsed,\n rowIndexes,\n });\n if (!isCollapsed) {\n for (const r of rowIndexes) {\n body.push({\n kind: 'data',\n key: dataRowKey(rows[r].id),\n rowIndex: r,\n groupId,\n });\n }\n }\n }\n // Rows without a group follow the groups, ungrouped.\n for (const r of loose) {\n body.push({ kind: 'data', key: dataRowKey(rows[r].id), rowIndex: r });\n }\n return body;\n}\n","import type { ReactElement } from 'react';\nimport { Tooltip } from '../tooltip';\nimport { useHeatmapContext } from './heatmap-context';\nimport type { HeatmapCellInfo } from './heatmap-model';\n\nexport interface HeatmapTooltipProps {\n /** The cell the tooltip describes. */\n cell: HeatmapCellInfo;\n /**\n * Tooltip text. Defaults to the Heatmap's `renderTooltip`, or to the\n * sentence every cell is named with (\"Tuesday, 10:00: 26%, 10 of 39\").\n * Plain text only: the kit Tooltip never carries interactive content.\n */\n label?: string;\n /** Controlled open state. */\n open?: boolean;\n onOpenChange?: (open: boolean) => void;\n /** Logical side. Default `'top'`. */\n side?: 'top' | 'end' | 'bottom' | 'start';\n /** The trigger. */\n children: ReactElement;\n}\n\n/**\n * Heatmap.Tooltip: the kit Tooltip with a cell's description. The grid uses\n * it for the cell under the pointer or the keyboard focus; a consumer can\n * use it to describe a cell somewhere else, with the same wording and the\n * same privacy masking.\n */\nexport function HeatmapTooltip({\n cell,\n label,\n open,\n onOpenChange,\n side = 'top',\n children,\n}: HeatmapTooltipProps) {\n const context = useHeatmapContext();\n const text = label ?? context?.tooltipText(cell) ?? '';\n return (\n <Tooltip\n label={text}\n open={open}\n onOpenChange={onOpenChange}\n side={side}\n delayDuration={0}\n >\n {children}\n </Tooltip>\n );\n}\n\nHeatmapTooltip.displayName = 'HeatmapTooltip';\n\n/**\n * The anchor the grid hangs a cell's tooltip on: an inert box over the\n * cell, so the cell itself never re-mounts (and never drops focus) when the\n * tooltip moves to it. Takes the text, not a cell, so a group header cell\n * (which has no single row) gets one too.\n */\nexport function HeatmapCellTooltip({\n label,\n onOpenChange,\n}: {\n label: string;\n onOpenChange: (open: boolean) => void;\n}) {\n return (\n <Tooltip label={label} open onOpenChange={onOpenChange} delayDuration={0}>\n <span\n aria-hidden=\"true\"\n data-component=\"heatmap-tooltip\"\n className=\"ds:pointer-events-none ds:absolute ds:inset-0\"\n />\n </Tooltip>\n );\n}\n","/* -------------------------------------------------------------------- */\n/* Heatmap virtualisation. Above VIRTUALISE_CELL_THRESHOLD cells the */\n/* grid renders only the rows and columns in (and just around) the */\n/* viewport, plus the cell that holds the roving focus, so focus is */\n/* never dropped by a scroll. */\n/* */\n/* Every row and column has the same pitch in a virtualised grid, so the */\n/* window is plain arithmetic on the scroll offset; the skipped tracks */\n/* are kept by spacer elements that span them (no pixel offsets, so no */\n/* inline transforms). */\n/* -------------------------------------------------------------------- */\n\n/**\n * Cell count above which the grid virtualises. Measured in Chromium on a\n * production build (heatmap mdx, \"Performance\"): a full render took about\n * 10 ms at 840 cells and 14 ms (p95 18 ms) at 1,200, against the 16 ms\n * budget in src/docs/19-performance.mdx. Above 1,000 cells the window keeps\n * render and hover cost tied to the viewport, not to the data.\n */\nexport const VIRTUALISE_CELL_THRESHOLD = 1000;\n\n/** Rows or columns rendered beyond each edge of the viewport. */\nexport const OVERSCAN = 3;\n\n/** Inputs for one axis. All lengths in CSS pixels. */\nexport interface AxisMetrics {\n /** Scroll offset along the axis (absolute; RTL scrollLeft is negative). */\n offset: number;\n /** Visible length of the scroll container along the axis. */\n viewport: number;\n /** Space before the first item: the sticky header or row header. */\n lead: number;\n /** Item length plus the gap after it. */\n pitch: number;\n /** Number of items on the axis. */\n count: number;\n}\n\n/** Half-open range `[start, end)` of item indexes in view. */\nexport function visibleRange(\n { offset, viewport, lead, pitch, count }: AxisMetrics,\n overscan = OVERSCAN,\n): [number, number] {\n if (count <= 0) return [0, 0];\n if (!(pitch > 0)) return [0, count];\n const from = Math.abs(offset) - lead;\n const first = Math.floor(from / pitch) - overscan;\n const last = Math.ceil((from + viewport) / pitch) + overscan;\n const start = Math.max(0, Math.min(count - 1, first));\n const end = Math.max(start + 1, Math.min(count, last));\n return [start, end];\n}\n\n/** What an axis renders: item indexes and the spans of the gaps. */\nexport interface AxisWindow {\n /** Sorted item indexes to render. */\n indexes: number[];\n /** Items skipped before the first rendered one. */\n lead: number;\n /**\n * Items skipped between the pinned (focused) item and the visible range,\n * when the pinned item lies outside it. Zero otherwise.\n */\n middle: number;\n /** Where the middle gap sits: after this many rendered items. */\n middleAfter: number;\n /** Items skipped after the last rendered one. */\n tail: number;\n}\n\n/** Combines the visible range with the item that must stay rendered. */\nexport function axisWindow(\n range: [number, number],\n count: number,\n pinned: number | null,\n): AxisWindow {\n const [start, end] = range;\n const visible: number[] = [];\n for (let i = start; i < end; i += 1) visible.push(i);\n if (pinned === null || pinned < 0 || pinned >= count) {\n return {\n indexes: visible,\n lead: start,\n middle: 0,\n middleAfter: 0,\n tail: Math.max(0, count - end),\n };\n }\n if (pinned < start) {\n return {\n indexes: [pinned, ...visible],\n lead: pinned,\n middle: start - pinned - 1,\n middleAfter: 1,\n tail: Math.max(0, count - end),\n };\n }\n if (pinned >= end) {\n return {\n indexes: [...visible, pinned],\n lead: start,\n middle: pinned - end,\n middleAfter: visible.length,\n tail: count - pinned - 1,\n };\n }\n return {\n indexes: visible,\n lead: start,\n middle: 0,\n middleAfter: 0,\n tail: Math.max(0, count - end),\n };\n}\n\n/** A window that renders everything (the grid below the threshold). */\nexport function fullWindow(count: number): AxisWindow {\n return {\n indexes: Array.from({ length: count }, (_, i) => i),\n lead: 0,\n middle: 0,\n middleAfter: 0,\n tail: 0,\n };\n}\n\n/**\n * A window with every index at or past `count` dropped: what a window built\n * for more items renders in the one pass before it is worked out again.\n * Returns the same window when nothing is past the end.\n */\nexport function trimWindow(window: AxisWindow, count: number): AxisWindow {\n if (window.indexes.every((index) => index < count)) return window;\n const indexes = window.indexes.filter((index) => index < count);\n return {\n indexes,\n lead: Math.min(window.lead, count),\n middle: 0,\n middleAfter: 0,\n tail: Math.max(0, count - (indexes.length + Math.min(window.lead, count))),\n };\n}\n\n/** Whether two windows render the same items (skips a needless render). */\nexport function sameWindow(a: AxisWindow, b: AxisWindow): boolean {\n if (a.lead !== b.lead || a.tail !== b.tail || a.middle !== b.middle) {\n return false;\n }\n if (a.indexes.length !== b.indexes.length) return false;\n return a.indexes.every((value, i) => value === b.indexes[i]);\n}\n","/* -------------------------------------------------------------------- */\n/* Heatmap class recipes. Every colour is a token; every per-cell */\n/* colour is a CVA variant written out in full so Tailwind generates it. */\n/* -------------------------------------------------------------------- */\n\nimport { cva } from 'class-variance-authority';\n\n/** Palettes, each backed by ten `--heatmap-<palette>-<step>` tokens. */\nexport type HeatmapPalette =\n | 'primary'\n | 'success'\n | 'destructive'\n | 'diverging';\n\n/** One colour step of one palette, the neutral midpoint of a diverging\n * scale, or a cell with no colour of its own. */\nexport type HeatmapTone =\n | `${HeatmapPalette}-${0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9}`\n | 'midpoint'\n | 'empty'\n | 'low-sample'\n | 'aggregate';\n\n/** The tone for a palette step. */\nexport const stepTone = (palette: HeatmapPalette, step: number): HeatmapTone =>\n `${palette}-${Math.min(9, Math.max(0, Math.round(step)))}` as HeatmapTone;\n\n/**\n * Background and ink for every tone. Shared by the cells and the legend\n * swatches, and written out in full so Tailwind generates every class.\n */\nconst toneClasses: Record<HeatmapTone, string> = {\n 'primary-0':\n 'ds:bg-[var(--heatmap-primary-0)] ds:text-[color:var(--heatmap-primary-0-foreground)]',\n 'primary-1':\n 'ds:bg-[var(--heatmap-primary-1)] ds:text-[color:var(--heatmap-primary-1-foreground)]',\n 'primary-2':\n 'ds:bg-[var(--heatmap-primary-2)] ds:text-[color:var(--heatmap-primary-2-foreground)]',\n 'primary-3':\n 'ds:bg-[var(--heatmap-primary-3)] ds:text-[color:var(--heatmap-primary-3-foreground)]',\n 'primary-4':\n 'ds:bg-[var(--heatmap-primary-4)] ds:text-[color:var(--heatmap-primary-4-foreground)]',\n 'primary-5':\n 'ds:bg-[var(--heatmap-primary-5)] ds:text-[color:var(--heatmap-primary-5-foreground)]',\n 'primary-6':\n 'ds:bg-[var(--heatmap-primary-6)] ds:text-[color:var(--heatmap-primary-6-foreground)]',\n 'primary-7':\n 'ds:bg-[var(--heatmap-primary-7)] ds:text-[color:var(--heatmap-primary-7-foreground)]',\n 'primary-8':\n 'ds:bg-[var(--heatmap-primary-8)] ds:text-[color:var(--heatmap-primary-8-foreground)]',\n 'primary-9':\n 'ds:bg-[var(--heatmap-primary-9)] ds:text-[color:var(--heatmap-primary-9-foreground)]',\n 'success-0':\n 'ds:bg-[var(--heatmap-success-0)] ds:text-[color:var(--heatmap-success-0-foreground)]',\n 'success-1':\n 'ds:bg-[var(--heatmap-success-1)] ds:text-[color:var(--heatmap-success-1-foreground)]',\n 'success-2':\n 'ds:bg-[var(--heatmap-success-2)] ds:text-[color:var(--heatmap-success-2-foreground)]',\n 'success-3':\n 'ds:bg-[var(--heatmap-success-3)] ds:text-[color:var(--heatmap-success-3-foreground)]',\n 'success-4':\n 'ds:bg-[var(--heatmap-success-4)] ds:text-[color:var(--heatmap-success-4-foreground)]',\n 'success-5':\n 'ds:bg-[var(--heatmap-success-5)] ds:text-[color:var(--heatmap-success-5-foreground)]',\n 'success-6':\n 'ds:bg-[var(--heatmap-success-6)] ds:text-[color:var(--heatmap-success-6-foreground)]',\n 'success-7':\n 'ds:bg-[var(--heatmap-success-7)] ds:text-[color:var(--heatmap-success-7-foreground)]',\n 'success-8':\n 'ds:bg-[var(--heatmap-success-8)] ds:text-[color:var(--heatmap-success-8-foreground)]',\n 'success-9':\n 'ds:bg-[var(--heatmap-success-9)] ds:text-[color:var(--heatmap-success-9-foreground)]',\n 'destructive-0':\n 'ds:bg-[var(--heatmap-destructive-0)] ds:text-[color:var(--heatmap-destructive-0-foreground)]',\n 'destructive-1':\n 'ds:bg-[var(--heatmap-destructive-1)] ds:text-[color:var(--heatmap-destructive-1-foreground)]',\n 'destructive-2':\n 'ds:bg-[var(--heatmap-destructive-2)] ds:text-[color:var(--heatmap-destructive-2-foreground)]',\n 'destructive-3':\n 'ds:bg-[var(--heatmap-destructive-3)] ds:text-[color:var(--heatmap-destructive-3-foreground)]',\n 'destructive-4':\n 'ds:bg-[var(--heatmap-destructive-4)] ds:text-[color:var(--heatmap-destructive-4-foreground)]',\n 'destructive-5':\n 'ds:bg-[var(--heatmap-destructive-5)] ds:text-[color:var(--heatmap-destructive-5-foreground)]',\n 'destructive-6':\n 'ds:bg-[var(--heatmap-destructive-6)] ds:text-[color:var(--heatmap-destructive-6-foreground)]',\n 'destructive-7':\n 'ds:bg-[var(--heatmap-destructive-7)] ds:text-[color:var(--heatmap-destructive-7-foreground)]',\n 'destructive-8':\n 'ds:bg-[var(--heatmap-destructive-8)] ds:text-[color:var(--heatmap-destructive-8-foreground)]',\n 'destructive-9':\n 'ds:bg-[var(--heatmap-destructive-9)] ds:text-[color:var(--heatmap-destructive-9-foreground)]',\n 'diverging-0':\n 'ds:bg-[var(--heatmap-diverging-0)] ds:text-[color:var(--heatmap-diverging-0-foreground)]',\n 'diverging-1':\n 'ds:bg-[var(--heatmap-diverging-1)] ds:text-[color:var(--heatmap-diverging-1-foreground)]',\n 'diverging-2':\n 'ds:bg-[var(--heatmap-diverging-2)] ds:text-[color:var(--heatmap-diverging-2-foreground)]',\n 'diverging-3':\n 'ds:bg-[var(--heatmap-diverging-3)] ds:text-[color:var(--heatmap-diverging-3-foreground)]',\n 'diverging-4':\n 'ds:bg-[var(--heatmap-diverging-4)] ds:text-[color:var(--heatmap-diverging-4-foreground)]',\n 'diverging-5':\n 'ds:bg-[var(--heatmap-diverging-5)] ds:text-[color:var(--heatmap-diverging-5-foreground)]',\n 'diverging-6':\n 'ds:bg-[var(--heatmap-diverging-6)] ds:text-[color:var(--heatmap-diverging-6-foreground)]',\n 'diverging-7':\n 'ds:bg-[var(--heatmap-diverging-7)] ds:text-[color:var(--heatmap-diverging-7-foreground)]',\n 'diverging-8':\n 'ds:bg-[var(--heatmap-diverging-8)] ds:text-[color:var(--heatmap-diverging-8-foreground)]',\n 'diverging-9':\n 'ds:bg-[var(--heatmap-diverging-9)] ds:text-[color:var(--heatmap-diverging-9-foreground)]',\n // A value exactly on a diverging scale's midpoint: neutral, so a cell\n // with no change never looks like one with a small change.\n midpoint:\n 'ds:bg-[var(--heatmap-midpoint)] ds:text-[color:var(--heatmap-midpoint-foreground)]',\n empty:\n 'ds:border ds:border-dashed ds:border-[color:var(--heatmap-empty-border)] ds:bg-[var(--heatmap-empty)] ds:text-[color:var(--heatmap-empty-foreground)]',\n 'low-sample':\n 'ds:border ds:border-[color:var(--heatmap-empty-border)] ds:bg-[var(--heatmap-low-sample-surface)] ds:bg-[image:var(--heatmap-low-sample)] ds:text-[color:var(--heatmap-empty-foreground)]',\n aggregate:\n 'ds:bg-[var(--muted)] ds:text-[color:var(--foreground)] ds:font-semibold',\n};\n\n/** Root: a column of legend bar, grid and live region. Never wider than\n * its container, so the page never scrolls sideways. */\nexport const heatmapRootVariants = cva(\n 'ds:flex ds:min-w-0 ds:max-w-full ds:flex-col ds:gap-[var(--spacing-sm)] ds:text-[color:var(--foreground)]',\n);\n\n/** The bar above the grid: legend at the start, view toggle at the end. */\nexport const heatmapToolbarVariants = cva(\n 'ds:flex ds:flex-wrap ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)]',\n);\n\n/** The scroll box. Only this box scrolls; sticky headers stick to it. */\nexport const heatmapScrollerVariants = cva(\n [\n 'ds:relative ds:max-w-full ds:overflow-auto ds:overscroll-contain',\n 'ds:max-h-[var(--heatmap-max-block-size)]',\n 'ds:bg-[var(--background)]',\n // Keep a cell scrolled into view clear of the sticky header, footer and\n // row-header column. The sizes are measured and set on this element.\n 'ds:scroll-pt-[var(--heatmap-sticky-block-start)] ds:scroll-pb-[var(--heatmap-sticky-block-end)] ds:scroll-ps-[var(--heatmap-sticky-inline-start)]',\n ].join(' '),\n);\n\n/**\n * The table view's box. `fit` lets the DataTable grow with its rows up to\n * the maximum; `capped` holds the maximum and the DataTable fills it,\n * scrolling inside.\n */\nexport const heatmapTableViewVariants = cva(\n // Focusable only to hold focus during a retry; not a control, so no ring.\n 'ds:min-w-0 ds:max-w-full ds:outline-none',\n {\n variants: {\n capped: {\n true: 'ds:flex ds:h-[var(--heatmap-max-block-size)] ds:flex-col',\n false: 'ds:block ds:max-h-[var(--heatmap-max-block-size)]',\n },\n },\n defaultVariants: { capped: false },\n },\n);\n\n/**\n * The grid. Columns come from `--heatmap-columns` (set on the scroll box);\n * rows share the column tracks through subgrid. Size sets the cell box,\n * density the gap, and a virtualised grid pins every track to one size so\n * the window arithmetic holds.\n */\nexport const heatmapGridVariants = cva(\n [\n 'ds:grid ds:w-max ds:min-w-full',\n 'ds:[grid-template-rows:auto] ds:auto-rows-[var(--heatmap-row-track)]',\n 'ds:gap-[var(--heatmap-gap)]',\n 'ds:outline-none',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:[--heatmap-cell-inline:var(--min-target-size)] ds:[--heatmap-cell-block:var(--min-target-size)]',\n md: 'ds:[--heatmap-cell-inline:max(var(--min-target-size),var(--spacing-2xl))] ds:[--heatmap-cell-block:var(--min-target-size)]',\n lg: 'ds:[--heatmap-cell-inline:max(var(--min-target-size),calc(var(--spacing-2xl)_+_var(--spacing-md)))] ds:[--heatmap-cell-block:max(var(--min-target-size),var(--spacing-2xl))]',\n },\n density: {\n default: 'ds:[--heatmap-gap:var(--spacing-2xs)]',\n compact: 'ds:[--heatmap-gap:var(--spacing-none)]',\n },\n virtualised: {\n true: 'ds:[--heatmap-track:var(--heatmap-cell-inline)] ds:[--heatmap-row-track:var(--heatmap-cell-block)]',\n false:\n 'ds:[--heatmap-track:minmax(var(--heatmap-cell-inline),1fr)] ds:[--heatmap-row-track:minmax(var(--heatmap-cell-block),auto)]',\n },\n totalsColumn: {\n true: 'ds:grid-cols-[max-content_repeat(var(--heatmap-columns),var(--heatmap-track))_max-content]',\n false:\n 'ds:grid-cols-[max-content_repeat(var(--heatmap-columns),var(--heatmap-track))]',\n },\n },\n defaultVariants: {\n size: 'md',\n density: 'default',\n virtualised: false,\n totalsColumn: false,\n },\n },\n);\n\n/** A row: spans every column and lines its cells up through subgrid. */\nexport const heatmapRowVariants = cva(\n 'ds:col-span-full ds:grid ds:grid-cols-subgrid',\n {\n variants: {\n position: {\n // The header and footer rows stick to the scroll box's block edges,\n // above the row headers that stick to its inline start.\n // Each also covers the row gap on its inner side, so cells\n // scrolling underneath never show through the gap.\n header:\n \"ds:sticky ds:top-0 ds:z-[calc(var(--z-sticky)+1)] ds:bg-[var(--background)] ds:after:pointer-events-none ds:after:absolute ds:after:inset-x-0 ds:after:top-[calc(100%_-_var(--spacing-2xs))] ds:after:h-[calc(var(--heatmap-gap)_+_var(--spacing-2xs))] ds:after:bg-[var(--background)] ds:after:content-['']\",\n footer:\n \"ds:sticky ds:bottom-0 ds:z-[calc(var(--z-sticky)+1)] ds:bg-[var(--background)] ds:after:pointer-events-none ds:after:absolute ds:after:inset-x-0 ds:after:bottom-[calc(100%_-_var(--spacing-2xs))] ds:after:h-[calc(var(--heatmap-gap)_+_var(--spacing-2xs))] ds:after:bg-[var(--background)] ds:after:content-['']\",\n body: '',\n },\n },\n defaultVariants: { position: 'body' },\n },\n);\n\n/** A spacer standing in for rows or columns the window skipped. */\nexport const heatmapSpacerVariants = cva('ds:pointer-events-none', {\n variants: {\n axis: {\n 'row-lead': 'ds:col-span-full ds:row-span-[var(--heatmap-row-lead)]',\n 'row-middle': 'ds:col-span-full ds:row-span-[var(--heatmap-row-middle)]',\n 'row-tail': 'ds:col-span-full ds:row-span-[var(--heatmap-row-tail)]',\n 'col-lead': 'ds:col-span-[var(--heatmap-col-lead)]',\n 'col-middle': 'ds:col-span-[var(--heatmap-col-middle)]',\n // Holds the skipped columns after the window, so the row-totals cell\n // lands in its own track at the end and never next to the window.\n 'col-tail': 'ds:col-span-[var(--heatmap-col-tail)]',\n },\n },\n});\n\nconst headerHighlight =\n 'ds:transition-colors ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none ds:data-[highlighted=true]:bg-[var(--muted)] ds:data-[highlighted=true]:text-[color:var(--foreground)]';\n\n/** Column header: the hour, day or other column label. */\nexport const heatmapColumnHeaderVariants = cva(\n [\n 'ds:flex ds:min-w-0 ds:items-end ds:justify-center ds:text-center',\n 'ds:rounded-[var(--radius-sm)] ds:px-[var(--spacing-2xs)] ds:py-[var(--spacing-xs)]',\n 'type-meta ds:text-[color:var(--muted-foreground)] ds:break-normal ds:[overflow-wrap:anywhere]',\n headerHighlight,\n ].join(' '),\n {\n variants: {\n corner: {\n // The top-start corner sticks with the row headers below it.\n true: 'ds:sticky ds:start-0 ds:z-[var(--z-sticky)] ds:items-end ds:justify-start ds:text-start ds:bg-[var(--background)] ds:pe-[var(--spacing-sm)]',\n false: '',\n },\n },\n defaultVariants: { corner: false },\n },\n);\n\n/** Row header: the row's label, sticky at the inline start. */\nexport const heatmapRowHeaderVariants = cva(\n [\n 'ds:sticky ds:start-0 ds:z-[var(--z-sticky)] ds:flex ds:min-w-0 ds:items-center',\n 'ds:max-w-[calc(var(--spacing-2xl)*4)] ds:gap-[var(--spacing-xs)]',\n 'ds:bg-[var(--background)] ds:ps-[var(--spacing-xs)] ds:pe-[var(--spacing-sm)]',\n // Cover the gaps at the inline end and below too, so cells scrolling\n // underneath never show through between row headers.\n \"ds:after:pointer-events-none ds:after:absolute ds:after:top-0 ds:after:bottom-[calc(var(--heatmap-gap)*-1)] ds:after:start-full ds:after:w-[var(--heatmap-gap)] ds:after:bg-[var(--background)] ds:after:content-['']\",\n // The strip below overlaps its neighbours slightly so a fractional row\n // position never leaves a hairline seam.\n \"ds:before:pointer-events-none ds:before:absolute ds:before:inset-x-0 ds:before:top-[calc(100%_-_var(--spacing-2xs))] ds:before:h-[calc(var(--heatmap-gap)_+_var(--spacing-2xs)*2)] ds:before:bg-[var(--background)] ds:before:content-['']\",\n 'type-body-sm ds:text-start ds:break-normal ds:[overflow-wrap:anywhere]',\n headerHighlight,\n ].join(' '),\n {\n variants: {\n kind: {\n data: '',\n group: 'ds:font-semibold',\n total: 'ds:font-semibold',\n },\n // A virtualised grid needs every row the same height: no wrapping.\n // The label truncates inside its own span (heatmapRowLabelVariants):\n // overflow on the header itself would clip its gap-covering strips.\n virtualised: {\n true: 'ds:whitespace-nowrap',\n false: '',\n },\n },\n defaultVariants: { kind: 'data', virtualised: false },\n },\n);\n\n/** The label inside a row header. */\nexport const heatmapRowLabelVariants = cva('ds:min-w-0', {\n variants: {\n virtualised: {\n true: 'ds:overflow-hidden ds:text-ellipsis',\n false: '',\n },\n },\n defaultVariants: { virtualised: false },\n});\n\n/**\n * A cell. Colour comes from `tone`; selection, focus and hover come from\n * state attributes so a cell's classes only change when its data does.\n *\n * Focus: an inset ring in `--ring` over an inset band of the page colour,\n * so it reads on every step. Selection: a dark line framed by two light\n * ones, also inset, so it reads on every step too and is a shape, not a\n * colour. On a focused, selected cell the selection lines move inward by\n * `--focus-ring-width`, so the ring (3px in the accessible theme) never\n * covers them. Windows high contrast keeps the cell colours\n * (forced-color-adjust: none) and paints focus in the system Highlight\n * colour.\n */\nexport const heatmapCellVariants = cva(\n [\n 'ds:relative ds:flex ds:min-w-0 ds:items-center ds:justify-center',\n 'ds:min-h-[var(--heatmap-cell-block)] ds:overflow-hidden ds:px-[var(--spacing-2xs)]',\n 'type-meta ds:tabular-nums ds:whitespace-nowrap ds:select-none',\n 'ds:forced-colors:[forced-color-adjust:none]',\n 'ds:focus-visible:outline-solid ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-ring',\n 'ds:focus-visible:outline-offset-[calc(var(--focus-ring-width)*-1)]',\n 'ds:focus-visible:shadow-[inset_0_0_0_calc(var(--focus-ring-width)*2)_var(--background)]',\n 'ds:forced-colors:focus-visible:outline-[Highlight]',\n 'ds:aria-selected:shadow-[inset_0_0_0_var(--spacing-2xs)_var(--background),inset_0_0_0_calc(var(--spacing-2xs)*2)_var(--foreground),inset_0_0_0_calc(var(--spacing-2xs)*3)_var(--background)]',\n 'ds:aria-selected:focus-visible:shadow-[inset_0_0_0_calc(var(--focus-ring-width)_+_var(--spacing-2xs))_var(--background),inset_0_0_0_calc(var(--focus-ring-width)_+_var(--spacing-2xs)*2)_var(--foreground),inset_0_0_0_calc(var(--focus-ring-width)_+_var(--spacing-2xs)*3)_var(--background)]',\n ].join(' '),\n {\n variants: {\n tone: toneClasses,\n interactive: {\n true: 'ds:cursor-pointer',\n false: 'ds:cursor-default',\n },\n },\n defaultVariants: { tone: 'empty', interactive: false },\n },\n);\n\n/** Legend container. */\nexport const heatmapLegendVariants = cva(\n 'ds:flex ds:min-w-0 ds:flex-wrap ds:items-center ds:gap-x-[var(--spacing-md)] ds:gap-y-[var(--spacing-xs)] type-meta ds:text-[color:var(--muted-foreground)]',\n);\n\n/** The bar of colour steps in the legend. It shrinks with its container\n * rather than pushing the page wider. */\nexport const heatmapLegendBarVariants = cva(\n 'ds:flex ds:w-[calc(var(--spacing-xl)*6)] ds:min-w-0 ds:max-w-full ds:shrink ds:items-stretch',\n {\n variants: {\n variant: {\n stepped: 'ds:gap-[var(--spacing-2xs)]',\n continuous: 'ds:overflow-hidden ds:rounded-[var(--radius-sm)]',\n },\n },\n defaultVariants: { variant: 'stepped' },\n },\n);\n\n/** A legend swatch: a step in the bar, the key for an empty or low-sample\n * cell, or the diverging midpoint, which carries its value in its own ink.\n * Same tone classes as the cells. */\nexport const heatmapSwatchVariants = cva(\n 'ds:inline-block ds:forced-colors:[forced-color-adjust:none]',\n {\n variants: {\n tone: toneClasses,\n shape: {\n stepped:\n 'ds:h-[var(--spacing-sm)] ds:min-w-0 ds:flex-1 ds:rounded-[var(--radius-sm)]',\n continuous: 'ds:h-[var(--spacing-sm)] ds:min-w-0 ds:flex-1',\n key: 'ds:size-[var(--spacing-md)] ds:shrink-0 ds:rounded-[var(--radius-sm)]',\n label:\n 'ds:shrink-0 ds:rounded-[var(--radius-sm)] ds:px-[var(--spacing-xs)] ds:whitespace-nowrap',\n },\n },\n defaultVariants: { tone: 'empty', shape: 'key' },\n },\n);\n","import {\n memo,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n type CSSProperties,\n type KeyboardEvent,\n type PointerEvent,\n type MouseEvent,\n type ReactElement,\n} from 'react';\nimport { ChevronDown } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { useIsomorphicLayoutEffect } from '../../hooks/use-isomorphic-layout-effect';\nimport type { HeatmapDescriber } from './heatmap-format';\nimport {\n FOOTER_ROW_KEY,\n isLowSample,\n type BodyRow,\n type HeatmapCellInfo,\n type HeatmapColumn,\n type HeatmapRow,\n type HeatmapTotals,\n type ModelCell,\n} from './heatmap-model';\nimport {\n onMidpoint,\n type AggregateResult,\n type HeatmapAggregate,\n type ResolvedHeatmapScale,\n} from './heatmap-scale';\nimport { HeatmapCellTooltip } from './heatmap-tooltip';\nimport {\n axisWindow,\n fullWindow,\n sameWindow,\n trimWindow,\n visibleRange,\n type AxisWindow,\n} from './heatmap-window';\nimport {\n heatmapCellVariants,\n heatmapColumnHeaderVariants,\n heatmapGridVariants,\n heatmapRowHeaderVariants,\n heatmapRowLabelVariants,\n heatmapRowVariants,\n heatmapScrollerVariants,\n heatmapSpacerVariants,\n stepTone,\n type HeatmapPalette,\n type HeatmapTone,\n} from './heatmap-variants';\n\n/** How the selection behaves. */\nexport type HeatmapSelectionMode = 'none' | 'single' | 'multiple' | 'range';\n\n/** A position in the navigable matrix: a body or footer row and a column\n * (the last column is the row-totals column when there is one). */\nexport interface GridPosition {\n rowKey: string;\n col: number;\n}\n\nconst KEY_SEPARATOR = '\\u001f';\n\n/** Internal selection key for a data cell: its row id and column id, never\n * its position, so a change to the columns cannot move it. */\nexport const selectionKey = (\n rowId: string,\n columnId: string | number,\n): string => `${rowId}${KEY_SEPARATOR}${String(columnId)}`;\n\n/** The row id and the column id (as a string) a selection key holds. */\nexport const splitSelectionKey = (key: string): [string, string] => {\n const at = key.indexOf(KEY_SEPARATOR);\n return [key.slice(0, at), key.slice(at + 1)];\n};\n\nexport interface HeatmapGridProps {\n title: string;\n rowsLabel?: string;\n rows: readonly HeatmapRow[];\n columns: readonly HeatmapColumn[];\n matrix: readonly ModelCell[][];\n body: readonly BodyRow[];\n scale: ResolvedHeatmapScale;\n palette: HeatmapPalette;\n describer: HeatmapDescriber;\n showValues: boolean;\n totals: HeatmapTotals | null;\n rowTotals: HeatmapAggregate | false;\n columnTotals: HeatmapAggregate | false;\n /** How a group header's per-column totals are worked out. */\n groupColumnMethod: HeatmapAggregate;\n /** Each group's public id: what DOM hooks carry, never a label. */\n groupIds: ReadonlyMap<string, string>;\n minCount?: number;\n selectionMode: HeatmapSelectionMode;\n /** Selection keys (row id + column id) of the selected cells. */\n selected: ReadonlySet<string>;\n /** Column index for the column id a selection key holds. */\n columnIndexOfKey: (columnKey: string) => number | undefined;\n interactive: boolean;\n virtualised: boolean;\n size: 'sm' | 'md' | 'lg';\n density: 'compact' | 'default';\n cellInfo: (rowIndex: number, columnIndex: number) => HeatmapCellInfo;\n /** A data cell's tooltip text. */\n tooltipText: (cell: HeatmapCellInfo) => string;\n /** Describe the focused data cell with its tooltip text (a consumer's\n * renderTooltip says more than the cell's name). */\n describeFocused: boolean;\n /** A data cell was activated by click, Enter or Space. `select` is false\n * for a click that only reports the cell (a range press already chose). */\n onActivate: (rowIndex: number, columnIndex: number, select: boolean) => void;\n /** Range drag or Shift+arrows: select the rectangle anchor to target. */\n onRange: (\n anchor: { rowIndex: number; col: number },\n target: { rowIndex: number; col: number },\n ) => void;\n onToggleGroup: (groupId: string) => void;\n}\n\n/* -------------------------------------------------------------------- */\n/* Per-render context shared by every row (memoised in the grid) */\n/* -------------------------------------------------------------------- */\n\ninterface RowContext {\n rows: readonly HeatmapRow[];\n columns: readonly HeatmapColumn[];\n matrix: readonly ModelCell[][];\n scale: ResolvedHeatmapScale;\n palette: HeatmapPalette;\n describer: HeatmapDescriber;\n showValues: boolean;\n totals: HeatmapTotals | null;\n rowTotals: HeatmapAggregate | false;\n groupColumnMethod: HeatmapAggregate;\n groupIds: ReadonlyMap<string, string>;\n minCount?: number;\n selectable: boolean;\n interactive: boolean;\n virtualised: boolean;\n colWindow: AxisWindow;\n /** Base for the ids that name group row headers. */\n idBase: string;\n /** The id of the focused cell's description, or undefined for none. */\n describedBy: string | undefined;\n cellInfo: (rowIndex: number, columnIndex: number) => HeatmapCellInfo;\n tooltipText: (cell: HeatmapCellInfo) => string;\n onTooltipOpenChange: (open: boolean) => void;\n onToggleGroup: (groupId: string) => void;\n expandLabel: (group: string) => string;\n collapseLabel: (group: string) => string;\n}\n\nfunction toneOf(\n cell: ModelCell,\n scale: ResolvedHeatmapScale,\n palette: HeatmapPalette,\n): HeatmapTone {\n if (cell.status === 'empty' || cell.value === null) return 'empty';\n if (cell.status === 'low-sample') return 'low-sample';\n if (onMidpoint(scale, cell.value)) return 'midpoint';\n return stepTone(palette, scale.stepOf(cell.value));\n}\n\nfunction aggregateCell(\n result: AggregateResult,\n minCount: number | undefined,\n): ModelCell {\n return {\n value: result.value,\n count: result.count,\n status:\n result.value === null\n ? 'empty'\n : isLowSample(result.count, minCount)\n ? 'low-sample'\n : 'value',\n };\n}\n\nconst aggregateTone = (cell: ModelCell): HeatmapTone =>\n cell.status === 'value' ? 'aggregate' : cell.status;\n\n/** Renders the column window: spacers stand in for skipped columns, before,\n * between and after the rendered ones, so whatever follows (the row-totals\n * cell) always sits in its own track at the end. */\nfunction renderColumns(\n window: AxisWindow,\n render: (columnIndex: number) => ReactElement,\n): ReactElement[] {\n const out: ReactElement[] = [];\n if (window.lead > 0) {\n out.push(\n <div\n key=\"lead\"\n aria-hidden=\"true\"\n className={heatmapSpacerVariants({ axis: 'col-lead' })}\n />,\n );\n }\n window.indexes.forEach((columnIndex, i) => {\n if (window.middle > 0 && i === window.middleAfter) {\n out.push(\n <div\n key=\"middle\"\n aria-hidden=\"true\"\n className={heatmapSpacerVariants({ axis: 'col-middle' })}\n />,\n );\n }\n out.push(render(columnIndex));\n });\n if (window.tail > 0) {\n out.push(\n <div\n key=\"tail\"\n aria-hidden=\"true\"\n className={heatmapSpacerVariants({ axis: 'col-tail' })}\n />,\n );\n }\n return out;\n}\n\ninterface BodyRowProps {\n ctx: RowContext;\n row: BodyRow;\n /** 1-based aria-rowindex. */\n ariaRowIndex: number;\n highlighted: boolean;\n /** Column holding the roving tabindex in this row, or -1. */\n activeCol: number;\n /** Column hosting the tooltip in this row, or -1. */\n tooltipCol: number;\n /** Selected column indexes, comma-joined (a string so memo compares by value). */\n selectedCols: string;\n}\n\n/** One body row: a data row or a group header. Memoised, so hover and\n * focus only re-render the rows they touch. */\nconst HeatmapBodyRow = memo(function HeatmapBodyRow({\n ctx,\n row,\n ariaRowIndex,\n highlighted,\n activeCol,\n tooltipCol,\n selectedCols,\n}: BodyRowProps) {\n const columnCount = ctx.columns.length;\n const selected = useMemo(\n () =>\n new Set(selectedCols === '' ? [] : selectedCols.split(',').map(Number)),\n [selectedCols],\n );\n\n if (row.kind === 'group') {\n const groupText = ctx.describer.groupLabel(row.groupId);\n // The public id: the group's own when `groups` lists it, else an\n // index-based one, because an unlisted id doubles as the label.\n const hookId = ctx.groupIds.get(row.groupId);\n const labelId = `${ctx.idBase}-label-${ariaRowIndex}`;\n const perColumn = ctx.totals?.groupColumns.get(row.groupId) ?? [];\n const overall = ctx.totals?.groups.get(row.groupId);\n /** A group's cell. Its value always prints, as a row total's does: the\n * group row is a margin, not a colour scale. */\n const groupCell = (\n result: AggregateResult | undefined,\n c: number,\n label: (cell: ModelCell) => string,\n withTooltip: boolean,\n ) => {\n const cell = aggregateCell(result ?? { value: null }, ctx.minCount);\n const name = label(cell);\n return (\n <div\n key={c}\n role=\"gridcell\"\n aria-colindex={c + 2}\n aria-expanded={!row.collapsed}\n aria-label={name}\n tabIndex={activeCol === c ? 0 : -1}\n data-heatmap-group-id={hookId}\n className={heatmapCellVariants({\n tone: aggregateTone(cell),\n interactive: true,\n })}\n >\n {ctx.describer.visibleText(cell)}\n {withTooltip && tooltipCol === c ? (\n <HeatmapCellTooltip\n label={name}\n onOpenChange={ctx.onTooltipOpenChange}\n />\n ) : null}\n </div>\n );\n };\n const perColumnRowText = ctx.describer.groupRowText(\n groupText,\n ctx.groupColumnMethod,\n );\n return (\n <div\n role=\"row\"\n aria-rowindex={ariaRowIndex}\n data-heatmap-body-row=\"\"\n data-heatmap-group-id={hookId}\n className={heatmapRowVariants({ position: 'body' })}\n >\n <div\n role=\"rowheader\"\n aria-colindex={1}\n // Named by the label alone: the button's own name (\"Collapse …\")\n // would otherwise be read with it, saying the group twice.\n aria-labelledby={labelId}\n data-highlighted={highlighted}\n className={heatmapRowHeaderVariants({\n kind: 'group',\n virtualised: ctx.virtualised,\n })}\n >\n {/*\n * Out of the tab order (tabIndex -1), and it never takes focus on\n * a press: the grid is one tab stop, and every cell of the group\n * row toggles the group with Enter, Space or a click, so the\n * button is a pointer shortcut. Its 24px box meets WCAG 2.5.8\n * (AA). The kit's own 44px target (2.5.5, 48px accessible) is met\n * through the equivalent-control exception: those cells are the\n * same control at full size.\n */}\n <button\n type=\"button\"\n tabIndex={-1}\n aria-expanded={!row.collapsed}\n aria-label={\n row.collapsed\n ? ctx.expandLabel(groupText)\n : ctx.collapseLabel(groupText)\n }\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => ctx.onToggleGroup(row.groupId)}\n className=\"ds:inline-flex ds:size-[var(--spacing-lg)] ds:shrink-0 ds:cursor-pointer ds:items-center ds:justify-center ds:rounded-[var(--radius-sm)] ds:bg-transparent ds:text-[color:inherit] ds:hover:bg-[var(--muted)] ds:focus-visible:outline-solid ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-ring ds:forced-colors:focus-visible:outline-[Highlight]\"\n >\n <ChevronDown\n aria-hidden=\"true\"\n className={[\n 'ds:size-4 ds:transition-transform ds:duration-[var(--animation-duration)] ds:motion-reduce:transition-none',\n row.collapsed ? 'ds:-rotate-90 ds:rtl:rotate-90' : '',\n ].join(' ')}\n />\n </button>\n <span\n id={labelId}\n className={heatmapRowLabelVariants({\n virtualised: ctx.virtualised,\n })}\n >\n {groupText}\n </span>\n </div>\n {renderColumns(ctx.colWindow, (c) =>\n groupCell(\n perColumn[c],\n c,\n (cell) =>\n ctx.describer.sentence(\n perColumnRowText,\n ctx.describer.columnLabel(ctx.columns[c]),\n cell,\n ),\n true,\n ),\n )}\n {ctx.rowTotals\n ? groupCell(\n overall,\n columnCount,\n (cell) =>\n ctx.describer.sentence(\n groupText,\n ctx.describer.methodLabel(ctx.rowTotals || 'mean'),\n cell,\n ),\n false,\n )\n : null}\n </div>\n );\n }\n\n const r = row.rowIndex;\n const source = ctx.rows[r];\n const rowText = ctx.describer.rowLabel(source);\n const cells = ctx.matrix[r];\n\n const dataCell = (c: number) => {\n const cell = cells[c];\n const column = ctx.columns[c];\n const isSelected = selected.has(c);\n return (\n <div\n key={c}\n role=\"gridcell\"\n aria-colindex={c + 2}\n aria-label={ctx.describer.sentence(\n rowText,\n ctx.describer.columnLabel(column),\n cell,\n )}\n aria-describedby={activeCol === c ? ctx.describedBy : undefined}\n aria-selected={ctx.selectable ? isSelected : undefined}\n tabIndex={activeCol === c ? 0 : -1}\n data-heatmap-cell-id={`${source.id}:${String(column.id)}`}\n data-status={cell.status}\n className={heatmapCellVariants({\n tone: toneOf(cell, ctx.scale, ctx.palette),\n interactive: ctx.interactive,\n })}\n >\n {ctx.showValues || cell.status === 'empty'\n ? ctx.describer.visibleText(cell)\n : null}\n {tooltipCol === c ? (\n <HeatmapCellTooltip\n label={ctx.tooltipText(ctx.cellInfo(r, c))}\n onOpenChange={ctx.onTooltipOpenChange}\n />\n ) : null}\n </div>\n );\n };\n\n let totalCell: ReactElement | null = null;\n if (ctx.rowTotals && ctx.totals) {\n const cell = aggregateCell(ctx.totals.rows[r], ctx.minCount);\n totalCell = (\n <div\n role=\"gridcell\"\n aria-colindex={columnCount + 2}\n aria-label={ctx.describer.sentence(\n rowText,\n ctx.describer.methodLabel(ctx.rowTotals),\n cell,\n )}\n tabIndex={activeCol === columnCount ? 0 : -1}\n className={heatmapCellVariants({ tone: aggregateTone(cell) })}\n >\n {ctx.describer.visibleText(cell)}\n </div>\n );\n }\n\n return (\n <div\n role=\"row\"\n aria-rowindex={ariaRowIndex}\n data-heatmap-body-row=\"\"\n data-heatmap-row-id={source.id}\n className={heatmapRowVariants({ position: 'body' })}\n >\n <div\n role=\"rowheader\"\n aria-colindex={1}\n data-highlighted={highlighted}\n className={heatmapRowHeaderVariants({\n kind: 'data',\n virtualised: ctx.virtualised,\n })}\n >\n <span\n className={heatmapRowLabelVariants({ virtualised: ctx.virtualised })}\n >\n {rowText}\n </span>\n </div>\n {renderColumns(ctx.colWindow, dataCell)}\n {totalCell}\n </div>\n );\n});\n\n/* -------------------------------------------------------------------- */\n/* Grid */\n/* -------------------------------------------------------------------- */\n\ninterface Metrics {\n headerBlock: number;\n footerBlock: number;\n rowPitch: number;\n leadInline: number;\n colPitch: number;\n viewportBlock: number;\n viewportInline: number;\n}\n\nconst DEFAULT_METRICS: Metrics = {\n headerBlock: 48,\n footerBlock: 0,\n rowPitch: 46,\n leadInline: 120,\n colPitch: 46,\n viewportBlock: 600,\n viewportInline: 900,\n};\n\nconst pageRows = (metrics: Metrics): number =>\n Math.max(\n 1,\n Math.floor(\n (metrics.viewportBlock - metrics.headerBlock - metrics.footerBlock) /\n Math.max(1, metrics.rowPitch),\n ),\n );\n\nexport function HeatmapGrid(props: HeatmapGridProps) {\n const {\n title,\n rowsLabel,\n rows,\n columns,\n matrix,\n body,\n scale,\n palette,\n describer,\n showValues,\n totals,\n rowTotals,\n columnTotals,\n groupColumnMethod,\n groupIds,\n minCount,\n selectionMode,\n selected,\n columnIndexOfKey,\n interactive,\n virtualised,\n size,\n density,\n cellInfo,\n tooltipText,\n describeFocused,\n onActivate,\n onRange,\n onToggleGroup,\n } = props;\n const { t } = useTranslation('ui');\n const idBase = useId();\n const scrollerRef = useRef<HTMLDivElement>(null);\n const gridRef = useRef<HTMLDivElement>(null);\n const headerRef = useRef<HTMLDivElement>(null);\n const footerRef = useRef<HTMLDivElement>(null);\n\n const columnCount = columns.length;\n const navColumnCount = columnCount + (rowTotals ? 1 : 0);\n const hasFooter = Boolean(columnTotals && totals);\n const navRowKeys = useMemo(\n () => [\n ...body.map((row) => row.key),\n ...(hasFooter ? [FOOTER_ROW_KEY] : []),\n ],\n [body, hasFooter],\n );\n const rowIndexOfKey = useMemo(() => {\n const map = new Map<string, number>();\n navRowKeys.forEach((key, i) => map.set(key, i));\n return map;\n }, [navRowKeys]);\n\n /* ---- roving focus -------------------------------------------------- */\n const [active, setActive] = useState<GridPosition>(() => ({\n rowKey: navRowKeys[0] ?? FOOTER_ROW_KEY,\n col: 0,\n }));\n // If the active row disappears (a group collapsed, rows changed), fall\n // back to its group header, else the first row.\n const activeRow = (() => {\n const found = rowIndexOfKey.get(active.rowKey);\n if (found !== undefined) return found;\n const hidden = rows.find((row) => `d:${row.id}` === active.rowKey);\n const header =\n hidden?.group === undefined\n ? undefined\n : rowIndexOfKey.get(`g:${hidden.group}`);\n return header ?? 0;\n })();\n const activeCol = Math.min(\n Math.max(0, active.col),\n Math.max(0, navColumnCount - 1),\n );\n const activeKey = navRowKeys[activeRow];\n\n const pendingFocus = useRef(false);\n const [hasFocus, setHasFocus] = useState(false);\n const hasFocusRef = useRef(false);\n const interaction = useRef<'keyboard' | 'pointer'>('pointer');\n\n /* ---- hover and tooltip --------------------------------------------- */\n const [hover, setHover] = useState<GridPosition | null>(null);\n const hoverRef = useRef<GridPosition | null>(null);\n const [tooltipDismissed, setTooltipDismissed] = useState(false);\n const updateHover = useCallback((next: GridPosition | null) => {\n const current = hoverRef.current;\n if (\n current === next ||\n (current &&\n next &&\n current.rowKey === next.rowKey &&\n current.col === next.col)\n ) {\n return;\n }\n hoverRef.current = next;\n setHover(next);\n setTooltipDismissed(false);\n }, []);\n\n /** The cell whose headers light up: the hovered one, else the focused one. */\n const highlight: GridPosition | null =\n hover ??\n (hasFocus && activeKey ? { rowKey: activeKey, col: activeCol } : null);\n /** The cell that shows the tooltip: hovered, or focused from the keyboard. */\n const tooltipAt: GridPosition | null = tooltipDismissed\n ? null\n : (hover ??\n (hasFocus && interaction.current === 'keyboard' && activeKey\n ? { rowKey: activeKey, col: activeCol }\n : null));\n\n /* ---- measurement and the virtual window ---------------------------- */\n const [metrics, setMetrics] = useState<Metrics>(DEFAULT_METRICS);\n const metricsRef = useRef(metrics);\n metricsRef.current = metrics;\n\n const measure = useCallback(() => {\n const scroller = scrollerRef.current;\n const grid = gridRef.current;\n if (!scroller || !grid) return;\n const style = window.getComputedStyle(grid);\n const rowGap = parseFloat(style.rowGap) || 0;\n const columnGap = parseFloat(style.columnGap) || 0;\n const tracks = style.gridTemplateColumns\n .split(' ')\n .map((track) => parseFloat(track))\n .filter((track) => Number.isFinite(track));\n const headerHeight = headerRef.current?.getBoundingClientRect().height ?? 0;\n const firstBody = grid.querySelector<HTMLElement>(\n '[data-heatmap-body-row]',\n );\n const bodyHeight = firstBody?.getBoundingClientRect().height ?? 0;\n const next: Metrics = {\n headerBlock: headerHeight + rowGap,\n footerBlock: footerRef.current?.getBoundingClientRect().height ?? 0,\n rowPitch:\n (bodyHeight || headerHeight || DEFAULT_METRICS.rowPitch) + rowGap,\n leadInline: (tracks[0] ?? 0) + columnGap,\n colPitch: (tracks[1] ?? DEFAULT_METRICS.colPitch) + columnGap,\n viewportBlock: scroller.clientHeight,\n viewportInline: scroller.clientWidth,\n };\n const current = metricsRef.current;\n if (\n (Object.keys(next) as (keyof Metrics)[]).some(\n (key) => Math.abs(next[key] - current[key]) > 0.5,\n )\n ) {\n setMetrics(next);\n }\n }, []);\n\n useIsomorphicLayoutEffect(() => {\n measure();\n const scroller = scrollerRef.current;\n if (!scroller || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(() => measure());\n observer.observe(scroller);\n if (gridRef.current) observer.observe(gridRef.current);\n return () => observer.disconnect();\n }, [measure, body.length, columnCount, size, density]);\n\n const pinnedRow = activeKey === FOOTER_ROW_KEY ? null : activeRow;\n const pinnedCol = activeCol < columnCount ? activeCol : null;\n\n const computeWindows = useCallback((): {\n rows: AxisWindow;\n cols: AxisWindow;\n } => {\n if (!virtualised) {\n return { rows: fullWindow(body.length), cols: fullWindow(columnCount) };\n }\n const scroller = scrollerRef.current;\n const m = metricsRef.current;\n const rowRange = visibleRange({\n offset: scroller?.scrollTop ?? 0,\n viewport: m.viewportBlock,\n lead: m.headerBlock,\n pitch: m.rowPitch,\n count: body.length,\n });\n const colRange = visibleRange({\n offset: scroller?.scrollLeft ?? 0,\n viewport: m.viewportInline,\n lead: m.leadInline,\n pitch: m.colPitch,\n count: columnCount,\n });\n return {\n rows: axisWindow(rowRange, body.length, pinnedRow),\n cols: axisWindow(colRange, columnCount, pinnedCol),\n };\n }, [virtualised, body.length, columnCount, pinnedRow, pinnedCol]);\n\n const [windowState, setWindows] = useState(computeWindows);\n // Below the threshold every row and column renders, worked out here so a\n // change to the data never meets a window built for the old data. Above\n // it, the window is trimmed to the data until the layout effect below\n // re-syncs it (before paint).\n const fullRows = useMemo(() => fullWindow(body.length), [body.length]);\n const fullCols = useMemo(() => fullWindow(columnCount), [columnCount]);\n const windows = useMemo(\n () =>\n virtualised\n ? {\n rows: trimWindow(windowState.rows, body.length),\n cols: trimWindow(windowState.cols, columnCount),\n }\n : { rows: fullRows, cols: fullCols },\n [virtualised, windowState, body.length, columnCount, fullRows, fullCols],\n );\n const syncWindows = useCallback(() => {\n const next = computeWindows();\n setWindows((current) =>\n sameWindow(current.rows, next.rows) && sameWindow(current.cols, next.cols)\n ? current\n : next,\n );\n }, [computeWindows]);\n useIsomorphicLayoutEffect(() => {\n syncWindows();\n }, [syncWindows, metrics]);\n\n const frame = useRef(0);\n const onScroll = useCallback(() => {\n if (!virtualised || frame.current) return;\n frame.current = window.requestAnimationFrame(() => {\n frame.current = 0;\n syncWindows();\n });\n }, [virtualised, syncWindows]);\n useEffect(() => () => window.cancelAnimationFrame(frame.current), []);\n\n /* ---- focus follows the roving position ----------------------------- */\n // The active row went away (its group collapsed, rows changed): settle the\n // roving position on the row that took its place.\n useIsomorphicLayoutEffect(() => {\n if (activeKey !== undefined && activeKey !== active.rowKey) {\n setActive({ rowKey: activeKey, col: activeCol });\n }\n });\n // If the focused cell itself was removed (an agent collapsed the group\n // holding focus), focus would fall to the page with no blur event: put it\n // back on the active cell, now the group row.\n useIsomorphicLayoutEffect(() => {\n if (!hasFocusRef.current || pendingFocus.current) return;\n const current = document.activeElement;\n if (current && current !== document.body && current.isConnected) return;\n pendingFocus.current = true;\n });\n\n const cellElement = useCallback(\n (rowIndex: number, col: number): HTMLElement | null =>\n gridRef.current?.querySelector<HTMLElement>(\n `[role=\"row\"][aria-rowindex=\"${rowIndex + 2}\"] > [aria-colindex=\"${col + 2}\"]`,\n ) ?? null,\n [],\n );\n\n useIsomorphicLayoutEffect(() => {\n if (!pendingFocus.current) return;\n const element = cellElement(activeRow, activeCol);\n if (!element) return;\n pendingFocus.current = false;\n element.focus({ preventScroll: true });\n element.scrollIntoView?.({ block: 'nearest', inline: 'nearest' });\n });\n\n const isRtl = () =>\n gridRef.current\n ? window.getComputedStyle(gridRef.current).direction === 'rtl'\n : false;\n\n /* ---- range anchor -------------------------------------------------- */\n const anchor = useRef<{ rowIndex: number; col: number } | null>(null);\n const dataRowIndexAt = (navIndex: number): number | null => {\n const row = body[navIndex];\n return row && row.kind === 'data' ? row.rowIndex : null;\n };\n\n /** Set by a range press on the only selected cell: the click that\n * follows (with no drag) clears it, as Enter does. */\n const clearOnClick = useRef(false);\n\n const moveTo = (rowIndex: number, col: number) => {\n const clampedRow = Math.max(0, Math.min(navRowKeys.length - 1, rowIndex));\n const clampedCol = Math.max(0, Math.min(navColumnCount - 1, col));\n pendingFocus.current = true;\n setTooltipDismissed(false);\n setActive({ rowKey: navRowKeys[clampedRow], col: clampedCol });\n return { row: clampedRow, col: clampedCol };\n };\n\n /** Activates the cell at a navigable position (click, Enter, Space). */\n const activate = (navIndex: number, col: number, extend: boolean) => {\n const row = body[navIndex];\n if (!row) return;\n if (row.kind === 'group') {\n onToggleGroup(row.groupId);\n return;\n }\n if (col >= columnCount) return;\n if (selectionMode === 'range' && extend && anchor.current) {\n onRange(anchor.current, { rowIndex: row.rowIndex, col });\n return;\n }\n anchor.current = { rowIndex: row.rowIndex, col };\n onActivate(row.rowIndex, col, true);\n };\n\n const onKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {\n // A key on the group toggle (if something focused it) keeps its own\n // meaning: Enter on that button toggles the group, never selects the\n // last active cell. Keys on a cell, or on the grid itself (a click on a\n // header focuses it), drive the grid.\n if (event.target instanceof Element && event.target.closest('button')) {\n return;\n }\n interaction.current = 'keyboard';\n const lastRow = navRowKeys.length - 1;\n const lastCol = navColumnCount - 1;\n const forward = isRtl() ? -1 : 1;\n let row = activeRow;\n let col = activeCol;\n const ctrl = event.ctrlKey || event.metaKey;\n switch (event.key) {\n case 'ArrowRight':\n col += forward;\n break;\n case 'ArrowLeft':\n col -= forward;\n break;\n case 'ArrowDown':\n row += 1;\n break;\n case 'ArrowUp':\n row -= 1;\n break;\n case 'Home':\n col = 0;\n if (ctrl) row = 0;\n break;\n case 'End':\n col = lastCol;\n if (ctrl) row = lastRow;\n break;\n case 'PageDown': {\n const nextGroup = body.findIndex(\n (r, i) => i > activeRow && r.kind === 'group',\n );\n const hasGroups = body.some((r) => r.kind === 'group');\n row = hasGroups\n ? nextGroup === -1\n ? lastRow\n : nextGroup\n : activeRow + pageRows(metricsRef.current);\n break;\n }\n case 'PageUp': {\n let previous = -1;\n for (let i = Math.min(activeRow, body.length) - 1; i >= 0; i -= 1) {\n if (body[i].kind === 'group') {\n previous = i;\n break;\n }\n }\n const hasGroups = body.some((r) => r.kind === 'group');\n row = hasGroups\n ? previous === -1\n ? 0\n : previous\n : activeRow - pageRows(metricsRef.current);\n break;\n }\n case 'Enter':\n case ' ':\n event.preventDefault();\n activate(activeRow, activeCol, event.shiftKey);\n return;\n case 'Escape':\n if (tooltipAt) {\n event.preventDefault();\n setTooltipDismissed(true);\n }\n return;\n default:\n return;\n }\n event.preventDefault();\n const moved = moveTo(row, col);\n const isArrow = event.key.startsWith('Arrow');\n if (selectionMode === 'range' && event.shiftKey && isArrow) {\n const target = dataRowIndexAt(moved.row);\n const from =\n anchor.current ??\n (() => {\n const start = dataRowIndexAt(activeRow);\n return start === null || activeCol >= columnCount\n ? null\n : { rowIndex: start, col: activeCol };\n })();\n if (from && target !== null && moved.col < columnCount) {\n anchor.current = from;\n onRange(from, { rowIndex: target, col: moved.col });\n }\n }\n };\n\n /** The navigable position of the cell an event landed on. */\n const positionOf = (\n target: EventTarget | null,\n ): { row: number; col: number } | null => {\n if (!(target instanceof Element)) return null;\n const cell = target.closest<HTMLElement>('[role=\"gridcell\"]');\n const rowElement = cell?.parentElement;\n if (!cell || !rowElement || !gridRef.current?.contains(cell)) return null;\n const rowIndex = Number(rowElement.getAttribute('aria-rowindex')) - 2;\n const col = Number(cell.getAttribute('aria-colindex')) - 2;\n if (!Number.isInteger(rowIndex) || rowIndex < 0 || col < 0) return null;\n return { row: rowIndex, col };\n };\n\n const dragging = useRef(false);\n const lastPointer = useRef<string>('mouse');\n\n const onPointerDown = (event: PointerEvent<HTMLDivElement>) => {\n interaction.current = 'pointer';\n lastPointer.current = event.pointerType;\n if (\n selectionMode !== 'range' ||\n event.pointerType !== 'mouse' ||\n event.button !== 0\n ) {\n return;\n }\n const position = positionOf(event.target);\n clearOnClick.current = false;\n if (!position) return;\n const rowIndex = dataRowIndexAt(position.row);\n if (rowIndex === null || position.col >= columnCount) return;\n if (event.shiftKey && anchor.current) {\n onRange(anchor.current, { rowIndex, col: position.col });\n } else {\n anchor.current = { rowIndex, col: position.col };\n const key = selectionKey(rows[rowIndex].id, columns[position.col].id);\n if (selected.size === 1 && selected.has(key)) {\n // Pressing the only selected cell: a drag still starts a range from\n // it, but a plain click clears it (see onClick), as Enter does.\n clearOnClick.current = true;\n } else {\n onRange(anchor.current, anchor.current);\n }\n }\n dragging.current = true;\n const stop = () => {\n dragging.current = false;\n window.removeEventListener('pointerup', stop);\n window.removeEventListener('pointercancel', stop);\n };\n window.addEventListener('pointerup', stop);\n window.addEventListener('pointercancel', stop);\n };\n\n const onPointerMove = (event: PointerEvent<HTMLDivElement>) => {\n if (event.pointerType !== 'mouse') return;\n const position = positionOf(event.target);\n updateHover(\n position ? { rowKey: navRowKeys[position.row], col: position.col } : null,\n );\n if (dragging.current && position && anchor.current) {\n const rowIndex = dataRowIndexAt(position.row);\n if (rowIndex !== null && position.col < columnCount) {\n if (\n rowIndex !== anchor.current.rowIndex ||\n position.col !== anchor.current.col\n ) {\n clearOnClick.current = false;\n }\n if (!clearOnClick.current) {\n onRange(anchor.current, { rowIndex, col: position.col });\n }\n }\n }\n };\n\n // While the pointer rests on the tooltip, one document listener waits for\n // it to land somewhere else. Kept in a ref so there is never more than one\n // and it goes away with the grid.\n const awayListener = useRef<\n ((event: globalThis.PointerEvent) => void) | null\n >(null);\n const stopAway = useCallback(() => {\n if (!awayListener.current) return;\n document.removeEventListener('pointerover', awayListener.current);\n awayListener.current = null;\n }, []);\n useEffect(() => stopAway, [stopAway]);\n\n const onPointerLeave = (event: PointerEvent<HTMLDivElement>) => {\n // Moving onto the tooltip keeps it open (WCAG 1.4.13, hoverable); it\n // closes once the pointer leaves both.\n stopAway();\n const next = event.relatedTarget;\n if (next instanceof Element && next.closest('[data-component=\"tooltip\"]')) {\n const away = (moved: globalThis.PointerEvent) => {\n const over = moved.target;\n if (\n over instanceof Element &&\n over.closest('[data-component=\"tooltip\"]')\n ) {\n return;\n }\n stopAway();\n if (!(over instanceof Node && gridRef.current?.contains(over))) {\n updateHover(null);\n }\n };\n awayListener.current = away;\n document.addEventListener('pointerover', away);\n return;\n }\n updateHover(null);\n };\n\n const onClick = (event: MouseEvent<HTMLDivElement>) => {\n const button =\n event.target instanceof Element ? event.target.closest('button') : null;\n if (button) {\n // The group toggle has run its own onClick. Grid focus moves to the\n // group row, so the keys carry on from there.\n const navIndex =\n Number(button.closest('[role=\"row\"]')?.getAttribute('aria-rowindex')) -\n 2;\n // Keep the column, so a grid scrolled sideways stays where it is.\n if (Number.isInteger(navIndex) && navIndex >= 0) {\n moveTo(navIndex, activeCol);\n }\n return;\n }\n const position = positionOf(event.target);\n if (!position) return;\n moveTo(position.row, position.col);\n pendingFocus.current = false;\n // Range drags select on pointer down; a click only follows up for touch,\n // except to clear the only selected cell and to toggle a group.\n if (selectionMode === 'range' && lastPointer.current === 'mouse') {\n const row = body[position.row];\n if (row?.kind === 'group') {\n activate(position.row, position.col, false);\n } else if (row?.kind === 'data' && position.col < columnCount) {\n onActivate(row.rowIndex, position.col, clearOnClick.current);\n }\n clearOnClick.current = false;\n return;\n }\n activate(position.row, position.col, event.shiftKey);\n };\n\n /* ---- tooltip and scrolling ------------------------------------------ */\n // Radix closes a tooltip when anything around its trigger scrolls. A key\n // that moves focus scrolls the cell into view, so that close is not the\n // user dismissing it. This listener is added before any tooltip's, so it\n // marks the scroll first and the close below can tell. A hover tooltip\n // still closes on a scroll: the wheel moves the cell from under the\n // pointer without a pointer event.\n const scrolling = useRef(false);\n useEffect(() => {\n let settle = 0;\n const onAnyScroll = () => {\n scrolling.current = true;\n window.cancelAnimationFrame(settle);\n settle = window.requestAnimationFrame(() => {\n scrolling.current = false;\n });\n };\n window.addEventListener('scroll', onAnyScroll, { capture: true });\n return () => {\n window.removeEventListener('scroll', onAnyScroll, { capture: true });\n window.cancelAnimationFrame(settle);\n };\n }, []);\n\n /* ---- row context ---------------------------------------------------- */\n const onTooltipOpenChange = useCallback((open: boolean) => {\n if (open) return;\n // Only the focus tooltip (nothing hovered) outlives a scroll.\n if (scrolling.current && hoverRef.current === null) return;\n setTooltipDismissed(true);\n }, []);\n const expandLabel = useCallback(\n (group: string) => t('heatmap.expandGroup', { group }),\n [t],\n );\n const collapseLabel = useCallback(\n (group: string) => t('heatmap.collapseGroup', { group }),\n [t],\n );\n\n /* ---- the focused cell's description ------------------------------- */\n // A consumer's renderTooltip text reaches screen readers as the focused\n // cell's description; one hidden node, whatever the grid's size.\n const descriptionId = `${idBase}-description`;\n const focusedRow = body[activeRow];\n const description =\n describeFocused && focusedRow?.kind === 'data' && activeCol < columnCount\n ? tooltipText(cellInfo(focusedRow.rowIndex, activeCol))\n : null;\n\n const ctx = useMemo<RowContext>(\n () => ({\n rows,\n columns,\n matrix,\n scale,\n palette,\n describer,\n showValues,\n totals,\n rowTotals,\n groupColumnMethod,\n groupIds,\n minCount,\n selectable: selectionMode !== 'none',\n interactive,\n virtualised,\n colWindow: windows.cols,\n idBase,\n describedBy: describeFocused ? descriptionId : undefined,\n cellInfo,\n tooltipText,\n onTooltipOpenChange,\n onToggleGroup,\n expandLabel,\n collapseLabel,\n }),\n [\n rows,\n columns,\n matrix,\n scale,\n palette,\n describer,\n showValues,\n totals,\n rowTotals,\n groupColumnMethod,\n groupIds,\n minCount,\n selectionMode,\n interactive,\n virtualised,\n windows.cols,\n idBase,\n describeFocused,\n descriptionId,\n cellInfo,\n tooltipText,\n onTooltipOpenChange,\n onToggleGroup,\n expandLabel,\n collapseLabel,\n ],\n );\n\n /** Selected column indexes per data row id, comma-joined. */\n const selectedByRow = useMemo(() => {\n const map = new Map<string, number[]>();\n for (const key of selected) {\n const [rowId, columnKey] = splitSelectionKey(key);\n const col = columnIndexOfKey(columnKey);\n if (col === undefined) continue;\n const list = map.get(rowId) ?? [];\n list.push(col);\n map.set(rowId, list);\n }\n const joined = new Map<string, string>();\n for (const [rowId, list] of map) {\n joined.set(rowId, list.sort((a, b) => a - b).join(','));\n }\n return joined;\n }, [selected, columnIndexOfKey]);\n\n /* ---- header and footer ---------------------------------------------- */\n const highlightCol = highlight?.col ?? -1;\n const header = (\n <div\n ref={headerRef}\n role=\"row\"\n aria-rowindex={1}\n className={heatmapRowVariants({ position: 'header' })}\n >\n <div\n role=\"columnheader\"\n aria-colindex={1}\n className={heatmapColumnHeaderVariants({ corner: true })}\n >\n {rowsLabel ?? (\n <span className=\"ds:sr-only\">{t('heatmap.rowsHeader')}</span>\n )}\n </div>\n {renderColumns(windows.cols, (c) => (\n <div\n key={c}\n role=\"columnheader\"\n aria-colindex={c + 2}\n data-highlighted={highlightCol === c}\n className={heatmapColumnHeaderVariants()}\n >\n {describer.columnLabel(columns[c])}\n </div>\n ))}\n {rowTotals ? (\n <div\n role=\"columnheader\"\n aria-colindex={columnCount + 2}\n data-highlighted={highlightCol === columnCount}\n className={heatmapColumnHeaderVariants()}\n >\n {describer.methodLabel(rowTotals)}\n </div>\n ) : null}\n </div>\n );\n\n let footer: ReactElement | null = null;\n if (columnTotals && totals) {\n const footerIndex = body.length;\n const methodText = describer.methodLabel(columnTotals);\n const footerActive = activeRow === footerIndex;\n const total = (\n result: AggregateResult,\n c: number,\n columnText: string,\n rowText = methodText,\n ) => {\n const cell = aggregateCell(result, minCount);\n return (\n <div\n key={c}\n role=\"gridcell\"\n aria-colindex={c + 2}\n aria-label={describer.sentence(rowText, columnText, cell)}\n tabIndex={footerActive && activeCol === c ? 0 : -1}\n className={heatmapCellVariants({ tone: aggregateTone(cell) })}\n >\n {describer.visibleText(cell)}\n </div>\n );\n };\n footer = (\n <div\n ref={footerRef}\n role=\"row\"\n aria-rowindex={footerIndex + 2}\n className={heatmapRowVariants({ position: 'footer' })}\n >\n <div\n role=\"rowheader\"\n aria-colindex={1}\n data-highlighted={highlight?.rowKey === FOOTER_ROW_KEY}\n className={heatmapRowHeaderVariants({ kind: 'total', virtualised })}\n >\n {methodText}\n </div>\n {renderColumns(windows.cols, (c) =>\n total(totals.columns[c], c, describer.columnLabel(columns[c])),\n )}\n {rowTotals\n ? total(\n totals.grand,\n columnCount,\n describer.methodLabel(rowTotals),\n // The corner aggregates every cell by the row method, so it\n // is named for all cells, not for the footer's own method.\n t('heatmap.allCells'),\n )\n : null}\n </div>\n );\n }\n\n /* ---- body ----------------------------------------------------------- */\n const bodyRows: ReactElement[] = [];\n const rowWindow = windows.rows;\n if (rowWindow.lead > 0) {\n bodyRows.push(\n <div\n key=\"row-lead\"\n aria-hidden=\"true\"\n className={heatmapSpacerVariants({ axis: 'row-lead' })}\n />,\n );\n }\n rowWindow.indexes.forEach((navIndex, i) => {\n if (rowWindow.middle > 0 && i === rowWindow.middleAfter) {\n bodyRows.push(\n <div\n key=\"row-middle\"\n aria-hidden=\"true\"\n className={heatmapSpacerVariants({ axis: 'row-middle' })}\n />,\n );\n }\n const row = body[navIndex];\n if (!row) return;\n const isActiveRow = navIndex === activeRow;\n bodyRows.push(\n <HeatmapBodyRow\n key={row.key}\n ctx={ctx}\n row={row}\n ariaRowIndex={navIndex + 2}\n highlighted={highlight?.rowKey === row.key}\n activeCol={isActiveRow ? activeCol : -1}\n tooltipCol={tooltipAt?.rowKey === row.key ? tooltipAt.col : -1}\n selectedCols={\n row.kind === 'data'\n ? (selectedByRow.get(rows[row.rowIndex].id) ?? '')\n : ''\n }\n />,\n );\n });\n if (rowWindow.tail > 0) {\n bodyRows.push(\n <div\n key=\"row-tail\"\n aria-hidden=\"true\"\n className={heatmapSpacerVariants({ axis: 'row-tail' })}\n />,\n );\n }\n\n // Inline style: permitted per 23-constraints §Runtime-computed dimensions\n // (custom-property setter on the scroll box; the column count comes from\n // the data, the spans from the virtual window and the sticky sizes from\n // measurement. Every rule that reads them lives in CVA).\n const scrollerStyle = {\n '--heatmap-columns': String(Math.max(1, columnCount)),\n '--heatmap-row-lead': String(rowWindow.lead),\n '--heatmap-row-middle': String(rowWindow.middle),\n '--heatmap-row-tail': String(rowWindow.tail),\n '--heatmap-col-lead': String(windows.cols.lead),\n '--heatmap-col-middle': String(windows.cols.middle),\n '--heatmap-col-tail': String(windows.cols.tail),\n '--heatmap-sticky-block-start': `${metrics.headerBlock}px`,\n '--heatmap-sticky-block-end': `${metrics.footerBlock}px`,\n '--heatmap-sticky-inline-start': `${metrics.leadInline}px`,\n } as CSSProperties;\n\n return (\n <div\n ref={scrollerRef}\n onScroll={onScroll}\n // eslint-disable-next-line react/forbid-dom-props -- 23-constraints §Runtime-computed dimensions: custom-property setter only\n style={scrollerStyle}\n data-component=\"heatmap-grid\"\n className={heatmapScrollerVariants()}\n >\n <div\n ref={gridRef}\n role=\"grid\"\n // Focus lives on the cells (roving tabindex); -1 keeps the grid itself\n // out of the tab order while letting it hold focus programmatically.\n tabIndex={-1}\n aria-label={title}\n aria-rowcount={navRowKeys.length + 1}\n aria-colcount={navColumnCount + 1}\n aria-multiselectable={\n selectionMode === 'multiple' || selectionMode === 'range'\n ? true\n : undefined\n }\n data-heatmap-grid=\"\"\n className={heatmapGridVariants({\n size,\n density,\n virtualised,\n totalsColumn: Boolean(rowTotals),\n })}\n onKeyDown={onKeyDown}\n onPointerDown={onPointerDown}\n onPointerMove={onPointerMove}\n onPointerLeave={onPointerLeave}\n onClick={onClick}\n onFocus={(event) => {\n // Tabbing in counts as keyboard use, so the tooltip shows at once.\n if (event.target.matches(':focus-visible')) {\n interaction.current = 'keyboard';\n }\n hasFocusRef.current = true;\n setHasFocus(true);\n }}\n onBlur={(event) => {\n if (\n !event.currentTarget.contains(event.relatedTarget as Node | null)\n ) {\n hasFocusRef.current = false;\n setHasFocus(false);\n }\n }}\n >\n {header}\n {bodyRows}\n {footer}\n </div>\n {description !== null ? (\n <span id={descriptionId} hidden>\n {description}\n </span>\n ) : null}\n </div>\n );\n}\n","import { forwardRef, useMemo } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport { formatLocale } from '../_shared/intl-locale';\nimport { useHeatmapContext } from './heatmap-context';\nimport { countFormatter, defaultValueFormatter } from './heatmap-format';\nimport {\n HEATMAP_STEPS,\n bucketStep,\n resolveScale,\n type HeatmapScale,\n type ResolvedHeatmapScale,\n} from './heatmap-scale';\nimport {\n heatmapLegendBarVariants,\n heatmapLegendVariants,\n heatmapSwatchVariants,\n stepTone,\n type HeatmapPalette,\n} from './heatmap-variants';\n\nexport interface HeatmapLegendProps {\n /**\n * `stepped` separates the ten steps; `continuous` joins them in a bar.\n * A quantile or threshold scale always shows its bands, one swatch per\n * step it uses, with the cut points between them.\n */\n variant?: 'stepped' | 'continuous';\n /** Palette. Inside a Heatmap it defaults to the Heatmap's. */\n palette?: HeatmapPalette;\n /** Scale. Inside a Heatmap it defaults to the Heatmap's resolved scale. */\n scale?: HeatmapScale;\n /** Values an `auto` or quantile scale is worked out from (outside a Heatmap). */\n values?: readonly number[];\n /** Formats the end labels. Inside a Heatmap it defaults to the Heatmap's. */\n valueFormatter?: (value: number) => string;\n /** Show the key for empty cells. Inside a Heatmap: when any cell is empty. */\n showEmpty?: boolean;\n /** Show the key for low-sample cells. Inside a Heatmap: when any is. */\n showLowSample?: boolean;\n /** The sample threshold, named in the low-sample key. Inside a Heatmap it\n * defaults to the Heatmap's `minCount`. */\n minCount?: number;\n className?: string;\n}\n\nconst STEPS = Array.from({ length: HEATMAP_STEPS }, (_, step) => step);\n\n/** End labels for the bar of a sequential or diverging scale. */\nfunction endLabels(\n scale: ResolvedHeatmapScale,\n format: (value: number) => string,\n): { start: string; end: string; middle?: string } {\n return {\n start: scale.min === null ? '' : format(scale.min),\n end: scale.max === null ? '' : format(scale.max),\n middle:\n scale.type === 'diverging' && scale.midpoint !== undefined\n ? format(scale.midpoint)\n : undefined,\n };\n}\n\n/**\n * Heatmap.Legend: the colour steps with the low and high ends of the scale,\n * plus keys for empty and low-sample cells. A diverging scale shows its\n * midpoint between the two hues as a neutral swatch carrying the midpoint\n * value, the colour of a cell exactly on it. Inside a Heatmap it reads the\n * Heatmap's scale; render it elsewhere with `legend={false}` on the Heatmap\n * and the same `scale`, `palette` and `values` here.\n */\nexport const HeatmapLegend = forwardRef<HTMLDivElement, HeatmapLegendProps>(\n (\n {\n variant = 'stepped',\n palette: paletteProp,\n scale: scaleProp,\n values,\n valueFormatter,\n showEmpty,\n showLowSample,\n minCount: minCountProp,\n className,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation('ui');\n const context = useHeatmapContext();\n const locale = formatLocale(i18n.resolvedLanguage ?? i18n.language);\n\n const scale = useMemo(\n () =>\n scaleProp\n ? resolveScale(scaleProp, values ?? [])\n : (context?.scale ??\n resolveScale({ type: 'sequential' }, values ?? [])),\n [scaleProp, values, context?.scale],\n );\n const palette =\n paletteProp ??\n context?.palette ??\n (scale.type === 'diverging' ? 'diverging' : 'primary');\n const format =\n valueFormatter ??\n context?.describer.formatValue ??\n defaultValueFormatter(locale, 'number');\n\n // A quantile or threshold scale paints only a few steps: one per band.\n // Show those, with each cut point between its two bands, not ten\n // swatches of which most never appear.\n const banded =\n (scale.type === 'quantile' || scale.type === 'threshold') &&\n scale.thresholds.length > 0;\n const bandCount = scale.thresholds.length + 1;\n const bandSteps = banded\n ? Array.from({ length: bandCount }, (_, band) =>\n bucketStep(band, bandCount),\n )\n : [];\n const edges = scale.thresholds.map(format);\n\n const labels = endLabels(scale, format);\n const description = banded\n ? t('heatmap.legend.descriptionBands', {\n count: bandCount,\n formatted: countFormatter(locale)(bandCount),\n edges: new Intl.ListFormat(locale, {\n type: 'conjunction',\n }).format(edges),\n })\n : labels.middle !== undefined\n ? t('heatmap.legend.descriptionDiverging', {\n min: labels.start,\n max: labels.end,\n midpoint: labels.middle,\n })\n : t('heatmap.legend.description', {\n min: labels.start,\n max: labels.end,\n });\n // A banded scale with no cut (every value equal) paints one step.\n const singleStep =\n (scale.type === 'quantile' || scale.type === 'threshold') && !banded\n ? [scale.min === null ? HEATMAP_STEPS / 2 : scale.stepOf(scale.min)]\n : null;\n const withEmpty = showEmpty ?? context?.hasEmpty ?? false;\n const withLowSample = showLowSample ?? context?.hasLowSample ?? false;\n const minCount = minCountProp ?? context?.minCount;\n const shape = variant === 'continuous' ? 'continuous' : 'stepped';\n\n const bar = (steps: readonly number[]) => (\n <span className={heatmapLegendBarVariants({ variant })}>\n {steps.map((step) => (\n <span\n key={step}\n className={heatmapSwatchVariants({\n tone: stepTone(palette, step),\n shape,\n })}\n />\n ))}\n </span>\n );\n\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-label={t('heatmap.legend.label')}\n data-component=\"heatmap-legend\"\n className={heatmapLegendVariants({ className })}\n >\n <span className=\"ds:sr-only\">{description}</span>\n {banded ? (\n <span\n aria-hidden=\"true\"\n data-legend=\"bands\"\n className=\"ds:flex ds:min-w-0 ds:max-w-full ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)] ds:tabular-nums\"\n >\n {bandSteps.map((step, band) => (\n <span\n key={step}\n className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n <span\n data-step={step}\n className={heatmapSwatchVariants({\n tone: stepTone(palette, step),\n shape: 'key',\n })}\n />\n {band < edges.length ? (\n <span className=\"ds:shrink-0\">{edges[band]}</span>\n ) : null}\n </span>\n ))}\n </span>\n ) : (\n <span\n aria-hidden=\"true\"\n className=\"ds:flex ds:min-w-0 ds:max-w-full ds:items-center ds:gap-[var(--spacing-xs)] ds:tabular-nums\"\n >\n <span className=\"ds:shrink-0\">{labels.start}</span>\n {labels.middle !== undefined ? (\n <>\n {bar(STEPS.slice(0, HEATMAP_STEPS / 2))}\n {/* A value exactly on the midpoint is painted neutral, so\n its swatch sits between the hues, carrying the value. */}\n <span\n data-legend=\"midpoint\"\n className={heatmapSwatchVariants({\n tone: 'midpoint',\n shape: 'label',\n })}\n >\n {labels.middle}\n </span>\n {bar(STEPS.slice(HEATMAP_STEPS / 2))}\n </>\n ) : (\n bar(singleStep ?? STEPS)\n )}\n <span className=\"ds:shrink-0\">{labels.end}</span>\n </span>\n )}\n {withEmpty ? (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <span\n aria-hidden=\"true\"\n className={heatmapSwatchVariants({ tone: 'empty' })}\n />\n {t('heatmap.legend.noData')}\n </span>\n ) : null}\n {withLowSample ? (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <span\n aria-hidden=\"true\"\n className={heatmapSwatchVariants({ tone: 'low-sample' })}\n />\n {minCount === undefined\n ? t('heatmap.legend.lowSample')\n : t('heatmap.legend.lowSampleUnder', {\n value: new Intl.NumberFormat(locale).format(minCount),\n })}\n </span>\n ) : null}\n </div>\n );\n },\n);\n\nHeatmapLegend.displayName = 'HeatmapLegend';\n","import {\n lazy,\n Suspense,\n useMemo,\n useRef,\n useState,\n type ComponentType,\n} from 'react';\nimport type { ColDef, GridOptions } from 'ag-grid-community';\nimport { useTranslation } from 'react-i18next';\nimport { useIsomorphicLayoutEffect } from '../../hooks/use-isomorphic-layout-effect';\nimport type { DataTableProps } from '../data-table/data-table';\nimport { ErrorBoundary } from '../error-boundary';\nimport { Skeleton } from '../skeleton';\nimport type { HeatmapDescriber } from './heatmap-format';\nimport type {\n BodyRow,\n HeatmapColumn,\n HeatmapRow,\n HeatmapTotals,\n ModelCell,\n} from './heatmap-model';\nimport { isLowSample } from './heatmap-model';\nimport { heatmapTableViewVariants } from './heatmap-variants';\nimport type { AggregateResult, HeatmapAggregate } from './heatmap-scale';\n\n/** One row of the table view: a data row or a group's totals. */\ninterface HeatmapTableRow {\n id: string;\n group?: string;\n row: string;\n cells: string[];\n total?: string;\n}\n\n/*\n * The DataTable (AG Grid) loads on demand: nothing in the heatmap's own\n * entry imports AG Grid, so a heatmap that never shows its table never\n * downloads it. Every table in the kit is DataTable. The consumer installs\n * ag-grid-community and ag-grid-react (src/docs/25-consuming.mdx).\n */\nconst loadDataTable = () =>\n import('../data-table/data-table').then((module) => ({\n default: module.DataTable as unknown as ComponentType<\n DataTableProps<HeatmapTableRow>\n >,\n }));\nconst LazyDataTable = lazy(loadDataTable);\n\n/** Starts fetching the table chunk ahead of a switch to the table view, so\n * the switch does not wait on the download. Safe to call repeatedly. */\nexport function preloadHeatmapTable(): void {\n loadDataTable().catch(() => {\n /* the switch itself retries and shows the error */\n });\n}\n\nexport interface HeatmapTableViewProps {\n title: string;\n rowsLabel?: string;\n rows: readonly HeatmapRow[];\n columns: readonly HeatmapColumn[];\n matrix: readonly ModelCell[][];\n /** Group headers and rows in display order, every group expanded. */\n body: readonly BodyRow[];\n grouped: boolean;\n /** Each group's public id, for the table's row ids (never a label). */\n groupIds: ReadonlyMap<string, string>;\n describer: HeatmapDescriber;\n totals: HeatmapTotals | null;\n rowTotals: HeatmapAggregate | false;\n columnTotals: HeatmapAggregate | false;\n groupColumnMethod: HeatmapAggregate;\n minCount?: number;\n /** The table failed to load or render (announced by the heatmap). */\n onLoadError?: () => void;\n}\n\nfunction totalCell(\n result: AggregateResult | undefined,\n minCount: number | undefined,\n): ModelCell {\n const value = result?.value ?? null;\n return {\n value,\n count: result?.count,\n status:\n value === null\n ? 'empty'\n : isLowSample(result?.count, minCount)\n ? 'low-sample'\n : 'value',\n };\n}\n\n/**\n * The heatmap's \"View as table\": the same rows, columns, values, counts and\n * totals as a DataTable, so every number is reachable without colour and\n * without a pointer. Group header rows carry their totals, and rows stay in\n * their groups in the grid's order. Labels go through the same privacy\n * masking as the grid.\n */\nexport function HeatmapTableView({\n title,\n rowsLabel,\n rows,\n columns,\n matrix,\n body,\n grouped,\n groupIds,\n describer,\n totals,\n rowTotals,\n columnTotals,\n groupColumnMethod,\n minCount,\n onLoadError,\n}: HeatmapTableViewProps) {\n const { t } = useTranslation('ui');\n\n const columnDefs = useMemo<ColDef<HeatmapTableRow>[]>(\n () => [\n ...(grouped\n ? [\n {\n colId: 'group',\n field: 'group' as const,\n headerName: t('heatmap.table.group'),\n // A sort here would pull rows out of their groups.\n sortable: false,\n },\n ]\n : []),\n {\n colId: 'row',\n field: 'row' as const,\n headerName: rowsLabel ?? t('heatmap.rowsHeader'),\n sortable: !grouped,\n },\n ...columns.map(\n (column, c): ColDef<HeatmapTableRow> => ({\n colId: `c${c}`,\n headerName: describer.columnLabel(column),\n valueGetter: (params) => params.data?.cells[c] ?? '',\n sortable: false,\n }),\n ),\n ...(rowTotals\n ? [\n {\n colId: 'total',\n field: 'total' as const,\n headerName: describer.methodLabel(rowTotals),\n sortable: false,\n },\n ]\n : []),\n ],\n [grouped, rowsLabel, columns, describer, rowTotals, t],\n );\n\n const rowData = useMemo<HeatmapTableRow[]>(\n () =>\n body.map((entry): HeatmapTableRow => {\n if (entry.kind === 'group') {\n const groupText = describer.groupLabel(entry.groupId);\n const perColumn = totals?.groupColumns.get(entry.groupId) ?? [];\n return {\n id: `group:${groupIds.get(entry.groupId) ?? ''}`,\n group: groupText,\n row: describer.groupRowText(groupText, groupColumnMethod),\n cells: columns.map((_, c) =>\n describer.tableText(totalCell(perColumn[c], minCount)),\n ),\n total:\n rowTotals && totals\n ? describer.tableText(\n totalCell(totals.groups.get(entry.groupId), minCount),\n )\n : undefined,\n };\n }\n const r = entry.rowIndex;\n const groupId = rows[r].group;\n return {\n id: `row:${rows[r].id}`,\n group:\n grouped && groupId !== undefined\n ? describer.groupLabel(groupId)\n : undefined,\n row: describer.rowLabel(rows[r]),\n cells: matrix[r].map((cell) => describer.tableText(cell)),\n total:\n rowTotals && totals\n ? describer.tableText(totalCell(totals.rows[r], minCount))\n : undefined,\n };\n }),\n [\n body,\n rows,\n columns,\n matrix,\n grouped,\n groupIds,\n describer,\n rowTotals,\n totals,\n groupColumnMethod,\n minCount,\n ],\n );\n\n const pinnedBottomRowData = useMemo<HeatmapTableRow[] | undefined>(\n () =>\n columnTotals && totals\n ? [\n {\n id: 'heatmap-column-totals',\n row: describer.methodLabel(columnTotals),\n cells: totals.columns.map((result) =>\n describer.tableText(totalCell(result, minCount)),\n ),\n // The grand total, by the row method, as the grid's corner.\n total: rowTotals\n ? describer.tableText(totalCell(totals.grand, minCount))\n : undefined,\n },\n ]\n : undefined,\n [columnTotals, rowTotals, totals, describer, minCount],\n );\n\n /*\n * Height: the table grows with its rows (AG Grid autoHeight) up to\n * --heatmap-max-block-size, so a small grid leaves no empty space. Past\n * that it holds the maximum and scrolls inside, keeping its header in\n * view. AG Grid has no max height for autoHeight, so the wrapper's own\n * max-height detects the overflow and switches the layout. Remembered\n * per row count: new rows fit again from scratch.\n */\n const rowCount = rowData.length + (pinnedBottomRowData?.length ?? 0);\n const rowCountRef = useRef(rowCount);\n rowCountRef.current = rowCount;\n const [cappedAt, setCappedAt] = useState<number | null>(null);\n const capped = cappedAt === rowCount;\n const wrapperRef = useRef<HTMLDivElement>(null);\n\n useIsomorphicLayoutEffect(() => {\n const wrapper = wrapperRef.current;\n if (capped || !wrapper || typeof ResizeObserver === 'undefined') return;\n const observer = new ResizeObserver(() => {\n if (wrapper.scrollHeight > wrapper.clientHeight + 1) {\n setCappedAt(rowCountRef.current);\n }\n });\n // Watch the content as well as the box: once the box reaches its\n // maximum it stops resizing, but the table inside may still grow.\n const watch = () => {\n observer.observe(wrapper);\n for (const child of Array.from(wrapper.children)) observer.observe(child);\n };\n watch();\n const children = new MutationObserver(watch);\n children.observe(wrapper, { childList: true });\n return () => {\n observer.disconnect();\n children.disconnect();\n };\n }, [capped]);\n\n const gridOptions = useMemo<GridOptions<HeatmapTableRow>>(\n () => ({\n getRowId: (params) => params.data.id,\n domLayout: capped ? 'normal' : 'autoHeight',\n }),\n [capped],\n );\n\n // A failed chunk load stays failed inside one lazy component, so a retry\n // makes a fresh one; the first attempt shares the module-level loader.\n const [attempt, setAttempt] = useState(0);\n const DataTable = useMemo(\n () => (attempt === 0 ? LazyDataTable : lazy(loadDataTable)),\n [attempt],\n );\n\n return (\n <div\n ref={wrapperRef}\n role=\"group\"\n aria-label={title}\n // Holds focus while a retry replaces the error state's button.\n tabIndex={-1}\n data-component=\"heatmap-table\"\n data-layout={capped ? 'capped' : 'fit'}\n className={heatmapTableViewVariants({ capped })}\n >\n <ErrorBoundary\n size=\"sm\"\n onError={() => onLoadError?.()}\n onRetry={() => {\n setAttempt((current) => current + 1);\n wrapperRef.current?.focus();\n }}\n >\n <Suspense\n fallback={\n <div role=\"status\" aria-label={t('heatmap.loadingTable')}>\n <Skeleton\n variant=\"rectangular\"\n className=\"ds:h-[calc(var(--min-target-size)*4)] ds:w-full\"\n />\n </div>\n }\n >\n <DataTable\n columnDefs={columnDefs}\n rowData={rowData}\n pinnedBottomRowData={pinnedBottomRowData}\n density=\"compact\"\n heightClass={capped ? 'ds:min-h-0 ds:flex-1' : ''}\n gridOptions={gridOptions}\n />\n </Suspense>\n </ErrorBoundary>\n </div>\n );\n}\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport { Grid3x3, Table2 } from 'lucide-react';\nimport { useTranslation } from 'react-i18next';\nimport { useAgentRegistration } from '../../agent';\nimport { formatLocale } from '../_shared/intl-locale';\nimport { Button } from '../button';\nimport { EmptyState } from '../empty-state';\nimport { LiveRegion } from '../live-region';\nimport { Skeleton } from '../skeleton';\nimport { TooltipProvider } from '../tooltip';\nimport { heatmapAgent } from './heatmap.agent';\nimport { HeatmapContext, type HeatmapContextValue } from './heatmap-context';\nimport {\n countFormatter,\n createDescriber,\n defaultValueFormatter,\n type HeatmapPrivacyScope,\n type HeatmapValueType,\n} from './heatmap-format';\nimport {\n HeatmapGrid,\n selectionKey,\n splitSelectionKey,\n type HeatmapSelectionMode,\n} from './heatmap-grid';\nimport { HeatmapLegend } from './heatmap-legend';\nimport {\n buildBodyRows,\n buildMatrix,\n computeTotals,\n hasAnyData,\n publicGroupIds,\n shownValues,\n sortRowIndexes,\n type HeatmapCellInfo,\n type HeatmapCellInput,\n type HeatmapCellKey,\n type HeatmapColumn,\n type HeatmapGroup,\n type HeatmapRow,\n type HeatmapSortRows,\n} from './heatmap-model';\nimport {\n resolveScale,\n type HeatmapAggregate,\n type HeatmapScale,\n} from './heatmap-scale';\nimport { HeatmapTableView, preloadHeatmapTable } from './heatmap-table-view';\nimport { HeatmapTooltip } from './heatmap-tooltip';\nimport {\n heatmapRootVariants,\n heatmapToolbarVariants,\n type HeatmapPalette,\n} from './heatmap-variants';\nimport { VIRTUALISE_CELL_THRESHOLD } from './heatmap-window';\n\nexport type {\n HeatmapCellData,\n HeatmapCellInfo,\n HeatmapCellInput,\n HeatmapCellKey,\n HeatmapCellStatus,\n HeatmapColumn,\n HeatmapGroup,\n HeatmapRow,\n HeatmapSortRows,\n} from './heatmap-model';\nexport type { HeatmapAggregate, HeatmapScale } from './heatmap-scale';\nexport type { HeatmapPalette } from './heatmap-variants';\nexport type { HeatmapPrivacyScope, HeatmapValueType } from './heatmap-format';\nexport type { HeatmapSelectionMode } from './heatmap-grid';\n\n/** What `renderTooltip` is told besides the cell. */\nexport interface HeatmapTooltipContext {\n /**\n * True in privacy mode. The cell's labels are then already masked (and\n * its free-text `label` dropped), so text built from them is safe to show.\n */\n privacyMode: boolean;\n}\n\n/** Which presentation is showing. */\nexport type HeatmapView = 'heatmap' | 'table';\n\n/** What one cell reads back to an agent: structure and numbers, no labels. */\nexport interface HeatmapCellReading {\n value: number | null;\n count?: number;\n status: HeatmapCellInfo['status'];\n /** As `HeatmapCellInfo.step`: a value exactly on a diverging midpoint\n * reads step 5, though it is painted neutral grey. */\n step: number | null;\n}\n\n/**\n * Curated handle for the agent adapter (see heatmap.agent.ts). Ids only,\n * never labels. Group ids are the public ones: a group's own id when it is\n * listed in `groups`, else `group-<n>`. Every write throws on an id the\n * heatmap does not have, before it changes or announces anything.\n */\nexport interface HeatmapHandle {\n getSelection: () => HeatmapCellKey[];\n getSelectionMode: () => HeatmapSelectionMode;\n selectCells: (cells: readonly HeatmapCellKey[]) => void;\n selectRange: (from: HeatmapCellKey, to: HeatmapCellKey) => void;\n clearSelection: () => void;\n readCell: (cell: HeatmapCellKey) => HeatmapCellReading | null;\n getView: () => HeatmapView;\n setView: (view: HeatmapView) => void;\n getSortRows: () => HeatmapSortRows;\n setSortRows: (sort: HeatmapSortRows) => void;\n /** Row ids in display order, every group expanded. */\n getRowIds: () => string[];\n /** Column ids in order. */\n getColumnIds: () => (string | number)[];\n /** Group ids in display order; empty unless `groupRows` is on. */\n getGroupIds: () => string[];\n getCollapsedGroups: () => string[];\n setGroupCollapsed: (groupId: string, collapsed: boolean) => void;\n}\n\n/*\n * Memoisation: `rows`, `columns`, `getCell`, `cells`, `groups` and\n * `valueFormatter` key the cell matrix, the totals and the wording every row\n * renders with. Keep them stable (useMemo, useCallback, or module scope): a\n * new array or an inline function on each parent render rebuilds them all.\n */\nexport interface HeatmapProps {\n /**\n * Required. Names the grid for assistive technology and the table view.\n * Never masked, so it must not name a person.\n */\n title: string;\n /** Rows, top to bottom. Keep the array stable (see Memoisation). */\n rows: readonly HeatmapRow[];\n /** Columns, in reading order. Keep the array stable. */\n columns: readonly HeatmapColumn[];\n /**\n * Returns a cell's data. Use this or `cells`. Keep it stable\n * (`useCallback`): an inline function rebuilds the matrix every render.\n */\n getCell?: (\n row: HeatmapRow,\n column: HeatmapColumn,\n rowIndex: number,\n columnIndex: number,\n ) => HeatmapCellInput;\n /** The cells as a `[row][column]` matrix, in the order of `rows` and `columns`. */\n cells?: readonly (readonly HeatmapCellInput[])[];\n /** Visible labels for the group ids rows carry. Keep the array stable. */\n groups?: readonly HeatmapGroup[];\n /** How values map to colour steps. Default sequential with an auto domain. */\n scale?: HeatmapScale;\n /** Colour palette. Default `diverging` for a diverging scale, else `primary`. */\n palette?: HeatmapPalette;\n /**\n * `rate` for proportions between 0 and 1: formats as a percentage and\n * reads counts as \"10 of 39\". Default `number`.\n */\n valueType?: HeatmapValueType;\n /**\n * Cells with a count below this render as \"too few to show\", hatched.\n * A display rule, not disclosure control: `read_cell`, `onCellClick`,\n * `onSelectionChange` and the totals still carry the value.\n */\n minCount?: number;\n /** Formats a value. Default: Intl in the active locale. Keep it stable. */\n valueFormatter?: (value: number) => string;\n /** Print the value inside each cell. */\n showValues?: boolean;\n /** Built-in legend above the grid, or `false` to place `Heatmap.Legend` yourself. */\n legend?: 'stepped' | 'continuous' | false;\n /**\n * A totals column at the row ends. A mean weights by count. Everything in\n * that column uses this method: each row's total, each group's and the\n * grand total in the corner.\n */\n rowTotals?: HeatmapAggregate | false;\n /**\n * A totals row under the columns. A mean weights by count. A group\n * header's per-column totals use this method too (else `rowTotals`).\n */\n columnTotals?: HeatmapAggregate | false;\n /**\n * Row order (within each group). Controlled when set. In privacy mode\n * `label` keeps the given order: sorting by masked names would reveal\n * their order.\n */\n sortRows?: HeatmapSortRows;\n /** Initial row order when uncontrolled. Default `none`. */\n defaultSortRows?: HeatmapSortRows;\n /** Called when the row order changes (agent `sort_rows`). */\n onSortRowsChange?: (sort: HeatmapSortRows) => void;\n /** Group rows by `row.group`, each group collapsible with its totals. */\n groupRows?: boolean;\n /** Group ids that start collapsed. */\n defaultCollapsedGroups?: readonly string[];\n /** How cells are selected. Default `none`. */\n selection?: HeatmapSelectionMode;\n /** Selected cells. Controlled when set. */\n selectedCells?: readonly HeatmapCellKey[];\n /** Initially selected cells when uncontrolled. */\n defaultSelectedCells?: readonly HeatmapCellKey[];\n /** Called with every cell in the new selection. */\n onSelectionChange?: (cells: HeatmapCellInfo[]) => void;\n /** Called when a cell is clicked, or activated with Enter or Space. */\n onCellClick?: (cell: HeatmapCellInfo) => void;\n /**\n * Tooltip text for a cell. Plain text: the kit Tooltip is text-only. It\n * also describes the focused cell to screen readers (aria-describedby).\n * In privacy mode the cell arrives with its labels masked, its free-text\n * `label` dropped and `row.group` replaced by the public group id, and\n * the context says so.\n */\n renderTooltip?: (\n cell: HeatmapCellInfo,\n context: HeatmapTooltipContext,\n ) => string;\n /** `compact` removes the gap between cells. Cells never shrink below the target size. */\n density?: 'compact' | 'default';\n /** Cell size. Every size keeps cells at least `--min-target-size`. */\n size?: 'sm' | 'md' | 'lg';\n /** Shows a skeleton while data loads. */\n loading?: boolean;\n /**\n * Masks row labels (people, chairs, patients) in the grid, the tooltip,\n * the table view and the announcements, and drops free-text cell labels.\n * Columns and groups stay readable unless `privacyScope=\"all\"`. `title`\n * and `rowsLabel` are never masked.\n */\n privacyMode?: boolean;\n /**\n * What privacy mode masks: `rows` (default) or `all`, which masks column\n * and group labels too.\n */\n privacyScope?: HeatmapPrivacyScope;\n /**\n * Names what the rows are (\"Chair\"): the corner header and the table's\n * first column. Never masked, so it must not name a person.\n */\n rowsLabel?: string;\n /** Initial presentation. Default `heatmap`. */\n defaultView?: HeatmapView;\n /** Called when the view switches between heatmap and table. */\n onViewChange?: (view: HeatmapView) => void;\n /** Instance id: `data-component-id`, and the agent registry key. */\n id?: string;\n className?: string;\n /**\n * Rendered inside the heatmap's context, after the grid (e.g.\n * `Heatmap.Legend`). Also while loading and when empty.\n */\n children?: ReactNode;\n}\n\nconst DEFAULT_SCALE: HeatmapScale = { type: 'sequential', domain: 'auto' };\n\n/** Selection keys for cells, by row id and column id (never by position,\n * so a change to `columns` keeps every selected cell on its own column). */\nconst toKeySet = (cells: readonly HeatmapCellKey[] | undefined): Set<string> =>\n new Set((cells ?? []).map((cell) => selectionKey(cell.rowId, cell.columnId)));\n\n/** What the live region says, and under which privacy setting it was made. */\ninterface Announcement {\n text: string;\n privacyMode: boolean;\n /** Bumped when the same words are said again, so they are heard again. */\n repeat: number;\n}\n\nconst SILENCE: Announcement = { text: '', privacyMode: false, repeat: 0 };\n\nconst HeatmapRoot = forwardRef<HTMLDivElement, HeatmapProps>(\n (\n {\n title,\n rows,\n columns,\n getCell,\n cells,\n groups,\n scale: scaleProp = DEFAULT_SCALE,\n palette: paletteProp,\n valueType = 'number',\n minCount,\n valueFormatter,\n showValues = false,\n legend = 'stepped',\n rowTotals = false,\n columnTotals = false,\n sortRows: sortRowsProp,\n defaultSortRows = 'none',\n onSortRowsChange,\n groupRows = false,\n defaultCollapsedGroups,\n selection = 'none',\n selectedCells,\n defaultSelectedCells,\n onSelectionChange,\n onCellClick,\n renderTooltip,\n density = 'default',\n size = 'md',\n loading = false,\n privacyMode = false,\n privacyScope = 'rows',\n rowsLabel,\n defaultView = 'heatmap',\n onViewChange,\n id,\n className,\n children,\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation('ui');\n const locale = formatLocale(i18n.resolvedLanguage ?? i18n.language);\n\n /* ---- data ---------------------------------------------------------- */\n const matrix = useMemo(\n () => buildMatrix(rows, columns, getCell, cells, minCount),\n [rows, columns, getCell, cells, minCount],\n );\n const values = useMemo(() => shownValues(matrix), [matrix]);\n // Consumers often pass the scale inline; key it by content so an equal\n // scale does not re-resolve on every render.\n const scaleKey = JSON.stringify(scaleProp);\n const scale = useMemo(\n () => resolveScale(scaleProp, values),\n // eslint-disable-next-line react-hooks/exhaustive-deps -- keyed by content\n [scaleKey, values],\n );\n const palette: HeatmapPalette =\n paletteProp ?? (scale.type === 'diverging' ? 'diverging' : 'primary');\n\n const formatValue = useMemo(\n () => valueFormatter ?? defaultValueFormatter(locale, valueType),\n [valueFormatter, locale, valueType],\n );\n const formatCount = useMemo(() => countFormatter(locale), [locale]);\n const describer = useMemo(\n () =>\n createDescriber({\n t,\n privacyMode,\n privacyScope,\n valueType,\n formatValue,\n formatCount,\n groups,\n }),\n [\n t,\n privacyMode,\n privacyScope,\n valueType,\n formatValue,\n formatCount,\n groups,\n ],\n );\n const groupIds = useMemo(\n () => publicGroupIds(rows, groups),\n [rows, groups],\n );\n\n // A group header's per-column totals are column margins within the\n // group, so they follow the column method; everything in the row-totals\n // column follows the row method (see computeTotals).\n const groupColumnMethod: HeatmapAggregate =\n columnTotals || rowTotals || 'mean';\n const rowMethod: HeatmapAggregate = rowTotals || 'mean';\n const totals = useMemo(\n () =>\n computeTotals(\n matrix,\n rows,\n columns.length,\n rowMethod,\n columnTotals || 'mean',\n groupColumnMethod,\n ),\n [\n matrix,\n rows,\n columns.length,\n rowMethod,\n columnTotals,\n groupColumnMethod,\n ],\n );\n\n /* ---- announcements ---------------------------------------------------- */\n const [announcement, setAnnouncement] = useState<Announcement>(SILENCE);\n const announceTimer = useRef(0);\n const privacyRef = useRef(privacyMode);\n privacyRef.current = privacyMode;\n const announce = useCallback((message: string, settle = false) => {\n window.clearTimeout(announceTimer.current);\n const madeUnder = privacyRef.current;\n const say = () =>\n setAnnouncement((current) => ({\n text: message,\n privacyMode: madeUnder,\n repeat: current.text === message ? current.repeat + 1 : 0,\n }));\n if (settle) {\n // A drag changes the selection on every cell it crosses; say only\n // where it settles.\n announceTimer.current = window.setTimeout(say, 300);\n } else {\n say();\n }\n }, []);\n useEffect(() => () => window.clearTimeout(announceTimer.current), []);\n // A message made before privacy mode turned on may name a row. Drop it\n // (and any still waiting) when the mode changes; until that lands, the\n // render below already refuses to show it.\n useEffect(() => {\n window.clearTimeout(announceTimer.current);\n setAnnouncement((current) => (current.text === '' ? current : SILENCE));\n }, [privacyMode]);\n const spoken =\n announcement.privacyMode === privacyMode\n ? // The same words twice leave the DOM unchanged and a screen reader\n // silent: a trailing no-break space on every other repeat changes\n // the text without changing what is read.\n `${announcement.text}${announcement.repeat % 2 === 1 ? '\\u00a0' : ''}`\n : '';\n\n /* ---- view, sort and groups ------------------------------------------ */\n const [view, setViewState] = useState<HeatmapView>(defaultView);\n\n const setView = useCallback(\n (next: HeatmapView) => {\n setViewState(next);\n onViewChange?.(next);\n announce(\n next === 'table'\n ? t('heatmap.announce.tableView')\n : t('heatmap.announce.heatmapView'),\n );\n },\n [onViewChange, announce, t],\n );\n\n const [sortInternal, setSortInternal] =\n useState<HeatmapSortRows>(defaultSortRows);\n const sortRows = sortRowsProp ?? sortInternal;\n const setSortRows = useCallback(\n (next: HeatmapSortRows) => {\n if (sortRowsProp === undefined) setSortInternal(next);\n onSortRowsChange?.(next);\n },\n [sortRowsProp, onSortRowsChange],\n );\n\n const [collapsed, setCollapsed] = useState<ReadonlySet<string>>(\n () => new Set(defaultCollapsedGroups ?? []),\n );\n const setGroupCollapsed = useCallback(\n (groupId: string, isCollapsed: boolean) => {\n // Already so: nothing changes, so nothing is said.\n if (collapsed.has(groupId) === isCollapsed) return;\n setCollapsed((current) => {\n if (current.has(groupId) === isCollapsed) return current;\n const next = new Set(current);\n if (isCollapsed) next.add(groupId);\n else next.delete(groupId);\n return next;\n });\n const label = describer.groupLabel(groupId);\n announce(\n isCollapsed\n ? t('heatmap.announce.groupCollapsed', { group: label })\n : t('heatmap.announce.groupExpanded', { group: label }),\n );\n },\n [collapsed, announce, describer, t],\n );\n const toggleGroup = useCallback(\n (groupId: string) => setGroupCollapsed(groupId, !collapsed.has(groupId)),\n [collapsed, setGroupCollapsed],\n );\n\n const collator = useMemo(\n () => new Intl.Collator(locale, { numeric: true, sensitivity: 'base' }),\n [locale],\n );\n // A label sort under masked labels would still order the rows by the\n // hidden names, and so reveal their order: in privacy mode it keeps the\n // given order.\n const appliedSort: HeatmapSortRows =\n sortRows === 'label' && describer.masksRows ? 'none' : sortRows;\n const order = useMemo(\n () =>\n sortRowIndexes(\n rows.map((_, r) => r),\n rows,\n totals.rows,\n appliedSort,\n collator,\n ),\n [rows, totals.rows, appliedSort, collator],\n );\n const body = useMemo(\n () => buildBodyRows(rows, order, groupRows, collapsed),\n [rows, order, groupRows, collapsed],\n );\n /** Every row in display order with every group expanded: the table\n * view's order, and the row ids an agent reads. */\n const expandedBody = useMemo(\n () => buildBodyRows(rows, order, groupRows, new Set()),\n [rows, order, groupRows],\n );\n\n /* ---- cells ---------------------------------------------------------- */\n const rowIndexById = useMemo(\n () => new Map(rows.map((row, r) => [row.id, r])),\n [rows],\n );\n const columnIndexById = useMemo(\n () => new Map(columns.map((column, c) => [String(column.id), c])),\n [columns],\n );\n const columnIndexOfKey = useCallback(\n (columnKey: string) => columnIndexById.get(columnKey),\n [columnIndexById],\n );\n const cellInfo = useCallback(\n (rowIndex: number, columnIndex: number): HeatmapCellInfo => {\n const row = rows[rowIndex];\n const column = columns[columnIndex];\n const cell = matrix[rowIndex][columnIndex];\n return {\n rowId: row.id,\n columnId: column.id,\n row,\n column,\n rowIndex,\n columnIndex,\n value: cell.value,\n count: cell.count,\n label: cell.label,\n status: cell.status,\n step:\n cell.status === 'value' && cell.value !== null\n ? scale.stepOf(cell.value)\n : null,\n };\n },\n [rows, columns, matrix, scale],\n );\n /** The cell as `renderTooltip` may see it in privacy mode: masked\n * labels, no free text, no group id that could be a name. */\n const maskedInfo = useCallback(\n (info: HeatmapCellInfo): HeatmapCellInfo => {\n const group =\n info.row.group === undefined\n ? undefined\n : groupIds.get(info.row.group);\n return {\n rowId: info.rowId,\n columnId: info.columnId,\n row: {\n id: info.row.id,\n label: describer.rowLabel(info.row),\n ...(group === undefined ? {} : { group }),\n },\n column: {\n id: info.column.id,\n label: describer.columnLabel(info.column),\n },\n rowIndex: info.rowIndex,\n columnIndex: info.columnIndex,\n value: info.value,\n count: info.count,\n status: info.status,\n step: info.step,\n };\n },\n [describer, groupIds],\n );\n const tooltipText = useCallback(\n (info: HeatmapCellInfo) =>\n renderTooltip\n ? renderTooltip(privacyMode ? maskedInfo(info) : info, {\n privacyMode,\n })\n : describer.sentence(\n describer.rowLabel(info.row),\n describer.columnLabel(info.column),\n matrix[info.rowIndex][info.columnIndex],\n ),\n [renderTooltip, privacyMode, maskedInfo, describer, matrix],\n );\n\n /* ---- selection ------------------------------------------------------- */\n const isControlled = selectedCells !== undefined;\n const [selectedInternal, setSelectedInternal] = useState<Set<string>>(() =>\n toKeySet(defaultSelectedCells),\n );\n // Keys are row id + column id. Only those naming a current row and\n // column count, so a removed column drops out of the selection instead\n // of pointing at whatever now sits in its place.\n const selected = useMemo(() => {\n const source = isControlled ? toKeySet(selectedCells) : selectedInternal;\n const present = new Set<string>();\n for (const key of source) {\n const [rowId, columnKey] = splitSelectionKey(key);\n if (rowIndexById.has(rowId) && columnIndexById.has(columnKey)) {\n present.add(key);\n }\n }\n return present;\n }, [\n isControlled,\n selectedCells,\n selectedInternal,\n rowIndexById,\n columnIndexById,\n ]);\n\n const infosOf = useCallback(\n (keys: ReadonlySet<string>): HeatmapCellInfo[] => {\n const infos: HeatmapCellInfo[] = [];\n for (const key of keys) {\n const [rowId, columnKey] = splitSelectionKey(key);\n const r = rowIndexById.get(rowId);\n const c = columnIndexById.get(columnKey);\n if (r !== undefined && c !== undefined) infos.push(cellInfo(r, c));\n }\n return infos;\n },\n [rowIndexById, columnIndexById, cellInfo],\n );\n const cellName = useCallback(\n (rowIndex: number, columnIndex: number) =>\n describer.cellName(\n describer.rowLabel(rows[rowIndex]),\n describer.columnLabel(columns[columnIndex]),\n ),\n [describer, rows, columns],\n );\n const commitSelection = useCallback(\n (next: Set<string>, message: string, settle = false) => {\n if (!isControlled) setSelectedInternal(next);\n onSelectionChange?.(infosOf(next));\n announce(message, settle);\n },\n [isControlled, onSelectionChange, infosOf, announce],\n );\n const countMessage = useCallback(\n (count: number) =>\n count === 0\n ? t('heatmap.announce.cleared')\n : t('heatmap.announce.count', {\n count,\n formatted: formatCount(count),\n }),\n [t, formatCount],\n );\n\n /** The visible data rows in display order, for range rectangles. */\n const dataOrder = useMemo(\n () => body.flatMap((row) => (row.kind === 'data' ? [row.rowIndex] : [])),\n [body],\n );\n const rectangle = useCallback(\n (\n from: { rowIndex: number; col: number },\n to: { rowIndex: number; col: number },\n ) => {\n const a = dataOrder.indexOf(from.rowIndex);\n const b = dataOrder.indexOf(to.rowIndex);\n const next = new Set<string>();\n if (a === -1 || b === -1) return next;\n const [top, bottom] = a <= b ? [a, b] : [b, a];\n const [left, right] =\n from.col <= to.col ? [from.col, to.col] : [to.col, from.col];\n for (let i = top; i <= bottom; i += 1) {\n const rowId = rows[dataOrder[i]].id;\n for (let c = left; c <= right; c += 1) {\n next.add(selectionKey(rowId, columns[c].id));\n }\n }\n return next;\n },\n [dataOrder, rows, columns],\n );\n\n const onActivate = useCallback(\n (rowIndex: number, columnIndex: number, select: boolean) => {\n onCellClick?.(cellInfo(rowIndex, columnIndex));\n if (!select || selection === 'none') return;\n const key = selectionKey(rows[rowIndex].id, columns[columnIndex].id);\n const name = cellName(rowIndex, columnIndex);\n if (selection === 'multiple') {\n const next = new Set(selected);\n const adding = !next.has(key);\n if (adding) next.add(key);\n else next.delete(key);\n commitSelection(\n next,\n t(adding ? 'heatmap.announce.added' : 'heatmap.announce.removed', {\n cell: name,\n count: next.size,\n formatted: formatCount(next.size),\n }),\n );\n return;\n }\n // Single and range: the cell becomes the whole selection (a range's\n // anchor); selecting the only selected cell again clears it.\n const clearing = selected.size === 1 && selected.has(key);\n commitSelection(\n clearing ? new Set() : new Set([key]),\n clearing\n ? t('heatmap.announce.cleared')\n : t('heatmap.announce.selected', { cell: name }),\n );\n },\n [\n onCellClick,\n cellInfo,\n selection,\n rows,\n columns,\n cellName,\n selected,\n commitSelection,\n formatCount,\n t,\n ],\n );\n\n const onRange = useCallback(\n (\n from: { rowIndex: number; col: number },\n to: { rowIndex: number; col: number },\n ) => {\n if (selection !== 'range' && selection !== 'multiple') return;\n const next = rectangle(from, to);\n if (\n next.size === selected.size &&\n [...next].every((key) => selected.has(key))\n ) {\n return;\n }\n commitSelection(next, countMessage(next.size), true);\n },\n [selection, rectangle, selected, commitSelection, countMessage],\n );\n\n /* ---- agent handle ------------------------------------------------------ */\n const groupByPublicId = useMemo(\n () => new Map([...groupIds].map(([own, shown]) => [shown, own])),\n [groupIds],\n );\n const agentState = {\n selected,\n selection,\n view,\n sortRows,\n collapsed,\n groupRows,\n rows,\n columns,\n expandedBody,\n groupIds,\n groupByPublicId,\n rowIndexById,\n columnIndexById,\n matrix,\n scale,\n setView,\n setSortRows,\n setGroupCollapsed,\n commitSelection,\n rectangle,\n countMessage,\n };\n const latest = useRef(agentState);\n latest.current = agentState;\n const agentHandle = useMemo<HeatmapHandle>(() => {\n const keysOf = (set: ReadonlySet<string>): HeatmapCellKey[] => {\n const { columns: cols, columnIndexById: byColumn } = latest.current;\n const keys: HeatmapCellKey[] = [];\n for (const key of set) {\n const [rowId, columnKey] = splitSelectionKey(key);\n const c = byColumn.get(columnKey);\n // The column's own id, number or string, as the consumer gave it.\n if (c !== undefined) keys.push({ rowId, columnId: cols[c].id });\n }\n return keys;\n };\n const position = (cell: HeatmapCellKey) => {\n const { rowIndexById: byRow, columnIndexById: byColumn } =\n latest.current;\n const rowIndex = byRow.get(cell.rowId);\n const col = byColumn.get(String(cell.columnId));\n return rowIndex === undefined || col === undefined\n ? null\n : { rowIndex, col };\n };\n /** Throws on an unknown cell, before anything changes or is said. */\n const requireCell = (cell: HeatmapCellKey) => {\n const at = position(cell);\n if (!at) {\n throw new Error(\n `Heatmap: no cell at row \"${cell.rowId}\", column \"${String(cell.columnId)}\".`,\n );\n }\n return at;\n };\n const requireSelection = () => {\n if (latest.current.selection === 'none') {\n throw new Error('Heatmap: selection is off (selection=\"none\").');\n }\n };\n return {\n getSelection: () => keysOf(latest.current.selected),\n getSelectionMode: () => latest.current.selection,\n selectCells: (cellsToSelect) => {\n requireSelection();\n cellsToSelect.forEach(requireCell);\n const { selection: mode } = latest.current;\n const picked =\n mode === 'single' ? cellsToSelect.slice(0, 1) : cellsToSelect;\n const next = toKeySet(picked);\n latest.current.commitSelection(\n next,\n latest.current.countMessage(next.size),\n );\n },\n selectRange: (from, to) => {\n const { selection: mode } = latest.current;\n if (mode !== 'range' && mode !== 'multiple') {\n throw new Error(\n 'Heatmap: select_range needs selection=\"range\" or \"multiple\".',\n );\n }\n const a = requireCell(from);\n const b = requireCell(to);\n const next = latest.current.rectangle(a, b);\n latest.current.commitSelection(\n next,\n latest.current.countMessage(next.size),\n );\n },\n clearSelection: () => {\n requireSelection();\n if (latest.current.selected.size === 0) return;\n latest.current.commitSelection(\n new Set(),\n latest.current.countMessage(0),\n );\n },\n readCell: (cell) => {\n const at = position(cell);\n if (!at) return null;\n const model = latest.current.matrix[at.rowIndex][at.col];\n return {\n value: model.value,\n count: model.count,\n status: model.status,\n step:\n model.status === 'value' && model.value !== null\n ? latest.current.scale.stepOf(model.value)\n : null,\n };\n },\n getView: () => latest.current.view,\n setView: (next) => latest.current.setView(next),\n getSortRows: () => latest.current.sortRows,\n setSortRows: (next) => latest.current.setSortRows(next),\n getRowIds: () => {\n const { expandedBody: shown, rows: all } = latest.current;\n return shown.flatMap((row) =>\n row.kind === 'data' ? [all[row.rowIndex].id] : [],\n );\n },\n getColumnIds: () => latest.current.columns.map((column) => column.id),\n getGroupIds: () => {\n const {\n groupRows: grouped,\n expandedBody: shown,\n groupIds: ids,\n } = latest.current;\n if (!grouped) return [];\n return shown.flatMap((row) =>\n row.kind === 'group' ? [ids.get(row.groupId) ?? ''] : [],\n );\n },\n getCollapsedGroups: () => {\n const { collapsed: hidden, groupIds: ids } = latest.current;\n return [...hidden].flatMap((own) => {\n const shown = ids.get(own);\n return shown === undefined ? [] : [shown];\n });\n },\n setGroupCollapsed: (groupId, isCollapsed) => {\n const { groupRows: grouped, groupByPublicId: byShown } =\n latest.current;\n if (!grouped) {\n throw new Error(\n 'Heatmap: rows are not grouped (groupRows is off).',\n );\n }\n const own = byShown.get(groupId);\n if (own === undefined) {\n throw new Error(`Heatmap: no group \"${groupId}\".`);\n }\n latest.current.setGroupCollapsed(own, isCollapsed);\n },\n };\n }, []);\n useAgentRegistration(heatmapAgent, agentHandle, id);\n\n /* ---- context ----------------------------------------------------------- */\n const hasEmpty = useMemo(\n () => matrix.some((row) => row.some((cell) => cell.status === 'empty')),\n [matrix],\n );\n const hasLowSample = useMemo(\n () =>\n matrix.some((row) => row.some((cell) => cell.status === 'low-sample')),\n [matrix],\n );\n const context = useMemo<HeatmapContextValue>(\n () => ({\n palette,\n scale,\n describer,\n hasEmpty,\n hasLowSample,\n minCount,\n tooltipText,\n }),\n [\n palette,\n scale,\n describer,\n hasEmpty,\n hasLowSample,\n minCount,\n tooltipText,\n ],\n );\n\n /* ---- render ------------------------------------------------------------ */\n const rootClassName = heatmapRootVariants({ className });\n\n if (loading) {\n return (\n <HeatmapContext.Provider value={context}>\n <div\n ref={ref}\n data-component=\"heatmap\"\n data-component-id={id}\n className={rootClassName}\n >\n <div\n role=\"status\"\n aria-label={t('heatmap.loading')}\n aria-busy=\"true\"\n className={heatmapRootVariants()}\n >\n <Skeleton\n variant=\"rectangular\"\n className=\"ds:h-[var(--spacing-md)] ds:w-[calc(var(--spacing-xl)*6)] ds:max-w-full\"\n />\n <Skeleton\n variant=\"rectangular\"\n className=\"ds:h-[calc(var(--min-target-size)*5)] ds:w-full\"\n />\n </div>\n {children}\n </div>\n </HeatmapContext.Provider>\n );\n }\n\n if (rows.length === 0 || columns.length === 0 || !hasAnyData(matrix)) {\n return (\n <HeatmapContext.Provider value={context}>\n <div\n ref={ref}\n data-component=\"heatmap\"\n data-component-id={id}\n className={rootClassName}\n >\n <EmptyState\n variant=\"no-results\"\n size=\"sm\"\n title={t('heatmap.empty.title')}\n description={t('heatmap.empty.description')}\n />\n {children}\n </div>\n </HeatmapContext.Provider>\n );\n }\n\n const virtualised =\n rows.length * columns.length > VIRTUALISE_CELL_THRESHOLD;\n const interactive = selection !== 'none' || onCellClick !== undefined;\n\n return (\n <HeatmapContext.Provider value={context}>\n <div\n ref={ref}\n data-component=\"heatmap\"\n data-component-id={id}\n className={rootClassName}\n >\n <div className={heatmapToolbarVariants()}>\n {legend !== false ? <HeatmapLegend variant={legend} /> : null}\n <Button\n intent=\"outline\"\n size=\"sm\"\n className=\"ds:ms-auto\"\n startIcon={\n view === 'table' ? (\n <Grid3x3 aria-hidden=\"true\" />\n ) : (\n <Table2 aria-hidden=\"true\" />\n )\n }\n // Fetch the table chunk on intent, so the switch rarely waits.\n onPointerEnter={\n view === 'table' ? undefined : preloadHeatmapTable\n }\n onFocus={view === 'table' ? undefined : preloadHeatmapTable}\n onClick={() => setView(view === 'table' ? 'heatmap' : 'table')}\n >\n {view === 'table'\n ? t('heatmap.viewAsHeatmap')\n : t('heatmap.viewAsTable')}\n </Button>\n </div>\n {view === 'table' ? (\n <HeatmapTableView\n // A new table when the privacy setting changes: AG Grid applies\n // new row data a frame later, and the old labels must not\n // show for that frame.\n key={`${privacyMode}-${privacyScope}`}\n onLoadError={() => announce(t('heatmap.announce.tableFailed'))}\n title={title}\n rowsLabel={rowsLabel}\n rows={rows}\n columns={columns}\n matrix={matrix}\n body={expandedBody}\n grouped={groupRows}\n groupIds={groupIds}\n describer={describer}\n totals={totals}\n rowTotals={rowTotals}\n columnTotals={columnTotals}\n groupColumnMethod={groupColumnMethod}\n minCount={minCount}\n />\n ) : (\n <TooltipProvider delayDuration={0}>\n <HeatmapGrid\n title={title}\n rowsLabel={rowsLabel}\n rows={rows}\n columns={columns}\n matrix={matrix}\n body={body}\n scale={scale}\n palette={palette}\n describer={describer}\n showValues={showValues}\n totals={totals}\n rowTotals={rowTotals}\n columnTotals={columnTotals}\n groupColumnMethod={groupColumnMethod}\n groupIds={groupIds}\n minCount={minCount}\n selectionMode={selection}\n selected={selected}\n columnIndexOfKey={columnIndexOfKey}\n interactive={interactive}\n virtualised={virtualised}\n size={size}\n density={density}\n cellInfo={cellInfo}\n tooltipText={tooltipText}\n describeFocused={renderTooltip !== undefined}\n onActivate={onActivate}\n onRange={onRange}\n onToggleGroup={toggleGroup}\n />\n </TooltipProvider>\n )}\n {children}\n {/* A fresh region when the privacy setting changes: LiveRegion\n shows its text from an effect, so a kept one would show a\n message made before privacy mode for one more render. */}\n <LiveRegion key={String(privacyMode)}>{spoken}</LiveRegion>\n </div>\n </HeatmapContext.Provider>\n );\n },\n);\n\nHeatmapRoot.displayName = 'Heatmap';\n\n/**\n * Heatmap: a grid of cells coloured by value on a token scale, for patterns\n * such as chair occupancy by hour or no-shows by weekday and hour. Keyboard,\n * screen reader and table view are built in; see heatmap.mdx.\n */\nexport const Heatmap = Object.assign(HeatmapRoot, {\n Legend: HeatmapLegend,\n Tooltip: HeatmapTooltip,\n});\n"],"names":["__iconNode","Grid3x3","createLucideIcon","Table2","cellSchema","heatmapAgent","handle","args","next","HeatmapContext","createContext","useHeatmapContext","useContext","defaultValueFormatter","locale","valueType","format","value","countFormatter","count","EMPTY_GLYPH","createDescriber","t","privacyMode","privacyScope","formatValue","formatCount","groups","groupNames","group","mask","privacyMask","masksRows","masksColumns","masksGroups","valueText","cell","countText","row","column","groupId","rowText","columnText","groupText","method","HEATMAP_STEPS","MIDDLE_STEP","TOP_STEP","HALF_STEPS","clamp","low","high","warned","warn","message","isDevelopment","orderedDomain","domain","distinctSorted","values","sorted","b","i","extent","sequentialStep","divergingStep","midpoint","span","onMidpoint","scale","magnitude","quantileSorted","p","n","position","below","above","quantileThresholds","buckets","edges","usableQuantileEdges","min","atOrAbove","edge","mid","thresholdBucket","thresholds","bucketStep","bucket","bucketCount","resolveScale","range","fixed","reach","a","given","distinct","sumOf","cells","total","seen","counted","weightedMean","weighted","weights","weight","aggregate","publicGroupIds","rows","listed","taken","ids","fallback","isLowSample","minCount","toModelCell","input","data","status","buildMatrix","columns","getCell","r","c","_a","shownValues","matrix","hasAnyData","computeTotals","columnCount","rowMethod","columnMethod","groupColumnMethod","rowTotals","columnTotals","byGroup","list","groupColumns","indexes","perColumn","dataRowKey","rowId","groupRowKey","FOOTER_ROW_KEY","sortRowIndexes","totals","sort","collator","direction","left","right","_b","buildBodyRows","sortedIndexes","groupRows","collapsed","order","members","loose","body","rowIndexes","isCollapsed","HeatmapTooltip","label","open","onOpenChange","side","children","context","text","jsx","Tooltip","HeatmapCellTooltip","VIRTUALISE_CELL_THRESHOLD","OVERSCAN","visibleRange","offset","viewport","lead","pitch","overscan","from","first","last","start","end","axisWindow","pinned","visible","fullWindow","_","trimWindow","window","index","sameWindow","stepTone","palette","step","toneClasses","heatmapRootVariants","cva","heatmapToolbarVariants","heatmapScrollerVariants","heatmapTableViewVariants","heatmapGridVariants","heatmapRowVariants","heatmapSpacerVariants","headerHighlight","heatmapColumnHeaderVariants","heatmapRowHeaderVariants","heatmapRowLabelVariants","heatmapCellVariants","heatmapLegendVariants","heatmapLegendBarVariants","heatmapSwatchVariants","KEY_SEPARATOR","selectionKey","columnId","splitSelectionKey","key","at","toneOf","aggregateCell","result","aggregateTone","renderColumns","render","out","columnIndex","HeatmapBodyRow","memo","ctx","ariaRowIndex","highlighted","activeCol","tooltipCol","selectedCols","selected","useMemo","hookId","labelId","overall","groupCell","withTooltip","name","jsxs","perColumnRowText","event","ChevronDown","source","dataCell","isSelected","totalCell","DEFAULT_METRICS","pageRows","metrics","HeatmapGrid","props","title","rowsLabel","describer","showValues","groupIds","selectionMode","columnIndexOfKey","interactive","virtualised","size","density","cellInfo","tooltipText","describeFocused","onActivate","onRange","onToggleGroup","useTranslation","idBase","useId","scrollerRef","useRef","gridRef","headerRef","footerRef","navColumnCount","hasFooter","navRowKeys","rowIndexOfKey","map","active","setActive","useState","activeRow","found","hidden","activeKey","pendingFocus","hasFocus","setHasFocus","hasFocusRef","interaction","hover","setHover","hoverRef","tooltipDismissed","setTooltipDismissed","updateHover","useCallback","current","highlight","tooltipAt","setMetrics","metricsRef","measure","scroller","grid","style","rowGap","columnGap","tracks","track","headerHeight","firstBody","bodyHeight","useIsomorphicLayoutEffect","observer","pinnedRow","pinnedCol","computeWindows","m","rowRange","colRange","windowState","setWindows","fullRows","fullCols","windows","syncWindows","frame","onScroll","useEffect","cellElement","rowIndex","col","element","isRtl","anchor","dataRowIndexAt","navIndex","clearOnClick","moveTo","clampedRow","clampedCol","activate","extend","onKeyDown","lastRow","lastCol","forward","ctrl","nextGroup","previous","moved","isArrow","target","positionOf","rowElement","dragging","lastPointer","onPointerDown","stop","onPointerMove","awayListener","stopAway","onPointerLeave","away","over","onClick","button","scrolling","settle","onAnyScroll","onTooltipOpenChange","expandLabel","collapseLabel","descriptionId","focusedRow","description","selectedByRow","columnKey","joined","highlightCol","header","footer","footerIndex","methodText","footerActive","bodyRows","rowWindow","isActiveRow","scrollerStyle","STEPS","endLabels","HeatmapLegend","forwardRef","variant","paletteProp","scaleProp","valueFormatter","showEmpty","showLowSample","minCountProp","className","ref","i18n","formatLocale","banded","bandCount","bandSteps","band","labels","singleStep","withEmpty","withLowSample","shape","bar","steps","Fragment","loadDataTable","module","LazyDataTable","lazy","preloadHeatmapTable","HeatmapTableView","grouped","onLoadError","columnDefs","params","rowData","entry","pinnedBottomRowData","rowCount","rowCountRef","cappedAt","setCappedAt","capped","wrapperRef","wrapper","watch","child","gridOptions","attempt","setAttempt","DataTable","ErrorBoundary","Suspense","Skeleton","DEFAULT_SCALE","toKeySet","SILENCE","HeatmapRoot","legend","sortRowsProp","defaultSortRows","onSortRowsChange","defaultCollapsedGroups","selection","selectedCells","defaultSelectedCells","onSelectionChange","onCellClick","renderTooltip","loading","defaultView","onViewChange","id","scaleKey","announcement","setAnnouncement","announceTimer","privacyRef","announce","madeUnder","say","spoken","view","setViewState","setView","sortInternal","setSortInternal","sortRows","setSortRows","setCollapsed","setGroupCollapsed","toggleGroup","appliedSort","expandedBody","rowIndexById","columnIndexById","maskedInfo","info","isControlled","selectedInternal","setSelectedInternal","present","infosOf","keys","infos","cellName","commitSelection","countMessage","dataOrder","rectangle","to","top","bottom","select","adding","clearing","groupByPublicId","own","shown","agentState","latest","agentHandle","keysOf","set","cols","byColumn","byRow","requireCell","requireSelection","cellsToSelect","mode","picked","model","all","byShown","useAgentRegistration","hasEmpty","hasLowSample","rootClassName","EmptyState","Button","TooltipProvider","LiveRegion","Heatmap"],"mappings":"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","x_google_ignoreList":[0,1]}
|