@privyid/persona 0.3.0 → 0.4.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.
Files changed (113) hide show
  1. package/dist/components/camera/Camera.vue +366 -0
  2. package/dist/components/camera/Camera.vue.d.ts +92 -0
  3. package/dist/components/camera/adapter/adapter.d.ts +41 -0
  4. package/dist/components/camera/adapter/adapter.mjs +3 -0
  5. package/dist/components/camera/adapter/capture.d.ts +5 -0
  6. package/dist/components/camera/adapter/capture.mjs +12 -0
  7. package/dist/components/camera/adapter/liveness.d.ts +5 -0
  8. package/dist/components/camera/adapter/liveness.mjs +46 -0
  9. package/dist/components/camera/adapter/qr-code.d.ts +2 -0
  10. package/dist/components/camera/adapter/qr-code.mjs +19 -0
  11. package/dist/components/camera/assets/shutter.wav +0 -0
  12. package/dist/components/camera/utils/motion.d.ts +29 -0
  13. package/dist/components/camera/utils/motion.mjs +88 -0
  14. package/dist/components/camera/utils/take-picture.d.ts +1 -0
  15. package/dist/components/camera/utils/take-picture.mjs +12 -0
  16. package/dist/components/collapse/Collapse.vue +88 -0
  17. package/dist/components/collapse/Collapse.vue.d.ts +29 -0
  18. package/dist/components/contextual-bar/ContextualBar.vue +292 -0
  19. package/dist/components/contextual-bar/ContextualBar.vue.d.ts +77 -0
  20. package/dist/components/contextual-bar/assets/images/img-background-contextualbar.svg +14 -0
  21. package/dist/components/contextual-bar/assets/images/img-bg-contextualbar.svg +19 -0
  22. package/dist/components/cropper/Cropper.vue +418 -0
  23. package/dist/components/cropper/Cropper.vue.d.ts +148 -0
  24. package/dist/components/cropper/assets/ps-neutral.png +0 -0
  25. package/dist/components/cropper/assets/sample-1.jpg +0 -0
  26. package/dist/components/cropper/utils/crop-image.d.ts +44 -0
  27. package/dist/components/cropper/utils/crop-image.mjs +43 -0
  28. package/dist/components/cropper/utils/use-pinch.d.ts +8 -0
  29. package/dist/components/cropper/utils/use-pinch.mjs +42 -0
  30. package/dist/components/cropper/utils/use-ratio.d.ts +9 -0
  31. package/dist/components/cropper/utils/use-ratio.mjs +24 -0
  32. package/dist/components/dialog/Dialog.vue +2 -0
  33. package/dist/components/dialog/DialogFooter.vue +4 -2
  34. package/dist/components/dialog/use-dialog.d.ts +3 -0
  35. package/dist/components/dropdown/Dropdown.vue.d.ts +2 -2
  36. package/dist/components/dropzone/Dropzone.vue +166 -0
  37. package/dist/components/dropzone/Dropzone.vue.d.ts +68 -0
  38. package/dist/components/dropzone/utils/accept.d.ts +1 -0
  39. package/dist/components/dropzone/utils/accept.mjs +17 -0
  40. package/dist/components/input/Input.vue +1 -1
  41. package/dist/components/modal/Modal.vue +62 -2
  42. package/dist/components/modal/Modal.vue.d.ts +21 -0
  43. package/dist/components/nav/Nav.vue +7 -1
  44. package/dist/components/nav/Nav.vue.d.ts +2 -2
  45. package/dist/components/nav/NavForm.vue +19 -0
  46. package/dist/components/nav/NavItem.vue +10 -0
  47. package/dist/components/nav/NavItemDropdown.vue +5 -1
  48. package/dist/components/nav/NavItemDropdown.vue.d.ts +9 -0
  49. package/dist/components/navbar/Navbar.vue +143 -0
  50. package/dist/components/navbar/Navbar.vue.d.ts +56 -0
  51. package/dist/components/navbar/NavbarBrand.vue +33 -0
  52. package/dist/components/navbar/NavbarBrand.vue.d.ts +14 -0
  53. package/dist/components/navbar/NavbarNav.vue +113 -0
  54. package/dist/components/navbar/NavbarNav.vue.d.ts +18 -0
  55. package/dist/components/navbar/NavbarToggle.vue +75 -0
  56. package/dist/components/navbar/NavbarToggle.vue.d.ts +6 -0
  57. package/dist/components/navbar/use-navbar.d.ts +10 -0
  58. package/dist/components/navbar/use-navbar.mjs +1 -0
  59. package/dist/components/navbar-menu/NavbarNavMenu.vue +62 -0
  60. package/dist/components/navbar-menu/NavbarNavMenu.vue.d.ts +15 -0
  61. package/dist/components/progress/Progress.vue +200 -0
  62. package/dist/components/progress/Progress.vue.d.ts +42 -0
  63. package/dist/components/progress/ProgressItem.vue +50 -0
  64. package/dist/components/progress/ProgressItem.vue.d.ts +25 -0
  65. package/dist/components/select/Select.vue.d.ts +1 -1
  66. package/dist/components/sidebar/SidebarNav.vue +4 -0
  67. package/dist/components/signature-draw/SignatureDrawDesktop.vue +2 -2
  68. package/dist/components/signature-draw/utils/canvas.d.ts +7 -1
  69. package/dist/components/signature-draw/utils/canvas.mjs +8 -2
  70. package/dist/components/signature-draw/utils/use-draw.mjs +6 -5
  71. package/dist/components/signature-text/SignatureText.vue.d.ts +1 -1
  72. package/dist/components/signature-text/utils/formatter.mjs +1 -1
  73. package/dist/components/spread/Spread.vue +55 -0
  74. package/dist/components/spread/Spread.vue.d.ts +14 -0
  75. package/dist/components/steps/Step.vue +55 -0
  76. package/dist/components/steps/Step.vue.d.ts +32 -0
  77. package/dist/components/steps/StepSlider.vue +39 -0
  78. package/dist/components/steps/StepSlider.vue.d.ts +25 -0
  79. package/dist/components/steps/Steps.vue +110 -0
  80. package/dist/components/steps/Steps.vue.d.ts +56 -0
  81. package/dist/components/steps/use-steps.d.ts +25 -0
  82. package/dist/components/steps/use-steps.mjs +52 -0
  83. package/dist/components/steps/utils/hook.d.ts +4 -0
  84. package/dist/components/steps/utils/hook.mjs +16 -0
  85. package/dist/components/subheading/Subheading.vue +2 -2
  86. package/dist/components/tabs/TabContent.vue +2 -2
  87. package/dist/components/tabs/Tabs.vue +4 -5
  88. package/dist/components/tabs/Tabs.vue.d.ts +1 -1
  89. package/dist/components/textarea/Textarea.vue.d.ts +1 -1
  90. package/dist/components/utils/base64.d.ts +8 -0
  91. package/dist/components/utils/base64.mjs +29 -0
  92. package/dist/components/utils/color.d.ts +6 -1
  93. package/dist/components/utils/color.mjs +4 -0
  94. package/dist/components/utils/vnode.d.ts +14 -1
  95. package/dist/components/utils/vnode.mjs +5 -2
  96. package/dist/components/wizard/Wizard.vue +85 -0
  97. package/dist/components/wizard/Wizard.vue.d.ts +72 -0
  98. package/dist/components/wizard/WizardBody.vue +50 -0
  99. package/dist/components/wizard/WizardBody.vue.d.ts +23 -0
  100. package/dist/components/wizard/WizardHeader.vue +38 -0
  101. package/dist/components/wizard/WizardHeader.vue.d.ts +16 -0
  102. package/dist/components/wizard/WizardStep.vue +20 -0
  103. package/dist/components/wizard/WizardStep.vue.d.ts +34 -0
  104. package/dist/core/index.cjs +1 -75
  105. package/dist/core/index.d.ts +6 -1
  106. package/dist/core/index.mjs +15 -1
  107. package/dist/module.d.ts +8 -2
  108. package/dist/module.json +1 -1
  109. package/dist/module.mjs +14 -2
  110. package/dist/types.d.ts +5 -1
  111. package/package.json +11 -7
  112. package/dist/components/dialog/index.d.ts +0 -6
  113. package/dist/components/dialog/index.mjs +0 -5
