uhc-portal-components-react 0.1.35 → 0.1.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 +21 -0
- package/README.md +25 -1
- package/dist/AnimalIdentityOnboarding.d.ts +82 -0
- package/dist/AnimalIdentityOnboarding.d.ts.map +1 -0
- package/dist/AnimalIdentityOnboarding.js +70 -0
- package/dist/ClinicalActionButton.d.ts +9 -0
- package/dist/ClinicalActionButton.d.ts.map +1 -0
- package/dist/ClinicalActionButton.js +12 -0
- package/dist/ClinicalArtifactEditor.d.ts.map +1 -1
- package/dist/ClinicalArtifactEditor.js +18 -1
- package/dist/ClinicalSpeechInput.d.ts +58 -0
- package/dist/ClinicalSpeechInput.d.ts.map +1 -0
- package/dist/ClinicalSpeechInput.js +83 -0
- package/dist/EmergencyTaskHub.d.ts +27 -0
- package/dist/EmergencyTaskHub.d.ts.map +1 -0
- package/dist/EmergencyTaskHub.js +24 -0
- package/dist/SoschainWorkspace.d.ts +10 -1
- package/dist/SoschainWorkspace.d.ts.map +1 -1
- package/dist/SoschainWorkspace.js +3 -3
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/styles.css +40 -5
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
- Add a portal-owned clinical speech-input provider. Schema-backed IPS text
|
|
6
|
+
fields now reflect the shared model state, append editable transcripts and
|
|
7
|
+
reuse the existing explicit terminology-candidate selection flow. A shared
|
|
8
|
+
external channel propagates runtime phase changes to editors that are
|
|
9
|
+
already open without importing or duplicating the model in those editors.
|
|
10
|
+
|
|
11
|
+
- Add a shared progressive animal, owner-or-caregiver and physical-evidence
|
|
12
|
+
onboarding form for veterinarian-assisted identity attestation.
|
|
13
|
+
- Add a capability-aware `SubjectIdentityCard` for provider-confirmed animal
|
|
14
|
+
identity and relationship readback.
|
|
15
|
+
- Add compact accessible clinical action buttons and a task-first emergency
|
|
16
|
+
hub with host-owned navigation and authorization.
|
|
17
|
+
- Let SOSChain hosts compose a task-first overview, keep secondary areas under
|
|
18
|
+
an accessible More menu and select cards without exposing identifiers in URLs.
|
|
19
|
+
- Make this repository the single source of truth for the cross-portal
|
|
20
|
+
BloodChain/UHC, VetChain Expo and HospitalApp component recovery inventory.
|
|
21
|
+
Keep consumer ownership and proof requirements beside the reusable React
|
|
22
|
+
component boundary instead of duplicating the matrix in one product portal.
|
|
23
|
+
|
|
3
24
|
## 0.1.35
|
|
4
25
|
|
|
5
26
|
- Keep create actions in the clinical section header while edit and delete
|
package/README.md
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
# UHC Portal Components React
|
|
2
2
|
|
|
3
|
+
Historical reusable UI and flow anchors are tracked in
|
|
4
|
+
[`docs/LEGACY_FRONTEND_RECOVERY_INVENTORY.md`](docs/LEGACY_FRONTEND_RECOVERY_INVENTORY.md).
|
|
5
|
+
|
|
3
6
|
Publishable, brand-neutral React components shared by:
|
|
4
7
|
|
|
5
8
|
- UHC Personal
|
|
@@ -83,6 +86,16 @@ The package deliberately exposes modules instead of a cloned application:
|
|
|
83
86
|
terminology candidate preserves source text and adds only the confirmed
|
|
84
87
|
`system|code` and display. Success requires a fresh provider readback Bundle;
|
|
85
88
|
local form state is never presented as a persisted write.
|
|
89
|
+
- `ClinicalSpeechInputProvider`: lets the owning portal publish one
|
|
90
|
+
speech-recognition capability and model phase to every nested clinical
|
|
91
|
+
editor. Compatible IPS text fields show an accessible microphone only when
|
|
92
|
+
configured; recognized text remains editable and enters the same debounced
|
|
93
|
+
terminology-selection flow. The shared component never downloads a model,
|
|
94
|
+
stores audio or confirms a clinical code. Use
|
|
95
|
+
`createClinicalSpeechInputChannel` with
|
|
96
|
+
`ClinicalSpeechInputChannelProvider` when the portal model must notify
|
|
97
|
+
already-mounted IPS sections as it moves through download, initialization,
|
|
98
|
+
readiness or failure.
|
|
86
99
|
- `InvitationAcceptancePanel`: controlled invitation-code UI for a related
|
|
87
100
|
individual member; the host refreshes the authorized-subject list after its
|
|
88
101
|
BFF accepts the invitation.
|
|
@@ -118,6 +131,15 @@ The package deliberately exposes modules instead of a cloned application:
|
|
|
118
131
|
- `IdentityEvidenceDeclarationForm`: collects the business fields used to
|
|
119
132
|
prepare a declaration. Hosts supply governed options and one high-level
|
|
120
133
|
callback; the form never authors claims or handles certificates.
|
|
134
|
+
- `AnimalIdentityOnboarding`: one progressive animal, owner-or-caregiver and
|
|
135
|
+
physical-evidence journey recovered from the VetChain Expo flow. The host
|
|
136
|
+
creates the subject and returns the veterinarian-attested result.
|
|
137
|
+
- `SubjectIdentityCard`: capability-aware person or animal identity readback.
|
|
138
|
+
Facts, relationship status and edit authority are always provider supplied.
|
|
139
|
+
- `ClinicalActionButton`: compact add, edit and delete actions with complete
|
|
140
|
+
accessible names and host-owned authorization state.
|
|
141
|
+
- `EmergencyTaskHub`: task-first emergency navigation whose destinations and
|
|
142
|
+
availability are supplied by the authorized host.
|
|
121
143
|
|
|
122
144
|
Clinical label semantics stay in `gdc-common-utils-ts` / the SDK reader. Hosts
|
|
123
145
|
pass human titles to `ClinicalSectionSummary`: local `CodeableConcept.text`
|
|
@@ -154,4 +176,6 @@ UHC host application and must be extracted behind host-owned adapters. A brand
|
|
|
154
176
|
adapter may change tokens, logo, product vocabulary, animal-specific forms and
|
|
155
177
|
route destinations; it must not fork shared flow or authorization behavior.
|
|
156
178
|
|
|
157
|
-
See [`docs/PERSONAL_FLOW_EXTRACTION.md`](docs/PERSONAL_FLOW_EXTRACTION.md)
|
|
179
|
+
See [`docs/PERSONAL_FLOW_EXTRACTION.md`](docs/PERSONAL_FLOW_EXTRACTION.md) and
|
|
180
|
+
the canonical cross-portal
|
|
181
|
+
[`docs/HISTORICAL_PORTAL_COMPONENT_RECOVERY_MATRIX.md`](docs/HISTORICAL_PORTAL_COMPONENT_RECOVERY_MATRIX.md).
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { IdentityEvidenceStatus } from './IdentityEvidenceWorkspace.js';
|
|
2
|
+
export type AnimalControllerRelationship = 'owner' | 'caregiver';
|
|
3
|
+
export type AnimalIdentityOnboardingInput = Readonly<{
|
|
4
|
+
animalName: string;
|
|
5
|
+
taxonomyId: string;
|
|
6
|
+
birthDate?: string;
|
|
7
|
+
sex: 'female' | 'male' | 'other' | 'unknown';
|
|
8
|
+
identifierSystem: string;
|
|
9
|
+
identifierValue: string;
|
|
10
|
+
controllerLegalName: string;
|
|
11
|
+
controllerIdentifierType: string;
|
|
12
|
+
controllerIdentifierValue: string;
|
|
13
|
+
controllerCountry: string;
|
|
14
|
+
relationship: AnimalControllerRelationship;
|
|
15
|
+
ownerDocument: File;
|
|
16
|
+
animalDocument: File;
|
|
17
|
+
relationshipDocument: File;
|
|
18
|
+
controllerPin: string;
|
|
19
|
+
}>;
|
|
20
|
+
export type AnimalIdentityOnboardingCopy = Readonly<{
|
|
21
|
+
title: string;
|
|
22
|
+
intro: string;
|
|
23
|
+
animalStep: string;
|
|
24
|
+
controllerStep: string;
|
|
25
|
+
evidenceStep: string;
|
|
26
|
+
animalName: string;
|
|
27
|
+
taxonomyId: string;
|
|
28
|
+
birthDate: string;
|
|
29
|
+
sex: string;
|
|
30
|
+
sexUnknown: string;
|
|
31
|
+
sexFemale: string;
|
|
32
|
+
sexMale: string;
|
|
33
|
+
sexOther: string;
|
|
34
|
+
identifierSystem: string;
|
|
35
|
+
identifierValue: string;
|
|
36
|
+
controllerLegalName: string;
|
|
37
|
+
controllerIdentifierType: string;
|
|
38
|
+
controllerIdentifierValue: string;
|
|
39
|
+
controllerCountry: string;
|
|
40
|
+
relationship: string;
|
|
41
|
+
owner: string;
|
|
42
|
+
caregiver: string;
|
|
43
|
+
ownerDocument: string;
|
|
44
|
+
animalDocument: string;
|
|
45
|
+
relationshipDocument: string;
|
|
46
|
+
controllerPin: string;
|
|
47
|
+
submit: string;
|
|
48
|
+
}>;
|
|
49
|
+
/**
|
|
50
|
+
* Brand-neutral animal identity and controller-evidence editor recovered from
|
|
51
|
+
* the progressive VetChain Expo journey. The host persists and verifies the
|
|
52
|
+
* result; this component never grants authority or marks evidence verified.
|
|
53
|
+
*/
|
|
54
|
+
export declare function AnimalIdentityOnboarding({ copy, onSubmit, submitAction, busy }: Readonly<{
|
|
55
|
+
copy: AnimalIdentityOnboardingCopy;
|
|
56
|
+
onSubmit: (input: AnimalIdentityOnboardingInput) => Promise<void> | void;
|
|
57
|
+
submitAction?: string;
|
|
58
|
+
busy?: boolean;
|
|
59
|
+
}>): import("react").JSX.Element;
|
|
60
|
+
export type SubjectIdentityCardSubject = Readonly<{
|
|
61
|
+
displayName: string;
|
|
62
|
+
kind: 'person' | 'animal';
|
|
63
|
+
imageUrl?: string;
|
|
64
|
+
facts: readonly Readonly<{
|
|
65
|
+
label: string;
|
|
66
|
+
value: string;
|
|
67
|
+
}>[];
|
|
68
|
+
}>;
|
|
69
|
+
/** Capability-aware readback. Values and status must come from the provider. */
|
|
70
|
+
export declare function SubjectIdentityCard({ subject, relationship, statusLabels, editLabel, canEdit, onEdit }: Readonly<{
|
|
71
|
+
subject: SubjectIdentityCardSubject;
|
|
72
|
+
relationship?: Readonly<{
|
|
73
|
+
label: string;
|
|
74
|
+
displayName: string;
|
|
75
|
+
status: IdentityEvidenceStatus;
|
|
76
|
+
}>;
|
|
77
|
+
statusLabels: Readonly<Record<IdentityEvidenceStatus, string>>;
|
|
78
|
+
editLabel?: string;
|
|
79
|
+
canEdit?: boolean;
|
|
80
|
+
onEdit?: () => void;
|
|
81
|
+
}>): import("react").JSX.Element;
|
|
82
|
+
//# sourceMappingURL=AnimalIdentityOnboarding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnimalIdentityOnboarding.d.ts","sourceRoot":"","sources":["../src/AnimalIdentityOnboarding.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
/**
|
|
4
|
+
* Brand-neutral animal identity and controller-evidence editor recovered from
|
|
5
|
+
* the progressive VetChain Expo journey. The host persists and verifies the
|
|
6
|
+
* result; this component never grants authority or marks evidence verified.
|
|
7
|
+
*/
|
|
8
|
+
export function AnimalIdentityOnboarding({ copy, onSubmit, submitAction, busy = false }) {
|
|
9
|
+
const [submitting, setSubmitting] = useState(false);
|
|
10
|
+
async function submit(event) {
|
|
11
|
+
event.preventDefault();
|
|
12
|
+
const formElement = event.currentTarget;
|
|
13
|
+
const form = new FormData(formElement);
|
|
14
|
+
const ownerDocument = requiredFile(formElement, 'ownerDocument');
|
|
15
|
+
const animalDocument = requiredFile(formElement, 'animalDocument');
|
|
16
|
+
const relationshipDocument = requiredFile(formElement, 'relationshipDocument');
|
|
17
|
+
setSubmitting(true);
|
|
18
|
+
try {
|
|
19
|
+
await onSubmit({
|
|
20
|
+
animalName: requiredText(form, 'animalName'),
|
|
21
|
+
taxonomyId: requiredText(form, 'taxonomyId'),
|
|
22
|
+
birthDate: optionalText(form, 'birthDate'),
|
|
23
|
+
sex: requiredText(form, 'sex'),
|
|
24
|
+
identifierSystem: requiredText(form, 'identifierSystem'),
|
|
25
|
+
identifierValue: requiredText(form, 'identifierValue'),
|
|
26
|
+
controllerLegalName: requiredText(form, 'controllerLegalName'),
|
|
27
|
+
controllerIdentifierType: requiredText(form, 'controllerIdentifierType'),
|
|
28
|
+
controllerIdentifierValue: requiredText(form, 'controllerIdentifierValue'),
|
|
29
|
+
controllerCountry: requiredText(form, 'controllerCountry').toUpperCase(),
|
|
30
|
+
relationship: requiredText(form, 'relationship'),
|
|
31
|
+
ownerDocument,
|
|
32
|
+
animalDocument,
|
|
33
|
+
relationshipDocument,
|
|
34
|
+
controllerPin: requiredText(form, 'controllerPin'),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
setSubmitting(false);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
const disabled = busy || submitting;
|
|
42
|
+
return _jsxs("section", { className: "uhcp-animal-onboarding", "aria-labelledby": "animal-identity-onboarding-title", children: [_jsxs("header", { children: [_jsx("h2", { id: "animal-identity-onboarding-title", children: copy.title }), _jsx("p", { children: copy.intro })] }), _jsxs("form", { onSubmit: submit, children: [_jsxs("fieldset", { children: [_jsxs("legend", { children: [_jsx(StepNumber, { value: 1 }), " ", copy.animalStep] }), _jsxs("div", { className: "uhcp-animal-onboarding-fields", children: [_jsxs("label", { children: [copy.animalName, _jsx("input", { name: "animalName", required: true, maxLength: 80 })] }), _jsxs("label", { children: [copy.taxonomyId, _jsx("input", { name: "taxonomyId", required: true, inputMode: "numeric", pattern: "[1-9][0-9]{0,6}", defaultValue: "9615" })] }), _jsxs("label", { children: [copy.birthDate, _jsx("input", { name: "birthDate", type: "date" })] }), _jsxs("label", { children: [copy.sex, _jsxs("select", { name: "sex", defaultValue: "unknown", children: [_jsx("option", { value: "unknown", children: copy.sexUnknown }), _jsx("option", { value: "female", children: copy.sexFemale }), _jsx("option", { value: "male", children: copy.sexMale }), _jsx("option", { value: "other", children: copy.sexOther })] })] }), _jsxs("label", { children: [copy.identifierSystem, _jsxs("select", { name: "identifierSystem", defaultValue: "urn:iso:std:iso:11784:11785", children: [_jsx("option", { value: "urn:iso:std:iso:11784:11785", children: "ISO 11784/11785" }), _jsx("option", { value: "https://europa.eu/pet-passport", children: "EU pet passport" }), _jsx("option", { value: "https://vetchain.app/identifier/tattoo", children: "Tattoo" })] })] }), _jsxs("label", { children: [copy.identifierValue, _jsx("input", { name: "identifierValue", required: true, maxLength: 80, autoComplete: "off" })] })] })] }), _jsxs("fieldset", { children: [_jsxs("legend", { children: [_jsx(StepNumber, { value: 2 }), " ", copy.controllerStep] }), _jsxs("div", { className: "uhcp-animal-onboarding-fields", children: [_jsxs("label", { children: [copy.controllerLegalName, _jsx("input", { name: "controllerLegalName", required: true, maxLength: 160, autoComplete: "name" })] }), _jsxs("label", { children: [copy.controllerIdentifierType, _jsx("input", { name: "controllerIdentifierType", required: true, defaultValue: "national_identity_card", maxLength: 80 })] }), _jsxs("label", { children: [copy.controllerIdentifierValue, _jsx("input", { name: "controllerIdentifierValue", required: true, maxLength: 120, autoComplete: "off" })] }), _jsxs("label", { children: [copy.controllerCountry, _jsx("input", { name: "controllerCountry", required: true, pattern: "[A-Za-z]{2}", maxLength: 2, autoComplete: "country" })] }), _jsxs("label", { children: [copy.relationship, _jsxs("select", { name: "relationship", defaultValue: "owner", children: [_jsx("option", { value: "owner", children: copy.owner }), _jsx("option", { value: "caregiver", children: copy.caregiver })] })] })] })] }), _jsxs("fieldset", { children: [_jsxs("legend", { children: [_jsx(StepNumber, { value: 3 }), " ", copy.evidenceStep] }), _jsxs("div", { className: "uhcp-animal-onboarding-fields", children: [_jsxs("label", { children: [copy.ownerDocument, _jsx("input", { name: "ownerDocument", type: "file", accept: "application/pdf,image/jpeg,image/png", required: true })] }), _jsxs("label", { children: [copy.animalDocument, _jsx("input", { name: "animalDocument", type: "file", accept: "application/pdf,image/jpeg,image/png", required: true })] }), _jsxs("label", { children: [copy.relationshipDocument, _jsx("input", { name: "relationshipDocument", type: "file", accept: "application/pdf,image/jpeg,image/png", required: true })] }), _jsxs("label", { children: [copy.controllerPin, _jsx("input", { name: "controllerPin", type: "password", inputMode: "numeric", pattern: "[0-9]{6,12}", required: true, autoComplete: "new-password" })] })] })] }), _jsx("button", { type: "submit", className: "uhcp-animal-onboarding-submit", "data-portal-action": submitAction, disabled: disabled, children: copy.submit })] })] });
|
|
43
|
+
}
|
|
44
|
+
/** Capability-aware readback. Values and status must come from the provider. */
|
|
45
|
+
export function SubjectIdentityCard({ subject, relationship, statusLabels, editLabel, canEdit = false, onEdit }) {
|
|
46
|
+
const initial = subject.displayName.trim().slice(0, 1).toUpperCase() || '•';
|
|
47
|
+
return _jsxs("article", { className: "uhcp-subject-identity-card", children: [_jsxs("header", { children: [subject.imageUrl
|
|
48
|
+
? _jsx("img", { src: subject.imageUrl, alt: "" })
|
|
49
|
+
: _jsx("span", { className: "uhcp-subject-identity-avatar", "aria-hidden": "true", children: initial }), _jsxs("div", { children: [_jsx("small", { children: subject.kind }), _jsx("h3", { children: subject.displayName })] }), canEdit && onEdit && editLabel ? _jsx("button", { type: "button", onClick: onEdit, children: editLabel }) : null] }), _jsx("dl", { children: subject.facts.map(fact => _jsxs("div", { children: [_jsx("dt", { children: fact.label }), _jsx("dd", { children: fact.value })] }, `${fact.label}:${fact.value}`)) }), relationship ? _jsxs("section", { className: "uhcp-subject-identity-relationship", children: [_jsx("span", { children: relationship.label }), _jsx("strong", { children: relationship.displayName }), _jsx("small", { className: `uhcp-identity-status uhcp-identity-status-${relationship.status}`, children: statusLabels[relationship.status] })] }) : null] });
|
|
50
|
+
}
|
|
51
|
+
function StepNumber({ value }) {
|
|
52
|
+
return _jsx("span", { className: "uhcp-identity-step-number", "aria-hidden": "true", children: value });
|
|
53
|
+
}
|
|
54
|
+
function requiredText(form, name) {
|
|
55
|
+
const value = form.get(name);
|
|
56
|
+
if (typeof value !== 'string' || !value.trim())
|
|
57
|
+
throw new Error(`animal_identity_${name}_required`);
|
|
58
|
+
return value.trim();
|
|
59
|
+
}
|
|
60
|
+
function optionalText(form, name) {
|
|
61
|
+
const value = form.get(name);
|
|
62
|
+
return typeof value === 'string' && value.trim() ? value.trim() : undefined;
|
|
63
|
+
}
|
|
64
|
+
function requiredFile(form, name) {
|
|
65
|
+
const input = form.elements.namedItem(name);
|
|
66
|
+
const value = input instanceof HTMLInputElement ? input.files?.[0] : undefined;
|
|
67
|
+
if (!value || value.size < 1)
|
|
68
|
+
throw new Error(`animal_identity_${name}_required`);
|
|
69
|
+
return value;
|
|
70
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export type ClinicalActionKind = 'add' | 'edit' | 'delete';
|
|
2
|
+
/** Compact clinical action; authorization and callback behavior remain host-owned. */
|
|
3
|
+
export declare function ClinicalActionButton({ kind, label, disabled, onClick }: Readonly<{
|
|
4
|
+
kind: ClinicalActionKind;
|
|
5
|
+
label: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
onClick: () => void;
|
|
8
|
+
}>): import("react").JSX.Element;
|
|
9
|
+
//# sourceMappingURL=ClinicalActionButton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClinicalActionButton.d.ts","sourceRoot":"","sources":["../src/ClinicalActionButton.tsx"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,GAAG,KAAK,GAAG,MAAM,GAAG,QAAQ,CAAA;AAE1D,sFAAsF;AACtF,wBAAgB,oBAAoB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAgB,EAAE,OAAO,EAAE,EAAE,QAAQ,CAAC;IACxF,IAAI,EAAE,kBAAkB,CAAA;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,CAAC,+BASD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
/** Compact clinical action; authorization and callback behavior remain host-owned. */
|
|
3
|
+
export function ClinicalActionButton({ kind, label, disabled = false, onClick }) {
|
|
4
|
+
return _jsx("button", { type: "button", className: `uhcp-clinical-icon-action uhcp-clinical-icon-action-${kind}`, "aria-label": label, title: label, disabled: disabled, onClick: onClick, children: _jsx(ActionIcon, { kind: kind }) });
|
|
5
|
+
}
|
|
6
|
+
function ActionIcon({ kind }) {
|
|
7
|
+
if (kind === 'add')
|
|
8
|
+
return _jsx("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { d: "M12 5v14M5 12h14" }) });
|
|
9
|
+
if (kind === 'delete')
|
|
10
|
+
return _jsx("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { d: "M4 7h16m-10 4v6m4-6v6M9 7l1-3h4l1 3m3 0-1 14H7L6 7" }) });
|
|
11
|
+
return _jsx("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { d: "m4 20 4.2-1 10.9-10.9a2.1 2.1 0 0 0-3-3L5.2 16 4 20Zm10.7-13.5 3 3" }) });
|
|
12
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClinicalArtifactEditor.d.ts","sourceRoot":"","sources":["../src/ClinicalArtifactEditor.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kDAAkD,CAAA;AAUlG,OAAO,EAML,KAAK,2BAA2B,EAEhC,KAAK,2BAA2B,EACjC,MAAM,kDAAkD,CAAA;AACzD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAA;
|
|
1
|
+
{"version":3,"file":"ClinicalArtifactEditor.d.ts","sourceRoot":"","sources":["../src/ClinicalArtifactEditor.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kDAAkD,CAAA;AAUlG,OAAO,EAML,KAAK,2BAA2B,EAEhC,KAAK,2BAA2B,EACjC,MAAM,kDAAkD,CAAA;AACzD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAA;AAIxE,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC5C,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC,qBAAqB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACzC,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CACjD,CAAC,CAAA;AAEF,MAAM,MAAM,6BAA6B,GAAG,QAAQ,CAAC;IACnD,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAA;IACzB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;IACjD,2EAA2E;IAC3E,eAAe,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;QAAE,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC9E,gFAAgF;IAChF,aAAa,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;CAClD,CAAC,CAAA;AAEF,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,YAAY,EAAE,MAAM,CAAA;IACpB,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAA;IACzB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACxC,yFAAyF;IACzF,eAAe,CAAC,EAAE,2BAA2B,CAAA;IAC7C,8DAA8D;IAC9D,aAAa,CAAC,EAAE,6BAA6B,CAAA;CAC9C,CAAC,CAAA;AAEF,MAAM,MAAM,6BAA6B,GAAG,QAAQ,CAAC;IACnD,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,SAAS,OAAO,EAAE,CAAA;IACzB,KAAK,CAAC,EAAE,SAAS,OAAO,EAAE,CAAA;CAC3B,CAAC,CAAA;AAEF,MAAM,MAAM,gCAAgC,GAAG,QAAQ,CAAC;IACtD,gBAAgB,EAAE,MAAM,CAAA;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,gBAAgB,EAAE,OAAO,GAAG,WAAW,CAAA;IACvC,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAC,CAAA;AAEF,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAC,CAAA;AAEF,MAAM,MAAM,yBAAyB,GAAG,QAAQ,CAAC;IAC/C,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,MAAM,CAAA;CACd,CAAC,CAAA;AAEF,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAAC;IAChD,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;IACb,kBAAkB,EAAE,MAAM,CAAA;IAC1B,sBAAsB,EAAE,MAAM,CAAA;IAC9B,eAAe,EAAE,MAAM,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,2BAA2B,CAAA;CACvC,CAAC,CAAA;AAEF,MAAM,MAAM,2BAA2B,GAAG,QAAQ,CAC9C;IAAE,KAAK,EAAE,WAAW,CAAC;IAAC,MAAM,EAAE,0BAA0B,CAAA;CAAE,GAC1D;IAAE,KAAK,EAAE,SAAS,GAAG,WAAW,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,GACpD;IAAE,KAAK,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CACzC,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG,QAAQ,CAAC;IACjD,OAAO,EAAE,6BAA6B,CAAA;IACtC,MAAM,EAAE,sBAAsB,CAAA;IAC9B,oFAAoF;IACpF,eAAe,CAAC,EAAE,2BAA2B,CAAA;IAC7C,mFAAmF;IACnF,gBAAgB,CAAC,EAAE,gCAAgC,CAAA;IACnD,IAAI,EAAE,0BAA0B,CAAA;IAChC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IACrC,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,yBAAyB,KAAK,OAAO,CAAC,SAAS,4BAA4B,EAAE,CAAC,CAAA;IAC1G,YAAY,EAAE,CAAC,KAAK,EAAE,qBAAqB,KAAK,OAAO,CAAC,0BAA0B,GAAG,2BAA2B,GAAG,SAAS,CAAC,CAAA;IAC7H,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,UAAU,EAAE,CAAC,MAAM,EAAE,0BAA0B,KAAK,IAAI,CAAA;CACzD,CAAC,CAAA;AAEF;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,OAAO,EACP,MAAM,EACN,eAAe,EACf,gBAAgB,EAChB,IAAI,EACJ,MAAa,EACb,QAA2D,EAC3D,UAAU,EACV,UAAU,EACV,iBAAiB,EACjB,YAAY,EACZ,QAAQ,EACR,UAAU,GACX,EAAE,2BAA2B,+BA+L7B"}
|
|
@@ -4,6 +4,7 @@ import { useEffect, useId, useMemo, useRef, useState } from 'react';
|
|
|
4
4
|
import { clinicalArtifactEditorClaimsFromFhirR4, clinicalArtifactFhirR4ToFlat, composeFhirDateTimeFromLocalParts, splitFhirDateTimeForInput, } from 'fhir-data-utils-ts';
|
|
5
5
|
import { buildMultichannelOperationBundle, MultichannelOperationMode, readMultichannelOperationFromBundle, selectMultichannelOperationClaimValues, } from 'sos-data-utils-ts/multichannel-operation-schemas';
|
|
6
6
|
import { ClinicalEditorLayer } from './ClinicalEditorLayer.js';
|
|
7
|
+
import { ClinicalSpeechInputButton } from './ClinicalSpeechInput.js';
|
|
7
8
|
/**
|
|
8
9
|
* Shared human/animal clinical editor. The host owns authorization, transport,
|
|
9
10
|
* persistence and terminology service access. A successful form submission is
|
|
@@ -140,7 +141,16 @@ export function ClinicalArtifactEditor({ request, schema, operationSchema, autho
|
|
|
140
141
|
};
|
|
141
142
|
if (isDateTimeSchemaNode(schemaNode))
|
|
142
143
|
return _jsx(ClinicalDateTimeClaimField, { label: label, required: requiredClaims.has(claim), value: value, timeZone: timeZone, labels: copy.dateTime ?? DEFAULT_DATE_TIME_LABELS, onChange: (nextValue) => setClaims((current) => ({ ...current, [claim]: nextValue })) }, claim);
|
|
143
|
-
|
|
144
|
+
const fieldClassName = `uhcp-clinical-editor-field${isMultiline(parameter) ? ' uhcp-clinical-editor-wide' : ''}`;
|
|
145
|
+
const appendTranscript = (transcript) => {
|
|
146
|
+
setClaims((current) => ({
|
|
147
|
+
...current,
|
|
148
|
+
[claim]: [current[claim]?.trim(), transcript].filter(Boolean).join(' '),
|
|
149
|
+
}));
|
|
150
|
+
if (terminologyEnabled)
|
|
151
|
+
setActiveTerminologyClaim(claim);
|
|
152
|
+
};
|
|
153
|
+
return _jsxs("div", { className: fieldClassName, children: [_jsxs("span", { className: "uhcp-clinical-editor-field-heading", children: [_jsxs("label", { htmlFor: inputId, children: [label, requiredClaims.has(claim) ? ' *' : ''] }), isSpeechCompatibleField(parameter, schemaNode) ? _jsx(ClinicalSpeechInputButton, { resourceType: request.resourceType, claim: claim, locale: locale, fieldLabel: label, onTranscript: appendTranscript }) : null] }), statusOptions(request.resourceType, parameter) ? _jsxs("select", { id: inputId, "aria-label": label, value: value, required: requiredClaims.has(claim), onChange: update, children: [!requiredClaims.has(claim) ? _jsx("option", { value: "" }) : null, statusOptions(request.resourceType, parameter).map((option) => _jsx("option", { value: option, children: humanize(option) }, option))] }) : isMultiline(parameter) ? _jsx("textarea", { id: inputId, "aria-label": label, value: value, required: requiredClaims.has(claim), rows: 3, onChange: update })
|
|
144
154
|
: _jsx("input", { id: inputId, "aria-label": label, value: value, required: requiredClaims.has(claim), type: fieldInputType(parameter, operationSchema?.properties.claims?.properties?.[claim]), onChange: update }), terminologyEnabled && activeTerminologyClaim === claim ? _jsxs("div", { className: "uhcp-terminology-results", children: [terminologyBusy ? _jsx("small", { role: "status", children: copy.terminologyLoading }) : null, terminologyError ? _jsx("small", { role: "alert", children: copy.terminologyUnavailable }) : null, candidates.length ? _jsx("ul", { children: candidates.map((candidate) => _jsx("li", { children: _jsxs("button", { type: "button", onClick: () => {
|
|
145
155
|
setClaims((current) => selectedCodingClaims(request.resourceType, claim, candidate, acceptedClaims, current));
|
|
146
156
|
setCandidates([]);
|
|
@@ -185,6 +195,13 @@ function composeTemporalClaim(parts, timeZone) {
|
|
|
185
195
|
function isDateTimeSchemaNode(schemaNode) {
|
|
186
196
|
return schemaNode?.format === 'date-time' || schemaNode?.format === 'fhir-date-time';
|
|
187
197
|
}
|
|
198
|
+
function isSpeechCompatibleField(parameter, schemaNode) {
|
|
199
|
+
if (statusOptions('', parameter))
|
|
200
|
+
return false;
|
|
201
|
+
if (schemaNode?.type === 'number' || schemaNode?.type === 'integer' || schemaNode?.type === 'boolean')
|
|
202
|
+
return false;
|
|
203
|
+
return fieldInputType(parameter, schemaNode) === 'text';
|
|
204
|
+
}
|
|
188
205
|
function isSaveOutcome(value) {
|
|
189
206
|
return typeof value === 'object' && value !== null && 'state' in value;
|
|
190
207
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
export declare const ClinicalSpeechInputPhases: Readonly<{
|
|
3
|
+
readonly Idle: "idle";
|
|
4
|
+
readonly Checking: "checking";
|
|
5
|
+
readonly Downloading: "downloading";
|
|
6
|
+
readonly Initializing: "initializing";
|
|
7
|
+
readonly Ready: "ready";
|
|
8
|
+
readonly Error: "error";
|
|
9
|
+
readonly Unavailable: "unavailable";
|
|
10
|
+
}>;
|
|
11
|
+
export type ClinicalSpeechInputPhase = typeof ClinicalSpeechInputPhases[keyof typeof ClinicalSpeechInputPhases];
|
|
12
|
+
export type ClinicalSpeechInputRequest = Readonly<{
|
|
13
|
+
resourceType: string;
|
|
14
|
+
claim: string;
|
|
15
|
+
locale: string;
|
|
16
|
+
}>;
|
|
17
|
+
export type ClinicalSpeechInputCapability = Readonly<{
|
|
18
|
+
phase: ClinicalSpeechInputPhase;
|
|
19
|
+
transcribe: (input: ClinicalSpeechInputRequest) => Promise<string>;
|
|
20
|
+
labels: Readonly<{
|
|
21
|
+
start: string;
|
|
22
|
+
unavailable: string;
|
|
23
|
+
busy: string;
|
|
24
|
+
failed?: string;
|
|
25
|
+
}>;
|
|
26
|
+
}>;
|
|
27
|
+
export type ClinicalSpeechInputRuntime = Pick<ClinicalSpeechInputCapability, 'phase' | 'transcribe'>;
|
|
28
|
+
export type ClinicalSpeechInputChannel = Readonly<{
|
|
29
|
+
getSnapshot: () => ClinicalSpeechInputRuntime;
|
|
30
|
+
publish: (runtime: ClinicalSpeechInputRuntime) => void;
|
|
31
|
+
subscribe: (listener: () => void) => () => void;
|
|
32
|
+
}>;
|
|
33
|
+
/**
|
|
34
|
+
* Creates one small external store through which a portal-owned model runtime
|
|
35
|
+
* can announce download, initialization and readiness changes to every nested
|
|
36
|
+
* clinical editor without importing the model into the shared UI package.
|
|
37
|
+
*/
|
|
38
|
+
export declare function createClinicalSpeechInputChannel(initialRuntime?: ClinicalSpeechInputRuntime): ClinicalSpeechInputChannel;
|
|
39
|
+
/**
|
|
40
|
+
* Supplies one portal-owned speech-recognition capability to nested clinical
|
|
41
|
+
* editors. The portal owns model download, microphone permission and fallback;
|
|
42
|
+
* shared editors receive only an editable transcript.
|
|
43
|
+
*/
|
|
44
|
+
export declare function ClinicalSpeechInputProvider({ value, children }: Readonly<{
|
|
45
|
+
value: ClinicalSpeechInputCapability;
|
|
46
|
+
children: ReactNode;
|
|
47
|
+
}>): import("react").JSX.Element;
|
|
48
|
+
export declare function ClinicalSpeechInputChannelProvider({ channel, labels, children, }: Readonly<{
|
|
49
|
+
channel: ClinicalSpeechInputChannel;
|
|
50
|
+
labels: ClinicalSpeechInputCapability['labels'];
|
|
51
|
+
children: ReactNode;
|
|
52
|
+
}>): import("react").JSX.Element;
|
|
53
|
+
export declare function useClinicalSpeechInput(): ClinicalSpeechInputCapability | undefined;
|
|
54
|
+
export declare function ClinicalSpeechInputButton({ resourceType, claim, locale, fieldLabel, onTranscript, }: Readonly<ClinicalSpeechInputRequest & {
|
|
55
|
+
fieldLabel: string;
|
|
56
|
+
onTranscript: (transcript: string) => void;
|
|
57
|
+
}>): import("react").JSX.Element | null;
|
|
58
|
+
//# sourceMappingURL=ClinicalSpeechInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClinicalSpeechInput.d.ts","sourceRoot":"","sources":["../src/ClinicalSpeechInput.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA6D,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAEjG,eAAO,MAAM,yBAAyB;;;;;;;;EAQ3B,CAAA;AAEX,MAAM,MAAM,wBAAwB,GAAG,OAAO,yBAAyB,CAAC,MAAM,OAAO,yBAAyB,CAAC,CAAA;AAE/G,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAAC;IAChD,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;CACf,CAAC,CAAA;AAEF,MAAM,MAAM,6BAA6B,GAAG,QAAQ,CAAC;IACnD,KAAK,EAAE,wBAAwB,CAAA;IAC/B,UAAU,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IAClE,MAAM,EAAE,QAAQ,CAAC;QACf,KAAK,EAAE,MAAM,CAAA;QACb,WAAW,EAAE,MAAM,CAAA;QACnB,IAAI,EAAE,MAAM,CAAA;QACZ,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,CAAC,CAAA;CACH,CAAC,CAAA;AAEF,MAAM,MAAM,0BAA0B,GAAG,IAAI,CAAC,6BAA6B,EAAE,OAAO,GAAG,YAAY,CAAC,CAAA;AAEpG,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAAC;IAChD,WAAW,EAAE,MAAM,0BAA0B,CAAA;IAC7C,OAAO,EAAE,CAAC,OAAO,EAAE,0BAA0B,KAAK,IAAI,CAAA;IACtD,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAA;CAChD,CAAC,CAAA;AAOF;;;;GAIG;AACH,wBAAgB,gCAAgC,CAC9C,cAAc,GAAE,0BAA+C,GAC9D,0BAA0B,CAc5B;AAID;;;;GAIG;AACH,wBAAgB,2BAA2B,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,QAAQ,CAAC;IACxE,KAAK,EAAE,6BAA6B,CAAA;IACpC,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAC,+BAED;AAED,wBAAgB,kCAAkC,CAAC,EACjD,OAAO,EACP,MAAM,EACN,QAAQ,GACT,EAAE,QAAQ,CAAC;IACV,OAAO,EAAE,0BAA0B,CAAA;IACnC,MAAM,EAAE,6BAA6B,CAAC,QAAQ,CAAC,CAAA;IAC/C,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAC,+BAGD;AAED,wBAAgB,sBAAsB,IAAI,6BAA6B,GAAG,SAAS,CAElF;AAED,wBAAgB,yBAAyB,CAAC,EACxC,YAAY,EACZ,KAAK,EACL,MAAM,EACN,UAAU,EACV,YAAY,GACb,EAAE,QAAQ,CAAC,0BAA0B,GAAG;IACvC,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;CAC3C,CAAC,sCA2CD"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, useContext, useState, useSyncExternalStore } from 'react';
|
|
4
|
+
export const ClinicalSpeechInputPhases = Object.freeze({
|
|
5
|
+
Idle: 'idle',
|
|
6
|
+
Checking: 'checking',
|
|
7
|
+
Downloading: 'downloading',
|
|
8
|
+
Initializing: 'initializing',
|
|
9
|
+
Ready: 'ready',
|
|
10
|
+
Error: 'error',
|
|
11
|
+
Unavailable: 'unavailable',
|
|
12
|
+
});
|
|
13
|
+
const unavailableRuntime = Object.freeze({
|
|
14
|
+
phase: ClinicalSpeechInputPhases.Unavailable,
|
|
15
|
+
transcribe: async () => { throw new Error('clinical_speech_input_unavailable'); },
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* Creates one small external store through which a portal-owned model runtime
|
|
19
|
+
* can announce download, initialization and readiness changes to every nested
|
|
20
|
+
* clinical editor without importing the model into the shared UI package.
|
|
21
|
+
*/
|
|
22
|
+
export function createClinicalSpeechInputChannel(initialRuntime = unavailableRuntime) {
|
|
23
|
+
let snapshot = Object.freeze(initialRuntime);
|
|
24
|
+
const listeners = new Set();
|
|
25
|
+
return Object.freeze({
|
|
26
|
+
getSnapshot: () => snapshot,
|
|
27
|
+
publish(runtime) {
|
|
28
|
+
snapshot = Object.freeze(runtime);
|
|
29
|
+
listeners.forEach((listener) => listener());
|
|
30
|
+
},
|
|
31
|
+
subscribe(listener) {
|
|
32
|
+
listeners.add(listener);
|
|
33
|
+
return () => listeners.delete(listener);
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
const ClinicalSpeechInputContext = createContext(undefined);
|
|
38
|
+
/**
|
|
39
|
+
* Supplies one portal-owned speech-recognition capability to nested clinical
|
|
40
|
+
* editors. The portal owns model download, microphone permission and fallback;
|
|
41
|
+
* shared editors receive only an editable transcript.
|
|
42
|
+
*/
|
|
43
|
+
export function ClinicalSpeechInputProvider({ value, children }) {
|
|
44
|
+
return _jsx(ClinicalSpeechInputContext.Provider, { value: value, children: children });
|
|
45
|
+
}
|
|
46
|
+
export function ClinicalSpeechInputChannelProvider({ channel, labels, children, }) {
|
|
47
|
+
const runtime = useSyncExternalStore(channel.subscribe, channel.getSnapshot, channel.getSnapshot);
|
|
48
|
+
return _jsx(ClinicalSpeechInputProvider, { value: { ...runtime, labels }, children: children });
|
|
49
|
+
}
|
|
50
|
+
export function useClinicalSpeechInput() {
|
|
51
|
+
return useContext(ClinicalSpeechInputContext);
|
|
52
|
+
}
|
|
53
|
+
export function ClinicalSpeechInputButton({ resourceType, claim, locale, fieldLabel, onTranscript, }) {
|
|
54
|
+
const capability = useClinicalSpeechInput();
|
|
55
|
+
const [busy, setBusy] = useState(false);
|
|
56
|
+
const [failed, setFailed] = useState(false);
|
|
57
|
+
if (!capability)
|
|
58
|
+
return null;
|
|
59
|
+
const ready = capability.phase === ClinicalSpeechInputPhases.Ready;
|
|
60
|
+
const actionLabel = busy
|
|
61
|
+
? capability.labels.busy
|
|
62
|
+
: ready
|
|
63
|
+
? capability.labels.start
|
|
64
|
+
: capability.labels.unavailable;
|
|
65
|
+
const transcribe = async () => {
|
|
66
|
+
if (!ready || busy)
|
|
67
|
+
return;
|
|
68
|
+
setBusy(true);
|
|
69
|
+
setFailed(false);
|
|
70
|
+
try {
|
|
71
|
+
const transcript = (await capability.transcribe({ resourceType, claim, locale })).trim();
|
|
72
|
+
if (transcript)
|
|
73
|
+
onTranscript(transcript);
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
setFailed(true);
|
|
77
|
+
}
|
|
78
|
+
finally {
|
|
79
|
+
setBusy(false);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
return _jsxs("span", { className: "uhcp-clinical-speech-control", children: [_jsx("button", { type: "button", className: "uhcp-clinical-speech-button", "aria-label": `${actionLabel}: ${fieldLabel}`, title: actionLabel, disabled: !ready || busy, "aria-pressed": busy, onClick: () => { void transcribe(); }, children: _jsx("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", focusable: "false", children: _jsx("path", { d: "M12 14a3 3 0 0 0 3-3V5a3 3 0 1 0-6 0v6a3 3 0 0 0 3 3Zm-5-3a1 1 0 1 0-2 0 7 7 0 0 0 6 6.92V21H8a1 1 0 1 0 0 2h8a1 1 0 1 0 0-2h-3v-3.08A7 7 0 0 0 19 11a1 1 0 1 0-2 0 5 5 0 0 1-10 0Z" }) }) }), failed ? _jsx("small", { role: "alert", children: capability.labels.failed ?? capability.labels.unavailable }) : null] });
|
|
83
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export type EmergencyTaskIcon = 'contact' | 'journey' | 'health' | 'scan';
|
|
2
|
+
export type EmergencyTaskItem = Readonly<{
|
|
3
|
+
id: string;
|
|
4
|
+
icon: EmergencyTaskIcon;
|
|
5
|
+
title: string;
|
|
6
|
+
description: string;
|
|
7
|
+
actionLabel: string;
|
|
8
|
+
href?: string;
|
|
9
|
+
status?: string;
|
|
10
|
+
}>;
|
|
11
|
+
export type EmergencyTaskHubCopy = Readonly<{
|
|
12
|
+
title: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
unavailable: string;
|
|
15
|
+
}>;
|
|
16
|
+
/**
|
|
17
|
+
* Brand-neutral, task-first entry to the three SOSChain emergency workflows.
|
|
18
|
+
* Hosts resolve every href and status from server-authorized capabilities.
|
|
19
|
+
* Rendering an action never grants subject, clinical or communication access.
|
|
20
|
+
*/
|
|
21
|
+
export declare function EmergencyTaskHub({ copy, tasks, layout, headingLevel }: Readonly<{
|
|
22
|
+
copy: EmergencyTaskHubCopy;
|
|
23
|
+
tasks: readonly EmergencyTaskItem[];
|
|
24
|
+
layout?: 'list' | 'grid';
|
|
25
|
+
headingLevel?: 1 | 2;
|
|
26
|
+
}>): import("react").JSX.Element;
|
|
27
|
+
//# sourceMappingURL=EmergencyTaskHub.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"EmergencyTaskHub.d.ts","sourceRoot":"","sources":["../src/EmergencyTaskHub.tsx"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAA;AAEzE,MAAM,MAAM,iBAAiB,GAAG,QAAQ,CAAC;IACvC,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,iBAAiB,CAAA;IACvB,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAC,CAAA;AAEF,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;CACpB,CAAC,CAAA;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAe,EAAE,YAAgB,EAAE,EAAE,QAAQ,CAAC;IAC5F,IAAI,EAAE,oBAAoB,CAAA;IAC1B,KAAK,EAAE,SAAS,iBAAiB,EAAE,CAAA;IACnC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IACxB,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;CACrB,CAAC,+BAqBD"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Brand-neutral, task-first entry to the three SOSChain emergency workflows.
|
|
4
|
+
* Hosts resolve every href and status from server-authorized capabilities.
|
|
5
|
+
* Rendering an action never grants subject, clinical or communication access.
|
|
6
|
+
*/
|
|
7
|
+
export function EmergencyTaskHub({ copy, tasks, layout = 'list', headingLevel = 2 }) {
|
|
8
|
+
const Heading = headingLevel === 1 ? 'h1' : 'h2';
|
|
9
|
+
return _jsxs("section", { className: `uhcp-emergency-task-hub${layout === 'grid' ? ' uhcp-emergency-task-hub-grid' : ''}`, "aria-labelledby": "emergency-task-hub-title", children: [_jsxs("header", { children: [_jsx(Heading, { id: "emergency-task-hub-title", children: copy.title }), copy.description ? _jsx("p", { children: copy.description }) : null] }), _jsx("div", { className: "uhcp-emergency-task-list", children: tasks.map((task) => _jsxs("article", { "data-emergency-task": task.id, children: [_jsx("span", { className: `uhcp-emergency-task-icon uhcp-emergency-task-icon-${task.icon}`, "aria-hidden": "true", children: _jsx(TaskIcon, { icon: task.icon }) }), _jsxs("div", { className: "uhcp-emergency-task-copy", children: [_jsx("h3", { children: task.title }), _jsx("p", { children: task.description }), task.status ? _jsx("small", { children: task.status }) : null] }), task.href
|
|
10
|
+
? _jsxs("a", { href: task.href, children: [task.actionLabel, _jsx(ArrowIcon, {})] })
|
|
11
|
+
: _jsx("span", { className: "uhcp-emergency-task-unavailable", children: copy.unavailable })] }, task.id)) })] });
|
|
12
|
+
}
|
|
13
|
+
function TaskIcon({ icon }) {
|
|
14
|
+
if (icon === 'contact')
|
|
15
|
+
return _jsx("svg", { viewBox: "0 0 24 24", children: _jsx("path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2M9 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8Zm8-1 2 2 3-4" }) });
|
|
16
|
+
if (icon === 'journey')
|
|
17
|
+
return _jsxs("svg", { viewBox: "0 0 24 24", children: [_jsx("circle", { cx: "6", cy: "18", r: "2" }), _jsx("circle", { cx: "18", cy: "6", r: "2" }), _jsx("path", { d: "M8 18h3a3 3 0 0 0 3-3v-6a3 3 0 0 1 3-3" })] });
|
|
18
|
+
if (icon === 'scan')
|
|
19
|
+
return _jsx("svg", { viewBox: "0 0 24 24", children: _jsx("path", { d: "M8 3H5a2 2 0 0 0-2 2v3m13-5h3a2 2 0 0 1 2 2v3M8 21H5a2 2 0 0 1-2-2v-3m13 5h3a2 2 0 0 0 2-2v-3M7 12h10" }) });
|
|
20
|
+
return _jsx("svg", { viewBox: "0 0 24 24", children: _jsx("path", { d: "M9 3h6v3h3v15H6V6h3V3Zm0 8h6m-6 4h6" }) });
|
|
21
|
+
}
|
|
22
|
+
function ArrowIcon() {
|
|
23
|
+
return _jsx("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", children: _jsx("path", { d: "m9 5 7 7-7 7" }) });
|
|
24
|
+
}
|
|
@@ -92,6 +92,15 @@ export type SoschainWorkspaceProps = Readonly<{
|
|
|
92
92
|
addPlaceHref?: string;
|
|
93
93
|
addProductHref?: string;
|
|
94
94
|
importCardHref?: string;
|
|
95
|
+
/** Host-composed primary workflows for the selected subject overview. */
|
|
96
|
+
overviewContent?: ReactNode;
|
|
97
|
+
/** Areas kept visible; remaining areas move into the accessible More menu. */
|
|
98
|
+
primaryAreas?: readonly SoschainWorkspaceArea[];
|
|
99
|
+
moreLabel?: string;
|
|
100
|
+
/** Raw provider identifiers are hidden by SOSChain portals by default. */
|
|
101
|
+
showCardIdentifier?: boolean;
|
|
102
|
+
/** Selects a card in host-owned state without exposing its identifier in a URL. */
|
|
103
|
+
onSelectCard?: (identifier: string) => void;
|
|
95
104
|
}>;
|
|
96
105
|
/**
|
|
97
106
|
* Shared subject-first SOSChain workspace for personal and professional apps.
|
|
@@ -100,5 +109,5 @@ export type SoschainWorkspaceProps = Readonly<{
|
|
|
100
109
|
* communications. This presentational component never derives authority from
|
|
101
110
|
* a selected role, card, tab or browser-controlled value.
|
|
102
111
|
*/
|
|
103
|
-
export declare function SoschainWorkspace({ copy, cards, selectedCard, activeArea, areaHrefs, places, products, communications, healthSummary, clinicalReadOnly, careJourney, emergencyData, canManageAssociations, addPlaceHref, addProductHref, importCardHref, }: SoschainWorkspaceProps): import("react").JSX.Element;
|
|
112
|
+
export declare function SoschainWorkspace({ copy, cards, selectedCard, activeArea, areaHrefs, places, products, communications, healthSummary, clinicalReadOnly, careJourney, emergencyData, canManageAssociations, addPlaceHref, addProductHref, importCardHref, overviewContent, primaryAreas, moreLabel, showCardIdentifier, onSelectCard, }: SoschainWorkspaceProps): import("react").JSX.Element;
|
|
104
113
|
//# sourceMappingURL=SoschainWorkspace.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SoschainWorkspace.d.ts","sourceRoot":"","sources":["../src/SoschainWorkspace.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"SoschainWorkspace.d.ts","sourceRoot":"","sources":["../src/SoschainWorkspace.tsx"],"names":[],"mappings":"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"}
|
|
@@ -21,9 +21,9 @@ function AssociationList({ items, empty }) {
|
|
|
21
21
|
* communications. This presentational component never derives authority from
|
|
22
22
|
* a selected role, card, tab or browser-controlled value.
|
|
23
23
|
*/
|
|
24
|
-
export function SoschainWorkspace({ copy, cards, selectedCard, activeArea, areaHrefs, places, products, communications, healthSummary, clinicalReadOnly = true, careJourney = [], emergencyData = [], canManageAssociations, addPlaceHref, addProductHref, importCardHref, }) {
|
|
24
|
+
export function SoschainWorkspace({ copy, cards, selectedCard, activeArea, areaHrefs, places, products, communications, healthSummary, clinicalReadOnly = true, careJourney = [], emergencyData = [], canManageAssociations, addPlaceHref, addProductHref, importCardHref, overviewContent, primaryAreas, moreLabel = 'More', showCardIdentifier = true, onSelectCard, }) {
|
|
25
25
|
if (!selectedCard) {
|
|
26
|
-
return (_jsxs("section", { className: "uhcp-sos-wrap", "aria-labelledby": "sos-card-picker-title", children: [_jsxs("header", { className: "uhcp-sos-heading", children: [_jsx("span", { children: copy.workspaceEyebrow }), _jsx("h1", { id: "sos-card-picker-title", children: copy.cardsTitle }), _jsx("p", { children: copy.cardsDescription }), importCardHref && copy.importCard ? _jsxs("a", { href: importCardHref, children: [copy.importCard, " \u2192"] }) : null] }), cards.length === 0 ? (_jsxs("div", { className: "uhcp-sos-empty-panel", children: [_jsx("h2", { children: copy.noCardTitle }), _jsx("p", { children: copy.noCardBody })] })) : (_jsx("ul", { className: "uhcp-sos-card-grid", children: cards.map((card) => (_jsx("li", { children: _jsxs("a", { href: card.openHref, children: [_jsx("span", { children: card.kindLabel }), _jsx("strong", { children: card.displayName }), _jsx("small", { children: card.identifier }), _jsxs("b", { children: [copy.openCard, " \u2192"] })] }) }, card.identifier))) }))] }));
|
|
26
|
+
return (_jsxs("section", { className: "uhcp-sos-wrap", "aria-labelledby": "sos-card-picker-title", children: [_jsxs("header", { className: "uhcp-sos-heading", children: [_jsx("span", { children: copy.workspaceEyebrow }), _jsx("h1", { id: "sos-card-picker-title", children: copy.cardsTitle }), _jsx("p", { children: copy.cardsDescription }), importCardHref && copy.importCard ? _jsxs("a", { href: importCardHref, children: [copy.importCard, " \u2192"] }) : null] }), cards.length === 0 ? (_jsxs("div", { className: "uhcp-sos-empty-panel", children: [_jsx("h2", { children: copy.noCardTitle }), _jsx("p", { children: copy.noCardBody })] })) : (_jsx("ul", { className: "uhcp-sos-card-grid", children: cards.map((card) => (_jsx("li", { children: onSelectCard ? _jsxs("button", { type: "button", onClick: () => onSelectCard(card.identifier), children: [_jsx("span", { children: card.kindLabel }), _jsx("strong", { children: card.displayName }), showCardIdentifier ? _jsx("small", { children: card.identifier }) : null, _jsxs("b", { children: [copy.openCard, " \u2192"] })] }) : _jsxs("a", { href: card.openHref, children: [_jsx("span", { children: card.kindLabel }), _jsx("strong", { children: card.displayName }), showCardIdentifier ? _jsx("small", { children: card.identifier }) : null, _jsxs("b", { children: [copy.openCard, " \u2192"] })] }) }, card.identifier))) }))] }));
|
|
27
27
|
}
|
|
28
28
|
const title = activeArea === 'places'
|
|
29
29
|
? copy.placesTitle
|
|
@@ -53,5 +53,5 @@ export function SoschainWorkspace({ copy, cards, selectedCard, activeArea, areaH
|
|
|
53
53
|
: copy.overviewBody;
|
|
54
54
|
const clinicalAreaIsReadOnly = activeArea === 'care-journey' || (activeArea === 'health-summary' && clinicalReadOnly);
|
|
55
55
|
const associationAreaIsReadOnly = !canManageAssociations && (activeArea === 'overview' || activeArea === 'places' || activeArea === 'products');
|
|
56
|
-
return (_jsxs("section", { className: "uhcp-sos-wrap", children: [_jsxs("header", { className: "uhcp-sos-heading", children: [_jsx("span", { children: copy.selectedCard }), _jsx("h1", { children: selectedCard.displayName }), _jsxs("p", { children: [selectedCard.kindLabel,
|
|
56
|
+
return (_jsxs("section", { className: "uhcp-sos-wrap", children: [_jsxs("header", { className: "uhcp-sos-heading", children: [_jsx("span", { children: copy.selectedCard }), _jsx("h1", { children: selectedCard.displayName }), _jsxs("p", { children: [selectedCard.kindLabel, showCardIdentifier ? ` · ${selectedCard.identifier}` : ''] })] }), _jsxs("nav", { className: "uhcp-sos-tabs", "aria-label": copy.workspaceEyebrow, children: [(primaryAreas ?? SOSCHAIN_SUBJECT_WORKSPACE_AREAS).map((area) => (_jsx("a", { href: areaHrefs[area], "aria-current": activeArea === area ? 'page' : undefined, children: copy.areas[area] }, area))), primaryAreas ? _jsxs("details", { className: "uhcp-sos-more", children: [_jsx("summary", { children: moreLabel }), _jsx("div", { children: SOSCHAIN_SUBJECT_WORKSPACE_AREAS.filter((area) => !primaryAreas.includes(area)).map((area) => (_jsx("a", { href: areaHrefs[area], "aria-current": activeArea === area ? 'page' : undefined, children: copy.areas[area] }, area))) })] }) : null] }), _jsxs("div", { className: "uhcp-sos-panel", children: [_jsxs("header", { children: [_jsxs("div", { children: [_jsx("h2", { children: title }), _jsx("p", { children: body })] }), (clinicalAreaIsReadOnly || associationAreaIsReadOnly) && (_jsx("span", { className: "uhcp-sos-readonly", children: copy.readOnly })), canManageAssociations && activeArea === 'places' && addPlaceHref && _jsx("a", { href: addPlaceHref, children: copy.addPlace }), canManageAssociations && activeArea === 'products' && addProductHref && _jsx("a", { href: addProductHref, children: copy.addProduct })] }), activeArea === 'overview' && (overviewContent ?? (_jsxs("div", { className: "uhcp-sos-overview-grid", children: [_jsxs("article", { children: [_jsx("strong", { children: places.length }), _jsx("span", { children: copy.areas.places })] }), _jsxs("article", { children: [_jsx("strong", { children: products.length }), _jsx("span", { children: copy.areas.products })] }), _jsxs("article", { children: [_jsx("strong", { children: communications.length }), _jsx("span", { children: copy.areas.communications })] }), _jsxs("article", { children: [_jsx("strong", { children: careJourney.length }), _jsx("span", { children: copy.areas['care-journey'] })] })] }))), activeArea === 'health-summary' && (healthSummary ?? _jsx("p", { className: "uhcp-sos-empty", children: copy.emptyHealthSummary })), activeArea === 'care-journey' && (careJourney.length === 0 ? _jsx("p", { className: "uhcp-sos-empty", children: copy.emptyCareJourney }) : (_jsx("ol", { className: "uhcp-sos-timeline uhcp-sos-care-journey", children: careJourney.map((encounter) => (_jsxs("li", { children: [_jsxs("div", { children: [_jsx("span", { children: encounter.statusLabel }), _jsx("time", { dateTime: encounter.periodStart, children: encounter.periodStart })] }), _jsx("strong", { children: encounter.serviceLabel }), encounter.detail ? _jsx("p", { children: encounter.detail }) : null, encounter.locationLabel || encounter.periodEnd ? _jsx("small", { children: [encounter.locationLabel, encounter.periodEnd].filter(Boolean).join(' · ') }) : null] }, encounter.identifier))) }))), activeArea === 'emergency-data' && _jsx(ProtectedIndexEmergencyData, { copy: copy.emergencyData, items: emergencyData }), activeArea === 'places' && _jsx(AssociationList, { items: places, empty: copy.emptyPlaces }), activeArea === 'products' && _jsx(AssociationList, { items: products, empty: copy.emptyProducts }), activeArea === 'communications' && (communications.length === 0 ? _jsx("p", { className: "uhcp-sos-empty", children: copy.emptyCommunications }) : (_jsx("ol", { className: "uhcp-sos-timeline", children: communications.map((message) => (_jsxs("li", { children: [_jsxs("div", { children: [_jsx("span", { children: message.categoryLabel }), _jsx("time", { children: message.occurredAt })] }), _jsx("strong", { children: message.subject }), _jsx("p", { children: message.body }), _jsxs("small", { children: [message.sender, message.placeLabel ? ` · ${message.placeLabel}` : ''] })] }, message.identifier))) })))] })] }));
|
|
57
57
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export * from './ClinicalDocumentEncounterExplorer.js';
|
|
|
12
12
|
export * from './AllClinicalSections.js';
|
|
13
13
|
export * from './ClinicalTimeline.js';
|
|
14
14
|
export * from './ClinicalArtifactEditor.js';
|
|
15
|
+
export * from './ClinicalSpeechInput.js';
|
|
16
|
+
export * from './ClinicalActionButton.js';
|
|
15
17
|
export * from './VitalSignArtifactEditor.js';
|
|
16
18
|
export * from './InvitationAcceptancePanel.js';
|
|
17
19
|
export * from './SubjectAccessRequestPanel.js';
|
|
@@ -26,4 +28,6 @@ export * from './LegalMarkdownDocument.js';
|
|
|
26
28
|
export * from './IdentityEvidenceWorkspace.js';
|
|
27
29
|
export * from './IdentityEvidenceDocumentPanel.js';
|
|
28
30
|
export * from './IdentityEvidenceDeclarationForm.js';
|
|
31
|
+
export * from './AnimalIdentityOnboarding.js';
|
|
32
|
+
export * from './EmergencyTaskHub.js';
|
|
29
33
|
//# 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,wCAAwC,CAAA;AACtD,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,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"}
|
|
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,wCAAwC,CAAA;AACtD,cAAc,0BAA0B,CAAA;AACxC,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,0BAA0B,CAAA;AACxC,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,uBAAuB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,8 @@ export * from './ClinicalDocumentEncounterExplorer.js';
|
|
|
12
12
|
export * from './AllClinicalSections.js';
|
|
13
13
|
export * from './ClinicalTimeline.js';
|
|
14
14
|
export * from './ClinicalArtifactEditor.js';
|
|
15
|
+
export * from './ClinicalSpeechInput.js';
|
|
16
|
+
export * from './ClinicalActionButton.js';
|
|
15
17
|
export * from './VitalSignArtifactEditor.js';
|
|
16
18
|
export * from './InvitationAcceptancePanel.js';
|
|
17
19
|
export * from './SubjectAccessRequestPanel.js';
|
|
@@ -26,3 +28,5 @@ export * from './LegalMarkdownDocument.js';
|
|
|
26
28
|
export * from './IdentityEvidenceWorkspace.js';
|
|
27
29
|
export * from './IdentityEvidenceDocumentPanel.js';
|
|
28
30
|
export * from './IdentityEvidenceDeclarationForm.js';
|
|
31
|
+
export * from './AnimalIdentityOnboarding.js';
|
|
32
|
+
export * from './EmergencyTaskHub.js';
|
package/dist/styles.css
CHANGED
|
@@ -177,8 +177,14 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
|
|
|
177
177
|
.uhcp-clinical-editor h2,.uhcp-clinical-editor p { margin:.2rem 0; }
|
|
178
178
|
.uhcp-clinical-editor>header>button { background:transparent; border:1px solid var(--uhcp-border); border-radius:50%; color:inherit; cursor:pointer; font-size:1.4rem; height:2.5rem; width:2.5rem; }
|
|
179
179
|
.uhcp-clinical-editor form { display:grid; gap:1rem; grid-template-columns:repeat(2,minmax(0,1fr)); margin-top:1.25rem; min-width:0; overflow:auto; }
|
|
180
|
-
.uhcp-clinical-editor label { color:var(--uhcp-text);
|
|
181
|
-
.uhcp-clinical-editor label,.uhcp-clinical-editor fieldset { min-width:0; }
|
|
180
|
+
.uhcp-clinical-editor label { color:var(--uhcp-text); font-weight:700; }
|
|
181
|
+
.uhcp-clinical-editor label,.uhcp-clinical-editor fieldset,.uhcp-clinical-editor-field { min-width:0; }
|
|
182
|
+
.uhcp-clinical-editor-field { display:grid; gap:.35rem; }
|
|
183
|
+
.uhcp-clinical-editor-field-heading { align-items:center; display:flex; gap:.5rem; justify-content:space-between; }
|
|
184
|
+
.uhcp-clinical-speech-control { align-items:center; display:flex; gap:.4rem; }
|
|
185
|
+
.uhcp-clinical-speech-button { align-items:center; background:transparent; border:1px solid var(--uhcp-border); border-radius:50%; color:inherit; cursor:pointer; display:inline-flex; height:2.25rem; justify-content:center; padding:.45rem; width:2.25rem; }
|
|
186
|
+
.uhcp-clinical-speech-button:disabled { cursor:not-allowed; opacity:.45; }
|
|
187
|
+
.uhcp-clinical-speech-button svg { fill:currentColor; height:1.15rem; width:1.15rem; }
|
|
182
188
|
.uhcp-clinical-editor input,.uhcp-clinical-editor select,.uhcp-clinical-editor textarea { background:var(--uhcp-panel); border:1px solid var(--uhcp-border); border-radius:.7rem; color:inherit; font:inherit; min-width:0; padding:.75rem; width:100%; }
|
|
183
189
|
.uhcp-clinical-editor-date-time { grid-column:1/-1; }
|
|
184
190
|
.uhcp-clinical-editor-wide,.uhcp-clinical-editor-error,.uhcp-clinical-editor footer { grid-column:1/-1; }
|
|
@@ -452,6 +458,12 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
|
|
|
452
458
|
.uhcp-clinical-grid { display: grid; gap: .75rem; grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr)); margin-top: 1rem; }
|
|
453
459
|
.uhcp-clinical-card { background: var(--uhcp-panel-muted); border-radius: 1rem; display: flex; flex-direction: column; min-width: 0; padding: 1rem; }
|
|
454
460
|
.uhcp-clinical-card-actions { align-items: center; display: flex; gap: .4rem; justify-content: flex-end; margin-top: .75rem; }
|
|
461
|
+
.uhcp-clinical-icon-action { align-items:center; background:var(--uhcp-panel); border:1px solid var(--uhcp-border); border-radius:.65rem; color:var(--uhcp-text); cursor:pointer; display:inline-flex; height:2.5rem; justify-content:center; padding:0; width:2.5rem; }
|
|
462
|
+
.uhcp-clinical-icon-action:hover { border-color:var(--uhcp-turquoise); color:var(--uhcp-turquoise); }
|
|
463
|
+
.uhcp-clinical-icon-action:focus-visible { outline:3px solid var(--uhcp-turquoise); outline-offset:2px; }
|
|
464
|
+
.uhcp-clinical-icon-action:disabled { cursor:not-allowed; opacity:.42; }
|
|
465
|
+
.uhcp-clinical-icon-action svg { fill:none; height:1.2rem; stroke:currentColor; stroke-linecap:round; stroke-linejoin:round; stroke-width:1.8; width:1.2rem; }
|
|
466
|
+
.uhcp-clinical-icon-action-delete:hover { border-color:var(--uhcp-attention); color:var(--uhcp-attention); }
|
|
455
467
|
.uhcp-clinical-title { font-weight: 800; margin: 0; }
|
|
456
468
|
.uhcp-clinical-type { color: var(--uhcp-muted); font-size: .72rem; font-weight: 800; letter-spacing: .06em; margin: .35rem 0 0; text-transform: uppercase; }
|
|
457
469
|
.uhcp-clinical-date, .uhcp-clinical-empty { color: var(--uhcp-muted); margin: .35rem 0 0; }
|
|
@@ -595,14 +607,15 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
|
|
|
595
607
|
.uhcp-sos-heading h1 { font-size: clamp(2rem, 5vw, 3.75rem); letter-spacing: -.04em; margin: .45rem 0; }
|
|
596
608
|
.uhcp-sos-heading p, .uhcp-sos-panel header p { color: var(--uhcp-muted); line-height: 1.6; margin: 0; }
|
|
597
609
|
.uhcp-sos-card-grid, .uhcp-sos-entity-list { display: grid; gap: 1rem; grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); list-style: none; margin: 2rem 0 0; padding: 0; }
|
|
598
|
-
.uhcp-sos-card-grid a, .uhcp-sos-entity-list li { background: var(--uhcp-panel); border: 1px solid var(--uhcp-border); border-radius: 1.5rem; color: var(--uhcp-text); display: grid; gap: .65rem; padding: 1.4rem; text-decoration: none; }
|
|
599
|
-
.uhcp-sos-card-grid a:hover { border-color: var(--uhcp-turquoise); transform: translateY(-2px); }
|
|
600
|
-
.uhcp-sos-card-grid a:focus-visible, .uhcp-sos-tabs a:focus-visible, .uhcp-sos-panel a:focus-visible { outline: 3px solid var(--uhcp-turquoise); outline-offset: 3px; }
|
|
610
|
+
.uhcp-sos-card-grid a, .uhcp-sos-card-grid button, .uhcp-sos-entity-list li { background: var(--uhcp-panel); border: 1px solid var(--uhcp-border); border-radius: 1.5rem; color: var(--uhcp-text); display: grid; font: inherit; gap: .65rem; padding: 1.4rem; text-align: left; text-decoration: none; width: 100%; }
|
|
611
|
+
.uhcp-sos-card-grid a:hover, .uhcp-sos-card-grid button:hover { border-color: var(--uhcp-turquoise); transform: translateY(-2px); }
|
|
612
|
+
.uhcp-sos-card-grid a:focus-visible, .uhcp-sos-card-grid button:focus-visible, .uhcp-sos-tabs a:focus-visible, .uhcp-sos-panel a:focus-visible { outline: 3px solid var(--uhcp-turquoise); outline-offset: 3px; }
|
|
601
613
|
.uhcp-sos-card-grid span, .uhcp-sos-card-grid small, .uhcp-sos-entity-list span, .uhcp-sos-entity-list small { color: var(--uhcp-muted); }
|
|
602
614
|
.uhcp-sos-card-grid b { color: var(--uhcp-turquoise); }
|
|
603
615
|
.uhcp-sos-tabs { display: flex; gap: .5rem; margin: 2rem 0 1rem; overflow-x: auto; padding: .25rem; }
|
|
604
616
|
.uhcp-sos-tabs a { border-radius: 999px; color: var(--uhcp-muted); font-weight: 800; padding: .75rem 1rem; text-decoration: none; white-space: nowrap; }
|
|
605
617
|
.uhcp-sos-tabs a[aria-current='page'] { background: linear-gradient(135deg, var(--uhcp-action-start), var(--uhcp-action-end)); color: #fff; }
|
|
618
|
+
.uhcp-sos-more{margin-left:auto;position:relative}.uhcp-sos-more>summary{border:1px solid var(--uhcp-border);border-radius:999px;color:var(--uhcp-muted);cursor:pointer;font-weight:800;list-style:none;padding:.7rem 1rem}.uhcp-sos-more>summary::-webkit-details-marker{display:none}.uhcp-sos-more>div{background:var(--uhcp-panel);border:1px solid var(--uhcp-border);border-radius:1rem;box-shadow:0 18px 45px rgb(22 39 66 / 14%);display:grid;min-width:13rem;padding:.45rem;position:absolute;right:0;top:calc(100% + .4rem);z-index:12}.uhcp-sos-more>div a{border-radius:.65rem}
|
|
606
619
|
.uhcp-sos-panel, .uhcp-sos-empty-panel { background: var(--uhcp-panel); border: 1px solid var(--uhcp-border); border-radius: 2rem; padding: clamp(1.25rem, 4vw, 2.25rem); }
|
|
607
620
|
.uhcp-sos-panel > header { align-items: flex-start; display: flex; gap: 1rem; justify-content: space-between; }
|
|
608
621
|
.uhcp-sos-panel h2 { margin: 0 0 .35rem; }
|
|
@@ -622,7 +635,10 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
|
|
|
622
635
|
@media (max-width: 620px) {
|
|
623
636
|
.uhcp-sos-overview-grid { grid-template-columns: 1fr; }
|
|
624
637
|
.uhcp-sos-panel > header { display: grid; }
|
|
638
|
+
.uhcp-sos-more{margin-left:0}.uhcp-sos-more>div{left:0;right:auto}
|
|
625
639
|
}
|
|
640
|
+
.uhcp-emergency-task-hub{display:grid;gap:1.25rem;margin-top:1.5rem}.uhcp-emergency-task-hub>header h2{font-size:clamp(1.35rem,3vw,1.9rem);margin:0}.uhcp-emergency-task-hub>header p{color:var(--uhcp-muted);margin:.35rem 0 0}.uhcp-emergency-task-list{display:grid;gap:.8rem}.uhcp-emergency-task-list article{align-items:center;border:1px solid var(--uhcp-border);border-radius:1.15rem;display:grid;gap:1rem;grid-template-columns:auto minmax(0,1fr) auto;padding:1rem}.uhcp-emergency-task-icon{align-items:center;background:color-mix(in srgb,var(--uhcp-turquoise) 12%,var(--uhcp-panel));border-radius:50%;color:var(--uhcp-turquoise);display:flex;height:3.25rem;justify-content:center;width:3.25rem}.uhcp-emergency-task-icon svg,.uhcp-emergency-task-list article>a svg{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.8}.uhcp-emergency-task-icon svg{height:1.65rem;width:1.65rem}.uhcp-emergency-task-copy h3{font-size:1.05rem;margin:0}.uhcp-emergency-task-copy p{color:var(--uhcp-muted);line-height:1.45;margin:.25rem 0 0}.uhcp-emergency-task-copy small{color:var(--uhcp-emerald);display:block;font-weight:750;margin-top:.35rem}.uhcp-emergency-task-list article>a{align-items:center;background:var(--uhcp-turquoise);border-radius:.75rem;color:#fff;display:inline-flex;font-weight:800;gap:.45rem;padding:.75rem .9rem;text-decoration:none}.uhcp-emergency-task-list article>a svg{height:1rem;width:1rem}.uhcp-emergency-task-unavailable{color:var(--uhcp-muted);font-size:.85rem;max-width:11rem}.uhcp-emergency-task-list article:has(>a):first-child{border-color:color-mix(in srgb,var(--uhcp-turquoise) 42%,var(--uhcp-border))}@media(max-width:720px){.uhcp-emergency-task-list article{align-items:start;grid-template-columns:auto 1fr}.uhcp-emergency-task-list article>a,.uhcp-emergency-task-unavailable{grid-column:1/-1;justify-content:center;max-width:none;text-align:center}}
|
|
641
|
+
.uhcp-emergency-task-hub-grid .uhcp-emergency-task-list{grid-template-columns:repeat(3,minmax(0,1fr))}.uhcp-emergency-task-hub-grid .uhcp-emergency-task-list article{align-content:start;grid-template-columns:1fr;min-height:16rem;padding:1.35rem}.uhcp-emergency-task-hub-grid .uhcp-emergency-task-icon{height:4rem;width:4rem}.uhcp-emergency-task-hub-grid .uhcp-emergency-task-copy h3{font-size:1.25rem}.uhcp-emergency-task-hub-grid .uhcp-emergency-task-list article>a{justify-content:space-between;margin-top:auto;width:100%}@media(max-width:840px){.uhcp-emergency-task-hub-grid .uhcp-emergency-task-list{grid-template-columns:1fr}.uhcp-emergency-task-hub-grid .uhcp-emergency-task-list article{min-height:0}}
|
|
626
642
|
.uhcp-emergency-copy { background: var(--uhcp-panel); border: 1px solid var(--uhcp-border); border-radius: 2rem; color: var(--uhcp-text); padding: clamp(1.25rem, 4vw, 2.25rem); }
|
|
627
643
|
.uhcp-emergency-copy > header { align-items: flex-start; display: flex; gap: 1.5rem; justify-content: space-between; }
|
|
628
644
|
.uhcp-emergency-copy h2 { margin: 0 0 .45rem; }
|
|
@@ -644,3 +660,22 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
|
|
|
644
660
|
.uhcp-legal-document{color:var(--uhcp-text);line-height:1.7}.uhcp-legal-document h2{font-size:clamp(1.6rem,4vw,2.35rem);line-height:1.15;margin:0 0 1.25rem}.uhcp-legal-document h3{font-size:1.2rem;line-height:1.3;margin:2rem 0 .65rem}.uhcp-legal-document p{margin:0 0 1rem}.uhcp-legal-document ul{margin:0 0 1rem;padding-left:1.4rem}.uhcp-legal-document code{background:var(--uhcp-panel-muted);border-radius:.3rem;padding:.08rem .3rem}
|
|
645
661
|
.uhcp-consent-directory{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}.uhcp-consent-directory>header{align-items:flex-start;display:flex;gap:1rem;justify-content:space-between}.uhcp-consent-directory h2,.uhcp-consent-directory p{margin:0}.uhcp-consent-directory>header p,.uhcp-consent-list article>p{color:var(--uhcp-muted)}.uhcp-consent-directory button,.uhcp-consent-directory select{background:var(--uhcp-panel);border:1px solid var(--uhcp-border);border-radius:.7rem;color:inherit;font:inherit;padding:.65rem .85rem}.uhcp-consent-list{display:grid;gap:.75rem}.uhcp-consent-list article{background:var(--uhcp-panel-muted);border:1px solid var(--uhcp-border);border-radius:1rem;display:grid;gap:.55rem;padding:1rem}.uhcp-consent-list article>div:first-child{align-items:center;display:flex;flex-wrap:wrap;gap:.55rem}.uhcp-consent-list article span{background:color-mix(in srgb,var(--uhcp-turquoise) 13%,transparent);border-radius:999px;font-size:.8rem;padding:.25rem .5rem}.uhcp-consent-actions{display:flex;flex-wrap:wrap;gap:.5rem}.uhcp-consent-editor{border-top:1px solid var(--uhcp-border);display:grid;gap:1rem;padding-top:1rem}.uhcp-consent-editor>label{display:grid;gap:.35rem}.uhcp-consent-editor fieldset{border:1px solid var(--uhcp-border);border-radius:1rem;display:flex;flex-wrap:wrap;gap:.75rem;margin:0;padding:1rem}.uhcp-consent-editor legend{font-weight:800;padding:0 .35rem}.uhcp-consent-editor fieldset label{align-items:center;display:flex;gap:.35rem}.uhcp-consent-editor>div{display:flex;gap:.6rem}@media(max-width:620px){.uhcp-consent-directory>header{display:grid}.uhcp-consent-editor fieldset{display:grid}}
|
|
646
662
|
.uhcp-loading-skeleton{background:var(--uhcp-panel);border:1px solid var(--uhcp-border);border-radius:2rem;display:grid;gap:1rem;margin:0 auto;max-width:1160px;overflow:hidden;padding:clamp(1.25rem,4vw,2.5rem);position:relative}.uhcp-loading-skeleton::after{animation:uhcp-loading-sweep 1.45s ease-in-out infinite;background:linear-gradient(90deg,transparent,color-mix(in srgb,#fff 42%,transparent),transparent);content:"";inset:0;position:absolute;transform:translateX(-100%)}.uhcp-loading-label{height:1px;overflow:hidden;position:absolute;width:1px;clip-path:inset(50%)}.uhcp-loading-heading,.uhcp-loading-copy,.uhcp-loading-row span{animation:uhcp-loading-pulse 1.45s ease-in-out infinite;background:color-mix(in srgb,var(--uhcp-muted) 17%,var(--uhcp-panel-muted));border-radius:999px}.uhcp-loading-heading{height:2.25rem;max-width:23rem;width:62%}.uhcp-loading-copy{height:1rem;max-width:38rem;width:86%}.uhcp-loading-grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(14rem,1fr));margin-top:.5rem}.uhcp-loading-row{background:var(--uhcp-panel-muted);border:1px solid var(--uhcp-border);border-radius:1.35rem;display:grid;gap:.8rem;padding:1.25rem}.uhcp-loading-row span{display:block;height:.8rem}.uhcp-loading-row span:nth-child(1){width:35%}.uhcp-loading-row span:nth-child(2){height:1.2rem;width:72%}.uhcp-loading-row span:nth-child(3){width:90%}.uhcp-loading-skeleton-compact{border-radius:1.25rem;padding:1.25rem}.uhcp-loading-skeleton-compact .uhcp-loading-heading{height:1.5rem}@keyframes uhcp-loading-pulse{0%,100%{opacity:.55}50%{opacity:1}}@keyframes uhcp-loading-sweep{to{transform:translateX(100%)}}@media(prefers-reduced-motion:reduce){.uhcp-loading-skeleton::after,.uhcp-loading-heading,.uhcp-loading-copy,.uhcp-loading-row span{animation:none}}
|
|
663
|
+
.uhcp-animal-onboarding { display: grid; gap: 1.25rem; }
|
|
664
|
+
.uhcp-animal-onboarding > header p { color: var(--uhcp-muted, #5f6875); margin: .35rem 0 0; }
|
|
665
|
+
.uhcp-animal-onboarding form { display: grid; gap: 1rem; }
|
|
666
|
+
.uhcp-animal-onboarding fieldset { border: 1px solid var(--uhcp-border, #d9dee7); border-radius: 1rem; margin: 0; padding: 1rem; }
|
|
667
|
+
.uhcp-animal-onboarding legend { align-items: center; display: flex; font-weight: 800; gap: .55rem; padding: 0 .35rem; }
|
|
668
|
+
.uhcp-animal-onboarding-fields { display: grid; gap: .85rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 14rem), 1fr)); }
|
|
669
|
+
.uhcp-animal-onboarding-fields label { display: grid; gap: .35rem; }
|
|
670
|
+
.uhcp-animal-onboarding-fields input, .uhcp-animal-onboarding-fields select { box-sizing: border-box; min-height: 2.8rem; width: 100%; }
|
|
671
|
+
.uhcp-animal-onboarding-submit { justify-self: start; }
|
|
672
|
+
.uhcp-emergency-task-hub > header h1 { font-size: clamp(1.35rem, 3vw, 1.9rem); margin: 0; }
|
|
673
|
+
.uhcp-subject-identity-card { border: 1px solid var(--uhcp-border, #d9dee7); border-radius: 1rem; display: grid; gap: 1rem; padding: 1rem; }
|
|
674
|
+
.uhcp-subject-identity-card > header { align-items: center; display: grid; gap: .8rem; grid-template-columns: auto 1fr auto; }
|
|
675
|
+
.uhcp-subject-identity-card img, .uhcp-subject-identity-avatar { align-items: center; aspect-ratio: 1; border-radius: 50%; display: flex; height: 3.5rem; justify-content: center; object-fit: cover; width: 3.5rem; }
|
|
676
|
+
.uhcp-subject-identity-avatar { background: var(--uhcp-accent-soft, #e9f3ff); font-size: 1.4rem; font-weight: 850; }
|
|
677
|
+
.uhcp-subject-identity-card h3 { margin: .15rem 0 0; }
|
|
678
|
+
.uhcp-subject-identity-card dl { display: grid; gap: .65rem; grid-template-columns: repeat(auto-fit, minmax(10rem, 1fr)); margin: 0; }
|
|
679
|
+
.uhcp-subject-identity-card dt { color: var(--uhcp-muted, #5f6875); font-size: .8rem; }
|
|
680
|
+
.uhcp-subject-identity-card dd { font-weight: 700; margin: .15rem 0 0; overflow-wrap: anywhere; }
|
|
681
|
+
.uhcp-subject-identity-relationship { align-items: center; background: var(--uhcp-surface-soft, #f6f8fb); border-radius: .8rem; display: grid; gap: .25rem; padding: .8rem; }
|
package/package.json
CHANGED