{"_id":"@cardgamesplay/klondike","_rev":"2-2667ab1836e1b1887530e9b6ff393709","name":"@cardgamesplay/klondike","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@cardgamesplay/klondike","version":"0.1.0","keywords":["klondike","solitaire","card-game","patience","browser-game","typescript","vanilla-js","drag-and-drop","keyboard-accessible","i18n","web-audio","free-online-game","canvas-game","html5-game"],"author":{"name":"Card Games Play"},"license":"MIT","_id":"@cardgamesplay/klondike@0.1.0","maintainers":[{"name":"tedonash","email":"tedo.nash@gmail.com"}],"homepage":"https://www.cardgamesplay.com/","bugs":{"url":"https://github.com/bgbigbrother/klondike/issues"},"dist":{"shasum":"e7739d23de372fd2060a35f70a31e7d23a2eddc8","tarball":"https://registry.npmjs.org/@cardgamesplay/klondike/-/klondike-0.1.0.tgz","fileCount":98,"integrity":"sha512-iHKu6PDFxpMdCZJiMvuSoGjrTIswJmMBctAEssLXalxsEw2Lmc0eGEy5NgZYj19VGwT+fC5nmYF74lmgmlXMdg==","signatures":[{"sig":"MEUCIAz7BJFCazLSBi1BTnG//y0xCe5+FGD/TSaS27lCzDWZAiEAgXZs9eF2SRl2QVsreUK4ysbyvtiwuXPAPeWgHRunY6g=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":30963774},"main":"./src/index.ts","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./src/index.ts","default":"./dist/index.js"},"./i18n":{"types":"./dist/i18n/index.d.ts","import":"./dist/i18n/index.js"},"./ui/*":{"types":"./dist/ui/*.d.ts","import":"./dist/ui/*.js"},"./game/*":{"types":"./dist/game/*.d.ts","import":"./dist/game/*.js"},"./i18n/*":{"types":"./dist/i18n/*.d.ts","import":"./dist/i18n/*.js"}},"funding":{"url":"https://www.cardgamesplay.com/","type":"individual"},"gitHead":"402267bae207ed9ef4eaecab102bff0d430046f7","scripts":{"dev":"vite","test":"vitest --run","build":"tsc -p tsconfig.build.json && vite build","prepublishOnly":"npm run build"},"_npmUser":{"name":"tedonash","email":"tedo.nash@gmail.com"},"repository":{"url":"git+https://github.com/bgbigbrother/klondike.git","type":"git"},"_npmVersion":"10.9.2","description":"Browser-based Klondike Solitaire game built with TypeScript and vanilla DOM. Features drag-and-drop, keyboard navigation, card animations, sound effects, a music player, and i18n support for 16 languages. Play free at https://www.cardgamesplay.com/","directories":{},"sideEffects":false,"_nodeVersion":"22.17.0","dependencies":{"cardsJS":"^1.0.0","@rse/soundlp":"^1.1.1"},"publishConfig":{"main":"./dist/index.js","access":"public","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./i18n":{"types":"./dist/i18n/index.d.ts","import":"./dist/i18n/index.js"},"./ui/*":{"types":"./dist/ui/*.d.ts","import":"./dist/ui/*.js"},"./game/*":{"types":"./dist/game/*.d.ts","import":"./dist/game/*.js"},"./i18n/*":{"types":"./dist/i18n/*.d.ts","import":"./dist/i18n/*.js"}}},"_hasShrinkwrap":false,"devDependencies":{"vite":"^5.0.0","vitest":"^1.0.0","happy-dom":"^20.8.9","@vitest/ui":"^1.0.0","fast-check":"^3.0.0","typescript":"^5.0.0"},"_npmOperationalInternal":{"tmp":"tmp/klondike_0.1.0_1776706402824_0.3405072381970322","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@cardgamesplay/klondike","version":"0.1.1","description":"Browser-based Klondike Solitaire game built with TypeScript and vanilla DOM. Features drag-and-drop, keyboard navigation, card animations, sound effects, a music player, and i18n support for 16 languages. Play free at https://www.cardgamesplay.com/","license":"MIT","author":{"name":"Card Games Play"},"homepage":"https://www.cardgamesplay.com/","repository":{"type":"git","url":"git+https://github.com/bgbigbrother/klondike.git"},"bugs":{"url":"https://github.com/bgbigbrother/klondike/issues"},"funding":{"type":"individual","url":"https://www.cardgamesplay.com/"},"keywords":["klondike","solitaire","card-game","patience","browser-game","typescript","vanilla-js","drag-and-drop","keyboard-accessible","i18n","web-audio","free-online-game","canvas-game","html5-game"],"type":"module","main":"./src/index.ts","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":"./src/index.ts","default":"./dist/index.js","types":"./dist/index.d.ts"},"./game/*":{"import":"./dist/game/*.js","types":"./dist/game/*.d.ts"},"./ui/*":{"import":"./dist/ui/*.js","types":"./dist/ui/*.d.ts"},"./i18n":{"import":"./dist/i18n/index.js","types":"./dist/i18n/index.d.ts"},"./i18n/*":{"import":"./dist/i18n/*.js","types":"./dist/i18n/*.d.ts"}},"publishConfig":{"access":"public","main":"./dist/index.js","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./game/*":{"import":"./dist/game/*.js","types":"./dist/game/*.d.ts"},"./ui/*":{"import":"./dist/ui/*.js","types":"./dist/ui/*.d.ts"},"./i18n":{"import":"./dist/i18n/index.js","types":"./dist/i18n/index.d.ts"},"./i18n/*":{"import":"./dist/i18n/*.js","types":"./dist/i18n/*.d.ts"}}},"scripts":{"dev":"vite","build":"tsc -p tsconfig.build.json && vite build","prepublishOnly":"npm run build","test":"vitest --run"},"sideEffects":true,"engines":{"node":">=18"},"dependencies":{"@rse/soundlp":"^1.1.1","cardsJS":"^1.0.0"},"devDependencies":{"@vitest/ui":"^1.0.0","fast-check":"^3.0.0","happy-dom":"^20.8.9","typescript":"^5.0.0","vite":"^5.0.0","vitest":"^1.0.0"},"_id":"@cardgamesplay/klondike@0.1.1","gitHead":"8663619071c6cd35213c12a18423a95c2813d022","_nodeVersion":"22.17.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-6s+q1btwlLo4moXMHKQlirb/iD5ZKeHeBFYTG7rFuLm0Jf860zeAUXoXyBW5oIkVriH+60bYXFQINAbKWYcK1w==","shasum":"b94c837f450c4935fec5aaac6ce1d48b4649a46c","tarball":"https://registry.npmjs.org/@cardgamesplay/klondike/-/klondike-0.1.1.tgz","fileCount":98,"unpackedSize":30963773,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDUvzqmQdESgyyFKRkRneTm8DCMitIp7FdUloaH1SgK8wIhAPDbyl/0J3tGeAeKEVwJxirkl7krlQk2zPLyYSlUKoND"}]},"_npmUser":{"name":"tedonash","email":"tedo.nash@gmail.com"},"directories":{},"maintainers":[{"name":"tedonash","email":"tedo.nash@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/klondike_0.1.1_1776708620331_0.20212469430908597"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-20T17:33:22.733Z","modified":"2026-04-20T18:10:21.153Z","0.1.0":"2026-04-20T17:33:23.599Z","0.1.1":"2026-04-20T18:10:21.037Z"},"bugs":{"url":"https://github.com/bgbigbrother/klondike/issues"},"author":{"name":"Card Games Play"},"license":"MIT","homepage":"https://www.cardgamesplay.com/","keywords":["klondike","solitaire","card-game","patience","browser-game","typescript","vanilla-js","drag-and-drop","keyboard-accessible","i18n","web-audio","free-online-game","canvas-game","html5-game"],"repository":{"type":"git","url":"git+https://github.com/bgbigbrother/klondike.git"},"description":"Browser-based Klondike Solitaire game built with TypeScript and vanilla DOM. Features drag-and-drop, keyboard navigation, card animations, sound effects, a music player, and i18n support for 16 languages. Play free at https://www.cardgamesplay.com/","maintainers":[{"name":"tedonash","email":"tedo.nash@gmail.com"}],"readme":"# @cardgamesplay/klondike\n\nA browser-based Klondike Solitaire game built with TypeScript, Vite, and vanilla DOM — no framework required. Features drag-and-drop, keyboard navigation, card animations, synthesised sound effects, a built-in music player, and full i18n support for 16 languages.\n\n**🎮 [Play the live demo at cardgamesplay.com](https://www.cardgamesplay.com/)**\n\n## Features\n\n- Classic Klondike (Patience) rules with configurable stock-pass limits (∞ / 1 / 3) and a face-up mode\n- Drag-and-drop card movement with visual drop-target highlighting and stack ghost images\n- Full keyboard navigation — arrow keys to move between piles, Space to select/place, Escape to cancel\n- Animated card dealing, stock flips (3D Y-axis rotation), and foundation fly-to transitions\n- Synthesised Web Audio API sound effects (card click, card drop, foundation chime) — no audio files needed\n- Built-in music player powered by `@rse/soundlp` with 27 ambient tracks, play/pause, volume slider, and mute toggle\n- Undo support — every action is reversible all the way back to the opening deal\n- Auto-move (sends all eligible cards to foundations) and auto-complete (finishes the game when all cards are visible)\n- Pause mode that hides all card faces and freezes the timer\n- Fullscreen support\n- Responsive layout that adapts to any viewport size, including mobile and orientation changes\n- Internationalisation (i18n) with 16 locales: English, Bulgarian, Spanish, French, German, Italian, Portuguese, Russian, Chinese, Japanese, Korean, Arabic (RTL), Hindi, Vietnamese, Polish, and Turkish\n- Language selector in the header and hamburger menu, with cross-tab sync via `localStorage`\n- Score tracking with point values for waste-to-tableau (+5), to-foundation (+10), card flip (+5), foundation-to-tableau (−15), and stock recycle (−100)\n- Win detection with a celebratory overlay showing final score, time, and move count\n- SVG card images via `cardsJS` with automatic CSS/Unicode fallback\n- Published as an ES module with typed exports for game engine, UI, and i18n\n\n## Project Structure\n\n```\n├── src/\n│   ├── index.ts              # App bootstrap — wires engine, renderer, drag-drop, keyboard, timer, UI\n│   ├── game/\n│   │   ├── types.ts           # Card, GameState, GameOptions, Move, scoring constants\n│   │   ├── deck.ts            # createDeck() and Fisher-Yates shuffle\n│   │   ├── gameEngine.ts      # Core game logic — draw, recycle, move, auto-move, undo\n│   │   ├── scoring.ts         # Score delta helpers\n│   │   ├── winCondition.ts    # checkWin(), canAutoComplete(), autoComplete()\n│   │   ├── undoManager.ts     # Command-pattern undo stack\n│   │   ├── deck.test.ts       # Unit + property-based tests for deck\n│   │   └── gameEngine.test.ts # Unit + property-based tests for engine\n│   ├── ui/\n│   │   ├── renderer.ts        # DOM rendering — stock, waste, foundations, tableau, keyboard highlights\n│   │   ├── layout.ts          # Responsive layout calculator (card sizing, pile positions)\n│   │   ├── dragDrop.ts        # HTML5 drag-and-drop with validity checking and stack ghosts\n│   │   ├── keyboardController.ts # Full keyboard navigation and selection\n│   │   ├── cardAnimator.ts    # Deal, stock-flip, and foundation-fly animations\n│   │   ├── audio.ts           # Synthesised sound effects (Web Audio API)\n│   │   ├── musicPlayer.ts     # Ambient music player with track selection and volume control\n│   │   └── langSelector.ts    # Language dropdown component\n│   └── i18n/\n│       ├── index.ts           # Locale registry, setLocale, applyLocale, cross-tab sync\n│       ├── init.ts            # Minimal bootstrap for static pages\n│       ├── en.ts              # English (canonical locale type)\n│       └── {bg,es,fr,de,it,pt,ru,zh,ja,ko,ar,hi,vi,pl,tr}.ts\n├── index.html                 # Standalone dev shell\n├── dev-entry.ts               # Dev entry point (imports shared styles + game)\n├── dev.css                    # Dev-mode style overrides\n├── package.json\n├── vite.config.ts             # Vite config (library build + dev server)\n├── vitest.config.ts           # Vitest config (happy-dom environment)\n├── tsconfig.json              # Dev/IDE TypeScript config\n└── tsconfig.build.json        # Build TypeScript config (emits declarations)\n```\n\n## Getting Started\n\n> Want to just play? Head over to **[cardgamesplay.com](https://www.cardgamesplay.com/)** — no install needed.\n\n### Prerequisites\n\n- Node.js ≥ 18\n- npm (or your preferred package manager)\n\n### Install\n\n```bash\nnpm install\n```\n\n### Development\n\n```bash\nnpm run dev\n```\n\nOpens a local Vite dev server with hot module replacement. The standalone dev shell at `index.html` includes a site header, language selector, and dev banner.\n\n### Build\n\n```bash\nnpm run build\n```\n\nCompiles TypeScript declarations via `tsc` and bundles the library as an ES module into `dist/`.\n\n### Test\n\n```bash\nnpm test\n```\n\nRuns all tests with Vitest in a `happy-dom` environment. The test suite includes:\n\n- Unit tests for deck creation, shuffle, game engine moves, scoring, foundations, and undo\n- Property-based tests (via `fast-check`) covering shuffle permutation validity, draw/recycle invariants, tableau/foundation placement rules, card count preservation, and i18n persistence round-trips\n\n## Keyboard Shortcuts\n\n| Key | Action |\n|---|---|\n| ← → ↑ ↓ | Move cursor between piles |\n| Space | Select card(s) or confirm a move |\n| Escape | Cancel current selection |\n| F2 | New game |\n| Ctrl+Z / Cmd+Z | Undo |\n| A | Auto-move all eligible cards to foundations |\n\n## Game Rules\n\n1. A standard 52-card deck is shuffled and dealt into 7 tableau columns (column N gets N cards; only the top card is face-up). The remaining 24 cards form the stock.\n2. Tableau builds go down in rank with alternating colours (red on black, black on red).\n3. Only Kings may fill empty tableau columns.\n4. Contiguous face-up sequences can be moved as a unit.\n5. Removing a card from a tableau column automatically flips the newly exposed face-down card.\n6. Click the stock to draw one card face-up to the waste pile.\n7. When the stock is empty, click to recycle the waste (−100 points; disabled if the pass limit is reached).\n8. Foundations build up by suit from Ace to King.\n9. Cards can be moved back from foundations to the tableau (−15 points).\n10. Complete all four foundations (Ace through King) to win.\n\n## Scoring\n\n| Action | Points |\n|---|---|\n| Waste → Tableau | +5 |\n| Any → Foundation | +10 |\n| Flip face-down card | +5 |\n| Foundation → Tableau | −15 |\n| Recycle waste to stock | −100 |\n\nScore floor is 0 (never goes negative).\n\n## Internationalisation\n\nAll UI strings are driven by locale objects in `src/i18n/`. The `applyLocale()` function walks the DOM and updates elements tagged with `data-i18n`, `data-i18n-title`, `data-i18n-aria-label`, and other data attributes. Arabic is supported with automatic RTL layout.\n\nTo add a new language, duplicate `src/i18n/en.ts`, translate the values, and register the new locale in `src/i18n/index.ts`.\n\n## Tech Stack\n\n- TypeScript (strict mode, ES2020 target)\n- Vite (dev server + library build)\n- Vitest + happy-dom (testing)\n- fast-check (property-based testing)\n- `@rse/soundlp` (ambient music sprite)\n- `cardsJS` (SVG card images)\n- Web Audio API (synthesised sound effects)\n- Vanilla DOM (no UI framework)\n\n## License\n\nThis project is licensed under the [MIT License](./LICENSE.md).\n\n## Links\n\n- **[Play Online](https://www.cardgamesplay.com/)** — free, no sign-up, works on any device\n- [GitHub Repository](https://github.com/bgbigbrother/klondike)\n- [npm Package](https://www.npmjs.com/package/@cardgamesplay/klondike)\n- [Report a Bug](https://github.com/bgbigbrother/klondike/issues)\n","readmeFilename":"README.md"}