@nqlib/nqui 0.1.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.
Files changed (219) hide show
  1. package/INSTALLATION.md +221 -0
  2. package/README.md +276 -0
  3. package/dist/App.d.ts +3 -0
  4. package/dist/App.d.ts.map +1 -0
  5. package/dist/components/AppLayout.d.ts +2 -0
  6. package/dist/components/AppLayout.d.ts.map +1 -0
  7. package/dist/components/app-sidebar.d.ts +4 -0
  8. package/dist/components/app-sidebar.d.ts.map +1 -0
  9. package/dist/components/component-example.d.ts +2 -0
  10. package/dist/components/component-example.d.ts.map +1 -0
  11. package/dist/components/custom/color-picker.d.ts +9 -0
  12. package/dist/components/custom/color-picker.d.ts.map +1 -0
  13. package/dist/components/custom/color-slider.d.ts +22 -0
  14. package/dist/components/custom/color-slider.d.ts.map +1 -0
  15. package/dist/components/custom/enhanced-button.d.ts +34 -0
  16. package/dist/components/custom/enhanced-button.d.ts.map +1 -0
  17. package/dist/components/custom/enhanced-checkbox.d.ts +28 -0
  18. package/dist/components/custom/enhanced-checkbox.d.ts.map +1 -0
  19. package/dist/components/custom/enhanced-radio-group.d.ts +36 -0
  20. package/dist/components/custom/enhanced-radio-group.d.ts.map +1 -0
  21. package/dist/components/custom/enhanced-scroll-area.d.ts +34 -0
  22. package/dist/components/custom/enhanced-scroll-area.d.ts.map +1 -0
  23. package/dist/components/custom/enhanced-separator.d.ts +36 -0
  24. package/dist/components/custom/enhanced-separator.d.ts.map +1 -0
  25. package/dist/components/custom/nqui-logo.d.ts +9 -0
  26. package/dist/components/custom/nqui-logo.d.ts.map +1 -0
  27. package/dist/components/custom/rating.d.ts +60 -0
  28. package/dist/components/custom/rating.d.ts.map +1 -0
  29. package/dist/components/custom/table-of-contents.d.ts +77 -0
  30. package/dist/components/custom/table-of-contents.d.ts.map +1 -0
  31. package/dist/components/debug/crosshair.d.ts +5 -0
  32. package/dist/components/debug/crosshair.d.ts.map +1 -0
  33. package/dist/components/debug/debug-panel.d.ts +5 -0
  34. package/dist/components/debug/debug-panel.d.ts.map +1 -0
  35. package/dist/components/debug/dependencies.d.ts +23 -0
  36. package/dist/components/debug/dependencies.d.ts.map +1 -0
  37. package/dist/components/debug/index.d.ts +17 -0
  38. package/dist/components/debug/index.d.ts.map +1 -0
  39. package/dist/components/debug/magnifier.d.ts +9 -0
  40. package/dist/components/debug/magnifier.d.ts.map +1 -0
  41. package/dist/components/debug/ui-tester.d.ts +13 -0
  42. package/dist/components/debug/ui-tester.d.ts.map +1 -0
  43. package/dist/components/debug/utils/css-variable-parser.d.ts +28 -0
  44. package/dist/components/debug/utils/css-variable-parser.d.ts.map +1 -0
  45. package/dist/components/debug/utils/element-selector.d.ts +24 -0
  46. package/dist/components/debug/utils/element-selector.d.ts.map +1 -0
  47. package/dist/components/debug/utils/style-injector.d.ts +40 -0
  48. package/dist/components/debug/utils/style-injector.d.ts.map +1 -0
  49. package/dist/components/debug/utils/style-parser.d.ts +53 -0
  50. package/dist/components/debug/utils/style-parser.d.ts.map +1 -0
  51. package/dist/components/example.d.ts +7 -0
  52. package/dist/components/example.d.ts.map +1 -0
  53. package/dist/components/login-form.d.ts +2 -0
  54. package/dist/components/login-form.d.ts.map +1 -0
  55. package/dist/components/nav-user.d.ts +8 -0
  56. package/dist/components/nav-user.d.ts.map +1 -0
  57. package/dist/components/showcase/app-builder/app-builder-context.d.ts +16 -0
  58. package/dist/components/showcase/app-builder/app-builder-context.d.ts.map +1 -0
  59. package/dist/components/showcase/app-builder/app-canvas.d.ts +11 -0
  60. package/dist/components/showcase/app-builder/app-canvas.d.ts.map +1 -0
  61. package/dist/components/showcase/app-builder/widget-configurator.d.ts +10 -0
  62. package/dist/components/showcase/app-builder/widget-configurator.d.ts.map +1 -0
  63. package/dist/components/showcase/app-builder/widget-palette.d.ts +6 -0
  64. package/dist/components/showcase/app-builder/widget-palette.d.ts.map +1 -0
  65. package/dist/components/showcase/app-builder/widget-registry.d.ts +29 -0
  66. package/dist/components/showcase/app-builder/widget-registry.d.ts.map +1 -0
  67. package/dist/components/showcase/app-builder/widget-renderer.d.ts +7 -0
  68. package/dist/components/showcase/app-builder/widget-renderer.d.ts.map +1 -0
  69. package/dist/components/theme-toggle.d.ts +2 -0
  70. package/dist/components/theme-toggle.d.ts.map +1 -0
  71. package/dist/components/ui/accordion.d.ts +8 -0
  72. package/dist/components/ui/accordion.d.ts.map +1 -0
  73. package/dist/components/ui/alert-dialog.d.ts +19 -0
  74. package/dist/components/ui/alert-dialog.d.ts.map +1 -0
  75. package/dist/components/ui/alert.d.ts +11 -0
  76. package/dist/components/ui/alert.d.ts.map +1 -0
  77. package/dist/components/ui/aspect-ratio.d.ts +4 -0
  78. package/dist/components/ui/aspect-ratio.d.ts.map +1 -0
  79. package/dist/components/ui/avatar.d.ts +7 -0
  80. package/dist/components/ui/avatar.d.ts.map +1 -0
  81. package/dist/components/ui/badge.d.ts +10 -0
  82. package/dist/components/ui/badge.d.ts.map +1 -0
  83. package/dist/components/ui/breadcrumb.d.ts +20 -0
  84. package/dist/components/ui/breadcrumb.d.ts.map +1 -0
  85. package/dist/components/ui/button-group.d.ts +12 -0
  86. package/dist/components/ui/button-group.d.ts.map +1 -0
  87. package/dist/components/ui/button.d.ts +12 -0
  88. package/dist/components/ui/button.d.ts.map +1 -0
  89. package/dist/components/ui/calendar.d.ts +9 -0
  90. package/dist/components/ui/calendar.d.ts.map +1 -0
  91. package/dist/components/ui/card.d.ts +9 -0
  92. package/dist/components/ui/card.d.ts.map +1 -0
  93. package/dist/components/ui/carousel.d.ts +29 -0
  94. package/dist/components/ui/carousel.d.ts.map +1 -0
  95. package/dist/components/ui/chart.d.ts +41 -0
  96. package/dist/components/ui/chart.d.ts.map +1 -0
  97. package/dist/components/ui/checkbox.d.ts +5 -0
  98. package/dist/components/ui/checkbox.d.ts.map +1 -0
  99. package/dist/components/ui/collapsible.d.ts +6 -0
  100. package/dist/components/ui/collapsible.d.ts.map +1 -0
  101. package/dist/components/ui/combobox.d.ts +25 -0
  102. package/dist/components/ui/combobox.d.ts.map +1 -0
  103. package/dist/components/ui/command.d.ts +19 -0
  104. package/dist/components/ui/command.d.ts.map +1 -0
  105. package/dist/components/ui/context-menu.d.ts +28 -0
  106. package/dist/components/ui/context-menu.d.ts.map +1 -0
  107. package/dist/components/ui/dialog.d.ts +18 -0
  108. package/dist/components/ui/dialog.d.ts.map +1 -0
  109. package/dist/components/ui/drawer.d.ts +14 -0
  110. package/dist/components/ui/drawer.d.ts.map +1 -0
  111. package/dist/components/ui/dropdown-menu.d.ts +28 -0
  112. package/dist/components/ui/dropdown-menu.d.ts.map +1 -0
  113. package/dist/components/ui/empty.d.ts +12 -0
  114. package/dist/components/ui/empty.d.ts.map +1 -0
  115. package/dist/components/ui/field.d.ts +25 -0
  116. package/dist/components/ui/field.d.ts.map +1 -0
  117. package/dist/components/ui/hover-card.d.ts +7 -0
  118. package/dist/components/ui/hover-card.d.ts.map +1 -0
  119. package/dist/components/ui/input-group.d.ts +17 -0
  120. package/dist/components/ui/input-group.d.ts.map +1 -0
  121. package/dist/components/ui/input-otp.d.ts +12 -0
  122. package/dist/components/ui/input-otp.d.ts.map +1 -0
  123. package/dist/components/ui/input.d.ts +4 -0
  124. package/dist/components/ui/input.d.ts.map +1 -0
  125. package/dist/components/ui/item.d.ts +24 -0
  126. package/dist/components/ui/item.d.ts.map +1 -0
  127. package/dist/components/ui/kbd.d.ts +4 -0
  128. package/dist/components/ui/kbd.d.ts.map +1 -0
  129. package/dist/components/ui/label.d.ts +6 -0
  130. package/dist/components/ui/label.d.ts.map +1 -0
  131. package/dist/components/ui/menubar.d.ts +27 -0
  132. package/dist/components/ui/menubar.d.ts.map +1 -0
  133. package/dist/components/ui/native-select.d.ts +9 -0
  134. package/dist/components/ui/native-select.d.ts.map +1 -0
  135. package/dist/components/ui/navigation-menu.d.ts +15 -0
  136. package/dist/components/ui/navigation-menu.d.ts.map +1 -0
  137. package/dist/components/ui/pagination.d.ts +14 -0
  138. package/dist/components/ui/pagination.d.ts.map +1 -0
  139. package/dist/components/ui/popover.d.ts +11 -0
  140. package/dist/components/ui/popover.d.ts.map +1 -0
  141. package/dist/components/ui/progress.d.ts +5 -0
  142. package/dist/components/ui/progress.d.ts.map +1 -0
  143. package/dist/components/ui/radio-group.d.ts +6 -0
  144. package/dist/components/ui/radio-group.d.ts.map +1 -0
  145. package/dist/components/ui/resizable.d.ts +8 -0
  146. package/dist/components/ui/resizable.d.ts.map +1 -0
  147. package/dist/components/ui/scroll-area.d.ts +6 -0
  148. package/dist/components/ui/scroll-area.d.ts.map +1 -0
  149. package/dist/components/ui/select.d.ts +16 -0
  150. package/dist/components/ui/select.d.ts.map +1 -0
  151. package/dist/components/ui/separator.d.ts +5 -0
  152. package/dist/components/ui/separator.d.ts.map +1 -0
  153. package/dist/components/ui/sheet.d.ts +26 -0
  154. package/dist/components/ui/sheet.d.ts.map +1 -0
  155. package/dist/components/ui/sidebar.d.ts +66 -0
  156. package/dist/components/ui/sidebar.d.ts.map +1 -0
  157. package/dist/components/ui/skeleton.d.ts +3 -0
  158. package/dist/components/ui/skeleton.d.ts.map +1 -0
  159. package/dist/components/ui/slider.d.ts +5 -0
  160. package/dist/components/ui/slider.d.ts.map +1 -0
  161. package/dist/components/ui/sonner.d.ts +4 -0
  162. package/dist/components/ui/sonner.d.ts.map +1 -0
  163. package/dist/components/ui/spinner.d.ts +3 -0
  164. package/dist/components/ui/spinner.d.ts.map +1 -0
  165. package/dist/components/ui/switch.d.ts +5 -0
  166. package/dist/components/ui/switch.d.ts.map +1 -0
  167. package/dist/components/ui/table.d.ts +11 -0
  168. package/dist/components/ui/table.d.ts.map +1 -0
  169. package/dist/components/ui/tabs.d.ts +12 -0
  170. package/dist/components/ui/tabs.d.ts.map +1 -0
  171. package/dist/components/ui/textarea.d.ts +4 -0
  172. package/dist/components/ui/textarea.d.ts.map +1 -0
  173. package/dist/components/ui/toggle-group.d.ts +11 -0
  174. package/dist/components/ui/toggle-group.d.ts.map +1 -0
  175. package/dist/components/ui/toggle.d.ts +10 -0
  176. package/dist/components/ui/toggle.d.ts.map +1 -0
  177. package/dist/components/ui/tooltip.d.ts +8 -0
  178. package/dist/components/ui/tooltip.d.ts.map +1 -0
  179. package/dist/hooks/use-mobile.d.ts +2 -0
  180. package/dist/hooks/use-mobile.d.ts.map +1 -0
  181. package/dist/hooks/use-scroll-spy.d.ts +50 -0
  182. package/dist/hooks/use-scroll-spy.d.ts.map +1 -0
  183. package/dist/index.d.ts +80 -0
  184. package/dist/index.d.ts.map +1 -0
  185. package/dist/lib/utils.d.ts +3 -0
  186. package/dist/lib/utils.d.ts.map +1 -0
  187. package/dist/main.d.ts +3 -0
  188. package/dist/main.d.ts.map +1 -0
  189. package/dist/mockdata/toc.d.ts +11 -0
  190. package/dist/mockdata/toc.d.ts.map +1 -0
  191. package/dist/nqui.cjs.js +521 -0
  192. package/dist/nqui.css +148 -0
  193. package/dist/nqui.es.js +35453 -0
  194. package/dist/pages/AppBuilder.d.ts +2 -0
  195. package/dist/pages/AppBuilder.d.ts.map +1 -0
  196. package/dist/pages/Dashboard.d.ts +2 -0
  197. package/dist/pages/Dashboard.d.ts.map +1 -0
  198. package/dist/pages/Drafts.d.ts +2 -0
  199. package/dist/pages/Drafts.d.ts.map +1 -0
  200. package/dist/pages/Inbox.d.ts +2 -0
  201. package/dist/pages/Inbox.d.ts.map +1 -0
  202. package/dist/pages/Junk.d.ts +2 -0
  203. package/dist/pages/Junk.d.ts.map +1 -0
  204. package/dist/pages/Sent.d.ts +2 -0
  205. package/dist/pages/Sent.d.ts.map +1 -0
  206. package/dist/pages/Settings.d.ts +2 -0
  207. package/dist/pages/Settings.d.ts.map +1 -0
  208. package/dist/pages/Trash.d.ts +2 -0
  209. package/dist/pages/Trash.d.ts.map +1 -0
  210. package/dist/styles.css +544 -0
  211. package/dist/vite.svg +1 -0
  212. package/package.json +128 -0
  213. package/scripts/build-styles.js +205 -0
  214. package/scripts/examples/nextjs-layout.tsx +30 -0
  215. package/scripts/examples/nextjs-page.tsx +66 -0
  216. package/scripts/init-css.js +568 -0
  217. package/scripts/init-debug-css.js +123 -0
  218. package/scripts/publish-npmjs.js +87 -0
  219. package/scripts/validate-exports.mjs +117 -0
