@threlte/xr 1.1.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,9 +18,9 @@ This should be placed within a Threlte `<Canvas />`.
18
18
 
19
19
  -->
20
20
  <script lang="ts">
21
+ import type { EventListener, WebXRManager, Event as ThreeEvent } from 'three'
21
22
  import type { Snippet } from 'svelte'
22
23
  import { useThrelte } from '@threlte/core'
23
- import type { XRSessionEvent } from '../types'
24
24
  import {
25
25
  isHandTracking,
26
26
  isPresenting,
@@ -59,17 +59,17 @@ This should be placed within a Threlte `<Canvas />`.
59
59
  fallback?: Snippet
60
60
  children?: Snippet
61
61
 
62
- /** Called as an XRSession is requested */
63
- onsessionstart?: (event: XRSessionEvent<'sessionstart'>) => void
62
+ /** Called as an XRSession is started */
63
+ onsessionstart?: (event: ThreeEvent<'sessionstart', WebXRManager>) => void
64
64
 
65
- /** Called after an XRSession is terminated */
66
- onsessionend?: (event: XRSessionEvent<'sessionend'>) => void
65
+ /** Called after an XRSession is ended */
66
+ onsessionend?: (event: XRSessionEvent) => void
67
67
 
68
68
  /** Called when an XRSession is hidden or unfocused. */
69
- onvisibilitychange?: (event: globalThis.XRSessionEvent) => void
69
+ onvisibilitychange?: (event: XRSessionEvent) => void
70
70
 
71
71
  /** Called when available inputsources change */
72
- oninputsourceschange?: (event: globalThis.XRSessionEvent) => void
72
+ oninputsourceschange?: (event: XRSessionEvent) => void
73
73
  }
74
74
 
