create-playcanvas 0.11.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +15 -2
  2. package/dist/index.mjs +41 -38
  3. package/package.json +5 -2
  4. package/templates/_features/physics/assets/public/ammo/SOURCE.md +4 -1
  5. package/templates/{react/interactive-sphere/src/App.css → _shared/interactive-sphere/src/counter.css} +0 -6
  6. package/templates/engine/base/README.md +1 -1
  7. package/templates/engine/base/vite.config.ts +3 -0
  8. package/templates/engine/first-person-controller/src/main.ts +2 -3
  9. package/templates/engine/interactive-sphere/src/App.ts +1 -1
  10. package/templates/engine/interactive-sphere/src/main.ts +3 -5
  11. package/templates/engine/model-viewer/src/main.ts +3 -3
  12. package/templates/engine/physics-playground/src/main.ts +2 -3
  13. package/templates/engine/spinning-cube/src/main.ts +1 -1
  14. package/templates/engine/splat-viewer/src/main.ts +1 -1
  15. package/templates/engine/third-person-controller/src/main.ts +2 -3
  16. package/templates/react/base/README.md +1 -1
  17. package/templates/react/base/vite.config.ts +3 -0
  18. package/templates/react/interactive-sphere/src/App.tsx +5 -6
  19. package/templates/react/interactive-sphere/src/Scene.tsx +1 -1
  20. package/templates/react/model-viewer/src/App.tsx +4 -2
  21. package/templates/react/spinning-cube/src/App.tsx +2 -0
  22. package/templates/react/splat-viewer/src/App.tsx +2 -0
  23. package/templates/web-components/base/README.md +1 -1
  24. package/templates/web-components/base/vite.config.ts +3 -0
  25. package/templates/web-components/first-person-controller/index.html +1 -6
  26. package/templates/web-components/interactive-sphere/src/main.ts +2 -2
  27. package/templates/web-components/model-viewer/index.html +2 -2
  28. package/templates/web-components/model-viewer/src/main.ts +0 -1
  29. package/templates/web-components/physics-playground/index.html +1 -6
  30. package/templates/web-components/spinning-cube/src/main.ts +0 -1
  31. package/templates/web-components/splat-viewer/src/main.ts +0 -1
  32. package/templates/web-components/third-person-controller/index.html +1 -6
  33. package/templates/_features/physics/assets/public/ammo/ammo.js +0 -973
  34. package/templates/engine/interactive-sphere/index.html +0 -13
  35. package/templates/engine/interactive-sphere/src/style.css +0 -28
  36. package/templates/engine/model-viewer/index.html +0 -13
  37. package/templates/engine/model-viewer/src/style.css +0 -8
  38. package/templates/engine/spinning-cube/index.html +0 -13
  39. package/templates/engine/spinning-cube/src/style.css +0 -8
  40. package/templates/engine/splat-viewer/index.html +0 -13
  41. package/templates/engine/splat-viewer/src/style.css +0 -8
  42. package/templates/react/base/.prettierignore +0 -3
  43. package/templates/react/base/_gitignore +0 -24
  44. package/templates/react/base/_npmrc +0 -1
  45. package/templates/react/base/prettier.config.mjs +0 -1
  46. package/templates/react/base/src/assets/playcanvas.png +0 -0
  47. package/templates/react/base/src/inspector.css +0 -33
  48. package/templates/react/base/src/inspector.ts +0 -38
  49. package/templates/react/base/src/starter.css +0 -104
  50. package/templates/react/base/src/vite-env.d.ts +0 -19
  51. package/templates/react/interactive-sphere/index.html +0 -13
  52. package/templates/react/interactive-sphere/src/index.css +0 -4
  53. package/templates/react/interactive-sphere/src/main.tsx +0 -11
  54. package/templates/react/model-viewer/index.html +0 -13
  55. package/templates/react/model-viewer/src/index.css +0 -9
  56. package/templates/react/model-viewer/src/main.tsx +0 -11
  57. package/templates/react/spinning-cube/index.html +0 -13
  58. package/templates/react/spinning-cube/src/index.css +0 -9
  59. package/templates/react/spinning-cube/src/main.tsx +0 -11
  60. package/templates/react/splat-viewer/index.html +0 -13
  61. package/templates/react/splat-viewer/src/index.css +0 -9
  62. package/templates/react/splat-viewer/src/main.tsx +0 -11
  63. package/templates/web-components/base/.prettierignore +0 -3
  64. package/templates/web-components/base/_gitignore +0 -24
  65. package/templates/web-components/base/_npmrc +0 -1
  66. package/templates/web-components/base/prettier.config.mjs +0 -1
  67. package/templates/web-components/base/src/assets/playcanvas.png +0 -0
  68. package/templates/web-components/base/src/inspector.css +0 -33
  69. package/templates/web-components/base/src/inspector.ts +0 -38
  70. package/templates/web-components/base/src/starter.css +0 -104
  71. package/templates/web-components/base/src/vite-env.d.ts +0 -19
  72. package/templates/web-components/interactive-sphere/src/style.css +0 -53
  73. package/templates/web-components/model-viewer/src/style.css +0 -8
  74. package/templates/web-components/spinning-cube/src/style.css +0 -8
  75. package/templates/web-components/splat-viewer/src/style.css +0 -8
  76. /package/templates/{engine/base → _common}/.prettierignore +0 -0
  77. /package/templates/{engine/base → _common}/_gitignore +0 -0
  78. /package/templates/{engine/base → _common}/_npmrc +0 -0
  79. /package/templates/{engine/base → _common}/prettier.config.mjs +0 -0
  80. /package/templates/{engine/base → _common}/src/assets/playcanvas.png +0 -0
  81. /package/templates/{engine/base → _common}/src/inspector.css +0 -0
  82. /package/templates/{engine/base → _common}/src/inspector.ts +0 -0
  83. /package/templates/{engine/base → _common}/src/starter.css +0 -0
  84. /package/templates/{engine/base → _common}/src/vite-env.d.ts +0 -0
package/README.md CHANGED
@@ -38,7 +38,7 @@ Every format uses TypeScript and includes Vite, ESLint, Prettier and a productio
38
38
 
39
39
  ## Starters
40
40
 
41
- Choose from 13 starter kits across basics, viewers, games, tools and XR. Run the creator to browse them; `spinning-cube` is the default.
41
+ Choose from starter kits across basics, viewers, games, tools and XR. Run the creator to browse them; `spinning-cube` is the default.
42
42
 
43
43
  ![The PlayCanvas starter scenes](images/starter-catalog.webp)
44
44
 
@@ -69,7 +69,7 @@ npm create playcanvas@latest my-game -- -f react -y
69
69
  | `--yes` | `-y` | Skip the prompts and take the defaults |
70
70
  | `--help` | `-h` | Show command help |
71
71
 
72
- `--yes` takes `playcanvas-project`, the `engine` format and the `spinning-cube` starter for anything you don't pass. It never deletes files, so a non-empty target directory still needs `--overwrite`. The previous `--template` and `--boilerplate` long flags remain accepted for compatibility.
72
+ `--yes` takes `playcanvas-project`, the `engine` format and the `spinning-cube` starter for anything you don't pass. It never deletes files, so a non-empty target directory still needs `--overwrite`. A run without a terminal, such as one started by an AI agent or in CI, takes the same defaults, so it never waits on a prompt. The previous `--template` and `--boilerplate` long flags remain accepted for compatibility.
73
73
 
74
74
  ## Agent skills
75
75
 
