@anywayseo/tools 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +62 -0
  3. package/dist/components/author/index.d.ts +8 -0
  4. package/dist/components/contact-form/index.d.ts +3 -0
  5. package/dist/components/expert/bio/index.d.ts +8 -0
  6. package/dist/components/expert/index.d.ts +8 -0
  7. package/dist/components/expert-tip/index.d.ts +9 -0
  8. package/dist/components/faq/index.d.ts +9 -0
  9. package/dist/components/features/index.d.ts +8 -0
  10. package/dist/components/game-demo/content/index.d.ts +10 -0
  11. package/dist/components/game-demo/index.d.ts +10 -0
  12. package/dist/components/game-demo/preview/index.d.ts +9 -0
  13. package/dist/components/game-info/index.d.ts +7 -0
  14. package/dist/components/game-info/item/index.d.ts +7 -0
  15. package/dist/components/game-info/utils.d.ts +2 -0
  16. package/dist/components/how-to/index.d.ts +8 -0
  17. package/dist/components/index.cjs +14 -0
  18. package/dist/components/index.d.ts +11 -0
  19. package/dist/components/index.mjs +14 -0
  20. package/dist/components/layout/content/index.d.ts +3 -0
  21. package/dist/components/layout/footer/brand/index.d.ts +6 -0
  22. package/dist/components/layout/footer/copyright/index.d.ts +3 -0
  23. package/dist/components/layout/footer/disclaimer/index.d.ts +3 -0
  24. package/dist/components/layout/footer/index.d.ts +3 -0
  25. package/dist/components/layout/footer/navigation/index.d.ts +3 -0
  26. package/dist/components/layout/header/index.d.ts +3 -0
  27. package/dist/components/layout/header/navbar/brand/index.d.ts +6 -0
  28. package/dist/components/layout/header/navbar/index.d.ts +6 -0
  29. package/dist/components/layout/header/navbar/navigation/desktop/index.d.ts +4 -0
  30. package/dist/components/layout/header/navbar/navigation/desktop/item/index.d.ts +5 -0
  31. package/dist/components/layout/header/navbar/navigation/index.d.ts +4 -0
  32. package/dist/components/layout/header/navbar/navigation/mobile/index.d.ts +4 -0
  33. package/dist/components/layout/header/navbar/navigation/mobile/item/index.d.ts +5 -0
  34. package/dist/components/layout/header/navbar/navigation/types.d.ts +4 -0
  35. package/dist/components/layout/header/navbar/theme-toggler/index.d.ts +3 -0
  36. package/dist/components/layout/hero/index.d.ts +9 -0
  37. package/dist/components/layout/index.d.ts +12 -0
  38. package/dist/components/layout/logo/index.d.ts +3 -0
  39. package/dist/components/layout/main/index.d.ts +3 -0
  40. package/dist/components/layout/scroll-to-top/index.d.ts +3 -0
  41. package/dist/components/pros-cons/card/index.d.ts +8 -0
  42. package/dist/components/pros-cons/card/utils.d.ts +6 -0
  43. package/dist/components/pros-cons/index.d.ts +8 -0
  44. package/dist/components/seo/index.d.ts +16 -0
  45. package/dist/hooks/index.cjs +4 -0
  46. package/dist/hooks/index.d.ts +1 -0
  47. package/dist/hooks/index.mjs +4 -0
  48. package/dist/hooks/use-primary-colors/index.d.ts +6 -0
  49. package/dist/i18n/index.cjs +7 -0
  50. package/dist/i18n/index.d.ts +9 -0
  51. package/dist/i18n/index.mjs +7 -0
  52. package/dist/i18n/resources/en/index.d.ts +99 -0
  53. package/dist/i18n/resources/index.d.ts +8 -0
  54. package/dist/i18n/resources/it/index.d.ts +99 -0
  55. package/dist/index-BWuTDC6H.js +17 -0
  56. package/dist/index-Bh5idiRE.mjs +257 -0
  57. package/dist/index-Bs4zA1wD.mjs +17 -0
  58. package/dist/index-BtWxmLHW.mjs +80 -0
  59. package/dist/index-D96zh94V.js +16 -0
  60. package/dist/index-DB1dS9cp.js +256 -0
  61. package/dist/index-Dfw_EKZ6.mjs +767 -0
  62. package/dist/index-IpSV-c71.js +8 -0
  63. package/dist/index-JMmaWcmu.js +79 -0
  64. package/dist/index-NWY9BnRg.js +766 -0
  65. package/dist/index-wbMOJRW_.mjs +18 -0
  66. package/dist/index-xuSxvz5z.mjs +9 -0
  67. package/dist/index.cjs +36 -0
  68. package/dist/index.d.ts +6 -0
  69. package/dist/index.mjs +36 -0
  70. package/dist/providers/index.cjs +7 -0
  71. package/dist/providers/index.d.ts +2 -0
  72. package/dist/providers/index.mjs +7 -0
  73. package/dist/providers/mdx-provider/index.d.ts +3 -0
  74. package/dist/providers/site-metadata-provider/index.d.ts +14 -0
  75. package/dist/style.css +15 -0
  76. package/dist/types/author/index.d.ts +17 -0
  77. package/dist/types/faq/index.d.ts +4 -0
  78. package/dist/types/feature/index.d.ts +4 -0
  79. package/dist/types/game-info/index.d.ts +63 -0
  80. package/dist/types/how-to/index.d.ts +5 -0
  81. package/dist/types/i18n/index.d.ts +2 -0
  82. package/dist/types/index.d.ts +9 -0
  83. package/dist/types/navigation/index.d.ts +9 -0
  84. package/dist/types/pros-cons/index.d.ts +6 -0
  85. package/dist/types/site-metadata/index.d.ts +10 -0
  86. package/dist/utils/date/index.d.ts +9 -0
  87. package/dist/utils/index.cjs +11 -0
  88. package/dist/utils/index.d.ts +3 -0
  89. package/dist/utils/index.mjs +11 -0
  90. package/dist/utils/numbers/index.d.ts +19 -0
  91. package/dist/utils/numbers/types.d.ts +1 -0
  92. package/dist/utils/url/index.d.ts +1 -0
  93. package/package.json +99 -0
