uhc-portal-components-react 0.1.25 → 0.1.27

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 CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.27
4
+
5
+ - Add generic `AllClinicalSections<Person|Animal>` organization with stack or
6
+ tab presentation, nested collapsible groups and host-controlled exclusions.
7
+ - Keep family health history, care-team members, emergency contacts,
8
+ Encounters and IPS summary as independent navigation concepts while the host
9
+ supplies authorized clinical content.
10
+
11
+ ## 0.1.26
12
+
13
+ - Add a brand-neutral clinical document and Encounter explorer for an
14
+ authorized care journey.
15
+ - Navigate chronologically between supplied Encounters while preserving
16
+ `Encounter.partOf` as hierarchy and rendering only document Bundles whose
17
+ leading Composition references the selected Encounter.
18
+ - Reuse the section viewer for IPS and non-IPS documents; the Composition title
19
+ and type provide the document label.
20
+
3
21
  ## 0.1.25
4
22
 
5
23
  - Render every labelled quantity component of a composite FHIR `Observation` in the shared IPS card, including systolic and diastolic blood-pressure values and units.
package/README.md CHANGED
@@ -53,6 +53,16 @@ The package deliberately exposes modules instead of a cloned application:
53
53
  - `IpsBundleSummary`: receives one in-memory IPS document Bundle, obtains all
54
54
  `Composition.section` entries through Common Utils and renders every
55
55
  section's cards. It performs no ingestion or GW call.
56
+ - `ClinicalDocumentEncounterExplorer`: receives host-authorized Encounter
57
+ resources and Composition-first document Bundles, provides backward/forward
58
+ journey navigation and renders either IPS or non-IPS sections with the same
59
+ viewer. It never treats an Encounter as the clinical subject or performs
60
+ authorization, fetching or persistence in the browser.
61
+ - `AllClinicalSections<Person|Animal>`: lets each portal compose the same
62
+ authorized section views as a stack or tabs, nest collapsible subsections and
63
+ exclude inapplicable areas. Family history, care-team members and emergency
64
+ contacts remain independent; the organizer never follows another subject's
65
+ card or documents automatically.
56
66
  - `ClinicalArtifactEditor`: renders the same schema-driven clinical form for
57
67
  human and animal subjects. The host supplies its UHC/Vet schema,
58
68
  terminology-search adapter and authorized persistence callback. Selecting a
