create-tauri-ui 1.0.3 → 1.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,32 +1,33 @@
1
- import s from"node:fs";import a from"node:path";import S from"node:process";import{text as _,confirm as P,select as we,multiselect as ve,isCancel as xe,cancel as W,log as h,intro as ye,spinner as be,outro as ke,note as K}from"@clack/prompts";import A from"picocolors";import z from"node:os";import{execFile as $e}from"node:child_process";import{fileURLToPath as I}from"node:url";const D=new Set;let Y=!1,X=!1;class L extends Error{constructor(t,r,n,i){super(t),this.stdout=r,this.stderr=n,this.code=i}}class w extends Error{constructor(t,r,n){super(r),this.tool=t,this.stderr=n}}class u extends Error{constructor(t,r){super(r),this.file=t}}function Ee(e){return e?.trim().replace(/\/+$/g,"")}function q(e,t){s.statSync(e).isDirectory()?Z(e,t):(s.mkdirSync(a.dirname(t),{recursive:!0}),s.copyFileSync(e,t))}function R(e){return/^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(e)}function J(e){return e.trim().toLowerCase().replace(/\s+/g,"-").replace(/^[._]/,"").replace(/[^a-z\d\-~]+/g,"-")}function Z(e,t){s.mkdirSync(t,{recursive:!0});for(const r of s.readdirSync(e)){const n=a.resolve(e,r),i=a.resolve(t,r);q(n,i)}}function je(e){const t=s.readdirSync(e);return t.length===0||t.length===1&&t[0]===".git"}function l(e,t){const r=s.readFileSync(e,"utf-8");s.writeFileSync(e,t(r),"utf-8")}function m(e,t){const r=JSON.parse(s.readFileSync(e,"utf-8")),n=t(r);s.writeFileSync(e,JSON.stringify(n,null,2)+`
2
- `)}async function C(e,t,r){return await new Promise((n,i)=>{$e(e,t,{cwd:r?.cwd,env:{...process.env,...r?.env},maxBuffer:1024*1024*10},(o,c,N)=>{if(o){i(new L(`Command failed: ${e} ${t.join(" ")}`,c,N,typeof o.code=="number"?o.code:null));return}n(c.trim())})})}function Q(e){return s.mkdtempSync(a.join(z.tmpdir(),e))}function O(e){D.add(e)}function f(e){D.delete(e)}function g(e){s.existsSync(e)&&s.rmSync(e,{recursive:!0,force:!0})}function Se(){const e=[...D].sort((t,r)=>r.length-t.length);for(const t of e)try{g(t)}catch{}finally{D.delete(t)}}function _e(){if(Y)return;Y=!0;const e=(t,r)=>{X&&process.exit(r),X=!0,Se(),process.exit(r)};process.once("SIGINT",()=>e("SIGINT",130)),process.once("SIGTERM",()=>e("SIGTERM",143))}function Pe(e){return e.replace(/^@[^/]+\//,"").replace(/[^a-zA-Z0-9]+/g,"_").replace(/^_+|_+$/g,"")}const De={name:"astro",async apply(e,t){l(a.join(e,"astro.config.mjs"),r=>{if(r.includes("server: {"))return r;const n=r.lastIndexOf(`
1
+ import s from"node:fs";import i from"node:path";import _ from"node:process";import{text as P,confirm as D,select as xe,multiselect as be,isCancel as ye,cancel as K,log as w,intro as ke,spinner as $e,outro as Ee,note as z}from"@clack/prompts";import A from"picocolors";import Y from"node:os";import{execFile as je}from"node:child_process";import{fileURLToPath as R}from"node:url";const L=new Set;let X=!1,q=!1;class C extends Error{constructor(t,r,n,a){super(t),this.stdout=r,this.stderr=n,this.code=a}}class v extends Error{constructor(t,r,n){super(r),this.tool=t,this.stderr=n}}class u extends Error{constructor(t,r){super(r),this.file=t}}function Se(e){return e?.trim().replace(/\/+$/g,"")}function J(e,t){s.statSync(e).isDirectory()?Q(e,t):(s.mkdirSync(i.dirname(t),{recursive:!0}),s.copyFileSync(e,t))}function O(e){return/^(?:@[a-z\d\-*~][a-z\d\-*._~]*\/)?[a-z\d\-~][a-z\d\-._~]*$/.test(e)}function Z(e){return e.trim().toLowerCase().replace(/\s+/g,"-").replace(/^[._]/,"").replace(/[^a-z\d\-~]+/g,"-")}function Q(e,t){s.mkdirSync(t,{recursive:!0});for(const r of s.readdirSync(e)){const n=i.resolve(e,r),a=i.resolve(t,r);J(n,a)}}function _e(e){const t=s.readdirSync(e);return t.length===0||t.length===1&&t[0]===".git"}function c(e,t){const r=s.readFileSync(e,"utf-8").replace(/\r\n/g,`
2
+ `);s.writeFileSync(e,t(r),"utf-8")}function f(e,t){const r=JSON.parse(s.readFileSync(e,"utf-8")),n=t(r);s.writeFileSync(e,JSON.stringify(n,null,2)+`
3
+ `)}async function T(e,t,r){return await new Promise((n,a)=>{je(e,t,{cwd:r?.cwd,env:{...process.env,...r?.env},maxBuffer:1024*1024*10},(o,l,I)=>{if(o){a(new C(`Command failed: ${e} ${t.join(" ")}`,l,I,typeof o.code=="number"?o.code:null));return}n(l.trim())})})}function ee(e){return s.mkdtempSync(i.join(Y.tmpdir(),e))}function F(e){L.add(e)}function g(e){L.delete(e)}function h(e){s.existsSync(e)&&s.rmSync(e,{recursive:!0,force:!0})}function Pe(){const e=[...L].sort((t,r)=>r.length-t.length);for(const t of e)try{h(t)}catch{}finally{L.delete(t)}}function De(){if(X)return;X=!0;const e=(t,r)=>{q&&process.exit(r),q=!0,Pe(),process.exit(r)};process.once("SIGINT",()=>e("SIGINT",130)),process.once("SIGTERM",()=>e("SIGTERM",143))}function Le(e){return e.replace(/^@[^/]+\//,"").replace(/[^a-zA-Z0-9]+/g,"_").replace(/^_+|_+$/g,"")}const Ce={name:"astro",async apply(e,t){c(i.join(e,"astro.config.mjs"),r=>{if(r.includes("server: {"))return r;const n=r.lastIndexOf(`
3
4
  })`);if(n===-1)throw new u("astro.config.mjs","Could not find the Astro config closing brace.");return`${r.slice(0,n)}
4
5
  server: {
5
6
  port: 1420,
6
- },${r.slice(n)}`})},tauriConfig(){return{frontendDist:"../dist",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}},Le={name:"next",async apply(e,t){l(a.join(e,"next.config.mjs"),r=>{if(r.includes('output: "export"'))return r;if(!r.includes("const nextConfig = {}"))throw new u("next.config.mjs","Could not find the default Next.js config shape.");return r.replace("const nextConfig = {}",`const nextConfig = {
7
+ },${r.slice(n)}`})},tauriConfig(){return{frontendDist:"../dist",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}},Te={name:"next",async apply(e,t){c(i.join(e,"next.config.mjs"),r=>{if(r.includes('output: "export"'))return r;if(!r.includes("const nextConfig = {}"))throw new u("next.config.mjs","Could not find the default Next.js config shape.");return r.replace("const nextConfig = {}",`const nextConfig = {
7
8
  output: "export",
8
9
  images: {
9
10
  unoptimized: true,
10
11
  },
11
- }`)}),m(a.join(e,"package.json"),r=>(r.scripts?.dev&&(r.scripts.dev=r.scripts.dev.replace("next dev --turbopack","next dev --turbopack -p 1420")),r))},tauriConfig(){return{frontendDist:"../out",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}};function Ce(e){if(e.includes("strictPort: true"))return e;const t=e.lastIndexOf(`
12
+ }`)}),f(i.join(e,"package.json"),r=>(r.scripts?.dev&&(r.scripts.dev=r.scripts.dev.replace("next dev --turbopack","next dev --turbopack -p 1420")),r))},tauriConfig(){return{frontendDist:"../out",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}};function Ge(e){if(e.includes("strictPort: true"))return e;const t=e.lastIndexOf(`
12
13
  })`);if(t===-1)throw new u("vite.config.ts","Could not find the React Router Vite config closing brace.");return`${e.slice(0,t)}
13
14
  server: {
14
15
  port: 1420,
15
16
  strictPort: true,
16
- },${e.slice(t)}`}const Te={name:"react-router",async apply(e,t){l(a.join(e,"react-router.config.ts"),r=>{if(r.includes("ssr: false"))return r;if(!r.includes("ssr: true"))throw new u("react-router.config.ts","Could not find the SSR flag in the generated React Router config.");return r.replace("ssr: true","ssr: false")}),l(a.join(e,"vite.config.ts"),Ce)},tauriConfig(){return{frontendDist:"../build/client",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}};function Ge(e){if(e.includes("strictPort: true"))return e;const t=e.lastIndexOf(`
17
+ },${e.slice(t)}`}const Ne={name:"react-router",async apply(e,t){c(i.join(e,"react-router.config.ts"),r=>{if(r.includes("ssr: false"))return r;if(!r.includes("ssr: true"))throw new u("react-router.config.ts","Could not find the SSR flag in the generated React Router config.");return r.replace("ssr: true","ssr: false")}),c(i.join(e,"vite.config.ts"),Ge)},tauriConfig(){return{frontendDist:"../build/client",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}};function Ie(e){if(e.includes("strictPort: true"))return e;const t=e.lastIndexOf(`
17
18
  })`);if(t===-1)throw new u("vite.config.ts","Could not find the TanStack Start config closing brace.");return`${e.slice(0,t)}
