Files
atomic-design-poc/documentation.json
Edwin van den Houdt 6bd6e854c7 Regenerate compodoc documentation.json
Reflects the new types, components, and pages from the impossible-states work.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-25 16:56:17 +02:00

5105 lines
288 KiB
JSON

{
"pipes": [],
"interfaces": [
{
"name": "Aantekening",
"id": "interface-Aantekening-2ecca36e413e22c1c5967d07b811fa4171ff578eb6b47a7275723bcca44e93a2db27d77a765b82e5f6182492464cc8b9268c9724e13b400718d30da7bc4ba50c",
"file": "src/app/core/models.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "interface",
"sourceCode": "export type RegistrationStatus =\n | { tag: 'Geregistreerd'; herregistratieDatum: string } // ISO date\n | { tag: 'Geschorst'; geschorstTot: string; reden: string }\n | { tag: 'Doorgehaald'; doorgehaaldOp: string; reden: string };\n\n/** Just the discriminant — for atoms that only need the label/color. */\nexport type StatusTag = RegistrationStatus['tag'];\n\nexport interface Registration {\n bigNummer: string;\n naam: string;\n beroep: string; // arts, verpleegkundige, apotheker, ...\n registratiedatum: string; // ISO date\n geboortedatum: string;\n status: RegistrationStatus;\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": 28
},
{
"name": "omschrijving",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 27
},
{
"name": "type",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 26
}
],
"indexSignatures": [],
"kind": 172,
"methods": [],
"extends": []
},
{
"name": "ChangeRequest",
"id": "interface-ChangeRequest-e366867f9f2a82d4c6cafc6fbdce9749e7775f651192c4de62cefc40a237a6e2c6772537e64a4aeeb6667ffa33d9a69ee6114c69160674807408090b1cbc283a",
"file": "src/app/organisms/change-request-form/change-request-form.component.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "interface",
"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';\nimport { Postcode, parsePostcode } from '../../core/parse';\n\n/** A submitted change request carries a *parsed* postcode (branded Postcode),\n not a raw string — downstream code can't receive an unvalidated one. */\nexport interface ChangeRequest {\n street: string;\n zip: Postcode;\n city: string;\n}\n\n/** Organism: change-request (adreswijziging) form. Reuses the same form-field\n molecule + text-input/button atoms as the login form. Field errors come\n straight from the parser's Result — no parallel \"is it valid\" flag to drift. */\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\" [error]=\"zipError()\">\n <app-text-input inputId=\"zip\" [(ngModel)]=\"zip\" name=\"zip\" placeholder=\"1234 AB\" [invalid]=\"!!zipError()\" />\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 zipError = signal('');\n submitted = output<ChangeRequest>();\n\n onSubmit() {\n const street = this.street.trim();\n this.streetError.set(street ? '' : 'Vul straat en huisnummer in.');\n\n const postcode = parsePostcode(this.zip);\n this.zipError.set(postcode.ok ? '' : postcode.error);\n\n if (!street || !postcode.ok) return;\n this.submitted.emit({ street, zip: postcode.value, city: this.city.trim() });\n }\n}\n",
"properties": [
{
"name": "city",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 14
},
{
"name": "street",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 12
},
{
"name": "zip",
"deprecated": false,
"deprecationMessage": "",
"type": "Postcode",
"indexKey": "",
"optional": false,
"description": "",
"line": 13
}
],
"indexSignatures": [],
"kind": 172,
"description": "<p>A submitted change request carries a <em>parsed</em> postcode (branded Postcode),\nnot a raw string — downstream code can&#39;t receive an unvalidated one.</p>\n",
"rawdescription": "\nA submitted change request carries a *parsed* postcode (branded Postcode),\nnot a raw string — downstream code can't receive an unvalidated one.",
"methods": [],
"extends": []
},
{
"name": "Draft",
"id": "interface-Draft-6fcaabe58c126a645622a7a77942a847877e8d80e60ddd45cb9ba4c247cede3ee197def542b645ef02b0ce5dd0deab6c644edddf2f37dec67a129b27ba53bb23",
"file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "interface",
"sourceCode": "import { Result } from '../../core/fp';\nimport { Uren, parseUren } from '../../core/parse';\n\n/** What the user is typing (raw, possibly invalid). */\nexport interface Draft {\n uren: string;\n punten: string;\n}\n\n/** What we have AFTER parsing — branded/typed, guaranteed valid. */\nexport interface Valid {\n uren: Uren;\n punten: number;\n}\n\n/**\n * The whole wizard as one tagged union. `step` and `errors` exist ONLY while\n * Editing; Submitting/Submitted/Failed carry a `Valid` payload and nothing else.\n * So \"submitting while a field is invalid\" or \"showing the success screen with\n * errors set\" are unrepresentable — the bug class is gone by construction.\n */\nexport type WizardState =\n | { tag: 'Editing'; step: 1 | 2; draft: Draft; errors: Partial<Record<keyof Draft, string>> }\n | { tag: 'Submitting'; data: Valid }\n | { tag: 'Submitted'; data: Valid }\n | { tag: 'Failed'; data: Valid; error: string };\n\nexport const initial: WizardState = { tag: 'Editing', step: 1, draft: { uren: '', punten: '' }, errors: {} };\n\n/** Parse every field; on success hand back a Valid, else the per-field errors. */\nfunction validate(draft: Draft): Result<Partial<Record<keyof Draft, string>>, Valid> {\n const uren = parseUren(draft.uren);\n const punten = parseUren(draft.punten);\n const errors: Partial<Record<keyof Draft, string>> = {};\n if (!uren.ok) errors.uren = uren.error;\n if (!punten.ok) errors.punten = punten.error;\n if (uren.ok && punten.ok) return { ok: true, value: { uren: uren.value, punten: punten.value } };\n return { ok: false, error: errors };\n}\n\n/** Step 1 → 2: only advance if the uren field parses. Illegal elsewhere = no-op. */\nexport function next(s: WizardState): WizardState {\n if (s.tag !== 'Editing' || s.step !== 1) return s;\n const uren = parseUren(s.draft.uren);\n return uren.ok\n ? { ...s, step: 2, errors: {} }\n : { ...s, errors: { uren: uren.error } };\n}\n\nexport function back(s: WizardState): WizardState {\n if (s.tag !== 'Editing' || s.step !== 2) return s;\n return { ...s, step: 1, errors: {} };\n}\n\n/** Step 2 submit: parse everything; move to Submitting only with Valid data. */\nexport function submit(s: WizardState): WizardState {\n if (s.tag !== 'Editing' || s.step !== 2) return s;\n const result = validate(s.draft);\n return result.ok ? { tag: 'Submitting', data: result.value } : { ...s, errors: result.error };\n}\n\n/** Resolve the async submit. Only meaningful while Submitting. */\nexport function resolve(s: WizardState, r: Result<string, void>): WizardState {\n if (s.tag !== 'Submitting') return s;\n return r.ok ? { tag: 'Submitted', data: s.data } : { tag: 'Failed', data: s.data, error: r.error };\n}\n",
"properties": [
{
"name": "punten",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 7
},
{
"name": "uren",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 6
}
],
"indexSignatures": [],
"kind": 172,
"description": "<p>What the user is typing (raw, possibly invalid).</p>\n",
"rawdescription": "\nWhat the user is typing (raw, possibly invalid).",
"methods": [],
"extends": []
},
{
"name": "Registration",
"id": "interface-Registration-2ecca36e413e22c1c5967d07b811fa4171ff578eb6b47a7275723bcca44e93a2db27d77a765b82e5f6182492464cc8b9268c9724e13b400718d30da7bc4ba50c",
"file": "src/app/core/models.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "interface",
"sourceCode": "export type RegistrationStatus =\n | { tag: 'Geregistreerd'; herregistratieDatum: string } // ISO date\n | { tag: 'Geschorst'; geschorstTot: string; reden: string }\n | { tag: 'Doorgehaald'; doorgehaaldOp: string; reden: string };\n\n/** Just the discriminant — for atoms that only need the label/color. */\nexport type StatusTag = RegistrationStatus['tag'];\n\nexport interface Registration {\n bigNummer: string;\n naam: string;\n beroep: string; // arts, verpleegkundige, apotheker, ...\n registratiedatum: string; // ISO date\n geboortedatum: string;\n status: RegistrationStatus;\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": 19
},
{
"name": "bigNummer",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 17
},
{
"name": "geboortedatum",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 21
},
{
"name": "naam",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 18
},
{
"name": "registratiedatum",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 20
},
{
"name": "status",
"deprecated": false,
"deprecationMessage": "",
"type": "RegistrationStatus",
"indexKey": "",
"optional": false,
"description": "",
"line": 22
}
],
"indexSignatures": [],
"kind": 172,
"methods": [],
"extends": []
},
{
"name": "Valid",
"id": "interface-Valid-6fcaabe58c126a645622a7a77942a847877e8d80e60ddd45cb9ba4c247cede3ee197def542b645ef02b0ce5dd0deab6c644edddf2f37dec67a129b27ba53bb23",
"file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "interface",
"sourceCode": "import { Result } from '../../core/fp';\nimport { Uren, parseUren } from '../../core/parse';\n\n/** What the user is typing (raw, possibly invalid). */\nexport interface Draft {\n uren: string;\n punten: string;\n}\n\n/** What we have AFTER parsing — branded/typed, guaranteed valid. */\nexport interface Valid {\n uren: Uren;\n punten: number;\n}\n\n/**\n * The whole wizard as one tagged union. `step` and `errors` exist ONLY while\n * Editing; Submitting/Submitted/Failed carry a `Valid` payload and nothing else.\n * So \"submitting while a field is invalid\" or \"showing the success screen with\n * errors set\" are unrepresentable — the bug class is gone by construction.\n */\nexport type WizardState =\n | { tag: 'Editing'; step: 1 | 2; draft: Draft; errors: Partial<Record<keyof Draft, string>> }\n | { tag: 'Submitting'; data: Valid }\n | { tag: 'Submitted'; data: Valid }\n | { tag: 'Failed'; data: Valid; error: string };\n\nexport const initial: WizardState = { tag: 'Editing', step: 1, draft: { uren: '', punten: '' }, errors: {} };\n\n/** Parse every field; on success hand back a Valid, else the per-field errors. */\nfunction validate(draft: Draft): Result<Partial<Record<keyof Draft, string>>, Valid> {\n const uren = parseUren(draft.uren);\n const punten = parseUren(draft.punten);\n const errors: Partial<Record<keyof Draft, string>> = {};\n if (!uren.ok) errors.uren = uren.error;\n if (!punten.ok) errors.punten = punten.error;\n if (uren.ok && punten.ok) return { ok: true, value: { uren: uren.value, punten: punten.value } };\n return { ok: false, error: errors };\n}\n\n/** Step 1 → 2: only advance if the uren field parses. Illegal elsewhere = no-op. */\nexport function next(s: WizardState): WizardState {\n if (s.tag !== 'Editing' || s.step !== 1) return s;\n const uren = parseUren(s.draft.uren);\n return uren.ok\n ? { ...s, step: 2, errors: {} }\n : { ...s, errors: { uren: uren.error } };\n}\n\nexport function back(s: WizardState): WizardState {\n if (s.tag !== 'Editing' || s.step !== 2) return s;\n return { ...s, step: 1, errors: {} };\n}\n\n/** Step 2 submit: parse everything; move to Submitting only with Valid data. */\nexport function submit(s: WizardState): WizardState {\n if (s.tag !== 'Editing' || s.step !== 2) return s;\n const result = validate(s.draft);\n return result.ok ? { tag: 'Submitting', data: result.value } : { ...s, errors: result.error };\n}\n\n/** Resolve the async submit. Only meaningful while Submitting. */\nexport function resolve(s: WizardState, r: Result<string, void>): WizardState {\n if (s.tag !== 'Submitting') return s;\n return r.ok ? { tag: 'Submitted', data: s.data } : { tag: 'Failed', data: s.data, error: r.error };\n}\n",
"properties": [
{
"name": "punten",
"deprecated": false,
"deprecationMessage": "",
"type": "number",
"indexKey": "",
"optional": false,
"description": "",
"line": 13
},
{
"name": "uren",
"deprecated": false,
"deprecationMessage": "",
"type": "Uren",
"indexKey": "",
"optional": false,
"description": "",
"line": 12
}
],
"indexSignatures": [],
"kind": 172,
"description": "<p>What we have AFTER parsing — branded/typed, guaranteed valid.</p>\n",
"rawdescription": "\nWhat we have AFTER parsing — branded/typed, guaranteed valid.",
"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-2c3bb2a3fee90c1c02ec41aacfd672fcdf754eccc5e8761a7590b96d19724dc55523a26a1eff26c0caeaf28a297042b8fdf7e78d70272079bd5465f72e58dbc9",
"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';\nimport { fromResource, foldRemote } from '../../core/remote-data';\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\n/**\n * Renders exactly ONE of loading / empty / error / loaded for a signal-based\n * resource (e.g. httpResource). Built on a RemoteData tagged union (see\n * core/remote-data.ts), so the states are mutually exclusive by construction —\n * the UI can never show two at once (\"impossible states\"). Unprovided slots\n * fall back to sensible defaults.\n */\n@Component({\n selector: 'app-async',\n imports: [NgTemplateOutlet, SpinnerComponent, AlertComponent, ButtonComponent],\n template: `\n @switch (rd().tag) {\n @case ('Loading') {\n @if (loadingTpl()) { <ng-container [ngTemplateOutlet]=\"loadingTpl()!.tpl\" /> }\n @else { <app-spinner /> }\n }\n @case ('Failure') {\n @if (errorTpl()) {\n <ng-container [ngTemplateOutlet]=\"errorTpl()!.tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: 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 ('Success') {\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 // Single source of truth: the resource projected into a RemoteData union.\n protected rd = computed(() => fromResource(this.resource(), this.isEmpty()));\n\n // value/error are pulled out via the exhaustive fold — only Success carries a\n // value, only Failure carries an error, so these can't lie.\n protected value = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: () => undefined, success: (v) => v }),\n );\n protected error = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: (e) => e, success: () => undefined }),\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": 20,
"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": 19,
"jsdoctags": [
{
"name": "tpl",
"type": "TemplateRef<unknown>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
},
{
"name": "AsyncErrorDirective",
"id": "directive-AsyncErrorDirective-2c3bb2a3fee90c1c02ec41aacfd672fcdf754eccc5e8761a7590b96d19724dc55523a26a1eff26c0caeaf28a297042b8fdf7e78d70272079bd5465f72e58dbc9",
"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';\nimport { fromResource, foldRemote } from '../../core/remote-data';\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\n/**\n * Renders exactly ONE of loading / empty / error / loaded for a signal-based\n * resource (e.g. httpResource). Built on a RemoteData tagged union (see\n * core/remote-data.ts), so the states are mutually exclusive by construction —\n * the UI can never show two at once (\"impossible states\"). Unprovided slots\n * fall back to sensible defaults.\n */\n@Component({\n selector: 'app-async',\n imports: [NgTemplateOutlet, SpinnerComponent, AlertComponent, ButtonComponent],\n template: `\n @switch (rd().tag) {\n @case ('Loading') {\n @if (loadingTpl()) { <ng-container [ngTemplateOutlet]=\"loadingTpl()!.tpl\" /> }\n @else { <app-spinner /> }\n }\n @case ('Failure') {\n @if (errorTpl()) {\n <ng-container [ngTemplateOutlet]=\"errorTpl()!.tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: 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 ('Success') {\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 // Single source of truth: the resource projected into a RemoteData union.\n protected rd = computed(() => fromResource(this.resource(), this.isEmpty()));\n\n // value/error are pulled out via the exhaustive fold — only Success carries a\n // value, only Failure carries an error, so these can't lie.\n protected value = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: () => undefined, success: (v) => v }),\n );\n protected error = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: (e) => e, success: () => undefined }),\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": 24,
"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": 23,
"jsdoctags": [
{
"name": "tpl",
"type": "TemplateRef<literal type>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
},
{
"name": "AsyncLoadedDirective",
"id": "directive-AsyncLoadedDirective-2c3bb2a3fee90c1c02ec41aacfd672fcdf754eccc5e8761a7590b96d19724dc55523a26a1eff26c0caeaf28a297042b8fdf7e78d70272079bd5465f72e58dbc9",
"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';\nimport { fromResource, foldRemote } from '../../core/remote-data';\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\n/**\n * Renders exactly ONE of loading / empty / error / loaded for a signal-based\n * resource (e.g. httpResource). Built on a RemoteData tagged union (see\n * core/remote-data.ts), so the states are mutually exclusive by construction —\n * the UI can never show two at once (\"impossible states\"). Unprovided slots\n * fall back to sensible defaults.\n */\n@Component({\n selector: 'app-async',\n imports: [NgTemplateOutlet, SpinnerComponent, AlertComponent, ButtonComponent],\n template: `\n @switch (rd().tag) {\n @case ('Loading') {\n @if (loadingTpl()) { <ng-container [ngTemplateOutlet]=\"loadingTpl()!.tpl\" /> }\n @else { <app-spinner /> }\n }\n @case ('Failure') {\n @if (errorTpl()) {\n <ng-container [ngTemplateOutlet]=\"errorTpl()!.tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: 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 ('Success') {\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 // Single source of truth: the resource projected into a RemoteData union.\n protected rd = computed(() => fromResource(this.resource(), this.isEmpty()));\n\n // value/error are pulled out via the exhaustive fold — only Success carries a\n // value, only Failure carries an error, so these can't lie.\n protected value = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: () => undefined, success: (v) => v }),\n );\n protected error = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: (e) => e, success: () => undefined }),\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": 12,
"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": 11,
"jsdoctags": [
{
"name": "tpl",
"type": "TemplateRef<literal type>",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
},
{
"name": "AsyncLoadingDirective",
"id": "directive-AsyncLoadingDirective-2c3bb2a3fee90c1c02ec41aacfd672fcdf754eccc5e8761a7590b96d19724dc55523a26a1eff26c0caeaf28a297042b8fdf7e78d70272079bd5465f72e58dbc9",
"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';\nimport { fromResource, foldRemote } from '../../core/remote-data';\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\n/**\n * Renders exactly ONE of loading / empty / error / loaded for a signal-based\n * resource (e.g. httpResource). Built on a RemoteData tagged union (see\n * core/remote-data.ts), so the states are mutually exclusive by construction —\n * the UI can never show two at once (\"impossible states\"). Unprovided slots\n * fall back to sensible defaults.\n */\n@Component({\n selector: 'app-async',\n imports: [NgTemplateOutlet, SpinnerComponent, AlertComponent, ButtonComponent],\n template: `\n @switch (rd().tag) {\n @case ('Loading') {\n @if (loadingTpl()) { <ng-container [ngTemplateOutlet]=\"loadingTpl()!.tpl\" /> }\n @else { <app-spinner /> }\n }\n @case ('Failure') {\n @if (errorTpl()) {\n <ng-container [ngTemplateOutlet]=\"errorTpl()!.tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: 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 ('Success') {\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 // Single source of truth: the resource projected into a RemoteData union.\n protected rd = computed(() => fromResource(this.resource(), this.isEmpty()));\n\n // value/error are pulled out via the exhaustive fold — only Success carries a\n // value, only Failure carries an error, so these can't lie.\n protected value = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: () => undefined, success: (v) => v }),\n );\n protected error = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: (e) => e, success: () => undefined }),\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": 16,
"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": 15,
"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-2c3bb2a3fee90c1c02ec41aacfd672fcdf754eccc5e8761a7590b96d19724dc55523a26a1eff26c0caeaf28a297042b8fdf7e78d70272079bd5465f72e58dbc9",
"file": "src/app/molecules/async/async.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-async",
"styleUrls": [],
"styles": [],
"template": "@switch (rd().tag) {\n @case ('Loading') {\n @if (loadingTpl()) { <ng-container [ngTemplateOutlet]=\"loadingTpl()!.tpl\" /> }\n @else { <app-spinner /> }\n }\n @case ('Failure') {\n @if (errorTpl()) {\n <ng-container [ngTemplateOutlet]=\"errorTpl()!.tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: 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 ('Success') {\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": "error",
"defaultValue": "computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: (e) => e, success: () => undefined }),\n )",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 82,
"modifierKind": [
124
]
},
{
"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": "rd",
"defaultValue": "computed(() => fromResource(this.resource(), this.isEmpty()))",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 75,
"modifierKind": [
124
]
},
{
"name": "retry",
"defaultValue": "() => {...}",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 86
},
{
"name": "value",
"defaultValue": "computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: () => undefined, success: (v) => v }),\n )",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 79,
"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). Built on a RemoteData tagged union (see\ncore/remote-data.ts), so the states are mutually exclusive by construction —\nthe UI can never show two at once (&quot;impossible states&quot;). Unprovided slots\nfall back to sensible defaults.</p>\n",
"rawdescription": "\n\nRenders exactly ONE of loading / empty / error / loaded for a signal-based\nresource (e.g. httpResource). Built on a RemoteData tagged union (see\ncore/remote-data.ts), so the states are mutually exclusive by construction —\nthe UI can never show two at once (\"impossible states\"). Unprovided slots\nfall 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';\nimport { fromResource, foldRemote } from '../../core/remote-data';\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\n/**\n * Renders exactly ONE of loading / empty / error / loaded for a signal-based\n * resource (e.g. httpResource). Built on a RemoteData tagged union (see\n * core/remote-data.ts), so the states are mutually exclusive by construction —\n * the UI can never show two at once (\"impossible states\"). Unprovided slots\n * fall back to sensible defaults.\n */\n@Component({\n selector: 'app-async',\n imports: [NgTemplateOutlet, SpinnerComponent, AlertComponent, ButtonComponent],\n template: `\n @switch (rd().tag) {\n @case ('Loading') {\n @if (loadingTpl()) { <ng-container [ngTemplateOutlet]=\"loadingTpl()!.tpl\" /> }\n @else { <app-spinner /> }\n }\n @case ('Failure') {\n @if (errorTpl()) {\n <ng-container [ngTemplateOutlet]=\"errorTpl()!.tpl\"\n [ngTemplateOutletContext]=\"{ $implicit: 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 ('Success') {\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 // Single source of truth: the resource projected into a RemoteData union.\n protected rd = computed(() => fromResource(this.resource(), this.isEmpty()));\n\n // value/error are pulled out via the exhaustive fold — only Success carries a\n // value, only Failure carries an error, so these can't lie.\n protected value = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: () => undefined, success: (v) => v }),\n );\n protected error = computed(() =>\n foldRemote(this.rd(), { loading: () => undefined, empty: () => undefined, failure: (e) => e, success: () => undefined }),\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-e366867f9f2a82d4c6cafc6fbdce9749e7775f651192c4de62cefc40a237a6e2c6772537e64a4aeeb6667ffa33d9a69ee6114c69160674807408090b1cbc283a",
"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\" [error]=\"zipError()\">\n <app-text-input inputId=\"zip\" [(ngModel)]=\"zip\" name=\"zip\" placeholder=\"1234 AB\" [invalid]=\"!!zipError()\" />\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": "ChangeRequest",
"indexKey": "",
"optional": false,
"description": "",
"line": 47,
"required": false
}
],
"propertiesClass": [
{
"name": "city",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 44
},
{
"name": "street",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 42
},
{
"name": "streetError",
"defaultValue": "signal('')",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 45
},
{
"name": "zip",
"defaultValue": "''",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 43
},
{
"name": "zipError",
"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": "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. Field errors come\nstraight from the parser&#39;s Result — no parallel &quot;is it valid&quot; flag to drift.</p>\n",
"rawdescription": "\nOrganism: change-request (adreswijziging) form. Reuses the same form-field\nmolecule + text-input/button atoms as the login form. Field errors come\nstraight from the parser's Result — no parallel \"is it valid\" flag to drift.",
"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';\nimport { Postcode, parsePostcode } from '../../core/parse';\n\n/** A submitted change request carries a *parsed* postcode (branded Postcode),\n not a raw string — downstream code can't receive an unvalidated one. */\nexport interface ChangeRequest {\n street: string;\n zip: Postcode;\n city: string;\n}\n\n/** Organism: change-request (adreswijziging) form. Reuses the same form-field\n molecule + text-input/button atoms as the login form. Field errors come\n straight from the parser's Result — no parallel \"is it valid\" flag to drift. */\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\" [error]=\"zipError()\">\n <app-text-input inputId=\"zip\" [(ngModel)]=\"zip\" name=\"zip\" placeholder=\"1234 AB\" [invalid]=\"!!zipError()\" />\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 zipError = signal('');\n submitted = output<ChangeRequest>();\n\n onSubmit() {\n const street = this.street.trim();\n this.streetError.set(street ? '' : 'Vul straat en huisnummer in.');\n\n const postcode = parsePostcode(this.zip);\n this.zipError.set(postcode.ok ? '' : postcode.error);\n\n if (!street || !postcode.ok) return;\n this.submitted.emit({ street, zip: postcode.value, city: this.city.trim() });\n }\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "ConceptsPage",
"id": "component-ConceptsPage-6ebc285de6e31b814c5a5499d296626fc51bce08971ae012bfa0176580e767b207f13bbc91e38ad1d616cb28e386208e7686eef9bdf8f5e0ddf89b7ee67362cb",
"file": "src/app/pages/concepts/concepts.page.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-concepts-page",
"styleUrls": [],
"styles": [
"\n .cols { display:flex; flex-wrap:wrap; gap:1.5rem; margin:1rem 0 2.5rem }\n .col { flex:1 1 20rem; min-width:18rem }\n .tag { font-weight:700; font-size:0.8rem; text-transform:uppercase; letter-spacing:0.04em }\n .bad { color:var(--rhc-color-rood-500) }\n .good { color:var(--rhc-color-groen-500) }\n pre { background:var(--rhc-color-grijs-100,#f3f3f3); padding:1rem; border-radius:4px; overflow:auto; font-size:0.85rem }\n "
],
"template": "<app-page-shell heading=\"Onmogelijke toestanden onmogelijk maken\" backLink=\"/dashboard\">\n <app-alert type=\"info\">\n Vier functionele patronen die met atomic design makkelijker te tonen zijn — telkens \"fout\"\n (de oude vorm liet het toe) naast \"goed\" (het type maakt het onmogelijk).\n </app-alert>\n\n <!-- 1. Discriminated unions -->\n <app-heading [level]=\"2\">1 · Discriminated unions</app-heading>\n <div class=\"cols\">\n <div class=\"col\">\n <p class=\"tag bad\">Fout — vlakke interface</p>\n <pre>{{ unionBad }}</pre>\n <p class=\"rhc-paragraph\">Een doorgehaalde registratie houdt tóch een herregistratiedatum: onmogelijke toestand.</p>\n </div>\n <div class=\"col\">\n <p class=\"tag good\">Goed — sum type</p>\n <app-registration-summary [reg]=\"doorgehaald\" />\n <p class=\"rhc-paragraph\">De variant <code>Doorgehaald</code> kent geen herregistratiedatum, dus de rij bestaat simpelweg niet.</p>\n </div>\n </div>\n\n <!-- 2. RemoteData fold -->\n <app-heading [level]=\"2\">2 · RemoteData fold</app-heading>\n <div class=\"cols\">\n <div class=\"col\">\n <p class=\"tag good\">Eén molecuul, vier elkaar uitsluitende toestanden</p>\n <p class=\"tag\">Loading</p>\n <app-async [resource]=\"loadingRes\"><ng-template appAsyncLoaded let-v>{{ v }}</ng-template><ng-template appAsyncLoading><app-skeleton [count]=\"2\" height=\"1.2rem\" [delay]=\"0\" /></ng-template></app-async>\n <p class=\"tag\">Empty</p>\n <app-async [resource]=\"emptyRes\" [isEmpty]=\"isEmpty\"><ng-template appAsyncLoaded let-v>{{ v }}</ng-template></app-async>\n <p class=\"tag\">Failure</p>\n <app-async [resource]=\"errorRes\"><ng-template appAsyncLoaded let-v>{{ v }}</ng-template></app-async>\n <p class=\"tag\">Success</p>\n <app-async [resource]=\"successRes\" [isEmpty]=\"isEmpty\"><ng-template appAsyncLoaded let-v><ul class=\"rhc-unordered-list\">@for (i of v; track i) {<li>{{ i }}</li>}</ul></ng-template></app-async>\n </div>\n <div class=\"col\">\n <p class=\"tag good\">De exhaustieve fold</p>\n <pre>{{ foldCode }}</pre>\n <p class=\"rhc-paragraph\">Een nieuwe variant toevoegen breekt de compile via <code>assertNever</code> tot je hem afhandelt.</p>\n </div>\n </div>\n\n <!-- 3. Parse, don't validate -->\n <app-heading [level]=\"2\">3 · Parse, don't validate</app-heading>\n <div class=\"cols\">\n <div class=\"col\">\n <p class=\"tag good\">Smart constructor → Result</p>\n <app-text-input inputId=\"pc\" [ngModel]=\"raw()\" (ngModelChange)=\"raw.set($event)\" name=\"pc\" placeholder=\"Typ een postcode, bijv. 1234 AB\" />\n </div>\n <div class=\"col\">\n @if (parsed().ok) {\n <p class=\"tag good\">ok</p>\n <pre>Postcode = \"{{ parsed().ok ? $any(parsed()).value : '' }}\"</pre>\n <p class=\"rhc-paragraph\">Een gevalideerde <code>Postcode</code> is een ander type dan een ruwe string.</p>\n } @else {\n <p class=\"tag bad\">err</p>\n <pre>{{ $any(parsed()).error }}</pre>\n }\n </div>\n </div>\n\n <!-- 4. State machine / wizard -->\n <app-heading [level]=\"2\">4 · Form als state machine</app-heading>\n <div class=\"cols\">\n <div class=\"col\">\n <p class=\"tag bad\">Fout — losse booleans</p>\n <pre>{{ machineBad }}</pre>\n <p class=\"rhc-paragraph\">Niets verhindert \"submitting\" mét validatiefouten of een successcherm met errors.</p>\n </div>\n <div class=\"col\">\n <p class=\"tag good\">Goed — één tagged union stuurt de UI</p>\n <app-herregistratie-wizard />\n </div>\n </div>\n</app-page-shell>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [],
"propertiesClass": [
{
"name": "doorgehaald",
"defaultValue": "{\n bigNummer: '19012345601', naam: 'Dr. A. (Anna) de Vries', beroep: 'Arts',\n registratiedatum: '2012-09-01', geboortedatum: '1985-03-14',\n status: { tag: 'Doorgehaald', doorgehaaldOp: '2024-05-01', reden: 'Op eigen verzoek' },\n }",
"deprecated": false,
"deprecationMessage": "",
"type": "Registration",
"indexKey": "",
"optional": false,
"description": "",
"line": 117
},
{
"name": "emptyRes",
"defaultValue": "fakeResource<string[]>('resolved', [])",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 124
},
{
"name": "errorRes",
"defaultValue": "fakeResource<string[]>('error', undefined, new Error('Demo'))",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 125
},
{
"name": "foldCode",
"defaultValue": "`foldRemote(rd, {\n loading: () => spinner,\n empty: () => 'geen data',\n failure: (e) => alert(e),\n success: (v) => render(v),\n}); // mist er één → compile-fout`",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 136
},
{
"name": "isEmpty",
"defaultValue": "() => {...}",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 115
},
{
"name": "loadingRes",
"defaultValue": "fakeResource<string[]>('loading')",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 123
},
{
"name": "machineBad",
"defaultValue": "`submitting = signal(false);\nsubmitted = signal(false);\nerrors = signal<...>({});\n// submitting === true && errors.size > 0 ? 🤷`",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 143
},
{
"name": "parsed",
"defaultValue": "computed(() => parsePostcode(this.raw()))",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 129
},
{
"name": "raw",
"defaultValue": "signal('')",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 128
},
{
"name": "successRes",
"defaultValue": "fakeResource<string[]>('resolved', ['Huisartsgeneeskunde', 'Spoedeisende hulp'])",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 126
},
{
"name": "unionBad",
"defaultValue": "`interface Registration {\n status: 'Geregistreerd' | 'Doorgehaald';\n herregistratieDatum: string; // altijd aanwezig 😬\n}`",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 131
}
],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "FormsModule",
"type": "module"
},
{
"name": "PageShellComponent",
"type": "component"
},
{
"name": "HeadingComponent",
"type": "component"
},
{
"name": "AlertComponent",
"type": "component"
},
{
"name": "TextInputComponent",
"type": "component"
},
{
"name": "ASYNC"
},
{
"name": "SkeletonComponent",
"type": "component"
},
{
"name": "RegistrationSummaryComponent",
"type": "component"
},
{
"name": "HerregistratieWizardComponent",
"type": "component"
}
],
"description": "<p>Teaching showcase: each section pairs the impossible-state-permitting &quot;before&quot;\nwith the &quot;after&quot; where the type system rules it out. Composition-only.</p>\n",
"rawdescription": "\nTeaching showcase: each section pairs the impossible-state-permitting \"before\"\nwith the \"after\" where the type system rules it out. Composition-only.",
"type": "component",
"sourceCode": "import { Component, computed, signal } from '@angular/core';\nimport { FormsModule } from '@angular/forms';\nimport type { Resource } from '@angular/core';\nimport { PageShellComponent } from '../../templates/page-shell/page-shell.component';\nimport { HeadingComponent } from '../../atoms/heading/heading.component';\nimport { AlertComponent } from '../../atoms/alert/alert.component';\nimport { TextInputComponent } from '../../atoms/text-input/text-input.component';\nimport { ASYNC } from '../../molecules/async/async.component';\nimport { SkeletonComponent } from '../../atoms/skeleton/skeleton.component';\nimport { RegistrationSummaryComponent } from '../../organisms/registration-summary/registration-summary.component';\nimport { HerregistratieWizardComponent } from '../../organisms/herregistratie-wizard/herregistratie-wizard.component';\nimport { Registration } from '../../core/models';\nimport { parsePostcode } from '../../core/parse';\n\n/** Minimal fake Resource so <app-async> can be driven through every state without HTTP. */\nfunction fakeResource<T>(status: string, value?: T, error?: Error): Resource<T> {\n return { value: () => value as T, status: () => status, error: () => error, hasValue: () => value !== undefined, reload: () => {} } as unknown as Resource<T>;\n}\n\n/** Teaching showcase: each section pairs the impossible-state-permitting \"before\"\n with the \"after\" where the type system rules it out. Composition-only. */\n@Component({\n selector: 'app-concepts-page',\n imports: [\n FormsModule, PageShellComponent, HeadingComponent, AlertComponent, TextInputComponent,\n ...ASYNC, SkeletonComponent, RegistrationSummaryComponent, HerregistratieWizardComponent,\n ],\n styles: [`\n .cols { display:flex; flex-wrap:wrap; gap:1.5rem; margin:1rem 0 2.5rem }\n .col { flex:1 1 20rem; min-width:18rem }\n .tag { font-weight:700; font-size:0.8rem; text-transform:uppercase; letter-spacing:0.04em }\n .bad { color:var(--rhc-color-rood-500) }\n .good { color:var(--rhc-color-groen-500) }\n pre { background:var(--rhc-color-grijs-100,#f3f3f3); padding:1rem; border-radius:4px; overflow:auto; font-size:0.85rem }\n `],\n template: `\n <app-page-shell heading=\"Onmogelijke toestanden onmogelijk maken\" backLink=\"/dashboard\">\n <app-alert type=\"info\">\n Vier functionele patronen die met atomic design makkelijker te tonen zijn — telkens \"fout\"\n (de oude vorm liet het toe) naast \"goed\" (het type maakt het onmogelijk).\n </app-alert>\n\n <!-- 1. Discriminated unions -->\n <app-heading [level]=\"2\">1 · Discriminated unions</app-heading>\n <div class=\"cols\">\n <div class=\"col\">\n <p class=\"tag bad\">Fout — vlakke interface</p>\n <pre>{{ unionBad }}</pre>\n <p class=\"rhc-paragraph\">Een doorgehaalde registratie houdt tóch een herregistratiedatum: onmogelijke toestand.</p>\n </div>\n <div class=\"col\">\n <p class=\"tag good\">Goed — sum type</p>\n <app-registration-summary [reg]=\"doorgehaald\" />\n <p class=\"rhc-paragraph\">De variant <code>Doorgehaald</code> kent geen herregistratiedatum, dus de rij bestaat simpelweg niet.</p>\n </div>\n </div>\n\n <!-- 2. RemoteData fold -->\n <app-heading [level]=\"2\">2 · RemoteData fold</app-heading>\n <div class=\"cols\">\n <div class=\"col\">\n <p class=\"tag good\">Eén molecuul, vier elkaar uitsluitende toestanden</p>\n <p class=\"tag\">Loading</p>\n <app-async [resource]=\"loadingRes\"><ng-template appAsyncLoaded let-v>{{ v }}</ng-template><ng-template appAsyncLoading><app-skeleton [count]=\"2\" height=\"1.2rem\" [delay]=\"0\" /></ng-template></app-async>\n <p class=\"tag\">Empty</p>\n <app-async [resource]=\"emptyRes\" [isEmpty]=\"isEmpty\"><ng-template appAsyncLoaded let-v>{{ v }}</ng-template></app-async>\n <p class=\"tag\">Failure</p>\n <app-async [resource]=\"errorRes\"><ng-template appAsyncLoaded let-v>{{ v }}</ng-template></app-async>\n <p class=\"tag\">Success</p>\n <app-async [resource]=\"successRes\" [isEmpty]=\"isEmpty\"><ng-template appAsyncLoaded let-v><ul class=\"rhc-unordered-list\">@for (i of v; track i) {<li>{{ i }}</li>}</ul></ng-template></app-async>\n </div>\n <div class=\"col\">\n <p class=\"tag good\">De exhaustieve fold</p>\n <pre>{{ foldCode }}</pre>\n <p class=\"rhc-paragraph\">Een nieuwe variant toevoegen breekt de compile via <code>assertNever</code> tot je hem afhandelt.</p>\n </div>\n </div>\n\n <!-- 3. Parse, don't validate -->\n <app-heading [level]=\"2\">3 · Parse, don't validate</app-heading>\n <div class=\"cols\">\n <div class=\"col\">\n <p class=\"tag good\">Smart constructor → Result</p>\n <app-text-input inputId=\"pc\" [ngModel]=\"raw()\" (ngModelChange)=\"raw.set($event)\" name=\"pc\" placeholder=\"Typ een postcode, bijv. 1234 AB\" />\n </div>\n <div class=\"col\">\n @if (parsed().ok) {\n <p class=\"tag good\">ok</p>\n <pre>Postcode = \"{{ parsed().ok ? $any(parsed()).value : '' }}\"</pre>\n <p class=\"rhc-paragraph\">Een gevalideerde <code>Postcode</code> is een ander type dan een ruwe string.</p>\n } @else {\n <p class=\"tag bad\">err</p>\n <pre>{{ $any(parsed()).error }}</pre>\n }\n </div>\n </div>\n\n <!-- 4. State machine / wizard -->\n <app-heading [level]=\"2\">4 · Form als state machine</app-heading>\n <div class=\"cols\">\n <div class=\"col\">\n <p class=\"tag bad\">Fout — losse booleans</p>\n <pre>{{ machineBad }}</pre>\n <p class=\"rhc-paragraph\">Niets verhindert \"submitting\" mét validatiefouten of een successcherm met errors.</p>\n </div>\n <div class=\"col\">\n <p class=\"tag good\">Goed — één tagged union stuurt de UI</p>\n <app-herregistratie-wizard />\n </div>\n </div>\n </app-page-shell>\n `,\n})\nexport class ConceptsPage {\n isEmpty = (v: string[]) => !v || v.length === 0;\n\n doorgehaald: Registration = {\n bigNummer: '19012345601', naam: 'Dr. A. (Anna) de Vries', beroep: 'Arts',\n registratiedatum: '2012-09-01', geboortedatum: '1985-03-14',\n status: { tag: 'Doorgehaald', doorgehaaldOp: '2024-05-01', reden: 'Op eigen verzoek' },\n };\n\n loadingRes = fakeResource<string[]>('loading');\n emptyRes = fakeResource<string[]>('resolved', []);\n errorRes = fakeResource<string[]>('error', undefined, new Error('Demo'));\n successRes = fakeResource<string[]>('resolved', ['Huisartsgeneeskunde', 'Spoedeisende hulp']);\n\n raw = signal('');\n parsed = computed(() => parsePostcode(this.raw()));\n\n unionBad = `interface Registration {\n status: 'Geregistreerd' | 'Doorgehaald';\n herregistratieDatum: string; // altijd aanwezig 😬\n}`;\n\n foldCode = `foldRemote(rd, {\n loading: () => spinner,\n empty: () => 'geen data',\n failure: (e) => alert(e),\n success: (v) => render(v),\n}); // mist er één → compile-fout`;\n\n machineBad = `submitting = signal(false);\nsubmitted = signal(false);\nerrors = signal<...>({});\n// submitting === true && errors.size > 0 ? 🤷`;\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "\n .cols { display:flex; flex-wrap:wrap; gap:1.5rem; margin:1rem 0 2.5rem }\n .col { flex:1 1 20rem; min-width:18rem }\n .tag { font-weight:700; font-size:0.8rem; text-transform:uppercase; letter-spacing:0.04em }\n .bad { color:var(--rhc-color-rood-500) }\n .good { color:var(--rhc-color-groen-500) }\n pre { background:var(--rhc-color-grijs-100,#f3f3f3); padding:1rem; border-radius:4px; overflow:auto; font-size:0.85rem }\n \n",
"extends": []
},
{
"name": "DashboardPage",
"id": "component-DashboardPage-f363992c5154b037dc0dc2a461da66f9a297af7bc7ba9dd9f19a1bef213af9b9fb15a92e6d5e1922040acbf5aa3f7ec27db8035944e496c8f97bb519b4652cb3",
"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 <p>\n <app-link to=\"/concepts\">Functionele patronen (impossible states) →</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": 60
},
{
"name": "notesEmpty",
"defaultValue": "() => {...}",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 61
},
{
"name": "reg",
"defaultValue": "this.svc.registrationResource()",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 59
},
{
"name": "regEmpty",
"defaultValue": "() => {...}",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 62
},
{
"name": "svc",
"defaultValue": "inject(RegistrationService)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 58,
"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 <p>\n <app-link to=\"/concepts\">Functionele patronen (impossible states) →</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-e6eeb0932b0d6c7f4073bda82d95601ef7d31f17ac310061dcf3347c8f30d1444f50e124bfedda286285ebfda9932bb075fdaf20683413b524570e51fa350c3f",
"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 <div style=\"margin-top:1.5rem\">\n <app-herregistratie-wizard />\n </div>\n</app-page-shell>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "PageShellComponent",
"type": "component"
},
{
"name": "AlertComponent",
"type": "component"
},
{
"name": "HerregistratieWizardComponent",
"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 } from '@angular/core';\nimport { PageShellComponent } from '../../templates/page-shell/page-shell.component';\nimport { AlertComponent } from '../../atoms/alert/alert.component';\nimport { HerregistratieWizardComponent } from '../../organisms/herregistratie-wizard/herregistratie-wizard.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: [PageShellComponent, AlertComponent, HerregistratieWizardComponent],\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 <div style=\"margin-top:1.5rem\">\n <app-herregistratie-wizard />\n </div>\n </app-page-shell>\n `,\n})\nexport class HerregistratiePage {}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"extends": []
},
{
"name": "HerregistratieWizardComponent",
"id": "component-HerregistratieWizardComponent-ad587121f38c0c6e6bb4c8525e7b626054b7790ec708c99a0f6e66b3b7703b935b47c6b141072f7f8c9e567974dd162961ef5e17b983e373d6d7a3a7814aaf80",
"file": "src/app/organisms/herregistratie-wizard/herregistratie-wizard.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-herregistratie-wizard",
"styleUrls": [],
"styles": [],
"template": "@switch (state().tag) {\n @case ('Editing') {\n <p class=\"rhc-paragraph\" style=\"color:var(--rhc-color-grijs-700)\">Stap {{ step() }} van 2</p>\n <form (ngSubmit)=\"onPrimary()\" style=\"max-width:28rem\">\n @if (step() === 1) {\n <app-form-field label=\"Gewerkte uren (afgelopen 5 jaar)\" fieldId=\"uren\" [error]=\"errUren()\">\n <app-text-input inputId=\"uren\" [ngModel]=\"draft().uren\" (ngModelChange)=\"set('uren', $event)\"\n name=\"uren\" [invalid]=\"!!errUren()\" placeholder=\"bijv. 4160\" />\n </app-form-field>\n <app-button type=\"submit\" variant=\"primary\">Volgende</app-button>\n } @else {\n <app-form-field label=\"Behaalde nascholingspunten\" fieldId=\"punten\" [error]=\"errPunten()\">\n <app-text-input inputId=\"punten\" [ngModel]=\"draft().punten\" (ngModelChange)=\"set('punten', $event)\"\n name=\"punten\" [invalid]=\"!!errPunten()\" placeholder=\"bijv. 200\" />\n </app-form-field>\n <div style=\"display:flex;gap:0.5rem\">\n <app-button type=\"button\" variant=\"secondary\" (click)=\"state.set(back(state()))\">Vorige</app-button>\n <app-button type=\"submit\" variant=\"primary\">Herregistratie aanvragen</app-button>\n </div>\n }\n </form>\n }\n @case ('Submitting') {\n <app-spinner /> <span>Aanvraag wordt verwerkt…</span>\n }\n @case ('Submitted') {\n <app-alert type=\"ok\">Uw aanvraag tot herregistratie is ontvangen.</app-alert>\n }\n @case ('Failed') {\n <app-alert type=\"error\">Indienen mislukt. Probeer het opnieuw.</app-alert>\n <div style=\"margin-top:1rem\">\n <app-button variant=\"secondary\" (click)=\"onRetry()\">Opnieuw proberen</app-button>\n </div>\n }\n}\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "seed",
"defaultValue": "initial",
"deprecated": false,
"deprecationMessage": "",
"type": "WizardState",
"indexKey": "",
"optional": false,
"description": "<p>Optional seed so Storybook / the showcase can mount any state directly.</p>\n",
"line": 58,
"rawdescription": "\nOptional seed so Storybook / the showcase can mount any state directly.",
"required": false
}
],
"outputsClass": [],
"propertiesClass": [
{
"name": "back",
"defaultValue": "back",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 61
},
{
"name": "draft",
"defaultValue": "computed<Draft>(() => this.editing()?.draft ?? { uren: '', punten: '' })",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 65,
"modifierKind": [
124
]
},
{
"name": "editing",
"defaultValue": "computed(() => (this.state().tag === 'Editing' ? (this.state() as Extract<WizardState, { tag: 'Editing' }>) : null))",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 63,
"modifierKind": [
123
]
},
{
"name": "errPunten",
"defaultValue": "computed(() => this.editing()?.errors.punten ?? '')",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 67,
"modifierKind": [
124
]
},
{
"name": "errUren",
"defaultValue": "computed(() => this.editing()?.errors.uren ?? '')",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 66,
"modifierKind": [
124
]
},
{
"name": "state",
"defaultValue": "signal<WizardState>(initial)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 59
},
{
"name": "step",
"defaultValue": "computed(() => this.editing()?.step ?? 1)",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 64,
"modifierKind": [
124
]
}
],
"methodsClass": [
{
"name": "onPrimary",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 79,
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "onRetry",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 86,
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "runIfSubmitting",
"args": [],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 94,
"deprecated": false,
"deprecationMessage": "",
"modifierKind": [
123
]
},
{
"name": "set",
"args": [
{
"name": "key",
"type": "unknown",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "value",
"type": "string",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": ""
}
],
"optional": false,
"returnType": "void",
"typeParameters": [],
"line": 73,
"deprecated": false,
"deprecationMessage": "",
"jsdoctags": [
{
"name": "key",
"type": "unknown",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "value",
"type": "string",
"optional": false,
"dotDotDotToken": false,
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
],
"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": "AlertComponent",
"type": "component"
},
{
"name": "SpinnerComponent",
"type": "component"
}
],
"description": "<p>Organism: multi-step herregistratie wizard driven entirely by a state\nmachine (wizard.machine.ts). The signal IS the union, so the UI just folds\nover its tag — no booleans like <code>submitting</code>/<code>submitted</code> that could contradict\neach other. Composition-only: reuses existing form-field/input/button/alert.</p>\n",
"rawdescription": "\nOrganism: multi-step herregistratie wizard driven entirely by a state\nmachine (wizard.machine.ts). The signal IS the union, so the UI just folds\nover its tag — no booleans like `submitting`/`submitted` that could contradict\neach other. Composition-only: reuses existing form-field/input/button/alert.",
"type": "component",
"sourceCode": "import { Component, computed, input, 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 { AlertComponent } from '../../atoms/alert/alert.component';\nimport { SpinnerComponent } from '../../atoms/spinner/spinner.component';\nimport { ok } from '../../core/fp';\nimport { WizardState, Draft, initial, next, back, submit, resolve } from './wizard.machine';\n\n/** Organism: multi-step herregistratie wizard driven entirely by a state\n machine (wizard.machine.ts). The signal IS the union, so the UI just folds\n over its tag — no booleans like `submitting`/`submitted` that could contradict\n each other. Composition-only: reuses existing form-field/input/button/alert. */\n@Component({\n selector: 'app-herregistratie-wizard',\n imports: [FormsModule, FormFieldComponent, TextInputComponent, ButtonComponent, AlertComponent, SpinnerComponent],\n template: `\n @switch (state().tag) {\n @case ('Editing') {\n <p class=\"rhc-paragraph\" style=\"color:var(--rhc-color-grijs-700)\">Stap {{ step() }} van 2</p>\n <form (ngSubmit)=\"onPrimary()\" style=\"max-width:28rem\">\n @if (step() === 1) {\n <app-form-field label=\"Gewerkte uren (afgelopen 5 jaar)\" fieldId=\"uren\" [error]=\"errUren()\">\n <app-text-input inputId=\"uren\" [ngModel]=\"draft().uren\" (ngModelChange)=\"set('uren', $event)\"\n name=\"uren\" [invalid]=\"!!errUren()\" placeholder=\"bijv. 4160\" />\n </app-form-field>\n <app-button type=\"submit\" variant=\"primary\">Volgende</app-button>\n } @else {\n <app-form-field label=\"Behaalde nascholingspunten\" fieldId=\"punten\" [error]=\"errPunten()\">\n <app-text-input inputId=\"punten\" [ngModel]=\"draft().punten\" (ngModelChange)=\"set('punten', $event)\"\n name=\"punten\" [invalid]=\"!!errPunten()\" placeholder=\"bijv. 200\" />\n </app-form-field>\n <div style=\"display:flex;gap:0.5rem\">\n <app-button type=\"button\" variant=\"secondary\" (click)=\"state.set(back(state()))\">Vorige</app-button>\n <app-button type=\"submit\" variant=\"primary\">Herregistratie aanvragen</app-button>\n </div>\n }\n </form>\n }\n @case ('Submitting') {\n <app-spinner /> <span>Aanvraag wordt verwerkt…</span>\n }\n @case ('Submitted') {\n <app-alert type=\"ok\">Uw aanvraag tot herregistratie is ontvangen.</app-alert>\n }\n @case ('Failed') {\n <app-alert type=\"error\">Indienen mislukt. Probeer het opnieuw.</app-alert>\n <div style=\"margin-top:1rem\">\n <app-button variant=\"secondary\" (click)=\"onRetry()\">Opnieuw proberen</app-button>\n </div>\n }\n }\n `,\n})\nexport class HerregistratieWizardComponent {\n /** Optional seed so Storybook / the showcase can mount any state directly. */\n seed = input<WizardState>(initial);\n state = signal<WizardState>(initial);\n\n back = back;\n\n private editing = computed(() => (this.state().tag === 'Editing' ? (this.state() as Extract<WizardState, { tag: 'Editing' }>) : null));\n protected step = computed(() => this.editing()?.step ?? 1);\n protected draft = computed<Draft>(() => this.editing()?.draft ?? { uren: '', punten: '' });\n protected errUren = computed(() => this.editing()?.errors.uren ?? '');\n protected errPunten = computed(() => this.editing()?.errors.punten ?? '');\n\n constructor() {\n queueMicrotask(() => this.state.set(this.seed()));\n }\n\n set(key: keyof Draft, value: string) {\n const s = this.state();\n if (s.tag !== 'Editing') return;\n this.state.set({ ...s, draft: { ...s.draft, [key]: value } });\n }\n\n onPrimary() {\n const s = this.state();\n if (s.tag !== 'Editing') return;\n this.state.set(s.step === 1 ? next(s) : submit(s));\n this.runIfSubmitting();\n }\n\n onRetry() {\n const s = this.state();\n if (s.tag !== 'Failed') return;\n this.state.set({ tag: 'Submitting', data: s.data });\n this.runIfSubmitting();\n }\n\n // ponytail: fake the backend with a timer; swap for a real httpResource call later.\n private runIfSubmitting() {\n if (this.state().tag !== 'Submitting') return;\n setTimeout(() => this.state.set(resolve(this.state(), ok(undefined))), 800);\n }\n}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": "",
"constructorObj": {
"name": "constructor",
"description": "",
"deprecated": false,
"deprecationMessage": "",
"args": [],
"line": 67
},
"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": "PageShellComponent",
"id": "component-PageShellComponent-f2d3224d1fdc66ba96a373ea16cc259b086450cd1700c9f2b59b9f3193d96b4cd69bc9218497aa73519a3545157d691f273fb410f78d9f7fe9373e5921be9c1b",
"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": "<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",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "backLabel",
"defaultValue": "'Terug naar overzicht'",
"deprecated": false,
"deprecationMessage": "",
"indexKey": "",
"optional": false,
"description": "",
"line": 29,
"required": false
},
{
"name": "backLink",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 28,
"required": false
},
{
"name": "heading",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 26,
"required": true
},
{
"name": "intro",
"deprecated": false,
"deprecationMessage": "",
"type": "string",
"indexKey": "",
"optional": false,
"description": "",
"line": 27,
"required": false
},
{
"name": "width",
"defaultValue": "'default'",
"deprecated": false,
"deprecationMessage": "",
"type": "\"default\" | \"narrow\"",
"indexKey": "",
"optional": false,
"description": "",
"line": 30,
"required": false
}
],
"outputsClass": [],
"propertiesClass": [],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [
{
"name": "HeadingComponent",
"type": "component"
},
{
"name": "LinkComponent",
"type": "component"
}
],
"description": "<p>Template: standard page body — optional back-link, a heading, optional intro,\nand projected content. Rendered inside the persistent ShellComponent via the\nrouter outlet, so it owns only the content (not the header/footer chrome).</p>\n",
"rawdescription": "\nTemplate: standard page body — optional back-link, a heading, optional intro,\nand projected content. Rendered inside the persistent ShellComponent via the\nrouter outlet, so it owns only the content (not the header/footer chrome).",
"type": "component",
"sourceCode": "import { Component, input } from '@angular/core';\nimport { HeadingComponent } from '../../atoms/heading/heading.component';\nimport { LinkComponent } from '../../atoms/link/link.component';\n\n/** Template: standard page body — optional back-link, a heading, optional intro,\n and projected content. Rendered inside the persistent ShellComponent via the\n router outlet, so it owns only the content (not the header/footer chrome). */\n@Component({\n selector: 'app-page-shell',\n imports: [HeadingComponent, LinkComponent],\n styles: [':host{display:block}'],\n template: `\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 `,\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-cad630ad4fd52e8743ba17ebf8f1cf8362c4f8677937ac6e41fadc055438d0c35c6756d7f2d39b67239ceb2af09e0a11c141fa9cd398f80e5d18a8e6960d90ee",
"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.tag\" />\n </app-data-row>\n <app-data-row key=\"Registratiedatum\" [value]=\"reg().registratiedatum | date:'longDate'\" />\n <!-- Each status variant renders only the row its own data supports. -->\n @switch (reg().status.tag) {\n @case ('Geregistreerd') {\n <app-data-row key=\"Uiterste herregistratie\" [value]=\"$any(reg().status).herregistratieDatum | date:'longDate'\" />\n }\n @case ('Geschorst') {\n <app-data-row key=\"Geschorst tot\" [value]=\"$any(reg().status).geschorstTot | date:'longDate'\" />\n <app-data-row key=\"Reden\" [value]=\"$any(reg().status).reden\" />\n }\n @case ('Doorgehaald') {\n <app-data-row key=\"Doorgehaald op\" [value]=\"$any(reg().status).doorgehaaldOp | date:'longDate'\" />\n <app-data-row key=\"Reden\" [value]=\"$any(reg().status).reden\" />\n }\n }\n </dl>\n</div>\n",
"templateUrl": [],
"viewProviders": [],
"hostDirectives": [],
"inputsClass": [
{
"name": "reg",
"deprecated": false,
"deprecationMessage": "",
"type": "Registration",
"indexKey": "",
"optional": false,
"description": "",
"line": 40,
"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.tag\" />\n </app-data-row>\n <app-data-row key=\"Registratiedatum\" [value]=\"reg().registratiedatum | date:'longDate'\" />\n <!-- Each status variant renders only the row its own data supports. -->\n @switch (reg().status.tag) {\n @case ('Geregistreerd') {\n <app-data-row key=\"Uiterste herregistratie\" [value]=\"$any(reg().status).herregistratieDatum | date:'longDate'\" />\n }\n @case ('Geschorst') {\n <app-data-row key=\"Geschorst tot\" [value]=\"$any(reg().status).geschorstTot | date:'longDate'\" />\n <app-data-row key=\"Reden\" [value]=\"$any(reg().status).reden\" />\n }\n @case ('Doorgehaald') {\n <app-data-row key=\"Doorgehaald op\" [value]=\"$any(reg().status).doorgehaaldOp | date:'longDate'\" />\n <app-data-row key=\"Reden\" [value]=\"$any(reg().status).reden\" />\n }\n }\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": "ShellComponent",
"id": "component-ShellComponent-a435ec99fc0234f16b0f1ab3b0860d9ec513acbf7cb2cefcaec3d7e36fd4c943f9b5e91c76481402563c62d8a63dd1363b29ac130c4d9a731839eccc4bbd12c2",
"file": "src/app/templates/shell/shell.component.ts",
"encapsulation": [],
"entryComponents": [],
"inputs": [],
"outputs": [],
"providers": [],
"selector": "app-shell",
"styleUrls": [],
"styles": [
":host{display:block}"
],
"template": "<a href=\"#main\" class=\"rhc-skip-link\" style=\"position:absolute;left:-999px\">Naar de inhoud</a>\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 <router-outlet />\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": "RouterOutlet"
},
{
"name": "SiteHeaderComponent",
"type": "component"
},
{
"name": "SiteFooterComponent",
"type": "component"
}
],
"description": "<p>Template: persistent app chrome. Header + footer mount once; only the routed\ncontent inside <router-outlet> changes (and cross-fades — see styles.scss).</p>\n",
"rawdescription": "\nTemplate: persistent app chrome. Header + footer mount once; only the routed\ncontent inside <router-outlet> changes (and cross-fades — see styles.scss).",
"type": "component",
"sourceCode": "import { Component } from '@angular/core';\nimport { RouterOutlet } from '@angular/router';\nimport { SiteHeaderComponent } from '../../organisms/site-header/site-header.component';\nimport { SiteFooterComponent } from '../../organisms/site-footer/site-footer.component';\n\n/** Template: persistent app chrome. Header + footer mount once; only the routed\n content inside <router-outlet> changes (and cross-fades — see styles.scss). */\n@Component({\n selector: 'app-shell',\n imports: [RouterOutlet, 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 <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 <router-outlet />\n </div>\n </main>\n <app-site-footer />\n </div>\n `,\n})\nexport class ShellComponent {}\n",
"assetsDirs": [],
"styleUrlsData": "",
"stylesData": ":host{display:block}\n",
"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-5cb9f831687f564e86bbc72b1276fd5b10bc1bc877bf15a2dfff580724e2795f7abdc861ad6ccce41846084a022c11d4c570924d3f7ec1388a1cd5e31b9fd8a2",
"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": "StatusTag",
"indexKey": "",
"optional": false,
"description": "",
"line": 18,
"required": true
}
],
"outputsClass": [],
"propertiesClass": [
{
"name": "color",
"defaultValue": "computed(() => {\n const tag = this.status();\n switch (tag) {\n case 'Geregistreerd':\n return 'var(--rhc-color-groen-500)';\n case 'Doorgehaald':\n return 'var(--rhc-color-rood-500)';\n case 'Geschorst':\n return 'var(--rhc-color-oranje-500)';\n default:\n return assertNever(tag);\n }\n })",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"indexKey": "",
"optional": false,
"description": "",
"line": 19
}
],
"methodsClass": [],
"deprecated": false,
"deprecationMessage": "",
"hostBindings": [],
"hostListeners": [],
"standalone": false,
"imports": [],
"description": "<p>Atom: status badge = colored RHC dot-badge + label. The color is a total\nfunction of the status tag — assertNever makes a new status fail to compile\nuntil a color is chosen for it.</p>\n",
"rawdescription": "\nAtom: status badge = colored RHC dot-badge + label. The color is a total\nfunction of the status tag — assertNever makes a new status fail to compile\nuntil a color is chosen for it.",
"type": "component",
"sourceCode": "import { Component, computed, input } from '@angular/core';\nimport { StatusTag } from '../../core/models';\nimport { assertNever } from '../../core/fp';\n\n/** Atom: status badge = colored RHC dot-badge + label. The color is a total\n function of the status tag — assertNever makes a new status fail to compile\n until a color is chosen for it. */\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<StatusTag>();\n color = computed(() => {\n const tag = this.status();\n switch (tag) {\n case 'Geregistreerd':\n return 'var(--rhc-color-groen-500)';\n case 'Doorgehaald':\n return 'var(--rhc-color-rood-500)';\n case 'Geschorst':\n return 'var(--rhc-color-oranje-500)';\n default:\n return assertNever(tag);\n }\n });\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, withViewTransitions()),\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": "err",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/core/fp.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"defaultValue": "<E>(error: E): Result<E, never> => ({ ok: false, error })"
},
{
"name": "initial",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "WizardState",
"defaultValue": "{ tag: 'Editing', step: 1, draft: { uren: '', punten: '' }, errors: {} }"
},
{
"name": "ok",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/core/fp.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"defaultValue": "<T>(value: T): Result<never, T> => ({ ok: true, value })"
},
{
"name": "routes",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/app.routes.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "Routes",
"defaultValue": "[\n {\n path: '',\n component: ShellComponent, // persistent header/footer; only children swap\n children: [\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: 'concepts', loadComponent: () => \"import('./pages/concepts/concepts.page').then(m => m.ConceptsPage)\" },\n { path: '**', redirectTo: 'login' },\n ],\n },\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": "assertNever",
"file": "src/app/core/fp.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Tiny native-TS functional toolkit. No dependency — this is the whole &quot;library&quot;.\nReused by every &quot;impossible states&quot; concept in the POC.</p>\n",
"args": [
{
"name": "x",
"type": "never",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "never",
"jsdoctags": [
{
"name": "x",
"type": "never",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "back",
"file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"args": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "WizardState",
"jsdoctags": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"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"
},
{
"name": "fakeResource",
"file": "src/app/pages/concepts/concepts.page.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Minimal fake Resource so <app-async> can be driven through every state without HTTP.</p>\n",
"args": [
{
"name": "status",
"type": "string",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "value",
"type": "T",
"deprecated": false,
"deprecationMessage": "",
"optional": true
},
{
"name": "error",
"type": "Error",
"deprecated": false,
"deprecationMessage": "",
"optional": true
}
],
"returnType": "Resource<T>",
"jsdoctags": [
{
"name": "status",
"type": "string",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "value",
"type": "T",
"deprecated": false,
"deprecationMessage": "",
"optional": true,
"tagName": {
"text": "param"
}
},
{
"name": "error",
"type": "Error",
"deprecated": false,
"deprecationMessage": "",
"optional": true,
"tagName": {
"text": "param"
}
}
]
},
{
"name": "foldRemote",
"file": "src/app/core/remote-data.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Exhaustive fold: you must handle every case, checked at compile time.</p>\n",
"args": [
{
"name": "rd",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "h",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "R",
"jsdoctags": [
{
"name": "rd",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "h",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "fromResource",
"file": "src/app/core/remote-data.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Project Angular&#39;s loosely-typed Resource into a RemoteData value.</p>\n",
"args": [
{
"name": "r",
"type": "Resource",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "isEmpty",
"deprecated": false,
"deprecationMessage": "",
"defaultValue": "() => false"
}
],
"returnType": "RemoteData<Error | undefined, T>",
"jsdoctags": [
{
"name": "r",
"type": "Resource",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "isEmpty",
"deprecated": false,
"deprecationMessage": "",
"defaultValue": "() => false",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "next",
"file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Step 1 → 2: only advance if the uren field parses. Illegal elsewhere = no-op.</p>\n",
"args": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "WizardState",
"jsdoctags": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "parsePostcode",
"file": "src/app/core/parse.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"args": [
{
"name": "raw",
"type": "string",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "Result<string, Postcode>",
"jsdoctags": [
{
"name": "raw",
"type": "string",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "parseUren",
"file": "src/app/core/parse.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"args": [
{
"name": "raw",
"type": "string",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "Result<string, Uren>",
"jsdoctags": [
{
"name": "raw",
"type": "string",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "resolve",
"file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Resolve the async submit. Only meaningful while Submitting.</p>\n",
"args": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "r",
"type": "Result",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "WizardState",
"jsdoctags": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "r",
"type": "Result",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "submit",
"file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Step 2 submit: parse everything; move to Submitting only with Valid data.</p>\n",
"args": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "WizardState",
"jsdoctags": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "validate",
"file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Parse every field; on success hand back a Valid, else the per-field errors.</p>\n",
"args": [
{
"name": "draft",
"type": "Draft",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "Result<Partial<Record<Draft, string>>, Valid>",
"jsdoctags": [
{
"name": "draft",
"type": "Draft",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
],
"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": "Brand",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "unknown",
"file": "src/app/core/fp.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Nominal typing: Brand&lt;string, &#39;Postcode&#39;&gt; is assignable from a plain string\nonly through an explicit cast — so a smart constructor is the only minter.</p>\n",
"kind": 194
},
{
"name": "Postcode",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "Brand<string | Postcode>",
"file": "src/app/core/parse.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>&quot;Parse, don&#39;t validate.&quot; A validated value gets its own branded type, and the\nsmart constructor is the ONLY way to mint one. So once you hold a Postcode you\nknow it&#39;s well-formed — validity is carried in the type, not re-checked\neverywhere or tracked in a parallel error flag.</p>\n",
"kind": 184
},
{
"name": "RegistrationStatus",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "literal type | literal type | literal type",
"file": "src/app/core/models.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Registration status as a discriminated union: each variant owns exactly the\ndata that makes sense for it. Only an active (Geregistreerd) registration has\na herregistratie date; a struck-off (Doorgehaald) one cannot carry one. The\nold flat interface allowed that impossible combination — this makes it\nunrepresentable.</p>\n",
"kind": 193
},
{
"name": "RemoteData",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "literal type | literal type | literal type | literal type",
"file": "src/app/core/remote-data.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>The four mutually-exclusive states of an async fetch, as a tagged union.\nCrucially the data lives ON the state: only <code>Failure</code> has an <code>error</code>, only\n<code>Success</code> has a <code>value</code>. &quot;Loaded but no value&quot; or &quot;error with stale value&quot;\nare unrepresentable — Richard Feldman&#39;s RemoteData.</p>\n",
"kind": 193
},
{
"name": "Result",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "literal type | literal type",
"file": "src/app/core/fp.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>A computation that either succeeded with a value or failed with an error.\nPlain objects (no classes) to match the signal/httpResource ergonomics.</p>\n",
"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": "StatusTag",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "RegistrationStatus",
"file": "src/app/core/models.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Just the discriminant — for atoms that only need the label/color.</p>\n",
"kind": 200
},
{
"name": "Uren",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "Brand<number | Uren>",
"file": "src/app/core/parse.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"kind": 184
},
{
"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
},
{
"name": "WizardState",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "literal type | literal type | literal type | literal type",
"file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>The whole wizard as one tagged union. <code>step</code> and <code>errors</code> exist ONLY while\nEditing; Submitting/Submitted/Failed carry a <code>Valid</code> payload and nothing else.\nSo &quot;submitting while a field is invalid&quot; or &quot;showing the success screen with\nerrors set&quot; are unrepresentable — the bug class is gone by construction.</p>\n",
"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, withViewTransitions()),\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/core/fp.ts": [
{
"name": "err",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/core/fp.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"defaultValue": "<E>(error: E): Result<E, never> => ({ ok: false, error })"
},
{
"name": "ok",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/core/fp.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "unknown",
"defaultValue": "<T>(value: T): Result<never, T> => ({ ok: true, value })"
}
],
"src/app/organisms/herregistratie-wizard/wizard.machine.ts": [
{
"name": "initial",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "WizardState",
"defaultValue": "{ tag: 'Editing', step: 1, draft: { uren: '', punten: '' }, errors: {} }"
}
],
"src/app/app.routes.ts": [
{
"name": "routes",
"ctype": "miscellaneous",
"subtype": "variable",
"file": "src/app/app.routes.ts",
"deprecated": false,
"deprecationMessage": "",
"type": "Routes",
"defaultValue": "[\n {\n path: '',\n component: ShellComponent, // persistent header/footer; only children swap\n children: [\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: 'concepts', loadComponent: () => \"import('./pages/concepts/concepts.page').then(m => m.ConceptsPage)\" },\n { path: '**', redirectTo: 'login' },\n ],\n },\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/fp.ts": [
{
"name": "assertNever",
"file": "src/app/core/fp.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Tiny native-TS functional toolkit. No dependency — this is the whole &quot;library&quot;.\nReused by every &quot;impossible states&quot; concept in the POC.</p>\n",
"args": [
{
"name": "x",
"type": "never",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "never",
"jsdoctags": [
{
"name": "x",
"type": "never",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
],
"src/app/organisms/herregistratie-wizard/wizard.machine.ts": [
{
"name": "back",
"file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"args": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "WizardState",
"jsdoctags": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "next",
"file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Step 1 → 2: only advance if the uren field parses. Illegal elsewhere = no-op.</p>\n",
"args": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "WizardState",
"jsdoctags": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "resolve",
"file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Resolve the async submit. Only meaningful while Submitting.</p>\n",
"args": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "r",
"type": "Result",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "WizardState",
"jsdoctags": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "r",
"type": "Result",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "submit",
"file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Step 2 submit: parse everything; move to Submitting only with Valid data.</p>\n",
"args": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "WizardState",
"jsdoctags": [
{
"name": "s",
"type": "WizardState",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "validate",
"file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Parse every field; on success hand back a Valid, else the per-field errors.</p>\n",
"args": [
{
"name": "draft",
"type": "Draft",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "Result<Partial<Record<Draft, string>>, Valid>",
"jsdoctags": [
{
"name": "draft",
"type": "Draft",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
],
"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"
}
],
"src/app/pages/concepts/concepts.page.ts": [
{
"name": "fakeResource",
"file": "src/app/pages/concepts/concepts.page.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Minimal fake Resource so <app-async> can be driven through every state without HTTP.</p>\n",
"args": [
{
"name": "status",
"type": "string",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "value",
"type": "T",
"deprecated": false,
"deprecationMessage": "",
"optional": true
},
{
"name": "error",
"type": "Error",
"deprecated": false,
"deprecationMessage": "",
"optional": true
}
],
"returnType": "Resource<T>",
"jsdoctags": [
{
"name": "status",
"type": "string",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "value",
"type": "T",
"deprecated": false,
"deprecationMessage": "",
"optional": true,
"tagName": {
"text": "param"
}
},
{
"name": "error",
"type": "Error",
"deprecated": false,
"deprecationMessage": "",
"optional": true,
"tagName": {
"text": "param"
}
}
]
}
],
"src/app/core/remote-data.ts": [
{
"name": "foldRemote",
"file": "src/app/core/remote-data.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Exhaustive fold: you must handle every case, checked at compile time.</p>\n",
"args": [
{
"name": "rd",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "h",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "R",
"jsdoctags": [
{
"name": "rd",
"type": "RemoteData",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "h",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "fromResource",
"file": "src/app/core/remote-data.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Project Angular&#39;s loosely-typed Resource into a RemoteData value.</p>\n",
"args": [
{
"name": "r",
"type": "Resource",
"deprecated": false,
"deprecationMessage": ""
},
{
"name": "isEmpty",
"deprecated": false,
"deprecationMessage": "",
"defaultValue": "() => false"
}
],
"returnType": "RemoteData<Error | undefined, T>",
"jsdoctags": [
{
"name": "r",
"type": "Resource",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
},
{
"name": "isEmpty",
"deprecated": false,
"deprecationMessage": "",
"defaultValue": "() => false",
"tagName": {
"text": "param"
}
}
]
}
],
"src/app/core/parse.ts": [
{
"name": "parsePostcode",
"file": "src/app/core/parse.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"args": [
{
"name": "raw",
"type": "string",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "Result<string, Postcode>",
"jsdoctags": [
{
"name": "raw",
"type": "string",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
},
{
"name": "parseUren",
"file": "src/app/core/parse.ts",
"ctype": "miscellaneous",
"subtype": "function",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"args": [
{
"name": "raw",
"type": "string",
"deprecated": false,
"deprecationMessage": ""
}
],
"returnType": "Result<string, Uren>",
"jsdoctags": [
{
"name": "raw",
"type": "string",
"deprecated": false,
"deprecationMessage": "",
"tagName": {
"text": "param"
}
}
]
}
]
},
"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/fp.ts": [
{
"name": "Brand",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "unknown",
"file": "src/app/core/fp.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Nominal typing: Brand&lt;string, &#39;Postcode&#39;&gt; is assignable from a plain string\nonly through an explicit cast — so a smart constructor is the only minter.</p>\n",
"kind": 194
},
{
"name": "Result",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "literal type | literal type",
"file": "src/app/core/fp.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>A computation that either succeeded with a value or failed with an error.\nPlain objects (no classes) to match the signal/httpResource ergonomics.</p>\n",
"kind": 193
}
],
"src/app/core/parse.ts": [
{
"name": "Postcode",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "Brand<string | Postcode>",
"file": "src/app/core/parse.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>&quot;Parse, don&#39;t validate.&quot; A validated value gets its own branded type, and the\nsmart constructor is the ONLY way to mint one. So once you hold a Postcode you\nknow it&#39;s well-formed — validity is carried in the type, not re-checked\neverywhere or tracked in a parallel error flag.</p>\n",
"kind": 184
},
{
"name": "Uren",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "Brand<number | Uren>",
"file": "src/app/core/parse.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "",
"kind": 184
}
],
"src/app/core/models.ts": [
{
"name": "RegistrationStatus",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "literal type | literal type | literal type",
"file": "src/app/core/models.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Registration status as a discriminated union: each variant owns exactly the\ndata that makes sense for it. Only an active (Geregistreerd) registration has\na herregistratie date; a struck-off (Doorgehaald) one cannot carry one. The\nold flat interface allowed that impossible combination — this makes it\nunrepresentable.</p>\n",
"kind": 193
},
{
"name": "StatusTag",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "RegistrationStatus",
"file": "src/app/core/models.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>Just the discriminant — for atoms that only need the label/color.</p>\n",
"kind": 200
}
],
"src/app/core/remote-data.ts": [
{
"name": "RemoteData",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "literal type | literal type | literal type | literal type",
"file": "src/app/core/remote-data.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>The four mutually-exclusive states of an async fetch, as a tagged union.\nCrucially the data lives ON the state: only <code>Failure</code> has an <code>error</code>, only\n<code>Success</code> has a <code>value</code>. &quot;Loaded but no value&quot; or &quot;error with stale value&quot;\nare unrepresentable — Richard Feldman&#39;s RemoteData.</p>\n",
"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/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
}
],
"src/app/organisms/herregistratie-wizard/wizard.machine.ts": [
{
"name": "WizardState",
"ctype": "miscellaneous",
"subtype": "typealias",
"rawtype": "literal type | literal type | literal type | literal type",
"file": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"deprecated": false,
"deprecationMessage": "",
"description": "<p>The whole wizard as one tagged union. <code>step</code> and <code>errors</code> exist ONLY while\nEditing; Submitting/Submitted/Failed carry a <code>Valid</code> payload and nothing else.\nSo &quot;submitting while a field is invalid&quot; or &quot;showing the success screen with\nerrors set&quot; are unrepresentable — the bug class is gone by construction.</p>\n",
"kind": 193
}
]
}
},
"routes": {
"name": "<root>",
"kind": "module",
"children": [
{
"name": "ShellComponent",
"kind": "component",
"filename": "src/app/app.routes.ts"
},
{
"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": "concepts",
"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": 41,
"status": "medium",
"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/fp.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "assertNever",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/core/fp.ts",
"type": "variable",
"linktype": "miscellaneous",
"linksubtype": "variable",
"name": "err",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/core/fp.ts",
"type": "variable",
"linktype": "miscellaneous",
"linksubtype": "variable",
"name": "ok",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/core/fp.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "Brand",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/core/fp.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "Result",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"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/7",
"status": "low"
},
{
"filePath": "src/app/core/models.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "RegistrationStatus",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/core/models.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "StatusTag",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/core/parse.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "parsePostcode",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/core/parse.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "parseUren",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/core/parse.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "Postcode",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/core/parse.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "Uren",
"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/remote-data.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "foldRemote",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/core/remote-data.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "fromResource",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/core/remote-data.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "RemoteData",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"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": 9,
"coverageCount": "1/11",
"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/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": 12,
"coverageCount": "1/8",
"status": "low"
},
{
"filePath": "src/app/organisms/change-request-form/change-request-form.component.ts",
"type": "interface",
"linktype": "interface",
"name": "ChangeRequest",
"coveragePercent": 25,
"coverageCount": "1/4",
"status": "low"
},
{
"filePath": "src/app/organisms/herregistratie-wizard/herregistratie-wizard.component.ts",
"type": "component",
"linktype": "component",
"name": "HerregistratieWizardComponent",
"coveragePercent": 14,
"coverageCount": "2/14",
"status": "low"
},
{
"filePath": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"type": "interface",
"linktype": "interface",
"name": "Draft",
"coveragePercent": 33,
"coverageCount": "1/3",
"status": "medium"
},
{
"filePath": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"type": "interface",
"linktype": "interface",
"name": "Valid",
"coveragePercent": 33,
"coverageCount": "1/3",
"status": "medium"
},
{
"filePath": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "back",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "next",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "resolve",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "submit",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "validate",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"filePath": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"type": "variable",
"linktype": "miscellaneous",
"linksubtype": "variable",
"name": "initial",
"coveragePercent": 0,
"coverageCount": "0/1",
"status": "low"
},
{
"filePath": "src/app/organisms/herregistratie-wizard/wizard.machine.ts",
"type": "type alias",
"linktype": "miscellaneous",
"linksubtype": "typealias",
"name": "WizardState",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"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/concepts/concepts.page.ts",
"type": "component",
"linktype": "component",
"name": "ConceptsPage",
"coveragePercent": 8,
"coverageCount": "1/12",
"status": "low"
},
{
"filePath": "src/app/pages/concepts/concepts.page.ts",
"type": "function",
"linktype": "miscellaneous",
"linksubtype": "function",
"name": "fakeResource",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"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": 100,
"coverageCount": "1/1",
"status": "very-good"
},
{
"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-shell/page-shell.component.ts",
"type": "component",
"linktype": "component",
"name": "PageShellComponent",
"coveragePercent": 16,
"coverageCount": "1/6",
"status": "low"
},
{
"filePath": "src/app/templates/shell/shell.component.ts",
"type": "component",
"linktype": "component",
"name": "ShellComponent",
"coveragePercent": 100,
"coverageCount": "1/1",
"status": "very-good"
}
]
}
}