@openmfp/webcomponents 0.6.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 (140) hide show
  1. package/.github/workflows/pipeline.yaml +41 -0
  2. package/.storybook/main.ts +34 -0
  3. package/.storybook/preview.ts +29 -0
  4. package/.storybook/tsconfig.json +11 -0
  5. package/AGENTS.md +153 -0
  6. package/CODEOWNERS +6 -0
  7. package/CONTRIBUTING.md +95 -0
  8. package/LICENSE +201 -0
  9. package/LICENSES/Apache-2.0.txt +73 -0
  10. package/README.md +91 -0
  11. package/REUSE.toml +9 -0
  12. package/angular.json +157 -0
  13. package/docs/dashboard.md +358 -0
  14. package/docs/declarative-form.md +178 -0
  15. package/docs/declarative-table-card.md +235 -0
  16. package/docs/declarative-table.md +315 -0
  17. package/eslint.config.js +41 -0
  18. package/package.json +73 -0
  19. package/projects/ngx/cards/favorites/favorites.component.html +12 -0
  20. package/projects/ngx/cards/favorites/favorites.component.scss +50 -0
  21. package/projects/ngx/cards/favorites/favorites.component.ts +19 -0
  22. package/projects/ngx/cards/public-api.ts +4 -0
  23. package/projects/ngx/cards/service-status/service-status-card.component.html +15 -0
  24. package/projects/ngx/cards/service-status/service-status-card.component.scss +87 -0
  25. package/projects/ngx/cards/service-status/service-status-card.component.ts +36 -0
  26. package/projects/ngx/cards/stories/visited-service-card.stories.ts +149 -0
  27. package/projects/ngx/cards/visited-service-card/visited-service-card.component.html +17 -0
  28. package/projects/ngx/cards/visited-service-card/visited-service-card.component.scss +34 -0
  29. package/projects/ngx/cards/visited-service-card/visited-service-card.component.ts +22 -0
  30. package/projects/ngx/cards/whats-new/whats-new.component.html +10 -0
  31. package/projects/ngx/cards/whats-new/whats-new.component.scss +25 -0
  32. package/projects/ngx/cards/whats-new/whats-new.component.ts +46 -0
  33. package/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.html +28 -0
  34. package/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.scss +44 -0
  35. package/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.spec.ts +85 -0
  36. package/projects/ngx/declarative-ui/dashboard/add-card-dialog/add-card-dialog.component.ts +58 -0
  37. package/projects/ngx/declarative-ui/dashboard/card/dashboard-card.component.html +29 -0
  38. package/projects/ngx/declarative-ui/dashboard/card/dashboard-card.component.scss +63 -0
  39. package/projects/ngx/declarative-ui/dashboard/card/dashboard-card.component.spec.ts +255 -0
  40. package/projects/ngx/declarative-ui/dashboard/card/dashboard-card.component.ts +75 -0
  41. package/projects/ngx/declarative-ui/dashboard/card/utils/dashboard-card-registry.spec.ts +76 -0
  42. package/projects/ngx/declarative-ui/dashboard/card/utils/dashboard-card-registry.ts +109 -0
  43. package/projects/ngx/declarative-ui/dashboard/card/utils/index.ts +4 -0
  44. package/projects/ngx/declarative-ui/dashboard/card/utils/mount-angular-card.spec.ts +141 -0
  45. package/projects/ngx/declarative-ui/dashboard/card/utils/mount-angular-card.ts +44 -0
  46. package/projects/ngx/declarative-ui/dashboard/card/utils/mount-sap-card.spec.ts +142 -0
  47. package/projects/ngx/declarative-ui/dashboard/card/utils/mount-sap-card.ts +52 -0
  48. package/projects/ngx/declarative-ui/dashboard/card/utils/mount-wc-card.spec.ts +107 -0
  49. package/projects/ngx/declarative-ui/dashboard/card/utils/mount-wc-card.ts +22 -0
  50. package/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.html +134 -0
  51. package/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.scss +88 -0
  52. package/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.spec.ts +354 -0
  53. package/projects/ngx/declarative-ui/dashboard/dashboard/dashboard.component.ts +238 -0
  54. package/projects/ngx/declarative-ui/dashboard/dashboard/index.ts +1 -0
  55. package/projects/ngx/declarative-ui/dashboard/index.ts +5 -0
  56. package/projects/ngx/declarative-ui/dashboard/models/constants.ts +2 -0
  57. package/projects/ngx/declarative-ui/dashboard/models/dashboard.model.ts +50 -0
  58. package/projects/ngx/declarative-ui/dashboard/models/index.ts +1 -0
  59. package/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.html +28 -0
  60. package/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.scss +85 -0
  61. package/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.spec.ts +104 -0
  62. package/projects/ngx/declarative-ui/dashboard/section/dashboard-section.component.ts +23 -0
  63. package/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.html +62 -0
  64. package/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.scss +12 -0
  65. package/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.spec.ts +301 -0
  66. package/projects/ngx/declarative-ui/form/declarative-form/declarative-form.component.ts +166 -0
  67. package/projects/ngx/declarative-ui/form/declarative-form/index.ts +1 -0
  68. package/projects/ngx/declarative-ui/form/index.ts +2 -0
  69. package/projects/ngx/declarative-ui/form/models/form-field-definition.ts +15 -0
  70. package/projects/ngx/declarative-ui/form/models/index.ts +1 -0
  71. package/projects/ngx/declarative-ui/form/utils/set-property-by-path.ts +30 -0
  72. package/projects/ngx/declarative-ui/models/index.ts +2 -0
  73. package/projects/ngx/declarative-ui/models/resource.ts +5 -0
  74. package/projects/ngx/declarative-ui/models/ui-definition.ts +95 -0
  75. package/projects/ngx/declarative-ui/public-api.ts +4 -0
  76. package/projects/ngx/declarative-ui/stories/add-card-dialog.stories.ts +91 -0
  77. package/projects/ngx/declarative-ui/stories/background-lightblue.png +0 -0
  78. package/projects/ngx/declarative-ui/stories/dashboard.cards.ts +107 -0
  79. package/projects/ngx/declarative-ui/stories/dashboard.stories.ts +296 -0
  80. package/projects/ngx/declarative-ui/stories/declarative-form.stories.ts +149 -0
  81. package/projects/ngx/declarative-ui/stories/declarative-table-card.stories.ts +358 -0
  82. package/projects/ngx/declarative-ui/stories/declarative-table.stories.ts +363 -0
  83. package/projects/ngx/declarative-ui/stories/pods-table.config.ts +188 -0
  84. package/projects/ngx/declarative-ui/table/declarative-table/declarative-table.component.html +138 -0
  85. package/projects/ngx/declarative-ui/table/declarative-table/declarative-table.component.scss +21 -0
  86. package/projects/ngx/declarative-ui/table/declarative-table/declarative-table.component.spec.ts +345 -0
  87. package/projects/ngx/declarative-ui/table/declarative-table/declarative-table.component.ts +61 -0
  88. package/projects/ngx/declarative-ui/table/declarative-table/index.ts +1 -0
  89. package/projects/ngx/declarative-ui/table/index.ts +2 -0
  90. package/projects/ngx/declarative-ui/table/models/index.ts +14 -0
  91. package/projects/ngx/declarative-ui/table/models/table.model.ts +17 -0
  92. package/projects/ngx/declarative-ui/table/utils/cssRules.engine.spec.ts +146 -0
  93. package/projects/ngx/declarative-ui/table/utils/cssRules.engine.ts +69 -0
  94. package/projects/ngx/declarative-ui/table/utils/field-definition.utils.spec.ts +70 -0
  95. package/projects/ngx/declarative-ui/table/utils/field-definition.utils.ts +13 -0
  96. package/projects/ngx/declarative-ui/table/utils/proccess-fields.spec.ts +511 -0
  97. package/projects/ngx/declarative-ui/table/utils/proccess-fields.ts +71 -0
  98. package/projects/ngx/declarative-ui/table/utils/resource-field-by-path.spec.ts +372 -0
  99. package/projects/ngx/declarative-ui/table/utils/resource-field-by-path.ts +98 -0
  100. package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-cell.constants.ts +5 -0
  101. package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.html +1 -0
  102. package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.scss +0 -0
  103. package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.spec.ts +119 -0
  104. package/projects/ngx/declarative-ui/table/value-cell/boolean-value/boolean-value.component.ts +35 -0
  105. package/projects/ngx/declarative-ui/table/value-cell/link-value/link-value.component.html +7 -0
  106. package/projects/ngx/declarative-ui/table/value-cell/link-value/link-value.component.scss +0 -0
  107. package/projects/ngx/declarative-ui/table/value-cell/link-value/link-value.component.spec.ts +114 -0
  108. package/projects/ngx/declarative-ui/table/value-cell/link-value/link-value.component.ts +19 -0
  109. package/projects/ngx/declarative-ui/table/value-cell/secret-value/secret-value.component.html +7 -0
  110. package/projects/ngx/declarative-ui/table/value-cell/secret-value/secret-value.component.scss +10 -0
  111. package/projects/ngx/declarative-ui/table/value-cell/secret-value/secret-value.component.spec.ts +188 -0
  112. package/projects/ngx/declarative-ui/table/value-cell/secret-value/secret-value.component.ts +16 -0
  113. package/projects/ngx/declarative-ui/table/value-cell/value-cell.component.html +59 -0
  114. package/projects/ngx/declarative-ui/table/value-cell/value-cell.component.scss +33 -0
  115. package/projects/ngx/declarative-ui/table/value-cell/value-cell.component.spec.ts +316 -0
  116. package/projects/ngx/declarative-ui/table/value-cell/value-cell.component.ts +115 -0
  117. package/projects/ngx/declarative-ui/table-card/declarative-table-card.component.html +156 -0
  118. package/projects/ngx/declarative-ui/table-card/declarative-table-card.component.scss +123 -0
  119. package/projects/ngx/declarative-ui/table-card/declarative-table-card.component.spec.ts +786 -0
  120. package/projects/ngx/declarative-ui/table-card/declarative-table-card.component.ts +286 -0
  121. package/projects/ngx/declarative-ui/table-card/index.ts +2 -0
  122. package/projects/ngx/declarative-ui/table-card/models/configs.ts +46 -0
  123. package/projects/ngx/declarative-ui/tsconfig.lib.json +11 -0
  124. package/projects/ngx/declarative-ui/tsconfig.lib.prod.json +9 -0
  125. package/projects/ngx/declarative-ui/tsconfig.spec.json +9 -0
  126. package/projects/ngx/ng-package.json +8 -0
  127. package/projects/ngx/package.json +22 -0
  128. package/projects/ngx/public-api.ts +2 -0
  129. package/projects/ngx/tsconfig.lib.json +11 -0
  130. package/projects/ngx/tsconfig.lib.prod.json +9 -0
  131. package/projects/webcomponents/main.ts +92 -0
  132. package/projects/webcomponents/tsconfig.app.json +9 -0
  133. package/projects/webcomponents-dashboard/main.ts +15 -0
  134. package/projects/webcomponents-dashboard/tsconfig.app.json +9 -0
  135. package/renovate.json +6 -0
  136. package/scripts/bundle-wc.mjs +79 -0
  137. package/tsconfig.json +37 -0
  138. package/tsconfig.spec.json +8 -0
  139. package/tsconfig.storybook.json +16 -0
  140. package/vitest.config.ts +26 -0
