Skip to content

Commit 971ffd5

Browse files
chore: restore native events export
1 parent 6d1aab5 commit 971ffd5

File tree

6 files changed

+140
-63
lines changed

6 files changed

+140
-63
lines changed

packages/fiber/src/core/events.ts

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -531,63 +531,3 @@ export function createEvents(store: UseBoundStore<RootState>) {
531531

532532
return { handlePointer }
533533
}
534-
535-
const DOM_EVENTS = {
536-
onClick: ['click', false],
537-
onContextMenu: ['contextmenu', false],
538-
onDoubleClick: ['dblclick', false],
539-
onWheel: ['wheel', true],
540-
onPointerDown: ['pointerdown', true],
541-
onPointerUp: ['pointerup', true],
542-
onPointerLeave: ['pointerleave', true],
543-
onPointerMove: ['pointermove', true],
544-
onPointerCancel: ['pointercancel', true],
545-
onLostPointerCapture: ['lostpointercapture', true],
546-
} as const
547-
548-
/** Default R3F event manager for web */
549-
export function createPointerEvents(store: UseBoundStore<RootState>): EventManager<HTMLElement> {
550-
const { handlePointer } = createEvents(store)
551-
552-
return {
553-
priority: 1,
554-
enabled: true,
555-
compute(event: DomEvent, state: RootState, previous?: RootState) {
556-
// https://github.com/pmndrs/react-three-fiber/pull/782
557-
// Events trigger outside of canvas when moved, use offsetX/Y by default and allow overrides
558-
state.pointer.set((event.offsetX / state.size.width) * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1)
559-
state.raycaster.setFromCamera(state.pointer, state.camera)
560-
},
561-
562-
connected: undefined,
563-
handlers: Object.keys(DOM_EVENTS).reduce(
564-
(acc, key) => ({ ...acc, [key]: handlePointer(key) }),
565-
{},
566-
) as unknown as Events,
567-
update: () => {
568-
const { events, internal } = store.getState()
569-
if (internal.lastEvent?.current && events.handlers) events.handlers.onPointerMove(internal.lastEvent.current)
570-
},
571-
connect: (target: HTMLElement) => {
572-
const { set, events } = store.getState()
573-
events.disconnect?.()
574-
set((state) => ({ events: { ...state.events, connected: target } }))
575-
Object.entries(events.handlers ?? []).forEach(([name, event]) => {
576-
const [eventName, passive] = DOM_EVENTS[name as keyof typeof DOM_EVENTS]
577-
target.addEventListener(eventName, event, { passive })
578-
})
579-
},
580-
disconnect: () => {
581-
const { set, events } = store.getState()
582-
if (events.connected) {
583-
Object.entries(events.handlers ?? []).forEach(([name, event]) => {
584-
if (events && events.connected instanceof HTMLElement) {
585-
const [eventName] = DOM_EVENTS[name as keyof typeof DOM_EVENTS]
586-
events.connected.removeEventListener(eventName, event)
587-
}
588-
})
589-
set((state) => ({ events: { ...state.events, connected: undefined } }))
590-
}
591-
},
592-
}
593-
}

packages/fiber/src/index.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@ export type {
1313
RootState,
1414
} from './core/store'
1515
export type { ThreeEvent, Events, EventManager, ComputeFunction } from './core/events'
16-
export { createEvents, createPointerEvents as events } from './core/events'
16+
export { createEvents } from './core/events'
1717
export type { ObjectMap, Camera } from './core/utils'
1818
export * from './web/Canvas'
19+
export { createPointerEvents as events, createPointerEvents } from './web/events'
1920
export type { GlobalRenderCallback, GlobalEffectType } from './core/loop'
2021
export * from './core'

packages/fiber/src/native.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ export type {
1313
RootState,
1414
} from './core/store'
1515
export type { ThreeEvent, Events, EventManager, ComputeFunction } from './core/events'
16-
export { createEvents, createPointerEvents as events } from './core/events'
16+
export { createEvents } from './core/events'
1717
export type { ObjectMap, Camera } from './core/utils'
1818
export * from './native/Canvas'
19+
export { createTouchEvents as events } from './native/events'
20+
export { createPointerEvents } from './web/events'
1921
export type { GlobalRenderCallback, GlobalEffectType } from './core/loop'
2022
export * from './core'
2123

packages/fiber/src/native/Canvas.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { ExpoWebGLRenderingContext, GLView } from 'expo-gl'
1515
import { useContextBridge, FiberProvider } from 'its-fine'
1616
import { SetBlock, Block, ErrorBoundary, useMutableCallback } from '../core/utils'
1717
import { extend, createRoot, unmountComponentAtNode, RenderProps, ReconcilerRoot } from '../core'
18-
import { createPointerEvents } from '../core/events'
18+
import { createPointerEvents } from '../web/events'
1919
import { RootState, Size } from '../core/store'
2020

