quasar
Version:
Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time
326 lines (270 loc) • 7.83 kB
JavaScript
import { h, ref, computed, watch, toRaw, getCurrentInstance } from 'vue'
import QDialog from '../dialog/QDialog.js'
import QBtn from '../btn/QBtn.js'
import QCard from '../card/QCard.js'
import QCardSection from '../card/QCardSection.js'
import QCardActions from '../card/QCardActions.js'
import QSeparator from '../separator/QSeparator.js'
import QInput from '../input/QInput.js'
import QOptionGroup from '../option-group/QOptionGroup.js'
import QSpinner from '../spinner/QSpinner.js'
import { createComponent } from '../../utils/private/create.js'
import useDark, { useDarkProps } from '../../composables/private/use-dark.js'
import { isKeyCode } from '../../utils/private/key-composition.js'
import { isObject } from '../../utils/is.js'
export default createComponent({
name: 'DialogPlugin',
props: {
...useDarkProps,
title: String,
message: String,
prompt: Object,
options: Object,
progress: [ Boolean, Object ],
html: Boolean,
ok: {
type: [ String, Object, Boolean ],
default: true
},
cancel: [ String, Object, Boolean ],
focus: {
type: String,
default: 'ok',
validator: v => [ 'ok', 'cancel', 'none' ].includes(v)
},
stackButtons: Boolean,
color: String,
cardClass: [ String, Array, Object ],
cardStyle: [ String, Array, Object ]
},
emits: [ 'ok', 'hide' ],
setup (props, { emit }) {
const { proxy } = getCurrentInstance()
const { $q } = proxy
const isDark = useDark(props, $q)
const dialogRef = ref(null)
const model = ref(
props.prompt !== void 0
? props.prompt.model
: (props.options !== void 0 ? props.options.model : void 0)
)
const classes = computed(() =>
'q-dialog-plugin'
+ (isDark.value === true ? ' q-dialog-plugin--dark q-dark' : '')
+ (props.progress !== false ? ' q-dialog-plugin--progress' : '')
)
const vmColor = computed(() =>
props.color || (isDark.value === true ? 'amber' : 'primary')
)
const spinner = computed(() => (
props.progress === false
? null
: (
isObject(props.progress) === true
? {
component: props.progress.spinner || QSpinner,
props: { color: props.progress.color || vmColor.value }
}
: {
component: QSpinner,
props: { color: vmColor.value }
}
)
))
const hasForm = computed(() =>
props.prompt !== void 0 || props.options !== void 0
)
const formProps = computed(() => {
if (hasForm.value !== true) {
return {}
}
const { model, isValid, items, ...formProps } = props.prompt !== void 0
? props.prompt
: props.options
return formProps
})
const okLabel = computed(() => (
isObject(props.ok) === true
? $q.lang.label.ok
: (
props.ok === true
? $q.lang.label.ok
: props.ok
)
))
const cancelLabel = computed(() => (
isObject(props.cancel) === true
? $q.lang.label.cancel
: (
props.cancel === true
? $q.lang.label.cancel
: props.cancel
)
))
const okDisabled = computed(() => {
if (props.prompt !== void 0) {
return props.prompt.isValid !== void 0
&& props.prompt.isValid(model.value) !== true
}
if (props.options !== void 0) {
return props.options.isValid !== void 0
&& props.options.isValid(model.value) !== true
}
return false
})
const okProps = computed(() => ({
color: vmColor.value,
label: okLabel.value,
ripple: false,
disable: okDisabled.value,
...(isObject(props.ok) === true ? props.ok : { flat: true }),
'data-autofocus': (props.focus === 'ok' && hasForm.value !== true) || void 0,
onClick: onOk
}))
const cancelProps = computed(() => ({
color: vmColor.value,
label: cancelLabel.value,
ripple: false,
...(isObject(props.cancel) === true ? props.cancel : { flat: true }),
'data-autofocus': (props.focus === 'cancel' && hasForm.value !== true) || void 0,
onClick: onCancel
}))
watch(() => props.prompt && props.prompt.model, onUpdateModel)
watch(() => props.options && props.options.model, onUpdateModel)
function show () {
dialogRef.value.show()
}
function hide () {
dialogRef.value.hide()
}
function onOk () {
emit('ok', toRaw(model.value))
hide()
}
function onCancel () {
hide()
}
function onDialogHide () {
emit('hide')
}
function onUpdateModel (val) {
model.value = val
}
function onInputKeyup (evt) {
// if ENTER key
if (
okDisabled.value !== true
&& props.prompt.type !== 'textarea'
&& isKeyCode(evt, 13) === true
) {
onOk()
}
}
function getSection (classes, text) {
return props.html === true
? h(QCardSection, {
class: classes,
innerHTML: text
})
: h(QCardSection, { class: classes }, () => text)
}
function getPrompt () {
return [
h(QInput, {
color: vmColor.value,
dense: true,
autofocus: true,
dark: isDark.value,
...formProps.value,
modelValue: model.value,
'onUpdate:modelValue': onUpdateModel,
onKeyup: onInputKeyup
})
]
}
function getOptions () {
return [
h(QOptionGroup, {
color: vmColor.value,
options: props.options.items,
dark: isDark.value,
...formProps.value,
modelValue: model.value,
'onUpdate:modelValue': onUpdateModel
})
]
}
function getButtons () {
const child = []
props.cancel && child.push(
h(QBtn, cancelProps.value)
)
props.ok && child.push(
h(QBtn, okProps.value)
)
return h(QCardActions, {
class: props.stackButtons === true ? 'items-end' : '',
vertical: props.stackButtons,
align: 'right'
}, () => child)
}
function getCardContent () {
const child = []
props.title && child.push(
getSection('q-dialog__title', props.title)
)
props.progress !== false && child.push(
h(
QCardSection,
{ class: 'q-dialog__progress' },
() => h(spinner.value.component, spinner.value.props)
)
)
props.message && child.push(
getSection('q-dialog__message', props.message)
)
if (props.prompt !== void 0) {
child.push(
h(
QCardSection,
{ class: 'scroll q-dialog-plugin__form' },
getPrompt
)
)
}
else if (props.options !== void 0) {
child.push(
h(QSeparator, { dark: isDark.value }),
h(
QCardSection,
{ class: 'scroll q-dialog-plugin__form' },
getOptions
),
h(QSeparator, { dark: isDark.value })
)
}
if (props.ok || props.cancel) {
child.push(getButtons())
}
return child
}
function getContent () {
return [
h(QCard, {
class: [
classes.value,
props.cardClass
],
style: props.cardStyle,
dark: isDark.value
}, getCardContent)
]
}
// expose public methods
Object.assign(proxy, { show, hide })
return () => h(QDialog, {
ref: dialogRef,
onHide: onDialogHide
}, getContent)
}
})