@object-ui/cli 0.3.0 → 0.5.0

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.
@@ -102,6 +102,13 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
102
102
  writeFileSync(join(srcDir, "main.tsx"), mainTsx);
103
103
  const appTsx = `import { SchemaRenderer } from '@object-ui/react';
104
104
  import '@object-ui/components';
105
+ import '@object-ui/plugin-charts';
106
+ import '@object-ui/plugin-editor';
107
+ import '@object-ui/plugin-kanban';
108
+ import '@object-ui/plugin-markdown';
109
+ import '@object-ui/plugin-form';
110
+ import '@object-ui/plugin-grid';
111
+ import '@object-ui/plugin-view';
105
112
 
106
113
  const schema = ${JSON.stringify(schema, null, 2)};
107
114
 
@@ -389,14 +396,91 @@ function createTempAppWithRouting(tmpDir, routes, appConfig) {
389
396
  schemaImports.push(`import ${schemaVarName} from './schemas/${schemaFileName}';`);
390
397
  routeComponents.push(` <Route path="${route.path}" element={<SchemaRenderer schema={${schemaVarName}} />} />`);
391
398
  });
399
+ const themeProviderTsx = `import { createContext, useContext, useEffect, useState } from "react"
400
+
401
+ type Theme = "dark" | "light" | "system"
402
+
403
+ type ThemeProviderProps = {
404
+ children: React.ReactNode
405
+ defaultTheme?: Theme
406
+ storageKey?: string
407
+ }
408
+
409
+ type ThemeProviderState = {
410
+ theme: Theme
411
+ setTheme: (theme: Theme) => void
412
+ }
413
+
414
+ const initialState: ThemeProviderState = {
415
+ theme: "system",
416
+ setTheme: () => null,
417
+ }
418
+
419
+ const ThemeProviderContext = createContext<ThemeProviderState>(initialState)
420
+
421
+ export function ThemeProvider({
422
+ children,
423
+ defaultTheme = "system",
424
+ storageKey = "vite-ui-theme",
425
+ ...props
426
+ }: ThemeProviderProps) {
427
+ const [theme, setTheme] = useState<Theme>(
428
+ () => (localStorage.getItem(storageKey) as Theme) || defaultTheme
429
+ )
430
+
431
+ useEffect(() => {
432
+ const root = window.document.documentElement
433
+
434
+ root.classList.remove("light", "dark")
435
+
436
+ if (theme === "system") {
437
+ const systemTheme = window.matchMedia("(prefers-color-scheme: dark)")
438
+ .matches
439
+ ? "dark"
440
+ : "light"
441
+
442
+ root.classList.add(systemTheme)
443
+ return
444
+ }
445
+
446
+ root.classList.add(theme)
447
+ }, [theme])
448
+
449
+ const value = {
450
+ theme,
451
+ setTheme: (theme: Theme) => {
452
+ localStorage.setItem(storageKey, theme)
453
+ setTheme(theme)
454
+ },
455
+ }
456
+
457
+ return (
458
+ <ThemeProviderContext.Provider {...props} value={value}>
459
+ {children}
460
+ </ThemeProviderContext.Provider>
461
+ )
462
+ }
463
+
464
+ export const useTheme = () => {
465
+ const context = useContext(ThemeProviderContext)
466
+
467
+ if (context === undefined)
468
+ throw new Error("useTheme must be used within a ThemeProvider")
469
+
470
+ return context
471
+ }`;
472
+ writeFileSync(join(srcDir, "theme-provider.tsx"), themeProviderTsx);
392
473
  const mainTsx = `import React from 'react';
393
474
  import ReactDOM from 'react-dom/client';
394
475
  import App from './App';
395
476
  import './index.css';
477
+ import { ThemeProvider } from "./theme-provider"
396
478
 
397
479
  ReactDOM.createRoot(document.getElementById('root')!).render(
398
480
  <React.StrictMode>
399
- <App />
481
+ <ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
482
+ <App />
483
+ </ThemeProvider>
400
484
  </React.StrictMode>
401
485
  );`;
402
486
  writeFileSync(join(srcDir, "main.tsx"), mainTsx);
@@ -407,8 +491,15 @@ ReactDOM.createRoot(document.getElementById('root')!).render(
407
491
  const layoutCode = `
408
492
  import { Link, useLocation } from 'react-router-dom';
409
493
  import * as LucideIcons from 'lucide-react';
