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 * as React from 'react';
|
|
2
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
3
|
+
import type { PlassSize } from '../../types.js';
|
|
4
|
+
/**
|
|
5
|
+
* How the media inside is fitted to the box, spelled the way CSS spells it.
|
|
6
|
+
*
|
|
7
|
+
* These are `object-fit`'s own values rather than a nicer set of words, for the
|
|
8
|
+
* reason the library keeps `aspect-ratio`'s own syntax below: inventing
|
|
9
|
+
* `fill-the-box` would only make a reader look up which CSS it maps to.
|
|
10
|
+
*/
|
|
11
|
+
export type PlAspectFit = 'cover' | 'contain' | 'fill' | 'none';
|
|
12
|
+
export interface PlAspectRatioProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
13
|
+
/**
|
|
14
|
+
* The proportion the box holds, written the way CSS writes it — a number
|
|
15
|
+
* (`1.5`) or a ratio (`'16 / 9'`). Both reach `aspect-ratio` untouched.
|
|
16
|
+
* @default 1
|
|
17
|
+
*/
|
|
18
|
+
ratio?: number | string;
|
|
19
|
+
/**
|
|
20
|
+
* How a single piece of media inside is fitted. Applies to an `img`, a
|
|
21
|
+
* `video`, a `canvas`, an `svg` or an `iframe` that is a direct child; those
|
|
22
|
+
* are stretched to the full box and then fitted. Anything else is laid out
|
|
23
|
+
* normally and this prop does not reach it.
|
|
24
|
+
* @default 'cover'
|
|
25
|
+
*/
|
|
26
|
+
fit?: PlAspectFit;
|
|
27
|
+
/**
|
|
28
|
+
* Rounds the corners to the `size` step of the house radius ladder.
|
|
29
|
+
*
|
|
30
|
+
* Off by default. A layout component draws nothing, and a photograph with its
|
|
31
|
+
* corners cut is a decision about the photograph — but it is such a common one
|
|
32
|
+
* that making the caller reach for a `className` would be perverse.
|
|
33
|
+
* @default false
|
|
34
|
+
*/
|
|
35
|
+
rounded?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Which step of the radius ladder `rounded` uses.
|
|
38
|
+
*
|
|
39
|
+
* `size` here is the size of the *sheet* — there is no height and no type
|
|
40
|
+
* scale on a box whose whole job is a proportion.
|
|
41
|
+
* @default 'md'
|
|
42
|
+
*/
|
|
43
|
+
size?: PlassSize;
|
|
44
|
+
/**
|
|
45
|
+
* Renders something other than a `<div>`: `render={<figure />}`,
|
|
46
|
+
* `render={<a href="…" />}`. Base UI's own escape hatch.
|
|
47
|
+
*/
|
|
48
|
+
render?: useRender.RenderProp;
|
|
49
|
+
children?: React.ReactNode;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* A box that keeps a proportion whatever width it is given.
|
|
53
|
+
*
|
|
54
|
+
* It draws nothing — no sheet, no hairline, no shadow — which is what puts it
|
|
55
|
+
* in `layout` beside `PlContainer` and `PlGrid` rather than in `surfaces`. What
|
|
56
|
+
* it does is reserve the space: a card whose image arrives late does not reflow
|
|
57
|
+
* the page around it, and a row of thumbnails is a row of one shape.
|
|
58
|
+
*
|
|
59
|
+
* The proportion is CSS's own `aspect-ratio`, so a caller who already knows
|
|
60
|
+
* `16 / 9` has nothing to translate. `fit` is the one convenience on top: the
|
|
61
|
+
* media inside is stretched to the box and then fitted, which is the pair of
|
|
62
|
+
* declarations every use of this component would otherwise start with.
|
|
63
|
+
*/
|
|
64
|
+
export declare const PlAspectRatio: React.ForwardRefExoticComponent<PlAspectRatioProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
3
|
+
import { cx, radiusClasses } from '../../internal/styles.js';
|
|
4
|
+
/**
|
|
5
|
+
* The media a `fit` reaches, stretched to the box first.
|
|
6
|
+
*
|
|
7
|
+
* Written out one selector at a time rather than as a comma list, because
|
|
8
|
+
* Tailwind only ever sees class names that appear literally in the source and a
|
|
9
|
+
* grouped arbitrary variant is one string it has to parse rather than match.
|
|
10
|
+
*
|
|
11
|
+
* `iframe` takes the sizing and not the fit: an embed lays its own content out
|
|
12
|
+
* and `object-fit` has nothing to act on.
|
|
13
|
+
*/
|
|
14
|
+
const stretchClasses = /* @__PURE__ */ [
|
|
15
|
+
'[&>img]:size-full',
|
|
16
|
+
'[&>video]:size-full',
|
|
17
|
+
'[&>canvas]:size-full',
|
|
18
|
+
'[&>svg]:size-full',
|
|
19
|
+
'[&>iframe]:size-full',
|
|
20
|
+
'[&>picture]:size-full',
|
|
21
|
+
'[&>picture>img]:size-full'
|
|
22
|
+
].join(' ');
|
|
23
|
+
const fitClasses = {
|
|
24
|
+
cover: '[&>img]:object-cover [&>video]:object-cover [&>picture>img]:object-cover',
|
|
25
|
+
contain: '[&>img]:object-contain [&>video]:object-contain [&>picture>img]:object-contain',
|
|
26
|
+
fill: '[&>img]:object-fill [&>video]:object-fill [&>picture>img]:object-fill',
|
|
27
|
+
none: '[&>img]:object-none [&>video]:object-none [&>picture>img]:object-none'
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* A box that keeps a proportion whatever width it is given.
|
|
31
|
+
*
|
|
32
|
+
* It draws nothing — no sheet, no hairline, no shadow — which is what puts it
|
|
33
|
+
* in `layout` beside `PlContainer` and `PlGrid` rather than in `surfaces`. What
|
|
34
|
+
* it does is reserve the space: a card whose image arrives late does not reflow
|
|
35
|
+
* the page around it, and a row of thumbnails is a row of one shape.
|
|
36
|
+
*
|
|
37
|
+
* The proportion is CSS's own `aspect-ratio`, so a caller who already knows
|
|
38
|
+
* `16 / 9` has nothing to translate. `fit` is the one convenience on top: the
|
|
39
|
+
* media inside is stretched to the box and then fitted, which is the pair of
|
|
40
|
+
* declarations every use of this component would otherwise start with.
|
|
41
|
+
*/
|
|
42
|
+
export const PlAspectRatio = /* @__PURE__ */ React.forwardRef(function PlAspectRatio({ ratio = 1, fit = 'cover', rounded = false, size = 'md', render, className, style, children, ...props }, ref) {
|
|
43
|
+
const classNames = cx(
|
|
44
|
+
// `overflow-hidden` is not decoration: without it a `cover` image spills
|
|
45
|
+
// out of the proportion it was just given, and the box would only be
|
|
46
|
+
// reserving space rather than holding anything to it.
|
|
47
|
+
'relative block w-full overflow-hidden', stretchClasses, fitClasses[fit], rounded ? radiusClasses[size] : '', className);
|
|
48
|
+
return useRender({
|
|
49
|
+
render,
|
|
50
|
+
ref,
|
|
51
|
+
props: {
|
|
52
|
+
className: classNames,
|
|
53
|
+
style: { aspectRatio: ratio, ...style },
|
|
54
|
+
children,
|
|
55
|
+
...props
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PlAspectRatio } from './PlAspectRatio.js';
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PlassColor, PlassElevation, PlassSize, PlassVariant } from '../../types.js';
|
|
3
|
+
/** What Base UI reports about the picture as it loads. */
|
|
4
|
+
export type PlAvatarLoadingStatus = 'idle' | 'loading' | 'loaded' | 'error';
|
|
5
|
+
/**
|
|
6
|
+
* The crop, not the material.
|
|
7
|
+
*
|
|
8
|
+
* `circle` is the default. A round crop is what a portrait has been for as long
|
|
9
|
+
* as there have been portraits, and an avatar is not a surface — it is a picture
|
|
10
|
+
* laid on one, so it does not owe the radius ladder anything.
|
|
11
|
+
*
|
|
12
|
+
* `square` takes the library's own fillet instead, which is what a logo or a
|
|
13
|
+
* repository icon wants: those are drawn to the edges of a rectangle and a round
|
|
14
|
+
* crop eats them.
|
|
15
|
+
*/
|
|
16
|
+
export type PlAvatarShape = 'circle' | 'square';
|
|
17
|
+
export interface PlAvatarProps extends Omit<React.ComponentPropsWithoutRef<'span'>, 'color'> {
|
|
18
|
+
/**
|
|
19
|
+
* The picture. Until it loads — and forever, if it fails — the fallback is
|
|
20
|
+
* what is drawn, so an avatar is never an empty box.
|
|
21
|
+
*/
|
|
22
|
+
src?: string;
|
|
23
|
+
/** Candidate images at other resolutions, as on any `<img>`. */
|
|
24
|
+
srcSet?: string;
|
|
25
|
+
/**
|
|
26
|
+
* What the picture says, for a reader who cannot see it. Defaults to `name`,
|
|
27
|
+
* and to nothing at all when there is no name — an avatar next to the person's
|
|
28
|
+
* own name in a row is decoration, and reading it out says the name twice.
|
|
29
|
+
*/
|
|
30
|
+
alt?: string;
|
|
31
|
+
/**
|
|
32
|
+
* Who or what this is. One prop doing three jobs: it names the picture, the
|
|
33
|
+
* initials are derived from it, and it is the sentence a screen reader hears
|
|
34
|
+
* instead of those initials.
|
|
35
|
+
*
|
|
36
|
+
* The initials are the first character of the first word plus the first
|
|
37
|
+
* character of the last — "Jane Doe" is `JD`, "홍길동" is `홍`. That rule is
|
|
38
|
+
* wrong for some names, which is what `initials` is for.
|
|
39
|
+
*/
|
|
40
|
+
name?: string;
|
|
41
|
+
/** The initials, written out, for when the rule derived the wrong ones. */
|
|
42
|
+
initials?: string;
|
|
43
|
+
/**
|
|
44
|
+
* The crop.
|
|
45
|
+
* @default 'circle'
|
|
46
|
+
*/
|
|
47
|
+
shape?: PlAvatarShape;
|
|
48
|
+
/**
|
|
49
|
+
* What the sheet behind the fallback is made of. Invisible once a picture has
|
|
50
|
+
* loaded, apart from the edge it keeps.
|
|
51
|
+
*
|
|
52
|
+
* `ghost` is the default: a directory is a page of avatars, and a page of
|
|
53
|
+
* saturated circles is a page nobody can read a name off.
|
|
54
|
+
* @default 'ghost'
|
|
55
|
+
*/
|
|
56
|
+
variant?: PlassVariant;
|
|
57
|
+
/**
|
|
58
|
+
* The box the picture is drawn in — the control heights, so an avatar and the
|
|
59
|
+
* button beside it in a toolbar are the same height.
|
|
60
|
+
* @default 'md'
|
|
61
|
+
*/
|
|
62
|
+
size?: PlassSize;
|
|
63
|
+
/** @default 'primary' */
|
|
64
|
+
color?: PlassColor;
|
|
65
|
+
/**
|
|
66
|
+
* Drop shadow depth. `0` is the default: an avatar is a picture set into the
|
|
67
|
+
* page rather than a key resting on it.
|
|
68
|
+
* @default 0
|
|
69
|
+
*/
|
|
70
|
+
elevation?: PlassElevation;
|
|
71
|
+
/**
|
|
72
|
+
* How long to wait before drawing the fallback, in milliseconds. Set it to
|
|
73
|
+
* roughly the time a cached image takes and the initials stop flashing up in
|
|
74
|
+
* front of a picture that was about to arrive anyway.
|
|
75
|
+
*/
|
|
76
|
+
delay?: number;
|
|
77
|
+
/** Anything else the `<img>` needs — `loading`, `crossOrigin`, `referrerPolicy`. */
|
|
78
|
+
imageProps?: Omit<React.ComponentPropsWithoutRef<'img'>, 'src' | 'srcSet' | 'alt'>;
|
|
79
|
+
/** Called as the picture moves between `idle`, `loading`, `loaded` and `error`. */
|
|
80
|
+
onLoadingStatusChange?: (status: PlAvatarLoadingStatus) => void;
|
|
81
|
+
/**
|
|
82
|
+
* The fallback, drawn instead of the initials. An icon, a logo, a single
|
|
83
|
+
* emoji — whatever stands in for this particular thing when there is no
|
|
84
|
+
* picture of it.
|
|
85
|
+
*/
|
|
86
|
+
children?: React.ReactNode;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* A picture of a person or a thing, at a known size, that is never an empty box.
|
|
90
|
+
*
|
|
91
|
+
* Three things can be drawn in it and exactly one of them is at a time: the
|
|
92
|
+
* picture, if `src` is given and it loads; otherwise whatever stands in for it —
|
|
93
|
+
* `children`, or `initials`, or the initials derived from `name`; and failing
|
|
94
|
+
* all of those, a silhouette. Which one is showing is Base UI's `Avatar` to
|
|
95
|
+
* decide, because "has the image loaded" is a question with four answers and a
|
|
96
|
+
* race in the middle of it.
|
|
97
|
+
*
|
|
98
|
+
* It carries no status dot of its own. An avatar with a green mark on it is a
|
|
99
|
+
* `PlBadge` with an avatar in it, and inventing a second spelling for that would
|
|
100
|
+
* give the library two of them.
|
|
101
|
+
*/
|
|
102
|
+
export declare const PlAvatar: React.ForwardRefExoticComponent<PlAvatarProps & React.RefAttributes<HTMLSpanElement>>;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Avatar as BaseUIAvatar } from '@base-ui/react/avatar';
|
|
4
|
+
import { controlHeightClasses, controlSlots, controlSquareClasses, glassClasses, hasContent, radiusClasses, srOnlyClasses, transitionClasses } from '../../internal/styles.js';
|
|
5
|
+
/**
|
|
6
|
+
* The initials, sized off the box rather than off the row.
|
|
7
|
+
*
|
|
8
|
+
* Its own ladder and not `controlTextClasses`, because a control's label is
|
|
9
|
+
* measured against the words next to it and this one is measured against the
|
|
10
|
+
* circle around it: roughly 40% of the diameter at every step, which is where
|
|
11
|
+
* two characters fill the width without touching the edge.
|
|
12
|
+
*/
|
|
13
|
+
const initialsTextClasses = {
|
|
14
|
+
xs: 'text-[0.5625rem]',
|
|
15
|
+
sm: 'text-[0.6875rem]',
|
|
16
|
+
md: 'text-[0.8125rem]',
|
|
17
|
+
lg: 'text-[1rem]',
|
|
18
|
+
xl: 'text-[1.1875rem]'
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* The three materials, said the way a *control* says them: an avatar **is** the
|
|
22
|
+
* thing being coloured — a portrait of one particular person — so its sheet
|
|
23
|
+
* takes the tint, exactly as a `PlAlert`'s does and unlike a `PlCard`'s.
|
|
24
|
+
*
|
|
25
|
+
* `solid` carries no gloss line, for the reason a filled `PlButton` carries
|
|
26
|
+
* none: the gradient is the form.
|
|
27
|
+
*/
|
|
28
|
+
const variantClasses = {
|
|
29
|
+
solid: /* @__PURE__ */ [
|
|
30
|
+
'text-(--p-on-solid) [background-image:var(--p-fill)]',
|
|
31
|
+
'[box-shadow:var(--p-elev),var(--p-lift)]'
|
|
32
|
+
].join(' '),
|
|
33
|
+
glass: /* @__PURE__ */ [
|
|
34
|
+
glassClasses,
|
|
35
|
+
'border text-(--p-accent) bg-(--plass-glass)',
|
|
36
|
+
'[border-color:var(--plass-border)]',
|
|
37
|
+
'[box-shadow:var(--p-elev),var(--plass-gloss-glass)]'
|
|
38
|
+
].join(' '),
|
|
39
|
+
ghost: 'text-(--p-accent) bg-(--p-soft-press) [box-shadow:var(--p-elev)]'
|
|
40
|
+
};
|
|
41
|
+
const baseClasses = /* @__PURE__ */ [
|
|
42
|
+
'relative inline-flex shrink-0 select-none items-center justify-center overflow-hidden',
|
|
43
|
+
'align-middle leading-none font-semibold tracking-wide whitespace-nowrap',
|
|
44
|
+
// A glyph handed to `children` is drawn against the circle, not against a
|
|
45
|
+
// word, so it is sized off the box like the initials are rather than off the
|
|
46
|
+
// `1.2em` an icon riding on a label takes.
|
|
47
|
+
'[&_svg]:pointer-events-none [&_svg]:size-[55%]',
|
|
48
|
+
transitionClasses
|
|
49
|
+
].join(' ');
|
|
50
|
+
/**
|
|
51
|
+
* The default fallback: a shoulders-and-head silhouette, drawn here rather than
|
|
52
|
+
* in `internal/icons` because this is the only component that needs it.
|
|
53
|
+
*
|
|
54
|
+
* It exists so that `<PlAvatar />` with nothing at all is still an avatar. A box
|
|
55
|
+
* with no picture, no name and no glyph in it is indistinguishable from a
|
|
56
|
+
* component that failed to render.
|
|
57
|
+
*/
|
|
58
|
+
function PersonIcon() {
|
|
59
|
+
return (_jsxs("svg", { viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: [_jsx("path", { d: "M12 12a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9Z" }), _jsx("path", { d: "M12 14.25c-4.28 0-7.75 2.42-7.75 5.4 0 .75.6 1.35 1.35 1.35h12.8c.75 0 1.35-.6 1.35-1.35 0-2.98-3.47-5.4-7.75-5.4Z" })] }));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The first character of the first word, plus the first of the last.
|
|
63
|
+
*
|
|
64
|
+
* `Array.from` rather than `[0]`, so a name that starts with an emoji or with
|
|
65
|
+
* any character outside the basic plane is not cut in half between its two code
|
|
66
|
+
* units. `normalize('NFC')` first, so a name whose accents arrived decomposed —
|
|
67
|
+
* which is what a macOS filename and a good many APIs hand you — yields `Ä`
|
|
68
|
+
* rather than a bare `A`.
|
|
69
|
+
*
|
|
70
|
+
* One word gives one character on purpose. Korean, Japanese and Chinese names
|
|
71
|
+
* are a single token, and two of their characters at 40px is a smudge where one
|
|
72
|
+
* is a name.
|
|
73
|
+
*/
|
|
74
|
+
function initialsOf(name) {
|
|
75
|
+
const words = name.normalize('NFC').trim().split(/\s+/).filter(Boolean);
|
|
76
|
+
if (words.length === 0) {
|
|
77
|
+
return '';
|
|
78
|
+
}
|
|
79
|
+
const first = Array.from(words[0])[0] ?? '';
|
|
80
|
+
const last = words.length > 1 ? (Array.from(words[words.length - 1])[0] ?? '') : '';
|
|
81
|
+
return (first + last).toLocaleUpperCase();
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* A picture of a person or a thing, at a known size, that is never an empty box.
|
|
85
|
+
*
|
|
86
|
+
* Three things can be drawn in it and exactly one of them is at a time: the
|
|
87
|
+
* picture, if `src` is given and it loads; otherwise whatever stands in for it —
|
|
88
|
+
* `children`, or `initials`, or the initials derived from `name`; and failing
|
|
89
|
+
* all of those, a silhouette. Which one is showing is Base UI's `Avatar` to
|
|
90
|
+
* decide, because "has the image loaded" is a question with four answers and a
|
|
91
|
+
* race in the middle of it.
|
|
92
|
+
*
|
|
93
|
+
* It carries no status dot of its own. An avatar with a green mark on it is a
|
|
94
|
+
* `PlBadge` with an avatar in it, and inventing a second spelling for that would
|
|
95
|
+
* give the library two of them.
|
|
96
|
+
*/
|
|
97
|
+
export const PlAvatar = /* @__PURE__ */ React.forwardRef(function PlAvatar({ src, srcSet, alt, name, initials, shape = 'circle', variant = 'ghost', size = 'md', color = 'primary', elevation = 0, delay, imageProps, onLoadingStatusChange, className, style, children, ...props }, ref) {
|
|
98
|
+
const derived = name ? initialsOf(name) : '';
|
|
99
|
+
const label = alt ?? name;
|
|
100
|
+
// `children` beats the initials beats the silhouette. Only the last of the
|
|
101
|
+
// three has nothing to say, which is what decides whether the fallback needs
|
|
102
|
+
// the name spelled out beside it.
|
|
103
|
+
const stand = hasContent(children) ? children : (initials ?? derived) || _jsx(PersonIcon, {});
|
|
104
|
+
const speaks = hasContent(children) || Boolean(initials ?? derived);
|
|
105
|
+
const classNames = [
|
|
106
|
+
baseClasses,
|
|
107
|
+
controlHeightClasses[size],
|
|
108
|
+
controlSquareClasses[size],
|
|
109
|
+
initialsTextClasses[size],
|
|
110
|
+
shape === 'circle' ? 'rounded-full' : radiusClasses[size],
|
|
111
|
+
variantClasses[variant],
|
|
112
|
+
className ?? ''
|
|
113
|
+
]
|
|
114
|
+
.filter(Boolean)
|
|
115
|
+
.join(' ');
|
|
116
|
+
return (_jsxs(BaseUIAvatar.Root, { ref: ref, className: classNames, style: { ...controlSlots(color, elevation, variant), ...style }, ...props, children: [src ? (_jsx(BaseUIAvatar.Image, { src: src, srcSet: srcSet,
|
|
117
|
+
// Empty rather than absent: an avatar beside the person's own name is
|
|
118
|
+
// decoration, and `alt` left off is what makes a screen reader read
|
|
119
|
+
// the file name out instead.
|
|
120
|
+
alt: label ?? '', className: "size-full object-cover", onLoadingStatusChange: onLoadingStatusChange, ...imageProps })) : null, _jsxs(BaseUIAvatar.Fallback, { delay: src ? delay : undefined, className: "flex size-full items-center justify-center", children: [label && speaks ? _jsx("span", { className: srOnlyClasses, children: label }) : null, _jsx("span", { "aria-hidden": label && speaks ? true : undefined, className: "contents", children: stand })] })] }));
|
|
121
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PlAvatar } from './PlAvatar.js';
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PlassCorner, PlassElevation, PlassStyleProps } from '../../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* The shape of the thing underneath, which is what decides how far the marker
|
|
5
|
+
* tucks in.
|
|
6
|
+
*/
|
|
7
|
+
export type PlBadgeOverlap = 'square' | 'circle';
|
|
8
|
+
export interface PlBadgeProps extends PlassStyleProps, Omit<React.ComponentPropsWithoutRef<'span'>, 'color' | 'content'> {
|
|
9
|
+
/**
|
|
10
|
+
* What the badge says — usually a count, sometimes a word.
|
|
11
|
+
*
|
|
12
|
+
* Omit it and the badge draws a dot instead, which is the honest thing when
|
|
13
|
+
* there is something to report but nothing to count.
|
|
14
|
+
*/
|
|
15
|
+
content?: React.ReactNode;
|
|
16
|
+
/**
|
|
17
|
+
* Caps a numeric `content` and adds a `+`. Only applies when the content is
|
|
18
|
+
* actually a number: a badge cannot know how to truncate a word.
|
|
19
|
+
* @default 99
|
|
20
|
+
*/
|
|
21
|
+
max?: number;
|
|
22
|
+
/**
|
|
23
|
+
* Draws the marker as a dot even when there is content, keeping the content
|
|
24
|
+
* for screen readers only. For the corner that has to stay quiet.
|
|
25
|
+
* @default false
|
|
26
|
+
*/
|
|
27
|
+
dot?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Whether a `content` of `0` is shown. Off by default — zero unread messages
|
|
30
|
+
* is not news, and a badge that never goes away stops meaning anything.
|
|
31
|
+
* @default false
|
|
32
|
+
*/
|
|
33
|
+
showZero?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Hides the marker without unmounting the anchor. The badge keeps its place in
|
|
36
|
+
* the DOM, so showing it again does not relayout what it sits on.
|
|
37
|
+
* @default false
|
|
38
|
+
*/
|
|
39
|
+
invisible?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Which corner of the anchor it sits on.
|
|
42
|
+
* @default 'top-end'
|
|
43
|
+
*/
|
|
44
|
+
placement?: PlassCorner;
|
|
45
|
+
/**
|
|
46
|
+
* The shape of the thing underneath, which is what decides how far the marker
|
|
47
|
+
* tucks in: a circle's corner is further from its centre than a square's, so a
|
|
48
|
+
* badge that looks right on an avatar hangs off an icon button.
|
|
49
|
+
* @default 'square'
|
|
50
|
+
*/
|
|
51
|
+
overlap?: PlBadgeOverlap;
|
|
52
|
+
/**
|
|
53
|
+
* Drop shadow depth. `0` is the default — a marker lies on the thing it is
|
|
54
|
+
* marking rather than floating above it.
|
|
55
|
+
* @default 0
|
|
56
|
+
*/
|
|
57
|
+
elevation?: PlassElevation;
|
|
58
|
+
/**
|
|
59
|
+
* What a screen reader hears instead of the raw content. `content={3}` on a
|
|
60
|
+
* bell is "3" to a reader and means nothing; `label="3 unread notifications"`
|
|
61
|
+
* is the sentence.
|
|
62
|
+
*/
|
|
63
|
+
label?: string;
|
|
64
|
+
/**
|
|
65
|
+
* What the badge is pinned to. Without it the badge is a standalone marker
|
|
66
|
+
* that lays out inline, which is what a status pill in a table cell is.
|
|
67
|
+
*/
|
|
68
|
+
children?: React.ReactNode;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* A small mark in the corner of something else: unread mail on an inbox icon, a
|
|
72
|
+
* status dot on an avatar, a count on a tab.
|
|
73
|
+
*
|
|
74
|
+
* The shell is a `<span>` that wraps the anchor and does nothing but establish a
|
|
75
|
+
* positioning context — no width, no padding, `align-middle` — so a badged icon
|
|
76
|
+
* button still measures and lines up exactly like a bare one. With no children
|
|
77
|
+
* the marker lays out inline instead, which is what a standalone status pill is.
|
|
78
|
+
*
|
|
79
|
+
* There is no Base UI primitive under this, and there should not be: a badge has
|
|
80
|
+
* no interaction, no state and no keyboard contract. It is a mark. Wiring it to a
|
|
81
|
+
* widget primitive would hand every decorative dot a role it cannot honour.
|
|
82
|
+
*
|
|
83
|
+
* What it does owe a screen reader is a sentence rather than a number, which is
|
|
84
|
+
* what `label` is for — `content={3}` beside a bell reads out as "3".
|
|
85
|
+
*/
|
|
86
|
+
export declare const PlBadge: React.ForwardRefExoticComponent<PlBadgeProps & React.RefAttributes<HTMLSpanElement>>;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { controlSlots, glassClasses, hasContent, srOnlyClasses, transitionClasses } from '../../internal/styles.js';
|
|
4
|
+
/**
|
|
5
|
+
* A badge is smaller than anything else in the library, so it has a ladder of
|
|
6
|
+
* its own rather than a step off `controlHeightClasses`.
|
|
7
|
+
*
|
|
8
|
+
* A control's height is the number a *row* lines up on; a badge lines up on
|
|
9
|
+
* nothing — it hangs off the corner of something else. `md` is 18px, which is
|
|
10
|
+
* the smallest a two-digit number stays legible at.
|
|
11
|
+
*/
|
|
12
|
+
const badgeHeightClasses = {
|
|
13
|
+
xs: 'h-3.5 min-w-3.5',
|
|
14
|
+
sm: 'h-4 min-w-4',
|
|
15
|
+
md: 'h-4.5 min-w-4.5',
|
|
16
|
+
lg: 'h-5 min-w-5',
|
|
17
|
+
xl: 'h-6 min-w-6'
|
|
18
|
+
};
|
|
19
|
+
/** The dot: the same ladder with the digits taken out, so it goes square. */
|
|
20
|
+
const dotSizeClasses = {
|
|
21
|
+
xs: 'size-1.5',
|
|
22
|
+
sm: 'size-2',
|
|
23
|
+
md: 'size-2.5',
|
|
24
|
+
lg: 'size-2.5',
|
|
25
|
+
xl: 'size-3'
|
|
26
|
+
};
|
|
27
|
+
const badgeTextClasses = {
|
|
28
|
+
xs: 'text-[0.5625rem]',
|
|
29
|
+
sm: 'text-[0.625rem]',
|
|
30
|
+
md: 'text-[0.6875rem]',
|
|
31
|
+
lg: 'text-[0.75rem]',
|
|
32
|
+
xl: 'text-[0.8125rem]'
|
|
33
|
+
};
|
|
34
|
+
/** Horizontal breathing room around the digits. `density` is what halves it. */
|
|
35
|
+
const badgePaddingClasses = {
|
|
36
|
+
default: { xs: 'px-1', sm: 'px-1', md: 'px-1.5', lg: 'px-1.5', xl: 'px-2' },
|
|
37
|
+
compact: { xs: 'px-0.5', sm: 'px-0.5', md: 'px-1', lg: 'px-1', xl: 'px-1.5' }
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* A badge sits well below the radius ladder — at 18px tall, `--plass-radius-xs`
|
|
41
|
+
* (8px) is already most of the way to a pill, and a badge *is* the one thing in
|
|
42
|
+
* the library allowed to be one.
|
|
43
|
+
*
|
|
44
|
+
* That is not a hole in the design language, it is the exception the language
|
|
45
|
+
* names. A Plass corner is a moulded fillet on a *surface*, and a badge is not a
|
|
46
|
+
* surface: it is a mark laid on one — which is also why it is the only component
|
|
47
|
+
* that overlaps its neighbour.
|
|
48
|
+
*/
|
|
49
|
+
const badgeRadiusClasses = 'rounded-full';
|
|
50
|
+
/**
|
|
51
|
+
* How far the marker is pulled out of the corner, per size.
|
|
52
|
+
*
|
|
53
|
+
* A negative margin rather than the `translate(50%,-50%)` every other library
|
|
54
|
+
* reaches for, because the house rule against `transform` is absolute and worth
|
|
55
|
+
* more than the two lines it costs here. The offsets are half the marker's own
|
|
56
|
+
* height, so the vertical overhang is exactly half — and horizontally a wide
|
|
57
|
+
* `99+` tucks in a little further than half, which is what you want anyway.
|
|
58
|
+
*/
|
|
59
|
+
const cornerOffsets = {
|
|
60
|
+
xs: { badge: '-mt-1.5 -mb-1.5 -ms-1.5 -me-1.5', dot: '-mt-0.5 -mb-0.5 -ms-0.5 -me-0.5' },
|
|
61
|
+
sm: { badge: '-mt-2 -mb-2 -ms-2 -me-2', dot: '-mt-1 -mb-1 -ms-1 -me-1' },
|
|
62
|
+
md: { badge: '-mt-2 -mb-2 -ms-2 -me-2', dot: '-mt-1 -mb-1 -ms-1 -me-1' },
|
|
63
|
+
lg: { badge: '-mt-2.5 -mb-2.5 -ms-2.5 -me-2.5', dot: '-mt-1 -mb-1 -ms-1 -me-1' },
|
|
64
|
+
xl: { badge: '-mt-3 -mb-3 -ms-3 -me-3', dot: '-mt-1.5 -mb-1.5 -ms-1.5 -me-1.5' }
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Which two edges the marker is pinned to. Logical properties throughout, so the
|
|
68
|
+
* corner flips with the writing direction rather than staying stuck on the right.
|
|
69
|
+
*/
|
|
70
|
+
const placementClasses = {
|
|
71
|
+
'top-start': 'top-0 start-0',
|
|
72
|
+
'top-end': 'top-0 end-0',
|
|
73
|
+
'bottom-start': 'bottom-0 start-0',
|
|
74
|
+
'bottom-end': 'bottom-0 end-0'
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* The extra inset a round anchor needs. A circle's corner is `r·(1 − 1/√2)` —
|
|
78
|
+
* about 15% of its diameter — inside the bounding box the badge is positioned
|
|
79
|
+
* against, so without this the marker floats off an avatar with a gap under it.
|
|
80
|
+
*/
|
|
81
|
+
const circleInsetClasses = {
|
|
82
|
+
'top-start': 'mt-[7%] ms-[7%]',
|
|
83
|
+
'top-end': 'mt-[7%] me-[7%]',
|
|
84
|
+
'bottom-start': 'mb-[7%] ms-[7%]',
|
|
85
|
+
'bottom-end': 'mb-[7%] me-[7%]'
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* The three materials, said the way a *control* says them: the marker is the
|
|
89
|
+
* thing being coloured, so its sheet takes the tint.
|
|
90
|
+
*
|
|
91
|
+
* `solid` carries the gradient and the tinted lift and no gloss line, exactly as
|
|
92
|
+
* a filled `PlButton` does. `ghost` is the one to reach for on a busy surface —
|
|
93
|
+
* a soft tinted mark that reports without shouting.
|
|
94
|
+
*/
|
|
95
|
+
const variantClasses = {
|
|
96
|
+
solid: /* @__PURE__ */ [
|
|
97
|
+
'text-(--p-on-solid) [background-image:var(--p-fill)]',
|
|
98
|
+
'[box-shadow:var(--p-elev),var(--p-lift)]'
|
|
99
|
+
].join(' '),
|
|
100
|
+
glass: /* @__PURE__ */ [
|
|
101
|
+
glassClasses,
|
|
102
|
+
'border text-(--p-accent) bg-(--plass-glass)',
|
|
103
|
+
'[border-color:var(--plass-border)]',
|
|
104
|
+
'[box-shadow:var(--p-elev),var(--plass-gloss-glass)]'
|
|
105
|
+
].join(' '),
|
|
106
|
+
ghost: 'text-(--p-accent) bg-(--p-soft-press)'
|
|
107
|
+
};
|
|
108
|
+
/** `99+`, but only for a value a `+` means anything on. */
|
|
109
|
+
function capContent(content, max) {
|
|
110
|
+
return typeof content === 'number' && content > max ? `${max}+` : content;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* A small mark in the corner of something else: unread mail on an inbox icon, a
|
|
114
|
+
* status dot on an avatar, a count on a tab.
|
|
115
|
+
*
|
|
116
|
+
* The shell is a `<span>` that wraps the anchor and does nothing but establish a
|
|
117
|
+
* positioning context — no width, no padding, `align-middle` — so a badged icon
|
|
118
|
+
* button still measures and lines up exactly like a bare one. With no children
|
|
119
|
+
* the marker lays out inline instead, which is what a standalone status pill is.
|
|
120
|
+
*
|
|
121
|
+
* There is no Base UI primitive under this, and there should not be: a badge has
|
|
122
|
+
* no interaction, no state and no keyboard contract. It is a mark. Wiring it to a
|
|
123
|
+
* widget primitive would hand every decorative dot a role it cannot honour.
|
|
124
|
+
*
|
|
125
|
+
* What it does owe a screen reader is a sentence rather than a number, which is
|
|
126
|
+
* what `label` is for — `content={3}` beside a bell reads out as "3".
|
|
127
|
+
*/
|
|
128
|
+
export const PlBadge = /* @__PURE__ */ React.forwardRef(function PlBadge({ variant = 'solid', size = 'md', color = 'primary', density = 'default', elevation = 0, content, max = 99, dot = false, showZero = false, invisible = false, placement = 'top-end', overlap = 'square', label, className, style, children, ...props }, ref) {
|
|
129
|
+
const anchored = hasContent(children);
|
|
130
|
+
// `0` is content, and `hasContent` would agree — this is the one place the
|
|
131
|
+
// library asks a second question, because a count of nothing is not news.
|
|
132
|
+
const empty = !hasContent(content) || (content === 0 && !showZero);
|
|
133
|
+
const asDot = dot || empty;
|
|
134
|
+
const hidden = invisible || (empty && !dot);
|
|
135
|
+
const markerClasses = [
|
|
136
|
+
'pointer-events-none z-10 inline-flex shrink-0 items-center justify-center',
|
|
137
|
+
'font-semibold tabular-nums whitespace-nowrap',
|
|
138
|
+
badgeRadiusClasses,
|
|
139
|
+
transitionClasses,
|
|
140
|
+
variantClasses[variant],
|
|
141
|
+
asDot
|
|
142
|
+
? dotSizeClasses[size]
|
|
143
|
+
: [
|
|
144
|
+
badgeHeightClasses[size],
|
|
145
|
+
badgeTextClasses[size],
|
|
146
|
+
badgePaddingClasses[density][size]
|
|
147
|
+
].join(' '),
|
|
148
|
+
anchored ? `absolute ${placementClasses[placement]}` : 'relative align-middle',
|
|
149
|
+
anchored ? (asDot ? cornerOffsets[size].dot : cornerOffsets[size].badge) : '',
|
|
150
|
+
anchored && overlap === 'circle' ? circleInsetClasses[placement] : '',
|
|
151
|
+
// Visibility, not opacity: a half-faded badge is a badge you have to squint
|
|
152
|
+
// at to find out whether it is there. The marker keeps its box either way,
|
|
153
|
+
// so nothing around it moves when it comes back.
|
|
154
|
+
hidden ? 'invisible' : '',
|
|
155
|
+
className ?? ''
|
|
156
|
+
]
|
|
157
|
+
.filter(Boolean)
|
|
158
|
+
.join(' ');
|
|
159
|
+
const capped = capContent(content, max);
|
|
160
|
+
const marker = (_jsx("span", { ref: ref, className: markerClasses, style: { ...controlSlots(color, elevation, variant), ...style }, "aria-hidden": hidden ? true : undefined, ...props, children: hidden ? null : (_jsxs(_Fragment, { children: [asDot || label ? _jsx("span", { className: srOnlyClasses, children: label ?? capped }) : null, asDot ? null : _jsx("span", { "aria-hidden": label ? true : undefined, children: capped })] })) }));
|
|
161
|
+
if (!anchored) {
|
|
162
|
+
return marker;
|
|
163
|
+
}
|
|
164
|
+
// `inline-flex` rather than `inline-block`: the shell has to be exactly as
|
|
165
|
+
// wide and as tall as what it wraps, or a badged icon button stops lining up
|
|
166
|
+
// with the bare one beside it.
|
|
167
|
+
return (_jsxs("span", { className: "relative inline-flex shrink-0 align-middle", children: [children, marker] }));
|
|
168
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PlBadge } from './PlBadge.js';
|