@alfadocs/ui-kit-debug 1.104.0 → 1.106.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/{ai-credits-exhausted-notice-CwZnSACy.js → ai-credits-exhausted-notice-Lws3113e.js} +2 -2
- package/dist/_chunks/{ai-credits-exhausted-notice-CwZnSACy.js.map → ai-credits-exhausted-notice-Lws3113e.js.map} +1 -1
- package/dist/_chunks/{ai-permission-notice-VNh3W57L.js → ai-permission-notice-BkgcGmu8.js} +2 -2
- package/dist/_chunks/{ai-permission-notice-VNh3W57L.js.map → ai-permission-notice-BkgcGmu8.js.map} +1 -1
- package/dist/_chunks/{alert-9kEwDza3.js → alert-C4WKViaS.js} +59 -50
- package/dist/_chunks/alert-C4WKViaS.js.map +1 -0
- package/dist/_chunks/{anamnesis-summary-rows-B9HqOGd7.js → anamnesis-summary-rows-QhbDdY7b.js} +4 -4
- package/dist/_chunks/{anamnesis-summary-rows-B9HqOGd7.js.map → anamnesis-summary-rows-QhbDdY7b.js.map} +1 -1
- package/dist/_chunks/{audio-recorder-BOm2FgEu.js → audio-recorder-BlDozxdU.js} +2 -2
- package/dist/_chunks/{audio-recorder-BOm2FgEu.js.map → audio-recorder-BlDozxdU.js.map} +1 -1
- package/dist/_chunks/{auth-form-parts-B3GWChvG.js → auth-form-parts-DVHfqnp6.js} +2 -2
- package/dist/_chunks/{auth-form-parts-B3GWChvG.js.map → auth-form-parts-DVHfqnp6.js.map} +1 -1
- package/dist/_chunks/{balance-badge-cell-DGFm2jfP.js → balance-badge-cell-wJ6cTD_h.js} +3 -3
- package/dist/_chunks/{balance-badge-cell-DGFm2jfP.js.map → balance-badge-cell-wJ6cTD_h.js.map} +1 -1
- package/dist/_chunks/{calendar-appointment-editor-dialog-DqyATSh3.js → calendar-appointment-editor-dialog-D8DblVjW.js} +8 -8
- package/dist/_chunks/{calendar-appointment-editor-dialog-DqyATSh3.js.map → calendar-appointment-editor-dialog-D8DblVjW.js.map} +1 -1
- package/dist/_chunks/{care-plan-card-YWKV8Kjq.js → care-plan-card-DMjlYlFc.js} +2 -2
- package/dist/_chunks/{care-plan-card-YWKV8Kjq.js.map → care-plan-card-DMjlYlFc.js.map} +1 -1
- package/dist/_chunks/{care-plan-entry-card-CApivtMW.js → care-plan-entry-card-3hguBW45.js} +2 -2
- package/dist/_chunks/{care-plan-entry-card-CApivtMW.js.map → care-plan-entry-card-3hguBW45.js.map} +1 -1
- package/dist/_chunks/{contact-profile-card-uExd3pKC.js → contact-profile-card-CAL66GaH.js} +120 -111
- package/dist/_chunks/contact-profile-card-CAL66GaH.js.map +1 -0
- package/dist/_chunks/{data-table-C5uN4ato.js → data-table-zXBxFYpJ.js} +761 -715
- package/dist/_chunks/data-table-zXBxFYpJ.js.map +1 -0
- package/dist/_chunks/{date-range-picker-B_j4VQlV.js → date-range-picker-DCADIR8o.js} +2 -2
- package/dist/_chunks/{date-range-picker-B_j4VQlV.js.map → date-range-picker-DCADIR8o.js.map} +1 -1
- package/dist/_chunks/{date-time-picker-cwsWiB4q.js → date-time-picker-CT2bC7-A.js} +2 -2
- package/dist/_chunks/{date-time-picker-cwsWiB4q.js.map → date-time-picker-CT2bC7-A.js.map} +1 -1
- package/dist/_chunks/{document-preview-U8H6tnDJ.js → document-preview-BalyZqnn.js} +2 -2
- package/dist/_chunks/{document-preview-U8H6tnDJ.js.map → document-preview-BalyZqnn.js.map} +1 -1
- package/dist/_chunks/{document-scanner-Bf3VUp00.js → document-scanner-5p-Uu8dy.js} +2 -2
- package/dist/_chunks/{document-scanner-Bf3VUp00.js.map → document-scanner-5p-Uu8dy.js.map} +1 -1
- package/dist/_chunks/{entity-summary-BKfR4Vws.js → entity-summary-BbqqYqF1.js} +2 -2
- package/dist/_chunks/{entity-summary-BKfR4Vws.js.map → entity-summary-BbqqYqF1.js.map} +1 -1
- package/dist/_chunks/{error-summary-mGxIyDAY.js → error-summary-DxNhwf_G.js} +2 -2
- package/dist/_chunks/{error-summary-mGxIyDAY.js.map → error-summary-DxNhwf_G.js.map} +1 -1
- package/dist/_chunks/{face-scheme-DdVLQ5dP.js → face-scheme-e2M2HJGz.js} +2 -2
- package/dist/_chunks/{face-scheme-DdVLQ5dP.js.map → face-scheme-e2M2HJGz.js.map} +1 -1
- package/dist/_chunks/{file-manager-CnGBVX_q.js → file-manager-BDKe59sg.js} +2 -2
- package/dist/_chunks/{file-manager-CnGBVX_q.js.map → file-manager-BDKe59sg.js.map} +1 -1
- package/dist/_chunks/{forgot-password-form-CeTb5p-x.js → forgot-password-form-vfCO2-Tt.js} +4 -4
- package/dist/_chunks/{forgot-password-form-CeTb5p-x.js.map → forgot-password-form-vfCO2-Tt.js.map} +1 -1
- package/dist/_chunks/{freemium-paywall-CM0zQSDE.js → freemium-paywall-BDeq9QWR.js} +2 -2
- package/dist/_chunks/{freemium-paywall-CM0zQSDE.js.map → freemium-paywall-BDeq9QWR.js.map} +1 -1
- package/dist/_chunks/{gestational-age-calculator-CXcDKQqC.js → gestational-age-calculator-AnaH00nk.js} +2 -2
- package/dist/_chunks/{gestational-age-calculator-CXcDKQqC.js.map → gestational-age-calculator-AnaH00nk.js.map} +1 -1
- package/dist/_chunks/{hcg-doubling-BJFR3onB.js → hcg-doubling-DdyUt4gz.js} +2 -2
- package/dist/_chunks/{hcg-doubling-BJFR3onB.js.map → hcg-doubling-DdyUt4gz.js.map} +1 -1
- package/dist/_chunks/{heatmap-Cz0Krieg.js → heatmap-D4qqpCEj.js} +1550 -1547
- package/dist/_chunks/{heatmap-Cz0Krieg.js.map → heatmap-D4qqpCEj.js.map} +1 -1
- package/dist/_chunks/{help-me-write-templates-ra5a__Yy.js → help-me-write-templates-YmceSxf5.js} +3 -3
- package/dist/_chunks/{help-me-write-templates-ra5a__Yy.js.map → help-me-write-templates-YmceSxf5.js.map} +1 -1
- package/dist/_chunks/info-tip-C-MPkShR.js +266 -0
- package/dist/_chunks/info-tip-C-MPkShR.js.map +1 -0
- package/dist/_chunks/{kit-extensions-C4o_tFN4.js → kit-extensions-BOnTM4Yf.js} +3 -3
- package/dist/_chunks/{kit-extensions-C4o_tFN4.js.map → kit-extensions-BOnTM4Yf.js.map} +1 -1
- package/dist/_chunks/{link-cell-renderer-BRek9kz7.js → link-cell-renderer-C8vfCOEp.js} +2 -2
- package/dist/_chunks/{link-cell-renderer-BRek9kz7.js.map → link-cell-renderer-C8vfCOEp.js.map} +1 -1
- package/dist/_chunks/{login-dev-card-D5BV5j1i.js → login-dev-card-Cz1Clugq.js} +3 -3
- package/dist/_chunks/{login-dev-card-D5BV5j1i.js.map → login-dev-card-Cz1Clugq.js.map} +1 -1
- package/dist/_chunks/{marketplace-app-shell-BsctSegT.js → marketplace-app-shell-C-4QF6mp.js} +2 -2
- package/dist/_chunks/{marketplace-app-shell-BsctSegT.js.map → marketplace-app-shell-C-4QF6mp.js.map} +1 -1
- package/dist/_chunks/{notes-panel-BjTpaz8d.js → notes-panel-SlzUL8in.js} +4 -4
- package/dist/_chunks/{notes-panel-BjTpaz8d.js.map → notes-panel-SlzUL8in.js.map} +1 -1
- package/dist/_chunks/{notice-group-DkYzKyAZ.js → notice-group-B-trhof8.js} +3 -3
- package/dist/_chunks/{notice-group-DkYzKyAZ.js.map → notice-group-B-trhof8.js.map} +1 -1
- package/dist/_chunks/{patient-details-BXM3dRKb.js → patient-details-wMgTFtpp.js} +2 -2
- package/dist/_chunks/{patient-details-BXM3dRKb.js.map → patient-details-wMgTFtpp.js.map} +1 -1
- package/dist/_chunks/{patient-field-row--dCDO5oB.js → patient-field-row-Bhm2Ig1P.js} +2 -2
- package/dist/_chunks/{patient-field-row--dCDO5oB.js.map → patient-field-row-Bhm2Ig1P.js.map} +1 -1
- package/dist/_chunks/{patient-summary-card-DB7fv-Tr.js → patient-summary-card-DMdPPG3n.js} +2 -2
- package/dist/_chunks/{patient-summary-card-DB7fv-Tr.js.map → patient-summary-card-DMdPPG3n.js.map} +1 -1
- package/dist/_chunks/{payment-automation-upsell-BPF0c-5D.js → payment-automation-upsell-u5EuFyCY.js} +2 -2
- package/dist/_chunks/{payment-automation-upsell-BPF0c-5D.js.map → payment-automation-upsell-u5EuFyCY.js.map} +1 -1
- package/dist/_chunks/{payment-form-PBuh8PIa.js → payment-form-C-s1x-bU.js} +2 -2
- package/dist/_chunks/{payment-form-PBuh8PIa.js.map → payment-form-C-s1x-bU.js.map} +1 -1
- package/dist/_chunks/{pdf-viewer-DlceXkfW.js → pdf-viewer-BnBKdx0y.js} +2 -2
- package/dist/_chunks/{pdf-viewer-DlceXkfW.js.map → pdf-viewer-BnBKdx0y.js.map} +1 -1
- package/dist/_chunks/{practice-profile-hero-BAvGdQmt.js → practice-profile-hero-Bb4YyxHA.js} +31 -29
- package/dist/_chunks/practice-profile-hero-Bb4YyxHA.js.map +1 -0
- package/dist/_chunks/{practice-results-ChBP9x2r.js → practice-results-BXz01sti.js} +485 -445
- package/dist/_chunks/practice-results-BXz01sti.js.map +1 -0
- package/dist/_chunks/{pregnancy-dating-D0Kf9s7s.js → pregnancy-dating-D6dLkMpl.js} +2 -2
- package/dist/_chunks/{pregnancy-dating-D0Kf9s7s.js.map → pregnancy-dating-D6dLkMpl.js.map} +1 -1
- package/dist/_chunks/{progress-notice-DiHWZ8Ms.js → progress-notice-F7ao70ZP.js} +2 -2
- package/dist/_chunks/{progress-notice-DiHWZ8Ms.js.map → progress-notice-F7ao70ZP.js.map} +1 -1
- package/dist/_chunks/{radiograph-panel.agent-BQ95uFCd.js → radiograph-panel.agent-0ngF2sGS.js} +2 -2
- package/dist/_chunks/{radiograph-panel.agent-BQ95uFCd.js.map → radiograph-panel.agent-0ngF2sGS.js.map} +1 -1
- package/dist/_chunks/{registration-form-JzzTomhd.js → registration-form-CEJRUS9G.js} +3 -3
- package/dist/_chunks/{registration-form-JzzTomhd.js.map → registration-form-CEJRUS9G.js.map} +1 -1
- package/dist/_chunks/{reserved.agent-BxD0gnbt.js → reserved.agent-C-C9cvO5.js} +2 -2
- package/dist/_chunks/{reserved.agent-BxD0gnbt.js.map → reserved.agent-C-C9cvO5.js.map} +1 -1
- package/dist/_chunks/{reset-password-form-DDdGEoIL.js → reset-password-form-B0acanDD.js} +4 -4
- package/dist/_chunks/{reset-password-form-DDdGEoIL.js.map → reset-password-form-B0acanDD.js.map} +1 -1
- package/dist/_chunks/{reviews-panel-jPYgYvxG.js → reviews-panel-CtrwZOUS.js} +215 -205
- package/dist/_chunks/reviews-panel-CtrwZOUS.js.map +1 -0
- package/dist/_chunks/{rich-text-editor-F04przIt.js → rich-text-editor-C3nANKZt.js} +2 -2
- package/dist/_chunks/{rich-text-editor-F04przIt.js.map → rich-text-editor-C3nANKZt.js.map} +1 -1
- package/dist/_chunks/{send-registration-link-form-DHCQpA4C.js → send-registration-link-form-Nn0jf65G.js} +3 -3
- package/dist/_chunks/{send-registration-link-form-DHCQpA4C.js.map → send-registration-link-form-Nn0jf65G.js.map} +1 -1
- package/dist/_chunks/{sign-document-B5qZhthO.js → sign-document-CQZVzfpk.js} +2 -2
- package/dist/_chunks/{sign-document-B5qZhthO.js.map → sign-document-CQZVzfpk.js.map} +1 -1
- package/dist/_chunks/{signature-request-DB6kePIm.js → signature-request-DtLph5Z4.js} +3 -3
- package/dist/_chunks/{signature-request-DB6kePIm.js.map → signature-request-DtLph5Z4.js.map} +1 -1
- package/dist/_chunks/{switch-D--x7n6h.js → switch-DO6uC4HJ.js} +40 -36
- package/dist/_chunks/switch-DO6uC4HJ.js.map +1 -0
- package/dist/_chunks/{task-editor-BiPGFXtB.js → task-editor-CmXcj6cC.js} +4 -4
- package/dist/_chunks/{task-editor-BiPGFXtB.js.map → task-editor-CmXcj6cC.js.map} +1 -1
- package/dist/_chunks/{tasks-panel-iVeuu9a8.js → tasks-panel-CFo5uIHx.js} +3 -3
- package/dist/_chunks/{tasks-panel-iVeuu9a8.js.map → tasks-panel-CFo5uIHx.js.map} +1 -1
- package/dist/_chunks/{theme-toggle-jZRbAidE.js → theme-toggle-Czq3K9jB.js} +2 -2
- package/dist/_chunks/{theme-toggle-jZRbAidE.js.map → theme-toggle-Czq3K9jB.js.map} +1 -1
- package/dist/_chunks/{time-picker-DSt-ns5F.js → time-picker-DDr5vhwQ.js} +344 -332
- package/dist/_chunks/time-picker-DDr5vhwQ.js.map +1 -0
- package/dist/_chunks/{tooth-scheme-Bd7xECuj.js → tooth-scheme-C-ALCHaV.js} +2 -2
- package/dist/_chunks/{tooth-scheme-Bd7xECuj.js.map → tooth-scheme-C-ALCHaV.js.map} +1 -1
- package/dist/_chunks/{use-appointment-details-read-CmqGGYCy.js → use-appointment-details-read-VI26Z-pc.js} +3 -3
- package/dist/_chunks/{use-appointment-details-read-CmqGGYCy.js.map → use-appointment-details-read-VI26Z-pc.js.map} +1 -1
- package/dist/_chunks/{voice-control-panel-BGJjUwnY.js → voice-control-panel-B0TUZAiP.js} +3 -3
- package/dist/_chunks/{voice-control-panel-BGJjUwnY.js.map → voice-control-panel-B0TUZAiP.js.map} +1 -1
- package/dist/_chunks/{warning-stack-3S7e2q07.js → warning-stack-Dx7cpj10.js} +2 -2
- package/dist/_chunks/{warning-stack-3S7e2q07.js.map → warning-stack-Dx7cpj10.js.map} +1 -1
- package/dist/_chunks/week-availability-CsTiwtYj.js +318 -0
- package/dist/_chunks/week-availability-CsTiwtYj.js.map +1 -0
- package/dist/_chunks/weekly-hours-editor-BsVsgeOc.js +252 -0
- package/dist/_chunks/weekly-hours-editor-BsVsgeOc.js.map +1 -0
- package/dist/_chunks/{workflow-map-B1jf6QaB.js → workflow-map-DWk-rZse.js} +2 -2
- package/dist/_chunks/{workflow-map-B1jf6QaB.js.map → workflow-map-DWk-rZse.js.map} +1 -1
- package/dist/_chunks/{workflow-webhook-action-B_52rH7O.js → workflow-webhook-action-DILFqAVd.js} +2 -2
- package/dist/_chunks/{workflow-webhook-action-B_52rH7O.js.map → workflow-webhook-action-DILFqAVd.js.map} +1 -1
- package/dist/ag-grid.css +5 -1
- package/dist/agent-catalog.json +1 -1
- package/dist/components/ai-credits-notice/index.js +1 -1
- package/dist/components/ai-permission-notice/index.js +1 -1
- package/dist/components/alert/alert.d.ts.map +1 -1
- package/dist/components/alert/index.js +1 -1
- package/dist/components/appointment-details-panel/index.js +1 -1
- package/dist/components/audio-recorder/index.js +1 -1
- package/dist/components/booking/index.js +1 -1
- package/dist/components/care-plan-card/index.js +1 -1
- package/dist/components/care-plan-entry-card/index.js +1 -1
- package/dist/components/contact-profile-card/contact-profile-card.d.ts +8 -0
- package/dist/components/contact-profile-card/contact-profile-card.d.ts.map +1 -1
- package/dist/components/contact-profile-card/index.js +1 -1
- package/dist/components/data-table/data-table.d.ts +6 -0
- package/dist/components/data-table/data-table.d.ts.map +1 -1
- package/dist/components/data-table/header-min-width.d.ts +21 -0
- package/dist/components/data-table/header-min-width.d.ts.map +1 -0
- package/dist/components/data-table/index.js +2 -2
- package/dist/components/date-range-picker/index.js +1 -1
- package/dist/components/date-time-picker/index.js +1 -1
- package/dist/components/document-preview/index.js +1 -1
- package/dist/components/document-scanner/index.js +1 -1
- package/dist/components/entity-summary/index.js +1 -1
- package/dist/components/error-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/freemium-paywall/index.js +1 -1
- package/dist/components/gestational-age-calculator/index.js +1 -1
- package/dist/components/hcg-doubling/index.js +1 -1
- package/dist/components/heatmap/heatmap.d.ts +5 -0
- package/dist/components/heatmap/heatmap.d.ts.map +1 -1
- package/dist/components/heatmap/index.js +1 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/info-tip/index.js +1 -1
- package/dist/components/info-tip/info-tip.d.ts +10 -0
- package/dist/components/info-tip/info-tip.d.ts.map +1 -1
- package/dist/components/notes-panel/index.js +1 -1
- package/dist/components/notice-group/index.js +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-form/index.js +1 -1
- package/dist/components/pdf-viewer/index.js +1 -1
- package/dist/components/practice-profile-hero/index.js +1 -1
- package/dist/components/practice-profile-hero/practice-profile-hero.d.ts +7 -0
- package/dist/components/practice-profile-hero/practice-profile-hero.d.ts.map +1 -1
- package/dist/components/practice-results/index.js +1 -1
- package/dist/components/practice-results/practice-results.d.ts +13 -0
- package/dist/components/practice-results/practice-results.d.ts.map +1 -1
- package/dist/components/pregnancy-dating/index.js +1 -1
- package/dist/components/progress-notice/index.js +1 -1
- package/dist/components/radiograph-panel/index.js +1 -1
- package/dist/components/reviews-panel/index.js +1 -1
- package/dist/components/reviews-panel/reviews-panel.d.ts +13 -0
- package/dist/components/reviews-panel/reviews-panel.d.ts.map +1 -1
- package/dist/components/rich-text-editor/index.js +2 -2
- package/dist/components/sign-document/index.js +1 -1
- package/dist/components/switch/index.js +1 -1
- package/dist/components/switch/switch.d.ts +2 -0
- package/dist/components/switch/switch.d.ts.map +1 -1
- package/dist/components/task-editor/index.js +1 -1
- package/dist/components/tasks-panel/index.js +1 -1
- package/dist/components/theme-toggle/index.js +1 -1
- package/dist/components/time-picker/index.js +1 -1
- package/dist/components/time-picker/time-picker.d.ts.map +1 -1
- package/dist/components/tooth-scheme/index.js +1 -1
- package/dist/components/voice-control-panel/index.js +1 -1
- package/dist/components/warning-stack/index.js +1 -1
- package/dist/components/week-availability/index.d.ts +3 -0
- package/dist/components/week-availability/index.d.ts.map +1 -0
- package/dist/components/week-availability/index.js +10 -0
- package/dist/components/week-availability/index.js.map +1 -0
- package/dist/components/week-availability/week-availability.d.ts +68 -0
- package/dist/components/week-availability/week-availability.d.ts.map +1 -0
- package/dist/components/weekly-hours-editor/index.d.ts +3 -0
- package/dist/components/weekly-hours-editor/index.d.ts.map +1 -0
- package/dist/components/weekly-hours-editor/index.js +9 -0
- package/dist/components/weekly-hours-editor/index.js.map +1 -0
- package/dist/components/weekly-hours-editor/weekly-hours-editor.d.ts +42 -0
- package/dist/components/weekly-hours-editor/weekly-hours-editor.d.ts.map +1 -0
- package/dist/components/workflow/index.js +1 -1
- package/dist/core.css +1 -1
- package/dist/i18n/locales/ar.d.ts +34 -0
- package/dist/i18n/locales/ar.d.ts.map +1 -1
- package/dist/i18n/locales/ar.js +34 -0
- package/dist/i18n/locales/ar.js.map +1 -1
- package/dist/i18n/locales/de.d.ts +34 -0
- package/dist/i18n/locales/de.d.ts.map +1 -1
- package/dist/i18n/locales/de.js +34 -0
- package/dist/i18n/locales/de.js.map +1 -1
- package/dist/i18n/locales/el.d.ts +34 -0
- package/dist/i18n/locales/el.d.ts.map +1 -1
- package/dist/i18n/locales/el.js +34 -0
- package/dist/i18n/locales/el.js.map +1 -1
- package/dist/i18n/locales/en.d.ts +34 -0
- package/dist/i18n/locales/en.d.ts.map +1 -1
- package/dist/i18n/locales/en.js +34 -0
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/es.d.ts +34 -0
- package/dist/i18n/locales/es.d.ts.map +1 -1
- package/dist/i18n/locales/es.js +34 -0
- package/dist/i18n/locales/es.js.map +1 -1
- package/dist/i18n/locales/fr.d.ts +34 -0
- package/dist/i18n/locales/fr.d.ts.map +1 -1
- package/dist/i18n/locales/fr.js +34 -0
- package/dist/i18n/locales/fr.js.map +1 -1
- package/dist/i18n/locales/hi.d.ts +34 -0
- package/dist/i18n/locales/hi.d.ts.map +1 -1
- package/dist/i18n/locales/hi.js +34 -0
- package/dist/i18n/locales/hi.js.map +1 -1
- package/dist/i18n/locales/it.d.ts +34 -0
- package/dist/i18n/locales/it.d.ts.map +1 -1
- package/dist/i18n/locales/it.js +34 -0
- package/dist/i18n/locales/it.js.map +1 -1
- package/dist/i18n/locales/ja.d.ts +34 -0
- package/dist/i18n/locales/ja.d.ts.map +1 -1
- package/dist/i18n/locales/ja.js +34 -0
- package/dist/i18n/locales/ja.js.map +1 -1
- package/dist/i18n/locales/nl.d.ts +34 -0
- package/dist/i18n/locales/nl.d.ts.map +1 -1
- package/dist/i18n/locales/nl.js +34 -0
- package/dist/i18n/locales/nl.js.map +1 -1
- package/dist/i18n/locales/pl.d.ts +34 -0
- package/dist/i18n/locales/pl.d.ts.map +1 -1
- package/dist/i18n/locales/pl.js +34 -0
- package/dist/i18n/locales/pl.js.map +1 -1
- package/dist/i18n/locales/pt.d.ts +34 -0
- package/dist/i18n/locales/pt.d.ts.map +1 -1
- package/dist/i18n/locales/pt.js +34 -0
- package/dist/i18n/locales/pt.js.map +1 -1
- package/dist/i18n/locales/ro.d.ts +34 -0
- package/dist/i18n/locales/ro.d.ts.map +1 -1
- package/dist/i18n/locales/ro.js +34 -0
- package/dist/i18n/locales/ro.js.map +1 -1
- package/dist/i18n/locales/ru.d.ts +34 -0
- package/dist/i18n/locales/ru.d.ts.map +1 -1
- package/dist/i18n/locales/ru.js +34 -0
- package/dist/i18n/locales/ru.js.map +1 -1
- package/dist/i18n/locales/sq.d.ts +34 -0
- package/dist/i18n/locales/sq.d.ts.map +1 -1
- package/dist/i18n/locales/sq.js +34 -0
- package/dist/i18n/locales/sq.js.map +1 -1
- package/dist/i18n/locales/sv.d.ts +34 -0
- package/dist/i18n/locales/sv.d.ts.map +1 -1
- package/dist/i18n/locales/sv.js +34 -0
- package/dist/i18n/locales/sv.js.map +1 -1
- package/dist/i18n/locales/tr.d.ts +34 -0
- package/dist/i18n/locales/tr.d.ts.map +1 -1
- package/dist/i18n/locales/tr.js +34 -0
- package/dist/i18n/locales/tr.js.map +1 -1
- package/dist/i18n/locales/zh.d.ts +34 -0
- package/dist/i18n/locales/zh.d.ts.map +1 -1
- package/dist/i18n/locales/zh.js +34 -0
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/index.js +879 -866
- package/dist/index.js.map +1 -1
- package/dist/locales/ar.json +34 -0
- package/dist/locales/de.json +34 -0
- package/dist/locales/el.json +34 -0
- package/dist/locales/en.json +34 -0
- package/dist/locales/es.json +34 -0
- package/dist/locales/fr.json +34 -0
- package/dist/locales/hi.json +34 -0
- package/dist/locales/it.json +34 -0
- package/dist/locales/ja.json +34 -0
- package/dist/locales/nl.json +34 -0
- package/dist/locales/pl.json +34 -0
- package/dist/locales/pt.json +34 -0
- package/dist/locales/ro.json +34 -0
- package/dist/locales/ru.json +34 -0
- package/dist/locales/sq.json +34 -0
- package/dist/locales/sv.json +34 -0
- package/dist/locales/tr.json +34 -0
- package/dist/locales/zh.json +34 -0
- 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 +2 -2
- package/dist/patterns/login-form/index.js +1 -1
- package/dist/patterns/marketplace-app-shell/index.js +1 -1
- package/dist/patterns/payment-automation-upsell/index.js +1 -1
- package/dist/patterns/registration-form/index.js +1 -1
- package/dist/patterns/reset-password-form/index.js +1 -1
- package/dist/patterns/send-registration-link-form/index.js +1 -1
- package/dist/patterns/signature-request/index.js +1 -1
- package/dist/patterns/workflow-webhook-action/index.js +1 -1
- package/dist/tokens.css +3 -1
- package/package.json +9 -1
- package/dist/_chunks/alert-9kEwDza3.js.map +0 -1
- package/dist/_chunks/contact-profile-card-uExd3pKC.js.map +0 -1
- package/dist/_chunks/data-table-C5uN4ato.js.map +0 -1
- package/dist/_chunks/info-tip-1Xsq9GLi.js +0 -230
- package/dist/_chunks/info-tip-1Xsq9GLi.js.map +0 -1
- package/dist/_chunks/practice-profile-hero-BAvGdQmt.js.map +0 -1
- package/dist/_chunks/practice-results-ChBP9x2r.js.map +0 -1
- package/dist/_chunks/reviews-panel-jPYgYvxG.js.map +0 -1
- package/dist/_chunks/switch-D--x7n6h.js.map +0 -1
- package/dist/_chunks/time-picker-DSt-ns5F.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"info-tip-C-MPkShR.js","sources":["../../src/components/info-tip/info-tip.agent.ts","../../src/components/info-tip/info-tip.tsx"],"sourcesContent":["import type { AgentAdapter } from '../../agent/types';\nimport type { InfoTipHandle } from './info-tip';\n\nexport const infoTipAgent: AgentAdapter<InfoTipHandle> = {\n id: 'info-tip',\n capabilities: ['open', 'close'],\n state: {\n isOpen: {\n type: 'boolean',\n descriptionKey: 'ui.agent.infoTip.state.isOpen',\n description: 'True when the info tip card is currently open.',\n read: (handle) => handle.getIsOpen(),\n },\n },\n actions: {\n open: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.infoTip.actions.open',\n description:\n 'Open the info tip card (including its formula and Learn more link, when set).',\n invoke: (handle) => {\n handle.open();\n },\n },\n close: {\n safety: 'read',\n idempotent: true,\n descriptionKey: 'ui.agent.infoTip.actions.close',\n description: 'Close the info tip card.',\n invoke: (handle) => {\n handle.close();\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'info-tip',\n description: 'Marks the InfoTip trigger button.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description: 'Sourced from the id prop on InfoTip.',\n },\n },\n};\n","import {\n forwardRef,\n useEffect,\n useMemo,\n useRef,\n useState,\n type MouseEvent as ReactMouseEvent,\n type ReactNode,\n} from 'react';\nimport { cva } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { Info } from 'lucide-react';\nimport { Popover } from '../popover';\nimport { Link } from '../link';\nimport { ScrollArea } from '../scroll-area';\nimport { composeRefs } from '../_shared/compose-refs';\nimport { useAgentRegistration } from '../../agent';\nimport { infoTipAgent } from './info-tip.agent';\n\n/* -------------------------------------------------------------------- */\n/* Trigger — a small circular, branded affordance: card surface inside */\n/* the circle, accent ring + accent \"i\" glyph, and a soft drop shadow. */\n/* The accent alias is safe here: `--accent` resolves to magenta-700 in */\n/* light mode (the AA-safe interactive step) and the dark accent on dark */\n/* surfaces — never reference a raw magenta ramp step. */\n/* -------------------------------------------------------------------- */\n\nconst infoTipTriggerVariants = cva(\n [\n 'ds:relative ds:inline-flex ds:shrink-0 ds:items-center ds:justify-center',\n 'ds:rounded-[var(--radius-full)]',\n 'ds:bg-[var(--card)]',\n 'ds:text-[var(--accent)]',\n // Single ring: the Lucide Info glyph draws its own accent circle, so the\n // trigger carries NO CSS border of its own (a border would read as a\n // second, concentric ring). The white circle comes from `bg-card` showing\n // through the glyph, lifted by the drop shadow.\n 'ds:shadow-[var(--shadow-sm)]',\n 'ds:cursor-pointer',\n 'ds:transition-[color,box-shadow] ds:motion-reduce:transition-none',\n 'ds:hover:text-[var(--accent-hover)] ds:hover:shadow-[var(--shadow-md)]',\n 'ds:data-[state=open]:text-[var(--accent-hover)] ds:data-[state=open]:shadow-[var(--shadow-md)]',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-ring ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:outline-[CanvasText]',\n ].join(' '),\n {\n variants: {\n size: {\n // Both diameters sit below `--min-target-size` (44/48px), so each\n // re-uses IconButton's invisible `::before` hit-area expansion to a\n // full touch target on touch / small screens. From the `sm:`\n // breakpoint up the pointer is precise, so the expansion relaxes —\n // but the interactive target must never fall below WCAG 2.5.8's 24px:\n // • md (24px visual) already meets the 24px floor, so its `::before`\n // is hidden on desktop and the 24px circle IS the target.\n // • sm (20px visual) would fall to 20px if hidden — below the floor\n // — so instead of hiding, its `::before` shrinks to a persistent\n // `--spacing-lg` (24px) minimum that holds on desktop too.\n sm: 'ds:w-5 ds:h-5 ds:before:absolute ds:before:inset-x-[calc((var(--min-target-size)-100%)/-2)] ds:before:inset-y-[calc((var(--min-target-size)-100%)/-2)] ds:before:content-[\"\"] ds:sm:before:inset-x-[calc((var(--spacing-lg)-100%)/-2)] ds:sm:before:inset-y-[calc((var(--spacing-lg)-100%)/-2)]',\n md: 'ds:w-6 ds:h-6 ds:before:absolute ds:before:inset-x-[calc((var(--min-target-size)-100%)/-2)] ds:before:inset-y-[calc((var(--min-target-size)-100%)/-2)] ds:before:content-[\"\"] ds:sm:before:hidden',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n },\n);\n\n// Curated agent-readiness handle — see info-tip.agent.ts.\nexport interface InfoTipHandle {\n getIsOpen: () => boolean;\n open: () => void;\n close: () => void;\n}\n\nexport interface InfoTipProps {\n /** Body of the tip — explanatory text shown in the floating card. */\n content: ReactNode;\n /** Optional heading rendered above the body. */\n heading?: ReactNode;\n /**\n * Trigger diameter. Also sets the floating card width unless `cardSize`\n * is given: `sm` → `--popover-size-sm`, `md` → `--popover-size-md`.\n */\n size?: 'sm' | 'md';\n /**\n * Width of the floating card, when it should differ from the trigger size:\n * `sm` → `--popover-size-sm`, `md` → `--popover-size-md`, `lg` →\n * `--popover-size-lg`. Defaults to the width that matches `size`, so a\n * small trigger can open a wider card for a longer explanation.\n */\n cardSize?: 'sm' | 'md' | 'lg';\n /** Logical side the card opens on. Default `'top'`. */\n side?: 'start' | 'top' | 'end' | 'bottom';\n /** Alignment along the side axis. Default `'center'`. */\n align?: 'start' | 'center' | 'end';\n /**\n * Accessible name for the trigger. Defaults to the translated\n * \"More information\" chrome string.\n */\n 'aria-label'?: string;\n /**\n * Opaque instance id — emitted as `data-component-id` on the trigger and\n * used to register the instance with the host agent registry.\n */\n id?: string;\n /** Extra classes merged onto the trigger button. */\n className?: string;\n /**\n * A formula written in words, shown below `content` in a quiet block, e.g.\n * \"Net revenue = invoices issued − credit notes\". It is part of the card's\n * description, so screen readers hear it.\n */\n formula?: ReactNode;\n /**\n * When set, the card gains a footer \"Learn more\" link to this URL and\n * becomes interactive: Tab from the open trigger moves to the link,\n * Shift+Tab returns, Escape closes and refocuses the trigger. Without it the\n * card is explanatory text and focus stays on the trigger, unless the text\n * is long enough to scroll: then Tab reaches the text so it can be scrolled.\n */\n learnMoreHref?: string;\n /**\n * Makes the card interactive: `content` may hold links or buttons (for\n * example a short list of links, use the kit `Link`). Tab from the open\n * trigger moves into the card, Shift+Tab from its first control returns,\n * Tab past its last closes the card and carries on after the trigger, and\n * Escape closes and refocuses the trigger. The card is named from\n * `heading` and its body is left out of `aria-describedby`, so links are\n * not read as flat text. Default `false`: the card stays explanatory.\n */\n interactive?: boolean;\n /** Link text. Defaults to the translated \"Learn more\" chrome string. */\n learnMoreLabel?: string;\n /**\n * Called when the link is activated. An SPA can call `event.preventDefault()`\n * and route client-side; the anchor keeps its real `href` either way.\n */\n onLearnMore?: (event: ReactMouseEvent<HTMLAnchorElement>) => void;\n}\n\nconst TABBABLE =\n 'a[href], button:not([disabled]), input:not([disabled]):not([type=\"hidden\"]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex=\"-1\"])';\n\nfunction firstTabbable(root: HTMLElement | null): HTMLElement | null {\n if (!root) return null;\n const all = root.querySelectorAll<HTMLElement>(TABBABLE);\n for (const el of all) {\n const style = getComputedStyle(el);\n if (!el.hidden && style.display !== 'none' && style.visibility !== 'hidden')\n return el;\n }\n return null;\n}\n\n// Interactive bodies stay out of the description: links read as flat text there.\nfunction BodyRegion({\n interactive,\n className,\n children,\n}: {\n interactive: boolean;\n className: string;\n children: ReactNode;\n}) {\n if (!interactive) {\n return (\n <Popover.Description className={className}>\n {children}\n </Popover.Description>\n );\n }\n return (\n <div\n className={`ds:text-[var(--muted-foreground)] type-body-sm ds:mt-[var(--spacing-xs)] ${className}`}\n >\n {children}\n </div>\n );\n}\n\n/**\n * InfoTip — a deliberate, branded \"more information\" affordance: a small\n * circular trigger that reveals an explanatory card on hover **and** click\n * (click also serves touch devices). Composes the kit Popover in\n * `openOn=\"hover-or-click\"` mode — hover intent, keyboard focus, Escape and\n * focus-return are all handled by the Popover/Radix layer.\n */\nexport const InfoTip = forwardRef<HTMLButtonElement, InfoTipProps>(\n (\n {\n content,\n heading,\n size = 'md',\n cardSize,\n side = 'top',\n align = 'center',\n 'aria-label': ariaLabelProp,\n id,\n className,\n formula,\n interactive = false,\n learnMoreHref,\n learnMoreLabel,\n onLearnMore,\n },\n ref,\n ) => {\n const { t } = useTranslation('ui');\n const [open, setOpen] = useState(false);\n\n // Agent handle.\n const openRef = useRef(open);\n useEffect(() => {\n openRef.current = open;\n }, [open]);\n\n const agentHandle = useMemo<InfoTipHandle>(\n () => ({\n getIsOpen: () => openRef.current,\n open: () => setOpen(true),\n close: () => setOpen(false),\n }),\n [],\n );\n useAgentRegistration(infoTipAgent, agentHandle, id);\n\n // Press bookkeeping. In hover-or-click mode the Popover opens as soon as\n // the trigger receives focus — which happens on pointerdown, BEFORE the\n // click event that Radix uses to toggle. Without intervention every\n // click/tap on a closed tip opens it (focus) and instantly toggles it\n // closed again (click). So each press (pointerdown, or Enter/Space)\n // snapshots the open state and the click handler consumes it: if the\n // press itself opened the card, swallow Radix's toggle so the card stays\n // open; if it was already open, let the toggle close it.\n //\n // `null` means \"no press recorded for this click\" — an orphan click\n // (programmatic .click(), or assistive tech dispatching click with no\n // pointer/key event). Those must fall through to Radix's default toggle\n // rather than read a stale snapshot, so the guard treats `null` as\n // \"don't suppress\" and every click clears the snapshot back to `null`.\n const pressStateRef = useRef<boolean | null>(null);\n const handlePressStart = () => {\n pressStateRef.current = openRef.current;\n };\n\n const hasLink = learnMoreHref != null;\n const triggerRef = useRef<HTMLButtonElement | null>(null);\n const composedTriggerRef = useMemo(\n () => composeRefs<HTMLButtonElement>(ref, triggerRef),\n [ref],\n );\n const linkRef = useRef<HTMLAnchorElement | null>(null);\n const contentRef = useRef<HTMLDivElement | null>(null);\n // A long tip is capped at the height the viewport leaves it and its text\n // scrolls in a ScrollArea, which is a tab stop only while it can scroll.\n const scrollRef = useRef<HTMLDivElement | null>(null);\n\n const ariaLabel =\n ariaLabelProp ?? t('infoTip.triggerLabel', 'More information');\n\n return (\n <Popover openOn=\"hover-or-click\" open={open} onOpenChange={setOpen}>\n <Popover.Trigger\n ref={composedTriggerRef}\n aria-label={ariaLabel}\n className={infoTipTriggerVariants({ size, className })}\n data-component=\"info-tip\"\n data-component-id={id}\n onPointerDown={handlePressStart}\n onKeyDown={(event) => {\n if (event.key === 'Enter' || event.key === ' ') {\n handlePressStart();\n }\n // The card is portalled, so native Tab order would skip it. Tab\n // from the open trigger goes to the scrolling text when it\n // overflows, otherwise straight to the link.\n const scroll = scrollRef.current;\n const scrollable = scroll?.tabIndex === 0;\n const next = scrollable\n ? scroll\n : interactive\n ? firstTabbable(contentRef.current)\n : linkRef.current;\n if (\n (hasLink || scrollable || interactive) &&\n event.key === 'Tab' &&\n !event.shiftKey &&\n openRef.current &&\n next\n ) {\n event.preventDefault();\n next.focus();\n }\n }}\n onClick={(event) => {\n // Consume this click's press snapshot. A genuine pointer/keyboard\n // press recorded `false`/`true` on press-start; an orphan click\n // with no preceding pointerdown/keydown finds `null` and is left\n // to Radix's default toggle.\n const wasOpenAtPressStart = pressStateRef.current;\n pressStateRef.current = null;\n if (wasOpenAtPressStart === false && openRef.current) {\n // This press opened the card via focus — keep it open and\n // skip Radix's click toggle.\n event.preventDefault();\n }\n }}\n >\n <Info\n aria-hidden=\"true\"\n // Fills the circle so the glyph's own ring IS the trigger's\n // visible edge and the drop shadow hugs it.\n className={size === 'sm' ? 'ds:size-5' : 'ds:size-6'}\n />\n </Popover.Trigger>\n <Popover.Content\n ref={contentRef}\n side={side}\n align={align}\n size={cardSize ?? (size === 'sm' ? 'sm' : 'md')}\n // Never taller than the space the viewport leaves; the text scrolls.\n // The card itself does not clip, so its arrow stays visible.\n className={[\n 'ds:flex ds:flex-col ds:max-h-[var(--radix-popover-content-available-height)]',\n // Links and buttons reach the touch target on small screens.\n interactive &&\n 'ds:max-sm:[&_a]:inline-flex ds:max-sm:[&_a]:items-center ds:max-sm:[&_a]:min-block-[var(--min-target-size)]',\n ]\n .filter(Boolean)\n .join(' ')}\n // The card is a Radix `role=\"dialog\"` surface, which axe requires\n // to have an accessible name (aria-dialog-name). With a heading,\n // Popover wires aria-labelledby; without one, fall back to the\n // trigger's label.\n aria-label={heading == null ? ariaLabel : undefined}\n // Toggletip focus contract: the card is explanatory text, never\n // interactive, so focus stays on the trigger for the whole\n // open/close cycle. Preventing the open move also keeps Escape\n // reliable — if Radix pulled focus into the card, closing would\n // refocus the trigger and re-fire the hover-mode focus handler,\n // reopening the card it just closed. Preventing the close move\n // keeps an unhover-close from stealing focus mid-task.\n //\n // With a learn-more link, or text long enough to scroll, the card\n // is interactive, but the same contract holds: focus is never\n // pulled in on open, only Tab moves it to the text or the link. Escape from inside the card is handled below so\n // focus returns to the trigger without re-firing its focus-open.\n onOpenAutoFocus={(event) => event.preventDefault()}\n onCloseAutoFocus={(event) => event.preventDefault()}\n onEscapeKeyDown={(event) => {\n // Focus anywhere inside the card (the link, or the card itself\n // after a click on its text) goes back to the trigger.\n const active = document.activeElement;\n if (active && contentRef.current?.contains(active)) {\n event.preventDefault();\n triggerRef.current?.focus();\n setOpen(false);\n }\n }}\n >\n {heading != null && <Popover.Heading>{heading}</Popover.Heading>}\n <BodyRegion\n interactive={interactive}\n className=\"ds:flex ds:min-h-0 ds:flex-col\"\n >\n <ScrollArea\n ref={scrollRef}\n type=\"native\"\n aria-label={typeof heading === 'string' ? heading : ariaLabel}\n // At high zoom the heading and link keep their height; the text\n // keeps at least three lines rather than collapsing to nothing.\n className=\"ds:min-h-[3lh]\"\n >\n {content}\n {formula != null && (\n <div\n data-slot=\"formula\"\n className=\"type-body-sm ds:mt-[var(--spacing-sm)] ds:rounded-[var(--radius-sm)] ds:bg-[var(--muted)] ds:px-[var(--spacing-sm)] ds:py-[var(--spacing-xs)] ds:text-[var(--foreground)] ds:tabular-nums\"\n >\n <span className=\"ds:sr-only\">\n {t('infoTip.formula', 'Formula')}:{' '}\n </span>\n {formula}\n </div>\n )}\n </ScrollArea>\n </BodyRegion>\n {hasLink && (\n <div\n data-slot=\"footer\"\n className=\"ds:mt-[var(--spacing-sm)] ds:flex ds:justify-end\"\n >\n <Link\n ref={linkRef}\n href={learnMoreHref}\n onClick={onLearnMore}\n weight=\"strong\"\n className=\"type-body-sm\"\n >\n {learnMoreLabel ?? t('infoTip.learnMore', 'Learn more')}\n </Link>\n </div>\n )}\n </Popover.Content>\n </Popover>\n );\n },\n);\n\nInfoTip.displayName = 'InfoTip';\n"],"names":["infoTipAgent","handle","infoTipTriggerVariants","cva","TABBABLE","firstTabbable","root","all","el","style","BodyRegion","interactive","className","children","jsx","Popover","InfoTip","forwardRef","content","heading","size","cardSize","side","align","ariaLabelProp","id","formula","learnMoreHref","learnMoreLabel","onLearnMore","ref","t","useTranslation","open","setOpen","useState","openRef","useRef","useEffect","agentHandle","useMemo","useAgentRegistration","pressStateRef","handlePressStart","hasLink","triggerRef","composedTriggerRef","composeRefs","linkRef","contentRef","scrollRef","ariaLabel","event","scroll","scrollable","next","wasOpenAtPressStart","Info","jsxs","active","_a","_b","ScrollArea","Link"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createElement as e } from "react";
|
|
2
|
-
import { P as i } from "./pregnancy-dating-
|
|
2
|
+
import { P as i } from "./pregnancy-dating-D6dLkMpl.js";
|
|
3
3
|
import { P as o } from "./pregnancy-weight-gain-B_Zldlzq.js";
|
|
4
|
-
import { G as r } from "./gestational-age-calculator-
|
|
4
|
+
import { G as r } from "./gestational-age-calculator-AnaH00nk.js";
|
|
5
5
|
import { C as c } from "./cycle-calculator-ZMDvToIm.js";
|
|
6
6
|
import { F as s } from "./fetal-weight-CkIwJgiH.js";
|
|
7
7
|
import { c as a } from "./createLucideIcon-DhHxpK9K.js";
|
|
@@ -91,4 +91,4 @@ const k = [
|
|
|
91
91
|
export {
|
|
92
92
|
I as k
|
|
93
93
|
};
|
|
94
|
-
//# sourceMappingURL=kit-extensions-
|
|
94
|
+
//# sourceMappingURL=kit-extensions-BOnTM4Yf.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kit-extensions-
|
|
1
|
+
{"version":3,"file":"kit-extensions-BOnTM4Yf.js","sources":["../../node_modules/lucide-react/dist/esm/icons/calendar-heart.mjs","../../node_modules/lucide-react/dist/esm/icons/scale.mjs","../../src/components/rich-text-editor/kit-extensions.ts"],"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 [\n \"path\",\n { d: \"M12.127 22H5a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2v5.125\", key: \"vxdnp4\" }\n ],\n [\n \"path\",\n {\n d: \"M14.62 18.8A2.25 2.25 0 1 1 18 15.836a2.25 2.25 0 1 1 3.38 2.966l-2.626 2.856a.998.998 0 0 1-1.507 0z\",\n key: \"15cy7q\"\n }\n ],\n [\"path\", { d: \"M16 2v4\", key: \"4m81vk\" }],\n [\"path\", { d: \"M3 10h18\", key: \"8toen8\" }],\n [\"path\", { d: \"M8 2v4\", key: \"1cmpym\" }]\n];\nconst CalendarHeart = createLucideIcon(\"calendar-heart\", __iconNode);\n\nexport { __iconNode, CalendarHeart as default };\n//# sourceMappingURL=calendar-heart.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 [\"path\", { d: \"M12 3v18\", key: \"108xh3\" }],\n [\"path\", { d: \"m19 8 3 8a5 5 0 0 1-6 0zV7\", key: \"zcdpyk\" }],\n [\"path\", { d: \"M3 7h1a17 17 0 0 0 8-2 17 17 0 0 0 8 2h1\", key: \"1yorad\" }],\n [\"path\", { d: \"m5 8 3 8a5 5 0 0 1-6 0zV7\", key: \"eua70x\" }],\n [\"path\", { d: \"M7 21h10\", key: \"1b0cd5\" }]\n];\nconst Scale = createLucideIcon(\"scale\", __iconNode);\n\nexport { __iconNode, Scale as default };\n//# sourceMappingURL=scale.mjs.map\n","import { createElement } from 'react';\nimport { Baby, CalendarHeart, Heart, Scale } from 'lucide-react';\nimport { PregnancyDating } from '../pregnancy-dating';\nimport { PregnancyWeightGain } from '../pregnancy-weight-gain';\nimport { GestationalAgeCalculator } from '../gestational-age-calculator';\nimport { CycleCalculator } from '../cycle-calculator';\nimport { FetalWeight } from '../fetal-weight';\nimport type { EditorExtension } from './editor-extensions';\n\n/** Labels are resolved by the editor's useTranslation, including live locale changes. */\nexport const kitEditorExtensions: EditorExtension[] = [\n {\n id: 'pregnancy-dating',\n label: 'insert.title.pregnancyDating',\n icon: createElement(CalendarHeart),\n kind: 'panel',\n contexts: ['note', 'diagnosis'],\n source: { kind: 'kit' },\n render: ({ insert }) =>\n createElement(PregnancyDating, { onInsert: insert }),\n },\n {\n id: 'pregnancy-weight-gain',\n label: 'insert.title.weightGain',\n icon: createElement(Baby),\n kind: 'panel',\n contexts: ['note', 'diagnosis'],\n source: { kind: 'kit' },\n render: ({ insert }) =>\n createElement(PregnancyWeightGain, { onInsert: insert }),\n },\n {\n id: 'gestational-age-calculator',\n label: 'insert.title.gestationalAge',\n icon: createElement(Baby),\n kind: 'panel',\n contexts: ['note', 'diagnosis'],\n source: { kind: 'kit' },\n render: ({ insert }) =>\n createElement(GestationalAgeCalculator, { onInsert: insert }),\n },\n {\n id: 'cycle-calculator',\n label: 'insert.title.cycle',\n icon: createElement(Heart),\n kind: 'panel',\n contexts: ['note', 'diagnosis'],\n source: { kind: 'kit' },\n render: ({ insert }) =>\n createElement(CycleCalculator, { onInsert: insert }),\n },\n {\n id: 'fetal-weight',\n label: 'insert.title.fetalWeight',\n icon: createElement(Scale),\n kind: 'panel',\n contexts: ['note', 'diagnosis'],\n source: { kind: 'kit' },\n render: ({ insert }) => createElement(FetalWeight, { onInsert: insert }),\n },\n];\n"],"names":["__iconNode","CalendarHeart","createLucideIcon","Scale","kitEditorExtensions","createElement","insert","PregnancyDating","Baby","PregnancyWeightGain","GestationalAgeCalculator","Heart","CycleCalculator","FetalWeight"],"mappings":";;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,MAAMA,IAAa;AAAA,EACjB;AAAA,IACE;AAAA,IACA,EAAE,GAAG,qEAAqE,KAAK,SAAQ;AAAA,EAC3F;AAAA,EACE;AAAA,IACE;AAAA,IACA;AAAA,MACE,GAAG;AAAA,MACH,KAAK;AAAA,IACX;AAAA,EACA;AAAA,EACE,CAAC,QAAQ,EAAE,GAAG,WAAW,KAAK,SAAQ,CAAE;AAAA,EACxC,CAAC,QAAQ,EAAE,GAAG,YAAY,KAAK,SAAQ,CAAE;AAAA,EACzC,CAAC,QAAQ,EAAE,GAAG,UAAU,KAAK,SAAQ,CAAE;AACzC,GACMC,IAAgBC,EAAiB,kBAAkBF,CAAU;ACzBnE;AAAA;AAAA;AAAA;AAAA;AAAA;AASA,MAAMA,IAAa;AAAA,EACjB,CAAC,QAAQ,EAAE,GAAG,YAAY,KAAK,SAAQ,CAAE;AAAA,EACzC,CAAC,QAAQ,EAAE,GAAG,8BAA8B,KAAK,SAAQ,CAAE;AAAA,EAC3D,CAAC,QAAQ,EAAE,GAAG,4CAA4C,KAAK,SAAQ,CAAE;AAAA,EACzE,CAAC,QAAQ,EAAE,GAAG,6BAA6B,KAAK,SAAQ,CAAE;AAAA,EAC1D,CAAC,QAAQ,EAAE,GAAG,YAAY,KAAK,SAAQ,CAAE;AAC3C,GACMG,IAAQD,EAAiB,SAASF,CAAU,GCNrCI,IAAyC;AAAA,EACpD;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,MAAMC,EAAcJ,CAAa;AAAA,IACjC,MAAM;AAAA,IACN,UAAU,CAAC,QAAQ,WAAW;AAAA,IAC9B,QAAQ,EAAE,MAAM,MAAA;AAAA,IAChB,QAAQ,CAAC,EAAE,QAAAK,EAAA,MACTD,EAAcE,GAAiB,EAAE,UAAUD,EAAA,CAAQ;AAAA,EAAA;AAAA,EAEvD;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,MAAMD,EAAcG,CAAI;AAAA,IACxB,MAAM;AAAA,IACN,UAAU,CAAC,QAAQ,WAAW;AAAA,IAC9B,QAAQ,EAAE,MAAM,MAAA;AAAA,IAChB,QAAQ,CAAC,EAAE,QAAAF,EAAA,MACTD,EAAcI,GAAqB,EAAE,UAAUH,EAAA,CAAQ;AAAA,EAAA;AAAA,EAE3D;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,MAAMD,EAAcG,CAAI;AAAA,IACxB,MAAM;AAAA,IACN,UAAU,CAAC,QAAQ,WAAW;AAAA,IAC9B,QAAQ,EAAE,MAAM,MAAA;AAAA,IAChB,QAAQ,CAAC,EAAE,QAAAF,EAAA,MACTD,EAAcK,GAA0B,EAAE,UAAUJ,EAAA,CAAQ;AAAA,EAAA;AAAA,EAEhE;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,MAAMD,EAAcM,CAAK;AAAA,IACzB,MAAM;AAAA,IACN,UAAU,CAAC,QAAQ,WAAW;AAAA,IAC9B,QAAQ,EAAE,MAAM,MAAA;AAAA,IAChB,QAAQ,CAAC,EAAE,QAAAL,EAAA,MACTD,EAAcO,GAAiB,EAAE,UAAUN,EAAA,CAAQ;AAAA,EAAA;AAAA,EAEvD;AAAA,IACE,IAAI;AAAA,IACJ,OAAO;AAAA,IACP,MAAMD,EAAcF,CAAK;AAAA,IACzB,MAAM;AAAA,IACN,UAAU,CAAC,QAAQ,WAAW;AAAA,IAC9B,QAAQ,EAAE,MAAM,MAAA;AAAA,IAChB,QAAQ,CAAC,EAAE,QAAAG,EAAA,MAAaD,EAAcQ,GAAa,EAAE,UAAUP,EAAA,CAAQ;AAAA,EAAA;AAE3E;","x_google_ignoreList":[0,1]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as u, jsxs as R } from "react/jsx-runtime";
|
|
2
2
|
import { useState as x, useEffect as w, useCallback as W, useMemo as E, useRef as ee } from "react";
|
|
3
3
|
import { useGridFilter as V } from "ag-grid-react";
|
|
4
|
-
import { D as te } from "./date-range-picker-
|
|
4
|
+
import { D as te } from "./date-range-picker-DCADIR8o.js";
|
|
5
5
|
import { useTranslation as M } from "react-i18next";
|
|
6
6
|
import { C as le } from "./checkbox-a7Sh-dXb.js";
|
|
7
7
|
import { B as j } from "./button-DohK_Ak_.js";
|
|
@@ -864,4 +864,4 @@ export {
|
|
|
864
864
|
Ke as g,
|
|
865
865
|
k as h
|
|
866
866
|
};
|
|
867
|
-
//# sourceMappingURL=link-cell-renderer-
|
|
867
|
+
//# sourceMappingURL=link-cell-renderer-C8vfCOEp.js.map
|
package/dist/_chunks/{link-cell-renderer-BRek9kz7.js.map → link-cell-renderer-C8vfCOEp.js.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"link-cell-renderer-BRek9kz7.js","sources":["../../src/components/data-table/calendar-day.ts","../../src/components/data-table/filters/date-range-filter.tsx","../../src/components/data-table/filters/select-filter.tsx","../../src/components/data-table/filters/typeahead-filter.tsx","../../src/components/data-table/filters/number-filter.tsx","../../src/components/data-table/cell-renderers/status-cell-renderer.tsx","../../src/components/data-table/cell-renderers/user-cell-renderer.tsx","../../src/components/data-table/cell-renderers/image-cell-renderer.tsx","../../src/components/data-table/cell-renderers/tag-list-cell-renderer.tsx","../../src/components/data-table/cell-renderers/date-cell-renderer.tsx","../../src/components/data-table/cell-renderers/link-cell-renderer.tsx"],"sourcesContent":["/**\n * Calendar-day helpers, shared by the date filter and the date cell renderer.\n *\n * A calendar day is not an instant. `new Date('2008-09-06')` is UTC midnight,\n * which every local getter then reads back shifted: west of UTC it is the 5th.\n * Everything here works in local date parts so a day stays the day it was\n * written with, whatever zone the browser is in.\n */\n\nconst DATE_ONLY = /^\\d{4}-\\d{2}-\\d{2}$/;\nconst ISO_DAY_PREFIX = /^(\\d{4}-\\d{2}-\\d{2})/;\n\n/**\n * A `Date` as `YYYY-MM-DD`, read off the LOCAL date parts — `toISOString()`\n * would shift a local midnight to the previous day anywhere east of UTC.\n */\nexport function toIsoDate(d: Date | undefined): string | null {\n if (!d) return null;\n const y = d.getFullYear();\n const m = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n return `${y}-${m}-${day}`;\n}\n\n/** Whether a value is a bare `YYYY-MM-DD` — a calendar day, carrying no instant. */\nexport function isCalendarDay(s: unknown): s is string {\n return typeof s === 'string' && DATE_ONLY.test(s);\n}\n\n/** A bare day parses as LOCAL midnight; anything with a time/offset as-is. */\nexport function fromIsoDate(s: string | null | undefined): Date | undefined {\n if (!s) return undefined;\n const d = DATE_ONLY.test(s)\n ? new Date(\n Number(s.slice(0, 4)),\n Number(s.slice(5, 7)) - 1,\n Number(s.slice(8, 10)),\n )\n : new Date(s);\n return Number.isNaN(d.getTime()) ? undefined : d;\n}\n\n/**\n * The calendar day a cell value stands for, as `YYYY-MM-DD`.\n *\n * An ISO string is read as the day it was WRITTEN with — `2026-04-15T17:32+02:00`\n * is the 15th and `1933-04-04T00:00+01:00` the 4th, whatever zone the browser\n * is in. Anything else is parsed and read off its local parts.\n */\nexport function dayOf(cellValue: unknown): string | null {\n if (cellValue === null || cellValue === undefined || cellValue === '')\n return null;\n if (typeof cellValue === 'string') {\n const prefix = ISO_DAY_PREFIX.exec(cellValue);\n if (prefix) return prefix[1];\n }\n const d = cellValue instanceof Date ? cellValue : new Date(String(cellValue));\n return Number.isNaN(d.getTime()) ? null : toIsoDate(d);\n}\n","import { useEffect, useState } from 'react';\nimport type {\n CustomFilterProps,\n CustomFloatingFilterProps,\n} from 'ag-grid-react';\nimport { useGridFilter } from 'ag-grid-react';\nimport type { IFilter } from 'ag-grid-community';\nimport { DateRangePicker } from '../../date-range-picker';\nimport type { DateRangeValue } from '../../date-range-picker';\n// Calendar-day handling lives in one place: the date cell renderer needs the\n// same rules and must not import from a filter to get them.\nimport { dayOf, fromIsoDate, toIsoDate } from '../calendar-day';\n\nexport { dayOf, fromIsoDate, toIsoDate };\n\n/**\n * Custom AG Grid filter component for date *ranges*. AG Grid Community's\n * built-in `agDateColumnFilter` only handles single-date comparison —\n * platform needs \"between X and Y\" for invoice / transaction lists.\n *\n * Wire on a colDef:\n * ```tsx\n * { field: 'date', filter: DateRangeFilter }\n * ```\n *\n * The filter model has shape `{ type: 'inRange', dateFrom, dateTo }` to\n * stay close to AG Grid's own date-filter convention so server-side\n * adapters can interpret it the same way.\n */\nexport interface DateRangeFilterModel {\n type: 'inRange';\n dateFrom: string | null;\n dateTo: string | null;\n}\n\n/**\n * `filterParams` a colDef may pass to `DateRangeFilter` /\n * `DateRangeFloatingFilter`.\n *\n * `commitMode` is forwarded to the wrapped `DateRangePicker`. Leave it unset\n * (picker default `'auto'`, commit-on-complete-range) for cheap client-side row\n * models; set `'apply'` for SERVER-side row models so each range edit defers to\n * one Apply and fires a single datasource round-trip instead of one per commit.\n */\nexport interface DateRangeFilterParams {\n placeholder?: string;\n commitMode?: 'auto' | 'apply';\n}\n\n/** Whether a cell's day lies within `[dateFrom, dateTo]` (either end open). */\nexport function dayInRange(\n cellValue: unknown,\n dateFrom: string | null | undefined,\n dateTo: string | null | undefined,\n): boolean {\n if (!dateFrom && !dateTo) return true;\n const day = dayOf(cellValue);\n if (!day) return false;\n if (dateFrom && day < dateFrom) return false;\n if (dateTo && day > dateTo) return false;\n return true;\n}\n\nexport function DateRangeFilter(\n props: CustomFilterProps<unknown, unknown, DateRangeFilterModel>,\n) {\n const { model, onModelChange, getValue, doesRowPassOtherFilter } = props;\n const filterParams =\n (props.colDef?.filterParams as DateRangeFilterParams | undefined) ?? {};\n // Picker UI state, seeded from the model and kept in sync when the model\n // changes externally — a programmatic default (e.g. \"this week\"), a server\n // restore, or an AG Grid reset. Mirrors `SelectFilter`'s `pending` sync.\n const [range, setRange] = useState<DateRangeValue>(() => ({\n from: fromIsoDate(model?.dateFrom),\n to: fromIsoDate(model?.dateTo),\n }));\n useEffect(() => {\n setRange({\n from: fromIsoDate(model?.dateFrom),\n to: fromIsoDate(model?.dateTo),\n });\n }, [model?.dateFrom, model?.dateTo]);\n\n // Tell AG Grid how to evaluate a row against the current model. AG Grid\n // calls this for each row; we read the cell value via `getValue(node)`\n // (a Date or ISO string), compare to the bounds. Bounds come from the\n // MODEL (the source of truth) — not the picker state — so a model set\n // programmatically applies even before the picker UI has mounted, exactly\n // as `SelectFilter` reads `model.values` directly.\n useGridFilter({\n doesFilterPass: (params) => {\n void doesRowPassOtherFilter;\n return dayInRange(getValue(params.node), model?.dateFrom, model?.dateTo);\n },\n });\n\n function apply(next: DateRangeValue) {\n setRange(next);\n if (!next.from && !next.to) {\n onModelChange(null);\n return;\n }\n onModelChange({\n type: 'inRange',\n dateFrom: toIsoDate(next.from),\n dateTo: toIsoDate(next.to),\n } satisfies DateRangeFilterModel);\n }\n\n return (\n <div\n data-component=\"date-range-filter\"\n className=\"ds:p-[var(--spacing-sm)] ds:min-w-[280px]\"\n >\n <DateRangePicker\n value={range}\n onChange={apply}\n commitMode={filterParams.commitMode}\n size=\"sm\"\n // A column filter has no room for the two-month rail-and-title layout.\n compact\n />\n </div>\n );\n}\n\n/**\n * Floating-filter companion for `DateRangeFilter`.\n *\n * Renders the kit's `<DateRangePicker>` directly as the floating-filter\n * input — its built-in trigger button + calendar popover IS the filter\n * UI. Earlier versions wrapped the picker in a second `<Popover>`,\n * producing the \"click → empty popover with another trigger → click\n * again → calendar\" double-step that read as duplicated UI.\n */\nexport function DateRangeFloatingFilter(\n props: CustomFloatingFilterProps<\n IFilter,\n unknown,\n unknown,\n DateRangeFilterModel\n >,\n) {\n const { model, onModelChange, column } = props;\n // Let a colDef supply a short `filterParams.placeholder` for the in-row\n // trigger — the default \"Select date range\" is long for a narrow filter\n // column. (The label truncates cleanly either way; a short placeholder just\n // reads better.)\n const filterParams =\n (column?.getColDef?.()?.filterParams as\n | DateRangeFilterParams\n | undefined) ?? {};\n const [range, setRange] = useState<DateRangeValue>(() => ({\n from: fromIsoDate(model?.dateFrom),\n to: fromIsoDate(model?.dateTo),\n }));\n // Reflect external model changes (a programmatic default, a parent-filter\n // edit, an AG Grid reset) in the in-row picker trigger.\n useEffect(() => {\n setRange({\n from: fromIsoDate(model?.dateFrom),\n to: fromIsoDate(model?.dateTo),\n });\n }, [model?.dateFrom, model?.dateTo]);\n\n function apply(next: DateRangeValue) {\n setRange(next);\n if (!next.from && !next.to) {\n onModelChange(null);\n return;\n }\n onModelChange({\n type: 'inRange',\n dateFrom: toIsoDate(next.from),\n dateTo: toIsoDate(next.to),\n } satisfies DateRangeFilterModel);\n }\n\n return (\n <div data-component=\"date-range-floating-filter\" className=\"ds:w-full\">\n <DateRangePicker\n value={range}\n onChange={apply}\n commitMode={filterParams.commitMode}\n size=\"sm\"\n placeholder={filterParams.placeholder}\n // A column filter has no room for the two-month rail-and-title layout.\n compact\n />\n </div>\n );\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type {\n CustomFilterProps,\n CustomFloatingFilterProps,\n} from 'ag-grid-react';\nimport { useGridFilter } from 'ag-grid-react';\nimport type { GridApi, IFilter, IRowNode } from 'ag-grid-community';\nimport { useTranslation } from 'react-i18next';\nimport { Checkbox } from '../../checkbox';\nimport { Button } from '../../button';\nimport { MultiSelect } from '../../multi-select';\nimport { ScrollArea } from '../../scroll-area/scroll-area';\n\n/**\n * Custom AG Grid filter component — multi-select facet filter.\n *\n * The Community-friendly equivalent of AG Grid Enterprise's\n * `agSetColumnFilter`. Surfaces a checkbox list of every value the column\n * can take, so users tick to include / untick to exclude. Much faster than\n * the default `agTextColumnFilter` for closed enums (status, room,\n * operator).\n *\n * Wire on a colDef:\n * ```tsx\n * {\n * field: 'status',\n * filter: SelectFilter,\n * filterParams: {\n * options: [\n * { value: 'open', label: 'Aperte' },\n * { value: 'paid', label: 'Pagate' },\n * ],\n * },\n * }\n * ```\n *\n * Model shape `{ type: 'set', values: Array<string | number> }` matches\n * AG Grid Enterprise's set-filter convention so server-side adapters can\n * read either implementation the same way.\n */\n\nexport interface SelectFilterOption {\n value: string | number;\n label: string;\n}\n\nexport interface SelectFilterModel {\n type: 'set';\n values: Array<string | number>;\n}\n\nexport interface SelectFilterParams {\n options?: SelectFilterOption[];\n placeholder?: string;\n}\n\ntype SelectFilterValue = string | number;\n\nfunction toValueKey(v: SelectFilterValue): string {\n return typeof v === 'number' ? `n:${v}` : `s:${v}`;\n}\n\n/** How a filter surface reads one row's value for its column. */\ntype SelectValueReader = (node: IRowNode) => unknown;\n\n/** Numeric collation, so a derived numeric column lists 1, 2, 3, 10 rather\n * than the lexicographic 1, 10, 2, 3. */\nconst LABEL_COLLATOR = new Intl.Collator(undefined, { numeric: true });\n\n/** Distinct values the column actually holds, label-sorted. `forEachNode`\n * walks the whole client-side row model, so the list does not shrink as\n * other columns filter rows out. */\nfunction collectColumnOptions(\n api: GridApi | undefined,\n readValue: SelectValueReader,\n): SelectFilterOption[] {\n if (!api) return [];\n const seen = new Map<string, SelectFilterOption>();\n api.forEachNode((node: IRowNode) => {\n const raw = readValue(node);\n if (raw === null || raw === undefined) return;\n const value =\n typeof raw === 'string' || typeof raw === 'number' ? raw : String(raw);\n const key = toValueKey(value);\n if (!seen.has(key)) seen.set(key, { value, label: String(value) });\n });\n return Array.from(seen.values()).sort((a, b) =>\n LABEL_COLLATOR.compare(String(a.label), String(b.label)),\n );\n}\n\nfunction sameOptions(\n a: SelectFilterOption[],\n b: SelectFilterOption[],\n): boolean {\n if (a.length !== b.length) return false;\n return a.every(\n (opt, i) =>\n toValueKey(opt.value) === toValueKey(b[i].value) &&\n opt.label === b[i].label,\n );\n}\n\n/**\n * The universe of choices for one Select-filtered column.\n *\n * An explicit `options` filterParam always wins — INCLUDING an empty one,\n * which means \"this column has no facets\", not \"derive them for me\". Omit\n * `options` entirely and the list is DERIVED from the values the column\n * actually holds, and re-derived as the row data changes, so both the popup\n * panel and its floating-filter twin offer the same, data-accurate choices.\n */\nfunction useSelectFilterOptions(\n api: GridApi | undefined,\n options: SelectFilterOption[] | undefined,\n readValue: SelectValueReader,\n): SelectFilterOption[] {\n const explicit = options;\n const hasExplicit = explicit !== undefined;\n const [derived, setDerived] = useState<SelectFilterOption[]>([]);\n\n // Latest-reader ref so a new `getValue` identity per grid render does not\n // tear down and rebuild the grid event subscription below.\n const readValueRef = useRef(readValue);\n useEffect(() => {\n readValueRef.current = readValue;\n });\n\n useEffect(() => {\n if (hasExplicit || !api) return;\n const recompute = () => {\n setDerived((prev) => {\n const next = collectColumnOptions(api, readValueRef.current);\n return sameOptions(prev, next) ? prev : next;\n });\n };\n recompute();\n api.addEventListener('modelUpdated', recompute);\n api.addEventListener('cellValueChanged', recompute);\n return () => {\n if (api.isDestroyed()) return;\n api.removeEventListener('modelUpdated', recompute);\n api.removeEventListener('cellValueChanged', recompute);\n };\n }, [api, hasExplicit]);\n\n return explicit ?? derived;\n}\n\nexport function SelectFilter(\n props: CustomFilterProps<unknown, unknown, SelectFilterModel> &\n SelectFilterParams,\n) {\n const { model, onModelChange, getValue, api, options, placeholder } = props;\n const { t } = useTranslation('ui');\n\n const readValue = useCallback<SelectValueReader>(\n (node) => getValue(node) as unknown,\n [getValue],\n );\n const derivedOptions = useSelectFilterOptions(api, options, readValue);\n\n // Working set — checkboxes mutate `pending` only; we commit to the\n // grid via `onModelChange` when the user clicks Apply (or clears).\n const initialSelected = useMemo<Set<string>>(() => {\n const set = new Set<string>();\n const incoming = model?.values ?? [];\n for (const v of incoming) set.add(toValueKey(v));\n return set;\n }, [model]);\n\n const [pending, setPending] = useState<Set<string>>(initialSelected);\n\n // Sync local `pending` if the model changes externally (e.g. when AG\n // Grid pushes a reset). `model` is the dependency — Set instances are\n // compared by reference in React, so the memo above is sufficient.\n useEffect(() => {\n setPending(initialSelected);\n }, [initialSelected]);\n\n useGridFilter({\n doesFilterPass: (params) => {\n const active = model?.values;\n if (!active || active.length === 0) return true;\n const raw = getValue(params.node) as unknown;\n if (raw === null || raw === undefined) return false;\n const value: SelectFilterValue =\n typeof raw === 'string' || typeof raw === 'number' ? raw : String(raw);\n const key = toValueKey(value);\n return active.some((v) => toValueKey(v) === key);\n },\n });\n\n function toggle(optionKey: string) {\n setPending((prev) => {\n const next = new Set(prev);\n if (next.has(optionKey)) next.delete(optionKey);\n else next.add(optionKey);\n return next;\n });\n }\n\n function apply() {\n if (pending.size === 0) {\n onModelChange(null);\n return;\n }\n const values: SelectFilterValue[] = [];\n for (const opt of derivedOptions) {\n if (pending.has(toValueKey(opt.value))) values.push(opt.value);\n }\n // A ticked value can leave the data before Apply (the derived list is\n // live). Committing `values: []` would read as an active filter that\n // matches every row, so clear instead.\n if (values.length === 0) {\n onModelChange(null);\n return;\n }\n onModelChange({ type: 'set', values });\n }\n\n function clear() {\n setPending(new Set());\n onModelChange(null);\n }\n\n const placeholderLabel = placeholder ?? t('dataTable.selectFilter.all');\n\n return (\n <div\n data-component=\"select-filter\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)] ds:min-w-[200px] ds:max-w-[260px]\"\n >\n <ScrollArea orientation=\"vertical\" className=\"ds:max-h-[240px]\">\n <div\n role=\"group\"\n aria-label={placeholderLabel}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n >\n {derivedOptions.length === 0 ? (\n <p className=\"ds:text-[length:var(--font-size-sm)] ds:text-[var(--muted-foreground)] ds:py-[var(--spacing-xs)]\">\n {t('dataTable.agGrid.noRowsToShow')}\n </p>\n ) : (\n derivedOptions.map((option) => {\n const key = toValueKey(option.value);\n return (\n <Checkbox\n key={key}\n size=\"sm\"\n label={option.label}\n checked={pending.has(key)}\n onCheckedChange={() => toggle(key)}\n />\n );\n })\n )}\n </div>\n </ScrollArea>\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:justify-end ds:gap-[var(--spacing-xs)] ds:pt-[var(--spacing-xs)] ds:border-t ds:border-[var(--border)]\">\n <Button intent=\"ghost\" size=\"sm\" onClick={clear} type=\"button\">\n {t('dataTable.selectFilter.clear')}\n </Button>\n <Button intent=\"primary\" size=\"sm\" onClick={apply} type=\"button\">\n {t('dataTable.selectFilter.apply')}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Floating-filter companion for `SelectFilter`.\n *\n * Renders the kit's `<MultiSelect>` directly as the floating-filter\n * input — its built-in trigger + checkbox dropdown IS the filter UI.\n * Earlier versions wrapped MultiSelect in another `<Popover>`,\n * producing the \"click trigger → empty popover with another trigger →\n * click → checkbox list\" double-step that read as duplicated UI.\n *\n * MultiSelect's options use `string` values; we string-convert the\n * model's `(string | number)[]` for the trigger and parse back on\n * apply. The grid model still tracks the original primitive types so\n * `doesFilterPass` keeps matching numeric columns correctly.\n *\n * Choices come from the same `useSelectFilterOptions` universe the popup\n * panel uses: an explicit `options` filterParam if the consumer declared\n * one, otherwise the column's own distinct values. Reading only\n * `filterParams.options` used to leave the trigger empty beside a working\n * panel whenever the consumer relied on derivation.\n */\nexport function SelectFloatingFilter(\n props: CustomFloatingFilterProps<\n IFilter,\n unknown,\n unknown,\n SelectFilterModel\n >,\n) {\n const { model, onModelChange, column, api } = props;\n\n const colDef = column?.getColDef?.();\n const filterParams =\n (colDef?.filterParams as SelectFilterParams | undefined) ?? {};\n\n // The floating filter has no `getValue`; read through the grid instead.\n // A column with a `filterValueGetter` should declare `options` — the two\n // reads would otherwise disagree with the panel's.\n const readValue = useCallback<SelectValueReader>(\n (node) =>\n api && column\n ? (api.getCellValue<unknown>({\n rowNode: node,\n colKey: column,\n }) as unknown)\n : undefined,\n [api, column],\n );\n const availableOptions = useSelectFilterOptions(\n api,\n filterParams.options,\n readValue,\n );\n // Name the floating-filter trigger after its column so the per-column Select\n // filters are distinguishable to assistive tech — they otherwise all read as\n // the generic MultiSelect placeholder. An explicit `placeholder` wins.\n const accessibleLabel =\n filterParams.placeholder ??\n (typeof colDef?.headerName === 'string' ? colDef.headerName : undefined);\n\n // MultiSelect's `value` is `string[]`. SelectFilter's model carries\n // `(string | number)[]` so we string-convert in / out. Build a lookup\n // from the stringified key back to the original primitive so the\n // model retains the consumer's typing.\n const valueByKey = useMemo(() => {\n const map = new Map<string, SelectFilterValue>();\n for (const opt of availableOptions) map.set(String(opt.value), opt.value);\n return map;\n }, [availableOptions]);\n\n const selectOptions = useMemo(\n () =>\n availableOptions.map((opt) => ({\n value: String(opt.value),\n label: opt.label,\n })),\n [availableOptions],\n );\n\n const currentValue = useMemo(\n () => (model?.values ?? []).map((v) => String(v)),\n [model],\n );\n\n function handleChange(next: string[]) {\n if (next.length === 0) {\n onModelChange(null);\n return;\n }\n const values: SelectFilterValue[] = [];\n for (const k of next) {\n const original = valueByKey.get(k);\n if (original !== undefined) values.push(original);\n }\n // Same live-list guard as the panel's Apply: an empty set is a cleared\n // filter, never an active one that matches everything.\n if (values.length === 0) {\n onModelChange(null);\n return;\n }\n onModelChange({ type: 'set', values });\n }\n\n return (\n <div data-component=\"select-floating-filter\" className=\"ds:w-full\">\n <MultiSelect\n size=\"sm\"\n options={selectOptions}\n value={currentValue}\n onChange={handleChange}\n placeholder={filterParams.placeholder}\n aria-label={accessibleLabel}\n allowClear\n />\n </div>\n );\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport type {\n CustomFilterProps,\n CustomFloatingFilterProps,\n} from 'ag-grid-react';\nimport { useGridFilter } from 'ag-grid-react';\nimport type { IFilter, IRowNode } from 'ag-grid-community';\nimport { useTranslation } from 'react-i18next';\nimport { Autocomplete } from '../../autocomplete';\nimport { Button } from '../../button';\nimport type { OptionShape } from '../../_shared/option';\n\n/**\n * Custom AG Grid filter component — single-select typeahead filter.\n *\n * Wraps the kit's existing `<Autocomplete>` so the user types to filter a\n * bounded-but-large set of values (e.g. patient names), picks one\n * suggestion, and the grid filters to rows matching that value exactly.\n *\n * Wire on a colDef:\n * ```tsx\n * {\n * field: 'patient',\n * filter: TypeaheadFilter,\n * filterParams: {\n * options: PATIENTS.map(p => ({ value: p.name, label: p.name })),\n * },\n * }\n * ```\n *\n * Model shape `{ type: 'equals', value: string }` matches AG Grid's\n * text-filter `equals` convention so server-side adapters can read either\n * implementation the same way.\n */\n\nexport interface TypeaheadFilterOption {\n value: string;\n label: string;\n}\n\nexport interface TypeaheadFilterModel {\n type: 'equals';\n value: string;\n}\n\nexport interface TypeaheadFilterParams {\n options?: TypeaheadFilterOption[];\n loadOptions?: (\n input: string,\n opts: { signal: AbortSignal; locale: string },\n ) => Promise<TypeaheadFilterOption[]>;\n placeholder?: string;\n}\n\nfunction normalise(s: string): string {\n return s.trim().toLocaleLowerCase();\n}\n\nexport function TypeaheadFilter(\n props: CustomFilterProps<unknown, unknown, TypeaheadFilterModel> &\n TypeaheadFilterParams,\n) {\n const {\n model,\n onModelChange,\n getValue,\n api,\n column,\n options,\n loadOptions,\n placeholder,\n } = props;\n const { t } = useTranslation('ui');\n\n // Universe of choices. Prefer explicit `options`; fall back to the\n // column's distinct values when neither `options` nor `loadOptions` is\n // supplied. Same shape as SelectFilter's derivation so the two filters\n // present a consistent experience when consumers don't enumerate.\n const derivedOptions = useMemo<TypeaheadFilterOption[]>(() => {\n if (options && options.length > 0) return options;\n if (!api || !column) return [];\n const seen = new Map<string, TypeaheadFilterOption>();\n api.forEachNode((node: IRowNode) => {\n const raw = getValue(node) as unknown;\n if (raw === null || raw === undefined) return;\n const value = typeof raw === 'string' ? raw : String(raw);\n if (!seen.has(value)) {\n seen.set(value, { value, label: value });\n }\n });\n return Array.from(seen.values()).sort((a, b) =>\n a.label.localeCompare(b.label),\n );\n }, [options, api, column, getValue]);\n\n // Build the async `loadOptions` adapter that <Autocomplete> consumes.\n // Local-options path filters the snapshot synchronously and wraps it\n // in Promise.resolve(); explicit `loadOptions` is passed through.\n const adapterLoadOptions = useMemo(() => {\n return async (\n query: string,\n opts: { signal: AbortSignal; locale: string },\n ): Promise<OptionShape[]> => {\n if (loadOptions) {\n const result = await loadOptions(query, opts);\n return result.map((o) => ({ value: o.value, label: o.label }));\n }\n const q = normalise(query);\n const filtered = q\n ? derivedOptions.filter((o) => normalise(o.label).includes(q))\n : derivedOptions;\n return filtered\n .slice(0, 50)\n .map((o) => ({ value: o.value, label: o.label }));\n };\n }, [loadOptions, derivedOptions]);\n\n const [draft, setDraft] = useState<string>(model?.value ?? '');\n\n useEffect(() => {\n setDraft(model?.value ?? '');\n }, [model?.value]);\n\n useGridFilter({\n doesFilterPass: (params) => {\n const target = model?.value;\n if (!target) return true;\n const raw = getValue(params.node) as unknown;\n if (raw === null || raw === undefined) return false;\n const value = typeof raw === 'string' ? raw : String(raw);\n return normalise(value) === normalise(target);\n },\n });\n\n function handleSelect(option: OptionShape) {\n // Autocomplete itself commits `option.label` to the input value; we\n // mirror that here so the displayed text matches what the user just\n // picked, even when label and value diverge (e.g. id vs name).\n setDraft(option.label);\n onModelChange({ type: 'equals', value: option.value });\n }\n\n function handleChange(next: string) {\n setDraft(next);\n // Clear the applied model when the user empties the input so the\n // grid stops filtering as soon as the field is blank.\n if (next === '' && model) onModelChange(null);\n }\n\n function clear() {\n setDraft('');\n onModelChange(null);\n }\n\n const placeholderLabel =\n placeholder ?? t('dataTable.typeaheadFilter.placeholder');\n\n return (\n <div\n data-component=\"typeahead-filter\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)] ds:min-w-[240px]\"\n >\n <Autocomplete\n size=\"sm\"\n value={draft}\n onChange={handleChange}\n onSelect={handleSelect}\n loadOptions={adapterLoadOptions}\n placeholder={placeholderLabel}\n aria-label={placeholderLabel}\n />\n <div className=\"ds:flex ds:items-center ds:justify-end ds:pt-[var(--spacing-xs)] ds:border-t ds:border-[var(--border)]\">\n <Button intent=\"ghost\" size=\"sm\" onClick={clear} type=\"button\">\n {t('dataTable.typeaheadFilter.clear')}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Floating-filter companion for `TypeaheadFilter`.\n *\n * Renders the kit's `<Autocomplete>` directly as the floating-filter\n * input — its built-in text input + portaled dropdown IS the filter\n * UI. Earlier versions wrapped Autocomplete in a second `<Popover>`,\n * producing the \"click trigger → popover with another search input →\n * type → list appears\" double-step that read as duplicated UI.\n */\nexport function TypeaheadFloatingFilter(\n props: CustomFloatingFilterProps<\n IFilter,\n unknown,\n unknown,\n TypeaheadFilterModel\n >,\n) {\n const { model, onModelChange, column } = props;\n const { t } = useTranslation('ui');\n\n const filterParams =\n (column?.getColDef?.()?.filterParams as\n | TypeaheadFilterParams\n | undefined) ?? {};\n const availableOptions = filterParams.options ?? [];\n const loadOptions = filterParams.loadOptions;\n const placeholderLabel =\n filterParams.placeholder ?? t('dataTable.typeaheadFilter.placeholder');\n\n const adapterLoadOptions = useMemo(() => {\n return async (\n query: string,\n opts: { signal: AbortSignal; locale: string },\n ): Promise<OptionShape[]> => {\n if (loadOptions) {\n const result = await loadOptions(query, opts);\n return result.map((o) => ({ value: o.value, label: o.label }));\n }\n const q = normalise(query);\n const filtered = q\n ? availableOptions.filter((o) => normalise(o.label).includes(q))\n : availableOptions;\n return filtered\n .slice(0, 50)\n .map((o) => ({ value: o.value, label: o.label }));\n };\n }, [loadOptions, availableOptions]);\n\n // Track the input's display value separately from the applied model.\n // The user can type freely; we only apply when they pick an option\n // from the dropdown (committing a known value to the model). Clearing\n // the input clears the filter.\n const [draft, setDraft] = useState<string>(model?.value ?? '');\n useEffect(() => {\n setDraft(model?.value ?? '');\n }, [model?.value]);\n\n function handleSelect(option: OptionShape) {\n setDraft(option.label);\n onModelChange({ type: 'equals', value: option.value });\n }\n\n function handleChange(next: string) {\n setDraft(next);\n if (next === '' && model) onModelChange(null);\n }\n\n return (\n <div data-component=\"typeahead-floating-filter\" className=\"ds:w-full\">\n <Autocomplete\n size=\"sm\"\n value={draft}\n onChange={handleChange}\n onSelect={handleSelect}\n loadOptions={adapterLoadOptions}\n placeholder={placeholderLabel}\n aria-label={placeholderLabel}\n />\n </div>\n );\n}\n","import { useEffect, useMemo, useRef, useState } from 'react';\nimport type {\n CustomFilterProps,\n CustomFloatingFilterProps,\n} from 'ag-grid-react';\nimport { useGridFilter } from 'ag-grid-react';\nimport type { IFilter } from 'ag-grid-community';\nimport { useTranslation } from 'react-i18next';\nimport { NumberInput } from '../../number-input';\nimport { Select } from '../../select';\nimport { Button } from '../../button';\n\n/**\n * Custom AG Grid filter component for numeric columns. AG Grid Community's\n * built-in `agNumberColumnFilter` paints a stock browser-skinned\n * `<input type=\"number\">` that does not match the kit's form language —\n * this wraps the DS `<NumberInput>` + `<Select>` so totals, prices,\n * quantities, etc. line up visually with neighbouring DS-styled cells.\n *\n * Wire on a colDef:\n * ```tsx\n * {\n * field: 'total',\n * filter: NumberFilter,\n * floatingFilterComponent: NumberFloatingFilter,\n * filterParams: { defaultOperator: 'greaterThan', min: 0 },\n * }\n * ```\n *\n * The full-popover variant exposes the operator dropdown (equals,\n * greaterThan, inRange, blank, …). The floating-filter row follows the\n * applied operator, or `defaultOperator` when no filter is applied: one\n * input for most operators, a from/to pair for `inRange`. Either bound may\n * be empty (from-only means \"≥ from\", to-only \"≤ to\"). Both variants speak\n * the same `NumberFilterModel` so server-side adapters can read either.\n *\n * Model shape `{ type, filter?, filterTo? }` matches AG Grid's own\n * `agNumberColumnFilter` vocabulary so adapters can interchange.\n */\n\nexport type NumberFilterOperator =\n | 'equals'\n | 'notEqual'\n | 'greaterThan'\n | 'greaterThanOrEqual'\n | 'lessThan'\n | 'lessThanOrEqual'\n | 'inRange'\n | 'blank'\n | 'notBlank';\n\nexport interface NumberFilterModel {\n type: NumberFilterOperator;\n /** Lower bound or comparison value. Optional, as in AG Grid's own model,\n * so an `inRange` model can carry only `filterTo` (\"≤ to\"). */\n filter?: number;\n filterTo?: number;\n}\n\nexport interface NumberFilterParams {\n defaultOperator?: NumberFilterOperator;\n min?: number;\n max?: number;\n step?: number;\n placeholder?: string;\n}\n\nconst ALL_OPERATORS: NumberFilterOperator[] = [\n 'equals',\n 'notEqual',\n 'greaterThan',\n 'greaterThanOrEqual',\n 'lessThan',\n 'lessThanOrEqual',\n 'inRange',\n 'blank',\n 'notBlank',\n];\n\nfunction operatorTakesValue(op: NumberFilterOperator): boolean {\n return op !== 'blank' && op !== 'notBlank';\n}\n\nfunction operatorTakesRange(op: NumberFilterOperator): boolean {\n return op === 'inRange';\n}\n\n/**\n * The predicate behind both the popover and the floating row. Exported for\n * unit tests only; not re-exported from the data-table barrel.\n */\nexport function numberFilterPasses(\n op: NumberFilterOperator,\n cell: number | null,\n primary: number | null,\n secondary: number | null,\n): boolean {\n if (op === 'blank') return cell === null;\n if (op === 'notBlank') return cell !== null;\n if (cell === null) return false;\n // Before the \"no primary → pass\" bail-out: a range may carry only `filterTo`.\n if (op === 'inRange') {\n if (primary === null) return secondary === null || cell <= secondary;\n if (secondary === null) return cell >= primary;\n // No min/max swap: an inverted range matches nothing, as it does in\n // agNumberColumnFilter and SQL `BETWEEN 100 AND 50`, and as the chip shows.\n return cell >= primary && cell <= secondary;\n }\n if (primary === null) return true;\n switch (op) {\n case 'equals':\n return cell === primary;\n case 'notEqual':\n return cell !== primary;\n case 'greaterThan':\n return cell > primary;\n case 'greaterThanOrEqual':\n return cell >= primary;\n case 'lessThan':\n return cell < primary;\n case 'lessThanOrEqual':\n return cell <= primary;\n default:\n return true;\n }\n}\n\nfunction nonEmpty(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() !== '' ? value : undefined;\n}\n\nfunction coerceCell(raw: unknown): number | null {\n if (raw === null || raw === undefined || raw === '') return null;\n const n = typeof raw === 'number' ? raw : Number(raw);\n return Number.isNaN(n) ? null : n;\n}\n\nexport function NumberFilter(\n props: CustomFilterProps<unknown, unknown, NumberFilterModel> &\n NumberFilterParams,\n) {\n const {\n model,\n onModelChange,\n getValue,\n defaultOperator,\n min,\n max,\n step,\n placeholder,\n } = props;\n const { t } = useTranslation('ui');\n\n const initialOperator: NumberFilterOperator =\n model?.type ?? defaultOperator ?? 'equals';\n const [operator, setOperator] =\n useState<NumberFilterOperator>(initialOperator);\n const [primary, setPrimary] = useState<number | null>(model?.filter ?? null);\n const [secondary, setSecondary] = useState<number | null>(\n model?.filterTo ?? null,\n );\n\n // If AG Grid pushes an externally-cleared / reset model, mirror it in\n // local state so the UI stays consistent with the applied filter. The\n // cleared model arrives as null OR undefined (removed from a setFilterModel\n // map), so a loose check is load-bearing here.\n useEffect(() => {\n if (model == null) {\n setOperator(defaultOperator ?? 'equals');\n setPrimary(null);\n setSecondary(null);\n return;\n }\n setOperator(model.type);\n setPrimary(model.filter ?? null);\n setSecondary(model.filterTo ?? null);\n }, [model, defaultOperator]);\n\n useGridFilter({\n doesFilterPass: (params) => {\n if (!model) return true;\n const cell = coerceCell(getValue(params.node));\n return numberFilterPasses(\n model.type,\n cell,\n model.filter ?? null,\n model.filterTo ?? null,\n );\n },\n });\n\n const operatorOptions = useMemo(\n () =>\n ALL_OPERATORS.map((op) => ({\n value: op,\n label: t(`dataTable.numberFilter.operators.${op}`),\n })),\n [t],\n );\n\n const placeholderLabel =\n placeholder ?? t('dataTable.numberFilter.placeholder');\n\n function apply() {\n if (!operatorTakesValue(operator)) {\n onModelChange({ type: operator, filter: 0 });\n return;\n }\n // Above the empty-primary guard: a to-only range (\"≤ 9\") has no `filter`.\n if (operatorTakesRange(operator)) {\n if (primary === null && secondary === null) {\n onModelChange(null);\n return;\n }\n onModelChange({\n type: operator,\n filter: primary ?? undefined,\n filterTo: secondary ?? undefined,\n });\n return;\n }\n if (primary === null) {\n onModelChange(null);\n return;\n }\n onModelChange({ type: operator, filter: primary });\n }\n\n function clear() {\n setOperator(defaultOperator ?? 'equals');\n setPrimary(null);\n setSecondary(null);\n onModelChange(null);\n }\n\n const showValue = operatorTakesValue(operator);\n const showRange = operatorTakesRange(operator);\n\n return (\n <div\n data-component=\"number-filter\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)] ds:min-w-[240px]\"\n >\n <Select\n size=\"sm\"\n options={operatorOptions}\n value={operator}\n onValueChange={(next) => {\n if (next === '') return;\n setOperator(next as NumberFilterOperator);\n }}\n aria-label={t('dataTable.numberFilter.operatorLabel')}\n />\n {showValue && !showRange && (\n <NumberInput\n size=\"sm\"\n mode=\"decimal\"\n value={primary}\n onChange={setPrimary}\n min={min}\n max={max}\n step={step}\n placeholder={placeholderLabel}\n aria-label={placeholderLabel}\n />\n )}\n {showRange && (\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <NumberInput\n size=\"sm\"\n mode=\"decimal\"\n value={primary}\n onChange={setPrimary}\n min={min}\n max={max}\n step={step}\n placeholder={t('dataTable.numberFilter.from')}\n aria-label={t('dataTable.numberFilter.from')}\n />\n <NumberInput\n size=\"sm\"\n mode=\"decimal\"\n value={secondary}\n onChange={setSecondary}\n min={min}\n max={max}\n step={step}\n placeholder={t('dataTable.numberFilter.to')}\n aria-label={t('dataTable.numberFilter.to')}\n />\n </div>\n )}\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:justify-end ds:gap-[var(--spacing-xs)] ds:pt-[var(--spacing-xs)] ds:border-t ds:border-[var(--border)]\">\n <Button intent=\"ghost\" size=\"sm\" onClick={clear} type=\"button\">\n {t('dataTable.numberFilter.clear')}\n </Button>\n <Button intent=\"primary\" size=\"sm\" onClick={apply} type=\"button\">\n {t('dataTable.numberFilter.apply')}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Floating-filter companion for `NumberFilter`.\n *\n * Follows the APPLIED operator, falling back to `defaultOperator` (or\n * `'equals'`) when no filter is applied. Emptying the row keeps the operator\n * it was editing, so retyping does not switch to the default; only an\n * external clear (chip remove, header Clear, `setFilterModel`) returns to it,\n * as with AG Grid's own floating filter. `inRange` renders a compact from/to\n * pair; either bound may stay empty, and clearing both commits `null`.\n * Every other value operator renders one input. `blank` / `notBlank` take no\n * value, so the input is disabled and names the operator. The operator\n * dropdown lives only in the full popover, as with `agNumberColumnFilter`.\n *\n * One 200 ms debounce covers both bounds, so each keystroke does not re-run\n * the grid filter, and an invalid number never reaches the model as `NaN`.\n * Every input, here and in the popover, is `mode=\"decimal\"`: the integer\n * default showed 0.01 as \"0\" once blurred, while the filter compared 0.01.\n */\nexport function NumberFloatingFilter(\n props: CustomFloatingFilterProps<\n IFilter,\n unknown,\n unknown,\n NumberFilterModel\n >,\n) {\n const { model, onModelChange, column, api } = props;\n const { t } = useTranslation('ui');\n\n const colDef = column?.getColDef?.();\n const filterParams =\n (colDef?.filterParams as NumberFilterParams | undefined) ?? {};\n // The operator the row was editing when it emptied itself. The `null`\n // model that comes back must not drop it: \"> 30\" retyped as \"40\" would\n // otherwise commit \"= 40\". Any non-null model releases it.\n const [heldOperator, setHeldOperator] = useState<NumberFilterOperator | null>(\n null,\n );\n // The applied operator wins. Reading only the default turned a popover\n // \"≤ 100\" on an inRange column into \"From 100\", then into a range as soon\n // as the other box was typed in.\n const operator: NumberFilterOperator =\n model?.type ?? heldOperator ?? filterParams.defaultOperator ?? 'equals';\n const isRange = operatorTakesRange(operator);\n const takesValue = operatorTakesValue(operator);\n const placeholderLabel =\n filterParams.placeholder ?? t('dataTable.numberFilter.placeholder');\n // AG Grid gives a floating filter no aria-labelledby to its header, so name\n // each input after its column: two such columns would otherwise put two\n // identical boxes in one row. The grid's display name also covers\n // field-only and headerValueGetter columns. The placeholder stays short.\n const columnName =\n nonEmpty(column ? api?.getDisplayNameForColumn(column, 'header') : null) ??\n nonEmpty(colDef?.headerName);\n const fromPlaceholder = t('dataTable.numberFilter.from');\n const toPlaceholder = t('dataTable.numberFilter.to');\n const fromLabel = columnName\n ? t('dataTable.numberFilter.columnFrom', { column: columnName })\n : fromPlaceholder;\n const toLabel = columnName\n ? t('dataTable.numberFilter.columnTo', { column: columnName })\n : toPlaceholder;\n const valueLabel = columnName\n ? t('dataTable.numberFilter.columnFilter', { column: columnName })\n : placeholderLabel;\n\n const [from, setFrom] = useState<number | null>(model?.filter ?? null);\n const [to, setTo] = useState<number | null>(model?.filterTo ?? null);\n // The bounds this row last committed. The grid echoes them back a render\n // or two later, by which time the other box may hold newer typing.\n const pendingEcho = useRef<{ from: number | null; to: number | null } | null>(\n null,\n );\n\n // Mirror an external change (header-menu Clear, chip remove, popover Apply,\n // setFilterModel) into both bounds. The echo of this row's own commit is\n // not one: mirroring it would wipe a bound typed while it was on its way.\n useEffect(() => {\n const next = { from: model?.filter ?? null, to: model?.filterTo ?? null };\n const echo = pendingEcho.current;\n pendingEcho.current = null;\n if (echo && echo.from === next.from && echo.to === next.to) return;\n setFrom(next.from);\n setTo(next.to);\n }, [model?.filter, model?.filterTo]);\n\n // A non-null model releases the held operator, so a later external clear\n // returns the row to the column default.\n useEffect(() => {\n if (model != null) setHeldOperator(null);\n }, [model]);\n\n // Debounced commit. A useEffect + setTimeout is cheaper than importing a\n // hook, and AG Grid only re-renders this floating filter per keystroke.\n useEffect(() => {\n if (!takesValue) return;\n if (from === (model?.filter ?? null) && to === (model?.filterTo ?? null)) {\n return;\n }\n const handle = setTimeout(() => {\n const lo = from === null || Number.isNaN(from) ? null : from;\n const hi = to === null || Number.isNaN(to) ? null : to;\n const commit = (next: NumberFilterModel | null) => {\n pendingEcho.current = {\n from: next?.filter ?? null,\n to: next?.filterTo ?? null,\n };\n onModelChange(next);\n };\n // The row emptied itself: keep its operator for the next value.\n const clearFromRow = () => {\n setHeldOperator(operator);\n commit(null);\n };\n if (!isRange) {\n if (lo === null) clearFromRow();\n else commit({ type: operator, filter: lo });\n return;\n }\n if (lo === null && hi === null) {\n clearFromRow();\n return;\n }\n commit({\n type: 'inRange',\n filter: lo ?? undefined,\n filterTo: hi ?? undefined,\n });\n }, 200);\n return () => clearTimeout(handle);\n // `model` intentionally excluded — we only react to user edits. Model\n // changes sync via the effect above.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [from, to, operator, isRange, takesValue]);\n\n if (!takesValue) {\n const operatorLabel = t(`dataTable.numberFilter.operators.${operator}`);\n return (\n <div data-component=\"number-floating-filter\" className=\"ds:w-full\">\n <NumberInput\n size=\"sm\"\n variant=\"plain\"\n value={null}\n disabled\n placeholder={operatorLabel}\n aria-label={\n columnName\n ? t('dataTable.numberFilter.columnOperator', {\n column: columnName,\n operator: operatorLabel,\n })\n : operatorLabel\n }\n />\n </div>\n );\n }\n\n if (!isRange) {\n return (\n <div data-component=\"number-floating-filter\" className=\"ds:w-full\">\n <NumberInput\n size=\"sm\"\n mode=\"decimal\"\n value={from}\n onChange={setFrom}\n min={filterParams.min}\n max={filterParams.max}\n step={filterParams.step}\n placeholder={placeholderLabel}\n aria-label={valueLabel}\n />\n </div>\n );\n }\n\n // `variant=\"plain\"` drops the stepper chevrons, which would take most of a\n // 150px column. They are tabIndex={-1}, so no keyboard path is lost, and\n // arrow keys still step. Flex + gap is direction-agnostic, so RTL flips.\n return (\n <div\n data-component=\"number-floating-filter\"\n className=\"ds:flex ds:w-full ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n <NumberInput\n size=\"sm\"\n variant=\"plain\"\n mode=\"decimal\"\n className=\"ds:min-w-0 ds:flex-1\"\n value={from}\n onChange={setFrom}\n min={filterParams.min}\n max={filterParams.max}\n step={filterParams.step}\n placeholder={fromPlaceholder}\n aria-label={fromLabel}\n />\n <NumberInput\n size=\"sm\"\n variant=\"plain\"\n mode=\"decimal\"\n className=\"ds:min-w-0 ds:flex-1\"\n value={to}\n onChange={setTo}\n min={filterParams.min}\n max={filterParams.max}\n step={filterParams.step}\n placeholder={toPlaceholder}\n aria-label={toLabel}\n />\n </div>\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { Badge } from '../../badge/badge';\n\nexport type BadgeVariant = 'neutral' | 'info' | 'success' | 'warning' | 'error';\n\nexport interface StatusCellRendererParams {\n variantMap?: Record<string, BadgeVariant>;\n}\n\nexport function StatusCellRenderer(\n props: CustomCellRendererProps & StatusCellRendererParams,\n) {\n const { value, variantMap } = props;\n const variant: BadgeVariant = variantMap?.[value as string] ?? 'neutral';\n return (\n <Badge variant={variant} withDot size=\"sm\">\n {String(value ?? '')}\n </Badge>\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { Avatar } from '../../avatar/avatar';\n\nexport interface UserCellValue {\n name: string;\n src?: string;\n}\n\nexport function UserCellRenderer(\n props: CustomCellRendererProps<unknown, UserCellValue>,\n) {\n const { value } = props;\n if (!value) return null;\n return (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Avatar name={value.name} src={value.src} size=\"sm\" />\n <span>{value.name}</span>\n </span>\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { Avatar } from '../../avatar/avatar';\n\nexport interface ImageCellRendererParams {\n /** Field name on the row whose value holds the image URL. */\n srcField: string;\n /** Optional field name holding alt text. Falls back to '' (decorative). */\n altField?: string;\n /**\n * Optional field name holding a name string. When the src URL is missing or\n * rejected, the cell falls back to `<Avatar name={fallback}>` so the cell\n * still has a visual.\n */\n fallbackField?: string;\n /** Visual size of the image. Matches `<Avatar>` sizes (sm=32, md=40, lg=48). */\n size?: 'sm' | 'md' | 'lg';\n /** Corner radius preset. `circle` matches `<Avatar>`. */\n shape?: 'square' | 'rounded' | 'circle';\n}\n\nconst SIZE_CLASS: Record<\n NonNullable<ImageCellRendererParams['size']>,\n string\n> = {\n sm: 'ds:size-8',\n md: 'ds:size-10',\n lg: 'ds:size-12',\n};\n\nconst SHAPE_CLASS: Record<\n NonNullable<ImageCellRendererParams['shape']>,\n string\n> = {\n square: 'ds:rounded-none',\n rounded: 'ds:rounded-[var(--radius-md)]',\n circle: 'ds:rounded-[var(--radius-full)]',\n};\n\nfunction readField(row: unknown, field: string): string | undefined {\n if (!row || typeof row !== 'object') return undefined;\n const value = (row as Record<string, unknown>)[field];\n return typeof value === 'string' ? value : undefined;\n}\n\n// Accept http(s), image data: URLs, and same-origin absolute paths. Reject\n// `javascript:` / `vbscript:` / any other smuggled scheme. Browsers won't\n// execute non-image data: URLs in `<img>`, but rejecting them in JS gives a\n// single audit point.\n//\n// A leading `/` cannot carry a scheme, so a root-relative path is at least as\n// safe as an absolute URL — and it is what an app serving its own images\n// naturally produces. `//host/x` IS excluded: protocol-relative URLs are\n// cross-origin, which is the thing this guard exists to control.\nconst SAFE_SRC_RE = /^(?:https?:|data:image\\/|\\/(?!\\/))/i;\n\nfunction sanitizeSrc(raw: string | undefined): string | undefined {\n if (!raw) return undefined;\n const trimmed = raw.trim();\n if (trimmed.length === 0) return undefined;\n return SAFE_SRC_RE.test(trimmed) ? trimmed : undefined;\n}\n\nexport function ImageCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & ImageCellRendererParams,\n) {\n const {\n data,\n srcField,\n altField,\n fallbackField,\n size = 'md',\n shape = 'rounded',\n } = props;\n\n if (!data) return null;\n\n const rawSrc = readField(data, srcField);\n const src = sanitizeSrc(rawSrc);\n const alt = altField ? (readField(data, altField) ?? '') : '';\n const fallbackName = fallbackField\n ? readField(data, fallbackField)\n : undefined;\n\n // A circular image with a name is a person: let <Avatar> own it. It paints the\n // initials first, covers them once the photo decodes, and drops the <img> on\n // error so the initials persist — instead of a blank cell that later pops.\n if (shape === 'circle' && fallbackName) {\n return <Avatar src={src} name={fallbackName} size={size} />;\n }\n\n if (!src) {\n if (fallbackName) {\n return <Avatar name={fallbackName} size={size} />;\n }\n return null;\n }\n\n return (\n <img\n src={src}\n alt={alt}\n loading=\"lazy\"\n decoding=\"async\"\n className={['ds:object-cover', SIZE_CLASS[size], SHAPE_CLASS[shape]].join(\n ' ',\n )}\n />\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { useTranslation } from 'react-i18next';\nimport { Tag } from '../../tag/tag';\nimport { Tooltip } from '../../tooltip';\n\nexport interface TagListCellRendererParams {\n maxVisible?: number;\n}\n\nexport function TagListCellRenderer(\n props: CustomCellRendererProps<unknown, string[]> & TagListCellRendererParams,\n) {\n const { value, maxVisible = 3 } = props;\n const { t } = useTranslation('ui');\n\n if (!Array.isArray(value) || value.length === 0) return null;\n\n const visible = value.slice(0, maxVisible);\n const overflow = value.length - maxVisible;\n\n return (\n <span className=\"ds:inline-flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)]\">\n {visible.map((tag) => (\n <Tag key={tag} label={tag} size=\"sm\" />\n ))}\n {overflow > 0 && (\n <Tooltip label={value.slice(maxVisible).join(', ')}>\n <Tag\n label={t('inputs.multiSelect.overflow', { count: overflow })}\n size=\"sm\"\n variant=\"neutral\"\n fill=\"outline\"\n />\n </Tooltip>\n )}\n </span>\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { Timestamp } from '../../timestamp';\nimport { fromIsoDate, isCalendarDay } from '../calendar-day';\n\nexport type DateCellFormat = 'date' | 'time' | 'datetime' | 'relative';\n\nexport interface DateCellRendererParams {\n /** Which preset to use. Default `'date'`. */\n format?: DateCellFormat;\n /** Escape hatch — overrides the preset entirely. */\n options?: Intl.DateTimeFormatOptions;\n}\n\nconst PRESETS: Record<\n Exclude<DateCellFormat, 'relative'>,\n Intl.DateTimeFormatOptions\n> = {\n date: { year: 'numeric', month: 'short', day: 'numeric' },\n time: { hour: '2-digit', minute: '2-digit' },\n datetime: {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n },\n};\n\nexport function DateCellRenderer(\n props: CustomCellRendererProps & DateCellRendererParams,\n) {\n const { value, format = 'date', options } = props;\n if (value == null || value === '') return null;\n\n const calendarDay = isCalendarDay(value);\n\n // `shape=\"bare\"` keeps the cell font inherited from --ag-font-size. Timestamp\n // still emits a proper `<time dateTime>` for assistive tech and feeds.\n //\n // A relative reading (\"3 days ago\") is about the viewer's own day, so a bare\n // date is anchored to LOCAL midnight here.\n if (format === 'relative' && !options) {\n const relativeValue = calendarDay ? (fromIsoDate(value) ?? value) : value;\n return <Timestamp value={relativeValue as string | Date} shape=\"bare\" />;\n }\n\n const absoluteFormat =\n options ?? PRESETS[format === 'relative' ? 'date' : format];\n\n return (\n <Timestamp\n value={value as string | Date}\n format=\"absolute\"\n shape=\"bare\"\n // A bare `YYYY-MM-DD` is a calendar day and carries no instant, so it is\n // read AND written in UTC: it then renders the day it was written with in\n // every browser zone, and under any `timeZone` the caller names. Anchoring\n // it to a real zone instead would move the day for readers on one side —\n // local midnight loses a day west of UTC, UTC midnight loses one east of\n // the named zone. Values carrying a time are instants and keep the\n // caller's options untouched.\n absoluteFormat={\n calendarDay ? { ...absoluteFormat, timeZone: 'UTC' } : absoluteFormat\n }\n />\n );\n}\n","import type { MouseEvent } from 'react';\nimport type { CustomCellRendererProps } from 'ag-grid-react';\n\ntype Getter<T, TData> = T | ((data: TData) => T | undefined);\n\nexport interface LinkCellRendererParams<TData = unknown> {\n /** Anchor href — or a function that derives it from the row. */\n href?: Getter<string, TData>;\n /** Fallback / additional onClick. Prevents default when provided without href. */\n onClick?: (data: TData) => void;\n /** Small text rendered below the link — supports a row-aware function. */\n secondary?: Getter<string, TData>;\n}\n\nfunction resolve<T, TData>(\n source: Getter<T, TData> | undefined,\n data: TData,\n): T | undefined {\n if (typeof source === 'function') {\n return (source as (data: TData) => T | undefined)(data);\n }\n return source;\n}\n\nfunction safeHref(href: string): string {\n return /^(https?:\\/\\/|\\/|#|mailto:|tel:)/i.test(href) ? href : '#';\n}\n\nexport function LinkCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & LinkCellRendererParams<TData>,\n) {\n const { value, data, href, onClick, secondary } = props;\n if (!data) return null;\n\n const resolvedHref = resolve(href, data);\n const resolvedSecondary = resolve(secondary, data);\n const content = value == null || value === '' ? '' : String(value);\n\n const linkClasses = [\n 'ds:text-[color:var(--primary)]',\n 'ds:hover:underline',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)]',\n 'ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:rounded-[var(--radius-sm)]',\n ].join(' ');\n\n const handleClick = (event: MouseEvent) => {\n if (!onClick) return;\n if (!resolvedHref) event.preventDefault();\n event.stopPropagation();\n onClick(data);\n };\n\n return (\n <span className=\"ds:flex ds:flex-col ds:leading-tight\">\n {resolvedHref ? (\n <a\n href={safeHref(resolvedHref)}\n onClick={handleClick}\n className={linkClasses}\n >\n {content}\n </a>\n ) : (\n <button\n type=\"button\"\n onClick={handleClick}\n className={[\n 'ds:appearance-none ds:bg-transparent ds:p-0 ds:text-start',\n linkClasses,\n ].join(' ')}\n >\n {content}\n </button>\n )}\n {resolvedSecondary ? (\n <span className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {resolvedSecondary}\n </span>\n ) : null}\n </span>\n );\n}\n"],"names":["DATE_ONLY","ISO_DAY_PREFIX","toIsoDate","d","y","m","day","isCalendarDay","s","fromIsoDate","dayOf","cellValue","prefix","dayInRange","dateFrom","dateTo","DateRangeFilter","props","model","onModelChange","getValue","doesRowPassOtherFilter","filterParams","_a","range","setRange","useState","useEffect","useGridFilter","params","apply","next","jsx","DateRangePicker","DateRangeFloatingFilter","column","_b","toValueKey","v","LABEL_COLLATOR","collectColumnOptions","api","readValue","seen","node","raw","value","key","b","sameOptions","a","opt","i","useSelectFilterOptions","options","explicit","hasExplicit","derived","setDerived","readValueRef","useRef","recompute","prev","SelectFilter","placeholder","t","useTranslation","useCallback","derivedOptions","initialSelected","useMemo","set","incoming","pending","setPending","active","toggle","optionKey","values","clear","placeholderLabel","jsxs","ScrollArea","option","Checkbox","Button","SelectFloatingFilter","colDef","availableOptions","accessibleLabel","valueByKey","map","selectOptions","currentValue","handleChange","k","original","MultiSelect","normalise","TypeaheadFilter","loadOptions","adapterLoadOptions","query","opts","o","q","draft","setDraft","target","handleSelect","Autocomplete","TypeaheadFloatingFilter","ALL_OPERATORS","operatorTakesValue","op","operatorTakesRange","numberFilterPasses","cell","primary","secondary","nonEmpty","coerceCell","n","NumberFilter","defaultOperator","min","max","step","initialOperator","operator","setOperator","setPrimary","setSecondary","operatorOptions","showValue","showRange","Select","NumberInput","NumberFloatingFilter","heldOperator","setHeldOperator","isRange","takesValue","columnName","fromPlaceholder","toPlaceholder","fromLabel","toLabel","valueLabel","from","setFrom","to","setTo","pendingEcho","echo","handle","lo","hi","commit","clearFromRow","operatorLabel","StatusCellRenderer","variantMap","variant","Badge","UserCellRenderer","Avatar","SIZE_CLASS","SHAPE_CLASS","readField","row","field","SAFE_SRC_RE","sanitizeSrc","trimmed","ImageCellRenderer","data","srcField","altField","fallbackField","size","shape","rawSrc","src","alt","fallbackName","TagListCellRenderer","maxVisible","visible","overflow","tag","Tag","Tooltip","PRESETS","DateCellRenderer","format","calendarDay","relativeValue","Timestamp","absoluteFormat","resolve","source","safeHref","href","LinkCellRenderer","onClick","resolvedHref","resolvedSecondary","content","linkClasses","handleClick","event"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"link-cell-renderer-C8vfCOEp.js","sources":["../../src/components/data-table/calendar-day.ts","../../src/components/data-table/filters/date-range-filter.tsx","../../src/components/data-table/filters/select-filter.tsx","../../src/components/data-table/filters/typeahead-filter.tsx","../../src/components/data-table/filters/number-filter.tsx","../../src/components/data-table/cell-renderers/status-cell-renderer.tsx","../../src/components/data-table/cell-renderers/user-cell-renderer.tsx","../../src/components/data-table/cell-renderers/image-cell-renderer.tsx","../../src/components/data-table/cell-renderers/tag-list-cell-renderer.tsx","../../src/components/data-table/cell-renderers/date-cell-renderer.tsx","../../src/components/data-table/cell-renderers/link-cell-renderer.tsx"],"sourcesContent":["/**\n * Calendar-day helpers, shared by the date filter and the date cell renderer.\n *\n * A calendar day is not an instant. `new Date('2008-09-06')` is UTC midnight,\n * which every local getter then reads back shifted: west of UTC it is the 5th.\n * Everything here works in local date parts so a day stays the day it was\n * written with, whatever zone the browser is in.\n */\n\nconst DATE_ONLY = /^\\d{4}-\\d{2}-\\d{2}$/;\nconst ISO_DAY_PREFIX = /^(\\d{4}-\\d{2}-\\d{2})/;\n\n/**\n * A `Date` as `YYYY-MM-DD`, read off the LOCAL date parts — `toISOString()`\n * would shift a local midnight to the previous day anywhere east of UTC.\n */\nexport function toIsoDate(d: Date | undefined): string | null {\n if (!d) return null;\n const y = d.getFullYear();\n const m = String(d.getMonth() + 1).padStart(2, '0');\n const day = String(d.getDate()).padStart(2, '0');\n return `${y}-${m}-${day}`;\n}\n\n/** Whether a value is a bare `YYYY-MM-DD` — a calendar day, carrying no instant. */\nexport function isCalendarDay(s: unknown): s is string {\n return typeof s === 'string' && DATE_ONLY.test(s);\n}\n\n/** A bare day parses as LOCAL midnight; anything with a time/offset as-is. */\nexport function fromIsoDate(s: string | null | undefined): Date | undefined {\n if (!s) return undefined;\n const d = DATE_ONLY.test(s)\n ? new Date(\n Number(s.slice(0, 4)),\n Number(s.slice(5, 7)) - 1,\n Number(s.slice(8, 10)),\n )\n : new Date(s);\n return Number.isNaN(d.getTime()) ? undefined : d;\n}\n\n/**\n * The calendar day a cell value stands for, as `YYYY-MM-DD`.\n *\n * An ISO string is read as the day it was WRITTEN with — `2026-04-15T17:32+02:00`\n * is the 15th and `1933-04-04T00:00+01:00` the 4th, whatever zone the browser\n * is in. Anything else is parsed and read off its local parts.\n */\nexport function dayOf(cellValue: unknown): string | null {\n if (cellValue === null || cellValue === undefined || cellValue === '')\n return null;\n if (typeof cellValue === 'string') {\n const prefix = ISO_DAY_PREFIX.exec(cellValue);\n if (prefix) return prefix[1];\n }\n const d = cellValue instanceof Date ? cellValue : new Date(String(cellValue));\n return Number.isNaN(d.getTime()) ? null : toIsoDate(d);\n}\n","import { useEffect, useState } from 'react';\nimport type {\n CustomFilterProps,\n CustomFloatingFilterProps,\n} from 'ag-grid-react';\nimport { useGridFilter } from 'ag-grid-react';\nimport type { IFilter } from 'ag-grid-community';\nimport { DateRangePicker } from '../../date-range-picker';\nimport type { DateRangeValue } from '../../date-range-picker';\n// Calendar-day handling lives in one place: the date cell renderer needs the\n// same rules and must not import from a filter to get them.\nimport { dayOf, fromIsoDate, toIsoDate } from '../calendar-day';\n\nexport { dayOf, fromIsoDate, toIsoDate };\n\n/**\n * Custom AG Grid filter component for date *ranges*. AG Grid Community's\n * built-in `agDateColumnFilter` only handles single-date comparison —\n * platform needs \"between X and Y\" for invoice / transaction lists.\n *\n * Wire on a colDef:\n * ```tsx\n * { field: 'date', filter: DateRangeFilter }\n * ```\n *\n * The filter model has shape `{ type: 'inRange', dateFrom, dateTo }` to\n * stay close to AG Grid's own date-filter convention so server-side\n * adapters can interpret it the same way.\n */\nexport interface DateRangeFilterModel {\n type: 'inRange';\n dateFrom: string | null;\n dateTo: string | null;\n}\n\n/**\n * `filterParams` a colDef may pass to `DateRangeFilter` /\n * `DateRangeFloatingFilter`.\n *\n * `commitMode` is forwarded to the wrapped `DateRangePicker`. Leave it unset\n * (picker default `'auto'`, commit-on-complete-range) for cheap client-side row\n * models; set `'apply'` for SERVER-side row models so each range edit defers to\n * one Apply and fires a single datasource round-trip instead of one per commit.\n */\nexport interface DateRangeFilterParams {\n placeholder?: string;\n commitMode?: 'auto' | 'apply';\n}\n\n/** Whether a cell's day lies within `[dateFrom, dateTo]` (either end open). */\nexport function dayInRange(\n cellValue: unknown,\n dateFrom: string | null | undefined,\n dateTo: string | null | undefined,\n): boolean {\n if (!dateFrom && !dateTo) return true;\n const day = dayOf(cellValue);\n if (!day) return false;\n if (dateFrom && day < dateFrom) return false;\n if (dateTo && day > dateTo) return false;\n return true;\n}\n\nexport function DateRangeFilter(\n props: CustomFilterProps<unknown, unknown, DateRangeFilterModel>,\n) {\n const { model, onModelChange, getValue, doesRowPassOtherFilter } = props;\n const filterParams =\n (props.colDef?.filterParams as DateRangeFilterParams | undefined) ?? {};\n // Picker UI state, seeded from the model and kept in sync when the model\n // changes externally — a programmatic default (e.g. \"this week\"), a server\n // restore, or an AG Grid reset. Mirrors `SelectFilter`'s `pending` sync.\n const [range, setRange] = useState<DateRangeValue>(() => ({\n from: fromIsoDate(model?.dateFrom),\n to: fromIsoDate(model?.dateTo),\n }));\n useEffect(() => {\n setRange({\n from: fromIsoDate(model?.dateFrom),\n to: fromIsoDate(model?.dateTo),\n });\n }, [model?.dateFrom, model?.dateTo]);\n\n // Tell AG Grid how to evaluate a row against the current model. AG Grid\n // calls this for each row; we read the cell value via `getValue(node)`\n // (a Date or ISO string), compare to the bounds. Bounds come from the\n // MODEL (the source of truth) — not the picker state — so a model set\n // programmatically applies even before the picker UI has mounted, exactly\n // as `SelectFilter` reads `model.values` directly.\n useGridFilter({\n doesFilterPass: (params) => {\n void doesRowPassOtherFilter;\n return dayInRange(getValue(params.node), model?.dateFrom, model?.dateTo);\n },\n });\n\n function apply(next: DateRangeValue) {\n setRange(next);\n if (!next.from && !next.to) {\n onModelChange(null);\n return;\n }\n onModelChange({\n type: 'inRange',\n dateFrom: toIsoDate(next.from),\n dateTo: toIsoDate(next.to),\n } satisfies DateRangeFilterModel);\n }\n\n return (\n <div\n data-component=\"date-range-filter\"\n className=\"ds:p-[var(--spacing-sm)] ds:min-w-[280px]\"\n >\n <DateRangePicker\n value={range}\n onChange={apply}\n commitMode={filterParams.commitMode}\n size=\"sm\"\n // A column filter has no room for the two-month rail-and-title layout.\n compact\n />\n </div>\n );\n}\n\n/**\n * Floating-filter companion for `DateRangeFilter`.\n *\n * Renders the kit's `<DateRangePicker>` directly as the floating-filter\n * input — its built-in trigger button + calendar popover IS the filter\n * UI. Earlier versions wrapped the picker in a second `<Popover>`,\n * producing the \"click → empty popover with another trigger → click\n * again → calendar\" double-step that read as duplicated UI.\n */\nexport function DateRangeFloatingFilter(\n props: CustomFloatingFilterProps<\n IFilter,\n unknown,\n unknown,\n DateRangeFilterModel\n >,\n) {\n const { model, onModelChange, column } = props;\n // Let a colDef supply a short `filterParams.placeholder` for the in-row\n // trigger — the default \"Select date range\" is long for a narrow filter\n // column. (The label truncates cleanly either way; a short placeholder just\n // reads better.)\n const filterParams =\n (column?.getColDef?.()?.filterParams as\n | DateRangeFilterParams\n | undefined) ?? {};\n const [range, setRange] = useState<DateRangeValue>(() => ({\n from: fromIsoDate(model?.dateFrom),\n to: fromIsoDate(model?.dateTo),\n }));\n // Reflect external model changes (a programmatic default, a parent-filter\n // edit, an AG Grid reset) in the in-row picker trigger.\n useEffect(() => {\n setRange({\n from: fromIsoDate(model?.dateFrom),\n to: fromIsoDate(model?.dateTo),\n });\n }, [model?.dateFrom, model?.dateTo]);\n\n function apply(next: DateRangeValue) {\n setRange(next);\n if (!next.from && !next.to) {\n onModelChange(null);\n return;\n }\n onModelChange({\n type: 'inRange',\n dateFrom: toIsoDate(next.from),\n dateTo: toIsoDate(next.to),\n } satisfies DateRangeFilterModel);\n }\n\n return (\n <div data-component=\"date-range-floating-filter\" className=\"ds:w-full\">\n <DateRangePicker\n value={range}\n onChange={apply}\n commitMode={filterParams.commitMode}\n size=\"sm\"\n placeholder={filterParams.placeholder}\n // A column filter has no room for the two-month rail-and-title layout.\n compact\n />\n </div>\n );\n}\n","import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport type {\n CustomFilterProps,\n CustomFloatingFilterProps,\n} from 'ag-grid-react';\nimport { useGridFilter } from 'ag-grid-react';\nimport type { GridApi, IFilter, IRowNode } from 'ag-grid-community';\nimport { useTranslation } from 'react-i18next';\nimport { Checkbox } from '../../checkbox';\nimport { Button } from '../../button';\nimport { MultiSelect } from '../../multi-select';\nimport { ScrollArea } from '../../scroll-area/scroll-area';\n\n/**\n * Custom AG Grid filter component — multi-select facet filter.\n *\n * The Community-friendly equivalent of AG Grid Enterprise's\n * `agSetColumnFilter`. Surfaces a checkbox list of every value the column\n * can take, so users tick to include / untick to exclude. Much faster than\n * the default `agTextColumnFilter` for closed enums (status, room,\n * operator).\n *\n * Wire on a colDef:\n * ```tsx\n * {\n * field: 'status',\n * filter: SelectFilter,\n * filterParams: {\n * options: [\n * { value: 'open', label: 'Aperte' },\n * { value: 'paid', label: 'Pagate' },\n * ],\n * },\n * }\n * ```\n *\n * Model shape `{ type: 'set', values: Array<string | number> }` matches\n * AG Grid Enterprise's set-filter convention so server-side adapters can\n * read either implementation the same way.\n */\n\nexport interface SelectFilterOption {\n value: string | number;\n label: string;\n}\n\nexport interface SelectFilterModel {\n type: 'set';\n values: Array<string | number>;\n}\n\nexport interface SelectFilterParams {\n options?: SelectFilterOption[];\n placeholder?: string;\n}\n\ntype SelectFilterValue = string | number;\n\nfunction toValueKey(v: SelectFilterValue): string {\n return typeof v === 'number' ? `n:${v}` : `s:${v}`;\n}\n\n/** How a filter surface reads one row's value for its column. */\ntype SelectValueReader = (node: IRowNode) => unknown;\n\n/** Numeric collation, so a derived numeric column lists 1, 2, 3, 10 rather\n * than the lexicographic 1, 10, 2, 3. */\nconst LABEL_COLLATOR = new Intl.Collator(undefined, { numeric: true });\n\n/** Distinct values the column actually holds, label-sorted. `forEachNode`\n * walks the whole client-side row model, so the list does not shrink as\n * other columns filter rows out. */\nfunction collectColumnOptions(\n api: GridApi | undefined,\n readValue: SelectValueReader,\n): SelectFilterOption[] {\n if (!api) return [];\n const seen = new Map<string, SelectFilterOption>();\n api.forEachNode((node: IRowNode) => {\n const raw = readValue(node);\n if (raw === null || raw === undefined) return;\n const value =\n typeof raw === 'string' || typeof raw === 'number' ? raw : String(raw);\n const key = toValueKey(value);\n if (!seen.has(key)) seen.set(key, { value, label: String(value) });\n });\n return Array.from(seen.values()).sort((a, b) =>\n LABEL_COLLATOR.compare(String(a.label), String(b.label)),\n );\n}\n\nfunction sameOptions(\n a: SelectFilterOption[],\n b: SelectFilterOption[],\n): boolean {\n if (a.length !== b.length) return false;\n return a.every(\n (opt, i) =>\n toValueKey(opt.value) === toValueKey(b[i].value) &&\n opt.label === b[i].label,\n );\n}\n\n/**\n * The universe of choices for one Select-filtered column.\n *\n * An explicit `options` filterParam always wins — INCLUDING an empty one,\n * which means \"this column has no facets\", not \"derive them for me\". Omit\n * `options` entirely and the list is DERIVED from the values the column\n * actually holds, and re-derived as the row data changes, so both the popup\n * panel and its floating-filter twin offer the same, data-accurate choices.\n */\nfunction useSelectFilterOptions(\n api: GridApi | undefined,\n options: SelectFilterOption[] | undefined,\n readValue: SelectValueReader,\n): SelectFilterOption[] {\n const explicit = options;\n const hasExplicit = explicit !== undefined;\n const [derived, setDerived] = useState<SelectFilterOption[]>([]);\n\n // Latest-reader ref so a new `getValue` identity per grid render does not\n // tear down and rebuild the grid event subscription below.\n const readValueRef = useRef(readValue);\n useEffect(() => {\n readValueRef.current = readValue;\n });\n\n useEffect(() => {\n if (hasExplicit || !api) return;\n const recompute = () => {\n setDerived((prev) => {\n const next = collectColumnOptions(api, readValueRef.current);\n return sameOptions(prev, next) ? prev : next;\n });\n };\n recompute();\n api.addEventListener('modelUpdated', recompute);\n api.addEventListener('cellValueChanged', recompute);\n return () => {\n if (api.isDestroyed()) return;\n api.removeEventListener('modelUpdated', recompute);\n api.removeEventListener('cellValueChanged', recompute);\n };\n }, [api, hasExplicit]);\n\n return explicit ?? derived;\n}\n\nexport function SelectFilter(\n props: CustomFilterProps<unknown, unknown, SelectFilterModel> &\n SelectFilterParams,\n) {\n const { model, onModelChange, getValue, api, options, placeholder } = props;\n const { t } = useTranslation('ui');\n\n const readValue = useCallback<SelectValueReader>(\n (node) => getValue(node) as unknown,\n [getValue],\n );\n const derivedOptions = useSelectFilterOptions(api, options, readValue);\n\n // Working set — checkboxes mutate `pending` only; we commit to the\n // grid via `onModelChange` when the user clicks Apply (or clears).\n const initialSelected = useMemo<Set<string>>(() => {\n const set = new Set<string>();\n const incoming = model?.values ?? [];\n for (const v of incoming) set.add(toValueKey(v));\n return set;\n }, [model]);\n\n const [pending, setPending] = useState<Set<string>>(initialSelected);\n\n // Sync local `pending` if the model changes externally (e.g. when AG\n // Grid pushes a reset). `model` is the dependency — Set instances are\n // compared by reference in React, so the memo above is sufficient.\n useEffect(() => {\n setPending(initialSelected);\n }, [initialSelected]);\n\n useGridFilter({\n doesFilterPass: (params) => {\n const active = model?.values;\n if (!active || active.length === 0) return true;\n const raw = getValue(params.node) as unknown;\n if (raw === null || raw === undefined) return false;\n const value: SelectFilterValue =\n typeof raw === 'string' || typeof raw === 'number' ? raw : String(raw);\n const key = toValueKey(value);\n return active.some((v) => toValueKey(v) === key);\n },\n });\n\n function toggle(optionKey: string) {\n setPending((prev) => {\n const next = new Set(prev);\n if (next.has(optionKey)) next.delete(optionKey);\n else next.add(optionKey);\n return next;\n });\n }\n\n function apply() {\n if (pending.size === 0) {\n onModelChange(null);\n return;\n }\n const values: SelectFilterValue[] = [];\n for (const opt of derivedOptions) {\n if (pending.has(toValueKey(opt.value))) values.push(opt.value);\n }\n // A ticked value can leave the data before Apply (the derived list is\n // live). Committing `values: []` would read as an active filter that\n // matches every row, so clear instead.\n if (values.length === 0) {\n onModelChange(null);\n return;\n }\n onModelChange({ type: 'set', values });\n }\n\n function clear() {\n setPending(new Set());\n onModelChange(null);\n }\n\n const placeholderLabel = placeholder ?? t('dataTable.selectFilter.all');\n\n return (\n <div\n data-component=\"select-filter\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)] ds:min-w-[200px] ds:max-w-[260px]\"\n >\n <ScrollArea orientation=\"vertical\" className=\"ds:max-h-[240px]\">\n <div\n role=\"group\"\n aria-label={placeholderLabel}\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\"\n >\n {derivedOptions.length === 0 ? (\n <p className=\"ds:text-[length:var(--font-size-sm)] ds:text-[var(--muted-foreground)] ds:py-[var(--spacing-xs)]\">\n {t('dataTable.agGrid.noRowsToShow')}\n </p>\n ) : (\n derivedOptions.map((option) => {\n const key = toValueKey(option.value);\n return (\n <Checkbox\n key={key}\n size=\"sm\"\n label={option.label}\n checked={pending.has(key)}\n onCheckedChange={() => toggle(key)}\n />\n );\n })\n )}\n </div>\n </ScrollArea>\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:justify-end ds:gap-[var(--spacing-xs)] ds:pt-[var(--spacing-xs)] ds:border-t ds:border-[var(--border)]\">\n <Button intent=\"ghost\" size=\"sm\" onClick={clear} type=\"button\">\n {t('dataTable.selectFilter.clear')}\n </Button>\n <Button intent=\"primary\" size=\"sm\" onClick={apply} type=\"button\">\n {t('dataTable.selectFilter.apply')}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Floating-filter companion for `SelectFilter`.\n *\n * Renders the kit's `<MultiSelect>` directly as the floating-filter\n * input — its built-in trigger + checkbox dropdown IS the filter UI.\n * Earlier versions wrapped MultiSelect in another `<Popover>`,\n * producing the \"click trigger → empty popover with another trigger →\n * click → checkbox list\" double-step that read as duplicated UI.\n *\n * MultiSelect's options use `string` values; we string-convert the\n * model's `(string | number)[]` for the trigger and parse back on\n * apply. The grid model still tracks the original primitive types so\n * `doesFilterPass` keeps matching numeric columns correctly.\n *\n * Choices come from the same `useSelectFilterOptions` universe the popup\n * panel uses: an explicit `options` filterParam if the consumer declared\n * one, otherwise the column's own distinct values. Reading only\n * `filterParams.options` used to leave the trigger empty beside a working\n * panel whenever the consumer relied on derivation.\n */\nexport function SelectFloatingFilter(\n props: CustomFloatingFilterProps<\n IFilter,\n unknown,\n unknown,\n SelectFilterModel\n >,\n) {\n const { model, onModelChange, column, api } = props;\n\n const colDef = column?.getColDef?.();\n const filterParams =\n (colDef?.filterParams as SelectFilterParams | undefined) ?? {};\n\n // The floating filter has no `getValue`; read through the grid instead.\n // A column with a `filterValueGetter` should declare `options` — the two\n // reads would otherwise disagree with the panel's.\n const readValue = useCallback<SelectValueReader>(\n (node) =>\n api && column\n ? (api.getCellValue<unknown>({\n rowNode: node,\n colKey: column,\n }) as unknown)\n : undefined,\n [api, column],\n );\n const availableOptions = useSelectFilterOptions(\n api,\n filterParams.options,\n readValue,\n );\n // Name the floating-filter trigger after its column so the per-column Select\n // filters are distinguishable to assistive tech — they otherwise all read as\n // the generic MultiSelect placeholder. An explicit `placeholder` wins.\n const accessibleLabel =\n filterParams.placeholder ??\n (typeof colDef?.headerName === 'string' ? colDef.headerName : undefined);\n\n // MultiSelect's `value` is `string[]`. SelectFilter's model carries\n // `(string | number)[]` so we string-convert in / out. Build a lookup\n // from the stringified key back to the original primitive so the\n // model retains the consumer's typing.\n const valueByKey = useMemo(() => {\n const map = new Map<string, SelectFilterValue>();\n for (const opt of availableOptions) map.set(String(opt.value), opt.value);\n return map;\n }, [availableOptions]);\n\n const selectOptions = useMemo(\n () =>\n availableOptions.map((opt) => ({\n value: String(opt.value),\n label: opt.label,\n })),\n [availableOptions],\n );\n\n const currentValue = useMemo(\n () => (model?.values ?? []).map((v) => String(v)),\n [model],\n );\n\n function handleChange(next: string[]) {\n if (next.length === 0) {\n onModelChange(null);\n return;\n }\n const values: SelectFilterValue[] = [];\n for (const k of next) {\n const original = valueByKey.get(k);\n if (original !== undefined) values.push(original);\n }\n // Same live-list guard as the panel's Apply: an empty set is a cleared\n // filter, never an active one that matches everything.\n if (values.length === 0) {\n onModelChange(null);\n return;\n }\n onModelChange({ type: 'set', values });\n }\n\n return (\n <div data-component=\"select-floating-filter\" className=\"ds:w-full\">\n <MultiSelect\n size=\"sm\"\n options={selectOptions}\n value={currentValue}\n onChange={handleChange}\n placeholder={filterParams.placeholder}\n aria-label={accessibleLabel}\n allowClear\n />\n </div>\n );\n}\n","import { useEffect, useMemo, useState } from 'react';\nimport type {\n CustomFilterProps,\n CustomFloatingFilterProps,\n} from 'ag-grid-react';\nimport { useGridFilter } from 'ag-grid-react';\nimport type { IFilter, IRowNode } from 'ag-grid-community';\nimport { useTranslation } from 'react-i18next';\nimport { Autocomplete } from '../../autocomplete';\nimport { Button } from '../../button';\nimport type { OptionShape } from '../../_shared/option';\n\n/**\n * Custom AG Grid filter component — single-select typeahead filter.\n *\n * Wraps the kit's existing `<Autocomplete>` so the user types to filter a\n * bounded-but-large set of values (e.g. patient names), picks one\n * suggestion, and the grid filters to rows matching that value exactly.\n *\n * Wire on a colDef:\n * ```tsx\n * {\n * field: 'patient',\n * filter: TypeaheadFilter,\n * filterParams: {\n * options: PATIENTS.map(p => ({ value: p.name, label: p.name })),\n * },\n * }\n * ```\n *\n * Model shape `{ type: 'equals', value: string }` matches AG Grid's\n * text-filter `equals` convention so server-side adapters can read either\n * implementation the same way.\n */\n\nexport interface TypeaheadFilterOption {\n value: string;\n label: string;\n}\n\nexport interface TypeaheadFilterModel {\n type: 'equals';\n value: string;\n}\n\nexport interface TypeaheadFilterParams {\n options?: TypeaheadFilterOption[];\n loadOptions?: (\n input: string,\n opts: { signal: AbortSignal; locale: string },\n ) => Promise<TypeaheadFilterOption[]>;\n placeholder?: string;\n}\n\nfunction normalise(s: string): string {\n return s.trim().toLocaleLowerCase();\n}\n\nexport function TypeaheadFilter(\n props: CustomFilterProps<unknown, unknown, TypeaheadFilterModel> &\n TypeaheadFilterParams,\n) {\n const {\n model,\n onModelChange,\n getValue,\n api,\n column,\n options,\n loadOptions,\n placeholder,\n } = props;\n const { t } = useTranslation('ui');\n\n // Universe of choices. Prefer explicit `options`; fall back to the\n // column's distinct values when neither `options` nor `loadOptions` is\n // supplied. Same shape as SelectFilter's derivation so the two filters\n // present a consistent experience when consumers don't enumerate.\n const derivedOptions = useMemo<TypeaheadFilterOption[]>(() => {\n if (options && options.length > 0) return options;\n if (!api || !column) return [];\n const seen = new Map<string, TypeaheadFilterOption>();\n api.forEachNode((node: IRowNode) => {\n const raw = getValue(node) as unknown;\n if (raw === null || raw === undefined) return;\n const value = typeof raw === 'string' ? raw : String(raw);\n if (!seen.has(value)) {\n seen.set(value, { value, label: value });\n }\n });\n return Array.from(seen.values()).sort((a, b) =>\n a.label.localeCompare(b.label),\n );\n }, [options, api, column, getValue]);\n\n // Build the async `loadOptions` adapter that <Autocomplete> consumes.\n // Local-options path filters the snapshot synchronously and wraps it\n // in Promise.resolve(); explicit `loadOptions` is passed through.\n const adapterLoadOptions = useMemo(() => {\n return async (\n query: string,\n opts: { signal: AbortSignal; locale: string },\n ): Promise<OptionShape[]> => {\n if (loadOptions) {\n const result = await loadOptions(query, opts);\n return result.map((o) => ({ value: o.value, label: o.label }));\n }\n const q = normalise(query);\n const filtered = q\n ? derivedOptions.filter((o) => normalise(o.label).includes(q))\n : derivedOptions;\n return filtered\n .slice(0, 50)\n .map((o) => ({ value: o.value, label: o.label }));\n };\n }, [loadOptions, derivedOptions]);\n\n const [draft, setDraft] = useState<string>(model?.value ?? '');\n\n useEffect(() => {\n setDraft(model?.value ?? '');\n }, [model?.value]);\n\n useGridFilter({\n doesFilterPass: (params) => {\n const target = model?.value;\n if (!target) return true;\n const raw = getValue(params.node) as unknown;\n if (raw === null || raw === undefined) return false;\n const value = typeof raw === 'string' ? raw : String(raw);\n return normalise(value) === normalise(target);\n },\n });\n\n function handleSelect(option: OptionShape) {\n // Autocomplete itself commits `option.label` to the input value; we\n // mirror that here so the displayed text matches what the user just\n // picked, even when label and value diverge (e.g. id vs name).\n setDraft(option.label);\n onModelChange({ type: 'equals', value: option.value });\n }\n\n function handleChange(next: string) {\n setDraft(next);\n // Clear the applied model when the user empties the input so the\n // grid stops filtering as soon as the field is blank.\n if (next === '' && model) onModelChange(null);\n }\n\n function clear() {\n setDraft('');\n onModelChange(null);\n }\n\n const placeholderLabel =\n placeholder ?? t('dataTable.typeaheadFilter.placeholder');\n\n return (\n <div\n data-component=\"typeahead-filter\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)] ds:min-w-[240px]\"\n >\n <Autocomplete\n size=\"sm\"\n value={draft}\n onChange={handleChange}\n onSelect={handleSelect}\n loadOptions={adapterLoadOptions}\n placeholder={placeholderLabel}\n aria-label={placeholderLabel}\n />\n <div className=\"ds:flex ds:items-center ds:justify-end ds:pt-[var(--spacing-xs)] ds:border-t ds:border-[var(--border)]\">\n <Button intent=\"ghost\" size=\"sm\" onClick={clear} type=\"button\">\n {t('dataTable.typeaheadFilter.clear')}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Floating-filter companion for `TypeaheadFilter`.\n *\n * Renders the kit's `<Autocomplete>` directly as the floating-filter\n * input — its built-in text input + portaled dropdown IS the filter\n * UI. Earlier versions wrapped Autocomplete in a second `<Popover>`,\n * producing the \"click trigger → popover with another search input →\n * type → list appears\" double-step that read as duplicated UI.\n */\nexport function TypeaheadFloatingFilter(\n props: CustomFloatingFilterProps<\n IFilter,\n unknown,\n unknown,\n TypeaheadFilterModel\n >,\n) {\n const { model, onModelChange, column } = props;\n const { t } = useTranslation('ui');\n\n const filterParams =\n (column?.getColDef?.()?.filterParams as\n | TypeaheadFilterParams\n | undefined) ?? {};\n const availableOptions = filterParams.options ?? [];\n const loadOptions = filterParams.loadOptions;\n const placeholderLabel =\n filterParams.placeholder ?? t('dataTable.typeaheadFilter.placeholder');\n\n const adapterLoadOptions = useMemo(() => {\n return async (\n query: string,\n opts: { signal: AbortSignal; locale: string },\n ): Promise<OptionShape[]> => {\n if (loadOptions) {\n const result = await loadOptions(query, opts);\n return result.map((o) => ({ value: o.value, label: o.label }));\n }\n const q = normalise(query);\n const filtered = q\n ? availableOptions.filter((o) => normalise(o.label).includes(q))\n : availableOptions;\n return filtered\n .slice(0, 50)\n .map((o) => ({ value: o.value, label: o.label }));\n };\n }, [loadOptions, availableOptions]);\n\n // Track the input's display value separately from the applied model.\n // The user can type freely; we only apply when they pick an option\n // from the dropdown (committing a known value to the model). Clearing\n // the input clears the filter.\n const [draft, setDraft] = useState<string>(model?.value ?? '');\n useEffect(() => {\n setDraft(model?.value ?? '');\n }, [model?.value]);\n\n function handleSelect(option: OptionShape) {\n setDraft(option.label);\n onModelChange({ type: 'equals', value: option.value });\n }\n\n function handleChange(next: string) {\n setDraft(next);\n if (next === '' && model) onModelChange(null);\n }\n\n return (\n <div data-component=\"typeahead-floating-filter\" className=\"ds:w-full\">\n <Autocomplete\n size=\"sm\"\n value={draft}\n onChange={handleChange}\n onSelect={handleSelect}\n loadOptions={adapterLoadOptions}\n placeholder={placeholderLabel}\n aria-label={placeholderLabel}\n />\n </div>\n );\n}\n","import { useEffect, useMemo, useRef, useState } from 'react';\nimport type {\n CustomFilterProps,\n CustomFloatingFilterProps,\n} from 'ag-grid-react';\nimport { useGridFilter } from 'ag-grid-react';\nimport type { IFilter } from 'ag-grid-community';\nimport { useTranslation } from 'react-i18next';\nimport { NumberInput } from '../../number-input';\nimport { Select } from '../../select';\nimport { Button } from '../../button';\n\n/**\n * Custom AG Grid filter component for numeric columns. AG Grid Community's\n * built-in `agNumberColumnFilter` paints a stock browser-skinned\n * `<input type=\"number\">` that does not match the kit's form language —\n * this wraps the DS `<NumberInput>` + `<Select>` so totals, prices,\n * quantities, etc. line up visually with neighbouring DS-styled cells.\n *\n * Wire on a colDef:\n * ```tsx\n * {\n * field: 'total',\n * filter: NumberFilter,\n * floatingFilterComponent: NumberFloatingFilter,\n * filterParams: { defaultOperator: 'greaterThan', min: 0 },\n * }\n * ```\n *\n * The full-popover variant exposes the operator dropdown (equals,\n * greaterThan, inRange, blank, …). The floating-filter row follows the\n * applied operator, or `defaultOperator` when no filter is applied: one\n * input for most operators, a from/to pair for `inRange`. Either bound may\n * be empty (from-only means \"≥ from\", to-only \"≤ to\"). Both variants speak\n * the same `NumberFilterModel` so server-side adapters can read either.\n *\n * Model shape `{ type, filter?, filterTo? }` matches AG Grid's own\n * `agNumberColumnFilter` vocabulary so adapters can interchange.\n */\n\nexport type NumberFilterOperator =\n | 'equals'\n | 'notEqual'\n | 'greaterThan'\n | 'greaterThanOrEqual'\n | 'lessThan'\n | 'lessThanOrEqual'\n | 'inRange'\n | 'blank'\n | 'notBlank';\n\nexport interface NumberFilterModel {\n type: NumberFilterOperator;\n /** Lower bound or comparison value. Optional, as in AG Grid's own model,\n * so an `inRange` model can carry only `filterTo` (\"≤ to\"). */\n filter?: number;\n filterTo?: number;\n}\n\nexport interface NumberFilterParams {\n defaultOperator?: NumberFilterOperator;\n min?: number;\n max?: number;\n step?: number;\n placeholder?: string;\n}\n\nconst ALL_OPERATORS: NumberFilterOperator[] = [\n 'equals',\n 'notEqual',\n 'greaterThan',\n 'greaterThanOrEqual',\n 'lessThan',\n 'lessThanOrEqual',\n 'inRange',\n 'blank',\n 'notBlank',\n];\n\nfunction operatorTakesValue(op: NumberFilterOperator): boolean {\n return op !== 'blank' && op !== 'notBlank';\n}\n\nfunction operatorTakesRange(op: NumberFilterOperator): boolean {\n return op === 'inRange';\n}\n\n/**\n * The predicate behind both the popover and the floating row. Exported for\n * unit tests only; not re-exported from the data-table barrel.\n */\nexport function numberFilterPasses(\n op: NumberFilterOperator,\n cell: number | null,\n primary: number | null,\n secondary: number | null,\n): boolean {\n if (op === 'blank') return cell === null;\n if (op === 'notBlank') return cell !== null;\n if (cell === null) return false;\n // Before the \"no primary → pass\" bail-out: a range may carry only `filterTo`.\n if (op === 'inRange') {\n if (primary === null) return secondary === null || cell <= secondary;\n if (secondary === null) return cell >= primary;\n // No min/max swap: an inverted range matches nothing, as it does in\n // agNumberColumnFilter and SQL `BETWEEN 100 AND 50`, and as the chip shows.\n return cell >= primary && cell <= secondary;\n }\n if (primary === null) return true;\n switch (op) {\n case 'equals':\n return cell === primary;\n case 'notEqual':\n return cell !== primary;\n case 'greaterThan':\n return cell > primary;\n case 'greaterThanOrEqual':\n return cell >= primary;\n case 'lessThan':\n return cell < primary;\n case 'lessThanOrEqual':\n return cell <= primary;\n default:\n return true;\n }\n}\n\nfunction nonEmpty(value: unknown): string | undefined {\n return typeof value === 'string' && value.trim() !== '' ? value : undefined;\n}\n\nfunction coerceCell(raw: unknown): number | null {\n if (raw === null || raw === undefined || raw === '') return null;\n const n = typeof raw === 'number' ? raw : Number(raw);\n return Number.isNaN(n) ? null : n;\n}\n\nexport function NumberFilter(\n props: CustomFilterProps<unknown, unknown, NumberFilterModel> &\n NumberFilterParams,\n) {\n const {\n model,\n onModelChange,\n getValue,\n defaultOperator,\n min,\n max,\n step,\n placeholder,\n } = props;\n const { t } = useTranslation('ui');\n\n const initialOperator: NumberFilterOperator =\n model?.type ?? defaultOperator ?? 'equals';\n const [operator, setOperator] =\n useState<NumberFilterOperator>(initialOperator);\n const [primary, setPrimary] = useState<number | null>(model?.filter ?? null);\n const [secondary, setSecondary] = useState<number | null>(\n model?.filterTo ?? null,\n );\n\n // If AG Grid pushes an externally-cleared / reset model, mirror it in\n // local state so the UI stays consistent with the applied filter. The\n // cleared model arrives as null OR undefined (removed from a setFilterModel\n // map), so a loose check is load-bearing here.\n useEffect(() => {\n if (model == null) {\n setOperator(defaultOperator ?? 'equals');\n setPrimary(null);\n setSecondary(null);\n return;\n }\n setOperator(model.type);\n setPrimary(model.filter ?? null);\n setSecondary(model.filterTo ?? null);\n }, [model, defaultOperator]);\n\n useGridFilter({\n doesFilterPass: (params) => {\n if (!model) return true;\n const cell = coerceCell(getValue(params.node));\n return numberFilterPasses(\n model.type,\n cell,\n model.filter ?? null,\n model.filterTo ?? null,\n );\n },\n });\n\n const operatorOptions = useMemo(\n () =>\n ALL_OPERATORS.map((op) => ({\n value: op,\n label: t(`dataTable.numberFilter.operators.${op}`),\n })),\n [t],\n );\n\n const placeholderLabel =\n placeholder ?? t('dataTable.numberFilter.placeholder');\n\n function apply() {\n if (!operatorTakesValue(operator)) {\n onModelChange({ type: operator, filter: 0 });\n return;\n }\n // Above the empty-primary guard: a to-only range (\"≤ 9\") has no `filter`.\n if (operatorTakesRange(operator)) {\n if (primary === null && secondary === null) {\n onModelChange(null);\n return;\n }\n onModelChange({\n type: operator,\n filter: primary ?? undefined,\n filterTo: secondary ?? undefined,\n });\n return;\n }\n if (primary === null) {\n onModelChange(null);\n return;\n }\n onModelChange({ type: operator, filter: primary });\n }\n\n function clear() {\n setOperator(defaultOperator ?? 'equals');\n setPrimary(null);\n setSecondary(null);\n onModelChange(null);\n }\n\n const showValue = operatorTakesValue(operator);\n const showRange = operatorTakesRange(operator);\n\n return (\n <div\n data-component=\"number-filter\"\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)] ds:min-w-[240px]\"\n >\n <Select\n size=\"sm\"\n options={operatorOptions}\n value={operator}\n onValueChange={(next) => {\n if (next === '') return;\n setOperator(next as NumberFilterOperator);\n }}\n aria-label={t('dataTable.numberFilter.operatorLabel')}\n />\n {showValue && !showRange && (\n <NumberInput\n size=\"sm\"\n mode=\"decimal\"\n value={primary}\n onChange={setPrimary}\n min={min}\n max={max}\n step={step}\n placeholder={placeholderLabel}\n aria-label={placeholderLabel}\n />\n )}\n {showRange && (\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n <NumberInput\n size=\"sm\"\n mode=\"decimal\"\n value={primary}\n onChange={setPrimary}\n min={min}\n max={max}\n step={step}\n placeholder={t('dataTable.numberFilter.from')}\n aria-label={t('dataTable.numberFilter.from')}\n />\n <NumberInput\n size=\"sm\"\n mode=\"decimal\"\n value={secondary}\n onChange={setSecondary}\n min={min}\n max={max}\n step={step}\n placeholder={t('dataTable.numberFilter.to')}\n aria-label={t('dataTable.numberFilter.to')}\n />\n </div>\n )}\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:justify-end ds:gap-[var(--spacing-xs)] ds:pt-[var(--spacing-xs)] ds:border-t ds:border-[var(--border)]\">\n <Button intent=\"ghost\" size=\"sm\" onClick={clear} type=\"button\">\n {t('dataTable.numberFilter.clear')}\n </Button>\n <Button intent=\"primary\" size=\"sm\" onClick={apply} type=\"button\">\n {t('dataTable.numberFilter.apply')}\n </Button>\n </div>\n </div>\n );\n}\n\n/**\n * Floating-filter companion for `NumberFilter`.\n *\n * Follows the APPLIED operator, falling back to `defaultOperator` (or\n * `'equals'`) when no filter is applied. Emptying the row keeps the operator\n * it was editing, so retyping does not switch to the default; only an\n * external clear (chip remove, header Clear, `setFilterModel`) returns to it,\n * as with AG Grid's own floating filter. `inRange` renders a compact from/to\n * pair; either bound may stay empty, and clearing both commits `null`.\n * Every other value operator renders one input. `blank` / `notBlank` take no\n * value, so the input is disabled and names the operator. The operator\n * dropdown lives only in the full popover, as with `agNumberColumnFilter`.\n *\n * One 200 ms debounce covers both bounds, so each keystroke does not re-run\n * the grid filter, and an invalid number never reaches the model as `NaN`.\n * Every input, here and in the popover, is `mode=\"decimal\"`: the integer\n * default showed 0.01 as \"0\" once blurred, while the filter compared 0.01.\n */\nexport function NumberFloatingFilter(\n props: CustomFloatingFilterProps<\n IFilter,\n unknown,\n unknown,\n NumberFilterModel\n >,\n) {\n const { model, onModelChange, column, api } = props;\n const { t } = useTranslation('ui');\n\n const colDef = column?.getColDef?.();\n const filterParams =\n (colDef?.filterParams as NumberFilterParams | undefined) ?? {};\n // The operator the row was editing when it emptied itself. The `null`\n // model that comes back must not drop it: \"> 30\" retyped as \"40\" would\n // otherwise commit \"= 40\". Any non-null model releases it.\n const [heldOperator, setHeldOperator] = useState<NumberFilterOperator | null>(\n null,\n );\n // The applied operator wins. Reading only the default turned a popover\n // \"≤ 100\" on an inRange column into \"From 100\", then into a range as soon\n // as the other box was typed in.\n const operator: NumberFilterOperator =\n model?.type ?? heldOperator ?? filterParams.defaultOperator ?? 'equals';\n const isRange = operatorTakesRange(operator);\n const takesValue = operatorTakesValue(operator);\n const placeholderLabel =\n filterParams.placeholder ?? t('dataTable.numberFilter.placeholder');\n // AG Grid gives a floating filter no aria-labelledby to its header, so name\n // each input after its column: two such columns would otherwise put two\n // identical boxes in one row. The grid's display name also covers\n // field-only and headerValueGetter columns. The placeholder stays short.\n const columnName =\n nonEmpty(column ? api?.getDisplayNameForColumn(column, 'header') : null) ??\n nonEmpty(colDef?.headerName);\n const fromPlaceholder = t('dataTable.numberFilter.from');\n const toPlaceholder = t('dataTable.numberFilter.to');\n const fromLabel = columnName\n ? t('dataTable.numberFilter.columnFrom', { column: columnName })\n : fromPlaceholder;\n const toLabel = columnName\n ? t('dataTable.numberFilter.columnTo', { column: columnName })\n : toPlaceholder;\n const valueLabel = columnName\n ? t('dataTable.numberFilter.columnFilter', { column: columnName })\n : placeholderLabel;\n\n const [from, setFrom] = useState<number | null>(model?.filter ?? null);\n const [to, setTo] = useState<number | null>(model?.filterTo ?? null);\n // The bounds this row last committed. The grid echoes them back a render\n // or two later, by which time the other box may hold newer typing.\n const pendingEcho = useRef<{ from: number | null; to: number | null } | null>(\n null,\n );\n\n // Mirror an external change (header-menu Clear, chip remove, popover Apply,\n // setFilterModel) into both bounds. The echo of this row's own commit is\n // not one: mirroring it would wipe a bound typed while it was on its way.\n useEffect(() => {\n const next = { from: model?.filter ?? null, to: model?.filterTo ?? null };\n const echo = pendingEcho.current;\n pendingEcho.current = null;\n if (echo && echo.from === next.from && echo.to === next.to) return;\n setFrom(next.from);\n setTo(next.to);\n }, [model?.filter, model?.filterTo]);\n\n // A non-null model releases the held operator, so a later external clear\n // returns the row to the column default.\n useEffect(() => {\n if (model != null) setHeldOperator(null);\n }, [model]);\n\n // Debounced commit. A useEffect + setTimeout is cheaper than importing a\n // hook, and AG Grid only re-renders this floating filter per keystroke.\n useEffect(() => {\n if (!takesValue) return;\n if (from === (model?.filter ?? null) && to === (model?.filterTo ?? null)) {\n return;\n }\n const handle = setTimeout(() => {\n const lo = from === null || Number.isNaN(from) ? null : from;\n const hi = to === null || Number.isNaN(to) ? null : to;\n const commit = (next: NumberFilterModel | null) => {\n pendingEcho.current = {\n from: next?.filter ?? null,\n to: next?.filterTo ?? null,\n };\n onModelChange(next);\n };\n // The row emptied itself: keep its operator for the next value.\n const clearFromRow = () => {\n setHeldOperator(operator);\n commit(null);\n };\n if (!isRange) {\n if (lo === null) clearFromRow();\n else commit({ type: operator, filter: lo });\n return;\n }\n if (lo === null && hi === null) {\n clearFromRow();\n return;\n }\n commit({\n type: 'inRange',\n filter: lo ?? undefined,\n filterTo: hi ?? undefined,\n });\n }, 200);\n return () => clearTimeout(handle);\n // `model` intentionally excluded — we only react to user edits. Model\n // changes sync via the effect above.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [from, to, operator, isRange, takesValue]);\n\n if (!takesValue) {\n const operatorLabel = t(`dataTable.numberFilter.operators.${operator}`);\n return (\n <div data-component=\"number-floating-filter\" className=\"ds:w-full\">\n <NumberInput\n size=\"sm\"\n variant=\"plain\"\n value={null}\n disabled\n placeholder={operatorLabel}\n aria-label={\n columnName\n ? t('dataTable.numberFilter.columnOperator', {\n column: columnName,\n operator: operatorLabel,\n })\n : operatorLabel\n }\n />\n </div>\n );\n }\n\n if (!isRange) {\n return (\n <div data-component=\"number-floating-filter\" className=\"ds:w-full\">\n <NumberInput\n size=\"sm\"\n mode=\"decimal\"\n value={from}\n onChange={setFrom}\n min={filterParams.min}\n max={filterParams.max}\n step={filterParams.step}\n placeholder={placeholderLabel}\n aria-label={valueLabel}\n />\n </div>\n );\n }\n\n // `variant=\"plain\"` drops the stepper chevrons, which would take most of a\n // 150px column. They are tabIndex={-1}, so no keyboard path is lost, and\n // arrow keys still step. Flex + gap is direction-agnostic, so RTL flips.\n return (\n <div\n data-component=\"number-floating-filter\"\n className=\"ds:flex ds:w-full ds:items-center ds:gap-[var(--spacing-xs)]\"\n >\n <NumberInput\n size=\"sm\"\n variant=\"plain\"\n mode=\"decimal\"\n className=\"ds:min-w-0 ds:flex-1\"\n value={from}\n onChange={setFrom}\n min={filterParams.min}\n max={filterParams.max}\n step={filterParams.step}\n placeholder={fromPlaceholder}\n aria-label={fromLabel}\n />\n <NumberInput\n size=\"sm\"\n variant=\"plain\"\n mode=\"decimal\"\n className=\"ds:min-w-0 ds:flex-1\"\n value={to}\n onChange={setTo}\n min={filterParams.min}\n max={filterParams.max}\n step={filterParams.step}\n placeholder={toPlaceholder}\n aria-label={toLabel}\n />\n </div>\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { Badge } from '../../badge/badge';\n\nexport type BadgeVariant = 'neutral' | 'info' | 'success' | 'warning' | 'error';\n\nexport interface StatusCellRendererParams {\n variantMap?: Record<string, BadgeVariant>;\n}\n\nexport function StatusCellRenderer(\n props: CustomCellRendererProps & StatusCellRendererParams,\n) {\n const { value, variantMap } = props;\n const variant: BadgeVariant = variantMap?.[value as string] ?? 'neutral';\n return (\n <Badge variant={variant} withDot size=\"sm\">\n {String(value ?? '')}\n </Badge>\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { Avatar } from '../../avatar/avatar';\n\nexport interface UserCellValue {\n name: string;\n src?: string;\n}\n\nexport function UserCellRenderer(\n props: CustomCellRendererProps<unknown, UserCellValue>,\n) {\n const { value } = props;\n if (!value) return null;\n return (\n <span className=\"ds:inline-flex ds:items-center ds:gap-[var(--spacing-sm)]\">\n <Avatar name={value.name} src={value.src} size=\"sm\" />\n <span>{value.name}</span>\n </span>\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { Avatar } from '../../avatar/avatar';\n\nexport interface ImageCellRendererParams {\n /** Field name on the row whose value holds the image URL. */\n srcField: string;\n /** Optional field name holding alt text. Falls back to '' (decorative). */\n altField?: string;\n /**\n * Optional field name holding a name string. When the src URL is missing or\n * rejected, the cell falls back to `<Avatar name={fallback}>` so the cell\n * still has a visual.\n */\n fallbackField?: string;\n /** Visual size of the image. Matches `<Avatar>` sizes (sm=32, md=40, lg=48). */\n size?: 'sm' | 'md' | 'lg';\n /** Corner radius preset. `circle` matches `<Avatar>`. */\n shape?: 'square' | 'rounded' | 'circle';\n}\n\nconst SIZE_CLASS: Record<\n NonNullable<ImageCellRendererParams['size']>,\n string\n> = {\n sm: 'ds:size-8',\n md: 'ds:size-10',\n lg: 'ds:size-12',\n};\n\nconst SHAPE_CLASS: Record<\n NonNullable<ImageCellRendererParams['shape']>,\n string\n> = {\n square: 'ds:rounded-none',\n rounded: 'ds:rounded-[var(--radius-md)]',\n circle: 'ds:rounded-[var(--radius-full)]',\n};\n\nfunction readField(row: unknown, field: string): string | undefined {\n if (!row || typeof row !== 'object') return undefined;\n const value = (row as Record<string, unknown>)[field];\n return typeof value === 'string' ? value : undefined;\n}\n\n// Accept http(s), image data: URLs, and same-origin absolute paths. Reject\n// `javascript:` / `vbscript:` / any other smuggled scheme. Browsers won't\n// execute non-image data: URLs in `<img>`, but rejecting them in JS gives a\n// single audit point.\n//\n// A leading `/` cannot carry a scheme, so a root-relative path is at least as\n// safe as an absolute URL — and it is what an app serving its own images\n// naturally produces. `//host/x` IS excluded: protocol-relative URLs are\n// cross-origin, which is the thing this guard exists to control.\nconst SAFE_SRC_RE = /^(?:https?:|data:image\\/|\\/(?!\\/))/i;\n\nfunction sanitizeSrc(raw: string | undefined): string | undefined {\n if (!raw) return undefined;\n const trimmed = raw.trim();\n if (trimmed.length === 0) return undefined;\n return SAFE_SRC_RE.test(trimmed) ? trimmed : undefined;\n}\n\nexport function ImageCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & ImageCellRendererParams,\n) {\n const {\n data,\n srcField,\n altField,\n fallbackField,\n size = 'md',\n shape = 'rounded',\n } = props;\n\n if (!data) return null;\n\n const rawSrc = readField(data, srcField);\n const src = sanitizeSrc(rawSrc);\n const alt = altField ? (readField(data, altField) ?? '') : '';\n const fallbackName = fallbackField\n ? readField(data, fallbackField)\n : undefined;\n\n // A circular image with a name is a person: let <Avatar> own it. It paints the\n // initials first, covers them once the photo decodes, and drops the <img> on\n // error so the initials persist — instead of a blank cell that later pops.\n if (shape === 'circle' && fallbackName) {\n return <Avatar src={src} name={fallbackName} size={size} />;\n }\n\n if (!src) {\n if (fallbackName) {\n return <Avatar name={fallbackName} size={size} />;\n }\n return null;\n }\n\n return (\n <img\n src={src}\n alt={alt}\n loading=\"lazy\"\n decoding=\"async\"\n className={['ds:object-cover', SIZE_CLASS[size], SHAPE_CLASS[shape]].join(\n ' ',\n )}\n />\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { useTranslation } from 'react-i18next';\nimport { Tag } from '../../tag/tag';\nimport { Tooltip } from '../../tooltip';\n\nexport interface TagListCellRendererParams {\n maxVisible?: number;\n}\n\nexport function TagListCellRenderer(\n props: CustomCellRendererProps<unknown, string[]> & TagListCellRendererParams,\n) {\n const { value, maxVisible = 3 } = props;\n const { t } = useTranslation('ui');\n\n if (!Array.isArray(value) || value.length === 0) return null;\n\n const visible = value.slice(0, maxVisible);\n const overflow = value.length - maxVisible;\n\n return (\n <span className=\"ds:inline-flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-xs)]\">\n {visible.map((tag) => (\n <Tag key={tag} label={tag} size=\"sm\" />\n ))}\n {overflow > 0 && (\n <Tooltip label={value.slice(maxVisible).join(', ')}>\n <Tag\n label={t('inputs.multiSelect.overflow', { count: overflow })}\n size=\"sm\"\n variant=\"neutral\"\n fill=\"outline\"\n />\n </Tooltip>\n )}\n </span>\n );\n}\n","import type { CustomCellRendererProps } from 'ag-grid-react';\nimport { Timestamp } from '../../timestamp';\nimport { fromIsoDate, isCalendarDay } from '../calendar-day';\n\nexport type DateCellFormat = 'date' | 'time' | 'datetime' | 'relative';\n\nexport interface DateCellRendererParams {\n /** Which preset to use. Default `'date'`. */\n format?: DateCellFormat;\n /** Escape hatch — overrides the preset entirely. */\n options?: Intl.DateTimeFormatOptions;\n}\n\nconst PRESETS: Record<\n Exclude<DateCellFormat, 'relative'>,\n Intl.DateTimeFormatOptions\n> = {\n date: { year: 'numeric', month: 'short', day: 'numeric' },\n time: { hour: '2-digit', minute: '2-digit' },\n datetime: {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n },\n};\n\nexport function DateCellRenderer(\n props: CustomCellRendererProps & DateCellRendererParams,\n) {\n const { value, format = 'date', options } = props;\n if (value == null || value === '') return null;\n\n const calendarDay = isCalendarDay(value);\n\n // `shape=\"bare\"` keeps the cell font inherited from --ag-font-size. Timestamp\n // still emits a proper `<time dateTime>` for assistive tech and feeds.\n //\n // A relative reading (\"3 days ago\") is about the viewer's own day, so a bare\n // date is anchored to LOCAL midnight here.\n if (format === 'relative' && !options) {\n const relativeValue = calendarDay ? (fromIsoDate(value) ?? value) : value;\n return <Timestamp value={relativeValue as string | Date} shape=\"bare\" />;\n }\n\n const absoluteFormat =\n options ?? PRESETS[format === 'relative' ? 'date' : format];\n\n return (\n <Timestamp\n value={value as string | Date}\n format=\"absolute\"\n shape=\"bare\"\n // A bare `YYYY-MM-DD` is a calendar day and carries no instant, so it is\n // read AND written in UTC: it then renders the day it was written with in\n // every browser zone, and under any `timeZone` the caller names. Anchoring\n // it to a real zone instead would move the day for readers on one side —\n // local midnight loses a day west of UTC, UTC midnight loses one east of\n // the named zone. Values carrying a time are instants and keep the\n // caller's options untouched.\n absoluteFormat={\n calendarDay ? { ...absoluteFormat, timeZone: 'UTC' } : absoluteFormat\n }\n />\n );\n}\n","import type { MouseEvent } from 'react';\nimport type { CustomCellRendererProps } from 'ag-grid-react';\n\ntype Getter<T, TData> = T | ((data: TData) => T | undefined);\n\nexport interface LinkCellRendererParams<TData = unknown> {\n /** Anchor href — or a function that derives it from the row. */\n href?: Getter<string, TData>;\n /** Fallback / additional onClick. Prevents default when provided without href. */\n onClick?: (data: TData) => void;\n /** Small text rendered below the link — supports a row-aware function. */\n secondary?: Getter<string, TData>;\n}\n\nfunction resolve<T, TData>(\n source: Getter<T, TData> | undefined,\n data: TData,\n): T | undefined {\n if (typeof source === 'function') {\n return (source as (data: TData) => T | undefined)(data);\n }\n return source;\n}\n\nfunction safeHref(href: string): string {\n return /^(https?:\\/\\/|\\/|#|mailto:|tel:)/i.test(href) ? href : '#';\n}\n\nexport function LinkCellRenderer<TData = unknown>(\n props: CustomCellRendererProps<TData> & LinkCellRendererParams<TData>,\n) {\n const { value, data, href, onClick, secondary } = props;\n if (!data) return null;\n\n const resolvedHref = resolve(href, data);\n const resolvedSecondary = resolve(secondary, data);\n const content = value == null || value === '' ? '' : String(value);\n\n const linkClasses = [\n 'ds:text-[color:var(--primary)]',\n 'ds:hover:underline',\n 'ds:focus-visible:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:outline-solid',\n 'ds:focus-visible:outline-[color:var(--ring)]',\n 'ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:rounded-[var(--radius-sm)]',\n ].join(' ');\n\n const handleClick = (event: MouseEvent) => {\n if (!onClick) return;\n if (!resolvedHref) event.preventDefault();\n event.stopPropagation();\n onClick(data);\n };\n\n return (\n <span className=\"ds:flex ds:flex-col ds:leading-tight\">\n {resolvedHref ? (\n <a\n href={safeHref(resolvedHref)}\n onClick={handleClick}\n className={linkClasses}\n >\n {content}\n </a>\n ) : (\n <button\n type=\"button\"\n onClick={handleClick}\n className={[\n 'ds:appearance-none ds:bg-transparent ds:p-0 ds:text-start',\n linkClasses,\n ].join(' ')}\n >\n {content}\n </button>\n )}\n {resolvedSecondary ? (\n <span className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {resolvedSecondary}\n </span>\n ) : null}\n </span>\n );\n}\n"],"names":["DATE_ONLY","ISO_DAY_PREFIX","toIsoDate","d","y","m","day","isCalendarDay","s","fromIsoDate","dayOf","cellValue","prefix","dayInRange","dateFrom","dateTo","DateRangeFilter","props","model","onModelChange","getValue","doesRowPassOtherFilter","filterParams","_a","range","setRange","useState","useEffect","useGridFilter","params","apply","next","jsx","DateRangePicker","DateRangeFloatingFilter","column","_b","toValueKey","v","LABEL_COLLATOR","collectColumnOptions","api","readValue","seen","node","raw","value","key","b","sameOptions","a","opt","i","useSelectFilterOptions","options","explicit","hasExplicit","derived","setDerived","readValueRef","useRef","recompute","prev","SelectFilter","placeholder","t","useTranslation","useCallback","derivedOptions","initialSelected","useMemo","set","incoming","pending","setPending","active","toggle","optionKey","values","clear","placeholderLabel","jsxs","ScrollArea","option","Checkbox","Button","SelectFloatingFilter","colDef","availableOptions","accessibleLabel","valueByKey","map","selectOptions","currentValue","handleChange","k","original","MultiSelect","normalise","TypeaheadFilter","loadOptions","adapterLoadOptions","query","opts","o","q","draft","setDraft","target","handleSelect","Autocomplete","TypeaheadFloatingFilter","ALL_OPERATORS","operatorTakesValue","op","operatorTakesRange","numberFilterPasses","cell","primary","secondary","nonEmpty","coerceCell","n","NumberFilter","defaultOperator","min","max","step","initialOperator","operator","setOperator","setPrimary","setSecondary","operatorOptions","showValue","showRange","Select","NumberInput","NumberFloatingFilter","heldOperator","setHeldOperator","isRange","takesValue","columnName","fromPlaceholder","toPlaceholder","fromLabel","toLabel","valueLabel","from","setFrom","to","setTo","pendingEcho","echo","handle","lo","hi","commit","clearFromRow","operatorLabel","StatusCellRenderer","variantMap","variant","Badge","UserCellRenderer","Avatar","SIZE_CLASS","SHAPE_CLASS","readField","row","field","SAFE_SRC_RE","sanitizeSrc","trimmed","ImageCellRenderer","data","srcField","altField","fallbackField","size","shape","rawSrc","src","alt","fallbackName","TagListCellRenderer","maxVisible","visible","overflow","tag","Tag","Tooltip","PRESETS","DateCellRenderer","format","calendarDay","relativeValue","Timestamp","absoluteFormat","resolve","source","safeHref","href","LinkCellRenderer","onClick","resolvedHref","resolvedSecondary","content","linkClasses","handleClick","event"],"mappings":"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"}
|