UNPKG

vite-plugin-entry-shaking-debugger

Version:
97 lines (85 loc) 3.1 kB
import type { Ref } from 'vue'; import { computed, reactive, useAttrs, useSlots } from 'vue'; import { randomId } from '#utils'; import type { Booleanish, ShortEmits } from '#uitypes'; import type Tooltip from '@components/Tooltip/Tooltip.vue'; import type Popover from '@components/Popover/Popover.vue'; import { useTooltip } from '@components/Tooltip/useTooltip'; import { usePopover } from '@components/Popover/usePopover'; import { useTeleport } from '@composables/useTeleport'; import type { UseFloatingReturn } from '@composables/useFloating'; import type { ButtonEvents, ButtonProps } from './Button.types'; export function useButton( props: ButtonProps, emit: ShortEmits<ButtonEvents>, className: string, reference: Ref<HTMLButtonElement | null>, tooltipRef: Ref<InstanceType<typeof Tooltip> | null>, popoverRef: Ref<InstanceType<typeof Popover> | null>, ) { const tooltipOptions = computed(() => ({ placement: props.tooltipOptions?.placement ?? 'top', ...(!props.tooltipOptions?.autoupdatePosition ? { whileElementsMounted: undefined } : {}), })); const tooltip = useTooltip(reference, tooltipRef, tooltipOptions.value); const popover = usePopover(reference, popoverRef); const teleport = useTeleport(); const attributes = useButtonAttributes(props, className, popover); const handlers = useButtonHandlers(emit, tooltip, popover); return { /** HTML Attributes. */ attributes, /** Special handlers to be attached to the button. */ handlers, /** Teleport parameters for tooltip. */ teleport, /** Tooltip. */ tooltip: reactive(tooltip), /** Popover. */ popover: reactive(popover), }; } function useButtonAttributes(props: ButtonProps, className: string, popover: UseFloatingReturn) { const attrs = useAttrs(); const slots = useSlots(); const id = computed(() => (attrs['id'] as string | undefined) ?? randomId('btn')); const ariaLabel = computed(() => attrs['aria-label'] as string | undefined); const tabindex = computed(() => attrs['tabindex'] as number | undefined); const popoverId = computed(() => `${id.value}-popover`); const classes = computed(() => [attrs.class ?? '', className, { 'icon-only': props.iconOnly }]); const ariaControls = computed(() => slots.popover ? popoverId.value : (attrs['aria-controls'] as string), ); const ariaExpanded = computed( () => (slots.popover ? popover.isOpen : attrs['aria-expanded']) as Booleanish, ); return reactive({ id, ariaLabel, ariaControls, ariaExpanded, tabindex, popoverId, title: props.disabled && typeof props.disabled === 'string' ? props.disabled : undefined, class: classes, }); } function useButtonHandlers( emit: ShortEmits<ButtonEvents>, tooltip: UseFloatingReturn, popover: UseFloatingReturn, ) { const handleClick = () => { emit('click'); popover.toggle(); }; const handleEscape = ($event: KeyboardEvent) => { emit('escape', $event); popover.close(); }; return { handleClick, handleEscape, tooltipHandlers: tooltip.handlers, }; }