@opexa/portal-components 0.0.934 → 0.0.935

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.
@@ -10,7 +10,7 @@ import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
10
10
  import { AlertCircleIcon } from '../../icons/AlertCircleIcon.js';
11
11
  import { CheckIcon } from '../../icons/CheckIcon.js';
12
12
  import pagcorLogo from '../../images/pagcor2.png';
13
- import responsibleGamingLogo from '../../images/responsible-gaming.png';
13
+ import responsibleGamingLogo from '../../images/responsible-gaming-new.png';
14
14
  import { Button } from '../../ui/Button/index.js';
15
15
  import { Checkbox } from '../../ui/Checkbox/index.js';
16
16
  import { Dialog } from '../../ui/Dialog/index.js';
@@ -27,12 +27,12 @@ export function DisclaimerV3(props) {
27
27
  })));
28
28
  const checked = globalStore.termsOfUse.accepted && globalStore.responsibleGaming.accepted;
29
29
  const [showWarning, setShowWarning] = useState(false);
30
- return (_jsx(Dialog.Root, { open: disclaimer.open, lazyMount: true, unmountOnExit: true, closeOnEscape: false, closeOnInteractOutside: false, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, {}), _jsx(Dialog.Positioner, { children: _jsxs(Dialog.Content, { "aria-label": `${props.siteName} Player Disclaimer`, "aria-labelledby": "disclaimer-title", "aria-describedby": "disclaimer-description", className: "flex h-full scrollbar:h-2 scrollbar:w-2 w-full flex-col items-start gap-y-4 overflow-y-auto scrollbar-thumb:rounded-full scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-transparent p-3xl lg:mx-auto lg:h-auto lg:max-h-[90vh] lg:w-[400px] lg:rounded-xl", children: [_jsx("div", { className: "mx-auto h-auto max-w-[120px]", children: _jsx(Image, { src: props.logo, alt: `${props.siteName} logo`, width: 200, height: 100, className: "h-full w-full object-cover", draggable: false, unoptimized: true }) }), _jsx("div", { className: "w-full text-center font-semibold text-3xl", id: "disclaimer-title", children: "Notice" }), _jsx("div", { className: "text-sm", id: "disclaimer-description", children: "By entering this website, you acknowledge and confirm:" }), _jsx("div", { className: "w-full grow", children: _jsxs(Dialog.Description, { className: "space-y-4 text-sm", children: [_jsxs("ul", { className: "space-y-1.5 text-left", "aria-label": "Restricted persons list", children: [_jsxs("li", { className: "flex gap-4 text-text-placeholder", children: [_jsx(Circle, {}), "You are 21 years old and above."] }), _jsxs("li", { className: "flex gap-4 text-text-placeholder", children: [_jsx(Circle, {}), "You are not a government official, or employee connected directly with the operation of the Government or any of its agencies, member of the Armed Forces of the Philippines including the Army, Navy, Air Force, or the Philippine Nationa Police."] }), _jsxs("li", { className: "flex gap-4 text-text-placeholder", children: [_jsx(Circle, {}), "You are not included in the PAGCOR's National Database Restricted Persons (NDRP)."] }), _jsxs("li", { className: "flex gap-4 text-text-placeholder", children: [_jsx(Circle, {}), "Funds or credits in the account of player who is found ineligible to play shall mean forfeiture of said funds/credits in favor of the Government."] }), _jsxs(Checkbox.Root, { checked: checked, onCheckedChange: (e) => {
30
+ return (_jsx(Dialog.Root, { open: disclaimer.open, lazyMount: true, unmountOnExit: true, closeOnEscape: false, closeOnInteractOutside: false, children: _jsxs(Portal, { children: [_jsx(Dialog.Backdrop, {}), _jsx(Dialog.Positioner, { children: _jsxs(Dialog.Content, { "aria-label": `${props.siteName} Player Disclaimer`, "aria-labelledby": "disclaimer-title", "aria-describedby": "disclaimer-description", className: twMerge('flex h-full scrollbar:h-2 scrollbar:w-2 w-full flex-col items-start overflow-y-auto scrollbar-thumb:rounded-full scrollbar-thumb:bg-bg-quaternary scrollbar-track:bg-transparent p-3xl lg:mx-auto lg:h-auto lg:max-h-[85vh] lg:w-[500px] lg:rounded-xl'), children: [_jsx("div", { className: "mx-auto h-auto max-w-[120px]", children: _jsx(Image, { src: props.logo, alt: `${props.siteName} logo`, width: 200, height: 100, className: "h-full w-full object-cover", draggable: false, unoptimized: true }) }), _jsxs("div", { className: "my-4 grid w-full grid-cols-2 items-center justify-center gap-3xl", children: [_jsx(Image, { src: props.pagcorLogo ?? pagcorLogo, alt: "PAGCOR logo", height: 50, width: 186, className: "mx-auto h-[43px] w-auto shrink-0 object-contain", draggable: false, unoptimized: true }), _jsx(Image, { src: props.responsibleGamingLogo ?? responsibleGamingLogo, alt: "Responsible Gaming logo", height: 50, width: 186, className: "mx-auto h-[50px] w-auto shrink-0", draggable: false, unoptimized: true })] }), _jsx("div", { className: "w-full text-center font-semibold text-2xl uppercase", id: "disclaimer-title", children: "Notice" }), _jsx("div", { className: "mb-1 text-sm text-text-secondary-700", id: "disclaimer-description", children: "By entering this website, you acknowledge and confirm:" }), _jsx("div", { className: "w-full grow", children: _jsxs(Dialog.Description, { className: "space-y-4 text-sm", children: [_jsxs("ul", { className: "space-y-1.5 text-left", "aria-label": "Restricted persons list", children: [_jsxs("li", { className: "flex gap-4 text-text-placeholder", children: [_jsx(Circle, {}), "You are 21 years old and above."] }), _jsxs("li", { className: "flex gap-4 text-text-placeholder", children: [_jsx(Circle, {}), "You are not a government official, or employee connected directly with the operation of the Government or any of its agencies, member of the Armed Forces of the Philippines including the Army, Navy, Air Force, or the Philippine Nationa Police."] }), _jsxs("li", { className: "flex gap-4 text-text-placeholder", children: [_jsx(Circle, {}), "You are not included in the PAGCOR's National Database Restricted Persons (NDRP)."] }), _jsxs("li", { className: "flex gap-4 text-text-placeholder", children: [_jsx(Circle, {}), "Funds or credits in the account of player who is found ineligible to play shall mean forfeiture of said funds/credits in favor of the Government."] }), _jsxs(Checkbox.Root, { checked: checked, onCheckedChange: (e) => {
31
31
  if (e.checked === 'indeterminate')
32
32
  return;
33
33
  globalStore.termsOfUse.setAccepted(e.checked);
34
34
  globalStore.responsibleGaming.setAccepted(e.checked);
35
- }, className: "pt-2.5 pb-2", children: [_jsx(Checkbox.Control, { children: _jsx(Checkbox.Indicator, { asChild: true, children: _jsx(CheckIcon, {}) }) }), _jsxs(Checkbox.Label, { children: ["You agree and read the", ' ', _jsx("button", { type: "button", className: "text-brand-400 underline underline-offset-2", onClick: () => {
35
+ }, className: "pt-2.5 pb-2 text-sm", children: [_jsx(Checkbox.Control, { children: _jsx(Checkbox.Indicator, { asChild: true, children: _jsx(CheckIcon, {}) }) }), _jsxs(Checkbox.Label, { children: ["You agree and read the", ' ', _jsx("button", { type: "button", className: "text-brand-400 underline underline-offset-2", onClick: () => {
36
36
  globalStore.termsOfUse.setOpen(true);
37
37
  globalStore.termsOfUse.setNext('DISCLAIMER');
38
38
  disclaimer.close();
@@ -40,7 +40,7 @@ export function DisclaimerV3(props) {
40
40
  globalStore.responsibleGaming.setOpen(true);
41
41
  globalStore.responsibleGaming.setNext('DISCLAIMER');
42
42
  disclaimer.close();
43
- }, children: "Responsible Gaming" }), ' ', "guidelines."] }), _jsx(Checkbox.HiddenInput, {})] }), _jsxs("li", { className: "mt-5", children: ["Self Exclusion Site:\u00A0", _jsx("a", { href: "https://osea.pagcor.ph", target: "_blank", className: "text-brand-400 underline underline-offset-2", rel: "noopener", children: "https://osea.pagcor.ph/" })] }), _jsxs("li", { className: "mt-5", children: ["To know more about PAGCOR\u2019s ResponsibleGaming Program:\u00A0", _jsxs("a", { href: "https://www.pagcor.ph/regulatory/responsible-gaming.php", target: "_blank", className: "text-brand-400 underline underline-offset-2", rel: "noopener", children: ["https://www.pagcor.ph", _jsx("br", {}), "/regulatory/responsible-gaming.php"] })] })] }), _jsx("div", { className: twMerge('mx-auto mt-2 flex max-w-full items-center gap-2 break-words rounded-md text-text-error-primary text-xs', showWarning ? 'h-[28px] opacity-100' : 'opacity-0'), role: "alert", "aria-live": "assertive", children: showWarning && (_jsxs(_Fragment, { children: [_jsx(AlertCircleIcon, { className: "size-5 text-text-error-primary" }), "Please agree to ", props.siteName, "'s Terms of Use and Responsible Gaming to proceed."] })) })] }) }), _jsxs("div", { className: "grid w-full grid-cols-2 items-center gap-3xl", children: [_jsx(Image, { src: props.pagcorLogo ?? pagcorLogo, alt: "PAGCOR logo", height: 50, width: 186, className: "h-[43px] w-auto shrink-0 object-contain", draggable: false, unoptimized: true }), _jsx(Image, { src: props.responsibleGamingLogo ?? responsibleGamingLogo, alt: "Responsible Gaming logo", height: 50, width: 186, className: "h-[50px] w-auto shrink-0", draggable: false, unoptimized: true })] }), _jsxs("div", { className: "row mt-4 flex w-full flex-col gap-3", children: [_jsx(Button, { type: "button", onClick: () => {
43
+ }, children: "Responsible Gaming" }), ' ', "guidelines."] }), _jsx(Checkbox.HiddenInput, {})] }), _jsxs("li", { className: "mt-5", children: ["Self Exclusion Site:\u00A0", _jsx("a", { href: "https://osea.pagcor.ph", target: "_blank", className: "text-brand-400 underline underline-offset-2", rel: "noopener", children: "https://osea.pagcor.ph/" })] }), _jsxs("li", { className: "mt-5", children: ["To know more about PAGCOR's Responsible Gaming Program:\u00A0", _jsx("a", { href: "https://www.pagcor.ph/regulatory/responsible-gaming.php", target: "_blank", className: "text-brand-400 underline underline-offset-2", rel: "noopener", children: "https://www.pagcor.ph/regulatory/responsible-gaming.php" })] })] }), _jsx("div", { className: twMerge('mx-auto mt-2 flex max-w-full items-center gap-2 break-words rounded-md text-text-error-primary text-xs', showWarning ? 'h-[28px] opacity-100' : 'opacity-0'), role: "alert", "aria-live": "assertive", children: showWarning && (_jsxs(_Fragment, { children: [_jsx(AlertCircleIcon, { className: "size-5 text-text-error-primary" }), "Please agree to ", props.siteName, "'s Terms of Use and Responsible Gaming to proceed."] })) })] }) }), _jsxs("div", { className: "row mt-4 flex w-full flex-col gap-3", children: [_jsx(Button, { type: "button", onClick: () => {
44
44
  if (!checked) {
45
45
  setShowWarning(true);
46
46
  setTimeout(() => setShowWarning(false), 4000);
@@ -64,4 +64,4 @@ export function DisclaimerV3(props) {
64
64
  }
65
65
  }, variant: "outline", children: "Exit" })] })] }) })] }) }));
66
66
  }
67
- const Circle = () => (_jsx("div", { children: _jsx("div", { className: "flex h-4.5 w-4.5 items-center justify-center rounded-full border border-brand-400", children: _jsx("div", { className: "h-3 w-3 rounded-full bg-brand-400" }) }) }));
67
+ const Circle = () => (_jsx("div", { children: _jsx("div", { className: "flex h-4.5 w-4.5 items-center justify-center rounded-full border-[5px] border-brand-400", children: _jsx("div", { className: "h-2 w-2 rounded-full bg-bg-disabled" }) }) }));
@@ -59,7 +59,7 @@ export function Game(props) {
59
59
  : featureFlag.enabled
60
60
  ? account?.status !== 'VERIFICATION_LOCKED'
61
61
  : true;
62
- return (_jsxs(GameLaunchTrigger, { bypassKycCheck: props.bypassKycCheck, game: game, className: twMerge('group md:hover:-translate-y-1 relative block w-full shadow-sm transition-transform duration-200', classNames.root), "aria-label": `Play ${game.name} game`, children: [props.badge === 'new' && (_jsx(BadgeNew, { className: "absolute top-0 left-0 size-[3.75rem]" })), props.badge === 'top' && (_jsx(BadgeTop, { className: "absolute top-0 left-0 size-[3.75rem]" })), props.badge === 'popular' && (_jsx(BadgePopular, { className: "absolute top-0 left-0 size-[3.75rem]" })), markUnmarkGameAsFavoriteEnabled && (_jsx("div", { role: "button", tabIndex: 0, onClick: (e) => {
62
+ return (_jsxs(GameLaunchTrigger, { bypassKycCheck: props.bypassKycCheck, game: game, className: twMerge('group md:hover:-translate-y-1 relative flex h-full w-full flex-col shadow-sm transition-transform duration-200', classNames.root), "aria-label": `Play ${game.name} game`, children: [props.badge === 'new' && (_jsx(BadgeNew, { className: "absolute top-0 left-0 size-[3.75rem]" })), props.badge === 'top' && (_jsx(BadgeTop, { className: "absolute top-0 left-0 size-[3.75rem]" })), props.badge === 'popular' && (_jsx(BadgePopular, { className: "absolute top-0 left-0 size-[3.75rem]" })), markUnmarkGameAsFavoriteEnabled && (_jsx("div", { role: "button", tabIndex: 0, onClick: (e) => {
63
63
  e.preventDefault();
64
64
  e.stopPropagation();
65
65
  if (markGameAsFavoriteMutation.isPending)
@@ -77,7 +77,7 @@ export function Game(props) {
77
77
  : 'Mark as favorite game', "aria-disabled": markGameAsFavoriteMutation.isPending ||
78
78
  unmarkGameAsFavoriteMutation.isPending, className: "absolute top-2 right-2 flex size-9 items-center justify-center rounded-xs bg-black/65 opacity-100 blur-[0.5px] transition-opacity duration-200 md:opacity-0 md:group-hover:opacity-100", children: _jsx(Star01Icon, { className: twMerge('size-5 text-white transition-colors duration-200 hover:text-yellow-400', markedAsFavorite
79
79
  ? 'fill-yellow-400 text-yellow-400'
80
- : 'text-white') }) })), _jsx(GameImage, { priority: props.priority }), _jsx("span", { className: twMerge('block w-full truncate rounded-b-md bg-bg-tertiary px-2 py-3.5 text-center font-semibold text-text-primary-brand text-xs', classNames.title), children: game.name })] }));
80
+ : 'text-white') }) })), _jsx(GameImage, { priority: props.priority }), _jsx("span", { className: twMerge('flex w-full flex-1 items-center justify-center break-words rounded-b-md bg-bg-tertiary px-2 py-3.5 text-center font-semibold text-text-primary-brand text-xs', classNames.title), children: game.name })] }));
81
81
  }
82
82
  function GameImage({ priority }) {
83
83
  const game = useGameContext();
@@ -60,12 +60,11 @@ export function GamesSearch(props) {
60
60
  }, children: "Clear" }));
61
61
  } })] }), _jsx(Portal, { children: _jsx(Combobox.Context, { children: (api) => (_jsxs(_Fragment, { children: [_jsx(Presence, { present: api.open, children: _jsx("div", { className: "fixed inset-0 z-40 bg-black/50 backdrop-blur-sm", onClick: () => api.setOpen(false) }) }), _jsx(Combobox.Positioner, { children: searchInput.trim().length > 0 && (_jsx(Combobox.Content, { className: "z-50 max-h-[33.25rem] overflow-y-auto p-0", children: showMinLengthWarning ? (_jsx(Alert, { message: "Search requires at least 3 characters." })) : (_jsxs(_Fragment, { children: [games.length <= 0 && (_jsx(Alert, { message: "No results found" })), games.length > 0 && (_jsxs("div", { className: "p-xl", children: [_jsx(Combobox.Context, { children: (api) => (_jsx("div", { className: twMerge('grid grid-cols-3 gap-1.5 lg:grid-cols-9 lg:gap-3.5', classNames.gameSearchResult), children: games.map((game) => (_jsxs(GameLaunchTrigger, { bypassKycCheck: isBypass, game: game, onClick: () => {
62
62
  api.setOpen(false);
63
- }, className: twMerge('block w-full shadow-sm', classNames.thumbnailRoot), children: [_jsx(Image, { src: getGameImageUrl({
63
+ }, className: twMerge('md:hover:-translate-y-1 relative flex h-full w-full flex-col shadow-sm transition-transform duration-200', classNames.thumbnailRoot), children: [_jsx(Image, { src: getGameImageUrl({
64
64
  reference: game.reference,
65
65
  provider: game.provider,
66
66
  image: game.image,
67
- }), alt: "", width: 200, height: 200, loading: "lazy", unoptimized: true, className: "aspect-square w-full rounded-t-md object-cover" }), _jsx("span", { className: twMerge('block w-full rounded-b-md bg-bg-tertiary px-2 py-2.5 text-center font-semibold text-text-primary-brand text-xs', props.variant !== '88play' &&
68
- 'truncate', classNames.thumbnailTitle), children: fixMojibake(game.name) })] }, game.id))) })) }), _jsx(Presence, { present: gamesQuery.hasNextPage, children: _jsx(Button, { variant: "outline", className: twMerge('mx-auto mt-4xl w-fit', classNames.loadMoreButton), onClick: () => gamesQuery.fetchNextPage(), children: "Load More" }) })] }))] })) })) })] })) }) })] }) }));
67
+ }), alt: "", width: 200, height: 200, loading: "lazy", unoptimized: true, className: "aspect-square w-full rounded-t-md object-cover" }), _jsx("span", { className: twMerge('flex w-full flex-1 items-center justify-center break-words rounded-b-md bg-bg-tertiary px-2 py-2.5 text-center font-semibold text-text-primary-brand text-xs', classNames.thumbnailTitle), children: fixMojibake(game.name) })] }, game.id))) })) }), _jsx(Presence, { present: gamesQuery.hasNextPage, children: _jsx(Button, { variant: "outline", className: twMerge('mx-auto mt-4xl w-fit', classNames.loadMoreButton), onClick: () => gamesQuery.fetchNextPage(), children: "Load More" }) })] }))] })) })) })] })) }) })] }) }));
69
68
  }
