uhc-portal-components-react 0.2.17 → 0.2.19
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 +15 -3
- package/README.md +12 -2
- package/dist/AnimalCardArtifact.d.ts +3 -1
- package/dist/AnimalCardArtifact.d.ts.map +1 -1
- package/dist/AnimalCardArtifact.js +7 -3
- package/dist/CommunicationsWorkspace.d.ts +18 -0
- package/dist/CommunicationsWorkspace.d.ts.map +1 -0
- package/dist/CommunicationsWorkspace.js +12 -0
- package/dist/NotificationComposer.d.ts +49 -0
- package/dist/NotificationComposer.d.ts.map +1 -0
- package/dist/NotificationComposer.js +82 -0
- package/dist/SelectedSubjectWorkspace.d.ts +32 -0
- package/dist/SelectedSubjectWorkspace.d.ts.map +1 -0
- package/dist/SelectedSubjectWorkspace.js +30 -0
- package/dist/SoschainWorkspace.d.ts +3 -1
- package/dist/SoschainWorkspace.d.ts.map +1 -1
- package/dist/SoschainWorkspace.js +2 -2
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/notification-bff-client.d.ts +44 -0
- package/dist/notification-bff-client.d.ts.map +1 -0
- package/dist/notification-bff-client.js +88 -0
- package/dist/styles.css +57 -18
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
- Add one neutral notification composer screen for subject-addressed care
|
|
6
|
+
transitions and public-dataset alerts, with safe Markdown preview and host-
|
|
7
|
+
uploaded image/PDF attachment references.
|
|
8
|
+
- Define independent portal deployments as the supported reuse model while
|
|
9
|
+
requiring versioned complete screens, one typed public BFF path contract and
|
|
10
|
+
one capability manifest across web, mobile, telephone, chat and assistant
|
|
11
|
+
hosts.
|
|
5
12
|
- Require confirmation for employee suspension, reactivation and permanent
|
|
6
13
|
deletion; expose only valid lifecycle actions and distinguish warning,
|
|
7
14
|
constructive and destructive actions with yellow, blue and red treatments.
|
|
@@ -10,9 +17,14 @@
|
|
|
10
17
|
animal species context and 21-digit telephone identifier and renders an
|
|
11
18
|
SHC-like identity QR only when the owning provider supplies it already
|
|
12
19
|
signed.
|
|
13
|
-
- Print both faces vertically at 50 x 80 mm
|
|
14
|
-
|
|
15
|
-
|
|
20
|
+
- Print both faces vertically at 50 x 80 mm and remove the unreadable printed
|
|
21
|
+
DID while preserving it as the exact face-A QR payload.
|
|
22
|
+
- Present both physical faces side by side whenever the screen has room and
|
|
23
|
+
collapse them to one column only on narrow viewports. Use a white face A,
|
|
24
|
+
one larger SOSCHAIN logo, a compact DID QR, the subject label below it and
|
|
25
|
+
the provider code needed for manual recovery.
|
|
26
|
+
- Keep the reverse free of repeated subject text and format the indivisible
|
|
27
|
+
21-digit telephone identifier as `4 4 4 4 5` without line wrapping.
|
|
16
28
|
|
|
17
29
|
## 0.2.14 - 2026-10-15
|
|
18
30
|
|
package/README.md
CHANGED
|
@@ -193,6 +193,12 @@ management, licences, clinical data, care and permissions still live in the
|
|
|
193
193
|
UHC host application and must be extracted behind host-owned adapters. A brand
|
|
194
194
|
adapter may change tokens, logo, product vocabulary, animal-specific forms and
|
|
195
195
|
route destinations; it must not fork shared flow or authorization behavior.
|
|
196
|
+
Independent deployments are expected: reuse means versioned complete screens,
|
|
197
|
+
one typed BFF path contract and one channel-neutral capability manifest, not a
|
|
198
|
+
mandatory shared deployed shell. Telephone and assistant templates consume
|
|
199
|
+
that same manifest and operation client so a subject-domain or jurisdiction
|
|
200
|
+
deployment changes trusted configuration and adapters rather than copying the
|
|
201
|
+
workflow.
|
|
196
202
|
|
|
197
203
|
See [`docs/PERSONAL_FLOW_EXTRACTION.md`](docs/PERSONAL_FLOW_EXTRACTION.md) and
|
|
198
204
|
the canonical cross-portal
|
|
@@ -205,5 +211,9 @@ encode only the canonical card `did:web`; face B may encode only an already
|
|
|
205
211
|
signed provider-issued identity credential. Presentation code never issues or
|
|
206
212
|
signs the credential. When no signed value is available, the reverse side
|
|
207
213
|
fails closed with an explicit unavailable state. Both faces use the vertical
|
|
208
|
-
50 x 80 mm label format
|
|
209
|
-
|
|
214
|
+
50 x 80 mm label format and appear side by side when the viewport permits.
|
|
215
|
+
Face A uses the supplied SOSCHAIN logo without duplicating its wordmark,
|
|
216
|
+
prints the provider code for manual recovery, and keeps the DID QR compact;
|
|
217
|
+
the long `did:web` is not repeated as unreadable microtext. Face B does not
|
|
218
|
+
repeat the localized subject label and keeps the 21 digits together in
|
|
219
|
+
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,+
|
|
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,
|
|
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
|
-
|
|
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
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
export type CommunicationsWorkspaceTopic = Readonly<{
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
content?: ReactNode;
|
|
7
|
+
}>;
|
|
8
|
+
/** Shared personal-portal navigation; hosts provide channel and topic data through their own BFF adapters. */
|
|
9
|
+
export declare function CommunicationsWorkspace(input: Readonly<{
|
|
10
|
+
copy: Readonly<{
|
|
11
|
+
communicationsLabel: string;
|
|
12
|
+
channels: string;
|
|
13
|
+
infoAndAlerts: string;
|
|
14
|
+
}>;
|
|
15
|
+
channels: ReactNode;
|
|
16
|
+
alertTopics: readonly CommunicationsWorkspaceTopic[];
|
|
17
|
+
}>): import("react").JSX.Element;
|
|
18
|
+
//# sourceMappingURL=CommunicationsWorkspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"CommunicationsWorkspace.d.ts","sourceRoot":"","sources":["../src/CommunicationsWorkspace.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAEvD,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,OAAO,CAAC,EAAE,SAAS,CAAA;CACpB,CAAC,CAAA;AAEF,8GAA8G;AAC9G,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,QAAQ,CAAC;IACtD,IAAI,EAAE,QAAQ,CAAC;QAAE,mBAAmB,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACxF,QAAQ,EAAE,SAAS,CAAA;IACnB,WAAW,EAAE,SAAS,4BAA4B,EAAE,CAAA;CACrD,CAAC,+BAmBD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useId, useState } from 'react';
|
|
4
|
+
/** Shared personal-portal navigation; hosts provide channel and topic data through their own BFF adapters. */
|
|
5
|
+
export function CommunicationsWorkspace(input) {
|
|
6
|
+
const id = useId();
|
|
7
|
+
const [section, setSection] = useState('channels');
|
|
8
|
+
const firstEnabledTopic = input.alertTopics.find((topic) => !topic.disabled);
|
|
9
|
+
const [topicId, setTopicId] = useState(firstEnabledTopic?.id ?? '');
|
|
10
|
+
const activeTopic = input.alertTopics.find((topic) => topic.id === topicId && !topic.disabled);
|
|
11
|
+
return _jsxs("section", { className: "uhcp-communications-workspace", children: [_jsxs("div", { role: "tablist", "aria-label": input.copy.communicationsLabel, className: "uhcp-communications-tabs", children: [_jsx("button", { type: "button", role: "tab", "aria-selected": section === 'channels', "aria-controls": `${id}-channels`, onClick: () => setSection('channels'), children: input.copy.channels }), _jsx("button", { type: "button", role: "tab", "aria-selected": section === 'alerts', "aria-controls": `${id}-alerts`, onClick: () => setSection('alerts'), children: input.copy.infoAndAlerts })] }), section === 'channels' ? _jsx("div", { id: `${id}-channels`, role: "tabpanel", children: input.channels }) : _jsxs("div", { id: `${id}-alerts`, role: "tabpanel", children: [_jsx("div", { role: "tablist", "aria-label": input.copy.infoAndAlerts, className: "uhcp-communications-topic-tabs", children: input.alertTopics.map((topic) => _jsx("button", { type: "button", role: "tab", disabled: topic.disabled, "aria-selected": activeTopic?.id === topic.id, onClick: () => setTopicId(topic.id), children: topic.label }, topic.id)) }), activeTopic?.content ? _jsx("div", { role: "tabpanel", children: activeTopic.content }) : null] })] });
|
|
12
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type NotificationAttachment, type NotificationComposerAudience, type NotificationComposerDraft } from 'sos-data-utils-ts/public-notifications';
|
|
2
|
+
export type NotificationComposerAudienceOption = Readonly<{
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
audience: NotificationComposerAudience;
|
|
7
|
+
}>;
|
|
8
|
+
export type NotificationComposerCopy = Readonly<{
|
|
9
|
+
title: string;
|
|
10
|
+
audience: string;
|
|
11
|
+
subject: string;
|
|
12
|
+
bodyMarkdown: string;
|
|
13
|
+
preview: string;
|
|
14
|
+
attachments: string;
|
|
15
|
+
addAttachments: string;
|
|
16
|
+
removeAttachment: string;
|
|
17
|
+
send: string;
|
|
18
|
+
sending: string;
|
|
19
|
+
sent: string;
|
|
20
|
+
unsupportedAttachment: string;
|
|
21
|
+
attachmentUploadFailed: string;
|
|
22
|
+
sendFailed: string;
|
|
23
|
+
priority?: string;
|
|
24
|
+
validUntil?: string;
|
|
25
|
+
}>;
|
|
26
|
+
export type NotificationComposerFormSchema = Readonly<{
|
|
27
|
+
$id: string;
|
|
28
|
+
required: readonly string[];
|
|
29
|
+
properties: Readonly<Record<string, Readonly<{
|
|
30
|
+
type: string;
|
|
31
|
+
enum?: readonly string[];
|
|
32
|
+
maxLength?: number;
|
|
33
|
+
maxItems?: number;
|
|
34
|
+
}>>>;
|
|
35
|
+
}>;
|
|
36
|
+
/**
|
|
37
|
+
* Channel-neutral notification editor. The host supplies BFF-authorized
|
|
38
|
+
* audiences plus upload/send adapters; this component never accepts direct
|
|
39
|
+
* recipient addresses, subscriber lists or publishing authority.
|
|
40
|
+
*/
|
|
41
|
+
export declare function NotificationComposer(input: Readonly<{
|
|
42
|
+
audiences: readonly NotificationComposerAudienceOption[];
|
|
43
|
+
copy: NotificationComposerCopy;
|
|
44
|
+
uploadAttachment(file: File): Promise<NotificationAttachment>;
|
|
45
|
+
onSubmit(draft: NotificationComposerDraft): Promise<void>;
|
|
46
|
+
formSchema?: NotificationComposerFormSchema;
|
|
47
|
+
disabled?: boolean;
|
|
48
|
+
}>): import("react").JSX.Element;
|
|
49
|
+
//# sourceMappingURL=NotificationComposer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NotificationComposer.d.ts","sourceRoot":"","sources":["../src/NotificationComposer.tsx"],"names":[],"mappings":"AAGA,OAAO,EAIL,KAAK,sBAAsB,EAC3B,KAAK,4BAA4B,EACjC,KAAK,yBAAyB,EAE/B,MAAM,wCAAwC,CAAA;AAG/C,MAAM,MAAM,kCAAkC,GAAG,QAAQ,CAAC;IACxD,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,4BAA4B,CAAA;CACvC,CAAC,CAAA;AAEF,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB,gBAAgB,EAAE,MAAM,CAAA;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,qBAAqB,EAAE,MAAM,CAAA;IAC7B,sBAAsB,EAAE,MAAM,CAAA;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAC,CAAA;AAEF,MAAM,MAAM,8BAA8B,GAAG,QAAQ,CAAC;IACpD,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;IAC3B,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC;QAC3C,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;QACxB,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAA;KAClB,CAAC,CAAC,CAAC,CAAA;CACL,CAAC,CAAA;AAEF;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,QAAQ,CAAC;IACnD,SAAS,EAAE,SAAS,kCAAkC,EAAE,CAAA;IACxD,IAAI,EAAE,wBAAwB,CAAA;IAC9B,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,sBAAsB,CAAC,CAAA;IAC7D,QAAQ,CAAC,KAAK,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IACzD,UAAU,CAAC,EAAE,8BAA8B,CAAA;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,CAAC,+BAmKD"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useId, useState } from 'react';
|
|
4
|
+
import { normalizeNotificationComposerDraft, NotificationAttachmentMediaTypes, PublicAlertPriorities, } from 'sos-data-utils-ts/public-notifications';
|
|
5
|
+
import { LegalMarkdownDocument } from './LegalMarkdownDocument.js';
|
|
6
|
+
/**
|
|
7
|
+
* Channel-neutral notification editor. The host supplies BFF-authorized
|
|
8
|
+
* audiences plus upload/send adapters; this component never accepts direct
|
|
9
|
+
* recipient addresses, subscriber lists or publishing authority.
|
|
10
|
+
*/
|
|
11
|
+
export function NotificationComposer(input) {
|
|
12
|
+
const id = useId();
|
|
13
|
+
const [audienceId, setAudienceId] = useState(input.audiences[0]?.id ?? '');
|
|
14
|
+
const [subject, setSubject] = useState('');
|
|
15
|
+
const [bodyMarkdown, setBodyMarkdown] = useState('');
|
|
16
|
+
const [priority, setPriority] = useState('routine');
|
|
17
|
+
const [validUntil, setValidUntil] = useState('');
|
|
18
|
+
const [attachments, setAttachments] = useState([]);
|
|
19
|
+
const [working, setWorking] = useState(false);
|
|
20
|
+
const [status, setStatus] = useState('');
|
|
21
|
+
const [error, setError] = useState('');
|
|
22
|
+
const audience = input.audiences.find((candidate) => candidate.id === audienceId);
|
|
23
|
+
const disabled = Boolean(input.disabled || working);
|
|
24
|
+
const publicAlertForm = Boolean(input.formSchema);
|
|
25
|
+
const priorityOptions = input.formSchema?.properties.priority?.enum ?? PublicAlertPriorities;
|
|
26
|
+
const subjectMaxLength = input.formSchema?.properties.subject?.maxLength;
|
|
27
|
+
const bodyMaxLength = input.formSchema?.properties.bodyMarkdown?.maxLength;
|
|
28
|
+
const attachmentLimit = input.formSchema?.properties.attachments?.maxItems;
|
|
29
|
+
async function addAttachments(files) {
|
|
30
|
+
if (!files?.length)
|
|
31
|
+
return;
|
|
32
|
+
setError('');
|
|
33
|
+
const selectedFiles = Array.from(files);
|
|
34
|
+
if (attachmentLimit !== undefined && attachments.length + selectedFiles.length > attachmentLimit) {
|
|
35
|
+
setError(input.copy.unsupportedAttachment);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
if (selectedFiles.some((file) => !NotificationAttachmentMediaTypes.includes(file.type))) {
|
|
39
|
+
setError(input.copy.unsupportedAttachment);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
setWorking(true);
|
|
43
|
+
try {
|
|
44
|
+
const uploaded = await Promise.all(selectedFiles.map((file) => input.uploadAttachment(file)));
|
|
45
|
+
setAttachments((current) => Object.freeze([...current, ...uploaded]));
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
setError(input.copy.attachmentUploadFailed);
|
|
49
|
+
}
|
|
50
|
+
finally {
|
|
51
|
+
setWorking(false);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
async function submit() {
|
|
55
|
+
if (!audience || !subject.trim() || !bodyMarkdown.trim())
|
|
56
|
+
return;
|
|
57
|
+
setWorking(true);
|
|
58
|
+
setStatus('');
|
|
59
|
+
setError('');
|
|
60
|
+
try {
|
|
61
|
+
const draft = normalizeNotificationComposerDraft({
|
|
62
|
+
audience: audience.audience,
|
|
63
|
+
subject,
|
|
64
|
+
bodyMarkdown,
|
|
65
|
+
attachments,
|
|
66
|
+
...(publicAlertForm ? {
|
|
67
|
+
priority,
|
|
68
|
+
validUntil: new Date(validUntil).toISOString(),
|
|
69
|
+
} : {}),
|
|
70
|
+
});
|
|
71
|
+
await input.onSubmit(draft);
|
|
72
|
+
setStatus(input.copy.sent);
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
setError(input.copy.sendFailed);
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
setWorking(false);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return _jsxs("section", { className: "uhcp-notification-composer", "aria-labelledby": `${id}-title`, "data-form-schema": input.formSchema?.$id, children: [_jsx("header", { children: _jsx("h2", { id: `${id}-title`, children: input.copy.title }) }), _jsx("label", { htmlFor: `${id}-audience`, children: input.copy.audience }), _jsx("select", { id: `${id}-audience`, value: audienceId, disabled: disabled, onChange: (event) => setAudienceId(event.currentTarget.value), children: input.audiences.map((option) => _jsx("option", { value: option.id, children: option.label }, option.id)) }), audience?.description ? _jsx("p", { className: "uhcp-muted", children: audience.description }) : null, _jsx("label", { htmlFor: `${id}-subject`, children: input.copy.subject }), _jsx("input", { id: `${id}-subject`, value: subject, maxLength: subjectMaxLength, disabled: disabled, onChange: (event) => setSubject(event.currentTarget.value) }), publicAlertForm ? _jsxs(_Fragment, { children: [_jsx("label", { htmlFor: `${id}-priority`, children: input.copy.priority || 'Priority' }), _jsx("select", { id: `${id}-priority`, value: priority, disabled: disabled, onChange: (event) => setPriority(event.currentTarget.value), children: priorityOptions.map((value) => _jsx("option", { value: value, children: value }, value)) }), _jsx("label", { htmlFor: `${id}-valid-until`, children: input.copy.validUntil || 'Valid until' }), _jsx("input", { id: `${id}-valid-until`, type: "datetime-local", value: validUntil, required: true, disabled: disabled, onChange: (event) => setValidUntil(event.currentTarget.value) })] }) : null, _jsxs("div", { className: "uhcp-notification-composer-body", children: [_jsxs("div", { children: [_jsx("label", { htmlFor: `${id}-body`, children: input.copy.bodyMarkdown }), _jsx("textarea", { id: `${id}-body`, value: bodyMarkdown, maxLength: bodyMaxLength, disabled: disabled, onChange: (event) => setBodyMarkdown(event.currentTarget.value) })] }), _jsxs("section", { "aria-labelledby": `${id}-preview`, children: [_jsx("h3", { id: `${id}-preview`, children: input.copy.preview }), _jsx(LegalMarkdownDocument, { source: bodyMarkdown })] })] }), _jsxs("fieldset", { disabled: disabled, children: [_jsx("legend", { children: input.copy.attachments }), _jsx("label", { htmlFor: `${id}-attachments`, children: input.copy.addAttachments }), _jsx("input", { id: `${id}-attachments`, type: "file", multiple: true, accept: NotificationAttachmentMediaTypes.join(','), onChange: (event) => void addAttachments(event.currentTarget.files) }), attachments.length > 0 ? _jsx("ul", { children: attachments.map((attachment) => _jsxs("li", { children: [_jsx("span", { children: attachment.fileName }), _jsx("button", { type: "button", onClick: () => setAttachments((current) => current.filter((item) => item.attachmentId !== attachment.attachmentId)), children: input.copy.removeAttachment })] }, attachment.attachmentId)) }) : null] }), _jsx("button", { type: "button", disabled: disabled || !audience || !subject.trim() || !bodyMarkdown.trim() || (publicAlertForm && !validUntil), onClick: () => void submit(), children: working ? input.copy.sending : input.copy.send }), status ? _jsx("p", { role: "status", children: status }) : null, error ? _jsx("p", { role: "alert", children: error }) : null] });
|
|
82
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
export declare const SELECTED_SUBJECT_AREAS: readonly ["identity", "health", "insurance", "appointments-tasks", "communications", "contacts-permissions"];
|
|
3
|
+
export type SelectedSubjectArea = (typeof SELECTED_SUBJECT_AREAS)[number];
|
|
4
|
+
export type SelectedSubjectAction = 'search' | 'read' | 'create' | 'update' | 'delete';
|
|
5
|
+
export type SelectedSubjectAreaCapability = Readonly<{
|
|
6
|
+
area: SelectedSubjectArea;
|
|
7
|
+
actions: readonly SelectedSubjectAction[];
|
|
8
|
+
recordCount?: number;
|
|
9
|
+
}>;
|
|
10
|
+
export type SelectedSubjectWorkspaceCopy = Readonly<{
|
|
11
|
+
card: string;
|
|
12
|
+
summary: string;
|
|
13
|
+
identity: string;
|
|
14
|
+
health: string;
|
|
15
|
+
insurance: string;
|
|
16
|
+
appointmentsTasks: string;
|
|
17
|
+
communications: string;
|
|
18
|
+
contactsPermissions: string;
|
|
19
|
+
records: string;
|
|
20
|
+
}>;
|
|
21
|
+
/** Capability-driven professional subject shell; selection never grants an action. */
|
|
22
|
+
export declare function SelectedSubjectWorkspace({ subject, capabilities, copy, content, initialArea }: Readonly<{
|
|
23
|
+
subject: Readonly<{
|
|
24
|
+
id: string;
|
|
25
|
+
display: string;
|
|
26
|
+
}>;
|
|
27
|
+
capabilities: readonly SelectedSubjectAreaCapability[];
|
|
28
|
+
copy: SelectedSubjectWorkspaceCopy;
|
|
29
|
+
content?: Partial<Record<SelectedSubjectArea, ReactNode>>;
|
|
30
|
+
initialArea?: 'card' | SelectedSubjectArea;
|
|
31
|
+
}>): import("react").JSX.Element;
|
|
32
|
+
//# sourceMappingURL=SelectedSubjectWorkspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SelectedSubjectWorkspace.d.ts","sourceRoot":"","sources":["../src/SelectedSubjectWorkspace.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAgC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAEpE,eAAO,MAAM,sBAAsB,8GAA+G,CAAA;AAClJ,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAA;AACzE,MAAM,MAAM,qBAAqB,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,QAAQ,CAAA;AACtF,MAAM,MAAM,6BAA6B,GAAG,QAAQ,CAAC;IAAE,IAAI,EAAE,mBAAmB,CAAC;IAAC,OAAO,EAAE,SAAS,qBAAqB,EAAE,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AACpJ,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAC;IAAC,cAAc,EAAE,MAAM,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAc5O,sFAAsF;AACtF,wBAAgB,wBAAwB,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,OAAY,EAAE,WAAoB,EAAE,EAAE,QAAQ,CAAC;IACrH,OAAO,EAAE,QAAQ,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAClD,YAAY,EAAE,SAAS,6BAA6B,EAAE,CAAA;IACtD,IAAI,EAAE,4BAA4B,CAAA;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC,MAAM,CAAC,mBAAmB,EAAE,SAAS,CAAC,CAAC,CAAA;IACzD,WAAW,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAAA;CAC3C,CAAC,+BAmBD"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
4
|
+
export const SELECTED_SUBJECT_AREAS = ['identity', 'health', 'insurance', 'appointments-tasks', 'communications', 'contacts-permissions'];
|
|
5
|
+
const copyKey = { identity: 'identity', health: 'health', insurance: 'insurance', 'appointments-tasks': 'appointmentsTasks', communications: 'communications', 'contacts-permissions': 'contactsPermissions' };
|
|
6
|
+
function mergeCapabilities(capabilities) {
|
|
7
|
+
const merged = new Map();
|
|
8
|
+
for (const capability of capabilities) {
|
|
9
|
+
if (!capability.actions.length)
|
|
10
|
+
continue;
|
|
11
|
+
const previous = merged.get(capability.area);
|
|
12
|
+
merged.set(capability.area, { area: capability.area, actions: [...new Set([...(previous?.actions ?? []), ...capability.actions])], recordCount: capability.actions.includes('search') ? capability.recordCount ?? previous?.recordCount : previous?.recordCount });
|
|
13
|
+
}
|
|
14
|
+
return merged;
|
|
15
|
+
}
|
|
16
|
+
/** Capability-driven professional subject shell; selection never grants an action. */
|
|
17
|
+
export function SelectedSubjectWorkspace({ subject, capabilities, copy, content = {}, initialArea = 'card' }) {
|
|
18
|
+
const capabilityByArea = useMemo(() => mergeCapabilities(capabilities), [capabilities]);
|
|
19
|
+
const visibleAreas = SELECTED_SUBJECT_AREAS.filter((area) => capabilityByArea.has(area));
|
|
20
|
+
const [selectedArea, setSelectedArea] = useState(initialArea);
|
|
21
|
+
useEffect(() => { if (selectedArea !== 'card' && !capabilityByArea.has(selectedArea))
|
|
22
|
+
setSelectedArea('card'); }, [capabilityByArea, selectedArea]);
|
|
23
|
+
const labelFor = (area) => {
|
|
24
|
+
const label = copy[copyKey[area]];
|
|
25
|
+
const capability = capabilityByArea.get(area);
|
|
26
|
+
return capability?.actions.includes('search') && capability.recordCount !== undefined ? `${label}, ${capability.recordCount} ${copy.records}` : label;
|
|
27
|
+
};
|
|
28
|
+
const selectedCapability = selectedArea === 'card' ? undefined : capabilityByArea.get(selectedArea);
|
|
29
|
+
return _jsxs("section", { className: "uhcp-selected-subject-workspace", "aria-labelledby": "uhcp-selected-subject-title", children: [_jsxs("header", { children: [_jsxs("div", { children: [_jsx("span", { children: copy.summary }), _jsx("h2", { id: "uhcp-selected-subject-title", children: subject.display })] }), _jsx("code", { children: subject.id })] }), _jsxs("div", { className: "uhcp-selected-subject-tabs", role: "tablist", "aria-label": subject.display, children: [_jsx("button", { type: "button", role: "tab", "aria-selected": selectedArea === 'card', onClick: () => setSelectedArea('card'), children: copy.card }), visibleAreas.map((area) => _jsx("button", { type: "button", role: "tab", "aria-selected": selectedArea === area, onClick: () => setSelectedArea(area), children: labelFor(area) }, area))] }), _jsx("div", { role: "tabpanel", children: selectedArea === 'card' ? _jsxs("div", { children: [_jsx("h3", { children: copy.summary }), _jsx("ul", { children: visibleAreas.map((area) => _jsx("li", { children: labelFor(area) }, area)) })] }) : selectedCapability?.actions.includes('read') ? content[selectedArea] : null })] });
|
|
30
|
+
}
|
|
@@ -82,6 +82,8 @@ export type SoschainWorkspaceProps = Readonly<{
|
|
|
82
82
|
places: readonly SoschainAssociationSummary[];
|
|
83
83
|
products: readonly SoschainAssociationSummary[];
|
|
84
84
|
communications: readonly SoschainCommunicationSummary[];
|
|
85
|
+
/** Shared channels/topics screen composed with host-owned BFF adapters. */
|
|
86
|
+
communicationsContent?: ReactNode;
|
|
85
87
|
/** Host-authorized IPS/clinical projection, normally `IpsBundleSummary`. */
|
|
86
88
|
healthSummary?: ReactNode;
|
|
87
89
|
/** False only when the host has already resolved a current write capability. */
|
|
@@ -109,5 +111,5 @@ export type SoschainWorkspaceProps = Readonly<{
|
|
|
109
111
|
* communications. This presentational component never derives authority from
|
|
110
112
|
* a selected role, card, tab or browser-controlled value.
|
|
111
113
|
*/
|
|
112
|
-
export declare function SoschainWorkspace({ copy, cards, selectedCard, activeArea, areaHrefs, places, products, communications, healthSummary, clinicalReadOnly, careJourney, emergencyData, canManageAssociations, addPlaceHref, addProductHref, importCardHref, overviewContent, primaryAreas, moreLabel, showCardIdentifier, onSelectCard, }: SoschainWorkspaceProps): import("react").JSX.Element;
|
|
114
|
+
export declare function SoschainWorkspace({ copy, cards, selectedCard, activeArea, areaHrefs, places, products, communications, communicationsContent, healthSummary, clinicalReadOnly, careJourney, emergencyData, canManageAssociations, addPlaceHref, addProductHref, importCardHref, overviewContent, primaryAreas, moreLabel, showCardIdentifier, onSelectCard, }: SoschainWorkspaceProps): import("react").JSX.Element;
|
|
113
115
|
//# sourceMappingURL=SoschainWorkspace.d.ts.map
|
|
@@ -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":"AAAA,OAAO,EAA+B,KAAK,2BAA2B,EAAE,KAAK,2BAA2B,EAAE,MAAM,kCAAkC,CAAA;AAClJ,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEtC,eAAO,MAAM,gCAAgC,mHAQnC,CAAA;AAEV,MAAM,MAAM,qBAAqB,GAAG,OAAO,gCAAgC,CAAC,MAAM,CAAC,CAAA;AAEnF,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACzC,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAC,CAAA;AAEF,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAAC;IAChD,UAAU,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;CACpB,CAAC,CAAA;AAEF,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAC,CAAA;AAEF;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAC,CAAA;AAEF,MAAM,MAAM,qBAAqB,GAAG,QAAQ,CAAC;IAC3C,UAAU,EAAE,MAAM,CAAA;IAClB,gBAAgB,EAAE,MAAM,CAAA;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,gBAAgB,EAAE,MAAM,CAAA;IACxB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAA;IAC5C,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,iBAAiB,EAAE,MAAM,CAAA;IACzB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,gBAAgB,EAAE,MAAM,CAAA;IACxB,eAAe,EAAE,MAAM,CAAA;IACvB,gBAAgB,EAAE,MAAM,CAAA;IACxB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,iBAAiB,EAAE,MAAM,CAAA;IACzB,aAAa,EAAE,2BAA2B,CAAA;IAC1C,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,kBAAkB,EAAE,MAAM,CAAA;IAC1B,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,MAAM,CAAA;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB,CAAC,CAAA;AAEF,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC5C,IAAI,EAAE,qBAAqB,CAAA;IAC3B,KAAK,EAAE,SAAS,mBAAmB,EAAE,CAAA;IACrC,YAAY,CAAC,EAAE,mBAAmB,CAAA;IAClC,UAAU,EAAE,qBAAqB,CAAA;IACjC,SAAS,EAAE,MAAM,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAA;IAChD,MAAM,EAAE,SAAS,0BAA0B,EAAE,CAAA;IAC7C,QAAQ,EAAE,SAAS,0BAA0B,EAAE,CAAA;IAC/C,cAAc,EAAE,SAAS,4BAA4B,EAAE,CAAA;IACvD,2EAA2E;IAC3E,qBAAqB,CAAC,EAAE,SAAS,CAAA;IACjC,4EAA4E;IAC5E,aAAa,CAAC,EAAE,SAAS,CAAA;IACzB,gFAAgF;IAChF,gBAAgB,CAAC,EAAE,OAAO,CAAA;IAC1B,WAAW,CAAC,EAAE,SAAS,wBAAwB,EAAE,CAAA;IACjD,aAAa,CAAC,EAAE,SAAS,2BAA2B,EAAE,CAAA;IACtD,qBAAqB,EAAE,OAAO,CAAA;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,yEAAyE;IACzE,eAAe,CAAC,EAAE,SAAS,CAAA;IAC3B,8EAA8E;IAC9E,YAAY,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAA;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,0EAA0E;IAC1E,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,mFAAmF;IACnF,YAAY,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAA;CAC5C,CAAC,CAAA;AAqBF;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,KAAK,EACL,YAAY,EACZ,UAAU,EACV,SAAS,EACT,MAAM,EACN,QAAQ,EACR,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,gBAAuB,EACvB,WAAgB,EAChB,aAAkB,EAClB,qBAAqB,EACrB,YAAY,EACZ,cAAc,EACd,cAAc,EACd,eAAe,EACf,YAAY,EACZ,SAAkB,EAClB,kBAAyB,EACzB,YAAY,GACb,EAAE,sBAAsB,+BAkJxB"}
|
|
@@ -21,7 +21,7 @@ function AssociationList({ items, empty }) {
|
|
|
21
21
|
* communications. This presentational component never derives authority from
|
|
22
22
|
* a selected role, card, tab or browser-controlled value.
|
|
23
23
|
*/
|
|
24
|
-
export function SoschainWorkspace({ copy, cards, selectedCard, activeArea, areaHrefs, places, products, communications, healthSummary, clinicalReadOnly = true, careJourney = [], emergencyData = [], canManageAssociations, addPlaceHref, addProductHref, importCardHref, overviewContent, primaryAreas, moreLabel = 'More', showCardIdentifier = true, onSelectCard, }) {
|
|
24
|
+
export function SoschainWorkspace({ copy, cards, selectedCard, activeArea, areaHrefs, places, products, communications, communicationsContent, healthSummary, clinicalReadOnly = true, careJourney = [], emergencyData = [], canManageAssociations, addPlaceHref, addProductHref, importCardHref, overviewContent, primaryAreas, moreLabel = 'More', showCardIdentifier = true, onSelectCard, }) {
|
|
25
25
|
if (!selectedCard) {
|
|
26
26
|
return (_jsxs("section", { className: "uhcp-sos-wrap", "aria-labelledby": "sos-card-picker-title", children: [_jsxs("header", { className: "uhcp-sos-heading", children: [_jsx("span", { children: copy.workspaceEyebrow }), _jsx("h1", { id: "sos-card-picker-title", children: copy.cardsTitle }), _jsx("p", { children: copy.cardsDescription }), importCardHref && copy.importCard ? _jsxs("a", { href: importCardHref, children: [copy.importCard, " \u2192"] }) : null] }), cards.length === 0 ? (_jsxs("div", { className: "uhcp-sos-empty-panel", children: [_jsx("h2", { children: copy.noCardTitle }), _jsx("p", { children: copy.noCardBody })] })) : (_jsx("ul", { className: "uhcp-sos-card-grid", children: cards.map((card) => (_jsx("li", { children: onSelectCard ? _jsxs("button", { type: "button", onClick: () => onSelectCard(card.identifier), children: [_jsx("span", { children: card.kindLabel }), _jsx("strong", { children: card.displayName }), showCardIdentifier ? _jsx("small", { children: card.identifier }) : null, _jsxs("b", { children: [copy.openCard, " \u2192"] })] }) : _jsxs("a", { href: card.openHref, children: [_jsx("span", { children: card.kindLabel }), _jsx("strong", { children: card.displayName }), showCardIdentifier ? _jsx("small", { children: card.identifier }) : null, _jsxs("b", { children: [copy.openCard, " \u2192"] })] }) }, card.identifier))) }))] }));
|
|
27
27
|
}
|
|
@@ -53,5 +53,5 @@ export function SoschainWorkspace({ copy, cards, selectedCard, activeArea, areaH
|
|
|
53
53
|
: copy.overviewBody;
|
|
54
54
|
const clinicalAreaIsReadOnly = activeArea === 'care-journey' || (activeArea === 'health-summary' && clinicalReadOnly);
|
|
55
55
|
const associationAreaIsReadOnly = !canManageAssociations && (activeArea === 'overview' || activeArea === 'places' || activeArea === 'products');
|
|
56
|
-
return (_jsxs("section", { className: "uhcp-sos-wrap", children: [_jsxs("header", { className: "uhcp-sos-heading", children: [_jsx("span", { children: copy.selectedCard }), _jsx("h1", { children: selectedCard.displayName }), _jsxs("p", { children: [selectedCard.kindLabel, showCardIdentifier ? ` · ${selectedCard.identifier}` : ''] })] }), _jsxs("nav", { className: "uhcp-sos-tabs", "aria-label": copy.workspaceEyebrow, children: [(primaryAreas ?? SOSCHAIN_SUBJECT_WORKSPACE_AREAS).map((area) => (_jsx("a", { href: areaHrefs[area], "aria-current": activeArea === area ? 'page' : undefined, children: copy.areas[area] }, area))), primaryAreas ? _jsxs("details", { className: "uhcp-sos-more", children: [_jsx("summary", { children: moreLabel }), _jsx("div", { children: SOSCHAIN_SUBJECT_WORKSPACE_AREAS.filter((area) => !primaryAreas.includes(area)).map((area) => (_jsx("a", { href: areaHrefs[area], "aria-current": activeArea === area ? 'page' : undefined, children: copy.areas[area] }, area))) })] }) : null] }), _jsxs("div", { className: "uhcp-sos-panel", children: [_jsxs("header", { children: [_jsxs("div", { children: [_jsx("h2", { children: title }), _jsx("p", { children: body })] }), (clinicalAreaIsReadOnly || associationAreaIsReadOnly) && (_jsx("span", { className: "uhcp-sos-readonly", children: copy.readOnly })), canManageAssociations && activeArea === 'places' && addPlaceHref && _jsx("a", { href: addPlaceHref, children: copy.addPlace }), canManageAssociations && activeArea === 'products' && addProductHref && _jsx("a", { href: addProductHref, children: copy.addProduct })] }), activeArea === 'overview' && (overviewContent ?? (_jsxs("div", { className: "uhcp-sos-overview-grid", children: [_jsxs("article", { children: [_jsx("strong", { children: places.length }), _jsx("span", { children: copy.areas.places })] }), _jsxs("article", { children: [_jsx("strong", { children: products.length }), _jsx("span", { children: copy.areas.products })] }), _jsxs("article", { children: [_jsx("strong", { children: communications.length }), _jsx("span", { children: copy.areas.communications })] }), _jsxs("article", { children: [_jsx("strong", { children: careJourney.length }), _jsx("span", { children: copy.areas['care-journey'] })] })] }))), activeArea === 'health-summary' && (healthSummary ?? _jsx("p", { className: "uhcp-sos-empty", children: copy.emptyHealthSummary })), activeArea === 'care-journey' && (careJourney.length === 0 ? _jsx("p", { className: "uhcp-sos-empty", children: copy.emptyCareJourney }) : (_jsx("ol", { className: "uhcp-sos-timeline uhcp-sos-care-journey", children: careJourney.map((encounter) => (_jsxs("li", { children: [_jsxs("div", { children: [_jsx("span", { children: encounter.statusLabel }), _jsx("time", { dateTime: encounter.periodStart, children: encounter.periodStart })] }), _jsx("strong", { children: encounter.serviceLabel }), encounter.detail ? _jsx("p", { children: encounter.detail }) : null, encounter.locationLabel || encounter.periodEnd ? _jsx("small", { children: [encounter.locationLabel, encounter.periodEnd].filter(Boolean).join(' · ') }) : null] }, encounter.identifier))) }))), activeArea === 'emergency-data' && _jsx(ProtectedIndexEmergencyData, { copy: copy.emergencyData, items: emergencyData }), activeArea === 'places' && _jsx(AssociationList, { items: places, empty: copy.emptyPlaces }), activeArea === 'products' && _jsx(AssociationList, { items: products, empty: copy.emptyProducts }), activeArea === 'communications' && (communications.length === 0 ? _jsx("p", { className: "uhcp-sos-empty", children: copy.emptyCommunications }) : (_jsx("ol", { className: "uhcp-sos-timeline", children: communications.map((message) => (_jsxs("li", { children: [_jsxs("div", { children: [_jsx("span", { children: message.categoryLabel }), _jsx("time", { children: message.occurredAt })] }), _jsx("strong", { children: message.subject }), _jsx("p", { children: message.body }), _jsxs("small", { children: [message.sender, message.placeLabel ? ` · ${message.placeLabel}` : ''] })] }, message.identifier))) })))] })] }));
|
|
56
|
+
return (_jsxs("section", { className: "uhcp-sos-wrap", children: [_jsxs("header", { className: "uhcp-sos-heading", children: [_jsx("span", { children: copy.selectedCard }), _jsx("h1", { children: selectedCard.displayName }), _jsxs("p", { children: [selectedCard.kindLabel, showCardIdentifier ? ` · ${selectedCard.identifier}` : ''] })] }), _jsxs("nav", { className: "uhcp-sos-tabs", "aria-label": copy.workspaceEyebrow, children: [(primaryAreas ?? SOSCHAIN_SUBJECT_WORKSPACE_AREAS).map((area) => (_jsx("a", { href: areaHrefs[area], "aria-current": activeArea === area ? 'page' : undefined, children: copy.areas[area] }, area))), primaryAreas ? _jsxs("details", { className: "uhcp-sos-more", children: [_jsx("summary", { children: moreLabel }), _jsx("div", { children: SOSCHAIN_SUBJECT_WORKSPACE_AREAS.filter((area) => !primaryAreas.includes(area)).map((area) => (_jsx("a", { href: areaHrefs[area], "aria-current": activeArea === area ? 'page' : undefined, children: copy.areas[area] }, area))) })] }) : null] }), _jsxs("div", { className: "uhcp-sos-panel", children: [_jsxs("header", { children: [_jsxs("div", { children: [_jsx("h2", { children: title }), _jsx("p", { children: body })] }), (clinicalAreaIsReadOnly || associationAreaIsReadOnly) && (_jsx("span", { className: "uhcp-sos-readonly", children: copy.readOnly })), canManageAssociations && activeArea === 'places' && addPlaceHref && _jsx("a", { href: addPlaceHref, children: copy.addPlace }), canManageAssociations && activeArea === 'products' && addProductHref && _jsx("a", { href: addProductHref, children: copy.addProduct })] }), activeArea === 'overview' && (overviewContent ?? (_jsxs("div", { className: "uhcp-sos-overview-grid", children: [_jsxs("article", { children: [_jsx("strong", { children: places.length }), _jsx("span", { children: copy.areas.places })] }), _jsxs("article", { children: [_jsx("strong", { children: products.length }), _jsx("span", { children: copy.areas.products })] }), _jsxs("article", { children: [_jsx("strong", { children: communications.length }), _jsx("span", { children: copy.areas.communications })] }), _jsxs("article", { children: [_jsx("strong", { children: careJourney.length }), _jsx("span", { children: copy.areas['care-journey'] })] })] }))), activeArea === 'health-summary' && (healthSummary ?? _jsx("p", { className: "uhcp-sos-empty", children: copy.emptyHealthSummary })), activeArea === 'care-journey' && (careJourney.length === 0 ? _jsx("p", { className: "uhcp-sos-empty", children: copy.emptyCareJourney }) : (_jsx("ol", { className: "uhcp-sos-timeline uhcp-sos-care-journey", children: careJourney.map((encounter) => (_jsxs("li", { children: [_jsxs("div", { children: [_jsx("span", { children: encounter.statusLabel }), _jsx("time", { dateTime: encounter.periodStart, children: encounter.periodStart })] }), _jsx("strong", { children: encounter.serviceLabel }), encounter.detail ? _jsx("p", { children: encounter.detail }) : null, encounter.locationLabel || encounter.periodEnd ? _jsx("small", { children: [encounter.locationLabel, encounter.periodEnd].filter(Boolean).join(' · ') }) : null] }, encounter.identifier))) }))), activeArea === 'emergency-data' && _jsx(ProtectedIndexEmergencyData, { copy: copy.emergencyData, items: emergencyData }), activeArea === 'places' && _jsx(AssociationList, { items: places, empty: copy.emptyPlaces }), activeArea === 'products' && _jsx(AssociationList, { items: products, empty: copy.emptyProducts }), activeArea === 'communications' && (communicationsContent ?? (communications.length === 0 ? _jsx("p", { className: "uhcp-sos-empty", children: copy.emptyCommunications }) : (_jsx("ol", { className: "uhcp-sos-timeline", children: communications.map((message) => (_jsxs("li", { children: [_jsxs("div", { children: [_jsx("span", { children: message.categoryLabel }), _jsx("time", { children: message.occurredAt })] }), _jsx("strong", { children: message.subject }), _jsx("p", { children: message.body }), _jsxs("small", { children: [message.sender, message.placeLabel ? ` · ${message.placeLabel}` : ''] })] }, message.identifier))) }))))] })] }));
|
|
57
57
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -45,4 +45,8 @@ export * from './AnimalControllerAttestationPanel.js';
|
|
|
45
45
|
export * from './EmergencyTaskHub.js';
|
|
46
46
|
export * from './SubjectCommunicationCenter.js';
|
|
47
47
|
export * from './ProfessionalAccessPanel.js';
|
|
48
|
+
export * from './NotificationComposer.js';
|
|
49
|
+
export * from './notification-bff-client.js';
|
|
50
|
+
export * from './CommunicationsWorkspace.js';
|
|
51
|
+
export * from './SelectedSubjectWorkspace.js';
|
|
48
52
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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"}
|
|
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"}
|
package/dist/index.js
CHANGED
|
@@ -45,3 +45,7 @@ export * from './AnimalControllerAttestationPanel.js';
|
|
|
45
45
|
export * from './EmergencyTaskHub.js';
|
|
46
46
|
export * from './SubjectCommunicationCenter.js';
|
|
47
47
|
export * from './ProfessionalAccessPanel.js';
|
|
48
|
+
export * from './NotificationComposer.js';
|
|
49
|
+
export * from './notification-bff-client.js';
|
|
50
|
+
export * from './CommunicationsWorkspace.js';
|
|
51
|
+
export * from './SelectedSubjectWorkspace.js';
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { type NotificationAttachment, type NotificationComposerDraft, type PublicNotificationRecord } from 'sos-data-utils-ts/public-notifications';
|
|
2
|
+
type AuthorizedFetch = (url: string, init: RequestInit) => Promise<Response>;
|
|
3
|
+
export type NotificationSendResult = Readonly<{
|
|
4
|
+
notificationId: string;
|
|
5
|
+
status: 'accepted';
|
|
6
|
+
}>;
|
|
7
|
+
export type NotificationProfileProof = Readonly<{
|
|
8
|
+
profileId: string;
|
|
9
|
+
profileSessionToken: string;
|
|
10
|
+
}>;
|
|
11
|
+
export type PersonalNotificationContext = Readonly<{
|
|
12
|
+
subjectReference: string;
|
|
13
|
+
subjectKind: 'human';
|
|
14
|
+
}> | Readonly<{
|
|
15
|
+
subjectReference: string;
|
|
16
|
+
subjectKind: 'animal';
|
|
17
|
+
species: 'dog' | 'cat';
|
|
18
|
+
}>;
|
|
19
|
+
/** Personal public-topic reader; the BFF derives subscriptions, exclusions and delivery decisions. */
|
|
20
|
+
export declare function createPersonalNotificationBffClient(input: Readonly<{
|
|
21
|
+
authorizedFetch: AuthorizedFetch;
|
|
22
|
+
routeRoot?: '/api/notifications';
|
|
23
|
+
}>): Readonly<{
|
|
24
|
+
listPublic(context: PersonalNotificationContext): Promise<readonly PublicNotificationRecord[]>;
|
|
25
|
+
}>;
|
|
26
|
+
/** Shared transport adapter for browser, mobile-web and assistant hosts. */
|
|
27
|
+
export declare function createNotificationBffClient(input: Readonly<{
|
|
28
|
+
authorizedFetch: AuthorizedFetch;
|
|
29
|
+
routeRoot?: '/api/notifications';
|
|
30
|
+
}>): Readonly<{
|
|
31
|
+
uploadAttachment(file: File): Promise<NotificationAttachment>;
|
|
32
|
+
send(draft: NotificationComposerDraft): Promise<NotificationSendResult>;
|
|
33
|
+
}>;
|
|
34
|
+
/** Public-dataset transport shared by professional portals; the BFF validates the trusted profile proof. */
|
|
35
|
+
export declare function createPublicNotificationBffClient(input: Readonly<{
|
|
36
|
+
authorizedFetch: AuthorizedFetch;
|
|
37
|
+
profileProof: NotificationProfileProof;
|
|
38
|
+
routeRoot?: '/api/notifications/public';
|
|
39
|
+
}>): Readonly<{
|
|
40
|
+
uploadAttachment(file: File): Promise<NotificationAttachment>;
|
|
41
|
+
send(draft: NotificationComposerDraft): Promise<NotificationSendResult>;
|
|
42
|
+
}>;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=notification-bff-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-bff-client.d.ts","sourceRoot":"","sources":["../src/notification-bff-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,sBAAsB,EAC3B,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC9B,MAAM,wCAAwC,CAAA;AAE/C,KAAK,eAAe,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAE5E,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC5C,cAAc,EAAE,MAAM,CAAA;IACtB,MAAM,EAAE,UAAU,CAAA;CACnB,CAAC,CAAA;AAEF,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,SAAS,EAAE,MAAM,CAAA;IACjB,mBAAmB,EAAE,MAAM,CAAA;CAC5B,CAAC,CAAA;AAEF,MAAM,MAAM,2BAA2B,GACnC,QAAQ,CAAC;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CAAC,GAC5D,QAAQ,CAAC;IAAE,gBAAgB,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,KAAK,GAAG,KAAK,CAAA;CAAE,CAAC,CAAA;AAEzF,sGAAsG;AACtG,wBAAgB,mCAAmC,CAAC,KAAK,EAAE,QAAQ,CAAC;IAClE,eAAe,EAAE,eAAe,CAAA;IAChC,SAAS,CAAC,EAAE,oBAAoB,CAAA;CACjC,CAAC;wBAG4B,2BAA2B,GAAG,OAAO,CAAC,SAAS,wBAAwB,EAAE,CAAC;GAavG;AAED,4EAA4E;AAC5E,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,QAAQ,CAAC;IAC1D,eAAe,EAAE,eAAe,CAAA;IAChC,SAAS,CAAC,EAAE,oBAAoB,CAAA;CACjC,CAAC;2BAI+B,IAAI,GAAG,OAAO,CAAC,sBAAsB,CAAC;gBAYjD,yBAAyB,GAAG,OAAO,CAAC,sBAAsB,CAAC;GAchF;AAED,4GAA4G;AAC5G,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,QAAQ,CAAC;IAChE,eAAe,EAAE,eAAe,CAAA;IAChC,YAAY,EAAE,wBAAwB,CAAA;IACtC,SAAS,CAAC,EAAE,2BAA2B,CAAA;CACxC,CAAC;2BAQ+B,IAAI,GAAG,OAAO,CAAC,sBAAsB,CAAC;gBAWjD,yBAAyB,GAAG,OAAO,CAAC,sBAAsB,CAAC;GAchF"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { normalizePublicNotificationRecord, normalizeNotificationComposerDraft, } from 'sos-data-utils-ts/public-notifications';
|
|
2
|
+
/** Personal public-topic reader; the BFF derives subscriptions, exclusions and delivery decisions. */
|
|
3
|
+
export function createPersonalNotificationBffClient(input) {
|
|
4
|
+
const routeRoot = input.routeRoot ?? '/api/notifications';
|
|
5
|
+
return Object.freeze({
|
|
6
|
+
async listPublic(context) {
|
|
7
|
+
const subjectReference = context.subjectReference.trim();
|
|
8
|
+
if (!subjectReference)
|
|
9
|
+
throw new Error('notification_subject_reference_required');
|
|
10
|
+
const query = new URLSearchParams({ subject: subjectReference });
|
|
11
|
+
if (context.subjectKind === 'animal')
|
|
12
|
+
query.set('species', context.species);
|
|
13
|
+
const response = await input.authorizedFetch(`${routeRoot}?${query.toString()}`, { method: 'GET' });
|
|
14
|
+
const payload = await response.json();
|
|
15
|
+
if (!response.ok || !Array.isArray(payload.notifications)) {
|
|
16
|
+
throw new Error(payload.error || 'notification_list_failed');
|
|
17
|
+
}
|
|
18
|
+
return Object.freeze(payload.notifications.map(normalizePublicNotificationRecord));
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/** Shared transport adapter for browser, mobile-web and assistant hosts. */
|
|
23
|
+
export function createNotificationBffClient(input) {
|
|
24
|
+
const routeRoot = input.routeRoot ?? '/api/notifications';
|
|
25
|
+
return Object.freeze({
|
|
26
|
+
async uploadAttachment(file) {
|
|
27
|
+
const form = new FormData();
|
|
28
|
+
form.set('attachment', file);
|
|
29
|
+
const response = await input.authorizedFetch(`${routeRoot}/attachments`, {
|
|
30
|
+
method: 'POST',
|
|
31
|
+
body: form,
|
|
32
|
+
});
|
|
33
|
+
const payload = await response.json();
|
|
34
|
+
if (!response.ok || !payload.attachment)
|
|
35
|
+
throw new Error(payload.error || 'notification_attachment_upload_failed');
|
|
36
|
+
return Object.freeze(payload.attachment);
|
|
37
|
+
},
|
|
38
|
+
async send(draft) {
|
|
39
|
+
const normalizedDraft = normalizeNotificationComposerDraft(draft);
|
|
40
|
+
const response = await input.authorizedFetch(routeRoot, {
|
|
41
|
+
method: 'POST',
|
|
42
|
+
headers: { 'content-type': 'application/json' },
|
|
43
|
+
body: JSON.stringify({ operation: 'send', draft: normalizedDraft }),
|
|
44
|
+
});
|
|
45
|
+
const payload = await response.json();
|
|
46
|
+
if (!response.ok || !payload.notificationId || payload.status !== 'accepted') {
|
|
47
|
+
throw new Error(payload.error || 'notification_send_failed');
|
|
48
|
+
}
|
|
49
|
+
return Object.freeze({ notificationId: payload.notificationId, status: 'accepted' });
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/** Public-dataset transport shared by professional portals; the BFF validates the trusted profile proof. */
|
|
54
|
+
export function createPublicNotificationBffClient(input) {
|
|
55
|
+
const routeRoot = input.routeRoot ?? '/api/notifications/public';
|
|
56
|
+
const profileId = input.profileProof.profileId.trim();
|
|
57
|
+
const profileSessionToken = input.profileProof.profileSessionToken.trim();
|
|
58
|
+
if (!profileId)
|
|
59
|
+
throw new Error('profile_id_required');
|
|
60
|
+
if (!profileSessionToken)
|
|
61
|
+
throw new Error('wallet_session_required');
|
|
62
|
+
return Object.freeze({
|
|
63
|
+
async uploadAttachment(file) {
|
|
64
|
+
const form = new FormData();
|
|
65
|
+
form.set('profileId', profileId);
|
|
66
|
+
form.set('profileSessionToken', profileSessionToken);
|
|
67
|
+
form.set('file', file);
|
|
68
|
+
const response = await input.authorizedFetch(`${routeRoot}/attachments`, { method: 'POST', body: form });
|
|
69
|
+
const payload = await response.json();
|
|
70
|
+
if (!response.ok || !payload.attachment)
|
|
71
|
+
throw new Error(payload.error || 'notification_attachment_upload_failed');
|
|
72
|
+
return Object.freeze(payload.attachment);
|
|
73
|
+
},
|
|
74
|
+
async send(draft) {
|
|
75
|
+
const normalizedDraft = normalizeNotificationComposerDraft(draft);
|
|
76
|
+
const response = await input.authorizedFetch(routeRoot, {
|
|
77
|
+
method: 'POST',
|
|
78
|
+
headers: { 'content-type': 'application/json' },
|
|
79
|
+
body: JSON.stringify({ operation: 'send', profileId, profileSessionToken, draft: normalizedDraft }),
|
|
80
|
+
});
|
|
81
|
+
const payload = await response.json();
|
|
82
|
+
if (!response.ok || !payload.notificationId || payload.status !== 'accepted') {
|
|
83
|
+
throw new Error(payload.error || 'public_notification_send_failed');
|
|
84
|
+
}
|
|
85
|
+
return Object.freeze({ notificationId: payload.notificationId, status: 'accepted' });
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
}
|
package/dist/styles.css
CHANGED
|
@@ -772,6 +772,7 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
|
|
|
772
772
|
@media (max-width: 620px) { .uhcp-emergency-copy > header { display: grid; } .uhcp-emergency-copy-legend { width: 100%; } }
|
|
773
773
|
.uhcp-settings{max-width:72rem;margin:0 auto;padding:2rem 1rem 4rem;display:grid;gap:1rem}.uhcp-settings>header,.uhcp-settings>section{background:var(--uhcp-surface,#fff);border:1px solid var(--uhcp-border,#dbe4ea);border-radius:1rem;padding:1.25rem}.uhcp-settings h1,.uhcp-settings h2{margin-top:0}.uhcp-settings fieldset{border:0;padding:0;margin:1rem 0;display:flex;gap:.5rem;flex-wrap:wrap}.uhcp-settings legend{width:100%;font-weight:700;margin-bottom:.5rem}.uhcp-settings button,.uhcp-settings-links a{border:1px solid var(--uhcp-border,#c9d7df);border-radius:.7rem;background:transparent;color:inherit;padding:.65rem .85rem;text-decoration:none}.uhcp-settings button[aria-pressed=true]{background:var(--uhcp-accent,#dceff7);border-color:var(--uhcp-accent-strong,#2489a7)}.uhcp-settings-links{display:flex;gap:.6rem;flex-wrap:wrap}
|
|
774
774
|
.uhcp-legal-document{color:var(--uhcp-text);line-height:1.7}.uhcp-legal-document h2{font-size:clamp(1.6rem,4vw,2.35rem);line-height:1.15;margin:0 0 1.25rem}.uhcp-legal-document h3{font-size:1.2rem;line-height:1.3;margin:2rem 0 .65rem}.uhcp-legal-document p{margin:0 0 1rem}.uhcp-legal-document ul{margin:0 0 1rem;padding-left:1.4rem}.uhcp-legal-document code{background:var(--uhcp-panel-muted);border-radius:.3rem;padding:.08rem .3rem}
|
|
775
|
+
.uhcp-notification-composer{background:var(--uhcp-panel);border:1px solid var(--uhcp-border);border-radius:1.5rem;color:var(--uhcp-text);display:grid;gap:.85rem;padding:1.25rem}.uhcp-notification-composer h2,.uhcp-notification-composer h3,.uhcp-notification-composer p{margin:0}.uhcp-notification-composer label,.uhcp-notification-composer legend{font-weight:800}.uhcp-notification-composer input,.uhcp-notification-composer select,.uhcp-notification-composer textarea,.uhcp-notification-composer button{font:inherit}.uhcp-notification-composer>input,.uhcp-notification-composer>select,.uhcp-notification-composer textarea{background:var(--uhcp-panel);border:1px solid var(--uhcp-border);border-radius:.75rem;color:inherit;padding:.75rem}.uhcp-notification-composer textarea{min-height:12rem;resize:vertical;width:100%}.uhcp-notification-composer-body{display:grid;gap:1rem;grid-template-columns:minmax(0,1fr) minmax(0,1fr)}.uhcp-notification-composer-body>div{display:grid;gap:.45rem}.uhcp-notification-composer-body>section{background:var(--uhcp-panel-muted);border:1px solid var(--uhcp-border);border-radius:1rem;min-width:0;padding:1rem}.uhcp-notification-composer-body>section h3{font-size:.85rem;margin-bottom:.75rem;text-transform:uppercase}.uhcp-notification-composer fieldset{border:1px solid var(--uhcp-border);border-radius:1rem;display:grid;gap:.75rem;margin:0;padding:1rem}.uhcp-notification-composer fieldset ul{display:grid;gap:.5rem;list-style:none;margin:0;padding:0}.uhcp-notification-composer fieldset li{align-items:center;background:var(--uhcp-panel-muted);border-radius:.7rem;display:flex;gap:.75rem;justify-content:space-between;padding:.6rem .75rem}.uhcp-notification-composer button{border:0;border-radius:.75rem;cursor:pointer;font-weight:800;padding:.7rem 1rem}.uhcp-notification-composer>button{background:var(--uhcp-turquoise);color:#fff;justify-self:start}.uhcp-notification-composer [role='alert']{color:#c64747;font-weight:800}.uhcp-notification-composer [role='status']{color:var(--uhcp-emerald);font-weight:800}@media(max-width:720px){.uhcp-notification-composer-body{grid-template-columns:1fr}}
|
|
775
776
|
.uhcp-consent-directory{background:var(--uhcp-panel);border:1px solid var(--uhcp-border);border-radius:1.5rem;color:var(--uhcp-text);display:grid;gap:1rem;padding:1.25rem}.uhcp-consent-directory>header{align-items:flex-start;display:flex;gap:1rem;justify-content:space-between}.uhcp-consent-directory h2,.uhcp-consent-directory p{margin:0}.uhcp-consent-directory>header p,.uhcp-consent-list article>p{color:var(--uhcp-muted)}.uhcp-consent-directory button,.uhcp-consent-directory select{background:var(--uhcp-panel);border:1px solid var(--uhcp-border);border-radius:.7rem;color:inherit;font:inherit;padding:.65rem .85rem}.uhcp-consent-list{display:grid;gap:.75rem}.uhcp-consent-list article{background:var(--uhcp-panel-muted);border:1px solid var(--uhcp-border);border-radius:1rem;display:grid;gap:.55rem;padding:1rem}.uhcp-consent-list article>div:first-child{align-items:center;display:flex;flex-wrap:wrap;gap:.55rem}.uhcp-consent-list article span{background:color-mix(in srgb,var(--uhcp-turquoise) 13%,transparent);border-radius:999px;font-size:.8rem;padding:.25rem .5rem}.uhcp-consent-actions{display:flex;flex-wrap:wrap;gap:.5rem}.uhcp-consent-editor{border-top:1px solid var(--uhcp-border);display:grid;gap:1rem;padding-top:1rem}.uhcp-consent-editor>label{display:grid;gap:.35rem}.uhcp-consent-editor fieldset{border:1px solid var(--uhcp-border);border-radius:1rem;display:flex;flex-wrap:wrap;gap:.75rem;margin:0;padding:1rem}.uhcp-consent-editor legend{font-weight:800;padding:0 .35rem}.uhcp-consent-editor fieldset label{align-items:center;display:flex;gap:.35rem}.uhcp-consent-editor>div{display:flex;gap:.6rem}@media(max-width:620px){.uhcp-consent-directory>header{display:grid}.uhcp-consent-editor fieldset{display:grid}}
|
|
776
777
|
.uhcp-loading-skeleton{background:var(--uhcp-panel);border:1px solid var(--uhcp-border);border-radius:2rem;display:grid;gap:1rem;margin:0 auto;max-width:1160px;overflow:hidden;padding:clamp(1.25rem,4vw,2.5rem);position:relative}.uhcp-loading-skeleton::after{animation:uhcp-loading-sweep 1.45s ease-in-out infinite;background:linear-gradient(90deg,transparent,color-mix(in srgb,#fff 42%,transparent),transparent);content:"";inset:0;position:absolute;transform:translateX(-100%)}.uhcp-loading-label{height:1px;overflow:hidden;position:absolute;width:1px;clip-path:inset(50%)}.uhcp-loading-heading,.uhcp-loading-copy,.uhcp-loading-row span{animation:uhcp-loading-pulse 1.45s ease-in-out infinite;background:color-mix(in srgb,var(--uhcp-muted) 17%,var(--uhcp-panel-muted));border-radius:999px}.uhcp-loading-heading{height:2.25rem;max-width:23rem;width:62%}.uhcp-loading-copy{height:1rem;max-width:38rem;width:86%}.uhcp-loading-grid{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(14rem,1fr));margin-top:.5rem}.uhcp-loading-row{background:var(--uhcp-panel-muted);border:1px solid var(--uhcp-border);border-radius:1.35rem;display:grid;gap:.8rem;padding:1.25rem}.uhcp-loading-row span{display:block;height:.8rem}.uhcp-loading-row span:nth-child(1){width:35%}.uhcp-loading-row span:nth-child(2){height:1.2rem;width:72%}.uhcp-loading-row span:nth-child(3){width:90%}.uhcp-loading-skeleton-compact{border-radius:1.25rem;padding:1.25rem}.uhcp-loading-skeleton-compact .uhcp-loading-heading{height:1.5rem}@keyframes uhcp-loading-pulse{0%,100%{opacity:.55}50%{opacity:1}}@keyframes uhcp-loading-sweep{to{transform:translateX(100%)}}@media(prefers-reduced-motion:reduce){.uhcp-loading-skeleton::after,.uhcp-loading-heading,.uhcp-loading-copy,.uhcp-loading-row span{animation:none}}
|
|
777
778
|
.uhcp-animal-onboarding { display: grid; gap: 1.25rem; }
|
|
@@ -835,28 +836,30 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
|
|
|
835
836
|
.uhcp-animal-card footer { min-width: 0; }
|
|
836
837
|
.uhcp-animal-card footer code { color: inherit; display: block; font-size: .68rem; opacity: .8; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
837
838
|
@media(max-width: 480px) { .uhcp-animal-card { aspect-ratio: auto; min-height: 17rem; } .uhcp-animal-card-qr { height: 6.25rem; width: 6.25rem; } }
|
|
838
|
-
.uhcp-smart-id-card-set { display: grid; gap: 1rem; width: min(100%,
|
|
839
|
-
.uhcp-smart-id-card { aspect-ratio: 5 / 8; border: 1px solid #cbd5e1; border-radius: 1.15rem; box-shadow: 0
|
|
840
|
-
.uhcp-smart-id-card-front { background:
|
|
841
|
-
.uhcp-smart-id-
|
|
842
|
-
.uhcp-smart-id-brand {
|
|
843
|
-
.uhcp-smart-id-
|
|
844
|
-
.uhcp-smart-id-
|
|
845
|
-
.uhcp-smart-id-brand span { font-size: .72rem; font-weight: 800; justify-self: end; text-align: end; }
|
|
846
|
-
.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); }
|
|
839
|
+
.uhcp-smart-id-card-set { display: grid; gap: 1rem; grid-template-columns: repeat(2, minmax(0, 19rem)); width: min(100%, 39rem); }
|
|
840
|
+
.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%; }
|
|
841
|
+
.uhcp-smart-id-card-front { background: #fff; color: #0f2942; display: grid; gap: .5rem; grid-template-rows: auto 1fr auto; }
|
|
842
|
+
.uhcp-smart-id-brand { align-items: center; display: flex; justify-content: center; min-height: 4.2rem; }
|
|
843
|
+
.uhcp-smart-id-brand img { display: block; height: 3.7rem; object-fit: contain; width: 5.6rem; }
|
|
844
|
+
.uhcp-smart-id-front-body { align-content: center; display: grid; gap: .55rem; justify-items: center; min-height: 0; }
|
|
845
|
+
.uhcp-smart-id-front-qr { aspect-ratio: 1; background: #fff; border: .2rem solid #fff; box-sizing: border-box; width: 68%; }
|
|
847
846
|
.uhcp-smart-id-front-qr > * { display: block; height: 100%; width: 100%; }
|
|
847
|
+
.uhcp-smart-id-subject-label { color: #0f2942; font-size: 1rem; font-weight: 800; line-height: 1.15; margin: 0; text-align: center; }
|
|
848
|
+
.uhcp-smart-id-card-front > footer { border-top: 1px solid #dbe3eb; display: grid; gap: .12rem; padding-top: .55rem; }
|
|
849
|
+
.uhcp-smart-id-card-front > footer span { color: #526174; font-size: .58rem; font-weight: 750; letter-spacing: .08em; text-transform: uppercase; }
|
|
850
|
+
.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; }
|
|
848
851
|
.uhcp-smart-id-card-back { background: #fff; color: #0f2942; display: grid; gap: .5rem; grid-template-rows: auto 1fr; }
|
|
849
|
-
.uhcp-smart-id-card-back > header {
|
|
850
|
-
.uhcp-smart-id-card-back > header strong { font-size: .68rem; letter-spacing: .
|
|
851
|
-
.uhcp-smart-id-
|
|
852
|
-
.uhcp-smart-id-back-body {
|
|
853
|
-
.uhcp-smart-id-back-body dl { display: grid; gap: .5rem; margin: 0; order: 2; }
|
|
852
|
+
.uhcp-smart-id-card-back > header { border-bottom: 2px solid #0f9ca8; padding-bottom: .45rem; }
|
|
853
|
+
.uhcp-smart-id-card-back > header strong { font-size: .68rem; letter-spacing: .07em; line-height: 1.15; }
|
|
854
|
+
.uhcp-smart-id-back-body { align-content: start; display: grid; gap: .65rem; grid-template-rows: auto auto; min-height: 0; }
|
|
855
|
+
.uhcp-smart-id-back-body dl { display: grid; gap: .4rem; margin: 0; order: 2; }
|
|
854
856
|
.uhcp-smart-id-back-body dt { color: #526174; font-size: .55rem; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; }
|
|
855
|
-
.uhcp-smart-id-back-body dd { font-
|
|
856
|
-
.uhcp-smart-id-identity-qr {
|
|
857
|
+
.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; }
|
|
858
|
+
.uhcp-smart-id-identity-qr { aspect-ratio: 1; background: #fff; box-sizing: border-box; justify-self: center; order: 1; width: 82%; }
|
|
857
859
|
.uhcp-smart-id-identity-qr > * { display: block; height: 100%; width: 100%; }
|
|
858
|
-
.uhcp-smart-id-unavailable {
|
|
859
|
-
@media
|
|
860
|
+
.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; }
|
|
861
|
+
@media (max-width: 40rem) { .uhcp-smart-id-card-set { grid-template-columns: minmax(0, 19rem); width: min(100%, 19rem); } }
|
|
862
|
+
@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; } }
|
|
860
863
|
.uhcp-animal-controller-attestation { border: 1px solid var(--uhcp-border, #d9dee7); border-radius: 1.25rem; display: grid; gap: 1rem; padding: 1rem; }
|
|
861
864
|
.uhcp-animal-controller-attestation header h2, .uhcp-animal-controller-attestation header p { margin: 0; }
|
|
862
865
|
.uhcp-animal-controller-attestation header p { color: var(--uhcp-muted, #5f6875); margin-top: .35rem; }
|
|
@@ -934,3 +937,39 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
|
|
|
934
937
|
.uhcp-auth-progress { align-items: center; display: flex; font-weight: 750; gap: .6rem; }
|
|
935
938
|
.uhcp-auth-progress > span { animation: uhcp-auth-spin .8s linear infinite; border: 3px solid var(--uhcp-line, #cbd5e1); border-radius: 50%; border-top-color: var(--uhcp-action-end, #2563a9); height: 1rem; width: 1rem; }
|
|
936
939
|
@keyframes uhcp-auth-spin { to { transform: rotate(360deg); } }
|
|
940
|
+
.uhcp-communications-tabs,
|
|
941
|
+
.uhcp-communications-topic-tabs {
|
|
942
|
+
display: flex;
|
|
943
|
+
flex-wrap: wrap;
|
|
944
|
+
gap: 0.75rem;
|
|
945
|
+
margin-bottom: 1rem;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
.uhcp-communications-tabs button,
|
|
949
|
+
.uhcp-communications-topic-tabs button {
|
|
950
|
+
min-height: 2.75rem;
|
|
951
|
+
border: 1px solid var(--uhcp-border, #cbd5e1);
|
|
952
|
+
border-radius: 999px;
|
|
953
|
+
padding: 0.625rem 1rem;
|
|
954
|
+
background: var(--uhcp-surface, #fff);
|
|
955
|
+
color: inherit;
|
|
956
|
+
font: inherit;
|
|
957
|
+
font-weight: 700;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
.uhcp-communications-tabs button[aria-selected='true'],
|
|
961
|
+
.uhcp-communications-topic-tabs button[aria-selected='true'] {
|
|
962
|
+
border-color: var(--uhcp-accent, #0f766e);
|
|
963
|
+
background: color-mix(in srgb, var(--uhcp-accent, #0f766e) 12%, transparent);
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
.uhcp-communications-topic-tabs button:disabled {
|
|
967
|
+
cursor: not-allowed;
|
|
968
|
+
opacity: 0.55;
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
.uhcp-selected-subject-workspace { display: grid; gap: 1rem; }
|
|
972
|
+
.uhcp-selected-subject-workspace > header { display: flex; align-items: start; justify-content: space-between; gap: 1rem; }
|
|
973
|
+
.uhcp-selected-subject-tabs { display: flex; flex-wrap: wrap; gap: 0.75rem; }
|
|
974
|
+
.uhcp-selected-subject-tabs button { min-height: 2.75rem; border: 1px solid var(--uhcp-border, #cbd5e1); border-radius: 999px; padding: 0.625rem 1rem; background: var(--uhcp-surface, #fff); color: inherit; font: inherit; font-weight: 700; }
|
|
975
|
+
.uhcp-selected-subject-tabs button[aria-selected='true'] { border-color: var(--uhcp-accent, #0f766e); background: color-mix(in srgb, var(--uhcp-accent, #0f766e) 12%, transparent); }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "uhc-portal-components-react",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.19",
|
|
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",
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
"react-dom": ">=18.3.0"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"fhir-data-utils-ts": "0.6.
|
|
34
|
+
"fhir-data-utils-ts": "0.6.21",
|
|
35
35
|
"gdc-common-utils-ts": "2.9.30",
|
|
36
|
-
"sos-data-utils-ts": "0.6.
|
|
36
|
+
"sos-data-utils-ts": "0.6.15",
|
|
37
37
|
"terminology-components-react": "0.2.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|