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
package/ng-package.json DELETED
@@ -1,27 +0,0 @@
1
- {
2
- "$schema": "./node_modules/ng-packagr/ng-package.schema.json",
3
- "dest": "./dist/ng-comps",
4
- "lib": {
5
- "entryFile": "src/public-api.ts"
6
- },
7
- "assets": [
8
- "LICENSE",
9
- "README.md",
10
- "src/styles.css",
11
- "src/theme/**/*"
12
- ],
13
- "allowedNonPeerDependencies": [
14
- "@angular/animations",
15
- "@angular/cdk",
16
- "@angular/common",
17
- "@angular/compiler",
18
- "@angular/core",
19
- "@angular/forms",
20
- "@angular/material",
21
- "@angular/platform-browser",
22
- "@angular/router",
23
- "@fontsource/material-icons",
24
- "rxjs",
25
- "tslib"
26
- ]
27
- }
Binary file
@@ -1,80 +0,0 @@
1
- import { readFileSync, writeFileSync, existsSync, rmSync } from 'node:fs';
2
- import { resolve } from 'node:path';
3
-
4
- const root = process.cwd();
5
- const rootPkgPath = resolve(root, 'package.json');
6
- const distDir = resolve(root, 'dist', 'ng-comps');
7
- const distPkgPath = resolve(distDir, 'package.json');
8
-
9
- if (!existsSync(distDir)) {
10
- throw new Error('No existe dist/ng-comps. Ejecuta primero npm run build:lib');
11
- }
12
-
13
- const rootPkg = JSON.parse(readFileSync(rootPkgPath, 'utf8'));
14
- const angularVersion = rootPkg.dependencies['@angular/core'];
15
- const cdkVersion = rootPkg.dependencies['@angular/cdk'];
16
- const materialVersion = rootPkg.dependencies['@angular/material'];
17
- const rxjsVersion = rootPkg.dependencies.rxjs;
18
- const tslibVersion = rootPkg.dependencies.tslib;
19
-
20
- for (const extraPath of [
21
- resolve(distDir, 'browser'),
22
- resolve(distDir, '3rdpartylicenses.txt'),
23
- resolve(distDir, 'prerendered-routes.json')
24
- ]) {
25
- if (existsSync(extraPath)) {
26
- rmSync(extraPath, { recursive: true, force: true });
27
- }
28
- }
29
-
30
- const packageJson = {
31
- name: rootPkg.name,
32
- version: rootPkg.version,
33
- description: 'Angular UI components for mf-design-system',
34
- keywords: ['angular', 'components', 'ui', 'design-system', 'material'],
35
- license: rootPkg.license || 'MIT',
36
- type: 'module',
37
- sideEffects: false,
38
- main: './fesm2022/ng-comps.mjs',
39
- module: './fesm2022/ng-comps.mjs',
40
- typings: './types/ng-comps.d.ts',
41
- files: [
42
- 'fesm2022/ng-comps.mjs',
43
- 'types/ng-comps.d.ts',
44
- 'src/styles.css',
45
- 'src/theme',
46
- 'README.md',
47
- 'LICENSE',
48
- 'package.json'
49
- ],
50
- exports: {
51
- '.': {
52
- types: './types/ng-comps.d.ts',
53
- default: './fesm2022/ng-comps.mjs'
54
- },
55
- './styles.css': './src/styles.css',
56
- './theme/tokens.css': './src/theme/tokens.css',
57
- './theme/material-theme.scss': './src/theme/material-theme.scss',
58
- './package.json': './package.json'
59
- },
60
- peerDependencies: {
61
- '@angular/animations': angularVersion,
62
- '@angular/cdk': cdkVersion,
63
- '@angular/common': angularVersion,
64
- '@angular/core': angularVersion,
65
- '@angular/forms': angularVersion,
66
- '@angular/material': materialVersion,
67
- '@angular/platform-browser': angularVersion,
68
- '@angular/router': angularVersion,
69
- rxjs: rxjsVersion
70
- },
71
- dependencies: {
72
- tslib: tslibVersion
73
- },
74
- publishConfig: {
75
- access: 'public'
76
- }
77
- };
78
-
79
- writeFileSync(distPkgPath, `${JSON.stringify(packageJson, null, 2)}\n`, 'utf8');
80
- console.log(`package.json optimizado generado en ${distPkgPath}`);
@@ -1,35 +0,0 @@
1
- import { isDevMode } from '@angular/core';
2
-
3
- let nextUniqueId = 0;
4
- const emittedWarnings = new Set<string>();
5
-
6
- export function createUniqueId(prefix: string): string {
7
- nextUniqueId += 1;
8
- return `${prefix}-${nextUniqueId}`;
9
- }
10
-
11
- export function mergeAriaIds(
12
- ...values: Array<string | null | undefined>
13
- ): string | null {
14
- const ids = values
15
- .flatMap((value) => (value ? value.split(/\s+/) : []))
16
- .map((value) => value.trim())
17
- .filter(Boolean);
18
-
19
- return ids.length > 0 ? Array.from(new Set(ids)).join(' ') : null;
20
- }
21
-
22
- export function hasAccessibleName(
23
- ...values: Array<string | null | undefined>
24
- ): boolean {
25
- return values.some((value) => Boolean(value?.trim()));
26
- }
27
-
28
- export function warnInDev(message: string): void {
29
- if (!isDevMode() || emittedWarnings.has(message)) {
30
- return;
31
- }
32
-
33
- emittedWarnings.add(message);
34
- console.warn(`[ng-comps:a11y] ${message}`);
35
- }
@@ -1,6 +0,0 @@
1
- export {
2
- createUniqueId,
3
- hasAccessibleName,
4
- mergeAriaIds,
5
- warnInDev,
6
- } from './accessibility.utils';
@@ -1,108 +0,0 @@
1
- import { ComponentFixture, TestBed } from '@angular/core/testing';
2
- import { NoopAnimationsModule } from '@angular/platform-browser/animations';
3
- import * as axe from 'axe-core';
4
- import { MfButtonComponent } from '../components/button';
5
- import { MfDialogComponent } from '../components/dialog';
6
- import { MfInputComponent } from '../components/input';
7
- import { MfSelectComponent } from '../components/select';
8
-
9
- async function expectNoAxeViolations(
10
- fixture: ComponentFixture<unknown>,
11
- ): Promise<void> {
12
- await fixture.whenStable();
13
- const results = await axe.run(fixture.nativeElement as HTMLElement, {
14
- runOnly: {
15
- type: 'tag',
16
- values: ['wcag2a', 'wcag2aa', 'wcag21aa', 'wcag22aa'],
17
- },
18
- rules: {
19
- region: { enabled: false },
20
- 'page-has-heading-one': { enabled: false },
21
- 'landmark-one-main': { enabled: false },
22
- },
23
- });
24
-
25
- const summaries = results.violations.map((violation) => ({
26
- id: violation.id,
27
- impact: violation.impact,
28
- nodes: violation.nodes.map((node) => node.target.join(' ')),
29
- }));
30
-
31
- expect(summaries).toEqual([]);
32
- }
33
-
34
- describe('ng-comps accessibility contract', () => {
35
- it('renders a labeled text button without axe violations', async () => {
36
- await TestBed.configureTestingModule({
37
- imports: [MfButtonComponent],
38
- }).compileComponents();
39
-
40
- const fixture = TestBed.createComponent(MfButtonComponent);
41
- fixture.componentRef.setInput('label', 'Guardar cambios');
42
- fixture.detectChanges();
43
-
44
- await expectNoAxeViolations(fixture);
45
- });
46
-
47
- it('renders an icon-only button with an explicit accessible name', async () => {
48
- await TestBed.configureTestingModule({
49
- imports: [MfButtonComponent],
50
- }).compileComponents();
51
-
52
- const fixture = TestBed.createComponent(MfButtonComponent);
53
- fixture.componentRef.setInput('iconOnly', true);
54
- fixture.componentRef.setInput('leadingIcon', 'settings');
55
- fixture.componentRef.setInput('ariaLabel', 'Abrir configuración');
56
- fixture.detectChanges();
57
-
58
- await expectNoAxeViolations(fixture);
59
- });
60
-
61
- it('renders an input with visible label, hint and error wiring', async () => {
62
- await TestBed.configureTestingModule({
63
- imports: [MfInputComponent, NoopAnimationsModule],
64
- }).compileComponents();
65
-
66
- const fixture = TestBed.createComponent(MfInputComponent);
67
- fixture.componentRef.setInput('label', 'Correo electrónico');
68
- fixture.componentRef.setInput('hint', 'Usa tu correo corporativo');
69
- fixture.componentRef.setInput('error', 'El correo es obligatorio');
70
- fixture.detectChanges();
71
-
72
- await expectNoAxeViolations(fixture);
73
- });
74
-
75
- it('renders a select with visible label and helper text', async () => {
76
- await TestBed.configureTestingModule({
77
- imports: [MfSelectComponent, NoopAnimationsModule],
78
- }).compileComponents();
79
-
80
- const fixture = TestBed.createComponent(MfSelectComponent);
81
- fixture.componentRef.setInput('label', 'Framework');
82
- fixture.componentRef.setInput('hint', 'Selecciona una opción');
83
- fixture.componentRef.setInput('options', [
84
- { value: 'angular', label: 'Angular' },
85
- { value: 'react', label: 'React' },
86
- ]);
87
- fixture.detectChanges();
88
-
89
- await expectNoAxeViolations(fixture);
90
- });
91
-
92
- it('renders an inline dialog with title and description', async () => {
93
- await TestBed.configureTestingModule({
94
- imports: [MfDialogComponent, NoopAnimationsModule],
95
- }).compileComponents();
96
-
97
- const fixture = TestBed.createComponent(MfDialogComponent);
98
- fixture.componentRef.setInput('title', 'Confirmar acción');
99
- fixture.componentRef.setInput(
100
- 'message',
101
- 'Este cambio se aplicará de forma permanente.',
102
- );
103
- fixture.componentRef.setInput('showActions', false);
104
- fixture.detectChanges();
105
-
106
- await expectNoAxeViolations(fixture);
107
- });
108
- });
@@ -1,11 +0,0 @@
1
- import { ApplicationConfig, provideBrowserGlobalErrorListeners } from '@angular/core';
2
- import { provideRouter } from '@angular/router';
3
-
4
- import { routes } from './app.routes';
5
-
6
- export const appConfig: ApplicationConfig = {
7
- providers: [
8
- provideBrowserGlobalErrorListeners(),
9
- provideRouter(routes)
10
- ]
11
- };
package/src/app/app.css DELETED
@@ -1,107 +0,0 @@
1
- :host {
2
- display: block;
3
- min-height: 100dvh;
4
- background:
5
- radial-gradient(circle at 10% 5%, rgba(15, 118, 110, 0.12), transparent 35%),
6
- radial-gradient(circle at 90% 0%, rgba(59, 130, 246, 0.15), transparent 32%),
7
- #f7fafc;
8
- }
9
-
10
- .welcome {
11
- max-width: 980px;
12
- margin: 0 auto;
13
- padding: 32px 20px 40px;
14
- display: grid;
15
- gap: 16px;
16
- color: #0f172a;
17
- font-family: var(--mf-font-base, 'Segoe UI', sans-serif);
18
- }
19
-
20
- .hero {
21
- background: #ffffff;
22
- border: 1px solid #d9e4ec;
23
- border-radius: 16px;
24
- padding: 24px;
25
- box-shadow: 0 10px 30px rgba(15, 23, 42, 0.06);
26
- }
27
-
28
- .badge {
29
- display: inline-flex;
30
- margin: 0 0 10px;
31
- padding: 4px 10px;
32
- border-radius: 999px;
33
- background: #dcfce7;
34
- color: #166534;
35
- font-weight: 600;
36
- font-size: 12px;
37
- letter-spacing: 0.02em;
38
- text-transform: uppercase;
39
- }
40
-
41
- h1 {
42
- margin: 0;
43
- font-family: var(--mf-font-display, 'Segoe UI', sans-serif);
44
- font-size: clamp(1.8rem, 4vw, 2.4rem);
45
- line-height: 1.1;
46
- }
47
-
48
- .lead {
49
- margin: 10px 0 0;
50
- color: #334155;
51
- max-width: 62ch;
52
- }
53
-
54
- .card {
55
- background: #ffffff;
56
- border: 1px solid #d9e4ec;
57
- border-radius: 16px;
58
- padding: 20px;
59
- box-shadow: 0 8px 26px rgba(15, 23, 42, 0.05);
60
- }
61
-
62
- .card h2 {
63
- margin: 0 0 10px;
64
- font-size: 1.1rem;
65
- }
66
-
67
- .card p {
68
- margin: 0 0 10px;
69
- color: #334155;
70
- }
71
-
72
- pre {
73
- margin: 0;
74
- padding: 12px;
75
- border-radius: 10px;
76
- background: #0b1220;
77
- color: #e2e8f0;
78
- border: 1px solid #1e293b;
79
- overflow-x: auto;
80
- }
81
-
82
- code {
83
- font-family: 'Cascadia Code', Consolas, monospace;
84
- font-size: 0.88rem;
85
- }
86
-
87
- ul {
88
- margin: 0;
89
- padding-left: 18px;
90
- color: #334155;
91
- }
92
-
93
- li + li {
94
- margin-top: 6px;
95
- }
96
-
97
- @media (max-width: 640px) {
98
- .welcome {
99
- padding: 20px 12px 28px;
100
- }
101
-
102
- .hero,
103
- .card {
104
- padding: 16px;
105
- border-radius: 12px;
106
- }
107
- }
package/src/app/app.html DELETED
@@ -1,48 +0,0 @@
1
- <main class="welcome">
2
- <header class="hero">
3
- <p class="badge">UI Library</p>
4
- <h1>Welcome to {{ title() }}</h1>
5
- <p class="lead">
6
- This page explains how to install and start using <strong>ng-comps</strong>
7
- in any Angular project.
8
- </p>
9
- </header>
10
-
11
- <section class="card" aria-labelledby="install-title">
12
- <h2 id="install-title">1) Install package</h2>
13
- <pre><code>npm i ng-comps</code></pre>
14
- </section>
15
-
16
- <section class="card" aria-labelledby="styles-title">
17
- <h2 id="styles-title">2) Load base styles and design tokens</h2>
18
- <p>Add these imports in your global styles file (for example <code>src/styles.css</code>):</p>
19
- <pre><code>@import 'ng-comps/theme/tokens.css';
20
- @import 'ng-comps/styles.css';</code></pre>
21
- </section>
22
-
23
- <section class="card" aria-labelledby="usage-title">
24
- <h2 id="usage-title">3) Use components in standalone Angular pages</h2>
25
- <p>Import only what you need for better tree-shaking.</p>
26
- <pre><code>import &#123; Component &#125; from '@angular/core';
27
- import &#123; MfButtonComponent, MfInputComponent &#125; from 'ng-comps';
28
-
29
- @Component(&#123;
30
- selector: 'app-example',
31
- imports: [MfButtonComponent, MfInputComponent],
32
- template: `
33
- &lt;mf-input label="Email" placeholder="you@company.com" /&gt;
34
- &lt;mf-button label="Save" variant="filled" /&gt;
35
- `,
36
- &#125;)
37
- export class ExampleComponent &#123;&#125;</code></pre>
38
- </section>
39
-
40
- <section class="card" aria-labelledby="notes-title">
41
- <h2 id="notes-title">4) Notes for production projects</h2>
42
- <ul>
43
- <li>The package is published with <code>sideEffects: false</code> for max tree-shaking.</li>
44
- <li>Angular and RxJS are peer dependencies to avoid duplicated framework installs.</li>
45
- <li>Import components directly from <code>ng-comps</code>; avoid wildcard barrel files in your app.</li>
46
- </ul>
47
- </section>
48
- </main>
@@ -1,3 +0,0 @@
1
- import { Routes } from '@angular/router';
2
-
3
- export const routes: Routes = [];
@@ -1,23 +0,0 @@
1
- import { TestBed } from '@angular/core/testing';
2
- import { App } from './app';
3
-
4
- describe('App', () => {
5
- beforeEach(async () => {
6
- await TestBed.configureTestingModule({
7
- imports: [App],
8
- }).compileComponents();
9
- });
10
-
11
- it('should create the app', () => {
12
- const fixture = TestBed.createComponent(App);
13
- const app = fixture.componentInstance;
14
- expect(app).toBeTruthy();
15
- });
16
-
17
- it('should render title', async () => {
18
- const fixture = TestBed.createComponent(App);
19
- await fixture.whenStable();
20
- const compiled = fixture.nativeElement as HTMLElement;
21
- expect(compiled.querySelector('h1')?.textContent).toContain('Welcome to ng-comps');
22
- });
23
- });
package/src/app/app.ts DELETED
@@ -1,10 +0,0 @@
1
- import { Component, signal } from '@angular/core';
2
-
3
- @Component({
4
- selector: 'app-root',
5
- templateUrl: './app.html',
6
- styleUrl: './app.css'
7
- })
8
- export class App {
9
- protected readonly title = signal('ng-comps');
10
- }
@@ -1,2 +0,0 @@
1
- export { MfAccordionComponent } from './mf-accordion.component';
2
- export type { MfAccordionPanel } from './mf-accordion.component';
@@ -1,38 +0,0 @@
1
- :host {
2
- display: block;
3
- }
4
-
5
- .mf-accordion .mat-expansion-panel {
6
- font-family: var(--mf-font-base) !important;
7
- border-radius: var(--mf-radius-md) !important;
8
- box-shadow: var(--mf-shadow-none) !important;
9
- border: 1px solid var(--mf-color-border);
10
- margin-bottom: var(--mf-space-2);
11
- }
12
-
13
- .mf-accordion .mat-expansion-panel-header {
14
- font-family: var(--mf-font-base) !important;
15
- }
16
-
17
- .mf-accordion .mat-expansion-panel-header-title {
18
- font-weight: var(--mf-weight-bold) !important;
19
- color: var(--mf-color-on-surface) !important;
20
- }
21
-
22
- .mf-accordion .mat-expansion-panel-header-description {
23
- color: var(--mf-color-neutral-400) !important;
24
- }
25
-
26
- .mf-accordion .mat-expansion-panel-body {
27
- font-size: var(--mf-text-sm) !important;
28
- color: var(--mf-color-neutral-600) !important;
29
- line-height: var(--mf-leading-normal);
30
- }
31
-
32
- .mf-accordion .mat-expansion-indicator::after {
33
- color: var(--mf-color-brand) !important;
34
- }
35
-
36
- .mf-accordion .mat-expansion-panel:not(.mat-expanded) .mat-expansion-panel-header:hover {
37
- background-color: var(--mf-color-brand-light) !important;
38
- }
@@ -1,48 +0,0 @@
1
- import { ComponentFixture, TestBed } from '@angular/core/testing';
2
- import { MfAccordionComponent } from './mf-accordion.component';
3
- import { NoopAnimationsModule } from '@angular/platform-browser/animations';
4
-
5
- describe('MfAccordionComponent', () => {
6
- let fixture: ComponentFixture<MfAccordionComponent>;
7
- let component: MfAccordionComponent;
8
-
9
- const testPanels = [
10
- { title: 'Panel 1', content: 'Content 1' },
11
- { title: 'Panel 2', description: 'Description', content: 'Content 2' },
12
- { title: 'Panel 3', content: 'Content 3', disabled: true },
13
- ];
14
-
15
- beforeEach(async () => {
16
- await TestBed.configureTestingModule({
17
- imports: [MfAccordionComponent, NoopAnimationsModule],
18
- }).compileComponents();
19
-
20
- fixture = TestBed.createComponent(MfAccordionComponent);
21
- component = fixture.componentInstance;
22
- fixture.componentRef.setInput('panels', testPanels);
23
- fixture.detectChanges();
24
- });
25
-
26
- it('should create', () => {
27
- expect(component).toBeTruthy();
28
- });
29
-
30
- it('should render expansion panels', () => {
31
- const panels = fixture.nativeElement.querySelectorAll('mat-expansion-panel');
32
- expect(panels.length).toBe(3);
33
- });
34
-
35
- it('should apply host classes', () => {
36
- expect(component.hostClasses()).toBe('mf-accordion');
37
- });
38
-
39
- it('should not allow multi by default', () => {
40
- expect(component.multi()).toBe(false);
41
- });
42
-
43
- it('should render panel titles', () => {
44
- const titles = fixture.nativeElement.querySelectorAll('mat-panel-title');
45
- expect(titles.length).toBe(3);
46
- expect(titles[0].textContent).toContain('Panel 1');
47
- });
48
- });
@@ -1,53 +0,0 @@
1
- import {
2
- ChangeDetectionStrategy,
3
- Component,
4
- computed,
5
- input,
6
- } from '@angular/core';
7
- import { MatExpansionModule } from '@angular/material/expansion';
8
-
9
- export interface MfAccordionPanel {
10
- title: string;
11
- description?: string;
12
- content: string;
13
- expanded?: boolean;
14
- disabled?: boolean;
15
- }
16
-
17
- /**
18
- * Accordion de la librería ng-comps.
19
- * Envuelve Angular Material `mat-accordion` / `mat-expansion-panel` y expone
20
- * una API uniforme con look and feel de marca.
21
- */
22
- @Component({
23
- selector: 'mf-accordion',
24
- imports: [MatExpansionModule],
25
- template: `
26
- <mat-accordion [multi]="multi()" [class]="hostClasses()">
27
- @for (panel of panels(); track panel.title) {
28
- <mat-expansion-panel
29
- [expanded]="panel.expanded ?? false"
30
- [disabled]="panel.disabled ?? false"
31
- >
32
- <mat-expansion-panel-header>
33
- <mat-panel-title>{{ panel.title }}</mat-panel-title>
34
- @if (panel.description) {
35
- <mat-panel-description>{{ panel.description }}</mat-panel-description>
36
- }
37
- </mat-expansion-panel-header>
38
- <p>{{ panel.content }}</p>
39
- </mat-expansion-panel>
40
- }
41
- </mat-accordion>
42
- `,
43
- styleUrl: './mf-accordion.component.css',
44
- changeDetection: ChangeDetectionStrategy.OnPush,
45
- })
46
- export class MfAccordionComponent {
47
- /** Paneles del accordion */
48
- readonly panels = input.required<MfAccordionPanel[]>();
49
- /** Permite múltiples paneles abiertos */
50
- readonly multi = input(false);
51
-
52
- readonly hostClasses = computed(() => 'mf-accordion');
53
- }
@@ -1,2 +0,0 @@
1
- export { MfAlertComponent } from './mf-alert.component';
2
- export type { MfAlertSeverity } from './mf-alert.component';