70
69
  function Alert({ message }) {
71
70
  return (_jsxs("div", { className: "py-lg", role: "alert", "aria-live": "polite", children: [_jsx("div", { className: "mx-auto flex size-12 items-center justify-center rounded-lg border border-border-primary bg-bg-secondary shadow-xs", children: _jsx(SearchLgIcon, { className: "size-6 text-text-secondary-700" }) }), _jsx("p", { className: "mt-4 text-center text-text-secondary-700", children: message })] }));
@@ -1,5 +1,5 @@
1
1
  import type { ResponsibleGamingProps as LazyProps } from './ResponsibleGaming.lazy';
2
2
  export type ResponsibleGamingProps = LazyProps & {
3
- version?: '1' | '2';
3
+ version?: '1' | '2' | '3';
4
4
  };
5
5
  export declare function ResponsibleGaming({ version, ...props }: ResponsibleGamingProps): import("react/jsx-runtime").JSX.Element | null;
@@ -11,6 +11,10 @@ const V2 = dynamic(() => import('./ResponsibleGamingV2.lazy.js').then((m) => m.R
11
11
  ssr: false,
12
12
  loading: () => null,
13
13
  });
14
+ const V3 = dynamic(() => import('./ResponsibleGamingV3.lazy.js').then((m) => m.ResponsibleGamingV3), {
15
+ ssr: false,
16
+ loading: () => null,
17
+ });
14
18
  export function ResponsibleGaming({ version = '1', ...props }) {
15
19
  const touched = useGlobalStore(useShallow((ctx) => ctx.responsibleGaming['~touched']));
16
20
  if (!touched) {
@@ -19,5 +23,8 @@ export function ResponsibleGaming({ version = '1', ...props }) {
19
23
  if (version === '2') {
20
24
  return _jsx(V2, { ...props });
21
25
  }
26
+ if (version === '3') {
27
+ return _jsx(V3, { ...props });
28
+ }
22
29
  return _jsx(V1, { ...props });
23
30
  }
@@ -0,0 +1,8 @@
1
+ import { type ImageProps } from 'next/image';
2
+ import { type ReactNode } from 'react';
3
+ export interface ResponsibleGamingV3Props {
4
+ logo: ImageProps['src'];
5
+ content: string | ReactNode;
6
+ responsibleGamingLogo?: ImageProps['src'];
7
+ }
8
+ export declare function ResponsibleGamingV3(props: ResponsibleGamingV3Props): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,71 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import Image, {} from 'next/image';
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import { twMerge } from 'tailwind-merge';
5
+ import { useShallow } from 'zustand/shallow';
6
+ import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
7
+ import { ScrollToBottomIcon } from '../../icons/ScrollToBottomIcon.js';
8
+ import { ScrollToTopIcon } from '../../icons/ScrollToTopIcon.js';
9
+ import decorativebackground from '../../images/decorative-patern.png';
10
+ import { Button } from '../../ui/Button/index.js';
11
+ import { Dialog } from '../../ui/Dialog/index.js';
12
+ import { Portal } from '../../ui/Portal/index.js';
13
+ export function ResponsibleGamingV3(props) {
14
+ const [hasReachedBottom, setHasReachedBottom] = useState(false);
15
+ const [isAtBottom, setIsAtBottom] = useState(false);
16
+ const scrollableContentRef = useRef(null);
17
+ const globalStore = useGlobalStore(useShallow((ctx) => ({
18
+ signIn: ctx.signIn,
19
+ signUp: ctx.signUp,
20
+ disclaimer: ctx.disclaimer,
21
+ responsibleGaming: ctx.responsibleGaming,
22
+ })));
23
+ useEffect(() => {
24
+ if (scrollableContentRef.current) {
25
+ const { scrollHeight, clientHeight } = scrollableContentRef.current;
26
+ const atBottom = scrollHeight <= clientHeight;
27
+ setIsAtBottom(atBottom);
28
+ if (atBottom) {
29
+ setHasReachedBottom(true);
30
+ }
31
+ }
32
+ }, []);
33
+ return (_jsx(Dialog.Root, { open: globalStore.responsibleGaming.open, onOpenChange: (details) => {
34
+ globalStore.responsibleGaming.setOpen(details.open);
35
+ if (!details.open)
36
+ globalStore.responsibleGaming.setAccepted(true);
37
+ }, lazyMount: true, unmountOnExit: true, closeOnEscape: false, closeOnInteractOutside: false, onExitComplete: () => {
38
+ if (globalStore.responsibleGaming.next === 'SIGN_IN') {
39
+ globalStore.signIn.setOpen(true);
40
+ }
41
+ if (globalStore.responsibleGaming.next === 'SIGN_UP') {
42
+ globalStore.signUp.setOpen(true);
43
+ }
44
+ if (globalStore.responsibleGaming.next === 'DISCLAIMER') {
45
+ globalStore.disclaimer.setOpen(true);
46
+ }
47
+ globalStore.responsibleGaming.setNext(null);
48
+ }, 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: 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) => {
49
+ const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
50
+ const atBottom = Math.abs(scrollHeight - clientHeight - scrollTop) < 1;
51
+ setIsAtBottom(atBottom);
52
+ if (atBottom) {
53
+ setHasReachedBottom(true);
54
+ }
55
+ }, children: [_jsx(Dialog.Description, { className: "text-xs leading-relaxed sm:text-sm sm:leading-2xl", children: props.content }), _jsx(Button, { type: "button", className: twMerge('absolute right-6 bottom-7 z-10 size-10 rounded-lg transition-colors duration-75 ease-in-out sm:right-6 sm:bottom-6 lg:right-8 lg:bottom-8', isAtBottom
56
+ ? 'border border-[#CECFD2] bg-bg-secondary'
57
+ : 'bg-bg-brand-secondary'), onClick: () => {
58
+ if (scrollableContentRef.current) {
59
+ scrollableContentRef.current.scrollTo({
60
+ top: isAtBottom
61
+ ? 0
62
+ : scrollableContentRef.current.scrollHeight,
63
+ behavior: 'smooth',
64
+ });
65
+ }
66
+ }, children: isAtBottom ? _jsx(ScrollToTopIcon, {}) : _jsx(ScrollToBottomIcon, {}) })] }) })] }), _jsx(Dialog.Context, { children: (api) => (_jsx(Button, { type: "button", className: twMerge('mt-4 w-full py-2 text-sm sm:py-2.5 sm:text-base', hasReachedBottom
67
+ ? 'bg-bg-brand-secondary'
68
+ : 'bg-bg-disabled text-text-disabled'), onClick: () => {
69
+ api.setOpen(false);
70
+ }, disabled: !hasReachedBottom, children: "I Agree" })) })] }) })] }) }));
71
+ }
@@ -1,5 +1,5 @@
1
1
  import type { TermsOfUseProps as LazyProps } from './TermsOfUse.lazy';
