From 4ba243a46cc42d7037ecf96d401b8bae5dedab61 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 18 Jan 2026 22:10:01 +0000 Subject: [PATCH 1/3] Add saved playground selector Co-authored-by: me --- epicshop/package-lock.json | 293 ++++++++++++++- epicshop/package.json | 6 +- .../@epic-web+workshop-app+6.58.0.patch | 348 ++++++++++++++++++ 3 files changed, 645 insertions(+), 2 deletions(-) create mode 100644 epicshop/patches/@epic-web+workshop-app+6.58.0.patch diff --git a/epicshop/package-lock.json b/epicshop/package-lock.json index 342251b..47e4a16 100644 --- a/epicshop/package-lock.json +++ b/epicshop/package-lock.json @@ -16,7 +16,8 @@ "fs-extra": "^11.3.3", "get-port": "^7.1.0", "match-sorter": "^8.2.0", - "p-limit": "^7.2.0" + "p-limit": "^7.2.0", + "patch-package": "^8.0.1" } }, "node_modules/@adobe/css-tools": { @@ -4657,6 +4658,12 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "license": "BSD-2-Clause" + }, "node_modules/accepts": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", @@ -5026,6 +5033,24 @@ "node": ">= 0.8" } }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -5247,6 +5272,21 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/cjs-module-lexer": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", @@ -6234,6 +6274,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-lazy-prop": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", @@ -6971,6 +7028,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "license": "Apache-2.0", + "dependencies": { + "micromatch": "^4.0.2" + } + }, "node_modules/fkill": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/fkill/-/fkill-10.0.1.tgz", @@ -7333,6 +7399,18 @@ "node": ">=8" } }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -7921,6 +7999,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, "node_modules/isbot": { "version": "5.1.32", "resolved": "https://registry.npmjs.org/isbot/-/isbot-5.1.32.tgz", @@ -7991,6 +8075,25 @@ "node": ">=6" } }, + "node_modules/json-stable-stringify": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz", + "integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==", + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "isarray": "^2.0.5", + "jsonify": "^0.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -8015,6 +8118,15 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", + "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", + "license": "Public Domain", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/katex": { "version": "0.16.27", "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.27.tgz", @@ -8054,6 +8166,15 @@ "node": ">=0.10.0" } }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, "node_modules/langium": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/langium/-/langium-3.3.1.tgz", @@ -9514,6 +9635,15 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", @@ -9886,6 +10016,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -10262,6 +10401,132 @@ "event-target-polyfill": "^0.0.4" } }, + "node_modules/patch-package": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.1.tgz", + "integrity": "sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw==", + "license": "MIT", + "dependencies": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^4.1.2", + "ci-info": "^3.7.0", + "cross-spawn": "^7.0.3", + "find-yarn-workspace-root": "^2.0.0", + "fs-extra": "^10.0.0", + "json-stable-stringify": "^1.0.2", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.6", + "open": "^7.4.2", + "semver": "^7.5.3", + "slash": "^2.0.0", + "tmp": "^0.2.4", + "yaml": "^2.2.2" + }, + "bin": { + "patch-package": "index.js" + }, + "engines": { + "node": ">=14", + "npm": ">5" + } + }, + "node_modules/patch-package/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/patch-package/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/patch-package/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/patch-package/node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/patch-package/node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/patch-package/node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/patch-package/node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/path-data-parser": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", @@ -11570,6 +11835,23 @@ "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", "license": "MIT" }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -12218,6 +12500,15 @@ "integrity": "sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==", "license": "MIT" }, + "node_modules/tmp": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", + "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", diff --git a/epicshop/package.json b/epicshop/package.json index a09fb0a..2bdadb0 100644 --- a/epicshop/package.json +++ b/epicshop/package.json @@ -1,5 +1,8 @@ { "type": "module", + "scripts": { + "postinstall": "patch-package" + }, "dependencies": { "@epic-web/workshop-app": "^6.58.0", "@epic-web/workshop-utils": "^6.58.0", @@ -12,6 +15,7 @@ "fs-extra": "^11.3.3", "get-port": "^7.1.0", "match-sorter": "^8.2.0", - "p-limit": "^7.2.0" + "p-limit": "^7.2.0", + "patch-package": "^8.0.1" } } diff --git a/epicshop/patches/@epic-web+workshop-app+6.58.0.patch b/epicshop/patches/@epic-web+workshop-app+6.58.0.patch new file mode 100644 index 0000000..9a84a4f --- /dev/null +++ b/epicshop/patches/@epic-web+workshop-app+6.58.0.patch @@ -0,0 +1,348 @@ +diff --git a/node_modules/@epic-web/workshop-app/build/client/assets/set-playground-CqWopo_p.js b/node_modules/@epic-web/workshop-app/build/client/assets/set-playground-CqWopo_p.js +index a36cb62..b249436 100644 +--- a/node_modules/@epic-web/workshop-app/build/client/assets/set-playground-CqWopo_p.js ++++ b/node_modules/@epic-web/workshop-app/build/client/assets/set-playground-CqWopo_p.js +@@ -1,2 +1,23 @@ +-import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{R as S,T as P,V as C,I as D,P as O,C as k,S as T,a as I,G as R,L as E,b as B,c as A,d as F,e as G}from"./index-wbZv2KL3.js";import{a as h,I as m}from"./misc-GmfBFNKU.js";import{r as x}from"./index-Az39ZADK.js";import{c as f}from"./chunk-UIGDSWPH-D7TrB36R.js";import{B as L}from"./button-Bhee0nJ5.js";import{u as U,O as V}from"./onboarding-indicator-BtHxYHrp.js";import{s as Y}from"./progress-bar-CXiAexcc.js";import{D as _,a as z,b as H,c as $,d as q,e as W}from"./dialog-D9Rz0D0m.js";import{S as J}from"./tooltip-DOPvLR3d.js";import{u as b}from"./pe-BgHP_H47.js";import{u as K}from"./root-loader-CcoJXu7H.js";const y="set-playground";function g(){const o=K(),t=o.preferences?.playground?.persist??!1,n=o.preferences?.onboardingComplete?.includes(y)??!1;return{persistEnabled:t,shouldConfirm:!t&&!n}}function N({open:o,onOpenChange:t,onConfirm:n,isSubmitting:l,persistFetcher:a}){const u=b(),{persistEnabled:c}=g(),d=a.state!=="idle",r=a.data?.status==="success"?a.data.persist:c,i=!r;return e.jsx(_,{open:o,onOpenChange:t,children:e.jsxs(z,{className:"max-w-xl",children:[e.jsxs(H,{children:[e.jsx($,{children:"Playground ready for your first step"}),e.jsx(q,{children:"Nice work getting here! Setting the playground is how you bring the next step's instructions into your workspace."})]}),e.jsxs("div",{className:"space-y-4 text-sm",children:[e.jsx("p",{className:"text-muted-foreground",children:"This will replace whatever is currently in your playground with the next step's files. That is expected and the default workflow."}),e.jsxs("div",{className:"border-border bg-muted/40 space-y-3 rounded-md border p-4",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-foreground font-semibold",children:"Optional: Save a copy each time"}),e.jsxs("p",{className:"text-muted-foreground mt-1 text-sm",children:["When enabled, every set saves a copy in",e.jsx("span",{className:"font-mono",children:" saved-playgrounds"}),". You can change this later in Preferences."]}),e.jsx("p",{className:"text-muted-foreground mt-2 text-xs",children:"You can always manage this in Preferences."})]}),e.jsxs(a.Form,{method:"POST",action:"/persist-playground",children:[u,e.jsx("input",{type:"hidden",name:"persist",value:i?"true":"false"}),e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-foreground text-sm font-medium",children:"Persistence"}),e.jsx("p",{className:"text-muted-foreground text-xs",children:r?"Enabled":"Disabled"})]}),e.jsx("button",{type:"submit",role:"switch","aria-checked":r,"aria-label":`Toggle playground persistence ${r?"off":"on"}`,className:h("focus-visible:ring-ring relative inline-flex h-6 w-11 items-center rounded-full border transition",r?"border-foreground bg-foreground":"border-border bg-muted",d?"cursor-progress opacity-70":null),disabled:d,children:e.jsx("span",{className:h("bg-background inline-block h-5 w-5 rounded-full shadow transition",r?"translate-x-5":"translate-x-0")})})]})]})]})]}),e.jsxs(W,{children:[e.jsx("button",{type:"button",className:"border-border text-foreground hover:bg-muted focus-visible:ring-ring inline-flex items-center justify-center rounded-md border px-3 py-2 text-sm font-semibold",onClick:()=>t(!1),children:"Cancel"}),e.jsx(L,{varient:"primary",type:"button",onClick:n,disabled:l,children:l?"Setting...":"Set playground"})]})]})})}function M({appName:o,reset:t=!1,tooltipText:n,...l}){const a=f(),u=f(),c=b(),{shouldConfirm:d}=g(),[r,i]=x.useState(!1),s=x.useRef(null),p=x.useRef(!1),v=a.state!=="idle",j=e.jsx("button",{type:"submit",...l,className:h(l.className,a.state!=="idle"?"cursor-progress":null,a.data?.status==="error"?"cursor-not-allowed":null)});return e.jsxs(e.Fragment,{children:[e.jsxs(a.Form,{action:"/set-playground",method:"POST",className:"inline-flex items-center justify-center",ref:s,onSubmit:w=>{if(d&&!p.current){w.preventDefault(),i(!0);return}p.current=!1},children:[c,e.jsx("input",{type:"hidden",name:"appName",value:o}),t?e.jsx("input",{type:"hidden",name:"reset",value:"true"}):null,Y,n?e.jsx(J,{content:n,children:j}):j]}),e.jsx(N,{open:r,onOpenChange:i,isSubmitting:v,persistFetcher:u,onConfirm:()=>{p.current=!0,i(!1),s.current?.requestSubmit()}})]})}function de({playgroundAppName:o,allApps:t}){const n=f(),l=f(),{shouldConfirm:a}=g(),[u,c]=x.useState(!1),[d,r]=x.useState(null),i=n.state!=="idle";return e.jsxs(e.Fragment,{children:[e.jsxs(S,{name:"appName",value:o,onValueChange:s=>{if(a){r(s),c(!0);return}n.submit({appName:s},{method:"POST",action:"/set-playground"})},children:[e.jsxs(P,{"aria-label":"Select app for playground",className:h("radix-placeholder:text-gray-500 flex h-full w-full items-center justify-between text-left focus-visible:outline-none",n.state!=="idle"?"cursor-progress":null,n.data?.status==="error"?"cursor-not-allowed":null),children:[e.jsx("span",{className:"scrollbar-thin scrollbar-thumb-scrollbar w-80 flex-1 overflow-hidden text-ellipsis whitespace-nowrap",children:e.jsx(C,{placeholder:"Select current app",className:"inline-block w-40 text-ellipsis"})}),e.jsx(D,{children:e.jsx(m,{name:"TriangleDownSmall"})})]}),e.jsx(O,{children:e.jsxs(k,{position:"popper",align:"start",className:"z-20 max-h-[50vh] bg-black text-white lg:max-h-[70vh]",children:[e.jsx(T,{className:"flex h-5 cursor-default items-center justify-center",children:e.jsx(m,{name:"ChevronUp"})}),e.jsx(I,{className:"p-3",children:e.jsxs(R,{children:[e.jsx(E,{className:"px-5 pb-3 font-mono uppercase",children:"App"}),t.filter(s=>s.name!=="playground").map(s=>e.jsx(Q,{value:s.name,children:s.displayName},s.name))]})}),e.jsx(B,{className:"flex h-5 cursor-default items-center justify-center",children:e.jsx(m,{name:"ChevronDown"})})]})})]}),e.jsx(N,{open:u,onOpenChange:s=>{c(s),s||r(null)},isSubmitting:i,persistFetcher:l,onConfirm:()=>{d&&(c(!1),n.submit({appName:d},{method:"POST",action:"/set-playground"}),r(null))}})]})}function Q({value:o,children:t}){return e.jsxs(A,{value:o,className:"radix-disabled:text-red-500 radix-highlighted:opacity-100 radix-highlighted:outline-none radix-state-checked:opacity-100 relative flex cursor-pointer items-center rounded px-10 py-2 leading-none opacity-80 select-none",children:[e.jsx(F,{children:t}),e.jsx(G,{className:"absolute left-0 inline-flex w-[25px] items-center justify-center",children:e.jsx(m,{name:"CheckSmall"})})]})}function ue({appName:o,isOutdated:t,hideTextOnNarrow:n,showOnboardingIndicator:l=!1,onClick:a,className:u,...c}){const[d,r]=U(y);if(ENV.EPICSHOP_DEPLOYED)return null;const i=l&&d,s=h(u,i?"relative":null);return e.jsx(M,{appName:o,tooltipText:t?"The app the playground was set to has been updated. Click to update to the latest version.":"Playground is not set to the right app. Click to set Playground.",...c,className:s,onClick:p=>{a?.(p),l&&r()},children:e.jsxs("span",{className:"text-foreground-destructive flex items-center justify-center gap-1 hover:underline",children:[e.jsx(m,{name:"Unlinked",className:"animate-ping"})," ",e.jsx("span",{className:n?"hidden uppercase @min-[600px]:inline":"uppercase",children:t?"Playground Outdated":"Set to Playground"}),i?e.jsx(V,{tooltip:"Set the playground for this step.",size:"sm"}):null]})})}export{de as P,ue as S,M as a}; ++import{j as e}from"./jsx-runtime-C5WNSv3b.js"; ++import{R as S,T as P,V as C,I as D,P as O,C as k,S as T,a as I,G as R,L as E,b as B,c as A,d as F,e as G}from"./index-wbZv2KL3.js"; ++import{a as h,I as m}from"./misc-GmfBFNKU.js"; ++import{r as x}from"./index-Az39ZADK.js"; ++import{c as f}from"./chunk-UIGDSWPH-D7TrB36R.js"; ++import{B as L}from"./button-Bhee0nJ5.js"; ++import{u as U,O as V}from"./onboarding-indicator-BtHxYHrp.js"; ++import{s as Y}from"./progress-bar-CXiAexcc.js"; ++import{D as _,a as z,b as H,c as $,d as q,e as W}from"./dialog-D9Rz0D0m.js"; ++import{S as J}from"./tooltip-DOPvLR3d.js"; ++import{u as b}from"./pe-BgHP_H47.js"; ++import{u as K}from"./root-loader-CcoJXu7H.js"; ++const y="set-playground"; ++const Z="saved-playground:"; ++const Q="__saved_playgrounds__"; ++function g(){const o=K(),t=o.preferences?.playground?.persist??!1,n=o.preferences?.onboardingComplete?.includes(y)??!1;return{persistEnabled:t,shouldConfirm:!t&&!n}} ++function N({open:o,onOpenChange:t,onConfirm:n,isSubmitting:l,persistFetcher:a}){const u=b(),{persistEnabled:c}=g(),d=a.state!=="idle",r=a.data?.status==="success"?a.data.persist:c,i=!r;return e.jsx(_,{open:o,onOpenChange:t,children:e.jsxs(z,{className:"max-w-xl",children:[e.jsxs(H,{children:[e.jsx($,{children:"Playground ready for your first step"}),e.jsx(q,{children:"Nice work getting here! Setting the playground is how you bring the next step's instructions into your workspace."})]}),e.jsxs("div",{className:"space-y-4 text-sm",children:[e.jsx("p",{className:"text-muted-foreground",children:"This will replace whatever is currently in your playground with the next step's files. That is expected and the default workflow."}),e.jsxs("div",{className:"border-border bg-muted/40 space-y-3 rounded-md border p-4",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-foreground font-semibold",children:"Optional: Save a copy each time"}),e.jsxs("p",{className:"text-muted-foreground mt-1 text-sm",children:["When enabled, every set saves a copy in",e.jsx("span",{className:"font-mono",children:" saved-playgrounds"}),". You can change this later in Preferences."]}),e.jsx("p",{className:"text-muted-foreground mt-2 text-xs",children:"You can always manage this in Preferences."})]}),e.jsxs(a.Form,{method:"POST",action:"/persist-playground",children:[u,e.jsx("input",{type:"hidden",name:"persist",value:i?"true":"false"}),e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-foreground text-sm font-medium",children:"Persistence"}),e.jsx("p",{className:"text-muted-foreground text-xs",children:r?"Enabled":"Disabled"})]}),e.jsx("button",{type:"submit",role:"switch","aria-checked":r,"aria-label":`Toggle playground persistence ${r?"off":"on"}`,className:h("focus-visible:ring-ring relative inline-flex h-6 w-11 items-center rounded-full border transition",r?"border-foreground bg-foreground":"border-border bg-muted",d?"cursor-progress opacity-70":null),disabled:d,children:e.jsx("span",{className:h("bg-background inline-block h-5 w-5 rounded-full shadow transition",r?"translate-x-5":"translate-x-0")})})]})]})]})]}),e.jsxs(W,{children:[e.jsx("button",{type:"button",className:"border-border text-foreground hover:bg-muted focus-visible:ring-ring inline-flex items-center justify-center rounded-md border px-3 py-2 text-sm font-semibold",onClick:()=>t(!1),children:"Cancel"}),e.jsx(L,{varient:"primary",type:"button",onClick:n,disabled:l,children:l?"Setting...":"Set playground"})]})]})})} ++function M({appName:o,reset:t=!1,tooltipText:n,...l}){const a=f(),u=f(),c=b(),{shouldConfirm:d}=g(),[r,i]=x.useState(!1),s=x.useRef(null),p=x.useRef(!1),v=a.state!=="idle",j=e.jsx("button",{type:"submit",...l,className:h(l.className,a.state!=="idle"?"cursor-progress":null,a.data?.status==="error"?"cursor-not-allowed":null)});return e.jsxs(e.Fragment,{children:[e.jsxs(a.Form,{action:"/set-playground",method:"POST",className:"inline-flex items-center justify-center",ref:s,onSubmit:w=>{if(d&&!p.current){w.preventDefault(),i(!0);return}p.current=!1},children:[c,e.jsx("input",{type:"hidden",name:"appName",value:o}),t?e.jsx("input",{type:"hidden",name:"reset",value:"true"}):null,Y,n?e.jsx(J,{content:n,children:j}):j]}),e.jsx(N,{open:r,onOpenChange:i,isSubmitting:v,persistFetcher:u,onConfirm:()=>{p.current=!0,i(!1),s.current?.requestSubmit()}})]})} ++function de({playgroundAppName:o,allApps:t}){const n=f(),l=f(),{shouldConfirm:a,persistEnabled:u}=g(),p=K(),v=u?p?.savedPlaygrounds??[]:[],[c,d]=x.useState(!1),[r,i]=x.useState(null),[s,w]=x.useState(!1),[j,M]=x.useState(""),y2=n.state!=="idle",savedItems=x.useMemo(()=>v.map(Ee=>{const Re=t.find(Te=>Te.name===Ee.appName);return{...Ee,displayName:Re?Re.displayName:Ee.appName}}),[v,t]),Ue=j.trim().toLowerCase(),De=Ue?savedItems.filter(Ee=>`${Ee.displayName} ${Ee.appName} ${Ee.savedAt}`.toLowerCase().includes(Ue)):savedItems,Le=u;return e.jsxs(e.Fragment,{children:[e.jsxs(S,{name:"appName",value:o,onValueChange:Ee=>{if(Ee===Q){w(!0);return}if(a){i(Ee),d(!0);return}n.submit({appName:Ee},{method:"POST",action:"/set-playground"})},children:[e.jsxs(P,{"aria-label":"Select app for playground",className:h("radix-placeholder:text-gray-500 flex h-full w-full items-center justify-between text-left focus-visible:outline-none",n.state!=="idle"?"cursor-progress":null,n.data?.status==="error"?"cursor-not-allowed":null),children:[e.jsx("span",{className:"scrollbar-thin scrollbar-thumb-scrollbar w-80 flex-1 overflow-hidden text-ellipsis whitespace-nowrap",children:e.jsx(C,{placeholder:"Select current app",className:"inline-block w-40 text-ellipsis"})}),e.jsx(D,{children:e.jsx(m,{name:"TriangleDownSmall"})})]}),e.jsx(O,{children:e.jsxs(k,{position:"popper",align:"start",className:"z-20 max-h-[50vh] bg-black text-white lg:max-h-[70vh]",children:[e.jsx(T,{className:"flex h-5 cursor-default items-center justify-center",children:e.jsx(m,{name:"ChevronUp"})}),e.jsx(I,{className:"p-3",children:e.jsxs(R,{children:[e.jsx(E,{className:"px-5 pb-3 font-mono uppercase",children:"App"}),t.filter(Ee=>Ee.name!=="playground").map(Ee=>e.jsx(Qa,{value:Ee.name,children:Ee.displayName},Ee.name)),Le?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"my-2 h-px bg-white/10"}),e.jsx(Qa,{value:Q,children:savedItems.length>0?`Saved playgrounds (${savedItems.length})...`:"Saved playgrounds..."})]}):null]})}),e.jsx(B,{className:"flex h-5 cursor-default items-center justify-center",children:e.jsx(m,{name:"ChevronDown"})})]})})]}),e.jsx(N,{open:c,onOpenChange:Ee=>{d(Ee),Ee||i(null)},isSubmitting:y2,persistFetcher:l,onConfirm:()=>{r&&(d(!1),n.submit({appName:r},{method:"POST",action:"/set-playground"}),i(null))}}),Le?e.jsx(_,{open:s,onOpenChange:Ee=>{w(Ee),Ee||M("")},children:e.jsxs(z,{className:"max-w-xl",children:[e.jsxs(H,{children:[e.jsx($,{children:"Saved playgrounds"}),e.jsx(q,{children:"Pick a saved playground to restore into your workspace."})]}),e.jsxs("div",{className:"space-y-3 text-sm",children:[e.jsx("input",{type:"text",value:j,onChange:Ee=>M(Ee.currentTarget.value),placeholder:"Filter saved playgrounds",className:"border-border bg-background text-foreground w-full rounded-md border px-3 py-2 text-sm"}),e.jsx("div",{className:"border-border bg-muted/20 max-h-72 overflow-y-auto rounded-md border",children:De.length>0?De.map(Ee=>e.jsxs("button",{type:"button",className:"hover:bg-muted/40 flex w-full flex-col gap-1 px-3 py-2 text-left",disabled:y2,onClick:()=>{w(!1),M(""),n.submit({appName:`${Z}${Ee.id}`},{method:"POST",action:"/set-playground"})},children:[e.jsx("span",{className:"text-sm font-medium",children:Ee.displayName}),e.jsx("span",{className:"text-muted-foreground text-xs",children:Ee.savedAt})]},Ee.id)):e.jsx("p",{className:"text-muted-foreground px-3 py-6 text-center text-sm",children:"No saved playgrounds found."})})]}),e.jsxs(W,{children:[e.jsx("button",{type:"button",className:"border-border text-foreground hover:bg-muted focus-visible:ring-ring inline-flex items-center justify-center rounded-md border px-3 py-2 text-sm font-semibold",onClick:()=>w(!1),children:"Close"})]})]})}):null]})} ++function Qa({value:o,children:t}){return e.jsxs(A,{value:o,className:"radix-disabled:text-red-500 radix-highlighted:opacity-100 radix-highlighted:outline-none radix-state-checked:opacity-100 relative flex cursor-pointer items-center rounded px-10 py-2 leading-none opacity-80 select-none",children:[e.jsx(F,{children:t}),e.jsx(G,{className:"absolute left-0 inline-flex w-[25px] items-center justify-center",children:e.jsx(m,{name:"CheckSmall"})})]})} ++function ue({appName:o,isOutdated:t,hideTextOnNarrow:n,showOnboardingIndicator:l=!1,onClick:a,className:u,...c}){const[d,r]=U(y);if(ENV.EPICSHOP_DEPLOYED)return null;const i=l&&d,s=h(u,i?"relative":null);return e.jsx(M,{appName:o,tooltipText:t?"The app the playground was set to has been updated. Click to update to the latest version.":"Playground is not set to the right app. Click to set Playground.",...c,className:s,onClick:p=>{a?.(p),l&&r()},children:e.jsxs("span",{className:"text-foreground-destructive flex items-center justify-center gap-1 hover:underline",children:[e.jsx(m,{name:"Unlinked",className:"animate-ping"})," ",e.jsx("span",{className:n?"hidden uppercase @min-[600px]:inline":"uppercase",children:t?"Playground Outdated":"Set to Playground"}),i?e.jsx(V,{tooltip:"Set the playground for this step.",size:"sm"}):null]})})} ++export{de as P,ue as S,M as a}; + //# sourceMappingURL=set-playground-CqWopo_p.js.map +diff --git a/node_modules/@epic-web/workshop-app/build/server/index.js b/node_modules/@epic-web/workshop-app/build/server/index.js +index a19b2a3..11ec3a1 100644 +--- a/node_modules/@epic-web/workshop-app/build/server/index.js ++++ b/node_modules/@epic-web/workshop-app/build/server/index.js +@@ -1978,6 +1978,45 @@ const meta$6 = ({ + requestInfo: loaderData.requestInfo + }); + }; ++const SAVED_PLAYGROUND_PREFIX = "saved-playground:"; ++const SAVED_PLAYGROUNDS_DIR_NAME = "saved-playgrounds"; ++function getPlaygroundAppNameInfoPath() { ++ return path.join(getWorkshopRoot(), "node_modules", ".cache", "epicshop", "playground.json"); ++} ++function parseSavedPlaygroundDirName(dirName) { ++ const [datePart, timePart, ...appNameParts] = dirName.split("_"); ++ if (!datePart || !timePart || appNameParts.length === 0) return null; ++ const appName = appNameParts.join("_"); ++ const timestamp = `${datePart}_${timePart}`; ++ const savedAt = `${datePart} ${timePart.replace(/\./g, ":")}`; ++ return { ++ id: dirName, ++ appName, ++ savedAt, ++ timestamp ++ }; ++} ++async function getSavedPlaygrounds() { ++ const savedDir = path.join(getWorkshopRoot(), SAVED_PLAYGROUNDS_DIR_NAME); ++ if (!await fsExtra.pathExists(savedDir)) return []; ++ const entries = await fs.promises.readdir(savedDir, { withFileTypes: true }); ++ const parsed = entries.filter((entry) => entry.isDirectory()).map((entry) => parseSavedPlaygroundDirName(entry.name)).filter(Boolean); ++ parsed.sort((a, b) => b.timestamp.localeCompare(a.timestamp)); ++ return parsed; ++} ++async function getSavedPlaygroundById(savedId) { ++ const parsed = parseSavedPlaygroundDirName(savedId); ++ if (!parsed) return null; ++ const fullPath = path.join(getWorkshopRoot(), SAVED_PLAYGROUNDS_DIR_NAME, savedId); ++ if (!await fsExtra.pathExists(fullPath)) return null; ++ return { ...parsed, fullPath }; ++} ++async function writePlaygroundAppName(appName) { ++ if (!appName) return; ++ const infoPath = getPlaygroundAppNameInfoPath(); ++ await fsExtra.ensureDir(path.dirname(infoPath)); ++ await fsExtra.writeJSON(infoPath, { appName }); ++} + async function loader$H({ + request + }) { +@@ -2027,6 +2066,10 @@ async function loader$H({ + exerciseChanges: checkForExerciseChanges(), + loggedInProductHosts: getLoggedInProductHosts() + }); ++ const savedPlaygrounds = asyncStuff.preferences?.playground?.persist ? await getSavedPlaygrounds().catch((error) => { ++ console.error("Failed to read saved playgrounds", error); ++ return []; ++ }) : []; + const presentUsers = await getPresentUsers({ + request, + timings +@@ -2054,6 +2097,7 @@ async function loader$H({ + fullPath, + relativePath + })), ++ savedPlaygrounds, + ENV: getEnv(), + requestInfo: { + protocol: new URL(request.url).protocol, +@@ -7677,34 +7721,92 @@ async function action$c({ + }); + } + const form = result.data; +- const app2 = await getAppByName(form.appName); +- if (!app2) { +- return dataWithPE(request, formData, { +- status: "error", +- error: `App ${form.appName} not found` +- }, { +- status: 404 +- }); +- } +- const converseApp = isProblemApp(app2) && app2.solutionName ? await getAppByName(app2.solutionName) : isSolutionApp(app2) && app2.problemName ? await getAppByName(app2.problemName) : void 0; +- try { +- await setPlayground(app2.fullPath, { +- reset: form.reset +- }); +- } catch (error) { +- const message = getErrorMessage(error); +- console.error("Error setting playground", message); +- return dataWithPE(request, formData, { +- status: "error", +- error: message +- }, { +- status: 500, +- headers: await createToastHeaders({ +- type: "error", +- title: "Error", +- description: "There was an error setting the playground. Check the terminal for details." +- }) +- }); ++ let converseApp; ++ if (form.appName.startsWith(SAVED_PLAYGROUND_PREFIX)) { ++ const savedId = form.appName.slice(SAVED_PLAYGROUND_PREFIX.length); ++ if (!savedId) { ++ return dataWithPE(request, formData, { ++ status: "error", ++ error: "Saved playground is missing an id" ++ }, { ++ status: 400 ++ }); ++ } ++ const preferences = await getPreferences(); ++ if (!preferences?.playground?.persist) { ++ return dataWithPE(request, formData, { ++ status: "error", ++ error: "Playground persistence is disabled" ++ }, { ++ status: 403, ++ headers: await createToastHeaders({ ++ type: "error", ++ title: "Persistence disabled", ++ description: "Enable playground persistence in Preferences to use saved playgrounds." ++ }) ++ }); ++ } ++ const savedPlayground = await getSavedPlaygroundById(savedId); ++ if (!savedPlayground) { ++ return dataWithPE(request, formData, { ++ status: "error", ++ error: `Saved playground ${savedId} not found` ++ }, { ++ status: 404 ++ }); ++ } ++ const baseApp = savedPlayground.appName ? await getAppByName(savedPlayground.appName) : null; ++ converseApp = baseApp && isProblemApp(baseApp) && baseApp.solutionName ? await getAppByName(baseApp.solutionName) : baseApp && isSolutionApp(baseApp) && baseApp.problemName ? await getAppByName(baseApp.problemName) : void 0; ++ try { ++ await setPlayground(savedPlayground.fullPath, { ++ reset: form.reset ++ }); ++ await writePlaygroundAppName(savedPlayground.appName); ++ } catch (error) { ++ const message = getErrorMessage(error); ++ console.error("Error setting playground", message); ++ return dataWithPE(request, formData, { ++ status: "error", ++ error: message ++ }, { ++ status: 500, ++ headers: await createToastHeaders({ ++ type: "error", ++ title: "Error", ++ description: "There was an error setting the playground. Check the terminal for details." ++ }) ++ }); ++ } ++ } else { ++ const app2 = await getAppByName(form.appName); ++ if (!app2) { ++ return dataWithPE(request, formData, { ++ status: "error", ++ error: `App ${form.appName} not found` ++ }, { ++ status: 404 ++ }); ++ } ++ converseApp = isProblemApp(app2) && app2.solutionName ? await getAppByName(app2.solutionName) : isSolutionApp(app2) && app2.problemName ? await getAppByName(app2.problemName) : void 0; ++ try { ++ await setPlayground(app2.fullPath, { ++ reset: form.reset ++ }); ++ } catch (error) { ++ const message = getErrorMessage(error); ++ console.error("Error setting playground", message); ++ return dataWithPE(request, formData, { ++ status: "error", ++ error: message ++ }, { ++ status: 500, ++ headers: await createToastHeaders({ ++ type: "error", ++ title: "Error", ++ description: "There was an error setting the playground. Check the terminal for details." ++ }) ++ }); ++ } + } + const apps = await getApps({ + forceFresh: true +@@ -7893,16 +7995,41 @@ function PlaygroundChooser({ + const fetcher = useFetcher(); + const persistFetcher = useFetcher(); + const { +- shouldConfirm ++ shouldConfirm, ++ persistEnabled + } = usePlaygroundOnboardingGate(); ++ const rootData = useRootLoaderData(); ++ const savedPlaygrounds = persistEnabled ? rootData?.savedPlaygrounds ?? [] : []; + const [dialogOpen, setDialogOpen] = React.useState(false); + const [pendingAppName, setPendingAppName] = React.useState(null); ++ const [savedDialogOpen, setSavedDialogOpen] = React.useState(false); ++ const [savedFilter, setSavedFilter] = React.useState(""); + const isSubmitting = fetcher.state !== "idle"; ++ const savedPlaygroundItems = React.useMemo(() => { ++ return savedPlaygrounds.map((saved) => { ++ const baseApp = allApps.find((app2) => app2.name === saved.appName); ++ return { ++ ...saved, ++ displayName: baseApp ? baseApp.displayName : saved.appName ++ }; ++ }); ++ }, [savedPlaygrounds, allApps]); ++ const normalizedFilter = savedFilter.trim().toLowerCase(); ++ const filteredSavedPlaygrounds = normalizedFilter ? savedPlaygroundItems.filter((saved) => { ++ const haystack = `${saved.displayName} ${saved.appName} ${saved.savedAt}`.toLowerCase(); ++ return haystack.includes(normalizedFilter); ++ }) : savedPlaygroundItems; ++ const showSavedPlaygrounds = persistEnabled; ++ const savedPlaygroundSelectValue = "__saved_playgrounds__"; + return /* @__PURE__ */ jsxs(Fragment, { + children: [/* @__PURE__ */ jsxs(Select.Root, { + name: "appName", + value: playgroundAppName, + onValueChange: (appName) => { ++ if (appName === savedPlaygroundSelectValue) { ++ setSavedDialogOpen(true); ++ return; ++ } + if (shouldConfirm) { + setPendingAppName(appName); + setDialogOpen(true); +@@ -7950,7 +8077,14 @@ function PlaygroundChooser({ + value: app2.name, + children: app2.displayName + }, app2.name); +- })] ++ }), showSavedPlaygrounds ? /* @__PURE__ */ jsxs(Fragment, { ++ children: [/* @__PURE__ */ jsx("div", { ++ className: "my-2 h-px bg-white/10" ++ }), /* @__PURE__ */ jsx(SelectItem$1, { ++ value: savedPlaygroundSelectValue, ++ children: savedPlaygroundItems.length > 0 ? `Saved playgrounds (${savedPlaygroundItems.length})...` : "Saved playgrounds..." ++ })] ++ }) : null] + }) + }), /* @__PURE__ */ jsx(Select.ScrollDownButton, { + className: "flex h-5 cursor-default items-center justify-center", +@@ -7981,7 +8115,68 @@ function PlaygroundChooser({ + }); + setPendingAppName(null); + } +- })] ++ }), showSavedPlaygrounds ? /* @__PURE__ */ jsx(Dialog, { ++ open: savedDialogOpen, ++ onOpenChange: (open) => { ++ setSavedDialogOpen(open); ++ if (!open) { ++ setSavedFilter(""); ++ } ++ }, ++ children: /* @__PURE__ */ jsxs(DialogContent, { ++ className: "max-w-xl", ++ children: [/* @__PURE__ */ jsxs(DialogHeader, { ++ children: [/* @__PURE__ */ jsx(DialogTitle, { ++ children: "Saved playgrounds" ++ }), /* @__PURE__ */ jsx(DialogDescription, { ++ children: "Pick a saved playground to restore into your workspace." ++ })] ++ }), /* @__PURE__ */ jsxs("div", { ++ className: "space-y-3 text-sm", ++ children: [/* @__PURE__ */ jsx("input", { ++ type: "text", ++ value: savedFilter, ++ onChange: (event) => setSavedFilter(event.currentTarget.value), ++ placeholder: "Filter saved playgrounds", ++ className: "border-border bg-background text-foreground w-full rounded-md border px-3 py-2 text-sm" ++ }), /* @__PURE__ */ jsx("div", { ++ className: "border-border bg-muted/20 max-h-72 overflow-y-auto rounded-md border", ++ children: filteredSavedPlaygrounds.length > 0 ? filteredSavedPlaygrounds.map((saved) => /* @__PURE__ */ jsxs("button", { ++ type: "button", ++ className: "hover:bg-muted/40 flex w-full flex-col gap-1 px-3 py-2 text-left", ++ disabled: isSubmitting, ++ onClick: () => { ++ setSavedDialogOpen(false); ++ setSavedFilter(""); ++ void fetcher.submit({ ++ appName: `${SAVED_PLAYGROUND_PREFIX}${saved.id}` ++ }, { ++ method: "POST", ++ action: "/set-playground" ++ }); ++ }, ++ children: [/* @__PURE__ */ jsx("span", { ++ className: "text-sm font-medium", ++ children: saved.displayName ++ }), /* @__PURE__ */ jsx("span", { ++ className: "text-muted-foreground text-xs", ++ children: saved.savedAt ++ })] ++ }, saved.id)) : /* @__PURE__ */ jsx("p", { ++ className: "text-muted-foreground px-3 py-6 text-center text-sm", ++ children: "No saved playgrounds found." ++ }) ++ })] ++ }), /* @__PURE__ */ jsxs(DialogFooter, { ++ children: [/* @__PURE__ */ jsx("button", { ++ type: "button", ++ className: "border-border text-foreground hover:bg-muted focus-visible:ring-ring inline-flex items-center justify-center rounded-md border px-3 py-2 text-sm font-semibold", ++ onClick: () => setSavedDialogOpen(false), ++ children: "Close" ++ })] ++ })] ++ }) ++ }) : null] + }); + } + function SelectItem$1({ From 1e089fe9b48be6e0ba6547aeedc3556830dc4b54 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 18 Jan 2026 22:28:45 +0000 Subject: [PATCH 2/3] Refresh saved playground list Co-authored-by: me --- .../patches/@epic-web+workshop-app+6.58.0.patch | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/epicshop/patches/@epic-web+workshop-app+6.58.0.patch b/epicshop/patches/@epic-web+workshop-app+6.58.0.patch index 9a84a4f..625fe47 100644 --- a/epicshop/patches/@epic-web+workshop-app+6.58.0.patch +++ b/epicshop/patches/@epic-web+workshop-app+6.58.0.patch @@ -1,5 +1,5 @@ diff --git a/node_modules/@epic-web/workshop-app/build/client/assets/set-playground-CqWopo_p.js b/node_modules/@epic-web/workshop-app/build/client/assets/set-playground-CqWopo_p.js -index a36cb62..b249436 100644 +index a36cb62..a69b3a3 100644 --- a/node_modules/@epic-web/workshop-app/build/client/assets/set-playground-CqWopo_p.js +++ b/node_modules/@epic-web/workshop-app/build/client/assets/set-playground-CqWopo_p.js @@ -1,2 +1,23 @@ @@ -8,7 +8,7 @@ index a36cb62..b249436 100644 +import{R as S,T as P,V as C,I as D,P as O,C as k,S as T,a as I,G as R,L as E,b as B,c as A,d as F,e as G}from"./index-wbZv2KL3.js"; +import{a as h,I as m}from"./misc-GmfBFNKU.js"; +import{r as x}from"./index-Az39ZADK.js"; -+import{c as f}from"./chunk-UIGDSWPH-D7TrB36R.js"; ++import{c as f,j as rr}from"./chunk-UIGDSWPH-D7TrB36R.js"; +import{B as L}from"./button-Bhee0nJ5.js"; +import{u as U,O as V}from"./onboarding-indicator-BtHxYHrp.js"; +import{s as Y}from"./progress-bar-CXiAexcc.js"; @@ -22,13 +22,13 @@ index a36cb62..b249436 100644 +function g(){const o=K(),t=o.preferences?.playground?.persist??!1,n=o.preferences?.onboardingComplete?.includes(y)??!1;return{persistEnabled:t,shouldConfirm:!t&&!n}} +function N({open:o,onOpenChange:t,onConfirm:n,isSubmitting:l,persistFetcher:a}){const u=b(),{persistEnabled:c}=g(),d=a.state!=="idle",r=a.data?.status==="success"?a.data.persist:c,i=!r;return e.jsx(_,{open:o,onOpenChange:t,children:e.jsxs(z,{className:"max-w-xl",children:[e.jsxs(H,{children:[e.jsx($,{children:"Playground ready for your first step"}),e.jsx(q,{children:"Nice work getting here! Setting the playground is how you bring the next step's instructions into your workspace."})]}),e.jsxs("div",{className:"space-y-4 text-sm",children:[e.jsx("p",{className:"text-muted-foreground",children:"This will replace whatever is currently in your playground with the next step's files. That is expected and the default workflow."}),e.jsxs("div",{className:"border-border bg-muted/40 space-y-3 rounded-md border p-4",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-foreground font-semibold",children:"Optional: Save a copy each time"}),e.jsxs("p",{className:"text-muted-foreground mt-1 text-sm",children:["When enabled, every set saves a copy in",e.jsx("span",{className:"font-mono",children:" saved-playgrounds"}),". You can change this later in Preferences."]}),e.jsx("p",{className:"text-muted-foreground mt-2 text-xs",children:"You can always manage this in Preferences."})]}),e.jsxs(a.Form,{method:"POST",action:"/persist-playground",children:[u,e.jsx("input",{type:"hidden",name:"persist",value:i?"true":"false"}),e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-foreground text-sm font-medium",children:"Persistence"}),e.jsx("p",{className:"text-muted-foreground text-xs",children:r?"Enabled":"Disabled"})]}),e.jsx("button",{type:"submit",role:"switch","aria-checked":r,"aria-label":`Toggle playground persistence ${r?"off":"on"}`,className:h("focus-visible:ring-ring relative inline-flex h-6 w-11 items-center rounded-full border transition",r?"border-foreground bg-foreground":"border-border bg-muted",d?"cursor-progress opacity-70":null),disabled:d,children:e.jsx("span",{className:h("bg-background inline-block h-5 w-5 rounded-full shadow transition",r?"translate-x-5":"translate-x-0")})})]})]})]})]}),e.jsxs(W,{children:[e.jsx("button",{type:"button",className:"border-border text-foreground hover:bg-muted focus-visible:ring-ring inline-flex items-center justify-center rounded-md border px-3 py-2 text-sm font-semibold",onClick:()=>t(!1),children:"Cancel"}),e.jsx(L,{varient:"primary",type:"button",onClick:n,disabled:l,children:l?"Setting...":"Set playground"})]})]})})} +function M({appName:o,reset:t=!1,tooltipText:n,...l}){const a=f(),u=f(),c=b(),{shouldConfirm:d}=g(),[r,i]=x.useState(!1),s=x.useRef(null),p=x.useRef(!1),v=a.state!=="idle",j=e.jsx("button",{type:"submit",...l,className:h(l.className,a.state!=="idle"?"cursor-progress":null,a.data?.status==="error"?"cursor-not-allowed":null)});return e.jsxs(e.Fragment,{children:[e.jsxs(a.Form,{action:"/set-playground",method:"POST",className:"inline-flex items-center justify-center",ref:s,onSubmit:w=>{if(d&&!p.current){w.preventDefault(),i(!0);return}p.current=!1},children:[c,e.jsx("input",{type:"hidden",name:"appName",value:o}),t?e.jsx("input",{type:"hidden",name:"reset",value:"true"}):null,Y,n?e.jsx(J,{content:n,children:j}):j]}),e.jsx(N,{open:r,onOpenChange:i,isSubmitting:v,persistFetcher:u,onConfirm:()=>{p.current=!0,i(!1),s.current?.requestSubmit()}})]})} -+function de({playgroundAppName:o,allApps:t}){const n=f(),l=f(),{shouldConfirm:a,persistEnabled:u}=g(),p=K(),v=u?p?.savedPlaygrounds??[]:[],[c,d]=x.useState(!1),[r,i]=x.useState(null),[s,w]=x.useState(!1),[j,M]=x.useState(""),y2=n.state!=="idle",savedItems=x.useMemo(()=>v.map(Ee=>{const Re=t.find(Te=>Te.name===Ee.appName);return{...Ee,displayName:Re?Re.displayName:Ee.appName}}),[v,t]),Ue=j.trim().toLowerCase(),De=Ue?savedItems.filter(Ee=>`${Ee.displayName} ${Ee.appName} ${Ee.savedAt}`.toLowerCase().includes(Ue)):savedItems,Le=u;return e.jsxs(e.Fragment,{children:[e.jsxs(S,{name:"appName",value:o,onValueChange:Ee=>{if(Ee===Q){w(!0);return}if(a){i(Ee),d(!0);return}n.submit({appName:Ee},{method:"POST",action:"/set-playground"})},children:[e.jsxs(P,{"aria-label":"Select app for playground",className:h("radix-placeholder:text-gray-500 flex h-full w-full items-center justify-between text-left focus-visible:outline-none",n.state!=="idle"?"cursor-progress":null,n.data?.status==="error"?"cursor-not-allowed":null),children:[e.jsx("span",{className:"scrollbar-thin scrollbar-thumb-scrollbar w-80 flex-1 overflow-hidden text-ellipsis whitespace-nowrap",children:e.jsx(C,{placeholder:"Select current app",className:"inline-block w-40 text-ellipsis"})}),e.jsx(D,{children:e.jsx(m,{name:"TriangleDownSmall"})})]}),e.jsx(O,{children:e.jsxs(k,{position:"popper",align:"start",className:"z-20 max-h-[50vh] bg-black text-white lg:max-h-[70vh]",children:[e.jsx(T,{className:"flex h-5 cursor-default items-center justify-center",children:e.jsx(m,{name:"ChevronUp"})}),e.jsx(I,{className:"p-3",children:e.jsxs(R,{children:[e.jsx(E,{className:"px-5 pb-3 font-mono uppercase",children:"App"}),t.filter(Ee=>Ee.name!=="playground").map(Ee=>e.jsx(Qa,{value:Ee.name,children:Ee.displayName},Ee.name)),Le?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"my-2 h-px bg-white/10"}),e.jsx(Qa,{value:Q,children:savedItems.length>0?`Saved playgrounds (${savedItems.length})...`:"Saved playgrounds..."})]}):null]})}),e.jsx(B,{className:"flex h-5 cursor-default items-center justify-center",children:e.jsx(m,{name:"ChevronDown"})})]})})]}),e.jsx(N,{open:c,onOpenChange:Ee=>{d(Ee),Ee||i(null)},isSubmitting:y2,persistFetcher:l,onConfirm:()=>{r&&(d(!1),n.submit({appName:r},{method:"POST",action:"/set-playground"}),i(null))}}),Le?e.jsx(_,{open:s,onOpenChange:Ee=>{w(Ee),Ee||M("")},children:e.jsxs(z,{className:"max-w-xl",children:[e.jsxs(H,{children:[e.jsx($,{children:"Saved playgrounds"}),e.jsx(q,{children:"Pick a saved playground to restore into your workspace."})]}),e.jsxs("div",{className:"space-y-3 text-sm",children:[e.jsx("input",{type:"text",value:j,onChange:Ee=>M(Ee.currentTarget.value),placeholder:"Filter saved playgrounds",className:"border-border bg-background text-foreground w-full rounded-md border px-3 py-2 text-sm"}),e.jsx("div",{className:"border-border bg-muted/20 max-h-72 overflow-y-auto rounded-md border",children:De.length>0?De.map(Ee=>e.jsxs("button",{type:"button",className:"hover:bg-muted/40 flex w-full flex-col gap-1 px-3 py-2 text-left",disabled:y2,onClick:()=>{w(!1),M(""),n.submit({appName:`${Z}${Ee.id}`},{method:"POST",action:"/set-playground"})},children:[e.jsx("span",{className:"text-sm font-medium",children:Ee.displayName}),e.jsx("span",{className:"text-muted-foreground text-xs",children:Ee.savedAt})]},Ee.id)):e.jsx("p",{className:"text-muted-foreground px-3 py-6 text-center text-sm",children:"No saved playgrounds found."})})]}),e.jsxs(W,{children:[e.jsx("button",{type:"button",className:"border-border text-foreground hover:bg-muted focus-visible:ring-ring inline-flex items-center justify-center rounded-md border px-3 py-2 text-sm font-semibold",onClick:()=>w(!1),children:"Close"})]})]})}):null]})} ++function de({playgroundAppName:o,allApps:t}){const n=f(),l=f(),{shouldConfirm:a,persistEnabled:u}=g(),p=K(),revalidator=rr(),v=u?p?.savedPlaygrounds??[]:[],[c,d]=x.useState(!1),[r,i]=x.useState(null),[s,w]=x.useState(!1),[j,M]=x.useState(""),y2=n.state!=="idle",savedItems=x.useMemo(()=>v.map(Ee=>{const Re=t.find(Te=>Te.name===Ee.appName);return{...Ee,displayName:Re?Re.displayName:Ee.appName}}),[v,t]),Ue=j.trim().toLowerCase(),De=Ue?savedItems.filter(Ee=>`${Ee.displayName} ${Ee.appName} ${Ee.savedAt}`.toLowerCase().includes(Ue)):savedItems,Le=u;return e.jsxs(e.Fragment,{children:[e.jsxs(S,{name:"appName",value:o,onValueChange:Ee=>{if(Ee===Q){revalidator.revalidate(),w(!0);return}if(a){i(Ee),d(!0);return}n.submit({appName:Ee},{method:"POST",action:"/set-playground"})},children:[e.jsxs(P,{"aria-label":"Select app for playground",className:h("radix-placeholder:text-gray-500 flex h-full w-full items-center justify-between text-left focus-visible:outline-none",n.state!=="idle"?"cursor-progress":null,n.data?.status==="error"?"cursor-not-allowed":null),children:[e.jsx("span",{className:"scrollbar-thin scrollbar-thumb-scrollbar w-80 flex-1 overflow-hidden text-ellipsis whitespace-nowrap",children:e.jsx(C,{placeholder:"Select current app",className:"inline-block w-40 text-ellipsis"})}),e.jsx(D,{children:e.jsx(m,{name:"TriangleDownSmall"})})]}),e.jsx(O,{children:e.jsxs(k,{position:"popper",align:"start",className:"z-20 max-h-[50vh] bg-black text-white lg:max-h-[70vh]",children:[e.jsx(T,{className:"flex h-5 cursor-default items-center justify-center",children:e.jsx(m,{name:"ChevronUp"})}),e.jsx(I,{className:"p-3",children:e.jsxs(R,{children:[e.jsx(E,{className:"px-5 pb-3 font-mono uppercase",children:"App"}),t.filter(Ee=>Ee.name!=="playground").map(Ee=>e.jsx(Qa,{value:Ee.name,children:Ee.displayName},Ee.name)),Le?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"my-2 h-px bg-white/10"}),e.jsx(Qa,{value:Q,children:savedItems.length>0?`Saved playgrounds (${savedItems.length})...`:"Saved playgrounds..."})]}):null]})}),e.jsx(B,{className:"flex h-5 cursor-default items-center justify-center",children:e.jsx(m,{name:"ChevronDown"})})]})})]}),e.jsx(N,{open:c,onOpenChange:Ee=>{d(Ee),Ee||i(null)},isSubmitting:y2,persistFetcher:l,onConfirm:()=>{r&&(d(!1),n.submit({appName:r},{method:"POST",action:"/set-playground"}),i(null))}}),Le?e.jsx(_,{open:s,onOpenChange:Ee=>{w(Ee),Ee||M("")},children:e.jsxs(z,{className:"max-w-xl",children:[e.jsxs(H,{children:[e.jsx($,{children:"Saved playgrounds"}),e.jsx(q,{children:"Pick a saved playground to restore into your workspace."})]}),e.jsxs("div",{className:"space-y-3 text-sm",children:[e.jsx("input",{type:"text",value:j,onChange:Ee=>M(Ee.currentTarget.value),placeholder:"Filter saved playgrounds",className:"border-border bg-background text-foreground w-full rounded-md border px-3 py-2 text-sm"}),e.jsx("div",{className:"border-border bg-muted/20 max-h-72 overflow-y-auto rounded-md border",children:De.length>0?De.map(Ee=>e.jsxs("button",{type:"button",className:"hover:bg-muted/40 flex w-full flex-col gap-1 px-3 py-2 text-left",disabled:y2,onClick:()=>{w(!1),M(""),n.submit({appName:`${Z}${Ee.id}`},{method:"POST",action:"/set-playground"})},children:[e.jsx("span",{className:"text-sm font-medium",children:Ee.displayName}),e.jsx("span",{className:"text-muted-foreground text-xs",children:Ee.savedAt})]},Ee.id)):e.jsx("p",{className:"text-muted-foreground px-3 py-6 text-center text-sm",children:"No saved playgrounds found."})})]}),e.jsxs(W,{children:[e.jsx("button",{type:"button",className:"border-border text-foreground hover:bg-muted focus-visible:ring-ring inline-flex items-center justify-center rounded-md border px-3 py-2 text-sm font-semibold",onClick:()=>w(!1),children:"Close"})]})]})}):null]})} +function Qa({value:o,children:t}){return e.jsxs(A,{value:o,className:"radix-disabled:text-red-500 radix-highlighted:opacity-100 radix-highlighted:outline-none radix-state-checked:opacity-100 relative flex cursor-pointer items-center rounded px-10 py-2 leading-none opacity-80 select-none",children:[e.jsx(F,{children:t}),e.jsx(G,{className:"absolute left-0 inline-flex w-[25px] items-center justify-center",children:e.jsx(m,{name:"CheckSmall"})})]})} +function ue({appName:o,isOutdated:t,hideTextOnNarrow:n,showOnboardingIndicator:l=!1,onClick:a,className:u,...c}){const[d,r]=U(y);if(ENV.EPICSHOP_DEPLOYED)return null;const i=l&&d,s=h(u,i?"relative":null);return e.jsx(M,{appName:o,tooltipText:t?"The app the playground was set to has been updated. Click to update to the latest version.":"Playground is not set to the right app. Click to set Playground.",...c,className:s,onClick:p=>{a?.(p),l&&r()},children:e.jsxs("span",{className:"text-foreground-destructive flex items-center justify-center gap-1 hover:underline",children:[e.jsx(m,{name:"Unlinked",className:"animate-ping"})," ",e.jsx("span",{className:n?"hidden uppercase @min-[600px]:inline":"uppercase",children:t?"Playground Outdated":"Set to Playground"}),i?e.jsx(V,{tooltip:"Set the playground for this step.",size:"sm"}):null]})})} +export{de as P,ue as S,M as a}; //# sourceMappingURL=set-playground-CqWopo_p.js.map diff --git a/node_modules/@epic-web/workshop-app/build/server/index.js b/node_modules/@epic-web/workshop-app/build/server/index.js -index a19b2a3..11ec3a1 100644 +index a19b2a3..dae145b 100644 --- a/node_modules/@epic-web/workshop-app/build/server/index.js +++ b/node_modules/@epic-web/workshop-app/build/server/index.js @@ -1978,6 +1978,45 @@ const meta$6 = ({ @@ -217,7 +217,7 @@ index a19b2a3..11ec3a1 100644 } const apps = await getApps({ forceFresh: true -@@ -7893,16 +7995,41 @@ function PlaygroundChooser({ +@@ -7893,16 +7995,43 @@ function PlaygroundChooser({ const fetcher = useFetcher(); const persistFetcher = useFetcher(); const { @@ -226,6 +226,7 @@ index a19b2a3..11ec3a1 100644 + persistEnabled } = usePlaygroundOnboardingGate(); + const rootData = useRootLoaderData(); ++ const revalidator = useRevalidator(); + const savedPlaygrounds = persistEnabled ? rootData?.savedPlaygrounds ?? [] : []; const [dialogOpen, setDialogOpen] = React.useState(false); const [pendingAppName, setPendingAppName] = React.useState(null); @@ -254,13 +255,14 @@ index a19b2a3..11ec3a1 100644 value: playgroundAppName, onValueChange: (appName) => { + if (appName === savedPlaygroundSelectValue) { ++ revalidator.revalidate(); + setSavedDialogOpen(true); + return; + } if (shouldConfirm) { setPendingAppName(appName); setDialogOpen(true); -@@ -7950,7 +8077,14 @@ function PlaygroundChooser({ +@@ -7950,7 +8079,14 @@ function PlaygroundChooser({ value: app2.name, children: app2.displayName }, app2.name); @@ -276,7 +278,7 @@ index a19b2a3..11ec3a1 100644 }) }), /* @__PURE__ */ jsx(Select.ScrollDownButton, { className: "flex h-5 cursor-default items-center justify-center", -@@ -7981,7 +8115,68 @@ function PlaygroundChooser({ +@@ -7981,7 +8117,68 @@ function PlaygroundChooser({ }); setPendingAppName(null); } From 28888f11fb5ae491f796e7d1bcd4ea8153ccaad3 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sun, 18 Jan 2026 22:35:44 +0000 Subject: [PATCH 3/3] Remove patch-package workaround Co-authored-by: me --- epicshop/package-lock.json | 294 +-------------- epicshop/package.json | 6 +- .../@epic-web+workshop-app+6.58.0.patch | 350 ------------------ 3 files changed, 3 insertions(+), 647 deletions(-) delete mode 100644 epicshop/patches/@epic-web+workshop-app+6.58.0.patch diff --git a/epicshop/package-lock.json b/epicshop/package-lock.json index 47e4a16..25f4f2f 100644 --- a/epicshop/package-lock.json +++ b/epicshop/package-lock.json @@ -4,6 +4,7 @@ "requires": true, "packages": { "": { + "hasInstallScript": true, "dependencies": { "@epic-web/workshop-app": "^6.58.0", "@epic-web/workshop-utils": "^6.58.0", @@ -16,8 +17,7 @@ "fs-extra": "^11.3.3", "get-port": "^7.1.0", "match-sorter": "^8.2.0", - "p-limit": "^7.2.0", - "patch-package": "^8.0.1" + "p-limit": "^7.2.0" } }, "node_modules/@adobe/css-tools": { @@ -4658,12 +4658,6 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "license": "BSD-2-Clause" - }, "node_modules/accepts": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", @@ -5033,24 +5027,6 @@ "node": ">= 0.8" } }, - "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/call-bind-apply-helpers": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", @@ -5272,21 +5248,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/cjs-module-lexer": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", @@ -6274,23 +6235,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/define-lazy-prop": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", @@ -7028,15 +6972,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/find-yarn-workspace-root": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", - "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", - "license": "Apache-2.0", - "dependencies": { - "micromatch": "^4.0.2" - } - }, "node_modules/fkill": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/fkill/-/fkill-10.0.1.tgz", @@ -7399,18 +7334,6 @@ "node": ">=8" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -7999,12 +7922,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "license": "MIT" - }, "node_modules/isbot": { "version": "5.1.32", "resolved": "https://registry.npmjs.org/isbot/-/isbot-5.1.32.tgz", @@ -8075,25 +7992,6 @@ "node": ">=6" } }, - "node_modules/json-stable-stringify": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz", - "integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.4", - "isarray": "^2.0.5", - "jsonify": "^0.0.1", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -8118,15 +8016,6 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jsonify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", - "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", - "license": "Public Domain", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/katex": { "version": "0.16.27", "resolved": "https://registry.npmjs.org/katex/-/katex-0.16.27.tgz", @@ -8166,15 +8055,6 @@ "node": ">=0.10.0" } }, - "node_modules/klaw-sync": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", - "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.1.11" - } - }, "node_modules/langium": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/langium/-/langium-3.3.1.tgz", @@ -9635,15 +9515,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/minipass": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", @@ -10016,15 +9887,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/on-finished": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", @@ -10401,132 +10263,6 @@ "event-target-polyfill": "^0.0.4" } }, - "node_modules/patch-package": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.1.tgz", - "integrity": "sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw==", - "license": "MIT", - "dependencies": { - "@yarnpkg/lockfile": "^1.1.0", - "chalk": "^4.1.2", - "ci-info": "^3.7.0", - "cross-spawn": "^7.0.3", - "find-yarn-workspace-root": "^2.0.0", - "fs-extra": "^10.0.0", - "json-stable-stringify": "^1.0.2", - "klaw-sync": "^6.0.0", - "minimist": "^1.2.6", - "open": "^7.4.2", - "semver": "^7.5.3", - "slash": "^2.0.0", - "tmp": "^0.2.4", - "yaml": "^2.2.2" - }, - "bin": { - "patch-package": "index.js" - }, - "engines": { - "node": ">=14", - "npm": ">5" - } - }, - "node_modules/patch-package/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/patch-package/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/patch-package/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/patch-package/node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/patch-package/node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "license": "MIT", - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/patch-package/node_modules/open": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", - "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", - "license": "MIT", - "dependencies": { - "is-docker": "^2.0.0", - "is-wsl": "^2.1.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/patch-package/node_modules/slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/path-data-parser": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/path-data-parser/-/path-data-parser-0.1.0.tgz", @@ -11835,23 +11571,6 @@ "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", "license": "MIT" }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -12500,15 +12219,6 @@ "integrity": "sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==", "license": "MIT" }, - "node_modules/tmp": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz", - "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==", - "license": "MIT", - "engines": { - "node": ">=14.14" - } - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", diff --git a/epicshop/package.json b/epicshop/package.json index 2bdadb0..a09fb0a 100644 --- a/epicshop/package.json +++ b/epicshop/package.json @@ -1,8 +1,5 @@ { "type": "module", - "scripts": { - "postinstall": "patch-package" - }, "dependencies": { "@epic-web/workshop-app": "^6.58.0", "@epic-web/workshop-utils": "^6.58.0", @@ -15,7 +12,6 @@ "fs-extra": "^11.3.3", "get-port": "^7.1.0", "match-sorter": "^8.2.0", - "p-limit": "^7.2.0", - "patch-package": "^8.0.1" + "p-limit": "^7.2.0" } } diff --git a/epicshop/patches/@epic-web+workshop-app+6.58.0.patch b/epicshop/patches/@epic-web+workshop-app+6.58.0.patch deleted file mode 100644 index 625fe47..0000000 --- a/epicshop/patches/@epic-web+workshop-app+6.58.0.patch +++ /dev/null @@ -1,350 +0,0 @@ -diff --git a/node_modules/@epic-web/workshop-app/build/client/assets/set-playground-CqWopo_p.js b/node_modules/@epic-web/workshop-app/build/client/assets/set-playground-CqWopo_p.js -index a36cb62..a69b3a3 100644 ---- a/node_modules/@epic-web/workshop-app/build/client/assets/set-playground-CqWopo_p.js -+++ b/node_modules/@epic-web/workshop-app/build/client/assets/set-playground-CqWopo_p.js -@@ -1,2 +1,23 @@ --import{j as e}from"./jsx-runtime-C5WNSv3b.js";import{R as S,T as P,V as C,I as D,P as O,C as k,S as T,a as I,G as R,L as E,b as B,c as A,d as F,e as G}from"./index-wbZv2KL3.js";import{a as h,I as m}from"./misc-GmfBFNKU.js";import{r as x}from"./index-Az39ZADK.js";import{c as f}from"./chunk-UIGDSWPH-D7TrB36R.js";import{B as L}from"./button-Bhee0nJ5.js";import{u as U,O as V}from"./onboarding-indicator-BtHxYHrp.js";import{s as Y}from"./progress-bar-CXiAexcc.js";import{D as _,a as z,b as H,c as $,d as q,e as W}from"./dialog-D9Rz0D0m.js";import{S as J}from"./tooltip-DOPvLR3d.js";import{u as b}from"./pe-BgHP_H47.js";import{u as K}from"./root-loader-CcoJXu7H.js";const y="set-playground";function g(){const o=K(),t=o.preferences?.playground?.persist??!1,n=o.preferences?.onboardingComplete?.includes(y)??!1;return{persistEnabled:t,shouldConfirm:!t&&!n}}function N({open:o,onOpenChange:t,onConfirm:n,isSubmitting:l,persistFetcher:a}){const u=b(),{persistEnabled:c}=g(),d=a.state!=="idle",r=a.data?.status==="success"?a.data.persist:c,i=!r;return e.jsx(_,{open:o,onOpenChange:t,children:e.jsxs(z,{className:"max-w-xl",children:[e.jsxs(H,{children:[e.jsx($,{children:"Playground ready for your first step"}),e.jsx(q,{children:"Nice work getting here! Setting the playground is how you bring the next step's instructions into your workspace."})]}),e.jsxs("div",{className:"space-y-4 text-sm",children:[e.jsx("p",{className:"text-muted-foreground",children:"This will replace whatever is currently in your playground with the next step's files. That is expected and the default workflow."}),e.jsxs("div",{className:"border-border bg-muted/40 space-y-3 rounded-md border p-4",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-foreground font-semibold",children:"Optional: Save a copy each time"}),e.jsxs("p",{className:"text-muted-foreground mt-1 text-sm",children:["When enabled, every set saves a copy in",e.jsx("span",{className:"font-mono",children:" saved-playgrounds"}),". You can change this later in Preferences."]}),e.jsx("p",{className:"text-muted-foreground mt-2 text-xs",children:"You can always manage this in Preferences."})]}),e.jsxs(a.Form,{method:"POST",action:"/persist-playground",children:[u,e.jsx("input",{type:"hidden",name:"persist",value:i?"true":"false"}),e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-foreground text-sm font-medium",children:"Persistence"}),e.jsx("p",{className:"text-muted-foreground text-xs",children:r?"Enabled":"Disabled"})]}),e.jsx("button",{type:"submit",role:"switch","aria-checked":r,"aria-label":`Toggle playground persistence ${r?"off":"on"}`,className:h("focus-visible:ring-ring relative inline-flex h-6 w-11 items-center rounded-full border transition",r?"border-foreground bg-foreground":"border-border bg-muted",d?"cursor-progress opacity-70":null),disabled:d,children:e.jsx("span",{className:h("bg-background inline-block h-5 w-5 rounded-full shadow transition",r?"translate-x-5":"translate-x-0")})})]})]})]})]}),e.jsxs(W,{children:[e.jsx("button",{type:"button",className:"border-border text-foreground hover:bg-muted focus-visible:ring-ring inline-flex items-center justify-center rounded-md border px-3 py-2 text-sm font-semibold",onClick:()=>t(!1),children:"Cancel"}),e.jsx(L,{varient:"primary",type:"button",onClick:n,disabled:l,children:l?"Setting...":"Set playground"})]})]})})}function M({appName:o,reset:t=!1,tooltipText:n,...l}){const a=f(),u=f(),c=b(),{shouldConfirm:d}=g(),[r,i]=x.useState(!1),s=x.useRef(null),p=x.useRef(!1),v=a.state!=="idle",j=e.jsx("button",{type:"submit",...l,className:h(l.className,a.state!=="idle"?"cursor-progress":null,a.data?.status==="error"?"cursor-not-allowed":null)});return e.jsxs(e.Fragment,{children:[e.jsxs(a.Form,{action:"/set-playground",method:"POST",className:"inline-flex items-center justify-center",ref:s,onSubmit:w=>{if(d&&!p.current){w.preventDefault(),i(!0);return}p.current=!1},children:[c,e.jsx("input",{type:"hidden",name:"appName",value:o}),t?e.jsx("input",{type:"hidden",name:"reset",value:"true"}):null,Y,n?e.jsx(J,{content:n,children:j}):j]}),e.jsx(N,{open:r,onOpenChange:i,isSubmitting:v,persistFetcher:u,onConfirm:()=>{p.current=!0,i(!1),s.current?.requestSubmit()}})]})}function de({playgroundAppName:o,allApps:t}){const n=f(),l=f(),{shouldConfirm:a}=g(),[u,c]=x.useState(!1),[d,r]=x.useState(null),i=n.state!=="idle";return e.jsxs(e.Fragment,{children:[e.jsxs(S,{name:"appName",value:o,onValueChange:s=>{if(a){r(s),c(!0);return}n.submit({appName:s},{method:"POST",action:"/set-playground"})},children:[e.jsxs(P,{"aria-label":"Select app for playground",className:h("radix-placeholder:text-gray-500 flex h-full w-full items-center justify-between text-left focus-visible:outline-none",n.state!=="idle"?"cursor-progress":null,n.data?.status==="error"?"cursor-not-allowed":null),children:[e.jsx("span",{className:"scrollbar-thin scrollbar-thumb-scrollbar w-80 flex-1 overflow-hidden text-ellipsis whitespace-nowrap",children:e.jsx(C,{placeholder:"Select current app",className:"inline-block w-40 text-ellipsis"})}),e.jsx(D,{children:e.jsx(m,{name:"TriangleDownSmall"})})]}),e.jsx(O,{children:e.jsxs(k,{position:"popper",align:"start",className:"z-20 max-h-[50vh] bg-black text-white lg:max-h-[70vh]",children:[e.jsx(T,{className:"flex h-5 cursor-default items-center justify-center",children:e.jsx(m,{name:"ChevronUp"})}),e.jsx(I,{className:"p-3",children:e.jsxs(R,{children:[e.jsx(E,{className:"px-5 pb-3 font-mono uppercase",children:"App"}),t.filter(s=>s.name!=="playground").map(s=>e.jsx(Q,{value:s.name,children:s.displayName},s.name))]})}),e.jsx(B,{className:"flex h-5 cursor-default items-center justify-center",children:e.jsx(m,{name:"ChevronDown"})})]})})]}),e.jsx(N,{open:u,onOpenChange:s=>{c(s),s||r(null)},isSubmitting:i,persistFetcher:l,onConfirm:()=>{d&&(c(!1),n.submit({appName:d},{method:"POST",action:"/set-playground"}),r(null))}})]})}function Q({value:o,children:t}){return e.jsxs(A,{value:o,className:"radix-disabled:text-red-500 radix-highlighted:opacity-100 radix-highlighted:outline-none radix-state-checked:opacity-100 relative flex cursor-pointer items-center rounded px-10 py-2 leading-none opacity-80 select-none",children:[e.jsx(F,{children:t}),e.jsx(G,{className:"absolute left-0 inline-flex w-[25px] items-center justify-center",children:e.jsx(m,{name:"CheckSmall"})})]})}function ue({appName:o,isOutdated:t,hideTextOnNarrow:n,showOnboardingIndicator:l=!1,onClick:a,className:u,...c}){const[d,r]=U(y);if(ENV.EPICSHOP_DEPLOYED)return null;const i=l&&d,s=h(u,i?"relative":null);return e.jsx(M,{appName:o,tooltipText:t?"The app the playground was set to has been updated. Click to update to the latest version.":"Playground is not set to the right app. Click to set Playground.",...c,className:s,onClick:p=>{a?.(p),l&&r()},children:e.jsxs("span",{className:"text-foreground-destructive flex items-center justify-center gap-1 hover:underline",children:[e.jsx(m,{name:"Unlinked",className:"animate-ping"})," ",e.jsx("span",{className:n?"hidden uppercase @min-[600px]:inline":"uppercase",children:t?"Playground Outdated":"Set to Playground"}),i?e.jsx(V,{tooltip:"Set the playground for this step.",size:"sm"}):null]})})}export{de as P,ue as S,M as a}; -+import{j as e}from"./jsx-runtime-C5WNSv3b.js"; -+import{R as S,T as P,V as C,I as D,P as O,C as k,S as T,a as I,G as R,L as E,b as B,c as A,d as F,e as G}from"./index-wbZv2KL3.js"; -+import{a as h,I as m}from"./misc-GmfBFNKU.js"; -+import{r as x}from"./index-Az39ZADK.js"; -+import{c as f,j as rr}from"./chunk-UIGDSWPH-D7TrB36R.js"; -+import{B as L}from"./button-Bhee0nJ5.js"; -+import{u as U,O as V}from"./onboarding-indicator-BtHxYHrp.js"; -+import{s as Y}from"./progress-bar-CXiAexcc.js"; -+import{D as _,a as z,b as H,c as $,d as q,e as W}from"./dialog-D9Rz0D0m.js"; -+import{S as J}from"./tooltip-DOPvLR3d.js"; -+import{u as b}from"./pe-BgHP_H47.js"; -+import{u as K}from"./root-loader-CcoJXu7H.js"; -+const y="set-playground"; -+const Z="saved-playground:"; -+const Q="__saved_playgrounds__"; -+function g(){const o=K(),t=o.preferences?.playground?.persist??!1,n=o.preferences?.onboardingComplete?.includes(y)??!1;return{persistEnabled:t,shouldConfirm:!t&&!n}} -+function N({open:o,onOpenChange:t,onConfirm:n,isSubmitting:l,persistFetcher:a}){const u=b(),{persistEnabled:c}=g(),d=a.state!=="idle",r=a.data?.status==="success"?a.data.persist:c,i=!r;return e.jsx(_,{open:o,onOpenChange:t,children:e.jsxs(z,{className:"max-w-xl",children:[e.jsxs(H,{children:[e.jsx($,{children:"Playground ready for your first step"}),e.jsx(q,{children:"Nice work getting here! Setting the playground is how you bring the next step's instructions into your workspace."})]}),e.jsxs("div",{className:"space-y-4 text-sm",children:[e.jsx("p",{className:"text-muted-foreground",children:"This will replace whatever is currently in your playground with the next step's files. That is expected and the default workflow."}),e.jsxs("div",{className:"border-border bg-muted/40 space-y-3 rounded-md border p-4",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-foreground font-semibold",children:"Optional: Save a copy each time"}),e.jsxs("p",{className:"text-muted-foreground mt-1 text-sm",children:["When enabled, every set saves a copy in",e.jsx("span",{className:"font-mono",children:" saved-playgrounds"}),". You can change this later in Preferences."]}),e.jsx("p",{className:"text-muted-foreground mt-2 text-xs",children:"You can always manage this in Preferences."})]}),e.jsxs(a.Form,{method:"POST",action:"/persist-playground",children:[u,e.jsx("input",{type:"hidden",name:"persist",value:i?"true":"false"}),e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-foreground text-sm font-medium",children:"Persistence"}),e.jsx("p",{className:"text-muted-foreground text-xs",children:r?"Enabled":"Disabled"})]}),e.jsx("button",{type:"submit",role:"switch","aria-checked":r,"aria-label":`Toggle playground persistence ${r?"off":"on"}`,className:h("focus-visible:ring-ring relative inline-flex h-6 w-11 items-center rounded-full border transition",r?"border-foreground bg-foreground":"border-border bg-muted",d?"cursor-progress opacity-70":null),disabled:d,children:e.jsx("span",{className:h("bg-background inline-block h-5 w-5 rounded-full shadow transition",r?"translate-x-5":"translate-x-0")})})]})]})]})]}),e.jsxs(W,{children:[e.jsx("button",{type:"button",className:"border-border text-foreground hover:bg-muted focus-visible:ring-ring inline-flex items-center justify-center rounded-md border px-3 py-2 text-sm font-semibold",onClick:()=>t(!1),children:"Cancel"}),e.jsx(L,{varient:"primary",type:"button",onClick:n,disabled:l,children:l?"Setting...":"Set playground"})]})]})})} -+function M({appName:o,reset:t=!1,tooltipText:n,...l}){const a=f(),u=f(),c=b(),{shouldConfirm:d}=g(),[r,i]=x.useState(!1),s=x.useRef(null),p=x.useRef(!1),v=a.state!=="idle",j=e.jsx("button",{type:"submit",...l,className:h(l.className,a.state!=="idle"?"cursor-progress":null,a.data?.status==="error"?"cursor-not-allowed":null)});return e.jsxs(e.Fragment,{children:[e.jsxs(a.Form,{action:"/set-playground",method:"POST",className:"inline-flex items-center justify-center",ref:s,onSubmit:w=>{if(d&&!p.current){w.preventDefault(),i(!0);return}p.current=!1},children:[c,e.jsx("input",{type:"hidden",name:"appName",value:o}),t?e.jsx("input",{type:"hidden",name:"reset",value:"true"}):null,Y,n?e.jsx(J,{content:n,children:j}):j]}),e.jsx(N,{open:r,onOpenChange:i,isSubmitting:v,persistFetcher:u,onConfirm:()=>{p.current=!0,i(!1),s.current?.requestSubmit()}})]})} -+function de({playgroundAppName:o,allApps:t}){const n=f(),l=f(),{shouldConfirm:a,persistEnabled:u}=g(),p=K(),revalidator=rr(),v=u?p?.savedPlaygrounds??[]:[],[c,d]=x.useState(!1),[r,i]=x.useState(null),[s,w]=x.useState(!1),[j,M]=x.useState(""),y2=n.state!=="idle",savedItems=x.useMemo(()=>v.map(Ee=>{const Re=t.find(Te=>Te.name===Ee.appName);return{...Ee,displayName:Re?Re.displayName:Ee.appName}}),[v,t]),Ue=j.trim().toLowerCase(),De=Ue?savedItems.filter(Ee=>`${Ee.displayName} ${Ee.appName} ${Ee.savedAt}`.toLowerCase().includes(Ue)):savedItems,Le=u;return e.jsxs(e.Fragment,{children:[e.jsxs(S,{name:"appName",value:o,onValueChange:Ee=>{if(Ee===Q){revalidator.revalidate(),w(!0);return}if(a){i(Ee),d(!0);return}n.submit({appName:Ee},{method:"POST",action:"/set-playground"})},children:[e.jsxs(P,{"aria-label":"Select app for playground",className:h("radix-placeholder:text-gray-500 flex h-full w-full items-center justify-between text-left focus-visible:outline-none",n.state!=="idle"?"cursor-progress":null,n.data?.status==="error"?"cursor-not-allowed":null),children:[e.jsx("span",{className:"scrollbar-thin scrollbar-thumb-scrollbar w-80 flex-1 overflow-hidden text-ellipsis whitespace-nowrap",children:e.jsx(C,{placeholder:"Select current app",className:"inline-block w-40 text-ellipsis"})}),e.jsx(D,{children:e.jsx(m,{name:"TriangleDownSmall"})})]}),e.jsx(O,{children:e.jsxs(k,{position:"popper",align:"start",className:"z-20 max-h-[50vh] bg-black text-white lg:max-h-[70vh]",children:[e.jsx(T,{className:"flex h-5 cursor-default items-center justify-center",children:e.jsx(m,{name:"ChevronUp"})}),e.jsx(I,{className:"p-3",children:e.jsxs(R,{children:[e.jsx(E,{className:"px-5 pb-3 font-mono uppercase",children:"App"}),t.filter(Ee=>Ee.name!=="playground").map(Ee=>e.jsx(Qa,{value:Ee.name,children:Ee.displayName},Ee.name)),Le?e.jsxs(e.Fragment,{children:[e.jsx("div",{className:"my-2 h-px bg-white/10"}),e.jsx(Qa,{value:Q,children:savedItems.length>0?`Saved playgrounds (${savedItems.length})...`:"Saved playgrounds..."})]}):null]})}),e.jsx(B,{className:"flex h-5 cursor-default items-center justify-center",children:e.jsx(m,{name:"ChevronDown"})})]})})]}),e.jsx(N,{open:c,onOpenChange:Ee=>{d(Ee),Ee||i(null)},isSubmitting:y2,persistFetcher:l,onConfirm:()=>{r&&(d(!1),n.submit({appName:r},{method:"POST",action:"/set-playground"}),i(null))}}),Le?e.jsx(_,{open:s,onOpenChange:Ee=>{w(Ee),Ee||M("")},children:e.jsxs(z,{className:"max-w-xl",children:[e.jsxs(H,{children:[e.jsx($,{children:"Saved playgrounds"}),e.jsx(q,{children:"Pick a saved playground to restore into your workspace."})]}),e.jsxs("div",{className:"space-y-3 text-sm",children:[e.jsx("input",{type:"text",value:j,onChange:Ee=>M(Ee.currentTarget.value),placeholder:"Filter saved playgrounds",className:"border-border bg-background text-foreground w-full rounded-md border px-3 py-2 text-sm"}),e.jsx("div",{className:"border-border bg-muted/20 max-h-72 overflow-y-auto rounded-md border",children:De.length>0?De.map(Ee=>e.jsxs("button",{type:"button",className:"hover:bg-muted/40 flex w-full flex-col gap-1 px-3 py-2 text-left",disabled:y2,onClick:()=>{w(!1),M(""),n.submit({appName:`${Z}${Ee.id}`},{method:"POST",action:"/set-playground"})},children:[e.jsx("span",{className:"text-sm font-medium",children:Ee.displayName}),e.jsx("span",{className:"text-muted-foreground text-xs",children:Ee.savedAt})]},Ee.id)):e.jsx("p",{className:"text-muted-foreground px-3 py-6 text-center text-sm",children:"No saved playgrounds found."})})]}),e.jsxs(W,{children:[e.jsx("button",{type:"button",className:"border-border text-foreground hover:bg-muted focus-visible:ring-ring inline-flex items-center justify-center rounded-md border px-3 py-2 text-sm font-semibold",onClick:()=>w(!1),children:"Close"})]})]})}):null]})} -+function Qa({value:o,children:t}){return e.jsxs(A,{value:o,className:"radix-disabled:text-red-500 radix-highlighted:opacity-100 radix-highlighted:outline-none radix-state-checked:opacity-100 relative flex cursor-pointer items-center rounded px-10 py-2 leading-none opacity-80 select-none",children:[e.jsx(F,{children:t}),e.jsx(G,{className:"absolute left-0 inline-flex w-[25px] items-center justify-center",children:e.jsx(m,{name:"CheckSmall"})})]})} -+function ue({appName:o,isOutdated:t,hideTextOnNarrow:n,showOnboardingIndicator:l=!1,onClick:a,className:u,...c}){const[d,r]=U(y);if(ENV.EPICSHOP_DEPLOYED)return null;const i=l&&d,s=h(u,i?"relative":null);return e.jsx(M,{appName:o,tooltipText:t?"The app the playground was set to has been updated. Click to update to the latest version.":"Playground is not set to the right app. Click to set Playground.",...c,className:s,onClick:p=>{a?.(p),l&&r()},children:e.jsxs("span",{className:"text-foreground-destructive flex items-center justify-center gap-1 hover:underline",children:[e.jsx(m,{name:"Unlinked",className:"animate-ping"})," ",e.jsx("span",{className:n?"hidden uppercase @min-[600px]:inline":"uppercase",children:t?"Playground Outdated":"Set to Playground"}),i?e.jsx(V,{tooltip:"Set the playground for this step.",size:"sm"}):null]})})} -+export{de as P,ue as S,M as a}; - //# sourceMappingURL=set-playground-CqWopo_p.js.map -diff --git a/node_modules/@epic-web/workshop-app/build/server/index.js b/node_modules/@epic-web/workshop-app/build/server/index.js -index a19b2a3..dae145b 100644 ---- a/node_modules/@epic-web/workshop-app/build/server/index.js -+++ b/node_modules/@epic-web/workshop-app/build/server/index.js -@@ -1978,6 +1978,45 @@ const meta$6 = ({ - requestInfo: loaderData.requestInfo - }); - }; -+const SAVED_PLAYGROUND_PREFIX = "saved-playground:"; -+const SAVED_PLAYGROUNDS_DIR_NAME = "saved-playgrounds"; -+function getPlaygroundAppNameInfoPath() { -+ return path.join(getWorkshopRoot(), "node_modules", ".cache", "epicshop", "playground.json"); -+} -+function parseSavedPlaygroundDirName(dirName) { -+ const [datePart, timePart, ...appNameParts] = dirName.split("_"); -+ if (!datePart || !timePart || appNameParts.length === 0) return null; -+ const appName = appNameParts.join("_"); -+ const timestamp = `${datePart}_${timePart}`; -+ const savedAt = `${datePart} ${timePart.replace(/\./g, ":")}`; -+ return { -+ id: dirName, -+ appName, -+ savedAt, -+ timestamp -+ }; -+} -+async function getSavedPlaygrounds() { -+ const savedDir = path.join(getWorkshopRoot(), SAVED_PLAYGROUNDS_DIR_NAME); -+ if (!await fsExtra.pathExists(savedDir)) return []; -+ const entries = await fs.promises.readdir(savedDir, { withFileTypes: true }); -+ const parsed = entries.filter((entry) => entry.isDirectory()).map((entry) => parseSavedPlaygroundDirName(entry.name)).filter(Boolean); -+ parsed.sort((a, b) => b.timestamp.localeCompare(a.timestamp)); -+ return parsed; -+} -+async function getSavedPlaygroundById(savedId) { -+ const parsed = parseSavedPlaygroundDirName(savedId); -+ if (!parsed) return null; -+ const fullPath = path.join(getWorkshopRoot(), SAVED_PLAYGROUNDS_DIR_NAME, savedId); -+ if (!await fsExtra.pathExists(fullPath)) return null; -+ return { ...parsed, fullPath }; -+} -+async function writePlaygroundAppName(appName) { -+ if (!appName) return; -+ const infoPath = getPlaygroundAppNameInfoPath(); -+ await fsExtra.ensureDir(path.dirname(infoPath)); -+ await fsExtra.writeJSON(infoPath, { appName }); -+} - async function loader$H({ - request - }) { -@@ -2027,6 +2066,10 @@ async function loader$H({ - exerciseChanges: checkForExerciseChanges(), - loggedInProductHosts: getLoggedInProductHosts() - }); -+ const savedPlaygrounds = asyncStuff.preferences?.playground?.persist ? await getSavedPlaygrounds().catch((error) => { -+ console.error("Failed to read saved playgrounds", error); -+ return []; -+ }) : []; - const presentUsers = await getPresentUsers({ - request, - timings -@@ -2054,6 +2097,7 @@ async function loader$H({ - fullPath, - relativePath - })), -+ savedPlaygrounds, - ENV: getEnv(), - requestInfo: { - protocol: new URL(request.url).protocol, -@@ -7677,34 +7721,92 @@ async function action$c({ - }); - } - const form = result.data; -- const app2 = await getAppByName(form.appName); -- if (!app2) { -- return dataWithPE(request, formData, { -- status: "error", -- error: `App ${form.appName} not found` -- }, { -- status: 404 -- }); -- } -- const converseApp = isProblemApp(app2) && app2.solutionName ? await getAppByName(app2.solutionName) : isSolutionApp(app2) && app2.problemName ? await getAppByName(app2.problemName) : void 0; -- try { -- await setPlayground(app2.fullPath, { -- reset: form.reset -- }); -- } catch (error) { -- const message = getErrorMessage(error); -- console.error("Error setting playground", message); -- return dataWithPE(request, formData, { -- status: "error", -- error: message -- }, { -- status: 500, -- headers: await createToastHeaders({ -- type: "error", -- title: "Error", -- description: "There was an error setting the playground. Check the terminal for details." -- }) -- }); -+ let converseApp; -+ if (form.appName.startsWith(SAVED_PLAYGROUND_PREFIX)) { -+ const savedId = form.appName.slice(SAVED_PLAYGROUND_PREFIX.length); -+ if (!savedId) { -+ return dataWithPE(request, formData, { -+ status: "error", -+ error: "Saved playground is missing an id" -+ }, { -+ status: 400 -+ }); -+ } -+ const preferences = await getPreferences(); -+ if (!preferences?.playground?.persist) { -+ return dataWithPE(request, formData, { -+ status: "error", -+ error: "Playground persistence is disabled" -+ }, { -+ status: 403, -+ headers: await createToastHeaders({ -+ type: "error", -+ title: "Persistence disabled", -+ description: "Enable playground persistence in Preferences to use saved playgrounds." -+ }) -+ }); -+ } -+ const savedPlayground = await getSavedPlaygroundById(savedId); -+ if (!savedPlayground) { -+ return dataWithPE(request, formData, { -+ status: "error", -+ error: `Saved playground ${savedId} not found` -+ }, { -+ status: 404 -+ }); -+ } -+ const baseApp = savedPlayground.appName ? await getAppByName(savedPlayground.appName) : null; -+ converseApp = baseApp && isProblemApp(baseApp) && baseApp.solutionName ? await getAppByName(baseApp.solutionName) : baseApp && isSolutionApp(baseApp) && baseApp.problemName ? await getAppByName(baseApp.problemName) : void 0; -+ try { -+ await setPlayground(savedPlayground.fullPath, { -+ reset: form.reset -+ }); -+ await writePlaygroundAppName(savedPlayground.appName); -+ } catch (error) { -+ const message = getErrorMessage(error); -+ console.error("Error setting playground", message); -+ return dataWithPE(request, formData, { -+ status: "error", -+ error: message -+ }, { -+ status: 500, -+ headers: await createToastHeaders({ -+ type: "error", -+ title: "Error", -+ description: "There was an error setting the playground. Check the terminal for details." -+ }) -+ }); -+ } -+ } else { -+ const app2 = await getAppByName(form.appName); -+ if (!app2) { -+ return dataWithPE(request, formData, { -+ status: "error", -+ error: `App ${form.appName} not found` -+ }, { -+ status: 404 -+ }); -+ } -+ converseApp = isProblemApp(app2) && app2.solutionName ? await getAppByName(app2.solutionName) : isSolutionApp(app2) && app2.problemName ? await getAppByName(app2.problemName) : void 0; -+ try { -+ await setPlayground(app2.fullPath, { -+ reset: form.reset -+ }); -+ } catch (error) { -+ const message = getErrorMessage(error); -+ console.error("Error setting playground", message); -+ return dataWithPE(request, formData, { -+ status: "error", -+ error: message -+ }, { -+ status: 500, -+ headers: await createToastHeaders({ -+ type: "error", -+ title: "Error", -+ description: "There was an error setting the playground. Check the terminal for details." -+ }) -+ }); -+ } - } - const apps = await getApps({ - forceFresh: true -@@ -7893,16 +7995,43 @@ function PlaygroundChooser({ - const fetcher = useFetcher(); - const persistFetcher = useFetcher(); - const { -- shouldConfirm -+ shouldConfirm, -+ persistEnabled - } = usePlaygroundOnboardingGate(); -+ const rootData = useRootLoaderData(); -+ const revalidator = useRevalidator(); -+ const savedPlaygrounds = persistEnabled ? rootData?.savedPlaygrounds ?? [] : []; - const [dialogOpen, setDialogOpen] = React.useState(false); - const [pendingAppName, setPendingAppName] = React.useState(null); -+ const [savedDialogOpen, setSavedDialogOpen] = React.useState(false); -+ const [savedFilter, setSavedFilter] = React.useState(""); - const isSubmitting = fetcher.state !== "idle"; -+ const savedPlaygroundItems = React.useMemo(() => { -+ return savedPlaygrounds.map((saved) => { -+ const baseApp = allApps.find((app2) => app2.name === saved.appName); -+ return { -+ ...saved, -+ displayName: baseApp ? baseApp.displayName : saved.appName -+ }; -+ }); -+ }, [savedPlaygrounds, allApps]); -+ const normalizedFilter = savedFilter.trim().toLowerCase(); -+ const filteredSavedPlaygrounds = normalizedFilter ? savedPlaygroundItems.filter((saved) => { -+ const haystack = `${saved.displayName} ${saved.appName} ${saved.savedAt}`.toLowerCase(); -+ return haystack.includes(normalizedFilter); -+ }) : savedPlaygroundItems; -+ const showSavedPlaygrounds = persistEnabled; -+ const savedPlaygroundSelectValue = "__saved_playgrounds__"; - return /* @__PURE__ */ jsxs(Fragment, { - children: [/* @__PURE__ */ jsxs(Select.Root, { - name: "appName", - value: playgroundAppName, - onValueChange: (appName) => { -+ if (appName === savedPlaygroundSelectValue) { -+ revalidator.revalidate(); -+ setSavedDialogOpen(true); -+ return; -+ } - if (shouldConfirm) { - setPendingAppName(appName); - setDialogOpen(true); -@@ -7950,7 +8079,14 @@ function PlaygroundChooser({ - value: app2.name, - children: app2.displayName - }, app2.name); -- })] -+ }), showSavedPlaygrounds ? /* @__PURE__ */ jsxs(Fragment, { -+ children: [/* @__PURE__ */ jsx("div", { -+ className: "my-2 h-px bg-white/10" -+ }), /* @__PURE__ */ jsx(SelectItem$1, { -+ value: savedPlaygroundSelectValue, -+ children: savedPlaygroundItems.length > 0 ? `Saved playgrounds (${savedPlaygroundItems.length})...` : "Saved playgrounds..." -+ })] -+ }) : null] - }) - }), /* @__PURE__ */ jsx(Select.ScrollDownButton, { - className: "flex h-5 cursor-default items-center justify-center", -@@ -7981,7 +8117,68 @@ function PlaygroundChooser({ - }); - setPendingAppName(null); - } -- })] -+ }), showSavedPlaygrounds ? /* @__PURE__ */ jsx(Dialog, { -+ open: savedDialogOpen, -+ onOpenChange: (open) => { -+ setSavedDialogOpen(open); -+ if (!open) { -+ setSavedFilter(""); -+ } -+ }, -+ children: /* @__PURE__ */ jsxs(DialogContent, { -+ className: "max-w-xl", -+ children: [/* @__PURE__ */ jsxs(DialogHeader, { -+ children: [/* @__PURE__ */ jsx(DialogTitle, { -+ children: "Saved playgrounds" -+ }), /* @__PURE__ */ jsx(DialogDescription, { -+ children: "Pick a saved playground to restore into your workspace." -+ })] -+ }), /* @__PURE__ */ jsxs("div", { -+ className: "space-y-3 text-sm", -+ children: [/* @__PURE__ */ jsx("input", { -+ type: "text", -+ value: savedFilter, -+ onChange: (event) => setSavedFilter(event.currentTarget.value), -+ placeholder: "Filter saved playgrounds", -+ className: "border-border bg-background text-foreground w-full rounded-md border px-3 py-2 text-sm" -+ }), /* @__PURE__ */ jsx("div", { -+ className: "border-border bg-muted/20 max-h-72 overflow-y-auto rounded-md border", -+ children: filteredSavedPlaygrounds.length > 0 ? filteredSavedPlaygrounds.map((saved) => /* @__PURE__ */ jsxs("button", { -+ type: "button", -+ className: "hover:bg-muted/40 flex w-full flex-col gap-1 px-3 py-2 text-left", -+ disabled: isSubmitting, -+ onClick: () => { -+ setSavedDialogOpen(false); -+ setSavedFilter(""); -+ void fetcher.submit({ -+ appName: `${SAVED_PLAYGROUND_PREFIX}${saved.id}` -+ }, { -+ method: "POST", -+ action: "/set-playground" -+ }); -+ }, -+ children: [/* @__PURE__ */ jsx("span", { -+ className: "text-sm font-medium", -+ children: saved.displayName -+ }), /* @__PURE__ */ jsx("span", { -+ className: "text-muted-foreground text-xs", -+ children: saved.savedAt -+ })] -+ }, saved.id)) : /* @__PURE__ */ jsx("p", { -+ className: "text-muted-foreground px-3 py-6 text-center text-sm", -+ children: "No saved playgrounds found." -+ }) -+ })] -+ }), /* @__PURE__ */ jsxs(DialogFooter, { -+ children: [/* @__PURE__ */ jsx("button", { -+ type: "button", -+ className: "border-border text-foreground hover:bg-muted focus-visible:ring-ring inline-flex items-center justify-center rounded-md border px-3 py-2 text-sm font-semibold", -+ onClick: () => setSavedDialogOpen(false), -+ children: "Close" -+ })] -+ })] -+ }) -+ }) : null] - }); - } - function SelectItem$1({