From 2f5d889f9e4aec7f4bd59346fdb3569467c87061 Mon Sep 17 00:00:00 2001 From: Matteo Bruni <176620+matteobruni@users.noreply.github.com> Date: Tue, 19 May 2026 08:53:32 +0200 Subject: [PATCH 01/10] fix: fixed typo in cards shape export docs: updated website and some readmes --- plugins/absorbers/README.md | 19 ++++++++++++++ plugins/emitters/README.md | 19 ++++++++++++++ shapes/cards/README.md | 22 ++++++++++++++++ shapes/cards/package.dist.json | 26 +++++++++---------- shapes/cards/package.json | 26 +++++++++---------- shapes/polygon/README.md | 15 +++++++++++ .../docs/de/guide/plugins-customization.md | 5 ++++ .../website/docs/de/migrations/from-v3.md | 22 ++++++++++++++-- .../docs/es/guide/plugins-customization.md | 5 ++++ .../website/docs/es/migrations/from-v3.md | 22 ++++++++++++++-- .../docs/fr/guide/plugins-customization.md | 5 ++++ .../website/docs/fr/migrations/from-v3.md | 22 ++++++++++++++-- .../docs/guide/plugins-customization.md | 5 ++++ .../docs/hi/guide/plugins-customization.md | 5 ++++ .../website/docs/hi/migrations/from-v3.md | 22 ++++++++++++++-- .../docs/it/guide/plugins-customization.md | 5 ++++ .../website/docs/it/migrations/from-v3.md | 22 ++++++++++++++-- .../docs/ja/guide/plugins-customization.md | 5 ++++ .../website/docs/ja/migrations/from-v3.md | 22 ++++++++++++++-- websites/website/docs/migrations/from-v3.md | 22 ++++++++++++++-- .../docs/pt/guide/plugins-customization.md | 5 ++++ .../website/docs/pt/migrations/from-v3.md | 22 ++++++++++++++-- .../docs/ru/guide/plugins-customization.md | 5 ++++ .../website/docs/ru/migrations/from-v3.md | 22 ++++++++++++++-- .../docs/zh/guide/plugins-customization.md | 5 ++++ .../website/docs/zh/migrations/from-v3.md | 22 ++++++++++++++-- 26 files changed, 351 insertions(+), 46 deletions(-) diff --git a/plugins/absorbers/README.md b/plugins/absorbers/README.md index f879b2d06da..dfdf8215692 100644 --- a/plugins/absorbers/README.md +++ b/plugins/absorbers/README.md @@ -84,6 +84,25 @@ import { loadAbsorbersPlugin } from "@tsparticles/plugin-absorbers"; })(); ``` +### Granular loading + +Instead of the full `loadAbsorbersPlugin`, you can import only the parts you need to reduce bundle size: + +- **Plugin only** (absorber lifecycle and drawing): + ```ts + import { loadAbsorbersPluginSimple } from "@tsparticles/plugin-absorbers/plugin"; + ``` +- **Interaction only** (click/hover on absorbers): + ```ts + import { loadAbsorbersInteraction } from "@tsparticles/plugin-absorbers/interaction"; + ``` + +Lazy-loaded variants are also available by appending `/lazy` to the import path: +```ts +import { loadAbsorbersPluginSimple } from "@tsparticles/plugin-absorbers/plugin/lazy"; +import { loadAbsorbersInteraction } from "@tsparticles/plugin-absorbers/interaction/lazy"; +``` + ## Option mapping - Primary options key: `absorbers` diff --git a/plugins/emitters/README.md b/plugins/emitters/README.md index 3a5a60498a3..ccfb097b57d 100644 --- a/plugins/emitters/README.md +++ b/plugins/emitters/README.md @@ -84,6 +84,25 @@ import { loadEmittersPlugin } from "@tsparticles/plugin-emitters"; })(); ``` +### Granular loading + +Instead of the full `loadEmittersPlugin`, you can import only the parts you need to reduce bundle size: + +- **Plugin only** (emitter lifecycle and drawing): + ```ts + import { loadEmittersPluginSimple } from "@tsparticles/plugin-emitters/plugin"; + ``` +- **Interaction only** (click/hover on emitters): + ```ts + import { loadEmittersInteraction } from "@tsparticles/plugin-emitters/interaction"; + ``` + +Lazy-loaded variants are also available by appending `/lazy` to the import path: +```ts +import { loadEmittersPluginSimple } from "@tsparticles/plugin-emitters/plugin/lazy"; +import { loadEmittersInteraction } from "@tsparticles/plugin-emitters/interaction/lazy"; +``` + ## Option mapping - Primary options key: `emitters` diff --git a/shapes/cards/README.md b/shapes/cards/README.md index a1c2cba6d93..cb614979c38 100644 --- a/shapes/cards/README.md +++ b/shapes/cards/README.md @@ -81,6 +81,28 @@ import { loadCardsShape } from "@tsparticles/shape-cards"; })(); ``` +### Granular loading + +This package exposes several subpath imports to load only the shapes you need: + +- **All card suits** (clubs, diamonds, hearts, spades): + ```ts + import { loadCardSuitsShape } from "@tsparticles/shape-cards/suits"; + ``` +- **Single suit** (e.g. clubs): + ```ts + import { loadClubsSuitShape } from "@tsparticles/shape-cards/clubs"; + import { loadDiamondsSuitShape } from "@tsparticles/shape-cards/diamonds"; + import { loadHeartsSuitShape } from "@tsparticles/shape-cards/hearts"; + import { loadSpadesSuitShape } from "@tsparticles/shape-cards/spades"; + ``` +- **Card images only** (full card face render): + ```ts + import { loadFullCardsShape } from "@tsparticles/shape-cards/cards"; + ``` + +All individual loader functions can also use the `/lazy` suffix for lazy imports (e.g. `@tsparticles/shape-cards/clubs/lazy`). + ## Option mapping - Primary options key: `particles.shape.type: "cards"` diff --git a/shapes/cards/package.dist.json b/shapes/cards/package.dist.json index 9206f3b15aa..6b34fd640c5 100644 --- a/shapes/cards/package.dist.json +++ b/shapes/cards/package.dist.json @@ -131,19 +131,19 @@ "require": "./cjs/clubs/index.lazy.js", "default": "./esm/clubs/index.lazy.js" }, - "./diamons": { - "types": "./types/diamons/index.d.ts", - "browser": "./browser/diamons/index.js", - "import": "./esm/diamons/index.js", - "require": "./cjs/diamons/index.js", - "default": "./esm/diamons/index.js" - }, - "./diamons/lazy": { - "types": "./types/diamons/index.lazy.d.ts", - "browser": "./browser/diamons/index.lazy.js", - "import": "./esm/diamons/index.lazy.js", - "require": "./cjs/diamons/index.lazy.js", - "default": "./esm/diamons/index.lazy.js" + "./diamonds": { + "types": "./types/diamonds/index.d.ts", + "browser": "./browser/diamonds/index.js", + "import": "./esm/diamonds/index.js", + "require": "./cjs/diamonds/index.js", + "default": "./esm/diamonds/index.js" + }, + "./diamonds/lazy": { + "types": "./types/diamonds/index.lazy.d.ts", + "browser": "./browser/diamonds/index.lazy.js", + "import": "./esm/diamonds/index.lazy.js", + "require": "./cjs/diamonds/index.lazy.js", + "default": "./esm/diamonds/index.lazy.js" }, "./hearts": { "types": "./types/hearts/index.d.ts", diff --git a/shapes/cards/package.json b/shapes/cards/package.json index e5c4d03b56b..e506cbb7bae 100644 --- a/shapes/cards/package.json +++ b/shapes/cards/package.json @@ -138,19 +138,19 @@ "require": "./dist/cjs/clubs/index.lazy.js", "default": "./dist/esm/clubs/index.lazy.js" }, - "./diamons": { - "types": "./dist/types/diamons/index.d.ts", - "browser": "./dist/browser/diamons/index.js", - "import": "./dist/esm/diamons/index.js", - "require": "./dist/cjs/diamons/index.js", - "default": "./dist/esm/diamons/index.js" - }, - "./diamons/lazy": { - "types": "./dist/types/diamons/index.lazy.d.ts", - "browser": "./dist/browser/diamons/index.lazy.js", - "import": "./dist/esm/diamons/index.lazy.js", - "require": "./dist/cjs/diamons/index.lazy.js", - "default": "./dist/esm/diamons/index.lazy.js" + "./diamonds": { + "types": "./dist/types/diamonds/index.d.ts", + "browser": "./dist/browser/diamonds/index.js", + "import": "./dist/esm/diamonds/index.js", + "require": "./dist/cjs/diamonds/index.js", + "default": "./dist/esm/diamonds/index.js" + }, + "./diamonds/lazy": { + "types": "./dist/types/diamonds/index.lazy.d.ts", + "browser": "./dist/browser/diamonds/index.lazy.js", + "import": "./dist/esm/diamonds/index.lazy.js", + "require": "./dist/cjs/diamonds/index.lazy.js", + "default": "./dist/esm/diamonds/index.lazy.js" }, "./hearts": { "types": "./dist/types/hearts/index.d.ts", diff --git a/shapes/polygon/README.md b/shapes/polygon/README.md index 6d558f0b450..33c3774a7b1 100644 --- a/shapes/polygon/README.md +++ b/shapes/polygon/README.md @@ -81,6 +81,21 @@ import { loadPolygonShape } from "@tsparticles/shape-polygon"; })(); ``` +### Granular loading + +Instead of loading all polygon shapes, you can import only the shape you need: + +- **Polygon only** (generic polygon shape): + ```ts + import { loadGenericPolygonShape } from "@tsparticles/shape-polygon"; + ``` +- **Triangle only**: + ```ts + import { loadTriangleShape } from "@tsparticles/shape-polygon"; + ``` + +Both functions are available from the same entry point. Lazy-loaded variants use `@tsparticles/shape-polygon/lazy`. + ## Option mapping - Primary options key: `particles.shape.type: "polygon"` diff --git a/websites/website/docs/de/guide/plugins-customization.md b/websites/website/docs/de/guide/plugins-customization.md index 189131745e4..53d38fa5b3e 100644 --- a/websites/website/docs/de/guide/plugins-customization.md +++ b/websites/website/docs/de/guide/plugins-customization.md @@ -353,6 +353,11 @@ export async function loadAppShape(engine: Engine): Promise { await loadAppShape(tsParticles); +/* Für granulare Ladefunktionen können nur die benötigten Formen importiert werden: + * - @tsparticles/shape-cards/clubs, /diamonds, /hearts, /spades, /suits, /cards + * - @tsparticles/shape-polygon: loadGenericPolygonShape oder loadTriangleShape + */ + const options = { particles: { paint: { diff --git a/websites/website/docs/de/migrations/from-v3.md b/websites/website/docs/de/migrations/from-v3.md index c33410477f1..386f38c16bb 100644 --- a/websites/website/docs/de/migrations/from-v3.md +++ b/websites/website/docs/de/migrations/from-v3.md @@ -18,6 +18,7 @@ Einige `v3.x`-Pakete wurden umbenannt oder umstrukturiert: | `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Durch Paint-System ersetzt | | `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Durch Paint-System ersetzt | | `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Nach `plugins/colors/hsv/` verschoben, gleicher Name | +| (in v3 nicht benötigt - integriert) | `@tsparticles/plugin-interactivity` | Erforderlich für alle Interaktions-Plugins (grab, bubble, repulse, etc.) | ## Beispiele fuer Optionszuordnung @@ -77,8 +78,25 @@ await tsParticles.load({ 1. Alle `@tsparticles/*`-Pakete auf die neueste Version bringen. 2. Veraltete Optionsschluessel (`particles.color`, `particles.stroke`) durch `particles.paint.*` ersetzen. 3. Umbenannte Pakete in `package.json` aktualisieren (siehe Tabelle oben). -4. Pruefen, dass benutzerdefinierte Plugins/Formen vor `tsParticles.load(...)` geladen werden. -5. Interaktionen und leistungskritische Szenarien erneut testen. +4. Wenn Sie Interaktions-Plugins verwenden (grab, bubble, repulse, etc.), installieren Sie `@tsparticles/plugin-interactivity` und laden Sie es mit `await loadInteractivityPlugin(tsParticles)` vor jedem Interaktions-Plugin. +5. Pruefen, dass benutzerdefinierte Plugins/Formen vor `tsParticles.load(...)` geladen werden. +6. Interaktionen und leistungskritische Szenarien erneut testen. + +## Granulare Ladefunktionen + +Einige Pakete bieten einzelne Ladefunktionen, um nur das zu laden, was benötigt wird, und so die Bundle-Größe zu reduzieren. + +### Plugins + +- **`@tsparticles/plugin-absorbers`**: `loadAbsorbersPluginSimple` (nur Absorber-Lebenszyklus und Zeichnung), `loadAbsorbersInteraction` (nur Klick/Hover-Interaktion) oder `loadAbsorbersPlugin` (beides). +- **`@tsparticles/plugin-emitters`**: `loadEmittersPluginSimple` (nur Emitter-Lebenszyklus und Zeichnung), `loadEmittersInteraction` (nur Klick/Hover-Interaktion) oder `loadEmittersPlugin` (beides). + +### Formen + +- **`@tsparticles/shape-polygon`**: `loadGenericPolygonShape` (Polygon) oder `loadTriangleShape` (Dreieck) einzeln, oder `loadPolygonShape` für beide. +- **`@tsparticles/shape-cards`**: `loadClubsSuitShape`, `loadDiamondsSuitShape`, `loadHeartsSuitShape`, `loadSpadesSuitShape` (einzelne Farben), `loadCardSuitsShape` (alle Farben), `loadFullCardsShape` (Kartenbilder) oder `loadCardsShape` (alle). + +Alle anderen Formpakete (arrow, circle, cog, emoji, heart, image, infinity, line, matrix, path, rounded-polygon, rounded-rect, spiral, square, squircle, star, text) exportieren direkt eine einzelne `load*Shape`-Funktion. ## Ressourcen diff --git a/websites/website/docs/es/guide/plugins-customization.md b/websites/website/docs/es/guide/plugins-customization.md index 3850f9f5d29..eadf785ab37 100644 --- a/websites/website/docs/es/guide/plugins-customization.md +++ b/websites/website/docs/es/guide/plugins-customization.md @@ -353,6 +353,11 @@ export async function loadAppShape(engine: Engine): Promise { await loadAppShape(tsParticles); +/* Para carga granular, puedes importar solo las formas que necesitas: + * - @tsparticles/shape-cards/clubs, /diamonds, /hearts, /spades, /suits, /cards + * - @tsparticles/shape-polygon: loadGenericPolygonShape o loadTriangleShape + */ + const options = { particles: { paint: { diff --git a/websites/website/docs/es/migrations/from-v3.md b/websites/website/docs/es/migrations/from-v3.md index a0df101c3d4..942c27b8aec 100644 --- a/websites/website/docs/es/migrations/from-v3.md +++ b/websites/website/docs/es/migrations/from-v3.md @@ -18,6 +18,7 @@ Algunos paquetes de `v3.x` han sido renombrados o reestructurados: | `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Reemplazado por el sistema paint | | `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Reemplazado por el sistema paint | | `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Movido a `plugins/colors/hsv/`, mismo nombre | +| (no necesario en v3 - integrado) | `@tsparticles/plugin-interactivity` | Necesario para que funcionen todos los plugins de interaccion (grab, bubble, repulse, etc.) | ## Ejemplos de mapeo de opciones @@ -77,8 +78,25 @@ await tsParticles.load({ 1. Alinea todos los paquetes `@tsparticles/*` a la ultima version disponible. 2. Reemplaza las claves de opciones obsoletas (`particles.color`, `particles.stroke`) con `particles.paint.*`. 3. Actualiza los paquetes renombrados en `package.json` (ver tabla arriba). -4. Verifica que los plugins/formas personalizados se carguen antes de `tsParticles.load(...)`. -5. Vuelve a probar interacciones y escenas criticas de rendimiento. +4. Si usas plugins de interaccion (grab, bubble, repulse, etc.), instala `@tsparticles/plugin-interactivity` y cargalo con `await loadInteractivityPlugin(tsParticles)` antes de cargar cualquier plugin de interaccion. +5. Verifica que los plugins/formas personalizados se carguen antes de `tsParticles.load(...)`. +6. Vuelve a probar interacciones y escenas criticas de rendimiento. + +## Funciones de carga granulare + +Algunos paquetes exponen funciones de carga individuales para cargar solo lo que necesitas, reduciendo el tamano del bundle. + +### Plugins + +- **`@tsparticles/plugin-absorbers`**: `loadAbsorbersPluginSimple` (solo ciclo de vida y dibujo de absorbers), `loadAbsorbersInteraction` (solo interaccion click/hover) o `loadAbsorbersPlugin` (ambos). +- **`@tsparticles/plugin-emitters`**: `loadEmittersPluginSimple` (solo ciclo de vida y dibujo de emisores), `loadEmittersInteraction` (solo interaccion click/hover) o `loadEmittersPlugin` (ambos). + +### Formas + +- **`@tsparticles/shape-polygon`**: `loadGenericPolygonShape` (poligono) o `loadTriangleShape` (triangulo) individualmente, o `loadPolygonShape` para ambos. +- **`@tsparticles/shape-cards`**: `loadClubsSuitShape`, `loadDiamondsSuitShape`, `loadHeartsSuitShape`, `loadSpadesSuitShape` (palos individuales), `loadCardSuitsShape` (todos los palos), `loadFullCardsShape` (imagenes de cartas) o `loadCardsShape` (todos). + +Todos los demas paquetes de formas (arrow, circle, cog, emoji, heart, image, infinity, line, matrix, path, rounded-polygon, rounded-rect, spiral, square, squircle, star, text) exportan directamente una unica funcion `load*Shape`. ## Recursos diff --git a/websites/website/docs/fr/guide/plugins-customization.md b/websites/website/docs/fr/guide/plugins-customization.md index 313718bbb4c..2ef7b018005 100644 --- a/websites/website/docs/fr/guide/plugins-customization.md +++ b/websites/website/docs/fr/guide/plugins-customization.md @@ -353,6 +353,11 @@ export async function loadAppShape(engine: Engine): Promise { await loadAppShape(tsParticles); +/* Pour un chargement granulaire, importez uniquement les formes nécessaires : + * - @tsparticles/shape-cards/clubs, /diamonds, /hearts, /spades, /suits, /cards + * - @tsparticles/shape-polygon : loadGenericPolygonShape ou loadTriangleShape + */ + const options = { particles: { paint: { diff --git a/websites/website/docs/fr/migrations/from-v3.md b/websites/website/docs/fr/migrations/from-v3.md index b2214772988..ff2067a707b 100644 --- a/websites/website/docs/fr/migrations/from-v3.md +++ b/websites/website/docs/fr/migrations/from-v3.md @@ -18,6 +18,7 @@ Certains paquets `v3.x` ont été renommés ou restructurés : | `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Remplacé par le système paint | | `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Remplacé par le système paint | | `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Déplacé dans `plugins/colors/hsv/`, même nom | +| (non nécessaire en v3 - intégré) | `@tsparticles/plugin-interactivity` | Requis pour que tous les plugins d'interaction (grab, bubble, repulse, etc.) fonctionnent | ## Exemples de correspondance des options @@ -77,8 +78,25 @@ await tsParticles.load({ 1. Alignez tous les paquets `@tsparticles/*` sur la dernière version disponible. 2. Remplacez les clés d'options obsolètes (`particles.color`, `particles.stroke`) par `particles.paint.*`. 3. Mettez à jour les paquets renommés dans `package.json` (voir tableau ci-dessus). -4. Vérifiez que les plugins/formes personnalisés sont chargés avant `tsParticles.load(...)`. -5. Retestez les interactions et les scènes critiques pour les performances. +4. Si vous utilisez des plugins d'interaction (grab, bubble, repulse, etc.), installez `@tsparticles/plugin-interactivity` et chargez-le avec `await loadInteractivityPlugin(tsParticles)` avant de charger tout plugin d'interaction. +5. Vérifiez que les plugins/formes personnalisés sont chargés avant `tsParticles.load(...)`. +6. Retestez les interactions et les scènes critiques pour les performances. + +## Fonctions de chargement granulaires + +Certains paquets exposent des fonctions de chargement individuelles pour charger uniquement ce dont vous avez besoin, réduisant ainsi la taille du bundle. + +### Plugins + +- **`@tsparticles/plugin-absorbers`** : `loadAbsorbersPluginSimple` (cycle de vie et dessin des absorbeurs uniquement), `loadAbsorbersInteraction` (interaction clic/souris uniquement) ou `loadAbsorbersPlugin` (les deux). +- **`@tsparticles/plugin-emitters`** : `loadEmittersPluginSimple` (cycle de vie et dessin des émetteurs uniquement), `loadEmittersInteraction` (interaction clic/souris uniquement) ou `loadEmittersPlugin` (les deux). + +### Formes + +- **`@tsparticles/shape-polygon`** : `loadGenericPolygonShape` (polygone) ou `loadTriangleShape` (triangle) individuellement, ou `loadPolygonShape` pour les deux. +- **`@tsparticles/shape-cards`** : `loadClubsSuitShape`, `loadDiamondsSuitShape`, `loadHeartsSuitShape`, `loadSpadesSuitShape` (couleurs individuelles), `loadCardSuitsShape` (toutes les couleurs), `loadFullCardsShape` (images de cartes) ou `loadCardsShape` (tout). + +Tous les autres paquets de formes (arrow, circle, cog, emoji, heart, image, infinity, line, matrix, path, rounded-polygon, rounded-rect, spiral, square, squircle, star, text) exportent directement une seule fonction `load*Shape`. ## Ressources diff --git a/websites/website/docs/guide/plugins-customization.md b/websites/website/docs/guide/plugins-customization.md index b4af17c2864..b937c752280 100644 --- a/websites/website/docs/guide/plugins-customization.md +++ b/websites/website/docs/guide/plugins-customization.md @@ -353,6 +353,11 @@ export async function loadAppShape(engine: Engine): Promise { await loadAppShape(tsParticles); +/* For granular loading, you can import only the shapes you need: + * - @tsparticles/shape-cards/clubs, /diamonds, /hearts, /spades, /suits, /cards + * - @tsparticles/shape-polygon: loadGenericPolygonShape or loadTriangleShape + */ + const options = { particles: { paint: { diff --git a/websites/website/docs/hi/guide/plugins-customization.md b/websites/website/docs/hi/guide/plugins-customization.md index 7a8f01c2f0d..0eabf9c7fb5 100644 --- a/websites/website/docs/hi/guide/plugins-customization.md +++ b/websites/website/docs/hi/guide/plugins-customization.md @@ -353,6 +353,11 @@ export async function loadAppShape(engine: Engine): Promise { await loadAppShape(tsParticles); +/* ग्रैन्युलर लोडिंग के लिए, आप केवल आवश्यक आकार आयात कर सकते हैं: + * - @tsparticles/shape-cards/clubs, /diamonds, /hearts, /spades, /suits, /cards + * - @tsparticles/shape-polygon: loadGenericPolygonShape या loadTriangleShape + */ + const options = { particles: { paint: { diff --git a/websites/website/docs/hi/migrations/from-v3.md b/websites/website/docs/hi/migrations/from-v3.md index ef0d0da870d..7a565ef27d1 100644 --- a/websites/website/docs/hi/migrations/from-v3.md +++ b/websites/website/docs/hi/migrations/from-v3.md @@ -18,6 +18,7 @@ | `@tsparticles/updater-color` | `@tsparticles/updater-paint` | paint सिस्टम से बदला गया | | `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | paint सिस्टम से बदला गया | | `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | `plugins/colors/hsv/` में स्थानांतरित, same name | +| (v3 में आवश्यक नहीं - अंतर्निर्मित) | `@tsparticles/plugin-interactivity` | सभी इंटरैक्शन प्लगइन (grab, bubble, repulse, आदि) के काम करने के लिए आवश्यक | ## ऑप्शन मैपिंग उदाहरण @@ -77,8 +78,25 @@ await tsParticles.load({ 1. सभी `@tsparticles/*` पैकेजों को नवीनतम संस्करण पर लाएं। 2. deprecated option keys (`particles.color`, `particles.stroke`) को `particles.paint.*` से बदलें। 3. नाम बदले गए पैकेजों को `package.json` में अपडेट करें (ऊपर तालिका देखें)। -4. सुनिश्चित करें कि custom plugins/shapes `tsParticles.load(...)` से पहले लोड हों। -5. इंटरैक्शन और performance-sensitive scenes को दोबारा जांचें। +4. यदि आप इंटरैक्शन प्लगइन (grab, bubble, repulse, आदि) का उपयोग करते हैं, तो `@tsparticles/plugin-interactivity` इंस्टॉल करें और किसी भी इंटरैक्शन प्लगइन को लोड करने से पहले इसे `await loadInteractivityPlugin(tsParticles)` से लोड करें। +5. सुनिश्चित करें कि custom plugins/shapes `tsParticles.load(...)` से पहले लोड हों। +6. इंटरैक्शन और performance-sensitive scenes को दोबारा जांचें। + +## ग्रैन्युलर लोडर फ़ंक्शन + +कुछ पैकेज केवल आवश्यक भागों को लोड करने के लिए अलग-अलग लोडर फ़ंक्शन प्रदान करते हैं, जिससे बंडल का आकार कम होता है। + +### प्लगइन + +- **`@tsparticles/plugin-absorbers`**: `loadAbsorbersPluginSimple` (केवल अब्ज़ॉर्बर जीवनचक्र और ड्राइंग), `loadAbsorbersInteraction` (केवल क्लिक/होवर इंटरैक्शन), या `loadAbsorbersPlugin` (दोनों)। +- **`@tsparticles/plugin-emitters`**: `loadEmittersPluginSimple` (केवल एमिटर जीवनचक्र और ड्राइंग), `loadEmittersInteraction` (केवल क्लिक/होवर इंटरैक्शन), या `loadEmittersPlugin` (दोनों)। + +### आकार + +- **`@tsparticles/shape-polygon`**: `loadGenericPolygonShape` (बहुभुज) या `loadTriangleShape` (त्रिकोण) अलग-अलग, या `loadPolygonShape` दोनों के लिए। +- **`@tsparticles/shape-cards`**: `loadClubsSuitShape`, `loadDiamondsSuitShape`, `loadHeartsSuitShape`, `loadSpadesSuitShape` (अलग-अलग सूट), `loadCardSuitsShape` (सभी सूट), `loadFullCardsShape` (कार्ड छवियाँ), या `loadCardsShape` (सभी)। + +अन्य सभी आकार पैकेज (arrow, circle, cog, emoji, heart, image, infinity, line, matrix, path, rounded-polygon, rounded-rect, spiral, square, squircle, star, text) सीधे एकल `load*Shape` फ़ंक्शन निर्यात करते हैं। ## Resources diff --git a/websites/website/docs/it/guide/plugins-customization.md b/websites/website/docs/it/guide/plugins-customization.md index 77034c9f8be..5ffd28418c0 100644 --- a/websites/website/docs/it/guide/plugins-customization.md +++ b/websites/website/docs/it/guide/plugins-customization.md @@ -353,6 +353,11 @@ export async function loadAppShape(engine: Engine): Promise { await loadAppShape(tsParticles); +/* Per un caricamento granulare puoi importare solo le forme che servono: + * - @tsparticles/shape-cards/clubs, /diamonds, /hearts, /spades, /suits, /cards + * - @tsparticles/shape-polygon: loadGenericPolygonShape o loadTriangleShape + */ + const options = { particles: { paint: { diff --git a/websites/website/docs/it/migrations/from-v3.md b/websites/website/docs/it/migrations/from-v3.md index dfefa5fb8cf..532779127af 100644 --- a/websites/website/docs/it/migrations/from-v3.md +++ b/websites/website/docs/it/migrations/from-v3.md @@ -18,6 +18,7 @@ Alcuni pacchetti di `v3.x` sono stati rinominati o ristrutturati: | `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Sostituito dal sistema paint | | `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Sostituito dal sistema paint | | `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Spostato in `plugins/colors/hsv/`, stesso nome | +| (non necessario in v3 - integrato) | `@tsparticles/plugin-interactivity` | Necessario per far funzionare qualsiasi plugin di interazione (grab, bubble, repulse, ecc.) | ## Esempi mappatura opzioni @@ -77,8 +78,25 @@ await tsParticles.load({ 1. Allinea tutti i pacchetti `@tsparticles/*` all'ultima versione disponibile. 2. Sostituisci le chiavi opzione deprecate (`particles.color`, `particles.stroke`) con `particles.paint.*`. 3. Aggiorna i pacchetti rinominati in `package.json` (vedi tabella sopra). -4. Verifica che plugin/shape personalizzati siano caricati prima di `tsParticles.load(...)`. -5. Ricontrolla interazioni e scene critiche per le performance. +4. Se usi plugin di interazione (grab, bubble, repulse, ecc.), installa `@tsparticles/plugin-interactivity` e caricalo con `await loadInteractivityPlugin(tsParticles)` prima di caricare qualsiasi plugin di interazione. +5. Verifica che plugin/shape personalizzati siano caricati prima di `tsParticles.load(...)`. +6. Ricontrolla interazioni e scene critiche per le performance. + +## Funzioni di caricamento granulari + +Alcuni pacchetti espongono funzioni di caricamento individuali per caricare solo ciò che serve, riducendo le dimensioni del bundle. + +### Plugin + +- **`@tsparticles/plugin-absorbers`**: `loadAbsorbersPluginSimple` (solo ciclo di vita e disegno degli absorber), `loadAbsorbersInteraction` (solo interazione click/hover), o `loadAbsorbersPlugin` (entrambi). +- **`@tsparticles/plugin-emitters`**: `loadEmittersPluginSimple` (solo ciclo di vita e disegno degli emettitori), `loadEmittersInteraction` (solo interazione click/hover), o `loadEmittersPlugin` (entrambi). + +### Forme + +- **`@tsparticles/shape-polygon`**: `loadGenericPolygonShape` (poligono) o `loadTriangleShape` (triangolo) singolarmente, o `loadPolygonShape` per entrambi. +- **`@tsparticles/shape-cards`**: `loadClubsSuitShape`, `loadDiamondsSuitShape`, `loadHeartsSuitShape`, `loadSpadesSuitShape` (semi individuali), `loadCardSuitsShape` (tutti i semi), `loadFullCardsShape` (immagini carte), o `loadCardsShape` (tutti). + +Tutti gli altri pacchetti di forme (arrow, circle, cog, emoji, heart, image, infinity, line, matrix, path, rounded-polygon, rounded-rect, spiral, square, squircle, star, text) esportano direttamente una singola funzione `load*Shape`. ## Risorse diff --git a/websites/website/docs/ja/guide/plugins-customization.md b/websites/website/docs/ja/guide/plugins-customization.md index 1a6ca52a7d2..b11b0a3e793 100644 --- a/websites/website/docs/ja/guide/plugins-customization.md +++ b/websites/website/docs/ja/guide/plugins-customization.md @@ -353,6 +353,11 @@ export async function loadAppShape(engine: Engine): Promise { await loadAppShape(tsParticles); +/* 細粒度ローディングのため、必要なシェイプのみをインポートできます: + * - @tsparticles/shape-cards/clubs, /diamonds, /hearts, /spades, /suits, /cards + * - @tsparticles/shape-polygon: loadGenericPolygonShape または loadTriangleShape + */ + const options = { particles: { paint: { diff --git a/websites/website/docs/ja/migrations/from-v3.md b/websites/website/docs/ja/migrations/from-v3.md index 4394e2a5346..8e225c465b5 100644 --- a/websites/website/docs/ja/migrations/from-v3.md +++ b/websites/website/docs/ja/migrations/from-v3.md @@ -18,6 +18,7 @@ | `@tsparticles/updater-color` | `@tsparticles/updater-paint` | paint システムに置き換え | | `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | paint システムに置き換え | | `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | `plugins/colors/hsv/` に移動、名前は同じ | +| (v3では不要 - 組み込み) | `@tsparticles/plugin-interactivity` | すべてのインタラクションプラグイン(grab, bubble, repulseなど)の動作に必要 | ## オプション対応例 @@ -77,8 +78,25 @@ await tsParticles.load({ 1. すべての `@tsparticles/*` パッケージを最新バージョンに揃える。 2. 非推奨のオプションキー(`particles.color`、`particles.stroke`)を `particles.paint.*` に置き換える。 3. 名称変更されたパッケージを `package.json` で更新する(上の表を参照)。 -4. カスタムプラグイン/シェイプが `tsParticles.load(...)` の前に読み込まれていることを確認する。 -5. インタラクションとパフォーマンス重視のシーンを再テストする。 +4. インタラクションプラグイン(grab, bubble, repulseなど)を使用する場合は、`@tsparticles/plugin-interactivity` をインストールし、インタラクションプラグインを読み込む前に `await loadInteractivityPlugin(tsParticles)` で読み込んでください。 +5. カスタムプラグイン/シェイプが `tsParticles.load(...)` の前に読み込まれていることを確認する。 +6. インタラクションとパフォーマンス重視のシーンを再テストする。 + +## 細粒度ローダー関数 + +一部のパッケージは、必要なものだけをロードしてバンドルサイズを削減するための個別のローダー関数を提供しています。 + +### プラグイン + +- **`@tsparticles/plugin-absorbers`**: `loadAbsorbersPluginSimple`(アブソーバーのライフサイクルと描画のみ)、`loadAbsorbersInteraction`(クリック/ホバーインタラクションのみ)、または `loadAbsorbersPlugin`(両方)。 +- **`@tsparticles/plugin-emitters`**: `loadEmittersPluginSimple`(エミッターのライフサイクルと描画のみ)、`loadEmittersInteraction`(クリック/ホバーインタラクションのみ)、または `loadEmittersPlugin`(両方)。 + +### シェイプ + +- **`@tsparticles/shape-polygon`**: `loadGenericPolygonShape`(ポリゴン)または `loadTriangleShape`(三角形)を個別に、または `loadPolygonShape` で両方。 +- **`@tsparticles/shape-cards`**: `loadClubsSuitShape`、`loadDiamondsSuitShape`、`loadHeartsSuitShape`、`loadSpadesSuitShape`(個別のスート)、`loadCardSuitsShape`(すべてのスート)、`loadFullCardsShape`(カード画像)、または `loadCardsShape`(すべて)。 + +他のすべてのシェイプパッケージ(arrow, circle, cog, emoji, heart, image, infinity, line, matrix, path, rounded-polygon, rounded-rect, spiral, square, squircle, star, text)は、単一の `load*Shape` 関数を直接エクスポートします。 ## リソース diff --git a/websites/website/docs/migrations/from-v3.md b/websites/website/docs/migrations/from-v3.md index a0fa8950b48..1dfa2ff0baa 100644 --- a/websites/website/docs/migrations/from-v3.md +++ b/websites/website/docs/migrations/from-v3.md @@ -85,14 +85,32 @@ Some `v3.x` packages have been renamed or restructured: | `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Replaced by paint system | | `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Replaced by paint system | | `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Moved to `plugins/colors/hsv/`, still the same package name | +| (not needed in v3 - built-in) | `@tsparticles/plugin-interactivity` | Required for all interaction plugins (grab, bubble, repulse, etc.) to work | ## Recommended steps 1. Align all `@tsparticles/*` packages to the same latest version line. 2. Replace deprecated option keys (`particles.color`, `particles.stroke`) with `particles.paint.*`. 3. Update renamed packages in `package.json` (see table above). -4. Verify custom plugins/shapes are loaded before `tsParticles.load(...)`. -5. Re-test interactions and performance-sensitive scenes. +4. If you use interaction plugins (grab, bubble, repulse, etc.), install `@tsparticles/plugin-interactivity` and load it with `await loadInteractivityPlugin(tsParticles)` before loading any interaction plugin. +5. Verify custom plugins/shapes are loaded before `tsParticles.load(...)`. +6. Re-test interactions and performance-sensitive scenes. + +## Granular loader functions + +Some packages expose individual loader functions to load only what you need, reducing bundle size. + +### Plugins + +- **`@tsparticles/plugin-absorbers`**: `loadAbsorbersPluginSimple` (absorber lifecycle and drawing only), `loadAbsorbersInteraction` (click/hover interaction only), or `loadAbsorbersPlugin` (both). +- **`@tsparticles/plugin-emitters`**: `loadEmittersPluginSimple` (emitter lifecycle and drawing only), `loadEmittersInteraction` (click/hover interaction only), or `loadEmittersPlugin` (both). + +### Shapes + +- **`@tsparticles/shape-polygon`**: `loadGenericPolygonShape` (polygon) or `loadTriangleShape` (triangle) individually, or `loadPolygonShape` for both. +- **`@tsparticles/shape-cards`**: `loadClubsSuitShape`, `loadDiamondsSuitShape`, `loadHeartsSuitShape`, `loadSpadesSuitShape` (individual suits), `loadCardSuitsShape` (all suits), `loadFullCardsShape` (card images), or `loadCardsShape` (all). + +All other shape packages (arrow, circle, cog, emoji, heart, image, infinity, line, matrix, path, rounded-polygon, rounded-rect, spiral, square, squircle, star, text) export a single `load*Shape` function directly. ## Checklist diff --git a/websites/website/docs/pt/guide/plugins-customization.md b/websites/website/docs/pt/guide/plugins-customization.md index c616ee2b611..c9547d7bbd5 100644 --- a/websites/website/docs/pt/guide/plugins-customization.md +++ b/websites/website/docs/pt/guide/plugins-customization.md @@ -353,6 +353,11 @@ export async function loadAppShape(engine: Engine): Promise { await loadAppShape(tsParticles); +/* Para carregamento granular, voce pode importar apenas as formas necessarias: + * - @tsparticles/shape-cards/clubs, /diamonds, /hearts, /spades, /suits, /cards + * - @tsparticles/shape-polygon: loadGenericPolygonShape ou loadTriangleShape + */ + const options = { particles: { paint: { diff --git a/websites/website/docs/pt/migrations/from-v3.md b/websites/website/docs/pt/migrations/from-v3.md index ba53f35c86d..b773925c14b 100644 --- a/websites/website/docs/pt/migrations/from-v3.md +++ b/websites/website/docs/pt/migrations/from-v3.md @@ -18,6 +18,7 @@ Alguns pacotes `v3.x` foram renomeados ou reestruturados: | `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Substituido pelo sistema paint | | `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Substituido pelo sistema paint | | `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Movido para `plugins/colors/hsv/`, mesmo nome | +| (nao necessario no v3 - integrado) | `@tsparticles/plugin-interactivity` | Necessario para todos os plugins de interacao (grab, bubble, repulse, etc.) funcionarem | ## Exemplos de mapeamento de opcoes @@ -77,8 +78,25 @@ await tsParticles.load({ 1. Alinhe todos os pacotes `@tsparticles/*` para a versao mais recente. 2. Substitua as chaves de opcao obsoletas (`particles.color`, `particles.stroke`) por `particles.paint.*`. 3. Atualize os pacotes renomeados em `package.json` (ver tabela acima). -4. Verifique se plugins/formas personalizados sao carregados antes de `tsParticles.load(...)`. -5. Reteste interacoes e cenas criticas de desempenho. +4. Se voce usa plugins de interacao (grab, bubble, repulse, etc.), instale `@tsparticles/plugin-interactivity` e carregue-o com `await loadInteractivityPlugin(tsParticles)` antes de carregar qualquer plugin de interacao. +5. Verifique se plugins/formas personalizados sao carregados antes de `tsParticles.load(...)`. +6. Reteste interacoes e cenas criticas de desempenho. + +## Funcoes de carregamento granulares + +Alguns pacotes expoem funcoes de carregamento individuais para carregar apenas o necessario, reduzindo o tamanho do bundle. + +### Plugins + +- **`@tsparticles/plugin-absorbers`**: `loadAbsorbersPluginSimple` (apenas ciclo de vida e desenho dos absorvedores), `loadAbsorbersInteraction` (apenas interacao clique/hover) ou `loadAbsorbersPlugin` (ambos). +- **`@tsparticles/plugin-emitters`**: `loadEmittersPluginSimple` (apenas ciclo de vida e desenho dos emissores), `loadEmittersInteraction` (apenas interacao clique/hover) ou `loadEmittersPlugin` (ambos). + +### Formas + +- **`@tsparticles/shape-polygon`**: `loadGenericPolygonShape` (poligono) ou `loadTriangleShape` (triangulo) individualmente, ou `loadPolygonShape` para ambos. +- **`@tsparticles/shape-cards`**: `loadClubsSuitShape`, `loadDiamondsSuitShape`, `loadHeartsSuitShape`, `loadSpadesSuitShape` (naipes individuais), `loadCardSuitsShape` (todos os naipes), `loadFullCardsShape` (imagens de cartas) ou `loadCardsShape` (todos). + +Todos os outros pacotes de formas (arrow, circle, cog, emoji, heart, image, infinity, line, matrix, path, rounded-polygon, rounded-rect, spiral, square, squircle, star, text) exportam diretamente uma unica funcao `load*Shape`. ## Recursos diff --git a/websites/website/docs/ru/guide/plugins-customization.md b/websites/website/docs/ru/guide/plugins-customization.md index 549cf562a4c..5e160a24396 100644 --- a/websites/website/docs/ru/guide/plugins-customization.md +++ b/websites/website/docs/ru/guide/plugins-customization.md @@ -353,6 +353,11 @@ export async function loadAppShape(engine: Engine): Promise { await loadAppShape(tsParticles); +/* Для детализированной загрузки можно импортировать только нужные фигуры: + * - @tsparticles/shape-cards/clubs, /diamonds, /hearts, /spades, /suits, /cards + * - @tsparticles/shape-polygon: loadGenericPolygonShape или loadTriangleShape + */ + const options = { particles: { paint: { diff --git a/websites/website/docs/ru/migrations/from-v3.md b/websites/website/docs/ru/migrations/from-v3.md index ad00b9d86ab..f11fd9e7e8d 100644 --- a/websites/website/docs/ru/migrations/from-v3.md +++ b/websites/website/docs/ru/migrations/from-v3.md @@ -18,6 +18,7 @@ | `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Заменён системой paint | | `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Заменён системой paint | | `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Перемещён в `plugins/colors/hsv/`, то же имя | +| (не нужно в v3 - встроено) | `@tsparticles/plugin-interactivity` | Требуется для работы всех плагинов взаимодействия (grab, bubble, repulse и т.д.) | ## Примеры соответствия опций @@ -77,8 +78,25 @@ await tsParticles.load({ 1. Приведите все пакеты `@tsparticles/*` к последней версии. 2. Замените устаревшие ключи опций (`particles.color`, `particles.stroke`) на `particles.paint.*`. 3. Обновите переименованные пакеты в `package.json` (см. таблицу выше). -4. Убедитесь, что пользовательские плагины/фигуры загружаются до `tsParticles.load(...)`. -5. Повторно протестируйте взаимодействия и сцены, критичные для производительности. +4. Если вы используете плагины взаимодействия (grab, bubble, repulse и т.д.), установите `@tsparticles/plugin-interactivity` и загрузите его с помощью `await loadInteractivityPlugin(tsParticles)` перед загрузкой любого плагина взаимодействия. +5. Убедитесь, что пользовательские плагины/фигуры загружаются до `tsParticles.load(...)`. +6. Повторно протестируйте взаимодействия и сцены, критичные для производительности. + +## Детализированные функции загрузки + +Некоторые пакеты предоставляют отдельные функции загрузки, чтобы загружать только то, что нужно, уменьшая размер бандла. + +### Плагины + +- **`@tsparticles/plugin-absorbers`**: `loadAbsorbersPluginSimple` (только жизненный цикл и отрисовка абсорберов), `loadAbsorbersInteraction` (только взаимодействие клик/наведение) или `loadAbsorbersPlugin` (оба). +- **`@tsparticles/plugin-emitters`**: `loadEmittersPluginSimple` (только жизненный цикл и отрисовка эмиттеров), `loadEmittersInteraction` (только взаимодействие клик/наведение) или `loadEmittersPlugin` (оба). + +### Фигуры + +- **`@tsparticles/shape-polygon`**: `loadGenericPolygonShape` (многоугольник) или `loadTriangleShape` (треугольник) по отдельности, или `loadPolygonShape` для обоих. +- **`@tsparticles/shape-cards`**: `loadClubsSuitShape`, `loadDiamondsSuitShape`, `loadHeartsSuitShape`, `loadSpadesSuitShape` (отдельные масти), `loadCardSuitsShape` (все масти), `loadFullCardsShape` (изображения карт) или `loadCardsShape` (все). + +Все остальные пакеты фигур (arrow, circle, cog, emoji, heart, image, infinity, line, matrix, path, rounded-polygon, rounded-rect, spiral, square, squircle, star, text) экспортируют одну функцию `load*Shape` напрямую. ## Ресурсы diff --git a/websites/website/docs/zh/guide/plugins-customization.md b/websites/website/docs/zh/guide/plugins-customization.md index 23413673536..fe49ad10781 100644 --- a/websites/website/docs/zh/guide/plugins-customization.md +++ b/websites/website/docs/zh/guide/plugins-customization.md @@ -353,6 +353,11 @@ export async function loadAppShape(engine: Engine): Promise { await loadAppShape(tsParticles); +/* 对于粒度加载,你可以只导入所需的形状: + * - @tsparticles/shape-cards/clubs, /diamonds, /hearts, /spades, /suits, /cards + * - @tsparticles/shape-polygon: loadGenericPolygonShape 或 loadTriangleShape + */ + const options = { particles: { paint: { diff --git a/websites/website/docs/zh/migrations/from-v3.md b/websites/website/docs/zh/migrations/from-v3.md index 5d1a23049dd..01149903f25 100644 --- a/websites/website/docs/zh/migrations/from-v3.md +++ b/websites/website/docs/zh/migrations/from-v3.md @@ -18,6 +18,7 @@ | `@tsparticles/updater-color` | `@tsparticles/updater-paint` | 被 paint 系统取代 | | `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | 被 paint 系统取代 | | `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | 移动到 `plugins/colors/hsv/`,名称不变 | +| (v3 中不需要 - 内置) | `@tsparticles/plugin-interactivity` | 所有交互插件(grab, bubble, repulse 等)正常工作所必需 | ## 选项映射示例 @@ -77,8 +78,25 @@ await tsParticles.load({ 1. 将所有 `@tsparticles/*` 包对齐到最新版本。 2. 将弃用的选项键(`particles.color`、`particles.stroke`)替换为 `particles.paint.*`。 3. 在 `package.json` 中更新重命名的包(见上表)。 -4. 确保自定义插件/形状在 `tsParticles.load(...)` 之前加载。 -5. 重新测试交互和性能敏感场景。 +4. 如果你使用交互插件(grab, bubble, repulse 等),请安装 `@tsparticles/plugin-interactivity` 并在加载任何交互插件之前使用 `await loadInteractivityPlugin(tsParticles)` 加载它。 +5. 确保自定义插件/形状在 `tsParticles.load(...)` 之前加载。 +6. 重新测试交互和性能敏感场景。 + +## 粒度加载函数 + +一些包提供单独的加载函数,以便只加载所需的部分,从而减小打包体积。 + +### 插件 + +- **`@tsparticles/plugin-absorbers`**:`loadAbsorbersPluginSimple`(仅吸收器的生命周期和绘制)、`loadAbsorbersInteraction`(仅点击/悬停交互)或 `loadAbsorbersPlugin`(两者)。 +- **`@tsparticles/plugin-emitters`**:`loadEmittersPluginSimple`(仅发射器的生命周期和绘制)、`loadEmittersInteraction`(仅点击/悬停交互)或 `loadEmittersPlugin`(两者)。 + +### 形状 + +- **`@tsparticles/shape-polygon`**:`loadGenericPolygonShape`(多边形)或 `loadTriangleShape`(三角形)单独加载,或使用 `loadPolygonShape` 加载两者。 +- **`@tsparticles/shape-cards`**:`loadClubsSuitShape`、`loadDiamondsSuitShape`、`loadHeartsSuitShape`、`loadSpadesSuitShape`(单个花色)、`loadCardSuitsShape`(所有花色)、`loadFullCardsShape`(卡牌图像)或 `loadCardsShape`(全部)。 + +所有其他形状包(arrow, circle, cog, emoji, heart, image, infinity, line, matrix, path, rounded-polygon, rounded-rect, spiral, square, squircle, star, text)直接导出单个 `load*Shape` 函数。 ## 参考 From 65d1bb05d1284c2cf28efbf218f88d9a7c0c2556 Mon Sep 17 00:00:00 2001 From: Matteo Bruni <176620+matteobruni@users.noreply.github.com> Date: Tue, 19 May 2026 14:23:37 +0200 Subject: [PATCH 02/10] docs: updated some docs and website --- plugins/absorbers/README.md | 1 + plugins/emitters/README.md | 1 + websites/website/docs/.vitepress/config.ts | 39 +- .../website/docs/de/migrations/from-v3.md | 14 +- .../website/docs/es/migrations/from-v3.md | 14 +- .../website/docs/fr/migrations/from-v3.md | 14 +- websites/website/docs/guide/bundles-all.md | 2 +- websites/website/docs/guide/bundles-basic.md | 2 +- .../website/docs/guide/bundles-confetti.md | 2 +- .../website/docs/guide/bundles-fireworks.md | 2 +- websites/website/docs/guide/bundles-full.md | 2 +- .../website/docs/guide/bundles-particles.md | 2 +- websites/website/docs/guide/bundles-slim.md | 2 +- .../guide/plugins-customization-bundle.md | 77 +++ .../guide/plugins-customization-effect.md | 101 ++++ .../plugins-customization-interaction.md | 117 +++++ .../guide/plugins-customization-palette.md | 106 ++++ .../docs/guide/plugins-customization-path.md | 118 +++++ .../guide/plugins-customization-plugin.md | 93 ++++ .../guide/plugins-customization-preset.md | 91 ++++ .../docs/guide/plugins-customization-shape.md | 100 ++++ .../guide/plugins-customization-updater.md | 81 +++ .../docs/guide/plugins-customization.md | 482 +----------------- .../website/docs/hi/migrations/from-v3.md | 14 +- .../website/docs/it/migrations/from-v3.md | 16 +- .../website/docs/ja/migrations/from-v3.md | 16 +- websites/website/docs/migrations/from-v3.md | 14 +- .../website/docs/pt/migrations/from-v3.md | 14 +- .../website/docs/ru/migrations/from-v3.md | 14 +- .../website/docs/zh/migrations/from-v3.md | 14 +- wrappers/svelte/CHANGELOG.md | 4 - 31 files changed, 1009 insertions(+), 560 deletions(-) create mode 100644 websites/website/docs/guide/plugins-customization-bundle.md create mode 100644 websites/website/docs/guide/plugins-customization-effect.md create mode 100644 websites/website/docs/guide/plugins-customization-interaction.md create mode 100644 websites/website/docs/guide/plugins-customization-palette.md create mode 100644 websites/website/docs/guide/plugins-customization-path.md create mode 100644 websites/website/docs/guide/plugins-customization-plugin.md create mode 100644 websites/website/docs/guide/plugins-customization-preset.md create mode 100644 websites/website/docs/guide/plugins-customization-shape.md create mode 100644 websites/website/docs/guide/plugins-customization-updater.md diff --git a/plugins/absorbers/README.md b/plugins/absorbers/README.md index dfdf8215692..863acb3293a 100644 --- a/plugins/absorbers/README.md +++ b/plugins/absorbers/README.md @@ -98,6 +98,7 @@ Instead of the full `loadAbsorbersPlugin`, you can import only the parts you nee ``` Lazy-loaded variants are also available by appending `/lazy` to the import path: + ```ts import { loadAbsorbersPluginSimple } from "@tsparticles/plugin-absorbers/plugin/lazy"; import { loadAbsorbersInteraction } from "@tsparticles/plugin-absorbers/interaction/lazy"; diff --git a/plugins/emitters/README.md b/plugins/emitters/README.md index ccfb097b57d..14009404aa2 100644 --- a/plugins/emitters/README.md +++ b/plugins/emitters/README.md @@ -98,6 +98,7 @@ Instead of the full `loadEmittersPlugin`, you can import only the parts you need ``` Lazy-loaded variants are also available by appending `/lazy` to the import path: + ```ts import { loadEmittersPluginSimple } from "@tsparticles/plugin-emitters/plugin/lazy"; import { loadEmittersInteraction } from "@tsparticles/plugin-emitters/interaction/lazy"; diff --git a/websites/website/docs/.vitepress/config.ts b/websites/website/docs/.vitepress/config.ts index e89def58925..0903400ad6f 100644 --- a/websites/website/docs/.vitepress/config.ts +++ b/websites/website/docs/.vitepress/config.ts @@ -66,18 +66,39 @@ const baseSidebar: DefaultTheme.Sidebar = { { text: "Getting Started", link: "/guide/getting-started" }, { text: "Installation", link: "/guide/installation" }, - { text: "Bundles", link: "/guide/bundles" }, - { text: "Bundle: Basic", link: "/guide/bundles-basic" }, - { text: "Bundle: Slim", link: "/guide/bundles-slim" }, - { text: "Bundle: tsparticles (Full)", link: "/guide/bundles-full" }, - { text: "Bundle: All", link: "/guide/bundles-all" }, - { text: "Bundle: Confetti", link: "/guide/bundles-confetti" }, - { text: "Bundle: Fireworks", link: "/guide/bundles-fireworks" }, - { text: "Bundle: Particles", link: "/guide/bundles-particles" }, + { + text: "Bundles", + collapsed: true, + items: [ + { text: "Overview", link: "/guide/bundles" }, + { text: "Basic", link: "/guide/bundles-basic" }, + { text: "Slim", link: "/guide/bundles-slim" }, + { text: "tsparticles (Full)", link: "/guide/bundles-full" }, + { text: "All", link: "/guide/bundles-all" }, + { text: "Confetti", link: "/guide/bundles-confetti" }, + { text: "Fireworks", link: "/guide/bundles-fireworks" }, + { text: "Particles", link: "/guide/bundles-particles" }, + ], + }, { text: "Framework Integrations", link: "/guide/frameworks" }, { text: "Color Formats", link: "/guide/color-formats" }, { text: "Container Lifecycle", link: "/guide/container-lifecycle" }, - { text: "Plugins & Customization", link: "/guide/plugins-customization" }, + { + text: "Plugins & Customization", + collapsed: true, + items: [ + { text: "Overview", link: "/guide/plugins-customization" }, + { text: "Plugin", link: "/guide/plugins-customization-plugin" }, + { text: "Shape", link: "/guide/plugins-customization-shape" }, + { text: "Preset", link: "/guide/plugins-customization-preset" }, + { text: "Updater", link: "/guide/plugins-customization-updater" }, + { text: "Effect", link: "/guide/plugins-customization-effect" }, + { text: "Interaction", link: "/guide/plugins-customization-interaction" }, + { text: "Path", link: "/guide/plugins-customization-path" }, + { text: "Palette", link: "/guide/plugins-customization-palette" }, + { text: "Custom Bundle", link: "/guide/plugins-customization-bundle" }, + ], + }, { text: "Templates & Resources", link: "/guide/templates-resources" }, { text: "Video Tutorials", link: "/guide/video-tutorials" }, { text: "Dependency Graph", link: "/guide/dependency-graph" }, diff --git a/websites/website/docs/de/migrations/from-v3.md b/websites/website/docs/de/migrations/from-v3.md index 386f38c16bb..8bc0157e60a 100644 --- a/websites/website/docs/de/migrations/from-v3.md +++ b/websites/website/docs/de/migrations/from-v3.md @@ -11,13 +11,13 @@ Bei `v3.x` sind die groessten Migrationsrisiken die **Options-Kompatibilitaet** Einige `v3.x`-Pakete wurden umbenannt oder umstrukturiert: -| v3-Paket | Aktuelles Paket | Hinweis | -| ----------------------------------- | ------------------------------- | ---------------------------------------------------- | -| `@tsparticles/move-base` | `@tsparticles/plugin-move` | In einem einzigen Plugin zusammengefuehrt | -| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | In einem einzigen Plugin zusammengefuehrt | -| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Durch Paint-System ersetzt | -| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Durch Paint-System ersetzt | -| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Nach `plugins/colors/hsv/` verschoben, gleicher Name | +| v3-Paket | Aktuelles Paket | Hinweis | +| ----------------------------------- | ----------------------------------- | ------------------------------------------------------------------------ | +| `@tsparticles/move-base` | `@tsparticles/plugin-move` | In einem einzigen Plugin zusammengefuehrt | +| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | In einem einzigen Plugin zusammengefuehrt | +| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Durch Paint-System ersetzt | +| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Durch Paint-System ersetzt | +| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Nach `plugins/colors/hsv/` verschoben, gleicher Name | | (in v3 nicht benötigt - integriert) | `@tsparticles/plugin-interactivity` | Erforderlich für alle Interaktions-Plugins (grab, bubble, repulse, etc.) | ## Beispiele fuer Optionszuordnung diff --git a/websites/website/docs/es/migrations/from-v3.md b/websites/website/docs/es/migrations/from-v3.md index 942c27b8aec..1d3a2bbed0b 100644 --- a/websites/website/docs/es/migrations/from-v3.md +++ b/websites/website/docs/es/migrations/from-v3.md @@ -11,13 +11,13 @@ Desde `v3.x`, los principales riesgos son la **compatibilidad de opciones** y lo Algunos paquetes de `v3.x` han sido renombrados o reestructurados: -| Paquete v3 | Paquete actual | Nota | -| ----------------------------------- | ------------------------------- | -------------------------------------------- | -| `@tsparticles/move-base` | `@tsparticles/plugin-move` | Fusionados en un solo plugin | -| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | Fusionados en un solo plugin | -| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Reemplazado por el sistema paint | -| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Reemplazado por el sistema paint | -| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Movido a `plugins/colors/hsv/`, mismo nombre | +| Paquete v3 | Paquete actual | Nota | +| ----------------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------- | +| `@tsparticles/move-base` | `@tsparticles/plugin-move` | Fusionados en un solo plugin | +| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | Fusionados en un solo plugin | +| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Reemplazado por el sistema paint | +| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Reemplazado por el sistema paint | +| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Movido a `plugins/colors/hsv/`, mismo nombre | | (no necesario en v3 - integrado) | `@tsparticles/plugin-interactivity` | Necesario para que funcionen todos los plugins de interaccion (grab, bubble, repulse, etc.) | ## Ejemplos de mapeo de opciones diff --git a/websites/website/docs/fr/migrations/from-v3.md b/websites/website/docs/fr/migrations/from-v3.md index ff2067a707b..fdb50bd3b1d 100644 --- a/websites/website/docs/fr/migrations/from-v3.md +++ b/websites/website/docs/fr/migrations/from-v3.md @@ -11,13 +11,13 @@ Depuis `v3.x`, les principaux risques de migration sont la **compatibilité des Certains paquets `v3.x` ont été renommés ou restructurés : -| Paquet v3 | Paquet actuel | Note | -| ----------------------------------- | ------------------------------- | -------------------------------------------- | -| `@tsparticles/move-base` | `@tsparticles/plugin-move` | Fusionnés en un seul plugin | -| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | Fusionnés en un seul plugin | -| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Remplacé par le système paint | -| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Remplacé par le système paint | -| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Déplacé dans `plugins/colors/hsv/`, même nom | +| Paquet v3 | Paquet actuel | Note | +| ----------------------------------- | ----------------------------------- | ----------------------------------------------------------------------------------------- | +| `@tsparticles/move-base` | `@tsparticles/plugin-move` | Fusionnés en un seul plugin | +| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | Fusionnés en un seul plugin | +| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Remplacé par le système paint | +| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Remplacé par le système paint | +| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Déplacé dans `plugins/colors/hsv/`, même nom | | (non nécessaire en v3 - intégré) | `@tsparticles/plugin-interactivity` | Requis pour que tous les plugins d'interaction (grab, bubble, repulse, etc.) fonctionnent | ## Exemples de correspondance des options diff --git a/websites/website/docs/guide/bundles-all.md b/websites/website/docs/guide/bundles-all.md index da0c5390a6e..fb5c51173d4 100644 --- a/websites/website/docs/guide/bundles-all.md +++ b/websites/website/docs/guide/bundles-all.md @@ -1,4 +1,4 @@ -# Bundle: All +# All `@tsparticles/all` loads all official features and is ideal for fast prototyping. diff --git a/websites/website/docs/guide/bundles-basic.md b/websites/website/docs/guide/bundles-basic.md index b19657e8433..6944cfe5c20 100644 --- a/websites/website/docs/guide/bundles-basic.md +++ b/websites/website/docs/guide/bundles-basic.md @@ -1,4 +1,4 @@ -# Bundle: Basic +# Basic `@tsparticles/basic` is for extra-light setups where you need a minimal runtime. diff --git a/websites/website/docs/guide/bundles-confetti.md b/websites/website/docs/guide/bundles-confetti.md index 18e5e1e7fd0..e27efe070c4 100644 --- a/websites/website/docs/guide/bundles-confetti.md +++ b/websites/website/docs/guide/bundles-confetti.md @@ -1,4 +1,4 @@ -# Bundle: Confetti +# Confetti `@tsparticles/confetti` exposes a focused API for confetti effects with minimal setup. diff --git a/websites/website/docs/guide/bundles-fireworks.md b/websites/website/docs/guide/bundles-fireworks.md index f10d832f799..68d38deb052 100644 --- a/websites/website/docs/guide/bundles-fireworks.md +++ b/websites/website/docs/guide/bundles-fireworks.md @@ -1,4 +1,4 @@ -# Bundle: Fireworks +# Fireworks `@tsparticles/fireworks` exposes a focused API for fireworks effects with minimal setup. diff --git a/websites/website/docs/guide/bundles-full.md b/websites/website/docs/guide/bundles-full.md index a4082853c50..2e21dace10e 100644 --- a/websites/website/docs/guide/bundles-full.md +++ b/websites/website/docs/guide/bundles-full.md @@ -1,4 +1,4 @@ -# Bundle: tsparticles (Full) +# tsparticles (Full) `tsparticles` is the full bundle and includes a broad set of official features with one loader. diff --git a/websites/website/docs/guide/bundles-particles.md b/websites/website/docs/guide/bundles-particles.md index e4f11977536..a851c41651d 100644 --- a/websites/website/docs/guide/bundles-particles.md +++ b/websites/website/docs/guide/bundles-particles.md @@ -1,4 +1,4 @@ -# Bundle: Particles +# Particles `@tsparticles/particles` exposes a focused API for simple particles backgrounds. diff --git a/websites/website/docs/guide/bundles-slim.md b/websites/website/docs/guide/bundles-slim.md index 3afde2e6d9b..de5feff536d 100644 --- a/websites/website/docs/guide/bundles-slim.md +++ b/websites/website/docs/guide/bundles-slim.md @@ -1,4 +1,4 @@ -# Bundle: Slim +# Slim `@tsparticles/slim` is the recommended default for most projects. diff --git a/websites/website/docs/guide/plugins-customization-bundle.md b/websites/website/docs/guide/plugins-customization-bundle.md new file mode 100644 index 00000000000..efb4bc16fd2 --- /dev/null +++ b/websites/website/docs/guide/plugins-customization-bundle.md @@ -0,0 +1,77 @@ +# Custom Bundle + +A bundle is a loader that groups multiple extension packages together and registers them all with a single function call. The official `slim`, `basic`, and `all` packages are bundles. + +## Quick app-local creation + +```ts +import type { Engine } from "@tsparticles/engine"; +import { loadSlim } from "@tsparticles/slim"; + +export async function loadAppBundle(engine: Engine): Promise { + await loadSlim(engine); + + await Promise.all([ + loadAppShape(engine), + loadAppPreset(), + loadAppPalette(engine), + loadAppEffect(engine), + loadAppPath(engine), + loadAppUpdater(engine), + loadAppInteraction(engine), + loadAppPlugin(engine), + ]); +} + +await loadAppBundle(tsParticles); +``` + +## Creating a reusable package + +### Using the CLI + +```bash +npx @tsparticles/cli-create bundle +``` + +### Generated files + +``` +src/ + bundle.ts — Bundle entry that loads all dependency loaders + index.ts — Load function + exports + index.lazy.ts — Lazy async loader + browser.ts — Browser global registration +``` + +### Package structure + +The bundle load function aggregates other loaders: + +```ts +export async function loadMyBundle(engine: Engine): Promise { + engine.checkVersion(__VERSION__); + await engine.pluginManager.register(async () => { + // load dependency packages + await loadFeatureA(engine); + await loadFeatureB(engine); + }); +} +``` + +### Using your package + +```ts +import { loadMyBundle } from "@tsparticles/my-bundle"; + +await loadMyBundle(tsParticles); +``` + +Add your dependency packages (shapes, updaters, plugins, presets, etc.) in `dependencies` in `package.json`. + +## Contributing to the official repository + +- Place your bundle in: `bundles//` +- Use `dependencies` (not `peerDependencies`) for all bundled sub-packages +- Lint and build with: `pnpm run build` +- Open a pull request on GitHub diff --git a/websites/website/docs/guide/plugins-customization-effect.md b/websites/website/docs/guide/plugins-customization-effect.md new file mode 100644 index 00000000000..5f726f2e784 --- /dev/null +++ b/websites/website/docs/guide/plugins-customization-effect.md @@ -0,0 +1,101 @@ +# Effect + +Effects are visual modifiers that draw before or after particles. They can apply canvas-wide transformations like fade, blur, or color overlays. Each effect implements `IEffectDrawer`. + +## Quick app-local creation + +```ts +import type { Engine } from "@tsparticles/engine"; + +export async function loadAppEffect(engine: Engine): Promise { + await engine.pluginManager.register((e) => { + e.pluginManager.addEffect("app-fade", () => + Promise.resolve({ + drawBefore: ({ context }) => { + context.save(); + context.globalAlpha *= 0.85; + }, + drawAfter: ({ context }) => { + context.restore(); + }, + }), + ); + }); +} + +await loadAppEffect(tsParticles); + +const options = { + particles: { + effect: { + type: "app-fade", + }, + }, +}; +``` + +## Creating a reusable package + +### Using the CLI + +```bash +npx @tsparticles/cli-create effect +``` + +### Generated files + +``` +src/ + index.ts — Load function + effect drawer implementation + index.lazy.ts — Lazy async loader + browser.ts — Browser global registration +``` + +### Package structure + +The effect drawer class implements `IEffectDrawer` with lifecycle hooks: + +```ts +export class MyEffectDrawer implements IEffectDrawer { + drawBefore(data: IEffectDrawData): void { + // canvas transform before particle drawing + } + + drawAfter(data: IEffectDrawData): void { + // canvas transform after particle drawing + } +} +``` + +The load function registers the effect: + +```ts +export async function loadMyEffect(engine: Engine): Promise { + engine.checkVersion(__VERSION__); + await engine.pluginManager.register((e) => { + e.pluginManager.addEffect("my-effect", () => new MyEffectDrawer()); + }); +} +``` + +### Using your package + +```ts +import { loadMyEffect } from "@tsparticles/effect-my-effect"; + +await loadMyEffect(tsParticles); + +const options = { + particles: { + effect: { + type: "my-effect", + }, + }, +}; +``` + +## Contributing to the official repository + +- Place your package in: `effects//` +- Lint and build with: `pnpm run build` +- Open a pull request on GitHub diff --git a/websites/website/docs/guide/plugins-customization-interaction.md b/websites/website/docs/guide/plugins-customization-interaction.md new file mode 100644 index 00000000000..0013e305a97 --- /dev/null +++ b/websites/website/docs/guide/plugins-customization-interaction.md @@ -0,0 +1,117 @@ +# Interaction + +Interactions define behavior between particles and events. They come in two categories: + +- **External**: triggered by mouse, touch, or canvas events (e.g. attract, grab, repulse) +- **Particles**: triggered by particle-to-particle proximity (e.g. links, collisions) + +Both extend `ExternalInteractorBase` or `ParticlesInteractorBase` from `@tsparticles/plugin-interactivity`. + +## Quick app-local creation + +```ts +import { + ExternalInteractorBase, + loadInteractivityPlugin, + type IInteractivityData, +} from "@tsparticles/plugin-interactivity"; +import type { Engine, IDelta } from "@tsparticles/engine"; + +class AppHoverPauseInteractor extends ExternalInteractorBase { + readonly maxDistance = 0; + + clear(): void {} + + init(): void {} + + interact(interactivityData: IInteractivityData, _delta: IDelta): void { + if (interactivityData.pointer?.position) { + this.container.pause(); + } + } + + isEnabled(interactivityData: IInteractivityData): boolean { + return !!interactivityData.pointer?.position; + } + + reset(): void { + this.container.play(); + } +} + +export async function loadAppInteraction(engine: Engine): Promise { + await loadInteractivityPlugin(engine); + + await engine.pluginManager.register((e) => { + e.pluginManager.addInteractor?.("app-hover-pause", (container) => { + return Promise.resolve(new AppHoverPauseInteractor(container)); + }); + }); +} + +await loadAppInteraction(tsParticles); + +const options = { + interactivity: { + events: { + onHover: { enable: true }, + }, + }, +}; +``` + +## Creating a reusable package + +### Using the CLI + +```bash +npx @tsparticles/cli-create interaction +``` + +The CLI prompts for an interaction type: + +| Type | Description | Package name pattern | +| ----------- | ---------------------------------- | ------------------------------------------- | +| `external` | Mouse/touch event interactions | `@tsparticles/interaction-external-{name}` | +| `particles` | Particle-to-particle interactions | `@tsparticles/interaction-particles-{name}` | +| `generic` | Combined or standalone interaction | `@tsparticles/interaction-{name}` | + +### Generated files + +``` +src/ + index.ts — Load function + interactor class(es) + index.lazy.ts — Lazy async loader + browser.ts — Browser global registration +``` + +The load function registers the interactor: + +```ts +export async function loadMyInteraction(engine: Engine): Promise { + engine.checkVersion(__VERSION__); + await engine.pluginManager.register((e) => { + e.pluginManager.addInteractor?.("external-my-interaction", (container) => { + return Promise.resolve(new MyExternalInteractor(container)); + }); + }); +} +``` + +### Using your package + +```ts +import { loadMyInteraction } from "@tsparticles/interaction-external-my-interaction"; + +await loadMyInteraction(tsParticles); +``` + +External interactions also depend on `@tsparticles/plugin-interactivity` for the base classes and event system. + +## Contributing to the official repository + +- External interactions go in: `interactions/external//` +- Particles interactions go in: `interactions/particles//` +- Combined interactions go in: `interactions//` +- Lint and build with: `pnpm run build` +- Open a pull request on GitHub diff --git a/websites/website/docs/guide/plugins-customization-palette.md b/websites/website/docs/guide/plugins-customization-palette.md new file mode 100644 index 00000000000..3109494bba0 --- /dev/null +++ b/websites/website/docs/guide/plugins-customization-palette.md @@ -0,0 +1,106 @@ +# Palette + +Palettes define reusable color profiles with fill and stroke colors, blend mode, and optional background. They are referenced with `particles.palette`. + +## Quick app-local creation + +```ts +import type { Engine, IPalette } from "@tsparticles/engine"; + +const appPalette: IPalette = { + name: "App Sunset", + blendMode: "multiply", + colors: { + fill: { + enable: true, + value: ["#ff6b6b", "#ffd166", "#4ecdc4"], + }, + }, +}; + +export async function loadAppPalette(engine: Engine): Promise { + await engine.pluginManager.register((e) => { + e.pluginManager.addPalette("app-sunset", appPalette); + }); +} + +await loadAppPalette(tsParticles); + +const options = { + particles: { + palette: "app-sunset", + }, +}; +``` + +## Creating a reusable package + +### Using the CLI + +```bash +npx @tsparticles/cli-create palette +``` + +### Generated files + +``` +src/ + options.ts — Palette configuration object + index.ts — Load function + exports + index.lazy.ts — Lazy async loader + browser.ts — Browser global registration +``` + +### Package structure + +The `options.ts` file contains the palette definition: + +```ts +import type { IPalette } from "@tsparticles/engine"; + +const paletteName = "my-palette"; + +export const myPaletteOptions: IPalette = { + name: "My Palette", + blendMode: "normal", + colors: { + fill: { + enable: true, + value: ["#color1", "#color2"], + }, + }, +}; + +export { paletteName }; +``` + +The load function registers the palette: + +```ts +export async function loadMyPalette(engine: Engine): Promise { + engine.checkVersion(__VERSION__); + await engine.pluginManager.register((e) => { + e.pluginManager.addPalette(paletteName, myPaletteOptions); + }); +} +``` + +### Using your package + +```ts +import { loadMyPalette } from "@tsparticles/palette-my-palette"; + +await loadMyPalette(tsParticles); + +const options = { + particles: { + palette: "my-palette", + }, +}; +``` + +## Contributing to the official repository + +- Place your package in: `palettes///` (two levels deep) +- Lint and build with: `pnpm run build` +- Open a pull request on GitHub diff --git a/websites/website/docs/guide/plugins-customization-path.md b/websites/website/docs/guide/plugins-customization-path.md new file mode 100644 index 00000000000..94e15cb5064 --- /dev/null +++ b/websites/website/docs/guide/plugins-customization-path.md @@ -0,0 +1,118 @@ +# Path + +Path generators control particle movement by returning a velocity vector each frame. They are used with `particles.move.path.generator`. Paths depend on `@tsparticles/plugin-move`. + +## Quick app-local creation + +```ts +import { loadMovePlugin } from "@tsparticles/plugin-move"; +import { Vector, type Engine } from "@tsparticles/engine"; + +export async function loadAppPath(engine: Engine): Promise { + await loadMovePlugin(engine); + + await engine.pluginManager.register((e) => { + e.pluginManager.addPathGenerator?.("app-sway", () => + Promise.resolve({ + generate: (particle) => { + const wave = Math.sin(particle.position.y * 0.02); + return Vector.create(wave, 0); + }, + init: () => {}, + reset: () => {}, + update: () => {}, + }), + ); + }); +} + +await loadAppPath(tsParticles); + +const options = { + particles: { + move: { + enable: true, + path: { + enable: true, + generator: "app-sway", + }, + }, + }, +}; +``` + +## Creating a reusable package + +### Using the CLI + +```bash +npx @tsparticles/cli-create path +``` + +### Generated files + +``` +src/ + index.ts — Load function + path generator class + index.lazy.ts — Lazy async loader + browser.ts — Browser global registration +``` + +### Package structure + +The path generator class implements `IPathGenerator`: + +```ts +export class MyPathGenerator implements IPathGenerator { + init(container: Container): void {} + + generate(particle: Particle): Vector { + return Vector.create(0, 0); + } + + reset(particle: Particle): void {} + + update(particle: Particle, delta: IDelta): void {} +} +``` + +The load function registers the generator: + +```ts +export async function loadMyPath(engine: Engine): Promise { + engine.checkVersion(__VERSION__); + await engine.pluginManager.register((e) => { + e.pluginManager.addPathGenerator?.("my-path", () => new MyPathGenerator()); + }); +} +``` + +### Using your package + +```ts +import { loadMyPath } from "@tsparticles/path-my-path"; +import { loadMovePlugin } from "@tsparticles/plugin-move"; + +await loadMovePlugin(tsParticles); +await loadMyPath(tsParticles); + +const options = { + particles: { + move: { + enable: true, + path: { + enable: true, + generator: "my-path", + }, + }, + }, +}; +``` + +Add `@tsparticles/plugin-move` as a dependency in your `package.json`. + +## Contributing to the official repository + +- Place your package in: `paths//` +- Lint and build with: `pnpm run build` +- Open a pull request on GitHub diff --git a/websites/website/docs/guide/plugins-customization-plugin.md b/websites/website/docs/guide/plugins-customization-plugin.md new file mode 100644 index 00000000000..2fef7fbbef0 --- /dev/null +++ b/websites/website/docs/guide/plugins-customization-plugin.md @@ -0,0 +1,93 @@ +# Plugin + +Plugins are the most powerful extension point. They implement `IPlugin` and `IContainerPlugin` and can hook into the full container lifecycle: init, draw, update, particle creation, resize, and option parsing. + +## Quick app-local creation + +```ts +import type { Container, Engine, IContainerPlugin, IPlugin, ISourceOptions, Options } from "@tsparticles/engine"; + +class AppPluginInstance implements IContainerPlugin { + private readonly container: Container; + + constructor(container: Container) { + this.container = container; + } + + async init(): Promise { + this.container.retina.pixelRatio = Math.max(this.container.retina.pixelRatio, 1); + } +} + +class AppPlugin implements IPlugin { + readonly id = "app-plugin"; + + async getPlugin(container: Container): Promise { + return new AppPluginInstance(container); + } + + loadOptions(_options: Options, source?: ISourceOptions): void { + if (source?.appPlugin === false) { + return; + } + } + + needsPlugin(source?: ISourceOptions): boolean { + return source?.appPlugin !== false; + } +} + +export async function loadAppPlugin(engine: Engine): Promise { + await engine.addPlugin(new AppPlugin()); +} + +await loadAppPlugin(tsParticles); + +const options = { + appPlugin: true, +}; +``` + +## Creating a reusable package + +### Using the CLI + +```bash +npx @tsparticles/cli-create plugin +``` + +The CLI prompts for a plugin type. Available types: + +| Type | Description | Package name pattern | +| ---------------- | ------------------------------------------------------- | ------------------------------------------- | +| `generic` | General-purpose plugin (`IPlugin`) | `@tsparticles/plugin-{name}` | +| `emitters-shape` | Custom emitter shape for `@tsparticles/plugin-emitters` | `@tsparticles/plugin-emitters-shape-{name}` | +| `easing` | Custom easing function | `@tsparticles/plugin-easing-{name}` | +| `export` | Custom export format | `@tsparticles/plugin-export-{name}` | +| `color-manager` | Custom color format parser | `@tsparticles/plugin-{name}-color` | + +### Generated files + +``` +src/ + Plugin.ts — IPlugin implementation with id, getPlugin, loadOptions, needsPlugin + PluginInstance.ts — IContainerPlugin implementation with lifecycle hooks + index.ts — Load function + exports + index.lazy.ts — Lazy async loader for code-splitting + browser.ts — Browser global registration +``` + +### Using your package + +```ts +import { loadMyPlugin } from "@tsparticles/plugin-my-plugin"; + +await loadMyPlugin(tsParticles); +``` + +## Contributing to the official repository + +- Place your package in: `plugins//` +- Interactions with subtypes: `plugins///` +- Lint and build with: `pnpm run build` +- Open a pull request on GitHub diff --git a/websites/website/docs/guide/plugins-customization-preset.md b/websites/website/docs/guide/plugins-customization-preset.md new file mode 100644 index 00000000000..4512da80678 --- /dev/null +++ b/websites/website/docs/guide/plugins-customization-preset.md @@ -0,0 +1,91 @@ +# Preset + +A preset bundles a full set of options into a single named configuration that users can reference with the `preset` option. This is the best way to share complete visual themes. + +## Quick app-local creation + +```ts +import { tsParticles } from "@tsparticles/engine"; + +export async function loadAppPreset(): Promise { + tsParticles.addPreset("app-hero", { + fpsLimit: 60, + particles: { + number: { value: 80 }, + move: { enable: true, speed: 2 }, + links: { enable: true, distance: 140 }, + }, + }); +} + +await loadAppPreset(); + +const options = { + preset: "app-hero", +}; +``` + +## Creating a reusable package + +### Using the CLI + +```bash +npx @tsparticles/cli-create preset +``` + +### Generated files + +``` +src/ + options.ts — Preset options object + bundle.ts — Bundle entry that auto-loads the preset + index.ts — Load function + exports + index.lazy.ts — Lazy async loader + browser.ts — Browser global registration +``` + +### Package structure + +The `options.ts` file contains the preset options: + +```ts +import type { ISourceOptions } from "@tsparticles/engine"; + +const options: ISourceOptions = { + // your preset options +}; + +export default options; +``` + +The load function registers the preset: + +```ts +export async function loadMyPreset(engine: Engine): Promise { + engine.checkVersion(__VERSION__); + await engine.pluginManager.register((e) => { + e.pluginManager.addPreset("my-preset", options); + }); +} +``` + +### Using your package + +```ts +import { loadMyPreset } from "@tsparticles/preset-my-preset"; + +await loadMyPreset(tsParticles); + +const options = { + preset: "my-preset", +}; +``` + +A preset package often depends on specific shape, updater, or plugin packages to provide the features it needs. Add them as `dependencies` in `package.json`. + +## Contributing to the official repository + +- Place your package in: `presets//` +- Presets typically bundle multiple dependencies — declare them in `dependencies`, not `peerDependencies` +- Lint and build with: `pnpm run build` +- Open a pull request on GitHub diff --git a/websites/website/docs/guide/plugins-customization-shape.md b/websites/website/docs/guide/plugins-customization-shape.md new file mode 100644 index 00000000000..67e526eb2e4 --- /dev/null +++ b/websites/website/docs/guide/plugins-customization-shape.md @@ -0,0 +1,100 @@ +# Shape + +Shapes are drawing primitives for particles. Each shape implements `IShapeDrawer` with a `draw` method that receives the canvas context and particle data. + +## Quick app-local creation + +```ts +import type { Engine } from "@tsparticles/engine"; + +// Register a custom shape inline +await tsParticles.addShape("app-star", { + draw: (data) => { + const { context, radius } = data; + const sides = 5; + const inset = 2; + + context.beginPath(); + for (let i = 0; i < sides * 2; i++) { + const angle = (Math.PI * i) / sides - Math.PI / 2; + const r = i % 2 === 0 ? radius : radius / inset; + const x = r * Math.cos(angle); + const y = r * Math.sin(angle); + + if (i === 0) context.moveTo(x, y); + else context.lineTo(x, y); + } + context.closePath(); + }, +}); + +const options = { + particles: { + shape: { type: "app-star" }, + }, +}; +``` + +## Creating a reusable package + +### Using the CLI + +```bash +npx @tsparticles/cli-create shape +``` + +### Generated files + +``` +src/ + ShapeDrawer.ts — IShapeDrawer class with draw, init, particleInit + index.ts — Load function + exports + index.lazy.ts — Lazy async loader for code-splitting + browser.ts — Browser global registration +``` + +### Package structure + +The generated `ShapeDrawer.ts` contains a class implementing `IShapeDrawer`: + +```ts +export class MyShapeDrawer implements IShapeDrawer { + readonly validTypes = ["my-shape"]; + + draw(data: IShapeDrawData): void { + const { context, radius } = data; + // drawing logic + } +} +``` + +The load function registers the shape: + +```ts +export async function loadMyShape(engine: Engine): Promise { + engine.checkVersion(__VERSION__); + await engine.pluginManager.register((e) => { + e.pluginManager.addShape(["my-shape"], () => new MyShapeDrawer()); + }); +} +``` + +### Using your package + +```ts +import { loadMyShape } from "@tsparticles/shape-my-shape"; + +await loadMyShape(tsParticles); + +const options = { + particles: { + shape: { type: "my-shape" }, + }, +}; +``` + +## Contributing to the official repository + +- Place your package in: `shapes//` +- Lint and build with: `pnpm run build` +- Open a pull request on GitHub diff --git a/websites/website/docs/guide/plugins-customization-updater.md b/websites/website/docs/guide/plugins-customization-updater.md new file mode 100644 index 00000000000..9fa0454b64c --- /dev/null +++ b/websites/website/docs/guide/plugins-customization-updater.md @@ -0,0 +1,81 @@ +# Updater + +Updaters mutate particle properties every frame — they are responsible for effects like tilt, roll, twinkle, opacity changes, size animations, and out-of-bounds handling. + +## Quick app-local creation + +```ts +import type { Engine, IDelta, Particle } from "@tsparticles/engine"; + +export async function loadAppUpdater(engine: Engine): Promise { + await engine.pluginManager.register((e) => { + e.pluginManager.addParticleUpdater("app-drift", () => + Promise.resolve({ + init: (): void => {}, + isEnabled: (): boolean => true, + update: (particle: Particle, delta: IDelta): void => { + particle.position.x += 0.02 * delta.factor; + }, + }), + ); + }); +} + +await loadAppUpdater(tsParticles); +``` + +## Creating a reusable package + +### Using the CLI + +```bash +npx @tsparticles/cli-create updater +``` + +### Generated files + +``` +src/ + Updater.ts — IParticleUpdater class with init, isEnabled, update + index.ts — Load function + exports + index.lazy.ts — Lazy async loader + browser.ts — Browser global registration +``` + +### Package structure + +The generated `Updater.ts` contains a class implementing `IParticleUpdater`: + +```ts +export class MyUpdater implements IParticleUpdater { + readonly name = "my-updater"; + + init(particle: Particle): void { + // initialize per-particle state + } + + isEnabled(particle: Particle): boolean { + return true; + } + + update(particle: Particle, delta: IDelta): void { + // mutate particle properties each frame + } +} +``` + +### Using your package + +```ts +import { loadMyUpdater } from "@tsparticles/updater-my-updater"; + +await loadMyUpdater(tsParticles); +``` + +Updaters run automatically on all particles where `isEnabled()` returns `true`. No extra options configuration is needed unless the updater defines custom options. + +## Contributing to the official repository + +- Place your package in: `updaters//` +- Lint and build with: `pnpm run build` +- Open a pull request on GitHub diff --git a/websites/website/docs/guide/plugins-customization.md b/websites/website/docs/guide/plugins-customization.md index b937c752280..710764cb9ea 100644 --- a/websites/website/docs/guide/plugins-customization.md +++ b/websites/website/docs/guide/plugins-customization.md @@ -1,8 +1,6 @@ # Plugins & Customization -tsParticles can be extended at runtime with custom shapes, presets, and plugins. - -This guide focuses on the quick path: add custom behavior directly inside an app, without creating a full standalone package first. +tsParticles can be extended at runtime with custom shapes, presets, plugins, and more. You can either create extensions inline (app-local) or build full npm packages using the CLI scaffolding tool. ## Quick decision map @@ -12,468 +10,17 @@ This guide focuses on the quick path: add custom behavior directly inside an app ## All extension types at a glance -tsParticles customization is broader than only custom plugins. - -- **Bundle**: grouped loader that registers many features at once (`slim`, `basic`, `all`). -- **Effect**: particle rendering effect (`particles.effect`). -- **Interaction**: behavior between particles and events; split into `external` (mouse/touch) and `particles` (particle-particle). -- **Palette**: reusable style/colors profile (`particles.palette`). -- **Path**: motion path generator for particle movement (`particles.move.path`). -- **Plugin**: container/runtime feature module (for example emitters, absorbers, polygon mask). -- **Preset**: reusable full options profile (`preset`). -- **Shape**: particle drawing primitive (`particles.shape.type`). -- **Updater**: per-frame particle property updater (tilt, roll, twinkle, opacity, size, and more). - -If you explain these categories to users, they immediately understand how deep the customization can go. - -## Summary table - -| Type | Quick create (app-local) | How to use | -| ----------- | ----------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | -| Bundle | Compose your own `loadAppBundle(engine)` and call internal loaders | Call `await loadAppBundle(tsParticles)` before `tsParticles.load(...)` | -| Effect | Register with `pluginManager.addEffect("app-*", drawer)` | Set `particles.effect.type` to your effect id | -| Interaction | Register with `pluginManager.addInteractor("app-*", interactor)` | Enable in `interactivity.events` / optional custom mode checks | -| Palette | Register with `pluginManager.addPalette("app-*", palette)` | Set `particles.palette` to your palette id | -| Path | Register with `pluginManager.addPathGenerator("app-*", generator)` | Set `particles.move.path.generator` to your path id | -| Plugin | Create `IPlugin` + `IContainerPlugin` and call `engine.addPlugin(...)` | Enable with your plugin options and lifecycle hooks | -| Preset | Register with `tsParticles.addPreset("app-*", options)` | Set root `preset` | -| Shape | Register with `tsParticles.addShape("app-*", drawer)` or load all official shape packages | Set `particles.shape.type` and per-shape `particles.shape.options` | -| Updater | Register with `pluginManager.addParticleUpdater("app-*", updater)` | Runs automatically on particles where `isEnabled(...)` returns `true` | - -## Quick app-local creation + usage by extension type - -All snippets assume this setup order: - -```ts -await loadSlim(tsParticles); -// register custom pieces -await tsParticles.load({ id: "tsparticles", options }); -``` - -### Bundle - -Create a tiny app bundle that wires exactly the pieces you want. - -```ts -import type { Engine } from "@tsparticles/engine"; -import { loadSlim } from "@tsparticles/slim"; - -export async function loadAppBundle(engine: Engine): Promise { - await loadSlim(engine); - - await Promise.all([ - loadAppShape(engine), - loadAppPreset(), - loadAppPalette(engine), - loadAppEffect(engine), - loadAppPath(engine), - loadAppUpdater(engine), - loadAppInteraction(engine), - loadAppPlugin(engine), - ]); -} - -await loadAppBundle(tsParticles); -``` - -### Effect - -```ts -import type { Engine } from "@tsparticles/engine"; - -export async function loadAppEffect(engine: Engine): Promise { - await engine.pluginManager.register((e) => { - e.pluginManager.addEffect("app-fade", () => - Promise.resolve({ - drawBefore: ({ context }) => { - context.save(); - context.globalAlpha *= 0.85; - }, - drawAfter: ({ context }) => { - context.restore(); - }, - }), - ); - }); -} - -await loadAppEffect(tsParticles); - -const options = { - particles: { - effect: { - type: "app-fade", - }, - }, -}; -``` - -### Interactions (external and particles) - -```ts -import { - ExternalInteractorBase, - loadInteractivityPlugin, - type IInteractivityData, -} from "@tsparticles/plugin-interactivity"; -import type { Engine, IDelta } from "@tsparticles/engine"; - -class AppHoverPauseInteractor extends ExternalInteractorBase { - readonly maxDistance = 0; - - clear(): void {} - - init(): void {} - - interact(interactivityData: IInteractivityData, _delta: IDelta): void { - if (interactivityData.pointer?.position) { - this.container.pause(); - } - } - - isEnabled(interactivityData: IInteractivityData): boolean { - return !!interactivityData.pointer?.position; - } - - reset(): void { - this.container.play(); - } -} - -export async function loadAppInteraction(engine: Engine): Promise { - await loadInteractivityPlugin(engine); - - await engine.pluginManager.register((e) => { - e.pluginManager.addInteractor?.("app-hover-pause", (container) => { - return Promise.resolve(new AppHoverPauseInteractor(container)); - }); - }); -} - -await loadAppInteraction(tsParticles); - -const options = { - interactivity: { - events: { - onHover: { - enable: true, - }, - }, - }, -}; -``` - -### Palette - -```ts -import type { Engine, IPalette } from "@tsparticles/engine"; - -const appPalette: IPalette = { - name: "App Sunset", - blendMode: "multiply", - colors: { - fill: { - enable: true, - value: ["#ff6b6b", "#ffd166", "#4ecdc4"], - }, - }, -}; - -export async function loadAppPalette(engine: Engine): Promise { - await engine.pluginManager.register((e) => { - e.pluginManager.addPalette("app-sunset", appPalette); - }); -} - -await loadAppPalette(tsParticles); - -const options = { - particles: { - palette: "app-sunset", - }, -}; -``` - -### Path - -```ts -import { loadMovePlugin } from "@tsparticles/plugin-move"; -import { Vector, type Engine } from "@tsparticles/engine"; - -export async function loadAppPath(engine: Engine): Promise { - await loadMovePlugin(engine); - - await engine.pluginManager.register((e) => { - e.pluginManager.addPathGenerator?.("app-sway", () => - Promise.resolve({ - generate: (particle) => { - const wave = Math.sin(particle.position.y * 0.02); - - return Vector.create(wave, 0); - }, - init: () => {}, - reset: () => {}, - update: () => {}, - }), - ); - }); -} - -await loadAppPath(tsParticles); - -const options = { - particles: { - move: { - enable: true, - path: { - enable: true, - generator: "app-sway", - }, - }, - }, -}; -``` - -### Plugin - -```ts -import type { Container, Engine, IContainerPlugin, IPlugin, ISourceOptions, Options } from "@tsparticles/engine"; - -class AppPluginInstance implements IContainerPlugin { - private readonly container: Container; - - constructor(container: Container) { - this.container = container; - } - - async init(): Promise { - this.container.retina.pixelRatio = Math.max(this.container.retina.pixelRatio, 1); - } -} - -class AppPlugin implements IPlugin { - readonly id = "app-plugin"; - - async getPlugin(container: Container): Promise { - return new AppPluginInstance(container); - } - - loadOptions(_options: Options, source?: ISourceOptions): void { - if (source?.appPlugin === false) { - return; - } - } - - needsPlugin(source?: ISourceOptions): boolean { - return source?.appPlugin !== false; - } -} - -export async function loadAppPlugin(engine: Engine): Promise { - await engine.addPlugin(new AppPlugin()); -} - -await loadAppPlugin(tsParticles); - -const options = { - appPlugin: true, -}; -``` - -### Preset - -```ts -import { tsParticles } from "@tsparticles/engine"; - -export async function loadAppPreset(): Promise { - tsParticles.addPreset("app-hero", { - fpsLimit: 60, - particles: { - number: { value: 80 }, - move: { enable: true, speed: 2 }, - links: { enable: true, distance: 140 }, - }, - }); -} - -await loadAppPreset(); - -const options = { - preset: "app-hero", -}; -``` - -### Shape - -```ts -import type { Engine } from "@tsparticles/engine"; -import { loadArrowShape } from "@tsparticles/shape-arrow"; -import { loadCardsShape } from "@tsparticles/shape-cards"; -import { loadCircleShape } from "@tsparticles/shape-circle"; -import { loadCogShape } from "@tsparticles/shape-cog"; -import { loadEmojiShape } from "@tsparticles/shape-emoji"; -import { loadHeartShape } from "@tsparticles/shape-heart"; -import { loadImageShape, type ImageEngine } from "@tsparticles/shape-image"; -import { loadInfinityShape } from "@tsparticles/shape-infinity"; -import { loadLineShape } from "@tsparticles/shape-line"; -import { loadMatrixShape } from "@tsparticles/shape-matrix"; -import { loadPathShape } from "@tsparticles/shape-path"; -import { loadPolygonShape } from "@tsparticles/shape-polygon"; -import { loadRoundedPolygonShape } from "@tsparticles/shape-rounded-polygon"; -import { loadRoundedRectShape } from "@tsparticles/shape-rounded-rect"; -import { loadSpiralShape } from "@tsparticles/shape-spiral"; -import { loadSquareShape } from "@tsparticles/shape-square"; -import { loadSquircleShape } from "@tsparticles/shape-squircle"; -import { loadStarShape } from "@tsparticles/shape-star"; -import { loadTextShape } from "@tsparticles/shape-text"; - -export async function loadAppShape(engine: Engine): Promise { - await Promise.all([ - loadArrowShape(engine), - loadCardsShape(engine), - loadCircleShape(engine), - loadCogShape(engine), - loadEmojiShape(engine), - loadHeartShape(engine), - loadImageShape(engine as ImageEngine), - loadInfinityShape(engine), - loadLineShape(engine), - loadMatrixShape(engine), - loadPathShape(engine), - loadPolygonShape(engine), - loadRoundedPolygonShape(engine), - loadRoundedRectShape(engine), - loadSpiralShape(engine), - loadSquareShape(engine), - loadSquircleShape(engine), - loadStarShape(engine), - loadTextShape(engine), - ]); -} - -await loadAppShape(tsParticles); - -/* For granular loading, you can import only the shapes you need: - * - @tsparticles/shape-cards/clubs, /diamonds, /hearts, /spades, /suits, /cards - * - @tsparticles/shape-polygon: loadGenericPolygonShape or loadTriangleShape - */ - -const options = { - particles: { - paint: { - stroke: { - width: 2, - }, - }, - shape: { - type: [ - "arrow", - "card", - "circle", - "club", - "cog", - "diamond", - "emoji", - "heart", - "hearts", - "image", - "images", - "infinity", - "line", - "matrix", - "path", - "polygon", - "rounded-polygon", - "rounded-rect", - "spade", - "spades", - "spiral", - "edge", - "square", - "squircle", - "star", - "text", - "character", - "char", - "multiline-text", - "triangle", - "clubs", - "diamonds", - ], - options: { - image: { - src: "https://particles.js.org/images/hdr/fruits/cherry.png", - width: 32, - height: 32, - replaceColor: false, - }, - line: { - close: false, - fill: false, - }, - path: { - close: true, - d: "M 0,-14 L 10,14 L -10,14 Z", - }, - polygon: { - sides: 6, - }, - "rounded-polygon": { - sides: 6, - radius: 0.25, - }, - "rounded-rect": { - width: 20, - height: 14, - radius: 3, - }, - spiral: { - innerRadius: 1, - lineSpacing: 1, - }, - star: { - sides: 5, - inset: 2, - }, - text: { - value: ["TS", "Particles"], - font: "Verdana", - }, - }, - }, - }, -}; -``` - -`line` shape is stroke-driven, so keep `fill: false` and configure `particles.paint.stroke`. - -The `image.src` URL above is reused from existing project configs (`utils/configs`). - -### Updater - -```ts -import type { Engine, IDelta, Particle } from "@tsparticles/engine"; - -export async function loadAppUpdater(engine: Engine): Promise { - await engine.pluginManager.register((e) => { - e.pluginManager.addParticleUpdater("app-drift", () => - Promise.resolve({ - init: (): void => {}, - isEnabled: (): boolean => true, - update: (particle: Particle, delta: IDelta): void => { - particle.position.x += 0.02 * delta.factor; - }, - }), - ); - }); -} - -await loadAppUpdater(tsParticles); - -// no extra options required: updater runs when isEnabled(...) is true -``` - -This is enough to prototype every extension type locally, then extract to dedicated packages later. +| Type | What it does | How to use | +| ------------------------------------------------------- | ------------------------------------------------------------------------ | --------------------------------------------------------------------- | +| [Plugin](/guide/plugins-customization-plugin) | Container/runtime feature module (emitters, absorbers, polygon mask) | Enable with your plugin options and lifecycle hooks | +| [Shape](/guide/plugins-customization-shape) | Particle drawing primitive (`particles.shape.type`) | Set `particles.shape.type` to your shape id | +| [Preset](/guide/plugins-customization-preset) | Reusable full options profile (`preset`) | Set root `preset` | +| [Updater](/guide/plugins-customization-updater) | Per-frame particle property updater (tilt, roll, opacity, size) | Runs automatically where `isEnabled` returns `true` | +| [Effect](/guide/plugins-customization-effect) | Particle rendering effect (`particles.effect`) | Set `particles.effect.type` to your effect id | +| [Interaction](/guide/plugins-customization-interaction) | Behavior between particles and events (mouse/touch or particle-particle) | Enable in `interactivity.events` / optional custom mode checks | +| [Path](/guide/plugins-customization-path) | Motion path generator for particle movement (`particles.move.path`) | Set `particles.move.path.generator` to your path id | +| [Palette](/guide/plugins-customization-palette) | Reusable style/colors profile (`particles.palette`) | Set `particles.palette` to your palette id | +| [Custom Bundle](/guide/plugins-customization-bundle) | Grouped loader that registers many features at once | Call `await loadMyBundle(tsParticles)` before `tsParticles.load(...)` | ## Composition strategy @@ -489,7 +36,6 @@ This is enough to prototype every extension type locally, then extract to dedica - Keep a tiny config fixture while developing (faster regressions checks). - If a feature is missing, verify the required package is loaded (shape, interaction, updater, plugin). -## Source reference +## Next steps -- Plugin interface docs: -- Extended markdown guide: +Choose an extension type above for step-by-step guides with inline code and package creation instructions. diff --git a/websites/website/docs/hi/migrations/from-v3.md b/websites/website/docs/hi/migrations/from-v3.md index 7a565ef27d1..d592c66d866 100644 --- a/websites/website/docs/hi/migrations/from-v3.md +++ b/websites/website/docs/hi/migrations/from-v3.md @@ -11,13 +11,13 @@ कुछ `v3.x` पैकेजों का नाम बदल दिया गया है या पुनर्गठित किया गया है: -| v3 पैकेज | वर्तमान पैकेज | नोट | -| ----------------------------------- | ------------------------------- | ------------------------------------------------ | -| `@tsparticles/move-base` | `@tsparticles/plugin-move` | एकल प्लगइन में विलय | -| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | एकल प्लगइन में विलय | -| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | paint सिस्टम से बदला गया | -| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | paint सिस्टम से बदला गया | -| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | `plugins/colors/hsv/` में स्थानांतरित, same name | +| v3 पैकेज | वर्तमान पैकेज | नोट | +| ----------------------------------- | ----------------------------------- | --------------------------------------------------------------------------- | +| `@tsparticles/move-base` | `@tsparticles/plugin-move` | एकल प्लगइन में विलय | +| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | एकल प्लगइन में विलय | +| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | paint सिस्टम से बदला गया | +| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | paint सिस्टम से बदला गया | +| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | `plugins/colors/hsv/` में स्थानांतरित, same name | | (v3 में आवश्यक नहीं - अंतर्निर्मित) | `@tsparticles/plugin-interactivity` | सभी इंटरैक्शन प्लगइन (grab, bubble, repulse, आदि) के काम करने के लिए आवश्यक | ## ऑप्शन मैपिंग उदाहरण diff --git a/websites/website/docs/it/migrations/from-v3.md b/websites/website/docs/it/migrations/from-v3.md index 532779127af..238a6897620 100644 --- a/websites/website/docs/it/migrations/from-v3.md +++ b/websites/website/docs/it/migrations/from-v3.md @@ -11,14 +11,14 @@ Da `v3.x`, i rischi principali in migrazione sono la **compatibilità delle opzi Alcuni pacchetti di `v3.x` sono stati rinominati o ristrutturati: -| Pacchetto v3 | Pacchetto attuale | Note | -| ----------------------------------- | ------------------------------- | ---------------------------------------------- | -| `@tsparticles/move-base` | `@tsparticles/plugin-move` | Uniti in un singolo plugin | -| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | Uniti in un singolo plugin | -| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Sostituito dal sistema paint | -| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Sostituito dal sistema paint | -| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Spostato in `plugins/colors/hsv/`, stesso nome | -| (non necessario in v3 - integrato) | `@tsparticles/plugin-interactivity` | Necessario per far funzionare qualsiasi plugin di interazione (grab, bubble, repulse, ecc.) | +| Pacchetto v3 | Pacchetto attuale | Note | +| ----------------------------------- | ----------------------------------- | ------------------------------------------------------------------------------------------- | +| `@tsparticles/move-base` | `@tsparticles/plugin-move` | Uniti in un singolo plugin | +| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | Uniti in un singolo plugin | +| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Sostituito dal sistema paint | +| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Sostituito dal sistema paint | +| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Spostato in `plugins/colors/hsv/`, stesso nome | +| (non necessario in v3 - integrato) | `@tsparticles/plugin-interactivity` | Necessario per far funzionare qualsiasi plugin di interazione (grab, bubble, repulse, ecc.) | ## Esempi mappatura opzioni diff --git a/websites/website/docs/ja/migrations/from-v3.md b/websites/website/docs/ja/migrations/from-v3.md index 8e225c465b5..953dd3cb97b 100644 --- a/websites/website/docs/ja/migrations/from-v3.md +++ b/websites/website/docs/ja/migrations/from-v3.md @@ -11,14 +11,14 @@ 一部の `v3.x` パッケージは名称変更または再構成されました: -| v3 パッケージ | 現在のパッケージ | 備考 | -| ----------------------------------- | ------------------------------- | ---------------------------------------- | -| `@tsparticles/move-base` | `@tsparticles/plugin-move` | 1つのプラグインに統合 | -| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | 1つのプラグインに統合 | -| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | paint システムに置き換え | -| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | paint システムに置き換え | -| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | `plugins/colors/hsv/` に移動、名前は同じ | -| (v3では不要 - 組み込み) | `@tsparticles/plugin-interactivity` | すべてのインタラクションプラグイン(grab, bubble, repulseなど)の動作に必要 | +| v3 パッケージ | 現在のパッケージ | 備考 | +| ----------------------------------- | ----------------------------------- | --------------------------------------------------------------------------- | +| `@tsparticles/move-base` | `@tsparticles/plugin-move` | 1つのプラグインに統合 | +| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | 1つのプラグインに統合 | +| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | paint システムに置き換え | +| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | paint システムに置き換え | +| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | `plugins/colors/hsv/` に移動、名前は同じ | +| (v3では不要 - 組み込み) | `@tsparticles/plugin-interactivity` | すべてのインタラクションプラグイン(grab, bubble, repulseなど)の動作に必要 | ## オプション対応例 diff --git a/websites/website/docs/migrations/from-v3.md b/websites/website/docs/migrations/from-v3.md index 1dfa2ff0baa..3af8f0c8758 100644 --- a/websites/website/docs/migrations/from-v3.md +++ b/websites/website/docs/migrations/from-v3.md @@ -78,13 +78,13 @@ await tsParticles.load({ Some `v3.x` packages have been renamed or restructured: -| v3 package | Current package | Note | -| ----------------------------------- | ------------------------------- | ----------------------------------------------------------- | -| `@tsparticles/move-base` | `@tsparticles/plugin-move` | Merged into single plugin | -| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | Merged into single plugin | -| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Replaced by paint system | -| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Replaced by paint system | -| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Moved to `plugins/colors/hsv/`, still the same package name | +| v3 package | Current package | Note | +| ----------------------------------- | ----------------------------------- | -------------------------------------------------------------------------- | +| `@tsparticles/move-base` | `@tsparticles/plugin-move` | Merged into single plugin | +| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | Merged into single plugin | +| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Replaced by paint system | +| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Replaced by paint system | +| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Moved to `plugins/colors/hsv/`, still the same package name | | (not needed in v3 - built-in) | `@tsparticles/plugin-interactivity` | Required for all interaction plugins (grab, bubble, repulse, etc.) to work | ## Recommended steps diff --git a/websites/website/docs/pt/migrations/from-v3.md b/websites/website/docs/pt/migrations/from-v3.md index b773925c14b..9e06ebc8190 100644 --- a/websites/website/docs/pt/migrations/from-v3.md +++ b/websites/website/docs/pt/migrations/from-v3.md @@ -11,13 +11,13 @@ Em `v3.x`, os maiores riscos de migracao sao a **compatibilidade das opcoes** e Alguns pacotes `v3.x` foram renomeados ou reestruturados: -| Pacote v3 | Pacote atual | Nota | -| ----------------------------------- | ------------------------------- | --------------------------------------------- | -| `@tsparticles/move-base` | `@tsparticles/plugin-move` | Unificados em um unico plugin | -| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | Unificados em um unico plugin | -| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Substituido pelo sistema paint | -| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Substituido pelo sistema paint | -| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Movido para `plugins/colors/hsv/`, mesmo nome | +| Pacote v3 | Pacote atual | Nota | +| ----------------------------------- | ----------------------------------- | --------------------------------------------------------------------------------------- | +| `@tsparticles/move-base` | `@tsparticles/plugin-move` | Unificados em um unico plugin | +| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | Unificados em um unico plugin | +| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Substituido pelo sistema paint | +| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Substituido pelo sistema paint | +| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Movido para `plugins/colors/hsv/`, mesmo nome | | (nao necessario no v3 - integrado) | `@tsparticles/plugin-interactivity` | Necessario para todos os plugins de interacao (grab, bubble, repulse, etc.) funcionarem | ## Exemplos de mapeamento de opcoes diff --git a/websites/website/docs/ru/migrations/from-v3.md b/websites/website/docs/ru/migrations/from-v3.md index f11fd9e7e8d..11a37040800 100644 --- a/websites/website/docs/ru/migrations/from-v3.md +++ b/websites/website/docs/ru/migrations/from-v3.md @@ -11,13 +11,13 @@ Некоторые пакеты `v3.x` были переименованы или реструктурированы: -| Пакет v3 | Текущий пакет | Примечание | -| ----------------------------------- | ------------------------------- | -------------------------------------------- | -| `@tsparticles/move-base` | `@tsparticles/plugin-move` | Объединены в один плагин | -| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | Объединены в один плагин | -| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Заменён системой paint | -| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Заменён системой paint | -| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Перемещён в `plugins/colors/hsv/`, то же имя | +| Пакет v3 | Текущий пакет | Примечание | +| ----------------------------------- | ----------------------------------- | -------------------------------------------------------------------------------- | +| `@tsparticles/move-base` | `@tsparticles/plugin-move` | Объединены в один плагин | +| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | Объединены в один плагин | +| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | Заменён системой paint | +| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | Заменён системой paint | +| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | Перемещён в `plugins/colors/hsv/`, то же имя | | (не нужно в v3 - встроено) | `@tsparticles/plugin-interactivity` | Требуется для работы всех плагинов взаимодействия (grab, bubble, repulse и т.д.) | ## Примеры соответствия опций diff --git a/websites/website/docs/zh/migrations/from-v3.md b/websites/website/docs/zh/migrations/from-v3.md index 01149903f25..5515ba03561 100644 --- a/websites/website/docs/zh/migrations/from-v3.md +++ b/websites/website/docs/zh/migrations/from-v3.md @@ -11,13 +11,13 @@ 部分 `v3.x` 包已重命名或重组: -| v3 包 | 当前包 | 说明 | -| ----------------------------------- | ------------------------------- | -------------------------------------- | -| `@tsparticles/move-base` | `@tsparticles/plugin-move` | 合并为单个插件 | -| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | 合并为单个插件 | -| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | 被 paint 系统取代 | -| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | 被 paint 系统取代 | -| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | 移动到 `plugins/colors/hsv/`,名称不变 | +| v3 包 | 当前包 | 说明 | +| ----------------------------------- | ----------------------------------- | ------------------------------------------------------ | +| `@tsparticles/move-base` | `@tsparticles/plugin-move` | 合并为单个插件 | +| `@tsparticles/move-parallax` | `@tsparticles/plugin-move` | 合并为单个插件 | +| `@tsparticles/updater-color` | `@tsparticles/updater-paint` | 被 paint 系统取代 | +| `@tsparticles/updater-stroke-color` | `@tsparticles/updater-paint` | 被 paint 系统取代 | +| `@tsparticles/plugin-hsv-color` | `@tsparticles/plugin-hsv-color` | 移动到 `plugins/colors/hsv/`,名称不变 | | (v3 中不需要 - 内置) | `@tsparticles/plugin-interactivity` | 所有交互插件(grab, bubble, repulse 等)正常工作所必需 | ## 选项映射示例 diff --git a/wrappers/svelte/CHANGELOG.md b/wrappers/svelte/CHANGELOG.md index e65ce413730..6d4467c9570 100644 --- a/wrappers/svelte/CHANGELOG.md +++ b/wrappers/svelte/CHANGELOG.md @@ -7,10 +7,6 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline **Note:** Version bump only for package @tsparticles/svelte - - - - ## [4.0.3](https://github.com/tsparticles/tsparticles/compare/v4.0.2...v4.0.3) (2026-05-18) **Note:** Version bump only for package @tsparticles/svelte From bcaa9e137bb8510f6aeed32a791bd91820264e60 Mon Sep 17 00:00:00 2001 From: Matteo Bruni <176620+matteobruni@users.noreply.github.com> Date: Tue, 19 May 2026 14:26:56 +0200 Subject: [PATCH 03/10] build: updated pnpm --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d944abe7971..e95d7c5f33a 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "webpack-cli": "^7.0.2", "yargs": "^18.0.0" }, - "packageManager": "pnpm@11.1.2", + "packageManager": "pnpm@11.1.3", "pnpm": { "overrides": { "@nuxt/vue-app@2.18.1>vue": "2.7.16", From 5a9f3184c234a4d80c9f5b92e37c44543df17e6c Mon Sep 17 00:00:00 2001 From: Matteo Bruni <176620+matteobruni@users.noreply.github.com> Date: Tue, 19 May 2026 15:15:09 +0200 Subject: [PATCH 04/10] build: updated websites --- websites/confetti/index.html | 19 +++++ websites/confetti/src/cookie-consent.js | 85 ++++--------------- websites/website/docs/.vitepress/config.ts | 57 +++++++++++++ .../docs/.vitepress/theme/tracking/runtime.ts | 44 +++++----- 4 files changed, 114 insertions(+), 91 deletions(-) diff --git a/websites/confetti/index.html b/websites/confetti/index.html index 134bd7ee40e..0a0eb994cf8 100644 --- a/websites/confetti/index.html +++ b/websites/confetti/index.html @@ -20,6 +20,25 @@ + + + + + diff --git a/websites/confetti/src/cookie-consent.js b/websites/confetti/src/cookie-consent.js index ebb58af0044..8802b55d458 100644 --- a/websites/confetti/src/cookie-consent.js +++ b/websites/confetti/src/cookie-consent.js @@ -10,9 +10,7 @@ const defaultConsent = { }; let consent = readConsent(); -let analyticsInitialized = false; let adsenseInitialized = false; -let consentDefaultsInitialized = false; let initialPageViewTracked = false; function readConsent() { @@ -66,40 +64,11 @@ function loadScript(id, src, attributes) { document.head.appendChild(script); } -function ensureGtagStub() { - window.dataLayer = window.dataLayer || []; - window.gtag = - window.gtag || - function () { - window.dataLayer.push(arguments); - }; -} - -function initAnalytics() { - if (analyticsInitialized) { - return; - } - - ensureGtagStub(); - initConsentDefaults(); - loadScript('ga-script', `https://www.googletagmanager.com/gtag/js?id=${GA_MEASUREMENT_ID}`); - window.gtag('js', new Date()); - window.gtag('config', GA_MEASUREMENT_ID, { - send_page_view: false, - }); - - analyticsInitialized = true; -} - function initAdSense() { if (adsenseInitialized) { return; } - // Auto-ads are configured via the AdSense dashboard and activated automatically - // by the script when loaded with ?client=ca-pub-XXXXX — no manual push needed. - // Pushing enable_page_level_ads manually conflicts with the script's own init - // and causes "Only one 'enable_page_level_ads' allowed per page" TagError. loadScript( 'adsense-script', `https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=${ADSENSE_CLIENT_ID}`, @@ -113,35 +82,6 @@ function initAdSense() { adsenseInitialized = true; } -function initConsentDefaults() { - if (consentDefaultsInitialized) { - return; - } - - ensureGtagStub(); - - window.gtag('consent', 'default', { - ad_storage: 'denied', - analytics_storage: 'denied', - ad_user_data: 'denied', - ad_personalization: 'denied', - }); - - consentDefaultsInitialized = true; -} - -function updateConsentMode(activeConsent) { - initConsentDefaults(); - ensureGtagStub(); - - window.gtag('consent', 'update', { - ad_storage: activeConsent.adsense ? 'granted' : 'denied', - analytics_storage: activeConsent.analytics ? 'granted' : 'denied', - ad_user_data: activeConsent.adsense ? 'granted' : 'denied', - ad_personalization: activeConsent.adsense ? 'granted' : 'denied', - }); -} - function updateAdSensePersonalization(activeConsent) { window.adsbygoogle = window.adsbygoogle || []; window.adsbygoogle.requestNonPersonalizedAds = @@ -153,27 +93,36 @@ function canTrackAnalytics(activeConsent) { } function trackInitialPageView(activeConsent) { - if (initialPageViewTracked || !canTrackAnalytics(activeConsent) || !globalThis.gtag) { + if (initialPageViewTracked || !canTrackAnalytics(activeConsent) || !window.gtag) { return; } - globalThis.gtag('event', 'page_view', { - page_location: globalThis.location.href, - page_path: globalThis.location.pathname, + window.gtag('event', 'page_view', { + page_location: window.location.href, + page_path: window.location.pathname, page_title: document.title, }); initialPageViewTracked = true; } +function updateConsentMode(activeConsent) { + if (!window.gtag) { + return; + } + + window.gtag('consent', 'update', { + ad_storage: activeConsent.adsense ? 'granted' : 'denied', + analytics_storage: activeConsent.analytics ? 'granted' : 'denied', + ad_user_data: activeConsent.adsense ? 'granted' : 'denied', + ad_personalization: activeConsent.adsense ? 'granted' : 'denied', + }); +} + function applyConsent(activeConsent) { updateConsentMode(activeConsent); updateAdSensePersonalization(activeConsent); - if (canTrackAnalytics(activeConsent)) { - initAnalytics(); - } - trackInitialPageView(activeConsent); if (activeConsent.adsense || ADSENSE_NON_PERSONALIZED_ON_REJECT) { diff --git a/websites/website/docs/.vitepress/config.ts b/websites/website/docs/.vitepress/config.ts index 0903400ad6f..3852e1118a7 100644 --- a/websites/website/docs/.vitepress/config.ts +++ b/websites/website/docs/.vitepress/config.ts @@ -1,8 +1,36 @@ import { defineConfig, type DefaultTheme } from "vitepress"; +import { readFileSync } from "fs"; +import { resolve, dirname } from "path"; +import { fileURLToPath } from "url"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); const base = process.env.VITEPRESS_BASE ?? "/"; const hostname = "https://particles.js.org"; +const envPath = resolve(__dirname, "../../.env"); + +let gaMeasurementId = process.env.VITE_GA_MEASUREMENT_ID ?? ""; + +if (!gaMeasurementId) { + try { + const envContent = readFileSync(envPath, "utf8"); + + for (const line of envContent.split("\n")) { + const trimmed = line.trim(); + + if (trimmed && !trimmed.startsWith("#") && trimmed.startsWith("VITE_GA_MEASUREMENT_ID=")) { + gaMeasurementId = trimmed.split("=").slice(1).join("=").trim(); + + break; + } + } + } catch { + // .env file not available + } +} + const nav: DefaultTheme.NavItem[] = [ { text: "Start", link: "/guide/getting-started" }, { text: "Playground", link: "/playground/" }, @@ -449,6 +477,35 @@ export default defineConfig({ ["meta", { property: "og:type", content: "website" }], ["meta", { property: "og:title", content: "tsParticles" }], ["meta", { property: "og:description", content: "TypeScript particle engine for websites and apps" }], + ...(gaMeasurementId + ? [ + [ + "script", + {}, + ` +window.dataLayer = window.dataLayer || []; +function gtag(){dataLayer.push(arguments);} +gtag("consent", "default", { + ad_storage: "denied", + analytics_storage: "denied", + ad_user_data: "denied", + ad_personalization: "denied", +}); +`, + ], + ["script", { async: "", src: `https://www.googletagmanager.com/gtag/js?id=${gaMeasurementId}`, id: "tsparticles-ga-loader" }], + [ + "script", + {}, + ` +gtag("js", new Date()); +gtag("config", "${gaMeasurementId}", { + send_page_view: false, +}); +`, + ], + ] + : []), ], themeConfig: { logo: "https://particles.js.org/tsParticles-64.png", diff --git a/websites/website/docs/.vitepress/theme/tracking/runtime.ts b/websites/website/docs/.vitepress/theme/tracking/runtime.ts index 4b5a1283d98..0777f0d31af 100644 --- a/websites/website/docs/.vitepress/theme/tracking/runtime.ts +++ b/websites/website/docs/.vitepress/theme/tracking/runtime.ts @@ -15,27 +15,6 @@ let adSenseInitialized = false; let consentApplied: CookieConsentPreferences | undefined; let consentDefaultsInitialized = false; -function initConsentModeDefaults(): void { - if (consentDefaultsInitialized) { - return; - } - - const trackingWindow = ensureGtagStub(); - - if (!trackingWindow?.gtag) { - return; - } - - trackingWindow.gtag("consent", "default", { - ad_storage: "denied", - analytics_storage: "denied", - ad_user_data: "denied", - ad_personalization: "denied", - }); - - consentDefaultsInitialized = true; -} - function getTrackingWindow(): TrackingWindow | undefined { if (typeof globalThis.window === "undefined") { return undefined; @@ -62,6 +41,27 @@ function ensureGtagStub(): TrackingWindow | undefined { return trackingWindow; } +function initConsentModeDefaults(): void { + if (consentDefaultsInitialized) { + return; + } + + const trackingWindow = ensureGtagStub(); + + if (!trackingWindow?.gtag) { + return; + } + + trackingWindow.gtag("consent", "default", { + ad_storage: "denied", + analytics_storage: "denied", + ad_user_data: "denied", + ad_personalization: "denied", + }); + + consentDefaultsInitialized = true; +} + function loadScriptOnce(id: string, src: string): void { const trackingWindow = getTrackingWindow(); @@ -82,8 +82,6 @@ function initGoogleAnalytics(): void { return; } - initConsentModeDefaults(); - const trackingWindow = ensureGtagStub(); if (!trackingWindow) { From 78d2914bd51990c8e2787e578aa44ee1aecabf77 Mon Sep 17 00:00:00 2001 From: Matteo Bruni <176620+matteobruni@users.noreply.github.com> Date: Tue, 19 May 2026 15:22:10 +0200 Subject: [PATCH 05/10] build: post build format --- websites/confetti/index.html | 10 ++++++++-- websites/website/docs/.vitepress/config.ts | 9 ++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/websites/confetti/index.html b/websites/confetti/index.html index 0a0eb994cf8..38a85f69bb2 100644 --- a/websites/confetti/index.html +++ b/websites/confetti/index.html @@ -24,7 +24,9 @@ - +