@moni-labs/moni-ui 0.3.0 → 0.3.2

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 (251) hide show
  1. package/custom-elements.json +5230 -1007
  2. package/dist/components/_base/moni-element.d.ts +16 -9
  3. package/dist/components/_base/moni-element.d.ts.map +1 -1
  4. package/dist/components/_base/moni-element.js +63 -9
  5. package/dist/components/index.js +2 -2
  6. package/dist/components/loading-shapes.d.ts +19 -0
  7. package/dist/components/loading-shapes.d.ts.map +1 -1
  8. package/dist/components/loading-shapes.js +19 -0
  9. package/dist/components/moni-app-bar.d.ts +72 -62
  10. package/dist/components/moni-app-bar.d.ts.map +1 -1
  11. package/dist/components/moni-app-bar.js +72 -62
  12. package/dist/components/moni-badge.d.ts +64 -65
  13. package/dist/components/moni-badge.d.ts.map +1 -1
  14. package/dist/components/moni-badge.js +64 -66
  15. package/dist/components/moni-bottom-sheet.d.ts +129 -61
  16. package/dist/components/moni-bottom-sheet.d.ts.map +1 -1
  17. package/dist/components/moni-bottom-sheet.js +217 -131
  18. package/dist/components/moni-button-group.d.ts +107 -29
  19. package/dist/components/moni-button-group.d.ts.map +1 -1
  20. package/dist/components/moni-button-group.js +107 -29
  21. package/dist/components/moni-button-segment.d.ts +53 -12
  22. package/dist/components/moni-button-segment.d.ts.map +1 -1
  23. package/dist/components/moni-button-segment.js +53 -12
  24. package/dist/components/moni-button.d.ts +116 -38
  25. package/dist/components/moni-button.d.ts.map +1 -1
  26. package/dist/components/moni-button.js +128 -38
  27. package/dist/components/moni-card.d.ts +68 -50
  28. package/dist/components/moni-card.d.ts.map +1 -1
  29. package/dist/components/moni-card.js +68 -50
  30. package/dist/components/moni-carousel.d.ts +484 -53
  31. package/dist/components/moni-carousel.d.ts.map +1 -1
  32. package/dist/components/moni-carousel.js +1024 -245
  33. package/dist/components/moni-checkbox.d.ts +49 -46
  34. package/dist/components/moni-checkbox.d.ts.map +1 -1
  35. package/dist/components/moni-checkbox.js +55 -48
  36. package/dist/components/moni-chip.d.ts +100 -33
  37. package/dist/components/moni-chip.d.ts.map +1 -1
  38. package/dist/components/moni-chip.js +104 -34
  39. package/dist/components/moni-color-field.d.ts +99 -24
  40. package/dist/components/moni-color-field.d.ts.map +1 -1
  41. package/dist/components/moni-color-field.js +99 -24
  42. package/dist/components/moni-context-menu.d.ts +72 -26
  43. package/dist/components/moni-context-menu.d.ts.map +1 -1
  44. package/dist/components/moni-context-menu.js +76 -30
  45. package/dist/components/moni-dialog.d.ts +84 -59
  46. package/dist/components/moni-dialog.d.ts.map +1 -1
  47. package/dist/components/moni-dialog.js +105 -58
  48. package/dist/components/moni-divider.d.ts +39 -27
  49. package/dist/components/moni-divider.d.ts.map +1 -1
  50. package/dist/components/moni-divider.js +42 -30
  51. package/dist/components/moni-expansion.d.ts +32 -22
  52. package/dist/components/moni-expansion.d.ts.map +1 -1
  53. package/dist/components/moni-expansion.js +32 -22
  54. package/dist/components/moni-fab-menu.d.ts +61 -23
  55. package/dist/components/moni-fab-menu.d.ts.map +1 -1
  56. package/dist/components/moni-fab-menu.js +69 -31
  57. package/dist/components/moni-fab.d.ts +86 -28
  58. package/dist/components/moni-fab.d.ts.map +1 -1
  59. package/dist/components/moni-fab.js +92 -34
  60. package/dist/components/moni-file-field.d.ts +118 -30
  61. package/dist/components/moni-file-field.d.ts.map +1 -1
  62. package/dist/components/moni-file-field.js +118 -30
  63. package/dist/components/moni-icon.d.ts +40 -35
  64. package/dist/components/moni-icon.d.ts.map +1 -1
  65. package/dist/components/moni-icon.js +43 -38
  66. package/dist/components/moni-list-item.d.ts +46 -33
  67. package/dist/components/moni-list-item.d.ts.map +1 -1
  68. package/dist/components/moni-list-item.js +61 -41
  69. package/dist/components/moni-list.d.ts +30 -20
  70. package/dist/components/moni-list.d.ts.map +1 -1
  71. package/dist/components/moni-list.js +36 -21
  72. package/dist/components/moni-loading-indicator.d.ts +54 -22
  73. package/dist/components/moni-loading-indicator.d.ts.map +1 -1
  74. package/dist/components/moni-loading-indicator.js +54 -22
  75. package/dist/components/moni-menu-item.d.ts +23 -16
  76. package/dist/components/moni-menu-item.d.ts.map +1 -1
  77. package/dist/components/moni-menu-item.js +23 -16
  78. package/dist/components/moni-menu.d.ts +81 -28
  79. package/dist/components/moni-menu.d.ts.map +1 -1
  80. package/dist/components/moni-menu.js +81 -30
  81. package/dist/components/moni-morph-modal.d.ts +141 -0
  82. package/dist/components/moni-morph-modal.d.ts.map +1 -1
  83. package/dist/components/moni-morph-modal.js +295 -58
  84. package/dist/components/moni-nav-item.d.ts +59 -29
  85. package/dist/components/moni-nav-item.d.ts.map +1 -1
  86. package/dist/components/moni-nav-item.js +59 -29
  87. package/dist/components/moni-nav.d.ts +94 -35
  88. package/dist/components/moni-nav.d.ts.map +1 -1
  89. package/dist/components/moni-nav.js +94 -35
  90. package/dist/components/moni-progress.d.ts +99 -55
  91. package/dist/components/moni-progress.d.ts.map +1 -1
  92. package/dist/components/moni-progress.js +99 -55
  93. package/dist/components/moni-radio.d.ts +62 -50
  94. package/dist/components/moni-radio.d.ts.map +1 -1
  95. package/dist/components/moni-radio.js +65 -52
  96. package/dist/components/moni-ripple.d.ts +74 -59
  97. package/dist/components/moni-ripple.d.ts.map +1 -1
  98. package/dist/components/moni-ripple.js +74 -59
  99. package/dist/components/moni-segmented-button.d.ts +91 -16
  100. package/dist/components/moni-segmented-button.d.ts.map +1 -1
  101. package/dist/components/moni-segmented-button.js +94 -17
  102. package/dist/components/moni-select-option.d.ts +30 -23
  103. package/dist/components/moni-select-option.d.ts.map +1 -1
  104. package/dist/components/moni-select-option.js +30 -23
  105. package/dist/components/moni-select.d.ts +300 -35
  106. package/dist/components/moni-select.d.ts.map +1 -1
  107. package/dist/components/moni-select.js +323 -39
  108. package/dist/components/moni-side-sheet.d.ts +94 -32
  109. package/dist/components/moni-side-sheet.d.ts.map +1 -1
  110. package/dist/components/moni-side-sheet.js +94 -32
  111. package/dist/components/moni-slider.d.ts +152 -41
  112. package/dist/components/moni-slider.d.ts.map +1 -1
  113. package/dist/components/moni-slider.js +154 -42
  114. package/dist/components/moni-snackbar.d.ts +53 -43
  115. package/dist/components/moni-snackbar.d.ts.map +1 -1
  116. package/dist/components/moni-snackbar.js +53 -43
  117. package/dist/components/moni-split-button.d.ts +63 -18
  118. package/dist/components/moni-split-button.d.ts.map +1 -1
  119. package/dist/components/moni-split-button.js +63 -18
  120. package/dist/components/moni-step.d.ts +36 -24
  121. package/dist/components/moni-step.d.ts.map +1 -1
  122. package/dist/components/moni-step.js +41 -29
  123. package/dist/components/moni-stepper.d.ts +64 -27
  124. package/dist/components/moni-stepper.d.ts.map +1 -1
  125. package/dist/components/moni-stepper.js +72 -34
  126. package/dist/components/moni-switch.d.ts +57 -46
  127. package/dist/components/moni-switch.d.ts.map +1 -1
  128. package/dist/components/moni-switch.js +59 -47
  129. package/dist/components/moni-tab.d.ts +26 -18
  130. package/dist/components/moni-tab.d.ts.map +1 -1
  131. package/dist/components/moni-tab.js +29 -21
  132. package/dist/components/moni-tabs.d.ts +34 -28
  133. package/dist/components/moni-tabs.d.ts.map +1 -1
  134. package/dist/components/moni-tabs.js +34 -28
  135. package/dist/components/moni-text-field.d.ts +139 -29
  136. package/dist/components/moni-text-field.d.ts.map +1 -1
  137. package/dist/components/moni-text-field.js +157 -31
  138. package/dist/components/moni-textarea.d.ts +127 -29
  139. package/dist/components/moni-textarea.d.ts.map +1 -1
  140. package/dist/components/moni-textarea.js +131 -32
  141. package/dist/components/moni-time-picker.d.ts +114 -24
  142. package/dist/components/moni-time-picker.d.ts.map +1 -1
  143. package/dist/components/moni-time-picker.js +127 -33
  144. package/dist/components/moni-toolbar.d.ts +37 -23
  145. package/dist/components/moni-toolbar.d.ts.map +1 -1
  146. package/dist/components/moni-toolbar.js +37 -23
  147. package/dist/components/moni-tooltip.d.ts +100 -36
  148. package/dist/components/moni-tooltip.d.ts.map +1 -1
  149. package/dist/components/moni-tooltip.js +104 -40
  150. package/dist/components/moni-typography.d.ts +68 -30
  151. package/dist/components/moni-typography.d.ts.map +1 -1
  152. package/dist/components/moni-typography.js +70 -32
  153. package/dist/styles/tokens.css +7 -7
  154. package/dist/types/events.d.ts +17 -0
  155. package/dist/types/events.d.ts.map +1 -0
  156. package/dist/types/events.js +1 -0
  157. package/dist/utils/event-emitter.d.ts +13 -0
  158. package/dist/utils/event-emitter.d.ts.map +1 -0
  159. package/dist/utils/event-emitter.js +13 -0
  160. package/package.json +2 -1
  161. package/src/components/_base/moni-element.ts +73 -9
  162. package/src/components/index.ts +2 -2
  163. package/src/components/loading-shapes.ts +19 -0
  164. package/src/components/moni-app-bar.test.ts +10 -10
  165. package/src/components/moni-app-bar.ts +72 -62
  166. package/src/components/moni-badge.ts +64 -66
  167. package/src/components/moni-bottom-sheet.test.ts +39 -45
  168. package/src/components/moni-bottom-sheet.ts +222 -131
  169. package/src/components/moni-button-group.test.ts +14 -14
  170. package/src/components/moni-button-group.ts +107 -29
  171. package/src/components/moni-button-segment.ts +53 -12
  172. package/src/components/moni-button.test.ts +28 -26
  173. package/src/components/moni-button.ts +139 -39
  174. package/src/components/moni-card.test.ts +6 -6
  175. package/src/components/moni-card.ts +70 -50
  176. package/src/components/moni-carousel.test.ts +12 -12
  177. package/src/components/moni-carousel.ts +1129 -269
  178. package/src/components/moni-checkbox.test.ts +7 -7
  179. package/src/components/moni-checkbox.ts +62 -48
  180. package/src/components/moni-chip.test.ts +17 -17
  181. package/src/components/moni-chip.ts +112 -34
  182. package/src/components/moni-color-field.test.ts +5 -5
  183. package/src/components/moni-color-field.ts +108 -24
  184. package/src/components/moni-context-menu.test.ts +11 -11
  185. package/src/components/moni-context-menu.ts +76 -30
  186. package/src/components/moni-dialog.ts +108 -59
  187. package/src/components/moni-divider.test.ts +4 -4
  188. package/src/components/moni-divider.ts +42 -30
  189. package/src/components/moni-expansion.ts +32 -22
  190. package/src/components/moni-fab-menu.test.ts +11 -11
  191. package/src/components/moni-fab-menu.ts +69 -31
  192. package/src/components/moni-fab.test.ts +16 -16
  193. package/src/components/moni-fab.ts +100 -34
  194. package/src/components/moni-file-field.test.ts +8 -8
  195. package/src/components/moni-file-field.ts +132 -30
  196. package/src/components/moni-icon.test.ts +11 -11
  197. package/src/components/moni-icon.ts +43 -38
  198. package/src/components/moni-list-item.test.ts +10 -10
  199. package/src/components/moni-list-item.ts +61 -41
  200. package/src/components/moni-list.ts +37 -21
  201. package/src/components/moni-loading-indicator.test.ts +3 -3
  202. package/src/components/moni-loading-indicator.ts +54 -22
  203. package/src/components/moni-menu-item.ts +23 -16
  204. package/src/components/moni-menu.test.ts +7 -7
  205. package/src/components/moni-menu.ts +87 -30
  206. package/src/components/moni-morph-modal.test.ts +18 -17
  207. package/src/components/moni-morph-modal.ts +327 -60
  208. package/src/components/moni-nav-item.ts +59 -29
  209. package/src/components/moni-nav.test.ts +11 -11
  210. package/src/components/moni-nav.ts +94 -35
  211. package/src/components/moni-progress.test.ts +9 -9
  212. package/src/components/moni-progress.ts +100 -56
  213. package/src/components/moni-radio.test.ts +8 -8
  214. package/src/components/moni-radio.ts +71 -51
  215. package/src/components/moni-ripple.ts +74 -59
  216. package/src/components/moni-segmented-button.test.ts +4 -4
  217. package/src/components/moni-segmented-button.ts +94 -17
  218. package/src/components/moni-select-option.ts +30 -23
  219. package/src/components/moni-select.test.ts +11 -11
  220. package/src/components/moni-select.ts +361 -50
  221. package/src/components/moni-side-sheet.test.ts +7 -7
  222. package/src/components/moni-side-sheet.ts +94 -32
  223. package/src/components/moni-slider.test.ts +7 -7
  224. package/src/components/moni-slider.ts +165 -42
  225. package/src/components/moni-snackbar.test.ts +8 -8
  226. package/src/components/moni-snackbar.ts +53 -43
  227. package/src/components/moni-split-button.ts +63 -18
  228. package/src/components/moni-step.test.ts +7 -7
  229. package/src/components/moni-step.ts +41 -29
  230. package/src/components/moni-stepper.test.ts +7 -7
  231. package/src/components/moni-stepper.ts +72 -34
  232. package/src/components/moni-switch.test.ts +12 -12
  233. package/src/components/moni-switch.ts +66 -47
  234. package/src/components/moni-tab.test.ts +5 -5
  235. package/src/components/moni-tab.ts +29 -21
  236. package/src/components/moni-tabs.ts +34 -28
  237. package/src/components/moni-text-field.test.ts +13 -13
  238. package/src/components/moni-text-field.ts +181 -30
  239. package/src/components/moni-textarea.test.ts +17 -17
  240. package/src/components/moni-textarea.ts +155 -31
  241. package/src/components/moni-time-picker.test.ts +5 -5
  242. package/src/components/moni-time-picker.ts +128 -33
  243. package/src/components/moni-toolbar.test.ts +8 -8
  244. package/src/components/moni-toolbar.ts +37 -23
  245. package/src/components/moni-tooltip.test.ts +15 -15
  246. package/src/components/moni-tooltip.ts +107 -40
  247. package/src/components/moni-typography.test.ts +10 -10
  248. package/src/components/moni-typography.ts +73 -32
  249. package/src/styles/tokens.css +7 -7
  250. package/src/types/events.ts +17 -0
  251. package/src/utils/event-emitter.ts +26 -0
