lunchboxjs 0.2.1017-beta → 0.2.1019

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.
@@ -1140,25 +1140,30 @@
1140
1140
  return item?.minidomType === 'RendererNode';
1141
1141
  }
1142
1142
 
1143
- const globalsInjectionKey = Symbol();
1144
- const updateGlobalsInjectionKey = Symbol();
1145
- const setCustomRenderKey = Symbol();
1146
- const clearCustomRenderKey = Symbol();
1147
- const beforeRenderKey = Symbol();
1148
- const onBeforeRenderKey = Symbol();
1149
- const offBeforeRenderKey = Symbol();
1150
- const afterRenderKey = Symbol();
1151
- const onAfterRenderKey = Symbol();
1152
- const offAfterRenderKey = Symbol();
1153
- const frameIdKey = Symbol();
1154
- const watchStopHandleKey = Symbol();
1155
- const appRootNodeKey = Symbol();
1156
- const appKey = Symbol();
1157
- const appRenderersKey = Symbol();
1158
- const appSceneKey = Symbol();
1159
- const appCameraKey = Symbol();
1160
- const lunchboxInteractables = Symbol();
1161
- const startCallbackKey = Symbol();
1143
+ // These keys originally used Symbols per Vue instructions,
1144
+ // but differing dev/build values made dev difficult.
1145
+ // These strings have some risk of namespace collision,
1146
+ // but that's a low enough risk that they're worth hardcoding
1147
+ // as strings, in my opinion.
1148
+ const globalsInjectionKey = 'lunchbox-globals'; // Symbol()
1149
+ const updateGlobalsInjectionKey = 'lunchbox-updateGlobals'; // Symbol()
1150
+ const setCustomRenderKey = 'lunchbox-setCustomRender'; // Symbol()
1151
+ const clearCustomRenderKey = 'lunchbox-clearCustomRender'; //Symbol()
1152
+ const beforeRenderKey = 'lunchbox-beforeRender'; // Symbol()
1153
+ const onBeforeRenderKey = 'lunchbox-onBeforeRender'; //Symbol()
1154
+ const offBeforeRenderKey = 'lunchbox-offBeforeRender'; // Symbol()
1155
+ const afterRenderKey = 'lunchbox-afterRender'; // Symbol()
1156
+ const onAfterRenderKey = 'lunchbox-onAfterRender'; // Symbol()
1157
+ const offAfterRenderKey = 'lunchbox-offAfterRender'; // Symbol()
1158
+ const frameIdKey = 'lunchbox-frameId'; // Symbol()
1159
+ const watchStopHandleKey = 'lunchbox-watchStopHandle'; // Symbol()
1160
+ const appRootNodeKey = 'lunchbox-appRootNode'; // Symbol()
1161
+ const appKey = 'lunchbox-appKey'; // Symbol()
1162
+ const appRenderersKey = 'lunchbox-renderer'; //Symbol()
1163
+ const appSceneKey = 'lunchbox-scene'; // Symbol()
1164
+ const appCameraKey = 'lunchbox-camera'; //Symbol()
1165
+ const lunchboxInteractables = 'lunchbox-interactables'; // Symbol()
1166
+ const startCallbackKey = 'lunchbox-startCallback'; // Symbol()
1162
1167
 
1163
1168
  const requestUpdate = opts => {
1164
1169
  if (typeof opts.app.config.globalProperties.lunchbox.frameId === 'number') {
@@ -1606,6 +1611,57 @@
1606
1611
  };
1607
1612
  };
1608
1613
 
1614
+ const BridgeComponent = vue.defineComponent({
1615
+ name: 'BridgeComponent',
1616
+ props: {
1617
+ app: {
1618
+ type: Object
1619
+ },
1620
+ root: {
1621
+ type: Object
1622
+ },
1623
+ appSetup: {
1624
+ type: Function,
1625
+ default: app => app
1626
+ }
1627
+ },
1628
+ setup(props, ctx) {
1629
+ // we need an app or root to mount
1630
+ if (!props.app && !props.root) {
1631
+ throw new Error('app or root required as <bridge> prop');
1632
+ }
1633
+ // prep container
1634
+ const container = vue.ref();
1635
+ // create app
1636
+ let app = props.appSetup(props.app ?? createApp(props.root, ctx.attrs));
1637
+ // get all provided values - this isn't in the types or docs, so it may be unstable
1638
+ const provides = vue.getCurrentInstance()?.provides ?? {};
1639
+ // provide values
1640
+ Object.keys(provides).forEach(key => {
1641
+ app?.provide(key, vue.inject(key));
1642
+ });
1643
+ // mount
1644
+ vue.onMounted(() => {
1645
+ app?.mount(container.value);
1646
+ });
1647
+ // unmount
1648
+ vue.onUnmounted(() => {
1649
+ app?.unmount();
1650
+ app = null;
1651
+ });
1652
+ return () => vue.createVNode("div", {
1653
+ "ref": container
1654
+ }, null);
1655
+ }
1656
+ });
1657
+
1658
+ const bridge = {
1659
+ install(app) {
1660
+ // register wrapper component
1661
+ app.component('lunchbox', BridgeComponent);
1662
+ }
1663
+ };
1664
+
1609
1665
  /** The current camera as a computed value. */
1610
1666
  const useCamera = () => vue.inject(appCameraKey);
1611
1667
  /** Run a function using the current camera when it's present. */
@@ -1735,12 +1791,12 @@
1735
1791
  });
1736
1792
  // CREATE APP
1737
1793
  // ====================
