@opexa/portal-components 0.1.28 → 0.1.30

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 (28) hide show
  1. package/dist/components/Account/Account.lazy.js +2 -11
  2. package/dist/components/Disclaimer/DisclaimerV1.js +2 -0
  3. package/dist/components/Disclaimer/DisclaimerV2.js +5 -14
  4. package/dist/components/Disclaimer/DisclaimerV3.js +3 -2
  5. package/dist/components/Disclaimer/useDisclaimer.js +19 -12
  6. package/dist/components/KYC/KYCDefault/PersonalInformation.js +3 -12
  7. package/dist/components/KYC/KYCNonPagCor/PersonalInformation.js +2 -11
  8. package/dist/components/KYC/KYCReminder.lazy.js +2 -12
  9. package/dist/components/Onboarding/OnboardingV1.lazy.js +2 -1
  10. package/dist/components/RegisterBiometrics/RegisterBiometrics.js +2 -1
  11. package/dist/components/ResponsibleGaming/ResponsibleGaming.lazy.js +2 -1
  12. package/dist/components/ResponsibleGaming/ResponsibleGamingV2.lazy.js +2 -1
  13. package/dist/components/ResponsibleGaming/ResponsibleGamingV3.lazy.js +2 -1
  14. package/dist/components/SignIn/MobileNumberSignIn.js +2 -2
  15. package/dist/components/SignIn/MobileNumberSignInternational.js +2 -1
  16. package/dist/components/SignIn/NameAndPasswordSignIn.js +4 -4
  17. package/dist/components/SignIn/SignInTrigger.js +2 -1
  18. package/dist/components/SignUp/SignUpLongForm/SignUpLongForm.js +2 -1
  19. package/dist/components/TermsAndConditions/TermsAndConditions.lazy.js +2 -1
  20. package/dist/components/TermsOfUse/TermsOfUse.lazy.js +2 -1
  21. package/dist/components/TermsOfUse/TermsOfUseV2.lazy.js +2 -1
  22. package/dist/components/TermsOfUse/TermsOfUseV3.lazy.js +2 -1
  23. package/dist/components/UpdateMobilePhoneNumber/hooks/useLogout.js +2 -12
  24. package/dist/utils/clear-local-storage-on-logout.d.ts +2 -0
  25. package/dist/utils/clear-local-storage-on-logout.js +17 -0
  26. package/dist/utils/disclaimer-cooldown.d.ts +4 -0
  27. package/dist/utils/disclaimer-cooldown.js +32 -0
  28. package/package.json +1 -1
@@ -17,7 +17,7 @@ import { useProfileCompletionQuery } from '../../client/hooks/useProfileCompleti
17
17
  import { useSignOutMutation } from '../../client/hooks/useSignOutMutation.js';
18
18
  import { useUnreadMessagesCountQuery } from '../../client/hooks/useUnreadMessagesCountQuery.js';
19
19
  import { getSession } from '../../client/services/getSession.js';
20
- import { BIOMETRIC_STORAGE_KEY } from '../../client/utils/biometric.js';
20
+ import { clearLocalStorageOnLogout } from '../../utils/clear-local-storage-on-logout.js';
21
21
  import { AlertCircleIcon } from '../../icons/AlertCircleIcon.js';
22
22
  import { Bell01Icon } from '../../icons/Bell01Icon.js';
23
23
  import { ChevronRightIcon } from '../../icons/ChevronRightIcon.js';
@@ -124,16 +124,7 @@ function Links({ router, classNames, }) {
124
124
  })));
