@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
package/README.md
CHANGED
|
@@ -29,7 +29,7 @@ ng add @mimi-ng/cli
|
|
|
29
29
|
|
|
30
30
|
Verifica Angular y Tailwind (si falta algo, se detiene sin modificar nada) y configura el proyecto:
|
|
31
31
|
|
|
32
|
-
- importa el tema de Mimi en tu CSS global, justo después de `@import "tailwindcss"
|
|
32
|
+
- importa el tema de Mimi en tu CSS global, justo después de `@import "tailwindcss"`, y excluye `.mimi/` del escaneo de Tailwind (`@source not "../.mimi";`, con Tailwind 4.1 o superior);
|
|
33
33
|
- agrega el alias `@/components/ui/*` al `tsconfig.json`;
|
|
34
34
|
- registra la CLI en `angular.json`, para que funcione `ng g mimi`;
|
|
35
35
|
- instala `clsx`, `tailwind-merge` y `class-variance-authority` con tu gestor de paquetes;
|
|
@@ -37,6 +37,14 @@ Verifica Angular y Tailwind (si falta algo, se detiene sin modificar nada) y con
|
|
|
37
37
|
|
|
38
38
|
Con `--icons` instala también [`@lucide/angular`](https://lucide.dev) para tus íconos.
|
|
39
39
|
|
|
40
|
+
**Si configuraste el CSS a mano, o instalaste con la 0.3.0 o una anterior,** agrega después de `@import "tailwindcss"` (la ruta va de tu CSS global a la carpeta `.mimi/` de la raíz; con `src/styles.css`, así):
|
|
41
|
+
|
|
42
|
+
```css
|
|
43
|
+
@source not "../.mimi";
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Sin esa línea, Tailwind escanea las copias originales de `.mimi/` (van en git) y tu CSS lleva sus clases aunque ya las hayas cambiado. `ng g mimi` te avisa si falta. Necesita Tailwind 4.1 o superior: la 4.0 no entiende `@source not`.
|
|
47
|
+
|
|
40
48
|
## Agregar componentes
|
|
41
49
|
|
|
42
50
|
```sh
|
|
@@ -71,8 +79,10 @@ export class App {}
|
|
|
71
79
|
- **Checkbox**: `ng g mimi checkbox` · [documentación](https://ng.mimiworks.dev/docs/components/switch)
|
|
72
80
|
- **Color Picker**: `ng g mimi color-picker` · [documentación](https://ng.mimiworks.dev/docs/components/color-picker)
|
|
73
81
|
- **Combobox**: `ng g mimi combobox` · [documentación](https://ng.mimiworks.dev/docs/components/combobox)
|
|
82
|
+
- **Command**: `ng g mimi command` · [documentación](https://ng.mimiworks.dev/docs/components/command)
|
|
74
83
|
- **Confirm**: `ng g mimi confirm` · [documentación](https://ng.mimiworks.dev/docs/components/confirm)
|
|
75
84
|
- **Context Menu**: `ng g mimi context-menu` · [documentación](https://ng.mimiworks.dev/docs/components/context-menu)
|
|
85
|
+
- **Data Table**: `ng g mimi data-table` · [documentación](https://ng.mimiworks.dev/docs/components/data-table)
|
|
76
86
|
- **Date Picker**: `ng g mimi date-picker` · [documentación](https://ng.mimiworks.dev/docs/components/date-picker)
|
|
77
87
|
- **Date Range**: `ng g mimi date-range` · [documentación](https://ng.mimiworks.dev/docs/components/date-range)
|
|
78
88
|
- **Dialog**: `ng g mimi dialog` · [documentación](https://ng.mimiworks.dev/docs/components/dialog)
|
|
@@ -91,6 +101,7 @@ export class App {}
|
|
|
91
101
|
- **Separator**: `ng g mimi separator` · [documentación](https://ng.mimiworks.dev/docs/components/separator)
|
|
92
102
|
- **Skeleton**: `ng g mimi skeleton` · [documentación](https://ng.mimiworks.dev/docs/components/skeleton)
|
|
93
103
|
- **Slider**: `ng g mimi slider` · [documentación](https://ng.mimiworks.dev/docs/components/slider)
|
|
104
|
+
- **Sortable List**: `ng g mimi sortable-list` · [documentación](https://ng.mimiworks.dev/docs/components/sortable-list)
|
|
94
105
|
- **Switch**: `ng g mimi switch` · [documentación](https://ng.mimiworks.dev/docs/components/switch)
|
|
95
106
|
- **Tabs**: `ng g mimi tabs` · [documentación](https://ng.mimiworks.dev/docs/components/tabs)
|
|
96
107
|
- **Textarea**: `ng g mimi textarea` · [documentación](https://ng.mimiworks.dev/docs/components/input)
|
|
@@ -99,6 +110,24 @@ export class App {}
|
|
|
99
110
|
- **Toggle Group**: `ng g mimi toggle-group` · [documentación](https://ng.mimiworks.dev/docs/components/toggle-group)
|
|
100
111
|
- **Toolbar**: `ng g mimi toolbar` · [documentación](https://ng.mimiworks.dev/docs/components/toolbar)
|
|
101
112
|
- **Tooltip**: `ng g mimi tooltip` · [documentación](https://ng.mimiworks.dev/docs/components/tooltip)
|
|
113
|
+
- **Tree**: `ng g mimi tree` · [documentación](https://ng.mimiworks.dev/docs/components/tree)
|
|
114
|
+
|
|
115
|
+
## Blocks
|
|
116
|
+
|
|
117
|
+
Pantallas y secciones (inicio de sesión, registro, ajustes, precios…) hechas con los componentes de Mimi. Se agregan con el mismo comando, por ejemplo `ng g mimi` seguido del nombre del Block, y los componentes que usan van a la carpeta de siempre.
|
|
118
|
+
|
|
119
|
+
- **Las páginas** (`login-01`, `login-02`, `otp-01`, `settings-01`, `signup-01`, `table-01`) se generan como una página tuya: `ng g mimi login-01` crea `src/app/pages/login/` (`aliases.pages` en `mimi.json`) con `login.ts`, `login.html` y `login.routes.ts`, y la clase `LoginPage`. Al terminar te da la línea para `app.routes.ts` (la CLI no toca tus rutas). Otro nombre: `--name admin-login`. Si la carpeta ya existe, no la toca y te pide otro nombre.
|
|
120
|
+
- **Las secciones** (`pricing-01`) se copian a `src/app/blocks/<nombre>` (`aliases.blocks`): ponlas dentro de una de tus páginas.
|
|
121
|
+
|
|
122
|
+
El Block es tuyo; si lo modificas, `ng g mimi` no lo vuelve a tocar al actualizar (te avisa y `--overwrite` lo reemplaza entero). Mimi lo sigue por su nombre (`login-01`) aunque le pongas otro. Si instalaste una pantalla con la 0.4.0, sigue en `src/app/blocks/` y se actualiza ahí.
|
|
123
|
+
|
|
124
|
+
- **login-01** (página: inicio de sesión centrado, con Google y GitHub): `ng g mimi login-01` · [documentación](https://ng.mimiworks.dev/docs/blocks/login-01)
|
|
125
|
+
- **login-02** (página: inicio de sesión en dos columnas, con imagen y testimonio): `ng g mimi login-02` · [documentación](https://ng.mimiworks.dev/docs/blocks/login-02)
|
|
126
|
+
- **otp-01** (página: verificación con un código de 6 dígitos, reenvío y cuenta regresiva): `ng g mimi otp-01` · [documentación](https://ng.mimiworks.dev/docs/blocks/otp-01)
|
|
127
|
+
- **pricing-01** (sección: tres planes con mensual/anual y el plan destacado): `ng g mimi pricing-01` · [documentación](https://ng.mimiworks.dev/docs/blocks/pricing-01)
|
|
128
|
+
- **settings-01** (página: ajustes de cuenta con secciones, interruptores, sesiones y facturación): `ng g mimi settings-01` · [documentación](https://ng.mimiworks.dev/docs/blocks/settings-01)
|
|
129
|
+
- **table-01** (página: clientes con la Data Table en escritorio y una lista de tarjetas en móvil): `ng g mimi table-01` · [documentación](https://ng.mimiworks.dev/docs/blocks/table-01)
|
|
130
|
+
- **signup-01** (página: registro con validación, medidor de contraseña y confirmación): `ng g mimi signup-01` · [documentación](https://ng.mimiworks.dev/docs/blocks/signup-01)
|
|
102
131
|
|
|
103
132
|
## Tus cambios
|
|
104
133
|
|
|
@@ -111,6 +140,18 @@ export class App {}
|
|
|
111
140
|
|
|
112
141
|
Desde pnpm 10, los scripts de instalación de las dependencias están bloqueados hasta que los apruebes, y la instalación puede fallar con `ERR_PNPM_IGNORED_BUILDS`. Apruébalos con `pnpm approve-builds`. Más detalles en la [página de Instalación](https://ng.mimiworks.dev/docs/installation).
|
|
113
142
|
|
|
143
|
+
## Si los componentes salen sin estilos
|
|
144
|
+
|
|
145
|
+
Si `ng build` termina bien pero los componentes salen sin estilos, y el CSS compilado pesa mucho menos de lo normal (en una prueba, unos 33 kB en vez de unos 100 kB), puede que tu sistema bloquee el binario nativo de Tailwind. Lo vimos en Windows, con el Control de aplicaciones, que bloqueó el binario de Tailwind 4.3.5: Tailwind usa entonces un respaldo que no escanea tus archivos, y no da ningún error. No es de Mimi.
|
|
146
|
+
|
|
147
|
+
Para comprobarlo, busca una clase de tus componentes (por ejemplo `bg-background`) en el `styles-*.css` de `dist/<proyecto>/browser`: si no está, Tailwind no escaneó nada. Para ver si es el bloqueo, carga el binario desde la raíz del proyecto (Windows x64):
|
|
148
|
+
|
|
149
|
+
```sh
|
|
150
|
+
node -e "require('./node_modules/@tailwindcss/oxide-win32-x64-msvc/tailwindcss-oxide.win32-x64-msvc.node')"
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Si falla con `ERR_DLOPEN_FAILED`, permite ese archivo en la política de tu sistema (con quien la administre) o fija una versión de Tailwind cuyo binario cargue; en la prueba donde lo vimos, la 4.3.3: `npm i -D --save-exact tailwindcss@4.3.3 @tailwindcss/postcss@4.3.3`. No desactives la política de seguridad para esto. Con otra versión, o en otro equipo, el resultado puede ser distinto.
|
|
154
|
+
|
|
114
155
|
## Licencia
|
|
115
156
|
|
|
116
157
|
MIT. Incluye íconos de Lucide (ISC); ver `THIRD_PARTY_NOTICES.md`.
|
package/dist/init/css.js
CHANGED
|
@@ -42,7 +42,7 @@ function insertAfterTheme(css, lines) {
|
|
|
42
42
|
const eol = eolOf(css);
|
|
43
43
|
return css.slice(0, end) + lines.map((line) => eol + line).join('') + css.slice(end);
|
|
44
44
|
}
|
|
45
|
-
/** ¿Ya hay un `@import` o `@source` con esa ruta (
|
|
45
|
+
/** ¿Ya hay un `@import`, `@source` o `@source not` con esa ruta (comillas simples o dobles)? */
|
|
46
46
|
function hasDirective(css, directive, path) {
|
|
47
47
|
const escaped = path.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
48
48
|
return new RegExp(`${directive}\\s+(["'])${escaped}\\1`).test(css);
|
package/dist/init/index.js
CHANGED
|
@@ -7,6 +7,7 @@ const utility_1 = require("@schematics/angular/utility");
|
|
|
7
7
|
const json_file_1 = require("@schematics/angular/utility/json-file");
|
|
8
8
|
const registry_1 = require("../registry");
|
|
9
9
|
const project_1 = require("../utils/project");
|
|
10
|
+
const tailwind_1 = require("../utils/tailwind");
|
|
10
11
|
const write_files_1 = require("../utils/write-files");
|
|
11
12
|
const css_1 = require("./css");
|
|
12
13
|
const items_1 = require("./items");
|
|
@@ -87,13 +88,18 @@ async function inspect(tree, options) {
|
|
|
87
88
|
}
|
|
88
89
|
const sourceRoot = (0, paths_1.normalizePath)(project.sourceRoot ?? `${project.root}/src`);
|
|
89
90
|
const mimiConfig = (0, project_1.readJson)(tree, 'mimi.json');
|
|
91
|
+
if (mimiConfig)
|
|
92
|
+
(0, project_1.assertAliases)(mimiConfig);
|
|
90
93
|
const componentsDir = (0, paths_1.normalizePath)(mimiConfig?.aliases?.components ?? `${sourceRoot}/app/components/ui`);
|
|
91
94
|
const tsConfig = build?.options?.['tsConfig'];
|
|
92
95
|
return {
|
|
93
96
|
projectName: name,
|
|
94
97
|
cssPath: withTailwind,
|
|
95
98
|
sourceNone: (0, css_1.findTailwindImport)(tree.readText(withTailwind)).sourceNone,
|
|
99
|
+
sourceNot: (0, tailwind_1.tailwindSupportsSourceNot)(tree, deps['tailwindcss']),
|
|
96
100
|
componentsDir,
|
|
101
|
+
blocksDir: (0, paths_1.normalizePath)(mimiConfig?.aliases?.blocks ?? (0, project_1.defaultBlocksDir)(componentsDir)),
|
|
102
|
+
pagesDir: (0, paths_1.normalizePath)(mimiConfig?.aliases?.pages ?? (0, project_1.defaultPagesDir)(componentsDir)),
|
|
97
103
|
buildTsConfig: typeof tsConfig === 'string' ? (0, paths_1.normalizePath)(tsConfig) : undefined,
|
|
98
104
|
mimiConfig,
|
|
99
105
|
sourceRoot,
|
|
@@ -134,6 +140,29 @@ function updateGlobalCss(plan) {
|
|
|
134
140
|
context.logger.warn(`El @import de Tailwind en ${plan.cssPath} usa source(none): Tailwind no escanea nada por su ` +
|
|
135
141
|
`cuenta. Se agregó @source "${sourcePath}"; para que genere las clases de los componentes.`);
|
|
136
142
|
}
|
|
143
|
+
// G1: y la carpeta de los Blocks (sin él, un Block queda sin estilos). Tailwind no se queja
|
|
144
|
+
// si la carpeta todavía no existe.
|
|
145
|
+
const blocksSourcePath = (0, paths_1.relativePath)(cssDir, plan.blocksDir);
|
|
146
|
+
if (plan.sourceNone && !(0, css_1.hasDirective)(css, '@source', blocksSourcePath)) {
|
|
147
|
+
lines.push(`@source "${blocksSourcePath}";`);
|
|
148
|
+
}
|
|
149
|
+
// B.11-i: y la de las páginas (los Blocks de tipo página).
|
|
150
|
+
const pagesSourcePath = (0, paths_1.relativePath)(cssDir, plan.pagesDir);
|
|
151
|
+
if (plan.sourceNone && !(0, css_1.hasDirective)(css, '@source', pagesSourcePath)) {
|
|
152
|
+
lines.push(`@source "${pagesSourcePath}";`);
|
|
153
|
+
}
|
|
154
|
+
// Sin source(none), Tailwind escanea todo el workspace salvo lo que ignora git, y .mimi/ va
|
|
155
|
+
// en git: las clases de las copias originales acabarían en el CSS aunque el usuario ya las
|
|
156
|
+
// haya cambiado o quitado en sus componentes.
|
|
157
|
+
// Con Tailwind 4.0 (no entiende `@source not`) no se escribe: solo se avisa.
|
|
158
|
+
if ((0, tailwind_1.missingMimiExclusion)(css, plan.cssPath)) {
|
|
159
|
+
const line = (0, tailwind_1.mimiSourceNotLine)(plan.cssPath);
|
|
160
|
+
if (plan.sourceNot)
|
|
161
|
+
lines.push(line);
|
|
162
|
+
else
|
|
163
|
+
context.logger.warn(`Tailwind 4.0 escanea ${write_files_1.BASE_DIR}/ y genera CSS de más. Con Tailwind 4.1 o superior, ` +
|
|
164
|
+
`agrega ${line} en ${plan.cssPath} (init lo hace si lo vuelves a ejecutar).`);
|
|
165
|
+
}
|
|
137
166
|
if (lines.length === 0)
|
|
138
167
|
return;
|
|
139
168
|
css = (0, css_1.insertAfterTailwind)(css, lines);
|
|
@@ -224,6 +253,10 @@ function writeMimiConfig(plan) {
|
|
|
224
253
|
components: plan.componentsDir,
|
|
225
254
|
utils: `${plan.componentsDir}/utils`,
|
|
226
255
|
theme: `${plan.sourceRoot}/app/mimi.preset.ts`,
|
|
256
|
+
// Desde la 0.4.0 (B.1-a). Los proyectos anteriores lo reciben con el primer Block.
|
|
257
|
+
blocks: plan.blocksDir,
|
|
258
|
+
// Desde la B.11. Los proyectos anteriores lo reciben con la primera página.
|
|
259
|
+
pages: plan.pagesDir,
|
|
227
260
|
},
|
|
228
261
|
components: {},
|
|
229
262
|
};
|
package/dist/init/paths.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.normalizePath = normalizePath;
|
|
9
|
+
exports.invalidAliasReason = invalidAliasReason;
|
|
9
10
|
exports.dirnameOf = dirnameOf;
|
|
10
11
|
exports.relativePath = relativePath;
|
|
11
12
|
/** `src\app\ui\`, `./src/app/ui` o `/src/app/ui` → `src/app/ui`. Resuelve `.` y `..`. */
|
|
@@ -21,6 +22,25 @@ function normalizePath(path) {
|
|
|
21
22
|
}
|
|
22
23
|
return out.join('/');
|
|
23
24
|
}
|
|
25
|
+
/**
|
|
26
|
+
* M2: un alias de mimi.json (`components`, `blocks`) tiene que ser una ruta relativa a la raíz del
|
|
27
|
+
* workspace y quedar dentro de él. Devuelve el motivo si no lo es (o null): absoluta (`/x`,
|
|
28
|
+
* `C:\x`, `\\servidor`, `~/x`), con `..` o vacía. Se comprueba antes de normalizar: normalizePath
|
|
29
|
+
* convertiría `C:\x` en una carpeta «C:» y quitaría el `/` inicial.
|
|
30
|
+
*/
|
|
31
|
+
function invalidAliasReason(value) {
|
|
32
|
+
if (typeof value !== 'string' || value.trim() === '')
|
|
33
|
+
return 'está vacío';
|
|
34
|
+
const path = value.trim().replace(/\\/g, '/');
|
|
35
|
+
if (/^[a-zA-Z]:/.test(path) || path.startsWith('/') || path.startsWith('~')) {
|
|
36
|
+
return 'es una ruta absoluta';
|
|
37
|
+
}
|
|
38
|
+
if (path.split('/').includes('..'))
|
|
39
|
+
return 'tiene «..» (saldría del proyecto)';
|
|
40
|
+
if (normalizePath(path) === '')
|
|
41
|
+
return 'apunta a la raíz del workspace';
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
24
44
|
/** Carpeta de un archivo: `src/styles.css` → `src`. */
|
|
25
45
|
function dirnameOf(path) {
|
|
26
46
|
const parts = normalizePath(path).split('/');
|
package/dist/registry.js
CHANGED
|
@@ -3,10 +3,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.registry = void 0;
|
|
6
|
+
exports.isPageBlock = exports.registry = void 0;
|
|
7
7
|
exports.resolveItems = resolveItems;
|
|
8
8
|
const registry_json_1 = __importDefault(require("./registry.json"));
|
|
9
9
|
exports.registry = registry_json_1.default;
|
|
10
|
+
/** ¿El ítem es un Block que se genera como página (B.11)? */
|
|
11
|
+
const isPageBlock = (name, reg = exports.registry) => reg.items[name]?.type === 'block' && reg.items[name].kind === 'page';
|
|
12
|
+
exports.isPageBlock = isPageBlock;
|
|
10
13
|
/**
|
|
11
14
|
* El ítem y todas sus `registryDependencies`, sin repetir, dependencias primero.
|
|
12
15
|
* Lanza un error si el nombre no existe.
|
package/dist/registry.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
2
|
+
"version": "0.5.0",
|
|
3
3
|
"suggestedDependencies": {
|
|
4
4
|
"@lucide/angular": "^1.47.0"
|
|
5
5
|
},
|
|
@@ -265,6 +265,23 @@
|
|
|
265
265
|
"utils/cn"
|
|
266
266
|
]
|
|
267
267
|
},
|
|
268
|
+
"data-table": {
|
|
269
|
+
"type": "component",
|
|
270
|
+
"files": [
|
|
271
|
+
"components/data-table/data-table.ts",
|
|
272
|
+
"components/data-table/data-table-texts.ts",
|
|
273
|
+
"components/data-table/index.ts"
|
|
274
|
+
],
|
|
275
|
+
"registryDependencies": [
|
|
276
|
+
"checkbox",
|
|
277
|
+
"chip",
|
|
278
|
+
"dropdown-menu",
|
|
279
|
+
"input",
|
|
280
|
+
"pagination",
|
|
281
|
+
"toggle-group",
|
|
282
|
+
"utils/cn"
|
|
283
|
+
]
|
|
284
|
+
},
|
|
268
285
|
"input-mask": {
|
|
269
286
|
"type": "component",
|
|
270
287
|
"files": [
|
|
@@ -334,6 +351,20 @@
|
|
|
334
351
|
"utils/cn"
|
|
335
352
|
]
|
|
336
353
|
},
|
|
354
|
+
"sortable-list": {
|
|
355
|
+
"type": "component",
|
|
356
|
+
"files": [
|
|
357
|
+
"components/sortable-list/sortable-list.ts",
|
|
358
|
+
"components/sortable-list/sortable-list-texts.ts",
|
|
359
|
+
"components/sortable-list/index.ts"
|
|
360
|
+
],
|
|
361
|
+
"peerDependencies": {
|
|
362
|
+
"@angular/cdk": "^22.2.4"
|
|
363
|
+
},
|
|
364
|
+
"registryDependencies": [
|
|
365
|
+
"utils/cn"
|
|
366
|
+
]
|
|
367
|
+
},
|
|
337
368
|
"slider": {
|
|
338
369
|
"type": "component",
|
|
339
370
|
"files": [
|
|
@@ -374,6 +405,22 @@
|
|
|
374
405
|
"utils/overlay"
|
|
375
406
|
]
|
|
376
407
|
},
|
|
408
|
+
"command": {
|
|
409
|
+
"type": "component",
|
|
410
|
+
"files": [
|
|
411
|
+
"components/command/command.ts",
|
|
412
|
+
"components/command/command-texts.ts",
|
|
413
|
+
"components/command/index.ts"
|
|
414
|
+
],
|
|
415
|
+
"peerDependencies": {
|
|
416
|
+
"@angular/aria": "^22.2.4"
|
|
417
|
+
},
|
|
418
|
+
"registryDependencies": [
|
|
419
|
+
"dialog",
|
|
420
|
+
"option-list",
|
|
421
|
+
"utils/cn"
|
|
422
|
+
]
|
|
423
|
+
},
|
|
377
424
|
"calendar": {
|
|
378
425
|
"type": "component",
|
|
379
426
|
"files": [
|
|
@@ -655,6 +702,22 @@
|
|
|
655
702
|
"utils/overlay"
|
|
656
703
|
]
|
|
657
704
|
},
|
|
705
|
+
"tree": {
|
|
706
|
+
"type": "component",
|
|
707
|
+
"files": [
|
|
708
|
+
"components/tree/tree.ts",
|
|
709
|
+
"components/tree/tree-texts.ts",
|
|
710
|
+
"components/tree/index.ts"
|
|
711
|
+
],
|
|
712
|
+
"peerDependencies": {
|
|
713
|
+
"@angular/cdk": "^22.2.4",
|
|
714
|
+
"@angular/forms": "^22.0.0"
|
|
715
|
+
},
|
|
716
|
+
"registryDependencies": [
|
|
717
|
+
"checkbox",
|
|
718
|
+
"utils/cn"
|
|
719
|
+
]
|
|
720
|
+
},
|
|
658
721
|
"textarea": {
|
|
659
722
|
"type": "component",
|
|
660
723
|
"files": [
|
|
@@ -670,6 +733,140 @@
|
|
|
670
733
|
"utils/control-styles",
|
|
671
734
|
"utils/field-state"
|
|
672
735
|
]
|
|
736
|
+
},
|
|
737
|
+
"login-01": {
|
|
738
|
+
"type": "block",
|
|
739
|
+
"kind": "page",
|
|
740
|
+
"files": [
|
|
741
|
+
"blocks/login-01/login-01.ts",
|
|
742
|
+
"blocks/login-01/login-01.html",
|
|
743
|
+
"blocks/login-01/index.ts"
|
|
744
|
+
],
|
|
745
|
+
"peerDependencies": {
|
|
746
|
+
"@angular/forms": "^22.0.0"
|
|
747
|
+
},
|
|
748
|
+
"registryDependencies": [
|
|
749
|
+
"button",
|
|
750
|
+
"card",
|
|
751
|
+
"checkbox",
|
|
752
|
+
"form-field",
|
|
753
|
+
"input",
|
|
754
|
+
"password",
|
|
755
|
+
"separator",
|
|
756
|
+
"utils/cn"
|
|
757
|
+
]
|
|
758
|
+
},
|
|
759
|
+
"login-02": {
|
|
760
|
+
"type": "block",
|
|
761
|
+
"kind": "page",
|
|
762
|
+
"files": [
|
|
763
|
+
"blocks/login-02/login-02.ts",
|
|
764
|
+
"blocks/login-02/login-02.html",
|
|
765
|
+
"blocks/login-02/index.ts"
|
|
766
|
+
],
|
|
767
|
+
"peerDependencies": {
|
|
768
|
+
"@angular/forms": "^22.0.0"
|
|
769
|
+
},
|
|
770
|
+
"registryDependencies": [
|
|
771
|
+
"avatar",
|
|
772
|
+
"button",
|
|
773
|
+
"form-field",
|
|
774
|
+
"input",
|
|
775
|
+
"utils/cn"
|
|
776
|
+
]
|
|
777
|
+
},
|
|
778
|
+
"signup-01": {
|
|
779
|
+
"type": "block",
|
|
780
|
+
"kind": "page",
|
|
781
|
+
"files": [
|
|
782
|
+
"blocks/signup-01/signup-01.ts",
|
|
783
|
+
"blocks/signup-01/signup-01.html",
|
|
784
|
+
"blocks/signup-01/index.ts"
|
|
785
|
+
],
|
|
786
|
+
"peerDependencies": {
|
|
787
|
+
"@angular/forms": "^22.0.0"
|
|
788
|
+
},
|
|
789
|
+
"registryDependencies": [
|
|
790
|
+
"button",
|
|
791
|
+
"checkbox",
|
|
792
|
+
"form-field",
|
|
793
|
+
"input",
|
|
794
|
+
"password",
|
|
795
|
+
"utils/cn"
|
|
796
|
+
]
|
|
797
|
+
},
|
|
798
|
+
"otp-01": {
|
|
799
|
+
"type": "block",
|
|
800
|
+
"kind": "page",
|
|
801
|
+
"files": [
|
|
802
|
+
"blocks/otp-01/otp-01.ts",
|
|
803
|
+
"blocks/otp-01/otp-01.html",
|
|
804
|
+
"blocks/otp-01/index.ts"
|
|
805
|
+
],
|
|
806
|
+
"registryDependencies": [
|
|
807
|
+
"button",
|
|
808
|
+
"card",
|
|
809
|
+
"input-otp",
|
|
810
|
+
"utils/cn"
|
|
811
|
+
]
|
|
812
|
+
},
|
|
813
|
+
"settings-01": {
|
|
814
|
+
"type": "block",
|
|
815
|
+
"kind": "page",
|
|
816
|
+
"files": [
|
|
817
|
+
"blocks/settings-01/settings-01.ts",
|
|
818
|
+
"blocks/settings-01/settings-01.html",
|
|
819
|
+
"blocks/settings-01/index.ts"
|
|
820
|
+
],
|
|
821
|
+
"peerDependencies": {
|
|
822
|
+
"@angular/forms": "^22.0.0"
|
|
823
|
+
},
|
|
824
|
+
"registryDependencies": [
|
|
825
|
+
"avatar",
|
|
826
|
+
"badge",
|
|
827
|
+
"button",
|
|
828
|
+
"card",
|
|
829
|
+
"form-field",
|
|
830
|
+
"input",
|
|
831
|
+
"progress",
|
|
832
|
+
"separator",
|
|
833
|
+
"switch",
|
|
834
|
+
"tabs",
|
|
835
|
+
"textarea",
|
|
836
|
+
"utils/cn"
|
|
837
|
+
]
|
|
838
|
+
},
|
|
839
|
+
"table-01": {
|
|
840
|
+
"type": "block",
|
|
841
|
+
"kind": "page",
|
|
842
|
+
"files": [
|
|
843
|
+
"blocks/table-01/table-01.ts",
|
|
844
|
+
"blocks/table-01/table-01.html",
|
|
845
|
+
"blocks/table-01/index.ts"
|
|
846
|
+
],
|
|
847
|
+
"registryDependencies": [
|
|
848
|
+
"badge",
|
|
849
|
+
"button",
|
|
850
|
+
"checkbox",
|
|
851
|
+
"data-table",
|
|
852
|
+
"input",
|
|
853
|
+
"utils/cn"
|
|
854
|
+
]
|
|
855
|
+
},
|
|
856
|
+
"pricing-01": {
|
|
857
|
+
"type": "block",
|
|
858
|
+
"kind": "section",
|
|
859
|
+
"files": [
|
|
860
|
+
"blocks/pricing-01/pricing-01.ts",
|
|
861
|
+
"blocks/pricing-01/pricing-01.html",
|
|
862
|
+
"blocks/pricing-01/index.ts"
|
|
863
|
+
],
|
|
864
|
+
"registryDependencies": [
|
|
865
|
+
"badge",
|
|
866
|
+
"button",
|
|
867
|
+
"toggle-group",
|
|
868
|
+
"utils/cn"
|
|
869
|
+
]
|
|
673
870
|
}
|
|
674
871
|
}
|
|
675
872
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './login-01';
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
<!-- Trama de puntos de fondo (solo escritorio). La máscara usa solo el canal alfa. -->
|
|
2
|
+
<div
|
|
3
|
+
aria-hidden="true"
|
|
4
|
+
class="pointer-events-none absolute inset-0 -z-10 hidden bg-[radial-gradient(color-mix(in_oklab,var(--mimi-foreground)_14%,transparent)_1px,transparent_1px)] bg-size-[18px_18px] mask-[radial-gradient(ellipse_at_50%_40%,var(--mimi-foreground)_30%,transparent_75%)] sm:block"
|
|
5
|
+
></div>
|
|
6
|
+
|
|
7
|
+
<mimi-card
|
|
8
|
+
class="w-full gap-[18px] border-0 bg-transparent p-0 shadow-none sm:max-w-[400px] sm:border sm:bg-card sm:p-8 sm:shadow-card"
|
|
9
|
+
>
|
|
10
|
+
<form
|
|
11
|
+
novalidate
|
|
12
|
+
class="flex flex-col gap-[18px]"
|
|
13
|
+
[attr.aria-labelledby]="id + '-title'"
|
|
14
|
+
(submit)="onSubmit($event)"
|
|
15
|
+
>
|
|
16
|
+
<div class="flex flex-col items-center gap-2.5 text-center">
|
|
17
|
+
<span
|
|
18
|
+
aria-hidden="true"
|
|
19
|
+
class="inline-flex size-10 items-center justify-center rounded-[12px] bg-primary text-[22px] leading-none font-extrabold text-primary-foreground shadow-primary"
|
|
20
|
+
>m</span
|
|
21
|
+
>
|
|
22
|
+
<h1 [id]="id + '-title'" class="text-2xl font-extrabold tracking-[-0.02em]">Sign in</h1>
|
|
23
|
+
<p class="text-sm text-muted-foreground">Welcome back to Mimi Sales.</p>
|
|
24
|
+
</div>
|
|
25
|
+
|
|
26
|
+
<div class="grid grid-cols-1 gap-2.5 sm:grid-cols-2">
|
|
27
|
+
<button
|
|
28
|
+
mimiBtn
|
|
29
|
+
type="button"
|
|
30
|
+
variant="outline"
|
|
31
|
+
tone="secondary"
|
|
32
|
+
(click)="provider.emit('google')"
|
|
33
|
+
>
|
|
34
|
+
<!-- La «G» del diseño, una letra en un círculo (no el logotipo de Google). -->
|
|
35
|
+
<span
|
|
36
|
+
aria-hidden="true"
|
|
37
|
+
class="inline-flex size-[18px] items-center justify-center rounded-full border-[1.5px] border-current text-[11px] font-extrabold"
|
|
38
|
+
>G</span
|
|
39
|
+
>
|
|
40
|
+
Google
|
|
41
|
+
</button>
|
|
42
|
+
<button
|
|
43
|
+
mimiBtn
|
|
44
|
+
type="button"
|
|
45
|
+
variant="outline"
|
|
46
|
+
tone="secondary"
|
|
47
|
+
(click)="provider.emit('github')"
|
|
48
|
+
>
|
|
49
|
+
<svg
|
|
50
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
51
|
+
width="17"
|
|
52
|
+
height="17"
|
|
53
|
+
viewBox="0 0 24 24"
|
|
54
|
+
fill="none"
|
|
55
|
+
stroke="currentColor"
|
|
56
|
+
stroke-width="2"
|
|
57
|
+
stroke-linecap="round"
|
|
58
|
+
stroke-linejoin="round"
|
|
59
|
+
aria-hidden="true"
|
|
60
|
+
>
|
|
61
|
+
<!-- Lucide github (ISC) -->
|
|
62
|
+
<path
|
|
63
|
+
d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.403 5.403 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"
|
|
64
|
+
/>
|
|
65
|
+
<path d="M9 18c-4.51 2-5-2-7-2" />
|
|
66
|
+
</svg>
|
|
67
|
+
GitHub
|
|
68
|
+
</button>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<div class="flex items-center gap-3 text-xs text-muted-foreground">
|
|
72
|
+
<mimi-separator class="w-auto flex-1" />
|
|
73
|
+
or with your email
|
|
74
|
+
<mimi-separator class="w-auto flex-1" />
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
<mimi-form-field label="Email">
|
|
78
|
+
<input mimiInput type="email" autocomplete="email" [formField]="login.email" />
|
|
79
|
+
</mimi-form-field>
|
|
80
|
+
|
|
81
|
+
<mimi-form-field class="relative">
|
|
82
|
+
<label [attr.for]="id + '-password'" class="text-sm font-medium">Password</label>
|
|
83
|
+
<a
|
|
84
|
+
[href]="forgotHref()"
|
|
85
|
+
class="absolute top-0 right-0 rounded-sm text-[13px] font-medium text-muted-foreground underline underline-offset-3 hover:text-foreground focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring"
|
|
86
|
+
>Forgot it?</a
|
|
87
|
+
>
|
|
88
|
+
<mimi-password>
|
|
89
|
+
<input
|
|
90
|
+
mimiInput
|
|
91
|
+
type="password"
|
|
92
|
+
autocomplete="current-password"
|
|
93
|
+
[id]="id + '-password'"
|
|
94
|
+
[formField]="login.password"
|
|
95
|
+
/>
|
|
96
|
+
</mimi-password>
|
|
97
|
+
</mimi-form-field>
|
|
98
|
+
|
|
99
|
+
<div class="flex items-center gap-2.5">
|
|
100
|
+
<mimi-checkbox [id]="id + '-remember'" [formField]="login.remember" />
|
|
101
|
+
<label [attr.for]="id + '-remember'" class="cursor-pointer text-sm"
|
|
102
|
+
>Remember me for 30 days</label
|
|
103
|
+
>
|
|
104
|
+
</div>
|
|
105
|
+
|
|
106
|
+
<!-- Siempre en la página: así el lector anuncia el error cuando aparece. -->
|
|
107
|
+
<div role="alert" class="empty:hidden">
|
|
108
|
+
@if (error(); as message) {
|
|
109
|
+
<p
|
|
110
|
+
class="flex items-start gap-2 rounded-[var(--mimi-radius)] bg-destructive-soft-bg px-3 py-2.5 text-sm text-destructive-soft-foreground"
|
|
111
|
+
>
|
|
112
|
+
<svg
|
|
113
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
114
|
+
width="16"
|
|
115
|
+
height="16"
|
|
116
|
+
viewBox="0 0 24 24"
|
|
117
|
+
fill="none"
|
|
118
|
+
stroke="currentColor"
|
|
119
|
+
stroke-width="2"
|
|
120
|
+
stroke-linecap="round"
|
|
121
|
+
stroke-linejoin="round"
|
|
122
|
+
aria-hidden="true"
|
|
123
|
+
class="mt-0.5 shrink-0"
|
|
124
|
+
>
|
|
125
|
+
<!-- Lucide circle-alert (ISC) -->
|
|
126
|
+
<circle cx="12" cy="12" r="10" />
|
|
127
|
+
<line x1="12" x2="12" y1="8" y2="12" />
|
|
128
|
+
<line x1="12" x2="12.01" y1="16" y2="16" />
|
|
129
|
+
</svg>
|
|
130
|
+
{{ message }}
|
|
131
|
+
</p>
|
|
132
|
+
}
|
|
133
|
+
</div>
|
|
134
|
+
|
|
135
|
+
<button
|
|
136
|
+
mimiBtn
|
|
137
|
+
type="submit"
|
|
138
|
+
class="h-[calc(var(--mimi-control-height,2.5rem)+4px)] text-[15px] font-semibold"
|
|
139
|
+
[attr.aria-disabled]="loading() ? 'true' : null"
|
|
140
|
+
[attr.aria-busy]="loading() ? 'true' : null"
|
|
141
|
+
>
|
|
142
|
+
@if (loading()) {
|
|
143
|
+
<svg
|
|
144
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
145
|
+
width="16"
|
|
146
|
+
height="16"
|
|
147
|
+
viewBox="0 0 24 24"
|
|
148
|
+
fill="none"
|
|
149
|
+
stroke="currentColor"
|
|
150
|
+
stroke-width="2"
|
|
151
|
+
stroke-linecap="round"
|
|
152
|
+
stroke-linejoin="round"
|
|
153
|
+
aria-hidden="true"
|
|
154
|
+
class="motion-safe:animate-[mimi-spin_0.8s_linear_infinite]"
|
|
155
|
+
>
|
|
156
|
+
<!-- Lucide loader-circle (ISC) -->
|
|
157
|
+
<path d="M21 12a9 9 0 1 1-6.219-8.56" />
|
|
158
|
+
</svg>
|
|
159
|
+
Signing in…
|
|
160
|
+
} @else {
|
|
161
|
+
Sign in
|
|
162
|
+
}
|
|
163
|
+
</button>
|
|
164
|
+
|
|
165
|
+
<p class="text-center text-sm text-muted-foreground">
|
|
166
|
+
Don't have an account?
|
|
167
|
+
<a
|
|
168
|
+
[href]="signupHref()"
|
|
169
|
+
class="rounded-sm font-semibold text-foreground underline underline-offset-3 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring"
|
|
170
|
+
>Sign up</a
|
|
171
|
+
>
|
|
172
|
+
</p>
|
|
173
|
+
</form>
|
|
174
|
+
</mimi-card>
|