18
19
  server: {
19
20
  port: 1420,
20
21
  strictPort: true,
21
- },${e.slice(t)}`}const Ne={name:"start",async apply(e,t){l(a.join(e,"vite.config.ts"),r=>{let n=Ge(r);if(!n.includes("tanstackStart({ spa: { enabled: true } })")){if(!n.includes("tanstackStart(),"))throw new u("vite.config.ts","Could not find tanstackStart() in the generated Vite config.");n=n.replace("tanstackStart(),","tanstackStart({ spa: { enabled: true } }),")}return n}),m(a.join(e,"package.json"),r=>(r.scripts?.dev&&(r.scripts.dev=r.scripts.dev.replace("--port 3000","--port 1420")),r))},tauriConfig(){return{frontendDist:"../.output/public",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}};function Ae(e){if(e.includes("strictPort: true"))return e;const t=e.lastIndexOf(`
22
+ },${e.slice(t)}`}const Ae={name:"start",async apply(e,t){c(i.join(e,"vite.config.ts"),r=>{let n=Ie(r);if(!n.includes("tanstackStart({ spa: { enabled: true } })")){if(!n.includes("tanstackStart(),"))throw new u("vite.config.ts","Could not find tanstackStart() in the generated Vite config.");n=n.replace("tanstackStart(),","tanstackStart({ spa: { enabled: true } }),")}return n}),f(i.join(e,"package.json"),r=>(r.scripts?.dev&&(r.scripts.dev=r.scripts.dev.replace("--port 3000","--port 1420")),r))},tauriConfig(){return{frontendDist:"../.output/public",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}};function Re(e){if(e.includes("strictPort: true"))return e;const t=e.lastIndexOf(`
22
23
  })`);if(t===-1)throw new u("vite.config.ts","Could not find the Vite config closing brace.");return`${e.slice(0,t)}
23
24
  server: {
24
25
  port: 1420,
25
26
  strictPort: true,
26
- },${e.slice(t)}`}const Ie={name:"vite",async apply(e,t){l(a.join(e,"vite.config.ts"),Ae)},tauriConfig(){return{frontendDist:"../dist",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}},Re={vite:Ie,next:Le,start:Ne,"react-router":Te,astro:De};function Oe(e){return Re[e]}async function ee(e,t){try{await C("bunx",["--bun","shadcn@latest",...t],{cwd:e})}catch(r){throw r instanceof L?new w("shadcn","shadcn CLI failed while updating the frontend scaffold.",r.stderr||r.stdout):r}}const Fe="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'%3E%3Crect width='96' height='96' rx='24' fill='%23181f2a'/%3E%3Ccircle cx='48' cy='34' r='18' fill='%23f8fafc'/%3E%3Cpath d='M18 82c6-14 18-22 30-22s24 8 30 22' fill='%23f8fafc'/%3E%3C/svg%3E";function Ue(e){const t=a.join(e,"app/layout.tsx");s.existsSync(t)&&l(t,r=>{let n=r;if(n.includes('import { TooltipProvider } from "@/components/ui/tooltip"')||(n=n.replace(`import { ThemeProvider } from "@/components/theme-provider"
27
+ },${e.slice(t)}`}const Oe={name:"vite",async apply(e,t){c(i.join(e,"vite.config.ts"),Re)},tauriConfig(){return{frontendDist:"../dist",devUrl:"http://localhost:1420",beforeDevCommand:"bun run dev",beforeBuildCommand:"bun run build"}}},Fe={vite:Oe,next:Te,start:Ae,"react-router":Ne,astro:Ce};function Ue(e){return Fe[e]}async function te(e,t){try{await T("bunx",["--bun","shadcn@latest",...t],{cwd:e})}catch(r){throw r instanceof C?new v("shadcn","shadcn CLI failed while updating the frontend scaffold.",r.stderr||r.stdout):r}}const Ve="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'%3E%3Crect width='96' height='96' rx='24' fill='%23181f2a'/%3E%3Ccircle cx='48' cy='34' r='18' fill='%23f8fafc'/%3E%3Cpath d='M18 82c6-14 18-22 30-22s24 8 30 22' fill='%23f8fafc'/%3E%3C/svg%3E";function Be(e){const t=i.join(e,"app/layout.tsx");s.existsSync(t)&&c(t,r=>{let n=r;if(n.includes('import { TooltipProvider } from "@/components/ui/tooltip"')||(n=n.replace(`import { ThemeProvider } from "@/components/theme-provider"
27
28
  `,`import { ThemeProvider } from "@/components/theme-provider"
28
29
  import { TooltipProvider } from "@/components/ui/tooltip"
29
- `)),n.includes("<TooltipProvider>"))return n;const i=n.replace(/<ThemeProvider>([\s\S]*?)<\/ThemeProvider>/,"<ThemeProvider><TooltipProvider>$1</TooltipProvider></ThemeProvider>");if(i===n)throw new u(t,"Could not wrap the Next.js layout with TooltipProvider.");return i})}function Ve(e,t){const r=t.template==="next"?a.join(e,"components/app-sidebar.tsx"):t.template==="react-router"?a.join(e,"app/components/app-sidebar.tsx"):a.join(e,"src/components/app-sidebar.tsx");s.existsSync(r)&&l(r,n=>n.replace('avatar: "/avatars/shadcn.jpg"',`avatar: "${Fe}"`))}function v(e,t,r,n){return`import type { CSSProperties } from "react"
30
+ `)),n.includes("<TooltipProvider>"))return n;const a=n.replace(/<ThemeProvider>([\s\S]*?)<\/ThemeProvider>/,"<ThemeProvider><TooltipProvider>$1</TooltipProvider></ThemeProvider>");if(a===n)throw new u(t,"Could not wrap the Next.js layout with TooltipProvider.");return a})}function Me(e,t){const r=t.template==="next"?i.join(e,"components/app-sidebar.tsx"):t.template==="react-router"?i.join(e,"app/components/app-sidebar.tsx"):i.join(e,"src/components/app-sidebar.tsx");s.existsSync(r)&&c(r,n=>n.replace('avatar: "/avatars/shadcn.jpg"',`avatar: "${Ve}"`))}function x(e,t,r,n){return`import type { CSSProperties } from "react"
30
31
  import { AppSidebar } from "${t}components/app-sidebar"
31
32
  import { ChartAreaInteractive } from "${t}components/chart-area-interactive"
32
33
  import { DataTable } from "${t}components/data-table"
