ng-comps 1.0.2 → 2.0.0

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 (197) hide show
  1. package/fesm2022/ng-comps.mjs +4254 -0
  2. package/package.json +54 -58
  3. package/src/styles.css +54 -0
  4. package/types/ng-comps.d.ts +1348 -0
  5. package/.editorconfig +0 -17
  6. package/.github/copilot-instructions.md +0 -55
  7. package/.github/workflows/ci.yml +0 -29
  8. package/.prettierrc +0 -12
  9. package/.storybook/main.ts +0 -21
  10. package/.storybook/preview.ts +0 -27
  11. package/.storybook/tsconfig.doc.json +0 -10
  12. package/.storybook/tsconfig.json +0 -15
  13. package/.storybook/typings.d.ts +0 -4
  14. package/.vscode/extensions.json +0 -4
  15. package/.vscode/launch.json +0 -20
  16. package/.vscode/mcp.json +0 -9
  17. package/.vscode/tasks.json +0 -42
  18. package/ACCESSIBILITY.md +0 -127
  19. package/angular.json +0 -106
  20. package/documentation.json +0 -13394
  21. package/ng-package.json +0 -27
  22. package/public/favicon.ico +0 -0
  23. package/scripts/prepare-package.mjs +0 -80
  24. package/src/app/a11y/accessibility.utils.ts +0 -35
  25. package/src/app/a11y/index.ts +0 -6
  26. package/src/app/accessibility/ng-comps.a11y.spec.ts +0 -108
  27. package/src/app/app.config.ts +0 -11
  28. package/src/app/app.css +0 -107
  29. package/src/app/app.html +0 -48
  30. package/src/app/app.routes.ts +0 -3
  31. package/src/app/app.spec.ts +0 -23
  32. package/src/app/app.ts +0 -10
  33. package/src/app/components/accordion/index.ts +0 -2
  34. package/src/app/components/accordion/mf-accordion.component.css +0 -38
  35. package/src/app/components/accordion/mf-accordion.component.spec.ts +0 -48
  36. package/src/app/components/accordion/mf-accordion.component.ts +0 -53
  37. package/src/app/components/alert/index.ts +0 -2
  38. package/src/app/components/alert/mf-alert.component.css +0 -100
  39. package/src/app/components/alert/mf-alert.component.spec.ts +0 -59
  40. package/src/app/components/alert/mf-alert.component.ts +0 -68
  41. package/src/app/components/autocomplete/index.ts +0 -5
  42. package/src/app/components/autocomplete/mf-autocomplete.component.css +0 -105
  43. package/src/app/components/autocomplete/mf-autocomplete.component.spec.ts +0 -116
  44. package/src/app/components/autocomplete/mf-autocomplete.component.ts +0 -307
  45. package/src/app/components/avatar/index.ts +0 -2
  46. package/src/app/components/avatar/mf-avatar.component.css +0 -27
  47. package/src/app/components/avatar/mf-avatar.component.spec.ts +0 -49
  48. package/src/app/components/avatar/mf-avatar.component.ts +0 -99
  49. package/src/app/components/badge/index.ts +0 -2
  50. package/src/app/components/badge/mf-badge.component.css +0 -32
  51. package/src/app/components/badge/mf-badge.component.spec.ts +0 -40
  52. package/src/app/components/badge/mf-badge.component.ts +0 -105
  53. package/src/app/components/breadcrumb/index.ts +0 -2
  54. package/src/app/components/breadcrumb/mf-breadcrumb.component.css +0 -61
  55. package/src/app/components/breadcrumb/mf-breadcrumb.component.spec.ts +0 -61
  56. package/src/app/components/breadcrumb/mf-breadcrumb.component.ts +0 -75
  57. package/src/app/components/button/index.ts +0 -2
  58. package/src/app/components/button/mf-button.component.css +0 -136
  59. package/src/app/components/button/mf-button.component.ts +0 -174
  60. package/src/app/components/card/index.ts +0 -2
  61. package/src/app/components/card/mf-card.component.css +0 -82
  62. package/src/app/components/card/mf-card.component.ts +0 -59
  63. package/src/app/components/checkbox/index.ts +0 -1
  64. package/src/app/components/checkbox/mf-checkbox.component.css +0 -75
  65. package/src/app/components/checkbox/mf-checkbox.component.ts +0 -187
  66. package/src/app/components/chip/index.ts +0 -2
  67. package/src/app/components/chip/mf-chip.component.css +0 -69
  68. package/src/app/components/chip/mf-chip.component.spec.ts +0 -47
  69. package/src/app/components/chip/mf-chip.component.ts +0 -77
  70. package/src/app/components/datepicker/index.ts +0 -2
  71. package/src/app/components/datepicker/mf-datepicker.component.css +0 -102
  72. package/src/app/components/datepicker/mf-datepicker.component.spec.ts +0 -69
  73. package/src/app/components/datepicker/mf-datepicker.component.ts +0 -233
  74. package/src/app/components/dialog/index.ts +0 -3
  75. package/src/app/components/dialog/mf-dialog.component.css +0 -73
  76. package/src/app/components/dialog/mf-dialog.component.ts +0 -160
  77. package/src/app/components/dialog/mf-dialog.service.spec.ts +0 -61
  78. package/src/app/components/dialog/mf-dialog.service.ts +0 -52
  79. package/src/app/components/divider/index.ts +0 -2
  80. package/src/app/components/divider/mf-divider.component.css +0 -38
  81. package/src/app/components/divider/mf-divider.component.spec.ts +0 -40
  82. package/src/app/components/divider/mf-divider.component.ts +0 -44
  83. package/src/app/components/form-field/index.ts +0 -1
  84. package/src/app/components/form-field/mf-form-field.component.css +0 -51
  85. package/src/app/components/form-field/mf-form-field.component.ts +0 -74
  86. package/src/app/components/grid-list/index.ts +0 -2
  87. package/src/app/components/grid-list/mf-grid-list.component.css +0 -47
  88. package/src/app/components/grid-list/mf-grid-list.component.spec.ts +0 -57
  89. package/src/app/components/grid-list/mf-grid-list.component.ts +0 -68
  90. package/src/app/components/icon/index.ts +0 -2
  91. package/src/app/components/icon/mf-icon.component.css +0 -56
  92. package/src/app/components/icon/mf-icon.component.ts +0 -41
  93. package/src/app/components/input/index.ts +0 -2
  94. package/src/app/components/input/mf-input.component.css +0 -105
  95. package/src/app/components/input/mf-input.component.ts +0 -217
  96. package/src/app/components/menu/index.ts +0 -2
  97. package/src/app/components/menu/mf-menu.component.css +0 -31
  98. package/src/app/components/menu/mf-menu.component.spec.ts +0 -49
  99. package/src/app/components/menu/mf-menu.component.ts +0 -66
  100. package/src/app/components/paginator/index.ts +0 -1
  101. package/src/app/components/paginator/mf-paginator.component.css +0 -32
  102. package/src/app/components/paginator/mf-paginator.component.spec.ts +0 -44
  103. package/src/app/components/paginator/mf-paginator.component.ts +0 -52
  104. package/src/app/components/progress-bar/index.ts +0 -2
  105. package/src/app/components/progress-bar/mf-progress-bar.component.css +0 -53
  106. package/src/app/components/progress-bar/mf-progress-bar.component.spec.ts +0 -65
  107. package/src/app/components/progress-bar/mf-progress-bar.component.ts +0 -79
  108. package/src/app/components/progress-spinner/index.ts +0 -2
  109. package/src/app/components/progress-spinner/mf-progress-spinner.component.css +0 -38
  110. package/src/app/components/progress-spinner/mf-progress-spinner.component.spec.ts +0 -59
  111. package/src/app/components/progress-spinner/mf-progress-spinner.component.ts +0 -81
  112. package/src/app/components/radio-button/index.ts +0 -2
  113. package/src/app/components/radio-button/mf-radio-button.component.css +0 -86
  114. package/src/app/components/radio-button/mf-radio-button.component.spec.ts +0 -55
  115. package/src/app/components/radio-button/mf-radio-button.component.ts +0 -219
  116. package/src/app/components/select/index.ts +0 -2
  117. package/src/app/components/select/mf-select.component.css +0 -121
  118. package/src/app/components/select/mf-select.component.spec.ts +0 -108
  119. package/src/app/components/select/mf-select.component.ts +0 -252
  120. package/src/app/components/sidenav/index.ts +0 -2
  121. package/src/app/components/sidenav/mf-sidenav.component.css +0 -168
  122. package/src/app/components/sidenav/mf-sidenav.component.spec.ts +0 -57
  123. package/src/app/components/sidenav/mf-sidenav.component.ts +0 -126
  124. package/src/app/components/slide-toggle/index.ts +0 -1
  125. package/src/app/components/slide-toggle/mf-slide-toggle.component.css +0 -42
  126. package/src/app/components/slide-toggle/mf-slide-toggle.component.spec.ts +0 -43
  127. package/src/app/components/slide-toggle/mf-slide-toggle.component.ts +0 -188
  128. package/src/app/components/snackbar/index.ts +0 -2
  129. package/src/app/components/snackbar/mf-snackbar.service.css +0 -31
  130. package/src/app/components/snackbar/mf-snackbar.service.spec.ts +0 -81
  131. package/src/app/components/snackbar/mf-snackbar.service.ts +0 -77
  132. package/src/app/components/table/index.ts +0 -2
  133. package/src/app/components/table/mf-table.component.css +0 -68
  134. package/src/app/components/table/mf-table.component.spec.ts +0 -76
  135. package/src/app/components/table/mf-table.component.ts +0 -117
  136. package/src/app/components/tabs/index.ts +0 -2
  137. package/src/app/components/tabs/mf-tabs.component.css +0 -31
  138. package/src/app/components/tabs/mf-tabs.component.spec.ts +0 -50
  139. package/src/app/components/tabs/mf-tabs.component.ts +0 -62
  140. package/src/app/components/textarea/index.ts +0 -2
  141. package/src/app/components/textarea/mf-textarea.component.css +0 -48
  142. package/src/app/components/textarea/mf-textarea.component.spec.ts +0 -55
  143. package/src/app/components/textarea/mf-textarea.component.ts +0 -227
  144. package/src/app/components/toolbar/index.ts +0 -2
  145. package/src/app/components/toolbar/mf-toolbar.component.css +0 -77
  146. package/src/app/components/toolbar/mf-toolbar.component.ts +0 -56
  147. package/src/app/components/tooltip/index.ts +0 -3
  148. package/src/app/components/tooltip/mf-tooltip.component.css +0 -7
  149. package/src/app/components/tooltip/mf-tooltip.component.spec.ts +0 -37
  150. package/src/app/components/tooltip/mf-tooltip.component.ts +0 -47
  151. package/src/app/components/tooltip/mf-tooltip.directive.ts +0 -22
  152. package/src/index.html +0 -18
  153. package/src/main.ts +0 -6
  154. package/src/public-api.ts +0 -31
  155. package/src/stories/About.mdx +0 -72
  156. package/src/stories/Accessibility.mdx +0 -59
  157. package/src/stories/Welcome.mdx +0 -26
  158. package/src/stories/assets/accessibility.png +0 -0
  159. package/src/stories/assets/accessibility.svg +0 -1
  160. package/src/stories/assets/addon-library.png +0 -0
  161. package/src/stories/assets/assets.png +0 -0
  162. package/src/stories/assets/avif-test-image.avif +0 -0
  163. package/src/stories/assets/context.png +0 -0
  164. package/src/stories/assets/discord.svg +0 -1
  165. package/src/stories/assets/docs.png +0 -0
  166. package/src/stories/assets/figma-plugin.png +0 -0
  167. package/src/stories/assets/github.svg +0 -1
  168. package/src/stories/assets/share.png +0 -0
  169. package/src/stories/assets/styling.png +0 -0
  170. package/src/stories/assets/testing.png +0 -0
  171. package/src/stories/assets/theming.png +0 -0
  172. package/src/stories/assets/tutorials.svg +0 -1
  173. package/src/stories/assets/youtube.svg +0 -1
  174. package/src/stories/mf-a11y-contracts.stories.ts +0 -472
  175. package/src/stories/mf-autocomplete.stories.ts +0 -194
  176. package/src/stories/mf-button.stories.ts +0 -152
  177. package/src/stories/mf-card.stories.ts +0 -147
  178. package/src/stories/mf-checkbox.stories.ts +0 -88
  179. package/src/stories/mf-datepicker.stories.ts +0 -118
  180. package/src/stories/mf-dialog.stories.ts +0 -159
  181. package/src/stories/mf-form-field.stories.ts +0 -108
  182. package/src/stories/mf-grid-list.stories.ts +0 -104
  183. package/src/stories/mf-icon.stories.ts +0 -133
  184. package/src/stories/mf-input.stories.ts +0 -158
  185. package/src/stories/mf-menu.stories.ts +0 -71
  186. package/src/stories/mf-progress-bar.stories.ts +0 -119
  187. package/src/stories/mf-progress-spinner.stories.ts +0 -124
  188. package/src/stories/mf-radio-button.stories.ts +0 -111
  189. package/src/stories/mf-select.stories.ts +0 -184
  190. package/src/stories/mf-sidenav.stories.ts +0 -331
  191. package/src/stories/mf-table.stories.ts +0 -80
  192. package/src/stories/mf-toolbar.stories.ts +0 -112
  193. package/src/stories/user.ts +0 -3
  194. package/tsconfig.app.json +0 -15
  195. package/tsconfig.json +0 -33
  196. package/tsconfig.spec.json +0 -15
  197. package/vercel.json +0 -6
