create-template-html-css 1.6.4 → 1.7.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,56 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.7.0] - 2026-02-01
9
+
10
+ ### Added
11
+ - **Customizable Navigation Items**: Choose exactly which menu items to include when creating navigation components
12
+ - Interactive prompt: "Enter navigation items (comma-separated)"
13
+ - Default: "Home, About, Services, Portfolio, Contact"
14
+ - Automatically generates navigation links and matching page sections
15
+ - Example: "Home, Blog, Shop, About Us, Contact" creates 5 custom navigation items
16
+
17
+ - **Customizable Form Fields**: Select and customize form fields during creation
18
+ - **Standard Fields**: Choose from 6 predefined fields (Name, Email, Phone, Subject, Message, Terms)
19
+ - **Custom Fields**: Add unlimited custom fields with format `type:label`
20
+ - Supports all HTML5 input types: text, email, url, date, number, tel, password, color, etc.
21
+ - Special field types: textarea, checkbox, select
22
+ - Examples:
23
+ - `text:Age` → text input for age
24
+ - `url:Website` → URL input
25
+ - `date:Birth Date` → date picker
26
+ - `number:Quantity` → number input
27
+ - `textarea:Comments` → text area
28
+ - `checkbox:Subscribe` → checkbox field
29
+ - `select:Country` → dropdown menu
30
+
31
+ - **Component Variation Selection**: Choose specific variations for components with multiple styles
32
+ - **Button Component**: Select from 6 button types or choose specific ones
33
+ - Primary, Secondary, Success, Danger, Outlined, Disabled
34
+ - Option: "All Buttons (6 variations)" or "Select Specific Buttons"
35
+ - **Card Component**: Select from 6 card variations or choose specific ones
36
+ - Modern Card (Featured), Premium Card (Price), Blog Card (Tags)
37
+ - Minimal Card, User Profile Card, Interactive Card
38
+ - Option: "All Cards (6 variations)" or "Select Specific Cards"
39
+ - **Spinner Component**: Select from 5 spinner types or choose specific ones
40
+ - Circle Spinner, Bouncing Dots, Pulse Loader, Bar Loader, Gradient Ring
41
+ - Option: "All Spinners (5 types)" or "Select Specific Spinners"
42
+
43
+ ### Improved
44
+ - Enhanced CLI prompts with better validation and user guidance
45
+ - More interactive component creation experience
46
+ - Clear format instructions for custom fields
47
+ - Cleaner generated HTML when selecting specific variations
48
+
49
+ ### Developer Notes
50
+ - Added `generateNavigationItems()` function to dynamically create nav menus
51
+ - Added `generateFormFields()` function to handle both standard and custom form fields
52
+ - Added `filterButtonVariations()` function to filter button HTML
53
+ - Added `filterCardVariations()` function to filter card HTML
54
+ - Added `filterSpinnerVariations()` function to filter spinner HTML
55
+ - Updated CLI to include conditional prompts based on component type
56
+ - Generator now accepts `navItems`, `formFields`, `customFormFields`, and variation parameters
57
+
8
58
  ## [1.6.2] - 2026-02-01
9
59
 
10
60
  ### Added
package/README.md CHANGED
@@ -41,8 +41,35 @@ npm install -g create-template-html-css
41
41
  - ✨ **Prettier Formatting** - All generated code is automatically formatted with Prettier (v1.6.2+)
42
42
  - 📂 **Organized Structure** - CSS and JS files automatically organized in folders (v1.6.2+)
43
43
  - 💾 **Simple Backups** - Clean backup naming without timestamps (v1.6.2+)
44
+ - 🎯 **Customizable Components** - Choose navigation items and form fields during creation (v1.7.0+)
44
45
 
