@tsparticles/template-tictactoe 4.4.0 → 4.5.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 (40) hide show
  1. package/CHANGELOG.md +10 -2
  2. package/package.json +5 -5
  3. package/scripts/prebuild.js +1 -1
  4. package/template/angular/package.json +14 -14
  5. package/template/angular/src/app/app.component.ts +1 -0
  6. package/template/angular-confetti/package.json +14 -14
  7. package/template/angular-confetti/src/app/app.component.ts +1 -0
  8. package/template/angular-fireworks/package.json +14 -14
  9. package/template/angular-fireworks/src/app/app.component.ts +1 -0
  10. package/template/astro/package.json +2 -2
  11. package/template/astro/src/pages/index.astro +6 -0
  12. package/template/ember/package.json +25 -4
  13. package/template/inferno/package.json +5 -4
  14. package/template/inferno/src/App.tsx +5 -5
  15. package/template/jquery/index.html +33 -0
  16. package/template/jquery/package.json +2 -2
  17. package/template/jquery/src/main.ts +5 -3
  18. package/template/lit/package.json +2 -2
  19. package/template/nextjs/package.json +7 -3
  20. package/template/nuxt2/package.json +12 -2
  21. package/template/nuxt3/package.json +2 -1
  22. package/template/nuxt4/package.json +2 -1
  23. package/template/preact/package.json +2 -2
  24. package/template/preact/src/App.tsx +11 -9
  25. package/template/qwik/package.json +2 -2
  26. package/template/qwik/src/App.tsx +10 -8
  27. package/template/react/package.json +4 -2
  28. package/template/riot/package.json +8 -4
  29. package/template/riot/src/app.riot +7 -4
  30. package/template/solid/package.json +2 -2
  31. package/template/stencil/package.json +1 -1
  32. package/template/stencil/src/components/app-home/app-home.tsx +11 -2
  33. package/template/svelte/package.json +1 -1
  34. package/template/vanilla/src/game/board.ts +1 -1
  35. package/template/vue2/package.json +3 -3
  36. package/template/vue3/package.json +1 -1
  37. package/template/webcomponents/index.html +32 -0
  38. package/template/webcomponents/package.json +2 -2
  39. package/template/webcomponents/src/main.ts +1 -1
  40. package/template.json +5 -5
