@splinetool/react-spline
Advanced tools
Comparing version 1.0.0 to 2.0.0
@@ -177,6 +177,4 @@ var __defProp = Object.defineProperty; | ||
}); | ||
const init = async function() { | ||
const response = await fetch(scene); | ||
const buffer = await response.arrayBuffer(); | ||
speApp.start(buffer); | ||
async function init() { | ||
await speApp.load(scene); | ||
for (let event of events) { | ||
@@ -189,3 +187,3 @@ if (event.cb) { | ||
onLoad == null ? void 0 : onLoad(speApp); | ||
}; | ||
} | ||
init(); | ||
@@ -214,2 +212,2 @@ } | ||
}); | ||
export { Spline }; | ||
export { Spline as default }; |
@@ -1,6 +0,6 @@ | ||
var K=Object.defineProperty;var E=Object.getOwnPropertySymbols;var Q=Object.prototype.hasOwnProperty,V=Object.prototype.propertyIsEnumerable;var P=(t,r,i)=>r in t?K(t,r,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[r]=i,R=(t,r)=>{for(var i in r||(r={}))Q.call(r,i)&&P(t,i,r[i]);if(E)for(var i of E(r))V.call(r,i)&&P(t,i,r[i]);return t};(function(t,r){typeof exports=="object"&&typeof module!="undefined"?r(exports,require("react"),require("@splinetool/runtime")):typeof define=="function"&&define.amd?define(["exports","react","@splinetool/runtime"],r):(t=typeof globalThis!="undefined"?globalThis:t||self,r(t["react-spline"]={},t.React,t.SPRuntime))})(this,function(t,r,i){"use strict";function x(e){return e&&typeof e=="object"&&"default"in e?e:{default:e}}var k=x(r),v={exports:{}},p={};/* | ||
var z=Object.defineProperty;var E=Object.getOwnPropertySymbols;var G=Object.prototype.hasOwnProperty,K=Object.prototype.propertyIsEnumerable;var x=(r,f,i)=>f in r?z(r,f,{enumerable:!0,configurable:!0,writable:!0,value:i}):r[f]=i,R=(r,f)=>{for(var i in f||(f={}))G.call(f,i)&&x(r,i,f[i]);if(E)for(var i of E(f))K.call(f,i)&&x(r,i,f[i]);return r};(function(r,f){typeof exports=="object"&&typeof module!="undefined"?module.exports=f(require("react"),require("@splinetool/runtime")):typeof define=="function"&&define.amd?define(["react","@splinetool/runtime"],f):(r=typeof globalThis!="undefined"?globalThis:r||self,r["react-spline"]=f(r.React,r.SPRuntime))})(this,function(r,f){"use strict";function i(e){return e&&typeof e=="object"&&"default"in e?e:{default:e}}var P=i(r),v={exports:{}},p={};/* | ||
object-assign | ||
(c) Sindre Sorhus | ||
@license MIT | ||
*/var O=Object.getOwnPropertySymbols,T=Object.prototype.hasOwnProperty,I=Object.prototype.propertyIsEnumerable;function N(e){if(e==null)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}function D(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de",Object.getOwnPropertyNames(e)[0]==="5")return!1;for(var n={},o=0;o<10;o++)n["_"+String.fromCharCode(o)]=o;var f=Object.getOwnPropertyNames(n).map(function(a){return n[a]});if(f.join("")!=="0123456789")return!1;var s={};return"abcdefghijklmnopqrst".split("").forEach(function(a){s[a]=a}),Object.keys(Object.assign({},s)).join("")==="abcdefghijklmnopqrst"}catch{return!1}}D();/** @license React v17.0.2 | ||
*/var O=Object.getOwnPropertySymbols,k=Object.prototype.hasOwnProperty,I=Object.prototype.propertyIsEnumerable;function N(e){if(e==null)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}function T(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de",Object.getOwnPropertyNames(e)[0]==="5")return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;var o=Object.getOwnPropertyNames(t).map(function(s){return t[s]});if(o.join("")!=="0123456789")return!1;var a={};return"abcdefghijklmnopqrst".split("").forEach(function(s){a[s]=s}),Object.keys(Object.assign({},a)).join("")==="abcdefghijklmnopqrst"}catch{return!1}}T();/** @license React v17.0.2 | ||
* react-jsx-runtime.production.min.js | ||
@@ -12,2 +12,2 @@ * | ||
* LICENSE file in the root directory of this source tree. | ||
*/var U=k.default,j=60103;if(p.Fragment=60107,typeof Symbol=="function"&&Symbol.for){var _=Symbol.for;j=_("react.element"),p.Fragment=_("react.fragment")}var A=U.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,C=Object.prototype.hasOwnProperty,L={key:!0,ref:!0,__self:!0,__source:!0};function g(e,n,o){var f,s={},a=null,c=null;o!==void 0&&(a=""+o),n.key!==void 0&&(a=""+n.key),n.ref!==void 0&&(c=n.ref);for(f in n)C.call(n,f)&&!L.hasOwnProperty(f)&&(s[f]=n[f]);if(e&&e.defaultProps)for(f in n=e.defaultProps,n)s[f]===void 0&&(s[f]=n[f]);return{$$typeof:j,type:e,key:a,ref:c,props:s,_owner:A.current}}p.jsx=g,p.jsxs=g,v.exports=p;const w=v.exports.jsx,F=r.forwardRef(({scene:e,id:n,style:o,className:f,onMouseDown:s,onMouseUp:a,onMouseHover:c,onKeyDown:u,onKeyUp:q,onStart:B,onLookAt:M,onFollow:H,onWheel:J,onLoad:b,autoRender:W=!1},Y)=>{const d=r.useRef(null),[z,h]=r.useState(!0);return r.useEffect(()=>{h(!0);let l;const S=[{name:"mouseDown",cb:s},{name:"mouseUp",cb:a},{name:"mouseHover",cb:c},{name:"keyDown",cb:u},{name:"keyUp",cb:q},{name:"start",cb:B},{name:"lookAt",cb:M},{name:"follow",cb:H},{name:"scroll",cb:J}];return d.current&&(l=new i.Application(d.current,{autoRender:W}),async function(){const G=await(await fetch(e)).arrayBuffer();l.start(G);for(let y of S)y.cb&&l.addEventListener(y.name,y.cb);h(!1),b==null||b(l)}()),()=>{for(let m of S)m.cb&&l.removeEventListener(m.name,m.cb);l.dispose()}},[e]),w("div",{style:R({display:`${z?"none":"flex"}`},o),className:f,ref:Y,children:w("canvas",{ref:d,id:n})})});t.Spline=F,Object.defineProperty(t,"__esModule",{value:!0}),t[Symbol.toStringTag]="Module"}); | ||
*/var D=P.default,j=60103;if(p.Fragment=60107,typeof Symbol=="function"&&Symbol.for){var _=Symbol.for;j=_("react.element"),p.Fragment=_("react.fragment")}var U=D.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,A=Object.prototype.hasOwnProperty,C={key:!0,ref:!0,__self:!0,__source:!0};function g(e,t,n){var o,a={},s=null,c=null;n!==void 0&&(s=""+n),t.key!==void 0&&(s=""+t.key),t.ref!==void 0&&(c=t.ref);for(o in t)A.call(t,o)&&!C.hasOwnProperty(o)&&(a[o]=t[o]);if(e&&e.defaultProps)for(o in t=e.defaultProps,t)a[o]===void 0&&(a[o]=t[o]);return{$$typeof:j,type:e,key:s,ref:c,props:a,_owner:U.current}}p.jsx=g,p.jsxs=g,v.exports=p;const w=v.exports.jsx;return r.forwardRef(({scene:e,id:t,style:n,className:o,onMouseDown:a,onMouseUp:s,onMouseHover:c,onKeyDown:u,onKeyUp:L,onStart:F,onLookAt:q,onFollow:B,onWheel:H,onLoad:b,autoRender:J=!1},W)=>{const d=r.useRef(null),[Y,h]=r.useState(!0);return r.useEffect(()=>{h(!0);let l;const S=[{name:"mouseDown",cb:a},{name:"mouseUp",cb:s},{name:"mouseHover",cb:c},{name:"keyDown",cb:u},{name:"keyUp",cb:L},{name:"start",cb:F},{name:"lookAt",cb:q},{name:"follow",cb:B},{name:"scroll",cb:H}];if(d.current){l=new f.Application(d.current,{autoRender:J});async function m(){await l.load(e);for(let y of S)y.cb&&l.addEventListener(y.name,y.cb);h(!1),b==null||b(l)}m()}return()=>{for(let m of S)m.cb&&l.removeEventListener(m.name,m.cb);l.dispose()}},[e]),w("div",{style:R({display:`${Y?"none":"flex"}`},n),className:o,ref:W,children:w("canvas",{ref:d,id:t})})})}); |
@@ -22,2 +22,3 @@ import { CSSProperties } from 'react'; | ||
} | ||
export declare const Spline: import("react").ForwardRefExoticComponent<SplineProps & import("react").RefAttributes<HTMLDivElement>>; | ||
declare const Spline: import("react").ForwardRefExoticComponent<SplineProps & import("react").RefAttributes<HTMLDivElement>>; | ||
export default Spline; |
{ | ||
"name": "@splinetool/react-spline", | ||
"version": "1.0.0", | ||
"version": "2.0.0", | ||
"files": [ | ||
@@ -23,3 +23,3 @@ "dist" | ||
"devDependencies": { | ||
"@splinetool/runtime": "^0.9.8", | ||
"@splinetool/runtime": "^0.9.15", | ||
"@types/animejs": "^3.1.4", | ||
@@ -26,0 +26,0 @@ "@types/node": "^16.11.9", |
199
README.md
@@ -0,10 +1,12 @@ | ||
![](.github/screenshots/hero.png) | ||
# react-spline | ||
**react-spline** allows you to export and use Spline scenes directly in your React websites. | ||
š [Spline](https://spline.design/) is a friendly 3d collaborative design tool for the web. | ||
**react-spline** allows you to export and use spline scenes directly in your React websites. | ||
[Website](https://spline.design/) — | ||
[Twitter](https://twitter.com/splinetool) — | ||
[Discord](https://discord.gg/M9hNDMqvnw) — | ||
[Community](https://discord.gg/M9hNDMqvnw) — | ||
[Documentation](https://docs.spline.design/) | ||
@@ -19,2 +21,4 @@ | ||
- [Trigger Spline events from outside](#trigger-spline-events-from-outside) | ||
- [Usage with Next.js](#usage-with-nextjs) | ||
- [Lazy loading](#lazy-loading) | ||
- [API](#api) | ||
@@ -40,3 +44,3 @@ - [Spline Component Props](#spline-component-props) | ||
To use react-spline, first you have to go to the Spline editor, click on the Export button and select "**React Component**". | ||
To use react-spline, first you have to go to the Spline editor, click on the **Export** button and select "**React Component**". | ||
@@ -49,3 +53,3 @@ Spline generates links for Development (Drafts) and Production. | ||
<img src="./.github/screenshots/react-export-pane.png" width="250"> | ||
<img width="250" src=".github/screenshots/react-export-pane.png"> | ||
@@ -55,9 +59,9 @@ Once you have a draft or production URL, you can start using the react-spline component in React. | ||
```jsx | ||
import { Spline } from '@splinetool/react-spline'; | ||
import Spline from '@splinetool/react-spline'; | ||
function App() { | ||
export default function App() { | ||
return ( | ||
<main> | ||
<Spline scene="[DRAFT OR PROD URL]" /> | ||
</main> | ||
<div> | ||
<Spline scene="https://prod.spline.design/TRfTj83xgjIdHPmT/scene.spline" /> | ||
</div> | ||
); | ||
@@ -67,2 +71,6 @@ } | ||
You should be able to see the scene you exported in your React app. | ||
[![](.github/screenshots/example-basic.png)](https://codesandbox.io/s/sweet-rain-28pcxt?file=/src/App.js) | ||
### Read and modify Spline objects | ||
@@ -75,30 +83,33 @@ | ||
```jsx | ||
import { SplineĀ } from '@splinetool/react-spline' | ||
import Spline from '@splinetool/react-spline'; | ||
function App() { | ||
const [myObj, setMyObj] = useState(null) | ||
export default function App() { | ||
const [myObj, setMyObj] = useState(null); | ||
function onLoad(spline) { | ||
const obj = spline.findObjectById('8E8C2DDD-18B6-4C54-861D-7ED2519DE20E') | ||
const obj = spline.findObjectById('8E8C2DDD-18B6-4C54-861D-7ED2519DE20E'); | ||
// or | ||
// const obj = spline.findObjectByName('my object') | ||
// const obj = spline.findObjectByName('my object'); | ||
setMyObj(obj) | ||
setMyObj(obj); | ||
} | ||
function moveObj() { | ||
console.log(myObj) // Spline Object => { name: 'my object', id: '8E8C2DDD-18B6-4C54-861D-7ED2519DE20E', position: {}, ... } | ||
console.log(myObj); // Spline Object => { name: 'my object', id: '8E8C2DDD-18B6-4C54-861D-7ED2519DE20E', position: {}, ... } | ||
// move the object in 3D space | ||
myObj.position.x += 10 | ||
myObj.position.x += 10; | ||
} | ||
return ( | ||
<main> | ||
<Spline scene="[DRAFT OR PROD URL]" onLoad={onLoad}/> | ||
<button type="button" onClick={moveObj}/> | ||
<div> | ||
<Spline | ||
scene="https://prod.spline.design/TRfTj83xgjIdHPmT/scene.spline" | ||
onLoad={onLoad} | ||
/> | ||
<button type="button" onClick={moveObj}> | ||
Move {myObj.name} | ||
</button> | ||
</main> | ||
) | ||
</div> | ||
); | ||
} | ||
@@ -112,5 +123,5 @@ ``` | ||
```jsx | ||
import { Spline } from '@splinetool/react-spline'; | ||
import Spline from '@splinetool/react-spline'; | ||
function App() { | ||
export default function App() { | ||
function onMouseDown(e) { | ||
@@ -123,5 +134,8 @@ if (e.target.id === '8E8C2DDD-18B6-4C54-861D-7ED2519DE20E') { | ||
return ( | ||
<main> | ||
<Spline scene="[DRAFT OR PROD URL]" onMouseDown={onMouseDown} /> | ||
</main> | ||
<div> | ||
<Spline | ||
scene="https://prod.spline.design/TRfTj83xgjIdHPmT/scene.spline" | ||
onMouseDown={onMouseDown} | ||
/> | ||
</div> | ||
); | ||
@@ -142,25 +156,27 @@ } | ||
```jsx | ||
import { SplineĀ } from '@splinetool/react-spline' | ||
import Spline from '@splinetool/react-spline'; | ||
function App() { | ||
const [spline, setSpline] = useState() | ||
export default function App() { | ||
const [spline, setSpline] = useState(); | ||
function onLoad(spline) { | ||
setSpline(spline) | ||
setSpline(spline); | ||
} | ||
function triggerAnimation() { | ||
spline.emitEvent('mouseHover', '8E8C2DDD-18B6-4C54-861D-7ED2519DE20E') | ||
spline.emitEvent('mouseHover', '8E8C2DDD-18B6-4C54-861D-7ED2519DE20E'); | ||
} | ||
return ( | ||
<main> | ||
<Spline scene="[DRAFT OR PROD URL]" onLoad={onLoad} /> | ||
<button type="button" onClick={triggerAnimation}/> | ||
<div> | ||
<Spline | ||
scene="https://prod.spline.design/TRfTj83xgjIdHPmT/scene.spline" | ||
onLoad={onLoad} | ||
/> | ||
<button type="button" onClick={triggerAnimation}> | ||
Trigger Spline Animation | ||
</button> | ||
</main> | ||
) | ||
</div> | ||
); | ||
} | ||
``` | ||
@@ -171,44 +187,61 @@ | ||
```jsx | ||
import { SplineĀ } from '@splinetool/react-spline' | ||
import Spline from '@splinetool/react-spline'; | ||
function App() { | ||
const [objectToAnimate, setObjectToAnimate] = useState(null) | ||
export default function App() { | ||
const [objectToAnimate, setObjectToAnimate] = useState(null); | ||
function onLoad(spline) { | ||
const obj = spline.findObjectById('8E8C2DDD-18B6-4C54-861D-7ED2519DE20E') | ||
setObjectToAnimate(obj) | ||
const obj = spline.findObjectById('8E8C2DDD-18B6-4C54-861D-7ED2519DE20E'); | ||
setObjectToAnimate(obj); | ||
} | ||
function triggerAnimation() { | ||
objectToAnimate.emitEvent('mouseHover') | ||
objectToAnimate.emitEvent('mouseHover'); | ||
} | ||
return ( | ||
<main> | ||
<Spline scene="[DRAFT OR PROD URL]" onLoad={onLoad} /> | ||
<button type="button" onClick={triggerAnimation}/> | ||
<div> | ||
<Spline | ||
scene="https://prod.spline.design/TRfTj83xgjIdHPmT/scene.spline" | ||
onLoad={onLoad} | ||
/> | ||
<button type="button" onClick={triggerAnimation}> | ||
Trigger Spline Animation | ||
</button> | ||
</main> | ||
) | ||
</div> | ||
); | ||
} | ||
``` | ||
You can find a list of all of the Spline Events you can pass to the `emitEvent` funtcion in the [Spline Events](#spline-events) section. | ||
You can find a list of all of the Spline Events you can pass to the `emitEvent` function in the [Spline Events](#spline-events) section. | ||
## API | ||
### Usage with Next.js | ||
### Spline Component Props | ||
Because react-spline only works on client-side, it needs to be registered as a client-side only component or be [lazy loaded](#lazy-loading). | ||
These are all the props you can pass to the `<Spline />` component. | ||
You can use [next/dynamic](https://nextjs.org/docs/advanced-features/dynamic-import) to import it as client-side only component: | ||
**NOTE**: if you're using [Next.js](https://nextjs.org/), to be albe to use the `ref` prop, you have to wrap `<Spline />` in a component and load it with [next/dynamic](https://nextjs.org/docs/advanced-features/dynamic-import). | ||
```jsx | ||
import dynamic from 'next/dynamic'; | ||
<details> | ||
<summary>See Next.js usage example</summary> | ||
const Spline = dynamic(() => import('@splinetool/react-spline'), { | ||
ssr: false, | ||
}); | ||
export default function App() { | ||
return ( | ||
<div> | ||
<Spline scene="https://prod.spline.design/TRfTj83xgjIdHPmT/scene.spline" /> | ||
</div> | ||
); | ||
} | ||
``` | ||
However, if you need to use the `ref` prop, you will need to create a wrapped component and import it dynamically: | ||
1. Create a wrapped component. | ||
```jsx | ||
import { Spline } from '@splinetool/react-spline'; | ||
import Spline from '@splinetool/react-spline'; | ||
export function WrappedSpline({ splineRef, ...props }) { | ||
@@ -224,8 +257,5 @@ return <Spline ref={splineRef} {...props} />; | ||
const WrappedSpline = dynamic( | ||
() => import('./WrappedSpline').then((mod) => mod.WrappedSpline), | ||
{ | ||
ssr: false, | ||
} | ||
); | ||
const WrappedSpline = dynamic(() => import('./WrappedSpline'), { | ||
ssr: false, | ||
}); | ||
@@ -238,4 +268,4 @@ const Spline = forwardRef((props, ref) => { | ||
```jsx | ||
function App() { | ||
const splineRef = useRef(); | ||
export default function App() { | ||
const ref = useRef(); | ||
@@ -247,5 +277,8 @@ useEffect(() => { | ||
return ( | ||
<main> | ||
<Spline scene="[DRAFT OR PROD URL]" ref={splineRef} /> | ||
</main> | ||
<div> | ||
<Spline | ||
scene="https://prod.spline.design/TRfTj83xgjIdHPmT/scene.spline" | ||
ref={ref} | ||
/> | ||
</div> | ||
); | ||
@@ -255,4 +288,30 @@ } | ||
</details> | ||
### Lazy loading | ||
To start loading react-spline after the whole website has finished loading, we can use lazy-loading. This technique can be achieved using [`React.lazy()`](https://it.reactjs.org/docs/code-splitting.html#reactlazy) in combination with dynamic imports: | ||
```jsx | ||
import React, { Suspense } from 'react'; | ||
const Spline = React.lazy(() => import('@splinetool/react-spline')); | ||
export default function App() { | ||
return ( | ||
<div> | ||
<Suspense fallback={<div>Loading...</div>}> | ||
<Spline scene="https://prod.spline.design/TRfTj83xgjIdHPmT/scene.spline" /> | ||
</Suspense> | ||
</div> | ||
); | ||
} | ||
``` | ||
More info in the [relative React documentation](https://it.reactjs.org/docs/code-splitting.html). | ||
## API | ||
### Spline Component Props | ||
These are all the props you can pass to the `<Spline />` component. | ||
| Name | Type | Description | | ||
@@ -259,0 +318,0 @@ | --------------- | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | |
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
24683
375
0
255