@@ -13,59 +13,64 @@ import './moni-icon.js';
13
13
  import './moni-progress.js';
14
14
 
15
15
  /**
16
- * Material Design 3 Button component.
16
+ * Componente Material Design 3 Button.
17
17
  *
18
- * Buttons allow users to take actions and make choices with a single tap.
19
- * This component provides all M3 button variants, sizes, and shape morphing
20
- * capabilities (e.g. morphing to a pill shape on press or toggle).
18
+ * Los botones permiten a los usuarios realizar acciones y hacer elecciones con un solo toque.
19
+ * Este componente proporciona todas las variantes de botones de M3, tamaños y capacidades
20
+ * de transformación de formas (ej. cambiar a una forma de píldora al presionar o alternar).
21
21
  *
22
- * **M3 spec reference:** `m3-docs/components/buttons/specs.md`
22
+ * **Referencia de la especificación M3:** `m3-docs/components/buttons/specs.md`
23
23
  *
24
- * **Variants:**
25
- * - `filled` (default) — High emphasis. Use for primary actions.
26
- * - `tonal` — Medium emphasis. Secondary actions that still need to stand out.
27
- * - `elevated` — Medium emphasis with shadow. Used when sitting on patterned backgrounds.
28
- * - `outlined` — Medium emphasis, no fill. Secondary or tertiary actions.
29
- * - `text` — Low emphasis. Tertiary actions (e.g. dialog cancel button).
24
+ * **Variantes:**
25
+ * - `filled` (por defecto) — Énfasis alto. Úsalo para acciones principales.
26
+ * - `tonal` — Énfasis medio. Acciones secundarias que aún necesitan destacar.
27
+ * - `elevated` — Énfasis medio con sombra. Úsalo al sentarse sobre fondos con patrones.
28
+ * - `outlined` — Énfasis medio, sin relleno. Acciones secundarias o terciarias.
29
+ * - `text` — Énfasis bajo. Acciones terciarias (ej. botón de cancelar diálogo).
30
30
  *
31
- * **Shape morphing (M3 Expressive feature):**
32
- * - On press (active state): Round and square buttons morph to a slightly squarer
33
- * "pressed" shape with specific M3 corner radii (e.g. XS/S 8dp, M 12dp).
34
- * - On toggle (`active` attribute): The resting shape flips (e.g. roundsquare).
31
+ * **Transformación de forma (Característica M3 Expressive):**
32
+ * - Al presionar (estado activo): Los botones redondos y cuadrados se transforman a una forma
33
+ * "presionada" ligeramente más cuadrada con radios de esquina específicos de M3 (ej. XS/S 8dp, M 12dp).
34
+ * - Al alternar (atributo `active`): La forma de reposo se invierte (ej. redondocuadrado).
35
35
  *
36
- * **Rendering as a link:**
37
- * When the `href` attribute is provided, the component internally renders as
38
- * an `<a>` element instead of a `<button>`, allowing native routing and
39
- * middle-click (open in new tab) behaviors while maintaining button visuals.
36
+ * **Renderizando como un enlace:**
37
+ * Cuando se proporciona el atributo `href`, el componente se renderiza internamente como
38
+ * un elemento `<a>` en lugar de un `<button>`, permitiendo enrutamiento nativo y comportamientos
39
+ * de clic central (abrir en nueva pestaña) mientras mantiene los visuales del botón.
40
40
  *
41
41
  * @example
42
42
  * ```html
43
- * <!-- Primary filled button -->
44
- * <moni-button icon="add">Create new</moni-button>
43
+ * <!-- Botón primario relleno -->
44
+ * <moni-button icon="add">Crear nuevo</moni-button>
45
45
  *
46
- * <!-- Outlined button -->
47
- * <moni-button variant="outlined">Cancel</moni-button>
46
+ * <!-- Botón contorneado -->
47
+ * <moni-button variant="outlined">Cancelar</moni-button>
48
48
  *
49
- * <!-- Toggle button (toggles active state on click) -->
50
- * <moni-button icon="favorite" active>Like</moni-button>
49
+ * <!-- Botón de alternar (alterna estado activo al hacer clic) -->
50
+ * <moni-button icon="favorite" active>Me gusta</moni-button>
51
51
  *
52
- * <!-- Link button -->
53
- * <moni-button href="/settings" icon="settings">Settings</moni-button>
52
+ * <!-- Botón enlace -->
53
+ * <moni-button href="/settings" icon="settings">Ajustes</moni-button>
54
54
  * ```
55
55
  *
56
- * @slot default - The button label text.
57
- * @slot icon - Optional override for the leading icon.
58
- * @slot icon-trailing - Optional override for the trailing icon.
56
+ * @slot default - El texto de la etiqueta del botón.
57
+ * @slot icon - Sobrescritura opcional para el icono inicial (leading).
58
+ * @slot icon-trailing - Sobrescritura opcional para el icono final (trailing).
59
59
  *
60
- * @csspart button - The inner `<button>` or `<a>` element.
61
- * @csspart icon - The leading icon container.
62
- * @csspart label - The label container.
63
- * @csspart trailing-icon - The trailing icon container.
60
+ * @csspart button - El elemento interno `<button>` o `<a>`.
61
+ * @csspart icon - El contenedor del icono inicial.
62
+ * @csspart label - El contenedor de la etiqueta.
63
+ * @csspart trailing-icon - El contenedor del icono final.
64
64
  */
