@nqlib/nqui 0.4.3 → 0.4.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.
Files changed (156) hide show
  1. package/INSTALLATION.md +234 -0
  2. package/README.md +109 -151
  3. package/dist/button-CJHdCq9I.js +155 -0
  4. package/dist/button-R304rhsj.cjs +1 -0
  5. package/dist/calendar.cjs.js +1 -1
  6. package/dist/calendar.es.js +1 -1
  7. package/dist/carousel-D1FMVglR.cjs +1 -0
  8. package/dist/carousel-U7RZhYZj.js +179 -0
  9. package/dist/carousel.cjs.js +1 -1
  10. package/dist/carousel.es.js +1 -1
  11. package/dist/command-palette-DCtLpM3Q.js +694 -0
  12. package/dist/command-palette-MHc03bBf.cjs +5 -0
  13. package/dist/command.cjs.js +1 -1
  14. package/dist/command.es.js +1 -1
  15. package/dist/components/custom/color-picker.d.ts +1 -1
  16. package/dist/components/custom/color-picker.d.ts.map +1 -1
  17. package/dist/components/custom/color-slider.d.ts +4 -10
  18. package/dist/components/custom/color-slider.d.ts.map +1 -1
  19. package/dist/components/custom/enhanced-radio-group.d.ts +13 -4
  20. package/dist/components/custom/enhanced-radio-group.d.ts.map +1 -1
  21. package/dist/components/custom/enhanced-tabs.d.ts.map +1 -1
  22. package/dist/components/debug/debug-features.d.ts +29 -0
  23. package/dist/components/debug/debug-features.d.ts.map +1 -0
  24. package/dist/components/debug/debug-panel.d.ts.map +1 -1
  25. package/dist/components/error-boundary.d.ts +20 -0
  26. package/dist/components/error-boundary.d.ts.map +1 -0
  27. package/dist/components/index.d.ts +103 -0
  28. package/dist/components/index.d.ts.map +1 -0
  29. package/dist/components/ui/badge.d.ts +16 -5
  30. package/dist/components/ui/badge.d.ts.map +1 -1
  31. package/dist/components/ui/button.d.ts +38 -4
  32. package/dist/components/ui/button.d.ts.map +1 -1
  33. package/dist/components/ui/checkbox.d.ts +16 -2
  34. package/dist/components/ui/checkbox.d.ts.map +1 -1
  35. package/dist/components/ui/combobox.d.ts +2 -1
  36. package/dist/components/ui/combobox.d.ts.map +1 -1
  37. package/dist/components/ui/frosted-glass.d.ts.map +1 -1
  38. package/dist/components/ui/input-group.d.ts +1 -1
  39. package/dist/components/ui/input-group.d.ts.map +1 -1
  40. package/dist/components/ui/pagination.d.ts +3 -2
  41. package/dist/components/ui/pagination.d.ts.map +1 -1
  42. package/dist/components/ui/radio-group.d.ts +3 -1
  43. package/dist/components/ui/radio-group.d.ts.map +1 -1
  44. package/dist/components/ui/select.d.ts +6 -1
  45. package/dist/components/ui/select.d.ts.map +1 -1
  46. package/dist/components/ui/sidebar.d.ts +1 -1
  47. package/dist/components/ui/sidebar.d.ts.map +1 -1
  48. package/dist/components/ui/slider.d.ts +10 -2
  49. package/dist/components/ui/slider.d.ts.map +1 -1
  50. package/dist/components/ui/sonner.d.ts +18 -2
  51. package/dist/components/ui/sonner.d.ts.map +1 -1
  52. package/dist/components/ui/spinner.d.ts +2 -1
  53. package/dist/components/ui/spinner.d.ts.map +1 -1
  54. package/dist/components/ui/switch.d.ts +15 -2
  55. package/dist/components/ui/switch.d.ts.map +1 -1
  56. package/dist/components/ui/tabs.d.ts +1 -1
  57. package/dist/components/ui/tabs.d.ts.map +1 -1
  58. package/dist/components/ui/toggle.d.ts +1 -1
  59. package/dist/components/ui/toggle.d.ts.map +1 -1
  60. package/dist/debug-panel-CNKk-No5.cjs +75 -0
  61. package/dist/debug-panel-pg39-6xw.js +9011 -0
  62. package/dist/debug.cjs.js +1 -0
  63. package/dist/debug.es.js +7 -0
  64. package/dist/{drawer-CU4lkcz7.js → drawer-DO26uhym.js} +31 -31
  65. package/dist/drawer-DVarEy65.cjs +1 -0
  66. package/dist/drawer.cjs.js +1 -1
  67. package/dist/drawer.es.js +1 -1
  68. package/dist/{enhanced-calendar-BENbxw7_.js → enhanced-calendar-BGlsSYJd.js} +1 -1
  69. package/dist/{enhanced-calendar-5PA8CeF7.cjs → enhanced-calendar-C7EQIr6i.cjs} +1 -1
  70. package/dist/entries/debug.d.ts +14 -0
  71. package/dist/entries/debug.d.ts.map +1 -0
  72. package/dist/entries/sonner.d.ts +1 -2
  73. package/dist/entries/sonner.d.ts.map +1 -1
  74. package/dist/hooks/use-mobile.d.ts.map +1 -1
  75. package/dist/hooks/use-scroll-spy.d.ts.map +1 -1
  76. package/dist/index-CI756mSv.cjs +41 -0
  77. package/dist/index-CgfzsUO6.js +1069 -0
  78. package/dist/index.d.ts +2 -98
  79. package/dist/index.d.ts.map +1 -1
  80. package/dist/lib/index.d.ts +9 -0
  81. package/dist/lib/index.d.ts.map +1 -0
  82. package/dist/lib/wrap-inline-label-text.d.ts +7 -0
  83. package/dist/lib/wrap-inline-label-text.d.ts.map +1 -0
  84. package/dist/nqui.cjs.js +49 -245
  85. package/dist/nqui.es.js +7402 -16735
  86. package/dist/sonner-CpmECDBk.js +179 -0
  87. package/dist/sonner-nE9hIalJ.cjs +48 -0
  88. package/dist/sonner.cjs.js +1 -1
  89. package/dist/sonner.es.js +3 -2
  90. package/dist/styles.css +237 -10
  91. package/docs/components/README.md +109 -10
  92. package/docs/components/nqui-badge.md +1 -0
  93. package/docs/components/nqui-button.md +3 -1
  94. package/docs/components/nqui-card.md +8 -0
  95. package/docs/components/nqui-carousel.md +6 -0
  96. package/docs/components/nqui-checkbox.md +38 -1
  97. package/docs/components/nqui-color-slider.md +5 -3
  98. package/docs/components/nqui-combobox.md +58 -37
  99. package/docs/components/nqui-drawer.md +1 -1
  100. package/docs/components/nqui-frosted-glass.md +83 -5
  101. package/docs/components/nqui-radio-group.md +47 -2
  102. package/docs/components/nqui-scroll-area.md +1 -1
  103. package/docs/components/nqui-select.md +2 -2
  104. package/docs/components/nqui-sheet.md +1 -1
  105. package/docs/components/nqui-slider.md +13 -0
  106. package/docs/components/nqui-spinner.md +6 -1
  107. package/docs/components/nqui-switch.md +23 -1
  108. package/docs/components/nqui-tabs.md +11 -1
  109. package/docs/components/nqui-toaster.md +5 -1
  110. package/docs/internal-notes/PUBLISHING.md +46 -4
  111. package/docs/nqui-skills/SKILL.md +106 -0
  112. package/docs/nqui-skills/design-system.md +143 -0
  113. package/docs/nqui-skills/rules/composition.md +183 -0
  114. package/docs/nqui-skills/rules/forms.md +190 -0
  115. package/docs/nqui-skills/rules/icons.md +158 -0
  116. package/docs/nqui-skills/rules/styling.md +192 -0
  117. package/package.json +23 -12
  118. package/scripts/build-styles.js +16 -0
  119. package/scripts/cli.js +1 -0
  120. package/scripts/download-skills.js +91 -0
  121. package/scripts/examples/nextjs-layout-sidebar.tsx +100 -0
  122. package/scripts/examples/nextjs-page-sidebar.tsx +81 -0
  123. package/scripts/examples/vite-app.tsx +135 -0
  124. package/scripts/examples/vite-main.tsx +17 -0
  125. package/scripts/examples.js +92 -6
  126. package/scripts/generate-docs.js +169 -0
  127. package/scripts/init-css.js +34 -14
  128. package/scripts/init-cursor.js +8 -0
  129. package/scripts/init-debug-css.js +4 -2
  130. package/scripts/post-install.js +41 -9
  131. package/scripts/publish-npmjs.js +17 -3
  132. package/scripts/resolve-target-dir.js +20 -1
  133. package/scripts/setup-helper.js +13 -1
  134. package/scripts/verify-build.js +1 -1
  135. package/scripts/wizard.js +12 -7
  136. package/dist/button-CYFTFDKe.cjs +0 -1
  137. package/dist/button-nJvDl3w8.js +0 -44
  138. package/dist/carousel-DEyyJi49.js +0 -179
  139. package/dist/carousel-Dhhz8m5V.cjs +0 -1
  140. package/dist/command-palette-UHk8zZOg.cjs +0 -45
  141. package/dist/command-palette-d-TrdBsM.js +0 -1778
  142. package/dist/components/custom/enhanced-badge.d.ts +0 -33
  143. package/dist/components/custom/enhanced-badge.d.ts.map +0 -1
  144. package/dist/components/custom/enhanced-button.d.ts +0 -34
  145. package/dist/components/custom/enhanced-button.d.ts.map +0 -1
  146. package/dist/components/custom/enhanced-checkbox.d.ts +0 -28
  147. package/dist/components/custom/enhanced-checkbox.d.ts.map +0 -1
  148. package/dist/components/custom/enhanced-combobox.d.ts +0 -35
  149. package/dist/components/custom/enhanced-combobox.d.ts.map +0 -1
  150. package/dist/components/custom/enhanced-select.d.ts +0 -30
  151. package/dist/components/custom/enhanced-select.d.ts.map +0 -1
  152. package/dist/components/custom/enhanced-sonner.d.ts +0 -16
  153. package/dist/components/custom/enhanced-sonner.d.ts.map +0 -1
  154. package/dist/drawer-BcIxWRN8.cjs +0 -1
  155. package/dist/sonner-Co6YpYVs.js +0 -546
  156. package/dist/sonner-DbQhVp8m.cjs +0 -330
