ng-comps 0.2.0 → 1.0.1

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 (200) hide show
  1. package/.editorconfig +17 -0
  2. package/.github/copilot-instructions.md +55 -0
  3. package/.github/workflows/ci.yml +29 -0
  4. package/.prettierrc +12 -0
  5. package/.storybook/main.ts +21 -0
  6. package/.storybook/preview.ts +27 -0
  7. package/.storybook/tsconfig.doc.json +10 -0
  8. package/.storybook/tsconfig.json +15 -0
  9. package/.storybook/typings.d.ts +4 -0
  10. package/.vscode/extensions.json +4 -0
  11. package/.vscode/launch.json +20 -0
  12. package/.vscode/mcp.json +9 -0
  13. package/.vscode/tasks.json +42 -0
  14. package/ACCESSIBILITY.md +127 -0
  15. package/README.md +79 -62
  16. package/angular.json +105 -0
  17. package/documentation.json +13394 -0
  18. package/ng-package.json +27 -0
  19. package/package.json +58 -45
  20. package/public/favicon.ico +0 -0
  21. package/scripts/prepare-package.mjs +61 -0
  22. package/src/app/a11y/accessibility.utils.ts +35 -0
  23. package/src/app/a11y/index.ts +6 -0
  24. package/src/app/accessibility/ng-comps.a11y.spec.ts +108 -0
  25. package/src/app/app.config.ts +11 -0
  26. package/src/app/app.css +107 -0
  27. package/src/app/app.html +48 -0
  28. package/src/app/app.routes.ts +3 -0
  29. package/src/app/app.spec.ts +23 -0
  30. package/src/app/app.ts +10 -0
  31. package/src/app/components/accordion/index.ts +2 -0
  32. package/src/app/components/accordion/mf-accordion.component.css +38 -0
  33. package/src/app/components/accordion/mf-accordion.component.spec.ts +48 -0
  34. package/src/app/components/accordion/mf-accordion.component.ts +53 -0
  35. package/src/app/components/alert/index.ts +2 -0
  36. package/src/app/components/alert/mf-alert.component.css +100 -0
  37. package/src/app/components/alert/mf-alert.component.spec.ts +59 -0
  38. package/src/app/components/alert/mf-alert.component.ts +68 -0
  39. package/src/app/components/autocomplete/index.ts +5 -0
  40. package/src/app/components/autocomplete/mf-autocomplete.component.css +105 -0
  41. package/src/app/components/autocomplete/mf-autocomplete.component.spec.ts +116 -0
  42. package/src/app/components/autocomplete/mf-autocomplete.component.ts +307 -0
  43. package/src/app/components/avatar/index.ts +2 -0
  44. package/src/app/components/avatar/mf-avatar.component.css +27 -0
  45. package/src/app/components/avatar/mf-avatar.component.spec.ts +49 -0
  46. package/src/app/components/avatar/mf-avatar.component.ts +99 -0
  47. package/src/app/components/badge/index.ts +2 -0
  48. package/src/app/components/badge/mf-badge.component.css +32 -0
  49. package/src/app/components/badge/mf-badge.component.spec.ts +40 -0
  50. package/src/app/components/badge/mf-badge.component.ts +105 -0
  51. package/src/app/components/breadcrumb/index.ts +2 -0
  52. package/src/app/components/breadcrumb/mf-breadcrumb.component.css +61 -0
  53. package/src/app/components/breadcrumb/mf-breadcrumb.component.spec.ts +61 -0
  54. package/src/app/components/breadcrumb/mf-breadcrumb.component.ts +75 -0
  55. package/src/app/components/button/index.ts +2 -0
  56. package/src/app/components/button/mf-button.component.css +136 -0
  57. package/src/app/components/button/mf-button.component.ts +174 -0
  58. package/src/app/components/card/index.ts +2 -0
  59. package/src/app/components/card/mf-card.component.css +82 -0
  60. package/src/app/components/card/mf-card.component.ts +59 -0
  61. package/src/app/components/checkbox/index.ts +1 -0
  62. package/src/app/components/checkbox/mf-checkbox.component.css +75 -0
  63. package/src/app/components/checkbox/mf-checkbox.component.ts +187 -0
  64. package/src/app/components/chip/index.ts +2 -0
  65. package/src/app/components/chip/mf-chip.component.css +69 -0
  66. package/src/app/components/chip/mf-chip.component.spec.ts +47 -0
  67. package/src/app/components/chip/mf-chip.component.ts +77 -0
  68. package/src/app/components/datepicker/index.ts +2 -0
  69. package/src/app/components/datepicker/mf-datepicker.component.css +102 -0
  70. package/src/app/components/datepicker/mf-datepicker.component.spec.ts +69 -0
  71. package/src/app/components/datepicker/mf-datepicker.component.ts +233 -0
  72. package/src/app/components/dialog/index.ts +3 -0
  73. package/src/app/components/dialog/mf-dialog.component.css +73 -0
  74. package/src/app/components/dialog/mf-dialog.component.ts +160 -0
  75. package/src/app/components/dialog/mf-dialog.service.spec.ts +61 -0
  76. package/src/app/components/dialog/mf-dialog.service.ts +52 -0
  77. package/src/app/components/divider/index.ts +2 -0
  78. package/src/app/components/divider/mf-divider.component.css +38 -0
  79. package/src/app/components/divider/mf-divider.component.spec.ts +40 -0
  80. package/src/app/components/divider/mf-divider.component.ts +44 -0
  81. package/src/app/components/form-field/index.ts +1 -0
  82. package/src/app/components/form-field/mf-form-field.component.css +51 -0
  83. package/src/app/components/form-field/mf-form-field.component.ts +74 -0
  84. package/src/app/components/grid-list/index.ts +2 -0
  85. package/src/app/components/grid-list/mf-grid-list.component.css +47 -0
  86. package/src/app/components/grid-list/mf-grid-list.component.spec.ts +57 -0
  87. package/src/app/components/grid-list/mf-grid-list.component.ts +68 -0
  88. package/src/app/components/icon/index.ts +2 -0
  89. package/src/app/components/icon/mf-icon.component.css +56 -0
  90. package/src/app/components/icon/mf-icon.component.ts +41 -0
  91. package/src/app/components/input/index.ts +2 -0
  92. package/src/app/components/input/mf-input.component.css +105 -0
  93. package/src/app/components/input/mf-input.component.ts +217 -0
  94. package/src/app/components/menu/index.ts +2 -0
  95. package/src/app/components/menu/mf-menu.component.css +31 -0
  96. package/src/app/components/menu/mf-menu.component.spec.ts +49 -0
  97. package/src/app/components/menu/mf-menu.component.ts +66 -0
  98. package/src/app/components/paginator/index.ts +1 -0
  99. package/src/app/components/paginator/mf-paginator.component.css +32 -0
  100. package/src/app/components/paginator/mf-paginator.component.spec.ts +44 -0
  101. package/src/app/components/paginator/mf-paginator.component.ts +52 -0
  102. package/src/app/components/progress-bar/index.ts +2 -0
  103. package/src/app/components/progress-bar/mf-progress-bar.component.css +53 -0
  104. package/src/app/components/progress-bar/mf-progress-bar.component.spec.ts +65 -0
  105. package/src/app/components/progress-bar/mf-progress-bar.component.ts +79 -0
  106. package/src/app/components/progress-spinner/index.ts +2 -0
  107. package/src/app/components/progress-spinner/mf-progress-spinner.component.css +38 -0
  108. package/src/app/components/progress-spinner/mf-progress-spinner.component.spec.ts +59 -0
  109. package/src/app/components/progress-spinner/mf-progress-spinner.component.ts +81 -0
  110. package/src/app/components/radio-button/index.ts +2 -0
  111. package/src/app/components/radio-button/mf-radio-button.component.css +86 -0
  112. package/src/app/components/radio-button/mf-radio-button.component.spec.ts +55 -0
  113. package/src/app/components/radio-button/mf-radio-button.component.ts +219 -0
  114. package/src/app/components/select/index.ts +2 -0
  115. package/src/app/components/select/mf-select.component.css +121 -0
  116. package/src/app/components/select/mf-select.component.spec.ts +108 -0
  117. package/src/app/components/select/mf-select.component.ts +252 -0
  118. package/src/app/components/sidenav/index.ts +2 -0
  119. package/src/app/components/sidenav/mf-sidenav.component.css +168 -0
  120. package/src/app/components/sidenav/mf-sidenav.component.spec.ts +57 -0
  121. package/src/app/components/sidenav/mf-sidenav.component.ts +126 -0
  122. package/src/app/components/slide-toggle/index.ts +1 -0
  123. package/src/app/components/slide-toggle/mf-slide-toggle.component.css +42 -0
  124. package/src/app/components/slide-toggle/mf-slide-toggle.component.spec.ts +43 -0
  125. package/src/app/components/slide-toggle/mf-slide-toggle.component.ts +188 -0
  126. package/src/app/components/snackbar/index.ts +2 -0
  127. package/src/app/components/snackbar/mf-snackbar.service.css +31 -0
  128. package/src/app/components/snackbar/mf-snackbar.service.spec.ts +81 -0
  129. package/src/app/components/snackbar/mf-snackbar.service.ts +77 -0
  130. package/src/app/components/table/index.ts +2 -0
  131. package/src/app/components/table/mf-table.component.css +68 -0
  132. package/src/app/components/table/mf-table.component.spec.ts +76 -0
  133. package/src/app/components/table/mf-table.component.ts +117 -0
  134. package/src/app/components/tabs/index.ts +2 -0
  135. package/src/app/components/tabs/mf-tabs.component.css +31 -0
  136. package/src/app/components/tabs/mf-tabs.component.spec.ts +50 -0
  137. package/src/app/components/tabs/mf-tabs.component.ts +62 -0
  138. package/src/app/components/textarea/index.ts +2 -0
  139. package/src/app/components/textarea/mf-textarea.component.css +48 -0
  140. package/src/app/components/textarea/mf-textarea.component.spec.ts +55 -0
  141. package/src/app/components/textarea/mf-textarea.component.ts +227 -0
  142. package/src/app/components/toolbar/index.ts +2 -0
  143. package/src/app/components/toolbar/mf-toolbar.component.css +77 -0
  144. package/src/app/components/toolbar/mf-toolbar.component.ts +56 -0
  145. package/src/app/components/tooltip/index.ts +3 -0
  146. package/src/app/components/tooltip/mf-tooltip.component.css +7 -0
  147. package/src/app/components/tooltip/mf-tooltip.component.spec.ts +37 -0
  148. package/src/app/components/tooltip/mf-tooltip.component.ts +47 -0
  149. package/src/app/components/tooltip/mf-tooltip.directive.ts +22 -0
  150. package/src/index.html +18 -0
  151. package/src/main.ts +6 -0
  152. package/src/public-api.ts +31 -0
  153. package/src/stories/About.mdx +72 -0
  154. package/src/stories/Accessibility.mdx +59 -0
  155. package/src/stories/Welcome.mdx +26 -0
  156. package/src/stories/assets/accessibility.png +0 -0
  157. package/src/stories/assets/accessibility.svg +1 -0
  158. package/src/stories/assets/addon-library.png +0 -0
  159. package/src/stories/assets/assets.png +0 -0
  160. package/src/stories/assets/avif-test-image.avif +0 -0
  161. package/src/stories/assets/context.png +0 -0
  162. package/src/stories/assets/discord.svg +1 -0
  163. package/src/stories/assets/docs.png +0 -0
  164. package/src/stories/assets/figma-plugin.png +0 -0
  165. package/src/stories/assets/github.svg +1 -0
  166. package/src/stories/assets/share.png +0 -0
  167. package/src/stories/assets/styling.png +0 -0
  168. package/src/stories/assets/testing.png +0 -0
  169. package/src/stories/assets/theming.png +0 -0
  170. package/src/stories/assets/tutorials.svg +1 -0
  171. package/src/stories/assets/youtube.svg +1 -0
  172. package/src/stories/mf-a11y-contracts.stories.ts +472 -0
  173. package/src/stories/mf-autocomplete.stories.ts +194 -0
  174. package/src/stories/mf-button.stories.ts +152 -0
  175. package/src/stories/mf-card.stories.ts +147 -0
  176. package/src/stories/mf-checkbox.stories.ts +88 -0
  177. package/src/stories/mf-datepicker.stories.ts +118 -0
  178. package/src/stories/mf-dialog.stories.ts +159 -0
  179. package/src/stories/mf-form-field.stories.ts +108 -0
  180. package/src/stories/mf-grid-list.stories.ts +104 -0
  181. package/src/stories/mf-icon.stories.ts +133 -0
  182. package/src/stories/mf-input.stories.ts +158 -0
  183. package/src/stories/mf-menu.stories.ts +71 -0
  184. package/src/stories/mf-progress-bar.stories.ts +119 -0
  185. package/src/stories/mf-progress-spinner.stories.ts +124 -0
  186. package/src/stories/mf-radio-button.stories.ts +111 -0
  187. package/src/stories/mf-select.stories.ts +184 -0
  188. package/src/stories/mf-sidenav.stories.ts +331 -0
  189. package/src/stories/mf-table.stories.ts +80 -0
  190. package/src/stories/mf-toolbar.stories.ts +112 -0
  191. package/src/stories/user.ts +3 -0
  192. package/src/styles.css +58 -21
  193. package/src/theme/tokens.css +7 -4
  194. package/tsconfig.app.json +15 -0
  195. package/tsconfig.json +33 -0
  196. package/tsconfig.spec.json +15 -0
  197. package/vercel.json +6 -0
  198. package/fesm2022/ng-comps.mjs +0 -2479
  199. package/fesm2022/ng-comps.mjs.map +0 -1
  200. package/types/ng-comps.d.ts +0 -917
