@ahrowe/ui 0.41.2 → 0.43.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/CHANGELOG.md +934 -0
- package/README.md +11 -10
- package/dist/cjs-types/common/accordion/accordion.types.d.ts +17 -2
- package/dist/cjs-types/common/actionButtons/actionButtons.types.d.ts +7 -1
- package/dist/cjs-types/common/actionIcon/actionIcon.d.ts +1 -1
- package/dist/cjs-types/common/actionIcon/actionIcon.types.d.ts +7 -9
- package/dist/cjs-types/common/alert/alert.types.d.ts +6 -8
- package/dist/cjs-types/common/animatedLogo/animatedLogo.types.d.ts +3 -2
- package/dist/cjs-types/common/badge/badge.types.d.ts +10 -6
- package/dist/cjs-types/common/button/button.types.d.ts +14 -4
- package/dist/cjs-types/common/calendar/calendar.types.d.ts +25 -10
- package/dist/cjs-types/common/calendar/components/agendaList/agendaList.d.ts +1 -1
- package/dist/cjs-types/common/calendar/components/agendaList/agendaList.types.d.ts +3 -0
- package/dist/cjs-types/common/calendar/components/calendarHeader/calendarHeader.d.ts +1 -1
- package/dist/cjs-types/common/calendar/components/calendarHeader/calendarHeader.types.d.ts +2 -0
- package/dist/cjs-types/common/calendar/components/compactMonth/compactMonth.d.ts +1 -1
- package/dist/cjs-types/common/calendar/components/monthView/monthView.d.ts +1 -1
- package/dist/cjs-types/common/calendar/components/monthView/monthView.types.d.ts +3 -2
- package/dist/cjs-types/common/calendar/components/timeGrid/timeGrid.d.ts +1 -1
- package/dist/cjs-types/common/calendar/components/timeGrid/timeGrid.types.d.ts +9 -1
- package/dist/cjs-types/common/calendar/dates.d.ts +21 -5
- package/dist/cjs-types/common/calendar/format.d.ts +3 -2
- package/dist/cjs-types/common/calendar/layout.d.ts +5 -0
- package/dist/cjs-types/common/calendar/useNow.d.ts +4 -0
- package/dist/cjs-types/common/calendar/view.types.d.ts +9 -2
- package/dist/cjs-types/common/card/card.types.d.ts +16 -2
- package/dist/cjs-types/common/chip/chip.types.d.ts +10 -5
- package/dist/cjs-types/common/copyButton/copyButton.types.d.ts +5 -4
- package/dist/cjs-types/common/fab/components/fabBase/fabBase.d.ts +1 -1
- package/dist/cjs-types/common/fab/components/fabBase/fabBase.types.d.ts +2 -1
- package/dist/cjs-types/common/floorPlan/floorPlan.graph.d.ts +10 -3
- package/dist/cjs-types/common/floorPlan/floorPlan.plan.d.ts +5 -0
- package/dist/cjs-types/common/floorPlan/floorPlan.rooms.d.ts +6 -2
- package/dist/cjs-types/common/floorPlan/floorPlan.snap.d.ts +1 -3
- package/dist/cjs-types/common/floorPlan/index.d.ts +1 -3
- package/dist/cjs-types/common/planCanvas/planCanvas.types.d.ts +1 -1
- package/dist/cjs-types/common/progressBar/progressBar.d.ts +0 -1
- package/dist/cjs-types/common/progressBar/progressBar.types.d.ts +3 -1
- package/dist/cjs-types/common/roomDrawer/roomDrawer.types.d.ts +29 -8
- package/dist/cjs-types/common/roomViewer/roomViewer.types.d.ts +4 -2
- package/dist/cjs-types/common/splitButton/splitButton.types.d.ts +4 -1
- package/dist/cjs-types/common/styles/tone.d.ts +11 -0
- package/dist/cjs-types/common/themeProvider/color.types.d.ts +20 -0
- package/dist/cjs-types/common/themeProvider/index.d.ts +2 -0
- package/dist/cjs-types/common/themeProvider/theme.types.d.ts +3 -6
- package/dist/cjs-types/common/timeline/timeline.types.d.ts +3 -10
- package/dist/cjs-types/common/toast/index.d.ts +1 -1
- package/dist/cjs-types/common/toast/toast.types.d.ts +7 -3
- package/dist/cjs-types/common/types/actions.types.d.ts +1 -1
- package/dist/cjs-types/common/utils/dismissClick.d.ts +4 -0
- package/dist/cjs-types/common/utils/isDev.d.ts +1 -0
- package/dist/esm/common/accordion/accordion.mjs +1 -1
- package/dist/esm/common/accordion/accordion.mjs.map +1 -1
- package/dist/esm/common/accordion/accordion.module.mjs +1 -1
- package/dist/esm/common/accordion/accordion.module.mjs.map +1 -1
- package/dist/esm/common/accordion/accordion.types.mjs +1 -1
- package/dist/esm/common/accordion/accordion.types.mjs.map +1 -1
- package/dist/esm/common/actionButtons/actionButtons.mjs +1 -1
- package/dist/esm/common/actionButtons/actionButtons.mjs.map +1 -1
- package/dist/esm/common/actionIcon/actionIcon.mjs +1 -1
- package/dist/esm/common/actionIcon/actionIcon.mjs.map +1 -1
- package/dist/esm/common/actionIcon/actionIcon.module.mjs +1 -1
- package/dist/esm/common/actionIcon/actionIcon.module.mjs.map +1 -1
- package/dist/esm/common/alert/alert.mjs +1 -1
- package/dist/esm/common/alert/alert.mjs.map +1 -1
- package/dist/esm/common/alert/alert.module.mjs +1 -1
- package/dist/esm/common/alert/alert.module.mjs.map +1 -1
- package/dist/esm/common/animatedLogo/animatedLogo.mjs +1 -1
- package/dist/esm/common/animatedLogo/animatedLogo.mjs.map +1 -1
- package/dist/esm/common/avatar/avatar.mjs +1 -1
- package/dist/esm/common/avatar/avatar.mjs.map +1 -1
- package/dist/esm/common/badge/badge.mjs +1 -1
- package/dist/esm/common/badge/badge.mjs.map +1 -1
- package/dist/esm/common/badge/badge.module.mjs +1 -1
- package/dist/esm/common/badge/badge.module.mjs.map +1 -1
- package/dist/esm/common/badge/badge.types.mjs +1 -1
- package/dist/esm/common/badge/badge.types.mjs.map +1 -1
- package/dist/esm/common/bodyEnd/bodyEnd.mjs +1 -1
- package/dist/esm/common/bodyEnd/bodyEnd.mjs.map +1 -1
- package/dist/esm/common/breadcrumb/breadcrumb.mjs +1 -1
- package/dist/esm/common/breadcrumb/breadcrumb.mjs.map +1 -1
- package/dist/esm/common/breadcrumb/breadcrumb.module.mjs.map +1 -1
- package/dist/esm/common/button/button.mjs +1 -1
- package/dist/esm/common/button/button.mjs.map +1 -1
- package/dist/esm/common/button/button.module.mjs +1 -1
- package/dist/esm/common/button/button.module.mjs.map +1 -1
- package/dist/esm/common/button/button.types.mjs +1 -1
- package/dist/esm/common/button/button.types.mjs.map +1 -1
- package/dist/esm/common/calendar/calendar.mjs +1 -1
- package/dist/esm/common/calendar/calendar.mjs.map +1 -1
- package/dist/esm/common/calendar/calendar.module.mjs.map +1 -1
- package/dist/esm/common/calendar/calendar.types.mjs.map +1 -1
- package/dist/esm/common/calendar/components/agendaList/agendaList.mjs +1 -1
- package/dist/esm/common/calendar/components/agendaList/agendaList.mjs.map +1 -1
- package/dist/esm/common/calendar/components/agendaList/agendaList.module.mjs.map +1 -1
- package/dist/esm/common/calendar/components/calendarHeader/calendarHeader.mjs +1 -1
- package/dist/esm/common/calendar/components/calendarHeader/calendarHeader.mjs.map +1 -1
- package/dist/esm/common/calendar/components/calendarHeader/calendarHeader.module.mjs +1 -1
- package/dist/esm/common/calendar/components/calendarHeader/calendarHeader.module.mjs.map +1 -1
- package/dist/esm/common/calendar/components/compactMonth/compactMonth.mjs +1 -1
- package/dist/esm/common/calendar/components/compactMonth/compactMonth.mjs.map +1 -1
- package/dist/esm/common/calendar/components/compactMonth/compactMonth.module.mjs +1 -1
- package/dist/esm/common/calendar/components/compactMonth/compactMonth.module.mjs.map +1 -1
- package/dist/esm/common/calendar/components/monthView/monthView.mjs +1 -1
- package/dist/esm/common/calendar/components/monthView/monthView.mjs.map +1 -1
- package/dist/esm/common/calendar/components/monthView/monthView.module.mjs +1 -1
- package/dist/esm/common/calendar/components/monthView/monthView.module.mjs.map +1 -1
- package/dist/esm/common/calendar/components/timeGrid/timeGrid.mjs +1 -1
- package/dist/esm/common/calendar/components/timeGrid/timeGrid.mjs.map +1 -1
- package/dist/esm/common/calendar/components/timeGrid/timeGrid.module.mjs +1 -1
- package/dist/esm/common/calendar/components/timeGrid/timeGrid.module.mjs.map +1 -1
- package/dist/esm/common/calendar/dates.mjs +1 -1
- package/dist/esm/common/calendar/dates.mjs.map +1 -1
- package/dist/esm/common/calendar/format.mjs +1 -1
- package/dist/esm/common/calendar/format.mjs.map +1 -1
- package/dist/esm/common/calendar/layout.mjs +1 -1
- package/dist/esm/common/calendar/layout.mjs.map +1 -1
- package/dist/esm/common/calendar/useNow.mjs +2 -0
- package/dist/esm/common/calendar/useNow.mjs.map +1 -0
- package/dist/esm/common/card/Card.mjs +1 -1
- package/dist/esm/common/card/Card.mjs.map +1 -1
- package/dist/esm/common/card/CardActions.mjs +1 -1
- package/dist/esm/common/card/CardActions.mjs.map +1 -1
- package/dist/esm/common/card/CardHeader.mjs.map +1 -1
- package/dist/esm/common/card/card.module.mjs +1 -1
- package/dist/esm/common/card/card.module.mjs.map +1 -1
- package/dist/esm/common/card/card.types.mjs +1 -1
- package/dist/esm/common/card/card.types.mjs.map +1 -1
- package/dist/esm/common/carousel/carousel.mjs +1 -1
- package/dist/esm/common/carousel/carousel.mjs.map +1 -1
- package/dist/esm/common/carousel/carousel.module.mjs.map +1 -1
- package/dist/esm/common/chip/chip.mjs +1 -1
- package/dist/esm/common/chip/chip.mjs.map +1 -1
- package/dist/esm/common/chip/chip.module.mjs +1 -1
- package/dist/esm/common/chip/chip.module.mjs.map +1 -1
- package/dist/esm/common/chip/chip.types.mjs +1 -1
- package/dist/esm/common/chip/chip.types.mjs.map +1 -1
- package/dist/esm/common/colorPicker/colorPicker.mjs +1 -1
- package/dist/esm/common/colorPicker/colorPicker.mjs.map +1 -1
- package/dist/esm/common/colorPicker/colorPicker.module.mjs.map +1 -1
- package/dist/esm/common/confirmModal/confirmModal.mjs +1 -1
- package/dist/esm/common/confirmModal/confirmModal.mjs.map +1 -1
- package/dist/esm/common/copyButton/copyButton.mjs +1 -1
- package/dist/esm/common/copyButton/copyButton.mjs.map +1 -1
- package/dist/esm/common/copyButton/copyButton.module.mjs +1 -1
- package/dist/esm/common/copyButton/copyButton.module.mjs.map +1 -1
- package/dist/esm/common/errorBoundary/errorBoundary.mjs +2 -2
- package/dist/esm/common/errorBoundary/errorBoundary.mjs.map +1 -1
- package/dist/esm/common/fab/components/fabBase/fabBase.mjs +1 -1
- package/dist/esm/common/fab/components/fabBase/fabBase.mjs.map +1 -1
- package/dist/esm/common/fab/fab.mjs +1 -1
- package/dist/esm/common/fab/fab.mjs.map +1 -1
- package/dist/esm/common/flip/flip.mjs +1 -1
- package/dist/esm/common/flip/flip.mjs.map +1 -1
- package/dist/esm/common/floorPlan/floorPlan.faces.mjs +1 -1
- package/dist/esm/common/floorPlan/floorPlan.faces.mjs.map +1 -1
- package/dist/esm/common/floorPlan/floorPlan.geometry.mjs +1 -1
- package/dist/esm/common/floorPlan/floorPlan.geometry.mjs.map +1 -1
- package/dist/esm/common/floorPlan/floorPlan.graph.mjs +1 -1
- package/dist/esm/common/floorPlan/floorPlan.graph.mjs.map +1 -1
- package/dist/esm/common/floorPlan/floorPlan.hit.mjs +1 -1
- package/dist/esm/common/floorPlan/floorPlan.hit.mjs.map +1 -1
- package/dist/esm/common/floorPlan/floorPlan.json.mjs +1 -1
- package/dist/esm/common/floorPlan/floorPlan.json.mjs.map +1 -1
- package/dist/esm/common/floorPlan/floorPlan.mesh.mjs +1 -1
- package/dist/esm/common/floorPlan/floorPlan.mesh.mjs.map +1 -1
- package/dist/esm/common/floorPlan/floorPlan.path.mjs +1 -1
- package/dist/esm/common/floorPlan/floorPlan.path.mjs.map +1 -1
- package/dist/esm/common/floorPlan/floorPlan.plan.mjs +1 -1
- package/dist/esm/common/floorPlan/floorPlan.plan.mjs.map +1 -1
- package/dist/esm/common/floorPlan/floorPlan.rooms.mjs +1 -1
- package/dist/esm/common/floorPlan/floorPlan.rooms.mjs.map +1 -1
- package/dist/esm/common/floorPlan/floorPlan.snap.mjs +1 -1
- package/dist/esm/common/floorPlan/floorPlan.snap.mjs.map +1 -1
- package/dist/esm/common/floorPlan/floorPlan.triangulate.mjs +1 -1
- package/dist/esm/common/floorPlan/floorPlan.triangulate.mjs.map +1 -1
- package/dist/esm/common/floorPlan/floorPlan.types.mjs +1 -1
- package/dist/esm/common/floorPlan/floorPlan.types.mjs.map +1 -1
- package/dist/esm/common/klipyPicker/klipyPicker.mjs +1 -1
- package/dist/esm/common/klipyPicker/klipyPicker.mjs.map +1 -1
- package/dist/esm/common/modal/modal.mjs +1 -1
- package/dist/esm/common/modal/modal.mjs.map +1 -1
- package/dist/esm/common/modal/modal.module.mjs.map +1 -1
- package/dist/esm/common/numberInput/numberInput.mjs +1 -1
- package/dist/esm/common/numberInput/numberInput.mjs.map +1 -1
- package/dist/esm/common/numberInput/numberInput.module.mjs.map +1 -1
- package/dist/esm/common/planCanvas/planCanvas.mjs +1 -1
- package/dist/esm/common/planCanvas/planCanvas.mjs.map +1 -1
- package/dist/esm/common/popover/popover.mjs +1 -1
- package/dist/esm/common/popover/popover.mjs.map +1 -1
- package/dist/esm/common/progressBar/progressBar.mjs +1 -1
- package/dist/esm/common/progressBar/progressBar.mjs.map +1 -1
- package/dist/esm/common/progressBar/progressBar.module.mjs +1 -1
- package/dist/esm/common/progressBar/progressBar.module.mjs.map +1 -1
- package/dist/esm/common/roomDrawer/roomDrawer.mjs +1 -1
- package/dist/esm/common/roomDrawer/roomDrawer.mjs.map +1 -1
- package/dist/esm/common/roomDrawer/roomDrawer.module.mjs.map +1 -1
- package/dist/esm/common/roomViewer/roomViewer.mjs +1 -1
- package/dist/esm/common/roomViewer/roomViewer.mjs.map +1 -1
- package/dist/esm/common/sectionHeader/sectionHeader.mjs.map +1 -1
- package/dist/esm/common/splitButton/splitButton.mjs +1 -1
- package/dist/esm/common/splitButton/splitButton.mjs.map +1 -1
- package/dist/esm/common/styles/tone.mjs +4 -0
- package/dist/esm/common/styles/tone.mjs.map +1 -0
- package/dist/esm/common/styles/tone.module.mjs +2 -0
- package/dist/esm/common/styles/tone.module.mjs.map +1 -0
- package/dist/esm/common/themeProvider/color.types.mjs +2 -0
- package/dist/esm/common/themeProvider/color.types.mjs.map +1 -0
- package/dist/esm/common/themeProvider/defaultTheme.mjs +1 -1
- package/dist/esm/common/themeProvider/defaultTheme.mjs.map +1 -1
- package/dist/esm/common/tilt/tilt.mjs +1 -1
- package/dist/esm/common/tilt/tilt.mjs.map +1 -1
- package/dist/esm/common/timeInput/timeInput.mjs +1 -1
- package/dist/esm/common/timeInput/timeInput.mjs.map +1 -1
- package/dist/esm/common/timeline/timeline.mjs +1 -1
- package/dist/esm/common/timeline/timeline.mjs.map +1 -1
- package/dist/esm/common/timeline/timeline.module.mjs +1 -1
- package/dist/esm/common/timeline/timeline.module.mjs.map +1 -1
- package/dist/esm/common/timeline/timeline.types.mjs +1 -1
- package/dist/esm/common/timeline/timeline.types.mjs.map +1 -1
- package/dist/esm/common/timer/timer.mjs +1 -1
- package/dist/esm/common/timer/timer.mjs.map +1 -1
- package/dist/esm/common/timer/timer.module.mjs +1 -1
- package/dist/esm/common/timer/timer.module.mjs.map +1 -1
- package/dist/esm/common/toast/toast.mjs +1 -1
- package/dist/esm/common/toast/toast.mjs.map +1 -1
- package/dist/esm/common/toast/toast.module.mjs +1 -1
- package/dist/esm/common/toast/toast.module.mjs.map +1 -1
- package/dist/esm/common/toast/toastHost.mjs +1 -1
- package/dist/esm/common/toast/toastHost.mjs.map +1 -1
- package/dist/esm/common/utils/dismissClick.mjs +2 -0
- package/dist/esm/common/utils/dismissClick.mjs.map +1 -0
- package/dist/esm/common/utils/isDev.mjs +2 -0
- package/dist/esm/common/utils/isDev.mjs.map +1 -0
- package/dist/esm/floor-plan.mjs +1 -0
- package/dist/esm/index.mjs +1 -1
- package/dist/esm/services/formValidation/FormValidatorGroupWithForm.mjs +1 -1
- package/dist/esm/services/formValidation/FormValidatorGroupWithForm.mjs.map +1 -1
- package/dist/floor-plan.cjs +1 -0
- package/dist/floorPlan-DLe5XAx6.cjs +2 -0
- package/dist/floorPlan-DLe5XAx6.cjs.map +1 -0
- package/dist/index.cjs +5 -3
- package/dist/index.cjs.map +1 -1
- package/dist/style.css +1 -1
- package/dist/types/common/accordion/accordion.types.d.ts +17 -2
- package/dist/types/common/actionButtons/actionButtons.types.d.ts +7 -1
- package/dist/types/common/actionIcon/actionIcon.d.ts +1 -1
- package/dist/types/common/actionIcon/actionIcon.types.d.ts +7 -9
- package/dist/types/common/alert/alert.types.d.ts +6 -8
- package/dist/types/common/animatedLogo/animatedLogo.types.d.ts +3 -2
- package/dist/types/common/badge/badge.types.d.ts +10 -6
- package/dist/types/common/button/button.types.d.ts +14 -4
- package/dist/types/common/calendar/calendar.types.d.ts +25 -10
- package/dist/types/common/calendar/components/agendaList/agendaList.d.ts +1 -1
- package/dist/types/common/calendar/components/agendaList/agendaList.types.d.ts +3 -0
- package/dist/types/common/calendar/components/calendarHeader/calendarHeader.d.ts +1 -1
- package/dist/types/common/calendar/components/calendarHeader/calendarHeader.types.d.ts +2 -0
- package/dist/types/common/calendar/components/compactMonth/compactMonth.d.ts +1 -1
- package/dist/types/common/calendar/components/monthView/monthView.d.ts +1 -1
- package/dist/types/common/calendar/components/monthView/monthView.types.d.ts +3 -2
- package/dist/types/common/calendar/components/timeGrid/timeGrid.d.ts +1 -1
- package/dist/types/common/calendar/components/timeGrid/timeGrid.types.d.ts +9 -1
- package/dist/types/common/calendar/dates.d.ts +21 -5
- package/dist/types/common/calendar/format.d.ts +3 -2
- package/dist/types/common/calendar/layout.d.ts +5 -0
- package/dist/types/common/calendar/useNow.d.ts +4 -0
- package/dist/types/common/calendar/view.types.d.ts +9 -2
- package/dist/types/common/card/card.types.d.ts +16 -2
- package/dist/types/common/chip/chip.types.d.ts +10 -5
- package/dist/types/common/copyButton/copyButton.types.d.ts +5 -4
- package/dist/types/common/fab/components/fabBase/fabBase.d.ts +1 -1
- package/dist/types/common/fab/components/fabBase/fabBase.types.d.ts +2 -1
- package/dist/types/common/floorPlan/floorPlan.graph.d.ts +10 -3
- package/dist/types/common/floorPlan/floorPlan.plan.d.ts +5 -0
- package/dist/types/common/floorPlan/floorPlan.rooms.d.ts +6 -2
- package/dist/types/common/floorPlan/floorPlan.snap.d.ts +1 -3
- package/dist/types/common/floorPlan/index.d.ts +1 -3
- package/dist/types/common/planCanvas/planCanvas.types.d.ts +1 -1
- package/dist/types/common/progressBar/progressBar.d.ts +0 -1
- package/dist/types/common/progressBar/progressBar.types.d.ts +3 -1
- package/dist/types/common/roomDrawer/roomDrawer.types.d.ts +29 -8
- package/dist/types/common/roomViewer/roomViewer.types.d.ts +4 -2
- package/dist/types/common/splitButton/splitButton.types.d.ts +4 -1
- package/dist/types/common/styles/tone.d.ts +11 -0
- package/dist/types/common/themeProvider/color.types.d.ts +20 -0
- package/dist/types/common/themeProvider/index.d.ts +2 -0
- package/dist/types/common/themeProvider/theme.types.d.ts +3 -6
- package/dist/types/common/timeline/timeline.types.d.ts +3 -10
- package/dist/types/common/toast/index.d.ts +1 -1
- package/dist/types/common/toast/toast.types.d.ts +7 -3
- package/dist/types/common/types/actions.types.d.ts +1 -1
- package/dist/types/common/utils/dismissClick.d.ts +4 -0
- package/dist/types/common/utils/isDev.d.ts +1 -0
- package/docs/Accordion.md +74 -5
- package/docs/ActionButtons.md +6 -3
- package/docs/ActionIcon.md +39 -14
- package/docs/Alert.md +27 -17
- package/docs/AnimatedLogo.md +1 -1
- package/docs/Badge.md +24 -7
- package/docs/Button.md +98 -40
- package/docs/ButtonGroup.md +18 -18
- package/docs/CLAUDE.md +24 -12
- package/docs/Calendar.md +35 -17
- package/docs/Card.md +53 -14
- package/docs/Chip.md +24 -9
- package/docs/ConfigProvider.md +3 -3
- package/docs/CopyButton.md +6 -5
- package/docs/FloorPlan.md +18 -14
- package/docs/ProgressBar.md +7 -4
- package/docs/RoomDrawer.md +42 -13
- package/docs/RoomViewer.md +1 -14
- package/docs/SectionHeader.md +1 -1
- package/docs/SplitButton.md +6 -5
- package/docs/ThemeColor.md +103 -0
- package/docs/ThemeProvider.md +5 -5
- package/docs/Timeline.md +18 -9
- package/docs/Toast.md +25 -11
- package/package.json +20 -2
- package/dist/cjs-types/common/floorPlan/legacySvg.d.ts +0 -27
- package/dist/esm/common/accordion/accordion.plain.module.mjs +0 -2
- package/dist/esm/common/accordion/accordion.plain.module.mjs.map +0 -1
- package/dist/esm/common/accordion/accordion.primary.module.mjs +0 -2
- package/dist/esm/common/accordion/accordion.primary.module.mjs.map +0 -1
- package/dist/esm/common/alert/alert.types.mjs +0 -2
- package/dist/esm/common/alert/alert.types.mjs.map +0 -1
- package/dist/esm/common/floorPlan/legacySvg.mjs +0 -2
- package/dist/esm/common/floorPlan/legacySvg.mjs.map +0 -1
- package/dist/types/common/floorPlan/legacySvg.d.ts +0 -27
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roomDrawer.module.mjs","names":[],"sources":["../../../../package/common/roomDrawer/roomDrawer.module.pcss"],"sourcesContent":[".roomDrawer {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-s, 8px);\n color: var(--text-color);\n position: relative;\n\n &:focus-visible {\n outline: 2px solid var(--focus-border-color, var(--primary-color));\n outline-offset: 2px;\n border-radius: var(--default-border-radius);\n }\n\n &-disabled {\n opacity: 0.6;\n pointer-events: none;\n }\n\n /* ── Toolbar ── */\n\n &-toolbar {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 4px;\n padding: 4px;\n background: var(--background-accent);\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n\n &-separator {\n width: 1px;\n align-self: stretch;\n margin: 2px 4px;\n background: var(--border-color);\n }\n }\n\n &-toolButton,\n &-viewButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 34px;\n height: 34px;\n padding: 0 8px;\n border: 1px solid transparent;\n border-radius: var(--default-border-radius);\n background: transparent;\n color: var(--text-color);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &:hover:not(:disabled) {\n background: var(--background-accent-light);\n }\n\n &:focus-visible {\n outline: none;\n border-color: var(--focus-border-color, var(--primary-color));\n }\n\n &:disabled {\n opacity: 0.4;\n cursor: default;\n }\n }\n\n &-toolButtonActive {\n background: var(--primary-color);\n color: var(--text-on-primary);\n\n &:hover {\n background: var(--primary-color);\n }\n }\n\n &-toolIcon {\n pointer-events: none;\n }\n\n &-viewControls {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n margin-left: auto;\n }\n\n &-zoomLabel {\n min-width: 62px;\n height: 34px;\n padding: 0 6px;\n border: 1px solid transparent;\n border-radius: var(--default-border-radius);\n background: transparent;\n color: var(--text-dark);\n font-size: 12px;\n font-variant-numeric: tabular-nums;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &:hover {\n background: var(--background-accent-light);\n }\n\n &:focus-visible {\n outline: none;\n border-color: var(--focus-border-color, var(--primary-color));\n }\n }\n\n /* Storeys, top one first. A strip rather than a dropdown because switching floors is\n something you do constantly while drawing, and a dropdown costs two clicks each time. */\n &-floorBar {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-wrap: wrap;\n padding: var(--spacing-xs, 4px);\n background: var(--background-accent);\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n }\n\n &-floorTab {\n height: 28px;\n padding: 0 10px;\n border: 1px solid transparent;\n border-radius: var(--default-border-radius);\n background: transparent;\n color: var(--text-dark);\n font-size: 12px;\n white-space: nowrap;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &:hover {\n background: var(--background-accent-light);\n }\n\n &:focus-visible {\n outline: none;\n border-color: var(--focus-border-color, var(--primary-color));\n }\n\n &-active {\n background: var(--primary-color);\n border-color: var(--primary-color);\n color: var(--text-on-primary);\n font-weight: 600;\n\n &:hover {\n background: var(--primary-color);\n }\n }\n\n &-add {\n padding: 0 8px;\n color: var(--text-dark);\n }\n }\n\n /* ── Canvas ── */\n\n &-canvasWrapper {\n position: relative;\n overflow: hidden;\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n background: var(--background);\n\n /* Without this the browser claims the gesture and pointermove stops firing mid-drag. */\n touch-action: none;\n cursor: default;\n -webkit-tap-highlight-color: transparent;\n\n &-drawing {\n cursor: crosshair;\n }\n }\n\n /* ── Screen-space overlay ── */\n\n &-preview {\n fill: var(--primary-accent);\n fill-opacity: 0.12;\n stroke: var(--primary-color);\n stroke-width: 1.5;\n stroke-dasharray: 5 4;\n }\n\n &-marquee {\n fill: var(--primary-color);\n fill-opacity: 0.1;\n stroke: var(--primary-color);\n stroke-width: 1;\n stroke-dasharray: 4 3;\n }\n\n &-handle {\n fill: var(--background);\n stroke: var(--primary-color);\n stroke-width: 2;\n\n &-active {\n fill: var(--primary-color);\n }\n }\n\n /* A latched toggle (snap, angle lock, grid): on, but not the active tool. */\n &-toolButtonOn {\n border-color: var(--primary-color);\n color: var(--primary-color);\n }\n\n /* ── Snap feedback ── */\n\n &-guide {\n stroke: var(--plan-guide-color, var(--info-color));\n stroke-width: 1;\n stroke-dasharray: 4 4;\n opacity: 0.8;\n pointer-events: none;\n\n /* Angle lock gets the brand colour: it is the one the user asked for by name. */\n &-angle {\n stroke: var(--primary-color);\n stroke-dasharray: 6 3;\n opacity: 0.9;\n }\n }\n\n &-snapMarker {\n fill: none;\n stroke: var(--primary-color);\n stroke-width: 1.5;\n pointer-events: none;\n }\n\n /* A measurement, not geometry: dashed and in the accent colour so it can never be\n mistaken for a wall that was actually drawn. */\n &-measureLine {\n pointer-events: none;\n\n line {\n stroke: var(--plan-measure-color, var(--primary-color));\n stroke-width: 1.25;\n stroke-dasharray: 5 4;\n }\n\n line + line {\n stroke-dasharray: none;\n }\n\n &-hovered line {\n stroke-width: 2;\n opacity: 1;\n }\n }\n\n /* Only drawn while the ruler is the active tool, so it never competes with a corner\n handle for the same pixel. */\n &-measureGrip {\n fill: var(--background);\n stroke: var(--plan-measure-color, var(--primary-color));\n stroke-width: 1.5;\n cursor: grab;\n -webkit-tap-highlight-color: transparent;\n }\n\n /* Hollow and smaller than a corner handle: it marks a corner that does not exist yet. */\n &-midHandle {\n fill: var(--background);\n stroke: var(--primary-color);\n stroke-width: 1.5;\n stroke-dasharray: 2.5 2;\n }\n\n &-measure {\n fill: var(--text-color);\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n paint-order: stroke;\n stroke: var(--background);\n stroke-width: 3px;\n stroke-linejoin: round;\n\n &-locked {\n fill: var(--primary-color);\n font-weight: 600;\n }\n\n /* How far a room has been dragged. Carries a chip behind it because it floats over the\n room's own fill rather than sitting on a wall, where the halo alone would do. */\n &-offset {\n fill: var(--text-on-primary);\n font-weight: 600;\n paint-order: stroke;\n stroke: var(--primary-color);\n stroke-width: 8px;\n stroke-linejoin: round;\n }\n\n /* A consequence of the edit rather than its subject: still readable, but clearly\n secondary to the wall or corner actually being moved. */\n &-secondary {\n fill: var(--text-dark);\n opacity: 0.75;\n }\n }\n\n /* ── Inspector ── */\n\n &-inspector {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 8px;\n padding: 8px;\n background: var(--background-accent);\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n\n &-action {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n height: 34px;\n padding: 0 12px;\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n background: var(--background);\n color: var(--text-color);\n font-size: 13px;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &:hover:not(:disabled) {\n background: var(--background-accent-light);\n }\n\n &:disabled {\n opacity: 0.4;\n cursor: default;\n }\n\n &:focus-visible {\n outline: none;\n border-color: var(--focus-border-color, var(--primary-color));\n }\n }\n\n &-label {\n color: var(--text-dark);\n font-size: 12px;\n font-variant-numeric: tabular-nums;\n }\n\n /* What is selected. Carries the bar on its own for a corner, which has nothing to edit\n but a position that is already being edited by dragging it. */\n &-kind {\n display: flex;\n align-items: center;\n flex: none;\n\n /* Always rendered, so it is what holds the row open to a field's height whether or\n not the selection has any fields. Setting this on the bar itself would not do:\n it is border-box, so the figure would have to know the padding. */\n min-height: 34px;\n color: var(--text-dark);\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n white-space: nowrap;\n }\n\n &-kindEmpty {\n opacity: 0.6;\n font-weight: 500;\n text-transform: none;\n letter-spacing: 0;\n font-size: 12px;\n }\n\n /* Sized to their contents, so the row stays a row. A field at its natural full width\n wrapped onto a line of its own and took the bar to three of them. They still wrap\n when the drawer is genuinely too narrow for them. */\n &-field {\n flex: none;\n\n /* Wide enough for the longest floating label, `Thickness (mm)`, plus the stepper\n arrows: a narrower box left the label hanging over its own border. */\n width: 142px;\n }\n\n &-name {\n flex: 1 1 150px;\n min-width: 120px;\n max-width: 280px;\n }\n\n /* The one action that applies to every kind of selection, and the only destructive one,\n so it sits apart at the end rather than in the run of fields. */\n &-delete {\n margin-left: auto;\n color: var(--error-color, var(--text-color));\n }\n }\n\n /* ── Hint ── */\n\n &-hint {\n color: var(--text-dark);\n font-size: 12px;\n line-height: 1.4;\n\n /* What an opened file needed doing to it. Louder than a hint because it is the only\n account of what happened to the user's file. */\n &-report {\n color: var(--error-color, var(--text-color));\n font-weight: 500;\n }\n }\n\n /* The picker is opened from the toolbar button, so the input itself is never shown.\n Hidden by clipping rather than `display: none`, which stops `.click()` opening the\n dialog in some browsers. */\n &-fileInput {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n border: 0;\n clip-path: inset(50%);\n overflow: hidden;\n white-space: nowrap;\n }\n}\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"roomDrawer.module.mjs","names":[],"sources":["../../../../package/common/roomDrawer/roomDrawer.module.pcss"],"sourcesContent":[".roomDrawer {\n display: flex;\n flex-direction: column;\n gap: var(--spacing-s, 8px);\n color: var(--text-color);\n position: relative;\n\n &:focus-visible {\n outline: 2px solid var(--focus-border-color, var(--primary-color));\n outline-offset: 2px;\n border-radius: var(--default-border-radius);\n }\n\n &-disabled {\n opacity: 0.6;\n pointer-events: none;\n }\n\n /* ── Toolbar ── */\n\n &-toolbar {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 4px;\n padding: 4px;\n background: var(--background-accent);\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n\n &-separator {\n width: 1px;\n align-self: stretch;\n margin: 2px 4px;\n background: var(--border-color);\n }\n }\n\n &-toolButton,\n &-viewButton {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 34px;\n height: 34px;\n padding: 0 8px;\n border: 1px solid transparent;\n border-radius: var(--default-border-radius);\n background: transparent;\n color: var(--text-color);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &:hover:not(:disabled) {\n background: var(--background-accent-light);\n }\n\n &:focus-visible {\n outline: none;\n border-color: var(--focus-border-color, var(--primary-color));\n }\n\n &:disabled {\n opacity: 0.4;\n cursor: default;\n }\n }\n\n &-toolButtonActive {\n background: var(--primary-color);\n color: var(--text-on-primary);\n\n &:hover {\n background: var(--primary-color);\n }\n }\n\n &-toolIcon {\n pointer-events: none;\n }\n\n &-viewControls {\n display: inline-flex;\n align-items: center;\n gap: 2px;\n margin-left: auto;\n }\n\n &-zoomLabel {\n min-width: 62px;\n height: 34px;\n padding: 0 6px;\n border: 1px solid transparent;\n border-radius: var(--default-border-radius);\n background: transparent;\n color: var(--text-dark);\n font-size: 12px;\n font-variant-numeric: tabular-nums;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &:hover {\n background: var(--background-accent-light);\n }\n\n &:focus-visible {\n outline: none;\n border-color: var(--focus-border-color, var(--primary-color));\n }\n }\n\n /* Storeys, top one first. A strip rather than a dropdown because switching floors is\n something you do constantly while drawing, and a dropdown costs two clicks each time. */\n &-floorBar {\n display: flex;\n align-items: center;\n gap: 2px;\n flex-wrap: wrap;\n padding: var(--spacing-xs, 4px);\n background: var(--background-accent);\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n }\n\n &-floorTab {\n height: 28px;\n padding: 0 10px;\n border: 1px solid transparent;\n border-radius: var(--default-border-radius);\n background: transparent;\n color: var(--text-dark);\n font-size: 12px;\n white-space: nowrap;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &:hover {\n background: var(--background-accent-light);\n }\n\n &:focus-visible {\n outline: none;\n border-color: var(--focus-border-color, var(--primary-color));\n }\n\n &-active {\n background: var(--primary-color);\n border-color: var(--primary-color);\n color: var(--text-on-primary);\n font-weight: 600;\n\n &:hover {\n background: var(--primary-color);\n }\n }\n\n &-add {\n padding: 0 8px;\n color: var(--text-dark);\n }\n }\n\n /* ── Canvas ── */\n\n &-canvasWrapper {\n position: relative;\n overflow: hidden;\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n background: var(--background);\n\n /* Without this the browser claims the gesture and pointermove stops firing mid-drag. */\n touch-action: none;\n cursor: default;\n -webkit-tap-highlight-color: transparent;\n\n &-drawing {\n cursor: crosshair;\n }\n }\n\n /* ── Screen-space overlay ── */\n\n &-preview {\n fill: var(--primary-accent);\n fill-opacity: 0.12;\n stroke: var(--primary-color);\n stroke-width: 1.5;\n stroke-dasharray: 5 4;\n }\n\n &-marquee {\n fill: var(--primary-color);\n fill-opacity: 0.1;\n stroke: var(--primary-color);\n stroke-width: 1;\n stroke-dasharray: 4 3;\n }\n\n &-handle {\n fill: var(--background);\n stroke: var(--primary-color);\n stroke-width: 2;\n\n &-active {\n fill: var(--primary-color);\n }\n }\n\n /* A latched toggle (snap, angle lock, grid): on, but not the active tool. */\n &-toolButtonOn {\n border-color: var(--primary-color);\n color: var(--primary-color);\n }\n\n /* ── Snap feedback ── */\n\n &-guide {\n stroke: var(--plan-guide-color, var(--info-color));\n stroke-width: 1;\n stroke-dasharray: 4 4;\n opacity: 0.8;\n pointer-events: none;\n\n /* Angle lock gets the brand colour: it is the one the user asked for by name. */\n &-angle {\n stroke: var(--primary-color);\n stroke-dasharray: 6 3;\n opacity: 0.9;\n }\n }\n\n &-snapMarker {\n fill: none;\n stroke: var(--primary-color);\n stroke-width: 1.5;\n pointer-events: none;\n }\n\n /* A measurement, not geometry: dashed and in the accent colour so it can never be\n mistaken for a wall that was actually drawn. */\n &-measureLine {\n pointer-events: none;\n\n line {\n stroke: var(--plan-measure-color, var(--primary-color));\n stroke-width: 1.25;\n stroke-dasharray: 5 4;\n }\n\n line + line {\n stroke-dasharray: none;\n }\n\n &-hovered line {\n stroke-width: 2;\n opacity: 1;\n }\n }\n\n /* Only drawn while the ruler is the active tool, so it never competes with a corner\n handle for the same pixel. */\n &-measureGrip {\n fill: var(--background);\n stroke: var(--plan-measure-color, var(--primary-color));\n stroke-width: 1.5;\n cursor: grab;\n -webkit-tap-highlight-color: transparent;\n }\n\n /* Hollow and smaller than a corner handle: it marks a corner that does not exist yet. */\n &-midHandle {\n fill: var(--background);\n stroke: var(--primary-color);\n stroke-width: 1.5;\n stroke-dasharray: 2.5 2;\n }\n\n &-measure {\n fill: var(--text-color);\n font-size: 11px;\n font-variant-numeric: tabular-nums;\n paint-order: stroke;\n stroke: var(--background);\n stroke-width: 3px;\n stroke-linejoin: round;\n\n &-locked {\n fill: var(--primary-color);\n font-weight: 600;\n }\n\n /* How far a room has been dragged. Carries a chip behind it because it floats over the\n room's own fill rather than sitting on a wall, where the halo alone would do. */\n &-offset {\n fill: var(--text-on-primary);\n font-weight: 600;\n paint-order: stroke;\n stroke: var(--primary-color);\n stroke-width: 8px;\n stroke-linejoin: round;\n }\n\n /* A consequence of the edit rather than its subject: still readable, but clearly\n secondary to the wall or corner actually being moved. */\n &-secondary {\n fill: var(--text-dark);\n opacity: 0.75;\n }\n }\n\n /* ── Inspector ── */\n\n &-inspector {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: 8px;\n padding: 8px;\n background: var(--background-accent);\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n\n &-action {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n height: 34px;\n padding: 0 12px;\n border: 1px solid var(--border-color);\n border-radius: var(--default-border-radius);\n background: var(--background);\n color: var(--text-color);\n font-size: 13px;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n\n &:hover:not(:disabled) {\n background: var(--background-accent-light);\n }\n\n &:disabled {\n opacity: 0.4;\n cursor: default;\n }\n\n &:focus-visible {\n outline: none;\n border-color: var(--focus-border-color, var(--primary-color));\n }\n }\n\n &-label {\n color: var(--text-dark);\n font-size: 12px;\n font-variant-numeric: tabular-nums;\n }\n\n /* What is selected. Carries the bar on its own for a corner, which has nothing to edit\n but a position that is already being edited by dragging it. */\n &-kind {\n display: flex;\n align-items: center;\n flex: none;\n\n /* Always rendered, so it is what holds the row open to a field's height whether or\n not the selection has any fields. Setting this on the bar itself would not do:\n it is border-box, so the figure would have to know the padding. */\n min-height: 34px;\n color: var(--text-dark);\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.04em;\n text-transform: uppercase;\n white-space: nowrap;\n }\n\n &-kindEmpty {\n opacity: 0.6;\n font-weight: 500;\n text-transform: none;\n letter-spacing: 0;\n font-size: 12px;\n }\n\n /* Sized to their contents, so the row stays a row. A field at its natural full width\n wrapped onto a line of its own and took the bar to three of them. They still wrap\n when the drawer is genuinely too narrow for them. */\n &-field {\n flex: none;\n\n /* Wide enough for the longest floating label, `Thickness (mm)`, plus the stepper\n arrows: a narrower box left the label hanging over its own border. */\n width: 142px;\n }\n\n &-name {\n flex: 1 1 150px;\n min-width: 120px;\n max-width: 280px;\n }\n\n /* The one action that applies to every kind of selection, and the only destructive one,\n so it sits apart at the end rather than in the run of fields. */\n &-delete {\n margin-left: auto;\n }\n }\n\n /* ── Hint ── */\n\n &-hint {\n color: var(--text-dark);\n font-size: 12px;\n line-height: 1.4;\n\n /* What an opened file needed doing to it. Louder than a hint because it is the only\n account of what happened to the user's file. */\n &-report {\n color: var(--error-color, var(--text-color));\n font-weight: 500;\n }\n }\n\n /* The picker is opened from the toolbar button, so the input itself is never shown.\n Hidden by clipping rather than `display: none`, which stops `.click()` opening the\n dialog in some browsers. */\n &-fileInput {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n border: 0;\n clip-path: inset(50%);\n overflow: hidden;\n white-space: nowrap;\n }\n}\n"],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{
|
|
1
|
+
"use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{useLabels as t}from"../configProvider/useLabels.mjs";import{renderIcon as n}from"../utils/renderIcon.mjs";import{floorBounds as r,getFloor as i}from"../floorPlan/floorPlan.plan.mjs";import{derivePlan as a}from"../floorPlan/floorPlan.rooms.mjs";import{clientToWorld as ee}from"../floorPlan/floorPlan.snap.mjs";import o from"../planCanvas/planCanvas.mjs";import s from"./roomViewer.module.mjs";import{useCallback as c,useEffect as l,useId as te,useImperativeHandle as ne,useMemo as u,useRef as d,useState as f}from"react";import p from"classnames";import{faExpand as re,faMagnifyingGlassMinus as ie,faMagnifyingGlassPlus as ae}from"@fortawesome/free-solid-svg-icons";import{jsx as m,jsxs as h}from"react/jsx-runtime";var g=.002,_=4,oe=4;function se(e){let t=e/1e6;return`${t<10?t.toFixed(1):Math.round(t)} m²`}var ce={floors:`Floors`,zoomIn:`Zoom in`,zoomOut:`Zoom out`,fit:`Fit to view`,empty:`Nothing to show`,unnamedRoom:`Unnamed room`,selectedRoom:(e,t)=>`${e} selected, ${t}`,noRoomSelected:`No room selected`};function v(v){let{ref:le,plan:y,activeFloorId:b,defaultActiveFloorId:ue,onFloorChange:x,selectedRoomId:S,defaultSelectedRoomId:de=null,onSelect:C,hoveredRoomId:w,onHoverChange:fe,view:T,defaultView:pe,onViewChange:me,interactive:E=!0,pannable:D=!0,fitOnMount:he=!0,showFloorBar:ge=!0,showViewControls:_e=!0,showGrid:ve=!1,showRoomLabels:ye=!0,showOpeningSymbols:be=!0,getRoomColor:xe,renderRoomLabel:Se,getRoomLabel:Ce,formatArea:O=se,height:we=360,emptyState:Te,labels:Ee,icons:k,className:De,style:Oe,classNames:A,styles:j,"aria-label":M,...ke}=e(`RoomViewer`,v),N=t(`RoomViewer`,Ee,ce),P=d(null),F=d(null),Ae=te().replace(/:/g,``),I=y?.floors??[],[je,Me]=f(ue),Ne=b??je??I[0]?.id,L=u(()=>y?i(y,Ne)??i(y):null,[y,Ne]),R=c(e=>{b===void 0&&Me(e),x?.(e)},[b,x]),z=u(()=>L?a(L).rooms:[],[L]),[Pe,Fe]=f(de),B=S===void 0?Pe:S,[Ie,Le]=f(null),V=w===void 0?Ie:w,H=c(e=>{S===void 0&&Fe(e);let t=e?z.find(t=>t.roomId===e)??null:null;C?.(e,t,L?.id??``)},[S,z,C,L?.id]),Re=c(e=>{w===void 0&&Le(e),fe?.(e)},[w,fe]),ze=(()=>{let e=B?z.find(e=>e.roomId===B):void 0;return e?N.selectedRoom(e.meta?.name||N.unnamedRoom,O(e.area)):N.noRoomSelected})(),[Be,Ve]=f(pe??{x:0,y:0,zoom:.05}),U=T??Be,W=d(U);W.current=U;let G=c(e=>{T===void 0&&Ve(e),me?.(e)},[T,me]),K=d(!1),[q,He]=f({width:800,height:360});l(()=>{let e=P.current;if(!e)return;let t=()=>{let t=e.getBoundingClientRect();t.width>0&&t.height>0&&He({width:Math.round(t.width),height:Math.round(t.height)})},n=new ResizeObserver(t);return n.observe(e),t(),()=>n.disconnect()},[]);let J=c((e={})=>{let t=e.padding??24,n=L?r(L):null;if(!n||n.width<=0||n.height<=0){G({x:-1e3,y:-1e3,zoom:.05});return}let i=Math.max(g,Math.min(_,Math.min((q.width-t*2)/n.width,(q.height-t*2)/n.height)));G({x:n.minX-(q.width/i-n.width)/2,y:n.minY-(q.height/i-n.height)/2,zoom:i})},[L,q.width,q.height,G]);l(()=>{he&&!K.current&&(!L||q.width<=0||Object.keys(L.nodes).length===0||J())},[he,L,q.width,q.height,J]);let Y=c((e,t)=>{K.current=!0;let n=W.current,r=Math.max(g,Math.min(_,n.zoom*e));if(r===n.zoom)return;let i=t?.x??q.width/2,a=t?.y??q.height/2;G({x:n.x+i/n.zoom-i/r,y:n.y+a/n.zoom-a/r,zoom:r})},[G,q.width,q.height]),X=d(new Map),Z=d(null),Q=d(null),Ue=c(e=>{if(D){if(X.current.set(e.pointerId,{x:e.clientX,y:e.clientY}),X.current.size===2){let[e,t]=[...X.current.values()];Q.current={dist:Math.hypot(t.x-e.x,t.y-e.y),view:W.current,mid:{x:(e.x+t.x)/2,y:(e.y+t.y)/2}},Z.current=null;return}Z.current={startClient:{x:e.clientX,y:e.clientY},startView:W.current,moved:!1}}},[D]),We=c(e=>{X.current.has(e.pointerId)&&X.current.set(e.pointerId,{x:e.clientX,y:e.clientY});let t=Q.current;if(t&&X.current.size>=2){let[e,n]=[...X.current.values()],r=Math.hypot(n.x-e.x,n.y-e.y);if(t.dist<=0)return;let i=Math.max(g,Math.min(_,t.view.zoom*(r/t.dist))),a=P.current?.getBoundingClientRect()??{left:0,top:0},o={x:(e.x+n.x)/2,y:(e.y+n.y)/2};K.current=!0;let s=ee(t.mid.x,t.mid.y,a,t.view);G({x:s.x-(o.x-a.left)/i,y:s.y-(o.y-a.top)/i,zoom:i});return}let n=Z.current;if(!n)return;let r=e.clientX-n.startClient.x,i=e.clientY-n.startClient.y;!n.moved&&Math.hypot(r,i)<=oe||(n.moved||e.currentTarget.setPointerCapture?.(e.pointerId),n.moved=!0,K.current=!0,G({x:n.startView.x-r/n.startView.zoom,y:n.startView.y-i/n.startView.zoom,zoom:n.startView.zoom}))},[G]),Ge=c(e=>{X.current.delete(e.pointerId),X.current.size<2&&(Q.current=null),Z.current=null},[]);l(()=>{let e=P.current;if(!e||!D)return;let t=t=>{t.preventDefault();let n=e.getBoundingClientRect();Y(t.deltaY<0?1.1:1/1.1,{x:t.clientX-n.left,y:t.clientY-n.top})};return e.addEventListener(`wheel`,t,{passive:!1}),()=>e.removeEventListener(`wheel`,t)},[D,Y]),ne(le,()=>({fitToContent:J,getView:()=>W.current,setView:G,zoomBy:e=>Y(e),select:H,getFloorId:()=>L?.id??null,setFloorId:R,getSvgElement:()=>F.current}),[J,G,Y,H,L?.id,R]);let Ke=u(()=>B?[{type:`room`,id:B}]:[],[B]),qe=u(()=>V?{type:`room`,id:V}:null,[V]),$=!L||Object.keys(L.walls).length===0;return h(`div`,{...ke,className:p(s.roomViewer,De,A?.root),style:{...Oe,...j?.root},"aria-label":M??`Floor plan`,children:[ge&&I.length>1&&m(`div`,{className:p(s.roomViewerFloorBar,A?.floorBar),style:j?.floorBar,role:`tablist`,"aria-label":N.floors,children:[...I].reverse().map(e=>m(`button`,{type:`button`,role:`tab`,className:p(s.roomViewerFloorTab,e.id===L?.id&&s.roomViewerFloorTabActive,A?.floorTab),style:j?.floorTab,"aria-selected":e.id===L?.id,onClick:()=>R(e.id),children:e.label},e.id))}),h(`div`,{ref:P,className:p(s.roomViewerCanvasWrapper,D&&s.roomViewerCanvasWrapperPannable,A?.canvasWrapper),style:{height:we,...j?.canvasWrapper},onPointerDown:Ue,onPointerMove:We,onPointerUp:Ge,onPointerCancel:Ge,children:[$?m(`div`,{className:p(s.roomViewerEmpty,A?.empty),style:j?.empty,children:Te??N.empty}):m(o,{ref:F,floor:L,rooms:z,view:U,size:q,selection:Ke,hovered:qe,interactiveRooms:E,showGrid:ve,showRoomLabels:ye,showOpeningSymbols:be,getRoomColor:xe,renderRoomLabel:Se,getRoomLabel:Ce??((e,{area:t})=>`${e?.name||N.unnamedRoom}, ${O(t)}`),formatArea:O,onRoomActivate:E?e=>H(e):void 0,onBackgroundActivate:E?()=>H(null):void 0,onHoverChange:E?e=>Re(e?.type===`room`?e.id:null):void 0,classNames:{canvas:A?.canvas,grid:A?.grid,rooms:A?.rooms,roomFill:A?.roomFill,roomLabel:A?.roomLabel,walls:A?.walls,wallBody:A?.wallBody,openings:A?.openings,opening:A?.opening},styles:{canvas:j?.canvas,grid:j?.grid,rooms:j?.rooms,roomFill:j?.roomFill,roomLabel:j?.roomLabel,walls:j?.walls,wallBody:j?.wallBody,openings:j?.openings,opening:j?.opening},"aria-label":M??`Floor plan`}),_e&&!$&&h(`div`,{className:p(s.roomViewerViewControls,A?.viewControls),style:j?.viewControls,children:[m(`button`,{type:`button`,className:p(s.roomViewerViewButton,A?.viewButton),style:j?.viewButton,title:N.zoomOut,"aria-label":N.zoomOut,onClick:()=>Y(1/1.2),children:n(k?.zoomOut??ie)}),m(`button`,{type:`button`,className:p(s.roomViewerViewButton,A?.viewButton),style:j?.viewButton,title:N.fit,"aria-label":N.fit,onClick:()=>{K.current=!1,J()},children:n(k?.fit??re)}),m(`button`,{type:`button`,className:p(s.roomViewerViewButton,A?.viewButton),style:j?.viewButton,title:N.zoomIn,"aria-label":N.zoomIn,onClick:()=>Y(1.2),children:n(k?.zoomIn??ae)})]})]}),m(`div`,{id:Ae,className:s.roomViewerLive,role:`status`,"aria-live":`polite`,children:ze})]})}export{v as default};
|
|
2
2
|
//# sourceMappingURL=roomViewer.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"roomViewer.mjs","names":[],"sources":["../../../../package/common/roomViewer/roomViewer.tsx"],"sourcesContent":["import { useCallback, useEffect, useImperativeHandle, useId, useMemo, useRef, useState } from 'react';\nimport type { PointerEvent as ReactPointerEvent } from 'react';\nimport cx from 'classnames';\nimport { faExpand, faMagnifyingGlassMinus, faMagnifyingGlassPlus } from '@fortawesome/free-solid-svg-icons';\n\nimport { useComponentDefaults } from '../configProvider';\nimport {\n clientToWorld,\n derivePlan,\n floorBounds,\n getFloor,\n type PlanFloor,\n type PlanSelection,\n type PlanView,\n} from '../floorPlan';\nimport PlanCanvas from '../planCanvas';\nimport { renderIcon } from '../utils/renderIcon';\nimport type { RoomViewerProps } from './roomViewer.types';\nimport styles from './roomViewer.module.pcss';\n\nconst MIN_ZOOM = 0.002;\nconst MAX_ZOOM = 4;\n/** Past this many pixels a press is a pan rather than a click on a room. */\nconst PAN_THRESHOLD_PX = 4;\n\nfunction formatAreaDefault(areaMm2: number): string {\n const m2 = areaMm2 / 1e6;\n return `${m2 < 10 ? m2.toFixed(1) : Math.round(m2)} m²`;\n}\n\n/**\n * Read-only view of a floor plan.\n *\n * It renders the same `planCanvas` the drawer does, from the same `FloorPlan`, so the\n * two cannot drift apart. Selection and hover are React state rather than classes pushed\n * onto DOM nodes, which is what lets them be controlled from outside.\n */\nfunction RoomViewer(props: RoomViewerProps) {\n const {\n ref,\n plan,\n activeFloorId,\n defaultActiveFloorId,\n onFloorChange,\n selectedRoomId,\n defaultSelectedRoomId = null,\n onSelect,\n hoveredRoomId,\n onHoverChange,\n view,\n defaultView,\n onViewChange,\n interactive = true,\n pannable = true,\n fitOnMount = true,\n showFloorBar = true,\n showViewControls = true,\n showGrid = false,\n showRoomLabels = true,\n showOpeningSymbols = true,\n getRoomColor,\n renderRoomLabel,\n getRoomLabel,\n formatArea = formatAreaDefault,\n height = 360,\n emptyState,\n labels,\n icons,\n className,\n style,\n classNames,\n styles: slotStyles,\n 'aria-label': ariaLabel,\n ...rest\n } = useComponentDefaults('RoomViewer', props);\n\n const wrapperRef = useRef<HTMLDivElement>(null);\n const svgRef = useRef<SVGSVGElement>(null);\n const liveId = useId().replace(/:/g, '');\n\n const floors = plan?.floors ?? [];\n\n // ─── Floor ────────────────────────────────────────────────────────────────────\n\n const [floorIdState, setFloorIdState] = useState<string | undefined>(defaultActiveFloorId);\n const currentFloorId = activeFloorId ?? floorIdState ?? floors[0]?.id;\n const floor: PlanFloor | null = useMemo(\n () => (plan ? (getFloor(plan, currentFloorId) ?? getFloor(plan)) : null),\n [plan, currentFloorId],\n );\n\n const selectFloor = useCallback(\n (nextId: string) => {\n if (activeFloorId === undefined) setFloorIdState(nextId);\n onFloorChange?.(nextId);\n },\n [activeFloorId, onFloorChange],\n );\n\n const rooms = useMemo(() => (floor ? derivePlan(floor).rooms : []), [floor]);\n\n // ─── Selection and hover ──────────────────────────────────────────────────────\n\n const [selectedState, setSelectedState] = useState<string | null>(defaultSelectedRoomId);\n const selected = selectedRoomId !== undefined ? selectedRoomId : selectedState;\n\n const [hoveredState, setHoveredState] = useState<string | null>(null);\n const hovered = hoveredRoomId !== undefined ? hoveredRoomId : hoveredState;\n\n const selectRoom = useCallback(\n (roomId: string | null) => {\n if (selectedRoomId === undefined) setSelectedState(roomId);\n const room = roomId ? (rooms.find((r) => r.roomId === roomId) ?? null) : null;\n onSelect?.(roomId, room, floor?.id ?? '');\n },\n [selectedRoomId, rooms, onSelect, floor?.id],\n );\n\n const setHovered = useCallback(\n (roomId: string | null) => {\n if (hoveredRoomId === undefined) setHoveredState(roomId);\n onHoverChange?.(roomId);\n },\n [hoveredRoomId, onHoverChange],\n );\n\n // A selection made by clicking a shape is silent to a screen reader, so it is\n // announced separately rather than relying on focus landing somewhere useful.\n const announcement = (() => {\n const room = selected ? rooms.find((r) => r.roomId === selected) : undefined;\n if (!room) return labels?.noRoomSelected ?? 'No room selected';\n const name = room.meta?.name || 'Unnamed room';\n return (labels?.selectedRoom ?? '{name} selected, {area}')\n .replace('{name}', name)\n .replace('{area}', formatArea(room.area));\n })();\n\n // ─── View ─────────────────────────────────────────────────────────────────────\n\n const [viewState, setViewState] = useState<PlanView>(defaultView ?? { x: 0, y: 0, zoom: 0.05 });\n const currentView = view ?? viewState;\n const viewRef = useRef(currentView);\n viewRef.current = currentView;\n\n const applyView = useCallback(\n (next: PlanView) => {\n if (view === undefined) setViewState(next);\n onViewChange?.(next);\n },\n [view, onViewChange],\n );\n\n const userMovedRef = useRef(false);\n const [size, setSize] = useState({ width: 800, height: 360 });\n useEffect(() => {\n const element = wrapperRef.current;\n if (!element) return;\n const measure = () => {\n const rect = element.getBoundingClientRect();\n if (rect.width > 0 && rect.height > 0) {\n setSize({ width: Math.round(rect.width), height: Math.round(rect.height) });\n }\n };\n const observer = new ResizeObserver(measure);\n observer.observe(element);\n measure();\n return () => observer.disconnect();\n }, []);\n\n const fitToContent = useCallback(\n (options: { padding?: number } = {}) => {\n const padding = options.padding ?? 24;\n const bounds = floor ? floorBounds(floor) : null;\n if (!bounds || bounds.width <= 0 || bounds.height <= 0) {\n applyView({ x: -1000, y: -1000, zoom: 0.05 });\n return;\n }\n const zoom = Math.max(\n MIN_ZOOM,\n Math.min(\n MAX_ZOOM,\n Math.min((size.width - padding * 2) / bounds.width, (size.height - padding * 2) / bounds.height),\n ),\n );\n applyView({\n x: bounds.minX - (size.width / zoom - bounds.width) / 2,\n y: bounds.minY - (size.height / zoom - bounds.height) / 2,\n zoom,\n });\n },\n [floor, size.width, size.height, applyView],\n );\n\n /**\n * Refit on anything that changes what \"fitted\" means — the floor, and the canvas size,\n * which is not known until the element has been measured. The moment the viewer pans or\n * zooms, the view is theirs and we stop touching it.\n */\n useEffect(() => {\n if (!fitOnMount || userMovedRef.current) return;\n if (!floor || size.width <= 0 || Object.keys(floor.nodes).length === 0) return;\n fitToContent();\n }, [fitOnMount, floor, size.width, size.height, fitToContent]);\n\n const zoomBy = useCallback(\n (factor: number, centre?: { x: number; y: number }) => {\n userMovedRef.current = true;\n const v = viewRef.current;\n const next = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, v.zoom * factor));\n if (next === v.zoom) return;\n const cx0 = centre?.x ?? size.width / 2;\n const cy0 = centre?.y ?? size.height / 2;\n // Keep the world point under the cursor where it is.\n applyView({\n x: v.x + cx0 / v.zoom - cx0 / next,\n y: v.y + cy0 / v.zoom - cy0 / next,\n zoom: next,\n });\n },\n [applyView, size.width, size.height],\n );\n\n // ─── Pan and pinch ────────────────────────────────────────────────────────────\n\n const pointersRef = useRef(new Map<number, { x: number; y: number }>());\n const panRef = useRef<{ startClient: { x: number; y: number }; startView: PlanView; moved: boolean } | null>(null);\n const pinchRef = useRef<{ dist: number; view: PlanView; mid: { x: number; y: number } } | null>(null);\n\n const handlePointerDown = useCallback(\n (event: ReactPointerEvent<HTMLDivElement>) => {\n if (!pannable) return;\n pointersRef.current.set(event.pointerId, { x: event.clientX, y: event.clientY });\n // Deliberately NOT capturing the pointer yet. While a capture is active the click\n // is dispatched to the capturing element instead of the shape under the cursor, so\n // capturing here would mean a room could never be clicked. The capture is taken in\n // the move handler, once the press has actually turned into a pan.\n if (pointersRef.current.size === 2) {\n const [p1, p2] = [...pointersRef.current.values()];\n pinchRef.current = {\n dist: Math.hypot(p2.x - p1.x, p2.y - p1.y),\n view: viewRef.current,\n mid: { x: (p1.x + p2.x) / 2, y: (p1.y + p2.y) / 2 },\n };\n panRef.current = null;\n return;\n }\n panRef.current = {\n startClient: { x: event.clientX, y: event.clientY },\n startView: viewRef.current,\n moved: false,\n };\n },\n [pannable],\n );\n\n const handlePointerMove = useCallback(\n (event: ReactPointerEvent<HTMLDivElement>) => {\n if (pointersRef.current.has(event.pointerId)) {\n pointersRef.current.set(event.pointerId, { x: event.clientX, y: event.clientY });\n }\n\n const pinch = pinchRef.current;\n if (pinch && pointersRef.current.size >= 2) {\n const [p1, p2] = [...pointersRef.current.values()];\n const now = Math.hypot(p2.x - p1.x, p2.y - p1.y);\n if (pinch.dist <= 0) return;\n const zoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, pinch.view.zoom * (now / pinch.dist)));\n const rect = wrapperRef.current?.getBoundingClientRect() ?? { left: 0, top: 0 };\n const mid = { x: (p1.x + p2.x) / 2, y: (p1.y + p2.y) / 2 };\n userMovedRef.current = true;\n const worldMid = clientToWorld(pinch.mid.x, pinch.mid.y, rect, pinch.view);\n applyView({\n x: worldMid.x - (mid.x - rect.left) / zoom,\n y: worldMid.y - (mid.y - rect.top) / zoom,\n zoom,\n });\n return;\n }\n\n const pan = panRef.current;\n if (!pan) return;\n const dx = event.clientX - pan.startClient.x;\n const dy = event.clientY - pan.startClient.y;\n if (!pan.moved && Math.hypot(dx, dy) <= PAN_THRESHOLD_PX) return;\n if (!pan.moved) {\n (event.currentTarget as HTMLElement).setPointerCapture?.(event.pointerId);\n }\n pan.moved = true;\n userMovedRef.current = true;\n applyView({\n x: pan.startView.x - dx / pan.startView.zoom,\n y: pan.startView.y - dy / pan.startView.zoom,\n zoom: pan.startView.zoom,\n });\n },\n [applyView],\n );\n\n const handlePointerUp = useCallback((event: ReactPointerEvent<HTMLDivElement>) => {\n pointersRef.current.delete(event.pointerId);\n if (pointersRef.current.size < 2) pinchRef.current = null;\n panRef.current = null;\n }, []);\n\n // React's onWheel is passive, so it cannot preventDefault and the page scrolls instead.\n useEffect(() => {\n const element = wrapperRef.current;\n if (!element || !pannable) return;\n const onWheel = (event: WheelEvent) => {\n event.preventDefault();\n const rect = element.getBoundingClientRect();\n zoomBy(event.deltaY < 0 ? 1.1 : 1 / 1.1, {\n x: event.clientX - rect.left,\n y: event.clientY - rect.top,\n });\n };\n element.addEventListener('wheel', onWheel, { passive: false });\n return () => element.removeEventListener('wheel', onWheel);\n }, [pannable, zoomBy]);\n\n // ─── Handle ───────────────────────────────────────────────────────────────────\n\n useImperativeHandle(\n ref,\n () => ({\n fitToContent,\n getView: () => viewRef.current,\n setView: applyView,\n zoomBy: (factor: number) => zoomBy(factor),\n select: selectRoom,\n getFloorId: () => floor?.id ?? null,\n setFloorId: selectFloor,\n getSvgElement: () => svgRef.current,\n }),\n [fitToContent, applyView, zoomBy, selectRoom, floor?.id, selectFloor],\n );\n\n // ─── Render ───────────────────────────────────────────────────────────────────\n\n const selection: readonly PlanSelection[] = useMemo(\n () => (selected ? [{ type: 'room', id: selected } as PlanSelection] : []),\n [selected],\n );\n const hoveredSelection: PlanSelection | null = useMemo(\n () => (hovered ? { type: 'room', id: hovered } : null),\n [hovered],\n );\n\n const isEmpty = !floor || Object.keys(floor.walls).length === 0;\n\n return (\n <div\n {...rest}\n className={cx(styles.roomViewer, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n aria-label={ariaLabel ?? 'Floor plan'}\n >\n {showFloorBar && floors.length > 1 && (\n <div\n className={cx(styles.roomViewerFloorBar, classNames?.floorBar)}\n style={slotStyles?.floorBar}\n role='tablist'\n aria-label={labels?.floors ?? 'Floors'}\n >\n {/* Top storey first, the way a building reads in section. */}\n {[...floors].reverse().map((f) => (\n <button\n key={f.id}\n type='button'\n role='tab'\n className={cx(\n styles.roomViewerFloorTab,\n f.id === floor?.id && styles.roomViewerFloorTabActive,\n classNames?.floorTab,\n )}\n style={slotStyles?.floorTab}\n aria-selected={f.id === floor?.id}\n onClick={() => selectFloor(f.id)}\n >\n {f.label}\n </button>\n ))}\n </div>\n )}\n\n <div\n ref={wrapperRef}\n className={cx(\n styles.roomViewerCanvasWrapper,\n pannable && styles.roomViewerCanvasWrapperPannable,\n classNames?.canvasWrapper,\n )}\n style={{ height, ...slotStyles?.canvasWrapper }}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n >\n {isEmpty ? (\n <div className={cx(styles.roomViewerEmpty, classNames?.empty)} style={slotStyles?.empty}>\n {emptyState ?? labels?.empty ?? 'Nothing to show'}\n </div>\n ) : (\n <PlanCanvas\n ref={svgRef}\n floor={floor}\n rooms={rooms}\n view={currentView}\n size={size}\n selection={selection}\n hovered={hoveredSelection}\n interactiveRooms={interactive}\n showGrid={showGrid}\n showRoomLabels={showRoomLabels}\n showOpeningSymbols={showOpeningSymbols}\n getRoomColor={getRoomColor}\n renderRoomLabel={renderRoomLabel}\n getRoomLabel={getRoomLabel}\n formatArea={formatArea}\n onRoomActivate={interactive ? (roomId) => selectRoom(roomId) : undefined}\n onBackgroundActivate={interactive ? () => selectRoom(null) : undefined}\n onHoverChange={interactive ? (target) => setHovered(target?.type === 'room' ? target.id : null) : undefined}\n classNames={{\n canvas: classNames?.canvas,\n grid: classNames?.grid,\n rooms: classNames?.rooms,\n roomFill: classNames?.roomFill,\n roomLabel: classNames?.roomLabel,\n walls: classNames?.walls,\n wallBody: classNames?.wallBody,\n openings: classNames?.openings,\n opening: classNames?.opening,\n }}\n styles={{\n canvas: slotStyles?.canvas,\n grid: slotStyles?.grid,\n rooms: slotStyles?.rooms,\n roomFill: slotStyles?.roomFill,\n roomLabel: slotStyles?.roomLabel,\n walls: slotStyles?.walls,\n wallBody: slotStyles?.wallBody,\n openings: slotStyles?.openings,\n opening: slotStyles?.opening,\n }}\n aria-label={ariaLabel ?? 'Floor plan'}\n />\n )}\n\n {showViewControls && !isEmpty && (\n <div className={cx(styles.roomViewerViewControls, classNames?.viewControls)} style={slotStyles?.viewControls}>\n <button\n type='button'\n className={cx(styles.roomViewerViewButton, classNames?.viewButton)}\n style={slotStyles?.viewButton}\n title={labels?.zoomOut ?? 'Zoom out'}\n aria-label={labels?.zoomOut ?? 'Zoom out'}\n onClick={() => zoomBy(1 / 1.2)}\n >\n {renderIcon(icons?.zoomOut ?? faMagnifyingGlassMinus)}\n </button>\n <button\n type='button'\n className={cx(styles.roomViewerViewButton, classNames?.viewButton)}\n style={slotStyles?.viewButton}\n title={labels?.fit ?? 'Fit to view'}\n aria-label={labels?.fit ?? 'Fit to view'}\n onClick={() => {\n userMovedRef.current = false;\n fitToContent();\n }}\n >\n {renderIcon(icons?.fit ?? faExpand)}\n </button>\n <button\n type='button'\n className={cx(styles.roomViewerViewButton, classNames?.viewButton)}\n style={slotStyles?.viewButton}\n title={labels?.zoomIn ?? 'Zoom in'}\n aria-label={labels?.zoomIn ?? 'Zoom in'}\n onClick={() => zoomBy(1.2)}\n >\n {renderIcon(icons?.zoomIn ?? faMagnifyingGlassPlus)}\n </button>\n </div>\n )}\n </div>\n\n <div id={liveId} className={styles.roomViewerLive} role='status' aria-live='polite'>\n {announcement}\n </div>\n </div>\n );\n}\n\nexport default RoomViewer;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"roomViewer.mjs","names":[],"sources":["../../../../package/common/roomViewer/roomViewer.tsx"],"sourcesContent":["import { useCallback, useEffect, useImperativeHandle, useId, useMemo, useRef, useState } from 'react';\nimport type { PointerEvent as ReactPointerEvent } from 'react';\nimport cx from 'classnames';\nimport { faExpand, faMagnifyingGlassMinus, faMagnifyingGlassPlus } from '@fortawesome/free-solid-svg-icons';\n\nimport { useComponentDefaults, useLabels } from '../configProvider';\nimport {\n clientToWorld,\n derivePlan,\n floorBounds,\n getFloor,\n type PlanFloor,\n type PlanSelection,\n type PlanView,\n} from '../floorPlan';\nimport PlanCanvas from '../planCanvas';\nimport { renderIcon } from '../utils/renderIcon';\nimport type { RoomViewerLabels, RoomViewerProps } from './roomViewer.types';\nimport styles from './roomViewer.module.pcss';\n\nconst MIN_ZOOM = 0.002;\nconst MAX_ZOOM = 4;\n/** Past this many pixels a press is a pan rather than a click on a room. */\nconst PAN_THRESHOLD_PX = 4;\n\nfunction formatAreaDefault(areaMm2: number): string {\n const m2 = areaMm2 / 1e6;\n return `${m2 < 10 ? m2.toFixed(1) : Math.round(m2)} m²`;\n}\n\nconst DEFAULT_LABELS: Required<RoomViewerLabels> = {\n floors: 'Floors',\n zoomIn: 'Zoom in',\n zoomOut: 'Zoom out',\n fit: 'Fit to view',\n empty: 'Nothing to show',\n unnamedRoom: 'Unnamed room',\n selectedRoom: (name, area) => `${name} selected, ${area}`,\n noRoomSelected: 'No room selected',\n};\n\n/**\n * Read-only view of a floor plan.\n *\n * It renders the same `planCanvas` the drawer does, from the same `FloorPlan`, so the\n * two cannot drift apart. Selection and hover are React state rather than classes pushed\n * onto DOM nodes, which is what lets them be controlled from outside.\n */\nfunction RoomViewer(props: RoomViewerProps) {\n const {\n ref,\n plan,\n activeFloorId,\n defaultActiveFloorId,\n onFloorChange,\n selectedRoomId,\n defaultSelectedRoomId = null,\n onSelect,\n hoveredRoomId,\n onHoverChange,\n view,\n defaultView,\n onViewChange,\n interactive = true,\n pannable = true,\n fitOnMount = true,\n showFloorBar = true,\n showViewControls = true,\n showGrid = false,\n showRoomLabels = true,\n showOpeningSymbols = true,\n getRoomColor,\n renderRoomLabel,\n getRoomLabel,\n formatArea = formatAreaDefault,\n height = 360,\n emptyState,\n labels,\n icons,\n className,\n style,\n classNames,\n styles: slotStyles,\n 'aria-label': ariaLabel,\n ...rest\n } = useComponentDefaults('RoomViewer', props);\n const text = useLabels('RoomViewer', labels, DEFAULT_LABELS);\n\n const wrapperRef = useRef<HTMLDivElement>(null);\n const svgRef = useRef<SVGSVGElement>(null);\n const liveId = useId().replace(/:/g, '');\n\n const floors = plan?.floors ?? [];\n\n // ─── Floor ────────────────────────────────────────────────────────────────────\n\n const [floorIdState, setFloorIdState] = useState<string | undefined>(defaultActiveFloorId);\n const currentFloorId = activeFloorId ?? floorIdState ?? floors[0]?.id;\n const floor: PlanFloor | null = useMemo(\n () => (plan ? (getFloor(plan, currentFloorId) ?? getFloor(plan)) : null),\n [plan, currentFloorId],\n );\n\n const selectFloor = useCallback(\n (nextId: string) => {\n if (activeFloorId === undefined) setFloorIdState(nextId);\n onFloorChange?.(nextId);\n },\n [activeFloorId, onFloorChange],\n );\n\n const rooms = useMemo(() => (floor ? derivePlan(floor).rooms : []), [floor]);\n\n // ─── Selection and hover ──────────────────────────────────────────────────────\n\n const [selectedState, setSelectedState] = useState<string | null>(defaultSelectedRoomId);\n const selected = selectedRoomId !== undefined ? selectedRoomId : selectedState;\n\n const [hoveredState, setHoveredState] = useState<string | null>(null);\n const hovered = hoveredRoomId !== undefined ? hoveredRoomId : hoveredState;\n\n const selectRoom = useCallback(\n (roomId: string | null) => {\n if (selectedRoomId === undefined) setSelectedState(roomId);\n const room = roomId ? (rooms.find((r) => r.roomId === roomId) ?? null) : null;\n onSelect?.(roomId, room, floor?.id ?? '');\n },\n [selectedRoomId, rooms, onSelect, floor?.id],\n );\n\n const setHovered = useCallback(\n (roomId: string | null) => {\n if (hoveredRoomId === undefined) setHoveredState(roomId);\n onHoverChange?.(roomId);\n },\n [hoveredRoomId, onHoverChange],\n );\n\n // A selection made by clicking a shape is silent to a screen reader, so it is\n // announced separately rather than relying on focus landing somewhere useful.\n const announcement = (() => {\n const room = selected ? rooms.find((r) => r.roomId === selected) : undefined;\n if (!room) return text.noRoomSelected;\n return text.selectedRoom(room.meta?.name || text.unnamedRoom, formatArea(room.area));\n })();\n\n // ─── View ─────────────────────────────────────────────────────────────────────\n\n const [viewState, setViewState] = useState<PlanView>(defaultView ?? { x: 0, y: 0, zoom: 0.05 });\n const currentView = view ?? viewState;\n const viewRef = useRef(currentView);\n viewRef.current = currentView;\n\n const applyView = useCallback(\n (next: PlanView) => {\n if (view === undefined) setViewState(next);\n onViewChange?.(next);\n },\n [view, onViewChange],\n );\n\n const userMovedRef = useRef(false);\n const [size, setSize] = useState({ width: 800, height: 360 });\n useEffect(() => {\n const element = wrapperRef.current;\n if (!element) return;\n const measure = () => {\n const rect = element.getBoundingClientRect();\n if (rect.width > 0 && rect.height > 0) {\n setSize({ width: Math.round(rect.width), height: Math.round(rect.height) });\n }\n };\n const observer = new ResizeObserver(measure);\n observer.observe(element);\n measure();\n return () => observer.disconnect();\n }, []);\n\n const fitToContent = useCallback(\n (options: { padding?: number } = {}) => {\n const padding = options.padding ?? 24;\n const bounds = floor ? floorBounds(floor) : null;\n if (!bounds || bounds.width <= 0 || bounds.height <= 0) {\n applyView({ x: -1000, y: -1000, zoom: 0.05 });\n return;\n }\n const zoom = Math.max(\n MIN_ZOOM,\n Math.min(\n MAX_ZOOM,\n Math.min((size.width - padding * 2) / bounds.width, (size.height - padding * 2) / bounds.height),\n ),\n );\n applyView({\n x: bounds.minX - (size.width / zoom - bounds.width) / 2,\n y: bounds.minY - (size.height / zoom - bounds.height) / 2,\n zoom,\n });\n },\n [floor, size.width, size.height, applyView],\n );\n\n /**\n * Refit on anything that changes what \"fitted\" means — the floor, and the canvas size,\n * which is not known until the element has been measured. The moment the viewer pans or\n * zooms, the view is theirs and we stop touching it.\n */\n useEffect(() => {\n if (!fitOnMount || userMovedRef.current) return;\n if (!floor || size.width <= 0 || Object.keys(floor.nodes).length === 0) return;\n fitToContent();\n }, [fitOnMount, floor, size.width, size.height, fitToContent]);\n\n const zoomBy = useCallback(\n (factor: number, centre?: { x: number; y: number }) => {\n userMovedRef.current = true;\n const v = viewRef.current;\n const next = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, v.zoom * factor));\n if (next === v.zoom) return;\n const cx0 = centre?.x ?? size.width / 2;\n const cy0 = centre?.y ?? size.height / 2;\n // Keep the world point under the cursor where it is.\n applyView({\n x: v.x + cx0 / v.zoom - cx0 / next,\n y: v.y + cy0 / v.zoom - cy0 / next,\n zoom: next,\n });\n },\n [applyView, size.width, size.height],\n );\n\n // ─── Pan and pinch ────────────────────────────────────────────────────────────\n\n const pointersRef = useRef(new Map<number, { x: number; y: number }>());\n const panRef = useRef<{ startClient: { x: number; y: number }; startView: PlanView; moved: boolean } | null>(null);\n const pinchRef = useRef<{ dist: number; view: PlanView; mid: { x: number; y: number } } | null>(null);\n\n const handlePointerDown = useCallback(\n (event: ReactPointerEvent<HTMLDivElement>) => {\n if (!pannable) return;\n pointersRef.current.set(event.pointerId, { x: event.clientX, y: event.clientY });\n // Deliberately NOT capturing the pointer yet. While a capture is active the click\n // is dispatched to the capturing element instead of the shape under the cursor, so\n // capturing here would mean a room could never be clicked. The capture is taken in\n // the move handler, once the press has actually turned into a pan.\n if (pointersRef.current.size === 2) {\n const [p1, p2] = [...pointersRef.current.values()];\n pinchRef.current = {\n dist: Math.hypot(p2.x - p1.x, p2.y - p1.y),\n view: viewRef.current,\n mid: { x: (p1.x + p2.x) / 2, y: (p1.y + p2.y) / 2 },\n };\n panRef.current = null;\n return;\n }\n panRef.current = {\n startClient: { x: event.clientX, y: event.clientY },\n startView: viewRef.current,\n moved: false,\n };\n },\n [pannable],\n );\n\n const handlePointerMove = useCallback(\n (event: ReactPointerEvent<HTMLDivElement>) => {\n if (pointersRef.current.has(event.pointerId)) {\n pointersRef.current.set(event.pointerId, { x: event.clientX, y: event.clientY });\n }\n\n const pinch = pinchRef.current;\n if (pinch && pointersRef.current.size >= 2) {\n const [p1, p2] = [...pointersRef.current.values()];\n const now = Math.hypot(p2.x - p1.x, p2.y - p1.y);\n if (pinch.dist <= 0) return;\n const zoom = Math.max(MIN_ZOOM, Math.min(MAX_ZOOM, pinch.view.zoom * (now / pinch.dist)));\n const rect = wrapperRef.current?.getBoundingClientRect() ?? { left: 0, top: 0 };\n const mid = { x: (p1.x + p2.x) / 2, y: (p1.y + p2.y) / 2 };\n userMovedRef.current = true;\n const worldMid = clientToWorld(pinch.mid.x, pinch.mid.y, rect, pinch.view);\n applyView({\n x: worldMid.x - (mid.x - rect.left) / zoom,\n y: worldMid.y - (mid.y - rect.top) / zoom,\n zoom,\n });\n return;\n }\n\n const pan = panRef.current;\n if (!pan) return;\n const dx = event.clientX - pan.startClient.x;\n const dy = event.clientY - pan.startClient.y;\n if (!pan.moved && Math.hypot(dx, dy) <= PAN_THRESHOLD_PX) return;\n if (!pan.moved) {\n (event.currentTarget as HTMLElement).setPointerCapture?.(event.pointerId);\n }\n pan.moved = true;\n userMovedRef.current = true;\n applyView({\n x: pan.startView.x - dx / pan.startView.zoom,\n y: pan.startView.y - dy / pan.startView.zoom,\n zoom: pan.startView.zoom,\n });\n },\n [applyView],\n );\n\n const handlePointerUp = useCallback((event: ReactPointerEvent<HTMLDivElement>) => {\n pointersRef.current.delete(event.pointerId);\n if (pointersRef.current.size < 2) pinchRef.current = null;\n panRef.current = null;\n }, []);\n\n // React's onWheel is passive, so it cannot preventDefault and the page scrolls instead.\n useEffect(() => {\n const element = wrapperRef.current;\n if (!element || !pannable) return;\n const onWheel = (event: WheelEvent) => {\n event.preventDefault();\n const rect = element.getBoundingClientRect();\n zoomBy(event.deltaY < 0 ? 1.1 : 1 / 1.1, {\n x: event.clientX - rect.left,\n y: event.clientY - rect.top,\n });\n };\n element.addEventListener('wheel', onWheel, { passive: false });\n return () => element.removeEventListener('wheel', onWheel);\n }, [pannable, zoomBy]);\n\n // ─── Handle ───────────────────────────────────────────────────────────────────\n\n useImperativeHandle(\n ref,\n () => ({\n fitToContent,\n getView: () => viewRef.current,\n setView: applyView,\n zoomBy: (factor: number) => zoomBy(factor),\n select: selectRoom,\n getFloorId: () => floor?.id ?? null,\n setFloorId: selectFloor,\n getSvgElement: () => svgRef.current,\n }),\n [fitToContent, applyView, zoomBy, selectRoom, floor?.id, selectFloor],\n );\n\n // ─── Render ───────────────────────────────────────────────────────────────────\n\n const selection: readonly PlanSelection[] = useMemo(\n () => (selected ? [{ type: 'room', id: selected } as PlanSelection] : []),\n [selected],\n );\n const hoveredSelection: PlanSelection | null = useMemo(\n () => (hovered ? { type: 'room', id: hovered } : null),\n [hovered],\n );\n\n const isEmpty = !floor || Object.keys(floor.walls).length === 0;\n\n return (\n <div\n {...rest}\n className={cx(styles.roomViewer, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n aria-label={ariaLabel ?? 'Floor plan'}\n >\n {showFloorBar && floors.length > 1 && (\n <div\n className={cx(styles.roomViewerFloorBar, classNames?.floorBar)}\n style={slotStyles?.floorBar}\n role='tablist'\n aria-label={text.floors}\n >\n {/* Top storey first, the way a building reads in section. */}\n {[...floors].reverse().map((f) => (\n <button\n key={f.id}\n type='button'\n role='tab'\n className={cx(\n styles.roomViewerFloorTab,\n f.id === floor?.id && styles.roomViewerFloorTabActive,\n classNames?.floorTab,\n )}\n style={slotStyles?.floorTab}\n aria-selected={f.id === floor?.id}\n onClick={() => selectFloor(f.id)}\n >\n {f.label}\n </button>\n ))}\n </div>\n )}\n\n <div\n ref={wrapperRef}\n className={cx(\n styles.roomViewerCanvasWrapper,\n pannable && styles.roomViewerCanvasWrapperPannable,\n classNames?.canvasWrapper,\n )}\n style={{ height, ...slotStyles?.canvasWrapper }}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onPointerCancel={handlePointerUp}\n >\n {isEmpty ? (\n <div className={cx(styles.roomViewerEmpty, classNames?.empty)} style={slotStyles?.empty}>\n {emptyState ?? text.empty}\n </div>\n ) : (\n <PlanCanvas\n ref={svgRef}\n floor={floor}\n rooms={rooms}\n view={currentView}\n size={size}\n selection={selection}\n hovered={hoveredSelection}\n interactiveRooms={interactive}\n showGrid={showGrid}\n showRoomLabels={showRoomLabels}\n showOpeningSymbols={showOpeningSymbols}\n getRoomColor={getRoomColor}\n renderRoomLabel={renderRoomLabel}\n getRoomLabel={\n getRoomLabel ?? ((room, { area }) => `${room?.name || text.unnamedRoom}, ${formatArea(area)}`)\n }\n formatArea={formatArea}\n onRoomActivate={interactive ? (roomId) => selectRoom(roomId) : undefined}\n onBackgroundActivate={interactive ? () => selectRoom(null) : undefined}\n onHoverChange={interactive ? (target) => setHovered(target?.type === 'room' ? target.id : null) : undefined}\n classNames={{\n canvas: classNames?.canvas,\n grid: classNames?.grid,\n rooms: classNames?.rooms,\n roomFill: classNames?.roomFill,\n roomLabel: classNames?.roomLabel,\n walls: classNames?.walls,\n wallBody: classNames?.wallBody,\n openings: classNames?.openings,\n opening: classNames?.opening,\n }}\n styles={{\n canvas: slotStyles?.canvas,\n grid: slotStyles?.grid,\n rooms: slotStyles?.rooms,\n roomFill: slotStyles?.roomFill,\n roomLabel: slotStyles?.roomLabel,\n walls: slotStyles?.walls,\n wallBody: slotStyles?.wallBody,\n openings: slotStyles?.openings,\n opening: slotStyles?.opening,\n }}\n aria-label={ariaLabel ?? 'Floor plan'}\n />\n )}\n\n {showViewControls && !isEmpty && (\n <div className={cx(styles.roomViewerViewControls, classNames?.viewControls)} style={slotStyles?.viewControls}>\n <button\n type='button'\n className={cx(styles.roomViewerViewButton, classNames?.viewButton)}\n style={slotStyles?.viewButton}\n title={text.zoomOut}\n aria-label={text.zoomOut}\n onClick={() => zoomBy(1 / 1.2)}\n >\n {renderIcon(icons?.zoomOut ?? faMagnifyingGlassMinus)}\n </button>\n <button\n type='button'\n className={cx(styles.roomViewerViewButton, classNames?.viewButton)}\n style={slotStyles?.viewButton}\n title={text.fit}\n aria-label={text.fit}\n onClick={() => {\n userMovedRef.current = false;\n fitToContent();\n }}\n >\n {renderIcon(icons?.fit ?? faExpand)}\n </button>\n <button\n type='button'\n className={cx(styles.roomViewerViewButton, classNames?.viewButton)}\n style={slotStyles?.viewButton}\n title={text.zoomIn}\n aria-label={text.zoomIn}\n onClick={() => zoomBy(1.2)}\n >\n {renderIcon(icons?.zoomIn ?? faMagnifyingGlassPlus)}\n </button>\n </div>\n )}\n </div>\n\n <div id={liveId} className={styles.roomViewerLive} role='status' aria-live='polite'>\n {announcement}\n </div>\n </div>\n );\n}\n\nexport default RoomViewer;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sectionHeader.mjs","names":[],"sources":["../../../../package/common/sectionHeader/sectionHeader.tsx"],"sourcesContent":["import React from 'react';\nimport type { ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport { SectionHeaderSize } from './sectionHeader.types';\nimport type { SectionHeaderProps, SectionHeaderAction } from './sectionHeader.types';\nimport styles from './sectionHeader.module.pcss';\nimport ActionIcon from '../actionIcon';\nimport Divider from '../divider';\nimport { useComponentDefaults } from '../configProvider';\nimport { renderIcon } from '../utils/renderIcon';\n\nconst CLASS_BY_SIZE: Record<SectionHeaderSize, string> = {\n [SectionHeaderSize.Small]: styles.sectionHeaderSizeSmall,\n [SectionHeaderSize.Medium]: styles.sectionHeaderSizeMedium,\n [SectionHeaderSize.Large]: styles.sectionHeaderSizeLarge,\n};\n\nfunction SectionHeader(props: SectionHeaderProps): ReactElement {\n const {\n title,\n subtitle,\n icon,\n thumbnail,\n left,\n center,\n actions,\n level = 2,\n size = SectionHeaderSize.Medium,\n divider = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('SectionHeader', props);\n\n const thumbnailUrl = typeof thumbnail === 'string' && thumbnail.startsWith('http') ? thumbnail : undefined;\n const hasThumbnail = thumbnail != null && thumbnail !== '';\n const hasLeading = hasThumbnail || icon != null;\n\n const Heading = `h${level}` as keyof React.JSX.IntrinsicElements;\n\n return (\n <>\n <div\n {...rest}\n className={cx(styles.sectionHeader, CLASS_BY_SIZE[size], className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n >\n <div className={cx(styles.sectionHeaderIdentity, classNames?.identity)} style={slotStyles?.identity}>\n {hasLeading && (\n <div\n className={cx(styles.sectionHeaderLeading, classNames?.leading)}\n style={{\n ...(thumbnailUrl ? { backgroundImage: `url(${thumbnailUrl})` } : {}),\n ...slotStyles?.leading,\n }}\n >\n {hasThumbnail ? !thumbnailUrl && thumbnail : icon ? renderIcon(icon) : null}\n </div>\n )}\n\n <div className={cx(styles.sectionHeaderTitles, classNames?.titles)} style={slotStyles?.titles}>\n <Heading\n className={cx(styles.sectionHeaderTitle, classNames?.title)}\n style={slotStyles?.title}\n // The title renders on a single line and truncates with an ellipsis,\n // so expose the full text on hover when it's plain text.\n title={typeof title === 'string' ? title : undefined}\n >\n {title}\n </Heading>\n {subtitle != null && subtitle !== '' && (\n <div className={cx(styles.sectionHeaderSubtitle, classNames?.subtitle)} style={slotStyles?.subtitle}>\n {subtitle}\n </div>\n )}\n </div>\n </div>\n\n <div className={cx(styles.sectionHeaderTrailing, classNames?.trailing)} style={slotStyles?.trailing}>\n <div className={cx(styles.sectionHeaderLeft, classNames?.left)} style={slotStyles?.left}>\n {left}\n </div>\n\n <div className={cx(styles.sectionHeaderCenter, classNames?.center)} style={slotStyles?.center}>\n {center}\n </div>\n\n <div className={cx(styles.sectionHeaderActions, classNames?.actions)} style={slotStyles?.actions}>\n {Array.isArray(actions)\n ? (actions as SectionHeaderAction[]).map((action, index) => (\n <ActionIcon\n key={index}\n title={action.title}\n onClick={\n action.onClick\n ? (e: React.MouseEvent<
|
|
1
|
+
{"version":3,"file":"sectionHeader.mjs","names":[],"sources":["../../../../package/common/sectionHeader/sectionHeader.tsx"],"sourcesContent":["import React from 'react';\nimport type { ReactElement } from 'react';\nimport cx from 'classnames';\n\nimport { SectionHeaderSize } from './sectionHeader.types';\nimport type { SectionHeaderProps, SectionHeaderAction } from './sectionHeader.types';\nimport styles from './sectionHeader.module.pcss';\nimport ActionIcon from '../actionIcon';\nimport Divider from '../divider';\nimport { useComponentDefaults } from '../configProvider';\nimport { renderIcon } from '../utils/renderIcon';\n\nconst CLASS_BY_SIZE: Record<SectionHeaderSize, string> = {\n [SectionHeaderSize.Small]: styles.sectionHeaderSizeSmall,\n [SectionHeaderSize.Medium]: styles.sectionHeaderSizeMedium,\n [SectionHeaderSize.Large]: styles.sectionHeaderSizeLarge,\n};\n\nfunction SectionHeader(props: SectionHeaderProps): ReactElement {\n const {\n title,\n subtitle,\n icon,\n thumbnail,\n left,\n center,\n actions,\n level = 2,\n size = SectionHeaderSize.Medium,\n divider = false,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('SectionHeader', props);\n\n const thumbnailUrl = typeof thumbnail === 'string' && thumbnail.startsWith('http') ? thumbnail : undefined;\n const hasThumbnail = thumbnail != null && thumbnail !== '';\n const hasLeading = hasThumbnail || icon != null;\n\n const Heading = `h${level}` as keyof React.JSX.IntrinsicElements;\n\n return (\n <>\n <div\n {...rest}\n className={cx(styles.sectionHeader, CLASS_BY_SIZE[size], className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n >\n <div className={cx(styles.sectionHeaderIdentity, classNames?.identity)} style={slotStyles?.identity}>\n {hasLeading && (\n <div\n className={cx(styles.sectionHeaderLeading, classNames?.leading)}\n style={{\n ...(thumbnailUrl ? { backgroundImage: `url(${thumbnailUrl})` } : {}),\n ...slotStyles?.leading,\n }}\n >\n {hasThumbnail ? !thumbnailUrl && thumbnail : icon ? renderIcon(icon) : null}\n </div>\n )}\n\n <div className={cx(styles.sectionHeaderTitles, classNames?.titles)} style={slotStyles?.titles}>\n <Heading\n className={cx(styles.sectionHeaderTitle, classNames?.title)}\n style={slotStyles?.title}\n // The title renders on a single line and truncates with an ellipsis,\n // so expose the full text on hover when it's plain text.\n title={typeof title === 'string' ? title : undefined}\n >\n {title}\n </Heading>\n {subtitle != null && subtitle !== '' && (\n <div className={cx(styles.sectionHeaderSubtitle, classNames?.subtitle)} style={slotStyles?.subtitle}>\n {subtitle}\n </div>\n )}\n </div>\n </div>\n\n <div className={cx(styles.sectionHeaderTrailing, classNames?.trailing)} style={slotStyles?.trailing}>\n <div className={cx(styles.sectionHeaderLeft, classNames?.left)} style={slotStyles?.left}>\n {left}\n </div>\n\n <div className={cx(styles.sectionHeaderCenter, classNames?.center)} style={slotStyles?.center}>\n {center}\n </div>\n\n <div className={cx(styles.sectionHeaderActions, classNames?.actions)} style={slotStyles?.actions}>\n {Array.isArray(actions)\n ? (actions as SectionHeaderAction[]).map((action, index) => (\n <ActionIcon\n key={index}\n title={action.title}\n onClick={\n action.onClick\n ? (e: React.MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation();\n action.onClick?.(e);\n }\n : undefined\n }\n icon={action.icon}\n />\n ))\n : (actions as React.ReactNode)}\n </div>\n </div>\n </div>\n {divider && <Divider className={styles.sectionHeaderDivider} />}\n </>\n );\n}\n\nexport default SectionHeader;\n"],"mappings":"sbAYA,IAAM,EAAmD,EACtD,EAAkB,OAAQ,EAAO,wBACjC,EAAkB,QAAS,EAAO,yBAClC,EAAkB,OAAQ,EAAO,sBACpC,EAEA,SAAS,EAAc,EAAyC,CAC9D,GAAM,CACJ,QACA,WACA,OACA,YACA,OACA,SACA,UACA,QAAQ,EACR,OAAO,EAAkB,OACzB,UAAU,GACV,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACD,EAAqB,gBAAiB,CAAK,EAEzC,EAAe,OAAO,GAAc,UAAY,EAAU,WAAW,MAAM,EAAI,EAAY,IAAA,GAC3F,EAAe,GAAa,MAAQ,IAAc,GAClD,EAAa,GAAgB,GAAQ,KAErC,EAAU,IAAI,IAEpB,OACE,EAAA,EAAA,CAAA,SAAA,CACE,EAAC,MAAD,CACE,GAAI,EACJ,UAAW,EAAG,EAAO,cAAe,EAAc,GAAO,EAAW,GAAY,IAAI,EACpF,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,EAHzC,SAAA,CAKE,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,sBAAuB,GAAY,QAAQ,EAAG,MAAO,GAAY,SAA3F,SAAA,CACG,GACC,EAAC,MAAD,CACE,UAAW,EAAG,EAAO,qBAAsB,GAAY,OAAO,EAC9D,MAAO,CACL,GAAI,EAAe,CAAE,gBAAiB,OAAO,EAAa,EAAG,EAAI,CAAC,EAClE,GAAG,GAAY,OACjB,EAEC,SAAA,EAAe,CAAC,GAAgB,EAAY,EAAO,EAAW,CAAI,EAAI,IACpE,CAAA,EAGP,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,oBAAqB,GAAY,MAAM,EAAG,MAAO,GAAY,OAAvF,SAAA,CACE,EAAC,EAAD,CACE,UAAW,EAAG,EAAO,mBAAoB,GAAY,KAAK,EAC1D,MAAO,GAAY,MAGnB,MAAO,OAAO,GAAU,SAAW,EAAQ,IAAA,GAE1C,SAAA,CACM,CAAA,EACR,GAAY,MAAQ,IAAa,IAChC,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,sBAAuB,GAAY,QAAQ,EAAG,MAAO,GAAY,SACxF,SAAA,CACE,CAAA,CAEJ,CACF,CAAA,CAAA,CAEL,CAAA,EAAA,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,sBAAuB,GAAY,QAAQ,EAAG,MAAO,GAAY,SAA3F,SAAA,CACE,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,kBAAmB,GAAY,IAAI,EAAG,MAAO,GAAY,KAChF,SAAA,CACE,CAAA,EAEL,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,oBAAqB,GAAY,MAAM,EAAG,MAAO,GAAY,OACpF,SAAA,CACE,CAAA,EAEL,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,qBAAsB,GAAY,OAAO,EAAG,MAAO,GAAY,QACtF,SAAA,MAAM,QAAQ,CAAO,EACjB,EAAkC,KAAK,EAAQ,IAC9C,EAAC,EAAD,CAEE,MAAO,EAAO,MACd,QACE,EAAO,QACF,GAA2C,CAC1C,EAAE,gBAAgB,EAClB,EAAO,UAAU,CAAC,CACpB,EACA,IAAA,GAEN,KAAM,EAAO,IACd,EAXM,CAWN,CACF,EACA,CACF,CAAA,CACF,CACF,CAAA,CAAA,CACJ,CAAA,EAAA,GAAW,EAAC,EAAD,CAAS,UAAW,EAAO,oBAAuB,CAAA,CAC9D,CAAA,CAAA,CAEN"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{useLabels as t}from"../configProvider/useLabels.mjs";import{ButtonSize as
|
|
1
|
+
"use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{useLabels as t}from"../configProvider/useLabels.mjs";import{ThemeColor as n}from"../themeProvider/color.types.mjs";import{ButtonSize as r,ButtonStyleType as i}from"../button/button.types.mjs";import a from"../button/button.mjs";import{PopoverAlign as o,PopoverPlacement as s}from"../popover/popover.types.mjs";import c from"../buttonGroup/buttonGroup.mjs";import l from"../menu/menu.mjs";import u from"./splitButton.module.mjs";import{useState as d}from"react";import f from"classnames";import{faChevronDown as p}from"@fortawesome/free-solid-svg-icons";import{jsx as m,jsxs as h}from"react/jsx-runtime";var g={moreActions:`More actions`};function _(_){let{children:v,onClick:y=()=>{},actions:b=[],styleType:x=i.Filled,color:S=n.Primary,size:C=r.Default,disabled:w=!1,isLoading:T=!1,align:E=o.End,className:D,style:O,classNames:k,styles:A,labels:j,...M}=e(`SplitButton`,_),N=t(`SplitButton`,j,g),[P,F]=d(!1),[I,L]=d(w);return w!==I&&(L(w),w&&F(!1)),h(c,{...M,className:f(u.splitButton,k?.root,D),style:{...O,...A?.root},children:[m(a,{styleType:x,color:S,size:C,disabled:w,isLoading:T,onClick:y,className:f(u.splitButtonPrimary,k?.primaryButton),style:A?.primaryButton,children:v}),m(l,{items:b,isOpen:P,onOpenChange:F,placement:s.Bottom,align:E,classNames:{menu:k?.menu,item:k?.menuItem},styles:{menu:A?.menu,item:A?.menuItem},children:m(a,{styleType:x,color:S,size:C,disabled:w,icon:p,"aria-label":N.moreActions,className:f(u.splitButtonTrigger,k?.triggerButton),style:A?.triggerButton})})]})}export{_ as default};
|
|
2
2
|
//# sourceMappingURL=splitButton.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"splitButton.mjs","names":[],"sources":["../../../../package/common/splitButton/splitButton.tsx"],"sourcesContent":["import { useState } from 'react';\nimport cx from 'classnames';\nimport { faChevronDown } from '@fortawesome/free-solid-svg-icons';\n\nimport Button from '../button';\nimport { ButtonStyleType, ButtonSize } from '../button/button.types';\nimport ButtonGroup from '../buttonGroup';\nimport Menu from '../menu';\nimport { PopoverAlign, PopoverPlacement } from '../popover/popover.types';\nimport { useComponentDefaults, useLabels } from '../configProvider';\nimport type { SplitButtonLabels, SplitButtonProps } from './splitButton.types';\n\nimport styles from './splitButton.module.pcss';\n\nconst DEFAULT_LABELS: Required<SplitButtonLabels> = {\n moreActions: 'More actions',\n};\n\nfunction SplitButton(props: SplitButtonProps) {\n const {\n children,\n onClick = () => {},\n actions = [],\n styleType = ButtonStyleType.Primary,\n size = ButtonSize.Default,\n disabled = false,\n isLoading = false,\n align = PopoverAlign.End,\n className,\n style,\n classNames,\n styles: slotStyles,\n labels,\n ...rest\n } = useComponentDefaults('SplitButton', props);\n const text = useLabels('SplitButton', labels, DEFAULT_LABELS);\n\n const [isOpen, setIsOpen] = useState(false);\n\n // Adjusting state during render (not in an effect) on a prop change is the documented React\n // pattern for this: closing the menu as soon as `disabled` becomes true, without an extra\n // render tick or a setState-in-effect lint violation.\n const [prevDisabled, setPrevDisabled] = useState(disabled);\n if (disabled !== prevDisabled) {\n setPrevDisabled(disabled);\n if (disabled) setIsOpen(false);\n }\n\n return (\n <ButtonGroup\n {...rest}\n className={cx(styles.splitButton, classNames?.root, className)}\n style={{ ...style, ...slotStyles?.root }}\n >\n <Button\n styleType={styleType}\n size={size}\n disabled={disabled}\n isLoading={isLoading}\n onClick={onClick}\n className={cx(styles.splitButtonPrimary, classNames?.primaryButton)}\n style={slotStyles?.primaryButton}\n >\n {children}\n </Button>\n\n {/* The list, its keys, its focus and its menu semantics are Menu's; this\n component only welds a second button to the first. */}\n <Menu\n items={actions}\n isOpen={isOpen}\n onOpenChange={setIsOpen}\n placement={PopoverPlacement.Bottom}\n align={align}\n classNames={{ menu: classNames?.menu, item: classNames?.menuItem }}\n styles={{ menu: slotStyles?.menu, item: slotStyles?.menuItem }}\n >\n <Button\n styleType={styleType}\n size={size}\n disabled={disabled}\n icon={faChevronDown}\n aria-label={text.moreActions}\n className={cx(styles.splitButtonTrigger, classNames?.triggerButton)}\n style={slotStyles?.triggerButton}\n />\n </Menu>\n </ButtonGroup>\n );\n}\n\nexport default SplitButton;\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"splitButton.mjs","names":[],"sources":["../../../../package/common/splitButton/splitButton.tsx"],"sourcesContent":["import { useState } from 'react';\nimport cx from 'classnames';\nimport { faChevronDown } from '@fortawesome/free-solid-svg-icons';\n\nimport Button from '../button';\nimport { ButtonStyleType, ButtonSize } from '../button/button.types';\nimport ButtonGroup from '../buttonGroup';\nimport Menu from '../menu';\nimport { PopoverAlign, PopoverPlacement } from '../popover/popover.types';\nimport { useComponentDefaults, useLabels } from '../configProvider';\nimport type { SplitButtonLabels, SplitButtonProps } from './splitButton.types';\n\nimport styles from './splitButton.module.pcss';\nimport { ThemeColor } from '../themeProvider/color.types';\n\nconst DEFAULT_LABELS: Required<SplitButtonLabels> = {\n moreActions: 'More actions',\n};\n\nfunction SplitButton(props: SplitButtonProps) {\n const {\n children,\n onClick = () => {},\n actions = [],\n styleType = ButtonStyleType.Filled,\n color = ThemeColor.Primary,\n size = ButtonSize.Default,\n disabled = false,\n isLoading = false,\n align = PopoverAlign.End,\n className,\n style,\n classNames,\n styles: slotStyles,\n labels,\n ...rest\n } = useComponentDefaults('SplitButton', props);\n const text = useLabels('SplitButton', labels, DEFAULT_LABELS);\n\n const [isOpen, setIsOpen] = useState(false);\n\n // Adjusting state during render (not in an effect) on a prop change is the documented React\n // pattern for this: closing the menu as soon as `disabled` becomes true, without an extra\n // render tick or a setState-in-effect lint violation.\n const [prevDisabled, setPrevDisabled] = useState(disabled);\n if (disabled !== prevDisabled) {\n setPrevDisabled(disabled);\n if (disabled) setIsOpen(false);\n }\n\n return (\n <ButtonGroup\n {...rest}\n className={cx(styles.splitButton, classNames?.root, className)}\n style={{ ...style, ...slotStyles?.root }}\n >\n <Button\n styleType={styleType}\n color={color}\n size={size}\n disabled={disabled}\n isLoading={isLoading}\n onClick={onClick}\n className={cx(styles.splitButtonPrimary, classNames?.primaryButton)}\n style={slotStyles?.primaryButton}\n >\n {children}\n </Button>\n\n {/* The list, its keys, its focus and its menu semantics are Menu's; this\n component only welds a second button to the first. */}\n <Menu\n items={actions}\n isOpen={isOpen}\n onOpenChange={setIsOpen}\n placement={PopoverPlacement.Bottom}\n align={align}\n classNames={{ menu: classNames?.menu, item: classNames?.menuItem }}\n styles={{ menu: slotStyles?.menu, item: slotStyles?.menuItem }}\n >\n <Button\n styleType={styleType}\n color={color}\n size={size}\n disabled={disabled}\n icon={faChevronDown}\n aria-label={text.moreActions}\n className={cx(styles.splitButtonTrigger, classNames?.triggerButton)}\n style={slotStyles?.triggerButton}\n />\n </Menu>\n </ButtonGroup>\n );\n}\n\nexport default SplitButton;\n"],"mappings":"isBAeA,IAAM,EAA8C,CAClD,YAAa,cACf,EAEA,SAAS,EAAY,EAAyB,CAC5C,GAAM,CACJ,WACA,cAAgB,CAAC,EACjB,UAAU,CAAC,EACX,YAAY,EAAgB,OAC5B,QAAQ,EAAW,QACnB,OAAO,EAAW,QAClB,WAAW,GACX,YAAY,GACZ,QAAQ,EAAa,IACrB,YACA,QACA,aACA,OAAQ,EACR,SACA,GAAG,GACD,EAAqB,cAAe,CAAK,EACvC,EAAO,EAAU,cAAe,EAAQ,CAAc,EAEtD,CAAC,EAAQ,GAAa,EAAS,EAAK,EAKpC,CAAC,EAAc,GAAmB,EAAS,CAAQ,EAMzD,OALI,IAAa,IACf,EAAgB,CAAQ,EACpB,GAAU,EAAU,EAAK,GAI7B,EAAC,EAAD,CACE,GAAI,EACJ,UAAW,EAAG,EAAO,YAAa,GAAY,KAAM,CAAS,EAC7D,MAAO,CAAE,GAAG,EAAO,GAAG,GAAY,IAAK,EAHzC,SAAA,CAKE,EAAC,EAAD,CACa,YACJ,QACD,OACI,WACC,YACF,UACT,UAAW,EAAG,EAAO,mBAAoB,GAAY,aAAa,EAClE,MAAO,GAAY,cAElB,UACK,CAAA,EAIR,EAAC,EAAD,CACE,MAAO,EACC,SACR,aAAc,EACd,UAAW,EAAiB,OACrB,QACP,WAAY,CAAE,KAAM,GAAY,KAAM,KAAM,GAAY,QAAS,EACjE,OAAQ,CAAE,KAAM,GAAY,KAAM,KAAM,GAAY,QAAS,EAE7D,SAAA,EAAC,EAAD,CACa,YACJ,QACD,OACI,WACV,KAAM,EACN,aAAY,EAAK,YACjB,UAAW,EAAG,EAAO,mBAAoB,GAAY,aAAa,EAClE,MAAO,GAAY,aACpB,CAAA,CACG,CAAA,CACK,GAEjB"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use client";import{isDev as e}from"../utils/isDev.mjs";import t from"./tone.module.mjs";import{useEffect as n}from"react";import r from"classnames";var i=new Map(Object.entries({primary:t.primary,neutral:t.neutral,success:t.success,info:t.info,warn:t.warn,error:t.error}));function a(e){let n=i.get(e);return n?{className:r(t.tone,n)}:{className:t.tone,style:{"--tone":e}}}var o=new Map(Object.entries({primary:`var(--primary-color)`,neutral:`currentcolor`,success:`var(--success-color)`,info:`var(--info-color)`,warn:`var(--warn-color)`,error:`var(--error-color)`}));function s(e){return o.get(e)??e}function c(t,r){let a=r.join(`
|
|
2
|
+
`);n(()=>{if(e()&&typeof globalThis.CSS?.supports==`function`)for(let e of a.split(`
|
|
3
|
+
`))e&&!i.has(e)&&!CSS.supports(`color`,e)&&console.warn(`${t}: \`color\` takes a ThemeColor or a CSS colour, and got '${e}'.`)},[t,a])}export{s as cssColor,a as toneProps,c as useToneCheck};
|
|
4
|
+
//# sourceMappingURL=tone.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tone.mjs","names":[],"sources":["../../../../package/common/styles/tone.ts"],"sourcesContent":["import { useEffect, type CSSProperties } from 'react';\nimport cx from 'classnames';\n\nimport { ThemeColor, type ColorValue } from '../themeProvider/color.types';\nimport { isDev } from '../utils/isDev';\nimport styles from './tone.module.pcss';\n\n// A Map, so a CSS colour can never hit an Object.prototype key.\nconst CLASS_BY_COLOR = new Map<string, string>(\n Object.entries({\n primary: styles.primary,\n neutral: styles.neutral,\n success: styles.success,\n info: styles.info,\n warn: styles.warn,\n error: styles.error,\n } satisfies Record<ThemeColor, string>),\n);\n\n/** The class, and for a colour of the caller's own the inline style, that set the --tone properties. */\nexport function toneProps(color: ColorValue): { className: string; style?: CSSProperties } {\n const named = CLASS_BY_COLOR.get(color);\n if (named) return { className: cx(styles.tone, named) };\n return { className: styles.tone, style: { '--tone': color } as CSSProperties };\n}\n\n// A Map, so a CSS colour can never hit an Object.prototype key.\nconst VAR_BY_COLOR = new Map<string, string>(\n Object.entries({\n primary: 'var(--primary-color)',\n neutral: 'currentcolor',\n success: 'var(--success-color)',\n info: 'var(--info-color)',\n warn: 'var(--warn-color)',\n error: 'var(--error-color)',\n } satisfies Record<ThemeColor, string>),\n);\n\n/** A colour as a CSS value, for a component that paints it itself rather than through --tone. */\nexport function cssColor(color: ColorValue): string {\n return VAR_BY_COLOR.get(color) ?? color;\n}\n\n/** Warns in development about a value that can never be a colour. A var() passes: it only resolves on screen. */\nexport function useToneCheck(component: string, colors: (ColorValue | undefined)[]): void {\n const key = colors.join('\\n');\n useEffect(() => {\n // jsdom before 30 has no CSS.supports, and a development check must not break a consumer's tests.\n if (!isDev() || typeof globalThis.CSS?.supports !== 'function') return;\n for (const color of key.split('\\n')) {\n if (color && !CLASS_BY_COLOR.has(color) && !CSS.supports('color', color)) {\n console.warn(`${component}: \\`color\\` takes a ThemeColor or a CSS colour, and got '${color}'.`);\n }\n }\n }, [component, key]);\n}\n"],"mappings":"qJAQA,IAAM,EAAiB,IAAI,IACzB,OAAO,QAAQ,CACb,QAAS,EAAO,QAChB,QAAS,EAAO,QAChB,QAAS,EAAO,QAChB,KAAM,EAAO,KACb,KAAM,EAAO,KACb,MAAO,EAAO,KAChB,CAAsC,CACxC,EAGA,SAAgB,EAAU,EAAiE,CACzF,IAAM,EAAQ,EAAe,IAAI,CAAK,EAEtC,OADI,EAAc,CAAE,UAAW,EAAG,EAAO,KAAM,CAAK,CAAE,EAC/C,CAAE,UAAW,EAAO,KAAM,MAAO,CAAE,SAAU,CAAM,CAAmB,CAC/E,CAGA,IAAM,EAAe,IAAI,IACvB,OAAO,QAAQ,CACb,QAAS,uBACT,QAAS,eACT,QAAS,uBACT,KAAM,oBACN,KAAM,oBACN,MAAO,oBACT,CAAsC,CACxC,EAGA,SAAgB,EAAS,EAA2B,CAClD,OAAO,EAAa,IAAI,CAAK,GAAK,CACpC,CAGA,SAAgB,EAAa,EAAmB,EAA0C,CACxF,IAAM,EAAM,EAAO,KAAK;CAAI,EAC5B,MAAgB,CAEV,GAAC,EAAM,GAAK,OAAO,WAAW,KAAK,UAAa,WACpD,IAAK,IAAM,KAAS,EAAI,MAAM;CAAI,EAC5B,GAAS,CAAC,EAAe,IAAI,CAAK,GAAK,CAAC,IAAI,SAAS,QAAS,CAAK,GACrE,QAAQ,KAAK,GAAG,EAAU,2DAA2D,EAAM,GAAG,CAGpG,EAAG,CAAC,EAAW,CAAG,CAAC,CACrB"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";var e=`tone_sXFTv`,t=`primary_83X15`,n=`neutral_7-EPm`,r=`success_dJuAA`,i=`info_kSz-g`,a=`warn_p-5wW`,o=`error_NnEOv`,s={tone:e,primary:t,neutral:n,success:r,info:i,warn:a,error:o};export{s as default,o as error,i as info,n as neutral,t as primary,r as success,e as tone,a as warn};
|
|
2
|
+
//# sourceMappingURL=tone.module.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tone.module.mjs","names":[],"sources":["../../../../package/common/styles/tone.module.pcss"],"sourcesContent":["/* --tone comes from a colour class below, or inline (tone.ts) for any other colour. */\n.tone {\n /* White wherever it reaches 3:1 (relative luminance below 0.3, as Mantine), else black at 7:1 or\n more. Not WCAG 2's own crossover at 0.179, which puts black on mid-tone blues where white reads\n far better. */\n --tone-is-dark: clamp(0, (0.3 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) * infinity, 1);\n --tone-auto-contrast: color(from var(--tone) srgb-linear var(--tone-is-dark) var(--tone-is-dark) var(--tone-is-dark));\n --tone-contrast: var(--tone-auto-contrast);\n\n /* A third of the way to the text colour, so it reads (dark red on a dark theme), with the lost\n saturation put back (x1.5) so a light theme is not muddy. Borders, dots and icons keep the\n pure colour. */\n --tone-text: oklch(from color-mix(in oklab, var(--tone) 67%, var(--text-color, currentcolor)) l calc(c * 1.5) h);\n --tone-light: color-mix(in srgb, var(--tone) 22%, transparent);\n --tone-fill: var(--tone);\n --tone-outline: var(--tone);\n --tone-gradient: none;\n}\n\n/* After .tone, whose defaults these override. Not the theme's solid -lighter pastels for\n --tone-light: Light looked like two styles depending on the colour. */\n.primary {\n --tone: var(--primary-color);\n --tone-contrast: var(--text-on-primary, var(--tone-auto-contrast));\n --tone-gradient: var(--primary-gradient, none);\n}\n\n/* currentcolor, so it takes the colour of what it sits on, such as a close button on an Alert. Not\n --background-accent for the fill: in a light theme it stood out less than the tint. */\n.neutral {\n --tone: currentcolor;\n --tone-contrast: currentcolor;\n --tone-text: currentcolor;\n --tone-fill: color-mix(in srgb, currentcolor 20%, transparent);\n --tone-light: color-mix(in srgb, currentcolor 8%, transparent);\n --tone-outline: var(--border-color);\n}\n\n.success {\n --tone: var(--success-color);\n}\n\n.info {\n --tone: var(--info-color);\n}\n\n.warn {\n --tone: var(--warn-color);\n}\n\n.error {\n --tone: var(--error-color);\n --tone-contrast: var(--text-on-delete, var(--tone-auto-contrast));\n}\n\n/* Browsers in the support floor without relative colour syntax (Chrome 119, Firefox 128). Tests\n the formula itself, so a browser that parses `from` but not the rest falls back too. */\n@supports not\n((color: color(from red srgb-linear clamp(0, (0.3 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) * infinity, 1) 0 0)) and\n (color: oklch(from red l calc(c * 1.5) h))) {\n .tone {\n --tone-auto-contrast: var(--text-on-primary);\n --tone-text: color-mix(in oklab, var(--tone) 67%, var(--text-color, currentcolor));\n }\n}\n"],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color.types.mjs","names":[],"sources":["../../../../package/common/themeProvider/color.types.ts"],"sourcesContent":["/** The theme's named colours, shared by every component that takes a `color`. */\nexport enum ThemeColor {\n /** `--primary-color`. */\n Primary = 'primary',\n /** The surrounding text colour, with `--border-color` for an outline. */\n Neutral = 'neutral',\n /** `--success-color`. */\n Success = 'success',\n /** `--info-color`. */\n Info = 'info',\n /** `--warn-color`. */\n Warn = 'warn',\n /** `--error-color`. */\n Error = 'error',\n}\n\n/**\n * A `ThemeColor`, or any CSS colour such as `'var(--brand)'` or `'#7c3aed'`.\n * `string & {}` rather than `string`, which would swallow the enum into one plain string type.\n */\nexport type ColorValue = ThemeColor | (string & {});\n"],"mappings":"aACA,IAAY,EAAL,SAAA,EAAA,OAEL,GAAA,QAAA,UAEA,EAAA,QAAA,UAEA,EAAA,QAAA,UAEA,EAAA,KAAA,OAEA,EAAA,KAAA,OAEA,EAAA,MAAA,SACF,EAAA,CAAA,CAAA"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";var e={id:`default`,variables:{"--grey":`#8A8A8A`,"--lightgrey":`#e0e0e0`,"--lightergrey":`#B1B1B1`,"--white":`#FFFFFF`,"--red":`#D6002A`,"--lighter-red":`#ffeae9`,"--green":`#287626`,"--lighter-green":`#C4FFC9`,"--blue":`#5873d5`,"--lighter-blue":`#C6DBFF`,"--black":`black`,"--orange":`#ff7f50`,"--lighter-orange":`#ffe5d9`,"--primary-color":`#8184d6`,"--primary-accent":`#90CAF9`,"--primary-lighter":`#9a9ce4`,"--accent-color":`var(--grey)`,"--accent-color-light":`var(--lightgrey)`,"--text-color":`var(--white)`,"--text-dark":`var(--lightergrey)`,"--text-light":`var(--lightergrey)`,"--text-on-primary":`var(--white)`,"--text-on-delete":`var(--white)`,"--border-color":`#656574`,"--focus-border-color":`var(--primary-color)`,"--background":`#393945`,"--background-accent":`#33333c`,"--background-accent-dark":`var(--grey)`,"--background-accent-light":`#484856`,"--background-modal":`#484856`,"--success-color":`var(--green)`,"--success-lighter":`var(--lighter-green)`,"--error-color":`var(--red)`,"--error-lighter":`var(--lighter-red)`,"--required-mark-color":`var(--error-color)`,"--info-color":`var(--blue)`,"--info-lighter":`var(--lighter-blue)`,"--warn-color":`var(--orange)`,"--warn-lighter":`var(--lighter-orange)`,"--default-font-size":`16px`,"--text-small-font-size":`14px`,"--header-font-size":`24px`,"--header-medium-font-size":`18px`,"--header-small-font-size":`16px`,"--default-font-weight":`400`,"--header-font-weight":`600`,"--input-background":`transparent`,"--input-icon-color":`var(--text-color)`,"--error-border-color":`var(--red)`,"--
|
|
1
|
+
"use client";var e={id:`default`,variables:{"--grey":`#8A8A8A`,"--lightgrey":`#e0e0e0`,"--lightergrey":`#B1B1B1`,"--white":`#FFFFFF`,"--red":`#D6002A`,"--lighter-red":`#ffeae9`,"--green":`#287626`,"--lighter-green":`#C4FFC9`,"--blue":`#5873d5`,"--lighter-blue":`#C6DBFF`,"--black":`black`,"--orange":`#ff7f50`,"--lighter-orange":`#ffe5d9`,"--primary-color":`#8184d6`,"--primary-accent":`#90CAF9`,"--primary-lighter":`#9a9ce4`,"--accent-color":`var(--grey)`,"--accent-color-light":`var(--lightgrey)`,"--text-color":`var(--white)`,"--text-dark":`var(--lightergrey)`,"--text-light":`var(--lightergrey)`,"--text-on-primary":`var(--white)`,"--text-on-delete":`var(--white)`,"--border-color":`#656574`,"--focus-border-color":`var(--primary-color)`,"--background":`#393945`,"--background-accent":`#33333c`,"--background-accent-dark":`var(--grey)`,"--background-accent-light":`#484856`,"--background-modal":`#484856`,"--success-color":`var(--green)`,"--success-lighter":`var(--lighter-green)`,"--error-color":`var(--red)`,"--error-lighter":`var(--lighter-red)`,"--required-mark-color":`var(--error-color)`,"--info-color":`var(--blue)`,"--info-lighter":`var(--lighter-blue)`,"--warn-color":`var(--orange)`,"--warn-lighter":`var(--lighter-orange)`,"--default-font-size":`16px`,"--text-small-font-size":`14px`,"--header-font-size":`24px`,"--header-medium-font-size":`18px`,"--header-small-font-size":`16px`,"--default-font-weight":`400`,"--header-font-weight":`600`,"--input-background":`transparent`,"--input-icon-color":`var(--text-color)`,"--error-border-color":`var(--red)`,"--default-border-radius":`8px`,"--padding-sides":`15px`,"--margin-top":`10px`,"--default-font":`'Inter', sans-serif`,"--themed-font":`'Inter', sans-serif`,"--card-shadow":`0 3px 1px -2px rgb(0 0 0 / 20%), 0 2px 2px 0 rgb(0 0 0 / 14%), 0 1px 5px 0 rgb(0 0 0 / 12%)`,"--background-card-elevated":`var(--background-accent-light)`,"--background-card-outlined":`transparent`,"--background-card-filled":`var(--background-accent)`,"--spacing-s":`4px`,"--spacing-m":`8px`,"--spacing-l":`16px`}};export{e as defaultTheme};
|
|
2
2
|
//# sourceMappingURL=defaultTheme.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaultTheme.mjs","names":[],"sources":["../../../../package/common/themeProvider/defaultTheme.ts"],"sourcesContent":["import type { Theme } from './theme.types';\n\n/**\n * Built-in default theme used by ThemeProvider when no `themes` prop is\n * supplied. Provides a complete set of CSS variables so the component\n * library renders correctly out of the box.\n */\nexport const defaultTheme: Theme = {\n id: 'default',\n variables: {\n '--grey': '#8A8A8A',\n '--lightgrey': '#e0e0e0',\n '--lightergrey': '#B1B1B1',\n '--white': '#FFFFFF',\n '--red': '#D6002A',\n '--lighter-red': '#ffeae9',\n '--green': '#287626',\n '--lighter-green': '#C4FFC9',\n '--blue': '#5873d5',\n '--lighter-blue': '#C6DBFF',\n '--black': 'black',\n '--orange': '#ff7f50',\n '--lighter-orange': '#ffe5d9',\n\n '--primary-color': '#8184d6',\n '--primary-accent': '#90CAF9',\n '--primary-lighter': '#9a9ce4',\n '--accent-color': 'var(--grey)',\n '--accent-color-light': 'var(--lightgrey)',\n\n '--text-color': 'var(--white)',\n '--text-dark': 'var(--lightergrey)',\n '--text-light': 'var(--lightergrey)',\n '--text-on-primary': 'var(--white)',\n '--text-on-delete': 'var(--white)',\n '--border-color': '#656574',\n '--focus-border-color': 'var(--primary-color)',\n\n '--background': '#393945',\n '--background-accent': '#33333c',\n '--background-accent-dark': 'var(--grey)',\n '--background-accent-light': '#484856',\n '--background-modal': '#484856',\n\n '--success-color': 'var(--green)',\n '--success-lighter': 'var(--lighter-green)',\n '--error-color': 'var(--red)',\n '--error-lighter': 'var(--lighter-red)',\n '--required-mark-color': 'var(--error-color)',\n '--info-color': 'var(--blue)',\n '--info-lighter': 'var(--lighter-blue)',\n '--warn-color': 'var(--orange)',\n '--warn-lighter': 'var(--lighter-orange)',\n\n '--default-font-size': '16px',\n '--text-small-font-size': '14px',\n '--header-font-size': '24px',\n '--header-medium-font-size': '18px',\n '--header-small-font-size': '16px',\n\n '--default-font-weight': '400',\n '--header-font-weight': '600',\n\n '--input-background': 'transparent',\n '--input-icon-color': 'var(--text-color)',\n '--error-border-color': 'var(--red)',\n\n '--
|
|
1
|
+
{"version":3,"file":"defaultTheme.mjs","names":[],"sources":["../../../../package/common/themeProvider/defaultTheme.ts"],"sourcesContent":["import type { Theme } from './theme.types';\n\n/**\n * Built-in default theme used by ThemeProvider when no `themes` prop is\n * supplied. Provides a complete set of CSS variables so the component\n * library renders correctly out of the box.\n */\nexport const defaultTheme: Theme = {\n id: 'default',\n variables: {\n '--grey': '#8A8A8A',\n '--lightgrey': '#e0e0e0',\n '--lightergrey': '#B1B1B1',\n '--white': '#FFFFFF',\n '--red': '#D6002A',\n '--lighter-red': '#ffeae9',\n '--green': '#287626',\n '--lighter-green': '#C4FFC9',\n '--blue': '#5873d5',\n '--lighter-blue': '#C6DBFF',\n '--black': 'black',\n '--orange': '#ff7f50',\n '--lighter-orange': '#ffe5d9',\n\n '--primary-color': '#8184d6',\n '--primary-accent': '#90CAF9',\n '--primary-lighter': '#9a9ce4',\n '--accent-color': 'var(--grey)',\n '--accent-color-light': 'var(--lightgrey)',\n\n '--text-color': 'var(--white)',\n '--text-dark': 'var(--lightergrey)',\n '--text-light': 'var(--lightergrey)',\n '--text-on-primary': 'var(--white)',\n '--text-on-delete': 'var(--white)',\n '--border-color': '#656574',\n '--focus-border-color': 'var(--primary-color)',\n\n '--background': '#393945',\n '--background-accent': '#33333c',\n '--background-accent-dark': 'var(--grey)',\n '--background-accent-light': '#484856',\n '--background-modal': '#484856',\n\n '--success-color': 'var(--green)',\n '--success-lighter': 'var(--lighter-green)',\n '--error-color': 'var(--red)',\n '--error-lighter': 'var(--lighter-red)',\n '--required-mark-color': 'var(--error-color)',\n '--info-color': 'var(--blue)',\n '--info-lighter': 'var(--lighter-blue)',\n '--warn-color': 'var(--orange)',\n '--warn-lighter': 'var(--lighter-orange)',\n\n '--default-font-size': '16px',\n '--text-small-font-size': '14px',\n '--header-font-size': '24px',\n '--header-medium-font-size': '18px',\n '--header-small-font-size': '16px',\n\n '--default-font-weight': '400',\n '--header-font-weight': '600',\n\n '--input-background': 'transparent',\n '--input-icon-color': 'var(--text-color)',\n '--error-border-color': 'var(--red)',\n\n '--default-border-radius': '8px',\n '--padding-sides': '15px',\n '--margin-top': '10px',\n\n '--default-font': \"'Inter', sans-serif\",\n '--themed-font': \"'Inter', sans-serif\",\n\n '--card-shadow': '0 3px 1px -2px rgb(0 0 0 / 20%), 0 2px 2px 0 rgb(0 0 0 / 14%), 0 1px 5px 0 rgb(0 0 0 / 12%)',\n\n '--background-card-elevated': 'var(--background-accent-light)',\n '--background-card-outlined': 'transparent',\n // Below the page: on a dark theme the tint fallback is as light as Elevated.\n '--background-card-filled': 'var(--background-accent)',\n\n '--spacing-s': '4px',\n '--spacing-m': '8px',\n '--spacing-l': '16px',\n },\n};\n"],"mappings":"aAOA,IAAa,EAAsB,CACjC,GAAI,UACJ,UAAW,CACT,SAAU,UACV,cAAe,UACf,gBAAiB,UACjB,UAAW,UACX,QAAS,UACT,gBAAiB,UACjB,UAAW,UACX,kBAAmB,UACnB,SAAU,UACV,iBAAkB,UAClB,UAAW,QACX,WAAY,UACZ,mBAAoB,UAEpB,kBAAmB,UACnB,mBAAoB,UACpB,oBAAqB,UACrB,iBAAkB,cAClB,uBAAwB,mBAExB,eAAgB,eAChB,cAAe,qBACf,eAAgB,qBAChB,oBAAqB,eACrB,mBAAoB,eACpB,iBAAkB,UAClB,uBAAwB,uBAExB,eAAgB,UAChB,sBAAuB,UACvB,2BAA4B,cAC5B,4BAA6B,UAC7B,qBAAsB,UAEtB,kBAAmB,eACnB,oBAAqB,uBACrB,gBAAiB,aACjB,kBAAmB,qBACnB,wBAAyB,qBACzB,eAAgB,cAChB,iBAAkB,sBAClB,eAAgB,gBAChB,iBAAkB,wBAElB,sBAAuB,OACvB,yBAA0B,OAC1B,qBAAsB,OACtB,4BAA6B,OAC7B,2BAA4B,OAE5B,wBAAyB,MACzB,uBAAwB,MAExB,qBAAsB,cACtB,qBAAsB,oBACtB,uBAAwB,aAExB,0BAA2B,MAC3B,kBAAmB,OACnB,eAAgB,OAEhB,iBAAkB,sBAClB,gBAAiB,sBAEjB,gBAAiB,8FAEjB,6BAA8B,iCAC9B,6BAA8B,cAE9B,2BAA4B,2BAE5B,cAAe,MACf,cAAe,MACf,cAAe,MACjB,CACF"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{
|
|
1
|
+
"use client";import{useComponentDefaults as e}from"../configProvider/useComponentDefaults.mjs";import{isDev as t}from"../utils/isDev.mjs";import{useTiltGroup as n}from"../tiltGroup/tiltGroup.mjs";import{computeTilt as r,defaultTiltEasing as i}from"./tiltMath.mjs";import a from"./tilt.module.mjs";import{useEffect as o,useImperativeHandle as s,useRef as c}from"react";import l from"classnames";import{jsx as u}from"react/jsx-runtime";function d(){return typeof window<`u`&&window.matchMedia?.(`(prefers-reduced-motion: reduce)`).matches===!0}var f=.3,p=.05;function m(m){let{ref:h,children:g,maxTilt:_=15,maxTiltX:v,maxTiltY:y,perspective:b=800,easing:x=i,lockAxis:S=`none`,scaleOnHover:C=1,trackingMode:w=`self`,disabled:T=!1,onTiltChange:E,className:D,style:O,classNames:k,styles:A,...j}=e(`Tilt`,m),M=c(null),N=c(null),P=c(void 0),F=c(!1),I=c(!1),L=c(!1),R=c(null),z=c({rotateX:0,rotateY:0}),B=n(),V=w===`group`,H=V&&B!==null;o(()=>{V&&B===null&&t()&&console.warn(`Tilt: trackingMode="group" was set with no ancestor TiltGroup, falling back to self tracking.`)},[V,B===null]);let U=v??_,W=y??_;function G(e,t,n){let r=N.current;r&&(r.style.transform=`rotateX(${e}deg) rotateY(${t}deg)`+(n===1?``:` scale(${n})`))}function K(){P.current!==void 0&&(cancelAnimationFrame(P.current),P.current=void 0),F.current=!1}function q(){if(P.current=void 0,!N.current){F.current=!1;return}let e=I.current&&!T&&!d(),t=0,n=0;if(e){let e=R.current,i=M.current?.getBoundingClientRect();if(e&&i){let a=r(e.x-i.left,e.y-i.top,i,{maxTiltX:U,maxTiltY:W,easing:x,lockAxis:S});t=a.rotateX,n=a.rotateY}}let i=z.current,a,o;if(L.current?(a=i.rotateX+(t-i.rotateX)*f,o=i.rotateY+(n-i.rotateY)*f,Math.abs(t-a)<p&&Math.abs(n-o)<p&&(a=t,o=n,L.current=!1)):(a=t,o=n),z.current={rotateX:a,rotateY:o},G(a,o,e?C:1),E?.(a,o),!L.current){F.current=!1;return}P.current=requestAnimationFrame(q)}function J(){F.current||(F.current=!0,P.current=requestAnimationFrame(q))}function Y(e){I.current!==e&&(L.current=!0),I.current=e,J()}let X=e=>{T||H||d()||(R.current={x:e.clientX,y:e.clientY},Y(!0))},Z=()=>{H||Y(!1)};return o(()=>{if(H){if(T||d()){Y(!1);return}B?.pointer&&B.rect?(R.current={x:B.rect.left+B.pointer.x,y:B.rect.top+B.pointer.y},Y(!0)):Y(!1)}},[H,T,B?.pointer,B?.rect]),o(()=>()=>{K()},[]),s(h,()=>({setTilt(e,t){let n={rotateX:Math.max(-U,Math.min(U,e)),rotateY:Math.max(-W,Math.min(W,t))};K(),I.current=!1,L.current=!1,z.current=n,G(n.rotateX,n.rotateY,C),E?.(n.rotateX,n.rotateY)},reset(){K(),I.current=!1,L.current=!1,z.current={rotateX:0,rotateY:0},G(0,0,1)}})),u(`div`,{...j,ref:M,className:l(a.tilt,D,k?.root),style:{...O,...A?.root},onPointerMove:X,onPointerLeave:Z,onPointerCancel:Z,children:u(`div`,{className:l(a.tiltPerspective,k?.perspective),style:{perspective:`${b}px`,...A?.perspective},children:u(`div`,{ref:N,className:l(a.tiltSurface,k?.surface),style:A?.surface,children:g})})})}export{m as default};
|
|
2
2
|
//# sourceMappingURL=tilt.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tilt.mjs","names":[],"sources":["../../../../package/common/tilt/tilt.tsx"],"sourcesContent":["import { useEffect, useImperativeHandle, useRef, type PointerEvent as ReactPointerEvent } from 'react';\nimport cx from 'classnames';\n\nimport { useComponentDefaults } from '../configProvider';\nimport { useTiltGroup } from '../tiltGroup';\nimport { computeTilt, defaultTiltEasing } from './tiltMath';\nimport type { TiltProps } from './tilt.types';\nimport styles from './tilt.module.pcss';\n\n// Module-scoped ambient typing for the bundler-replaced NODE_ENV guard below. See bodyEnd.tsx.\ndeclare const process: { env: { NODE_ENV?: string } };\n\nfunction isDev(): boolean {\n return typeof process !== 'undefined' && process.env.NODE_ENV !== 'production';\n}\n\nfunction prefersReducedMotion(): boolean {\n return typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches === true;\n}\n\n// Per-frame catch-up rate (fraction of the remaining gap closed each tick) and the gap size,\n// in degrees, below which we consider the catch-up finished and switch to direct 1:1 writes.\nconst TILT_SMOOTHING = 0.3;\nconst TILT_CONVERGE_EPSILON = 0.05;\n\nfunction Tilt(props: TiltProps) {\n const {\n ref,\n children,\n maxTilt = 15,\n maxTiltX,\n maxTiltY,\n perspective = 800,\n easing = defaultTiltEasing,\n lockAxis = 'none',\n scaleOnHover = 1,\n trackingMode = 'self',\n disabled = false,\n onTiltChange,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Tilt', props);\n\n const rootRef = useRef<HTMLDivElement>(null);\n const surfaceRef = useRef<HTMLDivElement>(null);\n const rafRef = useRef<number | undefined>(undefined);\n const loopActiveRef = useRef(false);\n // Whether the pointer is currently \"over\" the element (self mode: within its own bounds;\n // group mode: the shared group pointer is set). The tilt loop's target is (0,0) whenever this\n // is false, and computed from `latestPointerRef` whenever it's true.\n const isHoveringRef = useRef(false);\n // True while the visually-applied tilt is still catching up to the target after a\n // discontinuity (entering from flat, or leaving back to flat), eased via a per-frame lerp\n // toward whatever the *current* target is. Once the gap closes, updates apply directly (1:1,\n // no lag) so continuous tracking stays crisp. A CSS transition can't do this cleanly: retargeting\n // one mid-flight restarts its full duration from scratch, so a continuously-moving cursor makes\n // it fall further and further behind instead of ever catching up.\n const isCatchingUpRef = useRef(false);\n const latestPointerRef = useRef<{ x: number; y: number } | null>(null);\n const currentTiltRef = useRef({ rotateX: 0, rotateY: 0 });\n\n const group = useTiltGroup();\n const usingGroup = trackingMode === 'group';\n const groupActive = usingGroup && group !== null;\n\n useEffect(() => {\n if (usingGroup && group === null && isDev()) {\n console.warn('Tilt: trackingMode=\"group\" was set with no ancestor TiltGroup, falling back to self tracking.');\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [usingGroup, group === null]);\n\n const clampX = maxTiltX ?? maxTilt;\n const clampY = maxTiltY ?? maxTilt;\n\n function writeTiltTransform(rotateX: number, rotateY: number, scale: number) {\n const surface = surfaceRef.current;\n if (!surface) return;\n surface.style.transform = `rotateX(${rotateX}deg) rotateY(${rotateY}deg)` + (scale !== 1 ? ` scale(${scale})` : '');\n }\n\n function stopTiltLoop() {\n if (rafRef.current !== undefined) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = undefined;\n }\n loopActiveRef.current = false;\n }\n\n // The single continuous per-frame driver for tilt. Reads live authoritative state\n // (`isHoveringRef`/`latestPointerRef`) fresh every tick rather than closing over values\n // captured at schedule time, so there's no possibility of a stale queued frame overwriting a\n // newer state.\n function tick() {\n rafRef.current = undefined;\n const surface = surfaceRef.current;\n if (!surface) {\n loopActiveRef.current = false;\n return;\n }\n\n const hovering = isHoveringRef.current && !disabled && !prefersReducedMotion();\n let targetX = 0;\n let targetY = 0;\n if (hovering) {\n const pos = latestPointerRef.current;\n const rect = rootRef.current?.getBoundingClientRect();\n if (pos && rect) {\n const target = computeTilt(pos.x - rect.left, pos.y - rect.top, rect, {\n maxTiltX: clampX,\n maxTiltY: clampY,\n easing,\n lockAxis,\n });\n targetX = target.rotateX;\n targetY = target.rotateY;\n }\n }\n\n const cur = currentTiltRef.current;\n let nextX: number;\n let nextY: number;\n if (isCatchingUpRef.current) {\n nextX = cur.rotateX + (targetX - cur.rotateX) * TILT_SMOOTHING;\n nextY = cur.rotateY + (targetY - cur.rotateY) * TILT_SMOOTHING;\n if (Math.abs(targetX - nextX) < TILT_CONVERGE_EPSILON && Math.abs(targetY - nextY) < TILT_CONVERGE_EPSILON) {\n nextX = targetX;\n nextY = targetY;\n isCatchingUpRef.current = false;\n }\n } else {\n // Locked on: apply the target directly, every frame. This is what keeps continuous\n // tracking crisp with zero added lag once the catch-up phase has finished.\n nextX = targetX;\n nextY = targetY;\n }\n\n currentTiltRef.current = { rotateX: nextX, rotateY: nextY };\n writeTiltTransform(nextX, nextY, hovering ? scaleOnHover : 1);\n onTiltChange?.(nextX, nextY);\n\n // Once locked on (nothing left to ease), stop rescheduling. The next native pointermove\n // (self mode) or group pointer update (group mode) calls `ensureTiltLoopRunning()` again on\n // its own, restarting the loop for exactly the one instant tick it needs.\n if (!isCatchingUpRef.current) {\n loopActiveRef.current = false;\n return;\n }\n rafRef.current = requestAnimationFrame(tick);\n }\n\n function ensureTiltLoopRunning() {\n if (loopActiveRef.current) return;\n loopActiveRef.current = true;\n rafRef.current = requestAnimationFrame(tick);\n }\n\n // Marks a hover-state transition (entering or leaving) so the loop re-arms its catch-up phase.\n // Only on an actual flip, not on every pointermove while already hovering, so continuous\n // tracking never re-triggers easing.\n function setHovering(next: boolean) {\n if (isHoveringRef.current !== next) {\n isCatchingUpRef.current = true;\n }\n isHoveringRef.current = next;\n ensureTiltLoopRunning();\n }\n\n // Self-mode pointer handlers.\n const handlePointerMove = (event: ReactPointerEvent<HTMLDivElement>) => {\n if (disabled || groupActive || prefersReducedMotion()) return;\n latestPointerRef.current = { x: event.clientX, y: event.clientY };\n setHovering(true);\n };\n\n const handlePointerLeave = () => {\n if (groupActive) return;\n setHovering(false);\n };\n\n // Group-mode tracking: react to the shared pointer position published by TiltGroup.\n useEffect(() => {\n if (!groupActive) return;\n if (disabled || prefersReducedMotion()) {\n setHovering(false);\n return;\n }\n if (group?.pointer && group.rect) {\n latestPointerRef.current = { x: group.rect.left + group.pointer.x, y: group.rect.top + group.pointer.y };\n setHovering(true);\n } else {\n setHovering(false);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [groupActive, disabled, group?.pointer, group?.rect]);\n\n useEffect(() => {\n // Must go through stopTiltLoop() (not just cancelAnimationFrame) so loopActiveRef is reset\n // too. Under React StrictMode, every effect's cleanup runs once synchronously right after\n // its setup, before setup runs again, so this fires even though the component isn't really\n // unmounting. The group-mode effect above runs on every mount (it schedules the loop as soon\n // as there's a group context, even with a still-null pointer), so cancelling its pending\n // frame here without also clearing loopActiveRef left the loop believing it was still\n // \"active\" with nothing actually scheduled: permanently wedged, since every later call to\n // ensureTiltLoopRunning() saw loopActiveRef already true and silently no-opped forever.\n return () => {\n stopTiltLoop();\n };\n }, []);\n\n useImperativeHandle(ref, () => ({\n setTilt(rotateX: number, rotateY: number) {\n const clamped = {\n rotateX: Math.max(-clampX, Math.min(clampX, rotateX)),\n rotateY: Math.max(-clampY, Math.min(clampY, rotateY)),\n };\n // Stops the loop so live tracking (if any is active) can't overwrite this explicit value\n // on the very next frame. An external caller driving custom choreography expects the\n // value it just set to actually stick. A later real pointer move restarts tracking fresh.\n stopTiltLoop();\n isHoveringRef.current = false;\n isCatchingUpRef.current = false;\n currentTiltRef.current = clamped;\n writeTiltTransform(clamped.rotateX, clamped.rotateY, scaleOnHover);\n onTiltChange?.(clamped.rotateX, clamped.rotateY);\n },\n reset() {\n stopTiltLoop();\n isHoveringRef.current = false;\n isCatchingUpRef.current = false;\n currentTiltRef.current = { rotateX: 0, rotateY: 0 };\n writeTiltTransform(0, 0, 1);\n },\n }));\n\n return (\n <div\n {...rest}\n ref={rootRef}\n className={cx(styles.tilt, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n onPointerMove={handlePointerMove}\n onPointerLeave={handlePointerLeave}\n onPointerCancel={handlePointerLeave}\n >\n <div\n className={cx(styles.tiltPerspective, classNames?.perspective)}\n style={{ perspective: `${perspective}px`, ...slotStyles?.perspective }}\n >\n <div ref={surfaceRef} className={cx(styles.tiltSurface, classNames?.surface)} style={slotStyles?.surface}>\n {children}\n </div>\n </div>\n </div>\n );\n}\n\nexport default Tilt;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tilt.mjs","names":[],"sources":["../../../../package/common/tilt/tilt.tsx"],"sourcesContent":["import { useEffect, useImperativeHandle, useRef, type PointerEvent as ReactPointerEvent } from 'react';\nimport cx from 'classnames';\n\nimport { useComponentDefaults } from '../configProvider';\nimport { useTiltGroup } from '../tiltGroup';\nimport { computeTilt, defaultTiltEasing } from './tiltMath';\nimport type { TiltProps } from './tilt.types';\nimport styles from './tilt.module.pcss';\nimport { isDev } from '../utils/isDev';\n\nfunction prefersReducedMotion(): boolean {\n return typeof window !== 'undefined' && window.matchMedia?.('(prefers-reduced-motion: reduce)').matches === true;\n}\n\n// Per-frame catch-up rate (fraction of the remaining gap closed each tick) and the gap size,\n// in degrees, below which we consider the catch-up finished and switch to direct 1:1 writes.\nconst TILT_SMOOTHING = 0.3;\nconst TILT_CONVERGE_EPSILON = 0.05;\n\nfunction Tilt(props: TiltProps) {\n const {\n ref,\n children,\n maxTilt = 15,\n maxTiltX,\n maxTiltY,\n perspective = 800,\n easing = defaultTiltEasing,\n lockAxis = 'none',\n scaleOnHover = 1,\n trackingMode = 'self',\n disabled = false,\n onTiltChange,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n } = useComponentDefaults('Tilt', props);\n\n const rootRef = useRef<HTMLDivElement>(null);\n const surfaceRef = useRef<HTMLDivElement>(null);\n const rafRef = useRef<number | undefined>(undefined);\n const loopActiveRef = useRef(false);\n // Whether the pointer is currently \"over\" the element (self mode: within its own bounds;\n // group mode: the shared group pointer is set). The tilt loop's target is (0,0) whenever this\n // is false, and computed from `latestPointerRef` whenever it's true.\n const isHoveringRef = useRef(false);\n // True while the visually-applied tilt is still catching up to the target after a\n // discontinuity (entering from flat, or leaving back to flat), eased via a per-frame lerp\n // toward whatever the *current* target is. Once the gap closes, updates apply directly (1:1,\n // no lag) so continuous tracking stays crisp. A CSS transition can't do this cleanly: retargeting\n // one mid-flight restarts its full duration from scratch, so a continuously-moving cursor makes\n // it fall further and further behind instead of ever catching up.\n const isCatchingUpRef = useRef(false);\n const latestPointerRef = useRef<{ x: number; y: number } | null>(null);\n const currentTiltRef = useRef({ rotateX: 0, rotateY: 0 });\n\n const group = useTiltGroup();\n const usingGroup = trackingMode === 'group';\n const groupActive = usingGroup && group !== null;\n\n useEffect(() => {\n if (usingGroup && group === null && isDev()) {\n console.warn('Tilt: trackingMode=\"group\" was set with no ancestor TiltGroup, falling back to self tracking.');\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [usingGroup, group === null]);\n\n const clampX = maxTiltX ?? maxTilt;\n const clampY = maxTiltY ?? maxTilt;\n\n function writeTiltTransform(rotateX: number, rotateY: number, scale: number) {\n const surface = surfaceRef.current;\n if (!surface) return;\n surface.style.transform = `rotateX(${rotateX}deg) rotateY(${rotateY}deg)` + (scale !== 1 ? ` scale(${scale})` : '');\n }\n\n function stopTiltLoop() {\n if (rafRef.current !== undefined) {\n cancelAnimationFrame(rafRef.current);\n rafRef.current = undefined;\n }\n loopActiveRef.current = false;\n }\n\n // The single continuous per-frame driver for tilt. Reads live authoritative state\n // (`isHoveringRef`/`latestPointerRef`) fresh every tick rather than closing over values\n // captured at schedule time, so there's no possibility of a stale queued frame overwriting a\n // newer state.\n function tick() {\n rafRef.current = undefined;\n const surface = surfaceRef.current;\n if (!surface) {\n loopActiveRef.current = false;\n return;\n }\n\n const hovering = isHoveringRef.current && !disabled && !prefersReducedMotion();\n let targetX = 0;\n let targetY = 0;\n if (hovering) {\n const pos = latestPointerRef.current;\n const rect = rootRef.current?.getBoundingClientRect();\n if (pos && rect) {\n const target = computeTilt(pos.x - rect.left, pos.y - rect.top, rect, {\n maxTiltX: clampX,\n maxTiltY: clampY,\n easing,\n lockAxis,\n });\n targetX = target.rotateX;\n targetY = target.rotateY;\n }\n }\n\n const cur = currentTiltRef.current;\n let nextX: number;\n let nextY: number;\n if (isCatchingUpRef.current) {\n nextX = cur.rotateX + (targetX - cur.rotateX) * TILT_SMOOTHING;\n nextY = cur.rotateY + (targetY - cur.rotateY) * TILT_SMOOTHING;\n if (Math.abs(targetX - nextX) < TILT_CONVERGE_EPSILON && Math.abs(targetY - nextY) < TILT_CONVERGE_EPSILON) {\n nextX = targetX;\n nextY = targetY;\n isCatchingUpRef.current = false;\n }\n } else {\n // Locked on: apply the target directly, every frame. This is what keeps continuous\n // tracking crisp with zero added lag once the catch-up phase has finished.\n nextX = targetX;\n nextY = targetY;\n }\n\n currentTiltRef.current = { rotateX: nextX, rotateY: nextY };\n writeTiltTransform(nextX, nextY, hovering ? scaleOnHover : 1);\n onTiltChange?.(nextX, nextY);\n\n // Once locked on (nothing left to ease), stop rescheduling. The next native pointermove\n // (self mode) or group pointer update (group mode) calls `ensureTiltLoopRunning()` again on\n // its own, restarting the loop for exactly the one instant tick it needs.\n if (!isCatchingUpRef.current) {\n loopActiveRef.current = false;\n return;\n }\n rafRef.current = requestAnimationFrame(tick);\n }\n\n function ensureTiltLoopRunning() {\n if (loopActiveRef.current) return;\n loopActiveRef.current = true;\n rafRef.current = requestAnimationFrame(tick);\n }\n\n // Marks a hover-state transition (entering or leaving) so the loop re-arms its catch-up phase.\n // Only on an actual flip, not on every pointermove while already hovering, so continuous\n // tracking never re-triggers easing.\n function setHovering(next: boolean) {\n if (isHoveringRef.current !== next) {\n isCatchingUpRef.current = true;\n }\n isHoveringRef.current = next;\n ensureTiltLoopRunning();\n }\n\n // Self-mode pointer handlers.\n const handlePointerMove = (event: ReactPointerEvent<HTMLDivElement>) => {\n if (disabled || groupActive || prefersReducedMotion()) return;\n latestPointerRef.current = { x: event.clientX, y: event.clientY };\n setHovering(true);\n };\n\n const handlePointerLeave = () => {\n if (groupActive) return;\n setHovering(false);\n };\n\n // Group-mode tracking: react to the shared pointer position published by TiltGroup.\n useEffect(() => {\n if (!groupActive) return;\n if (disabled || prefersReducedMotion()) {\n setHovering(false);\n return;\n }\n if (group?.pointer && group.rect) {\n latestPointerRef.current = { x: group.rect.left + group.pointer.x, y: group.rect.top + group.pointer.y };\n setHovering(true);\n } else {\n setHovering(false);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [groupActive, disabled, group?.pointer, group?.rect]);\n\n useEffect(() => {\n // Must go through stopTiltLoop() (not just cancelAnimationFrame) so loopActiveRef is reset\n // too. Under React StrictMode, every effect's cleanup runs once synchronously right after\n // its setup, before setup runs again, so this fires even though the component isn't really\n // unmounting. The group-mode effect above runs on every mount (it schedules the loop as soon\n // as there's a group context, even with a still-null pointer), so cancelling its pending\n // frame here without also clearing loopActiveRef left the loop believing it was still\n // \"active\" with nothing actually scheduled: permanently wedged, since every later call to\n // ensureTiltLoopRunning() saw loopActiveRef already true and silently no-opped forever.\n return () => {\n stopTiltLoop();\n };\n }, []);\n\n useImperativeHandle(ref, () => ({\n setTilt(rotateX: number, rotateY: number) {\n const clamped = {\n rotateX: Math.max(-clampX, Math.min(clampX, rotateX)),\n rotateY: Math.max(-clampY, Math.min(clampY, rotateY)),\n };\n // Stops the loop so live tracking (if any is active) can't overwrite this explicit value\n // on the very next frame. An external caller driving custom choreography expects the\n // value it just set to actually stick. A later real pointer move restarts tracking fresh.\n stopTiltLoop();\n isHoveringRef.current = false;\n isCatchingUpRef.current = false;\n currentTiltRef.current = clamped;\n writeTiltTransform(clamped.rotateX, clamped.rotateY, scaleOnHover);\n onTiltChange?.(clamped.rotateX, clamped.rotateY);\n },\n reset() {\n stopTiltLoop();\n isHoveringRef.current = false;\n isCatchingUpRef.current = false;\n currentTiltRef.current = { rotateX: 0, rotateY: 0 };\n writeTiltTransform(0, 0, 1);\n },\n }));\n\n return (\n <div\n {...rest}\n ref={rootRef}\n className={cx(styles.tilt, className, classNames?.root)}\n style={{ ...style, ...slotStyles?.root }}\n onPointerMove={handlePointerMove}\n onPointerLeave={handlePointerLeave}\n onPointerCancel={handlePointerLeave}\n >\n <div\n className={cx(styles.tiltPerspective, classNames?.perspective)}\n style={{ perspective: `${perspective}px`, ...slotStyles?.perspective }}\n >\n <div ref={surfaceRef} className={cx(styles.tiltSurface, classNames?.surface)} style={slotStyles?.surface}>\n {children}\n </div>\n </div>\n </div>\n );\n}\n\nexport default Tilt;\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import
|
|
1
|
+
"use client";import e from"../button/button.mjs";import{PopoverAlign as t,PopoverPlacement as n}from"../popover/popover.types.mjs";import r from"../popover/popover.mjs";import i from"../tooltip/tooltip.mjs";import a from"../input/input.mjs";import o from"../modal/modal.mjs";import ee from"../maskedInput/maskedInput.mjs";import{clampHour as te,clampToRange as s,formatTime as c,parseTimeString as l,snapMinute as u}from"./timeFunctions.mjs";import ne from"./components/clockDial/clockDial.mjs";import d from"./timeInput.module.mjs";import{useEffect as re,useRef as ie,useState as f}from"react";import p from"classnames";import{FontAwesomeIcon as ae}from"@fortawesome/react-fontawesome";import{faClock as oe}from"@fortawesome/free-solid-svg-icons";import{jsx as m,jsxs as h}from"react/jsx-runtime";function g({value:g,selected:se,onChange:ce=()=>null,onSelect:_=()=>null,formValidator:v=null,isInline:y=!1,isModal:b=!1,noInput:le=!1,noHeader:ue=!1,showClearButton:x=!1,showNowButton:S=!1,minuteStep:C=1,use24Hour:w=!0,minTime:T=null,maxTime:E=null,label:de=``,isValid:fe=!0,errorMessage:D=``,isRequired:O=!1,disabled:k=!1,className:pe=``,style:A,classNames:j,styles:M,...me}){let N=()=>v?v.value||``:g??se??``,[P,F]=f(N),[I,L]=f(!1),[R,z]=f(`hours`),[he,B]=f(!1),[ge,V]=f(!1),[,_e]=f(0),H=N(),[ve,ye]=f(H),U=ie(v);!v&&ve!==H&&(ye(H),F(H)),re(()=>{if(U.current=v,!v)return;let e=()=>{F(v.value||``),_e(e=>e+1)};return v.registerOnUpdateListener(e),()=>v.removeOnUpdateListener(e)},[v]);let be=()=>v?v.touched&&v.hasError():!fe||!!D,xe=()=>!!(O||v?.validators.find(e=>e.validatorId===`required`)),W=e=>{let t=e?c(e):null;v&&v.set(t),ce?.(t)},G=e=>{F(e?c(e):``),W(e)},K=l(P),q=K??{hours:12,minutes:0},J=e=>{let t={hours:e.hours,minutes:u(e.minutes,C)};G(s(t,T,E))},Se=e=>{let t={hours:e.hours,minutes:u(e.minutes,C)},n=s(t,T,E);if(G(n),R===`hours`){z(`minutes`);return}_?.(c(n)),y||L(!1)},Y=()=>{k||(z(`hours`),L(!0))},Ce=({previousState:e,nextState:t})=>{if(t.value===e.value)return t;let n=t.value,r=n.slice(0,2);/^\d\d$/.test(r)&&Number(r)>23&&(n=`23${n.slice(2)}`);let i=n.slice(3,5);return/^\d\d$/.test(i)&&Number(i)>59&&(n=`${n.slice(0,3)}59`),n===t.value?t:{...t,value:n}},we=e=>{F(e);let t=l(e);t&&W(t)},Te=()=>{U.current&&(U.current.touched=!0),B(!1),W(l(P))},X=e=>{e!==q.hours>=12&&G({hours:te(q.hours+(e?12:-12)),minutes:q.minutes})},Z=be(),Ee=K?String(w?K.hours:(K.hours+11)%12+1).padStart(2,`0`):`--`,De=K?String(K.minutes).padStart(2,`0`):`--`,Oe=ue?null:h(`div`,{className:p(d.timeInputClockHeader,j?.clockHeader),style:M?.clockHeader,children:[m(`button`,{type:`button`,className:p(d.timeInputHeaderSegment,R===`hours`&&d.timeInputHeaderSegmentActive,j?.headerSegment),style:M?.headerSegment,onClick:()=>z(`hours`),children:Ee}),m(`span`,{className:d.timeInputHeaderColon,children:`:`}),m(`button`,{type:`button`,className:p(d.timeInputHeaderSegment,R===`minutes`&&d.timeInputHeaderSegmentActive,j?.headerSegment),style:M?.headerSegment,onClick:()=>z(`minutes`),children:De}),!w&&h(`div`,{className:p(d.timeInputMeridiem,j?.meridiem),style:M?.meridiem,children:[m(`button`,{type:`button`,className:p(q.hours<12&&d.timeInputMeridiemActive),onClick:()=>X(!1),children:`AM`}),m(`button`,{type:`button`,className:p(q.hours>=12&&d.timeInputMeridiemActive),onClick:()=>X(!0),children:`PM`})]})]}),ke=x||S?h(`div`,{className:p(d.timeInputFooter,j?.footer),style:M?.footer,children:[S&&m(e,{onClick:()=>{let e=new Date;J({hours:e.getHours(),minutes:e.getMinutes()})},children:`Now`}),x&&m(e,{onClick:()=>{G(null),_?.(null)},children:`Clear`})]}):null,Q=h(`div`,{className:p(d.timeInputClock,j?.clock),style:M?.clock,children:[Oe,m(ne,{time:q,mode:R,use24Hour:w,minuteStep:C,onChange:J,onCommit:Se,classNames:j,styles:M}),ke]}),$=le?null:m(a,{autoComplete:`off`,label:`${de}${xe()?` *`:``}`,value:P,icon:m(ae,{icon:oe}),onIconClick:Y,onClick:Y,readOnly:b,disabled:k,isValid:!Z,customInput:m(ee,{mask:`99:99`,beforeMaskedStateChange:Ce}),onChange:e=>we(e),onBlur:Te,onFocus:()=>B(!0),onMouseEnter:()=>V(!0),onMouseLeave:()=>V(!1)}),Ae=y?Q:b?m(o,{hideHeader:!0,isOpen:I,onClose:()=>L(!1),children:Q}):m(r,{isOpen:I,onOpenChange:L,content:Q,placement:n.Bottom,align:t.Start,closeOnTriggerClick:!1,constrainWidth:!1,children:$});return h(`div`,{className:p(d.timeInput,j?.root,pe),style:{...M?.root,...A},...me,children:[(b||y)&&$,Ae,m(i,{variant:`error`,message:v?v.getCurrentErrorMessage()??``:D||``,isVisible:Z&&(he||ge)})]})}export{g as default};
|
|
2
2
|
//# sourceMappingURL=timeInput.mjs.map
|