@threlte/xr 1.0.0-next.8 → 1.0.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 (50) hide show
  1. package/README.md +1 -8
  2. package/dist/components/ARButton.svelte +10 -3
  3. package/dist/components/ARButton.svelte.d.ts +8 -38
  4. package/dist/components/Controller.svelte +86 -46
  5. package/dist/components/Controller.svelte.d.ts +25 -37
  6. package/dist/components/Hand.svelte +109 -60
  7. package/dist/components/Hand.svelte.d.ts +21 -33
  8. package/dist/components/Headset.svelte +6 -4
  9. package/dist/components/Headset.svelte.d.ts +18 -16
  10. package/dist/components/VRButton.svelte +8 -3
  11. package/dist/components/VRButton.svelte.d.ts +2 -32
  12. package/dist/components/XR.svelte +156 -96
  13. package/dist/components/XR.svelte.d.ts +32 -45
  14. package/dist/components/XRButton.svelte +71 -38
  15. package/dist/components/XRButton.svelte.d.ts +26 -39
  16. package/dist/components/internal/Cursor.svelte +38 -25
  17. package/dist/components/internal/Cursor.svelte.d.ts +6 -18
  18. package/dist/components/internal/PointerCursor.svelte +46 -34
  19. package/dist/components/internal/PointerCursor.svelte.d.ts +5 -17
  20. package/dist/components/internal/ScenePortal.svelte +15 -12
  21. package/dist/components/internal/ScenePortal.svelte.d.ts +18 -16
  22. package/dist/components/internal/ShortRay.svelte +23 -12
  23. package/dist/components/internal/ShortRay.svelte.d.ts +5 -17
  24. package/dist/components/internal/TeleportCursor.svelte +51 -37
  25. package/dist/components/internal/TeleportCursor.svelte.d.ts +5 -17
  26. package/dist/components/internal/TeleportRay.svelte +77 -54
  27. package/dist/components/internal/TeleportRay.svelte.d.ts +6 -18
  28. package/dist/hooks/useController.d.ts +0 -1
  29. package/dist/hooks/useHand.d.ts +1 -1
  30. package/dist/hooks/useHandJoint.d.ts +1 -1
  31. package/dist/hooks/useHitTest.d.ts +0 -1
  32. package/dist/hooks/useXR.d.ts +0 -1
  33. package/dist/internal/stores.d.ts +0 -1
  34. package/dist/lib/getXRSessionOptions.d.ts +0 -1
  35. package/dist/lib/getXRSupportState.d.ts +1 -2
  36. package/dist/lib/toggleXRSession.d.ts +1 -2
  37. package/dist/plugins/pointerControls/context.d.ts +2 -2
  38. package/dist/plugins/pointerControls/index.d.ts +1 -1
  39. package/dist/plugins/pointerControls/index.js +1 -1
  40. package/dist/plugins/pointerControls/plugin.svelte.js +23 -0
  41. package/dist/plugins/teleportControls/context.d.ts +3 -3
  42. package/dist/plugins/teleportControls/index.d.ts +1 -1
  43. package/dist/plugins/teleportControls/index.js +1 -1
  44. package/dist/plugins/teleportControls/plugin.svelte.js +73 -0
  45. package/dist/types.d.ts +0 -1
  46. package/package.json +12 -12
  47. package/dist/plugins/pointerControls/plugin.js +0 -26
  48. package/dist/plugins/teleportControls/plugin.js +0 -54
  49. /package/dist/plugins/pointerControls/{plugin.d.ts → plugin.svelte.d.ts} +0 -0
  50. /package/dist/plugins/teleportControls/{plugin.d.ts → plugin.svelte.d.ts} +0 -0
