create-nativecore 0.1.1 → 0.2.1

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 (175) hide show
  1. package/README.md +6 -14
  2. package/bin/index.mjs +403 -431
  3. package/package.json +3 -2
  4. package/template/.env.example +28 -0
  5. package/template/.htmlhintrc +14 -0
  6. package/template/api/data/dashboard.json +11 -0
  7. package/template/api/data/users.json +18 -0
  8. package/template/api/mockApi.js +161 -0
  9. package/template/assets/icon.svg +13 -0
  10. package/template/assets/logo.svg +25 -0
  11. package/template/eslint.config.js +94 -0
  12. package/template/index.html +137 -0
  13. package/template/manifest.json +19 -0
  14. package/template/public/.well-known/security.txt +9 -0
  15. package/template/public/_headers +24 -0
  16. package/template/public/_redirects +14 -0
  17. package/template/public/assets/icon.svg +13 -0
  18. package/template/public/assets/logo.svg +25 -0
  19. package/template/public/manifest.json +19 -0
  20. package/template/public/robots.txt +13 -0
  21. package/template/public/sitemap.xml +27 -0
  22. package/template/scripts/build-for-bots.mjs +121 -0
  23. package/template/scripts/convert-to-ts.mjs +106 -0
  24. package/template/scripts/fix-encoding.mjs +38 -0
  25. package/template/scripts/fix-svg-paths.mjs +32 -0
  26. package/template/scripts/generate-cf-router.mjs +52 -0
  27. package/template/scripts/inject-dev-tools.mjs +41 -0
  28. package/template/scripts/inject-version.mjs +65 -0
  29. package/template/scripts/make-component.mjs +445 -0
  30. package/template/scripts/make-component.mjs.backup +432 -0
  31. package/template/scripts/make-controller.mjs +119 -0
  32. package/template/scripts/make-core-component.mjs +303 -0
  33. package/template/scripts/make-view.mjs +346 -0
  34. package/template/scripts/minify.mjs +71 -0
  35. package/template/scripts/prepare-static-assets.mjs +141 -0
  36. package/template/scripts/prompt-bot-build.mjs +223 -0
  37. package/template/scripts/remove-component.mjs +170 -0
  38. package/template/scripts/remove-core-component.mjs +156 -0
  39. package/template/scripts/remove-dev.mjs +13 -0
  40. package/template/scripts/remove-view.mjs +200 -0
  41. package/template/scripts/strip-dev-blocks.mjs +30 -0
  42. package/template/scripts/watch-compile.mjs +69 -0
  43. package/template/server.js +1066 -0
  44. package/template/src/app.ts +115 -0
  45. package/template/src/components/appRegistry.ts +8 -0
  46. package/template/src/components/core/app-footer.ts +27 -0
  47. package/template/src/components/core/app-header.ts +175 -0
  48. package/template/src/components/core/app-sidebar.ts +238 -0
  49. package/template/src/components/core/loading-spinner.ts +25 -0
  50. package/template/src/components/core/nc-a.ts +313 -0
  51. package/template/src/components/core/nc-accordion.ts +186 -0
  52. package/template/src/components/core/nc-alert.ts +153 -0
  53. package/template/src/components/core/nc-animation.ts +1150 -0
  54. package/template/src/components/core/nc-autocomplete.ts +271 -0
  55. package/template/src/components/core/nc-avatar-group.ts +113 -0
  56. package/template/src/components/core/nc-avatar.ts +148 -0
  57. package/template/src/components/core/nc-badge.ts +86 -0
  58. package/template/src/components/core/nc-bottom-nav.ts +214 -0
  59. package/template/src/components/core/nc-breadcrumb.ts +96 -0
  60. package/template/src/components/core/nc-button.ts +307 -0
  61. package/template/src/components/core/nc-card.ts +160 -0
  62. package/template/src/components/core/nc-checkbox.ts +282 -0
  63. package/template/src/components/core/nc-chip.ts +115 -0
  64. package/template/src/components/core/nc-code.ts +314 -0
  65. package/template/src/components/core/nc-collapsible.ts +154 -0
  66. package/template/src/components/core/nc-color-picker.ts +268 -0
  67. package/template/src/components/core/nc-copy-button.ts +119 -0
  68. package/template/src/components/core/nc-date-picker.ts +443 -0
  69. package/template/src/components/core/nc-div.ts +280 -0
  70. package/template/src/components/core/nc-divider.ts +81 -0
  71. package/template/src/components/core/nc-drawer.ts +230 -0
  72. package/template/src/components/core/nc-dropdown.ts +178 -0
  73. package/template/src/components/core/nc-empty-state.ts +134 -0
  74. package/template/src/components/core/nc-file-upload.ts +354 -0
  75. package/template/src/components/core/nc-form.ts +312 -0
  76. package/template/src/components/core/nc-image.ts +184 -0
  77. package/template/src/components/core/nc-input.ts +383 -0
  78. package/template/src/components/core/nc-kbd.ts +48 -0
  79. package/template/src/components/core/nc-menu-item.ts +193 -0
  80. package/template/src/components/core/nc-menu.ts +376 -0
  81. package/template/src/components/core/nc-modal.ts +238 -0
  82. package/template/src/components/core/nc-nav-item.ts +151 -0
  83. package/template/src/components/core/nc-number-input.ts +350 -0
  84. package/template/src/components/core/nc-otp-input.ts +235 -0
  85. package/template/src/components/core/nc-pagination.ts +178 -0
  86. package/template/src/components/core/nc-popover.ts +260 -0
  87. package/template/src/components/core/nc-progress-circular.ts +119 -0
  88. package/template/src/components/core/nc-progress.ts +134 -0
  89. package/template/src/components/core/nc-radio.ts +235 -0
  90. package/template/src/components/core/nc-rating.ts +266 -0
  91. package/template/src/components/core/nc-rich-text.ts +283 -0
  92. package/template/src/components/core/nc-scroll-top.ts +116 -0
  93. package/template/src/components/core/nc-select.ts +452 -0
  94. package/template/src/components/core/nc-skeleton.ts +107 -0
  95. package/template/src/components/core/nc-slider.ts +285 -0
  96. package/template/src/components/core/nc-snackbar.ts +230 -0
  97. package/template/src/components/core/nc-splash.ts +343 -0
  98. package/template/src/components/core/nc-stepper.ts +247 -0
  99. package/template/src/components/core/nc-switch.ts +281 -0
  100. package/template/src/components/core/nc-tab-item.ts +138 -0
  101. package/template/src/components/core/nc-table.ts +279 -0
  102. package/template/src/components/core/nc-tabs.ts +554 -0
  103. package/template/src/components/core/nc-tag-input.ts +279 -0
  104. package/template/src/components/core/nc-textarea.ts +216 -0
  105. package/template/src/components/core/nc-time-picker.ts +438 -0
  106. package/template/src/components/core/nc-timeline.ts +186 -0
  107. package/template/src/components/core/nc-tooltip.ts +143 -0
  108. package/template/src/components/frameworkRegistry.ts +68 -0
  109. package/template/src/components/preloadRegistry.ts +28 -0
  110. package/template/src/components/registry.ts +8 -0
  111. package/template/src/components/ui/dashboard-signal-lab.ts +284 -0
  112. package/template/src/constants/apiEndpoints.ts +27 -0
  113. package/template/src/constants/errorMessages.ts +23 -0
  114. package/template/src/constants/index.ts +8 -0
  115. package/template/src/constants/routePaths.ts +15 -0
  116. package/template/src/constants/storageKeys.ts +18 -0
  117. package/template/src/controllers/dashboard.controller.ts +200 -0
  118. package/template/src/controllers/home.controller.ts +21 -0
  119. package/template/src/controllers/index.ts +11 -0
  120. package/template/src/controllers/login.controller.ts +131 -0
  121. package/template/src/core/component.ts +354 -0
  122. package/template/src/core/errorHandler.ts +85 -0
  123. package/template/src/core/gpu-animation.ts +604 -0
  124. package/template/src/core/http.ts +173 -0
  125. package/template/src/core/lazyComponents.ts +90 -0
  126. package/template/src/core/router.ts +653 -0
  127. package/template/src/core/signals.ts +146 -0
  128. package/template/src/core/state.ts +248 -0
  129. package/template/src/dev/component-editor.ts +1363 -0
  130. package/template/src/dev/component-overlay.ts +278 -0
  131. package/template/src/dev/context-menu.ts +223 -0
  132. package/template/src/dev/denc-tools.ts +250 -0
  133. package/template/src/dev/hmr.ts +189 -0
  134. package/template/src/dev/nfbs.code-workspace +27 -0
  135. package/template/src/dev/outline-panel.ts +1247 -0
  136. package/template/src/middleware/auth.middleware.ts +23 -0
  137. package/template/src/routes/routes.ts +38 -0
  138. package/template/src/services/api.service.ts +394 -0
  139. package/template/src/services/auth.service.ts +176 -0
  140. package/template/src/services/index.ts +8 -0
  141. package/template/src/services/logger.service.ts +74 -0
  142. package/template/src/services/storage.service.ts +88 -0
  143. package/template/src/stores/appStore.ts +57 -0
  144. package/template/src/stores/uiStore.ts +36 -0
  145. package/template/src/styles/core-variables.css +219 -0
  146. package/template/src/styles/core.css +710 -0
  147. package/template/src/styles/main.css +3164 -0
  148. package/template/src/styles/variables.css +152 -0
  149. package/template/src/types/global.d.ts +47 -0
  150. package/template/src/utils/cacheBuster.ts +20 -0
  151. package/template/src/utils/dom.ts +149 -0
  152. package/template/src/utils/events.ts +203 -0
  153. package/template/src/utils/form.ts +176 -0
  154. package/template/src/utils/formatters.ts +169 -0
  155. package/template/src/utils/helpers.ts +195 -0
  156. package/template/src/utils/markdown.ts +307 -0
  157. package/template/src/utils/sidebar.ts +96 -0
  158. package/template/src/utils/smoothScroll.ts +85 -0
  159. package/template/src/utils/templates.ts +23 -0
  160. package/template/src/utils/validation.ts +73 -0
  161. package/template/src/views/protected/dashboard.html +293 -0
  162. package/template/src/views/public/home.html +150 -0
  163. package/template/src/views/public/login.html +102 -0
  164. package/template/tests/unit/component.test.ts +87 -0
  165. package/template/tests/unit/computed.test.ts +79 -0
  166. package/template/tests/unit/form.test.ts +68 -0
  167. package/template/tests/unit/formatters.test.ts +49 -0
  168. package/template/tests/unit/lazy-components.test.ts +59 -0
  169. package/template/tests/unit/markdown.test.ts +62 -0
  170. package/template/tests/unit/router.test.ts +112 -0
  171. package/template/tests/unit/signals.test.ts +54 -0
  172. package/template/tests/unit/validation.test.ts +50 -0
  173. package/template/tsconfig.build.json +21 -0
  174. package/template/tsconfig.json +51 -0
  175. package/template/vitest.config.ts +36 -0
