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.
- package/CHANGELOG.md +436 -0
- package/CODE-SPLITTING-GUIDE.md +274 -0
- package/COMPONENTS-GALLERY.html +143 -8
- package/HTML-VS-REACT.md +289 -0
- package/QUICKSTART-REACT.md +293 -0
- package/REACT-SUPPORT-SUMMARY.md +235 -0
- package/README.md +261 -12
- package/bin/cli.js +100 -759
- package/bin/commands/create.js +288 -0
- package/bin/commands/gallery.js +42 -0
- package/bin/commands/insert.js +123 -0
- package/bin/commands/list.js +73 -0
- package/package.json +10 -3
- package/src/component-choices.js +7 -0
- package/src/components-registry.js +112 -0
- package/src/format-utils.js +49 -0
- package/src/generator.js +83 -594
- package/src/generators/color-schemes.js +78 -0
- package/src/generators/color-utils.js +108 -0
- package/src/generators/component-filters.js +151 -0
- package/src/generators/html-generators.js +180 -0
- package/src/generators/validation.js +43 -0
- package/src/index.js +2 -1
- package/src/inserter.js +55 -233
- package/src/inserters/backup-utils.js +20 -0
- package/src/inserters/component-loader.js +68 -0
- package/src/inserters/html-utils.js +31 -0
- package/src/inserters/indentation-utils.js +90 -0
- package/src/inserters/validation-utils.js +49 -0
- package/src/react-component-choices.js +97 -0
- package/src/react-component-templates.js +182 -0
- package/src/react-file-operations.js +172 -0
- package/src/react-generator.js +219 -0
- package/src/react-templates.js +418 -0
- package/src/templates/basic-components-templates.js +157 -0
- package/src/templates/form-components-templates.js +194 -0
- package/src/templates/interactive-components-templates.js +139 -0
- package/src/utils/file-utils.js +97 -0
- package/src/utils/path-utils.js +32 -0
- package/src/utils/string-utils.js +51 -0
- package/src/utils/template-loader.js +91 -0
- package/templates/_shared/PATTERNS.md +246 -0
- package/templates/_shared/README.md +74 -0
- package/templates/_shared/base.css +18 -0
- package/templates/blackjack/index.html +1 -1
- package/templates/breakout/index.html +1 -1
- package/templates/connect-four/index.html +1 -1
- package/templates/dice-game/index.html +1 -1
- package/templates/flappy-bird/index.html +1 -1
- package/templates/pong/index.html +1 -1
- package/templates/skeleton/index.html +4 -4
- package/templates/slot-machine/index.html +1 -1
- package/templates/tetris/index.html +1 -1
- package/templates-react/README.md +126 -0
- package/templates-react/alert/Alert.css +158 -0
- package/templates-react/alert/Alert.example.jsx +106 -0
- package/templates-react/alert/Alert.jsx +61 -0
- package/templates-react/badge/Badge.css +196 -0
- package/templates-react/badge/Badge.example.jsx +182 -0
- package/templates-react/badge/Badge.jsx +44 -0
- package/templates-react/button/Button.css +88 -0
- package/templates-react/button/Button.example.jsx +40 -0
- package/templates-react/button/Button.jsx +29 -0
- package/templates-react/card/Card.css +86 -0
- package/templates-react/card/Card.example.jsx +49 -0
- package/templates-react/card/Card.jsx +35 -0
- package/templates-react/checkbox/Checkbox.css +217 -0
- package/templates-react/checkbox/Checkbox.example.jsx +141 -0
- package/templates-react/checkbox/Checkbox.jsx +82 -0
- package/templates-react/counter/Counter.css +99 -0
- package/templates-react/counter/Counter.example.jsx +45 -0
- package/templates-react/counter/Counter.jsx +70 -0
- package/templates-react/dropdown/Dropdown.css +237 -0
- package/templates-react/dropdown/Dropdown.example.jsx +98 -0
- package/templates-react/dropdown/Dropdown.jsx +154 -0
- package/templates-react/form/Form.css +128 -0
- package/templates-react/form/Form.example.jsx +64 -0
- package/templates-react/form/Form.jsx +125 -0
- package/templates-react/input/Input.css +113 -0
- package/templates-react/input/Input.example.jsx +82 -0
- package/templates-react/input/Input.jsx +87 -0
- package/templates-react/modal/Modal.css +152 -0
- package/templates-react/modal/Modal.example.jsx +90 -0
- package/templates-react/modal/Modal.jsx +46 -0
- package/templates-react/navbar/Navbar.css +139 -0
- package/templates-react/navbar/Navbar.example.jsx +37 -0
- package/templates-react/navbar/Navbar.jsx +62 -0
- package/templates-react/progress/Progress.css +247 -0
- package/templates-react/progress/Progress.example.jsx +244 -0
- package/templates-react/progress/Progress.jsx +79 -0
- package/templates-react/switch/Switch.css +244 -0
- package/templates-react/switch/Switch.example.jsx +221 -0
- package/templates-react/switch/Switch.jsx +98 -0
- package/templates-react/todo-list/TodoList.css +236 -0
- package/templates-react/todo-list/TodoList.example.jsx +15 -0
- package/templates-react/todo-list/TodoList.jsx +84 -0
- package/templates-react/tooltip/Tooltip.css +165 -0
- package/templates-react/tooltip/Tooltip.example.jsx +166 -0
- package/templates-react/tooltip/Tooltip.jsx +176 -0
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
.progress-container {
|
|
2
|
+
width: 100%;
|
|
3
|
+
margin-bottom: 1rem;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.progress-label-container {
|
|
7
|
+
display: flex;
|
|
8
|
+
justify-content: space-between;
|
|
9
|
+
align-items: center;
|
|
10
|
+
margin-bottom: 0.5rem;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.progress-label {
|
|
14
|
+
font-size: 0.875rem;
|
|
15
|
+
font-weight: 500;
|
|
16
|
+
color: #374151;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.progress {
|
|
20
|
+
width: 100%;
|
|
21
|
+
background-color: #e5e7eb;
|
|
22
|
+
border-radius: 9999px;
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
position: relative;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/* Sizes */
|
|
28
|
+
.progress-small {
|
|
29
|
+
height: 0.5rem;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.progress-medium {
|
|
33
|
+
height: 0.75rem;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.progress-large {
|
|
37
|
+
height: 1.25rem;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/* Progress Bar */
|
|
41
|
+
.progress-bar {
|
|
42
|
+
height: 100%;
|
|
43
|
+
display: flex;
|
|
44
|
+
align-items: center;
|
|
45
|
+
justify-content: center;
|
|
46
|
+
transition: width 0.6s ease;
|
|
47
|
+
border-radius: 9999px;
|
|
48
|
+
position: relative;
|
|
49
|
+
overflow: hidden;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/* Colors */
|
|
53
|
+
.progress-bar-primary {
|
|
54
|
+
background-color: ##PRIMARY_COLOR##;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.progress-bar-secondary {
|
|
58
|
+
background-color: ##SECONDARY_COLOR##;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.progress-bar-success {
|
|
62
|
+
background-color: #10b981;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.progress-bar-warning {
|
|
66
|
+
background-color: #f59e0b;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.progress-bar-error {
|
|
70
|
+
background-color: #ef4444;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.progress-bar-info {
|
|
74
|
+
background-color: #3b82f6;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.progress-bar-default {
|
|
78
|
+
background-color: #6b7280;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* Value Label */
|
|
82
|
+
.progress-value {
|
|
83
|
+
font-size: 0.75rem;
|
|
84
|
+
font-weight: 600;
|
|
85
|
+
color: white;
|
|
86
|
+
white-space: nowrap;
|
|
87
|
+
padding: 0 0.5rem;
|
|
88
|
+
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.progress-small .progress-value {
|
|
92
|
+
font-size: 0.625rem;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.progress-large .progress-value {
|
|
96
|
+
font-size: 0.875rem;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/* Striped Pattern */
|
|
100
|
+
.progress-bar-striped {
|
|
101
|
+
background-image: linear-gradient(
|
|
102
|
+
45deg,
|
|
103
|
+
rgba(255, 255, 255, 0.15) 25%,
|
|
104
|
+
transparent 25%,
|
|
105
|
+
transparent 50%,
|
|
106
|
+
rgba(255, 255, 255, 0.15) 50%,
|
|
107
|
+
rgba(255, 255, 255, 0.15) 75%,
|
|
108
|
+
transparent 75%,
|
|
109
|
+
transparent
|
|
110
|
+
);
|
|
111
|
+
background-size: 1rem 1rem;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* Animated Stripes */
|
|
115
|
+
.progress-bar-animated {
|
|
116
|
+
animation: progress-bar-stripes 1s linear infinite;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
@keyframes progress-bar-stripes {
|
|
120
|
+
from {
|
|
121
|
+
background-position: 1rem 0;
|
|
122
|
+
}
|
|
123
|
+
to {
|
|
124
|
+
background-position: 0 0;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* Indeterminate Progress */
|
|
129
|
+
.progress-indeterminate .progress-bar {
|
|
130
|
+
width: 100% !important;
|
|
131
|
+
animation: indeterminate 1.5s ease-in-out infinite;
|
|
132
|
+
background: linear-gradient(
|
|
133
|
+
90deg,
|
|
134
|
+
transparent,
|
|
135
|
+
currentColor 50%,
|
|
136
|
+
transparent
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
@keyframes indeterminate {
|
|
141
|
+
0% {
|
|
142
|
+
transform: translateX(-100%);
|
|
143
|
+
}
|
|
144
|
+
100% {
|
|
145
|
+
transform: translateX(100%);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/* Gradient Variants */
|
|
150
|
+
.progress-bar-gradient {
|
|
151
|
+
background: linear-gradient(90deg, ##PRIMARY_COLOR## 0%, ##SECONDARY_COLOR## 100%);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/* Pulse Animation */
|
|
155
|
+
@keyframes pulse-glow {
|
|
156
|
+
0%, 100% {
|
|
157
|
+
box-shadow: 0 0 0 0 rgba(59, 130, 246, 0.4);
|
|
158
|
+
}
|
|
159
|
+
50% {
|
|
160
|
+
box-shadow: 0 0 0 4px rgba(59, 130, 246, 0);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.progress-bar-pulse {
|
|
165
|
+
animation: pulse-glow 2s ease-in-out infinite;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/* Percentage outside bar */
|
|
169
|
+
.progress-percentage-outside {
|
|
170
|
+
display: flex;
|
|
171
|
+
align-items: center;
|
|
172
|
+
gap: 0.75rem;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.progress-percentage-outside .progress {
|
|
176
|
+
flex: 1;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.progress-percentage-text {
|
|
180
|
+
font-size: 0.875rem;
|
|
181
|
+
font-weight: 600;
|
|
182
|
+
color: #374151;
|
|
183
|
+
min-width: 3rem;
|
|
184
|
+
text-align: right;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/* Circular Progress (bonus) */
|
|
188
|
+
.progress-circular {
|
|
189
|
+
width: 100px;
|
|
190
|
+
height: 100px;
|
|
191
|
+
border-radius: 50%;
|
|
192
|
+
background: conic-gradient(
|
|
193
|
+
##PRIMARY_COLOR## calc(var(--progress) * 1%),
|
|
194
|
+
#e5e7eb 0
|
|
195
|
+
);
|
|
196
|
+
display: flex;
|
|
197
|
+
align-items: center;
|
|
198
|
+
justify-content: center;
|
|
199
|
+
position: relative;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.progress-circular::before {
|
|
203
|
+
content: '';
|
|
204
|
+
position: absolute;
|
|
205
|
+
width: 80%;
|
|
206
|
+
height: 80%;
|
|
207
|
+
border-radius: 50%;
|
|
208
|
+
background: white;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.progress-circular-value {
|
|
212
|
+
position: relative;
|
|
213
|
+
z-index: 1;
|
|
214
|
+
font-weight: 600;
|
|
215
|
+
color: #374151;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
/* Dark Mode Support */
|
|
219
|
+
@media (prefers-color-scheme: dark) {
|
|
220
|
+
.progress {
|
|
221
|
+
background-color: #374151;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.progress-label {
|
|
225
|
+
color: #e5e7eb;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
.progress-bar-primary {
|
|
229
|
+
background-color: ##SECONDARY_COLOR##;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.progress-bar-secondary {
|
|
233
|
+
background-color: ##PRIMARY_COLOR##;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.progress-percentage-text {
|
|
237
|
+
color: #e5e7eb;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
.progress-circular::before {
|
|
241
|
+
background: #1f2937;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
.progress-circular-value {
|
|
245
|
+
color: #e5e7eb;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
import Progress from './Progress';
|
|
3
|
+
|
|
4
|
+
function ProgressExample() {
|
|
5
|
+
const [uploadProgress, setUploadProgress] = useState(0);
|
|
6
|
+
const [downloadProgress, setDownloadProgress] = useState(0);
|
|
7
|
+
|
|
8
|
+
// Simulate upload progress
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
const interval = setInterval(() => {
|
|
11
|
+
setUploadProgress((prev) => {
|
|
12
|
+
if (prev >= 100) return 0;
|
|
13
|
+
return prev + 2;
|
|
14
|
+
});
|
|
15
|
+
}, 100);
|
|
16
|
+
|
|
17
|
+
return () => clearInterval(interval);
|
|
18
|
+
}, []);
|
|
19
|
+
|
|
20
|
+
// Simulate download progress
|
|
21
|
+
useEffect(() => {
|
|
22
|
+
const interval = setInterval(() => {
|
|
23
|
+
setDownloadProgress((prev) => {
|
|
24
|
+
if (prev >= 100) return 0;
|
|
25
|
+
return prev + 1;
|
|
26
|
+
});
|
|
27
|
+
}, 150);
|
|
28
|
+
|
|
29
|
+
return () => clearInterval(interval);
|
|
30
|
+
}, []);
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<div style={{ padding: '2rem', maxWidth: '800px', margin: '0 auto' }}>
|
|
34
|
+
<h1>Progress Component Examples</h1>
|
|
35
|
+
|
|
36
|
+
<section style={{ marginBottom: '3rem' }}>
|
|
37
|
+
<h2>Basic Progress</h2>
|
|
38
|
+
<Progress value={50} />
|
|
39
|
+
<Progress value={75} variant="success" />
|
|
40
|
+
<Progress value={30} variant="warning" />
|
|
41
|
+
</section>
|
|
42
|
+
|
|
43
|
+
<section style={{ marginBottom: '3rem' }}>
|
|
44
|
+
<h2>Sizes</h2>
|
|
45
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
|
|
46
|
+
<div>
|
|
47
|
+
<p style={{ marginBottom: '0.5rem', fontSize: '0.875rem', color: '#666' }}>Small</p>
|
|
48
|
+
<Progress value={60} size="small" variant="primary" />
|
|
49
|
+
</div>
|
|
50
|
+
<div>
|
|
51
|
+
<p style={{ marginBottom: '0.5rem', fontSize: '0.875rem', color: '#666' }}>Medium (default)</p>
|
|
52
|
+
<Progress value={60} size="medium" variant="primary" />
|
|
53
|
+
</div>
|
|
54
|
+
<div>
|
|
55
|
+
<p style={{ marginBottom: '0.5rem', fontSize: '0.875rem', color: '#666' }}>Large</p>
|
|
56
|
+
<Progress value={60} size="large" variant="primary" />
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
</section>
|
|
60
|
+
|
|
61
|
+
<section style={{ marginBottom: '3rem' }}>
|
|
62
|
+
<h2>Colors</h2>
|
|
63
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
|
|
64
|
+
<Progress value={70} variant="primary" showPercentage />
|
|
65
|
+
<Progress value={70} variant="secondary" showPercentage />
|
|
66
|
+
<Progress value={70} variant="success" showPercentage />
|
|
67
|
+
<Progress value={70} variant="warning" showPercentage />
|
|
68
|
+
<Progress value={70} variant="error" showPercentage />
|
|
69
|
+
<Progress value={70} variant="info" showPercentage />
|
|
70
|
+
</div>
|
|
71
|
+
</section>
|
|
72
|
+
|
|
73
|
+
<section style={{ marginBottom: '3rem' }}>
|
|
74
|
+
<h2>With Labels</h2>
|
|
75
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}>
|
|
76
|
+
<Progress
|
|
77
|
+
value={45}
|
|
78
|
+
variant="primary"
|
|
79
|
+
showLabel
|
|
80
|
+
label="Uploading files"
|
|
81
|
+
/>
|
|
82
|
+
<Progress
|
|
83
|
+
value={78}
|
|
84
|
+
variant="success"
|
|
85
|
+
showPercentage
|
|
86
|
+
size="large"
|
|
87
|
+
/>
|
|
88
|
+
<Progress
|
|
89
|
+
value={23}
|
|
90
|
+
max={50}
|
|
91
|
+
variant="info"
|
|
92
|
+
showLabel
|
|
93
|
+
/>
|
|
94
|
+
</div>
|
|
95
|
+
</section>
|
|
96
|
+
|
|
97
|
+
<section style={{ marginBottom: '3rem' }}>
|
|
98
|
+
<h2>Striped Progress</h2>
|
|
99
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
|
|
100
|
+
<Progress value={60} variant="primary" striped />
|
|
101
|
+
<Progress value={45} variant="success" striped />
|
|
102
|
+
<Progress value={80} variant="warning" striped />
|
|
103
|
+
</div>
|
|
104
|
+
</section>
|
|
105
|
+
|
|
106
|
+
<section style={{ marginBottom: '3rem' }}>
|
|
107
|
+
<h2>Animated Striped</h2>
|
|
108
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
|
|
109
|
+
<Progress value={65} variant="primary" striped animated showPercentage />
|
|
110
|
+
<Progress value={40} variant="success" striped animated showPercentage />
|
|
111
|
+
<Progress value={85} variant="error" striped animated showPercentage />
|
|
112
|
+
</div>
|
|
113
|
+
</section>
|
|
114
|
+
|
|
115
|
+
<section style={{ marginBottom: '3rem' }}>
|
|
116
|
+
<h2>Indeterminate (Loading)</h2>
|
|
117
|
+
<Progress indeterminate variant="primary" />
|
|
118
|
+
<p style={{ marginTop: '0.5rem', fontSize: '0.875rem', color: '#666' }}>
|
|
119
|
+
Use when progress cannot be determined
|
|
120
|
+
</p>
|
|
121
|
+
</section>
|
|
122
|
+
|
|
123
|
+
<section style={{ marginBottom: '3rem' }}>
|
|
124
|
+
<h2>Live Progress Examples</h2>
|
|
125
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '2rem' }}>
|
|
126
|
+
<div>
|
|
127
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '0.5rem' }}>
|
|
128
|
+
<span style={{ fontSize: '0.875rem', fontWeight: '500' }}>Uploading...</span>
|
|
129
|
+
<span style={{ fontSize: '0.875rem', color: '#666' }}>{uploadProgress}%</span>
|
|
130
|
+
</div>
|
|
131
|
+
<Progress
|
|
132
|
+
value={uploadProgress}
|
|
133
|
+
variant="primary"
|
|
134
|
+
striped
|
|
135
|
+
animated
|
|
136
|
+
size="large"
|
|
137
|
+
/>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
<div>
|
|
141
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '0.5rem' }}>
|
|
142
|
+
<span style={{ fontSize: '0.875rem', fontWeight: '500' }}>Downloading...</span>
|
|
143
|
+
<span style={{ fontSize: '0.875rem', color: '#666' }}>{downloadProgress}%</span>
|
|
144
|
+
</div>
|
|
145
|
+
<Progress
|
|
146
|
+
value={downloadProgress}
|
|
147
|
+
variant="success"
|
|
148
|
+
striped
|
|
149
|
+
animated
|
|
150
|
+
size="large"
|
|
151
|
+
/>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
</section>
|
|
155
|
+
|
|
156
|
+
<section style={{ marginBottom: '3rem' }}>
|
|
157
|
+
<h2>File Upload Simulation</h2>
|
|
158
|
+
<div style={{
|
|
159
|
+
backgroundColor: '#f9fafb',
|
|
160
|
+
padding: '1.5rem',
|
|
161
|
+
borderRadius: '0.5rem',
|
|
162
|
+
border: '1px solid #e5e7eb'
|
|
163
|
+
}}>
|
|
164
|
+
<div style={{ marginBottom: '1.5rem' }}>
|
|
165
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem', marginBottom: '0.75rem' }}>
|
|
166
|
+
<span style={{ fontSize: '1.5rem' }}>📄</span>
|
|
167
|
+
<div style={{ flex: 1 }}>
|
|
168
|
+
<div style={{ fontWeight: '500', fontSize: '0.875rem' }}>document.pdf</div>
|
|
169
|
+
<div style={{ fontSize: '0.75rem', color: '#6b7280' }}>2.4 MB</div>
|
|
170
|
+
</div>
|
|
171
|
+
<div style={{ fontSize: '0.875rem', fontWeight: '600', color: '##PRIMARY_COLOR##' }}>
|
|
172
|
+
{uploadProgress}%
|
|
173
|
+
</div>
|
|
174
|
+
</div>
|
|
175
|
+
<Progress
|
|
176
|
+
value={uploadProgress}
|
|
177
|
+
variant="primary"
|
|
178
|
+
striped
|
|
179
|
+
animated
|
|
180
|
+
/>
|
|
181
|
+
</div>
|
|
182
|
+
|
|
183
|
+
<div>
|
|
184
|
+
<div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem', marginBottom: '0.75rem' }}>
|
|
185
|
+
<span style={{ fontSize: '1.5rem' }}>🖼️</span>
|
|
186
|
+
<div style={{ flex: 1 }}>
|
|
187
|
+
<div style={{ fontWeight: '500', fontSize: '0.875rem' }}>image.jpg</div>
|
|
188
|
+
<div style={{ fontSize: '0.75rem', color: '#6b7280' }}>5.8 MB</div>
|
|
189
|
+
</div>
|
|
190
|
+
<div style={{ fontSize: '0.875rem', fontWeight: '600', color: '#10b981' }}>
|
|
191
|
+
{downloadProgress}%
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
<Progress
|
|
195
|
+
value={downloadProgress}
|
|
196
|
+
variant="success"
|
|
197
|
+
striped
|
|
198
|
+
animated
|
|
199
|
+
/>
|
|
200
|
+
</div>
|
|
201
|
+
</div>
|
|
202
|
+
</section>
|
|
203
|
+
|
|
204
|
+
<section style={{ marginBottom: '3rem' }}>
|
|
205
|
+
<h2>Skill Levels</h2>
|
|
206
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '1.5rem' }}>
|
|
207
|
+
<div>
|
|
208
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '0.5rem' }}>
|
|
209
|
+
<span style={{ fontSize: '0.875rem', fontWeight: '500' }}>JavaScript</span>
|
|
210
|
+
<span style={{ fontSize: '0.875rem', color: '#666' }}>90%</span>
|
|
211
|
+
</div>
|
|
212
|
+
<Progress value={90} variant="primary" />
|
|
213
|
+
</div>
|
|
214
|
+
|
|
215
|
+
<div>
|
|
216
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '0.5rem' }}>
|
|
217
|
+
<span style={{ fontSize: '0.875rem', fontWeight: '500' }}>React</span>
|
|
218
|
+
<span style={{ fontSize: '0.875rem', color: '#666' }}>85%</span>
|
|
219
|
+
</div>
|
|
220
|
+
<Progress value={85} variant="info" />
|
|
221
|
+
</div>
|
|
222
|
+
|
|
223
|
+
<div>
|
|
224
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '0.5rem' }}>
|
|
225
|
+
<span style={{ fontSize: '0.875rem', fontWeight: '500' }}>CSS</span>
|
|
226
|
+
<span style={{ fontSize: '0.875rem', color: '#666' }}>80%</span>
|
|
227
|
+
</div>
|
|
228
|
+
<Progress value={80} variant="secondary" />
|
|
229
|
+
</div>
|
|
230
|
+
|
|
231
|
+
<div>
|
|
232
|
+
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: '0.5rem' }}>
|
|
233
|
+
<span style={{ fontSize: '0.875rem', fontWeight: '500' }}>Node.js</span>
|
|
234
|
+
<span style={{ fontSize: '0.875rem', color: '#666' }}>75%</span>
|
|
235
|
+
</div>
|
|
236
|
+
<Progress value={75} variant="success" />
|
|
237
|
+
</div>
|
|
238
|
+
</div>
|
|
239
|
+
</section>
|
|
240
|
+
</div>
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
export default ProgressExample;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
|
|
2
|
+
import './Progress.css';
|
|
3
|
+
|
|
4
|
+
function Progress({
|
|
5
|
+
value = 0,
|
|
6
|
+
max = 100,
|
|
7
|
+
min = 0,
|
|
8
|
+
variant = 'primary',
|
|
9
|
+
size = 'medium',
|
|
10
|
+
showLabel = false,
|
|
11
|
+
label = null,
|
|
12
|
+
showPercentage = false,
|
|
13
|
+
striped = false,
|
|
14
|
+
animated = false,
|
|
15
|
+
indeterminate = false,
|
|
16
|
+
className = ''
|
|
17
|
+
}) {
|
|
18
|
+
const calculatePercentage = () => {
|
|
19
|
+
if (indeterminate) return 100;
|
|
20
|
+
const range = max - min;
|
|
21
|
+
const currentValue = Math.min(Math.max(value, min), max) - min;
|
|
22
|
+
return (currentValue / range) * 100;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const percentage = calculatePercentage();
|
|
26
|
+
const displayValue = Math.round(percentage);
|
|
27
|
+
|
|
28
|
+
const progressClasses = [
|
|
29
|
+
'progress',
|
|
30
|
+
`progress-${size}`,
|
|
31
|
+
indeterminate ? 'progress-indeterminate' : '',
|
|
32
|
+
className
|
|
33
|
+
].filter(Boolean).join(' ');
|
|
34
|
+
|
|
35
|
+
const barClasses = [
|
|
36
|
+
'progress-bar',
|
|
37
|
+
`progress-bar-${variant}`,
|
|
38
|
+
striped ? 'progress-bar-striped' : '',
|
|
39
|
+
animated ? 'progress-bar-animated' : ''
|
|
40
|
+
].filter(Boolean).join(' ');
|
|
41
|
+
|
|
42
|
+
const getLabel = () => {
|
|
43
|
+
if (label) return label;
|
|
44
|
+
if (showPercentage) return `${displayValue}%`;
|
|
45
|
+
if (showLabel) return `${value} / ${max}`;
|
|
46
|
+
return null;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const displayLabel = getLabel();
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<div className="progress-container">
|
|
53
|
+
{displayLabel && showLabel && !showPercentage && (
|
|
54
|
+
<div className="progress-label-container">
|
|
55
|
+
<span className="progress-label">{displayLabel}</span>
|
|
56
|
+
</div>
|
|
57
|
+
)}
|
|
58
|
+
<div
|
|
59
|
+
className={progressClasses}
|
|
60
|
+
role="progressbar"
|
|
61
|
+
aria-valuenow={indeterminate ? undefined : value}
|
|
62
|
+
aria-valuemin={min}
|
|
63
|
+
aria-valuemax={max}
|
|
64
|
+
aria-label={typeof label === 'string' ? label : 'Progress'}
|
|
65
|
+
>
|
|
66
|
+
<div
|
|
67
|
+
className={barClasses}
|
|
68
|
+
style={{ width: `${percentage}%` }}
|
|
69
|
+
>
|
|
70
|
+
{(showPercentage || (displayLabel && !showLabel)) && (
|
|
71
|
+
<span className="progress-value">{displayLabel}</span>
|
|
72
|
+
)}
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export default Progress;
|