2121
export interface CanvasProps extends Omit<RenderProps<HTMLCanvasElement>, 'size' | 'dpr'>, ViewProps {

packages/fiber/src/native/events.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { UseBoundStore } from 'zustand'
2+
import { RootState } from '../core/store'
3+
import { createEvents, DomEvent, EventManager, Events } from '../core/events'
4+
import { type GestureResponderEvent, PanResponder } from 'react-native'
5+
6+
/** Default R3F event manager for react-native */
7+
export function createTouchEvents(store: UseBoundStore<RootState>): EventManager<HTMLElement> {
8+
const { handlePointer } = createEvents(store)
9+
10+
const handleTouch = (event: GestureResponderEvent, name: string): true => {
11+
event.persist()
12+
13+
// Apply offset
14+
;(event as any).nativeEvent.offsetX = event.nativeEvent.locationX
15+
;(event as any).nativeEvent.offsetY = event.nativeEvent.locationY
16+
17+
// Emulate DOM event
18+
const callback = handlePointer(name)
19+
callback(event.nativeEvent as any)
20+
21+
return true
22+
}
23+
24+
const responder = PanResponder.create({
25+
onStartShouldSetPanResponder: () => true,
26+
onMoveShouldSetPanResponder: () => true,
27+
onMoveShouldSetPanResponderCapture: () => true,
28+
onPanResponderTerminationRequest: () => true,
29+
onStartShouldSetPanResponderCapture: (e) => handleTouch(e, 'onPointerCapture'),
30+
onPanResponderStart: (e) => handleTouch(e, 'onPointerDown'),
31+
onPanResponderMove: (e) => handleTouch(e, 'onPointerMove'),
32+
onPanResponderEnd: (e, state) => {
33+
handleTouch(e, 'onPointerUp')
34+
if (Math.hypot(state.dx, state.dy) < 20) handleTouch(e, 'onClick')
35+
},
36+
onPanResponderRelease: (e) => handleTouch(e, 'onPointerLeave'),
37+
onPanResponderTerminate: (e) => handleTouch(e, 'onLostPointerCapture'),
38+
onPanResponderReject: (e) => handleTouch(e, 'onLostPointerCapture'),
39+
})
40+
41+
return {
42+
priority: 1,
43+
enabled: true,
44+
compute(event: DomEvent, state: RootState, previous?: RootState) {
45+
// https://github.com/pmndrs/react-three-fiber/pull/782
46+
// Events trigger outside of canvas when moved, use offsetX/Y by default and allow overrides
47+
state.pointer.set((event.offsetX / state.size.width) * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1)
48+
state.raycaster.setFromCamera(state.pointer, state.camera)
49+
},
50+
51+
connected: undefined,
52+
handlers: responder.panHandlers as unknown as Events,
53+
update: () => {
54+
const { events, internal } = store.getState()
55+
if (internal.lastEvent?.current && events.handlers) {
56+
handlePointer('onPointerMove')(internal.lastEvent.current)
57+
}
58+
},
59+
connect: () => {
60+
const { set, events } = store.getState()
61+
events.disconnect?.()
62+
63+
set((state) => ({ events: { ...state.events, connected: true } }))
64+
},
65+
disconnect: () => {
66+
const { set } = store.getState()
67+
68+
set((state) => ({ events: { ...state.events, connected: false } }))
69+
},
70+
}
71+
}

packages/fiber/src/web/events.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { UseBoundStore } from 'zustand'
2+
import { RootState } from '../core/store'
3+
import { EventManager, Events, createEvents, DomEvent } from '../core/events'
4+
5+
const DOM_EVENTS = {
6+
onClick: ['click', false],
7+
onContextMenu: ['contextmenu', false],
8+
onDoubleClick: ['dblclick', false],
9+
onWheel: ['wheel', true],
10+
onPointerDown: ['pointerdown', true],
11+
onPointerUp: ['pointerup', true],
12+
onPointerLeave: ['pointerleave', true],
13+
onPointerMove: ['pointermove', true],
14+
onPointerCancel: ['pointercancel', true],
15+
onLostPointerCapture: ['lostpointercapture', true],
16+
} as const
17+
18+
/** Default R3F event manager for web */
19+
export function createPointerEvents(store: UseBoundStore<RootState>): EventManager<HTMLElement> {
20+
const { handlePointer } = createEvents(store)
21+
22+
return {
23+
priority: 1,
24+
enabled: true,
25+
compute(event: DomEvent, state: RootState, previous?: RootState) {
26+
// https://github.com/pmndrs/react-three-fiber/pull/782
27+
// Events trigger outside of canvas when moved, use offsetX/Y by default and allow overrides
28+
state.pointer.set((event.offsetX / state.size.width) * 2 - 1, -(event.offsetY / state.size.height) * 2 + 1)
29+
state.raycaster.setFromCamera(state.pointer, state.camera)
30+
},
31+
32+
connected: undefined,
33+
handlers: Object.keys(DOM_EVENTS).reduce(
34+
(acc, key) => ({ ...acc, [key]: handlePointer(key) }),
35+
{},
36+
) as unknown as Events,
37+
update: () => {
38+
const { events, internal } = store.getState()
39+
if (internal.lastEvent?.current && events.handlers) events.handlers.onPointerMove(internal.lastEvent.current)
40+
},
41+
connect: (target: HTMLElement) => {
42+
const { set, events } = store.getState()
43+
events.disconnect?.()
44+
set((state) => ({ events: { ...state.events, connected: target } }))
45+
Object.entries(events.handlers ?? []).forEach(([name, event]) => {
46+
const [eventName, passive] = DOM_EVENTS[name as keyof typeof DOM_EVENTS]
47+
target.addEventListener(eventName, event, { passive })
48+
})
49+
},
50+
disconnect: () => {
51+
const { set, events } = store.getState()
52+
if (events.connected) {
53+
Object.entries(events.handlers ?? []).forEach(([name, event]) => {
54+
if (events && events.connected instanceof HTMLElement) {
55+
const [eventName] = DOM_EVENTS[name as keyof typeof DOM_EVENTS]
56+
events.connected.removeEventListener(eventName, event)
57+
}
58+
})
59+
set((state) => ({ events: { ...state.events, connected: undefined } }))
60+
}
61+
},
62+
}
63+
}

0 commit comments

Comments
 (0)