koin.js 1.0.7 → 1.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Browser Retro Game Emulation for React
4
4
 
5
- > **27 systems. Cloud saves. Zero backend required.**
5
+ > **28 systems. Cloud saves. Multi-language. Zero backend required.**
6
6
 
7
7
  [![Try the Demo](https://img.shields.io/badge/PLAY-TRY%20THE%20DEMO-FFD600?style=for-the-badge&logoColor=black&labelColor=black)](https://koin.js.org/)
8
8
  [![NPM Version](https://img.shields.io/npm/v/koin.js?style=for-the-badge&color=white&labelColor=black)](https://www.npmjs.com/package/koin.js)
@@ -14,13 +14,58 @@ The drop-in React component for browser-based retro game emulation. Built on [No
14
14
 
15
15
  ## Features
16
16
 
17
- - 🎮 **27 Systems** — NES to PlayStation, Game Boy to Arcade
18
- - â˜ī¸ **Cloud-Ready Saves** — Slot-based saves with screenshots, auto-save, emergency saves
19
- - âĒ **Rewind Time** — Go back in time (auto-enabled for 8/16-bit systems)
20
- - 🏆 **RetroAchievements** — Official RA integration with hardcore mode
21
- - 📱 **Touch Controls** — GPU-accelerated virtual D-pad and buttons
22
- - 📹 **Gameplay Recording** — VP9 WebM capture at 30fps
23
- - 🎨 **10 CRT Shaders** — Lottes, Geom, zFast, LCD Grid, and more
17
+ ### 🎮 Core Emulation
18
+ - **28 Consoles** — NES to PlayStation, Game Boy to Dreamcast
19
+ - **Automatic Core Selection** — Best emulator core per system
20
+ - **BIOS Management** — Multi-file BIOS support with UI selection
21
+ - **Performance Optimized** — SharedArrayBuffer for maximum speed
22
+
23
+ ### â˜ī¸ Save System
24
+ - **Slot-Based Saves** — Multiple save states with screenshots
25
+ - **Auto-Save** — Periodic background saves (configurable interval)
26
+ - **Emergency Saves** — Automatic save on tab hide/close
27
+ - **Cloud-Ready API** — Bring your own backend with async handlers
28
+
29
+ ### 🎨 Display & Effects
30
+ - **10 CRT Shaders** — Lottes, Geom, Easymode, Hyllian, zFast, and more
31
+ - **Runtime Shader Switching** — Change filters without restart
32
+ - **System Theming** — Per-console accent colors
33
+ - **Screenshot Capture** — PNG snapshots with hotkey support
34
+
35
+ ### đŸ•šī¸ Controls
36
+ - **Keyboard Remapping** — Per-console custom key bindings
37
+ - **Gamepad Support** — Auto-detect Xbox, PlayStation, Nintendo controllers
38
+ - **Touch Controls** — GPU-accelerated virtual D-pad and buttons for mobile
39
+ - **Control Persistence** — Saves user preferences across sessions
40
+
41
+ ### âĒ Special Features
42
+ - **Rewind** — Time-travel gameplay (auto-enabled for 8/16-bit)
43
+ - **Speed Control** — 0.25x to 4x with hotkey toggle
44
+ - **Fast-Forward** — Turbo mode for grinding
45
+
46
+ ### 📹 Recording & Overlays
47
+ - **Gameplay Recording** — VP9/VP8 WebM capture at 30fps
48
+ - **Performance Overlay** — FPS, frame time, memory stats
49
+ - **Input Display** — Virtual controller overlay for streaming
50
+ - **Toast Notifications** — Non-intrusive save/load feedback
51
+
52
+ ### 🏆 RetroAchievements
53
+ - **Official RA Integration** — Track unlocks across sessions
54
+ - **Hardcore Mode** — Disable saves/cheats for leaderboard eligibility
55
+ - **Achievement Browser** — Filter by locked/unlocked status
56
+ - **Progress Tracking** — Points remaining per game
57
+
58
+ ### 🌍 Internationalization
59
+ - **3 Built-in Languages** — English, Spanish, French
60
+ - **Type-Safe Translations** — Full TypeScript support
61
+ - **Partial Overrides** — Customize specific strings
62
+ - **Custom Languages** — Implement your own translation set
63
+
64
+ ### đŸŽ¯ Developer Experience
65
+ - **TypeScript First** — Complete type definitions
66
+ - **Zero Config** — Works out of the box
67
+ - **Customizable UI** — Accent colors, shaders, controls
68
+ - **Web Component** — Use without React
24
69
 
25
70
  ## Installation
26
71
 
@@ -36,6 +81,7 @@ pnpm add koin.js
36
81
 
37
82
  ```tsx
38
83
  import { GamePlayer } from 'koin.js';
84
+ import 'koin.js/styles.css';
39
85
 
40
86
  export default function App() {
41
87
  return (
@@ -60,14 +106,45 @@ import { GamePlayer } from 'koin.js';
60
106
  system="NES"
61
107
  title="My Game"
62
108
 
63
- // Your backend handlers
64
- onSaveState={async (slot, blob, screenshot) => { /* save to your API */ }}
65
- onLoadState={async (slot) => { /* return Blob or null */ }}
66
- onAutoSave={async (blob, screenshot) => { /* periodic save */ }}
109
+ // Cloud save handlers
110
+ onSaveState={async (slot, blob, screenshot) => {
111
+ await fetch(`/api/saves/${slot}`, {
112
+ method: 'POST',
113
+ body: blob,
114
+ });
115
+ }}
116
+ onLoadState={async (slot) => {
117
+ const res = await fetch(`/api/saves/${slot}`);
118
+ return res.ok ? await res.blob() : null;
119
+ }}
120
+ onAutoSave={async (blob, screenshot) => {
121
+ await fetch('/api/autosave', { method: 'POST', body: blob });
122
+ }}
67
123
 
68
- // Optional theming
124
+ // Customization
69
125
  systemColor="#FF3333"
70
126
  shader="crt/crt-lottes"
127
+ initialLanguage="es"
128
+ />
129
+ ```
130
+
131
+ ## Internationalization
132
+
133
+ ```tsx
134
+ <GamePlayer
135
+ initialLanguage="es" // Spanish UI
136
+ />
137
+
138
+ // Or provide custom translations
139
+ import { en } from 'koin.js';
140
+
141
+ <GamePlayer
142
+ translations={{
143
+ controls: {
144
+ ...en.controls,
145
+ play: 'START GAME',
146
+ }
147
+ }}
71
148
  />
72
149
  ```
73
150
 
@@ -91,18 +168,30 @@ import { GamePlayer } from 'koin.js';
91
168
  | NES / Famicom | `NES` | fceumm |
92
169
  | Super Nintendo | `SNES` | snes9x |
93
170
  | Nintendo 64 | `N64` | mupen64plus_next |
94
- | Game Boy / Color / Advance | `GB`, `GBC`, `GBA` | gambatte, mgba |
171
+ | Game Boy / Color | `GB`, `GBC` | gambatte |
172
+ | Game Boy Advance | `GBA` | mgba |
95
173
  | Nintendo DS | `NDS` | desmume |
96
174
  | PlayStation | `PS1` | pcsx_rearmed |
97
175
  | PSP | `PSP` | ppsspp |
98
- | Genesis / Mega Drive | `GENESIS` | genesis_plus_gx |
99
- | Master System | `MASTER_SYSTEM` | gearsystem |
176
+ | Sega Genesis / Mega Drive | `GENESIS` | genesis_plus_gx |
177
+ | Sega Master System | `MASTER_SYSTEM` | gearsystem |
100
178
  | Game Gear | `GAME_GEAR` | gearsystem |
101
- | Saturn | `SATURN` | yabasanshiro |
102
- | Dreamcast | `DREAMCAST` | flycast |
179
+ | Sega Saturn | `SATURN` | yabasanshiro |
180
+ | Sega Dreamcast | `DREAMCAST` | flycast |
181
+ | Sega CD | `SEGA_CD` | genesis_plus_gx |
103
182
  | Neo Geo | `NEOGEO` | fbalpha2012_neogeo |
104
183
  | Arcade (MAME) | `ARCADE` | mame2003_plus |
105
- | ...and 13 more | [See full list](https://koin.js.org/docs/systems) |
184
+ | Atari 2600 | `ATARI2600` | stella |
185
+ | Atari 7800 | `ATARI7800` | prosystem |
186
+ | Atari Lynx | `LYNX` | handy |
187
+ | PC Engine / TurboGrafx-16 | `PCE` | mednafen_pce |
188
+ | WonderSwan / Color | `WS`, `WSC` | mednafen_wswan |
189
+ | Virtual Boy | `VB` | mednafen_vb |
190
+ | Vectrex | `VECTREX` | vecx |
191
+ | Commodore 64 | `C64` | vice_x64 |
192
+ | DOS | `DOS` | dosbox_pure |
193
+
194
+ [Full system details →](https://koin.js.org/docs/systems)
106
195
 
107
196
  ## Requirements
108
197
 
@@ -123,7 +212,11 @@ async headers() {
123
212
 
124
213
  ## Documentation
125
214
 
126
- Full documentation at **[koin.js.org](https://koin.js.org/docs)**
215
+ - **[Quick Start](https://koin.js.org/docs/installation)** — Get up and running
216
+ - **[Usage Guide](https://koin.js.org/docs/usage)** — Cloud saves, BIOS, RA integration
217
+ - **[API Reference](https://koin.js.org/docs/api)** — Complete props documentation
218
+ - **[Advanced Guide](https://koin.js.org/docs/advanced)** — Shaders, recording, controls, i18n
219
+ - **[Systems List](https://koin.js.org/docs/systems)** — Per-console configuration
127
220
 
128
221
  ## License
129
222
 
package/dist/index.d.mts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as react from 'react';
2
+ import react__default from 'react';
2
3
  import { Nostalgist } from 'nostalgist';
3
4
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
5
 
@@ -443,6 +444,236 @@ declare function getAchievementBadgeUrl(badgeName: string, locked?: boolean): st
443
444
  */
444
445
  declare function getUserAvatarUrl(userPic: string): string;
445
446
 
447
+ interface KoinTranslations {
448
+ controls: {
449
+ play: string;
450
+ pause: string;
451
+ reset: string;
452
+ rewind: string;
453
+ save: string;
454
+ load: string;
455
+ snap: string;
456
+ rec: string;
457
+ stopRec: string;
458
+ startRecord: string;
459
+ stopRecord: string;
460
+ mute: string;
461
+ unmute: string;
462
+ help: string;
463
+ full: string;
464
+ keys: string;
465
+ menuOpen: string;
466
+ menuClose: string;
467
+ gamepadConnected: string;
468
+ noGamepad: string;
469
+ press: string;
470
+ startBtn: string;
471
+ selectBtn: string;
472
+ };
473
+ common: {
474
+ disabledInHardcore: string;
475
+ notSupported: string;
476
+ playToEnableRewind: string;
477
+ };
478
+ settings: {
479
+ title: string;
480
+ general: string;
481
+ audio: string;
482
+ video: string;
483
+ input: string;
484
+ advanced: string;
485
+ fullscreen: string;
486
+ controls: string;
487
+ gamepad: string;
488
+ cheats: string;
489
+ retroAchievements: string;
490
+ shortcuts: string;
491
+ exit: string;
492
+ language: string;
493
+ selectLanguage: string;
494
+ };
495
+ overlay: {
496
+ play: string;
497
+ systemFirmware: string;
498
+ loading: string;
499
+ initializing: string;
500
+ loadingSave: string;
501
+ preparingSlot: string;
502
+ systemError: string;
503
+ failedInit: string;
504
+ retry: string;
505
+ slotReady: string;
506
+ paused: string;
507
+ };
508
+ notifications: {
509
+ saved: string;
510
+ loaded: string;
511
+ error: string;
512
+ recordingStarted: string;
513
+ recordingSaved: string;
514
+ downloaded: string;
515
+ loadedFile: string;
516
+ savedSlot: string;
517
+ loadedSlot: string;
518
+ deletedSlot: string;
519
+ emptySlot: string;
520
+ noSaveFound: string;
521
+ failedSave: string;
522
+ failedLoad: string;
523
+ failedDelete: string;
524
+ failedFetch: string;
525
+ controllerConnected: string;
526
+ controllerDisconnected: string;
527
+ controllerReady: string;
528
+ insertCoin: string;
529
+ insertCoinTitle: string;
530
+ controlsSaved: string;
531
+ controlsReset: string;
532
+ };
533
+ modals: {
534
+ shortcuts: {
535
+ title: string;
536
+ playerShortcuts: string;
537
+ overlays: string;
538
+ recording: string;
539
+ showHelp: string;
540
+ perfOverlay: string;
541
+ inputDisplay: string;
542
+ toggleRec: string;
543
+ toggleMute: string;
544
+ pressEsc: string;
545
+ };
546
+ controls: {
547
+ title: string;
548
+ keyboard: string;
549
+ description: string;
550
+ pressKey: string;
551
+ reset: string;
552
+ save: string;
553
+ };
554
+ gamepad: {
555
+ title: string;
556
+ noGamepad: string;
557
+ connected: string;
558
+ none: string;
559
+ player: string;
560
+ noController: string;
561
+ pressAny: string;
562
+ waiting: string;
563
+ pressButton: string;
564
+ pressEsc: string;
565
+ reset: string;
566
+ save: string;
567
+ };
568
+ cheats: {
569
+ title: string;
570
+ addCheat: string;
571
+ available: string;
572
+ emptyTitle: string;
573
+ emptyDesc: string;
574
+ copy: string;
575
+ active: string;
576
+ toggleHint: string;
577
+ };
578
+ saveSlots: {
579
+ title: string;
580
+ saveTitle: string;
581
+ loadTitle: string;
582
+ emptySlot: string;
583
+ subtitleSave: string;
584
+ subtitleLoad: string;
585
+ loading: string;
586
+ locked: string;
587
+ upgrade: string;
588
+ autoSave: string;
589
+ autoSaveDesc: string;
590
+ noData: string;
591
+ slot: string;
592
+ footerSave: string;
593
+ footerLoad: string;
594
+ };
595
+ bios: {
596
+ title: string;
597
+ description: string;
598
+ warningTitle: string;
599
+ warning: string;
600
+ systemDefault: string;
601
+ active: string;
602
+ defaultDesc: string;
603
+ emptyTitle: string;
604
+ emptyDesc: string;
605
+ footer: string;
606
+ };
607
+ };
608
+ retroAchievements: {
609
+ title: string;
610
+ login: string;
611
+ logout: string;
612
+ username: string;
613
+ password: string;
614
+ hardcore: string;
615
+ achievements: string;
616
+ locked: string;
617
+ unlocked: string;
618
+ mastered: string;
619
+ identifying: string;
620
+ achievementsAvailable: string;
621
+ gameNotSupported: string;
622
+ connect: string;
623
+ connected: string;
624
+ createAccount: string;
625
+ privacy: string;
626
+ privacyText: string;
627
+ connecting: string;
628
+ connectAccount: string;
629
+ poweredBy: string;
630
+ connectedStatus: string;
631
+ yourUsername: string;
632
+ yourPassword: string;
633
+ usernameRequired: string;
634
+ noGame: string;
635
+ loadGame: string;
636
+ noAchievements: string;
637
+ notSupported: string;
638
+ ptsRemaining: string;
639
+ filters: {
640
+ all: string;
641
+ locked: string;
642
+ unlocked: string;
643
+ };
644
+ };
645
+ overlays: {
646
+ performance: {
647
+ title: string;
648
+ fps: string;
649
+ frameTime: string;
650
+ memory: string;
651
+ core: string;
652
+ input: string;
653
+ active: string;
654
+ };
655
+ toast: {
656
+ saved: string;
657
+ loaded: string;
658
+ error: string;
659
+ };
660
+ recording: {
661
+ started: string;
662
+ stopped: string;
663
+ saved: string;
664
+ paused: string;
665
+ recording: string;
666
+ resume: string;
667
+ pause: string;
668
+ stop: string;
669
+ hover: string;
670
+ };
671
+ };
672
+ }
673
+ type RecursivePartial<T> = {
674
+ [P in keyof T]?: T[P] extends (infer U)[] ? RecursivePartial<U>[] : T[P] extends object ? RecursivePartial<T[P]> : T[P];
675
+ };
676
+
446
677
  interface SaveSlot {
447
678
  slot: number;
448
679
  timestamp: string;
@@ -514,6 +745,7 @@ interface GamePlayerProps {
514
745
  onRALogin?: (username: string, password: string) => Promise<boolean>;
515
746
  onRALogout?: () => void;
516
747
  onRAHardcoreChange?: (enabled: boolean) => void;
748
+ translations?: RecursivePartial<KoinTranslations>;
517
749
  }
518
750
  interface PlayerControlsProps {
519
751
  isPaused: boolean;
@@ -548,6 +780,7 @@ interface PlayerControlsProps {
548
780
  systemColor?: string;
549
781
  gamepadCount?: number;
550
782
  onGamepadSettings?: () => void;
783
+ onSettings?: () => void;
551
784
  volume?: number;
552
785
  isMuted?: boolean;
553
786
  onVolumeChange?: (volume: number) => void;
@@ -601,6 +834,7 @@ interface RAHardcodeRestrictions {
601
834
  declare const GamePlayer: react.NamedExoticComponent<GamePlayerProps & {
602
835
  controls?: KeyboardMapping;
603
836
  saveControls?: (controls: KeyboardMapping) => void;
837
+ initialLanguage?: "en" | "es" | "fr";
604
838
  }>;
605
839
 
606
840
  /**
@@ -862,4 +1096,17 @@ declare function useGameRecording({ getCanvasElement, }: UseGameRecordingProps):
862
1096
  declare function getCachedRom(romId: string): Promise<Blob | null>;
863
1097
  declare function fetchAndCacheRom(romId: string, url: string): Promise<Blob>;
864
1098
 
865
- export { ALL_BUTTONS, AchievementPopup, BUTTON_GROUPS, BUTTON_LABELS, type ButtonId, CONSOLE_CAPABILITIES, CONSOLE_KEYBOARD_OVERRIDES, type Cheat, type CheatModalProps, type ConsoleCapabilities, type ControlConfig, type ControlMapperProps, type ControlMapping, type ControllerBrand, DEFAULT_CONTROLS, DEFAULT_GAMEPAD, DEFAULT_KEYBOARD, DPAD_BUTTONS, type EmulatorStatus, FACE_BUTTONS, GamePlayer, type GamePlayerProps, type GamepadInfo, type GamepadMapping, type KeyboardMapping, PERFORMANCE_TIER_1_SYSTEMS, PERFORMANCE_TIER_2_SYSTEMS, type PlayerControlsProps, type PlayerIndex, type RAAchievement, type RACredentials, type RAGame, type RAGameExtended, type RAHardcodeRestrictions, RASidebar, type RAUser, RA_MEDIA_BASE, type RetroAchievementsConfig, SHADER_PRESETS, SHOULDER_BUTTONS, STANDARD_AXIS_MAP, STANDARD_GAMEPAD_BUTTONS, STICK_BUTTONS, SUPPORTED_EXTENSIONS, SYSTEMS, SYSTEM_BUTTONS, type SaveSlot, type SaveSlotModalProps, type ShaderPresetId, ShaderSelector, ShortcutsReference, type ShowToastOptions, type SpeedMultiplier, type StandardAxis, type SystemConfig, TRIGGER_BUTTONS, type Toast, ToastContainer, type ToastType, type UseGamepadOptions, type UseGamepadReturn, type UseNostalgistReturn, type UseToastReturn, buildRetroArchConfig, clearAllControls, consoleHasButton, detectControllerBrand, detectSystem, fetchAndCacheRom, formatGamepadButton, formatKeyCode, gamepadToRetroArchConfig, getAchievementBadgeUrl, getCachedRom, getConsoleButtons, getConsoleCapabilities, getConsoleKeyboardDefaults, getCore, getDBSystemNames, getFullGamepadMapping, getFullKeyboardMapping, getSupportedExtensions, getSystem, getSystemByDbName, getSystemByKey, getSystemFromExtension, getSystemsList, getUserAvatarUrl, isSystemSupported, keyboardToRetroArchConfig, loadAllGamepadMappings, loadGamepadMapping, loadKeyboardMapping, normalizeSystemKey, saveGamepadMapping, saveKeyboardMapping, systemsMatch, useGameRecording, useGamepad, useNostalgist, useToast };
1099
+ declare const en: KoinTranslations;
1100
+
1101
+ declare const es: KoinTranslations;
1102
+
1103
+ declare const fr: KoinTranslations;
1104
+
1105
+ interface KoinI18nProviderProps {
1106
+ children: react__default.ReactNode;
1107
+ translations?: RecursivePartial<KoinTranslations>;
1108
+ }
1109
+ declare const KoinI18nProvider: react__default.FC<KoinI18nProviderProps>;
1110
+ declare function useKoinTranslation(): KoinTranslations;
1111
+
1112
+ export { ALL_BUTTONS, AchievementPopup, BUTTON_GROUPS, BUTTON_LABELS, type ButtonId, CONSOLE_CAPABILITIES, CONSOLE_KEYBOARD_OVERRIDES, type Cheat, type CheatModalProps, type ConsoleCapabilities, type ControlConfig, type ControlMapperProps, type ControlMapping, type ControllerBrand, DEFAULT_CONTROLS, DEFAULT_GAMEPAD, DEFAULT_KEYBOARD, DPAD_BUTTONS, type EmulatorStatus, FACE_BUTTONS, GamePlayer, type GamePlayerProps, type GamepadInfo, type GamepadMapping, type KeyboardMapping, KoinI18nProvider, type KoinTranslations, PERFORMANCE_TIER_1_SYSTEMS, PERFORMANCE_TIER_2_SYSTEMS, type PlayerControlsProps, type PlayerIndex, type RAAchievement, type RACredentials, type RAGame, type RAGameExtended, type RAHardcodeRestrictions, RASidebar, type RAUser, RA_MEDIA_BASE, type RecursivePartial, type RetroAchievementsConfig, SHADER_PRESETS, SHOULDER_BUTTONS, STANDARD_AXIS_MAP, STANDARD_GAMEPAD_BUTTONS, STICK_BUTTONS, SUPPORTED_EXTENSIONS, SYSTEMS, SYSTEM_BUTTONS, type SaveSlot, type SaveSlotModalProps, type ShaderPresetId, ShaderSelector, ShortcutsReference, type ShowToastOptions, type SpeedMultiplier, type StandardAxis, type SystemConfig, TRIGGER_BUTTONS, type Toast, ToastContainer, type ToastType, type UseGamepadOptions, type UseGamepadReturn, type UseNostalgistReturn, type UseToastReturn, buildRetroArchConfig, clearAllControls, consoleHasButton, detectControllerBrand, detectSystem, en, es, fetchAndCacheRom, formatGamepadButton, formatKeyCode, fr, gamepadToRetroArchConfig, getAchievementBadgeUrl, getCachedRom, getConsoleButtons, getConsoleCapabilities, getConsoleKeyboardDefaults, getCore, getDBSystemNames, getFullGamepadMapping, getFullKeyboardMapping, getSupportedExtensions, getSystem, getSystemByDbName, getSystemByKey, getSystemFromExtension, getSystemsList, getUserAvatarUrl, isSystemSupported, keyboardToRetroArchConfig, loadAllGamepadMappings, loadGamepadMapping, loadKeyboardMapping, normalizeSystemKey, saveGamepadMapping, saveKeyboardMapping, systemsMatch, useGameRecording, useGamepad, useKoinTranslation, useNostalgist, useToast };