package/CHANGELOG.md CHANGED
@@ -3,11 +3,19 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [4.5.1](https://github.com/tsparticles/tsparticles/compare/v4.5.0...v4.5.1) (2026-11-02)
7
+
8
+ **Note:** Version bump only for package @tsparticles/template-tictactoe
9
+
10
+ # [4.5.0](https://github.com/tsparticles/tsparticles/compare/v4.4.0...v4.5.0) (2026-10-25)
11
+
12
+ **Note:** Version bump only for package @tsparticles/template-tictactoe
13
+
6
14
  # [4.4.0](https://github.com/tsparticles/tsparticles/compare/v4.3.3...v4.4.0) (2026-08-30)
7
15
 
8
16
  ### Bug Fixes
9
17
 
10
- * various fixes for 4.4.0 ([475d06d](https://github.com/tsparticles/tsparticles/commit/475d06da27e1497bb097c0822fcfcb72d7142456))
18
+ - various fixes for 4.4.0 ([475d06d](https://github.com/tsparticles/tsparticles/commit/475d06da27e1497bb097c0822fcfcb72d7142456))
11
19
 
12
20
  ## [4.3.3](https://github.com/tsparticles/tsparticles/compare/v4.3.2...v4.3.3) (2026-07-23)
13
21
 
@@ -25,7 +33,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
25
33
 
26
34
  ### Bug Fixes
27
35
 
28
- * fixed angular confetti ([6f25a4a](https://github.com/tsparticles/tsparticles/commit/6f25a4a1eaa69c47f2668316e7b396fe55195f84))
36
+ - fixed angular confetti ([6f25a4a](https://github.com/tsparticles/tsparticles/commit/6f25a4a1eaa69c47f2668316e7b396fe55195f84))
29
37
 
30
38
  ## [4.2.1](https://github.com/tsparticles/tsparticles/compare/v4.2.0...v4.2.1) (2026-06-18)
31
39
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tsparticles/template-tictactoe",
3
- "version": "4.4.0",
3
+ "version": "4.5.1",
4
4
  "private": false,
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -18,12 +18,12 @@
18
18
  "prepack": "pnpm run build"
19
19
  },
20
20
  "dependencies": {
21
- "@tsparticles/confetti": "4.4.0",
22
- "@tsparticles/engine": "4.4.0",
23
- "@tsparticles/slim": "4.4.0"
21
+ "@tsparticles/confetti": "4.5.1",
22
+ "@tsparticles/engine": "4.5.1",
23
+ "@tsparticles/slim": "4.5.1"
24
24
  },
25
25
  "devDependencies": {
26
26
  "fs-extra": "^11.3.4"
27
27
  },
28
- "gitHead": "b7e605098d6ea937d5068c06542671d4891070e4"
28
+ "gitHead": "433c560448e5020cb051e1b025e0f9914f23b147"
29
29
  }
@@ -52,7 +52,7 @@ fs.readFile(libPackage, function (error, data) {
52
52
  }
53
53
  }
54
54
 
55
- fs.writeFile(libPackage, JSON.stringify(libObj, undefined, 2), "utf-8", function () {
55
+ fs.writeFile(libPackage, `${JSON.stringify(libObj, undefined, 2)}\n`, "utf-8", function () {
56
56
  console.log("template.json dependencies updated successfully");
57
57
  });
58
58
  });
@@ -11,24 +11,24 @@
11
11
  "watch": "ng build --watch --configuration development"
12
12
  },
13
13
  "dependencies": {
14
- "@angular/animations": "~22.0.0",
15
- "@angular/common": "~22.0.0",
16
- "@angular/compiler": "~22.0.0",
17
- "@angular/core": "~22.0.0",
18
- "@angular/forms": "~22.0.0",
19
- "@angular/platform-browser": "~22.0.0",
20
- "@angular/platform-browser-dynamic": "~22.0.0",
21
- "@angular/router": "~22.0.0",
22
- "@tsparticles/angular": "^4.1.3",
23
- "@tsparticles/confetti": "^3.8.1",
14
+ "@angular/animations": "~22.2.2",
15
+ "@angular/common": "~22.2.2",
16
+ "@angular/compiler": "~22.2.2",
17
+ "@angular/core": "~22.2.2",
18
+ "@angular/forms": "~22.2.2",
19
+ "@angular/platform-browser": "~22.2.2",
20
+ "@angular/platform-browser-dynamic": "~22.2.2",
21
+ "@angular/router": "~22.2.2",
22
+ "@tsparticles/angular": "^4.4.0",
23
+ "@tsparticles/confetti": "^4.4.0",
24
24
  "rxjs": "~7.8.2",
25
25
  "tslib": "^2.8.1",
26
- "zone.js": "~0.16.2"
26
+ "zone.js": "~0.16.3"
27
27
  },
28
28
  "devDependencies": {
29
- "@angular-devkit/build-angular": "~22.0.0",
30
- "@angular/cli": "~22.0.0",
31
- "@angular/compiler-cli": "~22.0.0",
29
+ "@angular-devkit/build-angular": "~22.2.2",
30
+ "@angular/cli": "~22.2.2",
31
+ "@angular/compiler-cli": "~22.2.2",
32
32
  "typescript": "~6.0.3"
33
33
  }
34
34
  }
@@ -11,6 +11,7 @@ const WIN_PATTERNS = [
11
11
  ];
12
12
 
13
13
  @Component({
14
+ standalone: false,
14
15
  selector: "app-root",
15
16
  templateUrl: "./app.component.html",
16
17
  styleUrls: ["./app.component.css"],
@@ -11,24 +11,24 @@
11
11
  "watch": "ng build --watch --configuration development"
12
12
  },
13
13
  "dependencies": {
14
- "@angular/animations": "~22.0.0",
15
- "@angular/common": "~22.0.0",
16
- "@angular/compiler": "~22.0.0",
17
- "@angular/core": "~22.0.0",
18
- "@angular/forms": "~22.0.0",
19
- "@angular/platform-browser": "~22.0.0",
20
- "@angular/platform-browser-dynamic": "~22.0.0",
21
- "@angular/router": "~22.0.0",
22
- "@tsparticles/angular": "^4.1.3",
23
- "@tsparticles/confetti": "^3.8.1",
14
+ "@angular/animations": "~22.2.2",
15
+ "@angular/common": "~22.2.2",
16
+ "@angular/compiler": "~22.2.2",
17
+ "@angular/core": "~22.2.2",
18
+ "@angular/forms": "~22.2.2",
19
+ "@angular/platform-browser": "~22.2.2",
20
+ "@angular/platform-browser-dynamic": "~22.2.2",
21
+ "@angular/router": "~22.2.2",
22
+ "@tsparticles/angular": "^4.4.0",
23
+ "@tsparticles/confetti": "^4.4.0",
24
24
  "rxjs": "~7.8.2",
25
25
  "tslib": "^2.8.1",
26
- "zone.js": "~0.16.2"
26
+ "zone.js": "~0.16.3"
27
27
  },
28
28
  "devDependencies": {
29
- "@angular-devkit/build-angular": "~22.0.0",
30
- "@angular/cli": "~22.0.0",
31
- "@angular/compiler-cli": "~22.0.0",
29
+ "@angular-devkit/build-angular": "~22.2.2",
30
+ "@angular/cli": "~22.2.2",
31
+ "@angular/compiler-cli": "~22.2.2",
32
32
  "typescript": "~6.0.3"
33
33
  }
34
34
  }
@@ -11,6 +11,7 @@ const WIN_PATTERNS = [
11
11
  ];
12
12
 
13
13
  @Component({
14
+ standalone: false,
14
15
  selector: "app-root",
15
16
  templateUrl: "./app.component.html",
16
17
  styleUrls: ["./app.component.css"],
@@ -11,24 +11,24 @@
11
11
  "watch": "ng build --watch --configuration development"
12
12
  },
13
13
  "dependencies": {
14
- "@angular/animations": "~22.0.0",
15
- "@angular/common": "~22.0.0",
16
- "@angular/compiler": "~22.0.0",
17
- "@angular/core": "~22.0.0",
18
- "@angular/forms": "~22.0.0",
19
- "@angular/platform-browser": "~22.0.0",
20
- "@angular/platform-browser-dynamic": "~22.0.0",
21
- "@angular/router": "~22.0.0",
22
- "@tsparticles/angular": "^4.1.3",
23
- "@tsparticles/confetti": "^3.8.1",
14
+ "@angular/animations": "~22.2.2",
15
+ "@angular/common": "~22.2.2",
16
+ "@angular/compiler": "~22.2.2",
17
+ "@angular/core": "~22.2.2",
18
+ "@angular/forms": "~22.2.2",
19
+ "@angular/platform-browser": "~22.2.2",
20
+ "@angular/platform-browser-dynamic": "~22.2.2",
21
+ "@angular/router": "~22.2.2",
22
+ "@tsparticles/angular": "^4.4.0",
23
+ "@tsparticles/confetti": "^4.4.0",
24
24
  "rxjs": "~7.8.2",
25
25
  "tslib": "^2.8.1",
26
- "zone.js": "~0.16.2"
26
+ "zone.js": "~0.16.3"
27
27
  },
28
28
  "devDependencies": {
29
- "@angular-devkit/build-angular": "~22.0.0",
30
- "@angular/cli": "~22.0.0",
31
- "@angular/compiler-cli": "~22.0.0",
29
+ "@angular-devkit/build-angular": "~22.2.2",
30
+ "@angular/cli": "~22.2.2",
31
+ "@angular/compiler-cli": "~22.2.2",
32
32
  "typescript": "~6.0.3"
33
33
  }
34
34
  }
@@ -11,6 +11,7 @@ const WIN_PATTERNS = [
11
11
  ];
12
12
 
13
13
  @Component({
14
+ standalone: false,
14
15
  selector: "app-root",
15
16
  templateUrl: "./app.component.html",
16
17
  styleUrls: ["./app.component.css"],
@@ -9,7 +9,7 @@
9
9
  "preview": "astro preview"
10
10
  },
11
11
  "dependencies": {
12
- "astro": "^5.0.0",
13
- "@tsparticles/astro": "^4.1.3"
12
+ "astro": "^7.3.2",
13
+ "@tsparticles/astro": "^4.4.0"
14
14
  }
15
15
  }
@@ -63,8 +63,14 @@ import Particles from "@tsparticles/astro";
63
63
  </div>
64
64
 
65
65
  <script>
66
+ import { initParticlesEngine } from "@tsparticles/astro";
67
+ import { loadSlim } from "@tsparticles/slim";
66
68
  import { confetti } from "@tsparticles/confetti";
67
69
 
70
+ await initParticlesEngine(async (engine) => {
71
+ await loadSlim(engine);
72
+ });
73
+
68
74
  const WIN_PATTERNS = [
69
75
  [0, 1, 2], [3, 4, 5], [6, 7, 8],
70
76
  [0, 3, 6], [1, 4, 7], [2, 5, 8],
@@ -7,11 +7,32 @@
7
7
  "build": "ember build",
8
8
  "preview": "ember serve"
9
9
  },
10
+ "devDependencies": {
11
+ "@ember/optional-features": "^3.0.0",
12
+ "@glimmer/component": "^2.1.1",
13
+ "@glimmer/tracking": "^1.1.2",
14
+ "broccoli-asset-rev": "^3.0.0",
15
+ "ember-auto-import": "^2.13.1",
16
+ "ember-cli": "~6.12.0",
17
+ "ember-cli-babel": "^8.3.1",
18
+ "ember-cli-htmlbars": "^7.0.1",
19
+ "ember-cli-inject-live-reload": "^2.1.0",
20
+ "ember-cli-sri": "^2.1.1",
21
+ "ember-cli-terser": "^4.0.2",
22
+ "ember-load-initializers": "^3.0.1",
23
+ "ember-modifier": "^4.3.0",
24
+ "ember-resolver": "^13.2.0",
25
+ "ember-source": "~6.12.0",
26
+ "loader.js": "^4.7.0",
27
+ "typescript": "^6.0.3",
28
+ "webpack": "^5.106.1"
29
+ },
10
30
  "dependencies": {
11
- "ember-source": "^6.0.0",
12
- "@tsparticles/ember": "^4.1.3"
31
+ "@tsparticles/ember": "^4.4.0",
32
+ "@tsparticles/engine": "^4.4.0",
33
+ "@tsparticles/slim": "^4.4.0"
13
34
  },
14
- "devDependencies": {
15
- "ember-cli": "^6.0.0"
35
+ "ember": {
36
+ "edition": "octane"
16
37
  }
17
38
  }
@@ -9,12 +9,13 @@
9
9
  "preview": "vite preview"
10
10
  },
11
11
  "dependencies": {
12
- "inferno": "^9.0.0",
13
- "inferno-hydrate": "^9.0.0",
14
- "@tsparticles/inferno": "^4.1.3"
12
+ "inferno": "^9.1.0",
13
+ "inferno-create-element": "^9.1.0",
14
+ "inferno-hydrate": "^9.1.0",
15
+ "@tsparticles/inferno": "^4.4.0"
15
16
  },
16
17
  "devDependencies": {
17
18
  "typescript": "~5.7.0",
18
- "vite": "^6.0.0"
19
+ "vite": "^8.3.5"
19
20
  }
20
21
  }
@@ -1,5 +1,5 @@
1
1
  import { Component } from "inferno";
2
- import Particles from "@tsparticles/inferno";
2
+ import { Particles, ParticlesProvider } from "@tsparticles/inferno";
3
3
  import { loadSlim } from "@tsparticles/slim";
4
4
  import { confetti } from "@tsparticles/confetti";
5
5
  import type { Engine, ISourceOptions } from "@tsparticles/engine";
@@ -114,14 +114,14 @@ export default class App extends Component<any, GameState> {
114
114
  }
115
115
 
116
116
  render() {
117
- const state = this.state;
117
+ const state = this.state as GameState;
118
118
  const status = state.winner
119
119
  ? state.winner === "draw" ? "It's a draw!" : `${state.winner} wins!`
120
120
  : `${state.currentPlayer}'s turn`;
121
121
 
122
122
  return (
123
- <div>
124
- <Particles id="tsparticles" init={init} options={particlesOptions} />
123
+ <ParticlesProvider init={init}>
124
+ <Particles id="tsparticles" options={particlesOptions} />
125
125
  <div id="app">
126
126
  <h1>Tic-Tac-Toe</h1>
127
127
  <div className="scoreboard">
@@ -143,7 +143,7 @@ export default class App extends Component<any, GameState> {
143
143
  </div>
144
144
  <button className="reset-btn" onClick={this.handleReset}>New Game</button>
145
145
  </div>
146
- </div>
146
+ </ParticlesProvider>
147
147
  );
148
148
  }
149
149
  }
@@ -0,0 +1,33 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>{{projectName}}</title>
7
+ </head>
8
+ <body>
9
+ <div id="app">
10
+ <h1>Tic-Tac-Toe</h1>
11
+ <div class="scoreboard">
12
+ <span>X: <strong id="scoreX">0</strong></span>
13
+ <span>Draws: <strong id="scoreDraw">0</strong></span>
14
+ <span>O: <strong id="scoreO">0</strong></span>
15
+ </div>
16
+ <div id="turnIndicator" class="turn">X's turn</div>
17
+ <div id="board" class="board">
18
+ <div class="cell" data-index="0"></div>
19
+ <div class="cell" data-index="1"></div>
20
+ <div class="cell" data-index="2"></div>
21
+ <div class="cell" data-index="3"></div>
22
+ <div class="cell" data-index="4"></div>
23
+ <div class="cell" data-index="5"></div>
24
+ <div class="cell" data-index="6"></div>
25
+ <div class="cell" data-index="7"></div>
26
+ <div class="cell" data-index="8"></div>
27
+ </div>
28
+ <button id="resetBtn" class="reset-btn">New Game</button>
29
+ </div>
30
+ <div id="tsparticles"></div>
31
+ <script type="module" src="/src/main.ts"></script>
32
+ </body>
33
+ </html>
@@ -10,11 +10,11 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "jquery": "^3.7.1",
13
- "@tsparticles/jquery": "^4.1.3"
13
+ "@tsparticles/jquery": "^4.4.0"
14
14
  },
15
15
  "devDependencies": {
16
16
  "@types/jquery": "^3.5.30",
17
17
  "typescript": "~5.7.0",
18
- "vite": "^6.0.0"
18
+ "vite": "^8.3.5"
19
19
  }
20
20
  }
@@ -2,6 +2,7 @@ import "./style.css";
2
2
  import $ from "jquery";
3
3
  import "@tsparticles/jquery";
4
4
  import { loadSlim } from "@tsparticles/slim";
5
+ import { tsParticles } from "@tsparticles/engine";
5
6
  import { confetti } from "@tsparticles/confetti";
6
7
 
7
8
  type Player = "X" | "O";
@@ -61,7 +62,7 @@ function render(): void {
61
62
  $el.toggleClass("win", state.winLine?.includes(i) ?? false);
62
63
  });
