@solumflow-app/product-configurator 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ import {a}from'./chunk-YLNPPHX4.js';import*as d from'three';import {RoundedBoxGeometry}from'three/examples/jsm/geometries/RoundedBoxGeometry.js';function X(e){return (Array.isArray(e)?e:[e]).every(o=>!o.transparent&&o.toneMapped)}function Y(e){for(let t of Array.isArray(e)?e:[e]){let o=t.emissive;o&&(o.r>0||o.g>0||o.b>0)&&(t.toneMapped=false);}}var B=1/1e3,f=32;function r(e){return e*B}function _(e){e.computeBoundingBox();let t=e.boundingBox?.getCenter(new d.Vector3);return t&&e.translate(-t.x,-t.y,-t.z),e.computeBoundingBox(),e}function I(e){let t=e.getAttribute("position"),o=e.getAttribute("normal");if(!t||!o)return e;let a=new Float32Array(t.count*2);for(let s=0;s<t.count;s+=1){let m=Math.abs(o.getX(s)),i=Math.abs(o.getY(s)),n=Math.abs(o.getZ(s));m>=i&&m>=n?(a[s*2]=t.getZ(s),a[s*2+1]=t.getY(s)):i>=n?(a[s*2]=t.getX(s),a[s*2+1]=t.getZ(s)):(a[s*2]=t.getX(s),a[s*2+1]=t.getY(s));}return e.setAttribute("uv",new d.BufferAttribute(a,2)),e}function p(e){return I(_(e))}var g=3;function c(e,t=0){let o=Math.min(t,e/4);return o<=0?{depth:e,bevelEnabled:false,curveSegments:f,steps:1}:{depth:e-2*o,bevelEnabled:true,bevelThickness:o,bevelSize:o,bevelOffset:-o,bevelSegments:g,curveSegments:f,steps:1}}function O(e){let[t,,o]=e.size,a=Math.max(0,Math.min(e.params.thickness??0,t,o));return {width:t,depth:o,thickness:a,mirrored:(e.params.mirror??0)>=.5}}function A(e){let{width:t,depth:o,thickness:a,mirrored:s}=O(e),m=[];for(let i=0;i<=f;i+=1){let n=i/f*(Math.PI/2);m.push([t*Math.cos(n),o*Math.sin(n)]);}for(let i=f;i>=0;i-=1){let n=i/f*(Math.PI/2);m.push([(t-a)*Math.cos(n),(o-a)*Math.sin(n)]);}return m.map(([i,n])=>[s?t-i:i,n])}function M(e,t=0){let[,o]=e.size,a=new d.Shape(A(e).map(([m,i])=>new d.Vector2(r(m),r(i)))),s=new d.ExtrudeGeometry(a,c(r(o),r(t)));return s.rotateX(Math.PI/2),p(s)}function G(e,t=0){let[o,a,s]=e.size;return t<=0?p(new d.BoxGeometry(r(o),r(a),r(s))):p(new RoundedBoxGeometry(r(o),r(a),r(s),g,r(t)))}var k=5;function b(e,t){if(t==="sharp"||e.type==="led_strip"||e.type==="model")return 0;let o=Math.min(...e.size,...D(e));return Math.max(0,Math.min(k,o/4))}function D(e){if(e.type==="arc_panel")return [e.params.thickness??0];if(e.type==="niche_panel"){let t=a(e);return t.width<=0||t.height<=0?[]:[t.x,t.y,e.size[0]-t.x-t.width,e.size[1]-t.y-t.height]}return []}function H(e){let[t,o,a]=e.size;return p(new d.BoxGeometry(r(t),r(o),r(a)))}function S(e,t=0){let[o,a$1,s]=e.size,m=a(e),i=new d.Shape;if(i.moveTo(0,0),i.lineTo(r(o),0),i.lineTo(r(o),r(a$1)),i.lineTo(0,r(a$1)),i.closePath(),m.width>0&&m.height>0){let n=new d.Path;n.moveTo(r(m.x),r(m.y)),n.lineTo(r(m.x+m.width),r(m.y)),n.lineTo(r(m.x+m.width),r(m.y+m.height)),n.lineTo(r(m.x),r(m.y+m.height)),n.closePath(),i.holes.push(n);}return p(new d.ExtrudeGeometry(i,c(r(s),r(t))))}function N(e){let[,t,o]=e.size,a=Math.max(0,Math.min(e.params.radius??0,t,o));return {depth:o,height:t,radius:a}}function v(e,t=0){let[o]=e.size,{depth:a,height:s,radius:m}=N(e),i=r(a),n=r(s),h=r(m),u=new d.Shape;u.moveTo(0,0),u.lineTo(i,0),u.lineTo(i,n-h),h>0&&u.absarc(i-h,n-h,h,0,Math.PI/2,false),u.lineTo(0,n),u.closePath();let P=new d.ExtrudeGeometry(u,c(r(o),r(t)));return P.rotateY(-Math.PI/2),p(P)}function U(e){let[t,o]=e.size;return Math.min(t,o)/2}function z(e,t=0){let[o,a,s]=e.size,m=r(o),i=r(a),n=r(U(e)),h=new d.Shape;return h.moveTo(n,0),h.lineTo(m-n,0),h.absarc(m-n,n,n,-Math.PI/2,0,false),h.lineTo(m,i-n),h.absarc(m-n,i-n,n,0,Math.PI/2,false),h.lineTo(n,i),h.absarc(n,i-n,n,Math.PI/2,Math.PI,false),h.lineTo(0,n),h.absarc(n,n,n,Math.PI,3*Math.PI/2,false),p(new d.ExtrudeGeometry(h,c(r(s),r(t))))}var V={box:G,rounded_top_box:v,stadium_prism:z,arc_panel:M,led_strip:H,niche_panel:S,model:e=>G(e)};function ye(e,t){return V[e.type](e,b(e,t))}function le(e){return [r(e.at[0]+e.size[0]/2),r(e.at[1]+e.size[1]/2),r(e.at[2]+e.size[2]/2)]}export{X as a,Y as b,r as c,ye as d,le as e};
@@ -0,0 +1 @@
1
+ import {jsxs,jsx}from'react/jsx-runtime';function d(r){let{id:e,labels:n,nameRequired:i}=r;return jsxs("div",{className:"pc-checkout-grid",children:[jsx(a,{id:`${e}-first`,label:n.checkoutFirstName,children:jsx("input",{id:`${e}-first`,name:"firstName",className:"pc-control",autoComplete:"given-name",required:i,maxLength:100})}),jsx(a,{id:`${e}-last`,label:n.checkoutLastName,children:jsx("input",{id:`${e}-last`,name:"lastName",className:"pc-control",autoComplete:"family-name",required:i,maxLength:100})}),jsx(a,{id:`${e}-email`,label:n.checkoutEmail,wide:true,children:jsx("input",{id:`${e}-email`,name:"email",type:"email",className:"pc-control",autoComplete:"email",required:true,maxLength:254})}),jsx(a,{id:`${e}-phone`,label:n.checkoutPhone,wide:true,children:jsx("input",{id:`${e}-phone`,name:"phone",type:"tel",className:"pc-control",autoComplete:"tel",maxLength:40})})]})}function m(r){let{id:e,labels:n,countries:i}=r,l=o=>{if(!o)return;let s=new FormData(o);r.onPlaceChange({countryCode:String(s.get("countryCode")??""),postalCode:String(s.get("postalCode")??"").trim()});};return jsxs("div",{className:"pc-checkout-grid",children:[jsx(a,{id:`${e}-postal`,label:n.checkoutPostalCode,children:jsx("input",{id:`${e}-postal`,name:"postalCode",className:"pc-control",autoComplete:"postal-code",required:true,maxLength:20,onBlur:o=>l(o.currentTarget.form)})}),jsx(a,{id:`${e}-number`,label:n.checkoutHouseNumber,children:jsx("input",{id:`${e}-number`,name:"houseNumber",className:"pc-control",required:true,maxLength:20})}),jsx(a,{id:`${e}-street`,label:n.checkoutStreet,wide:true,children:jsx("input",{id:`${e}-street`,name:"street",className:"pc-control",autoComplete:"address-line1",required:true,maxLength:160})}),jsx(a,{id:`${e}-city`,label:n.checkoutCity,children:jsx("input",{id:`${e}-city`,name:"city",className:"pc-control",autoComplete:"address-level2",required:true,maxLength:120})}),jsx(a,{id:`${e}-country`,label:n.checkoutCountry,children:jsx("select",{id:`${e}-country`,name:"countryCode",className:"pc-control",autoComplete:"country",onChange:o=>l(o.currentTarget.form),children:i.map(o=>jsx("option",{value:o.code,children:o.label},o.code))})})]})}function a(r){return jsxs("div",{className:r.wide?"pc-field pc-checkout-wide":"pc-field",children:[jsx("label",{className:"pc-label",htmlFor:r.id,children:r.label}),r.children]})}function p(r){let{id:e,labels:n,termsUrl:i,privacyUrl:l}=r;if(!i&&!l)return null;let o=(s,u)=>jsx("a",{href:s,target:"_blank",rel:"noreferrer",children:u});return jsxs("label",{className:"pc-switch pc-checkout-terms",htmlFor:`${e}-terms`,children:[jsx("input",{id:`${e}-terms`,name:"terms",type:"checkbox",required:true}),jsxs("span",{children:[n.checkoutTermsPrefix," ",i?o(i,n.checkoutTerms):null,i&&l?` ${n.checkoutAnd} `:null,l?o(l,n.checkoutPrivacy):null]})]})}function b(r,e,n){return {attribute:r.attribute,selection:e,structureHash:r.structureHash,expected:{state:n.state,totalCents:n.totalCents}}}async function C(r,e){try{return await(await fetch(r,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify(e)})).json()}catch{return {error:"unavailable"}}}function f(){return typeof crypto<"u"&&"randomUUID"in crypto?crypto.randomUUID():`${Date.now()}-${Math.random().toString(36).slice(2)}`}var y=[{code:"NL",label:"Nederland"},{code:"BE",label:"Belgi\xEB"}];function k(r,e){return r==="price_changed"||r==="structure_changed"?e.checkoutPriceChanged:e.checkoutFailed}export{d as a,m as b,a as c,p as d,b as e,C as f,f as g,y as h,k as i};
@@ -0,0 +1 @@
1
+ function n(h){let[t,e]=h.size,a=Math.min(Math.max(h.params.niche_x??0,0),t),i=Math.min(Math.max(h.params.niche_y??0,0),e);return {x:a,y:i,width:Math.min(Math.max(h.params.niche_width??0,0),t-a),height:Math.min(Math.max(h.params.niche_height??0,0),e-i)}}export{n as a};
@@ -0,0 +1 @@
1
+ import {r,q,k,o,p,t,x,s,n}from'./chunk-UEIARFB4.js';import {a}from'./chunk-6ON4U6IB.js';import {e,d,a as a$1}from'./chunk-VQ7GFV6B.js';import'./chunk-YLNPPHX4.js';import'./chunk-GA7MFMMF.js';import {lazy,useState,useMemo,useRef,useEffect,useLayoutEffect,Suspense}from'react';import {ContactShadows,OrbitControls}from'@react-three/drei';import {Canvas,useThree,useFrame}from'@react-three/fiber';import*as w from'three';import {jsxs,jsx,Fragment}from'react/jsx-runtime';import {RectAreaLightUniformsLib}from'three/examples/jsm/lights/RectAreaLightUniformsLib.js';import {RoomEnvironment}from'three/examples/jsm/environments/RoomEnvironment.js';function ae(e){let{handle:t,labels:s}=e,r=(o,n,i,a)=>jsx("button",{type:"button",className:"pc-camera-button",style:{gridArea:a},"aria-label":o,title:o,"data-test":`configurator-camera-${a}`,onClick:()=>{t.current&&i(t.current);},children:jsx("span",{"aria-hidden":"true",children:n})});return jsxs("div",{className:"pc-camera",role:"group","aria-label":s.cameraControls,children:[jsxs("div",{className:"pc-camera-pad",children:[r(s.cameraUp,"\u2191",o=>o.pan(0,1),"up"),r(s.cameraLeft,"\u2190",o=>o.pan(-1,0),"left"),r(s.cameraReset,"\u27F2",o=>o.reset(),"reset"),r(s.cameraRight,"\u2192",o=>o.pan(1,0),"right"),r(s.cameraDown,"\u2193",o=>o.pan(0,-1),"down")]}),jsxs("div",{className:"pc-camera-zoom",children:[r(s.cameraZoomIn,"+",o=>o.zoom(1),"in"),r(s.cameraZoomOut,"\u2212",o=>o.zoom(-1),"out")]})]})}function se(e,t){let r={ArrowLeft:()=>t.pan(-1,0),ArrowRight:()=>t.pan(1,0),ArrowUp:()=>t.pan(0,1),ArrowDown:()=>t.pan(0,-1),"+":()=>t.zoom(1),"=":()=>t.zoom(1),"-":()=>t.zoom(-1),0:()=>t.reset()}[e];return r?.(),r!==void 0}var Pe=Math.PI/180,Fe=.8;function ce(e){let t=new Map;for(let r of e){if(!r.motion)continue;let o=t.get(r.motion.group),n=r.at.map(a=>a*.001),i=r.at.map((a,c)=>(a+r.size[c])*.001);if(!o){t.set(r.motion.group,{motion:r.motion,min:n,max:i,parts:[r.key]});continue}o.parts.push(r.key);for(let a=0;a<3;a+=1)o.min[a]=Math.min(o.min[a],n[a]),o.max[a]=Math.max(o.max[a],i[a]);}let s=new Map;for(let[r,o]of t){let{motion:n,min:i,max:a}=o,c=a[2],m=n.angle*Pe,l=E=>(i[E]+a[E])/2,p=[l(0),l(1),c],u=[0,0,0],y=[0,0,0];if(n.kind==="slide"){let E=a[2]-i[2];y=[0,0,n.distance===null?E*Fe:n.distance*.001];}else n.edge==="bottom"?(p=[l(0),i[1],c],u=[m,0,0]):n.edge==="top"?(p=[l(0),a[1],c],u=[-m,0,0]):n.edge==="left"?(p=[i[0],l(1),c],u=[0,-m,0]):(p=[a[0],l(1),c],u=[0,m,0]);s.set(r,{name:r,kind:n.kind,pivot:p,rotation:u,offset:y,parts:o.parts,min:i,max:a});}return s}function D(e){let t=Math.min(Math.max(e,0),1);return t<.5?2*t*t:1-(-2*t+2)**2/2}function H(){return typeof window<"u"&&typeof window.matchMedia=="function"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches}var me=.45,le=.7;function ue(e){let{geometry:t$1,camera:s$1,interactive:r$1,handle:o,framing:n}=e,{camera:i,invalidate:a,size:c}=useThree(),m=useRef(null),l=useRef(null),p$1=c.height>0?c.width/c.height:void 0,u=r({bounds:t$1.bounds,azimuth:s$1?.azimuth,elevation:s$1?.elevation,framing:n}),[y,E,h]=u.target,{radius:v}=u,b=p({radius:v,reach:e.reach});useLayoutEffect(()=>{let d=[y,E,h],f=l.current,g=m.current;if(f){let M=t({before:f,turning:g?g.target.toArray():f.middle,camera:i.position.toArray(),middle:d,radius:v,bounds:t$1.bounds});i.position.set(...M.position),g?.target.set(...M.target);}else g?.target.set(...d),n==="room"&&p$1&&i.position.set(...r({bounds:t$1.bounds,azimuth:s$1?.azimuth,elevation:s$1?.elevation,aspect:p$1,framing:n}).position);g?.update(),i.lookAt(g?.target??new w.Vector3(...d)),l.current={middle:d,radius:v},a();},[y,E,h,v,i,a]);let S=useRef(null),R=useRef(null),I=(d,f)=>{let g=m.current;g&&(S.current={from:{position:i.position.clone(),target:g.target.clone()},to:{position:d,target:f},progress:H()?1:0},a());},j=e.focus?.id??null,x$1=e.focusEnd??"return";useLayoutEffect(()=>{let d=m.current,f=e.focus;if(d){if(f?.frame){R.current??={position:i.position.clone(),target:d.target.clone()};let g=x({frame:f.frame,middle:[y,E,h],aspect:p$1??1.5});I(new w.Vector3(...g.position),new w.Vector3(...g.target));return}!f&&R.current&&(x$1==="return"&&I(R.current.position,R.current.target),R.current=null);}},[j]),useFrame((d,f)=>{let g=m.current,M=S.current;if(!g||!M)return;M.progress=Math.min(1,M.progress+f/le);let G=D(M.progress);i.position.lerpVectors(M.from.position,M.to.position,G),g.target.lerpVectors(M.from.target,M.to.target,G),g.update(),M.progress>=1&&(S.current=null),a();});let V=d=>{let f=m.current;if(!f)return;let g=new w.Vector3(...s(d.toArray(),t$1.bounds));i.position.add(g.clone().sub(f.target)),f.target.copy(g),f.update(),a();},O=()=>{S.current=null,R.current=null,e.onInteract?.();};return useLayoutEffect(()=>(o.current={pan:(d,f)=>{let g=m.current;if(!g)return;O(),i.updateMatrixWorld();let M=v*.15,G=new w.Vector3().setFromMatrixColumn(i.matrixWorld,0).multiplyScalar(d*M).add(new w.Vector3().setFromMatrixColumn(i.matrixWorld,1).multiplyScalar(f*M));V(g.target.clone().add(G));},zoom:d=>{let f=m.current;if(!f)return;O();let g=i.position.clone().sub(f.target),M=Math.min(Math.max(g.length()*(d>0?.8:1.25),b.minDistance),b.maxDistance);i.position.copy(f.target).add(g.setLength(M)),f.update(),a();},reset:()=>{O();let d=m.current,f=r({bounds:t$1.bounds,azimuth:s$1?.azimuth,elevation:s$1?.elevation,aspect:p$1,framing:n});i.position.set(...f.position),d?.target.set(...f.target),d?.update(),a();}},()=>{o.current=null;})),jsx(OrbitControls,{ref:m,makeDefault:true,enabled:r$1,enablePan:true,screenSpacePanning:true,minDistance:b.minDistance,maxDistance:b.maxDistance,minAzimuthAngle:b.minAzimuthAngle,maxAzimuthAngle:b.maxAzimuthAngle,maxPolarAngle:b.maxPolarAngle,onStart:O,onChange:()=>{let d=m.current;if(!d)return;s(d.target.toArray(),t$1.bounds).some((g,M)=>g!==d.target.getComponent(M))&&V(d.target.clone());}})}function de(e){let t=useThree(n=>n.invalidate),s=JSON.stringify(Object.entries(e).map(([n,i])=>[n,o(i)])),r=useMemo(()=>JSON.parse(s),[s]),o$1=useMemo(()=>Object.fromEntries(r.map(([n,i])=>[n,Ke(i)])),[r]);return useEffect(()=>{let n$1=new w.TextureLoader;n$1.setCrossOrigin("anonymous");let i=false,a=[];for(let[c,m]of r){let l=o$1[c];if(l)for(let p of Je(m))n$1.load(p.url,u=>{if(i){u.dispose();return}u.colorSpace=p.colorSpace,u.wrapS=w.RepeatWrapping,u.wrapT=w.RepeatWrapping;let y=n(m);u.repeat.set(y.repeat,y.repeat),u.rotation=y.rotation,p.apply(l,u),l.needsUpdate=true,a.push(u),t();},void 0,()=>{});}return ()=>{i=true;for(let c of a)c.dispose();}},[r,o$1,t]),useEffect(()=>()=>{for(let n of Object.values(o$1))n.dispose();},[o$1]),o$1}function Ke(e){let t=new w.MeshStandardMaterial({color:e.color,roughness:e.roughness,metalness:e.metalness});return e.emissive&&(t.emissive.set(e.color),t.emissiveIntensity=1,t.toneMapped=false),e.transparent&&(t.transparent=true,t.opacity=e.opacity,t.depthWrite=false),t}function Je(e){let t=[];return e.texture&&t.push({url:e.texture,colorSpace:w.SRGBColorSpace,apply:(s,r)=>{s.map=r,s.color.set("#ffffff");}}),e.normalMap&&t.push({url:e.normalMap,colorSpace:w.NoColorSpace,apply:(s,r)=>{s.normalMap=r,s.normalScale.set(e.normalScale,e.normalScale);}}),e.roughnessMap&&t.push({url:e.roughnessMap,colorSpace:w.NoColorSpace,apply:(s,r)=>{s.roughnessMap=r;}}),t}var qe=lazy(()=>import('./model-part-NMRB6VKW.js')),Qe=.05,et=1e-4;function be(e){let t=de(e.slots),s=useMemo(()=>ce(e.parts),[e.parts]),r=o=>{let n=t[o.slot];if(!n)return null;if(o.type!=="model"||!o.model)return jsx(ge,{part:o,material:n,edges:e.edges},o.key);let i=jsx(ge,{part:o,material:n});return jsx(a,{fallback:i,children:jsx(Suspense,{fallback:i,children:jsx(qe,{part:{...o,model:o.model},material:n})})},`${o.key}:${o.model}`)};return jsxs(Fragment,{children:[e.parts.filter(o=>!o.motion).map(r),[...s.values()].map(o=>jsx(tt,{group:o,open:e.open==="all"||e.open.has(o.name),children:e.parts.filter(n=>n.motion?.group===o.name).map(r)},o.name))]})}function tt(e){let{group:t,open:s}=e,r=useRef(null),o=useRef(0),n=useThree(a=>a.invalidate),i=()=>{let a=r.current;if(!a)return;let c=D(o.current),[m,l,p]=t.pivot,[u,y,E]=t.offset,[h,v,b]=t.rotation;a.position.set(m+u*c,l+y*c,p+E*c),a.rotation.set(h*c,v*c,b*c);};return useLayoutEffect(()=>{i(),n();}),useFrame((a,c)=>{let m=s?1:0;if(o.current===m)return;let l=H()?1:c/me;o.current=m>o.current?Math.min(m,o.current+l):Math.max(m,o.current-l),i(),n();}),jsx("group",{ref:r,children:jsx("group",{position:[-t.pivot[0],-t.pivot[1],-t.pivot[2]],children:e.children})})}function ge(e$1){let{part:t,material:s,edges:r}=e$1,o=useRef(null),n=useRef(false),i=useRef(t.size),a=useThree(y=>y.invalidate),[c,m,l]=e(t),p=JSON.stringify(t.params),u=useMemo(()=>d(t,r),[t.type,t.size[0],t.size[1],t.size[2],p,r]);return useEffect(()=>()=>u.dispose(),[u]),useLayoutEffect(()=>{let y=o.current;if(y){if(!n.current)y.position.set(c,m,l),n.current=true;else {let E=i.current,h=y.scale;h.set(h.x*K(E[0],t.size[0]),h.y*K(E[1],t.size[1]),h.z*K(E[2],t.size[2]));}i.current=t.size,a();}},[u,t.size,c,m,l,a]),useFrame((y,E)=>{let h=o.current;if(!h)return;let v=1-Math.exp(-E/Qe),b=new w.Vector3(c,m,l),S=new w.Vector3(1,1,1),R=Math.max(h.position.distanceTo(b),h.scale.distanceTo(S));if(R<et){R>0&&(h.position.copy(b),h.scale.copy(S));return}h.position.lerp(b,v),h.scale.lerp(S,v),a();}),jsx("mesh",{ref:o,geometry:u,material:s,castShadow:a$1(s),receiveShadow:true})}function K(e,t){return e>0&&t>0?e/t:1}function Re(e,t,s){let r=[];for(let o of e){if(o.type!=="led_strip")continue;let n=t(o);if(!n)continue;let[i,a,c]=o.size.map(E=>E*.001),m=o.at.map((E,h)=>(E+o.size[h]/2)*.001),l=Math.round(o.params.facing??0),p=l===0||l===1?c:a,u={width:Math.max(i,.04),height:Math.max(p,.04)},y=l===1?[Math.PI/2,0,0]:l===2?[0,Math.PI,0]:l===3?[0,0,0]:[-Math.PI/2,0,0];r.push({key:o.key,position:m,rotation:y,...u,color:n,intensity:18});}return r.map(o=>({light:o,distance:rt(o.position,s)})).sort((o,n)=>o.distance-n.distance).slice(0,8).map(({light:o})=>o)}function rt(e,t){return (e[0]-t[0])**2+(e[1]-t[1])**2+(e[2]-t[2])**2}RectAreaLightUniformsLib.init();function ve(e){return jsx(Fragment,{children:e.lights.map(t=>jsx("rectAreaLight",{position:t.position,rotation:t.rotation,width:t.width,height:t.height,color:t.color,intensity:t.intensity},t.key))})}var Te=.25,lt=.4;function xe(e){let{night:t,lighting:s,keyLight:r,fillLight:o}=e,n=useRef(1),{scene:i,invalidate:a}=useThree(),c=()=>{r.current&&(r.current.intensity=s.key.intensity*n.current),o.current&&(o.current.intensity=s.fill.intensity*n.current),i.environmentIntensity=s.environmentIntensity*n.current;};return useLayoutEffect(()=>{c(),a();}),useFrame((m,l)=>{let p=t?Te:1;if(n.current===p)return;let u=H()?1:l/lt*(1-Te);n.current=p>n.current?Math.min(p,n.current+u):Math.max(p,n.current-u),c(),a();}),null}function _e(e){let{frame:t,wallColor:s,floorColor:r}=e,o=useMemo(()=>new w.MeshStandardMaterial({roughness:.92,metalness:0,side:w.FrontSide,polygonOffset:true,polygonOffsetFactor:2,polygonOffsetUnits:2}),[]),n=useMemo(()=>new w.MeshStandardMaterial({roughness:.7,metalness:0,side:w.FrontSide,polygonOffset:true,polygonOffsetFactor:1,polygonOffsetUnits:1}),[]),i=useThree(a=>a.invalidate);return useLayoutEffect(()=>{o.color.set(s),n.color.set(r),i();},[o,n,s,r,i]),useEffect(()=>()=>{o.dispose(),n.dispose();},[o,n]),jsxs("group",{children:[jsx("mesh",{position:t.wall.position,material:o,receiveShadow:true,children:jsx("planeGeometry",{args:t.wall.size})}),jsx("mesh",{position:t.floor.position,rotation:[-Math.PI/2,0,0],material:n,receiveShadow:true,children:jsx("planeGeometry",{args:t.floor.size})})]})}function Oe(e,t,s=0){let r=Math.max(t.margin*.001,s*.9),o=e.min[0]*.001-r,n=e.max[0]*.001+r,i=n-o,a=(o+n)/2,c=e.min[1]*.001,m=e.min[2]*.001-.002,l=Math.max(t.depth*.001,(e.max[2]-e.min[2])*.001/2+s*1.1),p=Math.max((e.max[1]-e.min[1])*.001+.6,2.7);return {wall:{position:[a,c+p/2,m],size:[i,p]},floor:{position:[a,c,m+l/2],size:[i,l]},wallZ:m,frontZ:m+l,floorY:c}}var Le={studio:{exposure:1,environmentIntensity:.12,key:{color:"#ffffff",intensity:2.9,position:[2,4,5]},fill:{sky:"#fffaf2",ground:"#d8d2c8",intensity:.7},shadowOpacity:.45},warm:{exposure:1,environmentIntensity:.14,key:{color:"#ffead6",intensity:3.2,position:[1.5,3.5,5]},fill:{sky:"#fff0dc",ground:"#d6c6b0",intensity:.8},shadowOpacity:.5},daylight:{exposure:1,environmentIntensity:.18,key:{color:"#f4f7ff",intensity:3.3,position:[2.5,4.5,5]},fill:{sky:"#eef3ff",ground:"#d9d9d6",intensity:1},shadowOpacity:.35}};function Ce(e){return k.includes(e)?Le[e]:Le.studio}function He(e){let r=(e.max[0]-e.min[0])*.001+.4,o=(e.max[2]-e.min[2])*.001+.2,n=e.min[2]*.001;return {position:[(e.min[0]+e.max[0])/2*.001,e.min[1]*.001-.001,n+o/2],scale:[r,o]}}function Ie(){let e=useThree(t=>t.get);return useEffect(()=>{let{gl:t,scene:s,invalidate:r}=e(),o=new w.PMREMGenerator(t),n=new RoomEnvironment,i=o.fromScene(n,.04);return n.dispose(),o.dispose(),s.environment=i.texture,r(),()=>{s.environment===i.texture&&(s.environment=null),i.dispose();}},[e]),null}function ke(e){let{exposure:t}=e,s=useThree(r=>r.get);return useEffect(()=>{let{gl:r,invalidate:o}=s();r.toneMapping=w.NeutralToneMapping,r.toneMappingExposure=t,r.outputColorSpace=w.SRGBColorSpace,o();},[s,t]),null}var St=.75;function Co(e){let{geometry:t,slots:s,camera:r$1,interactive:o$1=true,className:n}=e,i=Ce(e.lighting),{room:a}=e,c=a?"room":"sphere",m=useState(()=>r({bounds:t.bounds,azimuth:r$1?.azimuth,elevation:r$1?.elevation,framing:c}))[0],l=He(t.bounds),p=a?q(r({bounds:t.bounds,azimuth:r$1?.azimuth,elevation:r$1?.elevation,aspect:St,framing:c})):void 0,u=a?Oe(t.bounds,a,p):null,y=useMemo(()=>e.openAll?"all":new Set(e.focus?.open??[]),[e.openAll,e.focus]),E=useRef(null),h=useRef(null),v=useMemo(()=>{let x=e.focus?.frame,V=x?x.min.map((O,d)=>(O+x.max[d])/2):m.target;return Re(t.parts,O=>{let d=s[O.slot],f=d?o(d):null;return f?.emissive?f.color:null},V)},[t.parts,s,e.focus,m.target]),b=t.parts.some(x=>x.type==="led_strip"),S=useRef(null),R=o$1&&e.cameraLabels,I=useRef(null),j=xt(I,o$1&&e.wheelZoom==="modifier");return jsxs("div",{ref:I,className:n,onPointerDownCapture:e.onInteract,onWheelCapture:e.onInteract,style:{position:"relative",width:"100%",height:"100%"},onContextMenu:x=>x.preventDefault(),tabIndex:R?0:void 0,onKeyDown:x=>{R&&S.current&&se(x.key,S.current)&&x.preventDefault();},children:[jsxs(Canvas,{frameloop:"demand",dpr:[1,2],camera:{fov:35,position:m.position,near:.05,far:100},gl:{antialias:true,alpha:true},shadows:"soft",children:[jsx(ke,{exposure:i.exposure}),jsx(Ie,{}),jsx(wt,{lamp:E,position:i.key.position,color:i.key.color,target:m.target,radius:m.radius}),jsx("hemisphereLight",{ref:h,color:i.fill.sky,groundColor:i.fill.ground}),jsx(xe,{night:e.night??false,lighting:i,keyLight:E,fillLight:h}),jsx(ve,{lights:v}),jsx(be,{parts:t.parts,slots:s,edges:e.edges,open:y}),a&&u?jsx(_e,{frame:u,wallColor:a.wallColor,floorColor:a.floorColor}):jsx(ContactShadows,{position:l.position,opacity:i.shadowOpacity,scale:l.scale,resolution:1024,blur:2,far:1.5}),jsx(ue,{geometry:t,camera:r$1,interactive:o$1,handle:S,framing:c,reach:p,focus:e.focus??null,focusEnd:e.focusEnd??"return",onInteract:e.onInteract})]}),R?jsx(ae,{handle:S,labels:R}):null,o$1&&b&&e.nightToggle?jsx("button",{type:"button",className:"pc-night-toggle","aria-pressed":e.night??false,"data-test":"configurator-night",onClick:e.nightToggle.onToggle,children:e.night?e.nightToggle.light:e.nightToggle.dim}):null,j&&e.wheelZoomHint?jsx("p",{className:"pc-wheel-hint",role:"status",children:e.wheelZoomHint}):null]})}var vt=1500;function xt(e,t){let[s,r]=useState(false);return useEffect(()=>{let o=e.current;if(!t||!o)return;let n,i=a=>{a.ctrlKey||a.metaKey||(a.stopPropagation(),r(true),clearTimeout(n),n=setTimeout(()=>r(false),vt));};return o.addEventListener("wheel",i,{capture:true}),()=>{clearTimeout(n),o.removeEventListener("wheel",i,{capture:true});}},[e,t]),s}function wt(e){let{target:t,radius:s}=e,r=e.lamp,o=useThree(i=>i.invalidate),n=Math.max(s*1.5,1);return useLayoutEffect(()=>{let i=r.current;if(!i)return;let a=new w.Vector3(...e.position).normalize();i.position.set(...t).add(a.multiplyScalar(n*2)),i.target.position.set(...t),i.target.updateMatrixWorld();let c=i.shadow.camera;c.left=-n,c.right=n,c.top=n,c.bottom=-n,c.near=.1,c.far=n*4,c.updateProjectionMatrix(),i.shadow.needsUpdate=true,o();},[r,e.position,t,n,o]),jsx("directionalLight",{ref:r,color:e.color,castShadow:true,"shadow-mapSize":[2048,2048],"shadow-bias":-8e-4,"shadow-normalBias":.04,"shadow-radius":4})}export{Co as ConfiguratorScene};
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { JSX } from 'react';
1
+ import type { JSX, ReactNode } from 'react';
2
2
 
