@opexa/portal-components 0.0.270 → 0.0.273

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 (85) hide show
  1. package/dist/client/hooks/useCamera.d.ts +1 -1
  2. package/dist/client/hooks/useCamera.js +51 -43
  3. package/dist/client/hooks/usePxToRemConverter.d.ts +2 -0
  4. package/dist/client/hooks/usePxToRemConverter.js +18 -0
  5. package/dist/client/hooks/useRect.d.ts +5 -0
  6. package/dist/client/hooks/useRect.js +45 -0
  7. package/dist/components/DepositWithdrawal/Withdrawal/GCashWithdrawal/GCashWithdrawal.js +1 -1
  8. package/dist/components/DepositWithdrawal/Withdrawal/InstapayWithdrawal/InstapayWithdrawal.js +1 -1
  9. package/dist/components/DepositWithdrawal/Withdrawal/MayaAppWithdrawal/MayaAppWithdrawal.js +1 -1
  10. package/dist/components/DepositWithdrawal/Withdrawal/MayaWithdrawal/MayaWithdrawal.js +1 -1
  11. package/dist/components/DepositWithdrawal/Withdrawal/PisoPayWithdrawal/PisoPayWithdrawal.js +1 -1
  12. package/dist/components/DepositWithdrawal/Withdrawal/VentajaWithdrawal/VentajaWithdrawal.js +1 -1
  13. package/dist/components/SignUp/SignUpKYC/IdFrontImageField/IdFrontImageField.client.d.ts +15 -0
  14. package/dist/components/SignUp/SignUpKYC/IdFrontImageField/IdFrontImageField.client.js +100 -0
  15. package/dist/components/SignUp/SignUpKYC/IdFrontImageField/IdFrontImageField.d.ts +2 -0
  16. package/dist/components/SignUp/SignUpKYC/IdFrontImageField/IdFrontImageField.js +11 -0
  17. package/dist/components/SignUp/SignUpKYC/IdFrontImageField/IdFrontImageFieldContext.d.ts +6 -0
  18. package/dist/components/SignUp/SignUpKYC/IdFrontImageField/IdFrontImageFieldContext.js +2 -0
  19. package/dist/components/SignUp/SignUpKYC/IdFrontImageField/index.d.ts +1 -0
  20. package/dist/components/SignUp/SignUpKYC/IdFrontImageField/index.js +1 -0
  21. package/dist/components/SignUp/SignUpKYC/IdFrontImageField/useIdFrontImageField.d.ts +18 -0
  22. package/dist/components/SignUp/SignUpKYC/IdFrontImageField/useIdFrontImageField.js +88 -0
  23. package/dist/components/SignUp/SignUpKYC/SelfieImageField/SelfieImageField.client.d.ts +15 -0
  24. package/dist/components/SignUp/SignUpKYC/SelfieImageField/SelfieImageField.client.js +113 -0
  25. package/dist/components/SignUp/SignUpKYC/SelfieImageField/SelfieImageField.d.ts +2 -0
  26. package/dist/components/SignUp/SignUpKYC/SelfieImageField/SelfieImageField.js +11 -0
  27. package/dist/components/SignUp/SignUpKYC/SelfieImageField/SelfieImageFieldContext.d.ts +6 -0
  28. package/dist/components/SignUp/SignUpKYC/SelfieImageField/SelfieImageFieldContext.js +2 -0
  29. package/dist/components/SignUp/SignUpKYC/SelfieImageField/index.d.ts +1 -0
  30. package/dist/components/SignUp/SignUpKYC/SelfieImageField/index.js +1 -0
  31. package/dist/components/SignUp/SignUpKYC/SelfieImageField/useSelfieImageField.d.ts +19 -0
  32. package/dist/components/SignUp/SignUpKYC/SelfieImageField/useSelfieImageField.js +186 -0
  33. package/dist/components/SignUp/SignUpKYC/SignUpKYC.lazy.js +3 -12
  34. package/dist/components/SignUp/SignUpKYC/SignUpKYCContext.d.ts +2 -3
  35. package/dist/components/SignUp/SignUpKYC/SignUpKYCForm.d.ts +1 -0
  36. package/dist/components/SignUp/SignUpKYC/SignUpKYCForm.js +464 -0
  37. package/dist/components/shared/IdFrontImageField/IdFrontImageField.client.js +11 -46
  38. package/dist/components/shared/SelfieImageField/SelfieImageField.client.js +20 -72
  39. package/dist/handlers/index.d.ts +7 -7
  40. package/dist/next.config.js +0 -8
  41. package/dist/ui/AlertDialog/AlertDialog.d.ts +88 -88
  42. package/dist/ui/AlertDialog/alertDialog.recipe.d.ts +8 -8
  43. package/dist/ui/Avatar/Avatar.d.ts +9 -9
  44. package/dist/ui/Avatar/avatar.recipe.d.ts +3 -3
  45. package/dist/ui/Badge/Badge.d.ts +12 -12
  46. package/dist/ui/Badge/badge.anatomy.d.ts +1 -1
  47. package/dist/ui/Badge/badge.recipe.d.ts +3 -3
  48. package/dist/ui/Carousel/Carousel.d.ts +72 -72
  49. package/dist/ui/Carousel/carousel.recipe.d.ts +8 -8
  50. package/dist/ui/Checkbox/Checkbox.d.ts +23 -23
  51. package/dist/ui/Checkbox/checkbox.recipe.d.ts +3 -3
  52. package/dist/ui/Clipboard/Clipboard.d.ts +18 -18
  53. package/dist/ui/Clipboard/clipboard.recipe.d.ts +3 -3
  54. package/dist/ui/Collapsible/Collapsible.d.ts +32 -32
  55. package/dist/ui/Collapsible/collapsible.recipe.d.ts +8 -8
  56. package/dist/ui/Combobox/Combobox.d.ts +42 -42
  57. package/dist/ui/Combobox/combobox.recipe.d.ts +3 -3
  58. package/dist/ui/DatePicker/DatePicker.d.ts +72 -72
  59. package/dist/ui/DatePicker/datePicker.recipe.d.ts +3 -3
  60. package/dist/ui/Dialog/Dialog.d.ts +88 -88
  61. package/dist/ui/Dialog/dialog.recipe.d.ts +8 -8
  62. package/dist/ui/Drawer/Drawer.d.ts +33 -33
  63. package/dist/ui/Drawer/drawer.recipe.d.ts +3 -3
  64. package/dist/ui/Field/Field.d.ts +21 -21
  65. package/dist/ui/Field/field.recipe.d.ts +3 -3
  66. package/dist/ui/Menu/Menu.d.ts +307 -307
  67. package/dist/ui/Menu/menu.recipe.d.ts +17 -17
  68. package/dist/ui/PasswordInput/PasswordInput.d.ts +18 -18
  69. package/dist/ui/PasswordInput/passwordInput.recipe.d.ts +3 -3
  70. package/dist/ui/Popover/Popover.d.ts +88 -88
  71. package/dist/ui/Popover/popover.recipe.d.ts +8 -8
  72. package/dist/ui/Progress/Progress.d.ts +27 -27
  73. package/dist/ui/Progress/progress.recipe.d.ts +3 -3
  74. package/dist/ui/QrCode/QrCode.d.ts +25 -25
  75. package/dist/ui/QrCode/qrCode.recipe.d.ts +5 -5
  76. package/dist/ui/SegmentGroup/SegmentGroup.d.ts +18 -18
  77. package/dist/ui/SegmentGroup/segmentGroup.recipe.d.ts +3 -3
  78. package/dist/ui/Select/Select.d.ts +45 -45
  79. package/dist/ui/Select/select.recipe.d.ts +3 -3
  80. package/dist/ui/Table/Table.d.ts +21 -21
  81. package/dist/ui/Table/table.anatomy.d.ts +1 -1
  82. package/dist/ui/Table/table.recipe.d.ts +3 -3
  83. package/dist/ui/Tabs/Tabs.d.ts +15 -15
  84. package/dist/ui/Tabs/tabs.recipe.d.ts +3 -3
  85. package/package.json +2 -4
