UNPKG

quasar

Version:

Build high-performance VueJS user interfaces (SPA, PWA, SSR, Mobile and Desktop) in record time

223 lines (180 loc) 4.54 kB
import { createDirective } from '../../utils/private.create/create.js' import morph from '../../utils/morph/morph.js' const morphGroups = {} const props = [ 'duration', 'delay', 'easing', 'fill', 'classes', 'style', 'duration', 'resize', 'useCSS', 'hideFromClone', 'keepToClone', 'tween', 'tweenFromOpacity', 'tweenToOpacity', 'waitFor', 'onEnd' ] const mods = ['resize', 'useCSS', 'hideFromClone', 'keepToClone', 'tween'] function changeClass(ctx, action) { if (ctx.clsAction !== action) { ctx.clsAction = action ctx.el.classList[action]('q-morph--invisible') } } function trigger(group) { if (group.animating === true || group.queue.length < 2) return const [from, to] = group.queue group.animating = true from.animating = true to.animating = true changeClass(from, 'remove') changeClass(to, 'remove') const cancelFn = morph({ from: from.el, to: to.el, onToggle() { changeClass(from, 'add') changeClass(to, 'remove') }, ...to.opts, onEnd(dir, aborted) { to.opts.onEnd?.(dir, aborted) if (aborted === true) return from.animating = false to.animating = false group.animating = false group.cancel = void 0 group.queue.shift() trigger(group) } }) group.cancel = () => { cancelFn(true) // abort group.cancel = void 0 } } function updateModifiers(mod, ctx) { const opts = ctx.opts mods.forEach(name => { opts[name] = mod[name] === true }) } function insertArgs(arg, ctx) { const opts = typeof arg === 'string' && arg.length !== 0 ? arg.split(':') : [] ctx.name = opts[0] ctx.group = opts[1] Object.assign(ctx.opts, { duration: isNaN(opts[2]) === true ? 300 : parseFloat(opts[2]), waitFor: opts[3] }) } function updateArgs(arg, ctx) { if (arg.group !== void 0) { ctx.group = arg.group } if (arg.name !== void 0) { ctx.name = arg.name } const opts = ctx.opts props.forEach(name => { if (arg[name] !== void 0) { opts[name] = arg[name] } }) } function updateModel(name, ctx) { if (ctx.name === name) { const group = morphGroups[ctx.group] // if group is not registered if (group === void 0) { morphGroups[ctx.group] = { name: ctx.group, model: name, queue: [ctx], animating: false } changeClass(ctx, 'remove') } // if model changed else if (group.model !== name) { group.model = name group.queue.push(ctx) if (group.animating === false && group.queue.length === 2) { trigger(group) } } return } if (ctx.animating === false) { changeClass(ctx, 'add') } } function updateValue(ctx, value) { let model if (Object(value) === value) { model = String(value.model) updateArgs(value, ctx) updateModifiers(value, ctx) } else { model = String(value) } if (model !== ctx.model) { ctx.model = model updateModel(model, ctx) } else if (ctx.animating === false && ctx.clsAction !== void 0) { // ensure HMR ctx.el.classList[ctx.clsAction]('q-morph--invisible') } } export default createDirective( __QUASAR_SSR_SERVER__ ? { name: 'morph', getSSRProps: binding => { const name = binding.arg ? binding.arg.split(':')[0] : false return { class: name === binding.value ? '' : 'q-morph--invisible' } } } : { name: 'morph', mounted(el, binding) { const ctx = { el, animating: false, opts: {} } updateModifiers(binding.modifiers, ctx) insertArgs(binding.arg, ctx) updateValue(ctx, binding.value) el.__qmorph = ctx }, updated(el, binding) { updateValue(el.__qmorph, binding.value) }, beforeUnmount(el) { const ctx = el.__qmorph const group = morphGroups[ctx.group] if (group !== void 0) { const index = group.queue.indexOf(ctx) if (index !== -1) { group.queue = group.queue.filter(item => item !== ctx) if (group.queue.length === 0) { group.cancel?.() delete morphGroups[ctx.group] } } } if (ctx.clsAction === 'add') { el.classList.remove('q-morph--invisible') } delete el.__qmorph } } )