uhc-portal-components-react 0.1.3 → 0.1.5

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,19 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.1.5 - 2026-07-29
4
+
5
+ - Allow advanced hosts to reuse the shared clinical card body while retaining
6
+ their own expandable section heading, filters and editors.
7
+
8
+ ## 0.1.4 - 2026-07-29
9
+
10
+ - Add `IpsBundleSummary`, which accepts a complete IPS document Bundle and
11
+ renders every Composition section and its Common Utils card projections.
12
+ - Test the official 16-section IPS fixture, every declared IPS resource type
13
+ and locale/terminology propagation.
14
+ - State explicitly that browser components render in-memory data and never call
15
+ backend ingestion operations.
16
+
3
17
  ## 0.1.3
4
18
 
5
19
  - Add the brand-neutral `ClinicalSectionSummary` renderer for resolved IPS
package/README.md CHANGED
@@ -48,7 +48,11 @@ The package deliberately exposes modules instead of a cloned application:
48
48
  - `PortalAccessChooser`: real-page navigation for professional access paths.
49
49
  - `ProfileProtectionGate`: fail-closed PIN unlock presentation.
50
50
  - `ClinicalSectionSummary`: brand-neutral rendering of already-resolved IPS
51
- cards for personal and professional portals.
51
+ cards for personal and professional portals. Advanced viewers can set
52
+ `showHeader={false}` when they retain their own expandable heading.
53
+ - `IpsBundleSummary`: receives one in-memory IPS document Bundle, obtains all
54
+ `Composition.section` entries through Common Utils and renders every
55
+ section's cards. It performs no ingestion or GW call.
52
56
 
53
57
  Clinical label semantics stay in `gdc-common-utils-ts` / the SDK reader. Hosts
54
58
  pass human titles to `ClinicalSectionSummary`: local `CodeableConcept.text`
@@ -56,6 +60,19 @@ when the UI matches the resource language, English `Coding.display` for
56
60
  English, or a terminology translation keyed by `system|code` for another
57
61
  locale. The terminology token is never a visible or editable title.
58
62
 
63
+ ```tsx
64
+ <IpsBundleSummary
65
+ bundle={bundleInMemory}
66
+ locale={currentLocale}
67
+ translateCode={terminology.translate}
68
+ emptyLabel={t('emptySection')}
69
+ />
70
+ ```
71
+
72
+ The browser may render an optimistic in-memory Bundle while its authenticated
73
+ BFF persists the command. Only backend code calls
74
+ `ingestCommunicationAndUpdateIndex(...)`; the component never does.
75
+
59
76
  UHC Personal and VetChain Personal must compose the same personal route
60
77
  modules. UHC Professional and VetChain Professional must compose the same
61
78
  professional route modules. A brand adapter may change only tokens, logo,
@@ -12,6 +12,8 @@ export type ClinicalSectionSummaryProps = Readonly<{
12
12
  emptyLabel: string;
13
13
  resourceTypeLabel?: (resourceType: string) => string;
14
14
  actions?: ReactNode;
15
+ /** Hide only the heading when a host already owns the expandable section header. */
16
+ showHeader?: boolean;
15
17
  }>;
16
18
  /**
17
19
  * Brand-neutral renderer for one already-resolved IPS section.
@@ -21,5 +23,5 @@ export type ClinicalSectionSummaryProps = Readonly<{
21
23
  * terminology identity/translation key and must never be supplied as a
22
24
  * replacement for manually authored text.
23
25
  */
24
- export declare function ClinicalSectionSummary({ code, title, resources, emptyLabel, resourceTypeLabel, actions, }: ClinicalSectionSummaryProps): import("react").JSX.Element;
26
+ export declare function ClinicalSectionSummary({ code, title, resources, emptyLabel, resourceTypeLabel, actions, showHeader, }: ClinicalSectionSummaryProps): import("react").JSX.Element;
25
27
  //# sourceMappingURL=ClinicalSectionSummary.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ClinicalSectionSummary.d.ts","sourceRoot":"","sources":["../src/ClinicalSectionSummary.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAC,CAAA;AAEF,MAAM,MAAM,2BAA2B,GAAG,QAAQ,CAAC;IACjD,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,SAAS,mBAAmB,EAAE,CAAA;IACzC,UAAU,EAAE,MAAM,CAAA;IAClB,iBAAiB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAA;IACpD,OAAO,CAAC,EAAE,SAAS,CAAA;CACpB,CAAC,CAAA;AAEF;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,IAAI,EACJ,KAAK,EACL,SAAS,EACT,UAAU,EACV,iBAAkD,EAClD,OAAO,GACR,EAAE,2BAA2B,+BAsB7B"}