1738
- const createApp = root => {
1794
+ const createApp = (root, rootProps = {}) => {
1739
1795
  const {
1740
1796
  nodeOps,
1741
1797
  interactables
1742
1798
  } = createNodeOps();
1743
- const app = vue.createRenderer(nodeOps).createApp(root);
1799
+ const app = vue.createRenderer(nodeOps).createApp(root, rootProps);
1744
1800
  // provide Lunchbox interaction handlers flag (modified when user references events via
1745
1801
  // @click, etc)
1746
1802
  app.provide(lunchboxInteractables, interactables);
@@ -1882,6 +1938,7 @@
1882
1938
  app.provide(appRenderersKey, vue.computed(() => app.config.globalProperties.lunchbox.renderer));
1883
1939
  app.provide(appSceneKey, vue.computed(() => app.config.globalProperties.lunchbox.scene));
1884
1940
  app.provide(appCameraKey, vue.computed(() => app.config.globalProperties.lunchbox.camera));
1941
+ app._props;
1885
1942
  // done
1886
1943
  return app;
1887
1944
  };
@@ -1910,6 +1967,7 @@
1910
1967
  exports.globalsInjectionKey = globalsInjectionKey;
1911
1968
  exports.instantiateThreeObject = instantiateThreeObject;
1912
1969
  exports.isMinidomNode = isMinidomNode;
1970
+ exports.lunchbox = bridge;
1913
1971
  exports.lunchboxInteractables = lunchboxInteractables;
1914
1972
  exports.nestedPropertiesToCheck = nestedPropertiesToCheck;
1915
1973
  exports.offAfterRender = offAfterRender;
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("vue"),require("three")):"function"==typeof define&&define.amd?define(["exports","vue","three"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Lunchbox={},e.vue,e.three)}(this,(function(e,t,r){"use strict";function n(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(r){if("default"!==r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})}})),t.default=e,Object.freeze(t)}var o=n(r);const a=(e,t,r)=>{if(!t)return;const n=(Array.isArray(t)?t:t.match(/([^[.\]])+/g))?.reduce(((e,t)=>e&&e[t]),e);return void 0===n?r:n},i=(()=>{const e=Object.prototype.toString;return function(t){return"number"==typeof t||function(e){return!!e&&"object"==typeof e}(t)&&"[object Number]"==e.call(t)}})(),s=e=>e?.$el&&e?.$el?.hasOwnProperty?.("instance"),c=e=>"domMeta"===e?.metaType||e?.props?.["data-lunchbox"],d=e=>"standardMeta"===e?.metaType,l=e=>e.isLunchboxRootNode;function u(t={}){const r={text:t.text??""};return new e.MiniDom.RendererCommentNode({...r,...t,metaType:"commentMeta"})}function p(t={}){const r={domElement:document.createElement(t.type??"")};return new e.MiniDom.RendererDomNode({...r,...t,metaType:"domMeta"})}function m(t={}){const r={text:t.text??""};return new e.MiniDom.RendererTextNode({...t,...r,metaType:"textMeta"})}function h(t={},r={}){const n={attached:t.attached??[],attachedArray:t.attachedArray??{},instance:t.instance??null},o=new e.MiniDom.RendererStandardNode({...t,...n,metaType:"standardMeta"});return!o.type||l(o)||o.instance||(o.instance=L({...o,props:{...o.props,...r}})),o}function f({node:e,key:t,interactables:r,value:n}){return e.eventListeners[t]||(e.eventListeners[t]=[]),e.eventListenerRemoveFunctions[t]||(e.eventListenerRemoveFunctions[t]=[]),e.eventListeners[t].push(n),y.includes(t)&&e.instance&&!r.value.includes(e)&&(r.value.push(e),e.eventListenerRemoveFunctions[t].push((()=>{const t=r.value.indexOf(e);-1!==t&&r.value.splice(t,1)}))),e}const y=["onClick","onPointerUp","onPointerDown","onPointerOver","onPointerOut","onPointerEnter","onPointerLeave","onPointerMove"],b=(e,r,n,o,a)=>{if(!r?.domElement||!n||!e)return;const i=(o=o??window.innerWidth)/(a=a??window.innerHeight);if("perspectivecamera"===e.type?.toLowerCase()){const t=e;t.aspect=i,t.updateProjectionMatrix()}else if("orthographiccamera"===e.type?.toLowerCase()){const t=e,r=a/o;t.top=10*r,t.bottom=10*-r,t.right=10,t.left=-10,t.updateProjectionMatrix()}r.setSize(o,a),n&&e&&r.render(t.toRaw(n),t.toRaw(e))},v=(e,t,r,n,o)=>{const a=e.value?.domElement;if(!a)throw new Error("missing container");const i=()=>{if("container"===o){const e=(e=>{const t=getComputedStyle(e);return{width:e.clientWidth-parseFloat(t.paddingLeft)-parseFloat(t.paddingRight),height:e.clientHeight-parseFloat(t.paddingTop)-parseFloat(t.paddingBottom)}})(a);b(t,r,n,e.width,e.height)}else b(t,r,n)};i();let s=new ResizeObserver((()=>{i()}));return a&&s.observe(a),{dispose(){a&&s.unobserve(a)}}},g=t.defineComponent({name:"LunchboxScene",setup:(e,{slots:r})=>()=>t.createVNode(t.resolveComponent("scene"),null,{default:()=>[r.default?.()]})}),x=t.defineComponent({name:"LunchboxEventHandlers",setup(){const e=Ne(),r=Ce(),n=t.ref({x:1/0,y:1/0}),a=t.ref(!1);let i=[];const s=new o.Raycaster(new o.Vector3,new o.Vector3(0,0,-1)),c=({element:e,eventKeys:t,intersection:r})=>{e&&t.forEach((t=>{e.eventListeners[t]&&e.eventListeners[t].forEach((e=>{e({intersection:r})}))}))};Re((e=>{if(!e?.domElement)return;const{domElement:t}=e;t.addEventListener("pointermove",(e=>{const o=(t.width??1)/r.dpr,a=(t.height??1)/r.dpr;n.value.x=e.offsetX/o*2-1,n.value.y=-e.offsetY/a*2+1})),t.addEventListener("pointerdown",(()=>a.value=!0)),t.addEventListener("pointerup",(()=>a.value=!1))}));const d=ge(),l=()=>{const t=d.value;if(!t)return;s.setFromCamera(n.value,t);const r=s.intersectObjects(e?.value.map((e=>e.instance))??[]);let o=[],a=[],l=[];o=i.map((e=>e.intersection)),r?.forEach((t=>{if(-1===i.findIndex((e=>e.intersection.object===t.object))){const r=e?.value.find((e=>e.instance?.uuid===t.object.uuid));r&&a.push({element:r,intersection:t})}else{const r=e?.value.find((e=>e.instance?.uuid===t.object.uuid));r&&l.push({element:r,intersection:t})}const r=o.findIndex((e=>e.object.uuid===t.object.uuid));-1!==r&&o.splice(r,1)}));const u=o.map((t=>({element:e?.value.find((e=>e.instance?.uuid===t.object.uuid)),intersection:t})));a.forEach((({element:e,intersection:t})=>{c({element:e,eventKeys:["onPointerEnter"],intersection:t})})),l.forEach((({element:e,intersection:t})=>{c({element:e,eventKeys:["onPointerOver","onPointerMove"],intersection:t})})),u.forEach((({element:e,intersection:t})=>{c({element:e,eventKeys:["onPointerLeave","onPointerOut"],intersection:t})})),i=[].concat(a,l)};oe(l);t.onBeforeUnmount((()=>ae(l)));const u=["onClick","onPointerDown","onPointerUp"];return t.watch(a,(e=>{l();const t=[];i.forEach((r=>{u.forEach((n=>{const o=r.element.uuid+n;!e||"onClick"!==n&&"onPointerDown"!==n?e||"onPointerUp"!==n||t.includes(o)||(r.element.eventListeners[n]?.forEach((e=>e({intersection:r.intersection}))),t.push(o)):t.includes(o)||(r.element.eventListeners[n]?.forEach((e=>e({intersection:r.intersection}))),t.push(o))}))}))})),()=>t.createVNode(t.resolveComponent("object3D"),null,null)}}),R=e=>({position:e,top:0,right:0,bottom:0,left:0,width:"100%",height:"100%",display:"block"}),w=t.defineComponent({name:"Lunchbox",props:{background:String,cameraArgs:Array,cameraLook:Array,cameraLookAt:Array,cameraPosition:Array,dpr:Number,ortho:Boolean,orthographic:Boolean,r3f:Boolean,rendererArguments:Object,rendererProperties:Object,sizePolicy:String,shadow:[Boolean,Object],transparent:Boolean,zoom:Number,updateSource:Object},setup(e,r){const n=t.ref();let a=e.dpr??-1;const i=t.ref(),s=t.ref(),c=t.ref(),d=t.ref(),l=Ce(),u=Ae(),p=Ee(),m=t.reactive({}),h=Le();e.r3f&&o?.ColorManagement&&(o.ColorManagement.legacyMode=!1);const f=Ne();t.onMounted((async()=>{if(!n.value&&!r.slots?.renderer?.()?.length)throw new Error("missing canvas");for(r.slots?.camera?.()?.length||(e.cameraPosition&&(m.position=e.cameraPosition),(e.cameraLook||e.cameraLookAt)&&(m.lookAt=e.cameraLook||e.cameraLookAt),void 0!==e.zoom&&(m.zoom=e.zoom)),d.value?.$el?.instance&&e.background&&(d.value.$el.instance.background=new o.Color(e.background)),-1===a&&(a=window.devicePixelRatio),u?.({dpr:a});!s.value?.$el?.instance&&!s.value?.component?.ctx.$el?.instance;)await new Promise((e=>requestAnimationFrame(e)));for(;!d.value?.$el?.instance&&!d.value?.component?.ctx.$el?.instance;)await new Promise((e=>requestAnimationFrame(e)));const t=s.value?.$el?.instance??s.value?.component?.ctx.$el?.instance;t.setPixelRatio(l.dpr);const f=d.value?.$el?.instance??d.value?.component?.ctx.$el?.instance,y=c.value?.$el?.instance??c.value?.component?.ctx.$el?.instance;if(!r.slots?.renderer?.()?.length){v(i,y,t,f,e.sizePolicy),e.r3f&&(t.outputEncoding=o.sRGBEncoding,t.toneMapping=o.ACESFilmicToneMapping);const r={shadow:e.shadow};r?.shadow&&(t.shadowMap.enabled=!0,"object"==typeof r.shadow&&(t.shadowMap.type=r.shadow.type))}if(!p)throw new Error("error creating app");p.config.globalProperties.lunchbox.camera=y,p.config.globalProperties.lunchbox.renderer=t,p.config.globalProperties.lunchbox.scene=f;for(let e of h??[])e({app:p,camera:y,renderer:t,scene:f});re({app:p,camera:y,renderer:t,scene:f,updateSource:e.updateSource})})),t.onBeforeUnmount((()=>{se(),de()}));const y="container"===e.sizePolicy?"static":"absolute",b="container"===e.sizePolicy?"static":"fixed",w=t.computed((()=>{const e=r.slots?.camera?.().find((e=>e.type?.name));return e||e}));return t.watch(w,(async(e,t)=>{e&&e?.props?.key!==t?.props?.key&&(c.value=e)}),{immediate:!0}),()=>t.createVNode(t.Fragment,null,[r.slots?.renderer?.()?.length?s.value=r.slots?.renderer?.()[0]:t.createVNode(t.Fragment,null,[t.createVNode("div",{class:"lunchbox-container",style:R(y),ref:i,"data-lunchbox":"true"},[t.createVNode("canvas",{ref:n,class:"lunchbox-canvas",style:R(b),"data-lunchbox":"true"},null)]),n.value?.domElement&&t.createVNode(t.resolveComponent("webGLRenderer"),t.mergeProps(e.rendererProperties??{},{ref:s,args:[{alpha:e.transparent,antialias:!0,canvas:n.value?.domElement,powerPreference:e.r3f?"high-performance":"default",...e.rendererArguments??{}}]}),null)]),r.slots?.scene?.()?.length?d.value=r.slots?.scene?.()[0]:t.createVNode(g,{ref:d},{default:()=>[r.slots?.default?.()]}),r.slots?.camera?.()?.length?c.value:e.ortho||e.orthographic?t.createVNode(t.resolveComponent("orthographicCamera"),t.mergeProps({ref:c,args:e.cameraArgs??[]},m),null):t.createVNode(t.resolveComponent("perspectiveCamera"),t.mergeProps({ref:c,args:e.cameraArgs??[e.r3f?75:45,.5625,1,1e3]},m),null),f?.value.length&&t.createVNode(x,null,null)])}}),P={},C={...["mesh","instancedMesh","scene","sprite","object3D","instancedBufferGeometry","bufferGeometry","boxBufferGeometry","circleBufferGeometry","coneBufferGeometry","cylinderBufferGeometry","dodecahedronBufferGeometry","extrudeBufferGeometry","icosahedronBufferGeometry","latheBufferGeometry","octahedronBufferGeometry","parametricBufferGeometry","planeBufferGeometry","polyhedronBufferGeometry","ringBufferGeometry","shapeBufferGeometry","sphereBufferGeometry","tetrahedronBufferGeometry","textBufferGeometry","torusBufferGeometry","torusKnotBufferGeometry","tubeBufferGeometry","wireframeGeometry","parametricGeometry","tetrahedronGeometry","octahedronGeometry","icosahedronGeometry","dodecahedronGeometry","polyhedronGeometry","tubeGeometry","torusKnotGeometry","torusGeometry","sphereGeometry","ringGeometry","planeGeometry","latheGeometry","shapeGeometry","extrudeGeometry","edgesGeometry","coneGeometry","cylinderGeometry","circleGeometry","boxGeometry","material","shadowMaterial","spriteMaterial","rawShaderMaterial","shaderMaterial","pointsMaterial","meshPhysicalMaterial","meshStandardMaterial","meshPhongMaterial","meshToonMaterial","meshNormalMaterial","meshLambertMaterial","meshDepthMaterial","meshDistanceMaterial","meshBasicMaterial","meshMatcapMaterial","lineDashedMaterial","lineBasicMaterial","light","spotLightShadow","spotLight","pointLight","rectAreaLight","hemisphereLight","directionalLightShadow","directionalLight","ambientLight","lightShadow","ambientLightProbe","hemisphereLightProbe","lightProbe","texture","videoTexture","dataTexture","dataTexture3D","compressedTexture","cubeTexture","canvasTexture","depthTexture","textureLoader","group","catmullRomCurve3","points","raycaster","cameraHelper","camera","perspectiveCamera","orthographicCamera","cubeCamera","arrayCamera","webGLRenderer"].map((e=>t.defineComponent({inheritAttrs:!1,name:e,setup:(r,n)=>()=>t.h(e,n.attrs,n.slots?.default?.()||[])}))).reduce(((e,t)=>(e[t.name]=t,e)),{}),Lunchbox:w},A=e=>t.defineComponent({inheritAttrs:!1,name:e,render(){return t.h(e,this.$attrs,this.$slots?.default?.()||[])}}),E=({app:e,...t})=>{Object.keys(t).forEach((r=>{e.component(r,A(r)),P[r]=t[r]}))};function L(e){if(!e.type)return null;const t=e.type[0].toUpperCase()+e.type.slice(1),r=t.replace(/Lunchbox$/,""),n=P[e.type]||o[t]||P[r]||o[r];if(!n)throw`${t} is not part of the THREE namespace! Did you forget to extend? import {extend} from 'lunchbox'; extend({app, YourComponent, ...})`;const a=(e.props.args??[]).map((t=>function({node:e,prop:t}){const r="string"==typeof t&&t.startsWith("$attachedArray"),n=function({node:e,prop:t}){return"string"==typeof t&&t.startsWith("$attachedArray")?e.attachedArray[t.replace("$attachedArray.","")]:"string"==typeof t&&t.startsWith("$attached")?e.attached[t.replace("$attached.","")]:t}({node:e,prop:t});return Array.isArray(n)&&r?n:[n]}({node:e,prop:t})));let i=[];a.forEach((e=>{i=i.concat(e)}));return new n(...i)}var N,S=new Uint8Array(16);function M(){if(!N&&!(N="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto)))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return N(S)}var j=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;function B(e){return"string"==typeof e&&j.test(e)}for(var G=[],T=0;T<256;++T)G.push((T+256).toString(16).substr(1));function k(e,t,r){var n=(e=e||{}).random||(e.rng||M)();if(n[6]=15&n[6]|64,n[8]=63&n[8]|128,t){r=r||0;for(var o=0;o<16;++o)t[r+o]=n[o];return t}return function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,r=(G[e[t+0]]+G[e[t+1]]+G[e[t+2]]+G[e[t+3]]+"-"+G[e[t+4]]+G[e[t+5]]+"-"+G[e[t+6]]+G[e[t+7]]+"-"+G[e[t+8]]+G[e[t+9]]+"-"+G[e[t+10]]+G[e[t+11]]+G[e[t+12]]+G[e[t+13]]+G[e[t+14]]+G[e[t+15]]).toLowerCase();if(!B(r))throw TypeError("Stringified UUID is invalid");return r}(n)}e.MiniDom=void 0,function(e){e.BaseNode=class{constructor(e={},t){this.parentNode=e?.parentNode??t??null,this.minidomType="MinidomBaseNode",this.uuid=e?.uuid??k()}uuid;parentNode;get nextSibling(){if(!this.parentNode)return null;const e=this.parentNode.children.findIndex((e=>e.uuid===this.uuid));return-1!==e&&e<this.parentNode.children.length-1?this.parentNode.children[e+1]:null}insertBefore(e,t){e.removeAsChildFromAnyParents(),e.parentNode=this;const r=this.children.findIndex((e=>e.uuid===t?.uuid));-1!==r?this.children.splice(r,0,e):this.children.push(e)}removeChild(e){const t=this.children.findIndex((t=>t?.uuid===e?.uuid));-1!==t&&this.children.splice(t,1)}children=[];addChild(e){return e&&(e.removeAsChildFromAnyParents(),e.parentNode=this,this.insertBefore(e,null)),this}getPath(){const e=[];let t=this;for(;t;)e.unshift(t),t=t.parentNode;return e}drop(){this.removeAsChildFromAnyParents(),this.parentNode=null}walk(e){const t=[this,...this.children],r=[];let n=!0;for(;t.length&&n;){const o=t.shift();if(o){if(r.includes(o))continue;r.push(o),t.push(...o.children.filter((e=>!r.includes(e)))),n=e(o)}else n=!1}}minidomType;removeAsChildFromAnyParents(){this.parentNode?.removeChild(this)}};class t extends e.BaseNode{constructor(e={},t){super(e,t),this.minidomType="RendererNode",this.eventListeners={},this.eventListenerRemoveFunctions={},this.name=e.name??"",this.metaType=e.metaType??"standardMeta",this.props=e.props??[],this.type=e.type??""}eventListeners;eventListenerRemoveFunctions;name;metaType;props;type;drop(){super.drop(),Object.keys(this.eventListenerRemoveFunctions).forEach((e=>{this.eventListenerRemoveFunctions[e].forEach((e=>e()))}))}}e.RendererBaseNode=t;class r extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.domElement=e.domElement??document.createElement("div")}domElement;isLunchboxRootNode=!0}e.RendererRootNode=r;class n extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.text=e.text??""}text}e.RendererCommentNode=n;class o extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.domElement=e.domElement??document.createElement("div")}domElement}e.RendererDomNode=o;class a extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.text=e.text??""}text}e.RendererTextNode=a;class i extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.attached=e.attached??[],this.attachedArray=e.attachedArray??{},this.instance=e.instance??null}attached;attachedArray;instance}e.RendererStandardNode=i}(e.MiniDom||(e.MiniDom={}));const O=Symbol(),$=Symbol(),D=Symbol(),F=Symbol(),K=Symbol(),I=Symbol(),V=Symbol(),U=Symbol(),z=Symbol(),H=Symbol(),W=Symbol(),q=Symbol(),X=Symbol(),Y=Symbol(),_=Symbol(),J=Symbol(),Q=Symbol(),Z=Symbol(),ee=Symbol(),te=e=>{"number"==typeof e.app.config.globalProperties.lunchbox.frameId&&cancelAnimationFrame(e.app.config.globalProperties.lunchbox.frameId),e.app.config.globalProperties.lunchbox.frameId=requestAnimationFrame((()=>re({app:e.app,renderer:e.renderer,scene:e.scene,camera:e.camera,updateSource:e.updateSource})))},re=e=>{e.updateSource?e.app.config.globalProperties.lunchbox.watchStopHandle||(e.app.config.globalProperties.lunchbox.watchStopHandle=t.watch(e.updateSource,(()=>{te(e)}),{deep:!0})):te(e);const{app:r,renderer:n,scene:o}=e;r.config.globalProperties.lunchbox.beforeRender.forEach((t=>{t?.(e)})),n&&o&&e.app.config.globalProperties.lunchbox.camera&&(r.customRender?r.customRender(e):n.render(t.toRaw(o),e.app.config.globalProperties.lunchbox.camera)),r.config.globalProperties.lunchbox.afterRender.forEach((t=>{t?.(e)}))},ne=()=>({onBeforeRender:t.inject(I),offBeforeRender:t.inject(V)}),oe=(e,t=1/0)=>{ne().onBeforeRender?.(e,t)},ae=e=>{ne().offBeforeRender?.(e)},ie=()=>{const e=t.inject(W);return()=>{void 0!==e&&cancelAnimationFrame(e)}},se=()=>{ie()?.()},ce=()=>{const e=t.inject(q);return()=>e?.()},de=()=>{ce()?.()};function le({node:e,key:t,interactables:r,value:n}){if((e=>["onClick","onContextMenu","onDoubleClick","onPointerUp","onPointerDown","onPointerOver","onPointerOut","onPointerEnter","onPointerLeave","onPointerMove","onWheel"].includes(e))(t))return f({node:e,key:t,interactables:r,value:n});const o=t.replace(/-/g,"."),s=ue[o]||o;if(me.includes(t)||me.includes(s))return e;if(!d(e))return e;if("string"==typeof n&&n.startsWith("$attached")){const t=n.replace("$attached.","");n=a(e.attached,t,null)}const c=e.instance;if(!c)return e;let l;for(let e=0;e<pe.length&&!l;e++){const t=[pe[e],s].filter(Boolean).join(".");l=l=a(c,t)}if(l&&i(n)&&l?.setScalar)l.setScalar(n);else if(l&&l.set){const e=Array.isArray(n)?n:[n];c[s].set(...e)}else if("function"==typeof l)if("onbeforerender"===s.toLowerCase()||"onafterrender"===s.toLowerCase())c[s]=n;else{if(!Array.isArray(n))throw new Error('Arguments on a declarative method must be wrapped in an array.\nWorks:\n<example :methodCall="[256]" />\nDoesn\'t work:\n<example :methodCall="256" />');l.bind(e.instance)(...n)}else void 0!==a(c,s,void 0)?((e,t,r)=>{const n=Array.isArray(t)?t:t.match(/([^[.\]])+/g);n?.reduce(((e,t,o)=>(void 0===e[t]&&(e[t]={}),o===n.length-1&&(e[t]=r),e[t])),e)})(c,s,""===n||n):console.log(`No property ${s} found on ${c}`);const u=c?.texture?.type||c?.type;if("string"==typeof u){const e=u.toLowerCase();switch(!0){case e.includes("material"):c.needsUpdate=!0;break;case e.includes("camera")&&c.updateProjectionMatrix:c.updateProjectionMatrix()}}return e}const ue={x:"position.x",y:"position.y",z:"position.z"},pe=["","parameters"],me=["args","attach","attachArray","is.default","isDefault","key","onAdded","ref","src"],he=["geometry","material"],fe=(e,t,r,n)=>{const o={type:e,props:n};if(c(o)){return p(o)}const a=h(o);return he.forEach((t=>{e.toLowerCase().endsWith(t)&&(a.props.attach=t)})),a},ye=(e,t,r)=>{if(!t)throw new Error("missing parent");if(t.insertBefore(e,r),"commentMeta"!==e.metaType&&"textMeta"!==e.metaType&&(c(e)&&(c(t)||l(t))&&t.domElement.appendChild(e.domElement),d(e))){let r=t.metaType;if("textMeta"===r||"commentMeta"===r){const e=t.getPath();for(let r=e.length-1;r>=0;r--)if("textMeta"!==e[r].metaType&&"commentMeta"!==e[r].metaType){t=e[r];break}}if(d(e)&&e.instance?.isObject3D&&d(t)&&t.instance?.isObject3D&&t.instance?.add?.(e.instance),e?.props?.attach&&d(t)&&t?.instance){e.type?.toLowerCase().endsWith("loader")&&e.props.src&&(e.props.attach||e.props.attachArray)?function(e,t){const r=e.instance;if(t.attached=t.attached||{},t.attachedArray=t.attachedArray||{},!e.props.attach)return;if("textureloader"===e.type?.toLowerCase()){const n=r.load(e.props.src);be(e,t,e.props.attach,n)}else r.load(e.props.src,(r=>{be(e,t,e.props.attach,r)}),null,(e=>{throw new Error(e)}))}(e,t):be(e,t,e.props.attach)}e.props?.onAdded&&e.props.onAdded({instance:e.instance})}};function be(e,t,r,n){const o=n??e.instance,a=t.instance;e.props.attach===r&&(t.attached={[r]:o,...t.attached||{}},a[r]=n??e.instance),e.props.attachArray===r&&(t.attachedArray[e.props.attachArray]||(t.attachedArray[e.props.attachArray]=[]),t.attachedArray[e.props.attachArray].push(o),a[r]=[a[r]])}const ve=e=>{if(!e)return;const t=[];e.walk((e=>(t.push(e),!0))),t.forEach((e=>{if(d(e)){e.instance?.removeFromParent?.();const t="scene"!==e.type&&e.instance?.dispose;t&&t.bind(e.instance)(),e.instance=null}e.drop()}))},ge=()=>t.inject(Q),xe=()=>t.inject(_),Re=e=>{const r=xe();if(r.value)return void e(r.value);let n=null;n=t.watch(xe(),(t=>{t&&(e(t),n?.())}),{immediate:!0})},we=()=>t.inject(J),Pe=()=>({setCustomRender:t.inject(D),clearCustomRender:t.inject(F)}),Ce=()=>t.inject(O),Ae=()=>t.inject($),Ee=()=>t.inject(Y),Le=()=>t.inject(ee),Ne=()=>t.inject(Z);e.addEventListener=f,e.afterRenderKey=U,e.appCameraKey=Q,e.appKey=Y,e.appRenderersKey=_,e.appRootNodeKey=X,e.appSceneKey=J,e.beforeRenderKey=K,e.cancelUpdate=se,e.cancelUpdateSource=de,e.clearCustomRender=()=>{Pe()?.clearCustomRender?.()},e.clearCustomRenderKey=F,e.createApp=r=>{const{nodeOps:n,interactables:o}=(()=>{const e=t.ref([]);return{nodeOps:{createElement:fe,createText:e=>m({text:e}),createComment:e=>u({text:e}),insert:ye,nextSibling:e=>e.nextSibling||null,parentNode:e=>e.parentNode||null,patchProp(t,r,n,o){c(t)?"style"===r?Object.keys(o).forEach((e=>{t.domElement.style[e]=o[e]})):t.domElement.setAttribute(r,o):l(t)||r.startsWith("$")||le({node:t,key:r,interactables:e,value:o})},remove:ve,setElementText(){},setText(){}},interactables:e}})(),a=t.createRenderer(n).createApp(r);a.provide(Z,o),Object.keys(C).forEach((e=>{a?.component(e,C[e])})),a.provide(D,(e=>{a.setCustomRender(e)})),a.provide(F,(()=>{a.clearCustomRender()}));const i=[];a.provide(K,i),a.provide(I,((e,t=1/0)=>{t===1/0?i.push(e):i.splice(t,0,e)})),a.provide(V,(e=>{if(isFinite(e))i.splice(e,1);else{const t=i.findIndex((t=>t==e));-1!==t&&i.splice(t,1)}}));const s=[];a.provide(U,s),a.provide(z,((e,t=1/0)=>{t===1/0?s.push(e):s.splice(t,0,e)})),a.provide(H,(e=>{if(isFinite(e))s.splice(e,1);else{const t=s.findIndex((t=>t==e));-1!==t&&s.splice(t,1)}})),a.config.globalProperties.lunchbox=t.reactive({afterRender:s,beforeRender:i,camera:null,dpr:1,frameId:-1,renderer:null,scene:null,watchStopHandle:null}),a.provide(O,a.config.globalProperties.lunchbox),a.provide($,(e=>{Object.keys(e).forEach((t=>{const r=t;a.config.globalProperties.lunchbox[r]=e[r]}))})),a.provide(W,a.config.globalProperties.lunchbox.frameId),a.provide(q,a.config.globalProperties.lunchbox.watchStopHandle);const{mount:d}=a;a.mount=(t,...r)=>{const n="string"==typeof t?document.querySelector(t):t,o=new e.MiniDom.RendererRootNode({domElement:n,isLunchboxRootNode:!0,name:"root",metaType:"rootMeta",type:"root",uuid:"LUNCHBOX_ROOT"});a.rootNode=o,a.provide(X,o);return d(o,...r)},a.extend=e=>(E({app:a,...e}),a);return a.provide(ee,[]),a.setCustomRender=e=>{a&&(a.customRender=e)},a.clearCustomRender=()=>{a&&(a.customRender=null)},a.provide(Y,a),a.provide(_,t.computed((()=>a.config.globalProperties.lunchbox.renderer))),a.provide(J,t.computed((()=>a.config.globalProperties.lunchbox.scene))),a.provide(Q,t.computed((()=>a.config.globalProperties.lunchbox.camera))),a},e.createCommentNode=u,e.createDomNode=p,e.createNode=h,e.createTextNode=m,e.extend=E,e.find=function(e){return e=t.isRef(e)?e.value:e,d(e)?e?.instance:s(e)?e?.$el?.instance:t.isVNode(e)?e.el?.instance:null},e.frameIdKey=W,e.getInstance=(e,r=!0)=>t.computed((()=>{const n=e.value?.$el?.instance??e.value?.instance??null;return n&&r?t.toRaw(n):n})),e.globalsInjectionKey=O,e.instantiateThreeObject=L,e.isMinidomNode=function(e){return"RendererNode"===e?.minidomType},e.lunchboxInteractables=Z,e.nestedPropertiesToCheck=pe,e.offAfterRender=e=>{ne().offBeforeRender?.(e)},e.offAfterRenderKey=H,e.offBeforeRender=ae,e.offBeforeRenderKey=V,e.onAfterRender=(e,t=1/0)=>{ne().onBeforeRender?.(e,t)},e.onAfterRenderKey=z,e.onBeforeRender=oe,e.onBeforeRenderKey=I,e.onCameraReady=e=>{const r=ge();if(r.value)return void e(r.value);let n=null;n=t.watch(ge(),(t=>{t&&(e(t),n?.())}))},e.onRendererReady=Re,e.onSceneReady=e=>{const r=we();if(r.value)return void e(r.value);let n=null;n=t.watch(we(),(t=>{t&&(e(t),n?.())}),{immediate:!0})},e.onStart=(e,t=1/0)=>{const r=Le();t===1/0?r?.push(e):r?.splice(t,0,e)},e.setCustomRender=e=>{Pe()?.setCustomRender?.(e)},e.setCustomRenderKey=D,e.startCallbackKey=ee,e.update=re,e.updateGlobals=e=>{Ae()?.(e)},e.updateGlobalsInjectionKey=$,e.updateObjectProp=le,e.useAfterRender=()=>({onAfterRender:t.inject(I),offAfterRender:t.inject(V)}),e.useApp=Ee,e.useBeforeRender=ne,e.useCamera=ge,e.useCancelUpdate=ie,e.useCancelUpdateSource=ce,e.useCustomRender=Pe,e.useGlobals=Ce,e.useLunchboxInteractables=Ne,e.useRenderer=xe,e.useScene=we,e.useStartCallbacks=Le,e.useUpdateGlobals=Ae,e.watchStopHandleKey=q}));
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("vue"),require("three")):"function"==typeof define&&define.amd?define(["exports","vue","three"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).Lunchbox={},e.vue,e.three)}(this,(function(e,t,n){"use strict";function r(e){var t=Object.create(null);return e&&Object.keys(e).forEach((function(n){if("default"!==n){var r=Object.getOwnPropertyDescriptor(e,n);Object.defineProperty(t,n,r.get?r:{enumerable:!0,get:function(){return e[n]}})}})),t.default=e,Object.freeze(t)}var o=r(n);const a=(e,t,n)=>{if(!t)return;const r=(Array.isArray(t)?t:t.match(/([^[.\]])+/g))?.reduce(((e,t)=>e&&e[t]),e);return void 0===r?n:r},i=(()=>{const e=Object.prototype.toString;return function(t){return"number"==typeof t||function(e){return!!e&&"object"==typeof e}(t)&&"[object Number]"==e.call(t)}})(),s=e=>e?.$el&&e?.$el?.hasOwnProperty?.("instance"),c=e=>"domMeta"===e?.metaType||e?.props?.["data-lunchbox"],d=e=>"standardMeta"===e?.metaType,l=e=>e.isLunchboxRootNode;function u(t={}){const n={text:t.text??""};return new e.MiniDom.RendererCommentNode({...n,...t,metaType:"commentMeta"})}function p(t={}){const n={domElement:document.createElement(t.type??"")};return new e.MiniDom.RendererDomNode({...n,...t,metaType:"domMeta"})}function m(t={}){const n={text:t.text??""};return new e.MiniDom.RendererTextNode({...t,...n,metaType:"textMeta"})}function h(t={},n={}){const r={attached:t.attached??[],attachedArray:t.attachedArray??{},instance:t.instance??null},o=new e.MiniDom.RendererStandardNode({...t,...r,metaType:"standardMeta"});return!o.type||l(o)||o.instance||(o.instance=N({...o,props:{...o.props,...n}})),o}function f({node:e,key:t,interactables:n,value:r}){return e.eventListeners[t]||(e.eventListeners[t]=[]),e.eventListenerRemoveFunctions[t]||(e.eventListenerRemoveFunctions[t]=[]),e.eventListeners[t].push(r),y.includes(t)&&e.instance&&!n.value.includes(e)&&(n.value.push(e),e.eventListenerRemoveFunctions[t].push((()=>{const t=n.value.indexOf(e);-1!==t&&n.value.splice(t,1)}))),e}const y=["onClick","onPointerUp","onPointerDown","onPointerOver","onPointerOut","onPointerEnter","onPointerLeave","onPointerMove"],b=(e,n,r,o,a)=>{if(!n?.domElement||!r||!e)return;const i=(o=o??window.innerWidth)/(a=a??window.innerHeight);if("perspectivecamera"===e.type?.toLowerCase()){const t=e;t.aspect=i,t.updateProjectionMatrix()}else if("orthographiccamera"===e.type?.toLowerCase()){const t=e,n=a/o;t.top=10*n,t.bottom=10*-n,t.right=10,t.left=-10,t.updateProjectionMatrix()}n.setSize(o,a),r&&e&&n.render(t.toRaw(r),t.toRaw(e))},v=(e,t,n,r,o)=>{const a=e.value?.domElement;if(!a)throw new Error("missing container");const i=()=>{if("container"===o){const e=(e=>{const t=getComputedStyle(e);return{width:e.clientWidth-parseFloat(t.paddingLeft)-parseFloat(t.paddingRight),height:e.clientHeight-parseFloat(t.paddingTop)-parseFloat(t.paddingBottom)}})(a);b(t,n,r,e.width,e.height)}else b(t,n,r)};i();let s=new ResizeObserver((()=>{i()}));return a&&s.observe(a),{dispose(){a&&s.unobserve(a)}}},g=t.defineComponent({name:"LunchboxScene",setup:(e,{slots:n})=>()=>t.createVNode(t.resolveComponent("scene"),null,{default:()=>[n.default?.()]})}),x=t.defineComponent({name:"LunchboxEventHandlers",setup(){const e=Be(),n=Ee(),r=t.ref({x:1/0,y:1/0}),a=t.ref(!1);let i=[];const s=new o.Raycaster(new o.Vector3,new o.Vector3(0,0,-1)),c=({element:e,eventKeys:t,intersection:n})=>{e&&t.forEach((t=>{e.eventListeners[t]&&e.eventListeners[t].forEach((e=>{e({intersection:n})}))}))};Ce((e=>{if(!e?.domElement)return;const{domElement:t}=e;t.addEventListener("pointermove",(e=>{const o=(t.width??1)/n.dpr,a=(t.height??1)/n.dpr;r.value.x=e.offsetX/o*2-1,r.value.y=-e.offsetY/a*2+1})),t.addEventListener("pointerdown",(()=>a.value=!0)),t.addEventListener("pointerup",(()=>a.value=!1))}));const d=Re(),l=()=>{const t=d.value;if(!t)return;s.setFromCamera(r.value,t);const n=s.intersectObjects(e?.value.map((e=>e.instance))??[]);let o=[],a=[],l=[];o=i.map((e=>e.intersection)),n?.forEach((t=>{if(-1===i.findIndex((e=>e.intersection.object===t.object))){const n=e?.value.find((e=>e.instance?.uuid===t.object.uuid));n&&a.push({element:n,intersection:t})}else{const n=e?.value.find((e=>e.instance?.uuid===t.object.uuid));n&&l.push({element:n,intersection:t})}const n=o.findIndex((e=>e.object.uuid===t.object.uuid));-1!==n&&o.splice(n,1)}));const u=o.map((t=>({element:e?.value.find((e=>e.instance?.uuid===t.object.uuid)),intersection:t})));a.forEach((({element:e,intersection:t})=>{c({element:e,eventKeys:["onPointerEnter"],intersection:t})})),l.forEach((({element:e,intersection:t})=>{c({element:e,eventKeys:["onPointerOver","onPointerMove"],intersection:t})})),u.forEach((({element:e,intersection:t})=>{c({element:e,eventKeys:["onPointerLeave","onPointerOut"],intersection:t})})),i=[].concat(a,l)};oe(l);t.onBeforeUnmount((()=>ae(l)));const u=["onClick","onPointerDown","onPointerUp"];return t.watch(a,(e=>{l();const t=[];i.forEach((n=>{u.forEach((r=>{const o=n.element.uuid+r;!e||"onClick"!==r&&"onPointerDown"!==r?e||"onPointerUp"!==r||t.includes(o)||(n.element.eventListeners[r]?.forEach((e=>e({intersection:n.intersection}))),t.push(o)):t.includes(o)||(n.element.eventListeners[r]?.forEach((e=>e({intersection:n.intersection}))),t.push(o))}))}))})),()=>t.createVNode(t.resolveComponent("object3D"),null,null)}}),R=e=>({position:e,top:0,right:0,bottom:0,left:0,width:"100%",height:"100%",display:"block"}),w=t.defineComponent({name:"Lunchbox",props:{background:String,cameraArgs:Array,cameraLook:Array,cameraLookAt:Array,cameraPosition:Array,dpr:Number,ortho:Boolean,orthographic:Boolean,r3f:Boolean,rendererArguments:Object,rendererProperties:Object,sizePolicy:String,shadow:[Boolean,Object],transparent:Boolean,zoom:Number,updateSource:Object},setup(e,n){const r=t.ref();let a=e.dpr??-1;const i=t.ref(),s=t.ref(),c=t.ref(),d=t.ref(),l=Ee(),u=Ne(),p=Le(),m=t.reactive({}),h=je();e.r3f&&o?.ColorManagement&&(o.ColorManagement.legacyMode=!1);const f=Be();t.onMounted((async()=>{if(!r.value&&!n.slots?.renderer?.()?.length)throw new Error("missing canvas");for(n.slots?.camera?.()?.length||(e.cameraPosition&&(m.position=e.cameraPosition),(e.cameraLook||e.cameraLookAt)&&(m.lookAt=e.cameraLook||e.cameraLookAt),void 0!==e.zoom&&(m.zoom=e.zoom)),d.value?.$el?.instance&&e.background&&(d.value.$el.instance.background=new o.Color(e.background)),-1===a&&(a=window.devicePixelRatio),u?.({dpr:a});!s.value?.$el?.instance&&!s.value?.component?.ctx.$el?.instance;)await new Promise((e=>requestAnimationFrame(e)));for(;!d.value?.$el?.instance&&!d.value?.component?.ctx.$el?.instance;)await new Promise((e=>requestAnimationFrame(e)));const t=s.value?.$el?.instance??s.value?.component?.ctx.$el?.instance;t.setPixelRatio(l.dpr);const f=d.value?.$el?.instance??d.value?.component?.ctx.$el?.instance,y=c.value?.$el?.instance??c.value?.component?.ctx.$el?.instance;if(!n.slots?.renderer?.()?.length){v(i,y,t,f,e.sizePolicy),e.r3f&&(t.outputEncoding=o.sRGBEncoding,t.toneMapping=o.ACESFilmicToneMapping);const n={shadow:e.shadow};n?.shadow&&(t.shadowMap.enabled=!0,"object"==typeof n.shadow&&(t.shadowMap.type=n.shadow.type))}if(!p)throw new Error("error creating app");p.config.globalProperties.lunchbox.camera=y,p.config.globalProperties.lunchbox.renderer=t,p.config.globalProperties.lunchbox.scene=f;for(let e of h??[])e({app:p,camera:y,renderer:t,scene:f});ne({app:p,camera:y,renderer:t,scene:f,updateSource:e.updateSource})})),t.onBeforeUnmount((()=>{se(),de()}));const y="container"===e.sizePolicy?"static":"absolute",b="container"===e.sizePolicy?"static":"fixed",w=t.computed((()=>{const e=n.slots?.camera?.().find((e=>e.type?.name));return e||e}));return t.watch(w,(async(e,t)=>{e&&e?.props?.key!==t?.props?.key&&(c.value=e)}),{immediate:!0}),()=>t.createVNode(t.Fragment,null,[n.slots?.renderer?.()?.length?s.value=n.slots?.renderer?.()[0]:t.createVNode(t.Fragment,null,[t.createVNode("div",{class:"lunchbox-container",style:R(y),ref:i,"data-lunchbox":"true"},[t.createVNode("canvas",{ref:r,class:"lunchbox-canvas",style:R(b),"data-lunchbox":"true"},null)]),r.value?.domElement&&t.createVNode(t.resolveComponent("webGLRenderer"),t.mergeProps(e.rendererProperties??{},{ref:s,args:[{alpha:e.transparent,antialias:!0,canvas:r.value?.domElement,powerPreference:e.r3f?"high-performance":"default",...e.rendererArguments??{}}]}),null)]),n.slots?.scene?.()?.length?d.value=n.slots?.scene?.()[0]:t.createVNode(g,{ref:d},{default:()=>[n.slots?.default?.()]}),n.slots?.camera?.()?.length?c.value:e.ortho||e.orthographic?t.createVNode(t.resolveComponent("orthographicCamera"),t.mergeProps({ref:c,args:e.cameraArgs??[]},m),null):t.createVNode(t.resolveComponent("perspectiveCamera"),t.mergeProps({ref:c,args:e.cameraArgs??[e.r3f?75:45,.5625,1,1e3]},m),null),f?.value.length&&t.createVNode(x,null,null)])}}),C={},P={...["mesh","instancedMesh","scene","sprite","object3D","instancedBufferGeometry","bufferGeometry","boxBufferGeometry","circleBufferGeometry","coneBufferGeometry","cylinderBufferGeometry","dodecahedronBufferGeometry","extrudeBufferGeometry","icosahedronBufferGeometry","latheBufferGeometry","octahedronBufferGeometry","parametricBufferGeometry","planeBufferGeometry","polyhedronBufferGeometry","ringBufferGeometry","shapeBufferGeometry","sphereBufferGeometry","tetrahedronBufferGeometry","textBufferGeometry","torusBufferGeometry","torusKnotBufferGeometry","tubeBufferGeometry","wireframeGeometry","parametricGeometry","tetrahedronGeometry","octahedronGeometry","icosahedronGeometry","dodecahedronGeometry","polyhedronGeometry","tubeGeometry","torusKnotGeometry","torusGeometry","sphereGeometry","ringGeometry","planeGeometry","latheGeometry","shapeGeometry","extrudeGeometry","edgesGeometry","coneGeometry","cylinderGeometry","circleGeometry","boxGeometry","material","shadowMaterial","spriteMaterial","rawShaderMaterial","shaderMaterial","pointsMaterial","meshPhysicalMaterial","meshStandardMaterial","meshPhongMaterial","meshToonMaterial","meshNormalMaterial","meshLambertMaterial","meshDepthMaterial","meshDistanceMaterial","meshBasicMaterial","meshMatcapMaterial","lineDashedMaterial","lineBasicMaterial","light","spotLightShadow","spotLight","pointLight","rectAreaLight","hemisphereLight","directionalLightShadow","directionalLight","ambientLight","lightShadow","ambientLightProbe","hemisphereLightProbe","lightProbe","texture","videoTexture","dataTexture","dataTexture3D","compressedTexture","cubeTexture","canvasTexture","depthTexture","textureLoader","group","catmullRomCurve3","points","raycaster","cameraHelper","camera","perspectiveCamera","orthographicCamera","cubeCamera","arrayCamera","webGLRenderer"].map((e=>t.defineComponent({inheritAttrs:!1,name:e,setup:(n,r)=>()=>t.h(e,r.attrs,r.slots?.default?.()||[])}))).reduce(((e,t)=>(e[t.name]=t,e)),{}),Lunchbox:w},A=e=>t.defineComponent({inheritAttrs:!1,name:e,render(){return t.h(e,this.$attrs,this.$slots?.default?.()||[])}}),E=({app:e,...t})=>{Object.keys(t).forEach((n=>{e.component(n,A(n)),C[n]=t[n]}))};function N(e){if(!e.type)return null;const t=e.type[0].toUpperCase()+e.type.slice(1),n=t.replace(/Lunchbox$/,""),r=C[e.type]||o[t]||C[n]||o[n];if(!r)throw`${t} is not part of the THREE namespace! Did you forget to extend? import {extend} from 'lunchbox'; extend({app, YourComponent, ...})`;const a=(e.props.args??[]).map((t=>function({node:e,prop:t}){const n="string"==typeof t&&t.startsWith("$attachedArray"),r=function({node:e,prop:t}){return"string"==typeof t&&t.startsWith("$attachedArray")?e.attachedArray[t.replace("$attachedArray.","")]:"string"==typeof t&&t.startsWith("$attached")?e.attached[t.replace("$attached.","")]:t}({node:e,prop:t});return Array.isArray(r)&&n?r:[r]}({node:e,prop:t})));let i=[];a.forEach((e=>{i=i.concat(e)}));return new r(...i)}var L,j=new Uint8Array(16);function B(){if(!L&&!(L="undefined"!=typeof crypto&&crypto.getRandomValues&&crypto.getRandomValues.bind(crypto)||"undefined"!=typeof msCrypto&&"function"==typeof msCrypto.getRandomValues&&msCrypto.getRandomValues.bind(msCrypto)))throw new Error("crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported");return L(j)}var M=/^(?:[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}|00000000-0000-0000-0000-000000000000)$/i;function G(e){return"string"==typeof e&&M.test(e)}for(var S=[],T=0;T<256;++T)S.push((T+256).toString(16).substr(1));function k(e,t,n){var r=(e=e||{}).random||(e.rng||B)();if(r[6]=15&r[6]|64,r[8]=63&r[8]|128,t){n=n||0;for(var o=0;o<16;++o)t[n+o]=r[o];return t}return function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:0,n=(S[e[t+0]]+S[e[t+1]]+S[e[t+2]]+S[e[t+3]]+"-"+S[e[t+4]]+S[e[t+5]]+"-"+S[e[t+6]]+S[e[t+7]]+"-"+S[e[t+8]]+S[e[t+9]]+"-"+S[e[t+10]]+S[e[t+11]]+S[e[t+12]]+S[e[t+13]]+S[e[t+14]]+S[e[t+15]]).toLowerCase();if(!G(n))throw TypeError("Stringified UUID is invalid");return n}(r)}e.MiniDom=void 0,function(e){e.BaseNode=class{constructor(e={},t){this.parentNode=e?.parentNode??t??null,this.minidomType="MinidomBaseNode",this.uuid=e?.uuid??k()}uuid;parentNode;get nextSibling(){if(!this.parentNode)return null;const e=this.parentNode.children.findIndex((e=>e.uuid===this.uuid));return-1!==e&&e<this.parentNode.children.length-1?this.parentNode.children[e+1]:null}insertBefore(e,t){e.removeAsChildFromAnyParents(),e.parentNode=this;const n=this.children.findIndex((e=>e.uuid===t?.uuid));-1!==n?this.children.splice(n,0,e):this.children.push(e)}removeChild(e){const t=this.children.findIndex((t=>t?.uuid===e?.uuid));-1!==t&&this.children.splice(t,1)}children=[];addChild(e){return e&&(e.removeAsChildFromAnyParents(),e.parentNode=this,this.insertBefore(e,null)),this}getPath(){const e=[];let t=this;for(;t;)e.unshift(t),t=t.parentNode;return e}drop(){this.removeAsChildFromAnyParents(),this.parentNode=null}walk(e){const t=[this,...this.children],n=[];let r=!0;for(;t.length&&r;){const o=t.shift();if(o){if(n.includes(o))continue;n.push(o),t.push(...o.children.filter((e=>!n.includes(e)))),r=e(o)}else r=!1}}minidomType;removeAsChildFromAnyParents(){this.parentNode?.removeChild(this)}};class t extends e.BaseNode{constructor(e={},t){super(e,t),this.minidomType="RendererNode",this.eventListeners={},this.eventListenerRemoveFunctions={},this.name=e.name??"",this.metaType=e.metaType??"standardMeta",this.props=e.props??[],this.type=e.type??""}eventListeners;eventListenerRemoveFunctions;name;metaType;props;type;drop(){super.drop(),Object.keys(this.eventListenerRemoveFunctions).forEach((e=>{this.eventListenerRemoveFunctions[e].forEach((e=>e()))}))}}e.RendererBaseNode=t;class n extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.domElement=e.domElement??document.createElement("div")}domElement;isLunchboxRootNode=!0}e.RendererRootNode=n;class r extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.text=e.text??""}text}e.RendererCommentNode=r;class o extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.domElement=e.domElement??document.createElement("div")}domElement}e.RendererDomNode=o;class a extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.text=e.text??""}text}e.RendererTextNode=a;class i extends e.RendererBaseNode{constructor(e={},t){super(e,t),this.attached=e.attached??[],this.attachedArray=e.attachedArray??{},this.instance=e.instance??null}attached;attachedArray;instance}e.RendererStandardNode=i}(e.MiniDom||(e.MiniDom={}));const O="lunchbox-globals",$="lunchbox-updateGlobals",D="lunchbox-setCustomRender",F="lunchbox-clearCustomRender",K="lunchbox-beforeRender",I="lunchbox-onBeforeRender",V="lunchbox-offBeforeRender",U="lunchbox-afterRender",z="lunchbox-onAfterRender",H="lunchbox-offAfterRender",W="lunchbox-frameId",q="lunchbox-watchStopHandle",X="lunchbox-appRootNode",Y="lunchbox-appKey",_="lunchbox-renderer",J="lunchbox-scene",Q="lunchbox-camera",Z="lunchbox-interactables",ee="lunchbox-startCallback",te=e=>{"number"==typeof e.app.config.globalProperties.lunchbox.frameId&&cancelAnimationFrame(e.app.config.globalProperties.lunchbox.frameId),e.app.config.globalProperties.lunchbox.frameId=requestAnimationFrame((()=>ne({app:e.app,renderer:e.renderer,scene:e.scene,camera:e.camera,updateSource:e.updateSource})))},ne=e=>{e.updateSource?e.app.config.globalProperties.lunchbox.watchStopHandle||(e.app.config.globalProperties.lunchbox.watchStopHandle=t.watch(e.updateSource,(()=>{te(e)}),{deep:!0})):te(e);const{app:n,renderer:r,scene:o}=e;n.config.globalProperties.lunchbox.beforeRender.forEach((t=>{t?.(e)})),r&&o&&e.app.config.globalProperties.lunchbox.camera&&(n.customRender?n.customRender(e):r.render(t.toRaw(o),e.app.config.globalProperties.lunchbox.camera)),n.config.globalProperties.lunchbox.afterRender.forEach((t=>{t?.(e)}))},re=()=>({onBeforeRender:t.inject(I),offBeforeRender:t.inject(V)}),oe=(e,t=1/0)=>{re().onBeforeRender?.(e,t)},ae=e=>{re().offBeforeRender?.(e)},ie=()=>{const e=t.inject(W);return()=>{void 0!==e&&cancelAnimationFrame(e)}},se=()=>{ie()?.()},ce=()=>{const e=t.inject(q);return()=>e?.()},de=()=>{ce()?.()};function le({node:e,key:t,interactables:n,value:r}){if((e=>["onClick","onContextMenu","onDoubleClick","onPointerUp","onPointerDown","onPointerOver","onPointerOut","onPointerEnter","onPointerLeave","onPointerMove","onWheel"].includes(e))(t))return f({node:e,key:t,interactables:n,value:r});const o=t.replace(/-/g,"."),s=ue[o]||o;if(me.includes(t)||me.includes(s))return e;if(!d(e))return e;if("string"==typeof r&&r.startsWith("$attached")){const t=r.replace("$attached.","");r=a(e.attached,t,null)}const c=e.instance;if(!c)return e;let l;for(let e=0;e<pe.length&&!l;e++){const t=[pe[e],s].filter(Boolean).join(".");l=l=a(c,t)}if(l&&i(r)&&l?.setScalar)l.setScalar(r);else if(l&&l.set){const e=Array.isArray(r)?r:[r];c[s].set(...e)}else if("function"==typeof l)if("onbeforerender"===s.toLowerCase()||"onafterrender"===s.toLowerCase())c[s]=r;else{if(!Array.isArray(r))throw new Error('Arguments on a declarative method must be wrapped in an array.\nWorks:\n<example :methodCall="[256]" />\nDoesn\'t work:\n<example :methodCall="256" />');l.bind(e.instance)(...r)}else void 0!==a(c,s,void 0)?((e,t,n)=>{const r=Array.isArray(t)?t:t.match(/([^[.\]])+/g);r?.reduce(((e,t,o)=>(void 0===e[t]&&(e[t]={}),o===r.length-1&&(e[t]=n),e[t])),e)})(c,s,""===r||r):console.log(`No property ${s} found on ${c}`);const u=c?.texture?.type||c?.type;if("string"==typeof u){const e=u.toLowerCase();switch(!0){case e.includes("material"):c.needsUpdate=!0;break;case e.includes("camera")&&c.updateProjectionMatrix:c.updateProjectionMatrix()}}return e}const ue={x:"position.x",y:"position.y",z:"position.z"},pe=["","parameters"],me=["args","attach","attachArray","is.default","isDefault","key","onAdded","ref","src"],he=["geometry","material"],fe=(e,t,n,r)=>{const o={type:e,props:r};if(c(o)){return p(o)}const a=h(o);return he.forEach((t=>{e.toLowerCase().endsWith(t)&&(a.props.attach=t)})),a},ye=(e,t,n)=>{if(!t)throw new Error("missing parent");if(t.insertBefore(e,n),"commentMeta"!==e.metaType&&"textMeta"!==e.metaType&&(c(e)&&(c(t)||l(t))&&t.domElement.appendChild(e.domElement),d(e))){let n=t.metaType;if("textMeta"===n||"commentMeta"===n){const e=t.getPath();for(let n=e.length-1;n>=0;n--)if("textMeta"!==e[n].metaType&&"commentMeta"!==e[n].metaType){t=e[n];break}}if(d(e)&&e.instance?.isObject3D&&d(t)&&t.instance?.isObject3D&&t.instance?.add?.(e.instance),e?.props?.attach&&d(t)&&t?.instance){e.type?.toLowerCase().endsWith("loader")&&e.props.src&&(e.props.attach||e.props.attachArray)?function(e,t){const n=e.instance;if(t.attached=t.attached||{},t.attachedArray=t.attachedArray||{},!e.props.attach)return;if("textureloader"===e.type?.toLowerCase()){const r=n.load(e.props.src);be(e,t,e.props.attach,r)}else n.load(e.props.src,(n=>{be(e,t,e.props.attach,n)}),null,(e=>{throw new Error(e)}))}(e,t):be(e,t,e.props.attach)}e.props?.onAdded&&e.props.onAdded({instance:e.instance})}};function be(e,t,n,r){const o=r??e.instance,a=t.instance;e.props.attach===n&&(t.attached={[n]:o,...t.attached||{}},a[n]=r??e.instance),e.props.attachArray===n&&(t.attachedArray[e.props.attachArray]||(t.attachedArray[e.props.attachArray]=[]),t.attachedArray[e.props.attachArray].push(o),a[n]=[a[n]])}const ve=e=>{if(!e)return;const t=[];e.walk((e=>(t.push(e),!0))),t.forEach((e=>{if(d(e)){e.instance?.removeFromParent?.();const t="scene"!==e.type&&e.instance?.dispose;t&&t.bind(e.instance)(),e.instance=null}e.drop()}))},ge=t.defineComponent({name:"BridgeComponent",props:{app:{type:Object},root:{type:Object},appSetup:{type:Function,default:e=>e}},setup(e,n){if(!e.app&&!e.root)throw new Error("app or root required as <bridge> prop");const r=t.ref();let o=e.appSetup(e.app??Me(e.root,n.attrs));const a=t.getCurrentInstance()?.provides??{};return Object.keys(a).forEach((e=>{o?.provide(e,t.inject(e))})),t.onMounted((()=>{o?.mount(r.value)})),t.onUnmounted((()=>{o?.unmount(),o=null})),()=>t.createVNode("div",{ref:r},null)}}),xe={install(e){e.component("lunchbox",ge)}},Re=()=>t.inject(Q),we=()=>t.inject(_),Ce=e=>{const n=we();if(n.value)return void e(n.value);let r=null;r=t.watch(we(),(t=>{t&&(e(t),r?.())}),{immediate:!0})},Pe=()=>t.inject(J),Ae=()=>({setCustomRender:t.inject(D),clearCustomRender:t.inject(F)}),Ee=()=>t.inject(O),Ne=()=>t.inject($),Le=()=>t.inject(Y),je=()=>t.inject(ee),Be=()=>t.inject(Z),Me=(n,r={})=>{const{nodeOps:o,interactables:a}=(()=>{const e=t.ref([]);return{nodeOps:{createElement:fe,createText:e=>m({text:e}),createComment:e=>u({text:e}),insert:ye,nextSibling:e=>e.nextSibling||null,parentNode:e=>e.parentNode||null,patchProp(t,n,r,o){c(t)?"style"===n?Object.keys(o).forEach((e=>{t.domElement.style[e]=o[e]})):t.domElement.setAttribute(n,o):l(t)||n.startsWith("$")||le({node:t,key:n,interactables:e,value:o})},remove:ve,setElementText(){},setText(){}},interactables:e}})(),i=t.createRenderer(o).createApp(n,r);i.provide(Z,a),Object.keys(P).forEach((e=>{i?.component(e,P[e])})),i.provide(D,(e=>{i.setCustomRender(e)})),i.provide(F,(()=>{i.clearCustomRender()}));const s=[];i.provide(K,s),i.provide(I,((e,t=1/0)=>{t===1/0?s.push(e):s.splice(t,0,e)})),i.provide(V,(e=>{if(isFinite(e))s.splice(e,1);else{const t=s.findIndex((t=>t==e));-1!==t&&s.splice(t,1)}}));const d=[];i.provide(U,d),i.provide(z,((e,t=1/0)=>{t===1/0?d.push(e):d.splice(t,0,e)})),i.provide(H,(e=>{if(isFinite(e))d.splice(e,1);else{const t=d.findIndex((t=>t==e));-1!==t&&d.splice(t,1)}})),i.config.globalProperties.lunchbox=t.reactive({afterRender:d,beforeRender:s,camera:null,dpr:1,frameId:-1,renderer:null,scene:null,watchStopHandle:null}),i.provide(O,i.config.globalProperties.lunchbox),i.provide($,(e=>{Object.keys(e).forEach((t=>{const n=t;i.config.globalProperties.lunchbox[n]=e[n]}))})),i.provide(W,i.config.globalProperties.lunchbox.frameId),i.provide(q,i.config.globalProperties.lunchbox.watchStopHandle);const{mount:p}=i;i.mount=(t,...n)=>{const r="string"==typeof t?document.querySelector(t):t,o=new e.MiniDom.RendererRootNode({domElement:r,isLunchboxRootNode:!0,name:"root",metaType:"rootMeta",type:"root",uuid:"LUNCHBOX_ROOT"});i.rootNode=o,i.provide(X,o);return p(o,...n)},i.extend=e=>(E({app:i,...e}),i);return i.provide(ee,[]),i.setCustomRender=e=>{i&&(i.customRender=e)},i.clearCustomRender=()=>{i&&(i.customRender=null)},i.provide(Y,i),i.provide(_,t.computed((()=>i.config.globalProperties.lunchbox.renderer))),i.provide(J,t.computed((()=>i.config.globalProperties.lunchbox.scene))),i.provide(Q,t.computed((()=>i.config.globalProperties.lunchbox.camera))),i._props,i};e.addEventListener=f,e.afterRenderKey=U,e.appCameraKey=Q,e.appKey=Y,e.appRenderersKey=_,e.appRootNodeKey=X,e.appSceneKey=J,e.beforeRenderKey=K,e.cancelUpdate=se,e.cancelUpdateSource=de,e.clearCustomRender=()=>{Ae()?.clearCustomRender?.()},e.clearCustomRenderKey=F,e.createApp=Me,e.createCommentNode=u,e.createDomNode=p,e.createNode=h,e.createTextNode=m,e.extend=E,e.find=function(e){return e=t.isRef(e)?e.value:e,d(e)?e?.instance:s(e)?e?.$el?.instance:t.isVNode(e)?e.el?.instance:null},e.frameIdKey=W,e.getInstance=(e,n=!0)=>t.computed((()=>{const r=e.value?.$el?.instance??e.value?.instance??null;return r&&n?t.toRaw(r):r})),e.globalsInjectionKey=O,e.instantiateThreeObject=N,e.isMinidomNode=function(e){return"RendererNode"===e?.minidomType},e.lunchbox=xe,e.lunchboxInteractables=Z,e.nestedPropertiesToCheck=pe,e.offAfterRender=e=>{re().offBeforeRender?.(e)},e.offAfterRenderKey=H,e.offBeforeRender=ae,e.offBeforeRenderKey=V,e.onAfterRender=(e,t=1/0)=>{re().onBeforeRender?.(e,t)},e.onAfterRenderKey=z,e.onBeforeRender=oe,e.onBeforeRenderKey=I,e.onCameraReady=e=>{const n=Re();if(n.value)return void e(n.value);let r=null;r=t.watch(Re(),(t=>{t&&(e(t),r?.())}))},e.onRendererReady=Ce,e.onSceneReady=e=>{const n=Pe();if(n.value)return void e(n.value);let r=null;r=t.watch(Pe(),(t=>{t&&(e(t),r?.())}),{immediate:!0})},e.onStart=(e,t=1/0)=>{const n=je();t===1/0?n?.push(e):n?.splice(t,0,e)},e.setCustomRender=e=>{Ae()?.setCustomRender?.(e)},e.setCustomRenderKey=D,e.startCallbackKey=ee,e.update=ne,e.updateGlobals=e=>{Ne()?.(e)},e.updateGlobalsInjectionKey=$,e.updateObjectProp=le,e.useAfterRender=()=>({onAfterRender:t.inject(I),offAfterRender:t.inject(V)}),e.useApp=Le,e.useBeforeRender=re,e.useCamera=Re,e.useCancelUpdate=ie,e.useCancelUpdateSource=ce,e.useCustomRender=Ae,e.useGlobals=Ee,e.useLunchboxInteractables=Be,e.useRenderer=we,e.useScene=Pe,e.useStartCallbacks=je,e.useUpdateGlobals=Ne,e.watchStopHandleKey=q}));
@@ -1,4 +1,4 @@
1
- import { isRef, isVNode, toRaw, defineComponent, createVNode, resolveComponent, ref, onBeforeUnmount, watch, reactive, onMounted, computed, Fragment, mergeProps, h, inject, createRenderer } from 'vue';
1
+ import { isRef, isVNode, toRaw, defineComponent, createVNode, resolveComponent, ref, onBeforeUnmount, watch, reactive, onMounted, computed, Fragment, mergeProps, h, inject, getCurrentInstance, onUnmounted, createRenderer } from 'vue';
2
2
  import * as THREE from 'three';
