@threlte/xr 1.1.0 → 1.2.0

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.
Files changed (54) hide show
  1. package/README.md +0 -4
  2. package/dist/components/ARButton.svelte +1 -1
  3. package/dist/components/Controller.svelte +3 -3
  4. package/dist/components/Controller.svelte.d.ts +1 -1
  5. package/dist/components/Hand.svelte +3 -3
  6. package/dist/components/Hand.svelte.d.ts +1 -1
  7. package/dist/components/Headset.svelte +1 -1
  8. package/dist/components/VRButton.svelte +1 -1
  9. package/dist/components/XR.svelte +23 -23
  10. package/dist/components/XR.svelte.d.ts +7 -7
  11. package/dist/components/XRButton.svelte +3 -3
  12. package/dist/components/internal/PointerCursor.svelte +1 -1
  13. package/dist/components/internal/ShortRay.svelte +1 -1
  14. package/dist/components/internal/TeleportCursor.svelte +1 -1
  15. package/dist/components/internal/TeleportRay.svelte +1 -1
  16. package/dist/hooks/useController.svelte.d.ts +2 -2
  17. package/dist/hooks/useController.svelte.js +1 -1
  18. package/dist/hooks/useHand.svelte.d.ts +5 -5
  19. package/dist/hooks/useHand.svelte.js +1 -1
  20. package/dist/hooks/useHandJoint.svelte.d.ts +2 -2
  21. package/dist/hooks/useHandJoint.svelte.js +2 -2
  22. package/dist/hooks/useHeadset.js +1 -1
  23. package/dist/hooks/useHitTest.svelte.js +2 -2
  24. package/dist/hooks/useXR.d.ts +1 -1
  25. package/dist/hooks/useXR.js +2 -2
  26. package/dist/index.d.ts +13 -13
  27. package/dist/index.js +12 -12
  28. package/dist/internal/setupControllers.js +3 -3
  29. package/dist/internal/setupHands.js +6 -3
  30. package/dist/internal/setupHeadset.svelte.js +1 -1
  31. package/dist/internal/setupRaf.svelte.js +2 -2
  32. package/dist/internal/state.svelte.d.ts +1 -1
  33. package/dist/lib/toggleXRSession.js +2 -2
  34. package/dist/plugins/pointerControls/compute.d.ts +1 -1
  35. package/dist/plugins/pointerControls/compute.js +1 -1
  36. package/dist/plugins/pointerControls/context.d.ts +1 -1
  37. package/dist/plugins/pointerControls/hook.js +1 -1
  38. package/dist/plugins/pointerControls/index.d.ts +3 -3
  39. package/dist/plugins/pointerControls/index.js +5 -5
  40. package/dist/plugins/pointerControls/plugin.svelte.js +2 -2
  41. package/dist/plugins/pointerControls/setup.svelte.d.ts +1 -1
  42. package/dist/plugins/pointerControls/setup.svelte.js +5 -5
  43. package/dist/plugins/pointerControls/types.d.ts +1 -1
  44. package/dist/plugins/teleportControls/compute.d.ts +1 -1
  45. package/dist/plugins/teleportControls/compute.js +1 -1
  46. package/dist/plugins/teleportControls/context.d.ts +1 -1
  47. package/dist/plugins/teleportControls/context.js +1 -1
  48. package/dist/plugins/teleportControls/index.d.ts +1 -1
  49. package/dist/plugins/teleportControls/index.js +5 -5
  50. package/dist/plugins/teleportControls/plugin.svelte.js +1 -1
  51. package/dist/plugins/teleportControls/setup.svelte.d.ts +1 -1
  52. package/dist/plugins/teleportControls/setup.svelte.js +4 -4
  53. package/dist/types.d.ts +12 -18
  54. package/package.json +4 -4
