@ahrowe/ui 0.42.0 → 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/progressBar/progressBar.d.ts +0 -1
- package/dist/cjs-types/common/progressBar/progressBar.types.d.ts +3 -1
- 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/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/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/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/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/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/progressBar/progressBar.d.ts +0 -1
- package/dist/types/common/progressBar/progressBar.types.d.ts +3 -1
- 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 +21 -11
- 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/ProgressBar.md +7 -4
- 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 +3 -2
- 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
|
@@ -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 +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
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeInput.mjs","names":[],"sources":["../../../../package/common/timeInput/timeInput.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport MaskedInput from '../maskedInput';\nimport type { BeforeMaskedStateChangeStates, MaskState } from '../maskedInput';\nimport { faClock } from '@fortawesome/free-solid-svg-icons';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport Input from '../input';\nimport Modal from '../modal';\nimport Popover from '../popover';\nimport Button from '../button';\nimport { ButtonStyleType } from '../button/button.types';\nimport Tooltip from '../tooltip';\nimport ClockDial from './components/clockDial';\nimport { PopoverAlign, PopoverPlacement } from '../popover/popover.types';\nimport { type TimeValue, parseTimeString, formatTime, snapMinute, clampToRange, clampHour } from './timeFunctions';\nimport type { TimeInputProps } from './timeInput.types';\n\nimport styles from './timeInput.module.pcss';\n\ntype ClockMode = 'hours' | 'minutes';\n\nexport default function TimeInput({\n value,\n selected,\n onChange = () => null,\n onSelect = () => null,\n formValidator = null,\n isInline = false,\n isModal = false,\n noInput = false,\n noHeader = false,\n showClearButton = false,\n showNowButton = false,\n minuteStep = 1,\n use24Hour = true,\n minTime = null,\n maxTime = null,\n label = '',\n isValid = true,\n errorMessage = '',\n isRequired = false,\n disabled = false,\n className = '',\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: TimeInputProps) {\n const getExternalString = (): string => {\n if (formValidator) return (formValidator.value as string) || '';\n return value ?? selected ?? '';\n };\n\n const [currentTimeString, setCurrentTimeString] = useState(getExternalString);\n const [isPickerOpen, setIsPickerOpen] = useState(false);\n const [mode, setMode] = useState<ClockMode>('hours');\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [, forceUpdate] = useState(0);\n\n const externalString = getExternalString();\n const [prevExternal, setPrevExternal] = useState(externalString);\n const fvRef = useRef(formValidator);\n\n // Sync when the controlled value changes externally.\n if (!formValidator && prevExternal !== externalString) {\n setPrevExternal(externalString);\n setCurrentTimeString(externalString);\n }\n\n useEffect(() => {\n fvRef.current = formValidator;\n if (!formValidator) return;\n const listener = () => {\n setCurrentTimeString((formValidator.value as string) || '');\n forceUpdate((n) => n + 1);\n };\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n const hasError = (): boolean =>\n formValidator ? formValidator.touched && formValidator.hasError() : !isValid || !!errorMessage;\n\n const computedIsRequired = (): boolean =>\n !!(isRequired || formValidator?.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required'));\n\n /** Push a value out to formValidator/onChange without touching the input string. */\n const emit = (time: TimeValue | null) => {\n const str = time ? formatTime(time) : null;\n if (formValidator) formValidator.set(str);\n onChange?.(str);\n };\n\n const applyTime = (time: TimeValue | null) => {\n setCurrentTimeString(time ? formatTime(time) : '');\n emit(time);\n };\n\n const parsed = parseTimeString(currentTimeString);\n const dialTime: TimeValue = parsed ?? { hours: 12, minutes: 0 };\n\n const handleDialChange = (time: TimeValue) => {\n const snapped = { hours: time.hours, minutes: snapMinute(time.minutes, minuteStep) };\n applyTime(clampToRange(snapped, minTime, maxTime));\n };\n\n const handleDialCommit = (time: TimeValue) => {\n const snapped = { hours: time.hours, minutes: snapMinute(time.minutes, minuteStep) };\n const next = clampToRange(snapped, minTime, maxTime);\n applyTime(next);\n if (mode === 'hours') {\n setMode('minutes');\n return;\n }\n onSelect?.(formatTime(next));\n if (!isInline) setIsPickerOpen(false);\n };\n\n const openPicker = () => {\n if (disabled) return;\n setMode('hours');\n setIsPickerOpen(true);\n };\n\n const beforeMaskedStateChange = ({ previousState, nextState }: BeforeMaskedStateChangeStates): MaskState => {\n if (nextState.value === previousState.value) return nextState;\n let v = nextState.value;\n const hourStr = v.slice(0, 2);\n if (/^\\d\\d$/.test(hourStr) && Number(hourStr) > 23) v = `23${v.slice(2)}`;\n const minStr = v.slice(3, 5);\n if (/^\\d\\d$/.test(minStr) && Number(minStr) > 59) v = `${v.slice(0, 3)}59`;\n return v === nextState.value ? nextState : { ...nextState, value: v };\n };\n\n const handleInputChange = (v: string) => {\n setCurrentTimeString(v);\n const t = parseTimeString(v);\n if (t) emit(t);\n };\n\n const handleBlur = () => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n emit(parseTimeString(currentTimeString));\n };\n\n const setMeridiem = (pm: boolean) => {\n const isPm = dialTime.hours >= 12;\n if (pm === isPm) return;\n applyTime({ hours: clampHour(dialTime.hours + (pm ? 12 : -12)), minutes: dialTime.minutes });\n };\n\n const hasErr = hasError();\n const displayHours = parsed\n ? String(use24Hour ? parsed.hours : ((parsed.hours + 11) % 12) + 1).padStart(2, '0')\n : '--';\n const displayMinutes = parsed ? String(parsed.minutes).padStart(2, '0') : '--';\n\n const header = noHeader ? null : (\n <div className={cx(styles.timeInputClockHeader, classNames?.clockHeader)} style={slotStyles?.clockHeader}>\n <button\n type='button'\n className={cx(\n styles.timeInputHeaderSegment,\n mode === 'hours' && styles.timeInputHeaderSegmentActive,\n classNames?.headerSegment,\n )}\n style={slotStyles?.headerSegment}\n onClick={() => setMode('hours')}\n >\n {displayHours}\n </button>\n <span className={styles.timeInputHeaderColon}>:</span>\n <button\n type='button'\n className={cx(\n styles.timeInputHeaderSegment,\n mode === 'minutes' && styles.timeInputHeaderSegmentActive,\n classNames?.headerSegment,\n )}\n style={slotStyles?.headerSegment}\n onClick={() => setMode('minutes')}\n >\n {displayMinutes}\n </button>\n {!use24Hour && (\n <div className={cx(styles.timeInputMeridiem, classNames?.meridiem)} style={slotStyles?.meridiem}>\n <button\n type='button'\n className={cx(dialTime.hours < 12 && styles.timeInputMeridiemActive)}\n onClick={() => setMeridiem(false)}\n >\n AM\n </button>\n <button\n type='button'\n className={cx(dialTime.hours >= 12 && styles.timeInputMeridiemActive)}\n onClick={() => setMeridiem(true)}\n >\n PM\n </button>\n </div>\n )}\n </div>\n );\n\n const footer =\n showClearButton || showNowButton ? (\n <div className={cx(styles.timeInputFooter, classNames?.footer)} style={slotStyles?.footer}>\n {showNowButton && (\n <Button\n styleType={ButtonStyleType.Default}\n onClick={() => {\n const now = new Date();\n handleDialChange({ hours: now.getHours(), minutes: now.getMinutes() });\n }}\n >\n Now\n </Button>\n )}\n {showClearButton && (\n <Button\n styleType={ButtonStyleType.Default}\n onClick={() => {\n applyTime(null);\n onSelect?.(null);\n }}\n >\n Clear\n </Button>\n )}\n </div>\n ) : null;\n\n const pickerContent = (\n <div className={cx(styles.timeInputClock, classNames?.clock)} style={slotStyles?.clock}>\n {header}\n <ClockDial\n time={dialTime}\n mode={mode}\n use24Hour={use24Hour}\n minuteStep={minuteStep}\n onChange={handleDialChange}\n onCommit={handleDialCommit}\n classNames={classNames}\n styles={slotStyles}\n />\n {footer}\n </div>\n );\n\n const input = noInput ? null : (\n <Input\n autoComplete='off'\n label={`${label}${computedIsRequired() ? ' *' : ''}`}\n value={currentTimeString}\n icon={<FontAwesomeIcon icon={faClock} />}\n onIconClick={openPicker}\n onClick={openPicker}\n readOnly={isModal}\n disabled={disabled}\n isValid={!hasErr}\n customInput={<MaskedInput mask='99:99' beforeMaskedStateChange={beforeMaskedStateChange} />}\n onChange={(v) => handleInputChange(v as string)}\n onBlur={handleBlur}\n onFocus={() => setIsFocused(true)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n />\n );\n\n const picker = (() => {\n if (isInline) return pickerContent;\n if (isModal) {\n return (\n <Modal hideHeader isOpen={isPickerOpen} onClose={() => setIsPickerOpen(false)}>\n {pickerContent}\n </Modal>\n );\n }\n return (\n <Popover\n isOpen={isPickerOpen}\n onOpenChange={setIsPickerOpen}\n content={pickerContent}\n placement={PopoverPlacement.Bottom}\n align={PopoverAlign.Start}\n // A click to place the caret in the field must not take the panel away.\n // The focus stays there on its own: Popover only follows a keyboard open.\n closeOnTriggerClick={false}\n constrainWidth={false}\n >\n {input}\n </Popover>\n );\n })();\n\n return (\n <div\n className={cx(styles.timeInput, classNames?.root, className)}\n style={{ ...slotStyles?.root, ...style }}\n {...rest}\n >\n {(isModal || isInline) && input}\n {picker}\n <Tooltip\n variant='error'\n message={formValidator ? (formValidator.getCurrentErrorMessage() ?? '') : errorMessage || ''}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </div>\n );\n}\n"],"mappings":"41BAqBA,SAAwB,EAAU,CAChC,QACA,YACA,gBAAiB,KACjB,eAAiB,KACjB,gBAAgB,KAChB,WAAW,GACX,UAAU,GACV,WAAU,GACV,YAAW,GACX,kBAAkB,GAClB,gBAAgB,GAChB,aAAa,EACb,YAAY,GACZ,UAAU,KACV,UAAU,KACV,SAAQ,GACR,UAAU,GACV,eAAe,GACf,cAAa,GACb,WAAW,GACX,aAAY,GACZ,SACA,aACA,OAAQ,EACR,GAAG,IACc,CACjB,IAAM,MACA,EAAuB,EAAc,OAAoB,GACtD,GAAS,IAAY,GAGxB,CAAC,EAAmB,GAAwB,EAAS,CAAiB,EACtE,CAAC,EAAc,GAAmB,EAAS,EAAK,EAChD,CAAC,EAAM,GAAW,EAAoB,OAAO,EAC7C,CAAC,EAAW,GAAgB,EAAS,EAAK,EAC1C,CAAC,GAAW,GAAgB,EAAS,EAAK,EAC1C,EAAG,IAAe,EAAS,CAAC,EAE5B,EAAiB,EAAkB,EACnC,CAAC,GAAc,IAAmB,EAAS,CAAc,EACzD,EAAQ,GAAO,CAAa,EAG9B,CAAC,GAAiB,KAAiB,IACrC,GAAgB,CAAc,EAC9B,EAAqB,CAAc,GAGrC,OAAgB,CAEd,GADA,EAAM,QAAU,EACZ,CAAC,EAAe,OACpB,IAAM,MAAiB,CACrB,EAAsB,EAAc,OAAoB,EAAE,EAC1D,GAAa,GAAM,EAAI,CAAC,CAC1B,EAEA,OADA,EAAc,yBAAyB,CAAQ,MAClC,EAAc,uBAAuB,CAAQ,CAC5D,EAAG,CAAC,CAAa,CAAC,EAElB,IAAM,OACJ,EAAgB,EAAc,SAAW,EAAc,SAAS,EAAI,CAAC,GAAW,CAAC,CAAC,EAE9E,OACJ,CAAC,EAAE,IAAc,GAAe,WAAW,KAAM,GAAO,EAA+B,cAAgB,UAAU,GAG7G,EAAQ,GAA2B,CACvC,IAAM,EAAM,EAAO,EAAW,CAAI,EAAI,KAClC,GAAe,EAAc,IAAI,CAAG,EACxC,KAAW,CAAG,CAChB,EAEM,EAAa,GAA2B,CAC5C,EAAqB,EAAO,EAAW,CAAI,EAAI,EAAE,EACjD,EAAK,CAAI,CACX,EAEM,EAAS,EAAgB,CAAiB,EAC1C,EAAsB,GAAU,CAAE,MAAO,GAAI,QAAS,CAAE,EAExD,EAAoB,GAAoB,CAC5C,IAAM,EAAU,CAAE,MAAO,EAAK,MAAO,QAAS,EAAW,EAAK,QAAS,CAAU,CAAE,EACnF,EAAU,EAAa,EAAS,EAAS,CAAO,CAAC,CACnD,EAEM,GAAoB,GAAoB,CAC5C,IAAM,EAAU,CAAE,MAAO,EAAK,MAAO,QAAS,EAAW,EAAK,QAAS,CAAU,CAAE,EAC7E,EAAO,EAAa,EAAS,EAAS,CAAO,EAEnD,GADA,EAAU,CAAI,EACV,IAAS,QAAS,CACpB,EAAQ,SAAS,EACjB,MACF,CACA,IAAW,EAAW,CAAI,CAAC,EACtB,GAAU,EAAgB,EAAK,CACtC,EAEM,MAAmB,CACnB,IACJ,EAAQ,OAAO,EACf,EAAgB,EAAI,EACtB,EAEM,IAA2B,CAAE,gBAAe,eAA0D,CAC1G,GAAI,EAAU,QAAU,EAAc,MAAO,OAAO,EACpD,IAAI,EAAI,EAAU,MACZ,EAAU,EAAE,MAAM,EAAG,CAAC,EACxB,SAAS,KAAK,CAAO,GAAK,OAAO,CAAO,EAAI,KAAI,EAAI,KAAK,EAAE,MAAM,CAAC,KACtE,IAAM,EAAS,EAAE,MAAM,EAAG,CAAC,EAE3B,MADI,SAAS,KAAK,CAAM,GAAK,OAAO,CAAM,EAAI,KAAI,EAAI,GAAG,EAAE,MAAM,EAAG,CAAC,EAAE,KAChE,IAAM,EAAU,MAAQ,EAAY,CAAE,GAAG,EAAW,MAAO,CAAE,CACtE,EAEM,GAAqB,GAAc,CACvC,EAAqB,CAAC,EACtB,IAAM,EAAI,EAAgB,CAAC,EACvB,GAAG,EAAK,CAAC,CACf,EAEM,OAAmB,CACnB,EAAM,UAAS,EAAM,QAAQ,QAAU,IAC3C,EAAa,EAAK,EAClB,EAAK,EAAgB,CAAiB,CAAC,CACzC,EAEM,EAAe,GAAgB,CAE/B,IADS,EAAS,OAAS,IAE/B,EAAU,CAAE,MAAO,GAAU,EAAS,OAAS,EAAK,GAAK,IAAI,EAAG,QAAS,EAAS,OAAQ,CAAC,CAC7F,EAEM,EAAS,GAAS,EAClB,GAAe,EACjB,OAAO,EAAY,EAAO,OAAU,EAAO,MAAQ,IAAM,GAAM,CAAC,CAAC,CAAC,SAAS,EAAG,GAAG,EACjF,KACE,GAAiB,EAAS,OAAO,EAAO,OAAO,CAAC,CAAC,SAAS,EAAG,GAAG,EAAI,KAEpE,GAAS,GAAW,KACxB,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,qBAAsB,GAAY,WAAW,EAAG,MAAO,GAAY,YAA7F,SAAA,CACE,EAAC,SAAD,CACE,KAAK,SACL,UAAW,EACT,EAAO,uBACP,IAAS,SAAW,EAAO,6BAC3B,GAAY,aACd,EACA,MAAO,GAAY,cACnB,YAAe,EAAQ,OAAO,EAE7B,SAAA,EACK,CAAA,EACR,EAAC,OAAD,CAAM,UAAW,EAAO,qBAAsB,SAAA,GAAO,CAAA,EACrD,EAAC,SAAD,CACE,KAAK,SACL,UAAW,EACT,EAAO,uBACP,IAAS,WAAa,EAAO,6BAC7B,GAAY,aACd,EACA,MAAO,GAAY,cACnB,YAAe,EAAQ,SAAS,EAE/B,SAAA,EACK,CAAA,EACP,CAAC,GACA,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,kBAAmB,GAAY,QAAQ,EAAG,MAAO,GAAY,SAAvF,SAAA,CACE,EAAC,SAAD,CACE,KAAK,SACL,UAAW,EAAG,EAAS,MAAQ,IAAM,EAAO,uBAAuB,EACnE,YAAe,EAAY,EAAK,EACjC,SAAA,IAEO,CAAA,EACR,EAAC,SAAD,CACE,KAAK,SACL,UAAW,EAAG,EAAS,OAAS,IAAM,EAAO,uBAAuB,EACpE,YAAe,EAAY,EAAI,EAChC,SAAA,IAEO,CAAA,CACL,GAEJ,IAGD,GACJ,GAAmB,EACjB,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,gBAAiB,GAAY,MAAM,EAAG,MAAO,GAAY,OAAnF,SAAA,CACG,GACC,EAAC,EAAD,CACE,UAAW,EAAgB,QAC3B,YAAe,CACb,IAAM,EAAM,IAAI,KAChB,EAAiB,CAAE,MAAO,EAAI,SAAS,EAAG,QAAS,EAAI,WAAW,CAAE,CAAC,CACvE,EACD,SAAA,KAEO,CAAA,EAET,GACC,EAAC,EAAD,CACE,UAAW,EAAgB,QAC3B,YAAe,CACb,EAAU,IAAI,EACd,IAAW,IAAI,CACjB,EACD,SAAA,OAEO,CAAA,CAEP,CACH,CAAA,EAAA,KAEA,EACJ,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,eAAgB,GAAY,KAAK,EAAG,MAAO,GAAY,MAAjF,SAAA,CACG,GACD,EAAC,GAAD,CACE,KAAM,EACA,OACK,YACC,aACZ,SAAU,EACV,SAAU,GACE,aACZ,OAAQ,CACT,CAAA,EACA,EACE,IAGD,EAAQ,GAAU,KACtB,EAAC,GAAD,CACE,aAAa,MACb,MAAO,GAAG,KAAQ,GAAmB,EAAI,KAAO,KAChD,MAAO,EACP,KAAM,EAAC,GAAD,CAAiB,KAAM,CAAU,CAAA,EACvC,YAAa,EACb,QAAS,EACT,SAAU,EACA,WACV,QAAS,CAAC,EACV,YAAa,EAAC,GAAD,CAAa,KAAK,QAAiC,0BAA0B,CAAA,EAC1F,SAAW,GAAM,GAAkB,CAAW,EAC9C,OAAQ,GACR,YAAe,EAAa,EAAI,EAChC,iBAAoB,EAAa,EAAI,EACrC,iBAAoB,EAAa,EAAK,CACvC,CAAA,EAGG,GACA,EAAiB,EACjB,EAEA,EAAC,EAAD,CAAO,WAAA,GAAW,OAAQ,EAAc,YAAe,EAAgB,EAAK,EACzE,SAAA,CACI,CAAA,EAIT,EAAC,EAAD,CACE,OAAQ,EACR,aAAc,EACd,QAAS,EACT,UAAW,EAAiB,OAC5B,MAAO,EAAa,MAGpB,oBAAqB,GACrB,eAAgB,GAEf,SAAA,CACM,CAAA,EAIb,OACE,EAAC,MAAD,CACE,UAAW,EAAG,EAAO,UAAW,GAAY,KAAM,EAAS,EAC3D,MAAO,CAAE,GAAG,GAAY,KAAM,GAAG,EAAM,EACvC,GAAI,GAHN,SAAA,EAKI,GAAW,IAAa,EACzB,GACD,EAAC,GAAD,CACE,QAAQ,QACR,QAAS,EAAiB,EAAc,uBAAuB,GAAK,GAAM,GAAgB,GAC1F,UAAW,IAAW,GAAa,GACpC,CAAA,CACE,GAET"}
|
|
1
|
+
{"version":3,"file":"timeInput.mjs","names":[],"sources":["../../../../package/common/timeInput/timeInput.tsx"],"sourcesContent":["import React, { useState, useEffect, useRef } from 'react';\nimport cx from 'classnames';\nimport MaskedInput from '../maskedInput';\nimport type { BeforeMaskedStateChangeStates, MaskState } from '../maskedInput';\nimport { faClock } from '@fortawesome/free-solid-svg-icons';\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome';\nimport Input from '../input';\nimport Modal from '../modal';\nimport Popover from '../popover';\nimport Button from '../button';\nimport Tooltip from '../tooltip';\nimport ClockDial from './components/clockDial';\nimport { PopoverAlign, PopoverPlacement } from '../popover/popover.types';\nimport { type TimeValue, parseTimeString, formatTime, snapMinute, clampToRange, clampHour } from './timeFunctions';\nimport type { TimeInputProps } from './timeInput.types';\n\nimport styles from './timeInput.module.pcss';\n\ntype ClockMode = 'hours' | 'minutes';\n\nexport default function TimeInput({\n value,\n selected,\n onChange = () => null,\n onSelect = () => null,\n formValidator = null,\n isInline = false,\n isModal = false,\n noInput = false,\n noHeader = false,\n showClearButton = false,\n showNowButton = false,\n minuteStep = 1,\n use24Hour = true,\n minTime = null,\n maxTime = null,\n label = '',\n isValid = true,\n errorMessage = '',\n isRequired = false,\n disabled = false,\n className = '',\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: TimeInputProps) {\n const getExternalString = (): string => {\n if (formValidator) return (formValidator.value as string) || '';\n return value ?? selected ?? '';\n };\n\n const [currentTimeString, setCurrentTimeString] = useState(getExternalString);\n const [isPickerOpen, setIsPickerOpen] = useState(false);\n const [mode, setMode] = useState<ClockMode>('hours');\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n const [, forceUpdate] = useState(0);\n\n const externalString = getExternalString();\n const [prevExternal, setPrevExternal] = useState(externalString);\n const fvRef = useRef(formValidator);\n\n // Sync when the controlled value changes externally.\n if (!formValidator && prevExternal !== externalString) {\n setPrevExternal(externalString);\n setCurrentTimeString(externalString);\n }\n\n useEffect(() => {\n fvRef.current = formValidator;\n if (!formValidator) return;\n const listener = () => {\n setCurrentTimeString((formValidator.value as string) || '');\n forceUpdate((n) => n + 1);\n };\n formValidator.registerOnUpdateListener(listener);\n return () => formValidator.removeOnUpdateListener(listener);\n }, [formValidator]);\n\n const hasError = (): boolean =>\n formValidator ? formValidator.touched && formValidator.hasError() : !isValid || !!errorMessage;\n\n const computedIsRequired = (): boolean =>\n !!(isRequired || formValidator?.validators.find((v) => (v as { validatorId?: string }).validatorId === 'required'));\n\n /** Push a value out to formValidator/onChange without touching the input string. */\n const emit = (time: TimeValue | null) => {\n const str = time ? formatTime(time) : null;\n if (formValidator) formValidator.set(str);\n onChange?.(str);\n };\n\n const applyTime = (time: TimeValue | null) => {\n setCurrentTimeString(time ? formatTime(time) : '');\n emit(time);\n };\n\n const parsed = parseTimeString(currentTimeString);\n const dialTime: TimeValue = parsed ?? { hours: 12, minutes: 0 };\n\n const handleDialChange = (time: TimeValue) => {\n const snapped = { hours: time.hours, minutes: snapMinute(time.minutes, minuteStep) };\n applyTime(clampToRange(snapped, minTime, maxTime));\n };\n\n const handleDialCommit = (time: TimeValue) => {\n const snapped = { hours: time.hours, minutes: snapMinute(time.minutes, minuteStep) };\n const next = clampToRange(snapped, minTime, maxTime);\n applyTime(next);\n if (mode === 'hours') {\n setMode('minutes');\n return;\n }\n onSelect?.(formatTime(next));\n if (!isInline) setIsPickerOpen(false);\n };\n\n const openPicker = () => {\n if (disabled) return;\n setMode('hours');\n setIsPickerOpen(true);\n };\n\n const beforeMaskedStateChange = ({ previousState, nextState }: BeforeMaskedStateChangeStates): MaskState => {\n if (nextState.value === previousState.value) return nextState;\n let v = nextState.value;\n const hourStr = v.slice(0, 2);\n if (/^\\d\\d$/.test(hourStr) && Number(hourStr) > 23) v = `23${v.slice(2)}`;\n const minStr = v.slice(3, 5);\n if (/^\\d\\d$/.test(minStr) && Number(minStr) > 59) v = `${v.slice(0, 3)}59`;\n return v === nextState.value ? nextState : { ...nextState, value: v };\n };\n\n const handleInputChange = (v: string) => {\n setCurrentTimeString(v);\n const t = parseTimeString(v);\n if (t) emit(t);\n };\n\n const handleBlur = () => {\n if (fvRef.current) fvRef.current.touched = true;\n setIsFocused(false);\n emit(parseTimeString(currentTimeString));\n };\n\n const setMeridiem = (pm: boolean) => {\n const isPm = dialTime.hours >= 12;\n if (pm === isPm) return;\n applyTime({ hours: clampHour(dialTime.hours + (pm ? 12 : -12)), minutes: dialTime.minutes });\n };\n\n const hasErr = hasError();\n const displayHours = parsed\n ? String(use24Hour ? parsed.hours : ((parsed.hours + 11) % 12) + 1).padStart(2, '0')\n : '--';\n const displayMinutes = parsed ? String(parsed.minutes).padStart(2, '0') : '--';\n\n const header = noHeader ? null : (\n <div className={cx(styles.timeInputClockHeader, classNames?.clockHeader)} style={slotStyles?.clockHeader}>\n <button\n type='button'\n className={cx(\n styles.timeInputHeaderSegment,\n mode === 'hours' && styles.timeInputHeaderSegmentActive,\n classNames?.headerSegment,\n )}\n style={slotStyles?.headerSegment}\n onClick={() => setMode('hours')}\n >\n {displayHours}\n </button>\n <span className={styles.timeInputHeaderColon}>:</span>\n <button\n type='button'\n className={cx(\n styles.timeInputHeaderSegment,\n mode === 'minutes' && styles.timeInputHeaderSegmentActive,\n classNames?.headerSegment,\n )}\n style={slotStyles?.headerSegment}\n onClick={() => setMode('minutes')}\n >\n {displayMinutes}\n </button>\n {!use24Hour && (\n <div className={cx(styles.timeInputMeridiem, classNames?.meridiem)} style={slotStyles?.meridiem}>\n <button\n type='button'\n className={cx(dialTime.hours < 12 && styles.timeInputMeridiemActive)}\n onClick={() => setMeridiem(false)}\n >\n AM\n </button>\n <button\n type='button'\n className={cx(dialTime.hours >= 12 && styles.timeInputMeridiemActive)}\n onClick={() => setMeridiem(true)}\n >\n PM\n </button>\n </div>\n )}\n </div>\n );\n\n const footer =\n showClearButton || showNowButton ? (\n <div className={cx(styles.timeInputFooter, classNames?.footer)} style={slotStyles?.footer}>\n {showNowButton && (\n <Button\n onClick={() => {\n const now = new Date();\n handleDialChange({ hours: now.getHours(), minutes: now.getMinutes() });\n }}\n >\n Now\n </Button>\n )}\n {showClearButton && (\n <Button\n onClick={() => {\n applyTime(null);\n onSelect?.(null);\n }}\n >\n Clear\n </Button>\n )}\n </div>\n ) : null;\n\n const pickerContent = (\n <div className={cx(styles.timeInputClock, classNames?.clock)} style={slotStyles?.clock}>\n {header}\n <ClockDial\n time={dialTime}\n mode={mode}\n use24Hour={use24Hour}\n minuteStep={minuteStep}\n onChange={handleDialChange}\n onCommit={handleDialCommit}\n classNames={classNames}\n styles={slotStyles}\n />\n {footer}\n </div>\n );\n\n const input = noInput ? null : (\n <Input\n autoComplete='off'\n label={`${label}${computedIsRequired() ? ' *' : ''}`}\n value={currentTimeString}\n icon={<FontAwesomeIcon icon={faClock} />}\n onIconClick={openPicker}\n onClick={openPicker}\n readOnly={isModal}\n disabled={disabled}\n isValid={!hasErr}\n customInput={<MaskedInput mask='99:99' beforeMaskedStateChange={beforeMaskedStateChange} />}\n onChange={(v) => handleInputChange(v as string)}\n onBlur={handleBlur}\n onFocus={() => setIsFocused(true)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n />\n );\n\n const picker = (() => {\n if (isInline) return pickerContent;\n if (isModal) {\n return (\n <Modal hideHeader isOpen={isPickerOpen} onClose={() => setIsPickerOpen(false)}>\n {pickerContent}\n </Modal>\n );\n }\n return (\n <Popover\n isOpen={isPickerOpen}\n onOpenChange={setIsPickerOpen}\n content={pickerContent}\n placement={PopoverPlacement.Bottom}\n align={PopoverAlign.Start}\n // A click to place the caret in the field must not take the panel away.\n // The focus stays there on its own: Popover only follows a keyboard open.\n closeOnTriggerClick={false}\n constrainWidth={false}\n >\n {input}\n </Popover>\n );\n })();\n\n return (\n <div\n className={cx(styles.timeInput, classNames?.root, className)}\n style={{ ...slotStyles?.root, ...style }}\n {...rest}\n >\n {(isModal || isInline) && input}\n {picker}\n <Tooltip\n variant='error'\n message={formValidator ? (formValidator.getCurrentErrorMessage() ?? '') : errorMessage || ''}\n isVisible={hasErr && (isFocused || isHovered)}\n />\n </div>\n );\n}\n"],"mappings":"8xBAoBA,SAAwB,EAAU,CAChC,QACA,YACA,gBAAiB,KACjB,eAAiB,KACjB,gBAAgB,KAChB,WAAW,GACX,UAAU,GACV,WAAU,GACV,YAAW,GACX,kBAAkB,GAClB,gBAAgB,GAChB,aAAa,EACb,YAAY,GACZ,UAAU,KACV,UAAU,KACV,SAAQ,GACR,WAAU,GACV,eAAe,GACf,aAAa,GACb,WAAW,GACX,aAAY,GACZ,QACA,aACA,OAAQ,EACR,GAAG,IACc,CACjB,IAAM,MACA,EAAuB,EAAc,OAAoB,GACtD,GAAS,IAAY,GAGxB,CAAC,EAAmB,GAAwB,EAAS,CAAiB,EACtE,CAAC,EAAc,GAAmB,EAAS,EAAK,EAChD,CAAC,EAAM,GAAW,EAAoB,OAAO,EAC7C,CAAC,GAAW,GAAgB,EAAS,EAAK,EAC1C,CAAC,GAAW,GAAgB,EAAS,EAAK,EAC1C,EAAG,IAAe,EAAS,CAAC,EAE5B,EAAiB,EAAkB,EACnC,CAAC,GAAc,IAAmB,EAAS,CAAc,EACzD,EAAQ,GAAO,CAAa,EAG9B,CAAC,GAAiB,KAAiB,IACrC,GAAgB,CAAc,EAC9B,EAAqB,CAAc,GAGrC,OAAgB,CAEd,GADA,EAAM,QAAU,EACZ,CAAC,EAAe,OACpB,IAAM,MAAiB,CACrB,EAAsB,EAAc,OAAoB,EAAE,EAC1D,GAAa,GAAM,EAAI,CAAC,CAC1B,EAEA,OADA,EAAc,yBAAyB,CAAQ,MAClC,EAAc,uBAAuB,CAAQ,CAC5D,EAAG,CAAC,CAAa,CAAC,EAElB,IAAM,OACJ,EAAgB,EAAc,SAAW,EAAc,SAAS,EAAI,CAAC,IAAW,CAAC,CAAC,EAE9E,OACJ,CAAC,EAAE,GAAc,GAAe,WAAW,KAAM,GAAO,EAA+B,cAAgB,UAAU,GAG7G,EAAQ,GAA2B,CACvC,IAAM,EAAM,EAAO,EAAW,CAAI,EAAI,KAClC,GAAe,EAAc,IAAI,CAAG,EACxC,KAAW,CAAG,CAChB,EAEM,EAAa,GAA2B,CAC5C,EAAqB,EAAO,EAAW,CAAI,EAAI,EAAE,EACjD,EAAK,CAAI,CACX,EAEM,EAAS,EAAgB,CAAiB,EAC1C,EAAsB,GAAU,CAAE,MAAO,GAAI,QAAS,CAAE,EAExD,EAAoB,GAAoB,CAC5C,IAAM,EAAU,CAAE,MAAO,EAAK,MAAO,QAAS,EAAW,EAAK,QAAS,CAAU,CAAE,EACnF,EAAU,EAAa,EAAS,EAAS,CAAO,CAAC,CACnD,EAEM,GAAoB,GAAoB,CAC5C,IAAM,EAAU,CAAE,MAAO,EAAK,MAAO,QAAS,EAAW,EAAK,QAAS,CAAU,CAAE,EAC7E,EAAO,EAAa,EAAS,EAAS,CAAO,EAEnD,GADA,EAAU,CAAI,EACV,IAAS,QAAS,CACpB,EAAQ,SAAS,EACjB,MACF,CACA,IAAW,EAAW,CAAI,CAAC,EACtB,GAAU,EAAgB,EAAK,CACtC,EAEM,MAAmB,CACnB,IACJ,EAAQ,OAAO,EACf,EAAgB,EAAI,EACtB,EAEM,IAA2B,CAAE,gBAAe,eAA0D,CAC1G,GAAI,EAAU,QAAU,EAAc,MAAO,OAAO,EACpD,IAAI,EAAI,EAAU,MACZ,EAAU,EAAE,MAAM,EAAG,CAAC,EACxB,SAAS,KAAK,CAAO,GAAK,OAAO,CAAO,EAAI,KAAI,EAAI,KAAK,EAAE,MAAM,CAAC,KACtE,IAAM,EAAS,EAAE,MAAM,EAAG,CAAC,EAE3B,MADI,SAAS,KAAK,CAAM,GAAK,OAAO,CAAM,EAAI,KAAI,EAAI,GAAG,EAAE,MAAM,EAAG,CAAC,EAAE,KAChE,IAAM,EAAU,MAAQ,EAAY,CAAE,GAAG,EAAW,MAAO,CAAE,CACtE,EAEM,GAAqB,GAAc,CACvC,EAAqB,CAAC,EACtB,IAAM,EAAI,EAAgB,CAAC,EACvB,GAAG,EAAK,CAAC,CACf,EAEM,OAAmB,CACnB,EAAM,UAAS,EAAM,QAAQ,QAAU,IAC3C,EAAa,EAAK,EAClB,EAAK,EAAgB,CAAiB,CAAC,CACzC,EAEM,EAAe,GAAgB,CAE/B,IADS,EAAS,OAAS,IAE/B,EAAU,CAAE,MAAO,GAAU,EAAS,OAAS,EAAK,GAAK,IAAI,EAAG,QAAS,EAAS,OAAQ,CAAC,CAC7F,EAEM,EAAS,GAAS,EAClB,GAAe,EACjB,OAAO,EAAY,EAAO,OAAU,EAAO,MAAQ,IAAM,GAAM,CAAC,CAAC,CAAC,SAAS,EAAG,GAAG,EACjF,KACE,GAAiB,EAAS,OAAO,EAAO,OAAO,CAAC,CAAC,SAAS,EAAG,GAAG,EAAI,KAEpE,GAAS,GAAW,KACxB,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,qBAAsB,GAAY,WAAW,EAAG,MAAO,GAAY,YAA7F,SAAA,CACE,EAAC,SAAD,CACE,KAAK,SACL,UAAW,EACT,EAAO,uBACP,IAAS,SAAW,EAAO,6BAC3B,GAAY,aACd,EACA,MAAO,GAAY,cACnB,YAAe,EAAQ,OAAO,EAE7B,SAAA,EACK,CAAA,EACR,EAAC,OAAD,CAAM,UAAW,EAAO,qBAAsB,SAAA,GAAO,CAAA,EACrD,EAAC,SAAD,CACE,KAAK,SACL,UAAW,EACT,EAAO,uBACP,IAAS,WAAa,EAAO,6BAC7B,GAAY,aACd,EACA,MAAO,GAAY,cACnB,YAAe,EAAQ,SAAS,EAE/B,SAAA,EACK,CAAA,EACP,CAAC,GACA,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,kBAAmB,GAAY,QAAQ,EAAG,MAAO,GAAY,SAAvF,SAAA,CACE,EAAC,SAAD,CACE,KAAK,SACL,UAAW,EAAG,EAAS,MAAQ,IAAM,EAAO,uBAAuB,EACnE,YAAe,EAAY,EAAK,EACjC,SAAA,IAEO,CAAA,EACR,EAAC,SAAD,CACE,KAAK,SACL,UAAW,EAAG,EAAS,OAAS,IAAM,EAAO,uBAAuB,EACpE,YAAe,EAAY,EAAI,EAChC,SAAA,IAEO,CAAA,CACL,GAEJ,IAGD,GACJ,GAAmB,EACjB,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,gBAAiB,GAAY,MAAM,EAAG,MAAO,GAAY,OAAnF,SAAA,CACG,GACC,EAAC,EAAD,CACE,YAAe,CACb,IAAM,EAAM,IAAI,KAChB,EAAiB,CAAE,MAAO,EAAI,SAAS,EAAG,QAAS,EAAI,WAAW,CAAE,CAAC,CACvE,EACD,SAAA,KAEO,CAAA,EAET,GACC,EAAC,EAAD,CACE,YAAe,CACb,EAAU,IAAI,EACd,IAAW,IAAI,CACjB,EACD,SAAA,OAEO,CAAA,CAEP,CACH,CAAA,EAAA,KAEA,EACJ,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,eAAgB,GAAY,KAAK,EAAG,MAAO,GAAY,MAAjF,SAAA,CACG,GACD,EAAC,GAAD,CACE,KAAM,EACA,OACK,YACC,aACZ,SAAU,EACV,SAAU,GACE,aACZ,OAAQ,CACT,CAAA,EACA,EACE,IAGD,EAAQ,GAAU,KACtB,EAAC,EAAD,CACE,aAAa,MACb,MAAO,GAAG,KAAQ,GAAmB,EAAI,KAAO,KAChD,MAAO,EACP,KAAM,EAAC,GAAD,CAAiB,KAAM,EAAU,CAAA,EACvC,YAAa,EACb,QAAS,EACT,SAAU,EACA,WACV,QAAS,CAAC,EACV,YAAa,EAAC,GAAD,CAAa,KAAK,QAAiC,0BAA0B,CAAA,EAC1F,SAAW,GAAM,GAAkB,CAAW,EAC9C,OAAQ,GACR,YAAe,EAAa,EAAI,EAChC,iBAAoB,EAAa,EAAI,EACrC,iBAAoB,EAAa,EAAK,CACvC,CAAA,EAGG,GACA,EAAiB,EACjB,EAEA,EAAC,EAAD,CAAO,WAAA,GAAW,OAAQ,EAAc,YAAe,EAAgB,EAAK,EACzE,SAAA,CACI,CAAA,EAIT,EAAC,EAAD,CACE,OAAQ,EACR,aAAc,EACd,QAAS,EACT,UAAW,EAAiB,OAC5B,MAAO,EAAa,MAGpB,oBAAqB,GACrB,eAAgB,GAEf,SAAA,CACM,CAAA,EAIb,OACE,EAAC,MAAD,CACE,UAAW,EAAG,EAAO,UAAW,GAAY,KAAM,EAAS,EAC3D,MAAO,CAAE,GAAG,GAAY,KAAM,GAAG,CAAM,EACvC,GAAI,GAHN,SAAA,EAKI,GAAW,IAAa,EACzB,GACD,EAAC,EAAD,CACE,QAAQ,QACR,QAAS,EAAiB,EAAc,uBAAuB,GAAK,GAAM,GAAgB,GAC1F,UAAW,IAAW,IAAa,GACpC,CAAA,CACE,GAET"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";import{
|
|
1
|
+
"use client";import{toneProps as e,useToneCheck as t}from"../styles/tone.mjs";import{renderIcon as n}from"../utils/renderIcon.mjs";import r from"../interactableDiv/index.mjs";import i from"./timeline.module.mjs";import{TimelineAlignment as a}from"./timeline.types.mjs";import"react";import o from"classnames";import{Fragment as s,jsx as c,jsxs as l}from"react/jsx-runtime";function u({items:u=[],alignment:d=a.Left,className:f,style:p,classNames:m,styles:h,...g}){let _=u.some(e=>!!e.icon);return t(`Timeline`,u.map(e=>e.color)),c(`div`,{...g,className:o(i.timeline,{[i.timelineRight]:d===a.Right,[i.timelineAlternate]:d===a.Alternate,[i.timelineWithIcons]:_},m?.root,f),style:{...h?.root,...p},children:u.map((t,f)=>{let p=t.id??f,g=f===u.length-1,_=d===a.Alternate&&f%2==1,v=!!t.onClick&&!t.disabled,y=t.color?e(t.color):void 0,b=l(s,{children:[l(`div`,{className:o(i.timelineMarker,m?.marker),style:h?.marker,children:[c(`div`,{className:o(i.timelineDot,{[i.timelineDotWithIcon]:!!t.icon},y&&[y.className,i.timelineDotToned],m?.dot),style:{...y?.style,...h?.dot},children:t.icon?n(t.icon):null}),!g&&c(`div`,{className:o(i.timelineConnector,m?.connector),style:h?.connector})]}),l(`div`,{className:o(i.timelineContent,m?.content),style:h?.content,children:[l(`div`,{className:i.timelineHeader,children:[c(`div`,{className:o(i.timelineTitle,m?.title),style:h?.title,children:t.title}),t.timestamp!=null&&c(`div`,{className:o(i.timelineTimestamp,m?.timestamp),style:h?.timestamp,children:t.timestamp})]}),t.description!=null&&c(`div`,{className:o(i.timelineDescription,m?.description),style:h?.description,children:t.description}),t.content]})]}),x=o(i.timelineItem,{[i.timelineItemRight]:_},{[i.timelineItemClickable]:v},{[i.timelineItemDisabled]:t.disabled},m?.item);return v?c(r,{className:x,style:h?.item,onClick:t.onClick,children:b},p):c(`div`,{className:x,style:h?.item,"aria-disabled":t.disabled||void 0,children:b},p)})})}export{u as default};
|
|
2
2
|
//# sourceMappingURL=timeline.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeline.mjs","names":[],"sources":["../../../../package/common/timeline/timeline.tsx"],"sourcesContent":["import React from 'react';\nimport cx from 'classnames';\nimport InteractableDiv from '../interactableDiv';\nimport styles from './timeline.module.pcss';\nimport { TimelineAlignment,
|
|
1
|
+
{"version":3,"file":"timeline.mjs","names":[],"sources":["../../../../package/common/timeline/timeline.tsx"],"sourcesContent":["import React from 'react';\nimport cx from 'classnames';\nimport InteractableDiv from '../interactableDiv';\nimport styles from './timeline.module.pcss';\nimport { TimelineAlignment, type TimelineProps, type TimelineItem } from './timeline.types';\nimport { renderIcon } from '../utils/renderIcon';\nimport { toneProps, useToneCheck } from '../styles/tone';\n\nexport default function Timeline({\n items = [],\n alignment = TimelineAlignment.Left,\n className,\n style,\n classNames,\n styles: slotStyles,\n ...rest\n}: TimelineProps) {\n // An icon dot is bigger than a plain one, and the marker is only as wide as the dot\n // inside it — so mixing the two put every row's spine and content column at a different\n // x. Widening the marker for the whole timeline fixes the alignment; doing it only when\n // an icon is actually present leaves an icon-less timeline exactly where it was.\n const hasIcons = items.some((item: TimelineItem) => !!item.icon);\n useToneCheck(\n 'Timeline',\n items.map((item) => item.color),\n );\n\n return (\n <div\n {...rest}\n className={cx(\n styles.timeline,\n {\n [styles.timelineRight]: alignment === TimelineAlignment.Right,\n [styles.timelineAlternate]: alignment === TimelineAlignment.Alternate,\n [styles.timelineWithIcons]: hasIcons,\n },\n classNames?.root,\n className,\n )}\n style={{ ...slotStyles?.root, ...style }}\n >\n {items.map((item: TimelineItem, index: number) => {\n const key = item.id ?? index;\n const isLast = index === items.length - 1;\n const isAlternateRight = alignment === TimelineAlignment.Alternate && index % 2 === 1;\n const isClickable = !!item.onClick && !item.disabled;\n const tone = item.color ? toneProps(item.color) : undefined;\n\n const itemContent = (\n <>\n <div className={cx(styles.timelineMarker, classNames?.marker)} style={slotStyles?.marker}>\n <div\n className={cx(\n styles.timelineDot,\n { [styles.timelineDotWithIcon]: !!item.icon },\n tone && [tone.className, styles.timelineDotToned],\n classNames?.dot,\n )}\n style={{ ...tone?.style, ...slotStyles?.dot }}\n >\n {item.icon ? renderIcon(item.icon) : null}\n </div>\n {!isLast && (\n <div className={cx(styles.timelineConnector, classNames?.connector)} style={slotStyles?.connector} />\n )}\n </div>\n <div className={cx(styles.timelineContent, classNames?.content)} style={slotStyles?.content}>\n <div className={styles.timelineHeader}>\n <div className={cx(styles.timelineTitle, classNames?.title)} style={slotStyles?.title}>\n {item.title}\n </div>\n {item.timestamp != null && (\n <div className={cx(styles.timelineTimestamp, classNames?.timestamp)} style={slotStyles?.timestamp}>\n {item.timestamp}\n </div>\n )}\n </div>\n {item.description != null && (\n <div\n className={cx(styles.timelineDescription, classNames?.description)}\n style={slotStyles?.description}\n >\n {item.description}\n </div>\n )}\n {item.content}\n </div>\n </>\n );\n\n const itemClassName = cx(\n styles.timelineItem,\n { [styles.timelineItemRight]: isAlternateRight },\n { [styles.timelineItemClickable]: isClickable },\n { [styles.timelineItemDisabled]: item.disabled },\n classNames?.item,\n );\n\n if (isClickable) {\n return (\n <InteractableDiv key={key} className={itemClassName} style={slotStyles?.item} onClick={item.onClick}>\n {itemContent}\n </InteractableDiv>\n );\n }\n\n return (\n <div key={key} className={itemClassName} style={slotStyles?.item} aria-disabled={item.disabled || undefined}>\n {itemContent}\n </div>\n );\n })}\n </div>\n );\n}\n"],"mappings":"qXAQA,SAAwB,EAAS,CAC/B,QAAQ,CAAC,EACT,YAAY,EAAkB,KAC9B,YACA,QACA,aACA,OAAQ,EACR,GAAG,GACa,CAKhB,IAAM,EAAW,EAAM,KAAM,GAAuB,CAAC,CAAC,EAAK,IAAI,EAM/D,OALA,EACE,WACA,EAAM,IAAK,GAAS,EAAK,KAAK,CAChC,EAGE,EAAC,MAAD,CACE,GAAI,EACJ,UAAW,EACT,EAAO,SACP,EACG,EAAO,eAAgB,IAAc,EAAkB,OACvD,EAAO,mBAAoB,IAAc,EAAkB,WAC3D,EAAO,mBAAoB,CAC9B,EACA,GAAY,KACZ,CACF,EACA,MAAO,CAAE,GAAG,GAAY,KAAM,GAAG,CAAM,EAEtC,SAAA,EAAM,KAAK,EAAoB,IAAkB,CAChD,IAAM,EAAM,EAAK,IAAM,EACjB,EAAS,IAAU,EAAM,OAAS,EAClC,EAAmB,IAAc,EAAkB,WAAa,EAAQ,GAAM,EAC9E,EAAc,CAAC,CAAC,EAAK,SAAW,CAAC,EAAK,SACtC,EAAO,EAAK,MAAQ,EAAU,EAAK,KAAK,EAAI,IAAA,GAE5C,EACJ,EAAA,EAAA,CAAA,SAAA,CACE,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,eAAgB,GAAY,MAAM,EAAG,MAAO,GAAY,OAAlF,SAAA,CACE,EAAC,MAAD,CACE,UAAW,EACT,EAAO,YACP,EAAG,EAAO,qBAAsB,CAAC,CAAC,EAAK,IAAK,EAC5C,GAAQ,CAAC,EAAK,UAAW,EAAO,gBAAgB,EAChD,GAAY,GACd,EACA,MAAO,CAAE,GAAG,GAAM,MAAO,GAAG,GAAY,GAAI,EAE3C,SAAA,EAAK,KAAO,EAAW,EAAK,IAAI,EAAI,IAClC,CAAA,EACJ,CAAC,GACA,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,kBAAmB,GAAY,SAAS,EAAG,MAAO,GAAY,SAAY,CAAA,CAEnG,CACL,CAAA,EAAA,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,gBAAiB,GAAY,OAAO,EAAG,MAAO,GAAY,QAApF,SAAA,CACE,EAAC,MAAD,CAAK,UAAW,EAAO,eAAvB,SAAA,CACE,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,cAAe,GAAY,KAAK,EAAG,MAAO,GAAY,MAC7E,SAAA,EAAK,KACH,CAAA,EACJ,EAAK,WAAa,MACjB,EAAC,MAAD,CAAK,UAAW,EAAG,EAAO,kBAAmB,GAAY,SAAS,EAAG,MAAO,GAAY,UACrF,SAAA,EAAK,SACH,CAAA,CAEJ,IACJ,EAAK,aAAe,MACnB,EAAC,MAAD,CACE,UAAW,EAAG,EAAO,oBAAqB,GAAY,WAAW,EACjE,MAAO,GAAY,YAElB,SAAA,EAAK,WACH,CAAA,EAEN,EAAK,OACH,CACL,CAAA,CAAA,CAAA,CAAA,EAGE,EAAgB,EACpB,EAAO,aACP,EAAG,EAAO,mBAAoB,CAAiB,EAC/C,EAAG,EAAO,uBAAwB,CAAY,EAC9C,EAAG,EAAO,sBAAuB,EAAK,QAAS,EAC/C,GAAY,IACd,EAUA,OARI,EAEA,EAAC,EAAD,CAA2B,UAAW,EAAe,MAAO,GAAY,KAAM,QAAS,EAAK,QACzF,SAAA,CACc,EAFK,CAEL,EAKnB,EAAC,MAAD,CAAe,UAAW,EAAe,MAAO,GAAY,KAAM,gBAAe,EAAK,UAAY,IAAA,GAC/F,SAAA,CACE,EAFK,CAEL,CAET,CAAC,CACE,CAAA,CAET"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";var e=`timeline_VtQdt`,t=`timeline-item_s8-U2`,n=`timeline-item-connector_06FQ0`,r=`timeline-item-clickable_0w8zK`,i=`timeline-item-disabled_EkWVA`,a=`timeline-marker_u6jDA`,o=`timeline-dot_l-s7C`,s=`timeline-dot-with-icon_6JK7D`,c=`timeline-dot-
|
|
1
|
+
"use client";var e=`timeline_VtQdt`,t=`timeline-item_s8-U2`,n=`timeline-item-connector_06FQ0`,r=`timeline-item-clickable_0w8zK`,i=`timeline-item-disabled_EkWVA`,a=`timeline-marker_u6jDA`,o=`timeline-dot_l-s7C`,s=`timeline-dot-with-icon_6JK7D`,c=`timeline-dot-toned_h1Cso`,l=`timeline-with-icons_ylDAw`,u=`timeline-connector_VuXnH`,d=`timeline-content_K4Ztg`,f=`timeline-header_xr4Tw`,p=`timeline-title_MZ26k`,m=`timeline-timestamp_-0w-N`,h=`timeline-description_WcWIu`,g=`timeline-right_fZEKn`,_=`timeline-alternate_Kv9LY`,v=`timeline-item-right_s5ELB`,y={timeline:e,"timeline-item":`timeline-item_s8-U2`,timelineItem:t,"timeline-item-connector":`timeline-item-connector_06FQ0`,timelineItemConnector:n,"timeline-item-clickable":`timeline-item-clickable_0w8zK`,timelineItemClickable:r,"timeline-item-disabled":`timeline-item-disabled_EkWVA`,timelineItemDisabled:i,"timeline-marker":`timeline-marker_u6jDA`,timelineMarker:a,"timeline-dot":`timeline-dot_l-s7C`,timelineDot:o,"timeline-dot-with-icon":`timeline-dot-with-icon_6JK7D`,timelineDotWithIcon:s,"timeline-dot-toned":`timeline-dot-toned_h1Cso`,timelineDotToned:c,"timeline-with-icons":`timeline-with-icons_ylDAw`,timelineWithIcons:l,"timeline-connector":`timeline-connector_VuXnH`,timelineConnector:u,"timeline-content":`timeline-content_K4Ztg`,timelineContent:d,"timeline-header":`timeline-header_xr4Tw`,timelineHeader:f,"timeline-title":`timeline-title_MZ26k`,timelineTitle:p,"timeline-timestamp":`timeline-timestamp_-0w-N`,timelineTimestamp:m,"timeline-description":`timeline-description_WcWIu`,timelineDescription:h,"timeline-right":`timeline-right_fZEKn`,timelineRight:g,"timeline-alternate":`timeline-alternate_Kv9LY`,timelineAlternate:_,"timeline-item-right":`timeline-item-right_s5ELB`,timelineItemRight:v};export{y as default,e as timeline,_ as timelineAlternate,u as timelineConnector,d as timelineContent,h as timelineDescription,o as timelineDot,c as timelineDotToned,s as timelineDotWithIcon,f as timelineHeader,t as timelineItem,r as timelineItemClickable,n as timelineItemConnector,i as timelineItemDisabled,v as timelineItemRight,a as timelineMarker,g as timelineRight,m as timelineTimestamp,p as timelineTitle,l as timelineWithIcons};
|
|
2
2
|
//# sourceMappingURL=timeline.module.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeline.module.mjs","names":[],"sources":["../../../../package/common/timeline/timeline.module.pcss"],"sourcesContent":[".timeline {\n /* Theme tokens resolved once, each with a built-in fallback. Set any of the\n public `--timeline-*` variables via ThemeProvider (theme-wide) or `style`\n (per instance) to override; unset ones fall back to the values below. */\n --custom-timeline-dot-size: var(--timeline-dot-size, 14px);\n --custom-timeline-dot-color: var(--timeline-dot-color, var(--primary-color));\n --custom-timeline-dot-border: var(--timeline-dot-border, var(--background));\n --custom-timeline-line-color: var(--timeline-line-color, var(--border-color));\n --custom-timeline-line-thickness: var(--timeline-line-thickness, 2px);\n --custom-timeline-gap: var(--timeline-gap, 16px);\n --custom-timeline-item-gap: var(--timeline-item-gap, 20px);\n --custom-timeline-icon-dot-size: var(--timeline-icon-dot-size, 28px);\n\n display: flex;\n flex-direction: column;\n color: var(--text-color);\n\n &-item {\n display: flex;\n gap: var(--custom-timeline-gap);\n border-radius: var(--default-border-radius);\n\n &:last-child &-connector {\n display: none;\n }\n }\n\n &-item-clickable {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n transition: background-color 0.15s ease;\n margin: 0 -10px;\n padding: 0 10px;\n\n &:hover {\n background-color: var(--background-accent-light);\n }\n\n &:focus-visible {\n outline: 2px solid var(--focus-border-color, var(--primary-color));\n outline-offset: -2px;\n }\n }\n\n &-item-disabled {\n opacity: 0.5;\n }\n\n &-marker {\n display: flex;\n flex-direction: column;\n align-items: center;\n flex-shrink: 0;\n }\n\n &-dot {\n width: var(--custom-timeline-dot-size);\n height: var(--custom-timeline-dot-size);\n border-radius: 50%;\n background-color: var(--custom-timeline-dot-color);\n box-shadow: 0 0 0 3px var(--custom-timeline-dot-border);\n flex-shrink: 0;\n }\n\n /* Set by the component whenever the item has an icon — not inferred from the\n rendered markup (`:has(svg)`), which would miss a custom icon element that\n isn't an <svg>, e.g. an <img>. */\n &-dot-with-icon {\n width: var(--custom-timeline-icon-dot-size);\n height: var(--custom-timeline-icon-dot-size);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--text-on-primary);\n font-size: calc(var(--custom-timeline-icon-dot-size) * 0.5);\n }\n\n
|
|
1
|
+
{"version":3,"file":"timeline.module.mjs","names":[],"sources":["../../../../package/common/timeline/timeline.module.pcss"],"sourcesContent":[".timeline {\n /* Theme tokens resolved once, each with a built-in fallback. Set any of the\n public `--timeline-*` variables via ThemeProvider (theme-wide) or `style`\n (per instance) to override; unset ones fall back to the values below. */\n --custom-timeline-dot-size: var(--timeline-dot-size, 14px);\n --custom-timeline-dot-color: var(--timeline-dot-color, var(--primary-color));\n --custom-timeline-dot-border: var(--timeline-dot-border, var(--background));\n --custom-timeline-line-color: var(--timeline-line-color, var(--border-color));\n --custom-timeline-line-thickness: var(--timeline-line-thickness, 2px);\n --custom-timeline-gap: var(--timeline-gap, 16px);\n --custom-timeline-item-gap: var(--timeline-item-gap, 20px);\n --custom-timeline-icon-dot-size: var(--timeline-icon-dot-size, 28px);\n\n display: flex;\n flex-direction: column;\n color: var(--text-color);\n\n &-item {\n display: flex;\n gap: var(--custom-timeline-gap);\n border-radius: var(--default-border-radius);\n\n &:last-child &-connector {\n display: none;\n }\n }\n\n &-item-clickable {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n transition: background-color 0.15s ease;\n margin: 0 -10px;\n padding: 0 10px;\n\n &:hover {\n background-color: var(--background-accent-light);\n }\n\n &:focus-visible {\n outline: 2px solid var(--focus-border-color, var(--primary-color));\n outline-offset: -2px;\n }\n }\n\n &-item-disabled {\n opacity: 0.5;\n }\n\n &-marker {\n display: flex;\n flex-direction: column;\n align-items: center;\n flex-shrink: 0;\n }\n\n &-dot {\n width: var(--custom-timeline-dot-size);\n height: var(--custom-timeline-dot-size);\n border-radius: 50%;\n background-color: var(--custom-timeline-dot-color);\n box-shadow: 0 0 0 3px var(--custom-timeline-dot-border);\n flex-shrink: 0;\n }\n\n /* Set by the component whenever the item has an icon — not inferred from the\n rendered markup (`:has(svg)`), which would miss a custom icon element that\n isn't an <svg>, e.g. an <img>. */\n &-dot-with-icon {\n width: var(--custom-timeline-icon-dot-size);\n height: var(--custom-timeline-icon-dot-size);\n display: flex;\n align-items: center;\n justify-content: center;\n color: var(--text-on-primary);\n font-size: calc(var(--custom-timeline-icon-dot-size) * 0.5);\n }\n\n /* After -dot-with-icon, which it ties on specificity: a coloured dot's icon reads on its colour. */\n &-dot-toned {\n background-color: var(--tone);\n color: var(--tone-contrast);\n }\n\n /* Neutral's --tone is its contrast colour too, so an icon needs the see-through fill behind it. */\n &-dot-toned&-dot-with-icon {\n background-color: var(--tone-fill);\n }\n\n /* Set by the component when ANY item has an icon. Every marker is then as wide as the\n widest dot it could hold, so the connectors line up into one vertical spine and every\n content column starts at the same x. max(), because a consumer is free to set the icon\n dot smaller than the plain one. */\n &-with-icons &-marker {\n width: max(var(--custom-timeline-dot-size), var(--custom-timeline-icon-dot-size));\n }\n\n &-connector {\n flex: 1 1 auto;\n width: var(--custom-timeline-line-thickness);\n min-height: 12px;\n background-color: var(--custom-timeline-line-color);\n margin: 4px 0;\n }\n\n &-content {\n flex: 1 1 auto;\n min-width: 0;\n padding-bottom: var(--custom-timeline-item-gap);\n }\n\n &-header {\n display: flex;\n align-items: baseline;\n justify-content: space-between;\n gap: 8px;\n }\n\n &-title {\n font-weight: 600;\n color: var(--text-color);\n }\n\n &-timestamp {\n flex-shrink: 0;\n color: var(--text-dark);\n font-size: var(--text-small-font-size, 0.85em);\n white-space: nowrap;\n }\n\n &-description {\n color: var(--text-dark);\n margin-top: 2px;\n }\n\n /* Right: markers + line on the right, content on the left */\n &-right &-item {\n flex-direction: row-reverse;\n text-align: right;\n }\n\n &-right &-header {\n flex-direction: row-reverse;\n }\n\n /* Alternate: two-column layout, entries alternating left/right of a centered line */\n &-alternate &-item {\n display: grid;\n grid-template-columns: 1fr auto 1fr;\n align-items: start;\n gap: var(--custom-timeline-gap);\n }\n\n &-alternate &-marker {\n grid-column: 2;\n grid-row: 1;\n }\n\n &-alternate &-content {\n grid-column: 1;\n grid-row: 1;\n text-align: right;\n }\n\n &-alternate &-header {\n flex-direction: row-reverse;\n }\n\n &-alternate &-item-right &-content {\n grid-column: 3;\n text-align: left;\n }\n\n &-alternate &-item-right &-header {\n flex-direction: row;\n }\n}\n"],"mappings":""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use client";var e=function(e){return e.Left=`left`,e.Right=`right`,e.Alternate=`alternate`,e}({})
|
|
1
|
+
"use client";var e=function(e){return e.Left=`left`,e.Right=`right`,e.Alternate=`alternate`,e}({});export{e as TimelineAlignment};
|
|
2
2
|
//# sourceMappingURL=timeline.types.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timeline.types.mjs","names":[],"sources":["../../../../package/common/timeline/timeline.types.ts"],"sourcesContent":["import type React from 'react';\nimport type { IconContent } from '../types/icon.types';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\n\n/** Layout of entries relative to the connecting line. */\nexport enum TimelineAlignment {\n /** Line and markers on the left, content to the right (the default). */\n Left = 'left',\n /** Line and markers on the right, content to the left. */\n Right = 'right',\n /** Line down the center, entries alternating left/right. */\n Alternate = 'alternate',\n}\n\
|
|
1
|
+
{"version":3,"file":"timeline.types.mjs","names":[],"sources":["../../../../package/common/timeline/timeline.types.ts"],"sourcesContent":["import type React from 'react';\nimport type { IconContent } from '../types/icon.types';\nimport type { SlotClassNames, SlotStyles, HtmlProps } from '../types/slots.types';\nimport type { ColorValue } from '../themeProvider/color.types';\n\n/** Layout of entries relative to the connecting line. */\nexport enum TimelineAlignment {\n /** Line and markers on the left, content to the right (the default). */\n Left = 'left',\n /** Line and markers on the right, content to the left. */\n Right = 'right',\n /** Line down the center, entries alternating left/right. */\n Alternate = 'alternate',\n}\n\nexport type TimelineSlots =\n | 'root'\n | 'item'\n | 'marker'\n | 'dot'\n | 'connector'\n | 'content'\n | 'title'\n | 'description'\n | 'timestamp';\n\nexport interface TimelineItem {\n /** Stable identity for the entry, used as its React key. Falls back to its array index when omitted; pass one whenever `items` can be reordered or have entries prepended (e.g. a live \"newest first\" audit log), so React doesn't misattribute row state across the shift. */\n id?: string | number;\n /** Primary label for the entry. */\n title: React.ReactNode;\n /** Secondary line under the title. */\n description?: React.ReactNode;\n /** Rendered next to the title, e.g. a date or relative time (\"2 hours ago\"). */\n timestamp?: React.ReactNode;\n /** Icon shown in the marker instead of a plain dot — a FontAwesome icon or any node. */\n icon?: IconContent;\n /** The marker's colour: a `ThemeColor` or any CSS colour. Unset, it is `--timeline-dot-color`. */\n color?: ColorValue;\n /** Extra content rendered under the description, e.g. a diff, an attachment, an actor avatar. */\n content?: React.ReactNode;\n /** Makes the whole entry clickable (e.g. to open the full record), rendering it as an accessible button. */\n onClick?: (event: React.MouseEvent<HTMLDivElement>) => void;\n /** Disables the entry: never clickable, dimmed. Only relevant alongside `onClick`. */\n disabled?: boolean;\n}\n\nexport interface TimelineProps extends HtmlProps {\n /** The entries to render, in display order (typically newest first for an audit log). */\n items?: TimelineItem[];\n /** Layout of entries relative to the connecting line (default `Left`). */\n alignment?: TimelineAlignment;\n className?: string;\n style?: React.CSSProperties;\n classNames?: SlotClassNames<TimelineSlots>;\n styles?: SlotStyles<TimelineSlots>;\n}\n"],"mappings":"aAMA,IAAY,EAAL,SAAA,EAAA,OAEL,GAAA,KAAA,OAEA,EAAA,MAAA,QAEA,EAAA,UAAA,aACF,EAAA,CAAA,CAAA"}
|