@tsparticles/template-tictactoe 4.4.0 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -2
- package/package.json +5 -5
- package/scripts/prebuild.js +1 -1
- package/template/angular/package.json +14 -14
- package/template/angular/src/app/app.component.ts +1 -0
- package/template/angular-confetti/package.json +14 -14
- package/template/angular-confetti/src/app/app.component.ts +1 -0
- package/template/angular-fireworks/package.json +14 -14
- package/template/angular-fireworks/src/app/app.component.ts +1 -0
- package/template/astro/package.json +2 -2
- package/template/astro/src/pages/index.astro +6 -0
- package/template/ember/package.json +25 -4
- package/template/inferno/package.json +5 -4
- package/template/inferno/src/App.tsx +5 -5
- package/template/jquery/index.html +33 -0
- package/template/jquery/package.json +2 -2
- package/template/jquery/src/main.ts +5 -3
- package/template/lit/package.json +2 -2
- package/template/nextjs/package.json +7 -3
- package/template/nuxt2/package.json +12 -2
- package/template/nuxt3/package.json +2 -1
- package/template/nuxt4/package.json +2 -1
- package/template/preact/package.json +2 -2
- package/template/preact/src/App.tsx +11 -9
- package/template/qwik/package.json +2 -2
- package/template/qwik/src/App.tsx +10 -8
- package/template/react/package.json +4 -2
- package/template/riot/package.json +8 -4
- package/template/riot/src/app.riot +7 -4
- package/template/solid/package.json +2 -2
- package/template/stencil/package.json +1 -1
- package/template/stencil/src/components/app-home/app-home.tsx +11 -2
- package/template/svelte/package.json +1 -1
- package/template/vanilla/src/game/board.ts +1 -1
- package/template/vue2/package.json +3 -3
- package/template/vue3/package.json +1 -1
- package/template/webcomponents/index.html +32 -0
- package/template/webcomponents/package.json +2 -2
- package/template/webcomponents/src/main.ts +1 -1
- package/template.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -3,11 +3,15 @@
|
|
|
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.0](https://github.com/tsparticles/tsparticles/compare/v4.4.0...v4.5.0) (2026-10-25)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @tsparticles/template-tictactoe
|
|
9
|
+
|
|
6
10
|
# [4.4.0](https://github.com/tsparticles/tsparticles/compare/v4.3.3...v4.4.0) (2026-08-30)
|
|
7
11
|
|
|
8
12
|
### Bug Fixes
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
- various fixes for 4.4.0 ([475d06d](https://github.com/tsparticles/tsparticles/commit/475d06da27e1497bb097c0822fcfcb72d7142456))
|
|
11
15
|
|
|
12
16
|
## [4.3.3](https://github.com/tsparticles/tsparticles/compare/v4.3.2...v4.3.3) (2026-07-23)
|
|
13
17
|
|
|
@@ -25,7 +29,7 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline
|
|
|
25
29
|
|
|
26
30
|
### Bug Fixes
|
|
27
31
|
|
|
28
|
-
|
|
32
|
+
- fixed angular confetti ([6f25a4a](https://github.com/tsparticles/tsparticles/commit/6f25a4a1eaa69c47f2668316e7b396fe55195f84))
|
|
29
33
|
|
|
30
34
|
## [4.2.1](https://github.com/tsparticles/tsparticles/compare/v4.2.0...v4.2.1) (2026-06-18)
|
|
31
35
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsparticles/template-tictactoe",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.0",
|
|
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.
|
|
22
|
-
"@tsparticles/engine": "4.
|
|
23
|
-
"@tsparticles/slim": "4.
|
|
21
|
+
"@tsparticles/confetti": "4.5.0",
|
|
22
|
+
"@tsparticles/engine": "4.5.0",
|
|
23
|
+
"@tsparticles/slim": "4.5.0"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
26
|
"fs-extra": "^11.3.4"
|
|
27
27
|
},
|
|
28
|
-
"gitHead": "
|
|
28
|
+
"gitHead": "a637373a03c008ab38edaaecf6524ec4b8e332c0"
|
|
29
29
|
}
|
package/scripts/prebuild.js
CHANGED
|
@@ -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)
|
|
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.
|
|
15
|
-
"@angular/common": "~22.
|
|
16
|
-
"@angular/compiler": "~22.
|
|
17
|
-
"@angular/core": "~22.
|
|
18
|
-
"@angular/forms": "~22.
|
|
19
|
-
"@angular/platform-browser": "~22.
|
|
20
|
-
"@angular/platform-browser-dynamic": "~22.
|
|
21
|
-
"@angular/router": "~22.
|
|
22
|
-
"@tsparticles/angular": "^4.
|
|
23
|
-
"@tsparticles/confetti": "^
|
|
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.
|
|
26
|
+
"zone.js": "~0.16.3"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@angular-devkit/build-angular": "~22.
|
|
30
|
-
"@angular/cli": "~22.
|
|
31
|
-
"@angular/compiler-cli": "~22.
|
|
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,24 +11,24 @@
|
|
|
11
11
|
"watch": "ng build --watch --configuration development"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@angular/animations": "~22.
|
|
15
|
-
"@angular/common": "~22.
|
|
16
|
-
"@angular/compiler": "~22.
|
|
17
|
-
"@angular/core": "~22.
|
|
18
|
-
"@angular/forms": "~22.
|
|
19
|
-
"@angular/platform-browser": "~22.
|
|
20
|
-
"@angular/platform-browser-dynamic": "~22.
|
|
21
|
-
"@angular/router": "~22.
|
|
22
|
-
"@tsparticles/angular": "^4.
|
|
23
|
-
"@tsparticles/confetti": "^
|
|
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.
|
|
26
|
+
"zone.js": "~0.16.3"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@angular-devkit/build-angular": "~22.
|
|
30
|
-
"@angular/cli": "~22.
|
|
31
|
-
"@angular/compiler-cli": "~22.
|
|
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,24 +11,24 @@
|
|
|
11
11
|
"watch": "ng build --watch --configuration development"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@angular/animations": "~22.
|
|
15
|
-
"@angular/common": "~22.
|
|
16
|
-
"@angular/compiler": "~22.
|
|
17
|
-
"@angular/core": "~22.
|
|
18
|
-
"@angular/forms": "~22.
|
|
19
|
-
"@angular/platform-browser": "~22.
|
|
20
|
-
"@angular/platform-browser-dynamic": "~22.
|
|
21
|
-
"@angular/router": "~22.
|
|
22
|
-
"@tsparticles/angular": "^4.
|
|
23
|
-
"@tsparticles/confetti": "^
|
|
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.
|
|
26
|
+
"zone.js": "~0.16.3"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@angular-devkit/build-angular": "~22.
|
|
30
|
-
"@angular/cli": "~22.
|
|
31
|
-
"@angular/compiler-cli": "~22.
|
|
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
|
}
|
|
@@ -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
|
|
12
|
-
"@tsparticles/
|
|
31
|
+
"@tsparticles/ember": "^4.4.0",
|
|
32
|
+
"@tsparticles/engine": "^4.4.0",
|
|
33
|
+
"@tsparticles/slim": "^4.4.0"
|
|
13
34
|
},
|
|
14
|
-
"
|
|
15
|
-
"
|
|
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.
|
|
13
|
-
"inferno-
|
|
14
|
-
"
|
|
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": "^
|
|
19
|
+
"vite": "^8.3.1"
|
|
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
|
-
<
|
|
124
|
-
<Particles id="tsparticles"
|
|
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
|
-
</
|
|
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.
|
|
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": "^
|
|
18
|
+
"vite": "^8.3.1"
|
|
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 = $("#
|
|
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(
|
|
112
|
-
|
|
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,
|
|
@@ -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
|
-
"
|
|
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.
|
|
12
|
-
"@tsparticles/vue2": "^4.
|
|
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
|
}
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"preact": "^10.26.0",
|
|
13
|
-
"@tsparticles/preact": "^4.
|
|
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": "^
|
|
18
|
+
"vite": "^8.3.1"
|
|
19
19
|
}
|
|
20
20
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { useState, useCallback } from "preact/hooks";
|
|
2
|
-
import Particles, {
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
141
|
+
</>
|
|
140
142
|
);
|
|
141
143
|
}
|
|
@@ -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 {
|
|
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
|
|
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.
|
|
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.
|
|
13
|
-
"@tsparticles/riot": "^4.
|
|
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
|
-
"
|
|
18
|
-
"
|
|
21
|
+
"typescript": "^5.7.2",
|
|
22
|
+
"vite": "^8.3.1"
|
|
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="{
|
|
13
|
-
class="cell{
|
|
14
|
-
onclick="{ () => handleMove(
|
|
15
|
-
{
|
|
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;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Component, State, h } from "@stencil/core";
|
|
2
2
|
import { confetti } from "@tsparticles/confetti";
|
|
3
|
-
import
|
|
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
|
|
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,11 +9,11 @@
|
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"vue": "^2.7.16",
|
|
12
|
-
"@tsparticles/vue2": "^4.
|
|
12
|
+
"@tsparticles/vue2": "^4.4.0"
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@vitejs/plugin-vue2": "^2.3.
|
|
16
|
-
"vite": "^
|
|
15
|
+
"@vitejs/plugin-vue2": "^2.3.4",
|
|
16
|
+
"vite": "^7.3.6",
|
|
17
17
|
"vue-template-compiler": "^2.7.16"
|
|
18
18
|
}
|
|
19
19
|
}
|
|
@@ -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>
|
|
@@ -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.
|
|
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.
|
|
5
|
-
"@tsparticles/slim": "^4.
|
|
6
|
-
"@tsparticles/confetti": "^4.
|
|
4
|
+
"@tsparticles/engine": "^4.5.0",
|
|
5
|
+
"@tsparticles/slim": "^4.5.0",
|
|
6
|
+
"@tsparticles/confetti": "^4.5.0"
|
|
7
7
|
},
|
|
8
8
|
"devDependencies": {
|
|
9
9
|
"typescript": "^6.0.3",
|
|
10
|
-
"vite": "^8.1
|
|
10
|
+
"vite": "^8.3.1"
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
|
-
}
|
|
13
|
+
}
|