techniq / svelte-ux

Collection of Svelte components, actions, stores, and utilities to build highly interactive applications.
https://svelte-ux.techniq.dev/
MIT License
791 stars 43 forks source link

Stop longpress propagation? #221

Open melMass opened 9 months ago

melMass commented 9 months ago

Hi,

Great project, I just stumbled on it while looking for longpress action implementations.

I basically found 3 and had made one myself years ago, they all look relatively similar but none stop propagation of the mouseclick event.

I tried a few approach like stopImmediatePropagation and preventDefault but I'm probably doing it wrong.

As this repo seems the most up to date project to ship such an action it would be nice to fix it here.

What do you think?

Thanks

simplified reproduction

On release of longpress here, onclick is triggered

 <button
      on:click={() =>  console.log(`Tool Clicked`)}
      on:longpress={() => console.log(`Context Menu Triggered`); }
      use:longpress
      class="tool-icon"
    >
    ToolA
</button>
melMass commented 9 months ago

For completeness here is my version:

import type { Action } from "svelte/action";

interface Attributes {
  "on:long"?: (event: CustomEvent) => void;
  "on:long_released"?: (event: CustomEvent) => void;
}

export const longpress: Action<HTMLElement, number | undefined, Attributes> = (
  node: HTMLElement,
  ms = undefined
) => {
  const defaultMS = 500;
  ms = ms || defaultMS;
  let timeoutPtr: number;
  function handleMouseDown(e: MouseEvent) {
    e.stopImmediatePropagation();

    timeoutPtr = window.setTimeout(() => {
      node.dispatchEvent(new CustomEvent("long"));
    }, ms);
  }

  function handleMouseUp() {
    node.dispatchEvent(new CustomEvent("long_released"));
    window.clearTimeout(timeoutPtr);
  }
  node.addEventListener("mousedown", handleMouseDown);
  node.addEventListener("mouseup", handleMouseUp);

  return {
    update(newMs: number | undefined) {
      window.clearTimeout(timeoutPtr);
      ms = newMs || defaultMS;
    },
    destroy: () => {
      window.clearTimeout(timeoutPtr);
      node.removeEventListener("mousedown", handleMouseDown);
      node.removeEventListener("mouseup", handleMouseUp);
    },
  };
};
techniq commented 9 months ago

I never thought of this use case, but it sounds reasonable to me. I’ve been (and still am) onboarding at a new employer so probably be a few days / week till I can get all caught up on my notifications and review items, but I would very much appreciate a PR and will try to review soon. Adding an example of how this stops the propagation to the docs would be great too. My current focus ATM is getting ready to ship the big theme / intl release, but could see this making the release, or following up quickly afterwards.

On Thu, Jan 25, 2024 at 1:45 PM Mel Massadian @.***> wrote:

For completeness here is my version:

import type { Action } from "svelte/action"; interface Attributes { "on:long"?: (event: CustomEvent) => void; "on:long_released"?: (event: CustomEvent) => void;} export const longpress: Action<HTMLElement, number | undefined, Attributes> = ( node: HTMLElement, ms = undefined) => { const defaultMS = 500; ms = ms || defaultMS; let timeoutPtr: number; function handleMouseDown(e: MouseEvent) { e.stopImmediatePropagation();

timeoutPtr = window.setTimeout(() => {
  node.dispatchEvent(new CustomEvent("long"));
}, ms);

}

function handleMouseUp() { node.dispatchEvent(new CustomEvent("long_released")); window.clearTimeout(timeoutPtr); } node.addEventListener("mousedown", handleMouseDown); node.addEventListener("mouseup", handleMouseUp);

return { update(newMs: number | undefined) { window.clearTimeout(timeoutPtr); ms = newMs || defaultMS; }, destroy: () => { window.clearTimeout(timeoutPtr); node.removeEventListener("mousedown", handleMouseDown); node.removeEventListener("mouseup", handleMouseUp); }, };};

— Reply to this email directly, view it on GitHub https://github.com/techniq/svelte-ux/issues/221#issuecomment-1910786081, or unsubscribe https://github.com/notifications/unsubscribe-auth/AABLKRBIUAKKHFRAXGL3RJTYQKR47AVCNFSM6AAAAABCK7QSBCVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSMJQG44DMMBYGE . You are receiving this because you are subscribed to this thread.Message ID: @.***>