uhc-portal-components-react 0.2.19 → 0.2.20

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
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.2.20 - 2026-10-21
6
+
7
+ - Add one accessible Personal subject workspace shared by UHC, PetChain and
8
+ SOSChain consumers, with five canonical screens and governed product-module
9
+ extensions.
10
+ - Add explicit human and animal clinical-summary profiles. The animal profile
11
+ reuses the same clinical screen while excluding Advance Directives for now.
12
+ - Keep the existing capability-driven professional subject workspace as the
13
+ shared UHC/VetChain composition; SOSChain layers emergency, Encounter and
14
+ communication capabilities on shared components rather than cloning them.
5
15
  - Add one neutral notification composer screen for subject-addressed care
6
16
  transitions and public-dataset alerts, with safe Markdown preview and host-
7
17
  uploaded image/PDF attachment references.
package/README.md CHANGED
@@ -9,6 +9,8 @@ Publishable, brand-neutral React components shared by:
9
9
  - UHC Professional
10
10
  - VetChain Personal
11
11
  - VetChain Professional
12
+ - SOSChain Personal
13
+ - SOSChain Professional
12
14
 
13
15
  The package owns visual shell behavior only. Authentication, protected-profile
14
16
  storage, PIN verification and actor authorization remain in the host portal
@@ -74,9 +76,16 @@ The package deliberately exposes modules instead of a cloned application:
74
76
  authorization, fetching or persistence in the browser.
75
77
  - `AllClinicalSections<Person|Animal>`: lets each portal compose the same
76
78
  authorized section views as a stack or tabs, nest collapsible subsections and
77
- exclude inapplicable areas. Family history, care-team members and emergency
79
+ exclude inapplicable areas. `ClinicalSummaryProfiles.Human` retains Advance
80
+ Directives; the current `ClinicalSummaryProfiles.Animal` excludes that
81
+ human-only section while reusing the same screen. Family history, care-team members and emergency
78
82
  contacts remain independent; the organizer never follows another subject's
79
83
  card or documents automatically.
84
+ - `SubjectWorkspace`: canonical Personal navigation for Profile, Health, Care,
85
+ Communications and Contacts/Permissions. Product profiles may append an
86
+ explicit capability screen, such as animal mobility or SOS emergency work,
87
+ but tab selection never creates authority and all content remains host-
88
+ authorized.
80
89
  - `ClinicalTimeline` and `ClinicalDateTimeFields`: render longitudinal entries
81
90
  with localized dates, inclusive date/time ranges, multi-select clinical
82
91
  facets and accessible latest-first navigation. Editors capture calendar date
@@ -122,9 +131,11 @@ The package deliberately exposes modules instead of a cloned application:
122
131
  returned identifier evidence never grant subject access.
123
132
  resolver plus section selector. It deliberately has no scanner role: the
124
133
  same component is reusable by an individual member or a professional.
125
- - `SoschainWorkspace`: subject-card picker and four-area workspace for Places,
126
- devices/vehicles and read-only emergency communications. The host supplies
127
- already-authorized cards and capabilities.
134
+ - `SoschainWorkspace`: subject-card picker and capability composition for the
135
+ overview, health summary, care journey, emergency data, communications,
136
+ places and products screens. The host supplies already-authorized cards,
137
+ content and capabilities; SOS-specific emergency modules do not fork the
138
+ common Personal or Professional components.
128
139
  - `EncounterTransferConsole`: visual patient-transfer workspace. The host
129
140
  resolves the authorized subject, contacts and write capability; the component
