@opexa/portal-components 0.0.970 → 0.0.972

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 (59) hide show
  1. package/dist/client/hooks/useVerifyMobileNumber.d.ts +3 -0
  2. package/dist/client/hooks/useVerifyMobileNumber.js +20 -0
  3. package/dist/components/DepositWithdrawal/Deposit/AurixPayPayMayaDeposit/AurixPayGrabPayDeposit.d.ts +1 -0
  4. package/dist/components/DepositWithdrawal/Deposit/AurixPayPayMayaDeposit/AurixPayGrabPayDeposit.js +241 -0
  5. package/dist/components/KYC/KYCReview.js +30 -4
  6. package/dist/components/Messages/MessagesPopup.js +3 -1
  7. package/dist/components/SingleSignOn/SingleSignOn.d.ts +4 -0
  8. package/dist/components/SingleSignOn/SingleSignOn.js +185 -0
  9. package/dist/components/SingleSignOn/index.d.ts +1 -0
  10. package/dist/components/SingleSignOn/index.js +1 -0
  11. package/dist/components/UpdateMobilePhoneNumber/UpdateMobilePhoneNumber.js +6 -2
  12. package/dist/components/shared/SelfieImageField/SelfieImageField.client.js +1 -1
  13. package/dist/components/shared/SelfieImageField/SelfieImageField.js +2 -7
  14. package/dist/components/shared/SelfieImageField/useSelfieImageField.d.ts +1 -0
  15. package/dist/components/shared/SelfieImageField/useSelfieImageField.js +44 -42
  16. package/dist/lib/components/UpdateMobilePhoneNumber/UpdateMobilePhoneNumber.d.ts +1 -0
  17. package/dist/lib/components/UpdateMobilePhoneNumber/UpdateMobilePhoneNumber.js +152 -0
  18. package/dist/lib/components/UpdateMobilePhoneNumber/index.d.ts +1 -0
  19. package/dist/lib/components/UpdateMobilePhoneNumber/index.js +1 -0
  20. package/dist/schemas/forgotPasswordSchema.d.ts +5 -5
  21. package/dist/ui/AlertDialog/AlertDialog.d.ts +187 -187
  22. package/dist/ui/AlertDialog/alertDialog.recipe.d.ts +17 -17
  23. package/dist/ui/Badge/Badge.d.ts +12 -12
  24. package/dist/ui/Badge/badge.anatomy.d.ts +1 -1
  25. package/dist/ui/Badge/badge.recipe.d.ts +3 -3
  26. package/dist/ui/Carousel/Carousel.d.ts +99 -99
  27. package/dist/ui/Carousel/carousel.recipe.d.ts +11 -11
  28. package/dist/ui/Checkbox/Checkbox.d.ts +23 -23
  29. package/dist/ui/Checkbox/checkbox.recipe.d.ts +3 -3
  30. package/dist/ui/Clipboard/Clipboard.d.ts +18 -18
  31. package/dist/ui/Clipboard/clipboard.recipe.d.ts +3 -3
  32. package/dist/ui/Collapsible/Collapsible.d.ts +20 -20
  33. package/dist/ui/Collapsible/collapsible.recipe.d.ts +5 -5
  34. package/dist/ui/Combobox/Combobox.d.ts +42 -42
  35. package/dist/ui/Combobox/combobox.recipe.d.ts +3 -3
  36. package/dist/ui/DatePicker/DatePicker.d.ts +72 -72
  37. package/dist/ui/DatePicker/datePicker.recipe.d.ts +3 -3
  38. package/dist/ui/Dialog/Dialog.d.ts +33 -33
  39. package/dist/ui/Dialog/dialog.recipe.d.ts +3 -3
  40. package/dist/ui/Drawer/Drawer.d.ts +33 -33
  41. package/dist/ui/Drawer/drawer.recipe.d.ts +3 -3
  42. package/dist/ui/Menu/Menu.d.ts +360 -360
  43. package/dist/ui/Menu/menu.recipe.d.ts +20 -20
  44. package/dist/ui/Popover/Popover.d.ts +154 -154
  45. package/dist/ui/Popover/popover.recipe.d.ts +14 -14
  46. package/dist/ui/Progress/Progress.d.ts +27 -27
  47. package/dist/ui/Progress/progress.recipe.d.ts +3 -3
  48. package/dist/ui/SegmentGroup/SegmentGroup.d.ts +18 -18
  49. package/dist/ui/SegmentGroup/segmentGroup.recipe.d.ts +3 -3
  50. package/dist/ui/Select/Select.d.ts +45 -45
  51. package/dist/ui/Select/select.recipe.d.ts +3 -3
  52. package/dist/ui/Table/Table.d.ts +21 -21
  53. package/dist/ui/Table/table.anatomy.d.ts +1 -1
  54. package/dist/ui/Table/table.recipe.d.ts +3 -3
  55. package/dist/ui/Tabs/Tabs.d.ts +15 -15
  56. package/dist/ui/Tabs/tabs.recipe.d.ts +3 -3
  57. package/dist/ui/Tooltip/Tooltip.d.ts +30 -30
  58. package/dist/ui/Tooltip/tooltip.recipe.d.ts +5 -5
  59. package/package.json +1 -1