@@ -0,0 +1,366 @@
1
+ <template>
2
+ <div
3
+ class="camera"
4
+ data-testid="camera"
5
+ :data-deviceid="deviceId"
6
+ :class="classNames">
7
+ <video
8
+ v-if="stream"
9
+ ref="video"
10
+ data-testid="camera-video"
11
+ :srcObject.prop="stream"
12
+ class="camera__video"
13
+ muted
14
+ autoplay
15
+ playsinline
16
+ @play="onStart" />
17
+
18
+ <!-- Result -->
19
+ <img
20
+ v-if="isTaken && !stream"
21
+ data-testid="camera-result"
22
+ class="camera__result"
23
+ :src="preview"
24
+ alt="camera-result">
25
+
26
+ <!-- Camera off -->
27
+ <span
28
+ v-if="!isActive && !isTaken"
29
+ data-testid="camera-off"
30
+ class="camera__off-info">
31
+ Camera is off
32
+ </span>
33
+
34
+ <!-- Mask -->
35
+ <div class="camera__mask-container">
36
+ <div
37
+ v-if="!isTaken"
38
+ data-testid="camera-mask"
39
+ class="camera__mask" />
40
+ </div>
41
+
42
+ <!-- Toast -->
43
+ <transition name="slide-up">
44
+ <div
45
+ v-if="message"
46
+ :key="message"
47
+ class="camera__toast">
48
+ <div
49
+ data-testid="camera-toast"
50
+ class="camera__toast-text">
51
+ {{ message }}
52
+ </div>
53
+ </div>
54
+ </transition>
55
+
56
+ <!-- Control Button -->
57
+ <div class="camera__controls">
58
+ <p-button
59
+ v-if="cameras.length > 1 && !isTaken"
60
+ data-testid="camera-toggle"
61
+ color="secondary"
62
+ size="sm"
63
+ icon
64
+ pill
65
+ @click="toggle">
66
+ <icon-rotate />
67
+ </p-button>
68
+
69
+ <!-- Main Button -->
70
+ <p-button
71
+ v-if="!isActive && !isTaken"
72
+ data-testid="camera-turn-on"
73
+ class="camera__main-control"
74
+ icon
75
+ pill
76
+ @click="turnOn()">
77
+ <icon-camera />
78
+ </p-button>
79
+ <p-button
80
+ v-else-if="isActive && !isTaken"
81
+ data-testid="camera-take"
82
+ class="camera__main-control"
83
+ icon
84
+ pill
85
+ :disabled="isProcessing"
86
+ @click="take()">
87
+ <icon-camera />
88
+ </p-button>
89
+ <p-button
90
+ v-else
91
+ data-testid="camera-retake"
92
+ class="camera__main-control"
93
+ icon
94
+ pill
95
+ @click="retake()">
96
+ <icon-retake />
97
+ </p-button>
98
+ <!-- End Main Button -->
99
+ </div>
100
+
101
+ <slot
102
+ :cameras="cameras"
103
+ :preview="preview"
104
+ :stream="stream"
105
+ :video="video"
106
+ :toast="toast" />
107
+ </div>
108
+ </template>
109
+
110
+ <script>
111
+ import {
112
+ computed,
113
+ defineComponent,
114
+ onBeforeUnmount,
115
+ onMounted,
116
+ ref,
117
+ toRef
118
+ } from "vue-demi";
119
+ import pButton from "../button/Button.vue";
120
+ import IconRotate from "@carbon/icons-vue/lib/renew/16";
121
+ import IconCamera from "@carbon/icons-vue/lib/camera/24";
122
+ import IconRetake from "@carbon/icons-vue/lib/reset/24";
123
+ import shutterWav from "./assets/shutter.wav";
124
+ import { useSound } from "@vueuse/sound";
125
+ import { useVModel } from "../input/use-input";
126
+ import CaptureAdapter from "./adapter/capture";
127
+ import {
128
+ usePermission,
129
+ useDevicesList,
130
+ useUserMedia,
131
+ until
132
+ } from "@vueuse/core";
133
+ import * as dialog from "../dialog/use-dialog";
134
+ import defu from "defu";
135
+ export default defineComponent({
136
+ components: {
137
+ pButton,
138
+ IconCamera,
139
+ IconRetake,
140
+ IconRotate
141
+ },
142
+ props: {
143
+ modelValue: {
144
+ type: [
145
+ globalThis.File,
146
+ String,
147
+ Array
148
+ ],
149
+ default: ""
150
+ },
151
+ modelModifiers: {
152
+ type: Object,
153
+ default: () => ({})
154
+ },
155
+ mirror: {
156
+ type: [Boolean, String],
157
+ default: void 0
158
+ },
159
+ mask: {
160
+ type: String,
161
+ default: void 0
162
+ },
163
+ adapter: {
164
+ type: Object,
165
+ default: CaptureAdapter
166
+ },
167
+ facingMode: {
168
+ type: String,
169
+ default: void 0
170
+ },
171
+ silent: {
172
+ type: Boolean,
173
+ default: false
174
+ }
175
+ },
176
+ models: {
177
+ prop: "modelValue",
178
+ event: "update:modelValue"
179
+ },
180
+ emits: [
181
+ "start",
182
+ "change",
183
+ "result",
184
+ "update:modelValue"
185
+ ],
186
+ setup(props, { emit }) {
187
+ const model = useVModel(props);
188
+ const modifier = toRef(props, "modelModifiers");
189
+ const isProcessing = ref(false);
190
+ const isTaken = ref(false);
191
+ const preview = ref("");
192
+ const message = ref("");
193
+ const shutter = useSound(shutterWav);
194
+ const video = ref();
195
+ const permission = usePermission("camera", { controls: true });
196
+ const camera = ref(0);
197
+ const meta = computed(() => {
198
+ return defu({
199
+ mirror: props.mirror,
200
+ mask: props.mask,
201
+ facingMode: props.facingMode
202
+ }, props.adapter.meta, { autoStart: false });
203
+ });
204
+ const { videoInputs: cameras } = useDevicesList({ constraints: { video: { facingMode: meta.value.facingMode } } });
205
+ const deviceId = computed(() => {
206
+ return cameras.value?.at(camera.value)?.deviceId;
207
+ });
208
+ const { stream, start, stop, enabled: isActive } = useUserMedia({
209
+ videoDeviceId: deviceId,
210
+ audioDeviceId: false
211
+ });
212
+ const classNames = computed(() => {
213
+ const result = [];
214
+ if (meta.value.mirror)
215
+ result.push("camera--mirror");
216
+ if (meta.value.mask)
217
+ result.push(`camera__mask--${meta.value.mask}`);
218
+ else
219
+ result.push("camera__mask--none");
220
+ return result;
221
+ });
222
+ async function turnOn() {
223
+ if (permission.state.value === "denied") {
224
+ await dialog.alert({
225
+ title: "Camera Access Blocked",
226
+ text: "Privy need to access your internal camera to process this journey",
227
+ confirm: { text: "Ok" },
228
+ footerAlign: "end"
229
+ });
230
+ }
231
+ if (permission.state.value === "prompt") {
232
+ await dialog.alert({
233
+ title: "Camera Access Required",
234
+ text: "Privy need to access your internal camera to process this journey",
235
+ confirm: { text: "Ok" },
236
+ footerAlign: "end"
237
+ });
238
+ }
239
+ await start();
240
+ }
241
+ function toggle() {
242
+ camera.value = (camera.value + 1) % cameras.value.length;
243
+ }
244
+ function toast(text) {
245
+ message.value = text;
246
+ }
247
+ async function take() {
248
+ isProcessing.value = true;
249
+ const output = await props.adapter.run({
250
+ video,
251
+ toast,
252
+ stream,
253
+ meta,
254
+ modifier
255
+ });
256
+ preview.value = output.preview;
257
+ model.value = output.result;
258
+ isTaken.value = true;
259
+ isProcessing.value = false;
260
+ isActive.value = false;
261
+ emit("result", output.result);
262
+ emit("change", output.result);
263
+ if (!props.silent)
264
+ shutter.play();
265
+ }
266
+ async function retake() {
267
+ isActive.value = true;
268
+ isTaken.value = false;
269
+ preview.value = "";
270
+ message.value = "";
271
+ }
272
+ function onStart() {
273
+ emit("start", stream.value);
274
+ if (meta.value.autoStart)
275
+ take();
276
+ }
277
+ onMounted(async () => {
278
+ if (permission.isSupported) {
279
+ await until(permission.state).not.toBeUndefined();
280
+ await turnOn();
281
+ }
282
+ });
283
+ onBeforeUnmount(() => {
284
+ stop();
285
+ });
286
+ return {
287
+ classNames,
288
+ cameras,
289
+ video,
290
+ stream,
291
+ toggle,
292
+ isActive,
293
+ isTaken,
294
+ isProcessing,
295
+ message,
296
+ take,
297
+ retake,
298
+ preview,
299
+ turnOn,
300
+ onStart,
301
+ toast,
302
+ deviceId
303
+ };
304
+ }
305
+ });
306
+ </script>
307
+
308
+ <style lang="postcss">
309
+ .camera {
310
+ @apply bg-black w-full flex flex-col aspect-video select-none relative;
311
+
312
+ &__video {
313
+ @apply flex-grow min-h-full max-w-full h-auto;
314
+ }
315
+
316
+ &--mirror {
317
+ .camera__video {
318
+ @apply -scale-x-100;
319
+ }
320
+ }
321
+
322
+ &__mask-container {
323
+ @apply absolute top-0 left-0 right-0 bottom-0 w-full h-full overflow-hidden pointer-events-none;
324
+ }
325
+
326
+ &__mask {
327
+ @apply absolute top-1/2 left-1/2 shadow-mask -translate-x-1/2 -translate-y-1/2;
328
+
329
+ &--none &-container {
330
+ @apply hidden;
331
+ }
332
+
333
+ &--square & {
334
+ @apply aspect-square w-2/3 md:w-1/2;
335
+ }
336
+
337
+ &--round & {
338
+ @apply aspect-square rounded-full w-1/2;
339
+ }
340
+
341
+ &--card & {
342
+ @apply aspect-[85.60/53.98] w-2/3 rounded-md;
343
+ }
344
+ }
345
+
346
+ &__result {
347
+ @apply max-w-full h-auto;
348
+ }
349
+
350
+ &__off-info {
351
+ @apply absolute bottom-20 text-white left-0 right-0 text-center text-sm;
352
+ }
353
+
354
+ &__controls {
355
+ @apply py-3 flex w-full flex-shrink-0 justify-center items-center absolute bottom-0 gap-3;
356
+ }
357
+
358
+ &__toast {
359
+ @apply absolute bottom-20 left-0 right-0 text-center text-white px-4;
360
+
361
+ &-text {
362
+ @apply bg-black bg-opacity-80 px-4 py-1 text-sm rounded shadow-md inline-block max-w-full truncate;
363
+ }
364
+ }
365
+ }
366
+ </style>
@@ -0,0 +1,92 @@
1
+ import { ComputedRef, PropType } from 'vue-demi';
2
+ import { Adapter, MaskVariant, ModelModifier } from './adapter/adapter';
3
+ declare const _default: import("vue-demi").DefineComponent<{
4
+ modelValue: {
5
+ type: PropType<string | string[] | File | File[]>;
6
+ default: string;
7
+ };
8
+ modelModifiers: {
9
+ type: PropType<ModelModifier>;
10
+ default: () => ModelModifier;
11
+ };
12
+ mirror: {
13
+ type: PropType<boolean | "all" | "preview">;
14
+ default: any;
15
+ };
16
+ mask: {
17
+ type: PropType<MaskVariant>;
18
+ default: any;
19
+ };
20
+ adapter: {
21
+ type: PropType<Adapter>;
22
+ default: Adapter;
23
+ };
24
+ facingMode: {
25
+ type: PropType<ConstrainDOMString>;
26
+ default: any;
27
+ };
28
+ silent: {
29
+ type: BooleanConstructor;
30
+ default: boolean;
31
+ };
32
+ }, {
33
+ classNames: ComputedRef<string[]>;
34
+ cameras: ComputedRef<MediaDeviceInfo[]>;
35
+ video: import("vue-demi").Ref<HTMLVideoElement>;
36
+ stream: import("vue-demi").Ref<MediaStream>;
37
+ toggle: () => void;
38
+ isActive: import("vue-demi").Ref<boolean>;
39
+ isTaken: import("vue-demi").Ref<boolean>;
40
+ isProcessing: import("vue-demi").Ref<boolean>;
41
+ message: import("vue-demi").Ref<string>;
42
+ take: () => Promise<void>;
43
+ retake: () => Promise<void>;
44
+ preview: import("vue-demi").Ref<string>;
45
+ turnOn: () => Promise<void>;
46
+ onStart: () => void;
47
+ toast: (text: string) => void;
48
+ deviceId: ComputedRef<string>;
49
+ }, unknown, {}, {}, import("vue-demi").ComponentOptionsMixin, import("vue-demi").ComponentOptionsMixin, ("change" | "update:modelValue" | "start" | "result")[], "change" | "start" | "update:modelValue" | "result", import("vue-demi").VNodeProps & import("vue-demi").AllowedComponentProps & import("vue-demi").ComponentCustomProps, Readonly<import("vue-demi").ExtractPropTypes<{
50
+ modelValue: {
51
+ type: PropType<string | string[] | File | File[]>;
52
+ default: string;
53
+ };
54
+ modelModifiers: {
55
+ type: PropType<ModelModifier>;
56
+ default: () => ModelModifier;
57
+ };
58
+ mirror: {
59
+ type: PropType<boolean | "all" | "preview">;
60
+ default: any;
61
+ };
62
+ mask: {
63
+ type: PropType<MaskVariant>;
64
+ default: any;
65
+ };
66
+ adapter: {
67
+ type: PropType<Adapter>;
68
+ default: Adapter;
69
+ };
70
+ facingMode: {
71
+ type: PropType<ConstrainDOMString>;
72
+ default: any;
73
+ };
74
+ silent: {
75
+ type: BooleanConstructor;
76
+ default: boolean;
77
+ };
78
+ }>> & {
79
+ onChange?: (...args: any[]) => any;
80
+ "onUpdate:modelValue"?: (...args: any[]) => any;
81
+ onStart?: (...args: any[]) => any;
82
+ onResult?: (...args: any[]) => any;
83
+ }, {
84
+ modelValue: string | string[] | File | File[];
85
+ mask: MaskVariant;
86
+ mirror: boolean | "all" | "preview";
87
+ facingMode: any;
88
+ modelModifiers: ModelModifier;
89
+ adapter: Adapter;
90
+ silent: boolean;
91
+ }>;
92
+ export default _default;
@@ -0,0 +1,41 @@
1
+ import { ComputedRef, Ref } from 'vue-demi';
2
+ export declare type MaskVariant = 'square' | 'round' | 'card' | 'none';
3
+ export declare type MirrorMode = boolean | 'preview' | 'all';
4
+ export interface ModelModifier {
5
+ base64: boolean;
6
+ }
7
+ export interface AdapterMeta {
8
+ /**
9
+ * Auto take an image,
10
+ * It will start processing when camera started.
11
+ */
12
+ autoStart: boolean;
13
+ /**
14
+ * Default value for props `facingMode`
15
+ */
16
+ mask: MaskVariant;
17
+ /**
18
+ * Default value for props `mirror`
19
+ */
20
+ mirror: MirrorMode;
21
+ /**
22
+ * Default value for props `facingMode`
23
+ */
24
+ facingMode: ConstrainDOMString;
25
+ }
26
+ export interface CameraContext {
27
+ video: Ref<HTMLVideoElement>;
28
+ stream: Ref<MediaStream>;
29
+ modifier: Ref<ModelModifier>;
30
+ meta: ComputedRef<AdapterMeta>;
31
+ toast: (message: string) => void;
32
+ }
33
+ export interface CameraResult {
34
+ preview: string;
35
+ result: string | string[] | globalThis.File | globalThis.File[];
36
+ }
37
+ export interface Adapter {
38
+ meta?: Partial<AdapterMeta>;
39
+ run: (context: CameraContext) => CameraResult | Promise<CameraResult>;
40
+ }
41
+ export declare function defineAdapter(adapter: Adapter): Adapter;
@@ -0,0 +1,3 @@
1
+ export function defineAdapter(adapter) {
2
+ return adapter;
3
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Basic adapter for capture image from camera
3
+ */
4
+ declare const _default: import("./adapter").Adapter;
5
+ export default _default;
@@ -0,0 +1,12 @@
1
+ import { fromBase64 } from "../../utils/base64.mjs";
2
+ import { takePicture } from "../utils/take-picture.mjs";
3
+ import { defineAdapter } from "./adapter.mjs";
4
+ export default defineAdapter({
5
+ meta: { facingMode: "environment" },
6
+ run({ video, meta, modifier }) {
7
+ const isMirrored = !!(meta.value.mirror && meta.value.mirror !== "preview");
8
+ const preview = takePicture(video.value, isMirrored);
9
+ const result = modifier.value.base64 ? preview : fromBase64(preview);
10
+ return { preview, result };
11
+ }
12
+ });
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Liveness adapter for camera, using Fast Motion Algorithm
3
+ */
4
+ declare const _default: import("./adapter").Adapter;
5
+ export default _default;
@@ -0,0 +1,46 @@
1
+ import { fromBase64 } from "../../utils/base64.mjs";
2
+ import {
3
+ createTemplate,
4
+ motionDetection,
5
+ MOTION_AREA_SIZE,
6
+ MOTION_FPS,
7
+ MOTION_THRESHOLD,
8
+ takeSample
9
+ } from "../utils/motion";
10
+ import { takePicture } from "../utils/take-picture.mjs";
11
+ import { defineAdapter } from "./adapter.mjs";
12
+ export default defineAdapter({
13
+ meta: {
14
+ mask: "round",
15
+ mirror: true,
16
+ facingMode: "user"
17
+ },
18
+ async run({ video, toast, meta, modifier }) {
19
+ return await new Promise((resolve) => {
20
+ const isMirrored = !!(meta.value.mirror && meta.value.mirror !== "preview");
21
+ const photoA = takePicture(video.value, isMirrored);
22
+ const canvas = document.createElement("canvas");
23
+ canvas.width = MOTION_AREA_SIZE;
24
+ canvas.height = MOTION_AREA_SIZE;
25
+ let template;
26
+ const interval = setInterval(function processFrame() {
27
+ if (video.value) {
28
+ const imageData = takeSample(canvas, video.value);
29
+ if (!template)
30
+ template = createTemplate(imageData);
31
+ else if (motionDetection(imageData, template) > MOTION_THRESHOLD) {
32
+ const photoB = takePicture(video.value, isMirrored);
33
+ const result = modifier.value.base64 ? [photoB, photoA] : [fromBase64(photoB), fromBase64(photoA)];
34
+ clearInterval(interval);
35
+ toast("");
36
+ resolve({
37
+ preview: photoB,
38
+ result
39
+ });
40
+ }
41
+ }
42
+ }, 1e3 / MOTION_FPS);
43
+ toast("Move your head slowly. Your photo will be taken automatically");
44
+ });
45
+ }
46
+ });
@@ -0,0 +1,2 @@
1
+ declare const _default: import("./adapter").Adapter;
2
+ export default _default;
@@ -0,0 +1,19 @@
1
+ import { defineAdapter } from "./adapter.mjs";
2
+ import { BrowserQRCodeReader } from "@zxing/browser";
3
+ import { takePicture } from "../utils/take-picture.mjs";
4
+ export default defineAdapter({
5
+ meta: {
6
+ mask: "square",
7
+ facingMode: "environment",
8
+ autoStart: true
9
+ },
10
+ async run({ video, toast, meta }) {
11
+ const isMirrored = !!(meta.value.mirror && meta.value.mirror !== "preview");
12
+ const reader = new BrowserQRCodeReader();
13
+ const result = await reader.decodeOnceFromVideoElement(video.value);
14
+ const image = takePicture(video.value, isMirrored);
15
+ const text = result.getText();
16
+ toast(text);
17
+ return { preview: image, result: text };
18
+ }
19
+ });
@@ -0,0 +1,29 @@
1
+ export interface MotionTemplate {
2
+ centerX: number;
3
+ centerY: number;
4
+ width: number;
5
+ height: number;
6
+ xPos: number;
7
+ yPos: number;
8
+ buffer: Uint8ClampedArray;
9
+ }
10
+ export declare const MOTION_THRESHOLD = 40;
11
+ export declare const MOTION_FPS = 15;
12
+ export declare const MOTION_AREA_SIZE = 160;
13
+ /**
14
+ * Capture and create sample image from HTML Video Element
15
+ * @param canvas Canvas 2d context
16
+ * @param video Html Video element
17
+ */
18
+ export declare function takeSample(canvas: HTMLCanvasElement, video: HTMLVideoElement): ImageData;
19
+ /**
20
+ * create motion template
21
+ * @param imageData sample imagedata
22
+ */
23
+ export declare function createTemplate(imageData: ImageData): MotionTemplate;
24
+ /**
25
+ * Compare image with Motion template and return the movement distance
26
+ * @param imageData new sample's imagedata
27
+ * @param template motion template to compare
28
+ */
29
+ export declare function motionDetection(imageData: ImageData, template: MotionTemplate): number;