pixi-rainman-game-engine 0.1.19 → 0.1.21
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/README.md +10 -16
- package/dist/SettingsUI/SystemSettings/SystemSettingsComponent.d.ts +0 -1
- package/dist/SettingsUI/SystemSettings/SystemSettingsComponent.jsx +7 -6
- package/dist/SettingsUI/components/AutoplaySettings/index.d.ts +0 -1
- package/dist/SettingsUI/components/AutoplaySettings/index.jsx +26 -38
- package/dist/SettingsUI/components/Bet/BetControls.d.ts +0 -1
- package/dist/SettingsUI/components/Bet/BetControls.jsx +9 -9
- package/dist/SettingsUI/components/Bet/index.d.ts +0 -1
- package/dist/SettingsUI/components/Bet/index.jsx +1 -3
- package/dist/SettingsUI/components/Button/index.d.ts +2 -0
- package/dist/SettingsUI/components/Button/index.jsx +6 -0
- package/dist/SettingsUI/components/BuyFreeSpins/index.d.ts +0 -1
- package/dist/SettingsUI/components/BuyFreeSpins/index.jsx +6 -6
- package/dist/SettingsUI/components/CloseModalButton/index.d.ts +0 -1
- package/dist/SettingsUI/components/CloseModalButton/index.jsx +3 -3
- package/dist/SettingsUI/components/GameRules/index.d.ts +0 -1
- package/dist/SettingsUI/components/GameRules/index.jsx +11 -13
- package/dist/SettingsUI/components/Modal/index.d.ts +10 -0
- package/dist/SettingsUI/components/Modal/index.jsx +24 -0
- package/dist/SettingsUI/components/OptionButton/index.jsx +1 -1
- package/dist/SettingsUI/components/RichLimitingSlider/index.d.ts +0 -1
- package/dist/SettingsUI/components/RichLimitingSlider/index.jsx +8 -8
- package/dist/SettingsUI/components/SlidingSwitch/index.d.ts +0 -1
- package/dist/SettingsUI/components/SlidingSwitch/index.jsx +4 -5
- package/dist/SettingsUI/components/SpeedSettingsPopup/index.d.ts +0 -1
- package/dist/SettingsUI/components/SpeedSettingsPopup/index.jsx +6 -6
- package/dist/SettingsUI/components/SpeedSwitchButton/index.jsx +6 -5
- package/dist/SettingsUI/components/SwitchWithHeader/index.d.ts +0 -1
- package/dist/SettingsUI/components/SwitchWithHeader/index.jsx +5 -6
- package/dist/SettingsUI/components/SymbolMultiplierPopup/index.d.ts +1 -2
- package/dist/SettingsUI/components/SymbolMultiplierPopup/index.jsx +17 -15
- package/dist/SettingsUI/components/UXSettings/index.d.ts +0 -1
- package/dist/SettingsUI/components/UXSettings/index.jsx +8 -21
- package/dist/SettingsUI/components/VolumeSettings/index.d.ts +0 -1
- package/dist/SettingsUI/components/VolumeSettings/index.jsx +4 -5
- package/dist/SettingsUI/hooks/index.d.ts +1 -0
- package/dist/SettingsUI/hooks/index.js +1 -0
- package/dist/SettingsUI/hooks/useClickOutside.d.ts +6 -0
- package/dist/SettingsUI/hooks/useClickOutside.js +20 -0
- package/dist/SettingsUI/index.css +46 -26
- package/dist/SettingsUI/index.d.ts +1 -1
- package/dist/SettingsUI/index.jsx +15 -14
- package/dist/SettingsUI/packedStyles.css +1617 -0
- package/dist/SettingsUI/utils/tw.d.ts +2 -0
- package/dist/SettingsUI/utils/tw.js +3 -0
- package/dist/application/ApiConfig/ApiConfig.d.ts +1 -1
- package/dist/application/ApiConfig/ApiConfig.js +2 -2
- package/dist/application/setup.js +1 -1
- package/dist/components/AbstractMainContainer/AbstractMainContainer.js +3 -2
- package/dist/components/dictionary/locales/en.json +2 -1
- package/dist/components/messageBox/MessageBox.js +10 -6
- package/dist/components/symbols/AbstractSymbolsColumn.js +3 -5
- package/dist/connectivity/serverData.d.ts +20 -0
- package/dist/controllers/AbstractController.d.ts +1 -0
- package/dist/controllers/AbstractController.js +12 -0
- package/dist/stores/SettingsStore.d.ts +5 -0
- package/dist/stores/SettingsStore.js +11 -0
- package/dist/utils/common/screenHelpers.js +1 -1
- package/package.json +9 -4
- package/dist/SettingsUI/SystemSettings/systemSettings.css +0 -41
- package/dist/SettingsUI/components/AutoplaySettings/autoplaySettings.css +0 -267
- package/dist/SettingsUI/components/Bet/bet.css +0 -104
- package/dist/SettingsUI/components/BuyFreeSpins/buyFreeSpin.css +0 -46
- package/dist/SettingsUI/components/CloseModalButton/closeModalButton.css +0 -20
- package/dist/SettingsUI/components/GameRules/gameRules.css +0 -96
- package/dist/SettingsUI/components/RichLimitingSlider/richLimitingSlider.css +0 -39
- package/dist/SettingsUI/components/SlidingSwitch/slidingSwitch.css +0 -126
- package/dist/SettingsUI/components/SpeedSettingsPopup/speedSettingsPopup.css +0 -119
- package/dist/SettingsUI/components/SwitchWithHeader/headerStyle.css +0 -28
- package/dist/SettingsUI/components/SymbolMultiplierPopup/symbolPopup.css +0 -101
- package/dist/SettingsUI/components/UXSettings/UXSettings.css +0 -28
- package/dist/SettingsUI/components/VolumeSettings/volume.css +0 -54
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# RainMan pixi game engine
|
|
2
2
|
|
|
3
|
-
This repository contains all
|
|
3
|
+
This repository contains all the mechanics that used in RainMan games. This library uses pixi and pixi-spine as dependencies.
|
|
4
4
|
|
|
5
5
|
### Scripts
|
|
6
6
|
|
|
@@ -16,19 +16,20 @@ This repository contains all of the mechanics that used in rainMan games. This l
|
|
|
16
16
|
|
|
17
17
|
Modifying css files does not automatically reload server, after each change manual restart is needed.
|
|
18
18
|
|
|
19
|
-
To have live updates in one of the games, link is recommended
|
|
19
|
+
To have live updates in one of the games, link is recommended. It needs to be done just once, yarn will remember link to this package even after computer restart.
|
|
20
20
|
|
|
21
21
|
```shell
|
|
22
|
-
yarn
|
|
22
|
+
yarn link
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
-
After that
|
|
25
|
+
After that use the following command in one of the games to use local version of the engine.
|
|
26
26
|
|
|
27
27
|
```sh
|
|
28
|
-
yarn
|
|
29
|
-
npm link pixi-rainman-game-engine
|
|
28
|
+
yarn link pixi-rainman-game-engine
|
|
30
29
|
```
|
|
31
30
|
|
|
31
|
+
Link is common to cause bugs when used together with npm version of the same package, that is why you should use helper commands engine:local and engine:npm in the games. If there are still some bugs (most common with pixi/layers) try deleting node_modules, installing dependencies without engine, linking engine and restart server. This should resolve all the problems.
|
|
32
|
+
|
|
32
33
|
By using package from npm, in vite optimizeDeps you must exclude this package, but must include each package that throws error in the console. This is probably due to problem with [excluding commonJS dependencies](https://vitejs.dev/config/dep-optimization-options#optimizedeps-exclude). An example is below.
|
|
33
34
|
|
|
34
35
|
```ts
|
|
@@ -60,9 +61,7 @@ This repository contains all of the mechanics that used in rainMan games. This l
|
|
|
60
61
|
Uncaught SyntaxError: The requested module '/node_modules/eventemitter3/index.js?v=ec22a584' does not provide an export named 'default'
|
|
61
62
|
```
|
|
62
63
|
|
|
63
|
-
you must include it in the optimizeDeps.include array. Typically it is the name after /node_modules/.
|
|
64
|
-
|
|
65
|
-
**On the other hand, when linking package with npm link, the whole optimizeDeps.include an optimzieDeps.exclude should be commented out.**
|
|
64
|
+
you must include it in the optimizeDeps.include array. Typically, it is the name after /node_modules/.
|
|
66
65
|
|
|
67
66
|
3. Lint project
|
|
68
67
|
```sh
|
|
@@ -71,11 +70,6 @@ This repository contains all of the mechanics that used in rainMan games. This l
|
|
|
71
70
|
|
|
72
71
|
### Game engine structure
|
|
73
72
|
|
|
74
|
-
Code for the game engine contains in the `src` directory. For
|
|
75
|
-
|
|
76
|
-
In utils directory there all of the utility functions and types.
|
|
77
|
-
|
|
78
|
-
### Test environment
|
|
73
|
+
Code for the game engine contains in the `src` directory. For creating a feature you should add new directory into `src` directory. For example: `freeSpins` and in this folder contains all the mechanics.
|
|
79
74
|
|
|
80
|
-
|
|
81
|
-
Test environment uses local built of game engine. To setup test environment go to [README](./test-environment/README.md) of test environment.
|
|
75
|
+
In utils directory there all the utility functions and types.
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import "./systemSettings.css";
|
|
2
1
|
import i18next from "i18next";
|
|
3
2
|
import React from "react";
|
|
4
3
|
import { UI_ITEMS } from "../../utils";
|
|
5
4
|
import { BetSettings, CloseModalButton, UXSettings } from "../components";
|
|
5
|
+
import { useDeviceOrientations } from "../hooks";
|
|
6
6
|
export const SystemSettingsComponent = () => {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
const deviceOrientation = useDeviceOrientations();
|
|
8
|
+
return (<div className="flex w-full max-w-lg flex-col justify-center gap-2 p-4">
|
|
9
|
+
<div className="flex w-full justify-center">
|
|
10
|
+
<h2 className="text-2xl font-bold uppercase text-primary-500">{i18next.t("systemSettings")}</h2>
|
|
10
11
|
</div>
|
|
11
12
|
<CloseModalButton layerId={UI_ITEMS.settings}/>
|
|
12
|
-
<div className="
|
|
13
|
-
<BetSettings className="bet-desktop__container"/>
|
|
13
|
+
<div className="flex w-full flex-col justify-center">
|
|
14
14
|
<UXSettings />
|
|
15
|
+
{!deviceOrientation.includes("mobile") ? <BetSettings className="flex w-full justify-center"/> : null}
|
|
15
16
|
</div>
|
|
16
17
|
</div>);
|
|
17
18
|
};
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import "react-custom-scroll/dist/customScroll.css";
|
|
2
|
-
import "./autoplaySettings.css";
|
|
3
2
|
import i18next from "i18next";
|
|
4
3
|
import { observer } from "mobx-react-lite";
|
|
5
4
|
import React, { useEffect, useState } from "react";
|
|
6
5
|
import { COMPONENTS } from "../../../components";
|
|
7
6
|
import { UI_ITEMS } from "../../../utils";
|
|
8
7
|
import { useStores } from "../../hooks";
|
|
8
|
+
import { cn } from "../../utils/tw";
|
|
9
|
+
import { Button } from "../Button";
|
|
9
10
|
import { CloseModalButton } from "../CloseModalButton";
|
|
10
11
|
import { RichLimitingSlider } from "../RichLimitingSlider";
|
|
11
12
|
import { SpeedButtonWithHeader, SwitchWithHeader } from "../SwitchWithHeader";
|
|
12
13
|
export const AutoplaySettings = observer(() => {
|
|
13
|
-
const [
|
|
14
|
+
const [limitNumbers, setLimitNumbers] = useState([0]);
|
|
14
15
|
const initialAutoSpinCount = 50;
|
|
15
16
|
const availableAutoSpinLimits = [10, 20, 50, 100, 150, 200, 250, 300, 350, 400, 500, 600, 700, 800, 900, 1000];
|
|
16
17
|
const { settingStore } = useStores();
|
|
@@ -50,28 +51,24 @@ export const AutoplaySettings = observer(() => {
|
|
|
50
51
|
updateLimitsBounds(initialAutoSpinCount);
|
|
51
52
|
}, []);
|
|
52
53
|
const { singleWinExceeds, balancedIncreased, balancedDecreased, howManyAutoSpinsLeft, infinitySpinsEnabled, setSingleWinExceeds, setBalancedIncreased, setBalancedDecreased, setAutoSpinsCount, flipInfinitySpinsFlag, resetAutoplaySettings, } = settingStore;
|
|
53
|
-
return (<div className="
|
|
54
|
+
return (<div className="flex w-full max-w-xs flex-col items-center justify-between gap-8 p-4 sm:max-w-md">
|
|
54
55
|
<CloseModalButton layerId={UI_ITEMS.autoplay}/>
|
|
55
|
-
<
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
<div className="autoplay-settings__stop-limits">
|
|
59
|
-
<div className={`autoplay-settings__limit left ${infinitySpinsEnabled ? "autoplay-settings__limit--infinity" : ""}`} onClick={() => {
|
|
56
|
+
<h2 className="text-center text-3xl font-bold text-primary-500">{i18next.t("autoPlay")}</h2>
|
|
57
|
+
<div className="flex h-12 w-full flex-wrap items-center justify-center gap-2 sm:max-w-72 sm:flex-nowrap">
|
|
58
|
+
<Button className="flex rounded bg-zinc-800 px-3 py-1 text-lg shadow shadow-primary-500/40 hover:bg-zinc-500 disabled:cursor-not-allowed disabled:bg-zinc-700" onClick={() => {
|
|
60
59
|
let indexOfSelectedSpinsLimit = availableAutoSpinLimits.findIndex((limitCount) => limitCount === howManyAutoSpinsLeft);
|
|
61
60
|
indexOfSelectedSpinsLimit -= 1;
|
|
62
61
|
if (indexOfSelectedSpinsLimit === -1) {
|
|
63
62
|
indexOfSelectedSpinsLimit = availableAutoSpinLimits.length - 1;
|
|
64
63
|
}
|
|
65
64
|
updateLimitsBounds(availableAutoSpinLimits[indexOfSelectedSpinsLimit]);
|
|
66
|
-
}}>
|
|
65
|
+
}} disabled={infinitySpinsEnabled}>
|
|
67
66
|
<p>-</p>
|
|
68
|
-
</
|
|
69
|
-
{
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
})}
|
|
74
|
-
<div className={`autoplay-settings__limit right ${infinitySpinsEnabled ? "autoplay-settings__limit--infinity" : ""}`} onClick={() => {
|
|
67
|
+
</Button>
|
|
68
|
+
{limitNumbers.map((limiter) => (<Button key={limiter} value={limiter} className={cn("flex items-center justify-center rounded bg-zinc-800 px-5 py-1 text-lg shadow shadow-primary-500/40 hover:bg-zinc-600 disabled:cursor-not-allowed disabled:bg-zinc-700 disabled:text-zinc-500", { "border-2 border-primary-500": limiter === howManyAutoSpinsLeft })} disabled={infinitySpinsEnabled} onClick={(event) => updateLimitsBounds(Number(event.currentTarget.value))}>
|
|
69
|
+
<p>{limiter}</p>
|
|
70
|
+
</Button>))}
|
|
71
|
+
<Button className="flex rounded bg-zinc-800 px-3 py-1 text-lg shadow shadow-primary-500/40 hover:bg-zinc-500 disabled:cursor-not-allowed disabled:bg-zinc-700 disabled:text-zinc-500" onClick={() => {
|
|
75
72
|
let indexOfSelectedSpinsLimit = availableAutoSpinLimits.findIndex((limitCount) => limitCount === howManyAutoSpinsLeft);
|
|
76
73
|
indexOfSelectedSpinsLimit += 1;
|
|
77
74
|
if (indexOfSelectedSpinsLimit === availableAutoSpinLimits.length) {
|
|
@@ -79,43 +76,34 @@ export const AutoplaySettings = observer(() => {
|
|
|
79
76
|
}
|
|
80
77
|
const newAutoSpinsLimitNumber = availableAutoSpinLimits[indexOfSelectedSpinsLimit];
|
|
81
78
|
updateLimitsBounds(newAutoSpinsLimitNumber);
|
|
82
|
-
}}>
|
|
79
|
+
}} disabled={infinitySpinsEnabled}>
|
|
83
80
|
<p>+</p>
|
|
84
|
-
</
|
|
85
|
-
<
|
|
81
|
+
</Button>
|
|
82
|
+
<Button className={"flex rounded bg-zinc-800 px-3 py-1 text-lg shadow shadow-primary-500/40 hover:bg-zinc-500 disabled:cursor-not-allowed disabled:bg-zinc-700"} onClick={() => flipInfinitySpinsFlag()}>
|
|
86
83
|
<p>∞</p>
|
|
87
|
-
</
|
|
84
|
+
</Button>
|
|
88
85
|
</div>
|
|
89
|
-
|
|
90
|
-
<div className="autoplay-settings__title">
|
|
91
|
-
<h2>{i18next.t("stopAutoPlay")}</h2>
|
|
92
|
-
</div>
|
|
93
|
-
<div className="autoplay-settings__sliders">
|
|
86
|
+
<div className="flex w-full max-w-3xl flex-col justify-around gap-4">
|
|
94
87
|
<RichLimitingSlider value={singleWinExceeds} setValue={setSingleWinExceeds} maxValue={Number(i18next.t("ifSingleWinExceedsMax"))} description={i18next.t("ifSingleWinExceedsMaxDescription")}/>
|
|
95
88
|
<RichLimitingSlider value={balancedIncreased} setValue={setBalancedIncreased} maxValue={Number(i18next.t("ifBalanceIncreasesBy"))} description={i18next.t("ifBalanceIncreasesByDescription")}/>
|
|
96
89
|
<RichLimitingSlider value={balancedDecreased} setValue={setBalancedDecreased} maxValue={Number(i18next.t("ifSingleWinExceedsMax"))} description={i18next.t("ifBalanceDecreaseByDescription")}/>
|
|
97
90
|
</div>
|
|
98
91
|
|
|
99
|
-
<div className="
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
</div>
|
|
103
|
-
<div className="autoplay-settings__switch">
|
|
104
|
-
<SpeedButtonWithHeader header={i18next.t("speedButtonHeader")} description={i18next.t("speedButtonDescription")}/>
|
|
105
|
-
</div>
|
|
92
|
+
<div className="flex w-full flex-col items-center justify-between gap-2 sm:flex-row">
|
|
93
|
+
<SwitchWithHeader header={i18next.t("onAnyWin")} flag={settingStore.onAnyWin} setFlag={settingStore.setOnAnyWin}/>
|
|
94
|
+
<SpeedButtonWithHeader header={i18next.t("speedButtonHeader")} description={i18next.t("speedButtonDescription")}/>
|
|
106
95
|
</div>
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
<div className="autoplay-settings__confirmation-button" onClick={() => {
|
|
96
|
+
<div className="flex w-full items-center justify-center gap-4">
|
|
97
|
+
<Button className="flex items-center rounded-lg bg-zinc-800 px-4 py-2 text-sm hover:bg-zinc-700" onClick={() => {
|
|
110
98
|
resetAutoplaySettings();
|
|
111
99
|
updateLimitsBounds(initialAutoSpinCount);
|
|
112
100
|
settingStore.handleModalInvocation?.(UI_ITEMS.autoplay);
|
|
113
101
|
}}>
|
|
114
102
|
<p>{i18next.t("cancel")}</p>
|
|
115
|
-
</
|
|
116
|
-
<
|
|
103
|
+
</Button>
|
|
104
|
+
<Button id={COMPONENTS.autoSpinConfirm} className="flex items-center justify-center rounded-lg bg-primary-500 px-4 py-2 text-sm hover:bg-primary-600" onClick={() => settingStore.handleModalInvocation?.(UI_ITEMS.autoplay)}>
|
|
117
105
|
<p>{i18next.t("confirm")}</p>
|
|
118
|
-
</
|
|
106
|
+
</Button>
|
|
119
107
|
</div>
|
|
120
108
|
</div>);
|
|
121
109
|
});
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import "./bet.css";
|
|
2
1
|
import i18next from "i18next";
|
|
3
2
|
import { observer } from "mobx-react-lite";
|
|
4
3
|
import React from "react";
|
|
5
4
|
import { useStores } from "../../hooks";
|
|
5
|
+
import { Button } from "../Button";
|
|
6
6
|
export const BetControls = observer(() => {
|
|
7
7
|
const { settingStore } = useStores();
|
|
8
|
-
return (<div className="
|
|
9
|
-
<h2>{i18next.t("totalBet")}</h2>
|
|
10
|
-
<div className="
|
|
11
|
-
<
|
|
8
|
+
return (<div className="flex w-full flex-col items-center justify-center gap-2 p-4">
|
|
9
|
+
<h2 className="font-bold uppercase text-primary-500 sm:text-2xl">{i18next.t("totalBet")}</h2>
|
|
10
|
+
<div className="flex w-full items-center justify-center gap-4">
|
|
11
|
+
<Button className="flex h-10 w-8 items-center justify-center rounded-lg bg-primary-400 p-4 font-bold text-black shadow-md transition duration-300 hover:bg-primary-300" name="bet-minus">
|
|
12
12
|
-
|
|
13
|
-
</
|
|
14
|
-
<div className="
|
|
13
|
+
</Button>
|
|
14
|
+
<div className="flex w-fit items-center justify-center rounded-lg bg-zinc-800 px-4 py-2 text-sm sm:text-xl">
|
|
15
15
|
<p>{settingStore.betText}</p>
|
|
16
16
|
</div>
|
|
17
|
-
<
|
|
17
|
+
<Button className="flex h-10 w-8 items-center justify-center rounded-lg bg-primary-400 p-4 font-bold text-black shadow-md transition duration-300 hover:bg-primary-300" name="bet-plus">
|
|
18
18
|
+
|
|
19
|
-
</
|
|
19
|
+
</Button>
|
|
20
20
|
</div>
|
|
21
21
|
</div>);
|
|
22
22
|
});
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import "./bet.css";
|
|
2
1
|
import { observer } from "mobx-react-lite";
|
|
3
2
|
import React from "react";
|
|
4
3
|
import { UI_ITEMS } from "../../../utils";
|
|
@@ -6,9 +5,8 @@ import { useDeviceOrientations } from "../../hooks";
|
|
|
6
5
|
import { CloseModalButton } from "../CloseModalButton";
|
|
7
6
|
import { BetControls } from "./BetControls";
|
|
8
7
|
export const BetSettings = observer(({ className }) => {
|
|
9
|
-
const allClassNames = className ? `bet-container ${className}` : "bet-container";
|
|
10
8
|
const deviceOrientation = useDeviceOrientations();
|
|
11
|
-
return (<div className={
|
|
9
|
+
return (<div className={className}>
|
|
12
10
|
{deviceOrientation.includes("mobile") ? <CloseModalButton layerId={UI_ITEMS.bet}/> : null}
|
|
13
11
|
<BetControls />
|
|
14
12
|
</div>);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import "
|
|
1
|
+
import i18next from "i18next";
|
|
2
2
|
import React, { useState } from "react";
|
|
3
3
|
import { Currencies } from "ts-money";
|
|
4
4
|
import { UI_ITEMS } from "../../../utils";
|
|
@@ -10,16 +10,16 @@ export const BuyFreeSpinModal = () => {
|
|
|
10
10
|
const freeSpinOptions = useBuyFreeSpinOptions();
|
|
11
11
|
const currency = Currencies[localStorage.getItem("currency")]?.symbol_native || "$";
|
|
12
12
|
const clearErrorMessage = () => setErrorMessage("");
|
|
13
|
-
return (<div className="
|
|
13
|
+
return (<div className="flex h-[90%] w-[90%] flex-col items-center justify-center gap-4 px-5">
|
|
14
14
|
<CloseModalButton layerId={UI_ITEMS.freeSpin} afterClose={clearErrorMessage}/>
|
|
15
|
-
<div className="
|
|
16
|
-
<h1
|
|
15
|
+
<div className="flex">
|
|
16
|
+
<h1 className="text-2xl font-bold text-primary-500">{i18next.t("buyFreeSpins")}</h1>
|
|
17
17
|
</div>
|
|
18
|
-
<div className="
|
|
18
|
+
<div className="flex items-center justify-between gap-4">
|
|
19
19
|
{freeSpinOptions.map((option) => (<OptionButton key={option.amount} setMessage={setErrorMessage} option={option} currency={currency}/>))}
|
|
20
20
|
</div>
|
|
21
21
|
{errorMessage ? (<div>
|
|
22
|
-
<p className="
|
|
22
|
+
<p className="text-center text-2xl text-primary-500">{errorMessage}</p>
|
|
23
23
|
</div>) : null}
|
|
24
24
|
</div>);
|
|
25
25
|
};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import "./closeModalButton.css";
|
|
2
1
|
import React from "react";
|
|
3
2
|
import { useStores } from "../../hooks";
|
|
3
|
+
import { Button } from "../Button";
|
|
4
4
|
export const CloseModalButton = ({ layerId, afterClose }) => {
|
|
5
5
|
const { settingStore } = useStores();
|
|
6
6
|
const onClose = () => {
|
|
7
7
|
settingStore.handleModalInvocation?.(layerId);
|
|
8
8
|
afterClose?.();
|
|
9
9
|
};
|
|
10
|
-
return (<
|
|
10
|
+
return (<Button className="absolute right-5 top-2 block border-none text-3xl text-white hover:text-zinc-500 sm:right-8 sm:top-4" onClick={onClose}>
|
|
11
11
|
x
|
|
12
|
-
</
|
|
12
|
+
</Button>);
|
|
13
13
|
};
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import "react-custom-scroll/dist/customScroll.css";
|
|
2
|
-
import "./gameRules.css";
|
|
3
2
|
import i18next from "i18next";
|
|
4
3
|
import { observer } from "mobx-react-lite";
|
|
5
4
|
import React, { useState } from "react";
|
|
@@ -23,21 +22,20 @@ export const GameRules = observer(() => {
|
|
|
23
22
|
}
|
|
24
23
|
setPageNumber(pageNumber + incrementor);
|
|
25
24
|
};
|
|
26
|
-
return (<div className="
|
|
27
|
-
<
|
|
28
|
-
<h2>{i18next.t("gameRules")}</h2>
|
|
29
|
-
</div>
|
|
25
|
+
return (<div className="max-w-5/6 flex h-fit max-h-[80vh] flex-col items-center gap-4 p-5">
|
|
26
|
+
<h2 className="text-center text-3xl font-bold text-primary-500">{i18next.t("gameRules")}</h2>
|
|
30
27
|
<CloseModalButton layerId={UI_ITEMS.gameRules}/>
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
28
|
+
<div className="custom-scroll max-w-5/6 h-full min-h-[60vh]">
|
|
29
|
+
<CustomScroll className="h-full w-full overflow-y-auto portrait:max-h-[60vh]" allowOuterScroll={true}>
|
|
30
|
+
<div className="text-md max-w-5/6 w-full overflow-y-auto landscape:max-h-[30vh]">
|
|
31
|
+
{gameRulesContent.pages[pageNumber]}
|
|
32
|
+
</div>
|
|
35
33
|
</CustomScroll>
|
|
36
34
|
</div>
|
|
37
|
-
<div className="
|
|
38
|
-
<div className="
|
|
39
|
-
<div className="
|
|
40
|
-
<div className="
|
|
35
|
+
<div className="flex h-[50px] items-center justify-center gap-2">
|
|
36
|
+
<div className="flex h-[24px] w-6 items-center bg-[url('/assets/settings/gameRules/left.png')] bg-contain bg-right bg-no-repeat hover:opacity-50" onClick={() => changePage(-1)}/>
|
|
37
|
+
<div className="flex h-[24px] w-6 items-center bg-[url('/assets/settings/gameRules/cross.png')] bg-contain bg-no-repeat hover:opacity-50" onClick={() => settingStore.handleModalInvocation?.(UI_ITEMS.gameRules)}/>
|
|
38
|
+
<div className="flex h-[24px] w-6 items-center bg-[url('/assets/settings/gameRules/right.png')] bg-contain bg-no-repeat hover:opacity-50" onClick={() => changePage(1)}/>
|
|
41
39
|
</div>
|
|
42
40
|
</div>);
|
|
43
41
|
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React, { ReactNode } from "react";
|
|
2
|
+
type ModalProps = {
|
|
3
|
+
layerId: string;
|
|
4
|
+
className?: string;
|
|
5
|
+
children?: ReactNode;
|
|
6
|
+
};
|
|
7
|
+
export declare const Modal: (({ layerId, children, className }: ModalProps) => React.JSX.Element) & {
|
|
8
|
+
displayName: string;
|
|
9
|
+
};
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { observer } from "mobx-react-lite";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { useClickOutside, useStores } from "../../hooks";
|
|
4
|
+
import { cn } from "../../utils/tw";
|
|
5
|
+
export const Modal = observer(({ layerId, children, className }) => {
|
|
6
|
+
const { settingStore } = useStores();
|
|
7
|
+
const { ref, open, setOpen } = useClickOutside(() => {
|
|
8
|
+
const element = document.getElementById(layerId);
|
|
9
|
+
if (element && element.style.display !== "none") {
|
|
10
|
+
setOpen(false);
|
|
11
|
+
settingStore.handleModalInvocation?.(layerId);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
return (<dialog onClick={() => setOpen(!open)} className="relative z-10 text-white" id={layerId} aria-labelledby={layerId}>
|
|
15
|
+
<div onClick={() => setOpen(!open)} className="fixed inset-0 bg-zinc-800 bg-opacity-75 transition-opacity"/>
|
|
16
|
+
<div className="fixed inset-0 z-10 w-screen overflow-y-auto p-6">
|
|
17
|
+
<div className="flex min-h-full w-full items-center justify-center rounded-lg shadow">
|
|
18
|
+
<div ref={ref} className={cn("relative flex h-5/6 transform flex-col items-center overflow-hidden rounded-lg bg-zinc-900 p-2 text-left shadow-xl transition-all", className)}>
|
|
19
|
+
{children}
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
</dialog>);
|
|
24
|
+
});
|
|
@@ -30,7 +30,7 @@ export const OptionButton = ({ option, currency, setMessage }) => {
|
|
|
30
30
|
settingStore.setIsFreeSpinBought(false);
|
|
31
31
|
}
|
|
32
32
|
};
|
|
33
|
-
return (<div className="
|
|
33
|
+
return (<div className="flex w-[120px] flex-col items-center justify-center rounded-[8px] bg-primary-900 p-2 hover:cursor-pointer hover:bg-primary-600" key={option.amount} onClick={async () => await onButtonClick(option)}>
|
|
34
34
|
<p>
|
|
35
35
|
{i18next.t("amount")}: {option.amount}
|
|
36
36
|
</p>
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import "rc-slider/assets/index.css";
|
|
2
|
-
import "./richLimitingSlider.css";
|
|
3
2
|
import { observer } from "mobx-react-lite";
|
|
4
3
|
import Slider from "rc-slider";
|
|
5
4
|
import React from "react";
|
|
6
5
|
export const RichLimitingSlider = observer(({ value, setValue, maxValue, description }) => {
|
|
7
|
-
|
|
6
|
+
const handleStyle = { width: "20px", height: "20px", bottom: "-4px" };
|
|
7
|
+
return (<div className="flex items-center gap-4 py-4">
|
|
8
8
|
{/* @ts-expect-error type error in library */}
|
|
9
|
-
<Slider className="
|
|
9
|
+
<Slider className="flex w-full flex-col items-center justify-center gap-2 sm:gap-4" step={1} min={0} max={maxValue} defaultValue={value} value={value} handleStyle={{
|
|
10
10
|
backgroundColor: "#fdf425",
|
|
11
11
|
borderColor: "#fdf425",
|
|
12
|
-
|
|
13
|
-
height: "20px",
|
|
14
|
-
bottom: "-4px",
|
|
12
|
+
...handleStyle,
|
|
15
13
|
}} railStyle={{
|
|
16
14
|
backgroundColor: "#fff",
|
|
17
15
|
}} trackStyle={{
|
|
@@ -19,8 +17,10 @@ export const RichLimitingSlider = observer(({ value, setValue, maxValue, descrip
|
|
|
19
17
|
}} dotStyle={{
|
|
20
18
|
borderColor: "#fdf425",
|
|
21
19
|
}} onChange={(value) => setValue(value)}>
|
|
22
|
-
<p className="
|
|
20
|
+
<p className="mt-6 self-center pt-4 text-center sm:mt-5 sm:text-xl">{description}</p>
|
|
23
21
|
</Slider>
|
|
24
|
-
<div className="
|
|
22
|
+
<div className="flex h-10 w-10 items-center justify-center rounded-xl bg-zinc-800 px-8 py-4 shadow-primary-400/25">
|
|
23
|
+
{value}
|
|
24
|
+
</div>
|
|
25
25
|
</div>);
|
|
26
26
|
});
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import "./slidingSwitch.css";
|
|
2
1
|
import { observer } from "mobx-react-lite";
|
|
3
2
|
import React from "react";
|
|
4
3
|
export const SlidingSwitch = observer(({ flag, setFlag }) => {
|
|
5
|
-
return (<label className="
|
|
6
|
-
|
|
7
|
-
<input type="checkbox" checked={flag} onChange={(event) => setFlag(event.target.checked)}/>
|
|
8
|
-
<
|
|
4
|
+
return (<label className="relative flex items-center justify-between p-2 text-xl">
|
|
5
|
+
{flag ? "ON" : "OFF"}
|
|
6
|
+
<input type="checkbox" className="peer absolute left-0 top-0 h-full w-full appearance-none rounded-md" checked={flag} onChange={(event) => setFlag(event.target.checked)}/>
|
|
7
|
+
<span className="ml-4 flex h-10 w-16 flex-shrink-0 items-center rounded-full bg-zinc-700 p-1 duration-300 ease-in-out after:h-8 after:w-8 after:rounded-full after:bg-white after:shadow-md after:duration-300 group-hover:after:translate-x-1 peer-checked:bg-primary-400 peer-checked:after:translate-x-6"/>
|
|
9
8
|
</label>);
|
|
10
9
|
});
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import "react-custom-scroll/dist/customScroll.css";
|
|
2
|
-
import "./speedSettingsPopup.css";
|
|
3
2
|
import i18next from "i18next";
|
|
4
3
|
import { observer } from "mobx-react-lite";
|
|
5
4
|
import React from "react";
|
|
6
5
|
import { SPEED_LEVELS } from "../../../application";
|
|
7
6
|
import { UI_ITEMS } from "../../../utils";
|
|
8
7
|
import { useStores } from "../../hooks";
|
|
8
|
+
import { cn } from "../../utils/tw";
|
|
9
9
|
import { CloseModalButton } from "../CloseModalButton";
|
|
10
10
|
export const SPEED_PREFIX = "speed-";
|
|
11
11
|
export const SpeedSettingsPopup = observer(() => {
|
|
@@ -15,12 +15,12 @@ export const SpeedSettingsPopup = observer(() => {
|
|
|
15
15
|
fast: SPEED_LEVELS.fast,
|
|
16
16
|
};
|
|
17
17
|
const { settingStore } = useStores();
|
|
18
|
-
return (<div className="
|
|
18
|
+
return (<div className="flex h-full w-fit flex-col items-center justify-between gap-2 p-4 portrait:max-w-72">
|
|
19
19
|
<CloseModalButton layerId={UI_ITEMS.speedSettings}/>
|
|
20
|
-
<
|
|
21
|
-
<div className="
|
|
22
|
-
{Object.keys(speedLevelMapper).map((speedLevelKey) => (<div id={`${SPEED_PREFIX}${speedLevelKey}`} key={`${SPEED_PREFIX}${speedLevelKey}`} className={
|
|
23
|
-
<img className=
|
|
20
|
+
<h1 className="mt-3 font-bold uppercase text-white sm:text-xl">{i18next.t("howDoYouWantToPlay")}</h1>
|
|
21
|
+
<div className="flex h-fit w-full flex-wrap justify-between gap-2 portrait:items-center portrait:justify-center">
|
|
22
|
+
{Object.keys(speedLevelMapper).map((speedLevelKey) => (<div id={`${SPEED_PREFIX}${speedLevelKey}`} key={`${SPEED_PREFIX}${speedLevelKey}`} className={cn("flex h-fit w-[145px] items-center justify-center border-2 border-zinc-400 bg-zinc-800 bg-contain bg-no-repeat p-4", speedLevelKey === settingStore.currentSpeed ? "h-fit border-2 border-primary-500" : "")}>
|
|
23
|
+
<img className="h-12 w-fit" src={`../../../assets/settings/speedPopup/speed-${speedLevelMapper[speedLevelKey]}.png`}/>
|
|
24
24
|
</div>))}
|
|
25
25
|
</div>
|
|
26
26
|
</div>);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { observer } from "mobx-react-lite";
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { useStores } from "../../hooks";
|
|
4
|
+
import { cn } from "../../utils/tw";
|
|
4
5
|
export const SpeedButtonSwitch = observer(() => {
|
|
5
6
|
const speedLevelMapper = {
|
|
6
7
|
slow: "turtle",
|
|
@@ -9,11 +10,11 @@ export const SpeedButtonSwitch = observer(() => {
|
|
|
9
10
|
};
|
|
10
11
|
const { settingStore } = useStores();
|
|
11
12
|
const { currentSpeed } = settingStore;
|
|
12
|
-
return (<label className="
|
|
13
|
-
<span className="
|
|
14
|
-
<img className="
|
|
15
|
-
<div className="
|
|
16
|
-
{Array.from({ length: 3 }).map((_, i) => (<div key={i} className={
|
|
13
|
+
return (<label className="speed-level-id relative inline-block h-[34px] w-full max-w-20 transition-all ease-in hover:cursor-pointer">
|
|
14
|
+
<span className="absolute bottom-0 left-0 right-0 top-0 cursor-pointer rounded-lg bg-zinc-800 shadow shadow-primary-500/30"/>
|
|
15
|
+
<img className="relative left-2 top-2 h-5 w-6" src={`assets/settings/speed-${speedLevelMapper[currentSpeed]}.png`}/>
|
|
16
|
+
<div className="relative bottom-2 left-9 flex w-9 justify-between gap-[2px]">
|
|
17
|
+
{Array.from({ length: 3 }).map((_, i) => (<div key={i} className={cn("relative h-3 w-3 rounded-full bg-white", i < settingStore.indexOfSpeedLevel ? "bg-primary-500" : "")}/>))}
|
|
17
18
|
</div>
|
|
18
19
|
</label>);
|
|
19
20
|
});
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import "./headerStyle.css";
|
|
2
1
|
import React from "react";
|
|
3
2
|
import { HeaderWithDescriptionProps, SpeedButtonWithHeaderProps, SwitchHeaderProps } from "./types";
|
|
4
3
|
export declare const HeaderWithDescription: ({ header, description }: HeaderWithDescriptionProps) => React.JSX.Element;
|
|
@@ -1,22 +1,21 @@
|
|
|
1
|
-
import "./headerStyle.css";
|
|
2
1
|
import { observer } from "mobx-react-lite";
|
|
3
2
|
import React from "react";
|
|
4
3
|
import { SlidingSwitch } from "../SlidingSwitch";
|
|
5
4
|
import { SpeedButtonSwitch } from "../SpeedSwitchButton";
|
|
6
5
|
export const HeaderWithDescription = ({ header, description }) => {
|
|
7
|
-
return (<div className="
|
|
8
|
-
<h2 className="
|
|
9
|
-
{description && <
|
|
6
|
+
return (<div className="flex flex-col gap-2">
|
|
7
|
+
<h2 className="text-xl font-bold uppercase">{header}</h2>
|
|
8
|
+
{description && <span>{description}</span>}
|
|
10
9
|
</div>);
|
|
11
10
|
};
|
|
12
11
|
export const SwitchWithHeader = observer(({ header, description, flag, setFlag }) => {
|
|
13
|
-
return (<div className="flex-
|
|
12
|
+
return (<div className="flex w-full items-center justify-between">
|
|
14
13
|
<HeaderWithDescription header={header} description={description}/>
|
|
15
14
|
<SlidingSwitch flag={flag} setFlag={setFlag}/>
|
|
16
15
|
</div>);
|
|
17
16
|
});
|
|
18
17
|
export const SpeedButtonWithHeader = observer(({ header, description }) => {
|
|
19
|
-
return (<div className="flex-
|
|
18
|
+
return (<div className="flex w-full items-center justify-between">
|
|
20
19
|
<HeaderWithDescription header={header} description={description}/>
|
|
21
20
|
<SpeedButtonSwitch />
|
|
22
21
|
</div>);
|