abstract-image 13.3.6 → 14.0.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.
@@ -1,54 +1,59 @@
1
1
  import type { Schema } from "jsxpression";
2
2
 
3
- export const baseSchema = {
3
+ export const baseSchema: Schema = {
4
4
  elements: {
5
5
  AbstractImage: {
6
6
  description: "Root container — defines the image canvas and its coordinate system.",
7
7
  props: {
8
- width: {
9
- type: "number",
10
- required: true,
11
- description: "Total width of the image canvas (in px).",
12
- },
13
- height: {
14
- type: "number",
15
- required: true,
16
- description: "Total height of the image canvas (in px).",
17
- },
8
+ type: "object",
9
+ properties: {
10
+ width: {
11
+ type: "number",
12
+ description: "Total width of the image canvas (in px).",
13
+ },
14
+ height: {
15
+ type: "number",
16
+ description: "Total height of the image canvas (in px).",
17
+ },
18
+ },
19
+ required: ["width", "height"],
18
20
  },
19
21
  allowedChildren: ["Image", "Text", "Rectangle", "Ellipse", "Line", "Polyline", "Polygon", "Group"],
20
22
  },
21
23
 
22
24
  Group: {
23
25
  description: "Groups elements together.",
24
- props: {},
26
+ props: { type: "object", properties: {} },
25
27
  allowedChildren: ["Image", "Text", "Rectangle", "Ellipse", "Line", "Polyline", "Polygon", "Group"],
26
28
  },
27
29
 
28
30
  Image: {
29
31
  description: "Displays a raster image.",
30
32
  props: {
31
- src: {
32
- type: "string",
33
- required: true,
34
- description: "Source of the image (URL or asset ID).",
35
- },
36
- x: {
37
- type: "number",
38
- description: "X position in pixels.",
39
- },
40
- y: {
41
- type: "number",
42
- description: "Y position in pixels.",
43
- },
44
- width: {
45
- type: "number",
46
- description: "Display width in pixels.",
47
- },
48
- height: {
49
- type: "number",
50
- description: "Display height in pixels.",
51
- },
33
+ type: "object",
34
+ properties: {
35
+ src: {
36
+ type: "string",
37
+ description: "Source of the image (URL or asset ID).",
38
+ },
39
+ x: {
40
+ type: "number",
41
+ description: "X position in pixels.",
42
+ },
43
+ y: {
44
+ type: "number",
45
+ description: "Y position in pixels.",
46
+ },
47
+ width: {
48
+ type: "number",
49
+ description: "Display width in pixels.",
50
+ },
51
+ height: {
52
+ type: "number",
53
+ description: "Display height in pixels.",
54
+ },
55
+ },
56
+ required: ["src"],
52
57
  },
53
58
  allowedChildren: [],
54
59
  },
@@ -56,35 +61,38 @@ export const baseSchema = {
56
61
  Ellipse: {
57
62
  description: "Draws an ellipse using x, y, width, and height.",
58
63
  props: {
59
- x: {
60
- type: "number",
61
- description: "X coordinate of the top-left of the ellipse box.",
62
- },
63
- y: {
64
- type: "number",
65
- description: "Y coordinate of the top-left of the ellipse box.",
66
- },
67
- width: {
68
- type: "number",
69
- description: "Box width.",
70
- },
71
- height: {
72
- type: "number",
73
- description: "Box height.",
74
- },
75
- stroke: {
76
- type: "string",
77
- format: "color",
78
- description: "Stroke color (CSS color string).",
79
- },
80
- strokeWidth: {
81
- type: "number",
82
- description: "Stroke width in pixels.",
83
- },
84
- fill: {
85
- type: "string",
86
- format: "color",
87
- description: "Fill color (inside the ellipse).",
64
+ type: "object",
65
+ properties: {
66
+ x: {
67
+ type: "number",
68
+ description: "X coordinate of the top-left of the ellipse box.",
69
+ },
70
+ y: {
71
+ type: "number",
72
+ description: "Y coordinate of the top-left of the ellipse box.",
73
+ },
74
+ width: {
75
+ type: "number",
76
+ description: "Box width.",
77
+ },
78
+ height: {
79
+ type: "number",
80
+ description: "Box height.",
81
+ },
82
+ stroke: {
83
+ type: "string",
84
+ format: "color",
85
+ description: "Stroke color (CSS color string).",
86
+ },
87
+ strokeWidth: {
88
+ type: "number",
89
+ description: "Stroke width in pixels.",
90
+ },
91
+ fill: {
92
+ type: "string",
93
+ format: "color",
94
+ description: "Fill color (inside the ellipse).",
95
+ },
88
96
  },
89
97
  },
90
98
  allowedChildren: [],
@@ -93,30 +101,33 @@ export const baseSchema = {
93
101
  Line: {
94
102
  description: "Draws a straight line between two points.",
95
103
  props: {
96
- x1: {
97
- type: "number",
98
- description: "X coordinate of the start point.",
99
- },
100
- y1: {
101
- type: "number",
102
- description: "Y coordinate of the start point.",
103
- },
104
- x2: {
105
- type: "number",
106
- description: "X coordinate of the end point.",
107
- },
108
- y2: {
109
- type: "number",
110
- description: "Y coordinate of the end point.",
111
- },
112
- stroke: {
113
- type: "string",
114
- format: "color",
115
- description: "Stroke color of the line.",
116
- },
117
- strokeWidth: {
118
- type: "number",
119
- description: "Width of the stroke in px.",
104
+ type: "object",
105
+ properties: {
106
+ x1: {
107
+ type: "number",
108
+ description: "X coordinate of the start point.",
109
+ },
110
+ y1: {
111
+ type: "number",
112
+ description: "Y coordinate of the start point.",
113
+ },
114
+ x2: {
115
+ type: "number",
116
+ description: "X coordinate of the end point.",
117
+ },
118
+ y2: {
119
+ type: "number",
120
+ description: "Y coordinate of the end point.",
121
+ },
122
+ stroke: {
123
+ type: "string",
124
+ format: "color",
125
+ description: "Stroke color of the line.",
126
+ },
127
+ strokeWidth: {
128
+ type: "number",
129
+ description: "Width of the stroke in px.",
130
+ },
120
131
  },
121
132
  },
122
133
  allowedChildren: [],
@@ -125,20 +136,23 @@ export const baseSchema = {
125
136
  Polyline: {
126
137
  description: "A connected set of line segments (open shape).",
127
138
  props: {
128
- points: {
129
- type: "string",
130
- required: true,
131
- description: "List of points: 'x0,y0 x1,y1 x2,y2'.",
132
- },
133
- stroke: {
134
- type: "string",
135
- format: "color",
136
- description: "Stroke color.",
137
- },
138
- strokeWidth: {
139
- type: "number",
140
- description: "Stroke width in px.",
141
- },
139
+ type: "object",
140
+ properties: {
141
+ points: {
142
+ type: "string",
143
+ description: "List of points: 'x0,y0 x1,y1 x2,y2'.",
144
+ },
145
+ stroke: {
146
+ type: "string",
147
+ format: "color",
148
+ description: "Stroke color.",
149
+ },
150
+ strokeWidth: {
151
+ type: "number",
152
+ description: "Stroke width in px.",
153
+ },
154
+ },
155
+ required: ["points"],
142
156
  },
143
157
  allowedChildren: [],
144
158
  },
@@ -146,25 +160,28 @@ export const baseSchema = {
146
160
  Polygon: {
147
161
  description: "A closed polygon shape.",
148
162
  props: {
149
- points: {
150
- type: "string",
151
- required: true,
152
- description: "List of vertex points: 'x0,y0 x1,y1 ...'.",
153
- },
154
- stroke: {
155
- type: "string",
156
- format: "color",
157
- description: "Stroke color.",
158
- },
159
- strokeWidth: {
160
- type: "number",
161
- description: "Stroke width in px.",
162
- },
163
- fill: {
164
- type: "string",
165
- format: "color",
166
- description: "Fill color of the polygon.",
167
- },
163
+ type: "object",
164
+ properties: {
165
+ points: {
166
+ type: "string",
167
+ description: "List of vertex points: 'x0,y0 x1,y1 ...'.",
168
+ },
169
+ stroke: {
170
+ type: "string",
171
+ format: "color",
172
+ description: "Stroke color.",
173
+ },
174
+ strokeWidth: {
175
+ type: "number",
176
+ description: "Stroke width in px.",
177
+ },
178
+ fill: {
179
+ type: "string",
180
+ format: "color",
181
+ description: "Fill color of the polygon.",
182
+ },
183
+ },
184
+ required: ["points"],
168
185
  },
169
186
  allowedChildren: [],
170
187
  },
@@ -172,39 +189,42 @@ export const baseSchema = {
172
189
  Rectangle: {
173
190
  description: "Draws a rectangle, optionally with rounded corners.",
174
191
  props: {
175
- x: {
176
- type: "number",
177
- description: "X position of the rectangle (top-left).",
178
- },
179
- y: {
180
- type: "number",
181
- description: "Y position of the rectangle (top-left).",
182
- },
183
- width: {
184
- type: "number",
185
- description: "Rectangle width in px.",
186
- },
187
- height: {
188
- type: "number",
189
- description: "Rectangle height in px.",
190
- },
191
- stroke: {
192
- type: "string",
193
- format: "color",
194
- description: "Stroke color.",
195
- },
196
- strokeWidth: {
197
- type: "number",
198
- description: "Stroke width in px.",
199
- },
200
- fill: {
201
- type: "string",
202
- format: "color",
203
- description: "Fill color of the rectangle.",
204
- },
205
- radius: {
206
- type: "number",
207
- description: "Corner radius in px (uniform).",
192
+ type: "object",
193
+ properties: {
194
+ x: {
195
+ type: "number",
196
+ description: "X position of the rectangle (top-left).",
197
+ },
198
+ y: {
199
+ type: "number",
200
+ description: "Y position of the rectangle (top-left).",
201
+ },
202
+ width: {
203
+ type: "number",
204
+ description: "Rectangle width in px.",
205
+ },
206
+ height: {
207
+ type: "number",
208
+ description: "Rectangle height in px.",
209
+ },
210
+ stroke: {
211
+ type: "string",
212
+ format: "color",
213
+ description: "Stroke color.",
214
+ },
215
+ strokeWidth: {
216
+ type: "number",
217
+ description: "Stroke width in px.",
218
+ },
219
+ fill: {
220
+ type: "string",
221
+ format: "color",
222
+ description: "Fill color of the rectangle.",
223
+ },
224
+ radius: {
225
+ type: "number",
226
+ description: "Corner radius in px (uniform).",
227
+ },
208
228
  },
209
229
  },
210
230
  allowedChildren: [],
@@ -213,32 +233,35 @@ export const baseSchema = {
213
233
  Text: {
214
234
  description: "Renders a text element.",
215
235
  props: {
216
- x: {
217
- type: "number",
218
- description: "X position of the text anchor.",
219
- },
220
- y: {
221
- type: "number",
222
- description: "Y position of the text baseline.",
223
- },
224
- fontFamily: {
225
- type: "string",
226
- description: "Font family, e.g. 'Inter, system-ui'.",
227
- },
228
- fontSize: {
229
- type: "number",
230
- description: "Font size in pixels.",
231
- },
232
- fontWeight: {
233
- type: "string",
234
- description: "Font weight, e.g. 'bold', '700'.",
235
- },
236
- fill: {
237
- type: "string",
238
- format: "color",
239
- description: "Fill color (text color).",
236
+ type: "object",
237
+ properties: {
238
+ x: {
239
+ type: "number",
240
+ description: "X position of the text anchor.",
241
+ },
242
+ y: {
243
+ type: "number",
244
+ description: "Y position of the text baseline.",
245
+ },
246
+ fontFamily: {
247
+ type: "string",
248
+ description: "Font family, e.g. 'Inter, system-ui'.",
249
+ },
250
+ fontSize: {
251
+ type: "number",
252
+ description: "Font size in pixels.",
253
+ },
254
+ fontWeight: {
255
+ type: "string",
256
+ description: "Font weight, e.g. 'bold', '700'.",
257
+ },
258
+ fill: {
259
+ type: "string",
260
+ format: "color",
261
+ description: "Fill color (text color).",
262
+ },
240
263
  },
241
264
  },
242
265
  },
243
266
  },
244
- } as const satisfies Schema;
267
+ };
@@ -1,64 +1,22 @@
1
- import type { PropertySchema } from "jsxpression";
1
+ import type { Schema } from "jsxpression";
2
2
 
3
- export function generateDataSchema(data: Record<string, unknown>): Record<string, PropertySchema> {
4
- const schema: Record<string, PropertySchema> = {};
3
+ type DataSchema = NonNullable<Schema["data"]>;
5
4
 
6
- for (const [key, value] of Object.entries(data)) {
7
- schema[key] = inferPropertySchema(value);
8
- }
9
-
10
- return schema;
5
+ /** The JSON schema of data like the given, each value's schema inferred from it, an array's from its first item */
6
+ export function generateDataSchema(data: Record<string, unknown>): DataSchema {
7
+ return { type: "object", properties: Object.fromEntries(Object.entries(data).map(([key, value]) => [key, inferSchema(value)])) };
11
8
  }
12
9
 
13
- function inferPropertySchema(value: unknown): PropertySchema {
14
- if (value === null || value === undefined) {
15
- return {
16
- type: "string",
17
- };
18
- }
19
-
20
- if (typeof value === "string") {
21
- return {
22
- type: "string",
23
- };
10
+ function inferSchema(value: unknown): DataSchema {
11
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
12
+ return { type: typeof value as "string" | "number" | "boolean" };
24
13
  }
25
-
26
- if (typeof value === "number") {
27
- return {
28
- type: "number",
29
- };
30
- }
31
-
32
- if (typeof value === "boolean") {
33
- return {
34
- type: "boolean",
35
- };
36
- }
37
-
38
- if (typeof value === "function") {
39
- return {
40
- type: "function",
41
- };
42
- }
43
-
44
14
  if (Array.isArray(value)) {
45
- const itemSchema: PropertySchema = value.length > 0 ? inferPropertySchema(value[0]) : { type: "string" };
46
- return {
47
- type: "array",
48
- shape: itemSchema,
49
- };
15
+ return { type: "array", items: value.length > 0 ? inferSchema(value[0]) : {} };
50
16
  }
51
-
52
- if (typeof value === "object") {
53
- const shape: Record<string, PropertySchema> = {};
54
- for (const [k, v] of Object.entries(value)) {
55
- shape[k] = inferPropertySchema(v);
56
- }
57
- return {
58
- type: "object",
59
- shape,
60
- };
17
+ if (typeof value === "object" && value !== null) {
18
+ return { type: "object", properties: Object.fromEntries(Object.entries(value).map(([k, v]) => [k, inferSchema(v)])) };
61
19
  }
62
-
63
- return { type: "string" };
20
+ // null, undefined and functions, which JSON schemas don't describe
21
+ return {};
64
22
  }