@smileid/web-components 11.5.0 → 11.6.0
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/dist/esm/DocumentCaptureScreens-DjSTdVP-.js +5398 -0
- package/dist/esm/DocumentCaptureScreens-DjSTdVP-.js.map +1 -0
- package/dist/esm/{Navigation-Xg565kcu.js → Navigation-6DH3vF4-.js} +2 -2
- package/dist/esm/{Navigation-Xg565kcu.js.map → Navigation-6DH3vF4-.js.map} +1 -1
- package/dist/esm/{PoweredBySmileId-CxbaihMu.js → PoweredBySmileId-DoKwoPUd.js} +424 -6
- package/dist/esm/PoweredBySmileId-DoKwoPUd.js.map +1 -0
- package/dist/esm/{SelfieCaptureScreens-D3KuMzZA.js → SelfieCaptureScreens-CtX-4Tco.js} +5 -6
- package/dist/esm/SelfieCaptureScreens-CtX-4Tco.js.map +1 -0
- package/dist/esm/combobox.js +1 -1
- package/dist/esm/document.js +1 -1
- package/dist/esm/end-user-consent.js +713 -2
- package/dist/esm/end-user-consent.js.map +1 -1
- package/dist/esm/index-BqyuTk9f.js +1366 -0
- package/dist/esm/{index-CUwa6MPI.js.map → index-BqyuTk9f.js.map} +1 -1
- package/dist/esm/localisation.js +1 -1
- package/dist/esm/main.js +14 -14
- package/dist/esm/navigation.js +1 -1
- package/dist/esm/{package-BmVbDNny.js → package-CjZI-cNQ.js} +177 -172
- package/dist/esm/{package-BmVbDNny.js.map → package-CjZI-cNQ.js.map} +1 -1
- package/dist/esm/selfie.js +1 -1
- package/dist/esm/smart-camera-web.js +32 -18
- package/dist/esm/smart-camera-web.js.map +1 -1
- package/dist/esm/totp-consent.js +731 -2
- package/dist/esm/totp-consent.js.map +1 -1
- package/dist/esm/validate.js +31 -0
- package/dist/esm/validate.js.map +1 -0
- package/dist/smart-camera-web.js +696 -321
- package/dist/smart-camera-web.js.map +1 -1
- package/dist/types/main.d.ts +7 -1
- package/dist/types/validate.d.ts +21 -0
- package/lib/components/document/src/DocumentCaptureScreens.js +97 -18
- package/lib/components/document/src/assets/lottie.d.ts +12 -0
- package/lib/components/document/src/assets/svg-inline.d.ts +8 -0
- package/lib/components/document/src/document-auto-capture/DocumentAutoCapture.stories.js +75 -0
- package/lib/components/document/src/document-auto-capture/DocumentAutoCapture.tsx +1458 -0
- package/lib/components/document/src/document-auto-capture/README.md +73 -0
- package/lib/components/document/src/document-auto-capture/assets/Greenbook_Shimmer.svg +42 -0
- package/lib/components/document/src/document-auto-capture/assets/ID_Back_Shimmer.svg +8 -0
- package/lib/components/document/src/document-auto-capture/assets/ID_Front_Shimmer.svg +20 -0
- package/lib/components/document/src/document-auto-capture/assets/Passport-Shimmer.svg +143 -0
- package/lib/components/document/src/document-auto-capture/assets/shimmers.ts +21 -0
- package/lib/components/document/src/document-auto-capture/assets/svg-raw.d.ts +4 -0
- package/lib/components/document/src/document-auto-capture/components/CaptureButton.tsx +122 -0
- package/lib/components/document/src/document-auto-capture/components/Overlay.tsx +167 -0
- package/lib/components/document/src/document-auto-capture/components/TuningPanel.tsx +856 -0
- package/lib/components/document/src/document-auto-capture/constants/captureLayout.ts +58 -0
- package/lib/components/document/src/document-auto-capture/detection/cvErrorRecovery.ts +40 -0
- package/lib/components/document/src/document-auto-capture/detection/documentAspect.ts +20 -0
- package/lib/components/document/src/document-auto-capture/detection/qualityScoring.ts +35 -0
- package/lib/components/document/src/document-auto-capture/detection/seamRejection.ts +209 -0
- package/lib/components/document/src/document-auto-capture/detection/synthesisTiming.ts +10 -0
- package/lib/components/document/src/document-auto-capture/hooks/useCamera.ts +117 -0
- package/lib/components/document/src/document-auto-capture/hooks/useCardDetection.ts +3059 -0
- package/lib/components/document/src/document-auto-capture/index.ts +4 -0
- package/lib/components/document/src/document-auto-capture/theme.ts +40 -0
- package/lib/components/document/src/document-auto-capture/utils/debug.ts +25 -0
- package/lib/components/document/src/document-auto-capture/utils/opencvLoader.ts +86 -0
- package/lib/components/document/src/document-capture-instructions/DocumentCaptureInstructions.tsx +327 -244
- package/lib/components/document/src/document-capture-review/DocumentCaptureReview.js +153 -189
- package/lib/components/document/src/document-capture-submission/DocumentCaptureSubmission.tsx +432 -0
- package/lib/components/document/src/document-capture-submission/index.js +3 -0
- package/lib/components/selfie/README.md +13 -0
- package/lib/components/signature-pad/package.json +1 -1
- package/lib/components/smart-camera-web/src/README.md +11 -0
- package/lib/components/smart-camera-web/src/SmartCameraWeb.js +25 -1
- package/lib/components/totp-consent/src/TotpConsent.js +1 -1
- package/package.json +8 -4
- package/dist/esm/DocumentCaptureScreens-ucJDu5nH.js +0 -2232
- package/dist/esm/DocumentCaptureScreens-ucJDu5nH.js.map +0 -1
- package/dist/esm/EndUserConsent-CsiwoThZ.js +0 -717
- package/dist/esm/EndUserConsent-CsiwoThZ.js.map +0 -1
- package/dist/esm/PoweredBySmileId-CxbaihMu.js.map +0 -1
- package/dist/esm/SelfieCaptureScreens-D3KuMzZA.js.map +0 -1
- package/dist/esm/TotpConsent-CRtmtudl.js +0 -734
- package/dist/esm/TotpConsent-CRtmtudl.js.map +0 -1
- package/dist/esm/index-CUwa6MPI.js +0 -1363
- package/dist/esm/styles-BTEClL7R.js +0 -419
- package/dist/esm/styles-BTEClL7R.js.map +0 -1
- /package/lib/components/document/src/assets/lottie/{taking photo of green book passport.lottie → greenbook.lottie} +0 -0
- /package/lib/components/document/src/assets/lottie/{taking photo of ID FLIP 2D.lottie → id-card-flip.lottie} +0 -0
- /package/lib/components/document/src/assets/lottie/{taking photo of ID.lottie → id-card.lottie} +0 -0
- /package/lib/components/document/src/assets/lottie/{taking photo of passport 2.lottie → passport.lottie} +0 -0
|
@@ -0,0 +1,432 @@
|
|
|
1
|
+
import { useState, useEffect, useRef } from 'preact/hooks';
|
|
2
|
+
import register from 'preact-custom-element';
|
|
3
|
+
import type { FunctionComponent } from 'preact';
|
|
4
|
+
|
|
5
|
+
import { getBoolProp } from '../../../../utils/props';
|
|
6
|
+
import { t } from '../../../../domain/localisation';
|
|
7
|
+
|
|
8
|
+
import '../../../attribution/PoweredBySmileId';
|
|
9
|
+
import '../../../navigation/src';
|
|
10
|
+
|
|
11
|
+
export type SubmissionState = 'submitting' | 'success' | 'error';
|
|
12
|
+
|
|
13
|
+
interface Props {
|
|
14
|
+
'theme-color'?: string;
|
|
15
|
+
'hide-attribution'?: string | boolean;
|
|
16
|
+
/** When set, render the close affordance (smileid-navigation). */
|
|
17
|
+
'show-navigation'?: string | boolean;
|
|
18
|
+
/** Captured document data URI shown behind the status card. */
|
|
19
|
+
'image-src'?: string;
|
|
20
|
+
/** Initial submission state. Can be overridden at runtime via attribute or event. */
|
|
21
|
+
'submission-state'?: SubmissionState;
|
|
22
|
+
/** Optional supporting copy under the title (e.g. failure reason). */
|
|
23
|
+
'submission-message'?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// ── Status overlays (match the Enhanced SmartSelfie visual language) ─────────
|
|
27
|
+
|
|
28
|
+
function Spinner() {
|
|
29
|
+
return (
|
|
30
|
+
<div class="doc-submit-overlay" aria-hidden="true">
|
|
31
|
+
<svg
|
|
32
|
+
class="doc-submit-spinner-svg"
|
|
33
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
34
|
+
width="64"
|
|
35
|
+
height="64"
|
|
36
|
+
viewBox="0 0 64 64"
|
|
37
|
+
fill="none"
|
|
38
|
+
>
|
|
39
|
+
<g clip-path="url(#doc-submit-loader-clip)">
|
|
40
|
+
<foreignObject
|
|
41
|
+
x="-1031.25"
|
|
42
|
+
y="-1031.25"
|
|
43
|
+
width="2062.5"
|
|
44
|
+
height="2062.5"
|
|
45
|
+
transform="matrix(0.032 0 0 0.032 32 32)"
|
|
46
|
+
>
|
|
47
|
+
<div
|
|
48
|
+
{...{ xmlns: 'http://www.w3.org/1999/xhtml' }}
|
|
49
|
+
style="background:conic-gradient(from 90deg,rgba(39,174,96,0) 0deg,rgba(58,225,128,0) 0.036deg,rgba(58,225,128,1) 360deg);height:100%;width:100%;opacity:1"
|
|
50
|
+
/>
|
|
51
|
+
</foreignObject>
|
|
52
|
+
</g>
|
|
53
|
+
<path
|
|
54
|
+
fill-rule="evenodd"
|
|
55
|
+
clip-rule="evenodd"
|
|
56
|
+
d="M60.751 25.6018C62.2117 25.4134 63.5486 26.4447 63.737 27.9053C63.9122 29.2632 64 30.6309 64 31.9999C64 33.4727 62.8061 34.6666 61.3334 34.6666C59.8606 34.6666 58.6667 33.4727 58.6667 31.9999C58.6667 30.859 58.5935 29.7193 58.4475 28.5878C58.2591 27.1271 59.2904 25.7903 60.751 25.6018Z"
|
|
57
|
+
fill="#2CC05C"
|
|
58
|
+
/>
|
|
59
|
+
<defs>
|
|
60
|
+
<clipPath id="doc-submit-loader-clip">
|
|
61
|
+
<path
|
|
62
|
+
fill-rule="evenodd"
|
|
63
|
+
clip-rule="evenodd"
|
|
64
|
+
d="M32 64C49.6731 64 64 49.6731 64 32C64 14.3269 49.6731 0 32 0C14.3269 0 0 14.3269 0 32C0 49.6731 14.3269 64 32 64ZM32 58.6667C46.7276 58.6667 58.6667 46.7276 58.6667 32C58.6667 17.2724 46.7276 5.33333 32 5.33333C17.2724 5.33333 5.33333 17.2724 5.33333 32C5.33333 46.7276 17.2724 58.6667 32 58.6667Z"
|
|
65
|
+
/>
|
|
66
|
+
</clipPath>
|
|
67
|
+
</defs>
|
|
68
|
+
</svg>
|
|
69
|
+
</div>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function TickBadge() {
|
|
74
|
+
return (
|
|
75
|
+
<div class="doc-submit-overlay" aria-hidden="true">
|
|
76
|
+
<svg
|
|
77
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
78
|
+
width="64"
|
|
79
|
+
height="64"
|
|
80
|
+
viewBox="0 0 64 64"
|
|
81
|
+
fill="none"
|
|
82
|
+
>
|
|
83
|
+
<rect width="64" height="64" rx="32" fill="#2CC05C" />
|
|
84
|
+
<path
|
|
85
|
+
d="M27.1566 42.6663C26.4724 42.6663 25.7882 42.4088 25.2481 41.8568L19.4503 35.9324C18.9481 35.4131 18.6664 34.7123 18.6664 33.9821C18.6664 33.252 18.9481 32.5512 19.4503 32.0319C20.4946 30.9647 22.2232 30.9647 23.2675 32.0319L27.1566 36.006L40.7327 22.1334C41.777 21.0662 43.5055 21.0662 44.5498 22.1334C45.5941 23.2005 45.5941 24.9668 44.5498 26.0339L29.0652 41.8568C28.525 42.4088 27.8408 42.6663 27.1566 42.6663Z"
|
|
86
|
+
fill="white"
|
|
87
|
+
/>
|
|
88
|
+
</svg>
|
|
89
|
+
</div>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function CrossBadge() {
|
|
94
|
+
return (
|
|
95
|
+
<div class="doc-submit-overlay" aria-hidden="true">
|
|
96
|
+
<svg
|
|
97
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
98
|
+
width="64"
|
|
99
|
+
height="64"
|
|
100
|
+
viewBox="0 0 64 64"
|
|
101
|
+
fill="none"
|
|
102
|
+
>
|
|
103
|
+
<rect width="64" height="64" rx="32" fill="#EC221F" />
|
|
104
|
+
<path
|
|
105
|
+
d="M36.1146 31.9953L45.0425 22.6828C46.1682 21.5086 46.1682 19.5651 45.0425 18.3909C44.4947 17.8261 43.7555 17.5094 42.9852 17.5094C42.215 17.5094 41.4758 17.8261 40.9279 18.3909L32 27.7035L23.0721 18.3909C22.5242 17.8261 21.785 17.5094 21.0148 17.5094C20.2445 17.5094 19.5053 17.8261 18.9575 18.3909C17.8318 19.5651 17.8318 21.5086 18.9575 22.6828L27.8854 31.9953L18.9575 41.3079C17.8318 42.4821 17.8318 44.4256 18.9575 45.5998C19.5397 46.2071 20.2773 46.4906 21.0148 46.4906C21.7523 46.4906 22.4898 46.2071 23.0721 45.5998L32 36.2872L40.9279 45.5998C41.5102 46.2071 42.2477 46.4906 42.9852 46.4906C43.7227 46.4906 44.4603 46.2071 45.0425 45.5998C46.1682 44.4256 46.1682 42.4821 45.0425 41.3079L36.1146 31.9953Z"
|
|
106
|
+
fill="white"
|
|
107
|
+
/>
|
|
108
|
+
</svg>
|
|
109
|
+
</div>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* `<document-capture-submission>` — standalone post-capture submission UI for
|
|
115
|
+
* document flows where the host takes the captured image, uploads it, and
|
|
116
|
+
* wants to show submitting / success / failure cards in our visual language.
|
|
117
|
+
*
|
|
118
|
+
* Mirrors `<enhanced-smart-selfie-submission>`: the host knows the upload
|
|
119
|
+
* outcome and drives this element accordingly.
|
|
120
|
+
*
|
|
121
|
+
* Drive it via either:
|
|
122
|
+
* - attribute updates: `submission-state="submitting|success|error"`,
|
|
123
|
+
* `submission-message`
|
|
124
|
+
* - or window events: `document-capture-submission.set-state`
|
|
125
|
+
* detail: { state, message? }
|
|
126
|
+
*
|
|
127
|
+
* Emits:
|
|
128
|
+
* - `document-capture-submission.continue` (detail: { success }) when the
|
|
129
|
+
* submission resolves (success or error). Hosts can listen to navigate on.
|
|
130
|
+
*/
|
|
131
|
+
const DocumentCaptureSubmission: FunctionComponent<Props> = ({
|
|
132
|
+
'theme-color': themeColor = '#001096',
|
|
133
|
+
'hide-attribution': hideAttributionProp = false,
|
|
134
|
+
'show-navigation': showNavigationProp = false,
|
|
135
|
+
'image-src': imageSrc = '',
|
|
136
|
+
'submission-state': submissionStateProp = 'submitting',
|
|
137
|
+
'submission-message': submissionMessage,
|
|
138
|
+
}) => {
|
|
139
|
+
const hideAttribution = getBoolProp(hideAttributionProp);
|
|
140
|
+
const showNavigation = getBoolProp(showNavigationProp);
|
|
141
|
+
const navRef = useRef<HTMLElement | null>(null);
|
|
142
|
+
|
|
143
|
+
const [state, setState] = useState<SubmissionState>(submissionStateProp);
|
|
144
|
+
const [message, setMessage] = useState<string | undefined>(submissionMessage);
|
|
145
|
+
|
|
146
|
+
// Bridge the navigation web component's `navigation.close` (which fires on
|
|
147
|
+
// the element, not bubbling) out to a window event the host can act on.
|
|
148
|
+
useEffect(() => {
|
|
149
|
+
const el = navRef.current;
|
|
150
|
+
if (!el) return undefined;
|
|
151
|
+
const onClose = () => {
|
|
152
|
+
window.dispatchEvent(
|
|
153
|
+
new CustomEvent('document-capture-submission.close'),
|
|
154
|
+
);
|
|
155
|
+
};
|
|
156
|
+
el.addEventListener('navigation.close', onClose);
|
|
157
|
+
return () => el.removeEventListener('navigation.close', onClose);
|
|
158
|
+
}, [showNavigation, state]);
|
|
159
|
+
|
|
160
|
+
// Sync attribute changes from the host through to local state so partners
|
|
161
|
+
// can update the card by setAttribute alone (no event required).
|
|
162
|
+
useEffect(() => {
|
|
163
|
+
setState(submissionStateProp);
|
|
164
|
+
}, [submissionStateProp]);
|
|
165
|
+
useEffect(() => {
|
|
166
|
+
setMessage(submissionMessage);
|
|
167
|
+
}, [submissionMessage]);
|
|
168
|
+
|
|
169
|
+
// Event-driven path: avoids partners having to reach into the shadow DOM
|
|
170
|
+
// to flip attributes. Detail mirrors the attribute names.
|
|
171
|
+
useEffect(() => {
|
|
172
|
+
const handler = (e: Event) => {
|
|
173
|
+
const ce = e as CustomEvent<{
|
|
174
|
+
state?: SubmissionState;
|
|
175
|
+
message?: string;
|
|
176
|
+
}>;
|
|
177
|
+
if (ce.detail?.state) setState(ce.detail.state);
|
|
178
|
+
if (ce.detail?.message !== undefined) setMessage(ce.detail.message);
|
|
179
|
+
};
|
|
180
|
+
window.addEventListener('document-capture-submission.set-state', handler);
|
|
181
|
+
return () => {
|
|
182
|
+
window.removeEventListener(
|
|
183
|
+
'document-capture-submission.set-state',
|
|
184
|
+
handler,
|
|
185
|
+
);
|
|
186
|
+
};
|
|
187
|
+
}, []);
|
|
188
|
+
|
|
189
|
+
// Emit a resolution event when submission settles so hosts can navigate on.
|
|
190
|
+
// Only fire on a transition INTO a resolved state — never on initial mount
|
|
191
|
+
// (a host may render the element already `success`/`error`) and never on a
|
|
192
|
+
// re-render where the state is unchanged — so the host gets exactly one
|
|
193
|
+
// `.continue` per submission.
|
|
194
|
+
const isResolved = state === 'success' || state === 'error';
|
|
195
|
+
const prevStateRef = useRef<SubmissionState>(submissionStateProp);
|
|
196
|
+
useEffect(() => {
|
|
197
|
+
const prevResolved =
|
|
198
|
+
prevStateRef.current === 'success' || prevStateRef.current === 'error';
|
|
199
|
+
prevStateRef.current = state;
|
|
200
|
+
if (!isResolved || prevResolved) return;
|
|
201
|
+
window.dispatchEvent(
|
|
202
|
+
new CustomEvent('document-capture-submission.continue', {
|
|
203
|
+
detail: { success: state === 'success' },
|
|
204
|
+
}),
|
|
205
|
+
);
|
|
206
|
+
}, [isResolved, state]);
|
|
207
|
+
|
|
208
|
+
const isSubmitting = state === 'submitting';
|
|
209
|
+
const isSuccess = state === 'success';
|
|
210
|
+
const isError = state === 'error';
|
|
211
|
+
|
|
212
|
+
let title = '';
|
|
213
|
+
let body = '';
|
|
214
|
+
if (isSubmitting) {
|
|
215
|
+
title = t('document.submission.submitting.title');
|
|
216
|
+
body = t('document.submission.submitting.body');
|
|
217
|
+
} else if (isSuccess) {
|
|
218
|
+
// Success shows only the title (matches the design). Never surface a
|
|
219
|
+
// leftover `submission-message` from a prior error state.
|
|
220
|
+
title = t('document.submission.success.title');
|
|
221
|
+
body = '';
|
|
222
|
+
} else {
|
|
223
|
+
title = t('document.submission.error.title');
|
|
224
|
+
body = message || '';
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return (
|
|
228
|
+
<div class="doc-submit-root">
|
|
229
|
+
{showNavigation && (
|
|
230
|
+
<div class="doc-submit-nav">
|
|
231
|
+
{/* @ts-expect-error preact-custom-element types */}
|
|
232
|
+
<smileid-navigation
|
|
233
|
+
ref={navRef}
|
|
234
|
+
theme-color={themeColor}
|
|
235
|
+
show-navigation
|
|
236
|
+
hide-back
|
|
237
|
+
/>
|
|
238
|
+
</div>
|
|
239
|
+
)}
|
|
240
|
+
<div class="doc-submit-image-area">
|
|
241
|
+
<div class="doc-submit-image-wrap">
|
|
242
|
+
{imageSrc && (
|
|
243
|
+
<img
|
|
244
|
+
class={`doc-submit-image ${isSubmitting ? 'is-dimmed' : ''}`}
|
|
245
|
+
src={imageSrc}
|
|
246
|
+
alt={t('document.submission.imageAlt')}
|
|
247
|
+
/>
|
|
248
|
+
)}
|
|
249
|
+
{isSubmitting && <Spinner />}
|
|
250
|
+
{isSuccess && <TickBadge />}
|
|
251
|
+
{isError && <CrossBadge />}
|
|
252
|
+
</div>
|
|
253
|
+
</div>
|
|
254
|
+
|
|
255
|
+
<div class="doc-submit-footer">
|
|
256
|
+
<div class="doc-submit-card">
|
|
257
|
+
<h1 class="doc-submit-title" style={{ color: themeColor }}>
|
|
258
|
+
{title}
|
|
259
|
+
</h1>
|
|
260
|
+
{isSubmitting ? (
|
|
261
|
+
<p class="doc-submit-body">
|
|
262
|
+
{body.split('\n').map((line, i, arr) => (
|
|
263
|
+
<>
|
|
264
|
+
{line}
|
|
265
|
+
{i < arr.length - 1 && <br />}
|
|
266
|
+
</>
|
|
267
|
+
))}
|
|
268
|
+
</p>
|
|
269
|
+
) : (
|
|
270
|
+
body && <p class="doc-submit-body">{body}</p>
|
|
271
|
+
)}
|
|
272
|
+
</div>
|
|
273
|
+
|
|
274
|
+
{!hideAttribution && (
|
|
275
|
+
<div class="doc-submit-attribution">
|
|
276
|
+
{/* @ts-expect-error preact-custom-element types */}
|
|
277
|
+
<powered-by-smile-id />
|
|
278
|
+
</div>
|
|
279
|
+
)}
|
|
280
|
+
</div>
|
|
281
|
+
|
|
282
|
+
<style>{`
|
|
283
|
+
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
|
|
284
|
+
:host { display: block; width: 100%; height: 100%; }
|
|
285
|
+
|
|
286
|
+
.doc-submit-root {
|
|
287
|
+
font-family: 'DM Sans', system-ui, -apple-system, sans-serif;
|
|
288
|
+
background: #f8fafc;
|
|
289
|
+
display: flex;
|
|
290
|
+
flex-direction: column;
|
|
291
|
+
width: 100%;
|
|
292
|
+
height: 100%;
|
|
293
|
+
min-height: 100%;
|
|
294
|
+
position: relative;
|
|
295
|
+
overflow: hidden;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.doc-submit-nav {
|
|
299
|
+
position: absolute;
|
|
300
|
+
top: 16px;
|
|
301
|
+
left: 16px;
|
|
302
|
+
right: 16px;
|
|
303
|
+
z-index: 10;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
.doc-submit-image-area {
|
|
307
|
+
flex: 1;
|
|
308
|
+
display: flex;
|
|
309
|
+
align-items: center;
|
|
310
|
+
justify-content: center;
|
|
311
|
+
padding: 72px 24px 16px;
|
|
312
|
+
min-height: 0;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
.doc-submit-image-wrap {
|
|
316
|
+
position: relative;
|
|
317
|
+
display: flex;
|
|
318
|
+
align-items: center;
|
|
319
|
+
justify-content: center;
|
|
320
|
+
max-width: 100%;
|
|
321
|
+
max-height: 100%;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
.doc-submit-image {
|
|
325
|
+
max-width: 100%;
|
|
326
|
+
max-height: 100%;
|
|
327
|
+
width: auto;
|
|
328
|
+
height: auto;
|
|
329
|
+
border-radius: 12px;
|
|
330
|
+
display: block;
|
|
331
|
+
object-fit: contain;
|
|
332
|
+
transition: filter 0.2s ease;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
.doc-submit-image.is-dimmed {
|
|
336
|
+
filter: brightness(0.55);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/* Centered status overlay (spinner / tick / cross) */
|
|
340
|
+
.doc-submit-overlay {
|
|
341
|
+
position: absolute;
|
|
342
|
+
top: 50%;
|
|
343
|
+
left: 50%;
|
|
344
|
+
transform: translate(-50%, -50%);
|
|
345
|
+
width: 64px;
|
|
346
|
+
height: 64px;
|
|
347
|
+
display: flex;
|
|
348
|
+
align-items: center;
|
|
349
|
+
justify-content: center;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.doc-submit-spinner-svg {
|
|
353
|
+
animation: doc-submit-spin 1s linear infinite;
|
|
354
|
+
transform-origin: center;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
@keyframes doc-submit-spin {
|
|
358
|
+
to { transform: rotate(360deg); }
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
.doc-submit-footer {
|
|
362
|
+
padding: 0 20px 16px;
|
|
363
|
+
display: flex;
|
|
364
|
+
flex-direction: column;
|
|
365
|
+
align-items: center;
|
|
366
|
+
gap: 16px;
|
|
367
|
+
flex-shrink: 0;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.doc-submit-card {
|
|
371
|
+
width: 100%;
|
|
372
|
+
max-width: 420px;
|
|
373
|
+
background: #ffffff;
|
|
374
|
+
border-radius: 16px;
|
|
375
|
+
box-shadow: 0px 12px 16px -4px rgba(16, 24, 40, 0.08),
|
|
376
|
+
0px 4px 6px -2px rgba(16, 24, 40, 0.03);
|
|
377
|
+
padding: 28px 20px;
|
|
378
|
+
display: flex;
|
|
379
|
+
flex-direction: column;
|
|
380
|
+
align-items: center;
|
|
381
|
+
gap: 8px;
|
|
382
|
+
text-align: center;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
.doc-submit-title {
|
|
386
|
+
margin: 0;
|
|
387
|
+
font-size: 1.125rem;
|
|
388
|
+
font-weight: 700;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
.doc-submit-body {
|
|
392
|
+
margin: 0;
|
|
393
|
+
font-size: 0.8125rem;
|
|
394
|
+
font-weight: 400;
|
|
395
|
+
line-height: 1.35;
|
|
396
|
+
color: #5b6b7b;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
.doc-submit-attribution {
|
|
400
|
+
display: flex;
|
|
401
|
+
align-items: center;
|
|
402
|
+
justify-content: center;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
@media (min-width: 640px) {
|
|
406
|
+
.doc-submit-image-area { padding-top: 80px; }
|
|
407
|
+
}
|
|
408
|
+
`}</style>
|
|
409
|
+
</div>
|
|
410
|
+
);
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
if (
|
|
414
|
+
typeof customElements !== 'undefined' &&
|
|
415
|
+
!customElements.get('document-capture-submission')
|
|
416
|
+
) {
|
|
417
|
+
register(
|
|
418
|
+
DocumentCaptureSubmission,
|
|
419
|
+
'document-capture-submission',
|
|
420
|
+
[
|
|
421
|
+
'theme-color',
|
|
422
|
+
'hide-attribution',
|
|
423
|
+
'show-navigation',
|
|
424
|
+
'image-src',
|
|
425
|
+
'submission-state',
|
|
426
|
+
'submission-message',
|
|
427
|
+
],
|
|
428
|
+
{ shadow: true },
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
export default DocumentCaptureSubmission;
|
|
@@ -44,6 +44,19 @@ Usage:
|
|
|
44
44
|
<selfie-capture-screens show-navigation></selfie-capture-screens>
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
+
#### use-strict-mode
|
|
48
|
+
|
|
49
|
+
This attribute enables Enhanced SmartSelfie (strict-mode capture flow).
|
|
50
|
+
|
|
51
|
+
Usage:
|
|
52
|
+
|
|
53
|
+
```html
|
|
54
|
+
<selfie-capture-screens use-strict-mode="true"></selfie-capture-screens>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`allow-legacy-selfie-fallback` is also available as an optional compatibility
|
|
58
|
+
attribute.
|
|
59
|
+
|
|
47
60
|
### Permissions
|
|
48
61
|
|
|
49
62
|
The `SelfieCaptureScreens` component requires camera permissions to function. It will automatically request these permissions when used. If the permissions are granted, it will remove the `data-camera-error` attribute from the capture screen and set the `data-camera-ready` attribute to true. If the permissions are denied, it will remove the `data-camera-ready` attribute and set the `data-camera-error` attribute with the error message.
|
|
@@ -193,6 +193,17 @@ After installation and necessary imports:
|
|
|
193
193
|
|
|
194
194
|
This approach can also be achieved using other Server to Server libraries.
|
|
195
195
|
|
|
196
|
+
### Enhanced SmartSelfie
|
|
197
|
+
|
|
198
|
+
For web-component integrations, Enhanced SmartSelfie is enabled with the
|
|
199
|
+
`use-strict-mode` attribute on the component.
|
|
200
|
+
|
|
201
|
+
```html
|
|
202
|
+
<smart-camera-web use-strict-mode="true"></smart-camera-web>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
- Set `use-strict-mode="true"` to enable strict-mode selfie capture.
|
|
206
|
+
|
|
196
207
|
## Compatibility
|
|
197
208
|
|
|
198
209
|
`SmartCameraWeb` is compatible with most JavaScript frameworks and libraries. For integration with [ReactJS](https://reactjs.org), refer to this [tutorial](https://www.robinwieruch.de/react-web-components) due to React-WebComponents compatibility issues.
|
|
@@ -30,7 +30,7 @@ function scwTemplateString() {
|
|
|
30
30
|
<selfie-capture-screens ${this.applyComponentThemeColor} ${this.title} ${this.showNavigation} ${this.disableImageTests} ${this.hideAttribution} ${this.hideInstructions} ${this.hideConsent} ${this.partnerName} ${this.partnerLogo} ${this.policyUrl} hidden
|
|
31
31
|
${this.hideBackToHost} ${this.allowAgentMode} ${this.allowAgentModeTests} ${this.allowLegacySelfieFallback} ${this.useStrictMode} ${this.showBackOnGuidelines}
|
|
32
32
|
></selfie-capture-screens>
|
|
33
|
-
<document-capture-screens ${this.applyComponentThemeColor} document-type
|
|
33
|
+
<document-capture-screens ${this.autoCaptureFeature} ${this.autoCapture} ${this.autoCaptureTimeout} ${this.applyComponentThemeColor} document-type="${escAttr(this.documentType)}" ${this.title} ${this.documentCaptureModes} ${this.showNavigation} ${this.hideAttribution}
|
|
34
34
|
${this.hideBackOfId} ${this.newInstructions} ${this.applyComponentThemeColor} hidden></document-capture-screens>
|
|
35
35
|
</div>
|
|
36
36
|
`;
|
|
@@ -78,6 +78,9 @@ class SmartCameraWeb extends HTMLElement {
|
|
|
78
78
|
return [
|
|
79
79
|
'allow-agent-mode',
|
|
80
80
|
'allow-legacy-selfie-fallback',
|
|
81
|
+
'auto-capture-enabled',
|
|
82
|
+
'auto-capture',
|
|
83
|
+
'auto-capture-timeout',
|
|
81
84
|
'disable-image-tests',
|
|
82
85
|
'document-capture-modes',
|
|
83
86
|
'document-type',
|
|
@@ -100,6 +103,9 @@ class SmartCameraWeb extends HTMLElement {
|
|
|
100
103
|
switch (name) {
|
|
101
104
|
case 'allow-agent-mode':
|
|
102
105
|
case 'allow-legacy-selfie-fallback':
|
|
106
|
+
case 'auto-capture-enabled':
|
|
107
|
+
case 'auto-capture':
|
|
108
|
+
case 'auto-capture-timeout':
|
|
103
109
|
case 'disable-image-tests':
|
|
104
110
|
case 'document-capture-modes':
|
|
105
111
|
case 'document-type':
|
|
@@ -296,6 +302,24 @@ class SmartCameraWeb extends HTMLElement {
|
|
|
296
302
|
: '';
|
|
297
303
|
}
|
|
298
304
|
|
|
305
|
+
get autoCaptureFeature() {
|
|
306
|
+
return this.hasAttribute('auto-capture-enabled')
|
|
307
|
+
? 'auto-capture-enabled'
|
|
308
|
+
: '';
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
get autoCapture() {
|
|
312
|
+
return this.hasAttribute('auto-capture')
|
|
313
|
+
? `auto-capture="${escAttr(this.getAttribute('auto-capture'))}"`
|
|
314
|
+
: '';
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
get autoCaptureTimeout() {
|
|
318
|
+
return this.hasAttribute('auto-capture-timeout')
|
|
319
|
+
? `auto-capture-timeout="${escAttr(this.getAttribute('auto-capture-timeout'))}"`
|
|
320
|
+
: '';
|
|
321
|
+
}
|
|
322
|
+
|
|
299
323
|
get disableImageTests() {
|
|
300
324
|
return this.hasAttribute('disable-image-tests')
|
|
301
325
|
? 'disable-image-tests'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smileid/web-components",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.6.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"main": "dist/esm/main.js",
|
|
6
6
|
"module": "dist/esm/main.js",
|
|
@@ -45,6 +45,10 @@
|
|
|
45
45
|
"./localisation": {
|
|
46
46
|
"types": "./dist/types/localisation.d.ts",
|
|
47
47
|
"import": "./dist/esm/localisation.js"
|
|
48
|
+
},
|
|
49
|
+
"./validate": {
|
|
50
|
+
"types": "./dist/types/validate.d.ts",
|
|
51
|
+
"import": "./dist/esm/validate.js"
|
|
48
52
|
}
|
|
49
53
|
},
|
|
50
54
|
"files": [
|
|
@@ -94,8 +98,7 @@
|
|
|
94
98
|
"preact": "^10.27.3",
|
|
95
99
|
"preact-custom-element": "^4.3.0",
|
|
96
100
|
"preact-router": "^4.1.2",
|
|
97
|
-
"signature_pad": "^5.0.2"
|
|
98
|
-
"validate.js": "^0.13.1"
|
|
101
|
+
"signature_pad": "^5.0.2"
|
|
99
102
|
},
|
|
100
103
|
"devDependencies": {
|
|
101
104
|
"@preact/preset-vite": "^2.10.2",
|
|
@@ -104,8 +107,9 @@
|
|
|
104
107
|
"@types/preact-custom-element": "^4.0.4",
|
|
105
108
|
"@typescript-eslint/eslint-plugin": "^8.49.0",
|
|
106
109
|
"@typescript-eslint/parser": "^8.49.0",
|
|
110
|
+
"@vitejs/plugin-basic-ssl": "^2.3.0",
|
|
107
111
|
"cross-env": "^7.0.3",
|
|
108
|
-
"cypress": "^
|
|
112
|
+
"cypress": "^15.16.0",
|
|
109
113
|
"eslint": "^8.57.0",
|
|
110
114
|
"eslint-config-airbnb-base": "^15.0.0",
|
|
111
115
|
"eslint-config-prettier": "^9.1.0",
|