UNPKG

vuetify

Version:

Vue Material Component Framework

307 lines (305 loc) 11.1 kB
import { Fragment as _Fragment, createVNode as _createVNode, resolveDirective as _resolveDirective, mergeProps as _mergeProps, withDirectives as _withDirectives } from "vue"; // Styles import "./VListItem.css"; // Components import { VListItemSubtitle } from "./VListItemSubtitle.js"; import { VListItemTitle } from "./VListItemTitle.js"; import { VAvatar } from "../VAvatar/index.js"; import { VDefaultsProvider } from "../VDefaultsProvider/index.js"; import { VIcon } from "../VIcon/index.js"; // Composables import { useList } from "./list.js"; import { makeBorderProps, useBorder } from "../../composables/border.js"; import { makeComponentProps } from "../../composables/component.js"; import { makeDensityProps, useDensity } from "../../composables/density.js"; import { makeDimensionProps, useDimension } from "../../composables/dimensions.js"; import { makeElevationProps, useElevation } from "../../composables/elevation.js"; import { IconValue } from "../../composables/icons.js"; import { useNestedItem } from "../../composables/nested/nested.js"; import { makeRoundedProps, useRounded } from "../../composables/rounded.js"; import { makeRouterProps, useLink } from "../../composables/router.js"; import { makeTagProps } from "../../composables/tag.js"; import { makeThemeProps, provideTheme } from "../../composables/theme.js"; import { genOverlays, makeVariantProps, useVariant } from "../../composables/variant.js"; // Directives import { Ripple } from "../../directives/ripple/index.js"; // Utilities import { computed, onBeforeMount, toDisplayString, toRef, watch } from 'vue'; import { deprecate, EventProp, genericComponent, propsFactory, useRender } from "../../util/index.js"; // Types export const makeVListItemProps = propsFactory({ active: { type: Boolean, default: undefined }, activeClass: String, /* @deprecated */ activeColor: String, appendAvatar: String, appendIcon: IconValue, baseColor: String, disabled: Boolean, lines: [Boolean, String], link: { type: Boolean, default: undefined }, nav: Boolean, prependAvatar: String, prependIcon: IconValue, ripple: { type: [Boolean, Object], default: true }, slim: Boolean, subtitle: { type: [String, Number, Boolean], default: undefined }, title: { type: [String, Number, Boolean], default: undefined }, value: null, onClick: EventProp(), onClickOnce: EventProp(), ...makeBorderProps(), ...makeComponentProps(), ...makeDensityProps(), ...makeDimensionProps(), ...makeElevationProps(), ...makeRoundedProps(), ...makeRouterProps(), ...makeTagProps(), ...makeThemeProps(), ...makeVariantProps({ variant: 'text' }) }, 'VListItem'); export const VListItem = genericComponent()({ name: 'VListItem', directives: { Ripple }, props: makeVListItemProps(), emits: { click: e => true }, setup(props, _ref) { let { attrs, slots, emit } = _ref; const link = useLink(props, attrs); const id = computed(() => props.value === undefined ? link.href.value : props.value); const { activate, isActivated, select, isOpen, isSelected, isIndeterminate, isGroupActivator, root, parent, openOnSelect, id: uid } = useNestedItem(id, false); const list = useList(); const isActive = computed(() => props.active !== false && (props.active || link.isActive?.value || (root.activatable.value ? isActivated.value : isSelected.value))); const isLink = toRef(() => props.link !== false && link.isLink.value); const isSelectable = computed(() => !!list && (root.selectable.value || root.activatable.value || props.value != null)); const isClickable = computed(() => !props.disabled && props.link !== false && (props.link || link.isClickable.value || isSelectable.value)); const roundedProps = toRef(() => props.rounded || props.nav); const color = toRef(() => props.color ?? props.activeColor); const variantProps = toRef(() => ({ color: isActive.value ? color.value ?? props.baseColor : props.baseColor, variant: props.variant })); // useNestedItem doesn't call register until beforeMount, // so this can't be an immediate watcher as we don't know parent yet watch(() => link.isActive?.value, val => { if (!val) return; handleActiveLink(); }); onBeforeMount(() => { if (link.isActive?.value) handleActiveLink(); }); function handleActiveLink() { if (parent.value != null) { root.open(parent.value, true); } openOnSelect(true); } const { themeClasses } = provideTheme(props); const { borderClasses } = useBorder(props); const { colorClasses, colorStyles, variantClasses } = useVariant(variantProps); const { densityClasses } = useDensity(props); const { dimensionStyles } = useDimension(props); const { elevationClasses } = useElevation(props); const { roundedClasses } = useRounded(roundedProps); const lineClasses = toRef(() => props.lines ? `v-list-item--${props.lines}-line` : undefined); const slotProps = computed(() => ({ isActive: isActive.value, select, isOpen: isOpen.value, isSelected: isSelected.value, isIndeterminate: isIndeterminate.value })); function onClick(e) { emit('click', e); if (['INPUT', 'TEXTAREA'].includes(e.target?.tagName)) return; if (!isClickable.value) return; link.navigate?.(e); if (isGroupActivator) return; if (root.activatable.value) { activate(!isActivated.value, e); } else if (root.selectable.value) { select(!isSelected.value, e); } else if (props.value != null) { select(!isSelected.value, e); } } function onKeyDown(e) { const target = e.target; if (['INPUT', 'TEXTAREA'].includes(target.tagName)) return; if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); e.target.dispatchEvent(new MouseEvent('click', e)); } } useRender(() => { const Tag = isLink.value ? 'a' : props.tag; const hasTitle = slots.title || props.title != null; const hasSubtitle = slots.subtitle || props.subtitle != null; const hasAppendMedia = !!(props.appendAvatar || props.appendIcon); const hasAppend = !!(hasAppendMedia || slots.append); const hasPrependMedia = !!(props.prependAvatar || props.prependIcon); const hasPrepend = !!(hasPrependMedia || slots.prepend); list?.updateHasPrepend(hasPrepend); if (props.activeColor) { deprecate('active-color', ['color', 'base-color']); } return _withDirectives(_createVNode(Tag, _mergeProps({ "class": ['v-list-item', { 'v-list-item--active': isActive.value, 'v-list-item--disabled': props.disabled, 'v-list-item--link': isClickable.value, 'v-list-item--nav': props.nav, 'v-list-item--prepend': !hasPrepend && list?.hasPrepend.value, 'v-list-item--slim': props.slim, [`${props.activeClass}`]: props.activeClass && isActive.value }, themeClasses.value, borderClasses.value, colorClasses.value, densityClasses.value, elevationClasses.value, lineClasses.value, roundedClasses.value, variantClasses.value, props.class], "style": [colorStyles.value, dimensionStyles.value, props.style], "tabindex": isClickable.value ? list ? -2 : 0 : undefined, "aria-selected": isSelectable.value ? root.activatable.value ? isActivated.value : root.selectable.value ? isSelected.value : isActive.value : undefined, "onClick": onClick, "onKeydown": isClickable.value && !isLink.value && onKeyDown }, link.linkProps), { default: () => [genOverlays(isClickable.value || isActive.value, 'v-list-item'), hasPrepend && _createVNode("div", { "key": "prepend", "class": "v-list-item__prepend" }, [!slots.prepend ? _createVNode(_Fragment, null, [props.prependAvatar && _createVNode(VAvatar, { "key": "prepend-avatar", "density": props.density, "image": props.prependAvatar }, null), props.prependIcon && _createVNode(VIcon, { "key": "prepend-icon", "density": props.density, "icon": props.prependIcon }, null)]) : _createVNode(VDefaultsProvider, { "key": "prepend-defaults", "disabled": !hasPrependMedia, "defaults": { VAvatar: { density: props.density, image: props.prependAvatar }, VIcon: { density: props.density, icon: props.prependIcon }, VListItemAction: { start: true } } }, { default: () => [slots.prepend?.(slotProps.value)] }), _createVNode("div", { "class": "v-list-item__spacer" }, null)]), _createVNode("div", { "class": "v-list-item__content", "data-no-activator": "" }, [hasTitle && _createVNode(VListItemTitle, { "key": "title" }, { default: () => [slots.title?.({ title: props.title }) ?? toDisplayString(props.title)] }), hasSubtitle && _createVNode(VListItemSubtitle, { "key": "subtitle" }, { default: () => [slots.subtitle?.({ subtitle: props.subtitle }) ?? toDisplayString(props.subtitle)] }), slots.default?.(slotProps.value)]), hasAppend && _createVNode("div", { "key": "append", "class": "v-list-item__append" }, [!slots.append ? _createVNode(_Fragment, null, [props.appendIcon && _createVNode(VIcon, { "key": "append-icon", "density": props.density, "icon": props.appendIcon }, null), props.appendAvatar && _createVNode(VAvatar, { "key": "append-avatar", "density": props.density, "image": props.appendAvatar }, null)]) : _createVNode(VDefaultsProvider, { "key": "append-defaults", "disabled": !hasAppendMedia, "defaults": { VAvatar: { density: props.density, image: props.appendAvatar }, VIcon: { density: props.density, icon: props.appendIcon }, VListItemAction: { end: true } } }, { default: () => [slots.append?.(slotProps.value)] }), _createVNode("div", { "class": "v-list-item__spacer" }, null)])] }), [[_resolveDirective("ripple"), isClickable.value && props.ripple]]); }); return { activate, isActivated, isGroupActivator, isSelected, list, select, root, id: uid, link }; } }); //# sourceMappingURL=VListItem.js.map