├── .changeset
├── README.md
└── config.json
├── .editorconfig
├── .gitattributes
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.yml
│ ├── feature_request.yml
│ └── question_request.yml
├── PULL_REQUEST_TEMPLATE.md
└── workflows
│ └── gh-pages.yml
├── .gitignore
├── .npmrc
├── .prettierignore
├── .prettierrc.cjs
├── .vscode
└── extensions.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── examples
├── basic
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── index.ts
│ │ ├── style.css
│ │ └── vite-env.d.ts
│ └── tsconfig.json
├── with-angular
│ ├── .browserslistrc
│ ├── angular.json
│ ├── package.json
│ ├── src
│ │ ├── app
│ │ │ ├── app.component.css
│ │ │ ├── app.component.html
│ │ │ ├── app.component.ts
│ │ │ └── app.module.ts
│ │ ├── environments
│ │ │ ├── environment.prod.ts
│ │ │ └── environment.ts
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── main.ts
│ │ ├── polyfills.ts
│ │ └── styles.css
│ ├── tsconfig.app.json
│ └── tsconfig.json
├── with-preact
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── App.tsx
│ │ ├── index.tsx
│ │ ├── preact.d.ts
│ │ └── vite-env.d.ts
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── with-react
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── App.tsx
│ │ ├── index.tsx
│ │ └── vite-env.d.ts
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── with-solid
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── App.tsx
│ │ ├── index.tsx
│ │ └── vite-end.d.ts
│ ├── tsconfig.json
│ └── vite.config.ts
├── with-svelte
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── App.svelte
│ │ ├── index.ts
│ │ └── shim.d.ts
│ ├── svelte.config.js
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ └── vite.config.ts
├── with-vue
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── App.vue
│ │ ├── index.ts
│ │ └── shim.d.ts
│ ├── tsconfig.json
│ └── vite.config.js
└── with-web-components
│ ├── index.html
│ ├── package.json
│ ├── src
│ └── index.ts
│ └── tsconfig.json
├── package.json
├── packages
├── angular
│ ├── README.md
│ ├── angular.json
│ ├── package.json
│ ├── projects
│ │ └── ng-fireworks
│ │ │ ├── .browserslistrc
│ │ │ ├── ng-package.json
│ │ │ ├── package.json
│ │ │ ├── src
│ │ │ ├── lib
│ │ │ │ ├── ng-fireworks.directive.ts
│ │ │ │ └── ng-fireworks.module.ts
│ │ │ └── public-api.ts
│ │ │ ├── tsconfig.lib.json
│ │ │ └── tsconfig.lib.prod.json
│ └── tsconfig.json
├── fireworks-js
│ ├── README.md
│ ├── package.json
│ ├── src
│ │ ├── explosion.ts
│ │ ├── fireworks.ts
│ │ ├── helpers.ts
│ │ ├── index.ts
│ │ ├── mouse.ts
│ │ ├── options.ts
│ │ ├── raf.ts
│ │ ├── resize.ts
│ │ ├── sound.ts
│ │ ├── trace.ts
│ │ └── types.ts
│ ├── tsconfig.json
│ └── vite.config.ts
├── preact
│ ├── README.md
│ ├── package.json
│ ├── src
│ │ ├── index.tsx
│ │ └── preact.d.ts
│ ├── tsconfig.json
│ └── vite.config.ts
├── react
│ ├── README.md
│ ├── package.json
│ ├── src
│ │ └── index.tsx
│ ├── tsconfig.json
│ └── vite.config.ts
├── solid
│ ├── README.md
│ ├── package.json
│ ├── src
│ │ └── index.tsx
│ ├── tsconfig.json
│ └── vite.config.ts
├── svelte
│ ├── README.md
│ ├── package.json
│ ├── src
│ │ ├── app.d.ts
│ │ ├── app.html
│ │ ├── lib
│ │ │ ├── fireworks.svelte
│ │ │ └── index.ts
│ │ └── routes
│ │ │ └── +page.svelte
│ ├── static
│ │ └── favicon.png
│ ├── svelte.config.js
│ ├── tsconfig.json
│ └── vite.config.ts
├── vue
│ ├── README.md
│ ├── package.json
│ ├── src
│ │ ├── fireworks.vue
│ │ ├── index.ts
│ │ └── shim.d.ts
│ ├── tsconfig.json
│ └── vite.config.ts
└── web
│ ├── README.md
│ ├── package.json
│ ├── src
│ └── index.ts
│ ├── tsconfig.json
│ └── vite.config.ts
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── turbo.json
└── website
├── index.html
├── package.json
├── public
├── CNAME
├── images
│ ├── fireworks_banner.gif
│ ├── fireworks_emoji.gif
│ └── fireworks_emoji.png
├── index.css
└── sounds
│ ├── explosion0.mp3
│ ├── explosion1.mp3
│ └── explosion2.mp3
├── src
├── config.ts
└── index.ts
└── tsconfig.json
/.changeset/README.md:
--------------------------------------------------------------------------------
1 | # Changesets
2 |
3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4 | with multi-package repos, or single-package repos to help you version and publish your code. You can
5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6 |
7 | We have a quick list of common questions to get you started engaging with this project in
8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
9 |
--------------------------------------------------------------------------------
/.changeset/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json",
3 | "changelog": "@changesets/cli/changelog",
4 | "commit": false,
5 | "fixed": [],
6 | "linked": [],
7 | "access": "public",
8 | "baseBranch": "master",
9 | "updateInternalDependencies": "patch",
10 | "ignore": [
11 | "website",
12 | "basic",
13 | "with-angular",
14 | "with-preact",
15 | "with-react",
16 | "with-solid",
17 | "with-svelte",
18 | "with-vue",
19 | "with-web-components",
20 | "@fireworks-js/*"
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: https://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | [*]
7 | indent_style = space
8 | indent_size = 2
9 | end_of_line = lf
10 | charset = utf-8
11 | trim_trailing_whitespace = true
12 | insert_final_newline = true
13 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
2 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.yml:
--------------------------------------------------------------------------------
1 | name: 🐛 Bug Report
2 | description: Create a report to help us improve.
3 | labels: bug
4 | assignees: crashmax-dev
5 |
6 | body:
7 | - type: textarea
8 | id: description
9 | attributes:
10 | label: Description
11 | description: A clear and concise description of what the bug is.
12 | validations:
13 | required: true
14 |
15 | - type: dropdown
16 | id: package
17 | attributes:
18 | label: Which package are you using?
19 | multiple: true
20 | options:
21 | - "fireworks-js"
22 | - "@fireworks-js/react"
23 | - "@fireworks-js/preact"
24 | - "@fireworks-js/solid"
25 | - "@fireworks-js/vue"
26 | - "@fireworks-js/svelte"
27 | - "@fireworks-js/angular"
28 | - "@fireworks-js/web"
29 | validations:
30 | required: true
31 |
32 | - type: input
33 | id: version
34 | attributes:
35 | label: fireworks-js version
36 | placeholder: 2.x.x
37 | validations:
38 | required: true
39 |
40 | - type: input
41 | id: browser
42 | attributes:
43 | label: Browser
44 | placeholder: Version 103.0.5060.114 (Official Build) (64-bit)
45 | validations:
46 | required: true
47 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yml:
--------------------------------------------------------------------------------
1 | name: 🚀 Feature Request
2 | description: Submit a proposal for a new feature.
3 | labels: enhancement
4 | assignees: crashmax-dev
5 |
6 | body:
7 | - type: textarea
8 | id: proposal
9 | attributes:
10 | label: Feature Proposal
11 | description: A clear and concise description of what the feature is.
12 | validations:
13 | required: true
14 |
15 | - type: textarea
16 | id: motivation
17 | attributes:
18 | label: Motivation
19 | description: The motivation for the proposal.
20 |
21 | - type: textarea
22 | id: example
23 | attributes:
24 | label: Example
25 | description: |
26 | An example for how this feature would be used.
27 | Make sure you place example code inside a [code (```) block](https://docs.github.com/en/github/writing-on-github/creating-and-highlighting-code-blocks) to avoid linking unrelated issues.
28 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question_request.yml:
--------------------------------------------------------------------------------
1 | name: ❔ Question Request
2 | description: If you have questions.
3 | labels: question
4 | assignees: crashmax-dev
5 |
6 | body:
7 | - type: textarea
8 | id: text
9 | attributes:
10 | label: Issue
11 | description: |
12 | Give as much detail as you can to help us understand.
13 | Make sure you place example code inside a [code (```) block](https://docs.github.com/en/github/writing-on-github/creating-and-highlighting-code-blocks) to avoid linking unrelated issues.
14 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | #### Checklist
2 |
3 | - [ ] run `pnpm format`
4 | - [ ] documentation is changed or added
5 | - [ ] commit message and code follows the [Developer's Certification of Origin](https://github.com/crashmax-dev/fireworks-js/blob/master/CONTRIBUTING.md#developers-certificate-of-origin-11)
6 | and the [Code of conduct](https://github.com/crashmax-dev/fireworks-js/blob/master/CODE_OF_CONDUCT.md)
7 |
--------------------------------------------------------------------------------
/.github/workflows/gh-pages.yml:
--------------------------------------------------------------------------------
1 | name: github-pages
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 |
8 | jobs:
9 | cache-and-install:
10 | runs-on: ubuntu-latest
11 | steps:
12 | - name: Checkout
13 | uses: actions/checkout@v3
14 |
15 | - name: Cache PNPM
16 | uses: actions/cache@v3
17 | with:
18 | path: ~/.pnpm-store
19 | key: ${{ runner.os }}-node-${{ hashFiles('**/pnpm-lock.yaml') }}
20 | restore-keys: |
21 | ${{ runner.os }}-node-
22 |
23 | - name: Setup Node
24 | uses: actions/setup-node@v3
25 | with:
26 | node-version: 16
27 |
28 | - name: Installing packages
29 | uses: pnpm/action-setup@v2.2.2
30 | with:
31 | version: 7.x.x
32 | run_install: |
33 | - args: [--frozen-lockfile]
34 |
35 | - name: Build website
36 | run: pnpm build:website
37 |
38 | - name: Deploy to GitHub Pages
39 | uses: JamesIves/github-pages-deploy-action@4.1.5
40 | with:
41 | branch: gh-pages
42 | folder: ./website/dist
43 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | **/node_modules
2 | **/dist
3 | **/.svelte-kit
4 | **/.angular
5 | **/.turbo
6 | **/package
7 | *.tgz
8 | *.log
9 | .DS_Store
10 | Thumbs.db
11 |
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | auto-install-peers=true
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | build
4 | logs
5 | coverage
6 | .next
7 | .turbo
8 | .github
9 | .angular
10 | .svelte-kit
11 | .vscode
12 | *.log*
13 | *.log
14 | *.lock
15 | *.yaml
16 | *.yml
17 | *.sh
18 | *.svg
19 | *rc.*
20 | *.htm
21 | *.html
22 | *.json
23 | *.md
24 | .*ignore
25 |
--------------------------------------------------------------------------------
/.prettierrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = require('@crashmax/prettier-config')
2 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "vue.volar",
4 | "angular.ng-template",
5 | "svelte.svelte-vscode",
6 | "esbenp.prettier-vscode"
7 | ]
8 | }
9 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | ## Our Pledge
4 |
5 | We as members, contributors, and leaders pledge to make participation in our
6 | community a harassment-free experience for everyone, regardless of age, body
7 | size, visible or invisible disability, ethnicity, sex characteristics, gender
8 | identity and expression, level of experience, education, socio-economic status,
9 | nationality, personal appearance, race, caste, color, religion, or sexual
10 | identity and orientation.
11 |
12 | We pledge to act and interact in ways that contribute to an open, welcoming,
13 | diverse, inclusive, and healthy community.
14 |
15 | ## Our Standards
16 |
17 | Examples of behavior that contributes to a positive environment for our
18 | community include:
19 |
20 | * Demonstrating empathy and kindness toward other people
21 | * Being respectful of differing opinions, viewpoints, and experiences
22 | * Giving and gracefully accepting constructive feedback
23 | * Accepting responsibility and apologizing to those affected by our mistakes,
24 | and learning from the experience
25 | * Focusing on what is best not just for us as individuals, but for the overall
26 | community
27 |
28 | Examples of unacceptable behavior include:
29 |
30 | * The use of sexualized language or imagery, and sexual attention or advances of
31 | any kind
32 | * Trolling, insulting or derogatory comments, and personal or political attacks
33 | * Public or private harassment
34 | * Publishing others' private information, such as a physical or email address,
35 | without their explicit permission
36 | * Other conduct which could reasonably be considered inappropriate in a
37 | professional setting
38 |
39 | ## Enforcement Responsibilities
40 |
41 | Community leaders are responsible for clarifying and enforcing our standards of
42 | acceptable behavior and will take appropriate and fair corrective action in
43 | response to any behavior that they deem inappropriate, threatening, offensive,
44 | or harmful.
45 |
46 | Community leaders have the right and responsibility to remove, edit, or reject
47 | comments, commits, code, wiki edits, issues, and other contributions that are
48 | not aligned to this Code of Conduct, and will communicate reasons for moderation
49 | decisions when appropriate.
50 |
51 | ## Scope
52 |
53 | This Code of Conduct applies within all community spaces, and also applies when
54 | an individual is officially representing the community in public spaces.
55 | Examples of representing our community include using an official e-mail address,
56 | posting via an official social media account, or acting as an appointed
57 | representative at an online or offline event.
58 |
59 | ## Enforcement
60 |
61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
62 | reported to the community leaders responsible for enforcement at help@crashmax.ru.
63 | All complaints will be reviewed and investigated promptly and fairly.
64 |
65 | All community leaders are obligated to respect the privacy and security of the
66 | reporter of any incident.
67 |
68 | ## Enforcement Guidelines
69 |
70 | Community leaders will follow these Community Impact Guidelines in determining
71 | the consequences for any action they deem in violation of this Code of Conduct:
72 |
73 | ### 1. Correction
74 |
75 | **Community Impact**: Use of inappropriate language or other behavior deemed
76 | unprofessional or unwelcome in the community.
77 |
78 | **Consequence**: A private, written warning from community leaders, providing
79 | clarity around the nature of the violation and an explanation of why the
80 | behavior was inappropriate. A public apology may be requested.
81 |
82 | ### 2. Warning
83 |
84 | **Community Impact**: A violation through a single incident or series of
85 | actions.
86 |
87 | **Consequence**: A warning with consequences for continued behavior. No
88 | interaction with the people involved, including unsolicited interaction with
89 | those enforcing the Code of Conduct, for a specified period of time. This
90 | includes avoiding interactions in community spaces as well as external channels
91 | like social media. Violating these terms may lead to a temporary or permanent
92 | ban.
93 |
94 | ### 3. Temporary Ban
95 |
96 | **Community Impact**: A serious violation of community standards, including
97 | sustained inappropriate behavior.
98 |
99 | **Consequence**: A temporary ban from any sort of interaction or public
100 | communication with the community for a specified period of time. No public or
101 | private interaction with the people involved, including unsolicited interaction
102 | with those enforcing the Code of Conduct, is allowed during this period.
103 | Violating these terms may lead to a permanent ban.
104 |
105 | ### 4. Permanent Ban
106 |
107 | **Community Impact**: Demonstrating a pattern of violation of community
108 | standards, including sustained inappropriate behavior, harassment of an
109 | individual, or aggression toward or disparagement of classes of individuals.
110 |
111 | **Consequence**: A permanent ban from any sort of public interaction within the
112 | community.
113 |
114 | ## Attribution
115 |
116 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
117 | version 2.1, available at
118 | [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
119 |
120 | Community Impact Guidelines were inspired by
121 | [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
122 |
123 | For answers to common questions about this code of conduct, see the FAQ at
124 | [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
125 | [https://www.contributor-covenant.org/translations][translations].
126 |
127 | [homepage]: https://www.contributor-covenant.org
128 | [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
129 | [Mozilla CoC]: https://github.com/mozilla/diversity
130 | [FAQ]: https://www.contributor-covenant.org/faq
131 | [translations]: https://www.contributor-covenant.org/translations
132 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | ## Rules
2 |
3 | There are a few basic ground-rules for contributors:
4 |
5 | 1. **No `--force` pushes** on `master` or modifying the Git history in any way
6 | after a PR has been merged.
7 | 2. **Non-master branches** ought to be used for ongoing work.
8 | 3. Internal pull-requests to solicit feedback are *encouraged* for any other
9 | non-trivial contribution but left to the discretion of the contributor.
10 | 4. Contributors should attempt to adhere to the prevailing code-style.
11 | 5. Do not bump version numbers in pull requests.
12 |
13 | ### fireworks-js v1
14 |
15 | Code for fireworks-js **v1** is in [branch
16 | v1](https://github.com/crashmax-dev/fireworks-js/tree/v1), so all fireworks-js v1 related
17 | changes should be based on **`branch v1`**.
18 |
19 | ### fireworks-js v2
20 |
21 | Code for fireworks-js **v2** is in [branch
22 | master](https://github.com/crashmax-dev/fireworks-js/tree/master), so all fireworks-js v2 related
23 | changes should be based on **`branch master`**.
24 |
25 | ## Changes to this arrangement
26 |
27 | This is an experiment and feedback is welcome! This document may also be subject
28 | to pull-requests or changes by contributors where you believe you have something
29 | valuable to add or change.
30 |
31 | -----------------------------------------
32 |
33 | ## Developer's Certificate of Origin 1.1
34 |
35 | By making a contribution to this project, I certify that:
36 |
37 | * (a) The contribution was created in whole or in part by me and I have the
38 | right to submit it under the open source license indicated in the file; or
39 |
40 | * (b) The contribution is based upon previous work that, to the best of my
41 | knowledge, is covered under an appropriate open source license and I have the
42 | right under that license to submit that work with modifications, whether
43 | created in whole or in part by me, under the same open source license (unless
44 | I am permitted to submit under a different license), as indicated in the file;
45 | or
46 |
47 | * (c) The contribution was provided directly to me by some other person who
48 | certified (a), (b) or (c) and I have not modified it.
49 |
50 | * (d) I understand and agree that this project and the contribution are public
51 | and that a record of the contribution (including all personal information I
52 | submit with it, including my sign-off) is maintained indefinitely and may be
53 | redistributed consistent with this project or the open source license(s)
54 | involved.
55 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021-2023 Vitalij Ryndin
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://fireworks.js.org)
2 |
3 |
4 | A simple fireworks library! | fireworks.js.org
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | ---
32 |
33 | ## Table of Contents
34 |
35 | > **Warning**\
36 | > This readme refers to upcoming v2 version, [read here](https://github.com/crashmax-dev/fireworks-js/tree/v1) for v1 documentation.
37 |
38 | - [Features](#features)
39 | - [Browsers support](#browsers-support)
40 | - [Demo](#demo)
41 | - [Installation](#installation)
42 | - [CDN](#cdn)
43 | - [Usage](#usage)
44 | - [fireworks-js](#fireworks-js)
45 | - [@fireworks-js/react](#fireworks-jsreact)
46 | - [@fireworks-js/preact](#fireworks-jspreact)
47 | - [@fireworks-js/solid](#fireworks-jssolid)
48 | - [@fireworks-js/vue](#fireworks-jsvue)
49 | - [@fireworks-js/svelte](#fireworks-jssvelte)
50 | - [@fireworks-js/angular](#fireworks-jsangular)
51 | - [@fireworks-js/web](#fireworks-jsweb)
52 | - [Documentation](#documentation)
53 | - [Options](#options)
54 | - [API](#api)
55 | - [Community](#community)
56 |
57 | ## Features
58 |
59 | - 🔥 Zero [dependencies](https://www.npmjs.com/package/fireworks-js?activeTab=dependencies)
60 | - ⚙️ Flexible [configuration](#options)
61 | - 📦 Lightweight ([~3.0kB gzipped](https://bundlephobia.com/package/fireworks-js))
62 | - 📜 Supports [TypeScript](https://www.typescriptlang.org) type definition
63 |
64 | ## Browsers support
65 |
66 | | [ ](http://godban.github.io/browsers-support-badges/) Edge | [ ](http://godban.github.io/browsers-support-badges/) Firefox | [ ](http://godban.github.io/browsers-support-badges/) Chrome | [ ](http://godban.github.io/browsers-support-badges/) Safari | [ ](http://godban.github.io/browsers-support-badges/) iOS Safari | [ ](http://godban.github.io/browsers-support-badges/) Opera | [ ](http://godban.github.io/browsers-support-badges/) Yandex |
67 | | --------- | --------- | --------- | --------- | --------- | --------- | --------- |
68 | | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ | ✔
69 |
70 | ## Demo
71 |
72 | You can play with `fireworks-js` at [fireworks.js.org](https://fireworks.js.org) or [codesandbox.io](https://codesandbox.io/s/fireworks-js-react-bjeoqy?file=/src/App.tsx)
73 |
74 | ## Installation
75 |
76 | ```sh
77 | npm install fireworks-js
78 | ```
79 |
80 | ```sh
81 | yarn add fireworks-js
82 | ```
83 |
84 | ```sh
85 | pnpm add fireworks-js
86 | ```
87 |
88 | | Package | Status | Description |
89 | | ------- | ------ | ----------- |
90 | | [fireworks-js](#fireworks-js) | [](https://npm.im/fireworks-js) | Vanilla JS |
91 | | [@fireworks-js/react](#fireworks-jsreact) | [](https://npm.im/@fireworks-js/react) | React component |
92 | | [@fireworks-js/preact](#fireworks-jspreact) | [](https://npm.im/@fireworks-js/preact) | Preact component |
93 | | [@fireworks-js/solid](#fireworks-jssolid) | [](https://npm.im/@fireworks-js/solid) | Solid component |
94 | | [@fireworks-js/vue](#fireworks-jsvue) | [](https://npm.im/@fireworks-js/vue) | Vue 3 component |
95 | | [@fireworks-js/svelte](#fireworks-jssvelte) | [](https://npm.im/@fireworks-js/svelte) | Svelte component |
96 | | [@fireworks-js/angular](#fireworks-jsangular) | [](https://npm.im/@fireworks-js/angular) | Angular component |
97 | | [@fireworks-js/web](#fireworks-jsweb) | [](https://npm.im/@fireworks-js/web) | Web components |
98 |
99 | # CDN
100 |
101 | ```html
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
114 | ```
115 |
116 | ## Usage
117 |
118 | #### [`fireworks-js`](https://github.com/crashmax-dev/fireworks-js/tree/master/examples/basic)
119 |
120 | ```js
121 | import { Fireworks } from 'fireworks-js'
122 |
123 | const container = document.querySelector('.container')
124 | const fireworks = new Fireworks(container, { /* options */ })
125 | fireworks.start()
126 | ```
127 |
128 | [](https://codesandbox.io/p/sandbox/blissful-sanderson-dkvnx4)
129 |
130 | #### [`@fireworks-js/react`](https://github.com/crashmax-dev/fireworks-js/tree/master/examples/with-react)
131 |
132 | ```sh
133 | npm install @fireworks-js/react
134 | ```
135 |
136 | [](https://codesandbox.io/s/fireworks-js-react-bjeoqy?fontsize=14&hidenavigation=1&theme=dark)
137 |
138 | #### [`@fireworks-js/preact`](https://github.com/crashmax-dev/fireworks-js/tree/master/examples/with-preact)
139 |
140 | ```sh
141 | npm install @fireworks-js/preact
142 | ```
143 |
144 | #### [`@fireworks-js/solid`](https://github.com/crashmax-dev/fireworks-js/tree/master/examples/with-solid)
145 |
146 | ```sh
147 | npm install @fireworks-js/solid
148 | ```
149 |
150 | #### [`@fireworks-js/vue`](https://github.com/crashmax-dev/fireworks-js/tree/master/examples/with-vue)
151 |
152 | ```sh
153 | npm install @fireworks-js/vue
154 | ```
155 |
156 | #### [`@fireworks-js/svelte`](https://github.com/crashmax-dev/fireworks-js/tree/master/examples/with-svelte)
157 |
158 | ```sh
159 | npm install @fireworks-js/svelte
160 | ```
161 |
162 | #### [`@fireworks-js/angular`](https://github.com/crashmax-dev/fireworks-js/tree/master/examples/with-angular)
163 |
164 | ```sh
165 | npm install @fireworks-js/angular
166 | ```
167 |
168 | #### [`@fireworks-js/web`](https://github.com/crashmax-dev/fireworks-js/tree/master/examples/with-web-components)
169 |
170 | ```sh
171 | npm install @fireworks-js/web
172 | ```
173 |
174 | ## Documentation
175 |
176 | ### Options
177 |
178 | > **Note**\
179 | > The options is optional, as are each of its properties.
180 |
181 | | Property | Type | Default |
182 | | ------------------ | ------------------- | ----------------------------------------------------------------------------- |
183 | | `hue` | object | [hue](https://github.com/crashmax-dev/fireworks-js/blob/eedee4020e9c458fde83b60dfac6f2502d4593bb/packages/fireworks-js/src/options.ts#L49-L52) |
184 | | `rocketsPoint` | object | [rocketsPoint](https://github.com/crashmax-dev/fireworks-js/blob/eedee4020e9c458fde83b60dfac6f2502d4593bb/packages/fireworks-js/src/options.ts#L54-L57) |
185 | | `mouse` | object | [mouse](https://github.com/crashmax-dev/fireworks-js/blob/eedee4020e9c458fde83b60dfac6f2502d4593bb/packages/fireworks-js/src/options.ts#L70-L74) |
186 | | `boundaries` | object | [boundaries](https://github.com/crashmax-dev/fireworks-js/blob/eedee4020e9c458fde83b60dfac6f2502d4593bb/packages/fireworks-js/src/options.ts#L104-L110) |
187 | | `sound` | object | [sound](https://github.com/crashmax-dev/fireworks-js/blob/eedee4020e9c458fde83b60dfac6f2502d4593bb/packages/fireworks-js/src/options.ts#L91-L102) |
188 | | `delay` | object | [delay](https://github.com/crashmax-dev/fireworks-js/blob/eedee4020e9c458fde83b60dfac6f2502d4593bb/packages/fireworks-js/src/options.ts#L76-L79) |
189 | | `brightness` | object | [brightness](https://github.com/crashmax-dev/fireworks-js/blob/eedee4020e9c458fde83b60dfac6f2502d4593bb/packages/fireworks-js/src/options.ts#L81-L84) |
190 | | `decay` | object | [decay](https://github.com/crashmax-dev/fireworks-js/blob/eedee4020e9c458fde83b60dfac6f2502d4593bb/packages/fireworks-js/src/options.ts#L86-L89) |
191 | | `lineWidth` | object | [lineWidth](https://github.com/crashmax-dev/fireworks-js/blob/eedee4020e9c458fde83b60dfac6f2502d4593bb/packages/fireworks-js/src/options.ts#L59-L68) |
192 | | `lineStyle` | string | round |
193 | | `explosion` | number | 5 |
194 | | `opacity` | number | 0.5 |
195 | | `acceleration` | number | 1.05 |
196 | | `friction` | number | 0.95 |
197 | | `gravity` | number | 1.5 |
198 | | `particles` | number | 50 |
199 | | `traceLength` | number | 3 |
200 | | `flickering` | number | 50 |
201 | | `intensity` | number | 30 |
202 | | `traceSpeed` | number | 10 |
203 | | `intensity` | number | 30 |
204 | | `autoresize` | boolean | true |
205 |
206 | The `hue`, `delay`, `decay`, `brightness`, `lineWidth.explosion`, `lineWidth.trace`, `sound.volume` and `rocketsPoint` options accept an object:
207 |
208 | | Property | Type |
209 | | -------- | ------- |
210 | | `min` | number |
211 | | `max` | number |
212 |
213 | > **Note**\
214 | > The `min` and `max` properties are used to randomly select values from the range.
215 |
216 | The `mouse` options accept an object:
217 |
218 | | Property | Type | Default |
219 | | -------- | ------- | ------- |
220 | | `click` | boolean | false |
221 | | `move` | boolean | false |
222 | | `max` | number | 1 |
223 |
224 | > **Note**\
225 | > The `max` property has no effect if `click` is false.
226 |
227 | The `sound` options accept an object:
228 |
229 | | Property | Type | Default |
230 | | ---------- | --------- | ------------------- |
231 | | `enabled` | boolean | false |
232 | | `files` | string[] | [files](https://github.com/crashmax-dev/fireworks-js/blob/eedee4020e9c458fde83b60dfac6f2502d4593bb/packages/fireworks-js/src/options.ts#L93-L97) |
233 | | `volume` | object | [volume](https://github.com/crashmax-dev/fireworks-js/blob/eedee4020e9c458fde83b60dfac6f2502d4593bb/packages/fireworks-js/src/options.ts#L98-L101) |
234 |
235 | ```js
236 | const fireworks = new Fireworks(container, {
237 | autoresize: true,
238 | opacity: 0.5,
239 | acceleration: 1.05,
240 | friction: 0.97,
241 | gravity: 1.5,
242 | particles: 50,
243 | traceLength: 3,
244 | traceSpeed: 10,
245 | explosion: 5,
246 | intensity: 30,
247 | flickering: 50,
248 | lineStyle: 'round',
249 | hue: {
250 | min: 0,
251 | max: 360
252 | },
253 | delay: {
254 | min: 30,
255 | max: 60
256 | },
257 | rocketsPoint: {
258 | min: 50,
259 | max: 50
260 | },
261 | lineWidth: {
262 | explosion: {
263 | min: 1,
264 | max: 3
265 | },
266 | trace: {
267 | min: 1,
268 | max: 2
269 | }
270 | },
271 | brightness: {
272 | min: 50,
273 | max: 80
274 | },
275 | decay: {
276 | min: 0.015,
277 | max: 0.03
278 | },
279 | mouse: {
280 | click: false,
281 | move: false,
282 | max: 1
283 | }
284 | })
285 | ```
286 |
287 | ### API
288 |
289 | #### `.start()`
290 | Start fireworks.
291 |
292 | #### `.launch(count)`
293 | Launching a specified number of fireworks.\
294 | Type: `number`\
295 | Default `1`
296 |
297 | #### `.stop(dispose)`
298 | Stop fireworks.\
299 | Type: `boolean`\
300 | Default: `false`
301 |
302 | #### `.waitStop(dispose)`
303 | Asynchronous stopping of the fireworks.\
304 | Type: `boolean`\
305 | Default: `false`
306 |
307 | #### `.pause()`
308 | Start/stop fireworks.
309 |
310 | #### `.clear()`
311 | Cleaning the canvas from fireworks.
312 |
313 | #### `.currentOptions`
314 | Getting current fireworks options.
315 |
316 | #### `.updateOptions(options)`
317 | Force update fireworks options.\
318 | Type: [`options`](https://github.com/crashmax-dev/fireworks-js/blob/6819ec8456ecb97140a8e1f41959ca2da5c17ddf/packages/fireworks-js/src/types.ts#L3-L25)
319 |
320 | #### `.updateSize(sizes)`
321 | Force update canvas size.\
322 | Type: [`sizes`](https://github.com/crashmax-dev/fireworks-js/blob/6819ec8456ecb97140a8e1f41959ca2da5c17ddf/packages/fireworks-js/src/types.ts#L58-L61)
323 |
324 | #### `.updateBoundaries(boundaries)`
325 | Force update canvas boundaries.\
326 | Type: [`boundaries`](https://github.com/crashmax-dev/fireworks-js/blob/6819ec8456ecb97140a8e1f41959ca2da5c17ddf/packages/fireworks-js/src/types.ts#L35-L40)
327 |
328 | ## Community
329 |
330 | ### Star History
331 |
332 | [](https://star-history.com/#crashmax-dev/fireworks-js&Date)
333 |
334 | ### Author
335 | - [crashmax](https://github.com/crashmax-dev)
336 |
337 | ### License
338 | - [MIT](https://github.com/crashmax-dev/fireworks-js/blob/master/LICENSE)
339 |
--------------------------------------------------------------------------------
/examples/basic/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | fireworks-js
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/examples/basic/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "basic",
3 | "private": true,
4 | "version": "0.0.0",
5 | "scripts": {
6 | "dev": "vite",
7 | "build": "tsc && vite build",
8 | "preview": "vite preview"
9 | },
10 | "dependencies": {
11 | "@zero-dependency/dom": "^0.10.0",
12 | "fireworks-js": "workspace:*"
13 | },
14 | "devDependencies": {
15 | "typescript": "^4.8.4"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/basic/src/index.ts:
--------------------------------------------------------------------------------
1 | import { el } from '@zero-dependency/dom'
2 | import { Fireworks } from 'fireworks-js'
3 | import './style.css'
4 |
5 | const app = document.querySelector('#app')!
6 | const fireworks = new Fireworks(app, {
7 | autoresize: true,
8 | boundaries: {
9 | width: app.clientWidth,
10 | height: app.clientHeight
11 | }
12 | })
13 |
14 | // const resizeObserver = new ResizeObserver((entries) => {
15 | // console.log(entries)
16 | // })
17 |
18 | // resizeObserver.observe(app)
19 |
20 | fireworks.start()
21 |
22 | const start = el(
23 | 'button',
24 | {
25 | onclick: () => {
26 | fireworks.start()
27 | }
28 | },
29 | 'Start'
30 | )
31 |
32 | const stop = el(
33 | 'button',
34 | {
35 | onclick: () => {
36 | fireworks.waitStop()
37 | }
38 | },
39 | 'Stop'
40 | )
41 |
42 | const launch = el(
43 | 'button',
44 | {
45 | onclick: () => {
46 | fireworks.launch(Number(count.value))
47 | }
48 | },
49 | 'Launch'
50 | )
51 |
52 | const count = el('input', {
53 | value: '1',
54 | min: '1',
55 | max: '15',
56 | type: 'number',
57 | placeholder: 'count',
58 | style: {
59 | width: '2rem'
60 | }
61 | })
62 |
63 | const buttons = el(
64 | 'div',
65 | {
66 | style: {
67 | position: 'absolute',
68 | display: 'flex',
69 | gap: '4px'
70 | }
71 | },
72 | start,
73 | stop,
74 | launch,
75 | count
76 | )
77 |
78 | document.body.appendChild(buttons)
79 |
--------------------------------------------------------------------------------
/examples/basic/src/style.css:
--------------------------------------------------------------------------------
1 | #app {
2 | top: 0;
3 | left: 0;
4 | width: 100%;
5 | height: 100%;
6 | position: fixed;
7 | background: #000;
8 | }
9 |
--------------------------------------------------------------------------------
/examples/basic/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/examples/basic/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "module": "ESNext",
6 | "lib": [
7 | "ESNext",
8 | "DOM"
9 | ],
10 | "moduleResolution": "Node",
11 | "strict": true,
12 | "sourceMap": true,
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "esModuleInterop": true,
16 | "noEmit": true,
17 | "noUnusedLocals": true,
18 | "noUnusedParameters": true,
19 | "noImplicitReturns": true,
20 | "skipLibCheck": true
21 | },
22 | "include": [
23 | "src"
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/examples/with-angular/.browserslistrc:
--------------------------------------------------------------------------------
1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 |
5 | # For the full list of supported browsers by the Angular framework, please see:
6 | # https://angular.io/guide/browser-support
7 |
8 | # You can see what browsers were selected by your queries by running:
9 | # npx browserslist
10 |
11 | last 1 Chrome version
12 | last 1 Firefox version
13 | last 2 Edge major versions
14 | last 2 Safari major versions
15 | last 2 iOS major versions
16 | Firefox ESR
17 |
--------------------------------------------------------------------------------
/examples/with-angular/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "with-angular": {
7 | "projectType": "application",
8 | "schematics": {},
9 | "root": "",
10 | "sourceRoot": "src",
11 | "prefix": "app",
12 | "architect": {
13 | "build": {
14 | "builder": "@angular-devkit/build-angular:browser",
15 | "options": {
16 | "outputPath": "dist/with-angular",
17 | "index": "src/index.html",
18 | "main": "src/main.ts",
19 | "polyfills": "src/polyfills.ts",
20 | "tsConfig": "tsconfig.app.json",
21 | "assets": [
22 | "src/favicon.ico",
23 | "src/assets"
24 | ],
25 | "styles": [
26 | "src/styles.css"
27 | ],
28 | "scripts": []
29 | },
30 | "configurations": {
31 | "production": {
32 | "budgets": [
33 | {
34 | "type": "initial",
35 | "maximumWarning": "500kb",
36 | "maximumError": "1mb"
37 | },
38 | {
39 | "type": "anyComponentStyle",
40 | "maximumWarning": "2kb",
41 | "maximumError": "4kb"
42 | }
43 | ],
44 | "fileReplacements": [
45 | {
46 | "replace": "src/environments/environment.ts",
47 | "with": "src/environments/environment.prod.ts"
48 | }
49 | ],
50 | "outputHashing": "all"
51 | },
52 | "development": {
53 | "buildOptimizer": false,
54 | "optimization": false,
55 | "vendorChunk": true,
56 | "extractLicenses": false,
57 | "sourceMap": true,
58 | "namedChunks": true
59 | }
60 | },
61 | "defaultConfiguration": "production"
62 | },
63 | "serve": {
64 | "builder": "@angular-devkit/build-angular:dev-server",
65 | "configurations": {
66 | "production": {
67 | "browserTarget": "with-angular:build:production"
68 | },
69 | "development": {
70 | "browserTarget": "with-angular:build:development"
71 | }
72 | },
73 | "defaultConfiguration": "development"
74 | },
75 | "extract-i18n": {
76 | "builder": "@angular-devkit/build-angular:extract-i18n",
77 | "options": {
78 | "browserTarget": "with-angular:build"
79 | }
80 | }
81 | }
82 | }
83 | },
84 | "cli": {
85 | "analytics": false
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/examples/with-angular/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-angular",
3 | "private": true,
4 | "version": "0.0.0",
5 | "scripts": {
6 | "ng": "ng",
7 | "dev": "ng serve",
8 | "build": "ng build",
9 | "watch": "ng build --watch --configuration development"
10 | },
11 | "dependencies": {
12 | "@angular/animations": "^14.0.0",
13 | "@angular/common": "^14.0.0",
14 | "@angular/compiler": "^14.0.0",
15 | "@angular/core": "^14.0.0",
16 | "@angular/forms": "^14.0.0",
17 | "@angular/platform-browser": "^14.0.0",
18 | "@angular/platform-browser-dynamic": "^14.0.0",
19 | "@angular/router": "^14.0.0",
20 | "@fireworks-js/angular": "workspace:*",
21 | "rxjs": "~7.5.0",
22 | "tslib": "^2.2.1",
23 | "zone.js": "~0.11.4"
24 | },
25 | "devDependencies": {
26 | "@angular-devkit/build-angular": "^14.0.5",
27 | "@angular/cli": "~14.2.4",
28 | "@angular/compiler-cli": "^14.0.0",
29 | "@types/jasmine": "~4.3.0",
30 | "jasmine-core": "~4.4.0",
31 | "typescript": "~4.8.4"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/examples/with-angular/src/app/app.component.css:
--------------------------------------------------------------------------------
1 | .fireworks {
2 | top: 0;
3 | left: 0;
4 | width: 100%;
5 | height: 100%;
6 | position: fixed;
7 | background: #000;
8 | }
9 |
--------------------------------------------------------------------------------
/examples/with-angular/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 | {{ enabled ? 'Mounted' : 'Unmounted' }}
3 | waitStop
4 |
5 |
6 |
--------------------------------------------------------------------------------
/examples/with-angular/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, ViewChild } from '@angular/core'
2 | import type {
3 | FireworksDirective,
4 | FireworksOptions
5 | } from '@fireworks-js/angular'
6 |
7 | @Component({
8 | selector: 'app-root',
9 | templateUrl: './app.component.html',
10 | styleUrls: ['./app.component.css']
11 | })
12 | export class AppComponent {
13 | enabled = true
14 | options: FireworksOptions = {
15 | opacity: 0.5
16 | }
17 |
18 | @ViewChild('fireworks') fireworks?: FireworksDirective
19 |
20 | toggleFireworks(): void {
21 | this.enabled = !this.enabled
22 | }
23 |
24 | waitStop(): void {
25 | this.fireworks?.waitStop()
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/examples/with-angular/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core'
2 | import { BrowserModule } from '@angular/platform-browser'
3 | import { NgFireworksModule } from '@fireworks-js/angular'
4 | import { AppComponent } from './app.component'
5 |
6 | @NgModule({
7 | declarations: [AppComponent],
8 | imports: [BrowserModule, NgFireworksModule],
9 | providers: [],
10 | bootstrap: [AppComponent]
11 | })
12 | export class AppModule {}
13 |
--------------------------------------------------------------------------------
/examples/with-angular/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | }
4 |
--------------------------------------------------------------------------------
/examples/with-angular/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false
7 | }
8 |
9 | /*
10 | * For easier debugging in development mode, you can import the following file
11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
12 | *
13 | * This import should be commented out in production mode because it will have a negative impact
14 | * on performance if an error is thrown.
15 | */
16 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI.
17 |
--------------------------------------------------------------------------------
/examples/with-angular/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodeWithUsman0/fireworks-js/8c15ac042fdafee69fd724e59bb2bb01a32230df/examples/with-angular/src/favicon.ico
--------------------------------------------------------------------------------
/examples/with-angular/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | @fireworks-js/angular
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/examples/with-angular/src/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core'
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'
3 | import { AppModule } from './app/app.module'
4 | import { environment } from './environments/environment'
5 |
6 | if (environment.production) {
7 | enableProdMode()
8 | }
9 |
10 | platformBrowserDynamic()
11 | .bootstrapModule(AppModule)
12 | .catch((err) => console.error(err))
13 |
--------------------------------------------------------------------------------
/examples/with-angular/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes recent versions of Safari, Chrome (including
12 | * Opera), Edge on the desktop, and iOS and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/guide/browser-support
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /**
22 | * By default, zone.js will patch all possible macroTask and DomEvents
23 | * user can disable parts of macroTask/DomEvents patch by setting following flags
24 | * because those flags need to be set before `zone.js` being loaded, and webpack
25 | * will put import in the top of bundle, so user need to create a separate file
26 | * in this directory (for example: zone-flags.ts), and put the following flags
27 | * into that file, and then add the following code before importing zone.js.
28 | * import './zone-flags';
29 | *
30 | * The flags allowed in zone-flags.ts are listed here.
31 | *
32 | * The following flags will work for all browsers.
33 | *
34 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
35 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
36 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
37 | *
38 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
39 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
40 | *
41 | * (window as any).__Zone_enable_cross_context_check = true;
42 | *
43 | */
44 |
45 | /***************************************************************************************************
46 | * Zone JS is required by default for Angular itself.
47 | */
48 | import 'zone.js'
49 |
50 | // Included with Angular CLI.
51 |
52 | /***************************************************************************************************
53 | * APPLICATION IMPORTS
54 | */
55 |
--------------------------------------------------------------------------------
/examples/with-angular/src/styles.css:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
--------------------------------------------------------------------------------
/examples/with-angular/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/app",
6 | "types": []
7 | },
8 | "files": [
9 | "src/main.ts",
10 | "src/polyfills.ts"
11 | ],
12 | "include": [
13 | "src/**/*.d.ts"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/examples/with-angular/tsconfig.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "compileOnSave": false,
4 | "compilerOptions": {
5 | "baseUrl": "./",
6 | "outDir": "./dist/out-tsc",
7 | "forceConsistentCasingInFileNames": true,
8 | "strict": true,
9 | "noImplicitOverride": true,
10 | "noPropertyAccessFromIndexSignature": true,
11 | "noImplicitReturns": true,
12 | "noFallthroughCasesInSwitch": true,
13 | "sourceMap": true,
14 | "declaration": false,
15 | "downlevelIteration": true,
16 | "experimentalDecorators": true,
17 | "moduleResolution": "node",
18 | "importHelpers": true,
19 | "target": "es2020",
20 | "module": "es2020",
21 | "lib": [
22 | "es2020",
23 | "dom"
24 | ]
25 | },
26 | "angularCompilerOptions": {
27 | "enableI18nLegacyMessageIdFormat": false,
28 | "strictInjectionParameters": true,
29 | "strictInputAccessModifiers": true,
30 | "strictTemplates": true
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/examples/with-preact/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | @fireworks-js/preact
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/examples/with-preact/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-preact",
3 | "private": true,
4 | "version": "0.0.0",
5 | "scripts": {
6 | "dev": "vite",
7 | "build": "tsc && vite build",
8 | "preview": "vite preview"
9 | },
10 | "dependencies": {
11 | "@fireworks-js/preact": "workspace:*",
12 | "preact": "10.11.0"
13 | },
14 | "devDependencies": {
15 | "@preact/preset-vite": "2.4.0",
16 | "typescript": "4.8.4"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/examples/with-preact/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { Fireworks } from '@fireworks-js/preact'
2 | import { useRef } from 'preact/hooks'
3 | import type { FireworksHandlers } from '@fireworks-js/preact'
4 |
5 | export function App() {
6 | const ref = useRef(null)
7 |
8 | const toggleFireworks = () => {
9 | if (!ref.current) return
10 | if (ref.current.isRunning) {
11 | ref.current.stop()
12 | } else {
13 | ref.current.start()
14 | }
15 | }
16 |
17 | return (
18 | <>
19 |
22 | toggleFireworks()}>Toggle
23 | ref.current!.clear()}>Clear
24 |
25 |
38 | >
39 | )
40 | }
41 |
--------------------------------------------------------------------------------
/examples/with-preact/src/index.tsx:
--------------------------------------------------------------------------------
1 | import { render } from 'preact'
2 | import React from 'preact/compat'
3 | import { App } from './App'
4 |
5 | const app = document.getElementById('app')!
6 | render(
7 |
8 |
9 | ,
10 | app
11 | )
12 |
--------------------------------------------------------------------------------
/examples/with-preact/src/preact.d.ts:
--------------------------------------------------------------------------------
1 | import JSX = preact.JSX
2 |
--------------------------------------------------------------------------------
/examples/with-preact/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/examples/with-preact/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "lib": [
6 | "DOM",
7 | "DOM.Iterable",
8 | "ESNext"
9 | ],
10 | "allowJs": false,
11 | "skipLibCheck": true,
12 | "esModuleInterop": false,
13 | "allowSyntheticDefaultImports": true,
14 | "strict": true,
15 | "forceConsistentCasingInFileNames": true,
16 | "module": "ESNext",
17 | "moduleResolution": "Node",
18 | "resolveJsonModule": true,
19 | "isolatedModules": true,
20 | "noEmit": true,
21 | "jsx": "preserve",
22 | "jsxFactory": "h",
23 | "jsxFragmentFactory": "Fragment"
24 | },
25 | "include": [
26 | "src"
27 | ],
28 | "references": [
29 | {
30 | "path": "./tsconfig.node.json"
31 | }
32 | ]
33 | }
34 |
--------------------------------------------------------------------------------
/examples/with-preact/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "esnext",
5 | "moduleResolution": "node"
6 | },
7 | "include": [
8 | "vite.config.ts"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/examples/with-preact/vite.config.ts:
--------------------------------------------------------------------------------
1 | import preact from '@preact/preset-vite'
2 | import { defineConfig } from 'vite'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [preact()]
7 | })
8 |
--------------------------------------------------------------------------------
/examples/with-react/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | @fireworks-js/react
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/examples/with-react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-react",
3 | "private": true,
4 | "version": "0.0.0",
5 | "scripts": {
6 | "dev": "vite",
7 | "build": "tsc && vite build",
8 | "preview": "vite preview"
9 | },
10 | "dependencies": {
11 | "@fireworks-js/react": "workspace:*",
12 | "react": "18.2.0",
13 | "react-dom": "18.2.0"
14 | },
15 | "devDependencies": {
16 | "@types/react": "18.0.21",
17 | "@types/react-dom": "18.0.6",
18 | "@vitejs/plugin-react": "2.1.0",
19 | "typescript": "4.8.4"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/examples/with-react/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { useRef } from 'react'
2 | import { Fireworks } from '@fireworks-js/react'
3 | import type { FireworksHandlers } from '@fireworks-js/react'
4 |
5 | export function App() {
6 | const ref = useRef(null)
7 |
8 | const toggle = () => {
9 | if (!ref.current) return
10 | if (ref.current.isRunning) {
11 | ref.current.stop()
12 | } else {
13 | ref.current.start()
14 | }
15 | }
16 |
17 | return (
18 | <>
19 |
22 | toggle()}>Toggle
23 | ref.current!.clear()}>Clear
24 |
25 |
37 | >
38 | )
39 | }
40 |
--------------------------------------------------------------------------------
/examples/with-react/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { createRoot } from 'react-dom/client'
3 | import { App } from './App'
4 |
5 | const app = document.querySelector('#app')!
6 | createRoot(app).render(
7 |
8 |
9 |
10 | )
11 |
--------------------------------------------------------------------------------
/examples/with-react/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/examples/with-react/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "lib": [
6 | "DOM",
7 | "DOM.Iterable",
8 | "ESNext"
9 | ],
10 | "allowJs": false,
11 | "skipLibCheck": true,
12 | "esModuleInterop": false,
13 | "allowSyntheticDefaultImports": true,
14 | "strict": true,
15 | "forceConsistentCasingInFileNames": true,
16 | "module": "ESNext",
17 | "moduleResolution": "Node",
18 | "resolveJsonModule": true,
19 | "isolatedModules": true,
20 | "noEmit": true,
21 | "jsx": "react-jsx"
22 | },
23 | "include": [
24 | "src"
25 | ],
26 | "references": [
27 | {
28 | "path": "./tsconfig.node.json"
29 | }
30 | ]
31 | }
32 |
--------------------------------------------------------------------------------
/examples/with-react/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "esnext",
5 | "moduleResolution": "node"
6 | },
7 | "include": [
8 | "vite.config.ts"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/examples/with-react/vite.config.ts:
--------------------------------------------------------------------------------
1 | import react from '@vitejs/plugin-react'
2 | import { defineConfig } from 'vite'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()]
7 | })
8 |
--------------------------------------------------------------------------------
/examples/with-solid/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | @fireworks-js/solid
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/examples/with-solid/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-solid",
3 | "private": true,
4 | "version": "0.0.0",
5 | "scripts": {
6 | "dev": "vite",
7 | "build": "vite build",
8 | "preview": "vite preview"
9 | },
10 | "dependencies": {
11 | "@fireworks-js/solid": "workspace:*",
12 | "solid-js": "1.5.7"
13 | },
14 | "devDependencies": {
15 | "typescript": "4.8.4",
16 | "vite-plugin-solid": "2.3.9"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/examples/with-solid/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { Fireworks, FireworksHandlers } from '@fireworks-js/solid'
2 | import { createSignal, Show } from 'solid-js'
3 |
4 | export function App() {
5 | const [enabled, setEnabled] = createSignal(true)
6 | let fireworks: FireworksHandlers
7 |
8 | // https://github.com/solidjs/solid/issues/116#issuecomment-583247897
9 | setTimeout(() => console.log(fireworks))
10 |
11 | const toggleFireworks = () => {
12 | if (fireworks.isRunning) {
13 | fireworks.waitStop()
14 | } else {
15 | fireworks.start()
16 | }
17 | }
18 |
19 | return (
20 | <>
21 |
29 | setEnabled(!enabled())}>
30 | {enabled() ? 'Enabled' : 'Disabled'}
31 |
32 | toggleFireworks()}>Toggle
33 |
34 |
35 | (fireworks = ref)}
37 | options={{ opacity: 0.5 }}
38 | style={{
39 | top: 0,
40 | left: 0,
41 | width: '100%',
42 | height: '100%',
43 | position: 'fixed',
44 | background: '#000'
45 | }}
46 | />
47 |
48 | >
49 | )
50 | }
51 |
--------------------------------------------------------------------------------
/examples/with-solid/src/index.tsx:
--------------------------------------------------------------------------------
1 | import { render } from 'solid-js/web'
2 | import { App } from './App'
3 |
4 | const app = document.querySelector('#app')!
5 | render(() => , app)
6 |
--------------------------------------------------------------------------------
/examples/with-solid/src/vite-end.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/examples/with-solid/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "strict": true,
4 | "target": "ESNext",
5 | "module": "ESNext",
6 | "moduleResolution": "node",
7 | "allowSyntheticDefaultImports": true,
8 | "esModuleInterop": true,
9 | "jsx": "preserve",
10 | "jsxImportSource": "solid-js",
11 | "noEmit": true,
12 | "isolatedModules": true
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/examples/with-solid/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import solidPlugin from 'vite-plugin-solid'
3 |
4 | export default defineConfig({
5 | plugins: [solidPlugin()],
6 | build: {
7 | target: 'esnext',
8 | polyfillDynamicImport: false
9 | }
10 | })
11 |
--------------------------------------------------------------------------------
/examples/with-svelte/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | @fireworks-js/svelte
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/examples/with-svelte/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-svelte",
3 | "type": "module",
4 | "private": true,
5 | "version": "0.0.0",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview",
10 | "check": "svelte-check --tsconfig ./tsconfig.json"
11 | },
12 | "dependencies": {
13 | "@fireworks-js/svelte": "workspace:*",
14 | "svelte": "3.50.1"
15 | },
16 | "devDependencies": {
17 | "@sveltejs/vite-plugin-svelte": "1.0.8",
18 | "@tsconfig/svelte": "3.0.0",
19 | "svelte-check": "2.9.1",
20 | "svelte-preprocess": "4.10.7",
21 | "typescript": "4.8.4"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/examples/with-svelte/src/App.svelte:
--------------------------------------------------------------------------------
1 |
26 |
27 |
28 |
29 | (mounted = !mounted)}>
30 | {mounted ? 'Mounted' : 'Unmounted'}
31 |
32 |
33 | {#if mounted}
34 |
39 | {/if}
40 |
41 |
42 |
59 |
--------------------------------------------------------------------------------
/examples/with-svelte/src/index.ts:
--------------------------------------------------------------------------------
1 | import App from './App.svelte'
2 |
3 | const app = new App({
4 | target: document.getElementById('app')
5 | })
6 |
7 | export default app
8 |
--------------------------------------------------------------------------------
/examples/with-svelte/src/shim.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
--------------------------------------------------------------------------------
/examples/with-svelte/svelte.config.js:
--------------------------------------------------------------------------------
1 | import sveltePreprocess from 'svelte-preprocess'
2 |
3 | export default {
4 | // Consult https://github.com/sveltejs/svelte-preprocess
5 | // for more information about preprocessors
6 | preprocess: sveltePreprocess()
7 | }
8 |
--------------------------------------------------------------------------------
/examples/with-svelte/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@tsconfig/svelte/tsconfig.json",
3 | "compilerOptions": {
4 | "target": "esnext",
5 | "useDefineForClassFields": true,
6 | "module": "esnext",
7 | "resolveJsonModule": true,
8 | "baseUrl": ".",
9 | "isolatedModules": true
10 | },
11 | "include": [
12 | "src/**/*.d.ts",
13 | "src/**/*.ts",
14 | "src/**/*.js",
15 | "src/**/*.svelte"
16 | ],
17 | "references": [
18 | {
19 | "path": "./tsconfig.node.json"
20 | }
21 | ]
22 | }
23 |
--------------------------------------------------------------------------------
/examples/with-svelte/tsconfig.node.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "composite": true,
4 | "module": "esnext",
5 | "moduleResolution": "node"
6 | },
7 | "include": [
8 | "vite.config.ts"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/examples/with-svelte/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { svelte } from '@sveltejs/vite-plugin-svelte'
2 | import { defineConfig } from 'vite'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [svelte()]
7 | })
8 |
--------------------------------------------------------------------------------
/examples/with-vue/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | @fireworks-js/vue
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/examples/with-vue/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-vue",
3 | "private": true,
4 | "version": "0.0.0",
5 | "scripts": {
6 | "dev": "vite",
7 | "build": "vite build"
8 | },
9 | "dependencies": {
10 | "@fireworks-js/vue": "workspace:*",
11 | "vue": "3.2.40"
12 | },
13 | "devDependencies": {
14 | "@vitejs/plugin-vue": "3.1.2",
15 | "typescript": "4.8.4"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/examples/with-vue/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ mounted ? 'Mounted' : 'Unmounted' }}
5 |
6 | Start
7 |
8 |
22 |
23 |
24 |
42 |
43 |
55 |
--------------------------------------------------------------------------------
/examples/with-vue/src/index.ts:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue'
2 | import App from './App.vue'
3 |
4 | createApp(App).mount('#app')
5 |
--------------------------------------------------------------------------------
/examples/with-vue/src/shim.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | declare module '*.vue' {
4 | import type { DefineComponent } from 'vue'
5 | const component: DefineComponent<{}, {}, any>
6 | export default component
7 | }
8 |
--------------------------------------------------------------------------------
/examples/with-vue/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@crashmax/tsconfig",
3 | "compilerOptions": {
4 | "jsx": "preserve",
5 | "moduleResolution": "node"
6 | },
7 | "include": [
8 | "src/**/*"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/examples/with-vue/vite.config.js:
--------------------------------------------------------------------------------
1 | import vue from '@vitejs/plugin-vue'
2 | import { defineConfig } from 'vite'
3 |
4 | export default defineConfig({
5 | plugins: [vue()]
6 | })
7 |
--------------------------------------------------------------------------------
/examples/with-web-components/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | @fireworks-js/web
8 |
9 |
10 |
11 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/examples/with-web-components/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-web-components",
3 | "private": true,
4 | "version": "0.0.0",
5 | "scripts": {
6 | "dev": "vite",
7 | "build": "vite build",
8 | "preview": "vite preview"
9 | },
10 | "dependencies": {
11 | "@fireworks-js/web": "workspace:*"
12 | },
13 | "devDependencies": {
14 | "typescript": "4.8.4"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/examples/with-web-components/src/index.ts:
--------------------------------------------------------------------------------
1 | import '@fireworks-js/web'
2 |
--------------------------------------------------------------------------------
/examples/with-web-components/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "useDefineForClassFields": true,
5 | "module": "ESNext",
6 | "lib": [
7 | "ESNext",
8 | "DOM"
9 | ],
10 | "moduleResolution": "Node",
11 | "strict": true,
12 | "sourceMap": true,
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "esModuleInterop": true,
16 | "noEmit": true,
17 | "noUnusedLocals": true,
18 | "noUnusedParameters": true,
19 | "noImplicitReturns": true,
20 | "skipLibCheck": true
21 | },
22 | "include": [
23 | "src"
24 | ]
25 | }
26 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@fireworks-js/monorepo",
3 | "version": "2.10.7",
4 | "private": true,
5 | "type": "module",
6 | "description": "A simple fireworks library!",
7 | "homepage": "https://fireworks.js.org",
8 | "packageManager": "pnpm@8.0.0",
9 | "workspaces": [
10 | "packages/*",
11 | "examples/*",
12 | "website"
13 | ],
14 | "scripts": {
15 | "dev": "turbo run dev --filter=./packages/*",
16 | "build": "turbo run build --filter=./packages/*",
17 | "dev:website": "turbo run dev --filter=./website",
18 | "build:website": "turbo run build --filter=./website",
19 | "dev:examples": "turbo run dev --filter=./examples/*",
20 | "build:examples": "turbo run build --filter=./examples/*",
21 | "format": "prettier --write --ignore-unknown **",
22 | "changesets": "changeset"
23 | },
24 | "repository": {
25 | "type": "git",
26 | "url": "git+https://github.com/crashmax-dev/fireworks-js.git"
27 | },
28 | "keywords": [
29 | "react",
30 | "preact",
31 | "solid",
32 | "vue",
33 | "angular",
34 | "svelte",
35 | "web-components",
36 | "canvas",
37 | "fireworks",
38 | "animation"
39 | ],
40 | "author": {
41 | "name": "Vitalij Ryndin",
42 | "email": "sys@crashmax.ru",
43 | "url": "https://crashmax.ru"
44 | },
45 | "license": "MIT",
46 | "bugs": {
47 | "url": "https://github.com/crashmax-dev/fireworks-js/issues"
48 | },
49 | "devDependencies": {
50 | "@changesets/cli": "2.26.2",
51 | "@crashmax/prettier-config": "2.2.1",
52 | "@crashmax/tsconfig": "1.0.2",
53 | "@types/node": "18.11.9",
54 | "del-cli": "5.0.0",
55 | "tsx": "3.11.0",
56 | "turbo": "1.6.3",
57 | "typescript": "4.8.4",
58 | "vite": "3.2.2",
59 | "vite-plugin-banner": "0.6.1",
60 | "vite-plugin-dts": "1.6.6"
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/packages/angular/README.md:
--------------------------------------------------------------------------------
1 | # @fireworks-js/angular
2 |
3 | > https://github.com/crashmax-dev/fireworks-js
4 |
--------------------------------------------------------------------------------
/packages/angular/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "ng-fireworks": {
7 | "projectType": "library",
8 | "root": "projects/ng-fireworks",
9 | "sourceRoot": "projects/ng-fireworks/src",
10 | "prefix": "lib",
11 | "architect": {
12 | "build": {
13 | "builder": "@angular-devkit/build-angular:ng-packagr",
14 | "options": {
15 | "project": "projects/ng-fireworks/ng-package.json"
16 | },
17 | "configurations": {
18 | "production": {
19 | "tsConfig": "projects/ng-fireworks/tsconfig.lib.prod.json"
20 | },
21 | "development": {
22 | "tsConfig": "projects/ng-fireworks/tsconfig.lib.json"
23 | }
24 | },
25 | "defaultConfiguration": "production"
26 | }
27 | }
28 | }
29 | },
30 | "cli": {
31 | "analytics": false
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/packages/angular/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@fireworks-js/angular",
3 | "private": true,
4 | "version": "2.10.7",
5 | "typings": "./dist/ng-fireworks/index.d.ts",
6 | "exports": {
7 | "./package.json": {
8 | "default": "./dist/ng-fireworks/package.json"
9 | },
10 | ".": {
11 | "types": "./dist/ng-fireworks/index.d.ts",
12 | "esm2020": "./dist/ng-fireworks/esm2020/fireworks-js-angular.mjs",
13 | "es2020": "./dist/ng-fireworks/fesm2020/fireworks-js-angular.mjs",
14 | "es2015": "./dist/ng-fireworks/fesm2015/fireworks-js-angular.mjs",
15 | "node": "./dist/ng-fireworks/fesm2015/fireworks-js-angular.mjs",
16 | "default": "./dist/ng-fireworks/fesm2020/fireworks-js-angular.mjs"
17 | }
18 | },
19 | "scripts": {
20 | "ng": "ng",
21 | "start": "ng serve",
22 | "build": "ng build",
23 | "watch": "ng build --watch --configuration development"
24 | },
25 | "dependencies": {
26 | "@angular/animations": "^14.1.2",
27 | "@angular/common": "^14.1.2",
28 | "@angular/compiler": "^14.1.2",
29 | "@angular/core": "^14.1.2",
30 | "@angular/forms": "^14.1.2",
31 | "@angular/platform-browser": "^14.1.2",
32 | "@angular/platform-browser-dynamic": "^14.1.2",
33 | "@angular/router": "^14.1.2",
34 | "fireworks-js": "workspace:2.10.7",
35 | "rxjs": "~7.5.6",
36 | "tslib": "2.4.0",
37 | "zone.js": "~0.11.8"
38 | },
39 | "devDependencies": {
40 | "@angular-devkit/build-angular": "^14.1.2",
41 | "@angular/cli": "~14.0.7",
42 | "@angular/compiler-cli": "^14.1.2",
43 | "@types/jasmine": "~4.0.3",
44 | "jasmine-core": "~4.1.1",
45 | "ng-packagr": "^14.1.0"
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/packages/angular/projects/ng-fireworks/.browserslistrc:
--------------------------------------------------------------------------------
1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 |
5 | # For the full list of supported browsers by the Angular framework, please see:
6 | # https://angular.io/guide/browser-support
7 |
8 | # You can see what browsers were selected by your queries by running:
9 | # npx browserslist
10 |
11 | last 1 Chrome version
12 | last 1 Firefox version
13 | last 2 Edge major versions
14 | last 2 Safari major versions
15 | last 2 iOS major versions
16 | Firefox ESR
17 |
--------------------------------------------------------------------------------
/packages/angular/projects/ng-fireworks/ng-package.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
3 | "dest": "../../dist/ng-fireworks",
4 | "lib": {
5 | "entryFile": "src/public-api.ts"
6 | },
7 | "allowedNonPeerDependencies": [
8 | "fireworks-js"
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/angular/projects/ng-fireworks/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@fireworks-js/angular",
3 | "version": "2.10.7",
4 | "description": "A simple fireworks library!",
5 | "homepage": "https://fireworks.js.org",
6 | "repository": {
7 | "type": "git",
8 | "url": "git+https://github.com/crashmax-dev/fireworks-js.git"
9 | },
10 | "keywords": [
11 | "angular",
12 | "canvas",
13 | "fireworks",
14 | "animation"
15 | ],
16 | "author": {
17 | "name": "Vitalij Ryndin",
18 | "email": "sys@crashmax.ru",
19 | "url": "https://crashmax.ru"
20 | },
21 | "license": "MIT",
22 | "bugs": {
23 | "url": "https://github.com/crashmax-dev/fireworks-js/issues"
24 | },
25 | "peerDependencies": {
26 | "@angular/common": "^12.0.0",
27 | "@angular/core": "^12.0.0"
28 | },
29 | "dependencies": {
30 | "fireworks-js": "workspace:2.10.7",
31 | "tslib": "2.5.0"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/packages/angular/projects/ng-fireworks/src/lib/ng-fireworks.directive.ts:
--------------------------------------------------------------------------------
1 | import { Directive, ElementRef, Input } from '@angular/core'
2 | import { Fireworks } from 'fireworks-js'
3 | import type { FireworksOptions } from 'fireworks-js'
4 |
5 | @Directive({
6 | selector: '[ngFireworks], ng-fireworks',
7 | exportAs: 'ngFireworks'
8 | })
9 | export class FireworksDirective extends Fireworks {
10 | constructor(elRef: ElementRef) {
11 | super(elRef.nativeElement)
12 | }
13 |
14 | @Input() options!: FireworksOptions
15 |
16 | private ngOnInit() {
17 | this.updateOptions(this.options)
18 | this.updateSize()
19 | this.start()
20 | }
21 |
22 | private ngOnDestroy(): void {
23 | this.stop()
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/packages/angular/projects/ng-fireworks/src/lib/ng-fireworks.module.ts:
--------------------------------------------------------------------------------
1 | import { NgModule } from '@angular/core'
2 | import { FireworksDirective } from './ng-fireworks.directive'
3 |
4 | export type { FireworksOptions } from 'fireworks-js'
5 |
6 | @NgModule({
7 | declarations: [FireworksDirective],
8 | exports: [FireworksDirective]
9 | })
10 | export class NgFireworksModule {}
11 |
--------------------------------------------------------------------------------
/packages/angular/projects/ng-fireworks/src/public-api.ts:
--------------------------------------------------------------------------------
1 | export * from './lib/ng-fireworks.directive'
2 | export * from './lib/ng-fireworks.module'
3 |
--------------------------------------------------------------------------------
/packages/angular/projects/ng-fireworks/tsconfig.lib.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "../../tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "../../out-tsc/lib",
6 | "declaration": true,
7 | "declarationMap": true,
8 | "inlineSources": true,
9 | "types": []
10 | },
11 | "exclude": [
12 | "src/test.ts",
13 | "**/*.spec.ts"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/packages/angular/projects/ng-fireworks/tsconfig.lib.prod.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.lib.json",
4 | "compilerOptions": {
5 | "declarationMap": false
6 | },
7 | "angularCompilerOptions": {
8 | "compilationMode": "partial"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/packages/angular/tsconfig.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "compileOnSave": false,
4 | "compilerOptions": {
5 | "baseUrl": "./",
6 | "outDir": "./dist/out-tsc",
7 | "forceConsistentCasingInFileNames": true,
8 | "strict": true,
9 | "noImplicitOverride": true,
10 | "noPropertyAccessFromIndexSignature": true,
11 | "noImplicitReturns": true,
12 | "noFallthroughCasesInSwitch": true,
13 | "sourceMap": true,
14 | "paths": {
15 | "ng-fireworks": [
16 | "dist/ng-fireworks"
17 | ]
18 | },
19 | "declaration": false,
20 | "downlevelIteration": true,
21 | "experimentalDecorators": true,
22 | "moduleResolution": "node",
23 | "importHelpers": true,
24 | "target": "es2020",
25 | "module": "es2020",
26 | "lib": [
27 | "es2020",
28 | "dom"
29 | ]
30 | },
31 | "angularCompilerOptions": {
32 | "enableI18nLegacyMessageIdFormat": false,
33 | "strictInjectionParameters": true,
34 | "strictInputAccessModifiers": true,
35 | "strictTemplates": true
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/packages/fireworks-js/README.md:
--------------------------------------------------------------------------------
1 | # fireworks-js
2 |
3 | > https://github.com/crashmax-dev/fireworks-js
4 |
--------------------------------------------------------------------------------
/packages/fireworks-js/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fireworks-js",
3 | "version": "2.10.7",
4 | "type": "module",
5 | "description": "A simple fireworks library!",
6 | "homepage": "https://fireworks.js.org",
7 | "types": "./dist/index.d.ts",
8 | "main": "./dist/index.cjs.js",
9 | "jsdelivr": "./dist/index.umd.js",
10 | "unpkg": "./dist/index.umd.js",
11 | "module": "./dist/index.es.js",
12 | "exports": {
13 | "require": "./dist/index.cjs.js",
14 | "import": "./dist/index.es.js",
15 | "types": "./dist/index.d.ts"
16 | },
17 | "files": [
18 | "dist"
19 | ],
20 | "repository": {
21 | "type": "git",
22 | "url": "git+https://github.com/crashmax-dev/fireworks-js.git"
23 | },
24 | "keywords": [
25 | "canvas",
26 | "fireworks",
27 | "animation"
28 | ],
29 | "author": {
30 | "name": "Vitalij Ryndin",
31 | "email": "sys@crashmax.ru",
32 | "url": "https://crashmax.ru"
33 | },
34 | "license": "MIT",
35 | "bugs": {
36 | "url": "https://github.com/crashmax-dev/fireworks-js/issues"
37 | },
38 | "scripts": {
39 | "dev": "vite build --watch",
40 | "build": "vite build",
41 | "prepublishOnly": "pnpm build"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/packages/fireworks-js/src/explosion.ts:
--------------------------------------------------------------------------------
1 | import { hsla, randomFloat, randomInt } from './helpers.js'
2 | import type { FireworksTypes } from './types.js'
3 |
4 | export class Explosion {
5 | private x: number
6 | private y: number
7 | private ctx: CanvasRenderingContext2D
8 | private hue: number
9 | private friction: number
10 | private gravity: number
11 | private flickering: boolean
12 | private lineWidth: number
13 | private explosionLength: number
14 |
15 | private angle: number
16 | private speed: number
17 | private brightness: number
18 | private coordinates: [number, number][] = []
19 | private decay: number
20 | private alpha = 1
21 |
22 | constructor({
23 | x,
24 | y,
25 | ctx,
26 | hue,
27 | decay,
28 | gravity,
29 | friction,
30 | brightness,
31 | flickering,
32 | lineWidth,
33 | explosionLength
34 | }: FireworksTypes.Explosion) {
35 | this.x = x
36 | this.y = y
37 | this.ctx = ctx
38 | this.hue = hue
39 | this.gravity = gravity
40 | this.friction = friction
41 | this.flickering = flickering
42 | this.lineWidth = lineWidth
43 | this.explosionLength = explosionLength
44 | this.angle = randomFloat(0, Math.PI * 2)
45 | this.speed = randomInt(1, 10)
46 | this.brightness = randomInt(brightness.min, brightness.max)
47 | this.decay = randomFloat(decay.min, decay.max)
48 |
49 | while (this.explosionLength--) {
50 | this.coordinates.push([x, y])
51 | }
52 | }
53 |
54 | update(callback: () => void): void {
55 | this.coordinates.pop()
56 | this.coordinates.unshift([this.x, this.y])
57 | this.speed *= this.friction
58 | this.x += Math.cos(this.angle) * this.speed
59 | this.y += Math.sin(this.angle) * this.speed + this.gravity
60 | this.alpha -= this.decay
61 |
62 | if (this.alpha <= this.decay) {
63 | callback()
64 | }
65 | }
66 |
67 | draw(): void {
68 | const lastIndex = this.coordinates.length - 1
69 |
70 | this.ctx.beginPath()
71 | this.ctx.lineWidth = this.lineWidth
72 | this.ctx.fillStyle = hsla(this.hue, this.brightness, this.alpha)
73 | this.ctx.moveTo(
74 | this.coordinates[lastIndex]![0],
75 | this.coordinates[lastIndex]![1]
76 | )
77 | this.ctx.lineTo(this.x, this.y)
78 | this.ctx.strokeStyle = hsla(
79 | this.hue,
80 | this.flickering ? randomFloat(0, this.brightness) : this.brightness,
81 | this.alpha
82 | )
83 | this.ctx.stroke()
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/packages/fireworks-js/src/fireworks.ts:
--------------------------------------------------------------------------------
1 | import { Explosion } from './explosion.js'
2 | import { floor, randomFloat, randomInt } from './helpers.js'
3 | import { Mouse } from './mouse.js'
4 | import { Options } from './options.js'
5 | import { RequestAnimationFrame } from './raf.js'
6 | import { Resize } from './resize.js'
7 | import { Sound } from './sound.js'
8 | import { Trace } from './trace.js'
9 | import type { FireworksOptions, FireworksTypes } from './types.js'
10 |
11 | declare const __VERSION__: string
12 |
13 | export class Fireworks {
14 | private target: Element | HTMLCanvasElement
15 | private container: Element
16 | private canvas: HTMLCanvasElement
17 | private ctx: CanvasRenderingContext2D
18 | private width: number
19 | private height: number
20 | private traces: Trace[] = []
21 | private explosions: Explosion[] = []
22 | private waitStopRaf: (() => void) | null
23 | private running = false
24 |
25 | private readonly opts: Options
26 | private readonly sound: Sound
27 | private readonly resize: Resize
28 | private readonly mouse: Mouse
29 | private readonly raf: RequestAnimationFrame
30 |
31 | constructor(
32 | container: Element | HTMLCanvasElement,
33 | options: FireworksOptions = {}
34 | ) {
35 | this.target = container
36 | this.container = container
37 |
38 | this.opts = new Options()
39 |
40 | this.createCanvas(this.target)
41 | this.updateOptions(options)
42 |
43 | this.sound = new Sound(this.opts)
44 | this.resize = new Resize(
45 | this.opts,
46 | this.updateSize.bind(this),
47 | this.container
48 | )
49 | this.mouse = new Mouse(this.opts, this.canvas)
50 | this.raf = new RequestAnimationFrame(this.opts, this.render.bind(this))
51 | }
52 |
53 | get isRunning(): boolean {
54 | return this.running
55 | }
56 |
57 | get version(): string {
58 | return __VERSION__
59 | }
60 |
61 | get currentOptions(): Options {
62 | return this.opts
63 | }
64 |
65 | start(): void {
66 | if (this.running) return
67 |
68 | if (!this.canvas.isConnected) {
69 | this.createCanvas(this.target)
70 | }
71 |
72 | this.running = true
73 | this.resize.mount()
74 | this.mouse.mount()
75 | this.raf.mount()
76 | }
77 |
78 | stop(dispose = false): void {
79 | if (!this.running) return
80 |
81 | this.running = false
82 | this.resize.unmount()
83 | this.mouse.unmount()
84 | this.raf.unmount()
85 | this.clear()
86 |
87 | if (dispose) {
88 | this.canvas.remove()
89 | }
90 | }
91 |
92 | async waitStop(dispose?: boolean): Promise {
93 | if (!this.running) return
94 |
95 | return new Promise((resolve) => {
96 | this.waitStopRaf = () => {
97 | if (!this.waitStopRaf) return
98 | requestAnimationFrame(this.waitStopRaf)
99 | if (!this.traces.length && !this.explosions.length) {
100 | this.waitStopRaf = null
101 | this.stop(dispose)
102 | resolve()
103 | }
104 | }
105 |
106 | this.waitStopRaf()
107 | })
108 | }
109 |
110 | pause(): void {
111 | this.running = !this.running
112 | if (this.running) {
113 | this.raf.mount()
114 | } else {
115 | this.raf.unmount()
116 | }
117 | }
118 |
119 | clear(): void {
120 | if (!this.ctx) return
121 |
122 | this.traces = []
123 | this.explosions = []
124 | this.ctx.clearRect(0, 0, this.width, this.height)
125 | }
126 |
127 | launch(count = 1): void {
128 | for (let i = 0; i < count; i++) {
129 | this.createTrace()
130 | }
131 |
132 | if (!this.waitStopRaf) {
133 | this.start()
134 | this.waitStop()
135 | }
136 | }
137 |
138 | updateOptions(options: FireworksOptions): void {
139 | this.opts.update(options)
140 | }
141 |
142 | updateSize({
143 | width = this.container.clientWidth,
144 | height = this.container.clientHeight
145 | }: Partial = {}): void {
146 | this.width = width
147 | this.height = height
148 |
149 | this.canvas.width = width
150 | this.canvas.height = height
151 |
152 | this.updateBoundaries({
153 | ...this.opts.boundaries,
154 | width,
155 | height
156 | })
157 | }
158 |
159 | updateBoundaries(boundaries: Partial): void {
160 | this.updateOptions({ boundaries })
161 | }
162 |
163 | private createCanvas(el: Element | HTMLCanvasElement): void {
164 | if (el instanceof HTMLCanvasElement) {
165 | if (!el.isConnected) {
166 | document.body.append(el)
167 | }
168 |
169 | this.canvas = el
170 | } else {
171 | this.canvas = document.createElement('canvas')
172 | this.container.append(this.canvas)
173 | }
174 |
175 | this.ctx = this.canvas.getContext('2d')!
176 | this.updateSize()
177 | }
178 |
179 | private render(): void {
180 | if (!this.ctx || !this.running) return
181 |
182 | const { opacity, lineStyle, lineWidth } = this.opts
183 | this.ctx.globalCompositeOperation = 'destination-out'
184 | this.ctx.fillStyle = `rgba(0, 0, 0, ${opacity})`
185 | this.ctx.fillRect(0, 0, this.width, this.height)
186 | this.ctx.globalCompositeOperation = 'lighter'
187 | this.ctx.lineCap = lineStyle
188 | this.ctx.lineJoin = 'round'
189 | this.ctx.lineWidth = randomFloat(lineWidth.trace.min, lineWidth.trace.max)
190 |
191 | this.initTrace()
192 | this.drawTrace()
193 | this.drawExplosion()
194 | }
195 |
196 | private createTrace(): void {
197 | const {
198 | hue,
199 | rocketsPoint,
200 | boundaries,
201 | traceLength,
202 | traceSpeed,
203 | acceleration,
204 | mouse
205 | } = this.opts
206 |
207 | this.traces.push(
208 | new Trace({
209 | x: (this.width * randomInt(rocketsPoint.min, rocketsPoint.max)) / 100,
210 | y: this.height,
211 | dx:
212 | (this.mouse.x && mouse.move) || this.mouse.active
213 | ? this.mouse.x
214 | : randomInt(boundaries.x, boundaries.width - boundaries.x * 2),
215 | dy:
216 | (this.mouse.y && mouse.move) || this.mouse.active
217 | ? this.mouse.y
218 | : randomInt(boundaries.y, boundaries.height * 0.5),
219 | ctx: this.ctx,
220 | hue: randomInt(hue.min, hue.max),
221 | speed: traceSpeed,
222 | acceleration,
223 | traceLength: floor(traceLength)
224 | })
225 | )
226 | }
227 |
228 | private initTrace(): void {
229 | if (this.waitStopRaf) return
230 |
231 | const { delay, mouse } = this.opts
232 | if (
233 | this.raf.tick > randomInt(delay.min, delay.max) ||
234 | (this.mouse.active && mouse.max > this.traces.length)
235 | ) {
236 | this.createTrace()
237 | this.raf.tick = 0
238 | }
239 | }
240 |
241 | private drawTrace(): void {
242 | let traceLength = this.traces.length
243 | while (traceLength--) {
244 | this.traces[traceLength]!.draw()
245 | this.traces[traceLength]!.update((x: number, y: number, hue: number) => {
246 | this.initExplosion(x, y, hue)
247 | this.sound.play()
248 | this.traces.splice(traceLength, 1)
249 | })
250 | }
251 | }
252 |
253 | private initExplosion(x: number, y: number, hue: number): void {
254 | const {
255 | particles,
256 | flickering,
257 | lineWidth,
258 | explosion,
259 | brightness,
260 | friction,
261 | gravity,
262 | decay
263 | } = this.opts
264 |
265 | let particlesLength = floor(particles)
266 | while (particlesLength--) {
267 | this.explosions.push(
268 | new Explosion({
269 | x,
270 | y,
271 | ctx: this.ctx,
272 | hue,
273 | friction,
274 | gravity,
275 | flickering: randomInt(0, 100) <= flickering,
276 | lineWidth: randomFloat(
277 | lineWidth.explosion.min,
278 | lineWidth.explosion.max
279 | ),
280 | explosionLength: floor(explosion),
281 | brightness,
282 | decay
283 | })
284 | )
285 | }
286 | }
287 |
288 | private drawExplosion(): void {
289 | let length = this.explosions.length
290 | while (length--) {
291 | this.explosions[length]!.draw()
292 | this.explosions[length]!.update(() => {
293 | this.explosions.splice(length, 1)
294 | })
295 | }
296 | }
297 | }
298 |
--------------------------------------------------------------------------------
/packages/fireworks-js/src/helpers.ts:
--------------------------------------------------------------------------------
1 | export function floor(num: number): number {
2 | return Math.abs(Math.floor(num))
3 | }
4 |
5 | export function randomFloat(min: number, max: number): number {
6 | return Math.random() * (max - min) + min
7 | }
8 |
9 | export function randomInt(min: number, max: number): number {
10 | return Math.floor(randomFloat(min, max + 1))
11 | }
12 |
13 | export function getDistance(
14 | x: number,
15 | y: number,
16 | dx: number,
17 | dy: number
18 | ): number {
19 | const pow = Math.pow
20 | return Math.sqrt(pow(x - dx, 2) + pow(y - dy, 2))
21 | }
22 |
23 | export function hsla(hue: number, lightness: number, alpha = 1): string {
24 | if (hue > 360 || hue < 0) {
25 | throw new Error(`Expected hue 0-360 range, got \`${hue}\``)
26 | }
27 |
28 | if (lightness > 100 || lightness < 0) {
29 | throw new Error(`Expected lightness 0-100 range, got \`${lightness}\``)
30 | }
31 |
32 | if (alpha > 1 || alpha < 0) {
33 | throw new Error(`Expected alpha 0-1 range, got \`${alpha}\``)
34 | }
35 |
36 | return `hsla(${hue}, 100%, ${lightness}%, ${alpha})`
37 | }
38 |
39 | /* https://github.com/voodoocreation/ts-deepmerge */
40 | interface IObject {
41 | [key: string]: any
42 | length?: never
43 | }
44 |
45 | type IUnionToIntersection = (
46 | U extends any ? (k: U) => void : never
47 | ) extends (k: infer I) => void
48 | ? I
49 | : never
50 |
51 | const isObject = (obj: any) => {
52 | if (typeof obj === 'object' && obj !== null) {
53 | if (typeof Object.getPrototypeOf === 'function') {
54 | const prototype = Object.getPrototypeOf(obj)
55 | return prototype === Object.prototype || prototype === null
56 | }
57 |
58 | return Object.prototype.toString.call(obj) === '[object Object]'
59 | }
60 |
61 | return false
62 | }
63 |
64 | const PROTECTED_KEYS = [
65 | '__proto__',
66 | 'constructor',
67 | 'prototype'
68 | ]
69 |
70 | export const deepMerge = (
71 | ...objects: T
72 | ): IUnionToIntersection => {
73 | return objects.reduce((result, current) => {
74 | Object.keys(current).forEach((key) => {
75 | if (PROTECTED_KEYS.includes(key)) {
76 | return
77 | }
78 |
79 | if (Array.isArray(result[key]) && Array.isArray(current[key])) {
80 | result[key] = false
81 | ? Array.from(new Set((result[key] as unknown[]).concat(current[key])))
82 | : current[key]
83 | } else if (isObject(result[key]) && isObject(current[key])) {
84 | result[key] = deepMerge(result[key] as IObject, current[key] as IObject)
85 | } else {
86 | result[key] = current[key]
87 | }
88 | })
89 |
90 | return result
91 | }, {}) as any
92 | }
93 |
94 | // https://github.com/zero-dependency/utils/blob/master/src/debounce.ts
95 | export function debounce void>(
96 | fn: T,
97 | ms: number
98 | ): (...args: Parameters) => void {
99 | let timeoutId: ReturnType
100 |
101 | return (...args) => {
102 | if (timeoutId) {
103 | clearTimeout(timeoutId)
104 | }
105 |
106 | timeoutId = setTimeout(() => fn(...args), ms)
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/packages/fireworks-js/src/index.ts:
--------------------------------------------------------------------------------
1 | import { Fireworks } from './fireworks.js'
2 | import type {
3 | FireworksHandlers,
4 | FireworksOptions,
5 | FireworksTypes
6 | } from './types.js'
7 |
8 | export { Fireworks }
9 | export default Fireworks
10 | export type { FireworksTypes, FireworksOptions, FireworksHandlers }
11 |
--------------------------------------------------------------------------------
/packages/fireworks-js/src/mouse.ts:
--------------------------------------------------------------------------------
1 | import type { Options } from './options.js'
2 |
3 | export class Mouse {
4 | active = false
5 | x: number
6 | y: number
7 |
8 | constructor(
9 | private readonly options: Options,
10 | private readonly canvas: HTMLCanvasElement
11 | ) {
12 | this.pointerDown = this.pointerDown.bind(this)
13 | this.pointerUp = this.pointerUp.bind(this)
14 | this.pointerMove = this.pointerMove.bind(this)
15 | }
16 |
17 | private get mouseOptions() {
18 | return this.options.mouse
19 | }
20 |
21 | mount(): void {
22 | this.canvas.addEventListener('pointerdown', this.pointerDown)
23 | this.canvas.addEventListener('pointerup', this.pointerUp)
24 | this.canvas.addEventListener('pointermove', this.pointerMove)
25 | }
26 |
27 | unmount(): void {
28 | this.canvas.removeEventListener('pointerdown', this.pointerDown)
29 | this.canvas.removeEventListener('pointerup', this.pointerUp)
30 | this.canvas.removeEventListener('pointermove', this.pointerMove)
31 | }
32 |
33 | private usePointer(event: PointerEvent, active: boolean): void {
34 | const { click, move } = this.mouseOptions
35 | if (click || move) {
36 | this.x = event.pageX - this.canvas.offsetLeft
37 | this.y = event.pageY - this.canvas.offsetTop
38 | this.active = active
39 | }
40 | }
41 |
42 | private pointerDown(event: PointerEvent): void {
43 | this.usePointer(event, this.mouseOptions.click)
44 | }
45 |
46 | private pointerUp(event: PointerEvent): void {
47 | this.usePointer(event, false)
48 | }
49 |
50 | private pointerMove(event: PointerEvent): void {
51 | this.usePointer(event, this.active)
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/packages/fireworks-js/src/options.ts:
--------------------------------------------------------------------------------
1 | import { deepMerge } from './helpers.js'
2 | import type { FireworksOptions, FireworksTypes } from './types.js'
3 |
4 | export class Options implements FireworksTypes.Options {
5 | hue: FireworksTypes.MinMax
6 | rocketsPoint: FireworksTypes.MinMax
7 | opacity: number
8 | acceleration: number
9 | friction: number
10 | gravity: number
11 | particles: number
12 | explosion: number
13 | mouse: FireworksTypes.Mouse
14 | boundaries: FireworksTypes.Boundaries
15 | sound: FireworksTypes.Sounds
16 | delay: FireworksTypes.MinMax
17 | brightness: FireworksTypes.MinMax
18 | decay: FireworksTypes.MinMax
19 | flickering: number
20 | intensity: number
21 | traceLength: number
22 | traceSpeed: number
23 | lineWidth: FireworksTypes.LineWidth
24 | lineStyle: FireworksTypes.LineStyle
25 | autoresize: boolean
26 |
27 | constructor() {
28 | this.autoresize = true
29 | this.lineStyle = 'round'
30 | this.flickering = 50
31 | this.traceLength = 3
32 | this.traceSpeed = 10
33 | this.intensity = 30
34 | this.explosion = 5
35 | this.gravity = 1.5
36 | this.opacity = 0.5
37 | this.particles = 50
38 | this.friction = 0.95
39 | this.acceleration = 1.05
40 |
41 | this.hue = {
42 | min: 0,
43 | max: 360
44 | }
45 |
46 | this.rocketsPoint = {
47 | min: 50,
48 | max: 50
49 | }
50 |
51 | this.lineWidth = {
52 | explosion: {
53 | min: 1,
54 | max: 3
55 | },
56 | trace: {
57 | min: 1,
58 | max: 2
59 | }
60 | }
61 |
62 | this.mouse = {
63 | click: false,
64 | move: false,
65 | max: 1
66 | }
67 |
68 | this.delay = {
69 | min: 30,
70 | max: 60
71 | }
72 |
73 | this.brightness = {
74 | min: 50,
75 | max: 80
76 | }
77 |
78 | this.decay = {
79 | min: 0.015,
80 | max: 0.03
81 | }
82 |
83 | this.sound = {
84 | enabled: false,
85 | files: [
86 | 'explosion0.mp3',
87 | 'explosion1.mp3',
88 | 'explosion2.mp3'
89 | ],
90 | volume: {
91 | min: 4,
92 | max: 8
93 | }
94 | }
95 |
96 | this.boundaries = {
97 | debug: false,
98 | height: 0,
99 | width: 0,
100 | x: 50,
101 | y: 50
102 | }
103 | }
104 |
105 | update(options: T): void {
106 | Object.assign(this, deepMerge(this, options))
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/packages/fireworks-js/src/raf.ts:
--------------------------------------------------------------------------------
1 | import type { Options } from './options.js'
2 |
3 | export class RequestAnimationFrame {
4 | tick = 0
5 |
6 | private rafId = 0
7 | private fps = 60
8 | private tolerance = 0.1
9 | private now: number
10 |
11 | constructor(
12 | private readonly options: Options,
13 | private readonly render: () => void
14 | ) {}
15 |
16 | mount(): void {
17 | this.now = performance.now()
18 | const interval = 1000 / this.fps
19 |
20 | const raf = (timestamp: number) => {
21 | this.rafId = requestAnimationFrame(raf)
22 | const delta = timestamp - this.now
23 |
24 | if (delta >= interval - this.tolerance) {
25 | this.render()
26 | this.now = timestamp - (delta % interval)
27 | this.tick += (delta * (this.options.intensity * Math.PI)) / 1000
28 | }
29 | }
30 |
31 | this.rafId = requestAnimationFrame(raf)
32 | }
33 |
34 | unmount() {
35 | cancelAnimationFrame(this.rafId)
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/packages/fireworks-js/src/resize.ts:
--------------------------------------------------------------------------------
1 | import { debounce } from './helpers.js'
2 | import type { Options } from './options.js'
3 |
4 | export class Resize {
5 | private resizer: ResizeObserver | undefined
6 |
7 | constructor(
8 | private readonly options: Options,
9 | private readonly updateSize: () => void,
10 | private readonly container: Element
11 | ) {}
12 |
13 | mount(): void {
14 | if (!this.resizer) {
15 | const debouncedResize = debounce(() => this.updateSize(), 100)
16 | this.resizer = new ResizeObserver(debouncedResize)
17 | }
18 |
19 | if (this.options.autoresize) {
20 | this.resizer.observe(this.container)
21 | }
22 | }
23 |
24 | unmount(): void {
25 | if (this.resizer) {
26 | this.resizer.unobserve(this.container)
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/packages/fireworks-js/src/sound.ts:
--------------------------------------------------------------------------------
1 | import { randomFloat, randomInt } from './helpers.js'
2 | import type { Options } from './options.js'
3 |
4 | declare global {
5 | interface Window {
6 | webkitAudioContext: typeof AudioContext
7 | }
8 | }
9 |
10 | export class Sound {
11 | private buffers: AudioBuffer[] = []
12 | private audioContext: AudioContext
13 | private onInit = false
14 |
15 | constructor(private readonly options: Options) {
16 | this.init()
17 | }
18 |
19 | private get isEnabled() {
20 | return this.options.sound.enabled
21 | }
22 |
23 | private get soundOptions() {
24 | return this.options.sound
25 | }
26 |
27 | private init(): void {
28 | if (!this.onInit && this.isEnabled) {
29 | this.onInit = true
30 | this.audioContext = new (window.AudioContext ||
31 | window.webkitAudioContext)()
32 | this.loadSounds()
33 | }
34 | }
35 |
36 | private async loadSounds(): Promise {
37 | for (const file of this.soundOptions.files) {
38 | const response = await (await fetch(file)).arrayBuffer()
39 |
40 | this.audioContext
41 | .decodeAudioData(response)
42 | .then((buffer) => {
43 | this.buffers.push(buffer)
44 | })
45 | .catch((err) => {
46 | throw err
47 | })
48 | }
49 | }
50 |
51 | play(): void {
52 | if (this.isEnabled && this.buffers.length) {
53 | const bufferSource = this.audioContext.createBufferSource()
54 | const soundBuffer = this.buffers[randomInt(0, this.buffers.length - 1)]!
55 | const volume = this.audioContext.createGain()
56 |
57 | bufferSource.buffer = soundBuffer
58 | volume.gain.value = randomFloat(
59 | this.soundOptions.volume.min / 100,
60 | this.soundOptions.volume.max / 100
61 | )
62 | volume.connect(this.audioContext.destination)
63 | bufferSource.connect(volume)
64 | bufferSource.start(0)
65 | } else {
66 | this.init()
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/packages/fireworks-js/src/trace.ts:
--------------------------------------------------------------------------------
1 | import { getDistance, hsla, randomInt } from './helpers.js'
2 | import type { FireworksTypes } from './types.js'
3 |
4 | export class Trace {
5 | private x: number
6 | private y: number
7 | private sx: number
8 | private sy: number
9 | private dx: number
10 | private dy: number
11 | private ctx: CanvasRenderingContext2D
12 | private hue: number
13 | private speed: number
14 | private acceleration: number
15 | private traceLength: number
16 |
17 | private totalDistance: number
18 | private angle: number
19 | private brightness: number
20 | private coordinates: [number, number][] = []
21 | private currentDistance = 0
22 |
23 | constructor({
24 | x,
25 | y,
26 | dx,
27 | dy,
28 | ctx,
29 | hue,
30 | speed,
31 | traceLength,
32 | acceleration
33 | }: FireworksTypes.Trace) {
34 | this.x = x
35 | this.y = y
36 | this.sx = x
37 | this.sy = y
38 | this.dx = dx
39 | this.dy = dy
40 | this.ctx = ctx
41 | this.hue = hue
42 | this.speed = speed
43 | this.traceLength = traceLength
44 | this.acceleration = acceleration
45 | this.totalDistance = getDistance(x, y, dx, dy)
46 | this.angle = Math.atan2(dy - y, dx - x)
47 | this.brightness = randomInt(50, 70)
48 |
49 | while (this.traceLength--) {
50 | this.coordinates.push([x, y])
51 | }
52 | }
53 |
54 | update(callback: (x: number, y: number, hue: number) => void): void {
55 | this.coordinates.pop()
56 | this.coordinates.unshift([this.x, this.y])
57 | this.speed *= this.acceleration
58 |
59 | const vx = Math.cos(this.angle) * this.speed
60 | const vy = Math.sin(this.angle) * this.speed
61 |
62 | this.currentDistance = getDistance(
63 | this.sx,
64 | this.sy,
65 | this.x + vx,
66 | this.y + vy
67 | )
68 |
69 | if (this.currentDistance >= this.totalDistance) {
70 | callback(this.dx, this.dy, this.hue)
71 | } else {
72 | this.x += vx
73 | this.y += vy
74 | }
75 | }
76 |
77 | draw(): void {
78 | const lastIndex = this.coordinates.length - 1
79 |
80 | this.ctx.beginPath()
81 | this.ctx.moveTo(
82 | this.coordinates[lastIndex]![0],
83 | this.coordinates[lastIndex]![1]
84 | )
85 | this.ctx.lineTo(this.x, this.y)
86 | this.ctx.strokeStyle = hsla(this.hue, this.brightness)
87 | this.ctx.stroke()
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/packages/fireworks-js/src/types.ts:
--------------------------------------------------------------------------------
1 | import type { Fireworks } from './fireworks.js'
2 |
3 | export namespace FireworksTypes {
4 | export interface Options {
5 | hue: MinMax
6 | rocketsPoint: MinMax
7 | opacity: number
8 | acceleration: number
9 | friction: number
10 | gravity: number
11 | particles: number
12 | explosion: number
13 | mouse: Mouse
14 | boundaries: Boundaries
15 | sound: Sounds
16 | delay: MinMax
17 | brightness: MinMax
18 | decay: MinMax
19 | flickering: number
20 | intensity: number
21 | traceLength: number
22 | traceSpeed: number
23 | lineWidth: LineWidth
24 | lineStyle: LineStyle
25 | autoresize: boolean
26 | }
27 |
28 | export type LineStyle = 'round' | 'square'
29 |
30 | export interface Mouse {
31 | click: boolean
32 | move: boolean
33 | max: number
34 | }
35 |
36 | export interface Boundaries {
37 | x: number
38 | y: number
39 | width: number
40 | height: number
41 | debug: boolean
42 | }
43 |
44 | export interface Sounds {
45 | enabled: boolean
46 | files: string[]
47 | volume: MinMax
48 | }
49 |
50 | export interface LineWidth {
51 | explosion: MinMax
52 | trace: MinMax
53 | }
54 |
55 | export interface MinMax {
56 | min: number
57 | max: number
58 | }
59 |
60 | export interface Sizes {
61 | width: number
62 | height: number
63 | }
64 |
65 | export interface Trace {
66 | x: number
67 | y: number
68 | dx: number
69 | dy: number
70 | ctx: CanvasRenderingContext2D
71 | hue: number
72 | speed: number
73 | acceleration: number
74 | traceLength: number
75 | }
76 |
77 | export interface Explosion {
78 | x: number
79 | y: number
80 | ctx: CanvasRenderingContext2D
81 | hue: number
82 | friction: number
83 | gravity: number
84 | explosionLength: number
85 | flickering: boolean
86 | lineWidth: number
87 | brightness: MinMax
88 | decay: MinMax
89 | }
90 | }
91 |
92 | export type FireworksOptions = RecursivePartial
93 |
94 | export interface FireworksHandlers
95 | extends Pick<
96 | Fireworks,
97 | | 'isRunning'
98 | | 'start'
99 | | 'launch'
100 | | 'pause'
101 | | 'clear'
102 | | 'updateOptions'
103 | | 'updateBoundaries'
104 | | 'updateSize'
105 | | 'currentOptions'
106 | > {
107 | waitStop(): Promise
108 | stop(): void
109 | }
110 |
111 | export type RecursivePartial = {
112 | [P in keyof T]?: T[P] extends (infer U)[]
113 | ? RecursivePartial[]
114 | : T[P] extends object
115 | ? RecursivePartial
116 | : T[P]
117 | }
118 |
--------------------------------------------------------------------------------
/packages/fireworks-js/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@crashmax/tsconfig",
3 | "compilerOptions": {
4 | "outDir": "dist",
5 | "types": [
6 | "vite/client"
7 | ]
8 | },
9 | "include": [
10 | "src"
11 | ]
12 | }
13 |
--------------------------------------------------------------------------------
/packages/fireworks-js/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path'
2 | import { defineConfig } from 'vite'
3 | import banner from 'vite-plugin-banner'
4 | import dts from 'vite-plugin-dts'
5 | import { author, homepage, license, name, version } from './package.json'
6 |
7 | export default defineConfig({
8 | plugins: [
9 | dts({ insertTypesEntry: true }),
10 | banner(
11 | `/**\n * name: ${name}` +
12 | `\n * version: ${version}` +
13 | `\n * author: ${author.name} (${author.url})` +
14 | `\n * homepage: ${homepage}` +
15 | `\n * license ${license}\n */`
16 | )
17 | ],
18 | define: {
19 | __VERSION__: JSON.stringify(version)
20 | },
21 | build: {
22 | target: 'esnext',
23 | lib: {
24 | entry: resolve(__dirname, 'src/index.ts'),
25 | name: 'Fireworks',
26 | formats: [
27 | 'es',
28 | 'cjs',
29 | 'umd'
30 | ],
31 | fileName: (format) => `index.${format}.js`
32 | },
33 | rollupOptions: {
34 | output: {
35 | exports: 'named'
36 | }
37 | }
38 | }
39 | })
40 |
--------------------------------------------------------------------------------
/packages/preact/README.md:
--------------------------------------------------------------------------------
1 | # @fireworks-js/preact
2 |
3 | > https://github.com/crashmax-dev/fireworks-js
4 |
--------------------------------------------------------------------------------
/packages/preact/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@fireworks-js/preact",
3 | "version": "2.10.7",
4 | "type": "module",
5 | "description": "A simple fireworks library!",
6 | "homepage": "https://fireworks.js.org",
7 | "types": "./dist/index.d.ts",
8 | "main": "./dist/index.cjs.js",
9 | "jsdelivr": "./dist/index.umd.js",
10 | "unpkg": "./dist/index.umd.js",
11 | "module": "./dist/index.es.js",
12 | "exports": {
13 | "require": "./dist/index.cjs.js",
14 | "import": "./dist/index.es.js",
15 | "types": "./dist/index.d.ts"
16 | },
17 | "files": [
18 | "dist"
19 | ],
20 | "repository": {
21 | "type": "git",
22 | "url": "git+https://github.com/crashmax-dev/fireworks-js.git"
23 | },
24 | "keywords": [
25 | "preact",
26 | "canvas",
27 | "fireworks",
28 | "animation"
29 | ],
30 | "author": {
31 | "name": "Vitalij Ryndin",
32 | "email": "sys@crashmax.ru",
33 | "url": "https://crashmax.ru"
34 | },
35 | "license": "MIT",
36 | "bugs": {
37 | "url": "https://github.com/crashmax-dev/fireworks-js/issues"
38 | },
39 | "scripts": {
40 | "dev": "vite build --watch",
41 | "build": "vite build && tsc",
42 | "prepublishOnly": "pnpm build"
43 | },
44 | "dependencies": {
45 | "fireworks-js": "workspace:2.10.7"
46 | },
47 | "devDependencies": {
48 | "@preact/preset-vite": "2.4.0",
49 | "preact": "10.11.2"
50 | },
51 | "peerDependencies": {
52 | "preact": ">=8.0.0"
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/packages/preact/src/index.tsx:
--------------------------------------------------------------------------------
1 | import { Fireworks as FireworksJs } from 'fireworks-js'
2 | import React from 'preact/compat'
3 | import { useEffect, useImperativeHandle, useRef } from 'preact/hooks'
4 | import type { FireworksHandlers, FireworksOptions } from 'fireworks-js'
5 | import type { ComponentChildren } from 'preact'
6 |
7 | interface FireworksProps extends React.HTMLAttributes {
8 | children?: ComponentChildren
9 | options?: FireworksOptions
10 | autostart?: boolean
11 | }
12 |
13 | const Fireworks = React.forwardRef(
14 | ({ children, options, autostart = true, ...rest }, ref) => {
15 | const container = useRef(null)
16 | const fireworks = useRef(null)
17 |
18 | useImperativeHandle(ref, () => ({
19 | get isRunning() {
20 | return fireworks.current!.isRunning
21 | },
22 | get currentOptions() {
23 | return fireworks.current!.currentOptions
24 | },
25 | start() {
26 | fireworks.current!.start()
27 | },
28 | launch(count) {
29 | fireworks.current!.launch(count)
30 | },
31 | stop() {
32 | fireworks.current!.stop()
33 | },
34 | async waitStop() {
35 | await fireworks.current!.waitStop()
36 | },
37 | pause() {
38 | fireworks.current!.pause()
39 | },
40 | clear() {
41 | fireworks.current!.clear()
42 | },
43 | updateOptions(options) {
44 | fireworks.current!.updateOptions(options)
45 | },
46 | updateSize(size) {
47 | fireworks.current!.updateSize(size)
48 | },
49 | updateBoundaries(boundaries) {
50 | fireworks.current!.updateBoundaries(boundaries)
51 | }
52 | }))
53 |
54 | useEffect(() => {
55 | fireworks.current = new FireworksJs(container.current!, options)
56 | if (autostart) {
57 | fireworks.current.start()
58 | }
59 |
60 | return () => {
61 | fireworks.current!.stop()
62 | }
63 | }, [])
64 |
65 | return (
66 |
70 | {children}
71 |
72 | )
73 | }
74 | )
75 |
76 | export { Fireworks }
77 | export default Fireworks
78 | export type { FireworksProps, FireworksHandlers, FireworksOptions }
79 |
--------------------------------------------------------------------------------
/packages/preact/src/preact.d.ts:
--------------------------------------------------------------------------------
1 | import JSX = preact.JSX
2 |
--------------------------------------------------------------------------------
/packages/preact/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@crashmax/tsconfig",
3 | "compilerOptions": {
4 | "emitDeclarationOnly": true,
5 | "jsx": "preserve",
6 | "jsxFactory": "h",
7 | "jsxFragmentFactory": "Fragment",
8 | "outDir": "dist",
9 | "types": [
10 | "vite/client"
11 | ]
12 | },
13 | "include": [
14 | "src"
15 | ]
16 | }
17 |
--------------------------------------------------------------------------------
/packages/preact/vite.config.ts:
--------------------------------------------------------------------------------
1 | import preact from '@preact/preset-vite'
2 | import { resolve } from 'path'
3 | import { defineConfig } from 'vite'
4 | import banner from 'vite-plugin-banner'
5 | import dts from 'vite-plugin-dts'
6 | import { author, homepage, license, name, version } from './package.json'
7 |
8 | export default defineConfig({
9 | plugins: [
10 | preact(),
11 | dts({ insertTypesEntry: true }),
12 | banner(
13 | `/**\n * name: ${name}` +
14 | `\n * version: ${version}` +
15 | `\n * author: ${author.name} (${author.url})` +
16 | `\n * homepage: ${homepage}` +
17 | `\n * license ${license}\n */`
18 | )],
19 | build: {
20 | target: 'esnext',
21 | lib: {
22 | entry: resolve(__dirname, 'src/index.tsx'),
23 | name: 'Fireworks',
24 | formats: [
25 | 'es',
26 | 'cjs',
27 | 'umd'
28 | ],
29 | fileName: (format) => `index.${format}.js`
30 | },
31 | rollupOptions: {
32 | external: [
33 | 'preact/compat',
34 | 'preact/hooks',
35 | 'fireworks-js'
36 | ],
37 | output: {
38 | exports: 'named',
39 | globals: {
40 | 'preact/compat': 'PreactCompat',
41 | 'preact/hooks': 'PreactHooks',
42 | 'fireworks-js': 'Fireworks'
43 | }
44 | }
45 | }
46 | }
47 | })
48 |
--------------------------------------------------------------------------------
/packages/react/README.md:
--------------------------------------------------------------------------------
1 | # @fireworks-js/react
2 |
3 | > https://github.com/crashmax-dev/fireworks-js
4 |
--------------------------------------------------------------------------------
/packages/react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@fireworks-js/react",
3 | "version": "2.10.7",
4 | "type": "module",
5 | "description": "A simple fireworks library!",
6 | "homepage": "https://fireworks.js.org",
7 | "types": "./dist/index.d.ts",
8 | "main": "./dist/index.cjs.js",
9 | "jsdelivr": "./dist/index.umd.js",
10 | "unpkg": "./dist/index.umd.js",
11 | "module": "./dist/index.es.js",
12 | "exports": {
13 | "require": "./dist/index.cjs.js",
14 | "import": "./dist/index.es.js",
15 | "types": "./dist/index.d.ts"
16 | },
17 | "files": [
18 | "dist"
19 | ],
20 | "repository": {
21 | "type": "git",
22 | "url": "git+https://github.com/crashmax-dev/fireworks-js.git"
23 | },
24 | "keywords": [
25 | "react",
26 | "canvas",
27 | "fireworks",
28 | "animation"
29 | ],
30 | "author": {
31 | "name": "Vitalij Ryndin",
32 | "email": "sys@crashmax.ru",
33 | "url": "https://crashmax.ru"
34 | },
35 | "license": "MIT",
36 | "bugs": {
37 | "url": "https://github.com/crashmax-dev/fireworks-js/issues"
38 | },
39 | "scripts": {
40 | "dev": "vite build --watch",
41 | "build": "vite build",
42 | "prepublishOnly": "pnpm build"
43 | },
44 | "dependencies": {
45 | "fireworks-js": "workspace:2.10.7"
46 | },
47 | "devDependencies": {
48 | "@types/react": "18.0.24",
49 | "@types/react-dom": "18.0.8",
50 | "@vitejs/plugin-react": "2.2.0",
51 | "react": "18.2.0",
52 | "react-dom": "18.2.0"
53 | },
54 | "peerDependencies": {
55 | "@types/react": ">=16.8.0",
56 | "react": ">=16.8.0"
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/packages/react/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useImperativeHandle, useRef } from 'react'
2 | import { Fireworks as FireworksJs } from 'fireworks-js'
3 | import type { FireworksHandlers, FireworksOptions } from 'fireworks-js'
4 |
5 | interface FireworksProps extends React.HTMLAttributes {
6 | children?: React.ReactNode
7 | options?: FireworksOptions
8 | autostart?: boolean
9 | }
10 |
11 | const Fireworks = React.forwardRef(
12 | ({ children, options, autostart = true, ...rest }, ref) => {
13 | const container = useRef(null)
14 | const fireworks = useRef(null)
15 |
16 | useImperativeHandle(ref, () => ({
17 | get isRunning() {
18 | return fireworks.current!.isRunning
19 | },
20 | get currentOptions() {
21 | return fireworks.current!.currentOptions
22 | },
23 | start() {
24 | fireworks.current!.start()
25 | },
26 | launch(count) {
27 | fireworks.current!.launch(count)
28 | },
29 | stop() {
30 | fireworks.current!.stop()
31 | },
32 | async waitStop() {
33 | await fireworks.current!.waitStop()
34 | },
35 | pause() {
36 | fireworks.current!.pause()
37 | },
38 | clear() {
39 | fireworks.current!.clear()
40 | },
41 | updateOptions(options) {
42 | fireworks.current!.updateOptions(options)
43 | },
44 | updateSize(size) {
45 | fireworks.current!.updateSize(size)
46 | },
47 | updateBoundaries(boundaries) {
48 | fireworks.current!.updateBoundaries(boundaries)
49 | }
50 | }))
51 |
52 | useEffect(() => {
53 | if (!fireworks.current) {
54 | fireworks.current = new FireworksJs(container.current!, options)
55 | }
56 |
57 | if (autostart) {
58 | fireworks.current.start()
59 | }
60 |
61 | return () => {
62 | fireworks.current!.stop()
63 | }
64 | }, [])
65 |
66 | return (
67 |
71 | {children}
72 |
73 | )
74 | }
75 | )
76 |
77 | export { Fireworks }
78 | export default Fireworks
79 | export type { FireworksProps, FireworksHandlers, FireworksOptions }
80 |
--------------------------------------------------------------------------------
/packages/react/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@crashmax/tsconfig",
3 | "compilerOptions": {
4 | "types": [
5 | "vite/client"
6 | ]
7 | },
8 | "include": [
9 | "src"
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/packages/react/vite.config.ts:
--------------------------------------------------------------------------------
1 | import react from '@vitejs/plugin-react'
2 | import { resolve } from 'path'
3 | import { defineConfig } from 'vite'
4 | import banner from 'vite-plugin-banner'
5 | import dts from 'vite-plugin-dts'
6 | import { author, homepage, license, name, version } from './package.json'
7 |
8 | export default defineConfig({
9 | plugins: [
10 | react({ jsxRuntime: 'classic' }),
11 | dts({ insertTypesEntry: true }),
12 | banner(
13 | `/**\n * name: ${name}` +
14 | `\n * version: ${version}` +
15 | `\n * author: ${author.name} (${author.url})` +
16 | `\n * homepage: ${homepage}` +
17 | `\n * license ${license}\n */`
18 | )],
19 | esbuild: {
20 | banner: '"use client";'
21 | },
22 | build: {
23 | target: 'esnext',
24 | lib: {
25 | entry: resolve(__dirname, 'src/index.tsx'),
26 | name: 'Fireworks',
27 | formats: [
28 | 'es',
29 | 'cjs',
30 | 'umd'
31 | ],
32 | fileName: (format) => `index.${format}.js`
33 | },
34 | rollupOptions: {
35 | external: ['react', 'fireworks-js'],
36 | output: {
37 | exports: 'named',
38 | globals: {
39 | react: 'React',
40 | 'fireworks-js': 'Fireworks'
41 | }
42 | }
43 | }
44 | }
45 | })
46 |
--------------------------------------------------------------------------------
/packages/solid/README.md:
--------------------------------------------------------------------------------
1 | # @fireworks-js/solid
2 |
3 | > https://github.com/crashmax-dev/fireworks-js
4 |
--------------------------------------------------------------------------------
/packages/solid/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@fireworks-js/solid",
3 | "version": "2.10.7",
4 | "type": "module",
5 | "description": "A simple fireworks library!",
6 | "homepage": "https://fireworks.js.org",
7 | "types": "./dist/index.d.ts",
8 | "main": "./dist/index.cjs.js",
9 | "jsdelivr": "./dist/index.umd.js",
10 | "unpkg": "./dist/index.umd.js",
11 | "module": "./dist/index.es.js",
12 | "exports": {
13 | "require": "./dist/index.cjs.js",
14 | "import": "./dist/index.es.js",
15 | "types": "./dist/index.d.ts"
16 | },
17 | "files": [
18 | "dist"
19 | ],
20 | "repository": {
21 | "type": "git",
22 | "url": "git+https://github.com/crashmax-dev/fireworks-js.git"
23 | },
24 | "keywords": [
25 | "solid-js",
26 | "canvas",
27 | "fireworks",
28 | "animation"
29 | ],
30 | "author": {
31 | "name": "Vitalij Ryndin",
32 | "email": "sys@crashmax.ru",
33 | "url": "https://crashmax.ru"
34 | },
35 | "license": "MIT",
36 | "bugs": {
37 | "url": "https://github.com/crashmax-dev/fireworks-js/issues"
38 | },
39 | "scripts": {
40 | "dev": "vite build --watch",
41 | "build": "vite build",
42 | "prepublishOnly": "pnpm build"
43 | },
44 | "dependencies": {
45 | "fireworks-js": "workspace:2.10.7",
46 | "solid-js": "^1.6.1"
47 | },
48 | "devDependencies": {
49 | "solid-js": "1.4.7",
50 | "vite-plugin-solid": "2.3.10"
51 | },
52 | "peerDependencies": {
53 | "solid-js": ">=1.0.0"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/packages/solid/src/index.tsx:
--------------------------------------------------------------------------------
1 | import { Fireworks as FireworksJS } from 'fireworks-js'
2 | import { mergeProps, onCleanup, onMount } from 'solid-js'
3 | import type { FireworksHandlers, FireworksOptions } from 'fireworks-js'
4 | import type { JSX, ParentComponent } from 'solid-js'
5 |
6 | interface FireworksProps
7 | extends Omit, 'ref'> {
8 | options?: FireworksOptions
9 | autostart?: boolean
10 | ref?: (handlers: FireworksHandlers) => void
11 | }
12 |
13 | const Fireworks: ParentComponent = (props) => {
14 | const { autostart, options, children, ref, ...rest } = mergeProps(
15 | { autostart: true },
16 | props
17 | )
18 | let container: HTMLDivElement | undefined
19 | let fireworks: FireworksJS | undefined
20 |
21 | onMount(() => {
22 | fireworks = new FireworksJS(container!, options)
23 | if (autostart) {
24 | fireworks.start()
25 | }
26 |
27 | if (ref) {
28 | ref(fireworks)
29 | }
30 |
31 | onCleanup(() => {
32 | fireworks!.stop()
33 | })
34 | })
35 |
36 | return (
37 |
41 | {children}
42 |
43 | )
44 | }
45 |
46 | export { Fireworks }
47 | export default Fireworks
48 | export type { FireworksOptions, FireworksHandlers }
49 |
--------------------------------------------------------------------------------
/packages/solid/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@crashmax/tsconfig",
3 | "compilerOptions": {
4 | "jsx": "preserve",
5 | "jsxImportSource": "solid-js",
6 | "outDir": "dist",
7 | "types": [
8 | "vite/client"
9 | ]
10 | },
11 | "include": [
12 | "src"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/packages/solid/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path'
2 | import { defineConfig } from 'vite'
3 | import banner from 'vite-plugin-banner'
4 | import dts from 'vite-plugin-dts'
5 | import solid from 'vite-plugin-solid'
6 | import { author, homepage, license, name, version } from './package.json'
7 |
8 | export default defineConfig({
9 | plugins: [
10 | solid(),
11 | dts({ insertTypesEntry: true }),
12 | banner(
13 | `/**\n * name: ${name}` +
14 | `\n * version: ${version}` +
15 | `\n * author: ${author.name} (${author.url})` +
16 | `\n * homepage: ${homepage}` +
17 | `\n * license ${license}\n */`
18 | )],
19 | build: {
20 | target: 'esnext',
21 | polyfillModulePreload: false,
22 | lib: {
23 | entry: resolve(__dirname, 'src/index.tsx'),
24 | name: 'Fireworks',
25 | formats: [
26 | 'es',
27 | 'cjs',
28 | 'umd'
29 | ],
30 | fileName: (format) => `index.${format}.js`
31 | },
32 | rollupOptions: {
33 | external: ['solid-js', 'fireworks-js'],
34 | output: {
35 | exports: 'named',
36 | globals: {
37 | 'solid-js': 'Solid',
38 | 'fireworks-js': 'Fireworks'
39 | }
40 | }
41 | }
42 | }
43 | })
44 |
--------------------------------------------------------------------------------
/packages/svelte/README.md:
--------------------------------------------------------------------------------
1 | # @fireworks-js/svelte
2 |
3 | > https://github.com/crashmax-dev/fireworks-js
4 |
5 | ## Installation
6 |
7 | ```sh
8 | npm install @fireworks-js/svelte
9 | ```
10 |
11 | ## Usage
12 |
13 | #### [`fireworks-js`](https://github.com/crashmax-dev/fireworks-js/tree/master/examples/with-svelte)
14 |
15 | ```svelte
16 |
34 |
35 | ```
36 |
--------------------------------------------------------------------------------
/packages/svelte/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@fireworks-js/svelte",
3 | "version": "2.10.7",
4 | "type": "module",
5 | "description": "A simple fireworks library!",
6 | "homepage": "https://fireworks.js.org",
7 | "types": "./dist/index.d.ts",
8 | "svelte": "./dist/index.js",
9 | "files": [
10 | "dist"
11 | ],
12 | "exports": {
13 | "./package.json": "./package.json",
14 | "./fireworks.svelte": "./dist/fireworks.svelte",
15 | ".": "./dist/index.js"
16 | },
17 | "repository": {
18 | "type": "git",
19 | "url": "git+https://github.com/crashmax-dev/fireworks-js.git"
20 | },
21 | "keywords": [
22 | "svelte",
23 | "canvas",
24 | "fireworks",
25 | "animation"
26 | ],
27 | "author": {
28 | "name": "Vitalij Ryndin",
29 | "email": "sys@crashmax.ru",
30 | "url": "https://crashmax.ru"
31 | },
32 | "license": "MIT",
33 | "bugs": {
34 | "url": "https://github.com/crashmax-dev/fireworks-js/issues"
35 | },
36 | "scripts": {
37 | "dev": "vite dev --port 8081 --open",
38 | "build": "svelte-kit sync && svelte-package && del-cli dist/package.json dist/README.md",
39 | "prepublishOnly": "pnpm build"
40 | },
41 | "dependencies": {
42 | "fireworks-js": "workspace:2.10.7"
43 | },
44 | "devDependencies": {
45 | "@sveltejs/adapter-auto": "1.0.0-next.86",
46 | "@sveltejs/kit": "1.0.0-next.531",
47 | "@sveltejs/package": "1.0.0-next.5",
48 | "svelte": "^3.52.0",
49 | "svelte-check": "^2.9.2",
50 | "svelte-preprocess": "^4.10.6",
51 | "tslib": "^2.4.1",
52 | "typescript": "^4.7.4",
53 | "vite": "^3.2.2"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/packages/svelte/src/app.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | // See https://kit.svelte.dev/docs/types#app
4 | // for information about these interfaces
5 | // and what to do when importing types
6 | declare namespace App {
7 | // interface Locals {}
8 | // interface PageData {}
9 | // interface Error {}
10 | // interface Platform {}
11 | }
12 |
--------------------------------------------------------------------------------
/packages/svelte/src/app.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | @fireworks-js/svelte
8 | %sveltekit.head%
9 |
10 |
11 | %sveltekit.body%
12 |
13 |
14 |
--------------------------------------------------------------------------------
/packages/svelte/src/lib/fireworks.svelte:
--------------------------------------------------------------------------------
1 |
32 |
33 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/packages/svelte/src/lib/index.ts:
--------------------------------------------------------------------------------
1 | import { default as Fireworks } from './fireworks.svelte'
2 | import type { FireworksOptions } from 'fireworks-js'
3 |
4 | export { Fireworks }
5 | export default Fireworks
6 | export type { FireworksOptions }
7 |
--------------------------------------------------------------------------------
/packages/svelte/src/routes/+page.svelte:
--------------------------------------------------------------------------------
1 |
34 |
35 |
36 |
37 | toggleFireworks()}>
38 | {enabled ? 'Stop' : 'Start'}
39 |
40 | launchFireworks()}>
41 | Launch
42 |
43 |
50 |
51 |
52 |
53 |
54 |
71 |
--------------------------------------------------------------------------------
/packages/svelte/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodeWithUsman0/fireworks-js/8c15ac042fdafee69fd724e59bb2bb01a32230df/packages/svelte/static/favicon.png
--------------------------------------------------------------------------------
/packages/svelte/svelte.config.js:
--------------------------------------------------------------------------------
1 | import adapter from '@sveltejs/adapter-auto'
2 | import preprocess from 'svelte-preprocess'
3 |
4 | /** @type {import('@sveltejs/kit').Config} */
5 | const config = {
6 | // Consult https://github.com/sveltejs/svelte-preprocess
7 | // for more information about preprocessors
8 | preprocess: preprocess(),
9 | kit: {
10 | adapter: adapter()
11 | },
12 | package: {
13 | dir: 'dist'
14 | }
15 | }
16 |
17 | export default config
18 |
--------------------------------------------------------------------------------
/packages/svelte/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./.svelte-kit/tsconfig.json",
3 | "compilerOptions": {
4 | "allowJs": true,
5 | "checkJs": true,
6 | "esModuleInterop": true,
7 | "forceConsistentCasingInFileNames": true,
8 | "resolveJsonModule": true,
9 | "skipLibCheck": true,
10 | "sourceMap": true,
11 | "strict": true
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/packages/svelte/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { sveltekit } from '@sveltejs/kit/vite'
2 | import type { UserConfig } from 'vite'
3 |
4 | const config: UserConfig = {
5 | plugins: [sveltekit()]
6 | }
7 |
8 | export default config
9 |
--------------------------------------------------------------------------------
/packages/vue/README.md:
--------------------------------------------------------------------------------
1 | # @fireworks-js/vue
2 |
3 | > https://github.com/crashmax-dev/fireworks-js
4 |
--------------------------------------------------------------------------------
/packages/vue/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@fireworks-js/vue",
3 | "version": "2.10.7",
4 | "type": "module",
5 | "description": "A simple fireworks library!",
6 | "homepage": "https://fireworks.js.org",
7 | "types": "./dist/index.d.ts",
8 | "main": "./dist/index.umd.js",
9 | "module": "./dist/index.es.js",
10 | "jsdelivr": "./dist/index.umd.js",
11 | "unpkg": "./dist/index.umd.js",
12 | "files": [
13 | "dist"
14 | ],
15 | "repository": {
16 | "type": "git",
17 | "url": "git+https://github.com/crashmax-dev/fireworks-js.git"
18 | },
19 | "keywords": [
20 | "vue",
21 | "canvas",
22 | "fireworks",
23 | "animation"
24 | ],
25 | "author": {
26 | "name": "Vitalij Ryndin",
27 | "email": "sys@crashmax.ru",
28 | "url": "https://crashmax.ru"
29 | },
30 | "license": "MIT",
31 | "bugs": {
32 | "url": "https://github.com/crashmax-dev/fireworks-js/issues"
33 | },
34 | "scripts": {
35 | "dev": "vite build --watch",
36 | "build": "del-cli dist && vite build && pnpm types",
37 | "types": "vue-tsc --declaration --emitDeclarationOnly",
38 | "prepublishOnly": "pnpm build"
39 | },
40 | "dependencies": {
41 | "fireworks-js": "workspace:2.10.7"
42 | },
43 | "devDependencies": {
44 | "@vitejs/plugin-vue": "3.2.0",
45 | "vue": "3.2.41",
46 | "vue-tsc": "1.0.9"
47 | },
48 | "peerDependencies": {
49 | "vue": ">=3.0.0"
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/packages/vue/src/fireworks.vue:
--------------------------------------------------------------------------------
1 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/packages/vue/src/index.ts:
--------------------------------------------------------------------------------
1 | import Fireworks from './fireworks.vue'
2 |
3 | export { Fireworks }
4 | export default Fireworks
5 | export type { FireworksOptions } from 'fireworks-js'
6 |
--------------------------------------------------------------------------------
/packages/vue/src/shim.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
3 | declare module '*.vue' {
4 | import type { DefineComponent } from 'vue'
5 | const component: DefineComponent<{}, {}, any>
6 | export default component
7 | }
8 |
--------------------------------------------------------------------------------
/packages/vue/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@crashmax/tsconfig",
3 | "compilerOptions": {
4 | "jsx": "preserve",
5 | "outDir": "dist",
6 | "noEmitOnError": false
7 | },
8 | "include": [
9 | "src"
10 | ]
11 | }
12 |
--------------------------------------------------------------------------------
/packages/vue/vite.config.ts:
--------------------------------------------------------------------------------
1 | import vue from '@vitejs/plugin-vue'
2 | import { resolve } from 'path'
3 | import { defineConfig } from 'vite'
4 | import banner from 'vite-plugin-banner'
5 | import { author, homepage, license, name, version } from './package.json'
6 |
7 | export default defineConfig({
8 | plugins: [
9 | vue(),
10 | banner(
11 | `/**\n * name: ${name}` +
12 | `\n * version: ${version}` +
13 | `\n * author: ${author.name} (${author.url})` +
14 | `\n * homepage: ${homepage}` +
15 | `\n * license ${license}\n */`
16 | )
17 | ],
18 | build: {
19 | target: 'esnext',
20 | lib: {
21 | entry: resolve(__dirname, 'src/index.ts'),
22 | name: 'Fireworks',
23 | formats: [
24 | 'es',
25 | 'cjs',
26 | 'umd'
27 | ],
28 | fileName: (format) => `index.${format}.js`
29 | },
30 | rollupOptions: {
31 | external: ['vue', 'fireworks-js'],
32 | output: {
33 | exports: 'named',
34 | globals: {
35 | vue: 'Vue',
36 | 'fireworks-js': 'Fireworks'
37 | }
38 | }
39 | }
40 | }
41 | })
42 |
--------------------------------------------------------------------------------
/packages/web/README.md:
--------------------------------------------------------------------------------
1 | # @fireworks-js/web
2 |
3 | > https://github.com/crashmax-dev/fireworks-js
4 |
--------------------------------------------------------------------------------
/packages/web/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@fireworks-js/web",
3 | "version": "2.10.7",
4 | "type": "module",
5 | "description": "A simple fireworks library!",
6 | "homepage": "https://fireworks.js.org",
7 | "types": "./dist/index.d.ts",
8 | "main": "./dist/index.cjs.js",
9 | "jsdelivr": "./dist/index.umd.js",
10 | "unpkg": "./dist/index.umd.js",
11 | "module": "./dist/index.es.js",
12 | "exports": {
13 | "require": "./dist/index.cjs.js",
14 | "import": "./dist/index.es.js",
15 | "types": "./dist/index.d.ts"
16 | },
17 | "files": [
18 | "dist"
19 | ],
20 | "repository": {
21 | "type": "git",
22 | "url": "git+https://github.com/crashmax-dev/fireworks-js.git"
23 | },
24 | "keywords": [
25 | "web-components",
26 | "fireworks",
27 | "animation"
28 | ],
29 | "author": {
30 | "name": "Vitalij Ryndin",
31 | "email": "sys@crashmax.ru",
32 | "url": "https://crashmax.ru"
33 | },
34 | "license": "MIT",
35 | "bugs": {
36 | "url": "https://github.com/crashmax-dev/fireworks-js/issues"
37 | },
38 | "scripts": {
39 | "dev": "vite build --watch",
40 | "build": "del-cli dist && vite build && tsc",
41 | "prepublishOnly": "pnpm build"
42 | },
43 | "dependencies": {
44 | "fireworks-js": "workspace:2.10.7"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/packages/web/src/index.ts:
--------------------------------------------------------------------------------
1 | import { Fireworks as FireworksJs } from 'fireworks-js'
2 | import type { FireworksOptions } from 'fireworks-js'
3 |
4 | class Fireworks extends HTMLElement {
5 | fireworks: FireworksJs
6 | private options: FireworksOptions = {}
7 |
8 | static get observedAttributes() {
9 | return ['options', 'style']
10 | }
11 |
12 | constructor() {
13 | super()
14 |
15 | const shadowRoot = this.attachShadow({ mode: 'open' })
16 | const div = document.createElement('div')
17 | const style = document.createElement('style')
18 | shadowRoot.append(style, div)
19 |
20 | this.attributeChangedCallback()
21 | }
22 |
23 | connectedCallback(): void {
24 | if (!this.isConnected) return
25 |
26 | const container = this.shadowRoot!.querySelector('div')
27 | if (!this.fireworks && container) {
28 | this.fireworks = new FireworksJs(container, this.options)
29 | this.fireworks.start()
30 | }
31 | }
32 |
33 | disconnectedCallback(): void {
34 | this.fireworks.stop()
35 | }
36 |
37 | attributeChangedCallback() {
38 | const options = this.getAttribute('options')
39 | if (options) {
40 | try {
41 | this.options = JSON.parse(options)
42 | this.fireworks?.updateOptions(this.options)
43 | } catch (err) {
44 | console.error('Attribute `options` failed parsed:', err)
45 | }
46 | }
47 |
48 | const style = this.getAttribute('style')
49 | if (style) {
50 | this.shadowRoot!.querySelector('style')!.textContent = `div { ${style} }`
51 | }
52 | }
53 | }
54 |
55 | declare global {
56 | interface HTMLElementTagNameMap {
57 | 'fireworks-js': Fireworks
58 | }
59 | }
60 |
61 | customElements.define('fireworks-js', Fireworks)
62 |
63 | export { Fireworks }
64 | export default Fireworks
65 | export type { FireworksOptions }
66 |
--------------------------------------------------------------------------------
/packages/web/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@crashmax/tsconfig",
3 | "compilerOptions": {
4 | "emitDeclarationOnly": true,
5 | "outDir": "dist",
6 | "types": [
7 | "vite/client"
8 | ]
9 | },
10 | "include": [
11 | "src"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/packages/web/vite.config.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path'
2 | import { defineConfig } from 'vite'
3 | import banner from 'vite-plugin-banner'
4 | import dts from 'vite-plugin-dts'
5 | import { author, homepage, license, name, version } from './package.json'
6 |
7 | export default defineConfig({
8 | plugins: [
9 | dts({ insertTypesEntry: true }),
10 | banner(
11 | `/**\n * name: ${name}` +
12 | `\n * version: ${version}` +
13 | `\n * author: ${author.name} (${author.url})` +
14 | `\n * homepage: ${homepage}` +
15 | `\n * license ${license}\n */`
16 | )
17 | ],
18 | build: {
19 | target: 'esnext',
20 | lib: {
21 | entry: resolve(__dirname, 'src/index.ts'),
22 | name: 'fireworks-js',
23 | formats: [
24 | 'es',
25 | 'cjs',
26 | 'umd'
27 | ],
28 | fileName: (format) => `index.${format}.js`
29 | },
30 | rollupOptions: {
31 | output: {
32 | exports: 'named'
33 | }
34 | }
35 | }
36 | })
37 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - 'website'
3 | - 'examples/*'
4 | - 'packages/*'
5 |
--------------------------------------------------------------------------------
/turbo.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://turborepo.org/schema.json",
3 | "pipeline": {
4 | "build": {
5 | "dependsOn": [
6 | "^build"
7 | ],
8 | "outputs": [
9 | "dist/**",
10 | ".svelte-kit/**",
11 | ".angular/**"
12 | ]
13 | },
14 | "dev": {
15 | "dependsOn": [
16 | "^build"
17 | ],
18 | "cache": false
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/website/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | fireworks-js
8 |
10 |
11 |
12 |
13 |
14 |
16 |
24 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/website/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "website",
3 | "private": true,
4 | "version": "0.0.0",
5 | "homepage": "https://fireworks.js.org",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build"
9 | },
10 | "dependencies": {
11 | "@r3-dev/brand": "1.2.0",
12 | "@tweakpane/core": "1.1.4",
13 | "@tweakpane/plugin-essentials": "0.1.7",
14 | "fireworks-js": "workspace:*",
15 | "tweakpane": "3.1.4"
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/website/public/CNAME:
--------------------------------------------------------------------------------
1 | fireworks.js.org
--------------------------------------------------------------------------------
/website/public/images/fireworks_banner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodeWithUsman0/fireworks-js/8c15ac042fdafee69fd724e59bb2bb01a32230df/website/public/images/fireworks_banner.gif
--------------------------------------------------------------------------------
/website/public/images/fireworks_emoji.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodeWithUsman0/fireworks-js/8c15ac042fdafee69fd724e59bb2bb01a32230df/website/public/images/fireworks_emoji.gif
--------------------------------------------------------------------------------
/website/public/images/fireworks_emoji.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodeWithUsman0/fireworks-js/8c15ac042fdafee69fd724e59bb2bb01a32230df/website/public/images/fireworks_emoji.png
--------------------------------------------------------------------------------
/website/public/index.css:
--------------------------------------------------------------------------------
1 | body {
2 | font-family: -apple-system, system-ui, BlinkMacSystemFont, 'Segoe UI',
3 | 'Open Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
4 | line-height: 1;
5 | user-select: none;
6 | overscroll-behavior: none;
7 | }
8 |
9 | .container {
10 | position: fixed;
11 | width: 240px;
12 | height: inherit;
13 | background: hsla(0, 0%, 10%, 1);
14 | top: 50%;
15 | left: 50%;
16 | margin: -120px 0 0 -120px;
17 | padding: 20px;
18 | border-radius: 4px;
19 | box-sizing: border-box;
20 | font-size: 20px;
21 | z-index: 1;
22 | opacity: 0.9;
23 | line-height: initial;
24 | }
25 |
26 | .container div {
27 | text-align: center;
28 | font-size: 3rem;
29 | }
30 |
31 | .container h1 {
32 | font-size: 1.8em;
33 | text-align: center;
34 | color: #ffffff;
35 | margin: 0;
36 | }
37 |
38 | .container h2 {
39 | font-weight: 400;
40 | font-size: 16px;
41 | margin-bottom: 10px;
42 | text-align: center;
43 | color: #ffffff;
44 | }
45 |
46 | .container a {
47 | width: 100%;
48 | text-align: center;
49 | line-height: 36px;
50 | background: #ffffff;
51 | margin-top: 10px;
52 | color: #222;
53 | border-radius: 4px;
54 | display: inline-block;
55 | font-size: 16px;
56 | font-weight: 500;
57 | transition-duration: 0.1s;
58 | text-decoration: none;
59 | }
60 |
61 | .container a:hover {
62 | transition: ease-in color;
63 | background: #222;
64 | color: hsla(0, 0%, 70%, 1);
65 | }
66 |
67 | .fireworks-container {
68 | position: fixed;
69 | left: 0;
70 | top: 0;
71 | width: 100%;
72 | height: 100%;
73 | background: #000000;
74 | }
75 |
76 | .fireworks-container > canvas {
77 | cursor: crosshair;
78 | }
79 |
80 | :root {
81 | --tp-base-background-color: hsla(0, 0%, 0%, 0.75);
82 | --tp-base-shadow-color: hsla(0, 0%, 0%, 0.2);
83 | --tp-button-background-color: hsla(0, 0%, 70%, 1);
84 | --tp-button-background-color-active: hsla(0, 0%, 85%, 1);
85 | --tp-button-background-color-focus: hsla(0, 0%, 80%, 1);
86 | --tp-button-background-color-hover: hsla(0, 0%, 75%, 1);
87 | --tp-button-foreground-color: hsla(0, 0%, 0%, 1);
88 | --tp-container-background-color: hsla(0, 0%, 10%, 1);
89 | --tp-container-background-color-active: hsla(0, 0%, 25%, 1);
90 | --tp-container-background-color-focus: hsla(0, 0%, 20%, 1);
91 | --tp-container-background-color-hover: hsla(0, 0%, 15%, 1);
92 | --tp-container-foreground-color: hsla(0, 0%, 50%, 1);
93 | --tp-groove-foreground-color: hsla(0, 0%, 10%, 1);
94 | --tp-input-background-color: hsla(0, 0%, 10%, 1);
95 | --tp-input-background-color-active: hsla(0, 0%, 25%, 1);
96 | --tp-input-background-color-focus: hsla(0, 0%, 20%, 1);
97 | --tp-input-background-color-hover: hsla(0, 0%, 15%, 1);
98 | --tp-input-foreground-color: hsla(0, 0%, 70%, 1);
99 | --tp-label-foreground-color: hsla(0, 0%, 50%, 1);
100 | --tp-monitor-background-color: hsla(0, 0%, 8%, 1);
101 | --tp-monitor-foreground-color: hsla(0, 0%, 48%, 1);
102 | }
103 |
104 | :root .tp-dfwv {
105 | padding-bottom: 8px;
106 | width: 350px !important;
107 | z-index: 1;
108 | }
109 |
--------------------------------------------------------------------------------
/website/public/sounds/explosion0.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodeWithUsman0/fireworks-js/8c15ac042fdafee69fd724e59bb2bb01a32230df/website/public/sounds/explosion0.mp3
--------------------------------------------------------------------------------
/website/public/sounds/explosion1.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodeWithUsman0/fireworks-js/8c15ac042fdafee69fd724e59bb2bb01a32230df/website/public/sounds/explosion1.mp3
--------------------------------------------------------------------------------
/website/public/sounds/explosion2.mp3:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CodeWithUsman0/fireworks-js/8c15ac042fdafee69fd724e59bb2bb01a32230df/website/public/sounds/explosion2.mp3
--------------------------------------------------------------------------------
/website/src/config.ts:
--------------------------------------------------------------------------------
1 | import type { FireworksOptions } from 'fireworks-js'
2 |
3 | export const mainContainer =
4 | document.querySelector('.container')!
5 |
6 | export const fireworksContainer = document.querySelector(
7 | '.fireworks-container'
8 | )!
9 |
10 | export const fireworksOptions: FireworksOptions = {
11 | hue: {
12 | min: 0,
13 | max: 345
14 | },
15 | delay: {
16 | min: 30,
17 | max: 60
18 | },
19 | rocketsPoint: {
20 | min: 50,
21 | max: 50
22 | },
23 | opacity: 0.5, // fillStyle
24 | acceleration: 1.02,
25 | friction: 0.97,
26 | gravity: 1.5,
27 | particles: 60,
28 | traceLength: 3,
29 | traceSpeed: 10,
30 | explosion: 5,
31 | intensity: 30,
32 | flickering: 50,
33 | lineStyle: 'round',
34 | lineWidth: {
35 | explosion: {
36 | min: 1,
37 | max: 4
38 | },
39 | trace: {
40 | min: 0.1,
41 | max: 1
42 | }
43 | },
44 | brightness: {
45 | min: 50,
46 | max: 80
47 | },
48 | decay: {
49 | min: 0.015,
50 | max: 0.03
51 | },
52 | boundaries: {
53 | x: 50,
54 | y: 50,
55 | width: fireworksContainer.clientWidth,
56 | height: fireworksContainer.clientHeight
57 | },
58 | sound: {
59 | enabled: false,
60 | files: [
61 | location.href + 'sounds/explosion0.mp3',
62 | location.href + 'sounds/explosion1.mp3',
63 | location.href + 'sounds/explosion2.mp3'
64 | ],
65 | volume: {
66 | min: 2,
67 | max: 4
68 | }
69 | },
70 | mouse: {
71 | click: true,
72 | move: false,
73 | max: 1
74 | }
75 | }
76 |
77 | export const backgroundConfig = {
78 | color: '#000000',
79 | image: '',
80 | size: 'cover',
81 | position: '50% 50%',
82 | repeat: 'no-repeat',
83 | container: false,
84 | fps: false
85 | }
86 |
--------------------------------------------------------------------------------
/website/src/index.ts:
--------------------------------------------------------------------------------
1 | import * as EssentialsPlugin from '@tweakpane/plugin-essentials'
2 | import { Fireworks } from 'fireworks-js'
3 | import { Pane } from 'tweakpane'
4 | import {
5 | backgroundConfig,
6 | fireworksContainer,
7 | fireworksOptions,
8 | mainContainer
9 | } from './config.js'
10 | import type { FpsGraphBladeApi } from '@tweakpane/plugin-essentials/dist/types/fps-graph/api/fps-graph'
11 | import '@r3-dev/brand'
12 |
13 | declare global {
14 | interface Window {
15 | fireworks: Fireworks
16 | }
17 | }
18 |
19 | const fireworks = new Fireworks(fireworksContainer, fireworksOptions)
20 | window.fireworks = fireworks
21 | fireworks.start()
22 |
23 | const fireworksGetters = {
24 | get traces(): number {
25 | // @ts-ignore
26 | return fireworks.traces.length
27 | },
28 | get particles(): number {
29 | // @ts-ignore
30 | return fireworks.explosions.length
31 | }
32 | }
33 |
34 | const isPcWidth = window.innerWidth > 1000
35 | const tweakpane = new Pane({
36 | document,
37 | expanded: isPcWidth,
38 | title: document.title
39 | })
40 |
41 | tweakpane.registerPlugin(EssentialsPlugin)
42 |
43 | tweakpane.on('fold', ({ expanded }) => {
44 | if (isPcWidth) return
45 | mainContainer.style.display = expanded ? 'none' : 'block'
46 | })
47 |
48 | /** options */
49 | tweakpane.addInput(fireworksOptions, 'hue', {
50 | min: 0,
51 | max: 360,
52 | step: 1
53 | })
54 |
55 | tweakpane.addInput(fireworksOptions, 'acceleration', {
56 | min: 1,
57 | max: 2
58 | })
59 |
60 | tweakpane.addInput(fireworksOptions, 'brightness', {
61 | min: 1,
62 | max: 100,
63 | step: 1
64 | })
65 |
66 | tweakpane.addInput(fireworksOptions, 'decay', {
67 | min: 0.001,
68 | max: 0.05
69 | })
70 |
71 | tweakpane.addInput(fireworksOptions, 'delay', {
72 | min: 10,
73 | max: 100
74 | })
75 |
76 | tweakpane.addInput(fireworksOptions, 'explosion', {
77 | min: 1,
78 | max: 10,
79 | step: 1
80 | })
81 |
82 | tweakpane.addInput(fireworksOptions, 'flickering', {
83 | min: 0,
84 | max: 100
85 | })
86 |
87 | tweakpane.addInput(fireworksOptions, 'intensity', {
88 | min: 1,
89 | max: 60
90 | })
91 |
92 | tweakpane.addInput(fireworksOptions, 'friction', {
93 | min: 0.5,
94 | max: 3
95 | })
96 |
97 | tweakpane.addInput(fireworksOptions, 'gravity', {
98 | min: 0,
99 | max: 10
100 | })
101 |
102 | tweakpane.addInput(fireworksOptions, 'opacity', {
103 | min: 0,
104 | max: 1,
105 | step: 0.1
106 | })
107 |
108 | tweakpane.addInput(fireworksOptions, 'particles', {
109 | step: 1,
110 | min: 1,
111 | max: 200
112 | })
113 |
114 | tweakpane.addInput(fireworksOptions, 'traceLength', {
115 | min: 1,
116 | max: 10
117 | })
118 |
119 | tweakpane.addInput(fireworksOptions, 'traceSpeed', {
120 | min: 1,
121 | max: 100,
122 | step: 1
123 | })
124 |
125 | tweakpane.addInput(fireworksOptions, 'rocketsPoint', {
126 | min: 0,
127 | max: 100,
128 | step: 1
129 | })
130 |
131 | tweakpane.addInput(fireworksOptions.lineWidth!, 'explosion', {
132 | label: 'lineWidth (explosion)',
133 | min: 0,
134 | max: 10
135 | })
136 |
137 | tweakpane.addInput(fireworksOptions.lineWidth!, 'trace', {
138 | label: 'lineWidth (trace)',
139 | min: 0,
140 | max: 10
141 | })
142 |
143 | tweakpane.addInput(fireworksOptions, 'lineStyle', {
144 | options: {
145 | round: 'round',
146 | square: 'square'
147 | }
148 | })
149 |
150 | /** mouse events */
151 | const mouse = tweakpane.addFolder({
152 | title: 'mouse',
153 | expanded: false
154 | })
155 |
156 | mouse.addInput(fireworksOptions.mouse!, 'click', {
157 | label: 'mouse click'
158 | })
159 |
160 | mouse.addInput(fireworksOptions.mouse!, 'max', {
161 | label: 'maximum rockets',
162 | min: 1,
163 | max: 15,
164 | step: 1
165 | })
166 |
167 | mouse.addInput(fireworksOptions.mouse!, 'move', {
168 | label: 'follow mouse'
169 | })
170 |
171 | /** sounds */
172 | const sound = tweakpane.addFolder({
173 | title: 'sound',
174 | expanded: false
175 | })
176 |
177 | sound.addInput(fireworksOptions.sound!, 'enabled')
178 |
179 | sound.addInput(fireworksOptions.sound!, 'volume', {
180 | min: 0,
181 | max: 100,
182 | step: 1
183 | })
184 |
185 | tweakpane.on('change', () => {
186 | fireworks.updateOptions(fireworksOptions)
187 | })
188 |
189 | /** background */
190 | const background = tweakpane.addFolder({
191 | title: 'background',
192 | expanded: false
193 | })
194 |
195 | background.addInput(backgroundConfig, 'container').on('change', ({ value }) => {
196 | mainContainer.style.display = value ? 'none' : 'block'
197 | })
198 |
199 | background.addInput(backgroundConfig, 'color').on('change', ({ value }) => {
200 | fireworksContainer.style.backgroundColor = value
201 | })
202 |
203 | background.addInput(backgroundConfig, 'image').on('change', ({ value }) => {
204 | fireworksContainer.style.backgroundImage = `url(${value})`
205 | })
206 |
207 | background.addInput(backgroundConfig, 'size').on('change', ({ value }) => {
208 | fireworksContainer.style.backgroundSize = value
209 | })
210 |
211 | background.addInput(backgroundConfig, 'position').on('change', ({ value }) => {
212 | fireworksContainer.style.backgroundPosition = value
213 | })
214 |
215 | background.addInput(backgroundConfig, 'repeat').on('change', ({ value }) => {
216 | fireworksContainer.style.backgroundRepeat = value
217 | })
218 |
219 | /** monitors */
220 | const monitors = tweakpane.addFolder({
221 | title: 'monitors',
222 | expanded: false
223 | })
224 |
225 | const fpsGraph = monitors.addBlade({
226 | view: 'fpsgraph',
227 | label: 'fps'
228 | }) as FpsGraphBladeApi
229 |
230 | monitors.addMonitor(fireworksGetters, 'particles', {
231 | view: 'graph',
232 | label: 'particles',
233 | min: 0,
234 | max: 5000
235 | })
236 |
237 | monitors.addMonitor(fireworksGetters, 'traces', {
238 | view: 'graph',
239 | label: 'traces',
240 | min: 0,
241 | max: 50
242 | })
243 |
244 | const updateGraph = () => {
245 | fpsGraph.begin()
246 | fpsGraph.end()
247 | requestAnimationFrame(updateGraph)
248 | }
249 |
250 | requestAnimationFrame(updateGraph)
251 |
252 | /** fullscreen */
253 | declare global {
254 | interface Element {
255 | webkitRequestFullscreen?(): void
256 | mozRequestFullScreen?(): void
257 | msRequestFullscreen?(): void
258 | }
259 | }
260 |
261 | document.addEventListener('keydown', (event) => {
262 | if (event.code === 'F11') {
263 | event.preventDefault()
264 |
265 | if (fireworksContainer.requestFullscreen) {
266 | fireworksContainer.requestFullscreen()
267 | } else if (fireworksContainer.webkitRequestFullscreen) {
268 | fireworksContainer.webkitRequestFullscreen()
269 | } else if (fireworksContainer.mozRequestFullScreen) {
270 | fireworksContainer.mozRequestFullScreen()
271 | } else if (fireworksContainer.msRequestFullscreen) {
272 | fireworksContainer.msRequestFullscreen()
273 | }
274 | }
275 | })
276 |
--------------------------------------------------------------------------------
/website/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "@crashmax/tsconfig",
3 | "include": [
4 | "src"
5 | ]
6 | }
7 |
--------------------------------------------------------------------------------