@epic-web/workshop-app 6.77.0 → 6.77.2

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 (98) hide show
  1. package/build/client/assets/{_exerciseNumber-C1aZpAWV.js → _exerciseNumber-JuXb6JTN.js} +2 -2
  2. package/build/client/assets/{_exerciseNumber-C1aZpAWV.js.map → _exerciseNumber-JuXb6JTN.js.map} +1 -1
  3. package/build/client/assets/{_exerciseNumber_.finished-BICggZV1.js → _exerciseNumber_.finished-DD-1txyR.js} +2 -2
  4. package/build/client/assets/{_exerciseNumber_.finished-BICggZV1.js.map → _exerciseNumber_.finished-DD-1txyR.js.map} +1 -1
  5. package/build/client/assets/_extra-BfK-kKBL.js +2 -0
  6. package/build/client/assets/_extra-BfK-kKBL.js.map +1 -0
  7. package/build/client/assets/{_layout-BZI3FoQD.js → _layout-BsHVX3B_.js} +2 -2
  8. package/build/client/assets/{_layout-BZI3FoQD.js.map → _layout-BsHVX3B_.js.map} +1 -1
  9. package/build/client/assets/{_layout-CunOyAg4.js → _layout-CDyeQVKG.js} +2 -2
  10. package/build/client/assets/{_layout-CunOyAg4.js.map → _layout-CDyeQVKG.js.map} +1 -1
  11. package/build/client/assets/_layout-mVyOtxmC.js +2 -0
  12. package/build/client/assets/_layout-mVyOtxmC.js.map +1 -0
  13. package/build/client/assets/{account-C96cpeZR.js → account-BKXMYhfO.js} +2 -2
  14. package/build/client/assets/{account-C96cpeZR.js.map → account-BKXMYhfO.js.map} +1 -1
  15. package/build/client/assets/{app-CJniokic.js → app-AWsnszeo.js} +2 -2
  16. package/build/client/assets/{app-CJniokic.js.map → app-AWsnszeo.js.map} +1 -1
  17. package/build/client/assets/{cache-CAr50MIB.js → cache-CxMFS2A_.js} +2 -2
  18. package/build/client/assets/{cache-CAr50MIB.js.map → cache-CxMFS2A_.js.map} +1 -1
  19. package/build/client/assets/{db-DAnX-T3_.js → db-BZ-tFzMp.js} +2 -2
  20. package/build/client/assets/{db-DAnX-T3_.js.map → db-BZ-tFzMp.js.map} +1 -1
  21. package/build/client/assets/{diff-D8TUonC2.js → diff-0VO9C_Sf.js} +2 -2
  22. package/build/client/assets/{diff-D8TUonC2.js.map → diff-0VO9C_Sf.js.map} +1 -1
  23. package/build/client/assets/{diff-Col_iM3X.js → diff-CC_jaH50.js} +2 -2
  24. package/build/client/assets/{diff-Col_iM3X.js.map → diff-CC_jaH50.js.map} +1 -1
  25. package/build/client/assets/discord-BVfxP4Rd.js +2 -0
  26. package/build/client/assets/discord-BVfxP4Rd.js.map +1 -0
  27. package/build/client/assets/{discord-BJkw0IrB.js → discord-XhHqPI49.js} +2 -2
  28. package/build/client/assets/{discord-BJkw0IrB.js.map → discord-XhHqPI49.js.map} +1 -1
  29. package/build/client/assets/{epic-video-BJW6MU1i.js → epic-video-D4jBdSKs.js} +2 -2
  30. package/build/client/assets/{epic-video-BJW6MU1i.js.map → epic-video-D4jBdSKs.js.map} +1 -1
  31. package/build/client/assets/{epic-video-jtxu_0bl.js → epic-video-Ddc9rYLT.js} +2 -2
  32. package/build/client/assets/{epic-video-jtxu_0bl.js.map → epic-video-Ddc9rYLT.js.map} +1 -1
  33. package/build/client/assets/{finished-C2jP5uE7.js → finished-BSfM_f4M.js} +2 -2
  34. package/build/client/assets/{finished-C2jP5uE7.js.map → finished-BSfM_f4M.js.map} +1 -1
  35. package/build/client/assets/{index-CdzVFL-Z.js → index-BrVvTrwg.js} +2 -2
  36. package/build/client/assets/{index-CdzVFL-Z.js.map → index-BrVvTrwg.js.map} +1 -1
  37. package/build/client/assets/{index-Dpyv8N6m.js → index-CfPaTqRT.js} +2 -2
  38. package/build/client/assets/{index-Dpyv8N6m.js.map → index-CfPaTqRT.js.map} +1 -1
  39. package/build/client/assets/{index-X8or9u7t.js → index-CuCZuiBp.js} +2 -2
  40. package/build/client/assets/{index-X8or9u7t.js.map → index-CuCZuiBp.js.map} +1 -1
  41. package/build/client/assets/{index-KRgoKRWG.js → index-D0vH1MiQ.js} +2 -2
  42. package/build/client/assets/{index-KRgoKRWG.js.map → index-D0vH1MiQ.js.map} +1 -1
  43. package/build/client/assets/{index-BCQgVrao.js → index-DTC_5pri.js} +2 -2
  44. package/build/client/assets/{index-BCQgVrao.js.map → index-DTC_5pri.js.map} +1 -1
  45. package/build/client/assets/{launch-editor-D2exGfVu.js → launch-editor-0oPpbFQe.js} +2 -2
  46. package/build/client/assets/{launch-editor-D2exGfVu.js.map → launch-editor-0oPpbFQe.js.map} +1 -1
  47. package/build/client/assets/{loading-CDNzW5oO.js → loading-CaCCsk9k.js} +2 -2
  48. package/build/client/assets/{loading-CDNzW5oO.js.map → loading-CaCCsk9k.js.map} +1 -1
  49. package/build/client/assets/{login-mWjVXGbJ.js → login-w4y7RVYa.js} +2 -2
  50. package/build/client/assets/{login-mWjVXGbJ.js.map → login-w4y7RVYa.js.map} +1 -1
  51. package/build/client/assets/{manifest-dd28a0e5.js → manifest-a63db2d2.js} +1 -1
  52. package/build/client/assets/{mdx-DdpoOTHm.js → mdx-DwvWT4Ou.js} +2 -2
  53. package/build/client/assets/{mdx-DdpoOTHm.js.map → mdx-DwvWT4Ou.js.map} +1 -1
  54. package/build/client/assets/{onboarding-indicator-B-XR90_G.js → onboarding-indicator-BkeHYs2C.js} +2 -2
  55. package/build/client/assets/{onboarding-indicator-B-XR90_G.js.map → onboarding-indicator-BkeHYs2C.js.map} +1 -1
  56. package/build/client/assets/{online-DiNLkgTC.js → online-DVk-W8Cr.js} +2 -2
  57. package/build/client/assets/{online-DiNLkgTC.js.map → online-DVk-W8Cr.js.map} +1 -1
  58. package/build/client/assets/{playground-DmEAkxG1.js → playground-DG4B62WX.js} +2 -2
  59. package/build/client/assets/{playground-DmEAkxG1.js.map → playground-DG4B62WX.js.map} +1 -1
  60. package/build/client/assets/{playground-window-x2mQ5o1O.js → playground-window-CF8lTXXI.js} +2 -2
  61. package/build/client/assets/{playground-window-x2mQ5o1O.js.map → playground-window-CF8lTXXI.js.map} +1 -1
  62. package/build/client/assets/{preferences-B7ND1VS9.js → preferences-Czy5oqWs.js} +2 -2
  63. package/build/client/assets/{preferences-B7ND1VS9.js.map → preferences-Czy5oqWs.js.map} +1 -1
  64. package/build/client/assets/{presence-VCvV2mg7.js → presence-Brtc_BN7.js} +2 -2
  65. package/build/client/assets/{presence-VCvV2mg7.js.map → presence-Brtc_BN7.js.map} +1 -1
  66. package/build/client/assets/{preview-fhmjENlm.js → preview-Be-plbPz.js} +2 -2
  67. package/build/client/assets/{preview-fhmjENlm.js.map → preview-Be-plbPz.js.map} +1 -1
  68. package/build/client/assets/{product-CvyMpYD_.js → product-D4IgPJN5.js} +2 -2
  69. package/build/client/assets/{product-CvyMpYD_.js.map → product-D4IgPJN5.js.map} +1 -1
  70. package/build/client/assets/{progress-Bby-ybMA.js → progress-JDMkfyr3.js} +2 -2
  71. package/build/client/assets/{progress-Bby-ybMA.js.map → progress-JDMkfyr3.js.map} +1 -1
  72. package/build/client/assets/{revalidation-ws-BJWJviUX.js → revalidation-ws-iocj9Mrl.js} +2 -2
  73. package/build/client/assets/{revalidation-ws-BJWJviUX.js.map → revalidation-ws-iocj9Mrl.js.map} +1 -1
  74. package/build/client/assets/{root-B-MkiU1r.js → root-IJJBVEoj.js} +2 -2
  75. package/build/client/assets/{root-B-MkiU1r.js.map → root-IJJBVEoj.js.map} +1 -1
  76. package/build/client/assets/{root-loader-BOzEMapJ.js → root-loader-BmUqzUDN.js} +2 -2
  77. package/build/client/assets/{root-loader-BOzEMapJ.js.map → root-loader-BmUqzUDN.js.map} +1 -1
  78. package/build/client/assets/{set-playground-BSGwH9dH.js → set-playground-DO5tJu4h.js} +2 -2
  79. package/build/client/assets/{set-playground-BSGwH9dH.js.map → set-playground-DO5tJu4h.js.map} +1 -1
  80. package/build/client/assets/{test-BeEphi7e.js → test-C8NrA0Ls.js} +2 -2
  81. package/build/client/assets/{test-BeEphi7e.js.map → test-C8NrA0Ls.js.map} +1 -1
  82. package/build/client/assets/{tests-RWSslYc0.js → tests-Bko6qhsh.js} +2 -2
  83. package/build/client/assets/{tests-RWSslYc0.js.map → tests-Bko6qhsh.js.map} +1 -1
  84. package/build/client/assets/{user-BsPobzjB.js → user-CYXKquT7.js} +2 -2
  85. package/build/client/assets/{user-BsPobzjB.js.map → user-CYXKquT7.js.map} +1 -1
  86. package/build/client/assets/{version-f8qqYbyU.js → version-CwWSRwe5.js} +2 -2
  87. package/build/client/assets/{version-f8qqYbyU.js.map → version-CwWSRwe5.js.map} +1 -1
  88. package/build/client/assets/{workshop-config-Zfc8zU0x.js → workshop-config-BMWaKPZT.js} +2 -2
  89. package/build/client/assets/{workshop-config-Zfc8zU0x.js.map → workshop-config-BMWaKPZT.js.map} +1 -1
  90. package/build/server/index.js +7 -3
  91. package/build/server/index.js.map +1 -1
  92. package/package.json +3 -3
  93. package/build/client/assets/_extra-Dki7HdFp.js +0 -2
  94. package/build/client/assets/_extra-Dki7HdFp.js.map +0 -1
  95. package/build/client/assets/_layout-DTrIGRDO.js +0 -2
  96. package/build/client/assets/_layout-DTrIGRDO.js.map +0 -1
  97. package/build/client/assets/discord-r3m19sUM.js +0 -2
  98. package/build/client/assets/discord-r3m19sUM.js.map +0 -1
