uhc-portal-components-react 0.1.15 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.md +10 -1
- package/dist/IdentityEvidenceDeclarationForm.d.ts +43 -0
- package/dist/IdentityEvidenceDeclarationForm.d.ts.map +1 -0
- package/dist/IdentityEvidenceDeclarationForm.js +47 -0
- package/dist/IdentityEvidenceDocumentPanel.d.ts +34 -0
- package/dist/IdentityEvidenceDocumentPanel.d.ts.map +1 -0
- package/dist/IdentityEvidenceDocumentPanel.js +40 -0
- package/dist/SubjectAccessRequestPanel.d.ts +10 -2
- package/dist/SubjectAccessRequestPanel.d.ts.map +1 -1
- package/dist/SubjectAccessRequestPanel.js +13 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/styles.css +21 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.17
|
|
4
|
+
|
|
5
|
+
- Add provider-enabled microchip, tattoo, email and telephone subject locator
|
|
6
|
+
kinds without exposing any locator that the owning BFF has not enabled.
|
|
7
|
+
- Carry server-returned identifier evidence as presentation-only metadata and
|
|
8
|
+
add suitable browser input hints for ISO animal microchips and contacts.
|
|
9
|
+
|
|
10
|
+
## 0.1.16
|
|
11
|
+
|
|
12
|
+
- Add `IdentityEvidenceDocumentPanel`, a brand-neutral signed-PDF upload and
|
|
13
|
+
verification surface used by PetChain, UHC UNID and SOSChain.
|
|
14
|
+
- Keep rendered status provider-owned: selecting or uploading a PDF never
|
|
15
|
+
changes pending evidence to verified in browser state.
|
|
16
|
+
- Add `IdentityEvidenceDeclarationForm` for governed legal-name, jurisdiction,
|
|
17
|
+
identifier and relationship options with one high-level preparation
|
|
18
|
+
callback and no session, certificate or gateway fields.
|
|
19
|
+
|
|
3
20
|
## 0.1.15
|
|
4
21
|
|
|
5
22
|
- Add an accessible, animated `PortalLoadingSkeleton` that authenticated
|
|
@@ -27,6 +44,8 @@
|
|
|
27
44
|
|
|
28
45
|
## Unreleased
|
|
29
46
|
|
|
47
|
+
- Add the repository-wide mandatory red-green-refactor contributor contract
|
|
48
|
+
and mark the existing component suites with an explicit TDD contract header.
|
|
30
49
|
- Correct the reuse contract: the package currently provides presentation
|
|
31
50
|
primitives, not the full UHC Personal route journeys. Document the extraction
|
|
32
51
|
required before PetChain can reuse login, protected profiles, individuals,
|
package/README.md
CHANGED
|
@@ -56,7 +56,9 @@ The package deliberately exposes modules instead of a cloned application:
|
|
|
56
56
|
- `InvitationAcceptancePanel`: controlled invitation-code UI for a related
|
|
57
57
|
individual member; the host refreshes the authorized-subject list after its
|
|
58
58
|
BFF accepts the invitation.
|
|
59
|
-
- `SubjectAccessRequestPanel`: controlled QR, numeric-code
|
|
59
|
+
- `SubjectAccessRequestPanel`: controlled provider-enabled QR, numeric-code,
|
|
60
|
+
`did:web`, microchip, tattoo, email or telephone locator. Resolution and
|
|
61
|
+
returned identifier evidence never grant subject access.
|
|
60
62
|
resolver plus section selector. It deliberately has no scanner role: the
|
|
61
63
|
same component is reusable by an individual member or a professional.
|
|
62
64
|
- `SoschainWorkspace`: subject-card picker and four-area workspace for Places,
|
|
@@ -71,6 +73,13 @@ The package deliberately exposes modules instead of a cloned application:
|
|
|
71
73
|
exact capabilities for self upload, organization-worker upload or
|
|
72
74
|
professional attestation; ICA or another trusted backend verifies the
|
|
73
75
|
signature after upload.
|
|
76
|
+
- `IdentityEvidenceDocumentPanel`: selects and uploads one signed PDF for the
|
|
77
|
+
chosen identity, requests trusted verification and renders only the status
|
|
78
|
+
returned by the provider facade. It contains no certificate or gateway
|
|
79
|
+
plumbing.
|
|
80
|
+
- `IdentityEvidenceDeclarationForm`: collects the business fields used to
|
|
81
|
+
prepare a declaration. Hosts supply governed options and one high-level
|
|
82
|
+
callback; the form never authors claims or handles certificates.
|
|
74
83
|
|
|
75
84
|
Clinical label semantics stay in `gdc-common-utils-ts` / the SDK reader. Hosts
|
|
76
85
|
pass human titles to `ClinicalSectionSummary`: local `CodeableConcept.text`
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type IdentityEvidenceOption = Readonly<{
|
|
2
|
+
value: string;
|
|
3
|
+
label: string;
|
|
4
|
+
}>;
|
|
5
|
+
export type IdentityEvidenceDeclarationInput = Readonly<{
|
|
6
|
+
fullLegalName: string;
|
|
7
|
+
countryCode: string;
|
|
8
|
+
regional: boolean;
|
|
9
|
+
subdivisionCode?: string;
|
|
10
|
+
identifierKind: string;
|
|
11
|
+
identifierValue: string;
|
|
12
|
+
controllerCapacity: string;
|
|
13
|
+
}>;
|
|
14
|
+
export type IdentityEvidenceDeclarationFormCopy = Readonly<{
|
|
15
|
+
title: string;
|
|
16
|
+
body: string;
|
|
17
|
+
fullLegalName: string;
|
|
18
|
+
country: string;
|
|
19
|
+
identifierKind: string;
|
|
20
|
+
identifierValue: string;
|
|
21
|
+
regional: string;
|
|
22
|
+
region: string;
|
|
23
|
+
capacity: string;
|
|
24
|
+
prepare: string;
|
|
25
|
+
preparing: string;
|
|
26
|
+
required: string;
|
|
27
|
+
}>;
|
|
28
|
+
/**
|
|
29
|
+
* Brand-neutral declaration form shared by UHC, PetChain and SOSChain.
|
|
30
|
+
*
|
|
31
|
+
* The host supplies governed options and one high-level preparation callback.
|
|
32
|
+
* This component neither authors resource claims nor handles certificates,
|
|
33
|
+
* sessions, gateway messages or verification decisions.
|
|
34
|
+
*/
|
|
35
|
+
export declare function IdentityEvidenceDeclarationForm({ copy, countries, regions, identifierKinds, capacities, onPrepare, }: Readonly<{
|
|
36
|
+
copy: IdentityEvidenceDeclarationFormCopy;
|
|
37
|
+
countries: readonly IdentityEvidenceOption[];
|
|
38
|
+
regions: readonly IdentityEvidenceOption[];
|
|
39
|
+
identifierKinds: readonly IdentityEvidenceOption[];
|
|
40
|
+
capacities: readonly IdentityEvidenceOption[];
|
|
41
|
+
onPrepare: (input: IdentityEvidenceDeclarationInput) => Promise<void>;
|
|
42
|
+
}>): import("react").JSX.Element;
|
|
43
|
+
//# sourceMappingURL=IdentityEvidenceDeclarationForm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IdentityEvidenceDeclarationForm.d.ts","sourceRoot":"","sources":["../src/IdentityEvidenceDeclarationForm.tsx"],"names":[],"mappings":"AAEA,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAE/E,MAAM,MAAM,gCAAgC,GAAG,QAAQ,CAAC;IACtD,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,OAAO,CAAA;IACjB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,cAAc,EAAE,MAAM,CAAA;IACtB,eAAe,EAAE,MAAM,CAAA;IACvB,kBAAkB,EAAE,MAAM,CAAA;CAC3B,CAAC,CAAA;AAEF,MAAM,MAAM,mCAAmC,GAAG,QAAQ,CAAC;IACzD,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,cAAc,EAAE,MAAM,CAAA;IACtB,eAAe,EAAE,MAAM,CAAA;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAC,CAAA;AAEF;;;;;;GAMG;AACH,wBAAgB,+BAA+B,CAAC,EAC9C,IAAI,EACJ,SAAS,EACT,OAAO,EACP,eAAe,EACf,UAAU,EACV,SAAS,GACV,EAAE,QAAQ,CAAC;IACV,IAAI,EAAE,mCAAmC,CAAA;IACzC,SAAS,EAAE,SAAS,sBAAsB,EAAE,CAAA;IAC5C,OAAO,EAAE,SAAS,sBAAsB,EAAE,CAAA;IAC1C,eAAe,EAAE,SAAS,sBAAsB,EAAE,CAAA;IAClD,UAAU,EAAE,SAAS,sBAAsB,EAAE,CAAA;IAC7C,SAAS,EAAE,CAAC,KAAK,EAAE,gCAAgC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACtE,CAAC,+BA+CD"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Brand-neutral declaration form shared by UHC, PetChain and SOSChain.
|
|
5
|
+
*
|
|
6
|
+
* The host supplies governed options and one high-level preparation callback.
|
|
7
|
+
* This component neither authors resource claims nor handles certificates,
|
|
8
|
+
* sessions, gateway messages or verification decisions.
|
|
9
|
+
*/
|
|
10
|
+
export function IdentityEvidenceDeclarationForm({ copy, countries, regions, identifierKinds, capacities, onPrepare, }) {
|
|
11
|
+
const [fullLegalName, setFullLegalName] = useState('');
|
|
12
|
+
const [identifierValue, setIdentifierValue] = useState('');
|
|
13
|
+
const [countryCode, setCountryCode] = useState(countries[0]?.value || '');
|
|
14
|
+
const [identifierKind, setIdentifierKind] = useState(identifierKinds[0]?.value || '');
|
|
15
|
+
const [controllerCapacity, setControllerCapacity] = useState(capacities[0]?.value || '');
|
|
16
|
+
const [regional, setRegional] = useState(false);
|
|
17
|
+
const [subdivisionCode, setSubdivisionCode] = useState('');
|
|
18
|
+
const [busy, setBusy] = useState(false);
|
|
19
|
+
const [error, setError] = useState('');
|
|
20
|
+
async function prepare() {
|
|
21
|
+
if (!fullLegalName.trim() || !identifierValue.trim() || !countryCode || !identifierKind || !controllerCapacity || (regional && !subdivisionCode)) {
|
|
22
|
+
setError(copy.required);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
setBusy(true);
|
|
26
|
+
setError('');
|
|
27
|
+
try {
|
|
28
|
+
await onPrepare({
|
|
29
|
+
fullLegalName: fullLegalName.trim(),
|
|
30
|
+
countryCode,
|
|
31
|
+
regional,
|
|
32
|
+
...(regional ? { subdivisionCode } : {}),
|
|
33
|
+
identifierKind,
|
|
34
|
+
identifierValue: identifierValue.trim(),
|
|
35
|
+
controllerCapacity,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
finally {
|
|
39
|
+
setBusy(false);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return _jsxs("section", { className: "uhcp-identity-declaration", "aria-labelledby": "identity-declaration-form-title", children: [_jsxs("header", { children: [_jsx("h3", { id: "identity-declaration-form-title", children: copy.title }), _jsx("p", { children: copy.body })] }), _jsxs("div", { className: "uhcp-identity-declaration-fields", children: [_jsxs("label", { children: [copy.fullLegalName, _jsx("input", { value: fullLegalName, onChange: (event) => setFullLegalName(event.target.value) })] }), _jsxs("label", { children: [copy.country, _jsx("select", { value: countryCode, onChange: (event) => setCountryCode(event.target.value), children: options(countries) })] }), _jsxs("label", { children: [copy.identifierKind, _jsx("select", { value: identifierKind, onChange: (event) => setIdentifierKind(event.target.value), children: options(identifierKinds) })] }), _jsxs("label", { children: [copy.identifierValue, _jsx("input", { value: identifierValue, onChange: (event) => setIdentifierValue(event.target.value) })] }), _jsxs("label", { children: [_jsx("input", { type: "checkbox", checked: regional, onChange: (event) => { setRegional(event.target.checked); if (!event.target.checked)
|
|
43
|
+
setSubdivisionCode(''); } }), copy.regional] }), _jsxs("label", { children: [copy.region, _jsxs("select", { value: subdivisionCode, disabled: !regional, onChange: (event) => setSubdivisionCode(event.target.value), children: [_jsx("option", { value: "" }), options(regions)] })] }), _jsxs("label", { children: [copy.capacity, _jsx("select", { value: controllerCapacity, onChange: (event) => setControllerCapacity(event.target.value), children: options(capacities) })] })] }), error ? _jsx("p", { role: "alert", children: error }) : null, _jsx("button", { type: "button", onClick: () => void prepare(), disabled: busy, children: busy ? copy.preparing : copy.prepare })] });
|
|
44
|
+
}
|
|
45
|
+
function options(values) {
|
|
46
|
+
return values.map((option) => _jsx("option", { value: option.value, children: option.label }, option.value));
|
|
47
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { IdentityEvidenceIdentifier, IdentityEvidenceStatus } from './IdentityEvidenceWorkspace.js';
|
|
2
|
+
export type IdentityEvidenceDocument = Readonly<{
|
|
3
|
+
id: string;
|
|
4
|
+
fileName: string;
|
|
5
|
+
status: IdentityEvidenceStatus;
|
|
6
|
+
}>;
|
|
7
|
+
export type IdentityEvidenceDocumentPanelCopy = Readonly<{
|
|
8
|
+
title: string;
|
|
9
|
+
body: string;
|
|
10
|
+
choosePdf: string;
|
|
11
|
+
upload: string;
|
|
12
|
+
uploading: string;
|
|
13
|
+
verify: string;
|
|
14
|
+
verifying: string;
|
|
15
|
+
noDocument: string;
|
|
16
|
+
invalidPdf: string;
|
|
17
|
+
statusLabels: Readonly<Record<IdentityEvidenceStatus, string>>;
|
|
18
|
+
}>;
|
|
19
|
+
/**
|
|
20
|
+
* Reusable signed-document panel for UHC, PetChain and SOSChain.
|
|
21
|
+
*
|
|
22
|
+
* The component only chooses a PDF and calls the host's high-level methods.
|
|
23
|
+
* It never parses certificates, builds gateway claims or promotes a local
|
|
24
|
+
* digest to verified evidence. The rendered status always comes from provider
|
|
25
|
+
* readback through `documents`.
|
|
26
|
+
*/
|
|
27
|
+
export declare function IdentityEvidenceDocumentPanel({ copy, selectedIdentifier, documents, onUpload, onVerifySignaturePdf, }: Readonly<{
|
|
28
|
+
copy: IdentityEvidenceDocumentPanelCopy;
|
|
29
|
+
selectedIdentifier?: IdentityEvidenceIdentifier;
|
|
30
|
+
documents: readonly IdentityEvidenceDocument[];
|
|
31
|
+
onUpload: (controllerIdentifierId: string, pdf: File) => Promise<void>;
|
|
32
|
+
onVerifySignaturePdf: (evidenceId: string) => Promise<void>;
|
|
33
|
+
}>): import("react").JSX.Element;
|
|
34
|
+
//# sourceMappingURL=IdentityEvidenceDocumentPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IdentityEvidenceDocumentPanel.d.ts","sourceRoot":"","sources":["../src/IdentityEvidenceDocumentPanel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AAExG,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,sBAAsB,CAAA;CAC/B,CAAC,CAAA;AAEF,MAAM,MAAM,iCAAiC,GAAG,QAAQ,CAAC;IACvD,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAC,CAAA;CAC/D,CAAC,CAAA;AAEF;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAAC,EAC5C,IAAI,EACJ,kBAAkB,EAClB,SAAS,EACT,QAAQ,EACR,oBAAoB,GACrB,EAAE,QAAQ,CAAC;IACV,IAAI,EAAE,iCAAiC,CAAA;IACvC,kBAAkB,CAAC,EAAE,0BAA0B,CAAA;IAC/C,SAAS,EAAE,SAAS,wBAAwB,EAAE,CAAA;IAC9C,QAAQ,EAAE,CAAC,sBAAsB,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACtE,oBAAoB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC5D,CAAC,+BAgED"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Reusable signed-document panel for UHC, PetChain and SOSChain.
|
|
5
|
+
*
|
|
6
|
+
* The component only chooses a PDF and calls the host's high-level methods.
|
|
7
|
+
* It never parses certificates, builds gateway claims or promotes a local
|
|
8
|
+
* digest to verified evidence. The rendered status always comes from provider
|
|
9
|
+
* readback through `documents`.
|
|
10
|
+
*/
|
|
11
|
+
export function IdentityEvidenceDocumentPanel({ copy, selectedIdentifier, documents, onUpload, onVerifySignaturePdf, }) {
|
|
12
|
+
const [file, setFile] = useState();
|
|
13
|
+
const [busy, setBusy] = useState();
|
|
14
|
+
const [error, setError] = useState('');
|
|
15
|
+
async function upload() {
|
|
16
|
+
if (!selectedIdentifier || !file || file.type !== 'application/pdf') {
|
|
17
|
+
setError(copy.invalidPdf);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
setBusy('upload');
|
|
21
|
+
setError('');
|
|
22
|
+
try {
|
|
23
|
+
await onUpload(selectedIdentifier.id, file);
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
setBusy(undefined);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async function verify(evidenceId) {
|
|
30
|
+
setBusy('verify');
|
|
31
|
+
setError('');
|
|
32
|
+
try {
|
|
33
|
+
await onVerifySignaturePdf(evidenceId);
|
|
34
|
+
}
|
|
35
|
+
finally {
|
|
36
|
+
setBusy(undefined);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return (_jsxs("section", { className: "uhcp-identity-documents", "aria-labelledby": "identity-evidence-documents-title", children: [_jsxs("header", { children: [_jsx("h3", { id: "identity-evidence-documents-title", children: copy.title }), _jsx("p", { children: copy.body })] }), _jsxs("label", { children: [_jsx("span", { children: copy.choosePdf }), _jsx("input", { type: "file", accept: "application/pdf,.pdf", "aria-label": copy.choosePdf, onChange: (event) => setFile(event.target.files?.[0]) })] }), _jsx("button", { type: "button", onClick: () => void upload(), disabled: busy !== undefined || !selectedIdentifier, children: busy === 'upload' ? copy.uploading : copy.upload }), error ? _jsx("p", { role: "alert", children: error }) : null, documents.length ? (_jsx("ul", { children: documents.map((document) => (_jsxs("li", { children: [_jsxs("span", { children: [_jsx("strong", { children: document.fileName }), _jsx("small", { children: copy.statusLabels[document.status] })] }), document.status === 'pending' ? (_jsx("button", { type: "button", onClick: () => void verify(document.id), disabled: busy !== undefined, children: busy === 'verify' ? copy.verifying : copy.verify })) : null] }, document.id))) })) : _jsx("p", { children: copy.noDocument })] }));
|
|
40
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type SubjectLocatorKind = 'qr' | 'numeric-code' | 'did-web';
|
|
1
|
+
export type SubjectLocatorKind = 'qr' | 'numeric-code' | 'did-web' | 'microchip' | 'tattoo' | 'email-address' | 'phone-number';
|
|
2
2
|
export type SubjectAccessRequestStatus = 'idle' | 'resolving' | 'resolved' | 'requesting' | 'requested' | 'granted' | 'error';
|
|
3
3
|
export type SubjectAccessSectionOption = Readonly<{
|
|
4
4
|
code: string;
|
|
@@ -8,12 +8,20 @@ export type SubjectAccessSectionOption = Readonly<{
|
|
|
8
8
|
export type ResolvedSubjectAccessTarget = Readonly<{
|
|
9
9
|
subjectId: string;
|
|
10
10
|
display: string;
|
|
11
|
+
/** Server-returned evidence for presentation only; it grants no access. */
|
|
12
|
+
identifiers?: readonly Readonly<{
|
|
13
|
+
kind: SubjectLocatorKind;
|
|
14
|
+
system: string;
|
|
15
|
+
value: string;
|
|
16
|
+
attested: boolean;
|
|
17
|
+
}>[];
|
|
11
18
|
}>;
|
|
12
19
|
export type SubjectAccessRequestPanelCopy = Readonly<{
|
|
13
20
|
title: string;
|
|
14
21
|
description: string;
|
|
15
22
|
locatorKindLabel: string;
|
|
16
|
-
|
|
23
|
+
/** Only entries authorized and supported by the owning product are shown. */
|
|
24
|
+
locatorKinds: Partial<Record<SubjectLocatorKind, string>>;
|
|
17
25
|
locatorLabel: string;
|
|
18
26
|
resolve: string;
|
|
19
27
|
resolving: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubjectAccessRequestPanel.d.ts","sourceRoot":"","sources":["../src/SubjectAccessRequestPanel.tsx"],"names":[],"mappings":"AAEA,MAAM,MAAM,kBAAkB,
|
|
1
|
+
{"version":3,"file":"SubjectAccessRequestPanel.d.ts","sourceRoot":"","sources":["../src/SubjectAccessRequestPanel.tsx"],"names":[],"mappings":"AAEA,MAAM,MAAM,kBAAkB,GAC1B,IAAI,GACJ,cAAc,GACd,SAAS,GACT,WAAW,GACX,QAAQ,GACR,eAAe,GACf,cAAc,CAAA;AAClB,MAAM,MAAM,0BAA0B,GAClC,MAAM,GACN,WAAW,GACX,UAAU,GACV,YAAY,GACZ,WAAW,GACX,SAAS,GACT,OAAO,CAAA;AAEX,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAAC;IAChD,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAC,CAAA;AAEF,MAAM,MAAM,2BAA2B,GAAG,QAAQ,CAAC;IACjD,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,2EAA2E;IAC3E,WAAW,CAAC,EAAE,SAAS,QAAQ,CAAC;QAC9B,IAAI,EAAE,kBAAkB,CAAA;QACxB,MAAM,EAAE,MAAM,CAAA;QACd,KAAK,EAAE,MAAM,CAAA;QACb,QAAQ,EAAE,OAAO,CAAA;KAClB,CAAC,EAAE,CAAA;CACL,CAAC,CAAA;AAEF,MAAM,MAAM,6BAA6B,GAAG,QAAQ,CAAC;IACnD,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,gBAAgB,EAAE,MAAM,CAAA;IACxB,6EAA6E;IAC7E,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC,CAAA;IACzD,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;CAChB,CAAC,CAAA;AAEF,MAAM,MAAM,8BAA8B,GAAG,QAAQ,CAAC;IACpD,IAAI,EAAE,6BAA6B,CAAA;IACnC,WAAW,EAAE,kBAAkB,CAAA;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,0BAA0B,CAAA;IAClC,MAAM,CAAC,EAAE,2BAA2B,CAAA;IACpC,QAAQ,EAAE,SAAS,0BAA0B,EAAE,CAAA;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,mBAAmB,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAA;IACvD,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACrC,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACtC,CAAC,CAAA;AAEF;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,IAAI,EACJ,WAAW,EACX,OAAO,EACP,MAAM,EACN,MAAM,EACN,QAAQ,EACR,KAAK,EACL,mBAAmB,EACnB,eAAe,EACf,SAAS,EACT,eAAe,EACf,SAAS,GACV,EAAE,8BAA8B,+BAgFhC"}
|
|
@@ -7,6 +7,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
7
7
|
* component; the authenticated BFF and GW decide identity and authorization.
|
|
8
8
|
*/
|
|
9
9
|
export function SubjectAccessRequestPanel({ copy, locatorKind, locator, status, target, sections, error, onLocatorKindChange, onLocatorChange, onResolve, onToggleSection, onRequest, }) {
|
|
10
|
+
const locatorInput = locatorInputAttributes(locatorKind);
|
|
10
11
|
function resolve(event) {
|
|
11
12
|
event.preventDefault();
|
|
12
13
|
void onResolve();
|
|
@@ -15,7 +16,18 @@ export function SubjectAccessRequestPanel({ copy, locatorKind, locator, status,
|
|
|
15
16
|
event.preventDefault();
|
|
16
17
|
void onRequest();
|
|
17
18
|
}
|
|
18
|
-
return (_jsxs("section", { className: "uhcp-access-panel", "aria-labelledby": "uhcp-access-request-title", children: [_jsx("h2", { id: "uhcp-access-request-title", children: copy.title }), _jsx("p", { children: copy.description }), _jsxs("form", { onSubmit: resolve, children: [_jsxs("label", { children: [_jsx("span", { children: copy.locatorKindLabel }), _jsx("select", { value: locatorKind, onChange: (event) => onLocatorKindChange(event.currentTarget.value), disabled: status === 'resolving', children: Object.entries(copy.locatorKinds).map(([kind, label]) => _jsx("option", { value: kind, children: label }, kind)) })] }), _jsxs("label", { children: [_jsx("span", { children: copy.locatorLabel }), _jsx("input", { value: locator, onChange: (event) => onLocatorChange(event.currentTarget.value), required: true, disabled: status === 'resolving' })] }), _jsx("button", { type: "submit", disabled: status === 'resolving' || !locator.trim(), children: status === 'resolving' ? copy.resolving : copy.resolve })] }), target && (_jsxs("form", { onSubmit: request, children: [_jsx("p", { children: _jsx("bdi", { children: target.display }) }), _jsxs("fieldset", { children: [_jsx("legend", { children: copy.sectionsLabel }), sections.map((section) => (_jsxs("label", { "data-section-code": section.code, children: [_jsx("input", { type: "checkbox", checked: section.selected, onChange: () => onToggleSection(section.code), disabled: status === 'requesting' || status === 'granted' }), _jsx("span", { children: section.label })] }, section.code)))] }), _jsx("button", { type: "submit", disabled: status === 'requesting'
|
|
19
|
+
return (_jsxs("section", { className: "uhcp-access-panel", "aria-labelledby": "uhcp-access-request-title", children: [_jsx("h2", { id: "uhcp-access-request-title", children: copy.title }), _jsx("p", { children: copy.description }), _jsxs("form", { onSubmit: resolve, children: [_jsxs("label", { children: [_jsx("span", { children: copy.locatorKindLabel }), _jsx("select", { value: locatorKind, onChange: (event) => onLocatorKindChange(event.currentTarget.value), disabled: status === 'resolving', children: Object.entries(copy.locatorKinds).map(([kind, label]) => _jsx("option", { value: kind, children: label }, kind)) })] }), _jsxs("label", { children: [_jsx("span", { children: copy.locatorLabel }), _jsx("input", { value: locator, onChange: (event) => onLocatorChange(event.currentTarget.value), type: locatorInput.type, inputMode: locatorInput.inputMode, pattern: locatorInput.pattern, required: true, disabled: status === 'resolving' })] }), _jsx("button", { type: "submit", disabled: status === 'resolving' || !locator.trim(), children: status === 'resolving' ? copy.resolving : copy.resolve })] }), target && (_jsxs("form", { onSubmit: request, children: [_jsx("p", { children: _jsx("bdi", { children: target.display }) }), _jsxs("fieldset", { children: [_jsx("legend", { children: copy.sectionsLabel }), sections.map((section) => (_jsxs("label", { "data-section-code": section.code, children: [_jsx("input", { type: "checkbox", checked: section.selected, onChange: () => onToggleSection(section.code), disabled: status === 'requesting' || status === 'granted' }), _jsx("span", { children: section.label })] }, section.code)))] }), _jsx("button", { type: "submit", disabled: status === 'requesting'
|
|
19
20
|
|| status === 'granted'
|
|
20
21
|
|| !sections.some((section) => section.selected), children: status === 'requesting' ? copy.requesting : copy.request })] })), status === 'requested' && _jsx("p", { role: "status", children: copy.requested }), status === 'granted' && _jsx("p", { role: "status", children: copy.granted }), error && _jsx("p", { role: "alert", children: error })] }));
|
|
21
22
|
}
|
|
23
|
+
function locatorInputAttributes(kind) {
|
|
24
|
+
if (kind === 'microchip')
|
|
25
|
+
return { inputMode: 'numeric', pattern: '[0-9 -]{15,21}' };
|
|
26
|
+
if (kind === 'numeric-code')
|
|
27
|
+
return { inputMode: 'numeric' };
|
|
28
|
+
if (kind === 'email-address')
|
|
29
|
+
return { type: 'email', inputMode: 'email' };
|
|
30
|
+
if (kind === 'phone-number')
|
|
31
|
+
return { type: 'tel', inputMode: 'tel' };
|
|
32
|
+
return {};
|
|
33
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -16,4 +16,6 @@ export * from './ProtectedIndexEmergencyData.js';
|
|
|
16
16
|
export * from './PortalSettingsPanel.js';
|
|
17
17
|
export * from './LegalMarkdownDocument.js';
|
|
18
18
|
export * from './IdentityEvidenceWorkspace.js';
|
|
19
|
+
export * from './IdentityEvidenceDocumentPanel.js';
|
|
20
|
+
export * from './IdentityEvidenceDeclarationForm.js';
|
|
19
21
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,yBAAyB,CAAA;AACvC,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA;AACrC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,0CAA0C,CAAA;AACxD,cAAc,kCAAkC,CAAA;AAChD,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,gCAAgC,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,yBAAyB,CAAA;AACvC,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA;AACrC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,0CAA0C,CAAA;AACxD,cAAc,kCAAkC,CAAA;AAChD,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,oCAAoC,CAAA;AAClD,cAAc,sCAAsC,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -16,3 +16,5 @@ export * from './ProtectedIndexEmergencyData.js';
|
|
|
16
16
|
export * from './PortalSettingsPanel.js';
|
|
17
17
|
export * from './LegalMarkdownDocument.js';
|
|
18
18
|
export * from './IdentityEvidenceWorkspace.js';
|
|
19
|
+
export * from './IdentityEvidenceDocumentPanel.js';
|
|
20
|
+
export * from './IdentityEvidenceDeclarationForm.js';
|
package/dist/styles.css
CHANGED
|
@@ -277,8 +277,29 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
|
|
|
277
277
|
.uhcp-identity-upload-action:hover { border-color: var(--uhcp-turquoise); }
|
|
278
278
|
.uhcp-identity-upload-action:disabled { cursor: not-allowed; opacity: .6; }
|
|
279
279
|
.uhcp-identity-upload-action small { color: var(--uhcp-muted); line-height: 1.45; }
|
|
280
|
+
.uhcp-identity-documents { background: var(--uhcp-panel); border: 1px solid var(--uhcp-border); border-radius: 1.5rem; color: var(--uhcp-text); display: grid; gap: 1rem; padding: 1.25rem; }
|
|
281
|
+
.uhcp-identity-documents h3, .uhcp-identity-documents p { margin: 0; }
|
|
282
|
+
.uhcp-identity-documents header p, .uhcp-identity-documents small { color: var(--uhcp-muted); }
|
|
283
|
+
.uhcp-identity-documents label { display: grid; font-weight: 800; gap: .5rem; }
|
|
284
|
+
.uhcp-identity-documents input { border: 1px solid var(--uhcp-border); border-radius: .85rem; color: var(--uhcp-text); padding: .75rem; }
|
|
285
|
+
.uhcp-identity-documents > button, .uhcp-identity-documents li button { background: linear-gradient(135deg, var(--uhcp-action-start), var(--uhcp-action-end)); border: 0; border-radius: .85rem; color: #fff; cursor: pointer; font: inherit; font-weight: 800; min-height: 2.75rem; padding: .65rem 1rem; }
|
|
286
|
+
.uhcp-identity-documents button:disabled { cursor: not-allowed; opacity: .55; }
|
|
287
|
+
.uhcp-identity-documents ul { display: grid; gap: .65rem; list-style: none; margin: 0; padding: 0; }
|
|
288
|
+
.uhcp-identity-documents li { align-items: center; background: var(--uhcp-panel-muted); border-radius: 1rem; display: flex; gap: 1rem; justify-content: space-between; padding: .85rem; }
|
|
289
|
+
.uhcp-identity-documents li span { display: grid; gap: .25rem; }
|
|
290
|
+
.uhcp-identity-documents [role='alert'] { color: #c64747; font-weight: 800; }
|
|
291
|
+
.uhcp-identity-declaration { background: var(--uhcp-panel); border: 1px solid var(--uhcp-border); border-radius: 1.5rem; color: var(--uhcp-text); display: grid; gap: 1rem; padding: 1.25rem; }
|
|
292
|
+
.uhcp-identity-declaration h3, .uhcp-identity-declaration p { margin: 0; }
|
|
293
|
+
.uhcp-identity-declaration header p { color: var(--uhcp-muted); line-height: 1.55; margin-top: .4rem; }
|
|
294
|
+
.uhcp-identity-declaration-fields { display: grid; gap: 1rem; }
|
|
295
|
+
.uhcp-identity-declaration label { display: grid; font-weight: 800; gap: .5rem; }
|
|
296
|
+
.uhcp-identity-declaration label:has(input[type='checkbox']) { align-items: center; display: flex; }
|
|
297
|
+
.uhcp-identity-declaration input:not([type='checkbox']), .uhcp-identity-declaration select { background: var(--uhcp-panel); border: 1px solid var(--uhcp-border); border-radius: .85rem; color: var(--uhcp-text); font: inherit; min-height: 2.75rem; padding: .7rem .8rem; }
|
|
298
|
+
.uhcp-identity-declaration > button { background: linear-gradient(135deg, var(--uhcp-action-start), var(--uhcp-action-end)); border: 0; border-radius: .85rem; color: #fff; cursor: pointer; font: inherit; font-weight: 800; min-height: 2.75rem; padding: .65rem 1rem; }
|
|
299
|
+
.uhcp-identity-declaration [role='alert'] { color: #c64747; font-weight: 800; }
|
|
280
300
|
@media (min-width: 760px) {
|
|
281
301
|
.uhcp-identity-upload-actions { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
302
|
+
.uhcp-identity-declaration-fields { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
282
303
|
}
|
|
283
304
|
|
|
284
305
|
.uhcp-clinical-summary {
|
package/package.json
CHANGED