45
- ## 🆕 What's New in v1.6.2
46
+ ## 🆕 What's New in v1.7.0
47
+
48
+ ### 🎯 Customizable Navigation
49
+ When creating a navigation component, you can now specify exactly which menu items you want:
50
+ - Enter comma-separated items: "Home, Blog, Shop, Contact"
51
+ - Automatically generates matching navigation links and page sections
52
+ - Default: "Home, About, Services, Portfolio, Contact"
53
+
54
+ ### 📝 Customizable Form Fields
55
+ Create forms with exactly the fields you need:
56
+ - **Standard Fields**: Select from Name, Email, Phone, Subject, Message, Terms
57
+ - **Custom Fields**: Add any field with format `type:label`
58
+ - Examples: `text:Age`, `url:Website`, `date:Birth Date`, `number:Quantity`
59
+ - Supports all HTML5 input types: text, email, url, date, number, tel, password, color, etc.
60
+ - Also supports: textarea, checkbox, select
61
+
62
+ ### 🎨 Component Variation Selection
63
+ Choose exactly which variations you want for multi-style components:
64
+ - **Button**: Select from 6 button types (Primary, Secondary, Success, Danger, Outlined, Disabled)
65
+ - **Card**: Choose from 6 card variations (Modern, Premium, Blog, Minimal, User Profile, Interactive)
66
+ - **Spinner**: Pick from 5 spinner types (Circle, Dots, Pulse, Bars, Gradient)
67
+ - Option to select "All Variations" or choose specific ones
68
+
69
+ ### 🚀 Interactive CLI Experience
70
+ Enhanced prompts guide you through component customization with clear instructions and validation.
71
+
72
+ ## 🎨 What Was Added in v1.6.2
46
73
 
47
74
  ### ✨ Prettier Code Formatting