@@ -0,0 +1,767 @@
1
+ import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
+ import { Box, Collapse, Text, Button, Flex, Stack, Card, CardHeader, Heading, CardBody, useToast, useColorModeValue, VStack, FormControl, FormLabel, InputGroup, InputLeftElement, Input, Textarea, CardFooter, Accordion, AccordionItem, AccordionButton, AccordionIcon, AccordionPanel, SimpleGrid, IconButton, AbsoluteCenter, Spinner, useDisclosure, Divider, Circle, Container, Popover, PopoverTrigger, PopoverContent, Icon, useBreakpointValue, List, ListItem, ListIcon } from "@chakra-ui/react";
3
+ import { useTranslation } from "react-i18next";
4
+ import { EmailIcon, StarIcon, CloseIcon, ExternalLinkIcon, ChevronRightIcon, ChevronDownIcon, HamburgerIcon, ChevronUpIcon, WarningIcon, CheckCircleIcon } from "@chakra-ui/icons";
5
+ import { getImage, GatsbyImage } from "gatsby-plugin-image";
6
+ import "@mdx-js/react";
7
+ import { u as useSiteMetadataContext } from "./index-Bs4zA1wD.mjs";
8
+ import { useRef, useState, useLayoutEffect, Fragment as Fragment$1, useEffect } from "react";
9
+ import { u as usePrimaryColors } from "./index-xuSxvz5z.mjs";
10
+ import { a as GameCharacteristic } from "./index-Bh5idiRE.mjs";
11
+ import { t } from "i18next";
12
+ import { b as formatNumber, f as formatDate, c as getDomain, g as getCurrentYear, a as getCurrentMonth } from "./index-BtWxmLHW.mjs";
13
+ import { Link } from "gatsby";
14
+ const ONE_LINE_HEIGHT = 24;
15
+ const Bio = ({ content, maxLines = 1 }) => {
16
+ const ref = useRef(null);
17
+ const [showToggle, setShowToggle] = useState(false);
18
+ const [isExpanded, setIsExpanded] = useState(false);
19
+ const { t: t2 } = useTranslation("author");
20
+ useLayoutEffect(() => {
21
+ if (ref.current) {
22
+ const { scrollWidth, clientWidth, scrollHeight, clientHeight } = ref.current;
23
+ const isClamped = scrollWidth > clientWidth || scrollHeight > clientHeight;
24
+ setShowToggle(isClamped);
25
+ }
26
+ return () => {
27
+ setShowToggle(false);
28
+ };
29
+ }, []);
30
+ function handleClick() {
31
+ setIsExpanded((prev) => !prev);
32
+ }
33
+ return /* @__PURE__ */ jsxs(Box, { children: [
34
+ /* @__PURE__ */ jsx(Collapse, { in: isExpanded, startingHeight: ONE_LINE_HEIGHT * maxLines, children: /* @__PURE__ */ jsx(Text, { ref, fontSize: "md", noOfLines: isExpanded ? void 0 : maxLines, children: content }) }),
35
+ showToggle && /* @__PURE__ */ jsx(Button, { size: "sm", variant: "link", colorScheme: "blue", onClick: handleClick, children: isExpanded ? t2("action.collapse") : t2("action.expand") })
36
+ ] });
37
+ };
38
+ const Expert = ({ expert, variant }) => {
39
+ const { firstName, lastName, jobTitle, bio } = expert;
40
+ const { expertImageData } = useSiteMetadataContext();
41
+ const image = getImage(expertImageData);
42
+ const fullName = `${firstName} ${lastName}`;
43
+ if (variant === "short") {
44
+ return /* @__PURE__ */ jsxs(Flex, { as: "article", align: "center", gap: 4, children: [
45
+ !!image && /* @__PURE__ */ jsx(Box, { w: 12, h: 12, children: /* @__PURE__ */ jsx(GatsbyImage, { image, alt: fullName, style: { borderRadius: "50%" } }) }),
46
+ /* @__PURE__ */ jsxs(Box, { fontWeight: "semibold", children: [
47
+ /* @__PURE__ */ jsx(Text, { children: fullName }),
48
+ /* @__PURE__ */ jsx(Text, { color: "gray.500", children: expert.jobTitle })
49
+ ] })
50
+ ] });
51
+ }
52
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
53
+ !!image && /* @__PURE__ */ jsx(Flex, { grow: 1, maxW: { base: 48, sm: 32 }, children: /* @__PURE__ */ jsx(GatsbyImage, { image, alt: fullName, style: { borderRadius: "50%" } }) }),
54
+ /* @__PURE__ */ jsx(Flex, { w: "100%", children: /* @__PURE__ */ jsxs(Stack, { children: [
55
+ /* @__PURE__ */ jsxs(Text, { fontSize: "lg", fontWeight: 600, children: [
56
+ `${fullName}, `,
57
+ /* @__PURE__ */ jsx(Text, { as: "span", color: "gray.500", children: jobTitle })
58
+ ] }),
59
+ /* @__PURE__ */ jsx(Bio, { content: bio })
60
+ ] }) })
61
+ ] });
62
+ };
63
+ const Author = ({ author, ...cardProps }) => {
64
+ const { t: t2 } = useTranslation("author");
65
+ return /* @__PURE__ */ jsxs(Card, { as: "article", variant: "filled", ...cardProps, children: [
66
+ /* @__PURE__ */ jsx(CardHeader, { pb: 0, children: /* @__PURE__ */ jsx(Heading, { size: "md", children: t2("title") }) }),
67
+ /* @__PURE__ */ jsx(
68
+ CardBody,
69
+ {
70
+ display: "flex",
71
+ flexDirection: { base: "column", sm: "row" },
72
+ alignItems: { base: "center", sm: "flex-start" },
73
+ gap: 4,
74
+ children: /* @__PURE__ */ jsx(Expert, { expert: author, variant: "full" })
75
+ }
76
+ )
77
+ ] });
78
+ };
79
+ const ContactForm = () => {
80
+ const toast = useToast();
81
+ const { t: t2 } = useTranslation("contactForm");
82
+ function handleSubmit(event) {
83
+ event.preventDefault();
84
+ const form = event.currentTarget;
85
+ const formData = new FormData(form);
86
+ const name = formData.get("name");
87
+ const email = formData.get("email");
88
+ const message = formData.get("message");
89
+ if (name && email && message) {
90
+ form.reset();
91
+ toast({
92
+ title: t2("notification.title", { name }),
93
+ description: t2("notification.description", { email }),
94
+ colorScheme: "brand",
95
+ status: "success",
96
+ duration: 5e3,
97
+ isClosable: true
98
+ });
99
+ } else {
100
+ console.error("Please fill out both fields");
101
+ }
102
+ }
103
+ return /* @__PURE__ */ jsx(
104
+ Box,
105
+ {
106
+ as: "form",
107
+ borderRadius: "lg",
108
+ p: 8,
109
+ color: useColorModeValue("gray.700", "whiteAlpha.900"),
110
+ bg: useColorModeValue("white", "gray.700"),
111
+ shadow: "base",
112
+ onSubmit: handleSubmit,
113
+ children: /* @__PURE__ */ jsxs(VStack, { spacing: 4, children: [
114
+ /* @__PURE__ */ jsxs(FormControl, { isRequired: true, children: [
115
+ /* @__PURE__ */ jsx(FormLabel, { children: t2("field.name.label") }),
116
+ /* @__PURE__ */ jsxs(InputGroup, { children: [
117
+ /* @__PURE__ */ jsx(InputLeftElement, { children: /* @__PURE__ */ jsx(
118
+ "svg",
119
+ {
120
+ xmlns: "http://www.w3.org/2000/svg",
121
+ width: "16",
122
+ height: "16",
123
+ fill: "currentColor",
124
+ className: "bi bi-person-fill",
125
+ viewBox: "0 0 16 16",
126
+ children: /* @__PURE__ */ jsx("path", { d: "M3 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6" })
127
+ }
128
+ ) }),
129
+ /* @__PURE__ */ jsx(Input, { type: "text", name: "name", placeholder: t2("field.name.placeholder") })
130
+ ] })
131
+ ] }),
132
+ /* @__PURE__ */ jsxs(FormControl, { isRequired: true, children: [
133
+ /* @__PURE__ */ jsx(FormLabel, { children: t2("field.email.label") }),
134
+ /* @__PURE__ */ jsxs(InputGroup, { children: [
135
+ /* @__PURE__ */ jsx(InputLeftElement, { children: /* @__PURE__ */ jsx(EmailIcon, {}) }),
136
+ /* @__PURE__ */ jsx(Input, { type: "email", name: "email", placeholder: t2("field.email.placeholder") })
137
+ ] })
138
+ ] }),
139
+ /* @__PURE__ */ jsxs(FormControl, { isRequired: true, children: [
140
+ /* @__PURE__ */ jsx(FormLabel, { children: t2("field.message.label") }),
141
+ /* @__PURE__ */ jsx(Textarea, { name: "message", placeholder: t2("field.message.placeholder"), rows: 6, resize: "none" })
142
+ ] }),
143
+ /* @__PURE__ */ jsx(Button, { type: "submit", colorScheme: "brand", width: "full", children: t2("action.send") })
144
+ ] })
145
+ }
146
+ );
147
+ };
148
+ const ExpertTip = ({ tip, expert, ...boxProps }) => {
149
+ return /* @__PURE__ */ jsxs(
150
+ Card,
151
+ {
152
+ variant: "filled",
153
+ p: 4,
154
+ borderLeft: "4px solid gray",
155
+ gap: 4,
156
+ _before: {
157
+ content: '"❛❛"',
158
+ position: "absolute",
159
+ top: -8,
160
+ left: -2,
161
+ fontSize: "6rem",
162
+ fontStyle: "italic",
163
+ color: useColorModeValue("blackAlpha.300", "whiteAlpha.300")
164
+ },
165
+ ...boxProps,
166
+ children: [
167
+ /* @__PURE__ */ jsx(CardBody, { as: "blockquote", p: 0, fontStyle: "italic", children: tip }),
168
+ !!expert && /* @__PURE__ */ jsx(CardFooter, { alignItems: "center", justify: "flex-end", p: 0, children: /* @__PURE__ */ jsx(Expert, { expert, variant: "short" }) })
169
+ ]
170
+ }
171
+ );
172
+ };
173
+ const Faq = ({ items, mb }) => {
174
+ const { bgColor, color } = usePrimaryColors();
175
+ return /* @__PURE__ */ jsx(Accordion, { allowToggle: true, mb, children: items.map(({ question, answer }) => {
176
+ return /* @__PURE__ */ jsxs(AccordionItem, { border: 0, children: [
177
+ /* @__PURE__ */ jsx(Box, { as: "h3", children: /* @__PURE__ */ jsxs(AccordionButton, { _hover: { color, bgColor }, children: [
178
+ /* @__PURE__ */ jsx(Box, { as: "span", flex: "1", textAlign: "left", fontWeight: "bold", children: question }),
179
+ /* @__PURE__ */ jsx(AccordionIcon, {})
180
+ ] }) }),
181
+ /* @__PURE__ */ jsx(AccordionPanel, { children: answer })
182
+ ] }, question);
183
+ }) });
184
+ };
185
+ const Features = ({ features, ...boxProps }) => {
186
+ return /* @__PURE__ */ jsx(SimpleGrid, { as: "ul", columns: { base: 1, md: 2, lg: 3 }, spacing: 10, p: 0, ...boxProps, children: features.map(({ title, description }) => /* @__PURE__ */ jsx(Stack, { as: "li", children: /* @__PURE__ */ jsxs(Card, { as: "article", variant: "outline", textAlign: "center", h: "100%", children: [
187
+ /* @__PURE__ */ jsxs(CardHeader, { as: "header", display: "flex", alignItems: "center", justifyContent: "center", gap: 2, pb: 2, children: [
188
+ /* @__PURE__ */ jsx(StarIcon, { w: 8, h: 8, color: "yellow.400" }),
189
+ /* @__PURE__ */ jsx(Text, { fontWeight: 600, children: title }),
190
+ /* @__PURE__ */ jsx(StarIcon, { w: 8, h: 8, color: "yellow.400" })
191
+ ] }),
192
+ /* @__PURE__ */ jsx(CardBody, { as: "section", pt: 0, children: /* @__PURE__ */ jsx(Text, { color: "gray.600", children: description }) })
193
+ ] }) }, title)) });
194
+ };
195
+ const GameDemoContent = ({ src, isFullscreen, isLoaded, onLoad, onToggleFullscreen }) => {
196
+ const { t: t2 } = useTranslation("gameDemo");
197
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
198
+ /* @__PURE__ */ jsx(
199
+ Box,
200
+ {
201
+ as: "iframe",
202
+ src,
203
+ sandbox: "allow-scripts allow-same-origin",
204
+ loading: "lazy",
205
+ w: "100%",
206
+ h: "100%",
207
+ allowFullScreen: true,
208
+ onLoad,
209
+ children: /* @__PURE__ */ jsx("p", { children: t2("warning") })
210
+ }
211
+ ),
212
+ /* @__PURE__ */ jsx(
213
+ IconButton,
214
+ {
215
+ icon: isFullscreen ? /* @__PURE__ */ jsx(CloseIcon, { w: 3, h: 3 }) : /* @__PURE__ */ jsx(ExternalLinkIcon, { w: 4, h: 4 }),
216
+ size: "sm",
217
+ variant: "outline",
218
+ title: t2(isFullscreen ? "action.deactivateFullscreen" : "action.activateFullscreen"),
219
+ "aria-label": "Fullscreen mode Toggle",
220
+ isRound: true,
221
+ disabled: !isLoaded,
222
+ position: "absolute",
223
+ top: 2,
224
+ left: 2,
225
+ border: "none",
226
+ color: "white",
227
+ _hover: { bgColor: "whiteAlpha.400" },
228
+ onClick: onToggleFullscreen
229
+ }
230
+ ),
231
+ /* @__PURE__ */ jsx(AbsoluteCenter, { children: /* @__PURE__ */ jsx(Spinner, { size: "xl", thickness: "0.6rem", display: isLoaded ? "none" : "block", color: "brand.100" }) })
232
+ ] });
233
+ };
234
+ const pulsing = "_pulsing_u8aju_1";
235
+ const styles = {
236
+ pulsing
237
+ };
238
+ const GameDemoPreview = ({ gameName, onPlay }) => {
239
+ const { gamePreviewImageData } = useSiteMetadataContext();
240
+ const { t: t2 } = useTranslation("gameDemo");
241
+ const image = getImage(gamePreviewImageData);
242
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
243
+ !!image && /* @__PURE__ */ jsx(GatsbyImage, { image, alt: `Play ${gameName} online`, objectFit: "contain" }),
244
+ /* @__PURE__ */ jsx(AbsoluteCenter, { children: /* @__PURE__ */ jsx(
245
+ Button,
246
+ {
247
+ size: { base: "sm", md: "lg" },
248
+ color: "gray.200",
249
+ bgColor: "brand.500",
250
+ _hover: { bgColor: "brand.200", color: "gray.700" },
251
+ className: styles.pulsing,
252
+ onClick: onPlay,
253
+ children: t2("action.playForFree")
254
+ }
255
+ ) })
256
+ ] });
257
+ };
258
+ const GameDemo = ({ name, src, previewImageFit, ...boxProps }) => {
259
+ const [isRunning, setIsRunning] = useState(false);
260
+ const [isLoaded, setIsLoaded] = useState(false);
261
+ const { isOpen: isFullscreen, onToggle } = useDisclosure({ defaultIsOpen: false });
262
+ function handlePlay() {
263
+ setIsRunning(true);
264
+ }
265
+ function onLoad() {
266
+ setIsLoaded(true);
267
+ }
268
+ function handleToggleFullscreen() {
269
+ document.body.style.overflowY = isFullscreen ? "auto" : "hidden";
270
+ onToggle();
271
+ }
272
+ return /* @__PURE__ */ jsx(
273
+ Box,
274
+ {
275
+ as: "article",
276
+ display: "grid",
277
+ w: "100%",
278
+ aspectRatio: "16/9 auto",
279
+ ...isFullscreen ? { zIndex: 100, inset: 0, position: "fixed", h: "100dvh" } : { position: "relative" },
280
+ ...boxProps,
281
+ children: isRunning ? /* @__PURE__ */ jsx(
282
+ GameDemoContent,
283
+ {
284
+ src,
285
+ isFullscreen,
286
+ isLoaded,
287
+ onLoad,
288
+ onToggleFullscreen: handleToggleFullscreen
289
+ }
290
+ ) : /* @__PURE__ */ jsx(GameDemoPreview, { gameName: name, previewImageFit, onPlay: handlePlay })
291
+ }
292
+ );
293
+ };
294
+ const GameInfoItem = ({ title, value }) => {
295
+ return /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
296
+ /* @__PURE__ */ jsxs(Text, { w: "50%", color: "gray.500", textTransform: "capitalize", children: [
297
+ title,
298
+ ":"
299
+ ] }),
300
+ /* @__PURE__ */ jsx(Text, { w: "50%", textTransform: "capitalize", children: value })
301
+ ] });
302
+ };
303
+ const VISIBLE_LANGUAGE_NUMBER = 5;
304
+ function stringifyHasFeature(value) {
305
+ return t(`gameInfo:value.boolean.${value}`);
306
+ }
307
+ function stringifyVolatility(value) {
308
+ return t(`gameInfo:value.volatility.${value}`);
309
+ }
310
+ function stringifyArray(array) {
311
+ return array.join(", ");
312
+ }
313
+ function stringifyLanguageArray(languages) {
314
+ return languages.length > VISIBLE_LANGUAGE_NUMBER ? `${stringifyArray(languages.slice(0, VISIBLE_LANGUAGE_NUMBER))}, +${languages.length - VISIBLE_LANGUAGE_NUMBER}` : stringifyArray(languages);
315
+ }
316
+ function getGameInfoItemValue(key, value, currency) {
317
+ let formattedValue = "";
318
+ if (key === GameCharacteristic.Rtp) {
319
+ formattedValue = formatNumber(value, { percent: "real", precision: 3 });
320
+ }
321
+ if (key === GameCharacteristic.MinBet || key === GameCharacteristic.MaxBet || key === GameCharacteristic.MaxWin && typeof value === "number") {
322
+ formattedValue = formatNumber(value, { currency });
323
+ }
324
+ if (key === GameCharacteristic.Compatibility || key === GameCharacteristic.BonusFeatures && typeof value !== "string") {
325
+ formattedValue = stringifyArray(value);
326
+ }
327
+ if (key === GameCharacteristic.Languages) {
328
+ formattedValue = stringifyLanguageArray(value);
329
+ }
330
+ if (key === GameCharacteristic.ReleaseDate) {
331
+ formattedValue = formatDate({ value, options: { year: "numeric", month: "long" } });
332
+ }
333
+ if (key === GameCharacteristic.Volatility) {
334
+ formattedValue = stringifyVolatility(value);
335
+ }
336
+ if (typeof value === "boolean") {
337
+ formattedValue = stringifyHasFeature(value);
338
+ }
339
+ if (!formattedValue) {
340
+ formattedValue = value.toLocaleString();
341
+ }
342
+ return formattedValue;
343
+ }
344
+ const GameInfo = ({ info }) => {
345
+ const { siteMetadata } = useSiteMetadataContext();
346
+ const { currency } = siteMetadata;
347
+ const { t: t2 } = useTranslation("gameInfo");
348
+ return /* @__PURE__ */ jsx(
349
+ Box,
350
+ {
351
+ as: "aside",
352
+ float: { base: "none", lg: "right" },
353
+ w: { base: "100%", lg: "xs" },
354
+ ml: { base: 0, lg: 4 },
355
+ mb: { base: 0, lg: 4 },
356
+ children: /* @__PURE__ */ jsxs(Card, { as: "article", variant: "outline", h: "100%", p: 2, children: [
357
+ /* @__PURE__ */ jsx(CardHeader, { as: "header", p: 0, children: /* @__PURE__ */ jsx(Heading, { as: "h2", fontSize: "xl", children: t2("title") }) }),
358
+ /* @__PURE__ */ jsx(CardBody, { as: "section", p: 0, children: Object.entries(info).map(([group, items]) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
359
+ /* @__PURE__ */ jsx(Divider, { my: 2 }),
360
+ /* @__PURE__ */ jsx(Text, { fontWeight: "semibold", mb: 2, children: t2(`group.${group}`) }),
361
+ Object.entries(items).map(([itemKey, itemValue]) => {
362
+ const feature = itemKey;
363
+ const value = getGameInfoItemValue(feature, itemValue, currency);
364
+ return /* @__PURE__ */ jsx(GameInfoItem, { title: t2(`feature.${feature}`), value }, itemKey);
365
+ })
366
+ ] }, group)) })
367
+ ] })
368
+ }
369
+ );
370
+ };
371
+ const HowTo = ({ steps, ...boxProps }) => {
372
+ const { color, bgColor } = usePrimaryColors();
373
+ return /* @__PURE__ */ jsx(SimpleGrid, { as: "ol", columns: { base: 1, md: 2, lg: 3 }, gap: 4, p: 0, ...boxProps, children: steps.map(({ title, description }, index) => /* @__PURE__ */ jsxs(Flex, { as: "li", alignItems: "flex-start", gap: 4, children: [
374
+ /* @__PURE__ */ jsx(Circle, { size: 12, bgColor, color, fontSize: "lg", fontWeight: "bold", children: String(index + 1) }),
375
+ /* @__PURE__ */ jsxs(Stack, { flex: 1, children: [
376
+ /* @__PURE__ */ jsx(Text, { fontSize: "lg", fontWeight: "bold", children: title }),
377
+ /* @__PURE__ */ jsx(Text, { children: description })
378
+ ] })
379
+ ] }, index)) });
380
+ };
381
+ const Content = ({ children }) => {
382
+ return /* @__PURE__ */ jsx(Container, { as: "section", maxW: "container.xl", children });
383
+ };
384
+ const Logo = () => {
385
+ const { logoImageData } = useSiteMetadataContext();
386
+ const image = getImage(logoImageData);
387
+ if (!image) {
388
+ return null;
389
+ }
390
+ return /* @__PURE__ */ jsx(GatsbyImage, { image, objectFit: "contain", alt: "Logo" });
391
+ };
392
+ const Brand$1 = ({ brand }) => {
393
+ return /* @__PURE__ */ jsxs(Box, { position: "relative", my: 2, py: 8, children: [
394
+ /* @__PURE__ */ jsx(Divider, {}),
395
+ /* @__PURE__ */ jsx(AbsoluteCenter, { display: "flex", bgColor: useColorModeValue("gray.50", "gray.900"), children: /* @__PURE__ */ jsx(Box, { as: Link, to: "/", children: brand }) })
396
+ ] });
397
+ };
398
+ const Copyright = () => {
399
+ const { siteMetadata } = useSiteMetadataContext();
400
+ const { siteUrl } = siteMetadata;
401
+ const { t: t2 } = useTranslation("footer");
402
+ return /* @__PURE__ */ jsx(Text, { as: "small", colorScheme: "gray", display: "flex", align: "center", justifyContent: "center", children: t2("copyright", { year: getCurrentYear(), domain: getDomain(siteUrl) }) });
403
+ };
404
+ const Disclaimer = () => {
405
+ const { siteMetadata } = useSiteMetadataContext();
406
+ const { siteUrl } = siteMetadata;
407
+ const { t: t2 } = useTranslation("footer");
408
+ return /* @__PURE__ */ jsxs(Text, { as: "small", colorScheme: "gray", fontSize: "sm", children: [
409
+ /* @__PURE__ */ jsx(Text, { as: "span", fontWeight: "bold", color: "red.600", children: t2("disclaimer.title") }),
410
+ t2("disclaimer.description", { domain: getDomain(siteUrl) })
411
+ ] });
412
+ };
413
+ const Navigation$1 = () => {
414
+ const { siteMetadata } = useSiteMetadataContext();
415
+ const { footerMenuLinks } = siteMetadata;
416
+ return /* @__PURE__ */ jsx(
417
+ SimpleGrid,
418
+ {
419
+ columns: { base: 1, sm: 2, md: 4 },
420
+ pt: 4,
421
+ pb: 6,
422
+ spacing: 4,
423
+ justifyItems: { base: "flex-start", md: "center" },
424
+ justifyContent: "space-between",
425
+ children: footerMenuLinks.map(({ url, title }) => /* @__PURE__ */ jsx(
426
+ Text,
427
+ {
428
+ as: Link,
429
+ to: url,
430
+ fontSize: "md",
431
+ fontWeight: "semibold",
432
+ colorScheme: "gray",
433
+ _hover: { textDecoration: "none", color: "brand.400" },
434
+ children: title
435
+ },
436
+ url
437
+ ))
438
+ }
439
+ );
440
+ };
441
+ const Footer = () => {
442
+ return /* @__PURE__ */ jsx(
443
+ Box,
444
+ {
445
+ as: "footer",
446
+ bg: useColorModeValue("gray.50", "gray.900"),
447
+ color: useColorModeValue("gray.700", "gray.200"),
448
+ py: 4,
449
+ children: /* @__PURE__ */ jsxs(Content, { children: [
450
+ /* @__PURE__ */ jsx(Navigation$1, {}),
451
+ /* @__PURE__ */ jsx(Disclaimer, {}),
452
+ /* @__PURE__ */ jsx(Brand$1, { brand: /* @__PURE__ */ jsx(Logo, {}) }),
453
+ /* @__PURE__ */ jsx(Copyright, {})
454
+ ] })
455
+ }
456
+ );
457
+ };
458
+ const Brand = ({ brand }) => {
459
+ return /* @__PURE__ */ jsx(
460
+ Box,
461
+ {
462
+ as: Link,
463
+ to: "/",
464
+ display: "flex",
465
+ h: { base: "40px", md: "60px" },
466
+ fontFamily: "heading",
467
+ color: useColorModeValue("gray.800", "white"),
468
+ children: brand
469
+ }
470
+ );
471
+ };
472
+ const DesktopNavItem = ({ title, url, children }) => {
473
+ const background = useColorModeValue("white", "gray.800");
474
+ const backgroundHover = useColorModeValue("brand.50", "gray.900");
475
+ return /* @__PURE__ */ jsxs(Popover, { trigger: "hover", placement: "bottom-start", children: [
476
+ /* @__PURE__ */ jsx(PopoverTrigger, { children: /* @__PURE__ */ jsx(
477
+ Text,
478
+ {
479
+ as: Link,
480
+ to: url,
481
+ p: 2,
482
+ fontSize: "sm",
483
+ fontWeight: 500,
484
+ _hover: { textDecoration: "none", color: "brand.400" },
485
+ children: title
486
+ }
487
+ ) }),
488
+ !!children && /* @__PURE__ */ jsx(PopoverContent, { p: 4, border: 0, minW: "sm", rounded: "xl", boxShadow: "xl", bg: background, children: /* @__PURE__ */ jsx(Stack, { as: "ul", children: children.map((child) => /* @__PURE__ */ jsx(
489
+ Box,
490
+ {
491
+ as: "li",
492
+ role: "group",
493
+ display: "block",
494
+ p: 2,
495
+ cursor: "pointer",
496
+ rounded: "md",
497
+ _hover: { bg: backgroundHover },
498
+ children: /* @__PURE__ */ jsxs(Stack, { direction: "row", children: [
499
+ /* @__PURE__ */ jsxs(Box, { children: [
500
+ /* @__PURE__ */ jsx(Text, { fontWeight: 500, transition: "all .3s ease", _groupHover: { color: "brand.400" }, children: child.title }),
501
+ !!child.subtitle && /* @__PURE__ */ jsx(Text, { fontSize: "sm", children: child.subtitle })
502
+ ] }),
503
+ /* @__PURE__ */ jsx(
504
+ Flex,
505
+ {
506
+ flex: 1,
507
+ justify: "flex-end",
508
+ align: "center",
509
+ opacity: 0,
510
+ transition: "all .3s ease",
511
+ transform: "translateX(-10px)",
512
+ _groupHover: { opacity: 1, transform: "translateX(0)" },
513
+ children: /* @__PURE__ */ jsx(Icon, { as: ChevronRightIcon, color: "brand.400", w: 5, h: 5 })
514
+ }
515
+ )
516
+ ] })
517
+ },
518
+ child.url
519
+ )) }) })
520
+ ] });
521
+ };
522
+ const DesktopNavigation = ({ menu }) => {
523
+ return /* @__PURE__ */ jsx(Stack, { as: "ul", direction: "row", spacing: 4, children: menu.map((item) => /* @__PURE__ */ jsx(Flex, { as: "li", children: /* @__PURE__ */ jsx(DesktopNavItem, { ...item }) }, item.url)) });
524
+ };
525
+ const MobileNavItem = ({ title, children, url }) => {
526
+ const { isOpen, onToggle } = useDisclosure();
527
+ return /* @__PURE__ */ jsxs(Stack, { w: "100%", p: 2, children: [
528
+ /* @__PURE__ */ jsxs(Flex, { align: "center", gap: 2, justify: "space-between", children: [
529
+ /* @__PURE__ */ jsx(Text, { as: Link, to: url, isTruncated: true, fontWeight: 600, children: title }),
530
+ !!children && /* @__PURE__ */ jsx(Flex, { as: "button", onClick: onToggle, children: /* @__PURE__ */ jsx(
531
+ Icon,
532
+ {
533
+ as: ChevronDownIcon,
534
+ w: 6,
535
+ h: 6,
536
+ transform: isOpen ? "rotate(180deg)" : "",
537
+ transition: "all .25s ease-in-out"
538
+ }
539
+ ) })
540
+ ] }),
541
+ /* @__PURE__ */ jsx(Collapse, { in: isOpen, animateOpacity: true, children: /* @__PURE__ */ jsx(
542
+ Stack,
543
+ {
544
+ as: "ul",
545
+ pl: 2,
546
+ borderLeft: 1,
547
+ borderStyle: "solid",
548
+ borderColor: useColorModeValue("gray.200", "gray.700"),
549
+ children: !!children && children.map((child) => /* @__PURE__ */ jsx(Flex, { as: "li", children: /* @__PURE__ */ jsx(Text, { as: Link, to: `${url}${child.url}`, py: 2, children: child.title }) }, child.url))
550
+ }
551
+ ) })
552
+ ] });
553
+ };
554
+ const MobileNavigation = ({ menu }) => {
555
+ const { isOpen, onToggle } = useDisclosure();
556
+ const background = useColorModeValue("white", "gray.800");
557
+ return menu.length ? /* @__PURE__ */ jsxs(Box, { children: [
558
+ /* @__PURE__ */ jsx(
559
+ IconButton,
560
+ {
561
+ icon: isOpen ? /* @__PURE__ */ jsx(CloseIcon, { w: 3, h: 3 }) : /* @__PURE__ */ jsx(HamburgerIcon, {}),
562
+ size: "md",
563
+ variant: "ghost",
564
+ "aria-label": "Toggle Navigation",
565
+ onClick: onToggle
566
+ }
567
+ ),
568
+ /* @__PURE__ */ jsx(Collapse, { in: isOpen, animateOpacity: true, children: /* @__PURE__ */ jsx(Box, { position: "absolute", top: 14, right: 0, w: "100vw", px: 2, children: /* @__PURE__ */ jsx(Stack, { as: "ul", spacing: 2, p: 2, w: "100%", borderRadius: "md", boxShadow: "md", bg: background, children: menu.map((item) => /* @__PURE__ */ jsx(Flex, { as: "li", children: /* @__PURE__ */ jsx(MobileNavItem, { ...item }) }, item.url)) }) }) })
569
+ ] }) : null;
570
+ };
571
+ const Navigation = ({ menu }) => {
572
+ const isDesktop = useBreakpointValue({ base: false, md: true });
573
+ return isDesktop ? /* @__PURE__ */ jsx(DesktopNavigation, { menu }) : /* @__PURE__ */ jsx(MobileNavigation, { menu });
574
+ };
575
+ const Navbar = ({ brand }) => {
576
+ const menu = [];
577
+ return /* @__PURE__ */ jsxs(Flex, { as: "nav", gap: 2, py: 1, children: [
578
+ /* @__PURE__ */ jsx(Brand, { brand }),
579
+ /* @__PURE__ */ jsx(Flex, { as: "section", flex: 1, align: "center", justifyContent: "flex-end", gap: 2, children: /* @__PURE__ */ jsx(Navigation, { menu }) })
580
+ ] });
581
+ };
582
+ const Header = () => {
583
+ return /* @__PURE__ */ jsx(
584
+ Box,
585
+ {
586
+ as: "header",
587
+ position: "sticky",
588
+ top: 0,
589
+ bg: useColorModeValue("white", "gray.900"),
590
+ color: useColorModeValue("gray.700", "gray.200"),
591
+ boxShadow: "sm",
592
+ zIndex: 100,
593
+ children: /* @__PURE__ */ jsx(Content, { children: /* @__PURE__ */ jsx(Navbar, { brand: /* @__PURE__ */ jsx(Logo, {}) }) })
594
+ }
595
+ );
596
+ };
597
+ const Hero = () => {
598
+ return /* @__PURE__ */ jsx("section", { children: /* @__PURE__ */ jsx(Content, {}) });
599
+ };
600
+ const Main = ({ children }) => {
601
+ return /* @__PURE__ */ jsx(
602
+ Flex,
603
+ {
604
+ as: "main",
605
+ direction: "column",
606
+ flexGrow: 1,
607
+ py: 4,
608
+ bg: useColorModeValue("white", "gray.800"),
609
+ color: useColorModeValue("gray.700", "gray.200"),
610
+ children
611
+ }
612
+ );
613
+ };
614
+ const ScrollToTop = () => {
615
+ const [isVisible, setIsVisible] = useState(false);
616
+ useEffect(() => {
617
+ const toggleVisibility = () => {
618
+ setIsVisible(window.scrollY > 300);
619
+ };
620
+ window.addEventListener("scroll", toggleVisibility);
621
+ return () => {
622
+ window.removeEventListener("scroll", toggleVisibility);
623
+ };
624
+ }, []);
625
+ function handleClick() {
626
+ window.scrollTo({
627
+ top: 0,
628
+ behavior: "smooth"
629
+ });
630
+ }
631
+ return /* @__PURE__ */ jsx(
632
+ Box,
633
+ {
634
+ position: "fixed",
635
+ bottom: { base: 4, md: 8, lg: 16 },
636
+ right: { base: 4, md: 8, lg: 16 },
637
+ zIndex: "1000",
638
+ opacity: isVisible ? 1 : 0,
639
+ transform: isVisible ? "translateY(0)" : "translateY(0.5rem)",
640
+ transition: "opacity 0.4s ease, transform 0.4s ease",
641
+ pointerEvents: isVisible ? "auto" : "none",
642
+ children: /* @__PURE__ */ jsx(
643
+ IconButton,
644
+ {
645
+ "aria-label": "Scroll to top",
646
+ icon: /* @__PURE__ */ jsx(ChevronUpIcon, { w: 6, h: 6 }),
647
+ size: "lg",
648
+ shadow: "lg",
649
+ colorScheme: "brand",
650
+ isRound: true,
651
+ onClick: handleClick
652
+ }
653
+ )
654
+ }
655
+ );
656
+ };
657
+ const Layout = ({ children }) => {
658
+ const content = typeof children === "function" ? children({ Hero, Content }) : /* @__PURE__ */ jsx(Content, { children });
659
+ return /* @__PURE__ */ jsxs(Stack, { spacing: 0, position: "relative", w: "100%", minH: "100dvh", children: [
660
+ /* @__PURE__ */ jsx(Header, {}),
661
+ /* @__PURE__ */ jsx(Main, { children: content }),
662
+ /* @__PURE__ */ jsx(Footer, {}),
663
+ /* @__PURE__ */ jsx(ScrollToTop, {})
664
+ ] });
665
+ };
666
+ const TitleMap = {
667
+ pros: "advantages",
668
+ cons: "disadvantages"
669
+ };
670
+ const IconMap = {
671
+ pros: CheckCircleIcon,
672
+ cons: WarningIcon
673
+ };
674
+ const IconColorMap = {
675
+ pros: "green.500",
676
+ cons: "red.500"
677
+ };
678
+ const BgColorMap = {
679
+ pros: "green",
680
+ cons: "red"
681
+ };
682
+ const ProsConsCard = ({ itemType, items }) => {
683
+ const { t: t2 } = useTranslation("prosCons");
684
+ return /* @__PURE__ */ jsxs(
685
+ Card,
686
+ {
687
+ as: "article",
688
+ flex: 1,
689
+ p: 2,
690
+ bgColor: useColorModeValue(`${BgColorMap[itemType]}.100`, `${BgColorMap[itemType]}.800`),
691
+ children: [
692
+ /* @__PURE__ */ jsx(
693
+ CardHeader,
694
+ {
695
+ as: "header",
696
+ p: 2,
697
+ borderTopRadius: "md",
698
+ bgColor: useColorModeValue("whiteAlpha.800", "blackAlpha.800"),
699
+ children: /* @__PURE__ */ jsx(Heading, { as: "h3", textTransform: "uppercase", fontSize: "xl", children: t2(TitleMap[itemType]) })
700
+ }
701
+ ),
702
+ /* @__PURE__ */ jsx(
703
+ CardBody,
704
+ {
705
+ as: "section",
706
+ p: 2,
707
+ borderBottomRadius: "md",
708
+ bgColor: useColorModeValue("whiteAlpha.800", "blackAlpha.800"),
709
+ children: /* @__PURE__ */ jsx(List, { spacing: 4, p: 0, children: items.map(({ title, description }) => /* @__PURE__ */ jsxs(ListItem, { display: "flex", children: [
710
+ /* @__PURE__ */ jsx(ListIcon, { as: IconMap[itemType], w: 6, h: 6, color: IconColorMap[itemType] }),
711
+ /* @__PURE__ */ jsxs(Text, { fontWeight: "semibold", fontSize: "md", children: [
712
+ title,
713
+ !!description && /* @__PURE__ */ jsxs(Text, { as: "span", fontWeight: "normal", children: [
714
+ ": ",
715
+ description
716
+ ] })
717
+ ] })
718
+ ] }, title)) })
719
+ }
720
+ )
721
+ ]
722
+ }
723
+ );
724
+ };
725
+ const ProsCons = ({ items, ...boxProps }) => {
726
+ const { pros, cons } = items;
727
+ return /* @__PURE__ */ jsxs(Flex, { as: "section", direction: { base: "column", md: "row" }, gap: 4, ...boxProps, children: [
728
+ /* @__PURE__ */ jsx(ProsConsCard, { itemType: "pros", items: pros }),
729
+ /* @__PURE__ */ jsx(ProsConsCard, { itemType: "cons", items: cons })
730
+ ] });
731
+ };
732
+ const Seo = ({ children, siteMetadata, title, description, lang }) => {
733
+ const { title: defaultTitle, description: defaultDescription, lang: defaultLang, siteUrl } = siteMetadata;
734
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
735
+ /* @__PURE__ */ jsx("html", { lang: lang ?? defaultLang }),
736
+ /* @__PURE__ */ jsx("title", { children: title ? typeof title === "string" ? title : title({
737
+ domain: getDomain(siteUrl),
738
+ currentYear: getCurrentYear(),
739
+ currentMonth: getCurrentMonth()
740
+ }) : defaultTitle }),
741
+ /* @__PURE__ */ jsx(
742
+ "meta",
743
+ {
744
+ name: "description",
745
+ content: description ? typeof description === "string" ? description : description({
746
+ domain: getDomain(siteUrl),
747
+ currentYear: getCurrentYear(),
748
+ currentMonth: getCurrentMonth()
749
+ }) : defaultDescription
750
+ }
751
+ ),
752
+ children
753
+ ] });
754
+ };
755
+ export {
756
+ Author as A,
757
+ ContactForm as C,
758
+ ExpertTip as E,
759
+ Faq as F,
760
+ GameDemo as G,
761
+ HowTo as H,
762
+ Layout as L,
763
+ ProsCons as P,
764
+ Seo as S,
765
+ Features as a,
766
+ GameInfo as b
767
+ };