uhc-portal-components-react 0.1.47 → 0.1.48
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 +11 -0
- package/README.md +7 -0
- package/dist/ClinicalArtifactEditor.d.ts +1 -0
- package/dist/ClinicalArtifactEditor.d.ts.map +1 -1
- package/dist/ClinicalArtifactEditor.js +1 -1
- package/dist/ClinicalArtifactEditorV2.d.ts +74 -0
- package/dist/ClinicalArtifactEditorV2.d.ts.map +1 -0
- package/dist/ClinicalArtifactEditorV2.js +78 -0
- package/dist/ClinicalArtifactPropertiesV2.d.ts +82 -0
- package/dist/ClinicalArtifactPropertiesV2.d.ts.map +1 -0
- package/dist/ClinicalArtifactPropertiesV2.js +95 -0
- package/dist/ClinicalBundleDraftEditor.d.ts +16 -2
- package/dist/ClinicalBundleDraftEditor.d.ts.map +1 -1
- package/dist/ClinicalBundleDraftEditor.js +17 -5
- package/dist/ImmunizationArtifactEditorV2.d.ts +14 -0
- package/dist/ImmunizationArtifactEditorV2.d.ts.map +1 -0
- package/dist/ImmunizationArtifactEditorV2.js +58 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/styles.css +27 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.1.48 - 2026-10-08
|
|
6
|
+
|
|
7
|
+
- Add an opt-in V2 clinical authoring shell without changing the existing V1
|
|
8
|
+
editor. Its reusable date/time, coded-concept, coded-select, positive-integer,
|
|
9
|
+
document-reference and progressive optional-field properties support
|
|
10
|
+
resource-specific editors.
|
|
11
|
+
- Add `ImmunizationArtifactEditorV2` with a minimal initial form, explicit
|
|
12
|
+
terminology search and selection, locked canonical coding, removable
|
|
13
|
+
optional flat claims, dose-series validation and automatic next-dose
|
|
14
|
+
ImmunizationRecommendation staging.
|
|
15
|
+
|
|
5
16
|
## 0.1.47 - 2026-10-08
|
|
6
17
|
|
|
7
18
|
- Show the localized FHIR resource type in the shared Bundle selector and in
|
package/README.md
CHANGED
|
@@ -86,6 +86,13 @@ The package deliberately exposes modules instead of a cloned application:
|
|
|
86
86
|
terminology candidate preserves source text and adds only the confirmed
|
|
87
87
|
`system|code` and display. Success requires a fresh provider readback Bundle;
|
|
88
88
|
local form state is never presented as a persisted write.
|
|
89
|
+
- `ClinicalArtifactEditorV2` is an explicit opt-in progressive shell; it does
|
|
90
|
+
not replace `ClinicalArtifactEditor`. Resource specializations such as
|
|
91
|
+
`ImmunizationArtifactEditorV2` compose reusable `DateTimePropertyV2`,
|
|
92
|
+
`CodedConceptPropertyV2`, `CodedSelectPropertyV2`,
|
|
93
|
+
`PositiveIntegerPropertyV2`, `DocumentReferencesPropertyV2` and
|
|
94
|
+
`OptionalFieldsV2` controls. `ClinicalBundleDraftEditorV2` uses a V2
|
|
95
|
+
specialization only when one exists and retains V1 for other resources.
|
|
89
96
|
- `ClinicalSpeechInputProvider`: lets the owning portal publish one
|
|
90
97
|
speech-recognition capability and model phase to every nested clinical
|
|
91
98
|
editor. Compatible IPS text fields show an accessible microphone only when
|
|
@@ -142,4 +142,5 @@ export type ClinicalArtifactEditorProps = Readonly<{
|
|
|
142
142
|
* published only after the host returns a fresh provider readback Bundle.
|
|
143
143
|
*/
|
|
144
144
|
export declare function ClinicalArtifactEditor({ request, schema, operationSchema, authoringContext, copy, locale, timeZone, taxonomyId, fieldLabel, resourceTypeLabel, searchTerminology, loadTerminologySources, saveArtifact, onCancel, onReadback, }: ClinicalArtifactEditorProps): import("react").JSX.Element;
|
|
145
|
+
export declare function readClinicalAttachment(file: File): Promise<ClinicalArtifactAttachment>;
|
|
145
146
|
//# sourceMappingURL=ClinicalArtifactEditor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClinicalArtifactEditor.d.ts","sourceRoot":"","sources":["../src/ClinicalArtifactEditor.tsx"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ClinicalArtifactEditor.d.ts","sourceRoot":"","sources":["../src/ClinicalArtifactEditor.tsx"],"names":[],"mappings":"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"}
|
|
@@ -201,7 +201,7 @@ export function ClinicalArtifactEditor({ request, schema, operationSchema, autho
|
|
|
201
201
|
}).catch((reason) => setError(reason instanceof Error ? reason.message : String(reason)));
|
|
202
202
|
} })] }), attachments.length ? _jsx("ul", { children: attachments.map((attachment) => _jsxs("li", { children: [_jsx("span", { children: attachment.name }), _jsx("button", { type: "button", "aria-label": `${copy.removeAttachment || 'Remove document'} ${attachment.name}`, onClick: () => setAttachments(current => current.filter(candidate => candidate.id !== attachment.id)), children: "\u00D7" })] }, attachment.id)) }) : null] }), error ? _jsx("p", { className: "uhcp-clinical-editor-error", role: "alert", children: error }) : null, pending ? _jsx("p", { className: "uhcp-clinical-editor-pending", role: "status", children: copy.pending || pending }) : null, _jsxs("footer", { children: [_jsx("button", { type: "button", onClick: onCancel, children: copy.cancel }), _jsx("button", { type: "submit", disabled: saving, children: saving ? copy.saving : pending ? (copy.retry || copy.save) : copy.save })] })] })] }) });
|
|
203
203
|
}
|
|
204
|
-
async function readClinicalAttachment(file) {
|
|
204
|
+
export async function readClinicalAttachment(file) {
|
|
205
205
|
const contentType = normalizeClinicalAttachmentType(file);
|
|
206
206
|
const bytes = new Uint8Array(await readFileBytes(file));
|
|
207
207
|
const digest = new Uint8Array(await crypto.subtle.digest('SHA-256', bytes));
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { ClinicalResourceBundleLike } from 'gdc-common-utils-ts/utils/clinical-resource-view';
|
|
2
|
+
import { type ClinicalPropertyOptionV2 } from './ClinicalArtifactPropertiesV2.js';
|
|
3
|
+
import type { ClinicalArtifactAuthoringContext, ClinicalArtifactDraft, ClinicalArtifactEditorRequest, ClinicalArtifactSaveOutcome, ClinicalTerminologyCandidate, ClinicalTerminologySearch, ClinicalTerminologySourceSearch } from './ClinicalArtifactEditor.js';
|
|
4
|
+
export type ClinicalArtifactRelatedEntryV2 = Readonly<{
|
|
5
|
+
entryId: string;
|
|
6
|
+
resourceType: string;
|
|
7
|
+
claims: Readonly<Record<string, string>>;
|
|
8
|
+
sectionCode?: string;
|
|
9
|
+
}>;
|
|
10
|
+
export type ClinicalArtifactDraftV2 = ClinicalArtifactDraft & Readonly<{
|
|
11
|
+
relatedEntries?: readonly ClinicalArtifactRelatedEntryV2[];
|
|
12
|
+
}>;
|
|
13
|
+
export type ClinicalArtifactFieldV2 = Readonly<{
|
|
14
|
+
claim: string;
|
|
15
|
+
kind: 'text' | 'date' | 'date-time' | 'positive-integer' | 'coded-select' | 'coded-concept' | 'documents';
|
|
16
|
+
required?: boolean;
|
|
17
|
+
transient?: boolean;
|
|
18
|
+
options?: readonly ClinicalPropertyOptionV2[];
|
|
19
|
+
textClaim?: string;
|
|
20
|
+
codeClaim?: string;
|
|
21
|
+
displayClaim?: string;
|
|
22
|
+
}>;
|
|
23
|
+
export type ClinicalArtifactEditorCopyV2 = Readonly<{
|
|
24
|
+
title: string;
|
|
25
|
+
description: string;
|
|
26
|
+
resourceType?: string;
|
|
27
|
+
save: string;
|
|
28
|
+
saving: string;
|
|
29
|
+
cancel: string;
|
|
30
|
+
close: string;
|
|
31
|
+
terminologyLoading: string;
|
|
32
|
+
terminologyUnavailable: string;
|
|
33
|
+
terminologySources: string;
|
|
34
|
+
readbackMissing: string;
|
|
35
|
+
addField: string;
|
|
36
|
+
chooseField: string;
|
|
37
|
+
addSelectedField: string;
|
|
38
|
+
removeField: string;
|
|
39
|
+
searchTerminology: string;
|
|
40
|
+
clearCoding: string;
|
|
41
|
+
selectCandidate: string;
|
|
42
|
+
canonicalCode: string;
|
|
43
|
+
canonicalDisplay: string;
|
|
44
|
+
documents: string;
|
|
45
|
+
addDocuments: string;
|
|
46
|
+
removeDocument: string;
|
|
47
|
+
date: string;
|
|
48
|
+
time: string;
|
|
49
|
+
useToday: string;
|
|
50
|
+
useCurrentTime: string;
|
|
51
|
+
}>;
|
|
52
|
+
export type ClinicalArtifactEditorV2Props = Readonly<{
|
|
53
|
+
request: ClinicalArtifactEditorRequest;
|
|
54
|
+
authoringContext: ClinicalArtifactAuthoringContext;
|
|
55
|
+
copy: ClinicalArtifactEditorCopyV2;
|
|
56
|
+
fields: readonly ClinicalArtifactFieldV2[];
|
|
57
|
+
initialVisibleClaims: readonly string[];
|
|
58
|
+
initialClaims?: Readonly<Record<string, string>>;
|
|
59
|
+
locale?: string;
|
|
60
|
+
timeZone?: string;
|
|
61
|
+
taxonomyId?: string;
|
|
62
|
+
fieldLabel: (claim: string) => string;
|
|
63
|
+
resourceTypeLabel?: string;
|
|
64
|
+
searchTerminology?: (input: ClinicalTerminologySearch) => Promise<readonly ClinicalTerminologyCandidate[]>;
|
|
65
|
+
loadTerminologySources?: ClinicalTerminologySourceSearch;
|
|
66
|
+
validate?: (claims: Readonly<Record<string, string>>) => void;
|
|
67
|
+
buildRelatedEntries?: (claims: Readonly<Record<string, string>>, draftId: string) => readonly ClinicalArtifactRelatedEntryV2[];
|
|
68
|
+
saveArtifact: (draft: ClinicalArtifactDraftV2) => Promise<ClinicalResourceBundleLike | ClinicalArtifactSaveOutcome | undefined>;
|
|
69
|
+
onCancel: () => void;
|
|
70
|
+
onReadback: (bundle: ClinicalResourceBundleLike) => void;
|
|
71
|
+
}>;
|
|
72
|
+
/** Progressive reusable V2 shell. Resource rules are supplied by a specialized editor. */
|
|
73
|
+
export declare function ClinicalArtifactEditorV2({ request, authoringContext, copy, fields, initialVisibleClaims, initialClaims, locale, timeZone, taxonomyId, fieldLabel, resourceTypeLabel, searchTerminology, loadTerminologySources, validate, buildRelatedEntries, saveArtifact, onCancel, onReadback }: ClinicalArtifactEditorV2Props): import("react").JSX.Element;
|
|
74
|
+
//# sourceMappingURL=ClinicalArtifactEditorV2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClinicalArtifactEditorV2.d.ts","sourceRoot":"","sources":["../src/ClinicalArtifactEditorV2.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useId, useRef, useState } from 'react';
|
|
4
|
+
import { ClinicalEditorLayer } from './ClinicalEditorLayer.js';
|
|
5
|
+
import { readClinicalAttachment } from './ClinicalArtifactEditor.js';
|
|
6
|
+
import { CodedConceptPropertyV2, CodedSelectPropertyV2, DateTimePropertyV2, DocumentReferencesPropertyV2, OptionalFieldsV2, PositiveIntegerPropertyV2, } from './ClinicalArtifactPropertiesV2.js';
|
|
7
|
+
/** Progressive reusable V2 shell. Resource rules are supplied by a specialized editor. */
|
|
8
|
+
export function ClinicalArtifactEditorV2({ request, authoringContext, copy, fields, initialVisibleClaims, initialClaims = {}, locale = 'en', timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone, taxonomyId, fieldLabel, resourceTypeLabel, searchTerminology, loadTerminologySources, validate, buildRelatedEntries, saveArtifact, onCancel, onReadback }) {
|
|
9
|
+
const titleId = useId();
|
|
10
|
+
const [claims, setClaims] = useState({ ...initialClaims, ...stringClaims(request.initialClaims) });
|
|
11
|
+
const [visibleClaims, setVisibleClaims] = useState(() => [...new Set([...initialVisibleClaims, ...Object.keys(request.initialClaims ?? {}).filter(claim => fields.some(field => field.claim === claim))])]);
|
|
12
|
+
const [selectedOptional, setSelectedOptional] = useState('');
|
|
13
|
+
const [saving, setSaving] = useState(false);
|
|
14
|
+
const [attachments, setAttachments] = useState(request.initialAttachments ?? []);
|
|
15
|
+
const [error, setError] = useState('');
|
|
16
|
+
const draftId = useRef(request.artifactId ?? crypto.randomUUID());
|
|
17
|
+
const optional = fields.filter(field => !field.required && !visibleClaims.includes(field.claim)).map(field => ({ value: field.claim, label: fieldLabel(field.claim) }));
|
|
18
|
+
const update = (claim, value) => setClaims(current => ({ ...current, [claim]: value }));
|
|
19
|
+
async function submit() {
|
|
20
|
+
setError('');
|
|
21
|
+
try {
|
|
22
|
+
validate?.(claims);
|
|
23
|
+
setSaving(true);
|
|
24
|
+
const draft = {
|
|
25
|
+
resourceType: request.resourceType,
|
|
26
|
+
id: draftId.current,
|
|
27
|
+
sectionCode: request.sectionCode,
|
|
28
|
+
mode: request.mode,
|
|
29
|
+
claims: cleanClaims(claims, fields),
|
|
30
|
+
attachments,
|
|
31
|
+
relatedEntries: buildRelatedEntries?.(claims, draftId.current) ?? [],
|
|
32
|
+
};
|
|
33
|
+
const result = await saveArtifact(draft);
|
|
34
|
+
if (!result)
|
|
35
|
+
throw new Error(copy.readbackMissing);
|
|
36
|
+
if ('state' in result) {
|
|
37
|
+
if (result.state === 'confirmed')
|
|
38
|
+
onReadback(result.bundle);
|
|
39
|
+
else if (result.state === 'rejected')
|
|
40
|
+
throw new Error(result.message);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
onReadback(result);
|
|
44
|
+
}
|
|
45
|
+
catch (reason) {
|
|
46
|
+
setError(reason instanceof Error ? reason.message : String(reason));
|
|
47
|
+
}
|
|
48
|
+
finally {
|
|
49
|
+
setSaving(false);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return _jsx(ClinicalEditorLayer, { onDismiss: onCancel, children: _jsxs("section", { className: "uhcp-clinical-editor uhcp-clinical-editor-v2", role: "dialog", "aria-modal": "true", "aria-labelledby": titleId, children: [_jsxs("header", { children: [_jsxs("div", { children: [_jsx("h2", { id: titleId, children: copy.title }), _jsxs("p", { className: "uhcp-clinical-editor-resource-type", children: [copy.resourceType || 'FHIR resource', ": ", resourceTypeLabel || request.resourceType] }), _jsx("p", { children: copy.description })] }), _jsx("button", { type: "button", "aria-label": copy.close, onClick: onCancel, children: "\u00D7" })] }), _jsxs("form", { onSubmit: event => { event.preventDefault(); void submit(); }, children: [fields.filter(field => visibleClaims.includes(field.claim)).map(field => _jsxs("div", { className: "uhcp-progressive-field-v2", children: [!field.required ? _jsx("button", { type: "button", className: "uhcp-remove-field-v2", "aria-label": `${copy.removeField}: ${fieldLabel(field.claim)}`, onClick: () => { setVisibleClaims(current => current.filter(claim => claim !== field.claim)); if (field.kind === 'documents')
|
|
53
|
+
setAttachments([]); setClaims(current => { const next = { ...current }; delete next[field.claim]; if (field.codeClaim)
|
|
54
|
+
delete next[field.codeClaim]; if (field.displayClaim)
|
|
55
|
+
delete next[field.displayClaim]; return next; }); }, children: "\u00D7" }) : null, field.kind === 'documents' ? _jsx(DocumentReferencesPropertyV2, { copy: copy, attachments: attachments, onFiles: files => { void Promise.all(files.map(readClinicalAttachment)).then(next => setAttachments(current => [...current, ...next])).catch(reason => setError(reason instanceof Error ? reason.message : String(reason))); }, onRemove: id => setAttachments(current => current.filter(attachment => attachment.id !== id)) })
|
|
56
|
+
: _jsx(ClinicalProperty, { field: field, label: fieldLabel(field.claim), resourceType: request.resourceType, value: claims[field.claim] ?? '', claims: claims, locale: locale, timeZone: timeZone, taxonomyId: taxonomyId, copy: copy, update: update, searchTerminology: searchTerminology, loadTerminologySources: loadTerminologySources })] }, field.claim)), _jsx(OptionalFieldsV2, { label: copy.addField, choose: copy.chooseField, add: copy.addSelectedField, options: optional, value: selectedOptional, onValueChange: setSelectedOptional, onAdd: () => { if (!selectedOptional)
|
|
57
|
+
return; setVisibleClaims(current => [...current, selectedOptional]); setSelectedOptional(''); } }), error ? _jsx("p", { className: "uhcp-clinical-editor-error", role: "alert", children: error }) : null, _jsxs("footer", { children: [_jsx("button", { type: "button", onClick: onCancel, children: copy.cancel }), _jsx("button", { type: "submit", disabled: saving, children: saving ? copy.saving : copy.save })] })] })] }) });
|
|
58
|
+
}
|
|
59
|
+
function ClinicalProperty({ field, label, resourceType, value, claims, locale, timeZone, taxonomyId, copy, update, searchTerminology, loadTerminologySources }) {
|
|
60
|
+
if (field.kind === 'date-time')
|
|
61
|
+
return _jsx(DateTimePropertyV2, { label: label, value: value, required: field.required, locale: locale, timeZone: timeZone, copy: copy, onChange: next => update(field.claim, next) });
|
|
62
|
+
if (field.kind === 'date')
|
|
63
|
+
return _jsxs("label", { className: "uhcp-clinical-property-v2", children: [label, field.required ? ' *' : '', _jsx("input", { "aria-label": label, type: "date", required: field.required, value: value, onChange: event => update(field.claim, event.currentTarget.value) })] });
|
|
64
|
+
if (field.kind === 'positive-integer')
|
|
65
|
+
return _jsx(PositiveIntegerPropertyV2, { label: label, value: value, required: field.required, onChange: next => update(field.claim, next) });
|
|
66
|
+
if (field.kind === 'coded-select')
|
|
67
|
+
return _jsx(CodedSelectPropertyV2, { label: label, value: value, required: field.required, options: field.options ?? [], onChange: next => update(field.claim, next) });
|
|
68
|
+
if (field.kind === 'coded-concept' && field.codeClaim)
|
|
69
|
+
return _jsx(CodedConceptPropertyV2, { resourceType: resourceType, textClaim: field.textClaim, codeClaim: field.codeClaim, displayClaim: field.displayClaim, label: label, locale: locale, taxonomyId: taxonomyId, text: field.textClaim ? claims[field.textClaim] ?? '' : '', code: claims[field.codeClaim] ?? '', display: field.displayClaim ? claims[field.displayClaim] ?? '' : '', required: field.required, copy: copy, searchTerminology: searchTerminology, loadTerminologySources: loadTerminologySources, onChange: next => { if (field.textClaim)
|
|
70
|
+
update(field.textClaim, next.text); update(field.codeClaim, next.code); if (field.displayClaim)
|
|
71
|
+
update(field.displayClaim, next.display); } });
|
|
72
|
+
return _jsxs("label", { className: "uhcp-clinical-property-v2", children: [label, field.required ? ' *' : '', _jsx("input", { "aria-label": label, required: field.required, value: value, onChange: event => update(field.claim, event.currentTarget.value) })] });
|
|
73
|
+
}
|
|
74
|
+
function stringClaims(value) { return Object.fromEntries(Object.entries(value ?? {}).map(([claim, item]) => [claim, String(item ?? '')])); }
|
|
75
|
+
function cleanClaims(value, fields) {
|
|
76
|
+
const transient = new Set(fields.filter(field => field.transient).map(field => field.claim));
|
|
77
|
+
return Object.fromEntries(Object.entries(value).filter(([claim, item]) => item !== '' && !transient.has(claim)));
|
|
78
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { ClinicalArtifactAttachment, ClinicalTerminologyCandidate, ClinicalTerminologySearch, ClinicalTerminologySourceSearch } from './ClinicalArtifactEditor.js';
|
|
2
|
+
export type ClinicalPropertyOptionV2 = Readonly<{
|
|
3
|
+
value: string;
|
|
4
|
+
label: string;
|
|
5
|
+
}>;
|
|
6
|
+
export declare function DateTimePropertyV2({ label, value, required, locale, timeZone, copy, onChange }: Readonly<{
|
|
7
|
+
label: string;
|
|
8
|
+
value: string;
|
|
9
|
+
required?: boolean;
|
|
10
|
+
locale: string;
|
|
11
|
+
timeZone: string;
|
|
12
|
+
copy: Readonly<{
|
|
13
|
+
date: string;
|
|
14
|
+
time: string;
|
|
15
|
+
useToday: string;
|
|
16
|
+
useCurrentTime: string;
|
|
17
|
+
}>;
|
|
18
|
+
onChange: (value: string) => void;
|
|
19
|
+
}>): import("react").JSX.Element;
|
|
20
|
+
export declare function CodedConceptPropertyV2({ resourceType, textClaim, codeClaim, displayClaim, label, locale, taxonomyId, text, code, display, required, copy, searchTerminology, loadTerminologySources, onChange }: Readonly<{
|
|
21
|
+
resourceType: string;
|
|
22
|
+
textClaim?: string;
|
|
23
|
+
codeClaim: string;
|
|
24
|
+
displayClaim?: string;
|
|
25
|
+
label: string;
|
|
26
|
+
locale: string;
|
|
27
|
+
taxonomyId?: string;
|
|
28
|
+
text: string;
|
|
29
|
+
code: string;
|
|
30
|
+
display: string;
|
|
31
|
+
required?: boolean;
|
|
32
|
+
copy: Readonly<{
|
|
33
|
+
searchTerminology: string;
|
|
34
|
+
terminologyLoading: string;
|
|
35
|
+
terminologyUnavailable: string;
|
|
36
|
+
terminologySources: string;
|
|
37
|
+
selectCandidate: string;
|
|
38
|
+
clearCoding: string;
|
|
39
|
+
canonicalCode: string;
|
|
40
|
+
canonicalDisplay: string;
|
|
41
|
+
}>;
|
|
42
|
+
searchTerminology?: (input: ClinicalTerminologySearch) => Promise<readonly ClinicalTerminologyCandidate[]>;
|
|
43
|
+
loadTerminologySources?: ClinicalTerminologySourceSearch;
|
|
44
|
+
onChange: (value: Readonly<{
|
|
45
|
+
text: string;
|
|
46
|
+
code: string;
|
|
47
|
+
display: string;
|
|
48
|
+
}>) => void;
|
|
49
|
+
}>): import("react").JSX.Element;
|
|
50
|
+
export declare function CodedSelectPropertyV2({ label, value, required, options, onChange }: Readonly<{
|
|
51
|
+
label: string;
|
|
52
|
+
value: string;
|
|
53
|
+
required?: boolean;
|
|
54
|
+
options: readonly ClinicalPropertyOptionV2[];
|
|
55
|
+
onChange: (value: string) => void;
|
|
56
|
+
}>): import("react").JSX.Element;
|
|
57
|
+
export declare function PositiveIntegerPropertyV2({ label, value, required, onChange }: Readonly<{
|
|
58
|
+
label: string;
|
|
59
|
+
value: string;
|
|
60
|
+
required?: boolean;
|
|
61
|
+
onChange: (value: string) => void;
|
|
62
|
+
}>): import("react").JSX.Element;
|
|
63
|
+
export declare function OptionalFieldsV2({ label, choose, add, options, value, onValueChange, onAdd }: Readonly<{
|
|
64
|
+
label: string;
|
|
65
|
+
choose: string;
|
|
66
|
+
add: string;
|
|
67
|
+
options: readonly ClinicalPropertyOptionV2[];
|
|
68
|
+
value: string;
|
|
69
|
+
onValueChange: (value: string) => void;
|
|
70
|
+
onAdd: () => void;
|
|
71
|
+
}>): import("react").JSX.Element | null;
|
|
72
|
+
export declare function DocumentReferencesPropertyV2({ copy, attachments, onFiles, onRemove }: Readonly<{
|
|
73
|
+
copy: Readonly<{
|
|
74
|
+
documents: string;
|
|
75
|
+
addDocuments: string;
|
|
76
|
+
removeDocument: string;
|
|
77
|
+
}>;
|
|
78
|
+
attachments: readonly ClinicalArtifactAttachment[];
|
|
79
|
+
onFiles: (files: readonly File[]) => void;
|
|
80
|
+
onRemove: (id: string) => void;
|
|
81
|
+
}>): import("react").JSX.Element;
|
|
82
|
+
//# sourceMappingURL=ClinicalArtifactPropertiesV2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClinicalArtifactPropertiesV2.d.ts","sourceRoot":"","sources":["../src/ClinicalArtifactPropertiesV2.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
4
|
+
import { composeFhirDateTimeFromLocalParts, splitFhirDateTimeForInput, } from 'fhir-data-utils-ts/fhir-temporal-presentation';
|
|
5
|
+
import { ClinicalSpeechInputButton } from './ClinicalSpeechInput.js';
|
|
6
|
+
export function DateTimePropertyV2({ label, value, required, locale, timeZone, copy, onChange }) {
|
|
7
|
+
const [parts, setParts] = useState(() => splitDateTime(value, timeZone));
|
|
8
|
+
const current = splitFhirDateTimeForInput(new Date(), timeZone);
|
|
9
|
+
const update = (next) => {
|
|
10
|
+
setParts(next);
|
|
11
|
+
onChange(!next.date ? '' : next.time ? composeFhirDateTimeFromLocalParts({ ...next, timeZone }) : next.date);
|
|
12
|
+
};
|
|
13
|
+
return _jsxs("fieldset", { className: "uhcp-clinical-property-v2 uhcp-date-time-property-v2", children: [_jsxs("legend", { children: [label, required ? ' *' : ''] }), _jsxs("label", { children: [_jsx("span", { children: copy.date }), _jsx("input", { "aria-label": `${label}: ${copy.date}`, type: "date", required: required, value: parts.date, onChange: event => update({ ...parts, date: event.currentTarget.value }) })] }), _jsx("button", { type: "button", onClick: () => update({ ...parts, date: current.date }), children: copy.useToday }), _jsxs("label", { children: [_jsx("span", { children: copy.time }), _jsx("input", { "aria-label": `${label}: ${copy.time}`, type: "time", step: "60", value: parts.time.slice(0, 5), onChange: event => update({ ...parts, time: event.currentTarget.value }) })] }), _jsx("button", { type: "button", onClick: () => update({ ...parts, time: current.time.slice(0, 5) }), children: copy.useCurrentTime })] });
|
|
14
|
+
}
|
|
15
|
+
export function CodedConceptPropertyV2({ resourceType, textClaim, codeClaim, displayClaim, label, locale, taxonomyId, text, code, display, required, copy, searchTerminology, loadTerminologySources, onChange }) {
|
|
16
|
+
const [query, setQuery] = useState(text || display);
|
|
17
|
+
const [sources, setSources] = useState([]);
|
|
18
|
+
const [selectedSources, setSelectedSources] = useState([]);
|
|
19
|
+
const [candidates, setCandidates] = useState([]);
|
|
20
|
+
const [busy, setBusy] = useState(false);
|
|
21
|
+
const [failed, setFailed] = useState(false);
|
|
22
|
+
useEffect(() => {
|
|
23
|
+
if (!loadTerminologySources)
|
|
24
|
+
return;
|
|
25
|
+
let current = true;
|
|
26
|
+
void loadTerminologySources({ resourceType, claim: codeClaim, language: locale, taxonomyId }).then(next => {
|
|
27
|
+
if (!current)
|
|
28
|
+
return;
|
|
29
|
+
setSources(next);
|
|
30
|
+
const defaults = next.filter(source => source.default).map(source => source.id);
|
|
31
|
+
setSelectedSources(defaults.length ? defaults : next[0] ? [next[0].id] : []);
|
|
32
|
+
}).catch(() => current && setSources([]));
|
|
33
|
+
return () => { current = false; };
|
|
34
|
+
}, [codeClaim, loadTerminologySources, locale, resourceType, taxonomyId]);
|
|
35
|
+
const selectedToken = useMemo(() => code, [code]);
|
|
36
|
+
const search = async () => {
|
|
37
|
+
if (!searchTerminology || query.trim().length < 2 || busy)
|
|
38
|
+
return;
|
|
39
|
+
setBusy(true);
|
|
40
|
+
setFailed(false);
|
|
41
|
+
try {
|
|
42
|
+
let governedSources = selectedSources;
|
|
43
|
+
if (!governedSources.length && loadTerminologySources) {
|
|
44
|
+
const loaded = await loadTerminologySources({ resourceType, claim: codeClaim, language: locale, taxonomyId });
|
|
45
|
+
const defaults = loaded.filter(source => source.default).map(source => source.id);
|
|
46
|
+
governedSources = defaults.length ? defaults : loaded[0] ? [loaded[0].id] : [];
|
|
47
|
+
setSources(loaded);
|
|
48
|
+
setSelectedSources(governedSources);
|
|
49
|
+
}
|
|
50
|
+
setCandidates(await searchTerminology({ resourceType, claim: codeClaim, language: locale, text: query.trim(), taxonomyId, limit: 20, ...(governedSources.length ? { sources: governedSources } : {}) }));
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
setCandidates([]);
|
|
54
|
+
setFailed(true);
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
setBusy(false);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
return _jsxs("div", { className: "uhcp-clinical-property-v2 uhcp-coded-concept-property-v2", children: [_jsxs("span", { className: "uhcp-clinical-editor-field-heading", children: [_jsxs("label", { htmlFor: `${codeClaim}-query`, children: [label, required ? ' *' : ''] }), textClaim ? _jsx(ClinicalSpeechInputButton, { resourceType: resourceType, claim: textClaim, locale: locale, fieldLabel: label, onTranscript: transcript => { setQuery(transcript); onChange({ text: transcript, code: '', display: '' }); } }) : null] }), _jsxs("div", { className: "uhcp-coded-concept-query-v2", children: [_jsx("input", { id: `${codeClaim}-query`, "aria-label": label, required: required, readOnly: Boolean(code), value: code ? (text || query || display) : query, onChange: event => { setQuery(event.currentTarget.value); onChange({ text: event.currentTarget.value, code: '', display: '' }); } }), _jsx("button", { type: "button", className: "uhcp-icon-button-v2", "aria-label": copy.searchTerminology, title: copy.searchTerminology, disabled: Boolean(code) || busy || query.trim().length < 2, onClick: () => void search(), children: _jsx("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", children: _jsx("path", { d: "m21 21-4.35-4.35m1.35-5.65a7 7 0 1 1-14 0 7 7 0 0 1 14 0Z" }) }) }), code ? _jsx("button", { type: "button", className: "uhcp-clear-code-v2", "aria-label": copy.clearCoding, title: copy.clearCoding, onClick: () => { setQuery(''); setCandidates([]); onChange({ text: '', code: '', display: '' }); }, children: "\u00D7" }) : null] }), sources.length ? _jsxs("fieldset", { className: "uhcp-coding-sources-v2", children: [_jsx("legend", { children: copy.terminologySources }), sources.map(source => _jsxs("label", { children: [_jsx("input", { type: "checkbox", checked: selectedSources.includes(source.id), onChange: event => setSelectedSources(current => event.currentTarget.checked ? [...new Set([...current, source.id])] : current.filter(value => value !== source.id)) }), source.label || source.id] }, source.id))] }) : null, busy ? _jsx("small", { role: "status", children: copy.terminologyLoading }) : null, failed ? _jsx("small", { role: "alert", children: copy.terminologyUnavailable }) : null, candidates.length ? _jsxs("label", { children: [copy.selectCandidate, _jsxs("select", { "aria-label": copy.selectCandidate, value: selectedToken, onChange: event => {
|
|
61
|
+
const candidate = candidates.find(value => `${value.system}|${value.code}` === event.currentTarget.value);
|
|
62
|
+
if (!candidate)
|
|
63
|
+
return;
|
|
64
|
+
const localText = candidate.text || query || candidate.display;
|
|
65
|
+
setQuery(localText);
|
|
66
|
+
onChange({ text: localText, code: `${candidate.system}|${candidate.code}`, display: candidate.display });
|
|
67
|
+
setCandidates([]);
|
|
68
|
+
}, children: [_jsx("option", { value: "" }), candidates.map(candidate => _jsxs("option", { value: `${candidate.system}|${candidate.code}`, children: [candidate.display, " (", candidate.code, ")"] }, `${candidate.system}|${candidate.code}`))] })] }) : null, code ? _jsxs("div", { className: "uhcp-selected-code-v2", children: [_jsxs("label", { children: [copy.canonicalCode, _jsx("input", { "aria-label": copy.canonicalCode, readOnly: true, value: code })] }), _jsxs("label", { children: [copy.canonicalDisplay, _jsx("input", { "aria-label": copy.canonicalDisplay, readOnly: true, value: display })] })] }) : null] });
|
|
69
|
+
}
|
|
70
|
+
export function CodedSelectPropertyV2({ label, value, required, options, onChange }) {
|
|
71
|
+
return _jsxs("label", { className: "uhcp-clinical-property-v2", children: [label, required ? ' *' : '', _jsxs("select", { "aria-label": label, required: required, value: value, onChange: event => onChange(event.currentTarget.value), children: [_jsx("option", { value: "" }), options.map(option => _jsx("option", { value: option.value, children: option.label }, option.value))] })] });
|
|
72
|
+
}
|
|
73
|
+
export function PositiveIntegerPropertyV2({ label, value, required, onChange }) {
|
|
74
|
+
return _jsxs("label", { className: "uhcp-clinical-property-v2", children: [label, required ? ' *' : '', _jsx("input", { "aria-label": label, type: "number", min: "1", step: "1", required: required, value: value, onChange: event => onChange(event.currentTarget.value) })] });
|
|
75
|
+
}
|
|
76
|
+
export function OptionalFieldsV2({ label, choose, add, options, value, onValueChange, onAdd }) {
|
|
77
|
+
if (!options.length)
|
|
78
|
+
return null;
|
|
79
|
+
return _jsxs("fieldset", { className: "uhcp-optional-fields-v2", children: [_jsx("legend", { children: label }), _jsxs("select", { "aria-label": choose, value: value, onChange: event => onValueChange(event.currentTarget.value), children: [_jsx("option", { value: "", children: choose }), options.map(option => _jsx("option", { value: option.value, children: option.label }, option.value))] }), _jsx("button", { type: "button", disabled: !value, onClick: onAdd, children: add })] });
|
|
80
|
+
}
|
|
81
|
+
export function DocumentReferencesPropertyV2({ copy, attachments, onFiles, onRemove }) {
|
|
82
|
+
return _jsxs("fieldset", { className: "uhcp-clinical-property-v2 uhcp-document-references-property-v2", children: [_jsx("legend", { children: copy.documents }), _jsxs("label", { children: [copy.addDocuments, _jsx("input", { "aria-label": copy.addDocuments, type: "file", multiple: true, accept: "application/pdf,image/png,image/jpeg,.pdf,.png,.jpg,.jpeg", onChange: event => { const files = [...(event.currentTarget.files ?? [])]; event.currentTarget.value = ''; onFiles(files); } })] }), attachments.length ? _jsx("ul", { children: attachments.map(attachment => _jsxs("li", { children: [_jsx("span", { children: attachment.name }), _jsx("button", { type: "button", "aria-label": `${copy.removeDocument}: ${attachment.name}`, onClick: () => onRemove(attachment.id), children: "\u00D7" })] }, attachment.id)) }) : null] });
|
|
83
|
+
}
|
|
84
|
+
function splitDateTime(value, timeZone) {
|
|
85
|
+
if (!value)
|
|
86
|
+
return { date: '', time: '' };
|
|
87
|
+
if (/^\d{4}-\d{2}-\d{2}$/.test(value))
|
|
88
|
+
return { date: value, time: '' };
|
|
89
|
+
try {
|
|
90
|
+
return splitFhirDateTimeForInput(value, timeZone);
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
return { date: '', time: '' };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -6,7 +6,8 @@ import 'gdc-common-utils-ts/utils/medication-statement-entry-editor';
|
|
|
6
6
|
import 'gdc-common-utils-ts/utils/observation-entry-editor';
|
|
7
7
|
import 'gdc-common-utils-ts/utils/procedure-entry-editor';
|
|
8
8
|
import type { MultichannelOperationSchema } from 'sos-data-utils-ts/multichannel-operation-schemas';
|
|
9
|
-
import { type ClinicalArtifactAuthoringContext, type ClinicalArtifactEditorCopy, type ClinicalArtifactSchema, type ClinicalTerminologySearch, type ClinicalTerminologyCandidate, type ClinicalTerminologySourceSearch } from './ClinicalArtifactEditor.js';
|
|
9
|
+
import { type ClinicalArtifactAuthoringContext, type ClinicalArtifactDraft, type ClinicalArtifactEditorCopy, type ClinicalArtifactSchema, type ClinicalTerminologySearch, type ClinicalTerminologyCandidate, type ClinicalTerminologySourceSearch } from './ClinicalArtifactEditor.js';
|
|
10
|
+
import { type ImmunizationArtifactEditorCopyV2 } from './ImmunizationArtifactEditorV2.js';
|
|
10
11
|
export type ClinicalBundleDraftSchema = Readonly<{
|
|
11
12
|
schema: ClinicalArtifactSchema;
|
|
12
13
|
operationSchema: MultichannelOperationSchema;
|
|
@@ -51,6 +52,12 @@ export type ClinicalBundleDraftEditorProps = Readonly<{
|
|
|
51
52
|
/** Optional claims-first document Bundle loaded into the local draft; loading it never persists. */
|
|
52
53
|
initialBundle?: ClinicalBundleDraft;
|
|
53
54
|
onSubmitDraft: (bundle: ClinicalBundleDraft) => Promise<ClinicalBundleDraftSubmitOutcome>;
|
|
55
|
+
editorVersion?: 'v1' | 'v2';
|
|
56
|
+
editorV2Copy?: ImmunizationArtifactEditorCopyV2;
|
|
57
|
+
}>;
|
|
58
|
+
type StagedArtifact = Readonly<{
|
|
59
|
+
schema: ClinicalBundleDraftSchema;
|
|
60
|
+
draft: ClinicalArtifactDraft;
|
|
54
61
|
}>;
|
|
55
62
|
/**
|
|
56
63
|
* Shared local-first IPS authoring workspace.
|
|
@@ -59,5 +66,12 @@ export type ClinicalBundleDraftEditorProps = Readonly<{
|
|
|
59
66
|
* It owns no authorization or persistence: the host supplies subject and
|
|
60
67
|
* provenance and only `onSubmitDraft` may cross a persistence boundary.
|
|
61
68
|
*/
|
|
62
|
-
export declare function ClinicalBundleDraftEditor({ schemas, authoringContext, copy, locale, timeZone, taxonomyId, fieldLabel, resourceTypeLabel, searchTerminology, loadTerminologySources, initialBundle, onSubmitDraft, }: ClinicalBundleDraftEditorProps): import("react").JSX.Element;
|
|
69
|
+
export declare function ClinicalBundleDraftEditor({ schemas, authoringContext, copy, locale, timeZone, taxonomyId, fieldLabel, resourceTypeLabel, searchTerminology, loadTerminologySources, initialBundle, onSubmitDraft, editorVersion, editorV2Copy, }: ClinicalBundleDraftEditorProps): import("react").JSX.Element;
|
|
70
|
+
export declare function combineClinicalDrafts(artifacts: readonly StagedArtifact[], authoringContext: ClinicalArtifactAuthoringContext, documentTitle: string): ClinicalBundleDraft;
|
|
71
|
+
export type ClinicalBundleDraftEditorV2Props = Omit<ClinicalBundleDraftEditorProps, 'editorVersion' | 'editorV2Copy'> & Readonly<{
|
|
72
|
+
editorV2Copy: ImmunizationArtifactEditorCopyV2;
|
|
73
|
+
}>;
|
|
74
|
+
/** V2 opt-in wrapper; the original editor remains the default everywhere else. */
|
|
75
|
+
export declare function ClinicalBundleDraftEditorV2(props: ClinicalBundleDraftEditorV2Props): import("react").JSX.Element;
|
|
76
|
+
export {};
|
|
63
77
|
//# sourceMappingURL=ClinicalBundleDraftEditor.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ClinicalBundleDraftEditor.d.ts","sourceRoot":"","sources":["../src/ClinicalBundleDraftEditor.tsx"],"names":[],"mappings":"AAQA,OAAO,4DAA4D,CAAA;AACnE,OAAO,kDAAkD,CAAA;AACzD,OAAO,2DAA2D,CAAA;AAClE,OAAO,qDAAqD,CAAA;AAC5D,OAAO,6DAA6D,CAAA;AACpE,OAAO,oDAAoD,CAAA;AAC3D,OAAO,kDAAkD,CAAA;AACzD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,kDAAkD,CAAA;AACnG,OAAO,EAEL,KAAK,gCAAgC,
|
|
1
|
+
{"version":3,"file":"ClinicalBundleDraftEditor.d.ts","sourceRoot":"","sources":["../src/ClinicalBundleDraftEditor.tsx"],"names":[],"mappings":"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"}
|
|
@@ -15,6 +15,7 @@ import 'gdc-common-utils-ts/utils/observation-entry-editor';
|
|
|
15
15
|
import 'gdc-common-utils-ts/utils/procedure-entry-editor';
|
|
16
16
|
import { ClinicalArtifactEditor, } from './ClinicalArtifactEditor.js';
|
|
17
17
|
import { ClinicalActionButton } from './ClinicalActionButton.js';
|
|
18
|
+
import { ImmunizationArtifactEditorV2, } from './ImmunizationArtifactEditorV2.js';
|
|
18
19
|
/**
|
|
19
20
|
* Shared local-first IPS authoring workspace.
|
|
20
21
|
*
|
|
@@ -22,7 +23,7 @@ import { ClinicalActionButton } from './ClinicalActionButton.js';
|
|
|
22
23
|
* It owns no authorization or persistence: the host supplies subject and
|
|
23
24
|
* provenance and only `onSubmitDraft` may cross a persistence boundary.
|
|
24
25
|
*/
|
|
25
|
-
export function ClinicalBundleDraftEditor({ schemas, authoringContext, copy, locale = 'en', timeZone, taxonomyId, fieldLabel, resourceTypeLabel, searchTerminology, loadTerminologySources, initialBundle, onSubmitDraft, }) {
|
|
26
|
+
export function ClinicalBundleDraftEditor({ schemas, authoringContext, copy, locale = 'en', timeZone, taxonomyId, fieldLabel, resourceTypeLabel, searchTerminology, loadTerminologySources, initialBundle, onSubmitDraft, editorVersion = 'v1', editorV2Copy, }) {
|
|
26
27
|
const [artifacts, setArtifacts] = useState(() => importedArtifacts(initialBundle, schemas));
|
|
27
28
|
const [editor, setEditor] = useState();
|
|
28
29
|
const [notice, setNotice] = useState('');
|
|
@@ -49,7 +50,7 @@ export function ClinicalBundleDraftEditor({ schemas, authoringContext, copy, loc
|
|
|
49
50
|
setSubmitting(true);
|
|
50
51
|
setError('');
|
|
51
52
|
try {
|
|
52
|
-
const outcome = await onSubmitDraft(
|
|
53
|
+
const outcome = await onSubmitDraft(combineClinicalDrafts(artifacts, authoringContext, copy.title));
|
|
53
54
|
if (outcome.state === 'confirmed') {
|
|
54
55
|
setArtifacts([]);
|
|
55
56
|
setNotice(outcome.message || '');
|
|
@@ -79,7 +80,7 @@ export function ClinicalBundleDraftEditor({ schemas, authoringContext, copy, loc
|
|
|
79
80
|
const title = artifactTitle(artifact.draft);
|
|
80
81
|
return _jsxs("li", { children: [_jsxs("span", { children: [_jsx("strong", { children: title }), _jsx("small", { children: artifact.draft.resourceType })] }), _jsxs("span", { children: [_jsx(ClinicalActionButton, { kind: "edit", label: `${copy.edit} ${title}`, onClick: () => setEditor({ schema: artifact.schema, draft: artifact.draft }) }), _jsx(ClinicalActionButton, { kind: "delete", label: `${copy.remove} ${title}`, onClick: () => setArtifacts((current) => current.filter((candidate) => candidate.draft.id !== artifact.draft.id)) })] })] }, artifact.draft.id);
|
|
81
82
|
}) })] }, label);
|
|
82
|
-
}), artifacts.length === 0 && sections.length === 0 ? _jsx("p", { children: copy.empty }) : null, _jsx("footer", { children: _jsx("button", { type: "button", disabled: artifacts.length === 0 || submitting, onClick: () => void submitDraft(), children: submitting ? copy.submitting : copy.submit }) }), editor ? _jsx(ClinicalArtifactEditor, { request: editorRequest(editor), schema: editor.schema.schema, operationSchema: editor.schema.operationSchema, authoringContext: authoringContext, copy: copy.editor, locale: locale, timeZone: timeZone, taxonomyId: taxonomyId, fieldLabel: fieldLabel, resourceTypeLabel: resourceTypeLabel?.(editor.schema.schema.resourceType) || editor.schema.artifactLabel, searchTerminology: searchTerminology, loadTerminologySources: loadTerminologySources, saveArtifact: async (draft) => stageArtifact(draft), onCancel: () => setEditor(undefined), onReadback: () => setEditor(undefined) }) : null] });
|
|
83
|
+
}), artifacts.length === 0 && sections.length === 0 ? _jsx("p", { children: copy.empty }) : null, _jsx("footer", { children: _jsx("button", { type: "button", disabled: artifacts.length === 0 || submitting, onClick: () => void submitDraft(), children: submitting ? copy.submitting : copy.submit }) }), editor && editorVersion === 'v2' && editor.schema.schema.resourceType === 'Immunization' && editorV2Copy ? _jsx(ImmunizationArtifactEditorV2, { request: editorRequest(editor), authoringContext: authoringContext, copy: editorV2Copy, locale: locale, timeZone: timeZone, taxonomyId: taxonomyId, fieldLabel: fieldLabel, resourceTypeLabel: resourceTypeLabel?.(editor.schema.schema.resourceType) || editor.schema.artifactLabel, searchTerminology: searchTerminology, loadTerminologySources: loadTerminologySources, saveArtifact: async (draft) => stageArtifact(draft), onCancel: () => setEditor(undefined), onReadback: () => setEditor(undefined) }) : editor ? _jsx(ClinicalArtifactEditor, { request: editorRequest(editor), schema: editor.schema.schema, operationSchema: editor.schema.operationSchema, authoringContext: authoringContext, copy: copy.editor, locale: locale, timeZone: timeZone, taxonomyId: taxonomyId, fieldLabel: fieldLabel, resourceTypeLabel: resourceTypeLabel?.(editor.schema.schema.resourceType) || editor.schema.artifactLabel, searchTerminology: searchTerminology, loadTerminologySources: loadTerminologySources, saveArtifact: async (draft) => stageArtifact(draft), onCancel: () => setEditor(undefined), onReadback: () => setEditor(undefined) }) : null] });
|
|
83
84
|
}
|
|
84
85
|
function editorRequest(editor) {
|
|
85
86
|
return {
|
|
@@ -89,7 +90,7 @@ function editorRequest(editor) {
|
|
|
89
90
|
...(editor.draft ? { artifactId: editor.draft.id, initialClaims: editor.draft.claims, initialAttachments: editor.draft.attachments } : { initialClaims: editor.schema.schema.initialClaims }),
|
|
90
91
|
};
|
|
91
92
|
}
|
|
92
|
-
function
|
|
93
|
+
export function combineClinicalDrafts(artifacts, authoringContext, documentTitle) {
|
|
93
94
|
const editor = new BundleEditor()
|
|
94
95
|
.setBundleType(BundleTypes.document)
|
|
95
96
|
.setCompositionSubject(authoringContext.subjectReference)
|
|
@@ -110,7 +111,7 @@ function combineDrafts(artifacts, authoringContext, documentTitle) {
|
|
|
110
111
|
for (const { draft } of artifacts) {
|
|
111
112
|
const attachments = draft.attachments ?? [];
|
|
112
113
|
const claims = {
|
|
113
|
-
...operationClaims(draft),
|
|
114
|
+
...(draft.changesBundle ? operationClaims(draft) : draft.claims),
|
|
114
115
|
...(attachments.length ? { [`${draft.resourceType}.contained-reference-list`]: attachments.map(attachment => `DocumentReference/${attachment.id}`).join(',') } : {}),
|
|
115
116
|
};
|
|
116
117
|
const entry = editor.newEntryAs(draft.resourceType, draft.id);
|
|
@@ -135,9 +136,20 @@ function combineDrafts(artifacts, authoringContext, documentTitle) {
|
|
|
135
136
|
documentEntry.setClaim('DocumentReference.subject', authoringContext.subjectReference);
|
|
136
137
|
documentEntry.setClaim('DocumentReference.author', authoringContext.dataAuthorReference);
|
|
137
138
|
}
|
|
139
|
+
for (const related of draft.relatedEntries ?? []) {
|
|
140
|
+
const relatedEntry = editor.newEntryAs(related.resourceType, related.entryId);
|
|
141
|
+
for (const [claim, value] of Object.entries(related.claims))
|
|
142
|
+
relatedEntry.setClaim(claim, value);
|
|
143
|
+
if (related.sectionCode && relatedEntry instanceof ClinicalResourceEntryEditor)
|
|
144
|
+
relatedEntry.setSectionList([related.sectionCode]);
|
|
145
|
+
}
|
|
138
146
|
}
|
|
139
147
|
return editor.buildDocument();
|
|
140
148
|
}
|
|
149
|
+
/** V2 opt-in wrapper; the original editor remains the default everywhere else. */
|
|
150
|
+
export function ClinicalBundleDraftEditorV2(props) {
|
|
151
|
+
return _jsx(ClinicalBundleDraftEditor, { ...props, editorVersion: "v2" });
|
|
152
|
+
}
|
|
141
153
|
function operationClaims(draft) {
|
|
142
154
|
const entries = draft.changesBundle?.data ?? draft.changesBundle?.entry ?? [];
|
|
143
155
|
const first = entries[0];
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ClinicalArtifactEditorCopyV2, type ClinicalArtifactEditorV2Props } from './ClinicalArtifactEditorV2.js';
|
|
2
|
+
export declare const ImmunizationArtifactEditorV2Claim: Readonly<{
|
|
3
|
+
readonly NextDoseDate: "Immunization.next-dose-date";
|
|
4
|
+
}>;
|
|
5
|
+
export type ImmunizationArtifactEditorCopyV2 = ClinicalArtifactEditorCopyV2 & Readonly<{
|
|
6
|
+
doseSequenceInvalid: string;
|
|
7
|
+
seriesDosesInvalid: string;
|
|
8
|
+
}>;
|
|
9
|
+
export type ImmunizationArtifactEditorV2Props = Omit<ClinicalArtifactEditorV2Props, 'fields' | 'initialVisibleClaims' | 'initialClaims' | 'validate' | 'buildRelatedEntries' | 'copy'> & Readonly<{
|
|
10
|
+
copy: ImmunizationArtifactEditorCopyV2;
|
|
11
|
+
}>;
|
|
12
|
+
/** Demo-first Immunization specialization over the reusable progressive V2 shell. */
|
|
13
|
+
export declare function ImmunizationArtifactEditorV2({ copy, locale, ...props }: ImmunizationArtifactEditorV2Props): import("react").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=ImmunizationArtifactEditorV2.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ImmunizationArtifactEditorV2.d.ts","sourceRoot":"","sources":["../src/ImmunizationArtifactEditorV2.tsx"],"names":[],"mappings":"AAQA,OAAO,EAEL,KAAK,4BAA4B,EACjC,KAAK,6BAA6B,EAEnC,MAAM,+BAA+B,CAAA;AAEtC,eAAO,MAAM,iCAAiC;;EAEnC,CAAA;AAEX,MAAM,MAAM,gCAAgC,GAAG,4BAA4B,GAAG,QAAQ,CAAC;IACrF,mBAAmB,EAAE,MAAM,CAAA;IAC3B,kBAAkB,EAAE,MAAM,CAAA;CAC3B,CAAC,CAAA;AAEF,MAAM,MAAM,iCAAiC,GAAG,IAAI,CAAC,6BAA6B,EAAE,QAAQ,GAAG,sBAAsB,GAAG,eAAe,GAAG,UAAU,GAAG,qBAAqB,GAAG,MAAM,CAAC,GAAG,QAAQ,CAAC;IAChM,IAAI,EAAE,gCAAgC,CAAA;CACvC,CAAC,CAAA;AAEF,qFAAqF;AACrF,wBAAgB,4BAA4B,CAAC,EAAE,IAAI,EAAE,MAAa,EAAE,GAAG,KAAK,EAAE,EAAE,iCAAiC,+BAoChH"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { ImmunizationClaim, buildImmunizationRecommendationFlatEntry, clinicalArtifactCodedOptionsForClaim, validateImmunizationDoseSeries, } from 'fhir-data-utils-ts';
|
|
4
|
+
import { ClinicalArtifactEditorV2, } from './ClinicalArtifactEditorV2.js';
|
|
5
|
+
export const ImmunizationArtifactEditorV2Claim = Object.freeze({
|
|
6
|
+
NextDoseDate: 'Immunization.next-dose-date',
|
|
7
|
+
});
|
|
8
|
+
/** Demo-first Immunization specialization over the reusable progressive V2 shell. */
|
|
9
|
+
export function ImmunizationArtifactEditorV2({ copy, locale = 'en', ...props }) {
|
|
10
|
+
const fields = immunizationFields(locale);
|
|
11
|
+
return _jsx(ClinicalArtifactEditorV2, { ...props, locale: locale, copy: copy, fields: fields, initialVisibleClaims: [ImmunizationClaim.Status, ImmunizationClaim.VaccineCodeText, ImmunizationClaim.Date], initialClaims: {
|
|
12
|
+
[ImmunizationClaim.Status]: 'completed',
|
|
13
|
+
[ImmunizationClaim.Patient]: props.authoringContext.subjectReference,
|
|
14
|
+
[ImmunizationClaim.Performer]: props.authoringContext.dataAuthorReference,
|
|
15
|
+
}, validate: claims => {
|
|
16
|
+
try {
|
|
17
|
+
validateImmunizationDoseSeries(claims[ImmunizationClaim.DoseSequence], claims[ImmunizationClaim.SeriesDoses]);
|
|
18
|
+
}
|
|
19
|
+
catch (reason) {
|
|
20
|
+
if (reason instanceof Error && reason.message === 'immunization_dose_sequence_invalid')
|
|
21
|
+
throw new TypeError(copy.doseSequenceInvalid);
|
|
22
|
+
throw new TypeError(copy.seriesDosesInvalid);
|
|
23
|
+
}
|
|
24
|
+
}, buildRelatedEntries: (claims, draftId) => {
|
|
25
|
+
const nextDoseDate = claims[ImmunizationArtifactEditorV2Claim.NextDoseDate];
|
|
26
|
+
const vaccineToken = claims[ImmunizationClaim.VaccineCode];
|
|
27
|
+
if (!nextDoseDate || !vaccineToken)
|
|
28
|
+
return [];
|
|
29
|
+
const separator = vaccineToken.indexOf('|');
|
|
30
|
+
if (separator <= 0 || separator === vaccineToken.length - 1)
|
|
31
|
+
return [];
|
|
32
|
+
const recommendation = buildImmunizationRecommendationFlatEntry({
|
|
33
|
+
entryId: `${draftId}-recommendation`, immunizationEntryId: draftId,
|
|
34
|
+
subjectReference: props.authoringContext.subjectReference,
|
|
35
|
+
recommendationDate: props.authoringContext.createdAt,
|
|
36
|
+
nextDoseDate,
|
|
37
|
+
vaccineCode: { system: vaccineToken.slice(0, separator), code: vaccineToken.slice(separator + 1), display: claims[ImmunizationClaim.VaccineCodeDisplay], text: claims[ImmunizationClaim.VaccineCodeText] },
|
|
38
|
+
});
|
|
39
|
+
return [recommendation];
|
|
40
|
+
} });
|
|
41
|
+
}
|
|
42
|
+
function immunizationFields(locale) {
|
|
43
|
+
return Object.freeze([
|
|
44
|
+
{ claim: ImmunizationClaim.Status, kind: 'coded-select', required: true, options: clinicalArtifactCodedOptionsForClaim(ImmunizationClaim.Status, locale).map(option => ({ value: option.code, label: option.label })) },
|
|
45
|
+
{ claim: ImmunizationClaim.VaccineCodeText, textClaim: ImmunizationClaim.VaccineCodeText, codeClaim: ImmunizationClaim.VaccineCode, displayClaim: ImmunizationClaim.VaccineCodeDisplay, kind: 'coded-concept', required: true },
|
|
46
|
+
{ claim: ImmunizationClaim.Date, kind: 'date-time', required: true },
|
|
47
|
+
{ claim: ImmunizationClaim.TargetDiseaseText, textClaim: ImmunizationClaim.TargetDiseaseText, codeClaim: ImmunizationClaim.TargetDisease, displayClaim: ImmunizationClaim.TargetDiseaseDisplay, kind: 'coded-concept' },
|
|
48
|
+
{ claim: ImmunizationClaim.LotNumber, kind: 'text' },
|
|
49
|
+
{ claim: ImmunizationClaim.DoseSequence, kind: 'positive-integer' },
|
|
50
|
+
{ claim: ImmunizationClaim.SeriesDoses, kind: 'positive-integer' },
|
|
51
|
+
{ claim: ImmunizationClaim.Series, kind: 'text' },
|
|
52
|
+
{ claim: ImmunizationArtifactEditorV2Claim.NextDoseDate, kind: 'date', transient: true },
|
|
53
|
+
{ claim: ImmunizationClaim.Route, codeClaim: ImmunizationClaim.Route, displayClaim: ImmunizationClaim.RouteDisplay, kind: 'coded-concept' },
|
|
54
|
+
{ claim: ImmunizationClaim.Site, codeClaim: ImmunizationClaim.Site, displayClaim: ImmunizationClaim.SiteDisplay, kind: 'coded-concept' },
|
|
55
|
+
{ claim: ImmunizationClaim.Note, kind: 'text' },
|
|
56
|
+
{ claim: '__documents', kind: 'documents', transient: true },
|
|
57
|
+
]);
|
|
58
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -13,6 +13,9 @@ export * from './ClinicalDocumentEncounterExplorer.js';
|
|
|
13
13
|
export * from './AllClinicalSections.js';
|
|
14
14
|
export * from './ClinicalTimeline.js';
|
|
15
15
|
export * from './ClinicalArtifactEditor.js';
|
|
16
|
+
export * from './ClinicalArtifactPropertiesV2.js';
|
|
17
|
+
export * from './ClinicalArtifactEditorV2.js';
|
|
18
|
+
export * from './ImmunizationArtifactEditorV2.js';
|
|
16
19
|
export * from './ClinicalBundleDraftEditor.js';
|
|
17
20
|
export * from './ClinicalSpeechInput.js';
|
|
18
21
|
export * from './BrowserClinicalSpeechInput.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,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,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,uCAAuC,CAAA;AACrD,cAAc,uBAAuB,CAAA;AACrC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,8BAA8B,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,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,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,uCAAuC,CAAA;AACrD,cAAc,uBAAuB,CAAA;AACrC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,8BAA8B,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,9 @@ export * from './ClinicalDocumentEncounterExplorer.js';
|
|
|
13
13
|
export * from './AllClinicalSections.js';
|
|
14
14
|
export * from './ClinicalTimeline.js';
|
|
15
15
|
export * from './ClinicalArtifactEditor.js';
|
|
16
|
+
export * from './ClinicalArtifactPropertiesV2.js';
|
|
17
|
+
export * from './ClinicalArtifactEditorV2.js';
|
|
18
|
+
export * from './ImmunizationArtifactEditorV2.js';
|
|
16
19
|
export * from './ClinicalBundleDraftEditor.js';
|
|
17
20
|
export * from './ClinicalSpeechInput.js';
|
|
18
21
|
export * from './BrowserClinicalSpeechInput.js';
|
package/dist/styles.css
CHANGED
|
@@ -246,6 +246,33 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
|
|
|
246
246
|
.uhcp-terminology-source-picker label { align-items:center; display:flex; gap:.55rem; }
|
|
247
247
|
.uhcp-terminology-source-picker input { margin:0; width:auto; }
|
|
248
248
|
.uhcp-sr-only { clip:rect(0,0,0,0); clip-path:inset(50%); height:1px; overflow:hidden; position:absolute; white-space:nowrap; width:1px; }
|
|
249
|
+
.uhcp-clinical-editor-v2 { max-width:44rem; }
|
|
250
|
+
.uhcp-clinical-editor-v2 form { grid-template-columns:1fr; }
|
|
251
|
+
.uhcp-progressive-field-v2 { background:var(--uhcp-surface-muted); border:1px solid var(--uhcp-border); border-radius:1rem; display:grid; gap:.45rem; padding:.85rem; position:relative; }
|
|
252
|
+
.uhcp-progressive-field-v2>.uhcp-remove-field-v2 { align-items:center; background:#fff1f0; border:1px solid #fda29b; border-radius:50%; color:#b42318; cursor:pointer; display:flex; font-size:1.1rem; height:1.8rem; justify-content:center; position:absolute; right:.55rem; top:.55rem; width:1.8rem; z-index:1; }
|
|
253
|
+
.uhcp-clinical-property-v2 { display:grid; gap:.45rem; min-width:0; }
|
|
254
|
+
.uhcp-clinical-property-v2 input,.uhcp-clinical-property-v2 select { background:var(--uhcp-panel); border:1px solid var(--uhcp-border); border-radius:.7rem; color:inherit; font:inherit; min-width:0; padding:.7rem; width:100%; }
|
|
255
|
+
.uhcp-date-time-property-v2 { align-items:end; border:0; grid-template-columns:minmax(9rem,1fr) auto minmax(7rem,.65fr) auto; margin:0; padding:0; }
|
|
256
|
+
.uhcp-date-time-property-v2 legend { font-weight:800; margin-bottom:.35rem; }
|
|
257
|
+
.uhcp-date-time-property-v2 label { display:grid; gap:.3rem; }
|
|
258
|
+
.uhcp-date-time-property-v2 button,.uhcp-optional-fields-v2 button { background:var(--uhcp-panel); border:1px solid var(--uhcp-border); border-radius:.7rem; color:inherit; cursor:pointer; font:inherit; min-height:2.7rem; padding:.55rem .75rem; }
|
|
259
|
+
.uhcp-coded-concept-query-v2 { display:grid; gap:.4rem; grid-template-columns:minmax(0,1fr) auto auto; }
|
|
260
|
+
.uhcp-icon-button-v2,.uhcp-clear-code-v2 { align-items:center; background:var(--uhcp-panel); border:1px solid var(--uhcp-border); border-radius:50%; color:inherit; cursor:pointer; display:flex; height:2.75rem; justify-content:center; padding:.65rem; width:2.75rem; }
|
|
261
|
+
.uhcp-icon-button-v2 svg { fill:none; height:1.2rem; stroke:currentColor; stroke-linecap:round; stroke-width:2; width:1.2rem; }
|
|
262
|
+
.uhcp-clear-code-v2 { background:#fff1f0; border-color:#fda29b; color:#b42318; font-size:1.15rem; }
|
|
263
|
+
.uhcp-coding-sources-v2 { border:0; display:flex; flex-wrap:wrap; gap:.45rem .8rem; margin:0; padding:.2rem 0; }
|
|
264
|
+
.uhcp-coding-sources-v2 legend { color:var(--uhcp-muted); font-size:.8rem; width:100%; }
|
|
265
|
+
.uhcp-coding-sources-v2 label { align-items:center; display:flex; font-size:.85rem; gap:.3rem; }
|
|
266
|
+
.uhcp-coding-sources-v2 input { width:auto; }
|
|
267
|
+
.uhcp-selected-code-v2 { display:grid; gap:.6rem; grid-template-columns:1fr 1fr; }
|
|
268
|
+
.uhcp-selected-code-v2 input[readonly] { background:var(--uhcp-panel-muted); color:var(--uhcp-muted); }
|
|
269
|
+
.uhcp-optional-fields-v2 { align-items:end; border:1px dashed var(--uhcp-border); border-radius:1rem; display:grid; gap:.6rem; grid-template-columns:minmax(0,1fr) auto; margin:0; padding:.8rem; }
|
|
270
|
+
.uhcp-optional-fields-v2 legend { font-weight:800; padding:0 .35rem; }
|
|
271
|
+
.uhcp-optional-fields-v2 select { background:var(--uhcp-panel); border:1px solid var(--uhcp-border); border-radius:.7rem; color:inherit; font:inherit; padding:.7rem; }
|
|
272
|
+
.uhcp-document-references-property-v2 ul { display:grid; gap:.4rem; list-style:none; margin:.2rem 0 0; padding:0; }
|
|
273
|
+
.uhcp-document-references-property-v2 li { align-items:center; display:flex; justify-content:space-between; }
|
|
274
|
+
.uhcp-document-references-property-v2 li button { background:#fff1f0; border:1px solid #fda29b; border-radius:50%; color:#b42318; cursor:pointer; height:1.8rem; width:1.8rem; }
|
|
275
|
+
@media (max-width:620px) { .uhcp-date-time-property-v2,.uhcp-selected-code-v2 { grid-template-columns:minmax(0,1fr) auto; } .uhcp-date-time-property-v2 legend,.uhcp-selected-code-v2 label { grid-column:1/-1; } .uhcp-optional-fields-v2 { grid-template-columns:1fr; } }
|
|
249
276
|
@media (max-width:44rem) { .uhcp-clinical-editor form,.uhcp-emergency-contact-editor { grid-template-columns:1fr; } .uhcp-emergency-contact-directory>ul>li { align-items:stretch; flex-direction:column; } .uhcp-emergency-contact-directory nav { justify-content:flex-start; } }
|
|
250
277
|
|
|
251
278
|
.uhcp-transfer-console { background:#fff; color:#102754; display:grid; font-family:Inter,ui-sans-serif,system-ui,sans-serif; grid-template-columns:minmax(16rem,23rem) minmax(0,1fr); min-height:calc(100vh - 4.5rem); }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uhc-portal-components-react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.48",
|
|
4
4
|
"description": "Brand-neutral React portal shell, account preferences and protected-profile UI for UHC and VetChain portals.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"react-dom": ">=18.3.0"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"fhir-data-utils-ts": "0.6.
|
|
34
|
+
"fhir-data-utils-ts": "0.6.18",
|
|
35
35
|
"gdc-common-utils-ts": "2.9.30",
|
|
36
36
|
"sos-data-utils-ts": "0.6.3"
|
|
37
37
|
},
|