uhc-portal-components-react 0.1.47 → 0.1.49
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 +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 +20 -2
- package/dist/ClinicalBundleDraftEditor.d.ts.map +1 -1
- package/dist/ClinicalBundleDraftEditor.js +44 -16
- package/dist/ImmunizationArtifactEditorV2.d.ts +14 -0
- package/dist/ImmunizationArtifactEditorV2.d.ts.map +1 -0
- package/dist/ImmunizationArtifactEditorV2.js +58 -0
- package/dist/IpsBundleSummary.d.ts +3 -1
- package/dist/IpsBundleSummary.d.ts.map +1 -1
- package/dist/IpsBundleSummary.js +3 -2
- 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,27 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 0.1.49 - 2026-10-08
|
|
6
|
+
|
|
7
|
+
- Start new clinical documents without pre-rendered empty sections. Authors add
|
|
8
|
+
a section first, then add resources from that section; a resource-type choice
|
|
9
|
+
appears only when the selected section supports more than one resource.
|
|
10
|
+
- Expose each prepared local document Bundle to host-owned download or
|
|
11
|
+
credential actions without crossing the final submission boundary.
|
|
12
|
+
- Allow the reusable IPS summary to omit sections that contain no records while
|
|
13
|
+
preserving localized terminology rendering for populated resource cards.
|
|
14
|
+
|
|
15
|
+
## 0.1.48 - 2026-10-08
|
|
16
|
+
|
|
17
|
+
- Add an opt-in V2 clinical authoring shell without changing the existing V1
|
|
18
|
+
editor. Its reusable date/time, coded-concept, coded-select, positive-integer,
|
|
19
|
+
document-reference and progressive optional-field properties support
|
|
20
|
+
resource-specific editors.
|
|
21
|
+
- Add `ImmunizationArtifactEditorV2` with a minimal initial form, explicit
|
|
22
|
+
terminology search and selection, locked canonical coding, removable
|
|
23
|
+
optional flat claims, dose-series validation and automatic next-dose
|
|
24
|
+
ImmunizationRecommendation staging.
|
|
25
|
+
|
|
5
26
|
## 0.1.47 - 2026-10-08
|
|
6
27
|
|
|
7
28
|
- 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;
|
|
@@ -29,7 +30,9 @@ export type ClinicalBundleDraftEditorCopy = Readonly<{
|
|
|
29
30
|
add: string;
|
|
30
31
|
section?: string;
|
|
31
32
|
resourceType?: string;
|
|
33
|
+
addSection?: string;
|
|
32
34
|
addEntry?: string;
|
|
35
|
+
chooseResource?: string;
|
|
33
36
|
edit: string;
|
|
34
37
|
remove: string;
|
|
35
38
|
submit: string;
|
|
@@ -50,7 +53,15 @@ export type ClinicalBundleDraftEditorProps = Readonly<{
|
|
|
50
53
|
loadTerminologySources?: ClinicalTerminologySourceSearch;
|
|
51
54
|
/** Optional claims-first document Bundle loaded into the local draft; loading it never persists. */
|
|
52
55
|
initialBundle?: ClinicalBundleDraft;
|
|
56
|
+
/** Observes the local draft only; it does not persist or submit it. */
|
|
57
|
+
onDraftChange?: (bundle: ClinicalBundleDraft | undefined) => void;
|
|
53
58
|
onSubmitDraft: (bundle: ClinicalBundleDraft) => Promise<ClinicalBundleDraftSubmitOutcome>;
|
|
59
|
+
editorVersion?: 'v1' | 'v2';
|
|
60
|
+
editorV2Copy?: ImmunizationArtifactEditorCopyV2;
|
|
61
|
+
}>;
|
|
62
|
+
type StagedArtifact = Readonly<{
|
|
63
|
+
schema: ClinicalBundleDraftSchema;
|
|
64
|
+
draft: ClinicalArtifactDraft;
|
|
54
65
|
}>;
|
|
55
66
|
/**
|
|
56
67
|
* Shared local-first IPS authoring workspace.
|
|
@@ -59,5 +70,12 @@ export type ClinicalBundleDraftEditorProps = Readonly<{
|
|
|
59
70
|
* It owns no authorization or persistence: the host supplies subject and
|
|
60
71
|
* provenance and only `onSubmitDraft` may cross a persistence boundary.
|
|
61
72
|
*/
|
|
62
|
-
export declare function ClinicalBundleDraftEditor({ schemas, authoringContext, copy, locale, timeZone, taxonomyId, fieldLabel, resourceTypeLabel, searchTerminology, loadTerminologySources, initialBundle, onSubmitDraft, }: ClinicalBundleDraftEditorProps): import("react").JSX.Element;
|
|
73
|
+
export declare function ClinicalBundleDraftEditor({ schemas, authoringContext, copy, locale, timeZone, taxonomyId, fieldLabel, resourceTypeLabel, searchTerminology, loadTerminologySources, initialBundle, onDraftChange, onSubmitDraft, editorVersion, editorV2Copy, }: ClinicalBundleDraftEditorProps): import("react").JSX.Element;
|
|
74
|
+
export declare function combineClinicalDrafts(artifacts: readonly StagedArtifact[], authoringContext: ClinicalArtifactAuthoringContext, documentTitle: string): ClinicalBundleDraft;
|
|
75
|
+
export type ClinicalBundleDraftEditorV2Props = Omit<ClinicalBundleDraftEditorProps, 'editorVersion' | 'editorV2Copy'> & Readonly<{
|
|
76
|
+
editorV2Copy: ImmunizationArtifactEditorCopyV2;
|
|
77
|
+
}>;
|
|
78
|
+
/** V2 opt-in wrapper; the original editor remains the default everywhere else. */
|
|
79
|
+
export declare function ClinicalBundleDraftEditorV2(props: ClinicalBundleDraftEditorV2Props): import("react").JSX.Element;
|
|
80
|
+
export {};
|
|
63
81
|
//# 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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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useMemo, useState } from 'react';
|
|
3
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
4
4
|
import { BundleEditor } from 'gdc-common-utils-ts/utils/bundle-editor-core';
|
|
5
5
|
import { BundleTypes } from 'gdc-common-utils-ts/models/bundle-editor-types';
|
|
6
6
|
import { HealthcareDocumentTypes } from 'gdc-common-utils-ts/constants/healthcare';
|
|
@@ -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,17 +23,20 @@ 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, onDraftChange, onSubmitDraft, editorVersion = 'v1', editorV2Copy, }) {
|
|
26
27
|
const [artifacts, setArtifacts] = useState(() => importedArtifacts(initialBundle, schemas));
|
|
27
28
|
const [editor, setEditor] = useState();
|
|
29
|
+
const [resourceChooser, setResourceChooser] = useState();
|
|
28
30
|
const [notice, setNotice] = useState('');
|
|
29
31
|
const [error, setError] = useState('');
|
|
30
32
|
const [submitting, setSubmitting] = useState(false);
|
|
31
33
|
const sections = useMemo(() => groupSchemas(schemas), [schemas]);
|
|
34
|
+
const [activeSections, setActiveSections] = useState(() => [...new Set(importedArtifacts(initialBundle, schemas).map(artifact => artifact.schema.sectionLabel))]);
|
|
32
35
|
const [selectedSection, setSelectedSection] = useState(() => groupSchemas(schemas)[0]?.label ?? '');
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
const availableSections = sections.filter(section => !activeSections.includes(section.label));
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
onDraftChange?.(artifacts.length ? combineClinicalDrafts(artifacts, authoringContext, copy.title) : undefined);
|
|
39
|
+
}, [artifacts, authoringContext, copy.title, onDraftChange]);
|
|
36
40
|
function stageArtifact(draft) {
|
|
37
41
|
if (!editor)
|
|
38
42
|
throw new TypeError('clinical_bundle_draft_editor_schema_required');
|
|
@@ -49,9 +53,10 @@ export function ClinicalBundleDraftEditor({ schemas, authoringContext, copy, loc
|
|
|
49
53
|
setSubmitting(true);
|
|
50
54
|
setError('');
|
|
51
55
|
try {
|
|
52
|
-
const outcome = await onSubmitDraft(
|
|
56
|
+
const outcome = await onSubmitDraft(combineClinicalDrafts(artifacts, authoringContext, copy.title));
|
|
53
57
|
if (outcome.state === 'confirmed') {
|
|
54
58
|
setArtifacts([]);
|
|
59
|
+
setActiveSections([]);
|
|
55
60
|
setNotice(outcome.message || '');
|
|
56
61
|
}
|
|
57
62
|
else if (outcome.state === 'rejected') {
|
|
@@ -68,18 +73,30 @@ export function ClinicalBundleDraftEditor({ schemas, authoringContext, copy, loc
|
|
|
68
73
|
setSubmitting(false);
|
|
69
74
|
}
|
|
70
75
|
}
|
|
71
|
-
return _jsxs("section", { className: "uhcp-clinical-bundle-draft", "data-clinical-bundle-draft": true, children: [_jsxs("header", { children: [_jsx("h2", { children: copy.title }), _jsx("p", { children: copy.description })] }), notice ? _jsx("p", { role: "status", children: notice }) : null, error ? _jsx("p", { role: "alert", className: "uhcp-clinical-editor-error", children: error }) : null,
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
return _jsxs("section", { className: "uhcp-clinical-bundle-draft", "data-clinical-bundle-draft": true, children: [_jsxs("header", { children: [_jsx("h2", { children: copy.title }), _jsx("p", { children: copy.description })] }), notice ? _jsx("p", { role: "status", children: notice }) : null, error ? _jsx("p", { role: "alert", className: "uhcp-clinical-editor-error", children: error }) : null, availableSections.length ? _jsxs("div", { className: "uhcp-clinical-bundle-draft-create", children: [_jsxs("label", { children: [copy.section || 'Section', _jsx("select", { value: availableSections.some(section => section.label === selectedSection) ? selectedSection : availableSections[0]?.label, onChange: (event) => setSelectedSection(event.currentTarget.value), children: availableSections.map(section => _jsx("option", { value: section.label, children: section.label }, section.label)) })] }), _jsxs("button", { type: "button", onClick: () => {
|
|
77
|
+
const label = availableSections.some(section => section.label === selectedSection) ? selectedSection : availableSections[0]?.label;
|
|
78
|
+
if (!label)
|
|
79
|
+
return;
|
|
80
|
+
setActiveSections(current => [...current, label]);
|
|
81
|
+
const nextAvailable = availableSections.find(section => section.label !== label);
|
|
82
|
+
setSelectedSection(nextAvailable?.label ?? '');
|
|
83
|
+
}, children: ["+ ", copy.addSection || copy.add] })] }) : null, sections.filter(section => activeSections.includes(section.label)).map(({ label, schemas: sectionSchemas }) => {
|
|
77
84
|
const sectionArtifacts = artifacts.filter((artifact) => artifact.schema.sectionLabel === label);
|
|
78
|
-
return _jsxs("details", { open: true, children: [_jsxs("summary", { children: [label, " (", sectionArtifacts.length, ")"] }),
|
|
85
|
+
return _jsxs("details", { open: true, children: [_jsxs("summary", { children: [label, " (", sectionArtifacts.length, ")"] }), _jsxs("button", { type: "button", onClick: () => {
|
|
86
|
+
if (sectionSchemas.length === 1)
|
|
87
|
+
setEditor({ schema: sectionSchemas[0] });
|
|
88
|
+
else
|
|
89
|
+
setResourceChooser({ sectionLabel: label, schemaKey: schemaKey(sectionSchemas[0]) });
|
|
90
|
+
}, children: ["+ ", copy.addEntry || copy.add] }), resourceChooser?.sectionLabel === label ? _jsxs("div", { className: "uhcp-clinical-bundle-resource-choice", children: [_jsxs("label", { children: [copy.resourceType || 'Resource type', _jsx("select", { value: resourceChooser.schemaKey, onChange: event => setResourceChooser({ sectionLabel: label, schemaKey: event.currentTarget.value }), children: sectionSchemas.map(candidate => _jsx("option", { value: schemaKey(candidate), children: resourceTypeLabel?.(candidate.schema.resourceType) || candidate.artifactLabel }, schemaKey(candidate))) })] }), _jsx("button", { type: "button", onClick: () => {
|
|
91
|
+
const selected = sectionSchemas.find(candidate => schemaKey(candidate) === resourceChooser.schemaKey);
|
|
92
|
+
if (selected)
|
|
93
|
+
setEditor({ schema: selected });
|
|
94
|
+
setResourceChooser(undefined);
|
|
95
|
+
}, children: copy.chooseResource || copy.add })] }) : null, sectionArtifacts.length === 0 ? _jsx("p", { children: copy.empty }) : _jsx("ul", { children: sectionArtifacts.map((artifact) => {
|
|
79
96
|
const title = artifactTitle(artifact.draft);
|
|
80
97
|
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
98
|
}) })] }, label);
|
|
82
|
-
}),
|
|
99
|
+
}), activeSections.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
100
|
}
|
|
84
101
|
function editorRequest(editor) {
|
|
85
102
|
return {
|
|
@@ -89,7 +106,7 @@ function editorRequest(editor) {
|
|
|
89
106
|
...(editor.draft ? { artifactId: editor.draft.id, initialClaims: editor.draft.claims, initialAttachments: editor.draft.attachments } : { initialClaims: editor.schema.schema.initialClaims }),
|
|
90
107
|
};
|
|
91
108
|
}
|
|
92
|
-
function
|
|
109
|
+
export function combineClinicalDrafts(artifacts, authoringContext, documentTitle) {
|
|
93
110
|
const editor = new BundleEditor()
|
|
94
111
|
.setBundleType(BundleTypes.document)
|
|
95
112
|
.setCompositionSubject(authoringContext.subjectReference)
|
|
@@ -110,7 +127,7 @@ function combineDrafts(artifacts, authoringContext, documentTitle) {
|
|
|
110
127
|
for (const { draft } of artifacts) {
|
|
111
128
|
const attachments = draft.attachments ?? [];
|
|
112
129
|
const claims = {
|
|
113
|
-
...operationClaims(draft),
|
|
130
|
+
...(draft.changesBundle ? operationClaims(draft) : draft.claims),
|
|
114
131
|
...(attachments.length ? { [`${draft.resourceType}.contained-reference-list`]: attachments.map(attachment => `DocumentReference/${attachment.id}`).join(',') } : {}),
|
|
115
132
|
};
|
|
116
133
|
const entry = editor.newEntryAs(draft.resourceType, draft.id);
|
|
@@ -135,9 +152,20 @@ function combineDrafts(artifacts, authoringContext, documentTitle) {
|
|
|
135
152
|
documentEntry.setClaim('DocumentReference.subject', authoringContext.subjectReference);
|
|
136
153
|
documentEntry.setClaim('DocumentReference.author', authoringContext.dataAuthorReference);
|
|
137
154
|
}
|
|
155
|
+
for (const related of draft.relatedEntries ?? []) {
|
|
156
|
+
const relatedEntry = editor.newEntryAs(related.resourceType, related.entryId);
|
|
157
|
+
for (const [claim, value] of Object.entries(related.claims))
|
|
158
|
+
relatedEntry.setClaim(claim, value);
|
|
159
|
+
if (related.sectionCode && relatedEntry instanceof ClinicalResourceEntryEditor)
|
|
160
|
+
relatedEntry.setSectionList([related.sectionCode]);
|
|
161
|
+
}
|
|
138
162
|
}
|
|
139
163
|
return editor.buildDocument();
|
|
140
164
|
}
|
|
165
|
+
/** V2 opt-in wrapper; the original editor remains the default everywhere else. */
|
|
166
|
+
export function ClinicalBundleDraftEditorV2(props) {
|
|
167
|
+
return _jsx(ClinicalBundleDraftEditor, { ...props, editorVersion: "v2" });
|
|
168
|
+
}
|
|
141
169
|
function operationClaims(draft) {
|
|
142
170
|
const entries = draft.changesBundle?.data ?? draft.changesBundle?.entry ?? [];
|
|
143
171
|
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
|
+
}
|
|
@@ -8,6 +8,8 @@ export type IpsBundleSummaryProps = Readonly<{
|
|
|
8
8
|
translateCode?: (input: ClinicalTerminologyTranslationInput) => string | undefined;
|
|
9
9
|
emptyLabel: string;
|
|
10
10
|
noSectionsLabel?: string;
|
|
11
|
+
/** Omits Composition sections that resolve to no resources. */
|
|
12
|
+
hideEmptySections?: boolean;
|
|
11
13
|
sectionTitle?: (section: ClinicalSectionView) => string;
|
|
12
14
|
resourceTypeLabel?: (resourceType: string) => string;
|
|
13
15
|
sectionActions?: (section: ClinicalSectionView) => ReactNode;
|
|
@@ -28,5 +30,5 @@ export type IpsBundleSummaryProps = Readonly<{
|
|
|
28
30
|
* native FHIR fields or canonical `resource.meta.claims` provide card content.
|
|
29
31
|
* This component performs no ingestion, persistence or GW call.
|
|
30
32
|
*/
|
|
31
|
-
export declare function IpsBundleSummary({ bundle, locale, timeZone, translateCode, emptyLabel, noSectionsLabel, sectionTitle, resourceTypeLabel, sectionActions, resourceActions, timeline, }: IpsBundleSummaryProps): import("react").JSX.Element;
|
|
33
|
+
export declare function IpsBundleSummary({ bundle, locale, timeZone, translateCode, emptyLabel, noSectionsLabel, hideEmptySections, sectionTitle, resourceTypeLabel, sectionActions, resourceActions, timeline, }: IpsBundleSummaryProps): import("react").JSX.Element;
|
|
32
34
|
//# sourceMappingURL=IpsBundleSummary.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IpsBundleSummary.d.ts","sourceRoot":"","sources":["../src/IpsBundleSummary.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,EAEL,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,EACxB,KAAK,mCAAmC,EACzC,MAAM,kDAAkD,CAAA;AAEzD,OAAO,EAAgD,KAAK,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAEjH,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,MAAM,EAAE,0BAA0B,CAAA;IAClC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,mCAAmC,KAAK,MAAM,GAAG,SAAS,CAAA;IAClF,UAAU,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,MAAM,CAAA;IACvD,iBAAiB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAA;IACpD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,SAAS,CAAA;IAC5D,yFAAyF;IACzF,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,KAAK,SAAS,CAAA;IACjH,QAAQ,CAAC,EAAE,QAAQ,CAAC;QAClB,MAAM,EAAE,sBAAsB,CAAA;QAC9B,iBAAiB,EAAE,MAAM,CAAA;QACzB,sBAAsB,EAAE,MAAM,CAAA;KAC/B,CAAC,CAAA;CACH,CAAC,CAAA;AAEF;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,MAAM,EACN,QAAQ,EACR,aAAa,EACb,UAAU,EACV,eAA4B,EAC5B,YAAyC,EACzC,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,QAAQ,GACT,EAAE,qBAAqB,+
|
|
1
|
+
{"version":3,"file":"IpsBundleSummary.d.ts","sourceRoot":"","sources":["../src/IpsBundleSummary.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AACtC,OAAO,EAEL,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,EACxB,KAAK,mCAAmC,EACzC,MAAM,kDAAkD,CAAA;AAEzD,OAAO,EAAgD,KAAK,sBAAsB,EAAE,MAAM,uBAAuB,CAAA;AAEjH,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,MAAM,EAAE,0BAA0B,CAAA;IAClC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,mCAAmC,KAAK,MAAM,GAAG,SAAS,CAAA;IAClF,UAAU,EAAE,MAAM,CAAA;IAClB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,+DAA+D;IAC/D,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,YAAY,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,MAAM,CAAA;IACvD,iBAAiB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAA;IACpD,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,KAAK,SAAS,CAAA;IAC5D,yFAAyF;IACzF,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,mBAAmB,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,KAAK,SAAS,CAAA;IACjH,QAAQ,CAAC,EAAE,QAAQ,CAAC;QAClB,MAAM,EAAE,sBAAsB,CAAA;QAC9B,iBAAiB,EAAE,MAAM,CAAA;QACzB,sBAAsB,EAAE,MAAM,CAAA;KAC/B,CAAC,CAAA;CACH,CAAC,CAAA;AAEF;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,MAAM,EACN,QAAQ,EACR,aAAa,EACb,UAAU,EACV,eAA4B,EAC5B,iBAAyB,EACzB,YAAyC,EACzC,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,QAAQ,GACT,EAAE,qBAAqB,+BAsEvB"}
|
package/dist/IpsBundleSummary.js
CHANGED
|
@@ -11,8 +11,9 @@ import { ClinicalTimeline } from './ClinicalTimeline.js';
|
|
|
11
11
|
* native FHIR fields or canonical `resource.meta.claims` provide card content.
|
|
12
12
|
* This component performs no ingestion, persistence or GW call.
|
|
13
13
|
*/
|
|
14
|
-
export function IpsBundleSummary({ bundle, locale, timeZone, translateCode, emptyLabel, noSectionsLabel = emptyLabel, sectionTitle = (section) => section.title, resourceTypeLabel, sectionActions, resourceActions, timeline, }) {
|
|
15
|
-
const sections = toClinicalSectionViews(bundle, { locale, translateCode })
|
|
14
|
+
export function IpsBundleSummary({ bundle, locale, timeZone, translateCode, emptyLabel, noSectionsLabel = emptyLabel, hideEmptySections = false, sectionTitle = (section) => section.title, resourceTypeLabel, sectionActions, resourceActions, timeline, }) {
|
|
15
|
+
const sections = toClinicalSectionViews(bundle, { locale, translateCode })
|
|
16
|
+
.filter(section => !hideEmptySections || section.resources.length > 0);
|
|
16
17
|
const nativeResources = new Map((bundle.entry ?? bundle.data ?? []).flatMap((entry) => entry.fullUrl && entry.resource ? [[entry.fullUrl, entry.resource]] : []));
|
|
17
18
|
if (sections.length === 0) {
|
|
18
19
|
return _jsx("p", { className: "uhcp-clinical-empty", "data-ips-summary-empty": true, children: noSectionsLabel });
|
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.49",
|
|
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
|
},
|