@@ -17,104 +17,164 @@ This should be placed within a Threlte `<Canvas />`.
17
17
  ```
18
18
 
19
19
  -->
20
- <script lang="ts">import { onMount } from "svelte";
21
- import { useThrelte, watch } from "@threlte/core";
22
- import {
23
- isHandTracking,
24
- isPresenting,
25
- referenceSpaceType,
26
- session,
27
- xr as xrStore
28
- } from "../internal/stores";
29
- import { setupRaf } from "../internal/setupRaf";
30
- import { setupHeadset } from "../internal/setupHeadset";
31
- import { setupControllers } from "../internal/setupControllers";
32
- import { setupHands } from "../internal/setupHands";
33
- let {
34
- foveation = 1,
35
- frameRate,
36
- referenceSpace = "local-floor",
37
- onsessionstart,
38
- onsessionend,
39
- onvisibilitychange,
40
- oninputsourceschange,
41
- fallback,
42
- children
43
- } = $props();
44
- const { renderer, renderMode } = useThrelte();
45
- const { xr } = renderer;
46
- let originalRenderMode = $renderMode;
47
- setupRaf();
48
- setupHeadset();
49
- setupControllers();
50
- setupHands();
51
- const handleSessionStart = () => {
52
- isPresenting.set(true);
53
- onsessionstart?.({ type: "sessionstart", target: $session });
54
- };
55
- const handleSessionEnd = () => {
56
- onsessionend?.({ type: "sessionend", target: $session });
57
- isPresenting.set(false);
58
- session.set(void 0);
59
- };
60
- const handleVisibilityChange = (event) => {
61
- onvisibilitychange?.({ ...event, target: $session });
62
- };
63
- const handleInputSourcesChange = (event) => {
64
- $isHandTracking = Object.values(event.session.inputSources).some((source) => source.hand);
65
- oninputsourceschange?.({ ...event, target: $session });
66
- };
67
- const handleFramerateChange = (event) => {
68
- onvisibilitychange?.({ ...event, target: $session });
69
- };
70
- const updateTargetFrameRate = (frameRate2) => {
71
- if (frameRate2 === void 0)
72
- return;
73
- try {
74
- $session?.updateTargetFrameRate(frameRate2);
75
- } catch {
20
+ <script lang="ts">
21
+ import { onMount, type Snippet } from 'svelte'
22
+ import { useThrelte, watch } from '@threlte/core'
23
+ import type { XRSessionEvent } from '../types'
24
+ import {
25
+ isHandTracking,
26
+ isPresenting,
27
+ referenceSpaceType,
28
+ session,
29
+ xr as xrStore
30
+ } from '../internal/stores'
31
+ import { setupRaf } from '../internal/setupRaf'
32
+ import { setupHeadset } from '../internal/setupHeadset'
33
+ import { setupControllers } from '../internal/setupControllers'
34
+ import { setupHands } from '../internal/setupHands'
35
+
36
+ interface Props {
37
+ /**
38
+ * Enables foveated rendering. Default is `1`, the three.js default.
39
+ *
40
+ * 0 = no foveation, full resolution
41
+ *
42
+ * 1 = maximum foveation, the edges render at lower resolution
43
+ */
44
+ foveation?: number
45
+
46
+ /**
47
+ * The target framerate for the XRSystem. Smaller rates give more CPU headroom at the cost of responsiveness.
48
+ * Recommended range is `72`-`120`. Default is unset and left to the device.
49
+ * @note If your experience cannot effectively reach the target framerate, it will be subject to frame reprojection
50
+ * which will halve the effective framerate. Choose a conservative estimate that balances responsiveness and
51
+ * headroom based on your experience.
52
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebXR_Device_API/Rendering#refresh_rate_and_frame_rate
53
+ */
54
+ frameRate?: number | undefined
55
+
56
+ /** Type of WebXR reference space to use. Default is `local-floor` */
57
+ referenceSpace?: XRReferenceSpaceType
58
+
59
+ fallback?: Snippet
60
+ children?: Snippet
61
+
62
+ /** Called as an XRSession is requested */
63
+ onsessionstart?: (event: XRSessionEvent<'sessionstart'>) => void
64
+
65
+ /** Called after an XRSession is terminated */
66
+ onsessionend?: (event: XRSessionEvent<'sessionend'>) => void
67
+
68
+ /** Called when an XRSession is hidden or unfocused. */
69
+ onvisibilitychange?: (event: globalThis.XRSessionEvent) => void
70
+
71
+ /** Called when available inputsources change */
72
+ oninputsourceschange?: (event: globalThis.XRSessionEvent) => void
76
73
  }
77
- };
78
- watch(session, (currentSession) => {
79
- if (currentSession === void 0)
80
- return;
81
- currentSession.addEventListener("visibilitychange", handleVisibilityChange);
82
- currentSession.addEventListener("inputsourceschange", handleInputSourcesChange);
83
- currentSession.addEventListener("frameratechange", handleFramerateChange);
84
- xr.setFoveation(foveation);
85
- updateTargetFrameRate(frameRate);
86
- return () => {
87
- currentSession.removeEventListener("visibilitychange", handleVisibilityChange);
88
- currentSession.removeEventListener("inputsourceschange", handleInputSourcesChange);
89
- currentSession.removeEventListener("frameratechange", handleFramerateChange);
90
- };
91
- });
92
- watch(isPresenting, (presenting) => {
93
- if (presenting) {
94
- originalRenderMode = renderMode.current;
95
- renderMode.set("always");
96
- } else {
97
- renderMode.set(originalRenderMode);
74
+
75
+ let {
76
+ foveation = 1,
77
+ frameRate,
78
+ referenceSpace = 'local-floor',
79
+ onsessionstart,
80
+ onsessionend,
81
+ onvisibilitychange,
82
+ oninputsourceschange,
83
+ fallback,
84
+ children
85
+ }: Props = $props()
86
+
87
+ const { renderer, renderMode } = useThrelte()
88
+ const { xr } = renderer
89
+
90
+ let originalRenderMode = $renderMode
91
+
92
+ setupRaf()
93
+ setupHeadset()
94
+ setupControllers()
95
+ setupHands()
96
+
97
+ const handleSessionStart = () => {
98
+ isPresenting.set(true)
99
+ onsessionstart?.({ type: 'sessionstart', target: $session! })
100
+ }
101
+
102
+ const handleSessionEnd = () => {
103
+ onsessionend?.({ type: 'sessionend', target: $session! })
104
+ isPresenting.set(false)
105
+ session.set(undefined)
106
+ }
107
+
108
+ const handleVisibilityChange = (event: globalThis.XRSessionEvent) => {
109
+ onvisibilitychange?.({ ...event, target: $session! })
98
110
  }
99
- });
100
- onMount(() => {
101
- $xrStore = xr;
102
- xr.enabled = true;
103
- xr.addEventListener("sessionstart", handleSessionStart);
104
- xr.addEventListener("sessionend", handleSessionEnd);
105
- return () => {
106
- $xrStore = void 0;
107
- xr.enabled = false;
108
- xr.removeEventListener("sessionstart", handleSessionStart);
109
- xr.removeEventListener("sessionend", handleSessionEnd);
110
- };
111
- });
112
- $effect.pre(() => updateTargetFrameRate(frameRate));
113
- $effect.pre(() => xr.setFoveation(foveation));
114
- $effect.pre(() => {
115
- xr.setReferenceSpaceType(referenceSpace);
116
- $referenceSpaceType = referenceSpace;
117
- });
111
+
112
+ const handleInputSourcesChange = (event: XRInputSourceChangeEvent) => {
113
+ $isHandTracking = Object.values(event.session.inputSources).some((source) => source.hand)
114
+ oninputsourceschange?.({ ...event, target: $session! })
115
+ }
116
+
117
+ const handleFramerateChange = (event: globalThis.XRSessionEvent) => {
118
+ onvisibilitychange?.({ ...event, target: $session! })
119
+ }
120
+
121
+ const updateTargetFrameRate = (frameRate?: number) => {
122
+ if (frameRate === undefined) return
123
+
124
+ try {
125
+ $session?.updateTargetFrameRate(frameRate)
126
+ } catch {
127
+ // Do nothing
128
+ }
129
+ }
130
+
131
+ watch(session, (currentSession) => {
132
+ if (currentSession === undefined) return
133
+
134
+ currentSession.addEventListener('visibilitychange', handleVisibilityChange)
135
+ currentSession.addEventListener('inputsourceschange', handleInputSourcesChange)
136
+ currentSession.addEventListener('frameratechange', handleFramerateChange)
137
+
138
+ xr.setFoveation(foveation)
139
+
140
+ updateTargetFrameRate(frameRate)
141
+
142
+ return () => {
143
+ currentSession.removeEventListener('visibilitychange', handleVisibilityChange)
144
+ currentSession.removeEventListener('inputsourceschange', handleInputSourcesChange)
145
+ currentSession.removeEventListener('frameratechange', handleFramerateChange)
146
+ }
147
+ })
148
+
149
+ watch(isPresenting, (presenting) => {
150
+ if (presenting) {
151
+ originalRenderMode = renderMode.current
152
+ renderMode.set('always')
153
+ } else {
154
+ renderMode.set(originalRenderMode)
155
+ }
156
+ })
157
+
158
+ onMount(() => {
159
+ $xrStore = xr
160
+ xr.enabled = true
161
+ xr.addEventListener('sessionstart', handleSessionStart)
162
+ xr.addEventListener('sessionend', handleSessionEnd)
163
+
164
+ return () => {
165
+ $xrStore = undefined
166
+ xr.enabled = false
167
+ xr.removeEventListener('sessionstart', handleSessionStart)
168
+ xr.removeEventListener('sessionend', handleSessionEnd)
169
+ }
170
+ })
171
+
172
+ $effect.pre(() => updateTargetFrameRate(frameRate))
173
+ $effect.pre(() => xr.setFoveation(foveation))
174
+ $effect.pre(() => {
175
+ xr.setReferenceSpaceType(referenceSpace)
176
+ $referenceSpaceType = referenceSpace
177
+ })
118
178
  </script>
119
179
 
120
180
  {#if $isPresenting}
@@ -1,47 +1,5 @@
1
- /// <reference types="webxr" />
2
- import { SvelteComponent } from "svelte";
3
1
  import { type Snippet } from 'svelte';
4
2
  import type { XRSessionEvent } from '../types';
5
- declare const __propDef: {
6
- props: {
7
- /**
8
- * Enables foveated rendering. Default is `1`, the three.js default.
9
- *
10
- * 0 = no foveation, full resolution
11
- *
12
- * 1 = maximum foveation, the edges render at lower resolution
13
- */
14
- foveation?: number | undefined;
15
- /**
16
- * The target framerate for the XRSystem. Smaller rates give more CPU headroom at the cost of responsiveness.
17
- * Recommended range is `72`-`120`. Default is unset and left to the device.
18
- * @note If your experience cannot effectively reach the target framerate, it will be subject to frame reprojection
19
- * which will halve the effective framerate. Choose a conservative estimate that balances responsiveness and
20
- * headroom based on your experience.
21
- * @see https://developer.mozilla.org/en-US/docs/Web/API/WebXR_Device_API/Rendering#refresh_rate_and_frame_rate
22
- */
23
- frameRate?: number | undefined;
24
- /** Type of WebXR reference space to use. Default is `local-floor` */
25
- referenceSpace?: XRReferenceSpaceType | undefined;
26
- fallback?: Snippet<[]> | undefined;
27
- children?: Snippet<[]> | undefined;
28
- /** Called as an XRSession is requested */
29
- onsessionstart?: ((event: XRSessionEvent<'sessionstart'>) => void) | undefined;
30
- /** Called after an XRSession is terminated */
31
- onsessionend?: ((event: XRSessionEvent<'sessionend'>) => void) | undefined;
32
- /** Called when an XRSession is hidden or unfocused. */
33
- onvisibilitychange?: ((event: globalThis.XRSessionEvent) => void) | undefined;
34
- /** Called when available inputsources change */
35
- oninputsourceschange?: ((event: globalThis.XRSessionEvent) => void) | undefined;
36
- };
37
- events: {
38
- [evt: string]: CustomEvent<any>;
39
- };
40
- slots: {};
41
- };
42
- export type XrProps = typeof __propDef.props;
43
- export type XrEvents = typeof __propDef.events;
44
- export type XrSlots = typeof __propDef.slots;
45
3
  /**
46
4
  * `<XR />` is a WebXR manager that configures your scene for XR rendering and interaction.
47
5
  *
@@ -59,6 +17,35 @@ export type XrSlots = typeof __propDef.slots;
59
17
  * />
60
18
  * ```
