canvasengine 2.0.0-beta.1 → 2.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,77 +1,32 @@
1
1
  {
2
2
  "name": "canvasengine",
3
- "description": "A reactive HTML5 Canvas management library built on top of PixiJS",
4
- "version": "2.0.0-beta.1",
3
+ "version": "2.0.0-beta.2",
5
4
  "type": "module",
6
5
  "main": "dist/index.js",
7
6
  "types": "dist/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./dist/index.d.ts",
11
- "import": "./dist/index.js"
12
- },
13
- "./compiler": {
14
- "types": "./dist/compiler/vite.js",
15
- "import": "./dist/compiler/vite.js"
16
- }
17
- },
18
- "scripts": {
19
- "dev": "cd sample && vite",
20
- "build": "tsup",
21
- "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
22
- "preview": "vite preview",
23
- "test": "vitest",
24
- "docs": "vitepress dev docs",
25
- "docs:build": "vitepress build docs",
26
- "publish": "npm run build && npm publish"
27
- },
28
7
  "dependencies": {
29
8
  "@barvynkoa/particle-emitter": "^0.0.1",
30
- "@pixi/layers": "^2.1.0",
31
- "@pixi/lights": "^4.1.0",
32
9
  "@pixi/tilemap": "^5.0.1",
33
10
  "@rpgjs/tiled": "^4.3.0",
34
11
  "@signe/reactive": "^1.0.1",
35
- "animejs": "^3.2.2",
36
- "d-path-parser": "^1.0.0",
37
- "framer-motion": "^11.11.9",
38
12
  "howler": "^2.2.4",
39
- "peggy": "^3.0.2",
13
+ "package.json": "^2.0.1",
40
14
  "pixi-filters": "^6.0.5",
41
- "pixi-viewport": "^5.0.3",
15
+ "pixi-viewport": "^6.0.3",
42
16
  "pixi.js": "^8.6.4",
43
17
  "popmotion": "^11.0.5",
44
- "revolt-fx": "^1.3.5",
45
18
  "rxjs": "^7.8.1",
46
- "stats.js": "^0.17.0",
47
- "svg-arc-to-cubic-bezier": "^3.2.0",
48
- "tinycolor2": "^1.6.0",
49
- "tsup": "^8.2.4",
50
19
  "yoga-layout": "^2.0.1"
51
20
  },
52
21
  "devDependencies": {
53
- "@types/howler": "^2.2.11",
54
- "@types/node": "^22.10.2",
55
- "@types/stats.js": "^0.17.3",
56
- "acorn": "^8.12.1",
57
- "canvas": "^2.11.2",
58
- "dedent": "^1.5.3",
59
- "eslint": "^8.57.0",
60
- "jsdom": "^25.0.1",
61
- "lightningcss": "^1.28.2",
62
- "rollup-plugin-node-polyfills": "^0.2.1",
63
- "typescript": "^5.6.2",
64
- "vite": "^5.4.4",
65
- "vitepress": "^1.3.4",
66
- "vitest": "^1.6.0",
67
- "vitest-webgl-canvas-mock": "^1.1.0"
22
+ "@types/howler": "^2.2.11"
68
23
  },
69
24
  "author": "Samuel Ronce",
70
25
  "license": "MIT",
71
26
  "homepage": "https://canvasengine.net",
72
27
  "repository": {
73
28
  "type": "git",
74
- "url": "https://github.com/RSamaium/CanvasEngine.git"
29
+ "url": "git+https://github.com/RSamaium/CanvasEngine.git"
75
30
  },
76
31
  "bugs": {
77
32
  "url": "https://github.com/RSamaium/CanvasEngine/issues"
@@ -84,5 +39,14 @@
84
39
  ],
85
40
  "publishConfig": {
86
41
  "access": "public"
42
+ },
43
+ "overrides": {
44
+ "revolt-fx": {
45
+ "pixi.js": "^8.6.4"
46
+ }
47
+ },
48
+ "scripts": {
49
+ "build": "tsup",
50
+ "dev": "tsup --watch"
87
51
  }
88
- }
52
+ }
@@ -9,4 +9,5 @@ export { TiledMap } from './Tilemap'
9
9
  export { TilingSprite } from './TilingSprite'