@@ -0,0 +1,445 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Component Generator Script
5
+ * Like Laravel Artisan for vanilla JS components
6
+ *
7
+ * Usage:
8
+ * node scripts/make-component.mjs counter
9
+ * npm run make:component counter
10
+ */
11
+
12
+ import fs from 'fs';
13
+ import path from 'path';
14
+ import { fileURLToPath } from 'url';
15
+ import readline from 'readline';
16
+
17
+ const __filename = fileURLToPath(import.meta.url);
18
+ const __dirname = path.dirname(__filename);
19
+
20
+ // Get component name from command line
21
+ const componentName = process.argv[2];
22
+
23
+ if (!componentName) {
24
+ console.error('Error: Component name is required');
25
+ console.log('\nUsage:');
26
+ console.log(' npm run make:component <name>');
27
+ console.log('\nExample:');
28
+ console.log(' npm run make:component my-card');
29
+ process.exit(1);
30
+ }
31
+
32
+ // Validate component name (kebab-case with required hyphen)
33
+ if (!/^[a-z][a-z0-9]*(-[a-z0-9]+)+$/.test(componentName)) {
34
+ console.error('Error: Component name must be in kebab-case with at least one hyphen');
35
+ console.error(' Custom elements require a hyphen to avoid conflicts with native HTML elements');
36
+ console.error('\nValid examples:');
37
+ console.error(' - my-card');
38
+ console.error(' - user-profile');
39
+ console.error(' - sample-component');
40
+ console.error('\nInvalid examples:');
41
+ console.error(' - card (no hyphen)');
42
+ console.error(' - MyCard (not kebab-case)');
43
+ process.exit(1);
44
+ }
45
+
46
+ // Generate class name (PascalCase)
47
+ const className = componentName
48
+ .split('-')
49
+ .map(word => word.charAt(0).toUpperCase() + word.slice(1))
50
+ .join('');
51
+
52
+ // Component file path (in components/ui folder by default)
53
+ const componentsDir = path.resolve(__dirname, '..', 'src', 'components');
54
+ const uiDir = path.join(componentsDir, 'ui');
55
+ const componentFile = path.join(uiDir, `${componentName}.ts`);
56
+ const registryFile = path.join(componentsDir, 'registry.ts');
57
+
58
+ // Ensure ui directory exists
59
+ if (!fs.existsSync(uiDir)) {
60
+ fs.mkdirSync(uiDir, { recursive: true });
61
+ }
62
+
63
+ // Check if component already exists
64
+ if (fs.existsSync(componentFile)) {
65
+ console.error(`Error: Component "${componentName}.ts" already exists`);
66
+ process.exit(1);
67
+ }
68
+
69
+ // Template files
70
+ const jsTemplate = `/**
71
+ * ${className} Component
72
+ * Generated on ${new Date().toLocaleDateString()}
73
+ *
74
+ * DEV MODE INTEGRATION:
75
+ * - Define variant/size CSS classes for automatic dropdown detection
76
+ * - Add attributes to observedAttributes for live editing
77
+ * - Implement attributeChangedCallback for instant preview updates
78
+ * - Changes can be saved to instance (HTML) or globally (component file)
79
+ *
80
+ * REGISTRATION:
81
+ * This component is automatically registered in src/components/registry.ts
82
+ * Usage: <${componentName}></${componentName}>
83
+ *
84
+ * PERFORMANCE:
85
+ * - Lazy-loaded by default (loads on first use)
86
+ * - For critical components: Add to src/components/preloadRegistry.ts
87
+ */
88
+ import { Component, defineComponent } from '@core/component.js';
89
+ import { useState, computed } from '@core/state.js';
90
+ import type { State, ComputedState } from '@core/state.js';
91
+ import { html } from '@utils/templates.js';
92
+
93
+ export class ${className} extends Component {
94
+ // ========== Shadow DOM ==========
95
+ // Enable for CSS encapsulation and <slot> support
96
+ static useShadowDOM = true;
97
+
98
+ // ========== Dev Tools: Attribute Options ==========
99
+ // Defines the dropdown values shown in the dev tools panel for each attribute.
100
+ // This takes priority over automatic CSS class detection.
101
+ // Add one entry per observed attribute that has a fixed set of valid values.
102
+ // The variant values here must match your CSS class names below (e.g. .primary { ... })
103
+ static attributeOptions = {
104
+ variant: ['primary', 'secondary', 'success'],
105
+ size: ['small', 'medium', 'large'],
106
+ };
107
+
108
+ // ========== Observed Attributes (Dev Tools Integration) ==========
109
+ // Attributes listed here:
110
+ // - Show up in dev tools sidebar
111
+ // - Trigger attributeChangedCallback when changed
112
+ static get observedAttributes() {
113
+ return ['variant', 'size', 'disabled'];
114
+ }
115
+
116
+ // ========== Local State ==========
117
+ private count?: State<number>;
118
+ private name?: State<string>;
119
+
120
+ // ========== Computed State ==========
121
+ private doubleCount?: ComputedState<number>;
122
+ private greeting?: ComputedState<string>;
123
+
124
+ // ========== Watcher unsubscribes (call in onUnmount) ==========
125
+ private _unwatchCount?: () => void;
126
+ private _unwatchName?: () => void;
127
+
128
+ constructor() {
129
+ super();
130
+
131
+ // ========== Initialize Local State ==========
132
+ // this.count = useState(0);
133
+ // this.name = useState('World');
134
+
135
+ // ========== Initialize Computed Values ==========
136
+ // Auto-updates when dependencies change
137
+ // this.doubleCount = computed(() => this.count!.value * 2);
138
+ // this.greeting = computed(() => \`Hello, \${this.name!.value}!\`);
139
+ }
140
+
141
+ template() {
142
+ // ========== Get Attributes ==========
143
+ const variant = this.attr('variant', 'primary');
144
+ const size = this.attr('size', 'medium');
145
+ const disabled = this.hasAttribute('disabled');
146
+
147
+ // TIP: Keep attributeOptions.variant in sync with the CSS class names below.
148
+ // Each value in the array needs a matching CSS rule (e.g. .primary { ... })
149
+ //
150
+ // CSS variables used below (var(--primary), var(--spacing-md), etc.) are
151
+ // defined in src/styles/variables.css — edit that file to change tokens globally.
152
+
153
+ return html\`
154
+ <style>
155
+ :host {
156
+ display: block;
157
+ }
158
+
159
+ .${componentName} {
160
+ padding: var(--spacing-md);
161
+ background: var(--bg-primary);
162
+ border-radius: var(--radius-md);
163
+ }
164
+
165
+ /* ========== Variant Examples ========== */
166
+ /* Dev tools will detect these as dropdown options */
167
+ .primary {
168
+ background: var(--primary);
169
+ color: white;
170
+ }
171
+
172
+ .secondary {
173
+ background: var(--secondary);
174
+ color: white;
175
+ }
176
+
177
+ .success {
178
+ background: var(--success);
179
+ color: white;
180
+ }
181
+
182
+ /* ========== Size Examples ========== */
183
+ .small {
184
+ padding: var(--spacing-sm);
185
+ font-size: 0.875rem;
186
+ }
187
+
188
+ .medium {
189
+ padding: var(--spacing-md);
190
+ font-size: 1rem;
191
+ }
192
+
193
+ .large {
194
+ padding: var(--spacing-lg);
195
+ font-size: 1.125rem;
196
+ }
197
+ </style>
198
+
199
+ <div class="${componentName} \${variant} \${size}" \${disabled ? 'disabled' : ''}>
200
+ <h3>${className}</h3>
201
+ <p>Your component content here</p>
202
+ <slot></slot>
203
+ </div>
204
+ \`;
205
+ }
206
+
207
+ /**
208
+ * Live attribute updates (Dev Tools Integration)
209
+ * Called automatically when observed attributes change
210
+ * Enables instant preview without full re-render
211
+ */
212
+ attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {
213
+ if (!this._mounted) return;
214
+
215
+ const container = this.$('.${componentName}') as HTMLElement;
216
+ if (!container) return;
217
+
218
+ switch (name) {
219
+ case 'variant':
220
+ case 'size':
221
+ // Update classes instantly
222
+ this.updateClasses(container);
223
+ break;
224
+
225
+ case 'disabled':
226
+ // Update disabled state
227
+ container.toggleAttribute('disabled', this.hasAttribute('disabled'));
228
+ break;
229
+ }
230
+ }
231
+
232
+ /**
233
+ * Helper: Update element classes based on current attributes
234
+ */
235
+ private updateClasses(element: HTMLElement): void {
236
+ const variant = this.attr('variant', 'primary');
237
+ const size = this.attr('size', 'medium');
238
+ element.className = \`${componentName} \${variant} \${size}\`;
239
+ }
240
+
241
+ onMount() {
242
+ // ========== Event Delegation (Recommended Pattern) ==========
243
+ // Handles clicks even after re-renders
244
+ this.shadowRoot.addEventListener('click', (e) => {
245
+ const target = e.target as HTMLElement;
246
+
247
+ // if (target.matches('.btn-increment')) {
248
+ // this.handleIncrement();
249
+ // }
250
+ });
251
+
252
+ // ========== State Watchers ==========
253
+ // Store the returned unsubscribe — call it in onUnmount
254
+ // this._unwatchCount = this.count?.watch(value => {
255
+ // const display = this.shadowRoot.querySelector('#count-display');
256
+ // if (display) display.textContent = value.toString();
257
+ // });
258
+
259
+ // this._unwatchName = this.name?.watch(value => {
260
+ // const display = this.shadowRoot.querySelector('#greeting');
261
+ // if (display) display.textContent = value;
262
+ // });
263
+ }
264
+
265
+ // ========== Event Handlers ==========
266
+ // private handleIncrement(): void {
267
+ // if (this.count) {
268
+ // this.count.value++;
269
+ // }
270
+ //
271
+ // // Emit event to parent
272
+ // this.emitEvent('increment', { value: this.count?.value });
273
+ // }
274
+
275
+ // private handleDecrement(): void {
276
+ // if (this.count) {
277
+ // this.count.value--;
278
+ // }
279
+ //
280
+ // // Emit event to parent
281
+ // this.emitEvent('decrement', { value: this.count?.value });
282
+ // }
283
+
284
+ /**
285
+ * Emit custom events to parent components
286
+ *
287
+ * Usage in parent:
288
+ * <${componentName}></${componentName}>
289
+ *
290
+ * // In controller:
291
+ * document.querySelector('${componentName}')
292
+ * .addEventListener('custom-event', (e) => {
293
+ * console.log(e.detail); // Your data here
294
+ * });
295
+ */
296
+ // emitEvent(name: string, detail: any = {}, options = {}) {
297
+ // this.dispatchEvent(new CustomEvent(name, {
298
+ // detail,
299
+ // bubbles: true,
300
+ // composed: true,
301
+ // ...options
302
+ // }));
303
+ // }
304
+
305
+ onUnmount() {
306
+ // Unsubscribe all state watchers
307
+ this._unwatchCount?.();
308
+ this._unwatchName?.();
309
+
310
+ // Dispose computed values to release dependency subscriptions
311
+ this.doubleCount?.dispose();
312
+ this.greeting?.dispose();
313
+ }
314
+ }
315
+
316
+ defineComponent('${componentName}', ${className});
317
+ `;
318
+
319
+ const readmeTemplate = `# ${className}
320
+
321
+ Custom element: \`<${componentName}>\`
322
+
323
+ ## Usage
324
+
325
+ \`\`\`html
326
+ <${componentName}></${componentName}>
327
+ \`\`\`
328
+
329
+ ## Properties
330
+
331
+ | Property | Type | Default | Description |
332
+ |----------|------|---------|-------------|
333
+ | - | - | - | - |
334
+
335
+ ## Events
336
+
337
+ | Event | Description |
338
+ |-------|-------------|
339
+ | - | - |
340
+
341
+ ## CSS Variables
342
+
343
+ | Variable | Description |
344
+ |----------|-------------|
345
+ | - | - |
346
+
347
+ ## Example
348
+
349
+ \`\`\`html
350
+ <${componentName}></${componentName}>
351
+ \`\`\`
352
+ `;
353
+
354
+ // Write component file
355
+ fs.writeFileSync(componentFile, jsTemplate.trim());
356
+
357
+ // Prompt for prefetch
358
+ const rl = readline.createInterface({
359
+ input: process.stdin,
360
+ output: process.stdout
361
+ });
362
+
363
+ console.log('\nPerformance optimization:');
364
+ console.log(' All components are lazy-loaded by default (loads on first use).');
365
+ console.log(' For critical layout components (header, sidebar, footer), prefetching improves performance.\n');
366
+
367
+ rl.question('Would you like to prefetch this component? (y/N): ', (answer) => {
368
+ const shouldPreload = answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes';
369
+
370
+ if (shouldPreload) {
371
+ // Add import to preloadRegistry.ts
372
+ const preloadFile = path.resolve(__dirname, '..', 'src', 'components', 'preloadRegistry.ts');
373
+
374
+ if (fs.existsSync(preloadFile)) {
375
+ let preloadContent = fs.readFileSync(preloadFile, 'utf-8');
376
+ const importStatement = `import './ui/${componentName}.js';`;
377
+
378
+ // Check if not already imported
379
+ if (!preloadContent.includes(importStatement)) {
380
+ // Find the last import line and add after it
381
+ const lines = preloadContent.split('\n');
382
+ const lastImportIndex = lines.findLastIndex(line =>
383
+ line.trim().startsWith("import './") && line.endsWith(".js';")
384
+ );
385
+
386
+ if (lastImportIndex !== -1) {
387
+ // Add after last import
388
+ lines.splice(lastImportIndex + 1, 0, importStatement);
389
+ } else {
390
+ // Add at the end of the file
391
+ lines.push(importStatement);
392
+ }
393
+
394
+ preloadContent = lines.join('\n');
395
+ fs.writeFileSync(preloadFile, preloadContent);
396
+ console.log('Component will be preloaded (added to preloadRegistry.ts)\n');
397
+ }
398
+ } else {
399
+ console.warn('preloadRegistry.ts not found - component will still be lazy-loaded\n');
400
+ }
401
+ } else {
402
+ console.log('Component will be lazy-loaded (default behavior)\n');
403
+ }
404
+
405
+ // Add to registry.ts for lazy loading registration
406
+ if (fs.existsSync(registryFile)) {
407
+ let registryContent = fs.readFileSync(registryFile, 'utf-8');
408
+ const registrationStatement = `componentRegistry.register('${componentName}', './ui/${componentName}.js');`;
409
+
410
+ // Check if already registered
411
+ if (!registryContent.includes(registrationStatement)) {
412
+ // Find the last registration line and add after it
413
+ const lines = registryContent.split('\n');
414
+ const lastRegisterIndex = lines.findLastIndex(line => line.includes('componentRegistry.register'));
415
+
416
+ if (lastRegisterIndex !== -1) {
417
+ // Add after the last registration
418
+ lines.splice(lastRegisterIndex + 1, 0, registrationStatement);
419
+ registryContent = lines.join('\n');
420
+ } else {
421
+ // Add at the end if no registrations found
422
+ registryContent = registryContent.trimEnd() + '\n' + registrationStatement + '\n';
423
+ }
424
+
425
+ fs.writeFileSync(registryFile, registryContent);
426
+ console.log('Component registered in component registry\n');
427
+ }
428
+ } else {
429
+ console.log('Note: src/components/registry.ts not found. Manual registration required.\n');
430
+ }
431
+
432
+ // Success message
433
+ console.log(`Location: src/components/ui/${componentName}.ts`);
434
+ console.log(`Registered in: src/components/registry.ts`);
435
+ if (shouldPreload) {
436
+ console.log(`Preloaded in: src/components/preloadRegistry.ts`);
437
+ }
438
+ console.log('\nNext steps:');
439
+ console.log(` 1. Edit src/components/ui/${componentName}.ts`);
440
+ console.log(` 2. Use in your HTML: <${componentName}></${componentName}>`);
441
+ console.log('\nComponent class:', className);
442
+ console.log('Custom element:', `<${componentName}>`);
443
+
444
+ rl.close();
445
+ });