61
19
  */
62
- export default class Xr extends SvelteComponent<XrProps, XrEvents, XrSlots> {
63
- }
64
- export {};
20
+ declare const Xr: import("svelte").Component<{
21
+ /**
22
+ * Enables foveated rendering. Default is `1`, the three.js default.
23
+ *
24
+ * 0 = no foveation, full resolution
25
+ *
26
+ * 1 = maximum foveation, the edges render at lower resolution
27
+ */
28
+ foveation?: number;
29
+ /**
30
+ * The target framerate for the XRSystem. Smaller rates give more CPU headroom at the cost of responsiveness.
31
+ * Recommended range is `72`-`120`. Default is unset and left to the device.
32
+ * @note If your experience cannot effectively reach the target framerate, it will be subject to frame reprojection
33
+ * which will halve the effective framerate. Choose a conservative estimate that balances responsiveness and
34
+ * headroom based on your experience.
35
+ * @see https://developer.mozilla.org/en-US/docs/Web/API/WebXR_Device_API/Rendering#refresh_rate_and_frame_rate
36
+ */
37
+ frameRate?: number | undefined;
38
+ /** Type of WebXR reference space to use. Default is `local-floor` */
39
+ referenceSpace?: XRReferenceSpaceType;
40
+ fallback?: Snippet;
41
+ children?: Snippet;
42
+ /** Called as an XRSession is requested */
43
+ onsessionstart?: (event: XRSessionEvent<"sessionstart">) => void;
44
+ /** Called after an XRSession is terminated */
45
+ onsessionend?: (event: XRSessionEvent<"sessionend">) => void;
46
+ /** Called when an XRSession is hidden or unfocused. */
47
+ onvisibilitychange?: (event: globalThis.XRSessionEvent) => void;
48
+ /** Called when available inputsources change */
49
+ oninputsourceschange?: (event: globalThis.XRSessionEvent) => void;
50
+ }, {}, "">;
51
+ export default Xr;
@@ -17,43 +17,75 @@ display info about your WebXR session. This is aliased by `ARButton` and
17
17
  />
