@mimi-ng/cli 0.2.0 → 0.4.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 (79) hide show
  1. package/README.md +35 -2
  2. package/dist/init/css.js +1 -1
  3. package/dist/init/index.js +25 -0
  4. package/dist/init/paths.js +20 -0
  5. package/dist/registry.json +385 -14
  6. package/dist/templates/blocks/login-01/index.ts +1 -0
  7. package/dist/templates/blocks/login-01/login-01.html +174 -0
  8. package/dist/templates/blocks/login-01/login-01.ts +105 -0
  9. package/dist/templates/blocks/login-02/index.ts +1 -0
  10. package/dist/templates/blocks/login-02/login-02.html +186 -0
  11. package/dist/templates/blocks/login-02/login-02.ts +92 -0
  12. package/dist/templates/blocks/otp-01/index.ts +1 -0
  13. package/dist/templates/blocks/otp-01/otp-01.html +166 -0
  14. package/dist/templates/blocks/otp-01/otp-01.ts +212 -0
  15. package/dist/templates/blocks/pricing-01/index.ts +1 -0
  16. package/dist/templates/blocks/pricing-01/pricing-01.html +173 -0
  17. package/dist/templates/blocks/pricing-01/pricing-01.ts +178 -0
  18. package/dist/templates/blocks/settings-01/index.ts +1 -0
  19. package/dist/templates/blocks/settings-01/settings-01.html +424 -0
  20. package/dist/templates/blocks/settings-01/settings-01.ts +382 -0
  21. package/dist/templates/blocks/signup-01/index.ts +1 -0
  22. package/dist/templates/blocks/signup-01/signup-01.html +332 -0
  23. package/dist/templates/blocks/signup-01/signup-01.ts +176 -0
  24. package/dist/templates/components/calendar/calendar-texts.ts +72 -0
  25. package/dist/templates/components/calendar/calendar.ts +588 -0
  26. package/dist/templates/components/calendar/dates.ts +181 -0
  27. package/dist/templates/components/calendar/index.ts +3 -0
  28. package/dist/templates/components/chip/chip-texts.ts +40 -0
  29. package/dist/templates/components/chip/chip.ts +116 -0
  30. package/dist/templates/components/chip/index.ts +2 -0
  31. package/dist/templates/components/color-picker/color-picker-texts.ts +57 -0
  32. package/dist/templates/components/color-picker/color-picker.ts +718 -0
  33. package/dist/templates/components/color-picker/color.ts +157 -0
  34. package/dist/templates/components/color-picker/index.ts +3 -0
  35. package/dist/templates/components/combobox/combobox-texts.ts +70 -0
  36. package/dist/templates/components/combobox/combobox.ts +798 -0
  37. package/dist/templates/components/combobox/index.ts +2 -0
  38. package/dist/templates/components/date-picker/date-picker.ts +240 -0
  39. package/dist/templates/components/date-picker/index.ts +3 -0
  40. package/dist/templates/components/date-range/date-range.ts +308 -0
  41. package/dist/templates/components/date-range/index.ts +1 -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/input-mask/index.ts +1 -0
  46. package/dist/templates/components/input-mask/input-mask.ts +319 -0
  47. package/dist/templates/components/input-otp/index.ts +1 -0
  48. package/dist/templates/components/input-otp/input-otp.ts +212 -0
  49. package/dist/templates/components/number-input/index.ts +2 -0
  50. package/dist/templates/components/number-input/number-input-texts.ts +46 -0
  51. package/dist/templates/components/number-input/number-input.ts +450 -0
  52. package/dist/templates/components/option-list/index.ts +11 -0
  53. package/dist/templates/components/option-list/option-list.ts +518 -0
  54. package/dist/templates/components/password/index.ts +2 -0
  55. package/dist/templates/components/password/password-texts.ts +68 -0
  56. package/dist/templates/components/password/password.ts +363 -0
  57. package/dist/templates/components/popover/popover.ts +12 -4
  58. package/dist/templates/components/progress/index.ts +1 -0
  59. package/dist/templates/components/progress/progress.ts +217 -0
  60. package/dist/templates/components/select/select.ts +3 -2
  61. package/dist/templates/components/slider/index.ts +2 -0
  62. package/dist/templates/components/slider/slider-texts.ts +26 -0
  63. package/dist/templates/components/slider/slider.ts +425 -0
  64. package/dist/templates/components/tabs/tabs.ts +88 -23
  65. package/dist/templates/components/tags-input/index.ts +2 -0
  66. package/dist/templates/components/tags-input/tags-input-texts.ts +44 -0
  67. package/dist/templates/components/tags-input/tags-input.ts +303 -0
  68. package/dist/templates/components/toggle-group/index.ts +1 -0
  69. package/dist/templates/components/toggle-group/toggle-group.ts +406 -0
  70. package/dist/templates/theme/provider.ts +13 -0
  71. package/dist/templates/theme/theme-base.css +103 -0
  72. package/dist/templates/theme/types.ts +216 -0
  73. package/dist/templates/utils/overlay.ts +17 -4
  74. package/dist/ui/index.js +232 -10
  75. package/dist/ui/schema.json +82 -2
  76. package/dist/utils/project.js +35 -0
  77. package/dist/utils/tailwind.js +80 -0
  78. package/dist/utils/write-files.js +49 -9
  79. package/package.json +1 -1
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "0.2.0",
2
+ "version": "0.4.0",
3
3
  "suggestedDependencies": {
4
4
  "@lucide/angular": "^1.47.0"
5
5
  },