75
75
  let {
@@ -93,28 +93,28 @@ This should be placed within a Threlte `<Canvas />`.
93
93
  setupControllers()
94
94
  setupHands()
95
95
 
96
- const handleSessionStart = () => {
96
+ const handleSessionStart: EventListener<object, 'sessionstart', WebXRManager> = (event) => {
97
97
  isPresenting.current = true
98
- onsessionstart?.({ type: 'sessionstart', target: session.current } as any)
98
+ onsessionstart?.(event)
99
99
  }
100
100
 
101
- const handleSessionEnd = () => {
102
- onsessionend?.({ type: 'sessionend', target: session.current } as any)
101
+ const handleSessionEnd = (event: XRSessionEvent) => {
102
+ onsessionend?.(event)
103
103
  isPresenting.current = false
104
104
  session.current = undefined
105
105
  }
106
106
 
107
- const handleVisibilityChange = (event: globalThis.XRSessionEvent) => {
108
- onvisibilitychange?.({ ...event, target: session.current! })
107
+ const handleVisibilityChange = (event: XRSessionEvent) => {
108
+ onvisibilitychange?.(event)
109
109
  }
110
110
 
111
111
  const handleInputSourcesChange = (event: XRInputSourcesChangeEvent) => {
112
112
  isHandTracking.current = Object.values(event.session.inputSources).some((source) => source.hand)
113
- oninputsourceschange?.({ ...event, target: session.current! })
113
+ oninputsourceschange?.(event)
114
114
  }
115
115
 
116
- const handleFramerateChange = (event: globalThis.XRSessionEvent) => {
117
- onvisibilitychange?.({ ...event, target: session.current! })
116
+ const handleFramerateChange = (event: XRSessionEvent) => {
117
+ onvisibilitychange?.(event)
118
118
  }
119
119
 
120
120
  $effect(() => {
@@ -127,11 +127,13 @@ This should be placed within a Threlte `<Canvas />`.
127
127
  currentSession.addEventListener('visibilitychange', handleVisibilityChange)
128
128
  currentSession.addEventListener('inputsourceschange', handleInputSourcesChange)
129
129
  currentSession.addEventListener('frameratechange', handleFramerateChange)
130
+ currentSession.addEventListener('end', handleSessionEnd)
130
131
 
131
132
  return () => {
132
133
  currentSession.removeEventListener('visibilitychange', handleVisibilityChange)
133
134
  currentSession.removeEventListener('inputsourceschange', handleInputSourcesChange)
134
135
  currentSession.removeEventListener('frameratechange', handleFramerateChange)
136
+ currentSession.removeEventListener('end', handleSessionEnd)
135
137
  }
136
138
  })
137
139
 
@@ -150,13 +152,11 @@ This should be placed within a Threlte `<Canvas />`.
150
152
  xr.current = renderer.xr
151
153
  renderer.xr.enabled = true
152
154
  renderer.xr.addEventListener('sessionstart', handleSessionStart)
153
- renderer.xr.addEventListener('sessionend', handleSessionEnd)
154
155
 
155
156
  return () => {
156
157
  xr.current = undefined
157
158
  renderer.xr.enabled = false
158
159
  renderer.xr.removeEventListener('sessionstart', handleSessionStart)
159
- renderer.xr.removeEventListener('sessionend', handleSessionEnd)
160
160
 
161
161
  // if unmounted while presenting (e.g. due to sveltekit navigation), end the session
162
162
  currentSession?.end()
@@ -1,5 +1,5 @@
1
+ import type { WebXRManager, Event as ThreeEvent } from 'three';
1
2
  import type { Snippet } from 'svelte';
2
- import type { XRSessionEvent } from '../types';
3
3
  interface Props {
4
4
  /**
5
5
  * Enables foveated rendering. Default is `1`, the three.js default.
@@ -22,14 +22,14 @@ interface Props {
22
22
  referenceSpace?: XRReferenceSpaceType;
23
23
  fallback?: Snippet;
24
24
  children?: Snippet;
25
- /** Called as an XRSession is requested */
26
- onsessionstart?: (event: XRSessionEvent<'sessionstart'>) => void;
27
- /** Called after an XRSession is terminated */
28
- onsessionend?: (event: XRSessionEvent<'sessionend'>) => void;
25
+ /** Called as an XRSession is started */
26
+ onsessionstart?: (event: ThreeEvent<'sessionstart', WebXRManager>) => void;
27
+ /** Called after an XRSession is ended */
28
+ onsessionend?: (event: XRSessionEvent) => void;
29
29
  /** Called when an XRSession is hidden or unfocused. */
30
- onvisibilitychange?: (event: globalThis.XRSessionEvent) => void;
30
+ onvisibilitychange?: (event: XRSessionEvent) => void;
31
31
  /** Called when available inputsources change */
32
- oninputsourceschange?: (event: globalThis.XRSessionEvent) => void;
32
+ oninputsourceschange?: (event: XRSessionEvent) => void;
33
33
  }
34
34
  /**
35
35
  * `<XR />` is a WebXR manager that configures your scene for XR rendering and interaction.
@@ -1,12 +1,12 @@
1
- import type { XRHand } from '../types';
1
+ import type { XRHandObject } from '../types';
2
2
  import { type CurrentReadable } from './currentReadable.svelte';
3
3
  declare class Hands {
4
- left: XRHand | undefined;
5
- right: XRHand | undefined;
4
+ left: XRHandObject | undefined;
5
+ right: XRHandObject | undefined;
6
6
  }
7
7
  export declare const hands: Hands;
8
8
  /**
9
9
  * Provides a reference to a current XRHand, filtered by handedness.
10
10
  */
11
- export declare const useHand: (handedness: "left" | "right") => CurrentReadable<undefined | XRHand>;
11
+ export declare const useHand: (handedness: "left" | "right") => CurrentReadable<undefined | XRHandObject>;
12
12
  export {};
package/dist/index.d.ts CHANGED
@@ -17,4 +17,4 @@ export { useHeadset } from './hooks/useHeadset';
17
17
  export { useHitTest } from './hooks/useHitTest.svelte';
18
18
  export { useTeleport } from './hooks/useTeleport';
19
19
  export { useXR } from './hooks/useXR';
20
- export type { XRSessionEventType, XRControllerEventType, XRHandEventType, XRSessionEvent, XRControllerEvent, XRController, XRHand, XRHandEvent } from './types';
20
+ export type { XRSessionEventType, XRControllerEventType, XRHandEventType, XRControllerEvent, XRController, XRHandObject, XRHandEvent } from './types';
@@ -29,6 +29,9 @@ export const setupHands = () => {
29
29
  const { model, targetRay } = map.get(this);
30
30
  const { data } = event;
31
31
  const { handedness, hand: inputSource } = data;
32
+ if (handedness === 'none' || inputSource === undefined) {
33
+ return;
34
+ }
32
35
  hands[handedness] = {
33
36
  hand: this,
34
37
  model,
package/dist/types.d.ts CHANGED
@@ -3,7 +3,7 @@ import type { XRControllerModel } from 'three/examples/jsm/webxr/XRControllerMod
3
3
  import type { XRHandModel } from 'three/examples/jsm/webxr/XRHandModelFactory.js';
4
4
  export type XRSessionEventType = 'sessionstart' | 'sessionend' | 'visibilitychange' | 'frameratechange';
5
5
  export type XRControllerEventType = 'select' | 'selectstart' | 'selectend' | 'squeeze' | 'squeezeend' | 'squeezestart' | 'disconnected' | 'connected';
6
- export type XRControllerEvents = {
6
+ export interface XRControllerEvents {
7
7
  onconnected?: XRControllerEventCallback<'connected'>;
8
8
  ondisconnected?: XRControllerEventCallback<'disconnected'>;
9
9
  onselect?: XRControllerEventCallback<'select'>;
@@ -12,30 +12,24 @@ export type XRControllerEvents = {
12
12
  onsqueeze?: XRControllerEventCallback<'squeeze'>;
13
13
  onsqueezeend?: XRControllerEventCallback<'squeezeend'>;
14
14
  onsqueezestart?: XRControllerEventCallback<'squeezestart'>;
15
- };
15
+ }
16
16
  export type XRHandEventType = 'pinchstart' | 'pinchend' | 'connected' | 'disconnected';
17
- export type XRSessionEvent<Type = XRSessionEventType> = (event: Event & {
18
- type: Type;
19
- target: XRSession;
20
- }) => void;
21
- export type XRControllerEvent<Type = XRControllerEventType> = Event & {
22
- type: Type;
23
- target: Group;
17
+ export interface XRControllerEvent<Type extends string = XRControllerEventType> extends Event<Type, Group> {
24
18
  data: XRInputSource;
25
- };
26
- export type XRControllerEventCallback<Type = XRControllerEventType> = (event: XRControllerEvent<Type>) => void;
27
- export type XRController = {
19
+ }
20
+ export type XRControllerEventCallback<Type extends string = XRControllerEventType> = (event: XRControllerEvent<Type>) => void;
21
+ export interface XRController {
28
22
  targetRay: XRTargetRaySpace;
29
23
  grip: XRGripSpace;
30
24
  model?: XRControllerModel | undefined;
31
25
  inputSource: XRInputSource;
32
- };
33
- export type XRHand = {
26
+ }
27
+ export interface XRHandObject {
34
28
  targetRay: XRTargetRaySpace;
35
29
  hand: XRHandSpace;
36
30
  model?: XRHandModel;
37
- inputSource: globalThis.XRHand;
38
- };
31
+ inputSource: XRHand;
32
+ }
39
33
  export type XRHandEvent<Type = XRHandEventType> = Type extends 'connected' | 'disconnected' ? {
40
34
  type: Type;
41
35
  target: XRHandSpace;
@@ -46,9 +40,9 @@ export type XRHandEvent<Type = XRHandEventType> = Type extends 'connected' | 'di
46
40
  target: null;
47
41
  } : never;
48
42
  export type XRHandEventCallback<Type> = (event: XRHandEvent<Type>) => void;
49
- export type XRHandEvents = {
43
+ export interface XRHandEvents {
50
44
  onconnected?: XRHandEventCallback<'connected'>;
51
45
  ondisconnected?: XRHandEventCallback<'disconnected'>;
52
46
  onpinchstart?: XRHandEventCallback<'pinchstart'>;
53
47
  onpinchend?: XRHandEventCallback<'pinchend'>;
54
- };
48
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@threlte/xr",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "author": "Micheal Parks <michealparks1989@gmail.com> (https://parks.lol)",
5
5
  "license": "MIT",
6
6
  "description": "Tools to more easily create VR and AR experiences with Threlte",
@@ -11,7 +11,7 @@
11
11
  "@sveltejs/package": "^2.3.7",
12
12
  "@sveltejs/vite-plugin-svelte": "^6.1.4",
13
13
  "@types/three": "^0.175.0",
14
- "@types/webxr": "^0.5.22",
14
+ "@types/webxr": "0.5.23",
15
15
  "autoprefixer": "^10.4.19",
16
16
  "eslint": "^9.26.0",
17
17
  "eslint-plugin-svelte": "^3.5.1",
@@ -22,7 +22,7 @@
22
22
  "svelte-check": "^4.3.1",
23
23
  "three": "^0.175.0",
24
24
  "tslib": "^2.6.2",
25
- "typescript": "^5.6.3",
25
+ "typescript": "5.9.2",
26
26
  "typescript-eslint": "^8.32.0",
27
27
  "vite": "^7.1.4",
28
28
  "vite-plugin-mkcert": "^1.17.5",