18
18
  ```
19
19
  -->
20
- <script lang="ts">import { getXRSupportState } from "../lib/getXRSupportState";
21
- import { toggleXRSession } from "../lib/toggleXRSession";
22
- import { session, xr } from "../internal/stores";
23
- let {
24
- mode,
25
- sessionInit,
26
- force,
27
- styled = true,
28
- onclick,
29
- onerror,
30
- children,
31
- ...props
32
- } = $props();
33
- const handleButtonClick = async (nativeEvent, state) => {
34
- if (!$xr) {
35
- throw new Error(
36
- "The <XR> component was not created. This is required to start an XR session."
37
- );
20
+ <script lang="ts">
21
+ import type { HTMLButtonAttributes } from 'svelte/elements'
22
+ import { getXRSupportState } from '../lib/getXRSupportState'
23
+ import { toggleXRSession } from '../lib/toggleXRSession'
24
+ import { session, xr } from '../internal/stores'
25
+ import type { Snippet } from 'svelte'
26
+
27
+ type Props = HTMLButtonAttributes & {
28
+ /** The type of `XRSession` to create */
29
+ mode: XRSessionMode
30
+ /**
31
+ * `XRSession` configuration options
32
+ * @see https://immersive-web.github.io/webxr/#feature-dependencies
33
+ */
34
+ sessionInit?: XRSessionInit & { domOverlay?: { root: HTMLElement } | undefined }
35
+ /** Whether this button should only enter / exit an `XRSession`. Default is to toggle both ways */
36
+ force?: 'enter' | 'exit'
37
+ /** Whether to apply automatic styling to the button. Set false to apply custom styles. Default is true. */
38
+ styled?: boolean
39
+
40
+ children?: Snippet<[{ state: SupportState }]>
41
+
42
+ onclick?: (event: { state: SupportState; nativeEvent: MouseEvent }) => void
43
+ onerror?: (error: Error) => void
38
44
  }
39
- onclick?.({ state, nativeEvent });
40
- if (state !== "supported")
41
- return;
42
- try {
43
- await toggleXRSession(mode, sessionInit, force);
44
- } catch (error) {
45
- onerror?.(error);
45
+
46
+ let {
47
+ mode,
48
+ sessionInit,
49
+ force,
50
+ styled = true,
51
+ onclick,
52
+ onerror,
53
+ children,
54
+ ...props
55
+ }: Props = $props()
56
+
57
+ type SupportState = 'unsupported' | 'insecure' | 'blocked' | 'supported'
58
+
59
+ const handleButtonClick = async (nativeEvent: MouseEvent, state: SupportState) => {
60
+ if (!$xr) {
61
+ throw new Error(
62
+ 'The <XR> component was not created. This is required to start an XR session.'
63
+ )
64
+ }
65
+
66
+ onclick?.({ state, nativeEvent })
67
+
68
+ if (state !== 'supported') return
69
+
70
+ try {
71
+ await toggleXRSession(mode, sessionInit, force)
72
+ } catch (error) {
73
+ /** This callback gets fired if XR initialization fails. */
74
+ onerror?.(error as Error)
75
+ }
46
76
  }
47
- };
48
- let modeText = $derived(
49
- {
50
- "immersive-vr": "VR",
51
- "immersive-ar": "AR",
52
- inline: "inline"
53
- }[mode]
54
- );
55
- let style = $derived(
56
- styled ? `
77
+
78
+ let modeText = $derived(
79
+ {
80
+ 'immersive-vr': 'VR',
81
+ 'immersive-ar': 'AR',
82
+ inline: 'inline'
83
+ }[mode]
84
+ )
85
+
86
+ let style = $derived(
87
+ styled
88
+ ? `
57
89
  position: absolute;
58
90
  bottom: 24px;
59
91
  left: 50%;
@@ -64,9 +96,10 @@ let style = $derived(
64
96
  color: white;
65
97
  outline: none;
66
98
  z-index: 10;
67
- ${props.style ?? ""}
68
- ` : props.style
69
- );
99
+ ${props.style ?? ''}
100
+ `
101
+ : props.style
102
+ )
70
103
  </script>
71
104
 
72
105
  {#await getXRSupportState(mode) then state}
@@ -1,41 +1,5 @@
1
- /// <reference types="webxr" />
2
- import { SvelteComponent } from "svelte";
3
1
  import type { HTMLButtonAttributes } from 'svelte/elements';
4
2
  import type { Snippet } from 'svelte';
5
- declare const __propDef: {
6
- props: HTMLButtonAttributes & {
7
- /** The type of `XRSession` to create */
8
- mode: XRSessionMode;
9
- /**
10
- * `XRSession` configuration options
11
- * @see https://immersive-web.github.io/webxr/#feature-dependencies
12
- */
13
- sessionInit?: (XRSessionInit & {
14
- domOverlay?: {
15
- root: HTMLElement;
16
- } | undefined;
17
- }) | undefined;
18
- /** Whether this button should only enter / exit an `XRSession`. Default is to toggle both ways */
19
- force?: "enter" | "exit" | undefined;
20
- /** Whether to apply automatic styling to the button. Set false to apply custom styles. Default is true. */
21
- styled?: boolean | undefined;
22
- children?: Snippet<[{
23
- state: "blocked" | "unsupported" | "insecure" | "supported";
24
- }]> | undefined;
25
- onclick?: ((event: {
26
- state: "blocked" | "unsupported" | "insecure" | "supported";
27
- nativeEvent: MouseEvent;
28
- }) => void) | undefined;
29
- onerror?: ((error: Error) => void) | undefined;
30
- };
31
- events: {
32
- [evt: string]: CustomEvent<any>;
33
- };
34
- slots: {};
35
- };
36
- export type XrButtonProps = typeof __propDef.props;
37
- export type XrButtonEvents = typeof __propDef.events;
38
- export type XrButtonSlots = typeof __propDef.slots;
39
3
  /**
40
4
  * `<XRButton />` is an HTML `<button />` that can be used to init and
41
5
  * display info about your WebXR session. This is aliased by `ARButton` and
@@ -54,6 +18,29 @@ export type XrButtonSlots = typeof __propDef.slots;
54
18
  * />
55
19
  * ```
