From 3a1fc6a00929057e283256eb198723b307701393 Mon Sep 17 00:00:00 2001 From: justintaddei Date: Thu, 27 Jun 2024 01:11:10 -0600 Subject: [PATCH] feat!: add disabled and respectDisabledAttribute options - add disabled option to disable the wave effect on an element - add respectDisabledAttribute option to respect the html disabled attribute on an element Resolves #543 BREAKING CHANGE: the disabled attr now disables the wave effect on the element and removed the ability to disable the wave effect by passing `false` to the directive --- README.md | 35 +++++++++++++++++--------- src/__snapshots__/options.test.ts.snap | 2 ++ src/index.ts | 16 ++++++------ src/options.ts | 25 ++++++++++++++++++ src/utils/hookKeys.ts | 11 +++++--- src/wave.ts | 4 +++ 6 files changed, 70 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 2daa3b4..bce61b1 100644 --- a/README.md +++ b/README.md @@ -72,9 +72,10 @@ After installing and registering the plugin, this is all you need to get started - [easing](#easing) - [cancellationPeriod](#cancellationperiod) - [trigger](#trigger) + - [disabled](#disabled) + - [respectDisabledAttribute](#respectdisabledattribute) - [tagName](#tagname) - [Using triggers](#using-triggers) - - [Disabling the directive](#disabling-the-directive) - [Advanced](#advanced) - [Registering the directive locally](#registering-the-directive-locally) - [Local registration with Composition API:](#local-registration-with-composition-api) @@ -519,6 +520,27 @@ export default { +#### disabled + +- **type:** `boolean` +- _default:_ `false` + +> Disables the wave effect on the element regardless of [`respectDisabledAttribute`](#respectdisabledattribute). + +#### respectDisabledAttribute + +- **type:** `boolean` +- _default:_ `true` + +> When `true`, the wave effect will be disabled if the html `disabled` attribute is present on the element. + +```html + + + + +``` + #### tagName - **type:** `string` @@ -552,17 +574,6 @@ In this next example, clicking one of the buttons will activate the wave on the > Triggers that use an ID support many-to-many relationships. See the grid example on the [example page](https://justintaddei.github.io/v-wave). -### Disabling the directive - -If you need to temporarily disable the wave effect, simply pass `false` to the directive. - -> Note that v-wave checks for strict `false` equality (`=== false`). -> Using any other _falsely_ value will **not** disable the directive. - -```html - -``` - ## Advanced ### Registering the directive locally diff --git a/src/__snapshots__/options.test.ts.snap b/src/__snapshots__/options.test.ts.snap index e276596..cec8fca 100644 --- a/src/__snapshots__/options.test.ts.snap +++ b/src/__snapshots__/options.test.ts.snap @@ -5,11 +5,13 @@ exports[`has documented default options 1`] = ` "cancellationPeriod": 75, "color": "currentColor", "directive": "wave", + "disabled": false, "dissolveDuration": 0.15, "duration": 0.4, "easing": "ease-out", "finalOpacity": 0.1, "initialOpacity": 0.2, + "respectDisabledAttribute": true, "tagName": "div", "trigger": "auto", } diff --git a/src/index.ts b/src/index.ts index 13c6879..69c4f48 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,11 +1,11 @@ -import type { App, Directive, DirectiveBinding } from 'vue' +import type { App, Directive } from 'vue' import { DEFAULT_PLUGIN_OPTIONS, IVWaveDirectiveOptions, IVWavePluginOptions } from './options' import { getHooks } from './utils/hookKeys' import { markWaveBoundary } from './utils/markWaveBoundary' import { triggerIsID } from './utils/triggerIsID' import { wave } from './wave' -const optionMap = new WeakMap | false>() +const optionMap = new WeakMap>() interface VWaveInstallObject { install: (app: any, globalUserOptions: Partial) => void @@ -37,8 +37,8 @@ const createDirective = ( associatedElements.forEach((el) => wave(event, el, { ...globalOptions, ...optionMap.get(el) })) } - const waveDirective: Directive = { - [hooks.mounted](el: HTMLElement, { value = {} }: DirectiveBinding | false>) { + const waveDirective: Directive> = { + [hooks.mounted](el, { value = {} }) { optionMap.set(el, value) markWaveBoundary(el, (value && value.trigger) ?? globalOptions.trigger) @@ -58,20 +58,20 @@ const createDirective = ( wave(event, el, options) }) }, - [hooks.updated](el: HTMLElement, { value = {} }: DirectiveBinding | false>) { + [hooks.updated](el, { value = {} }) { optionMap.set(el, value) markWaveBoundary(el, (value && value.trigger) ?? globalOptions.trigger) }, } - const triggerDirective: Directive = { - [hooks.mounted](el: HTMLElement, { arg: trigger = 'true' }: DirectiveBinding) { + const triggerDirective: Directive = { + [hooks.mounted](el, { arg: trigger = 'true' }) { el.dataset.vWaveTrigger = trigger if (trigger !== 'true') el.addEventListener('pointerdown', handleTrigger) }, - [hooks.updated](el: HTMLElement, { arg: trigger = 'true' }: DirectiveBinding) { + [hooks.updated](el, { arg: trigger = 'true' }) { el.dataset.vWaveTrigger = trigger if (trigger === 'true') el.removeEventListener('pointerdown', handleTrigger) diff --git a/src/options.ts b/src/options.ts index cd3d776..12e84ec 100644 --- a/src/options.ts +++ b/src/options.ts @@ -76,8 +76,31 @@ interface IVWaveDirectiveOptions { * Sets the tag name of the element used as the wave container. This is is useful in scenarios where the default `div` may interfere with `:last-of-type` selectors. * * @default + * 'div' */ tagName: string + + /** + * Disables the wave effect on the element. + * + * @default + * false + */ + disabled: boolean + + /** + * If `true`, the wave effect will be disabled if the html `disabled` attribute is present on the element. + * + * @example + * ```html + * + * + * ``` + * + * @default + * true + */ + respectDisabledAttribute: boolean } interface IVWavePluginOptions extends IVWaveDirectiveOptions { @@ -111,6 +134,8 @@ const DEFAULT_PLUGIN_OPTIONS: IVWavePluginOptions = { cancellationPeriod: 75, trigger: 'auto', tagName: 'div', + disabled: false, + respectDisabledAttribute: true, } export { DEFAULT_PLUGIN_OPTIONS, type IVWavePluginOptions, type IVWaveDirectiveOptions } diff --git a/src/utils/hookKeys.ts b/src/utils/hookKeys.ts index 904c672..34daa81 100644 --- a/src/utils/hookKeys.ts +++ b/src/utils/hookKeys.ts @@ -1,7 +1,12 @@ import type { App } from 'vue' import { isVue3 } from './isVue3' -const getHooks = (app: App | 'vue2' | 'vue3') => { +type v3Hooks = { + mounted: 'mounted' + updated: 'updated' +} + +const getHooks = (app: App | 'vue2' | 'vue3'): v3Hooks => { let vue3: boolean if (app === 'vue2') vue3 = false @@ -13,10 +18,10 @@ const getHooks = (app: App | 'vue2' | 'vue3') => { mounted: 'mounted', updated: 'updated', } - : { + : ({ mounted: 'inserted', updated: 'componentUpdated', - } + } as unknown as v3Hooks) } export { getHooks } diff --git a/src/wave.ts b/src/wave.ts index 36a5dd0..0ab0e02 100644 --- a/src/wave.ts +++ b/src/wave.ts @@ -6,6 +6,10 @@ import { getRelativePointer } from './utils/getRelativePointer' import { decrementWaveCount, deleteWaveCount, getWaveCount, incrementWaveCount } from './utils/wave-count' const wave = (event: PointerEvent, el: HTMLElement, options: IVWaveDirectiveOptions) => { + if (options.disabled) return + + if (options.respectDisabledAttribute && el.hasAttribute('disabled')) return + const rect = el.getBoundingClientRect() const computedStyles = window.getComputedStyle(el)