uhc-portal-components-react 0.2.36 → 0.2.37
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 +8 -0
- package/README.md +3 -2
- package/dist/ExistingProfessionalProfilePanel.d.ts +19 -1
- package/dist/ExistingProfessionalProfilePanel.d.ts.map +1 -1
- package/dist/ExistingProfessionalProfilePanel.js +39 -11
- package/dist/PortalHeader.d.ts.map +1 -1
- package/dist/PortalHeader.js +3 -5
- package/dist/ProfileIdentityTarget.d.ts +7 -0
- package/dist/ProfileIdentityTarget.d.ts.map +1 -0
- package/dist/ProfileIdentityTarget.js +10 -0
- package/dist/ProfileProtectionGateV2.d.ts.map +1 -1
- package/dist/ProfileProtectionGateV2.js +2 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/styles.css +9 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.37 - 2026-11-03
|
|
4
|
+
|
|
5
|
+
- Split existing-professional registration into evidence verification and
|
|
6
|
+
device-PIN setup so the verified role and organization are visible before a
|
|
7
|
+
local profile can be protected.
|
|
8
|
+
- Reuse one identity icon and resolved-profile target across the portal header,
|
|
9
|
+
profile unlock and professional registration screens.
|
|
10
|
+
|
|
3
11
|
## 0.2.36 - 2026-11-03
|
|
4
12
|
|
|
5
13
|
- Add an accessible shared card-provider selector that returns only the opaque
|
package/README.md
CHANGED
|
@@ -136,8 +136,9 @@ The package deliberately exposes modules instead of a cloned application:
|
|
|
136
136
|
BFF accepts the invitation.
|
|
137
137
|
- `ExistingProfessionalProfilePanel`: existing employees scan or upload a
|
|
138
138
|
signed professional-credential QR, or use the explicit DID/URN plus sector
|
|
139
|
-
fallback.
|
|
140
|
-
|
|
139
|
+
fallback. When the host supplies `onResolve`, the screen verifies and shows
|
|
140
|
+
the server-resolved role before it offers local device-PIN setup and DCR.
|
|
141
|
+
This screen never accepts an employee invitation.
|
|
141
142
|
- `SubjectAccessRequestPanel`: controlled provider-enabled QR, numeric-code,
|
|
142
143
|
`did:web`, microchip, tattoo, email or telephone locator. Resolution and
|
|
143
144
|
returned identifier evidence never grant subject access.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ProfileProtectionTargetV2 } from './contracts.js';
|
|
1
2
|
export type ExistingProfessionalProfileCopy = Readonly<{
|
|
2
3
|
eyebrow?: string;
|
|
3
4
|
title: string;
|
|
@@ -16,6 +17,11 @@ export type ExistingProfessionalProfileCopy = Readonly<{
|
|
|
16
17
|
pinLabel: string;
|
|
17
18
|
pinConfirmationLabel: string;
|
|
18
19
|
pinMismatch: string;
|
|
20
|
+
verify?: string;
|
|
21
|
+
verifying?: string;
|
|
22
|
+
verifiedProfile?: string;
|
|
23
|
+
changeEvidence?: string;
|
|
24
|
+
verificationFailed?: string;
|
|
19
25
|
submit: string;
|
|
20
26
|
submitting: string;
|
|
21
27
|
}>;
|
|
@@ -29,6 +35,17 @@ export type ExistingProfessionalProfileInput = Readonly<{
|
|
|
29
35
|
sector: string;
|
|
30
36
|
pin: string;
|
|
31
37
|
}>;
|
|
38
|
+
export type ExistingProfessionalEvidenceInput = Readonly<{
|
|
39
|
+
method: 'credential';
|
|
40
|
+
professionalCredential: string;
|
|
41
|
+
}> | Readonly<{
|
|
42
|
+
method: 'identifier';
|
|
43
|
+
professionalIdentifier: string;
|
|
44
|
+
sector: string;
|
|
45
|
+
}>;
|
|
46
|
+
export type ResolvedExistingProfessionalProfile = Omit<ProfileProtectionTargetV2, 'eyebrow'> & Readonly<{
|
|
47
|
+
eyebrow?: string;
|
|
48
|
+
}>;
|
|
32
49
|
export type ExistingProfessionalProfileRequest = Readonly<{
|
|
33
50
|
professionalCredential: string;
|
|
34
51
|
pin: string;
|
|
@@ -50,6 +67,7 @@ export type ExistingProfessionalProfilePanelProps = Readonly<{
|
|
|
50
67
|
error?: string;
|
|
51
68
|
onScanProfessionalCredential?: () => Promise<string | undefined>;
|
|
52
69
|
onReadProfessionalCredentialImage?: (file: File) => Promise<string | undefined>;
|
|
70
|
+
onResolve?: (input: ExistingProfessionalEvidenceInput) => Promise<ResolvedExistingProfessionalProfile>;
|
|
53
71
|
onSubmit: (input: ExistingProfessionalProfileInput) => void | Promise<void>;
|
|
54
72
|
}>;
|
|
55
73
|
/**
|
|
@@ -59,5 +77,5 @@ export type ExistingProfessionalProfilePanelProps = Readonly<{
|
|
|
59
77
|
* is the preferred path; a single DID-or-URN field plus sector is the explicit
|
|
60
78
|
* manual fallback and never becomes browser-selected authority by itself.
|
|
61
79
|
*/
|
|
62
|
-
export declare function ExistingProfessionalProfilePanel({ copy, sectors, busy, error, onScanProfessionalCredential, onReadProfessionalCredentialImage, onSubmit }: ExistingProfessionalProfilePanelProps): import("react").JSX.Element;
|
|
80
|
+
export declare function ExistingProfessionalProfilePanel({ copy, sectors, busy, error, onScanProfessionalCredential, onReadProfessionalCredentialImage, onResolve, onSubmit }: ExistingProfessionalProfilePanelProps): import("react").JSX.Element;
|
|
63
81
|
//# sourceMappingURL=ExistingProfessionalProfilePanel.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExistingProfessionalProfilePanel.d.ts","sourceRoot":"","sources":["../src/ExistingProfessionalProfilePanel.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ExistingProfessionalProfilePanel.d.ts","sourceRoot":"","sources":["../src/ExistingProfessionalProfilePanel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useRef, useState } from 'react';
|
|
4
4
|
import jsQrModule from 'jsqr';
|
|
5
|
+
import { ProfileIdentityTarget } from './ProfileIdentityTarget.js';
|
|
5
6
|
const decodeQrImage = jsQrModule;
|
|
6
7
|
/** Shared BFF serialization keeps professional evidence distinct from an invitation code. */
|
|
7
8
|
export function toExistingProfessionalProfileRequest(input) {
|
|
@@ -16,13 +17,15 @@ export function toExistingProfessionalProfileRequest(input) {
|
|
|
16
17
|
* is the preferred path; a single DID-or-URN field plus sector is the explicit
|
|
17
18
|
* manual fallback and never becomes browser-selected authority by itself.
|
|
18
19
|
*/
|
|
19
|
-
export function ExistingProfessionalProfilePanel({ copy, sectors, busy, error, onScanProfessionalCredential, onReadProfessionalCredentialImage, onSubmit }) {
|
|
20
|
+
export function ExistingProfessionalProfilePanel({ copy, sectors, busy, error, onScanProfessionalCredential, onReadProfessionalCredentialImage, onResolve, onSubmit }) {
|
|
20
21
|
const [method, setMethod] = useState('credential');
|
|
21
22
|
const [professionalCredential, setProfessionalCredential] = useState('');
|
|
22
23
|
const [professionalIdentifier, setProfessionalIdentifier] = useState('');
|
|
23
24
|
const [sector, setSector] = useState(sectors[0]?.value || '');
|
|
24
25
|
const [pin, setPin] = useState('');
|
|
25
26
|
const [pinConfirmation, setPinConfirmation] = useState('');
|
|
27
|
+
const [resolvedProfile, setResolvedProfile] = useState();
|
|
28
|
+
const [resolving, setResolving] = useState(false);
|
|
26
29
|
const [localError, setLocalError] = useState('');
|
|
27
30
|
const [cameraActive, setCameraActive] = useState(false);
|
|
28
31
|
const videoRef = useRef(null);
|
|
@@ -105,28 +108,53 @@ export function ExistingProfessionalProfilePanel({ copy, sectors, busy, error, o
|
|
|
105
108
|
}
|
|
106
109
|
setProfessionalCredential(credential);
|
|
107
110
|
}
|
|
108
|
-
function
|
|
111
|
+
function evidenceInput() {
|
|
112
|
+
if (method === 'credential') {
|
|
113
|
+
if (!professionalCredential) {
|
|
114
|
+
setLocalError(copy.professionalCredentialRequired);
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
return { method, professionalCredential: professionalCredential.trim() };
|
|
118
|
+
}
|
|
119
|
+
return { method, professionalIdentifier: professionalIdentifier.trim(), sector };
|
|
120
|
+
}
|
|
121
|
+
async function submit(event) {
|
|
109
122
|
event.preventDefault();
|
|
123
|
+
const evidence = evidenceInput();
|
|
124
|
+
if (!evidence)
|
|
125
|
+
return;
|
|
126
|
+
if (onResolve && !resolvedProfile) {
|
|
127
|
+
setLocalError('');
|
|
128
|
+
setResolving(true);
|
|
129
|
+
try {
|
|
130
|
+
setResolvedProfile(await onResolve(evidence));
|
|
131
|
+
}
|
|
132
|
+
catch (reason) {
|
|
133
|
+
setLocalError(reason instanceof Error ? reason.message : copy.verificationFailed || 'professional_profile_verification_failed');
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
setResolving(false);
|
|
137
|
+
}
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
110
140
|
if (pin !== pinConfirmation) {
|
|
111
141
|
setLocalError(copy.pinMismatch);
|
|
112
142
|
return;
|
|
113
143
|
}
|
|
114
144
|
setLocalError('');
|
|
115
|
-
if (method === 'credential') {
|
|
116
|
-
|
|
117
|
-
setLocalError(copy.professionalCredentialRequired);
|
|
118
|
-
return;
|
|
119
|
-
}
|
|
120
|
-
void onSubmit({ method, professionalCredential: professionalCredential.trim(), pin });
|
|
145
|
+
if (evidence.method === 'credential') {
|
|
146
|
+
void onSubmit({ ...evidence, pin });
|
|
121
147
|
return;
|
|
122
148
|
}
|
|
123
|
-
void onSubmit({
|
|
149
|
+
void onSubmit({ ...evidence, pin });
|
|
124
150
|
}
|
|
125
|
-
|
|
151
|
+
if (onResolve && resolvedProfile)
|
|
152
|
+
return _jsxs("section", { className: "uhcp-professional-activation uhcp-professional-pin-setup", "aria-labelledby": "uhcp-existing-professional-pin-title", children: [_jsxs("header", { children: [_jsx("h1", { id: "uhcp-existing-professional-pin-title", children: copy.verifiedProfile || copy.title }), _jsx("p", { children: copy.description })] }), _jsx(ProfileIdentityTarget, { target: { eyebrow: copy.verifiedProfile || '', ...resolvedProfile } }), _jsxs("form", { onSubmit: submit, children: [_jsxs("label", { children: [_jsx("span", { children: copy.pinLabel }), _jsx("input", { name: "newPin", type: "password", inputMode: "numeric", minLength: 6, maxLength: 12, autoComplete: "new-password", value: pin, onChange: event => setPin(event.currentTarget.value), required: true })] }), _jsxs("label", { children: [_jsx("span", { children: copy.pinConfirmationLabel }), _jsx("input", { name: "confirmPin", type: "password", inputMode: "numeric", minLength: 6, maxLength: 12, autoComplete: "new-password", value: pinConfirmation, onChange: event => setPinConfirmation(event.currentTarget.value), required: true })] }), (localError || error) ? _jsx("p", { role: "alert", children: localError || error }) : null, _jsx("button", { type: "submit", disabled: busy, children: busy ? copy.submitting : copy.submit }), _jsx("button", { type: "button", className: "uhcp-secondary-action", disabled: busy, onClick: () => { setResolvedProfile(undefined); setPin(''); setPinConfirmation(''); setLocalError(''); }, children: copy.changeEvidence || copy.manualMethodLabel })] })] });
|
|
153
|
+
return _jsx("section", { className: "uhcp-professional-activation", "aria-labelledby": "uhcp-existing-professional-title", children: _jsxs("form", { onSubmit: submit, children: [_jsxs("header", { children: [copy.eyebrow ? _jsx("p", { className: "uhcp-eyebrow", children: copy.eyebrow }) : null, _jsx("h1", { id: "uhcp-existing-professional-title", children: copy.title }), _jsx("p", { children: copy.description })] }), _jsxs("fieldset", { className: "uhcp-professional-evidence-methods", children: [_jsxs("label", { children: [_jsx("input", { type: "radio", name: "professionalEvidenceMethod", value: "credential", checked: method === 'credential', onChange: () => { setMethod('credential'); setLocalError(''); } }), _jsx("span", { children: copy.credentialMethodLabel })] }), _jsxs("label", { children: [_jsx("input", { type: "radio", name: "professionalEvidenceMethod", value: "identifier", checked: method === 'identifier', onChange: () => { setMethod('identifier'); setLocalError(''); } }), _jsx("span", { children: copy.manualMethodLabel })] })] }), method === 'credential'
|
|
126
154
|
? _jsxs("div", { className: "uhcp-professional-credential-capture", children: [_jsx("button", { type: "button", disabled: busy, onClick: () => void captureCredential(scanWithCamera).catch(() => setLocalError(copy.professionalCredentialRequired)), children: copy.scanProfessionalCredential }), _jsxs("label", { children: [_jsx("span", { children: copy.uploadProfessionalCredentialQr }), _jsx("input", { name: "professionalCredentialQrImage", type: "file", accept: "image/png,image/jpeg,image/webp", disabled: busy, onChange: event => {
|
|
127
155
|
const file = event.currentTarget.files?.[0];
|
|
128
156
|
if (file)
|
|
129
157
|
void captureCredential(() => readCredentialImage(file)).catch(() => setLocalError(copy.credentialQrUnreadable));
|
|
130
158
|
} })] }), cameraActive ? _jsxs(_Fragment, { children: [_jsx("video", { ref: videoRef, playsInline: true, muted: true, "aria-label": copy.cameraActive }), _jsx("p", { role: "status", children: copy.cameraActive }), _jsx("button", { type: "button", onClick: () => stopCamera(), children: copy.closeCamera })] }) : _jsx("video", { ref: videoRef, hidden: true, playsInline: true, muted: true }), _jsx("canvas", { ref: canvasRef, hidden: true, "aria-hidden": "true" }), professionalCredential ? _jsx("p", { role: "status", children: copy.professionalCredentialReady }) : null] })
|
|
131
|
-
: _jsxs(_Fragment, { children: [_jsxs("label", { children: [_jsx("span", { children: copy.professionalIdentifierLabel }), _jsx("input", { name: "professionalIdentifier", value: professionalIdentifier, onChange: event => setProfessionalIdentifier(event.currentTarget.value), autoComplete: "off", required: true })] }), _jsxs("label", { children: [_jsx("span", { children: copy.sectorLabel }), _jsx("select", { name: "professionalSector", value: sector, onChange: event => setSector(event.currentTarget.value), required: true, children: sectors.map(option => _jsx("option", { value: option.value, children: option.label }, option.value)) })] })] }), _jsxs("label", { children: [_jsx("span", { children: copy.pinLabel }), _jsx("input", { name: "newPin", type: "password", inputMode: "numeric", minLength: 6, maxLength: 12, autoComplete: "new-password", value: pin, onChange: event => setPin(event.currentTarget.value), required: true })] }), _jsxs("label", { children: [_jsx("span", { children: copy.pinConfirmationLabel }), _jsx("input", { name: "confirmPin", type: "password", inputMode: "numeric", minLength: 6, maxLength: 12, autoComplete: "new-password", value: pinConfirmation, onChange: event => setPinConfirmation(event.currentTarget.value), required: true })] }), (localError || error) ? _jsx("p", { role: "alert", children: localError || error }) : null, _jsx("button", { type: "submit", disabled: busy, children: busy ? copy.submitting : copy.submit })] }) });
|
|
159
|
+
: _jsxs(_Fragment, { children: [_jsxs("label", { children: [_jsx("span", { children: copy.professionalIdentifierLabel }), _jsx("input", { name: "professionalIdentifier", value: professionalIdentifier, onChange: event => setProfessionalIdentifier(event.currentTarget.value), autoComplete: "off", required: true })] }), _jsxs("label", { children: [_jsx("span", { children: copy.sectorLabel }), _jsx("select", { name: "professionalSector", value: sector, onChange: event => setSector(event.currentTarget.value), required: true, children: sectors.map(option => _jsx("option", { value: option.value, children: option.label }, option.value)) })] })] }), !onResolve ? _jsxs(_Fragment, { children: [_jsxs("label", { children: [_jsx("span", { children: copy.pinLabel }), _jsx("input", { name: "newPin", type: "password", inputMode: "numeric", minLength: 6, maxLength: 12, autoComplete: "new-password", value: pin, onChange: event => setPin(event.currentTarget.value), required: true })] }), _jsxs("label", { children: [_jsx("span", { children: copy.pinConfirmationLabel }), _jsx("input", { name: "confirmPin", type: "password", inputMode: "numeric", minLength: 6, maxLength: 12, autoComplete: "new-password", value: pinConfirmation, onChange: event => setPinConfirmation(event.currentTarget.value), required: true })] })] }) : null, (localError || error) ? _jsx("p", { role: "alert", children: localError || error }) : null, _jsx("button", { type: "submit", disabled: busy || resolving, children: resolving ? copy.verifying || copy.submitting : onResolve ? copy.verify || copy.submit : busy ? copy.submitting : copy.submit })] }) });
|
|
132
160
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PortalHeader.d.ts","sourceRoot":"","sources":["../src/PortalHeader.tsx"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EAEpB,KAAK,aAAa,EACnB,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"PortalHeader.d.ts","sourceRoot":"","sources":["../src/PortalHeader.tsx"],"names":[],"mappings":"AAGA,OAAO,EAGL,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EAEpB,KAAK,aAAa,EACnB,MAAM,gBAAgB,CAAA;AAQvB,OAAO,EAGL,KAAK,gCAAgC,EACtC,MAAM,2BAA2B,CAAA;AAElC,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC,KAAK,EAAE,WAAW,CAAA;IAClB,IAAI,EAAE,eAAe,CAAA;IACrB,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACjC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,eAAe,CAAC,EAAE,SAAS,oBAAoB,EAAE,CAAA;IACjD,eAAe,EAAE,MAAM,CAAA;IACvB,cAAc,CAAC,EAAE,SAAS,mBAAmB,EAAE,CAAA;IAC/C,eAAe,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACtC,WAAW,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAA;IACzC,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACtC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAA;IAC9C,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,cAAc,CAAC,EAAE,gCAAgC,CAAA;CAClD,CAAC,CAAA;AAEF;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,IAAI,EACJ,iBAAiB,EACjB,YAAY,EACZ,eAAoB,EACpB,eAAe,EACf,cAAmB,EACnB,eAAe,EACf,WAAgB,EAChB,SAAS,EACT,aAAa,EACb,gBAA+B,EAC/B,cAAc,GACf,EAAE,iBAAiB,+BAgMnB"}
|
package/dist/PortalHeader.js
CHANGED
|
@@ -4,6 +4,7 @@ import { useEffect, useRef, useState } from 'react';
|
|
|
4
4
|
import { portalUiDensities, portalUiThemes, } from './contracts.js';
|
|
5
5
|
import { resolvePortalUiDensity, resolvePortalUiTheme, resolveRenderedPortalTheme, } from './preferences.js';
|
|
6
6
|
import { PortalBrandArtwork } from './PortalBrandArtwork.js';
|
|
7
|
+
import { ProfileIdentityIcon } from './ProfileIdentityTarget.js';
|
|
7
8
|
import { PortalCurrentSubjectControl, PortalCurrentSubjectSlot, } from './PortalCurrentSubject.js';
|
|
8
9
|
/**
|
|
9
10
|
* Shared account/preferences header.
|
|
@@ -68,7 +69,7 @@ export function PortalHeader({ brand, copy, accountIdentifier, languageHref, lan
|
|
|
68
69
|
}
|
|
69
70
|
return (_jsxs("header", { className: "uhcp-header", style: brand.variables, children: [brand.mark && brand.markHref ? (_jsxs("div", { className: "uhcp-brand", children: [_jsx("a", { className: "uhcp-brand-mark-link", href: brand.markHref, "aria-label": brand.productName, children: _jsx(PortalBrandArtwork, { artwork: brand.mark, className: "uhcp-brand-mark" }) }), _jsx("a", { className: "uhcp-brand-copy", href: brand.homeHref, "aria-label": copy.home, children: _jsxs("span", { children: [_jsx("strong", { children: brand.productName }), _jsx("small", { className: accountIdentifier ? 'uhcp-brand-account' : undefined, children: accountIdentifier || brand.organizationName })] }) })] })) : (_jsxs("a", { className: "uhcp-brand", href: brand.homeHref, "aria-label": copy.home, children: [brand.mark ? (_jsx(PortalBrandArtwork, { artwork: brand.mark, className: "uhcp-brand-mark" })) : null, _jsxs("span", { children: [_jsx("strong", { children: brand.productName }), _jsx("small", { className: accountIdentifier ? 'uhcp-brand-account' : undefined, children: accountIdentifier || brand.organizationName })] })] })), currentSubject
|
|
70
71
|
? _jsx(PortalCurrentSubjectControl, { ...currentSubject })
|
|
71
|
-
: _jsx(PortalCurrentSubjectSlot, {}), _jsxs("div", { className: "uhcp-account-menu", ref: ref, children: [_jsx("button", { type: "button", className: "uhcp-trigger", onClick: () => setOpen((value) => !value), "aria-label": copy.accountAndPreferences, "aria-expanded": open, children: _jsx(
|
|
72
|
+
: _jsx(PortalCurrentSubjectSlot, {}), _jsxs("div", { className: "uhcp-account-menu", ref: ref, children: [_jsx("button", { type: "button", className: "uhcp-trigger", onClick: () => setOpen((value) => !value), "aria-label": copy.accountAndPreferences, "aria-expanded": open, children: _jsx(ProfileIdentityIcon, {}) }), open && (_jsxs("section", { className: "uhcp-menu", "aria-label": copy.accountAndPreferences, children: [_jsxs("div", { className: "uhcp-account-state", children: [_jsx("strong", { children: copy.accountAndPreferences }), _jsx("small", { children: accountIdentifier || copy.notSignedIn })] }), accountOptions.length > 0 && (_jsx("div", { className: "uhcp-account-options", children: accountOptions.map((option) => (_jsxs("button", { type: "button", disabled: option.disabled, "aria-pressed": Boolean(option.selected), onClick: () => {
|
|
72
73
|
onSelectAccount?.(option.id);
|
|
73
74
|
setOpen(false);
|
|
74
75
|
}, children: [_jsx("span", { children: option.label }), option.description && _jsx("small", { children: option.description })] }, option.id))) })), _jsx(PreferenceGroup, { label: copy.appearance, children: portalUiThemes.map((value) => (_jsxs("button", { type: "button", "aria-pressed": theme === value, onClick: () => changeTheme(value), children: [_jsx("span", { "aria-hidden": "true", children: value === 'light' ? '☀' : value === 'dark' ? '☾' : '◫' }), copy.themes[value]] }, value))) }), _jsx(PreferenceGroup, { label: copy.textSize, children: portalUiDensities.map((value) => (_jsx("button", { type: "button", "aria-pressed": density === value, onClick: () => changeDensity(value), children: value === 'small' ? 'S' : value === 'medium' ? 'M' : 'L' }, value))) }), _jsxs("div", { className: "uhcp-menu-actions", children: [languageOptions.length > 0
|
|
@@ -80,11 +81,8 @@ export function PortalHeader({ brand, copy, accountIdentifier, languageHref, lan
|
|
|
80
81
|
void action.onSelect?.();
|
|
81
82
|
}, children: action.label }, action.id))), accountIdentifier && onSignOut
|
|
82
83
|
? _jsxs("button", { type: "button", onClick: () => { setOpen(false); void onSignOut(); }, children: ["\u21AA ", copy.signOut] })
|
|
83
|
-
: _jsxs("a", { href: guestActionHref, onClick: () => setOpen(false), children: [_jsx(
|
|
84
|
+
: _jsxs("a", { href: guestActionHref, onClick: () => setOpen(false), children: [_jsx(ProfileIdentityIcon, {}), " ", copy.chooseAccess] })] })] }))] })] }));
|
|
84
85
|
}
|
|
85
86
|
function PreferenceGroup({ label, children }) {
|
|
86
87
|
return _jsxs("fieldset", { className: "uhcp-preferences", children: [_jsx("legend", { children: label }), _jsx("div", { children: children })] });
|
|
87
88
|
}
|
|
88
|
-
function PersonIcon() {
|
|
89
|
-
return (_jsxs("svg", { className: "uhcp-person-icon", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [_jsx("path", { d: "M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8Z", stroke: "currentColor", strokeWidth: "1.8" }), _jsx("path", { d: "M4.5 21a7.5 7.5 0 0 1 15 0", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" })] }));
|
|
90
|
-
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ProfileProtectionTargetV2 } from './contracts.js';
|
|
2
|
+
export declare function ProfileIdentityIcon(): import("react").JSX.Element;
|
|
3
|
+
/** Shared presentation for one host-resolved profile. It never selects or grants a role. */
|
|
4
|
+
export declare function ProfileIdentityTarget({ target }: Readonly<{
|
|
5
|
+
target: ProfileProtectionTargetV2;
|
|
6
|
+
}>): import("react").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=ProfileIdentityTarget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ProfileIdentityTarget.d.ts","sourceRoot":"","sources":["../src/ProfileIdentityTarget.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAA;AAE/D,wBAAgB,mBAAmB,gCAKlC;AAED,4FAA4F;AAC5F,wBAAgB,qBAAqB,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,CAAC;IAAE,MAAM,EAAE,yBAAyB,CAAA;CAAE,CAAC,+BAkBhG"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export function ProfileIdentityIcon() {
|
|
3
|
+
return _jsxs("svg", { "data-testid": "professional-identity-icon", className: "uhcp-person-icon", viewBox: "0 0 24 24", fill: "none", "aria-hidden": "true", children: [_jsx("path", { d: "M12 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8Z", stroke: "currentColor", strokeWidth: "1.8" }), _jsx("path", { d: "M4.5 21a7.5 7.5 0 0 1 15 0", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round" })] });
|
|
4
|
+
}
|
|
5
|
+
/** Shared presentation for one host-resolved profile. It never selects or grants a role. */
|
|
6
|
+
export function ProfileIdentityTarget({ target }) {
|
|
7
|
+
return _jsxs("div", { className: "uhcp-profile-target", children: [target.icon
|
|
8
|
+
? _jsx("img", { src: target.icon.src, alt: target.icon.alt, width: target.icon.width, height: target.icon.height })
|
|
9
|
+
: _jsx("span", { className: "uhcp-profile-target-default-icon", children: _jsx(ProfileIdentityIcon, {}) }), _jsxs("div", { className: "uhcp-profile-target-content", children: [_jsxs("div", { className: "uhcp-profile-target-copy", children: [_jsx("strong", { children: target.title }), target.subtitle && _jsx("span", { children: target.subtitle })] }), target.badges?.length ? _jsx("ul", { className: "uhcp-profile-target-badges uhcp-profile-target-badges-centered", "aria-label": target.title, children: target.badges.map(badge => _jsx("li", { children: badge }, badge)) }) : null, target.details?.length ? _jsx("dl", { className: "uhcp-profile-target-details", children: target.details.map(detail => _jsxs("div", { children: [_jsx("dt", { children: detail.label }), _jsx("dd", { children: detail.value })] }, `${detail.label}:${detail.value}`)) }) : null] })] });
|
|
10
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ProfileProtectionGateV2.d.ts","sourceRoot":"","sources":["../src/ProfileProtectionGateV2.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA+C,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AACnF,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACtB,yBAAyB,EACzB,mBAAmB,EACpB,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"ProfileProtectionGateV2.d.ts","sourceRoot":"","sources":["../src/ProfileProtectionGateV2.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA+C,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AACnF,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACtB,yBAAyB,EACzB,mBAAmB,EACpB,MAAM,gBAAgB,CAAA;AAGvB,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,KAAK,EAAE,sBAAsB,CAAA;IAC7B,MAAM,EAAE,yBAAyB,CAAA;IACjC,IAAI,EAAE,uBAAuB,CAAA;IAC7B,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAC9E,eAAe,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,iBAAiB,CAAC,EAAE,SAAS,CAAA;IAC7B,gBAAgB,CAAC,EAAE,SAAS,CAAA;IAC5B,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAC,CAAA;AAEF;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,KAAK,EACL,MAAM,EACN,IAAI,EACJ,QAAQ,EACR,eAAe,EACf,OAAO,EACP,iBAAiB,EACjB,gBAAgB,EAChB,QAAQ,GACT,EAAE,4BAA4B,+BA0G9B"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useEffect, useRef, useState } from 'react';
|
|
4
|
+
import { ProfileIdentityTarget } from './ProfileIdentityTarget.js';
|
|
4
5
|
/**
|
|
5
6
|
* Presentation-only profile gate that identifies the host-authorized target.
|
|
6
7
|
*
|
|
@@ -79,5 +80,5 @@ export function ProfileProtectionGateV2({ state, target, copy, onUnlock, onPassk
|
|
|
79
80
|
: state === 'unavailable'
|
|
80
81
|
? copy.unavailableBody
|
|
81
82
|
: copy.unlockBody;
|
|
82
|
-
return (_jsxs("section", { className: "uhcp-profile-gate uhcp-profile-gate-v2", "aria-live": "polite", children: [_jsxs("div", { className: "uhcp-profile-gate-copy", children: [_jsx("h1", { children: title }), _jsx("p", { children: body })] }),
|
|
83
|
+
return (_jsxs("section", { className: "uhcp-profile-gate uhcp-profile-gate-v2", "aria-live": "polite", children: [_jsxs("div", { className: "uhcp-profile-gate-copy", children: [_jsx("h1", { children: title }), _jsx("p", { children: body })] }), _jsx(ProfileIdentityTarget, { target: target }), state === 'locked' && onPasskeyUnlock && _jsx("button", { type: "button", className: "uhcp-action-unlock", "data-portal-action": "unlock-profile-with-passkey", disabled: busy, onClick: unlockWithPasskey, children: copy.unlockWithPasskey }), state === 'locked' && _jsxs("details", { className: "uhcp-profile-pin-fallback", open: !onPasskeyUnlock, children: [_jsx("summary", { children: onPasskeyUnlock ? copy.usePinInstead : copy.pinLabel }), _jsxs("form", { onSubmit: unlock, children: [_jsxs("label", { children: [copy.pinLabel, _jsx("input", { ref: input, type: "password", inputMode: "numeric", minLength: 6, autoComplete: "current-password", value: pin, onChange: (event) => setPin(event.target.value) })] }), error && _jsx("p", { role: "alert", className: "uhcp-error", children: error }), _jsx("button", { type: "submit", className: "uhcp-action-unlock", "data-portal-action": "unlock-profile", disabled: busy, children: copy.unlock })] }), pinRejected && pinFailureActions ? _jsx("div", { className: "uhcp-profile-pin-recovery", children: pinFailureActions }) : null] }), state === 'unavailable' && onRetry && _jsx("button", { type: "button", onClick: onRetry, children: copy.retry }), secondaryActions && _jsx("div", { className: "uhcp-profile-gate-secondary", children: secondaryActions })] }));
|
|
83
84
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from './PortalShell.js';
|
|
|
7
7
|
export * from './PortalEntry.js';
|
|
8
8
|
export * from './ProfileProtectionGate.js';
|
|
9
9
|
export * from './ProfileProtectionGateV2.js';
|
|
10
|
+
export * from './ProfileIdentityTarget.js';
|
|
10
11
|
export * from './PortalLoadingSkeleton.js';
|
|
11
12
|
export * from './ClinicalSectionSummary.js';
|
|
12
13
|
export * from './IpsBundleSummary.js';
|
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,2BAA2B,CAAA;AACzC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA;AACrC,cAAc,wCAAwC,CAAA;AACtD,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,mCAAmC,CAAA;AACjD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,qCAAqC,CAAA;AACnD,cAAc,mCAAmC,CAAA;AACjD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,0BAA0B,CAAA;AACxC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,iCAAiC,CAAA;AAC/C,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;AACpD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,yBAAyB,CAAA;AACvC,cAAc,uCAAuC,CAAA;AACrD,cAAc,uBAAuB,CAAA;AACrC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,kBAAkB,CAAA;AAChC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,yCAAyC,CAAA;AACvD,cAAc,uCAAuC,CAAA;AACrD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,qBAAqB,CAAA;AACnC,cAAc,2BAA2B,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,2BAA2B,CAAA;AACzC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA;AACrC,cAAc,wCAAwC,CAAA;AACtD,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,mCAAmC,CAAA;AACjD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,qCAAqC,CAAA;AACnD,cAAc,mCAAmC,CAAA;AACjD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,0BAA0B,CAAA;AACxC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,iCAAiC,CAAA;AAC/C,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;AACpD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,yBAAyB,CAAA;AACvC,cAAc,uCAAuC,CAAA;AACrD,cAAc,uBAAuB,CAAA;AACrC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,uBAAuB,CAAA;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,kBAAkB,CAAA;AAChC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,yCAAyC,CAAA;AACvD,cAAc,uCAAuC,CAAA;AACrD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,qBAAqB,CAAA;AACnC,cAAc,2BAA2B,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export * from './PortalShell.js';
|
|
|
7
7
|
export * from './PortalEntry.js';
|
|
8
8
|
export * from './ProfileProtectionGate.js';
|
|
9
9
|
export * from './ProfileProtectionGateV2.js';
|
|
10
|
+
export * from './ProfileIdentityTarget.js';
|
|
10
11
|
export * from './PortalLoadingSkeleton.js';
|
|
11
12
|
export * from './ClinicalSectionSummary.js';
|
|
12
13
|
export * from './IpsBundleSummary.js';
|
package/dist/styles.css
CHANGED
|
@@ -192,6 +192,8 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
|
|
|
192
192
|
.uhcp-profile-gate-copy p { margin-top: .45rem; }
|
|
193
193
|
.uhcp-profile-target { align-items: center; background: var(--uhcp-panel); border: 1px solid color-mix(in srgb, var(--uhcp-turquoise) 32%, var(--uhcp-border)); border-radius: 1rem; display: grid; gap: 1rem; grid-template-columns: auto minmax(0, 1fr); padding: 1rem; }
|
|
194
194
|
.uhcp-profile-target > img { background: var(--uhcp-panel); border-radius: .75rem; object-fit: contain; }
|
|
195
|
+
.uhcp-profile-target-default-icon { align-items: center; background: var(--uhcp-surface-muted); border: 1px solid var(--uhcp-border); border-radius: 50%; color: var(--uhcp-turquoise); display: flex; height: 4.5rem; justify-content: center; width: 4.5rem; }
|
|
196
|
+
.uhcp-profile-target-default-icon .uhcp-person-icon { height: 2.3rem; width: 2.3rem; }
|
|
195
197
|
.uhcp-profile-target-content { display: grid; gap: .65rem; min-width: 0; }
|
|
196
198
|
.uhcp-profile-target-copy { display: grid; gap: .2rem; text-align: left; }
|
|
197
199
|
.uhcp-profile-target-copy > strong { color: var(--uhcp-text); font-size: 1.2rem; }
|
|
@@ -211,6 +213,13 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
|
|
|
211
213
|
.uhcp-profile-target-badges-centered { justify-content: center; }
|
|
212
214
|
}
|
|
213
215
|
.uhcp-profile-pin-fallback { border-top: 1px solid var(--uhcp-border); padding-top: .8rem; }
|
|
216
|
+
.uhcp-professional-evidence-methods { border: 0; display: grid; gap: .75rem; margin: 0; padding: 0; }
|
|
217
|
+
.uhcp-professional-evidence-methods label { align-items: center; border: 1px solid var(--uhcp-border); border-radius: .9rem; cursor: pointer; display: grid; gap: .75rem; grid-template-columns: 1.25rem 1fr; padding: .9rem 1rem; }
|
|
218
|
+
.uhcp-professional-evidence-methods input[type='radio'] { accent-color: var(--uhcp-turquoise); height: 1.1rem; margin: 0; width: 1.1rem; }
|
|
219
|
+
.uhcp-professional-pin-setup { display: grid; gap: 1rem; }
|
|
220
|
+
.uhcp-professional-pin-setup > header h1, .uhcp-professional-pin-setup > header p { margin: 0; }
|
|
221
|
+
.uhcp-professional-pin-setup > header p { margin-top: .45rem; }
|
|
222
|
+
.uhcp-professional-pin-setup .uhcp-secondary-action { background: transparent; border: 1px solid var(--uhcp-border); color: var(--uhcp-text); }
|
|
214
223
|
.uhcp-profile-pin-fallback summary { color: var(--uhcp-text); cursor: pointer; font-weight: 700; }
|
|
215
224
|
.uhcp-profile-pin-fallback form { margin-top: .8rem; }
|
|
216
225
|
.uhcp-profile-pin-recovery { display: flex; justify-content: flex-start; margin-top: .7rem; }
|