@@ -0,0 +1,41 @@
1
+ import { type ReactNode } from 'react';
2
+ export declare const ClinicalSectionNavigationIds: Readonly<{
3
+ readonly IpsSummary: "ips-summary";
4
+ readonly Encounters: "encounters";
5
+ readonly HealthStatusAssessments: "health-status-assessments";
6
+ readonly HealthInsuranceInformation: "health-insurance-information";
7
+ readonly GoalsAndPreferences: "goals-and-preferences";
8
+ readonly FamilyHealthHistory: "family-health-history";
9
+ readonly ClinicalTests: "clinical-tests";
10
+ readonly ClinicalNotes: "clinical-notes";
11
+ readonly CareTeamMembers: "care-team-members";
12
+ readonly EmergencyContacts: "emergency-contacts";
13
+ }>;
14
+ export type ClinicalSectionNavigationId = typeof ClinicalSectionNavigationIds[keyof typeof ClinicalSectionNavigationIds];
15
+ export type ClinicalSubjectKind = 'person' | 'animal';
16
+ export type AllClinicalSectionDefinition<SubjectKind extends ClinicalSubjectKind> = Readonly<{
17
+ id: ClinicalSectionNavigationId | (string & {});
18
+ title: string;
19
+ description?: string;
20
+ content?: ReactNode;
21
+ collapsible?: boolean;
22
+ defaultOpen?: boolean;
23
+ children?: readonly AllClinicalSectionDefinition<SubjectKind>[];
24
+ }>;
25
+ export type AllClinicalSectionsProps<SubjectKind extends ClinicalSubjectKind> = Readonly<{
26
+ subjectKind: SubjectKind;
27
+ title: string;
28
+ sections: readonly AllClinicalSectionDefinition<SubjectKind>[];
29
+ excludedSectionIds?: readonly string[];
30
+ presentation?: 'sections' | 'tabs';
31
+ }>;
32
+ /**
33
+ * Organizes host-provided clinical views without redefining their FHIR model.
34
+ *
35
+ * The host decides which sections apply to a person or animal, supplies only
36
+ * authorized content and may exclude sections. Family history, emergency
37
+ * contacts and care-team members remain independent domains; this component
38
+ * never follows another subject's card or document links automatically.
39
+ */
40
+ export declare function AllClinicalSections<SubjectKind extends ClinicalSubjectKind>({ subjectKind, title, sections, excludedSectionIds, presentation, }: AllClinicalSectionsProps<SubjectKind>): import("react").JSX.Element;
41
+ //# sourceMappingURL=AllClinicalSections.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AllClinicalSections.d.ts","sourceRoot":"","sources":["../src/AllClinicalSections.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAEhD,eAAO,MAAM,4BAA4B;;;;;;;;;;;EAW9B,CAAA;AAEX,MAAM,MAAM,2BAA2B,GAAG,OAAO,4BAA4B,CAAC,MAAM,OAAO,4BAA4B,CAAC,CAAA;AACxH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAErD,MAAM,MAAM,4BAA4B,CAAC,WAAW,SAAS,mBAAmB,IAAI,QAAQ,CAAC;IAC3F,EAAE,EAAE,2BAA2B,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;IAC/C,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,QAAQ,CAAC,EAAE,SAAS,4BAA4B,CAAC,WAAW,CAAC,EAAE,CAAA;CAChE,CAAC,CAAA;AAEF,MAAM,MAAM,wBAAwB,CAAC,WAAW,SAAS,mBAAmB,IAAI,QAAQ,CAAC;IACvF,WAAW,EAAE,WAAW,CAAA;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,SAAS,4BAA4B,CAAC,WAAW,CAAC,EAAE,CAAA;IAC9D,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACtC,YAAY,CAAC,EAAE,UAAU,GAAG,MAAM,CAAA;CACnC,CAAC,CAAA;AAEF;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,SAAS,mBAAmB,EAAE,EAC3E,WAAW,EACX,KAAK,EACL,QAAQ,EACR,kBAAuB,EACvB,YAAyB,GAC1B,EAAE,wBAAwB,CAAC,WAAW,CAAC,+BAqCvC"}
@@ -0,0 +1,35 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ export const ClinicalSectionNavigationIds = Object.freeze({
4
+ IpsSummary: 'ips-summary',
5
+ Encounters: 'encounters',
6
+ HealthStatusAssessments: 'health-status-assessments',
7
+ HealthInsuranceInformation: 'health-insurance-information',
8
+ GoalsAndPreferences: 'goals-and-preferences',
9
+ FamilyHealthHistory: 'family-health-history',
10
+ ClinicalTests: 'clinical-tests',
11
+ ClinicalNotes: 'clinical-notes',
12
+ CareTeamMembers: 'care-team-members',
13
+ EmergencyContacts: 'emergency-contacts',
14
+ });
15
+ /**
16
+ * Organizes host-provided clinical views without redefining their FHIR model.
17
+ *
18
+ * The host decides which sections apply to a person or animal, supplies only
19
+ * authorized content and may exclude sections. Family history, emergency
20
+ * contacts and care-team members remain independent domains; this component
21
+ * never follows another subject's card or document links automatically.
22
+ */
23
+ export function AllClinicalSections({ subjectKind, title, sections, excludedSectionIds = [], presentation = 'sections', }) {
24
+ const visibleSections = sections.filter(({ id }) => !excludedSectionIds.includes(id));
25
+ const [selectedId, setSelectedId] = useState(visibleSections[0]?.id ?? '');
26
+ const selectedSection = visibleSections.find(({ id }) => id === selectedId) ?? visibleSections[0];
27
+ return (_jsxs("section", { className: "uhcp-all-clinical-sections", "data-subject-kind": subjectKind, children: [_jsx("h2", { children: title }), presentation === 'tabs' ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "uhcp-all-clinical-tabs", role: "tablist", "aria-label": title, children: visibleSections.map((section) => (_jsx("button", { type: "button", role: "tab", "aria-selected": section.id === selectedSection?.id, "aria-controls": `uhcp-all-section-${section.id}`, onClick: () => setSelectedId(section.id), children: section.title }, section.id))) }), selectedSection ? (_jsx("div", { id: `uhcp-all-section-${selectedSection.id}`, role: "tabpanel", children: _jsx(ClinicalSection, { definition: selectedSection, excludedSectionIds: excludedSectionIds }) })) : null] })) : (_jsx("div", { className: "uhcp-all-clinical-stack", children: visibleSections.map((section) => (_jsx(ClinicalSection, { definition: section, excludedSectionIds: excludedSectionIds }, section.id))) }))] }));
28
+ }
29
+ function ClinicalSection({ definition, excludedSectionIds, }) {
30
+ const body = (_jsxs("div", { className: "uhcp-all-clinical-content", children: [definition.description ? _jsx("p", { children: definition.description }) : null, definition.content, definition.children?.filter(({ id }) => !excludedSectionIds.includes(id)).map((child) => (_jsx(ClinicalSection, { definition: child, excludedSectionIds: excludedSectionIds }, child.id)))] }));
31
+ if (definition.collapsible !== false) {
32
+ return (_jsxs("details", { className: "uhcp-all-clinical-section", open: definition.defaultOpen, children: [_jsx("summary", { children: definition.title }), body] }));
33
+ }
34
+ return (_jsxs("section", { className: "uhcp-all-clinical-section", "aria-labelledby": `uhcp-all-section-title-${definition.id}`, children: [_jsx("h3", { id: `uhcp-all-section-title-${definition.id}`, children: definition.title }), body] }));
35
+ }
@@ -0,0 +1,62 @@
1
+ import type { ClinicalResourceBundleLike } from 'gdc-common-utils-ts/utils/clinical-resource-view';
2
+ export type EncounterJourneyResource = Readonly<{
3
+ resourceType: 'Encounter';
4
+ id?: string;
5
+ status?: string;
6
+ class?: Readonly<{
7
+ display?: string;
8
+ code?: string;
9
+ }>;
10
+ serviceType?: readonly Readonly<{
11
+ concept?: Readonly<{
12
+ text?: string;
13
+ }>;
14
+ }>[];
15
+ location?: readonly Readonly<{
16
+ location?: Readonly<{
17
+ display?: string;
18
+ reference?: string;
19
+ }>;
20
+ }>[];
21
+ actualPeriod?: Readonly<{
22
+ start?: string;
23
+ end?: string;
24
+ }>;
25
+ period?: Readonly<{
26
+ start?: string;
27
+ end?: string;
28
+ }>;
29
+ partOf?: Readonly<{
30
+ reference?: string;
31
+ }>;
32
+ }>;
33
+ export type ClinicalDocumentBundle = ClinicalResourceBundleLike & Readonly<{
34
+ id?: string;
35
+ }>;
36
+ export type ClinicalDocumentEncounterExplorerLabels = Readonly<{
37
+ journeyTitle: string;
38
+ documentsTitle: string;
39
+ previousEncounter: string;
40
+ nextEncounter: string;
41
+ noDocuments: string;
42
+ emptySection: string;
43
+ noSections: string;
44
+ documentTypeLabel: string;
45
+ currentEncounter: string;
46
+ }>;
47
+ export type ClinicalDocumentEncounterExplorerProps = Readonly<{
48
+ encounters: readonly EncounterJourneyResource[];
49
+ documents: readonly ClinicalDocumentBundle[];
50
+ labels: ClinicalDocumentEncounterExplorerLabels;
51
+ locale?: string;
52
+ }>;
53
+ /**
54
+ * Explores one host-authorized Encounter journey and its FHIR document Bundles.
55
+ *
56
+ * A document Bundle is Composition-first. The Encounter is care context, not
57
+ * the clinical subject, and `Encounter.partOf` remains a hierarchy rather than
58
+ * a substitute for chronological navigation. Fetching, authorization and
59
+ * persistence remain responsibilities of the hosting portal.
60
+ */
61
+ export declare function ClinicalDocumentEncounterExplorer({ encounters, documents, labels, locale, }: ClinicalDocumentEncounterExplorerProps): import("react").JSX.Element;
62
+ //# sourceMappingURL=ClinicalDocumentEncounterExplorer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ClinicalDocumentEncounterExplorer.d.ts","sourceRoot":"","sources":["../src/ClinicalDocumentEncounterExplorer.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kDAAkD,CAAA;AAGlG,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,YAAY,EAAE,WAAW,CAAA;IACzB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,QAAQ,CAAC;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACrD,WAAW,CAAC,EAAE,SAAS,QAAQ,CAAC;QAAE,OAAO,CAAC,EAAE,QAAQ,CAAC;YAAE,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC,EAAE,CAAA;IAC5E,QAAQ,CAAC,EAAE,SAAS,QAAQ,CAAC;QAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC;YAAE,OAAO,CAAC,EAAE,MAAM,CAAC;YAAC,SAAS,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,CAAC,EAAE,CAAA;IACjG,YAAY,CAAC,EAAE,QAAQ,CAAC;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACzD,MAAM,CAAC,EAAE,QAAQ,CAAC;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACnD,MAAM,CAAC,EAAE,QAAQ,CAAC;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAC1C,CAAC,CAAA;AAEF,MAAM,MAAM,sBAAsB,GAAG,0BAA0B,GAAG,QAAQ,CAAC;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAE3F,MAAM,MAAM,uCAAuC,GAAG,QAAQ,CAAC;IAC7D,YAAY,EAAE,MAAM,CAAA;IACpB,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,MAAM,CAAA;IACzB,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,EAAE,MAAM,CAAA;IAClB,iBAAiB,EAAE,MAAM,CAAA;IACzB,gBAAgB,EAAE,MAAM,CAAA;CACzB,CAAC,CAAA;AAEF,MAAM,MAAM,sCAAsC,GAAG,QAAQ,CAAC;IAC5D,UAAU,EAAE,SAAS,wBAAwB,EAAE,CAAA;IAC/C,SAAS,EAAE,SAAS,sBAAsB,EAAE,CAAA;IAC5C,MAAM,EAAE,uCAAuC,CAAA;IAC/C,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAC,CAAA;AASF;;;;;;;GAOG;AACH,wBAAgB,iCAAiC,CAAC,EAChD,UAAU,EACV,SAAS,EACT,MAAM,EACN,MAAM,GACP,EAAE,sCAAsC,+BAgHxC"}
@@ -0,0 +1,70 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useMemo, useState } from 'react';
3
+ import { IpsBundleSummary } from './IpsBundleSummary.js';
4
+ /**
5
+ * Explores one host-authorized Encounter journey and its FHIR document Bundles.
6
+ *
7
+ * A document Bundle is Composition-first. The Encounter is care context, not
8
+ * the clinical subject, and `Encounter.partOf` remains a hierarchy rather than
9
+ * a substitute for chronological navigation. Fetching, authorization and
10
+ * persistence remain responsibilities of the hosting portal.
11
+ */
12
+ export function ClinicalDocumentEncounterExplorer({ encounters, documents, labels, locale, }) {
13
+ const orderedEncounters = useMemo(() => [...encounters].sort((left, right) => encounterStart(left).localeCompare(encounterStart(right))), [encounters]);
14
+ const documentHeaders = useMemo(() => documents.map((document) => ({ document, header: compositionHeader(document) })), [documents]);
15
+ const firstDocumentEncounterIndex = orderedEncounters.findIndex((encounter) => documentHeaders.some(({ header }) => referencesEncounter(header.encounterReference, encounter)));
16
+ const [selectedEncounterId, setSelectedEncounterId] = useState(orderedEncounters[Math.max(firstDocumentEncounterIndex, 0)]?.id ?? '');
17
+ const selectedIndex = Math.max(orderedEncounters.findIndex((encounter) => encounter.id === selectedEncounterId), 0);
18
+ const selectedEncounter = orderedEncounters[selectedIndex];
19
+ const encounterDocuments = selectedEncounter
20
+ ? documentHeaders.filter(({ header }) => referencesEncounter(header.encounterReference, selectedEncounter))
21
+ : [];
22
+ const [selectedDocumentId, setSelectedDocumentId] = useState('');
23
+ const selectedDocument = encounterDocuments.find(({ document }) => document.id === selectedDocumentId)
24
+ ?? encounterDocuments[0];
25
+ function selectEncounter(encounter) {
26
+ setSelectedEncounterId(encounter.id ?? '');
27
+ setSelectedDocumentId('');
28
+ }
29
+ return (_jsxs("section", { className: "uhcp-document-explorer", "data-clinical-document-explorer": true, children: [_jsxs("header", { className: "uhcp-document-explorer-heading", children: [_jsxs("div", { children: [_jsx("p", { children: labels.currentEncounter }), _jsx("h2", { children: selectedEncounter ? encounterName(selectedEncounter) : labels.journeyTitle })] }), _jsxs("nav", { "aria-label": labels.journeyTitle, children: [_jsx("button", { type: "button", "aria-label": labels.previousEncounter, disabled: selectedIndex <= 0, onClick: () => selectEncounter(orderedEncounters[selectedIndex - 1]), children: "\u2190" }), _jsx("button", { type: "button", "aria-label": labels.nextEncounter, disabled: selectedIndex >= orderedEncounters.length - 1, onClick: () => selectEncounter(orderedEncounters[selectedIndex + 1]), children: "\u2192" })] })] }), _jsx("div", { className: "uhcp-encounter-rail", role: "list", "aria-label": labels.journeyTitle, children: orderedEncounters.map((encounter) => (_jsx("div", { role: "listitem", children: _jsxs("button", { type: "button", "aria-label": encounterName(encounter), "aria-current": encounter.id === selectedEncounter?.id ? 'step' : undefined, onClick: () => selectEncounter(encounter), children: [_jsx("strong", { children: encounterName(encounter) }), _jsx("span", { children: encounter.location?.[0]?.location?.display ?? encounter.class?.display }), _jsx("time", { dateTime: encounterStart(encounter), children: formatPeriod(encounter, locale) }), _jsx("small", { "data-status": encounter.status, children: encounter.status })] }) }, encounter.id))) }), _jsxs("section", { className: "uhcp-document-panel", children: [_jsx("h2", { children: labels.documentsTitle }), encounterDocuments.length === 0 ? _jsx("p", { children: labels.noDocuments }) : (_jsxs(_Fragment, { children: [encounterDocuments.length > 1 ? (_jsx("div", { className: "uhcp-document-tabs", role: "list", children: encounterDocuments.map(({ document, header }) => (_jsx("span", { role: "listitem", children: _jsx("button", { type: "button", "aria-pressed": document === selectedDocument?.document, onClick: () => setSelectedDocumentId(document.id ?? ''), children: header.title }) }, document.id ?? header.title))) })) : null, selectedDocument ? (_jsxs("article", { "data-clinical-document": true, children: [_jsxs("header", { children: [_jsxs("div", { children: [_jsxs("p", { children: [labels.documentTypeLabel, ": ", selectedDocument.header.type] }), _jsx("h3", { children: selectedDocument.header.title })] }), selectedDocument.header.date ? _jsx("time", { dateTime: selectedDocument.header.date, children: formatInstant(selectedDocument.header.date, locale) }) : null] }), _jsx(IpsBundleSummary, { bundle: selectedDocument.document, locale: locale, emptyLabel: labels.emptySection, noSectionsLabel: labels.noSections })] })) : null] }))] })] }));
30
+ }
31
+ function encounterName(encounter) {
32
+ return encounter.serviceType?.find(({ concept }) => concept?.text)?.concept?.text
33
+ ?? encounter.class?.display
34
+ ?? encounter.id
35
+ ?? 'Encounter';
36
+ }
37
+ function encounterStart(encounter) {
38
+ return encounter.actualPeriod?.start ?? encounter.period?.start ?? '';
39
+ }
40
+ function formatPeriod(encounter, locale) {
41
+ const period = encounter.actualPeriod ?? encounter.period;
42
+ if (!period?.start)
43
+ return '';
44
+ const start = formatInstant(period.start, locale);
45
+ return period.end ? `${start} – ${formatInstant(period.end, locale)}` : start;
46
+ }
47
+ function formatInstant(value, locale) {
48
+ const date = new Date(value);
49
+ return Number.isNaN(date.valueOf()) ? value : new Intl.DateTimeFormat(locale, {
50
+ dateStyle: 'medium',
51
+ timeStyle: 'short',
52
+ timeZone: 'UTC',
53
+ }).format(date);
54
+ }
55
+ function compositionHeader(document) {
56
+ const composition = (document.entry ?? document.data ?? [])
57
+ .map((entry) => entry.resource)
58
+ .find((resource) => resource?.resourceType === 'Composition');
59
+ return {
60
+ title: composition?.title ?? document.id ?? 'Clinical document',
61
+ type: composition?.type?.text
62
+ ?? composition?.type?.coding?.find(({ display }) => display)?.display
63
+ ?? 'Clinical document',
64
+ encounterReference: composition?.encounter?.reference,
65
+ date: composition?.date,
66
+ };
67
+ }
68
+ function referencesEncounter(reference, encounter) {
69
+ return Boolean(encounter.id && (reference === `Encounter/${encounter.id}` || reference === encounter.id));
70
+ }
package/dist/index.d.ts CHANGED
@@ -8,6 +8,8 @@ export * from './ProfileProtectionGate.js';
8
8
  export * from './PortalLoadingSkeleton.js';
