@12-apps/ui 6.90.0 → 6.92.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components-catalog.md +3 -3
- package/dist/_internal/components/data-display/Alert/Alert.js +2 -2
- package/dist/_internal/components/data-display/Avatar/Avatar.js +2 -2
- package/dist/_internal/components/data-display/Badge/Badge.js +2 -2
- package/dist/_internal/components/data-display/CardKit/card-actions-context.js +3 -3
- package/dist/_internal/components/data-display/CardKit/use-remove-confirm.js +4 -4
- package/dist/_internal/components/data-display/Carousel/Carousel.js +2 -2
- package/dist/_internal/components/data-display/Chart/Chart.js +4 -4
- package/dist/_internal/components/data-display/Chart/SpecChart.js +6 -6
- 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/DataGrid/DataGrid.js +2 -2
- package/dist/_internal/components/data-display/DataViews/DataViewsGrid.js +25 -25
- package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +31 -31
- package/dist/_internal/components/data-display/DataViews/base-list-card-geometry.js +6 -6
- package/dist/_internal/components/data-display/DataViews/base-list-card-layout.js +7 -7
- package/dist/_internal/components/data-display/DataViews/base-list-card-slots.js +5 -5
- package/dist/_internal/components/data-display/DataViews/base-list-card.js +8 -8
- package/dist/_internal/components/data-display/DataViews/data-views-display-panel.js +1 -1
- package/dist/_internal/components/data-display/DataViews/data-views-filter-panel.js +7 -7
- package/dist/_internal/components/data-display/DataViews/data-views-grid-bodies.js +9 -9
- package/dist/_internal/components/data-display/DataViews/data-views-grid-parts.js +22 -22
- 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 +7 -7
- package/dist/_internal/components/data-display/DataViews/data-views-more-filters.js +8 -8
- package/dist/_internal/components/data-display/DataViews/data-views-range-bounds.js +4 -4
- package/dist/_internal/components/data-display/DataViews/data-views-range-pill.js +6 -6
- package/dist/_internal/components/data-display/DataViews/data-views-scope-tabs.js +2 -2
- package/dist/_internal/components/data-display/DataViews/data-views-shell-toolbar.js +1 -1
- package/dist/_internal/components/data-display/DataViews/data-views-table-parts.js +3 -3
- package/dist/_internal/components/data-display/DataViews/data-views-toolbar.js +1 -1
- package/dist/_internal/components/data-display/DataViews/list-card-rails.js +4 -4
- package/dist/_internal/components/data-display/DataViews/use-data-views-state.js +2 -2
- package/dist/_internal/components/data-display/DayRuler/DayRuler.en-US.js +1 -1
- package/dist/_internal/components/data-display/DayRuler/DayRuler.js +5 -5
- package/dist/_internal/components/data-display/DayRuler/DayRuler.labels.js +3 -3
- package/dist/_internal/components/data-display/DayRuler/DayRuler.parts.js +9 -4
- package/dist/_internal/components/data-display/DayRuler/DayRuler.pt-BR.js +1 -1
- package/dist/_internal/components/data-display/DayRuler/DayRuler.styles.js +9 -1
- package/dist/_internal/components/data-display/FleetMap/FleetBody.js +10 -10
- package/dist/_internal/components/data-display/FleetMap/FleetCanvas.js +9 -9
- package/dist/_internal/components/data-display/FleetMap/FleetMap.js +12 -12
- 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/MapLayers.js +3 -3
- package/dist/_internal/components/data-display/MapPreview/MapMarkers.js +2 -2
- package/dist/_internal/components/data-display/MapPreview/MapPreview.js +8 -8
- package/dist/_internal/components/data-display/RegionMap/RegionMap.hooks.js +2 -1
- package/dist/_internal/components/data-display/RegionMap/RegionMap.js +5 -4
- package/dist/_internal/components/data-display/RegionMap/RegionMap.view.js +19 -0
- package/dist/_internal/components/data-display/RegionMap/RegionMapDrawing.js +1 -1
- package/dist/_internal/components/data-display/ScheduleGrid/ScheduleGrid.js +4 -3
- package/dist/_internal/components/data-display/ScheduleGrid/ScheduleGrid.parts.js +3 -2
- package/dist/_internal/components/data-display/ScheduleGrid/schedule-header-host.styles.js +12 -0
- package/dist/_internal/components/data-display/ScheduleGrid/schedule-header-host.styles.js.map +1 -0
- package/dist/_internal/components/data-display/index.js +58 -51
- package/dist/_internal/components/feedback/NotificationStatusNotice/NotificationStatusNotice.js +3 -3
- package/dist/_internal/components/feedback/SequenceResolver/SequenceResolver.js +5 -5
- package/dist/_internal/components/feedback/SequenceResolver/SequenceResolver.overview.js +4 -4
- package/dist/_internal/components/feedback/SequenceResolver/SequenceResolver.parts.js +3 -3
- package/dist/_internal/components/feedback/index.js +6 -6
- package/dist/_internal/components/index.js +69 -62
- package/dist/_internal/components/navigation/SectionNav/SectionNav.bar.js +6 -6
- package/dist/_internal/components/navigation/SectionNav/SectionNav.js +9 -9
- package/dist/_internal/components/navigation/SectionNav/SectionNav.parts.js +3 -3
- package/dist/_internal/components/navigation/SectionNav/SectionNav.primary.js +4 -4
- package/dist/_internal/components/navigation/SectionNav/SectionNav.rail.js +5 -5
- package/dist/_internal/components/navigation/SectionNav/SectionNav.railCreate.js +4 -4
- package/dist/_internal/components/navigation/SectionNav/SectionNav.sheet.js +4 -4
- package/dist/_internal/components/navigation/index.js +9 -9
- package/dist/_internal/user-avatar/user-avatar.js +3 -3
- package/dist/charts.js +6 -6
- package/dist/{chunk-FI2CQOGC.js → chunk-3OHZAZEE.js} +5 -5
- package/dist/{chunk-CJ6XXM4X.js → chunk-3PQL2EN5.js} +6 -6
- package/dist/{chunk-7YJYIMWP.js → chunk-4QR7LM5F.js} +6 -6
- package/dist/{chunk-HI7JPDD6.js → chunk-5357QUVE.js} +2 -2
- package/dist/{chunk-WNNA6YYE.js → chunk-5I75WRXT.js} +10 -7
- package/dist/chunk-5I75WRXT.js.map +1 -0
- package/dist/chunk-5MXVKZKZ.js +30 -0
- package/dist/chunk-5MXVKZKZ.js.map +1 -0
- package/dist/{chunk-BP3ZKIPE.js → chunk-64UNVW6D.js} +4 -4
- package/dist/{chunk-SCXVTNLE.js → chunk-66VKX6JE.js} +2 -2
- package/dist/{chunk-N5PVD4J5.js → chunk-6DO672AG.js} +7 -7
- package/dist/{chunk-NK6O4NE4.js → chunk-AI7XWBNG.js} +3 -3
- package/dist/{chunk-SNWCT6JN.js → chunk-AMIUZRDQ.js} +3 -3
- package/dist/{chunk-BMTIBQQC.js → chunk-BBBHPK2Q.js} +6 -6
- package/dist/{chunk-A3DDEKLV.js → chunk-BOADHYTA.js} +2 -2
- package/dist/{chunk-KRBPWTXW.js → chunk-CKQOYPH3.js} +2 -2
- package/dist/{chunk-EUR2ORTN.js → chunk-CSJ7WNXU.js} +2 -2
- package/dist/{chunk-QADTI63U.js → chunk-CZVAVX5L.js} +4 -4
- package/dist/{chunk-O3OU3ED7.js → chunk-D7R6SRJB.js} +3 -3
- package/dist/{chunk-O3OU3ED7.js.map → chunk-D7R6SRJB.js.map} +1 -1
- package/dist/{chunk-DVX4HDNP.js → chunk-DBPFKGXX.js} +2 -2
- package/dist/{chunk-XCUHGPPZ.js → chunk-DTZOP4ZR.js} +2 -2
- package/dist/chunk-DY2I6LMX.js +1 -0
- package/dist/chunk-DY2I6LMX.js.map +1 -0
- package/dist/{chunk-BLZDSCIZ.js → chunk-DYHOBKPU.js} +6 -6
- package/dist/{chunk-QKOJ4637.js → chunk-E6K2UZGR.js} +3 -3
- package/dist/{chunk-MX2RF34M.js → chunk-E73C73UD.js} +15 -7
- package/dist/chunk-E73C73UD.js.map +1 -0
- package/dist/{chunk-HNW7IZPV.js → chunk-EZBBLLEU.js} +5 -5
- package/dist/{chunk-HNW7IZPV.js.map → chunk-EZBBLLEU.js.map} +1 -1
- package/dist/{chunk-K3IB7S7Q.js → chunk-F2ZUUEXC.js} +3 -2
- package/dist/{chunk-K3IB7S7Q.js.map → chunk-F2ZUUEXC.js.map} +1 -1
- package/dist/{chunk-2M3W6ACW.js → chunk-FAUNQ3FS.js} +3 -3
- package/dist/{chunk-VIMMEADQ.js → chunk-FORAVDJF.js} +9 -9
- package/dist/{chunk-PJNIJIE6.js → chunk-FQNDJITD.js} +2 -2
- package/dist/chunk-FWAY2SAI.js +72 -0
- package/dist/chunk-FWAY2SAI.js.map +1 -0
- package/dist/{chunk-COKPPU42.js → chunk-FWTVIRZZ.js} +13 -13
- package/dist/{chunk-GMRQPNG3.js → chunk-G2NVBCF7.js} +20 -25
- package/dist/chunk-G2NVBCF7.js.map +1 -0
- package/dist/{chunk-JHWEL4NX.js → chunk-HS662RLW.js} +2 -2
- package/dist/{chunk-BZBLPXV7.js → chunk-IWSTMVCA.js} +4 -4
- package/dist/{chunk-TZC6KIK2.js → chunk-JG733RMP.js} +5 -5
- package/dist/{chunk-K3PMMW23.js → chunk-K6VEN5VN.js} +4 -4
- package/dist/{chunk-UKUGSU3Y.js → chunk-L4V7FZJI.js} +2 -2
- package/dist/{chunk-24HHUCWB.js → chunk-LDCZPZPD.js} +2 -2
- package/dist/{chunk-ILJ3FXIC.js → chunk-MM3QESLI.js} +2 -2
- package/dist/{chunk-EEO7M5GU.js → chunk-MYTV353T.js} +4 -4
- package/dist/{chunk-3HZKUN5J.js → chunk-MZAYIG2I.js} +2 -2
- package/dist/{chunk-AKE6KVQG.js → chunk-NGXL4R54.js} +5 -1
- package/dist/chunk-NGXL4R54.js.map +1 -0
- package/dist/{chunk-RDCIST7P.js → chunk-OCT5VCLP.js} +2 -2
- package/dist/{chunk-G2PVUPE7.js → chunk-OJZLFFG4.js} +41 -3
- package/dist/chunk-OJZLFFG4.js.map +1 -0
- package/dist/{chunk-F7LBTMCA.js → chunk-P53ANKZV.js} +4 -4
- package/dist/{chunk-HMEGQKNQ.js → chunk-PCQ5JWLF.js} +15 -7
- package/dist/chunk-PCQ5JWLF.js.map +1 -0
- package/dist/{chunk-QVDEGBME.js → chunk-PEAUGQKU.js} +4 -4
- package/dist/{chunk-BV2LOTMC.js → chunk-Q3SILZTQ.js} +2 -2
- package/dist/{chunk-DSBC6O46.js → chunk-R4LCPPKA.js} +3 -3
- package/dist/{chunk-ZH6NYB6Y.js → chunk-S2VZUBM7.js} +7 -7
- package/dist/{chunk-JFD742C3.js → chunk-TMINUTQQ.js} +2 -2
- package/dist/{chunk-SK2CTB3O.js → chunk-U2SAW6DH.js} +5 -5
- package/dist/{chunk-ACM3HHZY.js → chunk-UDBOGSFO.js} +68 -2
- package/dist/chunk-UDBOGSFO.js.map +1 -0
- package/dist/{chunk-DAHSKQBV.js → chunk-UMOHHWXY.js} +2 -2
- package/dist/{chunk-QAEO52Z4.js → chunk-VHE7UEG5.js} +2 -2
- package/dist/{chunk-TIM4PXWN.js → chunk-VWRXSBT2.js} +2 -2
- package/dist/{chunk-KANCE4MS.js → chunk-W2KOP27S.js} +3 -3
- package/dist/{chunk-P772HCHI.js → chunk-W676GY42.js} +4 -4
- package/dist/{chunk-T2G4LDU5.js → chunk-WLLUARTC.js} +2 -2
- package/dist/{chunk-3OTGREQG.js → chunk-X3GD3TFI.js} +15 -15
- package/dist/{chunk-3X2MA47R.js → chunk-XNAI7QGU.js} +6 -6
- package/dist/{chunk-L6JAALMX.js → chunk-XRV4QFEQ.js} +3 -3
- package/dist/{chunk-WH3LUOCQ.js → chunk-YE7M7URT.js} +2 -2
- package/dist/{chunk-WWR6APJR.js → chunk-YVDNCV2D.js} +5 -5
- package/dist/{chunk-LOLYBFYY.js → chunk-ZCNR4DN5.js} +5 -5
- package/dist/{chunk-D3OXTS7Y.js → chunk-ZHCZOPKE.js} +3 -2
- package/dist/{chunk-D3OXTS7Y.js.map → chunk-ZHCZOPKE.js.map} +1 -1
- package/dist/data-display/Alert.js +2 -2
- package/dist/data-display/Avatar.js +2 -2
- package/dist/data-display/Badge.js +2 -2
- package/dist/data-display/CardKit.js +14 -14
- package/dist/data-display/Carousel.js +2 -2
- package/dist/data-display/Chart.js +6 -6
- package/dist/data-display/DataGrid.js +2 -2
- package/dist/data-display/DataViews.js +47 -47
- package/dist/data-display/DayRuler.js +9 -9
- package/dist/data-display/FleetMap.js +12 -12
- package/dist/data-display/Lightbox.js +7 -7
- package/dist/data-display/MapPreview.js +8 -8
- package/dist/data-display/RegionMap.js +12 -6
- package/dist/data-display/ScheduleGrid.js +4 -3
- package/dist/feedback/NotificationStatusNotice.js +3 -3
- package/dist/feedback/SequenceResolver.js +5 -5
- package/dist/navigation/SectionNav.js +9 -9
- package/dist/types/components/data-display/DayRuler/DayRuler.d.ts.map +1 -1
- package/dist/types/components/data-display/DayRuler/DayRuler.en-US.d.ts.map +1 -1
- package/dist/types/components/data-display/DayRuler/DayRuler.labels.d.ts +2 -0
- package/dist/types/components/data-display/DayRuler/DayRuler.labels.d.ts.map +1 -1
- package/dist/types/components/data-display/DayRuler/DayRuler.parts.d.ts +13 -1
- package/dist/types/components/data-display/DayRuler/DayRuler.parts.d.ts.map +1 -1
- package/dist/types/components/data-display/DayRuler/DayRuler.pt-BR.d.ts.map +1 -1
- package/dist/types/components/data-display/DayRuler/DayRuler.styles.d.ts +16 -0
- package/dist/types/components/data-display/DayRuler/DayRuler.styles.d.ts.map +1 -1
- package/dist/types/components/data-display/DayRuler/DayRuler.types.d.ts +44 -1
- package/dist/types/components/data-display/DayRuler/DayRuler.types.d.ts.map +1 -1
- package/dist/types/components/data-display/DayRuler/index.d.ts +1 -1
- package/dist/types/components/data-display/DayRuler/index.d.ts.map +1 -1
- package/dist/types/components/data-display/RegionMap/RegionMap.d.ts +4 -1
- package/dist/types/components/data-display/RegionMap/RegionMap.d.ts.map +1 -1
- package/dist/types/components/data-display/RegionMap/RegionMap.hooks.d.ts +4 -2
- package/dist/types/components/data-display/RegionMap/RegionMap.hooks.d.ts.map +1 -1
- package/dist/types/components/data-display/RegionMap/RegionMap.types.d.ts +40 -0
- package/dist/types/components/data-display/RegionMap/RegionMap.types.d.ts.map +1 -1
- package/dist/types/components/data-display/RegionMap/RegionMap.view.d.ts +36 -0
- package/dist/types/components/data-display/RegionMap/RegionMap.view.d.ts.map +1 -0
- package/dist/types/components/data-display/RegionMap/RegionMapDrawing.d.ts +4 -1
- package/dist/types/components/data-display/RegionMap/RegionMapDrawing.d.ts.map +1 -1
- package/dist/types/components/data-display/RegionMap/index.d.ts +3 -2
- package/dist/types/components/data-display/RegionMap/index.d.ts.map +1 -1
- package/dist/types/components/data-display/ScheduleGrid/ScheduleGrid.parts.d.ts +3 -1
- package/dist/types/components/data-display/ScheduleGrid/ScheduleGrid.parts.d.ts.map +1 -1
- package/dist/types/components/data-display/ScheduleGrid/ScheduleGrid.types.d.ts +12 -0
- package/dist/types/components/data-display/ScheduleGrid/ScheduleGrid.types.d.ts.map +1 -1
- package/dist/types/components/data-display/ScheduleGrid/schedule-header-host.styles.d.ts +16 -0
- package/dist/types/components/data-display/ScheduleGrid/schedule-header-host.styles.d.ts.map +1 -0
- package/dist/user-avatar.js +3 -3
- package/package.json +1 -1
- package/src/components/data-display/DayRuler/DayRuler.en-US.ts +1 -0
- package/src/components/data-display/DayRuler/DayRuler.labels.ts +2 -0
- package/src/components/data-display/DayRuler/DayRuler.md +3 -2
- package/src/components/data-display/DayRuler/DayRuler.parts.tsx +120 -1
- package/src/components/data-display/DayRuler/DayRuler.pt-BR.ts +1 -0
- package/src/components/data-display/DayRuler/DayRuler.styles.ts +50 -1
- package/src/components/data-display/DayRuler/DayRuler.tsx +10 -1
- package/src/components/data-display/DayRuler/DayRuler.types.ts +30 -1
- package/src/components/data-display/DayRuler/index.ts +2 -0
- package/src/components/data-display/RegionMap/RegionMap.hooks.ts +24 -33
- package/src/components/data-display/RegionMap/RegionMap.md +27 -0
- package/src/components/data-display/RegionMap/RegionMap.tsx +7 -1
- package/src/components/data-display/RegionMap/RegionMap.types.ts +41 -0
- package/src/components/data-display/RegionMap/RegionMap.view.ts +105 -0
- package/src/components/data-display/RegionMap/RegionMapDrawing.tsx +11 -0
- package/src/components/data-display/RegionMap/index.ts +5 -1
- package/src/components/data-display/RegionMap/tests.md +10 -2
- package/src/components/data-display/ScheduleGrid/ScheduleGrid.md +3 -2
- package/src/components/data-display/ScheduleGrid/ScheduleGrid.parts.tsx +18 -3
- package/src/components/data-display/ScheduleGrid/ScheduleGrid.tsx +1 -1
- package/src/components/data-display/ScheduleGrid/ScheduleGrid.types.ts +12 -0
- package/src/components/data-display/ScheduleGrid/schedule-header-host.styles.ts +35 -0
- package/dist/chunk-ACFKPE2T.js +0 -1
- package/dist/chunk-ACM3HHZY.js.map +0 -1
- package/dist/chunk-AKE6KVQG.js.map +0 -1
- package/dist/chunk-G2PVUPE7.js.map +0 -1
- package/dist/chunk-GMRQPNG3.js.map +0 -1
- package/dist/chunk-HMEGQKNQ.js.map +0 -1
- package/dist/chunk-MX2RF34M.js.map +0 -1
- package/dist/chunk-WNNA6YYE.js.map +0 -1
- /package/dist/{chunk-ACFKPE2T.js.map → _internal/components/data-display/RegionMap/RegionMap.view.js.map} +0 -0
- /package/dist/{chunk-FI2CQOGC.js.map → chunk-3OHZAZEE.js.map} +0 -0
- /package/dist/{chunk-CJ6XXM4X.js.map → chunk-3PQL2EN5.js.map} +0 -0
- /package/dist/{chunk-7YJYIMWP.js.map → chunk-4QR7LM5F.js.map} +0 -0
- /package/dist/{chunk-HI7JPDD6.js.map → chunk-5357QUVE.js.map} +0 -0
- /package/dist/{chunk-BP3ZKIPE.js.map → chunk-64UNVW6D.js.map} +0 -0
- /package/dist/{chunk-SCXVTNLE.js.map → chunk-66VKX6JE.js.map} +0 -0
- /package/dist/{chunk-N5PVD4J5.js.map → chunk-6DO672AG.js.map} +0 -0
- /package/dist/{chunk-NK6O4NE4.js.map → chunk-AI7XWBNG.js.map} +0 -0
- /package/dist/{chunk-SNWCT6JN.js.map → chunk-AMIUZRDQ.js.map} +0 -0
- /package/dist/{chunk-BMTIBQQC.js.map → chunk-BBBHPK2Q.js.map} +0 -0
- /package/dist/{chunk-A3DDEKLV.js.map → chunk-BOADHYTA.js.map} +0 -0
- /package/dist/{chunk-KRBPWTXW.js.map → chunk-CKQOYPH3.js.map} +0 -0
- /package/dist/{chunk-EUR2ORTN.js.map → chunk-CSJ7WNXU.js.map} +0 -0
- /package/dist/{chunk-QADTI63U.js.map → chunk-CZVAVX5L.js.map} +0 -0
- /package/dist/{chunk-DVX4HDNP.js.map → chunk-DBPFKGXX.js.map} +0 -0
- /package/dist/{chunk-XCUHGPPZ.js.map → chunk-DTZOP4ZR.js.map} +0 -0
- /package/dist/{chunk-BLZDSCIZ.js.map → chunk-DYHOBKPU.js.map} +0 -0
- /package/dist/{chunk-QKOJ4637.js.map → chunk-E6K2UZGR.js.map} +0 -0
- /package/dist/{chunk-2M3W6ACW.js.map → chunk-FAUNQ3FS.js.map} +0 -0
- /package/dist/{chunk-VIMMEADQ.js.map → chunk-FORAVDJF.js.map} +0 -0
- /package/dist/{chunk-PJNIJIE6.js.map → chunk-FQNDJITD.js.map} +0 -0
- /package/dist/{chunk-COKPPU42.js.map → chunk-FWTVIRZZ.js.map} +0 -0
- /package/dist/{chunk-JHWEL4NX.js.map → chunk-HS662RLW.js.map} +0 -0
- /package/dist/{chunk-BZBLPXV7.js.map → chunk-IWSTMVCA.js.map} +0 -0
- /package/dist/{chunk-TZC6KIK2.js.map → chunk-JG733RMP.js.map} +0 -0
- /package/dist/{chunk-K3PMMW23.js.map → chunk-K6VEN5VN.js.map} +0 -0
- /package/dist/{chunk-UKUGSU3Y.js.map → chunk-L4V7FZJI.js.map} +0 -0
- /package/dist/{chunk-24HHUCWB.js.map → chunk-LDCZPZPD.js.map} +0 -0
- /package/dist/{chunk-ILJ3FXIC.js.map → chunk-MM3QESLI.js.map} +0 -0
- /package/dist/{chunk-EEO7M5GU.js.map → chunk-MYTV353T.js.map} +0 -0
- /package/dist/{chunk-3HZKUN5J.js.map → chunk-MZAYIG2I.js.map} +0 -0
- /package/dist/{chunk-RDCIST7P.js.map → chunk-OCT5VCLP.js.map} +0 -0
- /package/dist/{chunk-F7LBTMCA.js.map → chunk-P53ANKZV.js.map} +0 -0
- /package/dist/{chunk-QVDEGBME.js.map → chunk-PEAUGQKU.js.map} +0 -0
- /package/dist/{chunk-BV2LOTMC.js.map → chunk-Q3SILZTQ.js.map} +0 -0
- /package/dist/{chunk-DSBC6O46.js.map → chunk-R4LCPPKA.js.map} +0 -0
- /package/dist/{chunk-ZH6NYB6Y.js.map → chunk-S2VZUBM7.js.map} +0 -0
- /package/dist/{chunk-JFD742C3.js.map → chunk-TMINUTQQ.js.map} +0 -0
- /package/dist/{chunk-SK2CTB3O.js.map → chunk-U2SAW6DH.js.map} +0 -0
- /package/dist/{chunk-DAHSKQBV.js.map → chunk-UMOHHWXY.js.map} +0 -0
- /package/dist/{chunk-QAEO52Z4.js.map → chunk-VHE7UEG5.js.map} +0 -0
- /package/dist/{chunk-TIM4PXWN.js.map → chunk-VWRXSBT2.js.map} +0 -0
- /package/dist/{chunk-KANCE4MS.js.map → chunk-W2KOP27S.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-3OTGREQG.js.map → chunk-X3GD3TFI.js.map} +0 -0
- /package/dist/{chunk-3X2MA47R.js.map → chunk-XNAI7QGU.js.map} +0 -0
- /package/dist/{chunk-L6JAALMX.js.map → chunk-XRV4QFEQ.js.map} +0 -0
- /package/dist/{chunk-WH3LUOCQ.js.map → chunk-YE7M7URT.js.map} +0 -0
- /package/dist/{chunk-WWR6APJR.js.map → chunk-YVDNCV2D.js.map} +0 -0
- /package/dist/{chunk-LOLYBFYY.js.map → chunk-ZCNR4DN5.js.map} +0 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { SxProps, Theme } from '@mui/material/styles/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* The header row's host figures (FUT-3882): a day's adornment under its label
|
|
4
|
+
* and the corner above the names. Their own module to keep the grid's styles
|
|
5
|
+
* under the file-size budget.
|
|
6
|
+
*/
|
|
7
|
+
/** A day's adornment: under its label, the column's full width, in the secondary ink unless the host says otherwise. */
|
|
8
|
+
export declare const headerAdornmentSx: SxProps<Theme>;
|
|
9
|
+
/**
|
|
10
|
+
* The cell above the names. It is the pinned mask over the names column (the
|
|
11
|
+
* grid's sticky rule): it must stay a stretched grid item, the header row's
|
|
12
|
+
* full height, or a day scrolled sideways shows above the names. Its words sit
|
|
13
|
+
* inside it on the days' label line (the prototype's "Movimento, 11h–23h").
|
|
14
|
+
*/
|
|
15
|
+
export declare const cornerSx: SxProps<Theme>;
|
|
16
|
+
//# sourceMappingURL=schedule-header-host.styles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schedule-header-host.styles.d.ts","sourceRoot":"","sources":["../../../../../src/components/data-display/ScheduleGrid/schedule-header-host.styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AAKpE;;;;GAIG;AAEH,wHAAwH;AACxH,eAAO,MAAM,iBAAiB,EAAE,OAAO,CAAC,KAAK,CAK5C,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,QAAQ,EAAE,OAAO,CAAC,KAAK,CASnC,CAAC"}
|
package/dist/user-avatar.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
UserAvatar,
|
|
3
3
|
UserMenu
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-Q3SILZTQ.js";
|
|
5
5
|
import "./chunk-DQ22UKMZ.js";
|
|
6
6
|
import "./chunk-UDQSIRAP.js";
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-3ZVUNSFF.js";
|
|
7
|
+
import "./chunk-4QR7LM5F.js";
|
|
9
8
|
import "./chunk-EOQ6EKTS.js";
|
|
10
9
|
import "./chunk-6ZZGK5DT.js";
|
|
10
|
+
import "./chunk-3ZVUNSFF.js";
|
|
11
11
|
import "./chunk-MTEQEPNY.js";
|
|
12
12
|
import "./chunk-VUHLNYAE.js";
|
|
13
13
|
import "./chunk-2GSIEDGN.js";
|
package/package.json
CHANGED
|
@@ -47,6 +47,7 @@ Times are **hours from the day's midnight**, fractions included: `20.75` is 20:4
|
|
|
47
47
|
| `now` | `number?` | The "agora" line, when on the ruler. |
|
|
48
48
|
| `coverage` | `number[]?` | People per hour, index 0 = `from…from+1`. |
|
|
49
49
|
| `coverageLabel` | `string?` | Beside the counts ("Na escala, por hora"). |
|
|
50
|
+
| `groupFooter` | `(group) => DayRulerFooterRow[]?` | Lines under a group's rows, on the tracks' columns (FUT-3882), for the group titled `group` (`undefined` for rows with no group). A row is `{ id, label, cells }` — one `{ text, marked?, title? }` per hour from `from`, a `marked` hour drawn in the warning ink (deepened to read at 4.5:1 on the page) inside a `warning.main` outline ("O movimento pede", an hour short of people). A marked hour's `title` is also said as visually hidden text; without one, it reads "20:00 · 2 · " + `labels.footerMarked`. An unmarked hour's default title is "20:00 · 2", or just the hour when it says nothing — or `{ id, label, trend }`, one value (or `null`) per hour drawn as a line in the primary colour, the highest near the top ("Média de pedidos/hora"; the drawing is `aria-hidden` and its figures are said as visually hidden text, "11:00 4 · 12:00 6"). A row `{ id, label, note, marked? }` says a sentence across the track instead ("Pouco histórico: menos de 4 semanas com pedidos na cozinha."); `marked` draws it in the readable warning ink behind a warning bar (a shape, not colour alone) and flags it `data-marked` ("Faltam 2, 20h–22h"). Not drawn in a phone-sized pane, like the coverage row. Called for every group on each render: keep it cheap (derive the rows once, outside, and look them up). A host drawing these usually leaves out `coverage`: the same counts would show twice. |
|
|
50
51
|
| `tickHours` | `number` (default 4) | An axis label every this many hours (HH:MM). |
|
|
51
52
|
| `snapMinutes` | `number` (default 15) | |
|
|
52
53
|
| `createHours` | `number` (default 4) | What a click alone creates. |
|
|
@@ -55,8 +56,8 @@ Times are **hours from the day's midnight**, fractions included: `20.75` is 20:4
|
|
|
55
56
|
| `onCreate` / `onMove` / `onResize` / `onBlockClick` | see Gestures | Each is offered only when its handler is given. |
|
|
56
57
|
| `loading` / `error` / `empty` | `boolean` / node / node | Skeleton rows with `aria-busy`; the host's error; the host's empty sentence. |
|
|
57
58
|
| `aria-label` | `string?` | The region's name. |
|
|
58
|
-
| `labels` | `Partial<DayRulerLabels>` | `createTrack(row)`, `moved(block, range)`, `resized(block, range)`, `refused`, `loading`. Default: the English pack; pt-BR: `DAY_RULER_LABELS['pt-BR']` from `@12-apps/ui/data-display/DayRuler`. |
|
|
59
|
-
| `dataTestId` | `string?` (default `day-ruler`) | Parts: `-coverage`, `-axis`, `-row-${rowId}`, `-track-${rowId}`, `-block-${blockId}`, `-handle-l/-r-${blockId}`, `-break-${blockId}`, `-actual-${rowId}`, `-now`, `-preview`, `-live`, `-loading`. |
|
|
59
|
+
| `labels` | `Partial<DayRulerLabels>` | `createTrack(row)`, `moved(block, range)`, `resized(block, range)`, `refused`, `loading`, `footerMarked`. Default: the English pack; pt-BR: `DAY_RULER_LABELS['pt-BR']` from `@12-apps/ui/data-display/DayRuler`. |
|
|
60
|
+
| `dataTestId` | `string?` (default `day-ruler`) | Parts: `-coverage`, `-axis`, `-footer-${footerRowId}`, `-row-${rowId}`, `-track-${rowId}`, `-block-${blockId}`, `-handle-l/-r-${blockId}`, `-break-${blockId}`, `-actual-${rowId}`, `-now`, `-preview`, `-live`, `-loading`. |
|
|
60
61
|
|
|
61
62
|
Tones are `ScheduleGrid`'s; on the ruler a `plan` block is a dashed outline over a faint ground.
|
|
62
63
|
|
|
@@ -7,6 +7,7 @@ import type { RulerAbilities, RulerScale } from './DayRuler.keyboard';
|
|
|
7
7
|
import { DAY_RULER_METRICS as M } from './DayRuler.metrics';
|
|
8
8
|
import { useTextFits } from './useTextFits';
|
|
9
9
|
import { formatHour, formatRange, percentOf, ticksOf } from './day-ruler-model';
|
|
10
|
+
import { SR_ONLY_SX } from '../ScheduleGrid/ScheduleGrid.styles';
|
|
10
11
|
import {
|
|
11
12
|
actionsSx,
|
|
12
13
|
actualLabelSx,
|
|
@@ -17,15 +18,18 @@ import {
|
|
|
17
18
|
coverageCellSx,
|
|
18
19
|
coverageLabelSx,
|
|
19
20
|
coverageSx,
|
|
21
|
+
footerCellSx,
|
|
22
|
+
footerNoteSx,
|
|
20
23
|
handleSx,
|
|
21
24
|
lineSx,
|
|
22
25
|
nowSx,
|
|
23
26
|
rowSx,
|
|
24
27
|
trackSx,
|
|
28
|
+
trendSx,
|
|
25
29
|
whoSx,
|
|
26
30
|
type Span,
|
|
27
31
|
} from './DayRuler.styles';
|
|
28
|
-
import type { DayRulerBlock, DayRulerRow, RulerHour } from './DayRuler.types';
|
|
32
|
+
import type { DayRulerBlock, DayRulerFooterCell, DayRulerFooterRow, DayRulerRow, RulerHour } from './DayRuler.types';
|
|
29
33
|
import type { RulerDrag, RulerDragApi } from './useRulerDrag';
|
|
30
34
|
|
|
31
35
|
export const spanOf = (start: RulerHour, end: RulerHour, scale: RulerScale): Span => {
|
|
@@ -254,6 +258,121 @@ export function Coverage(props: { coverage: readonly number[]; label?: string; s
|
|
|
254
258
|
);
|
|
255
259
|
}
|
|
256
260
|
|
|
261
|
+
/** The points of a trend over the hours' centres, in a 100 × 40 box: the highest value near the top, `null` breaks nothing (it is skipped). */
|
|
262
|
+
export function trendPoints(values: readonly (number | null)[], hours: number): string {
|
|
263
|
+
const present = values.slice(0, hours).filter((value): value is number => value !== null);
|
|
264
|
+
const max = Math.max(0, ...present);
|
|
265
|
+
return values
|
|
266
|
+
.slice(0, hours)
|
|
267
|
+
.flatMap((value, index) => {
|
|
268
|
+
if (value === null) return [];
|
|
269
|
+
const x = ((index + 0.5) * 100) / hours;
|
|
270
|
+
const y = max > 0 ? 38 - (value / max) * 34 : 38;
|
|
271
|
+
return [`${x.toFixed(2)},${y.toFixed(2)}`];
|
|
272
|
+
})
|
|
273
|
+
.join(' ');
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/** One hour's default words: "20:00 · 4"; just the hour when it says nothing. */
|
|
277
|
+
const hourWords = (hour: RulerHour, text: string): string => (text ? `${formatHour(hour)} · ${text}` : formatHour(hour));
|
|
278
|
+
|
|
279
|
+
/** What a reader hears for a marked hour: the host's `title`, else the hour, its count and that it is short. */
|
|
280
|
+
function markedWords(cell: DayRulerFooterCell, hour: RulerHour, marked: string): string {
|
|
281
|
+
return cell.title ?? `${hourWords(hour, cell.text)} · ${marked}`;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
interface FooterContext {
|
|
285
|
+
hours: number;
|
|
286
|
+
from: RulerHour;
|
|
287
|
+
/** `labels.footerMarked`. */
|
|
288
|
+
marked: string;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function FooterCells({ cells, ctx }: { cells: readonly DayRulerFooterCell[]; ctx: FooterContext }): React.JSX.Element {
|
|
292
|
+
return (
|
|
293
|
+
<Box sx={coverageSx(ctx.hours)}>
|
|
294
|
+
{Array.from({ length: ctx.hours }, (_, index) => {
|
|
295
|
+
const cell = cells[index] ?? { text: '' };
|
|
296
|
+
const hour = ctx.from + index;
|
|
297
|
+
return (
|
|
298
|
+
<Box
|
|
299
|
+
key={index}
|
|
300
|
+
component="span"
|
|
301
|
+
sx={footerCellSx(Boolean(cell.marked))}
|
|
302
|
+
title={cell.marked ? markedWords(cell, hour, ctx.marked) : (cell.title ?? hourWords(hour, cell.text))}
|
|
303
|
+
data-marked={cell.marked ? '' : undefined}
|
|
304
|
+
>
|
|
305
|
+
{/* A marked hour is said in words too, not only by its outline and a tooltip touch never shows. */}
|
|
306
|
+
{cell.marked ? (
|
|
307
|
+
<>
|
|
308
|
+
<span aria-hidden>{cell.text}</span>
|
|
309
|
+
<Box component="span" sx={SR_ONLY_SX}>
|
|
310
|
+
{markedWords(cell, hour, ctx.marked)}
|
|
311
|
+
</Box>
|
|
312
|
+
</>
|
|
313
|
+
) : (
|
|
314
|
+
cell.text
|
|
315
|
+
)}
|
|
316
|
+
</Box>
|
|
317
|
+
);
|
|
318
|
+
})}
|
|
319
|
+
</Box>
|
|
320
|
+
);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/** A trend's figures in words, for the reader the drawn line does not reach: "11:00 4 · 12:00 6". */
|
|
324
|
+
function trendWords(values: readonly (number | null)[], ctx: FooterContext): string {
|
|
325
|
+
return values
|
|
326
|
+
.slice(0, ctx.hours)
|
|
327
|
+
.flatMap((value, index) => (value === null ? [] : [`${formatHour(ctx.from + index)} ${Math.round(value * 10) / 10}`]))
|
|
328
|
+
.join(' · ');
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function FooterFigures({ row, ctx }: { row: DayRulerFooterRow; ctx: FooterContext }): React.JSX.Element {
|
|
332
|
+
if (row.trend) {
|
|
333
|
+
return (
|
|
334
|
+
<Box component="span" sx={{ display: 'block', minWidth: 0 }}>
|
|
335
|
+
<Box component="svg" viewBox="0 0 100 40" preserveAspectRatio="none" sx={trendSx} aria-hidden>
|
|
336
|
+
<polyline fill="none" stroke="currentColor" strokeWidth={1.5} vectorEffect="non-scaling-stroke" points={trendPoints(row.trend, ctx.hours)} />
|
|
337
|
+
</Box>
|
|
338
|
+
<Box component="span" sx={SR_ONLY_SX}>
|
|
339
|
+
{trendWords(row.trend, ctx)}
|
|
340
|
+
</Box>
|
|
341
|
+
</Box>
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
if (row.note !== undefined) {
|
|
345
|
+
return (
|
|
346
|
+
<Box component="span" sx={footerNoteSx(Boolean(row.marked))} data-marked={row.marked ? '' : undefined}>
|
|
347
|
+
{row.note}
|
|
348
|
+
</Box>
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
return <FooterCells cells={row.cells ?? []} ctx={ctx} />;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* A group's lines under its rows (FUT-3882): counts per hour, a trend, or a
|
|
356
|
+
* sentence, on the tracks' columns. `marked` is `labels.footerMarked`.
|
|
357
|
+
*/
|
|
358
|
+
export function GroupFooter(props: { rows: readonly DayRulerFooterRow[]; scale: RulerScale; testId: string; marked: string }): React.JSX.Element {
|
|
359
|
+
const { rows, scale, testId } = props;
|
|
360
|
+
const ctx: FooterContext = { hours: scale.to - scale.from, from: scale.from, marked: props.marked };
|
|
361
|
+
return (
|
|
362
|
+
<>
|
|
363
|
+
{rows.map((row) => (
|
|
364
|
+
<Box key={row.id} sx={lineSx} data-testid={`${testId}-footer-${row.id}`}>
|
|
365
|
+
<Box component="span" sx={coverageLabelSx}>
|
|
366
|
+
{row.label}
|
|
367
|
+
</Box>
|
|
368
|
+
<FooterFigures row={row} ctx={ctx} />
|
|
369
|
+
<span />
|
|
370
|
+
</Box>
|
|
371
|
+
))}
|
|
372
|
+
</>
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
|
|
257
376
|
/** The hour labels under the coverage row. */
|
|
258
377
|
export function Axis({ scale, testId }: { scale: RulerScale; testId: string }): React.JSX.Element {
|
|
259
378
|
return (
|
|
@@ -2,7 +2,7 @@ import { alpha, type CSSObject, type SxProps, type Theme } from '@mui/material/s
|
|
|
2
2
|
|
|
3
3
|
import { FIELD_BORDER_WIDTH } from '../../../tokens/field-height.core';
|
|
4
4
|
import { rem, sxRem } from '../../../tokens/relative';
|
|
5
|
-
import { actualBarColor, blockToneStyles, breakHatch } from '../ScheduleGrid/schedule-tones';
|
|
5
|
+
import { actualBarColor, blockToneStyles, breakHatch, signalInk } from '../ScheduleGrid/schedule-tones';
|
|
6
6
|
import type { ScheduleBlockTone } from '../ScheduleGrid/ScheduleGrid.types';
|
|
7
7
|
import { DAY_RULER_METRICS as M } from './DayRuler.metrics';
|
|
8
8
|
|
|
@@ -301,3 +301,52 @@ export const skeletonNameSx: SxProps<Theme> = (theme: Theme) => ({
|
|
|
301
301
|
borderRadius: rem(theme, M.skeletonNameRadius),
|
|
302
302
|
backgroundColor: theme.palette.action.hover,
|
|
303
303
|
});
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* A marked footer's words (FUT-3882): the warning ink deepened until it reads
|
|
307
|
+
* at 4.5:1 on the page — `warning.main` is 3.1:1 on white. The outline keeps
|
|
308
|
+
* `warning.main`: a non-text mark needs 3:1.
|
|
309
|
+
*/
|
|
310
|
+
export function footerInk(theme: Theme, marked: boolean, plain: string): string {
|
|
311
|
+
return marked ? signalInk(theme, 'warning', theme.palette.background.default) : plain;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
/** A group's count line (FUT-3882): plain counts on the hours' columns, a marked hour outlined in the warning ink. */
|
|
315
|
+
export function footerCellSx(marked: boolean): SxProps<Theme> {
|
|
316
|
+
return (theme: Theme) => ({
|
|
317
|
+
display: 'flex',
|
|
318
|
+
alignItems: 'center',
|
|
319
|
+
justifyContent: 'center',
|
|
320
|
+
fontSize: rem(theme, M.coverage.font),
|
|
321
|
+
borderRadius: rem(theme, M.coverage.radius),
|
|
322
|
+
color: footerInk(theme, marked, theme.palette.text.primary),
|
|
323
|
+
fontWeight: marked ? 500 : 400,
|
|
324
|
+
// The hairline is always there, transparent when unmarked, so a mark never shifts a count.
|
|
325
|
+
border: `1px solid ${marked ? theme.palette.warning.main : 'transparent'}`,
|
|
326
|
+
minWidth: 0,
|
|
327
|
+
overflow: 'hidden',
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/**
|
|
332
|
+
* A footer line's sentence; when the host marks it ("Faltam 2, 20h–22h"), in
|
|
333
|
+
* the readable warning ink with a warning bar before it — a shape, so colour
|
|
334
|
+
* is never the only signal.
|
|
335
|
+
*/
|
|
336
|
+
export function footerNoteSx(marked: boolean): SxProps<Theme> {
|
|
337
|
+
return (theme: Theme) => ({
|
|
338
|
+
fontSize: rem(theme, M.meta),
|
|
339
|
+
color: footerInk(theme, marked, theme.palette.text.secondary),
|
|
340
|
+
fontWeight: marked ? 500 : 400,
|
|
341
|
+
...(marked ? { borderLeft: `${rem(theme, 3)} solid ${theme.palette.warning.main}`, paddingLeft: rem(theme, 6) } : {}),
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/** A group's trend line: as tall as the coverage row, drawn in the primary colour. */
|
|
346
|
+
export const trendSx: SxProps<Theme> = (theme: Theme) => ({
|
|
347
|
+
display: 'block',
|
|
348
|
+
width: '100%',
|
|
349
|
+
height: rem(theme, M.coverage.height + M.coverage.height / 2),
|
|
350
|
+
color: theme.palette.primary.main,
|
|
351
|
+
overflow: 'visible',
|
|
352
|
+
});
|
|
@@ -9,7 +9,7 @@ import { useAnnouncer } from '../ScheduleGrid/useAnnouncer';
|
|
|
9
9
|
import { handleBlockKey, keyCreateSpan, type RulerAbilities, type RulerScale } from './DayRuler.keyboard';
|
|
10
10
|
import { EN_US_DAY_RULER_LABELS } from './DayRuler.en-US';
|
|
11
11
|
import { DAY_RULER_METRICS as M } from './DayRuler.metrics';
|
|
12
|
-
import { Axis, Coverage, RulerRow, type RowContext } from './DayRuler.parts';
|
|
12
|
+
import { Axis, Coverage, GroupFooter, RulerRow, type RowContext } from './DayRuler.parts';
|
|
13
13
|
import { groupTitleSx, rootSx, rowSx, skeletonNameSx, skeletonTrackSx } from './DayRuler.styles';
|
|
14
14
|
import type { DayRulerProps, DayRulerRow } from './DayRuler.types';
|
|
15
15
|
import { useRulerDrag } from './useRulerDrag';
|
|
@@ -40,6 +40,14 @@ function abilitiesOf(props: DayRulerProps): RulerAbilities {
|
|
|
40
40
|
return { create: open && Boolean(props.onCreate), move: open && Boolean(props.onMove), resize: open && Boolean(props.onResize) };
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
+
/** A group's lines under its rows, when the host gives any (`groupFooter`). */
|
|
44
|
+
function FooterOf({ props, group, ctx }: { props: DayRulerProps; group: string | undefined; ctx: RowContext }): React.JSX.Element | null {
|
|
45
|
+
const rows = props.groupFooter?.(group);
|
|
46
|
+
if (!rows || rows.length === 0) return null;
|
|
47
|
+
const marked = props.labels?.footerMarked ?? EN_US_DAY_RULER_LABELS.footerMarked;
|
|
48
|
+
return <GroupFooter rows={rows} scale={ctx.scale} testId={ctx.testId} marked={marked} />;
|
|
49
|
+
}
|
|
50
|
+
|
|
43
51
|
/** The groups and their rows — or the skeleton, the host's error, or the host's empty state. */
|
|
44
52
|
function RulerBody({ props, ctx }: { props: DayRulerProps; ctx: RowContext }): React.JSX.Element {
|
|
45
53
|
if (props.error) return <>{props.error}</>;
|
|
@@ -68,6 +76,7 @@ function RulerBody({ props, ctx }: { props: DayRulerProps; ctx: RowContext }): R
|
|
|
68
76
|
{group.rows.map((row) => (
|
|
69
77
|
<RulerRow key={row.id} row={row} ctx={ctx} />
|
|
70
78
|
))}
|
|
79
|
+
<FooterOf props={props} group={group.title} ctx={ctx} />
|
|
71
80
|
</Box>
|
|
72
81
|
))}
|
|
73
82
|
</>
|
|
@@ -66,6 +66,29 @@ export interface DayRulerRow {
|
|
|
66
66
|
labelAccessible?: string;
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
/** One hour of a group's count line: what it says, and whether the host marks it (an hour short of people). */
|
|
70
|
+
export interface DayRulerFooterCell {
|
|
71
|
+
/** What the hour says ("4", "—"). Empty draws nothing. */
|
|
72
|
+
text: string;
|
|
73
|
+
/** Drawn in the warning ink inside a warning outline. Never the only signal: say it in `title` too. */
|
|
74
|
+
marked?: boolean;
|
|
75
|
+
/** The hour's tooltip and accessible words ("20h · o movimento pede 4, a escala tem 2"). Default: the hour and `text`. */
|
|
76
|
+
title?: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* A line under a group's rows, on the tracks' columns (FUT-3882): one count
|
|
81
|
+
* per hour (`cells`, index 0 = `from…from+1`) — "Na escala, por hora",
|
|
82
|
+
* "O movimento pede" —, a trend drawn as a line (`trend`, one value per hour,
|
|
83
|
+
* `null` for none) — "Média de pedidos/hora" —, or a sentence across the
|
|
84
|
+
* track where the figures would be (`note`) — "Pouco histórico: …", or,
|
|
85
|
+
* `marked`, in the warning ink: "Faltam 2, 20h–22h".
|
|
86
|
+
*/
|
|
87
|
+
export type DayRulerFooterRow =
|
|
88
|
+
| { id: string; label: string; cells: readonly DayRulerFooterCell[]; trend?: undefined; note?: undefined }
|
|
89
|
+
| { id: string; label: string; trend: readonly (number | null)[]; cells?: undefined; note?: undefined }
|
|
90
|
+
| { id: string; label: string; note: string; marked?: boolean; cells?: undefined; trend?: undefined };
|
|
91
|
+
|
|
69
92
|
export interface DayRulerProps {
|
|
70
93
|
rows: readonly DayRulerRow[];
|
|
71
94
|
/** The ruler's first hour (default 6, 06:00). */
|
|
@@ -78,6 +101,12 @@ export interface DayRulerProps {
|
|
|
78
101
|
coverage?: readonly number[];
|
|
79
102
|
/** Beside the coverage row ("Na escala, por hora"). */
|
|
80
103
|
coverageLabel?: string;
|
|
104
|
+
/**
|
|
105
|
+
* Lines under a group's rows, on the tracks' columns, for the group titled
|
|
106
|
+
* `group` (`undefined` for rows with no group). Like the coverage row they
|
|
107
|
+
* are not drawn in a phone-sized pane, where the host says it its own way.
|
|
108
|
+
*/
|
|
109
|
+
groupFooter?: (group: string | undefined) => readonly DayRulerFooterRow[] | undefined;
|
|
81
110
|
/** An axis label every this many hours (default 4). */
|
|
82
111
|
tickHours?: number;
|
|
83
112
|
/** Every gesture snaps to this (default 15 minutes). */
|
|
@@ -99,7 +128,7 @@ export interface DayRulerProps {
|
|
|
99
128
|
/** The component's own words. Default: the English pack. */
|
|
100
129
|
labels?: Partial<DayRulerLabels>;
|
|
101
130
|
/**
|
|
102
|
-
* Base test id (default `day-ruler`). Parts: `-coverage`, `-axis`, `-row-${rowId}`,
|
|
131
|
+
* Base test id (default `day-ruler`). Parts: `-coverage`, `-axis`, `-footer-${footerRowId}`, `-row-${rowId}`,
|
|
103
132
|
* `-track-${rowId}`, `-block-${blockId}`, `-handle-l-${blockId}`, `-handle-r-${blockId}`, `-break-${blockId}`,
|
|
104
133
|
* `-actual-${rowId}`, `-now`, `-preview`, `-live`, `-loading`.
|
|
105
134
|
*/
|
|
@@ -6,16 +6,19 @@ import {
|
|
|
6
6
|
geometryCache,
|
|
7
7
|
hitRegion,
|
|
8
8
|
projectionAt,
|
|
9
|
-
viewBoxFor,
|
|
10
9
|
type DrawnRegion,
|
|
11
10
|
type PlaneBox,
|
|
11
|
+
type Projection,
|
|
12
12
|
} from './RegionMap.helpers';
|
|
13
|
-
import type { RegionMapProps
|
|
13
|
+
import type { RegionMapProps } from './RegionMap.types';
|
|
14
|
+
import { centreOf, reachBox, viewWithin } from './RegionMap.view';
|
|
14
15
|
|
|
15
16
|
/** What the drawing needs, derived from the props. */
|
|
16
17
|
export interface RegionMapModel {
|
|
17
18
|
/** The square shown, or null when there is nothing to centre on. */
|
|
18
19
|
view: PlaneBox | null;
|
|
20
|
+
/** The projection drawn with, or null when there is nothing to centre on. */
|
|
21
|
+
projection: Projection | null;
|
|
19
22
|
drawn: DrawnRegion[];
|
|
20
23
|
/** Radii drawn, in metres; empty without circles. */
|
|
21
24
|
radii: number[];
|
|
@@ -28,15 +31,6 @@ export interface RegionMapModel {
|
|
|
28
31
|
/** A tap reaches an area this close: a share of the view (~8 px on a phone). */
|
|
29
32
|
const TOLERANCE_SHARE = 1 / 45;
|
|
30
33
|
|
|
31
|
-
/** The middle of every area, for a map with no centre of its own. */
|
|
32
|
-
function centreOf(regions: readonly RegionMapRegion[]): { latitude: number; longitude: number } | null {
|
|
33
|
-
const points = regions.flatMap((r) => r.rings.flat());
|
|
34
|
-
const lats = extent(points.map(([lat]) => lat));
|
|
35
|
-
const lngs = extent(points.map(([, lng]) => lng));
|
|
36
|
-
if (lats === null || lngs === null) return null;
|
|
37
|
-
return { latitude: (lats.min + lats.max) / 2, longitude: (lngs.min + lngs.max) / 2 };
|
|
38
|
-
}
|
|
39
|
-
|
|
40
34
|
/** The click, in the drawing's own coordinates — or null where it cannot be read. */
|
|
41
35
|
function svgPoint(event: React.MouseEvent<SVGSVGElement>): { x: number; y: number } | null {
|
|
42
36
|
const svg = event.currentTarget;
|
|
@@ -46,16 +40,6 @@ function svgPoint(event: React.MouseEvent<SVGSVGElement>): { x: number; y: numbe
|
|
|
46
40
|
return { x: point.x, y: point.y };
|
|
47
41
|
}
|
|
48
42
|
|
|
49
|
-
/** The view: the outermost circle when there is one, else every area's box. */
|
|
50
|
-
function viewOf(outermostMetres: number | null, drawable: () => (PlaneBox | null)[]): PlaneBox | null {
|
|
51
|
-
if (outermostMetres !== null) return viewBoxFor(outermostMetres, null);
|
|
52
|
-
const boxes = drawable().filter((box): box is PlaneBox => box !== null);
|
|
53
|
-
const xs = extent(boxes.flatMap((b) => [b.minX, b.minX + b.spanX]));
|
|
54
|
-
const ys = extent(boxes.flatMap((b) => [b.minY, b.minY + b.spanY]));
|
|
55
|
-
if (xs === null || ys === null) return null;
|
|
56
|
-
return viewBoxFor(null, { minX: xs.min, minY: ys.min, spanX: xs.max - xs.min, spanY: ys.max - ys.min });
|
|
57
|
-
}
|
|
58
|
-
|
|
59
43
|
/** Which area a click or tap means — see `useRegionMap`. */
|
|
60
44
|
function tappedRegion(
|
|
61
45
|
event: React.MouseEvent<SVGSVGElement>,
|
|
@@ -74,16 +58,18 @@ function tappedRegion(
|
|
|
74
58
|
);
|
|
75
59
|
}
|
|
76
60
|
|
|
77
|
-
/** The geometry cache for a centre, or
|
|
78
|
-
function useGeometry(
|
|
79
|
-
|
|
80
|
-
|
|
61
|
+
/** The projection and geometry cache for a centre, or nulls without one. */
|
|
62
|
+
function useGeometry(origin: { latitude: number; longitude: number } | null): {
|
|
63
|
+
projection: Projection | null;
|
|
64
|
+
geometryOf: ReturnType<typeof geometryCache> | null;
|
|
65
|
+
} {
|
|
81
66
|
const lat = origin?.latitude ?? null;
|
|
82
67
|
const lng = origin?.longitude ?? null;
|
|
83
|
-
return React.useMemo(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
68
|
+
return React.useMemo(() => {
|
|
69
|
+
if (lat === null || lng === null) return { projection: null, geometryOf: null };
|
|
70
|
+
const projection = projectionAt({ latitude: lat, longitude: lng });
|
|
71
|
+
return { projection, geometryOf: geometryCache(projection) };
|
|
72
|
+
}, [lat, lng]);
|
|
87
73
|
}
|
|
88
74
|
|
|
89
75
|
/**
|
|
@@ -101,13 +87,18 @@ export function useRegionMap({
|
|
|
101
87
|
regions,
|
|
102
88
|
center,
|
|
103
89
|
circles = [],
|
|
90
|
+
reach,
|
|
104
91
|
onToggle,
|
|
105
|
-
}: Pick<RegionMapProps, 'regions' | 'center' | 'circles' | 'onToggle'>): RegionMapModel {
|
|
106
|
-
const geometryOf = useGeometry(center ?? centreOf(regions));
|
|
92
|
+
}: Pick<RegionMapProps, 'regions' | 'center' | 'circles' | 'reach' | 'onToggle'>): RegionMapModel {
|
|
93
|
+
const { projection, geometryOf } = useGeometry(center ?? centreOf(regions));
|
|
107
94
|
const radii = circles.map((c) => c.radiusMetres);
|
|
108
95
|
const outermostMetres = extent(radii)?.max ?? null;
|
|
109
96
|
const view =
|
|
110
|
-
|
|
97
|
+
projection === null || geometryOf === null
|
|
98
|
+
? null
|
|
99
|
+
: viewWithin(outermostMetres, reach === undefined ? null : reachBox(reach, projection), () =>
|
|
100
|
+
regions.map((r) => geometryOf(r.rings).bounds),
|
|
101
|
+
);
|
|
111
102
|
const drawn = geometryOf && view ? drawOrder(regions, geometryOf, view) : [];
|
|
112
103
|
const pointerType = React.useRef<string>('mouse');
|
|
113
104
|
|
|
@@ -121,5 +112,5 @@ export function useRegionMap({
|
|
|
121
112
|
if (hit) onToggle(hit);
|
|
122
113
|
};
|
|
123
114
|
|
|
124
|
-
return { view, drawn, radii, outermostMetres, onPointerDown, onClick };
|
|
115
|
+
return { view, projection, drawn, radii, outermostMetres, onPointerDown, onClick };
|
|
125
116
|
}
|
|
@@ -75,6 +75,27 @@ clipped at an edge — the map reads the same at 320 px and at 1600 px. The
|
|
|
75
75
|
drawing is square; `maxHeight` caps it on a wide screen, and where it sits in a
|
|
76
76
|
wider box is the host's call.
|
|
77
77
|
|
|
78
|
+
### A host can draw inside it, at its scale
|
|
79
|
+
|
|
80
|
+
A host often has something of its own to show over the areas — a band served
|
|
81
|
+
past the largest circle, a route, a marker — and laying a second SVG over the
|
|
82
|
+
drawing means copying its view math and losing its frame. So:
|
|
83
|
+
|
|
84
|
+
- `reach` (`{ radiusMetres }` or `{ bounds }`) is an extent the view must ALSO
|
|
85
|
+
fit, before the 12% margin. With circles the view stays centred on the centre
|
|
86
|
+
and grows to the reach's farthest edge, so a ring stays a circle in the
|
|
87
|
+
middle; without circles the view fits the areas and the reach together. A
|
|
88
|
+
reach no radius describes — the outlines of some areas — is a box:
|
|
89
|
+
`boundsOfRings(rings)`. Omit it and the view is exactly what it was.
|
|
90
|
+
- `overlay(layer)` draws inside the SVG with `layer.view` and
|
|
91
|
+
`layer.projection` (`projectionAt(center)`), over the excluded hatch and
|
|
92
|
+
under the circles, highlights and centre. It sits in a `pointer-events: none`
|
|
93
|
+
group, so a tap still reaches the area beneath.
|
|
94
|
+
- `regionMapView(props)` returns the same view for HTML laid over the drawing
|
|
95
|
+
(a pill on a circle, a note): a point `p` sits at `(p.x - view.minX) /
|
|
96
|
+
view.spanX` across; with circles the view is centred and its half-side is
|
|
97
|
+
`view.spanX / 2`.
|
|
98
|
+
|
|
78
99
|
## Props
|
|
79
100
|
|
|
80
101
|
| prop | type | default | what it does |
|
|
@@ -82,6 +103,8 @@ wider box is the host's call.
|
|
|
82
103
|
| `regions` | `readonly RegionMapRegion[]` | — | the areas; drawn when any part is in view |
|
|
83
104
|
| `center` | `{ latitude, longitude } \| null` | — | centre, dot and circles; `null` centres on the areas, no dot |
|
|
84
105
|
| `circles` | `readonly { radiusMetres }[]` | `[]` | dashed circles; the view fits the largest |
|
|
106
|
+
| `reach` | `{ radiusMetres } \| { bounds: { south, west, north, east } }` | — | an extent the view must also fit (margin on top) |
|
|
107
|
+
| `overlay` | `(layer: { view, projection }) => ReactNode` | — | a host layer inside the SVG, under the circles, tap-transparent |
|
|
85
108
|
| `onToggle` | `(id: string) => void` | — | a tap or a list press; omit for read-only |
|
|
86
109
|
| `highlightedIds` | `readonly string[]` | `[]` | areas to point at (a search's hits), outlined and named |
|
|
87
110
|
| `copy` | `RegionMapCopy` | — | every word |
|
|
@@ -117,6 +140,10 @@ wider box is the host's call.
|
|
|
117
140
|
`[latitude, longitude]` points; outlines usually travel this way.
|
|
118
141
|
- `hitRegion(regions, point, tolerance)` and `projectionAt(center)` — the hit
|
|
119
142
|
test and projection the component uses, for a host that draws its own layer.
|
|
143
|
+
- `regionMapView({ regions, center, circles, reach })` — the view the
|
|
144
|
+
component shows for those props, in projected metres, for HTML laid over it.
|
|
145
|
+
- `boundsOfRings(rings)` — the latitude/longitude box around some outlines,
|
|
146
|
+
for a `reach` no radius describes.
|
|
120
147
|
|
|
121
148
|
## Example
|
|
122
149
|
|
|
@@ -29,6 +29,9 @@ const NO_IDS: readonly string[] = [];
|
|
|
29
29
|
* is that path. A finger's tap takes the SMALLEST area within a few pixels'
|
|
30
30
|
* worth of metres (`hitRegion`), so a sliver beside a big area can be hit
|
|
31
31
|
* from the map; one too thin even for that is still on the list.
|
|
32
|
+
* - **The host can draw inside it.** `reach` widens the view past the largest
|
|
33
|
+
* circle and `overlay` draws a layer in the SVG at the map's own projection,
|
|
34
|
+
* tap-transparent; `regionMapView` gives the same view to HTML laid over it.
|
|
32
35
|
* - **A toggle is cheap.** Geometry is projected once per `rings` identity,
|
|
33
36
|
* and the base layer is memoised, so a tap re-renders the hatch and labels.
|
|
34
37
|
*/
|
|
@@ -36,6 +39,8 @@ export function RegionMap({
|
|
|
36
39
|
regions,
|
|
37
40
|
center,
|
|
38
41
|
circles,
|
|
42
|
+
reach,
|
|
43
|
+
overlay,
|
|
39
44
|
onToggle,
|
|
40
45
|
highlightedIds = NO_IDS,
|
|
41
46
|
copy,
|
|
@@ -46,7 +51,7 @@ export function RegionMap({
|
|
|
46
51
|
dataTestId = 'region-map',
|
|
47
52
|
}: RegionMapProps): React.JSX.Element | null {
|
|
48
53
|
const theme = useTheme();
|
|
49
|
-
const model = useRegionMap({ regions, center, circles, onToggle });
|
|
54
|
+
const model = useRegionMap({ regions, center, circles, reach, onToggle });
|
|
50
55
|
const { view } = model;
|
|
51
56
|
if (view === null && regions.length === 0) return null;
|
|
52
57
|
return (
|
|
@@ -55,6 +60,7 @@ export function RegionMap({
|
|
|
55
60
|
<>
|
|
56
61
|
<RegionMapDrawing
|
|
57
62
|
model={{ ...model, view }}
|
|
63
|
+
overlay={overlay}
|
|
58
64
|
showCenter={center !== null}
|
|
59
65
|
highlightedIds={highlightedIds}
|
|
60
66
|
maxHeight={maxHeight}
|
|
@@ -7,6 +7,10 @@
|
|
|
7
7
|
* every word arrives through `copy`.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
+
import type React from 'react';
|
|
11
|
+
|
|
12
|
+
import type { PlaneBox, Projection } from './RegionMap.helpers';
|
|
13
|
+
|
|
10
14
|
/** A latitude/longitude pair, in that order. */
|
|
11
15
|
export type RegionMapPoint = readonly [latitude: number, longitude: number];
|
|
12
16
|
|
|
@@ -50,6 +54,29 @@ export interface RegionMapCircle {
|
|
|
50
54
|
radiusMetres: number;
|
|
51
55
|
}
|
|
52
56
|
|
|
57
|
+
/** A latitude/longitude box, by its four edges in degrees. */
|
|
58
|
+
export interface RegionMapBounds {
|
|
59
|
+
south: number;
|
|
60
|
+
west: number;
|
|
61
|
+
north: number;
|
|
62
|
+
east: number;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* An extent the view must fit besides its circles: a radius around the centre,
|
|
67
|
+
* or a box — e.g. the bounds of some outlines (`boundsOfRings`), for a reach
|
|
68
|
+
* no single radius describes.
|
|
69
|
+
*/
|
|
70
|
+
export type RegionMapReach = { radiusMetres: number } | { bounds: RegionMapBounds };
|
|
71
|
+
|
|
72
|
+
/** What a host overlay is drawn with: the map's own view and projection. */
|
|
73
|
+
export interface RegionMapLayer {
|
|
74
|
+
/** The SVG viewBox, in projected metres. */
|
|
75
|
+
view: PlaneBox;
|
|
76
|
+
/** The projection the map draws with — `projectionAt(center)`. */
|
|
77
|
+
projection: Projection;
|
|
78
|
+
}
|
|
79
|
+
|
|
53
80
|
/** Every word the map prints or announces. */
|
|
54
81
|
export interface RegionMapCopy {
|
|
55
82
|
/** The drawing's accessible name (`role="img"`). */
|
|
@@ -95,6 +122,20 @@ export interface RegionMapProps {
|
|
|
95
122
|
center: { latitude: number; longitude: number } | null;
|
|
96
123
|
/** Circles around the centre; the view fits the largest. */
|
|
97
124
|
circles?: readonly RegionMapCircle[];
|
|
125
|
+
/**
|
|
126
|
+
* An extent the view must ALSO fit, before its margin — something the host
|
|
127
|
+
* draws past the largest circle. With circles the view stays centred on the
|
|
128
|
+
* centre and grows to the reach's farthest edge; without, it fits the areas
|
|
129
|
+
* and the reach together. Omit it and the view is the circles' (or areas').
|
|
130
|
+
*/
|
|
131
|
+
reach?: RegionMapReach;
|
|
132
|
+
/**
|
|
133
|
+
* A host layer drawn INSIDE the drawing's SVG, over the excluded hatch and
|
|
134
|
+
* under the circles, highlights and centre, so it shares the map's view,
|
|
135
|
+
* projection and frame. It is wrapped in `pointer-events: none`: taps go
|
|
136
|
+
* through it to the areas. Return SVG elements, in projected metres.
|
|
137
|
+
*/
|
|
138
|
+
overlay?: (layer: RegionMapLayer) => React.ReactNode;
|
|
98
139
|
/**
|
|
99
140
|
* A tap on an area, or a press of its list button. Omit it and the map is
|
|
100
141
|
* read-only: nothing is tappable and the list rows are not buttons.
|