63
64
 
64
- const $turn = $("#turn");
65
+ const $turn = $("#turnIndicator");
65
66
  if (!state.winner) $turn.text(`${state.currentPlayer}'s turn`);
66
67
  else if (state.winner === "draw") $turn.text("It's a draw!");
67
68
  else $turn.text(`${state.winner} wins!`);
@@ -108,8 +109,9 @@ $(document).ready(async () => {
108
109
 
109
110
  render();
110
111
 
111
- await loadSlim($("#tsparticles").particles() as any);
112
- $("#tsparticles").particles({
112
+ await loadSlim(tsParticles);
113
+
114
+ $("#tsparticles").particles().load({
113
115
  fullScreen: { enable: true, zIndex: -1 },
114
116
  background: { color: { value: "#0a0a1a" } },
115
117
  fpsLimit: 60,
@@ -10,10 +10,10 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "lit": "^3.2.0",
13
- "@tsparticles/lit": "^4.1.3"
13
+ "@tsparticles/lit": "^4.4.0"
14
14
  },
15
15
  "devDependencies": {
16
- "vite": "^6.0.0",
16
+ "vite": "^8.3.5",
17
17
  "typescript": "~5.7.0"
18
18
  }
19
19
  }
@@ -9,12 +9,16 @@
9
9
  "preview": "next start"
10
10
  },
11
11
  "dependencies": {
12
+ "@tsparticles/nextjs": "^4.4.0",
13
+ "@tsparticles/react": "^4.4.0",
12
14
  "next": "^15.0.0",
13
15
  "react": "^19.2.5",
14
- "react-dom": "^19.2.5",
15
- "@tsparticles/react": "^4.1.3"
16
+ "react-dom": "^19.2.5"
16
17
  },
17
18
  "devDependencies": {
18
- "typescript": "~5.7.0"
19
+ "@types/node": "^24.10.1",
20
+ "@types/react": "^19.2.14",
21
+ "@types/react-dom": "^19.2.3",
22
+ "typescript": "^6.0.3"
19
23
  }
20
24
  }
@@ -8,7 +8,17 @@
8
8
  "preview": "nuxt start"
9
9
  },
10
10
  "dependencies": {
11
- "nuxt": "^2.19.0",
12
- "@tsparticles/vue2": "^4.1.3"
11
+ "nuxt": "^2.18.1",
12
+ "@tsparticles/vue2": "^4.4.0",
13
+ "@tsparticles/nuxt2": "^4.4.0"
14
+ },
15
+ "browserslist": [
16
+ "chrome 58",
17
+ "edge 16",
18
+ "firefox 57",
19
+ "safari 11"
20
+ ],
21
+ "devDependencies": {
22
+ "@babel/preset-env": "^7.29.0"
13
23
  }
14
24
  }
