@mimi-ng/cli 0.1.1 → 0.3.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 (104) hide show
  1. package/README.md +28 -1
  2. package/dist/init/css.js +17 -0
  3. package/dist/init/index.js +7 -5
  4. package/dist/init/items.js +9 -0
  5. package/dist/registry.json +482 -1
  6. package/dist/templates/components/avatar/avatar.ts +1 -1
  7. package/dist/templates/components/avatar/avatar.variants.ts +4 -4
  8. package/dist/templates/components/badge/badge.ts +41 -6
  9. package/dist/templates/components/badge/badge.variants.ts +105 -11
  10. package/dist/templates/components/button/button.ts +74 -7
  11. package/dist/templates/components/button/button.variants.ts +145 -21
  12. package/dist/templates/components/calendar/calendar-texts.ts +72 -0
  13. package/dist/templates/components/calendar/calendar.ts +588 -0
  14. package/dist/templates/components/calendar/dates.ts +181 -0
  15. package/dist/templates/components/calendar/index.ts +3 -0
  16. package/dist/templates/components/card/card.ts +8 -5
  17. package/dist/templates/components/checkbox/checkbox.ts +3 -3
  18. package/dist/templates/components/chip/chip-texts.ts +40 -0
  19. package/dist/templates/components/chip/chip.ts +116 -0
  20. package/dist/templates/components/chip/index.ts +2 -0
  21. package/dist/templates/components/color-picker/color-picker-texts.ts +57 -0
  22. package/dist/templates/components/color-picker/color-picker.ts +718 -0
  23. package/dist/templates/components/color-picker/color.ts +157 -0
  24. package/dist/templates/components/color-picker/index.ts +3 -0
  25. package/dist/templates/components/combobox/combobox-texts.ts +70 -0
  26. package/dist/templates/components/combobox/combobox.ts +798 -0
  27. package/dist/templates/components/combobox/index.ts +2 -0
  28. package/dist/templates/components/confirm/confirm-texts.ts +46 -0
  29. package/dist/templates/components/confirm/confirm.ts +190 -0
  30. package/dist/templates/components/confirm/index.ts +2 -0
  31. package/dist/templates/components/context-menu/context-menu.ts +378 -0
  32. package/dist/templates/components/context-menu/index.ts +14 -0
  33. package/dist/templates/components/date-picker/date-picker.ts +240 -0
  34. package/dist/templates/components/date-picker/index.ts +3 -0
  35. package/dist/templates/components/date-range/date-range.ts +308 -0
  36. package/dist/templates/components/date-range/index.ts +1 -0
  37. package/dist/templates/components/dialog/dialog-texts.ts +41 -0
  38. package/dist/templates/components/dialog/dialog.ts +701 -0
  39. package/dist/templates/components/dialog/index.ts +18 -0
  40. package/dist/templates/components/dropdown-menu/dropdown-menu.ts +252 -0
  41. package/dist/templates/components/dropdown-menu/index.ts +14 -0
  42. package/dist/templates/components/file-upload/file-upload-texts.ts +77 -0
  43. package/dist/templates/components/file-upload/file-upload.ts +698 -0
  44. package/dist/templates/components/file-upload/index.ts +2 -0
  45. package/dist/templates/components/form-field/form-error.ts +1 -1
  46. package/dist/templates/components/form-field/form-field.ts +3 -2
  47. package/dist/templates/components/input/input.variants.ts +6 -4
  48. package/dist/templates/components/input-mask/index.ts +1 -0
  49. package/dist/templates/components/input-mask/input-mask.ts +319 -0
  50. package/dist/templates/components/input-otp/index.ts +1 -0
  51. package/dist/templates/components/input-otp/input-otp.ts +212 -0
  52. package/dist/templates/components/menu/index.ts +15 -0
  53. package/dist/templates/components/menu/menu.ts +656 -0
  54. package/dist/templates/components/number-input/index.ts +2 -0
  55. package/dist/templates/components/number-input/number-input-texts.ts +46 -0
  56. package/dist/templates/components/number-input/number-input.ts +450 -0
  57. package/dist/templates/components/option-list/index.ts +11 -0
  58. package/dist/templates/components/option-list/option-list.ts +518 -0
  59. package/dist/templates/components/pagination/index.ts +2 -0
  60. package/dist/templates/components/pagination/pagination-page-size.ts +74 -0
  61. package/dist/templates/components/pagination/pagination-texts.ts +69 -0
  62. package/dist/templates/components/pagination/pagination.ts +443 -0
  63. package/dist/templates/components/password/index.ts +2 -0
  64. package/dist/templates/components/password/password-texts.ts +68 -0
  65. package/dist/templates/components/password/password.ts +363 -0
  66. package/dist/templates/components/popover/index.ts +12 -0
  67. package/dist/templates/components/popover/popover.ts +407 -0
  68. package/dist/templates/components/progress/index.ts +1 -0
  69. package/dist/templates/components/progress/progress.ts +217 -0
  70. package/dist/templates/components/select/index.ts +12 -0
  71. package/dist/templates/components/select/select-texts.ts +62 -0
  72. package/dist/templates/components/select/select.ts +1086 -0
  73. package/dist/templates/components/separator/separator.variants.ts +10 -7
  74. package/dist/templates/components/skeleton/skeleton.ts +4 -1
  75. package/dist/templates/components/slider/index.ts +2 -0
  76. package/dist/templates/components/slider/slider-texts.ts +26 -0
  77. package/dist/templates/components/slider/slider.ts +425 -0
  78. package/dist/templates/components/switch/switch.ts +6 -6
  79. package/dist/templates/components/tabs/index.ts +2 -0
  80. package/dist/templates/components/tabs/tabs.ts +426 -0
  81. package/dist/templates/components/tags-input/index.ts +2 -0
  82. package/dist/templates/components/tags-input/tags-input-texts.ts +44 -0
  83. package/dist/templates/components/tags-input/tags-input.ts +303 -0
  84. package/dist/templates/components/textarea/textarea.variants.ts +14 -11
  85. package/dist/templates/components/toast/index.ts +3 -0
  86. package/dist/templates/components/toast/toast-config.ts +45 -0
  87. package/dist/templates/components/toast/toast-texts.ts +46 -0
  88. package/dist/templates/components/toast/toast.ts +1000 -0
  89. package/dist/templates/components/toggle-group/index.ts +1 -0
  90. package/dist/templates/components/toggle-group/toggle-group.ts +406 -0
  91. package/dist/templates/components/toolbar/index.ts +1 -0
  92. package/dist/templates/components/toolbar/toolbar.ts +377 -0
  93. package/dist/templates/components/tooltip/index.ts +7 -0
  94. package/dist/templates/components/tooltip/tooltip.ts +407 -0
  95. package/dist/templates/theme/provider.ts +75 -6
  96. package/dist/templates/theme/theme-base.css +410 -9
  97. package/dist/templates/theme/types.ts +494 -4
  98. package/dist/templates/utils/cn.ts +15 -1
  99. package/dist/templates/utils/control-styles.ts +2 -2
  100. package/dist/templates/utils/overlay.ts +153 -0
  101. package/dist/ui/index.js +184 -8
  102. package/dist/ui/schema.json +100 -0
  103. package/dist/utils/write-files.js +166 -59
  104. package/package.json +1 -1
