@react-text-game/ui 0.2.4 → 0.3.1

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 (36) hide show
  1. package/README.md +67 -0
  2. package/dist/components/LanguageToggle.d.ts +47 -0
  3. package/dist/components/LanguageToggle.d.ts.map +1 -0
  4. package/dist/components/LanguageToggle.js +56 -0
  5. package/dist/components/LanguageToggle.js.map +1 -0
  6. package/dist/components/MainMenu.d.ts.map +1 -1
  7. package/dist/components/MainMenu.js +6 -5
  8. package/dist/components/MainMenu.js.map +1 -1
  9. package/dist/components/ReloadButton.d.ts.map +1 -1
  10. package/dist/components/ReloadButton.js +1 -0
  11. package/dist/components/ReloadButton.js.map +1 -1
  12. package/dist/components/SaveButton.d.ts.map +1 -1
  13. package/dist/components/SaveButton.js +1 -0
  14. package/dist/components/SaveButton.js.map +1 -1
  15. package/dist/components/SaveLoadModal/SaveLoadModal.d.ts +1 -1
  16. package/dist/components/SaveLoadModal/SaveLoadModal.d.ts.map +1 -1
  17. package/dist/components/SaveLoadModal/SaveLoadModal.js +11 -3
  18. package/dist/components/SaveLoadModal/SaveLoadModal.js.map +1 -1
  19. package/dist/components/SaveLoadModal/SaveSlot.d.ts +16 -0
  20. package/dist/components/SaveLoadModal/SaveSlot.d.ts.map +1 -0
  21. package/dist/components/SaveLoadModal/SaveSlot.js +21 -0
  22. package/dist/components/SaveLoadModal/SaveSlot.js.map +1 -0
  23. package/dist/components/index.d.ts +1 -0
  24. package/dist/components/index.d.ts.map +1 -1
  25. package/dist/components/index.js +1 -0
  26. package/dist/components/index.js.map +1 -1
  27. package/dist/context/ComponentsContext/ComponentsContext.d.ts.map +1 -1
  28. package/dist/context/ComponentsContext/ComponentsContext.js +1 -0
  29. package/dist/context/ComponentsContext/ComponentsContext.js.map +1 -1
  30. package/dist/i18n/index.d.ts +37 -0
  31. package/dist/i18n/index.d.ts.map +1 -0
  32. package/dist/i18n/index.js +5 -0
  33. package/dist/i18n/index.js.map +1 -0
  34. package/dist/i18n/locales/en/ui.json +32 -0
  35. package/dist/styles/index.css +47 -35
  36. package/package.json +10 -3
package/README.md CHANGED
@@ -4,6 +4,13 @@ UI components library for react-text-game built with React 19, TypeScript, and T
4
4
 
5
5
  > Install this package inside your own React project. It depends on `@react-text-game/core` for game state and Tailwind CSS v4 for styling tokens.
6
6
 
7
+ ## Features
8
+
9
+ - Drop-in game shell: main menu, passage renderer, save/load modal, and dev helpers
10
+ - Tailwind CSS v4 theme tokens for full visual customization
11
+ - Language-aware UI copy powered by i18next with persistent language switching
12
+ - React hooks and context utilities that integrate directly with `@react-text-game/core`
13
+
7
14
  ## Installation
8
15
 
9
16
  ### 1. Install and configure Tailwind CSS
