@geometra/renderer-canvas 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ export { CanvasRenderer } from './renderer.js';
2
+ export type { CanvasRendererOptions } from './renderer.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC9C,YAAY,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export { CanvasRenderer } from './renderer.js';
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA"}
@@ -0,0 +1,25 @@
1
+ import type { ComputedLayout } from 'textura';
2
+ import type { Renderer, UIElement } from '@geometra/core';
3
+ export interface CanvasRendererOptions {
4
+ /** Canvas element to render into. */
5
+ canvas: HTMLCanvasElement;
6
+ /** Device pixel ratio for crisp rendering. Default: window.devicePixelRatio. */
7
+ dpr?: number;
8
+ /** Background color for the canvas. Default: '#ffffff'. */
9
+ background?: string;
10
+ }
11
+ export declare class CanvasRenderer implements Renderer {
12
+ private ctx;
13
+ private canvas;
14
+ private dpr;
15
+ private background;
16
+ constructor(options: CanvasRendererOptions);
17
+ render(layout: ComputedLayout, tree: UIElement): void;
18
+ private paintNode;
19
+ private paintBox;
20
+ private paintText;
21
+ private wrapText;
22
+ private roundRect;
23
+ destroy(): void;
24
+ }
25
+ //# sourceMappingURL=renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAA2B,MAAM,gBAAgB,CAAA;AAElF,MAAM,WAAW,qBAAqB;IACpC,qCAAqC;IACrC,MAAM,EAAE,iBAAiB,CAAA;IACzB,gFAAgF;IAChF,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,2DAA2D;IAC3D,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,qBAAa,cAAe,YAAW,QAAQ;IAC7C,OAAO,CAAC,GAAG,CAA0B;IACrC,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,GAAG,CAAQ;IACnB,OAAO,CAAC,UAAU,CAAQ;gBAEd,OAAO,EAAE,qBAAqB;IAU1C,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAoBrD,OAAO,CAAC,SAAS;IAuBjB,OAAO,CAAC,QAAQ;IAqChB,OAAO,CAAC,SAAS;IA8BjB,OAAO,CAAC,QAAQ;IAwBhB,OAAO,CAAC,SAAS;IAejB,OAAO,IAAI,IAAI;CAGhB"}
@@ -0,0 +1,135 @@
1
+ export class CanvasRenderer {
2
+ ctx;
3
+ canvas;
4
+ dpr;
5
+ background;
6
+ constructor(options) {
7
+ this.canvas = options.canvas;
8
+ this.dpr = options.dpr ?? window.devicePixelRatio;
9
+ this.background = options.background ?? '#ffffff';
10
+ const ctx = this.canvas.getContext('2d');
11
+ if (!ctx)
12
+ throw new Error('Could not get 2d context');
13
+ this.ctx = ctx;
14
+ }
15
+ render(layout, tree) {
16
+ const { ctx, canvas, dpr } = this;
17
+ // Size canvas to layout
18
+ canvas.width = layout.width * dpr;
19
+ canvas.height = layout.height * dpr;
20
+ canvas.style.width = `${layout.width}px`;
21
+ canvas.style.height = `${layout.height}px`;
22
+ ctx.scale(dpr, dpr);
23
+ // Clear
24
+ ctx.fillStyle = this.background;
25
+ ctx.fillRect(0, 0, layout.width, layout.height);
26
+ this.paintNode(tree, layout, 0, 0);
27
+ // Reset transform for next frame
28
+ ctx.setTransform(1, 0, 0, 1, 0, 0);
29
+ }
30
+ paintNode(element, layout, offsetX, offsetY) {
31
+ const x = offsetX + layout.x;
32
+ const y = offsetY + layout.y;
33
+ const { width, height } = layout;
34
+ if (element.kind === 'box') {
35
+ this.paintBox(element, layout, x, y, width, height);
36
+ for (let i = 0; i < element.children.length; i++) {
37
+ const childLayout = layout.children[i];
38
+ if (childLayout) {
39
+ this.paintNode(element.children[i], childLayout, x, y);
40
+ }
41
+ }
42
+ }
43
+ else {
44
+ this.paintText(element, x, y, width, height);
45
+ }
46
+ }
47
+ paintBox(element, _layout, x, y, width, height) {
48
+ const { ctx } = this;
49
+ const { backgroundColor, borderColor, borderRadius, opacity } = element.props;
50
+ if (opacity !== undefined)
51
+ ctx.globalAlpha = opacity;
52
+ if (backgroundColor) {
53
+ ctx.fillStyle = backgroundColor;
54
+ if (borderRadius) {
55
+ this.roundRect(x, y, width, height, borderRadius);
56
+ ctx.fill();
57
+ }
58
+ else {
59
+ ctx.fillRect(x, y, width, height);
60
+ }
61
+ }
62
+ if (borderColor) {
63
+ ctx.strokeStyle = borderColor;
64
+ ctx.lineWidth = 1;
65
+ if (borderRadius) {
66
+ this.roundRect(x, y, width, height, borderRadius);
67
+ ctx.stroke();
68
+ }
69
+ else {
70
+ ctx.strokeRect(x, y, width, height);
71
+ }
72
+ }
73
+ if (opacity !== undefined)
74
+ ctx.globalAlpha = 1;
75
+ }
76
+ paintText(element, x, y, _width, _height) {
77
+ const { ctx } = this;
78
+ const { text, font, color, backgroundColor, lineHeight, opacity } = element.props;
79
+ if (opacity !== undefined)
80
+ ctx.globalAlpha = opacity;
81
+ if (backgroundColor) {
82
+ ctx.fillStyle = backgroundColor;
83
+ ctx.fillRect(x, y, _width, _height);
84
+ }
85
+ ctx.font = font;
86
+ ctx.fillStyle = color ?? '#000000';
87
+ ctx.textBaseline = 'top';
88
+ // Simple multi-line: split on newlines, wrap within width
89
+ const lines = this.wrapText(text, _width);
90
+ for (let i = 0; i < lines.length; i++) {
91
+ ctx.fillText(lines[i], x, y + i * lineHeight);
92
+ }
93
+ if (opacity !== undefined)
94
+ ctx.globalAlpha = 1;
95
+ }
96
+ wrapText(text, maxWidth) {
97
+ const { ctx } = this;
98
+ const lines = [];
99
+ const paragraphs = text.split('\n');
100
+ for (const para of paragraphs) {
101
+ const words = para.split(' ');
102
+ let current = '';
103
+ for (const word of words) {
104
+ const test = current ? `${current} ${word}` : word;
105
+ if (ctx.measureText(test).width > maxWidth && current) {
106
+ lines.push(current);
107
+ current = word;
108
+ }
109
+ else {
110
+ current = test;
111
+ }
112
+ }
113
+ lines.push(current);
114
+ }
115
+ return lines;
116
+ }
117
+ roundRect(x, y, w, h, r) {
118
+ const { ctx } = this;
119
+ ctx.beginPath();
120
+ ctx.moveTo(x + r, y);
121
+ ctx.lineTo(x + w - r, y);
122
+ ctx.quadraticCurveTo(x + w, y, x + w, y + r);
123
+ ctx.lineTo(x + w, y + h - r);
124
+ ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
125
+ ctx.lineTo(x + r, y + h);
126
+ ctx.quadraticCurveTo(x, y + h, x, y + h - r);
127
+ ctx.lineTo(x, y + r);
128
+ ctx.quadraticCurveTo(x, y, x + r, y);
129
+ ctx.closePath();
130
+ }
131
+ destroy() {
132
+ // Nothing to clean up for canvas
133
+ }
134
+ }
135
+ //# sourceMappingURL=renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.js","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "@geometra/renderer-canvas",
3
+ "version": "0.1.0",
4
+ "description": "Canvas2D renderer for Textura framework",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/razroo/textrura-framework",
10
+ "directory": "packages/renderer-canvas"
11
+ },
12
+ "homepage": "https://razroo.github.io/textrura-framework",
13
+ "keywords": [
14
+ "textura",
15
+ "renderer",
16
+ "canvas",
17
+ "dom-free"
18
+ ],
19
+ "main": "./dist/index.js",
20
+ "types": "./dist/index.d.ts",
21
+ "exports": {
22
+ ".": {
23
+ "types": "./dist/index.d.ts",
24
+ "import": "./dist/index.js"
25
+ }
26
+ },
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "scripts": {
31
+ "build": "rm -rf dist && tsc -p tsconfig.build.json",
32
+ "check": "tsc --noEmit"
33
+ },
34
+ "dependencies": {
35
+ "@geometra/core": "^0.1.0"
36
+ }
37
+ }