2
2
  export type TermsOfUseProps = LazyProps & {
3
- version?: '1' | '2';
3
+ version?: '1' | '2' | '3';
4
4
  };
5
5
  export declare function TermsOfUse({ version, ...props }: TermsOfUseProps): import("react/jsx-runtime").JSX.Element | null;
@@ -11,6 +11,10 @@ const V2 = dynamic(() => import('./TermsOfUseV2.lazy.js').then((m) => m.TermsOfU
11
11
  ssr: false,
12
12
  loading: () => null,
13
13
  });
14
+ const V3 = dynamic(() => import('./TermsOfUseV3.lazy.js').then((m) => m.TermsOfUseV3), {
15
+ ssr: false,
16
+ loading: () => null,
17
+ });
14
18
  export function TermsOfUse({ version = '1', ...props }) {
15
19
  const touched = useGlobalStore(useShallow((ctx) => ctx.termsOfUse['~touched']));
16
20
  if (!touched) {
@@ -19,5 +23,8 @@ export function TermsOfUse({ version = '1', ...props }) {
19
23
  if (version === '2') {
20
24
  return _jsx(V2, { ...props });
21
25
  }
26
+ if (version === '3') {
27
+ return _jsx(V3, { ...props });
28
+ }
22
29
  return _jsx(V1, { ...props });
23
30
  }
@@ -0,0 +1,9 @@
1
+ import { type ImageProps } from 'next/image';
2
+ import { type ReactNode } from 'react';
3
+ export interface TermsOfUseV3Props {
4
+ logo: ImageProps['src'];
5
+ content: string | ReactNode;
6
+ siteName: string;
7
+ responsibleGamingLogo?: ImageProps['src'];
8
+ }
9
+ export declare function TermsOfUseV3({ logo, siteName, content, ...props }: TermsOfUseV3Props): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,69 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import Image, {} from 'next/image';
3
+ import { useEffect, useRef, useState } from 'react';
4
+ import { twMerge } from 'tailwind-merge';
5
+ import { useShallow } from 'zustand/shallow';
6
+ import { useGlobalStore } from '../../client/hooks/useGlobalStore.js';
7
+ import { ScrollToBottomIcon } from '../../icons/ScrollToBottomIcon.js';
8
+ import { ScrollToTopIcon } from '../../icons/ScrollToTopIcon.js';
9
+ import decorativebackground from '../../images/decorative-patern.png';
10
+ import { Button } from '../../ui/Button/index.js';
11
+ import { Dialog } from '../../ui/Dialog/index.js';
12
+ import { Portal } from '../../ui/Portal/index.js';
13
+ export function TermsOfUseV3({ logo, siteName, content, ...props }) {
14
+ const scrollableContentRef = useRef(null);
15
+ const [hasReachedBottom, setHasReachedBottom] = useState(false);
16
+ const [isAtBottom, setIsAtBottom] = useState(false);
17
+ const globalStore = useGlobalStore(useShallow((ctx) => ({
18
+ signIn: ctx.signIn,
19
+ signUp: ctx.signUp,
20
+ disclaimer: ctx.disclaimer,
21
+ termsOfUse: ctx.termsOfUse,
22
+ })));
23
+ useEffect(() => {
24
+ if (scrollableContentRef.current) {
25
+ const { scrollHeight, clientHeight } = scrollableContentRef.current;
26
+ const atBottom = scrollHeight <= clientHeight;
27
+ setIsAtBottom(atBottom);
28
+ if (atBottom) {
29
+ setHasReachedBottom(true);
30
+ }
31
+ }
32
+ }, []);
33
+ return (_jsx(Dialog.Root, { open: globalStore.termsOfUse.open, onOpenChange: (details) => {
34
+ globalStore.termsOfUse.setOpen(details.open);
35
+ if (!details.open)
36
+ globalStore.termsOfUse.setAccepted(true);
37
+ }, lazyMount: true, unmountOnExit: true, closeOnEscape: false, closeOnInteractOutside: false, onExitComplete: () => {
38
+ if (globalStore.termsOfUse.next === 'SIGN_IN') {
39
+ globalStore.signIn.setOpen(true);
40
+ }
41
+ if (globalStore.termsOfUse.next === 'SIGN_UP') {
42
+ globalStore.signUp.setOpen(true);
43
+ }
44
+ if (globalStore.termsOfUse.next === 'DISCLAIMER') {
45
+ globalStore.disclaimer.setOpen(true);
46
+ }
47
+ globalStore.termsOfUse.setNext(null);
48
+ }, 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) => {
49
+ const { scrollTop, scrollHeight, clientHeight } = e.currentTarget;
50
+ if (Math.abs(scrollHeight - clientHeight - scrollTop) < 1) {
51
+ setHasReachedBottom(true);
52
+ }
53
+ }, children: [_jsx(Dialog.Description, { className: "text-xs leading-relaxed sm:text-sm sm:leading-2xl", children: content }), _jsx(Button, { type: "button", className: twMerge('absolute right-6 bottom-7 z-10 size-10 rounded-lg transition-colors duration-75 ease-in-out sm:right-6 sm:bottom-6 lg:right-8 lg:bottom-8', isAtBottom
54
+ ? 'border border-[#CECFD2] bg-bg-secondary'
55
+ : 'bg-bg-brand-secondary'), onClick: () => {
56
+ if (scrollableContentRef.current) {
57
+ scrollableContentRef.current.scrollTo({
58
+ top: isAtBottom
59
+ ? 0
60
+ : scrollableContentRef.current.scrollHeight,
61
+ behavior: 'smooth',
62
+ });
63
+ }
64
+ }, children: isAtBottom ? _jsx(ScrollToTopIcon, {}) : _jsx(ScrollToBottomIcon, {}) })] }) })] }), _jsx(Dialog.Context, { children: (api) => (_jsx(Button, { type: "button", className: twMerge('mt-4 flex-1 py-2 text-sm sm:py-2.5 sm:text-base', hasReachedBottom
65
+ ? 'bg-bg-brand-secondary'
66
+ : 'bg-bg-disabled text-text-disabled'), onClick: () => {
67
+ api.setOpen(false);
68
+ }, disabled: !hasReachedBottom, children: "Accept" })) })] }) })] }) }));
69
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opexa/portal-components",
3
- "version": "0.0.934",
3
+ "version": "0.0.935",
4
4
  "exports": {
5
5
  "./ui/*": {
6
6
  "types": "./dist/ui/*/index.d.ts",