abstract-image 13.0.13 → 13.0.14
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/lib/exporters/dxf2d-export-image.d.ts +3 -3
- package/lib/exporters/dxf2d-export-image.d.ts.map +1 -1
- package/lib/exporters/dxf2d-export-image.js +48 -22
- package/lib/exporters/dxf2d-export-image.js.map +1 -1
- package/lib/exporters/react-svg-export-image.d.ts +6 -1
- package/lib/exporters/react-svg-export-image.d.ts.map +1 -1
- package/lib/exporters/react-svg-export-image.js +10 -7
- package/lib/exporters/react-svg-export-image.js.map +1 -1
- package/lib/exporters/svg-export-image.d.ts +8 -1
- package/lib/exporters/svg-export-image.d.ts.map +1 -1
- package/lib/exporters/svg-export-image.js +15 -9
- package/lib/exporters/svg-export-image.js.map +1 -1
- package/package.json +2 -2
- package/src/exporters/dxf2d-export-image.ts +185 -76
- package/src/exporters/react-svg-export-image.tsx +22 -6
- package/src/exporters/svg-export-image.ts +23 -9
|
@@ -4,6 +4,7 @@ import { AbstractImage } from "../model/abstract-image.js";
|
|
|
4
4
|
import { createPoint, Point } from "../model/point.js";
|
|
5
5
|
import { AbstractFontWeight, BinaryFormat, Component, GrowthDirection, ImageData } from "../model/component.js";
|
|
6
6
|
import { Color } from "../model/color.js";
|
|
7
|
+
import { Optional } from "../model/shared.js";
|
|
7
8
|
|
|
8
9
|
export interface ReactSvgCallbacks {
|
|
9
10
|
readonly onClick?: MouseCallback;
|
|
@@ -14,13 +15,22 @@ export interface ReactSvgCallbacks {
|
|
|
14
15
|
|
|
15
16
|
export type MouseCallback = (id: string | undefined, point: Point) => void;
|
|
16
17
|
|
|
18
|
+
export type ReactSvgOptions = {
|
|
19
|
+
readonly imageDataByUrl: Record<string, `data:image/${string},${string}`>;
|
|
20
|
+
};
|
|
21
|
+
|
|
17
22
|
export function ReactSvg({
|
|
18
23
|
image,
|
|
19
24
|
callbacks,
|
|
25
|
+
options,
|
|
20
26
|
}: {
|
|
21
27
|
readonly image: AbstractImage;
|
|
22
28
|
readonly callbacks?: ReactSvgCallbacks;
|
|
29
|
+
readonly options?: Optional<ReactSvgOptions>;
|
|
23
30
|
}): React.JSX.Element {
|
|
31
|
+
const opts: ReactSvgOptions = {
|
|
32
|
+
imageDataByUrl: options?.imageDataByUrl ?? {},
|
|
33
|
+
};
|
|
24
34
|
const cb = callbacks || {};
|
|
25
35
|
const id = "ai_root";
|
|
26
36
|
return (
|
|
@@ -35,7 +45,7 @@ export function ReactSvg({
|
|
|
35
45
|
onContextMenu={_callback(cb.onContextMenu, id)}
|
|
36
46
|
>
|
|
37
47
|
{image.components.map((c, i) => (
|
|
38
|
-
<JsxComponent key={i} component={c} />
|
|
48
|
+
<JsxComponent key={i} component={c} options={opts} />
|
|
39
49
|
))}
|
|
40
50
|
</svg>
|
|
41
51
|
);
|
|
@@ -74,18 +84,24 @@ function getIdAttr(target: Element | undefined, rootId: string): string | undefi
|
|
|
74
84
|
return parts[1];
|
|
75
85
|
}
|
|
76
86
|
|
|
77
|
-
function JsxComponent({
|
|
87
|
+
function JsxComponent({
|
|
88
|
+
component,
|
|
89
|
+
options,
|
|
90
|
+
}: {
|
|
91
|
+
readonly component: Component;
|
|
92
|
+
readonly options: ReactSvgOptions;
|
|
93
|
+
}): React.JSX.Element {
|
|
78
94
|
switch (component.type) {
|
|
79
95
|
case "group":
|
|
80
96
|
return (
|
|
81
97
|
<g name={component.name}>
|
|
82
98
|
{component.children.flatMap((c, i) => (
|
|
83
|
-
<JsxComponent key={i} component={c} />
|
|
99
|
+
<JsxComponent key={i} component={c} options={options} />
|
|
84
100
|
))}
|
|
85
101
|
</g>
|
|
86
102
|
);
|
|
87
103
|
case "binaryimage":
|
|
88
|
-
const url = getImageUrl(component.format, component.data);
|
|
104
|
+
const url = getImageUrl(component.format, component.data, options);
|
|
89
105
|
return (
|
|
90
106
|
<image
|
|
91
107
|
x={component.topLeft.x}
|
|
@@ -270,9 +286,9 @@ function getTextFontWeight(fontWeight: AbstractFontWeight): React.CSSProperties[
|
|
|
270
286
|
}
|
|
271
287
|
}
|
|
272
288
|
|
|
273
|
-
function getImageUrl(format: BinaryFormat, data: ImageData): string {
|
|
289
|
+
function getImageUrl(format: BinaryFormat, data: ImageData, options: ReactSvgOptions): string {
|
|
274
290
|
if (data.type === "url") {
|
|
275
|
-
return data.url;
|
|
291
|
+
return options.imageDataByUrl[data.url] ?? data.url;
|
|
276
292
|
} else if (format === "png") {
|
|
277
293
|
const base64 = fromByteArray(data.bytes);
|
|
278
294
|
return `data:image/png;base64,${base64}`;
|
|
@@ -2,23 +2,37 @@ import { fromByteArray } from "base64-js";
|
|
|
2
2
|
import { Component, GrowthDirection, BinaryFormat, ImageData } from "../model/component.js";
|
|
3
3
|
import { AbstractImage } from "../model/abstract-image.js";
|
|
4
4
|
import { Color } from "../model/color.js";
|
|
5
|
+
import { Optional } from "../model/shared.js";
|
|
5
6
|
|
|
6
|
-
export
|
|
7
|
-
|
|
7
|
+
export const SVG_DATA_URL = "data:image/svg+xml,";
|
|
8
|
+
|
|
9
|
+
export type SvgOptions = {
|
|
10
|
+
readonly pixelWidth: number;
|
|
11
|
+
readonly pixelHeight: number;
|
|
12
|
+
readonly imageDataByUrl: Record<string, `data:image/${string},${string}`>;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function createSVG(image: AbstractImage, options?: Optional<SvgOptions>): string {
|
|
16
|
+
const opts: SvgOptions = {
|
|
17
|
+
imageDataByUrl: options?.imageDataByUrl ?? {},
|
|
18
|
+
pixelWidth: options?.pixelWidth || image.size.width,
|
|
19
|
+
pixelHeight: options?.pixelHeight || image.size.height,
|
|
20
|
+
};
|
|
21
|
+
const imageElements = image.components.map((c: Component) => abstractComponentToSVG(c, opts));
|
|
8
22
|
|
|
9
23
|
return createElement(
|
|
10
24
|
"svg",
|
|
11
25
|
{
|
|
12
26
|
xmlns: "http://www.w3.org/2000/svg",
|
|
13
|
-
width: `${pixelWidth
|
|
14
|
-
height: `${pixelHeight
|
|
27
|
+
width: `${opts.pixelWidth}px`,
|
|
28
|
+
height: `${opts.pixelHeight}px`,
|
|
15
29
|
viewBox: [0, 0, image.size.width, image.size.height].join(" "),
|
|
16
30
|
},
|
|
17
31
|
imageElements
|
|
18
32
|
);
|
|
19
33
|
}
|
|
20
34
|
|
|
21
|
-
function abstractComponentToSVG(component: Component): string {
|
|
35
|
+
function abstractComponentToSVG(component: Component, options: SvgOptions): string {
|
|
22
36
|
switch (component.type) {
|
|
23
37
|
case "group":
|
|
24
38
|
return createElement(
|
|
@@ -26,10 +40,10 @@ function abstractComponentToSVG(component: Component): string {
|
|
|
26
40
|
{
|
|
27
41
|
name: component.name,
|
|
28
42
|
},
|
|
29
|
-
component.children.map((c) => abstractComponentToSVG(c))
|
|
43
|
+
component.children.map((c) => abstractComponentToSVG(c, options))
|
|
30
44
|
);
|
|
31
45
|
case "binaryimage":
|
|
32
|
-
const url = getImageUrl(component.format, component.data);
|
|
46
|
+
const url = getImageUrl(component.format, component.data, options);
|
|
33
47
|
return url
|
|
34
48
|
? createElement(
|
|
35
49
|
"image",
|
|
@@ -339,9 +353,9 @@ function colorToOpacity(color: Color): string {
|
|
|
339
353
|
return (color.a / 255).toString();
|
|
340
354
|
}
|
|
341
355
|
|
|
342
|
-
function getImageUrl(format: BinaryFormat, data: ImageData): string | undefined {
|
|
356
|
+
function getImageUrl(format: BinaryFormat, data: ImageData, options: SvgOptions): string | undefined {
|
|
343
357
|
if (data.type === "url") {
|
|
344
|
-
return data.url;
|
|
358
|
+
return options.imageDataByUrl[data.url] ?? data.url;
|
|
345
359
|
} else if (format === "png") {
|
|
346
360
|
const base64 = fromByteArray(data.bytes);
|
|
347
361
|
return `data:image/png;base64,${base64}`;
|