@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.
- package/custom-elements.json +5230 -1007
- package/dist/components/_base/moni-element.d.ts +16 -9
- package/dist/components/_base/moni-element.d.ts.map +1 -1
- package/dist/components/_base/moni-element.js +63 -9
- package/dist/components/index.js +2 -2
- package/dist/components/loading-shapes.d.ts +19 -0
- package/dist/components/loading-shapes.d.ts.map +1 -1
- package/dist/components/loading-shapes.js +19 -0
- package/dist/components/moni-app-bar.d.ts +72 -62
- package/dist/components/moni-app-bar.d.ts.map +1 -1
- package/dist/components/moni-app-bar.js +72 -62
- package/dist/components/moni-badge.d.ts +64 -65
- package/dist/components/moni-badge.d.ts.map +1 -1
- package/dist/components/moni-badge.js +64 -66
- package/dist/components/moni-bottom-sheet.d.ts +129 -61
- package/dist/components/moni-bottom-sheet.d.ts.map +1 -1
- package/dist/components/moni-bottom-sheet.js +217 -131
- package/dist/components/moni-button-group.d.ts +107 -29
- package/dist/components/moni-button-group.d.ts.map +1 -1
- package/dist/components/moni-button-group.js +107 -29
- package/dist/components/moni-button-segment.d.ts +53 -12
- package/dist/components/moni-button-segment.d.ts.map +1 -1
- package/dist/components/moni-button-segment.js +53 -12
- package/dist/components/moni-button.d.ts +116 -38
- package/dist/components/moni-button.d.ts.map +1 -1
- package/dist/components/moni-button.js +128 -38
- package/dist/components/moni-card.d.ts +68 -50
- package/dist/components/moni-card.d.ts.map +1 -1
- package/dist/components/moni-card.js +68 -50
- package/dist/components/moni-carousel.d.ts +484 -53
- package/dist/components/moni-carousel.d.ts.map +1 -1
- package/dist/components/moni-carousel.js +1024 -245
- package/dist/components/moni-checkbox.d.ts +49 -46
- package/dist/components/moni-checkbox.d.ts.map +1 -1
- package/dist/components/moni-checkbox.js +55 -48
- package/dist/components/moni-chip.d.ts +100 -33
- package/dist/components/moni-chip.d.ts.map +1 -1
- package/dist/components/moni-chip.js +104 -34
- package/dist/components/moni-color-field.d.ts +99 -24
- package/dist/components/moni-color-field.d.ts.map +1 -1
- package/dist/components/moni-color-field.js +99 -24
- package/dist/components/moni-context-menu.d.ts +72 -26
- package/dist/components/moni-context-menu.d.ts.map +1 -1
- package/dist/components/moni-context-menu.js +76 -30
- package/dist/components/moni-dialog.d.ts +84 -59
- package/dist/components/moni-dialog.d.ts.map +1 -1
- package/dist/components/moni-dialog.js +105 -58
- package/dist/components/moni-divider.d.ts +39 -27
- package/dist/components/moni-divider.d.ts.map +1 -1
- package/dist/components/moni-divider.js +42 -30
- package/dist/components/moni-expansion.d.ts +32 -22
- package/dist/components/moni-expansion.d.ts.map +1 -1
- package/dist/components/moni-expansion.js +32 -22
- package/dist/components/moni-fab-menu.d.ts +61 -23
- package/dist/components/moni-fab-menu.d.ts.map +1 -1
- package/dist/components/moni-fab-menu.js +69 -31
- package/dist/components/moni-fab.d.ts +86 -28
- package/dist/components/moni-fab.d.ts.map +1 -1
- package/dist/components/moni-fab.js +92 -34
- package/dist/components/moni-file-field.d.ts +118 -30
- package/dist/components/moni-file-field.d.ts.map +1 -1
- package/dist/components/moni-file-field.js +118 -30
- package/dist/components/moni-icon.d.ts +40 -35
- package/dist/components/moni-icon.d.ts.map +1 -1
- package/dist/components/moni-icon.js +43 -38
- package/dist/components/moni-list-item.d.ts +46 -33
- package/dist/components/moni-list-item.d.ts.map +1 -1
- package/dist/components/moni-list-item.js +61 -41
- package/dist/components/moni-list.d.ts +30 -20
- package/dist/components/moni-list.d.ts.map +1 -1
- package/dist/components/moni-list.js +36 -21
- package/dist/components/moni-loading-indicator.d.ts +54 -22
- package/dist/components/moni-loading-indicator.d.ts.map +1 -1
- package/dist/components/moni-loading-indicator.js +54 -22
- package/dist/components/moni-menu-item.d.ts +23 -16
- package/dist/components/moni-menu-item.d.ts.map +1 -1
- package/dist/components/moni-menu-item.js +23 -16
- package/dist/components/moni-menu.d.ts +81 -28
- package/dist/components/moni-menu.d.ts.map +1 -1
- package/dist/components/moni-menu.js +81 -30
- package/dist/components/moni-morph-modal.d.ts +141 -0
- package/dist/components/moni-morph-modal.d.ts.map +1 -1
- package/dist/components/moni-morph-modal.js +295 -58
- package/dist/components/moni-nav-item.d.ts +59 -29
- package/dist/components/moni-nav-item.d.ts.map +1 -1
- package/dist/components/moni-nav-item.js +59 -29
- package/dist/components/moni-nav.d.ts +94 -35
- package/dist/components/moni-nav.d.ts.map +1 -1
- package/dist/components/moni-nav.js +94 -35
- package/dist/components/moni-progress.d.ts +99 -55
- package/dist/components/moni-progress.d.ts.map +1 -1
- package/dist/components/moni-progress.js +99 -55
- package/dist/components/moni-radio.d.ts +62 -50
- package/dist/components/moni-radio.d.ts.map +1 -1
- package/dist/components/moni-radio.js +65 -52
- package/dist/components/moni-ripple.d.ts +74 -59
- package/dist/components/moni-ripple.d.ts.map +1 -1
- package/dist/components/moni-ripple.js +74 -59
- package/dist/components/moni-segmented-button.d.ts +91 -16
- package/dist/components/moni-segmented-button.d.ts.map +1 -1
- package/dist/components/moni-segmented-button.js +94 -17
- package/dist/components/moni-select-option.d.ts +30 -23
- package/dist/components/moni-select-option.d.ts.map +1 -1
- package/dist/components/moni-select-option.js +30 -23
- package/dist/components/moni-select.d.ts +300 -35
- package/dist/components/moni-select.d.ts.map +1 -1
- package/dist/components/moni-select.js +323 -39
- package/dist/components/moni-side-sheet.d.ts +94 -32
- package/dist/components/moni-side-sheet.d.ts.map +1 -1
- package/dist/components/moni-side-sheet.js +94 -32
- package/dist/components/moni-slider.d.ts +152 -41
- package/dist/components/moni-slider.d.ts.map +1 -1
- package/dist/components/moni-slider.js +154 -42
- package/dist/components/moni-snackbar.d.ts +53 -43
- package/dist/components/moni-snackbar.d.ts.map +1 -1
- package/dist/components/moni-snackbar.js +53 -43
- package/dist/components/moni-split-button.d.ts +63 -18
- package/dist/components/moni-split-button.d.ts.map +1 -1
- package/dist/components/moni-split-button.js +63 -18
- package/dist/components/moni-step.d.ts +36 -24
- package/dist/components/moni-step.d.ts.map +1 -1
- package/dist/components/moni-step.js +41 -29
- package/dist/components/moni-stepper.d.ts +64 -27
- package/dist/components/moni-stepper.d.ts.map +1 -1
- package/dist/components/moni-stepper.js +72 -34
- package/dist/components/moni-switch.d.ts +57 -46
- package/dist/components/moni-switch.d.ts.map +1 -1
- package/dist/components/moni-switch.js +59 -47
- package/dist/components/moni-tab.d.ts +26 -18
- package/dist/components/moni-tab.d.ts.map +1 -1
- package/dist/components/moni-tab.js +29 -21
- package/dist/components/moni-tabs.d.ts +34 -28
- package/dist/components/moni-tabs.d.ts.map +1 -1
- package/dist/components/moni-tabs.js +34 -28
- package/dist/components/moni-text-field.d.ts +139 -29
- package/dist/components/moni-text-field.d.ts.map +1 -1
- package/dist/components/moni-text-field.js +157 -31
- package/dist/components/moni-textarea.d.ts +127 -29
- package/dist/components/moni-textarea.d.ts.map +1 -1
- package/dist/components/moni-textarea.js +131 -32
- package/dist/components/moni-time-picker.d.ts +114 -24
- package/dist/components/moni-time-picker.d.ts.map +1 -1
- package/dist/components/moni-time-picker.js +127 -33
- package/dist/components/moni-toolbar.d.ts +37 -23
- package/dist/components/moni-toolbar.d.ts.map +1 -1
- package/dist/components/moni-toolbar.js +37 -23
- package/dist/components/moni-tooltip.d.ts +100 -36
- package/dist/components/moni-tooltip.d.ts.map +1 -1
- package/dist/components/moni-tooltip.js +104 -40
- package/dist/components/moni-typography.d.ts +68 -30
- package/dist/components/moni-typography.d.ts.map +1 -1
- package/dist/components/moni-typography.js +70 -32
- package/dist/styles/tokens.css +7 -7
- package/dist/types/events.d.ts +17 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +1 -0
- package/dist/utils/event-emitter.d.ts +13 -0
- package/dist/utils/event-emitter.d.ts.map +1 -0
- package/dist/utils/event-emitter.js +13 -0
- package/package.json +2 -1
- package/src/components/_base/moni-element.ts +73 -9
- package/src/components/index.ts +2 -2
- package/src/components/loading-shapes.ts +19 -0
- package/src/components/moni-app-bar.test.ts +10 -10
- package/src/components/moni-app-bar.ts +72 -62
- package/src/components/moni-badge.ts +64 -66
- package/src/components/moni-bottom-sheet.test.ts +39 -45
- package/src/components/moni-bottom-sheet.ts +222 -131
- package/src/components/moni-button-group.test.ts +14 -14
- package/src/components/moni-button-group.ts +107 -29
- package/src/components/moni-button-segment.ts +53 -12
- package/src/components/moni-button.test.ts +28 -26
- package/src/components/moni-button.ts +139 -39
- package/src/components/moni-card.test.ts +6 -6
- package/src/components/moni-card.ts +70 -50
- package/src/components/moni-carousel.test.ts +12 -12
- package/src/components/moni-carousel.ts +1129 -269
- package/src/components/moni-checkbox.test.ts +7 -7
- package/src/components/moni-checkbox.ts +62 -48
- package/src/components/moni-chip.test.ts +17 -17
- package/src/components/moni-chip.ts +112 -34
- package/src/components/moni-color-field.test.ts +5 -5
- package/src/components/moni-color-field.ts +108 -24
- package/src/components/moni-context-menu.test.ts +11 -11
- package/src/components/moni-context-menu.ts +76 -30
- package/src/components/moni-dialog.ts +108 -59
- package/src/components/moni-divider.test.ts +4 -4
- package/src/components/moni-divider.ts +42 -30
- package/src/components/moni-expansion.ts +32 -22
- package/src/components/moni-fab-menu.test.ts +11 -11
- package/src/components/moni-fab-menu.ts +69 -31
- package/src/components/moni-fab.test.ts +16 -16
- package/src/components/moni-fab.ts +100 -34
- package/src/components/moni-file-field.test.ts +8 -8
- package/src/components/moni-file-field.ts +132 -30
- package/src/components/moni-icon.test.ts +11 -11
- package/src/components/moni-icon.ts +43 -38
- package/src/components/moni-list-item.test.ts +10 -10
- package/src/components/moni-list-item.ts +61 -41
- package/src/components/moni-list.ts +37 -21
- package/src/components/moni-loading-indicator.test.ts +3 -3
- package/src/components/moni-loading-indicator.ts +54 -22
- package/src/components/moni-menu-item.ts +23 -16
- package/src/components/moni-menu.test.ts +7 -7
- package/src/components/moni-menu.ts +87 -30
- package/src/components/moni-morph-modal.test.ts +18 -17
- package/src/components/moni-morph-modal.ts +327 -60
- package/src/components/moni-nav-item.ts +59 -29
- package/src/components/moni-nav.test.ts +11 -11
- package/src/components/moni-nav.ts +94 -35
- package/src/components/moni-progress.test.ts +9 -9
- package/src/components/moni-progress.ts +100 -56
- package/src/components/moni-radio.test.ts +8 -8
- package/src/components/moni-radio.ts +71 -51
- package/src/components/moni-ripple.ts +74 -59
- package/src/components/moni-segmented-button.test.ts +4 -4
- package/src/components/moni-segmented-button.ts +94 -17
- package/src/components/moni-select-option.ts +30 -23
- package/src/components/moni-select.test.ts +11 -11
- package/src/components/moni-select.ts +361 -50
- package/src/components/moni-side-sheet.test.ts +7 -7
- package/src/components/moni-side-sheet.ts +94 -32
- package/src/components/moni-slider.test.ts +7 -7
- package/src/components/moni-slider.ts +165 -42
- package/src/components/moni-snackbar.test.ts +8 -8
- package/src/components/moni-snackbar.ts +53 -43
- package/src/components/moni-split-button.ts +63 -18
- package/src/components/moni-step.test.ts +7 -7
- package/src/components/moni-step.ts +41 -29
- package/src/components/moni-stepper.test.ts +7 -7
- package/src/components/moni-stepper.ts +72 -34
- package/src/components/moni-switch.test.ts +12 -12
- package/src/components/moni-switch.ts +66 -47
- package/src/components/moni-tab.test.ts +5 -5
- package/src/components/moni-tab.ts +29 -21
- package/src/components/moni-tabs.ts +34 -28
- package/src/components/moni-text-field.test.ts +13 -13
- package/src/components/moni-text-field.ts +181 -30
- package/src/components/moni-textarea.test.ts +17 -17
- package/src/components/moni-textarea.ts +155 -31
- package/src/components/moni-time-picker.test.ts +5 -5
- package/src/components/moni-time-picker.ts +128 -33
- package/src/components/moni-toolbar.test.ts +8 -8
- package/src/components/moni-toolbar.ts +37 -23
- package/src/components/moni-tooltip.test.ts +15 -15
- package/src/components/moni-tooltip.ts +107 -40
- package/src/components/moni-typography.test.ts +10 -10
- package/src/components/moni-typography.ts +73 -32
- package/src/styles/tokens.css +7 -7
- package/src/types/events.ts +17 -0
- 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('
|
|
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('
|
|
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
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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
|
|
16
|
+
* Componente Material Design 3 Checkbox.
|
|
16
17
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
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 visuales — el consumidor es
|
|
20
|
+
* responsable de conectar la lógica de envío y validación del formulario.
|
|
20
21
|
*
|
|
21
|
-
* **
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* - `::before` —
|
|
26
|
-
* - `::after` —
|
|
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
|
-
*
|
|
29
|
-
* - `'check_box_outline_blank'` (
|
|
30
|
-
* - `'check_box'` (
|
|
31
|
-
* - `'indeterminate_check_box'` (
|
|
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
|
-
* **
|
|
34
|
-
*
|
|
35
|
-
*
|
|
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 -
|
|
38
|
-
*
|
|
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="
|
|
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 -
|
|
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
|
-
*
|
|
65
|
+
* Texto de la etiqueta mostrado a la derecha del icono del checkbox.
|
|
57
66
|
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
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
|
-
*
|
|
75
|
+
* Si el checkbox está actualmente marcado.
|
|
67
76
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
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
|
-
*
|
|
78
|
-
*
|
|
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
|
-
*
|
|
94
|
+
* Tamaño visual del icono del checkbox.
|
|
86
95
|
*
|
|
87
|
-
*
|
|
88
|
-
* input
|
|
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
|
-
* |
|
|
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
|
-
*
|
|
104
|
-
*
|
|
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
|
-
*
|
|
112
|
-
*
|
|
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
|
-
/**
|
|
127
|
+
/** Referencia directa al elemento input nativo para acceso programático. */
|
|
119
128
|
@query('input') private _input!: HTMLInputElement;
|
|
120
129
|
|
|
121
130
|
/**
|
|
122
|
-
*
|
|
123
|
-
*
|
|
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
|
-
*
|
|
126
|
-
* DOM
|
|
127
|
-
*
|
|
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 -
|
|
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'))
|
|
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
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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('
|
|
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
|
|
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
|
|
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
|
|
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('
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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('
|
|
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('
|
|
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
|
|
15
|
+
* Componente Material Design 3 Chip.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* Los chips (fichas) son elementos compactos e interactivos que representan acciones, filtros,
|
|
18
|
+
* atributos o entradas de usuario. Son contenedores solo visuales — el consumidor
|
|
19
|
+
* es dueño de todo el manejo del estado (selección, eliminación, estado de filtro activo).
|
|
20
20
|
*
|
|
21
|
-
* **
|
|
21
|
+
* **Referencia de la especificación M3:** `m3-docs/components/chips/specs.md`
|
|
22
22
|
*
|
|
23
|
-
* **
|
|
24
|
-
* - `assist` (
|
|
25
|
-
*
|
|
26
|
-
* - `filter` —
|
|
27
|
-
* `selected`. Alias: `fill`.
|
|
28
|
-
* - `input` —
|
|
29
|
-
*
|
|
30
|
-
* - `suggestion` —
|
|
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
|
|
33
|
-
* -
|
|
34
|
-
* -
|
|
35
|
-
* -
|
|
36
|
-
* - `medium`
|
|
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
|
-
* **
|
|
39
|
-
* `assist`
|
|
40
|
-
*
|
|
41
|
-
* `filter`
|
|
42
|
-
*
|
|
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 -
|
|
45
|
-
*
|
|
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
|
-
* <!--
|
|
49
|
+
* <!-- Chip de filtro con estado seleccionado -->
|
|
50
50
|
* <moni-chip variant="filter" selected>Technology</moni-chip>
|
|
51
51
|
*
|
|
52
|
-
* <!--
|
|
52
|
+
* <!-- Chip de entrada (etiqueta/token) -->
|
|
53
53
|
* <moni-chip variant="input" removable icon="label">TypeScript</moni-chip>
|
|
54
54
|
*
|
|
55
|
-
* <!--
|
|
55
|
+
* <!-- Chip de asistencia con icono -->
|
|
56
56
|
* <moni-chip icon="directions_car">Get directions</moni-chip>
|
|
57
57
|
* ```
|
|
58
58
|
*
|
|
59
|
-
* @slot default -
|
|
60
|
-
* @slot icon -
|
|
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 -
|
|
63
|
-
* @csspart label -
|
|
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
|
-
/**
|
|
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;
|