@@ -114,6 +114,19 @@ export function useSelfieImageField(props) {
114
114
  },
115
115
  });
116
116
  const [faceFound, setFaceFound] = useState(false);
117
+ const [detectorReady, setDetectorReady] = useState(false);
118
+ // Preload detector when disclosure opens
119
+ useEffect(() => {
120
+ if (disclosure.open) {
121
+ setDetectorReady(false);
122
+ getFaceDetector()
123
+ .then(() => setDetectorReady(true))
124
+ .catch((e) => {
125
+ console.error('Failed to load face detector:', e);
126
+ setDetectorReady(false);
127
+ });
128
+ }
129
+ }, [disclosure.open]);
117
130
  // Reset faceFound when camera is reset or reopened
118
131
  // biome-ignore lint/correctness/useExhaustiveDependencies: Reset faceFound on state change
119
132
  useEffect(() => {
@@ -123,9 +136,14 @@ export function useSelfieImageField(props) {
123
136
  if (!camera.videoRef.current || !guideRef.current) {
124
137
  return setFaceFound(false);
125
138
  }
126
- setFaceFound(await validateFaceFromVideo(camera.videoRef.current, guideRef.current));
127
- }, disclosure.open && !camera.data && !camera.error && !camera.loading
128
- ? 300
139
+ const found = await validateFaceFromVideo(camera.videoRef.current, guideRef.current);
140
+ setFaceFound(found);
141
+ }, disclosure.open &&
142
+ detectorReady &&
143
+ !camera.data &&
144
+ !camera.error &&
145
+ !camera.loading
146
+ ? 100
129
147
  : null);
130
148
  return {
131
149
  field,
@@ -139,13 +157,13 @@ export function useSelfieImageField(props) {
139
157
  guideRef,
140
158
  maskRef,
141
159
  faceFound,
160
+ detectorReady,
142
161
  };
143
162
  }
144
- let __image_face_detector__ = null;
145
- let __video_face_detector__ = null;
163
+ let __face_detector__ = null;
146
164
  let __vision__ = null;
147
- let __image_face_detector_promise__ = null;
148
- let __video_face_detector_promise__ = null;
165
+ let __current_running_mode__ = 'IMAGE';
166
+ let __face_detector_promise__ = null;
149
167
  let __vision_promise__ = null;
150
168
  async function getVision() {
151
169
  if (__vision__)
@@ -165,12 +183,12 @@ async function getVision() {
165
183
  })();
166
184
  return __vision_promise__;
167
185
  }