@@ -4,9 +4,11 @@ exports.hasFileChanges = exports.emptyReport = exports.MANIFEST = exports.BASE_D
4
4
  exports.projectPathOf = projectPathOf;
5
5
  exports.basePathOf = basePathOf;
6
6
  exports.writeTemplates = writeTemplates;
7
+ exports.blockedMessages = blockedMessages;
7
8
  exports.compareVersions = compareVersions;
8
9
  exports.updatedMessages = updatedMessages;
9
10
  const schematics_1 = require("@angular-devkit/schematics");
11
+ const registry_1 = require("../registry");
10
12
  /** Carpeta de las copias originales, en la raíz del workspace. Debe quedar en git. */
11
13
  exports.BASE_DIR = '.mimi/base';
12
14
  /** Versión de Mimi con la que se escribió la base de cada archivo. */
@@ -17,6 +19,7 @@ const emptyReport = () => ({
17
19
  updated: [],
18
20
  unchanged: [],
19
21
  skipped: [],
22
+ blocked: [],
20
23
  });
21
24
  exports.emptyReport = emptyReport;
22
25
  /** ¿El reporte tiene cambios en archivos del proyecto? */
@@ -47,26 +50,98 @@ function readManifest(tree) {
47
50
  }
48
51
  }
49
52
  /**
50
- * Copia archivos de las plantillas del paquete (`dist/templates`, rutas relativas a esa
51
- * carpeta) a `componentsDir`, revisando el árbol antes de escribir. Si el archivo ya existe:
53
+ * Copia los archivos de los ítems del registro desde las plantillas del paquete
54
+ * (`dist/templates`) a `componentsDir`. **Todo o nada por ítem:** primero revisa cada archivo
55
+ * (ver `FileState`) y después decide por ítem:
52
56
  *
53
- * - igual a la plantilla → al día;
54
- * - igual a su base en `.mimi/base/` → el usuario no lo tocó. Si la base es de esta versión,
55
- * la diferencia con la plantilla es solo de formato (la CLI de Angular pasa el Prettier del
56
- * proyecto por lo que escriben los schematics): al día. Si es de una versión anterior, se
57
- * actualiza;
58
- * - distinto de su base, o sin base → modificado por el usuario: se omite (o se reemplaza con
59
- * `overwrite`).
57
+ * - si el usuario modificó alguno de sus archivos de una versión anterior, no se escribe
58
+ * ninguno (ni los nuevos ni los que no tocó): mezclar versiones rompe la compilación;
59
+ * - lo mismo si depende (por `registryDependencies`, en cualquier nivel) de un ítem que quedó
60
+ * así, esté instalado o no;
61
+ * - si no, se crean los que faltan y se actualizan los que el usuario no tocó. Los modificados
62
+ * sobre esta versión se conservan (`skipped`).
60
63
  *
61
- * Nunca deja que mergeWith encuentre un archivo existente ("merge conflicted"). Guarda la base
62
- * y su versión en `.mimi/manifest.json` siempre que el archivo quede igual a la plantilla; si se
63
- * omitió por estar modificado, su base no cambia.
64
+ * Con `overwrite`, todo se reemplaza y nada se bloquea, también un archivo igual a su base de la
65
+ * misma versión (`formatted`; M.11). Los ítems `implicit` (el tema y lo que
66
+ * copia init, que `ng g mimi` revisa aunque no se pidan) solo se escriben si hay que
67
+ * actualizarlos: un cambio del usuario sobre la versión actual se respeta en silencio, también
68
+ * con `overwrite`, y no bloquean a otros ítems.
69
+ *
70
+ * Nunca deja que mergeWith encuentre un archivo existente ("merge conflicted"). Guarda la base y
71
+ * su versión en `.mimi/manifest.json` siempre que el archivo quede igual a la plantilla; los de un
72
+ * ítem bloqueado o conservado no cambian su base.
64
73
  */