3
3
  /**
4
4
  * The public types of `@solumflow-app/product-configurator`, written by hand
@@ -46,11 +46,35 @@ export interface ConfigurationPayload {
46
46
  expected: { state: ConfigurationQuoteState; totalCents: number | null };
47
47
  }
48
48
 
49
- /** A product as `getProduct` returns it; only `fields` is read. */
49
+ /** A product as `getProduct` returns it; `fields`, and `id` for `checkout`. */
50
50
  export interface ConfiguratorProduct {
51
+ id?: string;
51
52
  fields: Record<string, unknown>;
52
53
  }
53
54
 
55
+ /**
56
+ * Ordering and asking for a quote in the panel, through one route on the
57
+ * site's own server that holds the secret key:
58
+ * `createConfiguratorCheckoutHandler` from
59
+ * `@solumflow-app/crm-client/configurator-checkout`. Paying needs the
60
+ * optional peers `@stripe/stripe-js` and `@stripe/react-stripe-js`, loaded
61
+ * only when a visitor reaches the payment.
62
+ */
63
+ export interface ConfiguratorCheckoutProps {
64
+ /** The site's route, e.g. `/api/solumflow/configurator`. */
65
+ endpoint: string;
66
+ termsUrl?: string;
67
+ privacyUrl?: string;
68
+ /** `true` by default; only a fully priced configuration can be ordered. */
69
+ allowOrder?: boolean;
70
+ /** `true` by default. */
71
+ allowRequest?: boolean;
72
+ /** Where a bank's own payment page sends the visitor back; this page by default. */
73
+ returnUrl?: string;
74
+ /** The countries an address may be in; the Netherlands and Belgium by default. */
75
+ countries?: { code: string; label: string }[];
76
+ }
77
+
54
78
  /** Every word the configurator shows that does not come from the product. Dutch by default. */