@@ -73,11 +74,11 @@ ${n?` <div className="px-4 lg:px-6">
73
74
  </TooltipProvider>
74
75
  )
75
76
  }
76
- `}function Be(e){return`import { createFileRoute } from "@tanstack/react-router"
77
- ${v("DashboardPage","@/","@/app/dashboard/data.json",e)}export const Route = createFileRoute("/")({
77
+ `}function He(e){return`import { createFileRoute } from "@tanstack/react-router"
78
+ ${x("DashboardPage","@/","@/app/dashboard/data.json",e)}export const Route = createFileRoute("/")({
78
79
  component: DashboardPage,
79
80
  })
80
- `}function Me(e){return v("DashboardShell","@/","@/app/dashboard/data.json",e).replace("export default function DashboardShell()","export function DashboardShell()")}function He(e,t){try{s.renameSync(e,t);return}catch(r){if(!(r instanceof Error)||!("code"in r)||r.code!=="EXDEV")throw r}s.cpSync(e,t,{recursive:!0,force:!0}),s.rmSync(e,{recursive:!0,force:!0})}async function We(e){s.mkdirSync(a.dirname(e.targetDir),{recursive:!0});const t=Q("create-tauri-ui-frontend-"),r=a.join(t,e.projectName);O(t);try{if(await C("bunx",["--bun","shadcn@latest","init","--name",e.projectName,"--template",e.template,"--preset",e.preset,"--yes"],{cwd:t}),!s.existsSync(r))throw new Error("shadcn CLI did not produce the expected project directory.");s.rmSync(a.join(r,"node_modules"),{recursive:!0,force:!0}),He(r,e.targetDir)}catch(n){if(n instanceof L){f(t);try{g(t)}catch{}throw new w("shadcn","shadcn CLI failed while creating the frontend scaffold.",n.stderr||n.stdout)}f(t);try{g(t)}catch{}throw n}finally{f(t);try{g(t)}catch{}}return e.targetDir}async function Ke(e){const t=Q("create-tauri-ui-"),r="tauri-native";O(t);try{await C("bunx",["create-tauri-app",r,"--template","vanilla-ts","--manager","bun","--identifier",e.identifier,"--yes"],{cwd:t})}catch(n){if(n instanceof L){f(t);try{g(t)}catch{}throw new w("cta","create-tauri-app failed while creating the native scaffold.",n.stderr||n.stdout)}f(t);try{g(t)}catch{}throw n}return{tempDir:t,projectDir:a.join(t,r)}}async function ze(e,t){await ee(e,["add","dashboard-01","--yes"]),Ve(e,t);const r=t.template==="next"?a.join(e,"components/site-header.tsx"):t.template==="react-router"?a.join(e,"app/components/site-header.tsx"):a.join(e,"src/components/site-header.tsx");switch(s.existsSync(r)&&l(r,n=>n.includes("<Button")?n:n.replace(/import \{ Button \} from ["'][@~]\/components\/ui\/button["']\n/,"")),t.template){case"next":Ue(e),s.writeFileSync(a.join(e,"app/page.tsx"),v("Page","@/","@/app/dashboard/data.json",t.includeInvokeExample));return;case"vite":s.writeFileSync(a.join(e,"src/App.tsx"),v("App","@/","@/app/dashboard/data.json",t.includeInvokeExample));return;case"start":s.writeFileSync(a.join(e,"src/routes/index.tsx"),Be(t.includeInvokeExample));return;case"react-router":s.writeFileSync(a.join(e,"app/routes/home.tsx"),v("Home","~/","~/dashboard/data.json",t.includeInvokeExample));return;case"astro":s.writeFileSync(a.join(e,"src/components/dashboard-shell.tsx"),Me(t.includeInvokeExample)),s.writeFileSync(a.join(e,"src/pages/index.astro"),`---
81
+ `}function We(e){return x("DashboardShell","@/","@/app/dashboard/data.json",e).replace("export default function DashboardShell()","export function DashboardShell()")}function Ke(e,t){try{s.renameSync(e,t);return}catch(r){if(!(r instanceof Error)||!("code"in r)||r.code!=="EXDEV")throw r}s.cpSync(e,t,{recursive:!0,force:!0}),s.rmSync(e,{recursive:!0,force:!0})}async function ze(e){s.mkdirSync(i.dirname(e.targetDir),{recursive:!0});const t=ee("create-tauri-ui-frontend-"),r=i.join(t,e.projectName);F(t);try{if(await T("bunx",["--bun","shadcn@latest","init","--name",e.projectName,"--template",e.template,"--preset",e.preset,"--yes"],{cwd:t}),!s.existsSync(r))throw new Error("shadcn CLI did not produce the expected project directory.");s.rmSync(i.join(r,"node_modules"),{recursive:!0,force:!0}),Ke(r,e.targetDir)}catch(n){if(n instanceof C){g(t);try{h(t)}catch{}throw new v("shadcn","shadcn CLI failed while creating the frontend scaffold.",n.stderr||n.stdout)}g(t);try{h(t)}catch{}throw n}finally{g(t);try{h(t)}catch{}}return e.targetDir}async function Ye(e){const t=ee("create-tauri-ui-"),r="tauri-native";F(t);try{await T("bunx",["create-tauri-app",r,"--template","vanilla-ts","--manager","bun","--identifier",e.identifier,"--yes"],{cwd:t})}catch(n){if(n instanceof C){g(t);try{h(t)}catch{}throw new v("cta","create-tauri-app failed while creating the native scaffold.",n.stderr||n.stdout)}g(t);try{h(t)}catch{}throw n}return{tempDir:t,projectDir:i.join(t,r)}}async function Xe(e,t){await te(e,["add","dashboard-01","--yes"]),Me(e,t);const r=t.template==="next"?i.join(e,"components/site-header.tsx"):t.template==="react-router"?i.join(e,"app/components/site-header.tsx"):i.join(e,"src/components/site-header.tsx");switch(s.existsSync(r)&&c(r,n=>n.includes("<Button")?n:n.replace(/import \{ Button \} from ["'][@~]\/components\/ui\/button["']\n/,"")),t.template){case"next":Be(e),s.writeFileSync(i.join(e,"app/page.tsx"),x("Page","@/","@/app/dashboard/data.json",t.includeInvokeExample));return;case"vite":s.writeFileSync(i.join(e,"src/App.tsx"),x("App","@/","@/app/dashboard/data.json",t.includeInvokeExample));return;case"start":s.writeFileSync(i.join(e,"src/routes/index.tsx"),He(t.includeInvokeExample));return;case"react-router":s.writeFileSync(i.join(e,"app/routes/home.tsx"),x("Home","~/","~/dashboard/data.json",t.includeInvokeExample));return;case"astro":s.writeFileSync(i.join(e,"src/components/dashboard-shell.tsx"),We(t.includeInvokeExample)),s.writeFileSync(i.join(e,"src/pages/index.astro"),`---
81
82
  import Layout from "@/layouts/main.astro"
82
83
  import { DashboardShell } from "@/components/dashboard-shell"
83
84
  ---
@@ -85,10 +86,10 @@ import { DashboardShell } from "@/components/dashboard-shell"
85
86
  <Layout>
86
87
  <DashboardShell client:load />
87
88
  </Layout>
88
- `);return;default:throw new u(e,`No starter UI implementation exists for template "${t.template}".`)}}async function te(e,t){await ee(e,["add",t,"--yes"])}const T="use tauri_plugin_log::{Target, TargetKind};",re=` log::info!("greet command executed for {}", name);
89
- `,ne=` log::info!("opening external link in system browser: {}", url);
89
+ `);return;default:throw new u(e,`No starter UI implementation exists for template "${t.template}".`)}}async function re(e,t){await te(e,["add",t,"--yes"])}const G="use tauri_plugin_log::{Target, TargetKind};",ne=` log::info!("greet command executed for {}", name);
90
+ `,ae=` log::info!("opening external link in system browser: {}", url);
90
91
  `,ie=` log::info!("main webview finished loading");
91
- `,Ye=` .plugin(
92
+ `,qe=` .plugin(
92
93
  tauri_plugin_log::Builder::new()
93
94
  .targets([
94
95
  Target::new(TargetKind::Stdout),
@@ -97,35 +98,33 @@ import { DashboardShell } from "@/components/dashboard-shell"
97
98
  ])
98
99
  .build(),
99
100
  )
100
- `;function Xe(){const e=a.dirname(I(import.meta.url)),t=[a.resolve(e,"../assets/debug-panel"),a.resolve(e,"../../assets/debug-panel")];return t.find(r=>s.existsSync(r))??t[0]}const qe=Xe();function Je(e){return e==="react-router"?"~/":"@/"}function ae(e,t){switch(t.template){case"next":return a.join(e,"components");case"vite":case"start":case"astro":return a.join(e,"src/components");case"react-router":return a.join(e,"app/components")}}function Ze(e,t){switch(t.template){case"next":return a.join(e,"lib");case"vite":case"start":case"astro":return a.join(e,"src/lib");case"react-router":return a.join(e,"app/lib")}}function Qe(e,t){return a.join(ae(e,t),"ui")}function x(e){switch(e.template){case"next":return"@/components/debug-panel";case"vite":return"./components/debug-panel.tsx";case"start":return"../components/debug-panel";case"react-router":return"./components/debug-panel";case"astro":return"@/components/debug-panel"}}async function et(e,t){for(const r of["button","badge","sheet","tabs","toggle-group"]){const n=a.join(Qe(e,t),`${r}.tsx`);s.existsSync(n)||await te(e,r)}}function F(e){return s.readFileSync(a.join(qe,e),"utf-8")}function tt(e,t){const r=a.join(ae(e,t),"debug-panel.tsx"),n=Ze(e,t);s.mkdirSync(a.dirname(r),{recursive:!0}),s.mkdirSync(n,{recursive:!0}),s.writeFileSync(r,F("debug-panel.tsx.tmpl").split("__ALIAS_PREFIX__").join(Je(t.template)),"utf-8"),s.writeFileSync(a.join(n,"debug-events.ts"),F("debug-events.ts.tmpl"),"utf-8"),s.writeFileSync(a.join(n,"tauri.ts"),F("tauri.ts.tmpl"),"utf-8")}function rt(e){m(a.join(e,"package.json"),t=>(t.dependencies=t.dependencies||{},t.dependencies["@tauri-apps/plugin-log"]||(t.dependencies["@tauri-apps/plugin-log"]="^2"),t))}function oe(e,t){if(e.includes(t))return e;if(!e.includes(`[dependencies]
101
- `))throw new Error(`Could not find [dependencies] while inserting ${t}.`);return e.replace(`[dependencies]
102
- `,`[dependencies]
101
+ `;function Je(){const e=i.dirname(R(import.meta.url)),t=[i.resolve(e,"../assets/debug-panel"),i.resolve(e,"../../assets/debug-panel")];return t.find(r=>s.existsSync(r))??t[0]}const Ze=Je();function Qe(e){return e==="react-router"?"~/":"@/"}function oe(e,t){switch(t.template){case"next":return i.join(e,"components");case"vite":case"start":case"astro":return i.join(e,"src/components");case"react-router":return i.join(e,"app/components")}}function et(e,t){switch(t.template){case"next":return i.join(e,"lib");case"vite":case"start":case"astro":return i.join(e,"src/lib");case"react-router":return i.join(e,"app/lib")}}function tt(e,t){return i.join(oe(e,t),"ui")}function b(e){switch(e.template){case"next":return"@/components/debug-panel";case"vite":return"./components/debug-panel.tsx";case"start":return"../components/debug-panel";case"react-router":return"./components/debug-panel";case"astro":return"@/components/debug-panel"}}async function rt(e,t){for(const r of["button","badge","dropdown-menu","tabs"]){const n=i.join(tt(e,t),`${r}.tsx`);s.existsSync(n)||await re(e,r)}}function U(e){return s.readFileSync(i.join(Ze,e),"utf-8")}function nt(e,t){const r=i.join(oe(e,t),"debug-panel.tsx"),n=et(e,t);s.mkdirSync(i.dirname(r),{recursive:!0}),s.mkdirSync(n,{recursive:!0}),s.writeFileSync(r,U("debug-panel.tsx.tmpl").split("__ALIAS_PREFIX__").join(Qe(t.template)),"utf-8"),s.writeFileSync(i.join(n,"debug-events.ts"),U("debug-events.ts.tmpl"),"utf-8"),s.writeFileSync(i.join(n,"tauri.ts"),U("tauri.ts.tmpl"),"utf-8")}function at(e){f(i.join(e,"package.json"),t=>(t.dependencies=t.dependencies||{},t.dependencies["@tauri-apps/plugin-log"]||(t.dependencies["@tauri-apps/plugin-log"]="^2"),t))}function se(e,t){if(e.includes(t))return e;const r=/\[dependencies\]\r?\n/;if(!r.test(e))throw new Error(`Could not find [dependencies] while inserting ${t}.`);return e.replace(r,`[dependencies]
103
102
  ${t}
104
- `)}function nt(e){const t=a.join(e,"src-tauri/Cargo.toml"),r=a.join(e,"src-tauri/src/lib.rs");l(t,n=>{let i=n;return i=oe(i,'tauri-plugin-log = "2"'),i=oe(i,'log = "0.4"'),i}),m(a.join(e,"src-tauri/capabilities/default.json"),n=>(n.permissions=Array.isArray(n.permissions)?n.permissions:[],n.permissions.includes("log:default")||n.permissions.push("log:default"),n)),l(r,n=>{let i=n;if(i.includes(T)||(i.includes(`use tauri_plugin_opener::OpenerExt;
105
- `)?i=i.replace(`use tauri_plugin_opener::OpenerExt;
103
+ `)}function it(e){const t=i.join(e,"src-tauri/Cargo.toml"),r=i.join(e,"src-tauri/src/lib.rs");c(t,n=>{let a=n;return a=se(a,'tauri-plugin-log = "2"'),a=se(a,'log = "0.4"'),a}),f(i.join(e,"src-tauri/capabilities/default.json"),n=>(n.permissions=Array.isArray(n.permissions)?n.permissions:[],n.permissions.includes("log:default")||n.permissions.push("log:default"),n)),c(r,n=>{let a=n;if(a.includes(G)||(a.includes(`use tauri_plugin_opener::OpenerExt;
104
+ `)?a=a.replace(`use tauri_plugin_opener::OpenerExt;
106
105
  `,`use tauri_plugin_opener::OpenerExt;
107
- ${T}
108
- `):i.includes(`use tauri::webview::PageLoadEvent;
109
- `)?i=i.replace(`use tauri::webview::PageLoadEvent;
106
+ ${G}
107
+ `):a.includes(`use tauri::webview::PageLoadEvent;
108
+ `)?a=a.replace(`use tauri::webview::PageLoadEvent;
110
109
  `,`use tauri::webview::PageLoadEvent;
111
- ${T}
112
- `):i=`${T}
113
- ${i}`),i.includes("tauri_plugin_log::Builder::new()"))return i;const o=i.replace(` tauri::Builder::default()
110
+ ${G}
111
+ `):a=`${G}
112
+ ${a}`),a.includes("tauri_plugin_log::Builder::new()"))return a;const o=a.replace(` tauri::Builder::default()
114
113
  `,` tauri::Builder::default()
115
- ${Ye}`);if(o===i)throw new u(r,"Could not register the Tauri log plugin.");return i=o,!i.includes(re.trim())&&i.includes(` let message = format!("Hello, {}! You've been greeted from Rust!", name);
116
- `)&&(i=i.replace(` let message = format!("Hello, {}! You've been greeted from Rust!", name);
114
+ ${qe}`);if(o===a)throw new u(r,"Could not register the Tauri log plugin.");return a=o,!a.includes(ne.trim())&&a.includes(` let message = format!("Hello, {}! You've been greeted from Rust!", name);
115
+ `)&&(a=a.replace(` let message = format!("Hello, {}! You've been greeted from Rust!", name);
117
116
  `,` let message = format!("Hello, {}! You've been greeted from Rust!", name);
118
- ${re}`)),!i.includes(ne.trim())&&i.includes(` let _ = webview.opener().open_url(url.as_str(), None::<&str>);
119
- `)&&(i=i.replace(` let _ = webview.opener().open_url(url.as_str(), None::<&str>);
120
- `,`${ne} let _ = webview.opener().open_url(url.as_str(), None::<&str>);
121
- `)),!i.includes(ie.trim())&&i.includes(` let _ = webview.window().show();
122
- `)&&(i=i.replace(` let _ = webview.window().show();
117
+ ${ne}`)),!a.includes(ae.trim())&&a.includes(` let _ = webview.opener().open_url(url.as_str(), None::<&str>);
118
+ `)&&(a=a.replace(` let _ = webview.opener().open_url(url.as_str(), None::<&str>);
119
+ `,`${ae} let _ = webview.opener().open_url(url.as_str(), None::<&str>);
120
+ `)),!a.includes(ie.trim())&&a.includes(` let _ = webview.window().show();
121
+ `)&&(a=a.replace(` let _ = webview.window().show();
123
122
  `,`${ie} let _ = webview.window().show();
124
- `)),i})}function it(e,t){const r=a.join(e,"src/main.tsx"),n=x(t);l(r,i=>{let o=i;if(o.includes(`import { DebugPanel } from "${n}"`)||(o=o.replace(/import { ExternalLinkGuard } from "\.\/components\/external-link-guard\.tsx"\r?\n/,`import { ExternalLinkGuard } from "./components/external-link-guard.tsx"
123
+ `)),a})}function ot(e,t){const r=i.join(e,"src/main.tsx"),n=b(t);c(r,a=>{let o=a;if(o.includes(`import { DebugPanel } from "${n}"`)||(o=o.replace(/import { ExternalLinkGuard } from "\.\/components\/external-link-guard\.tsx"\r?\n/,`import { ExternalLinkGuard } from "./components/external-link-guard.tsx"
125
124
  import { DebugPanel } from "${n}"
126
- `)),o.includes("<DebugPanel />"))return o;const c=o.replace(/<ExternalLinkGuard \/>\r?\n(\s*)<main><App \/><\/main>/,`<ExternalLinkGuard />
125
+ `)),o.includes("<DebugPanel />"))return o;const l=o.replace(/<ExternalLinkGuard \/>\r?\n(\s*)<main(?:\s+data-ui-scroll-container)?><App \/><\/main>/,`<ExternalLinkGuard />
127
126
  $1{import.meta.env.DEV ? <DebugPanel /> : null}
128
- $1<main><App /></main>`);if(c===o)throw new u(r,"Could not mount DebugPanel in the Vite entrypoint.");return c})}function at(e,t){const r=a.join(e,"app/layout.tsx"),n=x(t);l(r,i=>{let o=i;if(o.includes(`import { DebugPanel } from "${n}"`)||(o.includes(`import { ExternalLinkGuard } from "@/components/external-link-guard"
127
+ $1<main data-ui-scroll-container><App /></main>`);if(l===o)throw new u(r,"Could not mount DebugPanel in the Vite entrypoint.");return l})}function st(e,t){const r=i.join(e,"app/layout.tsx"),n=b(t);c(r,a=>{let o=a;if(o.includes(`import { DebugPanel } from "${n}"`)||(o.includes(`import { ExternalLinkGuard } from "@/components/external-link-guard"
129
128
  `)?o=o.replace(`import { ExternalLinkGuard } from "@/components/external-link-guard"
130
129
  `,`import { ExternalLinkGuard } from "@/components/external-link-guard"
131
130
  import { DebugPanel } from "${n}"
@@ -133,19 +132,19 @@ import { DebugPanel } from "${n}"
133
132
  `)&&(o=o.replace(`import { ThemeProvider } from "@/components/theme-provider"
134
133
  `,`import { ThemeProvider } from "@/components/theme-provider"
135
134
  import { DebugPanel } from "${n}"
136
- `))),o.includes("<DebugPanel />"))return o;const c=o.replace("<ExternalLinkGuard />{children}",'<ExternalLinkGuard />{process.env.NODE_ENV === "development" ? <DebugPanel /> : null}{children}');if(c===o)throw new u(r,"Could not mount DebugPanel in the Next.js layout.");return c})}function ot(e,t){const r=a.join(e,"src/routes/__root.tsx"),n=x(t);l(r,i=>{let o=i;if(o.includes(`import { DebugPanel } from "${n}"`)||(o=o.replace(`import { ExternalLinkGuard } from "../components/external-link-guard"
135
+ `))),o.includes("<DebugPanel />"))return o;const l=o.replace(/<ExternalLinkGuard \/>\{children\}/,'<ExternalLinkGuard />{process.env.NODE_ENV === "development" ? <DebugPanel /> : null}{children}');if(l===o)throw new u(r,"Could not mount DebugPanel in the Next.js layout.");return l})}function lt(e,t){const r=i.join(e,"src/routes/__root.tsx"),n=b(t);c(r,a=>{let o=a;if(o.includes(`import { DebugPanel } from "${n}"`)||(o=o.replace(`import { ExternalLinkGuard } from "../components/external-link-guard"
137
136
  `,`import { ExternalLinkGuard } from "../components/external-link-guard"
138
137
  import { DebugPanel } from "${n}"
139
- `)),o.includes("<DebugPanel />"))return o;const c=o.replace("<main><ExternalLinkGuard />{children}</main>","<main><ExternalLinkGuard />{import.meta.env.DEV ? <DebugPanel /> : null}{children}</main>");if(c===o)throw new u(r,"Could not mount DebugPanel in the TanStack Start root route.");return c})}function st(e,t){const r=a.join(e,"app/root.tsx"),n=x(t);l(r,i=>{let o=i;if(o.includes(`import { DebugPanel } from "${n}"`)||(o=o.replace(`import { ExternalLinkGuard } from "./components/external-link-guard"
138
+ `)),o.includes("<DebugPanel />"))return o;const l=o.replace(/<main(?:\s+data-ui-scroll-container)?><ExternalLinkGuard \/>\{children\}<\/main>/,"<main data-ui-scroll-container><ExternalLinkGuard />{import.meta.env.DEV ? <DebugPanel /> : null}{children}</main>");if(l===o)throw new u(r,"Could not mount DebugPanel in the TanStack Start root route.");return l})}function ct(e,t){const r=i.join(e,"app/root.tsx"),n=b(t);c(r,a=>{let o=a;if(o.includes(`import { DebugPanel } from "${n}"`)||(o=o.replace(`import { ExternalLinkGuard } from "./components/external-link-guard"
140
139
  `,`import { ExternalLinkGuard } from "./components/external-link-guard"
141
140
  import { DebugPanel } from "${n}"
142
- `)),o.includes("<DebugPanel />"))return o;const c=o.replace(`<ExternalLinkGuard />
141
+ `)),o.includes("<DebugPanel />"))return o;const l=o.replace(`<ExternalLinkGuard />
143
142
  {children}`,`<ExternalLinkGuard />
144
143
  {import.meta.env.DEV ? <DebugPanel /> : null}
145
- {children}`);if(c===o)throw new u(r,"Could not mount DebugPanel in the React Router root layout.");return c})}function ct(e,t){const r=a.join(e,"src/layouts/main.astro"),n=x(t);l(r,i=>{let o=i;if(o.includes(`import { DebugPanel } from "${n}"`)||(o=o.replace(`import { ExternalLinkGuard } from "@/components/external-link-guard"
144
+ {children}`);if(l===o)throw new u(r,"Could not mount DebugPanel in the React Router root layout.");return l})}function ut(e,t){const r=i.join(e,"src/layouts/main.astro"),n=b(t);c(r,a=>{let o=a;if(o.includes(`import { DebugPanel } from "${n}"`)||(o=o.replace(`import { ExternalLinkGuard } from "@/components/external-link-guard"
146
145
  `,`import { ExternalLinkGuard } from "@/components/external-link-guard"
147
146
  import { DebugPanel } from "${n}"
148
- `)),o.includes("<DebugPanel client:load />"))return o;const c=o.replace("<main><ExternalLinkGuard client:load /><slot /></main>","<main><ExternalLinkGuard client:load />{import.meta.env.DEV ? <DebugPanel client:load /> : null}<slot /></main>");if(c===o)throw new u(r,"Could not mount DebugPanel in the Astro layout.");return c})}async function lt(e,t){switch(await et(e,t),tt(e,t),rt(e),nt(e),t.template){case"vite":it(e,t);return;case"next":at(e,t);return;case"start":ot(e,t);return;case"react-router":st(e,t);return;case"astro":ct(e,t);return}}const U="use tauri_plugin_opener::OpenerExt;",ut=`fn external_navigation_plugin<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
147
+ `)),o.includes("<DebugPanel client:load />"))return o;const l=o.replace(/<main(?:\s+data-ui-scroll-container)?><ExternalLinkGuard client:load \/><slot \/><\/main>/,"<main data-ui-scroll-container><ExternalLinkGuard client:load />{import.meta.env.DEV ? <DebugPanel client:load /> : null}<slot /></main>");if(l===o)throw new u(r,"Could not mount DebugPanel in the Astro layout.");return l})}async function pt(e,t){switch(await rt(e,t),nt(e,t),at(e),it(e),t.template){case"vite":ot(e,t);return;case"next":st(e,t);return;case"start":lt(e,t);return;case"react-router":ct(e,t);return;case"astro":ut(e,t);return}}const V="use tauri_plugin_opener::OpenerExt;",dt=`fn external_navigation_plugin<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
149
148
  tauri::plugin::Builder::<R>::new("external-navigation")
150
149
  .on_navigation(|webview, url| {
151
150
  let is_internal_host = matches!(
@@ -171,7 +170,7 @@ import { DebugPanel } from "${n}"
171
170
  .build()
172
171
  }
173
172
 
174
- `,pt=`"use client"
173
+ `,mt=`"use client"
175
174
 
176
175
  import { useEffect } from "react"
177
176
 
@@ -272,51 +271,49 @@ export function ExternalLinkGuard() {
272
271
 
273
272
  return null
274
273
  }
275
- `;function y(e){s.mkdirSync(a.dirname(e),{recursive:!0}),s.writeFileSync(e,pt,"utf-8")}function dt(e){const t=a.join(e,"src-tauri/src/lib.rs");l(t,r=>{let n=r;if(n.includes(U)||(n.includes(`use tauri::webview::PageLoadEvent;
274
+ `;function y(e){s.mkdirSync(i.dirname(e),{recursive:!0}),s.writeFileSync(e,mt,"utf-8")}function ft(e){const t=i.join(e,"src-tauri/src/lib.rs");c(t,r=>{let n=r;if(n.includes(V)||(n.includes(`use tauri::webview::PageLoadEvent;
276
275
  `)?n=n.replace(`use tauri::webview::PageLoadEvent;
277
276
  `,`use tauri::webview::PageLoadEvent;
278
- ${U}
279
- `):n=`${U}
280
- ${n}`),!n.includes("fn external_navigation_plugin<R: tauri::Runtime>()")){if(!n.includes("#[cfg_attr(mobile, tauri::mobile_entry_point)]"))throw new u(t,"Could not find the Tauri entry point while inserting the external navigation plugin.");n=n.replace("#[cfg_attr(mobile, tauri::mobile_entry_point)]",`${ut}#[cfg_attr(mobile, tauri::mobile_entry_point)]`)}if(!n.includes(".plugin(external_navigation_plugin())")){if(!n.includes(".plugin(tauri_plugin_opener::init())"))throw new u(t,"Could not find the opener plugin while inserting the external navigation guard.");n=n.replace(` .plugin(tauri_plugin_opener::init())
277
+ ${V}
278
+ `):n=`${V}
279
+ ${n}`),!n.includes("fn external_navigation_plugin<R: tauri::Runtime>()")){if(!n.includes("#[cfg_attr(mobile, tauri::mobile_entry_point)]"))throw new u(t,"Could not find the Tauri entry point while inserting the external navigation plugin.");n=n.replace("#[cfg_attr(mobile, tauri::mobile_entry_point)]",`${dt}#[cfg_attr(mobile, tauri::mobile_entry_point)]`)}if(!n.includes(".plugin(external_navigation_plugin())")){if(!n.includes(".plugin(tauri_plugin_opener::init())"))throw new u(t,"Could not find the opener plugin while inserting the external navigation guard.");n=n.replace(` .plugin(tauri_plugin_opener::init())
281
280
  `,` .plugin(tauri_plugin_opener::init())
282
281
  .plugin(external_navigation_plugin())
283
- `)}return n})}function mt(e){const t=a.join(e,"src/components/external-link-guard.tsx"),r=a.join(e,"src/main.tsx");y(t),l(r,n=>{let i=n;if(i.includes('import { ExternalLinkGuard } from "./components/external-link-guard.tsx"')||(i=i.replace(/import { ThemeProvider } from "@\/components\/theme-provider\.tsx"\r?\n/,`import { ThemeProvider } from "@/components/theme-provider.tsx"
282
+ `)}return n})}function gt(e){const t=i.join(e,"src/components/external-link-guard.tsx"),r=i.join(e,"src/main.tsx");y(t),c(r,n=>{let a=n;if(a.includes('import { ExternalLinkGuard } from "./components/external-link-guard.tsx"')||(a=a.replace(/import { ThemeProvider } from "@\/components\/theme-provider\.tsx"\r?\n/,`import { ThemeProvider } from "@/components/theme-provider.tsx"
284
283
  import { ExternalLinkGuard } from "./components/external-link-guard.tsx"
285
- `)),i.includes("<ExternalLinkGuard />"))return i;const o=i.replace(/<ThemeProvider>\r?\n(\s*)<main><App \/><\/main>/,`<ThemeProvider>
284
+ `)),a.includes("<ExternalLinkGuard />"))return a;const o=a.replace(/<ThemeProvider>\r?\n(\s*)<main(?:\s+data-ui-scroll-container)?><App \/><\/main>/,`<ThemeProvider>
286
285
  $1<ExternalLinkGuard />
287
- $1<main><App /></main>`);if(o===i)throw new u(r,"Could not mount ExternalLinkGuard in the Vite entrypoint.");return o})}function ft(e){const t=a.join(e,"components/external-link-guard.tsx"),r=a.join(e,"app/layout.tsx");y(t),l(r,n=>{let i=n;if(i.includes('import { ExternalLinkGuard } from "@/components/external-link-guard"')||(i.includes(`import { TooltipProvider } from "@/components/ui/tooltip"
288
- `)?i=i.replace(`import { TooltipProvider } from "@/components/ui/tooltip"
286
+ $1<main data-ui-scroll-container><App /></main>`);if(o===a)throw new u(r,"Could not mount ExternalLinkGuard in the Vite entrypoint.");return o})}function ht(e){const t=i.join(e,"components/external-link-guard.tsx"),r=i.join(e,"app/layout.tsx");y(t),c(r,n=>{let a=n;if(a.includes('import { ExternalLinkGuard } from "@/components/external-link-guard"')||(a.includes(`import { TooltipProvider } from "@/components/ui/tooltip"
287
+ `)?a=a.replace(`import { TooltipProvider } from "@/components/ui/tooltip"
289
288
  `,`import { TooltipProvider } from "@/components/ui/tooltip"
290
289
  import { ExternalLinkGuard } from "@/components/external-link-guard"
291
- `):i=i.replace(`import { ThemeProvider } from "@/components/theme-provider"
290
+ `):a=a.replace(`import { ThemeProvider } from "@/components/theme-provider"
292
291
  `,`import { ThemeProvider } from "@/components/theme-provider"
293
292
  import { ExternalLinkGuard } from "@/components/external-link-guard"
294
- `)),i.includes("<ExternalLinkGuard />"))return i;const o=i.replace("<main>{children}</main>","<main><ExternalLinkGuard />{children}</main>");if(o===i)throw new u(r,"Could not mount ExternalLinkGuard in the Next.js layout.");return o})}function gt(e){const t=a.join(e,"src/components/external-link-guard.tsx"),r=a.join(e,"src/routes/__root.tsx");y(t),l(r,n=>{let i=n;if(i.includes('import { ExternalLinkGuard } from "../components/external-link-guard"')||(i=i.replace(`import appCss from "../styles.css?url"
293
+ `)),a.includes("<ExternalLinkGuard />"))return a;const o=a.replace(/<main(?:\s+data-ui-scroll-container)?>\{children\}<\/main>/,"<main data-ui-scroll-container><ExternalLinkGuard />{children}</main>");if(o===a)throw new u(r,"Could not mount ExternalLinkGuard in the Next.js layout.");return o})}function wt(e){const t=i.join(e,"src/components/external-link-guard.tsx"),r=i.join(e,"src/routes/__root.tsx");y(t),c(r,n=>{let a=n;if(a.includes('import { ExternalLinkGuard } from "../components/external-link-guard"')||(a=a.replace(`import appCss from "../styles.css?url"
295
294
  `,`import appCss from "../styles.css?url"
296
295
  import { ExternalLinkGuard } from "../components/external-link-guard"
297
- `)),i.includes("<ExternalLinkGuard />"))return i;const o=i.replace("<main>{children}</main>","<main><ExternalLinkGuard />{children}</main>");if(o===i)throw new u(r,"Could not mount ExternalLinkGuard in the TanStack Start root route.");return o})}function ht(e){const t=a.join(e,"app/components/external-link-guard.tsx"),r=a.join(e,"app/root.tsx");y(t),l(r,n=>{let i=n;if(i.includes('import { ExternalLinkGuard } from "./components/external-link-guard"')||(i=i.replace(`import "./app.css"
296
+ `)),a.includes("<ExternalLinkGuard />"))return a;const o=a.replace(/<main(?:\s+data-ui-scroll-container)?>\{children\}<\/main>/,"<main data-ui-scroll-container><ExternalLinkGuard />{children}</main>");if(o===a)throw new u(r,"Could not mount ExternalLinkGuard in the TanStack Start root route.");return o})}function vt(e){const t=i.join(e,"app/components/external-link-guard.tsx"),r=i.join(e,"app/root.tsx");y(t),c(r,n=>{let a=n;if(a.includes('import { ExternalLinkGuard } from "./components/external-link-guard"')||(a=a.replace(`import "./app.css"
298
297
  `,`import "./app.css"
299
298
  import { ExternalLinkGuard } from "./components/external-link-guard"
300
- `)),i.includes("<ExternalLinkGuard />"))return i;const o=i.replace(`<body>
299
+ `)),a.includes("<ExternalLinkGuard />"))return a;const o=a.replace(`<body>
301
300
  {children}`,`<body>
302
301
  <ExternalLinkGuard />
303
- {children}`);if(o===i)throw new u(r,"Could not mount ExternalLinkGuard in the React Router root layout.");return o})}function wt(e){const t=a.join(e,"src/components/external-link-guard.tsx"),r=a.join(e,"src/layouts/main.astro");y(t),l(r,n=>{let i=n;if(i.includes('import { ExternalLinkGuard } from "@/components/external-link-guard"')||(i=i.replace(`import "@/styles/global.css"
302
+ {children}`);if(o===a)throw new u(r,"Could not mount ExternalLinkGuard in the React Router root layout.");return o})}function xt(e){const t=i.join(e,"src/components/external-link-guard.tsx"),r=i.join(e,"src/layouts/main.astro");y(t),c(r,n=>{let a=n;if(a.includes('import { ExternalLinkGuard } from "@/components/external-link-guard"')||(a=a.replace(`import "@/styles/global.css"
304
303
  `,`import "@/styles/global.css"
305
304
  import { ExternalLinkGuard } from "@/components/external-link-guard"
306
- `)),i.includes("<ExternalLinkGuard client:load />"))return i;const o=i.replace(` <body>
307
- <main><slot /></main>
308
- </body>`,` <body>
309
- <main><ExternalLinkGuard client:load /><slot /></main>
310
- </body>`);if(o===i)throw new u(r,"Could not mount ExternalLinkGuard in the Astro layout.");return o})}async function vt(e,t){switch(dt(e),t.template){case"vite":mt(e);return;case"next":ft(e);return;case"start":gt(e);return;case"react-router":ht(e);return;case"astro":wt(e);return}}const V="use tauri::webview::PageLoadEvent;",xt=` .on_page_load(|webview, payload| {
305
+ `)),a.includes("<ExternalLinkGuard client:load />"))return a;const o=a.replace(/ <body>\n <main(?:\s+data-ui-scroll-container)?><slot \/><\/main>\n <\/body>/,` <body>
306
+ <main data-ui-scroll-container><ExternalLinkGuard client:load /><slot /></main>
307
+ </body>`);if(o===a)throw new u(r,"Could not mount ExternalLinkGuard in the Astro layout.");return o})}async function bt(e,t){switch(ft(e),t.template){case"vite":gt(e);return;case"next":ht(e);return;case"start":wt(e);return;case"react-router":vt(e);return;case"astro":xt(e);return}}const B="use tauri::webview::PageLoadEvent;",yt=` .on_page_load(|webview, payload| {
311
308
  if webview.label() == "main" && matches!(payload.event(), PageLoadEvent::Finished) {
312
309
  let _ = webview.window().show();
313
310
  }
314
311
  })
315
- `;async function yt(e){m(a.join(e,"src-tauri/tauri.conf.json"),r=>{r.app=r.app||{},r.app.windows=Array.isArray(r.app.windows)?r.app.windows:[{}];const n=r.app.windows[0]||{};return r.app.windows[0]={...n,visible:!1},r});const t=a.join(e,"src-tauri/src/lib.rs");l(t,r=>{let n=r;if(n.includes(V)||(n.includes(`use tauri::Manager;
312
+ `;async function kt(e){f(i.join(e,"src-tauri/tauri.conf.json"),r=>{r.app=r.app||{},r.app.windows=Array.isArray(r.app.windows)?r.app.windows:[{}];const n=r.app.windows[0]||{};return r.app.windows[0]={...n,visible:!1},r});const t=i.join(e,"src-tauri/src/lib.rs");c(t,r=>{let n=r;if(n.includes(B)||(n.includes(`use tauri::Manager;
316
313
  `)?n=n.replace(`use tauri::Manager;
317
- `,`${V}
318
- `):n=`${V}
319
- ${n}`),n.includes(".on_page_load("))return n;const i=n.replace(" .run(tauri::generate_context!())",`${xt} .run(tauri::generate_context!())`);if(i===n)throw new u(t,"Could not insert the startup flash-prevention page-load hook.");return i})}function bt(){const e=a.dirname(I(import.meta.url)),t=[a.resolve(e,"../assets"),a.resolve(e,"../../assets")];return t.find(r=>s.existsSync(r))??t[0]}const kt=bt();async function $t(e){q(a.join(kt,"app-icon.png"),a.join(e,"app-icon.png"))}function Et(e){return`"use client"
314
+ `,`${B}
315
+ `):n=`${B}
316
+ ${n}`),n.includes(".on_page_load("))return n;const a=n.replace(" .run(tauri::generate_context!())",`${yt} .run(tauri::generate_context!())`);if(a===n)throw new u(t,"Could not insert the startup flash-prevention page-load hook.");return a})}function $t(){const e=i.dirname(R(import.meta.url)),t=[i.resolve(e,"../assets"),i.resolve(e,"../../assets")];return t.find(r=>s.existsSync(r))??t[0]}const Et=$t();async function jt(e){J(i.join(Et,"app-icon.png"),i.join(e,"app-icon.png"))}function St(e){return`"use client"
320
317
 
321
318
  import { useState } from "react"
322
319
  import { Button } from "${e}components/ui/button"
@@ -359,7 +356,7 @@ export function Greet() {
359
356
  </div>
360
357
  )
361
358
  }
362
- `}function jt(e,t){return`import { Greet } from "${t}components/greet"
359
+ `}function _t(e,t){return`import { Greet } from "${t}components/greet"
363
360
 
364
361
  export default function ${e}() {
365
362
  return (
@@ -376,7 +373,7 @@ export default function ${e}() {
376
373
  </div>
377
374
  )
378
375
  }
379
- `}function St(){return`import { createFileRoute } from "@tanstack/react-router"
376
+ `}function Pt(){return`import { createFileRoute } from "@tanstack/react-router"
380
377
  import { Greet } from "@/components/greet"
381
378
 
382
379
  export const Route = createFileRoute("/")({
@@ -398,7 +395,7 @@ function Home() {
398
395
  </div>
399
396
  )
400
397
  }
401
- `}function se(e,t){switch(e){case"next":return a.join(t,"app/page.tsx");case"vite":return a.join(t,"src/App.tsx");case"start":return a.join(t,"src/routes/index.tsx");case"react-router":return a.join(t,"app/routes/home.tsx");case"astro":return a.join(t,"src/pages/index.astro")}}function _t(e,t){switch(e){case"next":return a.join(t,"components/greet.tsx");case"vite":case"start":case"astro":return a.join(t,"src/components/greet.tsx");case"react-router":return a.join(t,"app/components/greet.tsx")}}async function Pt(e,t){t.includeStarterUI||await te(e,"input");const r=t.template==="react-router"?"~/":"@/";if(s.writeFileSync(_t(t.template,e),Et(r)),t.includeStarterUI)return;if(t.template==="astro"){s.writeFileSync(se(t.template,e),`---
398
+ `}function le(e,t){switch(e){case"next":return i.join(t,"app/page.tsx");case"vite":return i.join(t,"src/App.tsx");case"start":return i.join(t,"src/routes/index.tsx");case"react-router":return i.join(t,"app/routes/home.tsx");case"astro":return i.join(t,"src/pages/index.astro")}}function Dt(e,t){switch(e){case"next":return i.join(t,"components/greet.tsx");case"vite":case"start":case"astro":return i.join(t,"src/components/greet.tsx");case"react-router":return i.join(t,"app/components/greet.tsx")}}async function Lt(e,t){t.includeStarterUI||await re(e,"input");const r=t.template==="react-router"?"~/":"@/";if(s.writeFileSync(Dt(t.template,e),St(r)),t.includeStarterUI)return;if(t.template==="astro"){s.writeFileSync(le(t.template,e),`---
402
399
  import Layout from "@/layouts/main.astro"
403
400
  import { Greet } from "@/components/greet"
404
401
  ---
@@ -416,33 +413,39 @@ import { Greet } from "@/components/greet"
416
413
  </div>
417
414
  </div>
418
415
  </Layout>
419
- `);return}const n=t.template==="start"?St():jt(t.template==="vite"?"App":t.template==="react-router"?"Home":"Page",r);s.writeFileSync(se(t.template,e),n)}const b=`
416
+ `);return}const n=t.template==="start"?Pt():_t(t.template==="vite"?"App":t.template==="react-router"?"Home":"Page",r);s.writeFileSync(le(t.template,e),n)}const m="data-ui-scroll-container",k=`
417
+ /* Disable page-level overscroll and rubber-band scrolling so the UI feels more desktop-native. */
420
418
  html,
421
419
  body {
422
420
  height: 100%;
423
- overscroll-behavior: none;
424
421
  }
425
422
 
426
423
  body {
427
424
  overflow: hidden;
428
425
  }
429
426
 
430
- main {
431
- height: 100%;
432
- overflow: auto;
433
- overscroll-behavior: none;
427
+ /* Scope the desktop scroll shell to the generated root container only. */
428
+ [${m}] {
429
+ height: 100vh;
430
+ height: 100dvh;
431
+ overflow-x: hidden;
432
+ overflow-y: auto;
433
+ overscroll-behavior-y: none;
434
434
  }
435
- `,Dt=`
435
+ `,Ct=`
436
+ /* Vite mounts into #root, so it needs to inherit the full-height desktop shell. */
436
437
  #root {
437
438
  height: 100%;
438
439
  }
439
- `;function k(e,t){l(e,r=>r.includes("overscroll-behavior: none;")?r:`${r.trimEnd()}
440
- ${t}`)}function $(e,t,r){l(e,n=>{if(n.includes("<main>"))return n;const i=n.replace(t,r);if(i===n)throw new u(e,"Could not insert the scroll container <main> wrapper.");return i})}async function Lt(e,t){switch(t.template){case"next":k(a.join(e,"app/globals.css"),b),$(a.join(e,"app/layout.tsx"),/\{children\}/,"<main>{children}</main>");return;case"vite":k(a.join(e,"src/index.css"),`${b}${Dt}`),$(a.join(e,"src/main.tsx"),/<App \/>/,"<main><App /></main>");return;case"start":k(a.join(e,"src/styles.css"),b),$(a.join(e,"src/routes/__root.tsx"),/\{children\}/,"<main>{children}</main>");return;case"react-router":k(a.join(e,"app/app.css"),b),$(a.join(e,"app/root.tsx"),/return <Outlet \/>/,"return <main><Outlet /></main>");return;case"astro":k(a.join(e,"src/styles/global.css"),b),$(a.join(e,"src/layouts/main.astro"),/<slot \/>/,"<main><slot /></main>");return;default:throw new u(e,`No scroll container battery implementation exists for template "${t.template}".`)}}const E=`
440
+ `;function $(e,t){c(e,r=>r.includes("Disable page-level overscroll and rubber-band scrolling")?r:`${r.trimEnd()}
441
+ ${t}`)}function E(e,t,r){c(e,n=>{if(n.includes(`<main ${m}>`))return n;const a=n.replace(new RegExp(`<main(?![^>]*${m})([^>]*)>`),`<main ${m}$1>`);if(a!==n)return a;const o=n.replace(t,r);if(o===n)throw new u(e,"Could not insert the scroll container <main> wrapper.");return o})}async function Tt(e,t){switch(t.template){case"next":$(i.join(e,"app/globals.css"),k),E(i.join(e,"app/layout.tsx"),/\{children\}/,`<main ${m}>{children}</main>`);return;case"vite":$(i.join(e,"src/index.css"),`${k}${Ct}`),E(i.join(e,"src/main.tsx"),/<App \/>/,`<main ${m}><App /></main>`);return;case"start":$(i.join(e,"src/styles.css"),k),E(i.join(e,"src/routes/__root.tsx"),/\{children\}/,`<main ${m}>{children}</main>`);return;case"react-router":$(i.join(e,"app/app.css"),k),E(i.join(e,"app/root.tsx"),/return <Outlet \/>/,`return <main ${m}><Outlet /></main>`);return;case"astro":$(i.join(e,"src/styles/global.css"),k),E(i.join(e,"src/layouts/main.astro"),/<slot \/>/,`<main ${m}><slot /></main>`);return;default:throw new u(e,`No scroll container battery implementation exists for template "${t.template}".`)}}const j=`
441
442
  @layer base {
443
+ /* Desktop UIs often feel cleaner with accidental text selection disabled by default. */
442
444
  body {
443
445
  @apply select-none;
444
446
  }
445
447
 
448
+ /* Keep editing and code surfaces selectable so inputs and diagnostics still work normally. */
446
449
  input,
447
450
  textarea,
448
451
  [contenteditable="true"],
@@ -453,15 +456,16 @@ ${t}`)}function $(e,t,r){l(e,n=>{if(n.includes("<main>"))return n;const i=n.repl
453
456
  }
454
457
 
455
458
  @layer utilities {
459
+ /* Opt back into selection for any generated UI surface that should behave like regular text. */
456
460
  .ui-selectable {
457
461
  @apply select-text;
458
462
  }
459
463
  }
460
- `;function j(e,t){l(e,r=>r.includes(".ui-selectable")?r:`${r.trimEnd()}
461
- ${t}`)}async function Ct(e,t){switch(t.template){case"next":j(a.join(e,"app/globals.css"),E);return;case"vite":j(a.join(e,"src/index.css"),E);return;case"start":j(a.join(e,"src/styles.css"),E);return;case"react-router":j(a.join(e,"app/app.css"),E);return;case"astro":j(a.join(e,"src/styles/global.css"),E);return;default:throw new u(e,`No selection behavior battery implementation exists for template "${t.template}".`)}}function Tt(){const e=a.dirname(I(import.meta.url)),t=[a.resolve(e,"../assets"),a.resolve(e,"../../assets")];return t.find(r=>s.existsSync(r))??t[0]}const Gt=Tt();function Nt(e){const t=[];for(const r of e){if(r==="macos-latest"){t.push({name:"macOS Apple Silicon",platform:"macos-latest",args:"--target aarch64-apple-darwin"},{name:"macOS Intel",platform:"macos-latest",args:"--target x86_64-apple-darwin"});continue}if(r==="ubuntu-latest"){t.push({name:"Linux",platform:"ubuntu-22.04",args:""});continue}t.push({name:"Windows",platform:r,args:""})}return t.map(r=>` - name: "${r.name}"
464
+ `;function S(e,t){c(e,r=>r.includes(".ui-selectable")?r:`${r.trimEnd()}
465
+ ${t}`)}async function Gt(e,t){switch(t.template){case"next":S(i.join(e,"app/globals.css"),j);return;case"vite":S(i.join(e,"src/index.css"),j);return;case"start":S(i.join(e,"src/styles.css"),j);return;case"react-router":S(i.join(e,"app/app.css"),j);return;case"astro":S(i.join(e,"src/styles/global.css"),j);return;default:throw new u(e,`No selection behavior battery implementation exists for template "${t.template}".`)}}function Nt(){const e=i.dirname(R(import.meta.url)),t=[i.resolve(e,"../assets"),i.resolve(e,"../../assets")];return t.find(r=>s.existsSync(r))??t[0]}const It=Nt();function At(e){const t=[];for(const r of e){if(r==="macos-latest"){t.push({name:"macOS Apple Silicon",platform:"macos-latest",args:"--target aarch64-apple-darwin"},{name:"macOS Intel",platform:"macos-latest",args:"--target x86_64-apple-darwin"});continue}if(r==="ubuntu-latest"){t.push({name:"Linux",platform:"ubuntu-22.04",args:""});continue}t.push({name:"Windows",platform:r,args:""})}return t.map(r=>` - name: "${r.name}"
462
466
  platform: "${r.platform}"
463
467
  args: "${r.args}"`).join(`
464
- `)}async function At(e,t){const r=s.readFileSync(a.join(Gt,"release.yml.tmpl"),"utf-8").replace("{{PLATFORMS}}",Nt(t.targetOS)),n=a.join(e,".github/workflows");s.mkdirSync(n,{recursive:!0}),s.writeFileSync(a.join(n,"release.yml"),r)}const It=1400,Rt=918;async function Ot(e,t,r){Z(a.join(t,"src-tauri"),a.join(e,"src-tauri")),m(a.join(e,"package.json"),o=>(o.name=r.packageName,o.dependencies=o.dependencies||{},o.dependencies["@tauri-apps/api"]="^2",o.dependencies["@tauri-apps/plugin-opener"]="^2",o.devDependencies=o.devDependencies||{},o.devDependencies["@tauri-apps/cli"]="^2",o.scripts=o.scripts||{},o.scripts.tauri="tauri",o));const n=Pe(r.packageName),i=`${n}_lib`;l(a.join(e,"src-tauri/Cargo.toml"),o=>o.replace(/^name = "tauri-app"$/m,`name = "${n}"`).replace(/^name = "tauri_app_lib"$/m,`name = "${i}"`)),l(a.join(e,"src-tauri/src/main.rs"),o=>o.replace("tauri_app_lib::run()",`${i}::run()`))}async function Ft(e,t,r){m(a.join(e,"src-tauri/tauri.conf.json"),n=>{n.productName=t.projectName,n.identifier=t.identifier,n.build={...n.build,...r},n.app=n.app||{},n.app.windows=Array.isArray(n.app.windows)?n.app.windows:[{}];const i=n.app.windows[0]||{};return n.app.windows[0]={...i,title:t.projectName,center:!0,width:It,height:Rt},n})}const B=["vite","next","start","react-router","astro"],M=["windows-latest","macos-latest","ubuntu-latest"],ce="tauri-ui",le="b0",Ut={vite:"Vite",next:"Next.js",start:"TanStack Start","react-router":"React Router",astro:"Astro"};function p(e,t="Operation cancelled"){if(xe(e))throw new Error(t);return e}function Vt(e){if(B.includes(e))return e;throw new Error(`Unsupported template "${e}". Expected one of: ${B.join(", ")}`)}function ue(e){try{return`com.${J(z.userInfo().username)||"example"}.${e}`}catch{return`com.example.${e}`}}function G(e){return{placeholder:e,defaultValue:e}}async function Bt(e,t=process.cwd()){let r=Ee(e.targetDir);if(r||(r=p(await _({message:"Project name",...G(ce)}))),r||(r=ce),r===".")throw new Error("Scaffolding into the current directory is not supported yet.");const n=a.resolve(t,r),i=a.basename(n),o=R(i)?i:J(i);if(s.existsSync(n)&&!je(n))if(e.force)s.rmSync(n,{recursive:!0,force:!0});else{if(e.yes)throw new Error(`Target directory "${r}" is not empty. Re-run with --force to overwrite it.`);if(!p(await P({message:`Target directory "${r}" is not empty. Remove it and continue?`,initialValue:!1})))throw new Error("Operation cancelled");s.rmSync(n,{recursive:!0,force:!0})}let c=o;R(i)||(e.yes?c=o:c=p(await _({message:"Package name",...G(o),validate(d){if(!d||!R(d))return"Enter a valid package.json name"}})));const N=e.template?Vt(e.template):e.yes?"vite":p(await we({message:"Frontend template",initialValue:"vite",options:B.map(d=>({value:d,label:Ut[d]}))})),de=e.identifier?e.identifier:e.yes?ue(c):p(await _({message:"App identifier",...G(ue(c))})),me=e.preset?e.preset:e.yes?le:p(await _({message:"shadcn preset",...G(le)})),fe=e.includeStarterUI??(e.yes?!0:p(await P({message:"Include starter UI?",initialValue:!0}))),ge=e.includeInvokeExample??(e.yes?!0:p(await P({message:"Include Rust invoke example?",initialValue:!0}))),H=e.includeWorkflow??(e.yes?!0:p(await P({message:"Include GitHub release workflow?",initialValue:!0}))),he=H?e.yes?[...M]:p(await ve({message:"Target operating systems",initialValues:[...M],required:!0,options:M.map(d=>({value:d,label:d}))})):[];return{projectName:i,packageName:c,template:N,identifier:de,preset:me,includeStarterUI:fe,includeInvokeExample:ge,includeWorkflow:H,targetOS:he,targetDir:n}}function Mt(){console.log(`Usage: create-tauri-ui [target-dir] [options]
468
+ `)}async function Rt(e,t){const r=s.readFileSync(i.join(It,"release.yml.tmpl"),"utf-8").replace("{{PLATFORMS}}",At(t.targetOS)),n=i.join(e,".github/workflows");s.mkdirSync(n,{recursive:!0}),s.writeFileSync(i.join(n,"release.yml"),r)}const Ot=1400,Ft=918;async function Ut(e,t,r){Q(i.join(t,"src-tauri"),i.join(e,"src-tauri")),f(i.join(e,"package.json"),o=>(o.name=r.packageName,o.dependencies=o.dependencies||{},o.dependencies["@tauri-apps/api"]="^2",o.dependencies["@tauri-apps/plugin-opener"]="^2",o.devDependencies=o.devDependencies||{},o.devDependencies["@tauri-apps/cli"]="^2",o.scripts=o.scripts||{},o.scripts.tauri="tauri",o));const n=Le(r.packageName),a=`${n}_lib`;c(i.join(e,"src-tauri/Cargo.toml"),o=>o.replace(/^name = "tauri-app"$/m,`name = "${n}"`).replace(/^name = "tauri_app_lib"$/m,`name = "${a}"`)),c(i.join(e,"src-tauri/src/main.rs"),o=>o.replace("tauri_app_lib::run()",`${a}::run()`))}async function Vt(e,t,r){f(i.join(e,"src-tauri/tauri.conf.json"),n=>{n.productName=t.projectName,n.identifier=t.identifier,n.build={...n.build,...r},n.app=n.app||{},n.app.windows=Array.isArray(n.app.windows)?n.app.windows:[{}];const a=n.app.windows[0]||{};return n.app.windows[0]={...a,title:t.projectName,center:!0,width:Ot,height:Ft},n})}const M=["vite","next","start","react-router","astro"],H=["windows-latest","macos-latest","ubuntu-latest"],ce="tauri-ui",ue="b0",Bt={vite:"Vite",next:"Next.js",start:"TanStack Start","react-router":"React Router",astro:"Astro"},Mt={"windows-latest":"Windows","macos-latest":"macOS (Apple Silicon, Intel)","ubuntu-22.04":"Linux","ubuntu-latest":"Linux"};function p(e,t="Operation cancelled"){if(ye(e))throw new Error(t);return e}function Ht(e){if(M.includes(e))return e;throw new Error(`Unsupported template "${e}". Expected one of: ${M.join(", ")}`)}function pe(e){try{return`com.${Z(Y.userInfo().username)||"example"}.${e}`}catch{return`com.example.${e}`}}function N(e){return{placeholder:e,defaultValue:e}}function de(e){const t=e.trim().replace(/^['"]|['"]$/g,"");return(t.match(/^(?:--preset(?:=|\s+))?(.+)$/)?.[1]??t).trim()}async function Wt(e,t=process.cwd()){let r=Se(e.targetDir);if(r||(r=p(await P({message:"Project name",...N(ce)}))),r||(r=ce),r===".")throw new Error("Scaffolding into the current directory is not supported yet.");const n=i.resolve(t,r),a=i.basename(n),o=O(a)?a:Z(a);if(s.existsSync(n)&&!_e(n))if(e.force)s.rmSync(n,{recursive:!0,force:!0});else{if(e.yes)throw new Error(`Target directory "${r}" is not empty. Re-run with --force to overwrite it.`);if(!p(await D({message:`Target directory "${r}" is not empty. Remove it and continue?`,initialValue:!1})))throw new Error("Operation cancelled");s.rmSync(n,{recursive:!0,force:!0})}let l=o;O(a)||(e.yes?l=o:l=p(await P({message:"Package name",...N(o),validate(d){if(!d||!O(d))return"Enter a valid package.json name"}})));const I=e.template?Ht(e.template):e.yes?"vite":p(await xe({message:"Frontend template",initialValue:"vite",options:M.map(d=>({value:d,label:Bt[d]}))})),fe=e.identifier?e.identifier:e.yes?pe(l):p(await P({message:"App identifier",...N(pe(l))})),ge=e.preset?de(e.preset):e.yes?ue:de(p(await P({message:"shadcn preset",...N(ue)}))),he=e.includeStarterUI??(e.yes?!0:p(await D({message:"Include starter UI?",initialValue:!0}))),we=e.includeInvokeExample??(e.yes?!0:p(await D({message:"Include Rust invoke example?",initialValue:!0}))),W=e.includeWorkflow??(e.yes?!0:p(await D({message:"Include GitHub release workflow?",initialValue:!0}))),ve=W?e.yes?[...H]:p(await be({message:"GitHub workflow target operating systems",initialValues:[...H],required:!0,options:H.map(d=>({value:d,label:Mt[d]??d}))})):[];return{projectName:a,packageName:l,template:I,identifier:fe,preset:ge,includeStarterUI:he,includeInvokeExample:we,includeWorkflow:W,targetOS:ve,targetDir:n}}function Kt(){console.log(`Usage: create-tauri-ui [target-dir] [options]
465
469
 
466
470
  Options:
467
471
  -t, --template <name> vite | next | start | react-router | astro
@@ -475,5 +479,5 @@ Options:
475
479
  --no-workflow skip the GitHub release workflow
476
480
  -f, --force overwrite an existing target directory
477
481
  -y, --yes accept defaults
478
- -h, --help display help`)}function Ht(e){const t={},r=[],n=(i,o)=>{const c=e[i+1];if(!c||c.startsWith("-"))throw new Error(`Missing value for ${o}`);return c};for(let i=0;i<e.length;i+=1){const o=e[i];switch(o){case"-h":case"--help":t.help=!0;break;case"-t":case"--template":t.template=n(i,o),i+=1;break;case"--identifier":t.identifier=n(i,o),i+=1;break;case"--preset":t.preset=n(i,o),i+=1;break;case"--starter":t.includeStarterUI=!0;break;case"--no-starter":t.includeStarterUI=!1;break;case"--invoke-example":case"--example":t.includeInvokeExample=!0;break;case"--no-invoke-example":case"--no-example":t.includeInvokeExample=!1;break;case"--workflow":t.includeWorkflow=!0;break;case"--no-workflow":t.includeWorkflow=!1;break;case"-f":case"--force":t.force=!0;break;case"-y":case"--yes":t.yes=!0;break;default:if(o.startsWith("-"))throw new Error(`Unknown flag: ${o}`);r.push(o)}}if(r.length>1)throw new Error("Only one target directory may be provided.");return r[0]&&(t.targetDir=r[0]),t}function Wt(e){const t=a.relative(S.cwd(),e)||".";return t.includes(" ")?`"${t}"`:t}function Kt(e){s.rmSync(a.join(e,"node_modules"),{recursive:!0,force:!0})}function zt(e,t){const r=[`cd ${Wt(e)}`,"bun install","bun run tauri dev","bunx tauri icon app-icon.png"];K(r.join(`
479
- `),"Next steps"),t&&K("Configure the GitHub release workflow secrets before publishing builds.","Release workflow")}async function Yt(){try{await C("bun",["--version"])}catch{throw new Error("bun is required. Install it from https://bun.sh.")}}function pe(e){return e instanceof w?{message:e.message,detail:e.stderr.trim()}:e instanceof Error?{message:e.message,detail:""}:{message:"An unknown error occurred.",detail:""}}async function Xt(){const e=Ht(S.argv.slice(2));if(e.help){Mt();return}ye(A.bold("create-tauri-ui")),await Yt();const t=await Bt(e);_e(),O(t.targetDir);const r=be();let n;try{r.start("Creating the shadcn frontend scaffold"),await We(t),r.message("Creating the Tauri native scaffold");const i=await Ke(t);n=i.tempDir,r.message("Merging the native layer into the frontend project"),await Ot(t.targetDir,i.projectDir,t);const o=Oe(t.template);r.message(`Patching the ${t.template} project for Tauri`);try{await o.apply(t.targetDir,t)}catch(c){if(c instanceof u)h.warn(`${c.message} (${c.file})`);else throw c}if(await Ft(t.targetDir,t,o.tauriConfig()),r.message("Applying the startup flash-prevention battery"),await yt(t.targetDir),r.message("Applying the desktop scroll container battery"),await Lt(t.targetDir,t),r.message("Applying the external link guard battery"),await vt(t.targetDir,t),r.message("Applying the development debug panel battery"),await lt(t.targetDir,t),r.message("Applying the desktop selection-behavior battery"),await Ct(t.targetDir,t),t.includeStarterUI){r.message("Installing the starter dashboard");try{await ze(t.targetDir,t)}catch(c){if(c instanceof w)h.warn(c.message),c.stderr.trim()&&h.message(c.stderr.trim());else throw c}}t.includeInvokeExample&&(r.message("Adding the Rust invoke example"),await Pt(t.targetDir,t)),t.includeWorkflow&&(r.message("Writing the GitHub release workflow"),await At(t.targetDir,t)),r.message("Copying the app icon source"),await $t(t.targetDir),Kt(t.targetDir),f(t.targetDir),r.stop("Project ready"),zt(t.targetDir,t.includeWorkflow),ke(`Scaffolded ${A.cyan(t.projectName)} in ${A.dim(t.targetDir)}`)}catch(i){const o=pe(i);r.error("Scaffolding failed"),W(o.message),o.detail&&h.message(o.detail),S.exitCode=1}finally{if(n){f(n);try{g(n)}catch{}}}}Xt().catch(e=>{const t=pe(e);W(t.message),t.detail&&h.message(t.detail),S.exit(1)});
482
+ -h, --help display help`)}function zt(e){const t={},r=[],n=(a,o)=>{const l=e[a+1];if(!l||l.startsWith("-"))throw new Error(`Missing value for ${o}`);return l};for(let a=0;a<e.length;a+=1){const o=e[a];switch(o){case"-h":case"--help":t.help=!0;break;case"-t":case"--template":t.template=n(a,o),a+=1;break;case"--identifier":t.identifier=n(a,o),a+=1;break;case"--preset":t.preset=n(a,o),a+=1;break;case"--starter":t.includeStarterUI=!0;break;case"--no-starter":t.includeStarterUI=!1;break;case"--invoke-example":case"--example":t.includeInvokeExample=!0;break;case"--no-invoke-example":case"--no-example":t.includeInvokeExample=!1;break;case"--workflow":t.includeWorkflow=!0;break;case"--no-workflow":t.includeWorkflow=!1;break;case"-f":case"--force":t.force=!0;break;case"-y":case"--yes":t.yes=!0;break;default:if(o.startsWith("-"))throw new Error(`Unknown flag: ${o}`);r.push(o)}}if(r.length>1)throw new Error("Only one target directory may be provided.");return r[0]&&(t.targetDir=r[0]),t}function Yt(e){const t=i.relative(_.cwd(),e)||".";return t.includes(" ")?`"${t}"`:t}function Xt(e){s.rmSync(i.join(e,"node_modules"),{recursive:!0,force:!0})}function qt(e,t){const r=[`cd ${Yt(e)}`,"bun install","bun run tauri dev","bunx tauri icon app-icon.png"];z(r.join(`
483
+ `),"Next steps"),t&&z("Configure the GitHub release workflow secrets before publishing builds.","Release workflow")}async function Jt(){try{await T("bun",["--version"])}catch{throw new Error("bun is required. Install it from https://bun.sh.")}}function me(e){return e instanceof v?{message:e.message,detail:e.stderr.trim()}:e instanceof Error?{message:e.message,detail:""}:{message:"An unknown error occurred.",detail:""}}async function Zt(){const e=zt(_.argv.slice(2));if(e.help){Kt();return}ke(A.bold("create-tauri-ui")),await Jt();const t=await Wt(e);De(),F(t.targetDir);const r=$e();let n;try{r.start("Creating the shadcn frontend scaffold"),await ze(t),r.message("Creating the Tauri native scaffold");const a=await Ye(t);n=a.tempDir,r.message("Merging the native layer into the frontend project"),await Ut(t.targetDir,a.projectDir,t);const o=Ue(t.template);r.message(`Patching the ${t.template} project for Tauri`);try{await o.apply(t.targetDir,t)}catch(l){if(l instanceof u)w.warn(`${l.message} (${l.file})`);else throw l}if(await Vt(t.targetDir,t,o.tauriConfig()),r.message("Applying the startup flash-prevention battery"),await kt(t.targetDir),r.message("Applying the desktop scroll container battery"),await Tt(t.targetDir,t),r.message("Applying the external link guard battery"),await bt(t.targetDir,t),t.includeStarterUI){r.message("Installing the starter dashboard");try{await Xe(t.targetDir,t)}catch(l){if(l instanceof v)w.warn(l.message),l.stderr.trim()&&w.message(l.stderr.trim());else throw l}}r.message("Applying the development debug panel battery"),await pt(t.targetDir,t),r.message("Applying the desktop selection-behavior battery"),await Gt(t.targetDir,t),t.includeInvokeExample&&(r.message("Adding the Rust invoke example"),await Lt(t.targetDir,t)),t.includeWorkflow&&(r.message("Writing the GitHub release workflow"),await Rt(t.targetDir,t)),r.message("Copying the app icon source"),await jt(t.targetDir),Xt(t.targetDir),g(t.targetDir),r.stop("Project ready"),qt(t.targetDir,t.includeWorkflow),Ee(`Scaffolded ${A.cyan(t.projectName)} in ${A.dim(t.targetDir)}`)}catch(a){const o=me(a);r.error("Scaffolding failed"),K(o.message),o.detail&&w.message(o.detail),_.exitCode=1}finally{if(n){g(n);try{h(n)}catch{}}}}Zt().catch(e=>{const t=me(e);K(t.message),t.detail&&w.message(t.detail),_.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-tauri-ui",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "🦀 Create modern Tauri desktop apps in just a few simple steps.",
5
5
  "homepage": "https://github.com/agmmnn/tauri-ui",
6
6
  "bugs": {