494
+ import { Moon, Sun } from "lucide-react"
495
+ import { useTheme } from "./theme-provider"
410
496
  import {
411
497
  cn,
498
+ Button,
499
+ DropdownMenu,
500
+ DropdownMenuContent,
501
+ DropdownMenuItem,
502
+ DropdownMenuTrigger,
412
503
  SidebarProvider,
413
504
  Sidebar,
414
505
  SidebarContent,
@@ -433,12 +524,48 @@ import {
433
524
  } from '@object-ui/components';
434
525
 
435
526
  const DynamicIcon = ({ name, className }) => {
436
- // @ts-ignore
527
+ // @ts-expect-error - Dynamic icon lookup from Lucide icons
437
528
  const Icon = LucideIcons[name];
438
529
  if (!Icon) return null;
439
530
  return <Icon className={className} />;
440
531
  };
441
532
 
533
+ export function ModeToggle() {
534
+ const { setTheme } = useTheme()
535
+
536
+ return (
537
+ <DropdownMenu>
538
+ <DropdownMenuTrigger asChild>
539
+ <SidebarMenuButton size="lg" className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground">
540
+ <div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
541
+ <Sun className="h-4 w-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
542
+ <Moon className="absolute h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
543
+ </div>
544
+ <div className="grid flex-1 text-left text-sm leading-tight">
545
+ <span className="truncate font-semibold">Switch Theme</span>
546
+ <span className="truncate text-xs">Light / Dark</span>
547
+ </div>
548
+ <LucideIcons.ChevronsUpDown className="ml-auto size-4" />
549
+ </SidebarMenuButton>
550
+ </DropdownMenuTrigger>
551
+ <DropdownMenuContent className="w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-lg" side="bottom" align="end" sideOffset={4}>
552
+ <DropdownMenuItem onClick={() => setTheme("light")}>
553
+ <LucideIcons.Sun className="mr-2 size-4" />
554
+ Light
555
+ </DropdownMenuItem>
556
+ <DropdownMenuItem onClick={() => setTheme("dark")}>
557
+ <LucideIcons.Moon className="mr-2 size-4" />
558
+ Dark
559
+ </DropdownMenuItem>
560
+ <DropdownMenuItem onClick={() => setTheme("system")}>
561
+ <LucideIcons.Monitor className="mr-2 size-4" />
562
+ System
563
+ </DropdownMenuItem>
564
+ </DropdownMenuContent>
565
+ </DropdownMenu>
566
+ )
567
+ }
568
+
442
569
  const AppLayout = ({ app, children }) => {
443
570
  const location = useLocation();
444
571
  const menu = app.menu || [];
@@ -512,6 +639,11 @@ const AppLayout = ({ app, children }) => {
512
639
  </SidebarGroup>
513
640
  </SidebarContent>
514
641
  <SidebarFooter>
642
+ <SidebarMenu>
643
+ <SidebarMenuItem>
644
+ <ModeToggle />
645
+ </SidebarMenuItem>
646
+ </SidebarMenu>
515
647
  </SidebarFooter>
516
648
  <SidebarRail />
517
649
  </Sidebar>
@@ -545,6 +677,13 @@ const appConfig = ${JSON.stringify(appConfig)};`;
545
677
  const appTsx = `import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
546
678
  import { SchemaRenderer } from '@object-ui/react';
547
679
  import '@object-ui/components';
680
+ import '@object-ui/plugin-charts';
681
+ import '@object-ui/plugin-editor';
682
+ import '@object-ui/plugin-kanban';
683
+ import '@object-ui/plugin-markdown';
684
+ import '@object-ui/plugin-form';
685
+ import '@object-ui/plugin-grid';
686
+ import '@object-ui/plugin-view';
548
687
  ${schemaImports.join("\n")}
549
688
  ${layoutImport}
550
689
 
@@ -1269,4 +1408,4 @@ export {
1269
1408
  serve,
1270
1409
  init
1271
1410
  };
1272
- //# sourceMappingURL=chunk-WOV6EOMH.js.map
1411
+ //# sourceMappingURL=chunk-O3QIU2WQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands/serve.ts","../src/utils/app-generator.ts","../src/commands/init.ts"],"sourcesContent":["/**\n * ObjectUI\n * Copyright (c) 2024-present ObjectStack Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { createServer } from 'vite';\nimport react from '@vitejs/plugin-react';\nimport { existsSync, mkdirSync } from 'fs';\nimport { join, resolve, relative } from 'path';\nimport chalk from 'chalk';\nimport { execSync } from 'child_process';\nimport { scanPagesDirectory, createTempAppWithRouting, createTempApp, parseSchemaFile, type RouteInfo } from '../utils/app-generator.js';\n\ninterface ServeOptions {\n port: string;\n host: string;\n}\n\nexport async function serve(schemaPath: string, options: ServeOptions) {\n const cwd = process.cwd();\n \n // Check if pages directory exists for file-system routing\n const pagesDir = join(cwd, 'pages');\n const hasPagesDir = existsSync(pagesDir);\n \n let routes: RouteInfo[] = [];\n let schema: unknown = null;\n let useFileSystemRouting = false;\n\n if (hasPagesDir) {\n // File-system based routing\n console.log(chalk.blue('📁 Detected pages/ directory - using file-system routing'));\n routes = scanPagesDirectory(pagesDir);\n useFileSystemRouting = true;\n \n if (routes.length === 0) {\n throw new Error('No schema files found in pages/ directory');\n }\n \n console.log(chalk.green(`✓ Found ${routes.length} route(s)`));\n routes.forEach(route => {\n console.log(chalk.dim(` ${route.path} → ${relative(cwd, route.filePath)}`));\n });\n } else {\n // Single schema file mode\n const fullSchemaPath = resolve(cwd, schemaPath);\n\n // Check if schema file exists\n if (!existsSync(fullSchemaPath)) {\n throw new Error(`Schema file not found: ${schemaPath}\\nRun 'objectui init' to create a sample schema.`);\n }\n\n console.log(chalk.blue('📋 Loading schema:'), chalk.cyan(schemaPath));\n\n // Read and validate schema\n try {\n schema = parseSchemaFile(fullSchemaPath);\n } catch (error) {\n throw new Error(`Invalid schema file: ${error instanceof Error ? error.message : error}`);\n }\n }\n\n // Create temporary app directory\n const tmpDir = join(cwd, '.objectui-tmp');\n mkdirSync(tmpDir, { recursive: true });\n\n // Create temporary app files\n if (useFileSystemRouting) {\n createTempAppWithRouting(tmpDir, routes);\n } else {\n createTempApp(tmpDir, schema);\n }\n\n // Install dependencies\n console.log(chalk.blue('📦 Installing dependencies...'));\n console.log(chalk.dim(' This may take a moment on first run...'));\n try {\n execSync('npm install --silent --prefer-offline', { \n cwd: tmpDir, \n stdio: 'inherit',\n });\n console.log(chalk.green('✓ Dependencies installed'));\n } catch {\n throw new Error('Failed to install dependencies. Please check your internet connection and try again.');\n }\n\n console.log(chalk.green('✓ Schema loaded successfully'));\n console.log(chalk.blue('🚀 Starting development server...\\n'));\n\n // Create Vite config\n const viteConfig = {\n root: tmpDir,\n server: {\n port: parseInt(options.port),\n host: options.host,\n open: true,\n },\n plugins: [react()],\n };\n\n // Create Vite server\n const server = await createServer(viteConfig);\n\n await server.listen();\n\n const { port, host } = server.config.server;\n const protocol = server.config.server.https ? 'https' : 'http';\n const displayHost = host === '0.0.0.0' ? 'localhost' : host;\n\n console.log();\n console.log(chalk.green('✓ Server started successfully!'));\n console.log();\n console.log(chalk.bold(' Local: ') + chalk.cyan(`${protocol}://${displayHost}:${port}`));\n console.log();\n console.log(chalk.dim(' Press Ctrl+C to stop the server'));\n console.log();\n}\n","/**\n * ObjectUI\n * Copyright (c) 2024-present ObjectStack Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { readFileSync, writeFileSync, mkdirSync, readdirSync, statSync, existsSync } from 'fs';\nimport { join } from 'path';\nimport chalk from 'chalk';\nimport * as yaml from 'js-yaml';\n\nexport interface RouteInfo {\n path: string;\n filePath: string;\n schema: unknown;\n isDynamic: boolean;\n paramName?: string;\n}\n\n// Helper function to check if a file is a supported schema file\nexport function isSupportedSchemaFile(filename: string): boolean {\n return filename.endsWith('.json') || \n filename.endsWith('.yml') ||\n filename.endsWith('.yaml');\n}\n\n// Helper function to extract the base filename without extension\nexport function getBaseFileName(filename: string): string {\n // Remove supported extensions\n return filename\n .replace(/\\.(json|yml|yaml)$/, '');\n}\n\n// Helper function to parse schema file (JSON or YAML)\nexport function parseSchemaFile(filePath: string): unknown {\n const content = readFileSync(filePath, 'utf-8');\n \n if (filePath.endsWith('.json')) {\n return JSON.parse(content);\n } else if (filePath.endsWith('.yml') || filePath.endsWith('.yaml')) {\n return yaml.load(content);\n }\n \n throw new Error(`Unsupported file format: ${filePath}`);\n}\n\nexport function scanPagesDirectory(pagesDir: string): RouteInfo[] {\n const routes: RouteInfo[] = [];\n \n const scanDir = (dir: string, routePrefix: string = '') => {\n const entries = readdirSync(dir);\n \n for (const entry of entries) {\n const fullPath = join(dir, entry);\n const stat = statSync(fullPath);\n \n if (stat.isDirectory()) {\n // Recursively scan subdirectories\n const newPrefix = routePrefix + '/' + entry;\n scanDir(fullPath, newPrefix);\n } else if (isSupportedSchemaFile(entry)) {\n // Process schema file\n const fileName = getBaseFileName(entry);\n let routePath: string;\n let isDynamic = false;\n let paramName: string | undefined;\n \n if (fileName === 'index') {\n // index.schema.json or index.page.json maps to the directory path\n routePath = routePrefix || '/';\n } else if (fileName.startsWith('[') && fileName.endsWith(']')) {\n // Dynamic route: [id].schema.json -> /:id\n paramName = fileName.slice(1, -1);\n routePath = routePrefix + '/:' + paramName;\n isDynamic = true;\n } else {\n // Regular file: about.schema.json -> /about\n routePath = routePrefix + '/' + fileName;\n }\n \n // Read and parse schema\n try {\n const schema = parseSchemaFile(fullPath);\n \n routes.push({\n path: routePath,\n filePath: fullPath,\n schema,\n isDynamic,\n paramName,\n });\n } catch (error) {\n console.warn(chalk.yellow(`⚠ Warning: Failed to parse ${fullPath}: ${error instanceof Error ? error.message : error}`));\n }\n }\n }\n };\n \n scanDir(pagesDir);\n \n // Sort routes: exact routes first, then dynamic routes\n routes.sort((a, b) => {\n if (a.isDynamic && !b.isDynamic) return 1;\n if (!a.isDynamic && b.isDynamic) return -1;\n return a.path.localeCompare(b.path);\n });\n \n return routes;\n}\n\nexport function createTempApp(tmpDir: string, schema: unknown) {\n // Create index.html\n const html = `<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>Object UI App</title>\n </head>\n <body>\n <div id=\"root\"></div>\n <script type=\"module\" src=\"/src/main.tsx\"></script>\n </body>\n</html>`;\n\n writeFileSync(join(tmpDir, 'index.html'), html);\n\n // Create src directory\n const srcDir = join(tmpDir, 'src');\n mkdirSync(srcDir, { recursive: true });\n\n // Create main.tsx\n const mainTsx = `import React from 'react';\nimport ReactDOM from 'react-dom/client';\nimport App from './App';\nimport './index.css';\n\nReactDOM.createRoot(document.getElementById('root')!).render(\n <React.StrictMode>\n <App />\n </React.StrictMode>\n);`;\n\n writeFileSync(join(srcDir, 'main.tsx'), mainTsx);\n\n // Create App.tsx\n const appTsx = `import { SchemaRenderer } from '@object-ui/react';\nimport '@object-ui/components';\nimport '@object-ui/plugin-charts';\nimport '@object-ui/plugin-editor';\nimport '@object-ui/plugin-kanban';\nimport '@object-ui/plugin-markdown';\nimport '@object-ui/plugin-form';\nimport '@object-ui/plugin-grid';\nimport '@object-ui/plugin-view';\n\nconst schema = ${JSON.stringify(schema, null, 2)};\n\nfunction App() {\n return <SchemaRenderer schema={schema} />;\n}\n\nexport default App;`;\n\n writeFileSync(join(srcDir, 'App.tsx'), appTsx);\n\n // Create index.css\n const indexCss = `@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n@layer base {\n :root {\n --background: 0 0% 100%;\n --foreground: 222.2 84% 4.9%;\n --card: 0 0% 100%;\n --card-foreground: 222.2 84% 4.9%;\n --popover: 0 0% 100%;\n --popover-foreground: 222.2 84% 4.9%;\n --primary: 222.2 47.4% 11.2%;\n --primary-foreground: 210 40% 98%;\n --secondary: 210 40% 96.1%;\n --secondary-foreground: 222.2 47.4% 11.2%;\n --muted: 210 40% 96.1%;\n --muted-foreground: 215.4 16.3% 46.9%;\n --accent: 210 40% 96.1%;\n --accent-foreground: 222.2 47.4% 11.2%;\n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 210 40% 98%;\n --border: 214.3 31.8% 91.4%;\n --input: 214.3 31.8% 91.4%;\n --ring: 222.2 84% 4.9%;\n --radius: 0.5rem;\n --chart-1: 12 76% 61%;\n --chart-2: 173 58% 39%;\n --chart-3: 197 37% 24%;\n --chart-4: 43 74% 66%;\n --chart-5: 27 87% 67%;\n }\n\n .dark {\n --background: 222.2 84% 4.9%;\n --foreground: 210 40% 98%;\n --card: 222.2 84% 4.9%;\n --card-foreground: 210 40% 98%;\n --popover: 222.2 84% 4.9%;\n --popover-foreground: 210 40% 98%;\n --primary: 210 40% 98%;\n --primary-foreground: 222.2 47.4% 11.2%;\n --secondary: 217.2 32.6% 17.5%;\n --secondary-foreground: 210 40% 98%;\n --muted: 217.2 32.6% 17.5%;\n --muted-foreground: 215 20.2% 65.1%;\n --accent: 217.2 32.6% 17.5%;\n --accent-foreground: 210 40% 98%;\n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 210 40% 98%;\n --border: 217.2 32.6% 17.5%;\n --input: 217.2 32.6% 17.5%;\n --ring: 212.7 26.8% 83.9%;\n --chart-1: 220 70% 50%;\n --chart-2: 160 60% 45%;\n --chart-3: 30 80% 55%;\n --chart-4: 280 65% 60%;\n --chart-5: 340 75% 55%;\n }\n}\n\n@layer base {\n * {\n @apply border-border;\n }\n body {\n @apply bg-background text-foreground;\n }\n}`;\n\n writeFileSync(join(srcDir, 'index.css'), indexCss);\n\n // Create tailwind.config.js\n const tailwindConfig = `/** @type {import('tailwindcss').Config} */\nexport default {\n darkMode: ['class'],\n content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],\n theme: {\n extend: {\n borderRadius: {\n lg: 'var(--radius)',\n md: 'calc(var(--radius) - 2px)',\n sm: 'calc(var(--radius) - 4px)',\n },\n colors: {\n background: 'hsl(var(--background))',\n foreground: 'hsl(var(--foreground))',\n card: {\n DEFAULT: 'hsl(var(--card))',\n foreground: 'hsl(var(--card-foreground))',\n },\n popover: {\n DEFAULT: 'hsl(var(--popover))',\n foreground: 'hsl(var(--popover-foreground))',\n },\n primary: {\n DEFAULT: 'hsl(var(--primary))',\n foreground: 'hsl(var(--primary-foreground))',\n },\n secondary: {\n DEFAULT: 'hsl(var(--secondary))',\n foreground: 'hsl(var(--secondary-foreground))',\n },\n muted: {\n DEFAULT: 'hsl(var(--muted))',\n foreground: 'hsl(var(--muted-foreground))',\n },\n accent: {\n DEFAULT: 'hsl(var(--accent))',\n foreground: 'hsl(var(--accent-foreground))',\n },\n destructive: {\n DEFAULT: 'hsl(var(--destructive))',\n foreground: 'hsl(var(--destructive-foreground))',\n },\n border: 'hsl(var(--border))',\n input: 'hsl(var(--input))',\n ring: 'hsl(var(--ring))',\n chart: {\n 1: 'hsl(var(--chart-1))',\n 2: 'hsl(var(--chart-2))',\n 3: 'hsl(var(--chart-3))',\n 4: 'hsl(var(--chart-4))',\n 5: 'hsl(var(--chart-5))',\n },\n },\n },\n },\n plugins: [],\n};`;\n\n const cwd = process.cwd();\n const isMonorepo = existsSync(join(cwd, 'pnpm-workspace.yaml'));\n\n // Define Tailwind Content Paths\n // Include JSON files specifically\n const contentPaths = [\"'./index.html'\", \"'./src/**/*.{js,ts,jsx,tsx,json}'\"];\n if (isMonorepo) {\n const componentsPath = join(cwd, 'packages/components/src/**/*.{ts,tsx}');\n const pluginsPath = join(cwd, 'packages/plugin-*/src/**/*.{ts,tsx}');\n contentPaths.push(`'${componentsPath}'`);\n contentPaths.push(`'${pluginsPath}'`); \n }\n\n // Create tailwind.config.js\n const finalTailwindConfig = `/** @type {import('tailwindcss').Config} */\nexport default {\n darkMode: ['class'],\n content: [${contentPaths.join(', ')}],\n theme: {\n extend: {\n borderRadius: {\n lg: 'var(--radius)',\n md: 'calc(var(--radius) - 2px)',\n sm: 'calc(var(--radius) - 4px)',\n },\n colors: {\n background: 'hsl(var(--background))',\n foreground: 'hsl(var(--foreground))',\n card: {\n DEFAULT: 'hsl(var(--card))',\n foreground: 'hsl(var(--card-foreground))',\n },\n popover: {\n DEFAULT: 'hsl(var(--popover))',\n foreground: 'hsl(var(--popover-foreground))',\n },\n primary: {\n DEFAULT: 'hsl(var(--primary))',\n foreground: 'hsl(var(--primary-foreground))',\n },\n secondary: {\n DEFAULT: 'hsl(var(--secondary))',\n foreground: 'hsl(var(--secondary-foreground))',\n },\n muted: {\n DEFAULT: 'hsl(var(--muted))',\n foreground: 'hsl(var(--muted-foreground))',\n },\n accent: {\n DEFAULT: 'hsl(var(--accent))',\n foreground: 'hsl(var(--accent-foreground))',\n },\n destructive: {\n DEFAULT: 'hsl(var(--destructive))',\n foreground: 'hsl(var(--destructive-foreground))',\n },\n border: 'hsl(var(--border))',\n input: 'hsl(var(--input))',\n ring: 'hsl(var(--ring))',\n chart: {\n 1: 'hsl(var(--chart-1))',\n 2: 'hsl(var(--chart-2))',\n 3: 'hsl(var(--chart-3))',\n 4: 'hsl(var(--chart-4))',\n 5: 'hsl(var(--chart-5))',\n },\n },\n },\n },\n plugins: [],\n};`;\n\n writeFileSync(join(tmpDir, 'tailwind.config.js'), finalTailwindConfig);\n\n // Create postcss.config.js\n const finalPostcssConfig = `export default {\n plugins: {\n tailwindcss: {},\n autoprefixer: {},\n },\n};`;\n \n writeFileSync(join(tmpDir, 'postcss.config.js'), finalPostcssConfig);\n\n // Create package.json\n const baseDependencies = {\n react: '^18.3.1',\n 'react-dom': '^18.3.1',\n '@object-ui/react': '^0.1.0',\n '@object-ui/components': '^0.1.0',\n };\n\n const baseDevDependencies = {\n '@types/react': '^18.3.12',\n '@types/react-dom': '^18.3.1',\n '@vitejs/plugin-react': '^4.2.1',\n autoprefixer: '^10.4.23',\n postcss: '^8.5.6',\n tailwindcss: '^3.4.19',\n typescript: '~5.7.3',\n vite: '^5.0.0',\n };\n\n const packageJson = {\n name: 'objectui-temp-app',\n private: true,\n type: 'module',\n // In monorepo, we use root node_modules, so we don't need dependencies here\n dependencies: isMonorepo ? {} : baseDependencies,\n devDependencies: isMonorepo ? {} : baseDevDependencies,\n };\n\n writeFileSync(join(tmpDir, 'package.json'), JSON.stringify(packageJson, null, 2));\n\n // Create tsconfig.json\n const tsconfig = {\n compilerOptions: {\n target: 'ES2020',\n useDefineForClassFields: true,\n lib: ['ES2020', 'DOM', 'DOM.Iterable'],\n module: 'ESNext',\n skipLibCheck: true,\n moduleResolution: 'bundler',\n allowImportingTsExtensions: true,\n resolveJsonModule: true,\n isolatedModules: true,\n noEmit: true,\n jsx: 'react-jsx',\n strict: true,\n noUnusedLocals: true,\n noUnusedParameters: true,\n noFallthroughCasesInSwitch: true,\n },\n include: ['src'],\n };\n\n writeFileSync(join(tmpDir, 'tsconfig.json'), JSON.stringify(tsconfig, null, 2));\n}\n\nexport function createTempAppWithRouting(tmpDir: string, routes: RouteInfo[], appConfig?: unknown) {\n // Create index.html\n const html = `<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n <title>${(appConfig as any)?.title || 'Object UI App'}</title>\n </head>\n <body>\n <div id=\"root\"></div>\n <script type=\"module\" src=\"/src/main.tsx\"></script>\n </body>\n</html>`;\n\n writeFileSync(join(tmpDir, 'index.html'), html);\n\n // Create src directory\n const srcDir = join(tmpDir, 'src');\n mkdirSync(srcDir, { recursive: true });\n\n // Create schemas directory and copy all schemas\n const schemasDir = join(srcDir, 'schemas');\n mkdirSync(schemasDir, { recursive: true });\n \n const schemaImports: string[] = [];\n const routeComponents: string[] = [];\n \n routes.forEach((route, index) => {\n const schemaVarName = `schema${index}`;\n const schemaFileName = `page${index}.json`;\n \n // Write schema to schemas directory\n writeFileSync(\n join(schemasDir, schemaFileName),\n JSON.stringify(route.schema, null, 2)\n );\n \n // Add import statement\n schemaImports.push(`import ${schemaVarName} from './schemas/${schemaFileName}';`);\n \n // Add route component\n routeComponents.push(` <Route path=\"${route.path}\" element={<SchemaRenderer schema={${schemaVarName}} />} />`);\n });\n\n // Create theme-provider.tsx\n const themeProviderTsx = `import { createContext, useContext, useEffect, useState } from \"react\"\n\ntype Theme = \"dark\" | \"light\" | \"system\"\n\ntype ThemeProviderProps = {\n children: React.ReactNode\n defaultTheme?: Theme\n storageKey?: string\n}\n\ntype ThemeProviderState = {\n theme: Theme\n setTheme: (theme: Theme) => void\n}\n\nconst initialState: ThemeProviderState = {\n theme: \"system\",\n setTheme: () => null,\n}\n\nconst ThemeProviderContext = createContext<ThemeProviderState>(initialState)\n\nexport function ThemeProvider({\n children,\n defaultTheme = \"system\",\n storageKey = \"vite-ui-theme\",\n ...props\n}: ThemeProviderProps) {\n const [theme, setTheme] = useState<Theme>(\n () => (localStorage.getItem(storageKey) as Theme) || defaultTheme\n )\n\n useEffect(() => {\n const root = window.document.documentElement\n\n root.classList.remove(\"light\", \"dark\")\n\n if (theme === \"system\") {\n const systemTheme = window.matchMedia(\"(prefers-color-scheme: dark)\")\n .matches\n ? \"dark\"\n : \"light\"\n\n root.classList.add(systemTheme)\n return\n }\n\n root.classList.add(theme)\n }, [theme])\n\n const value = {\n theme,\n setTheme: (theme: Theme) => {\n localStorage.setItem(storageKey, theme)\n setTheme(theme)\n },\n }\n\n return (\n <ThemeProviderContext.Provider {...props} value={value}>\n {children}\n </ThemeProviderContext.Provider>\n )\n}\n\nexport const useTheme = () => {\n const context = useContext(ThemeProviderContext)\n\n if (context === undefined)\n throw new Error(\"useTheme must be used within a ThemeProvider\")\n\n return context\n}`;\n writeFileSync(join(srcDir, 'theme-provider.tsx'), themeProviderTsx);\n\n // Create main.tsx\n const mainTsx = `import React from 'react';\nimport ReactDOM from 'react-dom/client';\nimport App from './App';\nimport './index.css';\nimport { ThemeProvider } from \"./theme-provider\"\n\nReactDOM.createRoot(document.getElementById('root')!).render(\n <React.StrictMode>\n <ThemeProvider defaultTheme=\"dark\" storageKey=\"vite-ui-theme\">\n <App />\n </ThemeProvider>\n </React.StrictMode>\n);`;\n\n writeFileSync(join(srcDir, 'main.tsx'), mainTsx);\n\n // Generate Layout Code if appConfig is present\n let layoutImport = '';\n let layoutWrapperStart = '';\n let layoutWrapperEnd = '';\n \n if (appConfig) {\n // Very basic Layout implementation for now\n // Logic: If appConfig is present, current version assumes it's just a config object, \n // but we need a Layout component that renders navigation.\n // Since we don't have a Layout component in @object-ui/components yet, we generate a simple one.\n\n const layoutCode = `\nimport { Link, useLocation } from 'react-router-dom';\nimport * as LucideIcons from 'lucide-react';\nimport { Moon, Sun } from \"lucide-react\"\nimport { useTheme } from \"./theme-provider\"\nimport { \n cn,\n Button,\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n SidebarProvider,\n Sidebar,\n SidebarContent,\n SidebarFooter,\n SidebarHeader,\n SidebarRail,\n SidebarGroup,\n SidebarGroupContent,\n SidebarGroupLabel,\n SidebarMenu,\n SidebarMenuItem,\n SidebarMenuButton,\n SidebarMenuSub,\n SidebarMenuSubItem,\n SidebarMenuSubButton,\n SidebarInset,\n SidebarTrigger,\n Separator,\n Collapsible,\n CollapsibleTrigger,\n CollapsibleContent\n} from '@object-ui/components'; \n\nconst DynamicIcon = ({ name, className }) => {\n // @ts-expect-error - Dynamic icon lookup from Lucide icons\n const Icon = LucideIcons[name];\n if (!Icon) return null;\n return <Icon className={className} />;\n};\n\nexport function ModeToggle() {\n const { setTheme } = useTheme()\n\n return (\n <DropdownMenu>\n <DropdownMenuTrigger asChild>\n <SidebarMenuButton size=\"lg\" className=\"data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground\">\n <div className=\"flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground\">\n <Sun className=\"h-4 w-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0\" />\n <Moon className=\"absolute h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100\" />\n </div>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-semibold\">Switch Theme</span>\n <span className=\"truncate text-xs\">Light / Dark</span>\n </div>\n <LucideIcons.ChevronsUpDown className=\"ml-auto size-4\" />\n </SidebarMenuButton>\n </DropdownMenuTrigger>\n <DropdownMenuContent className=\"w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-lg\" side=\"bottom\" align=\"end\" sideOffset={4}>\n <DropdownMenuItem onClick={() => setTheme(\"light\")}>\n <LucideIcons.Sun className=\"mr-2 size-4\" />\n Light\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => setTheme(\"dark\")}>\n <LucideIcons.Moon className=\"mr-2 size-4\" />\n Dark\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => setTheme(\"system\")}>\n <LucideIcons.Monitor className=\"mr-2 size-4\" />\n System\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n )\n}\n\nconst AppLayout = ({ app, children }) => {\n const location = useLocation();\n const menu = app.menu || [];\n \n return (\n <SidebarProvider>\n <Sidebar collapsible=\"icon\">\n <SidebarHeader>\n <div className=\"flex items-center gap-2 px-2 py-2\">\n <div className=\"flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground\">\n {app.logo && <DynamicIcon name={app.logo} className=\"size-4\" />}\n {!app.logo && <span className=\"text-xl font-bold\">O</span>}\n </div>\n <div className=\"grid flex-1 text-left text-sm leading-tight\">\n <span className=\"truncate font-semibold\">{app.title || \"Object UI\"}</span>\n <span className=\"truncate text-xs\">Showcase</span>\n </div>\n </div>\n </SidebarHeader>\n <SidebarContent>\n <SidebarGroup>\n <SidebarMenu>\n {menu.map((item, idx) => {\n // Collapsible Item (Children present)\n if (item.children && item.children.length > 0) {\n const isActive = item.children.some(child => child.path === location.pathname);\n return (\n <Collapsible key={idx} asChild defaultOpen={isActive} className=\"group/collapsible\">\n <SidebarMenuItem>\n <CollapsibleTrigger asChild>\n <SidebarMenuButton tooltip={item.label}>\n {item.icon && <DynamicIcon name={item.icon} />}\n <span>{item.label}</span>\n <DynamicIcon name=\"ChevronRight\" className=\"ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90\" />\n </SidebarMenuButton>\n </CollapsibleTrigger>\n <CollapsibleContent>\n <SidebarMenuSub>\n {item.children.map((child, cIdx) => (\n <SidebarMenuSubItem key={cIdx}>\n <SidebarMenuSubButton asChild isActive={location.pathname === child.path}>\n <Link to={child.path || '#'}>\n <span>{child.label}</span>\n </Link>\n </SidebarMenuSubButton>\n </SidebarMenuSubItem>\n ))}\n </SidebarMenuSub>\n </CollapsibleContent>\n </SidebarMenuItem>\n </Collapsible>\n );\n }\n\n // Single Item\n if (item.path) {\n return (\n <SidebarMenuItem key={idx}>\n <SidebarMenuButton asChild isActive={location.pathname === item.path} tooltip={item.label}>\n <Link to={item.path}>\n {item.icon && <DynamicIcon name={item.icon} />}\n <span>{item.label}</span>\n </Link>\n </SidebarMenuButton>\n </SidebarMenuItem>\n );\n }\n return null;\n })}\n </SidebarMenu>\n </SidebarGroup>\n </SidebarContent>\n <SidebarFooter>\n <SidebarMenu>\n <SidebarMenuItem>\n <ModeToggle />\n </SidebarMenuItem>\n </SidebarMenu>\n </SidebarFooter>\n <SidebarRail />\n </Sidebar>\n \n <SidebarInset>\n <header className=\"flex h-16 shrink-0 items-center gap-2 border-b bg-background px-4\">\n <SidebarTrigger className=\"-ml-1\" />\n <Separator orientation=\"vertical\" className=\"mr-2 h-4\" />\n <div className=\"flex flex-1 items-center justify-between\">\n <span className=\"font-medium\">{app.title}</span>\n </div>\n </header>\n <div className=\"flex-1 flex flex-col min-h-0 bg-muted/20 p-4\">\n <div className=\"mx-auto max-w-full w-full\">\n {children}\n </div>\n </div>\n </SidebarInset>\n </SidebarProvider>\n );\n};\n\nexport default AppLayout;\n`;\n writeFileSync(join(srcDir, 'Layout.tsx'), layoutCode);\n \n layoutImport = `import AppLayout from './Layout';\\nconst appConfig = ${JSON.stringify(appConfig)};`;\n layoutWrapperStart = `<AppLayout app={appConfig}>`;\n layoutWrapperEnd = `</AppLayout>`;\n }\n\n // Create App.tsx with routing\n const appTsx = `import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';\nimport { SchemaRenderer } from '@object-ui/react';\nimport '@object-ui/components';\nimport '@object-ui/plugin-charts';\nimport '@object-ui/plugin-editor';\nimport '@object-ui/plugin-kanban';\nimport '@object-ui/plugin-markdown';\nimport '@object-ui/plugin-form';\nimport '@object-ui/plugin-grid';\nimport '@object-ui/plugin-view';\n${schemaImports.join('\\n')}\n${layoutImport}\n\nfunction App() {\n return (\n <BrowserRouter>\n ${layoutWrapperStart}\n <Routes>\n${routeComponents.join('\\n')}\n </Routes>\n ${layoutWrapperEnd}\n </BrowserRouter>\n );\n}\n\nexport default App;`;\n\n writeFileSync(join(srcDir, 'App.tsx'), appTsx);\n\n // Create index.css with Tailwind\n const indexCss = `@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n@layer base {\n :root {\n --background: 0 0% 100%;\n --foreground: 222.2 84% 4.9%;\n --card: 0 0% 100%;\n --card-foreground: 222.2 84% 4.9%;\n --popover: 0 0% 100%;\n --popover-foreground: 222.2 84% 4.9%;\n --primary: 222.2 47.4% 11.2%;\n --primary-foreground: 210 40% 98%;\n --secondary: 210 40% 96.1%;\n --secondary-foreground: 222.2 47.4% 11.2%;\n --muted: 210 40% 96.1%;\n --muted-foreground: 215.4 16.3% 46.9%;\n --accent: 210 40% 96.1%;\n --accent-foreground: 222.2 47.4% 11.2%;\n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 210 40% 98%;\n --border: 214.3 31.8% 91.4%;\n --input: 214.3 31.8% 91.4%;\n --ring: 222.2 84% 4.9%;\n --radius: 0.5rem;\n --chart-1: 12 76% 61%;\n --chart-2: 173 58% 39%;\n --chart-3: 197 37% 24%;\n --chart-4: 43 74% 66%;\n --chart-5: 27 87% 67%;\n }\n\n .dark {\n --background: 222.2 84% 4.9%;\n --foreground: 210 40% 98%;\n --card: 222.2 84% 4.9%;\n --card-foreground: 210 40% 98%;\n --popover: 222.2 84% 4.9%;\n --popover-foreground: 210 40% 98%;\n --primary: 210 40% 98%;\n --primary-foreground: 222.2 47.4% 11.2%;\n --secondary: 217.2 32.6% 17.5%;\n --secondary-foreground: 210 40% 98%;\n --muted: 217.2 32.6% 17.5%;\n --muted-foreground: 215 20.2% 65.1%;\n --accent: 217.2 32.6% 17.5%;\n --accent-foreground: 210 40% 98%;\n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 210 40% 98%;\n --border: 217.2 32.6% 17.5%;\n --input: 217.2 32.6% 17.5%;\n --ring: 212.7 26.8% 83.9%;\n --chart-1: 220 70% 50%;\n --chart-2: 160 60% 45%;\n --chart-3: 30 80% 55%;\n --chart-4: 280 65% 60%;\n --chart-5: 340 75% 55%;\n }\n}\n\n@layer base {\n * {\n @apply border-border;\n }\n body {\n @apply bg-background text-foreground font-sans antialiased min-h-screen;\n }\n}`;\n\n writeFileSync(join(srcDir, 'index.css'), indexCss);\n\n const cwd = process.cwd();\n const isMonorepo = existsSync(join(cwd, 'pnpm-workspace.yaml'));\n\n // Define Tailwind Content Paths\n // Include JSON files specifically\n const contentPaths = [\"'./index.html'\", \"'./src/**/*.{js,ts,jsx,tsx,json}'\"];\n if (isMonorepo) {\n const componentsPath = join(cwd, 'packages/components/src/**/*.{ts,tsx}');\n const pluginsPath = join(cwd, 'packages/plugin-*/src/**/*.{ts,tsx}');\n contentPaths.push(`'${componentsPath}'`);\n contentPaths.push(`'${pluginsPath}'`); \n }\n\n // Create tailwind.config.js\n const tailwindConfig = `/** @type {import('tailwindcss').Config} */\nexport default {\n darkMode: ['class'],\n content: [${contentPaths.join(', ')}],\n theme: {\n extend: {\n borderRadius: {\n lg: 'var(--radius)',\n md: 'calc(var(--radius) - 2px)',\n sm: 'calc(var(--radius) - 4px)',\n },\n colors: {\n background: 'hsl(var(--background))',\n foreground: 'hsl(var(--foreground))',\n card: {\n DEFAULT: 'hsl(var(--card))',\n foreground: 'hsl(var(--card-foreground))',\n },\n popover: {\n DEFAULT: 'hsl(var(--popover))',\n foreground: 'hsl(var(--popover-foreground))',\n },\n primary: {\n DEFAULT: 'hsl(var(--primary))',\n foreground: 'hsl(var(--primary-foreground))',\n },\n secondary: {\n DEFAULT: 'hsl(var(--secondary))',\n foreground: 'hsl(var(--secondary-foreground))',\n },\n muted: {\n DEFAULT: 'hsl(var(--muted))',\n foreground: 'hsl(var(--muted-foreground))',\n },\n accent: {\n DEFAULT: 'hsl(var(--accent))',\n foreground: 'hsl(var(--accent-foreground))',\n },\n destructive: {\n DEFAULT: 'hsl(var(--destructive))',\n foreground: 'hsl(var(--destructive-foreground))',\n },\n border: 'hsl(var(--border))',\n input: 'hsl(var(--input))',\n ring: 'hsl(var(--ring))',\n chart: {\n 1: 'hsl(var(--chart-1))',\n 2: 'hsl(var(--chart-2))',\n 3: 'hsl(var(--chart-3))',\n 4: 'hsl(var(--chart-4))',\n 5: 'hsl(var(--chart-5))',\n },\n },\n },\n },\n plugins: [],\n};`;\n\n writeFileSync(join(tmpDir, 'tailwind.config.js'), tailwindConfig);\n\n // Create postcss.config.js\n const postcssConfig = `export default {\n plugins: {\n tailwindcss: {},\n autoprefixer: {},\n },\n};`;\n \n writeFileSync(join(tmpDir, 'postcss.config.js'), postcssConfig);\n\n // Create package.json with react-router-dom\n const packageJson = {\n name: 'objectui-temp-app',\n private: true,\n type: 'module',\n dependencies: {\n react: '^18.3.1',\n 'react-dom': '^18.3.1',\n 'react-router-dom': '^7.12.0',\n '@object-ui/react': '^0.1.0',\n '@object-ui/components': '^0.1.0',\n },\n devDependencies: {\n '@types/react': '^18.3.12',\n '@types/react-dom': '^18.3.1',\n '@vitejs/plugin-react': '^4.2.1',\n autoprefixer: '^10.4.23',\n postcss: '^8.5.6',\n tailwindcss: '^3.4.19',\n typescript: '~5.7.3',\n vite: '^5.0.0',\n },\n };\n\n writeFileSync(join(tmpDir, 'package.json'), JSON.stringify(packageJson, null, 2));\n\n // Create tsconfig.json\n const tsconfig = {\n compilerOptions: {\n target: 'ES2020',\n useDefineForClassFields: true,\n lib: ['ES2020', 'DOM', 'DOM.Iterable'],\n module: 'ESNext',\n skipLibCheck: true,\n moduleResolution: 'bundler',\n allowImportingTsExtensions: true,\n resolveJsonModule: true,\n isolatedModules: true,\n noEmit: true,\n jsx: 'react-jsx',\n strict: true,\n noUnusedLocals: true,\n noUnusedParameters: true,\n noFallthroughCasesInSwitch: true,\n },\n include: ['src'],\n };\n\n writeFileSync(join(tmpDir, 'tsconfig.json'), JSON.stringify(tsconfig, null, 2));\n}\n","/**\n * ObjectUI\n * Copyright (c) 2024-present ObjectStack Inc.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n */\n\nimport { existsSync, writeFileSync, mkdirSync } from 'fs';\nimport { join } from 'path';\nimport chalk from 'chalk';\n\ninterface InitOptions {\n template: string;\n}\n\nconst templates = {\n simple: {\n type: 'div',\n className: 'min-h-screen flex items-center justify-center bg-gradient-to-br from-blue-50 to-indigo-100',\n body: {\n type: 'card',\n className: 'w-full max-w-md shadow-lg',\n title: 'Welcome to Object UI',\n description: 'Start building your application with JSON schemas',\n body: {\n type: 'div',\n className: 'p-6 space-y-4',\n body: [\n {\n type: 'text',\n content: 'This is a simple example. Edit app.json to customize your application.',\n className: 'text-sm text-muted-foreground',\n },\n {\n type: 'button',\n label: 'Get Started',\n className: 'w-full',\n },\n ],\n },\n },\n },\n form: {\n type: 'div',\n className: 'min-h-screen flex items-center justify-center bg-gradient-to-br from-purple-50 to-pink-100 p-4',\n body: {\n type: 'card',\n className: 'w-full max-w-2xl shadow-xl',\n title: 'Contact Form',\n description: 'Fill out the form below to get in touch',\n body: {\n type: 'div',\n className: 'p-6 space-y-6',\n body: [\n {\n type: 'div',\n className: 'grid grid-cols-2 gap-4',\n body: [\n {\n type: 'input',\n label: 'First Name',\n placeholder: 'John',\n required: true,\n },\n {\n type: 'input',\n label: 'Last Name',\n placeholder: 'Doe',\n required: true,\n },\n ],\n },\n {\n type: 'input',\n label: 'Email Address',\n inputType: 'email',\n placeholder: 'john.doe@example.com',\n required: true,\n },\n {\n type: 'input',\n label: 'Phone Number',\n inputType: 'tel',\n placeholder: '+1 (555) 000-0000',\n },\n {\n type: 'textarea',\n label: 'Message',\n placeholder: 'Tell us what you need...',\n rows: 4,\n },\n {\n type: 'div',\n className: 'flex gap-3',\n body: [\n {\n type: 'button',\n label: 'Submit',\n className: 'flex-1',\n },\n {\n type: 'button',\n label: 'Reset',\n variant: 'outline',\n className: 'flex-1',\n },\n ],\n },\n ],\n },\n },\n },\n dashboard: {\n type: 'div',\n className: 'min-h-screen bg-muted/10',\n body: [\n {\n type: 'div',\n className: 'border-b bg-background',\n body: {\n type: 'div',\n className: 'container mx-auto px-6 py-4',\n body: {\n type: 'div',\n className: 'flex items-center justify-between',\n body: [\n {\n type: 'div',\n className: 'text-2xl font-bold',\n body: { type: 'text', content: 'Dashboard' },\n },\n {\n type: 'button',\n label: 'New Item',\n size: 'sm',\n },\n ],\n },\n },\n },\n {\n type: 'div',\n className: 'container mx-auto p-6 space-y-6',\n body: [\n {\n type: 'div',\n className: 'grid gap-4 md:grid-cols-2 lg:grid-cols-4',\n body: [\n {\n type: 'card',\n className: 'shadow-sm',\n body: [\n {\n type: 'div',\n className: 'p-6 pb-2',\n body: {\n type: 'div',\n className: 'text-sm font-medium text-muted-foreground',\n body: { type: 'text', content: 'Total Revenue' },\n },\n },\n {\n type: 'div',\n className: 'p-6 pt-0',\n body: [\n {\n type: 'div',\n className: 'text-2xl font-bold',\n body: { type: 'text', content: '$45,231.89' },\n },\n {\n type: 'div',\n className: 'text-xs text-muted-foreground mt-1',\n body: { type: 'text', content: '+20.1% from last month' },\n },\n ],\n },\n ],\n },\n {\n type: 'card',\n className: 'shadow-sm',\n body: [\n {\n type: 'div',\n className: 'p-6 pb-2',\n body: {\n type: 'div',\n className: 'text-sm font-medium text-muted-foreground',\n body: { type: 'text', content: 'Active Users' },\n },\n },\n {\n type: 'div',\n className: 'p-6 pt-0',\n body: [\n {\n type: 'div',\n className: 'text-2xl font-bold',\n body: { type: 'text', content: '+2,350' },\n },\n {\n type: 'div',\n className: 'text-xs text-muted-foreground mt-1',\n body: { type: 'text', content: '+180.1% from last month' },\n },\n ],\n },\n ],\n },\n {\n type: 'card',\n className: 'shadow-sm',\n body: [\n {\n type: 'div',\n className: 'p-6 pb-2',\n body: {\n type: 'div',\n className: 'text-sm font-medium text-muted-foreground',\n body: { type: 'text', content: 'Sales' },\n },\n },\n {\n type: 'div',\n className: 'p-6 pt-0',\n body: [\n {\n type: 'div',\n className: 'text-2xl font-bold',\n body: { type: 'text', content: '+12,234' },\n },\n {\n type: 'div',\n className: 'text-xs text-muted-foreground mt-1',\n body: { type: 'text', content: '+19% from last month' },\n },\n ],\n },\n ],\n },\n {\n type: 'card',\n className: 'shadow-sm',\n body: [\n {\n type: 'div',\n className: 'p-6 pb-2',\n body: {\n type: 'div',\n className: 'text-sm font-medium text-muted-foreground',\n body: { type: 'text', content: 'Active Now' },\n },\n },\n {\n type: 'div',\n className: 'p-6 pt-0',\n body: [\n {\n type: 'div',\n className: 'text-2xl font-bold',\n body: { type: 'text', content: '+573' },\n },\n {\n type: 'div',\n className: 'text-xs text-muted-foreground mt-1',\n body: { type: 'text', content: '+201 since last hour' },\n },\n ],\n },\n ],\n },\n ],\n },\n {\n type: 'card',\n className: 'shadow-sm',\n title: 'Recent Activity',\n description: 'Your latest updates and notifications',\n body: {\n type: 'div',\n className: 'p-6 pt-0 space-y-4',\n body: [\n {\n type: 'div',\n className: 'flex items-center gap-4 border-b pb-4',\n body: [\n {\n type: 'div',\n className: 'flex-1',\n body: [\n {\n type: 'div',\n className: 'font-medium',\n body: { type: 'text', content: 'New user registration' },\n },\n {\n type: 'div',\n className: 'text-sm text-muted-foreground',\n body: { type: 'text', content: '2 minutes ago' },\n },\n ],\n },\n ],\n },\n {\n type: 'div',\n className: 'flex items-center gap-4 border-b pb-4',\n body: [\n {\n type: 'div',\n className: 'flex-1',\n body: [\n {\n type: 'div',\n className: 'font-medium',\n body: { type: 'text', content: 'Payment received' },\n },\n {\n type: 'div',\n className: 'text-sm text-muted-foreground',\n body: { type: 'text', content: '15 minutes ago' },\n },\n ],\n },\n ],\n },\n {\n type: 'div',\n className: 'flex items-center gap-4',\n body: [\n {\n type: 'div',\n className: 'flex-1',\n body: [\n {\n type: 'div',\n className: 'font-medium',\n body: { type: 'text', content: 'New order placed' },\n },\n {\n type: 'div',\n className: 'text-sm text-muted-foreground',\n body: { type: 'text', content: '1 hour ago' },\n },\n ],\n },\n ],\n },\n ],\n },\n },\n ],\n },\n ],\n },\n};\n\nexport async function init(name: string, options: InitOptions) {\n const cwd = process.cwd();\n const projectDir = join(cwd, name);\n\n // Check if directory already exists\n if (existsSync(projectDir) && name !== '.') {\n throw new Error(`Directory \"${name}\" already exists. Please choose a different name.`);\n }\n\n const targetDir = name === '.' ? cwd : projectDir;\n\n // Create project directory if needed\n if (name !== '.') {\n mkdirSync(projectDir, { recursive: true });\n }\n\n console.log(chalk.blue('🎨 Creating Object UI application...'));\n console.log(chalk.dim(` Template: ${options.template}`));\n console.log();\n\n // Get template\n const template = templates[options.template as keyof typeof templates];\n if (!template) {\n throw new Error(\n `Unknown template: ${options.template}\\nAvailable templates: ${Object.keys(templates).join(', ')}`\n );\n }\n\n // Create schema file\n const schemaPath = join(targetDir, 'app.json');\n writeFileSync(schemaPath, JSON.stringify(template, null, 2));\n\n console.log(chalk.green('✓ Created app.json'));\n\n // Create README\n const readme = `# ${name}\n\nA Object UI application built from JSON schemas.\n\n## Getting Started\n\n1. Install Object UI CLI globally (if you haven't already):\n \\`\\`\\`bash\n npm install -g @object-ui/cli\n \\`\\`\\`\n\n2. Start the development server:\n \\`\\`\\`bash\n objectui serve app.json\n \\`\\`\\`\n\n3. Open your browser and visit http://localhost:3000\n\n## Customize Your App\n\nEdit \\`app.json\\` to customize your application. The dev server will automatically reload when you save changes.\n\n## Available Templates\n\n- **simple**: A minimal getting started template\n- **form**: A contact form example\n- **dashboard**: A full dashboard with metrics and activity feed\n\n## Learn More\n\n- [Object UI Documentation](https://www.objectui.org)\n- [Schema Reference](https://www.objectui.org/docs/protocol/overview)\n- [Component Library](https://www.objectui.org/docs/api/components)\n\n## Commands\n\n- \\`objectui serve [schema]\\` - Start development server\n- \\`objectui init [name]\\` - Create a new application\n\nBuilt with ❤️ using [Object UI](https://www.objectui.org)\n`;\n\n writeFileSync(join(targetDir, 'README.md'), readme);\n console.log(chalk.green('✓ Created README.md'));\n\n // Create .gitignore\n const gitignore = `.objectui-tmp\nnode_modules\ndist\n.DS_Store\n*.log\n`;\n\n writeFileSync(join(targetDir, '.gitignore'), gitignore);\n console.log(chalk.green('✓ Created .gitignore'));\n\n console.log();\n console.log(chalk.green('✨ Application created successfully!'));\n console.log();\n console.log(chalk.bold('Next steps:'));\n console.log();\n if (name !== '.') {\n console.log(chalk.cyan(` cd ${name}`));\n }\n console.log(chalk.cyan(' objectui serve app.json'));\n console.log();\n console.log(chalk.dim(' The development server will start on http://localhost:3000'));\n console.log();\n}\n"],"mappings":"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","names":["existsSync","mkdirSync","join","chalk","join","existsSync","chalk","mkdirSync","existsSync","writeFileSync","mkdirSync","join","chalk"]}