uhc-portal-components-react 0.2.29 → 0.2.31

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.2.31 - 2026-10-23
4
+
5
+ - Add one concise, accessible `Sections` index for Personal portals so card,
6
+ health, appointments and tasks, emergencies, communications, permissions and
7
+ optional profile destinations do not need a duplicated top navigation row.
8
+ - Keep the active destination marked across human and animal profiles while
9
+ leaving authorization and enabled-section decisions with the trusted host.
10
+
11
+ ## 0.2.30 - 2026-10-22
12
+
13
+ - Restore the stable `activate-member-profile` action marker on the shared
14
+ employee-invitation activation submit button so consumer E2E inventories and
15
+ keyboard journeys keep the same observable action across portal brands.
16
+
3
17
  ## 0.2.29 - 2026-10-22
4
18
 
5
19
  - Add one product-neutral WebRTC engine and call screen for audio/video start,
@@ -21,5 +21,5 @@ export function ProfessionalProfileActivationPanel({ copy, busy, error, onSubmit
21
21
  setLocalError('');
22
22
  void onSubmit({ credential: credential.trim(), pin });
23
23
  }
24
- return _jsx("section", { className: "uhcp-professional-activation", "aria-labelledby": "uhcp-professional-activation-title", children: _jsxs("form", { onSubmit: submit, children: [_jsxs("header", { children: [copy.eyebrow ? _jsx("p", { className: "uhcp-eyebrow", children: copy.eyebrow }) : null, _jsx("h1", { id: "uhcp-professional-activation-title", children: copy.title }), _jsx("p", { children: copy.description })] }), _jsxs("label", { children: [_jsx("span", { children: copy.credentialLabel }), _jsx("input", { name: "professionalCredential", value: credential, onChange: event => setCredential(event.currentTarget.value), autoComplete: "one-time-code", required: true })] }), _jsxs("label", { children: [_jsx("span", { children: copy.pinLabel }), _jsx("input", { name: "newPin", type: "password", inputMode: "numeric", minLength: 6, maxLength: 12, autoComplete: "new-password", value: pin, onChange: event => setPin(event.currentTarget.value), required: true })] }), _jsxs("label", { children: [_jsx("span", { children: copy.pinConfirmationLabel }), _jsx("input", { name: "confirmPin", type: "password", inputMode: "numeric", minLength: 6, maxLength: 12, autoComplete: "new-password", value: pinConfirmation, onChange: event => setPinConfirmation(event.currentTarget.value), required: true })] }), (localError || error) ? _jsx("p", { role: "alert", children: localError || error }) : null, _jsx("button", { type: "submit", disabled: busy, children: busy ? copy.submitting : copy.submit })] }) });
24
+ return _jsx("section", { className: "uhcp-professional-activation", "aria-labelledby": "uhcp-professional-activation-title", children: _jsxs("form", { onSubmit: submit, children: [_jsxs("header", { children: [copy.eyebrow ? _jsx("p", { className: "uhcp-eyebrow", children: copy.eyebrow }) : null, _jsx("h1", { id: "uhcp-professional-activation-title", children: copy.title }), _jsx("p", { children: copy.description })] }), _jsxs("label", { children: [_jsx("span", { children: copy.credentialLabel }), _jsx("input", { name: "professionalCredential", value: credential, onChange: event => setCredential(event.currentTarget.value), autoComplete: "one-time-code", required: true })] }), _jsxs("label", { children: [_jsx("span", { children: copy.pinLabel }), _jsx("input", { name: "newPin", type: "password", inputMode: "numeric", minLength: 6, maxLength: 12, autoComplete: "new-password", value: pin, onChange: event => setPin(event.currentTarget.value), required: true })] }), _jsxs("label", { children: [_jsx("span", { children: copy.pinConfirmationLabel }), _jsx("input", { name: "confirmPin", type: "password", inputMode: "numeric", minLength: 6, maxLength: 12, autoComplete: "new-password", value: pinConfirmation, onChange: event => setPinConfirmation(event.currentTarget.value), required: true })] }), (localError || error) ? _jsx("p", { role: "alert", children: localError || error }) : null, _jsx("button", { type: "submit", "data-portal-action": "activate-member-profile", disabled: busy, children: busy ? copy.submitting : copy.submit })] }) });
25
25
  }
