@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
@@ -14,7 +14,7 @@ describe('moni-checkbox', () => {
14
14
  el.remove();
15
15
  });
16
16
 
17
- it('renders an input and a visual span', async () => {
17
+ it('renderiza un input y un span visual', async () => {
18
18
  await el.updateComplete;
19
19
  const input = el.shadowRoot?.querySelector('input');
20
20
  const span = el.shadowRoot?.querySelector('span');
@@ -22,7 +22,7 @@ describe('moni-checkbox', () => {
22
22
  expect(span).toBeTruthy();
23
23
  });
24
24
 
25
- it('forwards checked state to the input', async () => {
25
+ it('reenvía el estado checked al input', async () => {
26
26
  el.checked = true;
27
27
  await el.updateComplete;
28
28
  const input = el.shadowRoot?.querySelector(
@@ -35,7 +35,7 @@ describe('moni-checkbox', () => {
35
35
  expect(input.checked).toBe(false);
36
36
  });
37
37
 
38
- it('input is contained in the label (for click handling)', async () => {
38
+ it('el input está contenido en el label (para el manejo de clics)', async () => {
39
39
  await el.updateComplete;
40
40
  const input = el.shadowRoot?.querySelector(
41
41
  'input'
@@ -44,14 +44,14 @@ describe('moni-checkbox', () => {
44
44
  expect(label?.contains(input)).toBe(true);
45
45
  });
46
46
 
47
- it('renders a label span when label attribute is set', async () => {
47
+ it('renderiza un label span cuando se establece el atributo label', async () => {
48
48
  el.label = 'Accept terms';
49
49
  await el.updateComplete;
50
50
  const span = el.shadowRoot?.querySelector('span');
51
51
  expect(span?.textContent?.trim()).toBe('Accept terms');
52
52
  });
53
53
 
54
- it('forwards disabled to the input', async () => {
54
+ it('reenvía disabled al input', async () => {
55
55
  el.disabled = true;
56
56
  await el.updateComplete;
57
57
  const input = el.shadowRoot?.querySelector(
@@ -60,7 +60,7 @@ describe('moni-checkbox', () => {
60
60
  expect(input.disabled).toBe(true);
61
61
  });
62
62
 
63
- it('reflects the checked attribute', async () => {
63
+ it('refleja el atributo checked', async () => {
64
64
  el.checked = true;
65
65
  await el.updateComplete;
66
66
  expect(el.hasAttribute('checked')).toBe(true);
@@ -70,7 +70,7 @@ describe('moni-checkbox', () => {
70
70
  expect(el.hasAttribute('checked')).toBe(false);
71
71
  });
72
72
 
73
- it('reflects the disabled attribute', async () => {
73
+ it('refleja el atributo disabled', async () => {
74
74
  el.disabled = true;
75
75
  await el.updateComplete;
76
76
  expect(el.hasAttribute('disabled')).toBe(true);
@@ -10,84 +10,93 @@ import { customElement, property, query } from 'lit/decorators.js';
10
10
  import { ifDefined } from 'lit/directives/if-defined.js';
11
11
  import { live } from 'lit/directives/live.js';
12
12
  import { MoniElement, sharedStyles } from './_base/index.js';
13
+ import { emitMoniEvent } from '../utils/event-emitter.js';
13
14
 
14
15
  /**
15
- * Material Design 3 Checkbox component.
16
+ * Componente Material Design 3 Checkbox.
16
17
  *
17
- * Checkboxes allow users to select one or more items from a set, or toggle
18
- * a single binary option. They are visual-only shellsthe consumer is
19
- * responsible for wiring up form submission and validation logic.
18
+ * Los checkboxes permiten a los usuarios seleccionar uno o más elementos de un conjunto, o alternar
19
+ * una sola opción binaria. Son envolturas solo visualesel consumidor es
20
+ * responsable de conectar la lógica de envío y validación del formulario.
20
21
  *
21
- * **Visual architecture (BeerCSS pattern):**
22
- * The native `<input type="checkbox">` occupies real layout space (16×16 minimum)
23
- * but is visually hidden via `opacity: 0`. A `<span>` sibling rendered after
24
- * the input holds two pseudo-elements:
25
- * - `::before` — the visible checkbox icon (Material Symbols ligature).
26
- * - `::after` — the hover/focus state layer ripple ring.
22
+ * **Arquitectura visual (Patrón BeerCSS):**
23
+ * El `<input type="checkbox">` nativo ocupa espacio real en el diseño (mínimo 16×16)
24
+ * pero está oculto visualmente con `opacity: 0`. Un hermano `<span>` renderizado después
25
+ * del input contiene dos pseudo-elementos:
26
+ * - `::before` — el icono visible del checkbox (ligadura de Material Symbols).
27
+ * - `::after` — el anillo de onda (ripple) de la capa de estado hover/focus.
27
28
  *
28
- * The `::before` content switches between:
29
- * - `'check_box_outline_blank'` (unchecked)
30
- * - `'check_box'` (checked)
31
- * - `'indeterminate_check_box'` (native indeterminate state)
29
+ * El contenido de `::before` cambia entre:
30
+ * - `'check_box_outline_blank'` (desmarcado)
31
+ * - `'check_box'` (marcado)
32
+ * - `'indeterminate_check_box'` (estado nativo indeterminado)
32
33
  *
33
- * **Form integration:**
34
- * Setting `name` and `value` passes them to the native `<input>` element,
35
- * enabling participation in HTML form submissions.
34
+ * **Integración de formulario:**
35
+ * Establecer `name` y `value` los pasa al elemento `<input>` nativo,
36
+ * permitiendo la participación en envíos de formularios HTML.
36
37
  *
37
- * @fires change - Bubbles and is composed. Fired when the checkbox is toggled.
38
- * The consumer can read `element.checked` for the new state.
38
+ * @fires moni-change - Burbujea y está compuesto. Se dispara cuando se alterna el checkbox.
39
+ * El consumidor puede leer `element.checked` para el nuevo estado.
39
40
  *
40
41
  * @example
41
42
  * ```html
42
- * <moni-checkbox label="Accept terms" name="terms" value="yes"></moni-checkbox>
43
+ * <moni-checkbox label="Aceptar términos" name="terms" value="yes"></moni-checkbox>
43
44
  *
44
45
  * <script>
45
- * document.querySelector('moni-checkbox').addEventListener('change', (e) => {
46
+ * document.querySelector('moni-checkbox').addEventListener('moni-change', (e) => {
46
47
  * console.log('checked:', e.target.checked);
47
48
  * });
48
49
  * </script>
49
50
  * ```
50
51
  *
51
- * @csspart checkbox - The outer `<label>` element.
52
+ * @csspart checkbox - El elemento exterior `<label>`.
52
53
  */
53
54
  @customElement('moni-checkbox')
54
55
  export class MoniCheckbox extends MoniElement {
56
+ static formAssociated = true;
57
+ private _internals: ElementInternals;
58
+
59
+ constructor() {
60
+ super();
61
+ this._internals = this.attachInternals();
62
+ }
63
+
55
64
  /**
56
- * Text label displayed to the right of the checkbox icon.
65
+ * Texto de la etiqueta mostrado a la derecha del icono del checkbox.
57
66
  *
58
- * When non-empty, the label is rendered as a text node inside the `<span>`.
59
- * When empty, the default slot is rendered instead, allowing slotted HTML.
67
+ * Cuando no está vacío, la etiqueta se renderiza como un nodo de texto dentro del `<span>`.
68
+ * Cuando está vacío, el slot por defecto se renderiza en su lugar, permitiendo HTML en el slot.
60
69
  *
61
70
  * @default ''
62
71
  */
63
72
  @property({ reflect: true }) label = '';
64
73
 
65
74
  /**
66
- * Whether the checkbox is currently checked.
75
+ * Si el checkbox está actualmente marcado.
67
76
  *
68
- * Reflected as an attribute so CSS attribute selectors and external state
69
- * readers can observe the checked state without accessing the JS property.
70
- * Synced to the native input via `updated()`.
77
+ * Reflejado como un atributo para que los selectores de atributos CSS y los lectores
78
+ * de estado externos puedan observar el estado marcado sin acceder a la propiedad JS.
79
+ * Sincronizado con el input nativo a través de `updated()`.
71
80
  *
72
81
  * @default false
73
82
  */
74
83
  @property({ type: Boolean, reflect: true }) checked = false;
75
84
 
76
85
  /**
77
- * When `true`, the native input is disabled: the checkbox is not interactive
78
- * and renders at 50% opacity.
86
+ * Cuando es `true`, el input nativo se deshabilita: el checkbox no es interactivo
87
+ * y se renderiza con opacidad del 50%.
79
88
  *
80
89
  * @default false
81
90
  */
82
91
  @property({ type: Boolean, reflect: true }) disabled = false;
83
92
 
84
93
  /**
85
- * Visual size of the checkbox icon.
94
+ * Tamaño visual del icono del checkbox.
86
95
  *
87
- * Maps to the `--_size` custom property which controls both the invisible
88
- * input's hit area and the visible `::before` icon size.
96
+ * Se mapea a la propiedad personalizada `--_size` que controla tanto el área de impacto
97
+ * del input invisible como el tamaño del icono visible `::before`.
89
98
  *
90
- * | Value | `--_size` |
99
+ * | Valor | `--_size` |
91
100
  * |------------|-----------|
92
101
  * | `'small'` | 1rem |
93
102
  * | `'medium'` | 1.5rem |
@@ -100,37 +109,40 @@ export class MoniCheckbox extends MoniElement {
100
109
  size: 'small' | 'medium' | 'large' | 'extra' = 'medium';
101
110
 
102
111
  /**
103
- * Forwarded to the native `<input name>` attribute.
104
- * Required for grouping checkboxes within a form.
112
+ * Reenviado al atributo `<input name>` nativo.
113
+ * Requerido para agrupar checkboxes dentro de un formulario.
105
114
  *
106
115
  * @default ''
107
116
  */
108
117
  @property({ reflect: true }) name = '';
109
118
 
110
119
  /**
111
- * Forwarded to the native `<input value>` attribute.
112
- * The value submitted in a form when this checkbox is checked.
120
+ * Reenviado al atributo `<input value>` nativo.
121
+ * El valor enviado en un formulario cuando este checkbox está marcado.
113
122
  *
114
123
  * @default ''
115
124
  */
116
125
  @property({ reflect: true }) value = '';
117
126
 
118
- /** Direct reference to the native input element for programmatic access. */
127
+ /** Referencia directa al elemento input nativo para acceso programático. */
119
128
  @query('input') private _input!: HTMLInputElement;
120
129
 
121
130
  /**
122
- * Syncs `checked` and `disabled` back to the native input element after
123
- * Lit's render cycle, ensuring the DOM stays in sync with component state.
131
+ * Sincroniza `checked` y `disabled` de vuelta al elemento input nativo después
132
+ * del ciclo de renderizado de Lit, asegurando que el DOM se mantenga sincronizado con el estado del componente.
124
133
  *
125
- * This is necessary because Lit's `.property=${value}` binding updates the
126
- * DOM property, but the `live()` directive and direct property assignment
127
- * are more reliable for boolean inputs across browser implementations.
134
+ * Esto es necesario porque el enlace `.property=${value}` de Lit actualiza la
135
+ * propiedad DOM, pero la directiva `live()` y la asignación directa de propiedad
136
+ * son más fiables para entradas booleanas en diferentes implementaciones de navegadores.
128
137
  *
129
- * @param changed - Map of changed property names to their previous values.
138
+ * @param changed - Mapa de nombres de propiedades cambiadas a sus valores anteriores.
130
139
  */
131
140
  override updated(changed: Map<string, unknown>) {
132
141
  if (this._input) {
133
- if (changed.has('checked')) this._input.checked = this.checked;
142
+ if (changed.has('checked')) {
143
+ this._input.checked = this.checked;
144
+ this._internals?.setFormValue?.(this.checked ? (this.value || 'on') : null);
145
+ }
134
146
  if (changed.has('disabled')) this._input.disabled = this.disabled;
135
147
  }
136
148
  }
@@ -264,7 +276,9 @@ export class MoniCheckbox extends MoniElement {
264
276
  */
265
277
  private _onChange(e: Event) {
266
278
  this.checked = (e.target as HTMLInputElement).checked;
267
- this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
279
+ emitMoniEvent(this, 'moni-change', {
280
+ detail: { value: this.checked, originalEvent: e }
281
+ });
268
282
  }
269
283
 
270
284
  /**
@@ -14,21 +14,21 @@ describe('moni-chip', () => {
14
14
  el.remove();
15
15
  });
16
16
 
17
- it('renders a native <button>', async () => {
17
+ it('renderiza un <button> nativo', async () => {
18
18
  await el.updateComplete;
19
19
  const button = el.shadowRoot?.querySelector('button');
20
20
  expect(button).toBeTruthy();
21
21
  expect(button?.getAttribute('type')).toBe('button');
22
22
  });
23
23
 
24
- it('defaults to variant=assist and size=small (M3 spec)', async () => {
24
+ it('por defecto es variant=assist y size=small (especificación M3)', async () => {
25
25
  await el.updateComplete;
26
26
  expect(el.variant).toBe('assist');
27
27
  expect(el.size).toBe('small');
28
28
  expect(el.getAttribute('variant')).toBe('assist');
29
29
  });
30
30
 
31
- it('accepts all 4 M3 variants (assist, filter, input, suggestion)', async () => {
31
+ it('acepta las 4 variantes M3 (assist, filter, input, suggestion)', async () => {
32
32
  const variants: Array<'assist' | 'filter' | 'input' | 'suggestion'> = [
33
33
  'assist',
34
34
  'filter',
@@ -44,7 +44,7 @@ describe('moni-chip', () => {
44
44
  }
45
45
  });
46
46
 
47
- it('aliases outlined → assist for backward compat', async () => {
47
+ it('crea un alias de outlined → assist para compatibilidad con versiones anteriores', async () => {
48
48
  el.variant = 'outlined';
49
49
  await el.updateComplete;
50
50
  const button = el.shadowRoot?.querySelector('button');
@@ -52,7 +52,7 @@ describe('moni-chip', () => {
52
52
  expect(button?.classList.contains('outlined')).toBe(false);
53
53
  });
54
54
 
55
- it('aliases fill → filter for backward compat', async () => {
55
+ it('crea un alias de fill → filter para compatibilidad con versiones anteriores', async () => {
56
56
  el.variant = 'fill';
57
57
  await el.updateComplete;
58
58
  const button = el.shadowRoot?.querySelector('button');
@@ -60,14 +60,14 @@ describe('moni-chip', () => {
60
60
  expect(button?.classList.contains('fill')).toBe(false);
61
61
  });
62
62
 
63
- it('selected chip applies the selected class', async () => {
63
+ it('el chip seleccionado aplica la clase selected', async () => {
64
64
  el.selected = true;
65
65
  await el.updateComplete;
66
66
  const button = el.shadowRoot?.querySelector('button');
67
67
  expect(button?.classList.contains('selected')).toBe(true);
68
68
  });
69
69
 
70
- it('input variant always shows the trailing remove icon (M3 spec)', async () => {
70
+ it('la variante input siempre muestra el icono trailing de eliminar (especificación M3)', async () => {
71
71
  el.variant = 'input';
72
72
  el.textContent = 'Tag';
73
73
  await el.updateComplete;
@@ -75,7 +75,7 @@ describe('moni-chip', () => {
75
75
  expect(remove).toBeTruthy();
76
76
  });
77
77
 
78
- it('removable=true forces the trailing remove icon on any variant', async () => {
78
+ it('removable=true fuerza el icono trailing de eliminar en cualquier variante', async () => {
79
79
  el.variant = 'assist';
80
80
  el.removable = true;
81
81
  el.textContent = 'Tag';
@@ -84,7 +84,7 @@ describe('moni-chip', () => {
84
84
  expect(remove).toBeTruthy();
85
85
  });
86
86
 
87
- it('assist and suggestion chips do NOT show remove icon by default', async () => {
87
+ it('los chips assist y suggestion NO muestran el icono de eliminar por defecto', async () => {
88
88
  for (const v of ['assist', 'suggestion'] as const) {
89
89
  el.variant = v;
90
90
  el.removable = false;
@@ -95,7 +95,7 @@ describe('moni-chip', () => {
95
95
  }
96
96
  });
97
97
 
98
- it('icon attribute renders a leading moni-icon', async () => {
98
+ it('el atributo icon renderiza un moni-icon leading', async () => {
99
99
  el.icon = 'add';
100
100
  el.textContent = 'Add';
101
101
  await el.updateComplete;
@@ -104,28 +104,28 @@ describe('moni-chip', () => {
104
104
  expect(icon?.getAttribute('name')).toBe('add');
105
105
  });
106
106
 
107
- it('size=medium sets medium class on the button', async () => {
107
+ it('size=medium establece la clase medium en el botón', async () => {
108
108
  el.size = 'medium';
109
109
  await el.updateComplete;
110
110
  const button = el.shadowRoot?.querySelector('button');
111
111
  expect(button?.classList.contains('medium')).toBe(true);
112
112
  });
113
113
 
114
- it('size=large sets large class on the button', async () => {
114
+ it('size=large establece la clase large en el botón', async () => {
115
115
  el.size = 'large';
116
116
  await el.updateComplete;
117
117
  const button = el.shadowRoot?.querySelector('button');
118
118
  expect(button?.classList.contains('large')).toBe(true);
119
119
  });
120
120
 
121
- it('shape=square sets square class (M3 button morph target)', async () => {
121
+ it('shape=square establece la clase square (objetivo de transformación de botón M3)', async () => {
122
122
  el.shape = 'square';
123
123
  await el.updateComplete;
124
124
  const button = el.shadowRoot?.querySelector('button');
125
125
  expect(button?.classList.contains('square')).toBe(true);
126
126
  });
127
127
 
128
- it('disabled disables the inner button', async () => {
128
+ it('disabled deshabilita el botón interno', async () => {
129
129
  el.disabled = true;
130
130
  await el.updateComplete;
131
131
  const button = el.shadowRoot?.querySelector(
@@ -134,7 +134,7 @@ describe('moni-chip', () => {
134
134
  expect(button.disabled).toBe(true);
135
135
  });
136
136
 
137
- it('loading shows moni-progress and sets aria-busy', async () => {
137
+ it('loading muestra moni-progress y establece aria-busy', async () => {
138
138
  el.loading = true;
139
139
  await el.updateComplete;
140
140
  const progress = el.shadowRoot?.querySelector('moni-progress');
@@ -143,7 +143,7 @@ describe('moni-chip', () => {
143
143
  expect(button?.getAttribute('aria-busy')).toBe('true');
144
144
  });
145
145
 
146
- it('renders the default slot content inside [part=label]', async () => {
146
+ it('renderiza el contenido del slot por defecto dentro de [part=label]', async () => {
147
147
  el.textContent = 'Hello chip';
148
148
  await el.updateComplete;
149
149
  const label = el.shadowRoot?.querySelector('[part="label"]');
@@ -154,7 +154,7 @@ describe('moni-chip', () => {
154
154
  expect(text).toBe('Hello chip');
155
155
  });
156
156
 
157
- it('applies has-icon class only when a leading icon is present', async () => {
157
+ it('aplica la clase has-icon solo cuando hay un icono leading presente', async () => {
158
158
  el.textContent = 'Filter';
159
159
  await el.updateComplete;
160
160
  let button = el.shadowRoot?.querySelector('button');
@@ -12,58 +12,63 @@ import './moni-icon.js';
12
12
  import './moni-progress.js';
13
13
 
14
14
  /**
15
- * Material Design 3 Chip component.
15
+ * Componente Material Design 3 Chip.
16
16
  *
17
- * Chips are compact, interactive elements that represent actions, filters,
18
- * attributes, or user inputs. They are visual-only shellsthe consumer
19
- * owns all state management (selection, removal, active filter state).
17
+ * Los chips (fichas) son elementos compactos e interactivos que representan acciones, filtros,
18
+ * atributos o entradas de usuario. Son contenedores solo visualesel consumidor
19
+ * es dueño de todo el manejo del estado (selección, eliminación, estado de filtro activo).
20
20
  *
21
- * **M3 spec reference:** `m3-docs/components/chips/specs.md`
21
+ * **Referencia de la especificación M3:** `m3-docs/components/chips/specs.md`
22
22
  *
23
- * **Variants:**
24
- * - `assist` (default) — Smart or suggested actions. Uses `var(--outline)` border
25
- * to ensure 3:1 contrast per the M3 accessibility spec. Alias: `outlined`.
26
- * - `filter` — Filters for a content collection. Shows a leading checkmark when
27
- * `selected`. Alias: `fill`.
28
- * - `input` — Represents discrete user input (tags, tokens). Adds a trailing
29
- * remove icon when `removable`.
30
- * - `suggestion` — Product-generated suggestions. Outlined, no icons.
23
+ * **Variantes:**
24
+ * - `assist` (por defecto) — Acciones inteligentes o sugeridas. Usa borde `var(--outline)`
25
+ * para asegurar un contraste de 3:1 según la especificación de accesibilidad de M3. Alias: `outlined`.
26
+ * - `filter` — Filtros para una colección de contenido. Muestra una marca de verificación al principio cuando
27
+ * está `selected`. Alias: `fill`.
28
+ * - `input` — Representa una entrada de usuario discreta (etiquetas, tokens). Añade un icono de
29
+ * eliminación al final cuando es `removable`.
30
+ * - `suggestion` — Sugerencias generadas por el producto. Con contorno, sin iconos.
31
31
  *
32
- * **M3 measurements:**
33
- * - Default height: 32dp (`small` size = M3 spec baseline).
34
- * - Corner radius: 8dp.
35
- * - Icon size: 18dp.
36
- * - `medium` and `large` sizes are Moni extensions with larger touch targets.
32
+ * **Medidas M3:**
33
+ * - Altura por defecto: 32dp (tamaño `small` = línea base de la especificación M3).
34
+ * - Radio de esquina: 8dp.
35
+ * - Tamaño de icono: 18dp.
36
+ * - Los tamaños `medium` y `large` son extensiones de Moni con áreas táctiles más grandes.
37
37
  *
38
- * **Accessibility:**
39
- * `assist` and `suggestion` chips use `var(--outline)` for their stroke to
40
- * guarantee 3:1 contrast against the surface background at rest.
41
- * `filter` and `input` use `outline-variant` at rest but achieve contrast
42
- * through the `secondary-container` fill when selected.
38
+ * **Accesibilidad:**
39
+ * Los chips `assist` y `suggestion` usan `var(--outline)` para su trazo para
40
+ * garantizar un contraste de 3:1 contra el fondo de la superficie en reposo.
41
+ * `filter` e `input` usan `outline-variant` en reposo pero logran contraste
42
+ * a través del relleno `secondary-container` cuando se seleccionan.
43
43
  *
44
- * @fires remove - Bubbles and is composed. Fired when the trailing remove
45
- * icon is clicked on an `input` chip with `removable`.
44
+ * @fires remove - Burbujea y está compuesto. Se dispara cuando el icono de eliminación
45
+ * final se hace clic en un chip `input` con `removable`.
46
46
  *
47
47
  * @example
48
48
  * ```html
49
- * <!-- Filter chip with selected state -->
49
+ * <!-- Chip de filtro con estado seleccionado -->
50
50
  * <moni-chip variant="filter" selected>Technology</moni-chip>
51
51
  *
52
- * <!-- Input chip (tag/token) -->
52
+ * <!-- Chip de entrada (etiqueta/token) -->
53
53
  * <moni-chip variant="input" removable icon="label">TypeScript</moni-chip>
54
54
  *
55
- * <!-- Assist chip with icon -->
55
+ * <!-- Chip de asistencia con icono -->
56
56
  * <moni-chip icon="directions_car">Get directions</moni-chip>
57
57
  * ```
58
58
  *
59
- * @slot default - The chip label text.
60
- * @slot icon - Override for the leading icon (alternative to the `icon` attribute).
59
+ * @slot default - El texto de la etiqueta del chip.
60
+ * @slot icon - Anula el icono inicial (alternativa al atributo `icon`).
61
61
  *
62
- * @csspart chip - The inner `<button>` element.
63
- * @csspart label - The label `<span>` element.
62
+ * @csspart chip - El elemento interno `<button>`.
63
+ * @csspart label - El elemento `<span>` de la etiqueta.
64
64
  */
65
65
  @customElement('moni-chip')
66
66
  export class MoniChip extends MoniElement {
67
+ /**
68
+ * Variante visual del chip.
69
+ * @type {'assist' | 'filter' | 'input' | 'suggestion' | 'outlined' | 'fill'}
70
+ * @default 'assist'
71
+ */
67
72
  @property({ reflect: true })
68
73
  variant:
69
74
  | 'assist'
@@ -72,8 +77,20 @@ export class MoniChip extends MoniElement {
72
77
  | 'suggestion'
73
78
  | 'outlined'
74
79
  | 'fill' = 'assist';
80
+
81
+ /**
82
+ * Define las dimensiones del chip.
83
+ * @type {'small' | 'medium' | 'large'}
84
+ * @default 'small'
85
+ */
75
86
  @property({ reflect: true })
76
87
  size: 'small' | 'medium' | 'large' = 'small';
88
+
89
+ /**
90
+ * Forma del radio del borde del chip.
91
+ * @type {'round' | 'no-round' | 'square' | 'circle' | 'left-round' | 'right-round' | 'top-round' | 'bottom-round'}
92
+ * @default 'round'
93
+ */
77
94
  @property({ reflect: true })
78
95
  shape:
79
96
  | 'round'
@@ -84,21 +101,61 @@ export class MoniChip extends MoniElement {
84
101
  | 'right-round'
85
102
  | 'top-round'
86
103
  | 'bottom-round' = 'round';
104
+
105
+ /**
106
+ * Si es true, marca el chip como seleccionado (útil para chips de filtro).
107
+ * @type {boolean}
108
+ */
87
109
  @property({ type: Boolean, reflect: true }) selected = false;
110
+
111
+ /**
112
+ * Si es true, muestra un icono de cierre al final para permitir la eliminación.
113
+ * @type {boolean}
114
+ */
88
115
  @property({ type: Boolean, reflect: true }) removable = false;
116
+
117
+ /**
118
+ * Deshabilita el chip.
119
+ * @type {boolean}
120
+ */
89
121
  @property({ type: Boolean, reflect: true }) disabled = false;
122
+
123
+ /**
124
+ * Si es true, muestra un indicador de carga dentro del chip.
125
+ * @type {boolean}
126
+ */
90
127
  @property({ type: Boolean, reflect: true }) loading = false;
128
+
129
+ /**
130
+ * Nombre del icono inicial (Material Symbols).
131
+ * @type {string}
132
+ */
91
133
  @property({ reflect: true }) icon = '';
92
134
 
93
135
  @state()
94
136
  private _hasSlottedIcon = false;
95
137
 
138
+ /**
139
+ * Manejador del slot interno de icono (Slot Change).
140
+ * Determina si el desarrollador proporcionó un icono dinámicamente vía Light DOM
141
+ * (`<moni-icon slot="icon">`), permitiendo que el componente ajuste
142
+ * sus márgenes internos (`padding`) y espaciados dinámicamente.
143
+ */
96
144
  private _handleSlotChange(e: Event) {
97
145
  const slot = e.target as HTMLSlotElement;
98
146
  this._hasSlottedIcon = slot.assignedNodes({ flatten: true }).length > 0;
99
147
  }
100
148
 
101
- /** Normalize legacy variant names to M3 spec. */
149
+ /**
150
+ * Manejador de clics en el icono de remover.
151
+ * Detiene la propagación para no disparar el clic del chip y emite un evento custom 'remove'.
152
+ */
153
+ private _handleRemoveClick(e: Event) {
154
+ e.stopPropagation();
155
+ this.dispatchEvent(new CustomEvent('remove', { bubbles: true, composed: true }));
156
+ }
157
+
158
+ /** Normaliza los nombres de variantes heredadas a la especificación M3. */
102
159
  private get _variant(): 'assist' | 'filter' | 'input' | 'suggestion' {
103
160
  if (this.variant === 'outlined') return 'assist';
104
161
  if (this.variant === 'fill') return 'filter';
@@ -288,6 +345,27 @@ export class MoniChip extends MoniElement {
288
345
  `
289
346
  ];
290
347
 
348
+ /**
349
+ * Renderiza el elemento `<button>` del chip con su lista de clases calculada.
350
+ *
351
+ * **Normalización de variantes:**
352
+ * `_variant` mapea nombres de alias heredados (`'outlined'` → `'assist'`, `'fill'` → `'filter'`)
353
+ * a nombres de variantes canónicas de M3 antes de inyectarlos como clases CSS.
354
+ *
355
+ * **Ruta rápida de carga:**
356
+ * Cuando `loading=true`, se devuelve temprano un botón mínimo con solo un indicador de carga
357
+ * (sin slot de icono, sin etiqueta, sin botón de eliminación) con `aria-busy="true"`.
358
+ *
359
+ * **Lógica del botón de eliminación:**
360
+ * `showRemove` es `true` cuando:
361
+ * - `variant='input'` (Especificación M3: los chips de entrada siempre tienen un icono de cierre al final), o
362
+ * - `removable=true` se establece explícitamente.
363
+ *
364
+ * **Resolución de icono:**
365
+ * Si se establece el atributo `icon`, se renderiza un `<moni-icon>`. De lo contrario, se usa el
366
+ * slot nombrado `icon`, con `_hasSlottedIcon` rastreando si se proyectó contenido en el slot
367
+ * (usado para añadir condicionalmente los ajustes de relleno `has-icon`).
368
+ */
291
369
  override render() {
292
370
  const variant = this._variant;
293
371
  const hasIcon = Boolean(this.icon) || this._hasSlottedIcon;
@@ -335,7 +413,7 @@ export class MoniChip extends MoniElement {
335
413
  ></slot>`;
336
414
 
337
415
  const removeEl = showRemove
338
- ? html`<span class="remove" part="remove" aria-hidden="true"
416
+ ? html`<span class="remove" part="remove" aria-hidden="true" @click=${this._handleRemoveClick}
339
417
  ><moni-icon name="close"></moni-icon
340
418
  ></span>`
341
419
  : nothing;