130
141
  only reports the chosen source outcome (`on-hold` when returning or
@@ -10,9 +10,21 @@ export declare const ClinicalSectionNavigationIds: Readonly<{
10
10
  readonly ClinicalNotes: "clinical-notes";
11
11
  readonly CareTeamMembers: "care-team-members";
12
12
  readonly EmergencyContacts: "emergency-contacts";
13
+ readonly AdvanceDirectives: "advance-directives";
13
14
  }>;
14
15
  export type ClinicalSectionNavigationId = typeof ClinicalSectionNavigationIds[keyof typeof ClinicalSectionNavigationIds];
15
16
  export type ClinicalSubjectKind = 'person' | 'animal';
17
+ export declare const ClinicalSummaryProfiles: Readonly<{
18
+ readonly Human: Readonly<{
19
+ id: "human";
20
+ excludedSectionIds: readonly never[];
21
+ }>;
22
+ readonly Animal: Readonly<{
23
+ id: "animal";
24
+ excludedSectionIds: readonly "advance-directives"[];
25
+ }>;
26
+ }>;
27
+ export type ClinicalSummaryProfile = typeof ClinicalSummaryProfiles[keyof typeof ClinicalSummaryProfiles];
16
28
  export type AllClinicalSectionDefinition<SubjectKind extends ClinicalSubjectKind> = Readonly<{
17
29
  id: ClinicalSectionNavigationId | (string & {});
18
30
  title: string;
@@ -27,6 +39,7 @@ export type AllClinicalSectionsProps<SubjectKind extends ClinicalSubjectKind> =
27
39
  title: string;
28
40
  sections: readonly AllClinicalSectionDefinition<SubjectKind>[];
29
41
  excludedSectionIds?: readonly string[];
42
+ profile?: ClinicalSummaryProfile;
30
43
  presentation?: 'sections' | 'tabs';
31
44
  }>;
32
45
  /**
@@ -37,5 +50,5 @@ export type AllClinicalSectionsProps<SubjectKind extends ClinicalSubjectKind> =
37
50
  * contacts and care-team members remain independent domains; this component
38
51
  * never follows another subject's card or document links automatically.
39
52
  */
40
- export declare function AllClinicalSections<SubjectKind extends ClinicalSubjectKind>({ subjectKind, title, sections, excludedSectionIds, presentation, }: AllClinicalSectionsProps<SubjectKind>): import("react").JSX.Element;
53
+ export declare function AllClinicalSections<SubjectKind extends ClinicalSubjectKind>({ subjectKind, title, sections, excludedSectionIds, profile, presentation, }: AllClinicalSectionsProps<SubjectKind>): import("react").JSX.Element;
41
54
  //# sourceMappingURL=AllClinicalSections.d.ts.map
@@ -1 +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"}
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;;;;;;;;;;;;EAY9B,CAAA;AAEX,MAAM,MAAM,2BAA2B,GAAG,OAAO,4BAA4B,CAAC,MAAM,OAAO,4BAA4B,CAAC,CAAA;AACxH,MAAM,MAAM,mBAAmB,GAAG,QAAQ,GAAG,QAAQ,CAAA;AAErD,eAAO,MAAM,uBAAuB;;;;;;;;;EAGzB,CAAA;AAEX,MAAM,MAAM,sBAAsB,GAAG,OAAO,uBAAuB,CAAC,MAAM,OAAO,uBAAuB,CAAC,CAAA;AAEzG,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,OAAO,CAAC,EAAE,sBAAsB,CAAA;IAChC,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,OAAO,EACP,YAAyB,GAC1B,EAAE,wBAAwB,CAAC,WAAW,CAAC,+BAsCvC"}
@@ -11,6 +11,11 @@ export const ClinicalSectionNavigationIds = Object.freeze({
11
11
  ClinicalNotes: 'clinical-notes',
12
12
  CareTeamMembers: 'care-team-members',
13
13
  EmergencyContacts: 'emergency-contacts',
14
+ AdvanceDirectives: 'advance-directives',
15
+ });
16
+ export const ClinicalSummaryProfiles = Object.freeze({
17
+ Human: Object.freeze({ id: 'human', excludedSectionIds: Object.freeze([]) }),
18
+ Animal: Object.freeze({ id: 'animal', excludedSectionIds: Object.freeze([ClinicalSectionNavigationIds.AdvanceDirectives]) }),
14
19
  });
15
20
  /**
16
21
  * Organizes host-provided clinical views without redefining their FHIR model.
@@ -20,11 +25,12 @@ export const ClinicalSectionNavigationIds = Object.freeze({
20
25
  * contacts and care-team members remain independent domains; this component
21
26
  * never follows another subject's card or document links automatically.
22
27
  */
23
- export function AllClinicalSections({ subjectKind, title, sections, excludedSectionIds = [], presentation = 'sections', }) {
24
- const visibleSections = organizeClinicalSections(sections.filter(({ id }) => !excludedSectionIds.includes(id)));
28
+ export function AllClinicalSections({ subjectKind, title, sections, excludedSectionIds = [], profile, presentation = 'sections', }) {
29
+ const effectiveExcludedSectionIds = [...new Set([...(profile?.excludedSectionIds ?? []), ...excludedSectionIds])];
30
+ const visibleSections = organizeClinicalSections(sections.filter(({ id }) => !effectiveExcludedSectionIds.includes(id)));
25
31
  const [selectedId, setSelectedId] = useState(visibleSections[0]?.id ?? '');
26
32
  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))) }))] }));
