pptx-previewer 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.
- package/README.md +87 -0
- package/dist/index.d.mts +103 -0
- package/dist/index.d.ts +103 -0
- package/dist/index.js +449 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +422 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +47 -0
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# pptx-previewer
|
|
2
|
+
|
|
3
|
+
`pptx-previewer` is a React component for rendering PPTX-like slide JSON in the browser.
|
|
4
|
+
|
|
5
|
+
It is designed to work with JSON produced by PPTX parsers (for example the `pptx2json` output used in this repository) and supports common slide elements:
|
|
6
|
+
|
|
7
|
+
- `shape`
|
|
8
|
+
- `line`
|
|
9
|
+
- `text`
|
|
10
|
+
- `image`
|
|
11
|
+
- `table`
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pnpm add pptx-previewer
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { PPTXPreviewer, type Slide } from 'pptx-previewer';
|
|
23
|
+
|
|
24
|
+
const slide: Slide = {
|
|
25
|
+
background: { color: '#ffffff' },
|
|
26
|
+
elements: [
|
|
27
|
+
{
|
|
28
|
+
type: 'text',
|
|
29
|
+
left: 40,
|
|
30
|
+
top: 32,
|
|
31
|
+
width: 300,
|
|
32
|
+
height: 60,
|
|
33
|
+
content: '<p>Hello PPTX Preview</p>',
|
|
34
|
+
defaultColor: '#111827',
|
|
35
|
+
defaultFontName: 'Arial'
|
|
36
|
+
}
|
|
37
|
+
]
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export function App() {
|
|
41
|
+
return (
|
|
42
|
+
<div style={{ width: 960, height: 540 }}>
|
|
43
|
+
<PPTXPreviewer slide={slide} />
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## API
|
|
50
|
+
|
|
51
|
+
### `PPTXPreviewer`
|
|
52
|
+
|
|
53
|
+
Props:
|
|
54
|
+
|
|
55
|
+
- `slide: Slide` (required)
|
|
56
|
+
- `className?: string`
|
|
57
|
+
|
|
58
|
+
The component fills the size of its parent container. Set width/height on the parent element.
|
|
59
|
+
|
|
60
|
+
## Types
|
|
61
|
+
|
|
62
|
+
The package exports:
|
|
63
|
+
|
|
64
|
+
- `Slide`
|
|
65
|
+
- `SlideElement`
|
|
66
|
+
- `PPTXPreviewerProps`
|
|
67
|
+
|
|
68
|
+
## Development
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
cd src/lib/pptx-previewer
|
|
72
|
+
pnpm install
|
|
73
|
+
pnpm run typecheck
|
|
74
|
+
pnpm run build
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Build output is generated in `dist/`:
|
|
78
|
+
|
|
79
|
+
- `dist/index.mjs`
|
|
80
|
+
- `dist/index.js`
|
|
81
|
+
- `dist/index.d.ts`
|
|
82
|
+
|
|
83
|
+
## Notes
|
|
84
|
+
|
|
85
|
+
- This package is `react` peer-dependent (`>=18`).
|
|
86
|
+
- Element coordinates, sizes, and style semantics follow the input JSON schema.
|
|
87
|
+
- Text content is rendered via `dangerouslySetInnerHTML`; sanitize external/untrusted HTML before rendering.
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
type SlideElement = {
|
|
4
|
+
type: string;
|
|
5
|
+
id?: string;
|
|
6
|
+
groupId?: string;
|
|
7
|
+
left?: number;
|
|
8
|
+
top?: number;
|
|
9
|
+
width?: number;
|
|
10
|
+
height?: number;
|
|
11
|
+
rotate?: number;
|
|
12
|
+
fill?: string;
|
|
13
|
+
pattern?: string;
|
|
14
|
+
path?: string;
|
|
15
|
+
viewBox?: [number, number];
|
|
16
|
+
pathFormula?: string;
|
|
17
|
+
keypoints?: number[];
|
|
18
|
+
special?: boolean;
|
|
19
|
+
opacity?: number;
|
|
20
|
+
fixedRatio?: boolean;
|
|
21
|
+
outline?: {
|
|
22
|
+
width?: number;
|
|
23
|
+
color?: string;
|
|
24
|
+
style?: string;
|
|
25
|
+
};
|
|
26
|
+
shadow?: {
|
|
27
|
+
h?: number;
|
|
28
|
+
v?: number;
|
|
29
|
+
blur?: number;
|
|
30
|
+
color?: string;
|
|
31
|
+
};
|
|
32
|
+
content?: string;
|
|
33
|
+
defaultColor?: string;
|
|
34
|
+
defaultFontName?: string;
|
|
35
|
+
wordSpace?: number;
|
|
36
|
+
lineHeight?: number;
|
|
37
|
+
paragraphSpace?: number;
|
|
38
|
+
vertical?: boolean;
|
|
39
|
+
src?: string;
|
|
40
|
+
imageType?: string;
|
|
41
|
+
flipH?: boolean;
|
|
42
|
+
flipV?: boolean;
|
|
43
|
+
start?: [number, number];
|
|
44
|
+
end?: [number, number];
|
|
45
|
+
broken?: [number, number];
|
|
46
|
+
broken2?: [number, number];
|
|
47
|
+
curve?: [number, number];
|
|
48
|
+
cubic?: [[number, number], [number, number]];
|
|
49
|
+
color?: string;
|
|
50
|
+
points?: string[];
|
|
51
|
+
style?: string;
|
|
52
|
+
radius?: number;
|
|
53
|
+
clip?: {
|
|
54
|
+
shape?: string;
|
|
55
|
+
range?: [[number, number], [number, number]];
|
|
56
|
+
};
|
|
57
|
+
filters?: {
|
|
58
|
+
grayscale?: string;
|
|
59
|
+
opacity?: string;
|
|
60
|
+
blur?: string;
|
|
61
|
+
};
|
|
62
|
+
colWidths?: number[];
|
|
63
|
+
data?: Array<Array<{
|
|
64
|
+
id?: string;
|
|
65
|
+
colspan?: number;
|
|
66
|
+
rowspan?: number;
|
|
67
|
+
text?: string;
|
|
68
|
+
style?: {
|
|
69
|
+
fontname?: string;
|
|
70
|
+
color?: string;
|
|
71
|
+
align?: string;
|
|
72
|
+
fontsize?: string;
|
|
73
|
+
backcolor?: string;
|
|
74
|
+
};
|
|
75
|
+
}>>;
|
|
76
|
+
cellMinHeight?: number;
|
|
77
|
+
text?: {
|
|
78
|
+
content: string;
|
|
79
|
+
defaultColor?: string;
|
|
80
|
+
defaultFontName?: string;
|
|
81
|
+
align?: string;
|
|
82
|
+
lineHeight?: number;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
type Slide = {
|
|
86
|
+
id?: string;
|
|
87
|
+
elements?: SlideElement[];
|
|
88
|
+
remark?: string;
|
|
89
|
+
background?: {
|
|
90
|
+
type?: string;
|
|
91
|
+
color?: string;
|
|
92
|
+
src?: string;
|
|
93
|
+
};
|
|
94
|
+
type?: string;
|
|
95
|
+
};
|
|
96
|
+
type PPTXPreviewerProps = {
|
|
97
|
+
slide: Slide;
|
|
98
|
+
className?: string;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
declare function PPTXPreviewer({ slide, className }: PPTXPreviewerProps): react_jsx_runtime.JSX.Element;
|
|
102
|
+
|
|
103
|
+
export { PPTXPreviewer, type PPTXPreviewerProps, type Slide, type SlideElement };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
type SlideElement = {
|
|
4
|
+
type: string;
|
|
5
|
+
id?: string;
|
|
6
|
+
groupId?: string;
|
|
7
|
+
left?: number;
|
|
8
|
+
top?: number;
|
|
9
|
+
width?: number;
|
|
10
|
+
height?: number;
|
|
11
|
+
rotate?: number;
|
|
12
|
+
fill?: string;
|
|
13
|
+
pattern?: string;
|
|
14
|
+
path?: string;
|
|
15
|
+
viewBox?: [number, number];
|
|
16
|
+
pathFormula?: string;
|
|
17
|
+
keypoints?: number[];
|
|
18
|
+
special?: boolean;
|
|
19
|
+
opacity?: number;
|
|
20
|
+
fixedRatio?: boolean;
|
|
21
|
+
outline?: {
|
|
22
|
+
width?: number;
|
|
23
|
+
color?: string;
|
|
24
|
+
style?: string;
|
|
25
|
+
};
|
|
26
|
+
shadow?: {
|
|
27
|
+
h?: number;
|
|
28
|
+
v?: number;
|
|
29
|
+
blur?: number;
|
|
30
|
+
color?: string;
|
|
31
|
+
};
|
|
32
|
+
content?: string;
|
|
33
|
+
defaultColor?: string;
|
|
34
|
+
defaultFontName?: string;
|
|
35
|
+
wordSpace?: number;
|
|
36
|
+
lineHeight?: number;
|
|
37
|
+
paragraphSpace?: number;
|
|
38
|
+
vertical?: boolean;
|
|
39
|
+
src?: string;
|
|
40
|
+
imageType?: string;
|
|
41
|
+
flipH?: boolean;
|
|
42
|
+
flipV?: boolean;
|
|
43
|
+
start?: [number, number];
|
|
44
|
+
end?: [number, number];
|
|
45
|
+
broken?: [number, number];
|
|
46
|
+
broken2?: [number, number];
|
|
47
|
+
curve?: [number, number];
|
|
48
|
+
cubic?: [[number, number], [number, number]];
|
|
49
|
+
color?: string;
|
|
50
|
+
points?: string[];
|
|
51
|
+
style?: string;
|
|
52
|
+
radius?: number;
|
|
53
|
+
clip?: {
|
|
54
|
+
shape?: string;
|
|
55
|
+
range?: [[number, number], [number, number]];
|
|
56
|
+
};
|
|
57
|
+
filters?: {
|
|
58
|
+
grayscale?: string;
|
|
59
|
+
opacity?: string;
|
|
60
|
+
blur?: string;
|
|
61
|
+
};
|
|
62
|
+
colWidths?: number[];
|
|
63
|
+
data?: Array<Array<{
|
|
64
|
+
id?: string;
|
|
65
|
+
colspan?: number;
|
|
66
|
+
rowspan?: number;
|
|
67
|
+
text?: string;
|
|
68
|
+
style?: {
|
|
69
|
+
fontname?: string;
|
|
70
|
+
color?: string;
|
|
71
|
+
align?: string;
|
|
72
|
+
fontsize?: string;
|
|
73
|
+
backcolor?: string;
|
|
74
|
+
};
|
|
75
|
+
}>>;
|
|
76
|
+
cellMinHeight?: number;
|
|
77
|
+
text?: {
|
|
78
|
+
content: string;
|
|
79
|
+
defaultColor?: string;
|
|
80
|
+
defaultFontName?: string;
|
|
81
|
+
align?: string;
|
|
82
|
+
lineHeight?: number;
|
|
83
|
+
};
|
|
84
|
+
};
|
|
85
|
+
type Slide = {
|
|
86
|
+
id?: string;
|
|
87
|
+
elements?: SlideElement[];
|
|
88
|
+
remark?: string;
|
|
89
|
+
background?: {
|
|
90
|
+
type?: string;
|
|
91
|
+
color?: string;
|
|
92
|
+
src?: string;
|
|
93
|
+
};
|
|
94
|
+
type?: string;
|
|
95
|
+
};
|
|
96
|
+
type PPTXPreviewerProps = {
|
|
97
|
+
slide: Slide;
|
|
98
|
+
className?: string;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
declare function PPTXPreviewer({ slide, className }: PPTXPreviewerProps): react_jsx_runtime.JSX.Element;
|
|
102
|
+
|
|
103
|
+
export { PPTXPreviewer, type PPTXPreviewerProps, type Slide, type SlideElement };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
PPTXPreviewer: () => PPTXPreviewer
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(index_exports);
|
|
26
|
+
|
|
27
|
+
// src/renderers/image.tsx
|
|
28
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
29
|
+
function renderImage(element) {
|
|
30
|
+
const filterStr = [
|
|
31
|
+
element.filters?.grayscale ? `grayscale(${element.filters.grayscale})` : "",
|
|
32
|
+
element.filters?.opacity ? `opacity(${element.filters.opacity})` : "",
|
|
33
|
+
element.filters?.blur ? `blur(${element.filters.blur})` : ""
|
|
34
|
+
].filter(Boolean).join(" ");
|
|
35
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
36
|
+
"div",
|
|
37
|
+
{
|
|
38
|
+
style: {
|
|
39
|
+
width: "100%",
|
|
40
|
+
height: "100%",
|
|
41
|
+
overflow: "hidden",
|
|
42
|
+
borderRadius: element.clip?.shape === "ellipse" ? "50%" : element.radius ? `${element.radius}px` : void 0,
|
|
43
|
+
filter: filterStr || void 0
|
|
44
|
+
},
|
|
45
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: element.src || "", alt: "", style: { width: "100%", height: "100%", objectFit: "cover" } })
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// src/constants.ts
|
|
51
|
+
var MIN_LINE_SIZE = 24;
|
|
52
|
+
|
|
53
|
+
// src/renderers/line.tsx
|
|
54
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
55
|
+
var getLineDashArray = (width, style) => {
|
|
56
|
+
if (style === "dashed") return width <= 8 ? `${width * 5} ${width * 2.5}` : `${width * 5} ${width * 1.5}`;
|
|
57
|
+
if (style === "dotted") return width <= 8 ? `${width * 1.8} ${width * 1.6}` : `${width * 1.5} ${width * 1.2}`;
|
|
58
|
+
return "0 0";
|
|
59
|
+
};
|
|
60
|
+
var getLinePath = (element) => {
|
|
61
|
+
const start = element.start.join(",");
|
|
62
|
+
const end = element.end.join(",");
|
|
63
|
+
if (element.broken) return `M${start} L${element.broken.join(",")} L${end}`;
|
|
64
|
+
if (element.broken2) {
|
|
65
|
+
const width = Math.abs(element.end[0] - element.start[0]);
|
|
66
|
+
const height = Math.abs(element.end[1] - element.start[1]);
|
|
67
|
+
if (width >= height) {
|
|
68
|
+
return `M${start} L${element.broken2[0]},${element.start[1]} L${element.broken2[0]},${element.end[1]} L${end}`;
|
|
69
|
+
}
|
|
70
|
+
return `M${start} L${element.start[0]},${element.broken2[1]} L${element.end[0]},${element.broken2[1]} L${end}`;
|
|
71
|
+
}
|
|
72
|
+
if (element.curve) return `M${start} Q${element.curve.join(",")} ${end}`;
|
|
73
|
+
if (element.cubic) {
|
|
74
|
+
const [c1, c2] = element.cubic;
|
|
75
|
+
return `M${start} C${c1.join(",")} ${c2.join(",")} ${end}`;
|
|
76
|
+
}
|
|
77
|
+
return `M${start} L${end}`;
|
|
78
|
+
};
|
|
79
|
+
function renderLineMarker(props) {
|
|
80
|
+
const pathMap = {
|
|
81
|
+
dot: "m0 5a5 5 0 1 0 10 0a5 5 0 1 0 -10 0z",
|
|
82
|
+
arrow: "M0,0 L10,5 0,10 Z"
|
|
83
|
+
};
|
|
84
|
+
const rotateMap = {
|
|
85
|
+
"arrow-start": 180,
|
|
86
|
+
"arrow-end": 0
|
|
87
|
+
};
|
|
88
|
+
const size = props.baseSize < 2 ? 2 : props.baseSize;
|
|
89
|
+
const rotate = rotateMap[`${props.type}-${props.position}`] || 0;
|
|
90
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
91
|
+
"marker",
|
|
92
|
+
{
|
|
93
|
+
id: `${props.id}-${props.type}-${props.position}`,
|
|
94
|
+
markerUnits: "userSpaceOnUse",
|
|
95
|
+
orient: "auto",
|
|
96
|
+
markerWidth: size * 3,
|
|
97
|
+
markerHeight: size * 3,
|
|
98
|
+
refX: size * 1.5,
|
|
99
|
+
refY: size * 1.5,
|
|
100
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: pathMap[props.type], fill: props.color, transform: `scale(${size * 0.3}, ${size * 0.3}) rotate(${rotate}, 5, 5)` })
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
function renderLine(element, markerId) {
|
|
105
|
+
if (!element.start || !element.end) return null;
|
|
106
|
+
const width = Math.max(Math.abs(element.start[0] - element.end[0]), MIN_LINE_SIZE);
|
|
107
|
+
const height = Math.max(Math.abs(element.start[1] - element.end[1]), MIN_LINE_SIZE);
|
|
108
|
+
const lineWidth = element.width ?? 1;
|
|
109
|
+
const dashArray = getLineDashArray(lineWidth, element.style);
|
|
110
|
+
const path = getLinePath(element);
|
|
111
|
+
const points = element.points;
|
|
112
|
+
const startMarker = points?.[0] ? points[0] : void 0;
|
|
113
|
+
const endMarker = points?.[1] ? points[1] : void 0;
|
|
114
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { overflow: "visible", width, height, children: [
|
|
115
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("defs", { children: [
|
|
116
|
+
startMarker && renderLineMarker({ id: markerId, position: "start", type: startMarker, color: element.color, baseSize: lineWidth }),
|
|
117
|
+
endMarker && renderLineMarker({ id: markerId, position: "end", type: endMarker, color: element.color, baseSize: lineWidth })
|
|
118
|
+
] }),
|
|
119
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
120
|
+
"path",
|
|
121
|
+
{
|
|
122
|
+
d: path,
|
|
123
|
+
stroke: element.color ?? "#000",
|
|
124
|
+
strokeWidth: lineWidth,
|
|
125
|
+
strokeDasharray: dashArray,
|
|
126
|
+
fill: "none",
|
|
127
|
+
markerStart: startMarker ? `url(#${markerId}-${startMarker}-start)` : void 0,
|
|
128
|
+
markerEnd: endMarker ? `url(#${markerId}-${endMarker}-end)` : void 0
|
|
129
|
+
}
|
|
130
|
+
)
|
|
131
|
+
] });
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// src/renderers/shape.tsx
|
|
135
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
136
|
+
var getOutlineDashArray = (outline) => {
|
|
137
|
+
const style = outline?.style;
|
|
138
|
+
const width = outline?.width ?? 1;
|
|
139
|
+
if (style === "dashed") return width <= 8 ? `${width * 5} ${width * 2.5}` : `${width * 5} ${width * 1.5}`;
|
|
140
|
+
if (style === "dotted") return width <= 8 ? `${width * 1.8} ${width * 1.6}` : `${width * 1.5} ${width * 1.2}`;
|
|
141
|
+
return void 0;
|
|
142
|
+
};
|
|
143
|
+
function renderShape(element, patternId) {
|
|
144
|
+
const viewWidth = element.viewBox?.[0] ?? element.width ?? 0;
|
|
145
|
+
const viewHeight = element.viewBox?.[1] ?? element.height ?? 0;
|
|
146
|
+
const outlineDashArray = getOutlineDashArray(element.outline);
|
|
147
|
+
const fill = element.pattern ? `url(#${patternId})` : element.fill || "transparent";
|
|
148
|
+
const text = element.text;
|
|
149
|
+
const verticalAlign = text?.align ?? "middle";
|
|
150
|
+
const justifyContent = verticalAlign === "top" ? "flex-start" : verticalAlign === "bottom" ? "flex-end" : "center";
|
|
151
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { position: "relative", width: "100%", height: "100%" }, children: [
|
|
152
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { style: { position: "absolute", inset: 0 }, overflow: "visible", width: element.width, height: element.height, children: [
|
|
153
|
+
element.pattern && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
154
|
+
"pattern",
|
|
155
|
+
{
|
|
156
|
+
id: patternId,
|
|
157
|
+
patternUnits: "userSpaceOnUse",
|
|
158
|
+
patternContentUnits: "userSpaceOnUse",
|
|
159
|
+
width: viewWidth,
|
|
160
|
+
height: viewHeight,
|
|
161
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("image", { href: element.pattern, width: viewWidth, height: viewHeight, preserveAspectRatio: "xMidYMid slice" })
|
|
162
|
+
}
|
|
163
|
+
) }),
|
|
164
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("g", { transform: `scale(${(element.width ?? 0) / viewWidth || 1}, ${(element.height ?? 0) / viewHeight || 1}) translate(0,0) matrix(1,0,0,1,0,0)`, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
165
|
+
"path",
|
|
166
|
+
{
|
|
167
|
+
vectorEffect: "non-scaling-stroke",
|
|
168
|
+
strokeLinecap: "butt",
|
|
169
|
+
strokeMiterlimit: 8,
|
|
170
|
+
d: element.path || "",
|
|
171
|
+
fill,
|
|
172
|
+
stroke: element.outline?.color,
|
|
173
|
+
strokeWidth: element.outline?.width,
|
|
174
|
+
strokeDasharray: outlineDashArray
|
|
175
|
+
}
|
|
176
|
+
) })
|
|
177
|
+
] }),
|
|
178
|
+
text?.content && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
179
|
+
"div",
|
|
180
|
+
{
|
|
181
|
+
style: {
|
|
182
|
+
position: "absolute",
|
|
183
|
+
inset: 0,
|
|
184
|
+
display: "flex",
|
|
185
|
+
flexDirection: "column",
|
|
186
|
+
justifyContent,
|
|
187
|
+
alignItems: "stretch",
|
|
188
|
+
color: text.defaultColor,
|
|
189
|
+
fontFamily: text.defaultFontName || void 0,
|
|
190
|
+
lineHeight: text.lineHeight,
|
|
191
|
+
pointerEvents: "none"
|
|
192
|
+
},
|
|
193
|
+
dangerouslySetInnerHTML: { __html: text.content }
|
|
194
|
+
}
|
|
195
|
+
)
|
|
196
|
+
] });
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// src/renderers/table.tsx
|
|
200
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
201
|
+
var parseFontSize = (value) => {
|
|
202
|
+
if (!value) return void 0;
|
|
203
|
+
const size = Number.parseFloat(value);
|
|
204
|
+
return Number.isFinite(size) ? `${size}px` : void 0;
|
|
205
|
+
};
|
|
206
|
+
var normalizeFontName = (value) => {
|
|
207
|
+
if (!value) return void 0;
|
|
208
|
+
return value.replace(/^"+|"+$/g, "");
|
|
209
|
+
};
|
|
210
|
+
var tableColor = (value) => {
|
|
211
|
+
if (!value) return void 0;
|
|
212
|
+
return value.startsWith("rgb") || value.startsWith("#") ? value : void 0;
|
|
213
|
+
};
|
|
214
|
+
var isPlaceholderCell = (cell) => {
|
|
215
|
+
if (!cell) return false;
|
|
216
|
+
const colspan = cell.colspan ?? 1;
|
|
217
|
+
const rowspan = cell.rowspan ?? 1;
|
|
218
|
+
if (colspan !== 1 || rowspan !== 1) return false;
|
|
219
|
+
const style = cell.style;
|
|
220
|
+
const hasStyle = Boolean(style?.fontname) || Boolean(style?.fontsize) || Boolean(style?.color) || Boolean(style?.backcolor);
|
|
221
|
+
return (cell.text ?? "").trim() === "" && !hasStyle;
|
|
222
|
+
};
|
|
223
|
+
var buildTableRows = (element) => {
|
|
224
|
+
const rows = element.data ?? [];
|
|
225
|
+
const colCount = element.colWidths?.length ?? 0;
|
|
226
|
+
const rowCells = [];
|
|
227
|
+
const skip = new Array(colCount).fill(0);
|
|
228
|
+
rows.forEach((row, rowIndex) => {
|
|
229
|
+
const cells = [];
|
|
230
|
+
let colIndex = 0;
|
|
231
|
+
let cellIndex = 0;
|
|
232
|
+
while (colIndex < colCount) {
|
|
233
|
+
if (skip[colIndex] > 0) {
|
|
234
|
+
skip[colIndex] -= 1;
|
|
235
|
+
if (isPlaceholderCell(row[cellIndex])) cellIndex += 1;
|
|
236
|
+
colIndex += 1;
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
const cell = row[cellIndex];
|
|
240
|
+
if (!cell) break;
|
|
241
|
+
cellIndex += 1;
|
|
242
|
+
const colSpan = cell.colspan ?? 1;
|
|
243
|
+
const rowSpan = cell.rowspan ?? 1;
|
|
244
|
+
if (rowSpan > 1) {
|
|
245
|
+
for (let i = 0; i < colSpan; i += 1) {
|
|
246
|
+
skip[colIndex + i] = rowSpan - 1;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (colSpan > 1) {
|
|
250
|
+
for (let i = 0; i < colSpan - 1; i += 1) {
|
|
251
|
+
if (isPlaceholderCell(row[cellIndex])) cellIndex += 1;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
cells.push({
|
|
255
|
+
key: cell.id ?? `${rowIndex}-${colIndex}-${cellIndex}`,
|
|
256
|
+
colSpan,
|
|
257
|
+
rowSpan,
|
|
258
|
+
text: cell.text ?? "",
|
|
259
|
+
style: cell.style
|
|
260
|
+
});
|
|
261
|
+
colIndex += colSpan;
|
|
262
|
+
}
|
|
263
|
+
rowCells.push(cells);
|
|
264
|
+
});
|
|
265
|
+
return rowCells;
|
|
266
|
+
};
|
|
267
|
+
function renderTable(element) {
|
|
268
|
+
const colWidths = element.colWidths ?? [];
|
|
269
|
+
const rows = buildTableRows(element);
|
|
270
|
+
const rowCount = rows.length || 1;
|
|
271
|
+
const baseRowHeight = (element.height ?? 0) / rowCount;
|
|
272
|
+
const rowHeight = element.cellMinHeight ? Math.max(element.cellMinHeight, baseRowHeight) : baseRowHeight;
|
|
273
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
274
|
+
"table",
|
|
275
|
+
{
|
|
276
|
+
style: {
|
|
277
|
+
width: "100%",
|
|
278
|
+
height: "100%",
|
|
279
|
+
tableLayout: "fixed",
|
|
280
|
+
borderCollapse: "collapse",
|
|
281
|
+
border: element.outline ? `${element.outline.width ?? 1}px solid ${element.outline.color ?? "#000"}` : void 0
|
|
282
|
+
},
|
|
283
|
+
children: [
|
|
284
|
+
colWidths.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("colgroup", { children: colWidths.map((width, index) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("col", { style: { width: `${width * 100}%` } }, `col-${index}`)) }),
|
|
285
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("tbody", { children: rows.map((row, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("tr", { style: { height: rowHeight }, children: row.map((cell) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
286
|
+
"td",
|
|
287
|
+
{
|
|
288
|
+
colSpan: cell.colSpan,
|
|
289
|
+
rowSpan: cell.rowSpan,
|
|
290
|
+
style: {
|
|
291
|
+
border: element.outline ? `${element.outline.width ?? 1}px solid ${element.outline.color ?? "#000"}` : "1px solid #ddd",
|
|
292
|
+
background: tableColor(cell.style?.backcolor),
|
|
293
|
+
padding: "6px 8px",
|
|
294
|
+
textAlign: cell.style?.align ?? "left",
|
|
295
|
+
color: tableColor(cell.style?.color),
|
|
296
|
+
fontFamily: normalizeFontName(cell.style?.fontname),
|
|
297
|
+
fontSize: parseFontSize(cell.style?.fontsize),
|
|
298
|
+
verticalAlign: "middle"
|
|
299
|
+
},
|
|
300
|
+
children: cell.text
|
|
301
|
+
},
|
|
302
|
+
cell.key
|
|
303
|
+
)) }, `row-${rowIndex}`)) })
|
|
304
|
+
]
|
|
305
|
+
}
|
|
306
|
+
) });
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// src/renderers/text.tsx
|
|
310
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
311
|
+
function renderText(element) {
|
|
312
|
+
const paragraphStyle = element.paragraphSpace !== void 0 ? { ["--paragraphSpace"]: `${element.paragraphSpace}px` } : void 0;
|
|
313
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
314
|
+
"div",
|
|
315
|
+
{
|
|
316
|
+
style: {
|
|
317
|
+
width: "100%",
|
|
318
|
+
height: "100%",
|
|
319
|
+
padding: 10,
|
|
320
|
+
lineHeight: element.lineHeight ?? 1.5,
|
|
321
|
+
letterSpacing: `${element.wordSpace ?? 0}px`,
|
|
322
|
+
wordBreak: "break-word",
|
|
323
|
+
fontFamily: element.defaultFontName || "sans-serif",
|
|
324
|
+
color: element.defaultColor,
|
|
325
|
+
writingMode: element.vertical ? "vertical-rl" : void 0,
|
|
326
|
+
...paragraphStyle
|
|
327
|
+
},
|
|
328
|
+
dangerouslySetInnerHTML: { __html: element.content || "" }
|
|
329
|
+
}
|
|
330
|
+
);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// src/renderers/index.tsx
|
|
334
|
+
function renderElement(element, markerId) {
|
|
335
|
+
if (element.type === "shape") return renderShape(element, `shape-${markerId}`);
|
|
336
|
+
if (element.type === "line") return renderLine(element, markerId);
|
|
337
|
+
if (element.type === "text") return renderText(element);
|
|
338
|
+
if (element.type === "image") return renderImage(element);
|
|
339
|
+
if (element.type === "table") return renderTable(element);
|
|
340
|
+
return null;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
// src/utils/elementSize.ts
|
|
344
|
+
function getElementSize(element) {
|
|
345
|
+
if (element.type === "line" && element.start && element.end) {
|
|
346
|
+
return {
|
|
347
|
+
width: Math.max(Math.abs(element.end[0] - element.start[0]), MIN_LINE_SIZE),
|
|
348
|
+
height: Math.max(Math.abs(element.end[1] - element.start[1]), MIN_LINE_SIZE)
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
return {
|
|
352
|
+
width: element.width ?? 0,
|
|
353
|
+
height: element.height ?? 0
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
// src/utils/elementStyle.ts
|
|
358
|
+
var getShadowFilter = (shadow) => {
|
|
359
|
+
if (!shadow) return void 0;
|
|
360
|
+
const h = shadow.h ?? 0;
|
|
361
|
+
const v = shadow.v ?? 0;
|
|
362
|
+
const blur = shadow.blur ?? 0;
|
|
363
|
+
const color = shadow.color ?? "#000";
|
|
364
|
+
return `drop-shadow(${h}px ${v}px ${blur}px ${color})`;
|
|
365
|
+
};
|
|
366
|
+
var getFlipTransform = (flipH, flipV) => {
|
|
367
|
+
const transforms = [flipH ? "scaleX(-1)" : "", flipV ? "scaleY(-1)" : ""].filter(Boolean).join(" ");
|
|
368
|
+
return transforms || void 0;
|
|
369
|
+
};
|
|
370
|
+
|
|
371
|
+
// src/PPTXPreviewer.tsx
|
|
372
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
373
|
+
function PPTXPreviewer({ slide, className }) {
|
|
374
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
375
|
+
"div",
|
|
376
|
+
{
|
|
377
|
+
className,
|
|
378
|
+
style: {
|
|
379
|
+
position: "relative",
|
|
380
|
+
width: "100%",
|
|
381
|
+
height: "100%",
|
|
382
|
+
overflow: "hidden",
|
|
383
|
+
fontSize: 16,
|
|
384
|
+
lineHeight: "normal"
|
|
385
|
+
},
|
|
386
|
+
children: [
|
|
387
|
+
slide.background?.color ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
388
|
+
"div",
|
|
389
|
+
{
|
|
390
|
+
style: {
|
|
391
|
+
position: "absolute",
|
|
392
|
+
inset: 0,
|
|
393
|
+
backgroundColor: slide.background.color
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
) : null,
|
|
397
|
+
(slide.elements ?? []).map((element, elementIndex) => {
|
|
398
|
+
const size = getElementSize(element);
|
|
399
|
+
const markerId = element.id ?? `line-${elementIndex}`;
|
|
400
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
401
|
+
"div",
|
|
402
|
+
{
|
|
403
|
+
style: {
|
|
404
|
+
position: "absolute",
|
|
405
|
+
left: element.left ?? 0,
|
|
406
|
+
top: element.top ?? 0,
|
|
407
|
+
width: size.width,
|
|
408
|
+
height: size.height
|
|
409
|
+
},
|
|
410
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
411
|
+
"div",
|
|
412
|
+
{
|
|
413
|
+
style: {
|
|
414
|
+
width: "100%",
|
|
415
|
+
height: "100%",
|
|
416
|
+
transform: element.rotate ? `rotate(${element.rotate}deg)` : void 0
|
|
417
|
+
},
|
|
418
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
419
|
+
"div",
|
|
420
|
+
{
|
|
421
|
+
style: {
|
|
422
|
+
position: "relative",
|
|
423
|
+
width: "100%",
|
|
424
|
+
height: "100%",
|
|
425
|
+
opacity: element.opacity ?? 1,
|
|
426
|
+
filter: getShadowFilter(element.shadow),
|
|
427
|
+
transform: getFlipTransform(element.flipH, element.flipV),
|
|
428
|
+
transformOrigin: "center",
|
|
429
|
+
color: element.defaultColor,
|
|
430
|
+
fontFamily: element.defaultFontName
|
|
431
|
+
},
|
|
432
|
+
children: renderElement(element, markerId)
|
|
433
|
+
}
|
|
434
|
+
)
|
|
435
|
+
}
|
|
436
|
+
)
|
|
437
|
+
},
|
|
438
|
+
element.id ?? elementIndex
|
|
439
|
+
);
|
|
440
|
+
})
|
|
441
|
+
]
|
|
442
|
+
}
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
446
|
+
0 && (module.exports = {
|
|
447
|
+
PPTXPreviewer
|
|
448
|
+
});
|
|
449
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../index.ts","../src/renderers/image.tsx","../src/constants.ts","../src/renderers/line.tsx","../src/renderers/shape.tsx","../src/renderers/table.tsx","../src/renderers/text.tsx","../src/renderers/index.tsx","../src/utils/elementSize.ts","../src/utils/elementStyle.ts","../src/PPTXPreviewer.tsx"],"sourcesContent":["export { PPTXPreviewer } from './src/PPTXPreviewer';\nexport type { PPTXPreviewerProps, Slide, SlideElement } from './src/types';\n","import type { SlideElement } from '../types';\n\nexport function renderImage(element: SlideElement) {\n const filterStr = [\n element.filters?.grayscale ? `grayscale(${element.filters.grayscale})` : '',\n element.filters?.opacity ? `opacity(${element.filters.opacity})` : '',\n element.filters?.blur ? `blur(${element.filters.blur})` : ''\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n borderRadius: element.clip?.shape === 'ellipse' ? '50%' : element.radius ? `${element.radius}px` : undefined,\n filter: filterStr || undefined\n }}\n >\n <img src={element.src || ''} alt='' style={{ width: '100%', height: '100%', objectFit: 'cover' }} />\n </div>\n );\n}\n","export const MIN_LINE_SIZE = 24;\n","import { MIN_LINE_SIZE } from '../constants';\nimport type { SlideElement } from '../types';\n\ntype LineElement = SlideElement & { start: [number, number]; end: [number, number] };\ntype LinePointType = '' | 'arrow' | 'dot';\n\nconst getLineDashArray = (width: number, style?: string) => {\n if (style === 'dashed') return width <= 8 ? `${width * 5} ${width * 2.5}` : `${width * 5} ${width * 1.5}`;\n if (style === 'dotted') return width <= 8 ? `${width * 1.8} ${width * 1.6}` : `${width * 1.5} ${width * 1.2}`;\n return '0 0';\n};\n\nconst getLinePath = (element: LineElement) => {\n const start = element.start.join(',');\n const end = element.end.join(',');\n\n if (element.broken) return `M${start} L${element.broken.join(',')} L${end}`;\n\n if (element.broken2) {\n const width = Math.abs(element.end[0] - element.start[0]);\n const height = Math.abs(element.end[1] - element.start[1]);\n if (width >= height) {\n return `M${start} L${element.broken2[0]},${element.start[1]} L${element.broken2[0]},${element.end[1]} L${end}`;\n }\n return `M${start} L${element.start[0]},${element.broken2[1]} L${element.end[0]},${element.broken2[1]} L${end}`;\n }\n\n if (element.curve) return `M${start} Q${element.curve.join(',')} ${end}`;\n\n if (element.cubic) {\n const [c1, c2] = element.cubic;\n return `M${start} C${c1.join(',')} ${c2.join(',')} ${end}`;\n }\n\n return `M${start} L${end}`;\n};\n\nfunction renderLineMarker(props: {\n id: string;\n position: 'start' | 'end';\n type: 'arrow' | 'dot';\n baseSize: number;\n color?: string;\n}) {\n const pathMap = {\n dot: 'm0 5a5 5 0 1 0 10 0a5 5 0 1 0 -10 0z',\n arrow: 'M0,0 L10,5 0,10 Z'\n };\n const rotateMap: Record<string, number> = {\n 'arrow-start': 180,\n 'arrow-end': 0\n };\n const size = props.baseSize < 2 ? 2 : props.baseSize;\n const rotate = rotateMap[`${props.type}-${props.position}`] || 0;\n\n return (\n <marker\n id={`${props.id}-${props.type}-${props.position}`}\n markerUnits='userSpaceOnUse'\n orient='auto'\n markerWidth={size * 3}\n markerHeight={size * 3}\n refX={size * 1.5}\n refY={size * 1.5}\n >\n <path d={pathMap[props.type]} fill={props.color} transform={`scale(${size * 0.3}, ${size * 0.3}) rotate(${rotate}, 5, 5)`} />\n </marker>\n );\n}\n\nexport function renderLine(element: SlideElement, markerId: string) {\n if (!element.start || !element.end) return null;\n\n const width = Math.max(Math.abs(element.start[0] - element.end[0]), MIN_LINE_SIZE);\n const height = Math.max(Math.abs(element.start[1] - element.end[1]), MIN_LINE_SIZE);\n const lineWidth = element.width ?? 1;\n const dashArray = getLineDashArray(lineWidth, element.style);\n const path = getLinePath(element as LineElement);\n\n const points = element.points as [LinePointType, LinePointType] | undefined;\n const startMarker = points?.[0] ? points[0] : undefined;\n const endMarker = points?.[1] ? points[1] : undefined;\n\n return (\n <svg overflow='visible' width={width} height={height}>\n <defs>\n {startMarker && renderLineMarker({ id: markerId, position: 'start', type: startMarker, color: element.color, baseSize: lineWidth })}\n {endMarker && renderLineMarker({ id: markerId, position: 'end', type: endMarker, color: element.color, baseSize: lineWidth })}\n </defs>\n <path\n d={path}\n stroke={element.color ?? '#000'}\n strokeWidth={lineWidth}\n strokeDasharray={dashArray}\n fill='none'\n markerStart={startMarker ? `url(#${markerId}-${startMarker}-start)` : undefined}\n markerEnd={endMarker ? `url(#${markerId}-${endMarker}-end)` : undefined}\n />\n </svg>\n );\n}\n","import type { SlideElement } from '../types';\n\nconst getOutlineDashArray = (outline?: SlideElement['outline']) => {\n const style = outline?.style;\n const width = outline?.width ?? 1;\n if (style === 'dashed') return width <= 8 ? `${width * 5} ${width * 2.5}` : `${width * 5} ${width * 1.5}`;\n if (style === 'dotted') return width <= 8 ? `${width * 1.8} ${width * 1.6}` : `${width * 1.5} ${width * 1.2}`;\n return undefined;\n};\n\nexport function renderShape(element: SlideElement, patternId: string) {\n const viewWidth = element.viewBox?.[0] ?? element.width ?? 0;\n const viewHeight = element.viewBox?.[1] ?? element.height ?? 0;\n const outlineDashArray = getOutlineDashArray(element.outline);\n const fill = element.pattern ? `url(#${patternId})` : element.fill || 'transparent';\n\n const text = element.text;\n const verticalAlign = text?.align ?? 'middle';\n const justifyContent = verticalAlign === 'top' ? 'flex-start' : verticalAlign === 'bottom' ? 'flex-end' : 'center';\n\n return (\n <div style={{ position: 'relative', width: '100%', height: '100%' }}>\n <svg style={{ position: 'absolute', inset: 0 }} overflow='visible' width={element.width} height={element.height}>\n {element.pattern && (\n <defs>\n <pattern\n id={patternId}\n patternUnits='userSpaceOnUse'\n patternContentUnits='userSpaceOnUse'\n width={viewWidth}\n height={viewHeight}\n >\n <image href={element.pattern} width={viewWidth} height={viewHeight} preserveAspectRatio='xMidYMid slice' />\n </pattern>\n </defs>\n )}\n <g transform={`scale(${(element.width ?? 0) / viewWidth || 1}, ${(element.height ?? 0) / viewHeight || 1}) translate(0,0) matrix(1,0,0,1,0,0)`}>\n <path\n vectorEffect='non-scaling-stroke'\n strokeLinecap='butt'\n strokeMiterlimit={8}\n d={element.path || ''}\n fill={fill}\n stroke={element.outline?.color}\n strokeWidth={element.outline?.width}\n strokeDasharray={outlineDashArray}\n />\n </g>\n </svg>\n\n {text?.content && (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n flexDirection: 'column',\n justifyContent,\n alignItems: 'stretch',\n color: text.defaultColor,\n fontFamily: text.defaultFontName || undefined,\n lineHeight: text.lineHeight,\n pointerEvents: 'none'\n }}\n dangerouslySetInnerHTML={{ __html: text.content }}\n />\n )}\n </div>\n );\n}\n","import { type CSSProperties } from 'react';\nimport type { SlideElement } from '../types';\n\ntype TableCellData = NonNullable<NonNullable<SlideElement['data']>[number][number]>;\ntype TableCell = {\n key: string;\n colSpan: number;\n rowSpan: number;\n text: string;\n style: TableCellData['style'];\n};\n\nconst parseFontSize = (value?: string) => {\n if (!value) return undefined;\n const size = Number.parseFloat(value);\n return Number.isFinite(size) ? `${size}px` : undefined;\n};\n\nconst normalizeFontName = (value?: string) => {\n if (!value) return undefined;\n return value.replace(/^\"+|\"+$/g, '');\n};\n\nconst tableColor = (value?: string) => {\n if (!value) return undefined;\n return value.startsWith('rgb') || value.startsWith('#') ? value : undefined;\n};\n\nconst isPlaceholderCell = (cell: TableCellData | undefined) => {\n if (!cell) return false;\n const colspan = cell.colspan ?? 1;\n const rowspan = cell.rowspan ?? 1;\n if (colspan !== 1 || rowspan !== 1) return false;\n\n const style = cell.style;\n const hasStyle = Boolean(style?.fontname) || Boolean(style?.fontsize) || Boolean(style?.color) || Boolean(style?.backcolor);\n return (cell.text ?? '').trim() === '' && !hasStyle;\n};\n\nconst buildTableRows = (element: SlideElement) => {\n const rows = element.data ?? [];\n const colCount = element.colWidths?.length ?? 0;\n const rowCells: TableCell[][] = [];\n const skip = new Array(colCount).fill(0);\n\n rows.forEach((row, rowIndex) => {\n const cells: TableCell[] = [];\n let colIndex = 0;\n let cellIndex = 0;\n\n while (colIndex < colCount) {\n if (skip[colIndex] > 0) {\n skip[colIndex] -= 1;\n if (isPlaceholderCell(row[cellIndex])) cellIndex += 1;\n colIndex += 1;\n continue;\n }\n\n const cell = row[cellIndex];\n if (!cell) break;\n cellIndex += 1;\n\n const colSpan = cell.colspan ?? 1;\n const rowSpan = cell.rowspan ?? 1;\n\n if (rowSpan > 1) {\n for (let i = 0; i < colSpan; i += 1) {\n skip[colIndex + i] = rowSpan - 1;\n }\n }\n\n if (colSpan > 1) {\n for (let i = 0; i < colSpan - 1; i += 1) {\n if (isPlaceholderCell(row[cellIndex])) cellIndex += 1;\n }\n }\n\n cells.push({\n key: cell.id ?? `${rowIndex}-${colIndex}-${cellIndex}`,\n colSpan,\n rowSpan,\n text: cell.text ?? '',\n style: cell.style\n });\n\n colIndex += colSpan;\n }\n\n rowCells.push(cells);\n });\n\n return rowCells;\n};\n\nexport function renderTable(element: SlideElement) {\n const colWidths = element.colWidths ?? [];\n const rows = buildTableRows(element);\n const rowCount = rows.length || 1;\n const baseRowHeight = (element.height ?? 0) / rowCount;\n const rowHeight = element.cellMinHeight ? Math.max(element.cellMinHeight, baseRowHeight) : baseRowHeight;\n\n return (\n <div style={{ width: '100%', height: '100%' }}>\n <table\n style={{\n width: '100%',\n height: '100%',\n tableLayout: 'fixed',\n borderCollapse: 'collapse',\n border: element.outline ? `${element.outline.width ?? 1}px solid ${element.outline.color ?? '#000'}` : undefined\n }}\n >\n {colWidths.length > 0 && (\n <colgroup>\n {colWidths.map((width, index) => (\n <col key={`col-${index}`} style={{ width: `${width * 100}%` }} />\n ))}\n </colgroup>\n )}\n <tbody>\n {rows.map((row, rowIndex) => (\n <tr key={`row-${rowIndex}`} style={{ height: rowHeight }}>\n {row.map((cell) => (\n <td\n key={cell.key}\n colSpan={cell.colSpan}\n rowSpan={cell.rowSpan}\n style={{\n border: element.outline ? `${element.outline.width ?? 1}px solid ${element.outline.color ?? '#000'}` : '1px solid #ddd',\n background: tableColor(cell.style?.backcolor),\n padding: '6px 8px',\n textAlign: (cell.style?.align as CSSProperties['textAlign']) ?? 'left',\n color: tableColor(cell.style?.color),\n fontFamily: normalizeFontName(cell.style?.fontname),\n fontSize: parseFontSize(cell.style?.fontsize),\n verticalAlign: 'middle'\n }}\n >\n {cell.text}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n","import { type CSSProperties } from 'react';\nimport type { SlideElement } from '../types';\n\nexport function renderText(element: SlideElement) {\n const paragraphStyle =\n element.paragraphSpace !== undefined\n ? ({ ['--paragraphSpace' as string]: `${element.paragraphSpace}px` } as CSSProperties)\n : undefined;\n\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n padding: 10,\n lineHeight: element.lineHeight ?? 1.5,\n letterSpacing: `${element.wordSpace ?? 0}px`,\n wordBreak: 'break-word',\n fontFamily: element.defaultFontName || 'sans-serif',\n color: element.defaultColor,\n writingMode: element.vertical ? 'vertical-rl' : undefined,\n ...paragraphStyle\n }}\n dangerouslySetInnerHTML={{ __html: element.content || '' }}\n />\n );\n}\n","import type { SlideElement } from '../types';\nimport { renderImage } from './image';\nimport { renderLine } from './line';\nimport { renderShape } from './shape';\nimport { renderTable } from './table';\nimport { renderText } from './text';\n\nexport function renderElement(element: SlideElement, markerId: string) {\n if (element.type === 'shape') return renderShape(element, `shape-${markerId}`);\n if (element.type === 'line') return renderLine(element, markerId);\n if (element.type === 'text') return renderText(element);\n if (element.type === 'image') return renderImage(element);\n if (element.type === 'table') return renderTable(element);\n return null;\n}\n","import { MIN_LINE_SIZE } from '../constants';\nimport type { SlideElement } from '../types';\n\nexport function getElementSize(element: SlideElement): { width: number; height: number } {\n if (element.type === 'line' && element.start && element.end) {\n return {\n width: Math.max(Math.abs(element.end[0] - element.start[0]), MIN_LINE_SIZE),\n height: Math.max(Math.abs(element.end[1] - element.start[1]), MIN_LINE_SIZE)\n };\n }\n\n return {\n width: element.width ?? 0,\n height: element.height ?? 0\n };\n}\n","import type { SlideElement } from '../types';\n\nexport const getShadowFilter = (shadow?: SlideElement['shadow']) => {\n if (!shadow) return undefined;\n const h = shadow.h ?? 0;\n const v = shadow.v ?? 0;\n const blur = shadow.blur ?? 0;\n const color = shadow.color ?? '#000';\n return `drop-shadow(${h}px ${v}px ${blur}px ${color})`;\n};\n\nexport const getFlipTransform = (flipH?: boolean, flipV?: boolean) => {\n const transforms = [flipH ? 'scaleX(-1)' : '', flipV ? 'scaleY(-1)' : '']\n .filter(Boolean)\n .join(' ');\n return transforms || undefined;\n};\n","import { renderElement } from './renderers';\nimport type { PPTXPreviewerProps } from './types';\nimport { getElementSize } from './utils/elementSize';\nimport { getFlipTransform, getShadowFilter } from './utils/elementStyle';\n\nexport function PPTXPreviewer({ slide, className }: PPTXPreviewerProps) {\n return (\n <div\n className={className}\n style={{\n position: 'relative',\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n fontSize: 16,\n lineHeight: 'normal'\n }}\n >\n {slide.background?.color ? (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n backgroundColor: slide.background.color\n }}\n />\n ) : null}\n\n {(slide.elements ?? []).map((element, elementIndex) => {\n const size = getElementSize(element);\n const markerId = element.id ?? `line-${elementIndex}`;\n\n return (\n <div\n key={element.id ?? elementIndex}\n style={{\n position: 'absolute',\n left: element.left ?? 0,\n top: element.top ?? 0,\n width: size.width,\n height: size.height\n }}\n >\n <div\n style={{\n width: '100%',\n height: '100%',\n transform: element.rotate ? `rotate(${element.rotate}deg)` : undefined\n }}\n >\n <div\n style={{\n position: 'relative',\n width: '100%',\n height: '100%',\n opacity: element.opacity ?? 1,\n filter: getShadowFilter(element.shadow),\n transform: getFlipTransform(element.flipH, element.flipV),\n transformOrigin: 'center',\n color: element.defaultColor,\n fontFamily: element.defaultFontName\n }}\n >\n {renderElement(element, markerId)}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACqBM;AAnBC,SAAS,YAAY,SAAuB;AACjD,QAAM,YAAY;AAAA,IAChB,QAAQ,SAAS,YAAY,aAAa,QAAQ,QAAQ,SAAS,MAAM;AAAA,IACzE,QAAQ,SAAS,UAAU,WAAW,QAAQ,QAAQ,OAAO,MAAM;AAAA,IACnE,QAAQ,SAAS,OAAO,QAAQ,QAAQ,QAAQ,IAAI,MAAM;AAAA,EAC5D,EACG,OAAO,OAAO,EACd,KAAK,GAAG;AAEX,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,cAAc,QAAQ,MAAM,UAAU,YAAY,QAAQ,QAAQ,SAAS,GAAG,QAAQ,MAAM,OAAO;AAAA,QACnG,QAAQ,aAAa;AAAA,MACvB;AAAA,MAEA,sDAAC,SAAI,KAAK,QAAQ,OAAO,IAAI,KAAI,IAAG,OAAO,EAAE,OAAO,QAAQ,QAAQ,QAAQ,WAAW,QAAQ,GAAG;AAAA;AAAA,EACpG;AAEJ;;;ACxBO,IAAM,gBAAgB;;;ACiEvB,IAAAA,sBAAA;AA3DN,IAAM,mBAAmB,CAAC,OAAe,UAAmB;AAC1D,MAAI,UAAU,SAAU,QAAO,SAAS,IAAI,GAAG,QAAQ,CAAC,IAAI,QAAQ,GAAG,KAAK,GAAG,QAAQ,CAAC,IAAI,QAAQ,GAAG;AACvG,MAAI,UAAU,SAAU,QAAO,SAAS,IAAI,GAAG,QAAQ,GAAG,IAAI,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,IAAI,QAAQ,GAAG;AAC3G,SAAO;AACT;AAEA,IAAM,cAAc,CAAC,YAAyB;AAC5C,QAAM,QAAQ,QAAQ,MAAM,KAAK,GAAG;AACpC,QAAM,MAAM,QAAQ,IAAI,KAAK,GAAG;AAEhC,MAAI,QAAQ,OAAQ,QAAO,IAAI,KAAK,KAAK,QAAQ,OAAO,KAAK,GAAG,CAAC,KAAK,GAAG;AAEzE,MAAI,QAAQ,SAAS;AACnB,UAAM,QAAQ,KAAK,IAAI,QAAQ,IAAI,CAAC,IAAI,QAAQ,MAAM,CAAC,CAAC;AACxD,UAAM,SAAS,KAAK,IAAI,QAAQ,IAAI,CAAC,IAAI,QAAQ,MAAM,CAAC,CAAC;AACzD,QAAI,SAAS,QAAQ;AACnB,aAAO,IAAI,KAAK,KAAK,QAAQ,QAAQ,CAAC,CAAC,IAAI,QAAQ,MAAM,CAAC,CAAC,KAAK,QAAQ,QAAQ,CAAC,CAAC,IAAI,QAAQ,IAAI,CAAC,CAAC,KAAK,GAAG;AAAA,IAC9G;AACA,WAAO,IAAI,KAAK,KAAK,QAAQ,MAAM,CAAC,CAAC,IAAI,QAAQ,QAAQ,CAAC,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,QAAQ,QAAQ,CAAC,CAAC,KAAK,GAAG;AAAA,EAC9G;AAEA,MAAI,QAAQ,MAAO,QAAO,IAAI,KAAK,KAAK,QAAQ,MAAM,KAAK,GAAG,CAAC,IAAI,GAAG;AAEtE,MAAI,QAAQ,OAAO;AACjB,UAAM,CAAC,IAAI,EAAE,IAAI,QAAQ;AACzB,WAAO,IAAI,KAAK,KAAK,GAAG,KAAK,GAAG,CAAC,IAAI,GAAG,KAAK,GAAG,CAAC,IAAI,GAAG;AAAA,EAC1D;AAEA,SAAO,IAAI,KAAK,KAAK,GAAG;AAC1B;AAEA,SAAS,iBAAiB,OAMvB;AACD,QAAM,UAAU;AAAA,IACd,KAAK;AAAA,IACL,OAAO;AAAA,EACT;AACA,QAAM,YAAoC;AAAA,IACxC,eAAe;AAAA,IACf,aAAa;AAAA,EACf;AACA,QAAM,OAAO,MAAM,WAAW,IAAI,IAAI,MAAM;AAC5C,QAAM,SAAS,UAAU,GAAG,MAAM,IAAI,IAAI,MAAM,QAAQ,EAAE,KAAK;AAE/D,SACE;AAAA,IAAC;AAAA;AAAA,MACC,IAAI,GAAG,MAAM,EAAE,IAAI,MAAM,IAAI,IAAI,MAAM,QAAQ;AAAA,MAC/C,aAAY;AAAA,MACZ,QAAO;AAAA,MACP,aAAa,OAAO;AAAA,MACpB,cAAc,OAAO;AAAA,MACrB,MAAM,OAAO;AAAA,MACb,MAAM,OAAO;AAAA,MAEb,uDAAC,UAAK,GAAG,QAAQ,MAAM,IAAI,GAAG,MAAM,MAAM,OAAO,WAAW,SAAS,OAAO,GAAG,KAAK,OAAO,GAAG,YAAY,MAAM,WAAW;AAAA;AAAA,EAC7H;AAEJ;AAEO,SAAS,WAAW,SAAuB,UAAkB;AAClE,MAAI,CAAC,QAAQ,SAAS,CAAC,QAAQ,IAAK,QAAO;AAE3C,QAAM,QAAQ,KAAK,IAAI,KAAK,IAAI,QAAQ,MAAM,CAAC,IAAI,QAAQ,IAAI,CAAC,CAAC,GAAG,aAAa;AACjF,QAAM,SAAS,KAAK,IAAI,KAAK,IAAI,QAAQ,MAAM,CAAC,IAAI,QAAQ,IAAI,CAAC,CAAC,GAAG,aAAa;AAClF,QAAM,YAAY,QAAQ,SAAS;AACnC,QAAM,YAAY,iBAAiB,WAAW,QAAQ,KAAK;AAC3D,QAAM,OAAO,YAAY,OAAsB;AAE/C,QAAM,SAAS,QAAQ;AACvB,QAAM,cAAc,SAAS,CAAC,IAAI,OAAO,CAAC,IAAI;AAC9C,QAAM,YAAY,SAAS,CAAC,IAAI,OAAO,CAAC,IAAI;AAE5C,SACE,8CAAC,SAAI,UAAS,WAAU,OAAc,QACpC;AAAA,kDAAC,UACE;AAAA,qBAAe,iBAAiB,EAAE,IAAI,UAAU,UAAU,SAAS,MAAM,aAAa,OAAO,QAAQ,OAAO,UAAU,UAAU,CAAC;AAAA,MACjI,aAAa,iBAAiB,EAAE,IAAI,UAAU,UAAU,OAAO,MAAM,WAAW,OAAO,QAAQ,OAAO,UAAU,UAAU,CAAC;AAAA,OAC9H;AAAA,IACA;AAAA,MAAC;AAAA;AAAA,QACC,GAAG;AAAA,QACH,QAAQ,QAAQ,SAAS;AAAA,QACzB,aAAa;AAAA,QACb,iBAAiB;AAAA,QACjB,MAAK;AAAA,QACL,aAAa,cAAc,QAAQ,QAAQ,IAAI,WAAW,YAAY;AAAA,QACtE,WAAW,YAAY,QAAQ,QAAQ,IAAI,SAAS,UAAU;AAAA;AAAA,IAChE;AAAA,KACF;AAEJ;;;AC9EM,IAAAC,sBAAA;AApBN,IAAM,sBAAsB,CAAC,YAAsC;AACjE,QAAM,QAAQ,SAAS;AACvB,QAAM,QAAQ,SAAS,SAAS;AAChC,MAAI,UAAU,SAAU,QAAO,SAAS,IAAI,GAAG,QAAQ,CAAC,IAAI,QAAQ,GAAG,KAAK,GAAG,QAAQ,CAAC,IAAI,QAAQ,GAAG;AACvG,MAAI,UAAU,SAAU,QAAO,SAAS,IAAI,GAAG,QAAQ,GAAG,IAAI,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,IAAI,QAAQ,GAAG;AAC3G,SAAO;AACT;AAEO,SAAS,YAAY,SAAuB,WAAmB;AACpE,QAAM,YAAY,QAAQ,UAAU,CAAC,KAAK,QAAQ,SAAS;AAC3D,QAAM,aAAa,QAAQ,UAAU,CAAC,KAAK,QAAQ,UAAU;AAC7D,QAAM,mBAAmB,oBAAoB,QAAQ,OAAO;AAC5D,QAAM,OAAO,QAAQ,UAAU,QAAQ,SAAS,MAAM,QAAQ,QAAQ;AAEtE,QAAM,OAAO,QAAQ;AACrB,QAAM,gBAAgB,MAAM,SAAS;AACrC,QAAM,iBAAiB,kBAAkB,QAAQ,eAAe,kBAAkB,WAAW,aAAa;AAE1G,SACE,8CAAC,SAAI,OAAO,EAAE,UAAU,YAAY,OAAO,QAAQ,QAAQ,OAAO,GAChE;AAAA,kDAAC,SAAI,OAAO,EAAE,UAAU,YAAY,OAAO,EAAE,GAAG,UAAS,WAAU,OAAO,QAAQ,OAAO,QAAQ,QAAQ,QACtG;AAAA,cAAQ,WACP,6CAAC,UACC;AAAA,QAAC;AAAA;AAAA,UACC,IAAI;AAAA,UACJ,cAAa;AAAA,UACb,qBAAoB;AAAA,UACpB,OAAO;AAAA,UACP,QAAQ;AAAA,UAER,uDAAC,WAAM,MAAM,QAAQ,SAAS,OAAO,WAAW,QAAQ,YAAY,qBAAoB,kBAAiB;AAAA;AAAA,MAC3G,GACF;AAAA,MAEF,6CAAC,OAAE,WAAW,UAAU,QAAQ,SAAS,KAAK,aAAa,CAAC,MAAM,QAAQ,UAAU,KAAK,cAAc,CAAC,wCACtG;AAAA,QAAC;AAAA;AAAA,UACC,cAAa;AAAA,UACb,eAAc;AAAA,UACd,kBAAkB;AAAA,UAClB,GAAG,QAAQ,QAAQ;AAAA,UACnB;AAAA,UACA,QAAQ,QAAQ,SAAS;AAAA,UACzB,aAAa,QAAQ,SAAS;AAAA,UAC9B,iBAAiB;AAAA;AAAA,MACnB,GACF;AAAA,OACF;AAAA,IAEC,MAAM,WACL;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,UAAU;AAAA,UACV,OAAO;AAAA,UACP,SAAS;AAAA,UACT,eAAe;AAAA,UACf;AAAA,UACA,YAAY;AAAA,UACZ,OAAO,KAAK;AAAA,UACZ,YAAY,KAAK,mBAAmB;AAAA,UACpC,YAAY,KAAK;AAAA,UACjB,eAAe;AAAA,QACjB;AAAA,QACA,yBAAyB,EAAE,QAAQ,KAAK,QAAQ;AAAA;AAAA,IAClD;AAAA,KAEJ;AAEJ;;;ACkCM,IAAAC,sBAAA;AA3FN,IAAM,gBAAgB,CAAC,UAAmB;AACxC,MAAI,CAAC,MAAO,QAAO;AACnB,QAAM,OAAO,OAAO,WAAW,KAAK;AACpC,SAAO,OAAO,SAAS,IAAI,IAAI,GAAG,IAAI,OAAO;AAC/C;AAEA,IAAM,oBAAoB,CAAC,UAAmB;AAC5C,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,MAAM,QAAQ,YAAY,EAAE;AACrC;AAEA,IAAM,aAAa,CAAC,UAAmB;AACrC,MAAI,CAAC,MAAO,QAAO;AACnB,SAAO,MAAM,WAAW,KAAK,KAAK,MAAM,WAAW,GAAG,IAAI,QAAQ;AACpE;AAEA,IAAM,oBAAoB,CAAC,SAAoC;AAC7D,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,UAAU,KAAK,WAAW;AAChC,QAAM,UAAU,KAAK,WAAW;AAChC,MAAI,YAAY,KAAK,YAAY,EAAG,QAAO;AAE3C,QAAM,QAAQ,KAAK;AACnB,QAAM,WAAW,QAAQ,OAAO,QAAQ,KAAK,QAAQ,OAAO,QAAQ,KAAK,QAAQ,OAAO,KAAK,KAAK,QAAQ,OAAO,SAAS;AAC1H,UAAQ,KAAK,QAAQ,IAAI,KAAK,MAAM,MAAM,CAAC;AAC7C;AAEA,IAAM,iBAAiB,CAAC,YAA0B;AAChD,QAAM,OAAO,QAAQ,QAAQ,CAAC;AAC9B,QAAM,WAAW,QAAQ,WAAW,UAAU;AAC9C,QAAM,WAA0B,CAAC;AACjC,QAAM,OAAO,IAAI,MAAM,QAAQ,EAAE,KAAK,CAAC;AAEvC,OAAK,QAAQ,CAAC,KAAK,aAAa;AAC9B,UAAM,QAAqB,CAAC;AAC5B,QAAI,WAAW;AACf,QAAI,YAAY;AAEhB,WAAO,WAAW,UAAU;AAC1B,UAAI,KAAK,QAAQ,IAAI,GAAG;AACtB,aAAK,QAAQ,KAAK;AAClB,YAAI,kBAAkB,IAAI,SAAS,CAAC,EAAG,cAAa;AACpD,oBAAY;AACZ;AAAA,MACF;AAEA,YAAM,OAAO,IAAI,SAAS;AAC1B,UAAI,CAAC,KAAM;AACX,mBAAa;AAEb,YAAM,UAAU,KAAK,WAAW;AAChC,YAAM,UAAU,KAAK,WAAW;AAEhC,UAAI,UAAU,GAAG;AACf,iBAAS,IAAI,GAAG,IAAI,SAAS,KAAK,GAAG;AACnC,eAAK,WAAW,CAAC,IAAI,UAAU;AAAA,QACjC;AAAA,MACF;AAEA,UAAI,UAAU,GAAG;AACf,iBAAS,IAAI,GAAG,IAAI,UAAU,GAAG,KAAK,GAAG;AACvC,cAAI,kBAAkB,IAAI,SAAS,CAAC,EAAG,cAAa;AAAA,QACtD;AAAA,MACF;AAEA,YAAM,KAAK;AAAA,QACT,KAAK,KAAK,MAAM,GAAG,QAAQ,IAAI,QAAQ,IAAI,SAAS;AAAA,QACpD;AAAA,QACA;AAAA,QACA,MAAM,KAAK,QAAQ;AAAA,QACnB,OAAO,KAAK;AAAA,MACd,CAAC;AAED,kBAAY;AAAA,IACd;AAEA,aAAS,KAAK,KAAK;AAAA,EACrB,CAAC;AAED,SAAO;AACT;AAEO,SAAS,YAAY,SAAuB;AACjD,QAAM,YAAY,QAAQ,aAAa,CAAC;AACxC,QAAM,OAAO,eAAe,OAAO;AACnC,QAAM,WAAW,KAAK,UAAU;AAChC,QAAM,iBAAiB,QAAQ,UAAU,KAAK;AAC9C,QAAM,YAAY,QAAQ,gBAAgB,KAAK,IAAI,QAAQ,eAAe,aAAa,IAAI;AAE3F,SACE,6CAAC,SAAI,OAAO,EAAE,OAAO,QAAQ,QAAQ,OAAO,GAC1C;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,aAAa;AAAA,QACb,gBAAgB;AAAA,QAChB,QAAQ,QAAQ,UAAU,GAAG,QAAQ,QAAQ,SAAS,CAAC,YAAY,QAAQ,QAAQ,SAAS,MAAM,KAAK;AAAA,MACzG;AAAA,MAEC;AAAA,kBAAU,SAAS,KAClB,6CAAC,cACE,oBAAU,IAAI,CAAC,OAAO,UACrB,6CAAC,SAAyB,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,KAAlD,OAAO,KAAK,EAAyC,CAChE,GACH;AAAA,QAEF,6CAAC,WACE,eAAK,IAAI,CAAC,KAAK,aACd,6CAAC,QAA2B,OAAO,EAAE,QAAQ,UAAU,GACpD,cAAI,IAAI,CAAC,SACR;AAAA,UAAC;AAAA;AAAA,YAEC,SAAS,KAAK;AAAA,YACd,SAAS,KAAK;AAAA,YACd,OAAO;AAAA,cACL,QAAQ,QAAQ,UAAU,GAAG,QAAQ,QAAQ,SAAS,CAAC,YAAY,QAAQ,QAAQ,SAAS,MAAM,KAAK;AAAA,cACvG,YAAY,WAAW,KAAK,OAAO,SAAS;AAAA,cAC5C,SAAS;AAAA,cACT,WAAY,KAAK,OAAO,SAAwC;AAAA,cAChE,OAAO,WAAW,KAAK,OAAO,KAAK;AAAA,cACnC,YAAY,kBAAkB,KAAK,OAAO,QAAQ;AAAA,cAClD,UAAU,cAAc,KAAK,OAAO,QAAQ;AAAA,cAC5C,eAAe;AAAA,YACjB;AAAA,YAEC,eAAK;AAAA;AAAA,UAdD,KAAK;AAAA,QAeZ,CACD,KAnBM,OAAO,QAAQ,EAoBxB,CACD,GACH;AAAA;AAAA;AAAA,EACF,GACF;AAEJ;;;ACzII,IAAAC,sBAAA;AAPG,SAAS,WAAW,SAAuB;AAChD,QAAM,iBACJ,QAAQ,mBAAmB,SACtB,EAAE,CAAC,kBAA4B,GAAG,GAAG,QAAQ,cAAc,KAAK,IACjE;AAEN,SACE;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,YAAY,QAAQ,cAAc;AAAA,QAClC,eAAe,GAAG,QAAQ,aAAa,CAAC;AAAA,QACxC,WAAW;AAAA,QACX,YAAY,QAAQ,mBAAmB;AAAA,QACvC,OAAO,QAAQ;AAAA,QACf,aAAa,QAAQ,WAAW,gBAAgB;AAAA,QAChD,GAAG;AAAA,MACL;AAAA,MACA,yBAAyB,EAAE,QAAQ,QAAQ,WAAW,GAAG;AAAA;AAAA,EAC3D;AAEJ;;;ACnBO,SAAS,cAAc,SAAuB,UAAkB;AACrE,MAAI,QAAQ,SAAS,QAAS,QAAO,YAAY,SAAS,SAAS,QAAQ,EAAE;AAC7E,MAAI,QAAQ,SAAS,OAAQ,QAAO,WAAW,SAAS,QAAQ;AAChE,MAAI,QAAQ,SAAS,OAAQ,QAAO,WAAW,OAAO;AACtD,MAAI,QAAQ,SAAS,QAAS,QAAO,YAAY,OAAO;AACxD,MAAI,QAAQ,SAAS,QAAS,QAAO,YAAY,OAAO;AACxD,SAAO;AACT;;;ACXO,SAAS,eAAe,SAA0D;AACvF,MAAI,QAAQ,SAAS,UAAU,QAAQ,SAAS,QAAQ,KAAK;AAC3D,WAAO;AAAA,MACL,OAAO,KAAK,IAAI,KAAK,IAAI,QAAQ,IAAI,CAAC,IAAI,QAAQ,MAAM,CAAC,CAAC,GAAG,aAAa;AAAA,MAC1E,QAAQ,KAAK,IAAI,KAAK,IAAI,QAAQ,IAAI,CAAC,IAAI,QAAQ,MAAM,CAAC,CAAC,GAAG,aAAa;AAAA,IAC7E;AAAA,EACF;AAEA,SAAO;AAAA,IACL,OAAO,QAAQ,SAAS;AAAA,IACxB,QAAQ,QAAQ,UAAU;AAAA,EAC5B;AACF;;;ACbO,IAAM,kBAAkB,CAAC,WAAoC;AAClE,MAAI,CAAC,OAAQ,QAAO;AACpB,QAAM,IAAI,OAAO,KAAK;AACtB,QAAM,IAAI,OAAO,KAAK;AACtB,QAAM,OAAO,OAAO,QAAQ;AAC5B,QAAM,QAAQ,OAAO,SAAS;AAC9B,SAAO,eAAe,CAAC,MAAM,CAAC,MAAM,IAAI,MAAM,KAAK;AACrD;AAEO,IAAM,mBAAmB,CAAC,OAAiB,UAAoB;AACpE,QAAM,aAAa,CAAC,QAAQ,eAAe,IAAI,QAAQ,eAAe,EAAE,EACrE,OAAO,OAAO,EACd,KAAK,GAAG;AACX,SAAO,cAAc;AACvB;;;ACTI,IAAAC,sBAAA;AAFG,SAAS,cAAc,EAAE,OAAO,UAAU,GAAuB;AACtE,SACE;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA,OAAO;AAAA,QACL,UAAU;AAAA,QACV,OAAO;AAAA,QACP,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,UAAU;AAAA,QACV,YAAY;AAAA,MACd;AAAA,MAEC;AAAA,cAAM,YAAY,QACjB;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,UAAU;AAAA,cACV,OAAO;AAAA,cACP,iBAAiB,MAAM,WAAW;AAAA,YACpC;AAAA;AAAA,QACF,IACE;AAAA,SAEF,MAAM,YAAY,CAAC,GAAG,IAAI,CAAC,SAAS,iBAAiB;AACrD,gBAAM,OAAO,eAAe,OAAO;AACnC,gBAAM,WAAW,QAAQ,MAAM,QAAQ,YAAY;AAEnD,iBACE;AAAA,YAAC;AAAA;AAAA,cAEC,OAAO;AAAA,gBACL,UAAU;AAAA,gBACV,MAAM,QAAQ,QAAQ;AAAA,gBACtB,KAAK,QAAQ,OAAO;AAAA,gBACpB,OAAO,KAAK;AAAA,gBACZ,QAAQ,KAAK;AAAA,cACf;AAAA,cAEA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO;AAAA,oBACL,OAAO;AAAA,oBACP,QAAQ;AAAA,oBACR,WAAW,QAAQ,SAAS,UAAU,QAAQ,MAAM,SAAS;AAAA,kBAC/D;AAAA,kBAEA;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAO;AAAA,wBACL,UAAU;AAAA,wBACV,OAAO;AAAA,wBACP,QAAQ;AAAA,wBACR,SAAS,QAAQ,WAAW;AAAA,wBAC5B,QAAQ,gBAAgB,QAAQ,MAAM;AAAA,wBACtC,WAAW,iBAAiB,QAAQ,OAAO,QAAQ,KAAK;AAAA,wBACxD,iBAAiB;AAAA,wBACjB,OAAO,QAAQ;AAAA,wBACf,YAAY,QAAQ;AAAA,sBACtB;AAAA,sBAEC,wBAAc,SAAS,QAAQ;AAAA;AAAA,kBAClC;AAAA;AAAA,cACF;AAAA;AAAA,YA/BK,QAAQ,MAAM;AAAA,UAgCrB;AAAA,QAEJ,CAAC;AAAA;AAAA;AAAA,EACH;AAEJ;","names":["import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime"]}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
// src/renderers/image.tsx
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
function renderImage(element) {
|
|
4
|
+
const filterStr = [
|
|
5
|
+
element.filters?.grayscale ? `grayscale(${element.filters.grayscale})` : "",
|
|
6
|
+
element.filters?.opacity ? `opacity(${element.filters.opacity})` : "",
|
|
7
|
+
element.filters?.blur ? `blur(${element.filters.blur})` : ""
|
|
8
|
+
].filter(Boolean).join(" ");
|
|
9
|
+
return /* @__PURE__ */ jsx(
|
|
10
|
+
"div",
|
|
11
|
+
{
|
|
12
|
+
style: {
|
|
13
|
+
width: "100%",
|
|
14
|
+
height: "100%",
|
|
15
|
+
overflow: "hidden",
|
|
16
|
+
borderRadius: element.clip?.shape === "ellipse" ? "50%" : element.radius ? `${element.radius}px` : void 0,
|
|
17
|
+
filter: filterStr || void 0
|
|
18
|
+
},
|
|
19
|
+
children: /* @__PURE__ */ jsx("img", { src: element.src || "", alt: "", style: { width: "100%", height: "100%", objectFit: "cover" } })
|
|
20
|
+
}
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// src/constants.ts
|
|
25
|
+
var MIN_LINE_SIZE = 24;
|
|
26
|
+
|
|
27
|
+
// src/renderers/line.tsx
|
|
28
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
29
|
+
var getLineDashArray = (width, style) => {
|
|
30
|
+
if (style === "dashed") return width <= 8 ? `${width * 5} ${width * 2.5}` : `${width * 5} ${width * 1.5}`;
|
|
31
|
+
if (style === "dotted") return width <= 8 ? `${width * 1.8} ${width * 1.6}` : `${width * 1.5} ${width * 1.2}`;
|
|
32
|
+
return "0 0";
|
|
33
|
+
};
|
|
34
|
+
var getLinePath = (element) => {
|
|
35
|
+
const start = element.start.join(",");
|
|
36
|
+
const end = element.end.join(",");
|
|
37
|
+
if (element.broken) return `M${start} L${element.broken.join(",")} L${end}`;
|
|
38
|
+
if (element.broken2) {
|
|
39
|
+
const width = Math.abs(element.end[0] - element.start[0]);
|
|
40
|
+
const height = Math.abs(element.end[1] - element.start[1]);
|
|
41
|
+
if (width >= height) {
|
|
42
|
+
return `M${start} L${element.broken2[0]},${element.start[1]} L${element.broken2[0]},${element.end[1]} L${end}`;
|
|
43
|
+
}
|
|
44
|
+
return `M${start} L${element.start[0]},${element.broken2[1]} L${element.end[0]},${element.broken2[1]} L${end}`;
|
|
45
|
+
}
|
|
46
|
+
if (element.curve) return `M${start} Q${element.curve.join(",")} ${end}`;
|
|
47
|
+
if (element.cubic) {
|
|
48
|
+
const [c1, c2] = element.cubic;
|
|
49
|
+
return `M${start} C${c1.join(",")} ${c2.join(",")} ${end}`;
|
|
50
|
+
}
|
|
51
|
+
return `M${start} L${end}`;
|
|
52
|
+
};
|
|
53
|
+
function renderLineMarker(props) {
|
|
54
|
+
const pathMap = {
|
|
55
|
+
dot: "m0 5a5 5 0 1 0 10 0a5 5 0 1 0 -10 0z",
|
|
56
|
+
arrow: "M0,0 L10,5 0,10 Z"
|
|
57
|
+
};
|
|
58
|
+
const rotateMap = {
|
|
59
|
+
"arrow-start": 180,
|
|
60
|
+
"arrow-end": 0
|
|
61
|
+
};
|
|
62
|
+
const size = props.baseSize < 2 ? 2 : props.baseSize;
|
|
63
|
+
const rotate = rotateMap[`${props.type}-${props.position}`] || 0;
|
|
64
|
+
return /* @__PURE__ */ jsx2(
|
|
65
|
+
"marker",
|
|
66
|
+
{
|
|
67
|
+
id: `${props.id}-${props.type}-${props.position}`,
|
|
68
|
+
markerUnits: "userSpaceOnUse",
|
|
69
|
+
orient: "auto",
|
|
70
|
+
markerWidth: size * 3,
|
|
71
|
+
markerHeight: size * 3,
|
|
72
|
+
refX: size * 1.5,
|
|
73
|
+
refY: size * 1.5,
|
|
74
|
+
children: /* @__PURE__ */ jsx2("path", { d: pathMap[props.type], fill: props.color, transform: `scale(${size * 0.3}, ${size * 0.3}) rotate(${rotate}, 5, 5)` })
|
|
75
|
+
}
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
function renderLine(element, markerId) {
|
|
79
|
+
if (!element.start || !element.end) return null;
|
|
80
|
+
const width = Math.max(Math.abs(element.start[0] - element.end[0]), MIN_LINE_SIZE);
|
|
81
|
+
const height = Math.max(Math.abs(element.start[1] - element.end[1]), MIN_LINE_SIZE);
|
|
82
|
+
const lineWidth = element.width ?? 1;
|
|
83
|
+
const dashArray = getLineDashArray(lineWidth, element.style);
|
|
84
|
+
const path = getLinePath(element);
|
|
85
|
+
const points = element.points;
|
|
86
|
+
const startMarker = points?.[0] ? points[0] : void 0;
|
|
87
|
+
const endMarker = points?.[1] ? points[1] : void 0;
|
|
88
|
+
return /* @__PURE__ */ jsxs("svg", { overflow: "visible", width, height, children: [
|
|
89
|
+
/* @__PURE__ */ jsxs("defs", { children: [
|
|
90
|
+
startMarker && renderLineMarker({ id: markerId, position: "start", type: startMarker, color: element.color, baseSize: lineWidth }),
|
|
91
|
+
endMarker && renderLineMarker({ id: markerId, position: "end", type: endMarker, color: element.color, baseSize: lineWidth })
|
|
92
|
+
] }),
|
|
93
|
+
/* @__PURE__ */ jsx2(
|
|
94
|
+
"path",
|
|
95
|
+
{
|
|
96
|
+
d: path,
|
|
97
|
+
stroke: element.color ?? "#000",
|
|
98
|
+
strokeWidth: lineWidth,
|
|
99
|
+
strokeDasharray: dashArray,
|
|
100
|
+
fill: "none",
|
|
101
|
+
markerStart: startMarker ? `url(#${markerId}-${startMarker}-start)` : void 0,
|
|
102
|
+
markerEnd: endMarker ? `url(#${markerId}-${endMarker}-end)` : void 0
|
|
103
|
+
}
|
|
104
|
+
)
|
|
105
|
+
] });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// src/renderers/shape.tsx
|
|
109
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
110
|
+
var getOutlineDashArray = (outline) => {
|
|
111
|
+
const style = outline?.style;
|
|
112
|
+
const width = outline?.width ?? 1;
|
|
113
|
+
if (style === "dashed") return width <= 8 ? `${width * 5} ${width * 2.5}` : `${width * 5} ${width * 1.5}`;
|
|
114
|
+
if (style === "dotted") return width <= 8 ? `${width * 1.8} ${width * 1.6}` : `${width * 1.5} ${width * 1.2}`;
|
|
115
|
+
return void 0;
|
|
116
|
+
};
|
|
117
|
+
function renderShape(element, patternId) {
|
|
118
|
+
const viewWidth = element.viewBox?.[0] ?? element.width ?? 0;
|
|
119
|
+
const viewHeight = element.viewBox?.[1] ?? element.height ?? 0;
|
|
120
|
+
const outlineDashArray = getOutlineDashArray(element.outline);
|
|
121
|
+
const fill = element.pattern ? `url(#${patternId})` : element.fill || "transparent";
|
|
122
|
+
const text = element.text;
|
|
123
|
+
const verticalAlign = text?.align ?? "middle";
|
|
124
|
+
const justifyContent = verticalAlign === "top" ? "flex-start" : verticalAlign === "bottom" ? "flex-end" : "center";
|
|
125
|
+
return /* @__PURE__ */ jsxs2("div", { style: { position: "relative", width: "100%", height: "100%" }, children: [
|
|
126
|
+
/* @__PURE__ */ jsxs2("svg", { style: { position: "absolute", inset: 0 }, overflow: "visible", width: element.width, height: element.height, children: [
|
|
127
|
+
element.pattern && /* @__PURE__ */ jsx3("defs", { children: /* @__PURE__ */ jsx3(
|
|
128
|
+
"pattern",
|
|
129
|
+
{
|
|
130
|
+
id: patternId,
|
|
131
|
+
patternUnits: "userSpaceOnUse",
|
|
132
|
+
patternContentUnits: "userSpaceOnUse",
|
|
133
|
+
width: viewWidth,
|
|
134
|
+
height: viewHeight,
|
|
135
|
+
children: /* @__PURE__ */ jsx3("image", { href: element.pattern, width: viewWidth, height: viewHeight, preserveAspectRatio: "xMidYMid slice" })
|
|
136
|
+
}
|
|
137
|
+
) }),
|
|
138
|
+
/* @__PURE__ */ jsx3("g", { transform: `scale(${(element.width ?? 0) / viewWidth || 1}, ${(element.height ?? 0) / viewHeight || 1}) translate(0,0) matrix(1,0,0,1,0,0)`, children: /* @__PURE__ */ jsx3(
|
|
139
|
+
"path",
|
|
140
|
+
{
|
|
141
|
+
vectorEffect: "non-scaling-stroke",
|
|
142
|
+
strokeLinecap: "butt",
|
|
143
|
+
strokeMiterlimit: 8,
|
|
144
|
+
d: element.path || "",
|
|
145
|
+
fill,
|
|
146
|
+
stroke: element.outline?.color,
|
|
147
|
+
strokeWidth: element.outline?.width,
|
|
148
|
+
strokeDasharray: outlineDashArray
|
|
149
|
+
}
|
|
150
|
+
) })
|
|
151
|
+
] }),
|
|
152
|
+
text?.content && /* @__PURE__ */ jsx3(
|
|
153
|
+
"div",
|
|
154
|
+
{
|
|
155
|
+
style: {
|
|
156
|
+
position: "absolute",
|
|
157
|
+
inset: 0,
|
|
158
|
+
display: "flex",
|
|
159
|
+
flexDirection: "column",
|
|
160
|
+
justifyContent,
|
|
161
|
+
alignItems: "stretch",
|
|
162
|
+
color: text.defaultColor,
|
|
163
|
+
fontFamily: text.defaultFontName || void 0,
|
|
164
|
+
lineHeight: text.lineHeight,
|
|
165
|
+
pointerEvents: "none"
|
|
166
|
+
},
|
|
167
|
+
dangerouslySetInnerHTML: { __html: text.content }
|
|
168
|
+
}
|
|
169
|
+
)
|
|
170
|
+
] });
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// src/renderers/table.tsx
|
|
174
|
+
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
175
|
+
var parseFontSize = (value) => {
|
|
176
|
+
if (!value) return void 0;
|
|
177
|
+
const size = Number.parseFloat(value);
|
|
178
|
+
return Number.isFinite(size) ? `${size}px` : void 0;
|
|
179
|
+
};
|
|
180
|
+
var normalizeFontName = (value) => {
|
|
181
|
+
if (!value) return void 0;
|
|
182
|
+
return value.replace(/^"+|"+$/g, "");
|
|
183
|
+
};
|
|
184
|
+
var tableColor = (value) => {
|
|
185
|
+
if (!value) return void 0;
|
|
186
|
+
return value.startsWith("rgb") || value.startsWith("#") ? value : void 0;
|
|
187
|
+
};
|
|
188
|
+
var isPlaceholderCell = (cell) => {
|
|
189
|
+
if (!cell) return false;
|
|
190
|
+
const colspan = cell.colspan ?? 1;
|
|
191
|
+
const rowspan = cell.rowspan ?? 1;
|
|
192
|
+
if (colspan !== 1 || rowspan !== 1) return false;
|
|
193
|
+
const style = cell.style;
|
|
194
|
+
const hasStyle = Boolean(style?.fontname) || Boolean(style?.fontsize) || Boolean(style?.color) || Boolean(style?.backcolor);
|
|
195
|
+
return (cell.text ?? "").trim() === "" && !hasStyle;
|
|
196
|
+
};
|
|
197
|
+
var buildTableRows = (element) => {
|
|
198
|
+
const rows = element.data ?? [];
|
|
199
|
+
const colCount = element.colWidths?.length ?? 0;
|
|
200
|
+
const rowCells = [];
|
|
201
|
+
const skip = new Array(colCount).fill(0);
|
|
202
|
+
rows.forEach((row, rowIndex) => {
|
|
203
|
+
const cells = [];
|
|
204
|
+
let colIndex = 0;
|
|
205
|
+
let cellIndex = 0;
|
|
206
|
+
while (colIndex < colCount) {
|
|
207
|
+
if (skip[colIndex] > 0) {
|
|
208
|
+
skip[colIndex] -= 1;
|
|
209
|
+
if (isPlaceholderCell(row[cellIndex])) cellIndex += 1;
|
|
210
|
+
colIndex += 1;
|
|
211
|
+
continue;
|
|
212
|
+
}
|
|
213
|
+
const cell = row[cellIndex];
|
|
214
|
+
if (!cell) break;
|
|
215
|
+
cellIndex += 1;
|
|
216
|
+
const colSpan = cell.colspan ?? 1;
|
|
217
|
+
const rowSpan = cell.rowspan ?? 1;
|
|
218
|
+
if (rowSpan > 1) {
|
|
219
|
+
for (let i = 0; i < colSpan; i += 1) {
|
|
220
|
+
skip[colIndex + i] = rowSpan - 1;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (colSpan > 1) {
|
|
224
|
+
for (let i = 0; i < colSpan - 1; i += 1) {
|
|
225
|
+
if (isPlaceholderCell(row[cellIndex])) cellIndex += 1;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
cells.push({
|
|
229
|
+
key: cell.id ?? `${rowIndex}-${colIndex}-${cellIndex}`,
|
|
230
|
+
colSpan,
|
|
231
|
+
rowSpan,
|
|
232
|
+
text: cell.text ?? "",
|
|
233
|
+
style: cell.style
|
|
234
|
+
});
|
|
235
|
+
colIndex += colSpan;
|
|
236
|
+
}
|
|
237
|
+
rowCells.push(cells);
|
|
238
|
+
});
|
|
239
|
+
return rowCells;
|
|
240
|
+
};
|
|
241
|
+
function renderTable(element) {
|
|
242
|
+
const colWidths = element.colWidths ?? [];
|
|
243
|
+
const rows = buildTableRows(element);
|
|
244
|
+
const rowCount = rows.length || 1;
|
|
245
|
+
const baseRowHeight = (element.height ?? 0) / rowCount;
|
|
246
|
+
const rowHeight = element.cellMinHeight ? Math.max(element.cellMinHeight, baseRowHeight) : baseRowHeight;
|
|
247
|
+
return /* @__PURE__ */ jsx4("div", { style: { width: "100%", height: "100%" }, children: /* @__PURE__ */ jsxs3(
|
|
248
|
+
"table",
|
|
249
|
+
{
|
|
250
|
+
style: {
|
|
251
|
+
width: "100%",
|
|
252
|
+
height: "100%",
|
|
253
|
+
tableLayout: "fixed",
|
|
254
|
+
borderCollapse: "collapse",
|
|
255
|
+
border: element.outline ? `${element.outline.width ?? 1}px solid ${element.outline.color ?? "#000"}` : void 0
|
|
256
|
+
},
|
|
257
|
+
children: [
|
|
258
|
+
colWidths.length > 0 && /* @__PURE__ */ jsx4("colgroup", { children: colWidths.map((width, index) => /* @__PURE__ */ jsx4("col", { style: { width: `${width * 100}%` } }, `col-${index}`)) }),
|
|
259
|
+
/* @__PURE__ */ jsx4("tbody", { children: rows.map((row, rowIndex) => /* @__PURE__ */ jsx4("tr", { style: { height: rowHeight }, children: row.map((cell) => /* @__PURE__ */ jsx4(
|
|
260
|
+
"td",
|
|
261
|
+
{
|
|
262
|
+
colSpan: cell.colSpan,
|
|
263
|
+
rowSpan: cell.rowSpan,
|
|
264
|
+
style: {
|
|
265
|
+
border: element.outline ? `${element.outline.width ?? 1}px solid ${element.outline.color ?? "#000"}` : "1px solid #ddd",
|
|
266
|
+
background: tableColor(cell.style?.backcolor),
|
|
267
|
+
padding: "6px 8px",
|
|
268
|
+
textAlign: cell.style?.align ?? "left",
|
|
269
|
+
color: tableColor(cell.style?.color),
|
|
270
|
+
fontFamily: normalizeFontName(cell.style?.fontname),
|
|
271
|
+
fontSize: parseFontSize(cell.style?.fontsize),
|
|
272
|
+
verticalAlign: "middle"
|
|
273
|
+
},
|
|
274
|
+
children: cell.text
|
|
275
|
+
},
|
|
276
|
+
cell.key
|
|
277
|
+
)) }, `row-${rowIndex}`)) })
|
|
278
|
+
]
|
|
279
|
+
}
|
|
280
|
+
) });
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// src/renderers/text.tsx
|
|
284
|
+
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
285
|
+
function renderText(element) {
|
|
286
|
+
const paragraphStyle = element.paragraphSpace !== void 0 ? { ["--paragraphSpace"]: `${element.paragraphSpace}px` } : void 0;
|
|
287
|
+
return /* @__PURE__ */ jsx5(
|
|
288
|
+
"div",
|
|
289
|
+
{
|
|
290
|
+
style: {
|
|
291
|
+
width: "100%",
|
|
292
|
+
height: "100%",
|
|
293
|
+
padding: 10,
|
|
294
|
+
lineHeight: element.lineHeight ?? 1.5,
|
|
295
|
+
letterSpacing: `${element.wordSpace ?? 0}px`,
|
|
296
|
+
wordBreak: "break-word",
|
|
297
|
+
fontFamily: element.defaultFontName || "sans-serif",
|
|
298
|
+
color: element.defaultColor,
|
|
299
|
+
writingMode: element.vertical ? "vertical-rl" : void 0,
|
|
300
|
+
...paragraphStyle
|
|
301
|
+
},
|
|
302
|
+
dangerouslySetInnerHTML: { __html: element.content || "" }
|
|
303
|
+
}
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// src/renderers/index.tsx
|
|
308
|
+
function renderElement(element, markerId) {
|
|
309
|
+
if (element.type === "shape") return renderShape(element, `shape-${markerId}`);
|
|
310
|
+
if (element.type === "line") return renderLine(element, markerId);
|
|
311
|
+
if (element.type === "text") return renderText(element);
|
|
312
|
+
if (element.type === "image") return renderImage(element);
|
|
313
|
+
if (element.type === "table") return renderTable(element);
|
|
314
|
+
return null;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// src/utils/elementSize.ts
|
|
318
|
+
function getElementSize(element) {
|
|
319
|
+
if (element.type === "line" && element.start && element.end) {
|
|
320
|
+
return {
|
|
321
|
+
width: Math.max(Math.abs(element.end[0] - element.start[0]), MIN_LINE_SIZE),
|
|
322
|
+
height: Math.max(Math.abs(element.end[1] - element.start[1]), MIN_LINE_SIZE)
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
return {
|
|
326
|
+
width: element.width ?? 0,
|
|
327
|
+
height: element.height ?? 0
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// src/utils/elementStyle.ts
|
|
332
|
+
var getShadowFilter = (shadow) => {
|
|
333
|
+
if (!shadow) return void 0;
|
|
334
|
+
const h = shadow.h ?? 0;
|
|
335
|
+
const v = shadow.v ?? 0;
|
|
336
|
+
const blur = shadow.blur ?? 0;
|
|
337
|
+
const color = shadow.color ?? "#000";
|
|
338
|
+
return `drop-shadow(${h}px ${v}px ${blur}px ${color})`;
|
|
339
|
+
};
|
|
340
|
+
var getFlipTransform = (flipH, flipV) => {
|
|
341
|
+
const transforms = [flipH ? "scaleX(-1)" : "", flipV ? "scaleY(-1)" : ""].filter(Boolean).join(" ");
|
|
342
|
+
return transforms || void 0;
|
|
343
|
+
};
|
|
344
|
+
|
|
345
|
+
// src/PPTXPreviewer.tsx
|
|
346
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
347
|
+
function PPTXPreviewer({ slide, className }) {
|
|
348
|
+
return /* @__PURE__ */ jsxs4(
|
|
349
|
+
"div",
|
|
350
|
+
{
|
|
351
|
+
className,
|
|
352
|
+
style: {
|
|
353
|
+
position: "relative",
|
|
354
|
+
width: "100%",
|
|
355
|
+
height: "100%",
|
|
356
|
+
overflow: "hidden",
|
|
357
|
+
fontSize: 16,
|
|
358
|
+
lineHeight: "normal"
|
|
359
|
+
},
|
|
360
|
+
children: [
|
|
361
|
+
slide.background?.color ? /* @__PURE__ */ jsx6(
|
|
362
|
+
"div",
|
|
363
|
+
{
|
|
364
|
+
style: {
|
|
365
|
+
position: "absolute",
|
|
366
|
+
inset: 0,
|
|
367
|
+
backgroundColor: slide.background.color
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
) : null,
|
|
371
|
+
(slide.elements ?? []).map((element, elementIndex) => {
|
|
372
|
+
const size = getElementSize(element);
|
|
373
|
+
const markerId = element.id ?? `line-${elementIndex}`;
|
|
374
|
+
return /* @__PURE__ */ jsx6(
|
|
375
|
+
"div",
|
|
376
|
+
{
|
|
377
|
+
style: {
|
|
378
|
+
position: "absolute",
|
|
379
|
+
left: element.left ?? 0,
|
|
380
|
+
top: element.top ?? 0,
|
|
381
|
+
width: size.width,
|
|
382
|
+
height: size.height
|
|
383
|
+
},
|
|
384
|
+
children: /* @__PURE__ */ jsx6(
|
|
385
|
+
"div",
|
|
386
|
+
{
|
|
387
|
+
style: {
|
|
388
|
+
width: "100%",
|
|
389
|
+
height: "100%",
|
|
390
|
+
transform: element.rotate ? `rotate(${element.rotate}deg)` : void 0
|
|
391
|
+
},
|
|
392
|
+
children: /* @__PURE__ */ jsx6(
|
|
393
|
+
"div",
|
|
394
|
+
{
|
|
395
|
+
style: {
|
|
396
|
+
position: "relative",
|
|
397
|
+
width: "100%",
|
|
398
|
+
height: "100%",
|
|
399
|
+
opacity: element.opacity ?? 1,
|
|
400
|
+
filter: getShadowFilter(element.shadow),
|
|
401
|
+
transform: getFlipTransform(element.flipH, element.flipV),
|
|
402
|
+
transformOrigin: "center",
|
|
403
|
+
color: element.defaultColor,
|
|
404
|
+
fontFamily: element.defaultFontName
|
|
405
|
+
},
|
|
406
|
+
children: renderElement(element, markerId)
|
|
407
|
+
}
|
|
408
|
+
)
|
|
409
|
+
}
|
|
410
|
+
)
|
|
411
|
+
},
|
|
412
|
+
element.id ?? elementIndex
|
|
413
|
+
);
|
|
414
|
+
})
|
|
415
|
+
]
|
|
416
|
+
}
|
|
417
|
+
);
|
|
418
|
+
}
|
|
419
|
+
export {
|
|
420
|
+
PPTXPreviewer
|
|
421
|
+
};
|
|
422
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/renderers/image.tsx","../src/constants.ts","../src/renderers/line.tsx","../src/renderers/shape.tsx","../src/renderers/table.tsx","../src/renderers/text.tsx","../src/renderers/index.tsx","../src/utils/elementSize.ts","../src/utils/elementStyle.ts","../src/PPTXPreviewer.tsx"],"sourcesContent":["import type { SlideElement } from '../types';\n\nexport function renderImage(element: SlideElement) {\n const filterStr = [\n element.filters?.grayscale ? `grayscale(${element.filters.grayscale})` : '',\n element.filters?.opacity ? `opacity(${element.filters.opacity})` : '',\n element.filters?.blur ? `blur(${element.filters.blur})` : ''\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n borderRadius: element.clip?.shape === 'ellipse' ? '50%' : element.radius ? `${element.radius}px` : undefined,\n filter: filterStr || undefined\n }}\n >\n <img src={element.src || ''} alt='' style={{ width: '100%', height: '100%', objectFit: 'cover' }} />\n </div>\n );\n}\n","export const MIN_LINE_SIZE = 24;\n","import { MIN_LINE_SIZE } from '../constants';\nimport type { SlideElement } from '../types';\n\ntype LineElement = SlideElement & { start: [number, number]; end: [number, number] };\ntype LinePointType = '' | 'arrow' | 'dot';\n\nconst getLineDashArray = (width: number, style?: string) => {\n if (style === 'dashed') return width <= 8 ? `${width * 5} ${width * 2.5}` : `${width * 5} ${width * 1.5}`;\n if (style === 'dotted') return width <= 8 ? `${width * 1.8} ${width * 1.6}` : `${width * 1.5} ${width * 1.2}`;\n return '0 0';\n};\n\nconst getLinePath = (element: LineElement) => {\n const start = element.start.join(',');\n const end = element.end.join(',');\n\n if (element.broken) return `M${start} L${element.broken.join(',')} L${end}`;\n\n if (element.broken2) {\n const width = Math.abs(element.end[0] - element.start[0]);\n const height = Math.abs(element.end[1] - element.start[1]);\n if (width >= height) {\n return `M${start} L${element.broken2[0]},${element.start[1]} L${element.broken2[0]},${element.end[1]} L${end}`;\n }\n return `M${start} L${element.start[0]},${element.broken2[1]} L${element.end[0]},${element.broken2[1]} L${end}`;\n }\n\n if (element.curve) return `M${start} Q${element.curve.join(',')} ${end}`;\n\n if (element.cubic) {\n const [c1, c2] = element.cubic;\n return `M${start} C${c1.join(',')} ${c2.join(',')} ${end}`;\n }\n\n return `M${start} L${end}`;\n};\n\nfunction renderLineMarker(props: {\n id: string;\n position: 'start' | 'end';\n type: 'arrow' | 'dot';\n baseSize: number;\n color?: string;\n}) {\n const pathMap = {\n dot: 'm0 5a5 5 0 1 0 10 0a5 5 0 1 0 -10 0z',\n arrow: 'M0,0 L10,5 0,10 Z'\n };\n const rotateMap: Record<string, number> = {\n 'arrow-start': 180,\n 'arrow-end': 0\n };\n const size = props.baseSize < 2 ? 2 : props.baseSize;\n const rotate = rotateMap[`${props.type}-${props.position}`] || 0;\n\n return (\n <marker\n id={`${props.id}-${props.type}-${props.position}`}\n markerUnits='userSpaceOnUse'\n orient='auto'\n markerWidth={size * 3}\n markerHeight={size * 3}\n refX={size * 1.5}\n refY={size * 1.5}\n >\n <path d={pathMap[props.type]} fill={props.color} transform={`scale(${size * 0.3}, ${size * 0.3}) rotate(${rotate}, 5, 5)`} />\n </marker>\n );\n}\n\nexport function renderLine(element: SlideElement, markerId: string) {\n if (!element.start || !element.end) return null;\n\n const width = Math.max(Math.abs(element.start[0] - element.end[0]), MIN_LINE_SIZE);\n const height = Math.max(Math.abs(element.start[1] - element.end[1]), MIN_LINE_SIZE);\n const lineWidth = element.width ?? 1;\n const dashArray = getLineDashArray(lineWidth, element.style);\n const path = getLinePath(element as LineElement);\n\n const points = element.points as [LinePointType, LinePointType] | undefined;\n const startMarker = points?.[0] ? points[0] : undefined;\n const endMarker = points?.[1] ? points[1] : undefined;\n\n return (\n <svg overflow='visible' width={width} height={height}>\n <defs>\n {startMarker && renderLineMarker({ id: markerId, position: 'start', type: startMarker, color: element.color, baseSize: lineWidth })}\n {endMarker && renderLineMarker({ id: markerId, position: 'end', type: endMarker, color: element.color, baseSize: lineWidth })}\n </defs>\n <path\n d={path}\n stroke={element.color ?? '#000'}\n strokeWidth={lineWidth}\n strokeDasharray={dashArray}\n fill='none'\n markerStart={startMarker ? `url(#${markerId}-${startMarker}-start)` : undefined}\n markerEnd={endMarker ? `url(#${markerId}-${endMarker}-end)` : undefined}\n />\n </svg>\n );\n}\n","import type { SlideElement } from '../types';\n\nconst getOutlineDashArray = (outline?: SlideElement['outline']) => {\n const style = outline?.style;\n const width = outline?.width ?? 1;\n if (style === 'dashed') return width <= 8 ? `${width * 5} ${width * 2.5}` : `${width * 5} ${width * 1.5}`;\n if (style === 'dotted') return width <= 8 ? `${width * 1.8} ${width * 1.6}` : `${width * 1.5} ${width * 1.2}`;\n return undefined;\n};\n\nexport function renderShape(element: SlideElement, patternId: string) {\n const viewWidth = element.viewBox?.[0] ?? element.width ?? 0;\n const viewHeight = element.viewBox?.[1] ?? element.height ?? 0;\n const outlineDashArray = getOutlineDashArray(element.outline);\n const fill = element.pattern ? `url(#${patternId})` : element.fill || 'transparent';\n\n const text = element.text;\n const verticalAlign = text?.align ?? 'middle';\n const justifyContent = verticalAlign === 'top' ? 'flex-start' : verticalAlign === 'bottom' ? 'flex-end' : 'center';\n\n return (\n <div style={{ position: 'relative', width: '100%', height: '100%' }}>\n <svg style={{ position: 'absolute', inset: 0 }} overflow='visible' width={element.width} height={element.height}>\n {element.pattern && (\n <defs>\n <pattern\n id={patternId}\n patternUnits='userSpaceOnUse'\n patternContentUnits='userSpaceOnUse'\n width={viewWidth}\n height={viewHeight}\n >\n <image href={element.pattern} width={viewWidth} height={viewHeight} preserveAspectRatio='xMidYMid slice' />\n </pattern>\n </defs>\n )}\n <g transform={`scale(${(element.width ?? 0) / viewWidth || 1}, ${(element.height ?? 0) / viewHeight || 1}) translate(0,0) matrix(1,0,0,1,0,0)`}>\n <path\n vectorEffect='non-scaling-stroke'\n strokeLinecap='butt'\n strokeMiterlimit={8}\n d={element.path || ''}\n fill={fill}\n stroke={element.outline?.color}\n strokeWidth={element.outline?.width}\n strokeDasharray={outlineDashArray}\n />\n </g>\n </svg>\n\n {text?.content && (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n flexDirection: 'column',\n justifyContent,\n alignItems: 'stretch',\n color: text.defaultColor,\n fontFamily: text.defaultFontName || undefined,\n lineHeight: text.lineHeight,\n pointerEvents: 'none'\n }}\n dangerouslySetInnerHTML={{ __html: text.content }}\n />\n )}\n </div>\n );\n}\n","import { type CSSProperties } from 'react';\nimport type { SlideElement } from '../types';\n\ntype TableCellData = NonNullable<NonNullable<SlideElement['data']>[number][number]>;\ntype TableCell = {\n key: string;\n colSpan: number;\n rowSpan: number;\n text: string;\n style: TableCellData['style'];\n};\n\nconst parseFontSize = (value?: string) => {\n if (!value) return undefined;\n const size = Number.parseFloat(value);\n return Number.isFinite(size) ? `${size}px` : undefined;\n};\n\nconst normalizeFontName = (value?: string) => {\n if (!value) return undefined;\n return value.replace(/^\"+|\"+$/g, '');\n};\n\nconst tableColor = (value?: string) => {\n if (!value) return undefined;\n return value.startsWith('rgb') || value.startsWith('#') ? value : undefined;\n};\n\nconst isPlaceholderCell = (cell: TableCellData | undefined) => {\n if (!cell) return false;\n const colspan = cell.colspan ?? 1;\n const rowspan = cell.rowspan ?? 1;\n if (colspan !== 1 || rowspan !== 1) return false;\n\n const style = cell.style;\n const hasStyle = Boolean(style?.fontname) || Boolean(style?.fontsize) || Boolean(style?.color) || Boolean(style?.backcolor);\n return (cell.text ?? '').trim() === '' && !hasStyle;\n};\n\nconst buildTableRows = (element: SlideElement) => {\n const rows = element.data ?? [];\n const colCount = element.colWidths?.length ?? 0;\n const rowCells: TableCell[][] = [];\n const skip = new Array(colCount).fill(0);\n\n rows.forEach((row, rowIndex) => {\n const cells: TableCell[] = [];\n let colIndex = 0;\n let cellIndex = 0;\n\n while (colIndex < colCount) {\n if (skip[colIndex] > 0) {\n skip[colIndex] -= 1;\n if (isPlaceholderCell(row[cellIndex])) cellIndex += 1;\n colIndex += 1;\n continue;\n }\n\n const cell = row[cellIndex];\n if (!cell) break;\n cellIndex += 1;\n\n const colSpan = cell.colspan ?? 1;\n const rowSpan = cell.rowspan ?? 1;\n\n if (rowSpan > 1) {\n for (let i = 0; i < colSpan; i += 1) {\n skip[colIndex + i] = rowSpan - 1;\n }\n }\n\n if (colSpan > 1) {\n for (let i = 0; i < colSpan - 1; i += 1) {\n if (isPlaceholderCell(row[cellIndex])) cellIndex += 1;\n }\n }\n\n cells.push({\n key: cell.id ?? `${rowIndex}-${colIndex}-${cellIndex}`,\n colSpan,\n rowSpan,\n text: cell.text ?? '',\n style: cell.style\n });\n\n colIndex += colSpan;\n }\n\n rowCells.push(cells);\n });\n\n return rowCells;\n};\n\nexport function renderTable(element: SlideElement) {\n const colWidths = element.colWidths ?? [];\n const rows = buildTableRows(element);\n const rowCount = rows.length || 1;\n const baseRowHeight = (element.height ?? 0) / rowCount;\n const rowHeight = element.cellMinHeight ? Math.max(element.cellMinHeight, baseRowHeight) : baseRowHeight;\n\n return (\n <div style={{ width: '100%', height: '100%' }}>\n <table\n style={{\n width: '100%',\n height: '100%',\n tableLayout: 'fixed',\n borderCollapse: 'collapse',\n border: element.outline ? `${element.outline.width ?? 1}px solid ${element.outline.color ?? '#000'}` : undefined\n }}\n >\n {colWidths.length > 0 && (\n <colgroup>\n {colWidths.map((width, index) => (\n <col key={`col-${index}`} style={{ width: `${width * 100}%` }} />\n ))}\n </colgroup>\n )}\n <tbody>\n {rows.map((row, rowIndex) => (\n <tr key={`row-${rowIndex}`} style={{ height: rowHeight }}>\n {row.map((cell) => (\n <td\n key={cell.key}\n colSpan={cell.colSpan}\n rowSpan={cell.rowSpan}\n style={{\n border: element.outline ? `${element.outline.width ?? 1}px solid ${element.outline.color ?? '#000'}` : '1px solid #ddd',\n background: tableColor(cell.style?.backcolor),\n padding: '6px 8px',\n textAlign: (cell.style?.align as CSSProperties['textAlign']) ?? 'left',\n color: tableColor(cell.style?.color),\n fontFamily: normalizeFontName(cell.style?.fontname),\n fontSize: parseFontSize(cell.style?.fontsize),\n verticalAlign: 'middle'\n }}\n >\n {cell.text}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n );\n}\n","import { type CSSProperties } from 'react';\nimport type { SlideElement } from '../types';\n\nexport function renderText(element: SlideElement) {\n const paragraphStyle =\n element.paragraphSpace !== undefined\n ? ({ ['--paragraphSpace' as string]: `${element.paragraphSpace}px` } as CSSProperties)\n : undefined;\n\n return (\n <div\n style={{\n width: '100%',\n height: '100%',\n padding: 10,\n lineHeight: element.lineHeight ?? 1.5,\n letterSpacing: `${element.wordSpace ?? 0}px`,\n wordBreak: 'break-word',\n fontFamily: element.defaultFontName || 'sans-serif',\n color: element.defaultColor,\n writingMode: element.vertical ? 'vertical-rl' : undefined,\n ...paragraphStyle\n }}\n dangerouslySetInnerHTML={{ __html: element.content || '' }}\n />\n );\n}\n","import type { SlideElement } from '../types';\nimport { renderImage } from './image';\nimport { renderLine } from './line';\nimport { renderShape } from './shape';\nimport { renderTable } from './table';\nimport { renderText } from './text';\n\nexport function renderElement(element: SlideElement, markerId: string) {\n if (element.type === 'shape') return renderShape(element, `shape-${markerId}`);\n if (element.type === 'line') return renderLine(element, markerId);\n if (element.type === 'text') return renderText(element);\n if (element.type === 'image') return renderImage(element);\n if (element.type === 'table') return renderTable(element);\n return null;\n}\n","import { MIN_LINE_SIZE } from '../constants';\nimport type { SlideElement } from '../types';\n\nexport function getElementSize(element: SlideElement): { width: number; height: number } {\n if (element.type === 'line' && element.start && element.end) {\n return {\n width: Math.max(Math.abs(element.end[0] - element.start[0]), MIN_LINE_SIZE),\n height: Math.max(Math.abs(element.end[1] - element.start[1]), MIN_LINE_SIZE)\n };\n }\n\n return {\n width: element.width ?? 0,\n height: element.height ?? 0\n };\n}\n","import type { SlideElement } from '../types';\n\nexport const getShadowFilter = (shadow?: SlideElement['shadow']) => {\n if (!shadow) return undefined;\n const h = shadow.h ?? 0;\n const v = shadow.v ?? 0;\n const blur = shadow.blur ?? 0;\n const color = shadow.color ?? '#000';\n return `drop-shadow(${h}px ${v}px ${blur}px ${color})`;\n};\n\nexport const getFlipTransform = (flipH?: boolean, flipV?: boolean) => {\n const transforms = [flipH ? 'scaleX(-1)' : '', flipV ? 'scaleY(-1)' : '']\n .filter(Boolean)\n .join(' ');\n return transforms || undefined;\n};\n","import { renderElement } from './renderers';\nimport type { PPTXPreviewerProps } from './types';\nimport { getElementSize } from './utils/elementSize';\nimport { getFlipTransform, getShadowFilter } from './utils/elementStyle';\n\nexport function PPTXPreviewer({ slide, className }: PPTXPreviewerProps) {\n return (\n <div\n className={className}\n style={{\n position: 'relative',\n width: '100%',\n height: '100%',\n overflow: 'hidden',\n fontSize: 16,\n lineHeight: 'normal'\n }}\n >\n {slide.background?.color ? (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n backgroundColor: slide.background.color\n }}\n />\n ) : null}\n\n {(slide.elements ?? []).map((element, elementIndex) => {\n const size = getElementSize(element);\n const markerId = element.id ?? `line-${elementIndex}`;\n\n return (\n <div\n key={element.id ?? elementIndex}\n style={{\n position: 'absolute',\n left: element.left ?? 0,\n top: element.top ?? 0,\n width: size.width,\n height: size.height\n }}\n >\n <div\n style={{\n width: '100%',\n height: '100%',\n transform: element.rotate ? `rotate(${element.rotate}deg)` : undefined\n }}\n >\n <div\n style={{\n position: 'relative',\n width: '100%',\n height: '100%',\n opacity: element.opacity ?? 1,\n filter: getShadowFilter(element.shadow),\n transform: getFlipTransform(element.flipH, element.flipV),\n transformOrigin: 'center',\n color: element.defaultColor,\n fontFamily: element.defaultFontName\n }}\n >\n {renderElement(element, markerId)}\n </div>\n </div>\n </div>\n );\n })}\n </div>\n );\n}\n"],"mappings":"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","names":["jsx","jsx","jsxs","jsx","jsxs","jsx","jsx","jsxs"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "pptx-previewer",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A React component to preview PPTX JSON slides in the browser.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"module": "dist/index.mjs",
|
|
8
|
+
"types": "dist/index.d.ts",
|
|
9
|
+
"homepage": "https://json2pptx.henryge.com/",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/gezhiheng/json2ppt-editor/"
|
|
13
|
+
},
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"import": "./dist/index.mjs",
|
|
18
|
+
"require": "./dist/index.js",
|
|
19
|
+
"default": "./dist/index.mjs"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"typesVersions": {
|
|
23
|
+
"*": {
|
|
24
|
+
"*": [
|
|
25
|
+
"dist/index.d.ts"
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"dist",
|
|
31
|
+
"README.md"
|
|
32
|
+
],
|
|
33
|
+
"sideEffects": false,
|
|
34
|
+
"scripts": {
|
|
35
|
+
"build": "tsup",
|
|
36
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
37
|
+
"prepublishOnly": "pnpm run build"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"react": ">=18"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/react": "^18.3.3",
|
|
44
|
+
"tsup": "^8.0.1",
|
|
45
|
+
"typescript": "^5.3.3"
|
|
46
|
+
}
|
|
47
|
+
}
|