uhc-portal-components-react 0.2.16 → 0.2.18

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,14 +2,22 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ - Require confirmation for employee suspension, reactivation and permanent
6
+ deletion; expose only valid lifecycle actions and distinguish warning,
7
+ constructive and destructive actions with yellow, blue and red treatments.
5
8
  - Add the shared two-sided SOSCHAIN Smart Identity Card artifact. Face A keeps
6
9
  a DID-only QR and localized subject label; face B formats the seven-digit
7
10
  animal species context and 21-digit telephone identifier and renders an
8
11
  SHC-like identity QR only when the owning provider supplies it already
9
12
  signed.
10
- - Print both faces vertically at 50 x 80 mm, enlarge each QR to the usable
11
- card width and remove the unreadable printed DID while preserving it as the
12
- exact face-A QR payload.
13
+ - Print both faces vertically at 50 x 80 mm and remove the unreadable printed
14
+ DID while preserving it as the exact face-A QR payload.
15
+ - Present both physical faces side by side whenever the screen has room and
16
+ collapse them to one column only on narrow viewports. Use a white face A,
17
+ one larger SOSCHAIN logo, a compact DID QR, the subject label below it and
18
+ the provider code needed for manual recovery.
19
+ - Keep the reverse free of repeated subject text and format the indivisible
20
+ 21-digit telephone identifier as `4 4 4 4 5` without line wrapping.
13
21
 
14
22
  ## 0.2.14 - 2026-10-15
15
23
 
package/README.md CHANGED
@@ -205,5 +205,9 @@ encode only the canonical card `did:web`; face B may encode only an already
205
205
  signed provider-issued identity credential. Presentation code never issues or
206
206
  signs the credential. When no signed value is available, the reverse side
207
207
  fails closed with an explicit unavailable state. Both faces use the vertical
