uhc-portal-components-react 0.2.3 → 0.2.4

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,15 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.2.4 - 2026-10-09
6
+
7
+ - Lead the protected-profile card with the unlock task, center the selected
8
+ sector context and place passkey/PIN controls immediately after it without
9
+ repeating a visible "profile to unlock" eyebrow.
10
+ - Add host-customizable selected, unlock and alternative action tokens so
11
+ portals can distinguish blue selection, orange unlock and recovery actions
12
+ consistently in light and dark themes.
13
+
5
14
  ## 0.2.3 - 2026-10-09
6
15
 
7
16
  - Keep the section-removal action at the far edge of its section while still
@@ -1 +1 @@
1
- {"version":3,"file":"ProfileProtectionGateV2.d.ts","sourceRoot":"","sources":["../src/ProfileProtectionGateV2.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA+C,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AACnF,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACtB,yBAAyB,EACzB,mBAAmB,EACpB,MAAM,gBAAgB,CAAA;AAEvB,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,KAAK,EAAE,sBAAsB,CAAA;IAC7B,MAAM,EAAE,yBAAyB,CAAA;IACjC,IAAI,EAAE,uBAAuB,CAAA;IAC7B,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAC9E,eAAe,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,iBAAiB,CAAC,EAAE,SAAS,CAAA;IAC7B,gBAAgB,CAAC,EAAE,SAAS,CAAA;IAC5B,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAC,CAAA;AAEF;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,KAAK,EACL,MAAM,EACN,IAAI,EACJ,QAAQ,EACR,eAAe,EACf,OAAO,EACP,iBAAiB,EACjB,gBAAgB,EAChB,QAAQ,GACT,EAAE,4BAA4B,+BAuH9B"}
1
+ {"version":3,"file":"ProfileProtectionGateV2.d.ts","sourceRoot":"","sources":["../src/ProfileProtectionGateV2.tsx"],"names":[],"mappings":"AAEA,OAAO,EAA+C,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AACnF,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACtB,yBAAyB,EACzB,mBAAmB,EACpB,MAAM,gBAAgB,CAAA;AAEvB,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,KAAK,EAAE,sBAAsB,CAAA;IAC7B,MAAM,EAAE,yBAAyB,CAAA;IACjC,IAAI,EAAE,uBAAuB,CAAA;IAC7B,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,mBAAmB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAAA;IAC9E,eAAe,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,iBAAiB,CAAC,EAAE,SAAS,CAAA;IAC7B,gBAAgB,CAAC,EAAE,SAAS,CAAA;IAC5B,QAAQ,EAAE,SAAS,CAAA;CACpB,CAAC,CAAA;AAEF;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,KAAK,EACL,MAAM,EACN,IAAI,EACJ,QAAQ,EACR,eAAe,EACf,OAAO,EACP,iBAAiB,EACjB,gBAAgB,EAChB,QAAQ,GACT,EAAE,4BAA4B,+BAsH9B"}
@@ -79,5 +79,5 @@ export function ProfileProtectionGateV2({ state, target, copy, onUnlock, onPassk
79
79
  : state === 'unavailable'
80
80
  ? copy.unavailableBody
81
81
  : copy.unlockBody;
82
- return (_jsxs("section", { className: "uhcp-profile-gate uhcp-profile-gate-v2", "aria-live": "polite", children: [_jsxs("div", { className: "uhcp-profile-target", children: [target.icon && _jsx("img", { src: target.icon.src, alt: target.icon.alt, width: target.icon.width, height: target.icon.height }), _jsxs("div", { className: "uhcp-profile-target-copy", children: [_jsx("span", { className: "uhcp-profile-target-eyebrow", children: target.eyebrow }), _jsx("strong", { children: target.title }), target.subtitle && _jsx("span", { children: target.subtitle })] }), target.badges?.length ? _jsx("ul", { className: "uhcp-profile-target-badges", "aria-label": target.eyebrow, children: target.badges.map(badge => _jsx("li", { children: badge }, badge)) }) : null, target.details?.length ? _jsx("dl", { className: "uhcp-profile-target-details", children: target.details.map(detail => _jsxs("div", { children: [_jsx("dt", { children: detail.label }), _jsx("dd", { children: detail.value })] }, `${detail.label}:${detail.value}`)) }) : null] }), _jsxs("div", { className: "uhcp-profile-gate-copy", children: [_jsx("h1", { children: title }), _jsx("p", { children: body })] }), state === 'locked' && onPasskeyUnlock && _jsx("button", { type: "button", "data-portal-action": "unlock-profile-with-passkey", disabled: busy, onClick: unlockWithPasskey, children: copy.unlockWithPasskey }), state === 'locked' && _jsxs("details", { className: "uhcp-profile-pin-fallback", open: !onPasskeyUnlock, children: [_jsx("summary", { children: onPasskeyUnlock ? copy.usePinInstead : copy.pinLabel }), _jsxs("form", { onSubmit: unlock, children: [_jsxs("label", { children: [copy.pinLabel, _jsx("input", { ref: input, type: "password", inputMode: "numeric", minLength: 6, autoComplete: "current-password", value: pin, onChange: (event) => setPin(event.target.value) })] }), error && _jsx("p", { role: "alert", className: "uhcp-error", children: error }), _jsx("button", { type: "submit", "data-portal-action": "unlock-profile", disabled: busy, children: copy.unlock })] }), pinRejected && pinFailureActions ? _jsx("div", { className: "uhcp-profile-pin-recovery", children: pinFailureActions }) : null] }), state === 'unavailable' && onRetry && _jsx("button", { type: "button", onClick: onRetry, children: copy.retry }), secondaryActions && _jsx("div", { className: "uhcp-profile-gate-secondary", children: secondaryActions })] }));
82
+ return (_jsxs("section", { className: "uhcp-profile-gate uhcp-profile-gate-v2", "aria-live": "polite", children: [_jsxs("div", { className: "uhcp-profile-gate-copy", children: [_jsx("h1", { children: title }), _jsx("p", { children: body })] }), _jsxs("div", { className: "uhcp-profile-target", children: [target.icon && _jsx("img", { src: target.icon.src, alt: target.icon.alt, width: target.icon.width, height: target.icon.height }), _jsxs("div", { className: "uhcp-profile-target-copy", children: [_jsx("strong", { children: target.title }), target.subtitle && _jsx("span", { children: target.subtitle })] }), target.badges?.length ? _jsx("ul", { className: "uhcp-profile-target-badges uhcp-profile-target-badges-centered", "aria-label": target.title, children: target.badges.map(badge => _jsx("li", { children: badge }, badge)) }) : null, target.details?.length ? _jsx("dl", { className: "uhcp-profile-target-details", children: target.details.map(detail => _jsxs("div", { children: [_jsx("dt", { children: detail.label }), _jsx("dd", { children: detail.value })] }, `${detail.label}:${detail.value}`)) }) : null] }), state === 'locked' && onPasskeyUnlock && _jsx("button", { type: "button", className: "uhcp-action-unlock", "data-portal-action": "unlock-profile-with-passkey", disabled: busy, onClick: unlockWithPasskey, children: copy.unlockWithPasskey }), state === 'locked' && _jsxs("details", { className: "uhcp-profile-pin-fallback", open: !onPasskeyUnlock, children: [_jsx("summary", { children: onPasskeyUnlock ? copy.usePinInstead : copy.pinLabel }), _jsxs("form", { onSubmit: unlock, children: [_jsxs("label", { children: [copy.pinLabel, _jsx("input", { ref: input, type: "password", inputMode: "numeric", minLength: 6, autoComplete: "current-password", value: pin, onChange: (event) => setPin(event.target.value) })] }), error && _jsx("p", { role: "alert", className: "uhcp-error", children: error }), _jsx("button", { type: "submit", className: "uhcp-action-unlock", "data-portal-action": "unlock-profile", disabled: busy, children: copy.unlock })] }), pinRejected && pinFailureActions ? _jsx("div", { className: "uhcp-profile-pin-recovery", children: pinFailureActions }) : null] }), state === 'unavailable' && onRetry && _jsx("button", { type: "button", onClick: onRetry, children: copy.retry }), secondaryActions && _jsx("div", { className: "uhcp-profile-gate-secondary", children: secondaryActions })] }));
83
83
  }
package/dist/styles.css CHANGED
@@ -13,6 +13,12 @@
13
13
  /* Intentionally invariant across light/dark, matching UHC Personal. */
14
14
  --uhcp-action-start: hsl(184 74% 34% / .96);
15
15
  --uhcp-action-end: hsl(214 70% 42% / .9);
16
+ --uhcp-selected-start: var(--uhcp-action-start);
17
+ --uhcp-selected-end: var(--uhcp-action-end);
18
+ --uhcp-unlock-start: hsl(28 91% 57%);
19
+ --uhcp-unlock-end: hsl(21 86% 48%);
20
+ --uhcp-unlock-text: #fff;
21
+ --uhcp-alternative: color-mix(in srgb, var(--uhcp-attention) 22%, var(--uhcp-panel));
16
22
  }
17
23
  html[data-density='small'] { font-size: 15px; }
18
24
  html[data-density='medium'] { font-size: 16px; }
@@ -161,15 +167,21 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
161
167
  .uhcp-profile-gate label { color: var(--uhcp-muted); display: grid; gap: .45rem; }
162
168
  .uhcp-profile-gate input { background: var(--uhcp-panel); border: 1px solid var(--uhcp-border); border-radius: .75rem; color: var(--uhcp-text); padding: .8rem; }
163
169
  .uhcp-profile-gate button { background: linear-gradient(135deg, var(--uhcp-action-start), var(--uhcp-action-end)); border: 0; border-radius: .75rem; color: #fff; cursor: pointer; font: inherit; font-weight: 800; padding: .8rem 1rem; }
164
- .uhcp-profile-gate-v2 { background: linear-gradient(145deg, color-mix(in srgb, var(--uhcp-surface-accent) 76%, var(--uhcp-panel)), var(--uhcp-panel-muted)); border: 1px solid color-mix(in srgb, var(--uhcp-turquoise) 30%, var(--uhcp-border)); border-radius: 1.5rem; box-shadow: 0 1.2rem 3rem color-mix(in srgb, var(--uhcp-text) 10%, transparent); gap: 1rem; }
170
+ .uhcp-profile-gate-v2 { background: linear-gradient(145deg, color-mix(in srgb, var(--uhcp-surface-accent) 76%, var(--uhcp-panel)), var(--uhcp-panel-muted)); border: 1px solid color-mix(in srgb, var(--uhcp-turquoise) 30%, var(--uhcp-border)); border-radius: 1.5rem; box-shadow: 0 1.2rem 3rem color-mix(in srgb, var(--uhcp-text) 10%, transparent); gap: 1rem; transition: background .18s ease, border-color .18s ease, box-shadow .18s ease; }
171
+ .uhcp-profile-gate-v2:is(:hover, :focus-within) { background: linear-gradient(145deg, color-mix(in srgb, var(--uhcp-surface-accent) 62%, var(--uhcp-panel)), color-mix(in srgb, var(--uhcp-selected-start) 12%, var(--uhcp-panel-muted))); border-color: color-mix(in srgb, var(--uhcp-selected-start) 50%, var(--uhcp-border)); box-shadow: 0 1.3rem 3.2rem color-mix(in srgb, var(--uhcp-selected-start) 18%, transparent); }
172
+ .uhcp-profile-gate-copy { text-align: center; }
173
+ .uhcp-profile-gate-copy h1, .uhcp-profile-gate-copy p { margin: 0; }
174
+ .uhcp-profile-gate-copy p { margin-top: .45rem; }
165
175
  .uhcp-profile-target { background: linear-gradient(135deg, color-mix(in srgb, var(--uhcp-surface-accent) 80%, var(--uhcp-panel)), color-mix(in srgb, var(--uhcp-turquoise) 12%, var(--uhcp-panel))); border: 1px solid color-mix(in srgb, var(--uhcp-turquoise) 38%, var(--uhcp-border)); border-radius: 1rem; display: grid; gap: .8rem; padding: 1rem; }
166
176
  .uhcp-profile-target > img { border-radius: .75rem; object-fit: contain; }
167
- .uhcp-profile-target-copy { display: grid; gap: .2rem; }
177
+ .uhcp-profile-target-copy { display: grid; gap: .2rem; text-align: center; }
168
178
  .uhcp-profile-target-copy > strong { color: var(--uhcp-text); font-size: 1.2rem; }
169
179
  .uhcp-profile-target-copy > span:last-child { color: var(--uhcp-muted); }
170
180
  .uhcp-profile-target-eyebrow { color: var(--uhcp-muted); font-size: .78rem; font-weight: 800; letter-spacing: .04em; text-transform: uppercase; }
171
181
  .uhcp-profile-target-badges { display: flex; flex-wrap: wrap; gap: .45rem; list-style: none; margin: 0; padding: 0; }
172
- .uhcp-profile-target-badges li { background: color-mix(in srgb, var(--uhcp-turquoise) 13%, var(--uhcp-panel)); border: 1px solid color-mix(in srgb, var(--uhcp-turquoise) 36%, var(--uhcp-border)); border-radius: 999px; color: var(--uhcp-text); padding: .35rem .65rem; }
182
+ .uhcp-profile-target-badges-centered { justify-content: center; }
183
+ .uhcp-profile-target-badges li { background: linear-gradient(135deg, var(--uhcp-selected-start), var(--uhcp-selected-end)); border: 1px solid transparent; border-radius: 999px; color: #fff; padding: .35rem .65rem; }
184
+ .uhcp-profile-gate .uhcp-action-unlock { background: linear-gradient(135deg, var(--uhcp-unlock-start), var(--uhcp-unlock-end)); color: var(--uhcp-unlock-text); }
173
185
  .uhcp-profile-target-details { margin: 0; }
174
186
  .uhcp-profile-target-details > div { display: grid; gap: .2rem; grid-template-columns: minmax(8rem, auto) 1fr; }
175
187
  .uhcp-profile-target-details dt { color: var(--uhcp-muted); }
@@ -178,7 +190,7 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
178
190
  .uhcp-profile-pin-fallback summary { color: var(--uhcp-text); cursor: pointer; font-weight: 700; }
179
191
  .uhcp-profile-pin-fallback form { margin-top: .8rem; }
180
192
  .uhcp-profile-pin-recovery { display: flex; justify-content: flex-start; margin-top: .7rem; }
181
- .uhcp-profile-pin-recovery button { background: transparent; border: 1px solid var(--uhcp-border); color: var(--uhcp-text); }
193
+ .uhcp-profile-pin-recovery button { background: var(--uhcp-alternative); border: 1px solid color-mix(in srgb, var(--uhcp-attention) 48%, var(--uhcp-border)); color: var(--uhcp-text); }
182
194
  .uhcp-profile-gate-secondary { border-top: 1px solid var(--uhcp-border); display: grid; gap: .6rem; padding-top: .8rem; }
183
195
  .uhcp-profile-gate-secondary .uhcp-add-profile-action { align-items: center; background: transparent; border: 1px solid color-mix(in srgb, var(--uhcp-turquoise) 35%, var(--uhcp-border)); color: var(--uhcp-text); display: inline-flex; gap: .65rem; justify-content: flex-start; }
184
196
  .uhcp-profile-gate-secondary .uhcp-add-profile-action::first-letter { color: var(--uhcp-turquoise); font-size: 1.25em; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uhc-portal-components-react",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
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",