@@ -0,0 +1,91 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Download nqui-skills to user's project
4
+ *
5
+ * Usage: npx @nqlib/nqui init-skills
6
+ *
7
+ * Copies docs/nqui-skills to user's .cursor/nqui-skills
8
+ * Creates AGENTS.md pointing to the skills
9
+ */
10
+
11
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, cpSync } from 'fs';
12
+ import { join, resolve } from 'path';
13
+ import { getPackageRoot } from './getPackageRoot.js';
14
+ import { resolveTargetDir } from './resolve-target-dir.js';
15
+
16
+ const root = getPackageRoot();
17
+ const skillsSource = join(root, 'docs', 'nqui-skills');
18
+
19
+ function ensureDir(dir) {
20
+ if (!existsSync(dir)) {
21
+ mkdirSync(dir, { recursive: true });
22
+ }
23
+ }
24
+
25
+ export async function downloadSkills({ force = true }) {
26
+ const targetDir = resolveTargetDir(process.cwd());
27
+ const cursorDir = join(targetDir, '.cursor');
28
+ const skillsDest = join(cursorDir, 'nqui-skills');
29
+ const agentsFile = join(targetDir, 'AGENTS.md');
30
+
31
+ // Create .cursor directory if needed
32
+ ensureDir(cursorDir);
33
+
34
+ // Copy skills folder
35
+ if (existsSync(skillsSource)) {
36
+ if (existsSync(skillsDest) && !force) {
37
+ console.log('⏭️ nqui-skills already exists. Use --force to overwrite.');
38
+ } else {
39
+ cpSync(skillsSource, skillsDest, { recursive: true });
40
+ console.log('✅ Copied nqui-skills to:', skillsDest);
41
+ }
42
+ } else {
43
+ console.warn('⚠️ Source skills not found:', skillsSource);
44
+ return;
45
+ }
46
+
47
+ // Create or update AGENTS.md
48
+ const agentsContent = `# AGENTS.md
49
+
50
+ This file points to nqui skills for AI assistants.
51
+
52
+ ## nqui Skills
53
+
54
+ For component implementation and UI design with @nqlib/nqui, load skills from:
55
+
56
+ \`\`\`
57
+ .cursor/nqui-skills/SKILL.md
58
+ \`\`\`
59
+
60
+ The skills include:
61
+ - Component implementation guide
62
+ - Design system conventions (sizing, z-index)
63
+ - ToggleGroup usage rules
64
+ - App design patterns
65
+
66
+ ## How to Use
67
+
68
+ When working with nqui components, AI assistants should load:
69
+ - \`.cursor/nqui-skills/SKILL.md\` - main guide
70
+
71
+ ---
72
+
73
+ Generated by nqui. Run \`npx @nqlib/nqui init-skills\` to update.
74
+ `;
75
+
76
+ if (existsSync(agentsFile) && !force) {
77
+ console.log('⏭️ AGENTS.md already exists. Use --force to overwrite.');
78
+ } else {
79
+ writeFileSync(agentsFile, agentsContent);
80
+ console.log('✅ Created AGENTS.md at:', agentsFile);
81
+ }
82
+
83
+ console.log('\n📚 nqui-skills installed!');
84
+ console.log(' Restart Cursor to load the skills.');
85
+ }
86
+
87
+ // CLI execution
88
+ const args = process.argv.slice(2);
89
+ const force = args.includes('--force') || args.length === 0;
90
+
91
+ downloadSkills({ force }).catch(console.error);
@@ -0,0 +1,100 @@
1
+ import type { Metadata } from "next";
2
+ import { ThemeProvider } from "next-themes";
3
+ import "./globals.css";
4
+ import {
5
+ SidebarProvider,
6
+ Sidebar,
7
+ SidebarContent,
8
+ SidebarHeader,
9
+ SidebarMenu,
10
+ SidebarMenuItem,
11
+ SidebarMenuButton,
12
+ SidebarInset,
13
+ SidebarTrigger,
14
+ Separator,
15
+ } from "@nqlib/nqui";
16
+ import { NquiLogo } from "@nqlib/nqui";
17
+ import { HomeIcon, SettingsIcon, MailIcon, FileIcon } from "@hugeicons/core-free-icons";
18
+ import { HugeiconsIcon } from "@hugeicons/react";
19
+ import Link from "next/link";
20
+
21
+ export const metadata: Metadata = {
22
+ title: "nqui App",
23
+ description: "3-column app with sidebar, header, and content area (showcase-style)",
24
+ };
25
+
26
+ export default function RootLayout({
27
+ children,
28
+ }: Readonly<{
29
+ children: React.ReactNode;
30
+ }>) {
31
+ return (
32
+ <html lang="en" suppressHydrationWarning>
33
+ <body>
34
+ <ThemeProvider
35
+ attribute="class"
36
+ defaultTheme="system"
37
+ enableSystem
38
+ disableTransitionOnChange
39
+ >
40
+ <SidebarProvider defaultOpen>
41
+ <Sidebar>
42
+ <SidebarHeader>
43
+ <div className="flex items-center gap-2 px-2 py-4">
44
+ <NquiLogo className="w-8 h-8" />
45
+ <span className="font-semibold">My App</span>
46
+ </div>
47
+ </SidebarHeader>
48
+ <SidebarContent>
49
+ <SidebarMenu>
50
+ <SidebarMenuItem>
51
+ <SidebarMenuButton asChild>
52
+ <Link href="/">
53
+ <HugeiconsIcon icon={HomeIcon} className="w-4 h-4" />
54
+ <span>Home</span>
55
+ </Link>
56
+ </SidebarMenuButton>
57
+ </SidebarMenuItem>
58
+ <SidebarMenuItem>
59
+ <SidebarMenuButton asChild>
60
+ <Link href="/inbox">
61
+ <HugeiconsIcon icon={MailIcon} className="w-4 h-4" />
62
+ <span>Inbox</span>
63
+ </Link>
64
+ </SidebarMenuButton>
65
+ </SidebarMenuItem>
66
+ <SidebarMenuItem>
67
+ <SidebarMenuButton asChild>
68
+ <Link href="/files">
69
+ <HugeiconsIcon icon={FileIcon} className="w-4 h-4" />
70
+ <span>Files</span>
71
+ </Link>
72
+ </SidebarMenuButton>
73
+ </SidebarMenuItem>
74
+ <SidebarMenuItem>
75
+ <SidebarMenuButton asChild>
76
+ <Link href="/settings">
77
+ <HugeiconsIcon icon={SettingsIcon} className="w-4 h-4" />
78
+ <span>Settings</span>
79
+ </Link>
80
+ </SidebarMenuButton>
81
+ </SidebarMenuItem>
82
+ </SidebarMenu>
83
+ </SidebarContent>
84
+ </Sidebar>
85
+ <SidebarInset className="flex flex-col min-h-screen">
86
+ <header className="flex h-12 items-center gap-2 border-b px-4 shrink-0 bg-background/95">
87
+ <SidebarTrigger className="-ml-1" />
88
+ <Separator orientation="vertical" className="h-4" />
89
+ <span className="text-sm font-medium">My App</span>
90
+ </header>
91
+ <main className="flex-1 min-h-0 flex">
92
+ {children}
93
+ </main>
94
+ </SidebarInset>
95
+ </SidebarProvider>
96
+ </ThemeProvider>
97
+ </body>
98
+ </html>
99
+ );
100
+ }
@@ -0,0 +1,81 @@
1
+ "use client";
2
+
3
+ import { Button } from "@nqlib/nqui";
4
+ import {
5
+ Card,
6
+ CardContent,
7
+ CardDescription,
8
+ CardHeader,
9
+ CardTitle,
10
+ TableOfContents,
11
+ Input,
12
+ Label,
13
+ Checkbox,
14
+ Separator,
15
+ } from "@nqlib/nqui";
16
+
17
+ export default function Home() {
18
+ return (
19
+ <div className="flex flex-1 min-h-0">
20
+ <div className="flex-1 min-w-0 overflow-y-auto p-6">
21
+ <div className="max-w-3xl space-y-8">
22
+ <div className="space-y-2">
23
+ <h1 className="text-3xl font-bold">Welcome to My App</h1>
24
+ <p className="text-muted-foreground">
25
+ Sample 3-column layout: sidebar, main content, and table of contents (showcase-style).
26
+ </p>
27
+ </div>
28
+
29
+ <section className="space-y-4">
30
+ <h2 id="getting-started" className="text-xl font-semibold scroll-mt-6">
31
+ Getting Started
32
+ </h2>
33
+ <Card>
34
+ <CardHeader>
35
+ <CardTitle>Quick start</CardTitle>
36
+ <CardDescription>
37
+ Edit this page to start building your app
38
+ </CardDescription>
39
+ </CardHeader>
40
+ <CardContent className="space-y-4">
41
+ <div className="grid gap-2">
42
+ <Label htmlFor="name">Name</Label>
43
+ <Input id="name" placeholder="Enter your name" />
44
+ </div>
45
+ <div className="grid gap-2">
46
+ <Label htmlFor="email">Email</Label>
47
+ <Input id="email" type="email" placeholder="Enter your email" />
48
+ </div>
49
+ <Checkbox id="terms">Accept terms and conditions</Checkbox>
50
+ <Separator />
51
+ <div className="flex gap-2">
52
+ <Button variant="default">Submit</Button>
53
+ <Button variant="outline">Cancel</Button>
54
+ </div>
55
+ </CardContent>
56
+ </Card>
57
+ </section>
58
+
59
+ <section className="space-y-4">
60
+ <h2 id="next-steps" className="text-xl font-semibold scroll-mt-6">
61
+ Next steps
62
+ </h2>
63
+ <p className="text-muted-foreground text-sm">
64
+ Edit <code className="rounded bg-muted px-1 py-0.5">app/page.tsx</code> to get started.
65
+ </p>
66
+ </section>
67
+ </div>
68
+ </div>
69
+ <aside className="w-56 shrink-0 border-l bg-muted/30 p-4 hidden lg:block overflow-y-auto">
70
+ <TableOfContents
71
+ autoDetect
72
+ headingSelector="h2"
73
+ variant="clerk"
74
+ enableScrollSpy
75
+ title="Contents"
76
+ scrollOffset={80}
77
+ />
78
+ </aside>
79
+ </div>
80
+ );
81
+ }
@@ -0,0 +1,135 @@
1
+ import { Routes, Route } from "react-router-dom";
2
+ import {
3
+ SidebarProvider,
4
+ Sidebar,
5
+ SidebarContent,
6
+ SidebarHeader,
7
+ SidebarMenu,
8
+ SidebarMenuItem,
9
+ SidebarMenuButton,
10
+ SidebarInset,
11
+ SidebarTrigger,
12
+ Separator,
13
+ TableOfContents,
14
+ NquiLogo,
15
+ } from "@nqlib/nqui";
16
+ import { HomeIcon, SettingsIcon, MailIcon, FileIcon } from "@hugeicons/core-free-icons";
17
+ import { HugeiconsIcon } from "@hugeicons/react";
18
+ import { Link } from "react-router-dom";
19
+
20
+ function Layout({ children }: { children: React.ReactNode }) {
21
+ return (
22
+ <SidebarProvider defaultOpen>
23
+ <Sidebar>
24
+ <SidebarHeader>
25
+ <div className="flex items-center gap-2 px-2 py-4">
26
+ <NquiLogo className="w-8 h-8" />
27
+ <span className="font-semibold">My App</span>
28
+ </div>
29
+ </SidebarHeader>
30
+ <SidebarContent>
31
+ <SidebarMenu>
32
+ <SidebarMenuItem>
33
+ <SidebarMenuButton asChild>
34
+ <Link to="/">
35
+ <HugeiconsIcon icon={HomeIcon} className="w-4 h-4" />
36
+ <span>Home</span>
37
+ </Link>
38
+ </SidebarMenuButton>
39
+ </SidebarMenuItem>
40
+ <SidebarMenuItem>
41
+ <SidebarMenuButton asChild>
42
+ <Link to="/inbox">
43
+ <HugeiconsIcon icon={MailIcon} className="w-4 h-4" />
44
+ <span>Inbox</span>
45
+ </Link>
46
+ </SidebarMenuButton>
47
+ </SidebarMenuItem>
48
+ <SidebarMenuItem>
49
+ <SidebarMenuButton asChild>
50
+ <Link to="/files">
51
+ <HugeiconsIcon icon={FileIcon} className="w-4 h-4" />
52
+ <span>Files</span>
53
+ </Link>
54
+ </SidebarMenuButton>
55
+ </SidebarMenuItem>
56
+ <SidebarMenuItem>
57
+ <SidebarMenuButton asChild>
58
+ <Link to="/settings">
59
+ <HugeiconsIcon icon={SettingsIcon} className="w-4 h-4" />
60
+ <span>Settings</span>
61
+ </Link>
62
+ </SidebarMenuButton>
63
+ </SidebarMenuItem>
64
+ </SidebarMenu>
65
+ </SidebarContent>
66
+ </Sidebar>
67
+ <SidebarInset className="flex flex-col min-h-screen">
68
+ <header className="flex h-12 items-center gap-2 border-b px-4 shrink-0 bg-background/95">
69
+ <SidebarTrigger className="-ml-1" />
70
+ <Separator orientation="vertical" className="h-4" />
71
+ <span className="text-sm font-medium">My App</span>
72
+ </header>
73
+ <main className="flex-1 min-h-0 flex">
74
+ {children}
75
+ </main>
76
+ </SidebarInset>
77
+ </SidebarProvider>
78
+ );
79
+ }
80
+
81
+ function HomePage() {
82
+ return (
83
+ <div className="flex flex-1 min-h-0">
84
+ <div className="flex-1 min-w-0 overflow-y-auto p-6">
85
+ <div className="max-w-3xl space-y-8">
86
+ <div className="space-y-2">
87
+ <h1 className="text-3xl font-bold">Welcome to My App</h1>
88
+ <p className="text-muted-foreground">
89
+ Sample 3-column layout: sidebar, main content, and table of contents (showcase-style).
90
+ </p>
91
+ </div>
92
+ <section className="space-y-4">
93
+ <h2 id="getting-started" className="text-xl font-semibold scroll-mt-6">
94
+ Getting Started
95
+ </h2>
96
+ <p className="text-muted-foreground text-sm">
97
+ Edit <code className="rounded bg-muted px-1 py-0.5">App.tsx</code> to get started.
98
+ </p>
99
+ </section>
100
+ <section className="space-y-4">
101
+ <h2 id="next-steps" className="text-xl font-semibold scroll-mt-6">
102
+ Next steps
103
+ </h2>
104
+ <p className="text-muted-foreground text-sm">
105
+ Add routes and pages. The right column shows a table of contents from headings on this page.
106
+ </p>
107
+ </section>
108
+ </div>
109
+ </div>
110
+ <aside className="w-56 shrink-0 border-l bg-muted/30 p-4 hidden lg:block overflow-y-auto">
111
+ <TableOfContents
112
+ autoDetect
113
+ headingSelector="h2"
114
+ variant="clerk"
115
+ enableScrollSpy
116
+ title="Contents"
117
+ scrollOffset={80}
118
+ />
119
+ </aside>
120
+ </div>
121
+ );
122
+ }
123
+
124
+ export default function App() {
125
+ return (
126
+ <Layout>
127
+ <Routes>
128
+ <Route path="/" element={<HomePage />} />
129
+ <Route path="/inbox" element={<div className="p-6">Inbox – Coming soon</div>} />
130
+ <Route path="/files" element={<div className="p-6">Files – Coming soon</div>} />
131
+ <Route path="/settings" element={<div className="p-6">Settings – Coming soon</div>} />
132
+ </Routes>
133
+ </Layout>
134
+ );
135
+ }
@@ -0,0 +1,17 @@
1
+ import { StrictMode } from "react";
2
+ import { createRoot } from "react-dom/client";
3
+ import { ThemeProvider } from "next-themes";
4
+ import { BrowserRouter } from "react-router-dom";
5
+ import "./index.css";
6
+ import App from "./App";
7
+ // Required dependencies: npm install @nqlib/nqui tw-animate-css next-themes hugeicons-core-free-icons hugeicons-react react-router-dom
8
+
9
+ createRoot(document.getElementById("root")!).render(
10
+ <StrictMode>
11
+ <ThemeProvider attribute="class" defaultTheme="system" enableSystem disableTransitionOnChange>
12
+ <BrowserRouter>
13
+ <App />
14
+ </BrowserRouter>
15
+ </ThemeProvider>
16
+ </StrictMode>
17
+ );
@@ -7,7 +7,7 @@ import { askQuestion } from './wizard.js';
7
7
  /**
8
8
  * Copy Next.js example files to user's project
9
9
  */