65
65
  @customElement('moni-button')
66
66
  export class MoniButton extends MoniElement {
67
67
  private static _deprecationWarned = false;
68
68
 
69
+ /**
70
+ * Variante visual del botón.
71
+ * @type {'filled' | 'tonal' | 'outlined' | 'text' | 'fill' | 'elevated'}
72
+ * @default 'filled'
73
+ */
69
74
  @property({ reflect: true })
70
75
  variant:
71
76
  | 'filled'
@@ -73,14 +78,24 @@ export class MoniButton extends MoniElement {
73
78
  | 'outlined'
74
79
  | 'text'
75
80
  | 'fill'
76
- | 'elevated' = 'filled';
81
+ | 'elevated'
82
+ | 'error' = 'filled';
83
+
77
84
  /**
78
- * M3 Expressive sizes: xsmall, small, medium, large, xlarge.
79
- * `extra` is a Moni legacy alias for `xlarge`, deprecated in v0.3.1; will
80
- * be removed in v1.0. See `m3-docs/components/buttons/overview.md` § Sizes.
85
+ * Tamaños de M3 Expressive: xsmall, small, medium, large, xlarge.
86
+ * `extra` es un alias heredado de Moni para `xlarge`, obsoleto en v0.3.1; se
87
+ * eliminará en v1.0. Ver `m3-docs/components/buttons/overview.md` § Sizes.
88
+ * @type {'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'extra'}
89
+ * @default 'medium'
81
90
  */
82
91
  @property({ reflect: true })
83
92
  size: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'extra' = 'medium';
93
+
94
+ /**
95
+ * Forma de las esquinas del botón.
96
+ * @type {'round' | 'no-round' | 'square' | 'circle' | 'left-round' | 'right-round' | 'top-round' | 'bottom-round' | 'left-round-flat' | 'right-round-flat' | 'top-round-flat' | 'bottom-round-flat' | 'inner-round'}
97
+ * @default 'round'
98
+ */
84
99
  @property({ reflect: true })
85
100
  shape:
86
101
  | 'round'
@@ -96,14 +111,55 @@ export class MoniButton extends MoniElement {
96
111
  | 'top-round-flat'
97
112
  | 'bottom-round-flat'
98
113
  | 'inner-round' = 'round';
114
+
115
+ /**
116
+ * Deshabilita el botón.
117
+ * @type {boolean}
118
+ */
99
119
  @property({ type: Boolean, reflect: true }) disabled = false;
120
+
121
+ /**
122
+ * Si es verdadero, muestra un indicador de carga y deshabilita el botón.
123
+ * @type {boolean}
124
+ */
100
125
  @property({ type: Boolean, reflect: true }) loading = false;
126
+
127
+ /**
128
+ * Si es verdadero, establece el botón a un estado activo/seleccionado.
129
+ * @type {boolean}
130
+ */
101
131
  @property({ type: Boolean, reflect: true }) active = false;
132
+
133
+ /**
134
+ * Nombre del icono inicial (Material Symbols).
135
+ * @type {string}
136
+ */
102
137
  @property({ reflect: true }) icon = '';
138
+
139
+ /**
140
+ * Nombre del icono final (Material Symbols).
141
+ * @type {string}
142
+ */
103
143
  @property({ reflect: true, attribute: 'icon-trailing' }) iconTrailing = '';
144
+
145
+ /**
146
+ * Tipo nativo del botón (cuando se renderiza como un `<button>`).
147
+ * @type {'button' | 'submit' | 'reset'}
148
+ * @default 'button'
149
+ */
104
150
  @property({ reflect: true })
105
151
  type: 'button' | 'submit' | 'reset' = 'button';
152
+
153
+ /**
154
+ * Si está establecido, renderiza el botón como un elemento `<a>` con esta URL.
155
+ * @type {string}
156
+ */
106
157
  @property({ reflect: true }) href = '';
158
+
159
+ /**
160
+ * Atributo target para los botones tipo enlace.
161
+ * @type {string}
162
+ */
107
163
  @property({ reflect: true }) target = '';
108
164
 
109
165
  override connectedCallback(): void {
@@ -198,7 +254,7 @@ export class MoniButton extends MoniElement {
198
254
  /* Square keeps horizontal padding (like a normal button) but
199
255
  drops border-radius. Only the circle removes all padding. */
200
256
  .button.circle {
201
- padding: 0;
257
+ padding: 0 !important;
202
258
  border-radius: 50%;
203
259
  inline-size: 2.5rem;
204
260
  aspect-ratio: 1;
@@ -529,6 +585,16 @@ export class MoniButton extends MoniElement {
529
585
  color: var(--primary);
530
586
  box-shadow: var(--elevate1);
531
587
  }
588
+ .button.error {
589
+ background-color: var(--error);
590
+ color: var(--on-error);
591
+ }
592
+ .button.error:hover:not(:disabled) {
593
+ background-image: linear-gradient(color-mix(in srgb, currentColor 8%, transparent), color-mix(in srgb, currentColor 8%, transparent));
594
+ }
595
+ .button.error:focus-visible {
596
+ outline-color: var(--error);
597
+ }
532
598
 
533
599
  /* Disabled / active */
534
600
  .button:disabled,
@@ -630,6 +696,11 @@ export class MoniButton extends MoniElement {
630
696
  `
631
697
  ];
632
698
 
699
+ /**
700
+ * Intercepta los clicks en botones tipo enlace (`href="..."`).
701
+ * Si el botón está desactivado (`disabled`), previene agresivamente
702
+ * tanto la navegación por defecto del navegador como la burbuja de eventos.
703
+ */
633
704
  private handleLinkClick(e: Event) {
634
705
  if (this.disabled) {
635
706
  e.preventDefault();
@@ -637,12 +708,41 @@ export class MoniButton extends MoniElement {
637
708
  }
638
709
  }
639
710
 
711
+ /**
712
+ * Assembles the button's Shadow DOM structure for each Lit render cycle.
713
+ *
714
+ * **Variant → CSS class mapping:**
715
+ * | `variant` | CSS class | Visual result |
716
+ * |--------------|---------------|-----------------------------|
717
+ * | `'filled'` | `''` (empty) | Primary filled button |
718
+ * | `'outlined'` | `'border'` | Outlined/stroked button |
719
+ * | `'tonal'` | `'fill'` | Secondary container fill |
720
+ * | `'text'` | `'transparent'` | Ghost/text button |
721
+ * | `'elevated'` | `'elevated'` | Tonal surface + shadow |
722
+ *
723
+ * **Shape morphing:**
724
+ * When `active=true`, the button inverts its corner-radius shape to create
725
+ * a micro-animation where clicking "morphs" the shape (round → square, etc.).
726
+ * This is used in toggle-button patterns (e.g., a nav-item that morphs to
727
+ * indicate the current page).
728
+ *
729
+ * **Icon resolution priority:**
730
+ * 1. `loading=true` → renders a `<moni-progress>` spinner (hides label at 50% opacity).
731
+ * 2. `icon` attribute → renders a `<moni-icon>` in the leading icon slot.
732
+ * 3. Otherwise → renders the `icon` named slot for slotted content.
733
+ *
734
+ * **Link vs. button:**
735
+ * When `href` is set, the root element is an `<a>` tag (with disabled click
736
+ * guard) for proper browser navigation semantics. Otherwise it's a `<button>`
737
+ * with `type="button"` to prevent accidental form submission.
738
+ */
640
739
  override render() {
641
740
  let variantClass = '';
642
741
  if (this.variant === 'outlined') variantClass = 'border';
643
742
  else if (this.variant === 'tonal' || this.variant === 'fill') variantClass = 'fill';
644
743
  else if (this.variant === 'text') variantClass = 'transparent';
645
744
  else if (this.variant === 'elevated') variantClass = 'elevated';
745
+ else if (this.variant === 'error') variantClass = 'error';
646
746
 
647
747
  let activeShape: string = this.shape;
648
748
  if (this.active) {
@@ -14,7 +14,7 @@ describe('moni-card (P4.4 — recreated)', () => {
14
14
  el.remove();
15
15
  });
16
16
 
17
- it('renders the three M3 variants: elevated (default), filled, outlined', async () => {
17
+ it('renderiza las tres variantes M3: elevated (por defecto), filled, outlined', async () => {
18
18
  expect(el.variant).toBe('elevated');
19
19
  await el.updateComplete;
20
20
  expect(el.getAttribute('variant')).toBe('elevated');
@@ -28,7 +28,7 @@ describe('moni-card (P4.4 — recreated)', () => {
28
28
  expect(el.getAttribute('variant')).toBe('outlined');
29
29
  });
30
30
 
31
- it('renders media, body, and actions slots', async () => {
31
+ it('renderiza los slots media, body y actions', async () => {
32
32
  await el.updateComplete;
33
33
  const media = el.shadowRoot?.querySelector('[part="media"]');
34
34
  const body = el.shadowRoot?.querySelector('[part="body"]');
@@ -38,7 +38,7 @@ describe('moni-card (P4.4 — recreated)', () => {
38
38
  expect(actions).toBeTruthy();
39
39
  });
40
40
 
41
- it('reflects clickable, draggable, and disabled attributes', async () => {
41
+ it('refleja los atributos clickable, draggable y disabled', async () => {
42
42
  el.clickable = true;
43
43
  await el.updateComplete;
44
44
  expect(el.hasAttribute('clickable')).toBe(true);
@@ -52,7 +52,7 @@ describe('moni-card (P4.4 — recreated)', () => {
52
52
  expect(el.hasAttribute('disabled')).toBe(true);
53
53
  });
54
54
 
55
- it('supports slotted headings via the headline slot', async () => {
55
+ it('soporta encabezados insertados vía el slot headline', async () => {
56
56
  const heading = document.createElement('h3');
57
57
  heading.setAttribute('slot', 'headline');
58
58
  heading.textContent = 'Card title';
@@ -68,10 +68,10 @@ describe('moni-card (P4.4 — recreated)', () => {
68
68
  expect(text).toBe('Card title');
69
69
  });
70
70
 
71
- it('supports the default slot for primary content', async () => {
71
+ it('soporta el slot por defecto para el contenido primario', async () => {
72
72
  el.textContent = 'Body content';
73
73
  await el.updateComplete;
74
- // The default slot is inside the headline slot wrapper.
74
+ // El slot por defecto está dentro del contenedor del slot headline.
75
75
  const defaultSlot = el.shadowRoot?.querySelector(
76
76
  'slot:not([name])'
77
77
  ) as HTMLSlotElement | null;
@@ -10,67 +10,67 @@ import { customElement, property } from 'lit/decorators.js';
10
10
  import { MoniElement, sharedStyles } from './_base/index.js';
11
11
 
12
12
  /**
13
- * Material Design 3 Card component.
13
+ * Componente Material Design 3 Card.
14
14
  *
15
- * Cards display content and actions about a single subject. They are
16
- * container surfaces that group related information together, making it
17
- * easy for users to scan and interact with collections of related data.
15
+ * Las tarjetas muestran contenido y acciones sobre un solo sujeto. Son
16
+ * superficies contenedoras que agrupan información relacionada junta, haciendo
17
+ * fácil para los usuarios escanear e interactuar con colecciones de datos relacionados.
18
18
  *
19
- * **M3 spec reference:** `m3-docs/components/cards/specs.md`
19
+ * **Referencia de la especificación M3:** `m3-docs/components/cards/specs.md`
20
20
  *
21
- * **Variants:**
22
- * - `elevated` (default) — `surface-container-low` background + `--elevate1` shadow.
23
- * Best for collections where the card needs visual separation from a
24
- * patterned or colored background. Gains shadow on hover/drag.
25
- * - `filled` — `surface-container-highest` background, no shadow.
26
- * Lowest emphasis; use when cards sit directly on the main background surface.
27
- * - `outlined` — `surface` background + 1dp `outline-variant` stroke.
28
- * Highest structural emphasis without casting a shadow. Best on solid backgrounds.
21
+ * **Variantes:**
22
+ * - `elevated` (por defecto) — Fondo `surface-container-low` + sombra `--elevate1`.
23
+ * Mejor para colecciones donde la tarjeta necesita separación visual de un
24
+ * fondo con patrones o de color. Gana sombra al pasar el ratón/arrastrar.
25
+ * - `filled` — Fondo `surface-container-highest`, sin sombra.
26
+ * Énfasis más bajo; úsalo cuando las tarjetas se asientan directamente sobre la superficie del fondo principal.
27
+ * - `outlined` — Fondo `surface` + trazo `outline-variant` 1dp.
28
+ * Énfasis estructural más alto sin proyectar una sombra. Mejor en fondos sólidos.
29
29
  *
30
- * **M3 measurements:**
31
- * - Container corner radius: 12dp.
32
- * - Horizontal content padding: 16dp.
33
- * - Gap between cards in a collection: max 8dp.
34
- * - Headline text alignment: start.
30
+ * **Medidas M3:**
31
+ * - Radio de esquina del contenedor: 12dp.
32
+ * - Relleno de contenido horizontal: 16dp.
33
+ * - Espacio entre tarjetas en una colección: máx. 8dp.
34
+ * - Alineación de texto del titular: inicio.
35
35
  *
36
- * **Interactive cards:**
37
- * When `clickable=true`, the card renders M3 state layer overlays on hover,
38
- * focus, and press via the `::before` pseudo-element. The consumer must handle
39
- * the `click` event to implement navigation or selection logic.
36
+ * **Tarjetas interactivas:**
37
+ * Cuando `clickable=true`, la tarjeta renderiza capas de estado M3 (hover,
38
+ * focus, press) a través del pseudo-elemento `::before`. El consumidor debe manejar
39
+ * el evento `click` para implementar la lógica de navegación o selección.
40
40
  *
41
41
  * @example
42
42
  * ```html
43
43
  * <moni-card variant="outlined" clickable>
44
- * <img slot="media" src="photo.jpg" alt="Card image" />
45
- * <h3 slot="headline">Card Title</h3>
46
- * <p slot="supporting">Supporting text that describes the card topic.</p>
44
+ * <img slot="media" src="photo.jpg" alt="Imagen de la tarjeta" />
45
+ * <h3 slot="headline">Título de Tarjeta</h3>
46
+ * <p slot="supporting">Texto de soporte que describe el tema de la tarjeta.</p>
47
47
  * <div slot="actions">
48
- * <moni-button variant="text">Cancel</moni-button>
49
- * <moni-button>Confirm</moni-button>
48
+ * <moni-button variant="text">Cancelar</moni-button>
49
+ * <moni-button>Confirmar</moni-button>
50
50
  * </div>
51
51
  * </moni-card>
52
52
  * ```
53
53
  *
54
- * @slot media - An image, video, or icon at the top of the card.
55
- * @slot default - Primary body content (replaces all named slots if used).
56
- * @slot headline - H3-equivalent title text.
57
- * @slot subhead - Secondary title below the headline.
58
- * @slot supporting - Descriptive supporting body text.
59
- * @slot actions - Action buttons row at the bottom of the card.
54
+ * @slot media - Una imagen, video, o icono en la parte superior de la tarjeta.
55
+ * @slot default - Contenido del cuerpo principal (reemplaza todos los slots con nombre si se usa).
56
+ * @slot headline - Texto de título equivalente a H3.
57
+ * @slot subhead - Título secundario debajo del titular.
58
+ * @slot supporting - Texto de soporte descriptivo del cuerpo.
59
+ * @slot actions - Fila de botones de acción en la parte inferior de la tarjeta.
60
60
  *
61
- * @csspart card - The outer card container.
62
- * @csspart media - The media area wrapper.
63
- * @csspart content - The content wrapper.
64
- * @csspart actions - The actions row wrapper.
61
+ * @csspart card - El contenedor exterior de la tarjeta.
62
+ * @csspart media - El contenedor del área de medios.
63
+ * @csspart content - El contenedor de contenido.
64
+ * @csspart actions - El contenedor de la fila de acciones.
65
65
  */
66
66
  @customElement('moni-card')
67
67
  export class MoniCard extends MoniElement {
68
68
  /**
69
- * Visual variant of the card.
69
+ * Variante visual de la tarjeta.
70
70
  *
71
- * - `'elevated'` (default) — Surface-low background + elevation shadow.
72
- * - `'filled'` — Surface-highest background, no shadow.
73
- * - `'outlined'` — Surface background + outline-variant stroke.
71
+ * - `'elevated'` (por defecto) — Fondo Surface-low + sombra de elevación.
72
+ * - `'filled'` — Fondo Surface-highest, sin sombra.
73
+ * - `'outlined'` — Fondo Surface + trazo outline-variant.
74
74
  *
75
75
  * @default 'elevated'
76
76
  */
@@ -78,34 +78,36 @@ export class MoniCard extends MoniElement {
78
78
  variant: 'elevated' | 'filled' | 'outlined' = 'elevated';
79
79
 
80
80
  /**
81
- * When `true`, applies M3 state layer overlays (hover, focus, pressed)
82
- * to communicate interactivity. The card background shifts slightly on hover.
81
+ * Cuando es `true`, aplica capas de estado M3 (hover, focus, pressed)
82
+ * para comunicar interactividad. El fondo de la tarjeta cambia ligeramente en hover.
83
83
  *
84
- * Use when the card itself is a clickable navigation or selection target.
84
+ * Úsalo cuando la tarjeta en es un objetivo de navegación o selección clicable.
85
85
  *
86
86
  * @default false
87
87
  */
88
88
  @property({ type: Boolean, reflect: true }) clickable = false;
89
89
 
90
90
  /**
91
- * When `true`, applies `--elevate3` box-shadow to simulate the M3 "dragged"
92
- * state as specified in the M3 card interaction spec.
91
+ * Cuando es `true`, aplica box-shadow `--elevate3` para simular el estado "arrastrado"
92
+ * M3 según lo especificado en la especificación de interacción de tarjetas M3.
93
93
  *
94
- * Consumers should toggle this attribute based on the drag state of the card
95
- * (e.g. via a drag-and-drop library callback).
94
+ * Los consumidores deben alternar este atributo basado en el estado de arrastre de la tarjeta
95
+ * (ej. a través de un callback de biblioteca drag-and-drop).
96
96
  *
97
97
  * @default false
98
98
  */
99
99
  @property({ type: Boolean, reflect: true }) draggable = false;
100
100
 
101
101
  /**
102
- * When `true`, the card renders at 50% opacity with `cursor: not-allowed`,
103
- * signaling that the card and its actions are unavailable.
102
+ * Cuando es `true`, la tarjeta se renderiza con opacidad del 50% con `cursor: not-allowed`,
103
+ * indicando que la tarjeta y sus acciones no están disponibles.
104
104
  *
105
105
  * @default false
106
106
  */
107
107
  @property({ type: Boolean, reflect: true }) disabled = false;
108
108
 
109
+
110
+
109
111
  static override styles = [
110
112
  sharedStyles,
111
113
  css`
@@ -239,6 +241,24 @@ export class MoniCard extends MoniElement {
239
241
  `
240
242
  ];
241
243
 
244
+ /**
245
+ * Renderiza el contenedor de la tarjeta como un `<section>` con envoltorio interactivo opcional.
246
+ *
247
+ * **¿Por qué `<section>`?**
248
+ * Las tarjetas representan una unidad distintiva y cohesiva de contenido. Usar `<section>` da
249
+ * a los lectores de pantalla un punto de referencia ARIA implícito para que puedan navegar entre tarjetas.
250
+ *
251
+ * **Tarjetas interactivas (`clickable=true`):**
252
+ * Cuando es `clickable`, toda la superficie de la tarjeta se convierte en un `<button>` que envuelve
253
+ * all slots, giving the card keyboard focus and `click` semantics. A
254
+ * `<moni-ripple>` is rendered as the first child to provide the M3 touch feedback.
255
+ *
256
+ * **Slot zones:**
257
+ * - `[slot="media"]` — image or video area at the card's leading edge.
258
+ * - `[slot="header"]` — title and supporting text row.
259
+ * - Default slot — the card's main content body.
260
+ * - `[slot="footer"]` — action buttons row at the trailing edge.
261
+ */
242
262
  override render() {
243
263
  return html`
244
264
  <div class="media" part="media">
@@ -1,6 +1,6 @@
1
1
  import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
2
2
 
3
- // Mock ResizeObserver globally for jsdom environment before component imports
3
+ // Simular ResizeObserver globalmente para el entorno jsdom antes de las importaciones de componentes
4
4
  globalThis.ResizeObserver = class {
5
5
  observe = vi.fn();
6
6
  unobserve = vi.fn();
@@ -29,7 +29,7 @@ describe('moni-carousel', () => {
29
29
  el.remove();
30
30
  });
31
31
 
32
- it('renders container, viewport and scroll-container', async () => {
32
+ it('renderiza el container, viewport y scroll-container', async () => {
33
33
  await el.updateComplete;
34
34
  const container = el.shadowRoot?.querySelector('.carousel-container');
35
35
  const viewport = el.shadowRoot?.querySelector('.carousel-viewport');
@@ -40,7 +40,7 @@ describe('moni-carousel', () => {
40
40
  expect(scrollContainer).toBeTruthy();
41
41
  });
42
42
 
43
- it('renders the correct number of cards and snap-items', async () => {
43
+ it('renderiza el número correcto de cards y snap-items', async () => {
44
44
  await el.updateComplete;
45
45
  const cards = el.shadowRoot?.querySelectorAll('.card');
46
46
  const snapItems = el.shadowRoot?.querySelectorAll('.snap-item');
@@ -49,7 +49,7 @@ describe('moni-carousel', () => {
49
49
  expect(snapItems?.length).toBe(3);
50
50
  });
51
51
 
52
- it('renders the header title and show-all button when set', async () => {
52
+ it('renderiza el título del header y el botón show-all cuando se establecen', async () => {
53
53
  el.headerText = 'Recent Highlights';
54
54
  el.showAll = true;
55
55
  el.showAllText = 'View All';
@@ -64,7 +64,7 @@ describe('moni-carousel', () => {
64
64
  expect(showAllLink?.textContent?.trim()).toBe('View All');
65
65
  });
66
66
 
67
- it('renders card links when href is specified in items', async () => {
67
+ it('renderiza enlaces en las cards cuando href está especificado en los items', async () => {
68
68
  const testEl = document.createElement('moni-carousel') as MoniCarousel;
69
69
  testEl.items = [
70
70
  { title: 'Link Item', img: 'https://picsum.photos/200', href: 'https://moni.com', target: '_blank' }
@@ -82,7 +82,7 @@ describe('moni-carousel', () => {
82
82
  testEl.remove();
83
83
  });
84
84
 
85
- it('dispatches item-click event when card is clicked', async () => {
85
+ it('despacha el evento item-click cuando se hace clic en una card', async () => {
86
86
  await el.updateComplete;
87
87
  const card = el.shadowRoot?.querySelector('.card') as HTMLElement;
88
88
  expect(card).toBeTruthy();
@@ -98,7 +98,7 @@ describe('moni-carousel', () => {
98
98
  expect(eventDetail.item.title).toBe('Item 1');
99
99
  });
100
100
 
101
- it('dispatches show-all-click event when show-all link is clicked', async () => {
101
+ it('despacha el evento show-all-click cuando se hace clic en el enlace show-all', async () => {
102
102
  el.showAll = true;
103
103
  await el.updateComplete;
104
104
  const showAllLink = el.shadowRoot?.querySelector('.show-all-link') as HTMLElement;
@@ -112,7 +112,7 @@ describe('moni-carousel', () => {
112
112
  expect(clickSpy).toHaveBeenCalledOnce();
113
113
  });
114
114
 
115
- it('updates snap padding based on layout type', async () => {
115
+ it('actualiza el relleno de ajuste (snap padding) basándose en el tipo de diseño (layout)', async () => {
116
116
  el.layout = 'hero';
117
117
  await el.updateComplete;
118
118
  let containerStyle = el.shadowRoot?.querySelector('.carousel-container')?.getAttribute('style');
@@ -124,7 +124,7 @@ describe('moni-carousel', () => {
124
124
  expect(containerStyle?.includes('--carousel-right-padding')).toBe(true);
125
125
  });
126
126
 
127
- it('renders slotted images as items', async () => {
127
+ it('renderiza las imágenes insertadas como items', async () => {
128
128
  const testEl = document.createElement('moni-carousel') as MoniCarousel;
129
129
  const img1 = document.createElement('img');
130
130
  img1.src = 'https://picsum.photos/200?1';
@@ -152,7 +152,7 @@ describe('moni-carousel', () => {
152
152
  testEl.remove();
153
153
  });
154
154
 
155
- it('renders slotted show-all button and dispatches click event', async () => {
155
+ it('renderiza el botón show-all insertado y despacha el evento click', async () => {
156
156
  const testEl = document.createElement('moni-carousel') as MoniCarousel;
157
157
  const btn = document.createElement('button');
158
158
  btn.setAttribute('slot', 'show-all');
@@ -180,7 +180,7 @@ describe('moni-carousel', () => {
180
180
  testEl.remove();
181
181
  });
182
182
 
183
- it('hides navigation buttons when hideNav is true', async () => {
183
+ it('oculta los botones de navegación cuando hideNav es true', async () => {
184
184
  const testEl = document.createElement('moni-carousel') as MoniCarousel;
185
185
  testEl.hideNav = true;
186
186
  document.body.appendChild(testEl);
@@ -195,7 +195,7 @@ describe('moni-carousel', () => {
195
195
  testEl.remove();
196
196
  });
197
197
 
198
- it('provides enough scroll width to reach the last item (Firefox regression)', async () => {
198
+ it('proporciona suficiente ancho de desplazamiento para alcanzar el último elemento (regresión de Firefox)', async () => {
199
199
  const testEl = document.createElement('moni-carousel') as MoniCarousel;
200
200
  testEl.items = Array.from({ length: 10 }, (_, i) => ({
201
201
  title: `Item ${i}`,