uhc-portal-components-react 0.1.11 → 0.1.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 +29 -0
- package/README.md +15 -5
- package/dist/IdentityEvidenceWorkspace.d.ts +60 -0
- package/dist/IdentityEvidenceWorkspace.d.ts.map +1 -0
- package/dist/IdentityEvidenceWorkspace.js +18 -0
- package/dist/LegalMarkdownDocument.d.ts +6 -0
- package/dist/LegalMarkdownDocument.d.ts.map +1 -0
- package/dist/LegalMarkdownDocument.js +56 -0
- package/dist/PortalLoadingSkeleton.d.ts +14 -0
- package/dist/PortalLoadingSkeleton.d.ts.map +1 -0
- package/dist/PortalLoadingSkeleton.js +11 -0
- package/dist/PortalSettingsPanel.d.ts +30 -0
- package/dist/PortalSettingsPanel.d.ts.map +1 -0
- package/dist/PortalSettingsPanel.js +31 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/styles.css +112 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,7 +1,36 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.15
|
|
4
|
+
|
|
5
|
+
- Add an accessible, animated `PortalLoadingSkeleton` that authenticated
|
|
6
|
+
portals render while provider data is pending, before any empty or stale
|
|
7
|
+
business state is eligible to appear.
|
|
8
|
+
|
|
9
|
+
## 0.1.14
|
|
10
|
+
|
|
11
|
+
- Add a brand-neutral, three-step identity-evidence workspace that keeps the
|
|
12
|
+
selected subject separate from the controller's reusable identifiers.
|
|
13
|
+
- Model self upload, authorized organization-worker upload and professional
|
|
14
|
+
attestation as independent host-confirmed capabilities; uploading evidence
|
|
15
|
+
never marks its signature or identity as verified in browser state.
|
|
16
|
+
|
|
17
|
+
## 0.1.13
|
|
18
|
+
|
|
19
|
+
- Render versioned legal Markdown as semantic headings, paragraphs, lists,
|
|
20
|
+
links and inline code instead of exposing source markers.
|
|
21
|
+
|
|
22
|
+
## 0.1.12
|
|
23
|
+
|
|
24
|
+
- Add a brand-neutral full-page account settings surface for security actions,
|
|
25
|
+
theme, text size, language and legal links, with a product-extension slot for
|
|
26
|
+
jurisdiction and data-use controls.
|
|
27
|
+
|
|
3
28
|
## Unreleased
|
|
4
29
|
|
|
30
|
+
- Correct the reuse contract: the package currently provides presentation
|
|
31
|
+
primitives, not the full UHC Personal route journeys. Document the extraction
|
|
32
|
+
required before PetChain can reuse login, protected profiles, individuals,
|
|
33
|
+
members/licences, clinical data and permissions without cloning the app.
|
|
5
34
|
- Add a brand-neutral protected-index and emergency-copy panel. Hosts supply
|
|
6
35
|
backend-confirmed records; protected storage, individual authorship and
|
|
7
36
|
emergency availability remain separate states, and professional release is
|
package/README.md
CHANGED
|
@@ -66,6 +66,11 @@ The package deliberately exposes modules instead of a cloned application:
|
|
|
66
66
|
employee lifecycle and invitation-status UI. Invitations remain host-owned
|
|
67
67
|
application records; the component does not reserve licenses or create GW
|
|
68
68
|
employees.
|
|
69
|
+
- `IdentityEvidenceWorkspace`: plain-language subject, controller-identifier
|
|
70
|
+
and evidence steps. The host supplies authorized subjects, identifiers and
|
|
71
|
+
exact capabilities for self upload, organization-worker upload or
|
|
72
|
+
professional attestation; ICA or another trusted backend verifies the
|
|
73
|
+
signature after upload.
|
|
69
74
|
|
|
70
75
|
Clinical label semantics stay in `gdc-common-utils-ts` / the SDK reader. Hosts
|
|
71
76
|
pass human titles to `ClinicalSectionSummary`: local `CodeableConcept.text`
|
|
@@ -93,8 +98,13 @@ token immediately; otherwise it records a `Communication` request for the
|
|
|
93
98
|
individual controller to review. The GW remains authoritative for the exact
|
|
94
99
|
intersection of requested and consented sections.
|
|
95
100
|
|
|
96
|
-
UHC Personal and
|
|
97
|
-
modules. UHC Professional and VetChain Professional must
|
|
98
|
-
professional
|
|
99
|
-
|
|
100
|
-
|
|
101
|
+
UHC Personal and PetChain Personal must ultimately compose the same reusable
|
|
102
|
+
personal flow modules. UHC Professional and VetChain Professional must do the
|
|
103
|
+
same for professional flows. This package does **not yet expose those complete
|
|
104
|
+
route modules**: login, versioned terms, profile protection, individual/member
|
|
105
|
+
management, licences, clinical data, care and permissions still live in the
|
|
106
|
+
UHC host application and must be extracted behind host-owned adapters. A brand
|
|
107
|
+
adapter may change tokens, logo, product vocabulary, animal-specific forms and
|
|
108
|
+
route destinations; it must not fork shared flow or authorization behavior.
|
|
109
|
+
|
|
110
|
+
See [`docs/PERSONAL_FLOW_EXTRACTION.md`](docs/PERSONAL_FLOW_EXTRACTION.md).
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
export type IdentityEvidenceStatus = 'verified' | 'pending' | 'rejected';
|
|
2
|
+
export type IdentityEvidenceUploadMode = 'self' | 'organization-worker' | 'professional-attestation';
|
|
3
|
+
export type IdentityEvidenceSubject = Readonly<{
|
|
4
|
+
id: string;
|
|
5
|
+
displayName: string;
|
|
6
|
+
kind: 'person' | 'animal';
|
|
7
|
+
}>;
|
|
8
|
+
export type IdentityEvidenceIdentifier = Readonly<{
|
|
9
|
+
id: string;
|
|
10
|
+
typeLabel: string;
|
|
11
|
+
jurisdictionLabel: string;
|
|
12
|
+
displayValue: string;
|
|
13
|
+
status: IdentityEvidenceStatus;
|
|
14
|
+
}>;
|
|
15
|
+
export type IdentityEvidenceCapabilities = Readonly<{
|
|
16
|
+
editSubject: boolean;
|
|
17
|
+
addIdentifier: boolean;
|
|
18
|
+
selfUpload: boolean;
|
|
19
|
+
organizationUpload: boolean;
|
|
20
|
+
professionalAttestation: boolean;
|
|
21
|
+
}>;
|
|
22
|
+
export type IdentityEvidenceWorkspaceCopy = Readonly<{
|
|
23
|
+
title: string;
|
|
24
|
+
intro: string;
|
|
25
|
+
selectedSubject: string;
|
|
26
|
+
subjectStepTitle: string;
|
|
27
|
+
subjectStepBody: string;
|
|
28
|
+
editSubject: string;
|
|
29
|
+
controllerStepTitle: string;
|
|
30
|
+
controllerStepBody: string;
|
|
31
|
+
noIdentifiers: string;
|
|
32
|
+
addIdentifier: string;
|
|
33
|
+
evidenceStepTitle: string;
|
|
34
|
+
evidenceStepBody: string;
|
|
35
|
+
selfUpload: string;
|
|
36
|
+
selfUploadHelp: string;
|
|
37
|
+
organizationUpload: string;
|
|
38
|
+
organizationUploadHelp: string;
|
|
39
|
+
professionalAttestation: string;
|
|
40
|
+
statusLabels: Readonly<Record<IdentityEvidenceStatus, string>>;
|
|
41
|
+
}>;
|
|
42
|
+
/**
|
|
43
|
+
* Brand-neutral identity-evidence journey for one backend-authorized subject.
|
|
44
|
+
*
|
|
45
|
+
* The host owns subject resolution, persistence and capabilities. This view
|
|
46
|
+
* keeps the managed subject separate from the controller's identifiers and
|
|
47
|
+
* keeps uploader, signer and verifier roles independent. Selecting an upload
|
|
48
|
+
* route never changes evidence status in browser state.
|
|
49
|
+
*/
|
|
50
|
+
export declare function IdentityEvidenceWorkspace({ copy, subject, identifiers, capabilities, onEditSubject, onAddIdentifier, onSelectIdentifier, onUploadEvidence, }: Readonly<{
|
|
51
|
+
copy: IdentityEvidenceWorkspaceCopy;
|
|
52
|
+
subject: IdentityEvidenceSubject;
|
|
53
|
+
identifiers: readonly IdentityEvidenceIdentifier[];
|
|
54
|
+
capabilities: IdentityEvidenceCapabilities;
|
|
55
|
+
onEditSubject?: () => void;
|
|
56
|
+
onAddIdentifier?: () => void;
|
|
57
|
+
onSelectIdentifier?: (identifierId: string) => void;
|
|
58
|
+
onUploadEvidence?: (mode: IdentityEvidenceUploadMode) => void;
|
|
59
|
+
}>): import("react").JSX.Element;
|
|
60
|
+
//# sourceMappingURL=IdentityEvidenceWorkspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IdentityEvidenceWorkspace.d.ts","sourceRoot":"","sources":["../src/IdentityEvidenceWorkspace.tsx"],"names":[],"mappings":"AAAA,MAAM,MAAM,sBAAsB,GAAG,UAAU,GAAG,SAAS,GAAG,UAAU,CAAA;AAExE,MAAM,MAAM,0BAA0B,GAClC,MAAM,GACN,qBAAqB,GACrB,0BAA0B,CAAA;AAE9B,MAAM,MAAM,uBAAuB,GAAG,QAAQ,CAAC;IAC7C,EAAE,EAAE,MAAM,CAAA;IACV,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,QAAQ,GAAG,QAAQ,CAAA;CAC1B,CAAC,CAAA;AAEF,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAAC;IAChD,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,iBAAiB,EAAE,MAAM,CAAA;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,MAAM,EAAE,sBAAsB,CAAA;CAC/B,CAAC,CAAA;AAEF,MAAM,MAAM,4BAA4B,GAAG,QAAQ,CAAC;IAClD,WAAW,EAAE,OAAO,CAAA;IACpB,aAAa,EAAE,OAAO,CAAA;IACtB,UAAU,EAAE,OAAO,CAAA;IACnB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,uBAAuB,EAAE,OAAO,CAAA;CACjC,CAAC,CAAA;AAEF,MAAM,MAAM,6BAA6B,GAAG,QAAQ,CAAC;IACnD,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,eAAe,EAAE,MAAM,CAAA;IACvB,gBAAgB,EAAE,MAAM,CAAA;IACxB,eAAe,EAAE,MAAM,CAAA;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,kBAAkB,EAAE,MAAM,CAAA;IAC1B,aAAa,EAAE,MAAM,CAAA;IACrB,aAAa,EAAE,MAAM,CAAA;IACrB,iBAAiB,EAAE,MAAM,CAAA;IACzB,gBAAgB,EAAE,MAAM,CAAA;IACxB,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;IACtB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,sBAAsB,EAAE,MAAM,CAAA;IAC9B,uBAAuB,EAAE,MAAM,CAAA;IAC/B,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAC,CAAA;CAC/D,CAAC,CAAA;AAEF;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,IAAI,EACJ,OAAO,EACP,WAAW,EACX,YAAY,EACZ,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,gBAAgB,GACjB,EAAE,QAAQ,CAAC;IACV,IAAI,EAAE,6BAA6B,CAAA;IACnC,OAAO,EAAE,uBAAuB,CAAA;IAChC,WAAW,EAAE,SAAS,0BAA0B,EAAE,CAAA;IAClD,YAAY,EAAE,4BAA4B,CAAA;IAC1C,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,eAAe,CAAC,EAAE,MAAM,IAAI,CAAA;IAC5B,kBAAkB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAA;IACnD,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,0BAA0B,KAAK,IAAI,CAAA;CAC9D,CAAC,+BAkGD"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Brand-neutral identity-evidence journey for one backend-authorized subject.
|
|
4
|
+
*
|
|
5
|
+
* The host owns subject resolution, persistence and capabilities. This view
|
|
6
|
+
* keeps the managed subject separate from the controller's identifiers and
|
|
7
|
+
* keeps uploader, signer and verifier roles independent. Selecting an upload
|
|
8
|
+
* route never changes evidence status in browser state.
|
|
9
|
+
*/
|
|
10
|
+
export function IdentityEvidenceWorkspace({ copy, subject, identifiers, capabilities, onEditSubject, onAddIdentifier, onSelectIdentifier, onUploadEvidence, }) {
|
|
11
|
+
return (_jsxs("section", { className: "uhcp-identity-workspace", "aria-labelledby": "identity-evidence-workspace-title", children: [_jsxs("header", { className: "uhcp-identity-workspace-heading", children: [_jsx("h2", { id: "identity-evidence-workspace-title", children: copy.title }), _jsx("p", { children: copy.intro })] }), _jsxs("ol", { className: "uhcp-identity-steps", children: [_jsxs("li", { className: "uhcp-identity-step", children: [_jsx(StepNumber, { value: 1 }), _jsxs("div", { className: "uhcp-identity-step-content", children: [_jsx("h3", { children: copy.subjectStepTitle }), _jsx("p", { children: copy.subjectStepBody }), _jsxs("div", { className: "uhcp-identity-subject", children: [_jsx("span", { children: copy.selectedSubject }), _jsx("strong", { children: subject.displayName })] }), capabilities.editSubject && onEditSubject ? (_jsx("button", { type: "button", className: "uhcp-identity-secondary-action", onClick: onEditSubject, children: copy.editSubject })) : null] })] }), _jsxs("li", { className: "uhcp-identity-step", children: [_jsx(StepNumber, { value: 2 }), _jsxs("div", { className: "uhcp-identity-step-content", children: [_jsx("h3", { children: copy.controllerStepTitle }), _jsx("p", { children: copy.controllerStepBody }), identifiers.length === 0 ? (_jsx("p", { className: "uhcp-identity-empty", children: copy.noIdentifiers })) : (_jsx("ul", { className: "uhcp-identity-identifiers", children: identifiers.map((identifier) => (_jsx("li", { children: _jsxs("button", { type: "button", onClick: () => onSelectIdentifier?.(identifier.id), disabled: !onSelectIdentifier, "aria-label": `${identifier.typeLabel}, ${identifier.jurisdictionLabel}, ${identifier.displayValue}`, children: [_jsxs("span", { children: [_jsx("strong", { children: identifier.typeLabel }), _jsxs("small", { children: [identifier.jurisdictionLabel, " \u00B7 ", identifier.displayValue] })] }), _jsx("span", { className: `uhcp-identity-status uhcp-identity-status-${identifier.status}`, children: copy.statusLabels[identifier.status] })] }) }, identifier.id))) })), capabilities.addIdentifier && onAddIdentifier ? (_jsx("button", { type: "button", className: "uhcp-identity-secondary-action", onClick: onAddIdentifier, children: copy.addIdentifier })) : null] })] }), _jsxs("li", { className: "uhcp-identity-step", children: [_jsx(StepNumber, { value: 3 }), _jsxs("div", { className: "uhcp-identity-step-content", children: [_jsx("h3", { children: copy.evidenceStepTitle }), _jsx("p", { children: copy.evidenceStepBody }), _jsxs("div", { className: "uhcp-identity-upload-actions", children: [capabilities.selfUpload ? (_jsx(UploadAction, { title: copy.selfUpload, help: copy.selfUploadHelp, onClick: () => onUploadEvidence?.('self'), disabled: !onUploadEvidence })) : null, capabilities.organizationUpload ? (_jsx(UploadAction, { title: copy.organizationUpload, help: copy.organizationUploadHelp, onClick: () => onUploadEvidence?.('organization-worker'), disabled: !onUploadEvidence })) : null, capabilities.professionalAttestation ? (_jsx(UploadAction, { title: copy.professionalAttestation, onClick: () => onUploadEvidence?.('professional-attestation'), disabled: !onUploadEvidence })) : null] })] })] })] })] }));
|
|
12
|
+
}
|
|
13
|
+
function StepNumber({ value }) {
|
|
14
|
+
return _jsx("span", { className: "uhcp-identity-step-number", "aria-hidden": "true", children: value });
|
|
15
|
+
}
|
|
16
|
+
function UploadAction({ title, help, onClick, disabled, }) {
|
|
17
|
+
return (_jsxs("button", { type: "button", className: "uhcp-identity-upload-action", "aria-label": title, onClick: onClick, disabled: disabled, children: [_jsx("strong", { children: title }), help ? _jsx("small", { children: help }) : null] }));
|
|
18
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type JSX } from 'react';
|
|
2
|
+
/** Renders the deliberately small Markdown subset used by versioned legal notices. */
|
|
3
|
+
export declare function LegalMarkdownDocument({ source }: Readonly<{
|
|
4
|
+
source: string;
|
|
5
|
+
}>): JSX.Element;
|
|
6
|
+
//# sourceMappingURL=LegalMarkdownDocument.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LegalMarkdownDocument.d.ts","sourceRoot":"","sources":["../src/LegalMarkdownDocument.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAY,KAAK,GAAG,EAAkB,MAAM,OAAO,CAAA;AAa1D,sFAAsF;AACtF,wBAAgB,qBAAqB,CAAC,EAAE,MAAM,EAAE,EAAE,QAAQ,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,eAmC7E"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Fragment } from 'react';
|
|
3
|
+
function inlineMarkdown(value) {
|
|
4
|
+
const parts = value.split(/(`[^`]+`|\[[^\]]+\]\(https?:\/\/[^)]+\)|\*\*[^*]+\*\*)/g).filter(Boolean);
|
|
5
|
+
return parts.map((part, index) => {
|
|
6
|
+
if (part.startsWith('`') && part.endsWith('`'))
|
|
7
|
+
return _jsx("code", { children: part.slice(1, -1) }, index);
|
|
8
|
+
const link = part.match(/^\[([^\]]+)\]\((https?:\/\/[^)]+)\)$/);
|
|
9
|
+
if (link)
|
|
10
|
+
return _jsx("a", { href: link[2], rel: "noreferrer", children: link[1] }, index);
|
|
11
|
+
if (part.startsWith('**') && part.endsWith('**'))
|
|
12
|
+
return _jsx("strong", { children: part.slice(2, -2) }, index);
|
|
13
|
+
return _jsx(Fragment, { children: part }, index);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
/** Renders the deliberately small Markdown subset used by versioned legal notices. */
|
|
17
|
+
export function LegalMarkdownDocument({ source }) {
|
|
18
|
+
const lines = source.replace(/\r\n/g, '\n').split('\n');
|
|
19
|
+
const blocks = [];
|
|
20
|
+
let index = 0;
|
|
21
|
+
while (index < lines.length) {
|
|
22
|
+
const line = lines[index].trim();
|
|
23
|
+
if (!line) {
|
|
24
|
+
index += 1;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
const heading = line.match(/^(#{1,6})\s+(.+)$/);
|
|
28
|
+
if (heading) {
|
|
29
|
+
const level = Math.min(6, heading[1].length + 1);
|
|
30
|
+
const Heading = `h${level}`;
|
|
31
|
+
blocks.push(_jsx(Heading, { children: inlineMarkdown(heading[2]) }, `h-${index}`));
|
|
32
|
+
index += 1;
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
if (/^-\s+/.test(line)) {
|
|
36
|
+
const items = [];
|
|
37
|
+
while (index < lines.length && /^-\s+/.test(lines[index].trim())) {
|
|
38
|
+
items.push(_jsx("li", { children: inlineMarkdown(lines[index].trim().replace(/^-\s+/, '')) }, index));
|
|
39
|
+
index += 1;
|
|
40
|
+
}
|
|
41
|
+
blocks.push(_jsx("ul", { children: items }, `ul-${index}`));
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
const paragraph = [line];
|
|
45
|
+
index += 1;
|
|
46
|
+
while (index < lines.length) {
|
|
47
|
+
const next = lines[index].trim();
|
|
48
|
+
if (!next || /^(#{1,6})\s+/.test(next) || /^-\s+/.test(next))
|
|
49
|
+
break;
|
|
50
|
+
paragraph.push(next);
|
|
51
|
+
index += 1;
|
|
52
|
+
}
|
|
53
|
+
blocks.push(_jsx("p", { children: inlineMarkdown(paragraph.join(' ')) }, `p-${index}`));
|
|
54
|
+
}
|
|
55
|
+
return _jsx("div", { className: "uhcp-legal-document", children: blocks });
|
|
56
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type PortalLoadingSkeletonProps = Readonly<{
|
|
2
|
+
label: string;
|
|
3
|
+
rows?: number;
|
|
4
|
+
compact?: boolean;
|
|
5
|
+
}>;
|
|
6
|
+
/**
|
|
7
|
+
* Shared neutral loading surface for authenticated portal data.
|
|
8
|
+
*
|
|
9
|
+
* Hosts render this instead of business empty states while a BFF/provider
|
|
10
|
+
* read is pending. It contains no inferred card, identity or authorization
|
|
11
|
+
* data and therefore cannot flash stale or misleading content.
|
|
12
|
+
*/
|
|
13
|
+
export declare function PortalLoadingSkeleton({ label, rows, compact, }: PortalLoadingSkeletonProps): import("react").JSX.Element;
|
|
14
|
+
//# sourceMappingURL=PortalLoadingSkeleton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PortalLoadingSkeleton.d.ts","sourceRoot":"","sources":["../src/PortalLoadingSkeleton.tsx"],"names":[],"mappings":"AAAA,MAAM,MAAM,0BAA0B,GAAG,QAAQ,CAAC;IAChD,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAC,CAAA;AAEF;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,KAAK,EACL,IAAQ,EACR,OAAe,GAChB,EAAE,0BAA0B,+BAsB5B"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* Shared neutral loading surface for authenticated portal data.
|
|
4
|
+
*
|
|
5
|
+
* Hosts render this instead of business empty states while a BFF/provider
|
|
6
|
+
* read is pending. It contains no inferred card, identity or authorization
|
|
7
|
+
* data and therefore cannot flash stale or misleading content.
|
|
8
|
+
*/
|
|
9
|
+
export function PortalLoadingSkeleton({ label, rows = 3, compact = false, }) {
|
|
10
|
+
return (_jsxs("section", { className: `uhcp-loading-skeleton${compact ? ' uhcp-loading-skeleton-compact' : ''}`, role: "status", "aria-busy": "true", "aria-live": "polite", children: [_jsx("span", { className: "uhcp-loading-label", children: label }), _jsx("div", { className: "uhcp-loading-heading", "aria-hidden": "true" }), _jsx("div", { className: "uhcp-loading-copy", "aria-hidden": "true" }), _jsx("div", { className: "uhcp-loading-grid", "aria-hidden": "true", children: Array.from({ length: Math.max(1, rows) }, (_, index) => (_jsxs("div", { className: "uhcp-loading-row", children: [_jsx("span", {}), _jsx("span", {}), _jsx("span", {})] }, index))) })] }));
|
|
11
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import { type PortalLanguageOption, type PortalMenuAction, type PortalUiDensity, type PortalUiTheme } from './contracts.js';
|
|
3
|
+
export type PortalSettingsCopy = Readonly<{
|
|
4
|
+
title: string;
|
|
5
|
+
description: string;
|
|
6
|
+
security: string;
|
|
7
|
+
appearance: string;
|
|
8
|
+
theme: string;
|
|
9
|
+
textSize: string;
|
|
10
|
+
language: string;
|
|
11
|
+
legal: string;
|
|
12
|
+
themes: Record<PortalUiTheme, string>;
|
|
13
|
+
densities: Record<PortalUiDensity, string>;
|
|
14
|
+
}>;
|
|
15
|
+
export type PortalSettingsLink = Readonly<{
|
|
16
|
+
id: string;
|
|
17
|
+
label: string;
|
|
18
|
+
href: string;
|
|
19
|
+
}>;
|
|
20
|
+
export type PortalSettingsPanelProps = Readonly<{
|
|
21
|
+
copy: PortalSettingsCopy;
|
|
22
|
+
storageNamespace: string;
|
|
23
|
+
languageOptions: readonly PortalLanguageOption[];
|
|
24
|
+
securityActions?: readonly PortalMenuAction[];
|
|
25
|
+
legalLinks: readonly PortalSettingsLink[];
|
|
26
|
+
children?: ReactNode;
|
|
27
|
+
}>;
|
|
28
|
+
/** Shared settings surface. Product-specific privacy controls enter as children. */
|
|
29
|
+
export declare function PortalSettingsPanel({ copy, storageNamespace, languageOptions, securityActions, legalLinks, children, }: PortalSettingsPanelProps): import("react").JSX.Element;
|
|
30
|
+
//# sourceMappingURL=PortalSettingsPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PortalSettingsPanel.d.ts","sourceRoot":"","sources":["../src/PortalSettingsPanel.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAC3D,OAAO,EAGL,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,aAAa,EACnB,MAAM,gBAAgB,CAAA;AAGvB,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IACxC,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAA;IACrC,SAAS,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAAC,CAAA;CAC3C,CAAC,CAAA;AAEF,MAAM,MAAM,kBAAkB,GAAG,QAAQ,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAEtF,MAAM,MAAM,wBAAwB,GAAG,QAAQ,CAAC;IAC9C,IAAI,EAAE,kBAAkB,CAAA;IACxB,gBAAgB,EAAE,MAAM,CAAA;IACxB,eAAe,EAAE,SAAS,oBAAoB,EAAE,CAAA;IAChD,eAAe,CAAC,EAAE,SAAS,gBAAgB,EAAE,CAAA;IAC7C,UAAU,EAAE,SAAS,kBAAkB,EAAE,CAAA;IACzC,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB,CAAC,CAAA;AAEF,oFAAoF;AACpF,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,gBAAgB,EAChB,eAAe,EACf,eAAoB,EACpB,UAAU,EACV,QAAQ,GACT,EAAE,wBAAwB,+BAwC1B"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from 'react';
|
|
4
|
+
import { portalUiDensities, portalUiThemes, } from './contracts.js';
|
|
5
|
+
import { resolvePortalUiDensity, resolvePortalUiTheme, resolveRenderedPortalTheme } from './preferences.js';
|
|
6
|
+
/** Shared settings surface. Product-specific privacy controls enter as children. */
|
|
7
|
+
export function PortalSettingsPanel({ copy, storageNamespace, languageOptions, securityActions = [], legalLinks, children, }) {
|
|
8
|
+
const [theme, setTheme] = useState('system');
|
|
9
|
+
const [density, setDensity] = useState('medium');
|
|
10
|
+
const themeKey = `${storageNamespace}.theme`;
|
|
11
|
+
const densityKey = `${storageNamespace}.density`;
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
setTheme(resolvePortalUiTheme(localStorage.getItem(themeKey)));
|
|
14
|
+
setDensity(resolvePortalUiDensity(localStorage.getItem(densityKey)));
|
|
15
|
+
}, [densityKey, themeKey]);
|
|
16
|
+
function changeTheme(value) {
|
|
17
|
+
setTheme(value);
|
|
18
|
+
localStorage.setItem(themeKey, value);
|
|
19
|
+
const rendered = resolveRenderedPortalTheme(value, matchMedia('(prefers-color-scheme: dark)').matches);
|
|
20
|
+
document.documentElement.dataset.theme = rendered;
|
|
21
|
+
document.documentElement.style.colorScheme = rendered;
|
|
22
|
+
}
|
|
23
|
+
function changeDensity(value) {
|
|
24
|
+
setDensity(value);
|
|
25
|
+
localStorage.setItem(densityKey, value);
|
|
26
|
+
document.documentElement.dataset.density = value;
|
|
27
|
+
}
|
|
28
|
+
return (_jsxs("main", { className: "uhcp-settings", children: [_jsxs("header", { children: [_jsx("h1", { children: copy.title }), _jsx("p", { children: copy.description })] }), _jsxs("section", { children: [_jsx("h2", { children: copy.security }), _jsx("div", { className: "uhcp-settings-links", children: securityActions.map((action) => action.href
|
|
29
|
+
? _jsx("a", { href: action.href, children: action.label }, action.id)
|
|
30
|
+
: _jsx("button", { type: "button", onClick: () => void action.onSelect?.(), children: action.label }, action.id)) })] }), children, _jsxs("section", { children: [_jsx("h2", { children: copy.appearance }), _jsxs("fieldset", { children: [_jsx("legend", { children: copy.theme }), portalUiThemes.map((value) => _jsx("button", { type: "button", "aria-pressed": theme === value, onClick: () => changeTheme(value), children: copy.themes[value] }, value))] }), _jsxs("fieldset", { children: [_jsx("legend", { children: copy.textSize }), portalUiDensities.map((value) => _jsx("button", { type: "button", "aria-pressed": density === value, onClick: () => changeDensity(value), children: copy.densities[value] }, value))] })] }), _jsxs("section", { children: [_jsx("h2", { children: copy.language }), _jsx("div", { className: "uhcp-settings-links", children: languageOptions.map((option) => _jsx("a", { href: option.href, hrefLang: option.id, "aria-current": option.current ? 'page' : undefined, children: option.label }, option.id)) })] }), _jsxs("section", { children: [_jsx("h2", { children: copy.legal }), _jsx("div", { className: "uhcp-settings-links", children: legalLinks.map((link) => _jsx("a", { href: link.href, children: link.label }, link.id)) })] })] }));
|
|
31
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export * from './PortalHeader.js';
|
|
|
5
5
|
export * from './PortalShell.js';
|
|
6
6
|
export * from './PortalEntry.js';
|
|
7
7
|
export * from './ProfileProtectionGate.js';
|
|
8
|
+
export * from './PortalLoadingSkeleton.js';
|
|
8
9
|
export * from './ClinicalSectionSummary.js';
|
|
9
10
|
export * from './IpsBundleSummary.js';
|
|
10
11
|
export * from './InvitationAcceptancePanel.js';
|
|
@@ -12,4 +13,7 @@ export * from './SubjectAccessRequestPanel.js';
|
|
|
12
13
|
export * from './SoschainWorkspace.js';
|
|
13
14
|
export * from './OrganizationWorkforceAdministration.js';
|
|
14
15
|
export * from './ProtectedIndexEmergencyData.js';
|
|
16
|
+
export * from './PortalSettingsPanel.js';
|
|
17
|
+
export * from './LegalMarkdownDocument.js';
|
|
18
|
+
export * from './IdentityEvidenceWorkspace.js';
|
|
15
19
|
//# 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,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA;AACrC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,0CAA0C,CAAA;AACxD,cAAc,kCAAkC,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,kBAAkB,CAAA;AAChC,cAAc,kBAAkB,CAAA;AAChC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,uBAAuB,CAAA;AACrC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,0CAA0C,CAAA;AACxD,cAAc,kCAAkC,CAAA;AAChD,cAAc,0BAA0B,CAAA;AACxC,cAAc,4BAA4B,CAAA;AAC1C,cAAc,gCAAgC,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export * from './PortalHeader.js';
|
|
|
5
5
|
export * from './PortalShell.js';
|
|
6
6
|
export * from './PortalEntry.js';
|
|
7
7
|
export * from './ProfileProtectionGate.js';
|
|
8
|
+
export * from './PortalLoadingSkeleton.js';
|
|
8
9
|
export * from './ClinicalSectionSummary.js';
|
|
9
10
|
export * from './IpsBundleSummary.js';
|
|
10
11
|
export * from './InvitationAcceptancePanel.js';
|
|
@@ -12,3 +13,6 @@ export * from './SubjectAccessRequestPanel.js';
|
|
|
12
13
|
export * from './SoschainWorkspace.js';
|
|
13
14
|
export * from './OrganizationWorkforceAdministration.js';
|
|
14
15
|
export * from './ProtectedIndexEmergencyData.js';
|
|
16
|
+
export * from './PortalSettingsPanel.js';
|
|
17
|
+
export * from './LegalMarkdownDocument.js';
|
|
18
|
+
export * from './IdentityEvidenceWorkspace.js';
|
package/dist/styles.css
CHANGED
|
@@ -172,6 +172,115 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
|
|
|
172
172
|
padding: 1.25rem;
|
|
173
173
|
}
|
|
174
174
|
|
|
175
|
+
.uhcp-identity-workspace {
|
|
176
|
+
background: var(--uhcp-panel);
|
|
177
|
+
border: 1px solid var(--uhcp-border);
|
|
178
|
+
border-radius: 2rem;
|
|
179
|
+
color: var(--uhcp-text);
|
|
180
|
+
padding: clamp(1.25rem, 3vw, 2rem);
|
|
181
|
+
}
|
|
182
|
+
.uhcp-identity-workspace h2,
|
|
183
|
+
.uhcp-identity-workspace h3,
|
|
184
|
+
.uhcp-identity-workspace p { margin: 0; }
|
|
185
|
+
.uhcp-identity-workspace-heading { max-width: 46rem; }
|
|
186
|
+
.uhcp-identity-workspace-heading h2 { font-size: clamp(1.5rem, 3vw, 2rem); }
|
|
187
|
+
.uhcp-identity-workspace-heading p,
|
|
188
|
+
.uhcp-identity-step-content > p { color: var(--uhcp-muted); line-height: 1.6; margin-top: .5rem; }
|
|
189
|
+
.uhcp-identity-steps { display: grid; gap: 0; list-style: none; margin: 1.75rem 0 0; padding: 0; }
|
|
190
|
+
.uhcp-identity-step { display: grid; gap: 1rem; grid-template-columns: 2.25rem minmax(0, 1fr); position: relative; }
|
|
191
|
+
.uhcp-identity-step:not(:last-child)::before {
|
|
192
|
+
background: var(--uhcp-border);
|
|
193
|
+
content: '';
|
|
194
|
+
height: calc(100% - 2.25rem);
|
|
195
|
+
left: 1.09rem;
|
|
196
|
+
position: absolute;
|
|
197
|
+
top: 2.25rem;
|
|
198
|
+
width: 2px;
|
|
199
|
+
}
|
|
200
|
+
.uhcp-identity-step-number {
|
|
201
|
+
align-items: center;
|
|
202
|
+
background: var(--uhcp-surface-accent);
|
|
203
|
+
border: 1px solid color-mix(in srgb, var(--uhcp-turquoise) 42%, var(--uhcp-border));
|
|
204
|
+
border-radius: 999px;
|
|
205
|
+
color: var(--uhcp-turquoise);
|
|
206
|
+
display: flex;
|
|
207
|
+
font-weight: 900;
|
|
208
|
+
height: 2.25rem;
|
|
209
|
+
justify-content: center;
|
|
210
|
+
position: relative;
|
|
211
|
+
width: 2.25rem;
|
|
212
|
+
z-index: 1;
|
|
213
|
+
}
|
|
214
|
+
.uhcp-identity-step-content { padding: .25rem 0 1.75rem; }
|
|
215
|
+
.uhcp-identity-step:last-child .uhcp-identity-step-content { padding-bottom: 0; }
|
|
216
|
+
.uhcp-identity-subject {
|
|
217
|
+
background: var(--uhcp-panel-muted);
|
|
218
|
+
border-radius: 1rem;
|
|
219
|
+
display: grid;
|
|
220
|
+
gap: .2rem;
|
|
221
|
+
margin-top: 1rem;
|
|
222
|
+
padding: .9rem 1rem;
|
|
223
|
+
}
|
|
224
|
+
.uhcp-identity-subject span,
|
|
225
|
+
.uhcp-identity-subject small { color: var(--uhcp-muted); font-size: .78rem; }
|
|
226
|
+
.uhcp-identity-empty { color: var(--uhcp-muted); margin-top: 1rem !important; }
|
|
227
|
+
.uhcp-identity-identifiers { display: grid; gap: .65rem; list-style: none; margin: 1rem 0 0; padding: 0; }
|
|
228
|
+
.uhcp-identity-identifiers button {
|
|
229
|
+
align-items: center;
|
|
230
|
+
background: var(--uhcp-panel-muted);
|
|
231
|
+
border: 1px solid transparent;
|
|
232
|
+
border-radius: 1rem;
|
|
233
|
+
color: var(--uhcp-text);
|
|
234
|
+
display: flex;
|
|
235
|
+
font: inherit;
|
|
236
|
+
gap: 1rem;
|
|
237
|
+
justify-content: space-between;
|
|
238
|
+
padding: .9rem 1rem;
|
|
239
|
+
text-align: left;
|
|
240
|
+
width: 100%;
|
|
241
|
+
}
|
|
242
|
+
.uhcp-identity-identifiers button:not(:disabled) { cursor: pointer; }
|
|
243
|
+
.uhcp-identity-identifiers button:not(:disabled):hover { border-color: var(--uhcp-turquoise); }
|
|
244
|
+
.uhcp-identity-identifiers button:disabled { opacity: 1; }
|
|
245
|
+
.uhcp-identity-identifiers button > span:first-child { display: grid; gap: .25rem; }
|
|
246
|
+
.uhcp-identity-identifiers small { color: var(--uhcp-muted); }
|
|
247
|
+
.uhcp-identity-status { border-radius: 999px; font-size: .72rem; font-weight: 800; padding: .35rem .6rem; }
|
|
248
|
+
.uhcp-identity-status-verified { background: color-mix(in srgb, var(--uhcp-emerald) 15%, transparent); color: var(--uhcp-emerald); }
|
|
249
|
+
.uhcp-identity-status-pending { background: color-mix(in srgb, var(--uhcp-attention) 18%, transparent); color: color-mix(in srgb, var(--uhcp-attention) 72%, var(--uhcp-text)); }
|
|
250
|
+
.uhcp-identity-status-rejected { background: color-mix(in srgb, #c64747 14%, transparent); color: #c64747; }
|
|
251
|
+
.uhcp-identity-secondary-action {
|
|
252
|
+
background: transparent;
|
|
253
|
+
border: 1px solid var(--uhcp-border);
|
|
254
|
+
border-radius: .85rem;
|
|
255
|
+
color: var(--uhcp-text);
|
|
256
|
+
cursor: pointer;
|
|
257
|
+
font: inherit;
|
|
258
|
+
font-weight: 800;
|
|
259
|
+
margin-top: 1rem;
|
|
260
|
+
min-height: 2.75rem;
|
|
261
|
+
padding: .65rem 1rem;
|
|
262
|
+
}
|
|
263
|
+
.uhcp-identity-secondary-action:hover { border-color: var(--uhcp-turquoise); color: var(--uhcp-turquoise); }
|
|
264
|
+
.uhcp-identity-upload-actions { display: grid; gap: .75rem; margin-top: 1rem; }
|
|
265
|
+
.uhcp-identity-upload-action {
|
|
266
|
+
background: var(--uhcp-panel-muted);
|
|
267
|
+
border: 1px solid var(--uhcp-border);
|
|
268
|
+
border-radius: 1rem;
|
|
269
|
+
color: var(--uhcp-text);
|
|
270
|
+
cursor: pointer;
|
|
271
|
+
display: grid;
|
|
272
|
+
font: inherit;
|
|
273
|
+
gap: .25rem;
|
|
274
|
+
padding: 1rem;
|
|
275
|
+
text-align: left;
|
|
276
|
+
}
|
|
277
|
+
.uhcp-identity-upload-action:hover { border-color: var(--uhcp-turquoise); }
|
|
278
|
+
.uhcp-identity-upload-action:disabled { cursor: not-allowed; opacity: .6; }
|
|
279
|
+
.uhcp-identity-upload-action small { color: var(--uhcp-muted); line-height: 1.45; }
|
|
280
|
+
@media (min-width: 760px) {
|
|
281
|
+
.uhcp-identity-upload-actions { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
282
|
+
}
|
|
283
|
+
|
|
175
284
|
.uhcp-clinical-summary {
|
|
176
285
|
display: grid;
|
|
177
286
|
gap: 1rem;
|
|
@@ -344,3 +453,6 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
|
|
|
344
453
|
.uhcp-emergency-copy-list small, .uhcp-emergency-copy-list li > span, .uhcp-emergency-copy-empty { color: var(--uhcp-muted); }
|
|
345
454
|
.uhcp-emergency-copy-empty { margin: 1.5rem 0 0; }
|
|
346
455
|
@media (max-width: 620px) { .uhcp-emergency-copy > header { display: grid; } .uhcp-emergency-copy-legend { width: 100%; } }
|
|
456
|
+
.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}
|
|
457
|
+
.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}
|
|
458
|
+
.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}}
|
package/package.json
CHANGED