@meonode/canvas 1.2.0 → 1.3.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.
- package/README.md +320 -225
- package/dist/cjs/canvas/canvas.type.d.ts +38 -7
- package/dist/cjs/canvas/canvas.type.d.ts.map +1 -1
- package/dist/cjs/canvas/grid.canvas.util.d.ts +25 -18
- package/dist/cjs/canvas/grid.canvas.util.d.ts.map +1 -1
- package/dist/cjs/canvas/grid.canvas.util.js +298 -210
- package/dist/cjs/canvas/grid.canvas.util.js.map +1 -1
- package/dist/cjs/canvas/text.canvas.util.d.ts.map +1 -1
- package/dist/cjs/canvas/text.canvas.util.js +84 -51
- package/dist/cjs/canvas/text.canvas.util.js.map +1 -1
- package/dist/esm/canvas/canvas.type.d.ts +38 -7
- package/dist/esm/canvas/canvas.type.d.ts.map +1 -1
- package/dist/esm/canvas/grid.canvas.util.d.ts +25 -18
- package/dist/esm/canvas/grid.canvas.util.d.ts.map +1 -1
- package/dist/esm/canvas/grid.canvas.util.js +298 -210
- package/dist/esm/canvas/text.canvas.util.d.ts.map +1 -1
- package/dist/esm/canvas/text.canvas.util.js +84 -51
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# @meonode/canvas
|
|
2
2
|
|
|
3
|
-
A declarative, component-based library for server-side canvas image generation. Write complex visuals with simple
|
|
3
|
+
A declarative, component-based library for server-side canvas image generation. Write complex visuals with simple
|
|
4
|
+
functions, similar to the composition style of @meonode/ui.
|
|
4
5
|
It uses `skia-canvas` for drawing and `yoga-layout` for flexbox-based layouts.
|
|
5
6
|
|
|
6
7
|
This library allows you to build complex image layouts using a familiar component-based approach. You can define your
|
|
@@ -23,15 +24,16 @@ rendering to a canvas.
|
|
|
23
24
|
|
|
24
25
|
<table>
|
|
25
26
|
<tr>
|
|
26
|
-
<td><img src="https://i.ibb.co/VpPZybzF/profile-card.webp" alt="Image 1"></td>
|
|
27
|
-
<td><img src="https://i.ibb.co/zTgrBWpT/profile-card-1.webp" alt="Image 2"></td>
|
|
27
|
+
<td width="50%"><img src="https://i.ibb.co/VpPZybzF/profile-card.webp" alt="Image 1"></td>
|
|
28
|
+
<td width="50%"><img src="https://i.ibb.co/zTgrBWpT/profile-card-1.webp" alt="Image 2"></td>
|
|
28
29
|
</tr>
|
|
29
30
|
<tr>
|
|
30
|
-
<td><img src="https://i.ibb.co/F4xfHdBp/daily-notes.webp" alt="Image 3"></td>
|
|
31
|
-
<td><img src="https://i.ibb.co/Jj0x6khB/character-archive-base.webp" alt="Image 4"></td>
|
|
31
|
+
<td width="50%"><img src="https://i.ibb.co/F4xfHdBp/daily-notes.webp" alt="Image 3"></td>
|
|
32
|
+
<td width="50%"><img src="https://i.ibb.co/Jj0x6khB/character-archive-base.webp" alt="Image 4"></td>
|
|
32
33
|
</tr>
|
|
33
34
|
<tr>
|
|
34
|
-
<td
|
|
35
|
+
<td width="50%"><img src="https://i.ibb.co.com/B24SZ0C9/charts.webp" alt="Image 5"/></td>
|
|
36
|
+
<td width="50%"><img src="https://i.ibb.co.com/q3sy9r2L/sample-grids.png" alt="Image 6"/></td>
|
|
35
37
|
</tr>
|
|
36
38
|
</table>
|
|
37
39
|
|
|
@@ -50,41 +52,41 @@ import {Root, Box, Text} from '@meonode/canvas';
|
|
|
50
52
|
import {writeFile} from 'fs/promises';
|
|
51
53
|
|
|
52
54
|
async function generateImage() {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
children: [
|
|
63
|
-
Box({
|
|
64
|
-
width: '100%',
|
|
65
|
-
height: '100%',
|
|
66
|
-
backgroundColor: '#f0f0f0',
|
|
67
|
-
padding: 20,
|
|
55
|
+
const canvas = await Root({
|
|
56
|
+
width: 500,
|
|
57
|
+
height: 300,
|
|
58
|
+
fonts: [
|
|
59
|
+
{
|
|
60
|
+
family: 'Roboto',
|
|
61
|
+
paths: ['./fonts/Roboto-Regular.ttf', './fonts/Roboto-Bold.ttf'],
|
|
62
|
+
},
|
|
63
|
+
],
|
|
68
64
|
children: [
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
65
|
+
Box({
|
|
66
|
+
width: '100%',
|
|
67
|
+
height: '100%',
|
|
68
|
+
backgroundColor: '#f0f0f0',
|
|
69
|
+
padding: 20,
|
|
70
|
+
children: [
|
|
71
|
+
Text('Hello, World!', {
|
|
72
|
+
fontSize: 32,
|
|
73
|
+
fontWeight: 'bold',
|
|
74
|
+
fontFamily: 'Roboto',
|
|
75
|
+
color: '#333',
|
|
76
|
+
}),
|
|
77
|
+
Text('This is a basic example of using @meonode/canvas.', {
|
|
78
|
+
fontSize: 18,
|
|
79
|
+
fontFamily: 'Roboto',
|
|
80
|
+
color: '#666',
|
|
81
|
+
margin: {Top: 10},
|
|
82
|
+
}),
|
|
83
|
+
],
|
|
84
|
+
}),
|
|
81
85
|
],
|
|
82
|
-
|
|
83
|
-
],
|
|
84
|
-
});
|
|
86
|
+
});
|
|
85
87
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
+
const buffer = await canvas.toBuffer('png');
|
|
89
|
+
await writeFile('output.png', buffer);
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
generateImage().catch(console.error);
|
|
@@ -100,109 +102,109 @@ import {Root, Column, Row, Text, Image, Style} from '@meonode/canvas';
|
|
|
100
102
|
import {writeFile} from 'fs/promises';
|
|
101
103
|
|
|
102
104
|
async function generateComplexImage() {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
children: [
|
|
117
|
-
Column({
|
|
118
|
-
width: '100%',
|
|
119
|
-
height: '100%',
|
|
120
|
-
backgroundColor: '#f0f0f0',
|
|
121
|
-
padding: 20,
|
|
122
|
-
justifyContent: Style.Justify.SpaceBetween,
|
|
105
|
+
const canvas = await Root({
|
|
106
|
+
width: 800,
|
|
107
|
+
height: 600,
|
|
108
|
+
fonts: [
|
|
109
|
+
{
|
|
110
|
+
family: 'Roboto',
|
|
111
|
+
paths: ['./fonts/Roboto-Regular.ttf', './fonts/Roboto-Bold.ttf'],
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
family: 'Open Sans',
|
|
115
|
+
paths: ['./fonts/OpenSans-Regular.ttf'],
|
|
116
|
+
},
|
|
117
|
+
],
|
|
123
118
|
children: [
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
119
|
+
Column({
|
|
120
|
+
width: '100%',
|
|
121
|
+
height: '100%',
|
|
122
|
+
backgroundColor: '#f0f0f0',
|
|
123
|
+
padding: 20,
|
|
124
|
+
justifyContent: Style.Justify.SpaceBetween,
|
|
125
|
+
children: [
|
|
126
|
+
// Header Section
|
|
127
|
+
Row({
|
|
128
|
+
width: '100%',
|
|
129
|
+
alignItems: Style.Align.Center,
|
|
130
|
+
marginBottom: 20,
|
|
131
|
+
children: [
|
|
132
|
+
Image({
|
|
133
|
+
src: 'https://via.placeholder.com/80x80/FF0000/FFFFFF?text=Logo',
|
|
134
|
+
width: 80,
|
|
135
|
+
height: 80,
|
|
136
|
+
borderRadius: 40,
|
|
137
|
+
marginRight: 20,
|
|
138
|
+
objectFit: 'cover',
|
|
139
|
+
}),
|
|
140
|
+
Text('Welcome to MeoNode Canvas!', {
|
|
141
|
+
fontSize: 40,
|
|
142
|
+
fontWeight: 'bold',
|
|
143
|
+
fontFamily: 'Roboto',
|
|
144
|
+
color: '#333',
|
|
145
|
+
}),
|
|
146
|
+
],
|
|
147
|
+
}),
|
|
148
|
+
|
|
149
|
+
// Main Content Section
|
|
150
|
+
Column({
|
|
151
|
+
flexGrow: 1,
|
|
152
|
+
width: '100%',
|
|
153
|
+
backgroundColor: '#ffffff',
|
|
154
|
+
borderRadius: 10,
|
|
155
|
+
padding: 30,
|
|
156
|
+
boxShadow: {blur: 10, color: 'rgba(0,0,0,0.1)'},
|
|
157
|
+
children: [
|
|
158
|
+
Text('A New Way to Render Graphics', {
|
|
159
|
+
fontSize: 28,
|
|
160
|
+
fontWeight: 'bold',
|
|
161
|
+
fontFamily: 'Open Sans',
|
|
162
|
+
color: '#555',
|
|
163
|
+
marginBottom: 15,
|
|
164
|
+
}),
|
|
165
|
+
Text(
|
|
166
|
+
`This example demonstrates a more complex layout using various components.
|
|
165
167
|
We have a header with a logo and title, a main content area with text,
|
|
166
168
|
and a footer. Notice how flexbox properties are used to arrange elements.`,
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
169
|
+
{
|
|
170
|
+
fontSize: 18,
|
|
171
|
+
fontFamily: 'Open Sans',
|
|
172
|
+
color: '#777',
|
|
173
|
+
lineHeight: 24,
|
|
174
|
+
},
|
|
175
|
+
),
|
|
176
|
+
Image({
|
|
177
|
+
src: 'https://via.placeholder.com/600x200/007bff/ffffff?text=Feature+Image',
|
|
178
|
+
width: '100%',
|
|
179
|
+
height: 200,
|
|
180
|
+
marginTop: 20,
|
|
181
|
+
borderRadius: 8,
|
|
182
|
+
objectFit: 'contain',
|
|
183
|
+
objectPosition: {Top: '50%', Left: '50%'},
|
|
184
|
+
}),
|
|
185
|
+
],
|
|
186
|
+
}),
|
|
187
|
+
|
|
188
|
+
// Footer Section
|
|
189
|
+
Row({
|
|
190
|
+
width: '100%',
|
|
191
|
+
marginTop: 20,
|
|
192
|
+
justifyContent: Style.Justify.Center,
|
|
193
|
+
children: [
|
|
194
|
+
Text('© 2025 MeoNode Canvas. All rights reserved.', {
|
|
195
|
+
fontSize: 14,
|
|
196
|
+
fontFamily: 'Open Sans',
|
|
197
|
+
color: '#999',
|
|
198
|
+
}),
|
|
199
|
+
],
|
|
200
|
+
}),
|
|
201
|
+
],
|
|
202
|
+
}),
|
|
199
203
|
],
|
|
200
|
-
|
|
201
|
-
],
|
|
202
|
-
});
|
|
204
|
+
});
|
|
203
205
|
|
|
204
|
-
|
|
205
|
-
|
|
206
|
+
const buffer = await canvas.toBuffer('png');
|
|
207
|
+
await writeFile('complex_output.png', buffer);
|
|
206
208
|
}
|
|
207
209
|
|
|
208
210
|
generateComplexImage().catch(console.error);
|
|
@@ -219,39 +221,39 @@ import {Root, Chart} from '@meonode/canvas';
|
|
|
219
221
|
import {writeFile} from 'fs/promises';
|
|
220
222
|
|
|
221
223
|
async function generateBarChart() {
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
224
|
+
const canvas = await Root({
|
|
225
|
+
width: 600,
|
|
226
|
+
height: 400,
|
|
227
|
+
children: [
|
|
228
|
+
Chart({
|
|
229
|
+
type: 'bar',
|
|
230
|
+
width: '100%',
|
|
231
|
+
height: '100%',
|
|
232
|
+
data: {
|
|
233
|
+
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May'],
|
|
234
|
+
datasets: [
|
|
235
|
+
{
|
|
236
|
+
label: 'Sales',
|
|
237
|
+
data: [120, 150, 180, 90, 200],
|
|
238
|
+
color: '#36A2EB',
|
|
239
|
+
},
|
|
240
|
+
],
|
|
241
|
+
},
|
|
242
|
+
options: {
|
|
243
|
+
gridOptions: {show: true, style: 'dashed'},
|
|
244
|
+
axisColor: '#333',
|
|
245
|
+
labelColor: '#333',
|
|
246
|
+
showValues: true,
|
|
247
|
+
valueFontSize: 12,
|
|
248
|
+
showYAxis: true,
|
|
249
|
+
yAxisColor: '#666',
|
|
250
|
+
},
|
|
251
|
+
}),
|
|
252
|
+
],
|
|
253
|
+
});
|
|
252
254
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
+
const buffer = await canvas.toBuffer('png');
|
|
256
|
+
await writeFile('bar_chart.png', buffer);
|
|
255
257
|
}
|
|
256
258
|
|
|
257
259
|
generateBarChart().catch(console.error);
|
|
@@ -264,42 +266,128 @@ import {Root, Chart, Row, Box, Text} from '@meonode/canvas';
|
|
|
264
266
|
import {writeFile} from 'fs/promises';
|
|
265
267
|
|
|
266
268
|
async function generateDoughnutChart() {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
269
|
+
const canvas = await Root({
|
|
270
|
+
width: 600,
|
|
271
|
+
height: 400,
|
|
272
|
+
children: [
|
|
273
|
+
Chart({
|
|
274
|
+
type: 'doughnut',
|
|
275
|
+
width: '100%',
|
|
276
|
+
height: '100%',
|
|
277
|
+
data: [
|
|
278
|
+
{label: 'Red', value: 300, color: '#FF6384'},
|
|
279
|
+
{label: 'Blue', value: 50, color: '#36A2EB'},
|
|
280
|
+
{label: 'Yellow', value: 100, color: '#FFCE56'},
|
|
281
|
+
],
|
|
282
|
+
options: {
|
|
283
|
+
innerRadius: 0.7,
|
|
284
|
+
sliceBorderRadius: 5,
|
|
285
|
+
renderLegendItem: ({item, color}) =>
|
|
286
|
+
Row({
|
|
287
|
+
alignItems: 'center',
|
|
288
|
+
children: [
|
|
289
|
+
Box({width: 12, height: 12, backgroundColor: color, borderRadius: 6}),
|
|
290
|
+
Text(`${item.label}: ${item.value}`, {fontSize: 16, marginLeft: 8}),
|
|
291
|
+
],
|
|
292
|
+
}),
|
|
293
|
+
},
|
|
290
294
|
}),
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
],
|
|
294
|
-
});
|
|
295
|
+
],
|
|
296
|
+
});
|
|
295
297
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
+
const buffer = await canvas.toBuffer('png');
|
|
299
|
+
await writeFile('doughnut_chart.png', buffer);
|
|
298
300
|
}
|
|
299
301
|
|
|
300
302
|
generateDoughnutChart().catch(console.error);
|
|
301
303
|
```
|
|
302
304
|
|
|
305
|
+
## Grid Layout Examples
|
|
306
|
+
|
|
307
|
+
The `Grid` component simplifies creating complex layouts. It mimics CSS Grid Layout.
|
|
308
|
+
|
|
309
|
+
### Basic Grid
|
|
310
|
+
|
|
311
|
+
A simple grid with 3 columns, each 100 pixels wide.
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
import {Root, Grid, Box, Text} from '@meonode/canvas';
|
|
315
|
+
import {writeFile} from 'fs/promises';
|
|
316
|
+
|
|
317
|
+
async function generateBasicGrid() {
|
|
318
|
+
const canvas = await Root({
|
|
319
|
+
width: 400,
|
|
320
|
+
height: 300,
|
|
321
|
+
children: [
|
|
322
|
+
Grid({
|
|
323
|
+
columns: 3,
|
|
324
|
+
templateColumns: [100, 100, 100], // or ['100px', '100px', '100px']
|
|
325
|
+
gap: 10,
|
|
326
|
+
children: [
|
|
327
|
+
Box({backgroundColor: 'red', height: 50, children: [Text('1')]}),
|
|
328
|
+
Box({backgroundColor: 'blue', height: 50, children: [Text('2')]}),
|
|
329
|
+
Box({backgroundColor: 'green', height: 50, children: [Text('3')]}),
|
|
330
|
+
Box({backgroundColor: 'yellow', height: 50, children: [Text('4')]}),
|
|
331
|
+
],
|
|
332
|
+
}),
|
|
333
|
+
],
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
await canvas.toFile('grid_basic.png');
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
generateBasicGrid();
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### Responsive Grid (Fractional Units)
|
|
343
|
+
|
|
344
|
+
Using fractional units (`fr`) allows columns to take up proportional space.
|
|
345
|
+
|
|
346
|
+
```typescript
|
|
347
|
+
Grid({
|
|
348
|
+
// First column takes 1 part, second takes 2 parts, third takes 1 part
|
|
349
|
+
templateColumns: ['1fr', '2fr', '1fr'],
|
|
350
|
+
gap: 10,
|
|
351
|
+
children: [
|
|
352
|
+
Box({backgroundColor: 'red', height: 50, children: [Text('1fr')]}),
|
|
353
|
+
Box({backgroundColor: 'blue', height: 50, children: [Text('2fr')]}),
|
|
354
|
+
Box({backgroundColor: 'green', height: 50, children: [Text('1fr')]}),
|
|
355
|
+
],
|
|
356
|
+
});
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### Spanning Items
|
|
360
|
+
|
|
361
|
+
Use `GridItem` (or just passing `gridColumn`/`gridRow` props to any child) to span multiple columns or rows.
|
|
362
|
+
|
|
363
|
+
```typescript
|
|
364
|
+
import {Grid, GridItem, Box, Text} from '@meonode/canvas';
|
|
365
|
+
|
|
366
|
+
Grid({
|
|
367
|
+
templateColumns: ['1fr', '1fr', '1fr'],
|
|
368
|
+
gap: 10,
|
|
369
|
+
children: [
|
|
370
|
+
// Spans all 3 columns
|
|
371
|
+
GridItem({
|
|
372
|
+
gridColumn: 'span 3',
|
|
373
|
+
height: 50,
|
|
374
|
+
backgroundColor: '#333',
|
|
375
|
+
children: [Text('Header', {color: 'white'})],
|
|
376
|
+
}),
|
|
377
|
+
// Standard items
|
|
378
|
+
Box({backgroundColor: '#eee', height: 100, children: [Text('Content')]}),
|
|
379
|
+
Box({backgroundColor: '#ccc', height: 100, children: [Text('Sidebar')]}),
|
|
380
|
+
// Spans 2 columns
|
|
381
|
+
GridItem({
|
|
382
|
+
gridColumn: 'span 2',
|
|
383
|
+
height: 50,
|
|
384
|
+
backgroundColor: '#555',
|
|
385
|
+
children: [Text('Footer', {color: 'white'})],
|
|
386
|
+
}),
|
|
387
|
+
],
|
|
388
|
+
});
|
|
389
|
+
```
|
|
390
|
+
|
|
303
391
|
## Using Yoga Layout Properties
|
|
304
392
|
|
|
305
393
|
This library leverages `yoga-layout` for its powerful flexbox engine. Many layout properties directly map to Yoga's
|
|
@@ -311,19 +399,19 @@ For example, to set `flexDirection` to `row` or `positionType` to `absolute`, yo
|
|
|
311
399
|
import {Box, Style} from '@meonode/canvas';
|
|
312
400
|
|
|
313
401
|
Box({
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
402
|
+
flexDirection: Style.FlexDirection.Row,
|
|
403
|
+
justifyContent: Style.Justify.Center,
|
|
404
|
+
alignItems: Style.Align.Center,
|
|
405
|
+
children: [
|
|
406
|
+
Box({
|
|
407
|
+
width: 100,
|
|
408
|
+
height: 100,
|
|
409
|
+
backgroundColor: 'red',
|
|
410
|
+
positionType: Style.PositionType.Absolute,
|
|
411
|
+
position: {Top: 10, Left: 10},
|
|
412
|
+
}),
|
|
413
|
+
// ... other children
|
|
414
|
+
],
|
|
327
415
|
});
|
|
328
416
|
```
|
|
329
417
|
|
|
@@ -442,10 +530,17 @@ The `Grid` component arranges its children in a grid layout. It is a specialized
|
|
|
442
530
|
|
|
443
531
|
#### Grid-Specific Props
|
|
444
532
|
|
|
445
|
-
| Prop
|
|
446
|
-
|
|
447
|
-
| `columns`
|
|
448
|
-
| `
|
|
533
|
+
| Prop | Type | Description |
|
|
534
|
+
|-------------------|----------------------------------------------------------|---------------------------------------------------------|
|
|
535
|
+
| `columns` | `number` | The number of columns in the grid. Default is 1. |
|
|
536
|
+
| `templateColumns` | `GridTrackSize[]` | Defines the columns of the grid (e.g., `[100, '1fr']`). |
|
|
537
|
+
| `templateRows` | `GridTrackSize[]` | Defines the rows of the grid. |
|
|
538
|
+
| `autoRows` | `GridTrackSize` | Specifies the size of implicitly created rows. |
|
|
539
|
+
| `autoFlow` | `'row' \| 'column' \| 'row-dense' \| 'column-dense'` | Controls how the auto-placement algorithm works. |
|
|
540
|
+
| `gap` | `number \| string` | Defines the gap between grid items. |
|
|
541
|
+
| `rowGap` | `number \| string` | Defines the row gap. |
|
|
542
|
+
| `columnGap` | `number \| string` | Defines the column gap. |
|
|
543
|
+
| `direction` | `'row' \| 'column' \| 'row-reverse' \| 'column-reverse'` | The direction of the grid layout. Default is 'row'. |
|
|
449
544
|
|
|
450
545
|
---
|
|
451
546
|
|
|
@@ -479,17 +574,17 @@ The `options` prop is a conditional type that changes based on the chart `type`.
|
|
|
479
574
|
|
|
480
575
|
##### Cartesian Chart Options (`bar`, `line`)
|
|
481
576
|
|
|
482
|
-
| Prop
|
|
483
|
-
|
|
484
|
-
| `gridOptions`
|
|
485
|
-
| `axisColor`
|
|
486
|
-
| `showValues`
|
|
487
|
-
| `valueColor`
|
|
488
|
-
| `valueFontSize
|
|
489
|
-
| `showYAxis`
|
|
490
|
-
| `yAxisColor`
|
|
491
|
-
| `yAxisFontSize
|
|
492
|
-
| `yAxisLabelFormatter` | `(value: number) => string` | Custom formatter for Y-axis labels.
|
|
577
|
+
| Prop | Type | Description |
|
|
578
|
+
|-----------------------|-----------------------------|-------------------------------------------------------------------|
|
|
579
|
+
| `gridOptions` | `GridOptions` | An object to configure the grid lines (`show`, `color`, `style`). |
|
|
580
|
+
| `axisColor` | `string` | The color of the chart axes. |
|
|
581
|
+
| `showValues` | `boolean` | If `true`, displays values on top of bars or points. |
|
|
582
|
+
| `valueColor` | `string` | Color of the value labels. |
|
|
583
|
+
| `valueFontSize` | `number` | Font size of the value labels. |
|
|
584
|
+
| `showYAxis` | `boolean` | If `true`, displays the Y-axis labels on the left. |
|
|
585
|
+
| `yAxisColor` | `string` | Color of the Y-axis labels. |
|
|
586
|
+
| `yAxisFontSize` | `number` | Font size of the Y-axis labels. |
|
|
587
|
+
| `yAxisLabelFormatter` | `(value: number) => string` | Custom formatter for Y-axis labels. |
|
|
493
588
|
|
|
494
589
|
##### Pie & Doughnut Chart Options (`pie`, `doughnut`)
|
|
495
590
|
|