@@ -35,7 +35,7 @@
35
35
  "utils/overlay.ts"
36
36
  ],
37
37
  "peerDependencies": {
38
- "@angular/cdk": "^22.2.0"
38
+ "@angular/cdk": "^22.2.4"
39
39
  }
40
40
  },
41
41
  "menu": {
@@ -45,13 +45,41 @@
45
45
  "components/menu/index.ts"
46
46
  ],
47
47
  "peerDependencies": {
48
- "@angular/aria": "^22.2.0"
48
+ "@angular/aria": "^22.2.4"
49
49
  },
50
50
  "registryDependencies": [
51
51
  "utils/cn",
52
52
  "utils/overlay"
53
53
  ]
54
54
  },
55
+ "chip": {
56
+ "type": "util",
57
+ "files": [
58
+ "components/chip/chip.ts",
59
+ "components/chip/chip-texts.ts",
60
+ "components/chip/index.ts"
61
+ ],
62
+ "peerDependencies": {
63
+ "@angular/cdk": "^22.2.4"
64
+ },
65
+ "registryDependencies": [
66
+ "utils/cn",
67
+ "utils/control-styles"
68
+ ]
69
+ },
70
+ "option-list": {
71
+ "type": "util",
72
+ "files": [
73
+ "components/option-list/option-list.ts",
74
+ "components/option-list/index.ts"
75
+ ],
76
+ "peerDependencies": {
77
+ "@angular/aria": "^22.2.4"
78
+ },
79
+ "registryDependencies": [
80
+ "utils/cn"
81
+ ]
82
+ },
55
83
  "theme": {
56
84
  "type": "theme",
57
85
  "files": [
@@ -149,7 +177,7 @@
149
177
  "components/context-menu/index.ts"
150
178
  ],
151
179
  "peerDependencies": {
152
- "@angular/cdk": "^22.2.0"
180
+ "@angular/cdk": "^22.2.4"
153
181
  },
154
182
  "cssImports": [
155
183
  "@angular/cdk/overlay-prebuilt.css"
@@ -167,7 +195,7 @@
167
195
  "components/dialog/index.ts"
168
196
  ],
169
197
  "peerDependencies": {
170
- "@angular/cdk": "^22.2.0"
198
+ "@angular/cdk": "^22.2.4"
171
199
  },
172
200
  "cssImports": [
173
201
  "@angular/cdk/overlay-prebuilt.css"
@@ -188,7 +216,7 @@
188
216
  "class-variance-authority": "^0.7.1"
189
217
  },
190
218
  "peerDependencies": {
191
- "@angular/aria": "^22.2.0"
219
+ "@angular/aria": "^22.2.4"
192
220
  },
193
221
  "registryDependencies": [
194
222
  "utils/cn",
@@ -207,7 +235,7 @@
207
235
  "class-variance-authority": "^0.7.1"
208
236
  },
209
237
  "peerDependencies": {
210
- "@angular/cdk": "^22.2.0"
238
+ "@angular/cdk": "^22.2.4"
211
239
  },
212
240
  "registryDependencies": [
213
241
  "button",
@@ -228,7 +256,7 @@
228
256
  "class-variance-authority": "^0.7.1"
229
257
  },
230
258
  "peerDependencies": {
231
- "@angular/cdk": "^22.2.0"
259
+ "@angular/cdk": "^22.2.4"
232
260
  },
233
261
  "registryDependencies": [
234
262
  "button",
@@ -237,6 +265,238 @@
237
265
  "utils/cn"
238
266
  ]
239
267
  },