@@ -79,12 +79,25 @@ Every project includes [`@playcanvas/skills`](https://github.com/playcanvas/skil
79
79
 
80
80
  ```bash
81
81
  npm install
82
+ npm test
82
83
  npm run build
83
84
  node dist/index.mjs
84
85
  ```
85
86
 
86
87
  Contributions are welcome. Please open an issue before proposing a new format, starter or another substantial change.
87
88
 
89
+ ### Adding a starter
90
+
91
+ A project is assembled from the layers under `templates/`, in this order. A file in a later layer replaces the same file in an earlier one, and each layer's `package.json` is merged into those before it.
92
+
93
+ 1. `_common/`: files every project gets
94
+ 2. `<format>/base/`: the format's tooling and README, a default `index.html` for Engine and React, and React's `src/main.tsx`
95
+ 3. `_shared/<starter>/`: the starter's format-independent code and assets. Its `README.md` is inserted into the base README above `## Prerequisites`
96
+ 4. `_features/<feature>/<layer>/`: what each of the starter's `features` needs in that format, as mapped by `FEATURES` in `templates/index.ts`
97
+ 5. `<format>/<starter>/`: the starter's scene in that format
98
+
99
+ To add a starter, list it in `STARTERS` in `templates/index.ts`, add `_shared/<starter>/README.md`, and add its scene to every format: `engine/<starter>/src/main.ts`, `react/<starter>/src/App.tsx`, and `web-components/<starter>/index.html` with `src/main.ts`. Import `./starter.css` for the shared page and panel styles, and override a base file only when the starter needs something different. `npm test` checks that the starter exists in every format, and CI scaffolds and builds it in each one.
100
+
88
101
  ## License
89
102
 
90
103
  [MIT](LICENSE)
package/dist/index.mjs CHANGED
@@ -1,57 +1,57 @@
1
1
  #!/usr/bin/env node
2
- import{styleText as l}from"node:util";import B,{stdin as Le,stdout as he}from"node:process";import Ne from"node:readline";import"node:tty";import $ from"node:fs";import y from"node:path";import{fileURLToPath as De}from"node:url";const We=(()=>{const e=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g;return t=>{let r=0;for(e.lastIndex=0;e.test(t);)r+=1;return t.length-r}})(),Ve=e=>e===12288||e>=65281&&e<=65376||e>=65504&&e<=65510,Ue=e=>e===8987||e===9001||e>=12272&&e<=12287||e>=12289&&e<=12350||e>=12441&&e<=12543||e>=12549&&e<=12591||e>=12593&&e<=12686||e>=12688&&e<=12771||e>=12783&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=19903||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=127488&&e<=127490||e>=127504&&e<=127547||e>=127552&&e<=127560||e>=131072&&e<=196605||e>=196608&&e<=262141,Ge=/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y,Ke=/[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y,me=/(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu,He=/\t{1,1000}/y,de=new RegExp("[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F\\u20E3?))*","yu"),ze=/(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y,Je=new RegExp("\\p{M}+","gu"),Ye={limit:1/0,ellipsis:""},fe=(e,t={},r={})=>{const i=t.limit??1/0,n=t.ellipsis??"",c=t?.ellipsisWidth??(n?fe(n,Ye,r).width:0),a=0,o=r.controlWidth??0,s=r.tabWidth??8,u=r.emojiWidth??2,d=2,h=r.regularWidth??1,m=r.wideWidth??d,p=[[ze,h],[Ge,a],[Ke,o],[He,s],[de,u],[me,m]];let f=0,b=0,F=e.length,T=0,O=!1,M=F,k=Math.max(0,i-c),w=0,S=0,x=0,E=0;e:for(;;){if(S>w||b>=F&&b>f){const _=e.slice(w,S)||e.slice(f,b);T=0;for(const R of _.replaceAll(Je,"")){const I=R.codePointAt(0)||0;if(Ve(I)?E=d:Ue(I)?E=m:E=h,x+E>k&&(M=Math.min(M,Math.max(w,f)+T)),x+E>i){O=!0;break e}T+=R.length,x+=E}w=S=0}if(b>=F)break e;for(let _=0,R=p.length;_<R;_++){const[I,g]=p[_];if(I.lastIndex=b,I.test(e)){if(T=I===me?We(e.slice(b,I.lastIndex)):I===de?1:I.lastIndex-b,E=T*g,x+E>k&&(M=Math.min(M,b+Math.floor((k-x)/g))),x+E>i){O=!0;break e}x+=E,w=f,S=b,b=f=I.lastIndex;continue e}}b+=1}return{width:O?k:x,index:O?M:F,truncated:O,ellipsed:O&&i>=c}},qe={limit:1/0,ellipsis:"",ellipsisWidth:0},D=(e,t={})=>fe(e,qe,t).width,J="\x1B",pe="\x9B",Xe=39,te="\x07",ge="[",Ze="]",be="m",re=`${Ze}8;;`,ye=new RegExp(`(?:\\${ge}(?<code>\\d+)m|\\${re}(?<uri>.*)${te})`,"y"),$e=e=>{if(e>=30&&e<=37||e>=90&&e<=97)return 39;if(e>=40&&e<=47||e>=100&&e<=107)return 49;if(e===1||e===2)return 22;if(e===3)return 23;if(e===4)return 24;if(e===7)return 27;if(e===8)return 28;if(e===9)return 29;if(e===0)return 0},xe=e=>`${J}${ge}${e}${be}`,we=e=>`${J}${re}${e}${te}`,se=(e,t,r)=>{const i=t[Symbol.iterator]();let n=!1,c=!1,a=e.at(-1),o=a===void 0?0:D(a),s=i.next(),u=i.next(),d=0;for(;!s.done;){const h=s.value,m=D(h);o+m<=r?e[e.length-1]+=h:(e.push(h),o=0),(h===J||h===pe)&&(n=!0,c=t.startsWith(re,d+1)),n?c?h===te&&(n=!1,c=!1):h===be&&(n=!1):(o+=m,o===r&&!u.done&&(e.push(""),o=0)),s=u,u=i.next(),d+=h.length}a=e.at(-1),!o&&a!==void 0&&a.length&&e.length>1&&(e[e.length-2]+=e.pop())},Qe=e=>{const t=e.split(" ");let r=t.length;for(;r&&!D(t[r-1]);)r--;return r===t.length?e:t.slice(0,r).join(" ")+t.slice(r).join("")},et=(e,t,r={})=>{if(r.trim!==!1&&e.trim()==="")return"";let i="",n,c;const a=e.split(" ");let o=[""],s=0;for(let h=0;h<a.length;h++){const m=a[h];if(r.trim!==!1){const f=o.at(-1)??"",b=f.trimStart();f.length!==b.length&&(o[o.length-1]=b,s=D(b))}h!==0&&(s>=t&&(r.wordWrap===!1||r.trim===!1)&&(o.push(""),s=0),(s||r.trim===!1)&&(o[o.length-1]+=" ",s++));const p=D(m);if(r.hard&&p>t){const f=t-s,b=1+Math.floor((p-f-1)/t);Math.floor((p-1)/t)<b&&o.push(""),se(o,m,t),s=D(o.at(-1)??"");continue}if(s+p>t&&s&&p){if(r.wordWrap===!1&&s<t){se(o,m,t),s=D(o.at(-1)??"");continue}o.push(""),s=0}if(s+p>t&&r.wordWrap===!1){se(o,m,t),s=D(o.at(-1)??"");continue}o[o.length-1]+=m,s+=p}r.trim!==!1&&(o=o.map(h=>Qe(h)));const u=o.join(`
3
- `);let d=!1;for(let h=0;h<u.length;h++){const m=u[h];if(i+=m,d)d=!1;else if(d=m>="\uD800"&&m<="\uDBFF",d)continue;if(m===J||m===pe){ye.lastIndex=h+1;const f=ye.exec(u)?.groups;if(f?.code!==void 0){const b=Number.parseFloat(f.code);n=b===Xe?void 0:b}else f?.uri!==void 0&&(c=f.uri.length===0?void 0:f.uri)}if(u[h+1]===`
4
- `){c&&(i+=we(""));const p=n?$e(n):void 0;n&&p&&(i+=xe(p))}else m===`
5
- `&&(n&&$e(n)&&(i+=xe(n)),c&&(i+=we(c)))}return i},tt=/\r?\n/;function Y(e,t,r){return String(e).normalize().split(tt).map(i=>et(i,t,r)).join(`
6
- `)}function rt(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var ie,ve;function st(){if(ve)return ie;ve=1;const e="\x1B",t=`${e}[`,r="\x07",i={to(a,o){return o?`${t}${o+1};${a+1}H`:`${t}${a+1}G`},move(a,o){let s="";return a<0?s+=`${t}${-a}D`:a>0&&(s+=`${t}${a}C`),o<0?s+=`${t}${-o}A`:o>0&&(s+=`${t}${o}B`),s},up:(a=1)=>`${t}${a}A`,down:(a=1)=>`${t}${a}B`,forward:(a=1)=>`${t}${a}C`,backward:(a=1)=>`${t}${a}D`,nextLine:(a=1)=>`${t}E`.repeat(a),prevLine:(a=1)=>`${t}F`.repeat(a),left:`${t}G`,hide:`${t}?25l`,show:`${t}?25h`,save:`${e}7`,restore:`${e}8`},n={up:(a=1)=>`${t}S`.repeat(a),down:(a=1)=>`${t}T`.repeat(a)},c={screen:`${t}2J`,up:(a=1)=>`${t}1J`.repeat(a),down:(a=1)=>`${t}J`.repeat(a),line:`${t}2K`,lineEnd:`${t}K`,lineStart:`${t}1K`,lines(a){let o="";for(let s=0;s<a;s++)o+=this.line+(s<a-1?i.up():"");return a&&(o+=i.left),o}};return ie={cursor:i,scroll:n,erase:c,beep:r},ie}var P=st();function q(e,t,r){if(!r.some(a=>!a.disabled))return e;const i=e+t,n=Math.max(r.length-1,0),c=i<0?n:i>n?0:i;return r[c]?.disabled?q(c,t<0?-1:1,r):c}const it=["up","down","left","right","space","enter","cancel"],V={actions:new Set(it),aliases:new Map([["k","up"],["j","down"],["h","left"],["l","right"],["","cancel"],["escape","cancel"]]),withGuide:!0};function nt(e){if(e!==void 0)return e;const t=process.env.ACCESSIBLE;return t!==void 0&&t!==""&&t!=="0"&&t!=="false"}function Se(e,t){if(typeof e=="string")return V.aliases.get(e)===t;for(const r of e)if(r!==void 0&&Se(r,t))return!0;return!1}function at(e,t){if(e===t)return;const r=e.split(`
2
+ import{styleText as c}from"node:util";import k,{stdin as Ae,stdout as ae}from"node:process";import ke from"node:readline";import"node:tty";import w from"node:fs";import x from"node:path";import{fileURLToPath as je}from"node:url";const Oe=(()=>{const e=/[\uD800-\uDBFF][\uDC00-\uDFFF]/g;return t=>{let r=0;for(e.lastIndex=0;e.test(t);)r+=1;return t.length-r}})(),Be=e=>e===12288||e>=65281&&e<=65376||e>=65504&&e<=65510,Le=e=>e===8987||e===9001||e>=12272&&e<=12287||e>=12289&&e<=12350||e>=12441&&e<=12543||e>=12549&&e<=12591||e>=12593&&e<=12686||e>=12688&&e<=12771||e>=12783&&e<=12830||e>=12832&&e<=12871||e>=12880&&e<=19903||e>=65040&&e<=65049||e>=65072&&e<=65106||e>=65108&&e<=65126||e>=65128&&e<=65131||e>=127488&&e<=127490||e>=127504&&e<=127547||e>=127552&&e<=127560||e>=131072&&e<=196605||e>=196608&&e<=262141,Me=/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]|\u001b\]8;[^;]*;.*?(?:\u0007|\u001b\u005c)/y,Pe=/[\x00-\x08\x0A-\x1F\x7F-\x9F]{1,1000}/y,oe=/(?:(?![\uFF61-\uFF9F\uFF00-\uFFEF])[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}\p{Script=Tangut}]){1,1000}/yu,Ne=/\t{1,1000}/y,le=new RegExp("[\\u{1F1E6}-\\u{1F1FF}]{2}|\\u{1F3F4}[\\u{E0061}-\\u{E007A}]{2}[\\u{E0030}-\\u{E0039}\\u{E0061}-\\u{E007A}]{1,3}\\u{E007F}|(?:\\p{Emoji}\\uFE0F\\u20E3?|\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation})(?:\\u200D(?:\\p{Emoji_Modifier_Base}\\p{Emoji_Modifier}?|\\p{Emoji_Presentation}|\\p{Emoji}\\uFE0F\\u20E3?))*","yu"),De=/(?:[\x20-\x7E\xA0-\xFF](?!\uFE0F)){1,1000}/y,We=new RegExp("\\p{M}+","gu"),Ve={limit:1/0,ellipsis:""},ce=(e,t={},r={})=>{const i=t.limit??1/0,n=t.ellipsis??"",l=t?.ellipsisWidth??(n?ce(n,Ve,r).width:0),a=0,o=r.controlWidth??0,s=r.tabWidth??8,u=r.emojiWidth??2,d=2,h=r.regularWidth??1,m=r.wideWidth??d,b=[[De,h],[Me,a],[Pe,o],[Ne,s],[le,u],[oe,m]];let g=0,$=0,_=e.length,F=0,T=!1,R=_,I=Math.max(0,i-l),v=0,f=0,y=0,p=0;e:for(;;){if(f>v||$>=_&&$>g){const S=e.slice(v,f)||e.slice(g,$);F=0;for(const B of S.replaceAll(We,"")){const C=B.codePointAt(0)||0;if(Be(C)?p=d:Le(C)?p=m:p=h,y+p>I&&(R=Math.min(R,Math.max(v,g)+F)),y+p>i){T=!0;break e}F+=B.length,y+=p}v=f=0}if($>=_)break e;for(let S=0,B=b.length;S<B;S++){const[C,ne]=b[S];if(C.lastIndex=$,C.test(e)){if(F=C===oe?Oe(e.slice($,C.lastIndex)):C===le?1:C.lastIndex-$,p=F*ne,y+p>I&&(R=Math.min(R,$+Math.floor((I-y)/ne))),y+p>i){T=!0;break e}y+=p,v=g,f=$,$=g=C.lastIndex;continue e}}$+=1}return{width:T?I:y,index:T?R:_,truncated:T,ellipsed:T&&i>=l}},Ue={limit:1/0,ellipsis:"",ellipsisWidth:0},M=(e,t={})=>ce(e,Ue,t).width,V="\x1B",ue="\x9B",Ge=39,q="\x07",he="[",Ke="]",me="m",X=`${Ke}8;;`,de=new RegExp(`(?:\\${he}(?<code>\\d+)m|\\${X}(?<uri>.*)${q})`,"y"),fe=e=>{if(e>=30&&e<=37||e>=90&&e<=97)return 39;if(e>=40&&e<=47||e>=100&&e<=107)return 49;if(e===1||e===2)return 22;if(e===3)return 23;if(e===4)return 24;if(e===7)return 27;if(e===8)return 28;if(e===9)return 29;if(e===0)return 0},pe=e=>`${V}${he}${e}${me}`,ge=e=>`${V}${X}${e}${q}`,Z=(e,t,r)=>{const i=t[Symbol.iterator]();let n=!1,l=!1,a=e.at(-1),o=a===void 0?0:M(a),s=i.next(),u=i.next(),d=0;for(;!s.done;){const h=s.value,m=M(h);o+m<=r?e[e.length-1]+=h:(e.push(h),o=0),(h===V||h===ue)&&(n=!0,l=t.startsWith(X,d+1)),n?l?h===q&&(n=!1,l=!1):h===me&&(n=!1):(o+=m,o===r&&!u.done&&(e.push(""),o=0)),s=u,u=i.next(),d+=h.length}a=e.at(-1),!o&&a!==void 0&&a.length&&e.length>1&&(e[e.length-2]+=e.pop())},He=e=>{const t=e.split(" ");let r=t.length;for(;r&&!M(t[r-1]);)r--;return r===t.length?e:t.slice(0,r).join(" ")+t.slice(r).join("")},ze=(e,t,r={})=>{if(r.trim!==!1&&e.trim()==="")return"";let i="",n,l;const a=e.split(" ");let o=[""],s=0;for(let h=0;h<a.length;h++){const m=a[h];if(r.trim!==!1){const g=o.at(-1)??"",$=g.trimStart();g.length!==$.length&&(o[o.length-1]=$,s=M($))}h!==0&&(s>=t&&(r.wordWrap===!1||r.trim===!1)&&(o.push(""),s=0),(s||r.trim===!1)&&(o[o.length-1]+=" ",s++));const b=M(m);if(r.hard&&b>t){const g=t-s,$=1+Math.floor((b-g-1)/t);Math.floor((b-1)/t)<$&&o.push(""),Z(o,m,t),s=M(o.at(-1)??"");continue}if(s+b>t&&s&&b){if(r.wordWrap===!1&&s<t){Z(o,m,t),s=M(o.at(-1)??"");continue}o.push(""),s=0}if(s+b>t&&r.wordWrap===!1){Z(o,m,t),s=M(o.at(-1)??"");continue}o[o.length-1]+=m,s+=b}r.trim!==!1&&(o=o.map(h=>He(h)));const u=o.join(`
3
+ `);let d=!1;for(let h=0;h<u.length;h++){const m=u[h];if(i+=m,d)d=!1;else if(d=m>="\uD800"&&m<="\uDBFF",d)continue;if(m===V||m===ue){de.lastIndex=h+1;const g=de.exec(u)?.groups;if(g?.code!==void 0){const $=Number.parseFloat(g.code);n=$===Ge?void 0:$}else g?.uri!==void 0&&(l=g.uri.length===0?void 0:g.uri)}if(u[h+1]===`
4
+ `){l&&(i+=ge(""));const b=n?fe(n):void 0;n&&b&&(i+=pe(b))}else m===`
5
+ `&&(n&&fe(n)&&(i+=pe(n)),l&&(i+=ge(l)))}return i},Je=/\r?\n/;function U(e,t,r){return String(e).normalize().split(Je).map(i=>ze(i,t,r)).join(`
6
+ `)}function Ye(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var Q,be;function qe(){if(be)return Q;be=1;const e="\x1B",t=`${e}[`,r="\x07",i={to(a,o){return o?`${t}${o+1};${a+1}H`:`${t}${a+1}G`},move(a,o){let s="";return a<0?s+=`${t}${-a}D`:a>0&&(s+=`${t}${a}C`),o<0?s+=`${t}${-o}A`:o>0&&(s+=`${t}${o}B`),s},up:(a=1)=>`${t}${a}A`,down:(a=1)=>`${t}${a}B`,forward:(a=1)=>`${t}${a}C`,backward:(a=1)=>`${t}${a}D`,nextLine:(a=1)=>`${t}E`.repeat(a),prevLine:(a=1)=>`${t}F`.repeat(a),left:`${t}G`,hide:`${t}?25l`,show:`${t}?25h`,save:`${e}7`,restore:`${e}8`},n={up:(a=1)=>`${t}S`.repeat(a),down:(a=1)=>`${t}T`.repeat(a)},l={screen:`${t}2J`,up:(a=1)=>`${t}1J`.repeat(a),down:(a=1)=>`${t}J`.repeat(a),line:`${t}2K`,lineEnd:`${t}K`,lineStart:`${t}1K`,lines(a){let o="";for(let s=0;s<a;s++)o+=this.line+(s<a-1?i.up():"");return a&&(o+=i.left),o}};return Q={cursor:i,scroll:n,erase:l,beep:r},Q}var O=qe();function G(e,t,r){if(!r.some(a=>!a.disabled))return e;const i=e+t,n=Math.max(r.length-1,0),l=i<0?n:i>n?0:i;return r[l]?.disabled?G(l,t<0?-1:1,r):l}const Xe=["up","down","left","right","space","enter","cancel"],P={actions:new Set(Xe),aliases:new Map([["k","up"],["j","down"],["h","left"],["l","right"],["","cancel"],["escape","cancel"]]),withGuide:!0};function Ze(e){if(e!==void 0)return e;const t=process.env.ACCESSIBLE;return t!==void 0&&t!==""&&t!=="0"&&t!=="false"}function ye(e,t){if(typeof e=="string")return P.aliases.get(e)===t;for(const r of e)if(r!==void 0&&ye(r,t))return!0;return!1}function Qe(e,t){if(e===t)return;const r=e.split(`
7
7
  `),i=t.split(`
8
- `),n=Math.max(r.length,i.length),c=[];for(let a=0;a<n;a++)r[a]!==i[a]&&c.push(a);return{lines:c,numLinesBefore:r.length,numLinesAfter:i.length,numLines:n}}globalThis.process.platform.startsWith("win");const ne=Symbol("clack:cancel");function H(e){return e===ne}function X(e,t){const r=e;r.isTTY&&r.setRawMode(t)}const Ee=e=>"columns"in e&&typeof e.columns=="number"?e.columns:80,_e=e=>"rows"in e&&typeof e.rows=="number"?e.rows:20;function ae(e,t,r,i=r,n=r,c){const a=Ee(e??he);return Y(t,a-r.length,{hard:!0,trim:!1}).split(`
8
+ `),n=Math.max(r.length,i.length),l=[];for(let a=0;a<n;a++)r[a]!==i[a]&&l.push(a);return{lines:l,numLinesBefore:r.length,numLinesAfter:i.length,numLines:n}}globalThis.process.platform.startsWith("win");const ee=Symbol("clack:cancel");function W(e){return e===ee}function K(e,t){const r=e;r.isTTY&&r.setRawMode(t)}const $e=e=>"columns"in e&&typeof e.columns=="number"?e.columns:80,xe=e=>"rows"in e&&typeof e.rows=="number"?e.rows:20;function te(e,t,r,i=r,n=r,l){const a=$e(e??ae);return U(t,a-r.length,{hard:!0,trim:!1}).split(`
9
9
  `).map((o,s,u)=>{const d=o;return s===0?`${i}${d}`:s===u.length-1?`${n}${d}`:`${r}${d}`}).join(`
10
- `)}function ot(e,t){if("~standard"in e){const r=e["~standard"].validate(t);return r instanceof Promise?r.then(i=>i.issues?.at(0)?.message):r.issues?.at(0)?.message}return e(t)}class Ie{input;output;_abortSignal;rl;opts;_render;_track=!1;_prevFrame="";_subscribers=new Map;_cursor=0;state="initial";error="";value;userInput="";get accessible(){return nt(this.opts.accessible)}constructor(t,r=!0){const{input:i=Le,output:n=he,render:c,signal:a,...o}=t;this.opts=o,this.onKeypress=this.onKeypress.bind(this),this.close=this.close.bind(this),this.render=this.render.bind(this),this._render=c.bind(this),this._track=r,this._abortSignal=a,this.input=i,this.output=n}unsubscribe(){this._subscribers.clear()}setSubscriber(t,r){const i=this._subscribers.get(t)??[];i.push(r),this._subscribers.set(t,i)}on(t,r){this.setSubscriber(t,{cb:r})}once(t,r){this.setSubscriber(t,{cb:r,once:!0})}emit(t,...r){const i=this._subscribers.get(t)??[],n=[];for(const c of i)c.cb(...r),c.once&&n.push(()=>i.splice(i.indexOf(c),1));for(const c of n)c()}prompt(){return new Promise(t=>{if(this._abortSignal){if(this._abortSignal.aborted)return this.state="cancel",this.close(),t(ne);this._abortSignal.addEventListener("abort",()=>{this.state="cancel",this.close()},{once:!0})}this.rl=Ne.createInterface({input:this.input,tabSize:2,prompt:"",escapeCodeTimeout:50,terminal:!0}),this.rl.prompt(),this.opts.initialUserInput!==void 0&&this._setUserInput(this.opts.initialUserInput,!0),this.input.on("keypress",this.onKeypress),X(this.input,!0),this.output.on("resize",this.render),this.render(),this.once("submit",()=>{this.output.write(P.cursor.show),this.output.off("resize",this.render),X(this.input,!1),t(this.value)}),this.once("cancel",()=>{this.output.write(P.cursor.show),this.output.off("resize",this.render),X(this.input,!1),t(ne)})})}_isActionKey(t,r){return t===" "}_shouldSubmit(t,r){return!0}_setValue(t){this.value=t,this.emit("value",this.value)}_setUserInput(t,r){this.userInput=t??"",this.emit("userInput",this.userInput),r&&this._track&&this.rl&&(this.rl.write(this.userInput),this._cursor=this.rl.cursor)}_clearUserInput(){this.rl?.write(null,{ctrl:!0,name:"u"}),this._setUserInput("")}async onKeypress(t,r){if(this.state!=="validating"){if(this._track&&r.name!=="return"&&(r.name&&this._isActionKey(t,r)&&this.rl?.write(null,{ctrl:!0,name:"h"}),this._cursor=this.rl?.cursor??0,this._setUserInput(this.rl?.line)),this.state==="error"&&(this.state="active"),r?.name&&(!this._track&&V.aliases.has(r.name)&&this.emit("cursor",V.aliases.get(r.name)),V.actions.has(r.name)&&this.emit("cursor",r.name)),t&&(t.toLowerCase()==="y"||t.toLowerCase()==="n")&&this.emit("confirm",t.toLowerCase()==="y"),this.emit("key",t,r),r?.name==="return"&&this._shouldSubmit(t,r)){if(this.opts.validate){const i=ot(this.opts.validate,this.value);let n;i instanceof Promise?(this.state="validating",this.render(),n=await i):n=i,n&&(this.error=n instanceof Error?n.message:n,this.state="error",this.rl?.write(this.userInput))}this.state!=="error"&&(this.state="submit")}Se([t,r?.name,r?.sequence],"cancel")&&(this.state="cancel"),(this.state==="submit"||this.state==="cancel")&&this.emit("finalize"),this.render(),(this.state==="submit"||this.state==="cancel")&&this.close()}}close(){this.input.unpipe(),this.input.removeListener("keypress",this.onKeypress),this.output.write(`
11
- `),X(this.input,!1),this.rl?.close(),this.rl=void 0,this.emit(`${this.state}`,this.value),this.unsubscribe()}restoreCursor(){const t=Y(this._prevFrame,process.stdout.columns,{hard:!0,trim:!1}).split(`
12
- `).length-1;this.output.write(P.cursor.move(-999,t*-1))}render(){const t=Y(this._render(this)??"",process.stdout.columns,{hard:!0,trim:!1});if(t!==this._prevFrame){if(this.state==="initial")this.output.write(P.cursor.hide);else{const r=at(this._prevFrame,t),i=_e(this.output);if(this.restoreCursor(),r){const n=Math.max(0,r.numLinesAfter-i),c=Math.max(0,r.numLinesBefore-i);let a=r.lines.find(o=>o>=n);if(a===void 0){this._prevFrame=t;return}if(r.lines.length===1){this.output.write(P.cursor.move(0,a-c)),this.output.write(P.erase.lines(1));const o=t.split(`
13
- `);this.output.write(o[a]),this._prevFrame=t,this.output.write(P.cursor.move(0,o.length-a-1));return}else if(r.lines.length>1){if(n<c)a=n;else{const s=a-c;s>0&&this.output.write(P.cursor.move(0,s))}this.output.write(P.erase.down());const o=t.split(`
10
+ `)}function et(e,t){if("~standard"in e){const r=e["~standard"].validate(t);return r instanceof Promise?r.then(i=>i.issues?.at(0)?.message):r.issues?.at(0)?.message}return e(t)}class we{input;output;_abortSignal;rl;opts;_render;_track=!1;_prevFrame="";_subscribers=new Map;_cursor=0;state="initial";error="";value;userInput="";get accessible(){return Ze(this.opts.accessible)}constructor(t,r=!0){const{input:i=Ae,output:n=ae,render:l,signal:a,...o}=t;this.opts=o,this.onKeypress=this.onKeypress.bind(this),this.close=this.close.bind(this),this.render=this.render.bind(this),this._render=l.bind(this),this._track=r,this._abortSignal=a,this.input=i,this.output=n}unsubscribe(){this._subscribers.clear()}setSubscriber(t,r){const i=this._subscribers.get(t)??[];i.push(r),this._subscribers.set(t,i)}on(t,r){this.setSubscriber(t,{cb:r})}once(t,r){this.setSubscriber(t,{cb:r,once:!0})}emit(t,...r){const i=this._subscribers.get(t)??[],n=[];for(const l of i)l.cb(...r),l.once&&n.push(()=>i.splice(i.indexOf(l),1));for(const l of n)l()}prompt(){return new Promise(t=>{if(this._abortSignal){if(this._abortSignal.aborted)return this.state="cancel",this.close(),t(ee);this._abortSignal.addEventListener("abort",()=>{this.state="cancel",this.close()},{once:!0})}this.rl=ke.createInterface({input:this.input,tabSize:2,prompt:"",escapeCodeTimeout:50,terminal:!0}),this.rl.prompt(),this.opts.initialUserInput!==void 0&&this._setUserInput(this.opts.initialUserInput,!0),this.input.on("keypress",this.onKeypress),K(this.input,!0),this.output.on("resize",this.render),this.render(),this.once("submit",()=>{this.output.write(O.cursor.show),this.output.off("resize",this.render),K(this.input,!1),t(this.value)}),this.once("cancel",()=>{this.output.write(O.cursor.show),this.output.off("resize",this.render),K(this.input,!1),t(ee)})})}_isActionKey(t,r){return t===" "}_shouldSubmit(t,r){return!0}_setValue(t){this.value=t,this.emit("value",this.value)}_setUserInput(t,r){this.userInput=t??"",this.emit("userInput",this.userInput),r&&this._track&&this.rl&&(this.rl.write(this.userInput),this._cursor=this.rl.cursor)}_clearUserInput(){this.rl?.write(null,{ctrl:!0,name:"u"}),this._setUserInput("")}async onKeypress(t,r){if(this.state!=="validating"){if(this._track&&r.name!=="return"&&(r.name&&this._isActionKey(t,r)&&this.rl?.write(null,{ctrl:!0,name:"h"}),this._cursor=this.rl?.cursor??0,this._setUserInput(this.rl?.line)),this.state==="error"&&(this.state="active"),r?.name&&(!this._track&&P.aliases.has(r.name)&&this.emit("cursor",P.aliases.get(r.name)),P.actions.has(r.name)&&this.emit("cursor",r.name)),t&&(t.toLowerCase()==="y"||t.toLowerCase()==="n")&&this.emit("confirm",t.toLowerCase()==="y"),this.emit("key",t,r),r?.name==="return"&&this._shouldSubmit(t,r)){if(this.opts.validate){const i=et(this.opts.validate,this.value);let n;i instanceof Promise?(this.state="validating",this.render(),n=await i):n=i,n&&(this.error=n instanceof Error?n.message:n,this.state="error",this.rl?.write(this.userInput))}this.state!=="error"&&(this.state="submit")}ye([t,r?.name,r?.sequence],"cancel")&&(this.state="cancel"),(this.state==="submit"||this.state==="cancel")&&this.emit("finalize"),this.render(),(this.state==="submit"||this.state==="cancel")&&this.close()}}close(){this.input.unpipe(),this.input.removeListener("keypress",this.onKeypress),this.output.write(`
11
+ `),K(this.input,!1),this.rl?.close(),this.rl=void 0,this.emit(`${this.state}`,this.value),this.unsubscribe()}restoreCursor(){const t=U(this._prevFrame,process.stdout.columns,{hard:!0,trim:!1}).split(`
12
+ `).length-1;this.output.write(O.cursor.move(-999,t*-1))}render(){const t=U(this._render(this)??"",process.stdout.columns,{hard:!0,trim:!1});if(t!==this._prevFrame){if(this.state==="initial")this.output.write(O.cursor.hide);else{const r=Qe(this._prevFrame,t),i=xe(this.output);if(this.restoreCursor(),r){const n=Math.max(0,r.numLinesAfter-i),l=Math.max(0,r.numLinesBefore-i);let a=r.lines.find(o=>o>=n);if(a===void 0){this._prevFrame=t;return}if(r.lines.length===1){this.output.write(O.cursor.move(0,a-l)),this.output.write(O.erase.lines(1));const o=t.split(`
13
+ `);this.output.write(o[a]),this._prevFrame=t,this.output.write(O.cursor.move(0,o.length-a-1));return}else if(r.lines.length>1){if(n<l)a=n;else{const s=a-l;s>0&&this.output.write(O.cursor.move(0,s))}this.output.write(O.erase.down());const o=t.split(`
14
14
  `).slice(a);this.output.write(o.join(`
15
- `)),this._prevFrame=t;return}}this.output.write(P.erase.down())}this.output.write(t),this.state==="initial"&&(this.state="active"),this._prevFrame=t}}}let ct=class extends Ie{options;cursor=0;get _selectedValue(){return this.options[this.cursor]}changeValue(){const t=this._selectedValue;this.value=t===void 0?void 0:t.value}constructor(t){super(t,!1),this.options=t.options;const r=this.options.findIndex(({value:n})=>n===t.initialValue),i=r===-1?0:r;this.cursor=this.options[i]?.disabled?q(i,1,this.options):i,this.changeValue(),this.on("cursor",n=>{switch(n){case"left":case"up":this.cursor=q(this.cursor,-1,this.options);break;case"down":case"right":this.cursor=q(this.cursor,1,this.options);break}this.changeValue()})}};class lt extends Ie{get userInputWithCursor(){if(this.state==="submit")return this.userInput;const t=this.userInput;if(this.cursor>=t.length)return`${this.userInput}\u2588`;const r=t.slice(0,this.cursor),i=t.slice(this.cursor,this.cursor+1),n=t.slice(this.cursor+1);return`${r}${l("inverse",i)}${n}`}get cursor(){return this._cursor}constructor(t){super({...t,initialUserInput:t.initialUserInput??t.initialValue}),this.on("userInput",r=>{this._setValue(r)}),this.on("finalize",()=>{this.value||(this.value=t.defaultValue),this.value===void 0&&(this.value="")})}}function ut(){return B.platform!=="win32"?B.env.TERM!=="linux":!!B.env.CI||!!B.env.WT_SESSION||!!B.env.TERMINUS_SUBLIME||B.env.ConEmuTask==="{cmd::Cmder}"||B.env.TERM_PROGRAM==="Terminus-Sublime"||B.env.TERM_PROGRAM==="vscode"||B.env.TERM==="xterm-256color"||B.env.TERM==="alacritty"||B.env.TERMINAL_EMULATOR==="JetBrains-JediTerm"}const ht=ut(),j=(e,t)=>ht?e:t,Fe=j("\u25C6","*"),mt=j("\u25A0","x"),dt=j("\u25B2","x"),Ce=j("\u25C7","o"),v=j("\u2502","|"),U=j("\u2514","\u2014"),ft=j("\u25CF",">"),Te=j("\u25CB"," "),pt=j("\u25CF","\u2022"),gt=j("\u25C6","*"),bt=j("\u25B2","!"),yt=j("\u25A0","x"),Re=e=>{switch(e){case"initial":case"active":return l("cyan",Fe);case"cancel":return l("red",mt);case"error":return l("yellow",dt);case"submit":return l("green",Ce);case"validating":return l("dim",Fe)}},$t=e=>{switch(e){case"initial":case"active":return l("cyan",v);case"cancel":return l("red",v);case"error":return l("yellow",v);case"submit":return l("green",v)}};function xt(e,t){const r=[`${t?`${l("cyan",v)} `:""}${e.join(" \u2022 ")}`];return t&&r.push(l("cyan",U)),r}const Ae=(e,t,r,i,n,c=!1)=>{let a=t,o=0;if(c)for(let s=i-1;s>=r;s--){const u=e[s];if(u&&(a-=u.length),o++,a<=n)break}else for(let s=r;s<i;s++){const u=e[s];if(u&&(a-=u.length),o++,a<=n)break}return{lineCount:a,removals:o}},wt=({cursor:e,options:t,style:r,output:i=process.stdout,maxItems:n=Number.POSITIVE_INFINITY,columnPadding:c=0,rowPadding:a=4})=>{const o=Ee(i)-c,s=_e(i),u=l("dim","..."),d=Math.max(s-a,0),h=Math.max(Math.min(n,d),5);let m=0;e>=h-3&&(m=Math.max(Math.min(e-h+3,t.length-h),0));let p=h<t.length&&m>0,f=h<t.length&&m+h<t.length;const b=Math.min(m+h,t.length),F=[];let T=0;p&&T++,f&&T++;const O=m+(p?1:0),M=b-(f?1:0);for(let w=O;w<M;w++){const S=t[w],x=S?r(S,w===e):"",E=Y(x,o,{hard:!0,trim:!1}).split(`
16
- `);F.push(E),T+=E.length}if(T>d){let w=0,S=0,x=T;const E=e-O;let _=d;const R=()=>Ae(F,x,0,E,_),I=()=>Ae(F,x,E+1,F.length,_,!0);p?({lineCount:x,removals:w}=R(),x>_&&(f||(_-=1),{lineCount:x,removals:S}=I())):(f||(_-=1),{lineCount:x,removals:S}=I(),x>_&&(_-=1,{lineCount:x,removals:w}=R())),w>0&&(p=!0,F.splice(0,w)),S>0&&(f=!0,F.splice(F.length-S,S))}const k=[];p&&k.push(u);for(const w of F)for(const S of w)k.push(S);return f&&k.push(u),k};`${l("dim","\u2191/\u2193")}`,`${l("dim","Space:")}`,`${l("dim","Enter:")}`;const W={message:(e=[],{symbol:t=l("gray",v),secondarySymbol:r=l("gray",v),output:i=process.stdout,spacing:n=1,withGuide:c}={})=>{const a=[],o=c??V.withGuide,s=o?r:"",u=o?`${t} `:"",d=o?`${r} `:"";for(let m=0;m<n;m++)a.push(s);const h=Array.isArray(e)?e:e.split(`
17
- `);if(h.length>0){const[m,...p]=h;m.length>0?a.push(`${u}${m}`):a.push(o?t:"");for(const f of p)f.length>0?a.push(`${d}${f}`):a.push(o?r:"")}i.write(`${a.join(`
15
+ `)),this._prevFrame=t;return}}this.output.write(O.erase.down())}this.output.write(t),this.state==="initial"&&(this.state="active"),this._prevFrame=t}}}let tt=class extends we{options;cursor=0;get _selectedValue(){return this.options[this.cursor]}changeValue(){const t=this._selectedValue;this.value=t===void 0?void 0:t.value}constructor(t){super(t,!1),this.options=t.options;const r=this.options.findIndex(({value:n})=>n===t.initialValue),i=r===-1?0:r;this.cursor=this.options[i]?.disabled?G(i,1,this.options):i,this.changeValue(),this.on("cursor",n=>{switch(n){case"left":case"up":this.cursor=G(this.cursor,-1,this.options);break;case"down":case"right":this.cursor=G(this.cursor,1,this.options);break}this.changeValue()})}};class rt extends we{get userInputWithCursor(){if(this.state==="submit")return this.userInput;const t=this.userInput;if(this.cursor>=t.length)return`${this.userInput}\u2588`;const r=t.slice(0,this.cursor),i=t.slice(this.cursor,this.cursor+1),n=t.slice(this.cursor+1);return`${r}${c("inverse",i)}${n}`}get cursor(){return this._cursor}constructor(t){super({...t,initialUserInput:t.initialUserInput??t.initialValue}),this.on("userInput",r=>{this._setValue(r)}),this.on("finalize",()=>{this.value||(this.value=t.defaultValue),this.value===void 0&&(this.value="")})}}function st(){return k.platform!=="win32"?k.env.TERM!=="linux":!!k.env.CI||!!k.env.WT_SESSION||!!k.env.TERMINUS_SUBLIME||k.env.ConEmuTask==="{cmd::Cmder}"||k.env.TERM_PROGRAM==="Terminus-Sublime"||k.env.TERM_PROGRAM==="vscode"||k.env.TERM==="xterm-256color"||k.env.TERM==="alacritty"||k.env.TERMINAL_EMULATOR==="JetBrains-JediTerm"}const it=st(),A=(e,t)=>it?e:t,ve=A("\u25C6","*"),nt=A("\u25A0","x"),at=A("\u25B2","x"),Se=A("\u25C7","o"),E=A("\u2502","|"),N=A("\u2514","\u2014"),ot=A("\u25CF",">"),Ee=A("\u25CB"," "),lt=A("\u25CF","\u2022"),ct=A("\u25C6","*"),ut=A("\u25B2","!"),ht=A("\u25A0","x"),_e=e=>{switch(e){case"initial":case"active":return c("cyan",ve);case"cancel":return c("red",nt);case"error":return c("yellow",at);case"submit":return c("green",Se);case"validating":return c("dim",ve)}},mt=e=>{switch(e){case"initial":case"active":return c("cyan",E);case"cancel":return c("red",E);case"error":return c("yellow",E);case"submit":return c("green",E)}};function dt(e,t){const r=[`${t?`${c("cyan",E)} `:""}${e.join(" \u2022 ")}`];return t&&r.push(c("cyan",N)),r}const Ie=(e,t,r,i,n,l=!1)=>{let a=t,o=0;if(l)for(let s=i-1;s>=r;s--){const u=e[s];if(u&&(a-=u.length),o++,a<=n)break}else for(let s=r;s<i;s++){const u=e[s];if(u&&(a-=u.length),o++,a<=n)break}return{lineCount:a,removals:o}},ft=({cursor:e,options:t,style:r,output:i=process.stdout,maxItems:n=Number.POSITIVE_INFINITY,columnPadding:l=0,rowPadding:a=4})=>{const o=$e(i)-l,s=xe(i),u=c("dim","..."),d=Math.max(s-a,0),h=Math.max(Math.min(n,d),5);let m=0;e>=h-3&&(m=Math.max(Math.min(e-h+3,t.length-h),0));let b=h<t.length&&m>0,g=h<t.length&&m+h<t.length;const $=Math.min(m+h,t.length),_=[];let F=0;b&&F++,g&&F++;const T=m+(b?1:0),R=$-(g?1:0);for(let v=T;v<R;v++){const f=t[v],y=f?r(f,v===e):"",p=U(y,o,{hard:!0,trim:!1}).split(`
16
+ `);_.push(p),F+=p.length}if(F>d){let v=0,f=0,y=F;const p=e-T;let S=d;const B=()=>Ie(_,y,0,p,S),C=()=>Ie(_,y,p+1,_.length,S,!0);b?({lineCount:y,removals:v}=B(),y>S&&(g||(S-=1),{lineCount:y,removals:f}=C())):(g||(S-=1),{lineCount:y,removals:f}=C(),y>S&&(S-=1,{lineCount:y,removals:v}=B())),v>0&&(b=!0,_.splice(0,v)),f>0&&(g=!0,_.splice(_.length-f,f))}const I=[];b&&I.push(u);for(const v of _)for(const f of v)I.push(f);return g&&I.push(u),I};`${c("dim","\u2191/\u2193")}`,`${c("dim","Space:")}`,`${c("dim","Enter:")}`;const L={message:(e=[],{symbol:t=c("gray",E),secondarySymbol:r=c("gray",E),output:i=process.stdout,spacing:n=1,withGuide:l}={})=>{const a=[],o=l??P.withGuide,s=o?r:"",u=o?`${t} `:"",d=o?`${r} `:"";for(let m=0;m<n;m++)a.push(s);const h=Array.isArray(e)?e:e.split(`
17
+ `);if(h.length>0){const[m,...b]=h;m.length>0?a.push(`${u}${m}`):a.push(o?t:"");for(const g of b)g.length>0?a.push(`${d}${g}`):a.push(o?r:"")}i.write(`${a.join(`
18
18
  `)}
19
- `)},info:(e,t)=>{W.message(e,{...t,symbol:l("blue",pt)})},success:(e,t)=>{W.message(e,{...t,symbol:l("green",gt)})},step:(e,t)=>{W.message(e,{...t,symbol:l("green",Ce)})},warn:(e,t)=>{W.message(e,{...t,symbol:l("yellow",bt)})},warning:(e,t)=>{W.warn(e,t)},error:(e,t)=>{W.message(e,{...t,symbol:l("red",yt)})}},vt=(e="",t)=>{const r=process.stdout,i=`${l("gray",U)} `;r.write(`${i}${l("red",e)}
19
+ `)},info:(e,t)=>{L.message(e,{...t,symbol:c("blue",lt)})},success:(e,t)=>{L.message(e,{...t,symbol:c("green",ct)})},step:(e,t)=>{L.message(e,{...t,symbol:c("green",Se)})},warn:(e,t)=>{L.message(e,{...t,symbol:c("yellow",ut)})},warning:(e,t)=>{L.warn(e,t)},error:(e,t)=>{L.message(e,{...t,symbol:c("red",ht)})}},pt=(e="",t)=>{const r=process.stdout,i=`${c("gray",N)} `;r.write(`${i}${c("red",e)}
20
20
 
21
- `)},St=(e="",t)=>{const r=process.stdout,i=`${l("gray",v)}
22
- ${l("gray",U)} `;r.write(`${i}${e}
21
+ `)},gt=(e="",t)=>{const r=process.stdout,i=`${c("gray",E)}
22
+ ${c("gray",N)} `;r.write(`${i}${e}
23
23
 
24
- `)},Et=[`${l("dim","\u2191/\u2193")} to navigate`,`${l("dim","Enter:")} confirm`],Z=(e,t)=>e.includes(`
24
+ `)},bt=[`${c("dim","\u2191/\u2193")} to navigate`,`${c("dim","Enter:")} confirm`],H=(e,t)=>e.includes(`
25
25
  `)?e.split(`
26
26
  `).map(r=>t(r)).join(`
27
- `):t(e),oe=e=>{const t=(i,n)=>{if(i===void 0)return"";const c=i.label??String(i.value);switch(n){case"disabled":return`${l("gray",Te)} ${Z(c,a=>l("gray",a))}${i.hint?` ${l("dim",`(${i.hint??"disabled"})`)}`:""}`;case"selected":return`${Z(c,a=>l("dim",a))}`;case"active":return`${l("green",ft)} ${c}${i.hint?` ${l("dim",`(${i.hint})`)}`:""}`;case"cancelled":return`${Z(c,a=>l(["strikethrough","dim"],a))}`;default:return`${l("dim",Te)} ${Z(c,a=>l("dim",a))}`}},r=e.showInstructions??!0;return new ct({options:e.options,signal:e.signal,input:e.input,output:e.output,initialValue:e.initialValue,render(){const i=e.withGuide??V.withGuide,n=`${Re(this.state)} `,c=`${$t(this.state)} `,a=ae(e.output,e.message,c,n),o=`${i?`${l("gray",v)}
27
+ `):t(e),re=e=>{const t=(i,n)=>{if(i===void 0)return"";const l=i.label??String(i.value);switch(n){case"disabled":return`${c("gray",Ee)} ${H(l,a=>c("gray",a))}${i.hint?` ${c("dim",`(${i.hint??"disabled"})`)}`:""}`;case"selected":return`${H(l,a=>c("dim",a))}`;case"active":return`${c("green",ot)} ${l}${i.hint?` ${c("dim",`(${i.hint})`)}`:""}`;case"cancelled":return`${H(l,a=>c(["strikethrough","dim"],a))}`;default:return`${c("dim",Ee)} ${H(l,a=>c("dim",a))}`}},r=e.showInstructions??!0;return new tt({options:e.options,signal:e.signal,input:e.input,output:e.output,initialValue:e.initialValue,render(){const i=e.withGuide??P.withGuide,n=`${_e(this.state)} `,l=`${mt(this.state)} `,a=te(e.output,e.message,l,n),o=`${i?`${c("gray",E)}
28
28
  `:""}${a}
29
- `;switch(this.state){case"submit":{const s=i?`${l("gray",v)} `:"",u=ae(e.output,t(this.options[this.cursor],"selected"),s);return`${o}${u}`}case"cancel":{const s=i?`${l("gray",v)} `:"",u=ae(e.output,t(this.options[this.cursor],"cancelled"),s);return`${o}${u}${i?`
30
- ${l("gray",v)}`:""}`}default:{const s=i?`${l("cyan",v)} `:"",u=o.split(`
31
- `).length,d=r?xt(Et,i):i?[l("cyan",U)]:[],h=d.join(`
32
- `),m=d.length+1;return`${o}${s}${wt({output:e.output,cursor:this.cursor,options:this.options,maxItems:e.maxItems,columnPadding:s.length,rowPadding:u+m,style:(p,f)=>t(p,p.disabled?"disabled":f?"active":"inactive")}).join(`
29
+ `;switch(this.state){case"submit":{const s=i?`${c("gray",E)} `:"",u=te(e.output,t(this.options[this.cursor],"selected"),s);return`${o}${u}`}case"cancel":{const s=i?`${c("gray",E)} `:"",u=te(e.output,t(this.options[this.cursor],"cancelled"),s);return`${o}${u}${i?`
30
+ ${c("gray",E)}`:""}`}default:{const s=i?`${c("cyan",E)} `:"",u=o.split(`
31
+ `).length,d=r?dt(bt,i):i?[c("cyan",N)]:[],h=d.join(`
32
+ `),m=d.length+1;return`${o}${s}${ft({output:e.output,cursor:this.cursor,options:this.options,maxItems:e.maxItems,columnPadding:s.length,rowPadding:u+m,style:(b,g)=>t(b,b.disabled?"disabled":g?"active":"inactive")}).join(`
33
33
  ${s}`)}
34
34
  ${h}
35
- `}}}}).prompt()};`${l("gray",v)}`;const ke=e=>new lt({validate:e.validate,placeholder:e.placeholder,defaultValue:e.defaultValue,initialValue:e.initialValue,output:e.output,signal:e.signal,input:e.input,render(){const t=e?.withGuide??V.withGuide,r=`${`${t?`${l("gray",v)}
36
- `:""}${Re(this.state)} `}${e.message}
37
- `,i=e.placeholder&&e.placeholder.length>0?l("inverse",e.placeholder[0])+l("dim",e.placeholder.slice(1)):l(["inverse","hidden"],"_"),n=this.userInput?this.userInputWithCursor:i,c=this.value??"";switch(this.state){case"validating":{const a=t?`${l("cyan",v)} `:"",o=t?l("cyan",U):"",s=l("dim",n),u=l("dim","Validating...");return`${r}${a}${s}
35
+ `}}}}).prompt()};`${c("gray",E)}`;const Fe=e=>new rt({validate:e.validate,placeholder:e.placeholder,defaultValue:e.defaultValue,initialValue:e.initialValue,output:e.output,signal:e.signal,input:e.input,render(){const t=e?.withGuide??P.withGuide,r=`${`${t?`${c("gray",E)}
36
+ `:""}${_e(this.state)} `}${e.message}
37
+ `,i=e.placeholder&&e.placeholder.length>0?c("inverse",e.placeholder[0])+c("dim",e.placeholder.slice(1)):c(["inverse","hidden"],"_"),n=this.userInput?this.userInputWithCursor:i,l=this.value??"";switch(this.state){case"validating":{const a=t?`${c("cyan",E)} `:"",o=t?c("cyan",N):"",s=c("dim",n),u=c("dim","Validating...");return`${r}${a}${s}
38
38
  ${o} ${u}
39
- `}case"error":{const a=this.error?` ${l("yellow",this.error)}`:"",o=t?`${l("yellow",v)} `:"",s=t?l("yellow",U):"";return`${r.trim()}
39
+ `}case"error":{const a=this.error?` ${c("yellow",this.error)}`:"",o=t?`${c("yellow",E)} `:"",s=t?c("yellow",N):"";return`${r.trim()}
40
40
  ${o}${n}
41
41
  ${s}${a}
42
- `}case"submit":{const a=c?`${t?" ":""}${l("dim",c)}`:"",o=t?l("gray",v):"";return`${r}${o}${a}`}case"cancel":{const a=c?` ${l(["strikethrough","dim"],c)}`:"",o=t?l("gray",v):"";return`${r}${o}${a}${c.trim()?`
43
- ${o}`:""}`}default:{const a=t?`${l("cyan",v)} `:"",o=t?l("cyan",U):"";return`${r}${a}${n}
42
+ `}case"submit":{const a=l?`${t?" ":""}${c("dim",l)}`:"",o=t?c("gray",E):"";return`${r}${o}${a}`}case"cancel":{const a=l?` ${c(["strikethrough","dim"],l)}`:"",o=t?c("gray",E):"";return`${r}${o}${a}${l.trim()?`
43
+ ${o}`:""}`}default:{const a=t?`${c("cyan",E)} `:"",o=t?c("cyan",N):"";return`${r}${a}${n}
44
44
  ${o}
45
- `}}}}).prompt();function ce(e){return e==null?[]:Array.isArray(e)?e:[e]}function _t(e,t,r,i){var n,c=e[t],a=~i.string.indexOf(t)?r==null||r===!0?"":String(r):typeof r=="boolean"?r:~i.boolean.indexOf(t)?r==="false"?!1:r==="true"||(e._.push((n=+r,n*0===0?n:r)),!!r):(n=+r,n*0===0?n:r);e[t]=c==null?a:Array.isArray(c)?c.concat(a):[c,a]}function It(e,t){e=e||[],t=t||{};var r,i,n,c,a,o={_:[]},s=0,u=0,d=0,h=e.length;const m=t.alias!==void 0,p=t.unknown!==void 0,f=t.default!==void 0;if(t.alias=t.alias||{},t.string=ce(t.string),t.boolean=ce(t.boolean),m)for(r in t.alias)for(i=t.alias[r]=ce(t.alias[r]),s=0;s<i.length;s++)(t.alias[i[s]]=i.concat(r)).splice(s,1);for(s=t.boolean.length;s-- >0;)for(i=t.alias[t.boolean[s]]||[],u=i.length;u-- >0;)t.boolean.push(i[u]);for(s=t.string.length;s-- >0;)for(i=t.alias[t.string[s]]||[],u=i.length;u-- >0;)t.string.push(i[u]);if(f){for(r in t.default)if(c=typeof t.default[r],i=t.alias[r]=t.alias[r]||[],t[c]!==void 0)for(t[c].push(r),s=0;s<i.length;s++)t[c].push(i[s])}const b=p?Object.keys(t.alias):[];for(s=0;s<h;s++){if(n=e[s],n==="--"){o._=o._.concat(e.slice(++s));break}for(u=0;u<n.length&&n.charCodeAt(u)===45;u++);if(u===0)o._.push(n);else if(n.substring(u,u+3)==="no-"){if(c=n.substring(u+3),p&&!~b.indexOf(c))return t.unknown(n);o[c]=!1}else{for(d=u+1;d<n.length&&n.charCodeAt(d)!==61;d++);for(c=n.substring(u,d),a=n.substring(++d)||s+1===h||(""+e[s+1]).charCodeAt(0)===45||e[++s],i=u===2?[c]:c,d=0;d<i.length;d++){if(c=i[d],p&&!~b.indexOf(c))return t.unknown("-".repeat(u)+c);_t(o,c,d+1<i.length||a,t)}}}if(f)for(r in t.default)o[r]===void 0&&(o[r]=t.default[r]);if(m)for(r in o)for(i=t.alias[r]||[];i.length>0;)o[i.shift()]=o[r];return o}var Q={exports:{}},je;function Ft(){if(je)return Q.exports;je=1;let e=process||{},t=e.argv||[],r=e.env||{},i=!(r.NO_COLOR||t.includes("--no-color"))&&(!!r.FORCE_COLOR||t.includes("--color")||e.platform==="win32"||(e.stdout||{}).isTTY&&r.TERM!=="dumb"||!!r.CI),n=(o,s,u=o)=>d=>{let h=""+d,m=h.indexOf(s,o.length);return~m?o+c(h,s,u,m)+s:o+h+s},c=(o,s,u,d)=>{let h="",m=0;do h+=o.substring(m,d)+u,m=d+s.length,d=o.indexOf(s,m);while(~d);return h+o.substring(m)},a=(o=i)=>{let s=o?n:()=>String;return{isColorSupported:o,reset:s("\x1B[0m","\x1B[0m"),bold:s("\x1B[1m","\x1B[22m","\x1B[22m\x1B[1m"),dim:s("\x1B[2m","\x1B[22m","\x1B[22m\x1B[2m"),italic:s("\x1B[3m","\x1B[23m"),underline:s("\x1B[4m","\x1B[24m"),inverse:s("\x1B[7m","\x1B[27m"),hidden:s("\x1B[8m","\x1B[28m"),strikethrough:s("\x1B[9m","\x1B[29m"),black:s("\x1B[30m","\x1B[39m"),red:s("\x1B[31m","\x1B[39m"),green:s("\x1B[32m","\x1B[39m"),yellow:s("\x1B[33m","\x1B[39m"),blue:s("\x1B[34m","\x1B[39m"),magenta:s("\x1B[35m","\x1B[39m"),cyan:s("\x1B[36m","\x1B[39m"),white:s("\x1B[37m","\x1B[39m"),gray:s("\x1B[90m","\x1B[39m"),bgBlack:s("\x1B[40m","\x1B[49m"),bgRed:s("\x1B[41m","\x1B[49m"),bgGreen:s("\x1B[42m","\x1B[49m"),bgYellow:s("\x1B[43m","\x1B[49m"),bgBlue:s("\x1B[44m","\x1B[49m"),bgMagenta:s("\x1B[45m","\x1B[49m"),bgCyan:s("\x1B[46m","\x1B[49m"),bgWhite:s("\x1B[47m","\x1B[49m"),blackBright:s("\x1B[90m","\x1B[39m"),redBright:s("\x1B[91m","\x1B[39m"),greenBright:s("\x1B[92m","\x1B[39m"),yellowBright:s("\x1B[93m","\x1B[39m"),blueBright:s("\x1B[94m","\x1B[39m"),magentaBright:s("\x1B[95m","\x1B[39m"),cyanBright:s("\x1B[96m","\x1B[39m"),whiteBright:s("\x1B[97m","\x1B[39m"),bgBlackBright:s("\x1B[100m","\x1B[49m"),bgRedBright:s("\x1B[101m","\x1B[49m"),bgGreenBright:s("\x1B[102m","\x1B[49m"),bgYellowBright:s("\x1B[103m","\x1B[49m"),bgBlueBright:s("\x1B[104m","\x1B[49m"),bgMagentaBright:s("\x1B[105m","\x1B[49m"),bgCyanBright:s("\x1B[106m","\x1B[49m"),bgWhiteBright:s("\x1B[107m","\x1B[49m")}};return Q.exports=a(),Q.exports.createColors=a,Q.exports}var Ct=Ft();const Tt=rt(Ct),{cyan:Rt,magenta:At,yellow:kt}=Tt,z=[{name:"engine",display:"Engine",description:"with the PlayCanvas Engine API directly",color:kt},{name:"react",display:"React",description:"with @playcanvas/react",color:Rt},{name:"web-components",display:"Web Components",description:"with @playcanvas/web-components",color:At}],Oe={physics:{engine:["assets"],react:["react"],"web-components":["assets"]}},G=[{name:"spinning-cube",display:"Spinning Cube",category:"Basics",description:"a rotating cube and a light"},{name:"interactive-sphere",display:"Interactive Sphere",category:"Basics",description:"orbit controls, a grid and pointer picking"},{name:"model-viewer",display:"Model Viewer",category:"Viewers",description:"a glTF model, orbit controls and a procedural sky"},{name:"splat-viewer",display:"Splat Viewer",category:"Viewers",description:"a Gaussian splat and orbit controls"},{name:"product-configurator",display:"Product Configurator",category:"Viewers",description:"product variants, materials and orbit controls"},{name:"physics-playground",display:"Physics Playground",category:"Games",description:"rigid bodies, collisions, spawning and reset",features:["physics"]},{name:"first-person-controller",display:"First-Person Controller",category:"Games",description:"first-person movement, mouse look and jumping",features:["physics"]},{name:"third-person-controller",display:"Third-Person Controller",category:"Games",description:"an animated character, follow camera and locomotion",features:["physics"]},{name:"sprite-game",display:"Sprite Game",category:"Games",description:"an orthographic camera, sprite animation and input"},{name:"web-lens",display:"Snapchat Web Lens",category:"Games",description:"a portrait game with Snapchat leaderboards, packaged for upload"},{name:"scene-editor",display:"Scene Editor",category:"Tools",description:"selection and translate, rotate and scale gizmos"},{name:"vr-starter",display:"VR Starter",category:"XR",description:"immersive VR, controllers and locomotion"},{name:"ar-placement",display:"AR Placement",category:"XR",description:"mobile AR, hit testing and object placement"}],jt=async({argFormat:e,yes:t,cancel:r})=>{if(e&&z.some(n=>n.name===e))return e;if(e&&(!process.stdout.isTTY||t))throw new Error(`Unknown format: ${e}. Choose from: ${z.map(n=>n.name).join(", ")}`);if(t)return z[0].name;const i=await oe({message:e?`"${e}" isn't a valid format. Please choose from below: `:"Select a format:",options:z.map(n=>({label:n.color(n.display),value:n.name,hint:n.description}))});return H(i)&&r(),i},Ot=async({argStarter:e,yes:t,cancel:r})=>{if(e&&G.some(n=>n.name===e))return e;if(!process.stdout.isTTY||t){if(!e)return G[0].name;throw new Error(`Unknown starter: ${e}. Choose from: ${G.map(n=>n.name).join(", ")}`)}const i=await oe({message:e?`"${e}" isn't a valid starter. Please choose from below: `:"Select a starter:",initialValue:G[0].name,options:G.map(n=>({label:n.display,value:n.name,hint:`${n.category} \xB7 ${n.description}`}))});return H(i)&&r(),i},Be=e=>/^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(e),le=e=>e.trim().toLowerCase().replace(/\s+/g,"-").replace(/^[._]/,"").replace(/[^a-z\d\-~]+/g,"-"),Bt=async({targetDir:e,yes:t,cancel:r})=>{let i=y.basename(y.resolve(e));if(!Be(i)){if(t)return le(i);const n=await ke({message:"Package name:",defaultValue:le(i),placeholder:le(i),validate:c=>{if(!c||!Be(c))return"Invalid package.json name"}});if(H(n))return r();i=n}return i},ee=e=>e.trim().replace(/\/+$/g,""),Mt=e=>{const t=$.readdirSync(e);return t.length===0||t.length===1&&t[0]===".git"},Pt=e=>{if($.existsSync(e))for(const t of $.readdirSync(e))t!==".git"&&$.rmSync(y.resolve(e,t),{recursive:!0,force:!0})},Lt=async({argTargetDir:e,defaultTargetDir:t,yes:r,cancel:i})=>{let n=e?ee(String(e)):void 0;if(!n&&r)return t;if(!n){const c=await ke({message:"Project name:",defaultValue:t,placeholder:t,validate:a=>{if(a&&!ee(a))return"Invalid project name"}});H(c)&&i(),n=ee(c)}return n},Nt=async({targetDir:e,argOverwrite:t,yes:r,cancel:i})=>{if($.existsSync(e)&&!Mt(e)){if(r&&!t)throw new Error(`Target directory "${e}" is not empty. Pass --overwrite to remove its contents.`);const n=t?"yes":await oe({message:(e==="."?"Current directory":`Target directory "${e}"`)+" is not empty. Please choose how to proceed:",options:[{label:"Cancel operation",value:"no"},{label:"Remove existing files and continue",value:"yes"},{label:"Ignore files and continue",value:"ignore"}]});if(H(n))return i();switch(n){case"yes":Pt(e);break;case"no":i();return}}},Dt=["scripts","dependencies","devDependencies","peerDependencies","engines"],Me="## Prerequisites",Wt={engine:"src/main.ts",react:"src/App.tsx","web-components":"src/main.ts"},Vt=e=>{const{cwd:t,targetDir:r,format:i,starter:n,packageName:c,skills:a,renameFiles:o}=e,s=y.resolve(t,r);$.mkdirSync(s,{recursive:!0});const u=process.env.npm_config_user_agent?.split("/")[0]??"npm";W.step(`Creating project in ${s}...`);const d=De(import.meta.url),h=y.dirname(d),m=[y.resolve(h,"../templates"),y.resolve(h,"../../templates")].find(g=>$.existsSync(y.join(g,i)));if(!m)throw new Error(`Format directory not found for: ${i}`);const p=y.join(m,i);for(const g of z)for(const A of G){const C=y.join(m,g.name,A.name),N=Wt[g.name];if(!N||!$.existsSync(y.join(C,N)))throw new Error(`Incomplete starter matrix: ${g.name}/${A.name}`);for(const K of A.features??[]){const ue=Oe[K]?.[g.name];if(!ue?.length||ue.some(Pe=>!$.existsSync(y.join(m,"_features",K,Pe))))throw new Error(`Incomplete feature matrix: ${K}/${g.name}`)}}const f=G.find(g=>g.name===n);if(!f)throw new Error(`Starter not found: ${n}`);const b=y.join(m,"_shared",n),F=y.join(p,"base"),T=y.join(p,n),O=(f.features??[]).flatMap(g=>Oe[g][i].map(A=>y.join(m,"_features",g,A))),M=[b,F,...O,T],k=M.map(g=>{const A=y.join(g,"package.json");return $.existsSync(A)?JSON.parse($.readFileSync(A,"utf-8")):{}}),w=[k[1],k[0],...k.slice(2)];if(!$.existsSync(T))throw new Error(`Starter directory not found: ${i}/${n}`);for(const g of M)$.existsSync(g)&&$.cpSync(g,s,{recursive:!0});const S=y.join(b,"README.md"),x=y.join(s,"README.md");$.existsSync(S)&&$.writeFileSync(x,$.readFileSync(x,"utf8").replace(Me,`${$.readFileSync(S,"utf8").trimEnd()}
45
+ `}}}}).prompt();function se(e){return e==null?[]:Array.isArray(e)?e:[e]}function yt(e,t,r,i){var n,l=e[t],a=~i.string.indexOf(t)?r==null||r===!0?"":String(r):typeof r=="boolean"?r:~i.boolean.indexOf(t)?r==="false"?!1:r==="true"||(e._.push((n=+r,n*0===0?n:r)),!!r):(n=+r,n*0===0?n:r);e[t]=l==null?a:Array.isArray(l)?l.concat(a):[l,a]}function $t(e,t){e=e||[],t=t||{};var r,i,n,l,a,o={_:[]},s=0,u=0,d=0,h=e.length;const m=t.alias!==void 0,b=t.unknown!==void 0,g=t.default!==void 0;if(t.alias=t.alias||{},t.string=se(t.string),t.boolean=se(t.boolean),m)for(r in t.alias)for(i=t.alias[r]=se(t.alias[r]),s=0;s<i.length;s++)(t.alias[i[s]]=i.concat(r)).splice(s,1);for(s=t.boolean.length;s-- >0;)for(i=t.alias[t.boolean[s]]||[],u=i.length;u-- >0;)t.boolean.push(i[u]);for(s=t.string.length;s-- >0;)for(i=t.alias[t.string[s]]||[],u=i.length;u-- >0;)t.string.push(i[u]);if(g){for(r in t.default)if(l=typeof t.default[r],i=t.alias[r]=t.alias[r]||[],t[l]!==void 0)for(t[l].push(r),s=0;s<i.length;s++)t[l].push(i[s])}const $=b?Object.keys(t.alias):[];for(s=0;s<h;s++){if(n=e[s],n==="--"){o._=o._.concat(e.slice(++s));break}for(u=0;u<n.length&&n.charCodeAt(u)===45;u++);if(u===0)o._.push(n);else if(n.substring(u,u+3)==="no-"){if(l=n.substring(u+3),b&&!~$.indexOf(l))return t.unknown(n);o[l]=!1}else{for(d=u+1;d<n.length&&n.charCodeAt(d)!==61;d++);for(l=n.substring(u,d),a=n.substring(++d)||s+1===h||(""+e[s+1]).charCodeAt(0)===45||e[++s],i=u===2?[l]:l,d=0;d<i.length;d++){if(l=i[d],b&&!~$.indexOf(l))return t.unknown("-".repeat(u)+l);yt(o,l,d+1<i.length||a,t)}}}if(g)for(r in t.default)o[r]===void 0&&(o[r]=t.default[r]);if(m)for(r in o)for(i=t.alias[r]||[];i.length>0;)o[i.shift()]=o[r];return o}var z={exports:{}},Ce;function xt(){if(Ce)return z.exports;Ce=1;let e=process||{},t=e.argv||[],r=e.env||{},i=!(r.NO_COLOR||t.includes("--no-color"))&&(!!r.FORCE_COLOR||t.includes("--color")||e.platform==="win32"||(e.stdout||{}).isTTY&&r.TERM!=="dumb"||!!r.CI),n=(o,s,u=o)=>d=>{let h=""+d,m=h.indexOf(s,o.length);return~m?o+l(h,s,u,m)+s:o+h+s},l=(o,s,u,d)=>{let h="",m=0;do h+=o.substring(m,d)+u,m=d+s.length,d=o.indexOf(s,m);while(~d);return h+o.substring(m)},a=(o=i)=>{let s=o?n:()=>String;return{isColorSupported:o,reset:s("\x1B[0m","\x1B[0m"),bold:s("\x1B[1m","\x1B[22m","\x1B[22m\x1B[1m"),dim:s("\x1B[2m","\x1B[22m","\x1B[22m\x1B[2m"),italic:s("\x1B[3m","\x1B[23m"),underline:s("\x1B[4m","\x1B[24m"),inverse:s("\x1B[7m","\x1B[27m"),hidden:s("\x1B[8m","\x1B[28m"),strikethrough:s("\x1B[9m","\x1B[29m"),black:s("\x1B[30m","\x1B[39m"),red:s("\x1B[31m","\x1B[39m"),green:s("\x1B[32m","\x1B[39m"),yellow:s("\x1B[33m","\x1B[39m"),blue:s("\x1B[34m","\x1B[39m"),magenta:s("\x1B[35m","\x1B[39m"),cyan:s("\x1B[36m","\x1B[39m"),white:s("\x1B[37m","\x1B[39m"),gray:s("\x1B[90m","\x1B[39m"),bgBlack:s("\x1B[40m","\x1B[49m"),bgRed:s("\x1B[41m","\x1B[49m"),bgGreen:s("\x1B[42m","\x1B[49m"),bgYellow:s("\x1B[43m","\x1B[49m"),bgBlue:s("\x1B[44m","\x1B[49m"),bgMagenta:s("\x1B[45m","\x1B[49m"),bgCyan:s("\x1B[46m","\x1B[49m"),bgWhite:s("\x1B[47m","\x1B[49m"),blackBright:s("\x1B[90m","\x1B[39m"),redBright:s("\x1B[91m","\x1B[39m"),greenBright:s("\x1B[92m","\x1B[39m"),yellowBright:s("\x1B[93m","\x1B[39m"),blueBright:s("\x1B[94m","\x1B[39m"),magentaBright:s("\x1B[95m","\x1B[39m"),cyanBright:s("\x1B[96m","\x1B[39m"),whiteBright:s("\x1B[97m","\x1B[39m"),bgBlackBright:s("\x1B[100m","\x1B[49m"),bgRedBright:s("\x1B[101m","\x1B[49m"),bgGreenBright:s("\x1B[102m","\x1B[49m"),bgYellowBright:s("\x1B[103m","\x1B[49m"),bgBlueBright:s("\x1B[104m","\x1B[49m"),bgMagentaBright:s("\x1B[105m","\x1B[49m"),bgCyanBright:s("\x1B[106m","\x1B[49m"),bgWhiteBright:s("\x1B[107m","\x1B[49m")}};return z.exports=a(),z.exports.createColors=a,z.exports}var wt=xt();const vt=Ye(wt),{cyan:St,magenta:Et,yellow:_t}=vt,J=[{name:"engine",display:"Engine",description:"with the PlayCanvas Engine API directly",color:_t},{name:"react",display:"React",description:"with @playcanvas/react",color:St},{name:"web-components",display:"Web Components",description:"with @playcanvas/web-components",color:Et}],It={physics:{engine:["assets"],react:["react"],"web-components":["assets"]}},D=[{name:"spinning-cube",display:"Spinning Cube",category:"Basics",description:"a rotating cube and a light"},{name:"interactive-sphere",display:"Interactive Sphere",category:"Basics",description:"orbit controls, a grid and pointer picking"},{name:"model-viewer",display:"Model Viewer",category:"Viewers",description:"a glTF model, orbit controls and a procedural sky"},{name:"splat-viewer",display:"Splat Viewer",category:"Viewers",description:"a Gaussian splat and orbit controls"},{name:"product-configurator",display:"Product Configurator",category:"Viewers",description:"product variants, materials and orbit controls"},{name:"physics-playground",display:"Physics Playground",category:"Games",description:"rigid bodies, collisions, spawning and reset",features:["physics"]},{name:"first-person-controller",display:"First-Person Controller",category:"Games",description:"first-person movement, mouse look and jumping",features:["physics"]},{name:"third-person-controller",display:"Third-Person Controller",category:"Games",description:"an animated character, follow camera and locomotion",features:["physics"]},{name:"sprite-game",display:"Sprite Game",category:"Games",description:"an orthographic camera, sprite animation and input"},{name:"web-lens",display:"Snapchat Web Lens",category:"Games",description:"a portrait game with Snapchat leaderboards, packaged for upload"},{name:"scene-editor",display:"Scene Editor",category:"Tools",description:"selection and translate, rotate and scale gizmos"},{name:"vr-starter",display:"VR Starter",category:"XR",description:"immersive VR, controllers and locomotion"},{name:"ar-placement",display:"AR Placement",category:"XR",description:"mobile AR, hit testing and object placement"}],Ft=async({argFormat:e,yes:t,cancel:r})=>{if(e&&J.some(n=>n.name===e))return e;if(e&&t)throw new Error(`Unknown format: ${e}. Choose from: ${J.map(n=>n.name).join(", ")}`);if(t)return J[0].name;const i=await re({message:e?`"${e}" isn't a valid format. Please choose from below: `:"Select a format:",options:J.map(n=>({label:n.color(n.display),value:n.name,hint:n.description}))});return W(i)&&r(),i},Ct=async({argStarter:e,yes:t,cancel:r})=>{if(e&&D.some(n=>n.name===e))return e;if(t){if(!e)return D[0].name;throw new Error(`Unknown starter: ${e}. Choose from: ${D.map(n=>n.name).join(", ")}`)}const i=await re({message:e?`"${e}" isn't a valid starter. Please choose from below: `:"Select a starter:",initialValue:D[0].name,options:D.map(n=>({label:n.display,value:n.name,hint:`${n.category} \xB7 ${n.description}`}))});return W(i)&&r(),i},Te=e=>/^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(e),ie=e=>e.trim().toLowerCase().replace(/\s+/g,"-").replace(/^[._]/,"").replace(/[^a-z\d\-~]+/g,"-"),Tt=async({targetDir:e,yes:t,cancel:r})=>{let i=x.basename(x.resolve(e));if(!Te(i)){if(t)return ie(i);const n=await Fe({message:"Package name:",defaultValue:ie(i),placeholder:ie(i),validate:l=>{if(!l||!Te(l))return"Invalid package.json name"}});if(W(n))return r();i=n}return i},Y=e=>e.trim().replace(/\/+$/g,""),Rt=e=>{const t=w.readdirSync(e);return t.length===0||t.length===1&&t[0]===".git"},At=e=>{if(w.existsSync(e))for(const t of w.readdirSync(e))t!==".git"&&w.rmSync(x.resolve(e,t),{recursive:!0,force:!0})},kt=async({argTargetDir:e,defaultTargetDir:t,yes:r,cancel:i})=>{let n=e?Y(String(e)):void 0;if(!n&&r)return t;if(!n){const l=await Fe({message:"Project name:",defaultValue:t,placeholder:t,validate:a=>{if(a&&!Y(a))return"Invalid project name"}});W(l)&&i(),n=Y(l)}return n},jt=async({targetDir:e,argOverwrite:t,yes:r,cancel:i})=>{if(w.existsSync(e)&&!Rt(e)){if(r&&!t)throw new Error(`Target directory "${e}" is not empty. Pass --overwrite to remove its contents.`);const n=t?"yes":await re({message:(e==="."?"Current directory":`Target directory "${e}"`)+" is not empty. Please choose how to proceed:",options:[{label:"Cancel operation",value:"no"},{label:"Remove existing files and continue",value:"yes"},{label:"Ignore files and continue",value:"ignore"}]});if(W(n))return i();switch(n){case"yes":At(e);break;case"no":i();return}}},Ot=["scripts","dependencies","devDependencies","peerDependencies","engines"],Re="## Prerequisites",Bt=e=>{const{cwd:t,targetDir:r,format:i,starter:n,packageName:l,skills:a,renameFiles:o}=e,s=x.resolve(t,r);w.mkdirSync(s,{recursive:!0});const u=process.env.npm_config_user_agent?.split("/")[0]??"npm";L.step(`Creating project in ${s}...`);const d=je(import.meta.url),h=x.dirname(d),m=e.templatesDir??[x.resolve(h,"../templates"),x.resolve(h,"../../templates")].find(f=>w.existsSync(x.join(f,i)));if(!m)throw new Error(`Format directory not found for: ${i}`);const b=D.find(f=>f.name===n);if(!b)throw new Error(`Starter not found: ${n}`);const g=x.join(m,"_shared",n),$=x.join(m,i,n);if(!w.existsSync($))throw new Error(`Starter directory not found: ${i}/${n}`);const _=[x.join(m,"_common"),x.join(m,i,"base"),g,...(b.features??[]).flatMap(f=>It[f][i].map(y=>x.join(m,"_features",f,y))),$].filter(f=>w.existsSync(f)),F=x.join(g,"README.md");for(const f of _){const y=x.join(f,"package.json");w.cpSync(f,s,{recursive:!0,filter:p=>p!==y&&p!==F})}if(w.existsSync(F)){const f=x.join(s,"README.md"),y=`${w.readFileSync(F,"utf8").trimEnd()}
46
46
 
47
- ${Me}`));for(const[g,A]of Object.entries(o)){const C=y.join(s,g);$.existsSync(C)&&$.renameSync(C,y.join(s,A))}const E=y.join(s,"package.json"),_=Object.assign({},...w);for(const g of Dt){const A=Object.assign({},...w.map(N=>N?.[g])),C=Object.entries(A).sort(([N],[K])=>N>K?1:-1);C.length?_[g]=Object.fromEntries(C):delete _[g]}if(_.name=c,$.writeFileSync(E,JSON.stringify(_,null,4)+`
48
- `),a){const g=[y.resolve(h,"../skills"),y.resolve(h,"../../skills")].find(C=>$.existsSync(C));if(!g)throw new Error("Skills directory not found");const A=$.readdirSync(g,{withFileTypes:!0}).filter(C=>C.isDirectory()).map(C=>C.name);for(const C of[".claude/skills",".agents/skills"])for(const N of A)$.cpSync(y.join(g,N),y.join(s,C,N),{recursive:!0});W.step("Added PlayCanvas agent skills (opt out with --no-skills)")}let R=`Project created. Now run:
49
- `;const I=y.isAbsolute(r)?s:y.relative(t,s);switch(s!==t&&(R+=`
50
- cd ${I.includes(" ")?`"${I}"`:I}`),u){case"yarn":R+=`
51
- yarn`,R+=`
52
- yarn dev`;break;default:R+=`
53
- ${u} install`,R+=`
54
- ${u} run dev`;break}St(R)},L=It(process.argv.slice(2),{alias:{b:"boilerplate",f:"format",h:"help",s:"starter",t:"template",y:"yes"},boolean:["help","overwrite","yes"],string:["format","starter","template","boilerplate"]}),Ut=process.cwd(),Gt=`Usage: npm create playcanvas@latest [OPTION]...
47
+ ${Re}`,p=w.readFileSync(f,"utf8").replace(Re,()=>y);w.writeFileSync(f,p)}for(const[f,y]of Object.entries(o)){const p=x.join(s,f);w.existsSync(p)&&w.renameSync(p,x.join(s,y))}const T=_.map(f=>x.join(f,"package.json")).filter(f=>w.existsSync(f)).map(f=>JSON.parse(w.readFileSync(f,"utf-8"))),R=Object.assign({},...T);for(const f of Ot){const y=Object.assign({},...T.map(S=>S[f])),p=Object.entries(y).sort(([S],[B])=>S>B?1:-1);p.length?R[f]=Object.fromEntries(p):delete R[f]}if(R.name=l,w.writeFileSync(x.join(s,"package.json"),JSON.stringify(R,null,4)+`
48
+ `),a){const f=[x.resolve(h,"../skills"),x.resolve(h,"../../skills")].find(p=>w.existsSync(p));if(!f)throw new Error("Skills directory not found");const y=w.readdirSync(f,{withFileTypes:!0}).filter(p=>p.isDirectory()).map(p=>p.name);for(const p of[".claude/skills",".agents/skills"])for(const S of y)w.cpSync(x.join(f,S),x.join(s,p,S),{recursive:!0});L.step("Added PlayCanvas agent skills (opt out with --no-skills)")}let I=`Project created. Now run:
49
+ `;const v=x.isAbsolute(r)?s:x.relative(t,s);switch(s!==t&&(I+=`
50
+ cd ${v.includes(" ")?`"${v}"`:v}`),u){case"yarn":I+=`
51
+ yarn`,I+=`
52
+ yarn dev`;break;default:I+=`
53
+ ${u} install`,I+=`
54
+ ${u} run dev`;break}gt(I)},j=$t(process.argv.slice(2),{alias:{b:"boilerplate",f:"format",h:"help",s:"starter",t:"template",y:"yes"},boolean:["help","overwrite","yes"],string:["format","starter","template","boilerplate"]}),Lt=process.cwd(),Mt=`Usage: npm create playcanvas@latest [OPTION]...
55
55
 
56
56
  Create a new PlayCanvas project with TypeScript.
57
57
  With no arguments, start the CLI in interactive mode.
@@ -63,4 +63,7 @@ Options:
63
63
  --no-skills omit the PlayCanvas agent skills
64
64
  -y, --yes skip the prompts and take the defaults
65
65
  -h, --help show help
66
- `,Kt={_gitignore:".gitignore",_npmrc:".npmrc"},Ht="playcanvas-project",zt=async()=>{const e=L._[0]?ee(String(L._[0])):void 0,t=L.format??L.template,r=L.starter??L.boilerplate,i=L.overwrite,n=L.yes;if(L.help){console.log(Gt);return}const c=()=>{vt("Operation cancelled"),process.exit(0)},a=await Lt({argTargetDir:e,defaultTargetDir:Ht,yes:n,cancel:c});await Nt({targetDir:a,argOverwrite:i,yes:n,cancel:c});const o=await Bt({targetDir:a,yes:n,cancel:c}),s=await jt({argFormat:t,yes:n,cancel:c}),u=await Ot({argStarter:r,yes:n,cancel:c}),d=L.skills??!0;Vt({cwd:Ut,targetDir:a,format:s,starter:u,packageName:o,skills:d,renameFiles:Kt})};zt().catch(e=>{console.error(e instanceof Error?e.message:e),process.exitCode=1});
66
+
67
+ Without a terminal, as when an AI agent or CI runs it, the CLI takes the
68
+ defaults for any option not passed, as --yes does.
69
+ `,Pt={_gitignore:".gitignore",_npmrc:".npmrc"},Nt="playcanvas-project",Dt=async()=>{const e=j._[0]?Y(String(j._[0])):void 0,t=j.format??j.template,r=j.starter??j.boilerplate,i=j.overwrite,n=!!(process.stdin.isTTY&&process.stdout.isTTY),l=j.yes||!n;if(j.help){console.log(Mt);return}!n&&!j.yes&&L.info("Not running in a terminal, so using the defaults for any option not passed");const a=()=>{pt("Operation cancelled"),process.exit(0)},o=await kt({argTargetDir:e,defaultTargetDir:Nt,yes:l,cancel:a});await jt({targetDir:o,argOverwrite:i,yes:l,cancel:a});const s=await Tt({targetDir:o,yes:l,cancel:a}),u=await Ft({argFormat:t,yes:l,cancel:a}),d=await Ct({argStarter:r,yes:l,cancel:a}),h=j.skills??!0;Bt({cwd:Lt,targetDir:o,format:u,starter:d,packageName:s,skills:h,renameFiles:Pt})};Dt().catch(e=>{console.error(e instanceof Error?e.message:e),process.exitCode=1});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-playcanvas",
3
- "version": "0.11.0",
3
+ "version": "0.11.1",
4
4
  "description": "Scaffold a PlayCanvas project",
5
5
  "keywords": [
6
6
  "playcanvas",
@@ -39,6 +39,7 @@
39
39
  "fmt:fix": "prettier --write .",
40
40
  "lint": "eslint .",
41
41
  "lint:fix": "eslint . --fix",
42
+ "test": "vitest run",
42
43
  "typecheck": "tsc --noEmit"
43
44
  },
44
45
  "devDependencies": {
@@ -49,7 +50,9 @@
49
50
  "mri": "^1.2.0",
50
51
  "picocolors": "^1.1.1",
51
52
  "prettier": "^3.9.10",
52
- "unbuild": "^3.6.1"
53
+ "unbuild": "^3.6.1",
54
+ "vite": "^8.3.5",
55
+ "vitest": "^5.0.5"
53
56
  },
54
57
  "engines": {
55
58
  "node": ">=22.23.2"
@@ -7,10 +7,13 @@ These files are copied from `playcanvas/engine` tag `v2.21.4` (commit
7
7
  They are a WebAssembly build of [ammo.js](https://github.com/kripken/ammo.js),
8
8
  distributed under the zlib license in `LICENSE`.
9
9
 
10
+ The asm.js fallback in that folder, `ammo.js`, is left out, so the starters
11
+ configure no fallback: every browser that runs them supports WebAssembly, and
12
+ Vite would copy the 2 MB file into every physics project's build.
13
+
10
14
  ## SHA-256
11
15
 
12
16
  ```text
