@12-apps/ui 6.86.0 → 6.86.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/_internal/components/data-display/Alert/Alert.js +2 -2
- package/dist/_internal/components/data-display/AsyncStateContainer/AsyncStateContainer.js +3 -3
- package/dist/_internal/components/data-display/Avatar/Avatar.js +2 -2
- package/dist/_internal/components/data-display/CardKit/CardKebab.js +3 -3
- package/dist/_internal/components/data-display/CardKit/card-actions-context.js +3 -3
- package/dist/_internal/components/data-display/CardKit/use-remove-confirm.js +7 -7
- package/dist/_internal/components/data-display/CardKit/use-row-confirm.js +3 -3
- package/dist/_internal/components/data-display/Carousel/Carousel.js +3 -3
- package/dist/_internal/components/data-display/Chart/Chart.js +4 -4
- package/dist/_internal/components/data-display/Chart/SpecChart.js +5 -5
- package/dist/_internal/components/data-display/Chart/chart-context.js +2 -2
- package/dist/_internal/components/data-display/Chart/chart-renderers.js +3 -3
- package/dist/_internal/components/data-display/Chip/Chip.js +3 -3
- package/dist/_internal/components/data-display/Chip/Chip.styles.js +2 -2
- package/dist/_internal/components/data-display/DataGrid/DataGrid.js +3 -3
- package/dist/_internal/components/data-display/DataViews/DataViewsGrid.js +36 -36
- package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +46 -46
- package/dist/_internal/components/data-display/DataViews/DeleteViewDialog.js +3 -3
- package/dist/_internal/components/data-display/DataViews/ManageViewsDialog.js +4 -4
- package/dist/_internal/components/data-display/DataViews/SaveViewModal.js +3 -3
- package/dist/_internal/components/data-display/DataViews/base-list-card-geometry.js +3 -3
- package/dist/_internal/components/data-display/DataViews/base-list-card-layout.js +3 -3
- package/dist/_internal/components/data-display/DataViews/base-list-card-slots.js +2 -2
- package/dist/_internal/components/data-display/DataViews/base-list-card.js +4 -4
- package/dist/_internal/components/data-display/DataViews/data-views-card-body.js +4 -4
- package/dist/_internal/components/data-display/DataViews/data-views-columns.js +4 -4
- package/dist/_internal/components/data-display/DataViews/data-views-display-panel.js +4 -4
- package/dist/_internal/components/data-display/DataViews/data-views-empty.js +3 -3
- package/dist/_internal/components/data-display/DataViews/data-views-export.js +3 -3
- package/dist/_internal/components/data-display/DataViews/data-views-filter-panel.js +4 -4
- package/dist/_internal/components/data-display/DataViews/data-views-grid-bodies.js +11 -11
- package/dist/_internal/components/data-display/DataViews/data-views-grid-helpers.js +3 -3
- package/dist/_internal/components/data-display/DataViews/data-views-grid-parts.js +30 -30
- package/dist/_internal/components/data-display/DataViews/data-views-inline-bar.js +9 -9
- package/dist/_internal/components/data-display/DataViews/data-views-more-fields.js +5 -5
- package/dist/_internal/components/data-display/DataViews/data-views-more-filters.js +8 -8
- package/dist/_internal/components/data-display/DataViews/data-views-range-pill.js +3 -3
- package/dist/_internal/components/data-display/DataViews/data-views-scope-tabs.js +2 -2
- package/dist/_internal/components/data-display/DataViews/data-views-select-all-strip.js +3 -3
- package/dist/_internal/components/data-display/DataViews/data-views-shell-toolbar.js +8 -8
- package/dist/_internal/components/data-display/DataViews/data-views-table-parts.js +8 -8
- package/dist/_internal/components/data-display/DataViews/data-views-toolbar.js +7 -7
- package/dist/_internal/components/data-display/DataViews/data-views-view-nav.js +3 -3
- package/dist/_internal/components/data-display/DataViews/list-card-rails.js +2 -2
- package/dist/_internal/components/data-display/DataViews/use-data-views-state.js +7 -7
- package/dist/_internal/components/data-display/EmptyState/EmptyState.js +2 -2
- package/dist/_internal/components/data-display/FleetMap/FleetBody.js +11 -11
- package/dist/_internal/components/data-display/FleetMap/FleetCanvas.js +10 -10
- package/dist/_internal/components/data-display/FleetMap/FleetMap.js +14 -14
- package/dist/_internal/components/data-display/InteractiveTooltip/InteractiveTooltip.js +2 -2
- package/dist/_internal/components/data-display/Lightbox/Lightbox.js +7 -7
- package/dist/_internal/components/data-display/Lightbox/LightboxControls.js +2 -2
- package/dist/_internal/components/data-display/Lightbox/LightboxOverlay.js +3 -3
- package/dist/_internal/components/data-display/Lightbox/LightboxThumbnails.js +2 -2
- package/dist/_internal/components/data-display/MapPreview/MapDecorations.js +2 -2
- package/dist/_internal/components/data-display/MapPreview/MapLayers.js +2 -2
- package/dist/_internal/components/data-display/MapPreview/MapPreview.hooks.js +2 -2
- package/dist/_internal/components/data-display/MapPreview/MapPreview.js +9 -9
- package/dist/_internal/components/data-display/MapPreview/MapTiles.js +2 -2
- package/dist/_internal/components/data-display/MapPreview/StaticMapView.js +4 -4
- package/dist/_internal/components/data-display/MapPreview/useMapPreview.js +3 -3
- package/dist/_internal/components/data-display/RegionMap/RegionMap.js +4 -3
- package/dist/_internal/components/data-display/RegionMap/RegionMap.labels.js +12 -0
- package/dist/_internal/components/data-display/RegionMap/RegionMap.labels.js.map +1 -0
- package/dist/_internal/components/data-display/RegionMap/RegionMapDrawing.js +2 -1
- package/dist/_internal/components/data-display/SectionOnboarding/SectionOnboarding.js +3 -3
- package/dist/_internal/components/data-display/Sheet/Sheet.js +2 -2
- package/dist/_internal/components/data-display/Table/Table.js +2 -2
- package/dist/_internal/components/data-display/index.js +51 -50
- package/dist/_internal/components/feedback/ConfirmAction/ConfirmButton.js +3 -3
- package/dist/_internal/components/feedback/Modal/Modal.js +2 -2
- package/dist/_internal/components/feedback/NotificationStatusNotice/NotificationStatusNotice.js +5 -5
- package/dist/_internal/components/feedback/SequenceResolver/SequenceResolver.js +6 -6
- package/dist/_internal/components/feedback/SequenceResolver/SequenceResolver.parts.js +5 -5
- package/dist/_internal/components/feedback/index.js +10 -10
- package/dist/_internal/components/form/AddressAutocomplete/AddressAutocomplete.js +4 -4
- package/dist/_internal/components/form/AddressAutocomplete/AddressAutocompleteField.js +2 -2
- package/dist/_internal/components/form/AddressAutocomplete/AddressSuggestionsPaper.js +1 -1
- package/dist/_internal/components/form/Autocomplete/Autocomplete.js +1 -1
- package/dist/_internal/components/form/Button/Button.js +2 -2
- package/dist/_internal/components/form/Calendar/Calendar.band.js +18 -0
- package/dist/_internal/components/form/Calendar/Calendar.band.js.map +1 -0
- package/dist/_internal/components/form/Calendar/Calendar.js +7 -5
- package/dist/_internal/components/form/Calendar/CalendarDay.js +4 -1
- package/dist/_internal/components/form/Calendar/CalendarDayCell.js +4 -2
- package/dist/_internal/components/form/Calendar/CalendarMonth.js +5 -3
- package/dist/_internal/components/form/Calendar/CalendarSelectorsMonth.js +6 -4
- package/dist/_internal/components/form/DateRangePicker/DateRangePicker.js +7 -6
- package/dist/_internal/components/form/index.js +14 -13
- package/dist/_internal/components/form/total-form/SubmitButton.js +3 -3
- package/dist/_internal/components/index.js +84 -82
- package/dist/_internal/components/layout/SettingCard/SettingCard.js +10 -10
- package/dist/_internal/components/layout/SettingCard/SettingCard.parts.js +6 -6
- package/dist/_internal/components/layout/SettingCard/SettingCard.summary.js +9 -9
- package/dist/_internal/components/layout/SettingCard/SettingGrid.js +7 -7
- package/dist/_internal/components/layout/SettingCard/SettingGroup.js +11 -11
- package/dist/_internal/components/layout/SettingCard/SettingSwitch.js +10 -10
- package/dist/_internal/components/layout/SettingCard/SettingToggle.js +11 -11
- package/dist/_internal/components/layout/index.js +14 -14
- package/dist/_internal/components/navigation/AppHeader/AppHeader.details.js +5 -5
- package/dist/_internal/components/navigation/CommandPalette/CommandPalette.helpers.js +2 -2
- package/dist/_internal/components/navigation/CommandPalette/CommandPalette.hooks.js +3 -3
- package/dist/_internal/components/navigation/CommandPalette/CommandPalette.js +5 -5
- package/dist/_internal/components/navigation/CommandPalette/CommandPaletteResults.js +2 -2
- package/dist/_internal/components/navigation/index.js +10 -10
- package/dist/_internal/en-US.navigation.js +1 -1
- package/dist/_internal/pt-BR.navigation.js +1 -1
- package/dist/_internal/social-login-button/social-login-button.js +3 -3
- package/dist/_internal/user-avatar/user-avatar.js +5 -5
- package/dist/charts.js +5 -5
- package/dist/{chunk-OPY2AGAU.js → chunk-2IHUFUTO.js} +2 -2
- package/dist/{chunk-33AVAYCR.js → chunk-2L6TANRY.js} +5 -5
- package/dist/{chunk-ENJOBJPK.js → chunk-2MT6VSS2.js} +2 -2
- package/dist/{chunk-QADTI63U.js → chunk-3JZ3KEQQ.js} +2 -2
- package/dist/{chunk-EOIRU62W.js → chunk-42D7KBDH.js} +2 -2
- package/dist/{chunk-LXIPBHNJ.js → chunk-42TOCPXB.js} +5 -5
- package/dist/{chunk-IFX5KP65.js → chunk-437HQPUN.js} +4 -4
- package/dist/{chunk-VYQZ5U3N.js → chunk-4NG3LTRX.js} +2 -2
- package/dist/{chunk-POUNFTG3.js → chunk-4OUJ4ZMK.js} +9 -3
- package/dist/chunk-4OUJ4ZMK.js.map +1 -0
- package/dist/{chunk-7YJYIMWP.js → chunk-4QR7LM5F.js} +6 -6
- package/dist/{chunk-KR4TN3OF.js → chunk-4ZQQUICR.js} +2 -2
- package/dist/{chunk-IYDXKLCE.js → chunk-5C3JSXBK.js} +2 -2
- package/dist/{chunk-T6QVM5Q5.js → chunk-5IMI2XNU.js} +6 -6
- package/dist/{chunk-JKIKHWD2.js → chunk-5NT2M2JI.js} +4 -4
- package/dist/{chunk-Q7XLTN2D.js → chunk-5VKHJ7PI.js} +3 -3
- package/dist/{chunk-BP3ZKIPE.js → chunk-64UNVW6D.js} +4 -4
- package/dist/{chunk-SSCEX5NY.js → chunk-656DBMWT.js} +3 -2
- package/dist/{chunk-SSCEX5NY.js.map → chunk-656DBMWT.js.map} +1 -1
- package/dist/{chunk-FCLON3MO.js → chunk-6HXNFNOB.js} +3 -3
- package/dist/{chunk-3OL2TSEJ.js → chunk-6IRZZYHF.js} +5 -5
- package/dist/{chunk-ZLVRCQPG.js → chunk-6X7PE5DH.js} +6 -6
- package/dist/{chunk-ABRVOPC2.js → chunk-7FFY4LJY.js} +2 -2
- package/dist/{chunk-U3HGQHEO.js → chunk-7WE432RQ.js} +13 -13
- package/dist/{chunk-VHGHF537.js → chunk-A3DDEKLV.js} +3 -3
- package/dist/{chunk-A63WU4UZ.js → chunk-AKE6KVQG.js} +70 -41
- package/dist/chunk-AKE6KVQG.js.map +1 -0
- package/dist/{chunk-KRPDBVUB.js → chunk-APSEM5AA.js} +3 -3
- package/dist/{chunk-5ZC7CNU4.js → chunk-AQPPSR4P.js} +2 -2
- package/dist/{chunk-AWUFS2ZC.js → chunk-BAC2PBOS.js} +6 -6
- package/dist/{chunk-OA6T2ME3.js → chunk-BLZDSCIZ.js} +4 -4
- package/dist/{chunk-OQN2FHEL.js → chunk-C4NSEUT5.js} +3 -3
- package/dist/{chunk-IEAPXS57.js → chunk-CJLZHW2Z.js} +2 -2
- package/dist/{chunk-I7JUAHUO.js → chunk-DILDC77M.js} +3 -3
- package/dist/{chunk-U4WAAZXJ.js → chunk-DVX4HDNP.js} +2 -2
- package/dist/{chunk-UTUYXH72.js → chunk-E5QOT7KK.js} +8 -8
- package/dist/{chunk-V6KQ5R4T.js → chunk-EAFZ3RDY.js} +5 -5
- package/dist/{chunk-C5RQBTRZ.js → chunk-EIOGJBJ5.js} +25 -5
- package/dist/chunk-EIOGJBJ5.js.map +1 -0
- package/dist/{chunk-CESGZRVQ.js → chunk-EMSMJRP3.js} +4 -4
- package/dist/{chunk-ULAZDF6D.js → chunk-FF22F7FA.js} +2 -2
- package/dist/{chunk-Z5WUSI47.js → chunk-G3JFESKD.js} +6 -6
- package/dist/{chunk-CARUHKZW.js → chunk-G4W6HR6Q.js} +9 -9
- package/dist/{chunk-KYTFGW4R.js → chunk-GMIMHQ6H.js} +2 -2
- package/dist/chunk-H2UUMZQR.js +74 -0
- package/dist/chunk-H2UUMZQR.js.map +1 -0
- package/dist/{chunk-UT545JBQ.js → chunk-HC6OZ7QK.js} +3 -3
- package/dist/{chunk-MVNFUIJS.js → chunk-HOPRZEBM.js} +4 -4
- package/dist/{chunk-Z445LLFN.js → chunk-I44XL4Z4.js} +7 -6
- package/dist/chunk-I44XL4Z4.js.map +1 -0
- package/dist/{chunk-FZUAB2KS.js → chunk-INFBO356.js} +2 -2
- package/dist/{chunk-XW44IFYE.js → chunk-IWMAFTXP.js} +2 -2
- package/dist/{chunk-2DDCRHJE.js → chunk-IX5ADKII.js} +2 -2
- package/dist/{chunk-N5OEDOJT.js → chunk-J2KVF5GO.js} +3 -3
- package/dist/chunk-J3AWGTJY.js +29 -0
- package/dist/chunk-J3AWGTJY.js.map +1 -0
- package/dist/{chunk-TZC6KIK2.js → chunk-JG733RMP.js} +5 -5
- package/dist/{chunk-PGYYDSNX.js → chunk-JH2XLVWM.js} +2 -2
- package/dist/{chunk-XNMU32XC.js → chunk-JHW35C6W.js} +5 -5
- package/dist/{chunk-4V37DAMA.js → chunk-JRBSTOMA.js} +3 -3
- package/dist/{chunk-K6VEN5VN.js → chunk-K3PMMW23.js} +4 -4
- package/dist/{chunk-JVTZ7FWR.js → chunk-K6FCSB6T.js} +7 -7
- package/dist/{chunk-FZEDQNUN.js → chunk-K7IDOTSU.js} +3 -3
- package/dist/{chunk-XMWTVDQN.js → chunk-LH43GKP2.js} +17 -17
- package/dist/{chunk-YHPSPFU5.js → chunk-LIN4A2BW.js} +4 -4
- package/dist/{chunk-LXMFHD7M.js → chunk-LTSVYILY.js} +4 -4
- package/dist/{chunk-QJLOWBFW.js → chunk-LXTNWQWF.js} +2 -2
- package/dist/{chunk-HI7JPDD6.js → chunk-M3XJVD5G.js} +2 -2
- package/dist/{chunk-FQMLTCXT.js → chunk-MAHY7PK3.js} +4 -4
- package/dist/{chunk-NTRWUDP6.js → chunk-MKVDHR3B.js} +2 -2
- package/dist/{chunk-C74PDNTF.js → chunk-NKEFH3RS.js} +4 -4
- package/dist/{chunk-T6YTDEY4.js → chunk-OFESNJKE.js} +3 -3
- package/dist/{chunk-GLR5MSU3.js → chunk-OY437NRJ.js} +2 -2
- package/dist/{chunk-NI67M453.js → chunk-PGANINQD.js} +5 -5
- package/dist/{chunk-LRQT4MQO.js → chunk-PJNIJIE6.js} +2 -2
- package/dist/{chunk-KRYOT3KB.js → chunk-PQGHYFUA.js} +2 -2
- package/dist/{chunk-5XTPEA3O.js → chunk-PXEIN3J4.js} +7 -7
- package/dist/{chunk-ARMKSYEQ.js → chunk-Q4QFYGPH.js} +2 -2
- package/dist/{chunk-TIM4PXWN.js → chunk-QHIWV55K.js} +2 -2
- package/dist/{chunk-DHAXUVMR.js → chunk-QN7FVZQD.js} +4 -4
- package/dist/{chunk-2WVHZIWP.js → chunk-QSRZOXQI.js} +2 -2
- package/dist/{chunk-IF5UY3CT.js → chunk-QVDEGBME.js} +4 -4
- package/dist/{chunk-6PTP5NID.js → chunk-R2ODLE6G.js} +2 -2
- package/dist/{chunk-XQJPR57I.js → chunk-T5RFH2T5.js} +2 -2
- package/dist/{chunk-WMAS6DZR.js → chunk-TLJVUWJ5.js} +2 -2
- package/dist/{chunk-MK6UXAWY.js → chunk-TSEBMVYY.js} +3 -3
- package/dist/{chunk-NEYZV6V5.js → chunk-UAOE3ZPC.js} +6 -6
- package/dist/{chunk-IMCSY2SI.js → chunk-UFGT2SFD.js} +6 -6
- package/dist/{chunk-WTOA52EQ.js → chunk-UKNMPGEM.js} +2 -2
- package/dist/{chunk-P772HCHI.js → chunk-W676GY42.js} +4 -4
- package/dist/{chunk-T2G4LDU5.js → chunk-WLLUARTC.js} +2 -2
- package/dist/{chunk-JZQYVGPV.js → chunk-WLSFBXGS.js} +3 -3
- package/dist/{chunk-52RHAAIH.js → chunk-X3EEV3OI.js} +3 -3
- package/dist/{chunk-DYRZRY2T.js → chunk-X4N6Q37Q.js} +4 -4
- package/dist/{chunk-HKGKQKQT.js → chunk-X5OGIT2F.js} +52 -20
- package/dist/chunk-X5OGIT2F.js.map +1 -0
- package/dist/{chunk-56GWNA5V.js → chunk-X6D5JEUV.js} +12 -5
- package/dist/chunk-X6D5JEUV.js.map +1 -0
- package/dist/{chunk-ZVZTQF7E.js → chunk-XS6QHZMD.js} +2 -2
- package/dist/{chunk-CPZGFIFH.js → chunk-YNVTUQ5B.js} +2 -2
- package/dist/{chunk-HJJR2WGL.js → chunk-YOXYSAUI.js} +4 -4
- package/dist/{chunk-D72GD4XC.js → chunk-YPW4HZ3Z.js} +6 -2
- package/dist/chunk-YPW4HZ3Z.js.map +1 -0
- package/dist/{chunk-G76PIGF7.js → chunk-ZHQAVW2V.js} +3 -2
- package/dist/chunk-ZHQAVW2V.js.map +1 -0
- package/dist/{chunk-HWPQKHN2.js → chunk-ZIHSCBMN.js} +13 -13
- package/dist/data-display/Alert.js +2 -2
- package/dist/data-display/AsyncStateContainer.js +3 -3
- package/dist/data-display/Avatar.js +2 -2
- package/dist/data-display/CardKit.js +18 -18
- package/dist/data-display/Carousel.js +3 -3
- package/dist/data-display/Chart.js +5 -5
- package/dist/data-display/Chip.js +3 -3
- package/dist/data-display/DataGrid.js +3 -3
- package/dist/data-display/DataViews.js +59 -59
- package/dist/data-display/EmptyState.js +2 -2
- package/dist/data-display/FleetMap.js +14 -14
- package/dist/data-display/InteractiveTooltip.js +2 -2
- package/dist/data-display/Lightbox.js +7 -7
- package/dist/data-display/MapPreview.js +9 -9
- package/dist/data-display/RegionMap.js +4 -3
- package/dist/data-display/SectionOnboarding.js +3 -3
- package/dist/data-display/Sheet.js +2 -2
- package/dist/data-display/Table.js +2 -2
- package/dist/en-US.js +1 -1
- package/dist/feedback/ConfirmAction.js +3 -3
- package/dist/feedback/Modal.js +2 -2
- package/dist/feedback/NotificationStatusNotice.js +5 -5
- package/dist/feedback/SequenceResolver.js +6 -6
- package/dist/form/AddressAutocomplete.js +4 -4
- package/dist/form/Autocomplete.js +1 -1
- package/dist/form/Button.js +2 -2
- package/dist/form/Calendar.js +7 -5
- package/dist/form/DateRangePicker.js +7 -6
- package/dist/form/total-form.js +3 -3
- package/dist/layout/SettingCard.js +14 -14
- package/dist/locales.js +2 -2
- package/dist/navigation/AppHeader.js +5 -5
- package/dist/navigation/CommandPalette.js +5 -5
- package/dist/pt-BR.js +1 -1
- package/dist/social-login-button.js +3 -3
- package/dist/types/components/data-display/RegionMap/RegionMap.labels.d.ts +42 -0
- package/dist/types/components/data-display/RegionMap/RegionMap.labels.d.ts.map +1 -0
- package/dist/types/components/data-display/RegionMap/RegionMapDrawing.d.ts.map +1 -1
- package/dist/types/components/form/AddressAutocomplete/AddressAutocompleteField.d.ts.map +1 -1
- package/dist/types/components/form/AddressAutocomplete/AddressSuggestionsPaper.d.ts +11 -1
- package/dist/types/components/form/AddressAutocomplete/AddressSuggestionsPaper.d.ts.map +1 -1
- package/dist/types/components/form/Calendar/Calendar.band.d.ts +44 -0
- package/dist/types/components/form/Calendar/Calendar.band.d.ts.map +1 -0
- package/dist/types/components/form/Calendar/CalendarDay.d.ts +2 -0
- package/dist/types/components/form/Calendar/CalendarDay.d.ts.map +1 -1
- package/dist/types/components/form/Calendar/CalendarDayCell.d.ts.map +1 -1
- package/dist/types/components/form/Calendar/CalendarMonth.d.ts +3 -2
- package/dist/types/components/form/Calendar/CalendarMonth.d.ts.map +1 -1
- package/dist/types/components/navigation/CommandPalette/CommandPalette.d.ts.map +1 -1
- package/dist/types/copy/navigation.d.ts +2 -0
- package/dist/types/copy/navigation.d.ts.map +1 -1
- package/dist/types/en-US.navigation.d.ts.map +1 -1
- package/dist/types/pt-BR.navigation.d.ts.map +1 -1
- package/dist/user-avatar.js +5 -5
- package/package.json +1 -1
- package/src/components/data-display/RegionMap/RegionMap.labels.ts +60 -0
- package/src/components/data-display/RegionMap/RegionMapDrawing.tsx +87 -45
- package/src/components/form/AddressAutocomplete/AddressAutocompleteField.tsx +17 -4
- package/src/components/form/AddressAutocomplete/AddressSuggestionsPaper.tsx +32 -3
- package/src/components/form/Calendar/Calendar.band.ts +118 -0
- package/src/components/form/Calendar/CalendarDay.tsx +73 -23
- package/src/components/form/Calendar/CalendarDayCell.tsx +2 -0
- package/src/components/form/Calendar/CalendarMonth.tsx +14 -4
- package/src/components/navigation/CommandPalette/CommandPalette.md +1 -0
- package/src/components/navigation/CommandPalette/CommandPalette.tsx +4 -2
- package/src/copy/navigation.ts +2 -0
- package/src/en-US.navigation.ts +1 -0
- package/src/pt-BR.navigation.ts +1 -0
- package/dist/chunk-56GWNA5V.js.map +0 -1
- package/dist/chunk-A63WU4UZ.js.map +0 -1
- package/dist/chunk-C5RQBTRZ.js.map +0 -1
- package/dist/chunk-D72GD4XC.js.map +0 -1
- package/dist/chunk-G76PIGF7.js.map +0 -1
- package/dist/chunk-HKGKQKQT.js.map +0 -1
- package/dist/chunk-POUNFTG3.js.map +0 -1
- package/dist/chunk-Z445LLFN.js.map +0 -1
- /package/dist/{chunk-OPY2AGAU.js.map → chunk-2IHUFUTO.js.map} +0 -0
- /package/dist/{chunk-33AVAYCR.js.map → chunk-2L6TANRY.js.map} +0 -0
- /package/dist/{chunk-ENJOBJPK.js.map → chunk-2MT6VSS2.js.map} +0 -0
- /package/dist/{chunk-QADTI63U.js.map → chunk-3JZ3KEQQ.js.map} +0 -0
- /package/dist/{chunk-EOIRU62W.js.map → chunk-42D7KBDH.js.map} +0 -0
- /package/dist/{chunk-LXIPBHNJ.js.map → chunk-42TOCPXB.js.map} +0 -0
- /package/dist/{chunk-IFX5KP65.js.map → chunk-437HQPUN.js.map} +0 -0
- /package/dist/{chunk-VYQZ5U3N.js.map → chunk-4NG3LTRX.js.map} +0 -0
- /package/dist/{chunk-7YJYIMWP.js.map → chunk-4QR7LM5F.js.map} +0 -0
- /package/dist/{chunk-KR4TN3OF.js.map → chunk-4ZQQUICR.js.map} +0 -0
- /package/dist/{chunk-IYDXKLCE.js.map → chunk-5C3JSXBK.js.map} +0 -0
- /package/dist/{chunk-T6QVM5Q5.js.map → chunk-5IMI2XNU.js.map} +0 -0
- /package/dist/{chunk-JKIKHWD2.js.map → chunk-5NT2M2JI.js.map} +0 -0
- /package/dist/{chunk-Q7XLTN2D.js.map → chunk-5VKHJ7PI.js.map} +0 -0
- /package/dist/{chunk-BP3ZKIPE.js.map → chunk-64UNVW6D.js.map} +0 -0
- /package/dist/{chunk-FCLON3MO.js.map → chunk-6HXNFNOB.js.map} +0 -0
- /package/dist/{chunk-3OL2TSEJ.js.map → chunk-6IRZZYHF.js.map} +0 -0
- /package/dist/{chunk-ZLVRCQPG.js.map → chunk-6X7PE5DH.js.map} +0 -0
- /package/dist/{chunk-ABRVOPC2.js.map → chunk-7FFY4LJY.js.map} +0 -0
- /package/dist/{chunk-U3HGQHEO.js.map → chunk-7WE432RQ.js.map} +0 -0
- /package/dist/{chunk-VHGHF537.js.map → chunk-A3DDEKLV.js.map} +0 -0
- /package/dist/{chunk-KRPDBVUB.js.map → chunk-APSEM5AA.js.map} +0 -0
- /package/dist/{chunk-5ZC7CNU4.js.map → chunk-AQPPSR4P.js.map} +0 -0
- /package/dist/{chunk-AWUFS2ZC.js.map → chunk-BAC2PBOS.js.map} +0 -0
- /package/dist/{chunk-OA6T2ME3.js.map → chunk-BLZDSCIZ.js.map} +0 -0
- /package/dist/{chunk-OQN2FHEL.js.map → chunk-C4NSEUT5.js.map} +0 -0
- /package/dist/{chunk-IEAPXS57.js.map → chunk-CJLZHW2Z.js.map} +0 -0
- /package/dist/{chunk-I7JUAHUO.js.map → chunk-DILDC77M.js.map} +0 -0
- /package/dist/{chunk-U4WAAZXJ.js.map → chunk-DVX4HDNP.js.map} +0 -0
- /package/dist/{chunk-UTUYXH72.js.map → chunk-E5QOT7KK.js.map} +0 -0
- /package/dist/{chunk-V6KQ5R4T.js.map → chunk-EAFZ3RDY.js.map} +0 -0
- /package/dist/{chunk-CESGZRVQ.js.map → chunk-EMSMJRP3.js.map} +0 -0
- /package/dist/{chunk-ULAZDF6D.js.map → chunk-FF22F7FA.js.map} +0 -0
- /package/dist/{chunk-Z5WUSI47.js.map → chunk-G3JFESKD.js.map} +0 -0
- /package/dist/{chunk-CARUHKZW.js.map → chunk-G4W6HR6Q.js.map} +0 -0
- /package/dist/{chunk-KYTFGW4R.js.map → chunk-GMIMHQ6H.js.map} +0 -0
- /package/dist/{chunk-UT545JBQ.js.map → chunk-HC6OZ7QK.js.map} +0 -0
- /package/dist/{chunk-MVNFUIJS.js.map → chunk-HOPRZEBM.js.map} +0 -0
- /package/dist/{chunk-FZUAB2KS.js.map → chunk-INFBO356.js.map} +0 -0
- /package/dist/{chunk-XW44IFYE.js.map → chunk-IWMAFTXP.js.map} +0 -0
- /package/dist/{chunk-2DDCRHJE.js.map → chunk-IX5ADKII.js.map} +0 -0
- /package/dist/{chunk-N5OEDOJT.js.map → chunk-J2KVF5GO.js.map} +0 -0
- /package/dist/{chunk-TZC6KIK2.js.map → chunk-JG733RMP.js.map} +0 -0
- /package/dist/{chunk-PGYYDSNX.js.map → chunk-JH2XLVWM.js.map} +0 -0
- /package/dist/{chunk-XNMU32XC.js.map → chunk-JHW35C6W.js.map} +0 -0
- /package/dist/{chunk-4V37DAMA.js.map → chunk-JRBSTOMA.js.map} +0 -0
- /package/dist/{chunk-K6VEN5VN.js.map → chunk-K3PMMW23.js.map} +0 -0
- /package/dist/{chunk-JVTZ7FWR.js.map → chunk-K6FCSB6T.js.map} +0 -0
- /package/dist/{chunk-FZEDQNUN.js.map → chunk-K7IDOTSU.js.map} +0 -0
- /package/dist/{chunk-XMWTVDQN.js.map → chunk-LH43GKP2.js.map} +0 -0
- /package/dist/{chunk-YHPSPFU5.js.map → chunk-LIN4A2BW.js.map} +0 -0
- /package/dist/{chunk-LXMFHD7M.js.map → chunk-LTSVYILY.js.map} +0 -0
- /package/dist/{chunk-QJLOWBFW.js.map → chunk-LXTNWQWF.js.map} +0 -0
- /package/dist/{chunk-HI7JPDD6.js.map → chunk-M3XJVD5G.js.map} +0 -0
- /package/dist/{chunk-FQMLTCXT.js.map → chunk-MAHY7PK3.js.map} +0 -0
- /package/dist/{chunk-NTRWUDP6.js.map → chunk-MKVDHR3B.js.map} +0 -0
- /package/dist/{chunk-C74PDNTF.js.map → chunk-NKEFH3RS.js.map} +0 -0
- /package/dist/{chunk-T6YTDEY4.js.map → chunk-OFESNJKE.js.map} +0 -0
- /package/dist/{chunk-GLR5MSU3.js.map → chunk-OY437NRJ.js.map} +0 -0
- /package/dist/{chunk-NI67M453.js.map → chunk-PGANINQD.js.map} +0 -0
- /package/dist/{chunk-LRQT4MQO.js.map → chunk-PJNIJIE6.js.map} +0 -0
- /package/dist/{chunk-KRYOT3KB.js.map → chunk-PQGHYFUA.js.map} +0 -0
- /package/dist/{chunk-5XTPEA3O.js.map → chunk-PXEIN3J4.js.map} +0 -0
- /package/dist/{chunk-ARMKSYEQ.js.map → chunk-Q4QFYGPH.js.map} +0 -0
- /package/dist/{chunk-TIM4PXWN.js.map → chunk-QHIWV55K.js.map} +0 -0
- /package/dist/{chunk-DHAXUVMR.js.map → chunk-QN7FVZQD.js.map} +0 -0
- /package/dist/{chunk-2WVHZIWP.js.map → chunk-QSRZOXQI.js.map} +0 -0
- /package/dist/{chunk-IF5UY3CT.js.map → chunk-QVDEGBME.js.map} +0 -0
- /package/dist/{chunk-6PTP5NID.js.map → chunk-R2ODLE6G.js.map} +0 -0
- /package/dist/{chunk-XQJPR57I.js.map → chunk-T5RFH2T5.js.map} +0 -0
- /package/dist/{chunk-WMAS6DZR.js.map → chunk-TLJVUWJ5.js.map} +0 -0
- /package/dist/{chunk-MK6UXAWY.js.map → chunk-TSEBMVYY.js.map} +0 -0
- /package/dist/{chunk-NEYZV6V5.js.map → chunk-UAOE3ZPC.js.map} +0 -0
- /package/dist/{chunk-IMCSY2SI.js.map → chunk-UFGT2SFD.js.map} +0 -0
- /package/dist/{chunk-WTOA52EQ.js.map → chunk-UKNMPGEM.js.map} +0 -0
- /package/dist/{chunk-P772HCHI.js.map → chunk-W676GY42.js.map} +0 -0
- /package/dist/{chunk-T2G4LDU5.js.map → chunk-WLLUARTC.js.map} +0 -0
- /package/dist/{chunk-JZQYVGPV.js.map → chunk-WLSFBXGS.js.map} +0 -0
- /package/dist/{chunk-52RHAAIH.js.map → chunk-X3EEV3OI.js.map} +0 -0
- /package/dist/{chunk-DYRZRY2T.js.map → chunk-X4N6Q37Q.js.map} +0 -0
- /package/dist/{chunk-ZVZTQF7E.js.map → chunk-XS6QHZMD.js.map} +0 -0
- /package/dist/{chunk-CPZGFIFH.js.map → chunk-YNVTUQ5B.js.map} +0 -0
- /package/dist/{chunk-HJJR2WGL.js.map → chunk-YOXYSAUI.js.map} +0 -0
- /package/dist/{chunk-HWPQKHN2.js.map → chunk-ZIHSCBMN.js.map} +0 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// How the labels over a RegionMap drawing are ranked and laid out.
|
|
2
|
+
|
|
3
|
+
/** Where a label's centre may go along one axis so the whole label stays in view. */
|
|
4
|
+
export function clampCentre(wanted: number, half: number, span: number, gap: number): number {
|
|
5
|
+
if (span <= 2 * (half + gap)) return span / 2;
|
|
6
|
+
return Math.min(span - half - gap, Math.max(half + gap, wanted));
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** An area that may carry a label, as {@link labelOrder} ranks it. */
|
|
10
|
+
interface Labelable {
|
|
11
|
+
id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
excluded?: boolean;
|
|
14
|
+
geometry: { area: number };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* The order labels claim their place in: highlighted first (what the person is
|
|
19
|
+
* looking for), then excluded, then the larger area, then by name. When two
|
|
20
|
+
* labels would overlap, the earlier one is drawn and the later one hidden.
|
|
21
|
+
*/
|
|
22
|
+
export function labelOrder<T extends Labelable>(areas: readonly T[], highlighted: ReadonlySet<string>): T[] {
|
|
23
|
+
const rank = (area: T): number => (highlighted.has(area.id) ? 0 : area.excluded ? 1 : 2);
|
|
24
|
+
return [...areas].sort(
|
|
25
|
+
(a, b) => rank(a) - rank(b) || b.geometry.area - a.geometry.area || a.name.localeCompare(b.name),
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** A label measured in the drawing: where it wants to be (fractions), and its size in px. */
|
|
30
|
+
export interface LabelBox {
|
|
31
|
+
fractionX: number;
|
|
32
|
+
fractionY: number;
|
|
33
|
+
spanX: number;
|
|
34
|
+
spanY: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Where each label goes, in px, and whether it is drawn at all. */
|
|
38
|
+
export interface PlacedLabel {
|
|
39
|
+
x: number;
|
|
40
|
+
y: number;
|
|
41
|
+
visible: boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Lay labels out in priority order ({@link labelOrder}): each is pulled inside
|
|
46
|
+
* the drawing by its own size, and one whose box would overlap a label already
|
|
47
|
+
* drawn is hidden — the area keeps its name in its `<title>` and in the list,
|
|
48
|
+
* so hiding costs nothing but the clutter two names over each other made.
|
|
49
|
+
*/
|
|
50
|
+
export function placeLabels(labels: readonly LabelBox[], box: { spanX: number; spanY: number }, gap: number): PlacedLabel[] {
|
|
51
|
+
const kept: { x0: number; y0: number; x1: number; y1: number }[] = [];
|
|
52
|
+
return labels.map((label) => {
|
|
53
|
+
const x = clampCentre(label.fractionX * box.spanX, label.spanX / 2, box.spanX, gap);
|
|
54
|
+
const y = clampCentre(label.fractionY * box.spanY, label.spanY / 2, box.spanY, gap);
|
|
55
|
+
const rect = { x0: x - label.spanX / 2, y0: y - label.spanY / 2, x1: x + label.spanX / 2, y1: y + label.spanY / 2 };
|
|
56
|
+
const visible = !kept.some((o) => rect.x0 < o.x1 && o.x0 < rect.x1 && rect.y0 < o.y1 && o.y0 < rect.y1);
|
|
57
|
+
if (visible) kept.push(rect);
|
|
58
|
+
return { x, y, visible };
|
|
59
|
+
});
|
|
60
|
+
}
|
|
@@ -7,6 +7,7 @@ import { rem, remPx } from '../../../tokens/relative';
|
|
|
7
7
|
|
|
8
8
|
import { labelPosition, type AreaGeometry, type DrawnRegion, type PlaneBox } from './RegionMap.helpers';
|
|
9
9
|
import type { RegionMapModel } from './RegionMap.hooks';
|
|
10
|
+
import { labelOrder, placeLabels } from './RegionMap.labels';
|
|
10
11
|
|
|
11
12
|
export interface RegionMapDrawingProps {
|
|
12
13
|
model: RegionMapModel & { view: PlaneBox };
|
|
@@ -43,7 +44,11 @@ export function RegionMapDrawing({
|
|
|
43
44
|
const { view, drawn } = model;
|
|
44
45
|
const wanted = new Set(highlightedIds);
|
|
45
46
|
const highlighted = drawn.filter((d) => wanted.has(d.id));
|
|
46
|
-
|
|
47
|
+
// Highlighted, then excluded, then larger, then by name: the order labels
|
|
48
|
+
// claim their place in, so a collision hides the less important one.
|
|
49
|
+
const labelled = labelOrder(drawn.filter((d) => d.excluded || wanted.has(d.id)), wanted);
|
|
50
|
+
const boxRef = React.useRef<HTMLDivElement>(null);
|
|
51
|
+
useLabelPlacement(boxRef, labelled.map((d) => d.id).join('|'), remPx(theme, 4));
|
|
47
52
|
const base = drawn.map((d) => ({ id: d.id, name: d.name, geometry: d.geometry, outside: d.outside === true }));
|
|
48
53
|
return (
|
|
49
54
|
<Box
|
|
@@ -60,6 +65,7 @@ export function RegionMapDrawing({
|
|
|
60
65
|
bgcolor: 'background.paper',
|
|
61
66
|
}}
|
|
62
67
|
data-testid={`${testId}-canvas`}
|
|
68
|
+
ref={boxRef}
|
|
63
69
|
>
|
|
64
70
|
<svg
|
|
65
71
|
viewBox={`${view.minX} ${view.minY} ${view.spanX} ${view.spanY}`}
|
|
@@ -73,19 +79,7 @@ export function RegionMapDrawing({
|
|
|
73
79
|
<BaseAreas areas={base} testId={testId} theme={theme} />
|
|
74
80
|
<ExcludedAreas drawn={drawn} hatchId={hatchId} testId={testId} theme={theme} />
|
|
75
81
|
<Circles radii={model.radii} theme={theme} />
|
|
76
|
-
{highlighted
|
|
77
|
-
<path
|
|
78
|
-
key={`h-${d.id}`}
|
|
79
|
-
d={d.geometry.path}
|
|
80
|
-
fillRule="evenodd"
|
|
81
|
-
vectorEffect="non-scaling-stroke"
|
|
82
|
-
fill={alpha(theme.palette.primary.main, 0.3)}
|
|
83
|
-
stroke={theme.palette.primary.main}
|
|
84
|
-
strokeWidth={2.5}
|
|
85
|
-
pointerEvents="none"
|
|
86
|
-
data-testid={`${testId}-highlight-${d.id}`}
|
|
87
|
-
/>
|
|
88
|
-
))}
|
|
82
|
+
<Highlights areas={highlighted} testId={testId} theme={theme} />
|
|
89
83
|
{showCenter && (
|
|
90
84
|
<circle
|
|
91
85
|
cx={0}
|
|
@@ -107,6 +101,35 @@ export function RegionMapDrawing({
|
|
|
107
101
|
);
|
|
108
102
|
}
|
|
109
103
|
|
|
104
|
+
/** The highlighted areas, drawn over everything but the centre. */
|
|
105
|
+
function Highlights({
|
|
106
|
+
areas,
|
|
107
|
+
testId,
|
|
108
|
+
theme,
|
|
109
|
+
}: {
|
|
110
|
+
areas: readonly DrawnRegion[];
|
|
111
|
+
testId: string;
|
|
112
|
+
theme: Theme;
|
|
113
|
+
}): React.JSX.Element {
|
|
114
|
+
return (
|
|
115
|
+
<>
|
|
116
|
+
{areas.map((d) => (
|
|
117
|
+
<path
|
|
118
|
+
key={`h-${d.id}`}
|
|
119
|
+
d={d.geometry.path}
|
|
120
|
+
fillRule="evenodd"
|
|
121
|
+
vectorEffect="non-scaling-stroke"
|
|
122
|
+
fill={alpha(theme.palette.primary.main, 0.3)}
|
|
123
|
+
stroke={theme.palette.primary.main}
|
|
124
|
+
strokeWidth={2.5}
|
|
125
|
+
pointerEvents="none"
|
|
126
|
+
data-testid={`${testId}-highlight-${d.id}`}
|
|
127
|
+
/>
|
|
128
|
+
))}
|
|
129
|
+
</>
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
110
133
|
/** The hatch an excluded area is filled with: lines, not a colour. */
|
|
111
134
|
function Hatch({ id, pitch, theme }: { id: string; pitch: number; theme: Theme }): React.JSX.Element {
|
|
112
135
|
return (
|
|
@@ -225,16 +248,52 @@ function Circles({ radii, theme }: { radii: readonly number[]; theme: Theme }):
|
|
|
225
248
|
);
|
|
226
249
|
}
|
|
227
250
|
|
|
228
|
-
/**
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
251
|
+
/**
|
|
252
|
+
* Places every label the drawing carries, in their DOM order (the priority
|
|
253
|
+
* order), and hides one that would overlap a label already drawn
|
|
254
|
+
* (`placeLabels`). Measured by a ResizeObserver, never in a layout effect: its
|
|
255
|
+
* first call comes after the browser's own layout, so mounting a label on a
|
|
256
|
+
* tap forces no synchronous reflow of the drawing.
|
|
257
|
+
*/
|
|
258
|
+
function useLabelPlacement(boxRef: React.RefObject<HTMLDivElement | null>, key: string, gap: number): void {
|
|
259
|
+
React.useEffect(() => {
|
|
260
|
+
const box = boxRef.current;
|
|
261
|
+
if (!box || typeof ResizeObserver === 'undefined') return undefined;
|
|
262
|
+
const labels = Array.from(box.querySelectorAll<HTMLElement>('[data-region-label]'));
|
|
263
|
+
const place = (): void => {
|
|
264
|
+
const spanX = box.clientWidth;
|
|
265
|
+
const spanY = box.clientHeight;
|
|
266
|
+
if (spanX === 0 || spanY === 0) return;
|
|
267
|
+
const placed = placeLabels(
|
|
268
|
+
labels.map((label) => ({
|
|
269
|
+
fractionX: Number(label.dataset.fractionX),
|
|
270
|
+
fractionY: Number(label.dataset.fractionY),
|
|
271
|
+
spanX: label.offsetWidth,
|
|
272
|
+
spanY: label.offsetHeight,
|
|
273
|
+
})),
|
|
274
|
+
{ spanX, spanY },
|
|
275
|
+
gap,
|
|
276
|
+
);
|
|
277
|
+
placed.forEach(({ x, y, visible }, index) => {
|
|
278
|
+
const label = labels[index]!;
|
|
279
|
+
label.style.left = `${(x / spanX) * 100}%`;
|
|
280
|
+
label.style.top = `${(y / spanY) * 100}%`;
|
|
281
|
+
label.style.visibility = visible ? 'visible' : 'hidden';
|
|
282
|
+
label.dataset.hidden = visible ? 'false' : 'true';
|
|
283
|
+
});
|
|
284
|
+
};
|
|
285
|
+
const observer = new ResizeObserver(place);
|
|
286
|
+
observer.observe(box);
|
|
287
|
+
for (const label of labels) observer.observe(label);
|
|
288
|
+
return () => observer.disconnect();
|
|
289
|
+
}, [boxRef, key, gap]);
|
|
232
290
|
}
|
|
233
291
|
|
|
234
292
|
/**
|
|
235
293
|
* An area's name over the drawing, at the theme's type size whatever the
|
|
236
|
-
* width — and
|
|
237
|
-
* the
|
|
294
|
+
* width. Placed — and hidden on a collision — by {@link useLabelPlacement}.
|
|
295
|
+
* Decorative (`aria-hidden`): the area's name is its `<title>` and its row in
|
|
296
|
+
* the list.
|
|
238
297
|
*/
|
|
239
298
|
function AreaLabel({
|
|
240
299
|
area,
|
|
@@ -248,42 +307,25 @@ function AreaLabel({
|
|
|
248
307
|
theme: Theme;
|
|
249
308
|
}): React.JSX.Element {
|
|
250
309
|
const at = labelPosition(area.geometry.rings, view);
|
|
251
|
-
const ref = React.useRef<HTMLSpanElement>(null);
|
|
252
|
-
const gap = remPx(theme, 4);
|
|
253
|
-
// Measured by a ResizeObserver, never in a layout effect: the observer's
|
|
254
|
-
// first call comes after the browser's own layout, so mounting a label on a
|
|
255
|
-
// tap forces no synchronous reflow of the drawing.
|
|
256
|
-
React.useEffect(() => {
|
|
257
|
-
const label = ref.current;
|
|
258
|
-
const box = label?.parentElement;
|
|
259
|
-
if (!label || !box || typeof ResizeObserver === 'undefined') return undefined;
|
|
260
|
-
const observer = new ResizeObserver(() => {
|
|
261
|
-
const width = box.clientWidth;
|
|
262
|
-
const height = box.clientHeight;
|
|
263
|
-
if (width === 0 || height === 0) return;
|
|
264
|
-
const x = clampCentre(at.fractionX * width, label.offsetWidth / 2, width, gap);
|
|
265
|
-
const y = clampCentre(at.fractionY * height, label.offsetHeight / 2, height, gap);
|
|
266
|
-
label.style.left = `${(x / width) * 100}%`;
|
|
267
|
-
label.style.top = `${(y / height) * 100}%`;
|
|
268
|
-
});
|
|
269
|
-
observer.observe(box);
|
|
270
|
-
observer.observe(label);
|
|
271
|
-
return () => observer.disconnect();
|
|
272
|
-
}, [at.fractionX, at.fractionY, gap]);
|
|
273
310
|
const halo = `0 0 ${rem(theme, 3)} ${theme.palette.background.paper}`;
|
|
274
311
|
return (
|
|
275
312
|
<Typography
|
|
276
|
-
ref={ref}
|
|
277
313
|
component="span"
|
|
278
314
|
aria-hidden
|
|
279
315
|
data-testid={`${testId}-label-${area.id}`}
|
|
316
|
+
data-region-label=""
|
|
317
|
+
data-fraction-x={at.fractionX}
|
|
318
|
+
data-fraction-y={at.fractionY}
|
|
280
319
|
// Position as an inline style, not `sx`: a per-label class would insert
|
|
281
320
|
// a new CSS rule (and a style recalculation) on every tap.
|
|
282
|
-
style={{
|
|
321
|
+
style={{
|
|
322
|
+
left: `${(at.fractionX * 100).toFixed(2)}%`,
|
|
323
|
+
top: `${(at.fractionY * 100).toFixed(2)}%`,
|
|
324
|
+
}}
|
|
283
325
|
sx={{
|
|
284
326
|
position: 'absolute',
|
|
285
327
|
transform: 'translate(-50%, -50%)',
|
|
286
|
-
fontSize: rem(theme,
|
|
328
|
+
fontSize: rem(theme, 12),
|
|
287
329
|
fontWeight: 700,
|
|
288
330
|
lineHeight: 1.1,
|
|
289
331
|
textAlign: 'center',
|
|
@@ -15,10 +15,22 @@ import {
|
|
|
15
15
|
import type { AddressAutocompleteState } from './AddressAutocomplete.hooks';
|
|
16
16
|
import { AddressInputField } from './AddressInputField';
|
|
17
17
|
import { AddressOption } from './AddressOption';
|
|
18
|
-
import { AddressSuggestionsPaper } from './AddressSuggestionsPaper';
|
|
18
|
+
import { AddressSuggestionsPaper, type AddressSuggestionsPaperProps } from './AddressSuggestionsPaper';
|
|
19
19
|
|
|
20
20
|
export type AddressAutocompleteFieldProps = ResolvedAddressProps & AddressAutocompleteState;
|
|
21
21
|
|
|
22
|
+
// What the open list says when it is empty. A failed lookup is not an empty
|
|
23
|
+
// answer: the field's helper text and the alert below already say what went
|
|
24
|
+
// wrong.
|
|
25
|
+
const emptyTextFor = (
|
|
26
|
+
text: { typeToSearch: string; noAddressesFound: string },
|
|
27
|
+
inputValue: string,
|
|
28
|
+
apiError: string | null | undefined,
|
|
29
|
+
): string | undefined => {
|
|
30
|
+
if (apiError) return undefined;
|
|
31
|
+
return inputValue.length <= MIN_QUERY_LENGTH ? text.typeToSearch : text.noAddressesFound;
|
|
32
|
+
};
|
|
33
|
+
|
|
22
34
|
// The live field, rendered once Google Maps (or the mock stand-in) is ready.
|
|
23
35
|
export const AddressAutocompleteField: FC<AddressAutocompleteFieldProps> = ({
|
|
24
36
|
copy,
|
|
@@ -42,6 +54,9 @@ export const AddressAutocompleteField: FC<AddressAutocompleteFieldProps> = ({
|
|
|
42
54
|
handleGetCurrentLocation,
|
|
43
55
|
}) => {
|
|
44
56
|
const text = resolveLabels(EN_US_ADDRESS_AUTOCOMPLETE_COPY, copy);
|
|
57
|
+
const paperProps: AddressSuggestionsPaperProps = {
|
|
58
|
+
emptyText: emptyTextFor(text, inputValue, apiError),
|
|
59
|
+
};
|
|
45
60
|
return (
|
|
46
61
|
<Box data-testid="address-autocomplete-container">
|
|
47
62
|
<Autocomplete
|
|
@@ -57,9 +72,7 @@ export const AddressAutocompleteField: FC<AddressAutocompleteFieldProps> = ({
|
|
|
57
72
|
getOptionLabel={addressOptionLabel}
|
|
58
73
|
isOptionEqualToValue={isSameAddressOption}
|
|
59
74
|
PaperComponent={AddressSuggestionsPaper}
|
|
60
|
-
|
|
61
|
-
inputValue.length <= MIN_QUERY_LENGTH ? text.typeToSearch : text.noAddressesFound
|
|
62
|
-
}
|
|
75
|
+
slotProps={{ paper: paperProps }}
|
|
63
76
|
renderOption={({ key, ...optionProps }, option, state) => (
|
|
64
77
|
<AddressOption
|
|
65
78
|
key={key}
|
|
@@ -1,14 +1,30 @@
|
|
|
1
1
|
import type { PaperProps } from '@mui/material/Paper/index.js';
|
|
2
|
+
import Box from '@mui/material/Box/index.js';
|
|
2
3
|
import Paper from '@mui/material/Paper/index.js';
|
|
3
4
|
import { alpha, useTheme } from '@mui/material/styles/index.js';
|
|
4
5
|
import type { FC } from 'react';
|
|
5
|
-
import React from 'react';
|
|
6
|
+
import React, { Children } from 'react';
|
|
6
7
|
|
|
7
8
|
import { rem } from '../../../tokens/relative';
|
|
8
9
|
|
|
10
|
+
export interface AddressSuggestionsPaperProps extends PaperProps {
|
|
11
|
+
/**
|
|
12
|
+
* Said when the list is open with nothing in it. MUI never renders its own
|
|
13
|
+
* `noOptionsText` for a `freeSolo` field, so an empty list was a blank strip
|
|
14
|
+
* (FUT-4162): the paper says it instead, exactly when MUI gave it no content
|
|
15
|
+
* (no suggestions and no loading row).
|
|
16
|
+
*/
|
|
17
|
+
emptyText?: React.ReactNode;
|
|
18
|
+
}
|
|
19
|
+
|
|
9
20
|
// The dropdown surface, frosted to match the glass field.
|
|
10
|
-
export const AddressSuggestionsPaper: FC<
|
|
21
|
+
export const AddressSuggestionsPaper: FC<AddressSuggestionsPaperProps> = ({
|
|
22
|
+
emptyText,
|
|
23
|
+
children,
|
|
24
|
+
...props
|
|
25
|
+
}) => {
|
|
11
26
|
const theme = useTheme();
|
|
27
|
+
const empty = Children.toArray(children).length === 0;
|
|
12
28
|
|
|
13
29
|
return (
|
|
14
30
|
<Paper
|
|
@@ -22,6 +38,19 @@ export const AddressSuggestionsPaper: FC<PaperProps> = (props) => {
|
|
|
22
38
|
WebkitBackdropFilter: `blur(${rem(theme, 20)})`,
|
|
23
39
|
border: `1px solid ${alpha(theme.palette.divider, 0.18)}`,
|
|
24
40
|
}}
|
|
25
|
-
|
|
41
|
+
>
|
|
42
|
+
{children}
|
|
43
|
+
{empty && emptyText && (
|
|
44
|
+
<Box
|
|
45
|
+
role="presentation"
|
|
46
|
+
data-testid="address-suggestions-empty"
|
|
47
|
+
// Keeps the input focused, as MUI's own no-options row does.
|
|
48
|
+
onMouseDown={(event) => event.preventDefault()}
|
|
49
|
+
sx={{ px: 2, py: 1.5, color: 'text.secondary' }}
|
|
50
|
+
>
|
|
51
|
+
{emptyText}
|
|
52
|
+
</Box>
|
|
53
|
+
)}
|
|
54
|
+
</Paper>
|
|
26
55
|
);
|
|
27
56
|
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import type { Theme } from '@mui/material/styles/index.js';
|
|
2
|
+
|
|
3
|
+
import { alpha, blend, darken, decomposeColor, getContrastRatio, getLuminance, lighten } from '../../../tokens/color';
|
|
4
|
+
|
|
5
|
+
import { isSameDay } from './Calendar.dates';
|
|
6
|
+
import type { DateRange, DayRenderArgs, SelectionMode } from './Calendar.types';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* WHERE A DAY SITS ON THE RANGE BAND (FUT-4162).
|
|
10
|
+
*
|
|
11
|
+
* A selected range is ONE band behind its days, not a tile per day: the grid
|
|
12
|
+
* has no column gap and each day paints its share of the band. A day strictly
|
|
13
|
+
* inside the range paints all of it (`full`); the first and last day paint the
|
|
14
|
+
* half that faces the rest of the range (`after` / `before`), so the band runs
|
|
15
|
+
* into the round endpoint and stops at its centre. A range of one day, or no
|
|
16
|
+
* range, paints none.
|
|
17
|
+
*
|
|
18
|
+
* While only the start is chosen, the hovered day stands in for the end, the
|
|
19
|
+
* same preview `isDateInRange` draws.
|
|
20
|
+
*/
|
|
21
|
+
export type DayBand = 'none' | 'full' | 'after' | 'before';
|
|
22
|
+
|
|
23
|
+
// The other end of the range: its end, or while only the start is chosen, the
|
|
24
|
+
// hovered day standing in for it.
|
|
25
|
+
const otherEnd = (range: DateRange, hoveredDate: Date | null, isDisabled: (date: Date) => boolean) =>
|
|
26
|
+
range.end ?? (hoveredDate && !isDisabled(hoveredDate) ? hoveredDate : null);
|
|
27
|
+
|
|
28
|
+
// The half an endpoint paints: towards the rest of the range.
|
|
29
|
+
const endpointBand = (date: Date, start: Date, other: Date): DayBand => {
|
|
30
|
+
const [first, last] = start < other ? [start, other] : [other, start];
|
|
31
|
+
if (isSameDay(date, first)) return 'after';
|
|
32
|
+
if (isSameDay(date, last)) return 'before';
|
|
33
|
+
return 'none';
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const bandFor = ({
|
|
37
|
+
args,
|
|
38
|
+
selectionMode,
|
|
39
|
+
range,
|
|
40
|
+
hoveredDate,
|
|
41
|
+
isDisabled,
|
|
42
|
+
}: {
|
|
43
|
+
args: DayRenderArgs;
|
|
44
|
+
selectionMode: SelectionMode;
|
|
45
|
+
range: DateRange;
|
|
46
|
+
hoveredDate: Date | null;
|
|
47
|
+
isDisabled: (date: Date) => boolean;
|
|
48
|
+
}): DayBand => {
|
|
49
|
+
if (selectionMode !== 'range') return 'none';
|
|
50
|
+
if (args.inRange) return 'full';
|
|
51
|
+
|
|
52
|
+
const other = otherEnd(range, hoveredDate, isDisabled);
|
|
53
|
+
if (!range.start || !other || isSameDay(range.start, other)) return 'none';
|
|
54
|
+
return endpointBand(args.date, range.start, other);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The band: the brand at a quarter strength, so it reads as the brand's tint on
|
|
59
|
+
* any ground (on white it is the brand three quarters of the way to white).
|
|
60
|
+
*/
|
|
61
|
+
export const BAND_OPACITY = 0.25;
|
|
62
|
+
|
|
63
|
+
export const bandColor = (theme: Theme): string => alpha(theme.palette.primary.main, BAND_OPACITY);
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* WCAG AA for body text, plus a margin: `getLuminance` rounds to three
|
|
67
|
+
* places, which can move a ratio by about a hundredth either way.
|
|
68
|
+
*/
|
|
69
|
+
const ENDPOINT_MIN_CONTRAST = 4.55;
|
|
70
|
+
const STEP = 0.01;
|
|
71
|
+
|
|
72
|
+
// The ink as it reads ON the fill: MUI's dark ink is 87% black, so it is laid
|
|
73
|
+
// over the fill before it is measured, rather than taken as solid black.
|
|
74
|
+
const readsAt = (ink: string, fill: string): number => {
|
|
75
|
+
const [, , , opacity = 1] = decomposeColor(ink).values;
|
|
76
|
+
return getContrastRatio(opacity < 1 ? blend(fill, ink, opacity) : ink, fill);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// Light ink (white) wants a darker fill; dark ink a lighter one.
|
|
80
|
+
const awayFromInk = (ink: string): ((color: string, coefficient: number) => string) =>
|
|
81
|
+
getLuminance(ink) > 0.5 ? darken : lighten;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* An endpoint's fill: the brand, moved away from its own ink JUST far enough
|
|
85
|
+
* for that ink to read at AA (FUT-4162).
|
|
86
|
+
*
|
|
87
|
+
* The ink is the palette's `primary.contrastText`, which MUI picks at 3:1, so
|
|
88
|
+
* a brand can ship an ink that reads at 3 to 4.5:1 on it — the default indigo
|
|
89
|
+
* is 4.47:1 under white. Rather than change the ink (every other component
|
|
90
|
+
* shares it), the fill gives way: darker under white ink, lighter under dark
|
|
91
|
+
* ink. A brand that already passes is returned unchanged; the default indigo
|
|
92
|
+
* moves by one percent, which no one can see.
|
|
93
|
+
*/
|
|
94
|
+
export const endpointFill = (theme: Theme): string => {
|
|
95
|
+
const { main, contrastText } = theme.palette.primary;
|
|
96
|
+
try {
|
|
97
|
+
if (readsAt(contrastText, main) >= ENDPOINT_MIN_CONTRAST) return main;
|
|
98
|
+
const move = awayFromInk(contrastText);
|
|
99
|
+
for (let coefficient = STEP; coefficient < 1; coefficient += STEP) {
|
|
100
|
+
const fill = move(main, coefficient);
|
|
101
|
+
if (readsAt(contrastText, fill) >= ENDPOINT_MIN_CONTRAST) return fill;
|
|
102
|
+
}
|
|
103
|
+
return move(main, 1);
|
|
104
|
+
} catch {
|
|
105
|
+
// A colour format the helpers cannot decompose: the brand as it is.
|
|
106
|
+
return main;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/** A hovered endpoint: one more step the same way, so it only gains contrast. */
|
|
111
|
+
export const endpointHoverFill = (theme: Theme): string => {
|
|
112
|
+
const fill = endpointFill(theme);
|
|
113
|
+
try {
|
|
114
|
+
return awayFromInk(theme.palette.primary.contrastText)(fill, 0.15);
|
|
115
|
+
} catch {
|
|
116
|
+
return fill;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
@@ -5,14 +5,20 @@ import React from 'react';
|
|
|
5
5
|
|
|
6
6
|
import { rem, sxRem } from '../../../tokens/relative';
|
|
7
7
|
|
|
8
|
+
import type { DayBand } from './Calendar.band';
|
|
9
|
+
import { bandColor, endpointFill, endpointHoverFill } from './Calendar.band';
|
|
8
10
|
import type { DayRenderArgs } from './Calendar.types';
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
|
-
* A
|
|
12
|
-
*
|
|
13
|
-
*
|
|
13
|
+
* A column's width: the 304 design px a month asked for when its seven 40px
|
|
14
|
+
* cells sat 4px apart, shared by seven columns that now touch (FUT-4162). The
|
|
15
|
+
* cell fills its column up to this size, so the month shrinks with its
|
|
16
|
+
* container instead of holding a fixed 304px floor (FUT-3861).
|
|
14
17
|
*/
|
|
15
|
-
const
|
|
18
|
+
const COLUMN_SIZE = sxRem(304 / 7);
|
|
19
|
+
|
|
20
|
+
/** 304/7 wide to 40 tall: the day's face is a 40 design px circle at full size. */
|
|
21
|
+
const CELL_RATIO = '38 / 35';
|
|
16
22
|
|
|
17
23
|
interface DayState extends DayRenderArgs {
|
|
18
24
|
outside: boolean;
|
|
@@ -42,12 +48,24 @@ const dayClassNames = (state: DayState, custom?: string): string =>
|
|
|
42
48
|
const isEndpoint = (day: DayRenderArgs): boolean =>
|
|
43
49
|
day.selected || day.rangeStart || day.rangeEnd;
|
|
44
50
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
51
|
+
// The band's share of the cell (see `Calendar.band.ts`): all of it, or the
|
|
52
|
+
// half that faces the rest of the range.
|
|
53
|
+
const BAND_IMAGE: Record<Exclude<DayBand, 'none'>, (band: string) => string> = {
|
|
54
|
+
full: (band) => `linear-gradient(${band}, ${band})`,
|
|
55
|
+
after: (band) => `linear-gradient(to right, transparent 50%, ${band} 50%)`,
|
|
56
|
+
before: (band) => `linear-gradient(to left, transparent 50%, ${band} 50%)`,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
// A gradient's `to right` is physical; a right-to-left grid starts a range on
|
|
60
|
+
// its right, so the two halves trade places there.
|
|
61
|
+
const inDirection = (band: Exclude<DayBand, 'none'>, theme: Theme): Exclude<DayBand, 'none'> => {
|
|
62
|
+
if (theme.direction !== 'rtl' || band === 'full') return band;
|
|
63
|
+
return band === 'after' ? 'before' : 'after';
|
|
49
64
|
};
|
|
50
65
|
|
|
66
|
+
const faceBackgroundFor = (day: DayRenderArgs): ((theme: Theme) => string) | string =>
|
|
67
|
+
isEndpoint(day) ? endpointFill : 'transparent';
|
|
68
|
+
|
|
51
69
|
const colorFor = (day: DayRenderArgs, visible: boolean): string => {
|
|
52
70
|
if (isEndpoint(day)) return 'primary.contrastText';
|
|
53
71
|
if (day.disabled) return 'text.disabled';
|
|
@@ -57,35 +75,65 @@ const colorFor = (day: DayRenderArgs, visible: boolean): string => {
|
|
|
57
75
|
return 'text.primary';
|
|
58
76
|
};
|
|
59
77
|
|
|
60
|
-
const hoverBackgroundFor = (day: DayRenderArgs): string | undefined => {
|
|
78
|
+
const hoverBackgroundFor = (day: DayRenderArgs): ((theme: Theme) => string) | string | undefined => {
|
|
61
79
|
if (day.disabled) return undefined;
|
|
62
|
-
return day
|
|
80
|
+
return isEndpoint(day) ? endpointHoverFill : 'action.hover';
|
|
63
81
|
};
|
|
64
82
|
|
|
65
|
-
|
|
83
|
+
// The band reaches the cell's edges so neighbouring days join; where a week
|
|
84
|
+
// row ends, it rounds off instead of stopping square: half the cell each way
|
|
85
|
+
// is a half-round cap on a cell as tall as it is wide.
|
|
86
|
+
const BAND_RADIUS = '50%';
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* One cell: the band, painted on the button across its whole column, and the
|
|
90
|
+
* day's round face, a `::before` circle behind the number. The face is a
|
|
91
|
+
* pseudo-element so the button's own content stays the bare day number a host's
|
|
92
|
+
* tests query (`getByText('27')` is the cell, as it always was).
|
|
93
|
+
*/
|
|
94
|
+
const dayCellSx = (day: DayRenderArgs, band: DayBand, visible: boolean): SxProps<Theme> => ({
|
|
95
|
+
position: 'relative',
|
|
96
|
+
isolation: 'isolate',
|
|
66
97
|
display: 'flex',
|
|
67
98
|
alignItems: 'center',
|
|
68
99
|
justifyContent: 'center',
|
|
69
|
-
//
|
|
70
|
-
//
|
|
71
|
-
// column's `minmax(0, 1fr)`
|
|
72
|
-
|
|
100
|
+
// The column it ASKS for keeps the month's intrinsic width at 304 (FUT-3861),
|
|
101
|
+
// now that the seven columns carry no gap between them; `maxWidth` and the
|
|
102
|
+
// column's `minmax(0, 1fr)` let it give way below that, and the ratio keeps
|
|
103
|
+
// it 40 tall at full size and shrinking with it.
|
|
104
|
+
width: COLUMN_SIZE,
|
|
73
105
|
maxWidth: '100%',
|
|
74
|
-
aspectRatio:
|
|
75
|
-
justifySelf: '
|
|
106
|
+
aspectRatio: CELL_RATIO,
|
|
107
|
+
justifySelf: 'stretch',
|
|
76
108
|
boxSizing: 'border-box',
|
|
77
109
|
padding: 0,
|
|
78
110
|
border: 'none',
|
|
79
|
-
|
|
111
|
+
background: 'none',
|
|
112
|
+
backgroundImage: band === 'none' ? 'none' : (theme: Theme) => BAND_IMAGE[inDirection(band, theme)](bandColor(theme)),
|
|
80
113
|
cursor: day.disabled ? 'not-allowed' : 'pointer',
|
|
81
|
-
backgroundColor: backgroundFor(day),
|
|
82
114
|
color: colorFor(day, visible),
|
|
83
115
|
opacity: !day.inCurrentMonth && visible ? 0.5 : 1,
|
|
84
|
-
fontWeight: day.today ? 'bold' : 'normal',
|
|
85
|
-
'&:
|
|
116
|
+
fontWeight: day.today || isEndpoint(day) ? 'bold' : 'normal',
|
|
117
|
+
'&:nth-of-type(7n + 1)': { borderStartStartRadius: BAND_RADIUS, borderEndStartRadius: BAND_RADIUS },
|
|
118
|
+
'&:nth-of-type(7n)': { borderStartEndRadius: BAND_RADIUS, borderEndEndRadius: BAND_RADIUS },
|
|
119
|
+
'&::before': {
|
|
120
|
+
content: '""',
|
|
121
|
+
position: 'absolute',
|
|
122
|
+
inset: 0,
|
|
123
|
+
margin: 'auto',
|
|
124
|
+
zIndex: -1,
|
|
125
|
+
// A circle as tall as the cell: 40 design px at full size (FUT-3861).
|
|
126
|
+
height: '100%',
|
|
127
|
+
aspectRatio: '1 / 1',
|
|
128
|
+
maxWidth: '100%',
|
|
129
|
+
borderRadius: '50%',
|
|
130
|
+
backgroundColor: faceBackgroundFor(day),
|
|
131
|
+
},
|
|
132
|
+
'&:hover::before': {
|
|
86
133
|
backgroundColor: hoverBackgroundFor(day),
|
|
87
134
|
},
|
|
88
|
-
'&:focus': {
|
|
135
|
+
'&:focus': { outline: 'none' },
|
|
136
|
+
'&:focus::before': {
|
|
89
137
|
outline: (theme: Theme) => `${rem(theme, 2)} solid`,
|
|
90
138
|
outlineColor: 'primary.main',
|
|
91
139
|
outlineOffset: sxRem(1),
|
|
@@ -94,6 +142,7 @@ const dayCellSx = (day: DayRenderArgs, visible: boolean): SxProps<Theme> => ({
|
|
|
94
142
|
|
|
95
143
|
export interface CalendarDayProps {
|
|
96
144
|
day: DayRenderArgs;
|
|
145
|
+
band: DayBand;
|
|
97
146
|
focused: boolean;
|
|
98
147
|
showOutsideDays: boolean;
|
|
99
148
|
dayClassName?: (args: DayRenderArgs) => string;
|
|
@@ -104,6 +153,7 @@ export interface CalendarDayProps {
|
|
|
104
153
|
|
|
105
154
|
export const CalendarDay: FC<CalendarDayProps> = ({
|
|
106
155
|
day,
|
|
156
|
+
band,
|
|
107
157
|
focused,
|
|
108
158
|
showOutsideDays,
|
|
109
159
|
dayClassName,
|
|
@@ -127,7 +177,7 @@ export const CalendarDay: FC<CalendarDayProps> = ({
|
|
|
127
177
|
onClick={() => onSelect(day.date)}
|
|
128
178
|
onMouseEnter={() => onHover(day.date)}
|
|
129
179
|
onMouseLeave={onHoverEnd}
|
|
130
|
-
sx={dayCellSx(day, visible)}
|
|
180
|
+
sx={dayCellSx(day, band, visible)}
|
|
131
181
|
>
|
|
132
182
|
{day.selected && (
|
|
133
183
|
<Box component="span" data-testid="calendar-selected-date" sx={{ display: 'none' }} />
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { FC } from 'react';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
|
|
4
|
+
import { bandFor } from './Calendar.band';
|
|
4
5
|
import { isSameDay } from './Calendar.dates';
|
|
5
6
|
import { buildDayArgs } from './Calendar.selection';
|
|
6
7
|
import type { CalendarProps, DateRange, MonthMatrixDay, SelectionMode } from './Calendar.types';
|
|
@@ -41,6 +42,7 @@ export const CalendarDayCell: FC<DayCellContext & { day: MonthMatrixDay }> = ({
|
|
|
41
42
|
return (
|
|
42
43
|
<CalendarDay
|
|
43
44
|
day={args}
|
|
45
|
+
band={bandFor({ args, ...context })}
|
|
44
46
|
focused={isSameDay(args.date, focusedDate)}
|
|
45
47
|
showOutsideDays={showOutsideDays}
|
|
46
48
|
dayClassName={dayClassName}
|