9
9
  export * from './ClinicalSectionSummary.js';
10
10
  export * from './IpsBundleSummary.js';
11
+ export * from './ClinicalDocumentEncounterExplorer.js';
12
+ export * from './AllClinicalSections.js';
11
13
  export * from './ClinicalArtifactEditor.js';
12
14
  export * from './VitalSignArtifactEditor.js';
13
15
  export * from './InvitationAcceptancePanel.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,yBAAyB,CAAA;AACvC,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA;AACrC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,0CAA0C,CAAA;AACxD,cAAc,kCAAkC,CAAA;AAChD,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,oCAAoC,CAAA;AAClD,cAAc,sCAAsC,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,kBAAkB,CAAA;AAChC,cAAc,yBAAyB,CAAA;AACvC,cAAc,mBAAmB,CAAA;AACjC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA;AACrC,cAAc,wCAAwC,CAAA;AACtD,cAAc,0BAA0B,CAAA;AACxC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,0CAA0C,CAAA;AACxD,cAAc,kCAAkC,CAAA;AAChD,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,oCAAoC,CAAA;AAClD,cAAc,sCAAsC,CAAA"}
package/dist/index.js CHANGED
@@ -8,6 +8,8 @@ export * from './ProfileProtectionGate.js';
8
8
  export * from './PortalLoadingSkeleton.js';