125
125
  const signOutMutation = useSignOutMutation({
126
126
  onSuccess: async () => {
127
- const keepLocal = new Set([BIOMETRIC_STORAGE_KEY]);
128
- for (let i = 0; i < localStorage.length;) {
129
- const key = localStorage.key(i);
130
- if (key && !keepLocal.has(key)) {
131
- localStorage.removeItem(key);
132
- }
133
- else {
134
- i++;
135
- }
136
- }
127
+ clearLocalStorageOnLogout();
137
128
  const keepSession = new Set(['accessGranted']);
138
129
  for (let i = 0; i < sessionStorage.length;) {
139
130
  const key = sessionStorage.key(i);
@@ -7,6 +7,7 @@ import Link from 'next/link';
7
7
  import { useEffect, useRef, useState } from 'react';
8
8
  import { useShallow } from 'zustand/shallow';
9
9
  import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
10
+ import { setDisclaimerAccepted } from '../../utils/disclaimer-cooldown.js';
10
11
  import { AlertCircleIcon } from '../../icons/AlertCircleIcon.js';
11
12
  import { CheckIcon } from '../../icons/CheckIcon.js';
12
13
  import pagcorLogo from '../../images/pagcor.png';
@@ -50,6 +51,7 @@ export function DisclaimerV1(props) {
50
51
  // Reset terms and responsible gaming acceptance states
51
52
  // so users must re-accept in SignIn forms
52
53
  globalStore.termsAndConditions.setAccepted(false);
54
+ setDisclaimerAccepted();
53
55
  disclaimer.close();
54
56
  }, disabled: !checked, "data-testid": "disclaimer-v1-accept-btn", children: "Accept" }), _jsx(Button, { variant: "outline", type: "button", className: "mt-lg", "data-testid": "disclaimer-v1-exit-btn", onClick: () => {
55
57
  if (Capacitor.isNativePlatform()) {
@@ -11,8 +11,9 @@ import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
11
11
  import { useSessionQuery } from '../../client/hooks/useSessionQuery.js';
12
12
  import { useSignOutMutation } from '../../client/hooks/useSignOutMutation.js';
13
13
  import { getSession } from '../../client/services/getSession.js';
14
- import { BIOMETRIC_STORAGE_KEY } from '../../client/utils/biometric.js';
15
- import { DISCLAIMER_ACCEPTED_KEY, TERMS_OF_USE_PENDING_STORAGE_KEY, } from '../../constants/index.js';
14
+ import { TERMS_OF_USE_PENDING_STORAGE_KEY } from '../../constants/index.js';
15
+ import { clearLocalStorageOnLogout } from '../../utils/clear-local-storage-on-logout.js';
16
+ import { setDisclaimerAccepted } from '../../utils/disclaimer-cooldown.js';
16
17
  import { AlertCircleIcon } from '../../icons/AlertCircleIcon.js';
17
18
  import { CheckIcon } from '../../icons/CheckIcon.js';
18
19
  import pagcorLogo from '../../images/pagcor2.png';
@@ -56,17 +57,7 @@ export function DisclaimerV2(props) {
56
57
  ]);
57
58
  const signOutMutation = useSignOutMutation({
58
59
  async onSuccess() {
59
- // Clear everything except the 'biometric' entry
60
- const keep = new Set([BIOMETRIC_STORAGE_KEY]);
61
- for (let i = 0; i < localStorage.length;) {
62
- const key = localStorage.key(i);
63
- if (key && !keep.has(key)) {
64
- localStorage.removeItem(key);
65
- }
66
- else {
67
- i++;
68
- }
69
- }
60
+ clearLocalStorageOnLogout();
70
61
  sessionStorage.clear();
71
62
  },
72
63
  });
@@ -115,10 +106,10 @@ export function DisclaimerV2(props) {
115
106
  // so users must re-accept in SignIn forms
116
107
  globalStore.termsAndConditions.setAccepted(false);
117
108
  globalStore.responsibleGaming.setAccepted(false);
109
+ setDisclaimerAccepted();
118
110
  disclaimer.close();
119
111
  if (isAuthenticated) {
120
112
  sessionStorage.setItem(TERMS_OF_USE_PENDING_STORAGE_KEY, 'true');
121
- sessionStorage.setItem(DISCLAIMER_ACCEPTED_KEY, 'true');
122
113
  globalStore.termsOfUse.setOpen(true);
123
114
  return;
124
115
  }
@@ -9,7 +9,7 @@ import { useShallow } from 'zustand/shallow';
9
9
  import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
10
10
  import { useSessionQuery } from '../../client/hooks/useSessionQuery.js';
11
11
  import { useSignOutMutation } from '../../client/hooks/useSignOutMutation.js';
12
- import { DISCLAIMER_ACCEPTED_KEY, TERMS_OF_USE_PENDING_STORAGE_KEY, } from '../../constants/index.js';
12
+ import { TERMS_OF_USE_PENDING_STORAGE_KEY, } from '../../constants/index.js';
13
13
  import { AlertCircleIcon } from '../../icons/AlertCircleIcon.js';
14
14
  import { CheckIcon } from '../../icons/CheckIcon.js';
15
15
  import pagcorLogo from '../../images/pagcor2.png';
@@ -18,6 +18,7 @@ import { Button } from '../../ui/Button/index.js';
18
18
  import { Checkbox } from '../../ui/Checkbox/index.js';
19
19
  import { Dialog } from '../../ui/Dialog/index.js';
20
20
  import { Portal } from '../../ui/Portal/index.js';
21
+ import { setDisclaimerAccepted } from '../../utils/disclaimer-cooldown.js';
21
22
  import { useDisclaimer } from './useDisclaimer.js';
22
23
  export function DisclaimerV3(props) {
23
24
  const disclaimer = useDisclaimer({
@@ -83,10 +84,10 @@ export function DisclaimerV3(props) {
83
84
  // so users must re-accept in SignIn forms
84
85
  globalStore.termsAndConditions.setAccepted(false);
85
86
  globalStore.responsibleGaming.setAccepted(false);
87
+ setDisclaimerAccepted();
86
88
  disclaimer.close();
87
89
  if (isAuthenticated) {
88
90
  sessionStorage.setItem(TERMS_OF_USE_PENDING_STORAGE_KEY, 'true');
89
- sessionStorage.setItem(DISCLAIMER_ACCEPTED_KEY, 'true');
90
91
  globalStore.termsOfUse.setOpen(true);
91
92
  return;
92
93
  }
@@ -3,34 +3,41 @@ import { useTimeout } from 'usehooks-ts';
3
3
  import { useShallow } from 'zustand/shallow';
4
4
  import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
5
5
  import { useSessionQuery } from '../../client/hooks/useSessionQuery.js';
6
- import { DISCLAIMER_ACCEPTED_KEY } from '../../constants/index.js';
6
+ import { isDisclaimerCooldownActive } from '../../utils/disclaimer-cooldown.js';
7
7
  export function useDisclaimer({ showInLogin = false, } = {}) {
8
8
  'use no memo';
9
9
  const sessionQuery = useSessionQuery();
10
10
  const searchParams = useSearchParams();
11
11
  const pathname = usePathname();
12
- const disclaimerStore = useGlobalStore(useShallow((state) => state.disclaimer));
12
+ const store = useGlobalStore(useShallow((state) => ({
13
+ disclaimer: state.disclaimer,
14
+ termsOfUse: state.termsOfUse,
15
+ })));
13
16
  // Check if we're on an SSO route (like /login/[partnerId])
14
17
  const isSsoRoute = pathname?.startsWith('/login/') && pathname.includes('/');
15
18
  const shouldShowDisclaimer = searchParams.get('game-exit') !== 'true' && !isSsoRoute;
16
19
  const isAuthenticated = sessionQuery.data?.status === 'authenticated';
20
+ const isCooldownActive = isDisclaimerCooldownActive();
17
21
  // Auto-open logic
18
22
  useTimeout(() => {
19
- const isDisclaimerAccepted = sessionStorage.getItem(DISCLAIMER_ACCEPTED_KEY) === 'true';
20
- if (shouldShowDisclaimer &&
21
- (!isAuthenticated || showInLogin) &&
22
- !isDisclaimerAccepted) {
23
- disclaimerStore.setOpen(true);
23
+ if (!shouldShowDisclaimer || isCooldownActive) {
24
+ return;
25
+ }
26
+ if (!isAuthenticated) {
27
+ store.disclaimer.setOpen(true);
28
+ }
29
+ else if (showInLogin) {
30
+ store.termsOfUse.setOpen(true);
24
31
  }
25
32
  }, 0);
26
33
  return {
27
34
  open: sessionQuery.isLoading
28
35
  ? false
29
36
  : shouldShowDisclaimer &&
30
- (!isAuthenticated || // guest: always allowed
31
- (showInLogin && isAuthenticated)) && // logged-in: only if allowed
32
- disclaimerStore.open,
33
- setOpen: (v) => disclaimerStore.setOpen(v),
34
- close: () => disclaimerStore.setOpen(false),
37
+ !isAuthenticated &&
38
+ !isCooldownActive &&
39
+ store.disclaimer.open,
40
+ setOpen: (v) => store.disclaimer.setOpen(v),
41
+ close: () => store.disclaimer.setOpen(false),
35
42
  };
36
43
  }
@@ -16,7 +16,7 @@ import { useMemberVerificationQuery } from '../../../client/hooks/useMemberVerif
16
16
  import { useSignOutMutation } from '../../../client/hooks/useSignOutMutation.js';
17
17
  import { useUpdateMemberVerificationMutation } from '../../../client/hooks/useUpdateMemberVerificationMutation.js';
18
18
  import { getSession } from '../../../client/services/getSession.js';
19
- import { BIOMETRIC_STORAGE_KEY } from '../../../client/utils/biometric.js';
19
+ import { clearLocalStorageOnLogout } from '../../../utils/clear-local-storage-on-logout.js';
20
20
  import { toaster } from '../../../client/utils/toaster.js';
21
21
  import { CheckIcon } from '../../../icons/CheckIcon.js';
22
22
  import { ChevronDownIcon } from '../../../icons/ChevronDownIcon.js';
@@ -122,16 +122,7 @@ export function PersonalInformation() {
122
122
  const router = useRouter();
123
123
  const signOutMutation = useSignOutMutation({
124
124
  async onSuccess() {
125
- const keep = new Set([BIOMETRIC_STORAGE_KEY]);
126
- for (let i = 0; i < localStorage.length;) {
127
- const key = localStorage.key(i);
128
- if (key && !keep.has(key)) {
129
- localStorage.removeItem(key);
130
- }
131
- else {
132
- i++;
133
- }
134
- }
125
+ clearLocalStorageOnLogout();
135
126
  sessionStorage.clear();
136
127
  router.replace('/');
137
128
  },
@@ -169,7 +160,7 @@ export function PersonalInformation() {
169
160
  globalStore.kycAccountVerificationRequired.setOpen(false);
170
161
  globalStore.kycReminder.setOpen(true);
171
162
  if (globalStore.firstTimeSignUp) {
172
- globalStore.disclaimer.setOpen(true);
163
+ // globalStore.disclaimer.setOpen(true);
173
164
  globalStore.setFirstTimeSignUp(false);
174
165
  }
175
166
  toaster.success({
@@ -17,7 +17,7 @@ import { useSignOutMutation } from '../../../client/hooks/useSignOutMutation.js'
17
17
  import { useUpdateAccountMutation } from '../../../client/hooks/useUpdateAccountMutation.js';
18
18
  import { useUpdateMemberVerificationMutation } from '../../../client/hooks/useUpdateMemberVerificationMutation.js';
19
19
  import { getSession } from '../../../client/services/getSession.js';
20
- import { BIOMETRIC_STORAGE_KEY } from '../../../client/utils/biometric.js';
20
+ import { clearLocalStorageOnLogout } from '../../../utils/clear-local-storage-on-logout.js';
21
21
  import { toaster } from '../../../client/utils/toaster.js';
22
22
  import { ObjectType } from '../../../services/ObjectType.js';
23
23
  import { unregisterFCMDevice } from '../../../services/trigger.js';
@@ -102,16 +102,7 @@ export function PersonalInformation() {
102
102
  });
103
103
  const signOutMutation = useSignOutMutation({
104
104
  async onSuccess() {
105
- const keep = new Set([BIOMETRIC_STORAGE_KEY]);
106
- for (let i = 0; i < localStorage.length;) {
107
- const key = localStorage.key(i);
108
- if (key && !keep.has(key)) {
109
- localStorage.removeItem(key);
110
- }
111
- else {
112
- i++;
113
- }
114
- }
105
+ clearLocalStorageOnLogout();
115
106
  sessionStorage.clear();
116
107
  router.replace('/');
117
108
  },
@@ -11,7 +11,7 @@ import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
11
11
  import { useSessionQuery } from '../../client/hooks/useSessionQuery.js';
12
12
  import { useSignOutMutation } from '../../client/hooks/useSignOutMutation.js';
13
13
  import { getSession } from '../../client/services/getSession.js';
14
- import { BIOMETRIC_STORAGE_KEY } from '../../client/utils/biometric.js';
14
+ import { clearLocalStorageOnLogout } from '../../utils/clear-local-storage-on-logout.js';
15
15
  import { FileCheck02Icon } from '../../icons/FileCheck02Icon.js';
16
16
  import { XIcon } from '../../icons/XIcon.js';
17
17
  import pagcorLogo from '../../images/pagcor.png';
@@ -36,17 +36,7 @@ export function KYCReminder({ enablePendingKycReminder = false, ...props }) {
36
36
  })));
37
37
  const signOutMutation = useSignOutMutation({
38
38
  async onSuccess() {
39
- // Clear everything except the 'biometric' entry
40
- const keep = new Set([BIOMETRIC_STORAGE_KEY]);
41
- for (let i = 0; i < localStorage.length;) {
42
- const key = localStorage.key(i);
43
- if (key && !keep.has(key)) {
44
- localStorage.removeItem(key);
45
- }
46
- else {
47
- i++;
48
- }
49
- }
39
+ clearLocalStorageOnLogout();
50
40
  sessionStorage.clear();
51
41
  router.replace('/');
52
42
  },
@@ -10,6 +10,7 @@ import secondStepBackground from '../../images/second-step-background.png';
10
10
  import thirdStepBackground from '../../images/third-step-background.png';
11
11
  import { Dialog } from '../../ui/Dialog/index.js';
12
12
  import { Portal } from '../../ui/Portal/index.js';
13
+ import { openDisclaimerIfAllowed } from '../../utils/disclaimer-cooldown.js';
13
14
  const AnimatedHeader = ({ text }) => {
14
15
  if (text === '88PLAY') {
15
16
  return (_jsx("div", { className: "relative", children: _jsxs("h1", { className: "venus-rising flex items-center font-bold text-4xl drop-shadow-lg", children: [_jsx("span", { className: "text-transparent", style: {
@@ -120,7 +121,7 @@ export function Onboarding() {
120
121
  globalStore.signUp.setOpen(true);
121
122
  }
122
123
  if (globalStore.onboarding.next === 'DISCLAIMER') {
123
- globalStore.disclaimer.setOpen(true);
124
+ openDisclaimerIfAllowed(globalStore.disclaimer.setOpen);
124
125
  }
125
126
  globalStore.onboarding.setNext(null);
126
127
  }, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "z-popover" }), _jsx(Dialog.Positioner, { className: "z-popover", children: _jsx(Dialog.Content, { className: twMerge('flex h-full w-full flex-col items-start overflow-y-auto lg:mx-auto lg:h-auto lg:max-h-[80vh] lg:w-[400px]', 'scrollbar:h-2 scrollbar:w-2 scrollbar-thumb:rounded-full scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-transparent'), children: _jsx(OnboardingCarousel, {}) }) })] }) }));
@@ -13,6 +13,7 @@ import { createSingleUseToken } from '../../services/auth.js';
13
13
  import { Button } from '../../ui/Button/index.js';
14
14
  import { Dialog } from '../../ui/Dialog/index.js';
15
15
  import { Portal } from '../../ui/Portal/index.js';
16
+ import { openDisclaimerIfAllowed } from '../../utils/disclaimer-cooldown.js';
16
17
  import { getQueryClient } from '../../utils/getQueryClient.js';
17
18
  import { getSessionQueryKey } from '../../utils/queryKeys.js';
18
19
  export function RegisterBiometrics() {
@@ -91,7 +92,7 @@ export function RegisterBiometrics() {
91
92
  description: 'Biometric setup successful',
92
93
  });
93
94
  registerBiometricStore.setOpen(false);
94
- kycModals.disclaimer.setOpen(true);
95
+ openDisclaimerIfAllowed(kycModals.disclaimer.setOpen);
95
96
  }, className: "text-sm", children: "Sure" }), _jsx(Button, { className: "border-border-dark text-sm text-text-primary-900", variant: "outline", onClick: () => {
96
97
  registerBiometricStore.setOpen(false);
97
98
  }, children: "Not now" })] })] }) }) }) }));
@@ -8,6 +8,7 @@ import responsibleGamingLogo from '../../images/responsible-gaming.png';
8
8
  import { Button } from '../../ui/Button/index.js';
9
9
  import { Dialog } from '../../ui/Dialog/index.js';
10
10
  import { Portal } from '../../ui/Portal/index.js';
11
+ import { openDisclaimerIfAllowed } from '../../utils/disclaimer-cooldown.js';
11
12
  export function ResponsibleGaming(props) {
12
13
  const globalStore = useGlobalStore(useShallow((ctx) => ({
13
14
  signIn: ctx.signIn,
@@ -30,7 +31,7 @@ export function ResponsibleGaming(props) {
30
31
  globalStore.signUp.setOpen(true);
31
32
  }
32
33
  if (globalStore.responsibleGaming.next === 'DISCLAIMER') {
33
- globalStore.disclaimer.setOpen(true);
34
+ openDisclaimerIfAllowed(globalStore.disclaimer.setOpen);
34
35
  }
35
36
  globalStore.responsibleGaming.setNext(null);
36
37
  }, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "z-popover" }), _jsx(Dialog.Positioner, { className: "z-popover", children: _jsxs(Dialog.Content, { className: twMerge('flex h-full w-full flex-col items-start overflow-y-auto p-3xl lg:mx-auto lg:h-auto lg:max-h-[80vh] lg:w-[400px]', 'scrollbar:h-2 scrollbar:w-2 scrollbar-thumb:rounded-full scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-transparent'), children: [_jsx(Image, { src: props.logo, alt: "", width: 200, height: 100, className: "mx-auto h-auto w-[7.5rem]", draggable: false }), _jsxs("div", { className: "w-full grow", children: [_jsx(Dialog.Title, { className: "mt-3xl text-center font-semibold text-brand-400 text-lg", children: "Responsible Gaming" }), _jsx(Dialog.Description, { className: "mt-xs text-sm leading-2xl", children: props.content }), _jsxs("div", { className: "mt-5 flex items-center justify-center gap-3xl", children: [_jsx(Image, { src: pagcorLogo, alt: "", height: 75, width: 88, className: "h-[5.5rem] w-auto shrink-0", draggable: false }), _jsx(Image, { src: props.responsibleGamingLogo ?? responsibleGamingLogo, alt: "", height: 62, width: 186, className: "h-[3.875rem] w-auto shrink-0", draggable: false })] })] }), _jsx(Dialog.Context, { children: (api) => (_jsx(Button, { type: "button", className: "mt-3 py-2.5", onClick: () => {
@@ -9,6 +9,7 @@ import { ScrollToTopIcon } from '../../icons/ScrollToTopIcon.js';
9
9
  import { Button } from '../../ui/Button/index.js';
10
10
  import { Dialog } from '../../ui/Dialog/index.js';
11
11
  import { Portal } from '../../ui/Portal/index.js';
12
+ import { openDisclaimerIfAllowed } from '../../utils/disclaimer-cooldown.js';
12
13
  export function ResponsibleGamingV2(props) {
13
14
  const [hasReachedBottom, setHasReachedBottom] = useState(false);
14
15
  const [isAtBottom, setIsAtBottom] = useState(false);
@@ -51,7 +52,7 @@ export function ResponsibleGamingV2(props) {
51
52
  globalStore.signUp.setOpen(true);
52
53
  }
53
54
  if (globalStore.responsibleGaming.next === 'DISCLAIMER') {
54
- globalStore.disclaimer.setOpen(true);
55
+ openDisclaimerIfAllowed(globalStore.disclaimer.setOpen);
55
56
  }
56
57
  globalStore.responsibleGaming.setNext(null);
57
58
  }, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "z-popover" }), _jsx(Dialog.Positioner, { className: "z-popover", children: _jsxs(Dialog.Content, { className: twMerge('relative flex h-full w-full flex-col items-start overflow-hidden p-4 sm:p-6 lg:mx-auto lg:max-h-[90vh] lg:w-[500px] lg:p-3xl', 'scrollbar:h-2 scrollbar:w-2 scrollbar-thumb:rounded-full scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-transparent'), children: [_jsx(Image, { src: props.logo, alt: "", width: 250, height: 150, className: "mx-auto h-auto w-20 sm:w-24 lg:w-[7.5rem]", draggable: false }), _jsxs("div", { className: "relative flex h-full w-full flex-col overflow-hidden", children: [_jsx(Dialog.Title, { className: "my-3 text-center font-semibold text-brand-400 sm:mt-6 sm:text-lg lg:my-xl lg:text-2xl", children: "Responsible Gaming Guidelines" }), _jsx("div", { className: "flex min-h-0 flex-1 flex-col rounded-md bg-bg-primary-alt px-2 py-2", children: _jsxs("div", { ref: scrollableContentRef, className: "mt-2 scrollbar:h-2 scrollbar:w-2 flex-1 overflow-y-auto scrollbar-thumb:rounded-full scrollbar-track:rounded-full bg-bg-primary-alt scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-bg-primary p-3 pr-4 sm:mt-xs sm:p-4", onScroll: (e) => {
@@ -10,6 +10,7 @@ import decorativebackground from '../../images/decorative-patern.png';
10
10
  import { Button } from '../../ui/Button/index.js';
11
11
  import { Dialog } from '../../ui/Dialog/index.js';
12
12
  import { Portal } from '../../ui/Portal/index.js';
13
+ import { openDisclaimerIfAllowed } from '../../utils/disclaimer-cooldown.js';
13
14
  export function ResponsibleGamingV3(props) {
14
15
  const [hasReachedBottom, setHasReachedBottom] = useState(false);
15
16
  const [isAtBottom, setIsAtBottom] = useState(false);
@@ -52,7 +53,7 @@ export function ResponsibleGamingV3(props) {
52
53
  globalStore.signUp.setOpen(true);
53
54
  }
54
55
  if (globalStore.responsibleGaming.next === 'DISCLAIMER') {
55
- globalStore.disclaimer.setOpen(true);
56
+ openDisclaimerIfAllowed(globalStore.disclaimer.setOpen);
56
57
  }
57
58
  globalStore.responsibleGaming.setNext(null);
58
59
  }, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "z-popover" }), _jsx(Dialog.Positioner, { className: "z-popover", children: _jsxs(Dialog.Content, { className: twMerge('relative flex h-full w-full flex-col items-start overflow-hidden p-4 sm:p-6 lg:mx-auto lg:max-h-[90vh] lg:w-[500px] lg:p-3xl', 'scrollbar:h-2 scrollbar:w-2 scrollbar-thumb:rounded-full scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-transparent'), children: [_jsx(Image, { src: decorativebackground, alt: "", width: 200, height: 200, className: "absolute top-0 left-0" }), _jsx(Image, { src: props.logo, alt: "", width: 250, height: 150, className: "h-auto w-20 sm:w-24 lg:w-[7.5rem]", draggable: false }), _jsxs("div", { className: "relative flex h-full w-full flex-col overflow-hidden", children: [_jsx(Dialog.Title, { className: "my-3 text-center font-semibold text-brand-400 sm:mt-6 sm:text-lg lg:my-xl lg:text-2xl", children: "Responsible Gaming Guidelines" }), _jsx("div", { className: "flex min-h-0 flex-1 flex-col rounded-md bg-bg-primary-alt px-2 py-2", children: _jsxs("div", { ref: scrollableContent, className: "mt-2 scrollbar:h-2 scrollbar:w-2 flex-1 overflow-y-auto scrollbar-thumb:rounded-full scrollbar-track:rounded-full bg-bg-primary-alt scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-bg-primary p-3 pr-4 sm:mt-xs sm:p-4", onScroll: (e) => {
@@ -85,7 +85,7 @@ export function MobileNumberSignIn() {
85
85
  globalStore.responsibleGamingReminder.setOpen(true);
86
86
  }
87
87
  if (signInProps.shouldShowDisclaimer) {
88
- globalStore.disclaimer.setOpen(true);
88
+ globalStore.termsOfUse.setOpen(true);
89
89
  }
90
90
  if (Capacitor.isNativePlatform()) {
91
91
  if (!hasSavedBiometry()) {
@@ -115,7 +115,7 @@ export function MobileNumberSignIn() {
115
115
  console.warn('Failed to updated biometric credentials');
116
116
  globalStore.signIn.setOpen(!globalStore.signIn.open);
117
117
  }
118
- globalStore.disclaimer.setOpen(true);
118
+ globalStore.termsOfUse.setOpen(true);
119
119
  }
120
120
  else {
121
121
  console.error('Failed to create token');
@@ -78,6 +78,7 @@ export function MobileNumberSignInInternational() {
78
78
  kyc: ctx.kyc,
79
79
  registerBiometrics: ctx.registerBiometrics,
80
80
  disclaimer: ctx.disclaimer,
81
+ termsOfUse: ctx.termsOfUse,
81
82
  })));
82
83
  const signInMutation = useSignInMutation({
83
84
  // versionSession intentionally omitted: only applies to NAME_AND_PASSWORD
@@ -112,7 +113,7 @@ export function MobileNumberSignInInternational() {
112
113
  globalStore.responsibleGamingReminder.setOpen(true);
113
114
  }
114
115
  if (signInProps.shouldShowDisclaimer) {
115
- globalStore.disclaimer.setOpen(true);
116
+ globalStore.termsOfUse.setOpen(true);
116
117
  }
117
118
  if (Capacitor.isNativePlatform()) {
118
119
  if (!hasSavedBiometry()) {
@@ -111,7 +111,7 @@ export function NameAndPasswordSignIn() {
111
111
  else {
112
112
  console.warn('Failed to update biometric credentials');
113
113
  }
114
- globalStore.disclaimer.setOpen(true);
114
+ globalStore.termsOfUse.setOpen(true);
115
115
  }
116
116
  else {
117
117
  console.error('Failed to create token');
@@ -128,7 +128,7 @@ export function NameAndPasswordSignIn() {
128
128
  globalStore.responsibleGamingReminder.setOpen(true);
129
129
  }
130
130
  if (signInProps.shouldShowDisclaimer) {
131
- globalStore.disclaimer.setOpen(true);
131
+ globalStore.termsOfUse.setOpen(true);
132
132
  }
133
133
  }
134
134
  },
@@ -174,7 +174,7 @@ export function NameAndPasswordSignIn() {
174
174
  globalStore.responsibleGamingReminder.setOpen(true);
175
175
  }
176
176
  if (signInProps.shouldShowDisclaimer) {
177
- globalStore.disclaimer.setOpen(true);
177
+ globalStore.termsOfUse.setOpen(true);
178
178
  }
179
179
  if (Capacitor.isNativePlatform()) {
180
180
  if (!hasSavedBiometry()) {
@@ -205,7 +205,7 @@ export function NameAndPasswordSignIn() {
205
205
  else {
206
206
  console.warn('Failed to update biometric credentials');
207
207
  }
208
- globalStore.disclaimer.setOpen(true);
208
+ globalStore.termsOfUse.setOpen(true);
209
209
  }
210
210
  else {
211
211
  // globalStore.signIn.setOpen(!globalStore.signIn.open);
@@ -18,6 +18,7 @@ export function SignInTrigger(props) {
18
18
  signIn: ctx.signIn,
19
19
  registerBiometrics: ctx.registerBiometrics,
20
20
  disclaimer: ctx.disclaimer,
21
+ termsOfUse: ctx.termsOfUse,
21
22
  })));
22
23
  return (_jsx(ark.button, { type: "button", "aria-label": "Sign in", "data-state": globalStore.signIn.open ? 'open' : 'closed', ...props, onClick: async (e) => {
23
24
  if (hasSavedBiometry()) {
@@ -87,7 +88,7 @@ export function SignInTrigger(props) {
87
88
  queryKey: getSessionQueryKey(),
88
89
  });
89
90
  if (Capacitor.isNativePlatform()) {
90
- globalStore.disclaimer.setOpen(true);
91
+ globalStore.termsOfUse.setOpen(true);
91
92
  }
92
93
  const r = await createSingleUseToken({
93
94
  headers: {
@@ -35,6 +35,7 @@ import { Field } from '../../../ui/Field/index.js';
35
35
  import { PinInput } from '../../../ui/PinInput/index.js';
36
36
  import { Select } from '../../../ui/Select/index.js';
37
37
  import { createPoll } from '../../../utils/createPoll.js';
38
+ import { openDisclaimerIfAllowed } from '../../../utils/disclaimer-cooldown.js';
38
39
  import { getQueryClient } from '../../../utils/getQueryClient.js';
39
40
  import { getMemberVerificationQueryKey } from '../../../utils/queryKeys.js';
40
41
  import DateOfBirthField from '../../DateOfBirthField.js';
@@ -196,7 +197,7 @@ export default function SignUpLongForm() {
196
197
  step1Form.reset();
197
198
  step2Form.reset();
198
199
  setStep(1);
199
- globalStore.disclaimer.setOpen(true);
200
+ openDisclaimerIfAllowed(globalStore.disclaimer.setOpen);
200
201
  toaster.success({
201
202
  title: 'Member Created!',
202
203
  description: 'Member created successfully',
@@ -8,6 +8,7 @@ import responsibleGamingLogo from '../../images/responsible-gaming.png';
8
8
  import { Button } from '../../ui/Button/index.js';
9
9
  import { Dialog } from '../../ui/Dialog/index.js';
10
10
  import { Portal } from '../../ui/Portal/index.js';
11
+ import { openDisclaimerIfAllowed } from '../../utils/disclaimer-cooldown.js';
11
12
  export function TermsAndConditions({ logo, siteName, content, ...props }) {
12
13
  const globalStore = useGlobalStore(useShallow((ctx) => ({
13
14
  signIn: ctx.signIn,
@@ -30,7 +31,7 @@ export function TermsAndConditions({ logo, siteName, content, ...props }) {
30
31
  globalStore.signUp.setOpen(true);
31
32
  }
32
33
  if (globalStore.termsAndConditions.next === 'DISCLAIMER') {
33
- globalStore.disclaimer.setOpen(true);
34
+ openDisclaimerIfAllowed(globalStore.disclaimer.setOpen);
34
35
  }
35
36
  globalStore.termsAndConditions.setNext(null);
36
37
  }, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "z-popover" }), _jsx(Dialog.Positioner, { className: "z-popover", children: _jsxs(Dialog.Content, { className: twMerge('flex h-full w-full flex-col items-start overflow-y-auto p-3xl lg:mx-auto lg:h-auto lg:max-h-[80vh] lg:w-[400px]', 'scrollbar:h-2 scrollbar:w-2 scrollbar-thumb:rounded-full scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-transparent'), children: [_jsx(Image, { src: logo, alt: "", width: 200, height: 100, className: "mx-auto h-auto w-[120px]", draggable: false }), _jsxs("div", { className: "w-full grow", children: [_jsxs(Dialog.Title, { className: "mt-3xl text-center font-semibold text-brand-400 text-lg", children: [siteName, " Terms of Use"] }), _jsx(Dialog.Description, { className: "mt-xs text-sm leading-2xl", children: content }), _jsxs("div", { className: "mt-5 flex items-center justify-center gap-3xl", children: [_jsx(Image, { src: pagcorLogo, alt: "", height: 75, width: 88, className: "h-[5.5rem] w-auto shrink-0", draggable: false }), _jsx(Image, { src: props.responsibleGamingLogo ?? responsibleGamingLogo, alt: "", height: 62, width: 186, className: "h-[3.875rem] w-auto shrink-0", draggable: false })] })] }), _jsx(Dialog.Context, { children: (api) => (_jsx(Button, { type: "button", className: "mt-3 py-2.5", onClick: () => {
@@ -9,6 +9,7 @@ import responsibleGamingLogo from '../../images/responsible-gaming.png';
9
9
  import { Button } from '../../ui/Button/index.js';
10
10
  import { Dialog } from '../../ui/Dialog/index.js';
11
11
  import { Portal } from '../../ui/Portal/index.js';
12
+ import { openDisclaimerIfAllowed } from '../../utils/disclaimer-cooldown.js';
12
13
  export function TermsOfUse({ logo, siteName, content, ...props }) {
13
14
  const globalStore = useGlobalStore(useShallow((ctx) => ({
14
15
  signIn: ctx.signIn,
@@ -32,7 +33,7 @@ export function TermsOfUse({ logo, siteName, content, ...props }) {
32
33
  globalStore.signUp.setOpen(true);
33
34
  }
34
35
  if (globalStore.termsOfUse.next === 'DISCLAIMER') {
35
- globalStore.disclaimer.setOpen(true);
36
+ openDisclaimerIfAllowed(globalStore.disclaimer.setOpen);
36
37
  }
37
38
  globalStore.termsOfUse.setNext(null);
38
39
  }, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "z-popover" }), _jsx(Dialog.Positioner, { className: "z-popover", children: _jsxs(Dialog.Content, { className: twMerge('flex h-full w-full flex-col items-start overflow-y-auto p-3xl lg:mx-auto lg:h-auto lg:max-h-[80vh] lg:w-[400px]', 'scrollbar:h-2 scrollbar:w-2 scrollbar-thumb:rounded-full scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-transparent'), children: [_jsx(Image, { src: logo, alt: "", width: 200, height: 100, className: "mx-auto h-auto w-[120px]", draggable: false }), _jsxs("div", { className: "w-full grow", children: [_jsxs(Dialog.Title, { className: "mt-3xl text-center font-semibold text-brand-400 text-lg", children: [siteName, " Terms of Use"] }), _jsx(Dialog.Description, { className: "mt-xs text-sm leading-2xl", children: content }), _jsxs("div", { className: "mt-5 flex items-center justify-center gap-3xl", children: [_jsx(Image, { src: pagcorLogo, alt: "", height: 75, width: 88, className: "h-[5.5rem] w-auto shrink-0", draggable: false }), _jsx(Image, { src: props.responsibleGamingLogo ?? responsibleGamingLogo, alt: "", height: 62, width: 186, className: "h-[3.875rem] w-auto shrink-0", draggable: false })] })] }), _jsx(Dialog.Context, { children: (api) => (_jsx(Button, { type: "button", className: "mt-3 py-2.5", onClick: () => {
@@ -10,6 +10,7 @@ import { ScrollToTopIcon } from '../../icons/ScrollToTopIcon.js';
10
10
  import { Button } from '../../ui/Button/index.js';
11
11
  import { Dialog } from '../../ui/Dialog/index.js';
12
12
  import { Portal } from '../../ui/Portal/index.js';
13
+ import { openDisclaimerIfAllowed } from '../../utils/disclaimer-cooldown.js';
13
14
  export function TermsOfUseV2({ logo, content }) {
14
15
  const scrollableContentRef = useRef(null);
15
16
  const [hasReachedBottom, setHasReachedBottom] = useState(false);
@@ -54,7 +55,7 @@ export function TermsOfUseV2({ logo, content }) {
54
55
  globalStore.signUp.setOpen(true);
55
56
  }
56
57
  if (globalStore.termsOfUse.next === 'DISCLAIMER') {
57
- globalStore.disclaimer.setOpen(true);
58
+ openDisclaimerIfAllowed(globalStore.disclaimer.setOpen);
58
59
  }
59
60
  globalStore.termsOfUse.setNext(null);
60
61
  }, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "!z-[calc(var(--z-dialog)+1)]" }), _jsx(Dialog.Positioner, { className: "!z-[calc(var(--z-dialog)+3)]", children: _jsxs(Dialog.Content, { className: twMerge('relative flex h-full w-full flex-col items-start overflow-hidden bg-bg-primary p-4 sm:p-6 lg:mx-auto lg:max-h-[90vh] lg:w-[500px] lg:p-3xl', 'scrollbar:h-2 scrollbar:w-2 scrollbar-thumb:rounded-full scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-transparent'), children: [_jsx(Image, { src: logo, alt: "", width: 250, height: 150, className: "mx-auto h-auto w-20 sm:w-24 lg:w-[7.5rem]", draggable: false }), _jsxs("div", { className: "relative flex h-full w-full flex-col overflow-hidden", children: [_jsx(Dialog.Title, { className: "my-3 text-center font-semibold text-brand-400 sm:mt-6 sm:text-lg lg:my-xl lg:text-2xl", children: "Terms of Use" }), _jsx("div", { className: "flex min-h-0 flex-1 flex-col rounded-md bg-bg-primary-alt px-2 py-2", children: _jsxs("div", { ref: scrollableContentRef, className: "mt-2 scrollbar:h-2 scrollbar:w-2 flex-1 overflow-y-auto scrollbar-thumb:rounded-full scrollbar-track:rounded-full bg-bg-primary-alt scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-bg-primary p-3 pr-4 sm:mt-xs sm:p-4", onScroll: (e) => {
@@ -11,6 +11,7 @@ import decorativebackground from '../../images/decorative-patern.png';
11
11
  import { Button } from '../../ui/Button/index.js';
12
12
  import { Dialog } from '../../ui/Dialog/index.js';
13
13
  import { Portal } from '../../ui/Portal/index.js';
14
+ import { openDisclaimerIfAllowed } from '../../utils/disclaimer-cooldown.js';
14
15
  export function TermsOfUseV3({ logo, content }) {
15
16
  const scrollableContentRef = useRef(null);
16
17
  const [hasReachedBottom, setHasReachedBottom] = useState(false);
@@ -54,7 +55,7 @@ export function TermsOfUseV3({ logo, content }) {
54
55
  globalStore.signUp.setOpen(true);
55
56
  }
56
57
  if (globalStore.termsOfUse.next === 'DISCLAIMER') {
57
- globalStore.disclaimer.setOpen(true);
58
+ openDisclaimerIfAllowed(globalStore.disclaimer.setOpen);
58
59
  }
59
60
  globalStore.termsOfUse.setNext(null);
60
61
  }, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, { className: "z-popover" }), _jsx(Dialog.Positioner, { className: "z-popover", children: _jsxs(Dialog.Content, { className: twMerge('relative flex h-full w-full flex-col items-start overflow-hidden bg-bg-primary p-4 sm:p-6 lg:mx-auto lg:max-h-[90vh] lg:w-[500px] lg:p-3xl', 'scrollbar:h-2 scrollbar:w-2 scrollbar-thumb:rounded-full scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-transparent'), children: [_jsx(Image, { src: decorativebackground, alt: "", width: 200, height: 200, className: "absolute top-safe-area-inset-top left-0" }), _jsx(Image, { src: logo, alt: "", width: 250, height: 150, className: "h-auto w-20 sm:w-24 lg:w-[7.5rem]", draggable: false }), _jsxs("div", { className: "relative flex h-full w-full flex-col overflow-hidden", children: [_jsx(Dialog.Title, { className: "my-3 text-center font-semibold text-brand-400 sm:mt-6 sm:text-lg lg:my-xl lg:text-2xl", children: "Terms of Use" }), _jsx("div", { className: "flex min-h-0 flex-1 flex-col rounded-md bg-bg-primary-alt px-2 py-2", children: _jsxs("div", { ref: scrollableContentRef, className: "mt-2 scrollbar:h-2 scrollbar:w-2 flex-1 overflow-y-auto scrollbar-thumb:rounded-full scrollbar-track:rounded-full bg-bg-primary-alt scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-bg-primary p-3 pr-4 sm:mt-xs sm:p-4", onScroll: (e) => {
@@ -4,7 +4,7 @@ import { useRouter } from 'next/navigation';
4
4
  import invariant from 'tiny-invariant';
5
5
  import { useSignOutMutation } from '../../../client/hooks/useSignOutMutation.js';
6
6
  import { getSession } from '../../../client/services/getSession.js';
7
- import { BIOMETRIC_STORAGE_KEY } from '../../../client/utils/biometric.js';
7
+ import { clearLocalStorageOnLogout } from '../../../utils/clear-local-storage-on-logout.js';
8
8
  import { unregisterFCMDevice } from '../../../services/trigger.js';
9
9
  import { getQueryClient } from '../../../utils/getQueryClient.js';
10
10
  import { getSessionQueryKey } from '../../../utils/queryKeys.js';
@@ -13,17 +13,7 @@ export function useLogout(options = {}) {
13
13
  const router = useRouter();
14
14
  const signOutMutation = useSignOutMutation({
15
15
  async onSuccess() {
16
- // Clear everything except the 'biometric' entry
17
- const keep = new Set([BIOMETRIC_STORAGE_KEY]);
18
- for (let i = 0; i < localStorage.length;) {
19
- const key = localStorage.key(i);
20
- if (key && !keep.has(key)) {
21
- localStorage.removeItem(key);
22
- }
23
- else {
24
- i++;
25
- }
26
- }
16
+ clearLocalStorageOnLogout();
27
17
  sessionStorage.clear();
28
18
  router.replace('/');
29
19
  },
@@ -0,0 +1,2 @@
1
+ export declare const LOGOUT_PRESERVED_LOCAL_STORAGE_KEYS: Set<string>;
2
+ export declare function clearLocalStorageOnLogout(): void;
@@ -0,0 +1,17 @@
1
+ import { BIOMETRIC_STORAGE_KEY } from '../client/utils/biometric.js';
2
+ import { DISCLAIMER_ACCEPTED_KEY } from '../constants/index.js';
3
+ export const LOGOUT_PRESERVED_LOCAL_STORAGE_KEYS = new Set([
4
+ BIOMETRIC_STORAGE_KEY,
5
+ DISCLAIMER_ACCEPTED_KEY,
6
+ ]);
7
+ export function clearLocalStorageOnLogout() {
8
+ for (let i = 0; i < localStorage.length;) {
9
+ const key = localStorage.key(i);
10
+ if (key && !LOGOUT_PRESERVED_LOCAL_STORAGE_KEYS.has(key)) {
11
+ localStorage.removeItem(key);
12
+ }
13
+ else {
14
+ i++;
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,4 @@
1
+ /** Whether the disclaimer was accepted within the last 24 hours. */
2
+ export declare function isDisclaimerCooldownActive(): boolean;
3
+ export declare function setDisclaimerAccepted(): void;
4
+ export declare function openDisclaimerIfAllowed(setOpen: (open: boolean) => void): void;
@@ -0,0 +1,32 @@
1
+ import { DISCLAIMER_ACCEPTED_KEY } from '../constants/index.js';
2
+ const DISCLAIMER_COOLDOWN_MS = 24 * 60 * 60 * 1000;
3
+ function getDisclaimerAcceptedAt() {
4
+ if (typeof window === 'undefined') {
5
+ return null;
6
+ }
7
+ const raw = localStorage.getItem(DISCLAIMER_ACCEPTED_KEY);
8
+ if (!raw) {
9
+ return null;
10
+ }
11
+ if (raw === 'true') {
12
+ return Date.now();
13
+ }
14
+ const acceptedAt = Number(raw);
15
+ return Number.isFinite(acceptedAt) ? acceptedAt : null;
16
+ }
17
+ /** Whether the disclaimer was accepted within the last 24 hours. */
18
+ export function isDisclaimerCooldownActive() {
19
+ const acceptedAt = getDisclaimerAcceptedAt();
20
+ if (acceptedAt === null) {
21
+ return false;
22
+ }
23
+ return Date.now() - acceptedAt < DISCLAIMER_COOLDOWN_MS;
24
+ }
25
+ export function setDisclaimerAccepted() {
26
+ localStorage.setItem(DISCLAIMER_ACCEPTED_KEY, String(Date.now()));
27
+ }
28
+ export function openDisclaimerIfAllowed(setOpen) {
29
+ if (!isDisclaimerCooldownActive()) {
30
+ setOpen(true);
31
+ }
32
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opexa/portal-components",
3
- "version": "0.1.28",
3
+ "version": "0.1.30",
4
4
  "exports": {
5
5
  "./ui/*": {
6
6
  "types": "./dist/ui/*/index.d.ts",