pptx-previewer 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,14 +1,16 @@
1
1
  # pptx-previewer
2
2
 
3
- `pptx-previewer` is a React component for rendering PPTX-like slide JSON in the browser.
3
+ `pptx-previewer` is a React component for rendering `json2pptx-schema`-style slide JSON in the browser.
4
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:
5
+ It is designed to work with normalized deck JSON, including output from `ppt2json`, and supports common slide elements:
6
6
 
7
7
  - `shape`
8
8
  - `line`
9
9
  - `text`
10
10
  - `image`
11
11
  - `table`
12
+ - solid / gradient / image backgrounds and fills
13
+ - image clipping via `clip.range`
12
14
 
13
15
  ## Installation
14
16
 
@@ -22,7 +24,7 @@ pnpm add pptx-previewer
22
24
  import { PPTXPreviewer, type Slide } from 'pptx-previewer';
23
25
 
24
26
  const slide: Slide = {
25
- background: { color: '#ffffff' },
27
+ background: { type: 'solid', color: '#ffffff' },
26
28
  elements: [
27
29
  {
28
30
  type: 'text',
@@ -84,4 +86,5 @@ Build output is generated in `dist/`:
84
86
 
85
87
  - This package is `react` peer-dependent (`>=18`).
86
88
  - Element coordinates, sizes, and style semantics follow the input JSON schema.
89
+ - Backgrounds and fills follow the explicit `solid | gradient | image` union used by `json2pptx-schema`.
87
90
  - Text content is rendered via `dangerouslySetInnerHTML`; sanitize external/untrusted HTML before rendering.
package/dist/index.d.mts CHANGED
@@ -1,5 +1,25 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
 
3
+ type FillGradientStop = {
4
+ pos?: number;
5
+ color?: string;
6
+ };
7
+ type FillGradient = {
8
+ type?: string;
9
+ rotate?: number;
10
+ colors?: FillGradientStop[];
11
+ };
12
+ type ElementFill = {
13
+ type: 'solid';
14
+ color?: string;
15
+ } | {
16
+ type: 'gradient';
17
+ gradient?: FillGradient;
18
+ } | {
19
+ type: 'image';
20
+ src?: string;
21
+ opacity?: number;
22
+ };
3
23
  type SlideElement = {
4
24
  type: string;
5
25
  id?: string;
@@ -9,8 +29,7 @@ type SlideElement = {
9
29
  width?: number;
10
30
  height?: number;
11
31
  rotate?: number;
12
- fill?: string;
13
- pattern?: string;
32
+ fill?: ElementFill;
14
33
  path?: string;
15
34
  viewBox?: [number, number];
16
35
  pathFormula?: string;
@@ -86,11 +105,7 @@ type Slide = {
86
105
  id?: string;
87
106
  elements?: SlideElement[];
88
107
  remark?: string;
89
- background?: {
90
- type?: string;
91
- color?: string;
92
- src?: string;
93
- };
108
+ background?: ElementFill;
94
109
  type?: string;
95
110
  };
96
111
  type PPTXPreviewerProps = {
package/dist/index.d.ts CHANGED
@@ -1,5 +1,25 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
 
3
+ type FillGradientStop = {
4
+ pos?: number;
5
+ color?: string;
6
+ };
7
+ type FillGradient = {
8
+ type?: string;
9
+ rotate?: number;
10
+ colors?: FillGradientStop[];
11
+ };
12
+ type ElementFill = {
13
+ type: 'solid';
14
+ color?: string;
15
+ } | {
16
+ type: 'gradient';
17
+ gradient?: FillGradient;
18
+ } | {
19
+ type: 'image';
20
+ src?: string;
21
+ opacity?: number;
22
+ };
3
23
  type SlideElement = {
4
24
  type: string;
5
25
  id?: string;
@@ -9,8 +29,7 @@ type SlideElement = {
9
29
  width?: number;
10
30
  height?: number;
11
31
  rotate?: number;
12
- fill?: string;
13
- pattern?: string;
32
+ fill?: ElementFill;
14
33
  path?: string;
15
34
  viewBox?: [number, number];
16
35
  pathFormula?: string;
@@ -86,11 +105,7 @@ type Slide = {
86
105
  id?: string;
87
106
  elements?: SlideElement[];
88
107
  remark?: string;
89
- background?: {
90
- type?: string;
91
- color?: string;
92
- src?: string;
93
- };
108
+ background?: ElementFill;
94
109
  type?: string;
95
110
  };
96
111
  type PPTXPreviewerProps = {
package/dist/index.js CHANGED
@@ -36,6 +36,13 @@ function renderImage(element) {
36
36
  element.filters?.opacity ? `opacity(${element.filters.opacity})` : "",
37
37
  element.filters?.blur ? `blur(${element.filters.blur})` : ""
38
38
  ].filter(Boolean).join(" ");
39
+ const clipRange = element.clip?.range;
40
+ const startX = clipRange?.[0]?.[0] ?? 0;
41
+ const startY = clipRange?.[0]?.[1] ?? 0;
42
+ const endX = clipRange?.[1]?.[0] ?? 100;
43
+ const endY = clipRange?.[1]?.[1] ?? 100;
44
+ const rangeWidth = Math.max(1, endX - startX);
45
+ const rangeHeight = Math.max(1, endY - startY);
39
46
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
40
47
  "div",
41
48
  {
@@ -44,9 +51,23 @@ function renderImage(element) {
44
51
  height: "100%",
45
52
  overflow: "hidden",
46
53
  borderRadius: element.clip?.shape === "ellipse" ? "50%" : element.radius ? `${element.radius}px` : void 0,
47
- filter: filterStr || void 0
54
+ filter: filterStr || void 0,
55
+ position: "relative"
48
56
  },
49
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: element.src || "", alt: "", style: { width: "100%", height: "100%", objectFit: "cover" } })
57
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
58
+ "img",
59
+ {
60
+ src: element.src || "",
61
+ alt: "",
62
+ style: {
63
+ position: "absolute",
64
+ width: `${1e4 / rangeWidth}%`,
65
+ height: `${1e4 / rangeHeight}%`,
66
+ left: `${-startX / rangeWidth * 100}%`,
67
+ top: `${-startY / rangeHeight * 100}%`
68
+ }
69
+ }
70
+ )
50
71
  }
51
72
  );
52
73
  }
@@ -135,6 +156,38 @@ function renderLine(element, markerId) {
135
156
  ] });
136
157
  }
137
158
 
159
+ // src/utils/fill.ts
160
+ function buildGradientStops(gradient) {
161
+ return (gradient?.colors ?? []).map((stop) => `${stop.color ?? "#FFFFFF"} ${stop.pos ?? 0}%`).join(", ");
162
+ }
163
+ function getCssBackground(fill) {
164
+ if (!fill) return void 0;
165
+ if (fill.type === "solid") {
166
+ return fill.color;
167
+ }
168
+ if (fill.type === "image") {
169
+ return fill.src ? `url("${fill.src}") center / cover no-repeat` : void 0;
170
+ }
171
+ const stops = buildGradientStops(fill.gradient);
172
+ if (!stops) return void 0;
173
+ const gradientType = fill.gradient?.type === "linear" || fill.gradient?.type === "line" ? "linear" : "radial";
174
+ if (gradientType === "radial") {
175
+ return `radial-gradient(circle, ${stops})`;
176
+ }
177
+ return `linear-gradient(${(fill.gradient?.rotate ?? 0) + 90}deg, ${stops})`;
178
+ }
179
+ function getSvgLinearGradientCoordinates(rotate = 0) {
180
+ const radians = rotate * Math.PI / 180;
181
+ const dx = Math.cos(radians) / 2;
182
+ const dy = Math.sin(radians) / 2;
183
+ return {
184
+ x1: 0.5 - dx,
185
+ y1: 0.5 - dy,
186
+ x2: 0.5 + dx,
187
+ y2: 0.5 + dy
188
+ };
189
+ }
190
+
138
191
  // src/renderers/shape.tsx
139
192
  var import_jsx_runtime3 = require("react/jsx-runtime");
140
193
  var getOutlineDashArray = (outline) => {
@@ -148,13 +201,21 @@ function renderShape(element, patternId) {
148
201
  const viewWidth = element.viewBox?.[0] ?? element.width ?? 0;
149
202
  const viewHeight = element.viewBox?.[1] ?? element.height ?? 0;
150
203
  const outlineDashArray = getOutlineDashArray(element.outline);
151
- const fill = element.pattern ? `url(#${patternId})` : element.fill || "transparent";
204
+ const gradientId = `${patternId}-gradient`;
205
+ let fill = "transparent";
206
+ if (element.fill?.type === "solid") {
207
+ fill = element.fill.color || "transparent";
208
+ } else if (element.fill?.type === "image" && element.fill.src) {
209
+ fill = `url(#${patternId})`;
210
+ } else if (element.fill?.type === "gradient" && element.fill.gradient?.colors?.length) {
211
+ fill = `url(#${gradientId})`;
212
+ }
152
213
  const text = element.text;
153
214
  const verticalAlign = text?.align ?? "middle";
154
215
  const justifyContent = verticalAlign === "top" ? "flex-start" : verticalAlign === "bottom" ? "flex-end" : "center";
155
216
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { style: { position: "relative", width: "100%", height: "100%" }, children: [
156
217
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { style: { position: "absolute", inset: 0 }, overflow: "visible", width: element.width, height: element.height, children: [
157
- element.pattern && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
218
+ element.fill?.type === "image" && element.fill.src && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
158
219
  "pattern",
159
220
  {
160
221
  id: patternId,
@@ -162,9 +223,24 @@ function renderShape(element, patternId) {
162
223
  patternContentUnits: "userSpaceOnUse",
163
224
  width: viewWidth,
164
225
  height: viewHeight,
165
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("image", { href: element.pattern, width: viewWidth, height: viewHeight, preserveAspectRatio: "xMidYMid slice" })
226
+ children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
227
+ "image",
228
+ {
229
+ href: element.fill.src,
230
+ width: viewWidth,
231
+ height: viewHeight,
232
+ preserveAspectRatio: "xMidYMid slice",
233
+ opacity: element.fill.opacity ?? 1
234
+ }
235
+ )
166
236
  }
167
237
  ) }),
238
+ element.fill?.type === "gradient" && element.fill.gradient?.colors?.length ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("defs", { children: (() => {
239
+ const { x1, y1, x2, y2 } = getSvgLinearGradientCoordinates(
240
+ element.fill?.gradient?.rotate ?? 0
241
+ );
242
+ return element.fill.gradient?.type === "linear" || element.fill.gradient?.type === "line" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("linearGradient", { id: gradientId, x1, y1, x2, y2, children: element.fill.gradient.colors.map((stop, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("stop", { offset: `${stop.pos ?? 0}%`, stopColor: stop.color ?? "#FFFFFF" }, index)) }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("radialGradient", { id: gradientId, cx: "50%", cy: "50%", r: "50%", children: element.fill.gradient.colors.map((stop, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("stop", { offset: `${stop.pos ?? 0}%`, stopColor: stop.color ?? "#FFFFFF" }, index)) });
243
+ })() }) : null,
168
244
  /* @__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)(
169
245
  "path",
170
246
  {
@@ -314,6 +390,7 @@ function renderTable(element) {
314
390
  var import_jsx_runtime5 = require("react/jsx-runtime");
315
391
  function renderText(element) {
316
392
  const paragraphStyle = element.paragraphSpace !== void 0 ? { ["--paragraphSpace"]: `${element.paragraphSpace}px` } : void 0;
393
+ const background = getCssBackground(element.fill);
317
394
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
318
395
  "div",
319
396
  {
@@ -327,6 +404,7 @@ function renderText(element) {
327
404
  fontFamily: element.defaultFontName || "sans-serif",
328
405
  color: element.defaultColor,
329
406
  writingMode: element.vertical ? "vertical-rl" : void 0,
407
+ background,
330
408
  ...paragraphStyle
331
409
  },
332
410
  dangerouslySetInnerHTML: { __html: element.content || "" }
@@ -392,6 +470,7 @@ function preparePreviewSlide(slide) {
392
470
  }
393
471
  function PPTXPreviewer({ slide, className }) {
394
472
  const preparedSlide = (0, import_react.useMemo)(() => preparePreviewSlide(slide), [slide]);
473
+ const background = getCssBackground(preparedSlide.background);
395
474
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
396
475
  "div",
397
476
  {
@@ -405,13 +484,13 @@ function PPTXPreviewer({ slide, className }) {
405
484
  lineHeight: "normal"
406
485
  },
407
486
  children: [
408
- preparedSlide.background?.color ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
487
+ background ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
409
488
  "div",
410
489
  {
411
490
  style: {
412
491
  position: "absolute",
413
492
  inset: 0,
414
- backgroundColor: preparedSlide.background.color
493
+ background
415
494
  }
416
495
  }
417
496
  ) : null,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../index.ts","../src/PPTXPreviewer.tsx","../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"],"sourcesContent":["export { PPTXPreviewer } from './src/PPTXPreviewer';\nexport type { PPTXPreviewerProps, Slide, SlideElement } from './src/types';\n","import { useMemo } from 'react'\nimport { parseDocument } from 'json2pptx-schema'\nimport { renderElement } from './renderers'\nimport type { PPTXPreviewerProps, Slide } from './types'\nimport { getElementSize } from './utils/elementSize'\nimport { getFlipTransform, getShadowFilter } from './utils/elementStyle'\n\nconst PREVIEW_WIDTH = 1000\nconst PREVIEW_HEIGHT = 562.5\n\nexport function preparePreviewSlide (slide: Slide): Slide {\n try {\n const parsed = parseDocument({\n title: 'Preview',\n width: PREVIEW_WIDTH,\n height: PREVIEW_HEIGHT,\n theme: {},\n slides: [slide]\n })\n return parsed.slides[0] as unknown as Slide\n } catch {\n return slide\n }\n}\n\nexport function PPTXPreviewer ({ slide, className }: PPTXPreviewerProps) {\n const preparedSlide = useMemo(() => preparePreviewSlide(slide), [slide])\n\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 {preparedSlide.background?.color ? (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n backgroundColor: preparedSlide.background.color\n }}\n />\n ) : null}\n\n {(preparedSlide.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\n ? `rotate(${element.rotate}deg)`\n : 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","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"],"mappings":"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","names":["import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime"]}
1
+ {"version":3,"sources":["../index.ts","../src/PPTXPreviewer.tsx","../src/renderers/image.tsx","../src/constants.ts","../src/renderers/line.tsx","../src/utils/fill.ts","../src/renderers/shape.tsx","../src/renderers/table.tsx","../src/renderers/text.tsx","../src/renderers/index.tsx","../src/utils/elementSize.ts","../src/utils/elementStyle.ts"],"sourcesContent":["export { PPTXPreviewer } from './src/PPTXPreviewer';\nexport type { PPTXPreviewerProps, Slide, SlideElement } from './src/types';\n","import { useMemo } from 'react'\nimport { parseDocument } from 'json2pptx-schema'\nimport { renderElement } from './renderers'\nimport type { PPTXPreviewerProps, Slide } from './types'\nimport { getElementSize } from './utils/elementSize'\nimport { getFlipTransform, getShadowFilter } from './utils/elementStyle'\nimport { getCssBackground } from './utils/fill'\n\nconst PREVIEW_WIDTH = 1000\nconst PREVIEW_HEIGHT = 562.5\n\nexport function preparePreviewSlide (slide: Slide): Slide {\n try {\n const parsed = parseDocument({\n title: 'Preview',\n width: PREVIEW_WIDTH,\n height: PREVIEW_HEIGHT,\n theme: {},\n slides: [slide]\n })\n return parsed.slides[0] as unknown as Slide\n } catch {\n return slide\n }\n}\n\nexport function PPTXPreviewer ({ slide, className }: PPTXPreviewerProps) {\n const preparedSlide = useMemo(() => preparePreviewSlide(slide), [slide])\n const background = getCssBackground(preparedSlide.background)\n\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 {background ? (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n background\n }}\n />\n ) : null}\n\n {(preparedSlide.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\n ? `rotate(${element.rotate}deg)`\n : 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","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 const clipRange = element.clip?.range;\n const startX = clipRange?.[0]?.[0] ?? 0;\n const startY = clipRange?.[0]?.[1] ?? 0;\n const endX = clipRange?.[1]?.[0] ?? 100;\n const endY = clipRange?.[1]?.[1] ?? 100;\n const rangeWidth = Math.max(1, endX - startX);\n const rangeHeight = Math.max(1, endY - startY);\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 position: 'relative'\n }}\n >\n <img\n src={element.src || ''}\n alt=''\n style={{\n position: 'absolute',\n width: `${10000 / rangeWidth}%`,\n height: `${10000 / rangeHeight}%`,\n left: `${(-startX / rangeWidth) * 100}%`,\n top: `${(-startY / rangeHeight) * 100}%`\n }}\n />\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 { ElementFill, FillGradient } from '../types'\n\nfunction buildGradientStops(gradient?: FillGradient): string {\n return (gradient?.colors ?? [])\n .map((stop) => `${stop.color ?? '#FFFFFF'} ${stop.pos ?? 0}%`)\n .join(', ')\n}\n\nexport function getCssBackground(fill?: ElementFill): string | undefined {\n if (!fill) return undefined\n\n if (fill.type === 'solid') {\n return fill.color\n }\n\n if (fill.type === 'image') {\n return fill.src ? `url(\"${fill.src}\") center / cover no-repeat` : undefined\n }\n\n const stops = buildGradientStops(fill.gradient)\n if (!stops) return undefined\n\n const gradientType = fill.gradient?.type === 'linear' || fill.gradient?.type === 'line'\n ? 'linear'\n : 'radial'\n\n if (gradientType === 'radial') {\n return `radial-gradient(circle, ${stops})`\n }\n\n return `linear-gradient(${(fill.gradient?.rotate ?? 0) + 90}deg, ${stops})`\n}\n\nexport function getSvgLinearGradientCoordinates(rotate = 0): {\n x1: number\n y1: number\n x2: number\n y2: number\n} {\n const radians = (rotate * Math.PI) / 180\n const dx = Math.cos(radians) / 2\n const dy = Math.sin(radians) / 2\n\n return {\n x1: 0.5 - dx,\n y1: 0.5 - dy,\n x2: 0.5 + dx,\n y2: 0.5 + dy\n }\n}\n","import type { SlideElement } from '../types';\nimport { getSvgLinearGradientCoordinates } from '../utils/fill';\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 gradientId = `${patternId}-gradient`;\n let fill = 'transparent';\n\n if (element.fill?.type === 'solid') {\n fill = element.fill.color || 'transparent';\n } else if (element.fill?.type === 'image' && element.fill.src) {\n fill = `url(#${patternId})`;\n } else if (element.fill?.type === 'gradient' && element.fill.gradient?.colors?.length) {\n fill = `url(#${gradientId})`;\n }\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.fill?.type === 'image' && element.fill.src && (\n <defs>\n <pattern\n id={patternId}\n patternUnits='userSpaceOnUse'\n patternContentUnits='userSpaceOnUse'\n width={viewWidth}\n height={viewHeight}\n >\n <image\n href={element.fill.src}\n width={viewWidth}\n height={viewHeight}\n preserveAspectRatio='xMidYMid slice'\n opacity={element.fill.opacity ?? 1}\n />\n </pattern>\n </defs>\n )}\n {element.fill?.type === 'gradient' && element.fill.gradient?.colors?.length ? (\n <defs>\n {(() => {\n const { x1, y1, x2, y2 } = getSvgLinearGradientCoordinates(\n element.fill?.gradient?.rotate ?? 0\n );\n return element.fill.gradient?.type === 'linear' || element.fill.gradient?.type === 'line' ? (\n <linearGradient id={gradientId} x1={x1} y1={y1} x2={x2} y2={y2}>\n {element.fill.gradient.colors.map((stop, index) => (\n <stop key={index} offset={`${stop.pos ?? 0}%`} stopColor={stop.color ?? '#FFFFFF'} />\n ))}\n </linearGradient>\n ) : (\n <radialGradient id={gradientId} cx='50%' cy='50%' r='50%'>\n {element.fill.gradient.colors.map((stop, index) => (\n <stop key={index} offset={`${stop.pos ?? 0}%`} stopColor={stop.color ?? '#FFFFFF'} />\n ))}\n </radialGradient>\n );\n })()}\n </defs>\n ) : null}\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';\nimport { getCssBackground } from '../utils/fill';\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 const background = getCssBackground(element.fill);\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 background,\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"],"mappings":"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","names":["import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime","import_jsx_runtime"]}
package/dist/index.mjs CHANGED
@@ -10,6 +10,13 @@ function renderImage(element) {
10
10
  element.filters?.opacity ? `opacity(${element.filters.opacity})` : "",
11
11
  element.filters?.blur ? `blur(${element.filters.blur})` : ""
12
12
  ].filter(Boolean).join(" ");
13
+ const clipRange = element.clip?.range;
14
+ const startX = clipRange?.[0]?.[0] ?? 0;
15
+ const startY = clipRange?.[0]?.[1] ?? 0;
16
+ const endX = clipRange?.[1]?.[0] ?? 100;
17
+ const endY = clipRange?.[1]?.[1] ?? 100;
18
+ const rangeWidth = Math.max(1, endX - startX);
19
+ const rangeHeight = Math.max(1, endY - startY);
13
20
  return /* @__PURE__ */ jsx(
14
21
  "div",
15
22
  {
@@ -18,9 +25,23 @@ function renderImage(element) {
18
25
  height: "100%",
19
26
  overflow: "hidden",
20
27
  borderRadius: element.clip?.shape === "ellipse" ? "50%" : element.radius ? `${element.radius}px` : void 0,
21
- filter: filterStr || void 0
28
+ filter: filterStr || void 0,
29
+ position: "relative"
22
30
  },
23
- children: /* @__PURE__ */ jsx("img", { src: element.src || "", alt: "", style: { width: "100%", height: "100%", objectFit: "cover" } })
31
+ children: /* @__PURE__ */ jsx(
32
+ "img",
33
+ {
34
+ src: element.src || "",
35
+ alt: "",
36
+ style: {
37
+ position: "absolute",
38
+ width: `${1e4 / rangeWidth}%`,
39
+ height: `${1e4 / rangeHeight}%`,
40
+ left: `${-startX / rangeWidth * 100}%`,
41
+ top: `${-startY / rangeHeight * 100}%`
42
+ }
43
+ }
44
+ )
24
45
  }
25
46
  );
26
47
  }
@@ -109,6 +130,38 @@ function renderLine(element, markerId) {
109
130
  ] });
110
131
  }
111
132
 
133
+ // src/utils/fill.ts
134
+ function buildGradientStops(gradient) {
135
+ return (gradient?.colors ?? []).map((stop) => `${stop.color ?? "#FFFFFF"} ${stop.pos ?? 0}%`).join(", ");
136
+ }
137
+ function getCssBackground(fill) {
138
+ if (!fill) return void 0;
139
+ if (fill.type === "solid") {
140
+ return fill.color;
141
+ }
142
+ if (fill.type === "image") {
143
+ return fill.src ? `url("${fill.src}") center / cover no-repeat` : void 0;
144
+ }
145
+ const stops = buildGradientStops(fill.gradient);
146
+ if (!stops) return void 0;
147
+ const gradientType = fill.gradient?.type === "linear" || fill.gradient?.type === "line" ? "linear" : "radial";
148
+ if (gradientType === "radial") {
149
+ return `radial-gradient(circle, ${stops})`;
150
+ }
151
+ return `linear-gradient(${(fill.gradient?.rotate ?? 0) + 90}deg, ${stops})`;
152
+ }
153
+ function getSvgLinearGradientCoordinates(rotate = 0) {
154
+ const radians = rotate * Math.PI / 180;
155
+ const dx = Math.cos(radians) / 2;
156
+ const dy = Math.sin(radians) / 2;
157
+ return {
158
+ x1: 0.5 - dx,
159
+ y1: 0.5 - dy,
160
+ x2: 0.5 + dx,
161
+ y2: 0.5 + dy
162
+ };
163
+ }
164
+
112
165
  // src/renderers/shape.tsx
113
166
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
114
167
  var getOutlineDashArray = (outline) => {
@@ -122,13 +175,21 @@ function renderShape(element, patternId) {
122
175
  const viewWidth = element.viewBox?.[0] ?? element.width ?? 0;
123
176
  const viewHeight = element.viewBox?.[1] ?? element.height ?? 0;
124
177
  const outlineDashArray = getOutlineDashArray(element.outline);
125
- const fill = element.pattern ? `url(#${patternId})` : element.fill || "transparent";
178
+ const gradientId = `${patternId}-gradient`;
179
+ let fill = "transparent";
180
+ if (element.fill?.type === "solid") {
181
+ fill = element.fill.color || "transparent";
182
+ } else if (element.fill?.type === "image" && element.fill.src) {
183
+ fill = `url(#${patternId})`;
184
+ } else if (element.fill?.type === "gradient" && element.fill.gradient?.colors?.length) {
185
+ fill = `url(#${gradientId})`;
186
+ }
126
187
  const text = element.text;
127
188
  const verticalAlign = text?.align ?? "middle";
128
189
  const justifyContent = verticalAlign === "top" ? "flex-start" : verticalAlign === "bottom" ? "flex-end" : "center";
129
190
  return /* @__PURE__ */ jsxs2("div", { style: { position: "relative", width: "100%", height: "100%" }, children: [
130
191
  /* @__PURE__ */ jsxs2("svg", { style: { position: "absolute", inset: 0 }, overflow: "visible", width: element.width, height: element.height, children: [
131
- element.pattern && /* @__PURE__ */ jsx3("defs", { children: /* @__PURE__ */ jsx3(
192
+ element.fill?.type === "image" && element.fill.src && /* @__PURE__ */ jsx3("defs", { children: /* @__PURE__ */ jsx3(
132
193
  "pattern",
133
194
  {
134
195
  id: patternId,
@@ -136,9 +197,24 @@ function renderShape(element, patternId) {
136
197
  patternContentUnits: "userSpaceOnUse",
137
198
  width: viewWidth,
138
199
  height: viewHeight,
139
- children: /* @__PURE__ */ jsx3("image", { href: element.pattern, width: viewWidth, height: viewHeight, preserveAspectRatio: "xMidYMid slice" })
200
+ children: /* @__PURE__ */ jsx3(
201
+ "image",
202
+ {
203
+ href: element.fill.src,
204
+ width: viewWidth,
205
+ height: viewHeight,
206
+ preserveAspectRatio: "xMidYMid slice",
207
+ opacity: element.fill.opacity ?? 1
208
+ }
209
+ )
140
210
  }
141
211
  ) }),
212
+ element.fill?.type === "gradient" && element.fill.gradient?.colors?.length ? /* @__PURE__ */ jsx3("defs", { children: (() => {
213
+ const { x1, y1, x2, y2 } = getSvgLinearGradientCoordinates(
214
+ element.fill?.gradient?.rotate ?? 0
215
+ );
216
+ return element.fill.gradient?.type === "linear" || element.fill.gradient?.type === "line" ? /* @__PURE__ */ jsx3("linearGradient", { id: gradientId, x1, y1, x2, y2, children: element.fill.gradient.colors.map((stop, index) => /* @__PURE__ */ jsx3("stop", { offset: `${stop.pos ?? 0}%`, stopColor: stop.color ?? "#FFFFFF" }, index)) }) : /* @__PURE__ */ jsx3("radialGradient", { id: gradientId, cx: "50%", cy: "50%", r: "50%", children: element.fill.gradient.colors.map((stop, index) => /* @__PURE__ */ jsx3("stop", { offset: `${stop.pos ?? 0}%`, stopColor: stop.color ?? "#FFFFFF" }, index)) });
217
+ })() }) : null,
142
218
  /* @__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(
143
219
  "path",
144
220
  {
@@ -288,6 +364,7 @@ function renderTable(element) {
288
364
  import { jsx as jsx5 } from "react/jsx-runtime";
289
365
  function renderText(element) {
290
366
  const paragraphStyle = element.paragraphSpace !== void 0 ? { ["--paragraphSpace"]: `${element.paragraphSpace}px` } : void 0;
367
+ const background = getCssBackground(element.fill);
291
368
  return /* @__PURE__ */ jsx5(
292
369
  "div",
293
370
  {
@@ -301,6 +378,7 @@ function renderText(element) {
301
378
  fontFamily: element.defaultFontName || "sans-serif",
302
379
  color: element.defaultColor,
303
380
  writingMode: element.vertical ? "vertical-rl" : void 0,
381
+ background,
304
382
  ...paragraphStyle
305
383
  },
306
384
  dangerouslySetInnerHTML: { __html: element.content || "" }
@@ -366,6 +444,7 @@ function preparePreviewSlide(slide) {
366
444
  }
367
445
  function PPTXPreviewer({ slide, className }) {
368
446
  const preparedSlide = useMemo(() => preparePreviewSlide(slide), [slide]);
447
+ const background = getCssBackground(preparedSlide.background);
369
448
  return /* @__PURE__ */ jsxs4(
370
449
  "div",
371
450
  {
@@ -379,13 +458,13 @@ function PPTXPreviewer({ slide, className }) {
379
458
  lineHeight: "normal"
380
459
  },
381
460
  children: [
382
- preparedSlide.background?.color ? /* @__PURE__ */ jsx6(
461
+ background ? /* @__PURE__ */ jsx6(
383
462
  "div",
384
463
  {
385
464
  style: {
386
465
  position: "absolute",
387
466
  inset: 0,
388
- backgroundColor: preparedSlide.background.color
467
+ background
389
468
  }
390
469
  }
391
470
  ) : null,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/PPTXPreviewer.tsx","../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"],"sourcesContent":["import { useMemo } from 'react'\nimport { parseDocument } from 'json2pptx-schema'\nimport { renderElement } from './renderers'\nimport type { PPTXPreviewerProps, Slide } from './types'\nimport { getElementSize } from './utils/elementSize'\nimport { getFlipTransform, getShadowFilter } from './utils/elementStyle'\n\nconst PREVIEW_WIDTH = 1000\nconst PREVIEW_HEIGHT = 562.5\n\nexport function preparePreviewSlide (slide: Slide): Slide {\n try {\n const parsed = parseDocument({\n title: 'Preview',\n width: PREVIEW_WIDTH,\n height: PREVIEW_HEIGHT,\n theme: {},\n slides: [slide]\n })\n return parsed.slides[0] as unknown as Slide\n } catch {\n return slide\n }\n}\n\nexport function PPTXPreviewer ({ slide, className }: PPTXPreviewerProps) {\n const preparedSlide = useMemo(() => preparePreviewSlide(slide), [slide])\n\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 {preparedSlide.background?.color ? (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n backgroundColor: preparedSlide.background.color\n }}\n />\n ) : null}\n\n {(preparedSlide.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\n ? `rotate(${element.rotate}deg)`\n : 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","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"],"mappings":";AAAA,SAAS,eAAe;AACxB,SAAS,qBAAqB;;;ACoBxB;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,8BAAC,SAAI,KAAK,QAAQ,OAAO,IAAI,KAAI,IAAG,OAAO,EAAE,OAAO,QAAQ,QAAQ,QAAQ,WAAW,QAAQ,GAAG;AAAA;AAAA,EACpG;AAEJ;;;ACxBO,IAAM,gBAAgB;;;ACiEvB,gBAAAA,MAoBA,YApBA;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,gBAAAA;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,0BAAAA,KAAC,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,qBAAC,SAAI,UAAS,WAAU,OAAc,QACpC;AAAA,yBAAC,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,gBAAAA;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,SAUQ,OAAAC,MAVR,QAAAC,aAAA;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,gBAAAA,MAAC,SAAI,OAAO,EAAE,UAAU,YAAY,OAAO,QAAQ,QAAQ,OAAO,GAChE;AAAA,oBAAAA,MAAC,SAAI,OAAO,EAAE,UAAU,YAAY,OAAO,EAAE,GAAG,UAAS,WAAU,OAAO,QAAQ,OAAO,QAAQ,QAAQ,QACtG;AAAA,cAAQ,WACP,gBAAAD,KAAC,UACC,0BAAAA;AAAA,QAAC;AAAA;AAAA,UACC,IAAI;AAAA,UACJ,cAAa;AAAA,UACb,qBAAoB;AAAA,UACpB,OAAO;AAAA,UACP,QAAQ;AAAA,UAER,0BAAAA,KAAC,WAAM,MAAM,QAAQ,SAAS,OAAO,WAAW,QAAQ,YAAY,qBAAoB,kBAAiB;AAAA;AAAA,MAC3G,GACF;AAAA,MAEF,gBAAAA,KAAC,OAAE,WAAW,UAAU,QAAQ,SAAS,KAAK,aAAa,CAAC,MAAM,QAAQ,UAAU,KAAK,cAAc,CAAC,wCACtG,0BAAAA;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,gBAAAA;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,SAYQ,OAAAE,MAZR,QAAAC,aAAA;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,gBAAAD,KAAC,SAAI,OAAO,EAAE,OAAO,QAAQ,QAAQ,OAAO,GAC1C,0BAAAC;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,gBAAAD,KAAC,cACE,oBAAU,IAAI,CAAC,OAAO,UACrB,gBAAAA,KAAC,SAAyB,OAAO,EAAE,OAAO,GAAG,QAAQ,GAAG,IAAI,KAAlD,OAAO,KAAK,EAAyC,CAChE,GACH;AAAA,QAEF,gBAAAA,KAAC,WACE,eAAK,IAAI,CAAC,KAAK,aACd,gBAAAA,KAAC,QAA2B,OAAO,EAAE,QAAQ,UAAU,GACpD,cAAI,IAAI,CAAC,SACR,gBAAAA;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,gBAAAE,YAAA;AAPG,SAAS,WAAW,SAAuB;AAChD,QAAM,iBACJ,QAAQ,mBAAmB,SACtB,EAAE,CAAC,kBAA4B,GAAG,GAAG,QAAQ,cAAc,KAAK,IACjE;AAEN,SACE,gBAAAA;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;;;ATaI,SAYI,OAAAC,MAZJ,QAAAC,aAAA;AAtBJ,IAAM,gBAAgB;AACtB,IAAM,iBAAiB;AAEhB,SAAS,oBAAqB,OAAqB;AACxD,MAAI;AACF,UAAM,SAAS,cAAc;AAAA,MAC3B,OAAO;AAAA,MACP,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,OAAO,CAAC;AAAA,MACR,QAAQ,CAAC,KAAK;AAAA,IAChB,CAAC;AACD,WAAO,OAAO,OAAO,CAAC;AAAA,EACxB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,cAAe,EAAE,OAAO,UAAU,GAAuB;AACvE,QAAM,gBAAgB,QAAQ,MAAM,oBAAoB,KAAK,GAAG,CAAC,KAAK,CAAC;AAEvE,SACE,gBAAAA;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,sBAAc,YAAY,QACzB,gBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,UAAU;AAAA,cACV,OAAO;AAAA,cACP,iBAAiB,cAAc,WAAW;AAAA,YAC5C;AAAA;AAAA,QACF,IACE;AAAA,SAEF,cAAc,YAAY,CAAC,GAAG,IAAI,CAAC,SAAS,iBAAiB;AAC7D,gBAAM,OAAO,eAAe,OAAO;AACnC,gBAAM,WAAW,QAAQ,MAAM,QAAQ,YAAY;AAEnD,iBACE,gBAAAA;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,0BAAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO;AAAA,oBACL,OAAO;AAAA,oBACP,QAAQ;AAAA,oBACR,WAAW,QAAQ,SACf,UAAU,QAAQ,MAAM,SACxB;AAAA,kBACN;AAAA,kBAEA,0BAAAA;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,YAjCK,QAAQ,MAAM;AAAA,UAkCrB;AAAA,QAEJ,CAAC;AAAA;AAAA;AAAA,EACH;AAEJ;","names":["jsx","jsx","jsxs","jsx","jsxs","jsx","jsx","jsxs"]}
1
+ {"version":3,"sources":["../src/PPTXPreviewer.tsx","../src/renderers/image.tsx","../src/constants.ts","../src/renderers/line.tsx","../src/utils/fill.ts","../src/renderers/shape.tsx","../src/renderers/table.tsx","../src/renderers/text.tsx","../src/renderers/index.tsx","../src/utils/elementSize.ts","../src/utils/elementStyle.ts"],"sourcesContent":["import { useMemo } from 'react'\nimport { parseDocument } from 'json2pptx-schema'\nimport { renderElement } from './renderers'\nimport type { PPTXPreviewerProps, Slide } from './types'\nimport { getElementSize } from './utils/elementSize'\nimport { getFlipTransform, getShadowFilter } from './utils/elementStyle'\nimport { getCssBackground } from './utils/fill'\n\nconst PREVIEW_WIDTH = 1000\nconst PREVIEW_HEIGHT = 562.5\n\nexport function preparePreviewSlide (slide: Slide): Slide {\n try {\n const parsed = parseDocument({\n title: 'Preview',\n width: PREVIEW_WIDTH,\n height: PREVIEW_HEIGHT,\n theme: {},\n slides: [slide]\n })\n return parsed.slides[0] as unknown as Slide\n } catch {\n return slide\n }\n}\n\nexport function PPTXPreviewer ({ slide, className }: PPTXPreviewerProps) {\n const preparedSlide = useMemo(() => preparePreviewSlide(slide), [slide])\n const background = getCssBackground(preparedSlide.background)\n\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 {background ? (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n background\n }}\n />\n ) : null}\n\n {(preparedSlide.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\n ? `rotate(${element.rotate}deg)`\n : 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","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 const clipRange = element.clip?.range;\n const startX = clipRange?.[0]?.[0] ?? 0;\n const startY = clipRange?.[0]?.[1] ?? 0;\n const endX = clipRange?.[1]?.[0] ?? 100;\n const endY = clipRange?.[1]?.[1] ?? 100;\n const rangeWidth = Math.max(1, endX - startX);\n const rangeHeight = Math.max(1, endY - startY);\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 position: 'relative'\n }}\n >\n <img\n src={element.src || ''}\n alt=''\n style={{\n position: 'absolute',\n width: `${10000 / rangeWidth}%`,\n height: `${10000 / rangeHeight}%`,\n left: `${(-startX / rangeWidth) * 100}%`,\n top: `${(-startY / rangeHeight) * 100}%`\n }}\n />\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 { ElementFill, FillGradient } from '../types'\n\nfunction buildGradientStops(gradient?: FillGradient): string {\n return (gradient?.colors ?? [])\n .map((stop) => `${stop.color ?? '#FFFFFF'} ${stop.pos ?? 0}%`)\n .join(', ')\n}\n\nexport function getCssBackground(fill?: ElementFill): string | undefined {\n if (!fill) return undefined\n\n if (fill.type === 'solid') {\n return fill.color\n }\n\n if (fill.type === 'image') {\n return fill.src ? `url(\"${fill.src}\") center / cover no-repeat` : undefined\n }\n\n const stops = buildGradientStops(fill.gradient)\n if (!stops) return undefined\n\n const gradientType = fill.gradient?.type === 'linear' || fill.gradient?.type === 'line'\n ? 'linear'\n : 'radial'\n\n if (gradientType === 'radial') {\n return `radial-gradient(circle, ${stops})`\n }\n\n return `linear-gradient(${(fill.gradient?.rotate ?? 0) + 90}deg, ${stops})`\n}\n\nexport function getSvgLinearGradientCoordinates(rotate = 0): {\n x1: number\n y1: number\n x2: number\n y2: number\n} {\n const radians = (rotate * Math.PI) / 180\n const dx = Math.cos(radians) / 2\n const dy = Math.sin(radians) / 2\n\n return {\n x1: 0.5 - dx,\n y1: 0.5 - dy,\n x2: 0.5 + dx,\n y2: 0.5 + dy\n }\n}\n","import type { SlideElement } from '../types';\nimport { getSvgLinearGradientCoordinates } from '../utils/fill';\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 gradientId = `${patternId}-gradient`;\n let fill = 'transparent';\n\n if (element.fill?.type === 'solid') {\n fill = element.fill.color || 'transparent';\n } else if (element.fill?.type === 'image' && element.fill.src) {\n fill = `url(#${patternId})`;\n } else if (element.fill?.type === 'gradient' && element.fill.gradient?.colors?.length) {\n fill = `url(#${gradientId})`;\n }\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.fill?.type === 'image' && element.fill.src && (\n <defs>\n <pattern\n id={patternId}\n patternUnits='userSpaceOnUse'\n patternContentUnits='userSpaceOnUse'\n width={viewWidth}\n height={viewHeight}\n >\n <image\n href={element.fill.src}\n width={viewWidth}\n height={viewHeight}\n preserveAspectRatio='xMidYMid slice'\n opacity={element.fill.opacity ?? 1}\n />\n </pattern>\n </defs>\n )}\n {element.fill?.type === 'gradient' && element.fill.gradient?.colors?.length ? (\n <defs>\n {(() => {\n const { x1, y1, x2, y2 } = getSvgLinearGradientCoordinates(\n element.fill?.gradient?.rotate ?? 0\n );\n return element.fill.gradient?.type === 'linear' || element.fill.gradient?.type === 'line' ? (\n <linearGradient id={gradientId} x1={x1} y1={y1} x2={x2} y2={y2}>\n {element.fill.gradient.colors.map((stop, index) => (\n <stop key={index} offset={`${stop.pos ?? 0}%`} stopColor={stop.color ?? '#FFFFFF'} />\n ))}\n </linearGradient>\n ) : (\n <radialGradient id={gradientId} cx='50%' cy='50%' r='50%'>\n {element.fill.gradient.colors.map((stop, index) => (\n <stop key={index} offset={`${stop.pos ?? 0}%`} stopColor={stop.color ?? '#FFFFFF'} />\n ))}\n </radialGradient>\n );\n })()}\n </defs>\n ) : null}\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';\nimport { getCssBackground } from '../utils/fill';\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 const background = getCssBackground(element.fill);\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 background,\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"],"mappings":"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","names":["jsx","jsx","jsxs","jsx","jsxs","jsx","jsx","jsxs"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pptx-previewer",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "A React component to preview PPTX JSON slides in the browser.",
5
5
  "license": "MIT",
6
6
  "main": "dist/index.js",
@@ -41,11 +41,11 @@
41
41
  "react": ">=18"
42
42
  },
43
43
  "dependencies": {
44
- "json2pptx-schema": "0.1.0"
44
+ "json2pptx-schema": "workspace:*"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@types/react": "^18.3.3",
48
48
  "tsup": "^8.0.1",
49
49
  "typescript": "^5.3.3"
50
50
  }
51
- }
51
+ }