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,159 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { PlButton } from '../button/PlButton.js';
|
|
4
|
+
import { ChevronIcon } from '../../internal/icons.js';
|
|
5
|
+
import { controlTextClasses, gapClasses, srOnlyClasses } from '../../internal/styles.js';
|
|
6
|
+
function range(start, end) {
|
|
7
|
+
return Array.from({ length: Math.max(0, end - start + 1) }, (_, index) => start + index);
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Which pages the row actually shows.
|
|
11
|
+
*
|
|
12
|
+
* The shape every pagination converges on — a fixed run at each end, a window
|
|
13
|
+
* around the current page, and an ellipsis wherever those leave a gap — with one
|
|
14
|
+
* detail that is easy to get wrong and matters: a gap of exactly one page is
|
|
15
|
+
* filled with that page rather than with an ellipsis. `1 … 3 … 9` hides a single
|
|
16
|
+
* number behind a symbol wider than the number it replaced.
|
|
17
|
+
*
|
|
18
|
+
* The row is also pinned to a constant number of slots, whatever page it is on:
|
|
19
|
+
* the window slides toward whichever end it is near instead of being clipped by
|
|
20
|
+
* it, so page 1 shows `1 2 3 4 5 … 20` and page 10 shows `1 … 9 10 11 … 20`.
|
|
21
|
+
* Which slots are pages and which are ellipses changes; how many there are does
|
|
22
|
+
* not. Without that, stepping from page 1 to page 2 would relayout the row and
|
|
23
|
+
* every button would move out from under the pointer that just pressed one.
|
|
24
|
+
*/
|
|
25
|
+
function paginationRange(count, page, siblingCount, boundaryCount) {
|
|
26
|
+
const startPages = range(1, Math.min(boundaryCount, count));
|
|
27
|
+
const endPages = range(Math.max(count - boundaryCount + 1, boundaryCount + 1), count);
|
|
28
|
+
const siblingsStart = Math.max(Math.min(page - siblingCount, count - boundaryCount - siblingCount * 2 - 1), boundaryCount + 2);
|
|
29
|
+
const siblingsEnd = Math.min(Math.max(page + siblingCount, boundaryCount + siblingCount * 2 + 2), endPages.length > 0 ? endPages[0] - 2 : count - 1);
|
|
30
|
+
return [
|
|
31
|
+
...startPages,
|
|
32
|
+
// An ellipsis when more than one page is hidden, the page itself when
|
|
33
|
+
// exactly one is, and nothing when none is.
|
|
34
|
+
...(siblingsStart > boundaryCount + 2
|
|
35
|
+
? ['start-ellipsis']
|
|
36
|
+
: boundaryCount + 1 < count - boundaryCount
|
|
37
|
+
? [boundaryCount + 1]
|
|
38
|
+
: []),
|
|
39
|
+
...range(siblingsStart, siblingsEnd),
|
|
40
|
+
...(siblingsEnd < count - boundaryCount - 1
|
|
41
|
+
? ['end-ellipsis']
|
|
42
|
+
: count - boundaryCount > boundaryCount
|
|
43
|
+
? [count - boundaryCount]
|
|
44
|
+
: []),
|
|
45
|
+
...endPages
|
|
46
|
+
];
|
|
47
|
+
}
|
|
48
|
+
/** Two chevrons, for the steppers that jump to an end rather than by one page. */
|
|
49
|
+
function DoubleChevronIcon() {
|
|
50
|
+
return (_jsx("svg", { viewBox: "0 0 16 16", fill: "none", "aria-hidden": "true", children: _jsx("path", { d: "m7.5 4.5 3.5 3.5-3.5 3.5M3.5 4.5 7 8l-3.5 3.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }));
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* The ellipsis. A `<span>`, not a button and not a disabled button: it is not a
|
|
54
|
+
* control that happens to be unavailable, it is punctuation.
|
|
55
|
+
*/
|
|
56
|
+
const ellipsisClasses = {
|
|
57
|
+
xs: 'h-6 min-w-6',
|
|
58
|
+
sm: 'h-8 min-w-8',
|
|
59
|
+
md: 'h-10 min-w-10',
|
|
60
|
+
lg: 'h-12 min-w-12',
|
|
61
|
+
xl: 'h-14 min-w-14'
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* A row of page numbers.
|
|
65
|
+
*
|
|
66
|
+
* Every button in it is a real `PlButton`, which is the point: a pagination is
|
|
67
|
+
* not a new kind of control, it is buttons in a row that happen to know about
|
|
68
|
+
* each other. Reusing the component means the row inherits the glass, the
|
|
69
|
+
* pointer bloom, the press signature, the focus ring and every future change to
|
|
70
|
+
* any of them for free — and it means an `lg` pagination lines up with an `lg`
|
|
71
|
+
* button beside it, because it *is* one.
|
|
72
|
+
*
|
|
73
|
+
* `variant` sets how the pages at rest look; the current page is always `solid`,
|
|
74
|
+
* which is the one thing the row has to say without being read. That is why the
|
|
75
|
+
* default here is `ghost` rather than the `solid` a lone PlButton takes — nine
|
|
76
|
+
* panes of tinted glass in a row say that all nine are the primary action.
|
|
77
|
+
*
|
|
78
|
+
* The markup is a `<nav>` around a `<ul>` because that is what a screen reader
|
|
79
|
+
* needs to hear: a named landmark it can skip, holding a list whose length says
|
|
80
|
+
* how far the pages go, with `aria-current="page"` marking where it is.
|
|
81
|
+
*/
|
|
82
|
+
export const PlPagination = /* @__PURE__ */ React.forwardRef(function PlPagination({ variant = 'ghost', size = 'md', color = 'primary', density = 'compact', elevation = 0, count, page: pageProp, defaultPage = 1, onPageChange, siblingCount = 1, boundaryCount = 1, showEdges = false, showArrows = true, disabled = false, getPageHref, label = 'Pagination', pageLabel = (value) => `Page ${value}`, previousLabel = 'Previous page', nextLabel = 'Next page', firstLabel = 'First page', lastLabel = 'Last page', statusLabel = (value, total) => `Page ${value} of ${total}`, className, children, ...props }, ref) {
|
|
83
|
+
const [uncontrolled, setUncontrolled] = React.useState(defaultPage);
|
|
84
|
+
const current = Math.min(Math.max(pageProp ?? uncontrolled, 1), Math.max(count, 1));
|
|
85
|
+
const go = (next) => {
|
|
86
|
+
const clamped = Math.min(Math.max(next, 1), count);
|
|
87
|
+
if (clamped === current) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (pageProp === undefined) {
|
|
91
|
+
setUncontrolled(clamped);
|
|
92
|
+
}
|
|
93
|
+
onPageChange?.(clamped);
|
|
94
|
+
};
|
|
95
|
+
// One page is not a set of pages, and no pages is not a thing to say out
|
|
96
|
+
// loud. A row that renders a lone disabled "1" is a control advertising
|
|
97
|
+
// that it has nothing to do.
|
|
98
|
+
if (count < 2) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
const slots = paginationRange(count, current, siblingCount, boundaryCount);
|
|
102
|
+
const atStart = current <= 1;
|
|
103
|
+
const atEnd = current >= count;
|
|
104
|
+
/*
|
|
105
|
+
* A link only where there is somewhere to go. The page being read and a
|
|
106
|
+
* stepper at the end of the row are both `disabled`, and `disabled` is not
|
|
107
|
+
* something an `<a>` can be — a link that only looks unavailable is one a
|
|
108
|
+
* keyboard still lands on and a crawler still follows.
|
|
109
|
+
*/
|
|
110
|
+
const linkProps = (to, inert, rel) => getPageHref && !inert ? { render: _jsx("a", { href: getPageHref(to), rel: rel }) } : null;
|
|
111
|
+
/*
|
|
112
|
+
* Who answers the press.
|
|
113
|
+
*
|
|
114
|
+
* With an `href` and a handler both, the handler wins and the navigation is
|
|
115
|
+
* cancelled: that is a client-side router keeping the page it already has.
|
|
116
|
+
* With an `href` and no handler, the link is left to do what a link does —
|
|
117
|
+
* which is also what makes the row work with JavaScript still loading.
|
|
118
|
+
*/
|
|
119
|
+
const press = (event, to) => {
|
|
120
|
+
// A press carrying a modifier is the reader asking the browser for it: a
|
|
121
|
+
// new tab, a new window, a saved copy. Never ours to cancel.
|
|
122
|
+
if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (getPageHref && !onPageChange) {
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
event.preventDefault();
|
|
129
|
+
go(to);
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* The steppers. Icon-only PlButtons, so they go square and land on exactly
|
|
133
|
+
* the same footprint as a single-digit page — a row whose ends are a
|
|
134
|
+
* different width from its middle reads as two controls pushed together.
|
|
135
|
+
*/
|
|
136
|
+
const stepper = (key, accessibleName, to, inert, rotation, glyph, rel) => (_jsx("li", { className: "flex", children: _jsx(PlButton, { variant: variant, size: size, color: color, density: density, elevation: elevation, disabled: disabled || inert, "aria-label": accessibleName, startIcon: _jsx("span", { className: `flex items-center ${rotation}`, children: glyph }), onClick: (event) => press(event, to), ...linkProps(to, disabled || inert, rel) }) }, key));
|
|
137
|
+
return (_jsxs("nav", { ref: ref, "aria-label": label, className: ['flex items-center', className ?? ''].filter(Boolean).join(' '), ...props, children: [_jsxs("ul", { role: "list", className: `m-0 flex list-none items-center p-0 ${gapClasses[size]}`, children: [showEdges
|
|
138
|
+
? stepper('first', firstLabel, 1, atStart, 'rotate-180 rtl:rotate-0', _jsx(DoubleChevronIcon, {}))
|
|
139
|
+
: null, showArrows
|
|
140
|
+
? stepper('previous', previousLabel, current - 1, atStart, 'rotate-90 rtl:-rotate-90', _jsx(ChevronIcon, {}), 'prev')
|
|
141
|
+
: null, slots.map((slot, index) => typeof slot === 'number' ? (_jsx("li", { className: "flex", children: _jsx(PlButton
|
|
142
|
+
// The current page is always filled, whatever the row's
|
|
143
|
+
// resting variant is: it is the one thing here that has to be
|
|
144
|
+
// legible without being read.
|
|
145
|
+
, {
|
|
146
|
+
// The current page is always filled, whatever the row's
|
|
147
|
+
// resting variant is: it is the one thing here that has to be
|
|
148
|
+
// legible without being read.
|
|
149
|
+
variant: slot === current ? 'solid' : variant, size: size, color: color, density: density, elevation: elevation, disabled: disabled, "aria-label": pageLabel(slot), "aria-current": slot === current ? 'page' : undefined, className: "tabular-nums", onClick: (event) => press(event, slot), ...linkProps(slot, disabled || slot === current), children: slot }) }, `slot-${index}`)) : (_jsx("li", { "aria-hidden": "true", className: [
|
|
150
|
+
'flex select-none items-center justify-center',
|
|
151
|
+
'text-(--plass-muted-fg)',
|
|
152
|
+
controlTextClasses[size],
|
|
153
|
+
ellipsisClasses[size]
|
|
154
|
+
].join(' '), children: "\u2026" }, `slot-${index}`))), showArrows
|
|
155
|
+
? stepper('next', nextLabel, current + 1, atEnd, '-rotate-90 rtl:rotate-90', _jsx(ChevronIcon, {}), 'next')
|
|
156
|
+
: null, showEdges
|
|
157
|
+
? stepper('last', lastLabel, count, atEnd, 'rtl:rotate-180', _jsx(DoubleChevronIcon, {}))
|
|
158
|
+
: null] }), _jsx("span", { className: srOnlyClasses, "aria-live": "polite", children: statusLabel(current, count) }), children] }));
|
|
159
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PlPagination } from './PlPagination.js';
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PlassColor, PlassOrientation, PlassSize } from '../../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* A pane's share of the split, as a percentage of the container or as a CSS
|
|
5
|
+
* length.
|
|
6
|
+
*
|
|
7
|
+
* A bare number is a percentage — that is what a split is usually described in,
|
|
8
|
+
* and a percentage keeps its meaning when the window changes size. A string is
|
|
9
|
+
* an absolute length (`'240px'`, `'15rem'`, `'20%'`), which is what a sidebar
|
|
10
|
+
* with a minimum actually needs: "at least 200 pixels" does not survive being
|
|
11
|
+
* written down as a percentage of a width nobody knows yet.
|
|
12
|
+
*/
|
|
13
|
+
export type PlPaneSize = number | string;
|
|
14
|
+
export interface PlPanesProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'color'> {
|
|
15
|
+
/**
|
|
16
|
+
* Which way the panes run. `horizontal` puts them side by side with upright
|
|
17
|
+
* handles between them; `vertical` stacks them.
|
|
18
|
+
* @default 'horizontal'
|
|
19
|
+
*/
|
|
20
|
+
orientation?: PlassOrientation;
|
|
21
|
+
/**
|
|
22
|
+
* Whether the handles between the panes can be dragged. Turn it off for a
|
|
23
|
+
* split that is a layout rather than a control.
|
|
24
|
+
* @default true
|
|
25
|
+
*/
|
|
26
|
+
resizable?: boolean;
|
|
27
|
+
/** The colour family the handles light up in. @default 'primary' */
|
|
28
|
+
color?: PlassColor;
|
|
29
|
+
/** How thick a handle is, and how far it reaches. @default 'md' */
|
|
30
|
+
size?: PlassSize;
|
|
31
|
+
/** Fires with every pane's share, in percent, while a handle is dragged. */
|
|
32
|
+
onResize?: (sizes: number[]) => void;
|
|
33
|
+
/** Fires once, with the same shape, when the handle is let go. */
|
|
34
|
+
onResizeEnd?: (sizes: number[]) => void;
|
|
35
|
+
/** The panes. Anything that is not a `PlPane` is still laid out, but has no size. */
|
|
36
|
+
children?: React.ReactNode;
|
|
37
|
+
}
|
|
38
|
+
export interface PlPaneProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'color'> {
|
|
39
|
+
/**
|
|
40
|
+
* The share this pane starts with. Panes with no `defaultSize` split whatever
|
|
41
|
+
* is left over equally.
|
|
42
|
+
*/
|
|
43
|
+
defaultSize?: PlPaneSize;
|
|
44
|
+
/** How small it may be dragged. @default 0 */
|
|
45
|
+
minSize?: PlPaneSize;
|
|
46
|
+
/** How large it may be dragged. Unbounded when left out. */
|
|
47
|
+
maxSize?: PlPaneSize;
|
|
48
|
+
/** What is inside the pane. */
|
|
49
|
+
children?: React.ReactNode;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* A set of panes with draggable handles between them.
|
|
53
|
+
*
|
|
54
|
+
* The panes are sized in **fractions**, written out as
|
|
55
|
+
* `flex-basis: calc((100% - gutters) * fraction)`. That is the one decision the
|
|
56
|
+
* rest of this file follows from: a split described in percentages survives the
|
|
57
|
+
* window being resized without a single line of JavaScript running, so the
|
|
58
|
+
* component measures itself only twice — once on mount, to turn a `'240px'`
|
|
59
|
+
* default into a fraction, and once at the start of each drag, to know what a
|
|
60
|
+
* pixel of pointer movement is worth.
|
|
61
|
+
*
|
|
62
|
+
* The handles are interleaved here rather than written by the caller, so the
|
|
63
|
+
* children of a `PlPanes` are just panes. That does mean the direct children have
|
|
64
|
+
* to *be* `PlPane`s: the constraints are read off their props, and a pane wrapped
|
|
65
|
+
* in something else is a pane with no minimum.
|
|
66
|
+
*/
|
|
67
|
+
export declare const PlPanes: React.ForwardRefExoticComponent<PlPanesProps & React.RefAttributes<HTMLDivElement>>;
|
|
68
|
+
/**
|
|
69
|
+
* One region of a split.
|
|
70
|
+
*
|
|
71
|
+
* It carries no surface of its own on purpose: a split is layout, and the moment
|
|
72
|
+
* a pane drew a sheet it would stop being usable as the thing a `PlCard`, a
|
|
73
|
+
* `PlTable` or an editor is put inside. Put a `PlCard` in it when a surface is
|
|
74
|
+
* wanted.
|
|
75
|
+
*
|
|
76
|
+
* `defaultSize`, `minSize` and `maxSize` are read by the `PlPanes` around it
|
|
77
|
+
* rather than used here — a pane cannot know what "half" is, only the split can.
|
|
78
|
+
*/
|
|
79
|
+
export declare const PlPane: React.ForwardRefExoticComponent<PlPaneProps & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { cx, transitionClasses } from '../../internal/styles.js';
|
|
4
|
+
const PaneContext = /* @__PURE__ */ React.createContext({ basis: null });
|
|
5
|
+
/**
|
|
6
|
+
* The width of a handle, and the width of the target the pointer has to hit.
|
|
7
|
+
*
|
|
8
|
+
* A visible line one pixel wide is a target one pixel wide, which is not a
|
|
9
|
+
* target. So the handle is a track several pixels across with the hairline drawn
|
|
10
|
+
* down the middle of it — the same split a scrollbar makes between what is drawn
|
|
11
|
+
* and what can be grabbed.
|
|
12
|
+
*/
|
|
13
|
+
const handleTrackClasses = {
|
|
14
|
+
xs: 'basis-1',
|
|
15
|
+
sm: 'basis-1.5',
|
|
16
|
+
md: 'basis-2',
|
|
17
|
+
lg: 'basis-2.5',
|
|
18
|
+
xl: 'basis-3'
|
|
19
|
+
};
|
|
20
|
+
/** The same numbers, as the total the panes have to give up to the handles. */
|
|
21
|
+
const handleTrackValues = {
|
|
22
|
+
xs: 4,
|
|
23
|
+
sm: 6,
|
|
24
|
+
md: 8,
|
|
25
|
+
lg: 10,
|
|
26
|
+
xl: 12
|
|
27
|
+
};
|
|
28
|
+
/** How far one arrow key press moves a handle. */
|
|
29
|
+
const KEYBOARD_STEP = 16;
|
|
30
|
+
/**
|
|
31
|
+
* A CSS length, in pixels.
|
|
32
|
+
*
|
|
33
|
+
* Only the four units a split is ever written in are accepted; anything else
|
|
34
|
+
* resolves to `undefined`, which every caller here reads as "no constraint"
|
|
35
|
+
* rather than as zero. A bad string should leave a pane unbounded, not pin it
|
|
36
|
+
* shut.
|
|
37
|
+
*/
|
|
38
|
+
function toPixels(value, extent, root) {
|
|
39
|
+
if (value === undefined || value === null)
|
|
40
|
+
return undefined;
|
|
41
|
+
if (typeof value === 'number')
|
|
42
|
+
return (extent * value) / 100;
|
|
43
|
+
const match = /^\s*(-?[\d.]+)\s*(px|rem|em|%)\s*$/.exec(value);
|
|
44
|
+
if (!match)
|
|
45
|
+
return undefined;
|
|
46
|
+
const amount = Number(match[1]);
|
|
47
|
+
if (Number.isNaN(amount))
|
|
48
|
+
return undefined;
|
|
49
|
+
switch (match[2]) {
|
|
50
|
+
case 'px':
|
|
51
|
+
return amount;
|
|
52
|
+
case '%':
|
|
53
|
+
return (extent * amount) / 100;
|
|
54
|
+
case 'rem':
|
|
55
|
+
return amount * parseFloat(getComputedStyle(document.documentElement).fontSize || '16');
|
|
56
|
+
case 'em':
|
|
57
|
+
return amount * parseFloat((root && getComputedStyle(root).fontSize) || '16');
|
|
58
|
+
default:
|
|
59
|
+
return undefined;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/** Every pane's share of the space, summing to 1. */
|
|
63
|
+
function initialFractions(constraints, extent, root) {
|
|
64
|
+
const sizes = constraints.map((pane) => toPixels(pane.defaultSize, extent, root));
|
|
65
|
+
const named = sizes.reduce((total, size) => total + (size ?? 0), 0);
|
|
66
|
+
const unnamed = sizes.filter((size) => size === undefined).length;
|
|
67
|
+
// Whatever is left after the named panes, split evenly. Negative when the
|
|
68
|
+
// caller asked for more than there is, which the clamp below turns into zero.
|
|
69
|
+
const share = unnamed > 0 ? Math.max(0, extent - named) / unnamed : 0;
|
|
70
|
+
const resolved = sizes.map((size) => Math.max(0, size ?? share));
|
|
71
|
+
const total = resolved.reduce((sum, size) => sum + size, 0);
|
|
72
|
+
if (total <= 0)
|
|
73
|
+
return resolved.map(() => 1 / Math.max(1, resolved.length));
|
|
74
|
+
return resolved.map((size) => size / total);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A set of panes with draggable handles between them.
|
|
78
|
+
*
|
|
79
|
+
* The panes are sized in **fractions**, written out as
|
|
80
|
+
* `flex-basis: calc((100% - gutters) * fraction)`. That is the one decision the
|
|
81
|
+
* rest of this file follows from: a split described in percentages survives the
|
|
82
|
+
* window being resized without a single line of JavaScript running, so the
|
|
83
|
+
* component measures itself only twice — once on mount, to turn a `'240px'`
|
|
84
|
+
* default into a fraction, and once at the start of each drag, to know what a
|
|
85
|
+
* pixel of pointer movement is worth.
|
|
86
|
+
*
|
|
87
|
+
* The handles are interleaved here rather than written by the caller, so the
|
|
88
|
+
* children of a `PlPanes` are just panes. That does mean the direct children have
|
|
89
|
+
* to *be* `PlPane`s: the constraints are read off their props, and a pane wrapped
|
|
90
|
+
* in something else is a pane with no minimum.
|
|
91
|
+
*/
|
|
92
|
+
export const PlPanes = /* @__PURE__ */ React.forwardRef(function PlPanes({ orientation = 'horizontal', resizable = true, color = 'primary', size = 'md', onResize, onResizeEnd, className, style, children, ...props }, ref) {
|
|
93
|
+
const items = React.Children.toArray(children).filter(React.isValidElement);
|
|
94
|
+
const count = items.length;
|
|
95
|
+
const rootRef = React.useRef(null);
|
|
96
|
+
const setRootRef = React.useCallback((node) => {
|
|
97
|
+
rootRef.current = node;
|
|
98
|
+
if (typeof ref === 'function')
|
|
99
|
+
ref(node);
|
|
100
|
+
else if (ref)
|
|
101
|
+
ref.current = node;
|
|
102
|
+
}, [ref]);
|
|
103
|
+
// The constraints are read during render and used inside pointer handlers that
|
|
104
|
+
// outlive it, so they go through a ref rather than through the closure.
|
|
105
|
+
const constraintsRef = React.useRef([]);
|
|
106
|
+
constraintsRef.current = items.map((item) => item.props);
|
|
107
|
+
const [stored, setFractions] = React.useState(null);
|
|
108
|
+
// A pane added or removed leaves the stored split a render behind the children
|
|
109
|
+
// — the effect below re-splits, but the render in between would be reading a
|
|
110
|
+
// share off the end of the list. Until the two agree, nobody has a size and
|
|
111
|
+
// every pane falls back to an even share.
|
|
112
|
+
const fractions = stored && stored.length === count ? stored : null;
|
|
113
|
+
const fractionsRef = React.useRef(null);
|
|
114
|
+
fractionsRef.current = fractions;
|
|
115
|
+
const horizontal = orientation === 'horizontal';
|
|
116
|
+
const gutter = handleTrackValues[size] * Math.max(0, count - 1);
|
|
117
|
+
/*
|
|
118
|
+
* One measurement, for one purpose: turning a `defaultSize` written as a
|
|
119
|
+
* length into a fraction. It is an observer rather than a single read because
|
|
120
|
+
* a split inside a closed `PlAccordion` or an unselected `PlTab` is zero wide when
|
|
121
|
+
* it mounts, and dividing by that would put every pane at nothing.
|
|
122
|
+
*/
|
|
123
|
+
React.useEffect(() => {
|
|
124
|
+
const root = rootRef.current;
|
|
125
|
+
if (!root)
|
|
126
|
+
return;
|
|
127
|
+
const measure = () => {
|
|
128
|
+
const rect = root.getBoundingClientRect();
|
|
129
|
+
const extent = (horizontal ? rect.width : rect.height) - gutter;
|
|
130
|
+
if (extent <= 0)
|
|
131
|
+
return;
|
|
132
|
+
setFractions((previous) => previous && previous.length === count
|
|
133
|
+
? previous
|
|
134
|
+
: initialFractions(constraintsRef.current, extent, root));
|
|
135
|
+
};
|
|
136
|
+
measure();
|
|
137
|
+
const observer = new ResizeObserver(measure);
|
|
138
|
+
observer.observe(root);
|
|
139
|
+
return () => observer.disconnect();
|
|
140
|
+
}, [count, horizontal, gutter]);
|
|
141
|
+
/**
|
|
142
|
+
* Everything a drag needs to know, measured at the moment it starts.
|
|
143
|
+
*
|
|
144
|
+
* A drag only ever moves the boundary between two panes, so their total is
|
|
145
|
+
* fixed and one pane's floor is the other's ceiling. Folding all four bounds
|
|
146
|
+
* into a single range on the first of the pair is what keeps every move to one
|
|
147
|
+
* clamp and one division.
|
|
148
|
+
*/
|
|
149
|
+
function grip(index) {
|
|
150
|
+
const root = rootRef.current;
|
|
151
|
+
const current = fractionsRef.current;
|
|
152
|
+
if (!resizable || !root || !current || current[index + 1] === undefined)
|
|
153
|
+
return null;
|
|
154
|
+
const rect = root.getBoundingClientRect();
|
|
155
|
+
const extent = (horizontal ? rect.width : rect.height) - gutter;
|
|
156
|
+
if (extent <= 0)
|
|
157
|
+
return null;
|
|
158
|
+
const before = constraintsRef.current[index];
|
|
159
|
+
const after = constraintsRef.current[index + 1];
|
|
160
|
+
const start = current[index] * extent;
|
|
161
|
+
const pair = start + current[index + 1] * extent;
|
|
162
|
+
const lower = Math.max(toPixels(before?.minSize, extent, root) ?? 0, pair - (toPixels(after?.maxSize, extent, root) ?? pair));
|
|
163
|
+
const upper = Math.min(toPixels(before?.maxSize, extent, root) ?? pair, pair - (toPixels(after?.minSize, extent, root) ?? 0));
|
|
164
|
+
if (upper < lower)
|
|
165
|
+
return null;
|
|
166
|
+
return {
|
|
167
|
+
root,
|
|
168
|
+
current,
|
|
169
|
+
extent,
|
|
170
|
+
start,
|
|
171
|
+
pair,
|
|
172
|
+
resize(delta) {
|
|
173
|
+
const sized = Math.min(upper, Math.max(lower, start + delta));
|
|
174
|
+
const next = [...current];
|
|
175
|
+
next[index] = sized / extent;
|
|
176
|
+
next[index + 1] = (pair - sized) / extent;
|
|
177
|
+
setFractions(next);
|
|
178
|
+
onResize?.(next.map((fraction) => fraction * 100));
|
|
179
|
+
return next;
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* How to take a drag in flight apart, held for as long as one is running.
|
|
185
|
+
*
|
|
186
|
+
* A drag is torn down by the `pointerup` that ends it, and that event never
|
|
187
|
+
* arrives if the split goes away first — a route change, a closed accordion, a
|
|
188
|
+
* pane list that shrank. What is left behind is not only two listeners on a
|
|
189
|
+
* detached node: the drag takes the whole document's text selection away while
|
|
190
|
+
* it runs, and nothing else ever puts it back.
|
|
191
|
+
*/
|
|
192
|
+
const teardownRef = React.useRef(null);
|
|
193
|
+
React.useEffect(() => () => teardownRef.current?.(), []);
|
|
194
|
+
function beginDrag(index, event) {
|
|
195
|
+
const held = grip(index);
|
|
196
|
+
if (!held)
|
|
197
|
+
return;
|
|
198
|
+
const handle = event.currentTarget;
|
|
199
|
+
handle.setPointerCapture(event.pointerId);
|
|
200
|
+
handle.dataset.dragging = 'true';
|
|
201
|
+
/*
|
|
202
|
+
* A drag across a page selects the text it passes over, and the obvious cure
|
|
203
|
+
* — `preventDefault` on the press — also stops the browser focusing the
|
|
204
|
+
* handle, which leaves the component focusing it by hand and every mouse
|
|
205
|
+
* press wearing a keyboard focus ring. Taking the selection off the document
|
|
206
|
+
* for the length of the drag fixes the selection without touching the focus.
|
|
207
|
+
*
|
|
208
|
+
* The property is written prefixed and through `setProperty`, because WebKit
|
|
209
|
+
* implements only `-webkit-user-select`: it has no `userSelect` on a style
|
|
210
|
+
* declaration, so `style.userSelect = 'none'` hangs a plain JS property off
|
|
211
|
+
* the object, changes nothing, and Safari selects text through the whole
|
|
212
|
+
* drag. Chromium and Firefox both read the prefixed name as the standard
|
|
213
|
+
* one. This is what Tailwind's own `select-none` emits, for the same reason.
|
|
214
|
+
*/
|
|
215
|
+
const selection = document.body.style.getPropertyValue('-webkit-user-select');
|
|
216
|
+
document.body.style.setProperty('-webkit-user-select', 'none');
|
|
217
|
+
const origin = horizontal ? event.clientX : event.clientY;
|
|
218
|
+
// Positive is always "toward the end", so a drag under RTL moves the
|
|
219
|
+
// boundary the way the pointer went rather than the way the axis is numbered.
|
|
220
|
+
const towardsEnd = horizontal && getComputedStyle(held.root).direction === 'rtl' ? -1 : 1;
|
|
221
|
+
let latest = held.current;
|
|
222
|
+
const move = (moveEvent) => {
|
|
223
|
+
const position = horizontal ? moveEvent.clientX : moveEvent.clientY;
|
|
224
|
+
latest = held.resize((position - origin) * towardsEnd);
|
|
225
|
+
};
|
|
226
|
+
// Everything the drag took from outside itself, given back. Split from `end`
|
|
227
|
+
// because unmounting has to run this half and must not run the other: a
|
|
228
|
+
// component that disappeared did not finish resizing, and telling a caller it
|
|
229
|
+
// did would set state on the way out of the tree.
|
|
230
|
+
const release = () => {
|
|
231
|
+
teardownRef.current = null;
|
|
232
|
+
handle.removeEventListener('pointermove', move);
|
|
233
|
+
handle.removeEventListener('pointerup', end);
|
|
234
|
+
handle.removeEventListener('pointercancel', end);
|
|
235
|
+
delete handle.dataset.dragging;
|
|
236
|
+
// Removed rather than set back to '', so a page that never wrote the
|
|
237
|
+
// property inline is left with the declaration it actually had.
|
|
238
|
+
if (selection)
|
|
239
|
+
document.body.style.setProperty('-webkit-user-select', selection);
|
|
240
|
+
else
|
|
241
|
+
document.body.style.removeProperty('-webkit-user-select');
|
|
242
|
+
};
|
|
243
|
+
const end = () => {
|
|
244
|
+
release();
|
|
245
|
+
onResizeEnd?.(latest.map((fraction) => fraction * 100));
|
|
246
|
+
};
|
|
247
|
+
teardownRef.current = release;
|
|
248
|
+
handle.addEventListener('pointermove', move);
|
|
249
|
+
handle.addEventListener('pointerup', end);
|
|
250
|
+
handle.addEventListener('pointercancel', end);
|
|
251
|
+
}
|
|
252
|
+
function nudge(index, pixels) {
|
|
253
|
+
const held = grip(index);
|
|
254
|
+
if (!held)
|
|
255
|
+
return;
|
|
256
|
+
const next = held.resize(pixels);
|
|
257
|
+
// A key press is a whole gesture on its own — there is no "let go" to wait
|
|
258
|
+
// for, so the settled callback fires with it.
|
|
259
|
+
onResizeEnd?.(next.map((fraction) => fraction * 100));
|
|
260
|
+
}
|
|
261
|
+
const handleClassNames = cx('group/handle relative z-1 flex shrink-0 grow-0 items-center justify-center', handleTrackClasses[size], transitionClasses, '[outline:none] focus-visible:[outline:2px_solid_var(--p-ring)] focus-visible:outline-offset-0', resizable
|
|
262
|
+
? cx(horizontal ? 'cursor-col-resize' : 'cursor-row-resize', 'hover:bg-(--p-soft) data-[dragging]:bg-(--p-soft)')
|
|
263
|
+
: '');
|
|
264
|
+
return (_jsx("div", { ref: setRootRef, className: cx('flex h-full w-full', horizontal ? 'flex-row' : 'flex-col',
|
|
265
|
+
// A flex item refuses to go below its content's intrinsic size unless it
|
|
266
|
+
// is told to, which is what turns a pane holding a long line into a pane
|
|
267
|
+
// that cannot be dragged narrower.
|
|
268
|
+
'min-h-0 min-w-0', className),
|
|
269
|
+
// Three slots rather than the whole `surfaceSlots` set: a split draws no
|
|
270
|
+
// sheet, so the family only ever shows up in the handle's hairline, the
|
|
271
|
+
// tint under a hovered handle and the focus ring.
|
|
272
|
+
style: {
|
|
273
|
+
'--p-accent': `var(--plass-${color}-accent)`,
|
|
274
|
+
'--p-soft': `var(--plass-${color}-soft)`,
|
|
275
|
+
'--p-ring': `var(--plass-${color}-ring)`,
|
|
276
|
+
...style
|
|
277
|
+
}, ...props, children: items.map((item, index) => (_jsxs(React.Fragment, { children: [index > 0 ? (_jsx("div", { role: "separator", "aria-orientation": horizontal ? 'vertical' : 'horizontal', "aria-valuenow": fractions ? Math.round(fractions[index - 1] * 100) : undefined, "aria-valuemin": 0, "aria-valuemax": 100, "aria-disabled": !resizable || undefined, tabIndex: resizable ? 0 : -1, className: handleClassNames,
|
|
278
|
+
// No `preventDefault` and no explicit focus: the browser focuses
|
|
279
|
+
// the handle on a press by itself, and it knows that a press is
|
|
280
|
+
// not a keystroke — which is what keeps the focus ring off a
|
|
281
|
+
// handle somebody merely dragged. `beginDrag` takes the page's
|
|
282
|
+
// text selection away for the length of the drag instead.
|
|
283
|
+
onPointerDown: (event) => {
|
|
284
|
+
if (event.button !== 0)
|
|
285
|
+
return;
|
|
286
|
+
beginDrag(index - 1, event);
|
|
287
|
+
}, onKeyDown: (event) => {
|
|
288
|
+
const back = horizontal ? 'ArrowLeft' : 'ArrowUp';
|
|
289
|
+
const forward = horizontal ? 'ArrowRight' : 'ArrowDown';
|
|
290
|
+
if (event.key !== back && event.key !== forward)
|
|
291
|
+
return;
|
|
292
|
+
event.preventDefault();
|
|
293
|
+
nudge(index - 1, event.key === forward ? KEYBOARD_STEP : -KEYBOARD_STEP);
|
|
294
|
+
}, children: _jsx("span", { "aria-hidden": "true", className: cx('pointer-events-none bg-(--plass-border)', transitionClasses, horizontal ? 'h-full w-px' : 'h-px w-full', resizable
|
|
295
|
+
? 'group-hover/handle:bg-(--p-accent) group-focus-visible/handle:bg-(--p-accent) group-data-[dragging]/handle:bg-(--p-accent)'
|
|
296
|
+
: '') }) })) : null, _jsx(PaneContext.Provider, { value: {
|
|
297
|
+
basis: fractions
|
|
298
|
+
? `calc((100% - ${gutter}px) * ${fractions[index].toFixed(6)})`
|
|
299
|
+
: null
|
|
300
|
+
}, children: item })] }, item.key ?? index))) }));
|
|
301
|
+
});
|
|
302
|
+
/**
|
|
303
|
+
* One region of a split.
|
|
304
|
+
*
|
|
305
|
+
* It carries no surface of its own on purpose: a split is layout, and the moment
|
|
306
|
+
* a pane drew a sheet it would stop being usable as the thing a `PlCard`, a
|
|
307
|
+
* `PlTable` or an editor is put inside. Put a `PlCard` in it when a surface is
|
|
308
|
+
* wanted.
|
|
309
|
+
*
|
|
310
|
+
* `defaultSize`, `minSize` and `maxSize` are read by the `PlPanes` around it
|
|
311
|
+
* rather than used here — a pane cannot know what "half" is, only the split can.
|
|
312
|
+
*/
|
|
313
|
+
export const PlPane = /* @__PURE__ */ React.forwardRef(function PlPane(
|
|
314
|
+
// The three sizing props are named here only so they are taken out of the
|
|
315
|
+
// rest, which is spread onto a `<div>` — `defaultSize` on a div is an
|
|
316
|
+
// attribute React does not know and would hand straight to the DOM.
|
|
317
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
318
|
+
{ defaultSize, minSize, maxSize, className, style, children, ...props }, ref) {
|
|
319
|
+
const { basis } = React.useContext(PaneContext);
|
|
320
|
+
return (_jsx("div", { ref: ref, className: cx('relative min-h-0 min-w-0 overflow-auto', className),
|
|
321
|
+
// `1 1 0%` before the split has measured itself, so a pane renders at an
|
|
322
|
+
// even share on the first paint instead of at nothing and then jumping.
|
|
323
|
+
style: { flex: basis ? `0 0 ${basis}` : '1 1 0%', ...style }, ...props, children: children }));
|
|
324
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PlPane, PlPanes } from './PlPanes.js';
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PlassElevation, PlassPosition, PlassStyleProps } from '../../types.js';
|
|
3
|
+
export interface PlPillProps extends PlassStyleProps, Omit<React.ComponentPropsWithoutRef<'div'>, 'color' | 'onClick' | 'title'> {
|
|
4
|
+
/**
|
|
5
|
+
* Drop shadow depth. `2` here, against the `0` almost everything else takes.
|
|
6
|
+
*
|
|
7
|
+
* That is not an inconsistency: a pill is defined by **not** being part of the
|
|
8
|
+
* page. Every other surface in the library rests on the page and earns its
|
|
9
|
+
* separation from the glass edge, so a shadow is opt-in. This one hovers over
|
|
10
|
+
* whatever is underneath it, and a lozenge lying flat on the content it is
|
|
11
|
+
* floating over reads as a mistake — the same argument
|
|
12
|
+
* `PlFloatingBottomNavigation` makes for its own `2`.
|
|
13
|
+
* @default 2
|
|
14
|
+
*/
|
|
15
|
+
elevation?: PlassElevation;
|
|
16
|
+
/**
|
|
17
|
+
* The leading slot — a glyph, an avatar, a status dot, a photo.
|
|
18
|
+
*
|
|
19
|
+
* It is given a square box of its own and clipped to a circle, so an `<img>`
|
|
20
|
+
* lands in it as readily as an icon does: the image fills the box and is
|
|
21
|
+
* cropped rather than letterboxed, which is what a 20px portrait wants.
|
|
22
|
+
*/
|
|
23
|
+
startIcon?: React.ReactNode;
|
|
24
|
+
/** The trailing slot. Outside the pressable area, so it can be a control. */
|
|
25
|
+
endIcon?: React.ReactNode;
|
|
26
|
+
/**
|
|
27
|
+
* The headline in the middle — what the pill is currently about.
|
|
28
|
+
*
|
|
29
|
+
* A prop rather than something to compose, for the reason `PlCard`'s title is
|
|
30
|
+
* one: the arrangement is fixed and what a caller wants to decide is what goes
|
|
31
|
+
* in each slot. Almost every pill is a line of text and an optional second
|
|
32
|
+
* line under it, and spelling that as children means every caller inventing
|
|
33
|
+
* their own centring and type scale.
|
|
34
|
+
*/
|
|
35
|
+
title?: React.ReactNode;
|
|
36
|
+
/** The second line, under the title. One step down and quieter. */
|
|
37
|
+
description?: React.ReactNode;
|
|
38
|
+
/**
|
|
39
|
+
* The second half, revealed when `expanded`.
|
|
40
|
+
*
|
|
41
|
+
* The pill grows downward into it rather than swapping to a different shape:
|
|
42
|
+
* one object saying more.
|
|
43
|
+
*/
|
|
44
|
+
details?: React.ReactNode;
|
|
45
|
+
/** Whether `details` is showing. @default false */
|
|
46
|
+
expanded?: boolean;
|
|
47
|
+
/**
|
|
48
|
+
* How it sits in the page's scroll. `fixed` pins it against the viewport and
|
|
49
|
+
* centres it horizontally, which is the arrangement this shape exists for.
|
|
50
|
+
* @default 'static'
|
|
51
|
+
*/
|
|
52
|
+
position?: PlassPosition;
|
|
53
|
+
/** Which edge it is held against when `position` is not `static`. @default 'top' */
|
|
54
|
+
side?: 'top' | 'bottom';
|
|
55
|
+
/** Passing it makes the middle a real button. */
|
|
56
|
+
onClick?: React.MouseEventHandler<HTMLButtonElement>;
|
|
57
|
+
/**
|
|
58
|
+
* Anything the middle needs that `title` and `description` cannot say — a
|
|
59
|
+
* pair of small readouts, a live counter. Rendered under them, in the same
|
|
60
|
+
* centred column.
|
|
61
|
+
*/
|
|
62
|
+
children?: React.ReactNode;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* A floating lozenge holding a small amount of live information.
|
|
66
|
+
*
|
|
67
|
+
* The shape is a **stadium**, which the house radius rule otherwise forbids:
|
|
68
|
+
* every control is held just short of the 50% that would make it a pill, because
|
|
69
|
+
* the flat run along its top and bottom edge is what still reads as a sheet with
|
|
70
|
+
* the corners cut off it. This is the exception the rule is drawn against, and
|
|
71
|
+
* it works for the same reason the rule does — this is not a sheet lying on the
|
|
72
|
+
* page. It is an object hovering over one, and an object hovering over the page
|
|
73
|
+
* should not look as though it was cut from the same material.
|
|
74
|
+
*
|
|
75
|
+
* `details` is revealed by animating a measured height, exactly as a
|
|
76
|
+
* `PlAccordion` panel is: nothing is transformed and no text is resampled, the
|
|
77
|
+
* pill is simply a window that opens. The measurement is a `ResizeObserver`
|
|
78
|
+
* rather than a hardcoded height, so a details area whose content changes —
|
|
79
|
+
* which is what live information does — grows with it.
|
|
80
|
+
*/
|
|
81
|
+
export declare const PlPill: React.ForwardRefExoticComponent<PlPillProps & React.RefAttributes<HTMLDivElement>>;
|