pni 1.0.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 (50) hide show
  1. package/dist/add-three-app.d.ts +6 -0
  2. package/dist/add-three-app.js +111 -0
  3. package/dist/app.d.ts +11 -0
  4. package/dist/app.js +143 -0
  5. package/dist/cli.d.ts +2 -0
  6. package/dist/cli.js +71 -0
  7. package/dist/components/FeatureSelector.d.ts +21 -0
  8. package/dist/components/FeatureSelector.js +175 -0
  9. package/dist/components/ProgressIndicator.d.ts +7 -0
  10. package/dist/components/ProgressIndicator.js +46 -0
  11. package/dist/components/Summary.d.ts +8 -0
  12. package/dist/components/Summary.js +51 -0
  13. package/dist/components/WelcomeHeader.d.ts +2 -0
  14. package/dist/components/WelcomeHeader.js +8 -0
  15. package/dist/template_code/three/README.md +146 -0
  16. package/dist/template_code/three/World.js +133 -0
  17. package/dist/template_code/three/camera.js +30 -0
  18. package/dist/template_code/three/components/GlobeSphere.js +608 -0
  19. package/dist/template_code/three/components/cube.js +27 -0
  20. package/dist/template_code/three/components/lights.js +16 -0
  21. package/dist/template_code/three/components/sphere.js +26 -0
  22. package/dist/template_code/three/components/torus.js +25 -0
  23. package/dist/template_code/three/scene.js +28 -0
  24. package/dist/template_code/three/systems/Loop.js +43 -0
  25. package/dist/template_code/three/systems/Resizer.js +26 -0
  26. package/dist/template_code/three/systems/controls.js +19 -0
  27. package/dist/template_code/three/systems/post-processing.js +50 -0
  28. package/dist/template_code/three/systems/renderer.js +17 -0
  29. package/dist/template_code/three/utils/deviceDetector.js +141 -0
  30. package/dist/template_code/three/utils/gltfLoader.js +14 -0
  31. package/dist/template_code/three/utils/loadKTX2Texture.js +42 -0
  32. package/dist/template_code/three/utils/textureLoader.js +21 -0
  33. package/dist/utils/add-three.d.ts +7 -0
  34. package/dist/utils/add-three.js +288 -0
  35. package/dist/utils/app-creation.d.ts +4 -0
  36. package/dist/utils/app-creation.js +35 -0
  37. package/dist/utils/config-generator.d.ts +6 -0
  38. package/dist/utils/config-generator.js +508 -0
  39. package/dist/utils/css-variables.d.ts +4 -0
  40. package/dist/utils/css-variables.js +316 -0
  41. package/dist/utils/dependencies.d.ts +11 -0
  42. package/dist/utils/dependencies.js +68 -0
  43. package/dist/utils/package-manager.d.ts +4 -0
  44. package/dist/utils/package-manager.js +56 -0
  45. package/dist/utils/project-detection.d.ts +2 -0
  46. package/dist/utils/project-detection.js +60 -0
  47. package/dist/utils/shadcn-setup.d.ts +2 -0
  48. package/dist/utils/shadcn-setup.js +46 -0
  49. package/package.json +81 -0
  50. package/readme.md +119 -0
