create-template-html-css 2.0.4 → 2.2.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 (99) hide show
  1. package/CHANGELOG.md +436 -0
  2. package/CODE-SPLITTING-GUIDE.md +274 -0
  3. package/COMPONENTS-GALLERY.html +143 -8
  4. package/HTML-VS-REACT.md +289 -0
  5. package/QUICKSTART-REACT.md +293 -0
  6. package/REACT-SUPPORT-SUMMARY.md +235 -0
  7. package/README.md +261 -12
  8. package/bin/cli.js +100 -759
  9. package/bin/commands/create.js +288 -0
  10. package/bin/commands/gallery.js +42 -0
  11. package/bin/commands/insert.js +123 -0
  12. package/bin/commands/list.js +73 -0
  13. package/package.json +10 -3
  14. package/src/component-choices.js +7 -0
  15. package/src/components-registry.js +112 -0
  16. package/src/format-utils.js +49 -0
  17. package/src/generator.js +83 -594
  18. package/src/generators/color-schemes.js +78 -0
  19. package/src/generators/color-utils.js +108 -0
  20. package/src/generators/component-filters.js +151 -0
  21. package/src/generators/html-generators.js +180 -0
  22. package/src/generators/validation.js +43 -0
  23. package/src/index.js +2 -1
  24. package/src/inserter.js +55 -233
  25. package/src/inserters/backup-utils.js +20 -0
  26. package/src/inserters/component-loader.js +68 -0
  27. package/src/inserters/html-utils.js +31 -0
  28. package/src/inserters/indentation-utils.js +90 -0
  29. package/src/inserters/validation-utils.js +49 -0
  30. package/src/react-component-choices.js +97 -0
  31. package/src/react-component-templates.js +182 -0
  32. package/src/react-file-operations.js +172 -0
  33. package/src/react-generator.js +219 -0
  34. package/src/react-templates.js +418 -0
  35. package/src/templates/basic-components-templates.js +157 -0
  36. package/src/templates/form-components-templates.js +194 -0
  37. package/src/templates/interactive-components-templates.js +139 -0
  38. package/src/utils/file-utils.js +97 -0
  39. package/src/utils/path-utils.js +32 -0
  40. package/src/utils/string-utils.js +51 -0
  41. package/src/utils/template-loader.js +91 -0
  42. package/templates/_shared/PATTERNS.md +246 -0
  43. package/templates/_shared/README.md +74 -0
  44. package/templates/_shared/base.css +18 -0
  45. package/templates/blackjack/index.html +1 -1
  46. package/templates/breakout/index.html +1 -1
  47. package/templates/connect-four/index.html +1 -1
  48. package/templates/dice-game/index.html +1 -1
  49. package/templates/flappy-bird/index.html +1 -1
  50. package/templates/pong/index.html +1 -1
  51. package/templates/skeleton/index.html +4 -4
  52. package/templates/slot-machine/index.html +1 -1
  53. package/templates/tetris/index.html +1 -1
  54. package/templates-react/README.md +126 -0
  55. package/templates-react/alert/Alert.css +158 -0
  56. package/templates-react/alert/Alert.example.jsx +106 -0
  57. package/templates-react/alert/Alert.jsx +61 -0
  58. package/templates-react/badge/Badge.css +196 -0
  59. package/templates-react/badge/Badge.example.jsx +182 -0
  60. package/templates-react/badge/Badge.jsx +44 -0
  61. package/templates-react/button/Button.css +88 -0
  62. package/templates-react/button/Button.example.jsx +40 -0
  63. package/templates-react/button/Button.jsx +29 -0
  64. package/templates-react/card/Card.css +86 -0
  65. package/templates-react/card/Card.example.jsx +49 -0
  66. package/templates-react/card/Card.jsx +35 -0
  67. package/templates-react/checkbox/Checkbox.css +217 -0
  68. package/templates-react/checkbox/Checkbox.example.jsx +141 -0
  69. package/templates-react/checkbox/Checkbox.jsx +82 -0
  70. package/templates-react/counter/Counter.css +99 -0
  71. package/templates-react/counter/Counter.example.jsx +45 -0
  72. package/templates-react/counter/Counter.jsx +70 -0
  73. package/templates-react/dropdown/Dropdown.css +237 -0
  74. package/templates-react/dropdown/Dropdown.example.jsx +98 -0
  75. package/templates-react/dropdown/Dropdown.jsx +154 -0
  76. package/templates-react/form/Form.css +128 -0
  77. package/templates-react/form/Form.example.jsx +64 -0
  78. package/templates-react/form/Form.jsx +125 -0
  79. package/templates-react/input/Input.css +113 -0
  80. package/templates-react/input/Input.example.jsx +82 -0
  81. package/templates-react/input/Input.jsx +87 -0
  82. package/templates-react/modal/Modal.css +152 -0
  83. package/templates-react/modal/Modal.example.jsx +90 -0
  84. package/templates-react/modal/Modal.jsx +46 -0
  85. package/templates-react/navbar/Navbar.css +139 -0
  86. package/templates-react/navbar/Navbar.example.jsx +37 -0
  87. package/templates-react/navbar/Navbar.jsx +62 -0
  88. package/templates-react/progress/Progress.css +247 -0
  89. package/templates-react/progress/Progress.example.jsx +244 -0
  90. package/templates-react/progress/Progress.jsx +79 -0
  91. package/templates-react/switch/Switch.css +244 -0
  92. package/templates-react/switch/Switch.example.jsx +221 -0
  93. package/templates-react/switch/Switch.jsx +98 -0
  94. package/templates-react/todo-list/TodoList.css +236 -0
  95. package/templates-react/todo-list/TodoList.example.jsx +15 -0
  96. package/templates-react/todo-list/TodoList.jsx +84 -0
  97. package/templates-react/tooltip/Tooltip.css +165 -0
  98. package/templates-react/tooltip/Tooltip.example.jsx +166 -0
  99. package/templates-react/tooltip/Tooltip.jsx +176 -0
