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,206 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Radio as BaseUIRadio } from '@base-ui/react/radio';
|
|
4
|
+
import { RadioGroup as BaseUIRadioGroup } from '@base-ui/react/radio-group';
|
|
5
|
+
import { controlHeightClasses, controlSlots, controlTextClasses, focusRingInsetClasses, gapClasses, glassClasses, hasContent, iconClasses, paddingXClasses, transitionClasses } from '../../internal/styles.js';
|
|
6
|
+
const SegmentedButtonContext = /* @__PURE__ */ React.createContext({
|
|
7
|
+
variant: 'glass',
|
|
8
|
+
size: 'md',
|
|
9
|
+
density: 'default',
|
|
10
|
+
fullWidth: false
|
|
11
|
+
});
|
|
12
|
+
/* ---------------------------------------------------------------------------
|
|
13
|
+
* The groove and the tile
|
|
14
|
+
* ------------------------------------------------------------------------- */
|
|
15
|
+
/**
|
|
16
|
+
* The groove carries `--plass-well`, the one inset shadow in the library and
|
|
17
|
+
* the same one a `solid` field is drawn with. A segmented button, a slider's
|
|
18
|
+
* rail and a filled text field are the same idea: something recessed that holds
|
|
19
|
+
* a value.
|
|
20
|
+
*/
|
|
21
|
+
const troughClasses = {
|
|
22
|
+
solid: `${glassClasses} bg-(--plass-glass-press) p-1 [box-shadow:var(--p-elev),var(--plass-well)]`,
|
|
23
|
+
glass: `${glassClasses} border bg-(--plass-glass) p-1 [border-color:var(--plass-glass-line)] [box-shadow:var(--p-elev),var(--plass-well)]`,
|
|
24
|
+
ghost: ''
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* The tile that slides.
|
|
28
|
+
*
|
|
29
|
+
* `solid` makes it the family's gradient with that family's tinted shadow under
|
|
30
|
+
* it — a key of tinted glass riding in a groove, which is the design language's
|
|
31
|
+
* own sentence with nothing added. The other two lift a pane of clear glass
|
|
32
|
+
* instead and leave the label in the accent.
|
|
33
|
+
*/
|
|
34
|
+
const tileClasses = {
|
|
35
|
+
solid: '[background-image:var(--p-fill)] [box-shadow:var(--plass-shadow-1),var(--p-lift)]',
|
|
36
|
+
glass: `${glassClasses} bg-(--plass-glass-press) [box-shadow:var(--plass-shadow-1),var(--plass-gloss-glass)]`,
|
|
37
|
+
ghost: `${glassClasses} bg-(--plass-glass-press) [box-shadow:var(--plass-shadow-1),var(--plass-gloss-glass)]`
|
|
38
|
+
};
|
|
39
|
+
/** What the chosen label is written in, which is the other half of the tile. */
|
|
40
|
+
const checkedTextClasses = {
|
|
41
|
+
solid: 'data-[checked]:text-(--p-on-solid)',
|
|
42
|
+
glass: 'data-[checked]:text-(--p-accent)',
|
|
43
|
+
ghost: 'data-[checked]:text-(--p-accent)'
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* One choice in a segmented button.
|
|
47
|
+
*
|
|
48
|
+
* It has no `size`, no `color` and no `variant` of its own: all three belong to
|
|
49
|
+
* the set, which is the only place they can be set once and mean the same thing
|
|
50
|
+
* for every segment.
|
|
51
|
+
*/
|
|
52
|
+
export const PlSegment = /* @__PURE__ */ React.forwardRef(function PlSegment({ value, startIcon, endIcon, disabled = false, className, children, ...props }, ref) {
|
|
53
|
+
const { variant, size, density, fullWidth } = React.useContext(SegmentedButtonContext);
|
|
54
|
+
return (_jsxs(BaseUIRadio.Root, { ref: ref, value: value, disabled: disabled, "data-segment": "", className: [
|
|
55
|
+
// `z-10` and a stacking context of its own: the tile is painted behind
|
|
56
|
+
// the segments, and without this it would cover the label it is under.
|
|
57
|
+
'relative z-10 inline-flex shrink-0 cursor-pointer items-center justify-center select-none',
|
|
58
|
+
'font-semibold whitespace-nowrap',
|
|
59
|
+
'[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]',
|
|
60
|
+
controlHeightClasses[size],
|
|
61
|
+
controlTextClasses[size],
|
|
62
|
+
gapClasses[size],
|
|
63
|
+
paddingXClasses[density][size],
|
|
64
|
+
// Round, and one of only three places the library allows it — for the
|
|
65
|
+
// same reason a switch's track is: this is not a sheet lying on the
|
|
66
|
+
// page, it is a tile riding in a groove cut into one.
|
|
67
|
+
'rounded-full',
|
|
68
|
+
transitionClasses,
|
|
69
|
+
iconClasses,
|
|
70
|
+
'text-(--plass-muted-fg) hover:text-(--plass-fg)',
|
|
71
|
+
checkedTextClasses[variant],
|
|
72
|
+
// Inset rather than offset — an offset ring on a segment inside a groove
|
|
73
|
+
// is drawn on top of its neighbours.
|
|
74
|
+
focusRingInsetClasses,
|
|
75
|
+
'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50',
|
|
76
|
+
'data-[readonly]:cursor-default',
|
|
77
|
+
fullWidth ? 'flex-1' : '',
|
|
78
|
+
className ?? ''
|
|
79
|
+
]
|
|
80
|
+
.filter(Boolean)
|
|
81
|
+
.join(' '), ...props, children: [hasContent(startIcon) ? (_jsx("span", { className: "flex h-[1lh] shrink-0 items-center", children: startIcon })) : null, children, hasContent(endIcon) ? (_jsx("span", { className: "flex h-[1lh] shrink-0 items-center", children: endIcon })) : null] }));
|
|
82
|
+
});
|
|
83
|
+
/**
|
|
84
|
+
* Two or more choices in one pill, exactly one of them taken.
|
|
85
|
+
*
|
|
86
|
+
* Underneath it is a radio group, and that is the whole accessibility argument:
|
|
87
|
+
* a segmented button *is* "exactly one of these", so it gets
|
|
88
|
+
* `role="radiogroup"`, one tab stop for the set, arrow keys within it, and
|
|
89
|
+
* `aria-checked` on the one that is taken. Building it out of `aria-pressed`
|
|
90
|
+
* toggles — which is what a row of buttons would give — would announce four
|
|
91
|
+
* independent switches, three of which happen to be off.
|
|
92
|
+
*
|
|
93
|
+
* The tile slides because its `left`, `top`, `width` and `height` are measured
|
|
94
|
+
* off the chosen segment and animated. Nothing is transformed: the tile is an
|
|
95
|
+
* empty box, and no label is resampled while it travels. That is what lets the
|
|
96
|
+
* house no-transform rule survive a component whose entire point is that
|
|
97
|
+
* something moves.
|
|
98
|
+
*
|
|
99
|
+
* `left`, not `inset-inline-start`: `offsetLeft` is a distance from the left
|
|
100
|
+
* edge and stays one under RTL, and pairing a physical measurement with a
|
|
101
|
+
* logical property is what would break the direction.
|
|
102
|
+
*/
|
|
103
|
+
export const PlSegmentedButton = /* @__PURE__ */ React.forwardRef(function PlSegmentedButton({ variant = 'glass', size = 'md', color = 'primary', density = 'default', elevation = 0, value: valueProp, defaultValue = null, onValueChange, disabled = false, readOnly = false, name, fullWidth = false, className, style, children, ...props }, ref) {
|
|
104
|
+
const [uncontrolled, setUncontrolled] = React.useState(defaultValue);
|
|
105
|
+
const controlled = valueProp !== undefined;
|
|
106
|
+
const value = controlled ? valueProp : uncontrolled;
|
|
107
|
+
const rootRef = React.useRef(null);
|
|
108
|
+
const tileRef = React.useRef(null);
|
|
109
|
+
/**
|
|
110
|
+
* Writes the chosen segment's box onto the tile as four custom properties.
|
|
111
|
+
*
|
|
112
|
+
* Written straight to the element rather than held in state, the way
|
|
113
|
+
* PlButton writes the pointer position: a `setState` here would re-render
|
|
114
|
+
* the whole set on every resize, and nothing in the tree depends on the
|
|
115
|
+
* numbers except four CSS declarations.
|
|
116
|
+
*
|
|
117
|
+
* `animate` is what separates the two callers. A value change is the thing
|
|
118
|
+
* this component exists to animate; a resize is the container moving under a
|
|
119
|
+
* tile that was already in the right place, and animating that is a tile
|
|
120
|
+
* that lags behind the window being dragged.
|
|
121
|
+
*/
|
|
122
|
+
const measure = React.useCallback((animate) => {
|
|
123
|
+
const root = rootRef.current;
|
|
124
|
+
const tile = tileRef.current;
|
|
125
|
+
if (!root || !tile) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
const active = root.querySelector('[data-segment][data-checked]');
|
|
129
|
+
if (!active) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
// A tile that has only just mounted has nowhere to travel *from*, so its
|
|
133
|
+
// first placement is instant however it was asked for — that is what makes
|
|
134
|
+
// the first choice of an empty set appear under the segment rather than
|
|
135
|
+
// fly in from the left edge.
|
|
136
|
+
const instant = !animate || !tile.hasAttribute('data-ready');
|
|
137
|
+
if (instant) {
|
|
138
|
+
tile.removeAttribute('data-ready');
|
|
139
|
+
}
|
|
140
|
+
// `offsetLeft`/`offsetTop` are measured from the offsetParent's padding
|
|
141
|
+
// edge, and `left`/`top` on an absolutely positioned child resolve against
|
|
142
|
+
// the same box — so the groove's own padding is already accounted for and
|
|
143
|
+
// must not be subtracted again.
|
|
144
|
+
tile.style.setProperty('--p-seg-x', `${active.offsetLeft}px`);
|
|
145
|
+
tile.style.setProperty('--p-seg-y', `${active.offsetTop}px`);
|
|
146
|
+
tile.style.setProperty('--p-seg-w', `${active.offsetWidth}px`);
|
|
147
|
+
tile.style.setProperty('--p-seg-h', `${active.offsetHeight}px`);
|
|
148
|
+
if (instant) {
|
|
149
|
+
// Reading a layout property commits the four writes above while the
|
|
150
|
+
// duration is still 0ms, so turning the transition back on cannot
|
|
151
|
+
// animate a move that has already happened.
|
|
152
|
+
void tile.offsetWidth;
|
|
153
|
+
}
|
|
154
|
+
tile.setAttribute('data-ready', '');
|
|
155
|
+
}, []);
|
|
156
|
+
// Before the browser paints, or the tile is visibly at nothing for a frame.
|
|
157
|
+
React.useLayoutEffect(() => {
|
|
158
|
+
measure(true);
|
|
159
|
+
}, [measure, value, variant, size, density, fullWidth, children]);
|
|
160
|
+
React.useEffect(() => {
|
|
161
|
+
const root = rootRef.current;
|
|
162
|
+
if (!root) {
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const observer = new ResizeObserver(() => measure(false));
|
|
166
|
+
observer.observe(root);
|
|
167
|
+
return () => observer.disconnect();
|
|
168
|
+
}, [measure]);
|
|
169
|
+
const context = React.useMemo(() => ({ variant, size, density, fullWidth }), [variant, size, density, fullWidth]);
|
|
170
|
+
return (_jsx(SegmentedButtonContext.Provider, { value: context, children: _jsxs(BaseUIRadioGroup, { ref: (node) => {
|
|
171
|
+
rootRef.current = node;
|
|
172
|
+
if (typeof ref === 'function') {
|
|
173
|
+
ref(node);
|
|
174
|
+
}
|
|
175
|
+
else if (ref) {
|
|
176
|
+
ref.current = node;
|
|
177
|
+
}
|
|
178
|
+
}, value: value, onValueChange: (next) => {
|
|
179
|
+
const chosen = (next ?? null);
|
|
180
|
+
if (!controlled) {
|
|
181
|
+
setUncontrolled(chosen);
|
|
182
|
+
}
|
|
183
|
+
onValueChange?.(chosen);
|
|
184
|
+
}, disabled: disabled, readOnly: readOnly, name: name, className: [
|
|
185
|
+
// `relative` is load-bearing twice over: it is what makes the groove
|
|
186
|
+
// the segments' offsetParent, and what the tile is positioned in.
|
|
187
|
+
'relative inline-flex items-center rounded-full',
|
|
188
|
+
troughClasses[variant],
|
|
189
|
+
transitionClasses,
|
|
190
|
+
readOnly ? 'saturate-[0.55]' : '',
|
|
191
|
+
disabled ? 'opacity-50 saturate-[0.35]' : '',
|
|
192
|
+
fullWidth ? 'flex w-full' : '',
|
|
193
|
+
className ?? ''
|
|
194
|
+
]
|
|
195
|
+
.filter(Boolean)
|
|
196
|
+
.join(' '), style: { ...controlSlots(color, elevation, variant), ...style }, ...props, children: [value !== null && value !== undefined ? (_jsx("span", { ref: tileRef, "aria-hidden": "true", className: [
|
|
197
|
+
'pointer-events-none absolute rounded-full',
|
|
198
|
+
'top-(--p-seg-y) left-(--p-seg-x) h-(--p-seg-h) w-(--p-seg-w)',
|
|
199
|
+
tileClasses[variant],
|
|
200
|
+
'[transition-property:left,top,width,height]',
|
|
201
|
+
'[transition-timing-function:var(--plass-ease)]',
|
|
202
|
+
// Nothing until the first measurement has landed; the house
|
|
203
|
+
// duration from then on.
|
|
204
|
+
'[transition-duration:0ms] data-[ready]:[transition-duration:var(--plass-duration)]'
|
|
205
|
+
].join(' ') })) : null, children] }) }));
|
|
206
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PlSegment, PlSegmentedButton } from './PlSegmentedButton.js';
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PlassElevation, PlassStyleProps } from '../../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* What a select's value may be.
|
|
5
|
+
*
|
|
6
|
+
* Deliberately not generic over arbitrary objects. A select is a form control,
|
|
7
|
+
* its value is what a form submits, and every escape from that — object values,
|
|
8
|
+
* custom equality, a stringifier for the trigger — buys flexibility by making
|
|
9
|
+
* the common case harder to write. Keep the identifier here and look the object
|
|
10
|
+
* up on the other side.
|
|
11
|
+
*/
|
|
12
|
+
export type PlSelectValue = string | number;
|
|
13
|
+
export interface PlSelectOption {
|
|
14
|
+
/** Submitted, and what `value` / `onValueChange` speak in. */
|
|
15
|
+
value: PlSelectValue;
|
|
16
|
+
/** Shown in the list and in the trigger. Defaults to the value itself. */
|
|
17
|
+
label?: React.ReactNode;
|
|
18
|
+
/** Unavailable, but still listed — the option exists, it just cannot be picked. */
|
|
19
|
+
disabled?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface PlSelectProps extends PlassStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'defaultValue' | 'children'> {
|
|
22
|
+
/**
|
|
23
|
+
* The options, as data. There is no `<PlSelect.Option>` to compose: what a
|
|
24
|
+
* caller has is almost always an array already, and the list has to be
|
|
25
|
+
* available to the trigger before the popup has ever been opened.
|
|
26
|
+
*/
|
|
27
|
+
items: readonly PlSelectOption[];
|
|
28
|
+
/** The chosen value. Use with `onValueChange` for a controlled select. */
|
|
29
|
+
value?: PlSelectValue | null;
|
|
30
|
+
/** The initially chosen value, for an uncontrolled select. */
|
|
31
|
+
defaultValue?: PlSelectValue | null;
|
|
32
|
+
onValueChange?: (value: PlSelectValue | null) => void;
|
|
33
|
+
/** Shown in the trigger while nothing is chosen. */
|
|
34
|
+
placeholder?: React.ReactNode;
|
|
35
|
+
/**
|
|
36
|
+
* Drop shadow depth of the *trigger*. `0`, like a PlTextField: a field is cut
|
|
37
|
+
* into the sheet rather than resting on it. The popup has its own, fixed at
|
|
38
|
+
* `3` — it genuinely floats above the page, which is the one case elevation
|
|
39
|
+
* is for.
|
|
40
|
+
* @default 0
|
|
41
|
+
*/
|
|
42
|
+
elevation?: PlassElevation;
|
|
43
|
+
/** Label above the trigger, wired to it by Base UI's Field. */
|
|
44
|
+
label?: React.ReactNode;
|
|
45
|
+
/** Helper text below the trigger. */
|
|
46
|
+
description?: React.ReactNode;
|
|
47
|
+
/** Error message below. Its presence also turns the select invalid. */
|
|
48
|
+
error?: React.ReactNode;
|
|
49
|
+
/** Forces the invalid state without a message. Defaults to whether `error` has content. */
|
|
50
|
+
invalid?: boolean;
|
|
51
|
+
/** Content placed before the value. Sized in `em`, so it tracks the text. */
|
|
52
|
+
startIcon?: React.ReactNode;
|
|
53
|
+
/** Stretches to the width of the container. */
|
|
54
|
+
fullWidth?: boolean;
|
|
55
|
+
/** Unavailable. */
|
|
56
|
+
disabled?: boolean;
|
|
57
|
+
/** The value is shown but cannot be changed. */
|
|
58
|
+
readOnly?: boolean;
|
|
59
|
+
/** Whether a value must be chosen before the form is submitted. */
|
|
60
|
+
required?: boolean;
|
|
61
|
+
/** Identifies the field when a form is submitted. */
|
|
62
|
+
name?: string;
|
|
63
|
+
id?: string;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* One value chosen from a list of them.
|
|
67
|
+
*
|
|
68
|
+
* The trigger is a PlTextField's shell wearing a chevron, on purpose: a form
|
|
69
|
+
* where the select is a different height, radius or material from the fields
|
|
70
|
+
* around it is a form that looks assembled rather than designed. That is why
|
|
71
|
+
* `fieldRestClasses` lives in `internal/styles` and not in either component.
|
|
72
|
+
*
|
|
73
|
+
* Base UI owns everything hard about this — the popup's positioning and
|
|
74
|
+
* flipping, the focus trap, typeahead, the hidden input that makes it submit —
|
|
75
|
+
* and the work here is the surface it all wears.
|
|
76
|
+
*/
|
|
77
|
+
export declare const PlSelect: React.ForwardRefExoticComponent<PlSelectProps & React.RefAttributes<HTMLButtonElement>>;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Select as BaseUISelect } from '@base-ui/react/select';
|
|
4
|
+
import { Field } from '@base-ui/react/field';
|
|
5
|
+
import { CheckIcon, ChevronIcon } from '../../internal/icons.js';
|
|
6
|
+
import { WidthSizer } from '../../internal/sizer.js';
|
|
7
|
+
import { controlHeightClasses, controlTextLeadingClasses, disabledClasses, fieldReadOnlyClasses, fieldRestClasses, focusWithinRingClasses, gapClasses, glassClasses, hasContent, iconClasses, metaTextClasses, paddingXClasses, radiusClasses, stackGapClasses, surfaceSlots, transitionClasses } from '../../internal/styles.js';
|
|
8
|
+
/** The trigger is a PlTextField's shell, to the pixel. */
|
|
9
|
+
const triggerBaseClasses = /* @__PURE__ */ [
|
|
10
|
+
'group relative flex w-full cursor-pointer items-center select-none',
|
|
11
|
+
'[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]',
|
|
12
|
+
transitionClasses,
|
|
13
|
+
focusWithinRingClasses,
|
|
14
|
+
iconClasses
|
|
15
|
+
].join(' ');
|
|
16
|
+
/**
|
|
17
|
+
* The popup is the one surface in the library that is *supposed* to float, so
|
|
18
|
+
* unlike everything else it carries a shadow by default — at level 3.
|
|
19
|
+
*
|
|
20
|
+
* It is the glass at its most opaque, because it has a page under it rather
|
|
21
|
+
* than a sheet: a 62%-translucent pane over arbitrary body copy is a pane you
|
|
22
|
+
* read the body copy through.
|
|
23
|
+
*
|
|
24
|
+
* Every `--p-*` it reads is set on the popup itself rather than inherited from
|
|
25
|
+
* the Field around it. A portalled popup renders at the end of `<body>`, so it
|
|
26
|
+
* is outside the element the slots were declared on, and a `var()` with nothing
|
|
27
|
+
* to resolve to is not a fallback — `border-color` collapses to `currentColor`
|
|
28
|
+
* (a black hairline) and `background-color` to transparent.
|
|
29
|
+
*/
|
|
30
|
+
const popupClasses = /* @__PURE__ */ [
|
|
31
|
+
glassClasses,
|
|
32
|
+
'max-h-[min(20rem,var(--available-height))] overflow-y-auto overscroll-contain',
|
|
33
|
+
'min-w-[var(--anchor-width)] border bg-(--plass-glass-press) p-1',
|
|
34
|
+
'[border-color:var(--plass-glass-line)]',
|
|
35
|
+
'[box-shadow:var(--plass-shadow-3),var(--plass-gloss-glass)]',
|
|
36
|
+
'[outline:none]'
|
|
37
|
+
].join(' ');
|
|
38
|
+
const itemClasses = /* @__PURE__ */ [
|
|
39
|
+
'relative flex cursor-pointer items-center gap-2 select-none',
|
|
40
|
+
'rounded-(--plass-radius-xs) py-1.5 pe-2 ps-7',
|
|
41
|
+
transitionClasses,
|
|
42
|
+
// `data-highlighted` rather than `:hover`: it is also what the arrow keys
|
|
43
|
+
// move, so the mouse and the keyboard light the same row.
|
|
44
|
+
'data-[highlighted]:bg-(--p-soft-hover) data-[highlighted]:text-(--p-accent)',
|
|
45
|
+
'data-[selected]:font-semibold data-[selected]:text-(--p-accent)',
|
|
46
|
+
'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50',
|
|
47
|
+
'[outline:none]'
|
|
48
|
+
].join(' ');
|
|
49
|
+
/**
|
|
50
|
+
* One value chosen from a list of them.
|
|
51
|
+
*
|
|
52
|
+
* The trigger is a PlTextField's shell wearing a chevron, on purpose: a form
|
|
53
|
+
* where the select is a different height, radius or material from the fields
|
|
54
|
+
* around it is a form that looks assembled rather than designed. That is why
|
|
55
|
+
* `fieldRestClasses` lives in `internal/styles` and not in either component.
|
|
56
|
+
*
|
|
57
|
+
* Base UI owns everything hard about this — the popup's positioning and
|
|
58
|
+
* flipping, the focus trap, typeahead, the hidden input that makes it submit —
|
|
59
|
+
* and the work here is the surface it all wears.
|
|
60
|
+
*/
|
|
61
|
+
export const PlSelect = /* @__PURE__ */ React.forwardRef(function PlSelect({ variant = 'glass', size = 'md', color = 'primary', density = 'default', elevation = 0, items, value, defaultValue, onValueChange, placeholder, label, description, error, invalid, startIcon, fullWidth = false, disabled = false, readOnly = false, required = false, name, id, className, style, ...props }, ref) {
|
|
62
|
+
const hasError = hasContent(error);
|
|
63
|
+
const isInvalid = invalid ?? hasError;
|
|
64
|
+
// Invalid re-points the whole slot family at `danger`, so the edge, the ring
|
|
65
|
+
// and the message all turn over together.
|
|
66
|
+
const family = isInvalid ? 'danger' : color;
|
|
67
|
+
// Base UI reads this to render the chosen option's *label* in the trigger
|
|
68
|
+
// rather than its raw value, which is the only way `<Select.Value>` can show
|
|
69
|
+
// "Seoul" for `value="kr-11"` before the popup has ever been mounted.
|
|
70
|
+
const baseItems = React.useMemo(() => items.map((item) => ({ label: item.label ?? String(item.value), value: item.value })), [items]);
|
|
71
|
+
// Holds the trigger open at the width of the longest thing it could say, so
|
|
72
|
+
// choosing a shorter option does not shrink the field out from under the
|
|
73
|
+
// pointer that chose it.
|
|
74
|
+
const sizerSamples = React.useMemo(() => [
|
|
75
|
+
...items.map((item) => item.label ?? String(item.value)),
|
|
76
|
+
...(hasContent(placeholder) ? [placeholder] : [])
|
|
77
|
+
], [items, placeholder]);
|
|
78
|
+
return (_jsxs(Field.Root, { disabled: disabled, invalid: isInvalid, className: [
|
|
79
|
+
'flex-col align-top',
|
|
80
|
+
stackGapClasses[size],
|
|
81
|
+
fullWidth ? 'flex w-full' : 'inline-flex',
|
|
82
|
+
className ?? ''
|
|
83
|
+
]
|
|
84
|
+
.filter(Boolean)
|
|
85
|
+
.join(' '), style: { ...surfaceSlots(family, elevation), ...style }, ...props, children: [label ? (_jsx(Field.Label, { className: [
|
|
86
|
+
metaTextClasses[size],
|
|
87
|
+
'font-semibold',
|
|
88
|
+
disabled ? 'text-(--plass-muted-fg)' : 'text-(--plass-fg)'
|
|
89
|
+
].join(' '), children: label })) : null, _jsxs(BaseUISelect.Root, { id: id, name: name, items: baseItems, value: value, defaultValue: defaultValue, onValueChange: (next) => onValueChange?.(next), disabled: disabled, readOnly: readOnly, required: required, children: [_jsxs(BaseUISelect.Trigger, { ref: ref, className: [
|
|
90
|
+
triggerBaseClasses,
|
|
91
|
+
controlHeightClasses[size],
|
|
92
|
+
controlTextLeadingClasses[size],
|
|
93
|
+
radiusClasses[size],
|
|
94
|
+
gapClasses[size],
|
|
95
|
+
paddingXClasses[density][size],
|
|
96
|
+
// An if/else rather than stacked variants: two Tailwind classes of
|
|
97
|
+
// equal specificity resolve by their order in the generated sheet.
|
|
98
|
+
disabled
|
|
99
|
+
? disabledClasses[variant]
|
|
100
|
+
: readOnly
|
|
101
|
+
? `${fieldReadOnlyClasses[variant]} cursor-default`
|
|
102
|
+
: fieldRestClasses[variant]
|
|
103
|
+
].join(' '), children: [startIcon ? (_jsx("span", { className: "flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)", children: startIcon })) : null, _jsxs("span", { className: "flex min-w-0 flex-1 flex-col", children: [_jsx(BaseUISelect.Value, { className: [
|
|
104
|
+
'w-full truncate text-start',
|
|
105
|
+
// The placeholder is muted the same way a PlTextField's is, so
|
|
106
|
+
// an empty select and an empty field read as equally empty.
|
|
107
|
+
'data-[placeholder]:text-(--plass-muted-fg)'
|
|
108
|
+
].join(' '), placeholder: placeholder }), _jsx(WidthSizer, { samples: sizerSamples })] }), _jsx(BaseUISelect.Icon, { className: [
|
|
109
|
+
'flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)',
|
|
110
|
+
// The chevron is the one thing here that may turn: it is a glyph,
|
|
111
|
+
// not a label, and nothing about it resamples.
|
|
112
|
+
'[transition:rotate_var(--plass-duration)_var(--plass-ease)]',
|
|
113
|
+
'data-[popup-open]:rotate-180'
|
|
114
|
+
].join(' '), children: _jsx(ChevronIcon, {}) })] }), _jsx(BaseUISelect.Portal, { children: _jsx(BaseUISelect.Positioner, { className: "plass-portal z-50 [outline:none]", sideOffset: 6, alignItemWithTrigger: false, children: _jsx(BaseUISelect.Popup, { className: `${popupClasses} ${radiusClasses[size]} ${controlTextLeadingClasses[size]}`, style: surfaceSlots(family, 3), children: items.map((item) => (_jsxs(BaseUISelect.Item, { value: item.value, disabled: item.disabled, className: itemClasses, children: [_jsx(BaseUISelect.ItemIndicator, { className: "absolute start-1.5 flex size-4 items-center justify-center", children: _jsx(CheckIcon, {}) }), _jsx(BaseUISelect.ItemText, { className: "truncate", children: item.label ?? String(item.value) })] }, String(item.value)))) }) }) })] }), description ? (_jsx(Field.Description, { className: `${metaTextClasses[size]} text-(--plass-muted-fg)`, children: description })) : null, hasError ? (_jsx(Field.Error, { match: true, className: `${metaTextClasses[size]} text-(--p-accent)`, children: error })) : null] }));
|
|
115
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PlSelect } from './PlSelect.js';
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
3
|
+
import type { PlassColor, PlassSize } from '../../types.js';
|
|
4
|
+
/**
|
|
5
|
+
* What the placeholder is standing in for.
|
|
6
|
+
*
|
|
7
|
+
* - `line` — a run of text. Sized off the type scale, so a `md` line is exactly
|
|
8
|
+
* as tall as the `md` type it will be replaced by.
|
|
9
|
+
* - `rect` — a block: an image, a chart, a card, a map.
|
|
10
|
+
* - `circle` — an avatar, or anything else round.
|
|
11
|
+
*/
|
|
12
|
+
export type PlSkeletonShape = 'line' | 'rect' | 'circle';
|
|
13
|
+
export interface PlSkeletonProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'color'> {
|
|
14
|
+
/** @default 'line' */
|
|
15
|
+
shape?: PlSkeletonShape;
|
|
16
|
+
/**
|
|
17
|
+
* How many lines to draw, for `shape="line"`. The last one is drawn short, the
|
|
18
|
+
* way the last line of a paragraph is, so a block of them reads as prose
|
|
19
|
+
* rather than as a barcode. Ignored by the other two shapes.
|
|
20
|
+
* @default 1
|
|
21
|
+
*/
|
|
22
|
+
lines?: number;
|
|
23
|
+
/**
|
|
24
|
+
* The scale of the thing being stood in for: the type scale for a `line`, the
|
|
25
|
+
* diameter for a `circle`, the default block height for a `rect`.
|
|
26
|
+
* @default 'md'
|
|
27
|
+
*/
|
|
28
|
+
size?: PlassSize;
|
|
29
|
+
/**
|
|
30
|
+
* Colour family. `secondary` by default, and it is worth leaving there: a
|
|
31
|
+
* placeholder that carries a semantic colour is saying something about content
|
|
32
|
+
* that has not arrived yet.
|
|
33
|
+
* @default 'secondary'
|
|
34
|
+
*/
|
|
35
|
+
color?: PlassColor;
|
|
36
|
+
/** An explicit width. Numbers are pixels. */
|
|
37
|
+
width?: number | string;
|
|
38
|
+
/** An explicit height. Numbers are pixels. */
|
|
39
|
+
height?: number | string;
|
|
40
|
+
/**
|
|
41
|
+
* The travelling highlight. Turn it off for a page holding dozens of them, or
|
|
42
|
+
* where the wait is expected to be long enough that motion becomes noise.
|
|
43
|
+
*
|
|
44
|
+
* A reduced-motion preference already replaces the sweep with a colour pulse
|
|
45
|
+
* without being asked, so this is not the accessibility switch.
|
|
46
|
+
* @default true
|
|
47
|
+
*/
|
|
48
|
+
animated?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* What a screen reader is told, if anything.
|
|
51
|
+
*
|
|
52
|
+
* Unset — the default — the placeholder is `aria-hidden`, because a dozen
|
|
53
|
+
* boxes each announcing themselves is worse than silence. Give the *one*
|
|
54
|
+
* skeleton that stands for the whole region a label and it becomes a live
|
|
55
|
+
* `status` instead.
|
|
56
|
+
*/
|
|
57
|
+
label?: string;
|
|
58
|
+
/** Renders something other than a `<div>`. Base UI's own escape hatch. */
|
|
59
|
+
render?: useRender.RenderProp;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The shape of something that has not loaded yet.
|
|
63
|
+
*
|
|
64
|
+
* It reserves the space the real thing will take, which is the whole job: a card
|
|
65
|
+
* that grows by 200px when its image arrives has moved everything below it while
|
|
66
|
+
* somebody was reading. A spinner cannot do that.
|
|
67
|
+
*
|
|
68
|
+
* The three shapes are the three things a layout is made of — a run of text, a
|
|
69
|
+
* block and a circle — and each is sized off the ladder the real component uses,
|
|
70
|
+
* so a `md` line is as tall as `md` type and a `md` circle is exactly a
|
|
71
|
+
* `PlAvatar` at `md`.
|
|
72
|
+
*/
|
|
73
|
+
export declare const PlSkeleton: React.ForwardRefExoticComponent<PlSkeletonProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
4
|
+
import { controlHeightClasses, controlSquareClasses, surfaceSlots } from '../../internal/styles.js';
|
|
5
|
+
/**
|
|
6
|
+
* A line's height is the type scale itself — the same lengths
|
|
7
|
+
* `sheetBodyClasses` sets as a font size — so a placeholder occupies the em box
|
|
8
|
+
* of the text that replaces it. The leading around it is `lineGapClasses`, and
|
|
9
|
+
* the two together add up to that ladder's line box.
|
|
10
|
+
*/
|
|
11
|
+
const lineHeightClasses = {
|
|
12
|
+
xs: 'h-[0.6875rem]',
|
|
13
|
+
sm: 'h-[0.75rem]',
|
|
14
|
+
md: 'h-[0.8125rem]',
|
|
15
|
+
lg: 'h-[0.9375rem]',
|
|
16
|
+
xl: 'h-[1.0625rem]'
|
|
17
|
+
};
|
|
18
|
+
/** The leading: the body ladder's line box less the bar drawn in it. */
|
|
19
|
+
const lineGapClasses = {
|
|
20
|
+
xs: 'gap-[0.3125rem]',
|
|
21
|
+
sm: 'gap-[0.375rem]',
|
|
22
|
+
md: 'gap-[0.5625rem]',
|
|
23
|
+
lg: 'gap-[0.5625rem]',
|
|
24
|
+
xl: 'gap-[0.6875rem]'
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* A bar's corner, at ~45% of its own height — held just short of the 50% that
|
|
28
|
+
* would make it a capsule.
|
|
29
|
+
*
|
|
30
|
+
* Not `radiusClasses`, which is ~30% of a *control's* height: 12px on a 13px bar
|
|
31
|
+
* is a capsule and a half. Not `tickRadiusClasses` either, which is sized
|
|
32
|
+
* against a box rather than against a run of text.
|
|
33
|
+
*/
|
|
34
|
+
const barRadiusClasses = {
|
|
35
|
+
xs: 'rounded-[0.3125rem]',
|
|
36
|
+
sm: 'rounded-[0.3125rem]',
|
|
37
|
+
md: 'rounded-[0.375rem]',
|
|
38
|
+
lg: 'rounded-[0.4375rem]',
|
|
39
|
+
xl: 'rounded-[0.5rem]'
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* What a `rect` is as tall as when nothing says otherwise: a thumbnail. Anything
|
|
43
|
+
* else wants `height`, and most uses of this shape pass one.
|
|
44
|
+
*/
|
|
45
|
+
const blockHeightClasses = {
|
|
46
|
+
xs: 'h-12',
|
|
47
|
+
sm: 'h-16',
|
|
48
|
+
md: 'h-20',
|
|
49
|
+
lg: 'h-28',
|
|
50
|
+
xl: 'h-36'
|
|
51
|
+
};
|
|
52
|
+
/** A block's corner is the sheet ladder, because a block stands for a sheet. */
|
|
53
|
+
const blockRadiusClasses = {
|
|
54
|
+
xs: 'rounded-(--plass-radius-xs)',
|
|
55
|
+
sm: 'rounded-(--plass-radius-sm)',
|
|
56
|
+
md: 'rounded-(--plass-radius-md)',
|
|
57
|
+
lg: 'rounded-(--plass-radius-lg)',
|
|
58
|
+
xl: 'rounded-(--plass-radius-xl)'
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* The surface, and it is deliberately **not** glass.
|
|
62
|
+
*
|
|
63
|
+
* Every other sheet in the library is translucent over a blurred backdrop,
|
|
64
|
+
* because it is a thing sitting on the page. A skeleton is the opposite: it is
|
|
65
|
+
* the shape of something that is not there yet, so it is a flat tint and nothing
|
|
66
|
+
* else — no blur, no hairline, no gloss, no shadow. It also keeps a page of
|
|
67
|
+
* thirty placeholders from asking for thirty backdrop filters.
|
|
68
|
+
*/
|
|
69
|
+
const fillClasses = 'relative overflow-hidden bg-(--p-soft-hover)';
|
|
70
|
+
/** Pixels for a bare number, and whatever was written for a string. */
|
|
71
|
+
function length(value) {
|
|
72
|
+
if (value === undefined) {
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
return typeof value === 'number' ? `${value}px` : value;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* The shape of something that has not loaded yet.
|
|
79
|
+
*
|
|
80
|
+
* It reserves the space the real thing will take, which is the whole job: a card
|
|
81
|
+
* that grows by 200px when its image arrives has moved everything below it while
|
|
82
|
+
* somebody was reading. A spinner cannot do that.
|
|
83
|
+
*
|
|
84
|
+
* The three shapes are the three things a layout is made of — a run of text, a
|
|
85
|
+
* block and a circle — and each is sized off the ladder the real component uses,
|
|
86
|
+
* so a `md` line is as tall as `md` type and a `md` circle is exactly a
|
|
87
|
+
* `PlAvatar` at `md`.
|
|
88
|
+
*/
|
|
89
|
+
export const PlSkeleton = /* @__PURE__ */ React.forwardRef(function PlSkeleton({ shape = 'line', lines = 1, size = 'md', color = 'secondary', width, height, animated = true, label, render, className, style, ...props }, ref) {
|
|
90
|
+
// The sweep lives in `styles.css` rather than in an arbitrary variant for the
|
|
91
|
+
// reason `.plass-glow` does: a keyframe is not a Tailwind variant, so there is
|
|
92
|
+
// nothing to express one with.
|
|
93
|
+
const sweep = animated ? 'plass-skeleton' : '';
|
|
94
|
+
const shapeClasses = shape === 'circle'
|
|
95
|
+
? `shrink-0 rounded-full ${controlHeightClasses[size]} ${controlSquareClasses[size]}`
|
|
96
|
+
: shape === 'rect'
|
|
97
|
+
? `w-full ${blockRadiusClasses[size]} ${height === undefined ? blockHeightClasses[size] : ''}`
|
|
98
|
+
: `w-full ${barRadiusClasses[size]} ${lineHeightClasses[size]}`;
|
|
99
|
+
// Unlabelled it is scenery and says nothing; labelled it is the one element
|
|
100
|
+
// that reports the wait for the region around it.
|
|
101
|
+
const announce = label
|
|
102
|
+
? { role: 'status', 'aria-busy': true, 'aria-label': label }
|
|
103
|
+
: { 'aria-hidden': true };
|
|
104
|
+
// A run of lines is a stack of bars rather than one box, so the gaps between
|
|
105
|
+
// them are real gaps: text has leading, and a striped gradient would not
|
|
106
|
+
// survive a caller putting the block in a flex row. The root then holds only
|
|
107
|
+
// the stacking, which is why it drops the fill and the sweep.
|
|
108
|
+
const stacked = shape === 'line' && lines > 1;
|
|
109
|
+
return useRender({
|
|
110
|
+
render,
|
|
111
|
+
ref,
|
|
112
|
+
props: {
|
|
113
|
+
className: (stacked
|
|
114
|
+
? ['flex w-full flex-col', lineGapClasses[size], className ?? '']
|
|
115
|
+
: [fillClasses, sweep, shapeClasses, className ?? ''])
|
|
116
|
+
.filter(Boolean)
|
|
117
|
+
.join(' '),
|
|
118
|
+
style: {
|
|
119
|
+
...surfaceSlots(color, 0),
|
|
120
|
+
width: length(width),
|
|
121
|
+
height: length(height),
|
|
122
|
+
...style
|
|
123
|
+
},
|
|
124
|
+
...announce,
|
|
125
|
+
...(stacked
|
|
126
|
+
? {
|
|
127
|
+
children: Array.from({ length: lines }, (_, index) => (_jsx("div", { className: [
|
|
128
|
+
fillClasses,
|
|
129
|
+
sweep,
|
|
130
|
+
barRadiusClasses[size],
|
|
131
|
+
lineHeightClasses[size],
|
|
132
|
+
// The last line of a paragraph does not reach the margin.
|
|
133
|
+
index === lines - 1 ? 'w-3/5' : 'w-full'
|
|
134
|
+
]
|
|
135
|
+
.filter(Boolean)
|
|
136
|
+
.join(' ') }, index)))
|
|
137
|
+
}
|
|
138
|
+
: null),
|
|
139
|
+
...props
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PlSkeleton } from './PlSkeleton.js';
|