@alfadocs/ui-kit-debug 0.25.0 → 0.25.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_chunks/{agenda-card-BmpaUG1h.js → agenda-card-CznB7K8e.js} +2 -2
- package/dist/_chunks/{agenda-card-BmpaUG1h.js.map → agenda-card-CznB7K8e.js.map} +1 -1
- package/dist/_chunks/{agenda-tray-DiInnVqk.js → agenda-tray-C_bha7oK.js} +4 -4
- package/dist/_chunks/{agenda-tray-DiInnVqk.js.map → agenda-tray-C_bha7oK.js.map} +1 -1
- package/dist/_chunks/{ai-prompt-input-B5MdixzR.js → ai-prompt-input-Bka3jX3i.js} +2 -2
- package/dist/_chunks/{ai-prompt-input-B5MdixzR.js.map → ai-prompt-input-Bka3jX3i.js.map} +1 -1
- package/dist/_chunks/{alia-sidebar-CUi2UCbY.js → alia-sidebar-CnvXq95r.js} +92 -109
- package/dist/_chunks/alia-sidebar-CnvXq95r.js.map +1 -0
- package/dist/_chunks/{audio-recorder-D4xM3H5i.js → audio-recorder-OB6IV9B1.js} +2 -2
- package/dist/_chunks/{audio-recorder-D4xM3H5i.js.map → audio-recorder-OB6IV9B1.js.map} +1 -1
- package/dist/_chunks/{autocomplete-C7xq06bP.js → autocomplete-CUh0f7Dj.js} +2 -2
- package/dist/_chunks/{autocomplete-C7xq06bP.js.map → autocomplete-CUh0f7Dj.js.map} +1 -1
- package/dist/_chunks/{avatar-BpFohgWG.js → avatar-D_H4emLo.js} +7 -7
- package/dist/_chunks/avatar-D_H4emLo.js.map +1 -0
- package/dist/_chunks/{benefit-card-DXmrAyfn.js → benefit-card-CjYM8vNr.js} +29 -29
- package/dist/_chunks/benefit-card-CjYM8vNr.js.map +1 -0
- package/dist/_chunks/booking-CXngC-1u.js +1743 -0
- package/dist/_chunks/booking-CXngC-1u.js.map +1 -0
- package/dist/_chunks/{calendar-zy0tUUVG.js → calendar-9eOXumpH.js} +113 -142
- package/dist/_chunks/calendar-9eOXumpH.js.map +1 -0
- package/dist/_chunks/{card-C353dU-H.js → card-DKTMLVrw.js} +11 -11
- package/dist/_chunks/card-DKTMLVrw.js.map +1 -0
- package/dist/_chunks/{carousel.agent-DnPiqijR.js → carousel.agent-C9swH-Uf.js} +2 -2
- package/dist/_chunks/{carousel.agent-DnPiqijR.js.map → carousel.agent-C9swH-Uf.js.map} +1 -1
- package/dist/_chunks/{chat-input-B3XmFGDw.js → chat-input-BfDcz1Yi.js} +2 -2
- package/dist/_chunks/{chat-input-B3XmFGDw.js.map → chat-input-BfDcz1Yi.js.map} +1 -1
- package/dist/_chunks/{chat-message-W3k8rLOA.js → chat-message-fg221-yx.js} +2 -2
- package/dist/_chunks/{chat-message-W3k8rLOA.js.map → chat-message-fg221-yx.js.map} +1 -1
- package/dist/_chunks/{command-palette-DkL-aW4O.js → command-palette-11BieSNq.js} +2 -2
- package/dist/_chunks/{command-palette-DkL-aW4O.js.map → command-palette-11BieSNq.js.map} +1 -1
- package/dist/_chunks/{contact-card-CjG7c-1q.js → contact-card-CeEfEAxh.js} +2 -2
- package/dist/_chunks/{contact-card-CjG7c-1q.js.map → contact-card-CeEfEAxh.js.map} +1 -1
- package/dist/_chunks/{date-picker-BIoSLRly.js → date-picker-D0Ry1dMz.js} +26 -27
- package/dist/_chunks/{date-picker-BIoSLRly.js.map → date-picker-D0Ry1dMz.js.map} +1 -1
- package/dist/_chunks/{date-range-picker-9gANFNG9.js → date-range-picker-DYgHzMOo.js} +19 -20
- package/dist/_chunks/{date-range-picker-9gANFNG9.js.map → date-range-picker-DYgHzMOo.js.map} +1 -1
- package/dist/_chunks/{date-time-picker-DG7BiGdb.js → date-time-picker-CGmGtcyc.js} +10 -11
- package/dist/_chunks/{date-time-picker-DG7BiGdb.js.map → date-time-picker-CGmGtcyc.js.map} +1 -1
- package/dist/_chunks/{description-list-Bsga4IW8.js → description-list-yl3y3QKg.js} +34 -24
- package/dist/_chunks/description-list-yl3y3QKg.js.map +1 -0
- package/dist/_chunks/{dialog-DUomPCRS.js → dialog-BBXqpZIt.js} +2 -2
- package/dist/_chunks/{dialog-DUomPCRS.js.map → dialog-BBXqpZIt.js.map} +1 -1
- package/dist/_chunks/{editable-currency-cell-renderer-DJB5MxAI.js → editable-currency-cell-renderer-DSReCae7.js} +7 -7
- package/dist/_chunks/{editable-currency-cell-renderer-DJB5MxAI.js.map → editable-currency-cell-renderer-DSReCae7.js.map} +1 -1
- package/dist/_chunks/{empty-state-3CLJIXSj.js → empty-state-BLy7tigq.js} +13 -33
- package/dist/_chunks/empty-state-BLy7tigq.js.map +1 -0
- package/dist/_chunks/eye-LHlSU38h.js +21 -0
- package/dist/_chunks/eye-LHlSU38h.js.map +1 -0
- package/dist/_chunks/{freemium-paywall-CM6V1zNf.js → freemium-paywall-B9c8Ylww.js} +11 -11
- package/dist/_chunks/{freemium-paywall-CM6V1zNf.js.map → freemium-paywall-B9c8Ylww.js.map} +1 -1
- package/dist/_chunks/{header-DqmKROIY.js → header-B8V_sNPy.js} +2 -2
- package/dist/_chunks/{header-DqmKROIY.js.map → header-B8V_sNPy.js.map} +1 -1
- package/dist/_chunks/icon-button-BRHSSFmZ.js +70 -0
- package/dist/_chunks/icon-button-BRHSSFmZ.js.map +1 -0
- package/dist/_chunks/{isSameDay-ecuM8PBB.js → isSameDay-DHG8Xade.js} +4 -4
- package/dist/_chunks/{isSameDay-ecuM8PBB.js.map → isSameDay-DHG8Xade.js.map} +1 -1
- package/dist/_chunks/{key-value-pair-DBuOCtIc.js → key-value-pair-CqeKiP__.js} +2 -2
- package/dist/_chunks/{key-value-pair-DBuOCtIc.js.map → key-value-pair-CqeKiP__.js.map} +1 -1
- package/dist/_chunks/{locale-picker-BxEUUPW7.js → locale-picker-BHxbTNmR.js} +297 -208
- package/dist/_chunks/locale-picker-BHxbTNmR.js.map +1 -0
- package/dist/_chunks/{map-view-CcwycFQX.js → map-view-DyB8tr6c.js} +9 -9
- package/dist/_chunks/{map-view-CcwycFQX.js.map → map-view-DyB8tr6c.js.map} +1 -1
- package/dist/_chunks/{matrix-rain-CRPMXcVx.js → matrix-rain-sDOUUwZp.js} +35 -35
- package/dist/_chunks/matrix-rain-sDOUUwZp.js.map +1 -0
- package/dist/_chunks/{message-card-i61k1TGc.js → message-card-DjRtA8GG.js} +3 -3
- package/dist/_chunks/{message-card-i61k1TGc.js.map → message-card-DjRtA8GG.js.map} +1 -1
- package/dist/_chunks/{message-tray-DrV7G-wR.js → message-tray-DfsAMncP.js} +3 -3
- package/dist/_chunks/{message-tray-DrV7G-wR.js.map → message-tray-DfsAMncP.js.map} +1 -1
- package/dist/_chunks/monitor-D-SFdbrU.js +16 -0
- package/dist/_chunks/monitor-D-SFdbrU.js.map +1 -0
- package/dist/_chunks/{notification-card-ejOw5g6g.js → notification-card-B_847w5g.js} +3 -3
- package/dist/_chunks/notification-card-B_847w5g.js.map +1 -0
- package/dist/_chunks/{notification-tray-D_69dXFY.js → notification-tray-6f7smmT1.js} +22 -19
- package/dist/_chunks/notification-tray-6f7smmT1.js.map +1 -0
- package/dist/_chunks/patient-shell-Bq8CjRYF.js +173 -0
- package/dist/_chunks/{patient-shell-B164drIa.js.map → patient-shell-Bq8CjRYF.js.map} +1 -1
- package/dist/_chunks/{payment-form-F7uh0Rqr.js → payment-form-Ds3rxvad.js} +2 -2
- package/dist/_chunks/{payment-form-F7uh0Rqr.js.map → payment-form-Ds3rxvad.js.map} +1 -1
- package/dist/_chunks/{pdf-viewer-CuYaVR1I.js → pdf-viewer-CIuaocnq.js} +2 -2
- package/dist/_chunks/{pdf-viewer-CuYaVR1I.js.map → pdf-viewer-CIuaocnq.js.map} +1 -1
- package/dist/_chunks/{popover--derJ_wq.js → popover-D0slaBB9.js} +17 -13
- package/dist/_chunks/popover-D0slaBB9.js.map +1 -0
- package/dist/_chunks/{privacy-lock-BKsI6ReN.js → privacy-lock-BI4vi9Ud.js} +2 -2
- package/dist/_chunks/{privacy-lock-BKsI6ReN.js.map → privacy-lock-BI4vi9Ud.js.map} +1 -1
- package/dist/_chunks/{public-header.agent-BQ3r6Hgq.js → public-header.agent-5U3S9QiC.js} +49 -41
- package/dist/_chunks/public-header.agent-5U3S9QiC.js.map +1 -0
- package/dist/_chunks/react-day-picker-D3yzgvDB.js +3127 -0
- package/dist/_chunks/react-day-picker-D3yzgvDB.js.map +1 -0
- package/dist/_chunks/{recaptcha-widget-Kp1XntuE.js → recaptcha-widget-BtBNb6tB.js} +2 -2
- package/dist/_chunks/{recaptcha-widget-Kp1XntuE.js.map → recaptcha-widget-BtBNb6tB.js.map} +1 -1
- package/dist/_chunks/{search-bar-DORSAzNt.js → search-bar-BRMW1-WG.js} +2 -2
- package/dist/_chunks/{search-bar-DORSAzNt.js.map → search-bar-BRMW1-WG.js.map} +1 -1
- package/dist/_chunks/{search-input-BtEJAJHa.js → search-input-CIA6pPfn.js} +2 -2
- package/dist/_chunks/{search-input-BtEJAJHa.js.map → search-input-CIA6pPfn.js.map} +1 -1
- package/dist/_chunks/{sheet-BT0izeoI.js → sheet-D8M8hf8B.js} +2 -2
- package/dist/_chunks/{sheet-BT0izeoI.js.map → sheet-D8M8hf8B.js.map} +1 -1
- package/dist/_chunks/{sign-in-with-alfadocs-button-4zZC-I6y.js → sign-in-with-alfadocs-button-BI0fVonM.js} +2 -2
- package/dist/_chunks/{sign-in-with-alfadocs-button-4zZC-I6y.js.map → sign-in-with-alfadocs-button-BI0fVonM.js.map} +1 -1
- package/dist/_chunks/{slot-grid-CgpYgBkW.js → slot-grid-DoodeQGZ.js} +4 -4
- package/dist/_chunks/{slot-grid-CgpYgBkW.js.map → slot-grid-DoodeQGZ.js.map} +1 -1
- package/dist/_chunks/sparkles-CuYXqQLg.js +23 -0
- package/dist/_chunks/sparkles-CuYXqQLg.js.map +1 -0
- package/dist/_chunks/{spinner-DirtWZNG.js → spinner-CCByyvcb.js} +2 -2
- package/dist/_chunks/spinner-CCByyvcb.js.map +1 -0
- package/dist/_chunks/stepper-accordion-BfS6lUB9.js +257 -0
- package/dist/_chunks/stepper-accordion-BfS6lUB9.js.map +1 -0
- package/dist/_chunks/stepper-accordion.agent-C4quJ-MD.js +71 -0
- package/dist/_chunks/stepper-accordion.agent-C4quJ-MD.js.map +1 -0
- package/dist/_chunks/stethoscope-B8kpbtjh.js +35 -0
- package/dist/_chunks/stethoscope-B8kpbtjh.js.map +1 -0
- package/dist/_chunks/{sun-Eweh5fvi.js → sun-BuXE0xUS.js} +3 -15
- package/dist/_chunks/sun-BuXE0xUS.js.map +1 -0
- package/dist/_chunks/{task-tray-B3A2fRGR.js → task-tray-Bcmrrs8m.js} +3 -3
- package/dist/_chunks/{task-tray-B3A2fRGR.js.map → task-tray-Bcmrrs8m.js.map} +1 -1
- package/dist/_chunks/{theme-toggle-FrotC2VI.js → theme-toggle-nPzb378f.js} +37 -36
- package/dist/_chunks/{theme-toggle-FrotC2VI.js.map → theme-toggle-nPzb378f.js.map} +1 -1
- package/dist/_chunks/{timeline-jmd7lfDf.js → timeline-CR7HjZCK.js} +3 -3
- package/dist/_chunks/{timeline-jmd7lfDf.js.map → timeline-CR7HjZCK.js.map} +1 -1
- package/dist/_chunks/{toast.agent-32WNQ-_x.js → toast.agent-CTF6nIj5.js} +2 -2
- package/dist/_chunks/{toast.agent-32WNQ-_x.js.map → toast.agent-CTF6nIj5.js.map} +1 -1
- package/dist/_chunks/{transcript-panel-DUrjx5sa.js → transcript-panel-QUQ9XJmf.js} +2 -2
- package/dist/_chunks/{transcript-panel-DUrjx5sa.js.map → transcript-panel-QUQ9XJmf.js.map} +1 -1
- package/dist/_chunks/{use-password-requirements-C9vKBSVn.js → use-password-requirements-E0sSfx5X.js} +38 -53
- package/dist/_chunks/use-password-requirements-E0sSfx5X.js.map +1 -0
- package/dist/_chunks/use-theme-C2dHKUAN.js +145 -0
- package/dist/_chunks/use-theme-C2dHKUAN.js.map +1 -0
- package/dist/_chunks/{workflow-map-BR6txfFX.js → workflow-map-BKsKdYvZ.js} +5 -5
- package/dist/_chunks/{workflow-map-BR6txfFX.js.map → workflow-map-BKsKdYvZ.js.map} +1 -1
- package/dist/agent-catalog.json +56 -51
- package/dist/components/agenda-card/index.js +1 -1
- package/dist/components/agenda-tray/index.js +1 -1
- package/dist/components/ai-prompt-input/index.js +1 -1
- package/dist/components/audio-recorder/index.js +1 -1
- package/dist/components/autocomplete/index.js +1 -1
- package/dist/components/avatar/avatar.d.ts.map +1 -1
- package/dist/components/avatar/index.js +1 -1
- package/dist/components/benefit-card/benefit-card.d.ts.map +1 -1
- package/dist/components/benefit-card/index.js +1 -1
- package/dist/components/booking/booking.agent.d.ts +4 -0
- package/dist/components/booking/booking.agent.d.ts.map +1 -0
- package/dist/components/booking/booking.d.ts +91 -0
- package/dist/components/booking/booking.d.ts.map +1 -0
- package/dist/components/booking/index.d.ts +4 -0
- package/dist/components/booking/index.d.ts.map +1 -0
- package/dist/components/booking/index.js +6 -0
- package/dist/components/button/icon-button.d.ts.map +1 -1
- package/dist/components/button/index.js +1 -1
- package/dist/components/calendar/index.js +1 -1
- package/dist/components/card/card.d.ts.map +1 -1
- package/dist/components/card/index.js +1 -1
- package/dist/components/carousel/index.js +1 -1
- package/dist/components/chat-input/index.js +1 -1
- package/dist/components/chat-message/index.js +1 -1
- package/dist/components/command-palette/index.js +1 -1
- package/dist/components/contact-card/index.js +1 -1
- package/dist/components/data-table/index.js +1 -1
- package/dist/components/date-picker/index.js +1 -1
- package/dist/components/date-range-picker/index.js +1 -1
- package/dist/components/date-time-picker/index.js +1 -1
- package/dist/components/description-list/description-list.d.ts.map +1 -1
- package/dist/components/description-list/index.js +1 -1
- package/dist/components/dialog/index.js +1 -1
- package/dist/components/empty-state/empty-state.d.ts.map +1 -1
- package/dist/components/empty-state/index.js +1 -1
- package/dist/components/freemium-paywall/index.js +1 -1
- package/dist/components/header/index.js +1 -1
- package/dist/components/header-settings/index.js +60 -48
- package/dist/components/header-settings/index.js.map +1 -1
- package/dist/components/icon-button/index.js +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/key-value-pair/index.js +1 -1
- package/dist/components/locale-picker/index.js +1 -1
- package/dist/components/map-view/index.js +1 -1
- package/dist/components/matrix-rain/index.js +1 -1
- package/dist/components/message-card/index.js +1 -1
- package/dist/components/message-tray/index.js +1 -1
- package/dist/components/notification-card/index.js +1 -1
- package/dist/components/notification-tray/index.js +1 -1
- package/dist/components/notification-tray/notification-tray.d.ts.map +1 -1
- package/dist/components/password-input/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/popover/index.js +1 -1
- package/dist/components/popover/popover.d.ts.map +1 -1
- package/dist/components/privacy-lock/index.js +1 -1
- package/dist/components/public-header/index.js +1 -1
- package/dist/components/public-header/public-header.d.ts.map +1 -1
- package/dist/components/recaptcha-widget/index.js +1 -1
- package/dist/components/search-bar/index.js +1 -1
- package/dist/components/search-input/index.js +1 -1
- package/dist/components/sheet/index.js +1 -1
- package/dist/components/sign-in-with-alfadocs-button/index.js +1 -1
- package/dist/components/slot-grid/index.js +1 -1
- package/dist/components/spinner/index.js +1 -1
- package/dist/components/stepper-accordion/index.js +4 -3
- package/dist/components/stepper-accordion/index.js.map +1 -1
- package/dist/components/task-tray/index.js +1 -1
- package/dist/components/theme-toggle/index.js +1 -1
- package/dist/components/timeline/index.js +1 -1
- package/dist/components/toast/index.js +1 -1
- package/dist/components/transcript-panel/index.js +1 -1
- package/dist/components/workflow/index.js +1 -1
- package/dist/hooks/index.js +1 -1
- package/dist/hooks/use-theme.d.ts.map +1 -1
- package/dist/i18n/config.js +1090 -46
- package/dist/i18n/config.js.map +1 -1
- package/dist/i18n/locales/ar.d.ts +58 -0
- package/dist/i18n/locales/ar.d.ts.map +1 -1
- package/dist/i18n/locales/de.d.ts +58 -0
- package/dist/i18n/locales/de.d.ts.map +1 -1
- package/dist/i18n/locales/el.d.ts +58 -0
- package/dist/i18n/locales/el.d.ts.map +1 -1
- package/dist/i18n/locales/es.d.ts +58 -0
- package/dist/i18n/locales/es.d.ts.map +1 -1
- package/dist/i18n/locales/fr.d.ts +58 -0
- package/dist/i18n/locales/fr.d.ts.map +1 -1
- package/dist/i18n/locales/hi.d.ts +58 -0
- package/dist/i18n/locales/hi.d.ts.map +1 -1
- package/dist/i18n/locales/ja.d.ts +58 -0
- package/dist/i18n/locales/ja.d.ts.map +1 -1
- package/dist/i18n/locales/nl.d.ts +58 -0
- package/dist/i18n/locales/nl.d.ts.map +1 -1
- package/dist/i18n/locales/pl.d.ts +58 -0
- package/dist/i18n/locales/pl.d.ts.map +1 -1
- package/dist/i18n/locales/pt.d.ts +58 -0
- package/dist/i18n/locales/pt.d.ts.map +1 -1
- package/dist/i18n/locales/ro.d.ts +58 -0
- package/dist/i18n/locales/ro.d.ts.map +1 -1
- package/dist/i18n/locales/ru.d.ts +58 -0
- package/dist/i18n/locales/ru.d.ts.map +1 -1
- package/dist/i18n/locales/sq.d.ts +58 -0
- package/dist/i18n/locales/sq.d.ts.map +1 -1
- package/dist/i18n/locales/sv.d.ts +58 -0
- package/dist/i18n/locales/sv.d.ts.map +1 -1
- package/dist/i18n/locales/tr.d.ts +58 -0
- package/dist/i18n/locales/tr.d.ts.map +1 -1
- package/dist/i18n/locales/zh.d.ts +58 -0
- package/dist/i18n/locales/zh.d.ts.map +1 -1
- package/dist/i18n/resources.d.ts +116 -0
- package/dist/i18n/resources.d.ts.map +1 -1
- package/dist/index.js +270 -269
- package/dist/index.js.map +1 -1
- package/dist/locales/ar.json +59 -1
- package/dist/locales/de.json +59 -1
- package/dist/locales/el.json +59 -1
- package/dist/locales/en.json +59 -1
- package/dist/locales/es.json +59 -1
- package/dist/locales/fr.json +59 -1
- package/dist/locales/hi.json +59 -1
- package/dist/locales/it.json +59 -1
- package/dist/locales/ja.json +59 -1
- package/dist/locales/nl.json +59 -1
- package/dist/locales/pl.json +59 -1
- package/dist/locales/pt.json +59 -1
- package/dist/locales/ro.json +59 -1
- package/dist/locales/ru.json +59 -1
- package/dist/locales/sq.json +59 -1
- package/dist/locales/sv.json +59 -1
- package/dist/locales/tr.json +59 -1
- package/dist/locales/zh.json +59 -1
- package/dist/patterns/alia-assistant/index.js +1 -1
- package/dist/patterns/patient-shell/index.js +1 -1
- package/dist/patterns/patient-shell/patient-shell.d.ts.map +1 -1
- package/dist/tokens.css +1 -1
- package/package.json +5 -1
- package/dist/_chunks/alia-sidebar-CUi2UCbY.js.map +0 -1
- package/dist/_chunks/avatar-BpFohgWG.js.map +0 -1
- package/dist/_chunks/benefit-card-DXmrAyfn.js.map +0 -1
- package/dist/_chunks/calendar-zy0tUUVG.js.map +0 -1
- package/dist/_chunks/card-C353dU-H.js.map +0 -1
- package/dist/_chunks/description-list-Bsga4IW8.js.map +0 -1
- package/dist/_chunks/empty-state-3CLJIXSj.js.map +0 -1
- package/dist/_chunks/icon-button-C4CGcYuz.js +0 -54
- package/dist/_chunks/icon-button-C4CGcYuz.js.map +0 -1
- package/dist/_chunks/isSameMonth-5wNF2f4I.js +0 -1307
- package/dist/_chunks/isSameMonth-5wNF2f4I.js.map +0 -1
- package/dist/_chunks/locale-picker-BxEUUPW7.js.map +0 -1
- package/dist/_chunks/matrix-rain-CRPMXcVx.js.map +0 -1
- package/dist/_chunks/notification-card-ejOw5g6g.js.map +0 -1
- package/dist/_chunks/notification-tray-D_69dXFY.js.map +0 -1
- package/dist/_chunks/patient-shell-B164drIa.js +0 -173
- package/dist/_chunks/popover--derJ_wq.js.map +0 -1
- package/dist/_chunks/public-header.agent-BQ3r6Hgq.js.map +0 -1
- package/dist/_chunks/react-day-picker-C5F3-TTX.js +0 -1827
- package/dist/_chunks/react-day-picker-C5F3-TTX.js.map +0 -1
- package/dist/_chunks/spinner-DirtWZNG.js.map +0 -1
- package/dist/_chunks/stepper-C-sIpRRU.js +0 -7
- package/dist/_chunks/stepper-C-sIpRRU.js.map +0 -1
- package/dist/_chunks/stepper-accordion.agent-ckKYZCIP.js +0 -322
- package/dist/_chunks/stepper-accordion.agent-ckKYZCIP.js.map +0 -1
- package/dist/_chunks/stepper-calendar-BLOJUE0-.js +0 -648
- package/dist/_chunks/stepper-calendar-BLOJUE0-.js.map +0 -1
- package/dist/_chunks/sun-Eweh5fvi.js.map +0 -1
- package/dist/_chunks/use-password-requirements-C9vKBSVn.js.map +0 -1
- package/dist/_chunks/use-theme-B1cwAXJR.js +0 -145
- package/dist/_chunks/use-theme-B1cwAXJR.js.map +0 -1
- package/dist/components/stepper-calendar/index.d.ts +0 -4
- package/dist/components/stepper-calendar/index.d.ts.map +0 -1
- package/dist/components/stepper-calendar/index.js +0 -6
- package/dist/components/stepper-calendar/stepper-calendar.agent.d.ts +0 -4
- package/dist/components/stepper-calendar/stepper-calendar.agent.d.ts.map +0 -1
- package/dist/components/stepper-calendar/stepper-calendar.d.ts +0 -62
- package/dist/components/stepper-calendar/stepper-calendar.d.ts.map +0 -1
- /package/dist/components/{stepper-calendar → booking}/index.js.map +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as G } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef as Z, useRef as q, useMemo as ee, useEffect as te } from "react";
|
|
3
3
|
import { c as ne } from "./index-D2ZczOXr.js";
|
|
4
|
-
const
|
|
5
|
-
katakana:
|
|
6
|
-
hex:
|
|
4
|
+
const re = 'ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワ0123456789:・."=*+-<>¦|', ae = "0123456789ABCDEF{}[]<>/\\;:=$#@!*+-", oe = "01", se = "!@#$%^&*()_+-=[]{}|;:,.<>?/", I = {
|
|
5
|
+
katakana: re,
|
|
6
|
+
hex: ae,
|
|
7
7
|
binary: oe,
|
|
8
8
|
symbols: se
|
|
9
9
|
}, ie = ne(
|
|
@@ -15,12 +15,12 @@ const ae = 'ヲァィゥェォャュョッーアイウエオカキクケコサ
|
|
|
15
15
|
// Built-in surface so the rain has somewhere to read against
|
|
16
16
|
// without the consumer wrapping it themselves.
|
|
17
17
|
// `transparent` (default) lets the parent provide the background.
|
|
18
|
-
// `solid` paints
|
|
19
|
-
//
|
|
20
|
-
//
|
|
18
|
+
// `solid` paints the theme background — already a dark step in
|
|
19
|
+
// dark theme — so the rain's brightest glyphs read clean against
|
|
20
|
+
// it without locking in a specific palette step.
|
|
21
21
|
background: {
|
|
22
22
|
transparent: "",
|
|
23
|
-
solid: "ds:bg-[var(--
|
|
23
|
+
solid: "ds:bg-[var(--background)]"
|
|
24
24
|
},
|
|
25
25
|
vibe: {
|
|
26
26
|
// No overlay, no canvas filter — just the rain.
|
|
@@ -30,9 +30,9 @@ const ae = 'ヲァィゥェォャュョッーアイウエオカキクケコサ
|
|
|
30
30
|
// the draw loop).
|
|
31
31
|
terminal: [
|
|
32
32
|
"ds:before:pointer-events-none ds:before:absolute ds:before:inset-0 ds:before:z-[2] ds:before:content-['']",
|
|
33
|
-
"ds:before:bg-[radial-gradient(closest-side,transparent_55%,
|
|
33
|
+
"ds:before:bg-[radial-gradient(closest-side,transparent_55%,color-mix(in_srgb,var(--foreground)_55%,transparent)_100%)]",
|
|
34
34
|
"ds:after:pointer-events-none ds:after:absolute ds:after:inset-0 ds:after:z-[1] ds:after:content-['']",
|
|
35
|
-
"ds:after:bg-[repeating-linear-gradient(to_bottom,transparent_0,transparent_2px,
|
|
35
|
+
"ds:after:bg-[repeating-linear-gradient(to_bottom,transparent_0,transparent_2px,color-mix(in_srgb,var(--foreground)_32%,transparent)_2px,color-mix(in_srgb,var(--foreground)_32%,transparent)_3px)]",
|
|
36
36
|
"ds:after:mix-blend-multiply",
|
|
37
37
|
"ds:[&>canvas]:[filter:blur(0.55px)_brightness(1.25)_contrast(1.1)_saturate(1.3)]"
|
|
38
38
|
].join(" "),
|
|
@@ -40,7 +40,7 @@ const ae = 'ヲァィゥェォャュョッーアイウエオカキクケコサ
|
|
|
40
40
|
// per-glyph glow. No vignette.
|
|
41
41
|
hologram: [
|
|
42
42
|
"ds:after:pointer-events-none ds:after:absolute ds:after:inset-0 ds:after:z-[1] ds:after:content-['']",
|
|
43
|
-
"ds:after:bg-[repeating-linear-gradient(to_bottom,transparent_0,transparent_3px,
|
|
43
|
+
"ds:after:bg-[repeating-linear-gradient(to_bottom,transparent_0,transparent_3px,color-mix(in_srgb,var(--foreground)_18%,transparent)_3px,color-mix(in_srgb,var(--foreground)_18%,transparent)_4px)]",
|
|
44
44
|
"ds:after:mix-blend-multiply",
|
|
45
45
|
"ds:[&>canvas]:[filter:blur(0.4px)_brightness(1.15)_contrast(1.05)]",
|
|
46
46
|
"ds:[&>canvas]:[animation:matrix-rain-hologram-pulse_3s_ease-in-out_infinite]"
|
|
@@ -50,7 +50,7 @@ const ae = 'ヲァィゥェォャュョッーアイウエオカキクケコサ
|
|
|
50
50
|
// the draw loop (accent → info gradient).
|
|
51
51
|
synthwave: [
|
|
52
52
|
"ds:after:pointer-events-none ds:after:absolute ds:after:inset-x-0 ds:after:bottom-0 ds:after:h-[30%] ds:after:z-[1] ds:after:content-['']",
|
|
53
|
-
"ds:after:bg-[linear-gradient(to_top,var(--
|
|
53
|
+
"ds:after:bg-[linear-gradient(to_top,color-mix(in_srgb,var(--info)_60%,transparent),transparent)]",
|
|
54
54
|
"ds:after:opacity-50",
|
|
55
55
|
"ds:[&>canvas]:[filter:blur(0.7px)_brightness(1.3)_contrast(1.15)_saturate(1.5)]"
|
|
56
56
|
].join(" "),
|
|
@@ -59,7 +59,7 @@ const ae = 'ヲァィゥェォャュョッーアイウエオカキクケコサ
|
|
|
59
59
|
oscilloscope: [
|
|
60
60
|
// Scanlines (denser, alpha-heavier than terminal)
|
|
61
61
|
"ds:after:pointer-events-none ds:after:absolute ds:after:inset-0 ds:after:z-[1] ds:after:content-['']",
|
|
62
|
-
"ds:after:bg-[repeating-linear-gradient(to_bottom,transparent_0,transparent_1px,
|
|
62
|
+
"ds:after:bg-[repeating-linear-gradient(to_bottom,transparent_0,transparent_1px,color-mix(in_srgb,var(--foreground)_40%,transparent)_1px,color-mix(in_srgb,var(--foreground)_40%,transparent)_2px)]",
|
|
63
63
|
"ds:after:mix-blend-multiply",
|
|
64
64
|
// Sweep beam — thin highlight bar scrolling top → bottom
|
|
65
65
|
"ds:before:pointer-events-none ds:before:absolute ds:before:inset-x-0 ds:before:top-0 ds:before:z-[2] ds:before:h-[4px] ds:before:content-['']",
|
|
@@ -144,64 +144,64 @@ const ae = 'ヲァィゥェォャュョッーアイウエオカキクケコサ
|
|
|
144
144
|
if (!e) return;
|
|
145
145
|
const t = typeof window < "u" && typeof window.matchMedia == "function" ? window.matchMedia("(prefers-reduced-motion: reduce)") : null;
|
|
146
146
|
if (t != null && t.matches) return;
|
|
147
|
-
const A = v || (typeof window > "u" ? "" : getComputedStyle(document.documentElement).getPropertyValue(de[P]).trim() || getComputedStyle(o).color), Q = typeof window > "u" ? "monospace" : getComputedStyle(document.documentElement).getPropertyValue("--font-mono").trim() || "monospace",
|
|
148
|
-
let l = 0,
|
|
147
|
+
const A = v || (typeof window > "u" ? "" : getComputedStyle(document.documentElement).getPropertyValue(de[P]).trim() || getComputedStyle(o).color), Q = typeof window > "u" ? "monospace" : getComputedStyle(document.documentElement).getPropertyValue("--font-mono").trim() || "monospace", g = window.devicePixelRatio || 1;
|
|
148
|
+
let l = 0, h = [], m = [], E = [];
|
|
149
149
|
const R = () => {
|
|
150
150
|
const n = o.getBoundingClientRect();
|
|
151
|
-
if (o.width = Math.max(1, Math.floor(n.width *
|
|
151
|
+
if (o.width = Math.max(1, Math.floor(n.width * g)), o.height = Math.max(1, Math.floor(n.height * g)), e.setTransform(g, 0, 0, g, 0, 0), l = Math.max(1, Math.floor(n.width / d)), h = new Array(l).fill(0).map(
|
|
152
152
|
() => (
|
|
153
153
|
// Random initial offset so columns never start in sync.
|
|
154
154
|
Math.floor(Math.random() * (n.height / d))
|
|
155
155
|
)
|
|
156
156
|
), s === "synthwave") {
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
const w =
|
|
160
|
-
return
|
|
161
|
-
}), document.documentElement.removeChild(
|
|
157
|
+
const a = document.createElement("span");
|
|
158
|
+
a.style.display = "none", document.documentElement.appendChild(a), m = new Array(l).fill("").map((L, r) => {
|
|
159
|
+
const w = r / Math.max(1, l - 1) * 100;
|
|
160
|
+
return a.style.color = `color-mix(in oklch, var(--accent) ${100 - w}%, var(--info) ${w}%)`, getComputedStyle(a).color || A;
|
|
161
|
+
}), document.documentElement.removeChild(a);
|
|
162
162
|
} else
|
|
163
163
|
m = [];
|
|
164
164
|
u ? E = new Array(l).fill(0).map(() => 0.6 + Math.random() * 0.8) : E = [];
|
|
165
165
|
};
|
|
166
|
-
let
|
|
166
|
+
let k = 0, c = 0, C = !0, S = !0;
|
|
167
167
|
const B = (n) => {
|
|
168
|
-
if (n -
|
|
169
|
-
|
|
170
|
-
const
|
|
171
|
-
y !== null && (e.globalCompositeOperation = "destination-out", e.globalAlpha = y, e.fillStyle = "black", e.fillRect(0, 0,
|
|
168
|
+
if (n - k >= z) {
|
|
169
|
+
k = n;
|
|
170
|
+
const a = o.getBoundingClientRect();
|
|
171
|
+
y !== null && (e.globalCompositeOperation = "destination-out", e.globalAlpha = y, e.fillStyle = "black", e.fillRect(0, 0, a.width, a.height), e.globalAlpha = 1), e.globalCompositeOperation = "source-over", e.font = `${d}px ${Q}`, e.textBaseline = "top";
|
|
172
172
|
const L = s === "terminal" || s === "hologram" || s === "synthwave";
|
|
173
173
|
L ? (e.shadowColor = A, e.shadowBlur = Math.max(4, d * 0.6)) : e.shadowBlur = 0, s !== "synthwave" && (e.fillStyle = A);
|
|
174
|
-
for (let
|
|
174
|
+
for (let r = 0; r < l; r += 1) {
|
|
175
175
|
const w = x.charAt(
|
|
176
176
|
Math.floor(Math.random() * x.length)
|
|
177
|
-
), N = u ? (Math.random() - 0.5) * 2 : 0, U =
|
|
178
|
-
s === "synthwave" && m[
|
|
177
|
+
), N = u ? (Math.random() - 0.5) * 2 : 0, U = r * d + N, T = h[r] * d;
|
|
178
|
+
s === "synthwave" && m[r] && (e.fillStyle = m[r], L && (e.shadowColor = m[r])), e.fillText(w, U, T), T > a.height && Math.random() > 0.97 && (h[r] = 0), h[r] += u && E[r] || 1;
|
|
179
179
|
}
|
|
180
180
|
}
|
|
181
181
|
c = window.requestAnimationFrame(B);
|
|
182
|
-
},
|
|
183
|
-
c || !
|
|
182
|
+
}, b = () => {
|
|
183
|
+
c || !C || !S || (k = window.performance ? window.performance.now() : 0, c = window.requestAnimationFrame(B));
|
|
184
184
|
}, _ = () => {
|
|
185
185
|
c && (window.cancelAnimationFrame(c), c = 0);
|
|
186
186
|
};
|
|
187
|
-
R(),
|
|
187
|
+
R(), b();
|
|
188
188
|
const i = typeof ResizeObserver < "u" ? new ResizeObserver(R) : null;
|
|
189
189
|
i == null || i.observe(o);
|
|
190
190
|
const Y = () => R();
|
|
191
191
|
i || window.addEventListener("resize", Y);
|
|
192
192
|
const j = () => {
|
|
193
|
-
|
|
193
|
+
C = !document.hidden, C ? b() : _();
|
|
194
194
|
};
|
|
195
195
|
document.addEventListener("visibilitychange", j);
|
|
196
196
|
const f = typeof IntersectionObserver < "u" ? new IntersectionObserver(
|
|
197
197
|
(n) => {
|
|
198
|
-
|
|
198
|
+
S = n.some((a) => a.isIntersecting), S ? b() : _();
|
|
199
199
|
},
|
|
200
200
|
{ threshold: 0 }
|
|
201
201
|
) : null;
|
|
202
202
|
f == null || f.observe(o);
|
|
203
203
|
const F = () => {
|
|
204
|
-
t != null && t.matches ? _() :
|
|
204
|
+
t != null && t.matches ? _() : b();
|
|
205
205
|
};
|
|
206
206
|
return (H = t == null ? void 0 : t.addEventListener) == null || H.call(t, "change", F), () => {
|
|
207
207
|
var n;
|
|
@@ -241,4 +241,4 @@ me.displayName = "MatrixRain";
|
|
|
241
241
|
export {
|
|
242
242
|
me as M
|
|
243
243
|
};
|
|
244
|
-
//# sourceMappingURL=matrix-rain-
|
|
244
|
+
//# sourceMappingURL=matrix-rain-sDOUUwZp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"matrix-rain-sDOUUwZp.js","sources":["../../src/components/matrix-rain/matrix-rain.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* MatrixRain — decorative canvas overlay. */\n/* */\n/* Falling-glyph \"digital rain\" with a CRT terminal vibe. Designed for */\n/* easter-egg / dev-flavoured surfaces: place inside a relatively- */\n/* positioned container with an `inset-0` className. */\n/* */\n/* Behaviour: */\n/* - Honours `prefers-reduced-motion` (renders nothing, animation off). */\n/* - Pauses while the tab is hidden (visibility API). */\n/* - Pauses when scrolled off-screen (IntersectionObserver). */\n/* - DPR-aware so glyphs stay sharp on HiDPI. */\n/* - Resizes with the container (ResizeObserver). */\n/* - \"Density-by-use\" trail: the per-frame decay alpha is small, so */\n/* columns that fire often accumulate a denser background residue */\n/* than rarely-firing ones — well-trodden paths stay luminous. */\n/* */\n/* The canvas is purely decorative — `aria-hidden=\"true\"`, no focus, no */\n/* visible text. Consumers must own the parent's positioning + stacking. */\n/* -------------------------------------------------------------------- */\n\nimport { forwardRef, useEffect, useMemo, useRef } from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\n\n/* ------------------------------------------------------------------ */\n/* Glyph presets */\n/* ------------------------------------------------------------------ */\n\n/**\n * Half-width katakana + Latin digits + a few symbols. The canonical\n * Matrix used reverse-mirrored half-width katakana from a custom font;\n * plain half-width katakana is the closest open approximation.\n */\nconst KATAKANA_GLYPHS =\n 'ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワ' +\n '0123456789:・.\"=*+-<>¦|';\n\nconst HEX_GLYPHS = '0123456789ABCDEF{}[]<>/\\\\;:=$#@!*+-';\nconst BINARY_GLYPHS = '01';\nconst SYMBOL_GLYPHS = '!@#$%^&*()_+-=[]{}|;:,.<>?/';\n\nconst GLYPH_PRESETS = {\n katakana: KATAKANA_GLYPHS,\n hex: HEX_GLYPHS,\n binary: BINARY_GLYPHS,\n symbols: SYMBOL_GLYPHS,\n} as const;\n\ntype GlyphPreset = keyof typeof GLYPH_PRESETS;\n\n/* ------------------------------------------------------------------ */\n/* CVA variants */\n/* ------------------------------------------------------------------ */\n\nconst wrapperVariants = cva(\n // Wrapper holds the canvas plus optional overlay pseudo-elements.\n // pointer-events-none so the overlay never blocks underlying UI.\n 'ds:pointer-events-none ds:relative ds:overflow-hidden',\n {\n variants: {\n // Built-in surface so the rain has somewhere to read against\n // without the consumer wrapping it themselves.\n // `transparent` (default) lets the parent provide the background.\n // `solid` paints the theme background — already a dark step in\n // dark theme — so the rain's brightest glyphs read clean against\n // it without locking in a specific palette step.\n background: {\n transparent: '',\n solid: 'ds:bg-[var(--background)]',\n },\n vibe: {\n // No overlay, no canvas filter — just the rain.\n clean: '',\n // Fallout-CRT stack: vignette + dense scanlines + bloom +\n // per-glyph phosphor glow (canvas-side shadowBlur, applied in\n // the draw loop).\n terminal: [\n \"ds:before:pointer-events-none ds:before:absolute ds:before:inset-0 ds:before:z-[2] ds:before:content-['']\",\n 'ds:before:bg-[radial-gradient(closest-side,transparent_55%,color-mix(in_srgb,var(--foreground)_55%,transparent)_100%)]',\n \"ds:after:pointer-events-none ds:after:absolute ds:after:inset-0 ds:after:z-[1] ds:after:content-['']\",\n 'ds:after:bg-[repeating-linear-gradient(to_bottom,transparent_0,transparent_2px,color-mix(in_srgb,var(--foreground)_32%,transparent)_2px,color-mix(in_srgb,var(--foreground)_32%,transparent)_3px)]',\n 'ds:after:mix-blend-multiply',\n 'ds:[&>canvas]:[filter:blur(0.55px)_brightness(1.25)_contrast(1.1)_saturate(1.3)]',\n ].join(' '),\n // Sci-fi HUD: light scanlines, soft bloom, slow opacity pulse,\n // per-glyph glow. No vignette.\n hologram: [\n \"ds:after:pointer-events-none ds:after:absolute ds:after:inset-0 ds:after:z-[1] ds:after:content-['']\",\n 'ds:after:bg-[repeating-linear-gradient(to_bottom,transparent_0,transparent_3px,color-mix(in_srgb,var(--foreground)_18%,transparent)_3px,color-mix(in_srgb,var(--foreground)_18%,transparent)_4px)]',\n 'ds:after:mix-blend-multiply',\n 'ds:[&>canvas]:[filter:blur(0.4px)_brightness(1.15)_contrast(1.05)]',\n 'ds:[&>canvas]:[animation:matrix-rain-hologram-pulse_3s_ease-in-out_infinite]',\n ].join(' '),\n // Synthwave neon: heavy bloom, no scanlines, indigo horizon\n // glow at the bottom. Glyph colour is computed per-column in\n // the draw loop (accent → info gradient).\n synthwave: [\n \"ds:after:pointer-events-none ds:after:absolute ds:after:inset-x-0 ds:after:bottom-0 ds:after:h-[30%] ds:after:z-[1] ds:after:content-['']\",\n 'ds:after:bg-[linear-gradient(to_top,color-mix(in_srgb,var(--info)_60%,transparent),transparent)]',\n 'ds:after:opacity-50',\n 'ds:[&>canvas]:[filter:blur(0.7px)_brightness(1.3)_contrast(1.15)_saturate(1.5)]',\n ].join(' '),\n // Vintage scope monitor: dense thin scanlines, sharp edges\n // (no canvas filter), animated horizontal sweep beam.\n oscilloscope: [\n // Scanlines (denser, alpha-heavier than terminal)\n \"ds:after:pointer-events-none ds:after:absolute ds:after:inset-0 ds:after:z-[1] ds:after:content-['']\",\n 'ds:after:bg-[repeating-linear-gradient(to_bottom,transparent_0,transparent_1px,color-mix(in_srgb,var(--foreground)_40%,transparent)_1px,color-mix(in_srgb,var(--foreground)_40%,transparent)_2px)]',\n 'ds:after:mix-blend-multiply',\n // Sweep beam — thin highlight bar scrolling top → bottom\n \"ds:before:pointer-events-none ds:before:absolute ds:before:inset-x-0 ds:before:top-0 ds:before:z-[2] ds:before:h-[4px] ds:before:content-['']\",\n 'ds:before:bg-[linear-gradient(to_bottom,transparent,var(--foreground),transparent)]',\n 'ds:before:opacity-50',\n 'ds:before:[animation:matrix-rain-osc-sweep_4s_linear_infinite]',\n 'ds:before:mix-blend-screen',\n ].join(' '),\n // Production-friendly: low opacity, no overlay. Pairs with\n // `decay=\"slow\"` (the default) for a faint background-noise\n // feel that doesn't dominate foreground content.\n ghost: 'ds:[&>canvas]:opacity-30',\n },\n // Radial mask that fades the canvas to transparent in the middle\n // so foreground content stays readable. `closest-side` adapts to\n // non-square containers. The `--mr` custom property comes from\n // the `maskRadius` variant below.\n mask: {\n none: '',\n center: [\n 'ds:[&>canvas]:[mask-image:radial-gradient(closest-side,transparent_0%,transparent_var(--mr,30%),black_calc(var(--mr,30%)+45%))]',\n 'ds:[&>canvas]:[-webkit-mask-image:radial-gradient(closest-side,transparent_0%,transparent_var(--mr,30%),black_calc(var(--mr,30%)+45%))]',\n ].join(' '),\n },\n // Mask radius — t-shirt sizes drive the inner clear-zone radius.\n // Only applied when mask=\"center\". md (30%) is the default.\n maskRadius: {\n xs: 'ds:[--mr:15%]',\n sm: 'ds:[--mr:22%]',\n md: 'ds:[--mr:30%]',\n lg: 'ds:[--mr:42%]',\n xl: 'ds:[--mr:55%]',\n },\n },\n defaultVariants: {\n background: 'transparent',\n vibe: 'clean',\n mask: 'none',\n maskRadius: 'md',\n },\n },\n);\n\n/* ------------------------------------------------------------------ */\n/* Tone → semantic token resolution */\n/* ------------------------------------------------------------------ */\n\ntype Tone = 'primary' | 'accent' | 'success' | 'error' | 'info';\ntype Density = 'low' | 'medium' | 'high';\ntype Pace = 'gentle' | 'normal' | 'fast';\ntype Decay = 'none' | 'slow' | 'normal' | 'fast';\n\nconst TONE_VAR: Record<Tone, string> = {\n primary: '--primary',\n accent: '--accent',\n success: '--success',\n error: '--error',\n info: '--info',\n};\n\nconst DENSITY_FONT_PX: Record<Density, number> = {\n low: 18,\n medium: 14,\n high: 11,\n};\n\nconst PACE_FRAME_MS: Record<Pace, number> = {\n gentle: 100,\n normal: 60,\n fast: 33,\n};\n\n// Per-frame trail decay alpha. Smaller = trails persist longer = more\n// \"density by use\". `none` skips the decay step entirely; over long\n// uptimes the canvas approaches a saturated noise field. `slow` is the\n// new default that produces the \"well-trodden paths stay bright\" feel.\nconst DECAY_ALPHA: Record<Decay, number | null> = {\n none: null,\n slow: 0.003,\n normal: 0.02,\n fast: 0.08,\n};\n\n/* ------------------------------------------------------------------ */\n/* Props */\n/* ------------------------------------------------------------------ */\n\nexport interface MatrixRainProps extends VariantProps<typeof wrapperVariants> {\n /** Glyph preset name or a literal string of glyphs. Default `katakana`. */\n glyphs?: GlyphPreset | string;\n /** Brand tone for the rain. Resolved against the active theme. */\n tone?: Tone;\n /** Optional explicit colour — any CSS colour value. Overrides `tone` when set. */\n color?: string;\n /** Glyph density — controls font-size. */\n density?: Density;\n /** Animation pace — controls frame interval. */\n pace?: Pace;\n /** Trail persistence — smaller decay = denser cumulative background. */\n decay?: Decay;\n /**\n * Built-in surface beneath the rain. `transparent` (default) lets the\n * parent provide its own background; `solid` paints a near-black\n * surface so the rain reads cleanly without the consumer wrapping it\n * themselves — useful for standalone demos or full-bleed easter eggs.\n */\n background?: 'transparent' | 'solid';\n /**\n * Visual treatment.\n * - `clean` — just the rain.\n * - `terminal` — Fallout-CRT: vignette + scanlines + bloom + glow.\n * - `hologram` — sci-fi HUD: soft scanlines + slow opacity pulse.\n * - `synthwave` — 80s neon: heavy bloom + indigo horizon + accent→\n * info gradient across columns (overrides `tone`).\n * - `oscilloscope` — vintage scope: sharp edges + dense scanlines +\n * animated horizontal beam sweep.\n * - `ghost` — production-friendly faint background variant.\n */\n vibe?:\n | 'clean'\n | 'terminal'\n | 'hologram'\n | 'synthwave'\n | 'oscilloscope'\n | 'ghost';\n /**\n * When `true`, gives each column a stable random speed multiplier\n * (0.6×–1.4× of the base pace) and adds a small horizontal jitter to\n * each glyph. Pairs with any vibe — makes the rain feel alive vs.\n * metronomic.\n */\n storm?: boolean;\n /**\n * Radial mask. `center` fades the canvas to fully transparent in the\n * middle so foreground content sitting over the rain stays readable\n * (e.g. code-block easter egg with copy in the middle).\n */\n mask?: 'none' | 'center';\n /**\n * Inner clear-zone radius for `mask=\"center\"`. Ignored when `mask`\n * is `none`. T-shirt sizes map to: xs 15%, sm 22%, md 30% (default),\n * lg 42%, xl 55%.\n */\n maskRadius?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';\n /** Class merged onto the wrapper. */\n className?: string;\n}\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport const MatrixRain = forwardRef<HTMLDivElement, MatrixRainProps>(\n function MatrixRain(\n {\n glyphs = 'katakana',\n tone = 'primary',\n color,\n density = 'medium',\n pace = 'normal',\n decay = 'slow',\n vibe = 'clean',\n storm = false,\n mask = 'none',\n maskRadius = 'md',\n background = 'transparent',\n className,\n },\n ref,\n ) {\n const canvasRef = useRef<HTMLCanvasElement | null>(null);\n\n // Resolve the glyph string from a preset key or literal pass-through.\n const glyphString = useMemo<string>(() => {\n if (glyphs in GLYPH_PRESETS) {\n return GLYPH_PRESETS[glyphs as GlyphPreset];\n }\n return glyphs;\n }, [glyphs]);\n\n const fontSize = DENSITY_FONT_PX[density];\n const frameInterval = PACE_FRAME_MS[pace];\n const decayAlpha = DECAY_ALPHA[decay];\n\n useEffect(() => {\n const canvas = canvasRef.current;\n if (!canvas) return;\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n // Bail entirely under reduced-motion. The CSS overlay is also\n // suppressed by media-query in the consumer's stylesheet if needed\n // — defence in depth, but the JS is the authoritative gate here.\n const reduceMotionMql =\n typeof window !== 'undefined' && typeof window.matchMedia === 'function'\n ? window.matchMedia('(prefers-reduced-motion: reduce)')\n : null;\n if (reduceMotionMql?.matches) return;\n\n // Resolve colour: explicit prop wins; otherwise read the theme\n // token. Final fallback is the canvas's inherited `color` (cascade\n // of the host `<div>`), which the browser always resolves to a\n // usable value — keeps a literal hex out of component code.\n const resolvedColor = (() => {\n if (color) return color;\n if (typeof window === 'undefined') return '';\n const fromVar = getComputedStyle(document.documentElement)\n .getPropertyValue(TONE_VAR[tone])\n .trim();\n return fromVar || getComputedStyle(canvas).color;\n })();\n\n // Resolve --font-mono at runtime so the kit's font fallback chain\n // (incl. Noto Sans JP for katakana) flows through to canvas.\n const fontFamily = (() => {\n if (typeof window === 'undefined') return 'monospace';\n const fromVar = getComputedStyle(document.documentElement)\n .getPropertyValue('--font-mono')\n .trim();\n return fromVar || 'monospace';\n })();\n\n const dpr = window.devicePixelRatio || 1;\n let columns = 0;\n let drops: number[] = [];\n // Synthwave: per-column accent → info gradient. Resolved through\n // a temporary probe element so we get back fully-resolved rgb()\n // strings the canvas API accepts. Empty when not in synthwave.\n let columnColors: string[] = [];\n // Storm: per-column random speed factor (0.6×–1.4× base pace) +\n // glyph horizontal jitter. Stable across frames, recomputed on\n // each fit() so columns stay coherent.\n let columnSpeeds: number[] = [];\n\n const fit = () => {\n const rect = canvas.getBoundingClientRect();\n canvas.width = Math.max(1, Math.floor(rect.width * dpr));\n canvas.height = Math.max(1, Math.floor(rect.height * dpr));\n // Render in CSS pixels so font metrics stay sharp on HiDPI.\n ctx.setTransform(dpr, 0, 0, dpr, 0, 0);\n columns = Math.max(1, Math.floor(rect.width / fontSize));\n drops = new Array(columns).fill(0).map(() =>\n // Random initial offset so columns never start in sync.\n Math.floor(Math.random() * (rect.height / fontSize)),\n );\n\n if (vibe === 'synthwave') {\n // Build the per-column gradient by resolving color-mix()\n // through a probe span. Browser handles the OKLCH math; we\n // just store the resulting rgb() string per column.\n const probe = document.createElement('span');\n probe.style.display = 'none';\n document.documentElement.appendChild(probe);\n columnColors = new Array(columns).fill('').map((_, i) => {\n const t = (i / Math.max(1, columns - 1)) * 100;\n probe.style.color = `color-mix(in oklch, var(--accent) ${\n 100 - t\n }%, var(--info) ${t}%)`;\n const computed = getComputedStyle(probe).color;\n return computed || resolvedColor;\n });\n document.documentElement.removeChild(probe);\n } else {\n columnColors = [];\n }\n\n if (storm) {\n columnSpeeds = new Array(columns)\n .fill(0)\n .map(() => 0.6 + Math.random() * 0.8);\n } else {\n columnSpeeds = [];\n }\n };\n\n let lastFrame = 0;\n let rafHandle = 0;\n let isVisible = true;\n let isOnscreen = true;\n\n const draw = (now: number) => {\n if (now - lastFrame >= frameInterval) {\n lastFrame = now;\n const rect = canvas.getBoundingClientRect();\n\n // Trail decay — `destination-out` fades existing pixels by\n // `decayAlpha` each frame. Skip when `decay === 'none'` so\n // trails are permanent (eventually saturate; intended).\n // Under `destination-out` only the alpha channel matters, so\n // we drive the fade via `globalAlpha` and any opaque CSS-keyword\n // fillStyle — no rgba literal needed.\n if (decayAlpha !== null) {\n ctx.globalCompositeOperation = 'destination-out';\n ctx.globalAlpha = decayAlpha;\n ctx.fillStyle = 'black';\n ctx.fillRect(0, 0, rect.width, rect.height);\n ctx.globalAlpha = 1;\n }\n\n ctx.globalCompositeOperation = 'source-over';\n ctx.font = `${fontSize}px ${fontFamily}`;\n ctx.textBaseline = 'top';\n // Per-glyph phosphor glow (canvas shadowBlur). On for vibes\n // that need an emission envelope; off for sharp variants.\n const wantsGlow =\n vibe === 'terminal' || vibe === 'hologram' || vibe === 'synthwave';\n if (wantsGlow) {\n ctx.shadowColor = resolvedColor;\n ctx.shadowBlur = Math.max(4, fontSize * 0.6);\n } else {\n ctx.shadowBlur = 0;\n }\n\n // Default fill (overridden per-column for synthwave).\n if (vibe !== 'synthwave') ctx.fillStyle = resolvedColor;\n\n for (let i = 0; i < columns; i += 1) {\n const ch = glyphString.charAt(\n Math.floor(Math.random() * glyphString.length),\n );\n // Storm: small horizontal jitter so rows feel alive.\n const jitter = storm ? (Math.random() - 0.5) * 2 : 0;\n const x = i * fontSize + jitter;\n const y = drops[i] * fontSize;\n\n // Synthwave: gradient colour per column.\n if (vibe === 'synthwave' && columnColors[i]) {\n ctx.fillStyle = columnColors[i];\n if (wantsGlow) ctx.shadowColor = columnColors[i];\n }\n\n ctx.fillText(ch, x, y);\n\n // Reset randomly once past the bottom so columns restart\n // staggered rather than all at once.\n if (y > rect.height && Math.random() > 0.97) {\n drops[i] = 0;\n }\n // Storm: per-column variable advance speed.\n drops[i] += storm ? columnSpeeds[i] || 1 : 1;\n }\n }\n rafHandle = window.requestAnimationFrame(draw);\n };\n\n const start = () => {\n if (rafHandle) return;\n if (!isVisible || !isOnscreen) return;\n lastFrame = window.performance ? window.performance.now() : 0;\n rafHandle = window.requestAnimationFrame(draw);\n };\n const stop = () => {\n if (rafHandle) {\n window.cancelAnimationFrame(rafHandle);\n rafHandle = 0;\n }\n };\n\n fit();\n start();\n\n // Resize with the container.\n const resizeObserver =\n typeof ResizeObserver !== 'undefined' ? new ResizeObserver(fit) : null;\n resizeObserver?.observe(canvas);\n const onWindowResize = () => fit();\n if (!resizeObserver) window.addEventListener('resize', onWindowResize);\n\n // Pause when tab is hidden.\n const onVisibility = () => {\n isVisible = !document.hidden;\n if (isVisible) start();\n else stop();\n };\n document.addEventListener('visibilitychange', onVisibility);\n\n // Pause when scrolled off-screen.\n const intersectionObserver =\n typeof IntersectionObserver !== 'undefined'\n ? new IntersectionObserver(\n (entries) => {\n isOnscreen = entries.some((e) => e.isIntersecting);\n if (isOnscreen) start();\n else stop();\n },\n { threshold: 0 },\n )\n : null;\n intersectionObserver?.observe(canvas);\n\n // Pause if reduced-motion gets toggled at runtime.\n const onReduceMotionChange = () => {\n if (reduceMotionMql?.matches) stop();\n else start();\n };\n reduceMotionMql?.addEventListener?.('change', onReduceMotionChange);\n\n return () => {\n stop();\n resizeObserver?.disconnect();\n intersectionObserver?.disconnect();\n if (!resizeObserver)\n window.removeEventListener('resize', onWindowResize);\n document.removeEventListener('visibilitychange', onVisibility);\n reduceMotionMql?.removeEventListener?.('change', onReduceMotionChange);\n };\n }, [\n glyphString,\n tone,\n color,\n fontSize,\n frameInterval,\n decayAlpha,\n vibe,\n storm,\n ]);\n\n return (\n <div\n ref={ref}\n aria-hidden=\"true\"\n data-component=\"matrix-rain\"\n className={[\n wrapperVariants({ background, vibe, mask, maskRadius }),\n className,\n ]\n .filter(Boolean)\n .join(' ')}\n >\n <canvas\n ref={canvasRef}\n className=\"ds:absolute ds:inset-0 ds:block ds:size-full\"\n />\n </div>\n );\n },\n);\n\nMatrixRain.displayName = 'MatrixRain';\n"],"names":["KATAKANA_GLYPHS","HEX_GLYPHS","BINARY_GLYPHS","SYMBOL_GLYPHS","GLYPH_PRESETS","wrapperVariants","cva","TONE_VAR","DENSITY_FONT_PX","PACE_FRAME_MS","DECAY_ALPHA","MatrixRain","forwardRef","glyphs","tone","color","density","pace","decay","vibe","storm","mask","maskRadius","background","className","ref","canvasRef","useRef","glyphString","useMemo","fontSize","frameInterval","decayAlpha","useEffect","canvas","ctx","reduceMotionMql","resolvedColor","fontFamily","dpr","columns","drops","columnColors","columnSpeeds","fit","rect","probe","_","i","t","lastFrame","rafHandle","isVisible","isOnscreen","draw","now","wantsGlow","ch","jitter","x","y","start","stop","resizeObserver","onWindowResize","onVisibility","intersectionObserver","entries","e","onReduceMotionChange","_a","jsx"],"mappings":"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"}
|
|
@@ -2,9 +2,9 @@ import { jsx as a, jsxs as l } from "react/jsx-runtime";
|
|
|
2
2
|
import { forwardRef as B, useMemo as L, useState as U, useRef as W, useCallback as _ } from "react";
|
|
3
3
|
import { c as D } from "./index-D2ZczOXr.js";
|
|
4
4
|
import { useTranslation as E } from "react-i18next";
|
|
5
|
-
import { I as H } from "./icon-button-
|
|
5
|
+
import { I as H } from "./icon-button-BRHSSFmZ.js";
|
|
6
6
|
import { B as k } from "./button-DD_0Xdmr.js";
|
|
7
|
-
import { A as X } from "./avatar-
|
|
7
|
+
import { A as X } from "./avatar-D_H4emLo.js";
|
|
8
8
|
import { T as q } from "./timestamp-BV2lC-wV.js";
|
|
9
9
|
import { X as G } from "./x-CCcI3eJp.js";
|
|
10
10
|
const J = D(
|
|
@@ -277,4 +277,4 @@ export {
|
|
|
277
277
|
Q as M,
|
|
278
278
|
O as i
|
|
279
279
|
};
|
|
280
|
-
//# sourceMappingURL=message-card-
|
|
280
|
+
//# sourceMappingURL=message-card-DjRtA8GG.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-card-i61k1TGc.js","sources":["../../src/components/message-card/message-card.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { X } from 'lucide-react';\nimport { IconButton } from '../button/icon-button';\nimport { Button } from '../button/button';\nimport { Avatar } from '../avatar/avatar';\nimport { Timestamp } from '../timestamp';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport interface MessageSender {\n /** Display name — drives the avatar's deterministic colour + initials. */\n name: string;\n /** Optional avatar image URL. */\n avatarUrl?: string;\n}\n\nexport interface MessageItem {\n /** Unique identifier for the message (or thread). */\n id: string;\n /** Sender identity — avatar + bold display name. */\n sender: MessageSender;\n /** Optional subject / conversation title. Rendered bold when unread. */\n subject?: string;\n /** Last-message preview — rendered as plain text, clamped to two lines. */\n preview: string;\n /** ISO-8601 timestamp of when the message was sent. */\n sentAt: string;\n /** Whether the message has been seen. Unread items get accent styling. */\n read?: boolean;\n /** Optional deep link — when present the card row is an anchor. */\n url?: string;\n /**\n * Count of unread messages inside a thread. Rendered as an end-aligned\n * badge when greater than 1.\n */\n unreadCount?: number;\n}\n\nexport interface MessageCardProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'onClick' | 'role' | 'title'>,\n VariantProps<typeof cardVariants> {\n /** The message to render. */\n item: MessageItem;\n /**\n * Layout shape.\n * - `compact` — single-line row with the whole card clickable (used by\n * MessageTray).\n * - `dashboard` — bordered block with explicit CTA and mark-as-read\n * controls (used by dashboards / sidebars).\n */\n variant?: 'compact' | 'dashboard';\n /** Visual density. */\n size?: 'sm' | 'md';\n /** Fires when the row / title is activated. */\n onActivate?: (item: MessageItem) => void;\n /** Fires when the dismiss control is activated. */\n onDismiss?: (item: MessageItem) => void;\n /**\n * Label for the dashboard-variant CTA. Only rendered when `variant` is\n * `'dashboard'` and the item has a `url`.\n */\n ctaLabel?: string;\n /**\n * Label for the dashboard-variant mark-as-read link. Only rendered when\n * `variant` is `'dashboard'` and `onDismiss` is supplied.\n */\n dismissLabel?: string;\n /**\n * External exit-animation control. When supplied the card plays its\n * fade-out when this turns `true` and the consumer owns the subsequent\n * unmount (see MessageTray). If omitted, the card self-manages the\n * exit on internal dismiss.\n */\n leaving?: boolean;\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst cardVariants = cva(\n [\n 'ds:relative ds:flex ds:gap-[var(--spacing-sm)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:transition-colors',\n 'ds:motion-safe:animate-in ds:motion-safe:fade-in-0 ds:motion-safe:slide-in-from-top-2 ds:motion-safe:duration-[var(--animation-duration)]',\n 'ds:data-[leaving=true]:motion-safe:animate-out ds:data-[leaving=true]:motion-safe:fade-out-0 ds:data-[leaving=true]:motion-safe:slide-out-to-top-2',\n 'ds:data-[leaving=true]:motion-safe:fill-mode-forwards',\n 'ds:data-[leaving=true]:pointer-events-none',\n 'ds:motion-reduce:transition-none',\n 'ds:text-start',\n 'ds:forced-colors:border ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n {\n variants: {\n variant: {\n compact: 'ds:items-start ds:group',\n dashboard:\n 'ds:flex-col ds:sm:flex-row ds:items-stretch ds:sm:items-start ds:border ds:border-[color:var(--border)] ds:bg-[color:var(--card)]',\n },\n size: {\n sm: 'ds:p-[var(--spacing-sm)]',\n md: 'ds:p-[var(--spacing-md)]',\n },\n state: {\n unread: '',\n read: 'ds:bg-transparent',\n },\n },\n compoundVariants: [\n {\n variant: 'compact',\n state: 'unread',\n class: 'ds:bg-[color:var(--accent)]/5',\n },\n {\n variant: 'compact',\n state: 'read',\n class: 'ds:hover:bg-[color:var(--muted)]/40',\n },\n {\n variant: 'dashboard',\n state: 'unread',\n class: 'ds:bg-[color:var(--accent)]/5',\n },\n ],\n defaultVariants: {\n variant: 'compact',\n size: 'sm',\n state: 'read',\n },\n },\n);\n\nconst stretchedLinkClass = [\n 'ds:focus-visible:outline-none',\n \"ds:after:content-[''] ds:after:absolute ds:after:inset-0 ds:after:rounded-[var(--radius-sm)]\",\n 'ds:after:pointer-events-auto',\n 'ds:focus-visible:after:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:after:outline-solid',\n 'ds:focus-visible:after:outline-[color:var(--ring)]',\n 'ds:focus-visible:after:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:after:outline-[CanvasText]',\n].join(' ');\n\n/* ------------------------------------------------------------------ */\n/* Helpers */\n/* ------------------------------------------------------------------ */\n\nexport function isSafeMessageUrl(url: string): boolean {\n // Reject protocol-relative (//host), javascript:, data:, mailto: etc.\n // Only http(s), same-origin absolute paths (/), and hash (#) anchors pass.\n return /^(https?:\\/\\/(?!\\/)|\\/(?!\\/)|#)/.test(url);\n}\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport const MessageCard = forwardRef<HTMLDivElement, MessageCardProps>(\n (\n {\n item,\n variant = 'compact',\n size = 'sm',\n onActivate,\n onDismiss,\n ctaLabel,\n dismissLabel,\n leaving,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n\n const accessibleTime = useMemo(() => {\n const date = new Date(item.sentAt);\n if (Number.isNaN(date.getTime())) return '';\n return new Intl.DateTimeFormat(i18n.language, {\n dateStyle: 'medium',\n timeStyle: 'short',\n }).format(date);\n }, [item.sentAt, i18n.language]);\n\n const isControlledLeaving = leaving !== undefined;\n const [isLeaving, setIsLeaving] = useState(false);\n const dismissTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const effectiveLeaving = isControlledLeaving ? leaving : isLeaving;\n\n const prefersReducedMotion =\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n const handleDismiss = useCallback(\n (event?: React.MouseEvent) => {\n // The card carries a stretched-link `::after` overlay for the\n // whole-row click target. The dismiss button is rendered above it\n // (z-index), but click events still bubble — stop propagation so the\n // wrapper's navigation does not fire alongside the dismiss action.\n event?.preventDefault();\n event?.stopPropagation();\n if (!onDismiss) return;\n if (isControlledLeaving || prefersReducedMotion) {\n onDismiss(item);\n return;\n }\n setIsLeaving(true);\n if (dismissTimerRef.current) clearTimeout(dismissTimerRef.current);\n const raw =\n (typeof window !== 'undefined' &&\n window\n .getComputedStyle(document.documentElement)\n .getPropertyValue('--animation-duration')) ||\n '200ms';\n const ms = raw.trim().endsWith('ms')\n ? parseFloat(raw)\n : parseFloat(raw) * 1000;\n dismissTimerRef.current = setTimeout(\n () => onDismiss(item),\n Number.isFinite(ms) ? ms : 200,\n );\n },\n [onDismiss, item, isControlledLeaving, prefersReducedMotion],\n );\n\n const state = item.read ? 'read' : 'unread';\n\n const unreadSuffix = item.read\n ? ''\n : t('messageCard.unreadSuffix', ', unread');\n const subjectFragment = item.subject\n ? t('messageCard.subjectFragment', {\n subject: item.subject,\n defaultValue: ' — {{subject}}',\n })\n : '';\n const ariaLabel = t('messageCard.itemLabel', {\n sender: item.sender.name,\n subjectFragment,\n time: accessibleTime,\n unreadSuffix,\n defaultValue:\n 'Message from {{sender}}{{subjectFragment}}, {{time}}{{unreadSuffix}}',\n });\n\n const hasSafeUrl = !!item.url && isSafeMessageUrl(item.url);\n\n /* ------- Sender-name rendering (stretched link in compact mode) ------ */\n\n const senderText = (\n <span\n className={[\n 'ds:flex-1 ds:min-w-0 ds:truncate',\n item.read ? 'ds:font-normal' : 'ds:font-semibold',\n ].join(' ')}\n >\n {item.sender.name}\n </span>\n );\n\n let senderNode: ReactNode;\n if (variant === 'compact' && hasSafeUrl && onActivate) {\n senderNode = (\n <a\n href={item.url}\n aria-label={ariaLabel}\n className={stretchedLinkClass + ' ds:contents'}\n onClick={(event) => {\n // Let the browser handle modifier-click (open in new tab,\n // download, etc.) and respect upstream preventDefault.\n if (\n event.defaultPrevented ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey\n )\n return;\n // When the consumer wires `onActivate`, they own routing — stop\n // the browser's default navigation so we don't full-page reload\n // out of an SPA shell or a test iframe.\n event.preventDefault();\n onActivate(item);\n }}\n >\n {senderText}\n </a>\n );\n } else if (variant === 'compact' && onActivate) {\n senderNode = (\n <button\n type=\"button\"\n aria-label={ariaLabel}\n className={\n stretchedLinkClass +\n ' ds:contents ds:bg-transparent ds:border-0 ds:p-0'\n }\n onClick={() => onActivate(item)}\n >\n {senderText}\n </button>\n );\n } else if (variant === 'dashboard' && hasSafeUrl && onActivate) {\n senderNode = (\n <a\n href={item.url}\n className=\"ds:text-[color:var(--foreground)] ds:no-underline ds:hover:underline ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]\"\n onClick={(event) => {\n if (\n event.defaultPrevented ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey\n )\n return;\n onActivate(item);\n }}\n >\n {senderText}\n </a>\n );\n } else {\n senderNode = senderText;\n }\n\n const showThreadCount =\n typeof item.unreadCount === 'number' && item.unreadCount > 1;\n\n return (\n <div\n ref={ref}\n role=\"listitem\"\n data-component=\"message-card\"\n data-component-id={item.id}\n data-read={item.read ? 'true' : 'false'}\n data-leaving={effectiveLeaving ? 'true' : undefined}\n aria-hidden={effectiveLeaving || undefined}\n className={cardVariants({ variant, size, state, className })}\n {...rest}\n >\n {/* Avatar is decorative here — the row's assembled `aria-label`\n already names the sender, so letting Avatar contribute its own\n `role=\"img\"` + `aria-label={name}` would announce the name twice\n per row. `aria-hidden` + `role=\"presentation\"` (spread last, so\n they win over Avatar's internal values) pulls the element out of\n the a11y tree entirely. */}\n <Avatar\n name={item.sender.name}\n src={item.sender.avatarUrl}\n size={size === 'md' ? 'md' : 'sm'}\n className=\"ds:shrink-0\"\n aria-hidden=\"true\"\n role=\"presentation\"\n aria-label={undefined}\n />\n\n <div className=\"ds:flex-1 ds:min-w-0 ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n {!item.read ? (\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-block ds:size-1.5 ds:shrink-0 ds:rounded-[var(--radius-full)] ds:bg-[color:var(--primary)] ds:forced-colors:bg-[Highlight]\"\n />\n ) : null}\n {variant === 'dashboard' ? (\n <h3 className=\"ds:m-0 ds:flex-1 ds:min-w-0 type-title-item\">\n {senderNode}\n </h3>\n ) : (\n <span className=\"ds:flex-1 ds:min-w-0 type-title-item ds:text-[color:var(--foreground)]\">\n {senderNode}\n </span>\n )}\n {showThreadCount ? (\n <span\n aria-label={t('messageCard.threadCount', {\n count: item.unreadCount,\n defaultValue_one: '{{count}} new message in thread',\n defaultValue_other: '{{count}} new messages in thread',\n })}\n className=\"ds:relative ds:z-[1] ds:shrink-0 ds:inline-flex ds:items-center ds:justify-center ds:min-w-[calc(var(--spacing-md)+var(--spacing-xs))] ds:h-[calc(var(--spacing-md)+var(--spacing-xs))] ds:ps-[calc(var(--spacing-xs)/1.5)] ds:pe-[calc(var(--spacing-xs)/1.5)] ds:rounded-[var(--radius-full)] ds:bg-[color:var(--accent)] ds:text-[color:var(--accent-foreground)] ds:text-[length:var(--font-size-xs)] ds:font-semibold ds:leading-none ds:forced-colors:outline ds:forced-colors:outline-1 ds:forced-colors:outline-[CanvasText]\"\n >\n {item.unreadCount}\n </span>\n ) : null}\n </div>\n\n {item.subject ? (\n <p\n className={[\n 'ds:m-0 type-body-sm ds:text-[color:var(--foreground)] ds:truncate',\n item.read ? 'ds:font-normal' : 'ds:font-semibold',\n ].join(' ')}\n >\n {item.subject}\n </p>\n ) : null}\n\n <p className=\"ds:m-0 type-body-sm ds:text-[color:var(--muted-foreground)] ds:[overflow:hidden] ds:[display:-webkit-box] ds:[-webkit-box-orient:vertical] ds:[-webkit-line-clamp:2] ds:break-words\">\n {item.preview}\n </p>\n\n <Timestamp\n value={item.sentAt}\n shape=\"chip\"\n size=\"sm\"\n relativeWindow={12 * 60 * 60 * 1000}\n />\n\n {variant === 'dashboard' && (ctaLabel || dismissLabel) ? (\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n {ctaLabel && hasSafeUrl ? (\n <Button\n intent=\"outline\"\n size=\"sm\"\n asChild\n className=\"ds:relative ds:z-[1]\"\n >\n <a\n href={item.url}\n onClick={(event) => {\n if (\n event.defaultPrevented ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey\n )\n return;\n onActivate?.(item);\n }}\n >\n {ctaLabel}\n </a>\n </Button>\n ) : null}\n {dismissLabel && onDismiss ? (\n <Button\n intent=\"link\"\n size=\"sm\"\n onClick={handleDismiss}\n className=\"ds:relative ds:z-[1]\"\n >\n {dismissLabel}\n </Button>\n ) : null}\n </div>\n ) : null}\n </div>\n\n {variant === 'compact' && onDismiss ? (\n <span className=\"ds:relative ds:z-[1] ds:opacity-0 ds:group-hover:opacity-100 ds:group-focus-within:opacity-100 ds:transition-opacity ds:motion-reduce:transition-none\">\n <IconButton\n icon={<X />}\n intent=\"ghost\"\n size=\"sm\"\n aria-label={t('messageCard.dismiss', 'Dismiss message')}\n onClick={handleDismiss}\n />\n </span>\n ) : null}\n </div>\n );\n },\n);\n\nMessageCard.displayName = 'MessageCard';\n"],"names":["cardVariants","cva","stretchedLinkClass","isSafeMessageUrl","url","MessageCard","forwardRef","item","variant","size","onActivate","onDismiss","ctaLabel","dismissLabel","leaving","className","rest","ref","t","i18n","useTranslation","accessibleTime","useMemo","date","isControlledLeaving","isLeaving","setIsLeaving","useState","dismissTimerRef","useRef","effectiveLeaving","prefersReducedMotion","handleDismiss","useCallback","event","raw","ms","state","unreadSuffix","subjectFragment","ariaLabel","hasSafeUrl","senderText","jsx","senderNode","showThreadCount","jsxs","Avatar","Timestamp","Button","IconButton","X"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"message-card-DjRtA8GG.js","sources":["../../src/components/message-card/message-card.tsx"],"sourcesContent":["import {\n forwardRef,\n useCallback,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n type ReactNode,\n} from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { X } from 'lucide-react';\nimport { IconButton } from '../button/icon-button';\nimport { Button } from '../button/button';\nimport { Avatar } from '../avatar/avatar';\nimport { Timestamp } from '../timestamp';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\nexport interface MessageSender {\n /** Display name — drives the avatar's deterministic colour + initials. */\n name: string;\n /** Optional avatar image URL. */\n avatarUrl?: string;\n}\n\nexport interface MessageItem {\n /** Unique identifier for the message (or thread). */\n id: string;\n /** Sender identity — avatar + bold display name. */\n sender: MessageSender;\n /** Optional subject / conversation title. Rendered bold when unread. */\n subject?: string;\n /** Last-message preview — rendered as plain text, clamped to two lines. */\n preview: string;\n /** ISO-8601 timestamp of when the message was sent. */\n sentAt: string;\n /** Whether the message has been seen. Unread items get accent styling. */\n read?: boolean;\n /** Optional deep link — when present the card row is an anchor. */\n url?: string;\n /**\n * Count of unread messages inside a thread. Rendered as an end-aligned\n * badge when greater than 1.\n */\n unreadCount?: number;\n}\n\nexport interface MessageCardProps\n extends\n Omit<HTMLAttributes<HTMLDivElement>, 'onClick' | 'role' | 'title'>,\n VariantProps<typeof cardVariants> {\n /** The message to render. */\n item: MessageItem;\n /**\n * Layout shape.\n * - `compact` — single-line row with the whole card clickable (used by\n * MessageTray).\n * - `dashboard` — bordered block with explicit CTA and mark-as-read\n * controls (used by dashboards / sidebars).\n */\n variant?: 'compact' | 'dashboard';\n /** Visual density. */\n size?: 'sm' | 'md';\n /** Fires when the row / title is activated. */\n onActivate?: (item: MessageItem) => void;\n /** Fires when the dismiss control is activated. */\n onDismiss?: (item: MessageItem) => void;\n /**\n * Label for the dashboard-variant CTA. Only rendered when `variant` is\n * `'dashboard'` and the item has a `url`.\n */\n ctaLabel?: string;\n /**\n * Label for the dashboard-variant mark-as-read link. Only rendered when\n * `variant` is `'dashboard'` and `onDismiss` is supplied.\n */\n dismissLabel?: string;\n /**\n * External exit-animation control. When supplied the card plays its\n * fade-out when this turns `true` and the consumer owns the subsequent\n * unmount (see MessageTray). If omitted, the card self-manages the\n * exit on internal dismiss.\n */\n leaving?: boolean;\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst cardVariants = cva(\n [\n 'ds:relative ds:flex ds:gap-[var(--spacing-sm)]',\n 'ds:rounded-[var(--radius-sm)]',\n 'ds:transition-colors',\n 'ds:motion-safe:animate-in ds:motion-safe:fade-in-0 ds:motion-safe:slide-in-from-top-2 ds:motion-safe:duration-[var(--animation-duration)]',\n 'ds:data-[leaving=true]:motion-safe:animate-out ds:data-[leaving=true]:motion-safe:fade-out-0 ds:data-[leaving=true]:motion-safe:slide-out-to-top-2',\n 'ds:data-[leaving=true]:motion-safe:fill-mode-forwards',\n 'ds:data-[leaving=true]:pointer-events-none',\n 'ds:motion-reduce:transition-none',\n 'ds:text-start',\n 'ds:forced-colors:border ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n {\n variants: {\n variant: {\n compact: 'ds:items-start ds:group',\n dashboard:\n 'ds:flex-col ds:sm:flex-row ds:items-stretch ds:sm:items-start ds:border ds:border-[color:var(--border)] ds:bg-[color:var(--card)]',\n },\n size: {\n sm: 'ds:p-[var(--spacing-sm)]',\n md: 'ds:p-[var(--spacing-md)]',\n },\n state: {\n unread: '',\n read: 'ds:bg-transparent',\n },\n },\n compoundVariants: [\n {\n variant: 'compact',\n state: 'unread',\n class: 'ds:bg-[color:var(--accent)]/5',\n },\n {\n variant: 'compact',\n state: 'read',\n class: 'ds:hover:bg-[color:var(--muted)]/40',\n },\n {\n variant: 'dashboard',\n state: 'unread',\n class: 'ds:bg-[color:var(--accent)]/5',\n },\n ],\n defaultVariants: {\n variant: 'compact',\n size: 'sm',\n state: 'read',\n },\n },\n);\n\nconst stretchedLinkClass = [\n 'ds:focus-visible:outline-none',\n \"ds:after:content-[''] ds:after:absolute ds:after:inset-0 ds:after:rounded-[var(--radius-sm)]\",\n 'ds:after:pointer-events-auto',\n 'ds:focus-visible:after:outline-[length:var(--focus-ring-width)]',\n 'ds:focus-visible:after:outline-solid',\n 'ds:focus-visible:after:outline-[color:var(--ring)]',\n 'ds:focus-visible:after:outline-offset-[length:var(--focus-ring-offset)]',\n 'ds:forced-colors:focus-visible:after:outline-[CanvasText]',\n].join(' ');\n\n/* ------------------------------------------------------------------ */\n/* Helpers */\n/* ------------------------------------------------------------------ */\n\nexport function isSafeMessageUrl(url: string): boolean {\n // Reject protocol-relative (//host), javascript:, data:, mailto: etc.\n // Only http(s), same-origin absolute paths (/), and hash (#) anchors pass.\n return /^(https?:\\/\\/(?!\\/)|\\/(?!\\/)|#)/.test(url);\n}\n\n/* ------------------------------------------------------------------ */\n/* Component */\n/* ------------------------------------------------------------------ */\n\nexport const MessageCard = forwardRef<HTMLDivElement, MessageCardProps>(\n (\n {\n item,\n variant = 'compact',\n size = 'sm',\n onActivate,\n onDismiss,\n ctaLabel,\n dismissLabel,\n leaving,\n className,\n ...rest\n },\n ref,\n ) => {\n const { t, i18n } = useTranslation();\n\n const accessibleTime = useMemo(() => {\n const date = new Date(item.sentAt);\n if (Number.isNaN(date.getTime())) return '';\n return new Intl.DateTimeFormat(i18n.language, {\n dateStyle: 'medium',\n timeStyle: 'short',\n }).format(date);\n }, [item.sentAt, i18n.language]);\n\n const isControlledLeaving = leaving !== undefined;\n const [isLeaving, setIsLeaving] = useState(false);\n const dismissTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const effectiveLeaving = isControlledLeaving ? leaving : isLeaving;\n\n const prefersReducedMotion =\n typeof window !== 'undefined' &&\n typeof window.matchMedia === 'function' &&\n window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n\n const handleDismiss = useCallback(\n (event?: React.MouseEvent) => {\n // The card carries a stretched-link `::after` overlay for the\n // whole-row click target. The dismiss button is rendered above it\n // (z-index), but click events still bubble — stop propagation so the\n // wrapper's navigation does not fire alongside the dismiss action.\n event?.preventDefault();\n event?.stopPropagation();\n if (!onDismiss) return;\n if (isControlledLeaving || prefersReducedMotion) {\n onDismiss(item);\n return;\n }\n setIsLeaving(true);\n if (dismissTimerRef.current) clearTimeout(dismissTimerRef.current);\n const raw =\n (typeof window !== 'undefined' &&\n window\n .getComputedStyle(document.documentElement)\n .getPropertyValue('--animation-duration')) ||\n '200ms';\n const ms = raw.trim().endsWith('ms')\n ? parseFloat(raw)\n : parseFloat(raw) * 1000;\n dismissTimerRef.current = setTimeout(\n () => onDismiss(item),\n Number.isFinite(ms) ? ms : 200,\n );\n },\n [onDismiss, item, isControlledLeaving, prefersReducedMotion],\n );\n\n const state = item.read ? 'read' : 'unread';\n\n const unreadSuffix = item.read\n ? ''\n : t('messageCard.unreadSuffix', ', unread');\n const subjectFragment = item.subject\n ? t('messageCard.subjectFragment', {\n subject: item.subject,\n defaultValue: ' — {{subject}}',\n })\n : '';\n const ariaLabel = t('messageCard.itemLabel', {\n sender: item.sender.name,\n subjectFragment,\n time: accessibleTime,\n unreadSuffix,\n defaultValue:\n 'Message from {{sender}}{{subjectFragment}}, {{time}}{{unreadSuffix}}',\n });\n\n const hasSafeUrl = !!item.url && isSafeMessageUrl(item.url);\n\n /* ------- Sender-name rendering (stretched link in compact mode) ------ */\n\n const senderText = (\n <span\n className={[\n 'ds:flex-1 ds:min-w-0 ds:truncate',\n item.read ? 'ds:font-normal' : 'ds:font-semibold',\n ].join(' ')}\n >\n {item.sender.name}\n </span>\n );\n\n let senderNode: ReactNode;\n if (variant === 'compact' && hasSafeUrl && onActivate) {\n senderNode = (\n <a\n href={item.url}\n aria-label={ariaLabel}\n className={stretchedLinkClass + ' ds:contents'}\n onClick={(event) => {\n // Let the browser handle modifier-click (open in new tab,\n // download, etc.) and respect upstream preventDefault.\n if (\n event.defaultPrevented ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey\n )\n return;\n // When the consumer wires `onActivate`, they own routing — stop\n // the browser's default navigation so we don't full-page reload\n // out of an SPA shell or a test iframe.\n event.preventDefault();\n onActivate(item);\n }}\n >\n {senderText}\n </a>\n );\n } else if (variant === 'compact' && onActivate) {\n senderNode = (\n <button\n type=\"button\"\n aria-label={ariaLabel}\n className={\n stretchedLinkClass +\n ' ds:contents ds:bg-transparent ds:border-0 ds:p-0'\n }\n onClick={() => onActivate(item)}\n >\n {senderText}\n </button>\n );\n } else if (variant === 'dashboard' && hasSafeUrl && onActivate) {\n senderNode = (\n <a\n href={item.url}\n className=\"ds:text-[color:var(--foreground)] ds:no-underline ds:hover:underline ds:focus-visible:outline-[length:var(--focus-ring-width)] ds:focus-visible:outline-solid ds:focus-visible:outline-[color:var(--ring)] ds:focus-visible:outline-offset-[length:var(--focus-ring-offset)]\"\n onClick={(event) => {\n if (\n event.defaultPrevented ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey\n )\n return;\n onActivate(item);\n }}\n >\n {senderText}\n </a>\n );\n } else {\n senderNode = senderText;\n }\n\n const showThreadCount =\n typeof item.unreadCount === 'number' && item.unreadCount > 1;\n\n return (\n <div\n ref={ref}\n role=\"listitem\"\n data-component=\"message-card\"\n data-component-id={item.id}\n data-read={item.read ? 'true' : 'false'}\n data-leaving={effectiveLeaving ? 'true' : undefined}\n aria-hidden={effectiveLeaving || undefined}\n className={cardVariants({ variant, size, state, className })}\n {...rest}\n >\n {/* Avatar is decorative here — the row's assembled `aria-label`\n already names the sender, so letting Avatar contribute its own\n `role=\"img\"` + `aria-label={name}` would announce the name twice\n per row. `aria-hidden` + `role=\"presentation\"` (spread last, so\n they win over Avatar's internal values) pulls the element out of\n the a11y tree entirely. */}\n <Avatar\n name={item.sender.name}\n src={item.sender.avatarUrl}\n size={size === 'md' ? 'md' : 'sm'}\n className=\"ds:shrink-0\"\n aria-hidden=\"true\"\n role=\"presentation\"\n aria-label={undefined}\n />\n\n <div className=\"ds:flex-1 ds:min-w-0 ds:flex ds:flex-col ds:gap-[var(--spacing-sm)]\">\n <div className=\"ds:flex ds:items-center ds:gap-[var(--spacing-xs)]\">\n {!item.read ? (\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-block ds:size-1.5 ds:shrink-0 ds:rounded-[var(--radius-full)] ds:bg-[color:var(--primary)] ds:forced-colors:bg-[Highlight]\"\n />\n ) : null}\n {variant === 'dashboard' ? (\n <h3 className=\"ds:m-0 ds:flex-1 ds:min-w-0 type-title-item\">\n {senderNode}\n </h3>\n ) : (\n <span className=\"ds:flex-1 ds:min-w-0 type-title-item ds:text-[color:var(--foreground)]\">\n {senderNode}\n </span>\n )}\n {showThreadCount ? (\n <span\n aria-label={t('messageCard.threadCount', {\n count: item.unreadCount,\n defaultValue_one: '{{count}} new message in thread',\n defaultValue_other: '{{count}} new messages in thread',\n })}\n className=\"ds:relative ds:z-[1] ds:shrink-0 ds:inline-flex ds:items-center ds:justify-center ds:min-w-[calc(var(--spacing-md)+var(--spacing-xs))] ds:h-[calc(var(--spacing-md)+var(--spacing-xs))] ds:ps-[calc(var(--spacing-xs)/1.5)] ds:pe-[calc(var(--spacing-xs)/1.5)] ds:rounded-[var(--radius-full)] ds:bg-[color:var(--accent)] ds:text-[color:var(--accent-foreground)] ds:text-[length:var(--font-size-xs)] ds:font-semibold ds:leading-none ds:forced-colors:outline ds:forced-colors:outline-1 ds:forced-colors:outline-[CanvasText]\"\n >\n {item.unreadCount}\n </span>\n ) : null}\n </div>\n\n {item.subject ? (\n <p\n className={[\n 'ds:m-0 type-body-sm ds:text-[color:var(--foreground)] ds:truncate',\n item.read ? 'ds:font-normal' : 'ds:font-semibold',\n ].join(' ')}\n >\n {item.subject}\n </p>\n ) : null}\n\n <p className=\"ds:m-0 type-body-sm ds:text-[color:var(--muted-foreground)] ds:[overflow:hidden] ds:[display:-webkit-box] ds:[-webkit-box-orient:vertical] ds:[-webkit-line-clamp:2] ds:break-words\">\n {item.preview}\n </p>\n\n <Timestamp\n value={item.sentAt}\n shape=\"chip\"\n size=\"sm\"\n relativeWindow={12 * 60 * 60 * 1000}\n />\n\n {variant === 'dashboard' && (ctaLabel || dismissLabel) ? (\n <div className=\"ds:flex ds:flex-wrap ds:items-center ds:gap-[var(--spacing-sm)]\">\n {ctaLabel && hasSafeUrl ? (\n <Button\n intent=\"outline\"\n size=\"sm\"\n asChild\n className=\"ds:relative ds:z-[1]\"\n >\n <a\n href={item.url}\n onClick={(event) => {\n if (\n event.defaultPrevented ||\n event.metaKey ||\n event.ctrlKey ||\n event.shiftKey\n )\n return;\n onActivate?.(item);\n }}\n >\n {ctaLabel}\n </a>\n </Button>\n ) : null}\n {dismissLabel && onDismiss ? (\n <Button\n intent=\"link\"\n size=\"sm\"\n onClick={handleDismiss}\n className=\"ds:relative ds:z-[1]\"\n >\n {dismissLabel}\n </Button>\n ) : null}\n </div>\n ) : null}\n </div>\n\n {variant === 'compact' && onDismiss ? (\n <span className=\"ds:relative ds:z-[1] ds:opacity-0 ds:group-hover:opacity-100 ds:group-focus-within:opacity-100 ds:transition-opacity ds:motion-reduce:transition-none\">\n <IconButton\n icon={<X />}\n intent=\"ghost\"\n size=\"sm\"\n aria-label={t('messageCard.dismiss', 'Dismiss message')}\n onClick={handleDismiss}\n />\n </span>\n ) : null}\n </div>\n );\n },\n);\n\nMessageCard.displayName = 'MessageCard';\n"],"names":["cardVariants","cva","stretchedLinkClass","isSafeMessageUrl","url","MessageCard","forwardRef","item","variant","size","onActivate","onDismiss","ctaLabel","dismissLabel","leaving","className","rest","ref","t","i18n","useTranslation","accessibleTime","useMemo","date","isControlledLeaving","isLeaving","setIsLeaving","useState","dismissTimerRef","useRef","effectiveLeaving","prefersReducedMotion","handleDismiss","useCallback","event","raw","ms","state","unreadSuffix","subjectFragment","ariaLabel","hasSafeUrl","senderText","jsx","senderNode","showThreadCount","jsxs","Avatar","Timestamp","Button","IconButton","X"],"mappings":"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"}
|
|
@@ -4,11 +4,11 @@ import * as x from "@radix-ui/react-popover";
|
|
|
4
4
|
import { c as C } from "./index-D2ZczOXr.js";
|
|
5
5
|
import { useTranslation as q } from "react-i18next";
|
|
6
6
|
import { u as le } from "./use-controllable-state-BiY4xTzM.js";
|
|
7
|
-
import { I as me } from "./icon-button-
|
|
7
|
+
import { I as me } from "./icon-button-BRHSSFmZ.js";
|
|
8
8
|
import { B as E } from "./button-DD_0Xdmr.js";
|
|
9
9
|
import { S as L } from "./separator-CYU_bGFn.js";
|
|
10
10
|
import { S as f } from "./skeleton-CZbwyJAA.js";
|
|
11
|
-
import { M as pe } from "./message-card-
|
|
11
|
+
import { M as pe } from "./message-card-DjRtA8GG.js";
|
|
12
12
|
import { u as ue } from "./registry-C9nwlNyL.js";
|
|
13
13
|
import { M as F } from "./mail-C8irm52s.js";
|
|
14
14
|
const ge = {
|
|
@@ -411,4 +411,4 @@ export {
|
|
|
411
411
|
be as M,
|
|
412
412
|
ge as m
|
|
413
413
|
};
|
|
414
|
-
//# sourceMappingURL=message-tray-
|
|
414
|
+
//# sourceMappingURL=message-tray-DfsAMncP.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-tray-DrV7G-wR.js","sources":["../../src/components/message-tray/message-tray.agent.ts","../../src/components/message-tray/message-tray.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — MessageTray. */\n/* */\n/* Tray-level surface: open/close the inbox panel, read message ids and */\n/* unread flag (never sender names / subjects / previews — those are */\n/* PHI), and route per-message operations through the curated handle. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { MessageTrayHandle } from './message-tray';\n\nexport const messageTrayAgent: AgentAdapter<MessageTrayHandle> = {\n id: 'message-tray',\n capabilities: ['open', 'close', 'select_single', 'dismiss'],\n state: {\n items: {\n type: 'Array<{ id: string; read: boolean }>',\n descriptionKey: 'ui.agent.messageTray.state.items',\n description:\n 'Currently-displayed messages. Ids + read flag only — no PHI / no sender names.',\n read: (handle) => handle.getItems(),\n },\n unreadCount: {\n type: 'number',\n descriptionKey: 'ui.agent.messageTray.state.unreadCount',\n description: 'Badge unread count surfaced by the host.',\n read: (handle) => handle.getUnreadCount(),\n },\n isOpen: {\n type: 'boolean',\n descriptionKey: 'ui.agent.messageTray.state.isOpen',\n description: 'Whether the dropdown panel is currently open.',\n read: (handle) => handle.isOpen(),\n },\n },\n actions: {\n open: {\n safety: 'read',\n descriptionKey: 'ui.agent.messageTray.actions.open',\n description: 'Open the message panel.',\n invoke: (handle) => {\n handle.open();\n },\n },\n close: {\n safety: 'read',\n descriptionKey: 'ui.agent.messageTray.actions.close',\n description: 'Close the message panel.',\n invoke: (handle) => {\n handle.close();\n },\n },\n select_item: {\n safety: 'read',\n argsType: '{ id: string }',\n descriptionKey: 'ui.agent.messageTray.actions.selectItem',\n description: 'Activate the message with the given id.',\n invoke: (handle, args: { id: string }) => {\n handle.selectItem(args.id);\n },\n },\n mark_read: {\n safety: 'write',\n argsType: '{ id: string }',\n descriptionKey: 'ui.agent.messageTray.actions.markRead',\n description: 'Request the host to mark a message as read.',\n invoke: (handle, args: { id: string }) => {\n handle.markRead(args.id);\n },\n },\n dismiss: {\n safety: 'destructive',\n argsType: '{ id: string }',\n descriptionKey: 'ui.agent.messageTray.actions.dismiss',\n description:\n 'Request the host to dismiss / archive the message with the given id.',\n invoke: (handle, args: { id: string }) => {\n handle.dismiss(args.id);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'message-tray',\n description: 'Marks the MessageTray wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Required to address a specific tray from the agent.',\n },\n item: {\n attr: 'data-message-id',\n description:\n 'Stable message id emitted on each rendered MessageCard inside the tray.',\n },\n },\n};\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n} from 'react';\nimport * as RadixPopover from '@radix-ui/react-popover';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { useControllableState } from '../../hooks/use-controllable-state';\nimport { Mail } from 'lucide-react';\nimport { IconButton } from '../button/icon-button';\nimport { Button } from '../button/button';\nimport { Separator } from '../separator/separator';\nimport { Skeleton } from '../skeleton/skeleton';\nimport { MessageCard, type MessageItem } from '../message-card/message-card';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { messageTrayAgent } from './message-tray.agent';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\n/**\n * Curated imperative handle for MessageTray. Exposed as the forwardRef\n * target so a future agent / MCP UI bridge can drive the tray without\n * touching the DOM. See `message-tray.agent.ts`.\n */\nexport interface MessageTrayHandle {\n open: () => void;\n close: () => void;\n isOpen: () => boolean;\n getItems: () => Array<{ id: string; read: boolean }>;\n getUnreadCount: () => number;\n selectItem: (id: string) => void;\n markRead: (id: string) => void;\n dismiss: (id: string) => void;\n}\n\nexport interface MessageTrayProps\n extends\n Omit<\n HTMLAttributes<HTMLDivElement>,\n 'onClick' | 'children' | 'role' | 'id'\n >,\n VariantProps<typeof messageTrayVariants> {\n /**\n * Stable instance id. Surfaced on the root as `data-component-id` so\n * an agent / MCP UI bridge can address this specific tray.\n */\n id?: string;\n /** Fires when the host should mark a single message as read (used by agent integration). */\n onMarkRead?: (item: MessageItem) => void;\n /** Messages rendered in the dropdown panel. */\n items: MessageItem[];\n /** Number of unread messages. Drives the badge count. */\n unreadCount?: number;\n /** Controlled open state. */\n open?: boolean;\n /** Fires when the open state changes. */\n onOpenChange?: (open: boolean) => void;\n /** Fires when the user activates an item (click or Enter/Space). */\n onItemClick?: (item: MessageItem) => void;\n /** Fires when the user dismisses / archives a message. */\n onDismiss?: (item: MessageItem) => void;\n /** Fires when the user clicks the header \"Mark all as read\" action. */\n onMarkAllRead?: () => void;\n /** When true the panel shows skeleton placeholders. */\n loading?: boolean;\n /**\n * Advisory item count before the list scrolls. Consumers override the cap\n * via the `--message-tray-max-block-size` custom property.\n */\n maxVisible?: number;\n /** When set renders a footer link that invokes `onViewAll`. */\n viewAllLabel?: string;\n /** Fires when the footer \"View all\" link is clicked. */\n onViewAll?: () => void;\n /** Panel alignment relative to the trigger. Default `'end'`. */\n align?: 'start' | 'center' | 'end';\n /** Side of the trigger to open on. Default `'bottom'`. */\n side?: 'top' | 'bottom';\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst messageTrayVariants = cva('ds:relative ds:inline-flex ds:items-center', {\n variants: {\n size: {\n sm: '',\n md: '',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n});\n\nconst panelVariants = cva(\n [\n 'ds:flex ds:flex-col',\n 'ds:bg-[var(--popover)] ds:text-[var(--popover-foreground)]',\n 'ds:border ds:border-[color:var(--border)]',\n 'ds:rounded-[var(--radius-md)]',\n 'ds:shadow-[var(--shadow-lg)]',\n 'ds:z-[var(--z-popover)]',\n // Width: fluid below the design cap so narrow viewports keep a visible\n // gutter on both sides (shadow included). Cap slightly wider than\n // NotificationTray because message rows carry subject + preview.\n 'ds:w-[min(26rem,calc(100vw-2*var(--spacing-md)))]',\n // Height: below the `sm` breakpoint the panel takes a near-full-screen\n // sheet shape so the user gets room to triage an inbox without\n // scrolling a tiny popover. `6rem` reserves space for the Header\n // (≈4rem) plus the sideOffset + collisionPadding (≈2rem). Above `sm`\n // it returns to `h-auto` so the list's own cap governs the height.\n 'ds:h-[calc(100dvh-6rem)] ds:sm:h-auto',\n 'ds:data-[state=open]:animate-in ds:data-[state=closed]:animate-out',\n 'ds:data-[state=closed]:fade-out-0 ds:data-[state=open]:fade-in-0',\n 'ds:data-[state=closed]:zoom-out-95 ds:data-[state=open]:zoom-in-95',\n 'ds:motion-reduce:transition-none ds:motion-reduce:animate-none',\n 'ds:focus-visible:outline-none',\n 'ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:p-[var(--spacing-xs)]',\n md: 'ds:p-[var(--spacing-sm)]',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n },\n);\n\nconst badgeVariants = cva(\n [\n 'ds:absolute ds:-top-[var(--spacing-xs)] ds:-end-[var(--spacing-xs)]',\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:min-w-[calc(var(--spacing-md)+var(--spacing-xs))] ds:h-[calc(var(--spacing-md)+var(--spacing-xs))] ds:ps-[calc(var(--spacing-xs)/1.5)] ds:pe-[calc(var(--spacing-xs)/1.5)]',\n 'ds:rounded-[var(--radius-full)]',\n 'ds:bg-[color:var(--destructive)] ds:text-[color:var(--destructive-foreground)]',\n 'ds:text-[length:var(--font-size-xs)] ds:font-semibold ds:leading-none',\n 'ds:pointer-events-none ds:select-none',\n 'ds:forced-colors:outline ds:forced-colors:outline-1 ds:forced-colors:outline-[CanvasText]',\n ].join(' '),\n);\n\n/* ------------------------------------------------------------------ */\n/* Helpers */\n/* ------------------------------------------------------------------ */\n\nfunction formatBadgeCount(count: number, overflowLabel: string): string {\n return count > 99 ? overflowLabel : String(count);\n}\n\nfunction SkeletonRow() {\n return (\n <div\n aria-hidden=\"true\"\n className=\"ds:flex ds:items-start ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)]\"\n >\n <Skeleton variant=\"circular\" size=\"sm\" />\n <div className=\"ds:flex-1 ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <Skeleton variant=\"text\" size=\"md\" width=\"60%\" />\n <Skeleton variant=\"text\" size=\"sm\" width=\"80%\" />\n <Skeleton variant=\"text\" size=\"sm\" width=\"95%\" />\n <Skeleton variant=\"text\" size=\"sm\" width=\"30%\" />\n </div>\n </div>\n );\n}\n\nfunction EmptyPanel() {\n const { t } = useTranslation();\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"ds:flex ds:flex-col ds:items-center ds:justify-center ds:gap-[var(--spacing-xs)] ds:p-[var(--spacing-lg)] ds:text-center\"\n >\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-flex ds:items-center ds:justify-center ds:size-10 ds:rounded-[var(--radius-full)] ds:bg-[color:var(--muted)] ds:text-[color:var(--muted-foreground)] ds:[&>svg]:size-5\"\n >\n <Mail />\n </span>\n <p className=\"type-title-item ds:text-[color:var(--foreground)]\">\n {t('messageTray.noMessages', 'No messages')}\n </p>\n <p className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {t('messageTray.noMessagesDescription', 'Your inbox is clear.')}\n </p>\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Root */\n/* ------------------------------------------------------------------ */\n\nexport const MessageTray = forwardRef<HTMLDivElement, MessageTrayProps>(\n (\n {\n id,\n items,\n unreadCount,\n open,\n onOpenChange,\n onItemClick,\n onDismiss,\n onMarkRead,\n onMarkAllRead,\n loading = false,\n maxVisible,\n viewAllLabel,\n onViewAll,\n align = 'end',\n side = 'bottom',\n size = 'md',\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n\n const [isOpenRaw, handleOpenChange] = useControllableState<boolean>({\n value: open,\n defaultValue: false,\n onChange: onOpenChange,\n });\n const isOpen = isOpenRaw ?? false;\n\n /* Exit-animation list — same AnimatePresence-style bookkeeping as\n * NotificationTray. See that component for rationale. */\n type Displayed = { item: MessageItem; leaving: boolean };\n const [displayed, setDisplayed] = useState<Displayed[]>(() =>\n items.map((item) => ({ item, leaving: false })),\n );\n\n const animationDurationMs = useCallback((): number => {\n if (typeof window === 'undefined') return 200;\n const raw = window\n .getComputedStyle(document.documentElement)\n .getPropertyValue('--animation-duration');\n if (!raw) return 200;\n const trimmed = raw.trim();\n const n = parseFloat(trimmed);\n if (!Number.isFinite(n)) return 200;\n return trimmed.endsWith('ms') ? n : n * 1000;\n }, []);\n\n useLayoutEffect(() => {\n setDisplayed((prev) => {\n const nextIds = new Set(items.map((i) => i.id));\n const prevIds = new Set(prev.map((d) => d.item.id));\n\n const merged: Displayed[] = prev.map((d) => {\n if (nextIds.has(d.item.id)) {\n const fresh = items.find((i) => i.id === d.item.id);\n return fresh\n ? { item: fresh, leaving: false }\n : { ...d, leaving: true };\n }\n return { ...d, leaving: true };\n });\n\n for (const i of items) {\n if (!prevIds.has(i.id)) merged.push({ item: i, leaving: false });\n }\n return merged;\n });\n }, [items]);\n\n useEffect(() => {\n if (!displayed.some((d) => d.leaving)) return;\n const ms = animationDurationMs();\n const timer = setTimeout(() => {\n setDisplayed((prev) => prev.filter((d) => !d.leaving));\n }, ms);\n return () => clearTimeout(timer);\n }, [displayed, animationDurationMs]);\n\n const liveRegionRef = useRef<HTMLDivElement | null>(null);\n const lastTopIdRef = useRef<string | undefined>(items[0]?.id);\n\n useEffect(() => {\n const topId = items[0]?.id;\n const prev = lastTopIdRef.current;\n if (prev && topId && prev !== topId && liveRegionRef.current) {\n const newest = items[0];\n if (newest && !newest.read) {\n liveRegionRef.current.textContent = t('messageTray.newMessage', {\n sender: newest.sender.name,\n defaultValue: 'New message from {{sender}}',\n });\n }\n }\n lastTopIdRef.current = topId;\n }, [items, t]);\n\n const displayCount = unreadCount ?? 0;\n const triggerAriaLabel =\n displayCount > 0\n ? t('messageTray.triggerLabel', {\n count: displayCount,\n defaultValue: 'Messages, {{count}} unread',\n })\n : t('messageTray.triggerLabelNone', 'Messages, none unread');\n\n const badgeLabel = formatBadgeCount(\n displayCount,\n t('messageTray.badgeCountOverflow', '99+'),\n );\n\n const panelClass = panelVariants({ size });\n\n /* Curated imperative handle for agent integration. See\n * message-tray.agent.ts. */\n const itemsRef = useRef<MessageItem[]>(items);\n itemsRef.current = items;\n const unreadRef = useRef<number | undefined>(unreadCount);\n unreadRef.current = unreadCount;\n const isOpenRef = useRef<boolean>(isOpen);\n isOpenRef.current = isOpen;\n\n const handle = useMemo<MessageTrayHandle>(\n () => ({\n open: () => handleOpenChange(true),\n close: () => handleOpenChange(false),\n isOpen: () => isOpenRef.current,\n getItems: () =>\n itemsRef.current.map((i) => ({ id: i.id, read: !!i.read })),\n getUnreadCount: () =>\n unreadRef.current ?? itemsRef.current.filter((i) => !i.read).length,\n selectItem: (targetId: string) => {\n const found = itemsRef.current.find((i) => i.id === targetId);\n if (found) onItemClick?.(found);\n },\n markRead: (targetId: string) => {\n const found = itemsRef.current.find((i) => i.id === targetId);\n if (found) onMarkRead?.(found);\n },\n dismiss: (targetId: string) => {\n const found = itemsRef.current.find((i) => i.id === targetId);\n if (found) onDismiss?.(found);\n },\n }),\n [handleOpenChange, onItemClick, onMarkRead, onDismiss],\n );\n\n const rootRef = useRef<HTMLDivElement>(null);\n useImperativeHandle(ref, () => rootRef.current as HTMLDivElement, []);\n useAgentRegistration(messageTrayAgent, handle, id);\n\n return (\n <div\n ref={rootRef}\n data-component=\"message-tray\"\n data-component-id={id}\n className={[messageTrayVariants({ size }), className]\n .filter(Boolean)\n .join(' ')}\n {...rest}\n >\n <RadixPopover.Root open={isOpen} onOpenChange={handleOpenChange}>\n <RadixPopover.Trigger asChild>\n <IconButton\n icon={<Mail />}\n intent=\"outline\"\n size={size === 'sm' ? 'sm' : 'md'}\n aria-label={triggerAriaLabel}\n aria-haspopup=\"dialog\"\n />\n </RadixPopover.Trigger>\n {displayCount > 0 ? (\n <span\n aria-hidden=\"true\"\n data-testid=\"message-tray-badge\"\n className={badgeVariants()}\n >\n {badgeLabel}\n </span>\n ) : null}\n <div\n ref={liveRegionRef}\n aria-live=\"polite\"\n aria-atomic=\"true\"\n className=\"ds:sr-only\"\n />\n <RadixPopover.Portal>\n <RadixPopover.Content\n role=\"dialog\"\n aria-label={t('messageTray.panelTitle', 'Messages')}\n side={side}\n align={align}\n sideOffset={8}\n // `spacing-md` (16px) keeps Radix's collision-avoidance from\n // flush-mounting the panel against the viewport edge when the\n // trigger is near the inline-end of a narrow screen.\n collisionPadding={16}\n className={panelClass}\n >\n <div className=\"ds:flex ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)] ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:pb-[var(--spacing-xs)]\">\n <h3 className=\"ds:m-0 type-title-card ds:text-[color:var(--foreground)]\">\n {t('messageTray.panelTitle', 'Messages')}\n </h3>\n {onMarkAllRead && items.some((item) => !item.read) ? (\n <Button\n intent=\"link\"\n size=\"sm\"\n onClick={onMarkAllRead}\n className=\"ds:text-[length:var(--font-size-xs)]\"\n >\n {t('messageTray.markAllRead', 'Mark all as read')}\n </Button>\n ) : null}\n </div>\n <Separator />\n <div\n // Only carry `role=\"list\"` when there are list children —\n // axe's `aria-required-children` rule fires on an empty\n // list. The loading skeleton + populated rendering both\n // produce role=\"listitem\" descendants below.\n role={displayed.length > 0 ? 'list' : undefined}\n data-max-visible={maxVisible}\n // Below `sm` the panel is a near-full-screen sheet (see\n // `panelVariants`) and the list expands to fill the\n // remaining space with `flex-1`. Above `sm` the list\n // caps at the `--message-tray-max-block-size` custom\n // property so the popover stays compact.\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:overflow-y-auto ds:pt-[var(--spacing-xs)] ds:flex-1 ds:sm:flex-none ds:sm:[max-block-size:var(--message-tray-max-block-size,26rem)]\"\n >\n {loading ? (\n <>\n <SkeletonRow />\n <SkeletonRow />\n <SkeletonRow />\n </>\n ) : displayed.length === 0 ? (\n <EmptyPanel />\n ) : (\n displayed.map(({ item, leaving }) => (\n <MessageCard\n key={item.id}\n item={item}\n variant=\"compact\"\n leaving={leaving}\n onActivate={onItemClick}\n onDismiss={onDismiss}\n data-message-id={item.id}\n />\n ))\n )}\n </div>\n {viewAllLabel ? (\n <>\n <Separator />\n <div className=\"ds:pt-[var(--spacing-xs)]\">\n <Button\n intent=\"link\"\n size=\"sm\"\n onClick={onViewAll}\n className=\"ds:w-full ds:justify-center\"\n >\n {viewAllLabel}\n </Button>\n </div>\n </>\n ) : null}\n </RadixPopover.Content>\n </RadixPopover.Portal>\n </RadixPopover.Root>\n </div>\n );\n },\n);\n\nMessageTray.displayName = 'MessageTray';\n"],"names":["messageTrayAgent","handle","args","messageTrayVariants","cva","panelVariants","badgeVariants","formatBadgeCount","count","overflowLabel","SkeletonRow","jsxs","jsx","Skeleton","EmptyPanel","t","useTranslation","Mail","MessageTray","forwardRef","id","items","unreadCount","open","onOpenChange","onItemClick","onDismiss","onMarkRead","onMarkAllRead","loading","maxVisible","viewAllLabel","onViewAll","align","side","size","className","rest","ref","isOpenRaw","handleOpenChange","useControllableState","isOpen","displayed","setDisplayed","useState","item","animationDurationMs","useCallback","raw","trimmed","useLayoutEffect","prev","nextIds","prevIds","d","merged","fresh","i","useEffect","ms","timer","liveRegionRef","useRef","lastTopIdRef","_a","topId","newest","displayCount","triggerAriaLabel","badgeLabel","panelClass","itemsRef","unreadRef","isOpenRef","useMemo","targetId","found","rootRef","useImperativeHandle","useAgentRegistration","RadixPopover","IconButton","Button","Separator","Fragment","leaving","MessageCard"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"message-tray-DfsAMncP.js","sources":["../../src/components/message-tray/message-tray.agent.ts","../../src/components/message-tray/message-tray.tsx"],"sourcesContent":["/* -------------------------------------------------------------------- */\n/* Agent adapter — MessageTray. */\n/* */\n/* Tray-level surface: open/close the inbox panel, read message ids and */\n/* unread flag (never sender names / subjects / previews — those are */\n/* PHI), and route per-message operations through the curated handle. */\n/* -------------------------------------------------------------------- */\n\nimport type { AgentAdapter } from '../../agent/types';\nimport type { MessageTrayHandle } from './message-tray';\n\nexport const messageTrayAgent: AgentAdapter<MessageTrayHandle> = {\n id: 'message-tray',\n capabilities: ['open', 'close', 'select_single', 'dismiss'],\n state: {\n items: {\n type: 'Array<{ id: string; read: boolean }>',\n descriptionKey: 'ui.agent.messageTray.state.items',\n description:\n 'Currently-displayed messages. Ids + read flag only — no PHI / no sender names.',\n read: (handle) => handle.getItems(),\n },\n unreadCount: {\n type: 'number',\n descriptionKey: 'ui.agent.messageTray.state.unreadCount',\n description: 'Badge unread count surfaced by the host.',\n read: (handle) => handle.getUnreadCount(),\n },\n isOpen: {\n type: 'boolean',\n descriptionKey: 'ui.agent.messageTray.state.isOpen',\n description: 'Whether the dropdown panel is currently open.',\n read: (handle) => handle.isOpen(),\n },\n },\n actions: {\n open: {\n safety: 'read',\n descriptionKey: 'ui.agent.messageTray.actions.open',\n description: 'Open the message panel.',\n invoke: (handle) => {\n handle.open();\n },\n },\n close: {\n safety: 'read',\n descriptionKey: 'ui.agent.messageTray.actions.close',\n description: 'Close the message panel.',\n invoke: (handle) => {\n handle.close();\n },\n },\n select_item: {\n safety: 'read',\n argsType: '{ id: string }',\n descriptionKey: 'ui.agent.messageTray.actions.selectItem',\n description: 'Activate the message with the given id.',\n invoke: (handle, args: { id: string }) => {\n handle.selectItem(args.id);\n },\n },\n mark_read: {\n safety: 'write',\n argsType: '{ id: string }',\n descriptionKey: 'ui.agent.messageTray.actions.markRead',\n description: 'Request the host to mark a message as read.',\n invoke: (handle, args: { id: string }) => {\n handle.markRead(args.id);\n },\n },\n dismiss: {\n safety: 'destructive',\n argsType: '{ id: string }',\n descriptionKey: 'ui.agent.messageTray.actions.dismiss',\n description:\n 'Request the host to dismiss / archive the message with the given id.',\n invoke: (handle, args: { id: string }) => {\n handle.dismiss(args.id);\n },\n },\n },\n domHooks: {\n root: {\n attr: 'data-component',\n value: 'message-tray',\n description: 'Marks the MessageTray wrapper.',\n },\n instanceId: {\n attr: 'data-component-id',\n sourceProp: 'id',\n description:\n 'Sourced from the id prop. Required to address a specific tray from the agent.',\n },\n item: {\n attr: 'data-message-id',\n description:\n 'Stable message id emitted on each rendered MessageCard inside the tray.',\n },\n },\n};\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useLayoutEffect,\n useMemo,\n useRef,\n useState,\n type HTMLAttributes,\n} from 'react';\nimport * as RadixPopover from '@radix-ui/react-popover';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { useTranslation } from 'react-i18next';\nimport { useControllableState } from '../../hooks/use-controllable-state';\nimport { Mail } from 'lucide-react';\nimport { IconButton } from '../button/icon-button';\nimport { Button } from '../button/button';\nimport { Separator } from '../separator/separator';\nimport { Skeleton } from '../skeleton/skeleton';\nimport { MessageCard, type MessageItem } from '../message-card/message-card';\nimport { useAgentRegistration } from '../../agent/registry';\nimport { messageTrayAgent } from './message-tray.agent';\n\n/* ------------------------------------------------------------------ */\n/* Types */\n/* ------------------------------------------------------------------ */\n\n/**\n * Curated imperative handle for MessageTray. Exposed as the forwardRef\n * target so a future agent / MCP UI bridge can drive the tray without\n * touching the DOM. See `message-tray.agent.ts`.\n */\nexport interface MessageTrayHandle {\n open: () => void;\n close: () => void;\n isOpen: () => boolean;\n getItems: () => Array<{ id: string; read: boolean }>;\n getUnreadCount: () => number;\n selectItem: (id: string) => void;\n markRead: (id: string) => void;\n dismiss: (id: string) => void;\n}\n\nexport interface MessageTrayProps\n extends\n Omit<\n HTMLAttributes<HTMLDivElement>,\n 'onClick' | 'children' | 'role' | 'id'\n >,\n VariantProps<typeof messageTrayVariants> {\n /**\n * Stable instance id. Surfaced on the root as `data-component-id` so\n * an agent / MCP UI bridge can address this specific tray.\n */\n id?: string;\n /** Fires when the host should mark a single message as read (used by agent integration). */\n onMarkRead?: (item: MessageItem) => void;\n /** Messages rendered in the dropdown panel. */\n items: MessageItem[];\n /** Number of unread messages. Drives the badge count. */\n unreadCount?: number;\n /** Controlled open state. */\n open?: boolean;\n /** Fires when the open state changes. */\n onOpenChange?: (open: boolean) => void;\n /** Fires when the user activates an item (click or Enter/Space). */\n onItemClick?: (item: MessageItem) => void;\n /** Fires when the user dismisses / archives a message. */\n onDismiss?: (item: MessageItem) => void;\n /** Fires when the user clicks the header \"Mark all as read\" action. */\n onMarkAllRead?: () => void;\n /** When true the panel shows skeleton placeholders. */\n loading?: boolean;\n /**\n * Advisory item count before the list scrolls. Consumers override the cap\n * via the `--message-tray-max-block-size` custom property.\n */\n maxVisible?: number;\n /** When set renders a footer link that invokes `onViewAll`. */\n viewAllLabel?: string;\n /** Fires when the footer \"View all\" link is clicked. */\n onViewAll?: () => void;\n /** Panel alignment relative to the trigger. Default `'end'`. */\n align?: 'start' | 'center' | 'end';\n /** Side of the trigger to open on. Default `'bottom'`. */\n side?: 'top' | 'bottom';\n}\n\n/* ------------------------------------------------------------------ */\n/* CVA */\n/* ------------------------------------------------------------------ */\n\nconst messageTrayVariants = cva('ds:relative ds:inline-flex ds:items-center', {\n variants: {\n size: {\n sm: '',\n md: '',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n});\n\nconst panelVariants = cva(\n [\n 'ds:flex ds:flex-col',\n 'ds:bg-[var(--popover)] ds:text-[var(--popover-foreground)]',\n 'ds:border ds:border-[color:var(--border)]',\n 'ds:rounded-[var(--radius-md)]',\n 'ds:shadow-[var(--shadow-lg)]',\n 'ds:z-[var(--z-popover)]',\n // Width: fluid below the design cap so narrow viewports keep a visible\n // gutter on both sides (shadow included). Cap slightly wider than\n // NotificationTray because message rows carry subject + preview.\n 'ds:w-[min(26rem,calc(100vw-2*var(--spacing-md)))]',\n // Height: below the `sm` breakpoint the panel takes a near-full-screen\n // sheet shape so the user gets room to triage an inbox without\n // scrolling a tiny popover. `6rem` reserves space for the Header\n // (≈4rem) plus the sideOffset + collisionPadding (≈2rem). Above `sm`\n // it returns to `h-auto` so the list's own cap governs the height.\n 'ds:h-[calc(100dvh-6rem)] ds:sm:h-auto',\n 'ds:data-[state=open]:animate-in ds:data-[state=closed]:animate-out',\n 'ds:data-[state=closed]:fade-out-0 ds:data-[state=open]:fade-in-0',\n 'ds:data-[state=closed]:zoom-out-95 ds:data-[state=open]:zoom-in-95',\n 'ds:motion-reduce:transition-none ds:motion-reduce:animate-none',\n 'ds:focus-visible:outline-none',\n 'ds:forced-colors:border-[CanvasText]',\n ].join(' '),\n {\n variants: {\n size: {\n sm: 'ds:p-[var(--spacing-xs)]',\n md: 'ds:p-[var(--spacing-sm)]',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n },\n);\n\nconst badgeVariants = cva(\n [\n 'ds:absolute ds:-top-[var(--spacing-xs)] ds:-end-[var(--spacing-xs)]',\n 'ds:inline-flex ds:items-center ds:justify-center',\n 'ds:min-w-[calc(var(--spacing-md)+var(--spacing-xs))] ds:h-[calc(var(--spacing-md)+var(--spacing-xs))] ds:ps-[calc(var(--spacing-xs)/1.5)] ds:pe-[calc(var(--spacing-xs)/1.5)]',\n 'ds:rounded-[var(--radius-full)]',\n 'ds:bg-[color:var(--destructive)] ds:text-[color:var(--destructive-foreground)]',\n 'ds:text-[length:var(--font-size-xs)] ds:font-semibold ds:leading-none',\n 'ds:pointer-events-none ds:select-none',\n 'ds:forced-colors:outline ds:forced-colors:outline-1 ds:forced-colors:outline-[CanvasText]',\n ].join(' '),\n);\n\n/* ------------------------------------------------------------------ */\n/* Helpers */\n/* ------------------------------------------------------------------ */\n\nfunction formatBadgeCount(count: number, overflowLabel: string): string {\n return count > 99 ? overflowLabel : String(count);\n}\n\nfunction SkeletonRow() {\n return (\n <div\n aria-hidden=\"true\"\n className=\"ds:flex ds:items-start ds:gap-[var(--spacing-sm)] ds:p-[var(--spacing-sm)]\"\n >\n <Skeleton variant=\"circular\" size=\"sm\" />\n <div className=\"ds:flex-1 ds:flex ds:flex-col ds:gap-[var(--spacing-xs)]\">\n <Skeleton variant=\"text\" size=\"md\" width=\"60%\" />\n <Skeleton variant=\"text\" size=\"sm\" width=\"80%\" />\n <Skeleton variant=\"text\" size=\"sm\" width=\"95%\" />\n <Skeleton variant=\"text\" size=\"sm\" width=\"30%\" />\n </div>\n </div>\n );\n}\n\nfunction EmptyPanel() {\n const { t } = useTranslation();\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"ds:flex ds:flex-col ds:items-center ds:justify-center ds:gap-[var(--spacing-xs)] ds:p-[var(--spacing-lg)] ds:text-center\"\n >\n <span\n aria-hidden=\"true\"\n className=\"ds:inline-flex ds:items-center ds:justify-center ds:size-10 ds:rounded-[var(--radius-full)] ds:bg-[color:var(--muted)] ds:text-[color:var(--muted-foreground)] ds:[&>svg]:size-5\"\n >\n <Mail />\n </span>\n <p className=\"type-title-item ds:text-[color:var(--foreground)]\">\n {t('messageTray.noMessages', 'No messages')}\n </p>\n <p className=\"type-meta ds:text-[color:var(--muted-foreground)]\">\n {t('messageTray.noMessagesDescription', 'Your inbox is clear.')}\n </p>\n </div>\n );\n}\n\n/* ------------------------------------------------------------------ */\n/* Root */\n/* ------------------------------------------------------------------ */\n\nexport const MessageTray = forwardRef<HTMLDivElement, MessageTrayProps>(\n (\n {\n id,\n items,\n unreadCount,\n open,\n onOpenChange,\n onItemClick,\n onDismiss,\n onMarkRead,\n onMarkAllRead,\n loading = false,\n maxVisible,\n viewAllLabel,\n onViewAll,\n align = 'end',\n side = 'bottom',\n size = 'md',\n className,\n ...rest\n },\n ref,\n ) => {\n const { t } = useTranslation();\n\n const [isOpenRaw, handleOpenChange] = useControllableState<boolean>({\n value: open,\n defaultValue: false,\n onChange: onOpenChange,\n });\n const isOpen = isOpenRaw ?? false;\n\n /* Exit-animation list — same AnimatePresence-style bookkeeping as\n * NotificationTray. See that component for rationale. */\n type Displayed = { item: MessageItem; leaving: boolean };\n const [displayed, setDisplayed] = useState<Displayed[]>(() =>\n items.map((item) => ({ item, leaving: false })),\n );\n\n const animationDurationMs = useCallback((): number => {\n if (typeof window === 'undefined') return 200;\n const raw = window\n .getComputedStyle(document.documentElement)\n .getPropertyValue('--animation-duration');\n if (!raw) return 200;\n const trimmed = raw.trim();\n const n = parseFloat(trimmed);\n if (!Number.isFinite(n)) return 200;\n return trimmed.endsWith('ms') ? n : n * 1000;\n }, []);\n\n useLayoutEffect(() => {\n setDisplayed((prev) => {\n const nextIds = new Set(items.map((i) => i.id));\n const prevIds = new Set(prev.map((d) => d.item.id));\n\n const merged: Displayed[] = prev.map((d) => {\n if (nextIds.has(d.item.id)) {\n const fresh = items.find((i) => i.id === d.item.id);\n return fresh\n ? { item: fresh, leaving: false }\n : { ...d, leaving: true };\n }\n return { ...d, leaving: true };\n });\n\n for (const i of items) {\n if (!prevIds.has(i.id)) merged.push({ item: i, leaving: false });\n }\n return merged;\n });\n }, [items]);\n\n useEffect(() => {\n if (!displayed.some((d) => d.leaving)) return;\n const ms = animationDurationMs();\n const timer = setTimeout(() => {\n setDisplayed((prev) => prev.filter((d) => !d.leaving));\n }, ms);\n return () => clearTimeout(timer);\n }, [displayed, animationDurationMs]);\n\n const liveRegionRef = useRef<HTMLDivElement | null>(null);\n const lastTopIdRef = useRef<string | undefined>(items[0]?.id);\n\n useEffect(() => {\n const topId = items[0]?.id;\n const prev = lastTopIdRef.current;\n if (prev && topId && prev !== topId && liveRegionRef.current) {\n const newest = items[0];\n if (newest && !newest.read) {\n liveRegionRef.current.textContent = t('messageTray.newMessage', {\n sender: newest.sender.name,\n defaultValue: 'New message from {{sender}}',\n });\n }\n }\n lastTopIdRef.current = topId;\n }, [items, t]);\n\n const displayCount = unreadCount ?? 0;\n const triggerAriaLabel =\n displayCount > 0\n ? t('messageTray.triggerLabel', {\n count: displayCount,\n defaultValue: 'Messages, {{count}} unread',\n })\n : t('messageTray.triggerLabelNone', 'Messages, none unread');\n\n const badgeLabel = formatBadgeCount(\n displayCount,\n t('messageTray.badgeCountOverflow', '99+'),\n );\n\n const panelClass = panelVariants({ size });\n\n /* Curated imperative handle for agent integration. See\n * message-tray.agent.ts. */\n const itemsRef = useRef<MessageItem[]>(items);\n itemsRef.current = items;\n const unreadRef = useRef<number | undefined>(unreadCount);\n unreadRef.current = unreadCount;\n const isOpenRef = useRef<boolean>(isOpen);\n isOpenRef.current = isOpen;\n\n const handle = useMemo<MessageTrayHandle>(\n () => ({\n open: () => handleOpenChange(true),\n close: () => handleOpenChange(false),\n isOpen: () => isOpenRef.current,\n getItems: () =>\n itemsRef.current.map((i) => ({ id: i.id, read: !!i.read })),\n getUnreadCount: () =>\n unreadRef.current ?? itemsRef.current.filter((i) => !i.read).length,\n selectItem: (targetId: string) => {\n const found = itemsRef.current.find((i) => i.id === targetId);\n if (found) onItemClick?.(found);\n },\n markRead: (targetId: string) => {\n const found = itemsRef.current.find((i) => i.id === targetId);\n if (found) onMarkRead?.(found);\n },\n dismiss: (targetId: string) => {\n const found = itemsRef.current.find((i) => i.id === targetId);\n if (found) onDismiss?.(found);\n },\n }),\n [handleOpenChange, onItemClick, onMarkRead, onDismiss],\n );\n\n const rootRef = useRef<HTMLDivElement>(null);\n useImperativeHandle(ref, () => rootRef.current as HTMLDivElement, []);\n useAgentRegistration(messageTrayAgent, handle, id);\n\n return (\n <div\n ref={rootRef}\n data-component=\"message-tray\"\n data-component-id={id}\n className={[messageTrayVariants({ size }), className]\n .filter(Boolean)\n .join(' ')}\n {...rest}\n >\n <RadixPopover.Root open={isOpen} onOpenChange={handleOpenChange}>\n <RadixPopover.Trigger asChild>\n <IconButton\n icon={<Mail />}\n intent=\"outline\"\n size={size === 'sm' ? 'sm' : 'md'}\n aria-label={triggerAriaLabel}\n aria-haspopup=\"dialog\"\n />\n </RadixPopover.Trigger>\n {displayCount > 0 ? (\n <span\n aria-hidden=\"true\"\n data-testid=\"message-tray-badge\"\n className={badgeVariants()}\n >\n {badgeLabel}\n </span>\n ) : null}\n <div\n ref={liveRegionRef}\n aria-live=\"polite\"\n aria-atomic=\"true\"\n className=\"ds:sr-only\"\n />\n <RadixPopover.Portal>\n <RadixPopover.Content\n role=\"dialog\"\n aria-label={t('messageTray.panelTitle', 'Messages')}\n side={side}\n align={align}\n sideOffset={8}\n // `spacing-md` (16px) keeps Radix's collision-avoidance from\n // flush-mounting the panel against the viewport edge when the\n // trigger is near the inline-end of a narrow screen.\n collisionPadding={16}\n className={panelClass}\n >\n <div className=\"ds:flex ds:items-center ds:justify-between ds:gap-[var(--spacing-sm)] ds:ps-[var(--spacing-sm)] ds:pe-[var(--spacing-sm)] ds:pb-[var(--spacing-xs)]\">\n <h3 className=\"ds:m-0 type-title-card ds:text-[color:var(--foreground)]\">\n {t('messageTray.panelTitle', 'Messages')}\n </h3>\n {onMarkAllRead && items.some((item) => !item.read) ? (\n <Button\n intent=\"link\"\n size=\"sm\"\n onClick={onMarkAllRead}\n className=\"ds:text-[length:var(--font-size-xs)]\"\n >\n {t('messageTray.markAllRead', 'Mark all as read')}\n </Button>\n ) : null}\n </div>\n <Separator />\n <div\n // Only carry `role=\"list\"` when there are list children —\n // axe's `aria-required-children` rule fires on an empty\n // list. The loading skeleton + populated rendering both\n // produce role=\"listitem\" descendants below.\n role={displayed.length > 0 ? 'list' : undefined}\n data-max-visible={maxVisible}\n // Below `sm` the panel is a near-full-screen sheet (see\n // `panelVariants`) and the list expands to fill the\n // remaining space with `flex-1`. Above `sm` the list\n // caps at the `--message-tray-max-block-size` custom\n // property so the popover stays compact.\n className=\"ds:flex ds:flex-col ds:gap-[var(--spacing-xs)] ds:overflow-y-auto ds:pt-[var(--spacing-xs)] ds:flex-1 ds:sm:flex-none ds:sm:[max-block-size:var(--message-tray-max-block-size,26rem)]\"\n >\n {loading ? (\n <>\n <SkeletonRow />\n <SkeletonRow />\n <SkeletonRow />\n </>\n ) : displayed.length === 0 ? (\n <EmptyPanel />\n ) : (\n displayed.map(({ item, leaving }) => (\n <MessageCard\n key={item.id}\n item={item}\n variant=\"compact\"\n leaving={leaving}\n onActivate={onItemClick}\n onDismiss={onDismiss}\n data-message-id={item.id}\n />\n ))\n )}\n </div>\n {viewAllLabel ? (\n <>\n <Separator />\n <div className=\"ds:pt-[var(--spacing-xs)]\">\n <Button\n intent=\"link\"\n size=\"sm\"\n onClick={onViewAll}\n className=\"ds:w-full ds:justify-center\"\n >\n {viewAllLabel}\n </Button>\n </div>\n </>\n ) : null}\n </RadixPopover.Content>\n </RadixPopover.Portal>\n </RadixPopover.Root>\n </div>\n );\n },\n);\n\nMessageTray.displayName = 'MessageTray';\n"],"names":["messageTrayAgent","handle","args","messageTrayVariants","cva","panelVariants","badgeVariants","formatBadgeCount","count","overflowLabel","SkeletonRow","jsxs","jsx","Skeleton","EmptyPanel","t","useTranslation","Mail","MessageTray","forwardRef","id","items","unreadCount","open","onOpenChange","onItemClick","onDismiss","onMarkRead","onMarkAllRead","loading","maxVisible","viewAllLabel","onViewAll","align","side","size","className","rest","ref","isOpenRaw","handleOpenChange","useControllableState","isOpen","displayed","setDisplayed","useState","item","animationDurationMs","useCallback","raw","trimmed","useLayoutEffect","prev","nextIds","prevIds","d","merged","fresh","i","useEffect","ms","timer","liveRegionRef","useRef","lastTopIdRef","_a","topId","newest","displayCount","triggerAriaLabel","badgeLabel","panelClass","itemsRef","unreadRef","isOpenRef","useMemo","targetId","found","rootRef","useImperativeHandle","useAgentRegistration","RadixPopover","IconButton","Button","Separator","Fragment","leaving","MessageCard"],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { c as e } from "./createLucideIcon-CrFbzy84.js";
|
|
2
|
+
/**
|
|
3
|
+
* @license lucide-react v1.8.0 - ISC
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the ISC license.
|
|
6
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
const o = [
|
|
9
|
+
["rect", { width: "20", height: "14", x: "2", y: "3", rx: "2", key: "48i651" }],
|
|
10
|
+
["line", { x1: "8", x2: "16", y1: "21", y2: "21", key: "1svkeh" }],
|
|
11
|
+
["line", { x1: "12", x2: "12", y1: "17", y2: "21", key: "vw1qmm" }]
|
|
12
|
+
], t = e("monitor", o);
|
|
13
|
+
export {
|
|
14
|
+
t as M
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=monitor-D-SFdbrU.js.map
|