react-form-steps 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +542 -0
- package/assets/cli_demo.html +214 -0
- package/assets/cli_screenshot.png +0 -0
- package/dist/cli.js +857 -0
- package/dist/index.d.mts +129 -0
- package/dist/index.d.ts +129 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +24 -0
- package/dist/index.mjs.map +1 -0
- package/dist/index.native.d.mts +129 -0
- package/dist/index.native.js +2 -0
- package/dist/index.native.js.map +1 -0
- package/package.json +78 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>CLI Demo</title>
|
|
6
|
+
<style>
|
|
7
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
8
|
+
body {
|
|
9
|
+
background: #0c0c0c;
|
|
10
|
+
display: flex;
|
|
11
|
+
align-items: center;
|
|
12
|
+
justify-content: center;
|
|
13
|
+
min-height: 100vh;
|
|
14
|
+
font-family: 'Cascadia Code', 'Consolas', 'Courier New', monospace;
|
|
15
|
+
}
|
|
16
|
+
.terminal {
|
|
17
|
+
background: #1a1a2e;
|
|
18
|
+
border-radius: 12px;
|
|
19
|
+
width: 860px;
|
|
20
|
+
min-height: 540px;
|
|
21
|
+
box-shadow: 0 20px 60px rgba(0,0,0,0.6);
|
|
22
|
+
overflow: hidden;
|
|
23
|
+
border: 1px solid #2a2a4a;
|
|
24
|
+
}
|
|
25
|
+
.titlebar {
|
|
26
|
+
background: #16162a;
|
|
27
|
+
padding: 10px 16px;
|
|
28
|
+
display: flex;
|
|
29
|
+
align-items: center;
|
|
30
|
+
gap: 8px;
|
|
31
|
+
border-bottom: 1px solid #2a2a4a;
|
|
32
|
+
}
|
|
33
|
+
.dot { width: 12px; height: 12px; border-radius: 50%; }
|
|
34
|
+
.dot-red { background: #ff5f57; }
|
|
35
|
+
.dot-yellow { background: #febc2e; }
|
|
36
|
+
.dot-green { background: #28c840; }
|
|
37
|
+
.titlebar-text {
|
|
38
|
+
color: #888;
|
|
39
|
+
font-size: 12px;
|
|
40
|
+
margin-left: 8px;
|
|
41
|
+
}
|
|
42
|
+
.content {
|
|
43
|
+
padding: 16px 20px;
|
|
44
|
+
color: #e2e8f0;
|
|
45
|
+
font-size: 13.5px;
|
|
46
|
+
line-height: 1.6;
|
|
47
|
+
white-space: pre;
|
|
48
|
+
min-height: 490px;
|
|
49
|
+
}
|
|
50
|
+
.cyan { color: #22d3ee; }
|
|
51
|
+
.green { color: #4ade80; }
|
|
52
|
+
.yellow { color: #facc15; }
|
|
53
|
+
.red { color: #f87171; }
|
|
54
|
+
.bold { font-weight: 700; }
|
|
55
|
+
.dim { color: #64748b; }
|
|
56
|
+
.white { color: #f1f5f9; }
|
|
57
|
+
.cursor {
|
|
58
|
+
display: inline-block;
|
|
59
|
+
width: 8px;
|
|
60
|
+
height: 16px;
|
|
61
|
+
background: #e2e8f0;
|
|
62
|
+
animation: blink 1s step-end infinite;
|
|
63
|
+
vertical-align: text-bottom;
|
|
64
|
+
}
|
|
65
|
+
@keyframes blink {
|
|
66
|
+
50% { opacity: 0; }
|
|
67
|
+
}
|
|
68
|
+
</style>
|
|
69
|
+
</head>
|
|
70
|
+
<body>
|
|
71
|
+
<div class="terminal">
|
|
72
|
+
<div class="titlebar">
|
|
73
|
+
<div class="dot dot-red"></div>
|
|
74
|
+
<div class="dot dot-yellow"></div>
|
|
75
|
+
<div class="dot dot-green"></div>
|
|
76
|
+
<span class="titlebar-text">Terminal — npx react-form-steps</span>
|
|
77
|
+
</div>
|
|
78
|
+
<div class="content" id="output"></div>
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<script>
|
|
82
|
+
const output = document.getElementById('output');
|
|
83
|
+
|
|
84
|
+
const BANNER = `<span class="cyan bold"> ███████╗ ██████╗ ██████╗ ███╗ ███╗ ███████╗████████╗███████╗██████╗ ███████╗
|
|
85
|
+
██╔════╝██╔═══██╗██╔══██╗████╗ ████║ ██╔════╝╚══██╔══╝██╔════╝██╔══██╗██╔════╝
|
|
86
|
+
█████╗ ██║ ██║██████╔╝██╔████╔██║█████╗███████╗ ██║ █████╗ ██████╔╝███████╗
|
|
87
|
+
██╔══╝ ██║ ██║██╔══██╗██║╚██╔╝██║╚════╝╚════██║ ██║ ██╔══╝ ██╔═══╝ ╚════██║
|
|
88
|
+
██║ ╚██████╔╝██║ ██║██║ ╚═╝ ██║ ███████║ ██║ ███████╗██║ ███████║
|
|
89
|
+
╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝ ╚═╝ ╚══════╝╚═╝ ╚══════╝</span>
|
|
90
|
+
|
|
91
|
+
<span class="yellow">🚀 Generate customizable multi-step wizard forms in seconds!</span>
|
|
92
|
+
<span class="green">✨ Choose a platform, language, form type, and field structure.</span>
|
|
93
|
+
`;
|
|
94
|
+
|
|
95
|
+
const steps = [
|
|
96
|
+
{ type: 'typeCommand', text: 'npx react-form-steps', delay: 60 },
|
|
97
|
+
{ type: 'instant', text: '\n' + BANNER + '\n', delay: 600 },
|
|
98
|
+
{ type: 'select', question: 'Select Platform Structure:', options: ['Web (React)', 'React Native (Mobile)', 'None (Cancel)'], selected: 0, delay: 1200 },
|
|
99
|
+
{ type: 'select', question: 'Select Programming Language:', options: ['JavaScript (.js / .jsx)', 'TypeScript (.ts / .tsx)'], selected: 1, delay: 1000 },
|
|
100
|
+
{ type: 'select', question: 'Select Form Rendering Style:', options: ['Normal Inline Page Component', 'Popup / Modal Overlay Component'], selected: 0, delay: 1000 },
|
|
101
|
+
{ type: 'select', question: 'Select Form State Strategy:', options: ['Normal (React Hook Form)', 'Redux (React Hook Form + Redux Toolkit)'], selected: 0, delay: 1000 },
|
|
102
|
+
{ type: 'typeInput', question: 'How many steps do you want in the wizard?', default: '3', answer: '3', delay: 800 },
|
|
103
|
+
{ type: 'typeInput', question: 'How many input fields do you want per step?', default: '2', answer: '3', delay: 800 },
|
|
104
|
+
{ type: 'instant', text: '<span class="green">⏳ Generating form-steps scaffolding...</span>\n', delay: 1200 },
|
|
105
|
+
{ type: 'instant', text: '\n<span class="green bold">✔ Scaffolding created successfully inside folder: ./form-steps !</span>\n', delay: 400 },
|
|
106
|
+
{ type: 'instant', text: '\n<span class="bold white">Next steps to render: </span>\n Import and render it in your App Component:\n <span class="cyan">import { FormStepsWizard } from \'./form-steps\';</span>\n', delay: 400 },
|
|
107
|
+
{ type: 'instant', text: '\n<span class="green">Enjoy using react-form-steps CLI! 🎉</span>\n', delay: 100 },
|
|
108
|
+
];
|
|
109
|
+
|
|
110
|
+
let html = '';
|
|
111
|
+
|
|
112
|
+
function appendHTML(newHtml) {
|
|
113
|
+
html += newHtml;
|
|
114
|
+
output.innerHTML = html;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function setHTML(newHtml) {
|
|
118
|
+
html = newHtml;
|
|
119
|
+
output.innerHTML = html;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function sleep(ms) {
|
|
123
|
+
return new Promise(r => setTimeout(r, ms));
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
async function typeText(text, charDelay) {
|
|
127
|
+
for (const ch of text) {
|
|
128
|
+
appendHTML(ch);
|
|
129
|
+
await sleep(charDelay);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async function animateSelectOption(question, options, selectedIdx) {
|
|
134
|
+
const baseHTML = html;
|
|
135
|
+
const cyclePath = [];
|
|
136
|
+
for (let i = 0; i <= selectedIdx; i++) {
|
|
137
|
+
cyclePath.push(i);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
for (let c = 0; c < cyclePath.length; c++) {
|
|
141
|
+
const idx = cyclePath[c];
|
|
142
|
+
let menuHtml = `<span class="bold white">${question}</span>\n`;
|
|
143
|
+
for (let i = 0; i < options.length; i++) {
|
|
144
|
+
if (i === idx) {
|
|
145
|
+
menuHtml += ` <span class="cyan bold">❯ ${options[i]}</span>\n`;
|
|
146
|
+
} else {
|
|
147
|
+
menuHtml += ` ${options[i]}\n`;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
setHTML(baseHTML + menuHtml);
|
|
151
|
+
await sleep(350);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
await sleep(200);
|
|
155
|
+
setHTML(baseHTML + `<span class="bold white">${question}</span> <span class="green">${options[selectedIdx]}</span>\n`);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async function animateTypeInput(question, defaultVal, answer) {
|
|
159
|
+
const prompt = `<span class="bold white">${question}</span> <span class="dim">(default: ${defaultVal})</span>: `;
|
|
160
|
+
appendHTML(prompt);
|
|
161
|
+
await sleep(400);
|
|
162
|
+
|
|
163
|
+
if (answer === defaultVal) {
|
|
164
|
+
appendHTML(`<span class="green">${answer}</span>\n`);
|
|
165
|
+
} else {
|
|
166
|
+
for (const ch of answer) {
|
|
167
|
+
appendHTML(ch);
|
|
168
|
+
await sleep(120);
|
|
169
|
+
}
|
|
170
|
+
await sleep(200);
|
|
171
|
+
appendHTML('\n');
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async function run() {
|
|
176
|
+
appendHTML('<span class="green bold">❯</span> ');
|
|
177
|
+
|
|
178
|
+
for (const step of steps) {
|
|
179
|
+
switch (step.type) {
|
|
180
|
+
case 'typeCommand':
|
|
181
|
+
await typeText(step.text, step.delay);
|
|
182
|
+
await sleep(500);
|
|
183
|
+
appendHTML('\n');
|
|
184
|
+
break;
|
|
185
|
+
case 'instant':
|
|
186
|
+
await sleep(step.delay);
|
|
187
|
+
appendHTML(step.text);
|
|
188
|
+
break;
|
|
189
|
+
case 'select':
|
|
190
|
+
await animateSelectOption(step.question, step.options, step.selected);
|
|
191
|
+
await sleep(step.delay);
|
|
192
|
+
break;
|
|
193
|
+
case 'typeInput':
|
|
194
|
+
await animateTypeInput(step.question, step.default, step.answer);
|
|
195
|
+
await sleep(step.delay);
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
await sleep(300);
|
|
201
|
+
appendHTML('\n<span class="green bold">❯</span> <span class="cursor"></span>');
|
|
202
|
+
|
|
203
|
+
// Wait then loop
|
|
204
|
+
await sleep(3000);
|
|
205
|
+
html = '';
|
|
206
|
+
output.innerHTML = '';
|
|
207
|
+
appendHTML('<span class="green bold">❯</span> ');
|
|
208
|
+
await run();
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
setTimeout(run, 800);
|
|
212
|
+
</script>
|
|
213
|
+
</body>
|
|
214
|
+
</html>
|
|
Binary file
|