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,51 @@
1
+ import React from 'react';
2
+ import { Text, Box } from 'ink';
3
+ export default function Summary({ features, projectPath }) {
4
+ return (React.createElement(Box, { flexDirection: "column", padding: 1 },
5
+ React.createElement(Box, { borderStyle: "round", borderColor: "green", paddingX: 2, paddingY: 1, marginBottom: 1 },
6
+ React.createElement(Text, { color: "green", bold: true }, "\u2728 Setup Complete!")),
7
+ React.createElement(Box, { flexDirection: "column", paddingLeft: 1 },
8
+ React.createElement(Text, { color: "cyan", bold: true }, "\uD83D\uDCCB Project Summary"),
9
+ React.createElement(Text, null, " "),
10
+ React.createElement(Box, { flexDirection: "column", paddingLeft: 2 },
11
+ React.createElement(Text, null,
12
+ React.createElement(Text, { color: "magenta" }, "Project Type:"),
13
+ " ",
14
+ React.createElement(Text, { color: "green", bold: true }, features.projectType)),
15
+ features.projectName && (React.createElement(Text, null,
16
+ React.createElement(Text, { color: "magenta" }, "Project Name:"),
17
+ " ",
18
+ React.createElement(Text, { color: "green", bold: true }, features.projectName))),
19
+ React.createElement(Text, null,
20
+ React.createElement(Text, { color: "magenta" }, "Three.js:"),
21
+ " ",
22
+ React.createElement(Text, { color: features.threejs ? 'green' : 'gray', bold: true }, features.threejs ? 'Yes' : 'No')),
23
+ React.createElement(Text, null,
24
+ React.createElement(Text, { color: "magenta" }, "CSS Variables:"),
25
+ " ",
26
+ React.createElement(Text, { color: "green", bold: true }, "Yes"),
27
+ " ",
28
+ React.createElement(Text, { color: "gray" }, "(auto-generated)")),
29
+ React.createElement(Text, null,
30
+ React.createElement(Text, { color: "magenta" }, "Project Path:"),
31
+ " ",
32
+ React.createElement(Text, { color: "white" }, projectPath))),
33
+ React.createElement(Text, null, " "),
34
+ React.createElement(Box, { borderStyle: "single", borderColor: "cyan", paddingX: 1, paddingY: 1 },
35
+ React.createElement(Text, { color: "cyan", bold: true }, "\uD83D\uDE80 Next Steps"),
36
+ React.createElement(Text, null, " "),
37
+ React.createElement(Box, { flexDirection: "column", paddingLeft: 2 },
38
+ React.createElement(Text, null,
39
+ React.createElement(Text, { color: "yellow" }, "1."),
40
+ " ",
41
+ React.createElement(Text, { color: "white" }, "cd "),
42
+ React.createElement(Text, { color: "green", bold: true }, features.projectName || projectPath)),
43
+ React.createElement(Text, null,
44
+ React.createElement(Text, { color: "yellow" }, "2."),
45
+ " ",
46
+ React.createElement(Text, { color: "white" }, "Install dependencies (if not already done)")),
47
+ React.createElement(Text, null,
48
+ React.createElement(Text, { color: "yellow" }, "3."),
49
+ " ",
50
+ React.createElement(Text, { color: "white" }, "Start development server")))))));
51
+ }
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export default function WelcomeHeader(): React.JSX.Element;
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { Text, Box } from 'ink';
3
+ export default function WelcomeHeader() {
4
+ return (React.createElement(Box, { flexDirection: "column", marginBottom: 1 },
5
+ React.createElement(Box, { borderStyle: "double", borderColor: "cyan", paddingX: 2, paddingY: 1 },
6
+ React.createElement(Text, { color: "magenta", bold: true }, "\uD83D\uDE80 PNI - Project Setup CLI"),
7
+ React.createElement(Text, { color: "gray" }, "Nuxt/Vue + Three.js + CSS Variables"))));
8
+ }
@@ -0,0 +1,146 @@
1
+ # Three.js Setup for Nuxt
2
+
3
+ A professional, modular Three.js setup optimized for Nuxt 3 applications with proper cleanup and developer-friendly patterns.
4
+
5
+ ## Structure
6
+
7
+ ```
8
+ three/
9
+ ├── World.js # Main Three.js world orchestrator
10
+ ├── camera.js # Camera configuration
11
+ ├── scene.js # Scene setup with meshes
12
+ ├── components/ # 3D objects/meshes
13
+ │ ├── cube.js # Rotating cube
14
+ │ ├── torus.js # Animated torus
15
+ │ ├── sphere.js # Floating sphere
16
+ │ └── lights.js # Scene lighting
17
+ ├── systems/ # Core Three.js systems
18
+ │ ├── renderer.js # WebGL renderer
19
+ │ ├── Loop.js # Animation loop
20
+ │ ├── Resizer.js # Responsive canvas
21
+ │ ├── controls.js # Camera controls
22
+ │ └── post-processing.js # Post-processing effects
23
+ └── utils/ # Utility functions
24
+ ```
25
+
26
+ ## Usage in Nuxt
27
+
28
+ ### Basic Setup
29
+
30
+ ```vue
31
+ <script setup lang="ts">
32
+ import {ref} from 'vue';
33
+ import {useThree} from '@/composables/useThree';
34
+
35
+ const webglContainer = ref<HTMLElement | null>(null);
36
+ const {world, isLoading, error} = useThree(webglContainer);
37
+ </script>
38
+
39
+ <template>
40
+ <div ref="webglContainer" class="webgl-container">
41
+ <div v-if="isLoading">Loading 3D Scene...</div>
42
+ <div v-if="error">Error: {{ error.message }}</div>
43
+ </div>
44
+ </template>
45
+
46
+ <style scoped>
47
+ .webgl-container {
48
+ position: fixed;
49
+ width: 100%;
50
+ height: 100%;
51
+ }
52
+ </style>
53
+ ```
54
+
55
+ ## Features
56
+
57
+ - ✅ **Proper Cleanup**: Automatic disposal of resources on component unmount
58
+ - ✅ **SSR Safe**: Works with Nuxt's server-side rendering
59
+ - ✅ **Modular**: Easy to add/remove 3D objects
60
+ - ✅ **Performance**: Optimized renderer settings and animation loop
61
+ - ✅ **Responsive**: Auto-resize handling
62
+ - ✅ **Post-processing**: Built-in effects (SMAA, noise, bloom)
63
+ - ✅ **Developer Friendly**: TypeScript support via composable
64
+
65
+ ## Adding New Objects
66
+
67
+ Create a new file in `components/`:
68
+
69
+ ```js
70
+ // components/myMesh.js
71
+ import {BoxGeometry, Mesh, MeshStandardMaterial} from 'three';
72
+
73
+ function createMyMesh() {
74
+ const geometry = new BoxGeometry(1, 1, 1);
75
+ const material = new MeshStandardMaterial({color: '#ff0000'});
76
+ const mesh = new Mesh(geometry, material);
77
+
78
+ // Optional: Add animation
79
+ mesh.tick = delta => {
80
+ mesh.rotation.y += delta;
81
+ };
82
+
83
+ return mesh;
84
+ }
85
+
86
+ export {createMyMesh};
87
+ ```
88
+
89
+ Then add it to `scene.js`:
90
+
91
+ ```js
92
+ import { createMyMesh } from './components/myMesh.js';
93
+
94
+ function createScene() {
95
+ // ...
96
+ const myMesh = createMyMesh();
97
+ scene.add(myMesh);
98
+
99
+ // Add to updatables if it has tick method
100
+ scene.userData.updatables = [..., myMesh];
101
+ // ...
102
+ }
103
+ ```
104
+
105
+ ## Performance Tips
106
+
107
+ 1. **Pixel Ratio**: Automatically capped at 2 for performance
108
+ 2. **Animation Loop**: Uses `requestAnimationFrame` via Three.js
109
+ 3. **Proper Disposal**: All resources cleaned up on unmount
110
+ 4. **Post-processing**: Can be disabled for better performance
111
+
112
+ ## Customization
113
+
114
+ ### Adjust Camera
115
+
116
+ Edit `camera.js`:
117
+
118
+ ```js
119
+ camera.position.set(x, y, z);
120
+ ```
121
+
122
+ ### Modify Controls
123
+
124
+ Edit `systems/controls.js`:
125
+
126
+ ```js
127
+ controls.autoRotate = true;
128
+ controls.autoRotateSpeed = 2;
129
+ ```
130
+
131
+ ### Change Background
132
+
133
+ Edit `scene.js`:
134
+
135
+ ```js
136
+ scene.background = new Color('#yourcolor');
137
+ ```
138
+
139
+ ### Toggle Post-processing
140
+
141
+ Comment out in `World.js`:
142
+
143
+ ```js
144
+ // this.composer = createPostprocessing(...)
145
+ // Use this.renderer.render() instead of this.composer.render()
146
+ ```
@@ -0,0 +1,133 @@
1
+ import {camera} from './camera.js';
2
+ import {createScene} from './scene.js';
3
+ import {createControls} from './systems/controls.js';
4
+ import {createRenderer} from './systems/renderer.js';
5
+ import {Resizer} from './systems/Resizer.js';
6
+ import {Loop} from './systems/Loop.js';
7
+ import {createPostprocessing} from './systems/post-processing.js';
8
+
9
+ class World {
10
+ constructor(container) {
11
+ this.container = container;
12
+ this.camera = camera;
13
+ this.scene = null;
14
+ this.renderer = createRenderer();
15
+ this.loop = null;
16
+ this.controls = null;
17
+ this.resizer = null;
18
+ this.composer = null;
19
+
20
+ // Append canvas to container
21
+ container.append(this.renderer.domElement);
22
+ }
23
+
24
+ init() {
25
+ // Create scene
26
+ this.scene = createScene();
27
+
28
+ // Create controls
29
+ this.controls = createControls(this.camera, this.renderer.domElement);
30
+
31
+ // Create post-processing composer
32
+ this.composer = createPostprocessing(
33
+ this.scene,
34
+ this.camera,
35
+ this.renderer,
36
+ );
37
+
38
+ // Create loop
39
+ this.loop = new Loop(this.camera, this.scene, this.renderer, this.composer);
40
+
41
+ // Add scene updatables to loop
42
+ if (this.scene.userData.updatables) {
43
+ this.loop.updatables.push(...this.scene.userData.updatables);
44
+ }
45
+
46
+ // Add controls to loop
47
+ this.loop.updatables.push(this.controls);
48
+
49
+ // Initialize resizer
50
+ this.resizer = new Resizer(
51
+ this.container,
52
+ this.camera,
53
+ this.renderer,
54
+ this.composer,
55
+ );
56
+ }
57
+
58
+ start() {
59
+ if (this.loop) {
60
+ this.loop.start();
61
+ }
62
+ }
63
+
64
+ stop() {
65
+ if (this.loop) {
66
+ this.loop.stop();
67
+ }
68
+ }
69
+
70
+ dispose() {
71
+ // Stop animation loop
72
+ this.stop();
73
+
74
+ // Dispose controls
75
+ if (this.controls) {
76
+ this.controls.dispose();
77
+ }
78
+
79
+ // Traverse scene and dispose geometries, materials, and textures
80
+ if (this.scene) {
81
+ this.scene.traverse(object => {
82
+ if (object.geometry) {
83
+ object.geometry.dispose();
84
+ }
85
+ if (object.material) {
86
+ if (Array.isArray(object.material)) {
87
+ object.material.forEach(material => {
88
+ this.disposeMaterial(material);
89
+ });
90
+ } else {
91
+ this.disposeMaterial(object.material);
92
+ }
93
+ }
94
+ });
95
+ }
96
+
97
+ // Dispose composer
98
+ if (this.composer) {
99
+ this.composer.dispose();
100
+ }
101
+
102
+ // Dispose renderer and remove canvas
103
+ if (this.renderer) {
104
+ this.renderer.dispose();
105
+ if (this.renderer.domElement && this.renderer.domElement.parentNode) {
106
+ this.renderer.domElement.parentNode.removeChild(
107
+ this.renderer.domElement,
108
+ );
109
+ }
110
+ }
111
+
112
+ // Clear references
113
+ this.camera = null;
114
+ this.scene = null;
115
+ this.renderer = null;
116
+ this.composer = null;
117
+ this.loop = null;
118
+ this.controls = null;
119
+ this.resizer = null;
120
+ }
121
+
122
+ disposeMaterial(material) {
123
+ if (material.map) material.map.dispose();
124
+ if (material.lightMap) material.lightMap.dispose();
125
+ if (material.bumpMap) material.bumpMap.dispose();
126
+ if (material.normalMap) material.normalMap.dispose();
127
+ if (material.specularMap) material.specularMap.dispose();
128
+ if (material.envMap) material.envMap.dispose();
129
+ material.dispose();
130
+ }
131
+ }
132
+
133
+ export {World};
@@ -0,0 +1,30 @@
1
+ import {PerspectiveCamera} from 'three';
2
+
3
+ const getAspectRatio = () => {
4
+ if (typeof window !== 'undefined') {
5
+ return window.innerWidth / window.innerHeight;
6
+ }
7
+ return 16 / 9; // Default aspect ratio for SSR
8
+ };
9
+
10
+ const getFov = (z = 500) => {
11
+ // avoid accessing window during SSR
12
+ if (typeof window !== 'undefined') {
13
+ return (180 * (2 * Math.atan(window.innerHeight / 2 / z))) / Math.PI;
14
+ }
15
+ // Use a default 16:9 height for SSR (e.g., 1080p)
16
+ const defaultHeight = 1080;
17
+ return (180 * (2 * Math.atan(defaultHeight / 2 / z))) / Math.PI;
18
+ };
19
+
20
+ const camera = new PerspectiveCamera(
21
+ 50, // fov = Field Of View
22
+ getAspectRatio(), // aspect ratio
23
+ 0.01, // near clipping plane
24
+ 1000, // far clipping plane
25
+ );
26
+
27
+ camera.position.set(0, 0, 8);
28
+
29
+ export {camera};
30
+ export default camera;