Files
atomic-design-poc/documentation.json
Claude f1f4f982a6 Full-width layout, page-shell template, httpResource async states, README
- Fix full-bleed header/footer (align-items:stretch + block hosts; centered
  content column via shared --app-content-max).
- New templates/page-shell (back-link + heading + intro + content, narrow mode);
  all pages refactored to compose it.
- Async state management with native httpResource + <app-async> wrapper that
  renders exactly one of loading/empty/error/loaded (impossible states
  unrepresentable); delayed spinner + skeleton atoms for slow/fast connections.
- Scenario interceptor (?scenario=slow|loading|empty|error) to demo every state.
- Storybook: spinner/skeleton/page-shell/async-states stories.
- README rewritten as a guide (atomic design, reuse benefits, state handling).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 14:53:28 +02:00

3324 lines
187 KiB
JSON

{
"pipes": [],
"interfaces": [
{
"name": "Aantekening",
"id": "interface-Aantekening-ad224cc8184441fa9923164457d2a4916359232fbcc5bc89a42031573682d3c39f25d7596de394302d8d9e7a7c2157118f79ba2c6dc80ebbf36b836a6d7db8df",
"file": "src/app/core/models.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "interface",
"sourceCode": "export type RegistrationStatus = 'Geregistreerd' | 'Doorgehaald' | 'Geschorst';\n\nexport interface Registration {\n bigNummer: string;\n naam: string;\n beroep: string; // arts, verpleegkundige, apotheker, ...\n status: RegistrationStatus;\n registratiedatum: string; // ISO date\n herregistratieDatum: string;\n geboortedatum: string;\n}\n\nexport interface Aantekening {\n type: string; // specialisme of aantekening\n omschrijving: string;\n datum: string;\n}\n",
"properties": [
{
"name": "datum",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 16
},
{
"name": "omschrijving",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 15
},
{
"name": "type",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 14
}
],
"indexSignatures": [],
"kind": 172,
"methods": [],
"extends": []
},
{
"name": "Registration",
"id": "interface-Registration-ad224cc8184441fa9923164457d2a4916359232fbcc5bc89a42031573682d3c39f25d7596de394302d8d9e7a7c2157118f79ba2c6dc80ebbf36b836a6d7db8df",
"file": "src/app/core/models.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "interface",
"sourceCode": "export type RegistrationStatus = 'Geregistreerd' | 'Doorgehaald' | 'Geschorst';\n\nexport interface Registration {\n bigNummer: string;\n naam: string;\n beroep: string; // arts, verpleegkundige, apotheker, ...\n status: RegistrationStatus;\n registratiedatum: string; // ISO date\n herregistratieDatum: string;\n geboortedatum: string;\n}\n\nexport interface Aantekening {\n type: string; // specialisme of aantekening\n omschrijving: string;\n datum: string;\n}\n",
"properties": [
{
"name": "beroep",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 6
},
{
"name": "bigNummer",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 4
},
{
"name": "geboortedatum",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 10
},
{
"name": "herregistratieDatum",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 9
},
{
"name": "naam",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 5
},
{
"name": "registratiedatum",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 8
},
{
"name": "status",
"deprecated": false,
"deprecationMessage": "",
"type": "RegistrationStatus",
"indexKey": "",
"optional": false,
"description": "",
"line": 7
}
],
"indexSignatures": [],
"kind": 172,
"methods": [],
"extends": []
}
],
"injectables": [
{
"name": "RegistrationService",
"id": "injectable-RegistrationService-03230b1d6b08769d82b6b7d378749dd92ae4e2487883f5e23a741e40a04d5d54b22e38f1301b13de7a23c8d0e57015e3f77dfb741fb51883d9c30d7bdabd0291",
"file": "src/app/core/registration.service.ts",
"properties": [],
"methods": [
{
"name": "aantekeningenResource",
"args": [],
"optional": false,
"returnType": "any",
"typeParameters": [],
"line": 17,
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "registrationResource",
"args": [],
"optional": false,
"returnType": "any",
"typeParameters": [],
"line": 13,
"deprecated": false,
"deprecationMessage": ""
}
],
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Exposes signal-based resources (Angular&#39;s httpResource). Each returns a\nResource with status()/value()/error()/reload() — consumed by <app-async>,\nwhich turns those signals into the loading/empty/error/loaded UI.\nCall these from a component field initializer (injection context required).</p>\n",
"rawdescription": "\n\nExposes signal-based resources (Angular's httpResource). Each returns a\nResource with status()/value()/error()/reload() — consumed by <app-async>,\nwhich turns those signals into the loading/empty/error/loaded UI.\nCall these from a component field initializer (injection context required).\n",
"sourceCode": "import { Injectable } from '@angular/core';\nimport { httpResource } from '@angular/common/http';\nimport { Registration, Aantekening } from './models';\n\n/**\n * Exposes signal-based resources (Angular's httpResource). Each returns a\n * Resource with status()/value()/error()/reload() — consumed by <app-async>,\n * which turns those signals into the loading/empty/error/loaded UI.\n * Call these from a component field initializer (injection context required).\n */\n@Injectable({ providedIn: 'root' })\nexport class RegistrationService {\n registrationResource() {\n return httpResource<Registration>(() => 'mock/registration.json');\n }\n\n aantekeningenResource() {\n return httpResource<Aantekening[]>(() => 'mock/notes.json', { defaultValue: [] });\n }\n}\n",
"extends": [],
"type": "injectable"
}
],
"guards": [],
"interceptors": [],
"classes": [],
"directives": [
{
"name": "AsyncEmptyDirective",
"id": "directive-AsyncEmptyDirective-2f8f54349a396c3f59c90536339a2de5b28ea23c435f301c585563e8dcd7e5652d6b6dee37cd8065a1f9573e0fbbc44511e14a02310dba1fd9d0a8354991e759",
"file": "src/app/molecules/async/async.component.ts",
"type": "directive",
"description": "",
"rawdescription": "\n",
"sourceCode": "import { Component, Directive, TemplateRef, computed, contentChild, input } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport type { Resource } from '@angular/core';\nimport { SpinnerComponent } from '../../atoms/spinner/spinner.component';\nimport { AlertComponent } from '../../atoms/alert/alert.component';\nimport { ButtonComponent } from '../../atoms/button/button.component';\n\n/* Slot markers. Put on <ng-template> children of <app-async>. */\n@Directive({ selector: '[appAsyncLoaded]' })\nexport class AsyncLoadedDirective {\n constructor(public tpl: TemplateRef<{ $implicit: unknown }>) {}\n}\n@Directive({ selector: '[appAsyncLoading]' })\nexport class AsyncLoadingDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncEmpty]' })\nexport class AsyncEmptyDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncError]' })\nexport class AsyncErrorDirective {\n constructor(public tpl: TemplateRef<{ $implicit: Error | undefined; retry: () => void }>) {}\n}\n\ntype State = 'loading' | 'error' | 'empty' | 'loaded';\n\n/**\n * Renders exactly ONE of loading / empty / error / loaded for a signal-based\n * resource (e.g. httpResource). The states are mutually exclusive by\n * construction, so the UI can never show two at once (\"impossible states\").\n * Unprovided slots fall back to sensible defaults.\n */\n@Component({\n selector: 'app-async',\n imports: [NgTemplateOutlet, SpinnerComponent, AlertComponent, ButtonComponent],\n template: `\n @switch (state()) {\n @case ('loading') {\n @if (loadingTpl()) { <ng-container [ngTemplateOutlet]=\"loadingTpl()!.tpl\" /> }\n @else { <app-spinner /> }\n }\n @case ('error') {\n @if (errorTpl()) {\n <ng-container [ngTemplateOutlet]=\"errorTpl()!.tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: resource().error(), retry: retry }\" />\n } @else {\n <app-alert type=\"error\">Er ging iets mis bij het laden van de gegevens.</app-alert>\n <div style=\"margin-top:1rem\">\n <app-button variant=\"secondary\" (click)=\"retry()\">Opnieuw proberen</app-button>\n </div>\n }\n }\n @case ('empty') {\n @if (emptyTpl()) { <ng-container [ngTemplateOutlet]=\"emptyTpl()!.tpl\" /> }\n @else { <p class=\"rhc-paragraph\">Geen gegevens gevonden.</p> }\n }\n @case ('loaded') {\n <ng-container [ngTemplateOutlet]=\"loadedTpl().tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: value() }\" />\n }\n }\n `,\n})\nexport class AsyncComponent<T> {\n resource = input.required<Resource<T>>();\n isEmpty = input<(v: T) => boolean>(() => false);\n\n loadedTpl = contentChild.required(AsyncLoadedDirective);\n loadingTpl = contentChild(AsyncLoadingDirective);\n emptyTpl = contentChild(AsyncEmptyDirective);\n errorTpl = contentChild(AsyncErrorDirective);\n\n protected value = computed(() => {\n const r = this.resource();\n return r.hasValue() ? r.value() : undefined;\n });\n\n protected state = computed<State>(() => {\n const r = this.resource();\n if (r.status() === 'error') return 'error';\n if (r.status() === 'loading') return 'loading';\n if (r.hasValue()) return this.isEmpty()(r.value()) ? 'empty' : 'loaded';\n return 'loading';\n });\n\n retry = () => {\n const r = this.resource();\n if ('reload' in r && typeof (r as { reload?: unknown }).reload === 'function') {\n (r as { reload: () => void }).reload();\n }\n };\n}\n\n/** Convenience: import this array to get the wrapper + all slot directives. */\nexport const ASYNC = [\n AsyncComponent, AsyncLoadedDirective, AsyncLoadingDirective,\n AsyncEmptyDirective, AsyncErrorDirective,\n] as const;\n",
"selector": "[appAsyncEmpty]",
"providers": [],
"hostDirectives": [],
"standalone": false,
"inputsClass": [],
"outputsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"propertiesClass": [
{
"name": "tpl",
"deprecated": false,
"deprecationMessage": "",
"type": "TemplateRef<unknown>",
"indexKey": "",
"optional": false,
"description": "",
"line": 19,
"modifierKind": [
125
]
}
],
"methodsClass": [],
"extends": [],
"constructorObj": {
"name": "constructor",
"description": "",
"deprecated": false,
"deprecationMessage": "",
"args": [
{
"name": "tpl",
"type": "TemplateRef<unknown>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"line": 18,
"jsdoctags": [
{
"name": "tpl",
"type": "TemplateRef<unknown>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
},
{
"name": "AsyncErrorDirective",
"id": "directive-AsyncErrorDirective-2f8f54349a396c3f59c90536339a2de5b28ea23c435f301c585563e8dcd7e5652d6b6dee37cd8065a1f9573e0fbbc44511e14a02310dba1fd9d0a8354991e759",
"file": "src/app/molecules/async/async.component.ts",
"type": "directive",
"description": "",
"rawdescription": "\n",
"sourceCode": "import { Component, Directive, TemplateRef, computed, contentChild, input } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport type { Resource } from '@angular/core';\nimport { SpinnerComponent } from '../../atoms/spinner/spinner.component';\nimport { AlertComponent } from '../../atoms/alert/alert.component';\nimport { ButtonComponent } from '../../atoms/button/button.component';\n\n/* Slot markers. Put on <ng-template> children of <app-async>. */\n@Directive({ selector: '[appAsyncLoaded]' })\nexport class AsyncLoadedDirective {\n constructor(public tpl: TemplateRef<{ $implicit: unknown }>) {}\n}\n@Directive({ selector: '[appAsyncLoading]' })\nexport class AsyncLoadingDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncEmpty]' })\nexport class AsyncEmptyDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncError]' })\nexport class AsyncErrorDirective {\n constructor(public tpl: TemplateRef<{ $implicit: Error | undefined; retry: () => void }>) {}\n}\n\ntype State = 'loading' | 'error' | 'empty' | 'loaded';\n\n/**\n * Renders exactly ONE of loading / empty / error / loaded for a signal-based\n * resource (e.g. httpResource). The states are mutually exclusive by\n * construction, so the UI can never show two at once (\"impossible states\").\n * Unprovided slots fall back to sensible defaults.\n */\n@Component({\n selector: 'app-async',\n imports: [NgTemplateOutlet, SpinnerComponent, AlertComponent, ButtonComponent],\n template: `\n @switch (state()) {\n @case ('loading') {\n @if (loadingTpl()) { <ng-container [ngTemplateOutlet]=\"loadingTpl()!.tpl\" /> }\n @else { <app-spinner /> }\n }\n @case ('error') {\n @if (errorTpl()) {\n <ng-container [ngTemplateOutlet]=\"errorTpl()!.tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: resource().error(), retry: retry }\" />\n } @else {\n <app-alert type=\"error\">Er ging iets mis bij het laden van de gegevens.</app-alert>\n <div style=\"margin-top:1rem\">\n <app-button variant=\"secondary\" (click)=\"retry()\">Opnieuw proberen</app-button>\n </div>\n }\n }\n @case ('empty') {\n @if (emptyTpl()) { <ng-container [ngTemplateOutlet]=\"emptyTpl()!.tpl\" /> }\n @else { <p class=\"rhc-paragraph\">Geen gegevens gevonden.</p> }\n }\n @case ('loaded') {\n <ng-container [ngTemplateOutlet]=\"loadedTpl().tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: value() }\" />\n }\n }\n `,\n})\nexport class AsyncComponent<T> {\n resource = input.required<Resource<T>>();\n isEmpty = input<(v: T) => boolean>(() => false);\n\n loadedTpl = contentChild.required(AsyncLoadedDirective);\n loadingTpl = contentChild(AsyncLoadingDirective);\n emptyTpl = contentChild(AsyncEmptyDirective);\n errorTpl = contentChild(AsyncErrorDirective);\n\n protected value = computed(() => {\n const r = this.resource();\n return r.hasValue() ? r.value() : undefined;\n });\n\n protected state = computed<State>(() => {\n const r = this.resource();\n if (r.status() === 'error') return 'error';\n if (r.status() === 'loading') return 'loading';\n if (r.hasValue()) return this.isEmpty()(r.value()) ? 'empty' : 'loaded';\n return 'loading';\n });\n\n retry = () => {\n const r = this.resource();\n if ('reload' in r && typeof (r as { reload?: unknown }).reload === 'function') {\n (r as { reload: () => void }).reload();\n }\n };\n}\n\n/** Convenience: import this array to get the wrapper + all slot directives. */\nexport const ASYNC = [\n AsyncComponent, AsyncLoadedDirective, AsyncLoadingDirective,\n AsyncEmptyDirective, AsyncErrorDirective,\n] as const;\n",
"selector": "[appAsyncError]",
"providers": [],
"hostDirectives": [],
"standalone": false,
"inputsClass": [],
"outputsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"propertiesClass": [
{
"name": "tpl",
"deprecated": false,
"deprecationMessage": "",
"type": "TemplateRef<literal type>",
"indexKey": "",
"optional": false,
"description": "",
"line": 23,
"modifierKind": [
125
]
}
],
"methodsClass": [],
"extends": [],
"constructorObj": {
"name": "constructor",
"description": "",
"deprecated": false,
"deprecationMessage": "",
"args": [
{
"name": "tpl",
"type": "TemplateRef<literal type>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"line": 22,
"jsdoctags": [
{
"name": "tpl",
"type": "TemplateRef<literal type>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
},
{
"name": "AsyncLoadedDirective",
"id": "directive-AsyncLoadedDirective-2f8f54349a396c3f59c90536339a2de5b28ea23c435f301c585563e8dcd7e5652d6b6dee37cd8065a1f9573e0fbbc44511e14a02310dba1fd9d0a8354991e759",
"file": "src/app/molecules/async/async.component.ts",
"type": "directive",
"description": "",
"rawdescription": "\n",
"sourceCode": "import { Component, Directive, TemplateRef, computed, contentChild, input } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport type { Resource } from '@angular/core';\nimport { SpinnerComponent } from '../../atoms/spinner/spinner.component';\nimport { AlertComponent } from '../../atoms/alert/alert.component';\nimport { ButtonComponent } from '../../atoms/button/button.component';\n\n/* Slot markers. Put on <ng-template> children of <app-async>. */\n@Directive({ selector: '[appAsyncLoaded]' })\nexport class AsyncLoadedDirective {\n constructor(public tpl: TemplateRef<{ $implicit: unknown }>) {}\n}\n@Directive({ selector: '[appAsyncLoading]' })\nexport class AsyncLoadingDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncEmpty]' })\nexport class AsyncEmptyDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncError]' })\nexport class AsyncErrorDirective {\n constructor(public tpl: TemplateRef<{ $implicit: Error | undefined; retry: () => void }>) {}\n}\n\ntype State = 'loading' | 'error' | 'empty' | 'loaded';\n\n/**\n * Renders exactly ONE of loading / empty / error / loaded for a signal-based\n * resource (e.g. httpResource). The states are mutually exclusive by\n * construction, so the UI can never show two at once (\"impossible states\").\n * Unprovided slots fall back to sensible defaults.\n */\n@Component({\n selector: 'app-async',\n imports: [NgTemplateOutlet, SpinnerComponent, AlertComponent, ButtonComponent],\n template: `\n @switch (state()) {\n @case ('loading') {\n @if (loadingTpl()) { <ng-container [ngTemplateOutlet]=\"loadingTpl()!.tpl\" /> }\n @else { <app-spinner /> }\n }\n @case ('error') {\n @if (errorTpl()) {\n <ng-container [ngTemplateOutlet]=\"errorTpl()!.tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: resource().error(), retry: retry }\" />\n } @else {\n <app-alert type=\"error\">Er ging iets mis bij het laden van de gegevens.</app-alert>\n <div style=\"margin-top:1rem\">\n <app-button variant=\"secondary\" (click)=\"retry()\">Opnieuw proberen</app-button>\n </div>\n }\n }\n @case ('empty') {\n @if (emptyTpl()) { <ng-container [ngTemplateOutlet]=\"emptyTpl()!.tpl\" /> }\n @else { <p class=\"rhc-paragraph\">Geen gegevens gevonden.</p> }\n }\n @case ('loaded') {\n <ng-container [ngTemplateOutlet]=\"loadedTpl().tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: value() }\" />\n }\n }\n `,\n})\nexport class AsyncComponent<T> {\n resource = input.required<Resource<T>>();\n isEmpty = input<(v: T) => boolean>(() => false);\n\n loadedTpl = contentChild.required(AsyncLoadedDirective);\n loadingTpl = contentChild(AsyncLoadingDirective);\n emptyTpl = contentChild(AsyncEmptyDirective);\n errorTpl = contentChild(AsyncErrorDirective);\n\n protected value = computed(() => {\n const r = this.resource();\n return r.hasValue() ? r.value() : undefined;\n });\n\n protected state = computed<State>(() => {\n const r = this.resource();\n if (r.status() === 'error') return 'error';\n if (r.status() === 'loading') return 'loading';\n if (r.hasValue()) return this.isEmpty()(r.value()) ? 'empty' : 'loaded';\n return 'loading';\n });\n\n retry = () => {\n const r = this.resource();\n if ('reload' in r && typeof (r as { reload?: unknown }).reload === 'function') {\n (r as { reload: () => void }).reload();\n }\n };\n}\n\n/** Convenience: import this array to get the wrapper + all slot directives. */\nexport const ASYNC = [\n AsyncComponent, AsyncLoadedDirective, AsyncLoadingDirective,\n AsyncEmptyDirective, AsyncErrorDirective,\n] as const;\n",
"selector": "[appAsyncLoaded]",
"providers": [],
"hostDirectives": [],
"standalone": false,
"inputsClass": [],
"outputsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"propertiesClass": [
{
"name": "tpl",
"deprecated": false,
"deprecationMessage": "",
"type": "TemplateRef<literal type>",
"indexKey": "",
"optional": false,
"description": "",
"line": 11,
"modifierKind": [
125
]
}
],
"methodsClass": [],
"extends": [],
"constructorObj": {
"name": "constructor",
"description": "",
"deprecated": false,
"deprecationMessage": "",
"args": [
{
"name": "tpl",
"type": "TemplateRef<literal type>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"line": 10,
"jsdoctags": [
{
"name": "tpl",
"type": "TemplateRef<literal type>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
},
{
"name": "AsyncLoadingDirective",
"id": "directive-AsyncLoadingDirective-2f8f54349a396c3f59c90536339a2de5b28ea23c435f301c585563e8dcd7e5652d6b6dee37cd8065a1f9573e0fbbc44511e14a02310dba1fd9d0a8354991e759",
"file": "src/app/molecules/async/async.component.ts",
"type": "directive",
"description": "",
"rawdescription": "\n",
"sourceCode": "import { Component, Directive, TemplateRef, computed, contentChild, input } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport type { Resource } from '@angular/core';\nimport { SpinnerComponent } from '../../atoms/spinner/spinner.component';\nimport { AlertComponent } from '../../atoms/alert/alert.component';\nimport { ButtonComponent } from '../../atoms/button/button.component';\n\n/* Slot markers. Put on <ng-template> children of <app-async>. */\n@Directive({ selector: '[appAsyncLoaded]' })\nexport class AsyncLoadedDirective {\n constructor(public tpl: TemplateRef<{ $implicit: unknown }>) {}\n}\n@Directive({ selector: '[appAsyncLoading]' })\nexport class AsyncLoadingDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncEmpty]' })\nexport class AsyncEmptyDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncError]' })\nexport class AsyncErrorDirective {\n constructor(public tpl: TemplateRef<{ $implicit: Error | undefined; retry: () => void }>) {}\n}\n\ntype State = 'loading' | 'error' | 'empty' | 'loaded';\n\n/**\n * Renders exactly ONE of loading / empty / error / loaded for a signal-based\n * resource (e.g. httpResource). The states are mutually exclusive by\n * construction, so the UI can never show two at once (\"impossible states\").\n * Unprovided slots fall back to sensible defaults.\n */\n@Component({\n selector: 'app-async',\n imports: [NgTemplateOutlet, SpinnerComponent, AlertComponent, ButtonComponent],\n template: `\n @switch (state()) {\n @case ('loading') {\n @if (loadingTpl()) { <ng-container [ngTemplateOutlet]=\"loadingTpl()!.tpl\" /> }\n @else { <app-spinner /> }\n }\n @case ('error') {\n @if (errorTpl()) {\n <ng-container [ngTemplateOutlet]=\"errorTpl()!.tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: resource().error(), retry: retry }\" />\n } @else {\n <app-alert type=\"error\">Er ging iets mis bij het laden van de gegevens.</app-alert>\n <div style=\"margin-top:1rem\">\n <app-button variant=\"secondary\" (click)=\"retry()\">Opnieuw proberen</app-button>\n </div>\n }\n }\n @case ('empty') {\n @if (emptyTpl()) { <ng-container [ngTemplateOutlet]=\"emptyTpl()!.tpl\" /> }\n @else { <p class=\"rhc-paragraph\">Geen gegevens gevonden.</p> }\n }\n @case ('loaded') {\n <ng-container [ngTemplateOutlet]=\"loadedTpl().tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: value() }\" />\n }\n }\n `,\n})\nexport class AsyncComponent<T> {\n resource = input.required<Resource<T>>();\n isEmpty = input<(v: T) => boolean>(() => false);\n\n loadedTpl = contentChild.required(AsyncLoadedDirective);\n loadingTpl = contentChild(AsyncLoadingDirective);\n emptyTpl = contentChild(AsyncEmptyDirective);\n errorTpl = contentChild(AsyncErrorDirective);\n\n protected value = computed(() => {\n const r = this.resource();\n return r.hasValue() ? r.value() : undefined;\n });\n\n protected state = computed<State>(() => {\n const r = this.resource();\n if (r.status() === 'error') return 'error';\n if (r.status() === 'loading') return 'loading';\n if (r.hasValue()) return this.isEmpty()(r.value()) ? 'empty' : 'loaded';\n return 'loading';\n });\n\n retry = () => {\n const r = this.resource();\n if ('reload' in r && typeof (r as { reload?: unknown }).reload === 'function') {\n (r as { reload: () => void }).reload();\n }\n };\n}\n\n/** Convenience: import this array to get the wrapper + all slot directives. */\nexport const ASYNC = [\n AsyncComponent, AsyncLoadedDirective, AsyncLoadingDirective,\n AsyncEmptyDirective, AsyncErrorDirective,\n] as const;\n",
"selector": "[appAsyncLoading]",
"providers": [],
"hostDirectives": [],
"standalone": false,
"inputsClass": [],
"outputsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"propertiesClass": [
{
"name": "tpl",
"deprecated": false,
"deprecationMessage": "",
"type": "TemplateRef<unknown>",
"indexKey": "",
"optional": false,
"description": "",
"line": 15,
"modifierKind": [
125
]
}
],
"methodsClass": [],
"extends": [],
"constructorObj": {
"name": "constructor",
"description": "",
"deprecated": false,
"deprecationMessage": "",
"args": [
{
"name": "tpl",
"type": "TemplateRef<unknown>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"line": 14,
"jsdoctags": [
{
"name": "tpl",
"type": "TemplateRef<unknown>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
}
],
"components": [
{
"name": "AlertComponent",
"id": "component-AlertComponent-7d03ee2c0179c2f8d44795112c823951406810027571b5471bc765873f1aeaee550dcb89c6ebd8514ee36f2d96c8c6ba118293bf44a4a1316f61e91fa3c06f4e",
"file": "src/app/atoms/alert/alert.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-alert",
"styleUrls": [],
"styles": [],
"template": "<div\n class=\"utrecht-alert rhc-alert\"\n [class.utrecht-alert--info]=\"type() === 'info'\"\n [class.utrecht-alert--ok]=\"type() === 'ok'\"\n [class.utrecht-alert--warning]=\"type() === 'warning'\"\n [class.utrecht-alert--error]=\"type() === 'error'\"\n role=\"status\">\n <ng-content />\n</div>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "type",
"defaultValue": "'info'",
"deprecated": false,
"deprecationMessage": "",
"type": "AlertType",
"indexKey": "",
"optional": false,
"description": "",
"line": 21,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>Atom: alert/message banner.</p>\n",
"rawdescription": "\nAtom: alert/message banner.",
"type": "component",
"sourceCode": "import { Component, input } from '@angular/core';\n\ntype AlertType = 'info' | 'ok' | 'warning' | 'error';\n\n/** Atom: alert/message banner. */\n@Component({\n selector: 'app-alert',\n template: `\n <div\n class=\"utrecht-alert rhc-alert\"\n [class.utrecht-alert--info]=\"type() === 'info'\"\n [class.utrecht-alert--ok]=\"type() === 'ok'\"\n [class.utrecht-alert--warning]=\"type() === 'warning'\"\n [class.utrecht-alert--error]=\"type() === 'error'\"\n role=\"status\">\n <ng-content />\n </div>\n `,\n})\nexport class AlertComponent {\n type = input<AlertType>('info');\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "App",
"id": "component-App-a5889755e6aaa6ebd2f471f1253c27e411d38a42361e18619621ef0e6c5a91de3cf6ba4ace13bbe1756691f1f5e80728717fd18aab2cef50180bd579fa218a6d",
"file": "src/app/app.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-root",
"styleUrls": [],
"styles": [],
"template": "<router-outlet />",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "RouterOutlet"
}
],
"description": "",
"rawdescription": "\n",
"type": "component",
"sourceCode": "import { Component } from '@angular/core';\nimport { RouterOutlet } from '@angular/router';\n\n@Component({\n selector: 'app-root',\n imports: [RouterOutlet],\n template: '<router-outlet />',\n})\nexport class App {}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "AsyncComponent",
"id": "component-AsyncComponent-2f8f54349a396c3f59c90536339a2de5b28ea23c435f301c585563e8dcd7e5652d6b6dee37cd8065a1f9573e0fbbc44511e14a02310dba1fd9d0a8354991e759",
"file": "src/app/molecules/async/async.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-async",
"styleUrls": [],
"styles": [],
"template": "@switch (state()) {\n @case ('loading') {\n @if (loadingTpl()) { <ng-container [ngTemplateOutlet]=\"loadingTpl()!.tpl\" /> }\n @else { <app-spinner /> }\n }\n @case ('error') {\n @if (errorTpl()) {\n <ng-container [ngTemplateOutlet]=\"errorTpl()!.tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: resource().error(), retry: retry }\" />\n } @else {\n <app-alert type=\"error\">Er ging iets mis bij het laden van de gegevens.</app-alert>\n <div style=\"margin-top:1rem\">\n <app-button variant=\"secondary\" (click)=\"retry()\">Opnieuw proberen</app-button>\n </div>\n }\n }\n @case ('empty') {\n @if (emptyTpl()) { <ng-container [ngTemplateOutlet]=\"emptyTpl()!.tpl\" /> }\n @else { <p class=\"rhc-paragraph\">Geen gegevens gevonden.</p> }\n }\n @case ('loaded') {\n <ng-container [ngTemplateOutlet]=\"loadedTpl().tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: value() }\" />\n }\n}\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "isEmpty",
"defaultValue": "() => false",
"deprecated": false,
"deprecationMessage": "",
"type": "(v: T) => boolean",
"indexKey": "",
"optional": false,
"description": "",
"line": 67,
"required": false
},
{
"name": "resource",
"deprecated": false,
"deprecationMessage": "",
"type": "Resource<T>",
"indexKey": "",
"optional": false,
"description": "",
"line": 66,
"required": true
}
],
"outputsClass": [],
"propertiesClass": [
{
"name": "emptyTpl",
"defaultValue": "contentChild(AsyncEmptyDirective)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 71
},
{
"name": "errorTpl",
"defaultValue": "contentChild(AsyncErrorDirective)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 72
},
{
"name": "loadedTpl",
"defaultValue": "contentChild.required(AsyncLoadedDirective)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 69
},
{
"name": "loadingTpl",
"defaultValue": "contentChild(AsyncLoadingDirective)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 70
},
{
"name": "retry",
"defaultValue": "() => {...}",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 87
},
{
"name": "state",
"defaultValue": "computed<State>(() => {\n const r = this.resource();\n if (r.status() === 'error') return 'error';\n if (r.status() === 'loading') return 'loading';\n if (r.hasValue()) return this.isEmpty()(r.value()) ? 'empty' : 'loaded';\n return 'loading';\n })",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 79,
"modifierKind": [
124
]
},
{
"name": "value",
"defaultValue": "computed(() => {\n const r = this.resource();\n return r.hasValue() ? r.value() : undefined;\n })",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 74,
"modifierKind": [
124
]
}
],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "NgTemplateOutlet"
},
{
"name": "SpinnerComponent",
"type": "component"
},
{
"name": "AlertComponent",
"type": "component"
},
{
"name": "ButtonComponent",
"type": "component"
}
],
"description": "<p>Renders exactly ONE of loading / empty / error / loaded for a signal-based\nresource (e.g. httpResource). The states are mutually exclusive by\nconstruction, so the UI can never show two at once (&quot;impossible states&quot;).\nUnprovided slots fall back to sensible defaults.</p>\n",
"rawdescription": "\n\nRenders exactly ONE of loading / empty / error / loaded for a signal-based\nresource (e.g. httpResource). The states are mutually exclusive by\nconstruction, so the UI can never show two at once (\"impossible states\").\nUnprovided slots fall back to sensible defaults.\n",
"type": "component",
"sourceCode": "import { Component, Directive, TemplateRef, computed, contentChild, input } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\nimport type { Resource } from '@angular/core';\nimport { SpinnerComponent } from '../../atoms/spinner/spinner.component';\nimport { AlertComponent } from '../../atoms/alert/alert.component';\nimport { ButtonComponent } from '../../atoms/button/button.component';\n\n/* Slot markers. Put on <ng-template> children of <app-async>. */\n@Directive({ selector: '[appAsyncLoaded]' })\nexport class AsyncLoadedDirective {\n constructor(public tpl: TemplateRef<{ $implicit: unknown }>) {}\n}\n@Directive({ selector: '[appAsyncLoading]' })\nexport class AsyncLoadingDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncEmpty]' })\nexport class AsyncEmptyDirective {\n constructor(public tpl: TemplateRef<unknown>) {}\n}\n@Directive({ selector: '[appAsyncError]' })\nexport class AsyncErrorDirective {\n constructor(public tpl: TemplateRef<{ $implicit: Error | undefined; retry: () => void }>) {}\n}\n\ntype State = 'loading' | 'error' | 'empty' | 'loaded';\n\n/**\n * Renders exactly ONE of loading / empty / error / loaded for a signal-based\n * resource (e.g. httpResource). The states are mutually exclusive by\n * construction, so the UI can never show two at once (\"impossible states\").\n * Unprovided slots fall back to sensible defaults.\n */\n@Component({\n selector: 'app-async',\n imports: [NgTemplateOutlet, SpinnerComponent, AlertComponent, ButtonComponent],\n template: `\n @switch (state()) {\n @case ('loading') {\n @if (loadingTpl()) { <ng-container [ngTemplateOutlet]=\"loadingTpl()!.tpl\" /> }\n @else { <app-spinner /> }\n }\n @case ('error') {\n @if (errorTpl()) {\n <ng-container [ngTemplateOutlet]=\"errorTpl()!.tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: resource().error(), retry: retry }\" />\n } @else {\n <app-alert type=\"error\">Er ging iets mis bij het laden van de gegevens.</app-alert>\n <div style=\"margin-top:1rem\">\n <app-button variant=\"secondary\" (click)=\"retry()\">Opnieuw proberen</app-button>\n </div>\n }\n }\n @case ('empty') {\n @if (emptyTpl()) { <ng-container [ngTemplateOutlet]=\"emptyTpl()!.tpl\" /> }\n @else { <p class=\"rhc-paragraph\">Geen gegevens gevonden.</p> }\n }\n @case ('loaded') {\n <ng-container [ngTemplateOutlet]=\"loadedTpl().tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: value() }\" />\n }\n }\n `,\n})\nexport class AsyncComponent<T> {\n resource = input.required<Resource<T>>();\n isEmpty = input<(v: T) => boolean>(() => false);\n\n loadedTpl = contentChild.required(AsyncLoadedDirective);\n loadingTpl = contentChild(AsyncLoadingDirective);\n emptyTpl = contentChild(AsyncEmptyDirective);\n errorTpl = contentChild(AsyncErrorDirective);\n\n protected value = computed(() => {\n const r = this.resource();\n return r.hasValue() ? r.value() : undefined;\n });\n\n protected state = computed<State>(() => {\n const r = this.resource();\n if (r.status() === 'error') return 'error';\n if (r.status() === 'loading') return 'loading';\n if (r.hasValue()) return this.isEmpty()(r.value()) ? 'empty' : 'loaded';\n return 'loading';\n });\n\n retry = () => {\n const r = this.resource();\n if ('reload' in r && typeof (r as { reload?: unknown }).reload === 'function') {\n (r as { reload: () => void }).reload();\n }\n };\n}\n\n/** Convenience: import this array to get the wrapper + all slot directives. */\nexport const ASYNC = [\n AsyncComponent, AsyncLoadedDirective, AsyncLoadingDirective,\n AsyncEmptyDirective, AsyncErrorDirective,\n] as const;\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "ButtonComponent",
"id": "component-ButtonComponent-6eb936521438d91cc3a2276d1b8e366496e907e8a01d7b84b327c3cc31fa1dfadbb9502c6646472736722cf7ced9950fcaa4d8435ddf28224b3e7c9b7bd29505",
"file": "src/app/atoms/button/button.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-button",
"styleUrls": [],
"styles": [],
"template": "<button\n [type]=\"type()\"\n [disabled]=\"disabled()\"\n class=\"utrecht-button rhc-button\"\n [class.utrecht-button--primary-action]=\"variant() === 'primary'\"\n [class.utrecht-button--secondary-action]=\"variant() === 'secondary'\"\n [class.utrecht-button--subtle]=\"variant() === 'subtle'\"\n [class.utrecht-button--danger]=\"variant() === 'danger'\"\n [class.utrecht-button--disabled]=\"disabled()\">\n <ng-content />\n</button>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "disabled",
"defaultValue": "false",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 25,
"required": false
},
{
"name": "type",
"defaultValue": "'button'",
"deprecated": false,
"deprecationMessage": "",
"type": "\"button\" | \"submit\"",
"indexKey": "",
"optional": false,
"description": "",
"line": 24,
"required": false
},
{
"name": "variant",
"defaultValue": "'primary'",
"deprecated": false,
"deprecationMessage": "",
"type": "Variant",
"indexKey": "",
"optional": false,
"description": "",
"line": 23,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>Atom: button. Thin wrapper over the Utrecht/RHC button CSS.</p>\n",
"rawdescription": "\nAtom: button. Thin wrapper over the Utrecht/RHC button CSS.",
"type": "component",
"sourceCode": "import { Component, input } from '@angular/core';\n\ntype Variant = 'primary' | 'secondary' | 'subtle' | 'danger';\n\n/** Atom: button. Thin wrapper over the Utrecht/RHC button CSS. */\n@Component({\n selector: 'app-button',\n template: `\n <button\n [type]=\"type()\"\n [disabled]=\"disabled()\"\n class=\"utrecht-button rhc-button\"\n [class.utrecht-button--primary-action]=\"variant() === 'primary'\"\n [class.utrecht-button--secondary-action]=\"variant() === 'secondary'\"\n [class.utrecht-button--subtle]=\"variant() === 'subtle'\"\n [class.utrecht-button--danger]=\"variant() === 'danger'\"\n [class.utrecht-button--disabled]=\"disabled()\">\n <ng-content />\n </button>\n `,\n})\nexport class ButtonComponent {\n variant = input<Variant>('primary');\n type = input<'button' | 'submit'>('button');\n disabled = input(false);\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "ChangeRequestFormComponent",
"id": "component-ChangeRequestFormComponent-81277b5d39f6d8389da0d8313e3b14f50df8058e30513eca8776b01c490aed300ca483ab7ea00363d41e0a98360a792cc030698f4bf3918e14719ce4b08f64fa",
"file": "src/app/organisms/change-request-form/change-request-form.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-change-request-form",
"styleUrls": [],
"styles": [],
"template": "<app-heading [level]=\"2\">Adreswijziging doorgeven</app-heading>\n<form (ngSubmit)=\"onSubmit()\" style=\"max-width:28rem\">\n <app-form-field label=\"Straat en huisnummer\" fieldId=\"street\" [error]=\"streetError()\">\n <app-text-input inputId=\"street\" [(ngModel)]=\"street\" name=\"street\" [invalid]=\"!!streetError()\" />\n </app-form-field>\n <app-form-field label=\"Postcode\" fieldId=\"zip\">\n <app-text-input inputId=\"zip\" [(ngModel)]=\"zip\" name=\"zip\" placeholder=\"1234 AB\" />\n </app-form-field>\n <app-form-field label=\"Woonplaats\" fieldId=\"city\">\n <app-text-input inputId=\"city\" [(ngModel)]=\"city\" name=\"city\" />\n </app-form-field>\n <div style=\"margin-top:1rem\">\n <app-button type=\"submit\" variant=\"primary\">Wijziging indienen</app-button>\n </div>\n</form>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [
{
"name": "submitted",
"deprecated": false,
"deprecationMessage": "",
"type": "void",
"indexKey": "",
"optional": false,
"description": "",
"line": 36,
"required": false
}
],
"propertiesClass": [
{
"name": "city",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 34
},
{
"name": "street",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 32
},
{
"name": "streetError",
"defaultValue": "signal('')",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 35
},
{
"name": "zip",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 33
}
],
"methodsClass": [
{
"name": "onSubmit",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 38,
"deprecated": false,
"deprecationMessage": ""
}
],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "FormsModule",
"type": "module"
},
{
"name": "FormFieldComponent",
"type": "component"
},
{
"name": "TextInputComponent",
"type": "component"
},
{
"name": "ButtonComponent",
"type": "component"
},
{
"name": "HeadingComponent",
"type": "component"
}
],
"description": "<p>Organism: change-request (adreswijziging) form. Reuses the same form-field\nmolecule + text-input/button atoms as the login form.</p>\n",
"rawdescription": "\nOrganism: change-request (adreswijziging) form. Reuses the same form-field\nmolecule + text-input/button atoms as the login form.",
"type": "component",
"sourceCode": "import { Component, output, signal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FormFieldComponent } from '../../molecules/form-field/form-field.component';\nimport { TextInputComponent } from '../../atoms/text-input/text-input.component';\nimport { ButtonComponent } from '../../atoms/button/button.component';\nimport { HeadingComponent } from '../../atoms/heading/heading.component';\n\n/** Organism: change-request (adreswijziging) form. Reuses the same form-field\n molecule + text-input/button atoms as the login form. */\n@Component({\n selector: 'app-change-request-form',\n imports: [FormsModule, FormFieldComponent, TextInputComponent, ButtonComponent, HeadingComponent],\n template: `\n <app-heading [level]=\"2\">Adreswijziging doorgeven</app-heading>\n <form (ngSubmit)=\"onSubmit()\" style=\"max-width:28rem\">\n <app-form-field label=\"Straat en huisnummer\" fieldId=\"street\" [error]=\"streetError()\">\n <app-text-input inputId=\"street\" [(ngModel)]=\"street\" name=\"street\" [invalid]=\"!!streetError()\" />\n </app-form-field>\n <app-form-field label=\"Postcode\" fieldId=\"zip\">\n <app-text-input inputId=\"zip\" [(ngModel)]=\"zip\" name=\"zip\" placeholder=\"1234 AB\" />\n </app-form-field>\n <app-form-field label=\"Woonplaats\" fieldId=\"city\">\n <app-text-input inputId=\"city\" [(ngModel)]=\"city\" name=\"city\" />\n </app-form-field>\n <div style=\"margin-top:1rem\">\n <app-button type=\"submit\" variant=\"primary\">Wijziging indienen</app-button>\n </div>\n </form>\n `,\n})\nexport class ChangeRequestFormComponent {\n street = '';\n zip = '';\n city = '';\n streetError = signal('');\n submitted = output<void>();\n\n onSubmit() {\n if (!this.street.trim()) { this.streetError.set('Vul straat en huisnummer in.'); return; }\n this.streetError.set('');\n this.submitted.emit();\n }\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "DashboardPage",
"id": "component-DashboardPage-36586da5e82d0e8ebdd85752f770845da4b3cc25f67a64c1fbaa2fdc227f11a3686aa7e85d20ba00f27796d75849db0f6e52fc10e1f2c59c8dd10c6c940c6c91",
"file": "src/app/pages/dashboard/dashboard.page.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-dashboard-page",
"styleUrls": [],
"styles": [],
"template": "<app-page-shell heading=\"Mijn BIG-registratie\">\n <!-- Summary: loading -> skeleton, error -> retry, else the card -->\n <app-async [resource]=\"reg\" [isEmpty]=\"regEmpty\">\n <ng-template appAsyncLoaded let-r>\n <app-registration-summary [reg]=\"$any(r)\" />\n </ng-template>\n <ng-template appAsyncLoading>\n <app-skeleton height=\"2.5rem\" [count]=\"6\" />\n </ng-template>\n </app-async>\n\n <div style=\"margin-top:2rem\">\n <app-heading [level]=\"2\">Specialismen en aantekeningen</app-heading>\n <app-async [resource]=\"notes\" [isEmpty]=\"notesEmpty\">\n <ng-template appAsyncLoaded let-r>\n <app-registration-table [rows]=\"$any(r)\" />\n </ng-template>\n <ng-template appAsyncLoading>\n <app-skeleton height=\"2.5rem\" [count]=\"3\" />\n </ng-template>\n <ng-template appAsyncEmpty>\n <p class=\"rhc-paragraph\">U heeft nog geen specialismen of aantekeningen.</p>\n </ng-template>\n </app-async>\n </div>\n\n <p style=\"margin-top:2rem\">\n <app-link to=\"/registratie\">Gegevens bekijken of een wijziging doorgeven →</app-link>\n </p>\n <p>\n <app-link to=\"/herregistratie\">Herregistratie aanvragen →</app-link>\n </p>\n</app-page-shell>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [],
"propertiesClass": [
{
"name": "notes",
"defaultValue": "this.svc.aantekeningenResource()",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 57
},
{
"name": "notesEmpty",
"defaultValue": "() => {...}",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 58
},
{
"name": "reg",
"defaultValue": "this.svc.registrationResource()",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 56
},
{
"name": "regEmpty",
"defaultValue": "() => {...}",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 59
},
{
"name": "svc",
"defaultValue": "inject(RegistrationService)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 55,
"modifierKind": [
123
]
}
],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "PageShellComponent",
"type": "component"
},
{
"name": "HeadingComponent",
"type": "component"
},
{
"name": "LinkComponent",
"type": "component"
},
{
"name": "SkeletonComponent",
"type": "component"
},
{
"name": "ASYNC"
},
{
"name": "RegistrationSummaryComponent",
"type": "component"
},
{
"name": "RegistrationTableComponent",
"type": "component"
}
],
"description": "",
"rawdescription": "\n",
"type": "component",
"sourceCode": "import { Component, inject } from '@angular/core';\nimport { PageShellComponent } from '../../templates/page-shell/page-shell.component';\nimport { HeadingComponent } from '../../atoms/heading/heading.component';\nimport { LinkComponent } from '../../atoms/link/link.component';\nimport { SkeletonComponent } from '../../atoms/skeleton/skeleton.component';\nimport { ASYNC } from '../../molecules/async/async.component';\nimport { RegistrationSummaryComponent } from '../../organisms/registration-summary/registration-summary.component';\nimport { RegistrationTableComponent } from '../../organisms/registration-table/registration-table.component';\nimport { RegistrationService } from '../../core/registration.service';\nimport { Aantekening } from '../../core/models';\n\n@Component({\n selector: 'app-dashboard-page',\n imports: [\n PageShellComponent, HeadingComponent, LinkComponent, SkeletonComponent, ...ASYNC,\n RegistrationSummaryComponent, RegistrationTableComponent,\n ],\n template: `\n <app-page-shell heading=\"Mijn BIG-registratie\">\n <!-- Summary: loading -> skeleton, error -> retry, else the card -->\n <app-async [resource]=\"reg\" [isEmpty]=\"regEmpty\">\n <ng-template appAsyncLoaded let-r>\n <app-registration-summary [reg]=\"$any(r)\" />\n </ng-template>\n <ng-template appAsyncLoading>\n <app-skeleton height=\"2.5rem\" [count]=\"6\" />\n </ng-template>\n </app-async>\n\n <div style=\"margin-top:2rem\">\n <app-heading [level]=\"2\">Specialismen en aantekeningen</app-heading>\n <app-async [resource]=\"notes\" [isEmpty]=\"notesEmpty\">\n <ng-template appAsyncLoaded let-r>\n <app-registration-table [rows]=\"$any(r)\" />\n </ng-template>\n <ng-template appAsyncLoading>\n <app-skeleton height=\"2.5rem\" [count]=\"3\" />\n </ng-template>\n <ng-template appAsyncEmpty>\n <p class=\"rhc-paragraph\">U heeft nog geen specialismen of aantekeningen.</p>\n </ng-template>\n </app-async>\n </div>\n\n <p style=\"margin-top:2rem\">\n <app-link to=\"/registratie\">Gegevens bekijken of een wijziging doorgeven →</app-link>\n </p>\n <p>\n <app-link to=\"/herregistratie\">Herregistratie aanvragen →</app-link>\n </p>\n </app-page-shell>\n `,\n})\nexport class DashboardPage {\n private svc = inject(RegistrationService);\n reg = this.svc.registrationResource();\n notes = this.svc.aantekeningenResource();\n notesEmpty = (v: Aantekening[]) => v.length === 0;\n regEmpty = (v: unknown) => !v || Object.keys(v).length === 0;\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "DataRowComponent",
"id": "component-DataRowComponent-bf012e0b5e277c5c6d53311a7649373316677ab4f6d5ba0b313f5eaeb5a061ea55cb08b0af237c487dcc3be5b15014d5c2b21b6f6903ff7689881fc8607eb1b2",
"file": "src/app/molecules/data-row/data-row.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-data-row",
"styleUrls": [],
"styles": [],
"template": "<div class=\"rhc-data-summary__item\">\n <dt class=\"rhc-data-summary__item-key\">{{ key() }}</dt>\n <dd class=\"rhc-data-summary__item-value\"><ng-content>{{ value() }}</ng-content></dd>\n</div>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "key",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 15,
"required": true
},
{
"name": "value",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string | null",
"indexKey": "",
"optional": false,
"description": "",
"line": 16,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>Molecule: one key/value row inside an RHC data-summary.\nWrap several of these in .rhc-data-summary (see registration-summary).</p>\n",
"rawdescription": "\nMolecule: one key/value row inside an RHC data-summary.\nWrap several of these in .rhc-data-summary (see registration-summary).",
"type": "component",
"sourceCode": "import { Component, input } from '@angular/core';\n\n/** Molecule: one key/value row inside an RHC data-summary.\n Wrap several of these in .rhc-data-summary (see registration-summary). */\n@Component({\n selector: 'app-data-row',\n template: `\n <div class=\"rhc-data-summary__item\">\n <dt class=\"rhc-data-summary__item-key\">{{ key() }}</dt>\n <dd class=\"rhc-data-summary__item-value\"><ng-content>{{ value() }}</ng-content></dd>\n </div>\n `,\n})\nexport class DataRowComponent {\n key = input.required<string>();\n value = input<string | null>('');\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "FormFieldComponent",
"id": "component-FormFieldComponent-9f7fb7fac967056161f8440bccbd87825bc2897463f63a612a12ac6154cfaa4e17a2a6469fbe936deba74319ac6029c6aa024abfc07095b226f5980e654cb12c",
"file": "src/app/molecules/form-field/form-field.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-form-field",
"styleUrls": [],
"styles": [],
"template": "<div class=\"rhc-form-field utrecht-form-field\" [class.utrecht-form-field--invalid]=\"!!error()\">\n <label class=\"utrecht-form-label\" [for]=\"fieldId()\">{{ label() }}</label>\n @if (description()) {\n <div class=\"utrecht-form-field-description\">{{ description() }}</div>\n }\n <ng-content />\n @if (error()) {\n <div class=\"utrecht-form-field-error-message\" role=\"alert\">{{ error() }}</div>\n }\n</div>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "description",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 23,
"required": false
},
{
"name": "error",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 24,
"required": false
},
{
"name": "fieldId",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 22,
"required": true
},
{
"name": "label",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 21,
"required": true
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>Molecule: form field = label + projected control + optional error/description.\nReused by both the login form and the change-request form.</p>\n",
"rawdescription": "\nMolecule: form field = label + projected control + optional error/description.\nReused by both the login form and the change-request form.",
"type": "component",
"sourceCode": "import { Component, input } from '@angular/core';\n\n/** Molecule: form field = label + projected control + optional error/description.\n Reused by both the login form and the change-request form. */\n@Component({\n selector: 'app-form-field',\n template: `\n <div class=\"rhc-form-field utrecht-form-field\" [class.utrecht-form-field--invalid]=\"!!error()\">\n <label class=\"utrecht-form-label\" [for]=\"fieldId()\">{{ label() }}</label>\n @if (description()) {\n <div class=\"utrecht-form-field-description\">{{ description() }}</div>\n }\n <ng-content />\n @if (error()) {\n <div class=\"utrecht-form-field-error-message\" role=\"alert\">{{ error() }}</div>\n }\n </div>\n `,\n})\nexport class FormFieldComponent {\n label = input.required<string>();\n fieldId = input.required<string>();\n description = input<string>();\n error = input<string>();\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "HeadingComponent",
"id": "component-HeadingComponent-0f0b442fc9ccbfde8481137b728000bb093868ddc931f507bbd4a86ee528820cf4c6dab36a9a82b4a940bb96c2355f42bc34a94700acc7df3e7dfeea627be67c",
"file": "src/app/atoms/heading/heading.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-heading",
"styleUrls": [],
"styles": [],
"template": "<ng-template #content><ng-content /></ng-template>\n@switch (level()) {\n @case (1) { <h1 class=\"rhc-heading nl-heading--level-1\"><ng-container [ngTemplateOutlet]=\"content\" /></h1> }\n @case (2) { <h2 class=\"rhc-heading nl-heading--level-2\"><ng-container [ngTemplateOutlet]=\"content\" /></h2> }\n @case (3) { <h3 class=\"rhc-heading nl-heading--level-3\"><ng-container [ngTemplateOutlet]=\"content\" /></h3> }\n @case (4) { <h4 class=\"rhc-heading nl-heading--level-4\"><ng-container [ngTemplateOutlet]=\"content\" /></h4> }\n @default { <h5 class=\"rhc-heading nl-heading--level-5\"><ng-container [ngTemplateOutlet]=\"content\" /></h5> }\n}\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "level",
"defaultValue": "2",
"deprecated": false,
"deprecationMessage": "",
"type": "1 | 2 | 3 | 4 | 5",
"indexKey": "",
"optional": false,
"description": "",
"line": 22,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "NgTemplateOutlet"
}
],
"description": "<p>Atom: heading. Renders the right h1..h5 with RHC heading styling.\nSingle <ng-content> captured in a template — multiple ng-content across</p>\n",
"rawdescription": "\nAtom: heading. Renders the right h1..h5 with RHC heading styling.\nSingle <ng-content> captured in a template — multiple ng-content across",
"type": "component",
"sourceCode": "import { Component, input } from '@angular/core';\nimport { NgTemplateOutlet } from '@angular/common';\n\n/** Atom: heading. Renders the right h1..h5 with RHC heading styling.\n Single <ng-content> captured in a template — multiple ng-content across\n @switch branches silently drops the projected content. */\n@Component({\n selector: 'app-heading',\n imports: [NgTemplateOutlet],\n template: `\n <ng-template #content><ng-content /></ng-template>\n @switch (level()) {\n @case (1) { <h1 class=\"rhc-heading nl-heading--level-1\"><ng-container [ngTemplateOutlet]=\"content\" /></h1> }\n @case (2) { <h2 class=\"rhc-heading nl-heading--level-2\"><ng-container [ngTemplateOutlet]=\"content\" /></h2> }\n @case (3) { <h3 class=\"rhc-heading nl-heading--level-3\"><ng-container [ngTemplateOutlet]=\"content\" /></h3> }\n @case (4) { <h4 class=\"rhc-heading nl-heading--level-4\"><ng-container [ngTemplateOutlet]=\"content\" /></h4> }\n @default { <h5 class=\"rhc-heading nl-heading--level-5\"><ng-container [ngTemplateOutlet]=\"content\" /></h5> }\n }\n `,\n})\nexport class HeadingComponent {\n level = input<1 | 2 | 3 | 4 | 5>(2);\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "HerregistratiePage",
"id": "component-HerregistratiePage-ab0497d7957e16f74b4c042109d559a772b5fd5c364d0d3c721504a6467354672c7afef26ddf84aa3d7a9e64ec48213993f5550e57ca65a536d10403b61ec754",
"file": "src/app/pages/herregistratie/herregistratie.page.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-herregistratie-page",
"styleUrls": [],
"styles": [],
"template": "<app-page-shell heading=\"Herregistratie aanvragen\" backLink=\"/dashboard\">\n <app-alert type=\"info\">\n Uw huidige registratie verloopt op 1 september 2027. Vraag tijdig herregistratie aan.\n </app-alert>\n\n @if (submitted()) {\n <div style=\"margin-top:1.5rem\">\n <app-alert type=\"ok\">Uw aanvraag tot herregistratie is ontvangen.</app-alert>\n </div>\n } @else {\n <form (ngSubmit)=\"onSubmit()\" style=\"max-width:28rem;margin-top:1.5rem\">\n <app-form-field label=\"Gewerkte uren (afgelopen 5 jaar)\" fieldId=\"uren\" [error]=\"urenError()\">\n <app-text-input inputId=\"uren\" [(ngModel)]=\"uren\" name=\"uren\" [invalid]=\"!!urenError()\" placeholder=\"bijv. 4160\" />\n </app-form-field>\n <app-form-field label=\"Behaalde nascholingspunten\" fieldId=\"punten\">\n <app-text-input inputId=\"punten\" [(ngModel)]=\"punten\" name=\"punten\" placeholder=\"bijv. 200\" />\n </app-form-field>\n <div style=\"margin-top:1rem\">\n <app-button type=\"submit\" variant=\"primary\">Herregistratie aanvragen</app-button>\n </div>\n </form>\n }\n</app-page-shell>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [],
"propertiesClass": [
{
"name": "punten",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 45
},
{
"name": "submitted",
"defaultValue": "signal(false)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 47
},
{
"name": "uren",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 44
},
{
"name": "urenError",
"defaultValue": "signal('')",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 46
}
],
"methodsClass": [
{
"name": "onSubmit",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 49,
"deprecated": false,
"deprecationMessage": ""
}
],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "FormsModule",
"type": "module"
},
{
"name": "PageShellComponent",
"type": "component"
},
{
"name": "AlertComponent",
"type": "component"
},
{
"name": "ButtonComponent",
"type": "component"
},
{
"name": "FormFieldComponent",
"type": "component"
},
{
"name": "TextInputComponent",
"type": "component"
}
],
"description": "<p>A whole new page built from existing building blocks — no new components.\nThis is the atomic-design payoff: a new flow is just composition.</p>\n",
"rawdescription": "\nA whole new page built from existing building blocks — no new components.\nThis is the atomic-design payoff: a new flow is just composition.",
"type": "component",
"sourceCode": "import { Component, signal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { PageShellComponent } from '../../templates/page-shell/page-shell.component';\nimport { AlertComponent } from '../../atoms/alert/alert.component';\nimport { ButtonComponent } from '../../atoms/button/button.component';\nimport { FormFieldComponent } from '../../molecules/form-field/form-field.component';\nimport { TextInputComponent } from '../../atoms/text-input/text-input.component';\n\n/** A whole new page built from existing building blocks — no new components.\n This is the atomic-design payoff: a new flow is just composition. */\n@Component({\n selector: 'app-herregistratie-page',\n imports: [\n FormsModule, PageShellComponent, AlertComponent,\n ButtonComponent, FormFieldComponent, TextInputComponent,\n ],\n template: `\n <app-page-shell heading=\"Herregistratie aanvragen\" backLink=\"/dashboard\">\n <app-alert type=\"info\">\n Uw huidige registratie verloopt op 1 september 2027. Vraag tijdig herregistratie aan.\n </app-alert>\n\n @if (submitted()) {\n <div style=\"margin-top:1.5rem\">\n <app-alert type=\"ok\">Uw aanvraag tot herregistratie is ontvangen.</app-alert>\n </div>\n } @else {\n <form (ngSubmit)=\"onSubmit()\" style=\"max-width:28rem;margin-top:1.5rem\">\n <app-form-field label=\"Gewerkte uren (afgelopen 5 jaar)\" fieldId=\"uren\" [error]=\"urenError()\">\n <app-text-input inputId=\"uren\" [(ngModel)]=\"uren\" name=\"uren\" [invalid]=\"!!urenError()\" placeholder=\"bijv. 4160\" />\n </app-form-field>\n <app-form-field label=\"Behaalde nascholingspunten\" fieldId=\"punten\">\n <app-text-input inputId=\"punten\" [(ngModel)]=\"punten\" name=\"punten\" placeholder=\"bijv. 200\" />\n </app-form-field>\n <div style=\"margin-top:1rem\">\n <app-button type=\"submit\" variant=\"primary\">Herregistratie aanvragen</app-button>\n </div>\n </form>\n }\n </app-page-shell>\n `,\n})\nexport class HerregistratiePage {\n uren = '';\n punten = '';\n urenError = signal('');\n submitted = signal(false);\n\n onSubmit() {\n if (!this.uren.trim()) { this.urenError.set('Vul het aantal gewerkte uren in.'); return; }\n this.urenError.set('');\n this.submitted.set(true);\n }\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "LinkComponent",
"id": "component-LinkComponent-81d97782386b884f56c43d583cbf6d1005dda96974f169366a9af853aeb8b8f4e99f9cce2f9a7ef0fdafce32f51e6049483a44ab35614c486f82535b65ce2818",
"file": "src/app/atoms/link/link.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-link",
"styleUrls": [],
"styles": [],
"template": "<a [routerLink]=\"to()\" class=\"rhc-link nl-link utrecht-link\"><ng-content /></a>",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "to",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 11,
"required": true
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "RouterLink"
}
],
"description": "<p>Atom: link. Internal router link styled as an RHC/Utrecht link.</p>\n",
"rawdescription": "\nAtom: link. Internal router link styled as an RHC/Utrecht link.",
"type": "component",
"sourceCode": "import { Component, input } from '@angular/core';\nimport { RouterLink } from '@angular/router';\n\n/** Atom: link. Internal router link styled as an RHC/Utrecht link. */\n@Component({\n selector: 'app-link',\n imports: [RouterLink],\n template: `<a [routerLink]=\"to()\" class=\"rhc-link nl-link utrecht-link\"><ng-content /></a>`,\n})\nexport class LinkComponent {\n to = input.required<string>();\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "LoginFormComponent",
"id": "component-LoginFormComponent-09b4fa4e3820031285372fc93c6a18697b3099647bf79b1869c466189d5041da442eaac2e437ae8efa5cd2546d72bbdbd9c001c24e8b1d26f363e763d0382e3d",
"file": "src/app/organisms/login-form/login-form.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-login-form",
"styleUrls": [],
"styles": [],
"template": "<form (ngSubmit)=\"submit.emit()\">\n <app-form-field label=\"BSN\" fieldId=\"bsn\" description=\"9 cijfers (demo: vul iets in)\">\n <app-text-input inputId=\"bsn\" [(ngModel)]=\"bsn\" name=\"bsn\" placeholder=\"123456789\" />\n </app-form-field>\n\n <app-form-field label=\"Wachtwoord\" fieldId=\"pw\">\n <app-text-input inputId=\"pw\" type=\"password\" [(ngModel)]=\"password\" name=\"pw\" />\n </app-form-field>\n\n <div style=\"margin-top:1rem\">\n <app-button type=\"submit\" variant=\"primary\">Inloggen met DigiD</app-button>\n </div>\n</form>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [
{
"name": "submit",
"deprecated": false,
"deprecationMessage": "",
"type": "void",
"indexKey": "",
"optional": false,
"description": "",
"line": 30,
"required": false
}
],
"propertiesClass": [
{
"name": "bsn",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 28
},
{
"name": "password",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 29
}
],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "FormsModule",
"type": "module"
},
{
"name": "FormFieldComponent",
"type": "component"
},
{
"name": "TextInputComponent",
"type": "component"
},
{
"name": "ButtonComponent",
"type": "component"
}
],
"description": "<p>Organism: DigiD-style mock login. No real auth — just composes atoms/molecules.</p>\n",
"rawdescription": "\nOrganism: DigiD-style mock login. No real auth — just composes atoms/molecules.",
"type": "component",
"sourceCode": "import { Component, output } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport { FormFieldComponent } from '../../molecules/form-field/form-field.component';\nimport { TextInputComponent } from '../../atoms/text-input/text-input.component';\nimport { ButtonComponent } from '../../atoms/button/button.component';\n\n/** Organism: DigiD-style mock login. No real auth — just composes atoms/molecules. */\n@Component({\n selector: 'app-login-form',\n imports: [FormsModule, FormFieldComponent, TextInputComponent, ButtonComponent],\n template: `\n <form (ngSubmit)=\"submit.emit()\">\n <app-form-field label=\"BSN\" fieldId=\"bsn\" description=\"9 cijfers (demo: vul iets in)\">\n <app-text-input inputId=\"bsn\" [(ngModel)]=\"bsn\" name=\"bsn\" placeholder=\"123456789\" />\n </app-form-field>\n\n <app-form-field label=\"Wachtwoord\" fieldId=\"pw\">\n <app-text-input inputId=\"pw\" type=\"password\" [(ngModel)]=\"password\" name=\"pw\" />\n </app-form-field>\n\n <div style=\"margin-top:1rem\">\n <app-button type=\"submit\" variant=\"primary\">Inloggen met DigiD</app-button>\n </div>\n </form>\n `,\n})\nexport class LoginFormComponent {\n bsn = '';\n password = '';\n submit = output<void>();\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "LoginPage",
"id": "component-LoginPage-e8a9fcb0309464188c46b54292e1b26314533e424703d8d6d84a1cffe31832e80d7ae8fe256da4b42d053ec775301d70502a9022e092ee0b2d10c7777baf1913",
"file": "src/app/pages/login/login.page.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-login-page",
"styleUrls": [],
"styles": [],
"template": "<app-page-shell heading=\"Inloggen\" width=\"narrow\"\n intro=\"Log in op uw persoonlijke BIG-register omgeving.\">\n <app-login-form (submit)=\"login()\" />\n</app-page-shell>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [],
"propertiesClass": [
{
"name": "router",
"defaultValue": "inject(Router)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 17,
"modifierKind": [
123
]
}
],
"methodsClass": [
{
"name": "login",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 18,
"deprecated": false,
"deprecationMessage": ""
}
],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "PageShellComponent",
"type": "component"
},
{
"name": "LoginFormComponent",
"type": "component"
}
],
"description": "",
"rawdescription": "\n",
"type": "component",
"sourceCode": "import { Component, inject } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { PageShellComponent } from '../../templates/page-shell/page-shell.component';\nimport { LoginFormComponent } from '../../organisms/login-form/login-form.component';\n\n@Component({\n selector: 'app-login-page',\n imports: [PageShellComponent, LoginFormComponent],\n template: `\n <app-page-shell heading=\"Inloggen\" width=\"narrow\"\n intro=\"Log in op uw persoonlijke BIG-register omgeving.\">\n <app-login-form (submit)=\"login()\" />\n </app-page-shell>\n `,\n})\nexport class LoginPage {\n private router = inject(Router);\n login() { this.router.navigate(['/dashboard']); }\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "PageLayoutComponent",
"id": "component-PageLayoutComponent-dd10c533ec0fae79341ba928861681e8d5b84e8856a5d98644f7cfa8bddacd9059014a17899fb35eb34256d29d46fe17910e7541f7c227f82ebd04bd7ab00e8e",
"file": "src/app/templates/page-layout/page-layout.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-page-layout",
"styleUrls": [],
"styles": [
":host{display:block}"
],
"template": "<a href=\"#main\" class=\"rhc-skip-link\" style=\"position:absolute;left:-999px\">Naar de inhoud</a>\n<!-- align-items:stretch overrides the design-system flex-start so the\n full-bleed header/footer bars fill the viewport width. -->\n<div class=\"utrecht-page-layout utrecht-page-layout--stretch\" style=\"--app-content-max:64rem;min-height:100vh;align-items:stretch\">\n <app-site-header />\n <main id=\"main\" class=\"utrecht-page-content\" style=\"flex:1;width:100%;box-sizing:border-box\">\n <div style=\"max-width:var(--app-content-max);margin:0 auto;padding:2rem 1.5rem;box-sizing:border-box\">\n <ng-content />\n </div>\n </main>\n <app-site-footer />\n</div>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "SiteHeaderComponent",
"type": "component"
},
{
"name": "SiteFooterComponent",
"type": "component"
}
],
"description": "<p>Template: full-bleed header + footer with a centered content column. Wraps\nevery page. The colored bars span the viewport; content lines up via the\nshared --app-content-max width.</p>\n",
"rawdescription": "\nTemplate: full-bleed header + footer with a centered content column. Wraps\nevery page. The colored bars span the viewport; content lines up via the\nshared --app-content-max width.",
"type": "component",
"sourceCode": "import { Component } from '@angular/core';\nimport { SiteHeaderComponent } from '../../organisms/site-header/site-header.component';\nimport { SiteFooterComponent } from '../../organisms/site-footer/site-footer.component';\n\n/** Template: full-bleed header + footer with a centered content column. Wraps\n every page. The colored bars span the viewport; content lines up via the\n shared --app-content-max width. */\n@Component({\n selector: 'app-page-layout',\n imports: [SiteHeaderComponent, SiteFooterComponent],\n styles: [':host{display:block}'],\n template: `\n <a href=\"#main\" class=\"rhc-skip-link\" style=\"position:absolute;left:-999px\">Naar de inhoud</a>\n <!-- align-items:stretch overrides the design-system flex-start so the\n full-bleed header/footer bars fill the viewport width. -->\n <div class=\"utrecht-page-layout utrecht-page-layout--stretch\" style=\"--app-content-max:64rem;min-height:100vh;align-items:stretch\">\n <app-site-header />\n <main id=\"main\" class=\"utrecht-page-content\" style=\"flex:1;width:100%;box-sizing:border-box\">\n <div style=\"max-width:var(--app-content-max);margin:0 auto;padding:2rem 1.5rem;box-sizing:border-box\">\n <ng-content />\n </div>\n </main>\n <app-site-footer />\n </div>\n `,\n})\nexport class PageLayoutComponent {}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": ":host{display:block}\n",
"extends": []
},
{
"name": "PageShellComponent",
"id": "component-PageShellComponent-52728311f7328b4b0c4553918adf0b60fbfc082e4d7fcc85eb5375153b4231b4c11f8e83bb57b8bc14b0035921e4415ef241d802f7cf09e82557cef871c83623",
"file": "src/app/templates/page-shell/page-shell.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-page-shell",
"styleUrls": [],
"styles": [
":host{display:block}"
],
"template": "<app-page-layout>\n <div [style.max-width]=\"width() === 'narrow' ? '32rem' : null\">\n @if (backLink()) {\n <p><app-link [to]=\"backLink()!\">← {{ backLabel() }}</app-link></p>\n }\n <app-heading [level]=\"1\">{{ heading() }}</app-heading>\n @if (intro()) {\n <p class=\"rhc-paragraph\" style=\"margin-bottom:1.5rem\">{{ intro() }}</p>\n }\n <ng-content />\n </div>\n</app-page-layout>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "backLabel",
"defaultValue": "'Terug naar overzicht'",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 32,
"required": false
},
{
"name": "backLink",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 31,
"required": false
},
{
"name": "heading",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 29,
"required": true
},
{
"name": "intro",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 30,
"required": false
},
{
"name": "width",
"defaultValue": "'default'",
"deprecated": false,
"deprecationMessage": "",
"type": "\"default\" | \"narrow\"",
"indexKey": "",
"optional": false,
"description": "",
"line": 33,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "PageLayoutComponent",
"type": "component"
},
{
"name": "HeadingComponent",
"type": "component"
},
{
"name": "LinkComponent",
"type": "component"
}
],
"description": "<p>Template: standard page body inside the chrome — optional back-link, a\nheading, optional intro, and projected content. Every content page plugs\ninto this, so the heading/back-link markup lives in one place.</p>\n",
"rawdescription": "\nTemplate: standard page body inside the chrome — optional back-link, a\nheading, optional intro, and projected content. Every content page plugs\ninto this, so the heading/back-link markup lives in one place.",
"type": "component",
"sourceCode": "import { Component, input } from '@angular/core';\nimport { PageLayoutComponent } from '../page-layout/page-layout.component';\nimport { HeadingComponent } from '../../atoms/heading/heading.component';\nimport { LinkComponent } from '../../atoms/link/link.component';\n\n/** Template: standard page body inside the chrome — optional back-link, a\n heading, optional intro, and projected content. Every content page plugs\n into this, so the heading/back-link markup lives in one place. */\n@Component({\n selector: 'app-page-shell',\n imports: [PageLayoutComponent, HeadingComponent, LinkComponent],\n styles: [':host{display:block}'],\n template: `\n <app-page-layout>\n <div [style.max-width]=\"width() === 'narrow' ? '32rem' : null\">\n @if (backLink()) {\n <p><app-link [to]=\"backLink()!\">← {{ backLabel() }}</app-link></p>\n }\n <app-heading [level]=\"1\">{{ heading() }}</app-heading>\n @if (intro()) {\n <p class=\"rhc-paragraph\" style=\"margin-bottom:1.5rem\">{{ intro() }}</p>\n }\n <ng-content />\n </div>\n </app-page-layout>\n `,\n})\nexport class PageShellComponent {\n heading = input.required<string>();\n intro = input<string>();\n backLink = input<string>();\n backLabel = input('Terug naar overzicht');\n width = input<'default' | 'narrow'>('default');\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": ":host{display:block}\n",
"extends": []
},
{
"name": "RegistrationDetailPage",
"id": "component-RegistrationDetailPage-efb92f879b64c25c80211fcc675636fad2b1709613792834a68cec3b82982d290d7f04e97dd3186900b77a5922cd219f565fbf9a9957ec78e2321ad7e2eb30dc",
"file": "src/app/pages/registration-detail/registration-detail.page.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-registration-detail-page",
"styleUrls": [],
"styles": [],
"template": "<app-page-shell heading=\"Mijn gegevens\" backLink=\"/dashboard\">\n <app-async [resource]=\"reg\" [isEmpty]=\"regEmpty\">\n <ng-template appAsyncLoaded let-r>\n <app-registration-summary [reg]=\"$any(r)\" />\n </ng-template>\n <ng-template appAsyncLoading>\n <app-skeleton height=\"2.5rem\" [count]=\"6\" />\n </ng-template>\n </app-async>\n\n <div style=\"margin-top:2rem\">\n @if (submitted()) {\n <app-alert type=\"ok\">Uw adreswijziging is ontvangen. U ontvangt binnen 5 werkdagen bericht.</app-alert>\n } @else {\n <app-change-request-form (submitted)=\"submitted.set(true)\" />\n }\n </div>\n</app-page-shell>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [],
"propertiesClass": [
{
"name": "reg",
"defaultValue": "this.svc.registrationResource()",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 39
},
{
"name": "regEmpty",
"defaultValue": "() => {...}",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 40
},
{
"name": "submitted",
"defaultValue": "signal(false)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 41
},
{
"name": "svc",
"defaultValue": "inject(RegistrationService)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 38,
"modifierKind": [
123
]
}
],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "PageShellComponent",
"type": "component"
},
{
"name": "AlertComponent",
"type": "component"
},
{
"name": "SkeletonComponent",
"type": "component"
},
{
"name": "ASYNC"
},
{
"name": "RegistrationSummaryComponent",
"type": "component"
},
{
"name": "ChangeRequestFormComponent",
"type": "component"
}
],
"description": "",
"rawdescription": "\n",
"type": "component",
"sourceCode": "import { Component, inject, signal } from '@angular/core';\nimport { PageShellComponent } from '../../templates/page-shell/page-shell.component';\nimport { AlertComponent } from '../../atoms/alert/alert.component';\nimport { SkeletonComponent } from '../../atoms/skeleton/skeleton.component';\nimport { ASYNC } from '../../molecules/async/async.component';\nimport { RegistrationSummaryComponent } from '../../organisms/registration-summary/registration-summary.component';\nimport { ChangeRequestFormComponent } from '../../organisms/change-request-form/change-request-form.component';\nimport { RegistrationService } from '../../core/registration.service';\n\n@Component({\n selector: 'app-registration-detail-page',\n imports: [\n PageShellComponent, AlertComponent, SkeletonComponent, ...ASYNC,\n RegistrationSummaryComponent, ChangeRequestFormComponent,\n ],\n template: `\n <app-page-shell heading=\"Mijn gegevens\" backLink=\"/dashboard\">\n <app-async [resource]=\"reg\" [isEmpty]=\"regEmpty\">\n <ng-template appAsyncLoaded let-r>\n <app-registration-summary [reg]=\"$any(r)\" />\n </ng-template>\n <ng-template appAsyncLoading>\n <app-skeleton height=\"2.5rem\" [count]=\"6\" />\n </ng-template>\n </app-async>\n\n <div style=\"margin-top:2rem\">\n @if (submitted()) {\n <app-alert type=\"ok\">Uw adreswijziging is ontvangen. U ontvangt binnen 5 werkdagen bericht.</app-alert>\n } @else {\n <app-change-request-form (submitted)=\"submitted.set(true)\" />\n }\n </div>\n </app-page-shell>\n `,\n})\nexport class RegistrationDetailPage {\n private svc = inject(RegistrationService);\n reg = this.svc.registrationResource();\n regEmpty = (v: unknown) => !v || Object.keys(v).length === 0;\n submitted = signal(false);\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "RegistrationSummaryComponent",
"id": "component-RegistrationSummaryComponent-eb956e029fecdfc5c3173f0c48515cad94e7bb8023ebcc4d0a37ae311c0b39c215fb46643ac356b4dd5c0f4ead6123e79f4f7aeecc3b631eff0269e9f1a3e914",
"file": "src/app/organisms/registration-summary/registration-summary.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-registration-summary",
"styleUrls": [],
"styles": [],
"template": "<div class=\"rhc-card rhc-card--default\">\n <dl class=\"rhc-data-summary rhc-data-summary--row\">\n <app-data-row key=\"BIG-nummer\" [value]=\"reg().bigNummer\" />\n <app-data-row key=\"Naam\" [value]=\"reg().naam\" />\n <app-data-row key=\"Beroep\" [value]=\"reg().beroep\" />\n <app-data-row key=\"Status\">\n <app-status-badge [status]=\"reg().status\" />\n </app-data-row>\n <app-data-row key=\"Registratiedatum\" [value]=\"reg().registratiedatum | date:'longDate'\" />\n <app-data-row key=\"Uiterste herregistratie\" [value]=\"reg().herregistratieDatum | date:'longDate'\" />\n </dl>\n</div>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "reg",
"deprecated": false,
"deprecationMessage": "",
"type": "Registration",
"indexKey": "",
"optional": false,
"description": "",
"line": 27,
"required": true
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "DatePipe",
"type": "pipe"
},
{
"name": "DataRowComponent",
"type": "component"
},
{
"name": "StatusBadgeComponent",
"type": "component"
}
],
"description": "<p>Organism: registration summary card. Composes data-row molecules + status-badge atom.</p>\n",
"rawdescription": "\nOrganism: registration summary card. Composes data-row molecules + status-badge atom.",
"type": "component",
"sourceCode": "import { Component, input } from '@angular/core';\nimport { DatePipe } from '@angular/common';\nimport { Registration } from '../../core/models';\nimport { DataRowComponent } from '../../molecules/data-row/data-row.component';\nimport { StatusBadgeComponent } from '../../atoms/status-badge/status-badge.component';\n\n/** Organism: registration summary card. Composes data-row molecules + status-badge atom. */\n@Component({\n selector: 'app-registration-summary',\n imports: [DatePipe, DataRowComponent, StatusBadgeComponent],\n template: `\n <div class=\"rhc-card rhc-card--default\">\n <dl class=\"rhc-data-summary rhc-data-summary--row\">\n <app-data-row key=\"BIG-nummer\" [value]=\"reg().bigNummer\" />\n <app-data-row key=\"Naam\" [value]=\"reg().naam\" />\n <app-data-row key=\"Beroep\" [value]=\"reg().beroep\" />\n <app-data-row key=\"Status\">\n <app-status-badge [status]=\"reg().status\" />\n </app-data-row>\n <app-data-row key=\"Registratiedatum\" [value]=\"reg().registratiedatum | date:'longDate'\" />\n <app-data-row key=\"Uiterste herregistratie\" [value]=\"reg().herregistratieDatum | date:'longDate'\" />\n </dl>\n </div>\n `,\n})\nexport class RegistrationSummaryComponent {\n reg = input.required<Registration>();\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "RegistrationTableComponent",
"id": "component-RegistrationTableComponent-53e1c5109b067c2b72ccd183e6350c59ea4bbd34a8f40a0f4e50c59d6165f5f8040177f74a592be42b8e571c4530ad2bf60c4a3a712689c82460997cb91ed770",
"file": "src/app/organisms/registration-table/registration-table.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-registration-table",
"styleUrls": [],
"styles": [],
"template": "<div class=\"utrecht-table-container utrecht-table-container--overflow-inline\">\n <table class=\"utrecht-table utrecht-table--html-table utrecht-table--alternate-row-color\">\n <thead>\n <tr>\n <th class=\"utrecht-table__header-cell\">Type</th>\n <th class=\"utrecht-table__header-cell\">Omschrijving</th>\n <th class=\"utrecht-table__header-cell\">Datum</th>\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track row.omschrijving) {\n <tr>\n <td class=\"utrecht-table__cell\">{{ row.type }}</td>\n <td class=\"utrecht-table__cell\">{{ row.omschrijving }}</td>\n <td class=\"utrecht-table__cell\">{{ row.datum | date:'mediumDate' }}</td>\n </tr>\n }\n </tbody>\n </table>\n</div>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "rows",
"deprecated": false,
"deprecationMessage": "",
"type": "Aantekening[]",
"indexKey": "",
"optional": false,
"description": "",
"line": 33,
"required": true
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "DatePipe",
"type": "pipe"
}
],
"description": "<p>Organism: table of specialismen/aantekeningen.</p>\n",
"rawdescription": "\nOrganism: table of specialismen/aantekeningen.",
"type": "component",
"sourceCode": "import { Component, input } from '@angular/core';\nimport { DatePipe } from '@angular/common';\nimport { Aantekening } from '../../core/models';\n\n/** Organism: table of specialismen/aantekeningen. */\n@Component({\n selector: 'app-registration-table',\n imports: [DatePipe],\n template: `\n <div class=\"utrecht-table-container utrecht-table-container--overflow-inline\">\n <table class=\"utrecht-table utrecht-table--html-table utrecht-table--alternate-row-color\">\n <thead>\n <tr>\n <th class=\"utrecht-table__header-cell\">Type</th>\n <th class=\"utrecht-table__header-cell\">Omschrijving</th>\n <th class=\"utrecht-table__header-cell\">Datum</th>\n </tr>\n </thead>\n <tbody>\n @for (row of rows(); track row.omschrijving) {\n <tr>\n <td class=\"utrecht-table__cell\">{{ row.type }}</td>\n <td class=\"utrecht-table__cell\">{{ row.omschrijving }}</td>\n <td class=\"utrecht-table__cell\">{{ row.datum | date:'mediumDate' }}</td>\n </tr>\n }\n </tbody>\n </table>\n </div>\n `,\n})\nexport class RegistrationTableComponent {\n rows = input.required<Aantekening[]>();\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "SiteFooterComponent",
"id": "component-SiteFooterComponent-90391287c6e8f3ad80c034a7a6fdabdd0514fd9c0dcf549a8e4a2d3bc3d885fcd5a45a2eeeb24fa8a4bbcf2cfe865093d712765d9d1ed11b4bfca26d1fb35153",
"file": "src/app/organisms/site-footer/site-footer.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-site-footer",
"styleUrls": [],
"styles": [
":host{display:block}"
],
"template": "<footer class=\"utrecht-page-footer\" style=\"background:var(--rhc-color-lintblauw-900,#01689b);color:#fff;margin-top:3rem;width:100%\">\n <div style=\"max-width:var(--app-content-max);margin:0 auto;padding:1.5rem;display:flex;gap:2rem;flex-wrap:wrap;box-sizing:border-box\">\n <span>BIG-register</span>\n <span>CIBG — Ministerie van Volksgezondheid, Welzijn en Sport</span>\n <span style=\"margin-left:auto;opacity:0.85\">Demo / POC — geen echte gegevens</span>\n </div>\n</footer>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>Organism: site footer.</p>\n",
"rawdescription": "\nOrganism: site footer.",
"type": "component",
"sourceCode": "import { Component } from '@angular/core';\n\n/** Organism: site footer. */\n@Component({\n selector: 'app-site-footer',\n styles: [':host{display:block}'],\n template: `\n <footer class=\"utrecht-page-footer\" style=\"background:var(--rhc-color-lintblauw-900,#01689b);color:#fff;margin-top:3rem;width:100%\">\n <div style=\"max-width:var(--app-content-max);margin:0 auto;padding:1.5rem;display:flex;gap:2rem;flex-wrap:wrap;box-sizing:border-box\">\n <span>BIG-register</span>\n <span>CIBG — Ministerie van Volksgezondheid, Welzijn en Sport</span>\n <span style=\"margin-left:auto;opacity:0.85\">Demo / POC — geen echte gegevens</span>\n </div>\n </footer>\n `,\n})\nexport class SiteFooterComponent {}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": ":host{display:block}\n",
"extends": []
},
{
"name": "SiteHeaderComponent",
"id": "component-SiteHeaderComponent-710f1c109f26ae5f1888aa77ac682c58c9534fbba74aeae04b903e169f674c1ce04b8ae9e379a936c8ddef16e53c500e93d132021bcdd4ef743a601e05808f66",
"file": "src/app/organisms/site-header/site-header.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-site-header",
"styleUrls": [],
"styles": [
":host{display:block}"
],
"template": "<header class=\"utrecht-page-header\" style=\"background:var(--rhc-color-lintblauw-700,#154273);color:#fff;width:100%\">\n <div style=\"display:flex;align-items:center;gap:1rem;max-width:var(--app-content-max);margin:0 auto;padding:1rem 1.5rem;box-sizing:border-box\">\n <a routerLink=\"/dashboard\" style=\"display:flex;align-items:center;gap:0.75rem;color:inherit;text-decoration:none\">\n <span aria-hidden=\"true\" style=\"display:inline-block;width:0.5rem;height:2.25rem;background:#fff\"></span>\n <span style=\"font-weight:700;line-height:1.1\">\n Rijksoverheid<br><span style=\"font-weight:400;font-size:0.9rem\">BIG-register</span>\n </span>\n </a>\n <span style=\"margin-left:auto;font-weight:500\">{{ subtitle() }}</span>\n </div>\n</header>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "subtitle",
"defaultValue": "'Mijn omgeving'",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 27,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "RouterLink"
}
],
"description": "<p>Organism: site header with Rijksoverheid-style wordmark + title.\nponytail: text wordmark instead of the licensed Rijksoverheid logo.</p>\n",
"rawdescription": "\nOrganism: site header with Rijksoverheid-style wordmark + title.\nponytail: text wordmark instead of the licensed Rijksoverheid logo.",
"type": "component",
"sourceCode": "import { Component, input } from '@angular/core';\nimport { RouterLink } from '@angular/router';\n\n/** Organism: site header with Rijksoverheid-style wordmark + title.\n ponytail: text wordmark instead of the licensed Rijksoverheid logo. */\n@Component({\n selector: 'app-site-header',\n imports: [RouterLink],\n // :host display:block so the full-bleed bar fills the flex column (custom\n // elements default to display:inline, which collapsed the bar to its content).\n styles: [':host{display:block}'],\n template: `\n <header class=\"utrecht-page-header\" style=\"background:var(--rhc-color-lintblauw-700,#154273);color:#fff;width:100%\">\n <div style=\"display:flex;align-items:center;gap:1rem;max-width:var(--app-content-max);margin:0 auto;padding:1rem 1.5rem;box-sizing:border-box\">\n <a routerLink=\"/dashboard\" style=\"display:flex;align-items:center;gap:0.75rem;color:inherit;text-decoration:none\">\n <span aria-hidden=\"true\" style=\"display:inline-block;width:0.5rem;height:2.25rem;background:#fff\"></span>\n <span style=\"font-weight:700;line-height:1.1\">\n Rijksoverheid<br><span style=\"font-weight:400;font-size:0.9rem\">BIG-register</span>\n </span>\n </a>\n <span style=\"margin-left:auto;font-weight:500\">{{ subtitle() }}</span>\n </div>\n </header>\n `,\n})\nexport class SiteHeaderComponent {\n subtitle = input('Mijn omgeving');\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": ":host{display:block}\n",
"extends": []
},
{
"name": "SkeletonComponent",
"id": "component-SkeletonComponent-608d7384a7cd5705153c042fd961a63d69e4f61409276c2aec354b33db4199192d161fa81305090c262e18ab0a019913f469e85603ccefa6fba5c0dbc40d4f72",
"file": "src/app/atoms/skeleton/skeleton.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-skeleton",
"styleUrls": [],
"styles": [
"\n :host{display:block}\n .sk{background:linear-gradient(90deg,#e8ebee 25%,#f3f5f6 37%,#e8ebee 63%);\n background-size:400% 100%;animation:sh 1.4s ease infinite;border-radius:4px;\n margin-block-end:0.6rem}\n @keyframes sh{0%{background-position:100% 0}100%{background-position:0 0}}\n "
],
"template": "@if (visible()) {\n @for (l of lines(); track $index) {\n <div class=\"sk\" [style.width]=\"width()\" [style.height]=\"height()\"></div>\n }\n}\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "count",
"defaultValue": "1",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 25,
"required": false
},
{
"name": "delay",
"defaultValue": "150",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 26,
"required": false
},
{
"name": "height",
"defaultValue": "'1rem'",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 24,
"required": false
},
{
"name": "width",
"defaultValue": "'100%'",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 23,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [
{
"name": "lines",
"defaultValue": "computed(() => Array(this.count()).fill(0))",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 28,
"modifierKind": [
124
]
},
{
"name": "timer",
"deprecated": false,
"deprecationMessage": "",
"type": "ReturnType<unknown>",
"indexKey": "",
"optional": true,
"description": "",
"line": 29,
"modifierKind": [
123
]
},
{
"name": "visible",
"defaultValue": "signal(false)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 27,
"modifierKind": [
124
]
}
],
"methodsClass": [
{
"name": "ngOnDestroy",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 32,
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "ngOnInit",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 31,
"deprecated": false,
"deprecationMessage": ""
}
],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>Atom: skeleton placeholder (grey shimmer). Delay-gated so it never flashes\non fast responses. Render <code>count</code> lines shaped roughly like the content.</p>\n",
"rawdescription": "\nAtom: skeleton placeholder (grey shimmer). Delay-gated so it never flashes\non fast responses. Render `count` lines shaped roughly like the content.",
"type": "component",
"sourceCode": "import { Component, OnDestroy, OnInit, computed, input, signal } from '@angular/core';\n\n/** Atom: skeleton placeholder (grey shimmer). Delay-gated so it never flashes\n on fast responses. Render `count` lines shaped roughly like the content. */\n@Component({\n selector: 'app-skeleton',\n styles: [`\n :host{display:block}\n .sk{background:linear-gradient(90deg,#e8ebee 25%,#f3f5f6 37%,#e8ebee 63%);\n background-size:400% 100%;animation:sh 1.4s ease infinite;border-radius:4px;\n margin-block-end:0.6rem}\n @keyframes sh{0%{background-position:100% 0}100%{background-position:0 0}}\n `],\n template: `\n @if (visible()) {\n @for (l of lines(); track $index) {\n <div class=\"sk\" [style.width]=\"width()\" [style.height]=\"height()\"></div>\n }\n }\n `,\n})\nexport class SkeletonComponent implements OnInit, OnDestroy {\n width = input('100%');\n height = input('1rem');\n count = input(1);\n delay = input(150);\n protected visible = signal(false);\n protected lines = computed(() => Array(this.count()).fill(0));\n private timer?: ReturnType<typeof setTimeout>;\n\n ngOnInit() { this.timer = setTimeout(() => this.visible.set(true), this.delay()); }\n ngOnDestroy() { clearTimeout(this.timer); }\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "\n :host{display:block}\n .sk{background:linear-gradient(90deg,#e8ebee 25%,#f3f5f6 37%,#e8ebee 63%);\n background-size:400% 100%;animation:sh 1.4s ease infinite;border-radius:4px;\n margin-block-end:0.6rem}\n @keyframes sh{0%{background-position:100% 0}100%{background-position:0 0}}\n \n",
"extends": [],
"implements": [
"OnInit",
"OnDestroy"
]
},
{
"name": "SpinnerComponent",
"id": "component-SpinnerComponent-4ac83777af1737425f1eec0d4c22a830297cca57c3140ef014842789163b2c2873312a9ae4e9dc7554241ac3b3dc339b7bab22e02fd8a4fe748a985264126ca4",
"file": "src/app/atoms/spinner/spinner.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-spinner",
"styleUrls": [],
"styles": [
"\n :host{display:block}\n .sp{width:2rem;height:2rem;border-radius:50%;\n border:3px solid var(--rhc-color-grijs-300,#cad0d6);\n border-block-start-color:var(--rhc-color-lintblauw-700,#154273);\n animation:sp 0.8s linear infinite;margin:1.5rem auto}\n @keyframes sp{to{transform:rotate(360deg)}}\n "
],
"template": "@if (visible()) {\n <div class=\"sp\" role=\"status\" aria-label=\"Bezig met laden\"></div>\n}\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "delay",
"defaultValue": "250",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 22,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [
{
"name": "timer",
"deprecated": false,
"deprecationMessage": "",
"type": "ReturnType<unknown>",
"indexKey": "",
"optional": true,
"description": "",
"line": 24,
"modifierKind": [
123
]
},
{
"name": "visible",
"defaultValue": "signal(false)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 23,
"modifierKind": [
124
]
}
],
"methodsClass": [
{
"name": "ngOnDestroy",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 27,
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "ngOnInit",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 26,
"deprecated": false,
"deprecationMessage": ""
}
],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>Atom: spinner that only appears after <code>delay</code> ms — fast responses never\nflash a spinner, slow ones get feedback.</p>\n",
"rawdescription": "\nAtom: spinner that only appears after `delay` ms — fast responses never\nflash a spinner, slow ones get feedback.",
"type": "component",
"sourceCode": "import { Component, OnDestroy, OnInit, input, signal } from '@angular/core';\n\n/** Atom: spinner that only appears after `delay` ms — fast responses never\n flash a spinner, slow ones get feedback. */\n@Component({\n selector: 'app-spinner',\n styles: [`\n :host{display:block}\n .sp{width:2rem;height:2rem;border-radius:50%;\n border:3px solid var(--rhc-color-grijs-300,#cad0d6);\n border-block-start-color:var(--rhc-color-lintblauw-700,#154273);\n animation:sp 0.8s linear infinite;margin:1.5rem auto}\n @keyframes sp{to{transform:rotate(360deg)}}\n `],\n template: `\n @if (visible()) {\n <div class=\"sp\" role=\"status\" aria-label=\"Bezig met laden\"></div>\n }\n `,\n})\nexport class SpinnerComponent implements OnInit, OnDestroy {\n delay = input(250);\n protected visible = signal(false);\n private timer?: ReturnType<typeof setTimeout>;\n\n ngOnInit() { this.timer = setTimeout(() => this.visible.set(true), this.delay()); }\n ngOnDestroy() { clearTimeout(this.timer); }\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "\n :host{display:block}\n .sp{width:2rem;height:2rem;border-radius:50%;\n border:3px solid var(--rhc-color-grijs-300,#cad0d6);\n border-block-start-color:var(--rhc-color-lintblauw-700,#154273);\n animation:sp 0.8s linear infinite;margin:1.5rem auto}\n @keyframes sp{to{transform:rotate(360deg)}}\n \n",
"extends": [],
"implements": [
"OnInit",
"OnDestroy"
]
},
{
"name": "StatusBadgeComponent",
"id": "component-StatusBadgeComponent-3374b85f056b7a50e5cce348202733fea8109c0244004ec59ac829d32a629dbd750f1a087eabbdad5fce0aba1cf9495090e7a949f0bec2cdc371f854fc77d365",
"file": "src/app/atoms/status-badge/status-badge.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-status-badge",
"styleUrls": [],
"styles": [],
"template": "<span style=\"display:inline-flex;align-items:center;gap:0.5rem\">\n <span class=\"rhc-dot-badge\" [style.background-color]=\"color()\" aria-hidden=\"true\"></span>\n <span>{{ status() }}</span>\n</span>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "status",
"deprecated": false,
"deprecationMessage": "",
"type": "RegistrationStatus",
"indexKey": "",
"optional": false,
"description": "",
"line": 16,
"required": true
}
],
"outputsClass": [],
"propertiesClass": [
{
"name": "color",
"defaultValue": "computed(() => ({\n Geregistreerd: 'var(--rhc-color-groen-500)',\n Doorgehaald: 'var(--rhc-color-rood-500)',\n Geschorst: 'var(--rhc-color-oranje-500)',\n }[this.status()]))",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 17
}
],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>Atom: status badge = colored RHC dot-badge + label. Hand-built to show how\nyou compose a new atom from design tokens (dot color driven per status).</p>\n",
"rawdescription": "\nAtom: status badge = colored RHC dot-badge + label. Hand-built to show how\nyou compose a new atom from design tokens (dot color driven per status).",
"type": "component",
"sourceCode": "import { Component, computed, input } from '@angular/core';\nimport { RegistrationStatus } from '../../core/models';\n\n/** Atom: status badge = colored RHC dot-badge + label. Hand-built to show how\n you compose a new atom from design tokens (dot color driven per status). */\n@Component({\n selector: 'app-status-badge',\n template: `\n <span style=\"display:inline-flex;align-items:center;gap:0.5rem\">\n <span class=\"rhc-dot-badge\" [style.background-color]=\"color()\" aria-hidden=\"true\"></span>\n <span>{{ status() }}</span>\n </span>\n `,\n})\nexport class StatusBadgeComponent {\n status = input.required<RegistrationStatus>();\n color = computed(() => ({\n Geregistreerd: 'var(--rhc-color-groen-500)',\n Doorgehaald: 'var(--rhc-color-rood-500)',\n Geschorst: 'var(--rhc-color-oranje-500)',\n }[this.status()]));\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "TextInputComponent",
"id": "component-TextInputComponent-9d0cd6c2d7892958e9a016b570670f0186d410ea16a22925126f9eeea1aa178f081a4e5647af633f8a0bc1c458422a9f30169f159f930e9048702995fbb827e6",
"file": "src/app/atoms/text-input/text-input.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [
{
"name": ")"
}
],
"selector": "app-text-input",
"styleUrls": [],
"styles": [],
"template": "<input\n class=\"utrecht-textbox rhc-text-input\"\n [class.utrecht-textbox--invalid]=\"invalid()\"\n [type]=\"type()\"\n [id]=\"inputId()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (blur)=\"onTouched()\" />\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "inputId",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 25,
"required": false
},
{
"name": "invalid",
"defaultValue": "false",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 24,
"required": false
},
{
"name": "placeholder",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 23,
"required": false
},
{
"name": "type",
"defaultValue": "'text'",
"deprecated": false,
"deprecationMessage": "",
"type": "\"text\" | \"password\" | \"email\"",
"indexKey": "",
"optional": false,
"description": "",
"line": 22,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [
{
"name": "disabled",
"defaultValue": "false",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 28
},
{
"name": "onChange",
"defaultValue": "() => {...}",
"deprecated": false,
"deprecationMessage": "",
"type": "function",
"indexKey": "",
"optional": false,
"description": "",
"line": 29
},
{
"name": "onTouched",
"defaultValue": "() => {...}",
"deprecated": false,
"deprecationMessage": "",
"type": "function",
"indexKey": "",
"optional": false,
"description": "",
"line": 30
},
{
"name": "value",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 27
}
],
"methodsClass": [
{
"name": "onInput",
"args": [
{
"name": "e",
"type": "Event",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 32,
"deprecated": false,
"deprecationMessage": "",
"jsdoctags": [
{
"name": "e",
"type": "Event",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "registerOnChange",
"args": [
{
"name": "fn",
"type": "function",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"function": [
{
"name": "v",
"type": "string",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
]
}
],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 37,
"deprecated": false,
"deprecationMessage": "",
"jsdoctags": [
{
"name": "fn",
"type": "function",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"function": [
{
"name": "v",
"type": "string",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"tagName": {
"text": "param"
}
}
]
},
{
"name": "registerOnTouched",
"args": [
{
"name": "fn",
"type": "function",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"function": []
}
],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 38,
"deprecated": false,
"deprecationMessage": "",
"jsdoctags": [
{
"name": "fn",
"type": "function",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"function": [],
"tagName": {
"text": "param"
}
}
]
},
{
"name": "setDisabledState",
"args": [
{
"name": "d",
"type": "boolean",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 39,
"deprecated": false,
"deprecationMessage": "",
"jsdoctags": [
{
"name": "d",
"type": "boolean",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "writeValue",
"args": [
{
"name": "v",
"type": "string",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 36,
"deprecated": false,
"deprecationMessage": "",
"jsdoctags": [
{
"name": "v",
"type": "string",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>Atom: text input. Utrecht textbox wired up as a form control (ngModel/reactive).</p>\n",
"rawdescription": "\nAtom: text input. Utrecht textbox wired up as a form control (ngModel/reactive).",
"type": "component",
"sourceCode": "import { Component, forwardRef, input } from '@angular/core';\nimport { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';\n\n/** Atom: text input. Utrecht textbox wired up as a form control (ngModel/reactive). */\n@Component({\n selector: 'app-text-input',\n template: `\n <input\n class=\"utrecht-textbox rhc-text-input\"\n [class.utrecht-textbox--invalid]=\"invalid()\"\n [type]=\"type()\"\n [id]=\"inputId()\"\n [placeholder]=\"placeholder()\"\n [disabled]=\"disabled\"\n [value]=\"value\"\n (input)=\"onInput($event)\"\n (blur)=\"onTouched()\" />\n `,\n providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => TextInputComponent), multi: true }],\n})\nexport class TextInputComponent implements ControlValueAccessor {\n type = input<'text' | 'password' | 'email'>('text');\n placeholder = input('');\n invalid = input(false);\n inputId = input<string>();\n\n value = '';\n disabled = false;\n onChange: (v: string) => void = () => {};\n onTouched: () => void = () => {};\n\n onInput(e: Event) {\n this.value = (e.target as HTMLInputElement).value;\n this.onChange(this.value);\n }\n writeValue(v: string) { this.value = v ?? ''; }\n registerOnChange(fn: (v: string) => void) { this.onChange = fn; }\n registerOnTouched(fn: () => void) { this.onTouched = fn; }\n setDisabledState(d: boolean) { this.disabled = d; }\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": [],
"implements": [
"ControlValueAccessor"
]
}
],
"modules": [],
"miscellaneous": {
"variables": [
{
"name": "appConfig",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/app.config.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "ApplicationConfig",
"defaultValue": "{\n providers: [\n provideBrowserGlobalErrorListeners(),\n provideRouter(routes),\n provideHttpClient(withInterceptors([scenarioInterceptor])),\n { provide: LOCALE_ID, useValue: 'nl' },\n ]\n}"
},
{
"name": "ASYNC",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/molecules/async/async.component.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"defaultValue": "[\n AsyncComponent, AsyncLoadedDirective, AsyncLoadingDirective,\n AsyncEmptyDirective, AsyncErrorDirective,\n] as const",
"rawdescription": "Convenience: import this array to get the wrapper + all slot directives.",
"description": "<p>Convenience: import this array to get the wrapper + all slot directives.</p>\n"
},
{
"name": "routes",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/app.routes.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "Routes",
"defaultValue": "[\n { path: '', pathMatch: 'full', redirectTo: 'login' },\n { path: 'login', loadComponent: () => \"import('./pages/login/login.page').then(m => m.LoginPage)\" },\n { path: 'dashboard', loadComponent: () => \"import('./pages/dashboard/dashboard.page').then(m => m.DashboardPage)\" },\n { path: 'registratie', loadComponent: () => \"import('./pages/registration-detail/registration-detail.page').then(m => m.RegistrationDetailPage)\" },\n { path: 'herregistratie', loadComponent: () => \"import('./pages/herregistratie/herregistratie.page').then(m => m.HerregistratiePage)\" },\n { path: '**', redirectTo: 'login' },\n]"
},
{
"name": "scenarioInterceptor",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/core/scenario.interceptor.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "HttpInterceptorFn",
"defaultValue": "(req, next) => {\n if (!req.url.includes('mock/')) return next(req);\n\n switch (currentScenario()) {\n case 'slow':\n return next(req).pipe(delay(2500));\n case 'loading':\n return next(req).pipe(delay(600_000)); // effectively never resolves\n case 'empty':\n return of(new HttpResponse({ status: 200, body: [] })).pipe(delay(400));\n case 'error':\n return timer(400).pipe(\n switchMap(() => throwError(() =>\n new HttpErrorResponse({ status: 500, statusText: 'Demo-fout', url: req.url }))),\n );\n default:\n return next(req);\n }\n}",
"rawdescription": "Demo-only: rewrites the timing/outcome of mock data requests based on\n?scenario= so loading / empty / error states can be shown on demand.\nReal requests are untouched.",
"description": "<p>Demo-only: rewrites the timing/outcome of mock data requests based on\n?scenario= so loading / empty / error states can be shown on demand.\nReal requests are untouched.</p>\n"
},
{
"name": "VALID",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/core/scenario.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "Scenario[]",
"defaultValue": "['default', 'slow', 'loading', 'empty', 'error']"
}
],
"functions": [
{
"name": "currentScenario",
"file": "src/app/core/scenario.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Reads ?scenario= from the URL so a demo can force each async state.</p>\n",
"args": [],
"returnType": "Scenario"
}
],
"typealiases": [
{
"name": "AlertType",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "\"info\" | \"ok\" | \"warning\" | \"error\"",
"file": "src/app/atoms/alert/alert.component.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"kind": 193
},
{
"name": "RegistrationStatus",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "\"Geregistreerd\" | \"Doorgehaald\" | \"Geschorst\"",
"file": "src/app/core/models.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"kind": 193
},
{
"name": "Scenario",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "\"default\" | \"slow\" | \"loading\" | \"empty\" | \"error\"",
"file": "src/app/core/scenario.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"kind": 193
},
{
"name": "State",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "\"loading\" | \"error\" | \"empty\" | \"loaded\"",
"file": "src/app/molecules/async/async.component.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"kind": 193
},
{
"name": "Variant",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "\"primary\" | \"secondary\" | \"subtle\" | \"danger\"",
"file": "src/app/atoms/button/button.component.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"kind": 193
}
],
"enumerations": [],
"groupedVariables": {
"src/app/app.config.ts": [
{
"name": "appConfig",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/app.config.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "ApplicationConfig",
"defaultValue": "{\n providers: [\n provideBrowserGlobalErrorListeners(),\n provideRouter(routes),\n provideHttpClient(withInterceptors([scenarioInterceptor])),\n { provide: LOCALE_ID, useValue: 'nl' },\n ]\n}"
}
],
"src/app/molecules/async/async.component.ts": [
{
"name": "ASYNC",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/molecules/async/async.component.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"defaultValue": "[\n AsyncComponent, AsyncLoadedDirective, AsyncLoadingDirective,\n AsyncEmptyDirective, AsyncErrorDirective,\n] as const",
"rawdescription": "Convenience: import this array to get the wrapper + all slot directives.",
"description": "<p>Convenience: import this array to get the wrapper + all slot directives.</p>\n"
}
],
"src/app/app.routes.ts": [
{
"name": "routes",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/app.routes.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "Routes",
"defaultValue": "[\n { path: '', pathMatch: 'full', redirectTo: 'login' },\n { path: 'login', loadComponent: () => \"import('./pages/login/login.page').then(m => m.LoginPage)\" },\n { path: 'dashboard', loadComponent: () => \"import('./pages/dashboard/dashboard.page').then(m => m.DashboardPage)\" },\n { path: 'registratie', loadComponent: () => \"import('./pages/registration-detail/registration-detail.page').then(m => m.RegistrationDetailPage)\" },\n { path: 'herregistratie', loadComponent: () => \"import('./pages/herregistratie/herregistratie.page').then(m => m.HerregistratiePage)\" },\n { path: '**', redirectTo: 'login' },\n]"
}
],
"src/app/core/scenario.interceptor.ts": [
{
"name": "scenarioInterceptor",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/core/scenario.interceptor.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "HttpInterceptorFn",
"defaultValue": "(req, next) => {\n if (!req.url.includes('mock/')) return next(req);\n\n switch (currentScenario()) {\n case 'slow':\n return next(req).pipe(delay(2500));\n case 'loading':\n return next(req).pipe(delay(600_000)); // effectively never resolves\n case 'empty':\n return of(new HttpResponse({ status: 200, body: [] })).pipe(delay(400));\n case 'error':\n return timer(400).pipe(\n switchMap(() => throwError(() =>\n new HttpErrorResponse({ status: 500, statusText: 'Demo-fout', url: req.url }))),\n );\n default:\n return next(req);\n }\n}",
"rawdescription": "Demo-only: rewrites the timing/outcome of mock data requests based on\n?scenario= so loading / empty / error states can be shown on demand.\nReal requests are untouched.",
"description": "<p>Demo-only: rewrites the timing/outcome of mock data requests based on\n?scenario= so loading / empty / error states can be shown on demand.\nReal requests are untouched.</p>\n"
}
],
"src/app/core/scenario.ts": [
{
"name": "VALID",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/core/scenario.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "Scenario[]",
"defaultValue": "['default', 'slow', 'loading', 'empty', 'error']"
}
]
},
"groupedFunctions": {
"src/app/core/scenario.ts": [
{
"name": "currentScenario",
"file": "src/app/core/scenario.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Reads ?scenario= from the URL so a demo can force each async state.</p>\n",
"args": [],
"returnType": "Scenario"
}
]
},
"groupedEnumerations": {},
"groupedTypeAliases": {
"src/app/atoms/alert/alert.component.ts": [
{
"name": "AlertType",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "\"info\" | \"ok\" | \"warning\" | \"error\"",
"file": "src/app/atoms/alert/alert.component.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"kind": 193
}
],
"src/app/core/models.ts": [
{
"name": "RegistrationStatus",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "\"Geregistreerd\" | \"Doorgehaald\" | \"Geschorst\"",
"file": "src/app/core/models.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"kind": 193
}
],
"src/app/core/scenario.ts": [
{
"name": "Scenario",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "\"default\" | \"slow\" | \"loading\" | \"empty\" | \"error\"",
"file": "src/app/core/scenario.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"kind": 193
}
],
"src/app/molecules/async/async.component.ts": [
{
"name": "State",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "\"loading\" | \"error\" | \"empty\" | \"loaded\"",
"file": "src/app/molecules/async/async.component.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"kind": 193
}
],
"src/app/atoms/button/button.component.ts": [
{
"name": "Variant",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "\"primary\" | \"secondary\" | \"subtle\" | \"danger\"",
"file": "src/app/atoms/button/button.component.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"kind": 193
}
]
}
},
"routes": {
"name": "<root>",
"kind": "module",
"children": [
{
"name": "login",
"kind": "route-path",
"filename": "src/app/app.routes.ts"
},
{
"name": "dashboard",
"kind": "route-path",
"filename": "src/app/app.routes.ts"
},
{
"name": "registratie",
"kind": "route-path",
"filename": "src/app/app.routes.ts"
},
{
"name": "herregistratie",
"kind": "route-path",
"filename": "src/app/app.routes.ts"
},
{
"name": "**",
"kind": "route-path",
"filename": "src/app/app.routes.ts"
},
{
"name": "login",
"kind": "route-redirect",
"filename": "src/app/app.routes.ts"
},
{
"name": "login",
"kind": "route-redirect",
"filename": "src/app/app.routes.ts"
}
]
},
"coverage": {
"count": 25,
"status": "low",
"files": [
{
"filePath": "src/app/app.config.ts",
"type": "variable",
"linktype": "miscellaneous",
"linksubtype": "variable",
"name": "appConfig",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/app.routes.ts",
"type": "variable",
"linktype": "miscellaneous",
"linksubtype": "variable",
"name": "routes",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/app.ts",
"type": "component",
"linktype": "component",
"name": "App",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/atoms/alert/alert.component.ts",
"type": "component",
"linktype": "component",
"name": "AlertComponent",
"coveragePercent": 50,
"coverageCount": "1/2",
"status": "medium"
},
{
"filePath": "src/app/atoms/alert/alert.component.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "AlertType",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/atoms/button/button.component.ts",
"type": "component",
"linktype": "component",
"name": "ButtonComponent",
"coveragePercent": 25,
"coverageCount": "1/4",
"status": "low"
},
{
"filePath": "src/app/atoms/button/button.component.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "Variant",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/atoms/heading/heading.component.ts",
"type": "component",
"linktype": "component",
"name": "HeadingComponent",
"coveragePercent": 50,
"coverageCount": "1/2",
"status": "medium"
},
{
"filePath": "src/app/atoms/link/link.component.ts",
"type": "component",
"linktype": "component",
"name": "LinkComponent",
"coveragePercent": 50,
"coverageCount": "1/2",
"status": "medium"
},
{
"filePath": "src/app/atoms/skeleton/skeleton.component.ts",
"type": "component",
"linktype": "component",
"name": "SkeletonComponent",
"coveragePercent": 10,
"coverageCount": "1/10",
"status": "low"
},
{
"filePath": "src/app/atoms/spinner/spinner.component.ts",
"type": "component",
"linktype": "component",
"name": "SpinnerComponent",
"coveragePercent": 16,
"coverageCount": "1/6",
"status": "low"
},
{
"filePath": "src/app/atoms/status-badge/status-badge.component.ts",
"type": "component",
"linktype": "component",
"name": "StatusBadgeComponent",
"coveragePercent": 33,
"coverageCount": "1/3",
"status": "medium"
},
{
"filePath": "src/app/atoms/text-input/text-input.component.ts",
"type": "component",
"linktype": "component",
"name": "TextInputComponent",
"coveragePercent": 7,
"coverageCount": "1/14",
"status": "low"
},
{
"filePath": "src/app/core/models.ts",
"type": "interface",
"linktype": "interface",
"name": "Aantekening",
"coveragePercent": 0,
"coverageCount": "0/4",
"status": "low"
},
{
"filePath": "src/app/core/models.ts",
"type": "interface",
"linktype": "interface",
"name": "Registration",
"coveragePercent": 0,
"coverageCount": "0/8",
"status": "low"
},
{
"filePath": "src/app/core/models.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "RegistrationStatus",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/core/registration.service.ts",
"type": "injectable",
"linktype": "injectable",
"name": "RegistrationService",
"coveragePercent": 33,
"coverageCount": "1/3",
"status": "medium"
},
{
"filePath": "src/app/core/scenario.interceptor.ts",
"type": "variable",
"linktype": "miscellaneous",
"linksubtype": "variable",
"name": "scenarioInterceptor",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/core/scenario.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "currentScenario",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/core/scenario.ts",
"type": "variable",
"linktype": "miscellaneous",
"linksubtype": "variable",
"name": "VALID",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/core/scenario.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "Scenario",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/molecules/async/async.component.ts",
"type": "component",
"linktype": "component",
"name": "AsyncComponent",
"coveragePercent": 10,
"coverageCount": "1/10",
"status": "low"
},
{
"filePath": "src/app/molecules/async/async.component.ts",
"type": "directive",
"linktype": "directive",
"name": "AsyncEmptyDirective",
"coveragePercent": 0,
"coverageCount": "0/3",
"status": "low"
},
{
"filePath": "src/app/molecules/async/async.component.ts",
"type": "directive",
"linktype": "directive",
"name": "AsyncErrorDirective",
"coveragePercent": 0,
"coverageCount": "0/3",
"status": "low"
},
{
"filePath": "src/app/molecules/async/async.component.ts",
"type": "directive",
"linktype": "directive",
"name": "AsyncLoadedDirective",
"coveragePercent": 0,
"coverageCount": "0/3",
"status": "low"
},
{
"filePath": "src/app/molecules/async/async.component.ts",
"type": "directive",
"linktype": "directive",
"name": "AsyncLoadingDirective",
"coveragePercent": 0,
"coverageCount": "0/3",
"status": "low"
},
{
"filePath": "src/app/molecules/async/async.component.ts",
"type": "variable",
"linktype": "miscellaneous",
"linksubtype": "variable",
"name": "ASYNC",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/molecules/async/async.component.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "State",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/molecules/data-row/data-row.component.ts",
"type": "component",
"linktype": "component",
"name": "DataRowComponent",
"coveragePercent": 33,
"coverageCount": "1/3",
"status": "medium"
},
{
"filePath": "src/app/molecules/form-field/form-field.component.ts",
"type": "component",
"linktype": "component",
"name": "FormFieldComponent",
"coveragePercent": 20,
"coverageCount": "1/5",
"status": "low"
},
{
"filePath": "src/app/organisms/change-request-form/change-request-form.component.ts",
"type": "component",
"linktype": "component",
"name": "ChangeRequestFormComponent",
"coveragePercent": 14,
"coverageCount": "1/7",
"status": "low"
},
{
"filePath": "src/app/organisms/login-form/login-form.component.ts",
"type": "component",
"linktype": "component",
"name": "LoginFormComponent",
"coveragePercent": 25,
"coverageCount": "1/4",
"status": "low"
},
{
"filePath": "src/app/organisms/registration-summary/registration-summary.component.ts",
"type": "component",
"linktype": "component",
"name": "RegistrationSummaryComponent",
"coveragePercent": 50,
"coverageCount": "1/2",
"status": "medium"
},
{
"filePath": "src/app/organisms/registration-table/registration-table.component.ts",
"type": "component",
"linktype": "component",
"name": "RegistrationTableComponent",
"coveragePercent": 50,
"coverageCount": "1/2",
"status": "medium"
},
{
"filePath": "src/app/organisms/site-footer/site-footer.component.ts",
"type": "component",
"linktype": "component",
"name": "SiteFooterComponent",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/organisms/site-header/site-header.component.ts",
"type": "component",
"linktype": "component",
"name": "SiteHeaderComponent",
"coveragePercent": 50,
"coverageCount": "1/2",
"status": "medium"
},
{
"filePath": "src/app/pages/dashboard/dashboard.page.ts",
"type": "component",
"linktype": "component",
"name": "DashboardPage",
"coveragePercent": 0,
"coverageCount": "0/6",
"status": "low"
},
{
"filePath": "src/app/pages/herregistratie/herregistratie.page.ts",
"type": "component",
"linktype": "component",
"name": "HerregistratiePage",
"coveragePercent": 16,
"coverageCount": "1/6",
"status": "low"
},
{
"filePath": "src/app/pages/login/login.page.ts",
"type": "component",
"linktype": "component",
"name": "LoginPage",
"coveragePercent": 0,
"coverageCount": "0/3",
"status": "low"
},
{
"filePath": "src/app/pages/registration-detail/registration-detail.page.ts",
"type": "component",
"linktype": "component",
"name": "RegistrationDetailPage",
"coveragePercent": 0,
"coverageCount": "0/5",
"status": "low"
},
{
"filePath": "src/app/templates/page-layout/page-layout.component.ts",
"type": "component",
"linktype": "component",
"name": "PageLayoutComponent",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/templates/page-shell/page-shell.component.ts",
"type": "component",
"linktype": "component",
"name": "PageShellComponent",
"coveragePercent": 16,
"coverageCount": "1/6",
"status": "low"
}
]
}
}