@@ -57,6 +64,66 @@ export function App() {
57
64
 
58
65
  With those two components in place, the UI handles menus, passage rendering, and save/load modals. You can immediately start defining entities and passages through `@react-text-game/core`.
59
66
 
67
+ ## Internationalization
68
+
69
+ The UI package ships with an `en` translation bundle for the `ui` namespace and exposes it through `@react-text-game/ui/i18n`. When you call `Game.init`, the core engine automatically merges these strings with your game resources and persists the active language for every player.
70
+
71
+ ### Default UI copy
72
+
73
+ ```ts
74
+ import { uiTranslations } from '@react-text-game/ui/i18n';
75
+
76
+ console.log(uiTranslations.en.ui.mainMenu.title); // "Main Menu"
77
+ ```
78
+
79
+ Components such as `MainMenu`, `SaveLoadModal`, and `ErrorBoundary` already call `useTranslation('ui')`, so English works out of the box. You only need to add resources when you want to localize beyond the default language or override labels.
80
+
81
+ ### Adding more languages
82
+
83
+ Create your own `ui` namespace JSON file per language and pass it alongside your story translations:
84
+
85
+ ```ts
86
+ import uiEs from './locales/es/ui.json';
87
+ import passagesEs from './locales/es/passages.json';
88
+
89
+ await Game.init({
90
+ gameName: 'My Text Adventure',
91
+ translations: {
92
+ defaultLanguage: 'en',
93
+ fallbackLanguage: 'en',
94
+ resources: {
95
+ es: {
96
+ ui: uiEs,
97
+ passages: passagesEs,
98
+ },
99
+ },
100
+ },
101
+ });
102
+ ```
103
+
104
+ - Any namespace you provide (including `ui`) overrides the defaults for that language.
105
+ - If you omit a translation key, i18next falls back to the language defined in `fallbackLanguage`.
106
+ - Because the core engine persists language preference in its settings store, players keep their choice on reload.
107
+
108
+ ### Language toggle component
109
+
110
+ Use the built-in `LanguageToggle` to expose language switching in your UI. It relies on `useGameTranslation`, so language changes propagate everywhere.
111
+
112
+ ```tsx
113
+ import { LanguageToggle } from '@react-text-game/ui';
114
+
115
+ function Header() {
116
+ return (
117
+ <header className="flex justify-end">
118
+ <LanguageToggle
119
+ languageNames={{ en: 'English', es: 'Español' }}
120
+ showCode
121
+ />
122
+ </header>
123
+ );
124
+ }
125
+ ```
126
+
60
127
  ## Development
61
128
 
62
129
  ```bash
@@ -0,0 +1,47 @@
1
+ export type LanguageToggleProps = Readonly<{
2
+ /**
3
+ * Optional CSS class name for custom styling
4
+ */
5
+ className?: string;
6
+ /**
7
+ * Optional namespace for translations (defaults to 'ui')
8
+ */
9
+ namespace?: string;
10
+ /**
11
+ * Optional custom language names mapping
12
+ * Example: { en: 'English', ru: 'Русский', de: 'Deutsch' }
13
+ */
14
+ languageNames?: Record<string, string>;
15
+ /**
16
+ * Show language code alongside the name (e.g., "English (en)")
17
+ * @default false
18
+ */
19
+ showCode?: boolean;
20
+ }>;
21
+ /**
22
+ * A themed language toggle dropdown component that opens on hover.
23
+ * Uses the UI package's semantic theming system for automatic dark mode support.
24
+ *
25
+ * @example
26
+ * ```tsx
27
+ * // Basic usage
28
+ * <LanguageToggle />
29
+ *
30
+ * // With custom language names
31
+ * <LanguageToggle
32
+ * languageNames={{
33
+ * en: 'English',
34
+ * ru: 'Русский',
35
+ * de: 'Deutsch'
36
+ * }}
37
+ * />
38
+ *
39
+ * // With custom styling and code display
40
+ * <LanguageToggle
41
+ * className="custom-class"
42
+ * showCode={true}
43
+ * />
44
+ * ```
45
+ */
46
+ export declare const LanguageToggle: ({ className, namespace, languageNames, showCode, }: LanguageToggleProps) => import("react/jsx-runtime").JSX.Element | null;
47
+ //# sourceMappingURL=LanguageToggle.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LanguageToggle.d.ts","sourceRoot":"","sources":["../../src/components/LanguageToggle.tsx"],"names":[],"mappings":"AAMA,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC;IACvC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC,CAAC;AAEH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,eAAO,MAAM,cAAc,GAAI,oDAK5B,mBAAmB,mDAgHrB,CAAC"}
@@ -0,0 +1,56 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useGameTranslation } from "@react-text-game/core/i18n";
4
+ import { useState } from "react";
5
+ import { twMerge } from "tailwind-merge";
6
+ /**
7
+ * A themed language toggle dropdown component that opens on hover.
8
+ * Uses the UI package's semantic theming system for automatic dark mode support.
9
+ *
10
+ * @example
11
+ * ```tsx
12
+ * // Basic usage
13
+ * <LanguageToggle />
14
+ *
15
+ * // With custom language names
16
+ * <LanguageToggle
17
+ * languageNames={{
18
+ * en: 'English',
19
+ * ru: 'Русский',
20
+ * de: 'Deutsch'
21
+ * }}
22
+ * />
23
+ *
24
+ * // With custom styling and code display
25
+ * <LanguageToggle
26
+ * className="custom-class"
27
+ * showCode={true}
28
+ * />
29
+ * ```
30
+ */
31
+ export const LanguageToggle = ({ className = "", namespace, languageNames, showCode = false, }) => {
32
+ const { currentLanguage, languages, changeLanguage } = useGameTranslation(namespace);
33
+ const [isOpen, setIsOpen] = useState(false);
34
+ // Default language names - uppercase language codes
35
+ const getLanguageName = (lang) => {
36
+ if (languageNames && languageNames[lang]) {
37
+ return languageNames[lang];
38
+ }
39
+ return lang.toUpperCase();
40
+ };
41
+ const handleLanguageChange = async (lang) => {
42
+ await changeLanguage(lang);
43
+ setIsOpen(false);
44
+ };
45
+ // Don't render if there's only one language or no languages
46
+ if (languages.length <= 1) {
47
+ return null;
48
+ }
49
+ return (_jsxs("div", { className: twMerge("relative inline-block", className), onMouseEnter: () => setIsOpen(true), onMouseLeave: () => setIsOpen(false), children: [_jsxs("button", { className: "flex items-center gap-2 px-4 py-2 bg-primary-500 hover:bg-primary-600 text-primary-foreground rounded-lg shadow-md transition-colors duration-200 cursor-pointer active:scale-95", "aria-label": "Select language", "aria-expanded": isOpen, "aria-haspopup": "true", children: [_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "w-5 h-5", "aria-hidden": "true", children: [_jsx("circle", { cx: "12", cy: "12", r: "10" }), _jsx("path", { d: "M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" }), _jsx("path", { d: "M2 12h20" })] }), _jsxs("span", { className: "font-medium", children: [getLanguageName(currentLanguage), showCode && ` (${currentLanguage})`] }), _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: twMerge("w-4 h-4 transition-transform duration-200", isOpen ? "rotate-180" : ""), "aria-hidden": "true", children: _jsx("polyline", { points: "6 9 12 15 18 9" }) })] }), isOpen && (_jsx("div", { className: "absolute top-full left-0 pt-2 min-w-full z-50", role: "menu", "aria-orientation": "vertical", children: _jsx("div", { className: "bg-popover border border-border rounded-lg shadow-lg overflow-hidden animate-[fadeIn_150ms_ease-in]", children: languages.map((lang) => {
50
+ const isActive = lang === currentLanguage;
51
+ return (_jsxs("button", { onClick: () => handleLanguageChange(lang), className: twMerge("w-full text-left px-4 py-2.5 transition-colors duration-150 whitespace-nowrap", isActive
52
+ ? "bg-primary-100 text-primary-700 font-medium cursor-default"
53
+ : "text-popover-foreground hover:bg-muted hover:text-accent-foreground cursor-pointer"), role: "menuitem", "aria-current": isActive ? "true" : undefined, children: [getLanguageName(lang), showCode && ` (${lang})`, isActive && (_jsx("span", { className: "ml-2", "aria-label": "Current language", children: "\u2713" }))] }, lang));
54
+ }) }) }))] }));
55
+ };
56
+ //# sourceMappingURL=LanguageToggle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LanguageToggle.js","sourceRoot":"","sources":["../../src/components/LanguageToggle.tsx"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"MainMenu.d.ts","sourceRoot":"","sources":["../../src/components/MainMenu.tsx"],"names":[],"mappings":"AAOA,eAAO,MAAM,QAAQ,+CAyCpB,CAAC"}
1
+ {"version":3,"file":"MainMenu.d.ts","sourceRoot":"","sources":["../../src/components/MainMenu.tsx"],"names":[],"mappings":"AAWA,eAAO,MAAM,QAAQ,+CA+CpB,CAAC"}
@@ -1,15 +1,16 @@
1
+ "use client";
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { Game, SYSTEM_PASSAGE_NAMES } from "@react-text-game/core";
3
4
  import { useLastLoadGame } from "@react-text-game/core/saves";
5
+ import { useTranslation } from "react-i18next";
4
6
  import { useSaveLoadMenu } from "../context/SaveLoadMenuContext";
5
7
  import { Button } from "./common";
8
+ import { LanguageToggle } from "./LanguageToggle";
6
9
  export const MainMenu = () => {
10
+ const { t } = useTranslation("ui");
7
11
  const { hasLastSave, loadLastGame } = useLastLoadGame();
8
12
  const { openLoadMenu } = useSaveLoadMenu();
9
- const continueCallback = async () => {
10
- const result = await loadLastGame();
11
- console.log(result);
12
- };
13
- return (_jsxs("div", { className: "mt-10 flex flex-col items-center justify-center h-full gap-8", children: [_jsxs("div", { className: "fixed top-10 left-10 flex flex-col items-start", children: [_jsxs("h2", { className: "text-2xl flex gap-2", children: [_jsx("span", { className: "text-primary-500 font-semibold", children: Game.options.gameName.toUpperCase() }), _jsxs("span", { className: "font-mono font-light text-secondary-500", children: ["v", Game.options.gameVersion] })] }), Game.options.author && (_jsxs("h3", { className: "text-md font-light text-secondary-400", children: ["by ", Game.options.author] }))] }), _jsx("h1", { className: "text-4xl font-bold text-primary-900", children: "Main Menu" }), _jsxs("div", { className: "flex flex-col w-40 gap-4", children: [_jsx(Button, { onClick: () => Game.jumpTo(Game.options.startPassage || SYSTEM_PASSAGE_NAMES.START), children: "New Game" }), _jsx(Button, { disabled: !hasLastSave, onClick: continueCallback, children: "Continue" }), _jsx(Button, { onClick: openLoadMenu, children: "Load Game" })] })] }));
13
+ return (_jsxs("div", { className: "mt-10 flex flex-col items-center justify-center h-full gap-8", children: [_jsxs("div", { className: "fixed top-10 left-10 flex flex-col items-start", children: [_jsxs("h2", { className: "text-2xl flex gap-2", children: [_jsx("span", { className: "text-primary-500 font-semibold", children: Game.options.gameName.toUpperCase() }), _jsxs("span", { className: "font-mono font-light text-secondary-500", children: ["v", Game.options.gameVersion] })] }), Game.options.author && (_jsxs("h3", { className: "text-md font-light text-secondary-400", children: ["by ", Game.options.author] }))] }), _jsx("div", { className: "fixed top-10 right-20", children: _jsx(LanguageToggle, {}) }), _jsx("h1", { className: "text-4xl font-bold text-primary-900", children: t("mainMenu.title") }), _jsxs("div", { className: "flex flex-col w-40 gap-4", children: [_jsx(Button, { onClick: () => Game.jumpTo(Game.options.startPassage ||
14
+ SYSTEM_PASSAGE_NAMES.START), children: t("mainMenu.newGame") }), _jsx(Button, { disabled: !hasLastSave, onClick: loadLastGame, children: t("mainMenu.continue") }), _jsx(Button, { onClick: openLoadMenu, children: t("mainMenu.loadGame") })] })] }));
14
15
  };
15
16
  //# sourceMappingURL=MainMenu.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"MainMenu.js","sourceRoot":"","sources":["../../src/components/MainMenu.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAElC,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,EAAE;IACzB,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,eAAe,EAAE,CAAC;IACxD,MAAM,EAAE,YAAY,EAAE,GAAG,eAAe,EAAE,CAAC;IAE3C,MAAM,gBAAgB,GAAG,KAAK,IAAI,EAAE;QAChC,MAAM,MAAM,GAAG,MAAM,YAAY,EAAE,CAAC;QAEpC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC,CAAC;IAEF,OAAO,CACH,eAAK,SAAS,EAAC,8DAA8D,aACzE,eAAK,SAAS,EAAC,gDAAgD,aAC3D,cAAI,SAAS,EAAC,qBAAqB,aAC/B,eAAM,SAAS,EAAC,gCAAgC,YAC3C,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE,GACjC,EACP,gBAAM,SAAS,EAAC,yCAAyC,kBACnD,IAAI,CAAC,OAAO,CAAC,WAAW,IACvB,IACN,EACJ,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CACpB,cAAI,SAAS,EAAC,uCAAuC,oBAC7C,IAAI,CAAC,OAAO,CAAC,MAAM,IACtB,CACR,IACC,EACN,aAAI,SAAS,EAAC,qCAAqC,0BAAe,EAClE,eAAK,SAAS,EAAC,0BAA0B,aACrC,KAAC,MAAM,IAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,YAAY,IAAI,oBAAoB,CAAC,KAAK,CAAC,yBAElF,EACT,KAAC,MAAM,IAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,OAAO,EAAE,gBAAgB,yBAEhD,EACT,KAAC,MAAM,IAAC,OAAO,EAAE,YAAY,0BAEpB,IACP,IACJ,CACT,CAAC;AACN,CAAC,CAAC"}
1
+ {"version":3,"file":"MainMenu.js","sourceRoot":"","sources":["../../src/components/MainMenu.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,IAAI,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AACnE,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,EAAE;IACzB,MAAM,EAAE,CAAC,EAAE,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IAEnC,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,eAAe,EAAE,CAAC;IACxD,MAAM,EAAE,YAAY,EAAE,GAAG,eAAe,EAAE,CAAC;IAE3C,OAAO,CACH,eAAK,SAAS,EAAC,8DAA8D,aACzE,eAAK,SAAS,EAAC,gDAAgD,aAC3D,cAAI,SAAS,EAAC,qBAAqB,aAC/B,eAAM,SAAS,EAAC,gCAAgC,YAC3C,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,EAAE,GACjC,EACP,gBAAM,SAAS,EAAC,yCAAyC,kBACnD,IAAI,CAAC,OAAO,CAAC,WAAW,IACvB,IACN,EACJ,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CACpB,cAAI,SAAS,EAAC,uCAAuC,oBAC7C,IAAI,CAAC,OAAO,CAAC,MAAM,IACtB,CACR,IACC,EACN,cAAK,SAAS,EAAC,uBAAuB,YAClC,KAAC,cAAc,KAAG,GAChB,EACN,aAAI,SAAS,EAAC,qCAAqC,YAC9C,CAAC,CAAC,gBAAgB,CAAC,GACnB,EACL,eAAK,SAAS,EAAC,0BAA0B,aACrC,KAAC,MAAM,IACH,OAAO,EAAE,GAAG,EAAE,CACV,IAAI,CAAC,MAAM,CACP,IAAI,CAAC,OAAO,CAAC,YAAY;4BACrB,oBAAoB,CAAC,KAAK,CACjC,YAGJ,CAAC,CAAC,kBAAkB,CAAC,GACjB,EACT,KAAC,MAAM,IAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,OAAO,EAAE,YAAY,YAChD,CAAC,CAAC,mBAAmB,CAAC,GAClB,EACT,KAAC,MAAM,IAAC,OAAO,EAAE,YAAY,YAAG,CAAC,CAAC,mBAAmB,CAAC,GAAU,IAC9D,IACJ,CACT,CAAC;AACN,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ReloadButton.d.ts","sourceRoot":"","sources":["../../src/components/ReloadButton.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAU,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,SAAS,CAAC,GACrE,QAAQ,CAAC;IACL;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC,CAAC;AAEP,eAAO,MAAM,IAAI,GAAI,eAAe;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,4CAezD,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,qCAI1B,iBAAiB,4CAanB,CAAC"}
1
+ {"version":3,"file":"ReloadButton.d.ts","sourceRoot":"","sources":["../../src/components/ReloadButton.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAU,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,SAAS,CAAC,GACrE,QAAQ,CAAC;IACL;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB,CAAC,CAAC;AAEP,eAAO,MAAM,IAAI,GAAI,eAAe;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,4CAezD,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,qCAI1B,iBAAiB,4CAanB,CAAC"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { useRestartGame } from "@react-text-game/core/saves";
3
4
  import { twMerge } from "tailwind-merge";
@@ -1 +1 @@
1
- {"version":3,"file":"ReloadButton.js","sourceRoot":"","sources":["../../src/components/ReloadButton.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,OAAO,EAAE,MAAM,EAAe,MAAM,oBAAoB,CAAC;AAYzD,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,EAAE,SAAS,EAA0B,EAAE,EAAE,CAAC,CAC3D,cACI,KAAK,EAAC,4BAA4B,EAClC,IAAI,EAAC,MAAM,EACX,OAAO,EAAC,WAAW,EACnB,SAAS,EAAE,SAAS,YAEpB,aAAG,MAAM,EAAC,cAAc,EAAC,aAAa,EAAC,OAAO,EAAC,WAAW,EAAC,KAAK,aAC5D,eACI,cAAc,EAAC,OAAO,EACtB,CAAC,EAAC,wIAAwI,GAC5I,EACF,eAAM,CAAC,EAAC,8LAA8L,GAAG,IACzM,GACF,CACT,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EACzB,UAAU,EACV,SAAS,EACT,GAAG,KAAK,EACQ,EAAE,EAAE;IACpB,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAEhC,OAAO,CACH,MAAC,MAAM,IACH,SAAS,EAAE,OAAO,CAAC,yBAAyB,EAAE,SAAS,CAAC,EACxD,OAAO,EAAE,MAAM,KACX,KAAK,aAET,KAAC,IAAI,IAAC,SAAS,EAAC,SAAS,GAAG,EAC3B,CAAC,UAAU,IAAI,0CAAyB,IACpC,CACZ,CAAC;AACN,CAAC,CAAC"}
1
+ {"version":3,"file":"ReloadButton.js","sourceRoot":"","sources":["../../src/components/ReloadButton.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,OAAO,EAAE,MAAM,EAAe,MAAM,oBAAoB,CAAC;AAYzD,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,EAAE,SAAS,EAA0B,EAAE,EAAE,CAAC,CAC3D,cACI,KAAK,EAAC,4BAA4B,EAClC,IAAI,EAAC,MAAM,EACX,OAAO,EAAC,WAAW,EACnB,SAAS,EAAE,SAAS,YAEpB,aAAG,MAAM,EAAC,cAAc,EAAC,aAAa,EAAC,OAAO,EAAC,WAAW,EAAC,KAAK,aAC5D,eACI,cAAc,EAAC,OAAO,EACtB,CAAC,EAAC,wIAAwI,GAC5I,EACF,eAAM,CAAC,EAAC,8LAA8L,GAAG,IACzM,GACF,CACT,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EACzB,UAAU,EACV,SAAS,EACT,GAAG,KAAK,EACQ,EAAE,EAAE;IACpB,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAEhC,OAAO,CACH,MAAC,MAAM,IACH,SAAS,EAAE,OAAO,CAAC,yBAAyB,EAAE,SAAS,CAAC,EACxD,OAAO,EAAE,MAAM,KACX,KAAK,aAET,KAAC,IAAI,IAAC,SAAS,EAAC,SAAS,GAAG,EAC3B,CAAC,UAAU,IAAI,0CAAyB,IACpC,CACZ,CAAC;AACN,CAAC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"SaveButton.d.ts","sourceRoot":"","sources":["../../src/components/SaveButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAU,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAG5D,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,SAAS,CAAC,GACnE,QAAQ,CAAC;IACL;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;CACrC,CAAC,CAAC;AAkBP,eAAO,MAAM,UAAU,GAAI,2CAKxB,eAAe,4CAajB,CAAC"}
1
+ {"version":3,"file":"SaveButton.d.ts","sourceRoot":"","sources":["../../src/components/SaveButton.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAU,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAG5D,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,SAAS,CAAC,GACnE,QAAQ,CAAC;IACL;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;CACrC,CAAC,CAAC;AAkBP,eAAO,MAAM,UAAU,GAAI,2CAKxB,eAAe,4CAajB,CAAC"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { twMerge } from "tailwind-merge";
3
4
  import { Button } from "../components/common";
@@ -1 +1 @@
1
- {"version":3,"file":"SaveButton.js","sourceRoot":"","sources":["../../src/components/SaveButton.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,OAAO,EAAE,MAAM,EAAe,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAoB/D,MAAM,IAAI,GAAG,CAAC,EAAE,SAAS,EAA0B,EAAE,EAAE,CAAC,CACpD,cACI,KAAK,EAAC,4BAA4B,EAClC,IAAI,EAAC,MAAM,EACX,OAAO,EAAC,WAAW,EACnB,SAAS,EAAE,SAAS,YAEpB,eACI,IAAI,EAAC,cAAc,EACnB,QAAQ,EAAC,SAAS,EAClB,CAAC,EAAC,mbAAmb,EACrb,QAAQ,EAAC,SAAS,GACpB,GACA,CACT,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EACvB,UAAU,EACV,SAAS,EACT,IAAI,EACJ,GAAG,KAAK,EACM,EAAE,EAAE;IAClB,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,GAAG,eAAe,EAAE,CAAC;IAE7D,OAAO,CACH,MAAC,MAAM,IACH,SAAS,EAAE,OAAO,CAAC,yBAAyB,EAAE,SAAS,CAAC,EACxD,OAAO,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,gBAAgB,KACtD,KAAK,aAET,KAAC,IAAI,IAAC,SAAS,EAAC,SAAS,GAAG,EAC3B,CAAC,UAAU,IAAI,uCAAsB,IACjC,CACZ,CAAC;AACN,CAAC,CAAC"}
1
+ {"version":3,"file":"SaveButton.js","sourceRoot":"","sources":["../../src/components/SaveButton.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,OAAO,EAAE,MAAM,EAAe,MAAM,oBAAoB,CAAC;AAEzD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAoB/D,MAAM,IAAI,GAAG,CAAC,EAAE,SAAS,EAA0B,EAAE,EAAE,CAAC,CACpD,cACI,KAAK,EAAC,4BAA4B,EAClC,IAAI,EAAC,MAAM,EACX,OAAO,EAAC,WAAW,EACnB,SAAS,EAAE,SAAS,YAEpB,eACI,IAAI,EAAC,cAAc,EACnB,QAAQ,EAAC,SAAS,EAClB,CAAC,EAAC,mbAAmb,EACrb,QAAQ,EAAC,SAAS,GACpB,GACA,CACT,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EACvB,UAAU,EACV,SAAS,EACT,IAAI,EACJ,GAAG,KAAK,EACM,EAAE,EAAE;IAClB,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,GAAG,eAAe,EAAE,CAAC;IAE7D,OAAO,CACH,MAAC,MAAM,IACH,SAAS,EAAE,OAAO,CAAC,yBAAyB,EAAE,SAAS,CAAC,EACxD,OAAO,EAAE,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,gBAAgB,KACtD,KAAK,aAET,KAAC,IAAI,IAAC,SAAS,EAAC,SAAS,GAAG,EAC3B,CAAC,UAAU,IAAI,uCAAsB,IACjC,CACZ,CAAC;AACN,CAAC,CAAC"}
@@ -4,6 +4,6 @@ interface SaveLoadModalProps {
4
4
  onClose: () => void;
5
5
  mode?: SaveLoadMode;
6
6
  }
7
- export declare const SaveLoadModal: ({ isOpen, onClose, mode }: SaveLoadModalProps) => import("react/jsx-runtime").JSX.Element | null;
7
+ export declare const SaveLoadModal: ({ isOpen, onClose, mode, }: SaveLoadModalProps) => import("react/jsx-runtime").JSX.Element | null;
8
8
  export {};
9
9
  //# sourceMappingURL=SaveLoadModal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SaveLoadModal.d.ts","sourceRoot":"","sources":["../../../src/components/SaveLoadModal/SaveLoadModal.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,UAAU,kBAAkB;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,IAAI,CAAC,EAAE,YAAY,CAAC;CACvB;AAED,eAAO,MAAM,aAAa,GAAI,2BAAwC,kBAAkB,mDA2KvF,CAAC"}
1
+ {"version":3,"file":"SaveLoadModal.d.ts","sourceRoot":"","sources":["../../../src/components/SaveLoadModal/SaveLoadModal.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAI5D,UAAU,kBAAkB;IACxB,MAAM,EAAE,OAAO,CAAC;IAChB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,IAAI,CAAC,EAAE,YAAY,CAAC;CACvB;AAED,eAAO,MAAM,aAAa,GAAI,4BAI3B,kBAAkB,mDAwHpB,CAAC"}
@@ -1,7 +1,11 @@
1
+ "use client";
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  import { useSaveSlots } from "@react-text-game/core/saves";
3
4
  import { useEffect, useState } from "react";
4
- export const SaveLoadModal = ({ isOpen, onClose, mode = "saveLoad" }) => {
5
+ import { useTranslation } from "react-i18next";
6
+ import { SaveSlot } from "./SaveSlot";
7
+ export const SaveLoadModal = ({ isOpen, onClose, mode = "saveLoad", }) => {
8
+ const { t } = useTranslation("ui");
5
9
  const saveSlots = useSaveSlots({ count: 9 });
6
10
  const [loading, setLoading] = useState(null);
7
11
  useEffect(() => {
@@ -41,12 +45,16 @@ export const SaveLoadModal = ({ isOpen, onClose, mode = "saveLoad" }) => {
41
45
  }
42
46
  catch (error) {
43
47
  console.error("Action failed:", error);
44
- alert("An error occurred. Please check the console for details.");
48
+ alert(t("saves.errors.actionFailed"));
45
49
  }
46
50
  finally {
47
51
  setLoading(null);
48
52
  }
49
53
  };
50
- return (_jsxs("div", { className: "fixed inset-0 z-[9999] flex items-center justify-center", children: [_jsx("div", { className: "absolute inset-0 bg-overlay/40 backdrop-blur-sm", onClick: onClose }), _jsxs("div", { className: "relative w-full h-full md:h-auto md:max-h-[90vh] md:w-full md:max-w-4xl mx-0 md:mx-4 bg-background md:rounded-lg shadow-2xl flex flex-col overflow-hidden", children: [_jsxs("div", { className: "flex items-center justify-between p-4 md:p-6 border-b border-border", children: [_jsx("h2", { className: "text-xl md:text-2xl font-bold text-foreground", children: mode === "save" ? "Save Game" : mode === "load" ? "Load Game" : "Save / Load Game" }), _jsx("button", { onClick: onClose, className: "text-muted-foreground hover:text-foreground transition-colors p-2 hover:bg-muted rounded-lg", "aria-label": "Close", children: _jsx("svg", { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }), _jsx("div", { className: "flex-1 overflow-y-auto p-4 md:p-6 bg-muted", children: _jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", children: saveSlots.map((slot, index) => (_jsxs("div", { className: "bg-card rounded-lg border border-border hover:border-muted-400 transition-all hover:shadow-lg overflow-hidden", children: [_jsxs("div", { className: "p-3 border-b border-border", children: [_jsxs("h3", { className: "text-lg font-semibold text-card-foreground", children: ["Slot ", index + 1] }), slot.data && (_jsx("p", { className: "text-xs text-muted-foreground mt-1", children: new Date(slot.data.timestamp).toLocaleString() }))] }), _jsx("div", { className: "p-3", children: slot.data ? (_jsxs("div", { className: "space-y-2", children: [slot.data.description && (_jsx("p", { className: "text-sm text-card-foreground line-clamp-2", children: slot.data.description })), slot.data.screenshot && (_jsx("img", { src: slot.data.screenshot, alt: "Save screenshot", className: "w-full h-32 object-cover rounded" })), _jsxs("div", { className: "flex gap-2", children: [(mode === "load" || mode === "saveLoad") && (_jsx("button", { onClick: () => handleAction(index, slot.load), disabled: loading !== null, className: "flex-1 bg-primary-600 hover:bg-primary-700 disabled:bg-muted-400 disabled:cursor-not-allowed text-primary-foreground px-4 py-2 rounded-lg transition-colors font-medium", children: loading === index ? "Loading..." : "Load" })), (mode === "save" || mode === "saveLoad") && (_jsx("button", { onClick: () => handleAction(index, slot.save), disabled: loading !== null, className: "flex-1 bg-success-600 hover:bg-success-700 disabled:bg-muted-400 disabled:cursor-not-allowed text-success-foreground px-4 py-2 rounded-lg transition-colors font-medium", children: loading === index ? "Saving..." : "Overwrite" })), _jsx("button", { onClick: () => handleAction(index, slot.delete), disabled: loading !== null, className: "bg-danger-600 hover:bg-danger-700 disabled:bg-muted-400 disabled:cursor-not-allowed text-danger-foreground px-4 py-2 rounded-lg transition-colors", "aria-label": "Delete save", children: _jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }) })] })] })) : (_jsxs("div", { className: "flex flex-col items-center justify-center py-6", children: [_jsx("p", { className: "text-muted-foreground mb-4", children: "Empty Slot" }), (mode === "save" || mode === "saveLoad") && (_jsx("button", { onClick: () => handleAction(index, slot.save), disabled: loading !== null, className: "bg-success-600 hover:bg-success-700 disabled:bg-muted-400 disabled:cursor-not-allowed text-success-foreground px-4 py-2 rounded-lg transition-colors font-medium", children: loading === index ? "Saving..." : "Save Here" }))] })) })] }, index))) }) }), _jsx("div", { className: "p-4 md:p-6 border-t border-border bg-background", children: _jsx("button", { onClick: onClose, className: "w-full md:w-auto px-6 py-2 bg-muted hover:bg-muted-300 text-foreground rounded-lg transition-colors font-medium", children: "Close" }) })] })] }));
54
+ return (_jsxs("div", { className: "fixed inset-0 z-[9999] flex items-center justify-center", children: [_jsx("div", { className: "absolute inset-0 bg-overlay/40 backdrop-blur-sm", onClick: onClose }), _jsxs("div", { className: "relative w-full h-full md:h-auto md:max-h-[90vh] md:w-full md:max-w-4xl mx-0 md:mx-4 bg-background md:rounded-lg shadow-2xl flex flex-col overflow-hidden", children: [_jsxs("div", { className: "flex items-center justify-between p-4 md:p-6 border-b border-border", children: [_jsx("h2", { className: "text-xl md:text-2xl font-bold text-foreground", children: mode === "save"
55
+ ? t("saves.title.save")
56
+ : mode === "load"
57
+ ? t("saves.title.load")
58
+ : t("saves.title.saveLoad") }), _jsx("button", { onClick: onClose, className: "text-muted-foreground hover:text-foreground transition-colors p-2 hover:bg-muted rounded-lg", "aria-label": "Close", children: _jsx("svg", { className: "w-6 h-6", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) })] }), _jsx("div", { className: "flex-1 overflow-y-auto p-4 md:p-6 bg-muted", children: _jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", children: saveSlots.map((slot, index) => (_jsx(SaveSlot, { slot: slot, index: index, mode: mode, loading: loading, onAction: handleAction }, index))) }) }), _jsx("div", { className: "p-4 md:p-6 border-t border-border bg-background", children: _jsx("button", { onClick: onClose, className: "w-full md:w-auto px-6 py-2 bg-muted hover:bg-muted-300 text-foreground rounded-lg transition-colors font-medium", children: t("saves.actions.close") }) })] })] }));
51
59
  };
52
60
  //# sourceMappingURL=SaveLoadModal.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SaveLoadModal.js","sourceRoot":"","sources":["../../../src/components/SaveLoadModal/SaveLoadModal.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAU5C,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,GAAG,UAAU,EAAsB,EAAE,EAAE;IACxF,MAAM,SAAS,GAAG,YAAY,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IAC7C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAE5D,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,MAAM,EAAE,CAAC;YACT,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;QAC5C,CAAC;aAAM,CAAC;YACJ,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,EAAE,CAAC;QACtC,CAAC;QACD,OAAO,GAAG,EAAE;YACR,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,EAAE,CAAC;QACtC,CAAC,CAAC;IACN,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,SAAS,CAAC,GAAG,EAAE;QACX,MAAM,YAAY,GAAG,CAAC,KAAoB,EAAE,EAAE;YAC1C,IAAI,KAAK,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;gBACzB,OAAO,EAAE,CAAC;YACd,CAAC;QACL,CAAC,CAAC;QAEF,IAAI,MAAM,EAAE,CAAC;YACT,QAAQ,CAAC,gBAAgB,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QACvD,CAAC;QAED,OAAO,GAAG,EAAE;YACR,QAAQ,CAAC,mBAAmB,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;QAC1D,CAAC,CAAC;IACN,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAEtB,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,MAAM,YAAY,GAAG,KAAK,EAAE,SAAiB,EAAE,MAA+E,EAAE,EAAE;QAC9H,UAAU,CAAC,SAAS,CAAC,CAAC;QACtB,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,MAAM,MAAM,EAAE,CAAC;YAC9B,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBAC5B,wBAAwB;gBACxB,OAAO,EAAE,CAAC;YACd,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;YACvC,KAAK,CAAC,0DAA0D,CAAC,CAAC;QACtE,CAAC;gBAAS,CAAC;YACP,UAAU,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;IACL,CAAC,CAAC;IAEF,OAAO,CACH,eAAK,SAAS,EAAC,yDAAyD,aACpE,cACI,SAAS,EAAC,iDAAiD,EAC3D,OAAO,EAAE,OAAO,GAClB,EAEF,eAAK,SAAS,EAAC,2JAA2J,aACtK,eAAK,SAAS,EAAC,qEAAqE,aAChF,aAAI,SAAS,EAAC,+CAA+C,YACxD,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,kBAAkB,GAClF,EACL,iBACI,OAAO,EAAE,OAAO,EAChB,SAAS,EAAC,6FAA6F,gBAC5F,OAAO,YAElB,cAAK,SAAS,EAAC,SAAS,EAAC,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,cAAc,EAAC,OAAO,EAAC,WAAW,YAC1E,eAAM,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,EAAC,WAAW,EAAE,CAAC,EAAE,CAAC,EAAC,sBAAsB,GAAG,GAC5F,GACD,IACP,EAGN,cAAK,SAAS,EAAC,4CAA4C,YACvD,cAAK,SAAS,EAAC,sDAAsD,YAChE,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAC5B,eAEI,SAAS,EAAC,+GAA+G,aAGzH,eAAK,SAAS,EAAC,4BAA4B,aACvC,cAAI,SAAS,EAAC,4CAA4C,sBAChD,KAAK,GAAG,CAAC,IACd,EACJ,IAAI,CAAC,IAAI,IAAI,CACV,YAAG,SAAS,EAAC,oCAAoC,YAC5C,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,cAAc,EAAE,GAC/C,CACP,IACC,EAGN,cAAK,SAAS,EAAC,KAAK,YACf,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CACT,eAAK,SAAS,EAAC,WAAW,aACrB,IAAI,CAAC,IAAI,CAAC,WAAW,IAAI,CACtB,YAAG,SAAS,EAAC,2CAA2C,YACnD,IAAI,CAAC,IAAI,CAAC,WAAW,GACtB,CACP,EACA,IAAI,CAAC,IAAI,CAAC,UAAU,IAAI,CACrB,cACI,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,EACzB,GAAG,EAAC,iBAAiB,EACrB,SAAS,EAAC,kCAAkC,GAC9C,CACL,EACD,eAAK,SAAS,EAAC,YAAY,aACtB,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,UAAU,CAAC,IAAI,CACzC,iBACI,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,EAC7C,QAAQ,EAAE,OAAO,KAAK,IAAI,EAC1B,SAAS,EAAC,yKAAyK,YAElL,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,GACrC,CACZ,EACA,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,UAAU,CAAC,IAAI,CACzC,iBACI,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,EAC7C,QAAQ,EAAE,OAAO,KAAK,IAAI,EAC1B,SAAS,EAAC,yKAAyK,YAElL,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,GACzC,CACZ,EACD,iBACI,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAC/C,QAAQ,EAAE,OAAO,KAAK,IAAI,EAC1B,SAAS,EAAC,mJAAmJ,gBAClJ,aAAa,YAExB,cAAK,SAAS,EAAC,SAAS,EAAC,IAAI,EAAC,MAAM,EAAC,MAAM,EAAC,cAAc,EAAC,OAAO,EAAC,WAAW,YAC1E,eAAM,aAAa,EAAC,OAAO,EAAC,cAAc,EAAC,OAAO,EAAC,WAAW,EAAE,CAAC,EAAE,CAAC,EAAC,8HAA8H,GAAG,GACpM,GACD,IACP,IACJ,CACT,CAAC,CAAC,CAAC,CACA,eAAK,SAAS,EAAC,gDAAgD,aAC3D,YAAG,SAAS,EAAC,4BAA4B,2BAAe,EACvD,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,UAAU,CAAC,IAAI,CACzC,iBACI,OAAO,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,EAC7C,QAAQ,EAAE,OAAO,KAAK,IAAI,EAC1B,SAAS,EAAC,kKAAkK,YAE3K,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,GACzC,CACZ,IACC,CACT,GACC,KA5ED,KAAK,CA6ER,CACT,CAAC,GACA,GACJ,EAGN,cAAK,SAAS,EAAC,iDAAiD,YAC5D,iBACI,OAAO,EAAE,OAAO,EAChB,SAAS,EAAC,iHAAiH,sBAGtH,GACP,IACJ,IACJ,CACT,CAAC;AACN,CAAC,CAAC"}
1
+ {"version":3,"file":"SaveLoadModal.js","sourceRoot":"","sources":["../../../src/components/SaveLoadModal/SaveLoadModal.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { useSaveSlots } from "@react-text-game/core/saves";
2
+ import { SaveLoadMode } from "../../context/SaveLoadMenuContext";
3
+ type SaveSlotType = ReturnType<typeof useSaveSlots>[number];
4
+ interface SaveSlotProps {
5
+ slot: SaveSlotType;
6
+ index: number;
7
+ mode: SaveLoadMode;
8
+ loading: number | null;
9
+ onAction: (slotIndex: number, action: () => Promise<void | {
10
+ success: boolean;
11
+ message: string;
12
+ } | undefined>) => void;
13
+ }
14
+ export declare const SaveSlot: ({ slot, index, mode, loading, onAction, }: SaveSlotProps) => import("react/jsx-runtime").JSX.Element;
15
+ export {};
16
+ //# sourceMappingURL=SaveSlot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SaveSlot.d.ts","sourceRoot":"","sources":["../../../src/components/SaveLoadModal/SaveSlot.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAK3D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAE5D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D,UAAU,aAAa;IACnB,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,QAAQ,EAAE,CACN,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,OAAO,CACjB,IAAI,GAAG;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAC3D,KACA,IAAI,CAAC;CACb;AAED,eAAO,MAAM,QAAQ,GAAI,2CAMtB,aAAa,4CAgHf,CAAC"}
@@ -0,0 +1,21 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useTranslation } from "react-i18next";
4
+ import { twMerge } from "tailwind-merge";
5
+ import { Button } from "../../components/common/Button";
6
+ export const SaveSlot = ({ slot, index, mode, loading, onAction, }) => {
7
+ const { t } = useTranslation("ui");
8
+ const hasActions = mode === "save" || (mode === "load" && slot.data) || mode === "saveLoad";
9
+ return (_jsxs("div", { className: twMerge("bg-card rounded-lg border border-border transition-all overflow-hidden", hasActions ? "hover:border-muted-400 hover:shadow-lg" : "cursor-default"), children: [_jsxs("div", { className: "p-3 border-b border-border", children: [_jsx("h3", { className: "text-lg font-semibold text-card-foreground", children: t("saves.slot.label", {
10
+ number: index + 1,
11
+ }) }), _jsx("p", { className: "text-xs text-muted-foreground mt-1", children: slot.data ? new Date(slot.data.timestamp).toLocaleString() : 'no data' })] }), _jsx("div", { className: "p-3", children: slot.data ? (_jsxs("div", { className: "space-y-2", children: [slot.data.description &&
12
+ slot.data.description !== "undefined" && (_jsx("p", { className: "text-sm text-card-foreground line-clamp-2", children: slot.data.description })), slot.data.screenshot &&
13
+ slot.data.screenshot !== "undefined" && (_jsx("img", { src: slot.data.screenshot, alt: "Save screenshot", className: "w-full h-32 object-cover rounded" })), _jsxs("div", { className: "flex gap-2", children: [(mode === "load" || mode === "saveLoad") && (_jsx(Button, { onClick: () => onAction(index, slot.load), disabled: loading !== null, color: "primary", className: "flex-1 rounded-lg font-medium", children: loading === index
14
+ ? t("saves.actions.loading")
15
+ : t("saves.actions.load") })), (mode === "save" || mode === "saveLoad") && (_jsx(Button, { onClick: () => onAction(index, slot.save), disabled: loading !== null, color: "success", className: "flex-1 rounded-lg font-medium", children: loading === index
16
+ ? t("saves.actions.saving")
17
+ : t("saves.slot.overwrite") })), _jsx(Button, { onClick: () => onAction(index, slot.delete), disabled: loading !== null, color: "danger", className: "rounded-lg", "aria-label": "Delete save", children: _jsx("svg", { className: "w-5 h-5", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16" }) }) })] })] })) : (_jsxs("div", { className: "flex flex-col items-center justify-center py-6", children: [_jsx("p", { className: "text-muted-foreground mb-4", children: t("saves.slot.empty") }), (mode === "save" || mode === "saveLoad") && (_jsx(Button, { onClick: () => onAction(index, slot.save), disabled: loading !== null, color: "success", className: "rounded-lg font-medium", children: loading === index
18
+ ? t("saves.actions.saving")
19
+ : t("saves.slot.saveHere") }))] })) })] }));
20
+ };
21
+ //# sourceMappingURL=SaveSlot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SaveSlot.js","sourceRoot":"","sources":["../../../src/components/SaveLoadModal/SaveSlot.tsx"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  export * from "./common";
2
2
  export * from "./ErrorBoundary";
3
3
  export * from "./GameProvider";
4
+ export * from "./LanguageToggle";
4
5
  export { PassageController } from "./PassageController";
5
6
  export * from "./ReloadButton";
6
7
  export * from "./SaveButton";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,6BAA6B,CAAC"}
@@ -1,6 +1,7 @@
1
1
  export * from "./common";
2
2
  export * from "./ErrorBoundary";
3
3
  export * from "./GameProvider";
4
+ export * from "./LanguageToggle";
4
5
  export { PassageController } from "./PassageController";
5
6
  export * from "./ReloadButton";
6
7
  export * from "./SaveButton";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,cAAc,CAAC;AAC7B,cAAc,6BAA6B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ComponentsContext.d.ts","sourceRoot":"","sources":["../../../src/context/ComponentsContext/ComponentsContext.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE7C,eAAO,MAAM,iBAAiB,yDAE7B,CAAC"}
1
+ {"version":3,"file":"ComponentsContext.d.ts","sourceRoot":"","sources":["../../../src/context/ComponentsContext/ComponentsContext.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE7C,eAAO,MAAM,iBAAiB,yDAE7B,CAAC"}
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { createContext } from "react";
2
3
  export const ComponentsContext = createContext(undefined);
3
4
  //# sourceMappingURL=ComponentsContext.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ComponentsContext.js","sourceRoot":"","sources":["../../../src/context/ComponentsContext/ComponentsContext.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAItC,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAC1C,SAAS,CACZ,CAAC"}
1
+ {"version":3,"file":"ComponentsContext.js","sourceRoot":"","sources":["../../../src/context/ComponentsContext/ComponentsContext.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,aAAa,EAAE,MAAM,OAAO,CAAC;AAItC,MAAM,CAAC,MAAM,iBAAiB,GAAG,aAAa,CAC1C,SAAS,CACZ,CAAC"}
@@ -0,0 +1,37 @@
1
+ export declare const uiTranslations: {
2
+ readonly en: {
3
+ readonly ui: {
4
+ mainMenu: {
5
+ title: string;
6
+ newGame: string;
7
+ continue: string;
8
+ loadGame: string;
9
+ };
10
+ saves: {
11
+ title: {
12
+ save: string;
13
+ load: string;
14
+ saveLoad: string;
15
+ };
16
+ slot: {
17
+ label: string;
18
+ empty: string;
19
+ saveHere: string;
20
+ overwrite: string;
21
+ };
22
+ actions: {
23
+ load: string;
24
+ loading: string;
25
+ save: string;
26
+ saving: string;
27
+ delete: string;
28
+ close: string;
29
+ };
30
+ errors: {
31
+ actionFailed: string;
32
+ };
33
+ };
34
+ };
35
+ };
36
+ };
37
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/i18n/index.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAEjB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import ui from "./locales/en/ui.json";
2
+ export const uiTranslations = {
3
+ en: { ui },
4
+ };
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/i18n/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAEtC,MAAM,CAAC,MAAM,cAAc,GAAG;IAC1B,EAAE,EAAE,EAAE,EAAE,EAAE;CACJ,CAAC"}
@@ -0,0 +1,32 @@
1
+ {
2
+ "mainMenu": {
3
+ "title": "Main Menu",
4
+ "newGame": "New Game",
5
+ "continue": "Continue",
6
+ "loadGame": "Load Game"
7
+ },
8
+ "saves": {
9
+ "title": {
10
+ "save": "Save Game",
11
+ "load": "Load Game",
12
+ "saveLoad": "Save / Load Game"
13
+ },
14
+ "slot": {
15
+ "label": "Slot {{number}}",
16
+ "empty": "Empty Slot",
17
+ "saveHere": "Save Here",
18
+ "overwrite": "Overwrite"
19
+ },
20
+ "actions": {
21
+ "load": "Load",
22
+ "loading": "Loading...",
23
+ "save": "Save",
24
+ "saving": "Saving...",
25
+ "delete": "Delete",
26
+ "close": "Close"
27
+ },
28
+ "errors": {
29
+ "actionFailed": "An error occurred. Please check the console for details."
30
+ }
31
+ }
32
+ }
@@ -110,6 +110,7 @@
110
110
  --color-input: oklch(0.27 0.007 286);
111
111
  --color-muted: oklch(0.27 0.007 286);
112
112
  --color-muted-foreground: oklch(0.71 0.008 286);
113
+ --color-accent-foreground: oklch(0.98 0.001 286);
113
114
  --color-overlay: oklch(0 0 0);
114
115
  }
115
116
  }
@@ -313,6 +314,9 @@
313
314
  .right-4 {
314
315
  right: calc(var(--spacing) * 4);
315
316
  }
317
+ .right-20 {
318
+ right: calc(var(--spacing) * 20);
319
+ }
316
320
  .right-\[-4px\] {
317
321
  right: -4px;
318
322
  }
@@ -472,6 +476,9 @@
472
476
  .h-2 {
473
477
  height: calc(var(--spacing) * 2);
474
478
  }
479
+ .h-4 {
480
+ height: calc(var(--spacing) * 4);
481
+ }
475
482
  .h-5 {
476
483
  height: calc(var(--spacing) * 5);
477
484
  }
@@ -514,6 +521,9 @@
514
521
  .w-2 {
515
522
  width: calc(var(--spacing) * 2);
516
523
  }
524
+ .w-4 {
525
+ width: calc(var(--spacing) * 4);
526
+ }
517
527
  .w-5 {
518
528
  width: calc(var(--spacing) * 5);
519
529
  }
@@ -568,6 +578,9 @@
568
578
  .max-w-full {
569
579
  max-width: 100%;
570
580
  }
581
+ .min-w-full {
582
+ min-width: 100%;
583
+ }
571
584
  .flex-1 {
572
585
  flex: 1;
573
586
  }
@@ -596,12 +609,18 @@
596
609
  .rotate-45 {
597
610
  rotate: 45deg;
598
611
  }
612
+ .rotate-180 {
613
+ rotate: 180deg;
614
+ }
599
615
  .transform {
600
616
  transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
601
617
  }
602
618
  .animate-\[fadeIn_0\.3s_ease-in-out\] {
603
619
  animation: fadeIn 0.3s ease-in-out;
604
620
  }
621
+ .animate-\[fadeIn_150ms_ease-in\] {
622
+ animation: fadeIn 150ms ease-in;
623
+ }
605
624
  .animate-spin {
606
625
  animation: var(--animate-spin);
607
626
  }
@@ -800,9 +819,6 @@
800
819
  .bg-danger-500 {
801
820
  background-color: var(--color-danger-500);
802
821
  }
803
- .bg-danger-600 {
804
- background-color: var(--color-danger-600);
805
- }
806
822
  .bg-muted {
807
823
  background-color: var(--color-muted);
808
824
  }
@@ -857,9 +873,6 @@
857
873
  .bg-primary-500 {
858
874
  background-color: var(--color-primary-500);
859
875
  }
860
- .bg-primary-600 {
861
- background-color: var(--color-primary-600);
862
- }
863
876
  .bg-secondary-100 {
864
877
  background-color: var(--color-secondary-100);
865
878
  }
@@ -881,9 +894,6 @@
881
894
  .bg-success-500 {
882
895
  background-color: var(--color-success-500);
883
896
  }
884
- .bg-success-600 {
885
- background-color: var(--color-success-600);
886
- }
887
897
  .bg-transparent {
888
898
  background-color: transparent;
889
899
  }
@@ -947,15 +957,24 @@
947
957
  .py-2 {
948
958
  padding-block: calc(var(--spacing) * 2);
949
959
  }
960
+ .py-2\.5 {
961
+ padding-block: calc(var(--spacing) * 2.5);
962
+ }
950
963
  .py-3 {
951
964
  padding-block: calc(var(--spacing) * 3);
952
965
  }
953
966
  .py-6 {
954
967
  padding-block: calc(var(--spacing) * 6);
955
968
  }
969
+ .pt-2 {
970
+ padding-top: calc(var(--spacing) * 2);
971
+ }
956
972
  .text-justify {
957
973
  text-align: justify;
958
974
  }
975
+ .text-left {
976
+ text-align: left;
977
+ }
959
978
  .font-mono {
960
979
  font-family: var(--font-mono);
961
980
  }
@@ -1110,6 +1129,9 @@
1110
1129
  .text-white {
1111
1130
  color: var(--color-white);
1112
1131
  }
1132
+ .uppercase {
1133
+ text-transform: uppercase;
1134
+ }
1113
1135
  .accent-foreground {
1114
1136
  accent-color: var(--color-foreground);
1115
1137
  }
@@ -1201,6 +1223,15 @@
1201
1223
  transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
1202
1224
  transition-duration: var(--tw-duration, var(--default-transition-duration));
1203
1225
  }
1226
+ .transition-transform {
1227
+ transition-property: transform, translate, scale, rotate;
1228
+ transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
1229
+ transition-duration: var(--tw-duration, var(--default-transition-duration));
1230
+ }
1231
+ .duration-150 {
1232
+ --tw-duration: 150ms;
1233
+ transition-duration: 150ms;
1234
+ }
1204
1235
  .duration-200 {
1205
1236
  --tw-duration: 200ms;
1206
1237
  transition-duration: 200ms;
@@ -1261,13 +1292,6 @@
1261
1292
  }
1262
1293
  }
1263
1294
  }
1264
- .hover\:bg-danger-700 {
1265
- &:hover {
1266
- @media (hover: hover) {
1267
- background-color: var(--color-danger-700);
1268
- }
1269
- }
1270
- }
1271
1295
  .hover\:bg-muted {
1272
1296
  &:hover {
1273
1297
  @media (hover: hover) {
@@ -1338,13 +1362,6 @@
1338
1362
  }
1339
1363
  }
1340
1364
  }
1341
- .hover\:bg-primary-700 {
1342
- &:hover {
1343
- @media (hover: hover) {
1344
- background-color: var(--color-primary-700);
1345
- }
1346
- }
1347
- }
1348
1365
  .hover\:bg-secondary-50 {
1349
1366
  &:hover {
1350
1367
  @media (hover: hover) {
@@ -1401,13 +1418,6 @@
1401
1418
  }
1402
1419
  }
1403
1420
  }
1404
- .hover\:bg-success-700 {
1405
- &:hover {
1406
- @media (hover: hover) {
1407
- background-color: var(--color-success-700);
1408
- }
1409
- }
1410
- }
1411
1421
  .hover\:bg-warning-50 {
1412
1422
  &:hover {
1413
1423
  @media (hover: hover) {
@@ -1446,6 +1456,13 @@
1446
1456
  }
1447
1457
  }
1448
1458
  }
1459
+ .hover\:text-accent-foreground {
1460
+ &:hover {
1461
+ @media (hover: hover) {
1462
+ color: var(--color-accent-foreground);
1463
+ }
1464
+ }
1465
+ }
1449
1466
  .hover\:text-danger-800 {
1450
1467
  &:hover {
1451
1468
  @media (hover: hover) {
@@ -1488,11 +1505,6 @@
1488
1505
  cursor: not-allowed;
1489
1506
  }
1490
1507
  }
1491
- .disabled\:bg-muted-400 {
1492
- &:disabled {
1493
- background-color: var(--color-muted-400);
1494
- }
1495
- }
1496
1508
  .disabled\:opacity-50 {
1497
1509
  &:disabled {
1498
1510
  opacity: 50%;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@react-text-game/ui",
3
- "version": "0.2.4",
3
+ "version": "0.3.1",
4
4
  "description": "Themeable React UI component library for text-based games with Tailwind CSS v4, featuring story passages, interactive maps, and customizable game interfaces",
5
5
  "private": false,
6
6
  "type": "module",
@@ -8,11 +8,12 @@
8
8
  "module": "dist/index.js",
9
9
  "types": "dist/index.d.ts",
10
10
  "repository": "github:laruss/react-text-game",
11
- "homepage": "https://laruss.github.io/react-text-game/",
11
+ "homepage": "https://reacttextgame.dev/",
12
12
  "scripts": {
13
13
  "dev": "tsc --watch & tsc-alias --watch & bun run build:css --watch",
14
14
  "build": "tsc && tsc-alias && bun run build:css",
15
15
  "build:css": "mkdir -p dist/styles && bunx @tailwindcss/cli@latest -i src/styles/index.css -o dist/styles/index.css",
16
+ "check-types": "tsc --noEmit",
16
17
  "lint": "eslint .",
17
18
  "prepack": "rm -rf dist && bun run build",
18
19
  "test-pack": "npm pack --dry-run && bunx publint"
@@ -27,6 +28,8 @@
27
28
  "dist"
28
29
  ],
29
30
  "dependencies": {
31
+ "i18next": "^25.6.0",
32
+ "react-i18next": "^16.1.0",
30
33
  "tailwind-merge": "^3.3.1"
31
34
  },
32
35
  "peerDependencies": {
@@ -55,6 +58,10 @@
55
58
  "types": "./dist/index.d.ts",
56
59
  "import": "./dist/index.js"
57
60
  },
58
- "./styles": "./dist/styles/index.css"
61
+ "./styles": "./dist/styles/index.css",
62
+ "./i18n": {
63
+ "types": "./dist/i18n/index.d.ts",
64
+ "import": "./dist/i18n/index.js"
65
+ }
59
66
  }
60
67
  }