268
+ "input-mask": {
269
+ "type": "component",
270
+ "files": [
271
+ "components/input-mask/input-mask.ts",
272
+ "components/input-mask/index.ts"
273
+ ],
274
+ "peerDependencies": {
275
+ "@angular/forms": "^22.0.0"
276
+ },
277
+ "registryDependencies": [
278
+ "utils/cn",
279
+ "utils/field-state"
280
+ ]
281
+ },
282
+ "input-otp": {
283
+ "type": "component",
284
+ "files": [
285
+ "components/input-otp/input-otp.ts",
286
+ "components/input-otp/index.ts"
287
+ ],
288
+ "peerDependencies": {
289
+ "@angular/forms": "^22.0.0"
290
+ },
291
+ "registryDependencies": [
292
+ "utils/cn",
293
+ "utils/field-state"
294
+ ]
295
+ },
296
+ "number-input": {
297
+ "type": "component",
298
+ "files": [
299
+ "components/number-input/number-input.ts",
300
+ "components/number-input/number-input-texts.ts",
301
+ "components/number-input/index.ts"
302
+ ],
303
+ "peerDependencies": {
304
+ "@angular/forms": "^22.0.0"
305
+ },
306
+ "registryDependencies": [
307
+ "utils/cn",
308
+ "utils/field-state"
309
+ ]
310
+ },
311
+ "password": {
312
+ "type": "component",
313
+ "files": [
314
+ "components/password/password.ts",
315
+ "components/password/password-texts.ts",
316
+ "components/password/index.ts"
317
+ ],
318
+ "peerDependencies": {
319
+ "@angular/cdk": "^22.2.4"
320
+ },
321
+ "registryDependencies": [
322
+ "input",
323
+ "utils/cn",
324
+ "utils/control-styles"
325
+ ]
326
+ },
327
+ "progress": {
328
+ "type": "component",
329
+ "files": [
330
+ "components/progress/progress.ts",
331
+ "components/progress/index.ts"
332
+ ],
333
+ "registryDependencies": [
334
+ "utils/cn"
335
+ ]
336
+ },
337
+ "slider": {
338
+ "type": "component",
339
+ "files": [
340
+ "components/slider/slider.ts",
341
+ "components/slider/slider-texts.ts",
342
+ "components/slider/index.ts"
343
+ ],
344
+ "peerDependencies": {
345
+ "@angular/cdk": "^22.2.4",
346
+ "@angular/forms": "^22.0.0"
347
+ },
348
+ "registryDependencies": [
349
+ "utils/cn",
350
+ "utils/control-styles",
351
+ "utils/field-state"
352
+ ]
353
+ },
354
+ "combobox": {
355
+ "type": "component",
356
+ "files": [
357
+ "components/combobox/combobox.ts",
358
+ "components/combobox/combobox-texts.ts",
359
+ "components/combobox/index.ts"
360
+ ],
361
+ "peerDependencies": {
362
+ "@angular/aria": "^22.2.4",
363
+ "@angular/cdk": "^22.2.4",
364
+ "@angular/forms": "^22.0.0"
365
+ },
366
+ "cssImports": [
367
+ "@angular/cdk/overlay-prebuilt.css"
368
+ ],
369
+ "registryDependencies": [
370
+ "chip",
371
+ "option-list",
372
+ "utils/cn",
373
+ "utils/field-state",
374
+ "utils/overlay"
375
+ ]
376
+ },
377
+ "calendar": {
378
+ "type": "component",
379
+ "files": [
380
+ "components/calendar/calendar.ts",
381
+ "components/calendar/calendar-texts.ts",
382
+ "components/calendar/dates.ts",
383
+ "components/calendar/index.ts"
384
+ ],
385
+ "peerDependencies": {
386
+ "@angular/cdk": "^22.2.4"
387
+ },
388
+ "registryDependencies": [
389
+ "utils/cn",
390
+ "utils/control-styles"
391
+ ]
392
+ },
393
+ "date-picker": {
394
+ "type": "component",
395
+ "files": [
396
+ "components/date-picker/date-picker.ts",
397
+ "components/date-picker/index.ts"
398
+ ],
399
+ "peerDependencies": {
400
+ "@angular/forms": "^22.0.0"
401
+ },
402
+ "registryDependencies": [
403
+ "calendar",
404
+ "popover",
405
+ "utils/cn",
406
+ "utils/control-styles",
407
+ "utils/field-state"
408
+ ]
409
+ },
410
+ "date-range": {
411
+ "type": "component",
412
+ "files": [
413
+ "components/date-range/date-range.ts",
414
+ "components/date-range/index.ts"
415
+ ],
416
+ "peerDependencies": {
417
+ "@angular/forms": "^22.0.0"
418
+ },
419
+ "registryDependencies": [
420
+ "calendar",
421
+ "date-picker",
422
+ "popover",
423
+ "utils/cn",
424
+ "utils/control-styles",
425
+ "utils/field-state"
426
+ ]
427
+ },
428
+ "file-upload": {
429
+ "type": "component",
430
+ "files": [
431
+ "components/file-upload/file-upload.ts",
432
+ "components/file-upload/file-upload-texts.ts",
433
+ "components/file-upload/index.ts"
434
+ ],
435
+ "peerDependencies": {
436
+ "@angular/cdk": "^22.2.4",
437
+ "@angular/forms": "^22.0.0"
438
+ },
439
+ "registryDependencies": [
440
+ "button",
441
+ "progress",
442
+ "utils/cn",
443
+ "utils/control-styles",
444
+ "utils/field-state"
445
+ ]
446
+ },
447
+ "color-picker": {
448
+ "type": "component",
449
+ "files": [
450
+ "components/color-picker/color-picker.ts",
451
+ "components/color-picker/color-picker-texts.ts",
452
+ "components/color-picker/color.ts",
453
+ "components/color-picker/index.ts"
454
+ ],
455
+ "peerDependencies": {
456
+ "@angular/forms": "^22.0.0"
457
+ },
458
+ "registryDependencies": [
459
+ "input",
460
+ "popover",
461
+ "utils/cn",
462
+ "utils/control-styles",
463
+ "utils/field-state"
464
+ ]
465
+ },
466
+ "tags-input": {
467
+ "type": "component",
468
+ "files": [
469
+ "components/tags-input/tags-input.ts",
470
+ "components/tags-input/tags-input-texts.ts",
471
+ "components/tags-input/index.ts"
472
+ ],
473
+ "peerDependencies": {
474
+ "@angular/forms": "^22.0.0"
475
+ },
476
+ "registryDependencies": [
477
+ "chip",
478
+ "utils/cn",
479
+ "utils/field-state"
480
+ ]
481
+ },
482
+ "toggle-group": {
483
+ "type": "component",
484
+ "files": [
485
+ "components/toggle-group/toggle-group.ts",
486
+ "components/toggle-group/index.ts"
487
+ ],
488
+ "dependencies": {
489
+ "class-variance-authority": "^0.7.1"
490
+ },
491
+ "peerDependencies": {
492
+ "@angular/cdk": "^22.2.4",
493
+ "@angular/forms": "^22.0.0"
494
+ },
495
+ "registryDependencies": [
496
+ "utils/cn",
497
+ "utils/control-styles"
498
+ ]
499
+ },
240
500
  "toolbar": {
241
501
  "type": "component",
242
502
  "files": [
@@ -247,7 +507,7 @@
247
507
  "class-variance-authority": "^0.7.1"
248
508
  },
249
509
  "peerDependencies": {
250
- "@angular/cdk": "^22.2.0"
510
+ "@angular/cdk": "^22.2.4"
251
511
  },
252
512
  "registryDependencies": [
253
513
  "utils/cn",
@@ -261,7 +521,7 @@
261
521
  "components/dropdown-menu/index.ts"
262
522
  ],
263
523
  "peerDependencies": {
264
- "@angular/cdk": "^22.2.0"
524
+ "@angular/cdk": "^22.2.4"
265
525
  },
266
526
  "cssImports": [
267
527
  "@angular/cdk/overlay-prebuilt.css"
@@ -307,7 +567,7 @@
307
567
  "components/popover/index.ts"
308
568
  ],
309
569
  "peerDependencies": {
310
- "@angular/cdk": "^22.2.0"
570
+ "@angular/cdk": "^22.2.4"
311
571
  },
312
572
  "cssImports": [
313
573
  "@angular/cdk/overlay-prebuilt.css"
@@ -325,8 +585,8 @@
325
585
  "components/select/index.ts"
326
586
  ],
327
587
  "peerDependencies": {
328
- "@angular/aria": "^22.2.0",
329
- "@angular/cdk": "^22.2.0",
588
+ "@angular/aria": "^22.2.4",
589
+ "@angular/cdk": "^22.2.4",
330
590
  "@angular/forms": "^22.0.0"
331
591
  },
332
592
  "cssImports": [
@@ -385,7 +645,7 @@
385
645
  "components/tooltip/index.ts"
386
646
  ],
387
647
  "peerDependencies": {
388
- "@angular/cdk": "^22.2.0"
648
+ "@angular/cdk": "^22.2.4"
389
649
  },
390
650
  "cssImports": [
391
651
  "@angular/cdk/overlay-prebuilt.css"
@@ -410,6 +670,117 @@
410
670
  "utils/control-styles",
411
671
  "utils/field-state"
412
672
  ]
673
+ },
674
+ "login-01": {
675
+ "type": "block",
676
+ "files": [
677
+ "blocks/login-01/login-01.ts",
678
+ "blocks/login-01/login-01.html",
679
+ "blocks/login-01/index.ts"
680
+ ],
681
+ "peerDependencies": {
682
+ "@angular/forms": "^22.0.0"
683
+ },
684
+ "registryDependencies": [
685
+ "button",
686
+ "card",
687
+ "checkbox",
688
+ "form-field",
689
+ "input",
690
+ "password",
691
+ "separator",
692
+ "utils/cn"
693
+ ]
694
+ },
695
+ "login-02": {
696
+ "type": "block",
697
+ "files": [
698
+ "blocks/login-02/login-02.ts",
699
+ "blocks/login-02/login-02.html",
700
+ "blocks/login-02/index.ts"
701
+ ],
702
+ "peerDependencies": {
703
+ "@angular/forms": "^22.0.0"
704
+ },
705
+ "registryDependencies": [
706
+ "avatar",
707
+ "button",
708
+ "form-field",
709
+ "input",
710
+ "utils/cn"
711
+ ]
712
+ },
713
+ "signup-01": {
714
+ "type": "block",
715
+ "files": [
716
+ "blocks/signup-01/signup-01.ts",
717
+ "blocks/signup-01/signup-01.html",
718
+ "blocks/signup-01/index.ts"
719
+ ],
720
+ "peerDependencies": {
721
+ "@angular/forms": "^22.0.0"
722
+ },
723
+ "registryDependencies": [
724
+ "button",
725
+ "checkbox",
726
+ "form-field",
727
+ "input",
728
+ "password",
729
+ "utils/cn"
730
+ ]
731
+ },
732
+ "otp-01": {
733
+ "type": "block",
734
+ "files": [
735
+ "blocks/otp-01/otp-01.ts",
736
+ "blocks/otp-01/otp-01.html",
737
+ "blocks/otp-01/index.ts"
738
+ ],
739
+ "registryDependencies": [
740
+ "button",
741
+ "card",
742
+ "input-otp",
743
+ "utils/cn"
744
+ ]
745
+ },
746
+ "settings-01": {
747
+ "type": "block",
748
+ "files": [
749
+ "blocks/settings-01/settings-01.ts",
750
+ "blocks/settings-01/settings-01.html",
751
+ "blocks/settings-01/index.ts"
752
+ ],
753
+ "peerDependencies": {
754
+ "@angular/forms": "^22.0.0"
755
+ },
756
+ "registryDependencies": [
757
+ "avatar",
758
+ "badge",
759
+ "button",
760
+ "card",
761
+ "form-field",
762
+ "input",
763
+ "progress",
764
+ "separator",
765
+ "switch",
766
+ "tabs",
767
+ "textarea",
768
+ "utils/cn"
769
+ ]
770
+ },
771
+ "pricing-01": {
772
+ "type": "block",
773
+ "files": [
774
+ "blocks/pricing-01/pricing-01.ts",
775
+ "blocks/pricing-01/pricing-01.html",
776
+ "blocks/pricing-01/index.ts"
777
+ ],
778
+ "registryDependencies": [
779
+ "badge",
780
+ "button",
781
+ "toggle-group",
782
+ "utils/cn"
783
+ ]
413
784
  }
414
785
  }
415
786
  }
@@ -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>