ng-comps 0.2.0 → 1.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.
- package/.editorconfig +17 -0
- package/.github/copilot-instructions.md +55 -0
- package/.github/workflows/ci.yml +29 -0
- package/.prettierrc +12 -0
- package/.storybook/main.ts +21 -0
- package/.storybook/preview.ts +27 -0
- package/.storybook/tsconfig.doc.json +10 -0
- package/.storybook/tsconfig.json +15 -0
- package/.storybook/typings.d.ts +4 -0
- package/.vscode/extensions.json +4 -0
- package/.vscode/launch.json +20 -0
- package/.vscode/mcp.json +9 -0
- package/.vscode/tasks.json +42 -0
- package/ACCESSIBILITY.md +127 -0
- package/README.md +79 -62
- package/angular.json +105 -0
- package/documentation.json +13394 -0
- package/ng-package.json +27 -0
- package/package.json +58 -45
- package/public/favicon.ico +0 -0
- package/scripts/prepare-package.mjs +61 -0
- package/src/app/a11y/accessibility.utils.ts +35 -0
- package/src/app/a11y/index.ts +6 -0
- package/src/app/accessibility/ng-comps.a11y.spec.ts +108 -0
- package/src/app/app.config.ts +11 -0
- package/src/app/app.css +107 -0
- package/src/app/app.html +48 -0
- package/src/app/app.routes.ts +3 -0
- package/src/app/app.spec.ts +23 -0
- package/src/app/app.ts +10 -0
- package/src/app/components/accordion/index.ts +2 -0
- package/src/app/components/accordion/mf-accordion.component.css +38 -0
- package/src/app/components/accordion/mf-accordion.component.spec.ts +48 -0
- package/src/app/components/accordion/mf-accordion.component.ts +53 -0
- package/src/app/components/alert/index.ts +2 -0
- package/src/app/components/alert/mf-alert.component.css +100 -0
- package/src/app/components/alert/mf-alert.component.spec.ts +59 -0
- package/src/app/components/alert/mf-alert.component.ts +68 -0
- package/src/app/components/autocomplete/index.ts +5 -0
- package/src/app/components/autocomplete/mf-autocomplete.component.css +105 -0
- package/src/app/components/autocomplete/mf-autocomplete.component.spec.ts +116 -0
- package/src/app/components/autocomplete/mf-autocomplete.component.ts +307 -0
- package/src/app/components/avatar/index.ts +2 -0
- package/src/app/components/avatar/mf-avatar.component.css +27 -0
- package/src/app/components/avatar/mf-avatar.component.spec.ts +49 -0
- package/src/app/components/avatar/mf-avatar.component.ts +99 -0
- package/src/app/components/badge/index.ts +2 -0
- package/src/app/components/badge/mf-badge.component.css +32 -0
- package/src/app/components/badge/mf-badge.component.spec.ts +40 -0
- package/src/app/components/badge/mf-badge.component.ts +105 -0
- package/src/app/components/breadcrumb/index.ts +2 -0
- package/src/app/components/breadcrumb/mf-breadcrumb.component.css +61 -0
- package/src/app/components/breadcrumb/mf-breadcrumb.component.spec.ts +61 -0
- package/src/app/components/breadcrumb/mf-breadcrumb.component.ts +75 -0
- package/src/app/components/button/index.ts +2 -0
- package/src/app/components/button/mf-button.component.css +136 -0
- package/src/app/components/button/mf-button.component.ts +174 -0
- package/src/app/components/card/index.ts +2 -0
- package/src/app/components/card/mf-card.component.css +82 -0
- package/src/app/components/card/mf-card.component.ts +59 -0
- package/src/app/components/checkbox/index.ts +1 -0
- package/src/app/components/checkbox/mf-checkbox.component.css +75 -0
- package/src/app/components/checkbox/mf-checkbox.component.ts +187 -0
- package/src/app/components/chip/index.ts +2 -0
- package/src/app/components/chip/mf-chip.component.css +69 -0
- package/src/app/components/chip/mf-chip.component.spec.ts +47 -0
- package/src/app/components/chip/mf-chip.component.ts +77 -0
- package/src/app/components/datepicker/index.ts +2 -0
- package/src/app/components/datepicker/mf-datepicker.component.css +102 -0
- package/src/app/components/datepicker/mf-datepicker.component.spec.ts +69 -0
- package/src/app/components/datepicker/mf-datepicker.component.ts +233 -0
- package/src/app/components/dialog/index.ts +3 -0
- package/src/app/components/dialog/mf-dialog.component.css +73 -0
- package/src/app/components/dialog/mf-dialog.component.ts +160 -0
- package/src/app/components/dialog/mf-dialog.service.spec.ts +61 -0
- package/src/app/components/dialog/mf-dialog.service.ts +52 -0
- package/src/app/components/divider/index.ts +2 -0
- package/src/app/components/divider/mf-divider.component.css +38 -0
- package/src/app/components/divider/mf-divider.component.spec.ts +40 -0
- package/src/app/components/divider/mf-divider.component.ts +44 -0
- package/src/app/components/form-field/index.ts +1 -0
- package/src/app/components/form-field/mf-form-field.component.css +51 -0
- package/src/app/components/form-field/mf-form-field.component.ts +74 -0
- package/src/app/components/grid-list/index.ts +2 -0
- package/src/app/components/grid-list/mf-grid-list.component.css +47 -0
- package/src/app/components/grid-list/mf-grid-list.component.spec.ts +57 -0
- package/src/app/components/grid-list/mf-grid-list.component.ts +68 -0
- package/src/app/components/icon/index.ts +2 -0
- package/src/app/components/icon/mf-icon.component.css +56 -0
- package/src/app/components/icon/mf-icon.component.ts +41 -0
- package/src/app/components/input/index.ts +2 -0
- package/src/app/components/input/mf-input.component.css +105 -0
- package/src/app/components/input/mf-input.component.ts +217 -0
- package/src/app/components/menu/index.ts +2 -0
- package/src/app/components/menu/mf-menu.component.css +31 -0
- package/src/app/components/menu/mf-menu.component.spec.ts +49 -0
- package/src/app/components/menu/mf-menu.component.ts +66 -0
- package/src/app/components/paginator/index.ts +1 -0
- package/src/app/components/paginator/mf-paginator.component.css +32 -0
- package/src/app/components/paginator/mf-paginator.component.spec.ts +44 -0
- package/src/app/components/paginator/mf-paginator.component.ts +52 -0
- package/src/app/components/progress-bar/index.ts +2 -0
- package/src/app/components/progress-bar/mf-progress-bar.component.css +53 -0
- package/src/app/components/progress-bar/mf-progress-bar.component.spec.ts +65 -0
- package/src/app/components/progress-bar/mf-progress-bar.component.ts +79 -0
- package/src/app/components/progress-spinner/index.ts +2 -0
- package/src/app/components/progress-spinner/mf-progress-spinner.component.css +38 -0
- package/src/app/components/progress-spinner/mf-progress-spinner.component.spec.ts +59 -0
- package/src/app/components/progress-spinner/mf-progress-spinner.component.ts +81 -0
- package/src/app/components/radio-button/index.ts +2 -0
- package/src/app/components/radio-button/mf-radio-button.component.css +86 -0
- package/src/app/components/radio-button/mf-radio-button.component.spec.ts +55 -0
- package/src/app/components/radio-button/mf-radio-button.component.ts +219 -0
- package/src/app/components/select/index.ts +2 -0
- package/src/app/components/select/mf-select.component.css +121 -0
- package/src/app/components/select/mf-select.component.spec.ts +108 -0
- package/src/app/components/select/mf-select.component.ts +252 -0
- package/src/app/components/sidenav/index.ts +2 -0
- package/src/app/components/sidenav/mf-sidenav.component.css +168 -0
- package/src/app/components/sidenav/mf-sidenav.component.spec.ts +57 -0
- package/src/app/components/sidenav/mf-sidenav.component.ts +126 -0
- package/src/app/components/slide-toggle/index.ts +1 -0
- package/src/app/components/slide-toggle/mf-slide-toggle.component.css +42 -0
- package/src/app/components/slide-toggle/mf-slide-toggle.component.spec.ts +43 -0
- package/src/app/components/slide-toggle/mf-slide-toggle.component.ts +188 -0
- package/src/app/components/snackbar/index.ts +2 -0
- package/src/app/components/snackbar/mf-snackbar.service.css +31 -0
- package/src/app/components/snackbar/mf-snackbar.service.spec.ts +81 -0
- package/src/app/components/snackbar/mf-snackbar.service.ts +77 -0
- package/src/app/components/table/index.ts +2 -0
- package/src/app/components/table/mf-table.component.css +68 -0
- package/src/app/components/table/mf-table.component.spec.ts +76 -0
- package/src/app/components/table/mf-table.component.ts +117 -0
- package/src/app/components/tabs/index.ts +2 -0
- package/src/app/components/tabs/mf-tabs.component.css +31 -0
- package/src/app/components/tabs/mf-tabs.component.spec.ts +50 -0
- package/src/app/components/tabs/mf-tabs.component.ts +62 -0
- package/src/app/components/textarea/index.ts +2 -0
- package/src/app/components/textarea/mf-textarea.component.css +48 -0
- package/src/app/components/textarea/mf-textarea.component.spec.ts +55 -0
- package/src/app/components/textarea/mf-textarea.component.ts +227 -0
- package/src/app/components/toolbar/index.ts +2 -0
- package/src/app/components/toolbar/mf-toolbar.component.css +77 -0
- package/src/app/components/toolbar/mf-toolbar.component.ts +56 -0
- package/src/app/components/tooltip/index.ts +3 -0
- package/src/app/components/tooltip/mf-tooltip.component.css +7 -0
- package/src/app/components/tooltip/mf-tooltip.component.spec.ts +37 -0
- package/src/app/components/tooltip/mf-tooltip.component.ts +47 -0
- package/src/app/components/tooltip/mf-tooltip.directive.ts +22 -0
- package/src/index.html +18 -0
- package/src/main.ts +6 -0
- package/src/public-api.ts +31 -0
- package/src/stories/About.mdx +72 -0
- package/src/stories/Accessibility.mdx +59 -0
- package/src/stories/Welcome.mdx +27 -0
- package/src/stories/assets/accessibility.png +0 -0
- package/src/stories/assets/accessibility.svg +1 -0
- package/src/stories/assets/addon-library.png +0 -0
- package/src/stories/assets/assets.png +0 -0
- package/src/stories/assets/avif-test-image.avif +0 -0
- package/src/stories/assets/context.png +0 -0
- package/src/stories/assets/discord.svg +1 -0
- package/src/stories/assets/docs.png +0 -0
- package/src/stories/assets/figma-plugin.png +0 -0
- package/src/stories/assets/github.svg +1 -0
- package/src/stories/assets/share.png +0 -0
- package/src/stories/assets/styling.png +0 -0
- package/src/stories/assets/testing.png +0 -0
- package/src/stories/assets/theming.png +0 -0
- package/src/stories/assets/tutorials.svg +1 -0
- package/src/stories/assets/youtube.svg +1 -0
- package/src/stories/mf-a11y-contracts.stories.ts +472 -0
- package/src/stories/mf-autocomplete.stories.ts +188 -0
- package/src/stories/mf-button.stories.ts +156 -0
- package/src/stories/mf-card.stories.ts +148 -0
- package/src/stories/mf-checkbox.stories.ts +88 -0
- package/src/stories/mf-datepicker.stories.ts +118 -0
- package/src/stories/mf-dialog.stories.ts +167 -0
- package/src/stories/mf-form-field.stories.ts +108 -0
- package/src/stories/mf-grid-list.stories.ts +105 -0
- package/src/stories/mf-icon.stories.ts +130 -0
- package/src/stories/mf-input.stories.ts +158 -0
- package/src/stories/mf-menu.stories.ts +71 -0
- package/src/stories/mf-progress-bar.stories.ts +119 -0
- package/src/stories/mf-progress-spinner.stories.ts +124 -0
- package/src/stories/mf-radio-button.stories.ts +111 -0
- package/src/stories/mf-select.stories.ts +178 -0
- package/src/stories/mf-sidenav.stories.ts +334 -0
- package/src/stories/mf-table.stories.ts +80 -0
- package/src/stories/mf-toolbar.stories.ts +112 -0
- package/src/stories/user.ts +3 -0
- package/src/styles.css +58 -21
- package/src/theme/tokens.css +7 -4
- package/tsconfig.app.json +15 -0
- package/tsconfig.json +33 -0
- package/tsconfig.spec.json +15 -0
- package/vercel.json +6 -0
- package/fesm2022/ng-comps.mjs +0 -2479
- package/fesm2022/ng-comps.mjs.map +0 -1
- 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,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,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
|
+
}
|
package/.vscode/mcp.json
ADDED
|
@@ -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
|
+
}
|
package/ACCESSIBILITY.md
ADDED
|
@@ -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
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
npm run
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
-
|
|
62
|
-
-
|
|
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
|
+
}
|