55
79
  export interface ConfiguratorLabels {
56
80
  tabsLabel: string;
@@ -79,25 +103,105 @@ export interface ConfiguratorLabels {
79
103
  cameraZoomIn: string;
80
104
  cameraZoomOut: string;
81
105
  cameraReset: string;
106
+ viewsLabel: string;
107
+ views3d: string;
108
+ viewsSketch: string;
109
+ wheelZoomHint: string;
110
+ panelExpand: string;
111
+ panelCollapse: string;
112
+ roomTab: string;
113
+ roomWall: string;
114
+ roomFloor: string;
115
+ nightDim: string;
116
+ nightLight: string;
117
+ checkoutOrder: string;
118
+ checkoutRequest: string;
119
+ checkoutBack: string;
120
+ checkoutSummary: string;
121
+ checkoutDetails: string;
122
+ checkoutFirstName: string;
123
+ checkoutLastName: string;
124
+ checkoutEmail: string;
125
+ checkoutPhone: string;
126
+ checkoutPostalCode: string;
127
+ checkoutHouseNumber: string;
128
+ checkoutStreet: string;
129
+ checkoutCity: string;
130
+ checkoutCountry: string;
131
+ checkoutMessage: string;
132
+ checkoutDelivery: string;
133
+ checkoutDeliveryAfterAddress: string;
134
+ checkoutTermsPrefix: string;
135
+ checkoutTerms: string;
136
+ checkoutPrivacy: string;
137
+ checkoutAnd: string;
138
+ checkoutToPayment: string;
139
+ checkoutPay: string;
140
+ checkoutTotal: string;
141
+ checkoutSend: string;
142
+ checkoutOrderPlaced: string;
143
+ checkoutOrderNumber: string;
144
+ checkoutPaymentReceived: string;
145
+ checkoutRequestSent: string;
146
+ checkoutRequestSentNote: string;
147
+ checkoutPriceChanged: string;
148
+ checkoutPaymentsUnavailable: string;
149
+ checkoutFailed: string;
150
+ }
151
+
152
+ /** How the room around the furniture looks: a code per surface. A view, never part of an order. */
153
+ export interface RoomView {
154
+ wall: string;
155
+ floor: string;
82
156
  }
83
157
 
84
158
  export interface ConfigurationChange {
85
159
  selection: ConfigurationSelection;
160
+ /** The room's colours; null where the product draws no room. Also changes on its own. */
161
+ view: RoomView | null;
86
162
  /** Null while the selection cannot be priced. */
87
163
  quote: ConfigurationQuote | null;
88
164
  /** What to submit for this selection; null while it cannot be priced. */
89
165
  payload: ConfigurationPayload | null;
90
166
  }
91
167
 
168
+ export interface ConfiguratorActionState {
169
+ payload: ConfigurationPayload | null;
170
+ /** Everything chosen has a price: only then can it be ordered. */
171
+ priced: boolean;
172
+ }
173
+
92
174
  export interface ProductConfiguratorProps {
93
175
  product: ConfiguratorProduct;
94
176
  /** The slug of the configurator field. */
95
177
  attribute: string;
96
178
  initialSelection?: ConfigurationSelection;
179
+ /** The room's colours to start with, by code. */
180
+ initialView?: Partial<RoomView>;
97
181
  onChange?: (change: ConfigurationChange) => void;
98
- /** Draws a submit button that hands over the payload; the site submits it. */
182
+ /** Draws a submit button that hands over the payload; the site submits it. Ignored when `actions` is given. */
99
183
  onSubmit?: (payload: ConfigurationPayload) => void;
100
184
  submitLabel?: string;
185
+ /**
186
+ * The site's own buttons, drawn in the panel under the price. A function
187
+ * is given what to submit for the current selection (null while it cannot
188
+ * be priced) and whether everything has a price, so only then can it be
189
+ * ordered.
190
+ */
191
+ actions?: ReactNode | ((state: ConfiguratorActionState) => ReactNode);
192
+ /**
193
+ * `inline` (the default): a picture of 4:3 beside the choices, the
194
+ * dimension sketch under it. `fill`: the whole box the site gives it -- the
195
+ * site sets the height, e.g. `100dvh` -- the choices to the right, or under
196
+ * the picture below 900px wide.
197
+ */
198
+ layout?: 'inline' | 'fill';
199
+ /** Two views draw tabs over the picture. `fill` offers both by default. */
200
+ views?: Array<'3d' | 'sketch'>;
201
+ /** `modifier`: Ctrl/⌘ + wheel zooms, a plain wheel scrolls the page. The default in `fill`. */
202
+ wheelZoom?: 'always' | 'modifier';
203
+ /** Order and request in the panel itself; see `ConfiguratorCheckoutProps`. */
204
+ checkout?: ConfiguratorCheckoutProps;
101
205
  labels?: Partial<ConfiguratorLabels>;
102
206
  /** For amounts: `nl-NL` by default. */
103
207
  locale?: string;
@@ -153,6 +257,14 @@ export interface ConfigurationPart {
153
257
  params: Record<string, number>;
154
258
  /** A model block's file, as a URL. */
155
259
  model?: string;
260
+ /** How the part opens: its group (`vak_2`), a hinge about an edge or a slide forwards. */
261
+ motion?: {
262
+ group: string;
263
+ kind: 'hinge' | 'slide';
264
+ edge: 'bottom' | 'top' | 'left' | 'right';
265
+ angle: number;
266
+ distance: number | null;
267
+ };
156
268
  }
157
269
 
158
270
  export type ComputedConfiguration =
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import {e,g,f,b,k,c,d,a,i,o,l,h,n}from'./chunk-ATEH2U7F.js';import {b as b$1}from'./chunk-RNTBO6KY.js';import {lazy,useMemo,useState,useSyncExternalStore,Suspense,useRef,useEffect,useId}from'react';import {jsxs,jsx}from'react/jsx-runtime';var te="#b8b4ad",Me=1e-6;function W(n){let{structure:e,value:t,selection:o}=n,r=[],s=new Map(e.parameters.map(a=>[a.key,a])),m=new Map(e.materials.map(a=>[a.code,a]));for(let a$1 of Object.keys(o.values))s.has(a$1)||r.push(a(["values",a$1],"configurator.unknownParam",{key:a$1}));let l$1=e.presets?t.presets.map(a=>({code:a.code,label:a.label,productId:a.productId})):[],c=null;o.preset!==void 0&&(c=l$1.find(a=>a.code===o.preset)??null,c||r.push(a(["preset"],"configurator.presetNotOffered",{code:o.preset}))),!c&&e.presets?.required&&(c=l$1[0]??null);let u=c?t.presets.find(a=>a.code===c?.code)?.values??{}:{},p=new Set(e.presets?.sets??[]),f=new Map,v={},d$1=a=>{let g=f.get(a.param),N=g?.visible?g.value:null;switch(a.op){case "eq":return N===a.value;case "neq":return N!==a.value;case "in":return Array.isArray(a.value)&&a.value.includes(N);case "gte":return typeof N=="number"&&N>=a.value;case "lte":return typeof N=="number"&&N<=a.value}};for(let a$1 of l(e)){let g=s.get(a$1);if(!g)continue;let N=e.rules.filter(R=>R.param===a$1),i=N.filter(R=>R.kind==="visible").every(R=>d$1(R.when)),b=o.values[a$1],h=["values",a$1],I={key:a$1,kind:g.kind,label:g.label,tab:g.tab};if(g.kind==="number"){let R=t.numbers[a$1]??{min:g.min,max:g.max,default:g.min},C=R.min,P=R.max;for(let H of N){if(H.kind!=="limit")continue;let K=d(H.formula,v);if(!K.ok){r.push(a(["rules",e.rules.indexOf(H)],`configurator.${K.code}`));continue}H.bound==="min"?C=Math.max(C,K.value):P=Math.min(P,K.value);}C>P&&(r.push(a(h,"configurator.emptyRange",{key:a$1,min:C,max:P})),P=C);let j=p.has(a$1)?u[a$1]:void 0,V=de(R.default,C,P);j!==void 0?V=j:i&&b!==void 0&&(typeof b!="number"?r.push(a(h,"configurator.expectedNumber",{key:a$1})):b<C||b>P?(r.push(a(h,"configurator.outOfRange",{key:a$1,min:C,max:P})),V=de(b,C,P)):Ie(b,g.step)?V=b:r.push(a(h,"configurator.offStep",{key:a$1,step:g.step}))),v[a$1]=V,f.set(a$1,{...I,visible:i,value:V,min:C,max:P,step:g.step,unit:g.unit,fixed:j!==void 0,settled:j===void 0&&C===P});continue}if(g.kind==="toggle"){let R=t.toggles[a$1]??{offered:true,default:false};i=i&&R.offered;let C=R.default;i&&b!==void 0&&(typeof b!="boolean"?r.push(a(h,"configurator.expectedBoolean",{key:a$1})):C=b);let P=i&&C;v[a$1]=P?1:0,f.set(a$1,{...I,visible:i,value:P});continue}let G=new Set(N.filter(R=>R.kind==="exclude"&&d$1(R.when)).flatMap(R=>R.kind==="exclude"?R.codes:[])),L,ee;if(g.kind==="choice"){let R=e.choiceLists.find(P=>P.key===g.list),C=t.choices[g.list];L=(R?.options??[]).filter(P=>C?.options[P.code]!==void 0&&!G.has(P.code)).map(P=>({code:P.code,label:P.label,priceCents:C?.options[P.code]?.priceCents??null})),ee=C?.default;}else {let R=t.materials[a$1];L=(R?.offered??[]).map(C=>m.get(C)).filter(C=>C!==void 0).filter(C=>!G.has(C.code)).map(C=>({code:C.code,label:C.label,priceCents:C.priceGroup?t.priceGroups[C.priceGroup]??null:0,material:C})),ee=R?.default;}i=i&&L.length>0;let oe=L.find(R=>R.code===ee)?.code??L[0]?.code??null;i&&b!==void 0&&(typeof b!="string"||!L.some(R=>R.code===b)?r.push(a(h,"configurator.optionNotOffered",{key:a$1,code:String(b)})):oe=b),f.set(a$1,{...I,visible:i,value:i?oe:null,options:L,settled:L.length===1});}let y=e.parameters.map(a=>f.get(a.key)).filter(a=>a!==void 0),x={};for(let a of e.geometry.inputs){let g=f.get(a.binding.param);g&&(g.kind==="number"?x[a.name]=g.value:g.kind==="toggle"?x[a.name]=g.value===true?1:0:g.kind==="choice"&&(x[a.name]=typeof g.value=="string"?a.binding.map?.[g.value]??0:0));}let S={};for(let a of e.geometry.slots){let g=null;if(a.param){let N=f.get(a.param);g=N?.options?.find(i=>i.code===N.value)?.material??null;}else a.material&&(g=m.get(a.material)??null);S[a.name]={color:g?.color??a.color??te,material:g,grain:a.grain==="vertical"?"vertical":"horizontal"};}let M={values:{}};for(let a of y)a.visible&&!a.fixed&&a.value!==null&&(M.values[a.key]=a.value);return c&&(M.preset=c.code),{configuration:{parameters:y,byKey:Object.fromEntries(f),presets:l$1,preset:c,inputs:x,slots:S,selection:M},issues:r}}function Z(n){let e={};for(let t of n.parameters)t.kind==="choice"&&t.visible&&typeof t.value=="string"&&(e[t.key]=t.value);return {choices:e,preset:n.preset?.code}}function de(n,e,t){return Math.min(t,Math.max(e,n))}function Ie(n,e){let t=n/e;return Math.abs(t-Math.round(t))<Me}var Le=1;function U(n){let{structure:e,value:t,tax:o}=n,{configuration:r,issues:s}=W(n);if(s.length>0)return {ok:false,issues:s,configuration:r};let m=[],l={};for(let d of r.parameters)d.kind==="number"?l[d.key]=d.value:d.kind==="toggle"&&(l[d.key]=d.value===true?1:0);let c$1=[{key:"base",label:"base",amountCents:t.basePriceCents}],u=(d$1,y)=>{if(d$1===void 0)return 1;let x=d(d$1,l);return x.ok?x.value<0?(m.push(a(y,"configurator.negativeMultiplier")),null):x.value:(m.push(a(y,`configurator.${x.code}`)),null)};if(e.priceRules.forEach((d$1,y)=>{let x=["priceRules",y];if(d$1.kind==="formula"){let g=Object.fromEntries(e.amounts.map(I=>[I.key,t.amounts[I.key]])),N=c(d$1.formula);if(N.ok&&N.names.some(I=>I in g&&g[I]==null)){c$1.push({key:d$1.key,label:d$1.label,amountCents:null});return}let b={...l};for(let[I,G]of Object.entries(g))typeof G=="number"&&(b[I]=G);let h=d(d$1.formula,b);if(!h.ok){m.push(a([...x,"formula"],`configurator.${h.code}`));return}if(h.value<0){m.push(a([...x,"formula"],"configurator.negativeAmount"));return}fe(c$1,d$1.key,d$1.label,Math.round(h.value));return}let S=r.byKey[d$1.param];if(!S?.visible)return;let M;if(d$1.kind==="toggle"){if(S.value!==true)return;M=t.amounts[d$1.amount]??null;}else {let g=S.options?.find(N=>N.code===S.value);if(!g)return;M=g.priceCents;}if(M===null){c$1.push({key:d$1.key,label:d$1.label,amountCents:null});return}let a$1=u(d$1.multiplier,[...x,"multiplier"]);a$1!==null&&fe(c$1,d$1.key,d$1.label,Math.round(M*a$1));}),m.length>0)return {ok:false,issues:m,configuration:r};let p=t.basePriceCents===null?"open":c$1.some(d=>d.amountCents===null)?"partial":"priced",f=c$1.reduce((d,y)=>d+(y.amountCents??0),0),v=p==="open"?null:$e(f,o);return {ok:true,configuration:r,quote:{engineVersion:Le,state:p,lines:c$1,netCents:v?.netCents??null,taxCents:v?.taxCents??null,totalCents:v?.totalCents??null,taxPercentage:o.taxPercentage,pricesIncludeTax:o.pricesIncludeTax}}}function fe(n,e,t,o){o!==0&&n.push({key:e,label:t,amountCents:o});}function $e(n,e){let t=e.taxPercentage>0?e.taxPercentage:0;if(e.pricesIncludeTax){let r=Math.round(n*t/(100+t));return {netCents:n-r,taxCents:r,totalCents:n}}let o=Math.round(n*t/100);return {netCents:n,taxCents:o,totalCents:n+o}}function Y(n,e,t={choices:{}}){let o=[],r=[],s={...n.constants};for(let u of n.inputs){let p=e[u.name];if(p===void 0||!Number.isFinite(p)){o.push(a(["inputs",u.name],"configurator.inputMissing",{name:u.name}));continue}s[u.name]=p;}if(o.length>0)return {ok:false,issues:o};for(let u of i(n.root))s[u.name]=ge(u.node,t)===void 0?0:1;let m=(u,p,f)=>{let v=d(u,p);return v.ok?v.value:(o.push(v.code==="formula_unknown_name"?a(f,"configurator.unknownName",{name:v.name}):a(f,`configurator.${v.code}`)),null)},l=(u,p,f,v,d)=>{for(let y of u){if(o.length>0)return;let x=[...f,y.id];if(y.visible!==void 0){let i=m(y.visible,p,[...x,"visible"]);if(i===null||i<=0)continue}if(y.type==="repeat"){if(d+1>b.repeatDepth){o.push(a(x,"configurator.repeatTooDeep",{max:b.repeatDepth}));return}let i=m(y.count,p,[...x,"count"]);if(i===null)return;if(!Number.isInteger(i)||i<0||i>b.repeatCount){o.push(a([...x,"count"],"configurator.repeatCountInvalid",{count:i,max:b.repeatCount}));return}let b$1=y.index??"i";for(let h=0;h<i;h+=1)l(y.children,{...p,[b$1]:h},[...x,h],`${v}[${h}]`,d+1);continue}let S=y.size.map((i,b)=>m(i,p,[...x,"size",b])),M=y.at.map((i,b)=>m(i,p,[...x,"at",b]));if(S.includes(null)||M.includes(null))return;let a$1=S.findIndex(i=>i<0);if(a$1>=0){o.push(a([...x,"size",a$1],"configurator.negativeMeasure",{value:S[a$1]}));return}let g=ge(y,t);if(y.type==="model"&&g===void 0)continue;let N={};for(let[i,b]of Object.entries(y.params??{})){let h=m(b,p,[...x,"params",i]);if(h===null)return;N[i]=h;}if(r.push({key:`${y.id}${v}`,id:y.id,type:y.type,slot:y.slot,size:S,at:M,params:N,...g===void 0?{}:{model:g}}),r.length>b.expandedParts){o.push(a(["root"],"configurator.tooManyParts",{max:b.expandedParts}));return}}};l(n.root,s,["root"],"",0);let c=[];for(let u of n.annotations){let p=["annotations",u.id],f=m(u.from,s,[...p,"from"]),v=m(u.to,s,[...p,"to"]),d=m(u.at,s,[...p,"at"]);f===null||v===null||d===null||c.push({id:u.id,axis:u.axis,from:f,to:v,at:d,label:u.label??null,length:Math.abs(v-f)});}return o.length>0?{ok:false,issues:o}:{ok:true,geometry:{parts:r,dimensions:c,bounds:Te(r)}}}function Te(n){if(n.length===0)return {min:[0,0,0],max:[0,0,0]};let e=[1/0,1/0,1/0],t=[-1/0,-1/0,-1/0];for(let o of n)for(let r=0;r<3;r+=1)e[r]=Math.min(e[r],o.at[r]),t[r]=Math.max(t[r],o.at[r]+o.size[r]);return {min:e,max:t}}function ge(n,e){if(n.follows===void 0)return n.model;let t=n.follows===h?e.preset:e.choices[n.follows];return t===void 0?void 0:n.models?.[t]}var D={tabsLabel:"Onderdelen van de configurator",presetNone:"Geen keuze",switchOn:"Aan",switchOff:"Uit",unitMm:"mm",unitCount:"stuks",surchargePrefix:"+",optionOnRequest:"op aanvraag",priceHeading:"Prijs",priceIncludingTax:"incl. btw",priceFrom:"vanaf",priceInPartOnRequest:"deels op aanvraag",priceOnRequest:"prijs op aanvraag",priceUnavailable:"Prijs nog niet te berekenen",sketchTitle:"Maatschets",sketchUnavailable:"Deze combinatie kan niet getekend worden.",sceneLoading:"3D-weergave laden\u2026",sceneLabel:"3D-weergave van de configuratie",cameraControls:"Beeld verschuiven en zoomen",cameraLeft:"Beeld naar links",cameraRight:"Beeld naar rechts",cameraUp:"Beeld omhoog",cameraDown:"Beeld omlaag",cameraZoomIn:"Inzoomen",cameraZoomOut:"Uitzoomen",cameraReset:"Beeld herstellen"};var Ee=`
1
+ import {a as a$3}from'./chunk-5SFWVZIX.js';import {e,g,f,b,l,c,d,a,i,j,m,h,w,v,u,o}from'./chunk-UEIARFB4.js';import {a as a$1}from'./chunk-6ON4U6IB.js';import {a as a$2}from'./chunk-YLNPPHX4.js';import'./chunk-GA7MFMMF.js';import {lazy,useMemo,useState,useRef,useSyncExternalStore,useLayoutEffect,Suspense,useEffect,useId}from'react';import {jsx,jsxs,Fragment}from'react/jsx-runtime';var ue="#b8b4ad",et=1e-6;function oe(o){let{structure:e,value:t,selection:r}=o,n=[],a$1=new Map(e.parameters.map(i=>[i.key,i])),d$1=new Map(e.materials.map(i=>[i.code,i]));for(let i of Object.keys(r.values))a$1.has(i)||n.push(a(["values",i],"configurator.unknownParam",{key:i}));let s=e.presets?t.presets.map(i=>({code:i.code,label:i.label,productId:i.productId})):[],u=null;r.preset!==void 0&&(u=s.find(i=>i.code===r.preset)??null,u||n.push(a(["preset"],"configurator.presetNotOffered",{code:r.preset}))),!u&&e.presets?.required&&(u=s[0]??null);let c=u?t.presets.find(i=>i.code===u?.code)?.values??{}:{},m$1=new Set(e.presets?.sets??[]),l=new Map,y={},g=i=>{let h=l.get(i.param),P=h?.visible?h.value:null;switch(i.op){case "eq":return P===i.value;case "neq":return P!==i.value;case "in":return Array.isArray(i.value)&&i.value.includes(P);case "gte":return typeof P=="number"&&P>=i.value;case "lte":return typeof P=="number"&&P<=i.value}};for(let i of m(e)){let h=a$1.get(i);if(!h)continue;let P=e.rules.filter(w=>w.param===i),p=P.filter(w=>w.kind==="visible").every(w=>g(w.when)),f=r.values[i],v=["values",i],_={key:i,kind:h.kind,label:h.label,tab:h.tab};if(h.kind==="number"){let w=t.numbers[i]??{min:h.min,max:h.max,default:h.min},x=w.min,S=w.max;for(let E of P){if(E.kind!=="limit")continue;let A=d(E.formula,y);if(!A.ok){n.push(a(["rules",e.rules.indexOf(E)],`configurator.${A.code}`));continue}E.bound==="min"?x=Math.max(x,A.value):S=Math.min(S,A.value);}x>S&&(n.push(a(v,"configurator.emptyRange",{key:i,min:x,max:S})),S=x);let $=m$1.has(i)?c[i]:void 0,D=Le(w.default,x,S);$!==void 0?D=$:p&&f!==void 0&&(typeof f!="number"?n.push(a(v,"configurator.expectedNumber",{key:i})):f<x||f>S?(n.push(a(v,"configurator.outOfRange",{key:i,min:x,max:S})),D=Le(f,x,S)):tt(f,h.step)?D=f:n.push(a(v,"configurator.offStep",{key:i,step:h.step}))),y[i]=D,l.set(i,{..._,visible:p,value:D,min:x,max:S,step:h.step,unit:h.unit,fixed:$!==void 0,settled:$===void 0&&x===S});continue}if(h.kind==="toggle"){let w=t.toggles[i]??{offered:true,default:false};p=p&&w.offered;let x=w.default;p&&f!==void 0&&(typeof f!="boolean"?n.push(a(v,"configurator.expectedBoolean",{key:i})):x=f);let S=p&&x;y[i]=S?1:0,l.set(i,{..._,visible:p,value:S});continue}let q=new Set(P.filter(w=>w.kind==="exclude"&&g(w.when)).flatMap(w=>w.kind==="exclude"?w.codes:[])),R,Q;if(h.kind==="choice"){let w=e.choiceLists.find(S=>S.key===h.list),x=t.choices[h.list];R=(w?.options??[]).filter(S=>x?.options[S.code]!==void 0&&!q.has(S.code)).map(S=>({code:S.code,label:S.label,priceCents:x?.options[S.code]?.priceCents??null})),Q=x?.default;}else {let w=t.materials[i];R=(w?.offered??[]).map(x=>d$1.get(x)).filter(x=>x!==void 0).filter(x=>!q.has(x.code)).map(x=>({code:x.code,label:x.label,priceCents:x.priceGroup?t.priceGroups[x.priceGroup]??null:0,material:x})),Q=w?.default;}p=p&&R.length>0;let G=R.find(w=>w.code===Q)?.code??R[0]?.code??null;p&&f!==void 0&&(typeof f!="string"||!R.some(w=>w.code===f)?n.push(a(v,"configurator.optionNotOffered",{key:i,code:String(f)})):G=f),l.set(i,{..._,visible:p,value:p?G:null,options:R,settled:R.length===1});}let b=e.parameters.map(i=>l.get(i.key)).filter(i=>i!==void 0),C={};for(let i of e.geometry.inputs){let h=l.get(i.binding.param);h&&(h.kind==="number"?C[i.name]=h.value:h.kind==="toggle"?C[i.name]=h.value===true?1:0:h.kind==="choice"&&(C[i.name]=typeof h.value=="string"?i.binding.map?.[h.value]??0:0));}let L={};for(let i of e.geometry.slots){let h=null;if(i.param){let P=l.get(i.param);h=P?.options?.find(p=>p.code===P.value)?.material??null;}else i.material&&(h=d$1.get(i.material)??null);L[i.name]={color:h?.color??i.color??ue,material:h,grain:i.grain==="vertical"?"vertical":"horizontal"};}let M={values:{}};for(let i of b)i.visible&&!i.fixed&&i.value!==null&&(M.values[i.key]=i.value);return u&&(M.preset=u.code),{configuration:{parameters:b,byKey:Object.fromEntries(l),presets:s,preset:u,inputs:C,slots:L,selection:M},issues:n}}function ne(o){let e={};for(let t of o.parameters)t.kind==="choice"&&t.visible&&typeof t.value=="string"&&(e[t.key]=t.value);return {choices:e,preset:o.preset?.code}}function Le(o,e,t){return Math.min(t,Math.max(e,o))}function tt(o,e){let t=o/e;return Math.abs(t-Math.round(t))<et}var ot=1;function Z(o){let{structure:e,value:t,tax:r}=o,{configuration:n,issues:a$1}=oe(o);if(a$1.length>0)return {ok:false,issues:a$1,configuration:n};let d$1=[],s={};for(let g of n.parameters)g.kind==="number"?s[g.key]=g.value:g.kind==="toggle"&&(s[g.key]=g.value===true?1:0);let u=[{key:"base",label:"base",amountCents:t.basePriceCents}],c$1=(g,b)=>{if(g===void 0)return 1;let C=d(g,s);return C.ok?C.value<0?(d$1.push(a(b,"configurator.negativeMultiplier")),null):C.value:(d$1.push(a(b,`configurator.${C.code}`)),null)};if(e.priceRules.forEach((g,b)=>{let C=["priceRules",b];if(g.kind==="formula"){let h=Object.fromEntries(e.amounts.map(_=>[_.key,t.amounts[_.key]])),P=c(g.formula);if(P.ok&&P.names.some(_=>_ in h&&h[_]==null)){u.push({key:g.key,label:g.label,amountCents:null});return}let f={...s};for(let[_,q]of Object.entries(h))typeof q=="number"&&(f[_]=q);let v=d(g.formula,f);if(!v.ok){d$1.push(a([...C,"formula"],`configurator.${v.code}`));return}if(v.value<0){d$1.push(a([...C,"formula"],"configurator.negativeAmount"));return}Te(u,g.key,g.label,Math.round(v.value));return}let L=n.byKey[g.param];if(!L?.visible)return;let M;if(g.kind==="toggle"){if(L.value!==true)return;M=t.amounts[g.amount]??null;}else {let h=L.options?.find(P=>P.code===L.value);if(!h)return;M=h.priceCents;}if(M===null){u.push({key:g.key,label:g.label,amountCents:null});return}let i=c$1(g.multiplier,[...C,"multiplier"]);i!==null&&Te(u,g.key,g.label,Math.round(M*i));}),d$1.length>0)return {ok:false,issues:d$1,configuration:n};let m=t.basePriceCents===null?"open":u.some(g=>g.amountCents===null)?"partial":"priced",l=u.reduce((g,b)=>g+(b.amountCents??0),0),y=m==="open"?null:nt(l,r);return {ok:true,configuration:n,quote:{engineVersion:ot,state:m,lines:u,netCents:y?.netCents??null,taxCents:y?.taxCents??null,totalCents:y?.totalCents??null,taxPercentage:r.taxPercentage,pricesIncludeTax:r.pricesIncludeTax}}}function Te(o,e,t,r){r!==0&&o.push({key:e,label:t,amountCents:r});}function nt(o,e){let t=e.taxPercentage>0?e.taxPercentage:0;if(e.pricesIncludeTax){let n=Math.round(o*t/(100+t));return {netCents:o-n,taxCents:n,totalCents:o}}let r=Math.round(o*t/100);return {netCents:o,taxCents:r,totalCents:o+r}}function rt(o,e){return o.replace(/\{([ij])\}/g,(t,r)=>String((e[r]??0)+1))}var at=90;function re(o,e,t={choices:{}}){let r=[],n=[],a$1={...o.constants};for(let c of o.inputs){let m=e[c.name];if(m===void 0||!Number.isFinite(m)){r.push(a(["inputs",c.name],"configurator.inputMissing",{name:c.name}));continue}a$1[c.name]=m;}if(r.length>0)return {ok:false,issues:r};for(let c of i(o.root))a$1[c.name]=Me(c.node,t)===void 0?0:1;let d$1=(c,m,l)=>{let y=d(c,m);return y.ok?y.value:(r.push(y.code==="formula_unknown_name"?a(l,"configurator.unknownName",{name:y.name}):a(l,`configurator.${y.code}`)),null)},s=(c,m,l,y,g)=>{for(let b$1 of c){if(r.length>0)return;let C=[...l,b$1.id];if(b$1.visible!==void 0){let f=d$1(b$1.visible,m,[...C,"visible"]);if(f===null||f<=0)continue}if(b$1.type==="repeat"){if(g+1>b.repeatDepth){r.push(a(C,"configurator.repeatTooDeep",{max:b.repeatDepth}));return}let f=d$1(b$1.count,m,[...C,"count"]);if(f===null)return;if(!Number.isInteger(f)||f<0||f>b.repeatCount){r.push(a([...C,"count"],"configurator.repeatCountInvalid",{count:f,max:b.repeatCount}));return}let v=b$1.index??"i";for(let _=0;_<f;_+=1)s(b$1.children,{...m,[v]:_},[...C,_],`${y}[${_}]`,g+1);continue}let L=b$1.size.map((f,v)=>d$1(f,m,[...C,"size",v])),M=b$1.at.map((f,v)=>d$1(f,m,[...C,"at",v]));if(L.includes(null)||M.includes(null))return;let i=L.findIndex(f=>f<0);if(i>=0){r.push(a([...C,"size",i],"configurator.negativeMeasure",{value:L[i]}));return}let h=Me(b$1,t);if(b$1.type==="model"&&h===void 0)continue;let P={};for(let[f,v]of Object.entries(b$1.params??{})){let _=d$1(v,m,[...C,"params",f]);if(_===null)return;P[f]=_;}let p;if(b$1.motion){let f=b$1.motion.angle===void 0?at:d$1(b$1.motion.angle,m,[...C,"motion","angle"]),v=b$1.motion.distance===void 0?null:d$1(b$1.motion.distance,m,[...C,"motion","distance"]);if(f===null||b$1.motion.distance!==void 0&&v===null)return;p={group:rt(b$1.motion.group,m),kind:b$1.motion.kind,edge:b$1.motion.edge??"bottom",angle:f,distance:v};}if(n.push({key:`${b$1.id}${y}`,id:b$1.id,type:b$1.type,slot:b$1.slot,size:L,at:M,params:P,...h===void 0?{}:{model:h},...p===void 0?{}:{motion:p}}),n.length>b.expandedParts){r.push(a(["root"],"configurator.tooManyParts",{max:b.expandedParts}));return}}};s(o.root,a$1,["root"],"",0);let u=[];for(let c of o.annotations){let m=["annotations",c.id],l=d$1(c.from,a$1,[...m,"from"]),y=d$1(c.to,a$1,[...m,"to"]),g=d$1(c.at,a$1,[...m,"at"]);l===null||y===null||g===null||u.push({id:c.id,axis:c.axis,from:l,to:y,at:g,label:c.label??null,length:Math.abs(y-l)});}return r.length>0?{ok:false,issues:r}:{ok:true,geometry:{parts:n,dimensions:u,bounds:it(n)}}}function it(o){if(o.length===0)return {min:[0,0,0],max:[0,0,0]};let e=[1/0,1/0,1/0],t=[-1/0,-1/0,-1/0];for(let r of o)for(let n=0;n<3;n+=1)e[n]=Math.min(e[n],r.at[n]),t[n]=Math.max(t[n],r.at[n]+r.size[n]);return {min:e,max:t}}function Me(o,e){if(o.follows===void 0)return o.model;let t=o.follows===h?e.preset:e.choices[o.follows];return t===void 0?void 0:o.models?.[t]}var lt=lazy(()=>import('./checkout-step-H45B2AXW.js').then(o=>({default:o.CheckoutStep}))),ut=lazy(()=>import('./request-step-AI77BVKM.js').then(o=>({default:o.RequestStep})));function $e(o){let{checkout:e,selection:t,quote:r,labels:n,locale:a,currency:d,siteActions:s}=o,[u,c]=useState(null),m=e!==void 0&&e.allowOrder!==false&&r?.state==="priced",l=e!==void 0&&e.allowRequest!==false,y=m||l?jsxs(Fragment,{children:[m?jsx("button",{type:"button",className:"pc-checkout-primary","data-test":"configurator-order",onClick:()=>c("order"),children:n.checkoutOrder}):null,l?jsx("button",{type:"button",className:"pc-checkout-secondary","data-test":"configurator-request-quote",onClick:()=>c("request"),children:n.checkoutRequest}):null,s]}):s,g=e&&r&&u==="order"?jsx(lt,{checkout:e,selection:t,quote:r,labels:n,locale:a,currency:d,onBack:()=>c(null)}):e&&r&&u==="request"?jsx(ut,{checkout:e,selection:t,quote:r,labels:n,onBack:()=>c(null)}):null;return {actions:y,stepView:g?jsx(Suspense,{fallback:jsx("p",{className:"pc-scene-note",children:"\u2026"}),children:g}):null}}var B={tabsLabel:"Onderdelen van de configurator",presetNone:"Geen keuze",switchOn:"Aan",switchOff:"Uit",unitMm:"mm",unitCount:"stuks",surchargePrefix:"+",optionOnRequest:"op aanvraag",priceHeading:"Prijs",priceIncludingTax:"incl. btw",priceFrom:"vanaf",priceInPartOnRequest:"deels op aanvraag",priceOnRequest:"prijs op aanvraag",priceUnavailable:"Prijs nog niet te berekenen",sketchTitle:"Maatschets",sketchUnavailable:"Deze combinatie kan niet getekend worden.",sceneLoading:"3D-weergave laden\u2026",sceneLabel:"3D-weergave van de configuratie",cameraControls:"Beeld verschuiven en zoomen",cameraLeft:"Beeld naar links",cameraRight:"Beeld naar rechts",cameraUp:"Beeld omhoog",cameraDown:"Beeld omlaag",cameraZoomIn:"Inzoomen",cameraZoomOut:"Uitzoomen",cameraReset:"Beeld herstellen",viewsLabel:"Weergave",views3d:"3D",viewsSketch:"Tekening",wheelZoomHint:"Ctrl + scroll om te zoomen",panelExpand:"Keuzes tonen",panelCollapse:"Keuzes verbergen",roomTab:"Ruimte",roomWall:"Wand",roomFloor:"Vloer",nightDim:"Avondlicht",nightLight:"Daglicht",checkoutOrder:"Bestellen",checkoutRequest:"Offerte aanvragen",checkoutBack:"Terug naar de keuzes",checkoutSummary:"Je samenstelling",checkoutDetails:"Je gegevens",checkoutFirstName:"Voornaam",checkoutLastName:"Achternaam",checkoutEmail:"E-mailadres",checkoutPhone:"Telefoon",checkoutPostalCode:"Postcode",checkoutHouseNumber:"Huisnummer",checkoutStreet:"Straat",checkoutCity:"Plaats",checkoutCountry:"Land",checkoutMessage:"Je vraag of opmerking",checkoutDelivery:"Levering",checkoutDeliveryAfterAddress:"Vul je adres in om de leveropties te zien.",checkoutTermsPrefix:"Ik ga akkoord met de",checkoutTerms:"algemene voorwaarden",checkoutPrivacy:"privacyverklaring",checkoutAnd:"en de",checkoutToPayment:"Naar betalen",checkoutPay:"Betalen",checkoutTotal:"Totaal",checkoutSend:"Aanvraag versturen",checkoutOrderPlaced:"Bedankt voor je bestelling",checkoutOrderNumber:"Ordernummer",checkoutPaymentReceived:"Je betaling is ontvangen. Je krijgt een bevestiging per e-mail.",checkoutRequestSent:"Bedankt, je aanvraag is verstuurd",checkoutRequestSentNote:"We nemen zo snel mogelijk contact met je op.",checkoutPriceChanged:"De samenstelling is intussen gewijzigd. Controleer de prijs en probeer het opnieuw.",checkoutPaymentsUnavailable:"Online betalen is op dit moment niet mogelijk. Vraag een offerte aan.",checkoutFailed:"Dat lukte niet. Probeer het nog eens."};var mt=`
2
2
  .pc-scope{
3
3
  --_fg:var(--pc-fg,currentColor);--_bg:var(--pc-bg,transparent);
4
4
  --_surface:var(--pc-surface,color-mix(in srgb,currentColor 6%,transparent));
@@ -54,5 +54,52 @@ import {e,g,f,b,k,c,d,a,i,o,l,h,n}from'./chunk-ATEH2U7F.js';import {b as b$1}fro
54
54
  .pc-price-heading{color:var(--_muted);font-size:13px}
55
55
  .pc-price-total{font-size:26px;font-weight:700}
56
56
  .pc-price-note{color:var(--_muted);font-size:13px}
57
+ .pc-panel-foot{display:grid;gap:12px}
58
+ .pc-actions{display:grid;gap:8px}
59
+ .pc-view[hidden]{display:none}
60
+ .pc-views{position:absolute;top:10px;right:10px;z-index:2;display:flex;gap:2px;padding:2px;border-radius:calc(var(--_radius) / 2 + 2px);background:var(--_camera-bg)}
61
+ .pc-views-tab{appearance:none;border:0;border-radius:calc(var(--_radius) / 2);background:none;color:var(--_camera-fg);font:inherit;font-size:13px;padding:5px 12px;cursor:pointer;opacity:.7}
62
+ .pc-views-tab[aria-selected="true"]{background:color-mix(in srgb,var(--_camera-fg) 18%,transparent);opacity:1}
63
+ .pc-views-tab:focus-visible{outline:2px solid var(--_accent);outline-offset:1px}
64
+ .pc-wheel-hint{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);padding:8px 14px;border-radius:var(--_radius);background:color-mix(in srgb,var(--_camera-bg) 85%,transparent);color:var(--_camera-fg);font-size:14px;pointer-events:none;transition:opacity .2s}
65
+ .pc-panel-toggle{display:none}
66
+ .pc-panel-away{display:none!important}
67
+ .pc-checkout{display:grid;gap:16px;align-content:start}
68
+ .pc-checkout-form,.pc-checkout-pay{display:grid;gap:14px}
69
+ .pc-checkout-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px 12px}
70
+ .pc-checkout-wide{grid-column:1 / -1}
71
+ .pc-checkout-title{margin:0;font-size:17px;font-weight:600}
72
+ .pc-checkout-back{appearance:none;justify-self:start;border:0;background:none;padding:0;color:var(--_muted);font:inherit;font-size:13px;cursor:pointer}
73
+ .pc-checkout-lines{list-style:none;margin:0;padding:0;display:grid;gap:4px;font-size:14px}
74
+ .pc-checkout-lines li,.pc-checkout-total{display:flex;justify-content:space-between;gap:12px;margin:0}
75
+ .pc-checkout-total{font-size:18px}
76
+ .pc-checkout-terms{align-items:flex-start;font-size:14px}
77
+ .pc-checkout-terms a{color:inherit}
78
+ .pc-checkout-error{margin:0;color:var(--pc-danger,#b42318);font-size:14px}
79
+ .pc-checkout-primary,.pc-checkout-secondary{appearance:none;width:100%;padding:10px 16px;border-radius:calc(var(--_radius) - 2px);font:inherit;font-weight:600;cursor:pointer}
80
+ .pc-checkout-primary{border:1px solid var(--_accent);background:var(--_accent);color:var(--pc-accent-fg,#ffffff)}
81
+ .pc-checkout-secondary{border:1px solid var(--_border);background:var(--_bg);color:var(--_fg)}
82
+ .pc-checkout-primary:disabled{opacity:.6;cursor:default}
83
+ .pc-checkout-primary:focus-visible,.pc-checkout-secondary:focus-visible,.pc-checkout-back:focus-visible{outline:2px solid var(--_accent);outline-offset:2px}
84
+ .pc-root[data-layout="fill"] .pc-panel{padding-bottom:16px}
85
+ .pc-night-toggle{position:absolute;left:10px;bottom:10px;padding:6px 12px;border:1px solid color-mix(in srgb,var(--_camera-fg) 25%,transparent);border-radius:calc(var(--_radius) / 2);background:var(--_camera-bg);color:var(--_camera-fg);font:inherit;font-size:13px;cursor:pointer;opacity:.85}
86
+ .pc-night-toggle:hover,.pc-night-toggle[aria-pressed="true"]{opacity:1}
87
+ .pc-night-toggle:focus-visible{outline:2px solid var(--_accent);outline-offset:1px}
88
+ .pc-root[data-layout="fill"]{height:100%;gap:0;grid-template-columns:minmax(0,1fr) minmax(320px,400px);grid-template-rows:minmax(0,1fr);align-items:stretch}
89
+ .pc-root[data-layout="fill"] .pc-visual{position:relative;display:block;min-height:0}
90
+ .pc-root[data-layout="fill"] .pc-view{position:absolute;inset:0}
91
+ .pc-root[data-layout="fill"] .pc-view[hidden]{display:none}
92
+ .pc-root[data-layout="fill"] .pc-scene{height:100%;aspect-ratio:auto;min-height:0;border-radius:0}
93
+ .pc-root[data-layout="fill"] .pc-sketch{height:100%;box-sizing:border-box;display:grid;place-items:center;border-radius:0;padding:56px 24px 24px}
94
+ .pc-root[data-layout="fill"] .pc-sketch svg{height:100%;max-height:100%}
95
+ .pc-root[data-layout="fill"] .pc-side{display:flex;flex-direction:column;min-height:0;min-width:0;border-left:1px solid var(--_border)}
96
+ .pc-root[data-layout="fill"] .pc-panel{flex:1;min-height:0;overflow:auto;align-content:start;padding:16px 20px 0}
97
+ .pc-root[data-layout="fill"] .pc-panel-foot{position:sticky;bottom:0;margin-top:auto;padding:0 0 16px;background:var(--pc-panel-bg,var(--pc-bg,Canvas))}
98
+ @media (max-width:899px){
99
+ .pc-root[data-layout="fill"]{grid-template-columns:minmax(0,1fr);grid-template-rows:60% minmax(0,1fr)}
100
+ .pc-root[data-layout="fill"][data-panel="open"]{grid-template-rows:20% minmax(0,1fr)}
101
+ .pc-root[data-layout="fill"] .pc-side{border-left:0;border-top:1px solid var(--_border)}
102
+ .pc-root[data-layout="fill"] .pc-panel-toggle{display:block;appearance:none;border:0;border-bottom:1px solid var(--_border);background:none;color:var(--_muted);font:inherit;font-size:13px;padding:8px;cursor:pointer}
103
+ }
57
104
  .pc-hidden{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
58
- `;function B(){return jsx("style",{href:"product-configurator",precedence:"default",children:Ee})}function be(n,e,t){let o=n%100===0;return new Intl.NumberFormat(e,{style:"currency",currency:t,minimumFractionDigits:o?0:2,maximumFractionDigits:o?0:2}).format(n/100)}function he(n,e){let{min:t,max:o,step:r}=e,s=l=>Math.round(l*1e6)/1e6,m=Math.round(n/r)*r;return m<t&&(m=Math.ceil(t/r)*r),m>o&&(m=Math.floor(o/r)*r),s(Math.min(o,Math.max(t,m)))}function ve(n){let{structure:e,configuration:t,quote:o,onSelectionChange:r,locale:s="nl-NL",currency:m="EUR",disabled:l=false,className:c}=n,u={...D,...n.labels},p=useId(),f=useRef({}),v=e.presets&&t.presets.length>0?e.presets.tab:null,d=e.tabs.filter(i=>i.key===v||t.parameters.some(b=>b.tab===i.key&&ye(b))),[y,x]=useState(d[0]?.key),S=d.find(i=>i.key===y)??d[0],M=i=>be(i,s,m),a=(i,b)=>{r?.({...t.selection,values:{...t.selection.values,[i]:b}});},g=i=>{let{preset:b,...h}=t.selection;r?.(i===""?h:{...h,preset:i});},N=(i,b)=>{let h=i.key==="ArrowRight"?1:i.key==="ArrowLeft"?-1:0,I=d.length-1,G=i.key==="Home"?0:i.key==="End"?I:(b+h+d.length)%d.length;if(h===0&&i.key!=="Home"&&i.key!=="End")return;i.preventDefault();let L=d[G];L&&(x(L.key),f.current[L.key]?.focus());};return jsxs("div",{className:["pc-panel","pc-scope",c].filter(Boolean).join(" "),children:[jsx(B,{}),d.length>1?jsx("div",{role:"tablist","aria-label":u.tabsLabel,className:"pc-tabs",children:d.map((i,b)=>jsx("button",{ref:h=>{f.current[i.key]=h;},type:"button",role:"tab",id:`${p}-tab-${i.key}`,"aria-selected":i.key===S?.key,"aria-controls":`${p}-panel-${i.key}`,tabIndex:i.key===S?.key?0:-1,className:"pc-tab",onClick:()=>x(i.key),onKeyDown:h=>N(h,b),children:i.label},i.key))}):null,S?jsxs("fieldset",{role:d.length>1?"tabpanel":void 0,id:`${p}-panel-${S.key}`,"aria-labelledby":d.length>1?`${p}-tab-${S.key}`:void 0,className:"pc-fields",disabled:l,children:[e.presets&&v===S.key?jsxs("div",{className:"pc-field",children:[jsx("label",{className:"pc-label",htmlFor:`${p}-preset`,children:e.presets.label}),jsxs("select",{id:`${p}-preset`,className:"pc-control",value:t.preset?.code??"",onChange:i=>g(i.target.value),children:[e.presets.required?null:jsx("option",{value:"",children:u.presetNone}),t.presets.map(i=>jsx("option",{value:i.code,children:i.label},i.code))]})]}):null,t.parameters.filter(i=>ye(i)&&i.tab===S.key).map(i=>Ce(i)?jsx(Fe,{id:`${p}-${i.key}`,parameter:i,labels:u,money:M,onChange:b=>a(i.key,b)},i.key):jsx(Ue,{parameter:i,labels:u,money:M},i.key))]}):null,jsx(Be,{quote:o,labels:u,money:M})]})}function Fe(n){let{id:e,parameter:t,labels:o,money:r,onChange:s}=n;if(t.kind==="number"){let l={min:t.min??0,max:t.max??0,step:t.step??1},c=t.value,u=t.unit==="count"?o.unitCount:o.unitMm,p=f=>{Number.isFinite(f)&&s(he(f,l));};return jsxs("div",{className:"pc-field",children:[jsxs("label",{className:"pc-label",htmlFor:`${e}-range`,children:[t.label,jsxs("small",{children:[c," ",u]})]}),jsxs("div",{className:"pc-number",children:[jsx("input",{id:`${e}-range`,className:"pc-control",type:"range",min:l.min,max:l.max,step:l.step,value:c,disabled:t.fixed,onChange:f=>p(f.target.valueAsNumber)}),jsxs("span",{children:[jsx("label",{className:"pc-hidden",htmlFor:`${e}-number`,children:`${t.label} (${u})`}),jsx("input",{id:`${e}-number`,className:"pc-control",type:"number",inputMode:"numeric",min:l.min,max:l.max,step:l.step,defaultValue:c,readOnly:t.fixed,onBlur:f=>p(f.target.valueAsNumber),onKeyDown:f=>{f.key==="Enter"&&p(f.currentTarget.valueAsNumber);}},c)]})]})]})}if(t.kind==="toggle")return jsx("div",{className:"pc-field",children:jsxs("label",{className:"pc-switch",htmlFor:e,children:[jsx("input",{id:e,type:"checkbox",checked:t.value===true,onChange:l=>s(l.target.checked)}),jsx("span",{className:"pc-label",children:t.label})]})});let m=t.options??[];if(t.kind==="material"){let l=m.find(c=>c.code===t.value);return jsxs("fieldset",{className:"pc-field",children:[jsxs("legend",{className:"pc-label",children:[t.label,l?jsx("small",{children:l.label}):null]}),jsx("div",{className:"pc-swatches",children:m.map(c=>jsxs("label",{className:"pc-choice",title:c.label,children:[jsx("input",{type:"radio",name:e,value:c.code,checked:c.code===t.value,onChange:()=>s(c.code)}),jsx("span",{className:"pc-swatch",style:{backgroundColor:c.material?.color,backgroundImage:c.material?.texture?`url("${c.material.texture}")`:void 0},children:jsx("span",{className:"pc-hidden",children:c.label})})]},c.code))})]})}return jsxs("fieldset",{className:"pc-field",children:[jsx("legend",{className:"pc-label",children:t.label}),jsx("div",{className:"pc-choices",children:m.map(l=>jsxs("label",{className:"pc-choice",children:[jsx("input",{type:"radio",name:e,value:l.code,checked:l.code===t.value,onChange:()=>s(l.code)}),jsxs("span",{children:[l.label,jsx("small",{children:xe(l,o,r)})]})]},l.code))})]})}function Ue(n){let{parameter:e,labels:t,money:o}=n,r=e.options?.[0];return r?jsx("div",{className:"pc-field","data-pinned":e.key,children:jsxs("span",{className:"pc-label",children:[e.label,jsxs("small",{children:[r.label," \xB7 ",xe(r,t,o)]})]})}):null}function xe(n,e,t){return n.priceCents===null?e.optionOnRequest:n.priceCents>0?`${e.surchargePrefix} ${t(n.priceCents)}`:""}function Be(n){let{quote:e,labels:t,money:o}=n,r,s=null;return e?e.state==="open"||e.totalCents===null?r=t.priceOnRequest:e.state==="partial"?(r=`${t.priceFrom} ${o(e.totalCents)}`,s=`${t.priceInPartOnRequest}, ${t.priceIncludingTax}`):(r=o(e.totalCents),s=t.priceIncludingTax):r=t.priceUnavailable,jsxs("div",{className:"pc-price","aria-live":"polite","data-quote-state":e?.state??"none",children:[jsx("span",{className:"pc-price-heading",children:t.priceHeading}),jsx("span",{className:"pc-price-total",children:r}),s?jsx("span",{className:"pc-price-note",children:s}):null]})}function Ce(n){return n.visible&&!n.settled}function ye(n){if(Ce(n))return true;let e=n.options??[],t=e.length===1?e[0]:void 0;return n.visible&&t!==void 0&&(t.priceCents===null||t.priceCents>0)}function ke(n){let{geometry:e,slots:t={},labels:o=D,className:r}=n,s=je(e),m=Math.max(s.width,s.height)/42,l=[...e.parts].sort((u,p)=>u.at[2]+u.size[2]-(p.at[2]+p.size[2])),c=u=>s.top-u;return jsxs("div",{className:["pc-sketch","pc-scope",r].filter(Boolean).join(" "),children:[jsx(B,{}),jsxs("svg",{role:"img","aria-label":o.sketchTitle,viewBox:`${s.left} 0 ${s.width} ${s.height}`,preserveAspectRatio:"xMidYMid meet",children:[jsx("title",{children:o.sketchTitle}),l.map(u=>jsx(Ve,{part:u,slot:t[u.slot],y:c},u.key)),e.dimensions.map(u=>jsx(qe,{dimension:u,unit:o.unitMm,fontSize:m,y:c},u.id))]})]})}function Ve(n$1){let{part:e,slot:t,y:o}=n$1,[r,s]=e.size,m=e.at[0],l=o(e.at[1]+s),c=t?n(t):null,u={className:"pc-sketch-part",fill:t?.color??te,fillOpacity:c?.transparent?.35:1,"data-part":e.key};if(e.type==="niche_panel"){let f=b$1(e),v=o(e.at[1]+f.y+f.height),d=`M${m} ${l}h${r}v${s}h${-r}Z`,y=f.width>0&&f.height>0?`M${m+f.x} ${v}h${f.width}v${f.height}h${-f.width}Z`:"";return jsx("path",{...u,d:d+y,fillRule:"evenodd"})}let p=e.type==="stadium_prism"?Math.min(r,s)/2:0;return jsx("rect",{...u,x:m,y:l,width:r,height:s,rx:p,ry:p})}function qe(n){let{dimension:e,unit:t,fontSize:o,y:r}=n,s=o*.5,m=`${e.label?`${e.label} `:""}${Qe(e.length)} ${t}`,l=Math.min(e.from,e.to),c=Math.max(e.from,e.to);if(e.axis==="x"){let f=r(e.at);return jsxs("g",{"data-dimension":e.id,children:[jsx("path",{className:"pc-sketch-line",d:`M${l} ${f}H${c}M${l} ${f-s}v${s*2}M${c} ${f-s}v${s*2}`}),jsx("text",{className:"pc-sketch-text",x:(l+c)/2,y:f-s*1.4,fontSize:o,children:m})]})}let u=e.at,p=r((l+c)/2);return jsxs("g",{"data-dimension":e.id,children:[jsx("path",{className:"pc-sketch-line",d:`M${u} ${r(l)}V${r(c)}M${u-s} ${r(l)}h${s*2}M${u-s} ${r(c)}h${s*2}`}),jsx("text",{className:"pc-sketch-text",x:u-s*1.4,y:p,fontSize:o,transform:`rotate(-90 ${u-s*1.4} ${p})`,children:m})]})}function Qe(n){return String(Math.round(n*10)/10)}function je(n){let e=1/0,t=-1/0,o=1/0,r=-1/0,s=(l,c,u,p)=>{e=Math.min(e,l),t=Math.max(t,c),o=Math.min(o,u),r=Math.max(r,p);};for(let l of n.parts)s(l.at[0],l.at[0]+l.size[0],l.at[1],l.at[1]+l.size[1]);for(let l of n.dimensions){let c=Math.min(l.from,l.to),u=Math.max(l.from,l.to);l.axis==="x"?s(c,u,l.at,l.at):s(l.at,l.at,c,u);}if(!Number.isFinite(e))return {left:0,top:1e3,width:1e3,height:1e3};let m=Math.max(t-e,r-o)*.08;return {left:e-m,top:r+m,width:t-e+m*2,height:r-o+m*2}}var q;function Se(){if(q!==void 0)return q;try{let n=document.createElement("canvas");q=!!(n.getContext("webgl2")??n.getContext("webgl"));}catch{q=false;}return q}function Re(n){let{children:e,placeholder:t=null,minHeight:o=280,rootMargin:r="200px",className:s}=n,m=useRef(null),[l,c]=useState(false);return useEffect(()=>{let u=m.current;if(l||!u)return;if(typeof IntersectionObserver>"u"){c(true);return}let p=new IntersectionObserver(f=>{f.some(v=>v.isIntersecting)&&(c(true),p.disconnect());},{rootMargin:r});return p.observe(u),()=>p.disconnect()},[l,r]),jsx("div",{ref:m,className:s,style:l?void 0:{minHeight:o},children:l?e:t})}var tt=lazy(()=>import('./configurator-scene-3ABIR55G.js').then(n=>({default:n.ConfiguratorScene}))),nt=()=>()=>{},rt={values:{}};function re(n){let{structure:e,value:t,tax:o$1,initialSelection:r,onChange:s,locale:m,currency:l,interactive:c=true,className:u}=n,p=useMemo(()=>({...D,...n.labels}),[n.labels]),f=i=>W({structure:e,value:t,selection:i}).configuration.selection,[v,d]=useState(()=>f(r??rt)),y=useSyncExternalStore(nt,Se,()=>null),x=useMemo(()=>U({structure:e,value:t,selection:v,tax:o$1}),[e,t,v,o$1]),{configuration:S}=x,M=x.ok?x.quote:null,a=useMemo(()=>Y(e.geometry,S.inputs,Z(S)),[e.geometry,S]),g=i=>{let b=f(i),h=U({structure:e,value:t,selection:b,tax:o$1});d(b),s?.(b,h.ok?h.quote:null);},N=a.ok?jsx(ke,{geometry:a.geometry,slots:S.slots,labels:p}):jsx("p",{className:"pc-scene-note",children:p.sketchUnavailable});return jsxs("div",{className:["pc-root","pc-scope",u].filter(Boolean).join(" "),children:[jsx(B,{}),jsxs("div",{className:"pc-visual",children:[y&&a.ok?jsx(Re,{className:"pc-scene",placeholder:jsx("p",{className:"pc-scene-note",children:p.sceneLoading}),children:jsx(o,{fallback:null,children:jsx(Suspense,{fallback:jsx("p",{className:"pc-scene-note",children:p.sceneLoading}),children:jsx("div",{role:"region","aria-label":p.sceneLabel,style:{position:"absolute",inset:0},children:jsx(tt,{geometry:a.geometry,slots:S.slots,camera:e.geometry.camera,lighting:e.scene?.lighting,edges:e.scene?.edges,cameraLabels:p,interactive:c})})})})}):null,N]}),jsx(ve,{structure:e,configuration:S,quote:M,onSelectionChange:g,labels:p,locale:m,currency:l,disabled:!c})]})}var ot=e.number().int().min(0).max(1e8),X=ot.nullable(),Ne=e.strictObject({basePriceCents:X,numbers:e.record(f,e.strictObject({min:e.number().finite(),max:e.number().finite(),default:e.number().finite()})).default({}),choices:e.record(f,e.strictObject({options:e.record(g,e.strictObject({priceCents:X})),default:g.optional()})).default({}),materials:e.record(f,e.strictObject({offered:e.array(g).max(b.materials),default:g.optional()})).default({}),toggles:e.record(f,e.strictObject({offered:e.boolean(),default:e.boolean()})).default({}),priceGroups:e.record(g,X).default({}),amounts:e.record(f,X).default({}),presets:e.array(e.strictObject({code:g,label:e.string().trim().min(1).max(80),productId:e.string().uuid().nullable(),values:e.record(f,e.number().finite())})).max(b.presets).default([])});var Q=class extends Error{constructor(t,o){super(o);this.reason=t;this.name="ConfiguratorFieldError";}};function _e(n,e){let t=n.fields[e];if(t==null)throw new Q("missing",`The product has no public configurator under "${e}". Make the field public in the object builder.`);if(typeof t=="object"&&"configurator"in t&&!("structure"in t))throw new Q("listing",`"${e}" is the listing's flag. Fetch the product itself (getProduct) to draw its configurator.`);let o=t,r=k.safeParse(o.structure),s=Ne.safeParse(o.value),m=o.tax;if(!r.success||!s.success||typeof o.structureHash!="string"||typeof o.valueHash!="string"||typeof m?.taxPercentage!="number"||typeof m.pricesIncludeTax!="boolean")throw new Q("invalid",`"${e}" does not read as a configurator. Update @solumflow-app/product-configurator.`);return {structure:r.data,value:s.data,tax:{taxPercentage:m.taxPercentage,pricesIncludeTax:m.pricesIncludeTax},structureHash:o.structureHash,valueHash:o.valueHash}}function Pe(n,e,t,o){return {attribute:n,selection:t,structureHash:e,expected:{state:o.state,totalCents:o.totalCents}}}function bn(n,e,t){let o=_e(n,e),r=U({structure:o.structure,value:o.value,selection:t,tax:o.tax});if(!r.ok)return {ok:false,issues:r.issues,selection:r.configuration.selection};let s=Y(o.structure.geometry,r.configuration.inputs,Z(r.configuration));return s.ok?{ok:true,quote:r.quote,selection:r.configuration.selection,parts:s.geometry.parts,bounds:s.geometry.bounds}:{ok:false,issues:s.issues,selection:r.configuration.selection}}var st="Aanvragen";function hn(n){let{product:e,attribute:t,onChange:o,onSubmit:r}=n,s=useMemo(()=>_e(e,t),[e,t]),[m,l]=useState(()=>{let u=n.initialSelection??{values:{}},p=U({structure:s.structure,value:s.value,selection:u,tax:s.tax});return {selection:p.configuration.selection,quote:p.ok?p.quote:null}}),c=m.quote?Pe(t,s.structureHash,m.selection,m.quote):null;return jsxs("div",{className:n.className,children:[jsx(re,{structure:s.structure,value:s.value,tax:s.tax,initialSelection:n.initialSelection,labels:n.labels,locale:n.locale,currency:n.currency,onChange:(u,p)=>{l({selection:u,quote:p}),o?.({selection:u,quote:p,payload:p?Pe(t,s.structureHash,u,p):null});}}),r?jsx("button",{type:"button",className:"pc-submit",disabled:c===null,onClick:()=>{c&&r(c);},children:n.submitLabel??st}):null]})}export{Q as ConfiguratorFieldError,D as DEFAULT_CONFIGURATOR_LABELS,hn as ProductConfigurator,bn as computeConfiguration,_e as readConfigurator,Pe as toConfigurationPayload};
105
+ `;function K(){return jsx("style",{href:"product-configurator",precedence:"default",children:mt})}function Ee(o,e){let{min:t,max:r,step:n}=e,a=s=>Math.round(s*1e6)/1e6,d=Math.round(o/n)*n;return d<t&&(d=Math.ceil(t/n)*n),d>r&&(d=Math.floor(r/n)*n),a(Math.min(r,Math.max(t,d)))}var De="_room";function ze(o){let{structure:e,configuration:t,quote:r,onSelectionChange:n,locale:a="nl-NL",currency:d="EUR",disabled:s=false,className:u}=o,c={...B,...o.labels},m=useId(),l=useRef({}),y=e.presets&&t.presets.length>0?e.presets.tab:null,g=[...e.tabs.filter(p=>p.key===y||t.parameters.some(f=>f.tab===p.key&&Ae(f))),...o.room?[{key:De,label:c.roomTab}]:[]],[b,C]=useState(g[0]?.key),L=g.find(p=>p.key===b)??g[0],M=p=>a$3(p,a,d),i=(p,f)=>{n?.({...t.selection,values:{...t.selection.values,[p]:f}});},h=p=>{let{preset:f,...v}=t.selection;n?.(p===""?v:{...v,preset:p});},P=(p,f)=>{let v=p.key==="ArrowRight"?1:p.key==="ArrowLeft"?-1:0,_=g.length-1,q=p.key==="Home"?0:p.key==="End"?_:(f+v+g.length)%g.length;if(v===0&&p.key!=="Home"&&p.key!=="End")return;p.preventDefault();let R=g[q];R&&(C(R.key),l.current[R.key]?.focus());};return jsxs("div",{className:["pc-panel","pc-scope",u].filter(Boolean).join(" "),children:[jsx(K,{}),g.length>1?jsx("div",{role:"tablist","aria-label":c.tabsLabel,className:"pc-tabs",children:g.map((p,f)=>jsx("button",{ref:v=>{l.current[p.key]=v;},type:"button",role:"tab",id:`${m}-tab-${p.key}`,"aria-selected":p.key===L?.key,"aria-controls":`${m}-panel-${p.key}`,tabIndex:p.key===L?.key?0:-1,className:"pc-tab",onClick:()=>C(p.key),onKeyDown:v=>P(v,f),children:p.label},p.key))}):null,L?jsxs("fieldset",{role:g.length>1?"tabpanel":void 0,id:`${m}-panel-${L.key}`,"aria-labelledby":g.length>1?`${m}-tab-${L.key}`:void 0,className:"pc-fields",disabled:s,children:[e.presets&&y===L.key?jsxs("div",{className:"pc-field",children:[jsx("label",{className:"pc-label",htmlFor:`${m}-preset`,children:e.presets.label}),jsxs("select",{id:`${m}-preset`,className:"pc-control",value:t.preset?.code??"",onChange:p=>h(p.target.value),children:[e.presets.required?null:jsx("option",{value:"",children:c.presetNone}),t.presets.map(p=>jsx("option",{value:p.code,children:p.label},p.code))]})]}):null,o.room&&L.key===De?jsx(yt,{id:m,room:o.room,labels:c}):null,t.parameters.filter(p=>Ae(p)&&p.tab===L.key).map(p=>Ve(p)?jsx(vt,{id:`${m}-${p.key}`,parameter:p,labels:c,money:M,onChange:f=>i(p.key,f)},p.key):jsx(kt,{parameter:p,labels:c,money:M},p.key))]}):null,jsxs("div",{className:"pc-panel-foot",children:[jsx(xt,{quote:r,labels:c,money:M}),o.footer?jsx("div",{className:"pc-actions",children:o.footer}):null]})]})}function yt(o){let{id:e,room:t,labels:r}=o,n={wall:t.wall.code,floor:t.floor.code},a=(d,s)=>{let{options:u,code:c}=t[d],m=u.find(l=>l.code===c);return jsxs("fieldset",{className:"pc-field","data-room":d,children:[jsxs("legend",{className:"pc-label",children:[s,m?jsx("small",{children:m.label}):null]}),jsx("div",{className:"pc-swatches",children:u.map(l=>jsxs("label",{className:"pc-choice",title:l.label,children:[jsx("input",{type:"radio",name:`${e}-room-${d}`,value:l.code,checked:l.code===c,onChange:()=>t.onChange({...n,[d]:l.code})}),jsx("span",{className:"pc-swatch",style:{backgroundColor:l.color},children:jsx("span",{className:"pc-hidden",children:l.label})})]},l.code))})]})};return jsxs(Fragment,{children:[a("wall",r.roomWall),a("floor",r.roomFloor)]})}function vt(o){let{id:e,parameter:t,labels:r,money:n,onChange:a}=o;if(t.kind==="number"){let s={min:t.min??0,max:t.max??0,step:t.step??1},u=t.value,c=t.unit==="count"?r.unitCount:r.unitMm,m=l=>{Number.isFinite(l)&&a(Ee(l,s));};return jsxs("div",{className:"pc-field",children:[jsxs("label",{className:"pc-label",htmlFor:`${e}-range`,children:[t.label,jsxs("small",{children:[u," ",c]})]}),jsxs("div",{className:"pc-number",children:[jsx("input",{id:`${e}-range`,className:"pc-control",type:"range",min:s.min,max:s.max,step:s.step,value:u,disabled:t.fixed,onChange:l=>m(l.target.valueAsNumber)}),jsxs("span",{children:[jsx("label",{className:"pc-hidden",htmlFor:`${e}-number`,children:`${t.label} (${c})`}),jsx("input",{id:`${e}-number`,className:"pc-control",type:"number",inputMode:"numeric",min:s.min,max:s.max,step:s.step,defaultValue:u,readOnly:t.fixed,onBlur:l=>m(l.target.valueAsNumber),onKeyDown:l=>{l.key==="Enter"&&m(l.currentTarget.valueAsNumber);}},u)]})]})]})}if(t.kind==="toggle")return jsx("div",{className:"pc-field",children:jsxs("label",{className:"pc-switch",htmlFor:e,children:[jsx("input",{id:e,type:"checkbox",checked:t.value===true,onChange:s=>a(s.target.checked)}),jsx("span",{className:"pc-label",children:t.label})]})});let d=t.options??[];if(t.kind==="material"){let s=d.find(u=>u.code===t.value);return jsxs("fieldset",{className:"pc-field",children:[jsxs("legend",{className:"pc-label",children:[t.label,s?jsx("small",{children:s.label}):null]}),jsx("div",{className:"pc-swatches",children:d.map(u=>jsxs("label",{className:"pc-choice",title:u.label,children:[jsx("input",{type:"radio",name:e,value:u.code,checked:u.code===t.value,onChange:()=>a(u.code)}),jsx("span",{className:"pc-swatch",style:{backgroundColor:u.material?.color,backgroundImage:u.material?.texture?`url("${u.material.texture}")`:void 0},children:jsx("span",{className:"pc-hidden",children:u.label})})]},u.code))})]})}return jsxs("fieldset",{className:"pc-field",children:[jsx("legend",{className:"pc-label",children:t.label}),jsx("div",{className:"pc-choices",children:d.map(s=>jsxs("label",{className:"pc-choice",children:[jsx("input",{type:"radio",name:e,value:s.code,checked:s.code===t.value,onChange:()=>a(s.code)}),jsxs("span",{children:[s.label,jsx("small",{children:Fe(s,r,n)})]})]},s.code))})]})}function kt(o){let{parameter:e,labels:t,money:r}=o,n=e.options?.[0];return n?jsx("div",{className:"pc-field","data-pinned":e.key,children:jsxs("span",{className:"pc-label",children:[e.label,jsxs("small",{children:[n.label," \xB7 ",Fe(n,t,r)]})]})}):null}function Fe(o,e,t){return o.priceCents===null?e.optionOnRequest:o.priceCents>0?`${e.surchargePrefix} ${t(o.priceCents)}`:""}function xt(o){let{quote:e,labels:t,money:r}=o,n,a=null;return e?e.state==="open"||e.totalCents===null?n=t.priceOnRequest:e.state==="partial"?(n=`${t.priceFrom} ${r(e.totalCents)}`,a=`${t.priceInPartOnRequest}, ${t.priceIncludingTax}`):(n=r(e.totalCents),a=t.priceIncludingTax):n=t.priceUnavailable,jsxs("div",{className:"pc-price","aria-live":"polite","data-quote-state":e?.state??"none",children:[jsx("span",{className:"pc-price-heading",children:t.priceHeading}),jsx("span",{className:"pc-price-total",children:n}),a?jsx("span",{className:"pc-price-note",children:a}):null]})}function Ve(o){return o.visible&&!o.settled}function Ae(o){if(Ve(o))return true;let e=o.options??[],t=e.length===1?e[0]:void 0;return o.visible&&t!==void 0&&(t.priceCents===null||t.priceCents>0)}function qe(o){let{geometry:e,slots:t={},labels:r=B,className:n}=o,a=Nt(e),d=Math.max(a.width,a.height)/42,s=[...e.parts].sort((c,m)=>c.at[2]+c.size[2]-(m.at[2]+m.size[2])),u=c=>a.top-c;return jsxs("div",{className:["pc-sketch","pc-scope",n].filter(Boolean).join(" "),children:[jsx(K,{}),jsxs("svg",{role:"img","aria-label":r.sketchTitle,viewBox:`${a.left} 0 ${a.width} ${a.height}`,preserveAspectRatio:"xMidYMid meet",children:[jsx("title",{children:r.sketchTitle}),s.map(c=>jsx(wt,{part:c,slot:t[c.slot],y:u},c.key)),e.dimensions.map(c=>jsx(Rt,{dimension:c,unit:r.unitMm,fontSize:d,y:u},c.id))]})]})}function wt(o$1){let{part:e,slot:t,y:r}=o$1,[n,a]=e.size,d=e.at[0],s=r(e.at[1]+a),u=t?o(t):null,c={className:"pc-sketch-part",fill:t?.color??ue,fillOpacity:u?.transparent?.35:1,"data-part":e.key};if(e.type==="niche_panel"){let l=a$2(e),y=r(e.at[1]+l.y+l.height),g=`M${d} ${s}h${n}v${a}h${-n}Z`,b=l.width>0&&l.height>0?`M${d+l.x} ${y}h${l.width}v${l.height}h${-l.width}Z`:"";return jsx("path",{...c,d:g+b,fillRule:"evenodd"})}let m=e.type==="stadium_prism"?Math.min(n,a)/2:0;return jsx("rect",{...c,x:d,y:s,width:n,height:a,rx:m,ry:m})}function Rt(o){let{dimension:e,unit:t,fontSize:r,y:n}=o,a=r*.5,d=`${e.label?`${e.label} `:""}${St(e.length)} ${t}`,s=Math.min(e.from,e.to),u=Math.max(e.from,e.to);if(e.axis==="x"){let l=n(e.at);return jsxs("g",{"data-dimension":e.id,children:[jsx("path",{className:"pc-sketch-line",d:`M${s} ${l}H${u}M${s} ${l-a}v${a*2}M${u} ${l-a}v${a*2}`}),jsx("text",{className:"pc-sketch-text",x:(s+u)/2,y:l-a*1.4,fontSize:r,children:d})]})}let c=e.at,m=n((s+u)/2);return jsxs("g",{"data-dimension":e.id,children:[jsx("path",{className:"pc-sketch-line",d:`M${c} ${n(s)}V${n(u)}M${c-a} ${n(s)}h${a*2}M${c-a} ${n(u)}h${a*2}`}),jsx("text",{className:"pc-sketch-text",x:c-a*1.4,y:m,fontSize:r,transform:`rotate(-90 ${c-a*1.4} ${m})`,children:d})]})}function St(o){return String(Math.round(o*10)/10)}function Nt(o){let e=1/0,t=-1/0,r=1/0,n=-1/0,a=(s,u,c,m)=>{e=Math.min(e,s),t=Math.max(t,u),r=Math.min(r,c),n=Math.max(n,m);};for(let s of o.parts)a(s.at[0],s.at[0]+s.size[0],s.at[1],s.at[1]+s.size[1]);for(let s of o.dimensions){let u=Math.min(s.from,s.to),c=Math.max(s.from,s.to);s.axis==="x"?a(u,c,s.at,s.at):a(s.at,s.at,u,c);}if(!Number.isFinite(e))return {left:0,top:1e3,width:1e3,height:1e3};let d=Math.max(t-e,n-r)*.08;return {left:e-d,top:n+d,width:t-e+d*2,height:n-r+d*2}}function Ge(o,e){let[t,r]=useState({entry:null,id:0,end:"return"}),n=useRef(void 0);useEffect(()=>()=>clearTimeout(n.current),[]);let a=(u$1,c)=>{let m=v(o,u$1.values,c.values);m&&(r(l=>({entry:m,id:l.id+1,end:"return"})),clearTimeout(n.current),n.current=setTimeout(()=>r(l=>({...l,entry:null,end:"return"})),u));},d=()=>{t.entry&&(clearTimeout(n.current),r(u=>({...u,entry:null,end:"stay"})));};return {scene:useMemo(()=>t.entry&&e?w(t.entry,e,t.id):null,[t.entry,t.id,e]),end:t.end,start:a,stop:d}}var Y;function Be(){if(Y!==void 0)return Y;try{let o=document.createElement("canvas");Y=!!(o.getContext("webgl2")??o.getContext("webgl"));}catch{Y=false;}return Y}function Ue(o){let{children:e,placeholder:t=null,minHeight:r=280,rootMargin:n="200px",className:a}=o,d=useRef(null),[s,u]=useState(false);return useEffect(()=>{let c=d.current;if(s||!c)return;if(typeof IntersectionObserver>"u"){u(true);return}let m=new IntersectionObserver(l=>{l.some(y=>y.isIntersecting)&&(u(true),m.disconnect());},{rootMargin:n});return m.observe(c),()=>m.disconnect()},[s,n]),jsx("div",{ref:d,className:a,style:s?void 0:{minHeight:r},children:s?e:t})}var Vt=lazy(()=>import('./configurator-scene-RAWYHWX5.js').then(o=>({default:o.ConfiguratorScene}))),qt=()=>()=>{},Gt={values:{}};function me(o){let{structure:e,value:t,tax:r,initialSelection:n,onChange:a,locale:d,currency:s,interactive:u=true,layout:c="inline",className:m}=o,l=c==="fill",y=o.wheelZoom??(l?"modifier":"always"),g=!l&&o.views===void 0,b=o.views??(l?["3d","sketch"]:["3d"]),[C,L]=useState(b[0]??"3d"),[M,i]=useState(false),[h,P]=useState(()=>o.initialView??{}),p=e.scene?.room,f=p?j(p,h):null,v=useRef(null),[_,q]=useState(false),R=useMemo(()=>({...B,...o.labels}),[o.labels]),Q=z=>oe({structure:e,value:t,selection:z}).configuration.selection,[G,w]=useState(()=>Q(n??Gt)),x=useSyncExternalStore(qt,Be,()=>null);useLayoutEffect(()=>{l&&v.current&&v.current.clientHeight===0&&typeof process<"u";},[l]);let S=useMemo(()=>Z({structure:e,value:t,selection:G,tax:r}),[e,t,G,r]),{configuration:$}=S,D=S.ok?S.quote:null,E=useMemo(()=>re(e.geometry,$.inputs,ne($)),[e.geometry,$]),A=Ge(e.focus,E.ok?E.geometry.parts:null),Ze=z=>{let te=Q(z),be=Z({structure:e,value:t,selection:te,tax:r});w(te),A.start(G,te),a?.(te,be.ok?be.quote:null,f?.look??null);},We=z=>{P(z),a?.(G,D,p?j(p,z).look:null);},Ke=E.ok?jsx(qe,{geometry:E.geometry,slots:$.slots,labels:R}):jsx("p",{className:"pc-scene-note",children:R.sketchUnavailable}),ee=x===true&&E.ok&&b.includes("3d"),ge=ee&&!g&&b.length>1,se=ee?ge?C:"3d":"sketch",Je=g||se==="sketch"||!ee,he=ee?jsx(Ue,{className:"pc-scene",placeholder:jsx("p",{className:"pc-scene-note",children:R.sceneLoading}),children:jsx(a$1,{fallback:null,children:jsx(Suspense,{fallback:jsx("p",{className:"pc-scene-note",children:R.sceneLoading}),children:jsx("div",{role:"region","aria-label":R.sceneLabel,style:{position:"absolute",inset:0},children:jsx(Vt,{geometry:E.geometry,slots:$.slots,camera:e.geometry.camera,lighting:e.scene?.lighting,edges:e.scene?.edges,cameraLabels:R,interactive:u,wheelZoom:y,wheelZoomHint:R.wheelZoomHint,focus:A.scene,focusEnd:A.end,openAll:o.openAll,onInteract:A.stop,night:_||(A.scene?.night??false),nightToggle:{onToggle:()=>q(z=>!z),dim:R.nightDim,light:R.nightLight},room:f?{margin:f.margin,depth:f.depth,wallColor:f.wall.option.color,floorColor:f.floor.option.color}:void 0})})})})}):null,Ye=typeof o.actions=="function"?o.actions({selection:G,quote:D}):o.actions,{actions:Xe,stepView:ce}=$e({checkout:o.checkout,selection:G,quote:D,labels:R,locale:d??"nl-NL",currency:s??"EUR",siteActions:Ye});return jsxs("div",{ref:v,className:["pc-root","pc-scope",m].filter(Boolean).join(" "),"data-layout":c,"data-panel":M?"open":void 0,children:[jsx(K,{}),jsxs("div",{className:"pc-visual",children:[ge?jsx(Bt,{views:b,view:se,labels:R,onChoose:L}):null,he?jsx("div",{className:"pc-view",hidden:se!=="3d"?true:void 0,children:he}):null,Je?jsx("div",{className:"pc-view pc-view-sketch",children:Ke}):null]}),jsxs("div",{className:"pc-side",children:[l?jsx("button",{type:"button",className:"pc-panel-toggle","aria-expanded":M,onClick:()=>i(z=>!z),children:M?R.panelCollapse:R.panelExpand}):null,ce?jsx("div",{className:"pc-panel pc-scope",children:ce}):null,jsx(ze,{className:ce?"pc-panel-away":void 0,structure:e,configuration:$,quote:D,onSelectionChange:Ze,labels:R,locale:d,currency:s,disabled:!u,footer:Xe,room:f?{wall:{options:f.wall.options,code:f.look.wall},floor:{options:f.floor.options,code:f.look.floor},onChange:We}:void 0})]})]})}function Bt(o){let{views:e,view:t,labels:r,onChoose:n}=o;return jsx("div",{role:"tablist","aria-label":r.viewsLabel,className:"pc-views",children:e.map(a=>jsx("button",{type:"button",role:"tab","aria-selected":a===t,className:"pc-views-tab","data-test":`configurator-view-${a}`,onClick:()=>n(a),children:a==="3d"?r.views3d:r.viewsSketch},a))})}var Ut=e.number().int().min(0).max(1e8),ie=Ut.nullable(),je=e.strictObject({basePriceCents:ie,numbers:e.record(f,e.strictObject({min:e.number().finite(),max:e.number().finite(),default:e.number().finite()})).default({}),choices:e.record(f,e.strictObject({options:e.record(g,e.strictObject({priceCents:ie})),default:g.optional()})).default({}),materials:e.record(f,e.strictObject({offered:e.array(g).max(b.materials),default:g.optional()})).default({}),toggles:e.record(f,e.strictObject({offered:e.boolean(),default:e.boolean()})).default({}),priceGroups:e.record(g,ie).default({}),amounts:e.record(f,ie).default({}),presets:e.array(e.strictObject({code:g,label:e.string().trim().min(1).max(80),productId:e.string().uuid().nullable(),values:e.record(f,e.number().finite())})).max(b.presets).default([])});var J=class extends Error{constructor(t,r){super(r);this.reason=t;this.name="ConfiguratorFieldError";}};function Qe(o,e){let t=o.fields[e];if(t==null)throw new J("missing",`The product has no public configurator under "${e}". Make the field public in the object builder.`);if(typeof t=="object"&&"configurator"in t&&!("structure"in t))throw new J("listing",`"${e}" is the listing's flag. Fetch the product itself (getProduct) to draw its configurator.`);let r=t,n=l.safeParse(r.structure),a=je.safeParse(r.value),d=r.tax;if(!n.success||!a.success||typeof r.structureHash!="string"||typeof r.valueHash!="string"||typeof d?.taxPercentage!="number"||typeof d.pricesIncludeTax!="boolean")throw new J("invalid",`"${e}" does not read as a configurator. Update @solumflow-app/product-configurator.`);return {structure:n.data,value:a.data,tax:{taxPercentage:d.taxPercentage,pricesIncludeTax:d.pricesIncludeTax},structureHash:r.structureHash,valueHash:r.valueHash}}function He(o,e,t,r){return {attribute:o,selection:t,structureHash:e,expected:{state:r.state,totalCents:r.totalCents}}}function pn(o,e,t){let r=Qe(o,e),n=Z({structure:r.structure,value:r.value,selection:t,tax:r.tax});if(!n.ok)return {ok:false,issues:n.issues,selection:n.configuration.selection};let a=re(r.structure.geometry,n.configuration.inputs,ne(n.configuration));return a.ok?{ok:true,quote:n.quote,selection:n.configuration.selection,parts:a.geometry.parts,bounds:a.geometry.bounds}:{ok:false,issues:a.issues,selection:n.configuration.selection}}var Qt="Aanvragen";function mn(o){let{product:e,attribute:t,onChange:r,onSubmit:n}=o,a=useMemo(()=>Qe(e,t),[e,t]),[d,s]=useState(()=>{let l=o.initialSelection??{values:{}},y=Z({structure:a.structure,value:a.value,selection:l,tax:a.tax});return {selection:y.configuration.selection,quote:y.ok?y.quote:null}}),u=d.quote?He(t,a.structureHash,d.selection,d.quote):null,c={payload:u,priced:d.quote?.state==="priced"},m=o.actions!==void 0?typeof o.actions=="function"?o.actions(c):o.actions:n?jsx("button",{type:"button",className:"pc-submit",disabled:u===null,onClick:()=>{u&&n(u);},children:o.submitLabel??Qt}):null;return jsx("div",{className:o.className,style:Wt(o.layout),children:jsx(me,{structure:a.structure,value:a.value,tax:a.tax,initialSelection:o.initialSelection,labels:o.labels,locale:o.locale,currency:o.currency,layout:o.layout,views:o.views,wheelZoom:o.wheelZoom,initialView:o.initialView,checkout:Zt(o,a.structureHash),actions:m,onChange:(l,y,g)=>{s({selection:l,quote:y}),r?.({selection:l,quote:y,view:g,payload:y?He(t,a.structureHash,l,y):null});}})})}function Zt(o,e){if(o.checkout){if(!o.product.id)throw new J("invalid","checkout needs the product as getProduct returns it, with its id.");return {...o.checkout,productId:o.product.id,attribute:o.attribute,structureHash:e}}}function Wt(o){return o==="fill"?{height:"100%"}:void 0}export{J as ConfiguratorFieldError,B as DEFAULT_CONFIGURATOR_LABELS,mn as ProductConfigurator,pn as computeConfiguration,Qe as readConfigurator,He as toConfigurationPayload};
@@ -0,0 +1 @@
1
+ import {b,a,c,e}from'./chunk-VQ7GFV6B.js';import'./chunk-YLNPPHX4.js';import'./chunk-GA7MFMMF.js';import {useRef,useMemo,useLayoutEffect}from'react';import {useLoader,useThree,useFrame}from'@react-three/fiber';import*as l from'three';import {MeshoptDecoder}from'three/examples/jsm/libs/meshopt_decoder.module.js';import {GLTFLoader}from'three/examples/jsm/loaders/GLTFLoader.js';import {jsx}from'react/jsx-runtime';function G(s){return s===1?"stretch":s===2?"actual":"contain"}function P(s){let{frame:n,bounds:o,fit:a}=s;if(a==="actual")return {scale:[1,1,1],centre:[(o.min[0]+o.max[0])/2,o.min[1]+n[1]/2,o.max[2]-n[2]/2]};let m=[0,1,2].map(e=>o.max[e]-o.min[e]),p=[0,1,2].map(e=>{let d=m[e],u=n[e];return d>0&&u>0?u/d:null}),b=p.filter(e=>e!==null),c=b.length>0?Math.min(...b):1,i=[0,1,2].map(e=>a==="stretch"?p[e]??c:c),f=[0,1,2].map(e=>(o.min[e]+o.max[e])/2);return {scale:i,centre:f}}var J=.05,K=1e-4;function Q(s){s.setMeshoptDecoder(MeshoptDecoder);}function U(s){let{part:n,material:o}=s,a$1=useLoader(GLTFLoader,n.model,Q),m=useRef(null),p=useRef(new l.Vector3),b$1=useRef(new l.Vector3),c$1=useRef(false),i=useThree(r=>r.invalidate),f=n.params.paint===1,e$1=useMemo(()=>{let r=new l.Box3().setFromObject(a$1.scene);return {min:r.min.toArray(),max:r.max.toArray()}},[a$1.scene]),d=useMemo(()=>{let r=a$1.scene.clone(true);return r.traverse(F=>{let t=F;t.isMesh&&(f?t.material=o:b(t.material),t.castShadow=a(t.material),t.receiveShadow=true);}),r},[a$1.scene,f,o]),u=P({frame:[c(n.size[0]),c(n.size[1]),c(n.size[2])],bounds:e$1,fit:G(n.params.fit)}),[M,T,x]=e(n),[y,w,g]=u.scale,[_,j,N]=u.centre;return useLayoutEffect(()=>{let r=m.current;r&&!c$1.current&&(r.position.set(M,T,x),r.scale.set(y,w,g),c$1.current=true),i();},[M,T,x,y,w,g,i]),useFrame((r,F)=>{let t=m.current;if(!t)return;let H=1-Math.exp(-F/J),R=p.current.set(M,T,x),S=b$1.current.set(y,w,g),L=Math.max(t.position.distanceTo(R),t.scale.distanceTo(S));if(L<K){L>0&&(t.position.copy(R),t.scale.copy(S));return}t.position.lerp(R,H),t.scale.lerp(S,H),i();}),jsx("group",{ref:m,children:jsx("primitive",{object:d,position:[-_,-j,-N]})})}export{U as default};
@@ -0,0 +1 @@
1
+ import {g,a,c,d,f,e,i}from'./chunk-Y4YXTBBE.js';import'./chunk-GA7MFMMF.js';import {useId,useRef,useState}from'react';import {jsxs,jsx}from'react/jsx-runtime';function L(s){let{checkout:c$1,labels:e$1}=s,o=useId(),m=useRef(g()),[n,d$1]=useState({busy:false,error:null,sent:false}),y=async p=>{p.preventDefault();let C=new FormData(p.currentTarget),a=N=>String(C.get(N)??"").trim();d$1({busy:true,error:null,sent:false});let r=await f(c$1.endpoint,{action:"request",productId:c$1.productId,configuration:e(c$1,s.selection,s.quote),contact:{email:a("email"),firstName:a("firstName")||void 0,lastName:a("lastName")||void 0,phone:a("phone")||void 0},message:a("message")||e$1.checkoutRequest,postalCode:a("postalCode")||void 0,idempotencyKey:m.current});"error"in r&&r.error!=="unavailable"&&(m.current=g()),d$1("action"in r&&r.action==="request"?{busy:false,error:null,sent:true}:{busy:false,error:i("error"in r?r.error:"",e$1),sent:false});};return n.sent?jsxs("div",{className:"pc-checkout",role:"status","data-test":"configurator-request-sent",children:[jsx("h3",{className:"pc-checkout-title",children:e$1.checkoutRequestSent}),jsx("p",{className:"pc-price-note",children:e$1.checkoutRequestSentNote})]}):jsxs("div",{className:"pc-checkout","data-test":"configurator-request",children:[jsxs("button",{type:"button",className:"pc-checkout-back",onClick:s.onBack,children:["\u2190 ",e$1.checkoutBack]}),jsxs("form",{className:"pc-checkout-form",onSubmit:y,children:[jsx("h3",{className:"pc-checkout-title",children:e$1.checkoutDetails}),jsx(a,{id:o,labels:e$1,nameRequired:false}),jsx(c,{id:`${o}-postal`,label:e$1.checkoutPostalCode,children:jsx("input",{id:`${o}-postal`,name:"postalCode",className:"pc-control",autoComplete:"postal-code",maxLength:20})}),jsx(c,{id:`${o}-message`,label:e$1.checkoutMessage,children:jsx("textarea",{id:`${o}-message`,name:"message",className:"pc-control",rows:4,maxLength:5e3})}),jsx(d,{id:o,labels:e$1,privacyUrl:c$1.privacyUrl}),n.error?jsx("p",{className:"pc-checkout-error",role:"alert",children:n.error}):null,jsx("button",{type:"submit",className:"pc-checkout-primary",disabled:n.busy,"data-test":"configurator-send-request",children:e$1.checkoutSend})]})]})}export{L as RequestStep};
@@ -0,0 +1 @@
1
+ import'./chunk-GA7MFMMF.js';import {useMemo,useState}from'react';import {Elements,useStripe,useElements,PaymentElement}from'@stripe/react-stripe-js';import {loadStripe}from'@stripe/stripe-js';import {jsx,jsxs}from'react/jsx-runtime';function f(e){let{publishableKey:t,stripeAccount:r,clientSecret:n}=e,s=useMemo(()=>loadStripe(t,{stripeAccount:r}),[t,r]);return jsx(Elements,{stripe:s,options:{clientSecret:n},children:jsx(b,{returnUrl:e.returnUrl,payLabel:e.payLabel,onPaid:e.onPaid})})}function b(e){let t=useStripe(),r=useElements(),[n,s]=useState({paying:false,message:null});return jsxs("form",{className:"pc-checkout-pay",onSubmit:async l=>{if(l.preventDefault(),!t||!r)return;s({paying:true,message:null});let i=await t.confirmPayment({elements:r,confirmParams:{return_url:e.returnUrl},redirect:"if_required"});if(i.error){s({paying:false,message:i.error.message??null});return}e.onPaid();},children:[jsx(PaymentElement,{}),n.message?jsx("p",{className:"pc-checkout-error",role:"alert",children:n.message}):null,jsx("button",{type:"submit",className:"pc-checkout-primary",disabled:!t||n.paying,"data-test":"configurator-pay",children:e.payLabel})]})}export{f as default};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@solumflow-app/product-configurator",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Show a product's 3D configurator on your own website and send what a visitor put together back as a request or an order.",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -25,6 +25,8 @@
25
25
  "@kit/tsconfig": "0.1.0",
26
26
  "@react-three/drei": "10.7.9",
27
27
  "@react-three/fiber": "9.8.1",
28
+ "@stripe/react-stripe-js": "6.8.2",
29
+ "@stripe/stripe-js": "9.15.0",
28
30
  "@types/react": "19.2.18",
29
31
  "@types/react-dom": "19.2.5",
30
32
  "@types/three": "0.186.0",
@@ -39,10 +41,20 @@
39
41
  "peerDependencies": {
40
42
  "@react-three/drei": ">=10 <11",
41
43
  "@react-three/fiber": ">=9 <10",
44
+ "@stripe/react-stripe-js": ">=3 <7",
45
+ "@stripe/stripe-js": ">=5 <10",
42
46
  "react": ">=19 <19.4",
43
47
  "react-dom": ">=19 <19.4",
44
48
  "three": ">=0.163"
45
49
  },
50
+ "peerDependenciesMeta": {
51
+ "@stripe/react-stripe-js": {
52
+ "optional": true
53
+ },
54
+ "@stripe/stripe-js": {
55
+ "optional": true
56
+ }
57
+ },
46
58
  "engines": {
47
59
  "node": ">=20"
48
60
  },
@@ -1 +0,0 @@
1
- import {b as b$1}from'./chunk-RNTBO6KY.js';import*as d from'three';import {RoundedBoxGeometry}from'three/examples/jsm/geometries/RoundedBoxGeometry.js';var B=1/1e3,f=32;function r(e){return e*B}function _(e){e.computeBoundingBox();let t=e.boundingBox?.getCenter(new d.Vector3);return t&&e.translate(-t.x,-t.y,-t.z),e.computeBoundingBox(),e}function I(e){let t=e.getAttribute("position"),o=e.getAttribute("normal");if(!t||!o)return e;let a=new Float32Array(t.count*2);for(let s=0;s<t.count;s+=1){let m=Math.abs(o.getX(s)),i=Math.abs(o.getY(s)),n=Math.abs(o.getZ(s));m>=i&&m>=n?(a[s*2]=t.getZ(s),a[s*2+1]=t.getY(s)):i>=n?(a[s*2]=t.getX(s),a[s*2+1]=t.getZ(s)):(a[s*2]=t.getX(s),a[s*2+1]=t.getY(s));}return e.setAttribute("uv",new d.BufferAttribute(a,2)),e}function p(e){return I(_(e))}var g=3;function c(e,t=0){let o=Math.min(t,e/4);return o<=0?{depth:e,bevelEnabled:false,curveSegments:f,steps:1}:{depth:e-2*o,bevelEnabled:true,bevelThickness:o,bevelSize:o,bevelOffset:-o,bevelSegments:g,curveSegments:f,steps:1}}function Y(e){return (Array.isArray(e)?e:[e]).every(o=>!o.transparent&&o.toneMapped)}function Z(e){for(let t of Array.isArray(e)?e:[e]){let o=t.emissive;o&&(o.r>0||o.g>0||o.b>0)&&(t.toneMapped=false);}}function O(e){let[t,,o]=e.size,a=Math.max(0,Math.min(e.params.thickness??0,t,o));return {width:t,depth:o,thickness:a,mirrored:(e.params.mirror??0)>=.5}}function A(e){let{width:t,depth:o,thickness:a,mirrored:s}=O(e),m=[];for(let i=0;i<=f;i+=1){let n=i/f*(Math.PI/2);m.push([t*Math.cos(n),o*Math.sin(n)]);}for(let i=f;i>=0;i-=1){let n=i/f*(Math.PI/2);m.push([(t-a)*Math.cos(n),(o-a)*Math.sin(n)]);}return m.map(([i,n])=>[s?t-i:i,n])}function M(e,t=0){let[,o]=e.size,a=new d.Shape(A(e).map(([m,i])=>new d.Vector2(r(m),r(i)))),s=new d.ExtrudeGeometry(a,c(r(o),r(t)));return s.rotateX(Math.PI/2),p(s)}function G(e,t=0){let[o,a,s]=e.size;return t<=0?p(new d.BoxGeometry(r(o),r(a),r(s))):p(new RoundedBoxGeometry(r(o),r(a),r(s),g,r(t)))}var k=5;function b(e,t){if(t==="sharp"||e.type==="led_strip"||e.type==="model")return 0;let o=Math.min(...e.size,...D(e));return Math.max(0,Math.min(k,o/4))}function D(e){if(e.type==="arc_panel")return [e.params.thickness??0];if(e.type==="niche_panel"){let t=b$1(e);return t.width<=0||t.height<=0?[]:[t.x,t.y,e.size[0]-t.x-t.width,e.size[1]-t.y-t.height]}return []}function H(e){let[t,o,a]=e.size;return p(new d.BoxGeometry(r(t),r(o),r(a)))}function S(e,t=0){let[o,a,s]=e.size,m=b$1(e),i=new d.Shape;if(i.moveTo(0,0),i.lineTo(r(o),0),i.lineTo(r(o),r(a)),i.lineTo(0,r(a)),i.closePath(),m.width>0&&m.height>0){let n=new d.Path;n.moveTo(r(m.x),r(m.y)),n.lineTo(r(m.x+m.width),r(m.y)),n.lineTo(r(m.x+m.width),r(m.y+m.height)),n.lineTo(r(m.x),r(m.y+m.height)),n.closePath(),i.holes.push(n);}return p(new d.ExtrudeGeometry(i,c(r(s),r(t))))}function N(e){let[,t,o]=e.size,a=Math.max(0,Math.min(e.params.radius??0,t,o));return {depth:o,height:t,radius:a}}function v(e,t=0){let[o]=e.size,{depth:a,height:s,radius:m}=N(e),i=r(a),n=r(s),h=r(m),u=new d.Shape;u.moveTo(0,0),u.lineTo(i,0),u.lineTo(i,n-h),h>0&&u.absarc(i-h,n-h,h,0,Math.PI/2,false),u.lineTo(0,n),u.closePath();let P=new d.ExtrudeGeometry(u,c(r(o),r(t)));return P.rotateY(-Math.PI/2),p(P)}function U(e){let[t,o]=e.size;return Math.min(t,o)/2}function z(e,t=0){let[o,a,s]=e.size,m=r(o),i=r(a),n=r(U(e)),h=new d.Shape;return h.moveTo(n,0),h.lineTo(m-n,0),h.absarc(m-n,n,n,-Math.PI/2,0,false),h.lineTo(m,i-n),h.absarc(m-n,i-n,n,0,Math.PI/2,false),h.lineTo(n,i),h.absarc(n,i-n,n,Math.PI/2,Math.PI,false),h.lineTo(0,n),h.absarc(n,n,n,Math.PI,3*Math.PI/2,false),p(new d.ExtrudeGeometry(h,c(r(s),r(t))))}var V={box:G,rounded_top_box:v,stadium_prism:z,arc_panel:M,led_strip:H,niche_panel:S,model:e=>G(e)};function ye(e,t){return V[e.type](e,b(e,t))}function le(e){return [r(e.at[0]+e.size[0]/2),r(e.at[1]+e.size[1]/2),r(e.at[2]+e.size[2]/2)]}export{B as a,r as b,Y as c,Z as d,ye as e,le as f};
@@ -1 +0,0 @@
1
- var n=Object.defineProperty;var m=(h,t)=>{for(var e in t)n(h,e,{get:t[e],enumerable:true});};function o(h){let[t,e]=h.size,a=Math.min(Math.max(h.params.niche_x??0,0),t),i=Math.min(Math.max(h.params.niche_y??0,0),e);return {x:a,y:i,width:Math.min(Math.max(h.params.niche_width??0,0),t-a),height:Math.min(Math.max(h.params.niche_height??0,0),e-i)}}export{m as a,o as b};
@@ -1 +0,0 @@
1
- import {o,j,n,m}from'./chunk-ATEH2U7F.js';import {f,e,c,a}from'./chunk-QLPSL2DY.js';import'./chunk-RNTBO6KY.js';import {lazy,useState,useRef,useLayoutEffect,Suspense,useMemo,useEffect}from'react';import {ContactShadows,OrbitControls}from'@react-three/drei';import {Canvas,useThree,useFrame}from'@react-three/fiber';import*as v from'three';import {jsxs,jsx,Fragment}from'react/jsx-runtime';import {RoomEnvironment}from'three/examples/jsm/environments/RoomEnvironment.js';function B(r){let{handle:e,labels:t}=r,o=(n,a,i,c)=>jsx("button",{type:"button",className:"pc-camera-button",style:{gridArea:c},"aria-label":n,title:n,"data-test":`configurator-camera-${c}`,onClick:()=>{e.current&&i(e.current);},children:jsx("span",{"aria-hidden":"true",children:a})});return jsxs("div",{className:"pc-camera",role:"group","aria-label":t.cameraControls,children:[jsxs("div",{className:"pc-camera-pad",children:[o(t.cameraUp,"\u2191",n=>n.pan(0,1),"up"),o(t.cameraLeft,"\u2190",n=>n.pan(-1,0),"left"),o(t.cameraReset,"\u27F2",n=>n.reset(),"reset"),o(t.cameraRight,"\u2192",n=>n.pan(1,0),"right"),o(t.cameraDown,"\u2193",n=>n.pan(0,-1),"down")]}),jsxs("div",{className:"pc-camera-zoom",children:[o(t.cameraZoomIn,"+",n=>n.zoom(1),"in"),o(t.cameraZoomOut,"\u2212",n=>n.zoom(-1),"out")]})]})}function U(r,e){let o={ArrowLeft:()=>e.pan(-1,0),ArrowRight:()=>e.pan(1,0),ArrowUp:()=>e.pan(0,1),ArrowDown:()=>e.pan(0,-1),"+":()=>e.zoom(1),"=":()=>e.zoom(1),"-":()=>e.zoom(-1),0:()=>e.reset()}[r];return o?.(),o!==void 0}var O=35,se=1.5,R=Math.PI/180;function x(r){let{bounds:e,azimuth:t=0,elevation:o=10,aspect:n=se}=r,a$1=g=>(e.min[g]+e.max[g])/2*a,i=g=>(e.max[g]-e.min[g])*a,c=[a$1(0),a$1(1),a$1(2)],s=Math.max(Math.hypot(i(0),i(1),i(2))/2,.1),f=O*R/2,l=Math.atan(Math.tan(f)*n),m=s/Math.sin(Math.min(f,l)),h=[c[0]+m*Math.sin(t*R)*Math.cos(o*R),c[1]+m*Math.sin(o*R),c[2]+m*Math.cos(t*R)*Math.cos(o*R)];return {target:c,position:h,radius:s,distance:m}}function z(r,e){return [0,1,2].map(t=>{let o=e.min[t]*a,n=e.max[t]*a,a$1=(n-o)/4;return Math.min(Math.max(r[t],o-a$1),n+a$1)})}function W(r){let{before:e,turning:t,camera:o,middle:n,radius:a,bounds:i}=r,c=a/e.radius,s=z(n.map((l,m)=>l+(t[m]-e.middle[m])*c),i),f=s.map((l,m)=>l+(o[m]-t[m])*c);return {target:s,position:f}}function Z(r){let{geometry:e,camera:t,interactive:o,handle:n}=r,{camera:a,invalidate:i,size:c}=useThree(),s=useRef(null),f=useRef(null),l=x({bounds:e.bounds,azimuth:t?.azimuth,elevation:t?.elevation}),[m,h,g]=l.target,{radius:E}=l;useLayoutEffect(()=>{let p=[m,h,g],u=f.current,d=s.current;if(u){let S=W({before:u,turning:d?d.target.toArray():u.middle,camera:a.position.toArray(),middle:p,radius:E,bounds:e.bounds});a.position.set(...S.position),d?.target.set(...S.target);}else d?.target.set(...p);d?.update(),a.lookAt(d?.target??new v.Vector3(...p)),f.current={middle:p,radius:E},i();},[m,h,g,E,a,i]);let b=p=>{let u=s.current;if(!u)return;let d=new v.Vector3(...z(p.toArray(),e.bounds));a.position.add(d.clone().sub(u.target)),u.target.copy(d),u.update(),i();};return useLayoutEffect(()=>(n.current={pan:(p,u)=>{let d=s.current;if(!d)return;a.updateMatrixWorld();let S=E*.15,ie=new v.Vector3().setFromMatrixColumn(a.matrixWorld,0).multiplyScalar(p*S).add(new v.Vector3().setFromMatrixColumn(a.matrixWorld,1).multiplyScalar(u*S));b(d.target.clone().add(ie));},zoom:p=>{let u=s.current;if(!u)return;let d=a.position.clone().sub(u.target),S=Math.min(Math.max(d.length()*(p>0?.8:1.25),E*.8),E*8);a.position.copy(u.target).add(d.setLength(S)),u.update(),i();},reset:()=>{let p=s.current,u=x({bounds:e.bounds,azimuth:t?.azimuth,elevation:t?.elevation,aspect:c.height>0?c.width/c.height:void 0});a.position.set(...u.position),p?.target.set(...u.target),p?.update(),i();}},()=>{n.current=null;})),jsx(OrbitControls,{ref:s,makeDefault:true,enabled:o,enablePan:true,screenSpacePanning:true,minDistance:E*.8,maxDistance:E*8,maxPolarAngle:Math.PI/2+.05,onChange:()=>{let p=s.current;if(!p)return;z(p.target.toArray(),e.bounds).some((d,S)=>d!==p.target.getComponent(S))&&b(p.target.clone());}})}var J={studio:{exposure:1.3,environmentIntensity:.6,key:{color:"#ffffff",intensity:2.6,position:[3,5,4]},shadowOpacity:.5},warm:{exposure:1.4,environmentIntensity:.75,key:{color:"#ffd8b0",intensity:1.7,position:[2.5,4,4]},shadowOpacity:.55},daylight:{exposure:1.6,environmentIntensity:1.15,key:{color:"#eef3ff",intensity:1.8,position:[4,6,3]},shadowOpacity:.4}};function $(r){return j.includes(r)?J[r]:J.studio}function Q(r){let e=useThree(a=>a.invalidate),t=JSON.stringify(Object.entries(r).map(([a,i])=>[a,n(i)])),o=useMemo(()=>JSON.parse(t),[t]),n$1=useMemo(()=>Object.fromEntries(o.map(([a,i])=>[a,pe(i)])),[o]);return useEffect(()=>{let a=new v.TextureLoader;a.setCrossOrigin("anonymous");let i=false,c=[];for(let[s,f]of o){let l=n$1[s];if(l)for(let m$1 of de(f))a.load(m$1.url,h=>{if(i){h.dispose();return}h.colorSpace=m$1.colorSpace,h.wrapS=v.RepeatWrapping,h.wrapT=v.RepeatWrapping;let g=m(f);h.repeat.set(g.repeat,g.repeat),h.rotation=g.rotation,m$1.apply(l,h),l.needsUpdate=true,c.push(h),e();},void 0,()=>{});}return ()=>{i=true;for(let s of c)s.dispose();}},[o,n$1,e]),useEffect(()=>()=>{for(let a of Object.values(n$1))a.dispose();},[n$1]),n$1}function pe(r){let e=new v.MeshStandardMaterial({color:r.color,roughness:r.roughness,metalness:r.metalness});return r.emissive&&(e.emissive.set(r.color),e.emissiveIntensity=1,e.toneMapped=false),r.transparent&&(e.transparent=true,e.opacity=r.opacity,e.depthWrite=false),e}function de(r){let e=[];return r.texture&&e.push({url:r.texture,colorSpace:v.SRGBColorSpace,apply:(t,o)=>{t.map=o,t.color.set("#ffffff");}}),r.normalMap&&e.push({url:r.normalMap,colorSpace:v.NoColorSpace,apply:(t,o)=>{t.normalMap=o,t.normalScale.set(r.normalScale,r.normalScale);}}),r.roughnessMap&&e.push({url:r.roughnessMap,colorSpace:v.NoColorSpace,apply:(t,o)=>{t.roughnessMap=o;}}),e}function ee(r){let{intensity:e}=r,t=useThree(o=>o.get);return useEffect(()=>{let{gl:o,scene:n,invalidate:a}=t(),i=new v.PMREMGenerator(o),c=new RoomEnvironment,s=i.fromScene(c,.04);return c.dispose(),i.dispose(),n.environment=s.texture,a(),()=>{n.environment===s.texture&&(n.environment=null),s.dispose();}},[t]),useEffect(()=>{let{scene:o,invalidate:n}=t();o.environmentIntensity=e,n();},[t,e]),null}function te(r){let{exposure:e}=r,t=useThree(o=>o.get);return useEffect(()=>{let{gl:o,invalidate:n}=t();o.toneMapping=v.AgXToneMapping,o.toneMappingExposure=e,o.outputColorSpace=v.SRGBColorSpace,n();},[t,e]),null}var Ce=lazy(()=>import('./model-part-CGYO323N.js')),Me=.05,xe=1e-4;function st(r){let{geometry:e,slots:t,camera:o,interactive:n=true,className:a}=r,i=$(r.lighting),c=useState(()=>x({bounds:e.bounds,azimuth:o?.azimuth,elevation:o?.elevation}))[0],s=e.bounds.min[1]/1e3-.001,f=useRef(null),l=n&&r.cameraLabels;return jsxs("div",{className:a,style:{position:"relative",width:"100%",height:"100%"},onContextMenu:m=>m.preventDefault(),tabIndex:l?0:void 0,onKeyDown:m=>{l&&f.current&&U(m.key,f.current)&&m.preventDefault();},children:[jsxs(Canvas,{frameloop:"demand",dpr:[1,2],camera:{fov:O,position:c.position,near:.05,far:100},gl:{antialias:true,alpha:true},shadows:"soft",children:[jsx(te,{exposure:i.exposure}),jsx(ee,{intensity:i.environmentIntensity}),jsx(Te,{position:i.key.position,color:i.key.color,intensity:i.key.intensity,target:c.target,radius:c.radius}),jsx(we,{parts:e.parts,slots:t,edges:r.edges}),jsx(ContactShadows,{position:[c.target[0],s,c.target[2]],opacity:i.shadowOpacity,scale:Math.max(c.radius*4,2),resolution:1024,blur:2,far:1.5}),jsx(Z,{geometry:e,camera:o,interactive:n,handle:f})]}),l?jsx(B,{handle:f,labels:l}):null]})}function Te(r){let{target:e,radius:t}=r,o=useRef(null),n=useThree(i=>i.invalidate),a=Math.max(t*1.5,1);return useLayoutEffect(()=>{let i=o.current;if(!i)return;let c=new v.Vector3(...r.position).normalize();i.position.set(...e).add(c.multiplyScalar(a*2)),i.target.position.set(...e),i.target.updateMatrixWorld();let s=i.shadow.camera;s.left=-a,s.right=a,s.top=a,s.bottom=-a,s.near=.1,s.far=a*4,s.updateProjectionMatrix(),i.shadow.needsUpdate=true,n();},[r.position,e,a,n]),jsx("directionalLight",{ref:o,color:r.color,intensity:r.intensity,castShadow:true,"shadow-mapSize":[2048,2048],"shadow-bias":-8e-4,"shadow-normalBias":.04,"shadow-radius":4})}function we(r){let e=Q(r.slots);return jsx(Fragment,{children:r.parts.map(t=>{let o$1=e[t.slot];if(!o$1)return null;if(t.type!=="model"||!t.model)return jsx(oe,{part:t,material:o$1,edges:r.edges},t.key);let n=jsx(oe,{part:t,material:o$1});return jsx(o,{fallback:n,children:jsx(Suspense,{fallback:n,children:jsx(Ce,{part:{...t,model:t.model},material:o$1})})},`${t.key}:${t.model}`)})})}function oe(r){let{part:e$1,material:t,edges:o}=r,n=useRef(null),a=useRef(false),i=useRef(e$1.size),c$1=useThree(g=>g.invalidate),[s,f$1,l]=f(e$1),m=JSON.stringify(e$1.params),h=useMemo(()=>e(e$1,o),[e$1.type,e$1.size[0],e$1.size[1],e$1.size[2],m,o]);return useEffect(()=>()=>h.dispose(),[h]),useLayoutEffect(()=>{let g=n.current;if(g){if(!a.current)g.position.set(s,f$1,l),a.current=true;else {let E=i.current,b=g.scale;b.set(b.x*k(E[0],e$1.size[0]),b.y*k(E[1],e$1.size[1]),b.z*k(E[2],e$1.size[2]));}i.current=e$1.size,c$1();}},[h,e$1.size,s,f$1,l,c$1]),useFrame((g,E)=>{let b=n.current;if(!b)return;let p=1-Math.exp(-E/Me),u=new v.Vector3(s,f$1,l),d=new v.Vector3(1,1,1),S=Math.max(b.position.distanceTo(u),b.scale.distanceTo(d));if(S<xe){S>0&&(b.position.copy(u),b.scale.copy(d));return}b.position.lerp(u,p),b.scale.lerp(d,p),c$1();}),jsx("mesh",{ref:n,geometry:h,material:t,castShadow:c(t),receiveShadow:true})}function k(r,e){return r>0&&e>0?r/e:1}export{st as ConfiguratorScene};
@@ -1 +0,0 @@
1
- import {d,c,b,f}from'./chunk-QLPSL2DY.js';import'./chunk-RNTBO6KY.js';import {useRef,useMemo,useLayoutEffect}from'react';import {useLoader,useThree,useFrame}from'@react-three/fiber';import*as l from'three';import {MeshoptDecoder}from'three/examples/jsm/libs/meshopt_decoder.module.js';import {GLTFLoader}from'three/examples/jsm/loaders/GLTFLoader.js';import {jsx}from'react/jsx-runtime';function G(s){return s===1?"stretch":s===2?"actual":"contain"}function P(s){let{frame:n,bounds:o,fit:a}=s;if(a==="actual")return {scale:[1,1,1],centre:[(o.min[0]+o.max[0])/2,o.min[1]+n[1]/2,o.max[2]-n[2]/2]};let m=[0,1,2].map(e=>o.max[e]-o.min[e]),p=[0,1,2].map(e=>{let d=m[e],u=n[e];return d>0&&u>0?u/d:null}),b=p.filter(e=>e!==null),c=b.length>0?Math.min(...b):1,i=[0,1,2].map(e=>a==="stretch"?p[e]??c:c),f=[0,1,2].map(e=>(o.min[e]+o.max[e])/2);return {scale:i,centre:f}}var J=.05,K=1e-4;function Q(s){s.setMeshoptDecoder(MeshoptDecoder);}function U(s){let{part:n,material:o}=s,a=useLoader(GLTFLoader,n.model,Q),m=useRef(null),p=useRef(new l.Vector3),b$1=useRef(new l.Vector3),c$1=useRef(false),i=useThree(r=>r.invalidate),f$1=n.params.paint===1,e=useMemo(()=>{let r=new l.Box3().setFromObject(a.scene);return {min:r.min.toArray(),max:r.max.toArray()}},[a.scene]),d$1=useMemo(()=>{let r=a.scene.clone(true);return r.traverse(F=>{let t=F;t.isMesh&&(f$1?t.material=o:d(t.material),t.castShadow=c(t.material),t.receiveShadow=true);}),r},[a.scene,f$1,o]),u=P({frame:[b(n.size[0]),b(n.size[1]),b(n.size[2])],bounds:e,fit:G(n.params.fit)}),[M,T,x]=f(n),[y,w,g]=u.scale,[_,j,N]=u.centre;return useLayoutEffect(()=>{let r=m.current;r&&!c$1.current&&(r.position.set(M,T,x),r.scale.set(y,w,g),c$1.current=true),i();},[M,T,x,y,w,g,i]),useFrame((r,F)=>{let t=m.current;if(!t)return;let H=1-Math.exp(-F/J),R=p.current.set(M,T,x),S=b$1.current.set(y,w,g),L=Math.max(t.position.distanceTo(R),t.scale.distanceTo(S));if(L<K){L>0&&(t.position.copy(R),t.scale.copy(S));return}t.position.lerp(R,H),t.scale.lerp(S,H),i();}),jsx("group",{ref:m,children:jsx("primitive",{object:d$1,position:[-_,-j,-N]})})}export{U as default};