65
74
  function writeTemplates(options) {
66
- const files = new Set(options.files);
67
- return (tree) => {
75
+ const items = [...new Set(options.items)];
76
+ const implicit = new Set(options.implicit ?? []);
77
+ const files = new Set(items.flatMap((item) => registry_1.registry.items[item].files));
78
+ const contents = new Map();
79
+ // 1. Lee las plantillas (sin escribir nada: forEach devuelve null).
80
+ const read = (0, schematics_1.mergeWith)((0, schematics_1.apply)((0, schematics_1.url)('../templates'), [
81
+ (0, schematics_1.filter)((path) => files.has(path.replace(/^\//, ''))),
82
+ (0, schematics_1.forEach)((entry) => {
83
+ contents.set(entry.path.replace(/^\//, ''), entry.content.toString('utf8'));
84
+ return null;
85
+ }),
86
+ ]));
87
+ // 2. Decide por ítem y escribe.
88
+ const write = (tree) => {
68
89
  const manifest = readManifest(tree);
69
90
  let manifestChanged = false;
91
+ const targetOf = (file) => `${options.componentsDir}/${projectPathOf(file)}`;
92
+ const stateOf = (file) => {
93
+ const target = targetOf(file);
94
+ if (!tree.exists(target))
95
+ return { state: 'new', from: null };
96
+ const current = tree.readText(target);
97
+ if (current === contents.get(file))
98
+ return { state: 'same', from: null };
99
+ const from = manifest.files[projectPathOf(file)] ?? null;
100
+ const base = basePathOf(file);
101
+ if (tree.exists(base)) {
102
+ if (tree.readText(base) === current) {
103
+ return { state: from === options.version ? 'formatted' : 'old', from };
104
+ }
105
+ if (from !== null && from !== options.version)
106
+ return { state: 'modifiedOld', from };
107
+ }
108
+ return { state: 'modified', from };
109
+ };
110
+ const states = new Map(items.map((item) => [
111
+ item,
112
+ registry_1.registry.items[item].files
113
+ .filter((file) => contents.has(file))
114
+ .map((file) => ({ file, ...stateOf(file) })),
115
+ ]));
116
+ // Bloqueados por un cambio propio y, después, por una dependencia bloqueada.
117
+ const blocked = new Map();
118
+ if (!options.overwrite) {
119
+ for (const item of items) {
120
+ const modified = states.get(item).filter((s) => s.state === 'modifiedOld');
121
+ if (modified.length > 0) {
122
+ blocked.set(item, {
123
+ item,
124
+ files: modified.map((s) => s.file),
125
+ installed: true,
126
+ });
127
+ }
128
+ }
129
+ for (const item of items) {
130
+ if (blocked.has(item))
131
+ continue;
132
+ const dependency = (0, registry_1.resolveItems)(item)
133
+ .filter((dep) => dep !== item)
134
+ .find((dep) => blocked.has(dep) && blocked.get(dep).files.length > 0);
135
+ if (dependency) {
136
+ blocked.set(item, {
137
+ item,
138
+ files: [],
139
+ dependency,
140
+ installed: states.get(item).some((s) => s.state !== 'new'),
141
+ });
142
+ }
143
+ }
144
+ }
70
145
  const writeBase = (file, content) => {
71
146
  const base = basePathOf(file);
72
147
  if (!tree.exists(base))
@@ -79,60 +154,92 @@ function writeTemplates(options) {
79
154
  manifestChanged = true;
80
155
  }
81
156
  };
82
- const copy = (0, schematics_1.mergeWith)((0, schematics_1.apply)((0, schematics_1.url)('../templates'), [
83
- (0, schematics_1.filter)((path) => files.has(path.replace(/^\//, ''))),
84
- (0, schematics_1.forEach)((entry) => {
85
- const file = entry.path.replace(/^\//, '');
86
- const target = `${options.componentsDir}/${projectPathOf(file)}`;
87
- const base = basePathOf(file);
88
- const content = entry.content.toString('utf8');
89
- if (!tree.exists(target)) {
90
- tree.create(target, content);
91
- options.report.created.push(file);
92
- writeBase(file, content);
93
- return null;
94
- }
95
- const current = tree.readText(target);
96
- if (current === content) {
97
- options.report.unchanged.push(file);
98
- writeBase(file, content);
99
- }
100
- else if (tree.exists(base) && tree.readText(base) === current) {
101
- const from = manifest.files[projectPathOf(file)] ?? null;
102
- if (from === options.version) {
103
- // Mismo contenido que escribió Mimi, solo con otro formato.
157
+ for (const item of items) {
158
+ if (blocked.has(item)) {
159
+ options.report.blocked.push(blocked.get(item));
160
+ continue;
161
+ }
162
+ for (const { file, state, from } of states.get(item)) {
163
+ const content = contents.get(file);
164
+ const target = targetOf(file);
165
+ switch (state) {
166
+ case 'new':
167
+ tree.create(target, content);
168
+ options.report.created.push(file);
169
+ writeBase(file, content);
170
+ break;
171
+ case 'same':
104
172
  options.report.unchanged.push(file);
105
- }
106
- else {
173
+ writeBase(file, content);
174
+ break;
175
+ case 'formatted':
176
+ // Con --overwrite se reemplaza siempre, también con la misma versión (M.11): sin él,
177
+ // un archivo distinto de la plantilla con la misma versión no se podía reponer.
178
+ if (options.overwrite && !implicit.has(item)) {
179
+ tree.overwrite(target, content);
180
+ options.report.overwritten.push(file);
181
+ writeBase(file, content);
182
+ }
183
+ else {
184
+ options.report.unchanged.push(file);
185
+ }
186
+ break;
187
+ case 'old':
107
188
  tree.overwrite(target, content);
108
189
  options.report.updated.push({ file, from });
109
190
  writeBase(file, content);
110
- }
191
+ break;
192
+ case 'modifiedOld':
193
+ case 'modified':
194
+ // Un cambio sobre la versión actual de un ítem implícito se respeta siempre.
195
+ if (options.overwrite && !(implicit.has(item) && state === 'modified')) {
196
+ tree.overwrite(target, content);
197
+ options.report.overwritten.push(file);
198
+ writeBase(file, content);
199
+ }
200
+ else if (!implicit.has(item)) {
201
+ options.report.skipped.push(file);
202
+ }
203
+ break;
111
204
  }
112
- else if (options.overwrite) {
113
- tree.overwrite(target, content);
114
- options.report.overwritten.push(file);
115
- writeBase(file, content);
116
- }
117
- else {
118
- options.report.skipped.push(file);
119
- }
120
- // Todo se escribe arriba, en el árbol del proyecto: nada llega a mergeWith.
121
- return null;
122
- }),
123
- ]));
124
- const saveManifest = (t) => {
125
- if (!manifestChanged)
126
- return;
205
+ }
206
+ }
207
+ if (manifestChanged) {
127
208
  const sorted = Object.fromEntries(Object.entries(manifest.files).sort());
128
209
  const text = `${JSON.stringify({ files: sorted }, null, 2)}\n`;
129
- if (t.exists(exports.MANIFEST))
130
- t.overwrite(exports.MANIFEST, text);
210
+ if (tree.exists(exports.MANIFEST))
211
+ tree.overwrite(exports.MANIFEST, text);
131
212
  else
132
- t.create(exports.MANIFEST, text);
133
- };
134
- return (0, schematics_1.chain)([copy, saveManifest]);
213
+ tree.create(exports.MANIFEST, text);
214
+ }
135
215
  };
216
+ return (0, schematics_1.chain)([read, write]);
217
+ }
218
+ /**
219
+ * Los avisos de los ítems que no se escribieron (`report.blocked`): qué no se actualizó, por qué
220
+ * y qué hacer. Nunca dicen «actualizado».
221
+ */
222
+ function blockedMessages(report, componentsDir, version) {
223
+ const path = (file) => `${componentsDir}/${projectPathOf(file)}`;
224
+ return report.blocked.map(({ item, files, dependency, installed }) => {
225
+ if (dependency) {
226
+ const needs = `necesita ${dependency} ${version}, que no se actualizó (ver el aviso de ${dependency}).`;
227
+ return installed
228
+ ? `${item} no se actualizó a ${version}: ${needs}`
229
+ : `${item} no se agregó: ${needs}`;
230
+ }
231
+ const isTheme = registry_1.registry.items[item]?.type === 'theme';
232
+ const label = isTheme ? 'El tema' : item;
233
+ const dir = projectPathOf(files[0]).split('/').slice(0, -1).join('/');
234
+ return (`${label} no se actualizó a ${version} porque modificaste ${files.map(path).join(', ')}. ` +
235
+ 'No se cambió ninguno de sus archivos, para no mezclar versiones.' +
236
+ (isTheme
237
+ ? ` Los componentes de la ${version} usan tokens nuevos del tema: sin ellos, algunos estilos no se generan.`
238
+ : '') +
239
+ ' Para actualizarlo: guarda tus cambios (por ejemplo, en git), vuelve a ejecutar el ' +
240
+ 'comando con --overwrite y aplícalos de nuevo. La versión de Mimi que modificaste está en ' +
241
+ `${exports.BASE_DIR}/${dir}/, para comparar.`);
242
+ });
136
243
  }
137
244
  /** Compara versiones `x.y.z` numéricamente (`0.10.0` > `0.9.0`). `null` es la más vieja. */
138
245
  function compareVersions(a, b) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mimi-ng/cli",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "description": "Angular + Tailwind CSS 4 UI components that a CLI copies into your project, so you own the code. Schematics for ng add and ng generate.",
5
5
  "keywords": [
6
6
  "angular",