react-native-varia 0.2.2 → 0.2.3
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/bin/cli.js +316 -129
- package/lib/components/Button.tsx +9 -7
- package/lib/components/CircleProgress.tsx +18 -9
- package/lib/components/Drawer.tsx +539 -0
- package/lib/components/NumberInput.tsx +34 -8
- package/lib/components/Slideshow.tsx +3 -6
- package/lib/components/SlidingDrawer.tsx +60 -16
- package/lib/icons/Minus.tsx +24 -0
- package/lib/icons/Plus.tsx +23 -0
- package/lib/theme/NumberInput.recipe.tsx +1 -1
- package/package.json +3 -2
- package/lib/components/NewSelect.tsx +0 -202
- package/lib/components/index.tsx +0 -83
- package/lib/components/layoutTest.tsx +0 -74
package/bin/cli.js
CHANGED
|
@@ -1,9 +1,41 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const { program } = require("commander");
|
|
4
|
+
const inquirer = require("inquirer");
|
|
4
5
|
const path = require("path");
|
|
5
6
|
const fs = require("fs-extra");
|
|
6
7
|
|
|
8
|
+
// 🔹 Dependencias entre componentes
|
|
9
|
+
const COMPONENT_DEPENDENCIES = {
|
|
10
|
+
Button: ["Spinner", "IconWrapper"],
|
|
11
|
+
Field: ["Text"],
|
|
12
|
+
Link: ["Text"],
|
|
13
|
+
Modal: ["Text"],
|
|
14
|
+
ReText: ["Text"],
|
|
15
|
+
Select: ["Text"],
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const ICON_DEPENDENCIES = {
|
|
19
|
+
NumberInput: ["Plus", "Minus"],
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Obtiene todas las dependencias de un componente de forma recursiva.
|
|
24
|
+
*/
|
|
25
|
+
function resolveDependencies(component, seen = new Set()) {
|
|
26
|
+
if (seen.has(component)) return [];
|
|
27
|
+
seen.add(component);
|
|
28
|
+
|
|
29
|
+
const deps = COMPONENT_DEPENDENCIES[component] || [];
|
|
30
|
+
let allDeps = [...deps];
|
|
31
|
+
|
|
32
|
+
for (const dep of deps) {
|
|
33
|
+
allDeps = [...allDeps, ...resolveDependencies(dep, seen)];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return [...new Set(allDeps)];
|
|
37
|
+
}
|
|
38
|
+
|
|
7
39
|
// Carpetas base
|
|
8
40
|
const COMPONENTS_DIR = path.join(__dirname, "../lib/components");
|
|
9
41
|
const THEME_DIR = path.join(__dirname, "../lib/theme");
|
|
@@ -19,14 +51,20 @@ function getAvailableComponents() {
|
|
|
19
51
|
/**
|
|
20
52
|
* Copia un archivo desde origen a destino.
|
|
21
53
|
*/
|
|
22
|
-
function copyFile(srcPath, destPath, label) {
|
|
54
|
+
function copyFile(srcPath, destPath, label, overwrite = true) {
|
|
23
55
|
if (!fs.existsSync(srcPath)) {
|
|
24
56
|
console.warn(`⚠️ ${label} no encontrado: ${srcPath}`);
|
|
25
57
|
return false;
|
|
26
58
|
}
|
|
27
59
|
try {
|
|
28
|
-
fs.ensureDirSync(path.dirname(destPath));
|
|
29
|
-
|
|
60
|
+
fs.ensureDirSync(path.dirname(destPath));
|
|
61
|
+
|
|
62
|
+
if (!overwrite && fs.existsSync(destPath)) {
|
|
63
|
+
console.log(`⏭️ Saltando ${label}, ya existe en ${destPath}`);
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
fs.copySync(srcPath, destPath, { overwrite: true });
|
|
30
68
|
console.log(`✅ ${label} copiado a: ${destPath}`);
|
|
31
69
|
return true;
|
|
32
70
|
} catch (err) {
|
|
@@ -38,14 +76,31 @@ function copyFile(srcPath, destPath, label) {
|
|
|
38
76
|
/**
|
|
39
77
|
* Copia un componente y su recipe.
|
|
40
78
|
*/
|
|
41
|
-
function copyComponentAndRecipe(component, destComponents, destTheme) {
|
|
79
|
+
function copyComponentAndRecipe(component, destComponents, destTheme, overwrite = true) {
|
|
42
80
|
const componentSrc = path.join(COMPONENTS_DIR, `${component}.tsx`);
|
|
43
81
|
const componentDest = path.join(process.cwd(), destComponents, `${component}.tsx`);
|
|
44
|
-
copyFile(componentSrc, componentDest, `Componente "${component}"
|
|
82
|
+
copyFile(componentSrc, componentDest, `Componente "${component}"`, overwrite);
|
|
45
83
|
|
|
46
84
|
const recipeSrc = path.join(THEME_DIR, `${component}.recipe.tsx`);
|
|
47
85
|
const recipeDest = path.join(process.cwd(), destTheme, `${component}.recipe.tsx`);
|
|
48
|
-
copyFile(recipeSrc, recipeDest, `Recipe de "${component}"
|
|
86
|
+
copyFile(recipeSrc, recipeDest, `Recipe de "${component}"`, overwrite);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Pregunta si se desea sobrescribir componentes existentes.
|
|
91
|
+
*/
|
|
92
|
+
async function confirmOverwrite(existingComponents) {
|
|
93
|
+
const { overwrite } = await inquirer.prompt([
|
|
94
|
+
{
|
|
95
|
+
type: "confirm",
|
|
96
|
+
name: "overwrite",
|
|
97
|
+
message: `Los siguientes componentes ya existen: ${existingComponents.join(
|
|
98
|
+
", "
|
|
99
|
+
)}\n¿Quieres sobrescribirlos?`,
|
|
100
|
+
default: false,
|
|
101
|
+
},
|
|
102
|
+
]);
|
|
103
|
+
return overwrite;
|
|
49
104
|
}
|
|
50
105
|
|
|
51
106
|
program
|
|
@@ -53,74 +108,145 @@ program
|
|
|
53
108
|
.description("CLI para instalar componentes de react-native-varia")
|
|
54
109
|
.version("1.0.0");
|
|
55
110
|
|
|
56
|
-
// program
|
|
57
|
-
// .command('setup')
|
|
58
|
-
// .description('Copia mixins y utils a src/styles')
|
|
59
|
-
// .action(() => {
|
|
60
|
-
// const sourceDir = path.join(__dirname, '../lib');
|
|
61
|
-
// const destDir = path.join(process.cwd(), 'src/style');
|
|
62
|
-
|
|
63
|
-
// const filesToCopy = ['mixins', 'utils', 'types'];
|
|
64
|
-
|
|
65
|
-
// filesToCopy.forEach((file) => {
|
|
66
|
-
// const srcPath = path.join(sourceDir, `${file}.ts`);
|
|
67
|
-
// const destPath = path.join(destDir, `${file}.ts`);
|
|
68
|
-
|
|
69
|
-
// try {
|
|
70
|
-
// fs.ensureDirSync(destDir); // Asegura que el directorio de destino exista
|
|
71
|
-
// fs.copySync(srcPath, destPath, { overwrite: true });
|
|
72
|
-
// console.log(`✅ ${file}.tsx copiado a ${destPath}`);
|
|
73
|
-
// } catch (err) {
|
|
74
|
-
// console.error(`❌ Error al copiar ${file}.tsx: ${err.message}`);
|
|
75
|
-
// }
|
|
76
|
-
// });
|
|
77
|
-
// });
|
|
78
|
-
|
|
79
111
|
program
|
|
80
|
-
.command(
|
|
81
|
-
.description(
|
|
112
|
+
.command("setup")
|
|
113
|
+
.description("Copia la carpeta varia y patterns al proyecto (src/style/varia y src/patterns)")
|
|
82
114
|
.action(() => {
|
|
83
|
-
const
|
|
84
|
-
const
|
|
85
|
-
|
|
115
|
+
const variaSrc = path.join(__dirname, "../lib/varia");
|
|
116
|
+
const variaDest = path.join(process.cwd(), "src/style/varia");
|
|
117
|
+
|
|
118
|
+
const patternsSrc = path.join(__dirname, "../lib/patterns");
|
|
119
|
+
const patternsDest = path.join(process.cwd(), "src/patterns");
|
|
86
120
|
|
|
87
121
|
try {
|
|
88
|
-
|
|
89
|
-
fs.
|
|
90
|
-
|
|
122
|
+
// Copiar varia
|
|
123
|
+
fs.ensureDirSync(path.dirname(variaDest));
|
|
124
|
+
fs.copySync(variaSrc, variaDest, { overwrite: true });
|
|
125
|
+
console.log(`✅ Carpeta "varia" copiada a ${variaDest}`);
|
|
126
|
+
|
|
127
|
+
// Copiar patterns
|
|
128
|
+
fs.ensureDirSync(path.dirname(patternsDest));
|
|
129
|
+
fs.copySync(patternsSrc, patternsDest, { overwrite: true });
|
|
130
|
+
console.log(`✅ Carpeta "patterns" copiada a ${patternsDest}`);
|
|
91
131
|
} catch (err) {
|
|
92
|
-
console.error(`❌ Error
|
|
132
|
+
console.error(`❌ Error durante el setup: ${err.message}`);
|
|
93
133
|
}
|
|
94
134
|
});
|
|
95
135
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
.
|
|
136
|
+
|
|
137
|
+
program
|
|
138
|
+
.command("add-patterns")
|
|
139
|
+
.description("Copia la carpeta lib/patterns a src/patterns")
|
|
99
140
|
.action(() => {
|
|
100
|
-
const sourceDir = path.join(__dirname,
|
|
101
|
-
const destDir = path.join(process.cwd(),
|
|
141
|
+
const sourceDir = path.join(__dirname, "../lib/patterns");
|
|
142
|
+
const destDir = path.join(process.cwd(), "src/patterns");
|
|
102
143
|
|
|
103
144
|
try {
|
|
104
|
-
fs.ensureDirSync(destDir);
|
|
145
|
+
fs.ensureDirSync(destDir);
|
|
105
146
|
fs.copySync(sourceDir, destDir, { overwrite: true });
|
|
106
|
-
console.log(
|
|
147
|
+
console.log("✅ Carpeta patterns copiada a src/patterns");
|
|
107
148
|
} catch (err) {
|
|
108
149
|
console.error(`❌ Error al copiar patterns: ${err.message}`);
|
|
109
150
|
}
|
|
110
151
|
});
|
|
111
152
|
|
|
153
|
+
// program
|
|
154
|
+
// .command("add <components...>")
|
|
155
|
+
// .description("Copia uno o más componentes y sus recipes desde la librería a tu proyecto")
|
|
156
|
+
// .option("-d, --dest <path>", "Ruta de destino de componentes", "src/components")
|
|
157
|
+
// .option("-t, --theme <path>", "Ruta de destino de recipes", "src/theme")
|
|
158
|
+
// .action(async (components, options) => {
|
|
159
|
+
// const available = getAvailableComponents();
|
|
160
|
+
// const componentsCapitalized = components.map(
|
|
161
|
+
// (c) => c.charAt(0).toUpperCase() + c.slice(1)
|
|
162
|
+
// );
|
|
163
|
+
|
|
164
|
+
// // 🔹 Obtener dependencias totales
|
|
165
|
+
// const allComponents = new Set();
|
|
166
|
+
// const componentToDeps = {}; // para saber qué depende de qué
|
|
167
|
+
// for (const c of componentsCapitalized) {
|
|
168
|
+
// const deps = resolveDependencies(c);
|
|
169
|
+
// componentToDeps[c] = deps;
|
|
170
|
+
// allComponents.add(c);
|
|
171
|
+
// deps.forEach((d) => allComponents.add(d));
|
|
172
|
+
// }
|
|
173
|
+
|
|
174
|
+
// const allComponentsArray = Array.from(allComponents);
|
|
175
|
+
|
|
176
|
+
// // 🔹 Validar existencia
|
|
177
|
+
// const notFound = allComponentsArray.filter((c) => !available.includes(c));
|
|
178
|
+
// if (notFound.length > 0) {
|
|
179
|
+
// console.error(`❌ Los siguientes componentes no existen: ${notFound.join(", ")}`);
|
|
180
|
+
// console.log("\n📦 Componentes disponibles:");
|
|
181
|
+
// available.forEach((name) => console.log(` - ${name}`));
|
|
182
|
+
// process.exit(1);
|
|
183
|
+
// }
|
|
184
|
+
|
|
185
|
+
// // 🔹 Preparar instalación
|
|
186
|
+
// for (const mainComponent of componentsCapitalized) {
|
|
187
|
+
// const componentPath = path.join(process.cwd(), options.dest, `${mainComponent}.tsx`);
|
|
188
|
+
// let overwriteMain = true;
|
|
189
|
+
|
|
190
|
+
// // Preguntar solo si el componente principal existe
|
|
191
|
+
// if (fs.existsSync(componentPath)) {
|
|
192
|
+
// const { overwrite } = await inquirer.prompt([
|
|
193
|
+
// {
|
|
194
|
+
// type: "confirm",
|
|
195
|
+
// name: "overwrite",
|
|
196
|
+
// message: `El componente "${mainComponent}" ya existe. ¿Deseas sobrescribirlo?`,
|
|
197
|
+
// default: false,
|
|
198
|
+
// },
|
|
199
|
+
// ]);
|
|
200
|
+
|
|
201
|
+
// overwriteMain = overwrite;
|
|
202
|
+
// if (!overwriteMain) {
|
|
203
|
+
// console.log(`⏭️ Componente "${mainComponent}" no sobrescrito.`);
|
|
204
|
+
// }
|
|
205
|
+
// }
|
|
206
|
+
|
|
207
|
+
// // 🔹 Copiar componente principal
|
|
208
|
+
// copyComponentAndRecipe(mainComponent, options.dest, options.theme, overwriteMain);
|
|
209
|
+
|
|
210
|
+
// // 🔹 Copiar dependencias (sin sobrescribir si existen)
|
|
211
|
+
// const deps = componentToDeps[mainComponent] || [];
|
|
212
|
+
// for (const dep of deps) {
|
|
213
|
+
// const depPath = path.join(process.cwd(), options.dest, `${dep}.tsx`);
|
|
214
|
+
// const exists = fs.existsSync(depPath);
|
|
215
|
+
// if (exists) {
|
|
216
|
+
// console.log(`⏭️ Dependencia "${dep}" ya existe. No se sobrescribe.`);
|
|
217
|
+
// continue;
|
|
218
|
+
// }
|
|
219
|
+
// copyComponentAndRecipe(dep, options.dest, options.theme, true);
|
|
220
|
+
// }
|
|
221
|
+
// }
|
|
222
|
+
// });
|
|
223
|
+
|
|
112
224
|
program
|
|
113
225
|
.command("add <components...>")
|
|
114
226
|
.description("Copia uno o más componentes y sus recipes desde la librería a tu proyecto")
|
|
115
227
|
.option("-d, --dest <path>", "Ruta de destino de componentes", "src/components")
|
|
116
228
|
.option("-t, --theme <path>", "Ruta de destino de recipes", "src/theme")
|
|
117
|
-
.
|
|
229
|
+
.option("-i, --icons <path>", "Ruta de destino de íconos", "src/icons")
|
|
230
|
+
.action(async (components, options) => {
|
|
118
231
|
const available = getAvailableComponents();
|
|
119
232
|
const componentsCapitalized = components.map(
|
|
120
233
|
(c) => c.charAt(0).toUpperCase() + c.slice(1)
|
|
121
234
|
);
|
|
122
235
|
|
|
123
|
-
|
|
236
|
+
// 🔹 Obtener dependencias totales
|
|
237
|
+
const allComponents = new Set();
|
|
238
|
+
const componentToDeps = {}; // para saber qué depende de qué
|
|
239
|
+
for (const c of componentsCapitalized) {
|
|
240
|
+
const deps = resolveDependencies(c);
|
|
241
|
+
componentToDeps[c] = deps;
|
|
242
|
+
allComponents.add(c);
|
|
243
|
+
deps.forEach((d) => allComponents.add(d));
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const allComponentsArray = Array.from(allComponents);
|
|
247
|
+
|
|
248
|
+
// 🔹 Validar existencia
|
|
249
|
+
const notFound = allComponentsArray.filter((c) => !available.includes(c));
|
|
124
250
|
if (notFound.length > 0) {
|
|
125
251
|
console.error(`❌ Los siguientes componentes no existen: ${notFound.join(", ")}`);
|
|
126
252
|
console.log("\n📦 Componentes disponibles:");
|
|
@@ -128,90 +254,151 @@ program
|
|
|
128
254
|
process.exit(1);
|
|
129
255
|
}
|
|
130
256
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
257
|
+
// 🔹 Preparar instalación
|
|
258
|
+
for (const mainComponent of componentsCapitalized) {
|
|
259
|
+
const componentPath = path.join(process.cwd(), options.dest, `${mainComponent}.tsx`);
|
|
260
|
+
let overwriteMain = true;
|
|
135
261
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
262
|
+
// Preguntar solo si el componente principal existe
|
|
263
|
+
if (fs.existsSync(componentPath)) {
|
|
264
|
+
const { overwrite } = await inquirer.prompt([
|
|
265
|
+
{
|
|
266
|
+
type: "confirm",
|
|
267
|
+
name: "overwrite",
|
|
268
|
+
message: `El componente "${mainComponent}" ya existe. ¿Deseas sobrescribirlo?`,
|
|
269
|
+
default: false,
|
|
270
|
+
},
|
|
271
|
+
]);
|
|
272
|
+
|
|
273
|
+
overwriteMain = overwrite;
|
|
274
|
+
if (!overwriteMain) {
|
|
275
|
+
console.log(`⏭️ Componente "${mainComponent}" no sobrescrito.`);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// 🔹 Copiar componente principal
|
|
280
|
+
copyComponentAndRecipe(mainComponent, options.dest, options.theme, overwriteMain);
|
|
281
|
+
|
|
282
|
+
// 🔹 Copiar dependencias (sin sobrescribir si existen)
|
|
283
|
+
const deps = componentToDeps[mainComponent] || [];
|
|
284
|
+
for (const dep of deps) {
|
|
285
|
+
const depPath = path.join(process.cwd(), options.dest, `${dep}.tsx`);
|
|
286
|
+
const exists = fs.existsSync(depPath);
|
|
287
|
+
if (exists) {
|
|
288
|
+
console.log(`⏭️ Dependencia "${dep}" ya existe. No se sobrescribe.`);
|
|
289
|
+
continue;
|
|
290
|
+
}
|
|
291
|
+
copyComponentAndRecipe(dep, options.dest, options.theme, true);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// 🔹 Copiar íconos dependientes
|
|
295
|
+
const iconDeps = ICON_DEPENDENCIES[mainComponent] || [];
|
|
296
|
+
if (iconDeps.length > 0) {
|
|
297
|
+
console.log(`🎨 Añadiendo íconos requeridos por "${mainComponent}": ${iconDeps.join(", ")}`);
|
|
298
|
+
|
|
299
|
+
for (const iconName of iconDeps) {
|
|
300
|
+
const destIconPath = path.join(process.cwd(), options.icons, `${iconName}.tsx`);
|
|
301
|
+
if (fs.existsSync(destIconPath)) {
|
|
302
|
+
console.log(`⏭️ Icono "${iconName}" ya existe. No se sobrescribe.`);
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
copyIconTemplate(iconName, options.icons);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// Asegurar que IconWrapper esté disponible
|
|
309
|
+
ensureIconWrapper(options.dest, options.theme);
|
|
310
|
+
}
|
|
161
311
|
}
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
function copyIconTemplate(iconName, dest) {
|
|
316
|
+
const srcPath = path.join(COMPONENTS_DIR, "Icon.tsx");
|
|
317
|
+
const destPath = path.join(process.cwd(), dest, `${iconName}.tsx`);
|
|
318
|
+
|
|
319
|
+
if (!fs.existsSync(srcPath)) {
|
|
320
|
+
console.error(`❌ Plantilla de icono no encontrada en: ${srcPath}`);
|
|
321
|
+
return false;
|
|
162
322
|
}
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
323
|
+
|
|
324
|
+
try {
|
|
325
|
+
let content = fs.readFileSync(srcPath, "utf-8");
|
|
326
|
+
content = content.replace(/\bIconName\b/g, iconName);
|
|
327
|
+
|
|
328
|
+
fs.ensureDirSync(path.dirname(destPath));
|
|
329
|
+
fs.writeFileSync(destPath, content);
|
|
330
|
+
|
|
331
|
+
console.log(`✅ Icono "${iconName}" copiado a: ${destPath}`);
|
|
332
|
+
return true;
|
|
333
|
+
} catch (err) {
|
|
334
|
+
console.error(`❌ No se pudo copiar el icono "${iconName}": ${err.message}`);
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Copia IconWrapper si no existe en la app
|
|
341
|
+
*/
|
|
342
|
+
function ensureIconWrapper(destComponents, destTheme) {
|
|
343
|
+
const wrapperComponentDest = path.join(process.cwd(), destComponents, "IconWrapper.tsx");
|
|
344
|
+
const wrapperRecipeDest = path.join(process.cwd(), destTheme, "IconWrapper.recipe.tsx");
|
|
345
|
+
|
|
346
|
+
if (fs.existsSync(wrapperComponentDest)) {
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
const wrapperComponentSrc = path.join(COMPONENTS_DIR, "IconWrapper.tsx");
|
|
351
|
+
const wrapperRecipeSrc = path.join(THEME_DIR, "IconWrapper.recipe.tsx");
|
|
352
|
+
|
|
353
|
+
if (fs.existsSync(wrapperComponentSrc)) {
|
|
354
|
+
fs.ensureDirSync(path.dirname(wrapperComponentDest));
|
|
355
|
+
fs.copySync(wrapperComponentSrc, wrapperComponentDest, { overwrite: true });
|
|
356
|
+
console.log(`✅ IconWrapper copiado a: ${wrapperComponentDest}`);
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
if (fs.existsSync(wrapperRecipeSrc)) {
|
|
360
|
+
fs.ensureDirSync(path.dirname(wrapperRecipeDest));
|
|
361
|
+
fs.copySync(wrapperRecipeSrc, wrapperRecipeDest, { overwrite: true });
|
|
362
|
+
console.log(`✅ IconWrapper recipe copiado a: ${wrapperRecipeDest}`);
|
|
190
363
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Comando CLI: add-icon
|
|
367
|
+
program
|
|
368
|
+
.command("add-icon [iconName]")
|
|
369
|
+
.description("Copia un icono basado en la plantilla Icon.tsx")
|
|
370
|
+
.option("-n, --name <iconName>", "Nombre del icono")
|
|
371
|
+
.option("-d, --dest <path>", "Ruta de destino de iconos", "src/icons")
|
|
372
|
+
.option("-c, --components <path>", "Ruta de destino de componentes", "src/components")
|
|
373
|
+
.option("-t, --theme <path>", "Ruta de destino de recipes", "src/theme")
|
|
374
|
+
.action(async (iconNameArg, options) => {
|
|
375
|
+
const rawName = iconNameArg || options.name;
|
|
376
|
+
if (!rawName) {
|
|
377
|
+
console.error("❌ Debes indicar el nombre del icono como argumento o con --name");
|
|
378
|
+
process.exit(1);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const finalName = rawName.charAt(0).toUpperCase() + rawName.slice(1);
|
|
382
|
+
const destPath = path.join(process.cwd(), options.dest, `${finalName}.tsx`);
|
|
383
|
+
|
|
384
|
+
// 🔹 Si ya existe, preguntar antes de sobrescribir
|
|
385
|
+
if (fs.existsSync(destPath)) {
|
|
386
|
+
const { overwrite } = await inquirer.prompt([
|
|
387
|
+
{
|
|
388
|
+
type: "confirm",
|
|
389
|
+
name: "overwrite",
|
|
390
|
+
message: `El icono "${finalName}" ya existe. ¿Quieres sobrescribirlo?`,
|
|
391
|
+
default: false,
|
|
392
|
+
},
|
|
393
|
+
]);
|
|
394
|
+
if (!overwrite) {
|
|
395
|
+
console.log("⏭️ Icono no sobrescrito.");
|
|
396
|
+
return;
|
|
205
397
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
ensureIconWrapper(options.components, options.theme);
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
program.parse(process.argv);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
copyIconTemplate(finalName, options.dest);
|
|
401
|
+
ensureIconWrapper(options.components, options.theme);
|
|
402
|
+
});
|
|
403
|
+
|
|
404
|
+
program.parse(process.argv);
|
|
@@ -12,7 +12,7 @@ type ButtonVariants = UnistylesVariants<typeof ButtonStyles>
|
|
|
12
12
|
|
|
13
13
|
type ButtonProps = ButtonVariants & {
|
|
14
14
|
colorPalette?: PalettesWithNestedKeys
|
|
15
|
-
text
|
|
15
|
+
text?: string
|
|
16
16
|
onPress: () => void
|
|
17
17
|
loading?: boolean
|
|
18
18
|
disabled?: boolean
|
|
@@ -21,7 +21,7 @@ type ButtonProps = ButtonVariants & {
|
|
|
21
21
|
textAdjustment?: TextAdjustment
|
|
22
22
|
icon?: {
|
|
23
23
|
component: React.ComponentType<IconWrapperProps>
|
|
24
|
-
position
|
|
24
|
+
position?: 'left' | 'right'
|
|
25
25
|
scale?: number
|
|
26
26
|
rotation?: number
|
|
27
27
|
size?: number
|
|
@@ -98,11 +98,13 @@ const Button = ({
|
|
|
98
98
|
) : (
|
|
99
99
|
<>
|
|
100
100
|
{icon?.position === 'left' && IconRendered}
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
101
|
+
{text && (
|
|
102
|
+
<Text
|
|
103
|
+
{...getTextProps()}
|
|
104
|
+
style={[styles.text, ButtonStyles.text(colorPalette)]}>
|
|
105
|
+
{text}
|
|
106
|
+
</Text>
|
|
107
|
+
)}
|
|
106
108
|
{icon?.position === 'right' && IconRendered}
|
|
107
109
|
</>
|
|
108
110
|
)}
|
|
@@ -13,6 +13,7 @@ import {circleProgressTokens} from '../theme/CircleProgress.recipe'
|
|
|
13
13
|
import {withUnistyles} from 'react-native-unistyles'
|
|
14
14
|
import {resolveColor} from '../style/varia/utils'
|
|
15
15
|
import {PalettesWithNestedKeys} from '../style/varia/types'
|
|
16
|
+
import {SharedValue} from 'react-native-reanimated'
|
|
16
17
|
|
|
17
18
|
const AnimatedCircle = Animated.createAnimatedComponent(Circle)
|
|
18
19
|
const svgSize = 160
|
|
@@ -21,6 +22,8 @@ interface CircleProgressProps {
|
|
|
21
22
|
variant?: keyof typeof circleProgressTokens.variants.variant
|
|
22
23
|
size?: keyof typeof circleProgressTokens.variants.size
|
|
23
24
|
trackStrokeWidth?: number
|
|
25
|
+
progress: SharedValue<number> // ✅ Nuevo
|
|
26
|
+
|
|
24
27
|
progressStrokeWidth?: number
|
|
25
28
|
duration: number
|
|
26
29
|
trackColor?: string
|
|
@@ -37,6 +40,7 @@ const BaseCircleProgress = ({
|
|
|
37
40
|
variant = circleProgressTokens.defaultProps.variant,
|
|
38
41
|
size = circleProgressTokens.defaultProps.size,
|
|
39
42
|
trackStrokeWidth,
|
|
43
|
+
progress,
|
|
40
44
|
progressStrokeWidth,
|
|
41
45
|
duration,
|
|
42
46
|
trackColor,
|
|
@@ -69,21 +73,26 @@ const BaseCircleProgress = ({
|
|
|
69
73
|
|
|
70
74
|
const center = svgSize! / 2
|
|
71
75
|
|
|
72
|
-
const
|
|
76
|
+
const internalProgress = useSharedValue(0)
|
|
73
77
|
|
|
74
78
|
useEffect(() => {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
79
|
+
if (!progress) {
|
|
80
|
+
internalProgress.value = 0
|
|
81
|
+
internalProgress.value = withTiming(1, {
|
|
82
|
+
duration: duration,
|
|
83
|
+
easing: Easing.linear,
|
|
84
|
+
})
|
|
85
|
+
}
|
|
86
|
+
}, [progress, duration])
|
|
87
|
+
|
|
88
|
+
const progressValue = progress || internalProgress
|
|
80
89
|
|
|
81
90
|
const animatedProps = useAnimatedProps(() => {
|
|
82
91
|
const rStrokeDashOffset = interpolate(
|
|
83
|
-
|
|
92
|
+
progressValue.value,
|
|
84
93
|
[
|
|
85
|
-
progressDirection === 'forward' ?
|
|
86
|
-
progressDirection === 'forward' ?
|
|
94
|
+
progressDirection === 'forward' ? 0 : 1,
|
|
95
|
+
progressDirection === 'forward' ? 1 : 0,
|
|
87
96
|
],
|
|
88
97
|
[circumference, 0],
|
|
89
98
|
Extrapolation.CLAMP,
|