fix(setup): improve layout centering and add terminal-style complete page
- Fix CheckingPage centering by using justify-start with pt-[30%] padding - Replace h-full with flex-1 for proper flex container sizing - Redesign CompletePage with compact terminal-style command display - Add framework logos (JavaScript, TypeScript, React, Vue, Svelte, etc.) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
48
v3/internal/setupwizard/frontend/dist/assets/index-aGFUz6Rg.js
vendored
Normal file
1
v3/internal/setupwizard/frontend/dist/assets/index-sn0oTu7c.css
vendored
Normal file
|
|
@ -7,8 +7,8 @@
|
|||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
||||
<script type="module" crossorigin src="/assets/index-CdeMD05J.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-owjaKB1W.css">
|
||||
<script type="module" crossorigin src="/assets/index-aGFUz6Rg.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-sn0oTu7c.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
|
|
|
|||
1
v3/internal/setupwizard/frontend/dist/logos/javascript.svg
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill="#F7DF1E" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>JavaScript</title><path d="M0 0h24v24H0V0zm22.034 18.276c-.175-1.095-.888-2.015-3.003-2.873-.736-.345-1.554-.585-1.797-1.14-.091-.33-.105-.51-.046-.705.15-.646.915-.84 1.515-.66.39.12.75.42.976.9 1.034-.676 1.034-.676 1.755-1.125-.27-.42-.404-.601-.586-.78-.63-.705-1.469-1.065-2.834-1.034l-.705.089c-.676.165-1.32.525-1.71 1.005-1.14 1.291-.811 3.541.569 4.471 1.365 1.02 3.361 1.244 3.616 2.205.24 1.17-.87 1.545-1.966 1.41-.811-.18-1.26-.586-1.755-1.336l-1.83 1.051c.21.48.45.689.81 1.109 1.74 1.756 6.09 1.666 6.871-1.004.029-.09.24-.705.074-1.65l.046.067zm-8.983-7.245h-2.248c0 1.938-.009 3.864-.009 5.805 0 1.232.063 2.363-.138 2.711-.33.689-1.18.601-1.566.48-.396-.196-.597-.466-.83-.855-.063-.105-.11-.196-.127-.196l-1.825 1.125c.305.63.75 1.172 1.324 1.517.855.51 2.004.675 3.207.405.783-.226 1.458-.691 1.811-1.411.51-.93.402-2.07.397-3.346.012-2.054 0-4.109 0-6.179l.004-.056z"/></svg>
|
||||
|
After Width: | Height: | Size: 989 B |
1
v3/internal/setupwizard/frontend/dist/logos/lit.svg
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill="#324FFF" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Lit</title><path d="M2.4 9.6l4.8 4.8V24l-4.8-4.8V9.6zm4.8-4.8v9.6L12 9.6V0L7.2 4.8zM12 9.6v9.6l4.8-4.8V4.8L12 9.6zm4.8 4.8V24l4.8-4.8V9.6l-4.8 4.8z"/></svg>
|
||||
|
After Width: | Height: | Size: 249 B |
1
v3/internal/setupwizard/frontend/dist/logos/preact.svg
vendored
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
1
v3/internal/setupwizard/frontend/dist/logos/qwik.svg
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill="#AC7EF4" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Qwik</title><path d="M7.5469 0a2.957 2.957 0 0 0-2.5606 1.4785L.5332 9.1915a2.957 2.957 0 0 0 0 2.957l4.4531 7.7128A2.955 2.955 0 0 0 7.547 21.338H12l8.5938 2.6484c.2409.0742.4512-.1782.3359-.4023l-1.916-3.7227 4.4531-7.7129a2.957 2.957 0 0 0 0-2.957l-4.4531-7.7129A2.957 2.957 0 0 0 16.453 0zm0 .7656L17.7324 10.67l-1.8965 1.8985.5782 7.5332L6.2676 10.67l2.371-2.373z"/></svg>
|
||||
|
After Width: | Height: | Size: 470 B |
1
v3/internal/setupwizard/frontend/dist/logos/react.svg
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill="#61DAFB" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>React</title><path d="M14.23 12.004a2.236 2.236 0 0 1-2.235 2.236 2.236 2.236 0 0 1-2.236-2.236 2.236 2.236 0 0 1 2.235-2.236 2.236 2.236 0 0 1 2.236 2.236zm2.648-10.69c-1.346 0-3.107.96-4.888 2.622-1.78-1.653-3.542-2.602-4.887-2.602-.41 0-.783.093-1.106.278-1.375.793-1.683 3.264-.973 6.365C1.98 8.917 0 10.42 0 12.004c0 1.59 1.99 3.097 5.043 4.03-.704 3.113-.39 5.588.988 6.38.32.187.69.275 1.102.275 1.345 0 3.107-.96 4.888-2.624 1.78 1.654 3.542 2.603 4.887 2.603.41 0 .783-.09 1.106-.275 1.374-.792 1.683-3.263.973-6.365C22.02 15.096 24 13.59 24 12.004c0-1.59-1.99-3.097-5.043-4.032.704-3.11.39-5.587-.988-6.38-.318-.184-.688-.277-1.092-.278zm-.005 1.09v.006c.225 0 .406.044.558.127.666.382.955 1.835.73 3.704-.054.46-.142.945-.25 1.44-.96-.236-2.006-.417-3.107-.534-.66-.905-1.345-1.727-2.035-2.447 1.592-1.48 3.087-2.292 4.105-2.295zm-9.77.02c1.012 0 2.514.808 4.11 2.28-.686.72-1.37 1.537-2.02 2.442-1.107.117-2.154.298-3.113.538-.112-.49-.195-.964-.254-1.42-.23-1.868.054-3.32.714-3.707.19-.09.4-.127.563-.132zm4.882 3.05c.455.468.91.992 1.36 1.564-.44-.02-.89-.034-1.345-.034-.46 0-.915.01-1.36.034.44-.572.895-1.096 1.345-1.565zM12 8.1c.74 0 1.477.034 2.202.093.406.582.802 1.203 1.183 1.86.372.64.71 1.29 1.018 1.946-.308.655-.646 1.31-1.013 1.95-.38.66-.773 1.288-1.18 1.87-.728.063-1.466.098-2.21.098-.74 0-1.477-.035-2.202-.093-.406-.582-.802-1.204-1.183-1.86-.372-.64-.71-1.29-1.018-1.946.303-.657.646-1.313 1.013-1.954.38-.66.773-1.286 1.18-1.868.728-.064 1.466-.098 2.21-.098zm-3.635.254c-.24.377-.48.763-.704 1.16-.225.39-.435.782-.635 1.174-.265-.656-.49-1.31-.676-1.947.64-.15 1.315-.283 2.015-.386zm7.26 0c.695.103 1.365.23 2.006.387-.18.632-.405 1.282-.66 1.933-.2-.39-.41-.783-.64-1.174-.225-.392-.465-.774-.705-1.146zm3.063.675c.484.15.944.317 1.375.498 1.732.74 2.852 1.708 2.852 2.476-.005.768-1.125 1.74-2.857 2.475-.42.18-.88.342-1.355.493-.28-.958-.646-1.956-1.1-2.98.45-1.017.81-2.01 1.085-2.964zm-13.395.004c.278.96.645 1.957 1.1 2.98-.45 1.017-.812 2.01-1.086 2.964-.484-.15-.944-.318-1.37-.5-1.732-.737-2.852-1.706-2.852-2.474 0-.768 1.12-1.742 2.852-2.476.42-.18.88-.342 1.356-.494zm11.678 4.28c.265.657.49 1.312.676 1.948-.64.157-1.316.29-2.016.39.24-.375.48-.762.705-1.158.225-.39.435-.788.636-1.18zm-9.945.02c.2.392.41.783.64 1.175.23.39.465.772.705 1.143-.695-.102-1.365-.23-2.006-.386.18-.63.406-1.282.66-1.933zM17.92 16.32c.112.493.2.968.254 1.423.23 1.868-.054 3.32-.714 3.708-.147.09-.338.128-.563.128-1.012 0-2.514-.807-4.11-2.28.686-.72 1.37-1.536 2.02-2.44 1.107-.118 2.154-.3 3.113-.54zm-11.83.01c.96.234 2.006.415 3.107.532.66.905 1.345 1.727 2.035 2.446-1.595 1.483-3.092 2.295-4.11 2.295-.22-.005-.406-.05-.553-.132-.666-.38-.955-1.834-.73-3.703.054-.46.142-.944.25-1.438zm4.56.64c.44.02.89.034 1.345.034.46 0 .915-.01 1.36-.034-.44.572-.895 1.095-1.345 1.565-.455-.47-.91-.993-1.36-1.565z"/></svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
1
v3/internal/setupwizard/frontend/dist/logos/solid.svg
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill="#2C4F7C" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Solid</title><path d="M11.558.788A9.082 9.082 0 0 0 9.776.99l-.453.15c-.906.303-1.656.755-2.1 1.348l-.301.452-2.035 3.528c.426-.387.974-.698 1.643-.894h.001l.613-.154h.001a8.82 8.82 0 0 1 1.777-.206c2.916-.053 6.033 1.148 8.423 2.36 2.317 1.175 3.888 2.32 3.987 2.39L24 5.518c-.082-.06-1.66-1.21-3.991-2.386-2.393-1.206-5.521-2.396-8.45-2.343zM8.924 5.366a8.634 8.634 0 0 0-1.745.203l-.606.151c-1.278.376-2.095 1.16-2.43 2.108-.334.948-.188 2.065.487 3.116.33.43.747.813 1.216 1.147L12.328 10h.001a6.943 6.943 0 0 1 6.013 1.013l2.844-.963c-.17-.124-1.663-1.2-3.91-2.34-2.379-1.206-5.479-2.396-8.352-2.344zm5.435 4.497a6.791 6.791 0 0 0-1.984.283L2.94 13.189 0 18.334l9.276-2.992a6.945 6.945 0 0 1 7.408 2.314v.001c.695.903.89 1.906.66 2.808l2.572-4.63c.595-1.041.45-2.225-.302-3.429a6.792 6.792 0 0 0-5.255-2.543zm-3.031 5.341a6.787 6.787 0 0 0-2.006.283L.008 18.492c.175.131 2.02 1.498 4.687 2.768 2.797 1.332 6.37 2.467 9.468 1.712l.454-.152h.002c1.278-.376 2.134-1.162 2.487-2.09.353-.93.207-2.004-.541-2.978a6.791 6.791 0 0 0-5.237-2.548z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
1
v3/internal/setupwizard/frontend/dist/logos/svelte.svg
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill="#FF3E00" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Svelte</title><path d="M10.354 21.125a4.44 4.44 0 0 1-4.765-1.767 4.109 4.109 0 0 1-.703-3.107 3.898 3.898 0 0 1 .134-.522l.105-.321.287.21a7.21 7.21 0 0 0 2.186 1.092l.208.063-.02.208a1.253 1.253 0 0 0 .226.83 1.337 1.337 0 0 0 1.435.533 1.231 1.231 0 0 0 .343-.15l5.59-3.562a1.164 1.164 0 0 0 .524-.778 1.242 1.242 0 0 0-.211-.937 1.338 1.338 0 0 0-1.435-.533 1.23 1.23 0 0 0-.343.15l-2.133 1.36a4.078 4.078 0 0 1-1.135.499 4.44 4.44 0 0 1-4.765-1.766 4.108 4.108 0 0 1-.702-3.108 3.855 3.855 0 0 1 1.742-2.582l5.589-3.563a4.072 4.072 0 0 1 1.135-.499 4.44 4.44 0 0 1 4.765 1.767 4.109 4.109 0 0 1 .703 3.107 3.943 3.943 0 0 1-.134.522l-.105.321-.286-.21a7.204 7.204 0 0 0-2.187-1.093l-.208-.063.02-.207a1.255 1.255 0 0 0-.226-.831 1.337 1.337 0 0 0-1.435-.532 1.231 1.231 0 0 0-.343.15L8.62 9.368a1.162 1.162 0 0 0-.524.778 1.24 1.24 0 0 0 .211.937 1.338 1.338 0 0 0 1.435.533 1.235 1.235 0 0 0 .344-.151l2.132-1.36a4.067 4.067 0 0 1 1.135-.498 4.44 4.44 0 0 1 4.765 1.766 4.108 4.108 0 0 1 .702 3.108 3.857 3.857 0 0 1-1.742 2.583l-5.589 3.562a4.072 4.072 0 0 1-1.135.499m10.358-17.95C18.484-.015 14.082-.96 10.9 1.068L5.31 4.63a6.412 6.412 0 0 0-2.896 4.295 6.753 6.753 0 0 0 .666 4.336 6.43 6.43 0 0 0-.96 2.396 6.833 6.833 0 0 0 1.168 5.167c2.229 3.19 6.63 4.135 9.812 2.108l5.59-3.562a6.41 6.41 0 0 0 2.896-4.295 6.756 6.756 0 0 0-.665-4.336 6.429 6.429 0 0 0 .958-2.396 6.831 6.831 0 0 0-1.167-5.168Z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
1
v3/internal/setupwizard/frontend/dist/logos/typescript.svg
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill="#3178C6" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>TypeScript</title><path d="M1.125 0C.502 0 0 .502 0 1.125v21.75C0 23.498.502 24 1.125 24h21.75c.623 0 1.125-.502 1.125-1.125V1.125C24 .502 23.498 0 22.875 0zm17.363 9.75c.612 0 1.154.037 1.627.111a6.38 6.38 0 0 1 1.306.34v2.458a3.95 3.95 0 0 0-.643-.361 5.093 5.093 0 0 0-.717-.26 5.453 5.453 0 0 0-1.426-.2c-.3 0-.573.028-.819.086a2.1 2.1 0 0 0-.623.242c-.17.104-.3.229-.393.374a.888.888 0 0 0-.14.49c0 .196.053.373.156.529.104.156.252.304.443.444s.423.276.696.41c.273.135.582.274.926.416.47.197.892.407 1.266.628.374.222.695.473.963.753.268.279.472.598.614.957.142.359.214.776.214 1.253 0 .657-.125 1.21-.373 1.656a3.033 3.033 0 0 1-1.012 1.085 4.38 4.38 0 0 1-1.487.596c-.566.12-1.163.18-1.79.18a9.916 9.916 0 0 1-1.84-.164 5.544 5.544 0 0 1-1.512-.493v-2.63a5.033 5.033 0 0 0 3.237 1.2c.333 0 .624-.03.872-.09.249-.06.456-.144.623-.25.166-.108.29-.234.373-.38a1.023 1.023 0 0 0-.074-1.089 2.12 2.12 0 0 0-.537-.5 5.597 5.597 0 0 0-.807-.444 27.72 27.72 0 0 0-1.007-.436c-.918-.383-1.602-.852-2.053-1.405-.45-.553-.676-1.222-.676-2.005 0-.614.123-1.141.369-1.582.246-.441.58-.804 1.004-1.089a4.494 4.494 0 0 1 1.47-.629 7.536 7.536 0 0 1 1.77-.201zm-15.113.188h9.563v2.166H9.506v9.646H6.789v-9.646H3.375z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
1
v3/internal/setupwizard/frontend/dist/logos/vue.svg
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill="#4FC08D" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Vue.js</title><path d="M24,1.61H14.06L12,5.16,9.94,1.61H0L12,22.39ZM12,14.08,5.16,2.23H9.59L12,6.41l2.41-4.18h4.43Z"/></svg>
|
||||
|
After Width: | Height: | Size: 217 B |
|
|
@ -0,0 +1 @@
|
|||
<svg fill="#F7DF1E" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>JavaScript</title><path d="M0 0h24v24H0V0zm22.034 18.276c-.175-1.095-.888-2.015-3.003-2.873-.736-.345-1.554-.585-1.797-1.14-.091-.33-.105-.51-.046-.705.15-.646.915-.84 1.515-.66.39.12.75.42.976.9 1.034-.676 1.034-.676 1.755-1.125-.27-.42-.404-.601-.586-.78-.63-.705-1.469-1.065-2.834-1.034l-.705.089c-.676.165-1.32.525-1.71 1.005-1.14 1.291-.811 3.541.569 4.471 1.365 1.02 3.361 1.244 3.616 2.205.24 1.17-.87 1.545-1.966 1.41-.811-.18-1.26-.586-1.755-1.336l-1.83 1.051c.21.48.45.689.81 1.109 1.74 1.756 6.09 1.666 6.871-1.004.029-.09.24-.705.074-1.65l.046.067zm-8.983-7.245h-2.248c0 1.938-.009 3.864-.009 5.805 0 1.232.063 2.363-.138 2.711-.33.689-1.18.601-1.566.48-.396-.196-.597-.466-.83-.855-.063-.105-.11-.196-.127-.196l-1.825 1.125c.305.63.75 1.172 1.324 1.517.855.51 2.004.675 3.207.405.783-.226 1.458-.691 1.811-1.411.51-.93.402-2.07.397-3.346.012-2.054 0-4.109 0-6.179l.004-.056z"/></svg>
|
||||
|
After Width: | Height: | Size: 989 B |
1
v3/internal/setupwizard/frontend/public/logos/lit.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill="#324FFF" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Lit</title><path d="M2.4 9.6l4.8 4.8V24l-4.8-4.8V9.6zm4.8-4.8v9.6L12 9.6V0L7.2 4.8zM12 9.6v9.6l4.8-4.8V4.8L12 9.6zm4.8 4.8V24l4.8-4.8V9.6l-4.8 4.8z"/></svg>
|
||||
|
After Width: | Height: | Size: 249 B |
1
v3/internal/setupwizard/frontend/public/logos/preact.svg
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
1
v3/internal/setupwizard/frontend/public/logos/qwik.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill="#AC7EF4" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Qwik</title><path d="M7.5469 0a2.957 2.957 0 0 0-2.5606 1.4785L.5332 9.1915a2.957 2.957 0 0 0 0 2.957l4.4531 7.7128A2.955 2.955 0 0 0 7.547 21.338H12l8.5938 2.6484c.2409.0742.4512-.1782.3359-.4023l-1.916-3.7227 4.4531-7.7129a2.957 2.957 0 0 0 0-2.957l-4.4531-7.7129A2.957 2.957 0 0 0 16.453 0zm0 .7656L17.7324 10.67l-1.8965 1.8985.5782 7.5332L6.2676 10.67l2.371-2.373z"/></svg>
|
||||
|
After Width: | Height: | Size: 470 B |
1
v3/internal/setupwizard/frontend/public/logos/react.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill="#61DAFB" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>React</title><path d="M14.23 12.004a2.236 2.236 0 0 1-2.235 2.236 2.236 2.236 0 0 1-2.236-2.236 2.236 2.236 0 0 1 2.235-2.236 2.236 2.236 0 0 1 2.236 2.236zm2.648-10.69c-1.346 0-3.107.96-4.888 2.622-1.78-1.653-3.542-2.602-4.887-2.602-.41 0-.783.093-1.106.278-1.375.793-1.683 3.264-.973 6.365C1.98 8.917 0 10.42 0 12.004c0 1.59 1.99 3.097 5.043 4.03-.704 3.113-.39 5.588.988 6.38.32.187.69.275 1.102.275 1.345 0 3.107-.96 4.888-2.624 1.78 1.654 3.542 2.603 4.887 2.603.41 0 .783-.09 1.106-.275 1.374-.792 1.683-3.263.973-6.365C22.02 15.096 24 13.59 24 12.004c0-1.59-1.99-3.097-5.043-4.032.704-3.11.39-5.587-.988-6.38-.318-.184-.688-.277-1.092-.278zm-.005 1.09v.006c.225 0 .406.044.558.127.666.382.955 1.835.73 3.704-.054.46-.142.945-.25 1.44-.96-.236-2.006-.417-3.107-.534-.66-.905-1.345-1.727-2.035-2.447 1.592-1.48 3.087-2.292 4.105-2.295zm-9.77.02c1.012 0 2.514.808 4.11 2.28-.686.72-1.37 1.537-2.02 2.442-1.107.117-2.154.298-3.113.538-.112-.49-.195-.964-.254-1.42-.23-1.868.054-3.32.714-3.707.19-.09.4-.127.563-.132zm4.882 3.05c.455.468.91.992 1.36 1.564-.44-.02-.89-.034-1.345-.034-.46 0-.915.01-1.36.034.44-.572.895-1.096 1.345-1.565zM12 8.1c.74 0 1.477.034 2.202.093.406.582.802 1.203 1.183 1.86.372.64.71 1.29 1.018 1.946-.308.655-.646 1.31-1.013 1.95-.38.66-.773 1.288-1.18 1.87-.728.063-1.466.098-2.21.098-.74 0-1.477-.035-2.202-.093-.406-.582-.802-1.204-1.183-1.86-.372-.64-.71-1.29-1.018-1.946.303-.657.646-1.313 1.013-1.954.38-.66.773-1.286 1.18-1.868.728-.064 1.466-.098 2.21-.098zm-3.635.254c-.24.377-.48.763-.704 1.16-.225.39-.435.782-.635 1.174-.265-.656-.49-1.31-.676-1.947.64-.15 1.315-.283 2.015-.386zm7.26 0c.695.103 1.365.23 2.006.387-.18.632-.405 1.282-.66 1.933-.2-.39-.41-.783-.64-1.174-.225-.392-.465-.774-.705-1.146zm3.063.675c.484.15.944.317 1.375.498 1.732.74 2.852 1.708 2.852 2.476-.005.768-1.125 1.74-2.857 2.475-.42.18-.88.342-1.355.493-.28-.958-.646-1.956-1.1-2.98.45-1.017.81-2.01 1.085-2.964zm-13.395.004c.278.96.645 1.957 1.1 2.98-.45 1.017-.812 2.01-1.086 2.964-.484-.15-.944-.318-1.37-.5-1.732-.737-2.852-1.706-2.852-2.474 0-.768 1.12-1.742 2.852-2.476.42-.18.88-.342 1.356-.494zm11.678 4.28c.265.657.49 1.312.676 1.948-.64.157-1.316.29-2.016.39.24-.375.48-.762.705-1.158.225-.39.435-.788.636-1.18zm-9.945.02c.2.392.41.783.64 1.175.23.39.465.772.705 1.143-.695-.102-1.365-.23-2.006-.386.18-.63.406-1.282.66-1.933zM17.92 16.32c.112.493.2.968.254 1.423.23 1.868-.054 3.32-.714 3.708-.147.09-.338.128-.563.128-1.012 0-2.514-.807-4.11-2.28.686-.72 1.37-1.536 2.02-2.44 1.107-.118 2.154-.3 3.113-.54zm-11.83.01c.96.234 2.006.415 3.107.532.66.905 1.345 1.727 2.035 2.446-1.595 1.483-3.092 2.295-4.11 2.295-.22-.005-.406-.05-.553-.132-.666-.38-.955-1.834-.73-3.703.054-.46.142-.944.25-1.438zm4.56.64c.44.02.89.034 1.345.034.46 0 .915-.01 1.36-.034-.44.572-.895 1.095-1.345 1.565-.455-.47-.91-.993-1.36-1.565z"/></svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
1
v3/internal/setupwizard/frontend/public/logos/solid.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill="#2C4F7C" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Solid</title><path d="M11.558.788A9.082 9.082 0 0 0 9.776.99l-.453.15c-.906.303-1.656.755-2.1 1.348l-.301.452-2.035 3.528c.426-.387.974-.698 1.643-.894h.001l.613-.154h.001a8.82 8.82 0 0 1 1.777-.206c2.916-.053 6.033 1.148 8.423 2.36 2.317 1.175 3.888 2.32 3.987 2.39L24 5.518c-.082-.06-1.66-1.21-3.991-2.386-2.393-1.206-5.521-2.396-8.45-2.343zM8.924 5.366a8.634 8.634 0 0 0-1.745.203l-.606.151c-1.278.376-2.095 1.16-2.43 2.108-.334.948-.188 2.065.487 3.116.33.43.747.813 1.216 1.147L12.328 10h.001a6.943 6.943 0 0 1 6.013 1.013l2.844-.963c-.17-.124-1.663-1.2-3.91-2.34-2.379-1.206-5.479-2.396-8.352-2.344zm5.435 4.497a6.791 6.791 0 0 0-1.984.283L2.94 13.189 0 18.334l9.276-2.992a6.945 6.945 0 0 1 7.408 2.314v.001c.695.903.89 1.906.66 2.808l2.572-4.63c.595-1.041.45-2.225-.302-3.429a6.792 6.792 0 0 0-5.255-2.543zm-3.031 5.341a6.787 6.787 0 0 0-2.006.283L.008 18.492c.175.131 2.02 1.498 4.687 2.768 2.797 1.332 6.37 2.467 9.468 1.712l.454-.152h.002c1.278-.376 2.134-1.162 2.487-2.09.353-.93.207-2.004-.541-2.978a6.791 6.791 0 0 0-5.237-2.548z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
1
v3/internal/setupwizard/frontend/public/logos/svelte.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill="#FF3E00" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Svelte</title><path d="M10.354 21.125a4.44 4.44 0 0 1-4.765-1.767 4.109 4.109 0 0 1-.703-3.107 3.898 3.898 0 0 1 .134-.522l.105-.321.287.21a7.21 7.21 0 0 0 2.186 1.092l.208.063-.02.208a1.253 1.253 0 0 0 .226.83 1.337 1.337 0 0 0 1.435.533 1.231 1.231 0 0 0 .343-.15l5.59-3.562a1.164 1.164 0 0 0 .524-.778 1.242 1.242 0 0 0-.211-.937 1.338 1.338 0 0 0-1.435-.533 1.23 1.23 0 0 0-.343.15l-2.133 1.36a4.078 4.078 0 0 1-1.135.499 4.44 4.44 0 0 1-4.765-1.766 4.108 4.108 0 0 1-.702-3.108 3.855 3.855 0 0 1 1.742-2.582l5.589-3.563a4.072 4.072 0 0 1 1.135-.499 4.44 4.44 0 0 1 4.765 1.767 4.109 4.109 0 0 1 .703 3.107 3.943 3.943 0 0 1-.134.522l-.105.321-.286-.21a7.204 7.204 0 0 0-2.187-1.093l-.208-.063.02-.207a1.255 1.255 0 0 0-.226-.831 1.337 1.337 0 0 0-1.435-.532 1.231 1.231 0 0 0-.343.15L8.62 9.368a1.162 1.162 0 0 0-.524.778 1.24 1.24 0 0 0 .211.937 1.338 1.338 0 0 0 1.435.533 1.235 1.235 0 0 0 .344-.151l2.132-1.36a4.067 4.067 0 0 1 1.135-.498 4.44 4.44 0 0 1 4.765 1.766 4.108 4.108 0 0 1 .702 3.108 3.857 3.857 0 0 1-1.742 2.583l-5.589 3.562a4.072 4.072 0 0 1-1.135.499m10.358-17.95C18.484-.015 14.082-.96 10.9 1.068L5.31 4.63a6.412 6.412 0 0 0-2.896 4.295 6.753 6.753 0 0 0 .666 4.336 6.43 6.43 0 0 0-.96 2.396 6.833 6.833 0 0 0 1.168 5.167c2.229 3.19 6.63 4.135 9.812 2.108l5.59-3.562a6.41 6.41 0 0 0 2.896-4.295 6.756 6.756 0 0 0-.665-4.336 6.429 6.429 0 0 0 .958-2.396 6.831 6.831 0 0 0-1.167-5.168Z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
|
@ -0,0 +1 @@
|
|||
<svg fill="#3178C6" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>TypeScript</title><path d="M1.125 0C.502 0 0 .502 0 1.125v21.75C0 23.498.502 24 1.125 24h21.75c.623 0 1.125-.502 1.125-1.125V1.125C24 .502 23.498 0 22.875 0zm17.363 9.75c.612 0 1.154.037 1.627.111a6.38 6.38 0 0 1 1.306.34v2.458a3.95 3.95 0 0 0-.643-.361 5.093 5.093 0 0 0-.717-.26 5.453 5.453 0 0 0-1.426-.2c-.3 0-.573.028-.819.086a2.1 2.1 0 0 0-.623.242c-.17.104-.3.229-.393.374a.888.888 0 0 0-.14.49c0 .196.053.373.156.529.104.156.252.304.443.444s.423.276.696.41c.273.135.582.274.926.416.47.197.892.407 1.266.628.374.222.695.473.963.753.268.279.472.598.614.957.142.359.214.776.214 1.253 0 .657-.125 1.21-.373 1.656a3.033 3.033 0 0 1-1.012 1.085 4.38 4.38 0 0 1-1.487.596c-.566.12-1.163.18-1.79.18a9.916 9.916 0 0 1-1.84-.164 5.544 5.544 0 0 1-1.512-.493v-2.63a5.033 5.033 0 0 0 3.237 1.2c.333 0 .624-.03.872-.09.249-.06.456-.144.623-.25.166-.108.29-.234.373-.38a1.023 1.023 0 0 0-.074-1.089 2.12 2.12 0 0 0-.537-.5 5.597 5.597 0 0 0-.807-.444 27.72 27.72 0 0 0-1.007-.436c-.918-.383-1.602-.852-2.053-1.405-.45-.553-.676-1.222-.676-2.005 0-.614.123-1.141.369-1.582.246-.441.58-.804 1.004-1.089a4.494 4.494 0 0 1 1.47-.629 7.536 7.536 0 0 1 1.77-.201zm-15.113.188h9.563v2.166H9.506v9.646H6.789v-9.646H3.375z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
1
v3/internal/setupwizard/frontend/public/logos/vue.svg
Normal file
|
|
@ -0,0 +1 @@
|
|||
<svg fill="#4FC08D" role="img" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Vue.js</title><path d="M24,1.61H14.06L12,5.16,9.94,1.61H0L12,22.39ZM12,14.08,5.16,2.23H9.59L12,6.41l2.41-4.18h4.43Z"/></svg>
|
||||
|
After Width: | Height: | Size: 217 B |
|
|
@ -14,10 +14,21 @@ type OOBEStep =
|
|||
| 'cross-platform'
|
||||
| 'docker-setup'
|
||||
| 'projects'
|
||||
| 'language-select'
|
||||
| 'template-select'
|
||||
| 'complete';
|
||||
|
||||
// Framework template info
|
||||
type FrameworkTemplate = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
color: string;
|
||||
icon: string;
|
||||
};
|
||||
|
||||
// Wizard stages for sidebar progress display
|
||||
type WizardStage = 'welcome' | 'dependencies' | 'platform' | 'identity' | 'complete';
|
||||
type WizardStage = 'welcome' | 'dependencies' | 'platform' | 'identity' | 'templates' | 'complete';
|
||||
|
||||
// Map OOBE steps to wizard stages
|
||||
function getWizardStage(step: OOBEStep): WizardStage {
|
||||
|
|
@ -33,6 +44,9 @@ function getWizardStage(step: OOBEStep): WizardStage {
|
|||
return 'platform';
|
||||
case 'projects':
|
||||
return 'identity';
|
||||
case 'language-select':
|
||||
case 'template-select':
|
||||
return 'templates';
|
||||
case 'complete':
|
||||
return 'complete';
|
||||
default:
|
||||
|
|
@ -40,9 +54,9 @@ function getWizardStage(step: OOBEStep): WizardStage {
|
|||
}
|
||||
}
|
||||
|
||||
// Get stage index for progress tracking (1-5)
|
||||
// Get stage index for progress tracking (1-6)
|
||||
function getStageIndex(stage: WizardStage): number {
|
||||
const stages: WizardStage[] = ['welcome', 'dependencies', 'platform', 'identity', 'complete'];
|
||||
const stages: WizardStage[] = ['welcome', 'dependencies', 'platform', 'identity', 'templates', 'complete'];
|
||||
return stages.indexOf(stage) + 1;
|
||||
}
|
||||
|
||||
|
|
@ -75,6 +89,7 @@ function Sidebar({ currentStep }: { currentStep: OOBEStep }) {
|
|||
{ key: 'dependencies' as const, label: 'Dependencies' },
|
||||
{ key: 'platform' as const, label: 'Platform' },
|
||||
{ key: 'identity' as const, label: 'Projects' },
|
||||
{ key: 'templates' as const, label: 'Templates' },
|
||||
{ key: 'complete' as const, label: 'Complete' },
|
||||
];
|
||||
|
||||
|
|
@ -193,6 +208,33 @@ function PageTemplate({
|
|||
secondaryLabel?: string;
|
||||
primaryDisabled?: boolean;
|
||||
}) {
|
||||
// Render actions as a render prop so parent can place them where needed
|
||||
const actionsElement = (primaryAction || secondaryAction) ? (
|
||||
<div className="flex-shrink-0 pt-4 pb-6 flex flex-col items-center gap-1.5">
|
||||
{primaryAction && primaryLabel && (
|
||||
<button
|
||||
onClick={primaryAction}
|
||||
disabled={primaryDisabled}
|
||||
className={`px-5 py-2 rounded-lg text-sm font-medium transition-colors border ${
|
||||
primaryDisabled
|
||||
? 'border-gray-300 dark:border-gray-700 text-gray-400 cursor-not-allowed'
|
||||
: 'border-red-500 text-red-600 dark:text-red-400 hover:bg-red-500/10'
|
||||
}`}
|
||||
>
|
||||
{primaryLabel}
|
||||
</button>
|
||||
)}
|
||||
{secondaryAction && secondaryLabel && (
|
||||
<button
|
||||
onClick={secondaryAction}
|
||||
className="text-xs text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 transition-colors"
|
||||
>
|
||||
{secondaryLabel}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
variants={pageVariants}
|
||||
|
|
@ -200,45 +242,21 @@ function PageTemplate({
|
|||
animate="animate"
|
||||
exit="exit"
|
||||
transition={{ duration: 0.3 }}
|
||||
className="h-full flex flex-col"
|
||||
className="flex-1 flex flex-col"
|
||||
>
|
||||
{/* Header - centered */}
|
||||
<div className="text-center mb-6 flex-shrink-0">
|
||||
{/* Header - centered with horizontal padding */}
|
||||
<div className="text-center mb-6 flex-shrink-0 px-10 pt-10">
|
||||
<h1 className="text-2xl font-semibold text-gray-900 dark:text-white mb-1.5 tracking-tight">{title}</h1>
|
||||
<p className="text-base text-gray-500 dark:text-gray-400">{subtitle}</p>
|
||||
</div>
|
||||
|
||||
{/* Scrollable content area */}
|
||||
<div className="flex-1 overflow-y-auto scrollbar-thin min-h-0">
|
||||
{/* Scrollable content area with horizontal padding */}
|
||||
<div className="flex-1 overflow-y-auto scrollbar-thin min-h-0 px-10">
|
||||
{children}
|
||||
</div>
|
||||
|
||||
{/* Actions - only shown if provided */}
|
||||
{(primaryAction || secondaryAction) && (
|
||||
<div className="flex-shrink-0 pt-4 flex flex-col items-center gap-1.5">
|
||||
{primaryAction && primaryLabel && (
|
||||
<button
|
||||
onClick={primaryAction}
|
||||
disabled={primaryDisabled}
|
||||
className={`px-5 py-2 rounded-lg text-sm font-medium transition-colors border ${
|
||||
primaryDisabled
|
||||
? 'border-gray-300 dark:border-gray-700 text-gray-400 cursor-not-allowed'
|
||||
: 'border-red-500 text-red-600 dark:text-red-400 hover:bg-red-500/10'
|
||||
}`}
|
||||
>
|
||||
{primaryLabel}
|
||||
</button>
|
||||
)}
|
||||
{secondaryAction && secondaryLabel && (
|
||||
<button
|
||||
onClick={secondaryAction}
|
||||
className="text-xs text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 transition-colors"
|
||||
>
|
||||
{secondaryLabel}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{/* Actions - anchored to bottom */}
|
||||
{actionsElement}
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
|
@ -254,7 +272,7 @@ function SplashPage({ onNext }: { onNext: () => void }) {
|
|||
animate="animate"
|
||||
exit="exit"
|
||||
transition={{ duration: 0.3 }}
|
||||
className="h-full flex flex-col items-center justify-center"
|
||||
className="flex-1 flex flex-col items-center justify-center"
|
||||
>
|
||||
{/* Logo with glow effect */}
|
||||
<motion.div
|
||||
|
|
@ -312,7 +330,7 @@ function CheckingPage() {
|
|||
animate="animate"
|
||||
exit="exit"
|
||||
transition={{ duration: 0.3 }}
|
||||
className="h-full flex flex-col items-center justify-center"
|
||||
className="flex-1 flex flex-col items-center justify-start pt-[30%]"
|
||||
>
|
||||
<motion.div
|
||||
className="w-12 h-12 border-3 border-gray-300 dark:border-gray-600 border-t-red-500 rounded-full mb-6"
|
||||
|
|
@ -338,7 +356,7 @@ function DepsReadyPage({ onNext }: { onNext: () => void }) {
|
|||
animate="animate"
|
||||
exit="exit"
|
||||
transition={{ duration: 0.3 }}
|
||||
className="h-full flex flex-col items-center justify-center"
|
||||
className="flex-1 flex flex-col items-center justify-center"
|
||||
>
|
||||
{/* Animated checkmark */}
|
||||
<motion.div
|
||||
|
|
@ -512,7 +530,7 @@ function CrossPlatformPage({
|
|||
animate="animate"
|
||||
exit="exit"
|
||||
transition={{ duration: 0.3 }}
|
||||
className="h-full flex flex-col items-center justify-center"
|
||||
className="flex-1 flex flex-col items-center justify-center"
|
||||
>
|
||||
{isReady ? (
|
||||
<>
|
||||
|
|
@ -631,7 +649,7 @@ function DockerSetupPage({
|
|||
animate="animate"
|
||||
exit="exit"
|
||||
transition={{ duration: 0.3 }}
|
||||
className="h-full flex flex-col items-center justify-center"
|
||||
className="flex-1 flex flex-col items-center justify-center"
|
||||
>
|
||||
<div className="w-16 h-16 rounded-2xl bg-blue-500/20 flex items-center justify-center mb-6">
|
||||
<svg className="w-10 h-10" viewBox="0 0 756.26 596.9">
|
||||
|
|
@ -690,7 +708,7 @@ function DockerSetupPage({
|
|||
animate="animate"
|
||||
exit="exit"
|
||||
transition={{ duration: 0.3 }}
|
||||
className="h-full flex flex-col items-center justify-center"
|
||||
className="flex-1 flex flex-col items-center justify-center"
|
||||
>
|
||||
<div className="w-16 h-16 rounded-2xl bg-gray-200 dark:bg-gray-800 flex items-center justify-center mb-6 opacity-50">
|
||||
<svg className="w-10 h-10" viewBox="0 0 756.26 596.9">
|
||||
|
|
@ -733,7 +751,7 @@ function DockerSetupPage({
|
|||
animate="animate"
|
||||
exit="exit"
|
||||
transition={{ duration: 0.3 }}
|
||||
className="h-full flex flex-col items-center justify-center"
|
||||
className="flex-1 flex flex-col items-center justify-center"
|
||||
>
|
||||
<div className="w-16 h-16 rounded-2xl bg-blue-500/20 flex items-center justify-center mb-6">
|
||||
<svg className="w-10 h-10" viewBox="0 0 756.26 596.9">
|
||||
|
|
@ -781,7 +799,7 @@ function DockerSetupPage({
|
|||
animate="animate"
|
||||
exit="exit"
|
||||
transition={{ duration: 0.3 }}
|
||||
className="h-full flex flex-col items-center justify-center"
|
||||
className="flex-1 flex flex-col items-center justify-center"
|
||||
>
|
||||
<motion.div
|
||||
initial={{ scale: 0 }}
|
||||
|
|
@ -819,7 +837,7 @@ function DockerSetupPage({
|
|||
animate="animate"
|
||||
exit="exit"
|
||||
transition={{ duration: 0.3 }}
|
||||
className="h-full flex flex-col items-center justify-center"
|
||||
className="flex-1 flex flex-col items-center justify-center"
|
||||
>
|
||||
<div className="w-16 h-16 rounded-2xl bg-blue-500/20 flex items-center justify-center mb-6">
|
||||
<svg className="w-10 h-10" viewBox="0 0 756.26 596.9">
|
||||
|
|
@ -855,6 +873,144 @@ function DockerSetupPage({
|
|||
);
|
||||
}
|
||||
|
||||
// Available framework templates
|
||||
const FRAMEWORKS: FrameworkTemplate[] = [
|
||||
{ id: 'vanilla', name: 'Vanilla', description: 'Plain JavaScript/TypeScript', color: '#f7df1e', icon: 'javascript' },
|
||||
{ id: 'react', name: 'React', description: 'React with Vite', color: '#61dafb', icon: 'react' },
|
||||
{ id: 'vue', name: 'Vue', description: 'Vue 3 with Vite', color: '#42b883', icon: 'vue' },
|
||||
{ id: 'svelte', name: 'Svelte', description: 'Svelte with Vite', color: '#ff3e00', icon: 'svelte' },
|
||||
{ id: 'preact', name: 'Preact', description: 'Lightweight React alternative', color: '#673ab8', icon: 'preact' },
|
||||
{ id: 'lit', name: 'Lit', description: 'Web Components with Lit', color: '#324fff', icon: 'lit' },
|
||||
{ id: 'solid', name: 'Solid', description: 'Solid.js with Vite', color: '#2c4f7c', icon: 'solid' },
|
||||
{ id: 'qwik', name: 'Qwik', description: 'Qwik with Vite', color: '#18b6f6', icon: 'qwik' },
|
||||
];
|
||||
|
||||
// Language Select Page - TypeScript or JavaScript
|
||||
function LanguageSelectPage({
|
||||
preferTypeScript,
|
||||
onSelect,
|
||||
onNext,
|
||||
}: {
|
||||
preferTypeScript: boolean;
|
||||
onSelect: (useTypeScript: boolean) => void;
|
||||
onNext: () => void;
|
||||
}) {
|
||||
return (
|
||||
<motion.div
|
||||
variants={pageVariants}
|
||||
initial="initial"
|
||||
animate="animate"
|
||||
exit="exit"
|
||||
transition={{ duration: 0.3 }}
|
||||
className="flex-1 flex flex-col"
|
||||
>
|
||||
{/* Main content - centered */}
|
||||
<div className="flex-1 flex flex-col items-center justify-center">
|
||||
<h2 className="text-2xl font-semibold text-gray-900 dark:text-white mb-2 text-center">
|
||||
Language Preference
|
||||
</h2>
|
||||
<p className="text-gray-500 dark:text-gray-400 mb-8 text-center max-w-md">
|
||||
Choose your preferred language for new projects
|
||||
</p>
|
||||
|
||||
<div className="flex gap-4">
|
||||
{/* JavaScript card */}
|
||||
<button
|
||||
onClick={() => onSelect(false)}
|
||||
className={`w-40 h-48 rounded-xl p-5 flex flex-col items-center justify-center gap-3 transition-all border-2 ${
|
||||
!preferTypeScript
|
||||
? 'border-yellow-400 bg-yellow-400/10 shadow-lg shadow-yellow-400/20'
|
||||
: 'border-white/10 bg-white/5 hover:bg-white/10'
|
||||
}`}
|
||||
>
|
||||
<div className="w-16 h-16 flex items-center justify-center">
|
||||
<img src="/logos/javascript.svg" alt="JavaScript" className="w-14 h-14" />
|
||||
</div>
|
||||
<span className="text-lg font-semibold text-white">JavaScript</span>
|
||||
<span className="text-xs text-white/50">Dynamic typing</span>
|
||||
</button>
|
||||
|
||||
{/* TypeScript card */}
|
||||
<button
|
||||
onClick={() => onSelect(true)}
|
||||
className={`w-40 h-48 rounded-xl p-5 flex flex-col items-center justify-center gap-3 transition-all border-2 ${
|
||||
preferTypeScript
|
||||
? 'border-blue-400 bg-blue-400/10 shadow-lg shadow-blue-400/20'
|
||||
: 'border-white/10 bg-white/5 hover:bg-white/10'
|
||||
}`}
|
||||
>
|
||||
<div className="w-16 h-16 flex items-center justify-center">
|
||||
<img src="/logos/typescript.svg" alt="TypeScript" className="w-14 h-14" />
|
||||
</div>
|
||||
<span className="text-lg font-semibold text-white">TypeScript</span>
|
||||
<span className="text-xs text-white/50">Type safety</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Button area - sibling below main content */}
|
||||
<div className="flex justify-center pb-6">
|
||||
<button
|
||||
onClick={onNext}
|
||||
className="px-5 py-2 rounded-lg border border-red-500 text-red-600 dark:text-red-400 text-sm font-medium hover:bg-red-500/10 transition-colors"
|
||||
>
|
||||
Continue
|
||||
</button>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
// Template Select Page - Framework cards grid
|
||||
function TemplateSelectPage({
|
||||
selectedFramework,
|
||||
preferTypeScript,
|
||||
onSelect,
|
||||
onNext,
|
||||
onSkip,
|
||||
}: {
|
||||
selectedFramework: string;
|
||||
preferTypeScript: boolean;
|
||||
onSelect: (frameworkId: string) => void;
|
||||
onNext: () => void;
|
||||
onSkip: () => void;
|
||||
}) {
|
||||
return (
|
||||
<PageTemplate
|
||||
title="Default Template"
|
||||
subtitle="Choose a framework for new projects"
|
||||
primaryAction={onNext}
|
||||
primaryLabel="Continue"
|
||||
secondaryAction={onSkip}
|
||||
secondaryLabel="Skip"
|
||||
>
|
||||
<div className="grid grid-cols-4 gap-3 max-w-2xl mx-auto">
|
||||
{FRAMEWORKS.map((framework) => (
|
||||
<button
|
||||
key={framework.id}
|
||||
onClick={() => onSelect(framework.id)}
|
||||
className={`aspect-square rounded-xl p-4 flex flex-col items-center justify-center gap-2 transition-all border-2 ${
|
||||
selectedFramework === framework.id
|
||||
? 'border-red-500 bg-red-500/10 shadow-lg shadow-red-500/10'
|
||||
: 'border-white/10 bg-white/5 hover:bg-white/10'
|
||||
}`}
|
||||
>
|
||||
<img
|
||||
src={`/logos/${framework.id === 'vanilla' ? (preferTypeScript ? 'typescript' : 'javascript') : framework.icon}.svg`}
|
||||
alt={framework.name}
|
||||
className="w-12 h-12"
|
||||
/>
|
||||
<span className="text-sm font-medium text-white">{framework.name}</span>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
<p className="text-xs text-white/40 mt-4 text-center">
|
||||
This sets the default template for new projects
|
||||
</p>
|
||||
</PageTemplate>
|
||||
);
|
||||
}
|
||||
|
||||
// Projects Page - Company and Bundle ID (no template)
|
||||
function ProjectsPage({
|
||||
defaults,
|
||||
|
|
@ -1022,31 +1178,49 @@ function CompletePage({ onClose }: { onClose: () => void }) {
|
|||
animate="animate"
|
||||
exit="exit"
|
||||
transition={{ duration: 0.3 }}
|
||||
className="h-full flex flex-col items-center justify-center"
|
||||
className="flex-1 flex flex-col items-center justify-center px-8"
|
||||
>
|
||||
<motion.div
|
||||
initial={{ scale: 0 }}
|
||||
animate={{ scale: 1 }}
|
||||
transition={{ type: 'spring', stiffness: 200, damping: 15 }}
|
||||
className="w-20 h-20 rounded-full bg-green-500/20 flex items-center justify-center mb-6"
|
||||
>
|
||||
<svg className="w-10 h-10 text-green-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
</motion.div>
|
||||
{/* Header with check and title - compact */}
|
||||
<div className="flex items-center gap-3 mb-4">
|
||||
<motion.div
|
||||
initial={{ scale: 0 }}
|
||||
animate={{ scale: 1 }}
|
||||
transition={{ type: 'spring', stiffness: 200, damping: 15 }}
|
||||
className="w-8 h-8 rounded-full bg-green-500/20 flex items-center justify-center"
|
||||
>
|
||||
<svg className="w-4 h-4 text-green-500" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2.5} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
</motion.div>
|
||||
<h2 className="text-lg font-semibold text-gray-900 dark:text-white">
|
||||
You're ready to build!
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<h2 className="text-2xl font-semibold text-gray-900 dark:text-white mb-2">
|
||||
You're ready to build!
|
||||
</h2>
|
||||
<p className="text-gray-500 dark:text-gray-400 mb-8 text-center max-w-sm">
|
||||
Your development environment is all set up
|
||||
</p>
|
||||
|
||||
<div className="bg-gray-100 dark:bg-gray-900/50 rounded-xl p-5 mb-8 w-full max-w-sm">
|
||||
<div className="space-y-4">
|
||||
<CopyableCommand command="wails3 init -n myapp" label="Create your first app:" />
|
||||
<CopyableCommand command="cd myapp && wails3 dev" label="Start developing:" />
|
||||
<CopyableCommand command="wails3 build" label="Build for production:" />
|
||||
{/* Terminal-style command display */}
|
||||
<div className="bg-gray-900 dark:bg-black/50 rounded-lg p-4 mb-6 w-full max-w-md font-mono text-xs border border-gray-700/50">
|
||||
<div className="flex items-center gap-2 mb-3 pb-2 border-b border-gray-700/50">
|
||||
<div className="w-2.5 h-2.5 rounded-full bg-red-500/80" />
|
||||
<div className="w-2.5 h-2.5 rounded-full bg-yellow-500/80" />
|
||||
<div className="w-2.5 h-2.5 rounded-full bg-green-500/80" />
|
||||
<span className="text-gray-500 text-[10px] ml-2">terminal</span>
|
||||
</div>
|
||||
<div className="space-y-2 text-gray-300">
|
||||
<div className="flex items-start gap-2">
|
||||
<span className="text-green-400 select-none">$</span>
|
||||
<span className="text-gray-100">wails3 init -n myapp</span>
|
||||
<span className="text-gray-500 ml-auto text-[10px]"># create app</span>
|
||||
</div>
|
||||
<div className="flex items-start gap-2">
|
||||
<span className="text-green-400 select-none">$</span>
|
||||
<span className="text-gray-100">cd myapp && wails3 dev</span>
|
||||
<span className="text-gray-500 ml-auto text-[10px]"># develop</span>
|
||||
</div>
|
||||
<div className="flex items-start gap-2">
|
||||
<span className="text-green-400 select-none">$</span>
|
||||
<span className="text-gray-100">wails3 build</span>
|
||||
<span className="text-gray-500 ml-auto text-[10px]"># build</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -1069,73 +1243,6 @@ function CompletePage({ onClose }: { onClose: () => void }) {
|
|||
);
|
||||
}
|
||||
|
||||
// Persistent Docker status indicator
|
||||
function DockerStatusIndicator({
|
||||
status,
|
||||
visible
|
||||
}: {
|
||||
status: DockerStatus | null;
|
||||
visible: boolean;
|
||||
}) {
|
||||
if (!visible || !status) return null;
|
||||
if (!status.installed || !status.running) return null;
|
||||
if (status.imageBuilt && status.pullStatus !== 'pulling') return null;
|
||||
|
||||
const isPulling = status.pullStatus === 'pulling';
|
||||
const progress = status.pullProgress || 0;
|
||||
|
||||
return (
|
||||
<motion.div
|
||||
initial={{ opacity: 0, y: 10 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: 10 }}
|
||||
className="bg-white/95 dark:bg-gray-900/95 border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg px-3 py-2 backdrop-blur-sm min-w-[200px]"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-8 h-8 rounded-lg bg-blue-500/20 flex items-center justify-center flex-shrink-0">
|
||||
<svg className="w-5 h-5" viewBox="0 0 756.26 596.9">
|
||||
<path fill="#1d63ed" d="M743.96,245.25c-18.54-12.48-67.26-17.81-102.68-8.27-1.91-35.28-20.1-65.01-53.38-90.95l-12.32-8.27-8.21,12.4c-16.14,24.5-22.94,57.14-20.53,86.81,1.9,18.28,8.26,38.83,20.53,53.74-46.1,26.74-88.59,20.67-276.77,20.67H.06c-.85,42.49,5.98,124.23,57.96,190.77,5.74,7.35,12.04,14.46,18.87,21.31,42.26,42.32,106.11,73.35,201.59,73.44,145.66.13,270.46-78.6,346.37-268.97,24.98.41,90.92,4.48,123.19-57.88.79-1.05,8.21-16.54,8.21-16.54l-12.3-8.27ZM189.67,206.39h-81.7v81.7h81.7v-81.7ZM295.22,206.39h-81.7v81.7h81.7v-81.7ZM400.77,206.39h-81.7v81.7h81.7v-81.7ZM506.32,206.39h-81.7v81.7h81.7v-81.7ZM84.12,206.39H2.42v81.7h81.7v-81.7ZM189.67,103.2h-81.7v81.7h81.7v-81.7ZM295.22,103.2h-81.7v81.7h81.7v-81.7ZM400.77,103.2h-81.7v81.7h81.7v-81.7ZM400.77,0h-81.7v81.7h81.7V0Z"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
{isPulling ? (
|
||||
<>
|
||||
<div className="flex items-center gap-2 text-blue-600 dark:text-blue-400 text-sm mb-1">
|
||||
<motion.span
|
||||
className="w-3 h-3 border-2 border-blue-600 dark:border-blue-400 border-t-transparent rounded-full"
|
||||
animate={{ rotate: 360 }}
|
||||
transition={{ duration: 1, repeat: Infinity, ease: 'linear' }}
|
||||
/>
|
||||
<span className="truncate">Building image...</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex-1 h-1.5 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<motion.div
|
||||
className="h-full bg-blue-500"
|
||||
animate={{ width: `${progress}%` }}
|
||||
/>
|
||||
</div>
|
||||
<span className="text-xs text-gray-500 tabular-nums">{progress}%</span>
|
||||
</div>
|
||||
</>
|
||||
) : status.imageBuilt ? (
|
||||
<div className="flex items-center gap-2 text-green-600 dark:text-green-400 text-sm">
|
||||
<svg className="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
<span>Docker image ready</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="text-sm text-gray-600 dark:text-gray-400">
|
||||
Preparing Docker build...
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
);
|
||||
}
|
||||
|
||||
// Main App
|
||||
export default function App() {
|
||||
const [step, setStep] = useState<OOBEStep>('splash');
|
||||
|
|
@ -1155,6 +1262,8 @@ export default function App() {
|
|||
});
|
||||
const [savingDefaults, setSavingDefaults] = useState(false);
|
||||
const [backgroundDockerStarted, setBackgroundDockerStarted] = useState(false);
|
||||
const [preferTypeScript, setPreferTypeScript] = useState(true);
|
||||
const [selectedFramework, setSelectedFramework] = useState('vanilla');
|
||||
const [theme, setTheme] = useState<Theme>(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
const saved = localStorage.getItem('wails-setup-theme');
|
||||
|
|
@ -1282,14 +1391,45 @@ export default function App() {
|
|||
setStep('projects');
|
||||
};
|
||||
|
||||
const handleProjectsNext = async () => {
|
||||
const handleProjectsNext = () => {
|
||||
setStep('language-select');
|
||||
};
|
||||
|
||||
const handleProjectsSkip = () => {
|
||||
setStep('language-select');
|
||||
};
|
||||
|
||||
const handleLanguageSelectNext = () => {
|
||||
setStep('template-select');
|
||||
};
|
||||
|
||||
const handleTemplateSelectNext = async () => {
|
||||
// Build template name with TS suffix if needed
|
||||
const templateName = preferTypeScript && selectedFramework !== 'vanilla'
|
||||
? `${selectedFramework}-ts`
|
||||
: preferTypeScript && selectedFramework === 'vanilla'
|
||||
? 'vanilla-ts'
|
||||
: selectedFramework;
|
||||
|
||||
// Update defaults with selected template
|
||||
const updatedDefaults = {
|
||||
...defaults,
|
||||
project: {
|
||||
...defaults.project,
|
||||
defaultTemplate: templateName
|
||||
}
|
||||
};
|
||||
|
||||
setSavingDefaults(true);
|
||||
await saveDefaults(defaults);
|
||||
await saveDefaults(updatedDefaults);
|
||||
setSavingDefaults(false);
|
||||
setStep('complete');
|
||||
};
|
||||
|
||||
const handleProjectsSkip = () => {
|
||||
const handleTemplateSelectSkip = async () => {
|
||||
setSavingDefaults(true);
|
||||
await saveDefaults(defaults);
|
||||
setSavingDefaults(false);
|
||||
setStep('complete');
|
||||
};
|
||||
|
||||
|
|
@ -1315,8 +1455,6 @@ export default function App() {
|
|||
}
|
||||
}, [backgroundDockerStarted, buildingImage, dockerStatus?.pullStatus]);
|
||||
|
||||
const showDockerIndicator = backgroundDockerStarted && step !== 'docker-setup' && step !== 'splash' && step !== 'checking';
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={{ theme, toggleTheme }}>
|
||||
<div className="min-h-screen bg-gray-50 dark:bg-[#0f0f0f] flex items-center justify-center p-4 transition-colors relative overflow-hidden">
|
||||
|
|
@ -1335,7 +1473,7 @@ export default function App() {
|
|||
|
||||
{/* Content area - distinct from sidebar in dark mode */}
|
||||
<div className="flex-1 flex flex-col min-w-0 bg-white/50 dark:bg-white/[0.03]">
|
||||
<div className="flex-1 flex flex-col p-10 min-h-0">
|
||||
<div className="flex-1 flex flex-col min-h-0">
|
||||
<AnimatePresence mode="wait">
|
||||
{step === 'splash' && (
|
||||
<SplashPage key="splash" onNext={handleSplashNext} />
|
||||
|
|
@ -1383,23 +1521,29 @@ export default function App() {
|
|||
saving={savingDefaults}
|
||||
/>
|
||||
)}
|
||||
{step === 'language-select' && (
|
||||
<LanguageSelectPage
|
||||
key="language-select"
|
||||
preferTypeScript={preferTypeScript}
|
||||
onSelect={setPreferTypeScript}
|
||||
onNext={handleLanguageSelectNext}
|
||||
/>
|
||||
)}
|
||||
{step === 'template-select' && (
|
||||
<TemplateSelectPage
|
||||
key="template-select"
|
||||
selectedFramework={selectedFramework}
|
||||
preferTypeScript={preferTypeScript}
|
||||
onSelect={setSelectedFramework}
|
||||
onNext={handleTemplateSelectNext}
|
||||
onSkip={handleTemplateSelectSkip}
|
||||
/>
|
||||
)}
|
||||
{step === 'complete' && (
|
||||
<CompletePage key="complete" onClose={handleClose} />
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
|
||||
{/* Docker status indicator - bottom left of content area */}
|
||||
<div className="flex-shrink-0 px-6 pb-6 pt-2">
|
||||
<AnimatePresence>
|
||||
{showDockerIndicator && (
|
||||
<DockerStatusIndicator
|
||||
status={dockerStatus}
|
||||
visible={showDockerIndicator}
|
||||
/>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ html, body, #root {
|
|||
|
||||
/* Glass sidebar - blurred to show background through */
|
||||
.glass-sidebar {
|
||||
background: rgba(5, 7, 12, 0.75);
|
||||
background: rgba(5, 7, 12, 0.55);
|
||||
backdrop-filter: blur(30px);
|
||||
-webkit-backdrop-filter: blur(30px);
|
||||
border-right: 1px solid var(--glass-border);
|
||||
|
|
|
|||