@@ -12,7 +12,7 @@ export interface CameraData {
12
12
  export interface UseCameraReturn<T extends string = never> {
13
13
  open(): Promise<void>;
14
14
  close(): Promise<void>;
15
- snap(): Promise<void>;
15
+ snap(): Promise<CameraData | null>;
16
16
  reopen(): Promise<void>;
17
17
  reset(): Promise<void>;
18
18
  data: CameraData | null;
@@ -115,52 +115,60 @@ export function useCamera(options = {}) {
115
115
  context.scale(-1, 1);
116
116
  }
117
117
  context.drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
118
- canvas.toBlob(async (blob) => {
119
- if (!blob) {
120
- setSnapping(false);
121
- return setError({
122
- name: 'CameraError',
123
- message: "'canvas.toBlob' failed to create blob",
118
+ return new Promise((resolve) => {
119
+ canvas.toBlob(async (blob) => {
120
+ if (!blob) {
121
+ setSnapping(false);
122
+ resolve(null);
123
+ return setError({
124
+ name: 'CameraError',
125
+ message: "'canvas.toBlob' failed to create blob",
126
+ });
127
+ }
128
+ const url = canvas.toDataURL('image/jpeg', 1);
129
+ const file = new File([blob], `${crypto.randomUUID()}.jpeg`, {
130
+ type: 'image/jpeg',
131
+ endings: 'native',
132
+ lastModified: Date.now(),
124
133
  });
125
- }
126
- const url = canvas.toDataURL('image/jpeg', 1);
127
- const file = new File([blob], `${crypto.randomUUID()}.jpeg`, {
128
- type: 'image/jpeg',
129
- endings: 'native',
130
- lastModified: Date.now(),
131
- });
132
- const image = new Image();
133
- image.src = url;
134
- image.alt = '';
135
- image.width = canvas.width;
136
- image.height = canvas.height;
137
- if (!image.complete || image.naturalWidth === 0) {
138
- await new Promise((resolve, reject) => {
139
- image.onload = () => resolve();
140
- image.onerror = () => reject();
134
+ const image = new Image();
135
+ image.src = url;
136
+ image.alt = '';
137
+ image.width = canvas.width;
138
+ image.height = canvas.height;
139
+ if (!image.complete || image.naturalWidth === 0) {
140
+ await new Promise((resolve, reject) => {
141
+ image.onload = () => resolve();
142
+ image.onerror = () => reject();
143
+ });
144
+ }
145
+ const data = {
146
+ url,
147
+ file,
148
+ image,
149
+ };
150
+ if (!options.transform) {
151
+ setData(data);
152
+ setSnapping(false);
153
+ resolve(data);
154
+ return;
155
+ }
156
+ const transformResult = await options.transform({
157
+ ...data,
158
+ video,
159
+ canvas,
141
160
  });
142
- }
143
- const data = {
144
- url,
145
- file,
146
- image,
147
- };
148
- if (!options.transform) {
149
- setData(data);
161
+ if (transformResult.ok) {
162
+ setData(transformResult.data);
163
+ resolve(transformResult.data);
164
+ }
165
+ else {
166
+ setError(transformResult.error);
167
+ resolve(null);
168
+ }
150
169
  setSnapping(false);
151
- return;
152
- }
153
- const transformResult = await options.transform({
154
- ...data,
155
- video,
156
- canvas,
157
- });
158
- if (transformResult.ok)
159
- setData(transformResult.data);
160
- else
161
- setError(transformResult.error);
162
- setSnapping(false);
163
- }, 'image/jpeg', 1);
170
+ }, 'image/jpeg', 1);
171
+ });
164
172
  }, [mirror, options]);
165
173
  const reset = useCallback(() => {
166
174
  setData(null);
@@ -0,0 +1,2 @@
1
+ export type PxToRemConverter = (px: number) => number;
2
+ export declare function usePxToRemConverter(): PxToRemConverter;
@@ -0,0 +1,18 @@
1
+ import { useEffect, useState } from 'react';
2
+ export function usePxToRemConverter() {
3
+ const [rootFontSize, setRootFontSize] = useState(16);
4
+ useEffect(() => {
5
+ const updateRootFontSize = () => {
6
+ const root = document.documentElement;
7
+ setRootFontSize(parseFloat(getComputedStyle(root).fontSize));
8
+ };
9
+ updateRootFontSize();
10
+ window.addEventListener('resize', updateRootFontSize);
11
+ return () => {
12
+ window.removeEventListener('resize', updateRootFontSize);
13
+ };
14
+ }, []);
15
+ return function convert(px) {
16
+ return px / rootFontSize;
17
+ };
18
+ }
@@ -0,0 +1,5 @@
1
+ import { type RefObject } from 'react';
2
+ export interface UseRectOptions {
3
+ enabled?: boolean;
4
+ }
5
+ export declare function useRect<T extends HTMLElement>(ref: RefObject<T | null>, options?: UseRectOptions): DOMRect;
@@ -0,0 +1,45 @@
1
+ import { useEffect, useState } from 'react';
2
+ const FALLBACK_RECT = {
3
+ x: 0,
4
+ y: 0,
5
+ top: 0,
6
+ left: 0,
7
+ right: 0,
8
+ bottom: 0,
9
+ width: 0,
10
+ height: 0,
11
+ toJSON() {
12
+ return {
13
+ x: 0,
14
+ y: 0,
15
+ top: 0,
16
+ left: 0,
17
+ right: 0,
18
+ bottom: 0,
19
+ width: 0,
20
+ height: 0,
21
+ };
22
+ },
23
+ };
24
+ export function useRect(ref, options) {
25
+ const [rect, setRect] = useState(FALLBACK_RECT);
26
+ useEffect(() => {
27
+ if (options?.enabled === false)
28
+ return;
29
+ function updateRect() {
30
+ if (!ref.current)
31
+ return;
32
+ setRect(ref.current.getBoundingClientRect());
33
+ }
34
+ const observer = new ResizeObserver(updateRect);
35
+ if (ref.current)
36
+ observer.observe(ref.current);
37
+ requestAnimationFrame(updateRect);
38
+ window.addEventListener('resize', updateRect);
39
+ return () => {
40
+ observer.disconnect();
41
+ window.removeEventListener('resize', updateRect);
42
+ };
43
+ }, [options?.enabled, ref]);
44
+ return rect;
45
+ }
@@ -118,7 +118,7 @@ export function GCashWithdrawal() {
118
118
  shouldDirty: true,
119
119
  shouldValidate: true,
120
120
  });
121
- }, min: minimumAmount, max: maximumAmount, className: "mt-xl" }), _jsxs(Field.Root, { className: "mt-3xl", invalid: !!form.formState.errors.password, children: [_jsxs(PasswordInput.Root, { children: [_jsx(PasswordInput.Label, { children: "Transaction Password" }), _jsxs(PasswordInput.Control, { children: [_jsx(PasswordInput.Input, { placeholder: "Enter password", ...form.register('password') }), _jsx(PasswordInput.VisibilityTrigger, { children: _jsx(PasswordInput.Indicator, { fallback: _jsx(EyeOffIcon, {}), asChild: true, children: _jsx(EyeIcon, {}) }) })] })] }), _jsx(Field.ErrorText, { children: form.formState.errors.password?.message })] }), _jsx(TransactionPasswordNotSet, {}), _jsx(Button, { type: "submit", className: "mt-6", disabled: createWithdrawalMutation.isPending, children: "Withdraw" }), _jsxs("p", { className: "text-text-tertiary-600 mt-lg text-xs", children: ["Upon withdrawing, you agree to our", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/terms-of-use', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Terms of Use" }), ' ', "and", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/privacy-policy', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Privacy Policy" }), "."] }), _jsx(AlertDialog.Root, { open: status !== 'waiting', onOpenChange: (details) => {
121
+ }, min: minimumAmount, max: maximumAmount, className: "mt-xl" }), _jsxs(Field.Root, { className: "mt-3xl", invalid: !!form.formState.errors.password, children: [_jsxs(PasswordInput.Root, { children: [_jsx(PasswordInput.Label, { children: "Transaction Password" }), _jsxs(PasswordInput.Control, { children: [_jsx(PasswordInput.Input, { placeholder: "Enter password", ...form.register('password') }), _jsx(PasswordInput.VisibilityTrigger, { children: _jsx(PasswordInput.Indicator, { fallback: _jsx(EyeOffIcon, {}), asChild: true, children: _jsx(EyeIcon, {}) }) })] })] }), _jsx(Field.ErrorText, { children: form.formState.errors.password?.message })] }), _jsx(TransactionPasswordNotSet, {}), _jsx(Button, { type: "submit", className: "mt-6", disabled: createWithdrawalMutation.isPending, children: "Withdraw" }), _jsxs("p", { className: "text-text-tertiary-600 mt-lg text-xs", children: ["Upon withdrawing, you agree to our", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/terms-of-use', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Terms of Use" }), ' ', "and", ' ', _jsx(Link, { href: depositWithdrawalProps.privacyPolicyUrl ?? '/privacy-policy', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Privacy Policy" }), "."] }), _jsx(AlertDialog.Root, { open: status !== 'waiting', onOpenChange: (details) => {
122
122
  if (!details.open) {
123
123
  setStatus('waiting');
124
124
  }
@@ -142,7 +142,7 @@ export function InstapayWithdrawal() {
142
142
  shouldDirty: true,
143
143
  shouldValidate: true,
144
144
  });
145
- }, min: minimumAmount, max: maximumAmount, className: "mt-xl" }), _jsxs(Field.Root, { className: "mt-3xl", invalid: !!form.formState.errors.password, children: [_jsxs(PasswordInput.Root, { children: [_jsx(PasswordInput.Label, { children: "Transaction Password" }), _jsxs(PasswordInput.Control, { children: [_jsx(PasswordInput.Input, { placeholder: "Enter password", ...form.register('password') }), _jsx(PasswordInput.VisibilityTrigger, { children: _jsx(PasswordInput.Indicator, { fallback: _jsx(EyeOffIcon, {}), asChild: true, children: _jsx(EyeIcon, {}) }) })] })] }), _jsx(Field.ErrorText, { children: form.formState.errors.password?.message })] }), _jsx(TransactionPasswordNotSet, {}), _jsx(Button, { type: "submit", className: "mt-6", disabled: createWithdrawalMutation.isPending, children: "Withdraw" }), _jsxs("p", { className: "text-text-tertiary-600 mt-lg text-xs", children: ["Upon withdrawing, you agree to our", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/terms-of-use', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Terms of Use" }), ' ', "and", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/privacy-policy', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Privacy Policy" }), "."] }), _jsx(AlertDialog.Root, { open: status !== 'waiting', onOpenChange: (details) => {
145
+ }, min: minimumAmount, max: maximumAmount, className: "mt-xl" }), _jsxs(Field.Root, { className: "mt-3xl", invalid: !!form.formState.errors.password, children: [_jsxs(PasswordInput.Root, { children: [_jsx(PasswordInput.Label, { children: "Transaction Password" }), _jsxs(PasswordInput.Control, { children: [_jsx(PasswordInput.Input, { placeholder: "Enter password", ...form.register('password') }), _jsx(PasswordInput.VisibilityTrigger, { children: _jsx(PasswordInput.Indicator, { fallback: _jsx(EyeOffIcon, {}), asChild: true, children: _jsx(EyeIcon, {}) }) })] })] }), _jsx(Field.ErrorText, { children: form.formState.errors.password?.message })] }), _jsx(TransactionPasswordNotSet, {}), _jsx(Button, { type: "submit", className: "mt-6", disabled: createWithdrawalMutation.isPending, children: "Withdraw" }), _jsxs("p", { className: "text-text-tertiary-600 mt-lg text-xs", children: ["Upon withdrawing, you agree to our", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/terms-of-use', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Terms of Use" }), ' ', "and", ' ', _jsx(Link, { href: depositWithdrawalProps.privacyPolicyUrl ?? '/privacy-policy', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Privacy Policy" }), "."] }), _jsx(AlertDialog.Root, { open: status !== 'waiting', onOpenChange: (details) => {
146
146
  if (!details.open) {
147
147
  setStatus('waiting');
148
148
  }
@@ -108,7 +108,7 @@ export function MayaAppWithdrawal() {
108
108
  shouldDirty: true,
109
109
  shouldValidate: true,
110
110
  });
111
- }, min: minimumAmount, max: maximumAmount, className: "mt-xl" }), _jsxs(Field.Root, { className: "mt-3xl", invalid: !!form.formState.errors.password, children: [_jsxs(PasswordInput.Root, { children: [_jsx(PasswordInput.Label, { children: "Transaction Password" }), _jsxs(PasswordInput.Control, { children: [_jsx(PasswordInput.Input, { placeholder: "Enter password", ...form.register('password') }), _jsx(PasswordInput.VisibilityTrigger, { children: _jsx(PasswordInput.Indicator, { fallback: _jsx(EyeOffIcon, {}), asChild: true, children: _jsx(EyeIcon, {}) }) })] })] }), _jsx(Field.ErrorText, { children: form.formState.errors.password?.message })] }), _jsx(TransactionPasswordNotSet, {}), _jsx(Button, { type: "submit", className: "mt-6", disabled: createWithdrawalMutation.isPending, children: "Withdraw" }), _jsxs("p", { className: "text-text-tertiary-600 mt-lg text-xs", children: ["Upon withdrawing, you agree to our", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/terms-of-use', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Terms of Use" }), ' ', "and", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/privacy-policy', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Privacy Policy" }), "."] }), _jsx(AlertDialog.Root, { open: status !== 'waiting', onOpenChange: (details) => {
111
+ }, min: minimumAmount, max: maximumAmount, className: "mt-xl" }), _jsxs(Field.Root, { className: "mt-3xl", invalid: !!form.formState.errors.password, children: [_jsxs(PasswordInput.Root, { children: [_jsx(PasswordInput.Label, { children: "Transaction Password" }), _jsxs(PasswordInput.Control, { children: [_jsx(PasswordInput.Input, { placeholder: "Enter password", ...form.register('password') }), _jsx(PasswordInput.VisibilityTrigger, { children: _jsx(PasswordInput.Indicator, { fallback: _jsx(EyeOffIcon, {}), asChild: true, children: _jsx(EyeIcon, {}) }) })] })] }), _jsx(Field.ErrorText, { children: form.formState.errors.password?.message })] }), _jsx(TransactionPasswordNotSet, {}), _jsx(Button, { type: "submit", className: "mt-6", disabled: createWithdrawalMutation.isPending, children: "Withdraw" }), _jsxs("p", { className: "text-text-tertiary-600 mt-lg text-xs", children: ["Upon withdrawing, you agree to our", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/terms-of-use', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Terms of Use" }), ' ', "and", ' ', _jsx(Link, { href: depositWithdrawalProps.privacyPolicyUrl ?? '/privacy-policy', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Privacy Policy" }), "."] }), _jsx(AlertDialog.Root, { open: status !== 'waiting', onOpenChange: (details) => {
112
112
  if (!details.open) {
113
113
  setStatus('waiting');
114
114
  }
@@ -118,7 +118,7 @@ export function MayaWithdrawal() {
118
118
  shouldDirty: true,
119
119
  shouldValidate: true,
120
120
  });
121
- }, min: minimumAmount, max: maximumAmount, className: "mt-xl" }), _jsxs(Field.Root, { className: "mt-3xl", invalid: !!form.formState.errors.password, children: [_jsxs(PasswordInput.Root, { children: [_jsx(PasswordInput.Label, { children: "Transaction Password" }), _jsxs(PasswordInput.Control, { children: [_jsx(PasswordInput.Input, { placeholder: "Enter password", ...form.register('password') }), _jsx(PasswordInput.VisibilityTrigger, { children: _jsx(PasswordInput.Indicator, { fallback: _jsx(EyeOffIcon, {}), asChild: true, children: _jsx(EyeIcon, {}) }) })] })] }), _jsx(Field.ErrorText, { children: form.formState.errors.password?.message })] }), _jsx(TransactionPasswordNotSet, {}), _jsx(Button, { type: "submit", className: "mt-6", disabled: createWithdrawalMutation.isPending, children: "Withdraw" }), _jsxs("p", { className: "text-text-tertiary-600 mt-lg text-xs", children: ["Upon withdrawing, you agree to our", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/terms-of-use', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Terms of Use" }), ' ', "and", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/privacy-policy', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Privacy Policy" }), "."] }), _jsx(AlertDialog.Root, { open: status !== 'waiting', onOpenChange: (details) => {
121
+ }, min: minimumAmount, max: maximumAmount, className: "mt-xl" }), _jsxs(Field.Root, { className: "mt-3xl", invalid: !!form.formState.errors.password, children: [_jsxs(PasswordInput.Root, { children: [_jsx(PasswordInput.Label, { children: "Transaction Password" }), _jsxs(PasswordInput.Control, { children: [_jsx(PasswordInput.Input, { placeholder: "Enter password", ...form.register('password') }), _jsx(PasswordInput.VisibilityTrigger, { children: _jsx(PasswordInput.Indicator, { fallback: _jsx(EyeOffIcon, {}), asChild: true, children: _jsx(EyeIcon, {}) }) })] })] }), _jsx(Field.ErrorText, { children: form.formState.errors.password?.message })] }), _jsx(TransactionPasswordNotSet, {}), _jsx(Button, { type: "submit", className: "mt-6", disabled: createWithdrawalMutation.isPending, children: "Withdraw" }), _jsxs("p", { className: "text-text-tertiary-600 mt-lg text-xs", children: ["Upon withdrawing, you agree to our", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/terms-of-use', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Terms of Use" }), ' ', "and", ' ', _jsx(Link, { href: depositWithdrawalProps.privacyPolicyUrl ?? '/privacy-policy', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Privacy Policy" }), "."] }), _jsx(AlertDialog.Root, { open: status !== 'waiting', onOpenChange: (details) => {
122
122
  if (!details.open) {
123
123
  setStatus('waiting');
124
124
  }
@@ -142,7 +142,7 @@ export function PisoPayWithdrawal() {
142
142
  shouldDirty: true,
143
143
  shouldValidate: true,
144
144
  });
145
- }, min: minimumAmount, max: maximumAmount, className: "mt-xl" }), _jsxs(Field.Root, { className: "mt-3xl", invalid: !!form.formState.errors.password, children: [_jsxs(PasswordInput.Root, { children: [_jsx(PasswordInput.Label, { children: "Transaction Password" }), _jsxs(PasswordInput.Control, { children: [_jsx(PasswordInput.Input, { placeholder: "Enter password", ...form.register('password') }), _jsx(PasswordInput.VisibilityTrigger, { children: _jsx(PasswordInput.Indicator, { fallback: _jsx(EyeOffIcon, {}), asChild: true, children: _jsx(EyeIcon, {}) }) })] })] }), _jsx(Field.ErrorText, { children: form.formState.errors.password?.message })] }), _jsx(TransactionPasswordNotSet, {}), _jsx(Button, { type: "submit", className: "mt-6", disabled: createWithdrawalMutation.isPending, children: "Withdraw" }), _jsxs("p", { className: "text-text-tertiary-600 mt-lg text-xs", children: ["Upon withdrawing, you agree to our", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/terms-of-use', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Terms of Use" }), ' ', "and", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/privacy-policy', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Privacy Policy" }), "."] }), _jsx(AlertDialog.Root, { open: status !== 'waiting', onOpenChange: (details) => {
145
+ }, min: minimumAmount, max: maximumAmount, className: "mt-xl" }), _jsxs(Field.Root, { className: "mt-3xl", invalid: !!form.formState.errors.password, children: [_jsxs(PasswordInput.Root, { children: [_jsx(PasswordInput.Label, { children: "Transaction Password" }), _jsxs(PasswordInput.Control, { children: [_jsx(PasswordInput.Input, { placeholder: "Enter password", ...form.register('password') }), _jsx(PasswordInput.VisibilityTrigger, { children: _jsx(PasswordInput.Indicator, { fallback: _jsx(EyeOffIcon, {}), asChild: true, children: _jsx(EyeIcon, {}) }) })] })] }), _jsx(Field.ErrorText, { children: form.formState.errors.password?.message })] }), _jsx(TransactionPasswordNotSet, {}), _jsx(Button, { type: "submit", className: "mt-6", disabled: createWithdrawalMutation.isPending, children: "Withdraw" }), _jsxs("p", { className: "text-text-tertiary-600 mt-lg text-xs", children: ["Upon withdrawing, you agree to our", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/terms-of-use', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Terms of Use" }), ' ', "and", ' ', _jsx(Link, { href: depositWithdrawalProps.privacyPolicyUrl ?? '/privacy-policy', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Privacy Policy" }), "."] }), _jsx(AlertDialog.Root, { open: status !== 'waiting', onOpenChange: (details) => {
146
146
  if (!details.open) {
147
147
  setStatus('waiting');
148
148
  }
@@ -142,7 +142,7 @@ export function VentajaWithdrawal() {
142
142
  shouldDirty: true,
143
143
  shouldValidate: true,
144
144
  });
145
- }, min: minimumAmount, max: maximumAmount, className: "mt-xl" }), _jsxs(Field.Root, { className: "mt-3xl", invalid: !!form.formState.errors.password, children: [_jsxs(PasswordInput.Root, { children: [_jsx(PasswordInput.Label, { children: "Transaction Password" }), _jsxs(PasswordInput.Control, { children: [_jsx(PasswordInput.Input, { placeholder: "Enter password", ...form.register('password') }), _jsx(PasswordInput.VisibilityTrigger, { children: _jsx(PasswordInput.Indicator, { fallback: _jsx(EyeOffIcon, {}), asChild: true, children: _jsx(EyeIcon, {}) }) })] })] }), _jsx(Field.ErrorText, { children: form.formState.errors.password?.message })] }), _jsx(TransactionPasswordNotSet, {}), _jsx(Button, { type: "submit", className: "mt-6", disabled: createWithdrawalMutation.isPending, children: "Withdraw" }), _jsxs("p", { className: "text-text-tertiary-600 mt-lg text-xs", children: ["Upon withdrawing, you agree to our", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/terms-of-use', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Terms of Use" }), ' ', "and", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/privacy-policy', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Privacy Policy" }), "."] }), _jsx(AlertDialog.Root, { open: status !== 'waiting', onOpenChange: (details) => {
145
+ }, min: minimumAmount, max: maximumAmount, className: "mt-xl" }), _jsxs(Field.Root, { className: "mt-3xl", invalid: !!form.formState.errors.password, children: [_jsxs(PasswordInput.Root, { children: [_jsx(PasswordInput.Label, { children: "Transaction Password" }), _jsxs(PasswordInput.Control, { children: [_jsx(PasswordInput.Input, { placeholder: "Enter password", ...form.register('password') }), _jsx(PasswordInput.VisibilityTrigger, { children: _jsx(PasswordInput.Indicator, { fallback: _jsx(EyeOffIcon, {}), asChild: true, children: _jsx(EyeIcon, {}) }) })] })] }), _jsx(Field.ErrorText, { children: form.formState.errors.password?.message })] }), _jsx(TransactionPasswordNotSet, {}), _jsx(Button, { type: "submit", className: "mt-6", disabled: createWithdrawalMutation.isPending, children: "Withdraw" }), _jsxs("p", { className: "text-text-tertiary-600 mt-lg text-xs", children: ["Upon withdrawing, you agree to our", ' ', _jsx(Link, { href: depositWithdrawalProps.termsOfUseUrl ?? '/terms-of-use', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Terms of Use" }), ' ', "and", ' ', _jsx(Link, { href: depositWithdrawalProps.privacyPolicyUrl ?? '/privacy-policy', onClick: () => globalStore.depositWithdrawal.setOpen(false), className: "text-text-warning-primary-600 underline underline-offset-2", children: "Privacy Policy" }), "."] }), _jsx(AlertDialog.Root, { open: status !== 'waiting', onOpenChange: (details) => {
146
146
  if (!details.open) {
147
147
  setStatus('waiting');
148
148
  }
@@ -0,0 +1,15 @@
1
+ import { type CSSProperties, type RefObject } from 'react';
2
+ import { type ValidateFileError } from '../../../../utils/validateFile';
3
+ import { type UseIdFrontImageFieldProps } from './useIdFrontImageField';
4
+ export interface IdFrontImageFieldProps extends UseIdFrontImageFieldProps {
5
+ ref?: RefObject<HTMLDivElement | null>;
6
+ id?: string;
7
+ style?: CSSProperties;
8
+ className?: string;
9
+ invalid?: boolean;
10
+ readOnly?: boolean;
11
+ disabled?: boolean;
12
+ required?: boolean;
13
+ onError?: (error: ValidateFileError) => void;
14
+ }
15
+ export declare function IdFrontImageField__client(props: IdFrontImageFieldProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,100 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import Image from 'next/image';
3
+ import { useRef } from 'react';
4
+ import { twMerge } from 'tailwind-merge';
5
+ import { usePxToRemConverter } from '../../../../client/hooks/usePxToRemConverter.js';
6
+ import { useRect } from '../../../../client/hooks/useRect.js';
7
+ import { Camera01Icon } from '../../../../icons/Camera01Icon.js';
8
+ import { CameraOffIcon } from '../../../../icons/CameraOffIcon.js';
9
+ import { CheckCircleIcon } from '../../../../icons/CheckCircleIcon.js';
10
+ import { RefreshCcw01Icon } from '../../../../icons/RefreshCcw01Icon.js';
11
+ import { Spinner02Icon } from '../../../../icons/Spinner02Icon.js';
12
+ import { UploadCloud02Icon } from '../../../../icons/UploadCloud02Icon.js';
13
+ import { XIcon } from '../../../../icons/XIcon.js';
14
+ import { Button } from '../../../../ui/Button/index.js';
15
+ import { Dialog } from '../../../../ui/Dialog/index.js';
16
+ import { Portal } from '../../../../ui/Portal/index.js';
17
+ import { createSplitProps } from '../../../../utils/createSplitProps.js';
18
+ import { validateFile, } from '../../../../utils/validateFile.js';
19
+ import { IdFrontImageFieldProvider, useIdFrontImageFieldContext, } from './IdFrontImageFieldContext.js';
20
+ import { useIdFrontImageField, } from './useIdFrontImageField.js';
21
+ export function IdFrontImageField__client(props) {
22
+ const [useIdFrontImageFieldProps, localProps] = createSplitProps([
23
+ 'value',
24
+ 'onChange',
25
+ 'defaultValue',
26
+ ])(props);
27
+ const context = useIdFrontImageField(useIdFrontImageFieldProps);
28
+ return (_jsxs(IdFrontImageFieldProvider, { value: context, children: [_jsxs("div", { ref: localProps.ref, id: localProps.id, style: localProps.style, className: twMerge('border-border-primary bg-bg-primary group relative aspect-[352/180] w-full shrink-0 rounded-xl border p-xl', localProps.className), onDragOver: (e) => e.preventDefault(), onDragEnter: (e) => e.preventDefault(), onDragLeave: (e) => e.preventDefault(), onDrop: (e) => {
29
+ e.preventDefault();
30
+ const file = e.dataTransfer.files?.[0];
31
+ if (!file)
32
+ return;
33
+ const error = validateFile(file);
34
+ if (error)
35
+ return localProps.onError?.(error);
36
+ context.setValue(file);
37
+ }, "aria-describedby": context.field?.ariaDescribedby, children: [_jsx("input", { id: context.field?.ids?.control, ref: context.inputRef, type: "file", accept: "image/png, image/jpeg", onChange: (e) => {
38
+ const file = e.target.files?.[0];
39
+ if (!file)
40
+ return;
41
+ const error = validateFile(file);
42
+ if (error)
43
+ return localProps.onError?.(error);
44
+ context.setValue(file);
45
+ }, disabled: context.field?.disabled || localProps.disabled, readOnly: context.field?.readOnly || localProps.readOnly, required: context.field?.required || localProps.required, className: "sr-only" }), !context.value && (_jsxs("div", { className: "flex size-full flex-col justify-center", children: [_jsx("div", { className: "border-border-primary shadow-xs mx-auto flex size-8 items-center justify-center rounded-sm border", children: _jsx(UploadCloud02Icon, { className: "text-text-placeholder-subtle size-4" }) }), _jsxs("h2", { className: "text-text-tertiary-600 mt-lg", children: [_jsxs("span", { className: "block text-center text-sm", children: [_jsx("button", { type: "button", onClick: () => {
46
+ context.inputRef.current?.click();
47
+ }, disabled: context.field?.disabled ||
48
+ context.field?.readOnly ||
49
+ localProps.disabled ||
50
+ localProps.readOnly, className: "text-button-secondary-fg font-semibold disabled:opacity-60", children: "Click to upload" }), ' ', "or drag and drop"] }), _jsx("span", { className: "mt-xs block text-center text-xs", children: "PNG, JPG or JPEG (max. 10mb)" }), _jsx("span", { className: "m-txs block text-center text-xs", children: "or" })] }), _jsx(Button, { size: "sm", variant: "outline", className: "mx-auto mt-md w-auto", onClick: () => {
51
+ context.disclosure.setOpen(true);
52
+ }, disabled: context.field?.disabled ||
53
+ context.field?.readOnly ||
54
+ localProps.disabled ||
55
+ localProps.readOnly, children: "Take a photo" })] })), context.valueAsUrl && (_jsxs("div", { className: "relative", children: [_jsx(Image, { src: context.valueAsUrl, alt: "", width: 600, height: 378.08, unoptimized: true, className: "h-auto w-full rounded-md" }), _jsx("button", { type: "button", className: "backdrop-blur-xs absolute right-2 top-2 rounded-full bg-white/10 p-1", onClick: () => {
56
+ context.setValue(null);
57
+ }, children: _jsx(XIcon, { className: "size-5" }) })] }))] }), _jsx(Camera, {})] }));
58
+ }
59
+ /**
60
+ * -------------------------------------
61
+ * Camera
62
+ * -------------------------------------
63
+ */
64
+ function Camera() {
65
+ const context = useIdFrontImageFieldContext();
66
+ return (_jsx(Dialog.Root, { open: context.disclosure.open, onOpenChange: (details) => {
67
+ context.disclosure.setOpen(details.open);
68
+ }, closeOnEscape: false, closeOnInteractOutside: false, onExitComplete: context.camera.close, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "!z-[calc(var(--z-dialog)+1)]" }), _jsx(Dialog.Positioner, { className: "!z-[calc(var(--z-dialog)+2)] flex items-center justify-center overflow-y-auto py-4", children: _jsxs(Dialog.Content, { className: "bg-bg-primary-alt mx-auto w-[calc(100dvw-1rem)] max-w-[calc(100dvw-1rem)] overflow-y-auto rounded-lg px-4 py-5 lg:w-[747px] lg:max-w-[747px] lg:px-3xl lg:py-4xl", children: [_jsx(Dialog.CloseTrigger, { children: _jsx(XIcon, {}) }), _jsx(Dialog.Title, { className: "text-center font-semibold lg:text-xl", children: "Take a Picture of Your Front ID" }), _jsxs(Dialog.Description, { className: "text-text-tertiary-600 mt-md text-center text-xs lg:text-base", children: ["Make sure your ID is clearly visible, well-lit, and not blurry.", ' ', _jsx("br", { className: "hidden lg:block" }), "Avoid glare or reflections, and ensure all corners are within\u00A0the\u00A0frame."] }), _jsxs("div", { className: "relative mt-5 lg:mt-10 lg:px-3xl", children: [_jsx(Video, {}), context.camera.error && (_jsxs("div", { className: "border-border-disabled flex aspect-[4/3] flex-col items-center justify-center rounded-md border bg-black px-4 lg:aspect-video", children: [_jsx(CameraOffIcon, { className: "text-text-placeholder-subtle size-10 text-center lg:size-12" }), _jsx("h2", { className: "mt-3 text-sm font-semibold lg:mt-4 lg:text-base", children: context.camera.error.name }), _jsx("p", { className: "text-text-tertiary-600 mt-0.5 text-center text-xs lg:mt-1 lg:text-sm", children: context.camera.error.message }), _jsx(Button, { size: "xs", variant: "outline", colorScheme: "gray", fullWidth: false, className: "mt-4 lg:mt-5", onClick: () => {
69
+ context.camera.reopen();
70
+ }, children: "Try again" })] })), context.camera.loading && (_jsx("div", { className: "border-border-disabled flex aspect-[4/3] flex-col items-center justify-center rounded-md border bg-black px-4 lg:aspect-video", children: _jsx(Spinner02Icon, { className: "text-text-placeholder size-8" }) })), context.camera.data && (_jsx("div", { className: "border-border-disabled aspect-[4/3] w-full overflow-hidden rounded-md border bg-black lg:aspect-video", children: _jsx(Image, { src: context.camera.data.url, alt: "", width: 600, height: 378.08, unoptimized: true, className: "mx-auto mt-2 block h-[calc(100%-1rem)] w-auto" }) }))] }), !context.camera.data && (_jsx("div", { className: "mt-5 lg:mt-10", children: _jsxs(Button, { className: "disabled:bg-bg-disabled disabled:text-text-disabled mx-auto w-full px-xl py-lg lg:w-[10rem]", onClick: () => {
71
+ context.camera.snap();
72
+ }, disabled: context.camera.snapping ||
73
+ context.camera.loading ||
74
+ !!context.camera.error, children: [context.camera.snapping ? (_jsx(Spinner02Icon, { className: "size-5" })) : (_jsx(Camera01Icon, { className: "size-5" })), "Capture"] }) })), context.camera.data && (_jsxs("div", { className: "mt-5 flex gap-3 lg:mt-10 lg:justify-center", children: [_jsxs(Button, { onClick: () => {
75
+ const file = context.camera.data?.file;
76
+ if (!file)
77
+ return;
78
+ context.setValue(file);
79
+ context.disclosure.setOpen(false);
80
+ }, className: "w-full lg:w-[10rem]", children: [_jsx(CheckCircleIcon, { className: "size-5" }), "Use Photo"] }), _jsxs(Button, { variant: "outline", colorScheme: "gray", onClick: () => {
81
+ context.camera.reset();
82
+ }, className: "w-full lg:w-[10rem]", children: [_jsx(RefreshCcw01Icon, { className: "size-5" }), " Retake"] })] }))] }) })] }) }));
83
+ }
84
+ /**
85
+ * -------------------------------------
86
+ * Video
87
+ * -------------------------------------
88
+ */
89
+ function Video() {
90
+ const context = useIdFrontImageFieldContext();
91
+ const pxToRem = usePxToRemConverter();
92
+ const rootRef = useRef(null);
93
+ const rootRect = useRect(rootRef);
94
+ const guideRect = useRect(context.guideRef);
95
+ const x = (rootRect.width - guideRect.width) / 2;
96
+ const y = (rootRect.height - guideRect.height) / 2;
97
+ return (_jsxs("div", { ref: rootRef, className: twMerge('relative h-auto w-full overflow-hidden', !context.camera.data && !context.camera.error && !context.camera.loading
98
+ ? 'block'
99
+ : 'hidden'), children: [_jsx("video", { ...context.camera.videoProps }), _jsx("div", { className: "pointer-events-none absolute left-0 right-0 top-0 z-20 bg-black/60 backdrop-blur-sm", style: { height: `${pxToRem(y)}rem` } }), _jsx("div", { className: "pointer-events-none absolute bottom-0 left-0 right-0 z-20 bg-black/60 backdrop-blur-sm", style: { height: `${pxToRem(y)}rem` } }), _jsx("div", { className: "pointer-events-none absolute left-0 z-20 bg-black/60 backdrop-blur-sm", style: { top: y, bottom: y, width: `${pxToRem(x)}rem` } }), _jsx("div", { className: "pointer-events-none absolute right-0 z-20 bg-black/60 backdrop-blur-sm", style: { top: y, bottom: y, width: `${pxToRem(x)}rem` } }), _jsx("div", { ref: context.guideRef, className: "border-utility-warning-700 pointer-events-none absolute left-1/2 top-1/2 z-10 aspect-[85.6/53.98] w-[calc(100%-1rem)] max-w-[24.688rem] -translate-x-1/2 -translate-y-1/2 border-4 border-dashed transition-all duration-200" })] }));
100
+ }
@@ -0,0 +1,2 @@
1
+ import type { IdFrontImageFieldProps } from './IdFrontImageField.client';
2
+ export declare function IdFrontImageField(props: IdFrontImageFieldProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,11 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import dynamic from 'next/dynamic';
4
+ import { Spinner02Icon } from '../../../../icons/Spinner02Icon.js';
5
+ const Component = dynamic(() => import('./IdFrontImageField.client.js').then((mod) => mod.IdFrontImageField__client), {
6
+ ssr: false,
7
+ loading: () => (_jsx("div", { className: "border-border-primary bg-bg-primary flex aspect-[352/180] w-full shrink-0 items-center justify-center rounded-xl border", children: _jsx(Spinner02Icon, { className: "text-text-quinary size-8" }) })),
8
+ });
9
+ export function IdFrontImageField(props) {
10
+ return _jsx(Component, { ...props });
11
+ }
@@ -0,0 +1,6 @@
1
+ import type { UseIdFrontImageFieldReturn } from './useIdFrontImageField';
2
+ export declare const IdFrontImageFieldProvider: (props: {
3
+ value: UseIdFrontImageFieldReturn;
4
+ } & {
5
+ children?: import("react").ReactNode | undefined;
6
+ }) => React.ReactNode, useIdFrontImageFieldContext: () => UseIdFrontImageFieldReturn;
@@ -0,0 +1,2 @@
1
+ import { createContext } from '../../../../client/utils/createContext.js';
2
+ export const [IdFrontImageFieldProvider, useIdFrontImageFieldContext] = createContext();
@@ -0,0 +1 @@
1
+ export * from './IdFrontImageField';
@@ -0,0 +1 @@
1
+ export * from './IdFrontImageField.js';
@@ -0,0 +1,18 @@
1
+ export interface UseIdFrontImageFieldProps {
2
+ value?: File | null;
3
+ onChange?: (value: File | null) => void;
4
+ defaultValue?: File | null;
5
+ }
6
+ export interface UseIdFrontImageFieldReturn extends ReturnType<typeof useIdFrontImageField> {
7
+ }
8
+ export declare function useIdFrontImageField(props: UseIdFrontImageFieldProps): {
9
+ field: import("@ark-ui/react").UseFieldContext;
10
+ value: File | null;
11
+ valueAsUrl: string | null;
12
+ setValue: import("react").Dispatch<import("react").SetStateAction<File | null>>;
13
+ camera: import("../../../../client/hooks/useCamera").UseCameraReturn<never>;
14
+ disclosure: import("../../../../client/hooks/useDisclosure").UseDisclosureReturn;
15
+ inputRef: import("react").RefObject<HTMLInputElement | null>;
16
+ guideRef: import("react").RefObject<HTMLDivElement | null>;
17
+ maskRef: import("react").RefObject<HTMLDivElement | null>;
18
+ };
@@ -0,0 +1,88 @@
1
+ import { useFieldContext } from '@ark-ui/react';
2
+ import { useRef } from 'react';
3
+ import invariant from 'tiny-invariant';
4
+ import { useMediaQuery } from 'usehooks-ts';
5
+ import { useCamera } from '../../../../client/hooks/useCamera.js';
6
+ import { useControllableState } from '../../../../client/hooks/useControllableState.js';
7
+ import { useDisclosure } from '../../../../client/hooks/useDisclosure.js';
8
+ export function useIdFrontImageField(props) {
9
+ const field = useFieldContext();
10
+ const [value, setValue] = useControllableState({
11
+ value: props.value,
12
+ defaultValue: props.defaultValue ?? null,
13
+ onChange: props.onChange,
14
+ });
15
+ const valueAsUrl = value ? URL.createObjectURL(value) : null;
16
+ const inputRef = useRef(null);
17
+ const maskRef = useRef(null);
18
+ const guideRef = useRef(null);
19
+ const desktop = useMediaQuery('(min-width: 1024px)');
20
+ const camera = useCamera({
21
+ video: {
22
+ facingMode: desktop ? 'user' : 'environment',
23
+ },
24
+ async transform(data) {
25
+ const guideRect = guideRef.current?.getBoundingClientRect();
26
+ const videoRect = data.video.getBoundingClientRect();
27
+ invariant(guideRect, "'guideRef.getBoundingClientRect()' fails");
28
+ const scaleX = data.image.width / videoRect.width;
29
+ const scaleY = data.image.height / videoRect.height;
30
+ const cropTop = (guideRect.top - videoRect.top) * scaleY;
31
+ const cropLeft = (guideRect.left - videoRect.left) * scaleX;
32
+ const cropWidth = guideRect.width * scaleX;
33
+ const cropHeight = guideRect.height * scaleY;
34
+ const targetWidth = 1200;
35
+ const targetHeight = 757;
36
+ const canvas = document.createElement('canvas');
37
+ const context = canvas.getContext('2d');
38
+ invariant(context, "'canvas.getContext' failed");
39
+ canvas.width = targetWidth;
40
+ canvas.height = targetHeight;
41
+ context.imageSmoothingEnabled = true;
42
+ context.imageSmoothingQuality = 'high';
43
+ context.filter = 'brightness(1.05) contrast(1.1) saturate(1.1)';
44
+ context.drawImage(data.image, cropLeft, cropTop, cropWidth, cropHeight, 0, 0, targetWidth, targetHeight);
45
+ const file = await new Promise((resolve) => canvas.toBlob((blob) => {
46
+ invariant(blob);
47
+ resolve(new File([blob], `front-image-${Date.now()}.jpeg`, {
48
+ type: 'image/jpeg',
49
+ endings: 'native',
50
+ lastModified: Date.now(),
51
+ }));
52
+ }, 'image/jpeg', 1.0));
53
+ const url = URL.createObjectURL(file);
54
+ const image = new Image();
55
+ image.src = url;
56
+ image.alt = '';
57
+ image.width = targetWidth;
58
+ image.height = targetHeight;
59
+ context.filter = 'brightness(1.05)';
60
+ return {
61
+ ok: true,
62
+ data: {
63
+ url,
64
+ file,
65
+ image,
66
+ },
67
+ };
68
+ },
69
+ });
70
+ const disclosure = useDisclosure({
71
+ onOpenChange(open) {
72
+ if (open) {
73
+ camera.open();
74
+ }
75
+ },
76
+ });
77
+ return {
78
+ field,
79
+ value,
80
+ valueAsUrl,
81
+ setValue,
82
+ camera,
83
+ disclosure,
84
+ inputRef,
85
+ guideRef,
86
+ maskRef,
87
+ };
88
+ }
@@ -0,0 +1,15 @@
1
+ import { type CSSProperties, type RefObject } from 'react';
2
+ import { type ValidateFileError } from '../../../../utils/validateFile';
3
+ import { type UseSelfieImageFieldProps } from './useSelfieImageField';
4
+ export interface SelfieImageFieldProps extends UseSelfieImageFieldProps {
5
+ ref?: RefObject<HTMLDivElement | null>;
6
+ id?: string;
7
+ style?: CSSProperties;
8
+ className?: string;
9
+ invalid?: boolean;
10
+ readOnly?: boolean;
11
+ disabled?: boolean;
12
+ required?: boolean;
13
+ onError?: (error: ValidateFileError<'FaceNotFoundError'>) => void;
14
+ }
15
+ export declare function SelfieImageField__client(props: SelfieImageFieldProps): import("react/jsx-runtime").JSX.Element;