package/README.md CHANGED
@@ -46,10 +46,6 @@ Contributions are what make the open source community such an amazing place to l
46
46
  - **Filing Issues** - if you have feature requestions or you think you spotted a bug, [submit an issue](https://github.com/threlte/threlte/issues/new).
47
47
  - **Contributing Code** - if you would like to drop us a PR, read the [contribution guide](https://github.com/threlte/threlte/blob/main/CONTRIBUTING.md) first.
48
48
 
49
- ## Sponsors
50
-
51
- [![Powered by Vercel](./assets/vercel/powered-by-vercel.svg)](https://vercel.com/?utm_source=threlte&utm_campaign=oss)
52
-
53
49
  ---
54
50
 
55
51
  ### License
@@ -12,7 +12,7 @@
12
12
  <script lang="ts">
13
13
  import type { ComponentProps } from 'svelte'
14
14
  import XRButton from './XRButton.svelte'
15
- import { defaultFeatures } from '../internal/defaultFeatures'
15
+ import { defaultFeatures } from '../internal/defaultFeatures.js'
16
16
 
17
17
  type Props = Omit<ComponentProps<typeof XRButton>, 'mode' | 'sessionInit'> & {
18
18
  sessionInit?: XRSessionInit & { domOverlay?: { root: HTMLElement } | undefined }
@@ -3,14 +3,14 @@
3
3
  -->
4
4
  <script lang="ts">
5
5
  import { T, useThrelte } from '@threlte/core'
6
- import { controllers } from '../hooks/useController.svelte'
6
+ import { controllers } from '../hooks/useController.svelte.js'
7
7
  import {
8
8
  isHandTracking,
9
9
  pointerState,
10
10
  teleportState,
11
11
  controllerEvents
12
- } from '../internal/state.svelte'
13
- import type { XRControllerEvents } from '../types'
12
+ } from '../internal/state.svelte.js'
13
+ import type { XRControllerEvents } from '../types.js'
14
14
  import PointerCursor from './internal/PointerCursor.svelte'
15
15
  import ShortRay from './internal/ShortRay.svelte'
16
16
  import TeleportCursor from './internal/TeleportCursor.svelte'
@@ -1,4 +1,4 @@
1
- import type { XRControllerEvents } from '../types';
1
+ import type { XRControllerEvents } from '../types.js';
2
2
  import type { Snippet } from 'svelte';
3
3
  type Props = {
4
4
  children?: Snippet;
@@ -1,9 +1,9 @@
1
1
  <script lang="ts">
2
2
  import { Group } from 'three'
3
3
  import { T, useThrelte, useTask } from '@threlte/core'
4
- import type { XRHandEvents } from '../types'
5
- import { isHandTracking, handEvents } from '../internal/state.svelte'
6
- import { hands } from '../hooks/useHand.svelte'
4
+ import type { XRHandEvents } from '../types.js'
5
+ import { isHandTracking, handEvents } from '../internal/state.svelte.js'
6
+ import { hands } from '../hooks/useHand.svelte.js'
7
7
  import type { Snippet } from 'svelte'
8
8
 
9
9
  type Props = {
@@ -1,4 +1,4 @@
1
- import type { XRHandEvents } from '../types';
1
+ import type { XRHandEvents } from '../types.js';
2
2
  import type { Snippet } from 'svelte';
3
3
  type Props = {
4
4
  children?: Snippet;
@@ -2,7 +2,7 @@
2
2
  import type { Snippet } from 'svelte'
3
3
  import type { Group } from 'three'
4
4
  import { T, useThrelte } from '@threlte/core'
5
- import { useHeadset } from '../hooks/useHeadset'
5
+ import { useHeadset } from '../hooks/useHeadset.js'
6
6
 
7
7
  interface Props {
8
8
  children?: Snippet<[{ ref: Group }]>
@@ -12,7 +12,7 @@
12
12
  <script lang="ts">
13
13
  import type { ComponentProps } from 'svelte'
14
14
  import XRButton from './XRButton.svelte'
15
- import { defaultFeatures } from '../internal/defaultFeatures'
15
+ import { defaultFeatures } from '../internal/defaultFeatures.js'
16
16
 
17
17
  type Props = Omit<ComponentProps<typeof XRButton>, 'mode' | 'sessionInit'>
18
18
 
@@ -18,20 +18,20 @@ 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,
27
27
  referenceSpaceType,
28
28
  session,
29
29
  xr
30
- } from '../internal/state.svelte'
31
- import { setupRaf } from '../internal/setupRaf.svelte'
32
- import { setupHeadset } from '../internal/setupHeadset.svelte'
33
- import { setupControllers } from '../internal/setupControllers'
34
- import { setupHands } from '../internal/setupHands'
30
+ } from '../internal/state.svelte.js'
31
+ import { setupRaf } from '../internal/setupRaf.svelte.js'
32
+ import { setupHeadset } from '../internal/setupHeadset.svelte.js'
33
+ import { setupControllers } from '../internal/setupControllers.js'
34
+ import { setupHands } from '../internal/setupHands.js'
35
35
 
36
36
  interface Props {
37
37
  /**
@@ -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.
@@ -19,9 +19,9 @@ display info about your WebXR session. This is aliased by `ARButton` and
19
19
  -->
20
20
  <script lang="ts">
21
21
  import type { HTMLButtonAttributes } from 'svelte/elements'
22
- import { getXRSupportState } from '../lib/getXRSupportState'
23
- import { toggleXRSession } from '../lib/toggleXRSession'
24
- import { isPresenting, xr } from '../internal/state.svelte'
22
+ import { getXRSupportState } from '../lib/getXRSupportState.js'
23
+ import { toggleXRSession } from '../lib/toggleXRSession.js'
24
+ import { isPresenting, xr } from '../internal/state.svelte.js'
25
25
  import type { Snippet } from 'svelte'
26
26
 
27
27
  type Props = HTMLButtonAttributes & {
@@ -11,7 +11,7 @@
11
11
 
12
12
  <script lang="ts">
13
13
  import { T, useTask, useThrelte } from '@threlte/core'
14
- import { pointerIntersection, pointerState } from '../../internal/state.svelte'
14
+ import { pointerIntersection, pointerState } from '../../internal/state.svelte.js'
15
15
  import Cursor from './Cursor.svelte'
16
16
  import type { Snippet } from 'svelte'
17
17
 
@@ -1,6 +1,6 @@
1
1
  <script lang="ts">
2
2
  import { T } from '@threlte/core'
3
- import { pointerState, teleportState, teleportIntersection } from '../../internal/state.svelte'
3
+ import { pointerState, teleportState, teleportIntersection } from '../../internal/state.svelte.js'
4
4
  import type { Snippet } from 'svelte'
5
5
 
6
6
  interface Props {
@@ -12,7 +12,7 @@
12
12
  <script lang="ts">
13
13
  import { Spring } from 'svelte/motion'
14
14
  import { T, useTask, useThrelte } from '@threlte/core'
15
- import { teleportIntersection } from '../../internal/state.svelte'
15
+ import { teleportIntersection } from '../../internal/state.svelte.js'
16
16
  import Cursor from './Cursor.svelte'
17
17
  import type { Snippet } from 'svelte'
18
18
 
@@ -18,7 +18,7 @@
18
18
  import { LineGeometry } from 'three/examples/jsm/lines/LineGeometry.js'
19
19
  import { LineMaterial } from 'three/examples/jsm/lines/LineMaterial.js'
20
20
  import { T, useTask, useThrelte } from '@threlte/core'
21
- import { teleportIntersection } from '../../internal/state.svelte'
21
+ import { teleportIntersection } from '../../internal/state.svelte.js'
22
22
 
23
23
  interface Props {
24
24
  handedness: 'left' | 'right'
@@ -1,5 +1,5 @@
1
- import type { XRController } from '../types';
2
- import { type CurrentReadable } from './currentReadable.svelte';
1
+ import type { XRController } from '../types.js';
2
+ import { type CurrentReadable } from './currentReadable.svelte.js';
3
3
  declare class Controllers {
4
4
  left: XRController | undefined;
5
5
  right: XRController | undefined;
@@ -1,4 +1,4 @@
1
- import { toCurrentReadable } from './currentReadable.svelte';
1
+ import { toCurrentReadable } from './currentReadable.svelte.js';
2
2
  class Controllers {
3
3
  left = $state.raw();
4
4
  right = $state.raw();
@@ -1,12 +1,12 @@
1
- import type { XRHand } from '../types';
2
- import { type CurrentReadable } from './currentReadable.svelte';
1
+ import type { XRHandObject } from '../types.js';
2
+ import { type CurrentReadable } from './currentReadable.svelte.js';
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 {};
@@ -1,4 +1,4 @@
1
- import { toCurrentReadable } from './currentReadable.svelte';
1
+ import { toCurrentReadable } from './currentReadable.svelte.js';
2
2
  class Hands {
3
3
  left = $state.raw();
4
4
  right = $state.raw();
@@ -1,6 +1,6 @@
1
1
  import type { XRJointSpace } from 'three';
2
- import type { HandJoints } from '../lib/handJoints';
2
+ import type { HandJoints } from '../lib/handJoints.js';
3
3
  /**
4
4
  * Provides a reference to a requested hand joint, once available.
5
5
  */
6
- export declare const useHandJoint: (handedness: "left" | "right", joint: HandJoints) => import("./currentReadable.svelte").CurrentReadable<XRJointSpace | undefined>;
6
+ export declare const useHandJoint: (handedness: "left" | "right", joint: HandJoints) => import("./currentReadable.svelte.js").CurrentReadable<XRJointSpace | undefined>;
@@ -1,6 +1,6 @@
1
1
  import { useTask, useThrelte } from '@threlte/core';
2
- import { hands } from './useHand.svelte';
3
- import { toCurrentReadable } from './currentReadable.svelte';
2
+ import { hands } from './useHand.svelte.js';
3
+ import { toCurrentReadable } from './currentReadable.svelte.js';
4
4
  /**
5
5
  * Provides a reference to a requested hand joint, once available.
6
6
  */
@@ -1,4 +1,4 @@
1
- import { headset } from '../internal/setupHeadset.svelte';
1
+ import { headset } from '../internal/setupHeadset.svelte.js';
2
2
  export const useHeadset = () => {
3
3
  return headset;
4
4
  };
@@ -1,7 +1,7 @@
1
1
  import { Matrix4 } from 'three';
2
2
  import { useThrelte, useTask } from '@threlte/core';
3
- import { controllers } from './useController.svelte';
4
- import { isPresenting, session } from '../internal/state.svelte';
3
+ import { controllers } from './useController.svelte.js';
4
+ import { isPresenting, session } from '../internal/state.svelte.js';
5
5
  /**
6
6
  * Use this hook to perform a hit test per frame in an AR environment.
7
7
  *
@@ -1,5 +1,5 @@
1
1
  import type { WebXRManager } from 'three';
2
- import { type CurrentReadable } from './currentReadable.svelte';
2
+ import { type CurrentReadable } from './currentReadable.svelte.js';
3
3
  /**
4
4
  * Provides access to context related to `<XR />`.
5
5
  */
@@ -1,5 +1,5 @@
1
- import { isPresenting, isHandTracking, session, xr } from '../internal/state.svelte';
2
- import { toCurrentReadable } from './currentReadable.svelte';
1
+ import { isPresenting, isHandTracking, session, xr } from '../internal/state.svelte.js';
2
+ import { toCurrentReadable } from './currentReadable.svelte.js';
3
3
  /**
4
4
  * Provides access to context related to `<XR />`.
5
5
  */
package/dist/index.d.ts CHANGED
@@ -5,16 +5,16 @@ export { default as Controller } from './components/Controller.svelte';
5
5
  export { default as Hand } from './components/Hand.svelte';
6
6
  export { default as Headset } from './components/Headset.svelte';
7
7
  export { default as XR } from './components/XR.svelte';
8
- export { getXRSupportState } from './lib/getXRSupportState';
9
- export { toggleXRSession } from './lib/toggleXRSession';
10
- export { handJoints } from './lib/handJoints';
11
- export { pointerControls } from './plugins/pointerControls';
12
- export { teleportControls } from './plugins/teleportControls';
13
- export { useController } from './hooks/useController.svelte';
14
- export { useHand } from './hooks/useHand.svelte';
15
- export { useHandJoint } from './hooks/useHandJoint.svelte';
16
- export { useHeadset } from './hooks/useHeadset';
17
- export { useHitTest } from './hooks/useHitTest.svelte';
18
- export { useTeleport } from './hooks/useTeleport';
19
- export { useXR } from './hooks/useXR';
20
- export type { XRSessionEventType, XRControllerEventType, XRHandEventType, XRSessionEvent, XRControllerEvent, XRController, XRHand, XRHandEvent } from './types';
8
+ export { getXRSupportState } from './lib/getXRSupportState.js';
9
+ export { toggleXRSession } from './lib/toggleXRSession.js';
10
+ export { handJoints } from './lib/handJoints.js';
11
+ export { pointerControls } from './plugins/pointerControls/index.js';
12
+ export { teleportControls } from './plugins/teleportControls/index.js';
13
+ export { useController } from './hooks/useController.svelte.js';
14
+ export { useHand } from './hooks/useHand.svelte.js';
15
+ export { useHandJoint } from './hooks/useHandJoint.svelte.js';
16
+ export { useHeadset } from './hooks/useHeadset.js';
17
+ export { useHitTest } from './hooks/useHitTest.svelte.js';
18
+ export { useTeleport } from './hooks/useTeleport.js';
19
+ export { useXR } from './hooks/useXR.js';
20
+ export type { XRSessionEventType, XRControllerEventType, XRHandEventType, XRControllerEvent, XRController, XRHandObject, XRHandEvent } from './types.js';
package/dist/index.js CHANGED
@@ -7,17 +7,17 @@ export { default as Hand } from './components/Hand.svelte';
7
7
  export { default as Headset } from './components/Headset.svelte';
8
8
  export { default as XR } from './components/XR.svelte';
9
9
  // Utilities
10
- export { getXRSupportState } from './lib/getXRSupportState';
11
- export { toggleXRSession } from './lib/toggleXRSession';
12
- export { handJoints } from './lib/handJoints';
10
+ export { getXRSupportState } from './lib/getXRSupportState.js';
11
+ export { toggleXRSession } from './lib/toggleXRSession.js';
12
+ export { handJoints } from './lib/handJoints.js';
13
13
  // Plugins
14
- export { pointerControls } from './plugins/pointerControls';
15
- export { teleportControls } from './plugins/teleportControls';
14
+ export { pointerControls } from './plugins/pointerControls/index.js';
15
+ export { teleportControls } from './plugins/teleportControls/index.js';
16
16
  // Hooks
17
- export { useController } from './hooks/useController.svelte';
18
- export { useHand } from './hooks/useHand.svelte';
19
- export { useHandJoint } from './hooks/useHandJoint.svelte';
20
- export { useHeadset } from './hooks/useHeadset';
21
- export { useHitTest } from './hooks/useHitTest.svelte';
22
- export { useTeleport } from './hooks/useTeleport';
23
- export { useXR } from './hooks/useXR';
17
+ export { useController } from './hooks/useController.svelte.js';
18
+ export { useHand } from './hooks/useHand.svelte.js';
19
+ export { useHandJoint } from './hooks/useHandJoint.svelte.js';
20
+ export { useHeadset } from './hooks/useHeadset.js';
21
+ export { useHitTest } from './hooks/useHitTest.svelte.js';
22
+ export { useTeleport } from './hooks/useTeleport.js';
23
+ export { useXR } from './hooks/useXR.js';
@@ -1,9 +1,9 @@
1
1
  import { XRControllerModelFactory } from 'three/examples/jsm/webxr/XRControllerModelFactory.js';
2
2
  import { useThrelte } from '@threlte/core';
3
3
  import { onMount } from 'svelte';
4
- import { useHandTrackingState } from './useHandTrackingState';
5
- import { controllers } from '../hooks/useController.svelte';
6
- import { controllerEvents } from './state.svelte';
4
+ import { useHandTrackingState } from './useHandTrackingState.js';
5
+ import { controllers } from '../hooks/useController.svelte.js';
6
+ import { controllerEvents } from './state.svelte.js';
7
7
  export const setupControllers = () => {
8
8
  const factory = new XRControllerModelFactory();
9
9
  const { xr } = useThrelte().renderer;
@@ -1,9 +1,9 @@
1
1
  import { XRHandModelFactory } from 'three/examples/jsm/webxr/XRHandModelFactory.js';
2
2
  import { useThrelte } from '@threlte/core';
3
3
  import { onMount } from 'svelte';
4
- import { hands } from '../hooks/useHand.svelte';
5
- import { useHandTrackingState } from './useHandTrackingState';
6
- import { handEvents } from './state.svelte';
4
+ import { hands } from '../hooks/useHand.svelte.js';
5
+ import { useHandTrackingState } from './useHandTrackingState.js';
6
+ import { handEvents } from './state.svelte.js';
7
7
  export const setupHands = () => {
8
8
  const factory = new XRHandModelFactory();
9
9
  const { xr } = useThrelte().renderer;
@@ -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,
@@ -1,6 +1,6 @@
1
1
  import { Group } from 'three';
2
2
  import { useThrelte, useTask } from '@threlte/core';
3
- import { isPresenting } from './state.svelte';
3
+ import { isPresenting } from './state.svelte.js';
4
4
  export const headset = new Group();
5
5
  export const setupHeadset = () => {
6
6
  const { renderer, camera, scheduler, renderStage } = useThrelte();
@@ -1,5 +1,5 @@
1
- import { session } from './state.svelte';
2
- import { raf } from './raf';
1
+ import { session } from './state.svelte.js';
2
+ import { raf } from './raf.js';
3
3
  export const setupRaf = () => {
4
4
  if (typeof window === 'undefined')
5
5
  return;
@@ -1,5 +1,5 @@
1
1
  import type { WebXRManager, Intersection } from 'three';
2
- import type { XRControllerEvents, XRHandEvents } from '../types';
2
+ import type { XRControllerEvents, XRHandEvents } from '../types.js';
3
3
  interface ControllerEvents {
4
4
  left?: XRControllerEvents;
5
5
  right?: XRControllerEvents;
@@ -1,5 +1,5 @@
1
- import { session, referenceSpaceType, xr } from '../internal/state.svelte';
2
- import { getXRSessionOptions } from './getXRSessionOptions';
1
+ import { session, referenceSpaceType, xr } from '../internal/state.svelte.js';
2
+ import { getXRSessionOptions } from './getXRSessionOptions.js';
3
3
  /**
4
4
  * Starts / ends an XR session.
5
5
  *
@@ -1,3 +1,3 @@
1
- import type { ControlsContext, HandContext } from './types';
1
+ import type { ControlsContext, HandContext } from './types.js';
2
2
  export type ComputeFunction = (state: ControlsContext, handState: HandContext) => void;
3
3
  export declare const defaultComputeFunction: ComputeFunction;
@@ -1,5 +1,5 @@
1
1
  import { Vector3 } from 'three';
2
- import { controllers } from '../../hooks/useController.svelte';
2
+ import { controllers } from '../../hooks/useController.svelte.js';
3
3
  const forward = new Vector3();
4
4
  export const defaultComputeFunction = (context, handContext) => {
5
5
  const targetRay = controllers[handContext.hand]?.targetRay;
@@ -1,5 +1,5 @@
1
1
  import type { Object3D } from 'three';
2
- import type { ControlsContext, HandContext } from './types';
2
+ import type { ControlsContext, HandContext } from './types.js';
3
3
  export declare const getHandContext: (hand: "left" | "right") => HandContext;
4
4
  export declare const setHandContext: (hand: "left" | "right", context: HandContext) => void;
5
5
  export declare const getControlsContext: () => ControlsContext;
@@ -1,4 +1,4 @@
1
- import { getControlsContext, getInternalContext } from './context';
1
+ import { getControlsContext, getInternalContext } from './context.js';
2
2
  export const usePointerControls = () => {
3
3
  const context = getControlsContext();
4
4
  const { dispatchers } = getInternalContext();
@@ -1,5 +1,5 @@
1
- import { type ComputeFunction } from './compute';
2
- import type { FilterFunction } from './types';
1
+ import { type ComputeFunction } from './compute.js';
2
+ import type { FilterFunction } from './types.js';
3
3
  export type PointerControlsOptions = {
4
4
  enabled?: boolean;
5
5
  /**
@@ -23,5 +23,5 @@ export type PointerControlsOptions = {
23
23
  };
24
24
  export declare const pointerControls: (handedness: "left" | "right", options?: PointerControlsOptions) => {
25
25
  enabled: import("@threlte/core").CurrentWritable<boolean>;
26
- hovered: Map<string, import("./types").IntersectionEvent>;
26
+ hovered: Map<string, import("./types.js").IntersectionEvent>;
27
27
  };
@@ -1,10 +1,10 @@
1
1
  import { Raycaster, Vector3 } from 'three';
2
2
  import { currentWritable, watch } from '@threlte/core';
3
- import { defaultComputeFunction } from './compute';
4
- import { injectPointerControlsPlugin } from './plugin.svelte';
5
- import { setupPointerControls } from './setup.svelte';
6
- import { getControlsContext, getHandContext, setControlsContext, setHandContext, setInternalContext } from './context';
7
- import { pointerState } from '../../internal/state.svelte';
3
+ import { defaultComputeFunction } from './compute.js';
4
+ import { injectPointerControlsPlugin } from './plugin.svelte.js';
5
+ import { setupPointerControls } from './setup.svelte.js';
6
+ import { getControlsContext, getHandContext, setControlsContext, setHandContext, setInternalContext } from './context.js';
7
+ import { pointerState } from '../../internal/state.svelte.js';
8
8
  let controlsCounter = 0;
9
9
  export const pointerControls = (handedness, options) => {
10
10
  if (getControlsContext() === undefined) {
@@ -1,6 +1,6 @@
1
1
  import { injectPlugin, isInstanceOf, observe } from '@threlte/core';
2
- import { usePointerControls } from './hook';
3
- import { events } from './types';
2
+ import { usePointerControls } from './hook.js';
3
+ import { events } from './types.js';
4
4
  export const injectPointerControlsPlugin = () => {
5
5
  injectPlugin('threlte-pointer-controls', (args) => {
6
6
  if (!isInstanceOf(args.ref, 'Object3D'))
@@ -1,2 +1,2 @@
1
- import type { ControlsContext, HandContext } from './types';
1
+ import type { ControlsContext, HandContext } from './types.js';
2
2
  export declare const setupPointerControls: (context: ControlsContext, handContext: HandContext, fixedStep?: number) => void;
@@ -1,10 +1,10 @@
1
1
  import { Vector3 } from 'three';
2
2
  import { observe, watch } from '@threlte/core';
3
- import { getInternalContext } from './context';
4
- import { controllers } from '../../hooks/useController.svelte';
5
- import { useHand } from '../../hooks/useHand.svelte';
6
- import { useFixed } from '../../internal/useFixed';
7
- import { isPresenting, pointerIntersection } from '../../internal/state.svelte';
3
+ import { getInternalContext } from './context.js';
4
+ import { controllers } from '../../hooks/useController.svelte.js';
5
+ import { useHand } from '../../hooks/useHand.svelte.js';
6
+ import { useFixed } from '../../internal/useFixed.js';
7
+ import { isPresenting, pointerIntersection } from '../../internal/state.svelte.js';
8
8
  const getIntersectionId = (intersection) => {
9
9
  return `${(intersection.eventObject || intersection.object).uuid}/${intersection.index}${intersection.instanceId ?? ''}`;
10
10
  };
@@ -1,6 +1,6 @@
1
1
  import type { Intersection as ThreeIntersection, Object3D, Vector3, Ray, Raycaster, Event } from 'three';
2
2
  import type { CurrentWritable } from '@threlte/core';
3
- import type { ComputeFunction } from './compute';
3
+ import type { ComputeFunction } from './compute.js';
4
4
  export type Properties<T> = Pick<T, {
5
5
  [K in keyof T]: T[K] extends (_: any) => any ? never : K;
6
6
  }[keyof T]>;
@@ -1,3 +1,3 @@
1
- import type { Context, HandContext } from './context';
1
+ import type { Context, HandContext } from './context.js';
2
2
  export type ComputeFunction = (context: Context, handContext: HandContext) => void;
3
3
  export declare const defaultComputeFunction: (context: Context, handContext: HandContext) => void;
@@ -1,5 +1,5 @@
1
1
  import { Vector3 } from 'three';
2
- import { controllers } from '../../hooks/useController.svelte';
2
+ import { controllers } from '../../hooks/useController.svelte.js';
3
3
  const forward = new Vector3();
4
4
  export const defaultComputeFunction = (context, handContext) => {
5
5
  const targetRay = controllers[handContext.hand]?.targetRay;
@@ -1,6 +1,6 @@
1
1
  import { type Mesh, Raycaster, type Intersection } from 'three';
2
2
  import type { CurrentWritable } from '@threlte/core';
3
- import type { TeleportControlsOptions } from '.';
3
+ import type { TeleportControlsOptions } from './index.js';
4
4
  export type ComputeFunction = (context: Context, handContext: HandContext) => void;
5
5
  export type TeleportEvents = Record<string, (arg: unknown) => void>;
6
6
  export interface Context {
@@ -1,6 +1,6 @@
1
1
  import { Raycaster } from 'three';
2
2
  import { getContext, setContext } from 'svelte';
3
- import { defaultComputeFunction } from './compute';
3
+ import { defaultComputeFunction } from './compute.js';
4
4
  const handContextKeys = {
5
5
  left: Symbol('teleport-controls-context-left-hand'),
6
6
  right: Symbol('teleport-controls-context-right-hand')
@@ -1,4 +1,4 @@
1
- import { type ComputeFunction } from './context';
1
+ import { type ComputeFunction } from './context.js';
2
2
  export interface TeleportControlsOptions {
3
3
  enabled?: boolean;
4
4
  /**
@@ -1,9 +1,9 @@
1
1
  import { currentWritable, watch } from '@threlte/core';
2
- import { createTeleportContext, useTeleportControls, getHandContext } from './context';
3
- import { injectTeleportControlsPlugin } from './plugin.svelte';
4
- import { setHandContext } from './context';
5
- import { setupTeleportControls } from './setup.svelte';
6
- import { teleportState } from '../../internal/state.svelte';
2
+ import { createTeleportContext, useTeleportControls, getHandContext } from './context.js';
3
+ import { injectTeleportControlsPlugin } from './plugin.svelte.js';
4
+ import { setHandContext } from './context.js';
5
+ import { setupTeleportControls } from './setup.svelte.js';
6
+ import { teleportState } from '../../internal/state.svelte.js';
7
7
  let controlsCounter = 0;
8
8
  export const teleportControls = (handedness, options) => {
9
9
  if (useTeleportControls() === undefined) {
@@ -1,5 +1,5 @@
1
1
  import { injectPlugin, isInstanceOf } from '@threlte/core';
2
- import { useTeleportControls } from './context';
2
+ import { useTeleportControls } from './context.js';
3
3
  /**
4
4
  * Registers T components with "teleportSurface" or "teleportBlocker" attributes.
5
5
  */
@@ -1,2 +1,2 @@
1
- import type { Context, HandContext } from './context';
1
+ import type { Context, HandContext } from './context.js';
2
2
  export declare const setupTeleportControls: (context: Context, handContext: HandContext, fixedStep?: number) => void;
@@ -1,8 +1,8 @@
1
1
  import { observe } from '@threlte/core';
2
- import { controllers } from '../../hooks/useController.svelte';
3
- import { useTeleport } from '../../hooks/useTeleport';
4
- import { useFixed } from '../../internal/useFixed';
5
- import { isPresenting, teleportIntersection } from '../../internal/state.svelte';
2
+ import { controllers } from '../../hooks/useController.svelte.js';
3
+ import { useTeleport } from '../../hooks/useTeleport.js';
4
+ import { useFixed } from '../../internal/useFixed.js';
5
+ import { isPresenting, teleportIntersection } from '../../internal/state.svelte.js';
6
6
  export const setupTeleportControls = (context, handContext, fixedStep = 1 / 40) => {
7
7
  const handedness = handContext.hand;
8
8
  const controller = $derived(controllers[handedness]);
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.2.0",
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,11 +22,11 @@
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",
29
- "@threlte/core": "8.1.5"
29
+ "@threlte/core": "8.3.0"
30
30
  },
31
31
  "peerDependencies": {
32
32
  "svelte": ">=5",