deckjsx 0.8.1 → 0.8.3

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/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { c as isAuthoredTag, i as createAuthorElement, o as isAuthorTreeChild, s as isAuthorTreeNode, t as authorElementPropsFromEntries } from "./tree-DNsco0U3.mjs";
2
- import { A as CompositionDiagnosticError, C as parsePointValue, D as POINTS_PER_INCH, E as EMU_PER_INCH, F as formatDiagnostics, M as SemanticGraphDiagnosticError, N as StyleDiagnosticError, O as createDiagnostics, P as formatDiagnostic, S as parsePointToken, T as pointsToEmu, _ as isDeckLengthString, a as isInspectableThemePayload, b as parseLengthToken, c as fingerprintString, d as createWriterRenderContext, f as createTemplateHandle, g as DEFAULT_FONT_SIZE_PT, h as validateSlideTemplates, i as isContentTypesPayload, j as DeckDiagnosticError, k as diagnostic, l as stableJson, m as templateRefValue, n as pptxMediaAssetLoadRequirements, o as isRecord$2, p as isTemplateAreaRef, r as validatePptxPackageModel, s as projectedRelationshipTarget, t as pptx, u as withPackagePartFingerprints, v as isDeckPointLengthString, w as parseStrokeWidth, x as parsePercentage$1, y as parseLength } from "./adapter-CNSvvD4i.mjs";
1
+ import { c as isAuthoredTag, i as createAuthorElement, o as isAuthorTreeChild, s as isAuthorTreeNode, t as authorElementPropsFromEntries } from "./tree-DY5XQegS.mjs";
2
+ import { A as diagnostic, C as parsePointToken, D as EMU_PER_INCH, E as pointsToEmu, F as formatDiagnostic, I as formatDiagnostics, M as DeckDiagnosticError, N as SemanticGraphDiagnosticError, O as POINTS_PER_INCH, P as StyleDiagnosticError, S as parsePercentage$1, T as parseStrokeWidth, _ as isCssWideKeyword, a as isInspectableThemePayload, b as parseLength, c as fingerprintString, d as createWriterRenderContext, f as createTemplateHandle, g as DEFAULT_FONT_SIZE_PT, h as validateSlideTemplates, i as isContentTypesPayload, j as CompositionDiagnosticError, k as createDiagnostics, l as stableJson, m as templateRefValue, n as pptxMediaAssetLoadRequirements, o as isRecord$2, p as isTemplateAreaRef, r as validatePptxPackageModel, s as projectedRelationshipTarget, t as pptx, u as withPackagePartFingerprints, v as isDeckLengthString, w as parsePointValue, x as parseLengthToken, y as isDeckPointLengthString } from "./adapter-CGOiv9ip.mjs";
3
3
  import { n as isPptxMediaPart, o as isPptxSlidePart, r as isPptxPackageModel } from "./model-DIuh51qh.mjs";
4
4
  //#region src/composition/types.ts
5
5
  const COMPOSITION_SOURCE = Symbol("deckjsx.compositionSource");
