quasar
Version:
Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time
160 lines (129 loc) • 4.06 kB
JavaScript
import { h, ref, computed, getCurrentInstance } from 'vue'
import useDark, { useDarkProps } from '../../composables/private/use-dark.js'
import useRouterLink, { useRouterLinkProps } from '../../composables/private/use-router-link.js'
import { createComponent } from '../../utils/private/create.js'
import { hUniqueSlot } from '../../utils/private/render.js'
import { stopAndPrevent } from '../../utils/event.js'
import { isKeyCode } from '../../utils/private/key-composition.js'
export default createComponent({
name: 'QItem',
props: {
...useDarkProps,
...useRouterLinkProps,
tag: {
type: String,
default: 'div'
},
active: {
type: Boolean,
default: null
},
clickable: Boolean,
dense: Boolean,
insetLevel: Number,
tabindex: [ String, Number ],
focused: Boolean,
manualFocus: Boolean
},
emits: [ 'click', 'keyup' ],
setup (props, { slots, emit }) {
const { proxy: { $q } } = getCurrentInstance()
const isDark = useDark(props, $q)
const { hasLink, linkAttrs, linkClass, linkTag, navigateOnClick } = useRouterLink()
const rootRef = ref(null)
const blurTargetRef = ref(null)
const isActionable = computed(() =>
props.clickable === true
|| hasLink.value === true
|| props.tag === 'label'
)
const isClickable = computed(() =>
props.disable !== true && isActionable.value === true
)
const classes = computed(() =>
'q-item q-item-type row no-wrap'
+ (props.dense === true ? ' q-item--dense' : '')
+ (isDark.value === true ? ' q-item--dark' : '')
+ (
hasLink.value === true && props.active === null
? linkClass.value
: (
props.active === true
? ` q-item--active${ props.activeClass !== void 0 ? ` ${ props.activeClass }` : '' }`
: ''
)
)
+ (props.disable === true ? ' disabled' : '')
+ (
isClickable.value === true
? ' q-item--clickable q-link cursor-pointer '
+ (props.manualFocus === true ? 'q-manual-focusable' : 'q-focusable q-hoverable')
+ (props.focused === true ? ' q-manual-focusable--focused' : '')
: ''
)
)
const style = computed(() => {
if (props.insetLevel === void 0) {
return null
}
const dir = $q.lang.rtl === true ? 'Right' : 'Left'
return {
[ 'padding' + dir ]: (16 + props.insetLevel * 56) + 'px'
}
})
function onClick (e) {
if (isClickable.value === true) {
if (blurTargetRef.value !== null) {
if (e.qKeyEvent !== true && document.activeElement === rootRef.value) {
blurTargetRef.value.focus()
}
else if (document.activeElement === blurTargetRef.value) {
rootRef.value.focus()
}
}
navigateOnClick(e)
}
}
function onKeyup (e) {
if (isClickable.value === true && isKeyCode(e, 13) === true) {
stopAndPrevent(e)
// for ripple
e.qKeyEvent = true
// for click trigger
const evt = new MouseEvent('click', e)
evt.qKeyEvent = true
rootRef.value.dispatchEvent(evt)
}
emit('keyup', e)
}
function getContent () {
const child = hUniqueSlot(slots.default, [])
isClickable.value === true && child.unshift(
h('div', { class: 'q-focus-helper', tabindex: -1, ref: blurTargetRef })
)
return child
}
return () => {
const data = {
ref: rootRef,
class: classes.value,
style: style.value,
role: 'listitem',
onClick,
onKeyup
}
if (isClickable.value === true) {
data.tabindex = props.tabindex || '0'
Object.assign(data, linkAttrs.value)
}
else if (isActionable.value === true) {
data[ 'aria-disabled' ] = 'true'
}
return h(
linkTag.value,
data,
getContent()
)
}
}
})