@livestorm/ui-vue 1.1.3 → 2.0.1
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/README.md +154 -32
- package/components-vite.js +5 -5
- package/components.d.ts +3 -3
- package/dist/UiTimelineItem.vue_vue_type_style_index_0_lang-BN5208td.mjs +5452 -0
- package/dist/a11y--y7uaY4j.mjs +217 -0
- package/dist/breakpoints.mjs +9 -0
- package/dist/bus.mjs +5 -0
- package/dist/components.mjs +215 -1663
- package/dist/index.mjs +85 -166
- package/dist/integrations.mjs +8 -0
- package/dist/layouts.mjs +236 -0
- package/dist/responsive.mjs +25 -0
- package/dist/slot.mjs +21 -0
- package/dist/toastDSV2-wMh-UMzW.mjs +74 -0
- package/dist/types/index.d.ts +84 -0
- package/dist/types/src/components/Toast/LayoutToasts.vue.d.ts +3 -0
- package/dist/types/src/components/Toast/ToastMessage.vue.d.ts +21 -0
- package/dist/types/src/components/Toast/toastDSV2.d.ts +102 -0
- package/dist/types/src/components/UiActionBar/UiActionBar.vue.d.ts +44 -0
- package/dist/types/src/components/UiActionBar/UiActionBarItem.vue.d.ts +47 -0
- package/dist/types/src/components/UiActionBar/UiActionBarSeparator.vue.d.ts +3 -0
- package/dist/types/src/components/UiActionBar/index.d.ts +4 -0
- package/dist/types/src/components/UiActionBar/types.d.ts +14 -0
- package/dist/types/src/components/UiAnimatedLogo/UiAnimatedLogo.vue.d.ts +10 -0
- package/dist/types/src/components/UiAnimatedLogo/animations-links.d.ts +3 -0
- package/dist/types/src/components/UiAvatar/UiAvatar.vue.d.ts +55 -0
- package/dist/types/src/components/UiAvatar/index.d.ts +1 -0
- package/dist/types/src/components/UiAvatarList/UiAvatarList.vue.d.ts +28 -0
- package/dist/types/src/components/UiAvatarList/index.d.ts +1 -0
- package/dist/types/src/components/UiBadge/UiBadge.vue.d.ts +47 -0
- package/dist/types/src/components/UiBadge/index.d.ts +1 -0
- package/dist/types/src/components/UiBanner/UiBanner.vue.d.ts +96 -0
- package/dist/types/src/components/UiBanner/index.d.ts +2 -0
- package/dist/types/src/components/UiBreadcrumb/UiBreadcrumb.vue.d.ts +15 -0
- package/dist/types/src/components/UiBreadcrumb/index.d.ts +2 -0
- package/dist/types/src/components/UiButton/UiButton.vue.d.ts +280 -0
- package/dist/types/src/components/UiButtonGroup/UiButtonGroup.vue.d.ts +42 -0
- package/dist/types/src/components/UiButtonGroup/UiButtonGroupItem.vue.d.ts +21 -0
- package/dist/types/src/components/UiButtonGroup/index.d.ts +3 -0
- package/dist/types/src/components/UiButtonGroup/types.d.ts +10 -0
- package/dist/types/src/components/UiCard/UiCard.vue.d.ts +31 -0
- package/dist/types/src/components/UiCarousel/UiCarousel.vue.d.ts +63 -0
- package/dist/types/src/components/UiCarousel/index.d.ts +2 -0
- package/dist/types/src/components/UiColorField/UiColorField.vue.d.ts +19 -0
- package/dist/types/src/components/UiColorField/index.d.ts +2 -0
- package/dist/types/src/components/UiColorField/types.d.ts +29 -0
- package/dist/types/src/components/UiColorPicker/UiColorPicker.vue.d.ts +35 -0
- package/dist/types/src/components/UiColorPicker/index.d.ts +2 -0
- package/dist/types/src/components/UiColorPicker/types.d.ts +97 -0
- package/dist/types/src/components/UiDialog/MarketplaceHeaderExample.vue.d.ts +28 -0
- package/dist/types/src/components/UiDialog/UiDialog.vue.d.ts +18 -0
- package/dist/types/src/components/UiDialog/UiDialogClose.vue.d.ts +10 -0
- package/dist/types/src/components/UiDialog/UiDialogContent.vue.d.ts +54 -0
- package/dist/types/src/components/UiDialog/UiDialogFooter.vue.d.ts +13 -0
- package/dist/types/src/components/UiDialog/UiDialogTrigger.vue.d.ts +14 -0
- package/dist/types/src/components/UiDialog/index.d.ts +7 -0
- package/dist/types/src/components/UiDropdown/UiDropdown.vue.d.ts +42 -0
- package/dist/types/src/components/UiDropdown/UiDropdownContent.vue.d.ts +32 -0
- package/dist/types/src/components/UiDropdown/UiDropdownItem.vue.d.ts +27 -0
- package/dist/types/src/components/UiDropdown/UiDropdownSeparator.vue.d.ts +3 -0
- package/dist/types/src/components/UiDropdown/UiDropdownTrigger.vue.d.ts +45 -0
- package/dist/types/src/components/UiDropdown/context.d.ts +7 -0
- package/dist/types/src/components/UiDropdown/index.d.ts +6 -0
- package/dist/types/src/components/UiEmptyState/UiEmptyState.vue.d.ts +29 -0
- package/dist/types/src/components/UiFieldWrapper/UiFieldWrapper.vue.d.ts +36 -0
- package/dist/types/src/components/UiFieldWrapper/index.d.ts +1 -0
- package/dist/types/src/components/UiForm/UiFormField.types.d.ts +22 -0
- package/dist/types/src/components/UiForm/UiFormField.vue.d.ts +34 -0
- package/dist/types/src/components/UiForm/index.d.ts +3 -0
- package/dist/types/src/components/UiHorizontalSeparator/UiHorizontalSeparator.vue.d.ts +6 -0
- package/dist/types/src/components/UiInputCheckbox/UiInputCheckbox.vue.d.ts +108 -0
- package/dist/types/src/components/UiInputCheckbox/index.d.ts +2 -0
- package/dist/types/src/components/UiInputCheckbox/types.d.ts +1 -0
- package/dist/types/src/components/UiInputSelect/UiInputSelect.vue.d.ts +66 -0
- package/dist/types/src/components/UiInputSelect/index.d.ts +2 -0
- package/dist/types/src/components/UiInputSelect/types.d.ts +1 -0
- package/dist/types/src/components/UiInputTextarea/UiInputTextarea.vue.d.ts +49 -0
- package/dist/types/src/components/UiInputTextarea/index.d.ts +2 -0
- package/dist/types/src/components/UiInputTextarea/types.d.ts +1 -0
- package/dist/types/src/components/UiLabel/UiLabel.vue.d.ts +17 -0
- package/dist/types/src/components/UiList/UiList.vue.d.ts +27 -0
- package/dist/types/src/components/UiListItem/UiListItem.vue.d.ts +35 -0
- package/dist/types/src/components/UiLoader/UiLoader.vue.d.ts +17 -0
- package/dist/types/src/components/UiLogo/UiLogo.vue.d.ts +20 -0
- package/dist/types/src/components/UiLogo/variants/PulseVariant.vue.d.ts +3 -0
- package/dist/types/src/components/UiLogo/variants/TornadoVariant.vue.d.ts +3 -0
- package/dist/types/src/components/UiMenu/UiMenu.vue.d.ts +18 -0
- package/dist/types/src/components/UiMenu/UiMenuContent.vue.d.ts +30 -0
- package/dist/types/src/components/UiMenu/UiMenuGroup.vue.d.ts +16 -0
- package/dist/types/src/components/UiMenu/UiMenuItem.vue.d.ts +18 -0
- package/dist/types/src/components/UiMenu/UiMenuLabel.vue.d.ts +13 -0
- package/dist/types/src/components/UiMenu/UiMenuSeparator.vue.d.ts +13 -0
- package/dist/types/src/components/UiMenu/UiMenuSub.vue.d.ts +18 -0
- package/dist/types/src/components/UiMenu/UiMenuSubContent.vue.d.ts +32 -0
- package/dist/types/src/components/UiMenu/UiMenuSubTrigger.vue.d.ts +14 -0
- package/dist/types/src/components/UiMenu/UiMenuTrigger.vue.d.ts +14 -0
- package/dist/types/src/components/UiMenu/index.d.ts +10 -0
- package/dist/types/src/components/UiPage/UiPage.vue.d.ts +37 -0
- package/dist/types/src/components/UiPageHeader/UiPageHeader.vue.d.ts +33 -0
- package/dist/types/src/components/UiPopover/UiPopover.vue.d.ts +18 -0
- package/dist/types/src/components/UiPopover/UiPopoverAnchor.vue.d.ts +14 -0
- package/dist/types/src/components/UiPopover/UiPopoverContent.vue.d.ts +28 -0
- package/dist/types/src/components/UiPopover/UiPopoverTrigger.vue.d.ts +14 -0
- package/dist/types/src/components/UiProgress/UiProgress.vue.d.ts +15 -0
- package/dist/types/src/components/UiProgress/index.d.ts +2 -0
- package/dist/types/src/components/UiProgress/types.d.ts +4 -0
- package/dist/types/src/components/UiRoomButton/UiRoomButton.vue.d.ts +29 -0
- package/dist/types/src/components/UiShell/UiShell.vue.d.ts +24 -0
- package/dist/types/src/components/UiSideMenu/UiSideMenu.vue.d.ts +64 -0
- package/dist/types/src/components/UiSideMenu/UiSideMenuBottom.vue.d.ts +7 -0
- package/dist/types/src/components/UiSideMenu/UiSideMenuItem.vue.d.ts +53 -0
- package/dist/types/src/components/UiSideMenu/UiSideMenuItemContent.vue.d.ts +43 -0
- package/dist/types/src/components/UiSideMenu/UiSideMenuTop.vue.d.ts +7 -0
- package/dist/types/src/components/UiSideMenu/injection.d.ts +7 -0
- package/dist/types/src/components/UiSideMenu/types.d.ts +39 -0
- package/dist/types/src/components/UiSideMenu/useLabelHidden.d.ts +2 -0
- package/dist/types/src/components/UiSideMenu/useSideMenuLayout.d.ts +7 -0
- package/dist/types/src/components/UiStepper/UiStepper.vue.d.ts +18 -0
- package/dist/types/src/components/UiStepper/UiStepperDescription.vue.d.ts +14 -0
- package/dist/types/src/components/UiStepper/UiStepperIndicator.vue.d.ts +20 -0
- package/dist/types/src/components/UiStepper/UiStepperItem.vue.d.ts +19 -0
- package/dist/types/src/components/UiStepper/UiStepperSeparator.vue.d.ts +10 -0
- package/dist/types/src/components/UiStepper/UiStepperTitle.vue.d.ts +14 -0
- package/dist/types/src/components/UiStepper/index.d.ts +7 -0
- package/dist/types/src/components/UiTable/UiTable.vue.d.ts +20 -0
- package/dist/types/src/components/UiTable/UiTableBody.vue.d.ts +13 -0
- package/dist/types/src/components/UiTable/UiTableCell.vue.d.ts +13 -0
- package/dist/types/src/components/UiTable/UiTableHeader.vue.d.ts +13 -0
- package/dist/types/src/components/UiTable/UiTableHeaderCell.vue.d.ts +13 -0
- package/dist/types/src/components/UiTable/UiTableRow.vue.d.ts +16 -0
- package/dist/types/src/components/UiTable/index.d.ts +6 -0
- package/dist/types/src/components/UiTabs/UiTabs.vue.d.ts +37 -0
- package/dist/types/src/components/UiTabs/index.d.ts +2 -0
- package/dist/types/src/components/UiTag/UiTag.vue.d.ts +43 -0
- package/dist/types/src/components/UiTag/index.d.ts +1 -0
- package/dist/types/src/components/UiTextField/UiTextField.vue.d.ts +65 -0
- package/dist/types/src/components/UiTextField/index.d.ts +2 -0
- package/dist/types/src/components/UiTextField/types.d.ts +2 -0
- package/dist/types/src/components/UiTimeline/UiTimeline.vue.d.ts +19 -0
- package/dist/types/src/components/UiTimeline/UiTimelineItem.vue.d.ts +28 -0
- package/dist/types/src/components/UiTimeline/index.d.ts +2 -0
- package/dist/types/src/components/UiTooltip/UiTooltip.vue.d.ts +41 -0
- package/dist/types/src/components/UiTooltip/UiTooltipContent.vue.d.ts +54 -0
- package/dist/types/src/components/UiTooltip/UiTooltipProvider.vue.d.ts +17 -0
- package/dist/types/src/components/UiTooltip/UiTooltipTrigger.vue.d.ts +14 -0
- package/dist/types/src/components/UiTooltip/index.d.ts +4 -0
- package/dist/types/src/composables/useButtonStyles.d.ts +20 -0
- package/dist/types/src/composables/useMobileMenu.d.ts +11 -0
- package/dist/types/src/composables/useThemeAndModes.d.ts +34 -0
- package/dist/types/src/constants/index.d.ts +2 -0
- package/dist/types/src/constants/sizes.d.ts +2 -0
- package/dist/types/src/constants/themes.d.ts +22 -0
- package/dist/types/src/integrations/index.d.ts +1 -0
- package/dist/types/src/layouts/index.d.ts +2 -0
- package/dist/types/src/mixins/DynamicAction.d.ts +30 -0
- package/dist/types/src/primitives.d.ts +6 -0
- package/dist/types/src/theme.d.ts +1 -0
- package/dist/types/src/utils/a11y.d.ts +2 -0
- package/dist/types/src/utils/breakpoints.d.ts +9 -0
- package/dist/types/src/utils/bus.d.ts +2 -0
- package/dist/types/src/utils/clipboard.d.ts +4 -0
- package/dist/types/src/utils/devices.d.ts +19 -0
- package/dist/types/src/utils/elements.d.ts +1 -0
- package/dist/types/src/utils/index.d.ts +9 -0
- package/dist/types/src/utils/numbers.d.ts +30 -0
- package/dist/types/src/utils/responsive.d.ts +5 -0
- package/dist/types/src/utils/responsive.types.d.ts +12 -0
- package/dist/types/src/utils/router.d.ts +1 -0
- package/dist/types/src/utils/slot.d.ts +8 -0
- package/dist/types/src/utils/stack-view.d.ts +10 -0
- package/dist/types/src/utils/uid.d.ts +1 -0
- package/dist/types/style.d.ts +1 -0
- package/dist/ui-vue.css +1 -0
- package/dist/useThemeAndModes-DY5SDC0a.mjs +109 -0
- package/dist/utils.mjs +146 -0
- package/index.d.ts +88 -2
- package/index.js +169 -16
- package/integrations.d.ts +10 -0
- package/package.json +130 -63
- package/src/components/Toast/LayoutToasts.vue +63 -0
- package/src/components/Toast/ToastMessage.vue +208 -0
- package/src/components/Toast/toastDSV2.ts +151 -0
- package/src/components/UiActionBar/UiActionBar.vue +86 -0
- package/src/components/UiActionBar/UiActionBarItem.vue +179 -0
- package/src/components/UiActionBar/UiActionBarSeparator.vue +18 -0
- package/src/components/UiActionBar/index.ts +4 -0
- package/src/components/UiActionBar/types.ts +24 -0
- package/src/components/UiAnimatedLogo/UiAnimatedLogo.vue +47 -0
- package/src/components/UiAnimatedLogo/animations-links.ts +6 -0
- package/src/components/UiAvatar/UiAvatar.vue +186 -0
- package/src/components/UiAvatar/index.js +1 -0
- package/src/components/UiAvatarList/UiAvatarList.vue +109 -0
- package/src/components/UiAvatarList/index.js +1 -0
- package/src/components/UiBadge/UiBadge.vue +161 -0
- package/src/components/UiBadge/index.ts +2 -0
- package/src/components/UiBanner/UiBanner.vue +363 -0
- package/src/components/UiBanner/index.ts +2 -0
- package/src/components/UiBreadcrumb/UiBreadcrumb.vue +93 -0
- package/src/components/UiBreadcrumb/index.ts +2 -0
- package/src/components/UiButton/UiButton.vue +322 -0
- package/src/components/UiButtonGroup/UiButtonGroup.vue +198 -0
- package/src/components/UiButtonGroup/UiButtonGroupItem.vue +123 -0
- package/src/components/UiButtonGroup/index.ts +3 -0
- package/src/components/UiButtonGroup/types.ts +24 -0
- package/src/components/UiCard/UiCard.vue +112 -0
- package/src/components/UiCarousel/UiCarousel.vue +215 -0
- package/src/components/UiCarousel/index.ts +2 -0
- package/src/components/UiColorField/UiColorField.vue +158 -0
- package/src/components/UiColorField/index.ts +2 -0
- package/src/components/UiColorField/types.ts +30 -0
- package/src/components/UiColorPicker/UiColorPicker.vue +487 -0
- package/src/components/UiColorPicker/index.ts +2 -0
- package/src/components/UiColorPicker/types.ts +103 -0
- package/src/components/UiDialog/MarketplaceHeaderExample.vue +217 -0
- package/src/components/UiDialog/UiDialog.md +97 -0
- package/src/components/UiDialog/UiDialog.vue +16 -0
- package/src/components/UiDialog/UiDialogClose.vue +29 -0
- package/src/components/UiDialog/UiDialogContent.vue +238 -0
- package/src/components/UiDialog/UiDialogFooter.vue +9 -0
- package/src/components/UiDialog/UiDialogTrigger.vue +12 -0
- package/src/components/UiDialog/index.ts +18 -0
- package/src/components/UiDropdown/UiDropdown.vue +48 -0
- package/src/components/UiDropdown/UiDropdownContent.vue +72 -0
- package/src/components/UiDropdown/UiDropdownItem.vue +75 -0
- package/src/components/UiDropdown/UiDropdownSeparator.vue +7 -0
- package/src/components/UiDropdown/UiDropdownTrigger.vue +239 -0
- package/src/components/UiDropdown/context.ts +9 -0
- package/src/components/UiDropdown/index.ts +21 -0
- package/src/components/UiEmptyState/UiEmptyState.vue +80 -0
- package/src/components/UiFieldWrapper/UiFieldWrapper.vue +81 -0
- package/src/components/UiFieldWrapper/index.ts +1 -0
- package/src/components/UiForm/UiFormField.types.ts +24 -0
- package/src/components/UiForm/UiFormField.vue +66 -0
- package/src/components/UiForm/index.ts +3 -0
- package/src/components/UiHorizontalSeparator/UiHorizontalSeparator.vue +28 -0
- package/src/components/UiInputCheckbox/UiInputCheckbox.vue +481 -0
- package/src/components/UiInputCheckbox/index.ts +2 -0
- package/src/components/UiInputCheckbox/types.ts +1 -0
- package/src/components/UiInputSelect/UiInputSelect.vue +166 -0
- package/src/components/UiInputSelect/index.ts +2 -0
- package/src/components/UiInputSelect/types.ts +1 -0
- package/src/components/UiInputTextarea/UiInputTextarea.vue +219 -0
- package/src/components/UiInputTextarea/index.ts +2 -0
- package/src/components/UiInputTextarea/types.ts +1 -0
- package/src/components/UiLabel/UiLabel.vue +36 -0
- package/src/components/UiList/UiList.vue +45 -0
- package/src/components/UiListItem/UiListItem.vue +108 -0
- package/src/components/UiLoader/UiLoader.vue +45 -0
- package/src/components/UiLogo/UiLogo.vue +99 -0
- package/src/components/UiLogo/variants/PulseVariant.vue +51 -0
- package/src/components/UiLogo/variants/TornadoVariant.vue +147 -0
- package/src/components/UiMenu/UiMenu.vue +15 -0
- package/src/components/UiMenu/UiMenuContent.vue +25 -0
- package/src/components/UiMenu/UiMenuGroup.vue +19 -0
- package/src/components/UiMenu/UiMenuItem.vue +18 -0
- package/src/components/UiMenu/UiMenuLabel.vue +9 -0
- package/src/components/UiMenu/UiMenuSeparator.vue +9 -0
- package/src/components/UiMenu/UiMenuSub.vue +15 -0
- package/src/components/UiMenu/UiMenuSubContent.vue +23 -0
- package/src/components/UiMenu/UiMenuSubTrigger.vue +17 -0
- package/src/components/UiMenu/UiMenuTrigger.vue +13 -0
- package/src/components/UiMenu/index.ts +10 -0
- package/src/components/UiPage/UiPage.vue +201 -0
- package/src/components/UiPageHeader/UiPageHeader.vue +128 -0
- package/src/components/UiPopover/UiPopover.vue +16 -0
- package/src/components/UiPopover/UiPopoverAnchor.vue +12 -0
- package/src/components/UiPopover/UiPopoverContent.vue +26 -0
- package/src/components/UiPopover/UiPopoverTrigger.vue +19 -0
- package/src/components/UiProgress/UiProgress.vue +92 -0
- package/src/components/UiProgress/index.ts +2 -0
- package/src/components/UiProgress/types.ts +5 -0
- package/src/components/UiRoomButton/UiRoomButton.vue +240 -0
- package/src/components/UiShell/UiShell.vue +88 -0
- package/src/components/UiSideMenu/UiSideMenu.vue +513 -0
- package/src/components/UiSideMenu/UiSideMenuBottom.vue +27 -0
- package/src/components/UiSideMenu/UiSideMenuItem.vue +102 -0
- package/src/components/UiSideMenu/UiSideMenuItemContent.vue +172 -0
- package/src/components/UiSideMenu/UiSideMenuTop.vue +29 -0
- package/src/components/UiSideMenu/injection.ts +9 -0
- package/src/components/UiSideMenu/types.ts +41 -0
- package/src/components/UiSideMenu/useLabelHidden.ts +33 -0
- package/src/components/UiSideMenu/useSideMenuLayout.ts +12 -0
- package/src/components/UiStepper/UiStepper.vue +40 -0
- package/src/components/UiStepper/UiStepperDescription.vue +27 -0
- package/src/components/UiStepper/UiStepperIndicator.vue +93 -0
- package/src/components/UiStepper/UiStepperItem.vue +30 -0
- package/src/components/UiStepper/UiStepperSeparator.vue +49 -0
- package/src/components/UiStepper/UiStepperTitle.vue +24 -0
- package/src/components/UiStepper/index.ts +17 -0
- package/src/components/UiTable/UiTable.vue +24 -0
- package/src/components/UiTable/UiTableBody.vue +5 -0
- package/src/components/UiTable/UiTableCell.vue +26 -0
- package/src/components/UiTable/UiTableHeader.vue +17 -0
- package/src/components/UiTable/UiTableHeaderCell.vue +19 -0
- package/src/components/UiTable/UiTableRow.vue +27 -0
- package/src/components/UiTable/index.ts +6 -0
- package/src/components/UiTabs/UiTabs.vue +218 -0
- package/src/components/UiTabs/index.ts +5 -0
- package/src/components/UiTag/UiTag.vue +187 -0
- package/src/components/UiTag/index.js +1 -0
- package/src/components/UiTextField/UiTextField.vue +370 -0
- package/src/components/UiTextField/index.ts +2 -0
- package/src/components/UiTextField/types.ts +2 -0
- package/src/components/UiTimeline/README.md +169 -0
- package/src/components/UiTimeline/UiTimeline.vue +58 -0
- package/src/components/UiTimeline/UiTimelineItem.vue +141 -0
- package/src/components/UiTimeline/index.ts +2 -0
- package/src/components/UiTooltip/UiTooltip.vue +68 -0
- package/src/components/UiTooltip/UiTooltipContent.vue +86 -0
- package/src/components/UiTooltip/UiTooltipProvider.vue +15 -0
- package/src/components/UiTooltip/UiTooltipTrigger.vue +19 -0
- package/src/components/UiTooltip/index.js +4 -0
- package/src/composables/useButtonStyles.ts +242 -0
- package/src/composables/useMobileMenu.ts +57 -0
- package/src/composables/useThemeAndModes.ts +225 -0
- package/src/constants/index.ts +2 -0
- package/src/constants/sizes.ts +2 -0
- package/src/constants/themes.ts +34 -0
- package/src/css/{body.postcss → body.css} +3 -2
- package/src/css/reka-animations.css +209 -0
- package/src/css/{transitions.postcss → transitions.css} +12 -5
- package/src/global.d.ts +181 -0
- package/src/integrations/index.js +1 -0
- package/src/layouts/index.js +5 -0
- package/src/mixins/DynamicAction.js +5 -3
- package/src/primitives.ts +6 -0
- package/src/theme.ts +1 -0
- package/src/utils/a11y.ts +8 -0
- package/src/utils/{breakpoints.js → breakpoints.ts} +1 -0
- package/src/utils/clipboard.js +81 -14
- package/src/utils/devices.js +0 -3
- package/src/utils/index.js +2 -1
- package/src/utils/numbers.ts +61 -0
- package/src/utils/responsive.types.ts +12 -0
- package/src/utils/{slot.js → slot.ts} +18 -1
- package/style.js +3 -12
- package/theme.d.ts +1 -0
- package/.env +0 -1
- package/.eslintignore +0 -4
- package/.eslintrc.js +0 -49
- package/.pkg +0 -11
- package/babel.config.js +0 -5
- package/build/Dockerfile +0 -31
- package/ci/ci.yml +0 -54
- package/components-webpack.js +0 -29
- package/dist/environment-da321c85.mjs +0 -1656
- package/dist/style.css +0 -1
- package/plugins.js +0 -17
- package/postcss.config.js +0 -1
- package/src/components/BaseAutocomplete/BaseAutocomplete.spec.js +0 -506
- package/src/components/BaseAutocomplete/BaseAutocomplete.stories.js +0 -184
- package/src/components/BaseAutocomplete/BaseAutocomplete.vue +0 -431
- package/src/components/BaseBanner/BaseBanner.spec.js +0 -32
- package/src/components/BaseBanner/BaseBanner.stories.js +0 -133
- package/src/components/BaseBanner/BaseBanner.vue +0 -229
- package/src/components/BaseButton/BaseButton.spec.js +0 -98
- package/src/components/BaseButton/BaseButton.stories.js +0 -300
- package/src/components/BaseButton/BaseButton.vue +0 -193
- package/src/components/BaseButton/__snapshots__/BaseButton.spec.js.snap +0 -37
- package/src/components/BaseButton/__snapshots__/BaseButton.spec.js.snap.old +0 -31
- package/src/components/BaseCheckbox/BaseCheckbox.stories.js +0 -157
- package/src/components/BaseCheckbox/BaseCheckbox.vue +0 -180
- package/src/components/BaseDropdownMenu/BaseDropdownMenu.stories.js +0 -84
- package/src/components/BaseDropdownMenu/BaseDropdownMenu.vue +0 -251
- package/src/components/BaseDropdownMenu/BaseDropdownMenuButton.vue +0 -26
- package/src/components/BaseDropdownMenu/BaseDropdownMenuDivider.vue +0 -10
- package/src/components/BaseDropdownMenu/BaseDropdownMenuItem.vue +0 -206
- package/src/components/BaseDropdownMenu/BaseDropdownMenuSearch.vue +0 -49
- package/src/components/BaseDropdownMenu/BaseDropdownMenuTitle.vue +0 -26
- package/src/components/BaseModal/BaseModal.stories.js +0 -155
- package/src/components/BaseModal/BaseModal.vue +0 -187
- package/src/components/BaseModal/BaseModalContent.vue +0 -166
- package/src/components/BaseModal/BaseModalContentOld.vue +0 -242
- package/src/components/BaseRadio/BaseRadio.stories.js +0 -164
- package/src/components/BaseRadio/BaseRadio.vue +0 -153
- package/src/components/BaseRating/BaseRating.spec.js +0 -46
- package/src/components/BaseRating/BaseRating.stories.js +0 -46
- package/src/components/BaseRating/BaseRating.vue +0 -119
- package/src/components/BaseSelect/BaseSelect.stories.js +0 -177
- package/src/components/BaseSelect/BaseSelect.vue +0 -443
- package/src/components/BaseSelect/BaseSelectGroup.vue +0 -34
- package/src/components/BaseSelect/BaseSelectOption.vue +0 -219
- package/src/components/BaseSwitch/BaseSwitch.stories.js +0 -44
- package/src/components/BaseSwitch/BaseSwitch.vue +0 -114
- package/src/components/BaseTag/BaseTag.stories.js +0 -123
- package/src/components/BaseTag/BaseTag.vue +0 -244
- package/src/css/button.postcss +0 -363
- package/src/css/checkbox-radio.postcss +0 -188
- package/src/css/icon.postcss +0 -9
- package/src/css/loader.postcss +0 -120
- package/src/css/popper.postcss +0 -161
- package/src/css/tailwind-utilities.postcss +0 -1
- package/src/css/tailwind.postcss +0 -2
- package/style-postcss.d.ts +0 -3
- package/style-postcss.js +0 -2
- package/tailwind.config.base.cjs +0 -88
- package/tailwind.config.js +0 -9
- package/tsconfig.check.json +0 -13
- package/tsconfig.json +0 -66
- package/vite.config.js +0 -43
- package/vitest.setup.js +0 -26
|
@@ -0,0 +1,487 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { computed, ref, watch } from 'vue'
|
|
3
|
+
import {
|
|
4
|
+
ColorAreaRoot,
|
|
5
|
+
ColorAreaArea,
|
|
6
|
+
ColorAreaThumb,
|
|
7
|
+
ColorSliderRoot,
|
|
8
|
+
ColorSliderTrack,
|
|
9
|
+
ColorSliderThumb,
|
|
10
|
+
ColorFieldRoot,
|
|
11
|
+
ColorFieldInput,
|
|
12
|
+
ColorSwatch,
|
|
13
|
+
ColorSwatchPickerRoot,
|
|
14
|
+
ColorSwatchPickerItem,
|
|
15
|
+
ColorSwatchPickerItemSwatch,
|
|
16
|
+
Label,
|
|
17
|
+
colorToHex,
|
|
18
|
+
colorToString,
|
|
19
|
+
convertToHsb,
|
|
20
|
+
convertToHsl,
|
|
21
|
+
convertToRgb,
|
|
22
|
+
isValidColor,
|
|
23
|
+
normalizeColor,
|
|
24
|
+
useId,
|
|
25
|
+
} from 'reka-ui'
|
|
26
|
+
import type { Color } from 'reka-ui'
|
|
27
|
+
import { UiDropdown, UiDropdownTrigger, UiDropdownContent, UiDropdownItem } from '../UiDropdown'
|
|
28
|
+
import type { ColorFormat, UiColorPickerPreset, UiColorPickerProps, UiColorPickerSwatchSize } from './types'
|
|
29
|
+
|
|
30
|
+
const props = withDefaults(defineProps<UiColorPickerProps>(), {
|
|
31
|
+
modelValue: undefined,
|
|
32
|
+
color: undefined,
|
|
33
|
+
variant: 'default',
|
|
34
|
+
modes: () => ['hex', 'rgb', 'hsl', 'hsb'],
|
|
35
|
+
outputFormat: 'auto',
|
|
36
|
+
presetConfig: undefined,
|
|
37
|
+
selectedPresetValue: undefined,
|
|
38
|
+
showAlpha: true,
|
|
39
|
+
disabled: false,
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
// only used when the picker initialised with no color prop and modelValue is invalid or missing
|
|
43
|
+
const DEFAULT_HEX = '#0B42C3'
|
|
44
|
+
const presetsLabelId = useId()
|
|
45
|
+
const fieldId = useId()
|
|
46
|
+
|
|
47
|
+
const presets = computed(() => props.presetConfig?.presets)
|
|
48
|
+
// null = heading hidden (the listbox falls back to a direct aria-label)
|
|
49
|
+
const presetsLabel = computed<string | null>(() => {
|
|
50
|
+
if (props.presetConfig?.label === null) return null
|
|
51
|
+
return props.presetConfig?.label ?? 'Presets'
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
// Preset selector swatch sizes; the selection check icon scales to half the swatch.
|
|
55
|
+
// maxPerRow is how many swatches (at that size + gap) fit the panel's content width.
|
|
56
|
+
const SWATCH_SIZE_CLASSES: Record<UiColorPickerSwatchSize, { swatch: string; swatchPickerList: string; indicatorWrapper: string; indicator: string; maxPerRow: number }> = {
|
|
57
|
+
sm: { swatch: 'size-6', swatchPickerList: 'gap-2', indicatorWrapper: 'ring-2', indicator: 'h-3 w-3', maxPerRow: 8 },
|
|
58
|
+
lg: { swatch: 'size-12', swatchPickerList: 'gap-4', indicatorWrapper: 'ring-4', indicator: 'h-4 w-4', maxPerRow: 4 },
|
|
59
|
+
}
|
|
60
|
+
const swatchSizeClasses = computed(() => SWATCH_SIZE_CLASSES[props.presetConfig?.swatchSize ?? 'lg'])
|
|
61
|
+
|
|
62
|
+
// Balanced column count: distribute presets over the fewest rows the cap
|
|
63
|
+
// allows, evenly (6 = 3+3, 7 = 4+3).
|
|
64
|
+
// Used for the swatch grid's `grid-template-columns`.
|
|
65
|
+
const presetColumns = computed(() => {
|
|
66
|
+
const count = presets.value?.length ?? 0
|
|
67
|
+
if (count === 0) return 1
|
|
68
|
+
const rows = Math.ceil(count / swatchSizeClasses.value.maxPerRow)
|
|
69
|
+
return Math.ceil(count / rows)
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
const emit = defineEmits<{
|
|
73
|
+
/**
|
|
74
|
+
* Value in the currently-selected output format (e.g. '#0B42C3', 'rgb(...)')
|
|
75
|
+
* 'auto' output format emits the value in the currently-selected display mode (e.g. hex/rgb/hsl/hsb).
|
|
76
|
+
* else the value is emitted in the specified output format (e.g. hex/rgb/hsl/hsb) regardless of the display mode.
|
|
77
|
+
*/
|
|
78
|
+
'update:modelValue': [value: string]
|
|
79
|
+
'update:color': [color: Color]
|
|
80
|
+
/**
|
|
81
|
+
* Identity of the selected preset (`preset.value`), for
|
|
82
|
+
* `v-model:selected-preset-value`. Emitted only when the selected preset
|
|
83
|
+
* declares a `value`. Unlike the color emits, this survives duplicate-hex
|
|
84
|
+
* presets: it reports the preset the user actually picked.
|
|
85
|
+
*/
|
|
86
|
+
'update:selectedPresetValue': [value: string]
|
|
87
|
+
/** gets emitted when a value is committed (e.g., after dragging a slider or selecting a preset) */
|
|
88
|
+
'change': [value: string]
|
|
89
|
+
}>()
|
|
90
|
+
|
|
91
|
+
function toHsb(value: string | Color): Color {
|
|
92
|
+
return convertToHsb(normalizeColor(value))
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const MODE_LABELS: Record<ColorFormat, string> = {
|
|
96
|
+
hex: 'HEX',
|
|
97
|
+
rgb: 'RGB',
|
|
98
|
+
hsl: 'HSL',
|
|
99
|
+
hsb: 'HSB',
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
interface ChannelDef {
|
|
103
|
+
channel: 'red' | 'green' | 'blue' | 'hue' | 'saturation' | 'lightness' | 'brightness'
|
|
104
|
+
/** Accessible name for the channel input (no visible label is rendered). */
|
|
105
|
+
label: string
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Each non-hex mode is composed from one reka ColorFieldRoot per channel.
|
|
109
|
+
const MODE_CHANNELS: Record<Exclude<ColorFormat, 'hex'>, ChannelDef[]> = {
|
|
110
|
+
rgb: [
|
|
111
|
+
{ channel: 'red', label: 'Red' },
|
|
112
|
+
{ channel: 'green', label: 'Green' },
|
|
113
|
+
{ channel: 'blue', label: 'Blue' },
|
|
114
|
+
],
|
|
115
|
+
hsl: [
|
|
116
|
+
{ channel: 'hue', label: 'Hue' },
|
|
117
|
+
{ channel: 'saturation', label: 'Saturation' },
|
|
118
|
+
{ channel: 'lightness', label: 'Lightness' },
|
|
119
|
+
],
|
|
120
|
+
hsb: [
|
|
121
|
+
{ channel: 'hue', label: 'Hue' },
|
|
122
|
+
{ channel: 'saturation', label: 'Saturation' },
|
|
123
|
+
{ channel: 'brightness', label: 'Brightness' },
|
|
124
|
+
],
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Shared styling for each bordered value box (the hex field and each channel field).
|
|
128
|
+
// The mode switcher is a separate bordered box (the dropdown trigger draws its own).
|
|
129
|
+
const FIELD_BOX_CLASS =
|
|
130
|
+
'flex h-full items-center rounded-lg border border-solid border-borders-neutral-strong bg-actions-neutral-idle-alpha-light transition-all focus-within:border-actions-primary-idle-alpha-strong'
|
|
131
|
+
|
|
132
|
+
// Detect a value's mode. reka represents hex as space 'rgb', so hex must be
|
|
133
|
+
// matched on the '#' prefix; rgb/hsl/hsb (and hsv→hsb) come from normalizeColor.
|
|
134
|
+
function detectMode(value: string | undefined): ColorFormat | undefined {
|
|
135
|
+
if (!value || !isValidColor(value)) return undefined
|
|
136
|
+
if (value.trim().startsWith('#')) return 'hex'
|
|
137
|
+
return normalizeColor(value).space
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const detectedMode = detectMode(props.modelValue)
|
|
141
|
+
const colorMode = ref<ColorFormat>(
|
|
142
|
+
detectedMode && props.modes.includes(detectedMode) ? detectedMode : props.modes[0],
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
// Format the emitted value uses: the selected display mode when 'auto',
|
|
146
|
+
// otherwise the fixed outputFormat (independent of `modes`).
|
|
147
|
+
const outputMode = computed<ColorFormat>(() =>
|
|
148
|
+
props.outputFormat === 'auto' ? colorMode.value : props.outputFormat,
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
const showSwitcher = computed(() => props.modes.length > 1)
|
|
152
|
+
const showCustomControls = computed(() => props.variant !== 'swatch-only')
|
|
153
|
+
const activeChannels = computed<ChannelDef[]>(() =>
|
|
154
|
+
colorMode.value === 'hex' ? [] : MODE_CHANNELS[colorMode.value],
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
// The color in the active mode's space. Required so saturation/lightness vs
|
|
158
|
+
// brightness resolve correctly: reka's getChannelValue reads the stored channel
|
|
159
|
+
// for whichever space the color is in (HSL saturation ≠ HSB saturation).
|
|
160
|
+
const channelModel = computed<Color>(() => {
|
|
161
|
+
switch (colorMode.value) {
|
|
162
|
+
case 'rgb': return convertToRgb(internalColor.value)
|
|
163
|
+
case 'hsl': return convertToHsl(internalColor.value)
|
|
164
|
+
case 'hsb': return convertToHsb(internalColor.value)
|
|
165
|
+
default: return internalColor.value
|
|
166
|
+
}
|
|
167
|
+
})
|
|
168
|
+
|
|
169
|
+
// HSB color space because that corresponds to what the color area uses
|
|
170
|
+
const internalColor = ref<Color>(
|
|
171
|
+
toHsb(
|
|
172
|
+
props.color ??
|
|
173
|
+
(props.modelValue && isValidColor(props.modelValue) ? props.modelValue : DEFAULT_HEX),
|
|
174
|
+
),
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
// This is used to determine if a preset is selected so we can show the indicator
|
|
178
|
+
// instead of letting the ColorSwatchPicker component handle it with its internal state to allow
|
|
179
|
+
// keyboard navigation of the picker.
|
|
180
|
+
// This is because the swatch picker is a listbox which will re-focus the matching swatch/first
|
|
181
|
+
// swatch whenever the model value is updated programatically, so we leave it uncontrolled
|
|
182
|
+
// (it has a watch on the model value which does this for programatic updates)
|
|
183
|
+
const currentHex = computed(() => colorToHex(internalColor.value).toLowerCase())
|
|
184
|
+
function isPresetActive(preset: UiColorPickerPreset): boolean {
|
|
185
|
+
// Controlled identity selection (selectedPresetValue provided, incl. null)
|
|
186
|
+
// never falls back to color matching — duplicate-hex presets must not both
|
|
187
|
+
// light up, and null must mark none.
|
|
188
|
+
if (props.selectedPresetValue !== undefined) {
|
|
189
|
+
return preset.value !== undefined && preset.value === props.selectedPresetValue
|
|
190
|
+
}
|
|
191
|
+
return preset.color.toLowerCase() === currentHex.value
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function emitModelValue(): void {
|
|
195
|
+
emit('update:modelValue', colorToString(internalColor.value, outputMode.value))
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function onColorUpdate(next: Color): void {
|
|
199
|
+
// Field edits arrive in the active mode's space; normalize back to canonical HSB
|
|
200
|
+
// so the area + hue/alpha sliders (all hsb) stay correct.
|
|
201
|
+
const hsbNextColor = toHsb(next)
|
|
202
|
+
internalColor.value = hsbNextColor
|
|
203
|
+
emit('update:color', hsbNextColor)
|
|
204
|
+
emitModelValue()
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function onCommit(): void {
|
|
208
|
+
emit('change', colorToString(internalColor.value, outputMode.value))
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Selection is handled per item via its `select` event (fired for click, Space
|
|
212
|
+
// and Enter): the v-for closure carries the exact preset, so duplicate-hex
|
|
213
|
+
// presets stay distinguishable, and the listbox model's update — which reka
|
|
214
|
+
// double-emits per selection — is deliberately not listened to.
|
|
215
|
+
// reka fires `select` before its own disabled check, so guard it here.
|
|
216
|
+
function onPresetSelect(preset: UiColorPickerPreset): void {
|
|
217
|
+
if (props.disabled) return
|
|
218
|
+
onColorUpdate(toHsb(preset.color))
|
|
219
|
+
if (preset.value !== undefined) emit('update:selectedPresetValue', preset.value)
|
|
220
|
+
onCommit()
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Re-emit modelValue in the new format when the user switches modes (same color).
|
|
224
|
+
// Only relevant while the output follows the display mode ('auto'); with a fixed
|
|
225
|
+
// output format the emitted string is unchanged, so skip the redundant emit.
|
|
226
|
+
watch(colorMode, () => {
|
|
227
|
+
if (props.outputFormat === 'auto') emitModelValue()
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
watch(
|
|
231
|
+
() => props.modelValue,
|
|
232
|
+
(value) => {
|
|
233
|
+
if (!value || !isValidColor(value)) return
|
|
234
|
+
// Parse any supported format; guard against echoing our own emit and never
|
|
235
|
+
// re-select the mode (inference is initial-only).
|
|
236
|
+
const next = toHsb(value)
|
|
237
|
+
if (colorToHex(internalColor.value).toLowerCase() !== colorToHex(next).toLowerCase()) {
|
|
238
|
+
internalColor.value = next
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
watch(
|
|
244
|
+
() => props.color,
|
|
245
|
+
(color) => {
|
|
246
|
+
if (!color) return
|
|
247
|
+
const next = toHsb(color)
|
|
248
|
+
// Guard against echoing our own emit (compare normalized hex).
|
|
249
|
+
if (colorToHex(internalColor.value).toLowerCase() !== colorToHex(next).toLowerCase()) {
|
|
250
|
+
internalColor.value = next
|
|
251
|
+
}
|
|
252
|
+
},
|
|
253
|
+
)
|
|
254
|
+
</script>
|
|
255
|
+
|
|
256
|
+
<template>
|
|
257
|
+
<!-- Fixed width sized for the color area/sliders; swatch-only has none, so it hugs the swatch grid -->
|
|
258
|
+
<div
|
|
259
|
+
class="flex flex-col gap-4 rounded-2xl bg-surface-neutral-bg-main p-4 shadow-lg"
|
|
260
|
+
:class="showCustomControls ? 'w-[284px]' : 'w-fit'"
|
|
261
|
+
>
|
|
262
|
+
<ColorAreaRoot
|
|
263
|
+
v-if="showCustomControls"
|
|
264
|
+
v-slot="{ style }"
|
|
265
|
+
data-testid="ui-color-picker-area"
|
|
266
|
+
:model-value="internalColor"
|
|
267
|
+
:disabled="disabled"
|
|
268
|
+
color-space="hsb"
|
|
269
|
+
x-channel="saturation"
|
|
270
|
+
y-channel="brightness"
|
|
271
|
+
class="relative h-[189px] w-full rounded-md"
|
|
272
|
+
:class="{ 'cursor-not-allowed': disabled }"
|
|
273
|
+
@update:color="onColorUpdate"
|
|
274
|
+
@change-end="onCommit"
|
|
275
|
+
>
|
|
276
|
+
<ColorAreaArea
|
|
277
|
+
:style="style"
|
|
278
|
+
class="absolute inset-0 rounded-md"
|
|
279
|
+
>
|
|
280
|
+
<ColorAreaThumb class="group size-6 rounded-full border-4 border-actions-neutral-invert-idle transition-shadow hover:cursor-pointer hover:shadow-md">
|
|
281
|
+
<span class="pointer-events-none absolute -inset-1 rounded-full bg-actions-primary-hover-overlay opacity-0 transition-opacity group-hover:opacity-100" />
|
|
282
|
+
</ColorAreaThumb>
|
|
283
|
+
</ColorAreaArea>
|
|
284
|
+
</ColorAreaRoot>
|
|
285
|
+
|
|
286
|
+
<ColorSliderRoot
|
|
287
|
+
v-if="showCustomControls"
|
|
288
|
+
data-testid="ui-color-picker-hue"
|
|
289
|
+
:model-value="internalColor"
|
|
290
|
+
:disabled="disabled"
|
|
291
|
+
color-space="hsb"
|
|
292
|
+
channel="hue"
|
|
293
|
+
class="relative flex h-6 w-full items-center"
|
|
294
|
+
:class="{ 'cursor-not-allowed': disabled }"
|
|
295
|
+
@update:color="onColorUpdate"
|
|
296
|
+
@change-end="onCommit"
|
|
297
|
+
>
|
|
298
|
+
<ColorSliderTrack class="h-1 w-full rounded-full" />
|
|
299
|
+
<ColorSliderThumb class="group size-6 rounded-full border-4 border-actions-primary-idle bg-actions-neutral-invert-idle transition-shadow hover:cursor-pointer hover:shadow-md">
|
|
300
|
+
<span class="pointer-events-none absolute -inset-1 rounded-full bg-actions-primary-hover-overlay opacity-0 transition-opacity group-hover:opacity-100" />
|
|
301
|
+
</ColorSliderThumb>
|
|
302
|
+
</ColorSliderRoot>
|
|
303
|
+
|
|
304
|
+
<ColorSliderRoot
|
|
305
|
+
v-if="showCustomControls && showAlpha"
|
|
306
|
+
data-testid="ui-color-picker-alpha"
|
|
307
|
+
:model-value="internalColor"
|
|
308
|
+
:disabled="disabled"
|
|
309
|
+
color-space="hsb"
|
|
310
|
+
channel="alpha"
|
|
311
|
+
class="relative flex h-6 w-full items-center"
|
|
312
|
+
:class="{ 'cursor-not-allowed': disabled }"
|
|
313
|
+
@update:color="onColorUpdate"
|
|
314
|
+
@change-end="onCommit"
|
|
315
|
+
>
|
|
316
|
+
<ColorSliderTrack class="h-1 w-full rounded-full" />
|
|
317
|
+
<ColorSliderThumb class="group size-6 rounded-full border-4 border-actions-primary-idle bg-actions-neutral-invert-idle transition-shadow hover:cursor-pointer hover:shadow-md">
|
|
318
|
+
<span class="pointer-events-none absolute -inset-1 rounded-full bg-actions-primary-hover-overlay opacity-0 transition-opacity group-hover:opacity-100" />
|
|
319
|
+
</ColorSliderThumb>
|
|
320
|
+
</ColorSliderRoot>
|
|
321
|
+
|
|
322
|
+
<div
|
|
323
|
+
v-if="showCustomControls"
|
|
324
|
+
data-testid="ui-color-picker-field"
|
|
325
|
+
class="flex h-10 w-full items-center gap-2"
|
|
326
|
+
:class="{ 'cursor-not-allowed opacity-50': disabled }"
|
|
327
|
+
>
|
|
328
|
+
<!-- Mode switcher — its own bordered box; hidden when only one mode is available -->
|
|
329
|
+
<div
|
|
330
|
+
v-if="showSwitcher"
|
|
331
|
+
class="h-full w-20 shrink-0"
|
|
332
|
+
>
|
|
333
|
+
<UiDropdown
|
|
334
|
+
v-model="colorMode"
|
|
335
|
+
:disabled="disabled"
|
|
336
|
+
>
|
|
337
|
+
<UiDropdownTrigger
|
|
338
|
+
size="md"
|
|
339
|
+
variant="secondary"
|
|
340
|
+
color="neutral"
|
|
341
|
+
aria-label="Color format"
|
|
342
|
+
/>
|
|
343
|
+
<UiDropdownContent>
|
|
344
|
+
<UiDropdownItem
|
|
345
|
+
v-for="mode in modes"
|
|
346
|
+
:key="mode"
|
|
347
|
+
:value="mode"
|
|
348
|
+
:title="MODE_LABELS[mode]"
|
|
349
|
+
/>
|
|
350
|
+
</UiDropdownContent>
|
|
351
|
+
</UiDropdown>
|
|
352
|
+
</div>
|
|
353
|
+
|
|
354
|
+
<!-- HEX: swatch + value in a single bordered box (swatch only in hex mode) -->
|
|
355
|
+
<ColorFieldRoot
|
|
356
|
+
v-if="colorMode === 'hex'"
|
|
357
|
+
:model-value="internalColor"
|
|
358
|
+
:disabled="disabled"
|
|
359
|
+
color-space="hsb"
|
|
360
|
+
:class="[FIELD_BOX_CLASS, 'min-w-0 flex-1 gap-1.5 px-3']"
|
|
361
|
+
@update:color="onColorUpdate"
|
|
362
|
+
>
|
|
363
|
+
<ColorSwatch
|
|
364
|
+
:color="internalColor"
|
|
365
|
+
class="size-4 shrink-0 rounded-[5px] border border-borders-neutral-light bg-(--reka-color-swatch-color)"
|
|
366
|
+
/>
|
|
367
|
+
<Label
|
|
368
|
+
:for="fieldId"
|
|
369
|
+
class="sr-only"
|
|
370
|
+
>
|
|
371
|
+
Hex color
|
|
372
|
+
</Label>
|
|
373
|
+
<ColorFieldInput
|
|
374
|
+
:id="fieldId"
|
|
375
|
+
class="h-full w-full min-w-0 bg-transparent text-content-text-regular-md text-text-neutral-base"
|
|
376
|
+
@blur="onCommit"
|
|
377
|
+
/>
|
|
378
|
+
</ColorFieldRoot>
|
|
379
|
+
|
|
380
|
+
<!-- RGB / HSL / HSB: each channel is its own bordered box (no visible label) -->
|
|
381
|
+
<template v-else>
|
|
382
|
+
<ColorFieldRoot
|
|
383
|
+
v-for="ch in activeChannels"
|
|
384
|
+
:key="ch.channel"
|
|
385
|
+
:model-value="channelModel"
|
|
386
|
+
:disabled="disabled"
|
|
387
|
+
:color-space="colorMode"
|
|
388
|
+
:channel="ch.channel"
|
|
389
|
+
:class="[FIELD_BOX_CLASS, 'min-w-0 flex-1 justify-center px-2']"
|
|
390
|
+
@update:color="onColorUpdate"
|
|
391
|
+
>
|
|
392
|
+
<ColorFieldInput
|
|
393
|
+
:id="`${fieldId}-${ch.channel}`"
|
|
394
|
+
:aria-label="ch.label"
|
|
395
|
+
class="h-full w-full min-w-0 bg-transparent text-center text-content-text-regular-md text-text-neutral-base"
|
|
396
|
+
@blur="onCommit"
|
|
397
|
+
/>
|
|
398
|
+
</ColorFieldRoot>
|
|
399
|
+
</template>
|
|
400
|
+
</div>
|
|
401
|
+
|
|
402
|
+
<div
|
|
403
|
+
v-if="presets?.length"
|
|
404
|
+
class="flex flex-col gap-4"
|
|
405
|
+
>
|
|
406
|
+
<label
|
|
407
|
+
v-if="presetsLabel !== null"
|
|
408
|
+
:id="presetsLabelId"
|
|
409
|
+
class="text-content-legends-bold-md text-text-neutral-tertiary"
|
|
410
|
+
>
|
|
411
|
+
{{ presetsLabel }}
|
|
412
|
+
</label>
|
|
413
|
+
<!-- uncontrolled on purpose; otherwise it would steal focus from the sliders when the internal color is updated with the preset color -->
|
|
414
|
+
<ColorSwatchPickerRoot
|
|
415
|
+
:aria-labelledby="presetsLabel !== null ? presetsLabelId : undefined"
|
|
416
|
+
:aria-label="presetsLabel === null ? 'Presets' : undefined"
|
|
417
|
+
:disabled="disabled"
|
|
418
|
+
class="grid justify-center"
|
|
419
|
+
:class="[swatchSizeClasses.swatchPickerList, { 'cursor-not-allowed': disabled }]"
|
|
420
|
+
:style="{ gridTemplateColumns: `repeat(${presetColumns}, max-content)` }"
|
|
421
|
+
>
|
|
422
|
+
<div
|
|
423
|
+
v-for="preset in presets"
|
|
424
|
+
:key="preset.value ?? preset.color"
|
|
425
|
+
class="relative flex"
|
|
426
|
+
:class="swatchSizeClasses.swatch"
|
|
427
|
+
>
|
|
428
|
+
<ColorSwatchPickerItem
|
|
429
|
+
:value="preset.color.toLowerCase()"
|
|
430
|
+
v-bind="preset.label ? { 'aria-label': preset.label } : {}"
|
|
431
|
+
class="group block size-full cursor-pointer rounded-full data-disabled:cursor-not-allowed border border-borders-neutral-light"
|
|
432
|
+
@select="onPresetSelect(preset)"
|
|
433
|
+
>
|
|
434
|
+
<span class="relative block size-full overflow-hidden rounded-full">
|
|
435
|
+
<span
|
|
436
|
+
v-if="preset.leftColor && preset.rightColor"
|
|
437
|
+
class="flex size-full"
|
|
438
|
+
>
|
|
439
|
+
<span
|
|
440
|
+
class="h-full w-1/2"
|
|
441
|
+
:style="{ backgroundColor: preset.leftColor }"
|
|
442
|
+
/>
|
|
443
|
+
<span
|
|
444
|
+
class="h-full w-1/2"
|
|
445
|
+
:style="{ backgroundColor: preset.rightColor }"
|
|
446
|
+
/>
|
|
447
|
+
</span>
|
|
448
|
+
<ColorSwatchPickerItemSwatch
|
|
449
|
+
v-else
|
|
450
|
+
class="size-full rounded-full bg-(--reka-color-swatch-color)"
|
|
451
|
+
/>
|
|
452
|
+
<!-- focus-visible instead of data-highlighted to identify the preset that is being keyboard focused
|
|
453
|
+
because the listbox highlights the first item on mount if there's no preset matching the current color -->
|
|
454
|
+
<span
|
|
455
|
+
aria-hidden="true"
|
|
456
|
+
class="absolute inset-0 flex items-center justify-center rounded-full bg-actions-neutral-hover-overlay opacity-0 transition-opacity group-hover:opacity-100 group-focus-visible:opacity-100"
|
|
457
|
+
>
|
|
458
|
+
<div
|
|
459
|
+
class="i-ls-check-circle-fill text-text-neutral-invert-tertiary"
|
|
460
|
+
:class="swatchSizeClasses.indicator"
|
|
461
|
+
/>
|
|
462
|
+
</span>
|
|
463
|
+
</span>
|
|
464
|
+
</ColorSwatchPickerItem>
|
|
465
|
+
<!-- selection indicator: rendered outside the (v-memo'd) item so it reacts
|
|
466
|
+
to the live color and clears the moment the color moves off this preset -->
|
|
467
|
+
<span
|
|
468
|
+
v-if="isPresetActive(preset)"
|
|
469
|
+
aria-hidden="true"
|
|
470
|
+
:data-selected-preset="preset.value ?? preset.color.toLowerCase()"
|
|
471
|
+
class="pointer-events-none absolute inset-0 flex items-center justify-center rounded-full bg-actions-neutral-active-overlay ring-actions-neutral-idle ring-offset-surface-neutral-bg-main"
|
|
472
|
+
:class="swatchSizeClasses.indicatorWrapper"
|
|
473
|
+
>
|
|
474
|
+
<div
|
|
475
|
+
class="i-ls-check-circle-fill text-text-neutral-invert-base"
|
|
476
|
+
:class="swatchSizeClasses.indicator"
|
|
477
|
+
/>
|
|
478
|
+
</span>
|
|
479
|
+
</div>
|
|
480
|
+
</ColorSwatchPickerRoot>
|
|
481
|
+
</div>
|
|
482
|
+
|
|
483
|
+
<div v-if="$slots.footer">
|
|
484
|
+
<slot name="footer" />
|
|
485
|
+
</div>
|
|
486
|
+
</div>
|
|
487
|
+
</template>
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { Color, ColorFormat } from 'reka-ui'
|
|
2
|
+
|
|
3
|
+
export type { Color, ColorFormat }
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Rendering variant:
|
|
7
|
+
* - 'default' — full picker (area, sliders, value fields, presets).
|
|
8
|
+
* - 'swatch-only' — only the card with the presets grid (plus heading and footer
|
|
9
|
+
* slot); the custom-color controls are not rendered. `modes`, `outputFormat`,
|
|
10
|
+
* and `showAlpha` are irrelevant in this variant.
|
|
11
|
+
*/
|
|
12
|
+
export type UiColorPickerVariant = 'default' | 'swatch-only'
|
|
13
|
+
|
|
14
|
+
/** Size of the preset selector swatches: 'sm' (24px), 'lg' (48px). */
|
|
15
|
+
export type UiColorPickerSwatchSize = 'sm' | 'lg'
|
|
16
|
+
|
|
17
|
+
export interface UiColorPickerPreset {
|
|
18
|
+
/** Color applied to the picker when this preset is selected. */
|
|
19
|
+
color: string
|
|
20
|
+
/**
|
|
21
|
+
* Stable identity for the preset (e.g. a semantic token or enum name).
|
|
22
|
+
* Colors are lossy identifiers — two presets may share a hex. Set `value`
|
|
23
|
+
* together with the `selectedPresetValue` prop / `update:selectedPresetValue`
|
|
24
|
+
* emit to select and indicate presets by identity instead of by color.
|
|
25
|
+
*/
|
|
26
|
+
value?: string
|
|
27
|
+
/**
|
|
28
|
+
* Accessible name for the swatch (e.g. 'Accent 100'). When omitted, reka-ui
|
|
29
|
+
* announces a generated descriptive color name (e.g. 'vibrant red') — coarse
|
|
30
|
+
* and English-only, so prefer a label for semantic palettes.
|
|
31
|
+
*/
|
|
32
|
+
label?: string
|
|
33
|
+
/**
|
|
34
|
+
* Left half of the swatch (e.g. the tone as it appears in light mode).
|
|
35
|
+
* A two-tone swatch is rendered only when both leftColor and rightColor are set;
|
|
36
|
+
* otherwise the swatch uses `color`.
|
|
37
|
+
*/
|
|
38
|
+
leftColor?: string
|
|
39
|
+
/** Right half of the swatch (e.g. the tone as it appears in dark mode). See leftColor. */
|
|
40
|
+
rightColor?: string
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface UiColorPickerPresetConfig {
|
|
44
|
+
/** Label rendered above the presets grid. Defaults to 'Presets'; pass null to hide the heading (the swatch listbox keeps an aria-label). */
|
|
45
|
+
label?: string | null
|
|
46
|
+
/**
|
|
47
|
+
* Preset swatches. Each preset's `color` is applied to the picker on select;
|
|
48
|
+
* an optional `leftColor`/`rightColor` pair renders a two-tone swatch (otherwise
|
|
49
|
+
* the swatch uses `color`).
|
|
50
|
+
*/
|
|
51
|
+
presets: UiColorPickerPreset[]
|
|
52
|
+
/**
|
|
53
|
+
* Size of the preset selector swatches: 'sm' (24px), 'lg' (48px).
|
|
54
|
+
* @default 'lg'
|
|
55
|
+
*/
|
|
56
|
+
swatchSize?: UiColorPickerSwatchSize
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface UiColorPickerProps {
|
|
60
|
+
/**
|
|
61
|
+
* Primary v-model: a color string (e.g. '#0B42C3', 'rgb(11, 66, 195)',
|
|
62
|
+
* 'hsl(222, 89%, 40%)', 'hsb(222, 94%, 76%)').
|
|
63
|
+
* With the default `outputFormat: 'auto'`, the format follows the active
|
|
64
|
+
* display mode and changes when the mode is switched. With a fixed
|
|
65
|
+
* `outputFormat`, the emitted format is that fixed format regardless of
|
|
66
|
+
* the display mode. See `outputFormat`.
|
|
67
|
+
*/
|
|
68
|
+
modelValue?: string
|
|
69
|
+
/** Optional v-model:color — the full reka Color object (lossless). */
|
|
70
|
+
color?: Color
|
|
71
|
+
/** Rendering variant. See UiColorPickerVariant. */
|
|
72
|
+
variant?: UiColorPickerVariant
|
|
73
|
+
/**
|
|
74
|
+
* Color modes the user may switch between, in display order. Defaults to all
|
|
75
|
+
* four. With a single entry the switcher is hidden and the output format is
|
|
76
|
+
* fixed to that mode.
|
|
77
|
+
*/
|
|
78
|
+
modes?: ColorFormat[]
|
|
79
|
+
/**
|
|
80
|
+
* Format the `modelValue` / `change` value is emitted in.
|
|
81
|
+
* - `'auto'` (default) follows the mode the user has selected in the switcher.
|
|
82
|
+
* - A specific format (`'hex'`, `'rgb'`, `'hsl'`, `'hsb'`) pins the emitted
|
|
83
|
+
* format regardless of the display mode, independent of `modes`.
|
|
84
|
+
*/
|
|
85
|
+
outputFormat?: ColorFormat | 'auto'
|
|
86
|
+
/**
|
|
87
|
+
* Preset swatches plus their label and swatch size. Omit (or pass an empty
|
|
88
|
+
* `presets` array) to hide the presets section.
|
|
89
|
+
*/
|
|
90
|
+
presetConfig?: UiColorPickerPresetConfig
|
|
91
|
+
/**
|
|
92
|
+
* Controlled preset selection by identity (`v-model:selected-preset-value`).
|
|
93
|
+
* When provided (including null), the selection indicator marks the preset
|
|
94
|
+
* whose `value` matches — never by color, so duplicate-hex presets stay
|
|
95
|
+
* distinguishable; null marks none. When omitted, the indicator falls back
|
|
96
|
+
* to matching the current color against each preset's hex.
|
|
97
|
+
*/
|
|
98
|
+
selectedPresetValue?: string | null
|
|
99
|
+
/** Show the alpha/transparency slider. */
|
|
100
|
+
showAlpha?: boolean
|
|
101
|
+
/** Disable all interaction. */
|
|
102
|
+
disabled?: boolean
|
|
103
|
+
}
|