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,65 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Collapsible as BaseUICollapsible } from '@base-ui/react/collapsible';
|
|
4
|
+
import { ChevronIcon } from '../../internal/icons.js';
|
|
5
|
+
import { cx, focusRingInsetClasses, gapClasses, hasContent, iconClasses, metaTextClasses, radiusClasses, sheetBodyClasses, sheetHeaderGapClasses, sheetPaddingXClasses, sheetPaddingYClasses, sheetRestClasses, sheetTitleClasses, surfaceSlots, transitionClasses } from '../../internal/styles.js';
|
|
6
|
+
/**
|
|
7
|
+
* The space between the header and the body it opened.
|
|
8
|
+
*
|
|
9
|
+
* The header's own padding does not pay for it, which is the correction
|
|
10
|
+
* `PlAccordion` already carries: an open header is a tinted band with its own
|
|
11
|
+
* bottom edge, the body begins at that edge, and its first line lands against
|
|
12
|
+
* it with only half a leading in between — so the title and the paragraph
|
|
13
|
+
* explaining it read as one run of text broken by a colour change.
|
|
14
|
+
*/
|
|
15
|
+
const panelPaddingTopClasses = {
|
|
16
|
+
default: { xs: 'pt-1.5', sm: 'pt-2', md: 'pt-3', lg: 'pt-3.5', xl: 'pt-4' },
|
|
17
|
+
compact: { xs: 'pt-1', sm: 'pt-1.5', md: 'pt-2', lg: 'pt-2.5', xl: 'pt-3' }
|
|
18
|
+
};
|
|
19
|
+
/** And the space under it, on the same two tracks. */
|
|
20
|
+
const panelPaddingBottomClasses = {
|
|
21
|
+
default: { xs: 'pb-2.5', sm: 'pb-3', md: 'pb-5', lg: 'pb-6', xl: 'pb-7' },
|
|
22
|
+
compact: { xs: 'pb-2', sm: 'pb-2.5', md: 'pb-3.5', lg: 'pb-4', xl: 'pb-5' }
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* One section that folds, standing on its own.
|
|
26
|
+
*
|
|
27
|
+
* A `PlAccordion` is a *set* of these and owns which one of them is open; this
|
|
28
|
+
* is the same fold with nothing else beside it, so what it needs is an `open` of
|
|
29
|
+
* its own rather than a place in somebody's list. Reach for it for a "Show more"
|
|
30
|
+
* on a form, an optional block of settings, the details under a row.
|
|
31
|
+
*
|
|
32
|
+
* Base UI owns the parts that are genuinely hard: the `button` / panel pairing
|
|
33
|
+
* and the `aria-controls` / `aria-expanded` wiring between them,
|
|
34
|
+
* `hidden="until-found"`, and measuring the panel so it has a height to animate
|
|
35
|
+
* from.
|
|
36
|
+
*
|
|
37
|
+
* The panel's height *is* animated, which looks like an exception to the rule
|
|
38
|
+
* against moving things and is not: nothing is transformed, no text is
|
|
39
|
+
* resampled, and the content does not shift relative to the panel it is in — the
|
|
40
|
+
* panel is a window opening onto it. Content that appears instantly is a page
|
|
41
|
+
* that jumps, which is the failure the rule exists to prevent.
|
|
42
|
+
*/
|
|
43
|
+
export const PlCollapsible = /* @__PURE__ */ React.forwardRef(function PlCollapsible({ variant = 'glass', size = 'md', color = 'primary', density = 'default', elevation = 0, open, defaultOpen = false, onOpenChange, title, subtitle, startIcon, action, trigger, indicator = true, disabled = false, padded = true, hiddenUntilFound = false, keepMounted = false, className, style, children, ...props }, ref) {
|
|
44
|
+
const padX = sheetPaddingXClasses[density][size];
|
|
45
|
+
const padY = sheetPaddingYClasses[density][size];
|
|
46
|
+
return (_jsxs(BaseUICollapsible.Root, { ref: ref, open: open, defaultOpen: defaultOpen, onOpenChange: (next) => onOpenChange?.(next), disabled: disabled, className: cx(
|
|
47
|
+
// `overflow-hidden` is what makes the panel a window rather than
|
|
48
|
+
// something that spills past the sheet's own corners while it moves.
|
|
49
|
+
'flex flex-col overflow-hidden', radiusClasses[size], sheetRestClasses[variant], transitionClasses, className), style: { ...surfaceSlots(color, elevation), ...style }, ...props, children: [trigger ? (_jsx(BaseUICollapsible.Trigger, { render: trigger })) : (_jsxs("div", { className: "flex w-full items-center", children: [_jsxs(BaseUICollapsible.Trigger, { className: cx('flex min-w-0 flex-1 cursor-pointer items-center text-start', padX, padY, gapClasses[size], transitionClasses, iconClasses,
|
|
50
|
+
// Inset rather than offset. The sheet clips its children so the
|
|
51
|
+
// panel can be a window, and `overflow: hidden` clips a
|
|
52
|
+
// descendant's outline along with everything else — an offset
|
|
53
|
+
// ring on a trigger that fills the top of the sheet would be
|
|
54
|
+
// shaved off on three sides.
|
|
55
|
+
focusRingInsetClasses, 'hover:bg-(--p-soft)', 'data-[panel-open]:bg-(--p-soft) data-[panel-open]:text-(--p-accent)', 'disabled:cursor-not-allowed disabled:bg-transparent disabled:opacity-50'), children: [hasContent(startIcon) ? (_jsx("span", { className: "flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)", children: startIcon })) : null, _jsxs("span", { className: cx('flex min-w-0 flex-1 flex-col', sheetHeaderGapClasses[size]), children: [hasContent(title) ? (_jsx("span", { className: cx('plass-title truncate font-semibold', sheetTitleClasses[size]), children: title })) : null, hasContent(subtitle) ? (_jsx("span", { className: cx('truncate text-(--plass-muted-fg)', metaTextClasses[size]), children: subtitle })) : null] }), indicator ? (_jsx("span", { className: cx('flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)', '[transition:rotate_var(--plass-duration)_var(--plass-ease)]', 'data-[panel-open]:rotate-180'), children: _jsx(ChevronIcon, {}) })) : null] }), hasContent(action) ? (_jsx("span", { className: cx('flex shrink-0 items-center', padX), children: action })) : null] })), _jsx(BaseUICollapsible.Panel, { hiddenUntilFound: hiddenUntilFound, keepMounted: keepMounted, className: cx('h-(--collapsible-panel-height) overflow-hidden', '[transition:height_var(--plass-duration-slow)_var(--plass-ease)]', 'data-[starting-style]:h-0 data-[ending-style]:h-0'), children: _jsx("div", { className: cx('min-w-0 text-(--plass-muted-fg)', sheetBodyClasses[size], padded ? padX : '',
|
|
56
|
+
// The default header already paid for the space above, so the
|
|
57
|
+
// body only owes what goes under it — otherwise a closed
|
|
58
|
+
// collapsible would look padded. A caller's own `trigger` has paid
|
|
59
|
+
// for nothing, so there the panel owes both.
|
|
60
|
+
padded
|
|
61
|
+
? trigger
|
|
62
|
+
? `${panelPaddingTopClasses[density][size]} ${panelPaddingBottomClasses[density][size]}`
|
|
63
|
+
: panelPaddingBottomClasses[density][size]
|
|
64
|
+
: ''), children: children }) })] }));
|
|
65
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PlCollapsible } from './PlCollapsible.js';
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PlassElevation, PlassStyleProps } from '../../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* What a combobox's value may be — the same two types a PlSelect submits, and
|
|
5
|
+
* for the same reason: a form control's value is what a form sends, and every
|
|
6
|
+
* escape from that buys flexibility by making the common case harder to write.
|
|
7
|
+
*
|
|
8
|
+
* A value the list does not contain is a `string`: it is what the user typed.
|
|
9
|
+
*/
|
|
10
|
+
export type PlComboboxValue = string | number;
|
|
11
|
+
export interface PlComboboxOption {
|
|
12
|
+
/** Submitted, and what `value` / `onValueChange` speak in. */
|
|
13
|
+
value: PlComboboxValue;
|
|
14
|
+
/**
|
|
15
|
+
* Shown in the list, in the input and on the chip. Defaults to the value.
|
|
16
|
+
*
|
|
17
|
+
* A `string` rather than a `ReactNode`, which is the one place this differs
|
|
18
|
+
* from PlSelect: the label is typed against by the filter and written into a
|
|
19
|
+
* text input, and neither of those can be done to an element.
|
|
20
|
+
*/
|
|
21
|
+
label?: string;
|
|
22
|
+
/** Unavailable, but still listed — the option exists, it just cannot be picked. */
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
}
|
|
25
|
+
/** One value, or an array of them, depending on `multiple`. */
|
|
26
|
+
type Selection<Multiple extends boolean | undefined> = Multiple extends true ? PlComboboxValue[] : PlComboboxValue | null;
|
|
27
|
+
export interface PlComboboxProps<Multiple extends boolean | undefined = false> extends PlassStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'defaultValue' | 'children'> {
|
|
28
|
+
/**
|
|
29
|
+
* The options, as data — the same shape PlSelect takes, and for the same
|
|
30
|
+
* reason: what a caller has is almost always an array already.
|
|
31
|
+
*/
|
|
32
|
+
items: readonly PlComboboxOption[];
|
|
33
|
+
/**
|
|
34
|
+
* Whether more than one value may be held. The chosen ones become chips
|
|
35
|
+
* inside the field, and the input goes on filtering after each.
|
|
36
|
+
* @default false
|
|
37
|
+
*/
|
|
38
|
+
multiple?: Multiple;
|
|
39
|
+
/** The chosen value. Use with `onValueChange` for a controlled combobox. */
|
|
40
|
+
value?: Selection<Multiple> | null;
|
|
41
|
+
/** The initially chosen value, for an uncontrolled combobox. */
|
|
42
|
+
defaultValue?: Selection<Multiple> | null;
|
|
43
|
+
onValueChange?: (value: Selection<Multiple>) => void;
|
|
44
|
+
/** Called as the text in the input changes — the filter query, not the value. */
|
|
45
|
+
onInputValueChange?: (inputValue: string) => void;
|
|
46
|
+
/**
|
|
47
|
+
* Whether a value the list does not contain may be committed.
|
|
48
|
+
*
|
|
49
|
+
* On by default, and it is what separates this from a searchable PlSelect: the
|
|
50
|
+
* typed text is offered as its own row at the end of the list, so committing
|
|
51
|
+
* it is a choice the user makes rather than something that happens to them on
|
|
52
|
+
* blur. Turn it off for a field whose values are a closed set.
|
|
53
|
+
* @default true
|
|
54
|
+
*/
|
|
55
|
+
allowCustom?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* What that row says. Receives the trimmed query.
|
|
58
|
+
* @default (query) => `Add “${query}”`
|
|
59
|
+
*/
|
|
60
|
+
customLabel?: (query: string) => React.ReactNode;
|
|
61
|
+
/**
|
|
62
|
+
* Shows a × that empties the field. Off by default — a field that can be
|
|
63
|
+
* cleared in one click is a field that can be emptied by accident.
|
|
64
|
+
* @default false
|
|
65
|
+
*/
|
|
66
|
+
clearable?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Shown in the popup when nothing matched and no value may be added.
|
|
69
|
+
* @default 'No matches'
|
|
70
|
+
*/
|
|
71
|
+
emptyMessage?: React.ReactNode;
|
|
72
|
+
/** The most rows the list will show at once. `-1` is all of them. @default -1 */
|
|
73
|
+
limit?: number;
|
|
74
|
+
/** Shown in the input while nothing is typed. */
|
|
75
|
+
placeholder?: string;
|
|
76
|
+
/**
|
|
77
|
+
* Drop shadow depth of the *field*. `0`, like a PlTextField: a field is cut
|
|
78
|
+
* into the sheet rather than resting on it. The popup has its own, fixed at
|
|
79
|
+
* `3` — it genuinely floats above the page.
|
|
80
|
+
* @default 0
|
|
81
|
+
*/
|
|
82
|
+
elevation?: PlassElevation;
|
|
83
|
+
/** Label above the field, wired to it by Base UI's Field. */
|
|
84
|
+
label?: React.ReactNode;
|
|
85
|
+
/** Helper text below the field. */
|
|
86
|
+
description?: React.ReactNode;
|
|
87
|
+
/** Error message below. Its presence also turns the combobox invalid. */
|
|
88
|
+
error?: React.ReactNode;
|
|
89
|
+
/** Forces the invalid state without a message. Defaults to whether `error` has content. */
|
|
90
|
+
invalid?: boolean;
|
|
91
|
+
/** Content placed before the input. Sized in `em`, so it tracks the text. */
|
|
92
|
+
startIcon?: React.ReactNode;
|
|
93
|
+
/** Stretches to the width of the container. */
|
|
94
|
+
fullWidth?: boolean;
|
|
95
|
+
/** Unavailable. */
|
|
96
|
+
disabled?: boolean;
|
|
97
|
+
/** The value is shown but cannot be changed. */
|
|
98
|
+
readOnly?: boolean;
|
|
99
|
+
/** Whether a value must be chosen before the form is submitted. */
|
|
100
|
+
required?: boolean;
|
|
101
|
+
/** Identifies the field when a form is submitted. */
|
|
102
|
+
name?: string;
|
|
103
|
+
/** The popup is open. Use with `onOpenChange` for a controlled popup. */
|
|
104
|
+
open?: boolean;
|
|
105
|
+
/** Whether the popup starts open. */
|
|
106
|
+
defaultOpen?: boolean;
|
|
107
|
+
onOpenChange?: (open: boolean) => void;
|
|
108
|
+
/** Accessible name of the button that opens the list. @default 'Open' */
|
|
109
|
+
openLabel?: string;
|
|
110
|
+
/** Accessible name of the clear button. @default 'Clear' */
|
|
111
|
+
clearLabel?: string;
|
|
112
|
+
/**
|
|
113
|
+
* Accessible name of a chip's remove button. Receives the chip's label.
|
|
114
|
+
* @default (label) => `Remove ${label}`
|
|
115
|
+
*/
|
|
116
|
+
removeLabel?: (label: string) => string;
|
|
117
|
+
/** A ref to the text input the user types into. */
|
|
118
|
+
inputRef?: React.Ref<HTMLInputElement>;
|
|
119
|
+
id?: string;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* A field you can type into and also choose from.
|
|
123
|
+
*
|
|
124
|
+
* The shell is a PlTextField's wearing a chevron, exactly as PlSelect's trigger
|
|
125
|
+
* is — the three have to be indistinguishable in a form, or the form looks
|
|
126
|
+
* assembled rather than designed. What is different is what the text does: it
|
|
127
|
+
* filters the list, and — unless `allowCustom` is off — it can become the value
|
|
128
|
+
* itself, offered as the last row rather than committed silently on blur.
|
|
129
|
+
*
|
|
130
|
+
* With `multiple` the chosen values become PlChips inside the field and the
|
|
131
|
+
* input goes on filtering after each one, so a set of tags is built without the
|
|
132
|
+
* field ever closing.
|
|
133
|
+
*
|
|
134
|
+
* Base UI owns everything hard about this: the filtering and its collator, the
|
|
135
|
+
* popup's positioning and flipping, the `combobox`/`listbox` wiring, arrow-key
|
|
136
|
+
* navigation across both the list and the chips, and the hidden input that makes
|
|
137
|
+
* the whole thing submit with a form.
|
|
138
|
+
*/
|
|
139
|
+
export declare function PlCombobox<Multiple extends boolean | undefined = false>({ variant, size, color, density, elevation, items, multiple, value, defaultValue, onValueChange, onInputValueChange, allowCustom, customLabel, clearable, emptyMessage, limit, placeholder, label, description, error, invalid, startIcon, fullWidth, disabled, readOnly, required, name, open, defaultOpen, onOpenChange, openLabel, clearLabel, removeLabel, inputRef, id, className, style, ...props }: PlComboboxProps<Multiple>): React.JSX.Element;
|
|
140
|
+
export {};
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Combobox as BaseUICombobox } from '@base-ui/react/combobox';
|
|
4
|
+
import { Field } from '@base-ui/react/field';
|
|
5
|
+
import { PlChip } from '../chip/PlChip.js';
|
|
6
|
+
import { CheckIcon, ChevronIcon, CloseIcon, PlusIcon } from '../../internal/icons.js';
|
|
7
|
+
import { chipRemoveClasses, controlHeightClasses, controlTextLeadingClasses, cx, disabledClasses, fieldReadOnlyClasses, fieldRestClasses, focusWithinRingClasses, gapClasses, glassClasses, hasContent, iconClasses, metaTextClasses, paddingXClasses, radiusClasses, stackGapClasses, surfaceSlots, transitionClasses } from '../../internal/styles.js';
|
|
8
|
+
/** The field, and it is a PlTextField's shell to the pixel. */
|
|
9
|
+
const shellBaseClasses = /* @__PURE__ */ [
|
|
10
|
+
'group relative flex w-full cursor-text items-center',
|
|
11
|
+
'[-webkit-tap-highlight-color:transparent] [touch-action:manipulation]',
|
|
12
|
+
transitionClasses,
|
|
13
|
+
focusWithinRingClasses,
|
|
14
|
+
iconClasses
|
|
15
|
+
].join(' ');
|
|
16
|
+
/**
|
|
17
|
+
* With chips in it the field cannot have a fixed height — the chips wrap. The
|
|
18
|
+
* padding is `(control height − chip height) / 2` instead, which makes a one-row
|
|
19
|
+
* combobox exactly as tall as the field beside it, and `min-h-*` catches the
|
|
20
|
+
* variant that carries no border.
|
|
21
|
+
*
|
|
22
|
+
* Keyed by `size` and never by `density`: density is horizontal padding only.
|
|
23
|
+
*/
|
|
24
|
+
const chipsInsetClasses = {
|
|
25
|
+
xs: 'min-h-6 py-0',
|
|
26
|
+
sm: 'min-h-8 py-0.5',
|
|
27
|
+
md: 'min-h-10 py-1',
|
|
28
|
+
lg: 'min-h-12 py-1.5',
|
|
29
|
+
xl: 'min-h-14 py-2'
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* The popup is one of the few surfaces in the library that is *supposed* to
|
|
33
|
+
* float, so unlike everything else it carries a shadow by default — at level 3.
|
|
34
|
+
* Identical to PlSelect's, because a combobox's list and a select's list are the
|
|
35
|
+
* same list.
|
|
36
|
+
*
|
|
37
|
+
* Every `--p-*` it reads is set on the popup itself rather than inherited from
|
|
38
|
+
* the Field around it. A portalled popup renders at the end of `<body>`, so it
|
|
39
|
+
* is outside the element the slots were declared on, and a `var()` with nothing
|
|
40
|
+
* to resolve to is not a fallback — `border-color` collapses to `currentColor`
|
|
41
|
+
* and `background-color` to transparent.
|
|
42
|
+
*/
|
|
43
|
+
const popupClasses = /* @__PURE__ */ [
|
|
44
|
+
glassClasses,
|
|
45
|
+
'max-h-[min(20rem,var(--available-height))] overflow-y-auto overscroll-contain',
|
|
46
|
+
'w-[var(--anchor-width)] border bg-(--plass-glass-press) p-1',
|
|
47
|
+
'[border-color:var(--plass-glass-line)]',
|
|
48
|
+
'[box-shadow:var(--plass-shadow-3),var(--plass-gloss-glass)]',
|
|
49
|
+
'[outline:none]'
|
|
50
|
+
].join(' ');
|
|
51
|
+
const itemClasses = /* @__PURE__ */ [
|
|
52
|
+
'relative flex cursor-pointer items-center gap-2 select-none',
|
|
53
|
+
'rounded-(--plass-radius-xs) py-1.5 pe-2 ps-7',
|
|
54
|
+
transitionClasses,
|
|
55
|
+
// `data-highlighted` rather than `:hover`: it is also what the arrow keys
|
|
56
|
+
// move, so the mouse and the keyboard light the same row.
|
|
57
|
+
'data-[highlighted]:bg-(--p-soft-hover) data-[highlighted]:text-(--p-accent)',
|
|
58
|
+
'data-[selected]:font-semibold data-[selected]:text-(--p-accent)',
|
|
59
|
+
'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50',
|
|
60
|
+
'[outline:none]'
|
|
61
|
+
].join(' ');
|
|
62
|
+
/** The chevron and the ×, which sit in the field rather than in the list. */
|
|
63
|
+
const adornmentClasses = /* @__PURE__ */ [
|
|
64
|
+
'inline-flex h-[1lh] shrink-0 cursor-pointer items-center justify-center',
|
|
65
|
+
'rounded-(--plass-radius-xs) text-(--plass-muted-fg)',
|
|
66
|
+
'[transition:color_var(--plass-duration)_var(--plass-ease)]',
|
|
67
|
+
'hover:text-(--p-accent)',
|
|
68
|
+
'focus-visible:[outline:2px_solid_var(--p-ring)] focus-visible:[outline-offset:1px]',
|
|
69
|
+
'disabled:cursor-not-allowed disabled:opacity-50'
|
|
70
|
+
].join(' ');
|
|
71
|
+
/** Always an array inside, however the caller spells it. */
|
|
72
|
+
function toArray(value) {
|
|
73
|
+
if (value === null || value === undefined) {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
return Array.isArray(value) ? value.slice() : [value];
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* A field you can type into and also choose from.
|
|
80
|
+
*
|
|
81
|
+
* The shell is a PlTextField's wearing a chevron, exactly as PlSelect's trigger
|
|
82
|
+
* is — the three have to be indistinguishable in a form, or the form looks
|
|
83
|
+
* assembled rather than designed. What is different is what the text does: it
|
|
84
|
+
* filters the list, and — unless `allowCustom` is off — it can become the value
|
|
85
|
+
* itself, offered as the last row rather than committed silently on blur.
|
|
86
|
+
*
|
|
87
|
+
* With `multiple` the chosen values become PlChips inside the field and the
|
|
88
|
+
* input goes on filtering after each one, so a set of tags is built without the
|
|
89
|
+
* field ever closing.
|
|
90
|
+
*
|
|
91
|
+
* Base UI owns everything hard about this: the filtering and its collator, the
|
|
92
|
+
* popup's positioning and flipping, the `combobox`/`listbox` wiring, arrow-key
|
|
93
|
+
* navigation across both the list and the chips, and the hidden input that makes
|
|
94
|
+
* the whole thing submit with a form.
|
|
95
|
+
*/
|
|
96
|
+
export function PlCombobox({ variant = 'glass', size = 'md', color = 'primary', density = 'default', elevation = 0, items, multiple, value, defaultValue, onValueChange, onInputValueChange, allowCustom = true, customLabel, clearable = false, emptyMessage = 'No matches', limit, placeholder, label, description, error, invalid, startIcon, fullWidth = false, disabled = false, readOnly = false, required = false, name, open, defaultOpen, onOpenChange, openLabel = 'Open', clearLabel = 'Clear', removeLabel = (chip) => `Remove ${chip}`, inputRef, id, className, style, ...props }) {
|
|
97
|
+
const hasError = hasContent(error);
|
|
98
|
+
const isInvalid = invalid ?? hasError;
|
|
99
|
+
// Invalid re-points the whole slot family at `danger`, so the edge, the ring,
|
|
100
|
+
// the caret and the message all turn over together.
|
|
101
|
+
const family = isInvalid ? 'danger' : color;
|
|
102
|
+
const isMultiple = multiple === true;
|
|
103
|
+
const options = React.useMemo(() => items.map((item) => ({
|
|
104
|
+
value: item.value,
|
|
105
|
+
label: item.label ?? String(item.value),
|
|
106
|
+
disabled: item.disabled
|
|
107
|
+
})), [items]);
|
|
108
|
+
// The selection is mirrored internally even when the caller controls it. The
|
|
109
|
+
// "add this" row has to know what has already been chosen — otherwise a tag
|
|
110
|
+
// that was just added goes on being offered — and in uncontrolled mode there
|
|
111
|
+
// is nowhere else that knowledge lives.
|
|
112
|
+
const [ownSelection, setOwnSelection] = React.useState(() => toArray(defaultValue));
|
|
113
|
+
const selection = value === undefined ? ownSelection : toArray(value);
|
|
114
|
+
const [query, setQuery] = React.useState('');
|
|
115
|
+
/* A map rather than a `find`: this is called once per chosen item, and a
|
|
116
|
+
multi-select with a hundred options and twenty chips in it would otherwise
|
|
117
|
+
walk the list twenty times on every render. */
|
|
118
|
+
const byValue = React.useMemo(() => new Map(options.map((option) => [option.value, option])), [options]);
|
|
119
|
+
const entryFor = React.useCallback((item) => byValue.get(item) ?? { value: item, label: String(item), custom: true }, [byValue]);
|
|
120
|
+
// The row that offers what was typed. It is a real item rather than a special
|
|
121
|
+
// case in the keyboard handling, so Enter, a click and the arrow keys all
|
|
122
|
+
// reach it the same way every other row is reached — and Base UI's own filter
|
|
123
|
+
// keeps it visible, because its label *is* the query.
|
|
124
|
+
const trimmed = query.trim();
|
|
125
|
+
const folded = trimmed.toLocaleLowerCase();
|
|
126
|
+
const alreadyKnown = trimmed === '' ||
|
|
127
|
+
options.some((option) => option.label.toLocaleLowerCase() === folded ||
|
|
128
|
+
String(option.value).toLocaleLowerCase() === folded) ||
|
|
129
|
+
selection.some((item) => String(item).toLocaleLowerCase() === folded);
|
|
130
|
+
const customValue = allowCustom && !readOnly && !disabled && !alreadyKnown ? trimmed : null;
|
|
131
|
+
const listItems = React.useMemo(() => customValue === null
|
|
132
|
+
? options
|
|
133
|
+
: [...options, { value: customValue, label: customValue, custom: true }], [options, customValue]);
|
|
134
|
+
const baseValue = isMultiple
|
|
135
|
+
? selection.map(entryFor)
|
|
136
|
+
: selection.length > 0
|
|
137
|
+
? entryFor(selection[0])
|
|
138
|
+
: null;
|
|
139
|
+
function commit(next) {
|
|
140
|
+
if (value === undefined) {
|
|
141
|
+
setOwnSelection(next);
|
|
142
|
+
}
|
|
143
|
+
onValueChange?.((isMultiple ? next : (next[0] ?? null)));
|
|
144
|
+
}
|
|
145
|
+
const shellClasses = cx(shellBaseClasses, controlTextLeadingClasses[size], radiusClasses[size], gapClasses[size], isMultiple ? chipsInsetClasses[size] : controlHeightClasses[size],
|
|
146
|
+
// The chevron brings its own hit area; stacking the field's padding on top
|
|
147
|
+
// of it would leave the glyph floating in the middle of a gap.
|
|
148
|
+
`${paddingXClasses[density][size]} pe-1.5`,
|
|
149
|
+
// An if/else rather than stacked variants: two Tailwind classes of equal
|
|
150
|
+
// specificity resolve by their order in the generated stylesheet.
|
|
151
|
+
disabled
|
|
152
|
+
? disabledClasses[variant]
|
|
153
|
+
: readOnly
|
|
154
|
+
? fieldReadOnlyClasses[variant]
|
|
155
|
+
: fieldRestClasses[variant]);
|
|
156
|
+
const inputClasses = /* @__PURE__ */ [
|
|
157
|
+
// `self-stretch` and no height of its own, in both modes. An input centres
|
|
158
|
+
// its own text in its box, so letting the box be the full height of the row
|
|
159
|
+
// it sits on — the field in single mode, the chip line in multiple — is what
|
|
160
|
+
// puts the placeholder on the same baseline as the chips beside it.
|
|
161
|
+
'min-w-0 flex-1 self-stretch bg-transparent [font:inherit] text-inherit',
|
|
162
|
+
// Not `outline-none`: that utility zeroes `--tw-outline-style`, and the
|
|
163
|
+
// shell's focus ring is drawn from the same variable family.
|
|
164
|
+
'[outline:none]',
|
|
165
|
+
'placeholder:text-(--plass-muted-fg)',
|
|
166
|
+
'caret-(--p-accent) selection:bg-(--p-soft-press)',
|
|
167
|
+
'disabled:cursor-not-allowed'
|
|
168
|
+
].join(' ');
|
|
169
|
+
/**
|
|
170
|
+
* `afterChips` is the space between the last chip and where typing starts.
|
|
171
|
+
*
|
|
172
|
+
* The row's own `gap-1` is the distance between two chips, which is right
|
|
173
|
+
* between two things of the same kind and too little between a chip and a
|
|
174
|
+
* caret — the query reads as another chip's label rather than as the field's
|
|
175
|
+
* own text. It is only added when there is a chip to be clear of, so an empty
|
|
176
|
+
* multi-select lines its placeholder up with every other field in the form.
|
|
177
|
+
*/
|
|
178
|
+
const renderInput = (afterChips) => (_jsx(BaseUICombobox.Input, { ref: inputRef, placeholder: placeholder, className: cx(inputClasses, isMultiple && 'min-w-16', isMultiple && afterChips && 'ms-1.5') }));
|
|
179
|
+
return (_jsxs(Field.Root, { disabled: disabled, invalid: isInvalid, className: cx('flex-col align-top', stackGapClasses[size], fullWidth ? 'flex w-full' : 'inline-flex', className), style: { ...surfaceSlots(family, elevation), ...style }, ...props, children: [label ? (_jsx(Field.Label, { className: cx(metaTextClasses[size], 'font-semibold', disabled ? 'text-(--plass-muted-fg)' : 'text-(--plass-fg)'), children: label })) : null, _jsxs(BaseUICombobox.Root, { id: id, name: name, items: listItems, multiple: isMultiple, value: baseValue, onValueChange: (next) => {
|
|
180
|
+
const chosen = next === null ? [] : Array.isArray(next) ? next : [next];
|
|
181
|
+
commit(chosen.map((entry) => entry.value));
|
|
182
|
+
},
|
|
183
|
+
// The text is Base UI's to own, not ours: in single mode it is the
|
|
184
|
+
// chosen option's label, which has to be there from the first paint, and
|
|
185
|
+
// in multiple mode it empties itself after each pick. What is kept here
|
|
186
|
+
// is a copy, and only so the "add this" row knows what was typed.
|
|
187
|
+
onInputValueChange: (next) => {
|
|
188
|
+
setQuery(next);
|
|
189
|
+
onInputValueChange?.(next);
|
|
190
|
+
}, open: open, defaultOpen: defaultOpen, onOpenChange: (next) => onOpenChange?.(next),
|
|
191
|
+
// The first match lights up as you type, so Enter commits without an
|
|
192
|
+
// arrow key first. This is what makes the "add this" row reachable from
|
|
193
|
+
// the keyboard at all: a value the list does not have is the only match
|
|
194
|
+
// there is, so it is the one Enter lands on.
|
|
195
|
+
autoHighlight: true, itemToStringLabel: (entry) => entry.label, itemToStringValue: (entry) => String(entry.value), isItemEqualToValue: (a, b) => a.value === b.value, limit: limit, disabled: disabled, readOnly: readOnly, required: required, children: [_jsxs(BaseUICombobox.InputGroup, { className: shellClasses, children: [startIcon ? (_jsx("span", { className: "flex h-[1lh] shrink-0 items-center text-(--plass-muted-fg)", children: startIcon })) : null, isMultiple ? (_jsx(BaseUICombobox.Chips, { className: "flex min-w-0 flex-1 flex-wrap items-center gap-1", children: _jsx(BaseUICombobox.Value, { children: (chosen) => (_jsxs(React.Fragment, { children: [chosen.map((entry) => (_jsx(BaseUICombobox.Chip, { render: _jsx(PlChip, { variant: "glass", size: size, color: family, density: "compact", disabled: disabled, endIcon: readOnly || disabled ? null : (_jsx(BaseUICombobox.ChipRemove, { "aria-label": removeLabel(entry.label), className: chipRemoveClasses, children: _jsx(CloseIcon, {}) })) }), children: entry.label }, String(entry.value)))), renderInput(chosen.length > 0)] })) }) })) : (renderInput(false)), clearable && !readOnly ? (_jsx(BaseUICombobox.Clear, { "aria-label": clearLabel, className: adornmentClasses, children: _jsx(CloseIcon, {}) })) : null, _jsx(BaseUICombobox.Trigger, { "aria-label": openLabel, className: adornmentClasses, children: _jsx(BaseUICombobox.Icon, { className: cx(
|
|
196
|
+
// The chevron is the one thing here that may turn: it is a
|
|
197
|
+
// glyph, not a label, and nothing about it resamples.
|
|
198
|
+
'flex items-center', '[transition:rotate_var(--plass-duration)_var(--plass-ease)]', 'data-[popup-open]:rotate-180'), children: _jsx(ChevronIcon, {}) }) })] }), _jsx(BaseUICombobox.Portal, { children: _jsx(BaseUICombobox.Positioner, { className: "plass-portal z-50 [outline:none]", sideOffset: 6, children: _jsxs(BaseUICombobox.Popup, { className: cx(popupClasses, radiusClasses[size], controlTextLeadingClasses[size]), style: surfaceSlots(family, 3), children: [_jsx(BaseUICombobox.Empty, { className: "px-2 py-1.5 text-(--plass-muted-fg) empty:hidden", children: emptyMessage }), _jsx(BaseUICombobox.List, { children: (entry) => (_jsx(BaseUICombobox.Item, { value: entry, disabled: entry.disabled, className: itemClasses, children: entry.custom ? (_jsxs(React.Fragment, { children: [_jsx("span", { className: "absolute start-1.5 flex size-4 items-center justify-center text-(--p-accent) [&_svg]:size-4", children: _jsx(PlusIcon, {}) }), _jsx("span", { className: "truncate", children: customLabel ? customLabel(entry.label) : `Add “${entry.label}”` })] })) : (_jsxs(React.Fragment, { children: [_jsx(BaseUICombobox.ItemIndicator, { className: "absolute start-1.5 flex size-4 items-center justify-center", children: _jsx(CheckIcon, {}) }), _jsx("span", { className: "truncate", children: entry.label })] })) }, `${entry.custom ? 'custom:' : ''}${String(entry.value)}`)) })] }) }) })] }), description ? (_jsx(Field.Description, { className: cx(metaTextClasses[size], 'text-(--plass-muted-fg)'), children: description })) : null, hasError ? (_jsx(Field.Error, { match: true, className: cx(metaTextClasses[size], 'text-(--p-accent)'), children: error })) : null] }));
|
|
199
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PlCombobox } from './PlCombobox.js';
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
3
|
+
import type { PlassDensity, PlassSize } from '../../types.js';
|
|
4
|
+
/**
|
|
5
|
+
* How wide the content is allowed to get.
|
|
6
|
+
*
|
|
7
|
+
* `none` is the extra step and the default, because a `PlContainer`'s job is
|
|
8
|
+
* the gutter — a measure is a second decision, and a page should have to ask
|
|
9
|
+
* for one.
|
|
10
|
+
*/
|
|
11
|
+
export type PlContainerWidth = PlassSize | 'none';
|
|
12
|
+
export interface PlContainerProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
13
|
+
/**
|
|
14
|
+
* How wide the content is allowed to get, on the same ladder the breakpoints
|
|
15
|
+
* use — `xs` 30rem, `sm` 40rem, `md` 48rem, `lg` 64rem, `xl` 80rem.
|
|
16
|
+
* @default 'none'
|
|
17
|
+
*/
|
|
18
|
+
maxWidth?: PlContainerWidth;
|
|
19
|
+
/**
|
|
20
|
+
* The gutter, on the `size`/`density` scale. Turn it off to keep the centring
|
|
21
|
+
* and the measure without the padding.
|
|
22
|
+
* @default true
|
|
23
|
+
*/
|
|
24
|
+
padded?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* The gutter's scale.
|
|
27
|
+
*
|
|
28
|
+
* `size` here is the size of the *sheet* — it never touches a height or the
|
|
29
|
+
* type scale — and it is independent of `maxWidth`, which is how wide the
|
|
30
|
+
* content gets rather than how far it sits from the edge.
|
|
31
|
+
* @default 'md'
|
|
32
|
+
*/
|
|
33
|
+
size?: PlassSize;
|
|
34
|
+
/** @default 'default' */
|
|
35
|
+
density?: PlassDensity;
|
|
36
|
+
/**
|
|
37
|
+
* Centres the content once `maxWidth` is narrower than the page. No effect
|
|
38
|
+
* while `maxWidth` is `none`, because there is nothing left over to centre in.
|
|
39
|
+
* @default true
|
|
40
|
+
*/
|
|
41
|
+
centered?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Renders something other than a `<div>`: `render={<main />}`,
|
|
44
|
+
* `render={<section />}`. Base UI's own escape hatch.
|
|
45
|
+
*/
|
|
46
|
+
render?: useRender.RenderProp;
|
|
47
|
+
children?: React.ReactNode;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Horizontal breathing room, and optionally a measure.
|
|
51
|
+
*
|
|
52
|
+
* It draws nothing — no sheet, no hairline, no shadow — for the same reason
|
|
53
|
+
* `PlAspectRatio` does not. The outermost element on a page is the one thing
|
|
54
|
+
* that must not decide what the page looks like, and a container that carried a
|
|
55
|
+
* `variant` would put a second pane behind every card on it.
|
|
56
|
+
*
|
|
57
|
+
* The two questions it answers are deliberately separate from how the content
|
|
58
|
+
* inside divides itself up: a container holds a `PlGrid` as happily as it holds
|
|
59
|
+
* a single paragraph, and a grid needs no container around it.
|
|
60
|
+
*
|
|
61
|
+
* The gutter is the **sheet** padding track rather than the control one. What
|
|
62
|
+
* sits inside a container is a page, and the margin a page keeps from the edge
|
|
63
|
+
* of a window is the margin a card keeps around a paragraph — not the room a
|
|
64
|
+
* label needs beside the edge of the key it is printed on.
|
|
65
|
+
*/
|
|
66
|
+
export declare const PlContainer: React.ForwardRefExoticComponent<PlContainerProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { useRender } from '@base-ui/react/use-render';
|
|
3
|
+
import { cx, sheetPaddingXClasses } from '../../internal/styles.js';
|
|
4
|
+
/**
|
|
5
|
+
* The measure ladder, in `rem` rather than in Tailwind's named `max-w-*` steps,
|
|
6
|
+
* so that a container's `lg` and an `lg:` utility are the same 64rem.
|
|
7
|
+
*
|
|
8
|
+
* Tailwind's own container scale is a different set of numbers, and having two
|
|
9
|
+
* ladders called `lg` on one page is how a layout drifts by a few pixels for no
|
|
10
|
+
* reason anybody can find later.
|
|
11
|
+
*/
|
|
12
|
+
const maxWidthClasses = {
|
|
13
|
+
xs: 'max-w-[30rem]',
|
|
14
|
+
sm: 'max-w-[40rem]',
|
|
15
|
+
md: 'max-w-[48rem]',
|
|
16
|
+
lg: 'max-w-[64rem]',
|
|
17
|
+
xl: 'max-w-[80rem]'
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Horizontal breathing room, and optionally a measure.
|
|
21
|
+
*
|
|
22
|
+
* It draws nothing — no sheet, no hairline, no shadow — for the same reason
|
|
23
|
+
* `PlAspectRatio` does not. The outermost element on a page is the one thing
|
|
24
|
+
* that must not decide what the page looks like, and a container that carried a
|
|
25
|
+
* `variant` would put a second pane behind every card on it.
|
|
26
|
+
*
|
|
27
|
+
* The two questions it answers are deliberately separate from how the content
|
|
28
|
+
* inside divides itself up: a container holds a `PlGrid` as happily as it holds
|
|
29
|
+
* a single paragraph, and a grid needs no container around it.
|
|
30
|
+
*
|
|
31
|
+
* The gutter is the **sheet** padding track rather than the control one. What
|
|
32
|
+
* sits inside a container is a page, and the margin a page keeps from the edge
|
|
33
|
+
* of a window is the margin a card keeps around a paragraph — not the room a
|
|
34
|
+
* label needs beside the edge of the key it is printed on.
|
|
35
|
+
*/
|
|
36
|
+
export const PlContainer = /* @__PURE__ */ React.forwardRef(function PlContainer({ maxWidth = 'none', padded = true, size = 'md', density = 'default', centered = true, render, className, children, ...props }, ref) {
|
|
37
|
+
const classNames = cx('block w-full', maxWidth === 'none' ? '' : maxWidthClasses[maxWidth], centered ? 'mx-auto' : '', padded ? sheetPaddingXClasses[density][size] : '', className);
|
|
38
|
+
return useRender({
|
|
39
|
+
render,
|
|
40
|
+
ref,
|
|
41
|
+
props: {
|
|
42
|
+
className: classNames,
|
|
43
|
+
children,
|
|
44
|
+
...props
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PlContainer } from './PlContainer.js';
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { type PlassPickerLabels } from '../../internal/calendar.js';
|
|
3
|
+
import { type PlassPickerShellProps } from '../../internal/picker.js';
|
|
4
|
+
import type { PlassWeekday } from '../../types.js';
|
|
5
|
+
/** The strings a picker says that `Intl` has no opinion about. */
|
|
6
|
+
export type PlPickerLabels = PlassPickerLabels;
|
|
7
|
+
export interface PlDatePickerProps extends PlassPickerShellProps {
|
|
8
|
+
/** The chosen day. Use with `onValueChange` for a controlled picker. */
|
|
9
|
+
value?: Date | null;
|
|
10
|
+
/** The day the picker starts on, for an uncontrolled one. */
|
|
11
|
+
defaultValue?: Date | null;
|
|
12
|
+
onValueChange?: (value: Date | null) => void;
|
|
13
|
+
/** Whether the calendar is open. Use with `onOpenChange` to control it. */
|
|
14
|
+
open?: boolean;
|
|
15
|
+
defaultOpen?: boolean;
|
|
16
|
+
onOpenChange?: (open: boolean) => void;
|
|
17
|
+
/** Which month the calendar opens on when there is no value. @default this one */
|
|
18
|
+
defaultMonth?: Date;
|
|
19
|
+
/** The earliest day that may be chosen. Day-granular — the time is ignored. */
|
|
20
|
+
minDate?: Date | null;
|
|
21
|
+
/** The latest day that may be chosen. */
|
|
22
|
+
maxDate?: Date | null;
|
|
23
|
+
/**
|
|
24
|
+
* Blocks individual days that are inside the range but still not available —
|
|
25
|
+
* weekends, holidays, a room that is already booked.
|
|
26
|
+
*/
|
|
27
|
+
shouldDisableDate?: (date: Date) => boolean;
|
|
28
|
+
/**
|
|
29
|
+
* BCP 47 tag deciding the month and weekday names, the order of the header's
|
|
30
|
+
* two buttons, and how the trigger writes the date. Defaults to the browser's.
|
|
31
|
+
*/
|
|
32
|
+
locale?: string;
|
|
33
|
+
/** Which day the week starts on. Defaults to whatever the locale says. */
|
|
34
|
+
weekStartsOn?: PlassWeekday;
|
|
35
|
+
/**
|
|
36
|
+
* How the trigger writes the chosen date. Passed straight to `Intl`, so
|
|
37
|
+
* `{ dateStyle: 'full' }` and `{ year: '2-digit', month: 'narrow' }` both work.
|
|
38
|
+
* @default { dateStyle: 'medium' }
|
|
39
|
+
*/
|
|
40
|
+
format?: Intl.DateTimeFormatOptions;
|
|
41
|
+
/** Shown in the trigger while nothing is chosen. */
|
|
42
|
+
placeholder?: React.ReactNode;
|
|
43
|
+
/** Offers the × that empties the control. @default false */
|
|
44
|
+
clearable?: boolean;
|
|
45
|
+
/** Offers the shortcut to today in the footer. @default true */
|
|
46
|
+
showTodayButton?: boolean;
|
|
47
|
+
/** Closes the popup as soon as a day is chosen. @default true */
|
|
48
|
+
closeOnSelect?: boolean;
|
|
49
|
+
/** The strings the picker says. Every one has an English default. */
|
|
50
|
+
labels?: Partial<PlassPickerLabels>;
|
|
51
|
+
/** Identifies the field when a form is submitted, as `YYYY-MM-DD`. */
|
|
52
|
+
name?: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* One day, chosen from a calendar.
|
|
56
|
+
*
|
|
57
|
+
* The trigger is a `PlTextField`'s shell wearing a calendar glyph, on purpose
|
|
58
|
+
* and for the reason a `PlSelect`'s is: a form where the date field is a
|
|
59
|
+
* different height, radius or material from the fields around it is a form that
|
|
60
|
+
* looks assembled.
|
|
61
|
+
*
|
|
62
|
+
* What the calendar is actually for is the header. A picker that only steps a
|
|
63
|
+
* month at a time puts a birthday thirty years back a hundred and eighty clicks
|
|
64
|
+
* away, so the month name and the year are each a button that opens a grid of
|
|
65
|
+
* its own — twelve months, then twelve years at a time. Any month of the year on
|
|
66
|
+
* screen is two clicks; any year at all is three.
|
|
67
|
+
*
|
|
68
|
+
* There is no typing into the trigger. Parsing a date out of free text is
|
|
69
|
+
* locale-dependent in a way that cannot be done honestly without a date library,
|
|
70
|
+
* and a field that understands `27/7/26` in one browser and not in the next is
|
|
71
|
+
* worse than one that never claimed to.
|
|
72
|
+
*/
|
|
73
|
+
export declare const PlDatePicker: React.ForwardRefExoticComponent<PlDatePickerProps & React.RefAttributes<HTMLButtonElement>>;
|