208
- 50 x 80 mm label format. The QR fills the usable width; the long `did:web` is
209
- not repeated as unreadable microtext.
208
+ 50 x 80 mm label format and appear side by side when the viewport permits.
209
+ Face A uses the supplied SOSCHAIN logo without duplicating its wordmark,
210
+ prints the provider code for manual recovery, and keeps the DID QR compact;
211
+ the long `did:web` is not repeated as unreadable microtext. Face B does not
212
+ repeat the localized subject label and keeps the 21 digits together in
213
+ telephone groups of `4 4 4 4 5`.
@@ -20,6 +20,8 @@ export type SoschainSmartIdentityCardArtifactProps = Readonly<{
20
20
  subjectKind?: 'animal' | 'personal';
21
21
  subjectLabel?: string;
22
22
  cardDid: string;
23
+ /** Nine-digit public provider code printed for manual recovery when the DID QR cannot be read. */
24
+ providerCode?: string;
23
25
  speciesId7?: string;
24
26
  cardNumber21?: string;
25
27
  /** Host-rendered QR whose exact payload is `cardDid`. */
@@ -36,5 +38,5 @@ export declare function formatSoschainCardNumber21(value: string): string;
36
38
  * VetChain. The host owns both QR payloads. Face A is deliberately DID-only;
37
39
  * face B never invents or signs a credential in presentation code.
38
40
  */
39
- export declare function SoschainSmartIdentityCardArtifact({ subjectKind, subjectLabel, cardDid, speciesId7, cardNumber21, didQr, identityQr, logoUrl, signedIdentityUnavailableLabel, }: SoschainSmartIdentityCardArtifactProps): import("react").JSX.Element;
41
+ export declare function SoschainSmartIdentityCardArtifact({ subjectKind, subjectLabel, cardDid, providerCode, speciesId7, cardNumber21, didQr, identityQr, logoUrl, signedIdentityUnavailableLabel, }: SoschainSmartIdentityCardArtifactProps): import("react").JSX.Element;
40
42
  //# sourceMappingURL=AnimalCardArtifact.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"AnimalCardArtifact.d.ts","sourceRoot":"","sources":["../src/AnimalCardArtifact.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAC7C,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAC,CAAA;AAEF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,KAAK,EACL,QAAQ,EACR,OAAO,EACP,OAAO,EACP,UAAU,EACV,OAAO,EACP,UAAU,EACV,OAAO,GACR,EAAE,uBAAuB,+BAsBzB;AAED,MAAM,MAAM,sCAAsC,GAAG,QAAQ,CAAC;IAC5D,gHAAgH;IAChH,WAAW,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAA;IACnC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,yDAAyD;IACzD,KAAK,EAAE,SAAS,CAAA;IAChB,oFAAoF;IACpF,UAAU,CAAC,EAAE,SAAS,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,8BAA8B,CAAC,EAAE,MAAM,CAAA;CACxC,CAAC,CAAA;AAEF,8EAA8E;AAC9E,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIhE;AAED;;;;GAIG;AACH,wBAAgB,iCAAiC,CAAC,EAChD,WAAsB,EACtB,YAAY,EACZ,OAAO,EACP,UAAU,EACV,YAAY,EACZ,KAAK,EACL,UAAU,EACV,OAAO,EACP,8BAA8D,GAC/D,EAAE,sCAAsC,+BA8BxC"}
1
+ {"version":3,"file":"AnimalCardArtifact.d.ts","sourceRoot":"","sources":["../src/AnimalCardArtifact.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAC7C,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAC,CAAA;AAEF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,KAAK,EACL,QAAQ,EACR,OAAO,EACP,OAAO,EACP,UAAU,EACV,OAAO,EACP,UAAU,EACV,OAAO,GACR,EAAE,uBAAuB,+BAsBzB;AAED,MAAM,MAAM,sCAAsC,GAAG,QAAQ,CAAC;IAC5D,gHAAgH;IAChH,WAAW,CAAC,EAAE,QAAQ,GAAG,UAAU,CAAA;IACnC,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,kGAAkG;IAClG,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,yDAAyD;IACzD,KAAK,EAAE,SAAS,CAAA;IAChB,oFAAoF;IACpF,UAAU,CAAC,EAAE,SAAS,CAAA;IACtB,OAAO,EAAE,MAAM,CAAA;IACf,8BAA8B,CAAC,EAAE,MAAM,CAAA;CACxC,CAAC,CAAA;AAEF,8EAA8E;AAC9E,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAIhE;AAED;;;;GAIG;AACH,wBAAgB,iCAAiC,CAAC,EAChD,WAAsB,EACtB,YAAY,EACZ,OAAO,EACP,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,KAAK,EACL,UAAU,EACV,OAAO,EACP,8BAA8D,GAC/D,EAAE,sCAAsC,+BAsCxC"}
@@ -11,17 +11,21 @@ export function formatSoschainCardNumber21(value) {
11
11
  const digits = String(value || '').replace(/[ -]/g, '');
12
12
  if (!/^\d{21}$/.test(digits))
13
13
  throw new TypeError('cardNumber21 must contain exactly 21 digits.');
14
- return `${digits.slice(0, 5)} ${digits.slice(5, 10)} ${digits.slice(10, 15)} ${digits.slice(15, 20)} ${digits.slice(20)}`;
14
+ return `${digits.slice(0, 4)} ${digits.slice(4, 8)} ${digits.slice(8, 12)} ${digits.slice(12, 16)} ${digits.slice(16)}`;
15
15
  }
16
16
  /**
17
17
  * Two-sided physical identity artifact shared by SOSChain, PetChain and
18
18
  * VetChain. The host owns both QR payloads. Face A is deliberately DID-only;
19
19
  * face B never invents or signs a credential in presentation code.
20
20
  */
21
- export function SoschainSmartIdentityCardArtifact({ subjectKind = 'animal', subjectLabel, cardDid, speciesId7, cardNumber21, didQr, identityQr, logoUrl, signedIdentityUnavailableLabel = 'Signed identity unavailable', }) {
21
+ export function SoschainSmartIdentityCardArtifact({ subjectKind = 'animal', subjectLabel, cardDid, providerCode, speciesId7, cardNumber21, didQr, identityQr, logoUrl, signedIdentityUnavailableLabel = 'Signed identity unavailable', }) {
22
22
  const publicLabel = subjectKind === 'personal' ? 'Personal' : String(subjectLabel || 'Animal').trim();
23
23
  const formattedCardNumber = cardNumber21 ? formatSoschainCardNumber21(cardNumber21) : undefined;
24
- return _jsxs("div", { className: "uhcp-smart-id-card-set", "aria-label": `SOSCHAIN Smart Identity Card: ${publicLabel}`, children: [_jsxs("article", { className: "uhcp-smart-id-card uhcp-smart-id-card-front", "data-card-face": "front", children: [_jsxs("header", { className: "uhcp-smart-id-brand", children: [_jsx("img", { src: logoUrl, alt: "" }), _jsx("strong", { children: "SOSCHAIN" }), _jsx("span", { children: publicLabel })] }), _jsx("div", { className: "uhcp-smart-id-front-qr", "aria-label": "DID QR code", children: didQr })] }), _jsxs("article", { className: "uhcp-smart-id-card uhcp-smart-id-card-back", "data-card-face": "back", children: [_jsxs("header", { children: [_jsx("strong", { children: "SOSCHAIN SMART IDENTITY CARD" }), _jsx("span", { children: publicLabel })] }), _jsxs("div", { className: "uhcp-smart-id-back-body", children: [_jsxs("dl", { children: [speciesId7 ? _jsxs("div", { children: [_jsx("dt", { children: "Species" }), _jsx("dd", { children: speciesId7 })] }) : null, formattedCardNumber ? _jsxs("div", { children: [_jsx("dt", { children: "Card" }), _jsx("dd", { children: formattedCardNumber })] }) : null] }), identityQr
24
+ const normalizedProviderCode = providerCode ? String(providerCode).replace(/[ -]/g, '') : undefined;
25
+ if (normalizedProviderCode && !/^\d{9}$/.test(normalizedProviderCode)) {
26
+ throw new TypeError('providerCode must contain exactly 9 digits.');
27
+ }
28
+ return _jsxs("div", { className: "uhcp-smart-id-card-set", "aria-label": `SOSCHAIN Smart Identity Card: ${publicLabel}`, children: [_jsxs("article", { className: "uhcp-smart-id-card uhcp-smart-id-card-front", "data-card-face": "front", children: [_jsx("header", { className: "uhcp-smart-id-brand", children: _jsx("img", { src: logoUrl, alt: "SOSCHAIN" }) }), _jsxs("div", { className: "uhcp-smart-id-front-body", children: [_jsx("div", { className: "uhcp-smart-id-front-qr", "aria-label": "DID QR code", children: didQr }), _jsx("p", { className: "uhcp-smart-id-subject-label", children: publicLabel })] }), normalizedProviderCode ? _jsxs("footer", { children: [_jsx("span", { children: "Provider" }), _jsx("p", { className: "uhcp-smart-id-provider-code", children: normalizedProviderCode })] }) : null] }), _jsxs("article", { className: "uhcp-smart-id-card uhcp-smart-id-card-back", "data-card-face": "back", children: [_jsx("header", { children: _jsx("strong", { children: "SOSCHAIN SMART IDENTITY CARD" }) }), _jsxs("div", { className: "uhcp-smart-id-back-body", children: [_jsxs("dl", { children: [speciesId7 ? _jsxs("div", { children: [_jsx("dt", { children: "Species" }), _jsx("dd", { children: speciesId7 })] }) : null, formattedCardNumber ? _jsxs("div", { children: [_jsx("dt", { children: "Card" }), _jsx("dd", { children: formattedCardNumber })] }) : null] }), identityQr
25
29
  ? _jsx("div", { className: "uhcp-smart-id-identity-qr", "aria-label": "Signed identity QR code", children: identityQr })
26
30
  : _jsx("p", { className: "uhcp-smart-id-unavailable", role: "status", children: signedIdentityUnavailableLabel })] })] })] });
27
31
  }
@@ -51,7 +51,11 @@ export type OrganizationWorkforceCopy = Readonly<{
51
51
  accepted: string;
52
52
  cancelled: string;
53
53
  disable: string;
54
+ reactivate: string;
54
55
  purge: string;
56
+ confirmDisable: string;
57
+ confirmReactivate: string;
58
+ confirmPurge: string;
55
59
  devicesLater: string;
56
60
  }>;
57
61
  export type OrganizationWorkforceAdministrationProps = Readonly<{
@@ -70,6 +74,7 @@ export type OrganizationWorkforceAdministrationProps = Readonly<{
70
74
  onUnlockSecretChange: (value: string) => void;
71
75
  onInvite: () => void | Promise<void>;
72
76
  onDisable: (employeeId: string) => void | Promise<void>;
77
+ onReactivate: (employeeId: string) => void | Promise<void>;
73
78
  onPurge: (employeeId: string) => void | Promise<void>;
74
79
  }>;
75
80
  /**
@@ -78,5 +83,5 @@ export type OrganizationWorkforceAdministrationProps = Readonly<{
78
83
  * The component never infers authorization or changes GW state. The host owns
79
84
  * invitation persistence, license reads and employee lifecycle commands.
80
85
  */
81
- export declare function OrganizationWorkforceAdministration({ copy, summary, employees, invitations, roles, email, role, unlockSecret, busyAction, error, onEmailChange, onRoleChange, onUnlockSecretChange, onInvite, onDisable, onPurge, }: OrganizationWorkforceAdministrationProps): import("react").JSX.Element;
86
+ export declare function OrganizationWorkforceAdministration({ copy, summary, employees, invitations, roles, email, role, unlockSecret, busyAction, error, onEmailChange, onRoleChange, onUnlockSecretChange, onInvite, onDisable, onReactivate, onPurge, }: OrganizationWorkforceAdministrationProps): import("react").JSX.Element;
82
87
  //# sourceMappingURL=OrganizationWorkforceAdministration.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"OrganizationWorkforceAdministration.d.ts","sourceRoot":"","sources":["../src/OrganizationWorkforceAdministration.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"OrganizationWorkforceAdministration.d.ts","sourceRoot":"","sources":["../src/OrganizationWorkforceAdministration.tsx"],"names":[],"mappings":"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"}
@@ -1,11 +1,11 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  /**
3
3
  * Controlled organization workforce surface shared by professional portals.
4
4
  *
5
5
  * The component never infers authorization or changes GW state. The host owns
6
6
  * invitation persistence, license reads and employee lifecycle commands.
7
7
  */
8
- export function OrganizationWorkforceAdministration({ copy, summary, employees, invitations, roles, email, role, unlockSecret, busyAction, error, onEmailChange, onRoleChange, onUnlockSecretChange, onInvite, onDisable, onPurge, }) {
8
+ export function OrganizationWorkforceAdministration({ copy, summary, employees, invitations, roles, email, role, unlockSecret, busyAction, error, onEmailChange, onRoleChange, onUnlockSecretChange, onInvite, onDisable, onReactivate, onPurge, }) {
9
9
  const noCapacity = summary.free < 1;
10
10
  const inviting = busyAction === 'invite';
11
11
  const canInvite = !noCapacity && !inviting && Boolean(email.trim() && role && unlockSecret);
@@ -14,8 +14,12 @@ export function OrganizationWorkforceAdministration({ copy, summary, employees,
14
14
  if (canInvite)
15
15
  void onInvite();
16
16
  }
17
+ function confirmAction(message, action) {
18
+ if (window.confirm(message))
19
+ void action();
20
+ }
17
21
  return (_jsxs("section", { className: "uhcp-workforce", "aria-labelledby": "uhcp-workforce-title", children: [_jsxs("header", { children: [_jsxs("div", { children: [_jsx("h1", { id: "uhcp-workforce-title", children: copy.title }), _jsx("p", { children: copy.description })] }), _jsxs("dl", { className: "uhcp-license-summary", children: [_jsxs("div", { children: [_jsx("dt", { children: copy.totalLicenses }), _jsx("dd", { children: summary.total })] }), _jsxs("div", { children: [_jsx("dt", { children: copy.usedLicenses }), _jsx("dd", { children: summary.used })] }), _jsxs("div", { children: [_jsx("dt", { children: copy.freeLicenses }), _jsx("dd", { children: summary.free })] })] })] }), _jsxs("section", { className: "uhcp-workforce-panel", "aria-labelledby": "uhcp-invite-title", children: [_jsx("h2", { id: "uhcp-invite-title", children: copy.inviteTitle }), noCapacity && _jsx("p", { role: "status", className: "uhcp-workforce-warning", children: copy.noFreeLicenses }), _jsxs("form", { onSubmit: submitInvitation, children: [_jsxs("label", { children: [_jsx("span", { children: copy.emailLabel }), _jsx("input", { type: "email", required: true, value: email, onChange: (event) => onEmailChange(event.currentTarget.value) })] }), _jsxs("label", { children: [_jsx("span", { children: copy.roleLabel }), _jsxs("select", { required: true, value: role, onChange: (event) => onRoleChange(event.currentTarget.value), children: [_jsx("option", { value: "" }), roles.map((option) => _jsx("option", { value: option.value, children: option.label }, option.value))] })] }), _jsxs("label", { children: [_jsx("span", { children: copy.unlockSecretLabel }), _jsx("input", { type: "password", required: true, value: unlockSecret, onChange: (event) => onUnlockSecretChange(event.currentTarget.value) })] }), _jsx("button", { type: "submit", disabled: !canInvite, children: inviting ? copy.inviting : copy.invite })] })] }), _jsxs("section", { className: "uhcp-workforce-panel", "aria-labelledby": "uhcp-employees-title", children: [_jsx("h2", { id: "uhcp-employees-title", children: copy.employeesTitle }), employees.length === 0 ? _jsx("p", { children: copy.noEmployees }) : (_jsx("div", { className: "uhcp-table-scroll", children: _jsxs("table", { children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: copy.licenseColumn }), _jsx("th", { children: copy.employeeColumn }), _jsx("th", { children: copy.roleColumn }), _jsx("th", { children: copy.statusColumn }), _jsx("th", { children: copy.devicesColumn }), _jsx("th", { children: copy.actionsColumn })] }) }), _jsx("tbody", { children: employees.map((employee) => {
18
22
  const rowBusy = busyAction === employee.id;
19
- return _jsxs("tr", { children: [_jsx("td", { children: _jsx("code", { children: employee.licenseId }) }), _jsx("td", { children: employee.email }), _jsx("td", { children: employee.role }), _jsx("td", { children: _jsx("span", { className: `uhcp-status uhcp-status-${employee.status}`, children: employee.status === 'active' ? copy.active : copy.inactive }) }), _jsx("td", { children: employee.deviceCount === undefined ? copy.devicesLater : employee.deviceCount }), _jsxs("td", { className: "uhcp-row-actions", children: [_jsx("button", { type: "button", disabled: rowBusy || employee.status !== 'active', onClick: () => void onDisable(employee.id), children: copy.disable }), _jsx("button", { type: "button", className: "uhcp-danger", disabled: rowBusy || employee.status !== 'inactive', onClick: () => void onPurge(employee.id), children: copy.purge })] })] }, employee.id);
23
+ return _jsxs("tr", { children: [_jsx("td", { children: _jsx("code", { children: employee.licenseId }) }), _jsx("td", { children: employee.email }), _jsx("td", { children: employee.role }), _jsx("td", { children: _jsx("span", { className: `uhcp-status uhcp-status-${employee.status}`, children: employee.status === 'active' ? copy.active : copy.inactive }) }), _jsx("td", { children: employee.deviceCount === undefined ? copy.devicesLater : employee.deviceCount }), _jsx("td", { className: "uhcp-row-actions", children: employee.status === 'active' ? (_jsx("button", { type: "button", className: "uhcp-warning-action", disabled: rowBusy, onClick: () => confirmAction(copy.confirmDisable, () => onDisable(employee.id)), children: copy.disable })) : (_jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: "uhcp-primary-action", disabled: rowBusy, onClick: () => confirmAction(copy.confirmReactivate, () => onReactivate(employee.id)), children: copy.reactivate }), _jsx("button", { type: "button", className: "uhcp-danger", disabled: rowBusy, onClick: () => confirmAction(copy.confirmPurge, () => onPurge(employee.id)), children: copy.purge })] })) })] }, employee.id);
20
24
  }) })] }) }))] }), _jsxs("section", { className: "uhcp-workforce-panel", "aria-labelledby": "uhcp-invitations-title", children: [_jsx("h2", { id: "uhcp-invitations-title", children: copy.invitationsTitle }), invitations.length === 0 ? _jsx("p", { children: copy.noInvitations }) : _jsx("ul", { className: "uhcp-invitation-list", children: invitations.map((invitation) => _jsxs("li", { children: [_jsxs("span", { children: [_jsx("strong", { children: invitation.email }), _jsx("small", { children: invitation.role })] }), _jsx("span", { className: `uhcp-status uhcp-status-${invitation.status}`, children: copy[invitation.status] })] }, invitation.id)) })] }), error && _jsx("p", { role: "alert", className: "uhcp-error", children: error })] }));
21
25
  }
package/dist/styles.css CHANGED
@@ -645,6 +645,8 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
645
645
  .uhcp-workforce-panel input, .uhcp-workforce-panel select { background: var(--uhcp-panel); border: 1px solid var(--uhcp-border); border-radius: .75rem; color: var(--uhcp-text); font: inherit; min-width: 0; padding: .75rem; }
646
646
  .uhcp-workforce 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: .75rem 1rem; }
647
647
  .uhcp-workforce button:disabled { cursor: not-allowed; opacity: .45; }
648
+ .uhcp-workforce button.uhcp-warning-action { background: #facc15; color: #422006; }
649
+ .uhcp-workforce button.uhcp-primary-action { background: #2563eb; color: #fff; }
648
650
  .uhcp-workforce button.uhcp-danger { background: #9e3535; }
649
651
  .uhcp-workforce-warning { color: var(--uhcp-attention) !important; font-weight: 800; }
650
652
  .uhcp-table-scroll { overflow-x: auto; }
@@ -833,28 +835,30 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
833
835
  .uhcp-animal-card footer { min-width: 0; }
834
836
  .uhcp-animal-card footer code { color: inherit; display: block; font-size: .68rem; opacity: .8; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
835
837
  @media(max-width: 480px) { .uhcp-animal-card { aspect-ratio: auto; min-height: 17rem; } .uhcp-animal-card-qr { height: 6.25rem; width: 6.25rem; } }
836
- .uhcp-smart-id-card-set { display: grid; gap: 1rem; width: min(100%, 19rem); }
837
- .uhcp-smart-id-card { aspect-ratio: 5 / 8; border: 1px solid #cbd5e1; border-radius: 1.15rem; box-shadow: 0 1rem 2.5rem rgb(2 30 51 / 18%); box-sizing: border-box; overflow: hidden; padding: .75rem; position: relative; width: 100%; }
838
- .uhcp-smart-id-card-front { background: linear-gradient(145deg, #061c35 0%, #0a4169 58%, #087f8d 100%); color: #fff; display: grid; gap: .75rem; grid-template-rows: auto 1fr; }
839
- .uhcp-smart-id-card-front::after { background: radial-gradient(circle, rgb(255 255 255 / 16%), transparent 70%); content: ''; height: 18rem; inset: -8rem -7rem auto auto; pointer-events: none; position: absolute; width: 18rem; }
840
- .uhcp-smart-id-brand { align-items: center; display: grid; gap: .45rem; grid-template-columns: 2rem auto 1fr; position: relative; z-index: 1; }
841
- .uhcp-smart-id-brand img { background: #fff; border-radius: .48rem; box-sizing: border-box; height: 2rem; object-fit: contain; padding: .16rem; width: 2rem; }
842
- .uhcp-smart-id-brand strong { font-size: .85rem; letter-spacing: .08em; }
843
- .uhcp-smart-id-brand span { font-size: .72rem; font-weight: 800; justify-self: end; text-align: end; }
844
- .uhcp-smart-id-front-qr { align-self: center; aspect-ratio: 1; background: #fff; border: .35rem solid #fff; border-radius: .7rem; box-sizing: border-box; justify-self: center; width: calc(100% - .5rem); }
838
+ .uhcp-smart-id-card-set { display: grid; gap: 1rem; grid-template-columns: repeat(2, minmax(0, 19rem)); width: min(100%, 39rem); }
839
+ .uhcp-smart-id-card { aspect-ratio: 5 / 8; border: 1px solid #cbd5e1; border-radius: 1.15rem; box-shadow: 0 .8rem 2rem rgb(15 41 66 / 14%); box-sizing: border-box; font-family: Inter, "Helvetica Neue", Arial, sans-serif; line-height: 1.2; overflow: hidden; padding: .9rem; position: relative; width: 100%; }
840
+ .uhcp-smart-id-card-front { background: #fff; color: #0f2942; display: grid; gap: .5rem; grid-template-rows: auto 1fr auto; }
841
+ .uhcp-smart-id-brand { align-items: center; display: flex; justify-content: center; min-height: 4.2rem; }
842
+ .uhcp-smart-id-brand img { display: block; height: 3.7rem; object-fit: contain; width: 5.6rem; }
843
+ .uhcp-smart-id-front-body { align-content: center; display: grid; gap: .55rem; justify-items: center; min-height: 0; }
844
+ .uhcp-smart-id-front-qr { aspect-ratio: 1; background: #fff; border: .2rem solid #fff; box-sizing: border-box; width: 68%; }
845
845
  .uhcp-smart-id-front-qr > * { display: block; height: 100%; width: 100%; }
846
+ .uhcp-smart-id-subject-label { color: #0f2942; font-size: 1rem; font-weight: 800; line-height: 1.15; margin: 0; text-align: center; }
847
+ .uhcp-smart-id-card-front > footer { border-top: 1px solid #dbe3eb; display: grid; gap: .12rem; padding-top: .55rem; }
848
+ .uhcp-smart-id-card-front > footer span { color: #526174; font-size: .58rem; font-weight: 750; letter-spacing: .08em; text-transform: uppercase; }
849
+ .uhcp-smart-id-provider-code { font-size: .82rem; font-variant-numeric: tabular-nums; font-weight: 800; letter-spacing: .04em; line-height: 1; margin: 0; white-space: nowrap; }
846
850
  .uhcp-smart-id-card-back { background: #fff; color: #0f2942; display: grid; gap: .5rem; grid-template-rows: auto 1fr; }
847
- .uhcp-smart-id-card-back > header { align-items: baseline; border-bottom: 2px solid #0f9ca8; display: flex; gap: .5rem; justify-content: space-between; padding-bottom: .35rem; }
848
- .uhcp-smart-id-card-back > header strong { font-size: .68rem; letter-spacing: .08em; }
849
- .uhcp-smart-id-card-back > header span { color: #087f8d; font-size: .68rem; font-weight: 850; text-align: end; }
850
- .uhcp-smart-id-back-body { align-items: center; display: grid; gap: .7rem; grid-template-rows: minmax(0, 1fr) auto; min-height: 0; }
851
- .uhcp-smart-id-back-body dl { display: grid; gap: .5rem; margin: 0; order: 2; }
851
+ .uhcp-smart-id-card-back > header { border-bottom: 2px solid #0f9ca8; padding-bottom: .45rem; }
852
+ .uhcp-smart-id-card-back > header strong { font-size: .68rem; letter-spacing: .07em; line-height: 1.15; }
853
+ .uhcp-smart-id-back-body { align-content: start; display: grid; gap: .65rem; grid-template-rows: auto auto; min-height: 0; }
854
+ .uhcp-smart-id-back-body dl { display: grid; gap: .4rem; margin: 0; order: 2; }
852
855
  .uhcp-smart-id-back-body dt { color: #526174; font-size: .55rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
853
- .uhcp-smart-id-back-body dd { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: .72rem; font-weight: 850; margin: .12rem 0 0; overflow-wrap: anywhere; }
854
- .uhcp-smart-id-identity-qr { align-self: center; aspect-ratio: 1; background: #fff; box-sizing: border-box; justify-self: center; order: 1; width: calc(100% - .5rem); }
856
+ .uhcp-smart-id-back-body dd { font-size: .76rem; font-variant-numeric: tabular-nums; font-weight: 800; letter-spacing: .025em; line-height: 1.05; margin: .1rem 0 0; white-space: nowrap; }
857
+ .uhcp-smart-id-identity-qr { aspect-ratio: 1; background: #fff; box-sizing: border-box; justify-self: center; order: 1; width: 82%; }
855
858
  .uhcp-smart-id-identity-qr > * { display: block; height: 100%; width: 100%; }
856
- .uhcp-smart-id-unavailable { align-items: center; align-self: center; aspect-ratio: 1; background: #f1f5f9; border: 1px dashed #94a3b8; border-radius: .7rem; box-sizing: border-box; color: #526174; display: flex; font-size: .72rem; justify-content: center; justify-self: center; margin: 0; order: 1; padding: 1rem; text-align: center; width: calc(100% - .5rem); }
857
- @media print { .uhcp-smart-id-card-set { gap: 0; width: 50mm; } .uhcp-smart-id-card { break-after: page; border-radius: 3mm; box-shadow: none; height: 80mm; padding: 2mm; width: 50mm; } .uhcp-smart-id-front-qr, .uhcp-smart-id-identity-qr, .uhcp-smart-id-unavailable { width: 46mm; } .uhcp-smart-id-card:last-child { break-after: auto; } }
859
+ .uhcp-smart-id-unavailable { background: #f1f5f9; border: 1px dashed #94a3b8; border-radius: .6rem; box-sizing: border-box; color: #526174; font-size: .72rem; line-height: 1.25; margin: 0; order: 1; padding: .7rem; text-align: center; }
860
+ @media (max-width: 40rem) { .uhcp-smart-id-card-set { grid-template-columns: minmax(0, 19rem); width: min(100%, 19rem); } }
861
+ @media print { .uhcp-smart-id-card-set { gap: 0; grid-template-columns: 50mm; width: 50mm; } .uhcp-smart-id-card { break-after: page; border-radius: 3mm; box-shadow: none; height: 80mm; padding: 2.5mm; width: 50mm; } .uhcp-smart-id-front-qr { width: 34mm; } .uhcp-smart-id-identity-qr { width: 42mm; } .uhcp-smart-id-card:last-child { break-after: auto; } }
858
862
  .uhcp-animal-controller-attestation { border: 1px solid var(--uhcp-border, #d9dee7); border-radius: 1.25rem; display: grid; gap: 1rem; padding: 1rem; }
859
863
  .uhcp-animal-controller-attestation header h2, .uhcp-animal-controller-attestation header p { margin: 0; }
860
864
  .uhcp-animal-controller-attestation header p { color: var(--uhcp-muted, #5f6875); margin-top: .35rem; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uhc-portal-components-react",
3
- "version": "0.2.16",
3
+ "version": "0.2.18",
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",