babel-plugin-jsx icon indicating copy to clipboard operation
babel-plugin-jsx copied to clipboard

Help How to use modifiers in events, such as @click.stop="fn"?

Open core-admin opened this issue 3 years ago • 2 comments

🧐 Problem Description

💻 Sample code

🚑 Other information

core-admin avatar May 27 '21 02:05 core-admin

@core-admin ~~#533~~

funny-family avatar Dec 15 '21 16:12 funny-family

update

import { withModifiers as _withModifiers, capitalize } from 'vue';
import type { Events } from 'vue';

type UnionOfProperties<T> = {
  [K in keyof T]: SingleProperty<T, K>;
}[keyof T];

type EventObject = {
  [key in keyof Events]: ((event: Events[key]) => void) | undefined;
};

type EventObjetWithModifiers = {
  [eventName: string]: Function;
};

/**
 * @see  https://v3.vuejs.org/guide/migration/keycode-modifiers.html#keycode-modifiers
 *
 * @description
 * Add modifier to function.
 *
 * @example
 * <button
 *   class="btn"
 *   type="button"
 *   {...withModifiers(
 *     {
 *       onClick: () => {
 *         alert('Yeah, you clicked me! Only once, no more!');
 *       }
 *     },
 *     ['once']
 *   )}
 * >
 *   You can click me only once!
 * </button>
 */
export const withModifiers = (
  eventObject: UnionOfProperties<EventObject>,
  modifiers: string[]
): EventObjetWithModifiers => {
  const isModifierTransformable = (modifier: string): boolean =>
    (
      [
        'capture',
        'once',
        'passive'
      ] as string[]
    ).includes(modifier);

  const isArrayEmpty = <T>(array: T[]): boolean => array.length === 0;

  const transformableModifiers = modifiers.filter((modifier) =>
    isModifierTransformable(modifier)
  );
  const nonTransformableModifiers = modifiers.filter(
    (modifier) => !isModifierTransformable(modifier)
  );

  const inputEventName = Object.keys(eventObject)[0];
  const inputEventFunction = Object.values(eventObject)[0] as Function;

  const outputEventName = `${inputEventName}${transformableModifiers
    .map(capitalize)
    .join('')}`;
  const outputEventFunction = isArrayEmpty(nonTransformableModifiers)
    ? inputEventFunction
    : _withModifiers(inputEventFunction, [...nonTransformableModifiers]);

  const eventObjetWithModifiers: EventObjetWithModifiers = {
    [outputEventName]: outputEventFunction
  };

  return eventObjetWithModifiers;
};

funny-family avatar Jan 17 '22 02:01 funny-family