@meonode/canvas 1.0.0-beta.1
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/CONTRIBUTING.md +75 -0
- package/LICENSE +21 -0
- package/Readme.md +382 -0
- package/dist/cjs/canvas/canvas.helper.d.ts +57 -0
- package/dist/cjs/canvas/canvas.helper.d.ts.map +1 -0
- package/dist/cjs/canvas/canvas.helper.js +239 -0
- package/dist/cjs/canvas/canvas.helper.js.map +1 -0
- package/dist/cjs/canvas/canvas.type.d.ts +657 -0
- package/dist/cjs/canvas/canvas.type.d.ts.map +1 -0
- package/dist/cjs/canvas/grid.canvas.util.d.ts +39 -0
- package/dist/cjs/canvas/grid.canvas.util.d.ts.map +1 -0
- package/dist/cjs/canvas/grid.canvas.util.js +263 -0
- package/dist/cjs/canvas/grid.canvas.util.js.map +1 -0
- package/dist/cjs/canvas/image.canvas.util.d.ts +34 -0
- package/dist/cjs/canvas/image.canvas.util.d.ts.map +1 -0
- package/dist/cjs/canvas/image.canvas.util.js +310 -0
- package/dist/cjs/canvas/image.canvas.util.js.map +1 -0
- package/dist/cjs/canvas/layout.canvas.util.d.ts +123 -0
- package/dist/cjs/canvas/layout.canvas.util.d.ts.map +1 -0
- package/dist/cjs/canvas/layout.canvas.util.js +785 -0
- package/dist/cjs/canvas/layout.canvas.util.js.map +1 -0
- package/dist/cjs/canvas/root.canvas.util.d.ts +42 -0
- package/dist/cjs/canvas/root.canvas.util.d.ts.map +1 -0
- package/dist/cjs/canvas/root.canvas.util.js +140 -0
- package/dist/cjs/canvas/root.canvas.util.js.map +1 -0
- package/dist/cjs/canvas/text.canvas.util.d.ts +148 -0
- package/dist/cjs/canvas/text.canvas.util.d.ts.map +1 -0
- package/dist/cjs/canvas/text.canvas.util.js +1112 -0
- package/dist/cjs/canvas/text.canvas.util.js.map +1 -0
- package/dist/cjs/constant/common.const.d.ts +37 -0
- package/dist/cjs/constant/common.const.d.ts.map +1 -0
- package/dist/cjs/constant/common.const.js +51 -0
- package/dist/cjs/constant/common.const.js.map +1 -0
- package/dist/cjs/index.d.ts +7 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +31 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/esm/canvas/canvas.helper.d.ts +57 -0
- package/dist/esm/canvas/canvas.helper.d.ts.map +1 -0
- package/dist/esm/canvas/canvas.helper.js +214 -0
- package/dist/esm/canvas/canvas.type.d.ts +657 -0
- package/dist/esm/canvas/canvas.type.d.ts.map +1 -0
- package/dist/esm/canvas/grid.canvas.util.d.ts +39 -0
- package/dist/esm/canvas/grid.canvas.util.d.ts.map +1 -0
- package/dist/esm/canvas/grid.canvas.util.js +259 -0
- package/dist/esm/canvas/image.canvas.util.d.ts +34 -0
- package/dist/esm/canvas/image.canvas.util.d.ts.map +1 -0
- package/dist/esm/canvas/image.canvas.util.js +306 -0
- package/dist/esm/canvas/layout.canvas.util.d.ts +123 -0
- package/dist/esm/canvas/layout.canvas.util.d.ts.map +1 -0
- package/dist/esm/canvas/layout.canvas.util.js +777 -0
- package/dist/esm/canvas/root.canvas.util.d.ts +42 -0
- package/dist/esm/canvas/root.canvas.util.d.ts.map +1 -0
- package/dist/esm/canvas/root.canvas.util.js +116 -0
- package/dist/esm/canvas/text.canvas.util.d.ts +148 -0
- package/dist/esm/canvas/text.canvas.util.d.ts.map +1 -0
- package/dist/esm/canvas/text.canvas.util.js +1108 -0
- package/dist/esm/constant/common.const.d.ts +37 -0
- package/dist/esm/constant/common.const.d.ts.map +1 -0
- package/dist/esm/constant/common.const.js +23 -0
- package/dist/esm/index.d.ts +7 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +7 -0
- package/dist/meonode-canvas-1.0.0-beta.1.tgz +0 -0
- package/package.json +79 -0
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Contributing to @meonode/canvas
|
|
2
|
+
|
|
3
|
+
First off, thank you for considering contributing! It's people like you that make open source such a great community.
|
|
4
|
+
|
|
5
|
+
## Where do I go from here?
|
|
6
|
+
|
|
7
|
+
If you've noticed a bug or have a feature request, [make one](https://github.com/meonode/canvas/issues/new)! It's generally best if you get confirmation of your bug or approval for your feature request this way before starting to code.
|
|
8
|
+
|
|
9
|
+
### Fork & create a branch
|
|
10
|
+
|
|
11
|
+
If this is something you think you can fix, then [fork @meonode/canvas](https://github.com/meonode/canvas/fork) and create a branch with a descriptive name.
|
|
12
|
+
|
|
13
|
+
A good branch name would be (where issue #38 is the ticket you're working on):
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
git checkout -b 38-add-gaussian-blur-support
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Get the project running
|
|
20
|
+
|
|
21
|
+
At this point, you're ready to make your changes! Feel free to ask for help; everyone is a beginner at first :smile_cat:
|
|
22
|
+
|
|
23
|
+
1. Install dependencies:
|
|
24
|
+
```sh
|
|
25
|
+
yarn install
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
2. Run the linter to ensure your code follows the project's style guidelines:
|
|
29
|
+
```sh
|
|
30
|
+
yarn lint
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
3. Run the tests to make sure everything is working as expected:
|
|
34
|
+
```sh
|
|
35
|
+
yarn test
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
4. Build the project to generate the distribution files:
|
|
39
|
+
```sh
|
|
40
|
+
yarn build
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Make your changes
|
|
44
|
+
|
|
45
|
+
Now, go to town on your feature or bug fix.
|
|
46
|
+
|
|
47
|
+
### Commit your changes
|
|
48
|
+
|
|
49
|
+
Make sure your commit messages are clear and descriptive.
|
|
50
|
+
|
|
51
|
+
### Push to your fork and submit a pull request
|
|
52
|
+
|
|
53
|
+
At this point, you should switch back to your master branch and make sure it's up to date with the latest upstream master.
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
git remote add upstream git@github.com:meonode/canvas.git
|
|
57
|
+
git checkout master
|
|
58
|
+
git pull upstream master
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Then, update your feature branch from your local copy of master, and push it!
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
git checkout 38-add-gaussian-blur-support
|
|
65
|
+
git rebase master
|
|
66
|
+
git push --force-with-lease origin 38-add-gaussian-blur-support
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Finally, go to GitHub and [make a Pull Request](https://github.com/meonode/canvas/compare) :D
|
|
70
|
+
|
|
71
|
+
We're happy to help you get your PR reviewed and merged.
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
*This contribution guide was adapted from the [React-Boilerplate guide](https://github.com/react-boilerplate/react-boilerplate/blob/master/CONTRIBUTING.md).*
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Ukasyah Rahmatullah Zada
|
|
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.
|
package/Readme.md
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
# @meonode/canvas
|
|
2
|
+
|
|
3
|
+
A declarative, component-based library for generating images on a canvas, inspired by the MeoNode UI library for React.
|
|
4
|
+
It uses `skia-canvas` for drawing and `yoga-layout` for flexbox-based layouts.
|
|
5
|
+
|
|
6
|
+
This library allows you to build complex image layouts using a familiar component-based approach. You can define your
|
|
7
|
+
image structure with components like `Box`, `Text`, `Image`, and `Grid`, and the library will handle the layout and
|
|
8
|
+
rendering to a canvas.
|
|
9
|
+
|
|
10
|
+
## Key Features
|
|
11
|
+
|
|
12
|
+
- **Declarative API:** Build images using a component tree, just like in React.
|
|
13
|
+
- **Flexbox Layout:** Powered by `yoga-layout`, it supports flexbox for powerful and flexible layouts.
|
|
14
|
+
- **Rich Text:** Render text with custom fonts and inline styling using simple HTML-like tags. Supported tags include
|
|
15
|
+
`<color="value">`, `<weight="value">`, `<size="value">`, `<b>`, and `<i>`.
|
|
16
|
+
- **Image Support:** Render images from URLs, file paths, or buffers, with `object-fit` and `object-position` support.
|
|
17
|
+
- **Styling:** Style your components with properties that mimic CSS, including borders, padding, margins, and more.
|
|
18
|
+
- **Grid Layout:** A `Grid` component is provided for easy grid-based layouts.
|
|
19
|
+
- **TypeScript Support:** Fully typed for a better development experience.
|
|
20
|
+
|
|
21
|
+
## Showcase
|
|
22
|
+
|
|
23
|
+
<table>
|
|
24
|
+
<tr>
|
|
25
|
+
<td><img src="https://i.ibb.co/VpPZybzF/profile-card.webp" alt="Image 1"></td>
|
|
26
|
+
<td><img src="https://i.ibb.co/zTgrBWpT/profile-card-1.webp" alt="Image 2"></td>
|
|
27
|
+
</tr>
|
|
28
|
+
<tr>
|
|
29
|
+
<td><img src="https://i.ibb.co/F4xfHdBp/daily-notes.webp" alt="Image 3"></td>
|
|
30
|
+
<td><img src="https://i.ibb.co/Jj0x6khB/character-archive-base.webp" alt="Image 4"></td>
|
|
31
|
+
</tr>
|
|
32
|
+
</table>
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
yarn add @meonode/canvas
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Basic Usage
|
|
41
|
+
|
|
42
|
+
Here's a simple example of how to create an image with a title and a description:
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import {Root, Box, Text} from '@meonode/canvas';
|
|
46
|
+
import {writeFile} from 'fs/promises';
|
|
47
|
+
|
|
48
|
+
async function generateImage() {
|
|
49
|
+
const canvas = await Root({
|
|
50
|
+
width: 500,
|
|
51
|
+
height: 300,
|
|
52
|
+
fonts: [
|
|
53
|
+
{
|
|
54
|
+
family: 'Roboto',
|
|
55
|
+
paths: ['./fonts/Roboto-Regular.ttf', './fonts/Roboto-Bold.ttf'],
|
|
56
|
+
},
|
|
57
|
+
],
|
|
58
|
+
children: [
|
|
59
|
+
Box({
|
|
60
|
+
width: '100%',
|
|
61
|
+
height: '100%',
|
|
62
|
+
backgroundColor: '#f0f0f0',
|
|
63
|
+
padding: 20,
|
|
64
|
+
children: [
|
|
65
|
+
Text('Hello, World!', {
|
|
66
|
+
fontSize: 32,
|
|
67
|
+
fontWeight: 'bold',
|
|
68
|
+
fontFamily: 'Roboto',
|
|
69
|
+
color: '#333',
|
|
70
|
+
}),
|
|
71
|
+
Text('This is a basic example of using @meonode/canvas.', {
|
|
72
|
+
fontSize: 18,
|
|
73
|
+
fontFamily: 'Roboto',
|
|
74
|
+
color: '#666',
|
|
75
|
+
margin: {Top: 10},
|
|
76
|
+
}),
|
|
77
|
+
],
|
|
78
|
+
}),
|
|
79
|
+
],
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
const buffer = await canvas.toBuffer('png');
|
|
83
|
+
await writeFile('output.png', buffer);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
generateImage().catch(console.error);
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Wider Usage Example
|
|
90
|
+
|
|
91
|
+
This example demonstrates a more complex layout using various components, including `Image` and advanced flexbox
|
|
92
|
+
properties.
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
import {Root, Column, Row, Text, Image, Style} from '@meonode/canvas';
|
|
96
|
+
import {writeFile} from 'fs/promises';
|
|
97
|
+
|
|
98
|
+
async function generateComplexImage() {
|
|
99
|
+
const canvas = await Root({
|
|
100
|
+
width: 800,
|
|
101
|
+
height: 600,
|
|
102
|
+
fonts: [
|
|
103
|
+
{
|
|
104
|
+
family: 'Roboto',
|
|
105
|
+
paths: ['./fonts/Roboto-Regular.ttf', './fonts/Roboto-Bold.ttf'],
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
family: 'Open Sans',
|
|
109
|
+
paths: ['./fonts/OpenSans-Regular.ttf'],
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
children: [
|
|
113
|
+
Column({
|
|
114
|
+
width: '100%',
|
|
115
|
+
height: '100%',
|
|
116
|
+
backgroundColor: '#f0f0f0',
|
|
117
|
+
padding: 20,
|
|
118
|
+
justifyContent: Style.Justify.SpaceBetween,
|
|
119
|
+
children: [
|
|
120
|
+
// Header Section
|
|
121
|
+
Row({
|
|
122
|
+
width: '100%',
|
|
123
|
+
alignItems: Style.Align.Center,
|
|
124
|
+
marginBottom: 20,
|
|
125
|
+
children: [
|
|
126
|
+
Image({
|
|
127
|
+
src: 'https://via.placeholder.com/80x80/FF0000/FFFFFF?text=Logo',
|
|
128
|
+
width: 80,
|
|
129
|
+
height: 80,
|
|
130
|
+
borderRadius: 40,
|
|
131
|
+
marginRight: 20,
|
|
132
|
+
objectFit: 'cover',
|
|
133
|
+
}),
|
|
134
|
+
Text('Welcome to MeoNode Canvas!', {
|
|
135
|
+
fontSize: 40,
|
|
136
|
+
fontWeight: 'bold',
|
|
137
|
+
fontFamily: 'Roboto',
|
|
138
|
+
color: '#333',
|
|
139
|
+
}),
|
|
140
|
+
],
|
|
141
|
+
}),
|
|
142
|
+
|
|
143
|
+
// Main Content Section
|
|
144
|
+
Column({
|
|
145
|
+
flexGrow: 1,
|
|
146
|
+
width: '100%',
|
|
147
|
+
backgroundColor: '#ffffff',
|
|
148
|
+
borderRadius: 10,
|
|
149
|
+
padding: 30,
|
|
150
|
+
boxShadow: {blur: 10, color: 'rgba(0,0,0,0.1)'},
|
|
151
|
+
children: [
|
|
152
|
+
Text('A New Way to Render Graphics', {
|
|
153
|
+
fontSize: 28,
|
|
154
|
+
fontWeight: 'bold',
|
|
155
|
+
fontFamily: 'Open Sans',
|
|
156
|
+
color: '#555',
|
|
157
|
+
marginBottom: 15,
|
|
158
|
+
}),
|
|
159
|
+
Text(
|
|
160
|
+
`This example demonstrates a more complex layout using various components.
|
|
161
|
+
We have a header with a logo and title, a main content area with text,
|
|
162
|
+
and a footer. Notice how flexbox properties are used to arrange elements.`,
|
|
163
|
+
{
|
|
164
|
+
fontSize: 18,
|
|
165
|
+
fontFamily: 'Open Sans',
|
|
166
|
+
color: '#777',
|
|
167
|
+
lineHeight: 24,
|
|
168
|
+
},
|
|
169
|
+
),
|
|
170
|
+
Image({
|
|
171
|
+
src: 'https://via.placeholder.com/600x200/007bff/ffffff?text=Feature+Image',
|
|
172
|
+
width: '100%',
|
|
173
|
+
height: 200,
|
|
174
|
+
marginTop: 20,
|
|
175
|
+
borderRadius: 8,
|
|
176
|
+
objectFit: 'contain',
|
|
177
|
+
objectPosition: {Top: '50%', Left: '50%'},
|
|
178
|
+
}),
|
|
179
|
+
],
|
|
180
|
+
}),
|
|
181
|
+
|
|
182
|
+
// Footer Section
|
|
183
|
+
Row({
|
|
184
|
+
width: '100%',
|
|
185
|
+
marginTop: 20,
|
|
186
|
+
justifyContent: Style.Justify.Center,
|
|
187
|
+
children: [
|
|
188
|
+
Text('© 2025 MeoNode Canvas. All rights reserved.', {
|
|
189
|
+
fontSize: 14,
|
|
190
|
+
fontFamily: 'Open Sans',
|
|
191
|
+
color: '#999',
|
|
192
|
+
}),
|
|
193
|
+
],
|
|
194
|
+
}),
|
|
195
|
+
],
|
|
196
|
+
}),
|
|
197
|
+
],
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
const buffer = await canvas.toBuffer('png');
|
|
201
|
+
await writeFile('complex_output.png', buffer);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
generateComplexImage().catch(console.error);
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Using Yoga Layout Properties
|
|
208
|
+
|
|
209
|
+
This library leverages `yoga-layout` for its powerful flexbox engine. Many layout properties directly map to Yoga's
|
|
210
|
+
concepts. You can access Yoga-specific constants through the `Style` export from `@meonode/canvas`.
|
|
211
|
+
|
|
212
|
+
For example, to set `flexDirection` to `row` or `positionType` to `absolute`, you would use:
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
import {Box, Style} from '@meonode/canvas';
|
|
216
|
+
|
|
217
|
+
Box({
|
|
218
|
+
flexDirection: Style.FlexDirection.Row,
|
|
219
|
+
justifyContent: Style.Justify.Center,
|
|
220
|
+
alignItems: Style.Align.Center,
|
|
221
|
+
children: [
|
|
222
|
+
Box({
|
|
223
|
+
width: 100,
|
|
224
|
+
height: 100,
|
|
225
|
+
backgroundColor: 'red',
|
|
226
|
+
positionType: Style.PositionType.Absolute,
|
|
227
|
+
position: {Top: 10, Left: 10},
|
|
228
|
+
}),
|
|
229
|
+
// ... other children
|
|
230
|
+
],
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Refer to the [Yoga Layout documentation](https://yogalayout.dev/docs/) for a comprehensive understanding of these properties.
|
|
235
|
+
|
|
236
|
+
## Component API Reference
|
|
237
|
+
|
|
238
|
+
This section details the props available for each component.
|
|
239
|
+
|
|
240
|
+
### Box, Row, and Column
|
|
241
|
+
|
|
242
|
+
These are the fundamental layout components. `Row` and `Column` are wrappers around `Box` with a pre-set
|
|
243
|
+
`flexDirection`. They all share the same props.
|
|
244
|
+
|
|
245
|
+
#### Layout Props
|
|
246
|
+
|
|
247
|
+
| Prop | Type | Description |
|
|
248
|
+
|-------------------------|------------------------------|--------------------------------------------------------------------------------|
|
|
249
|
+
| `width`, `height` | `number \| string` | Sets the size of the node in pixels or percentage. |
|
|
250
|
+
| `minWidth`, `minHeight` | `number \| string` | Sets the minimum size of the node. |
|
|
251
|
+
| `maxWidth`, `maxHeight` | `number \| string` | Sets the maximum size of the node. |
|
|
252
|
+
| `flexDirection` | `Style.FlexDirection` | Defines the direction of the main axis (`Row`, `Column`, etc.). |
|
|
253
|
+
| `justifyContent` | `Style.Justify` | Defines how items are distributed along the main axis. |
|
|
254
|
+
| `alignItems` | `Style.Align` | Defines how items are aligned along the cross axis. |
|
|
255
|
+
| `alignSelf` | `Style.Align` | Overrides the parent's `alignItems` for a specific item. |
|
|
256
|
+
| `alignContent` | `Style.Align` | Defines how lines are distributed when content wraps. |
|
|
257
|
+
| `flexGrow` | `number` | Defines the ability of an item to grow. |
|
|
258
|
+
| `flexShrink` | `number` | Defines the ability of an item to shrink. |
|
|
259
|
+
| `flexBasis` | `number \| 'auto' \| string` | Defines the default size of an item along the main axis. |
|
|
260
|
+
| `flexWrap` | `Style.Wrap` | Controls whether flex items wrap to multiple lines. |
|
|
261
|
+
| `positionType` | `Style.PositionType` | Sets the positioning method (`Relative` or `Absolute`). |
|
|
262
|
+
| `position` | `object \| number \| string` | Sets the offset for a positioned element. |
|
|
263
|
+
| `margin` | `object \| number \| string` | Sets the margin space on the outside of the node. |
|
|
264
|
+
| `padding` | `object \| number \| string` | Sets the padding space on the inside of the node. |
|
|
265
|
+
| `border` | `object \| number` | Sets the width of the node's border. |
|
|
266
|
+
| `aspectRatio` | `number` | Locks the aspect ratio (width / height) of the node. |
|
|
267
|
+
| `overflow` | `Style.Overflow` | Defines how content that overflows is handled (`Visible`, `Hidden`). |
|
|
268
|
+
| `display` | `Style.Display` | Controls if the node is included in layout (`Flex`, `None`). |
|
|
269
|
+
| `direction` | `Style.Direction` | Sets the primary layout direction (`LTR`, `RTL`). |
|
|
270
|
+
| `gap` | `object \| number \| string` | Defines the space between flex items. |
|
|
271
|
+
| `boxSizing` | `Style.BoxSizing` | Defines how `width` and `height` are interpreted (`ContentBox`, `BorderBox`). |
|
|
272
|
+
| `zIndex` | `number` | Specifies the stack order of an element (only for `positionType: 'absolute'`). |
|
|
273
|
+
|
|
274
|
+
#### Styling Props
|
|
275
|
+
|
|
276
|
+
| Prop | Type | Description |
|
|
277
|
+
|-------------------|--------------------------------------|--------------------------------------------------------|
|
|
278
|
+
| `backgroundColor` | `string` | Sets the background color of the node. |
|
|
279
|
+
| `borderColor` | `string` | Sets the color of the node's border. |
|
|
280
|
+
| `borderStyle` | `Style.Border` | Sets the style of the border (`Solid`, `Dashed`). |
|
|
281
|
+
| `borderRadius` | `object \| number` | Sets the radius of the node's corners. |
|
|
282
|
+
| `opacity` | `number` | Sets the opacity of the node and its children (0-1). |
|
|
283
|
+
| `gradient` | `object` | Sets a linear or radial gradient as the background. |
|
|
284
|
+
| `boxShadow` | `BoxShadowProps \| BoxShadowProps[]` | Applies one or more box-shadow effects. |
|
|
285
|
+
| `transform` | `TransformProps` | Applies 2D transformations (translate, rotate, scale). |
|
|
286
|
+
|
|
287
|
+
#### Font & Text Props (Inheritable)
|
|
288
|
+
|
|
289
|
+
These props, when set on a `Box`, `Row`, or `Column`, are inherited by any descendant `Text` nodes.
|
|
290
|
+
|
|
291
|
+
| Prop | Type | Description |
|
|
292
|
+
|-----------------|------------------------------------------------------------------|--------------------------------------------|
|
|
293
|
+
| `fontSize` | `number` | Font size in pixels. |
|
|
294
|
+
| `fontFamily` | `string` | Font family name. |
|
|
295
|
+
| `fontWeight` | `string \| number` | Font weight ('normal', 'bold', 400, etc.). |
|
|
296
|
+
| `fontStyle` | `'normal' \| 'italic'` | Font style. |
|
|
297
|
+
| `color` | `string` | Text color. |
|
|
298
|
+
| `textAlign` | `'start' \| 'end' \| 'left' \| 'center' \| 'right' \| 'justify'` | Horizontal text alignment. |
|
|
299
|
+
| `verticalAlign` | `'top' \| 'middle' \| 'bottom'` | Vertical text alignment. |
|
|
300
|
+
| `lineHeight` | `number` | Line height in pixels. |
|
|
301
|
+
| `lineGap` | `number` | Additional vertical spacing between lines. |
|
|
302
|
+
| `letterSpacing` | `number \| string` | Spacing between letters. |
|
|
303
|
+
| `wordSpacing` | `number \| string` | Spacing between words. |
|
|
304
|
+
| `fontVariant` | `FontVariantSetting` | Specifies font variation settings. |
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
### Text
|
|
309
|
+
|
|
310
|
+
The `Text` component renders text content. It inherits all `BoxProps` except for `children`, `gap`, and flex container
|
|
311
|
+
properties.
|
|
312
|
+
|
|
313
|
+
#### Text-Specific Props
|
|
314
|
+
|
|
315
|
+
| Prop | Type | Description |
|
|
316
|
+
|--------------|----------------------------------------|----------------------------------------------------------------------------|
|
|
317
|
+
| `maxLines` | `number` | Maximum number of lines to display before truncating. |
|
|
318
|
+
| `ellipsis` | `boolean \| string` | If `true`, adds '...' when text is truncated. Can also be a custom string. |
|
|
319
|
+
| `textShadow` | `TextShadowProps \| TextShadowProps[]` | Applies one or more shadow effects to the text itself. |
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
### Image
|
|
324
|
+
|
|
325
|
+
The `Image` component renders an image. It inherits all `BoxProps` except for `children`.
|
|
326
|
+
|
|
327
|
+
#### Image-Specific Props
|
|
328
|
+
|
|
329
|
+
| Prop | Type | Description |
|
|
330
|
+
|------------------|------------------------------------------------------------|-----------------------------------------------------------------------|
|
|
331
|
+
| `src` | `string \| Buffer` | The source URL, file path, or buffer of the image. |
|
|
332
|
+
| `objectFit` | `'fill' \| 'contain' \| 'cover' \| 'none' \| 'scale-down'` | Specifies how the image should be resized to fit its container. |
|
|
333
|
+
| `objectPosition` | `object` | Specifies the alignment of the image within its box. |
|
|
334
|
+
| `saturate` | `number` | Adjusts the image's saturation level (0 is grayscale, 1 is original). |
|
|
335
|
+
| `dropShadow` | `DropShadowProps` | Applies a drop-shadow effect based on the image's alpha channel. |
|
|
336
|
+
| `alt` | `string` | Alternative text description (for accessibility). |
|
|
337
|
+
| `onLoad` | `() => void` | Callback function that executes when the image loads successfully. |
|
|
338
|
+
| `onError` | `(error: Error) => void` | Callback function that executes when the image fails to load. |
|
|
339
|
+
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
### Grid
|
|
343
|
+
|
|
344
|
+
The `Grid` component arranges its children in a grid layout. It is a specialized `RowNode` and inherits most `BoxProps`.
|
|
345
|
+
|
|
346
|
+
#### Grid-Specific Props
|
|
347
|
+
|
|
348
|
+
| Prop | Type | Description |
|
|
349
|
+
|-------------|----------------------------------------------------------|-----------------------------------------------------|
|
|
350
|
+
| `columns` | `number` | The number of columns in the grid. Default is 1. |
|
|
351
|
+
| `direction` | `'row' \| 'column' \| 'row-reverse' \| 'column-reverse'` | The direction of the grid layout. Default is 'row'. |
|
|
352
|
+
|
|
353
|
+
---
|
|
354
|
+
|
|
355
|
+
### Root
|
|
356
|
+
|
|
357
|
+
The `Root` component is the entry point for rendering. It is a specialized `ColumnNode`.
|
|
358
|
+
|
|
359
|
+
#### Root-Specific Props
|
|
360
|
+
|
|
361
|
+
| Prop | Type | Description |
|
|
362
|
+
|----------|--------------------------|--------------------------------------------------------------------------|
|
|
363
|
+
| `width` | `number` | **Required.** Width of the canvas in pixels. |
|
|
364
|
+
| `height` | `number` | Optional height of the canvas. If not set, it's calculated from content. |
|
|
365
|
+
| `scale` | `number` | Scale factor for rendering (e.g., 2 for 2x resolution). Default is 1. |
|
|
366
|
+
| `fonts` | `FontRegistrationInfo[]` | An array of font files to register for use in the canvas. |
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
## Contributing
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
|
|
373
|
+
Contributions are welcome! Please see the [Contributing Guidelines](CONTRIBUTING.md) for more details on how to get started.
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
## License
|
|
378
|
+
|
|
379
|
+
|
|
380
|
+
|
|
381
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
382
|
+
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { CanvasRenderingContext2D } from 'skia-canvas';
|
|
2
|
+
import * as YogaTypes from 'yoga-layout';
|
|
3
|
+
import type { BoxProps } from '../canvas/canvas.type.js';
|
|
4
|
+
export declare const drawBorders: ({ ctx, node, x, y, width, height, radii, borderColor, borderStyle, }: {
|
|
5
|
+
ctx: CanvasRenderingContext2D;
|
|
6
|
+
node: YogaTypes.Node;
|
|
7
|
+
x: number;
|
|
8
|
+
y: number;
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
radii: {
|
|
12
|
+
TopLeft: number;
|
|
13
|
+
TopRight: number;
|
|
14
|
+
BottomLeft: number;
|
|
15
|
+
BottomRight: number;
|
|
16
|
+
};
|
|
17
|
+
borderColor: BoxProps["borderColor"];
|
|
18
|
+
borderStyle: BoxProps["borderStyle"];
|
|
19
|
+
}) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Draws an optimized rounded rectangle path on the canvas context.
|
|
22
|
+
* Automatically clamps radius values to prevent visual artifacts based on box dimensions.
|
|
23
|
+
* Uses arc-based rendering for crisp corners and consistent border appearance.
|
|
24
|
+
*
|
|
25
|
+
* @param ctx - The canvas 2D rendering context to draw on
|
|
26
|
+
* @param x - Left position of the rectangle
|
|
27
|
+
* @param y - Top position of the rectangle
|
|
28
|
+
* @param width - Width of the rectangle
|
|
29
|
+
* @param height - Height of the rectangle
|
|
30
|
+
* @param radii - Corner radius values for each corner. Values are clamped to box constraints.
|
|
31
|
+
*/
|
|
32
|
+
export declare const drawRoundedRectPath: (ctx: CanvasRenderingContext2D, x: number, y: number, width: number, height: number, radii: {
|
|
33
|
+
TopLeft: number;
|
|
34
|
+
TopRight: number;
|
|
35
|
+
BottomRight: number;
|
|
36
|
+
BottomLeft: number;
|
|
37
|
+
}) => void;
|
|
38
|
+
/**
|
|
39
|
+
* Calculates border radius values from props
|
|
40
|
+
* @param radiusProp - Border radius property value
|
|
41
|
+
* @returns Calculated border radii for all corners
|
|
42
|
+
*/
|
|
43
|
+
export declare const parseBorderRadius: (radiusProp: BoxProps["borderRadius"]) => {
|
|
44
|
+
TopLeft: number;
|
|
45
|
+
TopRight: number;
|
|
46
|
+
BottomRight: number;
|
|
47
|
+
BottomLeft: number;
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Parses a percentage value or a number, returning the calculated value based on the base.
|
|
51
|
+
*
|
|
52
|
+
* @param value - The value to parse, can be a number, a percentage string, or undefined.
|
|
53
|
+
* @param base - The base value to calculate the percentage from.
|
|
54
|
+
* @returns The parsed number, or 0 if the value is not a number or a valid percentage.
|
|
55
|
+
*/
|
|
56
|
+
export declare function parsePercentage(value: number | string | undefined, base: number): number;
|
|
57
|
+
//# sourceMappingURL=canvas.helper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canvas.helper.d.ts","sourceRoot":"","sources":["../../../src/canvas/canvas.helper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAA;AAC3D,OAAO,KAAK,SAAS,MAAM,aAAa,CAAA;AAExC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAEvD,eAAO,MAAM,WAAW,GAAI,sEAUzB;IACD,GAAG,EAAE,wBAAwB,CAAA;IAC7B,IAAI,EAAE,SAAS,CAAC,IAAI,CAAA;IACpB,CAAC,EAAE,MAAM,CAAA;IACT,CAAC,EAAE,MAAM,CAAA;IACT,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE;QACL,OAAO,EAAE,MAAM,CAAA;QACf,QAAQ,EAAE,MAAM,CAAA;QAChB,UAAU,EAAE,MAAM,CAAA;QAClB,WAAW,EAAE,MAAM,CAAA;KACpB,CAAA;IACD,WAAW,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAA;IACpC,WAAW,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAA;CACrC,SAkJA,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB,GAC9B,KAAK,wBAAwB,EAC7B,GAAG,MAAM,EACT,GAAG,MAAM,EACT,OAAO,MAAM,EACb,QAAQ,MAAM,EACd,OAAO;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,SAwCtF,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAC5B,YAAY,QAAQ,CAAC,cAAc,CAAC,KACnC;IACD,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;CAYnB,CAAA;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAQxF"}
|