Skip to content

Commit

Permalink
feat: active wave on synthetic clicks
Browse files Browse the repository at this point in the history
  • Loading branch information
justintaddei committed Sep 11, 2024
1 parent 999bda7 commit ceda8e6
Showing 1 changed file with 64 additions and 17 deletions.
81 changes: 64 additions & 17 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { App, Directive } from 'vue'
import { DEFAULT_PLUGIN_OPTIONS, IVWaveDirectiveOptions, IVWavePluginOptions } from './options'
import type { Vector } from './types'
import { getHooks } from './utils/hookKeys'
import { markWaveBoundary } from './utils/markWaveBoundary'
import { triggerIsID } from './utils/triggerIsID'
Expand All @@ -19,6 +20,24 @@ interface DirectiveList {
vWaveTrigger: Directive
}

const createWaveActivationHandler =
(globalOptions: IVWaveDirectiveOptions, el: HTMLElement) => (event: PointerEvent | MouseEvent, position?: Vector) => {
if (!optionMap.has(el)) return

const options = { ...globalOptions, ...optionMap.get(el) }

if (options.stopPropagation) event.stopPropagation()

if (options.trigger === false) return wave(event, el, options)

if (triggerIsID(options.trigger)) return
const trigger = el.querySelector('[data-v-wave-trigger="true"]')
if (!trigger && options.trigger === true) return
if (trigger && !event.composedPath().includes(trigger)) return

wave(position ?? event, el, { ...options, waitForRelease: position ? false : options.waitForRelease })
}

const createDirective = (
globalUserOptions: Partial<IVWaveDirectiveOptions> = {},
app: App | 'vue2' | 'vue3' = 'vue3'
Expand All @@ -27,14 +46,35 @@ const createDirective = (

const hooks = getHooks(app)

const handleTrigger = (event: PointerEvent) => {
const trigger = (event.currentTarget as HTMLElement).dataset.vWaveTrigger
const handleTrigger = (event: PointerEvent | MouseEvent) => {
if (event.detail !== 0) return

const triggerEl = event.currentTarget as HTMLElement
const trigger = triggerEl.dataset.vWaveTrigger

const associatedElements = document.querySelectorAll(
`[data-v-wave-boundary="${trigger}"]`
) as NodeListOf<HTMLElement>

associatedElements.forEach((el) => wave(event, el, { ...globalOptions, ...optionMap.get(el) }))
associatedElements.forEach((el) => {
const isSyntheticClick = event.type === 'click'

let origin: Vector

if (isSyntheticClick) {
const rect = triggerEl.getBoundingClientRect()

origin = {
x: rect.left + rect.width / 2,
y: rect.top + rect.height / 2,
}
} else {
origin = event
}

const options = { ...globalOptions, ...optionMap.get(el) }
wave(origin, el, { ...options, waitForRelease: isSyntheticClick ? false : options.waitForRelease })
})
}

const waveDirective: Directive<HTMLElement, Partial<IVWaveDirectiveOptions>> = {
Expand All @@ -43,21 +83,20 @@ const createDirective = (

markWaveBoundary(el, value?.trigger ?? globalOptions.trigger)

el.addEventListener('pointerdown', (event) => {
if (!optionMap.has(el)) return

const options = { ...globalOptions, ...optionMap.get(el) }
const activationHandler = createWaveActivationHandler(globalOptions, el)

if (options.stopPropagation) event.stopPropagation()
el.addEventListener('pointerdown', activationHandler)
el.addEventListener('click', (event) => {
if (event.detail !== 0) return

if (options.trigger === false) return wave(event, el, options)
const rect = el.getBoundingClientRect()

if (triggerIsID(options.trigger)) return
const trigger = el.querySelector('[data-v-wave-trigger="true"]')
if (!trigger && options.trigger === true) return
if (trigger && !event.composedPath().includes(trigger)) return
const center = {
x: rect.left + rect.width / 2,
y: rect.top + rect.height / 2,
}

wave(event, el, options)
activationHandler(event, center)
})
},
[hooks.updated](el, { value = {} }) {
Expand All @@ -70,14 +109,22 @@ const createDirective = (
[hooks.mounted](el, { arg: trigger = 'true' }) {
el.dataset.vWaveTrigger = trigger

if (trigger !== 'true') el.addEventListener('pointerdown', handleTrigger)
if (trigger !== 'true') {
el.addEventListener('pointerdown', handleTrigger)
el.addEventListener('click', handleTrigger)
}
},

[hooks.updated](el, { arg: trigger = 'true' }) {
el.dataset.vWaveTrigger = trigger

if (trigger === 'true') el.removeEventListener('pointerdown', handleTrigger)
else el.addEventListener('pointerdown', handleTrigger)
if (trigger === 'true') {
el.removeEventListener('pointerdown', handleTrigger)
el.removeEventListener('click', handleTrigger)
} else {
el.addEventListener('pointerdown', handleTrigger)
el.addEventListener('click', handleTrigger)
}
},
}

Expand Down

0 comments on commit ceda8e6

Please sign in to comment.