@@ -11,6 +11,7 @@
11
11
  "dependencies": {
12
12
  "nuxt": "^3.16.0",
13
13
  "vue": "^3.5.32",
14
- "@tsparticles/vue3": "^4.1.3"
14
+ "@tsparticles/vue3": "^4.4.0",
15
+ "@tsparticles/nuxt3": "^4.4.0"
15
16
  }
16
17
  }
@@ -11,6 +11,7 @@
11
11
  "dependencies": {
12
12
  "nuxt": "^4.0.0",
13
13
  "vue": "^3.5.32",
14
- "@tsparticles/vue3": "^4.1.3"
14
+ "@tsparticles/vue3": "^4.4.0",
15
+ "@tsparticles/nuxt4": "^4.4.0"
15
16
  }
16
17
  }
@@ -10,11 +10,11 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "preact": "^10.26.0",
13
- "@tsparticles/preact": "^4.1.3"
13
+ "@tsparticles/preact": "^4.4.0"
14
14
  },
15
15
  "devDependencies": {
16
16
  "@preact/preset-vite": "^2.10.0",
17
17
  "typescript": "~5.7.0",
18
- "vite": "^6.0.0"
18
+ "vite": "^8.3.5"
19
19
  }
20
20
  }
@@ -1,8 +1,8 @@
1
- import { useState, useCallback } from "preact/hooks";
2
- import Particles, { ParticlesProvider } from "@tsparticles/preact";
1
+ import { useEffect, useState, useCallback } from "preact/hooks";
2
+ import Particles, { initParticlesEngine } from "@tsparticles/preact";
3
3
  import { loadSlim } from "@tsparticles/slim";