1
+ {"version":3,"file":"ClinicalSectionSummary.d.ts","sourceRoot":"","sources":["../src/ClinicalSectionSummary.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAC,CAAA;AAEF,MAAM,MAAM,2BAA2B,GAAG,QAAQ,CAAC;IACjD,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,SAAS,mBAAmB,EAAE,CAAA;IACzC,UAAU,EAAE,MAAM,CAAA;IAClB,iBAAiB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,MAAM,CAAA;IACpD,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,oFAAoF;IACpF,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB,CAAC,CAAA;AAEF;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,IAAI,EACJ,KAAK,EACL,SAAS,EACT,UAAU,EACV,iBAAkD,EAClD,OAAO,EACP,UAAiB,GAClB,EAAE,2BAA2B,+BA4B7B"}
@@ -7,8 +7,8 @@ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
7
7
  * terminology identity/translation key and must never be supplied as a
8
8
  * replacement for manually authored text.
9
9
  */
10
- export function ClinicalSectionSummary({ code, title, resources, emptyLabel, resourceTypeLabel = (resourceType) => resourceType, actions, }) {
11
- return (_jsxs("section", { className: "uhcp-clinical-section", "data-ips-section": code, "aria-labelledby": `uhcp-section-${code}`, children: [_jsxs("header", { children: [_jsxs("h3", { id: `uhcp-section-${code}`, children: [title, " ", _jsxs("span", { children: ["(", resources.length, ")"] })] }), actions] }), resources.length === 0
10
+ export function ClinicalSectionSummary({ code, title, resources, emptyLabel, resourceTypeLabel = (resourceType) => resourceType, actions, showHeader = true, }) {
11
+ return (_jsxs("section", { className: "uhcp-clinical-section", "data-ips-section": code, ...(showHeader ? { 'aria-labelledby': `uhcp-section-${code}` } : { 'aria-label': title }), children: [showHeader && (_jsxs("header", { children: [_jsxs("h3", { id: `uhcp-section-${code}`, children: [title, " ", _jsxs("span", { children: ["(", resources.length, ")"] })] }), actions] })), resources.length === 0
12
12
  ? _jsx("p", { className: "uhcp-clinical-empty", children: emptyLabel })
13
13
  : (_jsx("div", { className: "uhcp-clinical-grid", children: resources.map((resource) => (_jsxs("article", { className: "uhcp-clinical-card", "data-resource-type": resource.resourceType, children: [_jsx("p", { className: "uhcp-clinical-title", dir: "auto", children: _jsx("bdi", { children: resource.title }) }), _jsx("p", { className: "uhcp-clinical-type", children: resourceTypeLabel(resource.resourceType) }), resource.date && _jsx("p", { className: "uhcp-clinical-date", children: resource.date })] }, resource.key))) }))] }));
14
14
  }
@@ -0,0 +1,23 @@
1
+ import type { ReactNode } from 'react';
2
+ import { type ClinicalResourceBundleLike, type ClinicalSectionView, type ClinicalTerminologyTranslationInput } from 'gdc-common-utils-ts/utils/clinical-resource-view';
3
+ export type IpsBundleSummaryProps = Readonly<{
4
+ bundle: ClinicalResourceBundleLike;
5
+ locale?: string;
6
+ translateCode?: (input: ClinicalTerminologyTranslationInput) => string | undefined;
7
+ emptyLabel: string;
8
+ noSectionsLabel?: string;
9
+ sectionTitle?: (section: ClinicalSectionView) => string;
10
+ resourceTypeLabel?: (resourceType: string) => string;
11
+ sectionActions?: (section: ClinicalSectionView) => ReactNode;
12
+ }>;
13
+ /**
14
+ * Renders every section declared by an IPS Composition and the cards referenced
15
+ * by each section.
16
+ *
17
+ * The shared clinical reader owns Bundle traversal, section placement and card
18
+ * projection. `Composition.section.entry` is authoritative for placement;
19
+ * native FHIR fields or canonical `resource.meta.claims` provide card content.
20
+ * This component performs no ingestion, persistence or GW call.
21
+ */
22
+ export declare function IpsBundleSummary({ bundle, locale, translateCode, emptyLabel, noSectionsLabel, sectionTitle, resourceTypeLabel, sectionActions, }: IpsBundleSummaryProps): import("react").JSX.Element;
23
+ //# sourceMappingURL=IpsBundleSummary.d.ts.map
@@ -0,0 +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;AAGzD,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,MAAM,EAAE,0BAA0B,CAAA;IAClC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,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;CAC7D,CAAC,CAAA;AAEF;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,MAAM,EACN,aAAa,EACb,UAAU,EACV,eAA4B,EAC5B,YAAyC,EACzC,iBAAiB,EACjB,cAAc,GACf,EAAE,qBAAqB,+BA2BvB"}
@@ -0,0 +1,24 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { toClinicalSectionViews, } from 'gdc-common-utils-ts/utils/clinical-resource-view';
3
+ import { ClinicalSectionSummary } from './ClinicalSectionSummary.js';
4
+ /**
5
+ * Renders every section declared by an IPS Composition and the cards referenced
6
+ * by each section.
7
+ *
8
+ * The shared clinical reader owns Bundle traversal, section placement and card
9
+ * projection. `Composition.section.entry` is authoritative for placement;
10
+ * native FHIR fields or canonical `resource.meta.claims` provide card content.
11
+ * This component performs no ingestion, persistence or GW call.
12
+ */
13
+ export function IpsBundleSummary({ bundle, locale, translateCode, emptyLabel, noSectionsLabel = emptyLabel, sectionTitle = (section) => section.title, resourceTypeLabel, sectionActions, }) {
14
+ const sections = toClinicalSectionViews(bundle, { locale, translateCode });
15
+ if (sections.length === 0) {
16
+ return _jsx("p", { className: "uhcp-clinical-empty", "data-ips-summary-empty": true, children: noSectionsLabel });
17
+ }
18
+ return (_jsx("div", { className: "uhcp-clinical-summary", "data-ips-summary": true, children: sections.map((section, sectionIndex) => (_jsx(ClinicalSectionSummary, { code: section.code ?? '', title: sectionTitle(section), resources: section.resources.map((resource, resourceIndex) => ({
19
+ key: resource.fullUrl ?? `${resource.resourceType}:${resourceIndex}:${resource.title}`,
20
+ title: resource.title,
21
+ resourceType: resource.resourceType,
22
+ date: resource.date,
23
+ })), emptyLabel: emptyLabel, resourceTypeLabel: resourceTypeLabel, actions: sectionActions?.(section) }, section.code ?? `${section.title}:${sectionIndex}`))) }));
24
+ }
package/dist/index.d.ts CHANGED
@@ -6,4 +6,5 @@ export * from './PortalShell.js';
6
6
  export * from './PortalEntry.js';
7
7
  export * from './ProfileProtectionGate.js';
8
8
  export * from './ClinicalSectionSummary.js';
9
+ export * from './IpsBundleSummary.js';
9
10
  //# sourceMappingURL=index.d.ts.map
@@ -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,6BAA6B,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,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA"}
package/dist/index.js CHANGED
@@ -6,3 +6,4 @@ export * from './PortalShell.js';
6
6
  export * from './PortalEntry.js';
7
7
  export * from './ProfileProtectionGate.js';
8
8
  export * from './ClinicalSectionSummary.js';
9
+ export * from './IpsBundleSummary.js';
package/dist/styles.css CHANGED
@@ -171,6 +171,11 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
171
171
  color: var(--uhcp-text);
172
172
  padding: 1.25rem;
173
173
  }
174
+
175
+ .uhcp-clinical-summary {
176
+ display: grid;
177
+ gap: 1rem;
178
+ }
174
179
  .uhcp-clinical-section > header { align-items: center; display: flex; gap: 1rem; justify-content: space-between; }
175
180
  .uhcp-clinical-section h3 { font-size: 1.125rem; margin: 0; }
176
181
  .uhcp-clinical-section h3 span { color: var(--uhcp-muted); }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uhc-portal-components-react",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
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",
@@ -26,6 +26,9 @@
26
26
  "react": ">=18.3.0",
27
27
  "react-dom": ">=18.3.0"
28
28
  },
29
+ "dependencies": {
30
+ "gdc-common-utils-ts": "^2.3.10"
31
+ },
29
32
  "devDependencies": {
30
33
  "@types/react": "19.2.17",
31
34
  "@types/react-dom": "19.2.3",