@anywayseo/tools 2.5.1 → 3.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 (37) hide show
  1. package/dist/components/author-card/index.d.ts +7 -0
  2. package/dist/components/{author → base/author}/index.d.ts +3 -3
  3. package/dist/components/base/index.d.ts +1 -1
  4. package/dist/components/index.cjs +5 -3
  5. package/dist/components/index.d.ts +4 -2
  6. package/dist/components/index.mjs +11 -9
  7. package/dist/components/not-found/index.d.ts +3 -0
  8. package/dist/components/rich-text-renderer/index.d.ts +6 -0
  9. package/dist/components/seo/index.d.ts +7 -12
  10. package/dist/components/seo/types.d.ts +6 -0
  11. package/dist/components/seo/utils.d.ts +2 -0
  12. package/dist/components/{expert-tip → tip}/index.d.ts +4 -4
  13. package/dist/i18n/index.cjs +1 -1
  14. package/dist/i18n/index.mjs +1 -1
  15. package/dist/{index-BqUBNm7v.mjs → index-25M8hPOF.mjs} +1 -6
  16. package/dist/{index-BEqFPNAt.js → index-Biz1dDqA.js} +12 -12
  17. package/dist/{index-D2APUOog.js → index-Cte2-g6s.js} +1 -6
  18. package/dist/{index-CIHivV4r.mjs → index-DIxzgBCq.mjs} +119 -98
  19. package/dist/{index-F6_fGeRI.mjs → index-DoBCANwf.mjs} +12 -12
  20. package/dist/index-HmqLMmGf.js +1036 -0
  21. package/dist/index.cjs +7 -6
  22. package/dist/index.mjs +12 -11
  23. package/dist/providers/site-provider/index.d.ts +1 -2
  24. package/dist/types/components/how-to/index.d.ts +2 -2
  25. package/dist/types/components/image/index.d.ts +4 -0
  26. package/dist/types/content/author/index.d.ts +5 -4
  27. package/dist/types/content/index.d.ts +1 -0
  28. package/dist/types/content/seo/index.d.ts +4 -0
  29. package/dist/types/site/index.d.ts +8 -14
  30. package/dist/utils/index.cjs +1 -2
  31. package/dist/utils/index.d.ts +0 -1
  32. package/dist/utils/index.mjs +1 -2
  33. package/package.json +3 -2
  34. package/dist/components/base/expert/index.d.ts +0 -8
  35. package/dist/index-CQRefU3H.js +0 -1015
  36. package/dist/utils/url/index.d.ts +0 -1
  37. /package/dist/components/base/{expert → author}/bio/index.d.ts +0 -0