@@ -318,6 +318,7 @@ function packagePartOrderGroup(part) {
318
318
  if (part.kind === "relationships" && part.path.startsWith("ppt/slideLayouts/_rels/")) return "slideLayoutRelationships";
319
319
  if (part.kind === "view-properties") return "viewProperties";
320
320
  if (part.kind === "presentation-properties") return "presentationProperties";
321
+ if (part.kind === "table-styles") return "tableStyles";
321
322
  if (part.kind === "slide") return "slide";
322
323
  if (part.kind === "relationships" && part.path.startsWith("ppt/slides/_rels/")) return "slideRelationships";
323
324
  if (part.kind === "media") return "media";
@@ -336,6 +337,7 @@ const PACKAGE_PART_ORDER_GROUP_ORDER = {
336
337
  slideLayoutRelationships: 71,
337
338
  viewProperties: 75,
338
339
  presentationProperties: 76,
340
+ tableStyles: 77,
339
341
  slide: 80,
340
342
  slideRelationships: 81,
341
343
  media: 90,
@@ -459,7 +461,7 @@ function normalizePackagePartRequirement(requirement) {
459
461
  function packagePartRequirement(part, relationshipPartIdsByTargetPartId) {
460
462
  if (part.requirement) return normalizePackagePartRequirement(part.requirement);
461
463
  if (part.kind === "media") {
462
- const dependencies = relationshipPartIdsByTargetPartId.get(part.id) ?? [];
464
+ const dependencies = [...new Set(relationshipPartIdsByTargetPartId.get(part.id) ?? [])];
463
465
  return {
464
466
  status: "conditional",
465
467
  required: dependencies.length > 0,
@@ -628,7 +630,7 @@ const ELEMENT_DEFAULTS = {
628
630
  rotation: 0,
629
631
  zIndex: 0,
630
632
  overflow: "visible",
631
- position: "relative",
633
+ position: "static",
632
634
  boxSizing: "border-box",
633
635
  backgroundTransparency: 100,
634
636
  borderWidth: 0,
@@ -645,7 +647,7 @@ const ELEMENT_DEFAULTS = {
645
647
  rotation: 0,
646
648
  zIndex: 0,
647
649
  overflow: "visible",
648
- position: "relative",
650
+ position: "static",
649
651
  boxSizing: "border-box",
650
652
  backgroundTransparency: 100,
651
653
  borderWidth: 0,
@@ -705,7 +707,22 @@ const ELEMENT_DEFAULTS = {
705
707
  rotation: 0,
706
708
  zIndex: 0,
707
709
  overflow: "visible",
708
- position: "relative",
710
+ position: "static",
711
+ fit: "contain",
712
+ objectFit: "contain",
713
+ objectPosition: "50% 50%",
714
+ transparency: 0,
715
+ rounding: false,
716
+ margin: 0
717
+ },
718
+ video: {
719
+ display: "block",
720
+ visibility: "visible",
721
+ opacity: 1,
722
+ rotation: 0,
723
+ zIndex: 0,
724
+ overflow: "visible",
725
+ position: "static",
709
726
  fit: "contain",
710
727
  objectFit: "contain",
711
728
  objectPosition: "50% 50%",
@@ -720,7 +737,7 @@ const ELEMENT_DEFAULTS = {
720
737
  rotation: 0,
721
738
  zIndex: 0,
722
739
  overflow: "visible",
723
- position: "relative",
740
+ position: "static",
724
741
  boxSizing: "border-box",
725
742
  backgroundTransparency: 100,
726
743
  borderWidth: 0,
@@ -742,6 +759,7 @@ function elementDefaultsFor(node) {
742
759
  case "text": return ELEMENT_DEFAULTS.text;
743
760
  case "textRun": return ELEMENT_DEFAULTS.textRun;
744
761
  case "image": return ELEMENT_DEFAULTS.image;
762
+ case "video": return ELEMENT_DEFAULTS.video;
745
763
  case "shape": return ELEMENT_DEFAULTS.shape;
746
764
  case "document": return;
747
765
  }
@@ -1274,6 +1292,17 @@ const VIEW_STYLE_KEYS = [
1274
1292
  "gridAutoRows",
1275
1293
  "gridAutoFlow"
1276
1294
  ];
1295
+ const SLIDE_STYLE_KEYS$1 = [
1296
+ "background",
1297
+ "backgroundImage",
1298
+ "backgroundColor",
1299
+ "backgroundTransparency",
1300
+ "backgroundPosition",
1301
+ "backgroundSize",
1302
+ "backgroundRepeat",
1303
+ "backgroundClip",
1304
+ "backgroundOrigin"
1305
+ ];
1277
1306
  const TEXT_STYLE_KEYS = [
1278
1307
  ...VIEW_STYLE_KEYS,
1279
1308
  "fontFamily",
@@ -1400,6 +1429,62 @@ const IMAGE_STYLE_KEYS = [
1400
1429
  "marginBottom",
1401
1430
  "marginLeft"
1402
1431
  ];
1432
+ const VIDEO_STYLE_KEYS = [
1433
+ "opacity",
1434
+ "rotation",
1435
+ "transform",
1436
+ "transformOrigin",
1437
+ "filter",
1438
+ "mixBlendMode",
1439
+ "isolation",
1440
+ "zIndex",
1441
+ "flipH",
1442
+ "flipV",
1443
+ "overflow",
1444
+ "alignSelf",
1445
+ "justifySelf",
1446
+ "placeSelf",
1447
+ "position",
1448
+ "order",
1449
+ "flexGrow",
1450
+ "flexShrink",
1451
+ "flexBasis",
1452
+ "gridArea",
1453
+ "gridColumnStart",
1454
+ "gridColumnEnd",
1455
+ "gridRowStart",
1456
+ "gridRowEnd",
1457
+ "gridColumn",
1458
+ "gridRow",
1459
+ "display",
1460
+ "visibility",
1461
+ "x",
1462
+ "y",
1463
+ "inset",
1464
+ "left",
1465
+ "top",
1466
+ "right",
1467
+ "bottom",
1468
+ "width",
1469
+ "height",
1470
+ "aspectRatio",
1471
+ "minWidth",
1472
+ "minHeight",
1473
+ "maxWidth",
1474
+ "maxHeight",
1475
+ "fit",
1476
+ "objectFit",
1477
+ "objectPosition",
1478
+ "transparency",
1479
+ "rounding",
1480
+ "borderRadius",
1481
+ "boxShadow",
1482
+ "margin",
1483
+ "marginTop",
1484
+ "marginRight",
1485
+ "marginBottom",
1486
+ "marginLeft"
1487
+ ];
1403
1488
  const SHAPE_STYLE_KEYS = [
1404
1489
  ...VIEW_STYLE_KEYS,
1405
1490
  "href",
@@ -1543,11 +1628,45 @@ function applyProperties(style, source, properties) {
1543
1628
  };
1544
1629
  });
1545
1630
  }
1546
- function resolvedStyleFor$1(node, entity, registry, theme, context, diagnostics) {
1631
+ const INHERITED_STYLE_KEYS = new Set([
1632
+ "charSpacing",
1633
+ "color",
1634
+ "direction",
1635
+ "fontFamily",
1636
+ "fontSize",
1637
+ "fontStyle",
1638
+ "fontWeight",
1639
+ "italic",
1640
+ "letterSpacing",
1641
+ "lineHeight",
1642
+ "overflowWrap",
1643
+ "strike",
1644
+ "textAlign",
1645
+ "textTransform",
1646
+ "underline",
1647
+ "whiteSpace",
1648
+ "wordBreak",
1649
+ "writingMode"
1650
+ ]);
1651
+ function applyInheritedProperties(parentId, parent, properties) {
1652
+ if (parentId === void 0 || parent === void 0) return;
1653
+ for (const key of INHERITED_STYLE_KEYS) {
1654
+ const property = parent.properties[key];
1655
+ if (property?.value !== void 0) properties[key] = {
1656
+ value: property.value,
1657
+ source: {
1658
+ layer: "inherited",
1659
+ parentId
1660
+ }
1661
+ };
1662
+ }
1663
+ }
1664
+ function resolvedStyleFor$1(node, entity, registry, theme, context, inherited, diagnostics) {
1547
1665
  const properties = {};
1548
1666
  const appliedClasses = [];
1549
1667
  const defaults = elementDefaultsFor(node);
1550
1668
  if (defaults) applyProperties(defaults, { layer: "default" }, properties);
1669
+ applyInheritedProperties(inherited.parentId, inherited.style, properties);
1551
1670
  const themeDefaults = node.authoredTag && theme ? themeInput(theme).defaults : void 0;
1552
1671
  const themeDefault = node.authoredTag ? themeDefaults?.[node.authoredTag] : void 0;
1553
1672
  if (node.authoredTag && themeDefault) applyProperties(themeDefault, {
@@ -1606,9 +1725,10 @@ function resolveStyles(graph, roots) {
1606
1725
  const stylesheets = classesBySource(roots);
1607
1726
  const themes = themesBySource(roots);
1608
1727
  const registries = /* @__PURE__ */ new Map();
1728
+ const parentById = parentMapFor$1(graph);
1609
1729
  const selectorContext = {
1610
1730
  graph,
1611
- parentById: parentMapFor$1(graph),
1731
+ parentById,
1612
1732
  classNamesByNodeId: classNamesByNodeIdFor(graph)
1613
1733
  };
1614
1734
  const resolvedStyles = /* @__PURE__ */ new Map();
@@ -1618,8 +1738,10 @@ function resolveStyles(graph, roots) {
1618
1738
  themes.forEach((theme, sourceKey) => {
1619
1739
  diagnostics.push(...sourceThemeDiagnostics(sourceKey, theme));
1620
1740
  });
1621
- graph.nodes.forEach((node) => {
1741
+ const resolveNode = (node) => {
1622
1742
  if (!isStyleCapableNode(node)) return;
1743
+ const existing = resolvedStyles.get(node.id);
1744
+ if (existing) return existing;
1623
1745
  const sourceKey = sourceKeyFor$2(node.origin.source);
1624
1746
  const entity = node.styleRef ? graph.styles.get(node.styleRef) : void 0;
1625
1747
  let registry = registries.get(sourceKey);
@@ -1627,7 +1749,18 @@ function resolveStyles(graph, roots) {
1627
1749
  registry = registerStylesheets(sourceKey, stylesheets.get(sourceKey), diagnostics);
1628
1750
  registries.set(sourceKey, registry);
1629
1751
  }
1630
- resolvedStyles.set(node.id, resolvedStyleFor$1(node, entity, registry, themes.get(sourceKey), selectorContext, diagnostics));
1752
+ const parentId = parentById.get(node.id);
1753
+ const parent = parentId ? graph.nodes.get(parentId) : void 0;
1754
+ const inherited = parent ? resolveNode(parent) : void 0;
1755
+ const resolved = resolvedStyleFor$1(node, entity, registry, themes.get(sourceKey), selectorContext, {
1756
+ parentId,
1757
+ style: inherited
1758
+ }, diagnostics);
1759
+ resolvedStyles.set(node.id, resolved);
1760
+ return resolved;
1761
+ };
1762
+ graph.nodes.forEach((node) => {
1763
+ resolveNode(node);
1631
1764
  });
1632
1765
  return {
1633
1766
  resolvedStyles,
@@ -1795,9 +1928,10 @@ var PipelineArtifactCollection = class {
1795
1928
  styleIds.push(node.styleRef);
1796
1929
  stylesBySourceKey.set(sourceKey, styleIds);
1797
1930
  }
1798
- if (node.kind === "image" && node.assetRef) {
1931
+ const nodeAssetIds = node.kind === "image" && node.assetRef ? [node.assetRef] : node.kind === "video" ? [node.assetRef, node.posterAssetRef].filter((id) => id !== void 0) : [];
1932
+ if (nodeAssetIds.length > 0) {
1799
1933
  const assetIds = assetsBySourceKey.get(sourceKey) ?? [];
1800
- assetIds.push(node.assetRef);
1934
+ assetIds.push(...nodeAssetIds);
1801
1935
  assetsBySourceKey.set(sourceKey, assetIds);
1802
1936
  }
1803
1937
  });
@@ -1921,6 +2055,7 @@ function assetEntityId(material) {
1921
2055
  //#region src/graph/roles.ts
1922
2056
  function semanticKindForTag(tag) {
1923
2057
  if (tag === "img") return "image";
2058
+ if (tag === "video") return "video";
1924
2059
  if (tag === "shape") return "shape";
1925
2060
  if (tag === "p" || /^h[1-6]$/.test(tag) || tag === "span") return tag === "span" ? "textRun" : "text";
1926
2061
  return "container";
@@ -1950,6 +2085,7 @@ function semanticRoleForTag(tag) {
1950
2085
  level: Number(tag.slice(1))
1951
2086
  };
1952
2087
  case "img": return { kind: "image" };
2088
+ case "video": return { kind: "video" };
1953
2089
  case "shape": return { kind: "shape" };
1954
2090
  case "span": return;
1955
2091
  }
@@ -1980,6 +2116,9 @@ function isSlideElement(node) {
1980
2116
  function isImageElement(node) {
1981
2117
  return node.source.kind === "tag" && node.source.tag === "img";
1982
2118
  }
2119
+ function isVideoElement(node) {
2120
+ return node.source.kind === "tag" && node.source.tag === "video";
2121
+ }
1983
2122
  function isShapeElement(node) {
1984
2123
  return node.source.kind === "tag" && node.source.tag === "shape";
1985
2124
  }
@@ -2002,6 +2141,15 @@ function supportedPropNamesFor(node) {
2002
2141
  "src",
2003
2142
  "data"
2004
2143
  ]);
2144
+ case "video": return new Set([
2145
+ "className",
2146
+ "style",
2147
+ "area",
2148
+ "src",
2149
+ "data",
2150
+ "poster",
2151
+ "posterData"
2152
+ ]);
2005
2153
  case "shape": return new Set([
2006
2154
  "className",
2007
2155
  "style",
@@ -2015,6 +2163,23 @@ function supportedPropNamesFor(node) {
2015
2163
  ]);
2016
2164
  }
2017
2165
  }
2166
+ function supportedStyleNamesFor(node) {
2167
+ if (node.source.kind === "slide") return new Set(SLIDE_STYLE_KEYS$1);
2168
+ switch (node.source.tag) {
2169
+ case "span": return new Set(TEXT_RUN_STYLE_KEYS);
2170
+ case "img": return new Set(IMAGE_STYLE_KEYS);
2171
+ case "video": return new Set(VIDEO_STYLE_KEYS);
2172
+ case "shape": return new Set(SHAPE_STYLE_KEYS);
2173
+ case "p":
2174
+ case "h1":
2175
+ case "h2":
2176
+ case "h3":
2177
+ case "h4":
2178
+ case "h5":
2179
+ case "h6": return new Set(TEXT_STYLE_KEYS);
2180
+ default: return new Set(VIEW_STYLE_KEYS);
2181
+ }
2182
+ }
2018
2183
  function sourceFor(context) {
2019
2184
  return context.activeSlot?.source ?? context.source;
2020
2185
  }
@@ -2117,6 +2282,32 @@ function authoringPropDiagnostic(input) {
2117
2282
  ...input.help ? { help: input.help } : {}
2118
2283
  });
2119
2284
  }
2285
+ function videoPosterMissingDiagnostic(input) {
2286
+ return diagnostic({
2287
+ severity: "warning",
2288
+ code: "W_COMPILE_VIDEO_POSTER_MISSING",
2289
+ title: "video poster is missing",
2290
+ message: "Video nodes without poster or posterData may render with a black placeholder until the playback renderer loads the media.",
2291
+ labels: [{
2292
+ path: `${input.path}.props`,
2293
+ message: "Add poster or posterData when the first visual frame matters."
2294
+ }],
2295
+ help: ["The video is still included as playable media; this warning only covers the static placeholder."]
2296
+ });
2297
+ }
2298
+ function unsupportedStylePropDiagnostic(input) {
2299
+ return diagnostic({
2300
+ severity: "warning",
2301
+ code: "W_COMPILE_UNSUPPORTED_STYLE_PROP",
2302
+ title: "unsupported style property",
2303
+ message: `Style property "${input.property}" is not supported by the deckjsx CSS-like style subset for ${input.tag}.`,
2304
+ labels: [{
2305
+ path: input.path,
2306
+ message: `${input.property} is outside the supported deckjsx style property subset.`
2307
+ }],
2308
+ help: ["Use a supported deckjsx style key, or keep this value in your own data layer until deckjsx adds that CSS property."]
2309
+ });
2310
+ }
2120
2311
  function validateAuthoringProps(state, node, path) {
2121
2312
  const supported = supportedPropNamesFor(node);
2122
2313
  const propPath = node.source.kind === "slide" ? `${path}.options` : `${path}.props`;
@@ -2134,6 +2325,18 @@ function validateAuthoringProps(state, node, path) {
2134
2325
  path: `${propPath}.style`,
2135
2326
  message: "The style prop must be an object when it is provided."
2136
2327
  }));
2328
+ if (isRecord(style)) {
2329
+ const supportedStyleNames = supportedStyleNamesFor(node);
2330
+ const tag = sourceName(node);
2331
+ Object.keys(style).forEach((key) => {
2332
+ if (supportedStyleNames.has(key)) return;
2333
+ addDiagnostic(state, unsupportedStylePropDiagnostic({
2334
+ path: `${propPath}.style.${key}`,
2335
+ property: key,
2336
+ tag
2337
+ }));
2338
+ });
2339
+ }
2137
2340
  }
2138
2341
  if (isShapeElement(node) && node.props.shape !== void 0) {
2139
2342
  if (node.props.shape !== "rect" && node.props.shape !== "ellipse" && node.props.shape !== "line") addDiagnostic(state, authoringPropDiagnostic({
@@ -2217,6 +2420,134 @@ function assetForImage(state, idMaterial, props, path) {
2217
2420
  state.assets.set(id, entity);
2218
2421
  return id;
2219
2422
  }
2423
+ function mediaSourceFromString(value) {
2424
+ if (/^https?:\/\//i.test(value)) return {
2425
+ kind: "url",
2426
+ url: value
2427
+ };
2428
+ return {
2429
+ kind: "path",
2430
+ path: value
2431
+ };
2432
+ }
2433
+ function dataMediaType$1(value) {
2434
+ const commaIndex = value.indexOf(",");
2435
+ if (!value.startsWith("data:") || commaIndex === -1) return;
2436
+ const metadata = value.slice(5, commaIndex);
2437
+ return metadata ? metadata.replace(/;base64$/, "") : void 0;
2438
+ }
2439
+ function assetForVideoSource(input) {
2440
+ const { state, props, path } = input;
2441
+ const hasSrc = props.src !== void 0;
2442
+ const hasData = props.data !== void 0;
2443
+ if (hasSrc && typeof props.src !== "string") {
2444
+ addDiagnostic(state, authoringPropDiagnostic({
2445
+ code: "E_COMPILE_VIDEO_SOURCE_INVALID",
2446
+ title: "video src prop is invalid",
2447
+ path: `${path}.props.src`,
2448
+ message: "The video src prop must be a string when it is provided."
2449
+ }));
2450
+ return;
2451
+ }
2452
+ if (hasData && typeof props.data !== "string") {
2453
+ addDiagnostic(state, authoringPropDiagnostic({
2454
+ code: "E_COMPILE_VIDEO_SOURCE_INVALID",
2455
+ title: "video data prop is invalid",
2456
+ path: `${path}.props.data`,
2457
+ message: "The video data prop must be a string when it is provided."
2458
+ }));
2459
+ return;
2460
+ }
2461
+ if (typeof props.src === "string" && typeof props.data === "string") {
2462
+ addDiagnostic(state, authoringPropDiagnostic({
2463
+ code: "E_COMPILE_VIDEO_SOURCE_INVALID",
2464
+ title: "video source props are ambiguous",
2465
+ path: `${path}.props`,
2466
+ message: "Use either video src or video data, not both."
2467
+ }));
2468
+ return;
2469
+ }
2470
+ if (typeof props.src !== "string" && typeof props.data !== "string") {
2471
+ addDiagnostic(state, authoringPropDiagnostic({
2472
+ code: "E_COMPILE_VIDEO_SOURCE_INVALID",
2473
+ title: "video source is missing",
2474
+ path: `${path}.props`,
2475
+ message: "Video nodes require either src or data.",
2476
+ help: ["Add a src path or data URI to the video."]
2477
+ }));
2478
+ return;
2479
+ }
2480
+ let source;
2481
+ if (typeof props.src === "string") source = mediaSourceFromString(props.src);
2482
+ else {
2483
+ const data = props.data;
2484
+ if (typeof data !== "string") return;
2485
+ source = {
2486
+ kind: "data",
2487
+ data
2488
+ };
2489
+ }
2490
+ const id = assetEntityId(input.idMaterial);
2491
+ state.assets.set(id, {
2492
+ id,
2493
+ kind: "video",
2494
+ source,
2495
+ metadata: source.kind === "data" ? { mediaType: dataMediaType$1(source.data) } : {},
2496
+ resolution: "unresolved"
2497
+ });
2498
+ return id;
2499
+ }
2500
+ function assetForVideoPoster(state, idMaterial, props, path) {
2501
+ const hasPoster = props.poster !== void 0;
2502
+ const hasPosterData = props.posterData !== void 0;
2503
+ if (!hasPoster && !hasPosterData) return;
2504
+ if (hasPoster && typeof props.poster !== "string") {
2505
+ addDiagnostic(state, authoringPropDiagnostic({
2506
+ code: "E_COMPILE_VIDEO_POSTER_INVALID",
2507
+ title: "video poster prop is invalid",
2508
+ path: `${path}.props.poster`,
2509
+ message: "The video poster prop must be a string when it is provided."
2510
+ }));
2511
+ return;
2512
+ }
2513
+ if (hasPosterData && typeof props.posterData !== "string") {
2514
+ addDiagnostic(state, authoringPropDiagnostic({
2515
+ code: "E_COMPILE_VIDEO_POSTER_INVALID",
2516
+ title: "video posterData prop is invalid",
2517
+ path: `${path}.props.posterData`,
2518
+ message: "The video posterData prop must be a string when it is provided."
2519
+ }));
2520
+ return;
2521
+ }
2522
+ if (typeof props.poster === "string" && typeof props.posterData === "string") {
2523
+ addDiagnostic(state, authoringPropDiagnostic({
2524
+ code: "E_COMPILE_VIDEO_POSTER_INVALID",
2525
+ title: "video poster props are ambiguous",
2526
+ path: `${path}.props`,
2527
+ message: "Use either video poster or video posterData, not both."
2528
+ }));
2529
+ return;
2530
+ }
2531
+ let source;
2532
+ if (typeof props.poster === "string") source = mediaSourceFromString(props.poster);
2533
+ else {
2534
+ const data = props.posterData;
2535
+ if (typeof data !== "string") return;
2536
+ source = {
2537
+ kind: "data",
2538
+ data
2539
+ };
2540
+ }
2541
+ const id = assetEntityId(idMaterial);
2542
+ state.assets.set(id, {
2543
+ id,
2544
+ kind: "image",
2545
+ source,
2546
+ metadata: source.kind === "data" ? { mediaType: dataMediaType$1(source.data) } : {},
2547
+ resolution: "unresolved"
2548
+ });
2549
+ return id;
2550
+ }
2220
2551
  function semanticBase(state, node, id, kind, path, material, context) {
2221
2552
  const styleRef = styleRefFor(state, material, kind, node.props);
2222
2553
  const templateAreaRef = templateAreaRefFor(state, templateAreaValueFor(node), path, context);
@@ -2485,6 +2816,27 @@ function buildNode(state, node, context, index) {
2485
2816
  kind: "image"
2486
2817
  };
2487
2818
  }
2819
+ if (isVideoElement(node)) {
2820
+ if (node.children.length > 0) addDiagnostic(state, invalidStructure(path, "video cannot have children", "Video nodes are leaf nodes."));
2821
+ const assetRef = assetForVideoSource({
2822
+ state,
2823
+ idMaterial: material,
2824
+ props: node.props,
2825
+ path
2826
+ });
2827
+ const posterAssetRef = assetForVideoPoster(state, [...material, "poster"], node.props, path);
2828
+ if (node.props.poster === void 0 && node.props.posterData === void 0) addDiagnostic(state, videoPosterMissingDiagnostic({ path }));
2829
+ state.nodes.set(id, {
2830
+ ...semanticBase(state, node, id, "video", path, material, nodeContext),
2831
+ kind: "video",
2832
+ ...assetRef ? { assetRef } : {},
2833
+ ...posterAssetRef ? { posterAssetRef } : {}
2834
+ });
2835
+ return {
2836
+ id,
2837
+ kind: "video"
2838
+ };
2839
+ }
2488
2840
  if (isShapeElement(node)) {
2489
2841
  state.nodes.set(id, {
2490
2842
  ...semanticBase(state, node, id, "shape", path, material, nodeContext),
@@ -2712,6 +3064,9 @@ function effectiveProjectedValues(element) {
2712
3064
  ...element.kind === "text" ? { textStyle: element.style } : {},
2713
3065
  ...element.kind === "image" ? { imageSource: element.source } : {},
2714
3066
  ...element.kind === "image" ? { imageObjectPosition: element.objectPosition } : {},
3067
+ ...element.kind === "video" ? { videoSource: element.source } : {},
3068
+ ...element.kind === "video" && element.posterSource ? { videoPosterSource: element.posterSource } : {},
3069
+ ...element.kind === "video" ? { videoObjectPosition: element.objectPosition } : {},
2715
3070
  ...element.unsupportedSemantics?.length ? { unsupportedSemantics: element.unsupportedSemantics } : {}
2716
3071
  };
2717
3072
  }
@@ -3061,10 +3416,12 @@ function rawTextForNode(graph, node) {
3061
3416
  return text.length > 0 ? text : void 0;
3062
3417
  }
3063
3418
  function originFor$1(node) {
3419
+ const videoAssetIds = node.kind === "video" ? [node.assetRef, node.posterAssetRef].filter((id) => id !== void 0) : [];
3064
3420
  return {
3065
3421
  graphNodeIds: [node.id],
3066
3422
  ...node.styleRef ? { styleEntityIds: [node.styleRef] } : {},
3067
3423
  ...node.kind === "image" && node.assetRef ? { assetEntityIds: [node.assetRef] } : {},
3424
+ ...videoAssetIds.length > 0 ? { assetEntityIds: videoAssetIds } : {},
3068
3425
  ...node.origin.source ? { source: node.origin.source } : {}
3069
3426
  };
3070
3427
  }
@@ -3188,7 +3545,7 @@ function pushDefined(values, value) {
3188
3545
  function resolvedPropsFor(node, resolvedStyles) {
3189
3546
  const resolved = resolvedStyles.get(node.id);
3190
3547
  if (!resolved) return {};
3191
- return Object.fromEntries(Object.entries(resolved.properties).filter(([, property]) => property.source.layer !== "default").map(([key, property]) => [key, property.value]));
3548
+ return Object.fromEntries(Object.entries(resolved.properties).filter(([, property]) => property.source.layer !== "default" && property.source.layer !== "inherited").map(([key, property]) => [key, property.value]));
3192
3549
  }
3193
3550
  function sourceKeyForOrigin$2(source) {
3194
3551
  return !source || source.kind === "root" ? "root" : source.sourceIdentity;
@@ -3235,6 +3592,9 @@ function collectTextOrigin(graph, node) {
3235
3592
  ...styleEntityIds.length > 0 ? { styleEntityIds: [...new Set(styleEntityIds)] } : {}
3236
3593
  };
3237
3594
  }
3595
+ function collectVideoAssetIds(node) {
3596
+ return [node.assetRef, node.posterAssetRef].filter((id) => id !== void 0);
3597
+ }
3238
3598
  function layoutOriginFor(graph, node, templates) {
3239
3599
  const templateAreaKind = templateAreaKindFor$1(node, templates);
3240
3600
  if (node.kind === "text") return {
@@ -3247,6 +3607,7 @@ function layoutOriginFor(graph, node, templates) {
3247
3607
  graphNodeIds: [node.id],
3248
3608
  ...node.styleRef ? { styleEntityIds: [node.styleRef] } : {},
3249
3609
  ...node.kind === "image" && node.assetRef ? { assetEntityIds: [node.assetRef] } : {},
3610
+ ...node.kind === "video" && collectVideoAssetIds(node).length > 0 ? { assetEntityIds: collectVideoAssetIds(node) } : {},
3250
3611
  ...node.origin.source ? { source: node.origin.source } : {},
3251
3612
  ...node.templateAreaRef ? { templateAreaRef: node.templateAreaRef } : {},
3252
3613
  ...templateAreaKind ? { templateAreaKind } : {}
@@ -3315,6 +3676,23 @@ function layoutInputNodeFromGraph(graph, resolvedStyles, node, assetProbeArtifac
3315
3676
  origin: layoutOriginFor(graph, node, templates)
3316
3677
  };
3317
3678
  }
3679
+ case "video": {
3680
+ const props = propsWithTemplateAreaFrame(resolvedStyles, node, templates);
3681
+ const asset = node.assetRef ? graph.assets.get(node.assetRef) : void 0;
3682
+ if (!asset) return;
3683
+ const posterAsset = node.posterAssetRef ? graph.assets.get(node.posterAssetRef) : void 0;
3684
+ return {
3685
+ kind: "video",
3686
+ props: {
3687
+ ...props,
3688
+ ...videoSourceProps(asset),
3689
+ ...posterAsset ? videoPosterSourceProps(posterAsset) : {}
3690
+ },
3691
+ ...node.assetRef ? { assetProbe: assetProbeArtifacts?.get(node.assetRef)?.probe } : {},
3692
+ ...node.posterAssetRef ? { posterAssetProbe: assetProbeArtifacts?.get(node.posterAssetRef)?.probe } : {},
3693
+ origin: layoutOriginFor(graph, node, templates)
3694
+ };
3695
+ }
3318
3696
  case "shape": return {
3319
3697
  kind: "shape",
3320
3698
  props: {
@@ -3331,6 +3709,14 @@ function imageSourceProps(asset) {
3331
3709
  if (asset.source.kind === "data") return { data: asset.source.data };
3332
3710
  return { src: asset.source.kind === "path" ? asset.source.path : asset.source.url };
3333
3711
  }
3712
+ function videoSourceProps(asset) {
3713
+ if (asset.source.kind === "data") return { data: asset.source.data };
3714
+ return { src: asset.source.kind === "path" ? asset.source.path : asset.source.url };
3715
+ }
3716
+ function videoPosterSourceProps(asset) {
3717
+ if (asset.source.kind === "data") return { posterData: asset.source.data };
3718
+ return { poster: asset.source.kind === "path" ? asset.source.path : asset.source.url };
3719
+ }
3334
3720
  function buildLayoutInputSnapshot(input) {
3335
3721
  const document = input.graph.nodes.get(input.graph.documentId);
3336
3722
  const slideNodes = document?.kind === "document" ? document.children.map((id) => input.graph.nodes.get(id)).filter((node) => node?.kind === "slide") : [];
@@ -3913,16 +4299,120 @@ function resolveGridSelfAlignment(value) {
3913
4299
  return value;
3914
4300
  }
3915
4301
  //#endregion
4302
+ //#region src/style/defaulting.ts
4303
+ function authoredLengthOrUndefined(value) {
4304
+ if (typeof value === "string" && (value.trim().toLowerCase() === "auto" || isCssWideKeyword(value))) return;
4305
+ return value;
4306
+ }
4307
+ function hasAuthoredLength(value) {
4308
+ return authoredLengthOrUndefined(value) !== void 0;
4309
+ }
4310
+ function defaultingTokens(value) {
4311
+ if (typeof value === "string") return value.trim().split(/\s+/).filter(Boolean);
4312
+ if (Array.isArray(value)) return value;
4313
+ return value === void 0 || value === null ? [] : [value];
4314
+ }
4315
+ function hasAutoToken(value) {
4316
+ return defaultingTokens(value).some((token) => typeof token === "string" && token.trim().toLowerCase() === "auto");
4317
+ }
4318
+ function hasCssWideKeywordToken(value) {
4319
+ return defaultingTokens(value).some((token) => isCssWideKeyword(token));
4320
+ }
4321
+ //#endregion
3916
4322
  //#region src/layout/spacing.ts
3917
- function parseSpacing(value, context) {
4323
+ function splitSpacingTokens(value) {
4324
+ const tokens = [];
4325
+ let current = "";
4326
+ let depth = 0;
4327
+ for (const char of value) {
4328
+ if (char === "(") {
4329
+ depth += 1;
4330
+ current += char;
4331
+ continue;
4332
+ }
4333
+ if (char === ")") {
4334
+ depth = Math.max(depth - 1, 0);
4335
+ current += char;
4336
+ continue;
4337
+ }
4338
+ if (/\s/.test(char) && depth === 0) {
4339
+ if (current.trim()) tokens.push(current.trim());
4340
+ current = "";
4341
+ continue;
4342
+ }
4343
+ current += char;
4344
+ }
4345
+ if (current.trim()) tokens.push(current.trim());
4346
+ return tokens;
4347
+ }
4348
+ function expandSpacingTokens(value) {
4349
+ const tokens = splitSpacingTokens(value);
4350
+ if (tokens.length <= 1) return;
4351
+ if (tokens.length > 4) throw new Error(`Unsupported spacing shorthand: ${value}`);
4352
+ const [top, right = top, bottom = top, left = right] = tokens;
4353
+ if (top === void 0) return;
4354
+ return [
4355
+ top,
4356
+ right,
4357
+ bottom,
4358
+ left
4359
+ ];
4360
+ }
4361
+ function parseSpacing(value, context, percentageBaseEmu = 0) {
4362
+ if (value === void 0) return [
4363
+ 0,
4364
+ 0,
4365
+ 0,
4366
+ 0
4367
+ ];
4368
+ if (typeof value === "string") {
4369
+ const shorthand = expandSpacingTokens(value);
4370
+ if (shorthand) return [
4371
+ parseLength(shorthand[0], percentageBaseEmu, 0, context),
4372
+ parseLength(shorthand[1], percentageBaseEmu, 0, context),
4373
+ parseLength(shorthand[2], percentageBaseEmu, 0, context),
4374
+ parseLength(shorthand[3], percentageBaseEmu, 0, context)
4375
+ ];
4376
+ }
4377
+ if (typeof value === "number" || typeof value === "string") {
4378
+ const scalar = parseLength(value, percentageBaseEmu, 0, context);
4379
+ return [
4380
+ scalar,
4381
+ scalar,
4382
+ scalar,
4383
+ scalar
4384
+ ];
4385
+ }
4386
+ return [
4387
+ parseLength(value[0], percentageBaseEmu, 0, context),
4388
+ parseLength(value[1], percentageBaseEmu, 0, context),
4389
+ parseLength(value[2], percentageBaseEmu, 0, context),
4390
+ parseLength(value[3], percentageBaseEmu, 0, context)
4391
+ ];
4392
+ }
4393
+ function parseLengthOrAuto(value, percentageBaseEmu, fallbackEmu, context) {
4394
+ const authoredValue = authoredLengthOrUndefined(value);
4395
+ if (authoredValue === void 0) return fallbackEmu;
4396
+ return parseLength(authoredValue, percentageBaseEmu, fallbackEmu, context);
4397
+ }
4398
+ function parseSpacingAllowAuto(value, context, percentageBaseEmu = 0, autoFallbackEmu = 0) {
3918
4399
  if (value === void 0) return [
3919
4400
  0,
3920
4401
  0,
3921
4402
  0,
3922
4403
  0
3923
4404
  ];
4405
+ if (typeof value === "string") {
4406
+ const shorthand = expandSpacingTokens(value);
4407
+ if (shorthand) return [
4408
+ parseLengthOrAuto(shorthand[0], percentageBaseEmu, autoFallbackEmu, context),
4409
+ parseLengthOrAuto(shorthand[1], percentageBaseEmu, autoFallbackEmu, context),
4410
+ parseLengthOrAuto(shorthand[2], percentageBaseEmu, autoFallbackEmu, context),
4411
+ parseLengthOrAuto(shorthand[3], percentageBaseEmu, autoFallbackEmu, context)
4412
+ ];
4413
+ }
3924
4414
  if (typeof value === "number" || typeof value === "string") {
3925
- const scalar = parseLength(value, 0, 0, context);
4415
+ const scalar = parseLengthOrAuto(value, percentageBaseEmu, autoFallbackEmu, context);
3926
4416
  return [
3927
4417
  scalar,
3928
4418
  scalar,
@@ -3931,10 +4421,10 @@ function parseSpacing(value, context) {
3931
4421
  ];
3932
4422
  }
3933
4423
  return [
3934
- parseLength(value[0], 0, 0, context),
3935
- parseLength(value[1], 0, 0, context),
3936
- parseLength(value[2], 0, 0, context),
3937
- parseLength(value[3], 0, 0, context)
4424
+ parseLengthOrAuto(value[0], percentageBaseEmu, autoFallbackEmu, context),
4425
+ parseLengthOrAuto(value[1], percentageBaseEmu, autoFallbackEmu, context),
4426
+ parseLengthOrAuto(value[2], percentageBaseEmu, autoFallbackEmu, context),
4427
+ parseLengthOrAuto(value[3], percentageBaseEmu, autoFallbackEmu, context)
3938
4428
  ];
3939
4429
  }
3940
4430
  function expandRawSpacing(value) {
@@ -3944,12 +4434,21 @@ function expandRawSpacing(value) {
3944
4434
  void 0,
3945
4435
  void 0
3946
4436
  ];
3947
- if (typeof value === "number" || typeof value === "string") return [
3948
- value,
3949
- value,
3950
- value,
3951
- value
3952
- ];
4437
+ if (typeof value === "number" || typeof value === "string") {
4438
+ const shorthand = typeof value === "string" ? expandSpacingTokens(value) : void 0;
4439
+ if (shorthand) return [
4440
+ shorthand[0],
4441
+ shorthand[1],
4442
+ shorthand[2],
4443
+ shorthand[3]
4444
+ ];
4445
+ return [
4446
+ value,
4447
+ value,
4448
+ value,
4449
+ value
4450
+ ];
4451
+ }
3953
4452
  return [
3954
4453
  value[0],
3955
4454
  value[1],
@@ -3977,9 +4476,9 @@ function resolveInset(value, top, right, bottom, left) {
3977
4476
  left: left ?? baseLeft
3978
4477
  };
3979
4478
  }
3980
- function parseSpacingInPoints(value, context) {
4479
+ function parseSpacingInPoints(value, context, percentageBaseEmu = 0) {
3981
4480
  if (value === void 0) return;
3982
- const spacing = parseSpacing(value, context);
4481
+ const spacing = parseSpacing(value, context, percentageBaseEmu);
3983
4482
  return [
3984
4483
  spacing[0] / EMU_PER_INCH * 72,
3985
4484
  spacing[1] / EMU_PER_INCH * 72,
@@ -5416,7 +5915,7 @@ function parseStrokeDasharray(value, context) {
5416
5915
  if (rawTokens.length === 0) return;
5417
5916
  const lengths = rawTokens.map((token) => {
5418
5917
  if (/^-?(?:\d+|\d*\.\d+)$/.test(token)) return Number.parseFloat(token);
5419
- if (/^-?(?:\d+|\d*\.\d+)(?:pt|in|px|em|rem|vh|vw|ch)$/i.test(token)) return parsePointToken(token, 0, context);
5918
+ if (/^-?(?:\d+|\d*\.\d+)(?:in|cm|mm|q|pt|pc|px|em|rem|vh|vw|vmin|vmax|ch)$/i.test(token)) return parsePointToken(token, 0, context);
5420
5919
  throw new Error(`Unsupported strokeDasharray token: ${token}`);
5421
5920
  });
5422
5921
  if (lengths.some((length) => !Number.isFinite(length) || length < 0)) throw new Error(`Unsupported strokeDasharray value: ${value}`);
@@ -5504,10 +6003,15 @@ function parseTextDecoration(value) {
5504
6003
  };
5505
6004
  }
5506
6005
  function resolveLineHeight(lineHeight, context) {
5507
- if (lineHeight === void 0 || lineHeight === "normal") return {};
6006
+ if (lineHeight === void 0 || lineHeight === "normal" || isCssWideKeyword(lineHeight)) return {};
5508
6007
  if (typeof lineHeight === "number") return { lineSpacingMultiple: lineHeight };
5509
6008
  return { lineSpacing: parsePointValue(lineHeight, 0, context) };
5510
6009
  }
6010
+ function resolveCharacterSpacing(charSpacing, context) {
6011
+ if (charSpacing === void 0 || isCssWideKeyword(charSpacing)) return;
6012
+ if (charSpacing === "normal") return 0;
6013
+ return parsePointValue(charSpacing, 0, context);
6014
+ }
5511
6015
  function resolveTextWrap(wrap, whiteSpace, wordBreak, overflowWrap) {
5512
6016
  if (wrap !== void 0) return wrap;
5513
6017
  if (wordBreak === "break-all" || wordBreak === "break-word") return true;
@@ -5635,10 +6139,11 @@ function extractText(children, textTransform) {
5635
6139
  }
5636
6140
  //#endregion
5637
6141
  //#region src/layout/normalization.ts
5638
- function resolveFlexDirection(direction, flexDirection) {
6142
+ function resolveFlexDirection(direction, flexDirection, display) {
5639
6143
  if (direction) return direction;
5640
6144
  if (flexDirection === "row") return "horizontal";
5641
6145
  if (flexDirection === "column") return "vertical";
6146
+ if (display === "flex") return "horizontal";
5642
6147
  }
5643
6148
  function resolveLayout(layout, display, position) {
5644
6149
  if (layout) return layout;
@@ -5652,6 +6157,10 @@ function resolveGap(gap, rowGap, columnGap, direction) {
5652
6157
  if (direction === "vertical") return rowGap ?? columnGap;
5653
6158
  return rowGap ?? columnGap;
5654
6159
  }
6160
+ function normalizeImageFit(value) {
6161
+ if (value === "fill") return "stretch";
6162
+ return value;
6163
+ }
5655
6164
  function isCssAlignSelf(value) {
5656
6165
  return value === "start" || value === "flex-start" || value === "center" || value === "end" || value === "flex-end" || value === "stretch" || value === "auto";
5657
6166
  }
@@ -5722,7 +6231,7 @@ function normalizeViewProps(props) {
5722
6231
  authored.gridAutoColumns = resolved.gridAutoColumns ?? gridContainerAuthoring.gridAutoColumns;
5723
6232
  authored.gridAutoRows = resolved.gridAutoRows ?? gridContainerAuthoring.gridAutoRows;
5724
6233
  authored.gridAutoFlow = resolved.gridAutoFlow ?? gridContainerAuthoring.gridAutoFlow;
5725
- const direction = resolveFlexDirection(authored.direction, authored.flexDirection);
6234
+ const direction = resolveFlexDirection(authored.direction, authored.flexDirection, authored.display);
5726
6235
  const inset = resolveInset(authored.inset, authored.top, authored.right, authored.bottom, authored.left);
5727
6236
  return {
5728
6237
  ...authored,
@@ -5781,7 +6290,7 @@ function normalizeTextProps(props) {
5781
6290
  italic: resolved.italic ?? (resolved.fontStyle === "italic" ? true : void 0),
5782
6291
  underline: resolved.underline ?? decoration.underline,
5783
6292
  strike: resolved.strike ?? decoration.strike,
5784
- charSpacing: resolved.charSpacing ?? resolved.letterSpacing,
6293
+ charSpacing: resolved.charSpacing ?? (resolved.letterSpacing === "normal" ? 0 : resolved.letterSpacing),
5785
6294
  backgroundColor: resolved.backgroundColor ?? background.backgroundColor,
5786
6295
  borderColor: resolved.borderColor ?? border.borderColor,
5787
6296
  borderWidth: resolved.borderWidth ?? border.borderWidth,
@@ -5819,13 +6328,32 @@ function normalizeImageProps(props, context) {
5819
6328
  right: inset?.right ?? resolved.right,
5820
6329
  bottom: inset?.bottom ?? resolved.bottom,
5821
6330
  left: inset?.left ?? resolved.left,
5822
- fit: resolved.fit ?? resolved.objectFit,
6331
+ fit: normalizeImageFit(resolved.fit ?? resolved.objectFit),
5823
6332
  objectPosition: resolved.objectPosition,
5824
6333
  crop: resolved.crop,
5825
6334
  rounding: resolved.rounding ?? (resolved.borderRadius !== void 0 ? parseLength(resolved.borderRadius, 0, 0, context) > 0 : void 0),
5826
6335
  margin: resolveBoxSpacing(resolved.margin, resolved.marginTop, resolved.marginRight, resolved.marginBottom, resolved.marginLeft)
5827
6336
  };
5828
6337
  }
6338
+ function normalizeVideoProps(props, context) {
6339
+ const { style, ...rest } = props;
6340
+ const resolved = {
6341
+ ...rest,
6342
+ ...style
6343
+ };
6344
+ const inset = resolveInset(resolved.inset, resolved.top, resolved.right, resolved.bottom, resolved.left);
6345
+ return {
6346
+ ...resolved,
6347
+ top: inset?.top ?? resolved.top,
6348
+ right: inset?.right ?? resolved.right,
6349
+ bottom: inset?.bottom ?? resolved.bottom,
6350
+ left: inset?.left ?? resolved.left,
6351
+ fit: normalizeImageFit(resolved.fit ?? resolved.objectFit),
6352
+ objectPosition: resolved.objectPosition,
6353
+ rounding: resolved.rounding ?? (resolved.borderRadius !== void 0 ? parseLength(resolved.borderRadius, 0, 0, context) > 0 : void 0),
6354
+ margin: resolveBoxSpacing(resolved.margin, resolved.marginTop, resolved.marginRight, resolved.marginBottom, resolved.marginLeft)
6355
+ };
6356
+ }
5829
6357
  function normalizeSlideProps(props) {
5830
6358
  const { style, ...rest } = props;
5831
6359
  const resolved = {
@@ -6213,7 +6741,8 @@ function matrixTranslatePxToEmu(value) {
6213
6741
  function parseAspectRatio(value) {
6214
6742
  if (value === void 0) return;
6215
6743
  if (typeof value === "number") return value > 0 ? value : void 0;
6216
- const normalized = value.replace(/\s+/g, "");
6744
+ const normalized = value.replace(/\s+/g, "").toLowerCase();
6745
+ if (normalized === "auto") return;
6217
6746
  if (!normalized.includes("/")) {
6218
6747
  const parsed = Number.parseFloat(normalized);
6219
6748
  return Number.isFinite(parsed) && parsed > 0 ? parsed : void 0;
@@ -6245,35 +6774,51 @@ function inflateSpecifiedBoxSize(valueEmu, boxSizing, padding, dimension) {
6245
6774
  if (boxSizing !== "content-box") return valueEmu;
6246
6775
  return valueEmu + (dimension === "width" ? padding[1] + padding[3] : padding[0] + padding[2]);
6247
6776
  }
6777
+ function nonAutoLength(value) {
6778
+ if (typeof value === "string" && (value.trim().toLowerCase() === "auto" || isCssWideKeyword(value))) return;
6779
+ return value;
6780
+ }
6781
+ function specifiedLength(value) {
6782
+ return nonAutoLength(value);
6783
+ }
6248
6784
  function frameFromProps(props, parent, placement, context) {
6249
6785
  const transform = parseTransformShorthandOrIgnore(props.transform);
6250
6786
  const resolvedInset = resolveInset(props.inset, props.top, props.right, props.bottom, props.left);
6251
- const resolvedX = props.x ?? resolvedInset?.left;
6252
- const resolvedY = props.y ?? resolvedInset?.top;
6253
- const resolvedRight = resolvedInset?.right;
6254
- const resolvedBottom = resolvedInset?.bottom;
6787
+ const isRelativePosition = props.position === "relative";
6788
+ const relativeLeft = nonAutoLength(props.x ?? resolvedInset?.left);
6789
+ const relativeTop = nonAutoLength(props.y ?? resolvedInset?.top);
6790
+ const relativeRight = nonAutoLength(resolvedInset?.right);
6791
+ const relativeBottom = nonAutoLength(resolvedInset?.bottom);
6792
+ const specifiedWidth = specifiedLength(props.width);
6793
+ const specifiedHeight = specifiedLength(props.height);
6794
+ const resolvedX = isRelativePosition ? void 0 : relativeLeft;
6795
+ const resolvedY = isRelativePosition ? void 0 : relativeTop;
6796
+ const resolvedRight = isRelativePosition ? void 0 : relativeRight;
6797
+ const resolvedBottom = isRelativePosition ? void 0 : relativeBottom;
6255
6798
  const aspectRatio = parseAspectRatio(props.aspectRatio);
6256
- const padding = parseSpacing(props.padding, context);
6799
+ const padding = parseSpacing(props.padding, context, parent.widthEmu);
6257
6800
  const boxSizing = props.boxSizing ?? "border-box";
6258
6801
  const minWidthEmu = parseLength(props.minWidth, parent.widthEmu, 0, context);
6259
6802
  const minHeightEmu = parseLength(props.minHeight, parent.heightEmu, 0, context);
6260
6803
  const maxWidthEmu = parseLength(props.maxWidth, parent.widthEmu, Number.POSITIVE_INFINITY, context);
6261
6804
  const maxHeightEmu = parseLength(props.maxHeight, parent.heightEmu, Number.POSITIVE_INFINITY, context);
6262
6805
  const clampSize = (value, min, max) => Math.max(min, Math.min(value, max));
6263
- const baseWidth = placement?.widthEmu ?? (props.width !== void 0 ? parseLength(props.width, parent.widthEmu, 0, context) : resolvedX !== void 0 && resolvedRight !== void 0 ? Math.max(parent.widthEmu - parseLength(resolvedX, parent.widthEmu, 0, context) - parseLength(resolvedRight, parent.widthEmu, 0, context), 0) : 0);
6264
- const baseHeight = placement?.heightEmu ?? (props.height !== void 0 ? parseLength(props.height, parent.heightEmu, 0, context) : resolvedY !== void 0 && resolvedBottom !== void 0 ? Math.max(parent.heightEmu - parseLength(resolvedY, parent.heightEmu, 0, context) - parseLength(resolvedBottom, parent.heightEmu, 0, context), 0) : 0);
6806
+ const baseWidth = placement?.widthEmu ?? (specifiedWidth !== void 0 ? parseLength(specifiedWidth, parent.widthEmu, 0, context) : resolvedX !== void 0 && resolvedRight !== void 0 ? Math.max(parent.widthEmu - parseLength(resolvedX, parent.widthEmu, 0, context) - parseLength(resolvedRight, parent.widthEmu, 0, context), 0) : 0);
6807
+ const baseHeight = placement?.heightEmu ?? (specifiedHeight !== void 0 ? parseLength(specifiedHeight, parent.heightEmu, 0, context) : resolvedY !== void 0 && resolvedBottom !== void 0 ? Math.max(parent.heightEmu - parseLength(resolvedY, parent.heightEmu, 0, context) - parseLength(resolvedBottom, parent.heightEmu, 0, context), 0) : 0);
6265
6808
  const aspectResolvedWidth = baseWidth === 0 && aspectRatio !== void 0 && baseHeight > 0 ? baseHeight * aspectRatio : baseWidth;
6266
6809
  const aspectResolvedHeight = baseHeight === 0 && aspectRatio !== void 0 && aspectResolvedWidth > 0 ? aspectResolvedWidth / aspectRatio : baseHeight;
6267
6810
  const clampedWidth = clampSize(aspectResolvedWidth, minWidthEmu, maxWidthEmu);
6268
6811
  const clampedHeight = clampSize(aspectResolvedHeight, minHeightEmu, maxHeightEmu);
6269
- const widthUsesSpecifiedBox = props.width !== void 0 || props.height !== void 0 && aspectRatio !== void 0 && baseWidth === 0;
6270
- const heightUsesSpecifiedBox = props.height !== void 0 || props.width !== void 0 && aspectRatio !== void 0 && baseHeight === 0;
6812
+ const widthUsesSpecifiedBox = specifiedWidth !== void 0 || specifiedHeight !== void 0 && aspectRatio !== void 0 && baseWidth === 0;
6813
+ const heightUsesSpecifiedBox = specifiedHeight !== void 0 || specifiedWidth !== void 0 && aspectRatio !== void 0 && baseHeight === 0;
6271
6814
  const resolvedWidth = placement?.widthEmu !== void 0 || !widthUsesSpecifiedBox ? clampedWidth : inflateSpecifiedBoxSize(clampedWidth, boxSizing, padding, "width");
6272
6815
  const resolvedHeight = placement?.heightEmu !== void 0 || !heightUsesSpecifiedBox ? clampedHeight : inflateSpecifiedBoxSize(clampedHeight, boxSizing, padding, "height");
6273
6816
  const absoluteX = resolvedX !== void 0 ? parent.xEmu + parseLength(resolvedX, parent.widthEmu, 0, context) : resolvedRight !== void 0 && (props.width !== void 0 || placement?.widthEmu !== void 0) ? parent.xEmu + parent.widthEmu - parseLength(resolvedRight, parent.widthEmu, 0, context) - resolvedWidth : parent.xEmu;
6274
6817
  const absoluteY = resolvedY !== void 0 ? parent.yEmu + parseLength(resolvedY, parent.heightEmu, 0, context) : resolvedBottom !== void 0 && (props.height !== void 0 || placement?.heightEmu !== void 0) ? parent.yEmu + parent.heightEmu - parseLength(resolvedBottom, parent.heightEmu, 0, context) - resolvedHeight : parent.yEmu;
6275
- let transformedX = placement?.xEmu ?? absoluteX;
6276
- let transformedY = placement?.yEmu ?? absoluteY;
6818
+ const relativeOffsetX = isRelativePosition && relativeLeft !== void 0 ? parseLength(relativeLeft, parent.widthEmu, 0, context) : isRelativePosition && relativeRight !== void 0 ? -parseLength(relativeRight, parent.widthEmu, 0, context) : 0;
6819
+ const relativeOffsetY = isRelativePosition && relativeTop !== void 0 ? parseLength(relativeTop, parent.heightEmu, 0, context) : isRelativePosition && relativeBottom !== void 0 ? -parseLength(relativeBottom, parent.heightEmu, 0, context) : 0;
6820
+ let transformedX = (placement?.xEmu ?? absoluteX) + relativeOffsetX;
6821
+ let transformedY = (placement?.yEmu ?? absoluteY) + relativeOffsetY;
6277
6822
  let transformedWidth = resolvedWidth;
6278
6823
  let transformedHeight = resolvedHeight;
6279
6824
  let transformRotation = 0;
@@ -6468,11 +7013,11 @@ function resolveCrossPlacement(alignment, availableCross, childCross, hasExplici
6468
7013
  sizeEmu: childCross
6469
7014
  };
6470
7015
  }
6471
- function resolveMainGap(direction, gap, rowGap, columnGap, context) {
6472
- return parseLength(direction === "horizontal" ? columnGap ?? gap ?? rowGap : rowGap ?? gap ?? columnGap, 0, 0, context);
7016
+ function resolveMainGap(direction, gap, rowGap, columnGap, context, percentageBaseEmu = 0) {
7017
+ return parseLength(direction === "horizontal" ? columnGap ?? gap ?? rowGap : rowGap ?? gap ?? columnGap, percentageBaseEmu, 0, context);
6473
7018
  }
6474
- function resolveCrossGap(direction, gap, rowGap, columnGap, context) {
6475
- return parseLength(direction === "horizontal" ? rowGap ?? gap ?? columnGap : columnGap ?? gap ?? rowGap, 0, 0, context);
7019
+ function resolveCrossGap(direction, gap, rowGap, columnGap, context, percentageBaseEmu = 0) {
7020
+ return parseLength(direction === "horizontal" ? rowGap ?? gap ?? columnGap : columnGap ?? gap ?? rowGap, percentageBaseEmu, 0, context);
6476
7021
  }
6477
7022
  function buildStackLines(entries, direction, parentFrame, availableMain, mainGapEmu, flexWrap, metrics, context) {
6478
7023
  if (entries.length === 0) return [];
@@ -6598,7 +7143,7 @@ function splitTopLevelCommaList(value) {
6598
7143
  }
6599
7144
  function tryParsePointToken(value) {
6600
7145
  if (value === "0") return 0;
6601
- if (!isDeckPointLengthString(value) || !/^-?(?:\d+|\d*\.\d+)(?:pt|in|px)$/i.test(value)) return;
7146
+ if (!isDeckPointLengthString(value)) return;
6602
7147
  return parsePointToken(value);
6603
7148
  }
6604
7149
  function parseShadowShorthand(value) {
@@ -6640,29 +7185,97 @@ function parseShadowShorthand(value) {
6640
7185
  angle: angle % 360
6641
7186
  };
6642
7187
  }
7188
+ function hasShadowSpreadRadius(value) {
7189
+ if (!value) return false;
7190
+ const trimmed = value.trim();
7191
+ if (!trimmed || trimmed.toLowerCase() === "none") return false;
7192
+ const layers = splitTopLevelCommaList(trimmed);
7193
+ if (layers.length !== 1) return false;
7194
+ const [layer] = layers;
7195
+ if (layer === void 0) return false;
7196
+ return splitCssValueTokens(layer).filter((token) => token.toLowerCase() !== "inset").filter((token) => {
7197
+ if (parseCssColor(token)) return false;
7198
+ return tryParsePointToken(token) !== void 0;
7199
+ }).length === 4;
7200
+ }
6643
7201
  //#endregion
6644
- //#region src/layout/resolve.ts
6645
- function errorReason$1(error) {
7202
+ //#region src/layout/unsupported.ts
7203
+ function errorReason$2(error) {
6646
7204
  return error instanceof Error ? error.message : String(error);
6647
7205
  }
6648
- function unsupportedSemantic$1(input) {
7206
+ function semanticValue(value) {
7207
+ if (typeof value === "string") return value;
7208
+ return JSON.stringify(value) ?? String(value);
7209
+ }
7210
+ function unsupportedSemantic(input) {
6649
7211
  if (input.value === void 0 || input.value === null || input.value === "") return;
6650
7212
  return {
6651
7213
  feature: input.feature,
6652
7214
  property: input.property,
6653
- value: typeof input.value === "string" ? input.value : JSON.stringify(input.value),
6654
- reason: errorReason$1(input.error),
7215
+ value: semanticValue(input.value),
7216
+ reason: errorReason$2(input.error),
6655
7217
  ...input.fallback ? { fallback: input.fallback } : {}
6656
7218
  };
6657
7219
  }
7220
+ function unsupportedCssWideKeywordSemantic(property, value) {
7221
+ return unsupportedSemantic({
7222
+ feature: "layout",
7223
+ property,
7224
+ value,
7225
+ error: /* @__PURE__ */ new Error("CSS-wide keywords require cascade/defaulting semantics; deckjsx v0.8.2 falls back to the supported subset initial value and preserves the authored keyword for inspection."),
7226
+ fallback: {
7227
+ strategy: "preserveAuthoredValueOnly",
7228
+ preserves: ["authoredValue"],
7229
+ missing: ["cssWideKeywordCascade"]
7230
+ }
7231
+ });
7232
+ }
7233
+ //#endregion
7234
+ //#region src/layout/image-fit.ts
7235
+ function normalizeProjectedImageFit(value) {
7236
+ if (value === "cover" || value === "contain" || value === "stretch" || value === "fill") return value === "fill" ? "stretch" : value;
7237
+ return "contain";
7238
+ }
7239
+ function unsupportedObjectFitSemantics(value) {
7240
+ if (value === void 0 || value === "cover" || value === "contain" || value === "stretch" || value === "fill") return [];
7241
+ const unsupported = unsupportedSemantic({
7242
+ feature: "image",
7243
+ property: "objectFit",
7244
+ value,
7245
+ error: /* @__PURE__ */ new Error("CSS object-fit values none and scale-down require natural-size comparison that is outside the current deckjsx v0.8.2 image projection subset."),
7246
+ fallback: {
7247
+ strategy: "preserveAuthoredValueOnly",
7248
+ preserves: ["authoredObjectFit"],
7249
+ missing: ["cssObjectFitNaturalSize"]
7250
+ }
7251
+ });
7252
+ return unsupported ? [unsupported] : [];
7253
+ }
7254
+ //#endregion
7255
+ //#region src/layout/resolve.ts
7256
+ function errorReason$1(error) {
7257
+ return error instanceof Error ? error.message : String(error);
7258
+ }
6658
7259
  function parseShadowShorthandOrIgnore(input) {
6659
7260
  try {
7261
+ const shadow = parseShadowShorthand(input.value);
7262
+ const unsupported = hasShadowSpreadRadius(input.value) ? unsupportedSemantic({
7263
+ feature: "shadow",
7264
+ property: input.property,
7265
+ value: input.value,
7266
+ error: /* @__PURE__ */ new Error(`CSS shadow spread radius is not projected by the current PPTX shadow model: ${input.value}`),
7267
+ fallback: {
7268
+ strategy: "preserveAuthoredValueOnly",
7269
+ preserves: ["projectedShadowWithoutSpread"],
7270
+ missing: ["cssShadowSpreadRadius"]
7271
+ }
7272
+ }) : void 0;
6660
7273
  return {
6661
- shadow: parseShadowShorthand(input.value),
6662
- unsupportedSemantics: []
7274
+ shadow,
7275
+ unsupportedSemantics: unsupported ? [unsupported] : []
6663
7276
  };
6664
7277
  } catch (error) {
6665
- const unsupported = unsupportedSemantic$1({
7278
+ const unsupported = unsupportedSemantic({
6666
7279
  feature: "shadow",
6667
7280
  property: input.property,
6668
7281
  value: input.value,
@@ -6750,7 +7363,7 @@ function isStrokeIntentionallyNone$1(props) {
6750
7363
  }
6751
7364
  function unsupportedStrokeFallback$1(props, error) {
6752
7365
  const input = strokeFallbackInput$1(props);
6753
- return unsupportedSemantic$1({
7366
+ return unsupportedSemantic({
6754
7367
  feature: input.feature,
6755
7368
  property: input.property,
6756
7369
  value: input.value,
@@ -6791,7 +7404,7 @@ function outlineStrokeOrFallback(props, context) {
6791
7404
  unsupportedSemantics: []
6792
7405
  };
6793
7406
  const input = outlineFallbackInput$1(props);
6794
- const semantic = unsupportedSemantic$1({
7407
+ const semantic = unsupportedSemantic({
6795
7408
  feature: "outline",
6796
7409
  property: input.property,
6797
7410
  value: input.value,
@@ -6805,7 +7418,7 @@ function outlineStrokeOrFallback(props, context) {
6805
7418
  return { unsupportedSemantics: semantic ? [semantic] : [] };
6806
7419
  } catch (error) {
6807
7420
  const input = outlineFallbackInput$1(props);
6808
- const semantic = unsupportedSemantic$1({
7421
+ const semantic = unsupportedSemantic({
6809
7422
  feature: "outline",
6810
7423
  property: input.property,
6811
7424
  value: input.value,
@@ -6823,7 +7436,7 @@ function resolveBackgroundLayersOrEmpty(input, transparency, context, frame, box
6823
7436
  try {
6824
7437
  return resolveBackgroundLayers(input.value, transparency, context, frame, boxFrames, backgroundPosition, backgroundSize, backgroundRepeat, backgroundOrigin, backgroundClip);
6825
7438
  } catch (error) {
6826
- const unsupported = unsupportedSemantic$1({
7439
+ const unsupported = unsupportedSemantic({
6827
7440
  feature: "background",
6828
7441
  property: input.property,
6829
7442
  value: input.value,
@@ -6842,7 +7455,7 @@ function unsupportedTransformSemantics$1(props) {
6842
7455
  try {
6843
7456
  parseTransformShorthand(props.transform);
6844
7457
  } catch (error) {
6845
- const semantic = unsupportedSemantic$1({
7458
+ const semantic = unsupportedSemantic({
6846
7459
  feature: "transform",
6847
7460
  property: "transform",
6848
7461
  value: props.transform,
@@ -6856,7 +7469,7 @@ function unsupportedTransformSemantics$1(props) {
6856
7469
  heightEmu: EMU_PER_INCH
6857
7470
  });
6858
7471
  } catch (error) {
6859
- const semantic = unsupportedSemantic$1({
7472
+ const semantic = unsupportedSemantic({
6860
7473
  feature: "transform",
6861
7474
  property: "transformOrigin",
6862
7475
  value: props.transformOrigin,
@@ -6874,9 +7487,331 @@ const TRANSFORM_STACKING_CONTEXT_FALLBACK_REASON$1 = "CSS transforms create a st
6874
7487
  const FILTER_EFFECT_FALLBACK_REASON$1 = "CSS filter effects are not emitted by the current PPTX writer; v0.8 preserves the authored filter as an unsupported paint semantic for inspection.";
6875
7488
  const BLEND_MODE_FALLBACK_REASON$1 = "CSS blend modes require compositing behavior that the current PPTX writer does not reproduce; v0.8 preserves the authored blend mode as an unsupported paint semantic for inspection.";
6876
7489
  const ISOLATION_FALLBACK_REASON$1 = "CSS isolation creates a compositing group; v0.8 preserves the authored isolation input but does not yet evaluate isolated compositing groups.";
7490
+ const CSS_LAYOUT_UNSUPPORTED_VALUE_REASON = "This CSS layout value is valid CSS but is outside the current deckjsx v0.8.2 layout subset; deckjsx preserves the authored value for inspection and falls back to the closest supported layout behavior.";
7491
+ const CSS_SUPPORTED_DISPLAY_VALUES = new Set([
7492
+ "block",
7493
+ "flex",
7494
+ "grid",
7495
+ "none"
7496
+ ]);
7497
+ const CSS_SUPPORTED_OVERFLOW_VALUES = new Set(["visible", "hidden"]);
7498
+ const CSS_SUPPORTED_POSITION_VALUES = new Set([
7499
+ "static",
7500
+ "relative",
7501
+ "absolute"
7502
+ ]);
7503
+ const CSS_SUPPORTED_FLEX_DIRECTION_VALUES = new Set(["row", "column"]);
7504
+ const CSS_SUPPORTED_FLEX_WRAP_VALUES = new Set(["nowrap", "wrap"]);
7505
+ const CSS_SUPPORTED_SELF_ALIGNMENT_VALUES = new Set([
7506
+ "auto",
7507
+ "start",
7508
+ "flex-start",
7509
+ "center",
7510
+ "end",
7511
+ "flex-end",
7512
+ "stretch"
7513
+ ]);
7514
+ const CSS_SUPPORTED_CONTENT_ALIGNMENT_VALUES = new Set([
7515
+ "start",
7516
+ "flex-start",
7517
+ "center",
7518
+ "end",
7519
+ "flex-end",
7520
+ "stretch",
7521
+ "space-between",
7522
+ "space-around",
7523
+ "space-evenly"
7524
+ ]);
7525
+ function normalizedCssKeyword(value) {
7526
+ if (typeof value !== "string") return;
7527
+ return value.trim().toLowerCase() || void 0;
7528
+ }
7529
+ function unsupportedCssLayoutValueSemantic(property, value, missing) {
7530
+ return unsupportedSemantic({
7531
+ feature: "layout",
7532
+ property,
7533
+ value,
7534
+ error: new Error(CSS_LAYOUT_UNSUPPORTED_VALUE_REASON),
7535
+ fallback: {
7536
+ strategy: "preserveAuthoredValueOnly",
7537
+ preserves: ["authoredValue"],
7538
+ missing
7539
+ }
7540
+ });
7541
+ }
7542
+ function addUnsupportedKeywordSemantic(input) {
7543
+ const value = normalizedCssKeyword(input.props[input.property]);
7544
+ if (value === void 0 || input.supported.has(value) || isCssWideKeyword(value)) return;
7545
+ const semantic = unsupportedCssLayoutValueSemantic(input.property, input.props[input.property], input.missing);
7546
+ if (semantic) input.unsupported.push(semantic);
7547
+ }
7548
+ function hasUnsupportedAlignmentTokens(value, supported) {
7549
+ const normalized = normalizedCssKeyword(value);
7550
+ if (normalized === void 0) return false;
7551
+ if (isCssWideKeyword(normalized)) return false;
7552
+ const tokens = normalized.split(/\s+/).filter(Boolean);
7553
+ if (tokens.length === 0) return false;
7554
+ if (tokens[0] === "safe" || tokens[0] === "unsafe") return true;
7555
+ if (tokens.length >= 2 && (tokens[0] === "first" && tokens[1] === "baseline" || tokens[0] === "last" && tokens[1] === "baseline")) return true;
7556
+ return tokens.some((token) => !supported.has(token));
7557
+ }
7558
+ function hasUnsupportedGridLineValue(value) {
7559
+ if (value === void 0 || value === null) return false;
7560
+ if (typeof value === "number") return Number.isFinite(value) && value < 1;
7561
+ const normalized = normalizedCssKeyword(value);
7562
+ if (normalized === void 0 || normalized === "auto") return false;
7563
+ if (isCssWideKeyword(normalized)) return false;
7564
+ return !/^(?:span\s+\d+|\d+)$/.test(normalized);
7565
+ }
7566
+ function hasUnsupportedGridPlacementValue(value, allowNamedArea) {
7567
+ if (value === void 0 || value === null) return false;
7568
+ if (typeof value === "number") return Number.isFinite(value) && value < 1;
7569
+ const normalized = normalizedCssKeyword(value);
7570
+ if (normalized === void 0 || normalized === "auto") return false;
7571
+ if (isCssWideKeyword(normalized)) return false;
7572
+ if (allowNamedArea && !normalized.includes("/")) return false;
7573
+ const linePattern = String.raw`(?:\d+|span\s+\d+)`;
7574
+ return !new RegExp(String.raw`^(?:${linePattern}|${linePattern}\s*/\s*${linePattern})$`).test(normalized);
7575
+ }
7576
+ function unsupportedCssLayoutValueSemantics(props) {
7577
+ const unsupported = [];
7578
+ for (const property of [
7579
+ "display",
7580
+ "overflow",
7581
+ "position",
7582
+ "flexDirection",
7583
+ "flexWrap",
7584
+ "alignSelf",
7585
+ "justifySelf",
7586
+ "placeSelf",
7587
+ "alignItems",
7588
+ "justifyItems",
7589
+ "placeItems",
7590
+ "alignContent",
7591
+ "justifyContent",
7592
+ "placeContent",
7593
+ "inset",
7594
+ "top",
7595
+ "right",
7596
+ "bottom",
7597
+ "left",
7598
+ "x",
7599
+ "y",
7600
+ "width",
7601
+ "height",
7602
+ "minWidth",
7603
+ "minHeight",
7604
+ "maxWidth",
7605
+ "maxHeight",
7606
+ "padding",
7607
+ "paddingTop",
7608
+ "paddingRight",
7609
+ "paddingBottom",
7610
+ "paddingLeft",
7611
+ "margin",
7612
+ "marginTop",
7613
+ "marginRight",
7614
+ "marginBottom",
7615
+ "marginLeft",
7616
+ "gap",
7617
+ "rowGap",
7618
+ "columnGap",
7619
+ "fontSize",
7620
+ "lineHeight",
7621
+ "charSpacing",
7622
+ "letterSpacing",
7623
+ "paragraphSpacingBefore",
7624
+ "paragraphSpacingAfter",
7625
+ "textIndent",
7626
+ "borderWidth",
7627
+ "borderTopWidth",
7628
+ "borderRightWidth",
7629
+ "borderBottomWidth",
7630
+ "borderLeftWidth",
7631
+ "outlineWidth",
7632
+ "strokeWidth"
7633
+ ]) {
7634
+ if (!hasCssWideKeywordToken(props[property])) continue;
7635
+ const semantic = unsupportedCssWideKeywordSemantic(property, props[property]);
7636
+ if (semantic) unsupported.push(semantic);
7637
+ }
7638
+ addUnsupportedKeywordSemantic({
7639
+ unsupported,
7640
+ props,
7641
+ property: "display",
7642
+ supported: CSS_SUPPORTED_DISPLAY_VALUES,
7643
+ missing: ["cssDisplayBehavior"]
7644
+ });
7645
+ addUnsupportedKeywordSemantic({
7646
+ unsupported,
7647
+ props,
7648
+ property: "overflow",
7649
+ supported: CSS_SUPPORTED_OVERFLOW_VALUES,
7650
+ missing: ["cssOverflowBehavior"]
7651
+ });
7652
+ addUnsupportedKeywordSemantic({
7653
+ unsupported,
7654
+ props,
7655
+ property: "position",
7656
+ supported: CSS_SUPPORTED_POSITION_VALUES,
7657
+ missing: ["cssPositionBehavior"]
7658
+ });
7659
+ addUnsupportedKeywordSemantic({
7660
+ unsupported,
7661
+ props,
7662
+ property: "flexDirection",
7663
+ supported: CSS_SUPPORTED_FLEX_DIRECTION_VALUES,
7664
+ missing: ["reverseFlexOrdering"]
7665
+ });
7666
+ addUnsupportedKeywordSemantic({
7667
+ unsupported,
7668
+ props,
7669
+ property: "flexWrap",
7670
+ supported: CSS_SUPPORTED_FLEX_WRAP_VALUES,
7671
+ missing: ["reverseFlexLinePacking"]
7672
+ });
7673
+ const alignmentChecks = [
7674
+ {
7675
+ property: "alignSelf",
7676
+ supported: CSS_SUPPORTED_SELF_ALIGNMENT_VALUES,
7677
+ missing: ["cssBoxAlignment"]
7678
+ },
7679
+ {
7680
+ property: "justifySelf",
7681
+ supported: CSS_SUPPORTED_SELF_ALIGNMENT_VALUES,
7682
+ missing: ["cssBoxAlignment"]
7683
+ },
7684
+ {
7685
+ property: "placeSelf",
7686
+ supported: CSS_SUPPORTED_SELF_ALIGNMENT_VALUES,
7687
+ missing: ["cssBoxAlignment"]
7688
+ },
7689
+ {
7690
+ property: "alignItems",
7691
+ supported: CSS_SUPPORTED_SELF_ALIGNMENT_VALUES,
7692
+ missing: ["cssBoxAlignment"]
7693
+ },
7694
+ {
7695
+ property: "justifyItems",
7696
+ supported: CSS_SUPPORTED_SELF_ALIGNMENT_VALUES,
7697
+ missing: ["cssBoxAlignment"]
7698
+ },
7699
+ {
7700
+ property: "placeItems",
7701
+ supported: CSS_SUPPORTED_SELF_ALIGNMENT_VALUES,
7702
+ missing: ["cssBoxAlignment"]
7703
+ },
7704
+ {
7705
+ property: "alignContent",
7706
+ supported: CSS_SUPPORTED_CONTENT_ALIGNMENT_VALUES,
7707
+ missing: ["cssContentDistribution"]
7708
+ },
7709
+ {
7710
+ property: "justifyContent",
7711
+ supported: CSS_SUPPORTED_CONTENT_ALIGNMENT_VALUES,
7712
+ missing: ["cssContentDistribution"]
7713
+ },
7714
+ {
7715
+ property: "placeContent",
7716
+ supported: CSS_SUPPORTED_CONTENT_ALIGNMENT_VALUES,
7717
+ missing: ["cssContentDistribution"]
7718
+ }
7719
+ ];
7720
+ for (const check of alignmentChecks) {
7721
+ if (!hasUnsupportedAlignmentTokens(props[check.property], check.supported)) continue;
7722
+ const semantic = unsupportedCssLayoutValueSemantic(check.property, props[check.property], check.missing);
7723
+ if (semantic) unsupported.push(semantic);
7724
+ }
7725
+ for (const property of [
7726
+ "gridColumnStart",
7727
+ "gridColumnEnd",
7728
+ "gridRowStart",
7729
+ "gridRowEnd"
7730
+ ]) {
7731
+ if (!hasUnsupportedGridLineValue(props[property])) continue;
7732
+ const semantic = unsupportedCssLayoutValueSemantic(property, props[property], ["cssGridNamedOrNegativeLineResolution"]);
7733
+ if (semantic) unsupported.push(semantic);
7734
+ }
7735
+ for (const check of [
7736
+ {
7737
+ property: "gridColumn",
7738
+ allowNamedArea: false
7739
+ },
7740
+ {
7741
+ property: "gridRow",
7742
+ allowNamedArea: false
7743
+ },
7744
+ {
7745
+ property: "gridArea",
7746
+ allowNamedArea: true
7747
+ }
7748
+ ]) {
7749
+ if (!hasUnsupportedGridPlacementValue(props[check.property], check.allowNamedArea)) continue;
7750
+ const semantic = unsupportedCssLayoutValueSemantic(check.property, props[check.property], ["cssGridNamedOrNegativeLineResolution"]);
7751
+ if (semantic) unsupported.push(semantic);
7752
+ }
7753
+ for (const property of [
7754
+ "inset",
7755
+ "top",
7756
+ "right",
7757
+ "bottom",
7758
+ "left",
7759
+ "x",
7760
+ "y"
7761
+ ]) {
7762
+ if (!hasAutoToken(props[property])) continue;
7763
+ const semantic = unsupportedCssLayoutValueSemantic(property, props[property], ["cssAutoInsetResolution"]);
7764
+ if (semantic) unsupported.push(semantic);
7765
+ }
7766
+ for (const property of [
7767
+ "margin",
7768
+ "marginTop",
7769
+ "marginRight",
7770
+ "marginBottom",
7771
+ "marginLeft"
7772
+ ]) {
7773
+ if (!hasAutoToken(props[property])) continue;
7774
+ const semantic = unsupportedCssLayoutValueSemantic(property, props[property], ["cssAutoMarginResolution"]);
7775
+ if (semantic) unsupported.push(semantic);
7776
+ }
7777
+ return unsupported;
7778
+ }
7779
+ const CSS_LOGICAL_LAYOUT_AXIS_FALLBACK_REASON = "CSS writing-mode and direction remap logical layout axes; deckjsx v0.8.2 projects them to PPTX text body direction but still resolves layout, spacing, insets, and start/end alignment on physical axes.";
7780
+ function unsupportedTextLogicalLayoutSemantics(props) {
7781
+ const unsupported = [];
7782
+ if (props.direction === "rtl") {
7783
+ const semantic = unsupportedSemantic({
7784
+ feature: "layout",
7785
+ property: "direction",
7786
+ value: props.direction,
7787
+ error: new Error(CSS_LOGICAL_LAYOUT_AXIS_FALLBACK_REASON),
7788
+ fallback: {
7789
+ strategy: "preserveAuthoredValueOnly",
7790
+ preserves: ["textBodyDirection"],
7791
+ missing: ["logicalLayoutAxes", "cssLogicalStartEndMapping"]
7792
+ }
7793
+ });
7794
+ if (semantic) unsupported.push(semantic);
7795
+ }
7796
+ if (props.writingMode !== void 0 && props.writingMode !== "horizontal-tb") {
7797
+ const semantic = unsupportedSemantic({
7798
+ feature: "layout",
7799
+ property: "writingMode",
7800
+ value: props.writingMode,
7801
+ error: new Error(CSS_LOGICAL_LAYOUT_AXIS_FALLBACK_REASON),
7802
+ fallback: {
7803
+ strategy: "preserveAuthoredValueOnly",
7804
+ preserves: ["textBodyDirection"],
7805
+ missing: ["logicalLayoutAxes", "cssLogicalStartEndMapping"]
7806
+ }
7807
+ });
7808
+ if (semantic) unsupported.push(semantic);
7809
+ }
7810
+ return unsupported;
7811
+ }
6877
7812
  function unsupportedGroupOpacitySemantics$1(props) {
6878
7813
  if (props.opacity === void 0 || props.opacity <= 0 || props.opacity >= 1) return [];
6879
- const semantic = unsupportedSemantic$1({
7814
+ const semantic = unsupportedSemantic({
6880
7815
  feature: "opacity",
6881
7816
  property: "opacity",
6882
7817
  value: props.opacity,
@@ -6891,7 +7826,7 @@ function unsupportedGroupOpacitySemantics$1(props) {
6891
7826
  }
6892
7827
  function unsupportedOpacityStackingContextSemantics$1(props) {
6893
7828
  if (props.opacity === void 0 || props.opacity <= 0 || props.opacity >= 1) return [];
6894
- const semantic = unsupportedSemantic$1({
7829
+ const semantic = unsupportedSemantic({
6895
7830
  feature: "opacity",
6896
7831
  property: "stackingContext",
6897
7832
  value: props.opacity,
@@ -6909,7 +7844,7 @@ function hasProjectedTransform(input) {
6909
7844
  }
6910
7845
  function unsupportedClippingTransformSemantics(input) {
6911
7846
  if (!input.clip || !hasProjectedTransform(input)) return [];
6912
- const semantic = unsupportedSemantic$1({
7847
+ const semantic = unsupportedSemantic({
6913
7848
  feature: "clipping",
6914
7849
  property: "overflow",
6915
7850
  value: `hidden + transform:${input.clip.strategy}`,
@@ -6930,7 +7865,7 @@ function unsupportedClippingTransformSemantics(input) {
6930
7865
  function unsupportedClippedImageSourceRectTransformSemantics(input) {
6931
7866
  if (!input.clip || !hasProjectedTransform(input)) return [];
6932
7867
  const cropSuffix = input.hasExplicitCrop ? "+crop" : "";
6933
- const semantic = unsupportedSemantic$1({
7868
+ const semantic = unsupportedSemantic({
6934
7869
  feature: "clipping",
6935
7870
  property: "imageSourceRect",
6936
7871
  value: `clip:${input.clip.strategy}+transform+fit:${input.fit ?? "contain"}${cropSuffix}`,
@@ -6956,7 +7891,7 @@ function unsupportedTransformStackingContextSemantics$1(props) {
6956
7891
  return [];
6957
7892
  }
6958
7893
  if (!operations?.length) return [];
6959
- const semantic = unsupportedSemantic$1({
7894
+ const semantic = unsupportedSemantic({
6960
7895
  feature: "transform",
6961
7896
  property: "stackingContext",
6962
7897
  value: props.transform,
@@ -6973,7 +7908,7 @@ function unsupportedCompositingSemantics$1(props) {
6973
7908
  const unsupported = [];
6974
7909
  const filter = props.filter?.trim();
6975
7910
  if (filter && filter.toLowerCase() !== "none") {
6976
- const semantic = unsupportedSemantic$1({
7911
+ const semantic = unsupportedSemantic({
6977
7912
  feature: "filter",
6978
7913
  property: "filter",
6979
7914
  value: props.filter,
@@ -6988,7 +7923,7 @@ function unsupportedCompositingSemantics$1(props) {
6988
7923
  }
6989
7924
  const mixBlendMode = props.mixBlendMode?.trim();
6990
7925
  if (mixBlendMode && mixBlendMode.toLowerCase() !== "normal") {
6991
- const semantic = unsupportedSemantic$1({
7926
+ const semantic = unsupportedSemantic({
6992
7927
  feature: "blend",
6993
7928
  property: "mixBlendMode",
6994
7929
  value: props.mixBlendMode,
@@ -7002,7 +7937,7 @@ function unsupportedCompositingSemantics$1(props) {
7002
7937
  if (semantic) unsupported.push(semantic);
7003
7938
  }
7004
7939
  if (props.isolation === "isolate") {
7005
- const semantic = unsupportedSemantic$1({
7940
+ const semantic = unsupportedSemantic({
7006
7941
  feature: "isolation",
7007
7942
  property: "isolation",
7008
7943
  value: props.isolation,
@@ -7051,6 +7986,8 @@ const EMPTY_SPACING = [
7051
7986
  0,
7052
7987
  0
7053
7988
  ];
7989
+ const DEFAULT_TEXT_FONT_SIZE_PT = 18;
7990
+ const DEFAULT_NORMAL_LINE_HEIGHT_MULTIPLE = 1.2;
7054
7991
  function createIdGenerator() {
7055
7992
  let slideCount = 0;
7056
7993
  let nodeCount = 0;
@@ -7069,21 +8006,54 @@ function imageSourceFromProps(props) {
7069
8006
  if (props.src) {
7070
8007
  if (/^https?:\/\//i.test(props.src)) return {
7071
8008
  kind: "url",
7072
- url: props.src
8009
+ url: props.src
8010
+ };
8011
+ return {
8012
+ kind: "path",
8013
+ path: props.src
8014
+ };
8015
+ }
8016
+ if (props.data) return {
8017
+ kind: "data",
8018
+ data: props.data
8019
+ };
8020
+ throw new Error("Image requires either src or data.");
8021
+ }
8022
+ function videoSourceFromProps(props) {
8023
+ if (props.src) {
8024
+ if (/^https?:\/\//i.test(props.src)) return {
8025
+ kind: "url",
8026
+ url: props.src
8027
+ };
8028
+ return {
8029
+ kind: "path",
8030
+ path: props.src
8031
+ };
8032
+ }
8033
+ if (props.data) return {
8034
+ kind: "data",
8035
+ data: props.data
8036
+ };
8037
+ throw new Error("Video requires either src or data.");
8038
+ }
8039
+ function videoPosterSourceFromProps(props) {
8040
+ if (props.poster) {
8041
+ if (/^https?:\/\//i.test(props.poster)) return {
8042
+ kind: "url",
8043
+ url: props.poster
7073
8044
  };
7074
8045
  return {
7075
8046
  kind: "path",
7076
- path: props.src
8047
+ path: props.poster
7077
8048
  };
7078
8049
  }
7079
- if (props.data) return {
8050
+ if (props.posterData) return {
7080
8051
  kind: "data",
7081
- data: props.data
8052
+ data: props.posterData
7082
8053
  };
7083
- throw new Error("Image requires either src or data.");
7084
8054
  }
7085
8055
  function isLayoutInputContentNode(value) {
7086
- return typeof value === "object" && value !== null && "kind" in value && (value.kind === "view" || value.kind === "text" || value.kind === "image" || value.kind === "shape");
8056
+ return typeof value === "object" && value !== null && "kind" in value && (value.kind === "view" || value.kind === "text" || value.kind === "image" || value.kind === "video" || value.kind === "shape");
7087
8057
  }
7088
8058
  function isLayoutInputTextNode(value) {
7089
8059
  return typeof value === "object" && value !== null && "kind" in value && value.kind === "text";
@@ -7108,7 +8078,14 @@ function layoutChildFromNode(child, siblingOrder, context) {
7108
8078
  case "image": return {
7109
8079
  kind: "image",
7110
8080
  source: child,
7111
- props: normalizeImageProps(child.props, context),
8081
+ props: normalizeImagePropsWithIntrinsicAspectRatio(child, context),
8082
+ siblingOrder,
8083
+ ...origin ? { origin } : {}
8084
+ };
8085
+ case "video": return {
8086
+ kind: "video",
8087
+ source: child,
8088
+ props: normalizeVideoProps(child.props, context),
7112
8089
  siblingOrder,
7113
8090
  ...origin ? { origin } : {}
7114
8091
  };
@@ -7121,6 +8098,35 @@ function layoutChildFromNode(child, siblingOrder, context) {
7121
8098
  };
7122
8099
  }
7123
8100
  }
8101
+ function normalizeImagePropsWithIntrinsicAspectRatio(child, context) {
8102
+ const props = normalizeImageProps(child.props, context);
8103
+ if (props.aspectRatio !== void 0) return props;
8104
+ const width = child.assetProbe?.width;
8105
+ const height = child.assetProbe?.height;
8106
+ if (width === void 0 || height === void 0 || !Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return props;
8107
+ return {
8108
+ ...props,
8109
+ aspectRatio: width / height
8110
+ };
8111
+ }
8112
+ function resolveCornerRadiusEmu$1(value, frame, context) {
8113
+ return parseLength(value, Math.min(frame.widthEmu, frame.heightEmu), 0, context);
8114
+ }
8115
+ function unsupportedObjectPositionSemantics(input) {
8116
+ if (input.value === void 0 || input.resolved !== void 0) return [];
8117
+ const unsupported = unsupportedSemantic({
8118
+ feature: "image",
8119
+ property: "objectPosition",
8120
+ value: input.value,
8121
+ error: /* @__PURE__ */ new Error("Unsupported objectPosition value."),
8122
+ fallback: {
8123
+ strategy: "preserveAuthoredValueOnly",
8124
+ preserves: ["authoredObjectPosition"],
8125
+ missing: ["pptxObjectPosition"]
8126
+ }
8127
+ });
8128
+ return unsupported ? [unsupported] : [];
8129
+ }
7124
8130
  function parseCropValue$1(value) {
7125
8131
  if (value === void 0) return 0;
7126
8132
  if (typeof value === "number") {
@@ -7197,14 +8203,15 @@ function resolveAlignContentOffset(alignContent, availableEmu, usedEmu, lineCoun
7197
8203
  extraSizeEmu: 0
7198
8204
  };
7199
8205
  }
7200
- function getChildPadding(node, context) {
8206
+ function getChildPadding(node, context, percentageBaseEmu = 0) {
7201
8207
  switch (node.kind) {
7202
- case "view": return parseSpacing(node.props.padding, context);
8208
+ case "view": return parseSpacing(node.props.padding, context, percentageBaseEmu);
7203
8209
  case "text": {
7204
8210
  const { props } = node;
7205
- return parseSpacing(props.padding, getTextLengthContext(props, context));
8211
+ return parseSpacing(props.padding, getTextLengthContext(props, context), percentageBaseEmu);
7206
8212
  }
7207
8213
  case "image": return EMPTY_SPACING;
8214
+ case "video": return EMPTY_SPACING;
7208
8215
  case "shape": return EMPTY_SPACING;
7209
8216
  }
7210
8217
  }
@@ -7220,46 +8227,69 @@ function resolveChildMainLength(node, axis) {
7220
8227
  if (flexBasis !== void 0 && flexBasis !== "auto") return flexBasis;
7221
8228
  return node.props[axis === "horizontal" ? "width" : "height"];
7222
8229
  }
8230
+ function resolveTextFontSizePt(props, context) {
8231
+ return parsePointValue(props.fontSize, DEFAULT_TEXT_FONT_SIZE_PT, context);
8232
+ }
8233
+ function resolveTextLineHeightPt(props, context) {
8234
+ const fontSizePt = resolveTextFontSizePt(props, context);
8235
+ if (props.lineHeight === void 0 || props.lineHeight === "normal") return fontSizePt * DEFAULT_NORMAL_LINE_HEIGHT_MULTIPLE;
8236
+ if (typeof props.lineHeight === "number") return fontSizePt * props.lineHeight;
8237
+ return parsePointValue(props.lineHeight, fontSizePt * DEFAULT_NORMAL_LINE_HEIGHT_MULTIPLE, {
8238
+ ...context,
8239
+ fontSizePt
8240
+ });
8241
+ }
8242
+ function estimateTextAutoContentSize(node, dimension, parent, context) {
8243
+ const textContext = getTextLengthContext(node.props, context);
8244
+ const [paddingTop, , paddingBottom] = parseSpacing(node.props.padding, textContext, parent.widthEmu);
8245
+ if (dimension === "width") return parent.widthEmu;
8246
+ return resolveTextLineHeightPt(node.props, textContext) / 72 * EMU_PER_INCH + paddingTop + paddingBottom;
8247
+ }
7223
8248
  function estimateChildContentSize(node, dimension, parent, mainAxis, context) {
7224
8249
  const aspectRatio = parseAspectRatio(node.props.aspectRatio);
7225
8250
  const isMainDimension = mainAxis === "horizontal" && dimension === "width" || mainAxis === "vertical" && dimension === "height";
7226
8251
  const basis = dimension === "width" ? parent.widthEmu : parent.heightEmu;
7227
- const directValue = isMainDimension && mainAxis ? resolveChildMainLength(node, mainAxis) : node.props[dimension];
7228
- if (directValue !== void 0) return inflateSpecifiedBoxSize(parseLength(directValue, basis, 0, getNodeLengthContext(node, context)), node.kind === "image" ? "border-box" : node.props.boxSizing ?? "border-box", getChildPadding(node, context), dimension);
8252
+ const authoredValue = authoredLengthOrUndefined(isMainDimension && mainAxis ? resolveChildMainLength(node, mainAxis) : node.props[dimension]);
8253
+ if (authoredValue !== void 0) return inflateSpecifiedBoxSize(parseLength(authoredValue, basis, 0, getNodeLengthContext(node, context)), node.kind === "image" || node.kind === "video" ? "border-box" : node.props.boxSizing ?? "border-box", getChildPadding(node, context, parent.widthEmu), dimension);
8254
+ if (node.kind === "text") {
8255
+ if (dimension === "width" && mainAxis === "horizontal") return 0;
8256
+ return estimateTextAutoContentSize(node, dimension, parent, context);
8257
+ }
7229
8258
  if (aspectRatio === void 0) return 0;
7230
8259
  const oppositeDimension = dimension === "width" ? "height" : "width";
7231
8260
  const oppositeBasis = oppositeDimension === "width" ? parent.widthEmu : parent.heightEmu;
7232
- const oppositeValue = (mainAxis === "horizontal" && oppositeDimension === "width" || mainAxis === "vertical" && oppositeDimension === "height") && mainAxis ? resolveChildMainLength(node, mainAxis) : node.props[oppositeDimension];
7233
- if (oppositeValue === void 0) return 0;
7234
- const oppositeSize = parseLength(oppositeValue, oppositeBasis, 0, getNodeLengthContext(node, context));
7235
- return inflateSpecifiedBoxSize(dimension === "width" ? oppositeSize * aspectRatio : oppositeSize / aspectRatio, node.kind === "image" ? "border-box" : node.props.boxSizing ?? "border-box", getChildPadding(node, context), dimension);
8261
+ const authoredOppositeValue = authoredLengthOrUndefined((mainAxis === "horizontal" && oppositeDimension === "width" || mainAxis === "vertical" && oppositeDimension === "height") && mainAxis ? resolveChildMainLength(node, mainAxis) : node.props[oppositeDimension]);
8262
+ if (authoredOppositeValue === void 0) return 0;
8263
+ const oppositeSize = parseLength(authoredOppositeValue, oppositeBasis, 0, getNodeLengthContext(node, context));
8264
+ return inflateSpecifiedBoxSize(dimension === "width" ? oppositeSize * aspectRatio : oppositeSize / aspectRatio, node.kind === "image" || node.kind === "video" ? "border-box" : node.props.boxSizing ?? "border-box", getChildPadding(node, context, parent.widthEmu), dimension);
7236
8265
  }
7237
- function getNodeMargin(node, context) {
8266
+ function getNodeMargin(node, context, percentageBaseEmu = 0) {
7238
8267
  switch (node.kind) {
7239
- case "view": return parseSpacing(node.props.margin, context);
8268
+ case "view": return parseSpacingAllowAuto(node.props.margin, context, percentageBaseEmu);
7240
8269
  case "text": {
7241
8270
  const { props } = node;
7242
- return parseSpacing(props.margin, getTextLengthContext(props, context));
8271
+ return parseSpacingAllowAuto(props.margin, getTextLengthContext(props, context), percentageBaseEmu);
7243
8272
  }
7244
- case "image": return parseSpacing(node.props.margin, context);
7245
- case "shape": return parseSpacing(node.props.margin, context);
8273
+ case "image": return parseSpacingAllowAuto(node.props.margin, context, percentageBaseEmu);
8274
+ case "video": return parseSpacingAllowAuto(node.props.margin, context, percentageBaseEmu);
8275
+ case "shape": return parseSpacingAllowAuto(node.props.margin, context, percentageBaseEmu);
7246
8276
  }
7247
8277
  }
7248
8278
  function estimateChildMainSize(node, axis, parent, context) {
7249
- const [top, right, bottom, left] = getNodeMargin(node, context);
8279
+ const [top, right, bottom, left] = getNodeMargin(node, context, parent.widthEmu);
7250
8280
  const margin = axis === "horizontal" ? left + right : top + bottom;
7251
8281
  return estimateChildContentSize(node, axis === "horizontal" ? "width" : "height", parent, axis, context) + margin;
7252
8282
  }
7253
8283
  function estimateChildCrossSize(node, axis, parent, context) {
7254
- const [top, right, bottom, left] = getNodeMargin(node, context);
8284
+ const [top, right, bottom, left] = getNodeMargin(node, context, parent.widthEmu);
7255
8285
  const margin = axis === "horizontal" ? top + bottom : left + right;
7256
8286
  return estimateChildContentSize(node, axis === "horizontal" ? "height" : "width", parent, axis, context) + margin;
7257
8287
  }
7258
8288
  function shouldStretchGridDimension(node, dimension) {
7259
- if (node.props[dimension] !== void 0) return false;
8289
+ if (hasAuthoredLength(node.props[dimension])) return false;
7260
8290
  if (!parseAspectRatio(node.props.aspectRatio)) return true;
7261
8291
  const oppositeDimension = dimension === "width" ? "height" : "width";
7262
- return node.props[oppositeDimension] === void 0;
8292
+ return !hasAuthoredLength(node.props[oppositeDimension]);
7263
8293
  }
7264
8294
  function resolveChildGridPlacements(node, namedAreas) {
7265
8295
  const explicitRow = resolveGridPlacementFromLonghands(node.props.gridRowStart, node.props.gridRowEnd) ?? parseGridPlacement(node.props.gridRow);
@@ -7278,7 +8308,7 @@ function resolveChildGridPlacements(node, namedAreas) {
7278
8308
  };
7279
8309
  }
7280
8310
  function resolveGridContainerSpec(parentFrame, options, context) {
7281
- const [paddingTop, paddingRight, paddingBottom, paddingLeft] = parseSpacing(options.padding, context);
8311
+ const [paddingTop, paddingRight, paddingBottom, paddingLeft] = parseSpacing(options.padding, context, parentFrame.widthEmu);
7282
8312
  const contentX = parentFrame.xEmu + paddingLeft;
7283
8313
  const contentY = parentFrame.yEmu + paddingTop;
7284
8314
  const contentWidth = Math.max(parentFrame.widthEmu - paddingLeft - paddingRight, 0);
@@ -7289,8 +8319,8 @@ function resolveGridContainerSpec(parentFrame, options, context) {
7289
8319
  widthEmu: contentWidth,
7290
8320
  heightEmu: contentHeight
7291
8321
  };
7292
- const columnGapEmu = parseLength(options.columnGap ?? options.rowGap, 0, 0, context);
7293
- const rowGapEmu = parseLength(options.rowGap ?? options.columnGap, 0, 0, context);
8322
+ const columnGapEmu = parseLength(options.columnGap ?? options.rowGap, contentWidth, 0, context);
8323
+ const rowGapEmu = parseLength(options.rowGap ?? options.columnGap, contentHeight, 0, context);
7294
8324
  const placeItems = parsePlaceItems(options.placeItems);
7295
8325
  const placeContent = parsePlaceContent(options.placeContent);
7296
8326
  const namedAreas = parseGridTemplateAreas(options.gridTemplateAreas);
@@ -7375,7 +8405,7 @@ function compileGridChildren(authorChildren, parentFrame, idGenerator, options,
7375
8405
  const rowOffsets = resolveTrackOffsets(stretchedRowTracks, spec.rowGapEmu).map((offset) => offset + blockPacking.offsetEmu);
7376
8406
  return sortNodesForPaint(placements.map((placement) => {
7377
8407
  const { child, row, column, rowSpan, columnSpan } = placement;
7378
- const [marginTop, marginRight, marginBottom, marginLeft] = getNodeMargin(child, context);
8408
+ const [marginTop, marginRight, marginBottom, marginLeft] = getNodeMargin(child, context, spec.contentWidth);
7379
8409
  const cellWidth = stretchedColumnTracks.slice(column - 1, column - 1 + columnSpan).reduce((sum, size) => sum + size, 0) + Math.max(columnSpan - 1, 0) * spec.columnGapEmu;
7380
8410
  const cellHeight = stretchedRowTracks.slice(row - 1, row - 1 + rowSpan).reduce((sum, size) => sum + size, 0) + Math.max(rowSpan - 1, 0) * spec.rowGapEmu;
7381
8411
  const innerFrame = {
@@ -7402,6 +8432,44 @@ function compileGridChildren(authorChildren, parentFrame, idGenerator, options,
7402
8432
  return compileNode(child, innerFrame, idGenerator, placementOverride, clipRect, context, resolutionOptions);
7403
8433
  }).filter((node) => node !== null));
7404
8434
  }
8435
+ function hasExplicitFrameInput(child) {
8436
+ const { props } = child;
8437
+ const relativePosition = props.position === "relative";
8438
+ return props.position === "absolute" || props.area !== void 0 || !relativePosition && (hasAuthoredLength(props.x) || hasAuthoredLength(props.y) || hasCssWideKeywordToken(props.inset) === false && props.inset !== void 0 || hasAuthoredLength(props.left) || hasAuthoredLength(props.top) || hasAuthoredLength(props.right) || hasAuthoredLength(props.bottom)) || hasAuthoredLength(props.width) || hasAuthoredLength(props.height);
8439
+ }
8440
+ function compileBlockFlowChildren(authorChildren, parentFrame, idGenerator, options, clipRect, context, resolutionOptions) {
8441
+ const [paddingTop, paddingRight, paddingBottom, paddingLeft] = parseSpacing(options.padding, context, parentFrame.widthEmu);
8442
+ const contentFrame = {
8443
+ xEmu: parentFrame.xEmu + paddingLeft,
8444
+ yEmu: parentFrame.yEmu + paddingTop,
8445
+ widthEmu: Math.max(parentFrame.widthEmu - paddingLeft - paddingRight, 0),
8446
+ heightEmu: Math.max(parentFrame.heightEmu - paddingTop - paddingBottom, 0)
8447
+ };
8448
+ const blockGapEmu = resolveMainGap("vertical", options.gap, options.rowGap, options.columnGap, context, contentFrame.heightEmu);
8449
+ let cursorY = contentFrame.yEmu;
8450
+ const flowNodes = [];
8451
+ for (const child of authorChildren) {
8452
+ const [marginTop, marginRight, marginBottom, marginLeft] = getNodeMargin(child, context, contentFrame.widthEmu);
8453
+ const childWidth = authoredLengthOrUndefined(child.props.width) === void 0 ? Math.max(contentFrame.widthEmu - marginLeft - marginRight, 0) : estimateChildContentSize(child, "width", contentFrame, void 0, context);
8454
+ const childHeight = estimateChildContentSize(child, "height", contentFrame, "vertical", context);
8455
+ const compiledNode = compileNode(child, contentFrame, idGenerator, {
8456
+ xEmu: contentFrame.xEmu + marginLeft,
8457
+ yEmu: cursorY + marginTop,
8458
+ widthEmu: childWidth,
8459
+ heightEmu: childHeight
8460
+ }, clipRect, context, resolutionOptions);
8461
+ if (compiledNode) flowNodes.push(compiledNode);
8462
+ cursorY += marginTop + childHeight + marginBottom + blockGapEmu;
8463
+ }
8464
+ return flowNodes;
8465
+ }
8466
+ function compileAbsoluteChildren(authorChildren, parentFrame, idGenerator, options, clipRect, context, resolutionOptions) {
8467
+ const flowChildren = authorChildren.filter((child) => !hasExplicitFrameInput(child));
8468
+ const absoluteChildren = authorChildren.filter(hasExplicitFrameInput);
8469
+ const flowNodes = compileBlockFlowChildren(flowChildren, parentFrame, idGenerator, options, clipRect, context, resolutionOptions);
8470
+ const absoluteNodes = absoluteChildren.map((child) => compileNode(child, parentFrame, idGenerator, void 0, clipRect, context, resolutionOptions)).filter((node) => node !== null);
8471
+ return sortNodesForPaint([...flowNodes, ...absoluteNodes].sort((left, right) => left.siblingOrder - right.siblingOrder));
8472
+ }
7405
8473
  function compileChildren$1(children, parentFrame, idGenerator, layout, options, clipRect, context, resolutionOptions) {
7406
8474
  const authorChildren = children.map((child, siblingOrder) => {
7407
8475
  if (!isLayoutInputContentNode(child)) throw new Error("Only deckjsx components can be children of View in structured layout.");
@@ -7424,11 +8492,15 @@ function compileChildren$1(children, parentFrame, idGenerator, layout, options,
7424
8492
  placeContent: options.placeContent,
7425
8493
  gridAutoFlow: options.gridAutoFlow
7426
8494
  }, clipRect, context, resolutionOptions);
7427
- if (layout !== "stack") return sortNodesForPaint(authorChildren.map((child) => compileNode(child, parentFrame, idGenerator, void 0, clipRect, context, resolutionOptions)).filter((node) => node !== null));
8495
+ if (layout !== "stack") return compileAbsoluteChildren(authorChildren, parentFrame, idGenerator, {
8496
+ padding: options.padding,
8497
+ gap: options.gap,
8498
+ rowGap: options.rowGap,
8499
+ columnGap: options.columnGap
8500
+ }, clipRect, context, resolutionOptions);
7428
8501
  const direction = options.direction ?? "vertical";
7429
- const mainGapEmu = resolveMainGap(direction, options.gap, options.rowGap, options.columnGap, context);
7430
- const crossGapEmu = resolveCrossGap(direction, options.gap, options.rowGap, options.columnGap, context);
7431
- const [paddingTop, paddingRight, paddingBottom, paddingLeft] = parseSpacing(options.padding, context);
8502
+ const defaultAlignItems = options.alignItems ?? (options.display === "flex" ? "stretch" : void 0);
8503
+ const [paddingTop, paddingRight, paddingBottom, paddingLeft] = parseSpacing(options.padding, context, parentFrame.widthEmu);
7432
8504
  const contentX = parentFrame.xEmu + paddingLeft;
7433
8505
  const contentY = parentFrame.yEmu + paddingTop;
7434
8506
  const contentWidth = Math.max(parentFrame.widthEmu - paddingLeft - paddingRight, 0);
@@ -7439,6 +8511,8 @@ function compileChildren$1(children, parentFrame, idGenerator, layout, options,
7439
8511
  widthEmu: contentWidth,
7440
8512
  heightEmu: contentHeight
7441
8513
  };
8514
+ const mainGapEmu = resolveMainGap(direction, options.gap, options.rowGap, options.columnGap, context, direction === "horizontal" ? contentWidth : contentHeight);
8515
+ const crossGapEmu = resolveCrossGap(direction, options.gap, options.rowGap, options.columnGap, context, direction === "horizontal" ? contentHeight : contentWidth);
7442
8516
  const stackEntries = authorChildren.map((child, sourceIndex) => ({
7443
8517
  child,
7444
8518
  sourceIndex,
@@ -7456,13 +8530,13 @@ function compileChildren$1(children, parentFrame, idGenerator, layout, options,
7456
8530
  const absoluteEntries = stackEntries.filter((entry) => entry.position === "absolute");
7457
8531
  const availableMain = direction === "horizontal" ? contentWidth : contentHeight;
7458
8532
  const availableCross = direction === "horizontal" ? contentHeight : contentWidth;
7459
- const lines = buildStackLines(flowEntries, direction, parentFrame, availableMain, mainGapEmu, options.flexWrap, stackMetrics, context);
8533
+ const lines = buildStackLines(flowEntries, direction, contentFrame, availableMain, mainGapEmu, options.flexWrap, stackMetrics, context);
7460
8534
  const usedCross = lines.reduce((sum, line) => sum + line.crossSizeEmu, 0) + Math.max(lines.length - 1, 0) * crossGapEmu;
7461
8535
  const contentPacking = resolveAlignContentOffset(options.alignContent, availableCross, usedCross, lines.length);
7462
8536
  let crossCursor = contentPacking.offsetEmu;
7463
8537
  const flowNodes = [];
7464
8538
  for (const [lineIndex, line] of lines.entries()) {
7465
- const mainAllocations = resolveFlexMainAllocations(line, direction, parentFrame, availableMain, mainGapEmu, stackMetrics, context);
8539
+ const mainAllocations = resolveFlexMainAllocations(line, direction, contentFrame, availableMain, mainGapEmu, stackMetrics, context);
7466
8540
  const allocatedUsedMain = mainAllocations.reduce((sum, allocation) => sum + allocation.outerMainEmu, 0) + Math.max(line.entries.length - 1, 0) * mainGapEmu;
7467
8541
  const justify = resolveJustifyOffset(options.justifyContent, availableMain, allocatedUsedMain, line.entries.length);
7468
8542
  let mainCursor = justify.offsetEmu;
@@ -7471,10 +8545,10 @@ function compileChildren$1(children, parentFrame, idGenerator, layout, options,
7471
8545
  const mainAllocation = mainAllocations[entryIndex];
7472
8546
  if (mainAllocation === void 0) throw new Error("Stack layout allocation count did not match line entry count.");
7473
8547
  const { child } = entry;
7474
- const childCross = estimateChildCrossSize(child, direction, parentFrame, context);
7475
- const [marginTop, marginRight, marginBottom, marginLeft] = getNodeMargin(child, context);
7476
- let alignment = parsePlaceSelf(child.props.placeSelf).alignSelf ?? child.props.alignSelf ?? options.alignItems;
7477
- if (alignment === "auto") alignment = void 0;
8548
+ const childCross = estimateChildCrossSize(child, direction, contentFrame, context);
8549
+ const [marginTop, marginRight, marginBottom, marginLeft] = getNodeMargin(child, context, contentFrame.widthEmu);
8550
+ const alignSelf = parsePlaceSelf(child.props.placeSelf).alignSelf ?? child.props.alignSelf;
8551
+ let alignment = alignSelf === "auto" ? defaultAlignItems : alignSelf ?? defaultAlignItems;
7478
8552
  if (alignment === "flex-start") alignment = "start";
7479
8553
  if (alignment === "flex-end") alignment = "end";
7480
8554
  const hasExplicitCrossSize = child.props[direction === "horizontal" ? "height" : "width"] !== void 0;
@@ -7520,13 +8594,14 @@ function compileGroupNode(node, parentFrame, idGenerator, placement, clipRect, c
7520
8594
  const visibleFrame = intersectClipRect(originalFrame, clipRect);
7521
8595
  if (!visibleFrame) return null;
7522
8596
  const childClipRect = props.overflow === "hidden" ? intersectClipRect(originalFrame, clipRect) : clipRect;
7523
- const backgroundBoxFrames = resolveBackgroundBoxFrames(visibleFrame, strokes.stroke, strokes.edgeStrokes, parseSpacing(props.padding, context));
8597
+ const backgroundBoxFrames = resolveBackgroundBoxFrames(visibleFrame, strokes.stroke, strokes.edgeStrokes, parseSpacing(props.padding, context, visibleFrame.widthEmu));
7524
8598
  const backgroundFill = resolveBackgroundLayersOrEmpty(backgroundInput(props), props.backgroundTransparency, {
7525
8599
  widthEmu: visibleFrame.widthEmu,
7526
8600
  heightEmu: visibleFrame.heightEmu
7527
8601
  }, visibleFrame, backgroundBoxFrames, props.backgroundPosition, props.backgroundSize, props.backgroundRepeat, props.backgroundOrigin, props.backgroundClip);
7528
8602
  const clip = clippingMetadata(originalFrame, clipRect, visibleFrame);
7529
8603
  const unsupportedSemantics = [
8604
+ ...unsupportedCssLayoutValueSemantics(props),
7530
8605
  ...unsupportedTransformSemantics$1(props),
7531
8606
  ...unsupportedTransformStackingContextSemantics$1(props),
7532
8607
  ...unsupportedCompositingSemantics$1(props),
@@ -7562,9 +8637,10 @@ function compileGroupNode(node, parentFrame, idGenerator, placement, clipRect, c
7562
8637
  ...strokes.edgeStrokes ? { edgeStrokes: strokes.edgeStrokes } : {},
7563
8638
  ...outline.outline ? { outline: outline.outline } : {},
7564
8639
  ...shadow.shadow ? { shadow: shadow.shadow } : {},
7565
- radiusEmu: parseLength(props.borderRadius, 0, 0, context),
8640
+ radiusEmu: resolveCornerRadiusEmu$1(props.borderRadius, visibleFrame, context),
7566
8641
  children: compileChildren$1(node.source.children, originalFrame, idGenerator, props.layout, {
7567
8642
  direction: props.direction,
8643
+ display: props.display,
7568
8644
  gap: props.gap,
7569
8645
  rowGap: props.rowGap,
7570
8646
  columnGap: props.columnGap,
@@ -7592,7 +8668,7 @@ function textStyleFromProps$1(props, textLengthContext) {
7592
8668
  const underlineColor = normalizeColor(props.textDecorationColor);
7593
8669
  const textDirection = resolveTextDirection(props.writingMode);
7594
8670
  const tabStops = resolveTabStops(props.tabStops, textLengthContext);
7595
- const fontSizePt = props.fontSize === void 0 ? void 0 : parsePointValue(props.fontSize, 0, textLengthContext);
8671
+ const fontSizePt = props.fontSize === void 0 || isCssWideKeyword(props.fontSize) ? void 0 : parsePointValue(props.fontSize, 0, textLengthContext);
7596
8672
  return {
7597
8673
  fontFamily: props.fontFamily,
7598
8674
  fontSizePt,
@@ -7608,11 +8684,11 @@ function textStyleFromProps$1(props, textLengthContext) {
7608
8684
  paddingPt: parseSpacingInPoints(props.padding, textLengthContext),
7609
8685
  lineSpacing: props.lineSpacing ?? lineHeight.lineSpacing,
7610
8686
  lineSpacingMultiple: props.lineSpacingMultiple ?? lineHeight.lineSpacingMultiple,
7611
- paragraphSpacingBefore: props.paragraphSpacingBefore,
7612
- paragraphSpacingAfter: props.paragraphSpacingAfter,
8687
+ paragraphSpacingBefore: props.paragraphSpacingBefore === void 0 ? void 0 : parsePointValue(props.paragraphSpacingBefore, 0, textLengthContext),
8688
+ paragraphSpacingAfter: props.paragraphSpacingAfter === void 0 ? void 0 : parsePointValue(props.paragraphSpacingAfter, 0, textLengthContext),
7613
8689
  ...props.textIndent === void 0 ? {} : { textIndentPt: parsePointValue(props.textIndent, 0, textLengthContext) },
7614
8690
  ...tabStops ? { tabStops } : {},
7615
- charSpacing: props.charSpacing,
8691
+ charSpacing: resolveCharacterSpacing(props.charSpacing, textLengthContext),
7616
8692
  ...list ? { list } : {},
7617
8693
  fit: props.fit,
7618
8694
  wrap: props.wrap,
@@ -7662,10 +8738,66 @@ function clippingMetadata(originalFrame, clipRect, visibleFrame) {
7662
8738
  visibleFrame
7663
8739
  };
7664
8740
  }
8741
+ function textFramePropsWithFallback(props, placement, context) {
8742
+ let resolved = props;
8743
+ const hasAuthoredWidth = authoredLengthOrUndefined(props.width) !== void 0;
8744
+ const hasAuthoredHeight = authoredLengthOrUndefined(props.height) !== void 0;
8745
+ const hasAuthoredInset = props.inset !== void 0 && !hasCssWideKeywordToken(props.inset);
8746
+ const hasAuthoredLeft = authoredLengthOrUndefined(props.left) !== void 0;
8747
+ const hasAuthoredRight = authoredLengthOrUndefined(props.right) !== void 0;
8748
+ const hasAuthoredTop = authoredLengthOrUndefined(props.top) !== void 0;
8749
+ const hasAuthoredBottom = authoredLengthOrUndefined(props.bottom) !== void 0;
8750
+ const hasAuthoredX = authoredLengthOrUndefined(props.x) !== void 0;
8751
+ if (placement?.widthEmu === void 0 && !hasAuthoredWidth && !hasAuthoredInset) {
8752
+ if (!hasAuthoredRight && (hasAuthoredX || hasAuthoredLeft)) resolved = {
8753
+ ...resolved,
8754
+ right: 0
8755
+ };
8756
+ else if (!hasAuthoredLeft && hasAuthoredRight) resolved = {
8757
+ ...resolved,
8758
+ left: 0
8759
+ };
8760
+ else if (!hasAuthoredLeft && !hasAuthoredRight) resolved = {
8761
+ ...resolved,
8762
+ width: "100%"
8763
+ };
8764
+ }
8765
+ if (placement?.heightEmu === void 0 && !hasAuthoredHeight && !hasAuthoredInset && !(hasAuthoredTop && hasAuthoredBottom)) resolved = {
8766
+ ...resolved,
8767
+ height: `${resolveTextLineHeightPt(props, context)}pt`
8768
+ };
8769
+ return resolved;
8770
+ }
8771
+ function usesTextLineHeightFallback(props, placement) {
8772
+ const hasAuthoredHeight = authoredLengthOrUndefined(props.height) !== void 0;
8773
+ const hasAuthoredInset = props.inset !== void 0 && !hasCssWideKeywordToken(props.inset);
8774
+ const hasAuthoredTop = authoredLengthOrUndefined(props.top) !== void 0;
8775
+ const hasAuthoredBottom = authoredLengthOrUndefined(props.bottom) !== void 0;
8776
+ return placement?.heightEmu === void 0 && !hasAuthoredHeight && !hasAuthoredInset && !(hasAuthoredTop && hasAuthoredBottom);
8777
+ }
8778
+ function textMayNeedWrappedMeasurement(text, props) {
8779
+ if (!text || props.wrap === false) return false;
8780
+ return text.includes("\n") || text.trim().length > 80;
8781
+ }
8782
+ function unsupportedWrappedTextMeasurementSemantics(input) {
8783
+ if (!usesTextLineHeightFallback(input.props, input.placement) || !textMayNeedWrappedMeasurement(input.text, input.props)) return [];
8784
+ const semantic = unsupportedSemantic({
8785
+ feature: "layout",
8786
+ property: "height",
8787
+ value: "auto",
8788
+ error: /* @__PURE__ */ new Error("Exact wrapped text measurement is not part of the v0.8.2 layout subset; deckjsx uses a line-height based auto-height fallback."),
8789
+ fallback: {
8790
+ strategy: "preserveAuthoredValueOnly",
8791
+ preserves: ["availableInlineSize", "lineHeightAutoHeight"],
8792
+ missing: ["wrappedTextMeasurement"]
8793
+ }
8794
+ });
8795
+ return semantic ? [semantic] : [];
8796
+ }
7665
8797
  function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, context) {
7666
8798
  const { props } = node;
7667
8799
  const textLengthContext = getTextLengthContext(props, context);
7668
- const resolved = frameFromProps(props, parentFrame, placement, textLengthContext);
8800
+ const resolved = frameFromProps(textFramePropsWithFallback(props, placement, textLengthContext), parentFrame, placement, textLengthContext);
7669
8801
  const strokes = resolveNodeStrokesOrFallback(props, textLengthContext);
7670
8802
  const shadow = parseShadowShorthandOrIgnore({
7671
8803
  property: props.textShadow !== void 0 ? "textShadow" : "boxShadow",
@@ -7678,6 +8810,7 @@ function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, co
7678
8810
  } : void 0;
7679
8811
  const style = textStyleFromProps$1(props, textLengthContext);
7680
8812
  const runs = extractRichTextRuns(node.source.children, props.textTransform, textLengthContext);
8813
+ const text = runs.map((run) => run.text).join("");
7681
8814
  const originalFrame = {
7682
8815
  xEmu: resolved.xEmu,
7683
8816
  yEmu: resolved.yEmu,
@@ -7686,13 +8819,15 @@ function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, co
7686
8819
  };
7687
8820
  const visibleFrame = intersectClipRect(originalFrame, clipRect);
7688
8821
  if (!visibleFrame) return null;
7689
- const backgroundBoxFrames = resolveBackgroundBoxFrames(visibleFrame, strokes.stroke, strokes.edgeStrokes, parseSpacing(props.padding, textLengthContext));
8822
+ const backgroundBoxFrames = resolveBackgroundBoxFrames(visibleFrame, strokes.stroke, strokes.edgeStrokes, parseSpacing(props.padding, textLengthContext, visibleFrame.widthEmu));
7690
8823
  const backgroundFill = resolveBackgroundLayersOrEmpty(backgroundInput(props), props.backgroundTransparency, {
7691
8824
  widthEmu: visibleFrame.widthEmu,
7692
8825
  heightEmu: visibleFrame.heightEmu
7693
8826
  }, visibleFrame, backgroundBoxFrames, props.backgroundPosition, props.backgroundSize, props.backgroundRepeat, props.backgroundOrigin, props.backgroundClip);
7694
8827
  const clip = clippingMetadata(originalFrame, clipRect, visibleFrame);
7695
8828
  const unsupportedSemantics = [
8829
+ ...unsupportedCssLayoutValueSemantics(props),
8830
+ ...unsupportedTextLogicalLayoutSemantics(props),
7696
8831
  ...unsupportedTransformSemantics$1(props),
7697
8832
  ...unsupportedCompositingSemantics$1(props),
7698
8833
  ...unsupportedOpacityStackingContextSemantics$1(props),
@@ -7702,6 +8837,11 @@ function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, co
7702
8837
  flipH: resolved.flipH,
7703
8838
  flipV: resolved.flipV
7704
8839
  }),
8840
+ ...unsupportedWrappedTextMeasurementSemantics({
8841
+ props,
8842
+ placement,
8843
+ text
8844
+ }),
7705
8845
  ...strokes.unsupportedSemantics,
7706
8846
  ...outline.unsupportedSemantics,
7707
8847
  ...shadow.unsupportedSemantics,
@@ -7722,7 +8862,7 @@ function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, co
7722
8862
  flipV: resolved.flipV,
7723
8863
  ...unsupportedSemantics.length ? { unsupportedSemantics } : {},
7724
8864
  content: {
7725
- text: runs.map((run) => run.text).join(""),
8865
+ text,
7726
8866
  ...runs.length > 1 || runs.some((run) => run.style) ? { runs } : {}
7727
8867
  },
7728
8868
  style,
@@ -7733,11 +8873,12 @@ function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, co
7733
8873
  ...outline.outline ? { outline: outline.outline } : {},
7734
8874
  ...shadow.shadow ? { shadow: shadow.shadow } : {},
7735
8875
  ...hyperlink ? { hyperlink } : {},
7736
- radiusEmu: parseLength(props.borderRadius, 0, 0, textLengthContext)
8876
+ radiusEmu: resolveCornerRadiusEmu$1(props.borderRadius, visibleFrame, textLengthContext)
7737
8877
  };
7738
8878
  }
7739
8879
  function compileImageNode(node, parentFrame, idGenerator, placement, clipRect, context) {
7740
8880
  const { props } = node;
8881
+ const fit = normalizeProjectedImageFit(props.fit);
7741
8882
  const resolved = frameFromProps(props, parentFrame, placement, context);
7742
8883
  const shadow = parseShadowShorthandOrIgnore({
7743
8884
  property: "boxShadow",
@@ -7763,6 +8904,7 @@ function compileImageNode(node, parentFrame, idGenerator, placement, clipRect, c
7763
8904
  if (!visibleFrame) return null;
7764
8905
  const clip = clippingMetadata(originalFrame, clipRect, visibleFrame);
7765
8906
  const unsupportedSemantics = [
8907
+ ...unsupportedCssLayoutValueSemantics(props),
7766
8908
  ...unsupportedTransformSemantics$1(props),
7767
8909
  ...unsupportedCompositingSemantics$1(props),
7768
8910
  ...unsupportedOpacityStackingContextSemantics$1(props),
@@ -7777,9 +8919,14 @@ function compileImageNode(node, parentFrame, idGenerator, placement, clipRect, c
7777
8919
  rotation: resolved.rotation,
7778
8920
  flipH: resolved.flipH,
7779
8921
  flipV: resolved.flipV,
7780
- fit: props.fit,
8922
+ fit,
7781
8923
  hasExplicitCrop: crop !== void 0
7782
8924
  }),
8925
+ ...unsupportedObjectPositionSemantics({
8926
+ value: props.objectPosition,
8927
+ resolved: objectPosition
8928
+ }),
8929
+ ...unsupportedObjectFitSemantics(props.fit),
7783
8930
  ...shadow.unsupportedSemantics
7784
8931
  ];
7785
8932
  return {
@@ -7797,7 +8944,7 @@ function compileImageNode(node, parentFrame, idGenerator, placement, clipRect, c
7797
8944
  flipH: resolved.flipH,
7798
8945
  flipV: resolved.flipV,
7799
8946
  ...unsupportedSemantics.length ? { unsupportedSemantics } : {},
7800
- fit: props.fit ?? "contain",
8947
+ fit,
7801
8948
  ...objectPosition ? { objectPosition } : {},
7802
8949
  ...crop ? { crop } : {},
7803
8950
  transparency: normalizeTransparency$1(props.transparency),
@@ -7807,6 +8954,123 @@ function compileImageNode(node, parentFrame, idGenerator, placement, clipRect, c
7807
8954
  source: imageSourceFromProps(props)
7808
8955
  };
7809
8956
  }
8957
+ const DEFAULT_VIDEO_ASPECT_RATIO = 16 / 9;
8958
+ function isUnspecifiedVideoDimension(value) {
8959
+ if (value === void 0) return true;
8960
+ if (typeof value === "string") {
8961
+ const normalized = value.trim().toLowerCase();
8962
+ return normalized === "auto" || isCssWideKeyword(normalized);
8963
+ }
8964
+ return false;
8965
+ }
8966
+ function videoPropsWithFallbackFrame(props, parentFrame) {
8967
+ const missingWidth = isUnspecifiedVideoDimension(props.width);
8968
+ const missingHeight = isUnspecifiedVideoDimension(props.height);
8969
+ if (!missingWidth && !missingHeight) return {
8970
+ props,
8971
+ missingHeight,
8972
+ missingWidth,
8973
+ unsupportedSemantics: []
8974
+ };
8975
+ const aspectRatio = parseAspectRatio(props.aspectRatio) ?? DEFAULT_VIDEO_ASPECT_RATIO;
8976
+ const fallbackWidthIn = parentFrame.widthEmu / EMU_PER_INCH / 2;
8977
+ return {
8978
+ props: {
8979
+ ...props,
8980
+ aspectRatio: props.aspectRatio ?? `${DEFAULT_VIDEO_ASPECT_RATIO}`,
8981
+ ...missingWidth && missingHeight ? { width: fallbackWidthIn } : {}
8982
+ },
8983
+ missingHeight,
8984
+ missingWidth,
8985
+ unsupportedSemantics: [{
8986
+ feature: "layout",
8987
+ property: missingWidth && missingHeight ? "width,height" : missingWidth ? "width" : "height",
8988
+ value: missingWidth && missingHeight ? "auto auto" : "auto",
8989
+ reason: "Video frame size was omitted; deckjsx synthesized a 16:9 fallback frame for the initial playable video projection.",
8990
+ fallback: {
8991
+ strategy: "synthesizeFallbackFrame",
8992
+ preserves: ["playableVideoMedia"],
8993
+ missing: [
8994
+ ...missingWidth ? ["authoredWidth"] : [],
8995
+ ...missingHeight ? ["authoredHeight"] : [],
8996
+ ...props.aspectRatio === void 0 ? [`defaultAspectRatio=${aspectRatio}`] : []
8997
+ ]
8998
+ }
8999
+ }]
9000
+ };
9001
+ }
9002
+ function compileVideoNode(node, parentFrame, idGenerator, placement, clipRect, context) {
9003
+ const videoFrame = videoPropsWithFallbackFrame(node.props, parentFrame);
9004
+ const { props } = videoFrame;
9005
+ const fit = normalizeProjectedImageFit(props.fit);
9006
+ const resolved = frameFromProps(props, parentFrame, videoFrame.missingWidth || videoFrame.missingHeight ? {
9007
+ ...placement?.xEmu !== void 0 ? { xEmu: placement.xEmu } : {},
9008
+ ...placement?.yEmu !== void 0 ? { yEmu: placement.yEmu } : {},
9009
+ ...!videoFrame.missingWidth && placement?.widthEmu !== void 0 ? { widthEmu: placement.widthEmu } : {},
9010
+ ...!videoFrame.missingHeight && placement?.heightEmu !== void 0 ? { heightEmu: placement.heightEmu } : {}
9011
+ } : placement, context);
9012
+ const shadow = parseShadowShorthandOrIgnore({
9013
+ property: "boxShadow",
9014
+ value: props.boxShadow
9015
+ });
9016
+ const objectPosition = parseObjectPosition(props.objectPosition, {
9017
+ widthEmu: resolved.widthEmu,
9018
+ heightEmu: resolved.heightEmu
9019
+ });
9020
+ if (!props.src && !props.data) throw new Error("Video requires either src or data.");
9021
+ const originalFrame = {
9022
+ xEmu: resolved.xEmu,
9023
+ yEmu: resolved.yEmu,
9024
+ widthEmu: resolved.widthEmu,
9025
+ heightEmu: resolved.heightEmu
9026
+ };
9027
+ const visibleFrame = intersectClipRect(originalFrame, clipRect);
9028
+ if (!visibleFrame) return null;
9029
+ const clip = clippingMetadata(originalFrame, clipRect, visibleFrame);
9030
+ const unsupportedSemantics = [
9031
+ ...unsupportedCssLayoutValueSemantics(props),
9032
+ ...unsupportedTransformSemantics$1(props),
9033
+ ...unsupportedCompositingSemantics$1(props),
9034
+ ...unsupportedOpacityStackingContextSemantics$1(props),
9035
+ ...unsupportedClippingTransformSemantics({
9036
+ clip,
9037
+ rotation: resolved.rotation,
9038
+ flipH: resolved.flipH,
9039
+ flipV: resolved.flipV
9040
+ }),
9041
+ ...unsupportedObjectPositionSemantics({
9042
+ value: props.objectPosition,
9043
+ resolved: objectPosition
9044
+ }),
9045
+ ...unsupportedObjectFitSemantics(props.fit),
9046
+ ...shadow.unsupportedSemantics,
9047
+ ...videoFrame.unsupportedSemantics
9048
+ ];
9049
+ const posterSource = videoPosterSourceFromProps(props);
9050
+ return {
9051
+ id: idGenerator.nextNode(),
9052
+ kind: "video",
9053
+ ...node.origin ? { origin: node.origin } : {},
9054
+ frame: visibleFrame,
9055
+ siblingOrder: node.siblingOrder,
9056
+ ...clip ? { clip } : {},
9057
+ sourceFrame: originalFrame,
9058
+ opacity: resolved.opacity,
9059
+ rotation: resolved.rotation,
9060
+ zIndex: resolved.zIndex,
9061
+ ...props.visibility !== void 0 ? { visibility: props.visibility } : {},
9062
+ flipH: resolved.flipH,
9063
+ flipV: resolved.flipV,
9064
+ ...unsupportedSemantics.length ? { unsupportedSemantics } : {},
9065
+ fit,
9066
+ ...objectPosition ? { objectPosition } : {},
9067
+ transparency: normalizeTransparency$1(props.transparency),
9068
+ rounding: props.rounding,
9069
+ ...shadow.shadow ? { shadow: shadow.shadow } : {},
9070
+ source: videoSourceFromProps(props),
9071
+ ...posterSource ? { posterSource } : {}
9072
+ };
9073
+ }
7810
9074
  function compileShapeNode(node, parentFrame, idGenerator, placement, clipRect, context) {
7811
9075
  const { props } = node;
7812
9076
  const resolved = frameFromProps(props, parentFrame, placement, context);
@@ -7835,6 +9099,7 @@ function compileShapeNode(node, parentFrame, idGenerator, placement, clipRect, c
7835
9099
  }, visibleFrame, backgroundBoxFrames, props.backgroundPosition, props.backgroundSize, props.backgroundRepeat, props.backgroundOrigin, props.backgroundClip);
7836
9100
  const clip = clippingMetadata(originalFrame, clipRect, visibleFrame);
7837
9101
  const unsupportedSemantics = [
9102
+ ...unsupportedCssLayoutValueSemantics(props),
7838
9103
  ...unsupportedTransformSemantics$1(props),
7839
9104
  ...unsupportedCompositingSemantics$1(props),
7840
9105
  ...unsupportedOpacityStackingContextSemantics$1(props),
@@ -7871,7 +9136,7 @@ function compileShapeNode(node, parentFrame, idGenerator, placement, clipRect, c
7871
9136
  ...outline.outline ? { outline: outline.outline } : {},
7872
9137
  ...shadow.shadow ? { shadow: shadow.shadow } : {},
7873
9138
  ...hyperlink ? { hyperlink } : {},
7874
- radiusEmu: parseLength(props.radius, 0, 0, context)
9139
+ radiusEmu: resolveCornerRadiusEmu$1(props.radius, visibleFrame, context)
7875
9140
  };
7876
9141
  }
7877
9142
  function compileNode(child, parentFrame, idGenerator, placement, clipRect, context, resolutionOptions) {
@@ -7879,6 +9144,7 @@ function compileNode(child, parentFrame, idGenerator, placement, clipRect, conte
7879
9144
  case "view": return compileGroupNode(child, parentFrame, idGenerator, placement, clipRect, context, resolutionOptions);
7880
9145
  case "text": return compileTextNode(child, parentFrame, idGenerator, placement, clipRect, context);
7881
9146
  case "image": return compileImageNode(child, parentFrame, idGenerator, placement, clipRect, context);
9147
+ case "video": return compileVideoNode(child, parentFrame, idGenerator, placement, clipRect, context);
7882
9148
  case "shape": return compileShapeNode(child, parentFrame, idGenerator, placement, clipRect, context);
7883
9149
  }
7884
9150
  }
@@ -7889,14 +9155,19 @@ function compileSlide(root, context, slideFrame, idGenerator, lengthContext) {
7889
9155
  widthEmu: slideFrame.widthEmu,
7890
9156
  heightEmu: slideFrame.heightEmu
7891
9157
  }, slideFrame, backgroundBoxFrames, slideProps.backgroundPosition, slideProps.backgroundSize, slideProps.backgroundRepeat, slideProps.backgroundOrigin, slideProps.backgroundClip);
7892
- const nodes = root.children.map((child, siblingOrder) => layoutChildFromNode(child, siblingOrder, lengthContext)).filter((child) => child.props.display !== "none").map((child) => compileNode(child, slideFrame, idGenerator, void 0, void 0, lengthContext)).filter((node) => node !== null);
9158
+ const nodes = compileAbsoluteChildren(root.children.map((child, siblingOrder) => layoutChildFromNode(child, siblingOrder, lengthContext)).filter((child) => child.props.display !== "none"), slideFrame, idGenerator, {
9159
+ padding: void 0,
9160
+ gap: void 0,
9161
+ rowGap: void 0,
9162
+ columnGap: void 0
9163
+ }, void 0, lengthContext);
7893
9164
  return {
7894
9165
  id: idGenerator.nextSlide(),
7895
9166
  name: slideProps.name,
7896
9167
  ...root.origin ? { origin: root.origin } : {},
7897
9168
  background: backgroundFill.fill,
7898
9169
  ...backgroundFill.backgroundLayers ? { backgroundLayers: backgroundFill.backgroundLayers } : {},
7899
- nodes: sortNodesForPaint(nodes)
9170
+ nodes
7900
9171
  };
7901
9172
  }
7902
9173
  function resolveProjectedLayout(options, input) {
@@ -8001,6 +9272,7 @@ function mediaContentType(extension) {
8001
9272
  case "png": return "image/png";
8002
9273
  case "gif": return "image/gif";
8003
9274
  case "svg": return "image/svg+xml";
9275
+ case "mp4": return "video/mp4";
8004
9276
  default: return "application/octet-stream";
8005
9277
  }
8006
9278
  }
@@ -8065,8 +9337,15 @@ function buildPptxManifest(input) {
8065
9337
  targetPath: input.presentationPropertiesPart.path,
8066
9338
  type: "presentationProperties"
8067
9339
  }),
9340
+ relationship({
9341
+ id: input.serializedId("rId5"),
9342
+ ownerPath: input.presentationPart.path,
9343
+ targetPartId: input.tableStylesPart.id,
9344
+ targetPath: input.tableStylesPart.path,
9345
+ type: "tableStyles"
9346
+ }),
8068
9347
  ...input.slides.map((slide, index) => relationship({
8069
- id: input.serializedId(`rId${index + 5}`),
9348
+ id: input.serializedId(`rId${index + 6}`),
8070
9349
  ownerPath: input.presentationPart.path,
8071
9350
  targetPartId: slide.id,
8072
9351
  targetPath: slide.path,
@@ -8114,6 +9393,7 @@ function buildPptxManifest(input) {
8114
9393
  override(input.extendedDocumentPropertiesPart, "application/vnd.openxmlformats-officedocument.extended-properties+xml"),
8115
9394
  override(input.viewPropertiesPart, "application/vnd.openxmlformats-officedocument.presentationml.viewProps+xml"),
8116
9395
  override(input.presentationPropertiesPart, "application/vnd.openxmlformats-officedocument.presentationml.presProps+xml"),
9396
+ override(input.tableStylesPart, "application/vnd.openxmlformats-officedocument.presentationml.tableStyles+xml"),
8117
9397
  ...input.slides.map((slide) => override(slide, "application/vnd.openxmlformats-officedocument.presentationml.slide+xml"))
8118
9398
  ]
8119
9399
  };
@@ -8155,7 +9435,8 @@ function buildPptxManifest(input) {
8155
9435
  documentPropertiesPart: input.documentPropertiesPart,
8156
9436
  extendedDocumentPropertiesPart: input.extendedDocumentPropertiesPart,
8157
9437
  viewPropertiesPart: input.viewPropertiesPart,
8158
- presentationPropertiesPart: input.presentationPropertiesPart
9438
+ presentationPropertiesPart: input.presentationPropertiesPart,
9439
+ tableStylesPart: input.tableStylesPart
8159
9440
  };
8160
9441
  }
8161
9442
  //#endregion
@@ -8188,6 +9469,7 @@ function mediaTypeFromExtension$1(extension) {
8188
9469
  case "png": return "image/png";
8189
9470
  case "gif": return "image/gif";
8190
9471
  case "svg": return "image/svg+xml";
9472
+ case "mp4": return "video/mp4";
8191
9473
  default: return;
8192
9474
  }
8193
9475
  }
@@ -8197,6 +9479,7 @@ function extensionFromMediaType$1(mediaType) {
8197
9479
  case "image/png": return "png";
8198
9480
  case "image/gif": return "gif";
8199
9481
  case "image/svg+xml": return "svg";
9482
+ case "video/mp4": return "mp4";
8200
9483
  default: return;
8201
9484
  }
8202
9485
  }
@@ -8208,9 +9491,10 @@ function dataMediaType(value) {
8208
9491
  }
8209
9492
  function mediaAllocationKey(input) {
8210
9493
  const asset = input.assetEntityId ? input.assets?.get(input.assetEntityId) : void 0;
9494
+ const mediaKind = input.mediaKind ?? "image";
8211
9495
  const hash = asset?.probe?.hash;
8212
- if (hash) return `hash:${hash}:${asset?.probe?.extension ?? asset?.probe?.mediaType ?? imageExtension(input.source)}`;
8213
- return `source:${asset?.resolverScope ?? "deckjsx:builtin"}:${imageSourceKey(input.source)}`;
9496
+ if (hash) return `${mediaKind}:hash:${hash}:${asset?.probe?.extension ?? asset?.probe?.mediaType ?? imageExtension(input.source)}`;
9497
+ return `${mediaKind}:source:${asset?.resolverScope ?? "deckjsx:builtin"}:${imageSourceKey(input.source)}`;
8214
9498
  }
8215
9499
  function mediaPartIdForSource(input) {
8216
9500
  return packageIdentity("media", fingerprintString(mediaAllocationKey(input)));
@@ -8281,6 +9565,7 @@ function mediaPayloadFor(input) {
8281
9565
  } : void 0;
8282
9566
  const allocationKey = mediaAllocationKey(input);
8283
9567
  return {
9568
+ mediaKind: input.mediaKind ?? "image",
8284
9569
  source: input.source,
8285
9570
  sources: [input.source],
8286
9571
  ...input.elementId ? { elementId: input.elementId } : {},
@@ -8337,22 +9622,43 @@ function mergeMediaPackagePart(part, payload) {
8337
9622
  payload: mergeMediaPartPayload(part.payload, payload)
8338
9623
  };
8339
9624
  }
8340
- function withCanonicalImageMediaPartIds(slides, assets) {
9625
+ function withCanonicalMediaPartIds(slides, assets) {
8341
9626
  return slides.map((slide) => ({
8342
9627
  ...slide,
8343
9628
  payload: {
8344
9629
  ...slide.payload,
8345
9630
  drawing: drawingFromElements(mapElements(slideDrawingChildren(slide), (element) => {
8346
- if (element.kind !== "image") return element;
8347
- const assetEntityId = element.origin.assetEntityIds?.[0];
8348
- return {
8349
- ...element,
8350
- mediaPartId: mediaPartIdForSource({
8351
- source: element.source,
8352
- ...assetEntityId ? { assetEntityId } : {},
8353
- assets
8354
- })
8355
- };
9631
+ if (element.kind === "image") {
9632
+ const assetEntityId = element.origin.assetEntityIds?.[0];
9633
+ return {
9634
+ ...element,
9635
+ mediaPartId: mediaPartIdForSource({
9636
+ source: element.source,
9637
+ mediaKind: "image",
9638
+ ...assetEntityId ? { assetEntityId } : {},
9639
+ assets
9640
+ })
9641
+ };
9642
+ }
9643
+ if (element.kind === "video") {
9644
+ const [assetEntityId, posterAssetEntityId] = element.origin.assetEntityIds ?? [];
9645
+ return {
9646
+ ...element,
9647
+ mediaPartId: mediaPartIdForSource({
9648
+ source: element.source,
9649
+ mediaKind: "video",
9650
+ ...assetEntityId ? { assetEntityId } : {},
9651
+ assets
9652
+ }),
9653
+ ...element.posterSource ? { posterMediaPartId: mediaPartIdForSource({
9654
+ source: element.posterSource,
9655
+ mediaKind: "image",
9656
+ ...posterAssetEntityId ? { assetEntityId: posterAssetEntityId } : {},
9657
+ assets
9658
+ }) } : {}
9659
+ };
9660
+ }
9661
+ return element;
8356
9662
  }))
8357
9663
  }
8358
9664
  }));
@@ -8385,10 +9691,12 @@ function mediaPartsFor(slides, assets) {
8385
9691
  mediaIndex += 1;
8386
9692
  }
8387
9693
  walkElements(slideDrawingChildren(slide), (element) => {
8388
- if (element.kind !== "image" || !element.mediaPartId) return;
9694
+ if (element.kind !== "image" && element.kind !== "video") return;
9695
+ if (!element.mediaPartId) return;
8389
9696
  const assetEntityId = element.origin.assetEntityIds?.[0];
8390
9697
  const payload = mediaPayloadFor({
8391
9698
  source: element.source,
9699
+ mediaKind: element.kind === "video" ? "video" : "image",
8392
9700
  elementId: element.id,
8393
9701
  ...assetEntityId ? { assetEntityId } : {},
8394
9702
  assets
@@ -8404,6 +9712,7 @@ function mediaPartsFor(slides, assets) {
8404
9712
  kind: "media",
8405
9713
  path: `ppt/media/media${mediaIndex}.${mediaExtension({
8406
9714
  source: element.source,
9715
+ mediaKind: element.kind === "video" ? "video" : "image",
8407
9716
  ...assetEntityId ? { assetEntityId } : {},
8408
9717
  assets
8409
9718
  })}`,
@@ -8414,13 +9723,44 @@ function mediaPartsFor(slides, assets) {
8414
9723
  payload
8415
9724
  });
8416
9725
  mediaIndex += 1;
9726
+ if (element.kind !== "video" || !element.posterSource || !element.posterMediaPartId) return;
9727
+ const posterAssetEntityId = element.origin.assetEntityIds?.[1];
9728
+ const posterPayload = mediaPayloadFor({
9729
+ source: element.posterSource,
9730
+ mediaKind: "image",
9731
+ elementId: element.id,
9732
+ ...posterAssetEntityId ? { assetEntityId: posterAssetEntityId } : {},
9733
+ assets
9734
+ });
9735
+ const currentPoster = parts.get(element.posterMediaPartId);
9736
+ if (currentPoster) {
9737
+ parts.set(element.posterMediaPartId, mergeMediaPackagePart(currentPoster, posterPayload));
9738
+ return;
9739
+ }
9740
+ parts.set(element.posterMediaPartId, {
9741
+ id: element.posterMediaPartId,
9742
+ category: "authored-content",
9743
+ kind: "media",
9744
+ path: `ppt/media/media${mediaIndex}.${mediaExtension({
9745
+ source: element.posterSource,
9746
+ mediaKind: "image",
9747
+ ...posterAssetEntityId ? { assetEntityId: posterAssetEntityId } : {},
9748
+ assets
9749
+ })}`,
9750
+ origin: {
9751
+ ...element.origin.graphNodeIds ? { graphNodeIds: element.origin.graphNodeIds } : {},
9752
+ ...element.origin.source ? { source: element.origin.source } : {}
9753
+ },
9754
+ payload: posterPayload
9755
+ });
9756
+ mediaIndex += 1;
8417
9757
  });
8418
9758
  }
8419
9759
  return [...parts.values()];
8420
9760
  }
8421
9761
  function withHyperlinkRelationship(input) {
8422
9762
  const { element } = input;
8423
- if (element.kind === "group" || !element.hyperlink) return element;
9763
+ if (element.kind === "group" || element.kind === "video" || !element.hyperlink) return element;
8424
9764
  const relationshipId = nextSlideRelationshipId(input.relationships);
8425
9765
  const serialized = {
8426
9766
  ...element.serialized,
@@ -8456,6 +9796,9 @@ function withHyperlinkRelationship(input) {
8456
9796
  function nextSlideRelationshipId(relationships) {
8457
9797
  return mediaRelationshipId(relationships.length + 1);
8458
9798
  }
9799
+ function relationshipKey(type, mediaPartId) {
9800
+ return `${type}:${mediaPartId}`;
9801
+ }
8459
9802
  function attachMediaRelationships(slides, mediaParts, assets) {
8460
9803
  const mediaPartById = new Map(mediaParts.map((part) => [part.id, part]));
8461
9804
  return slides.map((slide) => {
@@ -8463,7 +9806,8 @@ function attachMediaRelationships(slides, mediaParts, assets) {
8463
9806
  const relationshipByMediaPartId = /* @__PURE__ */ new Map();
8464
9807
  for (const backgroundImage of backgroundImageLayersForSlide(slide, assets)) {
8465
9808
  const mediaPart = mediaPartById.get(backgroundImage.mediaPartId);
8466
- if (!mediaPart || relationshipByMediaPartId.has(backgroundImage.mediaPartId)) continue;
9809
+ const key = relationshipKey("image", backgroundImage.mediaPartId);
9810
+ if (!mediaPart || relationshipByMediaPartId.has(key)) continue;
8467
9811
  const relationship = {
8468
9812
  id: nextSlideRelationshipId(relationships),
8469
9813
  target: projectedRelationshipTarget({
@@ -8474,7 +9818,7 @@ function attachMediaRelationships(slides, mediaParts, assets) {
8474
9818
  targetPath: mediaPart.path,
8475
9819
  type: "image"
8476
9820
  };
8477
- relationshipByMediaPartId.set(backgroundImage.mediaPartId, relationship);
9821
+ relationshipByMediaPartId.set(key, relationship);
8478
9822
  relationships.push(relationship);
8479
9823
  }
8480
9824
  const children = mapElements(slideDrawingChildren(slide), (element) => {
@@ -8482,7 +9826,8 @@ function attachMediaRelationships(slides, mediaParts, assets) {
8482
9826
  if (nextElement.kind === "image" && nextElement.mediaPartId) {
8483
9827
  const mediaPart = mediaPartById.get(nextElement.mediaPartId);
8484
9828
  if (mediaPart) {
8485
- const relationship = relationshipByMediaPartId.get(nextElement.mediaPartId) ?? {
9829
+ const key = relationshipKey("image", nextElement.mediaPartId);
9830
+ const relationship = relationshipByMediaPartId.get(key) ?? {
8486
9831
  id: nextSlideRelationshipId(relationships),
8487
9832
  target: projectedRelationshipTarget({
8488
9833
  ownerPath: slide.path,
@@ -8492,8 +9837,8 @@ function attachMediaRelationships(slides, mediaParts, assets) {
8492
9837
  targetPath: mediaPart.path,
8493
9838
  type: "image"
8494
9839
  };
8495
- if (!relationshipByMediaPartId.has(nextElement.mediaPartId)) {
8496
- relationshipByMediaPartId.set(nextElement.mediaPartId, relationship);
9840
+ if (!relationshipByMediaPartId.has(key)) {
9841
+ relationshipByMediaPartId.set(key, relationship);
8497
9842
  relationships.push(relationship);
8498
9843
  }
8499
9844
  nextElement = {
@@ -8505,6 +9850,69 @@ function attachMediaRelationships(slides, mediaParts, assets) {
8505
9850
  };
8506
9851
  }
8507
9852
  }
9853
+ if (nextElement.kind === "video" && nextElement.mediaPartId) {
9854
+ const mediaPart = mediaPartById.get(nextElement.mediaPartId);
9855
+ if (mediaPart) {
9856
+ const videoKey = relationshipKey("video", nextElement.mediaPartId);
9857
+ const videoRelationship = relationshipByMediaPartId.get(videoKey) ?? {
9858
+ id: nextSlideRelationshipId(relationships),
9859
+ target: projectedRelationshipTarget({
9860
+ ownerPath: slide.path,
9861
+ targetPath: mediaPart.path
9862
+ }),
9863
+ targetPartId: mediaPart.id,
9864
+ targetPath: mediaPart.path,
9865
+ type: "video"
9866
+ };
9867
+ if (!relationshipByMediaPartId.has(videoKey)) {
9868
+ relationshipByMediaPartId.set(videoKey, videoRelationship);
9869
+ relationships.push(videoRelationship);
9870
+ }
9871
+ const mediaKey = relationshipKey("media", nextElement.mediaPartId);
9872
+ const mediaRelationship = relationshipByMediaPartId.get(mediaKey) ?? {
9873
+ id: nextSlideRelationshipId(relationships),
9874
+ target: projectedRelationshipTarget({
9875
+ ownerPath: slide.path,
9876
+ targetPath: mediaPart.path
9877
+ }),
9878
+ targetPartId: mediaPart.id,
9879
+ targetPath: mediaPart.path,
9880
+ type: "media"
9881
+ };
9882
+ if (!relationshipByMediaPartId.has(mediaKey)) {
9883
+ relationshipByMediaPartId.set(mediaKey, mediaRelationship);
9884
+ relationships.push(mediaRelationship);
9885
+ }
9886
+ nextElement = {
9887
+ ...nextElement,
9888
+ serialized: {
9889
+ ...nextElement.serialized,
9890
+ relationshipId: videoRelationship.id,
9891
+ mediaRelationshipId: mediaRelationship.id
9892
+ }
9893
+ };
9894
+ }
9895
+ if (nextElement.posterMediaPartId) {
9896
+ const posterPart = mediaPartById.get(nextElement.posterMediaPartId);
9897
+ if (posterPart) {
9898
+ const posterKey = relationshipKey("image", nextElement.posterMediaPartId);
9899
+ const posterRelationship = relationshipByMediaPartId.get(posterKey) ?? {
9900
+ id: nextSlideRelationshipId(relationships),
9901
+ target: projectedRelationshipTarget({
9902
+ ownerPath: slide.path,
9903
+ targetPath: posterPart.path
9904
+ }),
9905
+ targetPartId: posterPart.id,
9906
+ targetPath: posterPart.path,
9907
+ type: "image"
9908
+ };
9909
+ if (!relationshipByMediaPartId.has(posterKey)) {
9910
+ relationshipByMediaPartId.set(posterKey, posterRelationship);
9911
+ relationships.push(posterRelationship);
9912
+ }
9913
+ }
9914
+ }
9915
+ }
8508
9916
  return withHyperlinkRelationship({
8509
9917
  element: nextElement,
8510
9918
  ownerPath: slide.path,
@@ -8559,6 +9967,9 @@ function textRunStyleFor(node, resolvedStyles) {
8559
9967
  function imageStyleFor(node, resolvedStyles) {
8560
9968
  return targetStyle(pptxStyleFor(node, resolvedStyles), IMAGE_STYLE_KEYS);
8561
9969
  }
9970
+ function videoStyleFor(node, resolvedStyles) {
9971
+ return targetStyle(pptxStyleFor(node, resolvedStyles), VIDEO_STYLE_KEYS);
9972
+ }
8562
9973
  function shapeStyleFor(node, resolvedStyles, shape) {
8563
9974
  return {
8564
9975
  ...targetStyle(pptxStyleFor(node, resolvedStyles), SHAPE_STYLE_KEYS),
@@ -8611,24 +10022,23 @@ function shapeFillInputFor(resolved, props) {
8611
10022
  function errorReason(error) {
8612
10023
  return error instanceof Error ? error.message : String(error);
8613
10024
  }
8614
- function semanticValue(value) {
8615
- return typeof value === "string" ? value : JSON.stringify(value);
8616
- }
8617
- function unsupportedSemantic(input) {
8618
- if (input.value === void 0 || input.value === null || input.value === "") return;
8619
- return {
8620
- feature: input.feature,
8621
- property: input.property,
8622
- value: semanticValue(input.value),
8623
- reason: errorReason(input.error),
8624
- ...input.fallback ? { fallback: input.fallback } : {}
8625
- };
8626
- }
8627
10025
  function parseShadowSafely(input) {
8628
10026
  try {
10027
+ const shadow = parseShadowShorthand(input.value);
10028
+ const unsupported = hasShadowSpreadRadius(input.value) ? unsupportedSemantic({
10029
+ feature: "shadow",
10030
+ property: input.property,
10031
+ value: input.value,
10032
+ error: /* @__PURE__ */ new Error(`CSS shadow spread radius is not projected by the current PPTX shadow model: ${input.value}`),
10033
+ fallback: {
10034
+ strategy: "preserveAuthoredValueOnly",
10035
+ preserves: ["projectedShadowWithoutSpread"],
10036
+ missing: ["cssShadowSpreadRadius"]
10037
+ }
10038
+ }) : void 0;
8629
10039
  return {
8630
- shadow: parseShadowShorthand(input.value),
8631
- unsupportedSemantics: []
10040
+ shadow,
10041
+ unsupportedSemantics: unsupported ? [unsupported] : []
8632
10042
  };
8633
10043
  } catch (error) {
8634
10044
  const unsupported = unsupportedSemantic({
@@ -8717,6 +10127,27 @@ function isExplicitNone(value) {
8717
10127
  function isStrokeIntentionallyNone(props) {
8718
10128
  return isExplicitNone(props.border) || isExplicitNone(props.borderTop) || isExplicitNone(props.borderRight) || isExplicitNone(props.borderBottom) || isExplicitNone(props.borderLeft) || props.borderStyle === "none";
8719
10129
  }
10130
+ function unsupportedStrokeCssWideKeywordSemantics(props) {
10131
+ const unsupported = [];
10132
+ for (const property of [
10133
+ "borderWidth",
10134
+ "borderTopWidth",
10135
+ "borderRightWidth",
10136
+ "borderBottomWidth",
10137
+ "borderLeftWidth",
10138
+ "strokeWidth"
10139
+ ]) {
10140
+ if (!hasCssWideKeywordToken(props[property])) continue;
10141
+ const semantic = unsupportedCssWideKeywordSemantic(property, props[property]);
10142
+ if (semantic) unsupported.push(semantic);
10143
+ }
10144
+ return unsupported;
10145
+ }
10146
+ function unsupportedOutlineCssWideKeywordSemantics(props) {
10147
+ if (!hasCssWideKeywordToken(props.outlineWidth)) return [];
10148
+ const semantic = unsupportedCssWideKeywordSemantic("outlineWidth", props.outlineWidth);
10149
+ return semantic ? [semantic] : [];
10150
+ }
8720
10151
  function unsupportedStrokeFallback(props, error) {
8721
10152
  const input = strokeFallbackInput(props);
8722
10153
  return unsupportedSemantic({
@@ -8732,32 +10163,34 @@ function unsupportedStrokeFallback(props, error) {
8732
10163
  });
8733
10164
  }
8734
10165
  function resolveNodeStrokesSafely(props, context) {
10166
+ const cssWideSemantics = unsupportedStrokeCssWideKeywordSemantics(props);
8735
10167
  try {
8736
10168
  const strokes = resolveNodeStrokes(props, context);
8737
10169
  if (!strokes.stroke && !strokes.edgeStrokes && hasAuthoredStrokeInput(props) && !isStrokeIntentionallyNone(props)) {
8738
10170
  const semantic = unsupportedStrokeFallback(props, /* @__PURE__ */ new Error("No PPTX stroke could be produced from the authored stroke input."));
8739
10171
  return {
8740
10172
  ...strokes,
8741
- unsupportedSemantics: semantic ? [semantic] : []
10173
+ unsupportedSemantics: semantic ? [semantic, ...cssWideSemantics] : cssWideSemantics
8742
10174
  };
8743
10175
  }
8744
10176
  return {
8745
10177
  ...strokes,
8746
- unsupportedSemantics: []
10178
+ unsupportedSemantics: cssWideSemantics
8747
10179
  };
8748
10180
  } catch (error) {
8749
10181
  const semantic = unsupportedStrokeFallback(props, error);
8750
- return { unsupportedSemantics: semantic ? [semantic] : [] };
10182
+ return { unsupportedSemantics: semantic ? [semantic, ...cssWideSemantics] : cssWideSemantics };
8751
10183
  }
8752
10184
  }
8753
10185
  function outlineStrokeSafely(props, context) {
8754
10186
  if (!hasAuthoredOutlineInput(props)) return { unsupportedSemantics: [] };
10187
+ const cssWideSemantics = unsupportedOutlineCssWideKeywordSemantics(props);
8755
10188
  try {
8756
10189
  const outlineInput = parseOutlineShorthand(props.outline);
8757
10190
  const outline = toStroke(props.outlineColor ?? outlineInput.outlineColor, props.outlineWidth ?? outlineInput.outlineWidth, props.outlineStyle ?? outlineInput.outlineStyle, outlineInput.outlineDashType, parseStrokeLineCap(props.strokeLinecap), parseStrokeLineJoin(props.strokeLinejoin), void 0, context);
8758
10191
  if (outline) return {
8759
10192
  outline,
8760
- unsupportedSemantics: []
10193
+ unsupportedSemantics: cssWideSemantics
8761
10194
  };
8762
10195
  const input = outlineFallbackInput(props);
8763
10196
  const semantic = unsupportedSemantic({
@@ -8771,7 +10204,7 @@ function outlineStrokeSafely(props, context) {
8771
10204
  missing: ["pptxOutline"]
8772
10205
  }
8773
10206
  });
8774
- return { unsupportedSemantics: semantic ? [semantic] : [] };
10207
+ return { unsupportedSemantics: semantic ? [semantic, ...cssWideSemantics] : cssWideSemantics };
8775
10208
  } catch (error) {
8776
10209
  const input = outlineFallbackInput(props);
8777
10210
  const semantic = unsupportedSemantic({
@@ -8785,7 +10218,7 @@ function outlineStrokeSafely(props, context) {
8785
10218
  missing: ["pptxOutline"]
8786
10219
  }
8787
10220
  });
8788
- return { unsupportedSemantics: semantic ? [semantic] : [] };
10221
+ return { unsupportedSemantics: semantic ? [semantic, ...cssWideSemantics] : cssWideSemantics };
8789
10222
  }
8790
10223
  }
8791
10224
  function unsupportedTransformSemantics(props) {
@@ -9018,6 +10451,17 @@ function unsupportedSemanticsForGraphNode(node, resolvedStyles) {
9018
10451
  }).unsupportedSemantics
9019
10452
  ];
9020
10453
  }
10454
+ case "video": {
10455
+ const props = normalizeVideoProps(videoStyleFor(node, resolvedStyles));
10456
+ return [
10457
+ ...unsupportedTransformSemantics(props),
10458
+ ...unsupportedCompositingSemantics(props),
10459
+ ...parseShadowSafely({
10460
+ property: "boxShadow",
10461
+ value: props.boxShadow
10462
+ }).unsupportedSemantics
10463
+ ];
10464
+ }
9021
10465
  case "shape": {
9022
10466
  const props = normalizeShapeProps({ ...shapeStyleFor(node, resolvedStyles, node.shape) });
9023
10467
  const strokes = resolveNodeStrokesSafely(props);
@@ -9097,7 +10541,7 @@ function collectPptxUnsupportedProjectionModelDiagnostics(projection, options =
9097
10541
  const slideItems = [];
9098
10542
  walkElements(slide.payload.drawing.children, (element) => {
9099
10543
  for (const semantic of element.unsupportedSemantics ?? []) {
9100
- if (!options.includeAllUnsupportedSemantics && semantic.feature !== "border" && semantic.feature !== "clipping" && semantic.feature !== "filter" && semantic.feature !== "blend" && semantic.feature !== "isolation" && semantic.feature !== "outline" && semantic.feature !== "stroke" && !(semantic.feature === "opacity" && semantic.property === "stackingContext") && !(semantic.feature === "transform" && semantic.property === "stackingContext")) continue;
10544
+ if (!options.includeAllUnsupportedSemantics && semantic.feature !== "border" && semantic.feature !== "clipping" && semantic.feature !== "filter" && semantic.feature !== "blend" && semantic.feature !== "isolation" && semantic.feature !== "outline" && semantic.feature !== "stroke" && semantic.fallback?.strategy !== "synthesizeFallbackFrame" && !(semantic.feature === "opacity" && semantic.property === "stackingContext") && !(semantic.feature === "transform" && semantic.property === "stackingContext")) continue;
9101
10545
  const graphNodeId = element.origin.graphNodeIds?.[0];
9102
10546
  slideItems.push(diagnostic({
9103
10547
  severity: "warning",
@@ -9137,6 +10581,10 @@ const DEFAULT_OBJECT_POSITION = {
9137
10581
  x: .5,
9138
10582
  y: .5
9139
10583
  };
10584
+ const DEFAULT_VIDEO_POSTER_SOURCE = {
10585
+ kind: "data",
10586
+ data: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNgYAAAAAMAASsJTYQAAAAASUVORK5CYII="
10587
+ };
9140
10588
  const DEFAULT_TEXT_FIT = "none";
9141
10589
  const DEFAULT_TEXT_DIRECTION = "horz";
9142
10590
  const DEFAULT_TEXT_VERTICAL_ALIGN = "top";
@@ -9239,6 +10687,9 @@ function parseObjectPositionValue(objectPosition, frame) {
9239
10687
  y: axisValue(yToken, frame.heightEmu)
9240
10688
  };
9241
10689
  }
10690
+ function resolveCornerRadiusEmu(value, frame, context) {
10691
+ return parseLength(value, Math.min(frame.widthEmu, frame.heightEmu), 0, context);
10692
+ }
9242
10693
  function textStyleFromProps(props, textLengthContext) {
9243
10694
  const list = resolveListStyle(props, textLengthContext);
9244
10695
  const lineHeight = resolveLineHeight(props.lineHeight, textLengthContext);
@@ -9262,11 +10713,11 @@ function textStyleFromProps(props, textLengthContext) {
9262
10713
  paddingPt: parseSpacingInPoints(props.padding, textLengthContext),
9263
10714
  lineSpacing: props.lineSpacing ?? lineHeight.lineSpacing,
9264
10715
  lineSpacingMultiple: props.lineSpacingMultiple ?? lineHeight.lineSpacingMultiple,
9265
- paragraphSpacingBefore: props.paragraphSpacingBefore,
9266
- paragraphSpacingAfter: props.paragraphSpacingAfter,
10716
+ paragraphSpacingBefore: props.paragraphSpacingBefore === void 0 ? void 0 : parsePointValue(props.paragraphSpacingBefore, 0, textLengthContext),
10717
+ paragraphSpacingAfter: props.paragraphSpacingAfter === void 0 ? void 0 : parsePointValue(props.paragraphSpacingAfter, 0, textLengthContext),
9267
10718
  ...props.textIndent === void 0 ? {} : { textIndentPt: parsePointValue(props.textIndent, 0, textLengthContext) },
9268
10719
  ...tabStops ? { tabStops } : {},
9269
- charSpacing: props.charSpacing,
10720
+ charSpacing: resolveCharacterSpacing(props.charSpacing, textLengthContext),
9270
10721
  ...list ? { list } : {},
9271
10722
  fit: props.fit ?? DEFAULT_TEXT_FIT,
9272
10723
  wrap: props.wrap ?? DEFAULT_TEXT_WRAP,
@@ -9531,7 +10982,7 @@ function compileContainer(graph, resolvedStyles, node, templates, packagePartIdV
9531
10982
  ...outlineResult.outline ? { outline: outlineResult.outline } : {},
9532
10983
  ...generatedStrokes ? { generatedStrokes } : {},
9533
10984
  ...shadowResult.shadow ? { shadow: shadowResult.shadow } : {},
9534
- radiusEmu: parseLength(props.borderRadius, 0, 0, context),
10985
+ radiusEmu: resolveCornerRadiusEmu(props.borderRadius, frame, context),
9535
10986
  children: compileChildren(graph, resolvedStyles, node.children, templates, packagePartIdValue, frame, indexPath, context)
9536
10987
  };
9537
10988
  }
@@ -9610,7 +11061,7 @@ function compileText(graph, resolvedStyles, node, templates, packagePartIdValue,
9610
11061
  ...generatedStrokes ? { generatedStrokes } : {},
9611
11062
  ...shadowResult.shadow ? { shadow: shadowResult.shadow } : {},
9612
11063
  ...hyperlink ? { hyperlink } : {},
9613
- radiusEmu: parseLength(props.borderRadius, 0, 0, textLengthContext)
11064
+ radiusEmu: resolveCornerRadiusEmu(props.borderRadius, frame, textLengthContext)
9614
11065
  };
9615
11066
  }
9616
11067
  function compileImage(graph, resolvedStyles, node, templates, packagePartIdValue, parentFrame, indexPath, context) {
@@ -9623,6 +11074,7 @@ function compileImage(graph, resolvedStyles, node, templates, packagePartIdValue
9623
11074
  }, context);
9624
11075
  if (props.display === "none") return;
9625
11076
  const frame = frameToFrameIR$1(frameFromProps(props, parentFrame, void 0, context));
11077
+ const fit = normalizeProjectedImageFit(props.fit);
9626
11078
  const shadowResult = parseShadowSafely({
9627
11079
  property: "boxShadow",
9628
11080
  value: props.boxShadow
@@ -9642,6 +11094,7 @@ function compileImage(graph, resolvedStyles, node, templates, packagePartIdValue
9642
11094
  ...unsupportedTransformSemantics(props),
9643
11095
  ...unsupportedCompositingSemantics(props),
9644
11096
  ...unsupportedOpacityStackingContextSemantics(props),
11097
+ ...unsupportedObjectFitSemantics(props.fit),
9645
11098
  ...shadowResult.unsupportedSemantics
9646
11099
  ]
9647
11100
  });
@@ -9651,7 +11104,7 @@ function compileImage(graph, resolvedStyles, node, templates, packagePartIdValue
9651
11104
  mediaPartId: mediaPartIdForElement(base.id),
9652
11105
  sourceFrame: frame,
9653
11106
  source: assetSource(asset),
9654
- fit: props.fit ?? "contain",
11107
+ fit,
9655
11108
  objectPosition: parseObjectPositionValue(props.objectPosition, frame),
9656
11109
  ...parseImageCrop(props.crop) ? { crop: parseImageCrop(props.crop) } : {},
9657
11110
  transparency: props.transparency,
@@ -9728,7 +11181,7 @@ function compileShape(node, resolvedStyles, templates, packagePartIdValue, paren
9728
11181
  ...generatedStrokes ? { generatedStrokes } : {},
9729
11182
  ...shadowResult.shadow ? { shadow: shadowResult.shadow } : {},
9730
11183
  ...hyperlink ? { hyperlink } : {},
9731
- radiusEmu: parseLength(props.radius, 0, 0, context)
11184
+ radiusEmu: resolveCornerRadiusEmu(props.radius, frame, context)
9732
11185
  };
9733
11186
  }
9734
11187
  function compileElement(input) {
@@ -9738,6 +11191,7 @@ function compileElement(input) {
9738
11191
  case "container": return compileContainer(input.graph, input.resolvedStyles, node, input.templates, input.packagePartId, input.parentFrame, input.indexPath, input.context);
9739
11192
  case "text": return compileText(input.graph, input.resolvedStyles, node, input.templates, input.packagePartId, input.parentFrame, input.indexPath, input.context);
9740
11193
  case "image": return compileImage(input.graph, input.resolvedStyles, node, input.templates, input.packagePartId, input.parentFrame, input.indexPath, input.context);
11194
+ case "video": return;
9741
11195
  case "shape": return compileShape(node, input.resolvedStyles, input.templates, input.packagePartId, input.parentFrame, input.indexPath, input.context);
9742
11196
  case "document":
9743
11197
  case "slide":
@@ -9896,6 +11350,23 @@ function mapProjectedLayoutNodeToElement(input) {
9896
11350
  shadow: input.node.shadow,
9897
11351
  hyperlink: input.node.hyperlink
9898
11352
  };
11353
+ case "video": {
11354
+ const posterSource = input.node.posterSource ?? DEFAULT_VIDEO_POSTER_SOURCE;
11355
+ return {
11356
+ ...base,
11357
+ kind: "video",
11358
+ mediaPartId: mediaPartIdForElement(base.id),
11359
+ posterMediaPartId: packageIdentity("media", `${base.id}:poster`),
11360
+ sourceFrame: input.node.sourceFrame,
11361
+ source: input.node.source,
11362
+ posterSource,
11363
+ fit: input.node.fit,
11364
+ objectPosition: input.node.objectPosition ?? DEFAULT_OBJECT_POSITION,
11365
+ transparency: input.node.transparency,
11366
+ rounding: input.node.rounding,
11367
+ shadow: input.node.shadow
11368
+ };
11369
+ }
9899
11370
  case "shape": {
9900
11371
  const backgroundLayers = projectBackgroundLayers({
9901
11372
  layers: input.node.backgroundLayers,
@@ -10784,6 +12255,17 @@ function defaultPptxSupportParts(input) {
10784
12255
  editable: true,
10785
12256
  settings: {}
10786
12257
  }
12258
+ },
12259
+ tableStylesPart: {
12260
+ id: packageIdentity("support", "table-styles"),
12261
+ category: "support",
12262
+ kind: "table-styles",
12263
+ path: "ppt/tableStyles.xml",
12264
+ payload: {
12265
+ kind: "table-styles",
12266
+ editable: true,
12267
+ defaultStyleId: "{5C22544A-7EE6-4342-B048-85BDC9FD1C3A}"
12268
+ }
10787
12269
  }
10788
12270
  };
10789
12271
  }
@@ -10824,7 +12306,7 @@ function projectGraphToPptxPackageInternal(input) {
10824
12306
  widthEmu: size.widthEmu,
10825
12307
  heightEmu: size.heightEmu
10826
12308
  };
10827
- const projectedSlidesWithMedia = withCanonicalImageMediaPartIds(slideIds.flatMap((slideId, slideIndex) => {
12309
+ const projectedSlidesWithMedia = withCanonicalMediaPartIds(slideIds.flatMap((slideId, slideIndex) => {
10828
12310
  const slide = input.graph.nodes.get(slideId);
10829
12311
  if (slide?.kind !== "slide") return [];
10830
12312
  const layoutSlide = projectedLayout?.slides[slideIndex];
@@ -10880,6 +12362,7 @@ function projectGraphToPptxPackageInternal(input) {
10880
12362
  extendedDocumentPropertiesPart: supportParts.extendedDocumentPropertiesPart,
10881
12363
  viewPropertiesPart: supportParts.viewPropertiesPart,
10882
12364
  presentationPropertiesPart: supportParts.presentationPropertiesPart,
12365
+ tableStylesPart: supportParts.tableStylesPart,
10883
12366
  slides,
10884
12367
  mediaParts,
10885
12368
  serializedId
@@ -10898,6 +12381,7 @@ function projectGraphToPptxPackageInternal(input) {
10898
12381
  manifest.extendedDocumentPropertiesPart,
10899
12382
  manifest.viewPropertiesPart,
10900
12383
  manifest.presentationPropertiesPart,
12384
+ manifest.tableStylesPart,
10901
12385
  ...slides,
10902
12386
  ...slideRelationshipParts,
10903
12387
  ...mediaParts
@@ -10976,7 +12460,7 @@ async function loadNodeOutputRuntime() {
10976
12460
  const status = nodeOutputRuntimeStatus();
10977
12461
  if (!status.ok) return status;
10978
12462
  try {
10979
- const { createNodeOutputByteSink, writeNodeOutput } = await import("./node-output-BXQOTLKj.mjs");
12463
+ const { createNodeOutputByteSink, writeNodeOutput } = await import("./node-output-L2bV2_8g.mjs");
10980
12464
  return {
10981
12465
  ok: true,
10982
12466
  createByteSink: createNodeOutputByteSink,
@@ -11098,10 +12582,11 @@ function assetProbeInvalidFields(result) {
11098
12582
  if (result.byteLength !== void 0 && (!isFiniteNumber(result.byteLength) || result.byteLength < 0)) invalidFields.push("byteLength");
11099
12583
  return invalidFields;
11100
12584
  }
11101
- function missingRequiredAssetProbeFields(probe) {
12585
+ function missingRequiredAssetProbeFields(input) {
12586
+ if (input.assetKind === "video") return [];
11102
12587
  const missingFields = [];
11103
- if (probe?.width === void 0) missingFields.push("width");
11104
- if (probe?.height === void 0) missingFields.push("height");
12588
+ if (input.probe?.width === void 0) missingFields.push("width");
12589
+ if (input.probe?.height === void 0) missingFields.push("height");
11105
12590
  return missingFields;
11106
12591
  }
11107
12592
  function normalizedAssetProbeResult(input) {
@@ -11495,7 +12980,10 @@ async function resolveAssetArtifacts(input) {
11495
12980
  }
11496
12981
  resolverScope = BUILTIN_ASSET_RESOLVER_SCOPE;
11497
12982
  }
11498
- const missingRequiredFields = missingRequiredAssetProbeFields(probe);
12983
+ const missingRequiredFields = missingRequiredAssetProbeFields({
12984
+ probe,
12985
+ assetKind: asset.kind
12986
+ });
11499
12987
  if (missingRequiredFields.length > 0) diagnostics.push(missingRequiredAssetProbeDiagnostics({
11500
12988
  source,
11501
12989
  resolverScope,
@@ -11720,21 +13208,11 @@ async function prepareRenderOutputSink(adapter) {
11720
13208
  path: output,
11721
13209
  runtime: outputRuntime
11722
13210
  };
11723
- try {
11724
- return {
11725
- requested: true,
11726
- mode: "sink",
11727
- path: output,
11728
- sink: outputRuntime.createByteSink({ output })
11729
- };
11730
- } catch (error) {
11731
- return {
11732
- requested: true,
11733
- mode: "sinkCreationFailed",
11734
- path: output,
11735
- error
11736
- };
11737
- }
13211
+ return {
13212
+ requested: true,
13213
+ mode: "deferredWrite",
13214
+ path: output
13215
+ };
11738
13216
  }
11739
13217
  async function writeRenderedArtifact(input) {
11740
13218
  if (!input.preparedOutput.requested) return {