uhc-portal-components-react 0.2.14 → 0.2.15
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 +6 -0
- package/README.md +8 -0
- package/dist/AnimalCardArtifact.d.ts +23 -0
- package/dist/AnimalCardArtifact.d.ts.map +1 -1
- package/dist/AnimalCardArtifact.js +19 -0
- package/dist/styles.css +24 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
- Add the shared two-sided SOSCHAIN Smart Identity Card artifact. Face A keeps
|
|
6
|
+
a DID-only QR and localized subject label; face B formats the seven-digit
|
|
7
|
+
animal species context and 21-digit telephone identifier and renders an
|
|
8
|
+
SHC-like identity QR only when the owning provider supplies it already
|
|
9
|
+
signed.
|
|
10
|
+
|
|
5
11
|
## 0.2.14 - 2026-10-15
|
|
6
12
|
|
|
7
13
|
- Compose the existing coded-concept V2 field from the neutral
|
package/README.md
CHANGED
|
@@ -197,3 +197,11 @@ route destinations; it must not fork shared flow or authorization behavior.
|
|
|
197
197
|
See [`docs/PERSONAL_FLOW_EXTRACTION.md`](docs/PERSONAL_FLOW_EXTRACTION.md) and
|
|
198
198
|
the canonical cross-portal
|
|
199
199
|
[`docs/HISTORICAL_PORTAL_COMPONENT_RECOVERY_MATRIX.md`](docs/HISTORICAL_PORTAL_COMPONENT_RECOVERY_MATRIX.md).
|
|
200
|
+
### Two-sided SOSCHAIN identity card
|
|
201
|
+
|
|
202
|
+
`SoschainSmartIdentityCardArtifact` renders the common printable card used by
|
|
203
|
+
SOSChain, PetChain and VetChain. The host supplies both QR nodes: face A must
|
|
204
|
+
encode only the canonical card `did:web`; face B may encode only an already
|
|
205
|
+
signed provider-issued identity credential. Presentation code never issues or
|
|
206
|
+
signs the credential. When no signed value is available, the reverse side
|
|
207
|
+
fails closed with an explicit unavailable state.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
1
2
|
export type AnimalCardArtifactProps = Readonly<{
|
|
2
3
|
brand: string;
|
|
3
4
|
title: string;
|
|
@@ -14,4 +15,26 @@ export type AnimalCardArtifactProps = Readonly<{
|
|
|
14
15
|
* identifiers and QR payload; this component neither issues nor verifies them.
|
|
15
16
|
*/
|
|
16
17
|
export declare function AnimalCardArtifact({ brand, title, provider, subject, species, cardNumber, cardDid, qrImageUrl, logoUrl, }: AnimalCardArtifactProps): import("react").JSX.Element;
|
|
18
|
+
export type SoschainSmartIdentityCardArtifactProps = Readonly<{
|
|
19
|
+
/** Human cards use the fixed public label `Personal`; animal cards use the supplied localized species label. */
|
|
20
|
+
subjectKind?: 'animal' | 'personal';
|
|
21
|
+
subjectLabel?: string;
|
|
22
|
+
cardDid: string;
|
|
23
|
+
speciesId7?: string;
|
|
24
|
+
cardNumber21?: string;
|
|
25
|
+
/** Host-rendered QR whose exact payload is `cardDid`. */
|
|
26
|
+
didQr: ReactNode;
|
|
27
|
+
/** Host-rendered QR from a provider-issued, signed SHC-like identity credential. */
|
|
28
|
+
identityQr?: ReactNode;
|
|
29
|
+
logoUrl: string;
|
|
30
|
+
signedIdentityUnavailableLabel?: string;
|
|
31
|
+
}>;
|
|
32
|
+
/** Formats the canonical 21 digits for visual and telephone readback only. */
|
|
33
|
+
export declare function formatSoschainCardNumber21(value: string): string;
|
|
34
|
+
/**
|
|
35
|
+
* Two-sided physical identity artifact shared by SOSChain, PetChain and
|
|
36
|
+
* VetChain. The host owns both QR payloads. Face A is deliberately DID-only;
|
|
37
|
+
* face B never invents or signs a credential in presentation code.
|
|
38
|
+
*/
|
|
39
|
+
export declare function SoschainSmartIdentityCardArtifact({ subjectKind, subjectLabel, cardDid, speciesId7, cardNumber21, didQr, identityQr, logoUrl, signedIdentityUnavailableLabel, }: SoschainSmartIdentityCardArtifactProps): import("react").JSX.Element;
|
|
17
40
|
//# sourceMappingURL=AnimalCardArtifact.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnimalCardArtifact.d.ts","sourceRoot":"","sources":["../src/AnimalCardArtifact.tsx"],"names":[],"mappings":"AAAA,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"}
|
|
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,+BA+BxC"}
|
|
@@ -6,3 +6,22 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
6
6
|
export function AnimalCardArtifact({ brand, title, provider, subject, species, cardNumber, cardDid, qrImageUrl, logoUrl, }) {
|
|
7
7
|
return _jsxs("article", { className: "uhcp-animal-card", "aria-label": `${title}: ${subject}`, children: [_jsxs("header", { className: "uhcp-animal-card-header", children: [_jsxs("div", { className: "uhcp-animal-card-brand", children: [logoUrl ? _jsx("img", { src: logoUrl, alt: "" }) : _jsx("span", { "aria-hidden": "true", children: "V" }), _jsxs("div", { children: [_jsx("strong", { children: brand }), _jsx("small", { children: title })] })] }), _jsx("span", { className: "uhcp-animal-card-chip", "aria-hidden": "true" })] }), _jsxs("div", { className: "uhcp-animal-card-body", children: [_jsxs("section", { children: [_jsx("span", { children: species }), _jsx("h3", { children: subject }), _jsxs("dl", { children: [_jsxs("div", { children: [_jsx("dt", { children: "Card" }), _jsx("dd", { children: cardNumber })] }), _jsxs("div", { children: [_jsx("dt", { children: "Provider" }), _jsx("dd", { children: provider })] })] })] }), _jsx("img", { className: "uhcp-animal-card-qr", src: qrImageUrl, alt: `${title} QR` })] }), _jsx("footer", { children: _jsx("code", { children: cardDid }) })] });
|
|
8
8
|
}
|
|
9
|
+
/** Formats the canonical 21 digits for visual and telephone readback only. */
|
|
10
|
+
export function formatSoschainCardNumber21(value) {
|
|
11
|
+
const digits = String(value || '').replace(/[ -]/g, '');
|
|
12
|
+
if (!/^\d{21}$/.test(digits))
|
|
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)}`;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Two-sided physical identity artifact shared by SOSChain, PetChain and
|
|
18
|
+
* VetChain. The host owns both QR payloads. Face A is deliberately DID-only;
|
|
19
|
+
* face B never invents or signs a credential in presentation code.
|
|
20
|
+
*/
|
|
21
|
+
export function SoschainSmartIdentityCardArtifact({ subjectKind = 'animal', subjectLabel, cardDid, speciesId7, cardNumber21, didQr, identityQr, logoUrl, signedIdentityUnavailableLabel = 'Signed identity unavailable', }) {
|
|
22
|
+
const publicLabel = subjectKind === 'personal' ? 'Personal' : String(subjectLabel || 'Animal').trim();
|
|
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 }), _jsx("code", { children: cardDid })] }), _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
|
|
25
|
+
? _jsx("div", { className: "uhcp-smart-id-identity-qr", "aria-label": "Signed identity QR code", children: identityQr })
|
|
26
|
+
: _jsx("p", { className: "uhcp-smart-id-unavailable", role: "status", children: signedIdentityUnavailableLabel })] })] })] });
|
|
27
|
+
}
|
package/dist/styles.css
CHANGED
|
@@ -833,6 +833,30 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
|
|
|
833
833
|
.uhcp-animal-card footer { min-width: 0; }
|
|
834
834
|
.uhcp-animal-card footer code { color: inherit; display: block; font-size: .68rem; opacity: .8; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
835
835
|
@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%, 33.7rem); }
|
|
837
|
+
.uhcp-smart-id-card { aspect-ratio: 1.586; 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: .35rem; grid-template-rows: auto 1fr auto; }
|
|
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; background: #fff; border: .35rem solid #fff; border-radius: .55rem; box-sizing: border-box; height: 7rem; justify-self: center; width: 7rem; }
|
|
845
|
+
.uhcp-smart-id-front-qr > * { display: block; height: 100%; width: 100%; }
|
|
846
|
+
.uhcp-smart-id-card-front code { color: inherit; display: block; font-size: .5rem; opacity: .82; overflow: hidden; text-align: center; text-overflow: ellipsis; white-space: nowrap; }
|
|
847
|
+
.uhcp-smart-id-card-back { background: #fff; color: #0f2942; display: grid; gap: .5rem; grid-template-rows: auto 1fr; }
|
|
848
|
+
.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; }
|
|
849
|
+
.uhcp-smart-id-card-back > header strong { font-size: .68rem; letter-spacing: .08em; }
|
|
850
|
+
.uhcp-smart-id-card-back > header span { color: #087f8d; font-size: .68rem; font-weight: 850; text-align: end; }
|
|
851
|
+
.uhcp-smart-id-back-body { align-items: center; display: grid; gap: .65rem; grid-template-columns: minmax(0, 1fr) 7rem; min-height: 0; }
|
|
852
|
+
.uhcp-smart-id-back-body dl { display: grid; gap: .5rem; margin: 0; }
|
|
853
|
+
.uhcp-smart-id-back-body dt { color: #526174; font-size: .55rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
|
|
854
|
+
.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; }
|
|
855
|
+
.uhcp-smart-id-identity-qr { background: #fff; box-sizing: border-box; height: 7rem; width: 7rem; }
|
|
856
|
+
.uhcp-smart-id-identity-qr > * { display: block; height: 100%; width: 100%; }
|
|
857
|
+
.uhcp-smart-id-unavailable { align-items: center; background: #f1f5f9; border: 1px dashed #94a3b8; border-radius: .6rem; box-sizing: border-box; color: #526174; display: flex; font-size: .62rem; height: 7rem; justify-content: center; margin: 0; padding: .4rem; text-align: center; width: 7rem; }
|
|
858
|
+
@media(max-width: 480px) { .uhcp-smart-id-back-body { grid-template-columns: 1fr 6.5rem; } .uhcp-smart-id-identity-qr, .uhcp-smart-id-unavailable { height: 6.5rem; width: 6.5rem; } }
|
|
859
|
+
@media print { .uhcp-smart-id-card-set { gap: 0; } .uhcp-smart-id-card { break-after: page; box-shadow: none; height: 53.98mm; width: 85.6mm; } .uhcp-smart-id-card:last-child { break-after: auto; } }
|
|
836
860
|
.uhcp-animal-controller-attestation { border: 1px solid var(--uhcp-border, #d9dee7); border-radius: 1.25rem; display: grid; gap: 1rem; padding: 1rem; }
|
|
837
861
|
.uhcp-animal-controller-attestation header h2, .uhcp-animal-controller-attestation header p { margin: 0; }
|
|
838
862
|
.uhcp-animal-controller-attestation header p { color: var(--uhcp-muted, #5f6875); margin-top: .35rem; }
|
package/package.json
CHANGED