@mimi-ng/cli 0.3.0 → 0.5.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/README.md +42 -1
- package/dist/init/css.js +1 -1
- package/dist/init/index.js +33 -0
- package/dist/init/paths.js +20 -0
- package/dist/registry.js +4 -1
- package/dist/registry.json +198 -1
- package/dist/templates/blocks/login-01/index.ts +1 -0
- package/dist/templates/blocks/login-01/login-01.html +174 -0
- package/dist/templates/blocks/login-01/login-01.ts +114 -0
- package/dist/templates/blocks/login-02/index.ts +1 -0
- package/dist/templates/blocks/login-02/login-02.html +186 -0
- package/dist/templates/blocks/login-02/login-02.ts +101 -0
- package/dist/templates/blocks/otp-01/index.ts +1 -0
- package/dist/templates/blocks/otp-01/otp-01.html +166 -0
- package/dist/templates/blocks/otp-01/otp-01.ts +221 -0
- package/dist/templates/blocks/pricing-01/index.ts +1 -0
- package/dist/templates/blocks/pricing-01/pricing-01.html +173 -0
- package/dist/templates/blocks/pricing-01/pricing-01.ts +178 -0
- package/dist/templates/blocks/settings-01/index.ts +1 -0
- package/dist/templates/blocks/settings-01/settings-01.html +424 -0
- package/dist/templates/blocks/settings-01/settings-01.ts +392 -0
- package/dist/templates/blocks/signup-01/index.ts +1 -0
- package/dist/templates/blocks/signup-01/signup-01.html +332 -0
- package/dist/templates/blocks/signup-01/signup-01.ts +186 -0
- package/dist/templates/blocks/table-01/index.ts +1 -0
- package/dist/templates/blocks/table-01/table-01.html +214 -0
- package/dist/templates/blocks/table-01/table-01.ts +266 -0
- package/dist/templates/components/checkbox/checkbox.ts +14 -5
- package/dist/templates/components/command/command-texts.ts +65 -0
- package/dist/templates/components/command/command.ts +553 -0
- package/dist/templates/components/command/index.ts +13 -0
- package/dist/templates/components/data-table/data-table-texts.ts +110 -0
- package/dist/templates/components/data-table/data-table.ts +1153 -0
- package/dist/templates/components/data-table/index.ts +18 -0
- package/dist/templates/components/sortable-list/index.ts +9 -0
- package/dist/templates/components/sortable-list/sortable-list-texts.ts +71 -0
- package/dist/templates/components/sortable-list/sortable-list.ts +510 -0
- package/dist/templates/components/tabs/tabs.ts +88 -23
- package/dist/templates/components/tree/index.ts +9 -0
- package/dist/templates/components/tree/tree-texts.ts +45 -0
- package/dist/templates/components/tree/tree.ts +730 -0
- package/dist/templates/theme/provider.ts +4 -0
- package/dist/templates/theme/types.ts +84 -0
- package/dist/ui/index.js +323 -13
- package/dist/ui/schema.json +50 -2
- package/dist/utils/pages.js +138 -0
- package/dist/utils/project.js +59 -0
- package/dist/utils/tailwind.js +84 -0
- package/dist/utils/write-files.js +63 -8
- package/package.json +1 -1
|
@@ -97,37 +97,75 @@ export class MimiTabsOutlet {
|
|
|
97
97
|
});
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Orientación de la fila de pestañas (B.10): horizontal (por defecto) o vertical, para una
|
|
102
|
+
* navegación lateral. En vertical, las flechas son ↑/↓ (las pone aria) y el panel va al lado.
|
|
103
|
+
*/
|
|
104
|
+
export type MimiTabsOrientation = 'horizontal' | 'vertical';
|
|
105
|
+
|
|
100
106
|
/** El contenedor visible de las pestañas (recibe el `class` del usuario). */
|
|
101
107
|
const containerVariants = cva('relative font-sans', {
|
|
102
108
|
variants: {
|
|
103
109
|
variant: {
|
|
104
|
-
underline: 'border-
|
|
110
|
+
underline: 'border-border',
|
|
105
111
|
// 4px fijos (no rem): el indicador resta los mismos 8px.
|
|
106
|
-
pill: '
|
|
112
|
+
pill: 'rounded-[calc(var(--mimi-radius)_+_4px)] bg-[color:var(--mimi-tabs-pill-bg,var(--mimi-muted))] p-[4px]',
|
|
107
113
|
},
|
|
114
|
+
orientation: { horizontal: '', vertical: 'self-start' },
|
|
108
115
|
},
|
|
109
|
-
|
|
116
|
+
compoundVariants: [
|
|
117
|
+
{ variant: 'underline', orientation: 'horizontal', class: 'border-b' },
|
|
118
|
+
{ variant: 'underline', orientation: 'vertical', class: 'border-s' },
|
|
119
|
+
{ variant: 'pill', orientation: 'horizontal', class: 'max-w-[520px]' },
|
|
120
|
+
],
|
|
121
|
+
defaultVariants: { variant: 'underline', orientation: 'horizontal' },
|
|
110
122
|
});
|
|
111
123
|
|
|
112
124
|
/**
|
|
113
|
-
* El indicador: columnas iguales, así que su
|
|
114
|
-
* ancho por cada
|
|
125
|
+
* El indicador: columnas (o filas) iguales, así que su tamaño es el de una pestaña y se desplaza
|
|
126
|
+
* su propio ancho (o alto) por cada una (sin medir nada). En derecha a izquierda, al revés.
|
|
115
127
|
*/
|
|
116
128
|
const indicatorVariants = cva(
|
|
117
129
|
[
|
|
118
130
|
'pointer-events-none absolute',
|
|
119
|
-
'translate-x-[calc(100%_*_var(--mimi-tabs-index))] rtl:translate-x-[calc(-100%_*_var(--mimi-tabs-index))]',
|
|
120
131
|
'transition-[translate] duration-[450ms] ease-[var(--mimi-tabs-spring,cubic-bezier(0.3,1.35,0.5,1))] motion-reduce:transition-none',
|
|
121
132
|
],
|
|
122
133
|
{
|
|
123
134
|
variants: {
|
|
124
135
|
variant: {
|
|
125
|
-
underline:
|
|
126
|
-
|
|
127
|
-
|
|
136
|
+
underline: 'rounded-[2px] bg-[color:var(--mimi-tabs-indicator,var(--mimi-foreground))]',
|
|
137
|
+
pill: 'rounded-[var(--mimi-radius)] bg-[color:var(--mimi-tabs-pill-active,var(--mimi-card))] shadow-neutral',
|
|
138
|
+
},
|
|
139
|
+
orientation: {
|
|
140
|
+
horizontal:
|
|
141
|
+
'translate-x-[calc(100%_*_var(--mimi-tabs-index))] rtl:translate-x-[calc(-100%_*_var(--mimi-tabs-index))]',
|
|
142
|
+
vertical: 'translate-y-[calc(100%_*_var(--mimi-tabs-index))]',
|
|
128
143
|
},
|
|
129
144
|
},
|
|
130
|
-
|
|
145
|
+
compoundVariants: [
|
|
146
|
+
{
|
|
147
|
+
variant: 'underline',
|
|
148
|
+
orientation: 'horizontal',
|
|
149
|
+
class: '-bottom-px start-0 h-0.5 w-[calc(100%_/_var(--mimi-tabs-count))]',
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
// La barra va a la izquierda (al inicio), sobre el borde del contenedor.
|
|
153
|
+
variant: 'underline',
|
|
154
|
+
orientation: 'vertical',
|
|
155
|
+
class: '-start-px top-0 w-0.5 h-[calc(100%_/_var(--mimi-tabs-count))]',
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
variant: 'pill',
|
|
159
|
+
orientation: 'horizontal',
|
|
160
|
+
class: 'start-[4px] top-[4px] bottom-[4px] w-[calc((100%_-_8px)_/_var(--mimi-tabs-count))]',
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
variant: 'pill',
|
|
164
|
+
orientation: 'vertical',
|
|
165
|
+
class: 'start-[4px] end-[4px] top-[4px] h-[calc((100%_-_8px)_/_var(--mimi-tabs-count))]',
|
|
166
|
+
},
|
|
167
|
+
],
|
|
168
|
+
defaultVariants: { variant: 'underline', orientation: 'horizontal' },
|
|
131
169
|
},
|
|
132
170
|
);
|
|
133
171
|
|
|
@@ -148,8 +186,10 @@ const tabVariants = cva(
|
|
|
148
186
|
// 34px sin token (el token de alto es el de la subrayada): plan D6.
|
|
149
187
|
pill: 'h-[34px] gap-1.5 rounded-[var(--mimi-radius)] text-[13.5px] [&_svg]:size-[15px] [&_svg]:shrink-0',
|
|
150
188
|
},
|
|
189
|
+
// En vertical, el texto al inicio, como una navegación lateral.
|
|
190
|
+
orientation: { horizontal: '', vertical: 'justify-start px-3 text-start' },
|
|
151
191
|
},
|
|
152
|
-
defaultVariants: { variant: 'underline' },
|
|
192
|
+
defaultVariants: { variant: 'underline', orientation: 'horizontal' },
|
|
153
193
|
},
|
|
154
194
|
);
|
|
155
195
|
|
|
@@ -196,11 +236,12 @@ const COUNT_CLASSES =
|
|
|
196
236
|
<div
|
|
197
237
|
ngTabList
|
|
198
238
|
data-slot="tablist"
|
|
239
|
+
[orientation]="orientation()"
|
|
199
240
|
[selectedTab]="painted()"
|
|
200
241
|
(selectedTabChange)="fromAria($event)"
|
|
201
242
|
[attr.aria-label]="ariaLabel() || null"
|
|
202
243
|
[attr.aria-labelledby]="ariaLabelledby() || null"
|
|
203
|
-
[class]="tablistClasses"
|
|
244
|
+
[class]="tablistClasses()"
|
|
204
245
|
(click)="choose($event)"
|
|
205
246
|
(keydown.enter)="choose($event)"
|
|
206
247
|
(keydown.space)="choose($event)"
|
|
@@ -248,12 +289,19 @@ const COUNT_CLASSES =
|
|
|
248
289
|
</div>
|
|
249
290
|
`,
|
|
250
291
|
host: {
|
|
251
|
-
|
|
292
|
+
// flex-direction va en su binding (B.10), no aquí.
|
|
293
|
+
style: 'display: flex; gap: 14px',
|
|
252
294
|
// El class es del contenedor de las pestañas; aria-label y aria-labelledby, del tablist.
|
|
253
295
|
'[attr.class]': 'null',
|
|
254
296
|
'[attr.aria-label]': 'null',
|
|
255
297
|
'[attr.aria-labelledby]': 'null',
|
|
256
298
|
'[attr.data-variant]': 'variant()',
|
|
299
|
+
'[attr.data-orientation]': 'orientation()',
|
|
300
|
+
// En vertical, las pestañas a un lado y el panel al otro. Bindings sueltos (no [style] con
|
|
301
|
+
// un objeto, que sumaba ɵɵstyleMap al JS inicial: spec 10).
|
|
302
|
+
// Siempre con valor: con null, Angular quita también el flex-direction del style estático.
|
|
303
|
+
'[style.flex-direction]': 'orientation() === "vertical" ? "row" : "column"',
|
|
304
|
+
'[style.align-items]': 'orientation() === "vertical" ? "flex-start" : null',
|
|
257
305
|
},
|
|
258
306
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
259
307
|
})
|
|
@@ -264,6 +312,8 @@ export class MimiTabs {
|
|
|
264
312
|
readonly value = model<string | undefined>(undefined);
|
|
265
313
|
/** Por defecto, `underline`. */
|
|
266
314
|
readonly variant = input<MimiTabsVariant>('underline');
|
|
315
|
+
/** Por defecto, `horizontal`. Puede cambiar en vivo (por ejemplo, con el ancho). */
|
|
316
|
+
readonly orientation = input<MimiTabsOrientation>('horizontal');
|
|
267
317
|
/** Conserva el contenido de los paneles al cambiar de pestaña (por defecto se destruye). */
|
|
268
318
|
readonly preserveContent = input(false, { transform: booleanAttribute });
|
|
269
319
|
/** Nombre accesible de la fila de pestañas. */
|
|
@@ -298,22 +348,37 @@ export class MimiTabs {
|
|
|
298
348
|
this.tabs().findIndex((tab) => tab.value() === this.painted()),
|
|
299
349
|
);
|
|
300
350
|
|
|
351
|
+
private readonly variants = computed(() => ({
|
|
352
|
+
variant: this.variant(),
|
|
353
|
+
orientation: this.orientation(),
|
|
354
|
+
}));
|
|
301
355
|
protected readonly containerClasses = computed(() =>
|
|
302
|
-
cn(containerVariants(
|
|
356
|
+
cn(containerVariants(this.variants()), this.userClass()),
|
|
303
357
|
);
|
|
304
|
-
protected readonly indicatorClasses = computed(() =>
|
|
305
|
-
|
|
306
|
-
)
|
|
307
|
-
protected readonly tabClasses = computed(() => tabVariants(
|
|
358
|
+
protected readonly indicatorClasses = computed(() => indicatorVariants(this.variants()));
|
|
359
|
+
// Con cn(): la vertical cambia `justify-center` por `justify-start` (sin él, quedaban las dos y
|
|
360
|
+
// ganaba la que va después en el CSS).
|
|
361
|
+
protected readonly tabClasses = computed(() => cn(tabVariants(this.variants())));
|
|
308
362
|
// Sin outline-none: en Tailwind 4 pone --tw-outline-style en none y anula el anillo de foco.
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
363
|
+
// Las clases de cada orientación, completas (no variantes encadenadas: selectores largos, G2.1).
|
|
364
|
+
protected readonly tablistClasses = computed(() =>
|
|
365
|
+
cn(
|
|
366
|
+
this.orientation() === 'vertical'
|
|
367
|
+
? 'grid grid-rows-[repeat(var(--mimi-tabs-count),minmax(0,1fr))]'
|
|
368
|
+
: 'grid grid-cols-[repeat(var(--mimi-tabs-count),minmax(0,1fr))]',
|
|
369
|
+
'rounded-[inherit]',
|
|
370
|
+
// Con todas deshabilitadas, el foco queda en la fila (aria).
|
|
371
|
+
buttonFocusStyles,
|
|
372
|
+
),
|
|
313
373
|
);
|
|
314
374
|
protected readonly countClasses = COUNT_CLASSES;
|
|
315
375
|
protected readonly panelClasses = computed(() =>
|
|
316
|
-
cn(
|
|
376
|
+
cn(
|
|
377
|
+
'px-0.5 py-1',
|
|
378
|
+
this.orientation() === 'vertical' && 'min-w-0 flex-1',
|
|
379
|
+
buttonFocusStyles,
|
|
380
|
+
this.panelClass(),
|
|
381
|
+
),
|
|
317
382
|
);
|
|
318
383
|
|
|
319
384
|
/** El último valor que puso Mimi (no viene de fuera). */
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { InjectionToken, type Provider } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
/*
|
|
4
|
+
* Textos del Tree, en archivo propio y sin @angular/cdk: así se pueden proveer en `app.config.ts`
|
|
5
|
+
* sin llevar el Tree al chunk inicial.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/** Textos que el Tree muestra o anuncia. */
|
|
9
|
+
export interface MimiTreeText {
|
|
10
|
+
/** Fila mientras se cargan los hijos de un nodo (carga diferida). */
|
|
11
|
+
loading: string;
|
|
12
|
+
/** Fila cuando la carga falla; se reintenta al volver a abrir el nodo. */
|
|
13
|
+
loadError: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Textos predeterminados (inglés). */
|
|
17
|
+
export const MIMI_TREE_TEXT_EN: MimiTreeText = {
|
|
18
|
+
loading: 'Loading…',
|
|
19
|
+
loadError: 'Couldn’t load. Close and open it again to retry.',
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/** Textos en español: `provideMimiTreeText(MIMI_TREE_TEXT_ES)`. */
|
|
23
|
+
export const MIMI_TREE_TEXT_ES: MimiTreeText = {
|
|
24
|
+
loading: 'Cargando…',
|
|
25
|
+
loadError: 'No se pudo cargar. Ciérralo y ábrelo para reintentar.',
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/** Textos activos. Sin `provideMimiTreeText`, los predeterminados en inglés. */
|
|
29
|
+
export const MIMI_TREE_TEXT = new InjectionToken<MimiTreeText>('MIMI_TREE_TEXT', {
|
|
30
|
+
providedIn: 'root',
|
|
31
|
+
factory: () => MIMI_TREE_TEXT_EN,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Cambia los textos del Tree. Lo que no definas sigue en inglés:
|
|
36
|
+
*
|
|
37
|
+
* ```ts
|
|
38
|
+
* provideMimiTreeText(MIMI_TREE_TEXT_ES)
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* Va en `app.config.ts` o en los `providers` de un componente o ruta.
|
|
42
|
+
*/
|
|
43
|
+
export function provideMimiTreeText(text: Partial<MimiTreeText>): Provider {
|
|
44
|
+
return { provide: MIMI_TREE_TEXT, useValue: { ...MIMI_TREE_TEXT_EN, ...text } };
|
|
45
|
+
}
|