48
75
  All generated and inserted files are automatically formatted with [Prettier](https://prettier.io/) for beautiful, professional-looking code.
@@ -96,9 +123,12 @@ create-template create
96
123
  Follow the interactive prompts:
97
124
  1. **Select Component Type** - Choose from Button, Card, Form, Navigation, Modal, Footer, or Hero
98
125
  2. **Enter Component Name** - Give your component a meaningful name
99
- 3. **Include JavaScript** - Decide if you want to include the script file
126
+ 3. **Customize Component** (v1.7.0+):
127
+ - **Navigation**: Choose menu items (e.g., "Home, Blog, Shop, Contact")
128
+ - **Form**: Select standard fields and add custom fields (e.g., "text:Age, url:Website")
129
+ 4. **Include JavaScript** - Decide if you want to include the script file
100
130
 
101
- **Example:**
131
+ **Example (Basic):**
102
132
 
103
133
  ```bash
104
134
  $ create-template create
@@ -109,6 +139,29 @@ $ create-template create
109
139
  Location: ./my-awesome-button/
110
140
  ```
111
141
 
142
+ **Example (Navigation with Custom Items):**
143
+
144
+ ```bash
145
+ $ create-template create
146
+ ? Choose a component type: Navigation
147
+ ? Enter a name for your component: my-nav
148
+ ? Enter navigation items (comma-separated): Home, Blog, Shop, About Us, Contact
149
+ ✓ Template created successfully!
150
+ Location: ./my-nav/
151
+ ```
152
+
153
+ **Example (Form with Custom Fields):**
154
+
155
+ ```bash
156
+ $ create-template create
157
+ ? Choose a component type: Form
158
+ ? Enter a name for your component: contact-form
159
+ ? Select form fields to include: Name, Email, Message
160
+ ? Add custom fields: text:Age, url:Website, date:Birth Date
161
+ ✓ Template created successfully!
162
+ Location: ./contact-form/
163
+ ```
164
+
112
165
  **Result:**
113
166
  ```
114
167
  my-awesome-button/
@@ -207,31 +260,45 @@ Responsive card component with 6 professional variations:
207
260
 
208
261
  ### 3. Form
209
262
 
210
- Complete contact form with validation:
263
+ Complete contact form with validation and customizable fields (v1.7.0+):
211
264
 
212
- **Fields:**
213
- - Text input
214
- - Email input
215
- - Phone input
216
- - Select dropdown
217
- - Textarea
218
- - Checkboxes
265
+ **Customization Options:**
266
+ - **Standard Fields**: Name, Email, Phone, Subject, Message, Terms Checkbox
267
+ - **Custom Fields**: Add any field with `type:label` format
268
+ - Supported types: text, email, url, date, number, tel, password, color, textarea, checkbox, select
269
+ - Examples: `text:Age`, `url:Website`, `date:Birth Date`, `number:Quantity`
219
270
 
220
271
  **Features:**
221
272
  - Real-time validation
222
273
  - Focus effects
223
274
  - Error messages
224
275
  - Modern styling
276
+ - Fully customizable field selection
225
277
 
226
278
  ### 4. Navigation
227
279
 
228
- Responsive navigation bar for all devices:
280
+ Responsive navigation bar with customizable menu items (v1.7.0+):
281
+
282
+ **Customization:**
283
+ - Choose exactly which menu items to include
284
+ - Enter comma-separated items: "Home, Blog, Shop, Contact"
285
+ - Automatically generates matching page sections
286
+ - Default items: "Home, About, Services, Portfolio, Contact"
229
287
 
230
288
  **Components:**
231
289
  - Logo section
232
- - Navigation menu
290
+ - Customizable navigation menu
233
291
  - Mobile hamburger menu
234
292
  - Smooth scrolling
293
+ - Section highlighting on scroll
294
+
295
+ **Features:**
296
+ - Fully customizable menu structure
297
+ - Mobile-responsive design
298
+ - Sticky navigation
299
+ - Active link highlighting
300
+ - Animated hamburger menu
301
+ - Smooth scroll to sections
235
302
 
236
303
  **Features:**
237
304
  - Fixed header option
package/bin/cli.js CHANGED
@@ -13,7 +13,7 @@ program
13
13
  .description(
14
14
  chalk.cyan("🎨 Create HTML/CSS UI component templates in seconds"),
15
15
  )
16
- .version("1.6.4");
16
+ .version("1.7.0");
17
17
 
18
18
  // Add intro message
19
19
  program.on("--help", () => {
@@ -166,6 +166,149 @@ program
166
166
  return true;
167
167
  },
168
168
  },
169
+ {
170
+ type: "input",
171
+ name: "navItems",
172
+ message: "Enter navigation items (comma-separated):",
173
+ default: "Home, About, Services, Portfolio, Contact",
174
+ when: (answers) => answers.component === "navigation",
175
+ validate: (input) => {
176
+ if (!input || input.trim().length === 0) {
177
+ return "Please enter at least one navigation item";
178
+ }
179
+ return true;
180
+ },
181
+ },
182
+ {
183
+ type: "checkbox",
184
+ name: "formFields",
185
+ message: "Select form fields to include:",
186
+ choices: [
187
+ { name: "Name", value: "name", checked: true },
188
+ { name: "Email", value: "email", checked: true },
189
+ { name: "Phone", value: "phone", checked: false },
190
+ { name: "Subject", value: "subject", checked: false },
191
+ { name: "Message", value: "message", checked: true },
192
+ { name: "Terms Checkbox", value: "terms", checked: false },
193
+ ],
194
+ when: (answers) => answers.component === "form",
195
+ validate: (input) => {
196
+ if (input.length === 0) {
197
+ return "Please select at least one form field";
198
+ }
199
+ return true;
200
+ },
201
+ },
202
+ {
203
+ type: "list",
204
+ name: "buttonVariations",
205
+ message: "Which button variations do you want?",
206
+ choices: [
207
+ { name: "All Buttons (6 variations)", value: "all" },
208
+ { name: "Select Specific Buttons", value: "select" },
209
+ ],
210
+ when: (answers) => answers.component === "button",
211
+ },
212
+ {
213
+ type: "checkbox",
214
+ name: "selectedButtons",
215
+ message: "Select button variations:",
216
+ choices: [
217
+ { name: "Primary Button", value: "primary", checked: true },
218
+ { name: "Secondary Button", value: "secondary", checked: true },
219
+ { name: "Success Button", value: "success", checked: true },
220
+ { name: "Danger Button", value: "danger", checked: true },
221
+ { name: "Outlined Button", value: "outlined", checked: true },
222
+ { name: "Disabled Button", value: "disabled", checked: true },
223
+ ],
224
+ when: (answers) => answers.component === "button" && answers.buttonVariations === "select",
225
+ validate: (input) => {
226
+ if (input.length === 0) {
227
+ return "Please select at least one button variation";
228
+ }
229
+ return true;
230
+ },
231
+ },
232
+ {
233
+ type: "list",
234
+ name: "cardVariations",
235
+ message: "Which card variations do you want?",
236
+ choices: [
237
+ { name: "All Cards (6 variations)", value: "all" },
238
+ { name: "Select Specific Cards", value: "select" },
239
+ ],
240
+ when: (answers) => answers.component === "card",
241
+ },
242
+ {
243
+ type: "checkbox",
244
+ name: "selectedCards",
245
+ message: "Select card variations:",
246
+ choices: [
247
+ { name: "Modern Card (Featured)", value: "modern", checked: true },
248
+ { name: "Premium Card (Price)", value: "premium", checked: true },
249
+ { name: "Blog Card (Tags)", value: "blog", checked: true },
250
+ { name: "Minimal Card", value: "minimal", checked: true },
251
+ { name: "User Profile Card", value: "user", checked: true },
252
+ { name: "Interactive Card", value: "interactive", checked: true },
253
+ ],
254
+ when: (answers) => answers.component === "card" && answers.cardVariations === "select",
255
+ validate: (input) => {
256
+ if (input.length === 0) {
257
+ return "Please select at least one card variation";
258
+ }
259
+ return true;
260
+ },
261
+ },
262
+ {
263
+ type: "list",
264
+ name: "spinnerVariations",
265
+ message: "Which spinner variations do you want?",
266
+ choices: [
267
+ { name: "All Spinners (5 types)", value: "all" },
268
+ { name: "Select Specific Spinners", value: "select" },
269
+ ],
270
+ when: (answers) => answers.component === "spinner",
271
+ },
272
+ {
273
+ type: "checkbox",
274
+ name: "selectedSpinners",
275
+ message: "Select spinner types:",
276
+ choices: [
277
+ { name: "Circle Spinner", value: "circle", checked: true },
278
+ { name: "Bouncing Dots", value: "dots", checked: true },
279
+ { name: "Pulse Loader", value: "pulse", checked: true },
280
+ { name: "Bar Loader", value: "bars", checked: true },
281
+ { name: "Gradient Ring", value: "gradient", checked: true },
282
+ ],
283
+ when: (answers) => answers.component === "spinner" && answers.spinnerVariations === "select",
284
+ validate: (input) => {
285
+ if (input.length === 0) {
286
+ return "Please select at least one spinner type";
287
+ }
288
+ return true;
289
+ },
290
+ },
291
+ {
292
+ type: "input",
293
+ name: "customFormFields",
294
+ message: "Add custom fields (format: type:label, e.g., 'text:Age, url:Website'):",
295
+ when: (answers) => answers.component === "form",
296
+ default: "",
297
+ validate: (input) => {
298
+ if (!input || input.trim().length === 0) {
299
+ return true; // Optional field
300
+ }
301
+ // Basic validation for format
302
+ const fields = input.split(',');
303
+ for (const field of fields) {
304
+ const trimmed = field.trim();
305
+ if (trimmed && !trimmed.includes(':')) {
306
+ return "Invalid format. Use 'type:label' (e.g., 'text:Age, url:Website')";
307
+ }
308
+ }
309
+ return true;
310
+ },
311
+ },
169
312
  ]);
170
313
 
171
314
  // Always include JavaScript file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-template-html-css",
3
- "version": "1.6.4",
3
+ "version": "1.7.0",
4
4
  "description": "CLI tool to generate HTML and CSS templates for common UI elements",
5
5
  "main": "src/index.js",
6
6
  "bin": {
package/src/generator.js CHANGED
@@ -81,8 +81,291 @@ function sanitizeFilename(filename) {
81
81
  return sanitized.replace(/[<>:"|?*]/g, "").trim();
82
82
  }
83
83
 
84
+ /**
85
+ * Filter button variations based on user selection
86
+ */
87
+ function filterButtonVariations(htmlContent, buttonVariations, selectedButtons) {
88
+ if (buttonVariations === "all" || !selectedButtons || selectedButtons.length === 0) {
89
+ return htmlContent; // Return all buttons
90
+ }
91
+
92
+ // Map selection to button classes
93
+ const buttonMap = {
94
+ primary: "btn-primary",
95
+ secondary: "btn-secondary",
96
+ success: "btn-success",
97
+ danger: "btn-danger",
98
+ outlined: "btn-outlined",
99
+ disabled: "disabled"
100
+ };
101
+
102
+ let filteredHtml = htmlContent;
103
+
104
+ // Remove buttons that weren't selected
105
+ for (const [key, className] of Object.entries(buttonMap)) {
106
+ if (!selectedButtons.includes(key)) {
107
+ // Remove button and its comment
108
+ const patterns = [
109
+ new RegExp(`\\s*<!-- ${key.charAt(0).toUpperCase() + key.slice(1)} Button -->\\s*\\n\\s*<button[^>]*${className}[^>]*>.*?<\\/button>\\s*\\n`, 'gis'),
110
+ new RegExp(`\\s*<button[^>]*${className}[^>]*>.*?<\\/button>\\s*\\n`, 'gis')
111
+ ];
112
+
113
+ patterns.forEach(pattern => {
114
+ filteredHtml = filteredHtml.replace(pattern, '\n ');
115
+ });
116
+ }
117
+ }
118
+
119
+ return filteredHtml;
120
+ }
121
+
122
+ /**
123
+ * Filter card variations based on user selection
124
+ */
125
+ function filterCardVariations(htmlContent, cardVariations, selectedCards) {
126
+ if (cardVariations === "all" || !selectedCards || selectedCards.length === 0) {
127
+ return htmlContent; // Return all cards
128
+ }
129
+
130
+ const cardComments = {
131
+ modern: "Card 1 - Basic",
132
+ premium: "Card 2 - With Price",
133
+ blog: "Card 3 - With Tags",
134
+ minimal: "Card 4 - Minimal",
135
+ user: "Card 5 - With Avatar",
136
+ interactive: "Card 6 - Interactive"
137
+ };
138
+
139
+ let filteredHtml = htmlContent;
140
+
141
+ // Remove cards that weren't selected
142
+ for (const [key, comment] of Object.entries(cardComments)) {
143
+ if (!selectedCards.includes(key)) {
144
+ // Remove entire card div including comment
145
+ const pattern = new RegExp(`\\s*<!-- ${comment.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')} -->\\s*\\n\\s*<div class="card[^>]*>.*?<\\/div>\\s*\\n\\s*<\\/div>\\s*\\n`, 'gis');
146
+ filteredHtml = filteredHtml.replace(pattern, '\n ');
147
+ }
148
+ }
149
+
150
+ return filteredHtml;
151
+ }
152
+
153
+ /**
154
+ * Filter spinner variations based on user selection
155
+ */
156
+ function filterSpinnerVariations(htmlContent, spinnerVariations, selectedSpinners) {
157
+ if (spinnerVariations === "all" || !selectedSpinners || selectedSpinners.length === 0) {
158
+ return htmlContent; // Return all spinners
159
+ }
160
+
161
+ const spinnerTypes = {
162
+ circle: "Circle Spinner",
163
+ dots: "Bouncing Dots",
164
+ pulse: "Pulse Loader",
165
+ bars: "Bar Loader",
166
+ gradient: "Gradient Ring"
167
+ };
168
+
169
+ let filteredHtml = htmlContent;
170
+
171
+ // Remove spinners that weren't selected
172
+ for (const [key, title] of Object.entries(spinnerTypes)) {
173
+ if (!selectedSpinners.includes(key)) {
174
+ // Remove entire spinner-group div
175
+ const pattern = new RegExp(`\\s*<!-- ${title} Spinner -->\\s*\\n\\s*<div class="spinner-group">.*?<\\/div>\\s*\\n\\s*<\\/div>\\s*\\n`, 'gis');
176
+ filteredHtml = filteredHtml.replace(pattern, '\n ');
177
+ }
178
+ }
179
+
180
+ return filteredHtml;
181
+ }
182
+
183
+ /**
184
+ * Generate custom navigation items based on user input
185
+ */
186
+ function generateNavigationItems(htmlContent, navItems) {
187
+ // Parse the comma-separated navigation items
188
+ const items = navItems.split(',').map(item => item.trim()).filter(item => item.length > 0);
189
+
190
+ // Generate navigation HTML
191
+ let navHtml = '';
192
+ items.forEach((item, index) => {
193
+ const itemId = item.toLowerCase().replace(/\s+/g, '-');
194
+ const activeClass = index === 0 ? ' active' : '';
195
+ navHtml += ` <li class="nav-item">
196
+ <a href="#${itemId}" class="nav-link${activeClass}">${item}</a>
197
+ </li>\n`;
198
+ });
199
+
200
+ // Replace the navigation items in the HTML
201
+ const navMenuRegex = /<ul class="nav-menu"[^>]*>[\s\S]*?<\/ul>/;
202
+ const replacement = `<ul class="nav-menu" id="navMenu">
203
+ ${navHtml} </ul>`;
204
+
205
+ htmlContent = htmlContent.replace(navMenuRegex, replacement);
206
+
207
+ // Generate sections for each navigation item
208
+ let sectionsHtml = '';
209
+ items.forEach(item => {
210
+ const itemId = item.toLowerCase().replace(/\s+/g, '-');
211
+ sectionsHtml += ` <section id="${itemId}" class="section">
212
+ <h1>${item}</h1>
213
+ <p>Content for ${item} section</p>
214
+ </section>
215
+
216
+ `;
217
+ });
218
+
219
+ // Replace the sections in the HTML
220
+ const mainContentRegex = /<main class="main-content">[\s\S]*?<\/main>/;
221
+ const sectionsReplacement = `<main class="main-content">
222
+ ${sectionsHtml} </main>`;
223
+
224
+ htmlContent = htmlContent.replace(mainContentRegex, sectionsReplacement);
225
+
226
+ return htmlContent;
227
+ }
228
+
229
+ /**
230
+ * Generate custom form fields based on user selection
231
+ */
232
+ function generateFormFields(htmlContent, formFields, customFormFields) {
233
+ let fieldsHtml = '';
234
+
235
+ // Add standard fields
236
+ formFields.forEach(field => {
237
+ switch(field) {
238
+ case 'name':
239
+ fieldsHtml += ` <div class="form-group">
240
+ <label for="name">Full Name</label>
241
+ <input type="text" id="name" name="name" required>
242
+ </div>
243
+
244
+ `;
245
+ break;
246
+ case 'email':
247
+ fieldsHtml += ` <div class="form-group">
248
+ <label for="email">Email</label>
249
+ <input type="email" id="email" name="email" required>
250
+ </div>
251
+
252
+ `;
253
+ break;
254
+ case 'phone':
255
+ fieldsHtml += ` <div class="form-group">
256
+ <label for="phone">Phone</label>
257
+ <input type="tel" id="phone" name="phone">
258
+ </div>
259
+
260
+ `;
261
+ break;
262
+ case 'subject':
263
+ fieldsHtml += ` <div class="form-group">
264
+ <label for="subject">Subject</label>
265
+ <select id="subject" name="subject" required>
266
+ <option value="">Select a subject</option>
267
+ <option value="support">Technical Support</option>
268
+ <option value="sales">Sales</option>
269
+ <option value="general">General</option>
270
+ </select>
271
+ </div>
272
+
273
+ `;
274
+ break;
275
+ case 'message':
276
+ fieldsHtml += ` <div class="form-group">
277
+ <label for="message">Message</label>
278
+ <textarea id="message" name="message" rows="5" required></textarea>
279
+ </div>
280
+
281
+ `;
282
+ break;
283
+ case 'terms':
284
+ fieldsHtml += ` <div class="form-group checkbox-group">
285
+ <input type="checkbox" id="terms" name="terms" required>
286
+ <label for="terms">I agree to the terms of service</label>
287
+ </div>
288
+
289
+ `;
290
+ break;
291
+ }
292
+ });
293
+
294
+ // Add custom fields if provided
295
+ if (customFormFields && customFormFields.trim().length > 0) {
296
+ const customFields = customFormFields.split(',').map(f => f.trim()).filter(f => f.length > 0);
297
+
298
+ customFields.forEach(field => {
299
+ const [type, label] = field.split(':').map(s => s.trim());
300
+ if (type && label) {
301
+ const fieldId = label.toLowerCase().replace(/\s+/g, '-');
302
+
303
+ if (type === 'textarea') {
304
+ fieldsHtml += ` <div class="form-group">
305
+ <label for="${fieldId}">${label}</label>
306
+ <textarea id="${fieldId}" name="${fieldId}" rows="5"></textarea>
307
+ </div>
308
+
309
+ `;
310
+ } else if (type === 'checkbox') {
311
+ fieldsHtml += ` <div class="form-group checkbox-group">
312
+ <input type="checkbox" id="${fieldId}" name="${fieldId}">
313
+ <label for="${fieldId}">${label}</label>
314
+ </div>
315
+
316
+ `;
317
+ } else if (type === 'select') {
318
+ fieldsHtml += ` <div class="form-group">
319
+ <label for="${fieldId}">${label}</label>
320
+ <select id="${fieldId}" name="${fieldId}">
321
+ <option value="">Select an option</option>
322
+ <option value="option1">Option 1</option>
323
+ <option value="option2">Option 2</option>
324
+ </select>
325
+ </div>
326
+
327
+ `;
328
+ } else {
329
+ // Default to input with specified type
330
+ fieldsHtml += ` <div class="form-group">
331
+ <label for="${fieldId}">${label}</label>
332
+ <input type="${type}" id="${fieldId}" name="${fieldId}">
333
+ </div>
334
+
335
+ `;
336
+ }
337
+ }
338
+ });
339
+ }
340
+
341
+ // Replace the form fields in the HTML
342
+ const formRegex = /<form class="form"[^>]*>[\s\S]*?<button type="submit"/;
343
+ const replacement = `<form class="form" id="contactForm">
344
+ <h1 class="form-title">Contact Us</h1>
345
+ <p class="form-subtitle">Fill in the details and we'll get back to you soon</p>
346
+
347
+ ${fieldsHtml} <button type="submit"`;
348
+
349
+ htmlContent = htmlContent.replace(formRegex, replacement);
350
+
351
+ return htmlContent;
352
+ }
353
+
84
354
  async function generateTemplate(options) {
85
- const { component, name, includeJs } = options;
355
+ const {
356
+ component,
357
+ name,
358
+ includeJs,
359
+ navItems,
360
+ formFields,
361
+ customFormFields,
362
+ buttonVariations,
363
+ selectedButtons,
364
+ cardVariations,
365
+ selectedCards,
366
+ spinnerVariations,
367
+ selectedSpinners
368
+ } = options;
86
369
 
87
370
  // Security: Validate component name
88
371
  if (!VALID_COMPONENTS.includes(component)) {
@@ -117,6 +400,31 @@ async function generateTemplate(options) {
117
400
 
118
401
  // Replace placeholder name
119
402
  htmlContent = htmlContent.replace(/{{name}}/g, safeName);
403
+
404
+ // Filter button variations
405
+ if (component === "button") {
406
+ htmlContent = filterButtonVariations(htmlContent, buttonVariations, selectedButtons);
407
+ }
408
+
409
+ // Filter card variations
410
+ if (component === "card") {
411
+ htmlContent = filterCardVariations(htmlContent, cardVariations, selectedCards);
412
+ }
413
+
414
+ // Filter spinner variations
415
+ if (component === "spinner") {
416
+ htmlContent = filterSpinnerVariations(htmlContent, spinnerVariations, selectedSpinners);
417
+ }
418
+
419
+ // Custom navigation items
420
+ if (component === "navigation" && navItems) {
421
+ htmlContent = generateNavigationItems(htmlContent, navItems);
422
+ }
423
+
424
+ // Custom form fields
425
+ if (component === "form" && formFields) {
426
+ htmlContent = generateFormFields(htmlContent, formFields, customFormFields);
427
+ }
120
428
 
121
429
  // Add script tag if JavaScript is included (pointing to js/ folder)
122
430
  if (includeJs) {