@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
|
@@ -16,7 +16,7 @@ describe('moni-button-group', () => {
|
|
|
16
16
|
group.remove();
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
-
it('
|
|
19
|
+
it('propaga el tamaño a los botones hijos', async () => {
|
|
20
20
|
group.size = 'large';
|
|
21
21
|
const btn1 = document.createElement('moni-button') as MoniButton;
|
|
22
22
|
const btn2 = document.createElement('moni-button') as MoniButton;
|
|
@@ -31,7 +31,7 @@ describe('moni-button-group', () => {
|
|
|
31
31
|
expect(btn2.getAttribute('size')).toBe('large');
|
|
32
32
|
});
|
|
33
33
|
|
|
34
|
-
it('
|
|
34
|
+
it('establece las formas apropiadas para la variante connected', async () => {
|
|
35
35
|
group.variant = 'connected';
|
|
36
36
|
const btn1 = document.createElement('moni-button') as MoniButton;
|
|
37
37
|
const btn2 = document.createElement('moni-button') as MoniButton;
|
|
@@ -50,7 +50,7 @@ describe('moni-button-group', () => {
|
|
|
50
50
|
expect(btn3.getAttribute('shape')).toBe('right-round-flat');
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
-
it('
|
|
53
|
+
it('usa formas redondeadas para la variante connected cuando se establece un gap', async () => {
|
|
54
54
|
group.variant = 'connected';
|
|
55
55
|
group.gap = '8px';
|
|
56
56
|
const btn1 = document.createElement('moni-button') as MoniButton;
|
|
@@ -66,7 +66,7 @@ describe('moni-button-group', () => {
|
|
|
66
66
|
expect(btn2.getAttribute('shape')).toBe('right-round');
|
|
67
67
|
});
|
|
68
68
|
|
|
69
|
-
it('
|
|
69
|
+
it('gestiona los toggles activos en modo de selección única (multi=false)', async () => {
|
|
70
70
|
const btn1 = document.createElement('moni-button') as MoniButton;
|
|
71
71
|
const btn2 = document.createElement('moni-button') as MoniButton;
|
|
72
72
|
group.appendChild(btn1);
|
|
@@ -76,14 +76,14 @@ describe('moni-button-group', () => {
|
|
|
76
76
|
await btn1.updateComplete;
|
|
77
77
|
await btn2.updateComplete;
|
|
78
78
|
|
|
79
|
-
//
|
|
79
|
+
// Clic en btn1
|
|
80
80
|
btn1.click();
|
|
81
81
|
await btn1.updateComplete;
|
|
82
82
|
await btn2.updateComplete;
|
|
83
83
|
expect(btn1.active).toBe(true);
|
|
84
84
|
expect(btn2.active).toBe(false);
|
|
85
85
|
|
|
86
|
-
//
|
|
86
|
+
// Clic en btn2
|
|
87
87
|
btn2.click();
|
|
88
88
|
await btn1.updateComplete;
|
|
89
89
|
await btn2.updateComplete;
|
|
@@ -91,7 +91,7 @@ describe('moni-button-group', () => {
|
|
|
91
91
|
expect(btn2.active).toBe(true);
|
|
92
92
|
});
|
|
93
93
|
|
|
94
|
-
it('
|
|
94
|
+
it('gestiona los toggles activos en modo de selección múltiple (multi=true)', async () => {
|
|
95
95
|
group.multi = true;
|
|
96
96
|
const btn1 = document.createElement('moni-button') as MoniButton;
|
|
97
97
|
const btn2 = document.createElement('moni-button') as MoniButton;
|
|
@@ -110,38 +110,38 @@ describe('moni-button-group', () => {
|
|
|
110
110
|
expect(btn2.active).toBe(true);
|
|
111
111
|
});
|
|
112
112
|
|
|
113
|
-
it('
|
|
113
|
+
it('renderiza role="group" en el contenedor por defecto (accesibilidad M3)', async () => {
|
|
114
114
|
await group.updateComplete;
|
|
115
115
|
const container = group.shadowRoot?.querySelector('[part="container"]');
|
|
116
116
|
expect(container?.getAttribute('role')).toBe('group');
|
|
117
117
|
});
|
|
118
118
|
|
|
119
|
-
it('
|
|
119
|
+
it('soporta la sobrescritura de role="toolbar" para grupos de acciones de la aplicación', async () => {
|
|
120
120
|
group.role = 'toolbar';
|
|
121
121
|
await group.updateComplete;
|
|
122
122
|
const container = group.shadowRoot?.querySelector('[part="container"]');
|
|
123
123
|
expect(container?.getAttribute('role')).toBe('toolbar');
|
|
124
124
|
});
|
|
125
125
|
|
|
126
|
-
it('
|
|
126
|
+
it('reenvía aria-label al contenedor', async () => {
|
|
127
127
|
group.label = 'Text formatting';
|
|
128
128
|
await group.updateComplete;
|
|
129
129
|
const container = group.shadowRoot?.querySelector('[part="container"]');
|
|
130
130
|
expect(container?.getAttribute('aria-label')).toBe('Text formatting');
|
|
131
131
|
});
|
|
132
132
|
|
|
133
|
-
it('
|
|
133
|
+
it('reenvía aria-labelledby al contenedor', async () => {
|
|
134
134
|
group.labelledBy = 'group-title';
|
|
135
135
|
await group.updateComplete;
|
|
136
136
|
const container = group.shadowRoot?.querySelector('[part="container"]');
|
|
137
137
|
expect(container?.getAttribute('aria-labelledby')).toBe('group-title');
|
|
138
138
|
});
|
|
139
139
|
|
|
140
|
-
it('
|
|
140
|
+
it('no emite aria-label cuando la etiqueta está vacía (limpieza de accesibilidad M3)', async () => {
|
|
141
141
|
await group.updateComplete;
|
|
142
142
|
const container = group.shadowRoot?.querySelector('[part="container"]');
|
|
143
|
-
// aria-label
|
|
144
|
-
//
|
|
143
|
+
// el atributo aria-label debería estar ausente o ser una cadena vacía;
|
|
144
|
+
// usar nothing en lit elimina el atributo por completo.
|
|
145
145
|
const aria = container?.getAttribute('aria-label');
|
|
146
146
|
expect(aria === null || aria === '').toBe(true);
|
|
147
147
|
});
|
|
@@ -10,73 +10,107 @@ import { customElement, property, queryAssignedElements } from 'lit/decorators.j
|
|
|
10
10
|
import { MoniElement, sharedStyles } from './_base/index.js';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
|
-
* Material Design 3 Button Group
|
|
13
|
+
* Componente Material Design 3 Button Group.
|
|
14
14
|
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* Organiza múltiples componentes `<moni-button>` o `<moni-icon-button>`
|
|
16
|
+
* en una sola fila.
|
|
17
17
|
*
|
|
18
|
-
* **
|
|
19
|
-
* - `standard` (
|
|
20
|
-
* - `connected` —
|
|
21
|
-
*
|
|
22
|
-
*
|
|
18
|
+
* **Variantes:**
|
|
19
|
+
* - `standard` (por defecto) — Una fila flex simple con un espacio entre botones.
|
|
20
|
+
* - `connected` — El reemplazo de M3 Expressive para los botones segmentados. En este
|
|
21
|
+
* modo, los botones comparten bordes y forman una sola forma de píldora continua. El
|
|
22
|
+
* grupo gestiona el estado de selección única/múltiple de sus hijos.
|
|
23
23
|
*
|
|
24
|
-
*
|
|
25
|
-
* - **
|
|
26
|
-
* (`left-round-flat`, `no-round`, `right-round-flat`)
|
|
27
|
-
*
|
|
28
|
-
* - **
|
|
29
|
-
* `active
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* - **
|
|
24
|
+
* **Detalles de la variante `connected`:**
|
|
25
|
+
* - **Propagación de forma:** El grupo propaga automáticamente las clases de forma M3
|
|
26
|
+
* (`left-round-flat`, `no-round`, `right-round-flat`) a sus hijos para
|
|
27
|
+
* que se entrelacen sin problemas.
|
|
28
|
+
* - **Gestión del interruptor:** El grupo escucha los clics de los hijos y cambia sus
|
|
29
|
+
* atributos `active`. Cuando `multi=false` (por defecto), solo un botón puede estar
|
|
30
|
+
* activo a la vez (comportamiento de radio button). Cuando `multi=true`, múltiples botones
|
|
31
|
+
* pueden estar activos (comportamiento de checkbox).
|
|
32
|
+
* - **Propagación de eventos:** Dispara un evento `'change'` cuando la selección cambia.
|
|
33
33
|
*
|
|
34
|
-
* **
|
|
35
|
-
* -
|
|
36
|
-
* -
|
|
37
|
-
*
|
|
34
|
+
* **Accesibilidad:**
|
|
35
|
+
* - Renderiza con `role="group"` (puede ser sobrescrito a `toolbar` o `radiogroup`).
|
|
36
|
+
* - Los consumidores deben proporcionar un atributo `aria-label` o `aria-labelledby`
|
|
37
|
+
* para identificar el propósito del grupo para las tecnologías de asistencia.
|
|
38
38
|
*
|
|
39
|
-
* @fires change -
|
|
40
|
-
*
|
|
39
|
+
* @fires change - Disparado cuando se hace clic en un botón en modo `connected` y el
|
|
40
|
+
* estado de selección se actualiza.
|
|
41
41
|
*
|
|
42
42
|
* @example
|
|
43
43
|
* ```html
|
|
44
|
-
* <!--
|
|
45
|
-
* <moni-button-group variant="connected" label="
|
|
44
|
+
* <!-- Grupo conectado de selección única -->
|
|
45
|
+
* <moni-button-group variant="connected" label="Alineación">
|
|
46
46
|
* <moni-button icon="format_align_left" active></moni-button>
|
|
47
47
|
* <moni-button icon="format_align_center"></moni-button>
|
|
48
48
|
* <moni-button icon="format_align_right"></moni-button>
|
|
49
49
|
* </moni-button-group>
|
|
50
50
|
*
|
|
51
|
-
* <!--
|
|
51
|
+
* <!-- Fila estándar de botones -->
|
|
52
52
|
* <moni-button-group gap="1rem">
|
|
53
|
-
* <moni-button variant="text">
|
|
54
|
-
* <moni-button>
|
|
53
|
+
* <moni-button variant="text">Cancelar</moni-button>
|
|
54
|
+
* <moni-button>Guardar</moni-button>
|
|
55
55
|
* </moni-button-group>
|
|
56
56
|
* ```
|
|
57
57
|
*
|
|
58
|
-
* @slot default -
|
|
58
|
+
* @slot default - Los elementos `<moni-button>` que conforman el grupo.
|
|
59
59
|
*/
|
|
60
60
|
@customElement('moni-button-group')
|
|
61
61
|
export class MoniButtonGroup extends MoniElement {
|
|
62
|
+
/**
|
|
63
|
+
* Variante visual del grupo de botones.
|
|
64
|
+
* - `standard`: Los elementos se espacian normalmente.
|
|
65
|
+
* - `connected`: Los elementos se unen con bordes colapsados y radios internos aplanados.
|
|
66
|
+
* @type {'standard' | 'connected'}
|
|
67
|
+
* @default 'standard'
|
|
68
|
+
*/
|
|
62
69
|
@property({ reflect: true })
|
|
63
70
|
variant: 'standard' | 'connected' = 'standard';
|
|
64
71
|
|
|
72
|
+
/**
|
|
73
|
+
* Tamaño de los botones en el grupo. Si se especifica, se propaga hacia abajo a los hijos.
|
|
74
|
+
* @type {'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'extra'}
|
|
75
|
+
* @default 'medium'
|
|
76
|
+
*/
|
|
65
77
|
@property({ reflect: true })
|
|
66
78
|
size: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'extra' = 'medium';
|
|
67
79
|
|
|
80
|
+
/**
|
|
81
|
+
* Permite que múltiples botones estén activos a la vez (solo aplica a grupos seleccionables).
|
|
82
|
+
* @type {boolean}
|
|
83
|
+
*/
|
|
68
84
|
@property({ type: Boolean, reflect: true })
|
|
69
85
|
multi = false;
|
|
70
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Espacio CSS personalizado entre botones (ej., '1rem').
|
|
89
|
+
* Solo se aplica cuando la variante es 'standard'.
|
|
90
|
+
* @type {string}
|
|
91
|
+
*/
|
|
71
92
|
@property()
|
|
72
93
|
gap = '';
|
|
73
94
|
|
|
95
|
+
/**
|
|
96
|
+
* Rol ARIA del contenedor del grupo.
|
|
97
|
+
* @type {'group' | 'toolbar' | 'radiogroup'}
|
|
98
|
+
* @default 'group'
|
|
99
|
+
*/
|
|
74
100
|
@property({ reflect: true })
|
|
75
101
|
role: 'group' | 'toolbar' | 'radiogroup' = 'group';
|
|
76
102
|
|
|
103
|
+
/**
|
|
104
|
+
* Una etiqueta accesible para el grupo (`aria-label`).
|
|
105
|
+
* @type {string}
|
|
106
|
+
*/
|
|
77
107
|
@property({ reflect: true })
|
|
78
108
|
label = '';
|
|
79
109
|
|
|
110
|
+
/**
|
|
111
|
+
* ID de un elemento que etiqueta este grupo (`aria-labelledby`).
|
|
112
|
+
* @type {string}
|
|
113
|
+
*/
|
|
80
114
|
@property({ reflect: true, attribute: 'labelled-by' })
|
|
81
115
|
labelledBy = '';
|
|
82
116
|
|
|
@@ -124,6 +158,11 @@ export class MoniButtonGroup extends MoniElement {
|
|
|
124
158
|
`
|
|
125
159
|
];
|
|
126
160
|
|
|
161
|
+
/**
|
|
162
|
+
* Hook del ciclo de vida reactivo (Lit).
|
|
163
|
+
* Detecta alteraciones estructurales en el propio grupo (como `variant`, `size` o `gap`)
|
|
164
|
+
* y fuerza una re-sincronización de todos los botones hijos para aplicar las físicas CSS.
|
|
165
|
+
*/
|
|
127
166
|
protected override updated(changedProperties: Map<string | number | symbol, unknown>) {
|
|
128
167
|
super.updated(changedProperties);
|
|
129
168
|
if (changedProperties.has('variant') || changedProperties.has('size') || changedProperties.has('gap')) {
|
|
@@ -131,6 +170,11 @@ export class MoniButtonGroup extends MoniElement {
|
|
|
131
170
|
}
|
|
132
171
|
}
|
|
133
172
|
|
|
173
|
+
/**
|
|
174
|
+
* Manejador del slot interno (`<slot>`).
|
|
175
|
+
* Cuando el desarrollador inyecta dinámicamente o remueve botones en runtime,
|
|
176
|
+
* re-sincroniza las formas (shapes) y tamaños de todo el listado.
|
|
177
|
+
*/
|
|
134
178
|
private handleSlotChange() {
|
|
135
179
|
this.updateChildren();
|
|
136
180
|
}
|
|
@@ -146,6 +190,13 @@ export class MoniButtonGroup extends MoniElement {
|
|
|
146
190
|
return gap;
|
|
147
191
|
}
|
|
148
192
|
|
|
193
|
+
/**
|
|
194
|
+
* Sincronizador de Propiedades (Engine interno).
|
|
195
|
+
* Itera sobre cada botón hijo para transferirle jerárquicamente las configuraciones
|
|
196
|
+
* del grupo. Si el grupo es del tipo `connected` (botones pegados), evalúa matemáticamente
|
|
197
|
+
* la posición del índice actual (primero, en medio o último) e inyecta la propiedad `shape`
|
|
198
|
+
* correspondiente (`left-round-flat`, `inner-round`, etc.) para formar una cápsula unificada.
|
|
199
|
+
*/
|
|
149
200
|
private updateChildren() {
|
|
150
201
|
const buttons = this.slottedButtons.filter(
|
|
151
202
|
(el) => el.tagName.toLowerCase() === 'moni-button' || el.tagName.toLowerCase() === 'moni-icon-button'
|
|
@@ -188,6 +239,12 @@ export class MoniButtonGroup extends MoniElement {
|
|
|
188
239
|
});
|
|
189
240
|
}
|
|
190
241
|
|
|
242
|
+
/**
|
|
243
|
+
* Maneja la interacción táctil o de mouse (Pointer Down).
|
|
244
|
+
* Genera un micro-efecto físico (Squish effect). Cuando el usuario presiona un botón
|
|
245
|
+
* dentro de un listado estándar, empuja físicamente (`scaleX` / `translateX`) a los
|
|
246
|
+
* botones adyacentes para simular presión material y desplazamiento.
|
|
247
|
+
*/
|
|
191
248
|
private handlePointerDown(e: PointerEvent) {
|
|
192
249
|
if (this.variant !== 'standard') return;
|
|
193
250
|
const target = e.target as HTMLElement;
|
|
@@ -215,6 +272,11 @@ export class MoniButtonGroup extends MoniElement {
|
|
|
215
272
|
}
|
|
216
273
|
}
|
|
217
274
|
|
|
275
|
+
/**
|
|
276
|
+
* Conclusión de la interacción táctil (Pointer Up).
|
|
277
|
+
* Restaura todas las transformaciones elásticas aplicadas a los botones adyacentes
|
|
278
|
+
* a su estado nativo neutro.
|
|
279
|
+
*/
|
|
218
280
|
private handlePointerUp() {
|
|
219
281
|
const buttons = this.slottedButtons.filter(
|
|
220
282
|
(el) => el.tagName.toLowerCase() === 'moni-button' || el.tagName.toLowerCase() === 'moni-icon-button'
|
|
@@ -225,6 +287,11 @@ export class MoniButtonGroup extends MoniElement {
|
|
|
225
287
|
});
|
|
226
288
|
}
|
|
227
289
|
|
|
290
|
+
/**
|
|
291
|
+
* Interceptor de clics de delegación.
|
|
292
|
+
* En grupos de tipo 'segment', garantiza que solo un botón tenga la clase activa
|
|
293
|
+
* o el atributo encendido de forma excluyente, actuando como un gestor de radio-buttons.
|
|
294
|
+
*/
|
|
228
295
|
private handleClick(e: Event) {
|
|
229
296
|
const target = e.target as HTMLElement;
|
|
230
297
|
const clickedButton = target.closest('moni-button, moni-icon-button');
|
|
@@ -268,6 +335,17 @@ export class MoniButtonGroup extends MoniElement {
|
|
|
268
335
|
);
|
|
269
336
|
}
|
|
270
337
|
|
|
338
|
+
/**
|
|
339
|
+
* Renders the button group container with `role="group"` semantics.
|
|
340
|
+
*
|
|
341
|
+
* The group is a flex container that distributes its slotted `<moni-button>`
|
|
342
|
+
* or `<moni-button-segment>` children in a row or column (based on `orientation`).
|
|
343
|
+
* CSS handles the shared-border collapse between adjacent segments:
|
|
344
|
+
* - Middle segments use `border-radius: 0` and `margin-inline-start: -1px`
|
|
345
|
+
* to prevent doubled borders.
|
|
346
|
+
* - `_syncSegments()` in `firstUpdated()` injects `left-round` / `right-round`
|
|
347
|
+
* shape attributes into the first and last children for correct pill termination.
|
|
348
|
+
*/
|
|
271
349
|
override render() {
|
|
272
350
|
const resolvedGap = this.getGapValue(this.gap);
|
|
273
351
|
const inlineStyles = resolvedGap
|
|
@@ -11,46 +11,74 @@ import { MoniElement, sharedStyles } from './_base/index.js';
|
|
|
11
11
|
import './moni-icon.js';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
* Material Design 3 Segmented Button
|
|
14
|
+
* Componente Material Design 3 Segmented Button (Heredado).
|
|
15
15
|
*
|
|
16
|
-
* **
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
16
|
+
* **Aviso de obsolescencia:** La especificación M3 (`m3-docs/components/segmented-buttons/overview.md`)
|
|
17
|
+
* ha reemplazado el componente a medida "segmented button" con botones estándar organizados
|
|
18
|
+
* en un grupo "conectado". Por favor usa `<moni-button-group variant="connected">`
|
|
19
|
+
* conteniendo elementos `<moni-button>` estándar en lugar de este componente.
|
|
20
20
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
21
|
+
* Este componente permanece por compatibilidad hacia atrás pero será eliminado en una
|
|
22
|
+
* futura versión mayor. Renderiza un segmento único dentro de un `<moni-segmented-button>`.
|
|
23
23
|
*
|
|
24
|
-
* @deprecated
|
|
24
|
+
* @deprecated Usa `<moni-button-group variant="connected">` en su lugar.
|
|
25
25
|
*
|
|
26
26
|
* @example
|
|
27
27
|
* ```html
|
|
28
|
-
* <!--
|
|
28
|
+
* <!-- Uso heredado (no recomendado) -->
|
|
29
29
|
* <moni-segmented-button>
|
|
30
|
-
* <moni-button-segment value="day" checked>
|
|
31
|
-
* <moni-button-segment value="week">
|
|
30
|
+
* <moni-button-segment value="day" checked>Día</moni-button-segment>
|
|
31
|
+
* <moni-button-segment value="week">Semana</moni-button-segment>
|
|
32
32
|
* </moni-segmented-button>
|
|
33
33
|
* ```
|
|
34
34
|
*
|
|
35
|
-
* @slot default -
|
|
35
|
+
* @slot default - El texto de la etiqueta del segmento.
|
|
36
36
|
*/
|
|
37
37
|
@customElement('moni-button-segment')
|
|
38
38
|
export class MoniButtonSegment extends MoniElement {
|
|
39
|
+
/**
|
|
40
|
+
* Valor asociado con el segmento, usado por el grupo padre.
|
|
41
|
+
* @type {string}
|
|
42
|
+
* @default 'on'
|
|
43
|
+
*/
|
|
39
44
|
@property({ reflect: true })
|
|
40
45
|
value = 'on';
|
|
41
46
|
|
|
47
|
+
/**
|
|
48
|
+
* Estado seleccionado del segmento.
|
|
49
|
+
* @type {boolean}
|
|
50
|
+
*/
|
|
42
51
|
@property({ type: Boolean, reflect: true })
|
|
43
52
|
checked = false;
|
|
44
53
|
|
|
54
|
+
/**
|
|
55
|
+
* Tamaño del segmento (usualmente heredado del botón segmentado padre).
|
|
56
|
+
* @type {'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'extra'}
|
|
57
|
+
* @default 'medium'
|
|
58
|
+
*/
|
|
45
59
|
@property({ reflect: true })
|
|
46
60
|
size: 'xsmall' | 'small' | 'medium' | 'large' | 'xlarge' | 'extra' = 'medium';
|
|
47
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Deshabilita el segmento.
|
|
64
|
+
* @type {boolean}
|
|
65
|
+
*/
|
|
48
66
|
@property({ type: Boolean, reflect: true })
|
|
49
67
|
disabled = false;
|
|
50
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Índice posicional del segmento dentro del grupo.
|
|
71
|
+
* Determina la lógica de redondeo del border-radius.
|
|
72
|
+
* @type {'first' | 'middle' | 'last' | 'solo'}
|
|
73
|
+
* @default 'solo'
|
|
74
|
+
*/
|
|
51
75
|
@property({ reflect: true })
|
|
52
76
|
position: 'first' | 'middle' | 'last' | 'solo' = 'solo';
|
|
53
77
|
|
|
78
|
+
/**
|
|
79
|
+
* Si es verdadero, oculta el icono de marca de verificación que normalmente reemplaza al icono inicial cuando se selecciona.
|
|
80
|
+
* @type {boolean}
|
|
81
|
+
*/
|
|
54
82
|
@property({ type: Boolean, reflect: true, attribute: 'hide-check' })
|
|
55
83
|
hideCheck = false;
|
|
56
84
|
|
|
@@ -290,6 +318,19 @@ export class MoniButtonSegment extends MoniElement {
|
|
|
290
318
|
`
|
|
291
319
|
];
|
|
292
320
|
|
|
321
|
+
/**
|
|
322
|
+
* Renders the segment as a `role="radio"` toggle button within its group.
|
|
323
|
+
*
|
|
324
|
+
* **`role="radio"` + `aria-checked`:**
|
|
325
|
+
* Per the ARIA Segmented Button pattern, each segment acts as a radio button
|
|
326
|
+
* (`role="radio"`, `aria-checked=${this.active}`) within a `role="radiogroup"`
|
|
327
|
+
* container (the parent `<moni-segmented-button>`).
|
|
328
|
+
*
|
|
329
|
+
* **Checkmark icon:**
|
|
330
|
+
* When `active=true`, a `<moni-icon name="check">` is prepended to the label
|
|
331
|
+
* to signal the selected state visually (M3 Segmented Button spec, Figure 5).
|
|
332
|
+
* This icon disappears with a `scale(0)` transition when `active=false`.
|
|
333
|
+
*/
|
|
293
334
|
override render() {
|
|
294
335
|
return html`
|
|
295
336
|
<button class="button ${this.size}" type="button" ?disabled=${this.disabled}>
|
|
@@ -14,13 +14,13 @@ describe('moni-button', () => {
|
|
|
14
14
|
el.remove();
|
|
15
15
|
});
|
|
16
16
|
|
|
17
|
-
it('
|
|
17
|
+
it('renderiza un <button> nativo por defecto', async () => {
|
|
18
18
|
await el.updateComplete;
|
|
19
19
|
const button = el.shadowRoot?.querySelector('button');
|
|
20
20
|
expect(button).toBeTruthy();
|
|
21
21
|
});
|
|
22
22
|
|
|
23
|
-
it('
|
|
23
|
+
it('renderiza un <a> cuando el href está establecido', async () => {
|
|
24
24
|
el.href = 'https://example.com';
|
|
25
25
|
await el.updateComplete;
|
|
26
26
|
const a = el.shadowRoot?.querySelector('a');
|
|
@@ -28,27 +28,27 @@ describe('moni-button', () => {
|
|
|
28
28
|
expect(a?.getAttribute('href')).toBe('https://example.com');
|
|
29
29
|
});
|
|
30
30
|
|
|
31
|
-
it('
|
|
31
|
+
it('aplica la clase shape=circle en el botón', async () => {
|
|
32
32
|
el.shape = 'circle';
|
|
33
33
|
await el.updateComplete;
|
|
34
34
|
const button = el.shadowRoot?.querySelector('button');
|
|
35
35
|
expect(button?.classList.contains('circle')).toBe(true);
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
-
it('
|
|
38
|
+
it('oculta la parte del label cuando shape=circle (verifica el selector :host)', async () => {
|
|
39
39
|
el.shape = 'circle';
|
|
40
40
|
el.textContent = 'Click me';
|
|
41
41
|
await el.updateComplete;
|
|
42
|
-
//
|
|
43
|
-
//
|
|
44
|
-
//
|
|
45
|
-
//
|
|
42
|
+
// La regla :host([shape='circle']) [part='label'] vive en las hojas de estilo
|
|
43
|
+
// shadow. getComputedStyle de jsdom está limitado, así que verificamos la
|
|
44
|
+
// condición estructural: el host tiene el atributo shape reflejado
|
|
45
|
+
// y el elemento [part='label'] existe para el contenido del slot.
|
|
46
46
|
expect(el.getAttribute('shape')).toBe('circle');
|
|
47
47
|
const label = el.shadowRoot?.querySelector('[part="label"]');
|
|
48
48
|
expect(label).toBeTruthy();
|
|
49
49
|
});
|
|
50
50
|
|
|
51
|
-
it('
|
|
51
|
+
it('mantiene el label renderizado cuando shape=square', async () => {
|
|
52
52
|
el.shape = 'square';
|
|
53
53
|
el.textContent = 'Square';
|
|
54
54
|
await el.updateComplete;
|
|
@@ -57,7 +57,7 @@ describe('moni-button', () => {
|
|
|
57
57
|
expect(el.getAttribute('shape')).toBe('square');
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
-
it('
|
|
60
|
+
it('aplica la clase shape=square en el botón', async () => {
|
|
61
61
|
el.shape = 'square';
|
|
62
62
|
await el.updateComplete;
|
|
63
63
|
const button = el.shadowRoot?.querySelector('button');
|
|
@@ -65,7 +65,7 @@ describe('moni-button', () => {
|
|
|
65
65
|
expect(button?.classList.contains('circle')).toBe(false);
|
|
66
66
|
});
|
|
67
67
|
|
|
68
|
-
it('
|
|
68
|
+
it('aplica la clase shape=circle en el botón', async () => {
|
|
69
69
|
el.shape = 'circle';
|
|
70
70
|
await el.updateComplete;
|
|
71
71
|
const button = el.shadowRoot?.querySelector('button');
|
|
@@ -73,21 +73,21 @@ describe('moni-button', () => {
|
|
|
73
73
|
expect(button?.classList.contains('square')).toBe(false);
|
|
74
74
|
});
|
|
75
75
|
|
|
76
|
-
it('
|
|
76
|
+
it('aplica la clase de variante para outlined', async () => {
|
|
77
77
|
el.variant = 'outlined';
|
|
78
78
|
await el.updateComplete;
|
|
79
79
|
const button = el.shadowRoot?.querySelector('button');
|
|
80
80
|
expect(button?.classList.contains('border')).toBe(true);
|
|
81
81
|
});
|
|
82
82
|
|
|
83
|
-
it('
|
|
83
|
+
it('aplica la clase de tamaño para large', async () => {
|
|
84
84
|
el.size = 'large';
|
|
85
85
|
await el.updateComplete;
|
|
86
86
|
const button = el.shadowRoot?.querySelector('button');
|
|
87
87
|
expect(button?.classList.contains('large')).toBe(true);
|
|
88
88
|
});
|
|
89
89
|
|
|
90
|
-
it('
|
|
90
|
+
it('renderiza un ícono cuando el atributo icon está establecido', async () => {
|
|
91
91
|
el.icon = 'add';
|
|
92
92
|
await el.updateComplete;
|
|
93
93
|
const icon = el.shadowRoot?.querySelector('.icon');
|
|
@@ -97,7 +97,7 @@ describe('moni-button', () => {
|
|
|
97
97
|
expect(moniIcon?.getAttribute('name')).toBe('add');
|
|
98
98
|
});
|
|
99
99
|
|
|
100
|
-
it('
|
|
100
|
+
it('muestra un spinner de carga junto al ícono/label cuando loading=true', async () => {
|
|
101
101
|
el.loading = true;
|
|
102
102
|
await el.updateComplete;
|
|
103
103
|
const progress = el.shadowRoot?.querySelector('moni-progress');
|
|
@@ -108,7 +108,7 @@ describe('moni-button', () => {
|
|
|
108
108
|
expect(label).toBeTruthy();
|
|
109
109
|
});
|
|
110
110
|
|
|
111
|
-
it('
|
|
111
|
+
it('renderiza un <a> con el spinner de carga cuando href + loading están establecidos', async () => {
|
|
112
112
|
el.href = '#';
|
|
113
113
|
el.loading = true;
|
|
114
114
|
await el.updateComplete;
|
|
@@ -118,14 +118,14 @@ describe('moni-button', () => {
|
|
|
118
118
|
expect(progress).toBeTruthy();
|
|
119
119
|
});
|
|
120
120
|
|
|
121
|
-
it('
|
|
121
|
+
it('establece aria-busy en el botón cuando está cargando', async () => {
|
|
122
122
|
el.loading = true;
|
|
123
123
|
await el.updateComplete;
|
|
124
124
|
const button = el.shadowRoot?.querySelector('button');
|
|
125
125
|
expect(button?.getAttribute('aria-busy')).toBe('true');
|
|
126
126
|
});
|
|
127
127
|
|
|
128
|
-
it('
|
|
128
|
+
it('reenvía disabled al botón nativo', async () => {
|
|
129
129
|
el.disabled = true;
|
|
130
130
|
await el.updateComplete;
|
|
131
131
|
const button = el.shadowRoot?.querySelector(
|
|
@@ -134,23 +134,25 @@ describe('moni-button', () => {
|
|
|
134
134
|
expect(button.disabled).toBe(true);
|
|
135
135
|
});
|
|
136
136
|
|
|
137
|
-
it('
|
|
137
|
+
it('registra una advertencia de obsolescencia cuando se usa size="extra" (usar size="xlarge" según M3)', async () => {
|
|
138
|
+
(el.constructor as any)._deprecationWarned = false;
|
|
138
139
|
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
document.body.appendChild(
|
|
142
|
-
await
|
|
140
|
+
const extraBtn = document.createElement('moni-button') as MoniButton;
|
|
141
|
+
extraBtn.size = 'extra';
|
|
142
|
+
document.body.appendChild(extraBtn);
|
|
143
|
+
await extraBtn.updateComplete;
|
|
143
144
|
const call = warnSpy.mock.calls.find((c) =>
|
|
144
145
|
String(c[0]).includes('[moni-ui]') &&
|
|
145
146
|
String(c[0]).includes('size="extra"')
|
|
146
147
|
);
|
|
147
|
-
expect(call, '
|
|
148
|
+
expect(call, 'se esperaba que una advertencia de obsolescencia mencionara size="extra"').toBeTruthy();
|
|
149
|
+
extraBtn.remove();
|
|
148
150
|
warnSpy.mockRestore();
|
|
149
151
|
});
|
|
150
152
|
|
|
151
|
-
it('
|
|
153
|
+
it('no registra una advertencia de obsolescencia para los valores de tamaño compatibles con M3', async () => {
|
|
152
154
|
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
|
|
153
|
-
//
|
|
155
|
+
// Usar un tamaño nuevo para asegurar que no se registre una obsolescencia obsoleta de M3.
|
|
154
156
|
const fresh = document.createElement('moni-button') as MoniButton;
|
|
155
157
|
fresh.size = 'xlarge';
|
|
156
158
|
document.body.appendChild(fresh);
|