package/.editorconfig ADDED
@@ -0,0 +1,17 @@
1
+ # Editor configuration, see https://editorconfig.org
2
+ root = true
3
+
4
+ [*]
5
+ charset = utf-8
6
+ indent_style = space
7
+ indent_size = 2
8
+ insert_final_newline = true
9
+ trim_trailing_whitespace = true
10
+
11
+ [*.ts]
12
+ quote_type = single
13
+ ij_typescript_use_double_quotes = false
14
+
15
+ [*.md]
16
+ max_line_length = off
17
+ trim_trailing_whitespace = false
@@ -0,0 +1,55 @@
1
+
2
+ You are an expert in TypeScript, Angular, and scalable web application development. You write functional, maintainable, performant, and accessible code following Angular and TypeScript best practices.
3
+
4
+ ## TypeScript Best Practices
5
+
6
+ - Use strict type checking
7
+ - Prefer type inference when the type is obvious
8
+ - Avoid the `any` type; use `unknown` when type is uncertain
9
+
10
+ ## Angular Best Practices
11
+
12
+ - Always use standalone components over NgModules
13
+ - Must NOT set `standalone: true` inside Angular decorators. It's the default in Angular v20+.
14
+ - Use signals for state management
15
+ - Implement lazy loading for feature routes
16
+ - Do NOT use the `@HostBinding` and `@HostListener` decorators. Put host bindings inside the `host` object of the `@Component` or `@Directive` decorator instead
17
+ - Use `NgOptimizedImage` for all static images.
18
+ - `NgOptimizedImage` does not work for inline base64 images.
19
+
20
+ ## Accessibility Requirements
21
+
22
+ - It MUST pass all AXE checks.
23
+ - It MUST follow all WCAG AA minimums, including focus management, color contrast, and ARIA attributes.
24
+
25
+ ### Components
26
+
27
+ - Keep components small and focused on a single responsibility
28
+ - Use `input()` and `output()` functions instead of decorators
29
+ - Use `computed()` for derived state
30
+ - Set `changeDetection: ChangeDetectionStrategy.OnPush` in `@Component` decorator
31
+ - Prefer inline templates for small components
32
+ - Prefer Reactive forms instead of Template-driven ones
33
+ - Do NOT use `ngClass`, use `class` bindings instead
34
+ - Do NOT use `ngStyle`, use `style` bindings instead
35
+ - When using external templates/styles, use paths relative to the component TS file.
36
+
37
+ ## State Management
38
+
39
+ - Use signals for local component state
40
+ - Use `computed()` for derived state
41
+ - Keep state transformations pure and predictable
42
+ - Do NOT use `mutate` on signals, use `update` or `set` instead
43
+
44
+ ## Templates
45
+
46
+ - Keep templates simple and avoid complex logic
47
+ - Use native control flow (`@if`, `@for`, `@switch`) instead of `*ngIf`, `*ngFor`, `*ngSwitch`
48
+ - Use the async pipe to handle observables
49
+ - Do not assume globals like (`new Date()`) are available.
50
+
51
+ ## Services
52
+
53
+ - Design services around a single responsibility
54
+ - Use the `providedIn: 'root'` option for singleton services
55
+ - Use the `inject()` function instead of constructor injection
@@ -0,0 +1,29 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ - master
8
+ - 'codex/**'
9
+ pull_request:
10
+
11
+ jobs:
12
+ validate:
13
+ runs-on: ubuntu-latest
14
+
15
+ steps:
16
+ - name: Checkout
17
+ uses: actions/checkout@v4
18
+
19
+ - name: Setup Node
20
+ uses: actions/setup-node@v4
21
+ with:
22
+ node-version: 22
23
+ cache: npm
24
+
25
+ - name: Install
26
+ run: npm ci
27
+
28
+ - name: Validate Library
29
+ run: npm run ci
package/.prettierrc ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "printWidth": 100,
3
+ "singleQuote": true,
4
+ "overrides": [
5
+ {
6
+ "files": "*.html",
7
+ "options": {
8
+ "parser": "angular"
9
+ }
10
+ }
11
+ ]
12
+ }
@@ -0,0 +1,21 @@
1
+ import type { StorybookConfig } from '@storybook/angular';
2
+
3
+ const config: StorybookConfig = {
4
+ "stories": [
5
+ "../src/**/*.mdx",
6
+ "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"
7
+ ],
8
+ "addons": [
9
+ "@storybook/addon-a11y",
10
+ "@storybook/addon-docs"
11
+ ],
12
+ "framework": "@storybook/angular",
13
+ "previewHead": (head) => `
14
+ ${head}
15
+ <link rel="preconnect" href="https://fonts.googleapis.com">
16
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
17
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Manrope:wght@400;500;600;700&family=Sora:wght@500;700&display=swap">
18
+ <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
19
+ `,
20
+ };
21
+ export default config;
@@ -0,0 +1,27 @@
1
+ import { setCompodocJson } from '@storybook/addon-docs/angular';
2
+ import type { Preview } from '@storybook/angular';
3
+ import { applicationConfig } from '@storybook/angular';
4
+ import { provideAnimations } from '@angular/platform-browser/animations';
5
+ import { importProvidersFrom } from '@angular/core';
6
+ import { MatIconModule } from '@angular/material/icon';
7
+ import docJson from '../documentation.json';
8
+
9
+ setCompodocJson(docJson);
10
+
11
+ const preview: Preview = {
12
+ decorators: [
13
+ applicationConfig({
14
+ providers: [provideAnimations(), importProvidersFrom(MatIconModule)],
15
+ }),
16
+ ],
17
+ parameters: {
18
+ controls: {
19
+ matchers: {
20
+ color: /(background|color)$/i,
21
+ date: /Date$/i,
22
+ },
23
+ },
24
+ },
25
+ };
26
+
27
+ export default preview;
@@ -0,0 +1,10 @@
1
+ // This tsconfig is used by Compodoc to generate the documentation for the project.
2
+ // If Compodoc is not used, this file can be deleted.
3
+ {
4
+ "extends": "./tsconfig.json",
5
+ // Exclude all files that are not needed for documentation generation.
6
+ "exclude": ["../src/test.ts", "../src/**/*.spec.ts", "../src/**/*.stories.ts"],
7
+ // Please make sure to include all files from which Compodoc should generate documentation.
8
+ "include": ["../src/**/*"],
9
+ "files": ["./typings.d.ts"]
10
+ }
@@ -0,0 +1,15 @@
1
+ {
2
+ "extends": "../tsconfig.app.json",
3
+ "compilerOptions": {
4
+ "types": ["node"],
5
+ "allowSyntheticDefaultImports": true,
6
+ "resolveJsonModule": true
7
+ },
8
+ "exclude": ["../src/test.ts", "../src/**/*.spec.ts"],
9
+ "include": [
10
+ "../src/**/*.stories.*",
11
+ "../src/app/components/**/*.ts",
12
+ "./preview.ts"
13
+ ],
14
+ "files": ["./typings.d.ts"]
15
+ }
@@ -0,0 +1,4 @@
1
+ declare module '*.md' {
2
+ const content: string;
3
+ export default content;
4
+ }
@@ -0,0 +1,4 @@
1
+ {
2
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
3
+ "recommendations": ["angular.ng-template"]
4
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
3
+ "version": "0.2.0",
4
+ "configurations": [
5
+ {
6
+ "name": "ng serve",
7
+ "type": "chrome",
8
+ "request": "launch",
9
+ "preLaunchTask": "npm: start",
10
+ "url": "http://localhost:4200/"
11
+ },
12
+ {
13
+ "name": "ng test",
14
+ "type": "chrome",
15
+ "request": "launch",
16
+ "preLaunchTask": "npm: test",
17
+ "url": "http://localhost:9876/debug.html"
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ // For more information, visit: https://angular.dev/ai/mcp
3
+ "servers": {
4
+ "angular-cli": {
5
+ "command": "npx",
6
+ "args": ["-y", "@angular/cli", "mcp"]
7
+ }
8
+ }
9
+ }
@@ -0,0 +1,42 @@
1
+ {
2
+ // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
3
+ "version": "2.0.0",
4
+ "tasks": [
5
+ {
6
+ "type": "npm",
7
+ "script": "start",
8
+ "isBackground": true,
9
+ "problemMatcher": {
10
+ "owner": "typescript",
11
+ "pattern": "$tsc",
12
+ "background": {
13
+ "activeOnStart": true,
14
+ "beginsPattern": {
15
+ "regexp": "Changes detected"
16
+ },
17
+ "endsPattern": {
18
+ "regexp": "bundle generation (complete|failed)"
19
+ }
20
+ }
21
+ }
22
+ },
23
+ {
24
+ "type": "npm",
25
+ "script": "test",
26
+ "isBackground": true,
27
+ "problemMatcher": {
28
+ "owner": "typescript",
29
+ "pattern": "$tsc",
30
+ "background": {
31
+ "activeOnStart": true,
32
+ "beginsPattern": {
33
+ "regexp": "Changes detected"
34
+ },
35
+ "endsPattern": {
36
+ "regexp": "bundle generation (complete|failed)"
37
+ }
38
+ }
39
+ }
40
+ }
41
+ ]
42
+ }
@@ -0,0 +1,127 @@
1
+ # Accessibility Contract for ng-comps v1
2
+
3
+ ## Positioning
4
+
5
+ `ng-comps` v1 is built to make accessible implementation the default path for Angular teams using Angular Material under a branded component layer.
6
+
7
+ Repository goals:
8
+
9
+ - implement against WCAG 2.2 AA at component level
10
+ - keep contractual evidence aligned to EN 301 549 v3.2.1 / WCAG 2.1 AA until the next EN revision is formally published
11
+ - document known limits so procurement claims stay technically defensible
12
+
13
+ The library can support accessibility conformance. It cannot guarantee application-level conformance on its own.
14
+
15
+ ## Public Contract
16
+
17
+ Consumers must follow these rules:
18
+
19
+ 1. Every interactive component must expose an accessible name through visible text, `label`, `ariaLabel`, or `ariaLabelledby`.
20
+ 2. Placeholders are supplementary hints, never the only label.
21
+ 3. Icon-only actions must provide an explicit accessible label.
22
+ 4. Focus must remain visible. Consumers must not remove outlines without an equivalent replacement.
23
+ 5. Dialogs, menus, selects, datepickers, and sidenavs must use the provided accessible APIs and patterns.
24
+ 6. Table row interactions must be explicit buttons or links inside cells. Whole-row click targets are not part of the default contract.
25
+ 7. Theme overrides must preserve contrast and focus ring visibility.
26
+
27
+ ## What the Library Now Enforces
28
+
29
+ - shared accessible-name contract on interactive form controls
30
+ - `ControlValueAccessor` support for core form inputs
31
+ - `aria-describedby` wiring for hints, counters, and errors
32
+ - `aria-invalid` reflection for explicit and form-driven errors
33
+ - visible global `:focus-visible` styling
34
+ - safer dialog opening through `MfDialogService`
35
+ - explicit row actions in `MfTableComponent`
36
+ - snackbar politeness and announcement support
37
+ - tooltip directive support on the real host element via `mfTooltip`
38
+
39
+ ## Component Notes
40
+
41
+ ### Buttons and triggers
42
+
43
+ - `MfButtonComponent` supports icon-only mode, but icon-only usage requires `ariaLabel` or `ariaLabelledby`.
44
+ - `MfMenuComponent` exposes a labelled trigger and relies on Angular Material keyboard navigation for menu items.
45
+
46
+ ### Form controls
47
+
48
+ - `MfInputComponent`
49
+ - `MfTextareaComponent`
50
+ - `MfSelectComponent`
51
+ - `MfAutocompleteComponent`
52
+ - `MfDatepickerComponent`
53
+ - `MfCheckboxComponent`
54
+ - `MfRadioButtonComponent`
55
+ - `MfSlideToggleComponent`
56
+
57
+ These components support Angular forms integration, descriptive relationships, and explicit error announcements.
58
+
59
+ ### Overlays
60
+
61
+ - `MfDialogService` applies safe defaults for role, autofocus, restore focus, and panel class.
62
+ - `MfDialogComponent` requires a visible title or explicit accessible name.
63
+ - `MfDatepickerComponent`, `MfSelectComponent`, and `MfAutocompleteComponent` inherit keyboard interaction from Angular Material and are documented with keyboard contract stories in Storybook.
64
+
65
+ ### Data and status
66
+
67
+ - `MfTableComponent` uses explicit action controls instead of clickable rows.
68
+ - `MfProgressBarComponent` and `MfProgressSpinnerComponent` require accessible labels for informative usage.
69
+ - `MfBadgeComponent` distinguishes decorative usage from informative usage through `description`.
70
+ - `MfAvatarComponent` distinguishes decorative usage from informative usage through `decorative`.
71
+
72
+ ## Automated Validation in This Repo
73
+
74
+ Local commands:
75
+
76
+ ```bash
77
+ npm run build:lib
78
+ npm run test:ci
79
+ npm run build-storybook
80
+ npm run ci
81
+ ```
82
+
83
+ Automated coverage currently includes:
84
+
85
+ - unit tests
86
+ - DOM-level accessibility checks with `axe-core`
87
+ - regression checks for accessibility-oriented API defaults
88
+ - Storybook static build for documentation and contract stories
89
+
90
+ ## Manual Validation Matrix
91
+
92
+ This repository still requires manual validation before any formal claim:
93
+
94
+ - keyboard-only navigation
95
+ - 200% zoom
96
+ - reflow equivalent to 320 CSS px width
97
+ - NVDA on Windows
98
+ - VoiceOver on macOS
99
+ - visible focus review
100
+ - contrast review after any token override
101
+
102
+ ## Known Limitations
103
+
104
+ - Application conformance still depends on consumer content, routing, state changes, and custom wrappers.
105
+ - If consumers override tokens or Angular Material theme values, they must re-run contrast checks.
106
+ - `MfTooltipComponent` is retained for compatibility, but the preferred API in v1 is the `mfTooltip` directive on the host element.
107
+ - Repeated row actions in tables should provide contextual `rowActionAriaLabel` values for best screen reader output.
108
+ - Screen reader verification remains mandatory for procurement-grade evidence.
109
+
110
+ ## VPAT-Oriented Evidence Base
111
+
112
+ This repository now includes:
113
+
114
+ - component-level accessibility defaults
115
+ - automated checks that run in CI
116
+ - Storybook contract stories for critical interaction patterns
117
+ - explicit documentation of correct usage, anti-patterns, and limitations
118
+
119
+ That is a usable base for a VPAT process, but not a completed VPAT by itself.
120
+
121
+ ## Normative References
122
+
123
+ - W3C WCAG overview: https://www.w3.org/WAI/standards-guidelines/wcag/
124
+ - EN 301 549 working repository: https://labs.etsi.org/rep/HF/en301549
125
+ - ETSI download/status entry referenced in procurement notes: https://portal.etsi.org/webapp/ewp/copy_file.asp?wki_id=64282
126
+
127
+ As verified on 2026-03-27, W3C states that EN 301 549 currently uses WCAG 2.1 and encourages use of WCAG 2.2, while the EN 301 549 working repository describes the v4.1.0 draft as being in formal approval flow rather than a published replacement.
package/README.md CHANGED
@@ -1,62 +1,79 @@
1
- # ng-comps
2
-
3
- Libreria de componentes UI para Angular con enfoque en:
4
-
5
- - paquete NPM liviano
6
- - tree-shaking real
7
- - peers de Angular (sin duplicar framework en cada instalacion)
8
-
9
- ## Instalacion (consumidor)
10
-
11
- ```bash
12
- npm i ng-comps
13
- ```
14
-
15
- Importa solo lo que usas:
16
-
17
- ```ts
18
- import { MfButtonComponent } from 'ng-comps';
19
- ```
20
-
21
- Si quieres usar los tokens/estilos base:
22
-
23
- ```css
24
- @import 'ng-comps/theme/tokens.css';
25
- @import 'ng-comps/styles.css';
26
- ```
27
-
28
- ## Publicacion optimizada a NPM
29
-
30
- Este repo publica desde `dist/ng-comps`, no desde la raiz. De esta forma no se suben historias, tests ni archivos de desarrollo.
31
-
32
- 1. Construir la libreria APF:
33
-
34
- ```bash
35
- npm run build:lib
36
- ```
37
-
38
- 2. Generar `package.json` optimizado para distribucion:
39
-
40
- ```bash
41
- npm run prepare:package
42
- ```
43
-
44
- 3. Verificar contenido del paquete antes de publicar:
45
-
46
- ```bash
47
- npm run release:dry-run
48
- ```
49
-
50
- 4. Publicar:
51
-
52
- ```bash
53
- npm run publish:npm
54
- ```
55
-
56
- ## Estrategia de optimizacion aplicada
57
-
58
- - `sideEffects: false` para maximizar tree-shaking
59
- - `peerDependencies` para Angular y RxJS (evita bundles duplicados)
60
- - `dependencies` minimas (`tslib`)
61
- - `exports` explicitos para entrypoint y estilos
62
- - publicacion desde carpeta de build (`dist/ng-comps`)
1
+ # ng-comps
2
+
3
+ Angular UI library built on top of Angular Material with a public accessibility contract.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm i ng-comps
9
+ ```
10
+
11
+ Import only what you use:
12
+
13
+ ```ts
14
+ import { MfButtonComponent } from 'ng-comps';
15
+ ```
16
+
17
+ Load the shared tokens and base styles in your global stylesheet:
18
+
19
+ ```css
20
+ @import 'ng-comps/theme/tokens.css';
21
+ @import 'ng-comps/styles.css';
22
+ ```
23
+
24
+ ## Accessibility Contract
25
+
26
+ `ng-comps` v1 is designed to support:
27
+
28
+ - WCAG 2.2 AA implementation targets in the component layer
29
+ - EN 301 549 evidence mapping when the library is used as documented
30
+ - Contractual reporting against EN 301 549 v3.2.1 / WCAG 2.1 AA until the next EN update is formally published
31
+
32
+ The library is accessible by default only when consumers keep the semantic contract intact:
33
+
34
+ - interactive components must have an accessible name
35
+ - visible labels are preferred over placeholders
36
+ - overlays must be opened through the provided accessible APIs
37
+ - row actions in tables must be explicit and focusable
38
+ - custom theming must preserve contrast and visible focus states
39
+
40
+ Read the full contract, QA matrix, limitations, and VPAT-oriented notes in [ACCESSIBILITY.md](./ACCESSIBILITY.md).
41
+
42
+ ## Development
43
+
44
+ ```bash
45
+ npm run build:lib
46
+ npm run test:ci
47
+ npm run build-storybook
48
+ npm run ci
49
+ ```
50
+
51
+ `npm run ci` executes the local gate used by CI:
52
+
53
+ - library build
54
+ - unit and accessibility tests
55
+ - Storybook static build
56
+
57
+ ## Storybook
58
+
59
+ Storybook is the primary documentation surface for component usage and accessibility contracts.
60
+
61
+ - component API stories live in `src/stories`
62
+ - accessibility contract stories cover keyboard, focus, overlays, and explicit actions
63
+ - anti-patterns are documented as examples of what not to ship
64
+
65
+ ## Publishing
66
+
67
+ This repository publishes from `dist/ng-comps`, not from the workspace root.
68
+
69
+ ```bash
70
+ npm run build:lib
71
+ npm run prepare:package
72
+ npm run release:dry-run
73
+ npm run publish:npm
74
+ ```
75
+
76
+ ## Important Limitation
77
+
78
+ Using `ng-comps` does not make an application automatically conformant with WCAG or EN 301 549.
79
+ Final conformance still depends on product copy, content, workflows, application state management, custom wrappers, and consumer integration decisions.
package/angular.json ADDED
@@ -0,0 +1,105 @@
1
+ {
2
+ "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3
+ "version": 1,
4
+ "cli": {
5
+ "packageManager": "npm",
6
+ "analytics": "186cd70a-0821-4a2c-a822-a3d7739f41eb"
7
+ },
8
+ "newProjectRoot": "projects",
9
+ "projects": {
10
+ "ng-comps": {
11
+ "projectType": "application",
12
+ "schematics": {},
13
+ "root": "",
14
+ "sourceRoot": "src",
15
+ "prefix": "app",
16
+ "architect": {
17
+ "build": {
18
+ "builder": "@angular/build:application",
19
+ "options": {
20
+ "browser": "src/main.ts",
21
+ "tsConfig": "tsconfig.app.json",
22
+ "assets": [
23
+ {
24
+ "glob": "**/*",
25
+ "input": "public"
26
+ }
27
+ ],
28
+ "styles": [
29
+ "src/theme/material-theme.scss",
30
+ "src/styles.css"
31
+ ]
32
+ },
33
+ "configurations": {
34
+ "production": {
35
+ "budgets": [
36
+ {
37
+ "type": "initial",
38
+ "maximumWarning": "500kB",
39
+ "maximumError": "1MB"
40
+ },
41
+ {
42
+ "type": "anyComponentStyle",
43
+ "maximumWarning": "4kB",
44
+ "maximumError": "8kB"
45
+ }
46
+ ],
47
+ "outputHashing": "all"
48
+ },
49
+ "development": {
50
+ "optimization": false,
51
+ "extractLicenses": false,
52
+ "sourceMap": true
53
+ }
54
+ },
55
+ "defaultConfiguration": "production"
56
+ },
57
+ "serve": {
58
+ "builder": "@angular/build:dev-server",
59
+ "configurations": {
60
+ "production": {
61
+ "buildTarget": "ng-comps:build:production"
62
+ },
63
+ "development": {
64
+ "buildTarget": "ng-comps:build:development"
65
+ }
66
+ },
67
+ "defaultConfiguration": "development"
68
+ },
69
+ "test": {
70
+ "builder": "@angular/build:unit-test"
71
+ },
72
+ "storybook": {
73
+ "builder": "@storybook/angular:start-storybook",
74
+ "options": {
75
+ "configDir": ".storybook",
76
+ "browserTarget": "ng-comps:build",
77
+ "compodoc": true,
78
+ "compodocArgs": [
79
+ "-e",
80
+ "json",
81
+ "-d",
82
+ "."
83
+ ],
84
+ "port": 6006
85
+ }
86
+ },
87
+ "build-storybook": {
88
+ "builder": "@storybook/angular:build-storybook",
89
+ "options": {
90
+ "configDir": ".storybook",
91
+ "browserTarget": "ng-comps:build",
92
+ "compodoc": true,
93
+ "compodocArgs": [
94
+ "-e",
95
+ "json",
96
+ "-d",
97
+ "."
98
+ ],
99
+ "outputDir": "storybook-static"
100
+ }
101
+ }
102
+ }
103
+ }
104
+ }
105
+ }