@@ -1,2 +1,2 @@
1
- import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{r as u}from"./index-CqIc3cxq.js";import{f as x,d as A}from"./chunk-EPOLDU6W-BCLmut3y.js";import{u as F,l as k,I as h,a as C,c as R}from"./misc-W4055b-0.js";import{B as P,L as O}from"./button-Cd-ekki5.js";import{L as I}from"./loading-CDNzW5oO.js";import{s as j}from"./progress-bar-DpWhcyhC.js";import{u as g}from"./pe-CIZUOJMr.js";import{u as b}from"./index-CdzVFL-Z.js";import{a as L}from"./root-loader-BOzEMapJ.js";import{m as z,T as v,j as S,k as N}from"./tooltip-Tlsyx2YO.js";function q({name:r}){const t=x(),n=g(),o=t.formData?.get("intent"),l=o==="stop"?"Stopping App":o==="restart"?"Restarting App":null,a=F();return e.jsxs(t.Form,{method:"POST",action:"/start",children:[n,j,e.jsx("input",{type:"hidden",name:"name",value:r}),e.jsx("button",{type:"submit",name:"intent",value:a?"restart":"stop",className:"h-full border-r px-3 py-4 font-mono text-xs leading-none uppercase",children:l||(a?"Restart App":"Stop App")})]})}function B({port:r}){const t=x(),n=g();return e.jsxs(t.Form,{method:"POST",action:"/start",children:[n,j,e.jsx("input",{type:"hidden",name:"port",value:r}),e.jsx(P,{varient:"mono",type:"submit",name:"intent",value:"stop-port",children:t.state==="idle"?"Stop Port":"Stopping Port"})]})}function D({name:r}){const t=x(),n=g();return t.data?.status==="app-not-started"?t.data.error==="port-unavailable"?e.jsxs("div",{children:["The port is unavailable. Would you like to stop whatever is running on that port and try again?",e.jsx(B,{port:t.data.port})]}):e.jsx("div",{children:"An unknown error has happened."}):e.jsxs(t.Form,{method:"POST",action:"/start",children:[n,j,e.jsx("input",{type:"hidden",name:"name",value:r}),t.state==="idle"?e.jsx(P,{type:"submit",name:"intent",value:"start",varient:"mono",children:"Start App"}):e.jsx("div",{children:e.jsx(I,{children:"Starting App"})})]})}function _({name:r,port:t,portIsAvailable:n,isRunning:o,baseUrl:l,id:a,initialRoute:p,ref:s}){const d=L(),[m,c]=u.useState(!1);return o||m?e.jsx(K,{baseUrl:l,id:a,name:r,ref:s,initialRoute:p}):n===!1?e.jsxs("div",{className:"flex flex-col items-center justify-center",children:[e.jsxs("p",{className:"max-w-xs pb-5 text-center",role:"status",children:["The port for this app is unavailable. It could be that you're running it ",e.jsx("a",{href:k({domain:d.domain,port:t}),className:"underline",target:"_blank",rel:"noreferrer",children:"elsewhere"}),". ",e.jsx(O,{onClick:()=>c(!0),children:"Show here anyway"})]}),e.jsx(B,{port:t})]}):e.jsx("div",{className:"flex h-full flex-col items-center justify-center",children:e.jsx(D,{name:r})})}function K({baseUrl:r,id:t,name:n,initialRoute:o,ref:l}){const a=b(),[p,s]=u.useState(0),d=t+p,m=u.useRef(null),c=new URL(o,r),[i,w]=u.useState(c),y=u.useRef(t);y.current!==t&&(y.current=t,w(c));function U(f){if(f){const E=new URL(f,r);w(E),s(T=>T+1)}}return u.useImperativeHandle(l,()=>({handleExtrnalNavigation:U})),e.jsx(z,{children:e.jsxs("div",{className:"flex h-full grow flex-col",children:[e.jsxs("div",{className:"flex items-center justify-between border-b pl-1.5",children:[e.jsx("div",{className:"mr-2 flex items-center justify-center gap-2 px-1",children:e.jsxs(v,{children:[e.jsx(S,{asChild:!0,children:e.jsx("button",{type:"button",className:"flex aspect-square h-full w-full items-center justify-center p-1 transition disabled:opacity-40",onClick:()=>{s(f=>f+1)},children:e.jsx(h,{name:"Refresh","aria-hidden":"true"})})}),e.jsx(N,{children:"Refresh"})]})}),e.jsx("div",{className:"bg-background text-foreground flex flex-1 items-center border-x p-3 leading-none",children:e.jsx("a",{href:i.toString(),target:"_blank",rel:"noreferrer",children:i.toString()})}),e.jsx(q,{name:n}),e.jsxs(v,{children:[e.jsx(S,{asChild:!0,children:e.jsx("a",{href:i.toString(),target:"_blank",rel:"noreferrer",className:C("flex aspect-square items-center justify-center px-3.5"),children:e.jsx(h,{name:"ExternalLink"})})}),e.jsx(N,{children:"Open in new tab"})]})]}),e.jsx("div",{className:"bg-background flex h-full w-full grow",children:e.jsx("iframe",{title:n,ref:m,src:i.toString(),className:"bg-background h-full w-full grow",style:{colorScheme:a},allow:"clipboard-write"},d)})]})})}function te({id:r,appInfo:t,inBrowserBrowserRef:n}){const o=L(),[l]=A(),a=b();if(!t)return e.jsx("p",{children:"No app here. Sorry."});const{isRunning:p,dev:s,name:d,portIsAvailable:m,title:c}=t;if(!s)return e.jsx("div",{className:"flex h-full items-center justify-center text-lg",children:e.jsx("p",{children:"No preview available for this app."})});if(ENV.EPICSHOP_DEPLOYED&&t.stackBlitzUrl){const i=new URL(t.stackBlitzUrl);return i.searchParams.set("embed","1"),i.searchParams.set("theme",a),e.jsx(H,{title:c,url:i.toString(),loadingContent:e.jsx(I,{children:e.jsxs("span",{children:["Loading"," ",e.jsxs("a",{className:"underline",href:t.stackBlitzUrl,children:['"',c,'"']})]})})})}if(s.type==="script"){const i=k({domain:o.domain,port:s.portNumber});return e.jsx(_,{ref:n,isRunning:p,id:r??d,name:d,portIsAvailable:m,port:s.portNumber,baseUrl:i,initialRoute:l.get("pathname")??s.initialRoute})}else return s.type==="browser"||s.type==="export"?e.jsxs("div",{className:"scrollbar-thin scrollbar-thumb-scrollbar relative h-full grow overflow-y-auto",children:[e.jsxs("a",{href:s.pathname,target:"_blank",rel:"noreferrer",className:R("bg-muted text-foreground hover:bg-muted/80 absolute right-5 bottom-5 flex items-center justify-center rounded-full p-2.5 transition"),children:[e.jsx(h,{name:"ExternalLink","aria-hidden":"true"}),e.jsx("span",{className:"sr-only",children:"Open in New Window"})]}),e.jsx("iframe",{title:c,src:s.pathname,className:"bg-background h-full w-full grow",style:{colorScheme:a},allow:"clipboard-write"})]}):e.jsx("div",{className:"flex h-full items-center justify-center text-lg",children:e.jsxs("p",{children:["Preview for dev type of ",e.jsx("code",{children:s.type})," not supported."]})})}function H({url:r,title:t,loadingContent:n}){const o=b(),[l,a]=u.useState(!1);return e.jsxs("div",{className:"h-full w-full grow",children:[l?null:e.jsx("div",{className:"absolute inset-0 z-10 flex items-center justify-center",children:n}),e.jsx("iframe",{onLoad:()=>a(!0),onError:()=>a(!0),src:r,className:R("h-full w-full grow transition-opacity duration-300",l?"opacity-100":"opacity-0"),title:t,sandbox:"allow-forms allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox",allow:"clipboard-write",style:{colorScheme:o}})]})}export{te as P};
2
- //# sourceMappingURL=preview-fhmjENlm.js.map
1
+ import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{r as u}from"./index-CqIc3cxq.js";import{f as x,d as A}from"./chunk-EPOLDU6W-BCLmut3y.js";import{u as F,l as k,I as h,a as C,c as R}from"./misc-W4055b-0.js";import{B as P,L as O}from"./button-Cd-ekki5.js";import{L as I}from"./loading-CaCCsk9k.js";import{s as j}from"./progress-bar-DpWhcyhC.js";import{u as g}from"./pe-CIZUOJMr.js";import{u as b}from"./index-BrVvTrwg.js";import{b as L}from"./root-loader-BmUqzUDN.js";import{m as z,T as v,j as S,k as N}from"./tooltip-Tlsyx2YO.js";function q({name:r}){const t=x(),n=g(),o=t.formData?.get("intent"),l=o==="stop"?"Stopping App":o==="restart"?"Restarting App":null,a=F();return e.jsxs(t.Form,{method:"POST",action:"/start",children:[n,j,e.jsx("input",{type:"hidden",name:"name",value:r}),e.jsx("button",{type:"submit",name:"intent",value:a?"restart":"stop",className:"h-full border-r px-3 py-4 font-mono text-xs leading-none uppercase",children:l||(a?"Restart App":"Stop App")})]})}function B({port:r}){const t=x(),n=g();return e.jsxs(t.Form,{method:"POST",action:"/start",children:[n,j,e.jsx("input",{type:"hidden",name:"port",value:r}),e.jsx(P,{varient:"mono",type:"submit",name:"intent",value:"stop-port",children:t.state==="idle"?"Stop Port":"Stopping Port"})]})}function D({name:r}){const t=x(),n=g();return t.data?.status==="app-not-started"?t.data.error==="port-unavailable"?e.jsxs("div",{children:["The port is unavailable. Would you like to stop whatever is running on that port and try again?",e.jsx(B,{port:t.data.port})]}):e.jsx("div",{children:"An unknown error has happened."}):e.jsxs(t.Form,{method:"POST",action:"/start",children:[n,j,e.jsx("input",{type:"hidden",name:"name",value:r}),t.state==="idle"?e.jsx(P,{type:"submit",name:"intent",value:"start",varient:"mono",children:"Start App"}):e.jsx("div",{children:e.jsx(I,{children:"Starting App"})})]})}function _({name:r,port:t,portIsAvailable:n,isRunning:o,baseUrl:l,id:a,initialRoute:p,ref:s}){const d=L(),[m,c]=u.useState(!1);return o||m?e.jsx(K,{baseUrl:l,id:a,name:r,ref:s,initialRoute:p}):n===!1?e.jsxs("div",{className:"flex flex-col items-center justify-center",children:[e.jsxs("p",{className:"max-w-xs pb-5 text-center",role:"status",children:["The port for this app is unavailable. It could be that you're running it ",e.jsx("a",{href:k({domain:d.domain,port:t}),className:"underline",target:"_blank",rel:"noreferrer",children:"elsewhere"}),". ",e.jsx(O,{onClick:()=>c(!0),children:"Show here anyway"})]}),e.jsx(B,{port:t})]}):e.jsx("div",{className:"flex h-full flex-col items-center justify-center",children:e.jsx(D,{name:r})})}function K({baseUrl:r,id:t,name:n,initialRoute:o,ref:l}){const a=b(),[p,s]=u.useState(0),d=t+p,m=u.useRef(null),c=new URL(o,r),[i,w]=u.useState(c),y=u.useRef(t);y.current!==t&&(y.current=t,w(c));function U(f){if(f){const E=new URL(f,r);w(E),s(T=>T+1)}}return u.useImperativeHandle(l,()=>({handleExtrnalNavigation:U})),e.jsx(z,{children:e.jsxs("div",{className:"flex h-full grow flex-col",children:[e.jsxs("div",{className:"flex items-center justify-between border-b pl-1.5",children:[e.jsx("div",{className:"mr-2 flex items-center justify-center gap-2 px-1",children:e.jsxs(v,{children:[e.jsx(S,{asChild:!0,children:e.jsx("button",{type:"button",className:"flex aspect-square h-full w-full items-center justify-center p-1 transition disabled:opacity-40",onClick:()=>{s(f=>f+1)},children:e.jsx(h,{name:"Refresh","aria-hidden":"true"})})}),e.jsx(N,{children:"Refresh"})]})}),e.jsx("div",{className:"bg-background text-foreground flex flex-1 items-center border-x p-3 leading-none",children:e.jsx("a",{href:i.toString(),target:"_blank",rel:"noreferrer",children:i.toString()})}),e.jsx(q,{name:n}),e.jsxs(v,{children:[e.jsx(S,{asChild:!0,children:e.jsx("a",{href:i.toString(),target:"_blank",rel:"noreferrer",className:C("flex aspect-square items-center justify-center px-3.5"),children:e.jsx(h,{name:"ExternalLink"})})}),e.jsx(N,{children:"Open in new tab"})]})]}),e.jsx("div",{className:"bg-background flex h-full w-full grow",children:e.jsx("iframe",{title:n,ref:m,src:i.toString(),className:"bg-background h-full w-full grow",style:{colorScheme:a},allow:"clipboard-write"},d)})]})})}function te({id:r,appInfo:t,inBrowserBrowserRef:n}){const o=L(),[l]=A(),a=b();if(!t)return e.jsx("p",{children:"No app here. Sorry."});const{isRunning:p,dev:s,name:d,portIsAvailable:m,title:c}=t;if(!s)return e.jsx("div",{className:"flex h-full items-center justify-center text-lg",children:e.jsx("p",{children:"No preview available for this app."})});if(ENV.EPICSHOP_DEPLOYED&&t.stackBlitzUrl){const i=new URL(t.stackBlitzUrl);return i.searchParams.set("embed","1"),i.searchParams.set("theme",a),e.jsx(H,{title:c,url:i.toString(),loadingContent:e.jsx(I,{children:e.jsxs("span",{children:["Loading"," ",e.jsxs("a",{className:"underline",href:t.stackBlitzUrl,children:['"',c,'"']})]})})})}if(s.type==="script"){const i=k({domain:o.domain,port:s.portNumber});return e.jsx(_,{ref:n,isRunning:p,id:r??d,name:d,portIsAvailable:m,port:s.portNumber,baseUrl:i,initialRoute:l.get("pathname")??s.initialRoute})}else return s.type==="browser"||s.type==="export"?e.jsxs("div",{className:"scrollbar-thin scrollbar-thumb-scrollbar relative h-full grow overflow-y-auto",children:[e.jsxs("a",{href:s.pathname,target:"_blank",rel:"noreferrer",className:R("bg-muted text-foreground hover:bg-muted/80 absolute right-5 bottom-5 flex items-center justify-center rounded-full p-2.5 transition"),children:[e.jsx(h,{name:"ExternalLink","aria-hidden":"true"}),e.jsx("span",{className:"sr-only",children:"Open in New Window"})]}),e.jsx("iframe",{title:c,src:s.pathname,className:"bg-background h-full w-full grow",style:{colorScheme:a},allow:"clipboard-write"})]}):e.jsx("div",{className:"flex h-full items-center justify-center text-lg",children:e.jsxs("p",{children:["Preview for dev type of ",e.jsx("code",{children:s.type})," not supported."]})})}function H({url:r,title:t,loadingContent:n}){const o=b(),[l,a]=u.useState(!1);return e.jsxs("div",{className:"h-full w-full grow",children:[l?null:e.jsx("div",{className:"absolute inset-0 z-10 flex items-center justify-center",children:n}),e.jsx("iframe",{onLoad:()=>a(!0),onError:()=>a(!0),src:r,className:R("h-full w-full grow transition-opacity duration-300",l?"opacity-100":"opacity-0"),title:t,sandbox:"allow-forms allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox",allow:"clipboard-write",style:{colorScheme:o}})]})}export{te as P};
2
+ //# sourceMappingURL=preview-Be-plbPz.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"preview-fhmjENlm.js","sources":["../../../app/routes/start.tsx","../../../app/components/in-browser-browser.tsx","../../../app/routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/__shared/preview.tsx"],"sourcesContent":["import { invariant, invariantResponse } from '@epic-web/invariant'\nimport { getAppByName } from '@epic-web/workshop-utils/apps.server'\nimport {\n\tcloseProcess,\n\trunAppDev,\n\tstopPort,\n\twaitOnApp,\n} from '@epic-web/workshop-utils/process-manager.server'\nimport { data, type ActionFunctionArgs, useFetcher } from 'react-router'\nimport { Button } from '#app/components/button.tsx'\nimport { Loading } from '#app/components/loading.tsx'\nimport { showProgressBarField } from '#app/components/progress-bar.tsx'\nimport { ensureUndeployed, useAltDown } from '#app/utils/misc.tsx'\nimport { dataWithPE, usePERedirectInput } from '#app/utils/pe.tsx'\nimport { createToastHeaders } from '#app/utils/toast.server'\n\nexport async function action({ request }: ActionFunctionArgs) {\n\tensureUndeployed()\n\tconst formData = await request.formData()\n\tconst intent = formData.get('intent')\n\tinvariantResponse(typeof intent === 'string', 'intent is required')\n\n\tif (intent === 'start' || intent === 'stop' || intent === 'restart') {\n\t\tconst name = formData.get('name')\n\t\tinvariantResponse(typeof name === 'string', 'name is required')\n\t\tconst app = await getAppByName(name)\n\t\tif (!app) {\n\t\t\tthrow new Response('Not found', { status: 404 })\n\t\t}\n\t\tif (app.dev.type !== 'script') {\n\t\t\tthrow new Response(`App \"${name}\" does not have a server`, {\n\t\t\t\tstatus: 400,\n\t\t\t})\n\t\t}\n\n\t\tasync function startApp() {\n\t\t\tinvariant(app, 'app must be defined')\n\t\t\tconst result = await runAppDev(app)\n\t\t\tif (result.running) {\n\t\t\t\tconst appRunningResult = await waitOnApp(app)\n\t\t\t\tif (appRunningResult?.status === 'success') {\n\t\t\t\t\t// wait another 200ms just in case the build output for assets isn't finished\n\t\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, 200))\n\t\t\t\t\treturn dataWithPE(request, formData, {\n\t\t\t\t\t\tstatus: 'app-started',\n\t\t\t\t\t} as const)\n\t\t\t\t} else if (app.dev.type === 'script') {\n\t\t\t\t\tconst errorMessage = appRunningResult\n\t\t\t\t\t\t? appRunningResult.error\n\t\t\t\t\t\t: 'Unknown error'\n\t\t\t\t\treturn data(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstatus: 'app-not-started',\n\t\t\t\t\t\t\terror: errorMessage,\n\t\t\t\t\t\t\tport: app.dev.portNumber,\n\t\t\t\t\t\t} as const,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\t\tstatusText: 'App did not start',\n\t\t\t\t\t\t\theaders: await createToastHeaders({\n\t\t\t\t\t\t\t\tdescription: errorMessage,\n\t\t\t\t\t\t\t\ttitle: 'App did not start',\n\t\t\t\t\t\t\t\ttype: 'error',\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t},\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t} else if (result.portNumber) {\n\t\t\t\treturn dataWithPE(request, formData, {\n\t\t\t\t\tstatus: 'app-not-started',\n\t\t\t\t\terror: result.status,\n\t\t\t\t\tport: result.portNumber,\n\t\t\t\t} as const)\n\t\t\t} else {\n\t\t\t\tthrow new Response(\n\t\t\t\t\t'Tried starting a server for an app that does not have one',\n\t\t\t\t\t{ status: 400 },\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\tasync function stopApp() {\n\t\t\tinvariant(app, 'app must be defined')\n\t\t\tawait closeProcess(app.name)\n\t\t\treturn dataWithPE(request, formData, { status: 'app-stopped' } as const)\n\t\t}\n\n\t\tswitch (intent) {\n\t\t\tcase 'start': {\n\t\t\t\treturn startApp()\n\t\t\t}\n\t\t\tcase 'stop': {\n\t\t\t\treturn stopApp()\n\t\t\t}\n\t\t\tcase 'restart': {\n\t\t\t\tawait stopApp()\n\t\t\t\treturn startApp()\n\t\t\t}\n\t\t}\n\t}\n\n\tif (intent === 'stop-port') {\n\t\tconst port = formData.get('port')\n\t\tinvariantResponse(typeof port === 'string', 'port is required')\n\t\tawait stopPort(port)\n\t\treturn dataWithPE(request, formData, { status: 'port-stopped' } as const)\n\t}\n\tthrow new Error(`Unknown intent: ${intent}`)\n}\n\nexport function AppStopper({ name }: { name: string }) {\n\tconst fetcher = useFetcher<typeof action>()\n\tconst peRedirectInput = usePERedirectInput()\n\tconst inFlightIntent = fetcher.formData?.get('intent')\n\tconst inFlightState =\n\t\tinFlightIntent === 'stop'\n\t\t\t? 'Stopping App'\n\t\t\t: inFlightIntent === 'restart'\n\t\t\t\t? 'Restarting App'\n\t\t\t\t: null\n\tconst altDown = useAltDown()\n\treturn (\n\t\t<fetcher.Form method=\"POST\" action=\"/start\">\n\t\t\t{peRedirectInput}\n\t\t\t{showProgressBarField}\n\t\t\t<input type=\"hidden\" name=\"name\" value={name} />\n\t\t\t<button\n\t\t\t\ttype=\"submit\"\n\t\t\t\tname=\"intent\"\n\t\t\t\tvalue={altDown ? 'restart' : 'stop'}\n\t\t\t\tclassName=\"h-full border-r px-3 py-4 font-mono text-xs leading-none uppercase\"\n\t\t\t>\n\t\t\t\t{inFlightState ? inFlightState : altDown ? 'Restart App' : 'Stop App'}\n\t\t\t</button>\n\t\t</fetcher.Form>\n\t)\n}\n\nexport function PortStopper({ port }: { port: number | string }) {\n\tconst fetcher = useFetcher<typeof action>()\n\tconst peRedirectInput = usePERedirectInput()\n\treturn (\n\t\t<fetcher.Form method=\"POST\" action=\"/start\">\n\t\t\t{peRedirectInput}\n\t\t\t{showProgressBarField}\n\t\t\t<input type=\"hidden\" name=\"port\" value={port} />\n\t\t\t<Button varient=\"mono\" type=\"submit\" name=\"intent\" value=\"stop-port\">\n\t\t\t\t{fetcher.state === 'idle' ? 'Stop Port' : 'Stopping Port'}\n\t\t\t</Button>\n\t\t</fetcher.Form>\n\t)\n}\n\nexport function AppStarter({ name }: { name: string }) {\n\tconst fetcher = useFetcher<typeof action>()\n\tconst peRedirectInput = usePERedirectInput()\n\tif (fetcher.data?.status === 'app-not-started') {\n\t\tif (fetcher.data.error === 'port-unavailable') {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\tThe port is unavailable. Would you like to stop whatever is running on\n\t\t\t\t\tthat port and try again?\n\t\t\t\t\t<PortStopper port={fetcher.data.port} />\n\t\t\t\t</div>\n\t\t\t)\n\t\t} else {\n\t\t\treturn <div>An unknown error has happened.</div>\n\t\t}\n\t}\n\treturn (\n\t\t<fetcher.Form method=\"POST\" action=\"/start\">\n\t\t\t{peRedirectInput}\n\t\t\t{showProgressBarField}\n\t\t\t<input type=\"hidden\" name=\"name\" value={name} />\n\t\t\t{fetcher.state === 'idle' ? (\n\t\t\t\t<Button type=\"submit\" name=\"intent\" value=\"start\" varient=\"mono\">\n\t\t\t\t\tStart App\n\t\t\t\t</Button>\n\t\t\t) : (\n\t\t\t\t<div>\n\t\t\t\t\t<Loading>Starting App</Loading>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</fetcher.Form>\n\t)\n}\n","import { clsx } from 'clsx'\nimport * as React from 'react'\nimport { useImperativeHandle, useRef, useState } from 'react'\nimport { Icon } from '#app/components/icons.tsx'\nimport { AppStarter, AppStopper, PortStopper } from '#app/routes/start.tsx'\nimport { useTheme } from '#app/routes/theme/index.tsx'\nimport { getBaseUrl } from '#app/utils/misc.tsx'\nimport { useRequestInfo } from '#app/utils/root-loader.ts'\nimport { LinkButton } from './button.tsx'\nimport {\n\tTooltip,\n\tTooltipContent,\n\tTooltipProvider,\n\tTooltipTrigger,\n} from './ui/tooltip.tsx'\n\nexport type InBrowserBrowserRef = {\n\thandleExtrnalNavigation: (pathname?: string) => void\n}\n\ntype Props = {\n\tid: string\n\tname: string\n\tport: number\n\tportIsAvailable: boolean | null\n\tisRunning: boolean\n\tbaseUrl: string\n\tinitialRoute: string\n\tref?: React.Ref<InBrowserBrowserRef>\n}\n\nexport function InBrowserBrowser({\n\tname,\n\tport,\n\tportIsAvailable,\n\tisRunning,\n\tbaseUrl,\n\tid,\n\tinitialRoute,\n\tref,\n}: Props) {\n\tconst requestInfo = useRequestInfo()\n\tconst [showUnmanaged, setShowUnmanaged] = useState(false)\n\tif (isRunning || showUnmanaged) {\n\t\treturn (\n\t\t\t<InBrowserBrowserForRealz\n\t\t\t\tbaseUrl={baseUrl}\n\t\t\t\tid={id}\n\t\t\t\tname={name}\n\t\t\t\tref={ref}\n\t\t\t\tinitialRoute={initialRoute}\n\t\t\t/>\n\t\t)\n\t} else if (portIsAvailable === false) {\n\t\treturn (\n\t\t\t<div className=\"flex flex-col items-center justify-center\">\n\t\t\t\t<p className=\"max-w-xs pb-5 text-center\" role=\"status\">\n\t\t\t\t\t{`The port for this app is unavailable. It could be that you're running it `}\n\t\t\t\t\t<a\n\t\t\t\t\t\thref={getBaseUrl({ domain: requestInfo.domain, port })}\n\t\t\t\t\t\tclassName=\"underline\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t>\n\t\t\t\t\t\telsewhere\n\t\t\t\t\t</a>\n\t\t\t\t\t{'. '}\n\t\t\t\t\t<LinkButton onClick={() => setShowUnmanaged(true)}>\n\t\t\t\t\t\tShow here anyway\n\t\t\t\t\t</LinkButton>\n\t\t\t\t</p>\n\t\t\t\t<PortStopper port={port} />\n\t\t\t</div>\n\t\t)\n\t} else {\n\t\treturn (\n\t\t\t<div className=\"flex h-full flex-col items-center justify-center\">\n\t\t\t\t<AppStarter name={name} />\n\t\t\t</div>\n\t\t)\n\t}\n}\ntype RealBrowserProps = {\n\tbaseUrl: string\n\tid: string\n\tname: string\n\tinitialRoute: string\n\tref?: React.Ref<InBrowserBrowserRef>\n}\n\nfunction InBrowserBrowserForRealz({\n\tbaseUrl,\n\tid,\n\tname,\n\tinitialRoute,\n\tref,\n}: RealBrowserProps) {\n\tconst theme = useTheme()\n\tconst [iframeKeyNumber, setIframeKeyNumber] = useState(0)\n\tconst iframeKey = id + iframeKeyNumber\n\tconst iframeRef = useRef<HTMLIFrameElement>(null)\n\n\tconst appUrl = new URL(initialRoute, baseUrl)\n\tconst [iframeSrcUrl, setIframeSrcUrl] = useState(appUrl)\n\n\tconst currentId = useRef(id)\n\tif (currentId.current !== id) {\n\t\tcurrentId.current = id\n\t\tsetIframeSrcUrl(appUrl)\n\t}\n\n\tfunction handleExtrnalNavigation(pathname?: string) {\n\t\tif (pathname) {\n\t\t\tconst newUrl = new URL(pathname, baseUrl)\n\t\t\tsetIframeSrcUrl(newUrl)\n\t\t\tsetIframeKeyNumber((prev) => prev + 1)\n\t\t}\n\t}\n\n\tuseImperativeHandle(ref, () => ({ handleExtrnalNavigation }))\n\n\treturn (\n\t\t<TooltipProvider>\n\t\t\t<div className=\"flex h-full grow flex-col\">\n\t\t\t\t<div className=\"flex items-center justify-between border-b pl-1.5\">\n\t\t\t\t\t<div className=\"mr-2 flex items-center justify-center gap-2 px-1\">\n\t\t\t\t\t\t<Tooltip>\n\t\t\t\t\t\t\t<TooltipTrigger asChild>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclassName=\"flex aspect-square h-full w-full items-center justify-center p-1 transition disabled:opacity-40\"\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tsetIframeKeyNumber((prev) => prev + 1)\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Icon name=\"Refresh\" aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t\t\t<TooltipContent>Refresh</TooltipContent>\n\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"bg-background text-foreground flex flex-1 items-center border-x p-3 leading-none\">\n\t\t\t\t\t\t<a href={iframeSrcUrl.toString()} target=\"_blank\" rel=\"noreferrer\">\n\t\t\t\t\t\t\t{iframeSrcUrl.toString()}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<AppStopper name={name} />\n\t\t\t\t\t<Tooltip>\n\t\t\t\t\t\t<TooltipTrigger asChild>\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref={iframeSrcUrl.toString()}\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\t\t\tclassName={clsx(\n\t\t\t\t\t\t\t\t\t'flex aspect-square items-center justify-center px-3.5',\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Icon name=\"ExternalLink\" />\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t\t<TooltipContent>Open in new tab</TooltipContent>\n\t\t\t\t\t</Tooltip>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"bg-background flex h-full w-full grow\">\n\t\t\t\t\t<iframe\n\t\t\t\t\t\ttitle={name}\n\t\t\t\t\t\tkey={iframeKey}\n\t\t\t\t\t\tref={iframeRef}\n\t\t\t\t\t\tsrc={iframeSrcUrl.toString()}\n\t\t\t\t\t\tclassName=\"bg-background h-full w-full grow\"\n\t\t\t\t\t\tstyle={{ colorScheme: theme }}\n\t\t\t\t\t\tallow=\"clipboard-write\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</TooltipProvider>\n\t)\n}\n","import { type BaseExerciseStepApp } from '@epic-web/workshop-utils/apps.server'\nimport { useState } from 'react'\nimport { useSearchParams } from 'react-router'\nimport { Icon } from '#app/components/icons'\nimport {\n\tInBrowserBrowser,\n\ttype InBrowserBrowserRef,\n} from '#app/components/in-browser-browser.tsx'\nimport { Loading } from '#app/components/loading.tsx'\nimport { useTheme } from '#app/routes/theme/index.tsx'\nimport { cn, getBaseUrl } from '#app/utils/misc.tsx'\nimport { useRequestInfo } from '#app/utils/root-loader.ts'\n\nexport function Preview({\n\tid,\n\tappInfo,\n\tinBrowserBrowserRef,\n}: {\n\tid?: string\n\tappInfo: {\n\t\tisRunning: boolean\n\t\tappName?: string\n\t\tname: string\n\t\ttitle: string\n\t\tportIsAvailable: boolean | null\n\t\ttype: string\n\t\tfullPath: string\n\t\tdev: BaseExerciseStepApp['dev']\n\t\ttest: BaseExerciseStepApp['test']\n\t\tstackBlitzUrl: BaseExerciseStepApp['stackBlitzUrl']\n\t} | null\n\tinBrowserBrowserRef: React.RefObject<InBrowserBrowserRef | null>\n}) {\n\tconst requestInfo = useRequestInfo()\n\tconst [searchParams] = useSearchParams()\n\tconst theme = useTheme()\n\tif (!appInfo) return <p>No app here. Sorry.</p>\n\tconst { isRunning, dev, name, portIsAvailable, title } = appInfo\n\n\tif (!dev) {\n\t\treturn (\n\t\t\t<div className=\"flex h-full items-center justify-center text-lg\">\n\t\t\t\t<p>No preview available for this app.</p>\n\t\t\t</div>\n\t\t)\n\t}\n\n\tif (ENV.EPICSHOP_DEPLOYED && appInfo.stackBlitzUrl) {\n\t\tconst url = new URL(appInfo.stackBlitzUrl)\n\t\turl.searchParams.set('embed', '1')\n\t\turl.searchParams.set('theme', theme)\n\n\t\treturn (\n\t\t\t<StackBlitzEmbed\n\t\t\t\ttitle={title}\n\t\t\t\turl={url.toString()}\n\t\t\t\tloadingContent={\n\t\t\t\t\t<Loading>\n\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\tLoading{' '}\n\t\t\t\t\t\t\t<a className=\"underline\" href={appInfo.stackBlitzUrl}>\n\t\t\t\t\t\t\t\t\"{title}\"\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</Loading>\n\t\t\t\t}\n\t\t\t/>\n\t\t)\n\t}\n\n\tif (dev.type === 'script') {\n\t\tconst baseUrl = getBaseUrl({\n\t\t\tdomain: requestInfo.domain,\n\t\t\tport: dev.portNumber,\n\t\t})\n\t\treturn (\n\t\t\t<InBrowserBrowser\n\t\t\t\tref={inBrowserBrowserRef}\n\t\t\t\tisRunning={isRunning}\n\t\t\t\tid={id ?? name}\n\t\t\t\tname={name}\n\t\t\t\tportIsAvailable={portIsAvailable}\n\t\t\t\tport={dev.portNumber}\n\t\t\t\tbaseUrl={baseUrl}\n\t\t\t\tinitialRoute={searchParams.get('pathname') ?? dev.initialRoute}\n\t\t\t/>\n\t\t)\n\t} else if (dev.type === 'browser' || dev.type === 'export') {\n\t\treturn (\n\t\t\t<div className=\"scrollbar-thin scrollbar-thumb-scrollbar relative h-full grow overflow-y-auto\">\n\t\t\t\t<a\n\t\t\t\t\thref={dev.pathname}\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'bg-muted text-foreground hover:bg-muted/80 absolute right-5 bottom-5 flex items-center justify-center rounded-full p-2.5 transition',\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<Icon name=\"ExternalLink\" aria-hidden=\"true\" />\n\t\t\t\t\t<span className=\"sr-only\">Open in New Window</span>\n\t\t\t\t</a>\n\t\t\t\t<iframe\n\t\t\t\t\ttitle={title}\n\t\t\t\t\tsrc={dev.pathname}\n\t\t\t\t\tclassName=\"bg-background h-full w-full grow\"\n\t\t\t\t\tstyle={{ colorScheme: theme }}\n\t\t\t\t\tallow=\"clipboard-write\"\n\t\t\t\t/>\n\t\t\t</div>\n\t\t)\n\t} else {\n\t\treturn (\n\t\t\t<div className=\"flex h-full items-center justify-center text-lg\">\n\t\t\t\t<p>\n\t\t\t\t\tPreview for dev type of <code>{dev.type}</code> not supported.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t)\n\t}\n}\n\nexport function StackBlitzEmbed({\n\turl,\n\ttitle,\n\tloadingContent,\n}: {\n\turl: string\n\ttitle?: string\n\tloadingContent: React.ReactNode\n}) {\n\tconst theme = useTheme()\n\tconst [iframeLoaded, setIframeLoaded] = useState(false)\n\n\treturn (\n\t\t<div className=\"h-full w-full grow\">\n\t\t\t{iframeLoaded ? null : (\n\t\t\t\t<div className=\"absolute inset-0 z-10 flex items-center justify-center\">\n\t\t\t\t\t{loadingContent}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<iframe\n\t\t\t\tonLoad={() => setIframeLoaded(true)}\n\t\t\t\t// show what would have shown if there is an error\n\t\t\t\tonError={() => setIframeLoaded(true)}\n\t\t\t\tsrc={url}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'h-full w-full grow transition-opacity duration-300',\n\t\t\t\t\tiframeLoaded ? 'opacity-100' : 'opacity-0',\n\t\t\t\t)}\n\t\t\t\ttitle={title}\n\t\t\t\tsandbox=\"allow-forms allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox\"\n\t\t\t\tallow=\"clipboard-write\"\n\t\t\t\tstyle={{ colorScheme: theme }}\n\t\t\t/>\n\t\t</div>\n\t)\n}\n"],"names":["AppStopper","name","fetcher","useFetcher","peRedirectInput","usePERedirectInput","inFlightIntent","formData","get","inFlightState","altDown","useAltDown","Form","method","action","children","showProgressBarField","type","value","jsx","className","PortStopper","port","Button","varient","state","AppStarter","data","status","error","Loading","InBrowserBrowser","portIsAvailable","isRunning","baseUrl","id","initialRoute","ref","requestInfo","useRequestInfo","showUnmanaged","setShowUnmanaged","useState","InBrowserBrowserForRealz","jsxs","getBaseUrl","LinkButton","theme","useTheme","iframeKeyNumber","setIframeKeyNumber","iframeKey","iframeRef","useRef","appUrl","iframeSrcUrl","setIframeSrcUrl","currentId","handleExtrnalNavigation","pathname","newUrl","prev","useImperativeHandle","TooltipProvider","Tooltip","TooltipTrigger","Icon","TooltipContent","clsx","Preview","appInfo","inBrowserBrowserRef","searchParams","useSearchParams","dev","title","url","StackBlitzEmbed","cn","loadingContent","iframeLoaded","setIframeLoaded"],"mappings":"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"}
1
+ {"version":3,"file":"preview-Be-plbPz.js","sources":["../../../app/routes/start.tsx","../../../app/components/in-browser-browser.tsx","../../../app/routes/_app+/exercise+/$exerciseNumber_.$stepNumber.$type+/__shared/preview.tsx"],"sourcesContent":["import { invariant, invariantResponse } from '@epic-web/invariant'\nimport { getAppByName } from '@epic-web/workshop-utils/apps.server'\nimport {\n\tcloseProcess,\n\trunAppDev,\n\tstopPort,\n\twaitOnApp,\n} from '@epic-web/workshop-utils/process-manager.server'\nimport { data, type ActionFunctionArgs, useFetcher } from 'react-router'\nimport { Button } from '#app/components/button.tsx'\nimport { Loading } from '#app/components/loading.tsx'\nimport { showProgressBarField } from '#app/components/progress-bar.tsx'\nimport { ensureUndeployed, useAltDown } from '#app/utils/misc.tsx'\nimport { dataWithPE, usePERedirectInput } from '#app/utils/pe.tsx'\nimport { createToastHeaders } from '#app/utils/toast.server'\n\nexport async function action({ request }: ActionFunctionArgs) {\n\tensureUndeployed()\n\tconst formData = await request.formData()\n\tconst intent = formData.get('intent')\n\tinvariantResponse(typeof intent === 'string', 'intent is required')\n\n\tif (intent === 'start' || intent === 'stop' || intent === 'restart') {\n\t\tconst name = formData.get('name')\n\t\tinvariantResponse(typeof name === 'string', 'name is required')\n\t\tconst app = await getAppByName(name)\n\t\tif (!app) {\n\t\t\tthrow new Response('Not found', { status: 404 })\n\t\t}\n\t\tif (app.dev.type !== 'script') {\n\t\t\tthrow new Response(`App \"${name}\" does not have a server`, {\n\t\t\t\tstatus: 400,\n\t\t\t})\n\t\t}\n\n\t\tasync function startApp() {\n\t\t\tinvariant(app, 'app must be defined')\n\t\t\tconst result = await runAppDev(app)\n\t\t\tif (result.running) {\n\t\t\t\tconst appRunningResult = await waitOnApp(app)\n\t\t\t\tif (appRunningResult?.status === 'success') {\n\t\t\t\t\t// wait another 200ms just in case the build output for assets isn't finished\n\t\t\t\t\tawait new Promise((resolve) => setTimeout(resolve, 200))\n\t\t\t\t\treturn dataWithPE(request, formData, {\n\t\t\t\t\t\tstatus: 'app-started',\n\t\t\t\t\t} as const)\n\t\t\t\t} else if (app.dev.type === 'script') {\n\t\t\t\t\tconst errorMessage = appRunningResult\n\t\t\t\t\t\t? appRunningResult.error\n\t\t\t\t\t\t: 'Unknown error'\n\t\t\t\t\treturn data(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstatus: 'app-not-started',\n\t\t\t\t\t\t\terror: errorMessage,\n\t\t\t\t\t\t\tport: app.dev.portNumber,\n\t\t\t\t\t\t} as const,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tstatus: 500,\n\t\t\t\t\t\t\tstatusText: 'App did not start',\n\t\t\t\t\t\t\theaders: await createToastHeaders({\n\t\t\t\t\t\t\t\tdescription: errorMessage,\n\t\t\t\t\t\t\t\ttitle: 'App did not start',\n\t\t\t\t\t\t\t\ttype: 'error',\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t},\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t} else if (result.portNumber) {\n\t\t\t\treturn dataWithPE(request, formData, {\n\t\t\t\t\tstatus: 'app-not-started',\n\t\t\t\t\terror: result.status,\n\t\t\t\t\tport: result.portNumber,\n\t\t\t\t} as const)\n\t\t\t} else {\n\t\t\t\tthrow new Response(\n\t\t\t\t\t'Tried starting a server for an app that does not have one',\n\t\t\t\t\t{ status: 400 },\n\t\t\t\t)\n\t\t\t}\n\t\t}\n\n\t\tasync function stopApp() {\n\t\t\tinvariant(app, 'app must be defined')\n\t\t\tawait closeProcess(app.name)\n\t\t\treturn dataWithPE(request, formData, { status: 'app-stopped' } as const)\n\t\t}\n\n\t\tswitch (intent) {\n\t\t\tcase 'start': {\n\t\t\t\treturn startApp()\n\t\t\t}\n\t\t\tcase 'stop': {\n\t\t\t\treturn stopApp()\n\t\t\t}\n\t\t\tcase 'restart': {\n\t\t\t\tawait stopApp()\n\t\t\t\treturn startApp()\n\t\t\t}\n\t\t}\n\t}\n\n\tif (intent === 'stop-port') {\n\t\tconst port = formData.get('port')\n\t\tinvariantResponse(typeof port === 'string', 'port is required')\n\t\tawait stopPort(port)\n\t\treturn dataWithPE(request, formData, { status: 'port-stopped' } as const)\n\t}\n\tthrow new Error(`Unknown intent: ${intent}`)\n}\n\nexport function AppStopper({ name }: { name: string }) {\n\tconst fetcher = useFetcher<typeof action>()\n\tconst peRedirectInput = usePERedirectInput()\n\tconst inFlightIntent = fetcher.formData?.get('intent')\n\tconst inFlightState =\n\t\tinFlightIntent === 'stop'\n\t\t\t? 'Stopping App'\n\t\t\t: inFlightIntent === 'restart'\n\t\t\t\t? 'Restarting App'\n\t\t\t\t: null\n\tconst altDown = useAltDown()\n\treturn (\n\t\t<fetcher.Form method=\"POST\" action=\"/start\">\n\t\t\t{peRedirectInput}\n\t\t\t{showProgressBarField}\n\t\t\t<input type=\"hidden\" name=\"name\" value={name} />\n\t\t\t<button\n\t\t\t\ttype=\"submit\"\n\t\t\t\tname=\"intent\"\n\t\t\t\tvalue={altDown ? 'restart' : 'stop'}\n\t\t\t\tclassName=\"h-full border-r px-3 py-4 font-mono text-xs leading-none uppercase\"\n\t\t\t>\n\t\t\t\t{inFlightState ? inFlightState : altDown ? 'Restart App' : 'Stop App'}\n\t\t\t</button>\n\t\t</fetcher.Form>\n\t)\n}\n\nexport function PortStopper({ port }: { port: number | string }) {\n\tconst fetcher = useFetcher<typeof action>()\n\tconst peRedirectInput = usePERedirectInput()\n\treturn (\n\t\t<fetcher.Form method=\"POST\" action=\"/start\">\n\t\t\t{peRedirectInput}\n\t\t\t{showProgressBarField}\n\t\t\t<input type=\"hidden\" name=\"port\" value={port} />\n\t\t\t<Button varient=\"mono\" type=\"submit\" name=\"intent\" value=\"stop-port\">\n\t\t\t\t{fetcher.state === 'idle' ? 'Stop Port' : 'Stopping Port'}\n\t\t\t</Button>\n\t\t</fetcher.Form>\n\t)\n}\n\nexport function AppStarter({ name }: { name: string }) {\n\tconst fetcher = useFetcher<typeof action>()\n\tconst peRedirectInput = usePERedirectInput()\n\tif (fetcher.data?.status === 'app-not-started') {\n\t\tif (fetcher.data.error === 'port-unavailable') {\n\t\t\treturn (\n\t\t\t\t<div>\n\t\t\t\t\tThe port is unavailable. Would you like to stop whatever is running on\n\t\t\t\t\tthat port and try again?\n\t\t\t\t\t<PortStopper port={fetcher.data.port} />\n\t\t\t\t</div>\n\t\t\t)\n\t\t} else {\n\t\t\treturn <div>An unknown error has happened.</div>\n\t\t}\n\t}\n\treturn (\n\t\t<fetcher.Form method=\"POST\" action=\"/start\">\n\t\t\t{peRedirectInput}\n\t\t\t{showProgressBarField}\n\t\t\t<input type=\"hidden\" name=\"name\" value={name} />\n\t\t\t{fetcher.state === 'idle' ? (\n\t\t\t\t<Button type=\"submit\" name=\"intent\" value=\"start\" varient=\"mono\">\n\t\t\t\t\tStart App\n\t\t\t\t</Button>\n\t\t\t) : (\n\t\t\t\t<div>\n\t\t\t\t\t<Loading>Starting App</Loading>\n\t\t\t\t</div>\n\t\t\t)}\n\t\t</fetcher.Form>\n\t)\n}\n","import { clsx } from 'clsx'\nimport * as React from 'react'\nimport { useImperativeHandle, useRef, useState } from 'react'\nimport { Icon } from '#app/components/icons.tsx'\nimport { AppStarter, AppStopper, PortStopper } from '#app/routes/start.tsx'\nimport { useTheme } from '#app/routes/theme/index.tsx'\nimport { getBaseUrl } from '#app/utils/misc.tsx'\nimport { useRequestInfo } from '#app/utils/root-loader.ts'\nimport { LinkButton } from './button.tsx'\nimport {\n\tTooltip,\n\tTooltipContent,\n\tTooltipProvider,\n\tTooltipTrigger,\n} from './ui/tooltip.tsx'\n\nexport type InBrowserBrowserRef = {\n\thandleExtrnalNavigation: (pathname?: string) => void\n}\n\ntype Props = {\n\tid: string\n\tname: string\n\tport: number\n\tportIsAvailable: boolean | null\n\tisRunning: boolean\n\tbaseUrl: string\n\tinitialRoute: string\n\tref?: React.Ref<InBrowserBrowserRef>\n}\n\nexport function InBrowserBrowser({\n\tname,\n\tport,\n\tportIsAvailable,\n\tisRunning,\n\tbaseUrl,\n\tid,\n\tinitialRoute,\n\tref,\n}: Props) {\n\tconst requestInfo = useRequestInfo()\n\tconst [showUnmanaged, setShowUnmanaged] = useState(false)\n\tif (isRunning || showUnmanaged) {\n\t\treturn (\n\t\t\t<InBrowserBrowserForRealz\n\t\t\t\tbaseUrl={baseUrl}\n\t\t\t\tid={id}\n\t\t\t\tname={name}\n\t\t\t\tref={ref}\n\t\t\t\tinitialRoute={initialRoute}\n\t\t\t/>\n\t\t)\n\t} else if (portIsAvailable === false) {\n\t\treturn (\n\t\t\t<div className=\"flex flex-col items-center justify-center\">\n\t\t\t\t<p className=\"max-w-xs pb-5 text-center\" role=\"status\">\n\t\t\t\t\t{`The port for this app is unavailable. It could be that you're running it `}\n\t\t\t\t\t<a\n\t\t\t\t\t\thref={getBaseUrl({ domain: requestInfo.domain, port })}\n\t\t\t\t\t\tclassName=\"underline\"\n\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t>\n\t\t\t\t\t\telsewhere\n\t\t\t\t\t</a>\n\t\t\t\t\t{'. '}\n\t\t\t\t\t<LinkButton onClick={() => setShowUnmanaged(true)}>\n\t\t\t\t\t\tShow here anyway\n\t\t\t\t\t</LinkButton>\n\t\t\t\t</p>\n\t\t\t\t<PortStopper port={port} />\n\t\t\t</div>\n\t\t)\n\t} else {\n\t\treturn (\n\t\t\t<div className=\"flex h-full flex-col items-center justify-center\">\n\t\t\t\t<AppStarter name={name} />\n\t\t\t</div>\n\t\t)\n\t}\n}\ntype RealBrowserProps = {\n\tbaseUrl: string\n\tid: string\n\tname: string\n\tinitialRoute: string\n\tref?: React.Ref<InBrowserBrowserRef>\n}\n\nfunction InBrowserBrowserForRealz({\n\tbaseUrl,\n\tid,\n\tname,\n\tinitialRoute,\n\tref,\n}: RealBrowserProps) {\n\tconst theme = useTheme()\n\tconst [iframeKeyNumber, setIframeKeyNumber] = useState(0)\n\tconst iframeKey = id + iframeKeyNumber\n\tconst iframeRef = useRef<HTMLIFrameElement>(null)\n\n\tconst appUrl = new URL(initialRoute, baseUrl)\n\tconst [iframeSrcUrl, setIframeSrcUrl] = useState(appUrl)\n\n\tconst currentId = useRef(id)\n\tif (currentId.current !== id) {\n\t\tcurrentId.current = id\n\t\tsetIframeSrcUrl(appUrl)\n\t}\n\n\tfunction handleExtrnalNavigation(pathname?: string) {\n\t\tif (pathname) {\n\t\t\tconst newUrl = new URL(pathname, baseUrl)\n\t\t\tsetIframeSrcUrl(newUrl)\n\t\t\tsetIframeKeyNumber((prev) => prev + 1)\n\t\t}\n\t}\n\n\tuseImperativeHandle(ref, () => ({ handleExtrnalNavigation }))\n\n\treturn (\n\t\t<TooltipProvider>\n\t\t\t<div className=\"flex h-full grow flex-col\">\n\t\t\t\t<div className=\"flex items-center justify-between border-b pl-1.5\">\n\t\t\t\t\t<div className=\"mr-2 flex items-center justify-center gap-2 px-1\">\n\t\t\t\t\t\t<Tooltip>\n\t\t\t\t\t\t\t<TooltipTrigger asChild>\n\t\t\t\t\t\t\t\t<button\n\t\t\t\t\t\t\t\t\ttype=\"button\"\n\t\t\t\t\t\t\t\t\tclassName=\"flex aspect-square h-full w-full items-center justify-center p-1 transition disabled:opacity-40\"\n\t\t\t\t\t\t\t\t\tonClick={() => {\n\t\t\t\t\t\t\t\t\t\tsetIframeKeyNumber((prev) => prev + 1)\n\t\t\t\t\t\t\t\t\t}}\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t<Icon name=\"Refresh\" aria-hidden=\"true\" />\n\t\t\t\t\t\t\t\t</button>\n\t\t\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t\t\t<TooltipContent>Refresh</TooltipContent>\n\t\t\t\t\t\t</Tooltip>\n\t\t\t\t\t</div>\n\t\t\t\t\t<div className=\"bg-background text-foreground flex flex-1 items-center border-x p-3 leading-none\">\n\t\t\t\t\t\t<a href={iframeSrcUrl.toString()} target=\"_blank\" rel=\"noreferrer\">\n\t\t\t\t\t\t\t{iframeSrcUrl.toString()}\n\t\t\t\t\t\t</a>\n\t\t\t\t\t</div>\n\t\t\t\t\t<AppStopper name={name} />\n\t\t\t\t\t<Tooltip>\n\t\t\t\t\t\t<TooltipTrigger asChild>\n\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\thref={iframeSrcUrl.toString()}\n\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\t\t\t\tclassName={clsx(\n\t\t\t\t\t\t\t\t\t'flex aspect-square items-center justify-center px-3.5',\n\t\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<Icon name=\"ExternalLink\" />\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t</TooltipTrigger>\n\t\t\t\t\t\t<TooltipContent>Open in new tab</TooltipContent>\n\t\t\t\t\t</Tooltip>\n\t\t\t\t</div>\n\t\t\t\t<div className=\"bg-background flex h-full w-full grow\">\n\t\t\t\t\t<iframe\n\t\t\t\t\t\ttitle={name}\n\t\t\t\t\t\tkey={iframeKey}\n\t\t\t\t\t\tref={iframeRef}\n\t\t\t\t\t\tsrc={iframeSrcUrl.toString()}\n\t\t\t\t\t\tclassName=\"bg-background h-full w-full grow\"\n\t\t\t\t\t\tstyle={{ colorScheme: theme }}\n\t\t\t\t\t\tallow=\"clipboard-write\"\n\t\t\t\t\t/>\n\t\t\t\t</div>\n\t\t\t</div>\n\t\t</TooltipProvider>\n\t)\n}\n","import { type BaseExerciseStepApp } from '@epic-web/workshop-utils/apps.server'\nimport { useState } from 'react'\nimport { useSearchParams } from 'react-router'\nimport { Icon } from '#app/components/icons'\nimport {\n\tInBrowserBrowser,\n\ttype InBrowserBrowserRef,\n} from '#app/components/in-browser-browser.tsx'\nimport { Loading } from '#app/components/loading.tsx'\nimport { useTheme } from '#app/routes/theme/index.tsx'\nimport { cn, getBaseUrl } from '#app/utils/misc.tsx'\nimport { useRequestInfo } from '#app/utils/root-loader.ts'\n\nexport function Preview({\n\tid,\n\tappInfo,\n\tinBrowserBrowserRef,\n}: {\n\tid?: string\n\tappInfo: {\n\t\tisRunning: boolean\n\t\tappName?: string\n\t\tname: string\n\t\ttitle: string\n\t\tportIsAvailable: boolean | null\n\t\ttype: string\n\t\tfullPath: string\n\t\tdev: BaseExerciseStepApp['dev']\n\t\ttest: BaseExerciseStepApp['test']\n\t\tstackBlitzUrl: BaseExerciseStepApp['stackBlitzUrl']\n\t} | null\n\tinBrowserBrowserRef: React.RefObject<InBrowserBrowserRef | null>\n}) {\n\tconst requestInfo = useRequestInfo()\n\tconst [searchParams] = useSearchParams()\n\tconst theme = useTheme()\n\tif (!appInfo) return <p>No app here. Sorry.</p>\n\tconst { isRunning, dev, name, portIsAvailable, title } = appInfo\n\n\tif (!dev) {\n\t\treturn (\n\t\t\t<div className=\"flex h-full items-center justify-center text-lg\">\n\t\t\t\t<p>No preview available for this app.</p>\n\t\t\t</div>\n\t\t)\n\t}\n\n\tif (ENV.EPICSHOP_DEPLOYED && appInfo.stackBlitzUrl) {\n\t\tconst url = new URL(appInfo.stackBlitzUrl)\n\t\turl.searchParams.set('embed', '1')\n\t\turl.searchParams.set('theme', theme)\n\n\t\treturn (\n\t\t\t<StackBlitzEmbed\n\t\t\t\ttitle={title}\n\t\t\t\turl={url.toString()}\n\t\t\t\tloadingContent={\n\t\t\t\t\t<Loading>\n\t\t\t\t\t\t<span>\n\t\t\t\t\t\t\tLoading{' '}\n\t\t\t\t\t\t\t<a className=\"underline\" href={appInfo.stackBlitzUrl}>\n\t\t\t\t\t\t\t\t\"{title}\"\n\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t</span>\n\t\t\t\t\t</Loading>\n\t\t\t\t}\n\t\t\t/>\n\t\t)\n\t}\n\n\tif (dev.type === 'script') {\n\t\tconst baseUrl = getBaseUrl({\n\t\t\tdomain: requestInfo.domain,\n\t\t\tport: dev.portNumber,\n\t\t})\n\t\treturn (\n\t\t\t<InBrowserBrowser\n\t\t\t\tref={inBrowserBrowserRef}\n\t\t\t\tisRunning={isRunning}\n\t\t\t\tid={id ?? name}\n\t\t\t\tname={name}\n\t\t\t\tportIsAvailable={portIsAvailable}\n\t\t\t\tport={dev.portNumber}\n\t\t\t\tbaseUrl={baseUrl}\n\t\t\t\tinitialRoute={searchParams.get('pathname') ?? dev.initialRoute}\n\t\t\t/>\n\t\t)\n\t} else if (dev.type === 'browser' || dev.type === 'export') {\n\t\treturn (\n\t\t\t<div className=\"scrollbar-thin scrollbar-thumb-scrollbar relative h-full grow overflow-y-auto\">\n\t\t\t\t<a\n\t\t\t\t\thref={dev.pathname}\n\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\trel=\"noreferrer\"\n\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t'bg-muted text-foreground hover:bg-muted/80 absolute right-5 bottom-5 flex items-center justify-center rounded-full p-2.5 transition',\n\t\t\t\t\t)}\n\t\t\t\t>\n\t\t\t\t\t<Icon name=\"ExternalLink\" aria-hidden=\"true\" />\n\t\t\t\t\t<span className=\"sr-only\">Open in New Window</span>\n\t\t\t\t</a>\n\t\t\t\t<iframe\n\t\t\t\t\ttitle={title}\n\t\t\t\t\tsrc={dev.pathname}\n\t\t\t\t\tclassName=\"bg-background h-full w-full grow\"\n\t\t\t\t\tstyle={{ colorScheme: theme }}\n\t\t\t\t\tallow=\"clipboard-write\"\n\t\t\t\t/>\n\t\t\t</div>\n\t\t)\n\t} else {\n\t\treturn (\n\t\t\t<div className=\"flex h-full items-center justify-center text-lg\">\n\t\t\t\t<p>\n\t\t\t\t\tPreview for dev type of <code>{dev.type}</code> not supported.\n\t\t\t\t</p>\n\t\t\t</div>\n\t\t)\n\t}\n}\n\nexport function StackBlitzEmbed({\n\turl,\n\ttitle,\n\tloadingContent,\n}: {\n\turl: string\n\ttitle?: string\n\tloadingContent: React.ReactNode\n}) {\n\tconst theme = useTheme()\n\tconst [iframeLoaded, setIframeLoaded] = useState(false)\n\n\treturn (\n\t\t<div className=\"h-full w-full grow\">\n\t\t\t{iframeLoaded ? null : (\n\t\t\t\t<div className=\"absolute inset-0 z-10 flex items-center justify-center\">\n\t\t\t\t\t{loadingContent}\n\t\t\t\t</div>\n\t\t\t)}\n\t\t\t<iframe\n\t\t\t\tonLoad={() => setIframeLoaded(true)}\n\t\t\t\t// show what would have shown if there is an error\n\t\t\t\tonError={() => setIframeLoaded(true)}\n\t\t\t\tsrc={url}\n\t\t\t\tclassName={cn(\n\t\t\t\t\t'h-full w-full grow transition-opacity duration-300',\n\t\t\t\t\tiframeLoaded ? 'opacity-100' : 'opacity-0',\n\t\t\t\t)}\n\t\t\t\ttitle={title}\n\t\t\t\tsandbox=\"allow-forms allow-scripts allow-same-origin allow-popups allow-popups-to-escape-sandbox\"\n\t\t\t\tallow=\"clipboard-write\"\n\t\t\t\tstyle={{ colorScheme: theme }}\n\t\t\t/>\n\t\t</div>\n\t)\n}\n"],"names":["AppStopper","name","fetcher","useFetcher","peRedirectInput","usePERedirectInput","inFlightIntent","formData","get","inFlightState","altDown","useAltDown","Form","method","action","children","showProgressBarField","type","value","jsx","className","PortStopper","port","Button","varient","state","AppStarter","data","status","error","Loading","InBrowserBrowser","portIsAvailable","isRunning","baseUrl","id","initialRoute","ref","requestInfo","useRequestInfo","showUnmanaged","setShowUnmanaged","useState","InBrowserBrowserForRealz","jsxs","getBaseUrl","LinkButton","theme","useTheme","iframeKeyNumber","setIframeKeyNumber","iframeKey","iframeRef","useRef","appUrl","iframeSrcUrl","setIframeSrcUrl","currentId","handleExtrnalNavigation","pathname","newUrl","prev","useImperativeHandle","TooltipProvider","Tooltip","TooltipTrigger","Icon","TooltipContent","clsx","Preview","appInfo","inBrowserBrowserRef","searchParams","useSearchParams","dev","title","url","StackBlitzEmbed","cn","loadingContent","iframeLoaded","setIframeLoaded"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{u as g}from"./index-CdzVFL-Z.js";import{c as r}from"./misc-W4055b-0.js";import{u as p}from"./workshop-config-Zfc8zU0x.js";const i={font:"w-[1em] h-[1em]",xs:"w-3 h-3",sm:"w-4 h-4",md:"w-5 h-5",lg:"w-6 h-6",xl:"w-7 h-7","2xl":"w-8 h-8"},x={font:"gap-1.5",xs:"gap-1.5",sm:"gap-1.5",md:"gap-2",lg:"gap-2",xl:"gap-3","2xl":"gap-4"};function w({size:s="font",style:c="themed",className:o,children:t,...m}){const{product:{logo:n,displayName:l}}=p(),h=g(),a=n.includes(".svg")?e.jsxs("svg",{...m,className:r(i[s],"inline self-center",o),children:[e.jsx("title",{children:l}),e.jsx("use",{href:`${n}#${c==="themed"?h:"monochrome"}`})]}):e.jsx("img",{src:n,alt:l,...m,className:r(i[s],"inline self-center",o)});return t?e.jsxs("span",{className:`inline-flex items-center ${x[s]}`,children:[a,t]}):a}export{w as L};
2
- //# sourceMappingURL=product-CvyMpYD_.js.map
1
+ import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{u as g}from"./index-BrVvTrwg.js";import{c as r}from"./misc-W4055b-0.js";import{u as p}from"./workshop-config-BMWaKPZT.js";const i={font:"w-[1em] h-[1em]",xs:"w-3 h-3",sm:"w-4 h-4",md:"w-5 h-5",lg:"w-6 h-6",xl:"w-7 h-7","2xl":"w-8 h-8"},x={font:"gap-1.5",xs:"gap-1.5",sm:"gap-1.5",md:"gap-2",lg:"gap-2",xl:"gap-3","2xl":"gap-4"};function w({size:s="font",style:c="themed",className:o,children:t,...m}){const{product:{logo:n,displayName:l}}=p(),h=g(),a=n.includes(".svg")?e.jsxs("svg",{...m,className:r(i[s],"inline self-center",o),children:[e.jsx("title",{children:l}),e.jsx("use",{href:`${n}#${c==="themed"?h:"monochrome"}`})]}):e.jsx("img",{src:n,alt:l,...m,className:r(i[s],"inline self-center",o)});return t?e.jsxs("span",{className:`inline-flex items-center ${x[s]}`,children:[a,t]}):a}export{w as L};
2
+ //# sourceMappingURL=product-D4IgPJN5.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"product-CvyMpYD_.js","sources":["../../../app/components/product.tsx"],"sourcesContent":["import { useTheme } from '#app/routes/theme/index.tsx'\nimport { cn } from '#app/utils/misc.tsx'\nimport { useWorkshopConfig } from './workshop-config.tsx'\n\ntype Sizes = 'font' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'\n\nconst sizeClassName = {\n\tfont: 'w-[1em] h-[1em]',\n\txs: 'w-3 h-3',\n\tsm: 'w-4 h-4',\n\tmd: 'w-5 h-5',\n\tlg: 'w-6 h-6',\n\txl: 'w-7 h-7',\n\t'2xl': 'w-8 h-8',\n} as const\n\nconst childrenSizeClassName = {\n\tfont: 'gap-1.5',\n\txs: 'gap-1.5',\n\tsm: 'gap-1.5',\n\tmd: 'gap-2',\n\tlg: 'gap-2',\n\txl: 'gap-3',\n\t'2xl': 'gap-4',\n} satisfies Record<Sizes, string>\n\nexport function ProductName(props: React.HTMLAttributes<HTMLSpanElement>) {\n\tconst {\n\t\tproduct: { displayName },\n\t} = useWorkshopConfig()\n\treturn <span {...props}>{displayName}</span>\n}\n\nexport function Logo({\n\tsize = 'font',\n\tstyle = 'themed',\n\tclassName,\n\tchildren,\n\t...props\n}: React.SVGProps<SVGSVGElement> & {\n\tsize?: Sizes\n\tstyle?: 'themed' | 'monochrome'\n\tclassName?: string\n\tchildren?: React.ReactNode\n}) {\n\tconst {\n\t\tproduct: { logo, displayName },\n\t} = useWorkshopConfig()\n\tconst theme = useTheme()\n\n\tconst logoElement = logo.includes('.svg') ? (\n\t\t<svg\n\t\t\t{...props}\n\t\t\tclassName={cn(sizeClassName[size], 'inline self-center', className)}\n\t\t>\n\t\t\t<title>{displayName}</title>\n\t\t\t<use href={`${logo}#${style === 'themed' ? theme : 'monochrome'}`} />\n\t\t</svg>\n\t) : (\n\t\t// @ts-expect-error - svg props can't all be applied to img... meh, probably won't ever be a real issue...\n\t\t<img\n\t\t\tsrc={logo}\n\t\t\talt={displayName}\n\t\t\t{...props}\n\t\t\tclassName={cn(sizeClassName[size], 'inline self-center', className)}\n\t\t/>\n\t)\n\n\tif (children) {\n\t\treturn (\n\t\t\t<span\n\t\t\t\tclassName={`inline-flex items-center ${childrenSizeClassName[size]}`}\n\t\t\t>\n\t\t\t\t{logoElement}\n\t\t\t\t{children}\n\t\t\t</span>\n\t\t)\n\t}\n\n\treturn logoElement\n}\n"],"names":["sizeClassName","childrenSizeClassName","Logo","size","style","className","children","props","logo","displayName","useWorkshopConfig","theme","useTheme","logoElement","jsxs","cn","jsx"],"mappings":"+KAMA,MAAMA,EAAgB,CACrB,KAAM,kBACN,GAAI,UACJ,GAAI,UACJ,GAAI,UACJ,GAAI,UACJ,GAAI,UACJ,MAAO,SACR,EAEMC,EAAwB,CAC7B,KAAM,UACN,GAAI,UACJ,GAAI,UACJ,GAAI,QACJ,GAAI,QACJ,GAAI,QACJ,MAAO,OACR,EASO,SAASC,EAAK,CACpB,KAAAC,EAAO,OACP,MAAAC,EAAQ,SACR,UAAAC,EACA,SAAAC,EACA,GAAGC,CACJ,EAKG,CACF,KAAM,CACL,QAAS,CAAE,KAAAC,EAAM,YAAAC,CAAA,CAAY,EAC1BC,EAAA,EACEC,EAAQC,EAAA,EAERC,EAAcL,EAAK,SAAS,MAAM,EACvCM,EAAAA,KAAC,MAAA,CACC,GAAGP,EACJ,UAAWQ,EAAGf,EAAcG,CAAI,EAAG,qBAAsBE,CAAS,EAElE,SAAA,CAAAW,EAAAA,IAAC,SAAO,SAAAP,CAAA,CAAY,EACpBO,EAAAA,IAAC,MAAA,CAAI,KAAM,GAAGR,CAAI,IAAIJ,IAAU,SAAWO,EAAQ,YAAY,EAAA,CAAI,CAAA,CAAA,CAAA,EAIpEK,EAAAA,IAAC,MAAA,CACA,IAAKR,EACL,IAAKC,EACJ,GAAGF,EACJ,UAAWQ,EAAGf,EAAcG,CAAI,EAAG,qBAAsBE,CAAS,CAAA,CAAA,EAIpE,OAAIC,EAEFQ,EAAAA,KAAC,OAAA,CACA,UAAW,4BAA4Bb,EAAsBE,CAAI,CAAC,GAEjE,SAAA,CAAAU,EACAP,CAAA,CAAA,CAAA,EAKGO,CACR"}
1
+ {"version":3,"file":"product-D4IgPJN5.js","sources":["../../../app/components/product.tsx"],"sourcesContent":["import { useTheme } from '#app/routes/theme/index.tsx'\nimport { cn } from '#app/utils/misc.tsx'\nimport { useWorkshopConfig } from './workshop-config.tsx'\n\ntype Sizes = 'font' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl'\n\nconst sizeClassName = {\n\tfont: 'w-[1em] h-[1em]',\n\txs: 'w-3 h-3',\n\tsm: 'w-4 h-4',\n\tmd: 'w-5 h-5',\n\tlg: 'w-6 h-6',\n\txl: 'w-7 h-7',\n\t'2xl': 'w-8 h-8',\n} as const\n\nconst childrenSizeClassName = {\n\tfont: 'gap-1.5',\n\txs: 'gap-1.5',\n\tsm: 'gap-1.5',\n\tmd: 'gap-2',\n\tlg: 'gap-2',\n\txl: 'gap-3',\n\t'2xl': 'gap-4',\n} satisfies Record<Sizes, string>\n\nexport function ProductName(props: React.HTMLAttributes<HTMLSpanElement>) {\n\tconst {\n\t\tproduct: { displayName },\n\t} = useWorkshopConfig()\n\treturn <span {...props}>{displayName}</span>\n}\n\nexport function Logo({\n\tsize = 'font',\n\tstyle = 'themed',\n\tclassName,\n\tchildren,\n\t...props\n}: React.SVGProps<SVGSVGElement> & {\n\tsize?: Sizes\n\tstyle?: 'themed' | 'monochrome'\n\tclassName?: string\n\tchildren?: React.ReactNode\n}) {\n\tconst {\n\t\tproduct: { logo, displayName },\n\t} = useWorkshopConfig()\n\tconst theme = useTheme()\n\n\tconst logoElement = logo.includes('.svg') ? (\n\t\t<svg\n\t\t\t{...props}\n\t\t\tclassName={cn(sizeClassName[size], 'inline self-center', className)}\n\t\t>\n\t\t\t<title>{displayName}</title>\n\t\t\t<use href={`${logo}#${style === 'themed' ? theme : 'monochrome'}`} />\n\t\t</svg>\n\t) : (\n\t\t// @ts-expect-error - svg props can't all be applied to img... meh, probably won't ever be a real issue...\n\t\t<img\n\t\t\tsrc={logo}\n\t\t\talt={displayName}\n\t\t\t{...props}\n\t\t\tclassName={cn(sizeClassName[size], 'inline self-center', className)}\n\t\t/>\n\t)\n\n\tif (children) {\n\t\treturn (\n\t\t\t<span\n\t\t\t\tclassName={`inline-flex items-center ${childrenSizeClassName[size]}`}\n\t\t\t>\n\t\t\t\t{logoElement}\n\t\t\t\t{children}\n\t\t\t</span>\n\t\t)\n\t}\n\n\treturn logoElement\n}\n"],"names":["sizeClassName","childrenSizeClassName","Logo","size","style","className","children","props","logo","displayName","useWorkshopConfig","theme","useTheme","logoElement","jsxs","cn","jsx"],"mappings":"+KAMA,MAAMA,EAAgB,CACrB,KAAM,kBACN,GAAI,UACJ,GAAI,UACJ,GAAI,UACJ,GAAI,UACJ,GAAI,UACJ,MAAO,SACR,EAEMC,EAAwB,CAC7B,KAAM,UACN,GAAI,UACJ,GAAI,UACJ,GAAI,QACJ,GAAI,QACJ,GAAI,QACJ,MAAO,OACR,EASO,SAASC,EAAK,CACpB,KAAAC,EAAO,OACP,MAAAC,EAAQ,SACR,UAAAC,EACA,SAAAC,EACA,GAAGC,CACJ,EAKG,CACF,KAAM,CACL,QAAS,CAAE,KAAAC,EAAM,YAAAC,CAAA,CAAY,EAC1BC,EAAA,EACEC,EAAQC,EAAA,EAERC,EAAcL,EAAK,SAAS,MAAM,EACvCM,EAAAA,KAAC,MAAA,CACC,GAAGP,EACJ,UAAWQ,EAAGf,EAAcG,CAAI,EAAG,qBAAsBE,CAAS,EAElE,SAAA,CAAAW,EAAAA,IAAC,SAAO,SAAAP,CAAA,CAAY,EACpBO,EAAAA,IAAC,MAAA,CAAI,KAAM,GAAGR,CAAI,IAAIJ,IAAU,SAAWO,EAAQ,YAAY,EAAA,CAAI,CAAA,CAAA,CAAA,EAIpEK,EAAAA,IAAC,MAAA,CACA,IAAKR,EACL,IAAKC,EACJ,GAAGF,EACJ,UAAWQ,EAAGf,EAAcG,CAAI,EAAG,qBAAsBE,CAAS,CAAA,CAAA,EAIpE,OAAIC,EAEFQ,EAAAA,KAAC,OAAA,CACA,UAAW,4BAA4Bb,EAAsBE,CAAI,CAAC,GAEjE,SAAA,CAAAU,EACAP,CAAA,CAAA,CAAA,EAKGO,CACR"}