@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-color-field', () => {
14
14
  el.remove();
15
15
  });
16
16
 
17
- it('renders a swatch and a text input', async () => {
17
+ it('renderiza una muestra (swatch) y un input de texto', async () => {
18
18
  await el.updateComplete;
19
19
  const swatch = el.shadowRoot?.querySelector('.swatch');
20
20
  const text = el.shadowRoot?.querySelector('input[type="text"]');
@@ -22,14 +22,14 @@ describe('moni-color-field', () => {
22
22
  expect(text).toBeTruthy();
23
23
  });
24
24
 
25
- it('adds active class to the text input when value is set', async () => {
25
+ it('agrega la clase active al input de texto cuando se establece el valor', async () => {
26
26
  el.value = '#ff00aa';
27
27
  await el.updateComplete;
28
28
  const text = el.shadowRoot?.querySelector('input[type="text"]');
29
29
  expect(text?.classList.contains('active')).toBe(true);
30
30
  });
31
31
 
32
- it('forwards value to the text input', async () => {
32
+ it('reenvía el valor al input de texto', async () => {
33
33
  el.value = '#123456';
34
34
  await el.updateComplete;
35
35
  const text = el.shadowRoot?.querySelector(
@@ -38,7 +38,7 @@ describe('moni-color-field', () => {
38
38
  expect(text.value).toBe('#123456');
39
39
  });
40
40
 
41
- it('keeps the text input readonly (so the label can be lifted via .active)', async () => {
41
+ it('mantiene el input de texto en readonly (para que la etiqueta pueda elevarse vía .active)', async () => {
42
42
  await el.updateComplete;
43
43
  const text = el.shadowRoot?.querySelector(
44
44
  'input[type="text"]'
@@ -46,7 +46,7 @@ describe('moni-color-field', () => {
46
46
  expect(text.hasAttribute('readonly')).toBe(true);
47
47
  });
48
48
 
49
- it('renders label element adjacent to the text input for BeerCSS selector matching', async () => {
49
+ it('renderiza el elemento label adyacente al input de texto para el selector de BeerCSS', async () => {
50
50
  el.label = 'Pick a color';
51
51
  await el.updateComplete;
52
52
  const text = el.shadowRoot?.querySelector('input[type="text"]');
@@ -12,63 +12,123 @@ import { classMap } from 'lit/directives/class-map.js';
12
12
  import { MoniElement, sharedStyles, fieldStyles } from './_base/index.js';
13
13
 
14
14
  /**
15
- * Material Design 3 Color Field component.
15
+ * Componente Material Design 3 Color Field (Campo de Color).
16
16
  *
17
- * A specialized text field for color input that combines a native
18
- * `<input type="color">` with a read-only text display of the selected
19
- * hex value, wrapped in the standard M3 field shell.
17
+ * Un campo de texto especializado para la entrada de color que combina un
18
+ * `<input type="color">` nativo con una visualización de texto de solo lectura del
19
+ * valor hexadecimal seleccionado, envuelto en la carcasa estándar de campo M3.
20
20
  *
21
- * **Visual architecture:**
22
- * Extends the field styling pattern used by `<moni-text-field>`. The
23
- * leading icon slot is replaced by a circular color swatch (`.swatch`)
24
- * which is absolutely positioned over an invisible native color input.
25
- * Clicking the swatch opens the system color picker. The text input portion
26
- * displays the selected hex code and is strictly `readOnly`.
21
+ * **Arquitectura visual:**
22
+ * Extiende el patrón de estilo de campo usado por `<moni-text-field>`. El
23
+ * slot de icono inicial se reemplaza por una muestra de color circular (`.swatch`)
24
+ * que se posiciona absolutamente sobre una entrada de color nativa invisible.
25
+ * Al hacer clic en la muestra se abre el selector de color del sistema. La parte de entrada de texto
26
+ * muestra el código hexadecimal seleccionado y es estrictamente `readOnly`.
27
27
  *
28
- * **State syncing:**
29
- * The component listens to the native `change` event on the color input,
30
- * updates the `value` property, and re-dispatches a composed `'change'` event.
31
- * It does not listen to `input` (continuous drag in the color picker) to avoid
32
- * excessive event firing, but consumers can attach their own `input` listeners
33
- * directly to the element if live preview is needed.
28
+ * **Sincronización de estado:**
29
+ * El componente escucha el evento nativo `change` en la entrada de color,
30
+ * actualiza la propiedad `value`, y re-despacha un evento compuesto `'change'`.
31
+ * No escucha `input` (arrastre continuo en el selector de color) para evitar
32
+ * el disparo excesivo de eventos, pero los consumidores pueden adjuntar sus propios
33
+ * escuchas de `input` directamente al elemento si se necesita una vista previa en vivo.
34
34
  *
35
- * @fires change - Bubbles and is composed. Fired when the color picker closes
36
- * and the value is committed. Read `element.value`.
35
+ * @fires change - Burbujea y está compuesto. Se dispara cuando el selector de color se cierra
36
+ * y el valor se confirma. Leer `element.value`.
37
37
  *
38
38
  * @example
39
39
  * ```html
40
40
  * <moni-color-field
41
- * label="Theme Color"
41
+ * label="Color del Tema"
42
42
  * name="primaryColor"
43
43
  * value="#6750a4"
44
44
  * variant="outlined"
45
45
  * ></moni-color-field>
46
46
  * ```
47
47
  *
48
- * @csspart field - The outer `.field` div container.
49
- * @csspart swatch - The circular color preview element.
50
- * @csspart input-color - The native, visually hidden `<input type="color">`.
51
- * @csspart input-text - The native `<input type="text">` displaying the hex code.
52
- * @csspart label - The floating `<label>` element.
48
+ * @csspart field - El contenedor div exterior `.field`.
49
+ * @csspart swatch - El elemento de vista previa de color circular.
50
+ * @csspart input-color - El `<input type="color">` nativo, visualmente oculto.
51
+ * @csspart input-text - El `<input type="text">` nativo que muestra el código hexadecimal.
52
+ * @csspart label - El elemento flotante `<label>`.
53
53
  */
54
54
  @customElement('moni-color-field')
55
55
  export class MoniColorField extends MoniElement {
56
+ /**
57
+ * El nombre del input, enviado con los datos del formulario.
58
+ * @type {string}
59
+ */
56
60
  @property({ reflect: true }) name = '';
61
+
62
+ /**
63
+ * El texto de la etiqueta flotante.
64
+ * @type {string}
65
+ */
57
66
  @property({ reflect: true }) label = '';
67
+
68
+ /**
69
+ * Variante visual del campo de texto.
70
+ * @type {'filled' | 'outlined'}
71
+ * @default 'outlined'
72
+ */
58
73
  @property({ reflect: true }) variant: 'filled' | 'outlined' = 'outlined';
74
+
75
+ /**
76
+ * Define las dimensiones del campo de texto.
77
+ * @type {'small' | 'medium' | 'large' | 'extra'}
78
+ * @default 'medium'
79
+ */
59
80
  @property({ reflect: true })
60
81
  size: 'small' | 'medium' | 'large' | 'extra' = 'medium';
82
+
83
+ /**
84
+ * Forma del radio del borde del campo.
85
+ * @type {'round' | 'square' | 'no-round'}
86
+ * @default 'no-round'
87
+ */
61
88
  @property({ reflect: true })
62
89
  shape: 'round' | 'square' | 'no-round' = 'no-round';
90
+
91
+ /**
92
+ * Deshabilita el campo de color.
93
+ * @type {boolean}
94
+ */
63
95
  @property({ type: Boolean, reflect: true }) disabled = false;
96
+
97
+ /**
98
+ * Texto de ayuda mostrado debajo del campo.
99
+ * @type {string}
100
+ */
64
101
  @property({ reflect: true }) helper = '';
102
+
103
+ /**
104
+ * Texto de error mostrado debajo del campo cuando `error` es true.
105
+ * Sobrescribe el texto de ayuda.
106
+ * @type {string}
107
+ */
65
108
  @property({ reflect: true, attribute: 'error-text' }) errorText = '';
109
+
110
+ /**
111
+ * Si es true, establece el campo en un estado de error.
112
+ * @type {boolean}
113
+ */
66
114
  @property({ type: Boolean, reflect: true }) error = false;
115
+
116
+ /**
117
+ * El valor actual del color hexadecimal.
118
+ * @type {string}
119
+ * @default '#6750a4'
120
+ */
67
121
  @property({ reflect: true }) value = '#6750a4';
68
122
 
69
123
  @query('input[type="color"]') private _colorInput!: HTMLInputElement;
70
124
  @query('input[type="text"]') private _textInput!: HTMLInputElement;
71
125
 
126
+ /**
127
+ * Hook de ciclo de vida de Lit.
128
+ * Sincroniza manualmente el estado reactivo (`value`, `disabled`) con los
129
+ * elementos nativos del DOM subyacente. Se hace manualmente porque el input
130
+ * de tipo color no despacha eventos de forma natural si mutamos sus atributos.
131
+ */
72
132
  override updated(changed: Map<string, unknown>) {
73
133
  if (changed.has('value')) {
74
134
  if (this._colorInput) this._colorInput.value = this.value;
@@ -108,6 +168,30 @@ export class MoniColorField extends MoniElement {
108
168
  `
109
169
  ];
110
170
 
171
+ /**
172
+ * Ensambla la estructura del Shadow DOM del campo de color.
173
+ *
174
+ * **Estrategia de input en capas:**
175
+ * Dos elementos `<input>` se apilan absolutamente:
176
+ * 1. `<input type="color">` (z-index: 2, opacidad: 0) — invisible pero
177
+ * clicable, abre el selector de color nativo del sistema operativo.
178
+ * 2. `<input type="text" readonly>` (z-index: 0) — visible, muestra el
179
+ * valor hexadecimal. `tabindex="-1"` en el input de color significa que
180
+ * solo el input de texto es alcanzable por teclado.
181
+ *
182
+ * El círculo `.swatch` (z-index: 1) está posicionado absolutamente en el
183
+ * borde inicial del input de texto y estilizado a través de `--_swatch: ${this.value}`,
184
+ * lo cual establece su `background-color` mediante CSS `var(--_swatch)`.
185
+ *
186
+ * **Composición de `fieldClasses`:**
187
+ * El mapa de clases sigue la convención de nomenclatura field-styles de BeerCSS:
188
+ * `field`, `label`, `fill`/`border` (variante), `small`/`large`/`extra` (tamaño),
189
+ * `prefix` (activa el cambio de padding inicial para la muestra), `invalid`, forma.
190
+ *
191
+ * **Renderizado condicional de etiqueta / ayuda:**
192
+ * Usa el centinela `nothing` de Lit para evitar renderizar nodos DOM vacíos cuando
193
+ * `label` o `helper` son cadenas vacías, previniendo saltos de diseño.
194
+ */
111
195
  override render() {
112
196
  const isActive = Boolean(this.value);
113
197
  const fieldClasses = {
@@ -17,33 +17,33 @@ describe('moni-context-menu (P3.5 — flip)', () => {
17
17
  parent.remove();
18
18
  });
19
19
 
20
- it('renders a <moni-menu> in the shadow DOM', async () => {
20
+ it('renderiza un <moni-menu> en el shadow DOM', async () => {
21
21
  await el.updateComplete;
22
22
  const menu = el.shadowRoot?.querySelector('moni-menu');
23
23
  expect(menu).toBeTruthy();
24
24
  });
25
25
 
26
- it('reflects placement=bottom (default)', async () => {
26
+ it('refleja placement=bottom (por defecto)', async () => {
27
27
  await el.updateComplete;
28
28
  expect(el.placement).toBe('bottom');
29
29
  const menu = el.shadowRoot?.querySelector('moni-menu');
30
30
  expect(menu?.getAttribute('placement')).toBe('bottom');
31
31
  });
32
32
 
33
- it('reflects placement changes on the inner menu', async () => {
33
+ it('refleja los cambios de placement en el menú interno', async () => {
34
34
  el.placement = 'top';
35
35
  await el.updateComplete;
36
36
  const menu = el.shadowRoot?.querySelector('moni-menu');
37
37
  expect(menu?.getAttribute('placement')).toBe('top');
38
38
  });
39
39
 
40
- it('reflects the flip attribute on the host', async () => {
40
+ it('refleja el atributo flip en el host', async () => {
41
41
  el.flip = true;
42
42
  await el.updateComplete;
43
43
  expect(el.hasAttribute('flip')).toBe(true);
44
44
  });
45
45
 
46
- it('opens the menu on right-click on the parent', async () => {
46
+ it('abre el menú al hacer clic derecho en el padre', async () => {
47
47
  await el.updateComplete;
48
48
  const menu = el.shadowRoot?.querySelector(
49
49
  'moni-menu'
@@ -60,7 +60,7 @@ describe('moni-context-menu (P3.5 — flip)', () => {
60
60
  expect(menu?.hasAttribute('active')).toBe(true);
61
61
  });
62
62
 
63
- it('closes the menu on document click', async () => {
63
+ it('cierra el menú al hacer clic en el documento', async () => {
64
64
  await el.updateComplete;
65
65
  const menu = el.shadowRoot?.querySelector(
66
66
  'moni-menu'
@@ -74,7 +74,7 @@ describe('moni-context-menu (P3.5 — flip)', () => {
74
74
  expect(menu?.hasAttribute('active')).toBe(false);
75
75
  });
76
76
 
77
- it('closes the menu on Escape', async () => {
77
+ it('cierra el menú al presionar Escape', async () => {
78
78
  await el.updateComplete;
79
79
  const menu = el.shadowRoot?.querySelector(
80
80
  'moni-menu'
@@ -88,10 +88,10 @@ describe('moni-context-menu (P3.5 — flip)', () => {
88
88
  expect(menu?.hasAttribute('active')).toBe(false);
89
89
  });
90
90
 
91
- it('does not call showPopover (visual-only; no Popover API)', async () => {
92
- // Sanity: the component is visual-only. The moni-menu inside handles
93
- // the active attribute via CSS visibility/opacity. No native popover
94
- // toggling.
91
+ it('no llama a showPopover (solo visual; sin API Popover)', async () => {
92
+ // Sanidad: el componente es solo visual. El moni-menu interior maneja
93
+ // el atributo active vía visibility/opacity de CSS. No hay popover nativo
94
+ // de cambio.
95
95
  await el.updateComplete;
96
96
  const menu = el.shadowRoot?.querySelector('moni-menu');
97
97
  expect(menu?.hasAttribute('popover')).toBe(false);
@@ -11,47 +11,47 @@ import { MoniElement, sharedStyles } from './_base/index.js';
11
11
  import './moni-menu.js';
12
12
 
13
13
  /**
14
- * Material Design 3 Context Menu component.
14
+ * Componente Material Design 3 Context Menu (Menú Contextual).
15
15
  *
16
- * A specialized menu that opens at the exact coordinates of a pointer event,
17
- * typically triggered by a right-click (`contextmenu` event). It provides
18
- * contextual actions related to the specific item clicked.
16
+ * Un menú especializado que se abre en las coordenadas exactas de un evento de puntero,
17
+ * típicamente desencadenado por un clic derecho (evento `contextmenu`). Proporciona
18
+ * acciones contextuales relacionadas con el elemento específico clicado.
19
19
  *
20
- * **M3 spec reference:** `m3-docs/components/menus/specs.md` (Contextual menus)
20
+ * **Referencia de la especificación M3:** `m3-docs/components/menus/specs.md` (Menús contextuales)
21
21
  *
22
- * **Triggering mechanism:**
23
- * The component does not require programmatic triggering via an `open` property.
24
- * Instead, it attaches a `contextmenu` event listener to its parent element
25
- * during `connectedCallback`. When the parent is right-clicked, the menu
26
- * captures the `clientX`/`clientY` coordinates, prevents the default browser
27
- * context menu, and opens itself at the cursor position using `position: fixed`.
22
+ * **Mecanismo de activación:**
23
+ * El componente no requiere activación programática a través de una propiedad `open`.
24
+ * En su lugar, adjunta un detector de eventos `contextmenu` a su elemento padre
25
+ * durante `connectedCallback`. Cuando se hace clic derecho en el padre, el menú
26
+ * captura las coordenadas `clientX`/`clientY`, previene el menú contextual predeterminado
27
+ * del navegador, y se abre en la posición del cursor usando `position: fixed`.
28
28
  *
29
- * **Auto-flip behavior (`flip` attribute):**
30
- * Per the M3 guidelines, menus should flip to the opposite side of the cursor
31
- * if opening in the requested `placement` would cause them to overflow the
32
- * viewport. When `flip=true`, the component dynamically calculates viewport
33
- * bounds before opening and overrides `placement` if necessary (e.g., flipping
34
- * from `bottom` to `top` if clicked near the bottom of the screen).
29
+ * **Comportamiento de auto-inversión (atributo `flip`):**
30
+ * Según las pautas de M3, los menús deben invertirse al lado opuesto del cursor
31
+ * si al abrirse en la `placement` solicitada causarían un desbordamiento de la
32
+ * ventana gráfica. Cuando `flip=true`, el componente calcula dinámicamente los límites
33
+ * de la ventana antes de abrir y anula `placement` si es necesario (ej., invirtiendo
34
+ * de `bottom` a `top` si se hace clic cerca de la parte inferior de la pantalla).
35
35
  *
36
- * **Auto-dismiss:**
37
- * Closes automatically when clicking anywhere outside the menu, or when
38
- * pressing the `Escape` key.
36
+ * **Auto-descarte:**
37
+ * Se cierra automáticamente al hacer clic en cualquier lugar fuera del menú, o al
38
+ * presionar la tecla `Escape`.
39
39
  *
40
40
  * @example
41
41
  * ```html
42
- * <!-- Wrap the trigger area and the menu in a container -->
42
+ * <!-- Envuelve el área de activación y el menú en un contenedor -->
43
43
  * <div>
44
- * <p>Right-click me for options</p>
44
+ * <p>Haz clic derecho para ver las opciones</p>
45
45
  * <moni-context-menu flip>
46
- * <moni-menu-item>Copy</moni-menu-item>
47
- * <moni-menu-item>Paste</moni-menu-item>
46
+ * <moni-menu-item>Copiar</moni-menu-item>
47
+ * <moni-menu-item>Pegar</moni-menu-item>
48
48
  * <moni-divider></moni-divider>
49
- * <moni-menu-item>Delete</moni-menu-item>
49
+ * <moni-menu-item>Eliminar</moni-menu-item>
50
50
  * </moni-context-menu>
51
51
  * </div>
52
52
  * ```
53
53
  *
54
- * @slot default - The `<moni-menu-item>` elements that make up the menu.
54
+ * @slot default - Los elementos `<moni-menu-item>` que componen el menú.
55
55
  */
56
56
  @customElement('moni-context-menu')
57
57
  export class MoniContextMenu extends MoniElement {
@@ -67,8 +67,18 @@ export class MoniContextMenu extends MoniElement {
67
67
  @query('moni-menu') private _menuEl?: HTMLElement;
68
68
 
69
69
  private _target: HTMLElement | null = null;
70
+ /**
71
+ * Wrapper estático para el manejador de teclado global.
72
+ * Conserva la referencia exacta para desregistrar el evento en `disconnectedCallback`.
73
+ */
70
74
  private _docKeydown = (e: KeyboardEvent) => this._onDocKeydown(e);
71
75
 
76
+ /**
77
+ * Hook de inicialización (Lit).
78
+ * Atrapa al elemento padre directo y le inyecta `position: relative` (si era static)
79
+ * para que las coordenadas de despliegue del menú floten correctamente.
80
+ * Adjunta los eventos nativos de `contextmenu` (clic derecho) al contenedor.
81
+ */
72
82
  override connectedCallback() {
73
83
  super.connectedCallback();
74
84
  this._target = this.parentElement;
@@ -84,6 +94,11 @@ export class MoniContextMenu extends MoniElement {
84
94
  document.addEventListener('keydown', this._docKeydown);
85
95
  }
86
96
 
97
+ /**
98
+ * Hook de destrucción (Lit).
99
+ * Limpia los detectores de clic derecho y atajos de teclado para eludir memory leaks
100
+ * al desmontarse del DOM.
101
+ */
87
102
  override disconnectedCallback() {
88
103
  if (this._target) {
89
104
  this._target.removeEventListener('contextmenu', this._onContextMenu);
@@ -93,6 +108,11 @@ export class MoniContextMenu extends MoniElement {
93
108
  super.disconnectedCallback();
94
109
  }
95
110
 
111
+ /**
112
+ * Intercepta el clic derecho (`contextmenu`) del navegador de forma nativa.
113
+ * Previene el menú por defecto del SO y captura las coordenadas X/Y del ratón
114
+ * relativas al elemento anfitrión para ubicar milimétricamente el popup personalizado.
115
+ */
96
116
  private _onContextMenu = (e: MouseEvent) => {
97
117
  e.preventDefault();
98
118
  if (this._target) {
@@ -105,10 +125,16 @@ export class MoniContextMenu extends MoniElement {
105
125
  }
106
126
  this._resolvedPlacement = this.placement;
107
127
  this._open = true;
108
- // After Lit renders the menu, check viewport fit and flip if needed.
128
+ // Después de que Lit renderice el menú, verificar el ajuste al viewport y voltear si es necesario.
109
129
  this.updateComplete.then(() => this._maybeFlip());
110
130
  };
111
131
 
132
+ /**
133
+ * Sistema de Colisión/Desbordamiento de Ventana.
134
+ * Si la directiva `flip` está habilitada, examina los límites (BoundingClientRect)
135
+ * del menú tras su renderizado y altera su `placement` sobre la marcha si éste
136
+ * colisiona con el borde del Viewport, invirtiendo top/bottom o left/right.
137
+ */
112
138
  private _maybeFlip() {
113
139
  if (!this.flip) return;
114
140
  const menu = this._menuEl?.shadowRoot?.querySelector('menu') as HTMLElement | null;
@@ -129,12 +155,20 @@ export class MoniContextMenu extends MoniElement {
129
155
  }
130
156
  }
131
157
 
158
+ /**
159
+ * Cierra instintivamente el menú contextual si el usuario hace clic en
160
+ * cualquier zona exterior al mismo.
161
+ */
132
162
  private _onDocumentClick = () => {
133
163
  if (this._open) {
134
164
  this._open = false;
135
165
  }
136
166
  };
137
167
 
168
+ /**
169
+ * Escucha la tecla Escape a nivel documento para cerrar el menú si se
170
+ * encuentra desplegado, cumpliendo con los estándares de accesibilidad (WAI-ARIA).
171
+ */
138
172
  private _onDocKeydown = (e: KeyboardEvent) => {
139
173
  if (e.key === 'Escape' && this._open) {
140
174
  this._open = false;
@@ -159,10 +193,22 @@ export class MoniContextMenu extends MoniElement {
159
193
  `
160
194
  ];
161
195
 
196
+ /**
197
+ * Renderiza el menú contextual como una superposición de Popover API posicionada en las coordenadas del puntero.
198
+ *
199
+ * El `<div>` del menú usa `popover="manual"` para que aparezca en la capa superior
200
+ * por encima de todo el otro contenido. Sus `top` y `left` se establecen mediante propiedades personalizadas CSS
201
+ * `--_x` / `--_y` (inyectadas como estilo en línea) que se calculan
202
+ * a partir de `clientX` / `clientY` del evento `contextmenu`.
203
+ *
204
+ * El `@click` en el fondo (fuera de los límites del menú) llama a `hidePopover()`
205
+ * para descartar ligeramente el menú contextual. Los elementos dentro del menú deben llamar a
206
+ * `event.stopPropagation()` para evitar el cierre accidental al hacer clic en un elemento.
207
+ */
162
208
  override render() {
163
- // When the menu is open, prefer the resolved (possibly flipped)
164
- // placement; otherwise just use the host's requested placement so
165
- // the inner element reflects the attribute synchronously.
209
+ // Cuando el menú está abierto, preferir la ubicación resuelta (posiblemente volteada);
210
+ // de lo contrario, simplemente usar la ubicación solicitada por el host para que
211
+ // el elemento interno refleje el atributo sincrónicamente.
166
212
  const effectivePlacement = this._open
167
213
  ? this._resolvedPlacement
168
214
  : this.placement;