168
- async function getImageFaceDetector() {
169
- if (__image_face_detector__)
170
- return __image_face_detector__;
171
- if (__image_face_detector_promise__)
172
- return __image_face_detector_promise__;
173
- __image_face_detector_promise__ = (async () => {
186
+ async function getFaceDetector() {
187
+ if (__face_detector__)
188
+ return __face_detector__;
189
+ if (__face_detector_promise__)
190
+ return __face_detector_promise__;
191
+ __face_detector_promise__ = (async () => {
174
192
  try {
175
193
  const vision = await getVision();
176
194
  const detector = await FaceDetector.createFromOptions(vision, {
@@ -181,44 +199,28 @@ async function getImageFaceDetector() {
181
199
  modelAssetPath: 'https://storage.googleapis.com/mediapipe-models/face_detector/blaze_face_short_range/float16/1/blaze_face_short_range.tflite',
182
200
  },
183
201
  });
184
- __image_face_detector__ = detector;
202
+ __face_detector__ = detector;
203
+ __current_running_mode__ = 'IMAGE';
185
204
  return detector;
186
205
  }
187
206
  catch (e) {
188
- __image_face_detector_promise__ = null;
207
+ __face_detector_promise__ = null;
189
208
  throw e;
190
209
  }
191
210
  })();
192
- return __image_face_detector_promise__;
211
+ return __face_detector_promise__;
193
212
  }
194
- async function getVideoFaceDetector() {
195
- if (__video_face_detector__)
196
- return __video_face_detector__;
197
- if (__video_face_detector_promise__)
198
- return __video_face_detector_promise__;
199
- __video_face_detector_promise__ = (async () => {
200
- try {
201
- const vision = await FilesetResolver.forVisionTasks('https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@0.10.0/wasm');
202
- const detector = await FaceDetector.createFromOptions(vision, {
203
- baseOptions: {
204
- modelAssetPath: 'https://storage.googleapis.com/mediapipe-models/face_detector/blaze_face_short_range/float16/1/blaze_face_short_range.tflite',
205
- delegate: 'GPU',
206
- },
207
- runningMode: 'VIDEO',
208
- });
209
- __video_face_detector__ = detector;
210
- return detector;
211
- }
212
- catch (e) {
213
- __video_face_detector_promise__ = null;
214
- throw e;
215
- }
216
- })();
217
- return __video_face_detector_promise__;
213
+ async function ensureRunningMode(mode) {
214
+ const detector = await getFaceDetector();
215
+ if (__current_running_mode__ !== mode) {
216
+ await detector.setOptions({ runningMode: mode });
217
+ __current_running_mode__ = mode;
218
+ }
219
+ return detector;
218
220
  }
219
221
  async function validateFaceFromImage(image) {
220
222
  try {
221
- const detector = await getImageFaceDetector();
223
+ const detector = await ensureRunningMode('IMAGE');
222
224
  const result = detector.detect(image);
223
225
  return result.detections.length > 0;
224
226
  }
@@ -231,7 +233,7 @@ async function validateFaceFromVideo(video, guide) {
231
233
  if (video.readyState < 2)
232
234
  return false;
233
235
  try {
234
- const detector = await getVideoFaceDetector();
236
+ const detector = await ensureRunningMode('VIDEO');
235
237
  const result = detector.detectForVideo(video, performance.now());
236
238
  const detection = result.detections.at(0);
237
239
  if (!detection)
@@ -0,0 +1 @@
1
+ export declare function UpdateMobilePhoneNumber(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,152 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { zodResolver } from '@hookform/resolvers/zod';
4
+ import Image from 'next/image';
5
+ import { useEffect, useRef, useState } from 'react';
6
+ import { Controller, useForm } from 'react-hook-form';
7
+ import z from 'zod';
8
+ import { useAccountQuery } from '../../client/hooks/useAccountQuery.js';
9
+ import { useCooldown } from '../../client/hooks/useCooldown.js';
10
+ import { useLocaleInfo } from '../../client/hooks/useLocaleInfo.js';
11
+ import { useMobileNumberParser } from '../../client/hooks/useMobileNumberParser.js';
12
+ import { useSendVerificationCodeMutation } from '../../client/hooks/useSendVerificationCodeMutation.js';
13
+ import { useUpdateMobileNumber } from '../../client/hooks/useUpdateMobileNumber.js';
14
+ import { toaster } from '../../client/utils/toaster.js';
15
+ import { ArrowLeftIcon } from '../../icons/ArrowLeftIcon.js';
16
+ import inplayLogo from '../../images/inplay-logo.png';
17
+ import lightBg from '../../images/light-bg.png';
18
+ import { Button } from '../../ui/Button/index.js';
19
+ import { Dialog } from '../../ui/Dialog/index.js';
20
+ import { Field } from '../../ui/Field/index.js';
21
+ import { PinInput } from '../../ui/PinInput/index.js';
22
+ import { Portal } from '../../ui/Portal/index.js';
23
+ export function UpdateMobilePhoneNumber() {
24
+ const accountQuery = useAccountQuery();
25
+ const account = accountQuery.data;
26
+ const isAccountLoading = accountQuery.isLoading;
27
+ const hasMobileNumber = !!account?.mobileNumber;
28
+ const [isDialogOpen, setIsDialogOpen] = useState(false);
29
+ // biome-ignore lint/correctness/useExhaustiveDependencies: We only want to open the dialog when the account data loads, not on every hasMobileNumber change
30
+ useEffect(() => {
31
+ if (!isAccountLoading && !!account && !hasMobileNumber) {
32
+ setIsDialogOpen(true);
33
+ }
34
+ else if (!isAccountLoading && !!account && hasMobileNumber) {
35
+ setIsDialogOpen(false);
36
+ }
37
+ }, [isAccountLoading, account?.mobileNumber]);
38
+ const [step, setStep] = useState(1);
39
+ const sendVerificationCodeMutation = useSendVerificationCodeMutation({
40
+ onSuccess: () => {
41
+ setStep(2);
42
+ cooldown.start();
43
+ },
44
+ onError: (err) => {
45
+ toaster.error({
46
+ title: 'Sign In Failed',
47
+ description: err.message,
48
+ });
49
+ },
50
+ });
51
+ const updateMobileNumberMutation = useUpdateMobileNumber({
52
+ onSuccess: async () => {
53
+ step1Form.reset();
54
+ step2Form.reset();
55
+ setStep(1);
56
+ toaster.success({
57
+ title: 'Verification Successful',
58
+ description: 'Your mobile number has been verified.',
59
+ });
60
+ setIsDialogOpen(false);
61
+ console.log('mobile number updated successfully');
62
+ },
63
+ onError: (err) => {
64
+ const errorMessage = err.message === 'Internal Server Error'
65
+ ? `mobile number ${mobileNumberParser.format(step1Form.getValues('mobileNumber'))} is not available`
66
+ : err.message;
67
+ toaster.error({
68
+ title: 'Sign In Failed',
69
+ description: errorMessage,
70
+ });
71
+ console.log('error updating mobile number');
72
+ },
73
+ });
74
+ const localeInfo = useLocaleInfo();
75
+ const mobileNumberParser = useMobileNumberParser();
76
+ const Step1Definition = z.object({
77
+ mobileNumber: z
78
+ .string()
79
+ .min(1, 'Mobile number is required')
80
+ .superRefine((v, ctx) => {
81
+ if (!mobileNumberParser.validate(v)) {
82
+ ctx.addIssue({
83
+ code: z.ZodIssueCode.custom,
84
+ message: 'Invalid mobile number',
85
+ });
86
+ }
87
+ }),
88
+ });
89
+ const Step2Definition = z.object({
90
+ verificationCode: z.array(z.string()).superRefine((val, ctx) => {
91
+ if (val.length !== 6 || val.some((v) => v.length !== 1)) {
92
+ ctx.addIssue({
93
+ code: z.ZodIssueCode.custom,
94
+ message: 'Please enter your 6-digit verification code.',
95
+ });
96
+ }
97
+ }),
98
+ });
99
+ const step1Form = useForm({
100
+ resolver: zodResolver(Step1Definition),
101
+ defaultValues: {
102
+ mobileNumber: '',
103
+ },
104
+ });
105
+ const step2Form = useForm({
106
+ resolver: zodResolver(Step2Definition),
107
+ defaultValues: {
108
+ verificationCode: Array.from({ length: 6 }).fill(''),
109
+ },
110
+ });
111
+ const cooldown = useCooldown({
112
+ max: 60,
113
+ duration: 1000 * 60,
114
+ });
115
+ const formRef = useRef(null);
116
+ return (_jsx(Dialog.Root, { open: isDialogOpen, lazyMount: true, unmountOnExit: true, closeOnEscape: false, closeOnInteractOutside: false, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, {}), _jsx(Dialog.Positioner, { className: "flex items-center", children: _jsxs(Dialog.Content, { className: "flex w-[375px] flex-col items-center space-y-4 rounded-xl bg-[#111827] p-6 text-center", style: {
117
+ backgroundImage: `url(${lightBg.src})`,
118
+ }, children: [_jsx(Image, { src: inplayLogo, alt: "inplay logo", width: 82, height: 34, className: "h-auto w-[82px]" }), _jsxs("div", { children: [step === 1 && (_jsxs(_Fragment, { children: [_jsxs("div", { className: "font-bold text-sm", children: ["Get ", _jsx("span", { className: "text-[#F05127]", children: "\u20B150 Bonus" }), " when you verify your account and play."] }), _jsxs("form", { className: "mt-3xl", onSubmit: step1Form.handleSubmit(async (data) => {
119
+ sendVerificationCodeMutation.mutateAsync({
120
+ channel: 'SMS',
121
+ recipient: mobileNumberParser.format(data.mobileNumber),
122
+ });
123
+ }), children: [_jsxs(Field.Root, { invalid: !!step1Form.formState.errors.mobileNumber, className: "text-left", children: [_jsx(Field.Label, { children: "Mobile Number" }), _jsxs("div", { className: "relative", children: [_jsx("div", { className: "-translate-y-1/2 absolute top-1/2 left-3.5 flex shrink-0 items-center gap-md", children: _jsx("span", { className: "text-text-placeholder", children: localeInfo.mobileNumber.areaCode }) }), _jsx(Field.Input, { style: {
124
+ paddingLeft: `calc(1.25rem + ${localeInfo.mobileNumber.areaCode.length}ch)`,
125
+ }, ...step1Form.register('mobileNumber') })] }), _jsx(Field.ErrorText, { children: step1Form.formState.errors.mobileNumber?.message })] }), _jsx(Button, { type: "submit", className: "mt-3xl", disabled: step1Form.formState.isSubmitting, children: "Send Code" })] })] })), step === 2 && (_jsxs(_Fragment, { children: [_jsx("h2", { className: "mt-xl text-center font-semibold text-lg", children: "Check your Phone" }), _jsxs("p", { className: "mt-xs text-center text-sm text-text-secondary-700", children: ["We\u2019ve sent a verification code to your mobile number", ' ', _jsx("span", { className: "font-semibold text-[#F05127]", children: mobileNumberParser.format(step1Form.getValues('mobileNumber')) }), ' ', "via text"] }), _jsxs("form", { ref: formRef, className: "mt-5", onSubmit: step2Form.handleSubmit(async ({ verificationCode }) => {
126
+ updateMobileNumberMutation.mutateAsync({
127
+ mobileNumber: mobileNumberParser.format(step1Form.getValues('mobileNumber')),
128
+ verificationCode: verificationCode.join(''),
129
+ });
130
+ }), children: [_jsx(Controller, { name: "verificationCode", control: step2Form.control, render: (o) => (_jsxs(Field.Root, { invalid: o.fieldState.invalid, children: [_jsxs(PinInput.Root, { placeholder: "0", onKeyDown: (e) => {
131
+ if (e.key === 'Backspace') {
132
+ step2Form.reset();
133
+ }
134
+ }, value: o.field.value, onValueChange: (details) => {
135
+ o.field.onChange(details.value);
136
+ o.field.onBlur();
137
+ }, otp: true, onValueComplete: () => {
138
+ formRef.current?.requestSubmit();
139
+ }, blurOnComplete: true, readOnly: step2Form.formState.isSubmitting, type: "numeric", children: [_jsxs(PinInput.Control, { className: "grid-cols-[1fr_1fr_1fr_auto_1fr_1fr_1fr] items-center gap-md", children: [_jsx(PinInput.Input, { index: 0 }), _jsx(PinInput.Input, { index: 1 }), _jsx(PinInput.Input, { index: 2 }), _jsx("span", { className: "font-medium text-2xl text-text-placeholder-subtle", children: "\u2013" }), _jsx(PinInput.Input, { index: 3 }), _jsx(PinInput.Input, { index: 4 }), _jsx(PinInput.Input, { index: 5 })] }), _jsx(PinInput.HiddenInput, {})] }), _jsx(Field.ErrorText, { children: o.fieldState.error?.message })] })) }), _jsx(Button, { type: "submit", className: "mt-4xl", disabled: step2Form.formState.isSubmitting, children: "Verify" }), _jsxs("div", { className: "mt-4 flex w-full items-center justify-center gap-xs text-xs", children: [_jsx("span", { className: "text-[#9CA3AF]", children: "Didn't receive the code?" }), _jsx("button", { type: "button", className: "font-semibold text-[#C084FC]", disabled: cooldown.cooling, onClick: async () => {
140
+ await sendVerificationCodeMutation.mutateAsync({
141
+ channel: 'SMS',
142
+ recipient: mobileNumberParser.format(step1Form.getValues('mobileNumber')),
143
+ });
144
+ cooldown.start();
145
+ }, children: cooldown.cooling
146
+ ? `Resend in ${cooldown.countdown}s`
147
+ : 'Resend' })] }), _jsx("button", { type: "button", className: "absolute top-0 left-6 mx-auto mt-3xl flex h-8 w-8 items-center gap-1 rounded-full bg-[#1f2638] font-semibold text-sm text-text-tertiary-600", onClick: () => {
148
+ setStep(1);
149
+ step2Form.reset();
150
+ cooldown.stop();
151
+ }, children: _jsx(ArrowLeftIcon, { className: "mx-auto size-5" }) })] })] }))] })] }) })] }) }));
152
+ }
@@ -0,0 +1 @@
1
+ export * from './UpdateMobilePhoneNumber';
@@ -0,0 +1 @@
1
+ export * from './UpdateMobilePhoneNumber.js';
@@ -8,25 +8,25 @@ export declare const createForgotPasswordSchema: (mobileNumberParser: MobileNumb
8
8
  mobileNumber: z.ZodEffects<z.ZodString, string, string>;
9
9
  verificationCode: z.ZodEffects<z.ZodString, string, string>;
10
10
  }, "strip", z.ZodTypeAny, {
11
- mobileNumber: string;
12
- verificationCode: string;
13
11
  password: string;
14
12
  confirmPassword: string;
15
- }, {
16
13
  mobileNumber: string;
17
14
  verificationCode: string;
15
+ }, {
18
16
  password: string;
19
17
  confirmPassword: string;
20
- }>, {
21
18
  mobileNumber: string;
22
19
  verificationCode: string;
20
+ }>, {
23
21
  password: string;
24
22
  confirmPassword: string;
25
- }, {
26
23
  mobileNumber: string;
27
24
  verificationCode: string;
25
+ }, {
28
26
  password: string;
29
27
  confirmPassword: string;
28
+ mobileNumber: string;
29
+ verificationCode: string;
30
30
  }>;
31
31
  export type ForgotPasswordSchema = z.infer<ReturnType<typeof createForgotPasswordSchema>>;
32
32
  export {};