@opexa/portal-components 0.0.77 → 0.0.79
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.
- package/dist/client/hooks/index.d.ts +1 -0
- package/dist/client/hooks/index.js +1 -0
- package/dist/client/hooks/useChunk.d.ts +8 -0
- package/dist/client/hooks/useChunk.js +26 -0
- package/dist/components/DepositWithdrawal/Deposit/OnlineBankDeposit/OnlineBankDepositContext.d.ts +2 -2
- package/dist/components/DepositWithdrawal/Deposit/OnlineBankDeposit/useOnlineBankDeposit.d.ts +1 -1
- package/dist/components/DepositWithdrawal/Deposit/QRPHDeposit/QRPHDepositContext.d.ts +2 -2
- package/dist/components/DepositWithdrawal/Deposit/QRPHDeposit/useQRPHDeposit.d.ts +1 -1
- package/dist/components/GameProviders/GameProviders.d.ts +3 -24
- package/dist/components/GameProviders/GameProviders.js +9 -41
- package/dist/components/GameProviders/GameProvidersCarousel.d.ts +29 -0
- package/dist/components/GameProviders/GameProvidersCarousel.js +47 -0
- package/dist/components/GameProviders/GameProvidersList.d.ts +25 -0
- package/dist/components/GameProviders/GameProvidersList.js +25 -0
- package/dist/components/Games/Game.d.ts +6 -1
- package/dist/components/Games/Game.js +7 -3
- package/dist/components/Games/Games.d.ts +1 -5
- package/dist/components/Games/GamesCarousel.client.js +10 -3
- package/dist/components/Games/GamesCarousel.d.ts +7 -2
- package/dist/components/Games/GamesContext.d.ts +4 -0
- package/dist/components/Games/GamesContext.js +3 -0
- package/dist/components/Games/GamesList.client.js +10 -4
- package/dist/components/Games/GamesList.d.ts +7 -2
- package/dist/components/Promos/Promos.d.ts +3 -14
- package/dist/components/Promos/PromosCarousel.d.ts +13 -2
- package/dist/components/Promos/PromosGrid.d.ts +11 -2
- package/dist/constants/gameProviders.js +1 -1
- package/package.json +1 -1
|
@@ -10,6 +10,7 @@ export * from './useCashbackBonusQuery';
|
|
|
10
10
|
export * from './useCashbackQuery';
|
|
11
11
|
export * from './useCashbacksQuery';
|
|
12
12
|
export * from './useCheckInDailyCheckInQuestMutation';
|
|
13
|
+
export * from './useChunk';
|
|
13
14
|
export * from './useClaimCashbackBonusMutation';
|
|
14
15
|
export * from './useClaimSpotBonusMutation';
|
|
15
16
|
export * from './useControllableState';
|
|
@@ -10,6 +10,7 @@ export * from './useCashbackBonusQuery.js';
|
|
|
10
10
|
export * from './useCashbackQuery.js';
|
|
11
11
|
export * from './useCashbacksQuery.js';
|
|
12
12
|
export * from './useCheckInDailyCheckInQuestMutation.js';
|
|
13
|
+
export * from './useChunk.js';
|
|
13
14
|
export * from './useClaimCashbackBonusMutation.js';
|
|
14
15
|
export * from './useClaimSpotBonusMutation.js';
|
|
15
16
|
export * from './useControllableState.js';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { chunk } from 'lodash-es';
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
export function useChunk(items, size) {
|
|
4
|
+
const chunks = chunk(items, size);
|
|
5
|
+
const [currentIndex, setCurrentIndex] = useState(0);
|
|
6
|
+
const currentItems = chunks.at(currentIndex) ?? [];
|
|
7
|
+
const loadedItems = (() => {
|
|
8
|
+
return chunks.filter((_, index) => index <= currentIndex).flat();
|
|
9
|
+
})();
|
|
10
|
+
const next = () => {
|
|
11
|
+
if (currentIndex >= chunks.length - 1)
|
|
12
|
+
return;
|
|
13
|
+
setCurrentIndex((prevIndex) => prevIndex + 1);
|
|
14
|
+
};
|
|
15
|
+
const totalItems = items.length;
|
|
16
|
+
const totalLoadedItems = loadedItems.length;
|
|
17
|
+
const hasNext = currentIndex < chunks.length - 1;
|
|
18
|
+
return {
|
|
19
|
+
totalItems,
|
|
20
|
+
currentItems,
|
|
21
|
+
loadedItems,
|
|
22
|
+
totalLoadedItems,
|
|
23
|
+
hasNext,
|
|
24
|
+
next,
|
|
25
|
+
};
|
|
26
|
+
}
|
package/dist/components/DepositWithdrawal/Deposit/OnlineBankDeposit/OnlineBankDepositContext.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const OnlineBankDepositContext: import("react").Context<{
|
|
2
|
-
view: "
|
|
2
|
+
view: "form" | "vca";
|
|
3
3
|
status: "waiting" | "processing" | "failed" | "verification-waiting" | "verification-processing" | "verification-failed" | "verification-success";
|
|
4
4
|
verify: () => void;
|
|
5
5
|
reset: () => void;
|
|
@@ -9,7 +9,7 @@ export declare const OnlineBankDepositContext: import("react").Context<{
|
|
|
9
9
|
promo?: string | null;
|
|
10
10
|
}) => void;
|
|
11
11
|
}>, useOnlineBankDepositContext: () => {
|
|
12
|
-
view: "
|
|
12
|
+
view: "form" | "vca";
|
|
13
13
|
status: "waiting" | "processing" | "failed" | "verification-waiting" | "verification-processing" | "verification-failed" | "verification-success";
|
|
14
14
|
verify: () => void;
|
|
15
15
|
reset: () => void;
|
package/dist/components/DepositWithdrawal/Deposit/OnlineBankDeposit/useOnlineBankDeposit.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Deposit } from '@opexa/portal-sdk-core';
|
|
2
2
|
export type UseOnlineBankDepositReturn = ReturnType<typeof useOnlineBankDeposit>;
|
|
3
3
|
export declare function useOnlineBankDeposit(): {
|
|
4
|
-
view: "
|
|
4
|
+
view: "form" | "vca";
|
|
5
5
|
status: "waiting" | "processing" | "failed" | "verification-waiting" | "verification-processing" | "verification-failed" | "verification-success";
|
|
6
6
|
verify: () => void;
|
|
7
7
|
reset: () => void;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const QRPHDepositContext: import("react").Context<{
|
|
2
|
-
view: "
|
|
2
|
+
view: "form" | "qrCode";
|
|
3
3
|
status: "waiting" | "processing" | "failed" | "verification-waiting" | "verification-processing" | "verification-failed" | "verification-success";
|
|
4
4
|
verify: () => void;
|
|
5
5
|
reset: () => void;
|
|
@@ -9,7 +9,7 @@ export declare const QRPHDepositContext: import("react").Context<{
|
|
|
9
9
|
promo?: string | null;
|
|
10
10
|
}) => void;
|
|
11
11
|
}>, useQRPHDepositContext: () => {
|
|
12
|
-
view: "
|
|
12
|
+
view: "form" | "qrCode";
|
|
13
13
|
status: "waiting" | "processing" | "failed" | "verification-waiting" | "verification-processing" | "verification-failed" | "verification-success";
|
|
14
14
|
verify: () => void;
|
|
15
15
|
reset: () => void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Deposit } from '@opexa/portal-sdk-core';
|
|
2
2
|
export type UseQRPHDepositReturn = ReturnType<typeof useQRPHDeposit>;
|
|
3
3
|
export declare function useQRPHDeposit(): {
|
|
4
|
-
view: "
|
|
4
|
+
view: "form" | "qrCode";
|
|
5
5
|
status: "waiting" | "processing" | "failed" | "verification-waiting" | "verification-processing" | "verification-failed" | "verification-success";
|
|
6
6
|
verify: () => void;
|
|
7
7
|
reset: () => void;
|
|
@@ -1,25 +1,4 @@
|
|
|
1
|
-
import type
|
|
2
|
-
import type
|
|
3
|
-
export
|
|
4
|
-
gameProviders: GameProvider[];
|
|
5
|
-
heading?: string;
|
|
6
|
-
/**
|
|
7
|
-
* @default '/providers'
|
|
8
|
-
*/
|
|
9
|
-
viewAllUrl?: string;
|
|
10
|
-
/**
|
|
11
|
-
* @default '/providers/<slug>'
|
|
12
|
-
* @example
|
|
13
|
-
* ```ts
|
|
14
|
-
* '/bingo/:slug' // '/bingo/jili'
|
|
15
|
-
* '/bingo/:id' // '/bingo/JILI'
|
|
16
|
-
* // or using a function
|
|
17
|
-
* ({slug}) => `/bingo/${slug}`
|
|
18
|
-
* ```
|
|
19
|
-
*/
|
|
20
|
-
viewGamesUrl?: string | ((gameProvider: GameProviderData) => string);
|
|
21
|
-
className?: string;
|
|
22
|
-
gameProviderContainerClass?: string;
|
|
23
|
-
gameProviderImageClass?: string;
|
|
24
|
-
}
|
|
1
|
+
import { type GameProvidersCarouselProps } from './GameProvidersCarousel';
|
|
2
|
+
import { type GameProvidersListProps } from './GameProvidersList';
|
|
3
|
+
export type GameProvidersProps = GameProvidersCarouselProps | GameProvidersListProps;
|
|
25
4
|
export declare function GameProviders(props: GameProvidersProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,43 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
4
|
-
import Image from 'next/image';
|
|
5
|
-
import Link from 'next/link';
|
|
6
|
-
import { useCallback, useEffect, useState } from 'react';
|
|
7
|
-
import { twMerge } from 'tailwind-merge';
|
|
8
|
-
import { GAME_PROVIDER_DATA } from '../../constants/index.js';
|
|
9
|
-
import { ArrowLeftIcon, ArrowRightIcon, ChevronRightIcon } from '../../icons/index.js';
|
|
10
|
-
import { Button } from '../../ui/index.js';
|
|
11
|
-
import { callIfFn } from '../../utils/index.js';
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { GameProvidersCarousel, } from './GameProvidersCarousel.js';
|
|
3
|
+
import { GameProvidersList, } from './GameProvidersList.js';
|
|
12
4
|
export function GameProviders(props) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const onPrevButtonClick = useCallback(() => emblaApi?.scrollPrev(), [emblaApi]);
|
|
20
|
-
const onNextButtonClick = useCallback(async () => {
|
|
21
|
-
emblaApi?.scrollNext();
|
|
22
|
-
}, [emblaApi]);
|
|
23
|
-
const onSelect = useCallback((emblaApi) => {
|
|
24
|
-
setPrevBtnDisabled(!emblaApi?.canScrollPrev());
|
|
25
|
-
setNextBtnDisabled(!emblaApi?.canScrollNext());
|
|
26
|
-
}, []);
|
|
27
|
-
useEffect(() => {
|
|
28
|
-
if (!emblaApi)
|
|
29
|
-
return;
|
|
30
|
-
onSelect(emblaApi);
|
|
31
|
-
emblaApi.on('reInit', onSelect).on('select', onSelect);
|
|
32
|
-
}, [emblaApi, onSelect]);
|
|
33
|
-
const viewAllUrl = props.viewAllUrl ?? '/providers';
|
|
34
|
-
const viewGamesUrl = (data) => {
|
|
35
|
-
return props.viewGamesUrl
|
|
36
|
-
? callIfFn(props.viewGamesUrl, data)
|
|
37
|
-
.replace(':id', data.id)
|
|
38
|
-
.replace(':slug', data.slug)
|
|
39
|
-
: `/providers/${data.slug}`;
|
|
40
|
-
};
|
|
41
|
-
const gameProviders = props.gameProviders.map((provider) => GAME_PROVIDER_DATA[provider]);
|
|
42
|
-
return (_jsxs("div", { className: props.className, children: [_jsxs("div", { className: "flex items-center", children: [_jsx("h2", { className: "text-lg font-semibold", children: props.heading ?? 'Providers' }), _jsx("div", { className: "grow" }), _jsxs("div", { className: "flex items-center justify-center gap-xl", children: [_jsxs(Link, { href: viewAllUrl, className: "text-button-tertiary-fg flex gap-sm text-sm font-semibold", children: ["See All", _jsx(ChevronRightIcon, { className: "size-5 lg:hidden" })] }), _jsxs("div", { className: "hidden lg:flex", children: [_jsx(Button, { variant: "outline", colorScheme: "gray", className: "rounded-r-none border-r-0", onClick: onPrevButtonClick, disabled: prevBtnDisabled, "aria-label": "Previous", children: _jsx(ArrowLeftIcon, { className: "size-5" }) }), _jsx(Button, { variant: "outline", colorScheme: "gray", className: "rounded-l-none", onClick: onNextButtonClick, disabled: nextBtnDisabled, "aria-label": "Next", children: _jsx(ArrowRightIcon, { className: "size-5" }) })] })] })] }), _jsx("div", { ref: emblaRef, className: "relative mt-lg lg:overflow-hidden", children: _jsx("div", { className: "grid auto-cols-[calc((100%-(0.375rem*2))/3)] grid-flow-col grid-rows-1 gap-sm lg:auto-cols-[calc((100%-(0.5rem*5))/6)] lg:gap-md", children: gameProviders.map((provider) => (_jsx(Link, { href: viewGamesUrl(provider), className: twMerge('bg-gray-800 flex h-full w-full items-center overflow-hidden rounded-md lg:h-[5.75rem]', props.gameProviderContainerClass), "aria-label": `View ${provider.name} games`, children: _jsx(Image, { src: provider.logo, alt: "", width: 300, height: 150, className: twMerge('mx-auto h-auto w-full', props.gameProviderImageClass) }) }, provider.id))) }) })] }));
|
|
5
|
+
if (props.layout === 'list') {
|
|
6
|
+
return _jsx(GameProvidersList, { ...props });
|
|
7
|
+
}
|
|
8
|
+
else {
|
|
9
|
+
return _jsx(GameProvidersCarousel, { ...props });
|
|
10
|
+
}
|
|
43
11
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { GameProvider } from '@opexa/portal-sdk-core';
|
|
2
|
+
import type { GameProviderData } from '../../types';
|
|
3
|
+
export interface ClassNameEntries {
|
|
4
|
+
root?: string;
|
|
5
|
+
thumbnailRoot?: string;
|
|
6
|
+
thumbnailImage?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface GameProvidersCarouselProps {
|
|
9
|
+
layout: 'carousel';
|
|
10
|
+
gameProviders: GameProvider[];
|
|
11
|
+
heading?: string;
|
|
12
|
+
/**
|
|
13
|
+
* @default '/providers'
|
|
14
|
+
*/
|
|
15
|
+
viewAllUrl?: string;
|
|
16
|
+
/**
|
|
17
|
+
* @default '/providers/<slug>'
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* '/bingo/:slug' // '/bingo/jili'
|
|
21
|
+
* '/bingo/:id' // '/bingo/JILI'
|
|
22
|
+
* // or using a function
|
|
23
|
+
* ({slug}) => `/bingo/${slug}`
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
viewGamesUrl?: string | ((gameProvider: GameProviderData) => string);
|
|
27
|
+
className?: string | ClassNameEntries;
|
|
28
|
+
}
|
|
29
|
+
export declare function GameProvidersCarousel(props: GameProvidersCarouselProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import useEmblaCarousel from 'embla-carousel-react';
|
|
4
|
+
import { isString } from 'lodash-es';
|
|
5
|
+
import Image from 'next/image';
|
|
6
|
+
import Link from 'next/link';
|
|
7
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
8
|
+
import { twMerge } from 'tailwind-merge';
|
|
9
|
+
import { GAME_PROVIDER_DATA } from '../../constants/index.js';
|
|
10
|
+
import { ArrowLeftIcon, ArrowRightIcon, ChevronRightIcon } from '../../icons/index.js';
|
|
11
|
+
import { Button } from '../../ui/index.js';
|
|
12
|
+
import { callIfFn } from '../../utils/index.js';
|
|
13
|
+
export function GameProvidersCarousel(props) {
|
|
14
|
+
const [emblaRef, emblaApi] = useEmblaCarousel({
|
|
15
|
+
align: 'start',
|
|
16
|
+
slidesToScroll: 1,
|
|
17
|
+
});
|
|
18
|
+
const [prevBtnDisabled, setPrevBtnDisabled] = useState(true);
|
|
19
|
+
const [nextBtnDisabled, setNextBtnDisabled] = useState(true);
|
|
20
|
+
const onPrevButtonClick = useCallback(() => emblaApi?.scrollPrev(), [emblaApi]);
|
|
21
|
+
const onNextButtonClick = useCallback(async () => {
|
|
22
|
+
emblaApi?.scrollNext();
|
|
23
|
+
}, [emblaApi]);
|
|
24
|
+
const onSelect = useCallback((emblaApi) => {
|
|
25
|
+
setPrevBtnDisabled(!emblaApi?.canScrollPrev());
|
|
26
|
+
setNextBtnDisabled(!emblaApi?.canScrollNext());
|
|
27
|
+
}, []);
|
|
28
|
+
useEffect(() => {
|
|
29
|
+
if (!emblaApi)
|
|
30
|
+
return;
|
|
31
|
+
onSelect(emblaApi);
|
|
32
|
+
emblaApi.on('reInit', onSelect).on('select', onSelect);
|
|
33
|
+
}, [emblaApi, onSelect]);
|
|
34
|
+
const viewAllUrl = props.viewAllUrl ?? '/providers';
|
|
35
|
+
const viewGamesUrl = (data) => {
|
|
36
|
+
return props.viewGamesUrl
|
|
37
|
+
? callIfFn(props.viewGamesUrl, data)
|
|
38
|
+
.replace(':id', data.id)
|
|
39
|
+
.replace(':slug', data.slug)
|
|
40
|
+
: `/providers/${data.slug}`;
|
|
41
|
+
};
|
|
42
|
+
const gameProviders = props.gameProviders.map((provider) => GAME_PROVIDER_DATA[provider]);
|
|
43
|
+
const classNames = isString(props.className)
|
|
44
|
+
? { root: props.className }
|
|
45
|
+
: (props.className ?? {});
|
|
46
|
+
return (_jsxs("div", { className: classNames.root, children: [_jsxs("div", { className: "flex items-center", children: [_jsx("h2", { className: "text-lg font-semibold", children: props.heading ?? 'Providers' }), _jsx("div", { className: "grow" }), _jsxs("div", { className: "flex items-center justify-center gap-xl", children: [_jsxs(Link, { href: viewAllUrl, className: "text-button-tertiary-fg flex gap-sm text-sm font-semibold", children: ["See All", _jsx(ChevronRightIcon, { className: "size-5 lg:hidden" })] }), _jsxs("div", { className: "hidden lg:flex", children: [_jsx(Button, { variant: "outline", colorScheme: "gray", className: "rounded-r-none border-r-0", onClick: onPrevButtonClick, disabled: prevBtnDisabled, "aria-label": "Previous", children: _jsx(ArrowLeftIcon, { className: "size-5" }) }), _jsx(Button, { variant: "outline", colorScheme: "gray", className: "rounded-l-none", onClick: onNextButtonClick, disabled: nextBtnDisabled, "aria-label": "Next", children: _jsx(ArrowRightIcon, { className: "size-5" }) })] })] })] }), _jsx("div", { ref: emblaRef, className: "relative mt-lg lg:overflow-hidden", children: _jsx("div", { className: "grid auto-cols-[calc((100%-(0.375rem*2))/3)] grid-flow-col grid-rows-1 gap-sm lg:auto-cols-[calc((100%-(0.5rem*5))/6)] lg:gap-md", children: gameProviders.map((provider) => (_jsx(Link, { href: viewGamesUrl(provider), className: twMerge('bg-gray-800 flex h-full w-full items-center overflow-hidden rounded-md lg:h-[5.75rem]', classNames.thumbnailRoot), "aria-label": `View ${provider.name} games`, children: _jsx(Image, { src: provider.logo, alt: "", width: 300, height: 150, className: twMerge('mx-auto h-auto w-full', classNames.thumbnailImage) }) }, provider.id))) }) })] }));
|
|
47
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { GameProvider } from '@opexa/portal-sdk-core';
|
|
2
|
+
import type { GameProviderData } from '../../types';
|
|
3
|
+
export interface ClassNameEntries {
|
|
4
|
+
root?: string;
|
|
5
|
+
thumbnailRoot?: string;
|
|
6
|
+
thumbnailImage?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface GameProvidersListProps {
|
|
9
|
+
layout: 'list';
|
|
10
|
+
gameProviders: GameProvider[];
|
|
11
|
+
heading?: string;
|
|
12
|
+
/**
|
|
13
|
+
* @default '/providers/<slug>'
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* '/bingo/:slug' // '/bingo/jili'
|
|
17
|
+
* '/bingo/:id' // '/bingo/JILI'
|
|
18
|
+
* // or using a function
|
|
19
|
+
* ({slug}) => `/bingo/${slug}`
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
viewGamesUrl?: string | ((gameProvider: GameProviderData) => string);
|
|
23
|
+
className?: string | ClassNameEntries;
|
|
24
|
+
}
|
|
25
|
+
export declare function GameProvidersList(props: GameProvidersListProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { isString, noop } from 'lodash-es';
|
|
4
|
+
import Image from 'next/image';
|
|
5
|
+
import Link from 'next/link';
|
|
6
|
+
import { twMerge } from 'tailwind-merge';
|
|
7
|
+
import { useChunk } from '../../client/hooks/index.js';
|
|
8
|
+
import { GAME_PROVIDER_DATA } from '../../constants/index.js';
|
|
9
|
+
import { Button, Progress } from '../../ui/index.js';
|
|
10
|
+
import { callIfFn } from '../../utils/index.js';
|
|
11
|
+
export function GameProvidersList(props) {
|
|
12
|
+
const viewGamesUrl = (data) => {
|
|
13
|
+
return props.viewGamesUrl
|
|
14
|
+
? callIfFn(props.viewGamesUrl, data)
|
|
15
|
+
.replace(':id', data.id)
|
|
16
|
+
.replace(':slug', data.slug)
|
|
17
|
+
: `/providers/${data.slug}`;
|
|
18
|
+
};
|
|
19
|
+
const gameProviders = props.gameProviders.map((provider) => GAME_PROVIDER_DATA[provider]);
|
|
20
|
+
const classNames = isString(props.className)
|
|
21
|
+
? { root: props.className }
|
|
22
|
+
: (props.className ?? {});
|
|
23
|
+
const chunked = useChunk(gameProviders, 18);
|
|
24
|
+
return (_jsxs("div", { className: classNames.root, children: [_jsx("h2", { className: "text-lg font-semibold", children: props.heading ?? 'Providers' }), _jsx("div", { className: "mt-lg grid grid-cols-3 gap-1.5 lg:grid-cols-6 lg:gap-2.5", children: chunked.loadedItems.map((provider) => (_jsx(Link, { href: viewGamesUrl(provider), className: twMerge('bg-gray-800 flex h-full w-full items-center overflow-hidden rounded-md lg:h-[5.75rem]', classNames.thumbnailRoot), "aria-label": `View ${provider.name} games`, children: _jsx(Image, { src: provider.logo, alt: "", width: 300, height: 150, className: twMerge('mx-auto h-auto w-full', classNames.thumbnailImage) }) }, provider.id))) }), _jsxs("div", { className: "mt-2xl flex flex-col items-center lg:mt-3xl", children: [_jsx(Progress.Root, { min: 0, max: chunked.totalItems, value: chunked.totalLoadedItems, onValueChange: noop, className: "w-[12.5rem]", children: _jsx(Progress.Track, { className: "bg-bg-tertiary", children: _jsx(Progress.Range, {}) }) }), _jsx("p", { className: "text-button-tertiary-fg mt-md text-sm", children: `Displaying ${chunked.totalLoadedItems} of ${chunked.totalItems}` }), chunked.hasNext && (_jsx(Button, { size: "sm", variant: "outline", fullWidth: false, onClick: chunked.next, className: "mt-lg", children: "Load More" }))] })] }));
|
|
25
|
+
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
interface ClassNameEntries {
|
|
2
|
+
root?: string;
|
|
3
|
+
title?: string;
|
|
4
|
+
}
|
|
1
5
|
export interface GameProps {
|
|
2
6
|
badge?: 'top' | 'new' | 'popular';
|
|
3
|
-
|
|
7
|
+
className?: string | ClassNameEntries;
|
|
4
8
|
}
|
|
5
9
|
export declare function Game(props: GameProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { isString } from 'lodash-es';
|
|
2
3
|
import Image from 'next/image';
|
|
3
4
|
import { twMerge } from 'tailwind-merge';
|
|
4
5
|
import { useFavoriteGamesQuery, useMarkGameAsFavoriteMutation, useSessionQuery, useUnmarkGameAsFavoriteMutation, } from '../../client/hooks/index.js';
|
|
@@ -7,7 +8,7 @@ import { GameLaunchTrigger } from '../GameLaunch/index.js';
|
|
|
7
8
|
import { BadgeNew } from './BadgeNew.js';
|
|
8
9
|
import { BadgePopular } from './BadgePopular.js';
|
|
9
10
|
import { BadgeTop } from './BadgeTop.js';
|
|
10
|
-
import { useGameContext } from './
|
|
11
|
+
import { useGameContext } from './GamesContext.js';
|
|
11
12
|
export function Game(props) {
|
|
12
13
|
const game = useGameContext();
|
|
13
14
|
const sessionQuery = useSessionQuery();
|
|
@@ -17,7 +18,10 @@ export function Game(props) {
|
|
|
17
18
|
const markGameAsFavoriteMutation = useMarkGameAsFavoriteMutation();
|
|
18
19
|
const unmarkGameAsFavoriteMutation = useUnmarkGameAsFavoriteMutation();
|
|
19
20
|
const markedAsFavorite = favoriteGames.some((favoriteGame) => favoriteGame.id === game.id);
|
|
20
|
-
|
|
21
|
+
const classNames = isString(props.className)
|
|
22
|
+
? { root: props.className }
|
|
23
|
+
: (props.className ?? {});
|
|
24
|
+
return (_jsxs(GameLaunchTrigger, { game: game, className: twMerge('animate-scale-in relative block w-full shadow-sm', classNames.root), children: [props.badge === 'new' && (_jsx(BadgeNew, { className: "absolute left-0 top-0 size-[3.75rem]" })), props.badge === 'top' && (_jsx(BadgeTop, { className: "absolute left-0 top-0 size-[3.75rem]" })), props.badge === 'popular' && (_jsx(BadgePopular, { className: "absolute left-0 top-0 size-[3.75rem]" })), session?.status === 'authenticated' && (_jsx("div", { role: "button", onClick: (e) => {
|
|
21
25
|
e.preventDefault();
|
|
22
26
|
e.stopPropagation();
|
|
23
27
|
if (markGameAsFavoriteMutation.isPending)
|
|
@@ -33,5 +37,5 @@ export function Game(props) {
|
|
|
33
37
|
}, "aria-disabled": markGameAsFavoriteMutation.isPending ||
|
|
34
38
|
unmarkGameAsFavoriteMutation.isPending, className: "rounded-xs absolute right-2 top-2 flex size-9 items-center justify-center bg-black/65 blur-[0.5px]", children: _jsx(Star01Icon, { className: twMerge('size-5', markedAsFavorite
|
|
35
39
|
? 'fill-yellow-400 text-yellow-400'
|
|
36
|
-
: 'text-white') }) })), _jsx(Image, { src: game.image, alt: "", width: 200, height: 200, priority: true, className: "aspect-square w-full rounded-t-md object-cover" }), _jsx("span", { className: twMerge('bg-bg-tertiary text-text-primary-brand block w-full truncate rounded-b-md px-2 py-3.5 text-center text-xs font-semibold',
|
|
40
|
+
: 'text-white') }) })), _jsx(Image, { src: game.image, alt: "", width: 200, height: 200, priority: true, className: "aspect-square w-full rounded-t-md object-cover" }), _jsx("span", { className: twMerge('bg-bg-tertiary text-text-primary-brand block w-full truncate rounded-b-md px-2 py-3.5 text-center text-xs font-semibold', classNames.title), children: game.name })] }));
|
|
37
41
|
}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
1
|
import { type GamesCarouselProps } from './GamesCarousel';
|
|
2
2
|
import { type GamesListProps } from './GamesList';
|
|
3
|
-
export type GamesProps =
|
|
4
|
-
layout: 'list';
|
|
5
|
-
} & GamesListProps) | ({
|
|
6
|
-
layout?: 'carousel';
|
|
7
|
-
} & GamesCarouselProps);
|
|
3
|
+
export type GamesProps = GamesListProps | GamesCarouselProps;
|
|
8
4
|
export declare function Games(props: GamesProps): Promise<import("react/jsx-runtime").JSX.Element>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import useEmblaCarousel, {} from 'embla-carousel-react';
|
|
4
|
+
import { isString } from 'lodash-es';
|
|
4
5
|
import Link from 'next/link';
|
|
5
6
|
import { useCallback, useEffect, useState } from 'react';
|
|
6
7
|
import { twMerge } from 'tailwind-merge';
|
|
@@ -9,7 +10,7 @@ import { ArrowLeftIcon, ArrowRightIcon, ChevronRightIcon, GamingPad01Icon, Spinn
|
|
|
9
10
|
import { Button } from '../../ui/index.js';
|
|
10
11
|
import { Empty } from '../Empty.js';
|
|
11
12
|
import { Game } from './Game.js';
|
|
12
|
-
import { GameContext } from './
|
|
13
|
+
import { GameContext } from './GamesContext.js';
|
|
13
14
|
export function GamesCarousel__client(props) {
|
|
14
15
|
const numOfRows = props.numOfRows ?? 1;
|
|
15
16
|
const gamesQuery = useGamesQuery({
|
|
@@ -51,11 +52,17 @@ export function GamesCarousel__client(props) {
|
|
|
51
52
|
onSelect(emblaApi);
|
|
52
53
|
emblaApi.on('reInit', onSelect).on('select', onSelect);
|
|
53
54
|
}, [emblaApi, onSelect]);
|
|
54
|
-
|
|
55
|
+
const classNames = isString(props.className)
|
|
56
|
+
? { root: props.className }
|
|
57
|
+
: (props.className ?? {});
|
|
58
|
+
return (_jsxs("div", { className: classNames.root, children: [_jsxs("div", { className: "flex items-center", children: [_jsx("h2", { className: "text-lg font-semibold", children: props.heading ?? 'Games' }), _jsx("div", { className: "grow" }), _jsxs("div", { className: "flex items-center justify-center gap-xl", children: [_jsxs(Link, { href: props.viewAllUrl ?? '/games', className: "text-button-tertiary-fg flex gap-sm text-sm font-semibold", children: ["See All", _jsx(ChevronRightIcon, { className: "size-5 lg:hidden" })] }), _jsxs("div", { className: "hidden lg:flex", children: [_jsx(Button, { variant: "outline", colorScheme: "gray", className: "rounded-r-none border-r-0", onClick: onPrevButtonClick, disabled: prevBtnDisabled, "aria-label": "Previous", children: _jsx(ArrowLeftIcon, { className: "size-5" }) }), _jsx(Button, { variant: "outline", colorScheme: "gray", className: "rounded-l-none", onClick: onNextButtonClick, disabled: nextBtnDisabled && !gamesQuery.hasNextPage
|
|
55
59
|
? true
|
|
56
60
|
: gamesQuery.isFetchingNextPage, "aria-label": "Next", children: gamesQuery.isFetchingNextPage ? (_jsx(SpinnerIcon, { className: "size-5" })) : (_jsx(ArrowRightIcon, { className: "size-5" })) })] })] })] }), games.length <= 0 && (_jsx(Empty, { icon: GamingPad01Icon, title: "No games", message: "No game is currently available. Please check back later", className: "mt-lg" })), games.length >= 1 && (_jsx("div", { ref: emblaRef, className: "relative mt-lg lg:overflow-hidden", children: _jsx("div", { className: twMerge('grid auto-cols-[calc((100%-(0.375rem*2))/3)] grid-flow-col gap-sm lg:auto-cols-[calc((100%-(0.5rem*5))/6)] lg:gap-md', numOfRows === 3
|
|
57
61
|
? 'grid-rows-3'
|
|
58
62
|
: numOfRows === 2
|
|
59
63
|
? 'grid-rows-2'
|
|
60
|
-
: 'grid-rows-1'), children: games.map((game) => (_jsx(GameContext, { value: game, children: _jsx(Game, { badge: props.badge,
|
|
64
|
+
: 'grid-rows-1'), children: games.map((game) => (_jsx(GameContext, { value: game, children: _jsx(Game, { badge: props.badge, className: {
|
|
65
|
+
root: classNames.thumbnailRoot,
|
|
66
|
+
title: classNames.thumbnailTitle,
|
|
67
|
+
} }) }, game.id))) }) }))] }));
|
|
61
68
|
}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { GamesInput__Next } from '@opexa/portal-sdk-core';
|
|
2
|
+
export interface ClassNameEntries {
|
|
3
|
+
root?: string;
|
|
4
|
+
thumbnailRoot?: string;
|
|
5
|
+
thumbnailTitle?: string;
|
|
6
|
+
}
|
|
2
7
|
export interface GamesCarouselProps {
|
|
8
|
+
layout: 'carousel';
|
|
3
9
|
/** @default "Games" */
|
|
4
10
|
heading?: string;
|
|
5
11
|
/**
|
|
@@ -13,7 +19,6 @@ export interface GamesCarouselProps {
|
|
|
13
19
|
filter?: GamesInput__Next['filter'];
|
|
14
20
|
search?: string;
|
|
15
21
|
sort?: GamesInput__Next['sort'];
|
|
16
|
-
className?: string;
|
|
17
|
-
gameNameClass?: string;
|
|
22
|
+
className?: string | ClassNameEntries;
|
|
18
23
|
}
|
|
19
24
|
export declare function GamesCarousel(props: GamesCarouselProps): Promise<import("react/jsx-runtime").JSX.Element>;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Game } from '@opexa/portal-sdk-core';
|
|
2
|
+
import type { GamesProps } from './Games';
|
|
3
|
+
export declare const GamesPropsContext: import("react").Context<GamesProps>, useGamesPropsContext: () => GamesProps;
|
|
4
|
+
export declare const GameContext: import("react").Context<Game>, useGameContext: () => Game;
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { noop } from 'lodash-es';
|
|
3
|
+
import { isString, noop } from 'lodash-es';
|
|
4
4
|
import { useGamesQuery, useInfiniteQueryHelper } from '../../client/hooks/index.js';
|
|
5
5
|
import { GamingPad01Icon, SpinnerIcon } from '../../icons/index.js';
|
|
6
6
|
import { Button, Progress } from '../../ui/index.js';
|
|
7
7
|
import { Empty } from '../Empty.js';
|
|
8
8
|
import { Game } from './Game.js';
|
|
9
|
-
import { GameContext } from './
|
|
9
|
+
import { GameContext } from './GamesContext.js';
|
|
10
10
|
export function GamesList__client(props) {
|
|
11
11
|
const { loading, availableRows, totalRows, totalAvailableRows, hasNextPage, next, } = useInfiniteQueryHelper(useGamesQuery, {
|
|
12
12
|
first: props.first ?? 24,
|
|
@@ -14,7 +14,13 @@ export function GamesList__client(props) {
|
|
|
14
14
|
search: props.search,
|
|
15
15
|
sort: props.sort,
|
|
16
16
|
});
|
|
17
|
-
|
|
17
|
+
const classNames = isString(props.className)
|
|
18
|
+
? { root: props.className }
|
|
19
|
+
: (props.className ?? {});
|
|
20
|
+
return (_jsxs("div", { className: classNames.root, children: [_jsx("h2", { className: "text-lg font-semibold", children: props.heading ?? 'Games' }), totalRows <= 0 && (_jsx(Empty, { icon: loading ? SpinnerIcon : GamingPad01Icon, title: loading ? 'Just a moment' : 'No games', message: loading
|
|
18
21
|
? 'Fetching latest games...'
|
|
19
|
-
: 'No game is currently available. Please check back later', className: "mt-lg" })), totalRows >= 1 && (_jsxs(_Fragment, { children: [_jsx("div", { className: "mt-lg grid grid-cols-3 gap-1.5 lg:grid-cols-6 lg:gap-2.5", children: availableRows.map((game) => (_jsx(GameContext, { value: game, children: _jsx(Game, { badge: props.badge,
|
|
22
|
+
: 'No game is currently available. Please check back later', className: "mt-lg" })), totalRows >= 1 && (_jsxs(_Fragment, { children: [_jsx("div", { className: "mt-lg grid grid-cols-3 gap-1.5 lg:grid-cols-6 lg:gap-2.5", children: availableRows.map((game) => (_jsx(GameContext, { value: game, children: _jsx(Game, { badge: props.badge, className: {
|
|
23
|
+
root: classNames.thumbnailRoot,
|
|
24
|
+
title: classNames.thumbnailTitle,
|
|
25
|
+
} }) }, game.id))) }), _jsxs("div", { className: "mt-2xl flex flex-col items-center lg:mt-3xl", children: [_jsx(Progress.Root, { min: 0, max: totalRows, value: totalAvailableRows, onValueChange: noop, className: "w-[12.5rem]", children: _jsx(Progress.Track, { className: "bg-bg-tertiary", children: _jsx(Progress.Range, {}) }) }), _jsx("p", { className: "text-button-tertiary-fg mt-md text-sm", children: `Displaying ${totalAvailableRows} of ${totalRows}` }), hasNextPage && (_jsx(Button, { size: "sm", variant: "outline", fullWidth: false, onClick: next, className: "mt-lg", children: "Load More" }))] })] }))] }));
|
|
20
26
|
}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { GamesInput__Next } from '@opexa/portal-sdk-core';
|
|
2
|
+
export interface ClassNameEntries {
|
|
3
|
+
root?: string;
|
|
4
|
+
thumbnailRoot?: string;
|
|
5
|
+
thumbnailTitle?: string;
|
|
6
|
+
}
|
|
2
7
|
export interface GamesListProps {
|
|
8
|
+
layout: 'list';
|
|
3
9
|
badge?: 'top' | 'new' | 'popular';
|
|
4
10
|
/** @default 24 */
|
|
5
11
|
first?: number;
|
|
@@ -8,7 +14,6 @@ export interface GamesListProps {
|
|
|
8
14
|
search?: string;
|
|
9
15
|
/** @default "Games"*/
|
|
10
16
|
heading?: string;
|
|
11
|
-
className?: string;
|
|
12
|
-
gameNameClass?: string;
|
|
17
|
+
className?: string | ClassNameEntries;
|
|
13
18
|
}
|
|
14
19
|
export declare function GamesList(props: GamesListProps): Promise<import("react/jsx-runtime").JSX.Element>;
|
|
@@ -1,15 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
/** @default "/promos" */
|
|
5
|
-
viewAllUrl?: string;
|
|
6
|
-
/** @default "/promos" */
|
|
7
|
-
viewPromoDetailsUrl?: string;
|
|
8
|
-
/** @default "/promos/cashback" */
|
|
9
|
-
viewCashbackDetailsUrl?: string;
|
|
10
|
-
/** @default 1 */
|
|
11
|
-
className?: string;
|
|
12
|
-
/** @default 'carousel' */
|
|
13
|
-
layout?: 'carousel' | 'grid';
|
|
14
|
-
}
|
|
1
|
+
import { type PromosCarouselProps } from './PromosCarousel';
|
|
2
|
+
import { type PromosGridProps } from './PromosGrid';
|
|
3
|
+
export type PromosProps = PromosCarouselProps | PromosGridProps;
|
|
15
4
|
export declare function Promos(props: PromosProps): Promise<import("react/jsx-runtime").JSX.Element>;
|
|
@@ -1,2 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export interface PromosCarouselProps {
|
|
2
|
+
layout: 'carousel';
|
|
3
|
+
/** @default "Promotions" */
|
|
4
|
+
heading?: string;
|
|
5
|
+
/** @default "/promos" */
|
|
6
|
+
viewAllUrl?: string;
|
|
7
|
+
/** @default "/promos" */
|
|
8
|
+
viewPromoDetailsUrl?: string;
|
|
9
|
+
/** @default "/promos/cashback" */
|
|
10
|
+
viewCashbackDetailsUrl?: string;
|
|
11
|
+
className?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function PromosCarousel(props: PromosCarouselProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,2 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
export interface PromosGridProps {
|
|
2
|
+
layout: 'grid';
|
|
3
|
+
/** @default "Promotions" */
|
|
4
|
+
heading?: string;
|
|
5
|
+
/** @default "/promos" */
|
|
6
|
+
viewPromoDetailsUrl?: string;
|
|
7
|
+
/** @default "/promos/cashback" */
|
|
8
|
+
viewCashbackDetailsUrl?: string;
|
|
9
|
+
className?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function PromosGrid(props: PromosGridProps): import("react/jsx-runtime").JSX.Element;
|