-
Notifications
You must be signed in to change notification settings - Fork 130
/
Copy pathindex.ts
42 lines (40 loc) · 1.59 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import { createSignal } from "solid-js";
export type HTMLEventName = keyof HTMLElementEventMap;
export type EventNames = [name: HTMLEventName, ...moreNames: HTMLEventName[]];
export type EventStore<Names extends HTMLEventName[]> = {
[name in Names[number]]?: HTMLElementEventMap[name];
};
export type EventProps<Names extends EventNames> = {
[name in Names[number] as `on${name}`]: (ev: HTMLElementEventMap[name]) => void;
};
/**
* Creates the props for certain events for an intrinsic JSX element and a store with the received events
* @param names of the events that should be available in props and store
* @returns [eventStore, eventProps]
* @example
* ```ts
* const [events, eventProps] = createEventProps('mousedown', 'mousemove', 'mouseup');
*
* const isMouseDown = createMemo(() => (events.mousedown?.ts ?? 0) > (events.mouseup?.ts ?? 1));
*
* createEffect(() => {
* if (isMouseDown()) {
* console.log(events.mousemove?.clientX, events.mousemove?.clientY);
* }
* });
*
* <div {...eventProps}>Click and drag on me</div>
* ```
*/
export const createEventProps = <Names extends EventNames>(
...names: Names
): [EventStore<Names>, EventProps<Names>] => {
const store: EventStore<Names> = {};
const eventProps: Record<string, (ev: Event) => void> = {};
names.forEach(name => {
const [accessor, setter] = createSignal<HTMLElementEventMap[typeof name]>();
Object.defineProperty(store, name, { get: accessor, set: setter, enumerable: true });
eventProps[`on${name}` as `on${Names[number]}`] = setter;
});
return [store, eventProps as unknown as EventProps<Names>];
};