@@ -0,0 +1,22 @@
1
+ import { type ReactNode } from 'react';
2
+ export type SubjectSectionIndexItem = Readonly<{
3
+ id: string;
4
+ label: string;
5
+ icon?: ReactNode;
6
+ disabled?: boolean;
7
+ }>;
8
+ export type SubjectSectionIndexProps = Readonly<{
9
+ ariaLabel: string;
10
+ title: string;
11
+ sections: readonly SubjectSectionIndexItem[];
12
+ activeSection: string;
13
+ onSectionChange: (section: string) => void;
14
+ className?: string;
15
+ }>;
16
+ /**
17
+ * One concise, brand-neutral navigation index for a selected Personal subject.
18
+ * The host supplies only server-authorized destinations; selecting one changes
19
+ * presentation and never grants access to the underlying data.
20
+ */
21
+ export declare function SubjectSectionIndex({ ariaLabel, title, sections, activeSection, onSectionChange, className, }: SubjectSectionIndexProps): import("react").JSX.Element;
22
+ //# sourceMappingURL=SubjectSectionIndex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubjectSectionIndex.d.ts","sourceRoot":"","sources":["../src/SubjectSectionIndex.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAEjE,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAC7C,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAC,CAAA;AAEF,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,SAAS,uBAAuB,EAAE,CAAA;IAC5C,aAAa,EAAE,MAAM,CAAA;IACrB,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IAC1C,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAC,CAAA;AAEF;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,SAAS,EACT,KAAK,EACL,QAAQ,EACR,aAAa,EACb,eAAe,EACf,SAAS,GACV,EAAE,wBAAwB,+BAmC1B"}
@@ -0,0 +1,31 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useId } from 'react';
4
+ /**
5
+ * One concise, brand-neutral navigation index for a selected Personal subject.
6
+ * The host supplies only server-authorized destinations; selecting one changes
7
+ * presentation and never grants access to the underlying data.
8
+ */
9
+ export function SubjectSectionIndex({ ariaLabel, title, sections, activeSection, onSectionChange, className, }) {
10
+ const visibleSections = sections.filter(({ disabled }) => !disabled);
11
+ const instanceId = useId().replaceAll(':', '');
12
+ function moveWithKeyboard(event, sectionId) {
13
+ const currentIndex = visibleSections.findIndex(({ id }) => id === sectionId);
14
+ let nextIndex;
15
+ if (event.key === 'ArrowRight' || event.key === 'ArrowDown')
16
+ nextIndex = (currentIndex + 1) % visibleSections.length;
17
+ if (event.key === 'ArrowLeft' || event.key === 'ArrowUp')
18
+ nextIndex = (currentIndex - 1 + visibleSections.length) % visibleSections.length;
19
+ if (event.key === 'Home')
20
+ nextIndex = 0;
21
+ if (event.key === 'End')
22
+ nextIndex = visibleSections.length - 1;
23
+ if (nextIndex === undefined || !visibleSections[nextIndex])
24
+ return;
25
+ event.preventDefault();
26
+ const nextSection = visibleSections[nextIndex];
27
+ onSectionChange(nextSection.id);
28
+ document.getElementById(`${instanceId}-section-${nextSection.id}`)?.focus();
29
+ }
30
+ return _jsxs("nav", { className: className ?? 'uhcp-subject-section-index', "aria-label": ariaLabel, children: [_jsx("h2", { children: title }), _jsx("div", { role: "tablist", "aria-label": ariaLabel, children: visibleSections.map((section) => _jsxs("button", { id: `${instanceId}-section-${section.id}`, type: "button", role: "tab", "aria-selected": section.id === activeSection, onClick: () => onSectionChange(section.id), onKeyDown: (event) => moveWithKeyboard(event, section.id), children: [section.icon, _jsx("span", { children: section.label })] }, section.id)) })] });
31
+ }
package/dist/index.d.ts CHANGED
@@ -50,6 +50,7 @@ export * from './notification-bff-client.js';
50
50
  export * from './CommunicationsWorkspace.js';