13
- ef166d1315bc4a6441a8de341ecdf6ac4e7d69055caec65c523ed1a4e8e19b15 ammo.js
14
17
  5645b5a0c4f03be9d9d1ae604ffacd5e5e525310cfd1d0ed27474cdd1f34aab0 ammo.wasm.js
15
18
  a61b504d4a6ce6bb93bd843e0f61edb8115e7317f1b3462247031a83ddb25d09 ammo.wasm.wasm
16
19
  ```
@@ -1,9 +1,3 @@
1
- .full-bleed {
2
- width: 100vw;
3
- height: 100vh;
4
- overflow: hidden;
5
- }
6
-
7
1
  .counter {
8
2
  position: fixed;
9
3
  bottom: 22px;
@@ -32,7 +32,7 @@ Open <http://localhost:5173>. Edit the files under `src/` and save to see the sc
32
32
  | `npm run fmt` | Check formatting |
33
33
  | `npm run typecheck` | Run TypeScript checks |
34
34
 
35
- Run `npm run build` to generate a deployable static site in `dist/`.
35
+ Run `npm run build` to generate a deployable static site in `dist/`. Its paths are relative, so it runs from any folder, such as a GitHub Pages project site or an itch.io upload.
36
36
 
37
37
  ## Agent skills
38
38
 
@@ -2,6 +2,9 @@ import { defineConfig } from 'vite';
2
2
 
3
3
  // https://vite.dev/config/
4
4
  export default defineConfig({
5
+ // Relative URLs, so the build runs wherever it's served from: a domain root, a subpath such as
6
+ // GitHub Pages or itch.io, or a Snapchat Web Lens
7
+ base: './',
5
8
  plugins: [
6
9
  {
7
10
  // Dev only: install the PlayCanvas Inspector before the app starts (press ` to toggle)