10
10
  export { Viewport } from './Viewport'
11
11
  export { ImageMap } from './DrawMap'
12
- export { NineSliceSprite } from './NineSliceSprite'
12
+ export { NineSliceSprite } from './NineSliceSprite'
13
+ export { ComponentInstance } from './DisplayObject'
@@ -34,6 +34,7 @@ export interface DisplayObjectProps {
34
34
  pivot?: SignalOrPrimitive<{ x: number, y: number }>;
35
35
  filters?: any[];
36
36
  blendMode?: SignalOrPrimitive<PIXI.BLEND_MODES>;
37
+ blur?: SignalOrPrimitive<number>;
37
38
 
38
39
  click?: PIXI.FederatedEventHandler;
39
40
  mousedown?: PIXI.FederatedEventHandler;
@@ -468,7 +468,7 @@ export class KeyboardControls extends Directive {
468
468
  }
469
469
 
470
470
  private onKeyChange(e: KeyboardEvent, isDown: boolean) {
471
- e = e || window.event;
471
+ e = (e || window.event) as KeyboardEvent;
472
472
 
473
473
  const keyName: string = keyCodeTable[e.keyCode];
474
474
 
@@ -1,5 +1,4 @@
1
1
  import { WritableSignal } from '@signe/reactive';
2
- import Stats from 'stats.js';
3
2
  import { Directive, registerDirective } from '../engine/directive';
4
3
  import { Element } from '../engine/reactive';
5
4
  import * as Utils from '../engine/utils';
@@ -22,8 +21,6 @@ export class Scheduler extends Directive {
22
21
  private _stop: boolean = false
23
22
  private tick: WritableSignal<Tick | null>
24
23
 
25
- private stats = new Stats()
26
-
27
24
  onInit(element: Element) {
28
25
  this.tick = element.propObservables?.tick as any
29
26
  }
@@ -36,22 +33,15 @@ export class Scheduler extends Directive {
36
33
  this.lastTimestamp = this.lastTimestamp || this.timestamp // first
37
34
  this.deltaTime = Utils.preciseNow() - this.timestamp
38
35
  this.timestamp = timestamp
39
- this.stats.begin()
40
36
  this.tick.set({
41
37
  timestamp: this.timestamp,
42
38
  deltaTime: this.deltaTime,
43
39
  frame: this.frame,
44
40
  deltaRatio: ~~this.deltaTime / ~~Utils.fps2ms(this.fps)
45
41
  })
46
- this.stats.end()
47
42
  this.lastTimestamp = this.timestamp
48
43
  this.frame++
49
44
  }
50
-
51
- private showPanel() {
52
- this.stats.showPanel(0)
53
- }
54
-
55
45
  /**
56
46
  * start the schedule
57
47
  * @return {Scheduler} returns this scheduler instance
@@ -64,7 +54,6 @@ export class Scheduler extends Directive {
64
54
  if (options.maxFps) this.maxFps = options.maxFps
65
55
  if (options.fps) this.fps = options.fps
66
56
  if (options.delay) this.requestedDelay = options.delay
67
- this.showPanel()
68
57
  const requestAnimationFrame = (fn: (timestamp: number) => void) => {
69
58
  if (Utils.isBrowser()) {
70
59
  window.requestAnimationFrame(fn.bind(this))
package/src/index.ts CHANGED
@@ -8,7 +8,6 @@ export * from './engine/trigger'
8
8
  export * from './engine/bootstrap'
9
9
  export * from './engine/animation'
10
10
  export { useProps, useDefineProps } from './hooks/useProps'
11
-
12
- export * from './presets/Bar'
13
- export * from './presets/Particle'
14
- export * from './utils/Ease'
11
+ export * from './utils/Ease'
12
+ export * from './utils/RadialGradient'
13
+ export { isObservable } from 'rxjs'
package/.cursorrules DELETED
File without changes
package/README.md DELETED
@@ -1,71 +0,0 @@
1
- # CanvasEngine - A reactive HTML5 Canvas management library built on top of PixiJS
2
-
3
- ![CanvasEngine](logo.png)
4
-
5
- CanvasEngine is a reactive HTML5 Canvas management library built on top of PixiJS. It provides a component-oriented approach to canvas rendering, similar to modern frontend frameworks.
6
-
7
- Features:
8
- - Reactive components
9
- - Use flex in Canvas !
10
- - Easy Animation system
11
- - Keyboard, Gamepad et Virtual Joystick
12
- - Tiled Map Editor integration
13
- - Particle Emitter
14
- - Audio System
15
-
16
- ## Note: Performance Comparison with Pixi React
17
-
18
- CanvasEngine offers significant performance advantages over Pixi React. While Pixi React relies on React's detection cycles in addition to Pixi's traversal, which can be resource-intensive, CanvasEngine takes a more granular approach. It only updates the specific elements that have changed, resulting in more efficient rendering and better overall performance.
19
-
20
- ## Installation
21
-
22
- ```bash
23
- npx degit RSamaium/CanvasEngine/starter my-project
24
- cd my-project
25
- npm install
26
- npm run dev # and go to localhost:5173
27
- ```
28
-
29
- ## Documentation
30
-
31
- https://canvasengine.net
32
-
33
- ## Example:
34
-
35
- ```html
36
- <Container flexDirection="column" width="500px">
37
- <Sprite
38
- image="/assets/logo.png"
39
- anchor="0.5"
40
- rotation
41
- scale
42
- @pointerenter={onEnter}
43
- @pointerleave={onLeave}
44
- />
45
- <Text text size="70" fontFamily="Helvetica" x="90" y="-30" />
46
- </Container>
47
-
48
- <script>
49
- import { signal, tick, animatedSignal, Easing } from "canvasengine";
50
-
51
- const { text } = defineProps();
52
- const rotation = signal(0);
53
- const scale = animatedSignal(1, {
54
- duration: 300,
55
- ease: Easing.easeInOut,
56
- });
57
-
58
- tick(() => {
59
- rotation.update(rotation => rotation + 0.01);
60
- });
61
-
62
- const onEnter = () => {
63
- scale.set(1.5);
64
- };
65
-
66
- const onLeave = () => {
67
- scale.set(1);
68
- };
69
- </script>
70
- ```
71
-
@@ -1,119 +0,0 @@
1
- // src/compiler/vite.ts
2
- import { createFilter } from "vite";
3
- import { parse } from "acorn";
4
- import fs from "fs";
5
- import pkg from "peggy";
6
- import path from "path";
7
- import * as ts from "typescript";
8
- import { fileURLToPath } from "url";
9
- var { generate } = pkg;
10
- var DEV_SRC = "../../src";
11
- function canvasengine() {
12
- const filter = createFilter("**/*.ce");
13
- const __filename = fileURLToPath(import.meta.url);
14
- const __dirname = path.dirname(__filename);
15
- const grammar = fs.readFileSync(
16
- path.join(__dirname, "grammar.pegjs").replace("dist/compiler/grammar.pegjs", "src/compiler/grammar.pegjs"),
17
- "utf8"
18
- );
19
- const parser = generate(grammar);
20
- const isDev = process.env.NODE_ENV === "development";
21
- const FLAG_COMMENT = "/*--[TPL]--*/";
22
- const PRIMITIVE_COMPONENTS = [
23
- "Canvas",
24
- "Sprite",
25
- "Text",
26
- "Joystick",
27
- "Viewport",
28
- "Graphics",
29
- "Container",
30
- "ImageMap",
31
- "NineSliceSprite",
32
- "Rect",
33
- "Circle",
34
- "svg"
35
- ];
36
- return {
37
- name: "vite-plugin-ce",
38
- transform(code, id) {
39
- if (!filter(id)) return;
40
- const scriptMatch = code.match(/<script>([\s\S]*?)<\/script>/);
41
- let scriptContent = scriptMatch ? scriptMatch[1].trim() : "";
42
- let template = code.replace(/<script>[\s\S]*?<\/script>/, "").replace(/^\s+|\s+$/g, "");
43
- template = template.replace(/<svg>([\s\S]*?)<\/svg>/g, (match, content) => {
44
- return `<Svg content="${content.trim()}" />`;
45
- });
46
- const parsedTemplate = parser.parse(template);
47
- scriptContent += FLAG_COMMENT + parsedTemplate;
48
- let transpiledCode = ts.transpileModule(scriptContent, {
49
- compilerOptions: {
50
- module: ts.ModuleKind.Preserve
51
- }
52
- }).outputText;
53
- transpiledCode = transpiledCode.split(FLAG_COMMENT)[0];
54
- const parsed = parse(transpiledCode, {
55
- sourceType: "module",
56
- ecmaVersion: 2020
57
- });
58
- const imports = parsed.body.filter(
59
- (node) => node.type === "ImportDeclaration"
60
- );
61
- const nonImportCode = parsed.body.filter((node) => node.type !== "ImportDeclaration").map((node) => transpiledCode.slice(node.start, node.end)).join("\n");
62
- let importsCode = imports.map((imp) => {
63
- let importCode = transpiledCode.slice(imp.start, imp.end);
64
- if (isDev && importCode.includes("from 'canvasengine'")) {
65
- importCode = importCode.replace(
66
- "from 'canvasengine'",
67
- `from '${DEV_SRC}'`
68
- );
69
- }
70
- return importCode;
71
- }).join("\n");
72
- const requiredImports = ["h", "computed", "cond", "loop"];
73
- const missingImports = requiredImports.filter(
74
- (importName) => !imports.some(
75
- (imp) => imp.specifiers && imp.specifiers.some(
76
- (spec) => spec.type === "ImportSpecifier" && spec.imported && "name" in spec.imported && spec.imported.name === importName
77
- )
78
- )
79
- );
80
- if (missingImports.length > 0) {
81
- const additionalImportCode = `import { ${missingImports.join(
82
- ", "
83
- )} } from ${isDev ? `'${DEV_SRC}'` : "'canvasengine'"};`;
84
- importsCode = `${additionalImportCode}
85
- ${importsCode}`;
86
- }
87
- const primitiveImports = PRIMITIVE_COMPONENTS.filter(
88
- (component) => parsedTemplate.includes(`h(${component}`)
89
- );
90
- primitiveImports.forEach((component) => {
91
- const importStatement = `import { ${component} } from ${isDev ? `'${DEV_SRC}'` : "'canvasengine'"};`;
92
- if (!importsCode.includes(importStatement)) {
93
- importsCode = `${importStatement}
94
- ${importsCode}`;
95
- }
96
- });
97
- const output = String.raw`
98
- ${importsCode}
99
- import { useProps, useDefineProps } from ${isDev ? `'${DEV_SRC}'` : "'canvasengine'"}
100
-
101
- export default function component($$props) {
102
- const $props = useProps($$props)
103
- const defineProps = useDefineProps($$props)
104
- ${nonImportCode}
105
- let $this = ${parsedTemplate}
106
- return $this
107
- }
108
- `;
109
- return {
110
- code: output,
111
- map: null
112
- };
113
- }
114
- };
115
- }
116
- export {
117
- canvasengine as default
118
- };
119
- //# sourceMappingURL=vite.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../../src/compiler/vite.ts"],"sourcesContent":["import { createFilter } from \"vite\";\nimport { parse } from \"acorn\";\nimport fs from \"fs\";\nimport pkg from \"peggy\";\nimport path from \"path\";\nimport * as ts from \"typescript\"; // Import TypeScript package\nimport { fileURLToPath } from 'url';\n\nconst { generate } = pkg;\n\nconst DEV_SRC = \"../../src\"\n\nexport default function canvasengine() {\n const filter = createFilter(\"**/*.ce\");\n\n // Convert import.meta.url to a file path\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = path.dirname(__filename);\n\n const grammar = fs.readFileSync(\n path.join(__dirname, \"grammar.pegjs\").replace(\"dist/compiler/grammar.pegjs\", \"src/compiler/grammar.pegjs\"), \n \"utf8\");\n const parser = generate(grammar);\n const isDev = process.env.NODE_ENV === \"development\";\n const FLAG_COMMENT = \"/*--[TPL]--*/\";\n\n const PRIMITIVE_COMPONENTS = [\n \"Canvas\",\n \"Sprite\",\n \"Text\",\n \"Joystick\",\n \"Viewport\",\n \"Graphics\",\n \"Container\",\n \"ImageMap\",\n \"NineSliceSprite\",\n \"Rect\",\n \"Circle\",\n \"svg\"\n ];\n\n return {\n name: \"vite-plugin-ce\",\n transform(code: string, id: string) {\n if (!filter(id)) return;\n\n // Extract the script content\n const scriptMatch = code.match(/<script>([\\s\\S]*?)<\\/script>/);\n let scriptContent = scriptMatch ? scriptMatch[1].trim() : \"\";\n \n // Transform SVG tags to Svg components\n let template = code.replace(/<script>[\\s\\S]*?<\\/script>/, \"\")\n .replace(/^\\s+|\\s+$/g, '');\n \n // Add SVG transformation\n template = template.replace(/<svg>([\\s\\S]*?)<\\/svg>/g, (match, content) => {\n return `<Svg content=\"${content.trim()}\" />`;\n });\n \n const parsedTemplate = parser.parse(template);\n\n // trick to avoid typescript remove imports in scriptContent\n scriptContent += FLAG_COMMENT + parsedTemplate\n\n let transpiledCode = ts.transpileModule(scriptContent, {\n compilerOptions: {\n module: ts.ModuleKind.Preserve,\n },\n }).outputText;\n\n // remove code after /*---*/\n transpiledCode = transpiledCode.split(FLAG_COMMENT)[0]\n\n // Use Acorn to parse the script content\n const parsed = parse(transpiledCode, {\n sourceType: \"module\",\n ecmaVersion: 2020,\n });\n\n // Extract imports\n const imports = parsed.body.filter(\n (node) => node.type === \"ImportDeclaration\"\n );\n\n // Extract non-import statements from scriptContent\n const nonImportCode = parsed.body\n .filter((node) => node.type !== \"ImportDeclaration\")\n .map((node) => transpiledCode.slice(node.start, node.end))\n .join(\"\\n\");\n\n let importsCode = imports\n .map((imp) => {\n let importCode = transpiledCode.slice(imp.start, imp.end);\n if (isDev && importCode.includes(\"from 'canvasengine'\")) {\n importCode = importCode.replace(\n \"from 'canvasengine'\",\n `from '${DEV_SRC}'`\n );\n }\n return importCode;\n })\n .join(\"\\n\");\n\n // Define an array for required imports\n const requiredImports = [\"h\", \"computed\", \"cond\", \"loop\"];\n\n // Check for missing imports\n const missingImports = requiredImports.filter(\n (importName) =>\n !imports.some(\n (imp) =>\n imp.specifiers &&\n imp.specifiers.some(\n (spec) =>\n spec.type === \"ImportSpecifier\" &&\n spec.imported && \n 'name' in spec.imported &&\n spec.imported.name === importName\n )\n )\n );\n\n // Add missing imports\n if (missingImports.length > 0) {\n const additionalImportCode = `import { ${missingImports.join(\n \", \"\n )} } from ${isDev ? `'${DEV_SRC}'` : \"'canvasengine'\"};`;\n importsCode = `${additionalImportCode}\\n${importsCode}`;\n }\n\n // Check for primitive components in parsedTemplate\n const primitiveImports = PRIMITIVE_COMPONENTS.filter((component) =>\n parsedTemplate.includes(`h(${component}`)\n );\n\n // Add missing imports for primitive components\n primitiveImports.forEach((component) => {\n const importStatement = `import { ${component} } from ${\n isDev ? `'${DEV_SRC}'` : \"'canvasengine'\"\n };`;\n if (!importsCode.includes(importStatement)) {\n importsCode = `${importStatement}\\n${importsCode}`;\n }\n });\n\n // Generate the output\n const output = String.raw`\n ${importsCode}\n import { useProps, useDefineProps } from ${isDev ? `'${DEV_SRC}'` : \"'canvasengine'\"}\n\n export default function component($$props) {\n const $props = useProps($$props)\n const defineProps = useDefineProps($$props)\n ${nonImportCode}\n let $this = ${parsedTemplate}\n return $this\n }\n `;\n\n return {\n code: output,\n map: null,\n };\n },\n };\n}\n"],"mappings":"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","names":[]}