package/README.md ADDED
@@ -0,0 +1,91 @@
1
+ # OpenMFP Web Components Library
2
+
3
+ A modern Angular 21 web components library featuring declarative UI components built with the latest signal-based APIs.
4
+
5
+ ![Build Status](https://github.com/openmfp/webcomponents/actions/workflows/pipeline.yaml/badge.svg)
6
+
7
+ ## ✨ Features
8
+
9
+ - **Angular 21** - Built with the latest Angular features and signal-based APIs
10
+ - **Web Components Ready** - Exportable as native web components via Angular Elements
11
+ - **Declarative UI** - Intuitive generic ui component
12
+ - **Vitest Testing** - Fast, modern testing framework
13
+ - **TypeScript** - Full type safety with strict mode
14
+ - **Tree-Shakeable** - Optimized bundle size with ES modules
15
+
16
+ ## 🚀 Getting Started
17
+
18
+ ### Installation
19
+
20
+ ```bash
21
+ # Install dependencies
22
+ npm install
23
+
24
+ # Build the library
25
+ npm run build
26
+ ```
27
+
28
+ ### Build Commands
29
+
30
+ Run `npm run build` to build the project. The build artifacts will be stored in the `dist/` directory.
31
+
32
+ ```bash
33
+ # Build once
34
+ npm run build
35
+
36
+ # Build in watch mode (for development)
37
+ npm run build:watch
38
+
39
+ # Build and publish to yalc (for local testing)
40
+ npm run build:watch:yalc
41
+ ```
42
+
43
+ ### Testing
44
+
45
+ Run `npm run test` to execute unit tests with Vitest.
46
+
47
+ ```bash
48
+ # Run tests once
49
+ npm test
50
+
51
+ # Run tests in watch mode
52
+ npm run test:watch
53
+
54
+ # Generate coverage report
55
+ npm run test:cov
56
+ ```
57
+
58
+ ### Code Quality
59
+
60
+ ```bash
61
+ # Lint code
62
+ npm run lint
63
+
64
+ # Fix linting issues
65
+ npm run lint:fix
66
+
67
+ # Format code with Prettier
68
+ npm run format
69
+
70
+ # Check code formatting
71
+ npm run check-format
72
+ ```
73
+
74
+ ### Web Components Support
75
+
76
+ Components can be exported as native web components using Angular Elements, making them framework-agnostic.
77
+
78
+ ## Components
79
+
80
+ | Angular tag | Web Component tag | Documentation |
81
+ |---|---|------------------------------------------------------------------|
82
+ | `<mfp-declarative-table>` | `<mfp-wc-declarative-table>` | [docs/declarative-table.md](docs/declarative-table.md) |
83
+ | `<mfp-declarative-form>` | `<mfp-wc-declarative-form>` | [docs/declarative-form.md](docs/declarative-form.md) |
84
+ | `<mfp-declarative-table-card>` | `<mfp-wc-declarative-table-card>` | [docs/declarative-table-card.md](docs/declarative-table-card.md) |
85
+ | `<mfp-dashboard>` | `<mfp-wc-dashboard>` | [docs/dashboard.md](docs/declarative-dashboard.md) |
86
+
87
+ ## NeoNephos Foundation
88
+
89
+ This project is part of the [NeoNephos Foundation](https://neonephos.org), a Linux Foundation Europe initiative.
90
+
91
+ <p align="center"><img alt="Bundesministerium für Wirtschaft und Energie (BMWE)-EU funding logo" src="https://apeirora.eu/assets/img/BMWK-EU.png" width="400"/></p>
package/REUSE.toml ADDED
@@ -0,0 +1,9 @@
1
+ version = 1
2
+ SPDX-PackageName = "webcomponents"
3
+ SPDX-PackageDownloadLocation = "https://github.com/openmfp/webcomponents"
4
+
5
+ [[annotations]]
6
+ path = "**"
7
+ precedence = "aggregate"
8
+ SPDX-FileCopyrightText = "2026 openmfp contributors"
9
+ SPDX-License-Identifier = "Apache-2.0"
package/angular.json ADDED
@@ -0,0 +1,157 @@
1
+ {
2
+ "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3
+ "version": 1,
4
+ "newProjectRoot": "projects",
5
+ "projects": {
6
+ "ngx": {
7
+ "projectType": "library",
8
+ "schematics": {
9
+ "@schematics/angular:component": {
10
+ "style": "scss",
11
+ "path": "projects/ngx"
12
+ }
13
+ },
14
+ "root": "projects/ngx",
15
+ "sourceRoot": "projects/ngx",
16
+ "prefix": "mfp",
17
+ "architect": {
18
+ "build": {
19
+ "builder": "@angular/build:ng-packagr",
20
+ "options": {
21
+ "project": "projects/ngx/ng-package.json"
22
+ },
23
+ "configurations": {
24
+ "production": {
25
+ "tsConfig": "projects/ngx/tsconfig.lib.prod.json"
26
+ },
27
+ "development": {
28
+ "tsConfig": "projects/ngx/tsconfig.lib.json"
29
+ }
30
+ },
31
+ "defaultConfiguration": "production"
32
+ },
33
+ "lint": {
34
+ "builder": "@angular-eslint/builder:lint",
35
+ "options": {
36
+ "lintFilePatterns": [
37
+ "projects/ngx/**/*.ts",
38
+ "projects/ngx/**/*.html"
39
+ ],
40
+ "eslintConfig": "eslint.config.js"
41
+ }
42
+ },
43
+ "test": {
44
+ "builder": "@angular/build:unit-test",
45
+ "options": {
46
+ "runnerConfig": "vitest.config.ts",
47
+ "tsConfig": "./tsconfig.spec.json"
48
+ }
49
+ },
50
+ "storybook": {
51
+ "builder": "@storybook/angular:start-storybook",
52
+ "options": {
53
+ "configDir": ".storybook",
54
+ "browserTarget": "ngx:build",
55
+ "tsConfig": "tsconfig.storybook.json",
56
+ "styles": [
57
+ "node_modules/@sap-theming/theming-base-content/content/Base/baseLib/sap_horizon/css_variables.css",
58
+ "node_modules/fundamental-styles/dist/theming/sap_horizon.css"
59
+ ],
60
+ "port": 6006
61
+ }
62
+ },
63
+ "build-storybook": {
64
+ "builder": "@storybook/angular:build-storybook",
65
+ "options": {
66
+ "configDir": ".storybook",
67
+ "browserTarget": "ngx:build",
68
+ "tsConfig": "tsconfig.storybook.json",
69
+ "styles": [
70
+ "node_modules/@sap-theming/theming-base-content/content/Base/baseLib/sap_horizon/css_variables.css",
71
+ "node_modules/fundamental-styles/dist/theming/sap_horizon.css"
72
+ ],
73
+ "outputDir": "dist/storybook"
74
+ }
75
+ }
76
+ }
77
+ },
78
+ "webcomponents": {
79
+ "projectType": "application",
80
+ "root": "projects/webcomponents",
81
+ "sourceRoot": "projects/webcomponents",
82
+ "architect": {
83
+ "build": {
84
+ "builder": "@angular/build:application",
85
+ "options": {
86
+ "outputPath": {
87
+ "base": "dist/webcomponents",
88
+ "browser": ""
89
+ },
90
+ "browser": "projects/webcomponents/main.ts",
91
+ "tsConfig": "projects/webcomponents/tsconfig.app.json",
92
+ "index": false,
93
+ "outputHashing": "none",
94
+ "inlineStyleLanguage": "scss"
95
+ },
96
+ "configurations": {
97
+ "production": {
98
+ "optimization": true
99
+ },
100
+ "development": {
101
+ "optimization": false,
102
+ "sourceMap": true
103
+ }
104
+ },
105
+ "defaultConfiguration": "production"
106
+ }
107
+ }
108
+ },
109
+ "webcomponents-dashboard": {
110
+ "projectType": "application",
111
+ "root": "projects/webcomponents-dashboard",
112
+ "sourceRoot": "projects/webcomponents-dashboard",
113
+ "architect": {
114
+ "build": {
115
+ "builder": "@angular/build:application",
116
+ "options": {
117
+ "outputPath": {
118
+ "base": "dist/webcomponents-dashboard",
119
+ "browser": ""
120
+ },
121
+ "browser": "projects/webcomponents-dashboard/main.ts",
122
+ "tsConfig": "projects/webcomponents-dashboard/tsconfig.app.json",
123
+ "index": false,
124
+ "outputHashing": "none",
125
+ "inlineStyleLanguage": "scss"
126
+ },
127
+ "configurations": {
128
+ "production": {
129
+ "optimization": true
130
+ },
131
+ "development": {
132
+ "optimization": false,
133
+ "sourceMap": true
134
+ }
135
+ },
136
+ "defaultConfiguration": "production"
137
+ }
138
+ }
139
+ }
140
+ },
141
+ "cli": {
142
+ "analytics": false,
143
+ "schematicCollections": ["angular-eslint"]
144
+ },
145
+ "schematics": {
146
+ "@schematics/angular:component": {
147
+ "type": "component",
148
+ "addTypeToClassName": false
149
+ },
150
+ "@schematics/angular:directive": {
151
+ "type": "directive"
152
+ },
153
+ "@schematics/angular:service": {
154
+ "type": "service"
155
+ }
156
+ }
157
+ }
@@ -0,0 +1,358 @@
1
+ # Dashboard
2
+
3
+ An Angular dashboard layout component that combines editable sections with draggable loose cards. Cards can render either registered Angular components or pre-registered web components through the same `component` field.
4
+
5
+ ## Tags
6
+
7
+ | Usage | Tag |
8
+ | ----------------- | -------------------- |
9
+ | Angular component | `<mfp-dashboard>` |
10
+ | Web component | `<mfp-wc-dashboard>` |
11
+
12
+ ---
13
+
14
+ ## Usage as a web component
15
+
16
+ The dashboard is shipped as a **dedicated standalone bundle** `mfp-wc-dashboard.js`, separate from the main `mfp-webcomponents.js`. Load it independently — it does not depend on the main bundle.
17
+
18
+ ```html
19
+ <script type="module" src="/mfp-wc-dashboard.js"></script>
20
+
21
+ <mfp-wc-dashboard id="dashboard"></mfp-wc-dashboard>
22
+
23
+ <script type="module">
24
+ const el = document.getElementById('dashboard');
25
+ el.config = { title: 'Platform Overview' };
26
+ el.sections = [{ id: 'runtime', title: 'Runtime', w: 12 }];
27
+ el.cards = [
28
+ {
29
+ id: 'pods-card',
30
+ component: 'mfp-wc-declarative-table-card',
31
+ w: 12,
32
+ h: 5,
33
+ componentInputs: { header: 'Pods' },
34
+ },
35
+ ];
36
+ </script>
37
+ ```
38
+
39
+ All inputs (`config`, `sections`, `cards`, `availableCards`) and the `saved` event work the same as the Angular component.
40
+
41
+ ---
42
+
43
+ ## Usage as an Angular component
44
+
45
+ Register Angular card components once before rendering the dashboard. The dashboard reads each Angular component selector and uses that selector string from `CardConfig.component`.
46
+
47
+ ```ts
48
+ import {
49
+ CardConfig,
50
+ Dashboard,
51
+ DashboardConfig,
52
+ SectionConfig,
53
+ VisitedServiceCard,
54
+ } from '@openmfp/webcomponents';
55
+
56
+ Dashboard.registerAngularComponents([VisitedServiceCard]);
57
+
58
+ @Component({
59
+ imports: [Dashboard],
60
+ template: `
61
+ <mfp-dashboard
62
+ [config]="config"
63
+ [sections]="sections"
64
+ [cards]="cards"
65
+ [availableCards]="availableCards"
66
+ (saved)="onSaved($event)"
67
+ />
68
+ `,
69
+ })
70
+ export class DashboardPage {
71
+ config: DashboardConfig = {
72
+ title: 'Platform Overview',
73
+ description: 'Service health and team activity',
74
+ backgroundImageUrl: '/assets/dashboard-bg.png',
75
+ };
76
+
77
+ sections: SectionConfig[] = [
78
+ { id: 'favorites', title: 'Favorites', editable: false },
79
+ { id: 'runtime', title: 'Runtime', w: 12 },
80
+ ];
81
+
82
+ cards: CardConfig[] = [
83
+ {
84
+ id: 'recent-service-card',
85
+ sectionId: 'favorites',
86
+ component: 'mfp-visited-service-card',
87
+ type: 'angular',
88
+ w: 6,
89
+ h: 2,
90
+ componentInputs: {
91
+ serviceType: 'SAP HANA Cloud',
92
+ serviceName: 'orders-db',
93
+ serviceDescription: 'Production / europe',
94
+ serviceIcon: 'database',
95
+ path: '/hana/orders-db',
96
+ },
97
+ },
98
+ {
99
+ id: 'pods-card',
100
+ component: 'mfp-wc-declarative-table-card',
101
+ type: 'wc',
102
+ w: 12,
103
+ h: 5,
104
+ x: 0,
105
+ y: 0,
106
+ componentInputs: {
107
+ header: 'Pods',
108
+ },
109
+ },
110
+ ];
111
+
112
+ availableCards: CardConfig[] = [
113
+ {
114
+ id: 'service-status-template',
115
+ component: 'mfp-wc-service-status-card',
116
+ type: 'wc',
117
+ label: 'Service Status',
118
+ w: 4,
119
+ h: 2,
120
+ },
121
+ ];
122
+
123
+ onSaved(event: { sections: SectionConfig[]; cards: CardConfig[] }) {
124
+ console.log(event.cards);
125
+ }
126
+ }
127
+ ```
128
+
129
+ `componentInputs` behaviour depends on `type`:
130
+
131
+ - For `type: 'angular'`, values are applied with Angular `setInput(...)`.
132
+ - For Angular input aliases, both the class property name and the public alias are accepted.
133
+ - Unknown Angular input names are ignored and logged as a development warning.
134
+ - For `type: 'wc'` (or when `type` is omitted), values are set as DOM properties.
135
+ - For `type: 'sap-ui'`, values are forwarded as `settings` to `ComponentContainer`.
136
+
137
+ Example with an aliased Angular input:
138
+
139
+ ```ts
140
+ @Component({
141
+ selector: 'app-card',
142
+ template: '{{ title() }}',
143
+ })
144
+ export class AppCard {
145
+ title = input('', { alias: 'cardTitle' });
146
+ }
147
+
148
+ Dashboard.registerAngularComponents([AppCard]);
149
+
150
+ const card: CardConfig = {
151
+ id: 'app-card',
152
+ component: 'app-card',
153
+ type: 'angular',
154
+ componentInputs: {
155
+ // Class property name works.
156
+ title: 'Runtime',
157
+ },
158
+ };
159
+
160
+ const sameCardUsingAlias: CardConfig = {
161
+ id: 'app-card-alias',
162
+ component: 'app-card',
163
+ type: 'angular',
164
+ componentInputs: {
165
+ // Public alias works too.
166
+ cardTitle: 'Runtime',
167
+ },
168
+ };
169
+ ```
170
+
171
+ ## Usage with web components
172
+
173
+ Custom elements are still supported. They must be registered in the browser before the dashboard renders them.
174
+
175
+ ```ts
176
+ const cards: CardConfig[] = [
177
+ {
178
+ id: 'pods-card',
179
+ component: 'mfp-wc-declarative-table-card',
180
+ componentInputs: {
181
+ header: 'Pods',
182
+ },
183
+ },
184
+ ];
185
+ ```
186
+
187
+ ---
188
+
189
+ ## API
190
+
191
+ ### Inputs
192
+
193
+ | Input | Type | Required | Default | Description |
194
+ | ---------------- | ----------------- | -------- | ------- | ----------------------------------------------------------- |
195
+ | `config` | `DashboardConfig` | yes | — | Header text and optional background image |
196
+ | `sections` | `SectionConfig[]` | no | `[]` | Named dashboard sections rendered above the loose-card grid |
197
+ | `cards` | `CardConfig[]` | no | `[]` | All cards shown in sections or in the grid |
198
+ | `availableCards` | `CardConfig[]` | no | `[]` | Card templates that can be added in edit mode |
199
+
200
+ ### Outputs
201
+
202
+ | Output | Payload | Description |
203
+ | ------- | ---------------------------------------------------- | ------------------------------- |
204
+ | `saved` | `{ sections: SectionConfig[]; cards: CardConfig[] }` | Emits when the user saves edits |
205
+
206
+ ### Static methods
207
+
208
+ | Method | Description |
209
+ | ----------------------------- | --------------------------------------------------------------------------- |
210
+ | `registerAngularComponents()` | Registers standalone Angular card components by their element selector name |
211
+
212
+ ---
213
+
214
+ ## Configuration types
215
+
216
+ ### `DashboardConfig`
217
+
218
+ ```ts
219
+ interface DashboardConfig {
220
+ title: string;
221
+ description?: string;
222
+ backgroundImageUrl?: string;
223
+ buttonsSettings?: DashboardButtonsSettings;
224
+ customActions?: ButtonSettings[];
225
+ editable?: boolean;
226
+ }
227
+ ```
228
+
229
+ ### `DashboardButtonSettings`
230
+
231
+ Controls the appearance of the two built-in toolbar buttons. Both fields accept a `Partial<ButtonSettings>` that is **merged on top of the defaults** — any property you omit keeps its default value.
232
+
233
+ ```ts
234
+ interface DashboardButtonsSettings {
235
+ editViewButton?: Partial<ButtonSettings>;
236
+ addCardButton?: Partial<ButtonSettings>;
237
+ }
238
+ ```
239
+
240
+ | Button | Default `icon` | Default `design` | Default `tooltip` | Default `text` |
241
+ | ---------------- | ----------------- | ---------------- | ----------------- | --------------------- |
242
+ | `editViewButton` | `action-settings` | `Transparent` | `Edit View` | _(empty — icon only)_ |
243
+ | `addCardButton` | _(none)_ | `Default` | _(none)_ | `+ Add Card` |
244
+
245
+ **Example — text-only buttons without icons:**
246
+
247
+ ```ts
248
+ const config: DashboardConfig = {
249
+ title: 'Platform Overview',
250
+ editable: true,
251
+ buttonsSettings: {
252
+ editViewButton: {
253
+ text: 'Edit View',
254
+ icon: '',
255
+ design: 'Default',
256
+ tooltip: '',
257
+ },
258
+ addCardButton: {
259
+ text: 'Add Card',
260
+ icon: '',
261
+ design: 'Emphasized',
262
+ tooltip: '',
263
+ },
264
+ },
265
+ };
266
+ ```
267
+
268
+ The compact toolbar (viewport width < 726 px) collapses all actions into a burger menu. The Edit View menu item always uses the configured `icon` and falls back to the text `'Edit View'` when no `text` override is set.
269
+
270
+ ### `ButtonSettings`
271
+
272
+ Used both for `customActions` entries and as the override type for `DashboardButtonSettings`.
273
+
274
+ ```ts
275
+ interface ButtonSettings {
276
+ text?: string;
277
+ icon?: string;
278
+ endIcon?: string;
279
+ design?:
280
+ | 'Default'
281
+ | 'Positive'
282
+ | 'Negative'
283
+ | 'Transparent'
284
+ | 'Emphasized'
285
+ | 'Attention';
286
+ tooltip?: string;
287
+ action: 'openInModal' | 'navigate' | 'edit' | 'delete' | string;
288
+ }
289
+ ```
290
+
291
+ ### `SectionConfig`
292
+
293
+ ```ts
294
+ interface SectionConfig {
295
+ id: string;
296
+ w?: number;
297
+ title?: string;
298
+ editable?: boolean;
299
+ }
300
+ ```
301
+
302
+ ### `CardConfig`
303
+
304
+ ```ts
305
+ interface CardConfig {
306
+ id: string;
307
+ w?: number; // expressed in number of columns up to 12
308
+ h?: number; // expressed in hypothetical number of rows, where a row is 10px high, so the value of 27 translates to 270px
309
+ x?: number;
310
+ y?: number;
311
+ maxH?: number;
312
+ maxW?: number;
313
+ minH?: number;
314
+ minW?: number;
315
+ sectionId?: string;
316
+ component: string;
317
+ type?: 'wc' | 'angular' | 'sap-ui';
318
+ componentInputs?: Record<string, unknown>;
319
+ label?: string;
320
+ }
321
+ ```
322
+
323
+ For sections, `w` controls the column span while height is determined by the section content.
324
+ For cards, `w` and `h` control the initial rendered grid span. `x` and `y` persist the loose-card position reported by drag and drop when edit mode is saved. `minH`/`minW` and `maxH`/`maxW` set hard resize bounds enforced by the grid — the user cannot drag a card below the minimum or above the maximum size in edit mode.
325
+
326
+ `component` and `type` work together to determine how the card is rendered:
327
+
328
+ | `type` | Render strategy |
329
+ | ----------- | ---------------------------------------------------------------------- |
330
+ | `'wc'` | Creates a custom element tag; sets `componentInputs` as DOM properties |
331
+ | omitted | Same as `'wc'` |
332
+ | `'angular'` | Looks up the Angular registry; warns and renders nothing if not found |
333
+ | `'sap-ui'` | Mounts via `window.sap.ui.require` + `ComponentContainer` |
334
+
335
+ Angular registry support intentionally accepts only single element selectors such as `mfp-visited-service-card`. Attribute selectors like `[my-card]`, class selectors like `.my-card`, and comma-separated selectors are rejected because dashboard card configs use `component` as a tag-like persisted key.
336
+
337
+ ## Usage with SAP UI5 components
338
+
339
+ Cards with `type: 'sap-ui'` are rendered using the SAP UI5 `ComponentContainer` API. `window.sap.ui.require` must be available on the page (loaded via the SAP UI5 bootstrap script) before the dashboard renders.
340
+
341
+ `component` must be the SAP UI5 component name passed as `name` to `ComponentContainer`. `componentInputs` are forwarded as `settings` to the container constructor.
342
+
343
+ ```ts
344
+ const cards: CardConfig[] = [
345
+ {
346
+ id: 'sap-component-card',
347
+ component: 'my.namespace.Component',
348
+ type: 'sap-ui',
349
+ w: 6,
350
+ h: 20,
351
+ componentInputs: {
352
+ env: 'production',
353
+ },
354
+ },
355
+ ];
356
+ ```
357
+
358
+ If `window.sap` is not available when the card is rendered, an error is logged and the card host element is left empty.