3
3
 
4
4
  function find(target) {
@@ -1118,25 +1118,30 @@ function isMinidomNode(item) {
1118
1118
  return item?.minidomType === 'RendererNode';
1119
1119
  }
1120
1120
 
1121
- const globalsInjectionKey = Symbol();
1122
- const updateGlobalsInjectionKey = Symbol();
1123
- const setCustomRenderKey = Symbol();
1124
- const clearCustomRenderKey = Symbol();
1125
- const beforeRenderKey = Symbol();
1126
- const onBeforeRenderKey = Symbol();
1127
- const offBeforeRenderKey = Symbol();
1128
- const afterRenderKey = Symbol();
1129
- const onAfterRenderKey = Symbol();
1130
- const offAfterRenderKey = Symbol();
1131
- const frameIdKey = Symbol();
1132
- const watchStopHandleKey = Symbol();
1133
- const appRootNodeKey = Symbol();
1134
- const appKey = Symbol();
1135
- const appRenderersKey = Symbol();
1136
- const appSceneKey = Symbol();
1137
- const appCameraKey = Symbol();
1138
- const lunchboxInteractables = Symbol();
1139
- const startCallbackKey = Symbol();
1121
+ // These keys originally used Symbols per Vue instructions,
1122
+ // but differing dev/build values made dev difficult.
1123
+ // These strings have some risk of namespace collision,
1124
+ // but that's a low enough risk that they're worth hardcoding
1125
+ // as strings, in my opinion.
1126
+ const globalsInjectionKey = 'lunchbox-globals'; // Symbol()
1127
+ const updateGlobalsInjectionKey = 'lunchbox-updateGlobals'; // Symbol()
1128
+ const setCustomRenderKey = 'lunchbox-setCustomRender'; // Symbol()
1129
+ const clearCustomRenderKey = 'lunchbox-clearCustomRender'; //Symbol()
1130
+ const beforeRenderKey = 'lunchbox-beforeRender'; // Symbol()
1131
+ const onBeforeRenderKey = 'lunchbox-onBeforeRender'; //Symbol()
1132
+ const offBeforeRenderKey = 'lunchbox-offBeforeRender'; // Symbol()
1133
+ const afterRenderKey = 'lunchbox-afterRender'; // Symbol()
1134
+ const onAfterRenderKey = 'lunchbox-onAfterRender'; // Symbol()
1135
+ const offAfterRenderKey = 'lunchbox-offAfterRender'; // Symbol()
1136
+ const frameIdKey = 'lunchbox-frameId'; // Symbol()
1137
+ const watchStopHandleKey = 'lunchbox-watchStopHandle'; // Symbol()
1138
+ const appRootNodeKey = 'lunchbox-appRootNode'; // Symbol()
1139
+ const appKey = 'lunchbox-appKey'; // Symbol()
1140
+ const appRenderersKey = 'lunchbox-renderer'; //Symbol()
1141
+ const appSceneKey = 'lunchbox-scene'; // Symbol()
1142
+ const appCameraKey = 'lunchbox-camera'; //Symbol()
1143
+ const lunchboxInteractables = 'lunchbox-interactables'; // Symbol()
1144
+ const startCallbackKey = 'lunchbox-startCallback'; // Symbol()
1140
1145
 
1141
1146
  const requestUpdate = opts => {
1142
1147
  if (typeof opts.app.config.globalProperties.lunchbox.frameId === 'number') {
@@ -1584,6 +1589,57 @@ const createNodeOps = () => {
1584
1589
  };
1585
1590
  };
1586
1591
 
1592
+ const BridgeComponent = defineComponent({
1593
+ name: 'BridgeComponent',
1594
+ props: {
1595
+ app: {
1596
+ type: Object
1597
+ },
1598
+ root: {
1599
+ type: Object
1600
+ },
1601
+ appSetup: {
1602
+ type: Function,
1603
+ default: app => app
1604
+ }
1605
+ },
1606
+ setup(props, ctx) {
1607
+ // we need an app or root to mount
1608
+ if (!props.app && !props.root) {
1609
+ throw new Error('app or root required as <bridge> prop');
1610
+ }
1611
+ // prep container
1612
+ const container = ref();
1613
+ // create app
1614
+ let app = props.appSetup(props.app ?? createApp(props.root, ctx.attrs));
1615
+ // get all provided values - this isn't in the types or docs, so it may be unstable
1616
+ const provides = getCurrentInstance()?.provides ?? {};
1617
+ // provide values
1618
+ Object.keys(provides).forEach(key => {
1619
+ app?.provide(key, inject(key));
1620
+ });
1621
+ // mount
1622
+ onMounted(() => {
1623
+ app?.mount(container.value);
1624
+ });
1625
+ // unmount
1626
+ onUnmounted(() => {
1627
+ app?.unmount();
1628
+ app = null;
1629
+ });
1630
+ return () => createVNode("div", {
1631
+ "ref": container
1632
+ }, null);
1633
+ }
1634
+ });
1635
+
1636
+ const bridge = {
1637
+ install(app) {
1638
+ // register wrapper component
1639
+ app.component('lunchbox', BridgeComponent);
1640
+ }
1641
+ };
1642
+
1587
1643
  /** The current camera as a computed value. */
1588
1644
  const useCamera = () => inject(appCameraKey);
1589
1645
  /** Run a function using the current camera when it's present. */
@@ -1713,12 +1769,12 @@ const getInstance = (target, raw = true) => computed(() => {
1713
1769
  });
1714
1770
  // CREATE APP
1715
1771
  // ====================
1716
- const createApp = root => {
1772
+ const createApp = (root, rootProps = {}) => {
1717
1773
  const {
1718
1774
  nodeOps,
1719
1775
  interactables
1720
1776
  } = createNodeOps();
1721
- const app = createRenderer(nodeOps).createApp(root);
1777
+ const app = createRenderer(nodeOps).createApp(root, rootProps);
1722
1778
  // provide Lunchbox interaction handlers flag (modified when user references events via
1723
1779
  // @click, etc)
1724
1780
  app.provide(lunchboxInteractables, interactables);
@@ -1860,8 +1916,9 @@ const createApp = root => {
1860
1916
  app.provide(appRenderersKey, computed(() => app.config.globalProperties.lunchbox.renderer));
1861
1917
  app.provide(appSceneKey, computed(() => app.config.globalProperties.lunchbox.scene));
1862
1918
  app.provide(appCameraKey, computed(() => app.config.globalProperties.lunchbox.camera));
1919
+ app._props;
1863
1920
  // done
1864
1921
  return app;
1865
1922
  };
1866
1923
 
1867
- export { MiniDom, addEventListener, afterRenderKey, appCameraKey, appKey, appRenderersKey, appRootNodeKey, appSceneKey, beforeRenderKey, cancelUpdate, cancelUpdateSource, clearCustomRender, clearCustomRenderKey, createApp, createCommentNode, createDomNode, createNode, createTextNode, extend, find, frameIdKey, getInstance, globalsInjectionKey, instantiateThreeObject, isMinidomNode, lunchboxInteractables, nestedPropertiesToCheck, offAfterRender, offAfterRenderKey, offBeforeRender, offBeforeRenderKey, onAfterRender, onAfterRenderKey, onBeforeRender, onBeforeRenderKey, onCameraReady, onRendererReady, onSceneReady, onStart, setCustomRender, setCustomRenderKey, startCallbackKey, update, updateGlobals, updateGlobalsInjectionKey, updateObjectProp, useAfterRender, useApp, useBeforeRender, useCamera, useCancelUpdate, useCancelUpdateSource, useCustomRender, useGlobals, useLunchboxInteractables, useRenderer, useScene, useStartCallbacks, useUpdateGlobals, watchStopHandleKey };
1924
+ export { MiniDom, addEventListener, afterRenderKey, appCameraKey, appKey, appRenderersKey, appRootNodeKey, appSceneKey, beforeRenderKey, cancelUpdate, cancelUpdateSource, clearCustomRender, clearCustomRenderKey, createApp, createCommentNode, createDomNode, createNode, createTextNode, extend, find, frameIdKey, getInstance, globalsInjectionKey, instantiateThreeObject, isMinidomNode, bridge as lunchbox, lunchboxInteractables, nestedPropertiesToCheck, offAfterRender, offAfterRenderKey, offBeforeRender, offBeforeRenderKey, onAfterRender, onAfterRenderKey, onBeforeRender, onBeforeRenderKey, onCameraReady, onRendererReady, onSceneReady, onStart, setCustomRender, setCustomRenderKey, startCallbackKey, update, updateGlobals, updateGlobalsInjectionKey, updateObjectProp, useAfterRender, useApp, useBeforeRender, useCamera, useCancelUpdate, useCancelUpdateSource, useCustomRender, useGlobals, useLunchboxInteractables, useRenderer, useScene, useStartCallbacks, useUpdateGlobals, watchStopHandleKey };
package/package.json CHANGED
@@ -1,82 +1,83 @@
1
1
  {
2
- "name": "lunchboxjs",
3
- "version": "0.2.1017-beta",
4
- "engines": {
5
- "node": ">=16.0.0"
6
- },
7
- "dependencies": {
8
- "uuid": "8.3.2",
9
- "vue": "^3.2.16"
10
- },
11
- "devDependencies": {
12
- "@babel/plugin-transform-runtime": "7.18.10",
13
- "@rollup/plugin-babel": "5.3.1",
14
- "@rollup/plugin-node-resolve": "13.0.5",
15
- "@rollup/plugin-typescript": "8.3.0",
16
- "@types/node": "18.6.3",
17
- "@types/three": "0.141.0",
18
- "@types/uuid": "8.3.1",
19
- "@vitejs/plugin-vue": "3.0.1",
20
- "@vitejs/plugin-vue-jsx": "2.0.0",
21
- "@vue/babel-plugin-jsx": "1.1.1",
22
- "@vue/reactivity": "3.2.41",
23
- "chroma-js": "2.1.2",
24
- "kolorist": "1.5.1",
25
- "lodash": "4.17.21",
26
- "nice-color-palettes": "3.0.0",
27
- "prompt": "1.3.0",
28
- "prompts": "2.4.2",
29
- "rollup": "3.2.5",
30
- "rollup-plugin-delete": "2.0.0",
31
- "rollup-plugin-jsx": "1.0.3",
32
- "rollup-plugin-terser": "7.0.2",
33
- "three": "0.141.0",
34
- "typescript": "^4.4.3",
35
- "vite": "3.0.4",
36
- "vite-plugin-glsl": "0.0.5",
37
- "vitepress": "0.20.1",
38
- "vue-jsx-factory": "0.3.0",
39
- "vue-tsc": "^0.3.0"
40
- },
41
- "peerDependencies": {
42
- "three": "*"
43
- },
44
- "files": [
45
- "dist",
46
- "extras",
47
- "package.json",
48
- "README.md",
49
- "src",
50
- "types.d.ts"
51
- ],
52
- "main": "./dist/lunchboxjs.js",
53
- "module": "./dist/lunchboxjs.module.js",
54
- "types": "dist/lunchboxjs.es.d.ts",
55
- "directories": {
56
- "doc": "docs"
57
- },
58
- "repository": {
59
- "type": "git",
60
- "url": "git+https://github.com/breakfast-studio/lunchboxjs.git"
61
- },
62
- "keywords": [],
63
- "author": "",
64
- "license": "ISC",
65
- "bugs": {
66
- "url": "https://github.com/breakfast-studio/lunchboxjs/issues"
67
- },
68
- "homepage": "https://github.com/breakfast-studio/lunchboxjs#readme",
69
- "description": "",
70
- "scripts": {
71
- "dev": "vite -c utils/vite.config.ts",
72
- "build": "vue-tsc --noEmit && vite build -c utils/vite.config.ts",
73
- "build:tsc": "tsc --project ./utils/tsconfig.lib.json",
74
- "build:rollup": "rollup -c ./utils/lib-rollup.js",
75
- "build:dts": "node utils/cp utils/lib-dts.d.ts dist/lunchboxjs.es.d.ts && node utils/cp utils/lib-dts.d.ts dist/lunchboxjs.umd.d.ts",
76
- "build:lib": "node utils/rm js && npm run build:tsc && npm run build:rollup && npm run build:dts",
77
- "docs:dev": "vitepress dev docs",
78
- "docs:build": "vitepress build docs",
79
- "docs:serve": "vitepress serve docs",
80
- "demo:create": "node utils/createExample"
81
- }
82
- }
2
+ "name": "lunchboxjs",
3
+ "version": "0.2.1019",
4
+ "scripts": {
5
+ "dev": "vite -c utils/vite.config.ts",
6
+ "build": "vue-tsc --noEmit && vite build -c utils/vite.config.ts",
7
+ "build:tsc": "tsc --project ./utils/tsconfig.lib.json",
8
+ "build:rollup": "rollup -c ./utils/lib-rollup.js",
9
+ "build:dts": "node utils/cp utils/lib-dts.d.ts dist/lunchboxjs.es.d.ts && node utils/cp utils/lib-dts.d.ts dist/lunchboxjs.umd.d.ts",
10
+ "build:lib": "node utils/rm js && npm run build:tsc && npm run build:rollup && npm run build:dts",
11
+ "prepare": "npm run build:lib",
12
+ "docs:dev": "vitepress dev docs",
13
+ "docs:build": "vitepress build docs",
14
+ "docs:serve": "vitepress serve docs",
15
+ "demo:create": "node utils/createExample"
16
+ },
17
+ "engines": {
18
+ "node": ">=16.0.0"
19
+ },
20
+ "dependencies": {
21
+ "uuid": "8.3.2",
22
+ "vue": "^3.2.16"
23
+ },
24
+ "devDependencies": {
25
+ "@babel/plugin-transform-runtime": "7.18.10",
26
+ "@rollup/plugin-babel": "5.3.1",
27
+ "@rollup/plugin-node-resolve": "13.0.5",
28
+ "@rollup/plugin-typescript": "8.3.0",
29
+ "@types/node": "18.6.3",
30
+ "@types/three": "0.141.0",
31
+ "@types/uuid": "8.3.1",
32
+ "@vitejs/plugin-vue": "3.0.1",
33
+ "@vitejs/plugin-vue-jsx": "2.0.0",
34
+ "@vue/babel-plugin-jsx": "1.1.1",
35
+ "@vue/reactivity": "3.2.41",
36
+ "chroma-js": "2.1.2",
37
+ "kolorist": "1.5.1",
38
+ "lodash": "4.17.21",
39
+ "lunchboxjs-plugins": "workspace:*",
40
+ "nice-color-palettes": "3.0.0",
41
+ "prompt": "1.3.0",
42
+ "prompts": "2.4.2",
43
+ "rollup": "3.2.5",
44
+ "rollup-plugin-delete": "2.0.0",
45
+ "rollup-plugin-jsx": "1.0.3",
46
+ "rollup-plugin-terser": "7.0.2",
47
+ "three": "0.141.0",
48
+ "typescript": "^4.4.3",
49
+ "vite": "3.0.4",
50
+ "vite-plugin-glsl": "0.0.5",
51
+ "vue-jsx-factory": "0.3.0",
52
+ "vue-tsc": "^0.3.0"
53
+ },
54
+ "peerDependencies": {
55
+ "three": "*"
56
+ },
57
+ "files": [
58
+ "dist",
59
+ "extras",
60
+ "package.json",
61
+ "README.md",
62
+ "src",
63
+ "types.d.ts"
64
+ ],
65
+ "main": "./dist/lunchboxjs.js",
66
+ "module": "./dist/lunchboxjs.module.js",
67
+ "types": "dist/lunchboxjs.es.d.ts",
68
+ "directories": {
69
+ "doc": "docs"
70
+ },
71
+ "repository": {
72
+ "type": "git",
73
+ "url": "git+https://github.com/breakfast-studio/lunchboxjs.git"
74
+ },
75
+ "keywords": [],
76
+ "author": "",
77
+ "license": "ISC",
78
+ "bugs": {
79
+ "url": "https://github.com/breakfast-studio/lunchboxjs/issues"
80
+ },
81
+ "homepage": "https://github.com/breakfast-studio/lunchboxjs#readme",
82
+ "description": ""
83
+ }
package/src/index.ts CHANGED
@@ -198,9 +198,12 @@ export const getInstance = <T = unknown>(
198
198
 
199
199
  // CREATE APP
200
200
  // ====================
201
- export const createApp = (root: Component) => {
201
+ export const createApp = (
202
+ root: Component,
203
+ rootProps: Record<string, any> = {}
204
+ ) => {
202
205
  const { nodeOps, interactables } = createNodeOps()
203
- const app = createRenderer(nodeOps).createApp(root) as Lunch.App
206
+ const app = createRenderer(nodeOps).createApp(root, rootProps) as Lunch.App
204
207
 
205
208
  // provide Lunchbox interaction handlers flag (modified when user references events via
206
209
  // @click, etc)
@@ -387,6 +390,11 @@ export const createApp = (root: Component) => {
387
390
  computed(() => app.config.globalProperties.lunchbox.camera)
388
391
  )
389
392
 
393
+ app._props
394
+
390
395
  // done
391
396
  return app
392
397
  }
398
+
399
+ /** Use this plugin to add a <lunchbox> component in your HTML app. */
400
+ export { bridge as lunchbox } from './plugins/bridge/bridge'
package/src/keys.ts CHANGED
@@ -1,25 +1,31 @@
1
- export const globalsInjectionKey = Symbol()
2
- export const updateGlobalsInjectionKey = Symbol()
1
+ // These keys originally used Symbols per Vue instructions,
2
+ // but differing dev/build values made dev difficult.
3
+ // These strings have some risk of namespace collision,
4
+ // but that's a low enough risk that they're worth hardcoding
5
+ // as strings, in my opinion.
3
6
 
4
- export const setCustomRenderKey = Symbol()
5
- export const clearCustomRenderKey = Symbol()
7
+ export const globalsInjectionKey = 'lunchbox-globals' // Symbol()
8
+ export const updateGlobalsInjectionKey = 'lunchbox-updateGlobals' // Symbol()
6
9
 
7
- export const beforeRenderKey = Symbol()
8
- export const onBeforeRenderKey = Symbol()
9
- export const offBeforeRenderKey = Symbol()
10
+ export const setCustomRenderKey = 'lunchbox-setCustomRender' // Symbol()
11
+ export const clearCustomRenderKey = 'lunchbox-clearCustomRender' //Symbol()
10
12
 
11
- export const afterRenderKey = Symbol()
12
- export const onAfterRenderKey = Symbol()
13
- export const offAfterRenderKey = Symbol()
13
+ export const beforeRenderKey = 'lunchbox-beforeRender' // Symbol()
14
+ export const onBeforeRenderKey = 'lunchbox-onBeforeRender' //Symbol()
15
+ export const offBeforeRenderKey = 'lunchbox-offBeforeRender' // Symbol()
14
16
 
15
- export const frameIdKey = Symbol()
16
- export const watchStopHandleKey = Symbol()
17
+ export const afterRenderKey = 'lunchbox-afterRender' // Symbol()
18
+ export const onAfterRenderKey = 'lunchbox-onAfterRender' // Symbol()
19
+ export const offAfterRenderKey = 'lunchbox-offAfterRender' // Symbol()
17
20
 
18
- export const appRootNodeKey = Symbol()
19
- export const appKey = Symbol()
20
- export const appRenderersKey = Symbol()
21
- export const appSceneKey = Symbol()
22
- export const appCameraKey = Symbol()
23
- export const lunchboxInteractables = Symbol()
21
+ export const frameIdKey = 'lunchbox-frameId' // Symbol()
22
+ export const watchStopHandleKey = 'lunchbox-watchStopHandle' // Symbol()
24
23
 
25
- export const startCallbackKey = Symbol()
24
+ export const appRootNodeKey = 'lunchbox-appRootNode' // Symbol()
25
+ export const appKey = 'lunchbox-appKey' // Symbol()
26
+ export const appRenderersKey = 'lunchbox-renderer' //Symbol()
27
+ export const appSceneKey = 'lunchbox-scene' // Symbol()
28
+ export const appCameraKey = 'lunchbox-camera' //Symbol()
29
+ export const lunchboxInteractables = 'lunchbox-interactables' // Symbol()
30
+
31
+ export const startCallbackKey = 'lunchbox-startCallback' // Symbol()
@@ -0,0 +1,60 @@
1
+ import {
2
+ Component,
3
+ defineComponent,
4
+ getCurrentInstance,
5
+ inject,
6
+ onMounted,
7
+ onUnmounted,
8
+ PropType,
9
+ ref,
10
+ } from 'vue'
11
+ import { createApp, Lunch } from '../..'
12
+
13
+ export const BridgeComponent = defineComponent({
14
+ name: 'BridgeComponent',
15
+ props: {
16
+ app: {
17
+ type: Object as PropType<Lunch.App>,
18
+ },
19
+ root: {
20
+ type: Object as PropType<Component>,
21
+ },
22
+ appSetup: {
23
+ type: Function as PropType<(app: Lunch.App) => Lunch.App>,
24
+ default: (app: Lunch.App) => app,
25
+ },
26
+ },
27
+ setup(props, ctx) {
28
+ // we need an app or root to mount
29
+ if (!props.app && !props.root) {
30
+ throw new Error('app or root required as <bridge> prop')
31
+ }
32
+
33
+ // prep container
34
+ const container = ref<HTMLDivElement>()
35
+ // create app
36
+ let app: Lunch.App | null = props.appSetup(
37
+ props.app ?? createApp(props.root!, ctx.attrs)
38
+ )
39
+
40
+ // get all provided values - this isn't in the types or docs, so it may be unstable
41
+ const provides = (getCurrentInstance() as any)?.provides ?? {}
42
+ // provide values
43
+ Object.keys(provides).forEach((key) => {
44
+ app?.provide(key, inject(key))
45
+ })
46
+
47
+ // mount
48
+ onMounted(() => {
49
+ app?.mount(container.value)
50
+ })
51
+
52
+ // unmount
53
+ onUnmounted(() => {
54
+ app?.unmount()
55
+ app = null
56
+ })
57
+
58
+ return () => <div ref={container} />
59
+ },
60
+ })
@@ -0,0 +1,9 @@
1
+ import { Plugin } from 'vue'
2
+ import { BridgeComponent } from './BridgeComponent'
3
+
4
+ export const bridge: Plugin = {
5
+ install(app) {
6
+ // register wrapper component
7
+ app.component('lunchbox', BridgeComponent)
8
+ },
9
+ }
package/extras/Gltf.vue DELETED
@@ -1,34 +0,0 @@
1
- <template>
2
- <group ref="container">
3
- <gltfLoader :load="[props.src, onLoad, onProgress, onError]" />
4
- </group>
5
- </template>
6
-
7
- <script lang="ts" setup>
8
- import { ref } from 'vue'
9
- import { GLTF } from 'three/examples/jsm/loaders/GLTFLoader'
10
- import { Lunch } from '../src'
11
-
12
- const props = defineProps<{
13
- preventAdd?: boolean
14
- src: string
15
- }>()
16
-
17
- const emit = defineEmits<{
18
- (e: 'load', gltf: GLTF): void
19
- (e: 'progress', evt: ProgressEvent): void
20
- (e: 'error', evt: ErrorEvent): void
21
- }>()
22
-
23
- const container = ref<Lunch.LunchboxComponent<THREE.Group>>()
24
- const onLoad = (gltf: GLTF) => {
25
- if (!props.preventAdd) {
26
- container.value?.$el?.instance?.add(gltf.scene)
27
- }
28
- emit('load', gltf)
29
- }
30
- const onProgress = (evt: ProgressEvent) => {
31
- emit('progress', evt)
32
- }
33
- const onError = (evt: ErrorEvent) => emit('error', evt)
34
- </script>
@@ -1,39 +0,0 @@
1
- <template>
2
- <OrbitControls
3
- ref="controls"
4
- v-if="ready"
5
- :args="orbitArgs"
6
- :autoRotate="false"
7
- :enableDamping="true"
8
- :dampingFactor="0.1"
9
- v-bind="props.options ?? {}"
10
- />
11
- </template>
12
-
13
- <script lang="ts" setup>
14
- import { computed, ref } from 'vue'
15
- import { onBeforeRender, Lunch, useCamera, useRenderer } from '../src'
16
-
17
- // props
18
- const props = defineProps<{
19
- options?: object
20
- }>()
21
-
22
- // computed
23
- const ready = computed(() => {
24
- return camera.value !== null && renderer.value.domElement
25
- })
26
- const camera = useCamera()
27
- const renderer = useRenderer()
28
- const orbitArgs = computed(() => [camera.value, renderer.value?.domElement])
29
-
30
- // update
31
- const controls = ref<Lunch.LunchboxComponent>()
32
- const update = () => {
33
- const instance = controls.value?.$el.instance as any
34
- if (instance && ready.value) {
35
- instance.update()
36
- }
37
- }
38
- onBeforeRender(update)
39
- </script>