@@ -1,44 +0,0 @@
1
- import {
2
- ChangeDetectionStrategy,
3
- Component,
4
- computed,
5
- input,
6
- } from '@angular/core';
7
- import { MatDividerModule } from '@angular/material/divider';
8
-
9
- export type MfDividerVariant = 'full' | 'inset' | 'middle';
10
-
11
- /**
12
- * Divider de la librería ng-comps.
13
- * Envuelve Angular Material `mat-divider` y expone una API uniforme
14
- * con look and feel de marca.
15
- */
16
- @Component({
17
- selector: 'mf-divider',
18
- imports: [MatDividerModule],
19
- template: `
20
- <mat-divider
21
- [vertical]="vertical()"
22
- [inset]="insetValue()"
23
- [class]="hostClasses()"
24
- />
25
- `,
26
- styleUrl: './mf-divider.component.css',
27
- changeDetection: ChangeDetectionStrategy.OnPush,
28
- })
29
- export class MfDividerComponent {
30
- /** Orientación vertical */
31
- readonly vertical = input(false);
32
- /** Variante visual */
33
- readonly variant = input<MfDividerVariant>('full');
34
- /** Espaciado extra arriba y abajo */
35
- readonly spacing = input<'none' | 'sm' | 'md' | 'lg'>('none');
36
-
37
- readonly insetValue = computed(() => this.variant() === 'inset');
38
-
39
- readonly hostClasses = computed(() => {
40
- const classes = ['mf-divider', `mf-divider--${this.variant()}`, `mf-divider--spacing-${this.spacing()}`];
41
- if (this.vertical()) classes.push('mf-divider--vertical');
42
- return classes.join(' ');
43
- });
44
- }
@@ -1 +0,0 @@
1
- export { MfFormFieldComponent } from './mf-form-field.component';
@@ -1,51 +0,0 @@
1
- :host {
2
- display: block;
3
- }
4
-
5
- /* ── Base ──────────────────────────────────────────────────────── */
6
- .mf-form-field {
7
- display: flex;
8
- flex-direction: column;
9
- gap: var(--mf-space-1);
10
- }
11
-
12
- /* ── Label ─────────────────────────────────────────────────────── */
13
- .mf-form-field__label {
14
- font-family: var(--mf-font-base);
15
- font-size: var(--mf-text-sm);
16
- font-weight: var(--mf-weight-medium);
17
- color: var(--mf-color-on-surface);
18
- line-height: var(--mf-leading-normal);
19
- cursor: default;
20
- }
21
-
22
- .mf-form-field__label--error {
23
- color: var(--mf-color-error-500);
24
- }
25
-
26
- .mf-form-field__required {
27
- color: var(--mf-color-error-500);
28
- }
29
-
30
- /* ── Control container ────────────────────────────────────────── */
31
- .mf-form-field__control {
32
- width: 100%;
33
- }
34
-
35
- /* ── Hint ──────────────────────────────────────────────────────── */
36
- .mf-form-field__hint {
37
- font-family: var(--mf-font-base);
38
- font-size: var(--mf-text-xs);
39
- color: var(--mf-color-neutral-400);
40
- margin: 0;
41
- padding-left: var(--mf-space-1);
42
- }
43
-
44
- /* ── Error ─────────────────────────────────────────────────────── */
45
- .mf-form-field__error {
46
- font-family: var(--mf-font-base);
47
- font-size: var(--mf-text-xs);
48
- color: var(--mf-color-error-500);
49
- margin: 0;
50
- padding-left: var(--mf-space-1);
51
- }
@@ -1,74 +0,0 @@
1
- import {
2
- ChangeDetectionStrategy,
3
- Component,
4
- computed,
5
- effect,
6
- input,
7
- } from '@angular/core';
8
- import { warnInDev } from '../../a11y';
9
-
10
- /**
11
- * Contenedor de campo de formulario de la librería ng-comps.
12
- * Proporciona estructura de layout consistente con label, contenido proyectado,
13
- * y mensajes opcionales de ayuda o error.
14
- */
15
- @Component({
16
- selector: 'mf-form-field',
17
- imports: [],
18
- template: `
19
- @if (label()) {
20
- <label [class]="labelClasses()" [attr.for]="fieldId()">{{ label() }}
21
- @if (required()) {
22
- <span class="mf-form-field__required" aria-hidden="true"> *</span>
23
- }
24
- </label>
25
- }
26
- <div class="mf-form-field__control">
27
- <ng-content />
28
- </div>
29
- @if (error()) {
30
- <p class="mf-form-field__error" role="alert">{{ error() }}</p>
31
- } @else if (hint()) {
32
- <p class="mf-form-field__hint">{{ hint() }}</p>
33
- }
34
- `,
35
- styleUrl: './mf-form-field.component.css',
36
- changeDetection: ChangeDetectionStrategy.OnPush,
37
- host: {
38
- '[class]': 'hostClasses()',
39
- },
40
- })
41
- export class MfFormFieldComponent {
42
- /** Etiqueta del campo */
43
- readonly label = input<string | undefined>(undefined);
44
- /** ID para asociar el label con el control */
45
- readonly fieldId = input<string | undefined>(undefined);
46
- /** Texto de ayuda */
47
- readonly hint = input<string | undefined>(undefined);
48
- /** Mensaje de error */
49
- readonly error = input<string | undefined>(undefined);
50
- /** Campo requerido (muestra asterisco) */
51
- readonly required = input(false);
52
-
53
- constructor() {
54
- effect(() => {
55
- if (this.label() && !this.fieldId()) {
56
- warnInDev(
57
- 'mf-form-field requiere `fieldId` cuando renderiza `label` para poder asociarlo al control proyectado.',
58
- );
59
- }
60
- });
61
- }
62
-
63
- readonly labelClasses = computed(() => {
64
- const classes = ['mf-form-field__label'];
65
- if (this.error()) classes.push('mf-form-field__label--error');
66
- return classes.join(' ');
67
- });
68
-
69
- readonly hostClasses = computed(() => {
70
- const classes = ['mf-form-field'];
71
- if (this.error()) classes.push('mf-form-field--error');
72
- return classes.join(' ');
73
- });
74
- }
@@ -1,2 +0,0 @@
1
- export { MfGridListComponent } from './mf-grid-list.component';
2
- export type { MfGridTile } from './mf-grid-list.component';
@@ -1,47 +0,0 @@
1
- :host {
2
- display: block;
3
- }
4
-
5
- /* ── Grid list ─────────────────────────────────────────────────── */
6
- .mf-grid-list {
7
- font-family: var(--mf-font-base) !important;
8
- }
9
-
10
- /* ── Tile ──────────────────────────────────────────────────────── */
11
- .mf-grid-list__tile {
12
- background-color: var(--mf-color-surface-raised);
13
- border-radius: var(--mf-radius-md) !important;
14
- overflow: hidden;
15
- transition: box-shadow var(--mf-duration-base) var(--mf-ease-standard);
16
- }
17
-
18
- .mf-grid-list__tile:hover {
19
- box-shadow: var(--mf-shadow-md);
20
- }
21
-
22
- /* ── Tile header ───────────────────────────────────────────────── */
23
- .mf-grid-list__tile mat-grid-tile-header,
24
- .mf-grid-list__tile .mat-grid-tile-header {
25
- background: linear-gradient(
26
- to top,
27
- rgba(15, 23, 42, 0.64) 0%,
28
- rgba(15, 23, 42, 0) 100%
29
- ) !important;
30
- padding: var(--mf-space-3) var(--mf-space-4) !important;
31
- }
32
-
33
- .mf-grid-list__tile-title {
34
- font-family: var(--mf-font-base);
35
- font-size: var(--mf-text-sm);
36
- font-weight: var(--mf-weight-bold);
37
- color: var(--mf-color-neutral-0);
38
- display: block;
39
- }
40
-
41
- .mf-grid-list__tile-subtitle {
42
- font-family: var(--mf-font-base);
43
- font-size: var(--mf-text-xs);
44
- font-weight: var(--mf-weight-regular);
45
- color: var(--mf-color-neutral-200);
46
- display: block;
47
- }
@@ -1,57 +0,0 @@
1
- import { ComponentFixture, TestBed } from '@angular/core/testing';
2
- import { MfGridListComponent } from './mf-grid-list.component';
3
- import { NoopAnimationsModule } from '@angular/platform-browser/animations';
4
-
5
- const SAMPLE_TILES = [
6
- { title: 'Tile 1', subtitle: 'Sub 1', background: '#ccc' },
7
- { title: 'Tile 2', background: '#eee', colspan: 2 },
8
- ];
9
-
10
- describe('MfGridListComponent', () => {
11
- let fixture: ComponentFixture<MfGridListComponent>;
12
- let component: MfGridListComponent;
13
-
14
- beforeEach(async () => {
15
- await TestBed.configureTestingModule({
16
- imports: [MfGridListComponent, NoopAnimationsModule],
17
- }).compileComponents();
18
-
19
- fixture = TestBed.createComponent(MfGridListComponent);
20
- component = fixture.componentInstance;
21
- fixture.detectChanges();
22
- });
23
-
24
- it('should create', () => {
25
- expect(component).toBeTruthy();
26
- });
27
-
28
- it('should render mat-grid-list', () => {
29
- const gridList = fixture.nativeElement.querySelector('mat-grid-list');
30
- expect(gridList).toBeTruthy();
31
- });
32
-
33
- it('should render tiles from input', () => {
34
- fixture.componentRef.setInput('tiles', SAMPLE_TILES);
35
- fixture.detectChanges();
36
- const tiles = fixture.nativeElement.querySelectorAll('mat-grid-tile');
37
- expect(tiles.length).toBe(SAMPLE_TILES.length);
38
- });
39
-
40
- it('should render tile title', () => {
41
- fixture.componentRef.setInput('tiles', SAMPLE_TILES);
42
- fixture.detectChanges();
43
- const titleEl = fixture.nativeElement.querySelector('.mf-grid-list__tile-title');
44
- expect(titleEl?.textContent).toContain('Tile 1');
45
- });
46
-
47
- it('should default cols to 2', () => {
48
- expect(component.cols()).toBe(2);
49
- });
50
-
51
- it('should render empty grid when tiles is empty', () => {
52
- fixture.componentRef.setInput('tiles', []);
53
- fixture.detectChanges();
54
- const tiles = fixture.nativeElement.querySelectorAll('mat-grid-tile');
55
- expect(tiles.length).toBe(0);
56
- });
57
- });
@@ -1,68 +0,0 @@
1
- import {
2
- ChangeDetectionStrategy,
3
- Component,
4
- input,
5
- } from '@angular/core';
6
- import { MatGridListModule } from '@angular/material/grid-list';
7
-
8
- export interface MfGridTile {
9
- /** Título de la tile */
10
- title?: string;
11
- /** Subtítulo de la tile */
12
- subtitle?: string;
13
- /** Número de columnas que ocupa */
14
- colspan?: number;
15
- /** Número de filas que ocupa */
16
- rowspan?: number;
17
- /** Color de fondo */
18
- background?: string;
19
- }
20
-
21
- /**
22
- * Lista en cuadrícula de la librería ng-comps.
23
- * Envuelve Angular Material `mat-grid-list` y expone una API uniforme
24
- * con look and feel de marca. Soporta tiles estáticas y content projection.
25
- */
26
- @Component({
27
- selector: 'mf-grid-list',
28
- imports: [MatGridListModule],
29
- template: `
30
- <mat-grid-list
31
- class="mf-grid-list"
32
- [cols]="cols()"
33
- [rowHeight]="rowHeight()"
34
- [gutterSize]="gutterSize()"
35
- >
36
- @for (tile of tiles(); track $index) {
37
- <mat-grid-tile
38
- class="mf-grid-list__tile"
39
- [colspan]="tile.colspan ?? 1"
40
- [rowspan]="tile.rowspan ?? 1"
41
- [style.background]="tile.background || null"
42
- >
43
- <mat-grid-tile-header>
44
- @if (tile.title) {
45
- <span class="mf-grid-list__tile-title">{{ tile.title }}</span>
46
- }
47
- @if (tile.subtitle) {
48
- <span class="mf-grid-list__tile-subtitle">{{ tile.subtitle }}</span>
49
- }
50
- </mat-grid-tile-header>
51
- </mat-grid-tile>
52
- }
53
- <ng-content />
54
- </mat-grid-list>
55
- `,
56
- styleUrl: './mf-grid-list.component.css',
57
- changeDetection: ChangeDetectionStrategy.OnPush,
58
- })
59
- export class MfGridListComponent {
60
- /** Número de columnas */
61
- readonly cols = input(2);
62
- /** Altura de cada fila */
63
- readonly rowHeight = input<string | number>('1:1');
64
- /** Espacio entre tiles */
65
- readonly gutterSize = input('8px');
66
- /** Tiles a renderizar */
67
- readonly tiles = input<MfGridTile[]>([]);
68
- }
@@ -1,2 +0,0 @@
1
- export { MfIconComponent } from './mf-icon.component';
2
- export type { MfIconSize, MfIconColor } from './mf-icon.component';
@@ -1,56 +0,0 @@
1
- :host {
2
- display: inline-flex;
3
- align-items: center;
4
- justify-content: center;
5
- }
6
-
7
- /* ── Base ──────────────────────────────────────────────────────── */
8
- .mf-icon {
9
- transition: color var(--mf-duration-base) var(--mf-ease-standard);
10
- }
11
-
12
- /* ── Sizes ─────────────────────────────────────────────────────── */
13
- .mf-icon--sm {
14
- font-size: 16px !important;
15
- width: 16px !important;
16
- height: 16px !important;
17
- }
18
-
19
- .mf-icon--md {
20
- font-size: 20px !important;
21
- width: 20px !important;
22
- height: 20px !important;
23
- }
24
-
25
- .mf-icon--lg {
26
- font-size: 24px !important;
27
- width: 24px !important;
28
- height: 24px !important;
29
- }
30
-
31
- .mf-icon--xl {
32
- font-size: 32px !important;
33
- width: 32px !important;
34
- height: 32px !important;
35
- }
36
-
37
- /* ── Colors ────────────────────────────────────────────────────── */
38
- .mf-icon--default {
39
- color: var(--mf-color-on-surface);
40
- }
41
-
42
- .mf-icon--brand {
43
- color: var(--mf-color-brand);
44
- }
45
-
46
- .mf-icon--muted {
47
- color: var(--mf-color-neutral-400);
48
- }
49
-
50
- .mf-icon--error {
51
- color: var(--mf-color-error-500);
52
- }
53
-
54
- .mf-icon--inherit {
55
- color: inherit;
56
- }
@@ -1,41 +0,0 @@
1
- import {
2
- ChangeDetectionStrategy,
3
- Component,
4
- computed,
5
- input,
6
- } from '@angular/core';
7
- import { MatIconModule } from '@angular/material/icon';
8
-
9
- export type MfIconSize = 'sm' | 'md' | 'lg' | 'xl';
10
- export type MfIconColor = 'default' | 'brand' | 'muted' | 'error' | 'inherit';
11
-
12
- /**
13
- * Icono de la librería ng-comps.
14
- * Envuelve Angular Material `mat-icon` y expone una API uniforme
15
- * con tamaños y colores de marca.
16
- */
17
- @Component({
18
- selector: 'mf-icon',
19
- imports: [MatIconModule],
20
- template: `
21
- <mat-icon [class]="hostClasses()" [attr.aria-hidden]="ariaHidden()" [attr.aria-label]="label()">{{ name() }}</mat-icon>
22
- `,
23
- styleUrl: './mf-icon.component.css',
24
- changeDetection: ChangeDetectionStrategy.OnPush,
25
- })
26
- export class MfIconComponent {
27
- /** Nombre del icono de Material Symbols / Material Icons */
28
- readonly name = input.required<string>();
29
- /** Tamaño visual del icono */
30
- readonly size = input<MfIconSize>('md');
31
- /** Color semántico del icono */
32
- readonly color = input<MfIconColor>('default');
33
- /** Etiqueta accesible. Si se omite, el icono será decorativo (aria-hidden) */
34
- readonly label = input<string | undefined>(undefined);
35
-
36
- readonly ariaHidden = computed(() => (this.label() ? 'false' : 'true'));
37
-
38
- readonly hostClasses = computed(() => {
39
- return ['mf-icon', `mf-icon--${this.size()}`, `mf-icon--${this.color()}`].join(' ');
40
- });
41
- }
@@ -1,2 +0,0 @@
1
- export { MfInputComponent } from './mf-input.component';
2
- export type { MfInputSize } from './mf-input.component';
@@ -1,105 +0,0 @@
1
- :host {
2
- display: inline-block;
3
- }
4
-
5
- /* ── Base ──────────────────────────────────────────────────────── */
6
- .mf-input {
7
- font-family: var(--mf-font-base) !important;
8
- width: 100%;
9
- }
10
-
11
- .mf-input--full {
12
- width: 100%;
13
- }
14
-
15
- /* ── Mat-form-field overrides ─────────────────────────────────── */
16
- .mf-input .mat-mdc-text-field-wrapper {
17
- border-radius: var(--mf-radius-md) !important;
18
- }
19
-
20
- .mf-input .mdc-notched-outline__leading,
21
- .mf-input .mdc-notched-outline__notch,
22
- .mf-input .mdc-notched-outline__trailing {
23
- border-color: var(--mf-color-border) !important;
24
- transition: border-color var(--mf-duration-base) var(--mf-ease-standard);
25
- }
26
-
27
- .mf-input .mat-mdc-form-field-focus-overlay {
28
- background-color: transparent !important;
29
- }
30
-
31
- /* ── Focus state ──────────────────────────────────────────────── */
32
- .mf-input.mat-focused .mdc-notched-outline__leading,
33
- .mf-input.mat-focused .mdc-notched-outline__notch,
34
- .mf-input.mat-focused .mdc-notched-outline__trailing {
35
- border-color: var(--mf-color-brand) !important;
36
- border-width: 1.5px !important;
37
- }
38
-
39
- /* ── Error state ──────────────────────────────────────────────── */
40
- .mf-input--error .mdc-notched-outline__leading,
41
- .mf-input--error .mdc-notched-outline__notch,
42
- .mf-input--error .mdc-notched-outline__trailing {
43
- border-color: var(--mf-color-error-500) !important;
44
- }
45
-
46
- /* ── Label styles ─────────────────────────────────────────────── */
47
- .mf-input .mat-mdc-floating-label {
48
- font-family: var(--mf-font-base) !important;
49
- font-weight: var(--mf-weight-medium) !important;
50
- color: var(--mf-color-neutral-400) !important;
51
- }
52
-
53
- .mf-input.mat-focused .mat-mdc-floating-label {
54
- color: var(--mf-color-brand) !important;
55
- }
56
-
57
- /* ── Input text ───────────────────────────────────────────────── */
58
- .mf-input .mat-mdc-input-element {
59
- font-family: var(--mf-font-base) !important;
60
- color: var(--mf-color-on-surface) !important;
61
- caret-color: var(--mf-color-brand);
62
- }
63
-
64
- /* ── Hint & Error ─────────────────────────────────────────────── */
65
- .mf-input .mat-mdc-form-field-hint {
66
- font-size: var(--mf-text-xs) !important;
67
- color: var(--mf-color-neutral-400) !important;
68
- }
69
-
70
- .mf-input .mat-mdc-form-field-error {
71
- font-size: var(--mf-text-xs) !important;
72
- }
73
-
74
- /* ── Sizes ─────────────────────────────────────────────────────── */
75
- .mf-input--sm .mat-mdc-input-element {
76
- font-size: var(--mf-text-sm) !important;
77
- }
78
-
79
- .mf-input--md .mat-mdc-input-element {
80
- font-size: var(--mf-text-base) !important;
81
- }
82
-
83
- .mf-input--lg .mat-mdc-input-element {
84
- font-size: var(--mf-text-lg) !important;
85
- padding-top: var(--mf-space-1) !important;
86
- padding-bottom: var(--mf-space-1) !important;
87
- }
88
-
89
- /* ── Prefix / Suffix icons ────────────────────────────────────── */
90
- .mf-input .mat-icon {
91
- color: var(--mf-color-neutral-400) !important;
92
- font-size: 20px;
93
- width: 20px;
94
- height: 20px;
95
- transition: color var(--mf-duration-base) var(--mf-ease-standard);
96
- }
97
-
98
- .mf-input.mat-focused .mat-icon {
99
- color: var(--mf-color-brand) !important;
100
- }
101
-
102
- /* ── Disabled ──────────────────────────────────────────────────── */
103
- .mf-input .mat-mdc-input-element:disabled {
104
- color: var(--mf-color-neutral-300) !important;
105
- }