diff --git a/package.json b/package.json index 8a388f0..9860042 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@shadryx/pptk", - "version": "0.1.3", + "version": "0.1.4", "description": "Pixel-Perfect ToolKit, a library to help make pixel-perfect applications on high-DPI devices", "keywords": [ "pixel-perfect", diff --git a/src/index.js b/src/index.js index 21ed3f0..e7997a2 100644 --- a/src/index.js +++ b/src/index.js @@ -175,6 +175,7 @@ export function getContext2D(canvas) { * @prop {((touch: Touch[], touches: Map) => void)=} onMove * @prop {((touch: Touch | undefined, touches: Map) => void)=} onUp * @prop {number=} downscale + * @prop {boolean=} preventDefault **/ /** @@ -191,11 +192,7 @@ export function attachTouch(element, options = {}) { let queued_touches = []; function get_dpr() { - if (options.dpr) { - return window.devicePixelRatio ?? 1; - } else { - return 1; - } + return window.devicePixelRatio ?? 1; } function onDown(event) { @@ -233,7 +230,7 @@ export function attachTouch(element, options = {}) { let y = (event.clientY - bounding.y) * dpr / downscale; if (touches.has(event.pointerId)) { - let touch = touches.get(event.pointerId); + let touch = cloneGet(touches, event.pointerId); touch.dx = x - touch.x; touch.dy = y - touch.y; @@ -659,3 +656,23 @@ function subpixelPenalty(value) { function approxEq(a, b, epsilon = 0) { return Math.abs(a - b) <= epsilon; } + +/** + * Performs a shallow clone on `map.get(key)`, and replaces that value in the map. + * @template K,V + * @param {Map} map - The map to get the object from, will be mutated + * @param {K} key + * @returns {V | undefined} + **/ +function cloneGet(map, key) { + let value = map.get(key); + if (!value) return value; + if (typeof value === 'object') { + value = { + ...value + }; + map.set(key, value); + } + + return value; +} diff --git a/src/solid/PixelPerfectTouch.tsx b/src/solid/PixelPerfectTouch.tsx index 5510fcf..a471d33 100644 --- a/src/solid/PixelPerfectTouch.tsx +++ b/src/solid/PixelPerfectTouch.tsx @@ -1,12 +1,16 @@ -import { children, Component, createEffect, JSX, onCleanup } from "solid-js"; -import { attachTouch, AttachTouchOptions, Touch } from "../index.js"; - -export type TouchHandler = (touches: Map, touch: T) => void; +import { Component, createEffect, createSignal, type JSX, onCleanup } from "solid-js"; +import { attachTouch, type AttachTouchOptions, type Touch } from "../index.js"; export type PixelPefectTouchProps = { children: JSX.Element; onMount?: (element: HTMLDivElement) => void; + + /** + * Called whenever the touchMap is updated. + * You can safely pass the setter of a solid.js signal to have reactive updates to the touchMap. + **/ + onUpdate?: (touchMap: Map) => void } & AttachTouchOptions; export const PixelPerfectTouch: Component = ( @@ -19,7 +23,21 @@ export const PixelPerfectTouch: Component = ( if (!element) return; - const cleanup = attachTouch(element, options); + const cleanup = attachTouch(element, { + ...options, + onDown(touch, touchMap) { + options.onUpdate?.(new Map(touchMap)); + options.onDown?.(touch, touchMap); + }, + onUp(touch, touchMap) { + options.onUpdate?.(new Map(touchMap)); + options.onUp?.(touch, touchMap); + }, + onMove(touches, touchMap) { + options.onUpdate?.(new Map(touchMap)); + options.onMove?.(touches, touchMap); + } + }); onCleanup(cleanup); });