9
9
  export * from './ClinicalSectionSummary.js';
10
10
  export * from './IpsBundleSummary.js';
11
+ export * from './ClinicalDocumentEncounterExplorer.js';
12
+ export * from './AllClinicalSections.js';
11
13
  export * from './ClinicalArtifactEditor.js';
12
14
  export * from './VitalSignArtifactEditor.js';
13
15
  export * from './InvitationAcceptancePanel.js';
package/dist/styles.css CHANGED
@@ -183,6 +183,38 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
183
183
  .uhcp-clinical-editor footer button,.uhcp-terminology-results button { border:1px solid var(--uhcp-border); border-radius:.7rem; cursor:pointer; font:inherit; padding:.7rem 1rem; }
184
184
  .uhcp-clinical-editor footer button[type=submit] { background:linear-gradient(135deg,var(--uhcp-action-start),var(--uhcp-action-end)); color:#fff; font-weight:800; }
185
185
  .uhcp-clinical-editor-error { color:#b42318; font-weight:700; }
186
+ .uhcp-document-explorer { background:var(--uhcp-surface); color:var(--uhcp-text); display:grid; gap:1rem; padding:1rem; }
187
+ .uhcp-document-explorer button { color:inherit; cursor:pointer; font:inherit; }
188
+ .uhcp-document-explorer button:disabled { cursor:not-allowed; opacity:.45; }
189
+ .uhcp-document-explorer-heading { align-items:center; display:flex; gap:1rem; justify-content:space-between; }
190
+ .uhcp-document-explorer-heading p,.uhcp-document-panel>article>header p { color:var(--uhcp-muted); font-size:.8rem; font-weight:750; margin:0 0 .25rem; text-transform:uppercase; }
191
+ .uhcp-document-explorer-heading h2,.uhcp-document-panel h2,.uhcp-document-panel h3 { margin:0; }
192
+ .uhcp-document-explorer-heading nav { display:flex; gap:.45rem; }
193
+ .uhcp-document-explorer-heading button { background:var(--uhcp-panel); border:1px solid var(--uhcp-border); border-radius:50%; height:2.5rem; width:2.5rem; }
194
+ .uhcp-encounter-rail { display:flex; gap:.75rem; overflow-x:auto; padding:.15rem .05rem .65rem; scroll-snap-type:x proximity; }
195
+ .uhcp-encounter-rail>div { flex:0 0 min(17rem,76vw); scroll-snap-align:start; }
196
+ .uhcp-encounter-rail>div>button { background:var(--uhcp-panel); border:1px solid var(--uhcp-border); border-radius:1rem; display:grid; gap:.45rem; min-height:9.5rem; padding:1rem; text-align:start; width:100%; }
197
+ .uhcp-encounter-rail>div>button[aria-current=step] { border-color:var(--uhcp-turquoise); box-shadow:0 0 0 2px color-mix(in srgb,var(--uhcp-turquoise) 24%,transparent); }
198
+ .uhcp-encounter-rail span,.uhcp-encounter-rail time { color:var(--uhcp-muted); font-size:.78rem; }
199
+ .uhcp-encounter-rail small { background:var(--uhcp-surface-muted); border-radius:999px; justify-self:start; padding:.25rem .55rem; }
200
+ .uhcp-document-panel { background:var(--uhcp-panel); border:1px solid var(--uhcp-border); border-radius:1.5rem; padding:1.25rem; }
201
+ .uhcp-document-panel>p { color:var(--uhcp-muted); }
202
+ .uhcp-document-tabs { display:flex; gap:.5rem; overflow:auto; padding:.75rem 0; }
203
+ .uhcp-document-tabs button { background:var(--uhcp-surface-muted); border:1px solid var(--uhcp-border); border-radius:999px; padding:.55rem .8rem; white-space:nowrap; }
204
+ .uhcp-document-tabs button[aria-pressed=true] { background:var(--uhcp-turquoise); color:#fff; }
205
+ .uhcp-document-panel>article>header { align-items:start; border-bottom:1px solid var(--uhcp-border); display:flex; gap:1rem; justify-content:space-between; margin:1rem 0; padding-bottom:1rem; }
206
+ .uhcp-document-panel>article>header time { color:var(--uhcp-muted); font-size:.8rem; white-space:nowrap; }
207
+ .uhcp-all-clinical-sections { color:var(--uhcp-text); display:grid; gap:1rem; }
208
+ .uhcp-all-clinical-sections>h2 { margin:0; }
209
+ .uhcp-all-clinical-stack { display:grid; gap:.75rem; }
210
+ .uhcp-all-clinical-section { background:var(--uhcp-panel); border:1px solid var(--uhcp-border); border-radius:1rem; padding:1rem; }
211
+ .uhcp-all-clinical-section>summary { cursor:pointer; font-size:1.05rem; font-weight:800; }
212
+ .uhcp-all-clinical-section>h3 { margin:0; }
213
+ .uhcp-all-clinical-content { display:grid; gap:.75rem; padding-top:.85rem; }
214
+ .uhcp-all-clinical-content>p { color:var(--uhcp-muted); margin:0; }
215
+ .uhcp-all-clinical-tabs { display:flex; gap:.5rem; overflow:auto; }
216
+ .uhcp-all-clinical-tabs button { background:var(--uhcp-panel); border:1px solid var(--uhcp-border); border-radius:999px; color:inherit; cursor:pointer; font:inherit; padding:.6rem .85rem; white-space:nowrap; }
217
+ .uhcp-all-clinical-tabs button[aria-selected=true] { background:var(--uhcp-turquoise); color:#fff; }
186
218
  .uhcp-terminology-results ul { display:grid; gap:.35rem; list-style:none; margin:.25rem 0 0; padding:0; }
187
219
  .uhcp-terminology-results button { background:var(--uhcp-surface-muted); color:inherit; display:grid; text-align:start; width:100%; }
188
220
  .uhcp-terminology-results small { color:var(--uhcp-muted); display:block; font-weight:400; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uhc-portal-components-react",
3
- "version": "0.1.25",
3
+ "version": "0.1.27",
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.7",
34
+ "fhir-data-utils-ts": "0.6.8",
35
35
  "gdc-common-utils-ts": "^2.3.12"
36
36
  },
37
37
  "devDependencies": {