@@ -0,0 +1,568 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * nqui CSS initialization script
5
+ *
6
+ * Copies the nqui design system CSS (variables, colors, tokens) to the user's project.
7
+ * Usage: npx nqui init-css [target-path]
8
+ */
9
+
10
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
11
+ import { join, dirname, resolve } from 'path';
12
+ import { fileURLToPath } from 'url';
13
+ import { createInterface } from 'readline';
14
+
15
+ const __filename = fileURLToPath(import.meta.url);
16
+ const __dirname = dirname(__filename);
17
+
18
+ // Get the project root (where package.json is)
19
+ const projectRoot = resolve(__dirname, '..');
20
+ const indexCssPath = join(projectRoot, 'src', 'index.css');
21
+ const colorsCssPath = join(projectRoot, 'src', 'styles', 'colors.css');
22
+ const examplesDir = join(projectRoot, 'scripts', 'examples');
23
+
24
+ // Function to find actual CSS file location for Next.js
25
+ function findNextJsCssFile() {
26
+ const possiblePaths = [
27
+ 'src/app/globals.css',
28
+ 'app/globals.css',
29
+ 'src/app/layout.css',
30
+ 'app/layout.css',
31
+ ];
32
+
33
+ for (const path of possiblePaths) {
34
+ const fullPath = join(process.cwd(), path);
35
+ if (existsSync(fullPath)) {
36
+ return path;
37
+ }
38
+ }
39
+
40
+ // Default fallback based on directory structure
41
+ if (existsSync(join(process.cwd(), 'src', 'app'))) {
42
+ return 'src/app/globals.css';
43
+ }
44
+ return 'app/globals.css';
45
+ }
46
+
47
+ // Function to find actual CSS file location for Vite
48
+ function findViteCssFile() {
49
+ const possiblePaths = [
50
+ 'src/index.css',
51
+ 'src/main.css',
52
+ 'src/App.css',
53
+ ];
54
+
55
+ for (const path of possiblePaths) {
56
+ const fullPath = join(process.cwd(), path);
57
+ if (existsSync(fullPath)) {
58
+ return path;
59
+ }
60
+ }
61
+
62
+ return 'src/index.css';
63
+ }
64
+
65
+ // Get default path based on project type (uses detection functions)
66
+ function getDefaultPath(projectType) {
67
+ switch (projectType) {
68
+ case 'nextjs':
69
+ return findNextJsCssFile();
70
+ case 'vite':
71
+ return findViteCssFile();
72
+ case 'remix':
73
+ return 'app/root.css';
74
+ case 'create-react-app':
75
+ return 'src/index.css';
76
+ default:
77
+ return 'nqui.css';
78
+ }
79
+ }
80
+
81
+ function findProjectType() {
82
+ // Check for framework-specific files
83
+ if (existsSync(join(process.cwd(), 'next.config.js')) ||
84
+ existsSync(join(process.cwd(), 'next.config.ts'))) {
85
+ return 'nextjs';
86
+ }
87
+ if (existsSync(join(process.cwd(), 'vite.config.js')) ||
88
+ existsSync(join(process.cwd(), 'vite.config.ts'))) {
89
+ return 'vite';
90
+ }
91
+ if (existsSync(join(process.cwd(), 'remix.config.js'))) {
92
+ return 'remix';
93
+ }
94
+ if (existsSync(join(process.cwd(), 'src', 'index.css'))) {
95
+ return 'create-react-app';
96
+ }
97
+ return null;
98
+ }
99
+
100
+ function extractStandaloneCSS() {
101
+ // Read the source CSS files
102
+ if (!existsSync(indexCssPath)) {
103
+ throw new Error(`Source CSS file not found: ${indexCssPath}`);
104
+ }
105
+ if (!existsSync(colorsCssPath)) {
106
+ throw new Error(`Colors CSS file not found: ${colorsCssPath}`);
107
+ }
108
+
109
+ let indexCss = readFileSync(indexCssPath, 'utf-8');
110
+ let colorsCss = readFileSync(colorsCssPath, 'utf-8');
111
+
112
+ // Extract :root and .dark blocks from colors.css (they're wrapped in @layer base)
113
+ // We need to unwrap them and merge with index.css's :root and .dark
114
+ const colorsRootMatch = colorsCss.match(/@layer base\s*\{\s*:root\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}\s*\.dark\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}\s*\}/s);
115
+
116
+ let colorsRootContent = '';
117
+ let colorsDarkContent = '';
118
+
119
+ if (colorsRootMatch) {
120
+ colorsRootContent = colorsRootMatch[1].trim();
121
+ colorsDarkContent = colorsRootMatch[2].trim();
122
+ } else {
123
+ // Fallback: try to extract without @layer base wrapper
124
+ const rootMatch = colorsCss.match(/:root\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}/s);
125
+ const darkMatch = colorsCss.match(/\.dark\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}/s);
126
+ if (rootMatch) colorsRootContent = rootMatch[1].trim();
127
+ if (darkMatch) colorsDarkContent = darkMatch[1].trim();
128
+ }
129
+
130
+ // Remove imports that require build tools (users should handle these in their own setup)
131
+ // Keep only the design tokens and variables
132
+ indexCss = indexCss
133
+ .replace(/@import\s+["']tailwindcss["'];?\s*\n/g, '')
134
+ .replace(/@import\s+["']tw-animate-css["'];?\s*\n/g, '')
135
+ .replace(/@import\s+["']shadcn\/tailwind\.css["'];?\s*\n/g, '')
136
+ .replace(/@import\s+["']@fontsource-variable\/inter["'];?\s*\n/g, '')
137
+ .replace(/@import\s+["']\.\/styles\/colors\.css["'];?\s*\n/g, '')
138
+ .replace(/\/\*\s*Import enhanced color system\s*\*\//g, '');
139
+
140
+ // Extract :root and .dark blocks from index.css
141
+ const indexRootMatch = indexCss.match(/:root\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}/s);
142
+ const indexDarkMatch = indexCss.match(/\.dark\s*\{([^}]+(?:\{[^}]*\}[^}]*)*)\}/s);
143
+
144
+ let indexRootContent = '';
145
+ let indexDarkContent = '';
146
+
147
+ if (indexRootMatch) indexRootContent = indexRootMatch[1].trim();
148
+ if (indexDarkMatch) indexDarkContent = indexDarkMatch[1].trim();
149
+
150
+ // Merge :root blocks (colors.css first, then index.css)
151
+ const mergedRootContent = colorsRootContent
152
+ ? colorsRootContent + '\n\n /* Additional variables from index.css */\n ' + indexRootContent
153
+ : indexRootContent;
154
+
155
+ // Merge .dark blocks (colors.css first, then index.css)
156
+ const mergedDarkContent = colorsDarkContent
157
+ ? colorsDarkContent + '\n\n /* Additional variables from index.css */\n ' + indexDarkContent
158
+ : indexDarkContent;
159
+
160
+ // Replace :root and .dark in index.css with merged versions
161
+ if (indexRootMatch) {
162
+ indexCss = indexCss.replace(/:root\s*\{[^}]+(?:\{[^}]*\}[^}]*)*\}/s, `:root {\n ${mergedRootContent}\n}`);
163
+ }
164
+
165
+ if (indexDarkMatch) {
166
+ indexCss = indexCss.replace(/\.dark\s*\{[^}]+(?:\{[^}]*\}[^}]*)*\}/s, `.dark {\n ${mergedDarkContent}\n}`);
167
+ }
168
+
169
+ // Remove duplicate @layer base blocks (there are two identical ones in index.css)
170
+ // Match @layer base blocks with proper brace counting
171
+ const lines = indexCss.split('\n');
172
+ let inLayerBase = false;
173
+ let layerBaseStart = -1;
174
+ let braceCount = 0;
175
+ const layerBaseBlocks = [];
176
+
177
+ for (let i = 0; i < lines.length; i++) {
178
+ const line = lines[i];
179
+ if (line.includes('@layer base')) {
180
+ if (!inLayerBase) {
181
+ inLayerBase = true;
182
+ layerBaseStart = i;
183
+ braceCount = (line.match(/\{/g) || []).length - (line.match(/\}/g) || []).length;
184
+ } else {
185
+ braceCount += (line.match(/\{/g) || []).length - (line.match(/\}/g) || []).length;
186
+ }
187
+ } else if (inLayerBase) {
188
+ braceCount += (line.match(/\{/g) || []).length - (line.match(/\}/g) || []).length;
189
+ if (braceCount === 0) {
190
+ layerBaseBlocks.push({ start: layerBaseStart, end: i });
191
+ inLayerBase = false;
192
+ }
193
+ }
194
+ }
195
+
196
+ // If we found duplicate @layer base blocks, remove all but the first
197
+ if (layerBaseBlocks.length > 1) {
198
+ const firstBlock = layerBaseBlocks[0];
199
+ const firstBlockContent = lines.slice(firstBlock.start, firstBlock.end + 1).join('\n');
200
+
201
+ // Check if all blocks are identical
202
+ const allIdentical = layerBaseBlocks.every(block => {
203
+ const blockContent = lines.slice(block.start, block.end + 1).join('\n');
204
+ return blockContent === firstBlockContent;
205
+ });
206
+
207
+ if (allIdentical) {
208
+ // Remove all but the first block (working backwards to preserve indices)
209
+ for (let i = layerBaseBlocks.length - 1; i > 0; i--) {
210
+ const block = layerBaseBlocks[i];
211
+ lines.splice(block.start, block.end - block.start + 1);
212
+ }
213
+ indexCss = lines.join('\n');
214
+ }
215
+ }
216
+
217
+ // The :root and .dark blocks are already merged into indexCss
218
+ // Now we just need to add a comment header
219
+ let combinedCss = indexCss;
220
+
221
+ // Add comment before :root if it doesn't already have one
222
+ if (combinedCss.includes(':root') && !combinedCss.includes('nqui Color System')) {
223
+ const rootIndex = combinedCss.indexOf(':root');
224
+ combinedCss = combinedCss.slice(0, rootIndex) +
225
+ '/* ============================================\n' +
226
+ ' nqui Color System & Design Tokens\n' +
227
+ ' ============================================ */\n\n' +
228
+ combinedCss.slice(rootIndex);
229
+ }
230
+
231
+ // Clean up extra blank lines
232
+ combinedCss = combinedCss.replace(/\n{4,}/g, '\n\n\n');
233
+
234
+ // Add header comment
235
+ const header = `/* nqui Design System CSS
236
+ *
237
+ * This file contains ALL design tokens, CSS variables, and color scales from nqui.
238
+ * It includes everything the library needs to style components correctly.
239
+ *
240
+ * IMPORTANT: This file does NOT include Tailwind CSS imports.
241
+ * You must have Tailwind CSS configured in your project.
242
+ *
243
+ * For Tailwind CSS v4, add this at the TOP of your CSS file:
244
+ * @import "tailwindcss";
245
+ *
246
+ * For Tailwind CSS v3, configure it in your tailwind.config.js
247
+ *
248
+ * This file includes:
249
+ * - All CSS variables (--primary, --background, --foreground, etc.)
250
+ * - Complete color scales (100-600) for all semantic colors
251
+ * - Light and dark mode support
252
+ * - Base layer styles
253
+ * - Utility animations
254
+ *
255
+ * Generated by: npx nqui init-css
256
+ * Do not edit manually - regenerate if nqui is updated
257
+ */
258
+
259
+ `;
260
+
261
+ return header + combinedCss;
262
+ }
263
+
264
+ function getFrameworkDirectives(projectType) {
265
+ switch (projectType) {
266
+ case 'nextjs':
267
+ return `@import "tailwindcss";
268
+ @source "./**/*.{js,ts,jsx,tsx,mdx}";
269
+ @source "../components/**/*.{js,ts,jsx,tsx,mdx}";
270
+ @source "../node_modules/@nqlib/nqui/dist/**/*.js";
271
+ @import "../node_modules/tw-animate-css/dist/tw-animate.css";
272
+ @custom-variant dark (&:is(.dark *));
273
+
274
+ `;
275
+ case 'vite':
276
+ case 'create-react-app':
277
+ return `@import "tailwindcss";
278
+ @import "../node_modules/tw-animate-css/dist/tw-animate.css";
279
+
280
+ `;
281
+ case 'remix':
282
+ return `@import "tailwindcss";
283
+ @import "../node_modules/tw-animate-css/dist/tw-animate.css";
284
+
285
+ `;
286
+ default:
287
+ return '';
288
+ }
289
+ }
290
+
291
+ // Function to ask user for input
292
+ function askQuestion(question) {
293
+ const rl = createInterface({
294
+ input: process.stdin,
295
+ output: process.stdout,
296
+ });
297
+
298
+ return new Promise((resolve) => {
299
+ rl.question(question, (answer) => {
300
+ rl.close();
301
+ resolve(answer.trim().toLowerCase());
302
+ });
303
+ });
304
+ }
305
+
306
+ // Function to find Next.js page.tsx file
307
+ function findNextJsPageFile() {
308
+ const possiblePaths = [
309
+ 'src/app/page.tsx',
310
+ 'app/page.tsx',
311
+ ];
312
+
313
+ for (const path of possiblePaths) {
314
+ const fullPath = join(process.cwd(), path);
315
+ if (existsSync(fullPath)) {
316
+ return path;
317
+ }
318
+ }
319
+
320
+ // Default fallback based on directory structure
321
+ if (existsSync(join(process.cwd(), 'src', 'app'))) {
322
+ return 'src/app/page.tsx';
323
+ }
324
+ return 'app/page.tsx';
325
+ }
326
+
327
+ // Function to find Next.js layout.tsx file
328
+ function findNextJsLayoutFile() {
329
+ const possiblePaths = [
330
+ 'src/app/layout.tsx',
331
+ 'app/layout.tsx',
332
+ ];
333
+
334
+ for (const path of possiblePaths) {
335
+ const fullPath = join(process.cwd(), path);
336
+ if (existsSync(fullPath)) {
337
+ return path;
338
+ }
339
+ }
340
+
341
+ // Default fallback based on directory structure
342
+ if (existsSync(join(process.cwd(), 'src', 'app'))) {
343
+ return 'src/app/layout.tsx';
344
+ }
345
+ return 'app/layout.tsx';
346
+ }
347
+
348
+ // Function to copy example files for Next.js
349
+ async function copyNextJsExamples() {
350
+ const pageExamplePath = join(examplesDir, 'nextjs-page.tsx');
351
+ const layoutExamplePath = join(examplesDir, 'nextjs-layout.tsx');
352
+
353
+ if (!existsSync(pageExamplePath) || !existsSync(layoutExamplePath)) {
354
+ console.log('⚠️ Example files not found. Skipping example copy.');
355
+ return;
356
+ }
357
+
358
+ const targetPagePath = findNextJsPageFile();
359
+ const targetLayoutPath = findNextJsLayoutFile();
360
+ const fullPagePath = resolve(process.cwd(), targetPagePath);
361
+ const fullLayoutPath = resolve(process.cwd(), targetLayoutPath);
362
+
363
+ // Check if files exist
364
+ const pageExists = existsSync(fullPagePath);
365
+ const layoutExists = existsSync(fullLayoutPath);
366
+
367
+ if (pageExists || layoutExists) {
368
+ console.log('\n📄 Found existing Next.js files:');
369
+ if (pageExists) console.log(` - ${targetPagePath}`);
370
+ if (layoutExists) console.log(` - ${targetLayoutPath}`);
371
+
372
+ const overwrite = await askQuestion('\n Do you want to overwrite them with nqui examples? (y/n): ');
373
+ if (overwrite !== 'y' && overwrite !== 'yes') {
374
+ console.log(' Skipping example files...');
375
+ return;
376
+ }
377
+ }
378
+
379
+ // Create directories if needed
380
+ const pageDir = dirname(fullPagePath);
381
+ const layoutDir = dirname(fullLayoutPath);
382
+ if (!existsSync(pageDir)) {
383
+ mkdirSync(pageDir, { recursive: true });
384
+ }
385
+ if (!existsSync(layoutDir)) {
386
+ mkdirSync(layoutDir, { recursive: true });
387
+ }
388
+
389
+ // Copy example files
390
+ try {
391
+ const pageContent = readFileSync(pageExamplePath, 'utf-8');
392
+ const layoutContent = readFileSync(layoutExamplePath, 'utf-8');
393
+
394
+ writeFileSync(fullPagePath, pageContent, 'utf-8');
395
+ writeFileSync(fullLayoutPath, layoutContent, 'utf-8');
396
+
397
+ console.log(`✅ Copied example page: ${targetPagePath}`);
398
+ console.log(`✅ Copied example layout: ${targetLayoutPath}`);
399
+ console.log('\n📝 Note: Make sure to install next-themes if not already installed:');
400
+ console.log(' npm install next-themes');
401
+ } catch (error) {
402
+ console.error('❌ Error copying example files:', error.message);
403
+ }
404
+ }
405
+
406
+ async function main() {
407
+ const args = process.argv.slice(2);
408
+ const targetPath = args[0];
409
+
410
+ try {
411
+ // Extract standalone CSS
412
+ const standaloneCss = extractStandaloneCSS();
413
+
414
+ let finalTargetPath;
415
+ let projectType = null;
416
+
417
+ if (targetPath) {
418
+ // User provided a custom path
419
+ finalTargetPath = resolve(process.cwd(), targetPath);
420
+ projectType = findProjectType();
421
+ } else {
422
+ // Auto-detect project type
423
+ projectType = findProjectType();
424
+
425
+ if (projectType) {
426
+ const defaultPath = getDefaultPath(projectType);
427
+ finalTargetPath = resolve(process.cwd(), defaultPath);
428
+ console.log(`📦 Detected ${projectType} project`);
429
+ console.log(` Found CSS file: ${defaultPath}`);
430
+ } else {
431
+ // Fallback: create a new CSS file
432
+ finalTargetPath = resolve(process.cwd(), 'nqui.css');
433
+ console.log('⚠️ Could not detect project type.');
434
+ console.log(` Creating standalone file: nqui.css`);
435
+ console.log(' You can import this file manually in your app.');
436
+ }
437
+ }
438
+
439
+ // Create target directory if it doesn't exist
440
+ const targetDir = dirname(finalTargetPath);
441
+ if (!existsSync(targetDir)) {
442
+ mkdirSync(targetDir, { recursive: true });
443
+ }
444
+
445
+ // Get framework-specific directives
446
+ const frameworkDirectives = projectType ? getFrameworkDirectives(projectType) : '';
447
+ const fullCss = frameworkDirectives + standaloneCss;
448
+
449
+ // Check if target file exists
450
+ if (existsSync(finalTargetPath)) {
451
+ console.log(`\n⚠️ File already exists: ${finalTargetPath}`);
452
+
453
+ // Read existing content
454
+ const existingContent = readFileSync(finalTargetPath, 'utf-8');
455
+
456
+ // Check if nqui CSS is already present
457
+ if (existingContent.includes('nqui Design System CSS') ||
458
+ existingContent.includes('nqui Color System')) {
459
+ console.log(' ⚠️ nqui CSS already present in file.');
460
+ const update = await askQuestion(' Do you want to update it? (y/n): ');
461
+ if (update !== 'y' && update !== 'yes') {
462
+ console.log(' Skipping...');
463
+ return;
464
+ }
465
+ // Remove old nqui CSS and add new
466
+ const cleaned = existingContent.replace(
467
+ /\/\* nqui Design System CSS[\s\S]*?(?=\n\n|\n$|$)/,
468
+ ''
469
+ ).replace(
470
+ /\/\* ============================================[\s\S]*?============================================ \*\/[\s\S]*?}/g,
471
+ ''
472
+ );
473
+ const hasTailwindImport = cleaned.includes('@import "tailwindcss"');
474
+ if (hasTailwindImport && frameworkDirectives) {
475
+ writeFileSync(finalTargetPath, cleaned.trim() + '\n\n' + standaloneCss, 'utf-8');
476
+ } else {
477
+ writeFileSync(finalTargetPath, fullCss + '\n\n' + cleaned.trim(), 'utf-8');
478
+ }
479
+ console.log(`✅ Updated nqui CSS in: ${finalTargetPath}`);
480
+ console.log('\n✨ Done!');
481
+ return;
482
+ }
483
+
484
+ // Ask user what to do
485
+ console.log('\n What would you like to do?');
486
+ console.log(' 1. Overwrite the file (replace all content)');
487
+ console.log(' 2. Append nqui CSS to the file');
488
+ console.log(' 3. Create a separate file (nqui.css) and import it');
489
+
490
+ const choice = await askQuestion('\n Enter your choice (1/2/3): ');
491
+
492
+ if (choice === '1') {
493
+ // Overwrite
494
+ const hasTailwindImport = existingContent.includes('@import "tailwindcss"');
495
+ if (hasTailwindImport && frameworkDirectives) {
496
+ // Keep existing Tailwind setup, add nqui CSS
497
+ writeFileSync(finalTargetPath, existingContent + '\n\n' + standaloneCss, 'utf-8');
498
+ } else {
499
+ // Replace with framework directives + nqui CSS
500
+ writeFileSync(finalTargetPath, fullCss, 'utf-8');
501
+ }
502
+ console.log(`✅ Updated: ${finalTargetPath}`);
503
+ } else if (choice === '2') {
504
+ // Append
505
+ const hasTailwindImport = existingContent.includes('@import "tailwindcss"');
506
+ if (hasTailwindImport && frameworkDirectives) {
507
+ writeFileSync(finalTargetPath, existingContent + '\n\n' + standaloneCss, 'utf-8');
508
+ } else {
509
+ writeFileSync(finalTargetPath, fullCss + '\n\n' + existingContent, 'utf-8');
510
+ }
511
+ console.log(`✅ Appended nqui CSS to: ${finalTargetPath}`);
512
+ } else if (choice === '3') {
513
+ // Create separate file
514
+ const separatePath = join(dirname(finalTargetPath), 'nqui.css');
515
+ writeFileSync(separatePath, standaloneCss, 'utf-8');
516
+ console.log(`✅ Created: ${separatePath}`);
517
+ console.log(`\n📝 Next step: Import this file in ${finalTargetPath}:`);
518
+ const relativeSeparatePath = separatePath.replace(process.cwd() + '/', '');
519
+ const relativeTargetPath = finalTargetPath.replace(process.cwd() + '/', '');
520
+ const importPath = relativeSeparatePath.replace(dirname(relativeTargetPath) + '/', './');
521
+ console.log(` @import "${importPath}";`);
522
+ console.log('\n✨ Done!');
523
+ return;
524
+ } else {
525
+ console.log(' Invalid choice. Skipping...');
526
+ return;
527
+ }
528
+ } else {
529
+ // Create new file with framework directives + nqui CSS
530
+ writeFileSync(finalTargetPath, fullCss, 'utf-8');
531
+ console.log(`✅ Created: ${finalTargetPath}`);
532
+ if (frameworkDirectives) {
533
+ console.log(` Added ${projectType}-specific Tailwind setup`);
534
+ }
535
+ }
536
+
537
+ // Provide next steps
538
+ console.log('\n📝 Next steps:');
539
+ if (!frameworkDirectives) {
540
+ console.log(' 1. Ensure Tailwind CSS is configured in your project');
541
+ console.log(' 2. Add Tailwind imports at the top of this CSS file if needed');
542
+ }
543
+ console.log(' 3. The CSS file is ready to use!');
544
+
545
+ // Offer to copy example files for Next.js
546
+ if (projectType === 'nextjs') {
547
+ const copyExamples = await askQuestion('\n Would you like to copy example Next.js files (page.tsx, layout.tsx)? (y/n): ');
548
+ if (copyExamples === 'y' || copyExamples === 'yes') {
549
+ await copyNextJsExamples();
550
+ }
551
+ }
552
+
553
+ console.log('\n✨ Done!');
554
+ } catch (error) {
555
+ console.error('❌ Error:', error.message);
556
+ if (error.message.includes('not found')) {
557
+ console.error(' Please ensure you are running this from the nqui package directory');
558
+ console.error(' or that the source CSS files exist.');
559
+ }
560
+ process.exit(1);
561
+ }
562
+ }
563
+
564
+ main().catch((error) => {
565
+ console.error('❌ Unexpected error:', error);
566
+ process.exit(1);
567
+ });
568
+
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * nqui debug CSS initialization script
5
+ *
6
+ * Copies the debug CSS file to the user's project.
7
+ * Usage: npx nqui init-debug-css [target-path]
8
+ */
9
+
10
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
11
+ import { join, dirname, resolve } from 'path';
12
+ import { fileURLToPath } from 'url';
13
+
14
+ const __filename = fileURLToPath(import.meta.url);
15
+ const __dirname = dirname(__filename);
16
+
17
+ // Get the project root (where package.json is)
18
+ const projectRoot = resolve(__dirname, '..');
19
+ const cssSourcePath = join(projectRoot, 'dist', 'nqui.css');
20
+
21
+ // Default target paths for common frameworks
22
+ const defaultTargets = {
23
+ nextjs: 'app/globals.css', // or styles/globals.css
24
+ vite: 'src/index.css',
25
+ remix: 'app/root.css',
26
+ 'create-react-app': 'src/index.css',
27
+ };
28
+
29
+ function findProjectType() {
30
+ // Check for framework-specific files
31
+ if (existsSync(join(process.cwd(), 'next.config.js')) ||
32
+ existsSync(join(process.cwd(), 'next.config.ts'))) {
33
+ return 'nextjs';
34
+ }
35
+ if (existsSync(join(process.cwd(), 'vite.config.js')) ||
36
+ existsSync(join(process.cwd(), 'vite.config.ts'))) {
37
+ return 'vite';
38
+ }
39
+ if (existsSync(join(process.cwd(), 'remix.config.js'))) {
40
+ return 'remix';
41
+ }
42
+ if (existsSync(join(process.cwd(), 'src', 'index.css'))) {
43
+ return 'create-react-app';
44
+ }
45
+ return null;
46
+ }
47
+
48
+ function main() {
49
+ const args = process.argv.slice(2);
50
+ const targetPath = args[0];
51
+
52
+ // Check if CSS source exists
53
+ if (!existsSync(cssSourcePath)) {
54
+ console.error('❌ Error: nqui.css not found in dist folder.');
55
+ console.error(' Please run "npm run build:lib" first to build the library.');
56
+ process.exit(1);
57
+ }
58
+
59
+ let finalTargetPath;
60
+
61
+ if (targetPath) {
62
+ // User provided a custom path
63
+ finalTargetPath = resolve(process.cwd(), targetPath);
64
+ } else {
65
+ // Auto-detect project type
66
+ const projectType = findProjectType();
67
+
68
+ if (projectType) {
69
+ const defaultPath = defaultTargets[projectType];
70
+ finalTargetPath = resolve(process.cwd(), defaultPath);
71
+ console.log(`📦 Detected ${projectType} project`);
72
+ console.log(` Using default path: ${defaultPath}`);
73
+ } else {
74
+ // Fallback: create a new CSS file
75
+ finalTargetPath = resolve(process.cwd(), 'nqui-debug.css');
76
+ console.log('⚠️ Could not detect project type.');
77
+ console.log(` Creating standalone file: nqui-debug.css`);
78
+ console.log(' You can import this file manually in your app.');
79
+ }
80
+ }
81
+
82
+ // Read the CSS file
83
+ const cssContent = readFileSync(cssSourcePath, 'utf-8');
84
+
85
+ // Create target directory if it doesn't exist
86
+ const targetDir = dirname(finalTargetPath);
87
+ if (!existsSync(targetDir)) {
88
+ mkdirSync(targetDir, { recursive: true });
89
+ }
90
+
91
+ // Check if target file exists
92
+ if (existsSync(finalTargetPath)) {
93
+ console.log(`⚠️ File already exists: ${finalTargetPath}`);
94
+ console.log(' The CSS will be appended to the existing file.');
95
+
96
+ // Append import statement instead of overwriting
97
+ const existingContent = readFileSync(finalTargetPath, 'utf-8');
98
+ const importStatement = '\n\n/* nqui debug tools CSS - imported via init script */\n';
99
+
100
+ if (!existingContent.includes('nqui-debug') && !existingContent.includes('data-debug-panel')) {
101
+ writeFileSync(finalTargetPath, existingContent + importStatement + cssContent, 'utf-8');
102
+ console.log(`✅ Appended nqui debug CSS to: ${finalTargetPath}`);
103
+ } else {
104
+ console.log(' CSS already imported. Skipping...');
105
+ }
106
+ } else {
107
+ // Create new file
108
+ writeFileSync(finalTargetPath, cssContent, 'utf-8');
109
+ console.log(`✅ Created: ${finalTargetPath}`);
110
+ }
111
+
112
+ // Provide next steps
113
+ console.log('\n📝 Next steps:');
114
+ console.log(' 1. Import the CSS in your app entry point:');
115
+ console.log(` import './${finalTargetPath.replace(process.cwd() + '/', '')}'`);
116
+ console.log(' 2. Use DebugPanel in your app:');
117
+ console.log(' import { DebugPanel } from "nqui"');
118
+ console.log(' 3. Add DebugPanel to your root component');
119
+ console.log('\n✨ Done!');
120
+ }
121
+
122
+ main();
123
+