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,185 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { transitionClasses } from '../../internal/styles.js';
|
|
4
|
+
/**
|
|
5
|
+
* There is no `size` here on purpose, and it is the one prop a reader will look
|
|
6
|
+
* for. A mark sits inside running text and has to be the size of the text it is
|
|
7
|
+
* inside; a `size` prop would only offer ways to be wrong.
|
|
8
|
+
*/
|
|
9
|
+
const variantClasses = {
|
|
10
|
+
solid: '[background-image:var(--p-fill)] text-(--p-on-solid)',
|
|
11
|
+
glass: 'border bg-(--p-soft) text-(--p-accent) [border-color:var(--p-line)]',
|
|
12
|
+
// Both properties are still set. A `<mark>` arrives from the browser's own
|
|
13
|
+
// stylesheet with a yellow background and black ink, and "no surface" has to
|
|
14
|
+
// be said out loud or it turns into the UA's surface.
|
|
15
|
+
ghost: 'bg-transparent text-(--p-accent)'
|
|
16
|
+
};
|
|
17
|
+
const weightClasses = {
|
|
18
|
+
regular: 'font-normal',
|
|
19
|
+
medium: 'font-medium',
|
|
20
|
+
semibold: 'font-semibold',
|
|
21
|
+
bold: 'font-bold'
|
|
22
|
+
};
|
|
23
|
+
/** Letters, digits and underscores in any script — what `wholeWord` counts. */
|
|
24
|
+
const wordCharacter = /[\p{L}\p{N}_]/u;
|
|
25
|
+
/** The characters a regular expression treats as syntax. */
|
|
26
|
+
function escapeRegExp(text) {
|
|
27
|
+
return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Turns the `query` prop into one expression, or `null` when there is nothing to
|
|
31
|
+
* look for — an empty search box should leave the text exactly as it was, not
|
|
32
|
+
* mark every character in it.
|
|
33
|
+
*
|
|
34
|
+
* Terms are sorted longest first because alternation in a regular expression is
|
|
35
|
+
* first-match-wins: without it `['data', 'database']` would mark `data` and
|
|
36
|
+
* stop, leaving `base` outside the mark.
|
|
37
|
+
*/
|
|
38
|
+
function buildPattern(query, caseSensitive) {
|
|
39
|
+
if (query instanceof RegExp) {
|
|
40
|
+
// Always a copy, even when the flags are already right. A global regular
|
|
41
|
+
// expression carries a `lastIndex` that `markString` moves, and mutating one
|
|
42
|
+
// the caller is holding — and may be matching with elsewhere — is not this
|
|
43
|
+
// component's to do.
|
|
44
|
+
return new RegExp(query.source, query.global ? query.flags : `${query.flags}g`);
|
|
45
|
+
}
|
|
46
|
+
const terms = (Array.isArray(query) ? query : [query])
|
|
47
|
+
.map((term) => term.trim())
|
|
48
|
+
.filter(Boolean)
|
|
49
|
+
.sort((a, b) => b.length - a.length);
|
|
50
|
+
if (terms.length === 0) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
return new RegExp(terms.map(escapeRegExp).join('|'), caseSensitive ? 'gu' : 'giu');
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Whether a match is a whole word.
|
|
57
|
+
*
|
|
58
|
+
* Checked here rather than with a lookbehind in the pattern, because lookbehind
|
|
59
|
+
* is the one regular-expression feature this library would have to think about
|
|
60
|
+
* shipping — Safari only grew it in 16.4. Two character tests cost nothing and
|
|
61
|
+
* work everywhere.
|
|
62
|
+
*/
|
|
63
|
+
function isWholeWord(text, start, end) {
|
|
64
|
+
const before = start > 0 ? text[start - 1] : '';
|
|
65
|
+
const after = end < text.length ? text[end] : '';
|
|
66
|
+
return !wordCharacter.test(before) && !wordCharacter.test(after);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Splits one string into plain runs and marked ones.
|
|
70
|
+
*
|
|
71
|
+
* Returns the string itself when nothing matched, so an unmatched text node
|
|
72
|
+
* stays a text node rather than becoming an array of one.
|
|
73
|
+
*/
|
|
74
|
+
function markString(text, pattern, wholeWord, mark) {
|
|
75
|
+
pattern.lastIndex = 0;
|
|
76
|
+
const parts = [];
|
|
77
|
+
let cursor = 0;
|
|
78
|
+
let match;
|
|
79
|
+
while ((match = pattern.exec(text)) !== null) {
|
|
80
|
+
// A pattern that can match nothing — `/x*/` — would otherwise never advance.
|
|
81
|
+
if (match[0] === '') {
|
|
82
|
+
pattern.lastIndex += 1;
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
const start = match.index;
|
|
86
|
+
const end = start + match[0].length;
|
|
87
|
+
if (wholeWord && !isWholeWord(text, start, end)) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (start > cursor) {
|
|
91
|
+
parts.push(text.slice(cursor, start));
|
|
92
|
+
}
|
|
93
|
+
parts.push(mark(match[0], `${start}`));
|
|
94
|
+
cursor = end;
|
|
95
|
+
}
|
|
96
|
+
if (parts.length === 0) {
|
|
97
|
+
return text;
|
|
98
|
+
}
|
|
99
|
+
if (cursor < text.length) {
|
|
100
|
+
parts.push(text.slice(cursor));
|
|
101
|
+
}
|
|
102
|
+
return parts;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Walks the tree, marking the text in it and leaving everything else alone.
|
|
106
|
+
*
|
|
107
|
+
* The alternative — requiring `children` to be a string — is what most libraries
|
|
108
|
+
* do, and it fails on the first search result that has a `<strong>` in it. An
|
|
109
|
+
* element is cloned with its children marked, which keeps its type, its props
|
|
110
|
+
* and its key; anything that is not a string, a number, an array or an element
|
|
111
|
+
* with children is returned untouched.
|
|
112
|
+
*/
|
|
113
|
+
function markNode(node, pattern, wholeWord, mark) {
|
|
114
|
+
if (typeof node === 'string') {
|
|
115
|
+
return markString(node, pattern, wholeWord, mark);
|
|
116
|
+
}
|
|
117
|
+
if (typeof node === 'number') {
|
|
118
|
+
return markString(String(node), pattern, wholeWord, mark);
|
|
119
|
+
}
|
|
120
|
+
if (Array.isArray(node)) {
|
|
121
|
+
return React.Children.map(node, (child) => markNode(child, pattern, wholeWord, mark));
|
|
122
|
+
}
|
|
123
|
+
if (React.isValidElement(node)) {
|
|
124
|
+
const children = node.props.children;
|
|
125
|
+
// A component whose children are a render prop, and every void element:
|
|
126
|
+
// there is no text in either, and cloning one with a `children` it never
|
|
127
|
+
// declared is how an `<input>` ends up with a child.
|
|
128
|
+
if (children === undefined || typeof children === 'function') {
|
|
129
|
+
return node;
|
|
130
|
+
}
|
|
131
|
+
return React.cloneElement(node, undefined, markNode(children, pattern, wholeWord, mark));
|
|
132
|
+
}
|
|
133
|
+
return node;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Marks the words a reader is looking for, inside text they were already
|
|
137
|
+
* reading.
|
|
138
|
+
*
|
|
139
|
+
* The component is the search, not just the styling: `query` is what a search
|
|
140
|
+
* box holds, and everything about *how* the matching is done — case, whole
|
|
141
|
+
* words, a regular expression — is a prop rather than something a caller has to
|
|
142
|
+
* pre-compute into a list of offsets.
|
|
143
|
+
*
|
|
144
|
+
* The mark is a real `<mark>`, which is the element for "text of relevance to
|
|
145
|
+
* the reader" and is announced as such. That has one consequence worth knowing:
|
|
146
|
+
* marking eleven words in a paragraph tells a screen reader that eleven things
|
|
147
|
+
* are important, which is a way of saying nothing. A highlight is for a handful
|
|
148
|
+
* of matches.
|
|
149
|
+
*
|
|
150
|
+
* Nothing here is stateful and nothing measures — the whole component is a pure
|
|
151
|
+
* function of `children` and `query`, so it re-marks on its own the moment the
|
|
152
|
+
* search box changes.
|
|
153
|
+
*/
|
|
154
|
+
export const PlHighlight = /* @__PURE__ */ React.forwardRef(function PlHighlight({ query, variant = 'solid', color = 'warning', caseSensitive = false, wholeWord = false, underline = false, weight, className, style, children, ...props }, ref) {
|
|
155
|
+
const pattern = React.useMemo(() => buildPattern(query, caseSensitive), [query, caseSensitive]);
|
|
156
|
+
const markClasses = [
|
|
157
|
+
// A hair of padding so the surface does not sit flush against the letters,
|
|
158
|
+
// and the same hair back out as a negative margin so the marked line is the
|
|
159
|
+
// same length as it was before. A mark must not move the text around it.
|
|
160
|
+
'-mx-0.5 rounded-[0.25rem] px-0.5',
|
|
161
|
+
// A mark that wraps across two lines gets its corners on both fragments
|
|
162
|
+
// rather than one long box with two square ends.
|
|
163
|
+
'box-decoration-clone',
|
|
164
|
+
variantClasses[variant],
|
|
165
|
+
// `decoration-2` and the offset so the rule sits under the descenders rather
|
|
166
|
+
// than through them, which is the whole difference between an underline and
|
|
167
|
+
// a strikethrough that missed.
|
|
168
|
+
underline ? 'underline decoration-2 underline-offset-2' : '',
|
|
169
|
+
weight ? weightClasses[weight] : '',
|
|
170
|
+
transitionClasses
|
|
171
|
+
]
|
|
172
|
+
.filter(Boolean)
|
|
173
|
+
.join(' ');
|
|
174
|
+
const marked = pattern
|
|
175
|
+
? markNode(children, pattern, wholeWord, (matched, key) => (_jsx("mark", { className: markClasses, children: matched }, key)))
|
|
176
|
+
: children;
|
|
177
|
+
return (_jsx("span", { ref: ref, className: className, style: {
|
|
178
|
+
'--p-fill': `var(--plass-${color}-fill)`,
|
|
179
|
+
'--p-on-solid': `var(--plass-${color}-on-solid)`,
|
|
180
|
+
'--p-accent': `var(--plass-${color}-accent)`,
|
|
181
|
+
'--p-soft': `var(--plass-${color}-soft)`,
|
|
182
|
+
'--p-line': `var(--plass-${color}-line)`,
|
|
183
|
+
...style
|
|
184
|
+
}, ...props, children: marked }));
|
|
185
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PlHighlight } from './PlHighlight.js';
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PlassElevation, PlassStyleProps } from '../../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Which keyboard the shortcut is being read on.
|
|
5
|
+
*
|
|
6
|
+
* `auto` asks the browser, which is right for a shortcut a reader is about to
|
|
7
|
+
* press. The three explicit values are for documentation that has to name a
|
|
8
|
+
* platform rather than the reader's own — a support page describing the Windows
|
|
9
|
+
* build, a table comparing the two.
|
|
10
|
+
*/
|
|
11
|
+
export type PlHotKeysOS = 'auto' | 'mac' | 'windows' | 'linux';
|
|
12
|
+
/** Four keys laid out as an inverted T: one on top, three beneath. */
|
|
13
|
+
export interface PlHotKeysCluster {
|
|
14
|
+
up: string;
|
|
15
|
+
left: string;
|
|
16
|
+
down: string;
|
|
17
|
+
right: string;
|
|
18
|
+
}
|
|
19
|
+
export interface PlHotKeysProps extends PlassStyleProps, Omit<React.ComponentPropsWithoutRef<'span'>, 'color' | 'children'> {
|
|
20
|
+
/**
|
|
21
|
+
* The keys, innermost punctuation and all.
|
|
22
|
+
*
|
|
23
|
+
* A string is split on `+` — `'Mod+Shift+P'` — which covers everything except
|
|
24
|
+
* a shortcut whose key *is* a plus. For that one, pass the array form:
|
|
25
|
+
* `keys={['Ctrl', '+']}`.
|
|
26
|
+
*/
|
|
27
|
+
keys?: string | string[];
|
|
28
|
+
/**
|
|
29
|
+
* Draws the four movement keys as an inverted T instead of an inline combo —
|
|
30
|
+
* `WASD`, or the arrow cluster. Takes precedence over `keys`.
|
|
31
|
+
*
|
|
32
|
+
* It is its own prop rather than a `layout` on `keys`, because the two are
|
|
33
|
+
* different objects: a combo is keys pressed *together*, and a cluster is four
|
|
34
|
+
* keys pressed one at a time whose arrangement on the keyboard is the point.
|
|
35
|
+
*/
|
|
36
|
+
cluster?: PlHotKeysCluster;
|
|
37
|
+
/**
|
|
38
|
+
* Which keyboard to name the modifiers for.
|
|
39
|
+
* @default 'auto'
|
|
40
|
+
*/
|
|
41
|
+
os?: PlHotKeysOS;
|
|
42
|
+
/**
|
|
43
|
+
* What goes between two keys. Omit it for the platform's own convention: a `+`
|
|
44
|
+
* on Windows and Linux, and nothing at all on macOS, where a shortcut is
|
|
45
|
+
* written as a run of symbols — `⇧⌘P`, never `⇧+⌘+P`.
|
|
46
|
+
*/
|
|
47
|
+
separator?: React.ReactNode;
|
|
48
|
+
/**
|
|
49
|
+
* Drop shadow depth. `0` is the default. A key cap already has a lip under it
|
|
50
|
+
* — this is a picture of a key, not a key, and raising it off the page as well
|
|
51
|
+
* is one depth cue too many.
|
|
52
|
+
* @default 0
|
|
53
|
+
*/
|
|
54
|
+
elevation?: PlassElevation;
|
|
55
|
+
}
|
|
56
|
+
export interface PlKbdProps extends Pick<PlassStyleProps, 'variant' | 'size' | 'density'>, Omit<React.ComponentPropsWithoutRef<'kbd'>, 'color'> {
|
|
57
|
+
children?: React.ReactNode;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* One key cap.
|
|
61
|
+
*
|
|
62
|
+
* Exported so a caller can compose a layout this component does not draw — a
|
|
63
|
+
* numeric keypad, a row of function keys — out of the same object the shortcut
|
|
64
|
+
* strip is made of.
|
|
65
|
+
*
|
|
66
|
+
* It reads its colour slots from whatever set them, which is the `PlHotKeys`
|
|
67
|
+
* around it in the common case. On its own it falls back to the page's own ink,
|
|
68
|
+
* so a bare `<PlKbd>` still draws.
|
|
69
|
+
*/
|
|
70
|
+
export declare const PlKbd: React.ForwardRefExoticComponent<PlKbdProps & React.RefAttributes<HTMLElement>>;
|
|
71
|
+
/**
|
|
72
|
+
* A keyboard key, a combination of them, or the four movement keys as they sit
|
|
73
|
+
* on the keyboard.
|
|
74
|
+
*
|
|
75
|
+
* Two things make this more than a styled `<kbd>`, and both are about the label
|
|
76
|
+
* rather than the box around it.
|
|
77
|
+
*
|
|
78
|
+
* The first is `Mod`. A shortcut written as `Ctrl+K` is wrong for every Mac
|
|
79
|
+
* reader and one written as `⌘K` is wrong for everybody else, so the token that
|
|
80
|
+
* means "the modifier shortcuts are built on" resolves per platform — and `os`
|
|
81
|
+
* is there for the pages that have to name a platform rather than the reader's.
|
|
82
|
+
*
|
|
83
|
+
* The second is that `⌘` is not a word. A screen reader reads it as "place of
|
|
84
|
+
* interest sign", so every key drawn as a glyph carries its name beside it, in
|
|
85
|
+
* the clipped box `srOnlyClasses` describes. What is announced is "Command K",
|
|
86
|
+
* which is what the shortcut is called.
|
|
87
|
+
*
|
|
88
|
+
* The keys are real `<kbd>` elements; the wrapper around them is a `<span>`.
|
|
89
|
+
* Nesting `<kbd>` inside `<kbd>` is allowed and would also be defensible, but a
|
|
90
|
+
* `kbd` wrapper is a second box for a host stylesheet to reach into for no gain
|
|
91
|
+
* — the semantics are carried by the keys themselves either way.
|
|
92
|
+
*/
|
|
93
|
+
export declare const PlHotKeys: React.ForwardRefExoticComponent<PlHotKeysProps & React.RefAttributes<HTMLSpanElement>>;
|
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { controlHeightClasses, controlSlots, controlTextClasses, glassClasses, paddingXClasses, radiusClasses, srOnlyClasses, transitionClasses } from '../../internal/styles.js';
|
|
4
|
+
const word = (text) => ({ symbol: text, name: text });
|
|
5
|
+
/**
|
|
6
|
+
* One entry per key that is spelled differently somewhere, keyed by the token
|
|
7
|
+
* with its case and spaces taken off.
|
|
8
|
+
*
|
|
9
|
+
* The aliases are deliberate and not generosity: `Cmd`, `Command` and `Meta` are
|
|
10
|
+
* three names one key already has, and a component that accepted only one of
|
|
11
|
+
* them would be a component every caller has to look up.
|
|
12
|
+
*
|
|
13
|
+
* `Mod` is the entry the rest exist for. It is the only token whose *meaning*
|
|
14
|
+
* changes with the platform rather than just its spelling — the modifier a
|
|
15
|
+
* shortcut is actually built on, which is Command on a Mac and Control
|
|
16
|
+
* everywhere else. Writing `Ctrl` and hoping is what makes a documentation page
|
|
17
|
+
* wrong for half its readers.
|
|
18
|
+
*/
|
|
19
|
+
const keyLabels = {
|
|
20
|
+
mod: {
|
|
21
|
+
mac: { symbol: '⌘', name: 'Command' },
|
|
22
|
+
windows: word('Ctrl'),
|
|
23
|
+
linux: word('Ctrl')
|
|
24
|
+
},
|
|
25
|
+
meta: {
|
|
26
|
+
mac: { symbol: '⌘', name: 'Command' },
|
|
27
|
+
windows: word('Win'),
|
|
28
|
+
linux: word('Super')
|
|
29
|
+
},
|
|
30
|
+
ctrl: {
|
|
31
|
+
mac: { symbol: '⌃', name: 'Control' },
|
|
32
|
+
windows: word('Ctrl'),
|
|
33
|
+
linux: word('Ctrl')
|
|
34
|
+
},
|
|
35
|
+
alt: {
|
|
36
|
+
mac: { symbol: '⌥', name: 'Option' },
|
|
37
|
+
windows: word('Alt'),
|
|
38
|
+
linux: word('Alt')
|
|
39
|
+
},
|
|
40
|
+
shift: {
|
|
41
|
+
mac: { symbol: '⇧', name: 'Shift' },
|
|
42
|
+
windows: word('Shift'),
|
|
43
|
+
linux: word('Shift')
|
|
44
|
+
},
|
|
45
|
+
enter: {
|
|
46
|
+
mac: { symbol: '↩', name: 'Enter' },
|
|
47
|
+
windows: word('Enter'),
|
|
48
|
+
linux: word('Enter')
|
|
49
|
+
},
|
|
50
|
+
tab: {
|
|
51
|
+
mac: { symbol: '⇥', name: 'Tab' },
|
|
52
|
+
windows: word('Tab'),
|
|
53
|
+
linux: word('Tab')
|
|
54
|
+
},
|
|
55
|
+
escape: {
|
|
56
|
+
mac: { symbol: '⎋', name: 'Escape' },
|
|
57
|
+
windows: word('Esc'),
|
|
58
|
+
linux: word('Esc')
|
|
59
|
+
},
|
|
60
|
+
backspace: {
|
|
61
|
+
mac: { symbol: '⌫', name: 'Backspace' },
|
|
62
|
+
windows: word('Backspace'),
|
|
63
|
+
linux: word('Backspace')
|
|
64
|
+
},
|
|
65
|
+
delete: {
|
|
66
|
+
mac: { symbol: '⌦', name: 'Delete' },
|
|
67
|
+
windows: word('Del'),
|
|
68
|
+
linux: word('Del')
|
|
69
|
+
},
|
|
70
|
+
capslock: {
|
|
71
|
+
mac: { symbol: '⇪', name: 'Caps Lock' },
|
|
72
|
+
windows: word('Caps Lock'),
|
|
73
|
+
linux: word('Caps Lock')
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
/** The tokens that name one key by more than one word. */
|
|
77
|
+
const keyAliases = {
|
|
78
|
+
cmdorctrl: 'mod',
|
|
79
|
+
commandorcontrol: 'mod',
|
|
80
|
+
cmd: 'meta',
|
|
81
|
+
command: 'meta',
|
|
82
|
+
super: 'meta',
|
|
83
|
+
win: 'meta',
|
|
84
|
+
windows: 'meta',
|
|
85
|
+
control: 'ctrl',
|
|
86
|
+
option: 'alt',
|
|
87
|
+
opt: 'alt',
|
|
88
|
+
return: 'enter',
|
|
89
|
+
esc: 'escape',
|
|
90
|
+
del: 'delete',
|
|
91
|
+
caps: 'capslock'
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* The keys drawn as arrows on every platform, not just on a Mac. An arrow is not
|
|
95
|
+
* a Mac convention — it is what is printed on the key.
|
|
96
|
+
*/
|
|
97
|
+
const arrowLabels = {
|
|
98
|
+
up: { symbol: '↑', name: 'Arrow up' },
|
|
99
|
+
down: { symbol: '↓', name: 'Arrow down' },
|
|
100
|
+
left: { symbol: '←', name: 'Arrow left' },
|
|
101
|
+
right: { symbol: '→', name: 'Arrow right' },
|
|
102
|
+
arrowup: { symbol: '↑', name: 'Arrow up' },
|
|
103
|
+
arrowdown: { symbol: '↓', name: 'Arrow down' },
|
|
104
|
+
arrowleft: { symbol: '←', name: 'Arrow left' },
|
|
105
|
+
arrowright: { symbol: '→', name: 'Arrow right' }
|
|
106
|
+
};
|
|
107
|
+
/** Resolves one token into what to draw and what to announce. */
|
|
108
|
+
function labelFor(token, os) {
|
|
109
|
+
const normalized = token.toLowerCase().replace(/[\s_-]/g, '');
|
|
110
|
+
const canonical = keyAliases[normalized] ?? normalized;
|
|
111
|
+
const arrow = arrowLabels[canonical];
|
|
112
|
+
if (arrow) {
|
|
113
|
+
return arrow;
|
|
114
|
+
}
|
|
115
|
+
const known = keyLabels[canonical];
|
|
116
|
+
if (known) {
|
|
117
|
+
return known[os];
|
|
118
|
+
}
|
|
119
|
+
// Everything else is printed as it was written, with the one courtesy that a
|
|
120
|
+
// single letter is capitalised: `keys="mod+k"` should draw a K, because that
|
|
121
|
+
// is what is on the key.
|
|
122
|
+
return word(token.length === 1 ? token.toUpperCase() : token);
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Splits the string form. Empty segments are what `'Ctrl++'` leaves behind, and
|
|
126
|
+
* dropping them is why the array form exists for that case.
|
|
127
|
+
*/
|
|
128
|
+
function tokenize(keys) {
|
|
129
|
+
if (Array.isArray(keys)) {
|
|
130
|
+
return keys.map((key) => key.trim()).filter(Boolean);
|
|
131
|
+
}
|
|
132
|
+
return keys
|
|
133
|
+
.split('+')
|
|
134
|
+
.map((key) => key.trim())
|
|
135
|
+
.filter(Boolean);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* What the browser says it is running on.
|
|
139
|
+
*
|
|
140
|
+
* `userAgentData.platform` is the modern spelling and `navigator.platform` the
|
|
141
|
+
* deprecated one that every browser still answers; the user agent string is the
|
|
142
|
+
* last resort. All three are matched at once because the question here is coarse
|
|
143
|
+
* — which of three key caps to print — and getting it slightly wrong is a label,
|
|
144
|
+
* not a bug.
|
|
145
|
+
*/
|
|
146
|
+
function detectOS() {
|
|
147
|
+
if (typeof navigator === 'undefined') {
|
|
148
|
+
return 'windows';
|
|
149
|
+
}
|
|
150
|
+
const data = navigator.userAgentData;
|
|
151
|
+
const haystack = `${data?.platform ?? ''} ${navigator.platform ?? ''} ${navigator.userAgent ?? ''}`;
|
|
152
|
+
if (/mac|iphone|ipad|ipod/i.test(haystack)) {
|
|
153
|
+
return 'mac';
|
|
154
|
+
}
|
|
155
|
+
if (/win/i.test(haystack)) {
|
|
156
|
+
return 'windows';
|
|
157
|
+
}
|
|
158
|
+
return 'linux';
|
|
159
|
+
}
|
|
160
|
+
/** The platform never changes under a running page, so there is nothing to subscribe to. */
|
|
161
|
+
function subscribe() {
|
|
162
|
+
return () => { };
|
|
163
|
+
}
|
|
164
|
+
function serverOS() {
|
|
165
|
+
return 'windows';
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* `useSyncExternalStore` rather than `useEffect` plus state, and rather than
|
|
169
|
+
* reading `navigator` during render.
|
|
170
|
+
*
|
|
171
|
+
* Reading it during render is a hydration mismatch waiting to happen: the server
|
|
172
|
+
* has no `navigator`, so it would render `Ctrl` and the client would render `⌘`
|
|
173
|
+
* into the same markup. This hook is the one API that tells React the two are
|
|
174
|
+
* *meant* to differ — it hydrates with the server's answer and re-renders with
|
|
175
|
+
* the browser's, which is exactly the sequence a Mac reader sees.
|
|
176
|
+
*/
|
|
177
|
+
function useDetectedOS() {
|
|
178
|
+
return React.useSyncExternalStore(subscribe, detectOS, serverOS);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* A key cap sits one step down the control ladder: it is a token inside a line
|
|
182
|
+
* of text, not a control the line lines up against.
|
|
183
|
+
*/
|
|
184
|
+
const keyScale = {
|
|
185
|
+
xs: 'xs',
|
|
186
|
+
sm: 'xs',
|
|
187
|
+
md: 'sm',
|
|
188
|
+
lg: 'md',
|
|
189
|
+
xl: 'lg'
|
|
190
|
+
};
|
|
191
|
+
/**
|
|
192
|
+
* The three materials, and the one place in the library where a filled surface
|
|
193
|
+
* gets a hard-edged shadow directly under it.
|
|
194
|
+
*
|
|
195
|
+
* That lip is not the gloss line the design language rules out — a gloss line is
|
|
196
|
+
* a highlight *on* the surface, claiming a lamp. This is a two-pixel offset
|
|
197
|
+
* shadow *under* it, which is the one thing every printed manual has used to
|
|
198
|
+
* mean "this is a key you press". A picture of a key is allowed to look like a
|
|
199
|
+
* key; a control is not allowed to look like a picture of one.
|
|
200
|
+
*
|
|
201
|
+
* `glass` is the default, because a hairline box is what a key cap has looked
|
|
202
|
+
* like in every manual ever printed. Its edge is `--plass-border` rather than
|
|
203
|
+
* the sheet's white hairline, or a cap set on a light card would have no edge.
|
|
204
|
+
*/
|
|
205
|
+
const variantClasses = {
|
|
206
|
+
solid: /* @__PURE__ */ [
|
|
207
|
+
'text-(--p-on-solid) [background-image:var(--p-fill)]',
|
|
208
|
+
'[box-shadow:var(--p-elev),0_2px_0_0_var(--p-tint)]'
|
|
209
|
+
].join(' '),
|
|
210
|
+
glass: /* @__PURE__ */ [
|
|
211
|
+
glassClasses,
|
|
212
|
+
'border text-(--p-accent) bg-(--plass-glass)',
|
|
213
|
+
'[border-color:var(--plass-border)]',
|
|
214
|
+
'[box-shadow:var(--p-elev),0_2px_0_0_var(--plass-shadow-ambient)]'
|
|
215
|
+
].join(' '),
|
|
216
|
+
ghost: 'text-(--p-accent) bg-(--p-soft)'
|
|
217
|
+
};
|
|
218
|
+
/** The width a single-letter cap is held to, so `⌘` and `K` are the same square. */
|
|
219
|
+
const keyMinWidthClasses = {
|
|
220
|
+
xs: 'min-w-6',
|
|
221
|
+
sm: 'min-w-8',
|
|
222
|
+
md: 'min-w-10',
|
|
223
|
+
lg: 'min-w-12',
|
|
224
|
+
xl: 'min-w-14'
|
|
225
|
+
};
|
|
226
|
+
/**
|
|
227
|
+
* One key cap.
|
|
228
|
+
*
|
|
229
|
+
* Exported so a caller can compose a layout this component does not draw — a
|
|
230
|
+
* numeric keypad, a row of function keys — out of the same object the shortcut
|
|
231
|
+
* strip is made of.
|
|
232
|
+
*
|
|
233
|
+
* It reads its colour slots from whatever set them, which is the `PlHotKeys`
|
|
234
|
+
* around it in the common case. On its own it falls back to the page's own ink,
|
|
235
|
+
* so a bare `<PlKbd>` still draws.
|
|
236
|
+
*/
|
|
237
|
+
export const PlKbd = /* @__PURE__ */ React.forwardRef(function PlKbd({ variant = 'glass', size = 'md', density = 'compact', className, children, ...props }, ref) {
|
|
238
|
+
const step = keyScale[size];
|
|
239
|
+
return (_jsx("kbd", { ref: ref, className: [
|
|
240
|
+
'inline-flex shrink-0 items-center justify-center',
|
|
241
|
+
'font-mono leading-none font-medium tabular-nums whitespace-nowrap',
|
|
242
|
+
controlHeightClasses[step],
|
|
243
|
+
controlTextClasses[step],
|
|
244
|
+
keyMinWidthClasses[step],
|
|
245
|
+
paddingXClasses[density][step],
|
|
246
|
+
radiusClasses[step],
|
|
247
|
+
variantClasses[variant],
|
|
248
|
+
transitionClasses,
|
|
249
|
+
className ?? ''
|
|
250
|
+
]
|
|
251
|
+
.filter(Boolean)
|
|
252
|
+
.join(' '), ...props, children: children }));
|
|
253
|
+
});
|
|
254
|
+
/**
|
|
255
|
+
* A keyboard key, a combination of them, or the four movement keys as they sit
|
|
256
|
+
* on the keyboard.
|
|
257
|
+
*
|
|
258
|
+
* Two things make this more than a styled `<kbd>`, and both are about the label
|
|
259
|
+
* rather than the box around it.
|
|
260
|
+
*
|
|
261
|
+
* The first is `Mod`. A shortcut written as `Ctrl+K` is wrong for every Mac
|
|
262
|
+
* reader and one written as `⌘K` is wrong for everybody else, so the token that
|
|
263
|
+
* means "the modifier shortcuts are built on" resolves per platform — and `os`
|
|
264
|
+
* is there for the pages that have to name a platform rather than the reader's.
|
|
265
|
+
*
|
|
266
|
+
* The second is that `⌘` is not a word. A screen reader reads it as "place of
|
|
267
|
+
* interest sign", so every key drawn as a glyph carries its name beside it, in
|
|
268
|
+
* the clipped box `srOnlyClasses` describes. What is announced is "Command K",
|
|
269
|
+
* which is what the shortcut is called.
|
|
270
|
+
*
|
|
271
|
+
* The keys are real `<kbd>` elements; the wrapper around them is a `<span>`.
|
|
272
|
+
* Nesting `<kbd>` inside `<kbd>` is allowed and would also be defensible, but a
|
|
273
|
+
* `kbd` wrapper is a second box for a host stylesheet to reach into for no gain
|
|
274
|
+
* — the semantics are carried by the keys themselves either way.
|
|
275
|
+
*/
|
|
276
|
+
export const PlHotKeys = /* @__PURE__ */ React.forwardRef(function PlHotKeys({ variant = 'glass', size = 'md', color = 'secondary', density = 'compact', elevation = 0, keys, cluster, os = 'auto', separator, className, style, ...props }, ref) {
|
|
277
|
+
const detected = useDetectedOS();
|
|
278
|
+
const resolved = os === 'auto' ? detected : os;
|
|
279
|
+
const slots = { ...controlSlots(color, elevation, variant), ...style };
|
|
280
|
+
const capProps = { variant, size, density };
|
|
281
|
+
const gap = size === 'xs' || size === 'sm' ? 'gap-1' : 'gap-1.5';
|
|
282
|
+
if (cluster) {
|
|
283
|
+
return (_jsxs("span", { ref: ref, className: ['inline-flex flex-col items-center align-middle', gap, className ?? '']
|
|
284
|
+
.filter(Boolean)
|
|
285
|
+
.join(' '), style: slots, ...props, children: [_jsx(PlKbd, { ...capProps, children: cluster.up }), _jsxs("span", { className: `inline-flex ${gap}`, children: [_jsx(PlKbd, { ...capProps, children: cluster.left }), _jsx(PlKbd, { ...capProps, children: cluster.down }), _jsx(PlKbd, { ...capProps, children: cluster.right })] })] }));
|
|
286
|
+
}
|
|
287
|
+
const labels = tokenize(keys ?? []).map((token) => labelFor(token, resolved));
|
|
288
|
+
// macOS writes a shortcut as a run of symbols with nothing between them; the
|
|
289
|
+
// other two join theirs with a `+`. A caller who passes one gets theirs.
|
|
290
|
+
const joiner = separator === undefined ? (resolved === 'mac' ? null : '+') : separator;
|
|
291
|
+
return (_jsx("span", { ref: ref, className: ['inline-flex max-w-full items-center gap-1 align-middle', className ?? '']
|
|
292
|
+
.filter(Boolean)
|
|
293
|
+
.join(' '), style: slots, ...props, children: labels.map((label, index) => (_jsxs(React.Fragment, { children: [index > 0 && joiner !== null ? (_jsx("span", { "aria-hidden": "true", className: "text-(--plass-muted-fg)", children: joiner })) : null, _jsx(PlKbd, { ...capProps, children: label.symbol === label.name ? (label.symbol) : (_jsxs(_Fragment, { children: [_jsx("span", { "aria-hidden": "true", children: label.symbol }), _jsx("span", { className: srOnlyClasses, children: label.name })] })) })] }, index))) }));
|
|
294
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PlHotKeys, PlKbd } from './PlHotKeys.js';
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { PlassColor, PlassSize } from '../../types.js';
|
|
3
|
+
export interface PlIconProps extends Omit<React.ComponentPropsWithoutRef<'span'>, 'color'> {
|
|
4
|
+
/**
|
|
5
|
+
* The glyph. An `<svg>` element, an `<img>`, a component from an icon set, or
|
|
6
|
+
* a character — whatever is passed is laid into a box of the right size and
|
|
7
|
+
* given a colour to inherit.
|
|
8
|
+
*
|
|
9
|
+
* It is a prop rather than `children` on purpose. An icon set hands you an
|
|
10
|
+
* element you did not draw, and the two things you always want to change about
|
|
11
|
+
* it — how big it is and what colour it is — are the two you cannot reach once
|
|
12
|
+
* it is a child of something. As a prop it is content the icon *sizes*, not
|
|
13
|
+
* content the icon merely wraps.
|
|
14
|
+
*/
|
|
15
|
+
icon: React.ReactNode;
|
|
16
|
+
/**
|
|
17
|
+
* The box the glyph is drawn in: 14, 16, 20, 24 and 28px. Its own ladder
|
|
18
|
+
* rather than the control heights, because an icon is not a control.
|
|
19
|
+
* @default 'md'
|
|
20
|
+
*/
|
|
21
|
+
size?: PlassSize;
|
|
22
|
+
/**
|
|
23
|
+
* Semantic colour role, or `inherit` — the default — to take the colour of
|
|
24
|
+
* whatever the icon sits in.
|
|
25
|
+
*
|
|
26
|
+
* `inherit` and not `primary`, which is the one place this prop departs from
|
|
27
|
+
* every other component in the library. An icon is content, and the
|
|
28
|
+
* overwhelmingly common case is an icon inside something that has already
|
|
29
|
+
* decided what colour its content is: a `PlButton`'s label, a muted caption, a
|
|
30
|
+
* `PlAlert`'s own family. An icon that arrived pre-dyed would have to be turned
|
|
31
|
+
* off again at every one of those.
|
|
32
|
+
* @default 'inherit'
|
|
33
|
+
*/
|
|
34
|
+
color?: PlassColor | 'inherit';
|
|
35
|
+
/**
|
|
36
|
+
* What the icon says, for a reader who cannot see it.
|
|
37
|
+
*
|
|
38
|
+
* Without it the icon is hidden from the accessibility tree entirely, which is
|
|
39
|
+
* the right default: the overwhelming majority of icons sit next to a word that
|
|
40
|
+
* already says the same thing, and reading both out loud is worse than reading
|
|
41
|
+
* one. Pass this only when the glyph is carrying meaning on its own.
|
|
42
|
+
*/
|
|
43
|
+
label?: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A glyph at a known size, in a known colour.
|
|
47
|
+
*
|
|
48
|
+
* The library draws no icons of its own beyond the handful its components need —
|
|
49
|
+
* an icon set is a decision that belongs to the app, not to the component
|
|
50
|
+
* library it installs. What this does is give whatever icon the app chose the
|
|
51
|
+
* same two axes everything else here has.
|
|
52
|
+
*
|
|
53
|
+
* The box is `inline-flex` with the glyph told to fill it, and `font-size` is
|
|
54
|
+
* set to the same length — so an `<svg>` with its own `width`, an `<svg>` sized
|
|
55
|
+
* in `em`, and a bare character all come out the same size. That is the whole
|
|
56
|
+
* component: a box, a length written twice, and a colour.
|
|
57
|
+
*
|
|
58
|
+
* There is no `variant` and no `elevation`. An icon is not a surface: it is ink,
|
|
59
|
+
* and the only thing the design language has to say about ink is which family it
|
|
60
|
+
* is drawn in.
|
|
61
|
+
*/
|
|
62
|
+
export declare const PlIcon: React.ForwardRefExoticComponent<PlIconProps & React.RefAttributes<HTMLSpanElement>>;
|