@@ -21,9 +21,8 @@ import { addFirstPersonController } from './controller';
21
21
  import './starter.css';
22
22
 
23
23
  WasmModule.setConfig('Ammo', {
24
- glueUrl: '/ammo/ammo.wasm.js',
25
- wasmUrl: '/ammo/ammo.wasm.wasm',
26
- fallbackUrl: '/ammo/ammo.js'
24
+ glueUrl: './ammo/ammo.wasm.js',
25
+ wasmUrl: './ammo/ammo.wasm.wasm'
27
26
  });
28
27
  await new Promise<void>((resolve) => {
29
28
  WasmModule.getInstance('Ammo', () => resolve());
@@ -36,7 +36,7 @@ const assets = {
36
36
  envAtlas: new Asset(
37
37
  'env-atlas',
38
38
  'texture',
39
- { url: '/environment-map.png' },
39
+ { url: './environment-map.png' },
40
40
  {
41
41
  type: TEXTURETYPE_RGBP,
42
42
  mipmaps: false
@@ -1,12 +1,10 @@
1
- import './style.css';
2
1
  import { setupApp } from './App';
2
+ import './counter.css';
3
+ import './starter.css';
3
4
 
4
5
  let count = 0;
5
6
 
6
- document.querySelector<HTMLDivElement>('#root')!.innerHTML = `
7
- <canvas id="application-canvas"></canvas>
8
- <p id="counter" class="counter">Click count: ${count}</p>
9
- `;
7
+ document.body.insertAdjacentHTML('beforeend', `<p id="counter" class="counter">Click count: ${count}</p>`);
10
8
 
11
9
  const counterElement = document.getElementById('counter')!;
12
10
 
@@ -17,10 +17,10 @@ import {
17
17
  import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
18
18
  import { ProceduralSky } from 'playcanvas/scripts/esm/sky/procedural-sky.mjs';
19
19
 
20
- import './style.css';
20
+ import './starter.css';
21
21
 
22
- // Swap this for your own model - anything you drop in public/ is served from the site root
23
- const MODEL_URL = '/playcanvas-cube.glb';
22
+ // Swap this for your own model - files in public/ are served next to index.html, so use a ./ path
23
+ const MODEL_URL = './playcanvas-cube.glb';
24
24
 
25
25
  const canvas = document.getElementById('application-canvas') as HTMLCanvasElement;
26
26
 
@@ -30,9 +30,8 @@ const SCALES: [number, number, number][] = [
30
30
  ];
31
31
 
32
32
  WasmModule.setConfig('Ammo', {
33
- glueUrl: '/ammo/ammo.wasm.js',
34
- wasmUrl: '/ammo/ammo.wasm.wasm',
35
- fallbackUrl: '/ammo/ammo.js'
33
+ glueUrl: './ammo/ammo.wasm.js',
34
+ wasmUrl: './ammo/ammo.wasm.wasm'
36
35
  });
37
36
  await new Promise<void>((resolve) => {
38
37
  WasmModule.getInstance('Ammo', () => resolve());
@@ -13,7 +13,7 @@ import {
13
13
  createGraphicsDevice
14
14
  } from 'playcanvas';
15
15
 
16
- import './style.css';
16
+ import './starter.css';
17
17
 
18
18
  const canvas = document.getElementById('application-canvas') as HTMLCanvasElement;
19
19
 
@@ -16,7 +16,7 @@ import {
16
16
  } from 'playcanvas';
17
17
  import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
18
18
 
19
- import './style.css';
19
+ import './starter.css';
20
20
 
21
21
  // Hosted so the template stays small. Capture or edit your own splat at https://superspl.at, then
22
22
  // drop the .sog or .ply in public/ and point this at it instead
@@ -42,9 +42,8 @@ const PINE_LAYERS: [number, number, number][] = [
42
42
  ];
43
43
 
44
44
  WasmModule.setConfig('Ammo', {
45
- glueUrl: '/ammo/ammo.wasm.js',
46
- wasmUrl: '/ammo/ammo.wasm.wasm',
47
- fallbackUrl: '/ammo/ammo.js'
45
+ glueUrl: './ammo/ammo.wasm.js',
46
+ wasmUrl: './ammo/ammo.wasm.wasm'
48
47
  });
49
48
  await new Promise<void>((resolve) => {
50
49
  WasmModule.getInstance('Ammo', () => resolve());
@@ -32,7 +32,7 @@ Open <http://localhost:5173>. Edit the files under `src/` and save to see the sc
32
32
  | `npm run fmt` | Check formatting |
33
33
  | `npm run typecheck` | Run TypeScript checks |
34
34
 
35
- Run `npm run build` to generate a deployable static site in `dist/`.
35
+ Run `npm run build` to generate a deployable static site in `dist/`. Its paths are relative, so it runs from any folder, such as a GitHub Pages project site or an itch.io upload.
36
36
 
37
37
  ## Agent skills
38
38
 
@@ -3,6 +3,9 @@ import { defineConfig } from 'vite';
3
3
 
4
4
  // https://vite.dev/config/
5
5
  export default defineConfig({
6
+ // Relative URLs, so the build runs wherever it's served from: a domain root, a subpath such as
7
+ // GitHub Pages or itch.io, or a Snapchat Web Lens
8
+ base: './',
6
9
  plugins: [
7
10
  react(),
8
11
  {
@@ -1,19 +1,18 @@
1
1
  import { Application } from '@playcanvas/react';
2
2
  import { useState } from 'react';
3
3
 
4
- import './App.css';
4
+ import './counter.css';
5
5
  import Scene from './Scene';
6
+ import './starter.css';
6
7
 
7
8
  function App() {
8
9
  const [count, setCount] = useState(0);
9
10
 
10
11
  return (
11
12
  <>
12
- <div className="full-bleed">
13
- <Application className="playcanvas-app">
14
- <Scene onClick={() => setCount((count) => count + 1)} />
15
- </Application>
16
- </div>
13
+ <Application className="playcanvas-app">
14
+ <Scene onClick={() => setCount((count) => count + 1)} />
15
+ </Application>
17
16
  <p className="counter">Click count: {count}</p>
18
17
  </>
19
18
  );
@@ -18,7 +18,7 @@ function Scene({ onClick }: SceneProps) {
18
18
  const material = useMaterial({ diffuse });
19
19
 
20
20
  // Load the environment map
21
- const { asset: envMap } = useEnvAtlas('/environment-map.png');
21
+ const { asset: envMap } = useEnvAtlas('./environment-map.png');
22
22
 
23
23
  // Change the mouse cursor based on the hover state
24
24
  useEffect(() => {
@@ -5,8 +5,10 @@ import { TONEMAP_ACES2 } from 'playcanvas';
5
5
  import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
6
6
  import { ProceduralSky } from 'playcanvas/scripts/esm/sky/procedural-sky.mjs';
7
7
 
8
- // Swap this for your own model - anything you drop in public/ is served from the site root
9
- const MODEL_URL = '/playcanvas-cube.glb';
8
+ import './starter.css';
9
+
10
+ // Swap this for your own model - files in public/ are served next to index.html, so use a ./ path
11
+ const MODEL_URL = './playcanvas-cube.glb';
10
12
 
11
13
  function Model() {
12
14
  const { asset } = useModel(MODEL_URL);
@@ -4,6 +4,8 @@ import { useAppEvent } from '@playcanvas/react/hooks';
4
4
  import type { Entity as PcEntity } from 'playcanvas';
5
5
  import { useRef } from 'react';
6
6
 
7
+ import './starter.css';
8
+
7
9
  function Scene() {
8
10
  const cube = useRef<PcEntity>(null);
9
11
 
@@ -3,6 +3,8 @@ import { Camera, GSplat, Script } from '@playcanvas/react/components';
3
3
  import { useSplat } from '@playcanvas/react/hooks';
4
4
  import { CameraControls } from 'playcanvas/scripts/esm/camera-controls.mjs';
5
5
 
6
+ import './starter.css';
7
+
6
8
  // Hosted so the template stays small. Capture or edit your own splat at https://superspl.at, then
7
9
  // drop the .sog or .ply in public/ and point this at it instead
8
10
  const SPLAT_URL = 'https://developer.playcanvas.com/assets/toy-cat.sog';