@@ -0,0 +1,288 @@
1
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, cpSync } from 'fs';
2
+ import { join, dirname, basename, resolve, relative } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import { detectProjectType } from './project-detection.js';
5
+ const __filename = fileURLToPath(import.meta.url);
6
+ const __dirname = dirname(__filename);
7
+ /**
8
+ * Find app folder by looking for app directory going up the directory tree (Nuxt)
9
+ * or src folder (Vue)
10
+ */
11
+ function findComposablesFolder(startPath, projectType) {
12
+ let currentPath = resolve(startPath);
13
+ while (currentPath !== dirname(currentPath)) {
14
+ if (projectType === 'nuxt') {
15
+ const appPath = join(currentPath, 'app');
16
+ if (existsSync(appPath)) {
17
+ return join(appPath, 'composables');
18
+ }
19
+ }
20
+ else {
21
+ // Vue project
22
+ const srcPath = join(currentPath, 'src');
23
+ if (existsSync(srcPath)) {
24
+ return join(srcPath, 'composables');
25
+ }
26
+ }
27
+ currentPath = dirname(currentPath);
28
+ }
29
+ if (projectType === 'nuxt') {
30
+ throw new Error('app folder not found. Please run this command in a Nuxt project with an app directory.');
31
+ }
32
+ else {
33
+ throw new Error('src folder not found. Please run this command in a Vue project.');
34
+ }
35
+ }
36
+ /**
37
+ * Find project root by looking for package.json going up the directory tree
38
+ */
39
+ function findProjectRoot(startPath) {
40
+ let currentPath = resolve(startPath);
41
+ while (currentPath !== dirname(currentPath)) {
42
+ const packageJsonPath = join(currentPath, 'package.json');
43
+ if (existsSync(packageJsonPath)) {
44
+ return currentPath;
45
+ }
46
+ currentPath = dirname(currentPath);
47
+ }
48
+ throw new Error('Project root not found. Please run this command in a Nuxt/Vue project.');
49
+ }
50
+ export async function addThree(currentDir) {
51
+ const currentPath = resolve(currentDir);
52
+ const directoryName = basename(currentPath);
53
+ // Find project root to check for three.js
54
+ const projectRoot = findProjectRoot(currentPath);
55
+ const packageJsonPath = join(projectRoot, 'package.json');
56
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
57
+ const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
58
+ if (!deps.three) {
59
+ throw new Error('Three.js is not installed. Please install it first: npm install three');
60
+ }
61
+ // Detect project type
62
+ const projectType = await detectProjectType(projectRoot);
63
+ if (projectType !== 'nuxt' && projectType !== 'vue') {
64
+ throw new Error('Project type not supported. Please run this command in a Nuxt or Vue project.');
65
+ }
66
+ // Find composables folder (app/composables for Nuxt, src/composables for Vue)
67
+ const composablesFolder = findComposablesFolder(currentPath, projectType);
68
+ const appFolder = projectType === 'nuxt'
69
+ ? join(composablesFolder, '..') // app folder
70
+ : join(composablesFolder, '..'); // src folder
71
+ // Get template directory path
72
+ // When compiled: dist/utils/add-three.js -> dist/template_code/three
73
+ // When in source: source/utils/add-three.ts -> source/template_code/three
74
+ let templateDir = join(__dirname, '..', 'template_code', 'three');
75
+ if (!existsSync(templateDir)) {
76
+ // Try from source location (for development/testing)
77
+ const sourceTemplateDir = join(__dirname, '..', '..', 'source', 'template_code', 'three');
78
+ if (existsSync(sourceTemplateDir)) {
79
+ templateDir = sourceTemplateDir;
80
+ }
81
+ else {
82
+ throw new Error('Three.js template not found. Expected at: ' +
83
+ templateDir +
84
+ ' or ' +
85
+ sourceTemplateDir);
86
+ }
87
+ }
88
+ // Copy template to three/ in current directory (where command is run)
89
+ const targetDir = join(currentPath, 'three');
90
+ // Copy the template directory
91
+ if (existsSync(targetDir)) {
92
+ throw new Error('three directory already exists. Please remove it first.');
93
+ }
94
+ cpSync(templateDir, targetDir, { recursive: true });
95
+ // Create composables/{directoryName} inside app/src folder
96
+ const composablesTargetDir = join(composablesFolder, directoryName);
97
+ if (!existsSync(composablesTargetDir)) {
98
+ mkdirSync(composablesTargetDir, { recursive: true });
99
+ }
100
+ // Calculate import path from composables/{directoryName} to three folder
101
+ // In Nuxt/Vue, @/ resolves to project root (Nuxt) or src (Vue), so we use the path relative to project root
102
+ const threePathRelative = relative(projectRoot, targetDir).replace(/\\/g, '/');
103
+ const importPath = `@/${threePathRelative}/World.js`;
104
+ // Determine file extension based on project type
105
+ const fileExtension = projectType === 'vue' ? 'js' : 'ts';
106
+ // Create usethree.{js|ts}
107
+ const useThreePath = join(composablesTargetDir, `usethree.${fileExtension}`);
108
+ // Type annotations only for TypeScript
109
+ const typeAnnotations = projectType === 'nuxt'
110
+ ? `: Ref<HTMLElement | null>`
111
+ : '';
112
+ const typeImports = projectType === 'nuxt'
113
+ ? `, type Ref`
114
+ : '';
115
+ const worldType = projectType === 'nuxt' ? `<World | null>` : '';
116
+ const errorType = projectType === 'nuxt' ? `<Error | null>` : '';
117
+ const useThreeContent = `import { ref, onMounted, onBeforeUnmount, markRaw, nextTick${typeImports} } from 'vue';
118
+ import { World } from '${importPath}';
119
+
120
+ export function useThree(containerRef${typeAnnotations}) {
121
+ const world = ref${worldType}(null);
122
+ const isLoading = ref(true);
123
+ const error = ref${errorType}(null);
124
+
125
+ const init = async () => {
126
+ if (!containerRef.value) {
127
+ error.value = new Error('Container element not found');
128
+ isLoading.value = false;
129
+ return;
130
+ }
131
+
132
+ try {
133
+ // Create Three.js world and mark as non-reactive to prevent proxy issues
134
+ const worldInstance = new World(containerRef.value);
135
+ world.value = markRaw(worldInstance);
136
+
137
+ // Initialize scene
138
+ world.value.init();
139
+
140
+ // Start render loop
141
+ world.value.start();
142
+
143
+ isLoading.value = false;
144
+ } catch (e) {
145
+ error.value = e instanceof Error ? e : new Error('Failed to initialize Three.js');
146
+ isLoading.value = false;
147
+ console.error('Three.js initialization error:', e);
148
+ }
149
+ };
150
+
151
+ const cleanup = () => {
152
+ if (world.value) {
153
+ world.value.dispose();
154
+ world.value = null;
155
+ }
156
+ };
157
+
158
+ onMounted(() => {
159
+ // Wait for next tick to ensure DOM is ready
160
+ nextTick(() => init());
161
+ });
162
+
163
+ onBeforeUnmount(() => {
164
+ cleanup();
165
+ });
166
+
167
+ return {
168
+ world,
169
+ isLoading,
170
+ error,
171
+ cleanup,
172
+ };
173
+ }
174
+ `;
175
+ writeFileSync(useThreePath, useThreeContent, 'utf-8');
176
+ // Create useThreeAdvanced.{js|ts}
177
+ const useThreeAdvancedPath = join(composablesTargetDir, `useThreeAdvanced.${fileExtension}`);
178
+ const threeTypeImports = projectType === 'nuxt'
179
+ ? `import type { Scene, Camera, WebGLRenderer } from 'three';`
180
+ : '';
181
+ const useThreeAdvancedContent = `import { ref, onMounted, onBeforeUnmount, markRaw, nextTick${typeImports} } from 'vue';
182
+ import { World } from '${importPath}';
183
+ ${threeTypeImports}
184
+
185
+ /**
186
+ * Advanced Three.js composable with more control and access to internals
187
+ * Use this when you need direct access to scene, camera, renderer, etc.
188
+ */
189
+ export function useThreeAdvanced(containerRef${typeAnnotations}) {
190
+ const world = ref${worldType}(null);
191
+ const isLoading = ref(true);
192
+ const error = ref${errorType}(null);
193
+ const isRunning = ref(false);
194
+
195
+ // Getters for Three.js internals
196
+ const scene = ref${projectType === 'nuxt' ? '<Scene | null>' : ''}(null);
197
+ const camera = ref${projectType === 'nuxt' ? '<Camera | null>' : ''}(null);
198
+ const renderer = ref${projectType === 'nuxt' ? '<WebGLRenderer | null>' : ''}(null);
199
+
200
+ const init = async () => {
201
+ if (!containerRef.value) {
202
+ error.value = new Error('Container element not found');
203
+ isLoading.value = false;
204
+ return;
205
+ }
206
+
207
+ try {
208
+ // Create Three.js world and mark as non-reactive to prevent proxy issues
209
+ const worldInstance = new World(containerRef.value);
210
+ world.value = markRaw(worldInstance);
211
+
212
+ // Initialize scene
213
+ world.value.init();
214
+
215
+ // Store references and mark Three.js objects as non-reactive
216
+ scene.value = markRaw(world.value.scene${projectType === 'nuxt' ? ' as Scene' : ''});
217
+ camera.value = markRaw(world.value.camera);
218
+ renderer.value = markRaw(world.value.renderer);
219
+
220
+ // Start render loop
221
+ world.value.start();
222
+ isRunning.value = true;
223
+
224
+ isLoading.value = false;
225
+ } catch (e) {
226
+ error.value = e instanceof Error ? e : new Error('Failed to initialize Three.js');
227
+ isLoading.value = false;
228
+ console.error('Three.js initialization error:', e);
229
+ }
230
+ };
231
+
232
+ const start = () => {
233
+ if (world.value && !isRunning.value) {
234
+ world.value.start();
235
+ isRunning.value = true;
236
+ }
237
+ };
238
+
239
+ const stop = () => {
240
+ if (world.value && isRunning.value) {
241
+ world.value.stop();
242
+ isRunning.value = false;
243
+ }
244
+ };
245
+
246
+ const cleanup = () => {
247
+ if (world.value) {
248
+ world.value.dispose();
249
+ world.value = null;
250
+ scene.value = null;
251
+ camera.value = null;
252
+ renderer.value = null;
253
+ isRunning.value = false;
254
+ }
255
+ };
256
+
257
+ onMounted(() => {
258
+ // Wait for next tick to ensure DOM is ready
259
+ nextTick(() => init());
260
+ });
261
+
262
+ onBeforeUnmount(() => {
263
+ cleanup();
264
+ });
265
+
266
+ return {
267
+ world,
268
+ scene,
269
+ camera,
270
+ renderer,
271
+ isLoading,
272
+ isRunning,
273
+ error,
274
+ start,
275
+ stop,
276
+ cleanup,
277
+ };
278
+ }
279
+ `;
280
+ writeFileSync(useThreeAdvancedPath, useThreeAdvancedContent, 'utf-8');
281
+ return {
282
+ directoryName,
283
+ appFolder,
284
+ threePath: targetDir,
285
+ projectType,
286
+ fileExtension,
287
+ };
288
+ }
@@ -0,0 +1,4 @@
1
+ import type { ProjectType } from './project-detection.js';
2
+ export declare function createNuxtApp(dir: string, name: string): Promise<void>;
3
+ export declare function createVueApp(dir: string, name: string): Promise<void>;
4
+ export declare function createApp(projectType: ProjectType, dir: string, name: string): Promise<void>;
@@ -0,0 +1,35 @@
1
+ import { execSync } from 'child_process';
2
+ export async function createNuxtApp(dir, name) {
3
+ try {
4
+ execSync(`npx nuxi@latest init ${name}`, {
5
+ cwd: dir,
6
+ stdio: 'inherit',
7
+ });
8
+ }
9
+ catch (error) {
10
+ throw new Error(`Failed to create Nuxt app: ${error}`);
11
+ }
12
+ }
13
+ export async function createVueApp(dir, name) {
14
+ try {
15
+ // Use npm create vue@latest for Vue 3
16
+ execSync(`npm create vue@latest ${name} -- --yes`, {
17
+ cwd: dir,
18
+ stdio: 'inherit',
19
+ });
20
+ }
21
+ catch (error) {
22
+ throw new Error(`Failed to create Vue app: ${error}`);
23
+ }
24
+ }
25
+ export async function createApp(projectType, dir, name) {
26
+ if (projectType === 'nuxt') {
27
+ await createNuxtApp(dir, name);
28
+ }
29
+ else if (projectType === 'vue') {
30
+ await createVueApp(dir, name);
31
+ }
32
+ else {
33
+ throw new Error('Cannot create app: project type must be nuxt or vue');
34
+ }
35
+ }
@@ -0,0 +1,6 @@
1
+ import type { ProjectType } from './project-detection.js';
2
+ export declare function generateNuxtConfig(projectPath: string, threejs: boolean, cssVars: boolean): Promise<void>;
3
+ export declare function generateViteConfig(projectPath: string, threejs: boolean, cssVars?: boolean): Promise<void>;
4
+ export declare function generateTailwindConfig(projectPath: string, projectType: ProjectType): Promise<void>;
5
+ export declare function generatePostCSSConfig(projectPath: string): Promise<void>;
6
+ export declare function generateConfigFiles(projectType: ProjectType, projectPath: string, threejs: boolean, cssVars: boolean): Promise<void>;