51
51
  export * from './SelectedSubjectWorkspace.js';
52
52
  export * from './SubjectWorkspace.js';
53
+ export * from './SubjectSectionIndex.js';
53
54
  export * from './SubjectDemographicsFields.js';
54
55
  export * from './CardPreview.js';
55
56
  export * from './CollapsiblePortalSection.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,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;AACrC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,kBAAkB,CAAA;AAChC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,yCAAyC,CAAA;AACvD,cAAc,uCAAuC,CAAA;AACrD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,qBAAqB,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;AACrC,cAAc,0BAA0B,CAAA;AACxC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,kBAAkB,CAAA;AAChC,cAAc,+BAA+B,CAAA;AAC7C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,yCAAyC,CAAA;AACvD,cAAc,uCAAuC,CAAA;AACrD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,+BAA+B,CAAA;AAC7C,cAAc,qBAAqB,CAAA"}
package/dist/index.js CHANGED
@@ -50,6 +50,7 @@ export * from './notification-bff-client.js';
50
50
  export * from './CommunicationsWorkspace.js';
51
51
  export * from './SelectedSubjectWorkspace.js';
52
52
  export * from './SubjectWorkspace.js';
53
+ export * from './SubjectSectionIndex.js';
53
54
  export * from './SubjectDemographicsFields.js';
54
55
  export * from './CardPreview.js';
55
56
  export * from './CollapsiblePortalSection.js';
package/dist/styles.css CHANGED
@@ -1016,3 +1016,42 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
1016
1016
  .uhcp-subject-demographics-fields dd {
1017
1017
  margin: 0;
1018
1018
  }
1019
+ .uhcp-subject-section-index {
1020
+ border: 1px solid var(--uhcp-border, currentColor);
1021
+ border-radius: 1.5rem;
1022
+ padding: 1rem;
1023
+ }
1024
+
1025
+ .uhcp-subject-section-index > h2 {
1026
+ margin: 0 0 0.75rem;
1027
+ font-size: 1rem;
1028
+ font-weight: 700;
1029
+ }
1030
+
1031
+ .uhcp-subject-section-index [role='tablist'] {
1032
+ display: grid;
1033
+ grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
1034
+ gap: 0.5rem;
1035
+ }
1036
+
1037
+ .uhcp-subject-section-index [role='tab'] {
1038
+ display: flex;
1039
+ align-items: center;
1040
+ gap: 0.5rem;
1041
+ min-height: 2.75rem;
1042
+ padding: 0.65rem 0.9rem;
1043
+ border: 1px solid var(--uhcp-border, currentColor);
1044
+ border-radius: 0.9rem;
1045
+ background: transparent;
1046
+ color: inherit;
1047
+ font: inherit;
1048
+ font-weight: 650;
1049
+ text-align: left;
1050
+ cursor: pointer;
1051
+ }
1052
+
1053
+ .uhcp-subject-section-index [role='tab'][aria-selected='true'] {
1054
+ border-color: var(--uhcp-accent, currentColor);
1055
+ color: var(--uhcp-accent, inherit);
1056
+ box-shadow: inset 0 0 0 1px var(--uhcp-accent, currentColor);
1057
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uhc-portal-components-react",
3
- "version": "0.2.29",
3
+ "version": "0.2.31",
4
4
  "description": "Brand-neutral React portal screens, account preferences and protected-profile UI.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",