@@ -0,0 +1,1036 @@
1
+ "use strict";
2
+ const jsxRuntime = require("react/jsx-runtime");
3
+ const react$1 = require("@chakra-ui/react");
4
+ const reactI18next = require("react-i18next");
5
+ const index = require("./index-Cte2-g6s.js");
6
+ const i18n = require("./index-Biz1dDqA.js");
7
+ require("@ctrl/tinycolor");
8
+ const react = require("react");
9
+ const icons = require("@chakra-ui/icons");
10
+ const index$1 = require("./index-IpSV-c71.js");
11
+ const react$2 = require("@mdx-js/react");
12
+ const index$2 = require("./index-BhsXlbd8.js");
13
+ const i18n$1 = require("i18next");
14
+ const gatsby = require("gatsby");
15
+ const Markdown = require("react-markdown");
16
+ const ONE_LINE_HEIGHT = 24;
17
+ const Bio = ({ content, maxLines = 1 }) => {
18
+ const ref = react.useRef(null);
19
+ const [showToggle, setShowToggle] = react.useState(false);
20
+ const [isExpanded, setIsExpanded] = react.useState(false);
21
+ const { t } = reactI18next.useTranslation("author");
22
+ react.useLayoutEffect(() => {
23
+ if (ref.current) {
24
+ const { scrollWidth, clientWidth, scrollHeight, clientHeight } = ref.current;
25
+ const isClamped = scrollWidth > clientWidth || scrollHeight > clientHeight;
26
+ setShowToggle(isClamped);
27
+ }
28
+ return () => {
29
+ setShowToggle(false);
30
+ };
31
+ }, []);
32
+ function handleClick() {
33
+ setIsExpanded((prev) => !prev);
34
+ }
35
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Box, { children: [
36
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Collapse, { in: isExpanded, startingHeight: ONE_LINE_HEIGHT * maxLines, children: /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { ref, fontSize: "md", noOfLines: isExpanded ? void 0 : maxLines, children: content }) }),
37
+ showToggle && /* @__PURE__ */ jsxRuntime.jsx(react$1.Button, { size: "sm", variant: "link", colorScheme: "blue", onClick: handleClick, children: isExpanded ? t("action.collapse") : t("action.expand") })
38
+ ] });
39
+ };
40
+ const Author = ({ author, variant }) => {
41
+ const { name, role, bio, avatar } = author;
42
+ const imageComponent = typeof avatar === "string" ? /* @__PURE__ */ jsxRuntime.jsx(react$1.Image, { src: avatar, alt: name, rounded: "full" }) : avatar;
43
+ if (variant === "short") {
44
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Flex, { as: "article", align: "center", gap: 4, children: [
45
+ !!imageComponent && /* @__PURE__ */ jsxRuntime.jsx(react$1.Box, { w: 12, h: 12, children: imageComponent }),
46
+ /* @__PURE__ */ jsxRuntime.jsxs(react$1.Box, { fontWeight: "semibold", children: [
47
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { children: name }),
48
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { color: "gray.500", children: role })
49
+ ] })
50
+ ] });
51
+ }
52
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
53
+ !!imageComponent && /* @__PURE__ */ jsxRuntime.jsx(react$1.Flex, { grow: 1, maxW: { base: 48, sm: 32 }, children: imageComponent }),
54
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Flex, { w: "100%", children: /* @__PURE__ */ jsxRuntime.jsxs(react$1.Stack, { children: [
55
+ /* @__PURE__ */ jsxRuntime.jsxs(react$1.Text, { fontSize: "lg", fontWeight: 600, children: [
56
+ name,
57
+ ", ",
58
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { as: "span", color: "gray.500", children: role })
59
+ ] }),
60
+ /* @__PURE__ */ jsxRuntime.jsx(Bio, { content: bio })
61
+ ] }) })
62
+ ] });
63
+ };
64
+ const Center = ({ children, ...boxProps }) => {
65
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.Center, { ...boxProps, children });
66
+ };
67
+ const defaultColumns = { base: 1, sm: 2, md: 3, lg: 4, xl: 5 };
68
+ const Grid = ({ items, columns = defaultColumns, gap, render, getKey, ...boxProps }) => {
69
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.SimpleGrid, { as: "ul", columns, spacing: gap, p: 0, m: 0, listStyleType: "none", ...boxProps, children: items.map((item, index2) => /* @__PURE__ */ jsxRuntime.jsx(react$1.Box, { as: "li", children: render(item) }, getKey ? getKey(item) : index2)) });
70
+ };
71
+ const LinkButton = ({ label, url, width = "auto", ...boxProps }) => {
72
+ return /* @__PURE__ */ jsxRuntime.jsx(
73
+ react$1.Button,
74
+ {
75
+ as: react$1.Link,
76
+ href: url,
77
+ w: width,
78
+ bg: "brand.600",
79
+ textTransform: "uppercase",
80
+ _hover: { textDecoration: "none", bg: "brand.300" },
81
+ _active: { transform: "scale(0.95)" },
82
+ ...boxProps,
83
+ children: label
84
+ }
85
+ );
86
+ };
87
+ const ColorMap = {
88
+ light: "gray.200",
89
+ dark: "gray.700"
90
+ };
91
+ const PulseButton = ({ label, colorScheme = "light", to, onClick }) => {
92
+ return /* @__PURE__ */ jsxRuntime.jsx(
93
+ react$1.Button,
94
+ {
95
+ size: { base: "sm", md: "lg" },
96
+ color: ColorMap[colorScheme],
97
+ bgColor: "brand.500",
98
+ animation: `${index.Animation.pulse} 2s infinite linear`,
99
+ _hover: { bgColor: "brand.200", color: "gray.700" },
100
+ ...to ? { as: react$1.Link, href: to } : { onClick },
101
+ children: label
102
+ }
103
+ );
104
+ };
105
+ const AuthorCard = ({ author, ...boxProps }) => {
106
+ const { t } = reactI18next.useTranslation("author");
107
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Card, { as: "article", variant: "filled", ...boxProps, children: [
108
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.CardHeader, { pb: 0, children: /* @__PURE__ */ jsxRuntime.jsx(react$1.Heading, { size: "md", children: t("title") }) }),
109
+ /* @__PURE__ */ jsxRuntime.jsx(
110
+ react$1.CardBody,
111
+ {
112
+ display: "flex",
113
+ flexDirection: { base: "column", sm: "row" },
114
+ alignItems: { base: "center", sm: "flex-start" },
115
+ gap: 4,
116
+ children: /* @__PURE__ */ jsxRuntime.jsx(Author, { author, variant: "full" })
117
+ }
118
+ )
119
+ ] });
120
+ };
121
+ const BonusCardContent = ({ content }) => {
122
+ const { t } = reactI18next.useTranslation("author");
123
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.Popover, { autoFocus: false, isLazy: true, lazyBehavior: "keepMounted", children: ({ isOpen }) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
124
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.PopoverTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx(react$1.Button, { size: "sm", variant: "link", color: "white", children: isOpen ? t("action.collapse") : t("action.expand") }) }),
125
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(react$1.PopoverContent, { children: /* @__PURE__ */ jsxRuntime.jsx(react$1.PopoverBody, { children: Array.isArray(content) ? /* @__PURE__ */ jsxRuntime.jsx(react$1.Stack, { children: content.map((paragraph, index2) => /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { as: "span", children: paragraph }, index2)) }) : /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { children: content }) }) }) })
126
+ ] }) });
127
+ };
128
+ const BonusCardTitle = ({ content }) => {
129
+ return /* @__PURE__ */ jsxRuntime.jsx(
130
+ react$1.Text,
131
+ {
132
+ as: "h3",
133
+ display: "inline-block",
134
+ py: 1,
135
+ px: 2,
136
+ borderRadius: "md",
137
+ bg: "yellow",
138
+ color: "black",
139
+ fontWeight: "bold",
140
+ fontSize: "lg",
141
+ children: content
142
+ }
143
+ );
144
+ };
145
+ const BonusCard = ({ title, subtitle, content, link, image, className }) => {
146
+ return /* @__PURE__ */ jsxRuntime.jsxs(
147
+ react$1.Card,
148
+ {
149
+ as: "article",
150
+ h: "full",
151
+ color: "whiteAlpha.900",
152
+ bg: "linear-gradient(90deg, #3b1f47, #731d58)",
153
+ _before: image ? {
154
+ content: '""',
155
+ position: "absolute",
156
+ top: 0,
157
+ left: 0,
158
+ w: "100%",
159
+ h: "100%",
160
+ bgImage: `url(${image})`,
161
+ bgSize: "cover",
162
+ bgPosition: "center",
163
+ filter: "blur(0.05em) opacity(50%)",
164
+ zIndex: 0
165
+ } : void 0,
166
+ className,
167
+ children: [
168
+ /* @__PURE__ */ jsxRuntime.jsxs(react$1.CardBody, { as: "section", pb: 0, flex: 1, children: [
169
+ /* @__PURE__ */ jsxRuntime.jsx(BonusCardTitle, { content: title }),
170
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { fontSize: "2xl", fontWeight: "bold", my: 2, children: subtitle }),
171
+ /* @__PURE__ */ jsxRuntime.jsx(BonusCardContent, { content })
172
+ ] }),
173
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.CardFooter, { as: "footer", p: 4, children: /* @__PURE__ */ jsxRuntime.jsx(LinkButton, { ...link, width: "full" }) })
174
+ ]
175
+ }
176
+ );
177
+ };
178
+ const ContactForm = ({ ...boxProps }) => {
179
+ const toast = react$1.useToast();
180
+ const { t } = reactI18next.useTranslation("contactForm");
181
+ function handleSubmit(event) {
182
+ event.preventDefault();
183
+ const form = event.currentTarget;
184
+ const formData = new FormData(form);
185
+ const name = formData.get("name");
186
+ const email = formData.get("email");
187
+ const message = formData.get("message");
188
+ if (name && email && message) {
189
+ form.reset();
190
+ toast({
191
+ title: t("notification.title", { name }),
192
+ description: t("notification.description", { email }),
193
+ colorScheme: "brand",
194
+ status: "success",
195
+ duration: 5e3,
196
+ isClosable: true
197
+ });
198
+ } else {
199
+ console.error("Please fill out both fields");
200
+ }
201
+ }
202
+ return /* @__PURE__ */ jsxRuntime.jsx(
203
+ react$1.Box,
204
+ {
205
+ as: "form",
206
+ borderRadius: "lg",
207
+ p: 8,
208
+ color: react$1.useColorModeValue("gray.700", "whiteAlpha.900"),
209
+ bg: react$1.useColorModeValue("white", "gray.700"),
210
+ shadow: "base",
211
+ onSubmit: handleSubmit,
212
+ ...boxProps,
213
+ children: /* @__PURE__ */ jsxRuntime.jsxs(react$1.VStack, { spacing: 4, children: [
214
+ /* @__PURE__ */ jsxRuntime.jsxs(react$1.FormControl, { isRequired: true, children: [
215
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.FormLabel, { children: t("field.name.label") }),
216
+ /* @__PURE__ */ jsxRuntime.jsxs(react$1.InputGroup, { children: [
217
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.InputLeftElement, { children: /* @__PURE__ */ jsxRuntime.jsx(
218
+ "svg",
219
+ {
220
+ xmlns: "http://www.w3.org/2000/svg",
221
+ width: "16",
222
+ height: "16",
223
+ fill: "currentColor",
224
+ className: "bi bi-person-fill",
225
+ viewBox: "0 0 16 16",
226
+ children: /* @__PURE__ */ jsxRuntime.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" })
227
+ }
228
+ ) }),
229
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Input, { type: "text", name: "name", placeholder: t("field.name.placeholder") })
230
+ ] })
231
+ ] }),
232
+ /* @__PURE__ */ jsxRuntime.jsxs(react$1.FormControl, { isRequired: true, children: [
233
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.FormLabel, { children: t("field.email.label") }),
234
+ /* @__PURE__ */ jsxRuntime.jsxs(react$1.InputGroup, { children: [
235
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.InputLeftElement, { children: /* @__PURE__ */ jsxRuntime.jsx(icons.EmailIcon, {}) }),
236
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Input, { type: "email", name: "email", placeholder: t("field.email.placeholder") })
237
+ ] })
238
+ ] }),
239
+ /* @__PURE__ */ jsxRuntime.jsxs(react$1.FormControl, { isRequired: true, children: [
240
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.FormLabel, { children: t("field.message.label") }),
241
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Textarea, { name: "message", placeholder: t("field.message.placeholder"), rows: 6, resize: "none" })
242
+ ] }),
243
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Button, { type: "submit", colorScheme: "brand", width: "full", children: t("action.send") })
244
+ ] })
245
+ }
246
+ );
247
+ };
248
+ const Faq = ({ items, ...boxProps }) => {
249
+ const { bgColor, color } = index$1.usePrimaryColors();
250
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.Accordion, { allowToggle: true, ...boxProps, children: items.map(({ question, answer }) => {
251
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$1.AccordionItem, { border: 0, children: [
252
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Box, { as: "h3", children: /* @__PURE__ */ jsxRuntime.jsxs(react$1.AccordionButton, { _hover: { color, bgColor }, children: [
253
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Box, { as: "span", flex: "1", textAlign: "left", fontWeight: "bold", children: question }),
254
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.AccordionIcon, {})
255
+ ] }) }),
256
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.AccordionPanel, { children: answer })
257
+ ] }, question);
258
+ }) });
259
+ };
260
+ const FeatureCard = ({ title, description }) => {
261
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Card, { as: "article", variant: "outline", textAlign: "center", h: "100%", children: [
262
+ /* @__PURE__ */ jsxRuntime.jsxs(react$1.CardHeader, { as: "header", display: "flex", alignItems: "center", justifyContent: "center", gap: 2, pb: 2, children: [
263
+ /* @__PURE__ */ jsxRuntime.jsx(icons.StarIcon, { w: 8, h: 8, color: "yellow.400" }),
264
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { fontWeight: 600, children: title }),
265
+ /* @__PURE__ */ jsxRuntime.jsx(icons.StarIcon, { w: 8, h: 8, color: "yellow.400" })
266
+ ] }),
267
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.CardBody, { as: "section", pt: 0, children: /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { color: "gray.200", children: description }) })
268
+ ] });
269
+ };
270
+ const Features = ({ features, ...boxProps }) => {
271
+ return /* @__PURE__ */ jsxRuntime.jsx(
272
+ Grid,
273
+ {
274
+ items: features,
275
+ columns: { base: 1, md: 2, lg: 3 },
276
+ gap: 10,
277
+ getKey: ({ title }) => title,
278
+ render: (item) => /* @__PURE__ */ jsxRuntime.jsx(FeatureCard, { ...item }),
279
+ ...boxProps
280
+ }
281
+ );
282
+ };
283
+ const GameCard = ({ name, description, image, link, height = "auto" }) => {
284
+ return /* @__PURE__ */ jsxRuntime.jsxs(
285
+ react$1.LinkBox,
286
+ {
287
+ as: "article",
288
+ rounded: "md",
289
+ borderWidth: 1,
290
+ transition: "transform 0.2s ease",
291
+ cursor: link ? "pointer" : "default",
292
+ overflow: "hidden",
293
+ bg: "blackAlpha.200",
294
+ height,
295
+ _hover: { transform: "scale(1.1)" },
296
+ children: [
297
+ typeof image === "string" ? /* @__PURE__ */ jsxRuntime.jsx(react$1.Image, { src: image, alt: name, w: "100%", aspectRatio: "16/9", objectFit: "cover", objectPosition: "center" }) : !!image && /* @__PURE__ */ jsxRuntime.jsx(react$1.Box, { w: "100%", aspectRatio: "16/9", children: image }),
298
+ /* @__PURE__ */ jsxRuntime.jsxs(react$1.Box, { as: "section", rounded: "md", p: 4, children: [
299
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { as: "span", children: link ? /* @__PURE__ */ jsxRuntime.jsx(react$1.LinkOverlay, { href: link, children: name }) : name }),
300
+ !!description && /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { fontSize: "sm", color: "gray.600", children: description })
301
+ ] })
302
+ ]
303
+ }
304
+ );
305
+ };
306
+ const GameDemoContent = ({ src, isFullscreen, isLoaded, onLoad, onToggleFullscreen }) => {
307
+ const { t } = reactI18next.useTranslation("gameDemo");
308
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
309
+ /* @__PURE__ */ jsxRuntime.jsx(
310
+ react$1.Box,
311
+ {
312
+ as: "iframe",
313
+ src,
314
+ sandbox: "allow-scripts allow-same-origin",
315
+ loading: "lazy",
316
+ w: "100%",
317
+ h: "100%",
318
+ allowFullScreen: true,
319
+ onLoad,
320
+ children: /* @__PURE__ */ jsxRuntime.jsx("p", { children: t("warning") })
321
+ }
322
+ ),
323
+ /* @__PURE__ */ jsxRuntime.jsx(
324
+ react$1.IconButton,
325
+ {
326
+ icon: isFullscreen ? /* @__PURE__ */ jsxRuntime.jsx(icons.CloseIcon, { w: 3, h: 3 }) : /* @__PURE__ */ jsxRuntime.jsx(icons.ExternalLinkIcon, { w: 4, h: 4 }),
327
+ size: "sm",
328
+ variant: "outline",
329
+ title: t(isFullscreen ? "action.deactivateFullscreen" : "action.activateFullscreen"),
330
+ "aria-label": "Fullscreen mode Toggle",
331
+ isRound: true,
332
+ disabled: !isLoaded,
333
+ position: "absolute",
334
+ top: 2,
335
+ left: 2,
336
+ border: "none",
337
+ color: "white",
338
+ _hover: { bgColor: "whiteAlpha.400" },
339
+ onClick: onToggleFullscreen
340
+ }
341
+ ),
342
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.AbsoluteCenter, { children: /* @__PURE__ */ jsxRuntime.jsx(react$1.Spinner, { size: "xl", thickness: "0.6rem", display: isLoaded ? "none" : "block", color: "brand.100" }) })
343
+ ] });
344
+ };
345
+ const GameDemoPreview = ({ image, alt, imageFit = "contain", onPlay }) => {
346
+ const { t } = reactI18next.useTranslation("gameDemo");
347
+ const imageComponent = typeof image === "string" ? /* @__PURE__ */ jsxRuntime.jsx(react$1.Image, { src: image, alt, objectFit: imageFit }) : image;
348
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
349
+ imageComponent,
350
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.AbsoluteCenter, { children: /* @__PURE__ */ jsxRuntime.jsx(PulseButton, { label: t("action.playForFree"), onClick: onPlay }) })
351
+ ] });
352
+ };
353
+ const GameDemo = ({ name, src, previewImage, previewImageFit, ...boxProps }) => {
354
+ const [isRunning, setIsRunning] = react.useState(false);
355
+ const [isLoaded, setIsLoaded] = react.useState(false);
356
+ const { isOpen: isFullscreen, onToggle } = react$1.useDisclosure({ defaultIsOpen: false });
357
+ function handlePlay() {
358
+ setIsRunning(true);
359
+ }
360
+ function onLoad() {
361
+ setIsLoaded(true);
362
+ }
363
+ function handleToggleFullscreen() {
364
+ document.body.style.overflowY = isFullscreen ? "auto" : "hidden";
365
+ onToggle();
366
+ }
367
+ return /* @__PURE__ */ jsxRuntime.jsx(
368
+ react$1.Box,
369
+ {
370
+ as: "article",
371
+ display: "grid",
372
+ w: "100%",
373
+ aspectRatio: "16/9 auto",
374
+ ...isFullscreen ? { zIndex: 100, inset: 0, position: "fixed", h: "100dvh" } : { position: "relative" },
375
+ ...boxProps,
376
+ children: isRunning ? /* @__PURE__ */ jsxRuntime.jsx(
377
+ GameDemoContent,
378
+ {
379
+ src,
380
+ isFullscreen,
381
+ isLoaded,
382
+ onLoad,
383
+ onToggleFullscreen: handleToggleFullscreen
384
+ }
385
+ ) : /* @__PURE__ */ jsxRuntime.jsx(GameDemoPreview, { image: previewImage, alt: name, imageFit: previewImageFit, onPlay: handlePlay })
386
+ }
387
+ );
388
+ };
389
+ const GameInfoItem = ({ title, value }) => {
390
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Flex, { gap: 2, children: [
391
+ /* @__PURE__ */ jsxRuntime.jsxs(react$1.Text, { w: "50%", color: "gray.500", textTransform: "capitalize", children: [
392
+ title,
393
+ ":"
394
+ ] }),
395
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { w: "50%", textTransform: "capitalize", children: value })
396
+ ] });
397
+ };
398
+ const VISIBLE_LANGUAGE_NUMBER = 5;
399
+ function stringifyHasFeature(value) {
400
+ return i18n$1.t(`gameInfo:value.boolean.${value}`);
401
+ }
402
+ function stringifyVolatility(value) {
403
+ return i18n$1.t(`gameInfo:value.volatility.${value}`);
404
+ }
405
+ function stringifyArray(array) {
406
+ return array.join(", ");
407
+ }
408
+ function stringifyLanguageArray(languages) {
409
+ return languages.length > VISIBLE_LANGUAGE_NUMBER ? `${stringifyArray(languages.slice(0, VISIBLE_LANGUAGE_NUMBER))}, +${languages.length - VISIBLE_LANGUAGE_NUMBER}` : stringifyArray(languages);
410
+ }
411
+ function getGameInfoItemValue(key, value, currency) {
412
+ let formattedValue = "";
413
+ if (typeof value !== "string") {
414
+ if (key === i18n.GameCharacteristic.Rtp) {
415
+ formattedValue = index.formatNumber(value, { percent: "real", precision: 3 });
416
+ }
417
+ if (key === i18n.GameCharacteristic.MinBet || key === i18n.GameCharacteristic.MaxBet || key === i18n.GameCharacteristic.MaxWin) {
418
+ if (Array.isArray(currency)) {
419
+ const [primary, ...secondaries] = currency || ["USD"];
420
+ const primaryValue = index.formatNumber(value, { currency: primary });
421
+ formattedValue = secondaries.length ? `${primaryValue} (${secondaries.map((currency2) => index.getCurrencySymbol(currency2)).join(", ")})` : primaryValue;
422
+ } else {
423
+ formattedValue = index.formatNumber(value, { currency });
424
+ }
425
+ }
426
+ if (key === i18n.GameCharacteristic.Compatibility || key === i18n.GameCharacteristic.BonusFeatures) {
427
+ formattedValue = stringifyArray(value);
428
+ }
429
+ if (key === i18n.GameCharacteristic.Languages) {
430
+ formattedValue = stringifyLanguageArray(value);
431
+ }
432
+ if (typeof value === "boolean") {
433
+ formattedValue = stringifyHasFeature(value);
434
+ }
435
+ }
436
+ if (key === i18n.GameCharacteristic.ReleaseDate) {
437
+ formattedValue = index.formatDate({ value, options: { year: "numeric", month: "long" } });
438
+ }
439
+ if (key === i18n.GameCharacteristic.Volatility) {
440
+ formattedValue = stringifyVolatility(value);
441
+ }
442
+ if (!formattedValue) {
443
+ formattedValue = value.toLocaleString();
444
+ }
445
+ return formattedValue;
446
+ }
447
+ const GameInfo = ({ info }) => {
448
+ const { metadata } = index$2.useSiteContext();
449
+ const { currency } = metadata;
450
+ const { t } = reactI18next.useTranslation("gameInfo");
451
+ return /* @__PURE__ */ jsxRuntime.jsx(
452
+ react$1.Box,
453
+ {
454
+ as: "aside",
455
+ float: { base: "none", lg: "right" },
456
+ w: { base: "100%", lg: "xs" },
457
+ ml: { base: 0, lg: 4 },
458
+ mb: { base: 0, lg: 4 },
459
+ children: /* @__PURE__ */ jsxRuntime.jsxs(react$1.Card, { as: "article", variant: "outline", h: "100%", p: 2, children: [
460
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.CardHeader, { as: "header", p: 0, children: /* @__PURE__ */ jsxRuntime.jsx(react$1.Heading, { as: "h2", fontSize: "xl", children: t("title") }) }),
461
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.CardBody, { as: "section", p: 0, children: Object.entries(info).map(([group, items]) => /* @__PURE__ */ jsxRuntime.jsxs(react.Fragment, { children: [
462
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Divider, { my: 2 }),
463
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { fontWeight: "semibold", mb: 2, children: t(`group.${group}`) }),
464
+ Object.entries(items).map(([itemKey, itemValue]) => {
465
+ const feature = itemKey;
466
+ const value = getGameInfoItemValue(feature, itemValue, currency);
467
+ return /* @__PURE__ */ jsxRuntime.jsx(GameInfoItem, { title: t(`feature.${feature}`), value }, itemKey);
468
+ })
469
+ ] }, group)) })
470
+ ] })
471
+ }
472
+ );
473
+ };
474
+ const HowTo = ({ steps, ...boxProps }) => {
475
+ const { color, bgColor } = index$1.usePrimaryColors();
476
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.SimpleGrid, { as: "ol", columns: { base: 1, md: 2, lg: 3 }, gap: 4, p: 0, ...boxProps, children: steps.map(({ title, description, thumbnail }, index2) => /* @__PURE__ */ jsxRuntime.jsxs(react$1.Flex, { as: "li", alignItems: "flex-start", gap: 4, children: [
477
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Circle, { size: 12, bgColor, color, fontSize: "lg", fontWeight: "bold", children: String(index2 + 1) }),
478
+ /* @__PURE__ */ jsxRuntime.jsxs(react$1.Stack, { flex: 1, children: [
479
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { fontSize: "lg", fontWeight: "bold", children: title }),
480
+ typeof thumbnail === "string" ? /* @__PURE__ */ jsxRuntime.jsx(react$1.Image, { src: thumbnail, alt: title, aspectRatio: "16/9", objectFit: "cover" }) : thumbnail,
481
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { children: description })
482
+ ] })
483
+ ] }, index2)) });
484
+ };
485
+ const Container = ({ children }) => {
486
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.Container, { maxW: "container.xl", children });
487
+ };
488
+ const Content = ({ children }) => {
489
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.Box, { as: "section", py: 4, children: /* @__PURE__ */ jsxRuntime.jsx(Container, { children }) });
490
+ };
491
+ const Logo = () => {
492
+ const { metadata } = index$2.useSiteContext();
493
+ const { logo } = metadata;
494
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.Box, { display: "flex", h: { base: 10, md: 14 }, overflow: "hidden", children: typeof logo === "string" ? /* @__PURE__ */ jsxRuntime.jsx(react$1.Image, { src: logo, alt: "Logo", objectFit: "contain" }) : logo });
495
+ };
496
+ const Brand$1 = ({ brand }) => {
497
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Box, { position: "relative", my: 2, py: 8, children: [
498
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Divider, {}),
499
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.AbsoluteCenter, { display: "flex", bgColor: react$1.useColorModeValue("gray.50", "gray.900"), children: /* @__PURE__ */ jsxRuntime.jsx(gatsby.Link, { to: "/", children: brand }) })
500
+ ] });
501
+ };
502
+ const Copyright = () => {
503
+ const { metadata } = index$2.useSiteContext();
504
+ const { name: siteName } = metadata;
505
+ const { t } = reactI18next.useTranslation("footer");
506
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { as: "small", colorScheme: "gray", display: "flex", align: "center", justifyContent: "center", children: t("copyright", { year: index.getCurrentYear(), siteName }) });
507
+ };
508
+ const Disclaimer = () => {
509
+ const { metadata } = index$2.useSiteContext();
510
+ const { name: siteName } = metadata;
511
+ const { t } = reactI18next.useTranslation("footer");
512
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Text, { as: "small", colorScheme: "gray", fontSize: "sm", children: [
513
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { as: "span", fontWeight: "bold", color: "red.600", children: t("disclaimer.title") }),
514
+ t("disclaimer.description", { siteName })
515
+ ] });
516
+ };
517
+ const Extra = ({ children }) => {
518
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.Box, { as: "section", my: 2, children });
519
+ };
520
+ const Navigation$1 = ({ menu }) => {
521
+ return /* @__PURE__ */ jsxRuntime.jsx(
522
+ react$1.SimpleGrid,
523
+ {
524
+ as: "ul",
525
+ columns: { base: 1, sm: 2, md: 4 },
526
+ mt: 4,
527
+ mb: 6,
528
+ p: 0,
529
+ spacing: 4,
530
+ justifyItems: { base: "flex-start", md: "center" },
531
+ justifyContent: "space-between",
532
+ children: menu.map(({ path, label }, index2) => /* @__PURE__ */ jsxRuntime.jsx(react$1.Flex, { as: "li", children: /* @__PURE__ */ jsxRuntime.jsx(
533
+ react$1.Text,
534
+ {
535
+ as: gatsby.Link,
536
+ to: path,
537
+ fontSize: "md",
538
+ fontWeight: "semibold",
539
+ colorScheme: "gray",
540
+ _hover: { textDecoration: "none", color: "brand.400" },
541
+ children: label
542
+ },
543
+ path
544
+ ) }, index2))
545
+ }
546
+ );
547
+ };
548
+ const Footer = () => {
549
+ var _a, _b, _c;
550
+ const { configs } = index$2.useSiteContext();
551
+ const navigation = ((_a = configs == null ? void 0 : configs.footer) == null ? void 0 : _a.navigation) ?? [];
552
+ const extra = (_b = configs == null ? void 0 : configs.footer) == null ? void 0 : _b.extra;
553
+ const showDisclaimer = ((_c = configs == null ? void 0 : configs.footer) == null ? void 0 : _c.showDisclaimer) ?? true;
554
+ const hasNavigation = !!navigation.length;
555
+ const hasExtra = !!extra;
556
+ return /* @__PURE__ */ jsxRuntime.jsx(
557
+ react$1.Box,
558
+ {
559
+ as: "footer",
560
+ bg: react$1.useColorModeValue("gray.50", "gray.900"),
561
+ color: react$1.useColorModeValue("gray.700", "gray.200"),
562
+ py: 4,
563
+ children: /* @__PURE__ */ jsxRuntime.jsxs(Container, { children: [
564
+ hasNavigation && /* @__PURE__ */ jsxRuntime.jsx(Navigation$1, { menu: navigation }),
565
+ hasExtra && /* @__PURE__ */ jsxRuntime.jsx(Extra, { children: extra }),
566
+ showDisclaimer && /* @__PURE__ */ jsxRuntime.jsx(Disclaimer, {}),
567
+ /* @__PURE__ */ jsxRuntime.jsx(Brand$1, { brand: /* @__PURE__ */ jsxRuntime.jsx(Logo, {}) }),
568
+ /* @__PURE__ */ jsxRuntime.jsx(Copyright, {})
569
+ ] })
570
+ }
571
+ );
572
+ };
573
+ const Brand = ({ brand }) => {
574
+ return /* @__PURE__ */ jsxRuntime.jsx(gatsby.Link, { to: "/", children: brand });
575
+ };
576
+ const NavLink = react.forwardRef(({ path, label }, ref) => {
577
+ return /* @__PURE__ */ jsxRuntime.jsx(
578
+ react$1.Text,
579
+ {
580
+ ref,
581
+ as: gatsby.Link,
582
+ to: path,
583
+ p: 2,
584
+ fontWeight: "semibold",
585
+ _hover: { textDecoration: "none", color: "brand.400" },
586
+ children: label
587
+ }
588
+ );
589
+ });
590
+ NavLink.displayName = "NavLink";
591
+ const NavList$1 = ({ path, label, children }) => {
592
+ const background = react$1.useColorModeValue("white", "gray.800");
593
+ const backgroundHover = react$1.useColorModeValue("brand.50", "gray.900");
594
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Popover, { trigger: "hover", placement: "bottom-start", children: [
595
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.PopoverTrigger, { children: /* @__PURE__ */ jsxRuntime.jsx(
596
+ react$1.Text,
597
+ {
598
+ p: 2,
599
+ fontWeight: "semibold",
600
+ cursor: "pointer",
601
+ tabIndex: 0,
602
+ _hover: { textDecoration: "none", color: "brand.400" },
603
+ children: label
604
+ }
605
+ ) }),
606
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.PopoverContent, { p: 2, border: 0, minW: "sm", rounded: "xl", boxShadow: "xl", bg: background, children: /* @__PURE__ */ jsxRuntime.jsx(react$1.List, { spacing: 2, p: 0, children: children == null ? void 0 : children.map((child, index2) => /* @__PURE__ */ jsxRuntime.jsx(react$1.ListItem, { rounded: "md", _hover: { bg: backgroundHover }, children: /* @__PURE__ */ jsxRuntime.jsxs(react$1.Flex, { as: gatsby.Link, to: `${path}${child.path}`, p: 2, role: "group", children: [
607
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { fontWeight: 500, transition: "all .3s ease", _groupHover: { color: "brand.400" }, children: child.label }),
608
+ /* @__PURE__ */ jsxRuntime.jsx(
609
+ react$1.Flex,
610
+ {
611
+ flex: 1,
612
+ justify: "flex-end",
613
+ align: "center",
614
+ opacity: 0,
615
+ transition: "all .3s ease",
616
+ transform: "translateX(-10px)",
617
+ _groupHover: { opacity: 1, transform: "translateX(0)" },
618
+ children: /* @__PURE__ */ jsxRuntime.jsx(react$1.Icon, { as: icons.ChevronRightIcon, color: "brand.400", w: 5, h: 5 })
619
+ }
620
+ )
621
+ ] }) }, index2)) }) })
622
+ ] });
623
+ };
624
+ const DesktopNavigation = ({ menu }) => {
625
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.Flex, { as: "ul", role: "list", gap: 2, p: 0, display: { base: "none", md: "flex" }, children: menu.map((item, index2) => {
626
+ var _a;
627
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.Flex, { as: "li", role: "listitem", children: ((_a = item.children) == null ? void 0 : _a.length) ? /* @__PURE__ */ jsxRuntime.jsx(NavList$1, { ...item }) : /* @__PURE__ */ jsxRuntime.jsx(NavLink, { ...item }) }, index2);
628
+ }) });
629
+ };
630
+ const CHEVRON_DOWN_ICON_SIZE = "1.5rem";
631
+ const NavList = ({ path, label, children, isExpanded, onExpand }) => {
632
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Stack, { flex: 1, children: [
633
+ /* @__PURE__ */ jsxRuntime.jsxs(
634
+ react$1.Flex,
635
+ {
636
+ as: "button",
637
+ p: 2,
638
+ pr: "3px",
639
+ align: "center",
640
+ justifyContent: "space-between",
641
+ _hover: { textDecoration: "none", color: "brand.400" },
642
+ onClick: onExpand,
643
+ children: [
644
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { isTruncated: true, fontWeight: 600, children: label }),
645
+ /* @__PURE__ */ jsxRuntime.jsx(
646
+ icons.ChevronDownIcon,
647
+ {
648
+ w: CHEVRON_DOWN_ICON_SIZE,
649
+ h: CHEVRON_DOWN_ICON_SIZE,
650
+ transform: isExpanded ? "rotate(180deg)" : "",
651
+ transition: "all .25s ease-in-out"
652
+ }
653
+ )
654
+ ]
655
+ }
656
+ ),
657
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Collapse, { in: isExpanded, transition: { enter: { ease: "easeIn" }, exit: { duration: 0.2 } }, children: /* @__PURE__ */ jsxRuntime.jsx(react$1.List, { ml: 2, pl: 0, borderLeft: 1, borderStyle: "solid", borderColor: react$1.useColorModeValue("gray.200", "gray.700"), children: children == null ? void 0 : children.map((child, index2) => /* @__PURE__ */ jsxRuntime.jsx(react$1.Flex, { as: "li", role: "listitem", children: /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { as: gatsby.Link, to: `${path}${child.path}`, p: 2, fontSize: "sm", children: child.label }) }, index2)) }) })
658
+ ] });
659
+ };
660
+ const CLOSE_ICON_SIZE = "0.75rem";
661
+ const HAMBURGER_ICON_SIZE = "1rem";
662
+ const MobileNavigation = ({ menu }) => {
663
+ const [expanded, setExpanded] = react.useState(null);
664
+ const { isOpen, onToggle } = react$1.useDisclosure();
665
+ const background = react$1.useColorModeValue("gray.50", "gray.900");
666
+ function handleExpand(index2) {
667
+ return () => {
668
+ setExpanded((prev) => prev === index2 ? null : index2);
669
+ };
670
+ }
671
+ function handleClick() {
672
+ setExpanded(null);
673
+ onToggle();
674
+ }
675
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Box, { display: { base: "block", md: "none" }, children: [
676
+ /* @__PURE__ */ jsxRuntime.jsx(
677
+ react$1.IconButton,
678
+ {
679
+ icon: isOpen ? /* @__PURE__ */ jsxRuntime.jsx(icons.CloseIcon, { w: CLOSE_ICON_SIZE, h: CLOSE_ICON_SIZE }) : /* @__PURE__ */ jsxRuntime.jsx(icons.HamburgerIcon, { w: HAMBURGER_ICON_SIZE, h: HAMBURGER_ICON_SIZE }),
680
+ size: "sm",
681
+ variant: "ghost",
682
+ "aria-label": `${isOpen ? "Close" : "Open"} navigation menu`,
683
+ "aria-expanded": isOpen,
684
+ onClick: handleClick
685
+ }
686
+ ),
687
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Collapse, { in: isOpen, animateOpacity: true, children: /* @__PURE__ */ jsxRuntime.jsx(react$1.Box, { position: "absolute", top: 16, left: 0, right: 0, w: "100vw", px: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
688
+ react$1.List,
689
+ {
690
+ spacing: 2,
691
+ p: 2,
692
+ boxShadow: "md",
693
+ borderWidth: "1px",
694
+ borderColor: react$1.useColorModeValue("gray.200", "gray.700"),
695
+ borderRadius: "md",
696
+ bg: background,
697
+ children: menu.map((item, index2) => {
698
+ var _a;
699
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.Flex, { as: "li", role: "listitem", children: ((_a = item.children) == null ? void 0 : _a.length) ? /* @__PURE__ */ jsxRuntime.jsx(NavList, { ...item, isExpanded: index2 === expanded, onExpand: handleExpand(index2) }) : /* @__PURE__ */ jsxRuntime.jsx(NavLink, { ...item }) }, index2);
700
+ })
701
+ }
702
+ ) }) })
703
+ ] });
704
+ };
705
+ const Navigation = ({ menu }) => {
706
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
707
+ /* @__PURE__ */ jsxRuntime.jsx(DesktopNavigation, { menu }),
708
+ /* @__PURE__ */ jsxRuntime.jsx(MobileNavigation, { menu })
709
+ ] });
710
+ };
711
+ const Header = () => {
712
+ var _a, _b;
713
+ const { configs } = index$2.useSiteContext();
714
+ const navigation = ((_a = configs == null ? void 0 : configs.header) == null ? void 0 : _a.navigation) ?? [];
715
+ const toolbar = (_b = configs == null ? void 0 : configs.header) == null ? void 0 : _b.toolbar;
716
+ const hasToolbar = !!toolbar;
717
+ const hasNavigation = !!navigation.length;
718
+ return /* @__PURE__ */ jsxRuntime.jsx(
719
+ react$1.Box,
720
+ {
721
+ as: "header",
722
+ position: "sticky",
723
+ top: 0,
724
+ bg: react$1.useColorModeValue("white", "gray.900"),
725
+ color: react$1.useColorModeValue("gray.700", "gray.200"),
726
+ boxShadow: "sm",
727
+ zIndex: 100,
728
+ children: /* @__PURE__ */ jsxRuntime.jsx(Container, { children: /* @__PURE__ */ jsxRuntime.jsxs(react$1.Flex, { as: "nav", gap: 2, py: 2, children: [
729
+ /* @__PURE__ */ jsxRuntime.jsx(Brand, { brand: /* @__PURE__ */ jsxRuntime.jsx(Logo, {}) }),
730
+ (hasNavigation || hasToolbar) && /* @__PURE__ */ jsxRuntime.jsxs(
731
+ react$1.Flex,
732
+ {
733
+ as: "section",
734
+ flex: 1,
735
+ flexDir: { base: "row-reverse", md: "row" },
736
+ justifyContent: "end",
737
+ align: "center",
738
+ gap: 2,
739
+ children: [
740
+ hasNavigation && /* @__PURE__ */ jsxRuntime.jsx(react$1.Flex, { flex: { base: 0, md: 1 }, children: /* @__PURE__ */ jsxRuntime.jsx(Navigation, { menu: navigation }) }),
741
+ hasToolbar && /* @__PURE__ */ jsxRuntime.jsx(react$1.Flex, { gap: 2, flex: { base: 1, md: 0 }, justifyContent: "flex-end", children: toolbar })
742
+ ]
743
+ }
744
+ )
745
+ ] }) })
746
+ }
747
+ );
748
+ };
749
+ const Hero = ({ title, subtitle, content, link, image }) => {
750
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.Box, { as: "section", bg: "gray.900", children: /* @__PURE__ */ jsxRuntime.jsx(Container, { children: /* @__PURE__ */ jsxRuntime.jsxs(react$1.Flex, { direction: { base: "column", md: "row" }, children: [
751
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Flex, { align: "center", justify: { base: "center", md: "flex-start" }, flex: 1, py: 8, pe: 8, children: /* @__PURE__ */ jsxRuntime.jsxs(react$1.Stack, { spacing: 6, w: "full", maxW: "lg", children: [
752
+ /* @__PURE__ */ jsxRuntime.jsxs(react$1.Heading, { as: "h1", fontSize: { base: "3xl", md: "4xl", lg: "5xl" }, children: [
753
+ /* @__PURE__ */ jsxRuntime.jsxs(react$1.Text, { as: "span", display: "block", children: [
754
+ title,
755
+ " —"
756
+ ] }),
757
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { as: "span", display: "block", color: "brand.400", children: subtitle })
758
+ ] }),
759
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { fontSize: { base: "md", lg: "lg" }, color: "gray.500", children: content }),
760
+ !!link && /* @__PURE__ */ jsxRuntime.jsx(react$1.Flex, { direction: { base: "column", md: "row" }, children: /* @__PURE__ */ jsxRuntime.jsx(LinkButton, { ...link }) })
761
+ ] }) }),
762
+ image && /* @__PURE__ */ jsxRuntime.jsx(react$1.Flex, { display: { base: "none", md: "flex" }, flex: 1, children: image })
763
+ ] }) }) });
764
+ };
765
+ const Main = ({ children }) => {
766
+ return /* @__PURE__ */ jsxRuntime.jsx(
767
+ react$1.Flex,
768
+ {
769
+ as: "main",
770
+ direction: "column",
771
+ flexGrow: 1,
772
+ bg: react$1.useColorModeValue("white", "gray.800"),
773
+ color: react$1.useColorModeValue("gray.700", "gray.200"),
774
+ children
775
+ }
776
+ );
777
+ };
778
+ const ScrollToTop = () => {
779
+ const [isVisible, setIsVisible] = react.useState(false);
780
+ react.useEffect(() => {
781
+ const toggleVisibility = () => {
782
+ setIsVisible(window.scrollY > 300);
783
+ };
784
+ window.addEventListener("scroll", toggleVisibility);
785
+ return () => {
786
+ window.removeEventListener("scroll", toggleVisibility);
787
+ };
788
+ }, []);
789
+ function handleClick() {
790
+ window.scrollTo({
791
+ top: 0,
792
+ behavior: "smooth"
793
+ });
794
+ }
795
+ return /* @__PURE__ */ jsxRuntime.jsx(
796
+ react$1.Box,
797
+ {
798
+ position: "fixed",
799
+ bottom: { base: 4, md: 8, lg: 16 },
800
+ right: { base: 4, md: 8, lg: 16 },
801
+ zIndex: "1000",
802
+ opacity: isVisible ? 1 : 0,
803
+ transform: isVisible ? "translateY(0)" : "translateY(0.5rem)",
804
+ transition: "opacity 0.4s ease, transform 0.4s ease",
805
+ pointerEvents: isVisible ? "auto" : "none",
806
+ children: /* @__PURE__ */ jsxRuntime.jsx(
807
+ react$1.IconButton,
808
+ {
809
+ "aria-label": "Scroll to top",
810
+ icon: /* @__PURE__ */ jsxRuntime.jsx(icons.ChevronUpIcon, { w: 6, h: 6 }),
811
+ size: "lg",
812
+ shadow: "lg",
813
+ colorScheme: "brand",
814
+ isRound: true,
815
+ onClick: handleClick
816
+ }
817
+ )
818
+ }
819
+ );
820
+ };
821
+ const Layout = ({ children }) => {
822
+ const content = typeof children === "function" ? children({ Hero, Content }) : /* @__PURE__ */ jsxRuntime.jsx(Content, { children });
823
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Stack, { spacing: 0, position: "relative", w: "100%", minH: "100dvh", children: [
824
+ /* @__PURE__ */ jsxRuntime.jsx(Header, {}),
825
+ /* @__PURE__ */ jsxRuntime.jsx(Main, { children: content }),
826
+ /* @__PURE__ */ jsxRuntime.jsx(Footer, {}),
827
+ /* @__PURE__ */ jsxRuntime.jsx(ScrollToTop, {})
828
+ ] });
829
+ };
830
+ const List = ({ items, bullet = "—", render, ...boxProps }) => {
831
+ return /* @__PURE__ */ jsxRuntime.jsx(react$1.List, { pl: 0, ml: 2, mb: 4, ...boxProps, children: items.map((item, index2) => /* @__PURE__ */ jsxRuntime.jsxs(react$1.ListItem, { display: "flex", gap: 1, children: [
832
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Box, { children: bullet }),
833
+ render ? render(item) : item
834
+ ] }, index2)) });
835
+ };
836
+ const NotFound = () => {
837
+ const { t } = reactI18next.useTranslation("pageNotFound");
838
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Stack, { gap: 4, children: [
839
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Heading, { as: "h1", children: t("title") }),
840
+ /* @__PURE__ */ jsxRuntime.jsxs(react$1.Text, { fontSize: "xl", children: [
841
+ t("description"),
842
+ " ",
843
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Button, { as: gatsby.Link, to: "/", variant: "link", colorScheme: "brand", fontSize: "xl", children: t("action") })
844
+ ] })
845
+ ] });
846
+ };
847
+ const TitleMap = {
848
+ pros: "advantages",
849
+ cons: "disadvantages"
850
+ };
851
+ const IconMap = {
852
+ pros: icons.CheckCircleIcon,
853
+ cons: icons.WarningIcon
854
+ };
855
+ const IconColorMap = {
856
+ pros: "green.500",
857
+ cons: "red.500"
858
+ };
859
+ const BgColorMap = {
860
+ pros: "green",
861
+ cons: "red"
862
+ };
863
+ const ProsConsCard = ({ itemType, items }) => {
864
+ const { t } = reactI18next.useTranslation("prosCons");
865
+ return /* @__PURE__ */ jsxRuntime.jsxs(
866
+ react$1.Card,
867
+ {
868
+ as: "article",
869
+ flex: 1,
870
+ p: 2,
871
+ bgColor: react$1.useColorModeValue(`${BgColorMap[itemType]}.100`, `${BgColorMap[itemType]}.800`),
872
+ children: [
873
+ /* @__PURE__ */ jsxRuntime.jsx(
874
+ react$1.CardHeader,
875
+ {
876
+ as: "header",
877
+ p: 2,
878
+ borderTopRadius: "md",
879
+ bgColor: react$1.useColorModeValue("whiteAlpha.800", "blackAlpha.800"),
880
+ children: /* @__PURE__ */ jsxRuntime.jsx(react$1.Heading, { as: "h3", textTransform: "uppercase", fontSize: "xl", children: t(TitleMap[itemType]) })
881
+ }
882
+ ),
883
+ /* @__PURE__ */ jsxRuntime.jsx(
884
+ react$1.CardBody,
885
+ {
886
+ as: "section",
887
+ p: 2,
888
+ borderBottomRadius: "md",
889
+ bgColor: react$1.useColorModeValue("whiteAlpha.800", "blackAlpha.800"),
890
+ children: /* @__PURE__ */ jsxRuntime.jsx(react$1.List, { spacing: 4, p: 0, children: items.map(({ title, description }) => /* @__PURE__ */ jsxRuntime.jsxs(react$1.ListItem, { display: "flex", children: [
891
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.ListIcon, { as: IconMap[itemType], w: 6, h: 6, color: IconColorMap[itemType] }),
892
+ /* @__PURE__ */ jsxRuntime.jsxs(react$1.Text, { fontWeight: "semibold", fontSize: "md", children: [
893
+ title,
894
+ !!description && /* @__PURE__ */ jsxRuntime.jsxs(react$1.Text, { as: "span", fontWeight: "normal", children: [
895
+ ": ",
896
+ description
897
+ ] })
898
+ ] })
899
+ ] }, title)) })
900
+ }
901
+ )
902
+ ]
903
+ }
904
+ );
905
+ };
906
+ const ProsCons = ({ items, ...boxProps }) => {
907
+ const { pros, cons } = items;
908
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Flex, { as: "section", direction: { base: "column", md: "row" }, gap: 4, ...boxProps, children: [
909
+ /* @__PURE__ */ jsxRuntime.jsx(ProsConsCard, { itemType: "pros", items: pros }),
910
+ /* @__PURE__ */ jsxRuntime.jsx(ProsConsCard, { itemType: "cons", items: cons })
911
+ ] });
912
+ };
913
+ const RichTextRenderer = ({ content }) => {
914
+ const components = react$2.useMDXComponents();
915
+ return /* @__PURE__ */ jsxRuntime.jsx(Markdown, { components, children: content });
916
+ };
917
+ function replacePlaceholders(text, placeholders) {
918
+ Object.entries(placeholders).forEach(([placeholder, replacement]) => {
919
+ const regex = new RegExp(`{{${placeholder}}}`, "g");
920
+ text = text.replace(regex, replacement);
921
+ });
922
+ return text;
923
+ }
924
+ const Seo = ({ children, siteMetadata, title, description, lang }) => {
925
+ const { name: siteName, lang: defaultLang, seo } = siteMetadata;
926
+ const { title: defaultTitle, description: defaultDescription } = seo;
927
+ const placeholders = react.useMemo(
928
+ () => ({
929
+ siteName,
930
+ currentYear: index.getCurrentYear(),
931
+ currentMonth: index.getCurrentMonth()
932
+ }),
933
+ [siteName]
934
+ );
935
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
936
+ /* @__PURE__ */ jsxRuntime.jsx("html", { lang: lang ?? defaultLang }),
937
+ /* @__PURE__ */ jsxRuntime.jsx("title", { children: title ? typeof title === "string" ? replacePlaceholders(title, placeholders) : title(placeholders) : defaultTitle }),
938
+ /* @__PURE__ */ jsxRuntime.jsx(
939
+ "meta",
940
+ {
941
+ name: "description",
942
+ content: description ? typeof description === "string" ? replacePlaceholders(description, placeholders) : description(placeholders) : defaultDescription
943
+ }
944
+ ),
945
+ children
946
+ ] });
947
+ };
948
+ const Table = ({
949
+ columnNumber,
950
+ items,
951
+ caption,
952
+ bordered = false,
953
+ striped = true,
954
+ scrollable,
955
+ ...boxProps
956
+ }) => {
957
+ const headerItems = items.slice(0, columnNumber);
958
+ const bodyItems = items.slice(columnNumber);
959
+ return /* @__PURE__ */ jsxRuntime.jsx(
960
+ react$1.TableContainer,
961
+ {
962
+ border: bordered ? void 0 : "none",
963
+ ...scrollable ? { maxH: "50vh", overflowY: "auto" } : {},
964
+ ...boxProps,
965
+ children: /* @__PURE__ */ jsxRuntime.jsxs(react$1.Table, { variant: striped ? "striped" : "simple", children: [
966
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Thead, { ...scrollable ? { position: "sticky", top: 0, zIndex: 1, bg: "gray.800" } : {}, children: /* @__PURE__ */ jsxRuntime.jsx(react$1.Tr, { children: headerItems.map((item, index2) => /* @__PURE__ */ jsxRuntime.jsx(react$1.Th, { children: item }, index2)) }) }),
967
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.Tbody, { children: Array.from({ length: Math.ceil(bodyItems.length / columnNumber) }, (_, rowIndex) => /* @__PURE__ */ jsxRuntime.jsx(react$1.Tr, { children: Array.from({ length: columnNumber }, (_2, colIndex) => /* @__PURE__ */ jsxRuntime.jsx(react$1.Td, { children: bodyItems[rowIndex * columnNumber + colIndex] || "" }, colIndex)) }, rowIndex)) }),
968
+ !!caption && /* @__PURE__ */ jsxRuntime.jsx(react$1.TableCaption, { children: caption })
969
+ ] })
970
+ }
971
+ );
972
+ };
973
+ const Tabs = ({ items, render, ...boxProps }) => {
974
+ const { tabs, panels } = react.useMemo(() => {
975
+ const tabs2 = [];
976
+ const panels2 = [];
977
+ items.forEach(({ content, ...tab }) => {
978
+ tabs2.push(tab);
979
+ panels2.push(content);
980
+ });
981
+ return { tabs: tabs2, panels: panels2 };
982
+ }, []);
983
+ return /* @__PURE__ */ jsxRuntime.jsxs(react$1.Tabs, { overflow: "hidden", colorScheme: "brand", ...boxProps, children: [
984
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.TabList, { overflow: "auto hidden", children: tabs.map(({ label, icon }, index2) => /* @__PURE__ */ jsxRuntime.jsx(react$1.Tab, { children: /* @__PURE__ */ jsxRuntime.jsx(react$1.Text, { as: "h3", isTruncated: true, children: icon ? `${icon} ${label}` : label }) }, index2)) }),
985
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.TabPanels, { children: panels.map((panel, index2) => /* @__PURE__ */ jsxRuntime.jsx(react$1.TabPanel, { children: render ? render(panel) : panel }, index2)) })
986
+ ] });
987
+ };
988
+ const Tip = ({ tip, author = null, ...boxProps }) => {
989
+ return /* @__PURE__ */ jsxRuntime.jsxs(
990
+ react$1.Card,
991
+ {
992
+ variant: "filled",
993
+ p: 4,
994
+ borderLeft: "4px solid gray",
995
+ gap: 4,
996
+ _before: {
997
+ content: '"❛❛"',
998
+ position: "absolute",
999
+ top: -8,
1000
+ left: -2,
1001
+ fontSize: "6rem",
1002
+ fontStyle: "italic",
1003
+ color: react$1.useColorModeValue("blackAlpha.300", "whiteAlpha.300")
1004
+ },
1005
+ ...boxProps,
1006
+ children: [
1007
+ /* @__PURE__ */ jsxRuntime.jsx(react$1.CardBody, { as: "blockquote", p: 0, fontStyle: "italic", children: tip }),
1008
+ !!author && /* @__PURE__ */ jsxRuntime.jsx(react$1.CardFooter, { alignItems: "center", justify: "flex-end", p: 0, children: /* @__PURE__ */ jsxRuntime.jsx(Author, { author, variant: "short" }) })
1009
+ ]
1010
+ }
1011
+ );
1012
+ };
1013
+ exports.Author = Author;
1014
+ exports.AuthorCard = AuthorCard;
1015
+ exports.BonusCard = BonusCard;
1016
+ exports.Center = Center;
1017
+ exports.ContactForm = ContactForm;
1018
+ exports.Faq = Faq;
1019
+ exports.FeatureCard = FeatureCard;
1020
+ exports.Features = Features;
1021
+ exports.GameCard = GameCard;
1022
+ exports.GameDemo = GameDemo;
1023
+ exports.GameInfo = GameInfo;
1024
+ exports.Grid = Grid;
1025
+ exports.HowTo = HowTo;
1026
+ exports.Layout = Layout;
1027
+ exports.LinkButton = LinkButton;
1028
+ exports.List = List;
1029
+ exports.NotFound = NotFound;
1030
+ exports.ProsCons = ProsCons;
1031
+ exports.PulseButton = PulseButton;
1032
+ exports.RichTextRenderer = RichTextRenderer;
1033
+ exports.Seo = Seo;
1034
+ exports.Table = Table;
1035
+ exports.Tabs = Tabs;
1036
+ exports.Tip = Tip;