@@ -0,0 +1,244 @@
1
+ .switch-wrapper {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ gap: 0.75rem;
5
+ cursor: pointer;
6
+ user-select: none;
7
+ }
8
+
9
+ .switch {
10
+ position: relative;
11
+ display: inline-block;
12
+ flex-shrink: 0;
13
+ }
14
+
15
+ .switch-input {
16
+ position: absolute;
17
+ opacity: 0;
18
+ width: 100%;
19
+ height: 100%;
20
+ cursor: pointer;
21
+ z-index: 1;
22
+ }
23
+
24
+ .switch-input:disabled {
25
+ cursor: not-allowed;
26
+ }
27
+
28
+ .switch-slider {
29
+ position: relative;
30
+ display: flex;
31
+ align-items: center;
32
+ background-color: #d1d5db;
33
+ border-radius: 9999px;
34
+ transition: all 0.3s ease;
35
+ }
36
+
37
+ .switch-slider::before {
38
+ content: '';
39
+ position: absolute;
40
+ background-color: white;
41
+ border-radius: 50%;
42
+ transition: all 0.3s ease;
43
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
44
+ }
45
+
46
+ /* Sizes */
47
+ .switch-small {
48
+ width: 2rem;
49
+ height: 1.125rem;
50
+ }
51
+
52
+ .switch-small .switch-slider::before {
53
+ width: 0.875rem;
54
+ height: 0.875rem;
55
+ left: 0.125rem;
56
+ }
57
+
58
+ .switch-small.switch-checked .switch-slider::before {
59
+ transform: translateX(0.875rem);
60
+ }
61
+
62
+ .switch-medium {
63
+ width: 2.75rem;
64
+ height: 1.5rem;
65
+ }
66
+
67
+ .switch-medium .switch-slider::before {
68
+ width: 1.25rem;
69
+ height: 1.25rem;
70
+ left: 0.125rem;
71
+ }
72
+
73
+ .switch-medium.switch-checked .switch-slider::before {
74
+ transform: translateX(1.25rem);
75
+ }
76
+
77
+ .switch-large {
78
+ width: 3.5rem;
79
+ height: 2rem;
80
+ }
81
+
82
+ .switch-large .switch-slider::before {
83
+ width: 1.75rem;
84
+ height: 1.75rem;
85
+ left: 0.125rem;
86
+ }
87
+
88
+ .switch-large.switch-checked .switch-slider::before {
89
+ transform: translateX(1.5rem);
90
+ }
91
+
92
+ /* Colors */
93
+ .switch-checked.switch-primary .switch-slider {
94
+ background-color: ##PRIMARY_COLOR##;
95
+ }
96
+
97
+ .switch-checked.switch-secondary .switch-slider {
98
+ background-color: ##SECONDARY_COLOR##;
99
+ }
100
+
101
+ .switch-checked.switch-success .switch-slider {
102
+ background-color: #10b981;
103
+ }
104
+
105
+ .switch-checked.switch-error .switch-slider {
106
+ background-color: #ef4444;
107
+ }
108
+
109
+ .switch-checked.switch-warning .switch-slider {
110
+ background-color: #f59e0b;
111
+ }
112
+
113
+ .switch-checked.switch-info .switch-slider {
114
+ background-color: #3b82f6;
115
+ }
116
+
117
+ /* Disabled state */
118
+ .switch-disabled {
119
+ opacity: 0.6;
120
+ cursor: not-allowed;
121
+ }
122
+
123
+ .switch-disabled .switch-input {
124
+ cursor: not-allowed;
125
+ }
126
+
127
+ /* Loading state */
128
+ .switch-loading {
129
+ pointer-events: none;
130
+ }
131
+
132
+ .switch-spinner {
133
+ position: absolute;
134
+ left: 50%;
135
+ top: 50%;
136
+ transform: translate(-50%, -50%);
137
+ width: 0.75rem;
138
+ height: 0.75rem;
139
+ border: 2px solid white;
140
+ border-top-color: transparent;
141
+ border-radius: 50%;
142
+ animation: spin 0.6s linear infinite;
143
+ }
144
+
145
+ @keyframes spin {
146
+ to {
147
+ transform: translate(-50%, -50%) rotate(360deg);
148
+ }
149
+ }
150
+
151
+ /* Icons */
152
+ .switch-icon {
153
+ position: absolute;
154
+ left: 50%;
155
+ top: 50%;
156
+ transform: translate(-50%, -50%);
157
+ display: flex;
158
+ align-items: center;
159
+ justify-content: center;
160
+ font-size: 0.75rem;
161
+ color: white;
162
+ pointer-events: none;
163
+ transition: opacity 0.2s;
164
+ }
165
+
166
+ .switch-small .switch-icon {
167
+ font-size: 0.625rem;
168
+ }
169
+
170
+ .switch-large .switch-icon {
171
+ font-size: 0.875rem;
172
+ }
173
+
174
+ /* Label */
175
+ .switch-label {
176
+ color: #374151;
177
+ font-size: 0.875rem;
178
+ cursor: pointer;
179
+ transition: color 0.2s;
180
+ }
181
+
182
+ .switch-label-disabled {
183
+ color: #9ca3af;
184
+ cursor: not-allowed;
185
+ }
186
+
187
+ /* Focus state */
188
+ .switch-input:focus + .switch-slider {
189
+ outline: 2px solid ##PRIMARY_COLOR##;
190
+ outline-offset: 2px;
191
+ }
192
+
193
+ /* Hover state */
194
+ .switch:not(.switch-disabled):hover .switch-slider {
195
+ filter: brightness(0.95);
196
+ }
197
+
198
+ .switch-checked:not(.switch-disabled):hover .switch-slider {
199
+ filter: brightness(1.05);
200
+ }
201
+
202
+ /* Active state */
203
+ .switch:not(.switch-disabled):active .switch-slider::before {
204
+ width: 1.5rem;
205
+ }
206
+
207
+ .switch-small:not(.switch-disabled):active .switch-slider::before {
208
+ width: 1rem;
209
+ }
210
+
211
+ .switch-large:not(.switch-disabled):active .switch-slider::before {
212
+ width: 2rem;
213
+ }
214
+
215
+ /* Dark Mode Support */
216
+ @media (prefers-color-scheme: dark) {
217
+ .switch-slider {
218
+ background-color: #4b5563;
219
+ }
220
+
221
+ .switch-slider::before {
222
+ background-color: #1f2937;
223
+ }
224
+
225
+ .switch-checked.switch-primary .switch-slider {
226
+ background-color: ##SECONDARY_COLOR##;
227
+ }
228
+
229
+ .switch-checked.switch-secondary .switch-slider {
230
+ background-color: ##PRIMARY_COLOR##;
231
+ }
232
+
233
+ .switch-label {
234
+ color: #e5e7eb;
235
+ }
236
+
237
+ .switch-label-disabled {
238
+ color: #6b7280;
239
+ }
240
+
241
+ .switch-input:focus + .switch-slider {
242
+ outline-color: ##SECONDARY_COLOR##;
243
+ }
244
+ }
@@ -0,0 +1,221 @@
1
+ import { useState } from 'react';
2
+ import Switch from './Switch';
3
+
4
+ function SwitchExample() {
5
+ const [checked, setChecked] = useState(false);
6
+ const [notifications, setNotifications] = useState(true);
7
+ const [darkMode, setDarkMode] = useState(false);
8
+ const [settings, setSettings] = useState({
9
+ wifi: true,
10
+ bluetooth: false,
11
+ airplane: false
12
+ });
13
+
14
+ const handleSettingChange = (key) => (value) => {
15
+ setSettings(prev => ({ ...prev, [key]: value }));
16
+ };
17
+
18
+ return (
19
+ <div style={{ padding: '2rem', maxWidth: '800px', margin: '0 auto' }}>
20
+ <h1>Switch Component Examples</h1>
21
+
22
+ <section style={{ marginBottom: '3rem' }}>
23
+ <h2>Basic Switch</h2>
24
+ <Switch
25
+ checked={checked}
26
+ onChange={setChecked}
27
+ label="Enable feature"
28
+ />
29
+ <p style={{ marginTop: '0.5rem', color: '#666' }}>
30
+ Status: {checked ? 'ON' : 'OFF'}
31
+ </p>
32
+ </section>
33
+
34
+ <section style={{ marginBottom: '3rem' }}>
35
+ <h2>Sizes</h2>
36
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
37
+ <Switch size="small" label="Small switch" />
38
+ <Switch size="medium" label="Medium switch (default)" />
39
+ <Switch size="large" label="Large switch" />
40
+ </div>
41
+ </section>
42
+
43
+ <section style={{ marginBottom: '3rem' }}>
44
+ <h2>Colors</h2>
45
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
46
+ <Switch checked color="primary" label="Primary" />
47
+ <Switch checked color="secondary" label="Secondary" />
48
+ <Switch checked color="success" label="Success" />
49
+ <Switch checked color="error" label="Error" />
50
+ <Switch checked color="warning" label="Warning" />
51
+ <Switch checked color="info" label="Info" />
52
+ </div>
53
+ </section>
54
+
55
+ <section style={{ marginBottom: '3rem' }}>
56
+ <h2>Label Positions</h2>
57
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
58
+ <Switch label="Label on right (default)" labelPosition="right" />
59
+ <Switch label="Label on left" labelPosition="left" />
60
+ <Switch />
61
+ </div>
62
+ </section>
63
+
64
+ <section style={{ marginBottom: '3rem' }}>
65
+ <h2>With Icons</h2>
66
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
67
+ <Switch
68
+ checked
69
+ label="Light/Dark mode"
70
+ icons={{
71
+ checked: '🌙',
72
+ unchecked: '☀️'
73
+ }}
74
+ />
75
+ <Switch
76
+ checked
77
+ label="Sound"
78
+ icons={{
79
+ checked: '🔊',
80
+ unchecked: '🔇'
81
+ }}
82
+ color="success"
83
+ />
84
+ <Switch
85
+ label="Notifications"
86
+ icons={{
87
+ checked: '✓',
88
+ unchecked: '✕'
89
+ }}
90
+ color="info"
91
+ />
92
+ </div>
93
+ </section>
94
+
95
+ <section style={{ marginBottom: '3rem' }}>
96
+ <h2>States</h2>
97
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
98
+ <Switch label="Normal switch" />
99
+ <Switch checked label="Checked switch" />
100
+ <Switch disabled label="Disabled off" />
101
+ <Switch checked disabled label="Disabled on" />
102
+ <Switch loading label="Loading state" />
103
+ </div>
104
+ </section>
105
+
106
+ <section style={{ marginBottom: '3rem' }}>
107
+ <h2>Settings Panel Example</h2>
108
+ <div style={{
109
+ backgroundColor: '#f9fafb',
110
+ padding: '1.5rem',
111
+ borderRadius: '0.5rem',
112
+ border: '1px solid #e5e7eb'
113
+ }}>
114
+ <h3 style={{ fontSize: '1rem', marginBottom: '1rem', color: '#111827' }}>
115
+ Connection Settings
116
+ </h3>
117
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
118
+ <div style={{
119
+ display: 'flex',
120
+ justifyContent: 'space-between',
121
+ alignItems: 'center',
122
+ padding: '0.75rem',
123
+ backgroundColor: 'white',
124
+ borderRadius: '0.375rem'
125
+ }}>
126
+ <div>
127
+ <div style={{ fontWeight: '500', color: '#111827' }}>Wi-Fi</div>
128
+ <div style={{ fontSize: '0.875rem', color: '#6b7280' }}>
129
+ {settings.wifi ? 'Connected' : 'Disconnected'}
130
+ </div>
131
+ </div>
132
+ <Switch
133
+ checked={settings.wifi}
134
+ onChange={handleSettingChange('wifi')}
135
+ color="success"
136
+ />
137
+ </div>
138
+
139
+ <div style={{
140
+ display: 'flex',
141
+ justifyContent: 'space-between',
142
+ alignItems: 'center',
143
+ padding: '0.75rem',
144
+ backgroundColor: 'white',
145
+ borderRadius: '0.375rem'
146
+ }}>
147
+ <div>
148
+ <div style={{ fontWeight: '500', color: '#111827' }}>Bluetooth</div>
149
+ <div style={{ fontSize: '0.875rem', color: '#6b7280' }}>
150
+ {settings.bluetooth ? 'On' : 'Off'}
151
+ </div>
152
+ </div>
153
+ <Switch
154
+ checked={settings.bluetooth}
155
+ onChange={handleSettingChange('bluetooth')}
156
+ color="info"
157
+ />
158
+ </div>
159
+
160
+ <div style={{
161
+ display: 'flex',
162
+ justifyContent: 'space-between',
163
+ alignItems: 'center',
164
+ padding: '0.75rem',
165
+ backgroundColor: 'white',
166
+ borderRadius: '0.375rem'
167
+ }}>
168
+ <div>
169
+ <div style={{ fontWeight: '500', color: '#111827' }}>Airplane Mode</div>
170
+ <div style={{ fontSize: '0.875rem', color: '#6b7280' }}>
171
+ {settings.airplane ? 'Enabled' : 'Disabled'}
172
+ </div>
173
+ </div>
174
+ <Switch
175
+ checked={settings.airplane}
176
+ onChange={handleSettingChange('airplane')}
177
+ color="warning"
178
+ />
179
+ </div>
180
+ </div>
181
+ </div>
182
+ </section>
183
+
184
+ <section style={{ marginBottom: '3rem' }}>
185
+ <h2>Preference Toggles</h2>
186
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
187
+ <Switch
188
+ checked={notifications}
189
+ onChange={setNotifications}
190
+ label="Enable notifications"
191
+ color="primary"
192
+ icons={{
193
+ checked: '🔔',
194
+ unchecked: '🔕'
195
+ }}
196
+ />
197
+
198
+ <Switch
199
+ checked={darkMode}
200
+ onChange={setDarkMode}
201
+ label="Dark mode"
202
+ color="secondary"
203
+ icons={{
204
+ checked: '🌙',
205
+ unchecked: '☀️'
206
+ }}
207
+ />
208
+ </div>
209
+ <div style={{ marginTop: '1rem', padding: '1rem', backgroundColor: '#f3f4f6', borderRadius: '0.375rem' }}>
210
+ <strong>Current Preferences:</strong>
211
+ <ul style={{ marginTop: '0.5rem', paddingLeft: '1.5rem' }}>
212
+ <li>Notifications: {notifications ? 'Enabled' : 'Disabled'}</li>
213
+ <li>Dark Mode: {darkMode ? 'On' : 'Off'}</li>
214
+ </ul>
215
+ </div>
216
+ </section>
217
+ </div>
218
+ );
219
+ }
220
+
221
+ export default SwitchExample;
@@ -0,0 +1,98 @@
1
+
2
+ import './Switch.css';
3
+ import { useState } from 'react';
4
+
5
+ function Switch({
6
+ checked = false,
7
+ onChange,
8
+ disabled = false,
9
+ size = 'medium',
10
+ color = 'primary',
11
+ label = '',
12
+ labelPosition = 'right',
13
+ loading = false,
14
+ icons = null,
15
+ name = '',
16
+ id,
17
+ className = ''
18
+ }) {
19
+ const [isChecked, setIsChecked] = useState(checked);
20
+
21
+ const handleChange = (e) => {
22
+ if (disabled || loading) return;
23
+
24
+ const newValue = e.target.checked;
25
+ setIsChecked(newValue);
26
+ onChange?.(newValue, e);
27
+ };
28
+
29
+ const switchId = id || `switch-${name || Math.random().toString(36).substr(2, 9)}`;
30
+
31
+ const switchClasses = [
32
+ 'switch',
33
+ `switch-${size}`,
34
+ `switch-${color}`,
35
+ isChecked ? 'switch-checked' : '',
36
+ disabled ? 'switch-disabled' : '',
37
+ loading ? 'switch-loading' : '',
38
+ className
39
+ ].filter(Boolean).join(' ');
40
+
41
+ const labelClasses = [
42
+ 'switch-label',
43
+ labelPosition === 'left' ? 'switch-label-left' : 'switch-label-right',
44
+ disabled ? 'switch-label-disabled' : ''
45
+ ].filter(Boolean).join(' ');
46
+
47
+ const renderIcons = () => {
48
+ if (!icons) return null;
49
+
50
+ return (
51
+ <span className="switch-icon">
52
+ {isChecked ? icons.checked : icons.unchecked}
53
+ </span>
54
+ );
55
+ };
56
+
57
+ const switchElement = (
58
+ <div className={switchClasses}>
59
+ <input
60
+ id={switchId}
61
+ type="checkbox"
62
+ className="switch-input"
63
+ checked={isChecked}
64
+ onChange={handleChange}
65
+ disabled={disabled || loading}
66
+ name={name}
67
+ role="switch"
68
+ aria-checked={isChecked}
69
+ aria-label={label || undefined}
70
+ />
71
+ <span className="switch-slider">
72
+ {loading ? (
73
+ <span className="switch-spinner"></span>
74
+ ) : (
75
+ renderIcons()
76
+ )}
77
+ </span>
78
+ </div>
79
+ );
80
+
81
+ if (!label) {
82
+ return switchElement;
83
+ }
84
+
85
+ return (
86
+ <label htmlFor={switchId} className="switch-wrapper">
87
+ {labelPosition === 'left' && (
88
+ <span className={labelClasses}>{label}</span>
89
+ )}
90
+ {switchElement}
91
+ {labelPosition === 'right' && (
92
+ <span className={labelClasses}>{label}</span>
93
+ )}
94
+ </label>
95
+ );
96
+ }
97
+
98
+ export default Switch;