56
20
  */
57
- export default class XrButton extends SvelteComponent<XrButtonProps, XrButtonEvents, XrButtonSlots> {
58
- }
59
- export {};
21
+ declare const XrButton: import("svelte").Component<HTMLButtonAttributes & {
22
+ /** The type of `XRSession` to create */
23
+ mode: XRSessionMode;
24
+ /**
25
+ * `XRSession` configuration options
26
+ * @see https://immersive-web.github.io/webxr/#feature-dependencies
27
+ */
28
+ sessionInit?: XRSessionInit & {
29
+ domOverlay?: {
30
+ root: HTMLElement;
31
+ } | undefined;
32
+ };
33
+ /** Whether this button should only enter / exit an `XRSession`. Default is to toggle both ways */
34
+ force?: "enter" | "exit";
35
+ /** Whether to apply automatic styling to the button. Set false to apply custom styles. Default is true. */
36
+ styled?: boolean;
37
+ children?: Snippet<[{
38
+ state: "blocked" | "unsupported" | "insecure" | "supported";
39
+ }]>;
40
+ onclick?: (event: {
41
+ state: "blocked" | "unsupported" | "insecure" | "supported";
42
+ nativeEvent: MouseEvent;
43
+ }) => void;
44
+ onerror?: (error: Error) => void;
45
+ }, {}, "">;
46
+ export default XrButton;
@@ -1,7 +1,16 @@
1
- <script lang="ts">import { Color, DoubleSide, RawShaderMaterial } from "three";
2
- import { T } from "@threlte/core";
3
- let { color = new Color("white"), size = 0.03, thickness = 0.035 } = $props();
4
- const vertexShader = `
1
+ <script lang="ts">
2
+ import { Color, DoubleSide, RawShaderMaterial, type ColorRepresentation } from 'three'
3
+ import { T } from '@threlte/core'
4
+
5
+ interface Props {
6
+ color?: ColorRepresentation
7
+ size?: number
8
+ thickness?: number
9
+ }
10
+
11
+ let { color = new Color('white'), size = 0.03, thickness = 0.035 }: Props = $props()
12
+
13
+ const vertexShader = `
5
14
  uniform mat4 projectionMatrix;