33
+ 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: effectiveExcludedSectionIds }) })) : null] })) : (_jsx("div", { className: "uhcp-all-clinical-stack", children: visibleSections.map((section) => (_jsx(ClinicalSection, { definition: section, excludedSectionIds: effectiveExcludedSectionIds }, section.id))) }))] }));
28
34
  }
29
35
  function organizeClinicalSections(sections) {
30
36
  const ipsChildrenIds = new Set([
@@ -6,6 +6,7 @@ export type SoschainCardSummary = Readonly<{
6
6
  identifier: string;
7
7
  displayName: string;
8
8
  kindLabel: string;
9
+ subjectKind?: 'person' | 'animal';
9
10
  selected?: boolean;
10
11
  openHref: string;
11
12
  }>;
@@ -1 +1 @@
1
- {"version":3,"file":"SoschainWorkspace.d.ts","sourceRoot":"","sources":["../src/SoschainWorkspace.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SoschainWorkspace.d.ts","sourceRoot":"","sources":["../src/SoschainWorkspace.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { type ReactNode } from 'react';
2
+ export declare const PERSONAL_SUBJECT_WORKSPACE_AREAS: readonly ["profile", "health", "care", "communications", "access"];
3
+ export type PersonalSubjectWorkspaceAreaId = typeof PERSONAL_SUBJECT_WORKSPACE_AREAS[number];
4
+ export type SubjectWorkspaceArea = Readonly<{
5
+ id: string;
6
+ label: string;
7
+ content: ReactNode;
8
+ icon?: ReactNode;
9
+ disabled?: boolean;
10
+ }>;
11
+ export type SubjectWorkspaceProps = Readonly<{
12
+ ariaLabel: string;
13
+ areas: readonly SubjectWorkspaceArea[];
14
+ activeArea?: string;
15
+ initialArea?: string;
16
+ onAreaChange?: (area: string) => void;
17
+ className?: string;
18
+ tabListClassName?: string;
19
+ tabClassName?: string;
20
+ panelClassName?: string;
21
+ }>;
22
+ /**
23
+ * Shared subject-screen shell for Personal portals.
24
+ *
25
+ * Hosts provide already-authorized content and product-specific additions.
26
+ * Selecting a tab changes presentation only and never grants data access.
27
+ */
28
+ export declare function SubjectWorkspace({ ariaLabel, areas, activeArea, initialArea, onAreaChange, className, tabListClassName, tabClassName, panelClassName, }: SubjectWorkspaceProps): import("react").JSX.Element;
29
+ //# sourceMappingURL=SubjectWorkspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubjectWorkspace.d.ts","sourceRoot":"","sources":["../src/SubjectWorkspace.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAkD,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtF,eAAO,MAAM,gCAAgC,oEAMnC,CAAA;AAEV,MAAM,MAAM,8BAA8B,GAAG,OAAO,gCAAgC,CAAC,MAAM,CAAC,CAAA;AAC5F,MAAM,MAAM,oBAAoB,GAAG,QAAQ,CAAC;IAC1C,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,SAAS,CAAA;IAClB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAC,CAAA;AAEF,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,SAAS,oBAAoB,EAAE,CAAA;IACtC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAC,CAAA;AAEF;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,SAAS,EACT,KAAK,EACL,UAAU,EACV,WAAW,EACX,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,YAAY,EACZ,cAAc,GACf,EAAE,qBAAqB,+BAyDvB"}
@@ -0,0 +1,56 @@
1
+ 'use client';
2
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
3
+ import { useEffect, useId, useState } from 'react';
4
+ export const PERSONAL_SUBJECT_WORKSPACE_AREAS = [
5
+ 'profile',
6
+ 'health',
7
+ 'care',
8
+ 'communications',
9
+ 'access',
10
+ ];
11
+ /**
12
+ * Shared subject-screen shell for Personal portals.
13
+ *
14
+ * Hosts provide already-authorized content and product-specific additions.
15
+ * Selecting a tab changes presentation only and never grants data access.
16
+ */
17
+ export function SubjectWorkspace({ ariaLabel, areas, activeArea, initialArea, onAreaChange, className, tabListClassName, tabClassName, panelClassName, }) {
18
+ const firstEnabledArea = areas.find(({ disabled }) => !disabled)?.id ?? '';
19
+ const [uncontrolledArea, setUncontrolledArea] = useState(initialArea ?? firstEnabledArea);
20
+ const requestedArea = activeArea ?? uncontrolledArea;
21
+ const selectedArea = areas.some(({ id, disabled }) => id === requestedArea && !disabled)
22
+ ? requestedArea
23
+ : firstEnabledArea;
24
+ const instanceId = useId().replaceAll(':', '');
25
+ useEffect(() => {
26
+ if (activeArea === undefined && uncontrolledArea !== selectedArea)
27
+ setUncontrolledArea(selectedArea);
28
+ }, [activeArea, selectedArea, uncontrolledArea]);
29
+ function select(area) {
30
+ if (area.disabled)
31
+ return;
32
+ if (activeArea === undefined)
33
+ setUncontrolledArea(area.id);
34
+ onAreaChange?.(area.id);
35
+ }
36
+ function moveWithKeyboard(event, area) {
37
+ const enabledAreas = areas.filter(({ disabled }) => !disabled);
38
+ const currentIndex = enabledAreas.findIndex(({ id }) => id === area.id);
39
+ let nextIndex;
40
+ if (event.key === 'ArrowRight' || event.key === 'ArrowDown')
41
+ nextIndex = (currentIndex + 1) % enabledAreas.length;
42
+ if (event.key === 'ArrowLeft' || event.key === 'ArrowUp')
43
+ nextIndex = (currentIndex - 1 + enabledAreas.length) % enabledAreas.length;
44
+ if (event.key === 'Home')
45
+ nextIndex = 0;
46
+ if (event.key === 'End')
47
+ nextIndex = enabledAreas.length - 1;
48
+ if (nextIndex === undefined || !enabledAreas[nextIndex])
49
+ return;
50
+ event.preventDefault();
51
+ const nextArea = enabledAreas[nextIndex];
52
+ select(nextArea);
53
+ document.getElementById(`${instanceId}-tab-${nextArea.id}`)?.focus();
54
+ }
55
+ return _jsxs("section", { className: className ?? 'uhcp-subject-workspace', children: [_jsx("div", { className: tabListClassName ?? 'uhcp-subject-workspace-tabs', role: "tablist", "aria-label": ariaLabel, children: areas.map((area) => _jsxs("button", { id: `${instanceId}-tab-${area.id}`, type: "button", role: "tab", "aria-selected": selectedArea === area.id, "aria-controls": `${instanceId}-panel-${area.id}`, disabled: area.disabled, className: tabClassName, onClick: () => select(area), onKeyDown: (event) => moveWithKeyboard(event, area), children: [area.icon, area.label] }, area.id)) }), areas.map((area) => selectedArea === area.id ? _jsx("div", { id: `${instanceId}-panel-${area.id}`, role: "tabpanel", "aria-labelledby": `${instanceId}-tab-${area.id}`, className: panelClassName, children: area.content }, area.id) : null)] });
56
+ }
package/dist/index.d.ts CHANGED
@@ -49,4 +49,5 @@ export * from './NotificationComposer.js';
49
49
  export * from './notification-bff-client.js';
50
50
  export * from './CommunicationsWorkspace.js';
51
51
  export * from './SelectedSubjectWorkspace.js';
52
+ export * from './SubjectWorkspace.js';
52
53
  //# 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,2BAA2B,CAAA;AACzC,cAAc,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,8BAA8B,CAAA;AAC5C,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,qCAAqC,CAAA;AACnD,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,iCAAiC,CAAA;AAC/C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,yBAAyB,CAAA;AACvC,cAAc,uCAAuC,CAAA;AACrD,cAAc,uBAAuB,CAAA;AACrC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,+BAA+B,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,8BAA8B,CAAA;AAC5C,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,qCAAqC,CAAA;AACnD,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,iCAAiC,CAAA;AAC/C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,yBAAyB,CAAA;AACvC,cAAc,uCAAuC,CAAA;AACrD,cAAc,uBAAuB,CAAA;AACrC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,8BAA8B,CAAA;AAC5C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,uBAAuB,CAAA"}
package/dist/index.js CHANGED
@@ -49,3 +49,4 @@ export * from './NotificationComposer.js';
49
49
  export * from './notification-bff-client.js';
50
50
  export * from './CommunicationsWorkspace.js';
51
51
  export * from './SelectedSubjectWorkspace.js';
52
+ export * from './SubjectWorkspace.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uhc-portal-components-react",
3
- "version": "0.2.19",
3
+ "version": "0.2.20",
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",