plass-ui 0.0.1 → 1.0.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/dist/components/accordion/PlAccordion.d.ts +98 -0
- package/dist/components/accordion/PlAccordion.js +131 -0
- package/dist/components/accordion/index.d.ts +2 -0
- package/dist/components/accordion/index.js +1 -0
- package/dist/components/alert/PlAlert.d.ts +50 -0
- package/dist/components/alert/PlAlert.js +109 -0
- package/dist/components/alert/index.d.ts +2 -0
- package/dist/components/alert/index.js +1 -0
- package/dist/components/animate-appear/PlAnimateAppear.d.ts +55 -0
- package/dist/components/animate-appear/PlAnimateAppear.js +71 -0
- package/dist/components/animate-appear/index.d.ts +2 -0
- package/dist/components/animate-appear/index.js +1 -0
- package/dist/components/animate-blink/PlAnimateBlink.d.ts +30 -0
- package/dist/components/animate-blink/PlAnimateBlink.js +47 -0
- package/dist/components/animate-blink/index.d.ts +2 -0
- package/dist/components/animate-blink/index.js +1 -0
- package/dist/components/animate-fade/PlAnimateFade.d.ts +35 -0
- package/dist/components/animate-fade/PlAnimateFade.js +48 -0
- package/dist/components/animate-fade/index.d.ts +2 -0
- package/dist/components/animate-fade/index.js +1 -0
- package/dist/components/animate-grow/PlAnimateGrow.d.ts +45 -0
- package/dist/components/animate-grow/PlAnimateGrow.js +49 -0
- package/dist/components/animate-grow/index.d.ts +2 -0
- package/dist/components/animate-grow/index.js +1 -0
- package/dist/components/animate-headline/PlAnimateHeadline.d.ts +55 -0
- package/dist/components/animate-headline/PlAnimateHeadline.js +120 -0
- package/dist/components/animate-headline/index.d.ts +2 -0
- package/dist/components/animate-headline/index.js +1 -0
- package/dist/components/animate-lighting/PlAnimateLighting.d.ts +67 -0
- package/dist/components/animate-lighting/PlAnimateLighting.js +65 -0
- package/dist/components/animate-lighting/index.d.ts +2 -0
- package/dist/components/animate-lighting/index.js +1 -0
- package/dist/components/animate-marquee/PlAnimateMarquee.d.ts +65 -0
- package/dist/components/animate-marquee/PlAnimateMarquee.js +94 -0
- package/dist/components/animate-marquee/index.d.ts +2 -0
- package/dist/components/animate-marquee/index.js +1 -0
- package/dist/components/animate-rotate/PlAnimateRotate.d.ts +52 -0
- package/dist/components/animate-rotate/PlAnimateRotate.js +50 -0
- package/dist/components/animate-rotate/index.d.ts +2 -0
- package/dist/components/animate-rotate/index.js +1 -0
- package/dist/components/animate-slide/PlAnimateSlide.d.ts +47 -0
- package/dist/components/animate-slide/PlAnimateSlide.js +49 -0
- package/dist/components/animate-slide/index.d.ts +2 -0
- package/dist/components/animate-slide/index.js +1 -0
- package/dist/components/animate-typing/PlAnimateTyping.d.ts +56 -0
- package/dist/components/animate-typing/PlAnimateTyping.js +177 -0
- package/dist/components/animate-typing/index.d.ts +2 -0
- package/dist/components/animate-typing/index.js +1 -0
- package/dist/components/animate-zoom/PlAnimateZoom.d.ts +37 -0
- package/dist/components/animate-zoom/PlAnimateZoom.js +45 -0
- package/dist/components/animate-zoom/index.d.ts +2 -0
- package/dist/components/animate-zoom/index.js +1 -0
- package/dist/components/aspect-ratio/PlAspectRatio.d.ts +64 -0
- package/dist/components/aspect-ratio/PlAspectRatio.js +58 -0
- package/dist/components/aspect-ratio/index.d.ts +2 -0
- package/dist/components/aspect-ratio/index.js +1 -0
- package/dist/components/avatar/PlAvatar.d.ts +102 -0
- package/dist/components/avatar/PlAvatar.js +121 -0
- package/dist/components/avatar/index.d.ts +2 -0
- package/dist/components/avatar/index.js +1 -0
- package/dist/components/badge/PlBadge.d.ts +86 -0
- package/dist/components/badge/PlBadge.js +168 -0
- package/dist/components/badge/index.d.ts +2 -0
- package/dist/components/badge/index.js +1 -0
- package/dist/components/blockquote/PlBlockquote.d.ts +64 -0
- package/dist/components/blockquote/PlBlockquote.js +112 -0
- package/dist/components/blockquote/index.d.ts +2 -0
- package/dist/components/blockquote/index.js +1 -0
- package/dist/components/bottom-navigation/PlBottomNavigation.d.ts +111 -0
- package/dist/components/bottom-navigation/PlBottomNavigation.js +141 -0
- package/dist/components/bottom-navigation/index.d.ts +2 -0
- package/dist/components/bottom-navigation/index.js +1 -0
- package/dist/components/box/PlBox.d.ts +50 -0
- package/dist/components/box/PlBox.js +46 -0
- package/dist/components/box/index.d.ts +2 -0
- package/dist/components/box/index.js +1 -0
- package/dist/components/breadcrumb/PlBreadcrumb.d.ts +138 -0
- package/dist/components/breadcrumb/PlBreadcrumb.js +201 -0
- package/dist/components/breadcrumb/index.d.ts +2 -0
- package/dist/components/breadcrumb/index.js +1 -0
- package/dist/components/button/{Button.d.ts → PlButton.d.ts} +3 -3
- package/dist/components/button/PlButton.js +196 -0
- package/dist/components/button/index.d.ts +2 -2
- package/dist/components/button/index.js +1 -1
- package/dist/components/button-group/PlButtonGroup.d.ts +32 -0
- package/dist/components/button-group/PlButtonGroup.js +64 -0
- package/dist/components/button-group/index.d.ts +2 -0
- package/dist/components/button-group/index.js +1 -0
- package/dist/components/card/PlCard.d.ts +81 -0
- package/dist/components/card/PlCard.js +102 -0
- package/dist/components/card/index.d.ts +2 -0
- package/dist/components/card/index.js +1 -0
- package/dist/components/carousel/PlCarousel.d.ts +78 -0
- package/dist/components/carousel/PlCarousel.js +177 -0
- package/dist/components/carousel/index.d.ts +2 -0
- package/dist/components/carousel/index.js +1 -0
- package/dist/components/chat-bubble/PlChatBubble.d.ts +127 -0
- package/dist/components/chat-bubble/PlChatBubble.js +206 -0
- package/dist/components/chat-bubble/index.d.ts +2 -0
- package/dist/components/chat-bubble/index.js +1 -0
- package/dist/components/checkbox/PlCheckbox.d.ts +39 -0
- package/dist/components/checkbox/PlCheckbox.js +100 -0
- package/dist/components/checkbox/index.d.ts +2 -0
- package/dist/components/checkbox/index.js +1 -0
- package/dist/components/chip/PlChip.d.ts +55 -0
- package/dist/components/chip/PlChip.js +144 -0
- package/dist/components/chip/index.d.ts +2 -0
- package/dist/components/chip/index.js +1 -0
- package/dist/components/collapsible/PlCollapsible.d.ts +84 -0
- package/dist/components/collapsible/PlCollapsible.js +65 -0
- package/dist/components/collapsible/index.d.ts +2 -0
- package/dist/components/collapsible/index.js +1 -0
- package/dist/components/combobox/PlCombobox.d.ts +140 -0
- package/dist/components/combobox/PlCombobox.js +199 -0
- package/dist/components/combobox/index.d.ts +2 -0
- package/dist/components/combobox/index.js +1 -0
- package/dist/components/container/PlContainer.d.ts +66 -0
- package/dist/components/container/PlContainer.js +47 -0
- package/dist/components/container/index.d.ts +2 -0
- package/dist/components/container/index.js +1 -0
- package/dist/components/date-picker/PlDatePicker.d.ts +73 -0
- package/dist/components/date-picker/PlDatePicker.js +87 -0
- package/dist/components/date-picker/index.d.ts +2 -0
- package/dist/components/date-picker/index.js +1 -0
- package/dist/components/date-range-picker/PlDateRangePicker.d.ts +91 -0
- package/dist/components/date-range-picker/PlDateRangePicker.js +152 -0
- package/dist/components/date-range-picker/index.d.ts +2 -0
- package/dist/components/date-range-picker/index.js +1 -0
- package/dist/components/date-time-picker/PlDateTimePicker.d.ts +74 -0
- package/dist/components/date-time-picker/PlDateTimePicker.js +106 -0
- package/dist/components/date-time-picker/index.d.ts +2 -0
- package/dist/components/date-time-picker/index.js +1 -0
- package/dist/components/divider/PlDivider.d.ts +73 -0
- package/dist/components/divider/PlDivider.js +107 -0
- package/dist/components/divider/index.d.ts +2 -0
- package/dist/components/divider/index.js +1 -0
- package/dist/components/drawer/PlDrawer.d.ts +144 -0
- package/dist/components/drawer/PlDrawer.js +190 -0
- package/dist/components/drawer/index.d.ts +2 -0
- package/dist/components/drawer/index.js +1 -0
- package/dist/components/file-picker/PlFilePicker.d.ts +105 -0
- package/dist/components/file-picker/PlFilePicker.js +274 -0
- package/dist/components/file-picker/index.d.ts +2 -0
- package/dist/components/file-picker/index.js +1 -0
- package/dist/components/floating-bottom-navigation/PlFloatingBottomNavigation.d.ts +118 -0
- package/dist/components/floating-bottom-navigation/PlFloatingBottomNavigation.js +291 -0
- package/dist/components/floating-bottom-navigation/index.d.ts +2 -0
- package/dist/components/floating-bottom-navigation/index.js +1 -0
- package/dist/components/grid/PlGrid.d.ts +67 -0
- package/dist/components/grid/PlGrid.js +51 -0
- package/dist/components/grid/PlGridItem.d.ts +50 -0
- package/dist/components/grid/PlGridItem.js +34 -0
- package/dist/components/grid/index.d.ts +4 -0
- package/dist/components/grid/index.js +2 -0
- package/dist/components/highlight/PlHighlight.d.ts +90 -0
- package/dist/components/highlight/PlHighlight.js +185 -0
- package/dist/components/highlight/index.d.ts +2 -0
- package/dist/components/highlight/index.js +1 -0
- package/dist/components/hot-keys/PlHotKeys.d.ts +93 -0
- package/dist/components/hot-keys/PlHotKeys.js +294 -0
- package/dist/components/hot-keys/index.d.ts +2 -0
- package/dist/components/hot-keys/index.js +1 -0
- package/dist/components/icon/PlIcon.d.ts +62 -0
- package/dist/components/icon/PlIcon.js +58 -0
- package/dist/components/icon/index.d.ts +2 -0
- package/dist/components/icon/index.js +1 -0
- package/dist/components/icon-button/PlIconButton.d.ts +39 -0
- package/dist/components/icon-button/PlIconButton.js +37 -0
- package/dist/components/icon-button/index.d.ts +2 -0
- package/dist/components/icon-button/index.js +1 -0
- package/dist/components/list/PlList.d.ts +82 -0
- package/dist/components/list/PlList.js +160 -0
- package/dist/components/list/index.d.ts +2 -0
- package/dist/components/list/index.js +1 -0
- package/dist/components/menu/PlMenu.d.ts +210 -0
- package/dist/components/menu/PlMenu.js +209 -0
- package/dist/components/menu/index.d.ts +2 -0
- package/dist/components/menu/index.js +1 -0
- package/dist/components/modal/PlModal.d.ts +112 -0
- package/dist/components/modal/PlModal.js +150 -0
- package/dist/components/modal/index.d.ts +2 -0
- package/dist/components/modal/index.js +1 -0
- package/dist/components/number-field/PlNumberField.d.ts +133 -0
- package/dist/components/number-field/PlNumberField.js +111 -0
- package/dist/components/number-field/index.d.ts +2 -0
- package/dist/components/number-field/index.js +1 -0
- package/dist/components/otp-field/PlOtpField.d.ts +82 -0
- package/dist/components/otp-field/PlOtpField.js +109 -0
- package/dist/components/otp-field/index.d.ts +2 -0
- package/dist/components/otp-field/index.js +1 -0
- package/dist/components/overlay/PlOverlay.d.ts +96 -0
- package/dist/components/overlay/PlOverlay.js +77 -0
- package/dist/components/overlay/index.d.ts +2 -0
- package/dist/components/overlay/index.js +1 -0
- package/dist/components/pagination/PlPagination.d.ts +88 -0
- package/dist/components/pagination/PlPagination.js +159 -0
- package/dist/components/pagination/index.d.ts +2 -0
- package/dist/components/pagination/index.js +1 -0
- package/dist/components/panes/PlPanes.d.ts +79 -0
- package/dist/components/panes/PlPanes.js +324 -0
- package/dist/components/panes/index.d.ts +2 -0
- package/dist/components/panes/index.js +1 -0
- package/dist/components/pill/PlPill.d.ts +81 -0
- package/dist/components/pill/PlPill.js +154 -0
- package/dist/components/pill/index.d.ts +2 -0
- package/dist/components/pill/index.js +1 -0
- package/dist/components/popover/PlPopover.d.ts +107 -0
- package/dist/components/popover/PlPopover.js +113 -0
- package/dist/components/popover/index.d.ts +2 -0
- package/dist/components/popover/index.js +1 -0
- package/dist/components/progress-box/PlProgressBox.d.ts +32 -0
- package/dist/components/progress-box/PlProgressBox.js +34 -0
- package/dist/components/progress-box/index.d.ts +2 -0
- package/dist/components/progress-box/index.js +1 -0
- package/dist/components/progress-circular/PlProgressCircular.d.ts +22 -0
- package/dist/components/progress-circular/PlProgressCircular.js +47 -0
- package/dist/components/progress-circular/index.d.ts +2 -0
- package/dist/components/progress-circular/index.js +1 -0
- package/dist/components/progress-linear/PlProgressLinear.d.ts +31 -0
- package/dist/components/progress-linear/PlProgressLinear.js +40 -0
- package/dist/components/progress-linear/index.d.ts +2 -0
- package/dist/components/progress-linear/index.js +1 -0
- package/dist/components/radio-group/PlRadioGroup.d.ts +54 -0
- package/dist/components/radio-group/PlRadioGroup.js +99 -0
- package/dist/components/radio-group/index.d.ts +2 -0
- package/dist/components/radio-group/index.js +1 -0
- package/dist/components/rating/PlRating.d.ts +90 -0
- package/dist/components/rating/PlRating.js +101 -0
- package/dist/components/rating/index.d.ts +2 -0
- package/dist/components/rating/index.js +1 -0
- package/dist/components/scroll-zone/PlScrollZone.d.ts +132 -0
- package/dist/components/scroll-zone/PlScrollZone.js +411 -0
- package/dist/components/scroll-zone/index.d.ts +2 -0
- package/dist/components/scroll-zone/index.js +1 -0
- package/dist/components/segmented-button/PlSegmentedButton.d.ts +79 -0
- package/dist/components/segmented-button/PlSegmentedButton.js +206 -0
- package/dist/components/segmented-button/index.d.ts +2 -0
- package/dist/components/segmented-button/index.js +1 -0
- package/dist/components/select/PlSelect.d.ts +77 -0
- package/dist/components/select/PlSelect.js +115 -0
- package/dist/components/select/index.d.ts +2 -0
- package/dist/components/select/index.js +1 -0
- package/dist/components/skeleton/PlSkeleton.d.ts +73 -0
- package/dist/components/skeleton/PlSkeleton.js +142 -0
- package/dist/components/skeleton/index.d.ts +2 -0
- package/dist/components/skeleton/index.js +1 -0
- package/dist/components/slider/PlSlider.d.ts +44 -0
- package/dist/components/slider/PlSlider.js +132 -0
- package/dist/components/slider/index.d.ts +2 -0
- package/dist/components/slider/index.js +1 -0
- package/dist/components/spoiler/PlSpoiler.d.ts +84 -0
- package/dist/components/spoiler/PlSpoiler.js +74 -0
- package/dist/components/spoiler/index.d.ts +2 -0
- package/dist/components/spoiler/index.js +1 -0
- package/dist/components/switch/PlSwitch.d.ts +42 -0
- package/dist/components/switch/PlSwitch.js +131 -0
- package/dist/components/switch/index.d.ts +2 -0
- package/dist/components/switch/index.js +1 -0
- package/dist/components/table/PlTable.d.ts +112 -0
- package/dist/components/table/PlTable.js +210 -0
- package/dist/components/table/index.d.ts +2 -0
- package/dist/components/table/index.js +1 -0
- package/dist/components/tabs/PlTabs.d.ts +94 -0
- package/dist/components/tabs/PlTabs.js +182 -0
- package/dist/components/tabs/index.d.ts +2 -0
- package/dist/components/tabs/index.js +1 -0
- package/dist/components/text-field/{TextField.d.ts → PlTextField.d.ts} +5 -5
- package/dist/components/text-field/PlTextField.js +126 -0
- package/dist/components/text-field/index.d.ts +2 -2
- package/dist/components/text-field/index.js +1 -1
- package/dist/components/text-link/PlTextLink.d.ts +80 -0
- package/dist/components/text-link/PlTextLink.js +136 -0
- package/dist/components/text-link/index.d.ts +2 -0
- package/dist/components/text-link/index.js +1 -0
- package/dist/components/time-picker/PlTimePicker.d.ts +88 -0
- package/dist/components/time-picker/PlTimePicker.js +97 -0
- package/dist/components/time-picker/index.d.ts +2 -0
- package/dist/components/time-picker/index.js +1 -0
- package/dist/components/timeline/PlTimeline.d.ts +98 -0
- package/dist/components/timeline/PlTimeline.js +207 -0
- package/dist/components/timeline/index.d.ts +2 -0
- package/dist/components/timeline/index.js +1 -0
- package/dist/components/toast/PlToast.d.ts +122 -0
- package/dist/components/toast/PlToast.js +174 -0
- package/dist/components/toast/index.d.ts +2 -0
- package/dist/components/toast/index.js +1 -0
- package/dist/components/toolbar/PlToolbar.d.ts +68 -0
- package/dist/components/toolbar/PlToolbar.js +65 -0
- package/dist/components/toolbar/index.d.ts +2 -0
- package/dist/components/toolbar/index.js +1 -0
- package/dist/components/tooltip/PlTooltip.d.ts +92 -0
- package/dist/components/tooltip/PlTooltip.js +117 -0
- package/dist/components/tooltip/index.d.ts +2 -0
- package/dist/components/tooltip/index.js +1 -0
- package/dist/components/typography/PlTypography.d.ts +66 -0
- package/dist/components/typography/PlTypography.js +143 -0
- package/dist/components/typography/index.d.ts +2 -0
- package/dist/components/typography/index.js +1 -0
- package/dist/css/accordion.css +2 -0
- package/dist/css/alert.css +2 -0
- package/dist/css/animate-appear.css +2 -0
- package/dist/css/animate-blink.css +2 -0
- package/dist/css/animate-fade.css +2 -0
- package/dist/css/animate-grow.css +2 -0
- package/dist/css/animate-headline.css +2 -0
- package/dist/css/animate-lighting.css +2 -0
- package/dist/css/animate-marquee.css +2 -0
- package/dist/css/animate-rotate.css +2 -0
- package/dist/css/animate-slide.css +2 -0
- package/dist/css/animate-typing.css +2 -0
- package/dist/css/animate-zoom.css +2 -0
- package/dist/css/aspect-ratio.css +2 -0
- package/dist/css/avatar.css +2 -0
- package/dist/css/badge.css +2 -0
- package/dist/css/base.css +4 -0
- package/dist/css/blockquote.css +2 -0
- package/dist/css/bottom-navigation.css +2 -0
- package/dist/css/box.css +2 -0
- package/dist/css/breadcrumb.css +2 -0
- package/dist/css/button-group.css +2 -0
- package/dist/css/button.css +2 -0
- package/dist/css/card.css +2 -0
- package/dist/css/carousel.css +2 -0
- package/dist/css/chat-bubble.css +2 -0
- package/dist/css/checkbox.css +2 -0
- package/dist/css/chip.css +2 -0
- package/dist/css/collapsible.css +2 -0
- package/dist/css/combobox.css +2 -0
- package/dist/css/container.css +2 -0
- package/dist/css/date-picker.css +2 -0
- package/dist/css/date-range-picker.css +2 -0
- package/dist/css/date-time-picker.css +2 -0
- package/dist/css/divider.css +2 -0
- package/dist/css/drawer.css +2 -0
- package/dist/css/file-picker.css +2 -0
- package/dist/css/floating-bottom-navigation.css +2 -0
- package/dist/css/grid.css +2 -0
- package/dist/css/highlight.css +2 -0
- package/dist/css/hot-keys.css +2 -0
- package/dist/css/icon-button.css +2 -0
- package/dist/css/icon.css +2 -0
- package/dist/css/list.css +2 -0
- package/dist/css/menu.css +2 -0
- package/dist/css/modal.css +2 -0
- package/dist/css/number-field.css +2 -0
- package/dist/css/otp-field.css +2 -0
- package/dist/css/overlay.css +2 -0
- package/dist/css/pagination.css +2 -0
- package/dist/css/panes.css +2 -0
- package/dist/css/pill.css +2 -0
- package/dist/css/popover.css +2 -0
- package/dist/css/progress-box.css +2 -0
- package/dist/css/progress-circular.css +2 -0
- package/dist/css/progress-linear.css +2 -0
- package/dist/css/radio-group.css +2 -0
- package/dist/css/rating.css +2 -0
- package/dist/css/scroll-zone.css +2 -0
- package/dist/css/segmented-button.css +2 -0
- package/dist/css/select.css +2 -0
- package/dist/css/skeleton.css +2 -0
- package/dist/css/slider.css +2 -0
- package/dist/css/spoiler.css +2 -0
- package/dist/css/switch.css +2 -0
- package/dist/css/table.css +2 -0
- package/dist/css/tabs.css +2 -0
- package/dist/css/text-field.css +2 -0
- package/dist/css/text-link.css +2 -0
- package/dist/css/time-picker.css +2 -0
- package/dist/css/timeline.css +2 -0
- package/dist/css/toast.css +2 -0
- package/dist/css/toolbar.css +2 -0
- package/dist/css/tooltip.css +2 -0
- package/dist/css/typography.css +2 -0
- package/dist/index.d.ts +75 -3
- package/dist/index.js +75 -1
- package/dist/internal/animate.d.ts +161 -0
- package/dist/internal/animate.js +318 -0
- package/dist/internal/button-group.d.ts +27 -0
- package/dist/internal/button-group.js +19 -0
- package/dist/internal/calendar.d.ts +148 -0
- package/dist/internal/calendar.js +501 -0
- package/dist/internal/date.d.ts +173 -0
- package/dist/internal/date.js +353 -0
- package/dist/internal/format.d.ts +24 -0
- package/dist/internal/format.js +41 -0
- package/dist/internal/grid.d.ts +67 -0
- package/dist/internal/grid.js +143 -0
- package/dist/internal/icons.d.ts +86 -1
- package/dist/internal/icons.js +138 -1
- package/dist/internal/menu.d.ts +20 -0
- package/dist/internal/menu.js +18 -0
- package/dist/internal/picker.d.ts +118 -0
- package/dist/internal/picker.js +139 -0
- package/dist/internal/progress.d.ts +145 -0
- package/dist/internal/progress.js +167 -0
- package/dist/internal/sizer.d.ts +32 -0
- package/dist/internal/sizer.js +35 -0
- package/dist/internal/styles.d.ts +198 -8
- package/dist/internal/styles.js +636 -1
- package/dist/styles.css +1 -1
- package/dist/tailwind.css +899 -125
- package/dist/tokens.css +1275 -0
- package/dist/types.d.ts +150 -8
- package/dist/types.js +1 -1
- package/package.json +31 -27
- package/README.md +0 -111
- package/dist/components/button/Button.js +0 -1
- package/dist/components/text-field/TextField.js +0 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { ButtonGroupContext } from '../../internal/button-group.js';
|
|
4
|
+
import { cx } from '../../internal/styles.js';
|
|
5
|
+
/**
|
|
6
|
+
* The corners that face a neighbour are squared off, so the run reads as one
|
|
7
|
+
* piece scored into segments rather than as three keys that happen to be
|
|
8
|
+
* touching.
|
|
9
|
+
*
|
|
10
|
+
* Logical properties (`s`/`e`) rather than left/right: under RTL the first
|
|
11
|
+
* button is on the right, and `rounded-l-none` would flatten the wrong side.
|
|
12
|
+
*/
|
|
13
|
+
const joinClasses = {
|
|
14
|
+
horizontal: '[&>*:not(:first-child)]:rounded-s-none [&>*:not(:last-child)]:rounded-e-none',
|
|
15
|
+
vertical: '[&>*:not(:first-child)]:rounded-t-none [&>*:not(:last-child)]:rounded-b-none'
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Only `glass` needs the overlap, because it is the only variant that draws an
|
|
19
|
+
* edge. Two glass keys meeting would otherwise show both of their hairlines and
|
|
20
|
+
* the seam would be twice as heavy as every other edge on the page; pulling the
|
|
21
|
+
* second one back a pixel makes the two share one line.
|
|
22
|
+
*
|
|
23
|
+
* A `solid` group must **not** do this. Its keys have no border to double up,
|
|
24
|
+
* and overlapping would put one gradient over the start of the next — which is
|
|
25
|
+
* exactly the join the squared corners are drawing.
|
|
26
|
+
*/
|
|
27
|
+
const overlapClasses = {
|
|
28
|
+
horizontal: '[&>*:not(:first-child)]:-ms-px',
|
|
29
|
+
vertical: '[&>*:not(:first-child)]:-mt-px'
|
|
30
|
+
};
|
|
31
|
+
const baseClasses = /* @__PURE__ */ [
|
|
32
|
+
'inline-flex align-middle',
|
|
33
|
+
// Every child gets a stacking context so the hovered or focused one can come
|
|
34
|
+
// forward. Without it the focus ring — which is drawn outside the border box —
|
|
35
|
+
// is painted over by whichever neighbour happens to come after it.
|
|
36
|
+
'[&>*]:relative [&>*:hover]:z-10 [&>*:focus-visible]:z-10',
|
|
37
|
+
// A group is a set of equal actions, so they stay the same height even when
|
|
38
|
+
// one of them has an icon and the others do not.
|
|
39
|
+
'[&>*]:shrink-0'
|
|
40
|
+
].join(' ');
|
|
41
|
+
/**
|
|
42
|
+
* A run of buttons that belong together.
|
|
43
|
+
*
|
|
44
|
+
* Two things are happening here and only one of them is visual. The corners
|
|
45
|
+
* that face a neighbour are squared off — that is the look. The other half is
|
|
46
|
+
* that `variant`, `size`, `color`, `density`, `elevation` and `disabled` are
|
|
47
|
+
* stated once for the set rather than repeated on every button; a group where
|
|
48
|
+
* one button is a size out is the failure this exists to prevent.
|
|
49
|
+
*
|
|
50
|
+
* The buttons stay real `PlButton`s and nothing about them is replaced. Which
|
|
51
|
+
* also means this is **not** a segmented control and it does not manage
|
|
52
|
+
* selection: for one-of-a-set reach for `PlSegmentedButton`, which is what that
|
|
53
|
+
* actually is.
|
|
54
|
+
*/
|
|
55
|
+
export const PlButtonGroup = /* @__PURE__ */ React.forwardRef(function PlButtonGroup({ variant, size, color, density, elevation, orientation = 'horizontal', disabled, fullWidth = false, className, children, ...props }, ref) {
|
|
56
|
+
// Every value is passed through as it arrived, `undefined` included. A
|
|
57
|
+
// PlButton reads the group only as a fallback, so "not set here" goes on
|
|
58
|
+
// meaning "use the button's own default" rather than turning into one.
|
|
59
|
+
const context = React.useMemo(() => ({ variant, size, color, density, elevation, disabled }), [variant, size, color, density, elevation, disabled]);
|
|
60
|
+
return (_jsx(ButtonGroupContext.Provider, { value: context, children: _jsx("div", { ref: ref, role: "group", className: cx(baseClasses, orientation === 'vertical' ? 'flex-col' : 'flex-row', joinClasses[orientation],
|
|
61
|
+
// `variant` defaults to `solid` on a PlButton, so a group that says
|
|
62
|
+
// nothing is a solid group and must not overlap.
|
|
63
|
+
(variant ?? 'solid') === 'glass' ? overlapClasses[orientation] : '', fullWidth ? 'flex w-full [&>*]:flex-1' : '', className), ...props, children: children }) }));
|
|
64
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PlButtonGroup } from './PlButtonGroup.js';
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
3
|
+
import type { PlassElevation, PlassStyleProps } from '../../types.js';
|
|
4
|
+
export interface PlCardProps extends PlassStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'title'> {
|
|
5
|
+
/**
|
|
6
|
+
* Drop shadow depth. `1` is the default: a card is a sheet lying **on** the
|
|
7
|
+
* page wash rather than printed into it, and the small amount of grey under
|
|
8
|
+
* it is what says so.
|
|
9
|
+
* @default 1
|
|
10
|
+
*/
|
|
11
|
+
elevation?: PlassElevation;
|
|
12
|
+
/**
|
|
13
|
+
* The card's heading. A plain string is styled as the title; pass a real
|
|
14
|
+
* heading element (`title={<h2>…</h2>}`) when the card belongs in the
|
|
15
|
+
* document outline — it inherits the title's typography rather than the
|
|
16
|
+
* browser's.
|
|
17
|
+
*/
|
|
18
|
+
title?: React.ReactNode;
|
|
19
|
+
/** A second line under the title, one step down the type scale and muted. */
|
|
20
|
+
subtitle?: React.ReactNode;
|
|
21
|
+
/**
|
|
22
|
+
* Content pinned to the end of the header row — a menu button, a status
|
|
23
|
+
* chip. Stays on the title's line while the title wraps beside it.
|
|
24
|
+
*/
|
|
25
|
+
headerAction?: React.ReactNode;
|
|
26
|
+
/**
|
|
27
|
+
* The bottom area. Laid out as a wrapping row so a pair of buttons needs no
|
|
28
|
+
* wrapper of its own; anything else can bring its own layout.
|
|
29
|
+
*/
|
|
30
|
+
footer?: React.ReactNode;
|
|
31
|
+
/**
|
|
32
|
+
* Scores the sheet between sections with a hairline instead of separating
|
|
33
|
+
* them with space. The rules run the full width, so the padding moves from
|
|
34
|
+
* the card onto each section.
|
|
35
|
+
* @default false
|
|
36
|
+
*/
|
|
37
|
+
dividers?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Inner padding, on the `size` / `density` scale. Turn it off for full-bleed
|
|
40
|
+
* content — an image, a table, a list that draws its own rows.
|
|
41
|
+
* @default true
|
|
42
|
+
*/
|
|
43
|
+
padded?: boolean;
|
|
44
|
+
/**
|
|
45
|
+
* Lifts the sheet under the pointer and adds a level of elevation.
|
|
46
|
+
*
|
|
47
|
+
* This is the one place the library allows a `transform`, and the exception
|
|
48
|
+
* is the rule rather than a hole in it: what may not move is the thing under
|
|
49
|
+
* the finger — a key whose label resamples as it scales. A sheet that
|
|
50
|
+
* *holds* content is the other kind of surface, and lifting one is how a
|
|
51
|
+
* pane of glass says it can be picked up.
|
|
52
|
+
*
|
|
53
|
+
* It changes how the card looks and nothing else. A card that is actually
|
|
54
|
+
* clickable has to be a real element: `render={<a href="…" />}` or
|
|
55
|
+
* `render={<button type="button" />}`, so it is focusable, announced, and
|
|
56
|
+
* reachable from a keyboard.
|
|
57
|
+
* @default false
|
|
58
|
+
*/
|
|
59
|
+
interactive?: boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Renders something other than a `<div>`: `render={<section />}`,
|
|
62
|
+
* `render={<li />}`, `render={<a href="…" />}`. Base UI's own escape hatch.
|
|
63
|
+
*/
|
|
64
|
+
render?: useRender.RenderProp;
|
|
65
|
+
/** The card's body. */
|
|
66
|
+
children?: React.ReactNode;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The sheet everything else on a screen is grouped onto, with the parts a card
|
|
70
|
+
* is made of laid out on it: a title, a subtitle, a body and a footer.
|
|
71
|
+
*
|
|
72
|
+
* The sections are props rather than compound sub-components — `<Card.Header>`,
|
|
73
|
+
* `<Card.Title>` — for the same reason `PlTextField` takes `label` and
|
|
74
|
+
* `description` as props: the arrangement is fixed, and what a caller wants to
|
|
75
|
+
* decide is what goes in each slot, not what order the slots come in.
|
|
76
|
+
*
|
|
77
|
+
* There is no Base UI primitive under this, and there should not be. A card has
|
|
78
|
+
* no interaction to delegate: it is a surface with a layout, and the moment it
|
|
79
|
+
* becomes something you press it is a `render` away from being a real one.
|
|
80
|
+
*/
|
|
81
|
+
export declare const PlCard: React.ForwardRefExoticComponent<PlCardProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
4
|
+
import { focusRingClasses, hasContent, metaTextClasses, radiusClasses, sheetBodyClasses, sheetHeaderGapClasses, sheetLineClasses, sheetPaddingXClasses, sheetPaddingYClasses, sheetRestClasses, sheetSectionGapClasses, sheetTitleClasses, surfaceSlots } from '../../internal/styles.js';
|
|
5
|
+
/**
|
|
6
|
+
* The house transition with `transform` added to the property list.
|
|
7
|
+
*
|
|
8
|
+
* `transitionClasses` deliberately leaves it out, because no *control* may be
|
|
9
|
+
* transformed. A card is the other kind of surface, so it writes its own list
|
|
10
|
+
* rather than stacking a `transition-[transform]` on top of the shared one —
|
|
11
|
+
* two `transition-property` declarations of equal specificity resolve by their
|
|
12
|
+
* order in the generated stylesheet, which is not something a component should
|
|
13
|
+
* depend on.
|
|
14
|
+
*/
|
|
15
|
+
const cardTransitionClasses = /* @__PURE__ */ [
|
|
16
|
+
'[transition-property:background-color,border-color,box-shadow,color,transform]',
|
|
17
|
+
'[transition-duration:var(--plass-duration)]',
|
|
18
|
+
'[transition-timing-function:var(--plass-ease)]'
|
|
19
|
+
].join(' ');
|
|
20
|
+
/**
|
|
21
|
+
* Hover lifts the sheet and puts a level of shadow under it; the press sets it
|
|
22
|
+
* back down. Both directions take the house duration, and no `filter` is
|
|
23
|
+
* involved — a card is not a coloured surface, so there is no brightness to
|
|
24
|
+
* turn up.
|
|
25
|
+
*/
|
|
26
|
+
const interactiveClasses = {
|
|
27
|
+
solid: /* @__PURE__ */ [
|
|
28
|
+
'cursor-pointer hover:-translate-y-0.5',
|
|
29
|
+
'hover:[box-shadow:var(--p-elev-hover),var(--plass-gloss-glass)]',
|
|
30
|
+
'active:translate-y-0 active:[box-shadow:var(--p-elev-press),var(--plass-gloss-glass)]'
|
|
31
|
+
].join(' '),
|
|
32
|
+
glass: /* @__PURE__ */ [
|
|
33
|
+
'cursor-pointer hover:-translate-y-0.5 hover:bg-(--plass-glass-hover)',
|
|
34
|
+
'hover:[border-color:var(--p-line)]',
|
|
35
|
+
'hover:[box-shadow:var(--p-elev-hover),var(--plass-gloss-glass)]',
|
|
36
|
+
'active:translate-y-0 active:[box-shadow:var(--p-elev-press),var(--plass-gloss-glass)]'
|
|
37
|
+
].join(' '),
|
|
38
|
+
ghost: 'cursor-pointer hover:bg-(--p-soft) active:bg-(--p-soft-hover)'
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* The sheet everything else on a screen is grouped onto, with the parts a card
|
|
42
|
+
* is made of laid out on it: a title, a subtitle, a body and a footer.
|
|
43
|
+
*
|
|
44
|
+
* The sections are props rather than compound sub-components — `<Card.Header>`,
|
|
45
|
+
* `<Card.Title>` — for the same reason `PlTextField` takes `label` and
|
|
46
|
+
* `description` as props: the arrangement is fixed, and what a caller wants to
|
|
47
|
+
* decide is what goes in each slot, not what order the slots come in.
|
|
48
|
+
*
|
|
49
|
+
* There is no Base UI primitive under this, and there should not be. A card has
|
|
50
|
+
* no interaction to delegate: it is a surface with a layout, and the moment it
|
|
51
|
+
* becomes something you press it is a `render` away from being a real one.
|
|
52
|
+
*/
|
|
53
|
+
export const PlCard = /* @__PURE__ */ React.forwardRef(function PlCard({ variant = 'glass', size = 'md', color = 'primary', density = 'default', elevation = 1, title, subtitle, headerAction, footer, dividers = false, padded = true, interactive = false, render, className, style, children, ...props }, ref) {
|
|
54
|
+
const insetX = padded ? sheetPaddingXClasses[density][size] : '';
|
|
55
|
+
const insetY = padded ? sheetPaddingYClasses[density][size] : '';
|
|
56
|
+
// Scored, the rules have to reach both edges, so the sheet gives up its
|
|
57
|
+
// padding and every section takes it on instead. Unscored, the sheet keeps
|
|
58
|
+
// its vertical padding and the sections are told apart by a gap.
|
|
59
|
+
const sectionClasses = dividers ? `${insetX} ${insetY}` : insetX;
|
|
60
|
+
const hasHeader = hasContent(title) || hasContent(subtitle) || hasContent(headerAction);
|
|
61
|
+
const header = (_jsxs(_Fragment, { children: [hasContent(title) || hasContent(subtitle) ? (_jsxs("div", { className: `flex min-w-0 flex-1 flex-col ${sheetHeaderGapClasses[size]}`, children: [hasContent(title) ? (_jsx("div", { className: `plass-title font-semibold ${sheetTitleClasses[size]}`, children: title })) : null, hasContent(subtitle) ? (_jsx("div", { className: `text-(--plass-muted-fg) ${metaTextClasses[size]}`, children: subtitle })) : null] })) : null, hasContent(headerAction) ? _jsx("div", { className: "ml-auto shrink-0", children: headerAction }) : null] }));
|
|
62
|
+
const sections = [
|
|
63
|
+
hasHeader ? { key: 'header', className: 'flex items-start gap-3', content: header } : null,
|
|
64
|
+
hasContent(children)
|
|
65
|
+
? { key: 'content', className: sheetBodyClasses[size], content: children }
|
|
66
|
+
: null,
|
|
67
|
+
hasContent(footer)
|
|
68
|
+
? {
|
|
69
|
+
key: 'footer',
|
|
70
|
+
className: `flex flex-wrap items-center gap-2 ${sheetBodyClasses[size]}`,
|
|
71
|
+
content: footer
|
|
72
|
+
}
|
|
73
|
+
: null
|
|
74
|
+
].filter((section) => section !== null);
|
|
75
|
+
const classNames = [
|
|
76
|
+
'flex flex-col',
|
|
77
|
+
radiusClasses[size],
|
|
78
|
+
sheetRestClasses[variant],
|
|
79
|
+
cardTransitionClasses,
|
|
80
|
+
interactive ? `${interactiveClasses[variant]} ${focusRingClasses}` : '',
|
|
81
|
+
dividers ? 'overflow-hidden' : `${insetY} ${sheetSectionGapClasses[size]}`,
|
|
82
|
+
className ?? ''
|
|
83
|
+
]
|
|
84
|
+
.filter(Boolean)
|
|
85
|
+
.join(' ');
|
|
86
|
+
return useRender({
|
|
87
|
+
render: render ?? _jsx("div", {}),
|
|
88
|
+
ref,
|
|
89
|
+
props: {
|
|
90
|
+
className: classNames,
|
|
91
|
+
style: { ...surfaceSlots(color, elevation), ...style },
|
|
92
|
+
...props,
|
|
93
|
+
children: sections.map((section, index) => (_jsx("div", { className: [
|
|
94
|
+
sectionClasses,
|
|
95
|
+
section.className,
|
|
96
|
+
dividers && index > 0 ? sheetLineClasses : ''
|
|
97
|
+
]
|
|
98
|
+
.filter(Boolean)
|
|
99
|
+
.join(' '), children: section.content }, section.key)))
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PlCard } from './PlCard.js';
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PlassElevation, PlassStyleProps } from '../../types.js';
|
|
3
|
+
export interface PlCarouselProps extends PlassStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'defaultValue' | 'onChange'> {
|
|
4
|
+
/**
|
|
5
|
+
* Drop shadow depth of the frame. `0` — the default — is flat.
|
|
6
|
+
* @default 0
|
|
7
|
+
*/
|
|
8
|
+
elevation?: PlassElevation;
|
|
9
|
+
/** Which slide is showing, counted from 0. Use with `onValueChange`. */
|
|
10
|
+
value?: number;
|
|
11
|
+
/** Which starts showing, for an uncontrolled carousel. @default 0 */
|
|
12
|
+
defaultValue?: number;
|
|
13
|
+
onValueChange?: (index: number) => void;
|
|
14
|
+
/**
|
|
15
|
+
* Whether the arrows wrap from the last slide back to the first. With it off
|
|
16
|
+
* they go inert at the ends instead, which is the honest thing for a set that
|
|
17
|
+
* has a beginning and an end — a gallery of three photographs does, a
|
|
18
|
+
* rotating banner does not.
|
|
19
|
+
* @default true
|
|
20
|
+
*/
|
|
21
|
+
loop?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Advances on its own.
|
|
24
|
+
*
|
|
25
|
+
* Off by default and deliberately so: a carousel that moves while it is being
|
|
26
|
+
* read is the most complained-about pattern on the web. It pauses on hover,
|
|
27
|
+
* on focus anywhere inside it, while the tab is in the background, and it
|
|
28
|
+
* does not start at all for a reader who has asked for reduced motion.
|
|
29
|
+
* @default false
|
|
30
|
+
*/
|
|
31
|
+
autoPlay?: boolean;
|
|
32
|
+
/** How long each slide is held, in milliseconds. @default 5000 */
|
|
33
|
+
interval?: number;
|
|
34
|
+
/** The previous/next buttons. @default true */
|
|
35
|
+
arrows?: boolean;
|
|
36
|
+
/** The row of position dots under the frame. @default true */
|
|
37
|
+
indicators?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* The carousel's accessible name, and what the arrows and the dots are called.
|
|
40
|
+
* Never drawn.
|
|
41
|
+
* @default 'Carousel'
|
|
42
|
+
*/
|
|
43
|
+
label?: string;
|
|
44
|
+
/** @default 'Previous slide' */
|
|
45
|
+
previousLabel?: string;
|
|
46
|
+
/** @default 'Next slide' */
|
|
47
|
+
nextLabel?: string;
|
|
48
|
+
/**
|
|
49
|
+
* How one slide is named to a screen reader, and how its dot is labelled.
|
|
50
|
+
* @default (index, count) => `Slide ${index} of ${count}`
|
|
51
|
+
*/
|
|
52
|
+
slideLabel?: (index: number, count: number) => string;
|
|
53
|
+
/** The slides. Every top-level child becomes one. */
|
|
54
|
+
children?: React.ReactNode;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* A strip of slides, one of which is in view.
|
|
58
|
+
*
|
|
59
|
+
* The mechanism is a scroll container with CSS scroll snapping, and everything
|
|
60
|
+
* good about this component follows from that one choice. Swiping on a phone
|
|
61
|
+
* and two-finger dragging on a trackpad both work because they are the
|
|
62
|
+
* browser's own scrolling and not a gesture handler pretending to be it. The
|
|
63
|
+
* strip runs the other way under RTL without being told, because scrolling is
|
|
64
|
+
* directional and `translate` is not. And nothing is transformed — the house
|
|
65
|
+
* rule against moving a surface holds here for free, where a translated track
|
|
66
|
+
* would have had to argue for an exception.
|
|
67
|
+
*
|
|
68
|
+
* The motion is `scroll-behavior: smooth`, which means a reader who has asked
|
|
69
|
+
* for reduced motion gets an instant cut from the same code path rather than
|
|
70
|
+
* from a second one written to remember them.
|
|
71
|
+
*
|
|
72
|
+
* Slides are not a sub-component. Every top-level child is wrapped in its own
|
|
73
|
+
* slide, so `<PlCarousel><img /><img /></PlCarousel>` is the whole API — and the
|
|
74
|
+
* wrapper is what carries the snap point, the width and the
|
|
75
|
+
* `role="group"` / `aria-roledescription="slide"` pair a screen reader needs,
|
|
76
|
+
* none of which a caller should have to remember to put on a photograph.
|
|
77
|
+
*/
|
|
78
|
+
export declare const PlCarousel: React.ForwardRefExoticComponent<PlCarouselProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { PlIconButton } from '../icon-button/PlIconButton.js';
|
|
4
|
+
import { ChevronIcon } from '../../internal/icons.js';
|
|
5
|
+
import { cx, radiusClasses, sheetRestClasses, srOnlyClasses, surfaceSlots, transitionClasses } from '../../internal/styles.js';
|
|
6
|
+
/** How far the arrows sit in from the frame's edge. */
|
|
7
|
+
const arrowInsetClasses = {
|
|
8
|
+
xs: 'start-1 end-1',
|
|
9
|
+
sm: 'start-1.5 end-1.5',
|
|
10
|
+
md: 'start-2 end-2',
|
|
11
|
+
lg: 'start-3 end-3',
|
|
12
|
+
xl: 'start-4 end-4'
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* The dot ladder.
|
|
16
|
+
*
|
|
17
|
+
* A current dot is a short bar rather than a bigger circle: it grows along the
|
|
18
|
+
* row it is in, so the row's height never changes and the dots either side of
|
|
19
|
+
* it do not move. Width and colour are the only two things that travel, which
|
|
20
|
+
* is what keeps this inside the house rule against scaling anything.
|
|
21
|
+
*/
|
|
22
|
+
const dotClasses = {
|
|
23
|
+
xs: { rest: 'h-1 w-1', current: 'h-1 w-3', gap: 'gap-1' },
|
|
24
|
+
sm: { rest: 'h-1 w-1', current: 'h-1 w-3.5', gap: 'gap-1' },
|
|
25
|
+
md: { rest: 'h-1.5 w-1.5', current: 'h-1.5 w-4', gap: 'gap-1.5' },
|
|
26
|
+
lg: { rest: 'h-1.5 w-1.5', current: 'h-1.5 w-5', gap: 'gap-2' },
|
|
27
|
+
xl: { rest: 'h-2 w-2', current: 'h-2 w-6', gap: 'gap-2' }
|
|
28
|
+
};
|
|
29
|
+
/** How long a smooth scroll of our own is given to arrive. */
|
|
30
|
+
const SETTLE_MS = 700;
|
|
31
|
+
/**
|
|
32
|
+
* A strip of slides, one of which is in view.
|
|
33
|
+
*
|
|
34
|
+
* The mechanism is a scroll container with CSS scroll snapping, and everything
|
|
35
|
+
* good about this component follows from that one choice. Swiping on a phone
|
|
36
|
+
* and two-finger dragging on a trackpad both work because they are the
|
|
37
|
+
* browser's own scrolling and not a gesture handler pretending to be it. The
|
|
38
|
+
* strip runs the other way under RTL without being told, because scrolling is
|
|
39
|
+
* directional and `translate` is not. And nothing is transformed — the house
|
|
40
|
+
* rule against moving a surface holds here for free, where a translated track
|
|
41
|
+
* would have had to argue for an exception.
|
|
42
|
+
*
|
|
43
|
+
* The motion is `scroll-behavior: smooth`, which means a reader who has asked
|
|
44
|
+
* for reduced motion gets an instant cut from the same code path rather than
|
|
45
|
+
* from a second one written to remember them.
|
|
46
|
+
*
|
|
47
|
+
* Slides are not a sub-component. Every top-level child is wrapped in its own
|
|
48
|
+
* slide, so `<PlCarousel><img /><img /></PlCarousel>` is the whole API — and the
|
|
49
|
+
* wrapper is what carries the snap point, the width and the
|
|
50
|
+
* `role="group"` / `aria-roledescription="slide"` pair a screen reader needs,
|
|
51
|
+
* none of which a caller should have to remember to put on a photograph.
|
|
52
|
+
*/
|
|
53
|
+
export const PlCarousel = /* @__PURE__ */ React.forwardRef(function PlCarousel({ variant = 'glass', size = 'md', color = 'primary', density = 'default', elevation = 0, value, defaultValue = 0, onValueChange, loop = true, autoPlay = false, interval = 5000, arrows = true, indicators = true, label = 'Carousel', previousLabel = 'Previous slide', nextLabel = 'Next slide', slideLabel, className, style, children, ...props }, ref) {
|
|
54
|
+
const nameSlide = slideLabel ?? ((index, total) => `Slide ${index} of ${total}`);
|
|
55
|
+
// `toArray` is what drops the `null`s and `false`s a conditional slide
|
|
56
|
+
// leaves behind, and what gives every remaining child a stable key.
|
|
57
|
+
const slides = React.Children.toArray(children);
|
|
58
|
+
const count = slides.length;
|
|
59
|
+
const [uncontrolled, setUncontrolled] = React.useState(defaultValue);
|
|
60
|
+
const index = Math.min(Math.max(value ?? uncontrolled, 0), Math.max(count - 1, 0));
|
|
61
|
+
const trackRef = React.useRef(null);
|
|
62
|
+
const slideRefs = React.useRef([]);
|
|
63
|
+
// Set while the index is catching up with a scroll the reader performed. The
|
|
64
|
+
// effect below skips those, or every drag would be answered by a scroll back
|
|
65
|
+
// to where the browser had already put us.
|
|
66
|
+
const fromScroll = React.useRef(false);
|
|
67
|
+
const mounted = React.useRef(false);
|
|
68
|
+
// Raised while a smooth scroll of our own is still travelling. Without it
|
|
69
|
+
// the scroll events thrown on the way from slide 0 to slide 2 would each be
|
|
70
|
+
// read as the reader landing on slide 1.
|
|
71
|
+
const settling = React.useRef(false);
|
|
72
|
+
const [paused, setPaused] = React.useState(false);
|
|
73
|
+
const go = React.useCallback((next, viaScroll = false) => {
|
|
74
|
+
if (count === 0) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
const wrapped = loop
|
|
78
|
+
? ((next % count) + count) % count
|
|
79
|
+
: Math.min(Math.max(next, 0), count - 1);
|
|
80
|
+
fromScroll.current = viaScroll;
|
|
81
|
+
if (value === undefined) {
|
|
82
|
+
setUncontrolled(wrapped);
|
|
83
|
+
}
|
|
84
|
+
if (wrapped !== index) {
|
|
85
|
+
onValueChange?.(wrapped);
|
|
86
|
+
}
|
|
87
|
+
}, [count, loop, value, index, onValueChange]);
|
|
88
|
+
React.useEffect(() => {
|
|
89
|
+
if (fromScroll.current) {
|
|
90
|
+
fromScroll.current = false;
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
// The first pass would otherwise scroll the page down to a carousel
|
|
94
|
+
// nobody has looked at yet, just to put slide 0 where the browser already
|
|
95
|
+
// had it.
|
|
96
|
+
if (!mounted.current) {
|
|
97
|
+
mounted.current = true;
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
slideRefs.current[index]?.scrollIntoView({ block: 'nearest', inline: 'start' });
|
|
101
|
+
settling.current = true;
|
|
102
|
+
const timer = window.setTimeout(() => {
|
|
103
|
+
settling.current = false;
|
|
104
|
+
}, SETTLE_MS);
|
|
105
|
+
return () => window.clearTimeout(timer);
|
|
106
|
+
}, [index]);
|
|
107
|
+
/**
|
|
108
|
+
* Where the strip has settled, read off the scroll offset rather than
|
|
109
|
+
* measured per slide: every slide is exactly the width of the frame, so the
|
|
110
|
+
* offset divided by that width *is* the index. `Math.abs` is what makes it
|
|
111
|
+
* hold under RTL, where a scroll position counts backwards from zero.
|
|
112
|
+
*/
|
|
113
|
+
const handleScroll = () => {
|
|
114
|
+
const track = trackRef.current;
|
|
115
|
+
// `settling` is tested before anything is measured, and that order is the
|
|
116
|
+
// point: a smooth scroll of our own throws events for most of a second,
|
|
117
|
+
// and those are exactly the ones with nothing to answer. Reading
|
|
118
|
+
// `clientWidth` first would force a layout on every one of them.
|
|
119
|
+
if (settling.current || !track || track.clientWidth === 0) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const nearest = Math.round(Math.abs(track.scrollLeft) / track.clientWidth);
|
|
123
|
+
if (nearest !== index && nearest >= 0 && nearest < count) {
|
|
124
|
+
go(nearest, true);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
React.useEffect(() => {
|
|
128
|
+
if (!autoPlay || paused || count < 2) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
// A reader who has asked for less motion has asked for this in particular.
|
|
132
|
+
if (window.matchMedia?.('(prefers-reduced-motion: reduce)').matches) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
const timer = window.setInterval(() => {
|
|
136
|
+
if (document.hidden) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
go(index + 1);
|
|
140
|
+
}, interval);
|
|
141
|
+
return () => window.clearInterval(timer);
|
|
142
|
+
}, [autoPlay, paused, count, interval, index, go]);
|
|
143
|
+
const atStart = index <= 0;
|
|
144
|
+
const atEnd = index >= count - 1;
|
|
145
|
+
return (_jsxs("div", { ref: ref, role: "region", "aria-roledescription": "carousel", "aria-label": label, className: cx('flex flex-col', className), style: { ...surfaceSlots(color, elevation), ...style },
|
|
146
|
+
// Hover and focus both stop the timer. The second one is the important
|
|
147
|
+
// one: a keyboard reader who has tabbed into a slide is reading it.
|
|
148
|
+
onPointerEnter: () => setPaused(true), onPointerLeave: () => setPaused(false), onFocus: () => setPaused(true), onBlur: () => setPaused(false), ...props, children: [_jsxs("div", { className: cx('relative min-w-0 overflow-hidden', radiusClasses[size], sheetRestClasses[variant], transitionClasses), children: [_jsx("div", { ref: trackRef,
|
|
149
|
+
// Focusable, so the strip can be scrolled with the arrow keys by
|
|
150
|
+
// whoever is not using a pointer. That is the browser's own key
|
|
151
|
+
// handling on a scroll container, which means it is already right
|
|
152
|
+
// under RTL — a handler of ours mapping ArrowRight to "next" would
|
|
153
|
+
// not have been.
|
|
154
|
+
tabIndex: 0, role: "group", "aria-label": label, className: cx('flex min-w-0 snap-x snap-mandatory overflow-x-auto scroll-smooth', 'motion-reduce:scroll-auto',
|
|
155
|
+
// The strip is driven by buttons and by dragging; a scrollbar
|
|
156
|
+
// under it is a third control saying the same thing.
|
|
157
|
+
'[scrollbar-width:none] [&::-webkit-scrollbar]:hidden', 'focus-visible:[outline:2px_solid_var(--p-ring)] focus-visible:[outline-offset:-2px]'), onScroll: handleScroll, children: slides.map((slide, slideIndex) => (_jsx("div", { ref: (element) => {
|
|
158
|
+
slideRefs.current[slideIndex] = element;
|
|
159
|
+
}, role: "group", "aria-roledescription": "slide", "aria-label": nameSlide(slideIndex + 1, count),
|
|
160
|
+
// Deliberately *not* `aria-hidden` when off-screen. A slide can
|
|
161
|
+
// hold a link or a button, and an `aria-hidden` subtree that is
|
|
162
|
+
// still in the tab order is the exact shape of the bug where a
|
|
163
|
+
// keyboard reader lands somewhere their screen reader refuses
|
|
164
|
+
// to describe. The strip is scrollable, so everything in it is
|
|
165
|
+
// genuinely reachable — hiding it would be a lie.
|
|
166
|
+
className: "w-full shrink-0 grow-0 basis-full snap-start", children: slide }, slideIndex))) }), arrows && count > 1 ? (_jsxs("div", { className: cx('pointer-events-none absolute inset-y-0 flex items-center', arrowInsetClasses[size]), children: [_jsx(PlIconButton, { variant: "glass", size: size, color: color, density: density, elevation: 1, label: previousLabel, disabled: !loop && atStart, className: "pointer-events-auto",
|
|
167
|
+
// Drawn pointing down and turned, which is the one allowance the
|
|
168
|
+
// no-transform rule makes — and turned the other way under RTL,
|
|
169
|
+
// where "previous" is on the other side of the frame.
|
|
170
|
+
icon: _jsx("span", { className: "flex rotate-90 items-center rtl:-rotate-90", children: _jsx(ChevronIcon, {}) }), onClick: () => go(index - 1) }), _jsx("span", { className: "flex-1" }), _jsx(PlIconButton, { variant: "glass", size: size, color: color, density: density, elevation: 1, label: nextLabel, disabled: !loop && atEnd, className: "pointer-events-auto", icon: _jsx("span", { className: "flex -rotate-90 items-center rtl:rotate-90", children: _jsx(ChevronIcon, {}) }), onClick: () => go(index + 1) })] })) : null] }), indicators && count > 1 ? (_jsx("div", { className: cx('flex shrink-0 items-center justify-center pt-2', dotClasses[size].gap), children: slides.map((_, dotIndex) => (_jsx("button", { type: "button", "aria-label": nameSlide(dotIndex + 1, count), "aria-current": dotIndex === index ? 'true' : undefined, className: cx('cursor-pointer rounded-full',
|
|
171
|
+
// Width and colour, never a transform: the current dot grows
|
|
172
|
+
// along the row instead of scaling, so nothing beside it
|
|
173
|
+
// moves.
|
|
174
|
+
'[transition-property:width,background-color]', '[transition-duration:var(--plass-duration)]', '[transition-timing-function:var(--plass-ease)]', 'focus-visible:[outline:2px_solid_var(--p-ring)] focus-visible:outline-offset-2', dotIndex === index
|
|
175
|
+
? `${dotClasses[size].current} bg-(--p-accent)`
|
|
176
|
+
: `${dotClasses[size].rest} bg-(--plass-border) hover:bg-(--p-accent)`), onClick: () => go(dotIndex) }, dotIndex))) })) : null, _jsx("span", { className: srOnlyClasses, "aria-live": autoPlay ? 'off' : 'polite', children: count > 0 ? nameSlide(index + 1, count) : '' })] }));
|
|
177
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PlCarousel } from './PlCarousel.js';
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PlassColor, PlassDensity, PlassElevation, PlassSize, PlassVariant } from '../../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Whose message this is.
|
|
5
|
+
*
|
|
6
|
+
* `start` and `end` rather than `them`/`me` or `left`/`right`: a thread runs the
|
|
7
|
+
* way the language does, and the same two words already mean this everywhere
|
|
8
|
+
* else in the library. `start` is the default because a message from someone
|
|
9
|
+
* else is the one you have no other way of knowing about.
|
|
10
|
+
*/
|
|
11
|
+
export type PlChatBubbleSide = 'start' | 'end';
|
|
12
|
+
/**
|
|
13
|
+
* How far a message has got.
|
|
14
|
+
*
|
|
15
|
+
* The four steps are a ladder and the fifth is not on it: `failed` is the
|
|
16
|
+
* message that did not go, which is why it is the only one drawn in another
|
|
17
|
+
* colour family.
|
|
18
|
+
*/
|
|
19
|
+
export type PlChatBubbleStatus = 'sending' | 'sent' | 'delivered' | 'read' | 'failed';
|
|
20
|
+
/** What a link inside a message unfurls to. */
|
|
21
|
+
export interface PlChatBubbleLinkPreview {
|
|
22
|
+
/** Where the card goes. */
|
|
23
|
+
url: string;
|
|
24
|
+
/** The page's title. */
|
|
25
|
+
title?: React.ReactNode;
|
|
26
|
+
/** Its summary, clamped to two lines. */
|
|
27
|
+
description?: React.ReactNode;
|
|
28
|
+
/** The share image, drawn across the top of the card. */
|
|
29
|
+
image?: string;
|
|
30
|
+
/** Who published it — a domain, a site name. */
|
|
31
|
+
site?: React.ReactNode;
|
|
32
|
+
/**
|
|
33
|
+
* Opens the card in a new tab.
|
|
34
|
+
* @default false
|
|
35
|
+
*/
|
|
36
|
+
newTab?: boolean;
|
|
37
|
+
}
|
|
38
|
+
export interface PlChatBubbleProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'title'> {
|
|
39
|
+
/**
|
|
40
|
+
* Whose message this is.
|
|
41
|
+
* @default 'start'
|
|
42
|
+
*/
|
|
43
|
+
side?: PlChatBubbleSide;
|
|
44
|
+
/** Who sent it, above the bubble. */
|
|
45
|
+
name?: React.ReactNode;
|
|
46
|
+
/** When it was sent, beside the name. */
|
|
47
|
+
time?: React.ReactNode;
|
|
48
|
+
/**
|
|
49
|
+
* The sender's picture — a `PlAvatar`, at the size the thread uses. Left out,
|
|
50
|
+
* the bubble takes the whole row.
|
|
51
|
+
*/
|
|
52
|
+
avatar?: React.ReactNode;
|
|
53
|
+
/**
|
|
54
|
+
* How far the message has got, drawn as a mark under the bubble. Left out,
|
|
55
|
+
* nothing is drawn — a received message has no delivery state worth showing.
|
|
56
|
+
*/
|
|
57
|
+
status?: PlChatBubbleStatus;
|
|
58
|
+
/**
|
|
59
|
+
* What the mark is read out as. Never drawn. Defaults to the English word for
|
|
60
|
+
* whichever `status` is set.
|
|
61
|
+
*/
|
|
62
|
+
statusLabel?: string;
|
|
63
|
+
/**
|
|
64
|
+
* Draws the three dots instead of the message. What `children` holds is left
|
|
65
|
+
* alone, so the same bubble can go back to it when the message arrives.
|
|
66
|
+
* @default false
|
|
67
|
+
*/
|
|
68
|
+
typing?: boolean;
|
|
69
|
+
/**
|
|
70
|
+
* What the dots are read out as. Never drawn.
|
|
71
|
+
* @default 'Typing…'
|
|
72
|
+
*/
|
|
73
|
+
typingLabel?: string;
|
|
74
|
+
/**
|
|
75
|
+
* A picture, a video, a map — drawn edge to edge above the text, so the
|
|
76
|
+
* bubble's corners crop it.
|
|
77
|
+
*/
|
|
78
|
+
media?: React.ReactNode;
|
|
79
|
+
/** A link in the message, unfurled into a card under the text. */
|
|
80
|
+
preview?: PlChatBubbleLinkPreview;
|
|
81
|
+
/**
|
|
82
|
+
* The message's own actions — a menu trigger, most of the time. Sits beside
|
|
83
|
+
* the bubble and stays out of the way until the row is hovered or something in
|
|
84
|
+
* it takes focus.
|
|
85
|
+
*/
|
|
86
|
+
actions?: React.ReactNode;
|
|
87
|
+
/**
|
|
88
|
+
* What the bubble's surface is made of. `solid` is the usual way to tell your
|
|
89
|
+
* own messages from everyone else's; `side` deliberately does not decide this,
|
|
90
|
+
* because which end is filled is a decision about the product, not about the
|
|
91
|
+
* component.
|
|
92
|
+
* @default 'glass'
|
|
93
|
+
*/
|
|
94
|
+
variant?: PlassVariant;
|
|
95
|
+
/** @default 'md' */
|
|
96
|
+
size?: PlassSize;
|
|
97
|
+
/** @default 'primary' */
|
|
98
|
+
color?: PlassColor;
|
|
99
|
+
/**
|
|
100
|
+
* Padding inside the bubble, and nothing else.
|
|
101
|
+
* @default 'default'
|
|
102
|
+
*/
|
|
103
|
+
density?: PlassDensity;
|
|
104
|
+
/**
|
|
105
|
+
* Drop shadow depth. `0` is the default — a message lies in the thread rather
|
|
106
|
+
* than floating over it.
|
|
107
|
+
* @default 0
|
|
108
|
+
*/
|
|
109
|
+
elevation?: PlassElevation;
|
|
110
|
+
/** The message. */
|
|
111
|
+
children?: React.ReactNode;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* One message in a conversation.
|
|
115
|
+
*
|
|
116
|
+
* Everything around the bubble is optional and nothing about it is fixed by
|
|
117
|
+
* `side`: the avatar, the sender's name, the time, the delivery mark, the media
|
|
118
|
+
* above the text and the link card below it are each drawn only when they are
|
|
119
|
+
* given something. What `side` decides is which way the row runs and which
|
|
120
|
+
* corner of the sheet is cut short.
|
|
121
|
+
*
|
|
122
|
+
* `variant` is what tells your own messages from everyone else's, and it is
|
|
123
|
+
* deliberately not tied to `side` — filling the right-hand column is a
|
|
124
|
+
* convention, not a law, and a thread that fills neither is a perfectly good
|
|
125
|
+
* thread.
|
|
126
|
+
*/
|
|
127
|
+
export declare const PlChatBubble: React.ForwardRefExoticComponent<PlChatBubbleProps & React.RefAttributes<HTMLDivElement>>;
|