10
- export async function copyNextJsExamples(framework, { force }) {
10
+ export async function copyNextJsExamples(framework, { force, sidebar }) {
11
11
  if (framework !== 'nextjs') {
12
12
  return;
13
13
  }
@@ -21,9 +21,95 @@ export async function copyNextJsExamples(framework, { force }) {
21
21
  ? join(cwd, 'src', 'app')
22
22
  : join(cwd, 'app');
23
23
 
24
+ // Choose examples based on sidebar flag
25
+ const examples = sidebar
26
+ ? [
27
+ { src: 'nextjs-page-sidebar.tsx', dest: join(appDir, 'page.tsx'), name: 'page.tsx' },
28
+ { src: 'nextjs-layout-sidebar.tsx', dest: join(appDir, 'layout.tsx'), name: 'layout.tsx' },
29
+ ]
30
+ : [
31
+ { src: 'nextjs-page.tsx', dest: join(appDir, 'page.tsx'), name: 'page.tsx' },
32
+ { src: 'nextjs-layout.tsx', dest: join(appDir, 'layout.tsx'), name: 'layout.tsx' },
33
+ ];
34
+
35
+ const copied = [];
36
+ const existing = [];
37
+
38
+ // Check which files exist
39
+ for (const { dest, name } of examples) {
40
+ if (existsSync(dest)) {
41
+ existing.push({ dest, name });
42
+ }
43
+ }
44
+
45
+ // Ask about overwriting if files exist and force is not set
46
+ let shouldOverwrite = force;
47
+ if (existing.length > 0 && !force) {
48
+ const fileList = existing.map(e => e.name).join(' and ');
49
+ const answer = await askQuestion(
50
+ `\n⚠️ ${fileList} already exist(s). Overwrite? (y/n): `
51
+ );
52
+ shouldOverwrite = answer === 'y';
53
+ }
54
+
55
+ for (const { src, dest, name } of examples) {
56
+ const srcPath = join(examplesDir, src);
57
+
58
+ if (!existsSync(srcPath)) {
59
+ console.warn(`⚠️ Example file not found: ${srcPath}`);
60
+ continue;
61
+ }
62
+
63
+ if (existsSync(dest) && !shouldOverwrite) {
64
+ console.log(`⏭️ Skipped: ${dest} (already exists)`);
65
+ continue;
66
+ }
67
+
68
+ const content = readFileSync(srcPath, 'utf8');
69
+ writeFileSync(dest, content, 'utf8');
70
+ copied.push(dest);
71
+ console.log(`✅ ${existsSync(dest) && shouldOverwrite ? 'Overwritten' : 'Created'}: ${dest}`);
72
+ }
73
+
74
+ if (copied.length > 0) {
75
+ const deps = sidebar
76
+ ? 'npm install @nqlib/nqui @hugeicons/react @hugeicons/core-free-icons tw-animate-css next-themes react-router-dom'
77
+ : 'npm install @nqlib/nqui tw-animate-css next-themes';
78
+ console.log(`\n📝 Required dependencies for example files:`);
79
+ console.log(` ${deps}\n`);
80
+ if (sidebar) {
81
+ console.log(` Note: 3-column layout uses Sidebar, TableOfContents; main.tsx includes ThemeProvider + BrowserRouter for Vite.\n`);
82
+ }
83
+ }
84
+
85
+ return copied;
86
+ }
87
+
88
+ /**
89
+ * Copy Vite example files to user's project
90
+ */
91
+ export async function copyViteExamples(framework, { force, sidebar }) {
92
+ if (framework !== 'vite') {
93
+ return;
94
+ }
95
+
96
+ const root = getPackageRoot();
97
+ const examplesDir = join(root, 'scripts', 'examples');
98
+ const cwd = process.cwd();
99
+
100
+ // Determine src directory
101
+ const srcDir = existsSync(join(cwd, 'src')) ? join(cwd, 'src') : join(cwd, 'src');
102
+
103
+ // Ensure src directory exists
104
+ if (!existsSync(srcDir)) {
105
+ console.warn('⚠️ src directory not found');
106
+ return;
107
+ }
108
+
109
+ // Choose examples based on sidebar flag (3-column with TOC when sidebar; same files + main for ThemeProvider)
24
110
  const examples = [
25
- { src: 'nextjs-page.tsx', dest: join(appDir, 'page.tsx'), name: 'page.tsx' },
26
- { src: 'nextjs-layout.tsx', dest: join(appDir, 'layout.tsx'), name: 'layout.tsx' },
111
+ { src: 'vite-app.tsx', dest: join(srcDir, 'App.tsx'), name: 'App.tsx' },
112
+ { src: 'vite-main.tsx', dest: join(srcDir, 'main.tsx'), name: 'main.tsx' },
27
113
  ];
28
114
 
29
115
  const copied = [];
@@ -66,11 +152,11 @@ export async function copyNextJsExamples(framework, { force }) {
66
152
  }
67
153
 
68
154
  if (copied.length > 0) {
155
+ const deps = 'npm install @nqlib/nqui tw-animate-css next-themes @hugeicons/react @hugeicons/core-free-icons react-router-dom';
69
156
  console.log(`\n📝 Required dependencies for example files:`);
70
- console.log(` npm install @nqlib/nqui tw-animate-css next-themes\n`);
71
- console.log(` Make sure your globals.css includes the setup from nqui/nqui-setup.css\n`);
157
+ console.log(` ${deps}`);
158
+ console.log(` Note: For Vite, wrap your app with ThemeProvider and BrowserRouter in main.tsx\n`);
72
159
  }
73
160
 
74
161
  return copied;
75
162
  }
76
-