6
15
  uniform mat4 modelViewMatrix;
7
16
  attribute vec2 uv;
@@ -11,8 +20,9 @@ const vertexShader = `
11
20
  vUv = uv;
12
21
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
13
22
  }
14
- `;
15
- const fragmentShader = `
23
+ `
24
+
25
+ const fragmentShader = `
16
26
  precision mediump float;
17
27
  uniform float thickness;
18
28
  uniform vec3 color;
@@ -23,25 +33,28 @@ const fragmentShader = `
23
33
  float alpha = 1.0 - step(thickness, abs(distance(vUv, vec2(0.5)) - 0.25));
24
34
  gl_FragColor = vec4(color, alpha);
25
35
  }
26
- `;
27
- const uniforms = {
28
- thickness: { value: thickness },
29
- color: { value: color }
30
- };
31
- const shaderMaterial = new RawShaderMaterial({
32
- vertexShader,
33
- fragmentShader,
34
- uniforms,
35
- side: DoubleSide,
36
- transparent: true,
37
- depthTest: false
38
- });
39
- $effect.pre(() => {
40
- uniforms.thickness.value = thickness;
41
- });
42
- $effect.pre(() => {
43
- uniforms.color.value = color;
44
- });
36
+ `
37
+
38
+ const uniforms = {
39
+ thickness: { value: thickness },
40
+ color: { value: color }
41
+ }
42
+
43
+ const shaderMaterial = new RawShaderMaterial({
44
+ vertexShader,
45
+ fragmentShader,
46
+ uniforms,
47
+ side: DoubleSide,
48
+ transparent: true,
49
+ depthTest: false
50
+ })
51
+
52
+ $effect.pre(() => {
53
+ uniforms.thickness.value = thickness
54
+ })
55
+ $effect.pre(() => {
56
+ uniforms.color.value = color
57
+ })
45
58
  </script>
46
59
 
47
60
  <T.Mesh scale={size}>
@@ -1,19 +1,7 @@
1
- import { SvelteComponent } from "svelte";
2
1
  import { type ColorRepresentation } from 'three';
3
- declare const __propDef: {
4
- props: {
5
- color?: ColorRepresentation | undefined;
6
- size?: number | undefined;
7
- thickness?: number | undefined;
8
- };
9
- events: {
10
- [evt: string]: CustomEvent<any>;
11
- };
12
- slots: {};
13
- };
14
- export type CursorProps = typeof __propDef.props;
15
- export type CursorEvents = typeof __propDef.events;
16
- export type CursorSlots = typeof __propDef.slots;
17
- export default class Cursor extends SvelteComponent<CursorProps, CursorEvents, CursorSlots> {
18
- }
19
- export {};
2
+ declare const Cursor: import("svelte").Component<{
3
+ color?: ColorRepresentation;
4
+ size?: number;
5
+ thickness?: number;
6
+ }, {}, "">;
7
+ export default Cursor;