uhc-portal-components-react 0.2.6 → 0.2.8
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 +13 -1
- package/dist/AnimalIdentityOnboarding.d.ts +5 -0
- package/dist/AnimalIdentityOnboarding.d.ts.map +1 -1
- package/dist/AnimalIdentityOnboardingV2.d.ts +31 -1
- package/dist/AnimalIdentityOnboardingV2.d.ts.map +1 -1
- package/dist/AnimalIdentityOnboardingV2.js +79 -8
- package/dist/styles.css +11 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 0.2.8 - 2026-10-10
|
|
4
|
+
|
|
5
|
+
- Restore the visual animal-photo picker from the earlier VetChain Expo flow:
|
|
6
|
+
click or drop a PNG/JPG, preview it, remove it in place, and enforce the
|
|
7
|
+
documented 2 MiB maximum and portrait 3:4 minimum of 300 by 400 pixels.
|
|
8
|
+
- Extend the opt-in animal identity flow with person/organization ownership,
|
|
9
|
+
country and optional regional jurisdiction, governed identifier choices,
|
|
10
|
+
email-or-telephone contact and OIDC4IDA verification method selection.
|
|
11
|
+
|
|
12
|
+
## 0.2.7 - 2026-10-09
|
|
13
|
+
|
|
14
|
+
- Give every V2 animal-onboarding disclosure an accessible group name derived
|
|
15
|
+
from its localized summary.
|
|
4
16
|
|
|
5
17
|
## 0.2.6 - 2026-10-09
|
|
6
18
|
|
|
@@ -11,6 +11,11 @@ export type AnimalIdentityOnboardingInput = Readonly<{
|
|
|
11
11
|
controllerIdentifierType: string;
|
|
12
12
|
controllerIdentifierValue: string;
|
|
13
13
|
controllerCountry: string;
|
|
14
|
+
controllerKind?: 'person' | 'organization';
|
|
15
|
+
controllerRegion?: string;
|
|
16
|
+
controllerEmail?: string;
|
|
17
|
+
controllerTelephone?: string;
|
|
18
|
+
verificationMethod?: 'pipp' | 'sripp' | 'eid' | 'uripp';
|
|
14
19
|
relationship: AnimalControllerRelationship;
|
|
15
20
|
ownerDocument: File;
|
|
16
21
|
animalDocument: File;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnimalIdentityOnboarding.d.ts","sourceRoot":"","sources":["../src/AnimalIdentityOnboarding.tsx"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AnimalIdentityOnboarding.d.ts","sourceRoot":"","sources":["../src/AnimalIdentityOnboarding.tsx"],"names":[],"mappings":"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"}
|
|
@@ -2,12 +2,34 @@ import type { AnimalIdentityOnboardingCopy, AnimalIdentityOnboardingInput } from
|
|
|
2
2
|
export type AnimalIdentityOnboardingV2Copy = AnimalIdentityOnboardingCopy & Readonly<{
|
|
3
3
|
controllerIsLegalRepresentative: string;
|
|
4
4
|
animalPreview: string;
|
|
5
|
+
addAnimalPhoto: string;
|
|
6
|
+
removeAnimalPhoto: string;
|
|
7
|
+
photoHelp: string;
|
|
8
|
+
photoTooLarge: string;
|
|
9
|
+
photoDimensionsInvalid: string;
|
|
10
|
+
ownerKind: string;
|
|
11
|
+
personOwner: string;
|
|
12
|
+
organizationOwner: string;
|
|
13
|
+
regionalIdentifier: string;
|
|
14
|
+
controllerRegion: string;
|
|
15
|
+
controllerEmail: string;
|
|
16
|
+
controllerTelephone: string;
|
|
17
|
+
contactRequired: string;
|
|
18
|
+
verificationMethod: string;
|
|
19
|
+
physicalInPerson: string;
|
|
20
|
+
supervisedRemote: string;
|
|
21
|
+
electronicId: string;
|
|
22
|
+
unsupervisedRemote: string;
|
|
23
|
+
}>;
|
|
24
|
+
type SelectOption = Readonly<{
|
|
25
|
+
value: string;
|
|
26
|
+
label: string;
|
|
5
27
|
}>;
|
|
6
28
|
/**
|
|
7
29
|
* Progressive animal onboarding presentation. It preserves the V1 payload so
|
|
8
30
|
* hosts can adopt it without changing evidence, authorization or persistence.
|
|
9
31
|
*/
|
|
10
|
-
export declare function AnimalIdentityOnboardingV2({ copy, onSubmit, submitAction, speciesOptions, busy }: Readonly<{
|
|
32
|
+
export declare function AnimalIdentityOnboardingV2({ copy, onSubmit, submitAction, speciesOptions, countryOptions, regionOptionsByCountry, identifierTypeOptions, showHeader, busy }: Readonly<{
|
|
11
33
|
copy: AnimalIdentityOnboardingV2Copy;
|
|
12
34
|
onSubmit: (input: AnimalIdentityOnboardingInput) => Promise<void> | void;
|
|
13
35
|
submitAction?: string;
|
|
@@ -15,6 +37,14 @@ export declare function AnimalIdentityOnboardingV2({ copy, onSubmit, submitActio
|
|
|
15
37
|
taxonomyId: string;
|
|
16
38
|
label: string;
|
|
17
39
|
}>[];
|
|
40
|
+
countryOptions?: readonly SelectOption[];
|
|
41
|
+
regionOptionsByCountry?: Readonly<Record<string, readonly SelectOption[]>>;
|
|
42
|
+
identifierTypeOptions?: Readonly<{
|
|
43
|
+
person: readonly SelectOption[];
|
|
44
|
+
organization: readonly SelectOption[];
|
|
45
|
+
}>;
|
|
46
|
+
showHeader?: boolean;
|
|
18
47
|
busy?: boolean;
|
|
19
48
|
}>): import("react").JSX.Element;
|
|
49
|
+
export {};
|
|
20
50
|
//# sourceMappingURL=AnimalIdentityOnboardingV2.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AnimalIdentityOnboardingV2.d.ts","sourceRoot":"","sources":["../src/AnimalIdentityOnboardingV2.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,4BAA4B,EAC5B,6BAA6B,EAC9B,MAAM,+BAA+B,CAAA;AAEtC,MAAM,MAAM,8BAA8B,GAAG,4BAA4B,GAAG,QAAQ,CAAC;IACnF,+BAA+B,EAAE,MAAM,CAAA;IACvC,aAAa,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"AnimalIdentityOnboardingV2.d.ts","sourceRoot":"","sources":["../src/AnimalIdentityOnboardingV2.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,4BAA4B,EAC5B,6BAA6B,EAC9B,MAAM,+BAA+B,CAAA;AAEtC,MAAM,MAAM,8BAA8B,GAAG,4BAA4B,GAAG,QAAQ,CAAC;IACnF,+BAA+B,EAAE,MAAM,CAAA;IACvC,aAAa,EAAE,MAAM,CAAA;IACrB,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,MAAM,CAAA;IACzB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,MAAM,CAAA;IACrB,sBAAsB,EAAE,MAAM,CAAA;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,iBAAiB,EAAE,MAAM,CAAA;IACzB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,gBAAgB,EAAE,MAAM,CAAA;IACxB,eAAe,EAAE,MAAM,CAAA;IACvB,mBAAmB,EAAE,MAAM,CAAA;IAC3B,eAAe,EAAE,MAAM,CAAA;IACvB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,gBAAgB,EAAE,MAAM,CAAA;IACxB,gBAAgB,EAAE,MAAM,CAAA;IACxB,YAAY,EAAE,MAAM,CAAA;IACpB,kBAAkB,EAAE,MAAM,CAAA;CAC3B,CAAC,CAAA;AAEF,KAAK,YAAY,GAAG,QAAQ,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAA;AAG9D;;;GAGG;AACH,wBAAgB,0BAA0B,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAmB,EAAE,cAAmB,EAAE,sBAA2B,EAAE,qBAAqB,EAAE,UAAiB,EAAE,IAAY,EAAE,EAAE,QAAQ,CAAC;IACnN,IAAI,EAAE,8BAA8B,CAAA;IACpC,QAAQ,EAAE,CAAC,KAAK,EAAE,6BAA6B,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;IACxE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,cAAc,CAAC,EAAE,SAAS,QAAQ,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,EAAE,CAAA;IAC3E,cAAc,CAAC,EAAE,SAAS,YAAY,EAAE,CAAA;IACxC,sBAAsB,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,CAAC,CAAC,CAAA;IAC1E,qBAAqB,CAAC,EAAE,QAAQ,CAAC;QAAE,MAAM,EAAE,SAAS,YAAY,EAAE,CAAC;QAAC,YAAY,EAAE,SAAS,YAAY,EAAE,CAAA;KAAE,CAAC,CAAA;IAC5G,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,IAAI,CAAC,EAAE,OAAO,CAAA;CACf,CAAC,+BAkJD"}
|
|
@@ -1,32 +1,75 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
|
+
const MAX_ANIMAL_PHOTO_BYTES = 2 * 1024 * 1024;
|
|
3
4
|
/**
|
|
4
5
|
* Progressive animal onboarding presentation. It preserves the V1 payload so
|
|
5
6
|
* hosts can adopt it without changing evidence, authorization or persistence.
|
|
6
7
|
*/
|
|
7
|
-
export function AnimalIdentityOnboardingV2({ copy, onSubmit, submitAction, speciesOptions = [], busy = false }) {
|
|
8
|
+
export function AnimalIdentityOnboardingV2({ copy, onSubmit, submitAction, speciesOptions = [], countryOptions = [], regionOptionsByCountry = {}, identifierTypeOptions, showHeader = true, busy = false }) {
|
|
8
9
|
const [submitting, setSubmitting] = useState(false);
|
|
9
10
|
const [animalName, setAnimalName] = useState('');
|
|
10
11
|
const [previewUrl, setPreviewUrl] = useState('');
|
|
12
|
+
const [animalDocument, setAnimalDocument] = useState();
|
|
13
|
+
const [photoError, setPhotoError] = useState('');
|
|
14
|
+
const [contactError, setContactError] = useState('');
|
|
15
|
+
const [controllerKind, setControllerKind] = useState('person');
|
|
16
|
+
const [controllerCountry, setControllerCountry] = useState(countryOptions[0]?.value || '');
|
|
17
|
+
const [regionalIdentifier, setRegionalIdentifier] = useState(false);
|
|
11
18
|
useEffect(() => () => {
|
|
12
19
|
if (previewUrl.startsWith('blob:'))
|
|
13
20
|
URL.revokeObjectURL(previewUrl);
|
|
14
21
|
}, [previewUrl]);
|
|
15
|
-
function previewAnimal(file) {
|
|
22
|
+
async function previewAnimal(file) {
|
|
16
23
|
if (previewUrl.startsWith('blob:'))
|
|
17
24
|
URL.revokeObjectURL(previewUrl);
|
|
18
|
-
|
|
25
|
+
setPhotoError('');
|
|
26
|
+
if (!file?.type.startsWith('image/')) {
|
|
27
|
+
setAnimalDocument(undefined);
|
|
19
28
|
return setPreviewUrl('');
|
|
29
|
+
}
|
|
30
|
+
if (file.size > MAX_ANIMAL_PHOTO_BYTES) {
|
|
31
|
+
setAnimalDocument(undefined);
|
|
32
|
+
setPreviewUrl('');
|
|
33
|
+
return setPhotoError(copy.photoTooLarge);
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const dimensions = await readImageDimensions(file);
|
|
37
|
+
if (!hasAcceptedPhotoDimensions(dimensions.width, dimensions.height)) {
|
|
38
|
+
setAnimalDocument(undefined);
|
|
39
|
+
setPreviewUrl('');
|
|
40
|
+
return setPhotoError(copy.photoDimensionsInvalid);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
setAnimalDocument(undefined);
|
|
45
|
+
setPreviewUrl('');
|
|
46
|
+
return setPhotoError(copy.photoDimensionsInvalid);
|
|
47
|
+
}
|
|
48
|
+
setAnimalDocument(file);
|
|
20
49
|
if (typeof URL.createObjectURL === 'function')
|
|
21
50
|
return setPreviewUrl(URL.createObjectURL(file));
|
|
22
51
|
const reader = new FileReader();
|
|
23
52
|
reader.onload = () => setPreviewUrl(typeof reader.result === 'string' ? reader.result : '');
|
|
24
53
|
reader.readAsDataURL(file);
|
|
25
54
|
}
|
|
55
|
+
function removeAnimalPhoto() {
|
|
56
|
+
if (previewUrl.startsWith('blob:'))
|
|
57
|
+
URL.revokeObjectURL(previewUrl);
|
|
58
|
+
setAnimalDocument(undefined);
|
|
59
|
+
setPreviewUrl('');
|
|
60
|
+
setPhotoError('');
|
|
61
|
+
}
|
|
26
62
|
async function submit(event) {
|
|
27
63
|
event.preventDefault();
|
|
28
64
|
const formElement = event.currentTarget;
|
|
29
65
|
const form = new FormData(formElement);
|
|
66
|
+
const controllerEmail = optionalText(form, 'controllerEmail');
|
|
67
|
+
const controllerTelephone = optionalText(form, 'controllerTelephone');
|
|
68
|
+
if (!controllerEmail && !controllerTelephone) {
|
|
69
|
+
setContactError(copy.contactRequired);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
setContactError('');
|
|
30
73
|
setSubmitting(true);
|
|
31
74
|
try {
|
|
32
75
|
await onSubmit({
|
|
@@ -40,9 +83,14 @@ export function AnimalIdentityOnboardingV2({ copy, onSubmit, submitAction, speci
|
|
|
40
83
|
controllerIdentifierType: requiredText(form, 'controllerIdentifierType'),
|
|
41
84
|
controllerIdentifierValue: requiredText(form, 'controllerIdentifierValue'),
|
|
42
85
|
controllerCountry: requiredText(form, 'controllerCountry').toUpperCase(),
|
|
86
|
+
controllerKind,
|
|
87
|
+
controllerRegion: optionalText(form, 'controllerRegion'),
|
|
88
|
+
controllerEmail,
|
|
89
|
+
controllerTelephone,
|
|
90
|
+
verificationMethod: requiredText(form, 'verificationMethod'),
|
|
43
91
|
relationship: requiredText(form, 'relationship'),
|
|
44
92
|
ownerDocument: requiredFile(formElement, 'ownerDocument'),
|
|
45
|
-
animalDocument: requiredFile(formElement, 'animalDocument'),
|
|
93
|
+
animalDocument: animalDocument || requiredFile(formElement, 'animalDocument'),
|
|
46
94
|
relationshipDocument: requiredFile(formElement, 'relationshipDocument'),
|
|
47
95
|
controllerPin: requiredText(form, 'controllerPin'),
|
|
48
96
|
});
|
|
@@ -52,11 +100,11 @@ export function AnimalIdentityOnboardingV2({ copy, onSubmit, submitAction, speci
|
|
|
52
100
|
}
|
|
53
101
|
}
|
|
54
102
|
const disabled = busy || submitting;
|
|
55
|
-
return _jsxs("section", { className: "uhcp-animal-onboarding uhcp-animal-onboarding-v2", "aria-labelledby":
|
|
56
|
-
|
|
57
|
-
|
|
103
|
+
return _jsxs("section", { className: "uhcp-animal-onboarding uhcp-animal-onboarding-v2", "aria-labelledby": showHeader ? 'animal-identity-onboarding-v2-title' : undefined, "aria-label": showHeader ? undefined : copy.title, children: [showHeader ? _jsxs("header", { children: [_jsx("h2", { id: "animal-identity-onboarding-v2-title", children: copy.title }), _jsx("p", { children: copy.intro })] }) : null, _jsxs("form", { onSubmit: submit, children: [_jsxs("details", { open: true, "aria-labelledby": "animal-onboarding-v2-animal-step", children: [_jsxs("summary", { id: "animal-onboarding-v2-animal-step", children: [_jsx(StepNumber, { value: 1 }), " ", copy.animalStep] }), _jsxs("div", { className: "uhcp-animal-onboarding-primary", children: [_jsxs("div", { className: "uhcp-animal-photo", children: [_jsxs("label", { className: "uhcp-animal-photo-dropzone", role: "button", "aria-label": copy.addAnimalPhoto, onDragOver: event => event.preventDefault(), onDrop: event => { event.preventDefault(); void previewAnimal(event.dataTransfer.files?.[0]); }, children: [previewUrl
|
|
104
|
+
? _jsx("img", { src: previewUrl, alt: copy.animalPreview.replace('{name}', animalName || copy.animalName) })
|
|
105
|
+
: _jsx("span", { "aria-hidden": "true", children: "\uFF0B" }), _jsx("input", { name: "animalDocument", type: "file", accept: "image/jpeg,image/png", required: !animalDocument, "aria-label": copy.addAnimalPhoto, onChange: event => void previewAnimal(event.currentTarget.files?.[0]) })] }), previewUrl ? _jsx("button", { type: "button", className: "uhcp-animal-photo-remove", "aria-label": copy.removeAnimalPhoto, title: copy.removeAnimalPhoto, onClick: removeAnimalPhoto, children: "\u00D7" }) : null, _jsx("small", { children: copy.photoHelp }), photoError ? _jsx("p", { role: "alert", children: photoError }) : null] }), _jsxs("div", { className: "uhcp-animal-onboarding-fields", children: [_jsxs("label", { children: [copy.animalName, _jsx("input", { name: "animalName", required: true, maxLength: 80, value: animalName, onChange: event => setAnimalName(event.currentTarget.value) })] }), _jsxs("label", { children: [copy.taxonomyId, speciesOptions.length > 0
|
|
58
106
|
? _jsx("select", { name: "taxonomyId", required: true, defaultValue: speciesOptions[0]?.taxonomyId, children: speciesOptions.map(option => _jsx("option", { value: option.taxonomyId, children: option.label }, option.taxonomyId)) })
|
|
59
|
-
: _jsx("input", { name: "taxonomyId", required: true, inputMode: "numeric", pattern: "[1-9][0-9]{0,6}", defaultValue: "9615" })] }), _jsxs("label", { children: [copy.birthDate, _jsx("input", { name: "birthDate", type: "date" })] }), _jsxs("label", { children: [copy.sex, _jsxs("select", { name: "sex", defaultValue: "unknown", children: [_jsx("option", { value: "unknown", children: copy.sexUnknown }), _jsx("option", { value: "female", children: copy.sexFemale }), _jsx("option", { value: "male", children: copy.sexMale }), _jsx("option", { value: "other", children: copy.sexOther })] })] }), _jsxs("label", { children: [copy.identifierSystem, _jsxs("select", { name: "identifierSystem", defaultValue: "urn:iso:std:iso:11784:11785", children: [_jsx("option", { value: "urn:iso:std:iso:11784:11785", children: "ISO 11784/11785" }), _jsx("option", { value: "https://europa.eu/pet-passport", children: "EU pet passport" }), _jsx("option", { value: "https://vetchain.app/identifier/tattoo", children: "Tattoo" })] })] }), _jsxs("label", { children: [copy.identifierValue, _jsx("input", { name: "identifierValue", required: true, maxLength: 80, autoComplete: "off" })] })] })] })] }), _jsxs("details", { children: [_jsxs("summary", { children: [_jsx(StepNumber, { value: 2 }), " ", copy.controllerStep] }), _jsxs("div", { className: "uhcp-animal-onboarding-fields", children: [_jsxs("label", { children: [copy.controllerLegalName, _jsx("input", { name: "controllerLegalName", required: true, maxLength: 160, autoComplete: "name" })] }), _jsxs("label", { children: [copy.controllerIdentifierType, _jsx("input", { name: "controllerIdentifierType", required: true, defaultValue: "national_identity_card", maxLength: 80 })] }), _jsxs("label", { children: [copy.controllerIdentifierValue, _jsx("input", { name: "controllerIdentifierValue", required: true, maxLength: 120, autoComplete: "off" })] }), _jsxs("label", { children: [copy.
|
|
107
|
+
: _jsx("input", { name: "taxonomyId", required: true, inputMode: "numeric", pattern: "[1-9][0-9]{0,6}", defaultValue: "9615" })] }), _jsxs("label", { children: [copy.birthDate, _jsx("input", { name: "birthDate", type: "date" })] }), _jsxs("label", { children: [copy.sex, _jsxs("select", { name: "sex", defaultValue: "unknown", children: [_jsx("option", { value: "unknown", children: copy.sexUnknown }), _jsx("option", { value: "female", children: copy.sexFemale }), _jsx("option", { value: "male", children: copy.sexMale }), _jsx("option", { value: "other", children: copy.sexOther })] })] }), _jsxs("label", { children: [copy.identifierSystem, _jsxs("select", { name: "identifierSystem", defaultValue: "urn:iso:std:iso:11784:11785", children: [_jsx("option", { value: "urn:iso:std:iso:11784:11785", children: "ISO 11784/11785" }), _jsx("option", { value: "https://europa.eu/pet-passport", children: "EU pet passport" }), _jsx("option", { value: "https://vetchain.app/identifier/tattoo", children: "Tattoo" })] })] }), _jsxs("label", { children: [copy.identifierValue, _jsx("input", { name: "identifierValue", required: true, maxLength: 80, autoComplete: "off" })] })] })] })] }), _jsxs("details", { "aria-labelledby": "animal-onboarding-v2-controller-step", children: [_jsxs("summary", { id: "animal-onboarding-v2-controller-step", children: [_jsx(StepNumber, { value: 2 }), " ", copy.controllerStep] }), _jsxs("div", { className: "uhcp-animal-onboarding-fields", children: [_jsxs("fieldset", { className: "uhcp-animal-owner-kind", children: [_jsx("legend", { children: copy.ownerKind }), _jsxs("label", { children: [_jsx("input", { type: "radio", name: "controllerKind", value: "person", checked: controllerKind === 'person', onChange: () => setControllerKind('person') }), " ", copy.personOwner] }), _jsxs("label", { children: [_jsx("input", { type: "radio", name: "controllerKind", value: "organization", checked: controllerKind === 'organization', onChange: () => setControllerKind('organization') }), " ", copy.organizationOwner] })] }), _jsxs("label", { className: "uhcp-animal-owner-name", children: [copy.controllerLegalName, _jsx("input", { name: "controllerLegalName", required: true, maxLength: 160, autoComplete: controllerKind === 'person' ? 'name' : 'organization' })] }), _jsxs("label", { children: [copy.controllerCountry, countryOptions.length ? _jsx("select", { name: "controllerCountry", required: true, value: controllerCountry, onChange: event => { setControllerCountry(event.currentTarget.value); setRegionalIdentifier(false); }, children: countryOptions.map(option => _jsx("option", { value: option.value, children: option.label }, option.value)) }) : _jsx("input", { name: "controllerCountry", required: true, pattern: "[A-Za-z]{2}", maxLength: 2, autoComplete: "country", onChange: event => setControllerCountry(event.currentTarget.value.toUpperCase()) })] }), _jsxs("label", { className: "uhcp-animal-regional-identifier", children: [_jsx("input", { type: "checkbox", checked: regionalIdentifier, disabled: !regionOptionsByCountry[controllerCountry]?.length, onChange: event => setRegionalIdentifier(event.currentTarget.checked) }), " ", copy.regionalIdentifier] }), regionalIdentifier ? _jsxs("label", { children: [copy.controllerRegion, _jsx("select", { name: "controllerRegion", required: true, children: (regionOptionsByCountry[controllerCountry] || []).map(option => _jsx("option", { value: option.value, children: option.label }, option.value)) })] }) : null, _jsxs("label", { children: [copy.controllerIdentifierType, identifierTypeOptions ? _jsx("select", { name: "controllerIdentifierType", required: true, children: identifierTypeOptions[controllerKind].map(option => _jsx("option", { value: option.value, children: option.label }, option.value)) }, controllerKind) : _jsx("input", { name: "controllerIdentifierType", required: true, defaultValue: "national_identity_card", maxLength: 80 })] }), _jsxs("label", { children: [copy.controllerIdentifierValue, _jsx("input", { name: "controllerIdentifierValue", required: true, maxLength: 120, autoComplete: "off" })] }), _jsxs("label", { children: [copy.controllerEmail, _jsx("input", { name: "controllerEmail", type: "email", autoComplete: "email" })] }), _jsxs("label", { children: [copy.controllerTelephone, _jsx("input", { name: "controllerTelephone", type: "tel", autoComplete: "tel" })] }), _jsxs("label", { children: [copy.relationship, _jsxs("select", { name: "relationship", defaultValue: "owner", children: [_jsx("option", { value: "owner", children: copy.owner }), _jsx("option", { value: "caregiver", children: copy.caregiver })] })] }), _jsxs("label", { className: "uhcp-animal-controller-confirmation", children: [_jsx("input", { type: "checkbox", defaultChecked: true, required: true }), " ", copy.controllerIsLegalRepresentative] }), contactError ? _jsx("p", { role: "alert", children: contactError }) : null] })] }), _jsxs("details", { "aria-labelledby": "animal-onboarding-v2-evidence-step", children: [_jsxs("summary", { id: "animal-onboarding-v2-evidence-step", children: [_jsx(StepNumber, { value: 3 }), " ", copy.evidenceStep] }), _jsxs("div", { className: "uhcp-animal-onboarding-fields", children: [_jsxs("label", { children: [copy.verificationMethod, _jsxs("select", { name: "verificationMethod", defaultValue: "pipp", children: [_jsx("option", { value: "pipp", children: copy.physicalInPerson }), _jsx("option", { value: "sripp", children: copy.supervisedRemote }), _jsx("option", { value: "eid", children: copy.electronicId }), _jsx("option", { value: "uripp", children: copy.unsupervisedRemote })] })] }), _jsxs("label", { children: [copy.ownerDocument, _jsx("input", { name: "ownerDocument", type: "file", accept: "application/pdf,image/jpeg,image/png", required: true })] }), _jsxs("label", { children: [copy.relationshipDocument, _jsx("input", { name: "relationshipDocument", type: "file", accept: "application/pdf,image/jpeg,image/png", required: true })] }), _jsxs("label", { children: [copy.controllerPin, _jsx("input", { name: "controllerPin", type: "password", inputMode: "numeric", pattern: "[0-9]{6,12}", required: true, autoComplete: "new-password" })] })] })] }), _jsx("button", { type: "submit", className: "uhcp-animal-onboarding-submit", "data-portal-action": submitAction, disabled: disabled, children: copy.submit })] })] });
|
|
60
108
|
}
|
|
61
109
|
function StepNumber({ value }) {
|
|
62
110
|
return _jsx("span", { className: "uhcp-identity-step-number", "aria-hidden": "true", children: value });
|
|
@@ -78,3 +126,26 @@ function requiredFile(form, name) {
|
|
|
78
126
|
throw new Error(`animal_identity_${name}_required`);
|
|
79
127
|
return value;
|
|
80
128
|
}
|
|
129
|
+
async function readImageDimensions(file) {
|
|
130
|
+
if (typeof createImageBitmap === 'function') {
|
|
131
|
+
const bitmap = await createImageBitmap(file);
|
|
132
|
+
const dimensions = { width: bitmap.width, height: bitmap.height };
|
|
133
|
+
bitmap.close();
|
|
134
|
+
return dimensions;
|
|
135
|
+
}
|
|
136
|
+
return new Promise((resolve, reject) => {
|
|
137
|
+
const reader = new FileReader();
|
|
138
|
+
reader.onerror = () => reject(new Error('animal_photo_unreadable'));
|
|
139
|
+
reader.onload = () => {
|
|
140
|
+
const image = new Image();
|
|
141
|
+
image.onerror = () => reject(new Error('animal_photo_unreadable'));
|
|
142
|
+
image.onload = () => resolve({ width: image.naturalWidth, height: image.naturalHeight });
|
|
143
|
+
image.src = String(reader.result || '');
|
|
144
|
+
};
|
|
145
|
+
reader.readAsDataURL(file);
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
function hasAcceptedPhotoDimensions(width, height) {
|
|
149
|
+
const ratio = width / height;
|
|
150
|
+
return width >= 300 && height >= 400 && Math.abs(ratio - 3 / 4) <= 0.06;
|
|
151
|
+
}
|
package/dist/styles.css
CHANGED
|
@@ -784,9 +784,17 @@ html[data-theme='dark'] .uhcp-brand-artwork-dark { display: block !important; }
|
|
|
784
784
|
.uhcp-animal-onboarding-v2 details > .uhcp-animal-onboarding-fields,
|
|
785
785
|
.uhcp-animal-onboarding-v2 details > .uhcp-animal-onboarding-primary { border-top:1px solid var(--uhcp-border, #d9dee7); padding:1rem; }
|
|
786
786
|
.uhcp-animal-onboarding-primary { align-items:start; display:grid; gap:1rem; grid-template-columns:minmax(10rem, 14rem) minmax(0, 1fr); }
|
|
787
|
-
.uhcp-animal-photo { display:grid; gap:.
|
|
788
|
-
.uhcp-animal-photo
|
|
789
|
-
.uhcp-animal-photo
|
|
787
|
+
.uhcp-animal-photo { display:grid; gap:.45rem; position:relative; }
|
|
788
|
+
.uhcp-animal-photo-dropzone { align-items:center; aspect-ratio:1; background:var(--uhcp-accent-soft, #e9f3ff); border:2px dashed color-mix(in srgb, var(--uhcp-turquoise, #1597a6) 58%, var(--uhcp-border, #d9dee7)); border-radius:1.25rem; cursor:pointer; display:flex; font-size:4rem; font-weight:850; justify-content:center; overflow:hidden; width:100%; }
|
|
789
|
+
.uhcp-animal-photo-dropzone:hover,.uhcp-animal-photo-dropzone:focus-within { background:color-mix(in srgb, var(--uhcp-accent-soft, #e9f3ff) 70%, var(--uhcp-turquoise, #1597a6)); border-style:solid; }
|
|
790
|
+
.uhcp-animal-photo-dropzone img { height:100%; object-fit:cover; width:100%; }
|
|
791
|
+
.uhcp-animal-photo-dropzone input { height:1px; opacity:0; overflow:hidden; position:absolute; width:1px; }
|
|
792
|
+
.uhcp-animal-photo-remove { background:#b42318; border:2px solid #fff; border-radius:999px; block-size:2.25rem; color:#fff; cursor:pointer; font-size:1.45rem; inline-size:2.25rem; inset-block-start:.65rem; inset-inline-end:.65rem; line-height:1; position:absolute; }
|
|
793
|
+
.uhcp-animal-photo small { color:var(--uhcp-muted, #5f6875); }
|
|
794
|
+
.uhcp-animal-owner-kind { border:0!important; display:flex; gap:1rem; grid-column:1/-1; padding:0!important; }
|
|
795
|
+
.uhcp-animal-owner-kind label,.uhcp-animal-regional-identifier { align-items:center; display:flex!important; gap:.45rem; }
|
|
796
|
+
.uhcp-animal-owner-kind input,.uhcp-animal-regional-identifier input { min-height:auto!important; width:auto!important; }
|
|
797
|
+
.uhcp-animal-owner-name { grid-column:1/-1; }
|
|
790
798
|
.uhcp-animal-controller-confirmation { align-items:center; background:var(--uhcp-accent-soft, #e9f3ff); border-radius:.75rem; display:flex !important; grid-column:1 / -1; padding:.75rem; }
|
|
791
799
|
.uhcp-animal-controller-confirmation input { min-height:auto !important; width:auto !important; }
|
|
792
800
|
@media (max-width: 42rem) { .uhcp-animal-onboarding-primary { grid-template-columns:1fr; } .uhcp-animal-photo { justify-self:center; max-width:15rem; width:100%; } }
|
package/package.json
CHANGED