4
4
  import { confetti } from "@tsparticles/confetti";
5
- import type { Engine, ISourceOptions } from "@tsparticles/engine";
5
+ import type { ISourceOptions } from "@tsparticles/engine";
6
6
  import "./App.css";
7
7
 
8
8
  type Player = "X" | "O";
@@ -57,10 +57,6 @@ function fireConfettiEffect() {
57
57
  fire(0.1, { spread: 120, startVelocity: 45 });
58
58
  }
59
59
 
60
- async function init(engine: Engine): Promise<void> {
61
- await loadSlim(engine);
62
- }
63
-
64
60
  const particlesOptions: ISourceOptions = {
65
61
  fullScreen: { enable: true, zIndex: -1 },
66
62
  background: { color: { value: "#0a0a1a" } },
@@ -79,6 +75,12 @@ const particlesOptions: ISourceOptions = {
79
75
  export default function App() {
80
76
  const [state, setState] = useState<GameState>(createInitialState);
81
77
 
78
+ useEffect(() => {
79
+ void initParticlesEngine(async (engine) => {
80
+ await loadSlim(engine);
81
+ });
82
+ }, []);
83
+
82
84
  const handleMove = useCallback((index: number) => {
83
85
  setState((prev) => {
84
86
  if (prev.board[index] || prev.winner) return prev;
@@ -113,7 +115,7 @@ export default function App() {
113
115
  : `${state.currentPlayer}'s turn`;
114
116
 
115
117
  return (
116
- <ParticlesProvider init={init}>
118
+ <>
117
119
  <Particles id="tsparticles" options={particlesOptions} />
118
120
  <div id="app">
119
121
  <h1>Tic-Tac-Toe</h1>
@@ -136,6 +138,6 @@ export default function App() {
136
138
  </div>
137
139
  <button class="reset-btn" onClick={handleReset}>New Game</button>
138
140
  </div>
139
- </ParticlesProvider>
141
+ </>
140
142
  );
141
143
  }
@@ -10,10 +10,10 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "@builder.io/qwik": "^1.12.0",
13
- "@tsparticles/qwik": "^4.1.3"
13
+ "@tsparticles/qwik": "^4.4.0"
14
14
  },
15
15
  "devDependencies": {
16
16
  "typescript": "~5.7.0",
17
- "vite": "^6.0.0"
17
+ "vite": "^7.3.6"
18
18
  }
19
19
  }
@@ -1,8 +1,8 @@
1
- import { component$, useSignal, $ } from "@builder.io/qwik";
2
- import Particles from "@tsparticles/qwik";
1
+ import { component$, useSignal, useVisibleTask$, $ } from "@builder.io/qwik";
2
+ import { Particles, initParticlesEngine } from "@tsparticles/qwik";
3
3
  import { loadSlim } from "@tsparticles/slim";
4
4
  import { confetti } from "@tsparticles/confetti";
5
- import type { Engine, ISourceOptions } from "@tsparticles/engine";
5
+ import type { ISourceOptions } from "@tsparticles/engine";
6
6
 
7
7
  type Player = "X" | "O";
8
8
 
@@ -36,10 +36,6 @@ function fireConfettiEffect() {
36
36
  fire(0.1, { spread: 120, startVelocity: 45 });
37
37
  }
38
38
 
39
- async function init(engine: Engine): Promise<void> {
40
- await loadSlim(engine);
41
- }
42
-
43
39
  const particlesOptions: ISourceOptions = {
44
40
  fullScreen: { enable: true, zIndex: -1 },
45
41
  background: { color: { value: "#0a0a1a" } },
@@ -64,6 +60,12 @@ interface GameState {
64
60
  }
65
61
 
66
62
  export default component$(() => {
63
+ useVisibleTask$(() => {
64
+ void initParticlesEngine(async (engine) => {
65
+ await loadSlim(engine);
66
+ });
67
+ });
68
+
67
69
  const state = useSignal<GameState>({
68
70
  board: Array(9).fill(null),
69
71
  currentPlayer: "X",
@@ -105,7 +107,7 @@ export default component$(() => {
105
107
 
106
108
  return (
107
109
  <>
108
- <Particles init={init} id="tsparticles" options={particlesOptions} />
110
+ <Particles id="tsparticles" options={particlesOptions} />
109
111
  <div id="app">
110
112
  <h1>Tic-Tac-Toe</h1>
111
113
  <div class="scoreboard">
@@ -11,9 +11,11 @@
11
11
  "dependencies": {
12
12
  "react": "^19.2.5",
13
13
  "react-dom": "^19.2.5",
14
- "@tsparticles/react": "^4.1.3"
14
+ "@tsparticles/react": "^4.4.0"
15
15
  },
16
16
  "devDependencies": {
17
- "@vitejs/plugin-react": "^6.0.1"
17
+ "@vitejs/plugin-react": "^6.0.1",
18
+ "@types/react": "^19.2.14",
19
+ "@types/react-dom": "^19.2.3"
18
20
  }
19
21
  }
@@ -9,12 +9,16 @@
9
9
  "preview": "vite preview"
10
10
  },
11
11
  "dependencies": {
12
- "riot": "^10.0.0",
13
- "@tsparticles/riot": "^4.1.3"
12
+ "riot": "^10.1.6",
13
+ "@tsparticles/riot": "^4.4.0",
14
+ "@tsparticles/confetti": "^4.4.0",
15
+ "@tsparticles/engine": "^4.4.0",
16
+ "@tsparticles/slim": "^4.4.0"
14
17
  },
15
18
  "devDependencies": {
19
+ "@riotjs/compiler": "^10.0.4",
16
20
  "rollup-plugin-riot": "^10.0.0",
17
- "vite": "^6.0.0",
18
- "typescript": "~5.7.0"
21
+ "typescript": "^5.7.2",
22
+ "vite": "^8.3.5"
19
23
  }
20
24
  }
@@ -9,10 +9,10 @@
9
9
  </div>
10
10
  <div class="turn">{ statusText }</div>
11
11
  <div class="board">
12
- <div each="{ cell, i in state.board }"
13
- class="cell{ cell ? ' taken' : '' }{ state.winLine && state.winLine.includes(i) ? ' win' : '' }"
14
- onclick="{ () => handleMove(i) }">
15
- { cell }
12
+ <div each="{ square in state.squares }"
13
+ class="cell{ square.value ? ' taken' : '' }{ state.winLine && state.winLine.includes(square.index) ? ' win' : '' }"
14
+ onclick="{ () => handleMove(square.index) }">
15
+ { square.value }
16
16
  </div>
17
17
  </div>
18
18
  <button class="reset-btn" onclick="{ handleReset }">New Game</button>
@@ -36,6 +36,9 @@
36
36
  winner: null,
37
37
  winLine: null,
38
38
  scores: { X: 0, O: 0, draw: 0 },
39
+ get squares() {
40
+ return this.board.map((value, index) => ({ value, index }));
41
+ },
39
42
  },
40
43
  get statusText() {
41
44
  const w = this.state.winner;
@@ -10,9 +10,9 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "solid-js": "^1.8.11",
13
- "@tsparticles/solid": "^4.1.3"
13
+ "@tsparticles/solid": "^4.4.0"
14
14
  },
15
15
  "devDependencies": {
16
- "vite-plugin-solid": "^2.8.2"
16
+ "vite-plugin-solid": "^2.11.14"
17
17
  }
18
18
  }
@@ -9,6 +9,6 @@
9
9
  },
10
10
  "dependencies": {
11
11
  "@stencil/core": "^4.20.0",
12
- "@tsparticles/stencil": "^4.1.3"
12
+ "@tsparticles/stencil": "^4.4.0"
13
13
  }
14
14
  }
@@ -1,6 +1,7 @@
1
1
  import { Component, State, h } from "@stencil/core";
2
2
  import { confetti } from "@tsparticles/confetti";
3
- import type { ISourceOptions } from "@tsparticles/engine";
3
+ import { loadSlim } from "@tsparticles/slim";
4
+ import type { Engine, ISourceOptions } from "@tsparticles/engine";
4
5
 
5
6
  type Player = "X" | "O";
6
7
 
@@ -61,6 +62,10 @@ export class AppHome {
61
62
  @State() winLine: number[] | null = null;
62
63
  @State() scores = { X: 0, O: 0, draw: 0 };
63
64
 
65
+ private async particlesInit(engine: Engine): Promise<void> {
66
+ await loadSlim(engine);
67
+ }
68
+
64
69
  get status(): string {
65
70
  if (!this.winner) return `${this.currentPlayer}'s turn`;
66
71
  if (this.winner === "draw") return "It's a draw!";
@@ -95,7 +100,11 @@ export class AppHome {
95
100
  render() {
96
101
  return (
97
102
  <div>
98
- <stencil-particles id="tsparticles" options={particlesOptions} />
103
+ <stencil-particles
104
+ container-id="tsparticles"
105
+ init={this.particlesInit.bind(this)}
106
+ options={particlesOptions}
107
+ />
99
108
  <div id="app">
100
109
  <h1>Tic-Tac-Toe</h1>
101
110
  <div class="scoreboard">
@@ -9,7 +9,7 @@
9
9
  "preview": "vite preview"
10
10
  },
11
11
  "dependencies": {
12
- "@tsparticles/svelte": "^4.1.3"
12
+ "@tsparticles/svelte": "^4.4.0"
13
13
  },
14
14
  "devDependencies": {
15
15
  "@sveltejs/vite-plugin-svelte": "^5.0.3",
@@ -1,4 +1,4 @@
1
- import { type GameState, makeMove } from "./game-state";
1
+ import type { GameState } from "./game-state";
2
2
  import { fireConfetti } from "./confetti-effect";
3
3
 
4
4
  const boardEl = document.getElementById("board") as HTMLDivElement;
@@ -9,11 +9,11 @@
9
9
  },
10
10
  "dependencies": {
11
11
  "vue": "^2.7.16",
12
- "@tsparticles/vue2": "^4.1.3"
12
+ "@tsparticles/vue2": "^4.4.0"
13
13
  },
14
14
  "devDependencies": {
15
- "@vitejs/plugin-vue2": "^2.3.1",
16
- "vite": "^6.0.0",
15
+ "@vitejs/plugin-vue2": "^2.3.4",
16
+ "vite": "^7.3.6",
17
17
  "vue-template-compiler": "^2.7.16"
18
18
  }
19
19
  }
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "vue": "^3.5.32",
13
- "@tsparticles/vue3": "^4.1.3"
13
+ "@tsparticles/vue3": "^4.4.0"
14
14
  },
15
15
  "devDependencies": {
16
16
  "@vitejs/plugin-vue": "^6.0.5",
@@ -0,0 +1,32 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>{{projectName}}</title>
7
+ </head>
8
+ <body>
9
+ <div id="app">
10
+ <h1>Tic-Tac-Toe</h1>
11
+ <div class="scoreboard">
12
+ <span>X: <strong id="scoreX">0</strong></span>
13
+ <span>Draws: <strong id="scoreDraw">0</strong></span>
14
+ <span>O: <strong id="scoreO">0</strong></span>
15
+ </div>
16
+ <div id="turnIndicator" class="turn">X's turn</div>
17
+ <div id="board" class="board">
18
+ <div class="cell" data-index="0"></div>
19
+ <div class="cell" data-index="1"></div>
20
+ <div class="cell" data-index="2"></div>
21
+ <div class="cell" data-index="3"></div>
22
+ <div class="cell" data-index="4"></div>
23
+ <div class="cell" data-index="5"></div>
24
+ <div class="cell" data-index="6"></div>
25
+ <div class="cell" data-index="7"></div>
26
+ <div class="cell" data-index="8"></div>
27
+ </div>
28
+ <button id="resetBtn" class="reset-btn">New Game</button>
29
+ </div>
30
+ <script type="module" src="/src/main.ts"></script>
31
+ </body>
32
+ </html>
@@ -9,10 +9,10 @@
9
9
  "preview": "vite preview"
10
10
  },
11
11
  "dependencies": {
12
- "@tsparticles/webcomponents": "^4.1.3"
12
+ "@tsparticles/webcomponents": "^4.4.0"
13
13
  },
14
14
  "devDependencies": {
15
15
  "typescript": "~5.7.0",
16
- "vite": "^6.0.0"
16
+ "vite": "^8.3.5"
17
17
  }
18
18
  }
@@ -53,7 +53,7 @@ function fireConfettiEffect(): void {
53
53
 
54
54
  function render(): void {
55
55
  const boardEl = document.getElementById("board") as HTMLDivElement;
56
- const turnEl = document.getElementById("turn") as HTMLDivElement;
56
+ const turnEl = document.querySelector(".turn") as HTMLDivElement;
57
57
  const scoreX = document.getElementById("scoreX") as HTMLSpanElement;
58
58
  const scoreO = document.getElementById("scoreO") as HTMLSpanElement;
59
59
  const scoreDraw = document.getElementById("scoreDraw") as HTMLSpanElement;
package/template.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "package": {
3
3
  "dependencies": {
4
- "@tsparticles/engine": "^4.4.0",
5
- "@tsparticles/slim": "^4.4.0",
6
- "@tsparticles/confetti": "^4.4.0"
4
+ "@tsparticles/engine": "^4.5.1",
5
+ "@tsparticles/slim": "^4.5.1",
6
+ "@tsparticles/confetti": "^4.5.1"
7
7
  },
8
8
  "devDependencies": {
9
9
  "typescript": "^6.0.3",
10
- "vite": "^8.1.0"
10
+ "vite": "^8.3.5"
11
11
  }
12
12
  }
13
- }
13
+ }