deckjsx 0.8.0 → 0.8.2

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 { a as isSlideNode, c as authorElementPropsFromEntries, d as isAuthorTreeNode, f as isAuthoredTag, i as isContentNode, l as createAuthorElement, o as isAuthorNodeValue, r as isAuthorNode, s as toAuthorJsxNode, u as isAuthorTreeChild } from "./jsx-DGGM5erN.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-BamaV2yi.mjs";
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 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-B3Efckbf.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");
@@ -61,7 +61,6 @@ function validateSourceKey(sourceKey) {
61
61
  if (sourceKey.includes("/")) return "Source Key must not contain /.";
62
62
  }
63
63
  function describeInvalidRoot(value) {
64
- if (isAuthorNodeValue(value)) return "Slide factory returned an AuthorNode value instead of an Author Tree node.";
65
64
  if (isAuthorTreeNode(value)) return "Slide factory returned an Author Tree node that cannot be used as slide content.";
66
65
  if (value === null) return "Slide factory returned null.";
67
66
  return `Slide factory returned ${typeof value}.`;
@@ -629,7 +628,7 @@ const ELEMENT_DEFAULTS = {
629
628
  rotation: 0,
630
629
  zIndex: 0,
631
630
  overflow: "visible",
632
- position: "relative",
631
+ position: "static",
633
632
  boxSizing: "border-box",
634
633
  backgroundTransparency: 100,
635
634
  borderWidth: 0,
@@ -646,7 +645,7 @@ const ELEMENT_DEFAULTS = {
646
645
  rotation: 0,
647
646
  zIndex: 0,
648
647
  overflow: "visible",
649
- position: "relative",
648
+ position: "static",
650
649
  boxSizing: "border-box",
651
650
  backgroundTransparency: 100,
652
651
  borderWidth: 0,
@@ -706,7 +705,7 @@ const ELEMENT_DEFAULTS = {
706
705
  rotation: 0,
707
706
  zIndex: 0,
708
707
  overflow: "visible",
709
- position: "relative",
708
+ position: "static",
710
709
  fit: "contain",
711
710
  objectFit: "contain",
712
711
  objectPosition: "50% 50%",
@@ -721,7 +720,7 @@ const ELEMENT_DEFAULTS = {
721
720
  rotation: 0,
722
721
  zIndex: 0,
723
722
  overflow: "visible",
724
- position: "relative",
723
+ position: "static",
725
724
  boxSizing: "border-box",
726
725
  backgroundTransparency: 100,
727
726
  borderWidth: 0,
@@ -1275,6 +1274,17 @@ const VIEW_STYLE_KEYS = [
1275
1274
  "gridAutoRows",
1276
1275
  "gridAutoFlow"
1277
1276
  ];
1277
+ const SLIDE_STYLE_KEYS$1 = [
1278
+ "background",
1279
+ "backgroundImage",
1280
+ "backgroundColor",
1281
+ "backgroundTransparency",
1282
+ "backgroundPosition",
1283
+ "backgroundSize",
1284
+ "backgroundRepeat",
1285
+ "backgroundClip",
1286
+ "backgroundOrigin"
1287
+ ];
1278
1288
  const TEXT_STYLE_KEYS = [
1279
1289
  ...VIEW_STYLE_KEYS,
1280
1290
  "fontFamily",
@@ -1544,11 +1554,45 @@ function applyProperties(style, source, properties) {
1544
1554
  };
1545
1555
  });
1546
1556
  }
1547
- function resolvedStyleFor$1(node, entity, registry, theme, context, diagnostics) {
1557
+ const INHERITED_STYLE_KEYS = new Set([
1558
+ "charSpacing",
1559
+ "color",
1560
+ "direction",
1561
+ "fontFamily",
1562
+ "fontSize",
1563
+ "fontStyle",
1564
+ "fontWeight",
1565
+ "italic",
1566
+ "letterSpacing",
1567
+ "lineHeight",
1568
+ "overflowWrap",
1569
+ "strike",
1570
+ "textAlign",
1571
+ "textTransform",
1572
+ "underline",
1573
+ "whiteSpace",
1574
+ "wordBreak",
1575
+ "writingMode"
1576
+ ]);
1577
+ function applyInheritedProperties(parentId, parent, properties) {
1578
+ if (parentId === void 0 || parent === void 0) return;
1579
+ for (const key of INHERITED_STYLE_KEYS) {
1580
+ const property = parent.properties[key];
1581
+ if (property?.value !== void 0) properties[key] = {
1582
+ value: property.value,
1583
+ source: {
1584
+ layer: "inherited",
1585
+ parentId
1586
+ }
1587
+ };
1588
+ }
1589
+ }
1590
+ function resolvedStyleFor$1(node, entity, registry, theme, context, inherited, diagnostics) {
1548
1591
  const properties = {};
1549
1592
  const appliedClasses = [];
1550
1593
  const defaults = elementDefaultsFor(node);
1551
1594
  if (defaults) applyProperties(defaults, { layer: "default" }, properties);
1595
+ applyInheritedProperties(inherited.parentId, inherited.style, properties);
1552
1596
  const themeDefaults = node.authoredTag && theme ? themeInput(theme).defaults : void 0;
1553
1597
  const themeDefault = node.authoredTag ? themeDefaults?.[node.authoredTag] : void 0;
1554
1598
  if (node.authoredTag && themeDefault) applyProperties(themeDefault, {
@@ -1607,9 +1651,10 @@ function resolveStyles(graph, roots) {
1607
1651
  const stylesheets = classesBySource(roots);
1608
1652
  const themes = themesBySource(roots);
1609
1653
  const registries = /* @__PURE__ */ new Map();
1654
+ const parentById = parentMapFor$1(graph);
1610
1655
  const selectorContext = {
1611
1656
  graph,
1612
- parentById: parentMapFor$1(graph),
1657
+ parentById,
1613
1658
  classNamesByNodeId: classNamesByNodeIdFor(graph)
1614
1659
  };
1615
1660
  const resolvedStyles = /* @__PURE__ */ new Map();
@@ -1619,8 +1664,10 @@ function resolveStyles(graph, roots) {
1619
1664
  themes.forEach((theme, sourceKey) => {
1620
1665
  diagnostics.push(...sourceThemeDiagnostics(sourceKey, theme));
1621
1666
  });
1622
- graph.nodes.forEach((node) => {
1667
+ const resolveNode = (node) => {
1623
1668
  if (!isStyleCapableNode(node)) return;
1669
+ const existing = resolvedStyles.get(node.id);
1670
+ if (existing) return existing;
1624
1671
  const sourceKey = sourceKeyFor$2(node.origin.source);
1625
1672
  const entity = node.styleRef ? graph.styles.get(node.styleRef) : void 0;
1626
1673
  let registry = registries.get(sourceKey);
@@ -1628,7 +1675,18 @@ function resolveStyles(graph, roots) {
1628
1675
  registry = registerStylesheets(sourceKey, stylesheets.get(sourceKey), diagnostics);
1629
1676
  registries.set(sourceKey, registry);
1630
1677
  }
1631
- resolvedStyles.set(node.id, resolvedStyleFor$1(node, entity, registry, themes.get(sourceKey), selectorContext, diagnostics));
1678
+ const parentId = parentById.get(node.id);
1679
+ const parent = parentId ? graph.nodes.get(parentId) : void 0;
1680
+ const inherited = parent ? resolveNode(parent) : void 0;
1681
+ const resolved = resolvedStyleFor$1(node, entity, registry, themes.get(sourceKey), selectorContext, {
1682
+ parentId,
1683
+ style: inherited
1684
+ }, diagnostics);
1685
+ resolvedStyles.set(node.id, resolved);
1686
+ return resolved;
1687
+ };
1688
+ graph.nodes.forEach((node) => {
1689
+ resolveNode(node);
1632
1690
  });
1633
1691
  return {
1634
1692
  resolvedStyles,
@@ -1960,6 +2018,9 @@ function semanticRoleForTag(tag) {
1960
2018
  function isRecord(value) {
1961
2019
  return typeof value === "object" && value !== null && !Array.isArray(value);
1962
2020
  }
2021
+ function hasOwnProp(props, key) {
2022
+ return Object.prototype.hasOwnProperty.call(props, key);
2023
+ }
1963
2024
  function keySegment(key, index) {
1964
2025
  return key === void 0 ? `index:${index}` : `key:${String(key)}`;
1965
2026
  }
@@ -1984,6 +2045,51 @@ function isShapeElement(node) {
1984
2045
  function templateAreaValueFor(node) {
1985
2046
  return "area" in node.props ? node.props.area : void 0;
1986
2047
  }
2048
+ function supportedPropNamesFor(node) {
2049
+ if (node.source.kind === "slide") return new Set([
2050
+ "name",
2051
+ "template",
2052
+ "className",
2053
+ "style"
2054
+ ]);
2055
+ switch (node.source.tag) {
2056
+ case "span": return new Set(["className", "style"]);
2057
+ case "img": return new Set([
2058
+ "className",
2059
+ "style",
2060
+ "area",
2061
+ "src",
2062
+ "data"
2063
+ ]);
2064
+ case "shape": return new Set([
2065
+ "className",
2066
+ "style",
2067
+ "area",
2068
+ "shape"
2069
+ ]);
2070
+ default: return new Set([
2071
+ "className",
2072
+ "style",
2073
+ "area"
2074
+ ]);
2075
+ }
2076
+ }
2077
+ function supportedStyleNamesFor(node) {
2078
+ if (node.source.kind === "slide") return new Set(SLIDE_STYLE_KEYS$1);
2079
+ switch (node.source.tag) {
2080
+ case "span": return new Set(TEXT_RUN_STYLE_KEYS);
2081
+ case "img": return new Set(IMAGE_STYLE_KEYS);
2082
+ case "shape": return new Set(SHAPE_STYLE_KEYS);
2083
+ case "p":
2084
+ case "h1":
2085
+ case "h2":
2086
+ case "h3":
2087
+ case "h4":
2088
+ case "h5":
2089
+ case "h6": return new Set(TEXT_STYLE_KEYS);
2090
+ default: return new Set(VIEW_STYLE_KEYS);
2091
+ }
2092
+ }
1987
2093
  function sourceFor(context) {
1988
2094
  return context.activeSlot?.source ?? context.source;
1989
2095
  }
@@ -2035,22 +2141,12 @@ function classRefsFor(value) {
2035
2141
  index
2036
2142
  }));
2037
2143
  }
2038
- function directStyleProps(props) {
2039
- const directStyle = Object.fromEntries(Object.entries(props).filter(([key]) => key !== "children" && key !== "className" && key !== "data" && key !== "area" && key !== "name" && key !== "shape" && key !== "src" && key !== "style" && key !== "template"));
2040
- return Object.keys(directStyle).length === 0 ? void 0 : directStyle;
2041
- }
2042
2144
  function sourceKeyFor(source) {
2043
2145
  return !source || source.kind === "root" ? "root" : source.sourceIdentity;
2044
2146
  }
2045
2147
  function mergedAuthoredStyle(props) {
2046
- const directStyle = directStyleProps(props);
2047
2148
  const inlineStyle = props.style;
2048
- if (directStyle === void 0) return isRecord(inlineStyle) ? Object.fromEntries(Object.entries(inlineStyle)) : void 0;
2049
- if (inlineStyle !== void 0 && (typeof inlineStyle !== "object" || inlineStyle === null || Array.isArray(inlineStyle))) return;
2050
- return {
2051
- ...directStyle,
2052
- ...isRecord(inlineStyle) ? inlineStyle : void 0
2053
- };
2149
+ return isRecord(inlineStyle) ? Object.fromEntries(Object.entries(inlineStyle)) : void 0;
2054
2150
  }
2055
2151
  function styleRefFor(state, idMaterial, target, props) {
2056
2152
  const style = mergedAuthoredStyle(props);
@@ -2083,7 +2179,115 @@ function invalidStructure(path, title, message, help) {
2083
2179
  ...help ? { help } : {}
2084
2180
  });
2085
2181
  }
2182
+ function authoringPropDiagnostic(input) {
2183
+ return diagnostic({
2184
+ severity: "error",
2185
+ code: input.code,
2186
+ title: input.title,
2187
+ message: input.message,
2188
+ labels: [{
2189
+ path: input.path,
2190
+ message: input.message
2191
+ }],
2192
+ ...input.help ? { help: input.help } : {}
2193
+ });
2194
+ }
2195
+ function unsupportedStylePropDiagnostic(input) {
2196
+ return diagnostic({
2197
+ severity: "warning",
2198
+ code: "W_COMPILE_UNSUPPORTED_STYLE_PROP",
2199
+ title: "unsupported style property",
2200
+ message: `Style property "${input.property}" is not supported by the deckjsx CSS-like style subset for ${input.tag}.`,
2201
+ labels: [{
2202
+ path: input.path,
2203
+ message: `${input.property} is outside the supported deckjsx style property subset.`
2204
+ }],
2205
+ help: ["Use a supported deckjsx style key, or keep this value in your own data layer until deckjsx adds that CSS property."]
2206
+ });
2207
+ }
2208
+ function validateAuthoringProps(state, node, path) {
2209
+ const supported = supportedPropNamesFor(node);
2210
+ const propPath = node.source.kind === "slide" ? `${path}.options` : `${path}.props`;
2211
+ for (const key of Object.keys(node.props)) if (!supported.has(key)) addDiagnostic(state, authoringPropDiagnostic({
2212
+ code: "E_COMPILE_UNSUPPORTED_AUTHORING_PROP",
2213
+ title: `unsupported ${node.source.kind === "slide" ? "slide declaration option" : "authoring prop"}`,
2214
+ path: `${propPath}.${key}`,
2215
+ message: `${key} is not supported in the current deckjsx authoring interface.`
2216
+ }));
2217
+ if (hasOwnProp(node.props, "style")) {
2218
+ const style = node.props.style;
2219
+ if (style !== void 0 && !isRecord(style)) addDiagnostic(state, authoringPropDiagnostic({
2220
+ code: "E_COMPILE_INVALID_STYLE_PROP",
2221
+ title: "style prop is invalid",
2222
+ path: `${propPath}.style`,
2223
+ message: "The style prop must be an object when it is provided."
2224
+ }));
2225
+ if (isRecord(style)) {
2226
+ const supportedStyleNames = supportedStyleNamesFor(node);
2227
+ const tag = sourceName(node);
2228
+ Object.keys(style).forEach((key) => {
2229
+ if (supportedStyleNames.has(key)) return;
2230
+ addDiagnostic(state, unsupportedStylePropDiagnostic({
2231
+ path: `${propPath}.style.${key}`,
2232
+ property: key,
2233
+ tag
2234
+ }));
2235
+ });
2236
+ }
2237
+ }
2238
+ if (isShapeElement(node) && node.props.shape !== void 0) {
2239
+ if (node.props.shape !== "rect" && node.props.shape !== "ellipse" && node.props.shape !== "line") addDiagnostic(state, authoringPropDiagnostic({
2240
+ code: "E_COMPILE_INVALID_SHAPE_PROP",
2241
+ title: "shape prop is invalid",
2242
+ path: `${propPath}.shape`,
2243
+ message: "The shape prop must be rect, ellipse, or line."
2244
+ }));
2245
+ }
2246
+ if (isSlideElement(node)) {
2247
+ if (node.props.name !== void 0 && typeof node.props.name !== "string") addDiagnostic(state, authoringPropDiagnostic({
2248
+ code: "E_COMPILE_INVALID_SLIDE_NAME_OPTION",
2249
+ title: "slide name option is invalid",
2250
+ path: `${propPath}.name`,
2251
+ message: "The slide declaration name option must be a string when it is provided."
2252
+ }));
2253
+ if (node.props.template !== void 0 && typeof node.props.template !== "string") addDiagnostic(state, authoringPropDiagnostic({
2254
+ code: "E_COMPILE_INVALID_SLIDE_TEMPLATE_OPTION",
2255
+ title: "slide template option is invalid",
2256
+ path: `${propPath}.template`,
2257
+ message: "The slide declaration template option must be a template name string."
2258
+ }));
2259
+ }
2260
+ }
2086
2261
  function assetForImage(state, idMaterial, props, path) {
2262
+ const hasSrc = props.src !== void 0;
2263
+ const hasData = props.data !== void 0;
2264
+ if (hasSrc && typeof props.src !== "string") {
2265
+ addDiagnostic(state, authoringPropDiagnostic({
2266
+ code: "E_COMPILE_INVALID_IMAGE_SOURCE_PROP",
2267
+ title: "image src prop is invalid",
2268
+ path: `${path}.props.src`,
2269
+ message: "The img src prop must be a string when it is provided."
2270
+ }));
2271
+ return;
2272
+ }
2273
+ if (hasData && typeof props.data !== "string") {
2274
+ addDiagnostic(state, authoringPropDiagnostic({
2275
+ code: "E_COMPILE_INVALID_IMAGE_SOURCE_PROP",
2276
+ title: "image data prop is invalid",
2277
+ path: `${path}.props.data`,
2278
+ message: "The img data prop must be a string when it is provided."
2279
+ }));
2280
+ return;
2281
+ }
2282
+ if (typeof props.src === "string" && typeof props.data === "string") {
2283
+ addDiagnostic(state, authoringPropDiagnostic({
2284
+ code: "E_COMPILE_AMBIGUOUS_IMAGE_SOURCE_PROP",
2285
+ title: "image source props are ambiguous",
2286
+ path: `${path}.props`,
2287
+ message: "Use either img src or img data, not both."
2288
+ }));
2289
+ return;
2290
+ }
2087
2291
  if (typeof props.src !== "string" && typeof props.data !== "string") {
2088
2292
  addDiagnostic(state, invalidStructure(path, "image source is missing", "Image nodes require either src or data.", ["Add a src path or data URL to the image."]));
2089
2293
  return;
@@ -2350,6 +2554,7 @@ function buildNode(state, node, context, index) {
2350
2554
  const material = [...nodeContext.parentMaterial, segment];
2351
2555
  const id = graphNodeId(material);
2352
2556
  const path = `${nodeContext.path} > ${sourceName(node)}[${keySegment(node.key, index)}]`;
2557
+ validateAuthoringProps(state, node, path);
2353
2558
  if (kind === "textRun") {
2354
2559
  if (!context.inline) {
2355
2560
  addDiagnostic(state, invalidStructure(path, "span cannot appear here", "span must be inside a text-like element.", ["Wrap the span in <p>...</p> or move it inside an existing text element."]));
@@ -3076,6 +3281,169 @@ function summarizePptxPackage(projection, options = {}) {
3076
3281
  };
3077
3282
  }
3078
3283
  //#endregion
3284
+ //#region src/layout/input.ts
3285
+ function pushDefined(values, value) {
3286
+ if (value !== void 0) values.push(value);
3287
+ }
3288
+ function resolvedPropsFor(node, resolvedStyles) {
3289
+ const resolved = resolvedStyles.get(node.id);
3290
+ if (!resolved) return {};
3291
+ return Object.fromEntries(Object.entries(resolved.properties).filter(([, property]) => property.source.layer !== "default" && property.source.layer !== "inherited").map(([key, property]) => [key, property.value]));
3292
+ }
3293
+ function sourceKeyForOrigin$2(source) {
3294
+ return !source || source.kind === "root" ? "root" : source.sourceIdentity;
3295
+ }
3296
+ function propsWithTemplateAreaFrame(resolvedStyles, node, templates) {
3297
+ const props = resolvedPropsFor(node, resolvedStyles);
3298
+ const ref = node.templateAreaRef;
3299
+ if (!ref) return props;
3300
+ const frame = templates?.[ref.template]?.areas?.[ref.area]?.frame;
3301
+ if (!frame) return props;
3302
+ const resolved = resolvedStyles.get(node.id);
3303
+ const frameProps = {};
3304
+ if (resolved?.properties.x?.source.layer !== "style") frameProps.x = frame.x;
3305
+ if (resolved?.properties.y?.source.layer !== "style") frameProps.y = frame.y;
3306
+ if (resolved?.properties.width?.source.layer !== "style") frameProps.width = frame.width;
3307
+ if (resolved?.properties.height?.source.layer !== "style") frameProps.height = frame.height;
3308
+ return {
3309
+ ...props,
3310
+ ...frameProps
3311
+ };
3312
+ }
3313
+ function templateAreaKindFor$1(node, templates) {
3314
+ const ref = node.templateAreaRef;
3315
+ if (!ref) return;
3316
+ return templates?.[ref.template]?.areas?.[ref.area]?.kind ?? "generic";
3317
+ }
3318
+ function collectTextOrigin(graph, node) {
3319
+ const graphNodeIds = [node.id];
3320
+ const styleEntityIds = [];
3321
+ pushDefined(styleEntityIds, node.styleRef);
3322
+ node.inlineChildren.forEach((childId) => {
3323
+ const child = graph.nodes.get(childId);
3324
+ if (!child) return;
3325
+ graphNodeIds.push(child.id);
3326
+ pushDefined(styleEntityIds, child.styleRef);
3327
+ if (child.kind === "text") {
3328
+ const nested = collectTextOrigin(graph, child);
3329
+ graphNodeIds.push(...nested.graphNodeIds ?? []);
3330
+ styleEntityIds.push(...nested.styleEntityIds ?? []);
3331
+ }
3332
+ });
3333
+ return {
3334
+ graphNodeIds: [...new Set(graphNodeIds)],
3335
+ ...styleEntityIds.length > 0 ? { styleEntityIds: [...new Set(styleEntityIds)] } : {}
3336
+ };
3337
+ }
3338
+ function layoutOriginFor(graph, node, templates) {
3339
+ const templateAreaKind = templateAreaKindFor$1(node, templates);
3340
+ if (node.kind === "text") return {
3341
+ ...collectTextOrigin(graph, node),
3342
+ ...node.origin.source ? { source: node.origin.source } : {},
3343
+ ...node.templateAreaRef ? { templateAreaRef: node.templateAreaRef } : {},
3344
+ ...templateAreaKind ? { templateAreaKind } : {}
3345
+ };
3346
+ return {
3347
+ graphNodeIds: [node.id],
3348
+ ...node.styleRef ? { styleEntityIds: [node.styleRef] } : {},
3349
+ ...node.kind === "image" && node.assetRef ? { assetEntityIds: [node.assetRef] } : {},
3350
+ ...node.origin.source ? { source: node.origin.source } : {},
3351
+ ...node.templateAreaRef ? { templateAreaRef: node.templateAreaRef } : {},
3352
+ ...templateAreaKind ? { templateAreaKind } : {}
3353
+ };
3354
+ }
3355
+ function textChildrenFromGraph(graph, resolvedStyles, childIds, templates) {
3356
+ return childIds.flatMap((childId) => {
3357
+ const child = graph.nodes.get(childId);
3358
+ if (!child) return [];
3359
+ if (child.kind === "textRun") return [{
3360
+ kind: "text",
3361
+ props: resolvedPropsFor(child, resolvedStyles),
3362
+ children: [child.text],
3363
+ origin: layoutOriginFor(graph, child, templates)
3364
+ }];
3365
+ if (child.kind === "text") return textChildrenFromGraph(graph, resolvedStyles, child.inlineChildren, templates);
3366
+ return [];
3367
+ });
3368
+ }
3369
+ function contentChildrenFromGraph(graph, resolvedStyles, childIds, assetProbeArtifacts, templates) {
3370
+ return childIds.flatMap((childId) => {
3371
+ const child = graph.nodes.get(childId);
3372
+ if (!child) return [];
3373
+ const node = layoutInputNodeFromGraph(graph, resolvedStyles, child, assetProbeArtifacts, templates);
3374
+ return node && node.kind !== "slide" ? [node] : [];
3375
+ });
3376
+ }
3377
+ function layoutInputNodeFromGraph(graph, resolvedStyles, node, assetProbeArtifacts, templates) {
3378
+ switch (node.kind) {
3379
+ case "slide": {
3380
+ const props = propsWithTemplateAreaFrame(resolvedStyles, node, templates);
3381
+ const slideTemplates = graph.templates.get(sourceKeyForOrigin$2(node.origin.source));
3382
+ return {
3383
+ kind: "slide",
3384
+ props: {
3385
+ ...props,
3386
+ name: node.name
3387
+ },
3388
+ children: contentChildrenFromGraph(graph, resolvedStyles, node.children, assetProbeArtifacts, slideTemplates),
3389
+ origin: layoutOriginFor(graph, node, slideTemplates)
3390
+ };
3391
+ }
3392
+ case "container": return {
3393
+ kind: "view",
3394
+ props: propsWithTemplateAreaFrame(resolvedStyles, node, templates),
3395
+ children: contentChildrenFromGraph(graph, resolvedStyles, node.children, assetProbeArtifacts, templates),
3396
+ origin: layoutOriginFor(graph, node, templates)
3397
+ };
3398
+ case "text": return {
3399
+ kind: "text",
3400
+ props: propsWithTemplateAreaFrame(resolvedStyles, node, templates),
3401
+ children: textChildrenFromGraph(graph, resolvedStyles, node.inlineChildren, templates),
3402
+ origin: layoutOriginFor(graph, node, templates)
3403
+ };
3404
+ case "image": {
3405
+ const props = propsWithTemplateAreaFrame(resolvedStyles, node, templates);
3406
+ const asset = node.assetRef ? graph.assets.get(node.assetRef) : void 0;
3407
+ if (!asset) return;
3408
+ return {
3409
+ kind: "image",
3410
+ props: {
3411
+ ...props,
3412
+ ...imageSourceProps(asset)
3413
+ },
3414
+ ...node.assetRef ? { assetProbe: assetProbeArtifacts?.get(node.assetRef)?.probe } : {},
3415
+ origin: layoutOriginFor(graph, node, templates)
3416
+ };
3417
+ }
3418
+ case "shape": return {
3419
+ kind: "shape",
3420
+ props: {
3421
+ ...propsWithTemplateAreaFrame(resolvedStyles, node, templates),
3422
+ shape: node.shape
3423
+ },
3424
+ origin: layoutOriginFor(graph, node, templates)
3425
+ };
3426
+ case "document":
3427
+ case "textRun": return;
3428
+ }
3429
+ }
3430
+ function imageSourceProps(asset) {
3431
+ if (asset.source.kind === "data") return { data: asset.source.data };
3432
+ return { src: asset.source.kind === "path" ? asset.source.path : asset.source.url };
3433
+ }
3434
+ function buildLayoutInputSnapshot(input) {
3435
+ const document = input.graph.nodes.get(input.graph.documentId);
3436
+ const slideNodes = document?.kind === "document" ? document.children.map((id) => input.graph.nodes.get(id)).filter((node) => node?.kind === "slide") : [];
3437
+ return {
3438
+ snapshot: {
3439
+ ...input.meta ? { meta: input.meta } : {},
3440
+ ...input.deckSize ? { size: input.deckSize } : {},
3441
+ slides: slideNodes.map((node) => layoutInputNodeFromGraph(input.graph, input.resolvedStyles, node, input.assetProbeArtifacts)).filter((node) => node?.kind === "slide")
3442
+ },
3443
+ diagnostics: input.diagnostics ?? createDiagnostics()
3444
+ };
3445
+ }
3446
+ //#endregion
3079
3447
  //#region src/layout/frame.ts
3080
3448
  function intersectClipRect(frame, clipRect) {
3081
3449
  if (!clipRect) return frame;
@@ -3645,16 +4013,83 @@ function resolveGridSelfAlignment(value) {
3645
4013
  return value;
3646
4014
  }
3647
4015
  //#endregion
4016
+ //#region src/style/defaulting.ts
4017
+ function authoredLengthOrUndefined(value) {
4018
+ if (typeof value === "string" && (value.trim().toLowerCase() === "auto" || isCssWideKeyword(value))) return;
4019
+ return value;
4020
+ }
4021
+ function hasAuthoredLength(value) {
4022
+ return authoredLengthOrUndefined(value) !== void 0;
4023
+ }
4024
+ function defaultingTokens(value) {
4025
+ if (typeof value === "string") return value.trim().split(/\s+/).filter(Boolean);
4026
+ if (Array.isArray(value)) return value;
4027
+ return value === void 0 || value === null ? [] : [value];
4028
+ }
4029
+ function hasAutoToken(value) {
4030
+ return defaultingTokens(value).some((token) => typeof token === "string" && token.trim().toLowerCase() === "auto");
4031
+ }
4032
+ function hasCssWideKeywordToken(value) {
4033
+ return defaultingTokens(value).some((token) => isCssWideKeyword(token));
4034
+ }
4035
+ //#endregion
3648
4036
  //#region src/layout/spacing.ts
3649
- function parseSpacing(value, context) {
4037
+ function splitSpacingTokens(value) {
4038
+ const tokens = [];
4039
+ let current = "";
4040
+ let depth = 0;
4041
+ for (const char of value) {
4042
+ if (char === "(") {
4043
+ depth += 1;
4044
+ current += char;
4045
+ continue;
4046
+ }
4047
+ if (char === ")") {
4048
+ depth = Math.max(depth - 1, 0);
4049
+ current += char;
4050
+ continue;
4051
+ }
4052
+ if (/\s/.test(char) && depth === 0) {
4053
+ if (current.trim()) tokens.push(current.trim());
4054
+ current = "";
4055
+ continue;
4056
+ }
4057
+ current += char;
4058
+ }
4059
+ if (current.trim()) tokens.push(current.trim());
4060
+ return tokens;
4061
+ }
4062
+ function expandSpacingTokens(value) {
4063
+ const tokens = splitSpacingTokens(value);
4064
+ if (tokens.length <= 1) return;
4065
+ if (tokens.length > 4) throw new Error(`Unsupported spacing shorthand: ${value}`);
4066
+ const [top, right = top, bottom = top, left = right] = tokens;
4067
+ if (top === void 0) return;
4068
+ return [
4069
+ top,
4070
+ right,
4071
+ bottom,
4072
+ left
4073
+ ];
4074
+ }
4075
+ function parseSpacing(value, context, percentageBaseEmu = 0) {
3650
4076
  if (value === void 0) return [
3651
4077
  0,
3652
4078
  0,
3653
4079
  0,
3654
4080
  0
3655
4081
  ];
4082
+ if (typeof value === "string") {
4083
+ const shorthand = expandSpacingTokens(value);
4084
+ if (shorthand) return [
4085
+ parseLength(shorthand[0], percentageBaseEmu, 0, context),
4086
+ parseLength(shorthand[1], percentageBaseEmu, 0, context),
4087
+ parseLength(shorthand[2], percentageBaseEmu, 0, context),
4088
+ parseLength(shorthand[3], percentageBaseEmu, 0, context)
4089
+ ];
4090
+ }
3656
4091
  if (typeof value === "number" || typeof value === "string") {
3657
- const scalar = parseLength(value, 0, 0, context);
4092
+ const scalar = parseLength(value, percentageBaseEmu, 0, context);
3658
4093
  return [
3659
4094
  scalar,
3660
4095
  scalar,
@@ -3663,10 +4098,47 @@ function parseSpacing(value, context) {
3663
4098
  ];
3664
4099
  }
3665
4100
  return [
3666
- parseLength(value[0], 0, 0, context),
3667
- parseLength(value[1], 0, 0, context),
3668
- parseLength(value[2], 0, 0, context),
3669
- parseLength(value[3], 0, 0, context)
4101
+ parseLength(value[0], percentageBaseEmu, 0, context),
4102
+ parseLength(value[1], percentageBaseEmu, 0, context),
4103
+ parseLength(value[2], percentageBaseEmu, 0, context),
4104
+ parseLength(value[3], percentageBaseEmu, 0, context)
4105
+ ];
4106
+ }
4107
+ function parseLengthOrAuto(value, percentageBaseEmu, fallbackEmu, context) {
4108
+ const authoredValue = authoredLengthOrUndefined(value);
4109
+ if (authoredValue === void 0) return fallbackEmu;
4110
+ return parseLength(authoredValue, percentageBaseEmu, fallbackEmu, context);
4111
+ }
4112
+ function parseSpacingAllowAuto(value, context, percentageBaseEmu = 0, autoFallbackEmu = 0) {
4113
+ if (value === void 0) return [
4114
+ 0,
4115
+ 0,
4116
+ 0,
4117
+ 0
4118
+ ];
4119
+ if (typeof value === "string") {
4120
+ const shorthand = expandSpacingTokens(value);
4121
+ if (shorthand) return [
4122
+ parseLengthOrAuto(shorthand[0], percentageBaseEmu, autoFallbackEmu, context),
4123
+ parseLengthOrAuto(shorthand[1], percentageBaseEmu, autoFallbackEmu, context),
4124
+ parseLengthOrAuto(shorthand[2], percentageBaseEmu, autoFallbackEmu, context),
4125
+ parseLengthOrAuto(shorthand[3], percentageBaseEmu, autoFallbackEmu, context)
4126
+ ];
4127
+ }
4128
+ if (typeof value === "number" || typeof value === "string") {
4129
+ const scalar = parseLengthOrAuto(value, percentageBaseEmu, autoFallbackEmu, context);
4130
+ return [
4131
+ scalar,
4132
+ scalar,
4133
+ scalar,
4134
+ scalar
4135
+ ];
4136
+ }
4137
+ return [
4138
+ parseLengthOrAuto(value[0], percentageBaseEmu, autoFallbackEmu, context),
4139
+ parseLengthOrAuto(value[1], percentageBaseEmu, autoFallbackEmu, context),
4140
+ parseLengthOrAuto(value[2], percentageBaseEmu, autoFallbackEmu, context),
4141
+ parseLengthOrAuto(value[3], percentageBaseEmu, autoFallbackEmu, context)
3670
4142
  ];
3671
4143
  }
3672
4144
  function expandRawSpacing(value) {
@@ -3676,12 +4148,21 @@ function expandRawSpacing(value) {
3676
4148
  void 0,
3677
4149
  void 0
3678
4150
  ];
3679
- if (typeof value === "number" || typeof value === "string") return [
3680
- value,
3681
- value,
3682
- value,
3683
- value
3684
- ];
4151
+ if (typeof value === "number" || typeof value === "string") {
4152
+ const shorthand = typeof value === "string" ? expandSpacingTokens(value) : void 0;
4153
+ if (shorthand) return [
4154
+ shorthand[0],
4155
+ shorthand[1],
4156
+ shorthand[2],
4157
+ shorthand[3]
4158
+ ];
4159
+ return [
4160
+ value,
4161
+ value,
4162
+ value,
4163
+ value
4164
+ ];
4165
+ }
3685
4166
  return [
3686
4167
  value[0],
3687
4168
  value[1],
@@ -3709,9 +4190,9 @@ function resolveInset(value, top, right, bottom, left) {
3709
4190
  left: left ?? baseLeft
3710
4191
  };
3711
4192
  }
3712
- function parseSpacingInPoints(value, context) {
4193
+ function parseSpacingInPoints(value, context, percentageBaseEmu = 0) {
3713
4194
  if (value === void 0) return;
3714
- const spacing = parseSpacing(value, context);
4195
+ const spacing = parseSpacing(value, context, percentageBaseEmu);
3715
4196
  return [
3716
4197
  spacing[0] / EMU_PER_INCH * 72,
3717
4198
  spacing[1] / EMU_PER_INCH * 72,
@@ -5148,7 +5629,7 @@ function parseStrokeDasharray(value, context) {
5148
5629
  if (rawTokens.length === 0) return;
5149
5630
  const lengths = rawTokens.map((token) => {
5150
5631
  if (/^-?(?:\d+|\d*\.\d+)$/.test(token)) return Number.parseFloat(token);
5151
- if (/^-?(?:\d+|\d*\.\d+)(?:pt|in|px|em|rem|vh|vw|ch)$/i.test(token)) return parsePointToken(token, 0, context);
5632
+ 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);
5152
5633
  throw new Error(`Unsupported strokeDasharray token: ${token}`);
5153
5634
  });
5154
5635
  if (lengths.some((length) => !Number.isFinite(length) || length < 0)) throw new Error(`Unsupported strokeDasharray value: ${value}`);
@@ -5236,10 +5717,15 @@ function parseTextDecoration(value) {
5236
5717
  };
5237
5718
  }
5238
5719
  function resolveLineHeight(lineHeight, context) {
5239
- if (lineHeight === void 0 || lineHeight === "normal") return {};
5720
+ if (lineHeight === void 0 || lineHeight === "normal" || isCssWideKeyword(lineHeight)) return {};
5240
5721
  if (typeof lineHeight === "number") return { lineSpacingMultiple: lineHeight };
5241
5722
  return { lineSpacing: parsePointValue(lineHeight, 0, context) };
5242
5723
  }
5724
+ function resolveCharacterSpacing(charSpacing, context) {
5725
+ if (charSpacing === void 0 || isCssWideKeyword(charSpacing)) return;
5726
+ if (charSpacing === "normal") return 0;
5727
+ return parsePointValue(charSpacing, 0, context);
5728
+ }
5243
5729
  function resolveTextWrap(wrap, whiteSpace, wordBreak, overflowWrap) {
5244
5730
  if (wrap !== void 0) return wrap;
5245
5731
  if (wordBreak === "break-all" || wordBreak === "break-word") return true;
@@ -5361,16 +5847,17 @@ function extractText(children, textTransform) {
5361
5847
  parts.push(String(child));
5362
5848
  continue;
5363
5849
  }
5364
- if (isAuthorNode(child)) throw new Error("Text nodes can only contain string or number children.");
5850
+ if (typeof child === "object") throw new Error("Text nodes can only contain string or number children.");
5365
5851
  }
5366
5852
  return applyTextTransform$1(parts.join(""), textTransform);
5367
5853
  }
5368
5854
  //#endregion
5369
- //#region src/compiler/normalization.ts
5370
- function resolveFlexDirection(direction, flexDirection) {
5855
+ //#region src/layout/normalization.ts
5856
+ function resolveFlexDirection(direction, flexDirection, display) {
5371
5857
  if (direction) return direction;
5372
5858
  if (flexDirection === "row") return "horizontal";
5373
5859
  if (flexDirection === "column") return "vertical";
5860
+ if (display === "flex") return "horizontal";
5374
5861
  }
5375
5862
  function resolveLayout(layout, display, position) {
5376
5863
  if (layout) return layout;
@@ -5384,6 +5871,10 @@ function resolveGap(gap, rowGap, columnGap, direction) {
5384
5871
  if (direction === "vertical") return rowGap ?? columnGap;
5385
5872
  return rowGap ?? columnGap;
5386
5873
  }
5874
+ function normalizeImageFit(value) {
5875
+ if (value === "fill") return "stretch";
5876
+ return value;
5877
+ }
5387
5878
  function isCssAlignSelf(value) {
5388
5879
  return value === "start" || value === "flex-start" || value === "center" || value === "end" || value === "flex-end" || value === "stretch" || value === "auto";
5389
5880
  }
@@ -5454,7 +5945,7 @@ function normalizeViewProps(props) {
5454
5945
  authored.gridAutoColumns = resolved.gridAutoColumns ?? gridContainerAuthoring.gridAutoColumns;
5455
5946
  authored.gridAutoRows = resolved.gridAutoRows ?? gridContainerAuthoring.gridAutoRows;
5456
5947
  authored.gridAutoFlow = resolved.gridAutoFlow ?? gridContainerAuthoring.gridAutoFlow;
5457
- const direction = resolveFlexDirection(authored.direction, authored.flexDirection);
5948
+ const direction = resolveFlexDirection(authored.direction, authored.flexDirection, authored.display);
5458
5949
  const inset = resolveInset(authored.inset, authored.top, authored.right, authored.bottom, authored.left);
5459
5950
  return {
5460
5951
  ...authored,
@@ -5513,7 +6004,7 @@ function normalizeTextProps(props) {
5513
6004
  italic: resolved.italic ?? (resolved.fontStyle === "italic" ? true : void 0),
5514
6005
  underline: resolved.underline ?? decoration.underline,
5515
6006
  strike: resolved.strike ?? decoration.strike,
5516
- charSpacing: resolved.charSpacing ?? resolved.letterSpacing,
6007
+ charSpacing: resolved.charSpacing ?? (resolved.letterSpacing === "normal" ? 0 : resolved.letterSpacing),
5517
6008
  backgroundColor: resolved.backgroundColor ?? background.backgroundColor,
5518
6009
  borderColor: resolved.borderColor ?? border.borderColor,
5519
6010
  borderWidth: resolved.borderWidth ?? border.borderWidth,
@@ -5551,7 +6042,7 @@ function normalizeImageProps(props, context) {
5551
6042
  right: inset?.right ?? resolved.right,
5552
6043
  bottom: inset?.bottom ?? resolved.bottom,
5553
6044
  left: inset?.left ?? resolved.left,
5554
- fit: resolved.fit ?? resolved.objectFit,
6045
+ fit: normalizeImageFit(resolved.fit ?? resolved.objectFit),
5555
6046
  objectPosition: resolved.objectPosition,
5556
6047
  crop: resolved.crop,
5557
6048
  rounding: resolved.rounding ?? (resolved.borderRadius !== void 0 ? parseLength(resolved.borderRadius, 0, 0, context) > 0 : void 0),
@@ -5574,7 +6065,8 @@ function normalizeShapeProps(props) {
5574
6065
  const { style, ...rest } = props;
5575
6066
  const resolved = {
5576
6067
  ...rest,
5577
- ...style
6068
+ ...style,
6069
+ shape: rest.shape ?? "rect"
5578
6070
  };
5579
6071
  const background = parseBackgroundShorthand(resolved.background);
5580
6072
  const border = parseBorderShorthand(resolved.border);
@@ -5944,7 +6436,8 @@ function matrixTranslatePxToEmu(value) {
5944
6436
  function parseAspectRatio(value) {
5945
6437
  if (value === void 0) return;
5946
6438
  if (typeof value === "number") return value > 0 ? value : void 0;
5947
- const normalized = value.replace(/\s+/g, "");
6439
+ const normalized = value.replace(/\s+/g, "").toLowerCase();
6440
+ if (normalized === "auto") return;
5948
6441
  if (!normalized.includes("/")) {
5949
6442
  const parsed = Number.parseFloat(normalized);
5950
6443
  return Number.isFinite(parsed) && parsed > 0 ? parsed : void 0;
@@ -5976,35 +6469,51 @@ function inflateSpecifiedBoxSize(valueEmu, boxSizing, padding, dimension) {
5976
6469
  if (boxSizing !== "content-box") return valueEmu;
5977
6470
  return valueEmu + (dimension === "width" ? padding[1] + padding[3] : padding[0] + padding[2]);
5978
6471
  }
6472
+ function nonAutoLength(value) {
6473
+ if (typeof value === "string" && (value.trim().toLowerCase() === "auto" || isCssWideKeyword(value))) return;
6474
+ return value;
6475
+ }
6476
+ function specifiedLength(value) {
6477
+ return nonAutoLength(value);
6478
+ }
5979
6479
  function frameFromProps(props, parent, placement, context) {
5980
6480
  const transform = parseTransformShorthandOrIgnore(props.transform);
5981
6481
  const resolvedInset = resolveInset(props.inset, props.top, props.right, props.bottom, props.left);
5982
- const resolvedX = props.x ?? resolvedInset?.left;
5983
- const resolvedY = props.y ?? resolvedInset?.top;
5984
- const resolvedRight = resolvedInset?.right;
5985
- const resolvedBottom = resolvedInset?.bottom;
6482
+ const isRelativePosition = props.position === "relative";
6483
+ const relativeLeft = nonAutoLength(props.x ?? resolvedInset?.left);
6484
+ const relativeTop = nonAutoLength(props.y ?? resolvedInset?.top);
6485
+ const relativeRight = nonAutoLength(resolvedInset?.right);
6486
+ const relativeBottom = nonAutoLength(resolvedInset?.bottom);
6487
+ const specifiedWidth = specifiedLength(props.width);
6488
+ const specifiedHeight = specifiedLength(props.height);
6489
+ const resolvedX = isRelativePosition ? void 0 : relativeLeft;
6490
+ const resolvedY = isRelativePosition ? void 0 : relativeTop;
6491
+ const resolvedRight = isRelativePosition ? void 0 : relativeRight;
6492
+ const resolvedBottom = isRelativePosition ? void 0 : relativeBottom;
5986
6493
  const aspectRatio = parseAspectRatio(props.aspectRatio);
5987
- const padding = parseSpacing(props.padding, context);
6494
+ const padding = parseSpacing(props.padding, context, parent.widthEmu);
5988
6495
  const boxSizing = props.boxSizing ?? "border-box";
5989
6496
  const minWidthEmu = parseLength(props.minWidth, parent.widthEmu, 0, context);
5990
6497
  const minHeightEmu = parseLength(props.minHeight, parent.heightEmu, 0, context);
5991
6498
  const maxWidthEmu = parseLength(props.maxWidth, parent.widthEmu, Number.POSITIVE_INFINITY, context);
5992
6499
  const maxHeightEmu = parseLength(props.maxHeight, parent.heightEmu, Number.POSITIVE_INFINITY, context);
5993
6500
  const clampSize = (value, min, max) => Math.max(min, Math.min(value, max));
5994
- 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);
5995
- 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);
6501
+ 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);
6502
+ 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);
5996
6503
  const aspectResolvedWidth = baseWidth === 0 && aspectRatio !== void 0 && baseHeight > 0 ? baseHeight * aspectRatio : baseWidth;
5997
6504
  const aspectResolvedHeight = baseHeight === 0 && aspectRatio !== void 0 && aspectResolvedWidth > 0 ? aspectResolvedWidth / aspectRatio : baseHeight;
5998
6505
  const clampedWidth = clampSize(aspectResolvedWidth, minWidthEmu, maxWidthEmu);
5999
6506
  const clampedHeight = clampSize(aspectResolvedHeight, minHeightEmu, maxHeightEmu);
6000
- const widthUsesSpecifiedBox = props.width !== void 0 || props.height !== void 0 && aspectRatio !== void 0 && baseWidth === 0;
6001
- const heightUsesSpecifiedBox = props.height !== void 0 || props.width !== void 0 && aspectRatio !== void 0 && baseHeight === 0;
6507
+ const widthUsesSpecifiedBox = specifiedWidth !== void 0 || specifiedHeight !== void 0 && aspectRatio !== void 0 && baseWidth === 0;
6508
+ const heightUsesSpecifiedBox = specifiedHeight !== void 0 || specifiedWidth !== void 0 && aspectRatio !== void 0 && baseHeight === 0;
6002
6509
  const resolvedWidth = placement?.widthEmu !== void 0 || !widthUsesSpecifiedBox ? clampedWidth : inflateSpecifiedBoxSize(clampedWidth, boxSizing, padding, "width");
6003
6510
  const resolvedHeight = placement?.heightEmu !== void 0 || !heightUsesSpecifiedBox ? clampedHeight : inflateSpecifiedBoxSize(clampedHeight, boxSizing, padding, "height");
6004
6511
  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;
6005
6512
  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;
6006
- let transformedX = placement?.xEmu ?? absoluteX;
6007
- let transformedY = placement?.yEmu ?? absoluteY;
6513
+ const relativeOffsetX = isRelativePosition && relativeLeft !== void 0 ? parseLength(relativeLeft, parent.widthEmu, 0, context) : isRelativePosition && relativeRight !== void 0 ? -parseLength(relativeRight, parent.widthEmu, 0, context) : 0;
6514
+ const relativeOffsetY = isRelativePosition && relativeTop !== void 0 ? parseLength(relativeTop, parent.heightEmu, 0, context) : isRelativePosition && relativeBottom !== void 0 ? -parseLength(relativeBottom, parent.heightEmu, 0, context) : 0;
6515
+ let transformedX = (placement?.xEmu ?? absoluteX) + relativeOffsetX;
6516
+ let transformedY = (placement?.yEmu ?? absoluteY) + relativeOffsetY;
6008
6517
  let transformedWidth = resolvedWidth;
6009
6518
  let transformedHeight = resolvedHeight;
6010
6519
  let transformRotation = 0;
@@ -6199,11 +6708,11 @@ function resolveCrossPlacement(alignment, availableCross, childCross, hasExplici
6199
6708
  sizeEmu: childCross
6200
6709
  };
6201
6710
  }
6202
- function resolveMainGap(direction, gap, rowGap, columnGap, context) {
6203
- return parseLength(direction === "horizontal" ? columnGap ?? gap ?? rowGap : rowGap ?? gap ?? columnGap, 0, 0, context);
6711
+ function resolveMainGap(direction, gap, rowGap, columnGap, context, percentageBaseEmu = 0) {
6712
+ return parseLength(direction === "horizontal" ? columnGap ?? gap ?? rowGap : rowGap ?? gap ?? columnGap, percentageBaseEmu, 0, context);
6204
6713
  }
6205
- function resolveCrossGap(direction, gap, rowGap, columnGap, context) {
6206
- return parseLength(direction === "horizontal" ? rowGap ?? gap ?? columnGap : columnGap ?? gap ?? rowGap, 0, 0, context);
6714
+ function resolveCrossGap(direction, gap, rowGap, columnGap, context, percentageBaseEmu = 0) {
6715
+ return parseLength(direction === "horizontal" ? rowGap ?? gap ?? columnGap : columnGap ?? gap ?? rowGap, percentageBaseEmu, 0, context);
6207
6716
  }
6208
6717
  function buildStackLines(entries, direction, parentFrame, availableMain, mainGapEmu, flexWrap, metrics, context) {
6209
6718
  if (entries.length === 0) return [];
@@ -6329,7 +6838,7 @@ function splitTopLevelCommaList(value) {
6329
6838
  }
6330
6839
  function tryParsePointToken(value) {
6331
6840
  if (value === "0") return 0;
6332
- if (!isDeckPointLengthString(value) || !/^-?(?:\d+|\d*\.\d+)(?:pt|in|px)$/i.test(value)) return;
6841
+ if (!isDeckPointLengthString(value)) return;
6333
6842
  return parsePointToken(value);
6334
6843
  }
6335
6844
  function parseShadowShorthand(value) {
@@ -6371,29 +6880,97 @@ function parseShadowShorthand(value) {
6371
6880
  angle: angle % 360
6372
6881
  };
6373
6882
  }
6883
+ function hasShadowSpreadRadius(value) {
6884
+ if (!value) return false;
6885
+ const trimmed = value.trim();
6886
+ if (!trimmed || trimmed.toLowerCase() === "none") return false;
6887
+ const layers = splitTopLevelCommaList(trimmed);
6888
+ if (layers.length !== 1) return false;
6889
+ const [layer] = layers;
6890
+ if (layer === void 0) return false;
6891
+ return splitCssValueTokens(layer).filter((token) => token.toLowerCase() !== "inset").filter((token) => {
6892
+ if (parseCssColor(token)) return false;
6893
+ return tryParsePointToken(token) !== void 0;
6894
+ }).length === 4;
6895
+ }
6374
6896
  //#endregion
6375
- //#region src/layout/resolve.ts
6376
- function errorReason$1(error) {
6897
+ //#region src/layout/unsupported.ts
6898
+ function errorReason$2(error) {
6377
6899
  return error instanceof Error ? error.message : String(error);
6378
6900
  }
6379
- function unsupportedSemantic$1(input) {
6901
+ function semanticValue(value) {
6902
+ if (typeof value === "string") return value;
6903
+ return JSON.stringify(value) ?? String(value);
6904
+ }
6905
+ function unsupportedSemantic(input) {
6380
6906
  if (input.value === void 0 || input.value === null || input.value === "") return;
6381
6907
  return {
6382
6908
  feature: input.feature,
6383
6909
  property: input.property,
6384
- value: typeof input.value === "string" ? input.value : JSON.stringify(input.value),
6385
- reason: errorReason$1(input.error),
6910
+ value: semanticValue(input.value),
6911
+ reason: errorReason$2(input.error),
6386
6912
  ...input.fallback ? { fallback: input.fallback } : {}
6387
6913
  };
6388
6914
  }
6915
+ function unsupportedCssWideKeywordSemantic(property, value) {
6916
+ return unsupportedSemantic({
6917
+ feature: "layout",
6918
+ property,
6919
+ value,
6920
+ 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."),
6921
+ fallback: {
6922
+ strategy: "preserveAuthoredValueOnly",
6923
+ preserves: ["authoredValue"],
6924
+ missing: ["cssWideKeywordCascade"]
6925
+ }
6926
+ });
6927
+ }
6928
+ //#endregion
6929
+ //#region src/layout/image-fit.ts
6930
+ function normalizeProjectedImageFit(value) {
6931
+ if (value === "cover" || value === "contain" || value === "stretch" || value === "fill") return value === "fill" ? "stretch" : value;
6932
+ return "contain";
6933
+ }
6934
+ function unsupportedObjectFitSemantics(value) {
6935
+ if (value === void 0 || value === "cover" || value === "contain" || value === "stretch" || value === "fill") return [];
6936
+ const unsupported = unsupportedSemantic({
6937
+ feature: "image",
6938
+ property: "objectFit",
6939
+ value,
6940
+ 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."),
6941
+ fallback: {
6942
+ strategy: "preserveAuthoredValueOnly",
6943
+ preserves: ["authoredObjectFit"],
6944
+ missing: ["cssObjectFitNaturalSize"]
6945
+ }
6946
+ });
6947
+ return unsupported ? [unsupported] : [];
6948
+ }
6949
+ //#endregion
6950
+ //#region src/layout/resolve.ts
6951
+ function errorReason$1(error) {
6952
+ return error instanceof Error ? error.message : String(error);
6953
+ }
6389
6954
  function parseShadowShorthandOrIgnore(input) {
6390
6955
  try {
6956
+ const shadow = parseShadowShorthand(input.value);
6957
+ const unsupported = hasShadowSpreadRadius(input.value) ? unsupportedSemantic({
6958
+ feature: "shadow",
6959
+ property: input.property,
6960
+ value: input.value,
6961
+ error: /* @__PURE__ */ new Error(`CSS shadow spread radius is not projected by the current PPTX shadow model: ${input.value}`),
6962
+ fallback: {
6963
+ strategy: "preserveAuthoredValueOnly",
6964
+ preserves: ["projectedShadowWithoutSpread"],
6965
+ missing: ["cssShadowSpreadRadius"]
6966
+ }
6967
+ }) : void 0;
6391
6968
  return {
6392
- shadow: parseShadowShorthand(input.value),
6393
- unsupportedSemantics: []
6969
+ shadow,
6970
+ unsupportedSemantics: unsupported ? [unsupported] : []
6394
6971
  };
6395
6972
  } catch (error) {
6396
- const unsupported = unsupportedSemantic$1({
6973
+ const unsupported = unsupportedSemantic({
6397
6974
  feature: "shadow",
6398
6975
  property: input.property,
6399
6976
  value: input.value,
@@ -6481,7 +7058,7 @@ function isStrokeIntentionallyNone$1(props) {
6481
7058
  }
6482
7059
  function unsupportedStrokeFallback$1(props, error) {
6483
7060
  const input = strokeFallbackInput$1(props);
6484
- return unsupportedSemantic$1({
7061
+ return unsupportedSemantic({
6485
7062
  feature: input.feature,
6486
7063
  property: input.property,
6487
7064
  value: input.value,
@@ -6522,7 +7099,7 @@ function outlineStrokeOrFallback(props, context) {
6522
7099
  unsupportedSemantics: []
6523
7100
  };
6524
7101
  const input = outlineFallbackInput$1(props);
6525
- const semantic = unsupportedSemantic$1({
7102
+ const semantic = unsupportedSemantic({
6526
7103
  feature: "outline",
6527
7104
  property: input.property,
6528
7105
  value: input.value,
@@ -6536,7 +7113,7 @@ function outlineStrokeOrFallback(props, context) {
6536
7113
  return { unsupportedSemantics: semantic ? [semantic] : [] };
6537
7114
  } catch (error) {
6538
7115
  const input = outlineFallbackInput$1(props);
6539
- const semantic = unsupportedSemantic$1({
7116
+ const semantic = unsupportedSemantic({
6540
7117
  feature: "outline",
6541
7118
  property: input.property,
6542
7119
  value: input.value,
@@ -6554,7 +7131,7 @@ function resolveBackgroundLayersOrEmpty(input, transparency, context, frame, box
6554
7131
  try {
6555
7132
  return resolveBackgroundLayers(input.value, transparency, context, frame, boxFrames, backgroundPosition, backgroundSize, backgroundRepeat, backgroundOrigin, backgroundClip);
6556
7133
  } catch (error) {
6557
- const unsupported = unsupportedSemantic$1({
7134
+ const unsupported = unsupportedSemantic({
6558
7135
  feature: "background",
6559
7136
  property: input.property,
6560
7137
  value: input.value,
@@ -6573,7 +7150,7 @@ function unsupportedTransformSemantics$1(props) {
6573
7150
  try {
6574
7151
  parseTransformShorthand(props.transform);
6575
7152
  } catch (error) {
6576
- const semantic = unsupportedSemantic$1({
7153
+ const semantic = unsupportedSemantic({
6577
7154
  feature: "transform",
6578
7155
  property: "transform",
6579
7156
  value: props.transform,
@@ -6587,7 +7164,7 @@ function unsupportedTransformSemantics$1(props) {
6587
7164
  heightEmu: EMU_PER_INCH
6588
7165
  });
6589
7166
  } catch (error) {
6590
- const semantic = unsupportedSemantic$1({
7167
+ const semantic = unsupportedSemantic({
6591
7168
  feature: "transform",
6592
7169
  property: "transformOrigin",
6593
7170
  value: props.transformOrigin,
@@ -6605,9 +7182,331 @@ const TRANSFORM_STACKING_CONTEXT_FALLBACK_REASON$1 = "CSS transforms create a st
6605
7182
  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.";
6606
7183
  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.";
6607
7184
  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.";
7185
+ 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.";
7186
+ const CSS_SUPPORTED_DISPLAY_VALUES = new Set([
7187
+ "block",
7188
+ "flex",
7189
+ "grid",
7190
+ "none"
7191
+ ]);
7192
+ const CSS_SUPPORTED_OVERFLOW_VALUES = new Set(["visible", "hidden"]);
7193
+ const CSS_SUPPORTED_POSITION_VALUES = new Set([
7194
+ "static",
7195
+ "relative",
7196
+ "absolute"
7197
+ ]);
7198
+ const CSS_SUPPORTED_FLEX_DIRECTION_VALUES = new Set(["row", "column"]);
7199
+ const CSS_SUPPORTED_FLEX_WRAP_VALUES = new Set(["nowrap", "wrap"]);
7200
+ const CSS_SUPPORTED_SELF_ALIGNMENT_VALUES = new Set([
7201
+ "auto",
7202
+ "start",
7203
+ "flex-start",
7204
+ "center",
7205
+ "end",
7206
+ "flex-end",
7207
+ "stretch"
7208
+ ]);
7209
+ const CSS_SUPPORTED_CONTENT_ALIGNMENT_VALUES = new Set([
7210
+ "start",
7211
+ "flex-start",
7212
+ "center",
7213
+ "end",
7214
+ "flex-end",
7215
+ "stretch",
7216
+ "space-between",
7217
+ "space-around",
7218
+ "space-evenly"
7219
+ ]);
7220
+ function normalizedCssKeyword(value) {
7221
+ if (typeof value !== "string") return;
7222
+ return value.trim().toLowerCase() || void 0;
7223
+ }
7224
+ function unsupportedCssLayoutValueSemantic(property, value, missing) {
7225
+ return unsupportedSemantic({
7226
+ feature: "layout",
7227
+ property,
7228
+ value,
7229
+ error: new Error(CSS_LAYOUT_UNSUPPORTED_VALUE_REASON),
7230
+ fallback: {
7231
+ strategy: "preserveAuthoredValueOnly",
7232
+ preserves: ["authoredValue"],
7233
+ missing
7234
+ }
7235
+ });
7236
+ }
7237
+ function addUnsupportedKeywordSemantic(input) {
7238
+ const value = normalizedCssKeyword(input.props[input.property]);
7239
+ if (value === void 0 || input.supported.has(value) || isCssWideKeyword(value)) return;
7240
+ const semantic = unsupportedCssLayoutValueSemantic(input.property, input.props[input.property], input.missing);
7241
+ if (semantic) input.unsupported.push(semantic);
7242
+ }
7243
+ function hasUnsupportedAlignmentTokens(value, supported) {
7244
+ const normalized = normalizedCssKeyword(value);
7245
+ if (normalized === void 0) return false;
7246
+ if (isCssWideKeyword(normalized)) return false;
7247
+ const tokens = normalized.split(/\s+/).filter(Boolean);
7248
+ if (tokens.length === 0) return false;
7249
+ if (tokens[0] === "safe" || tokens[0] === "unsafe") return true;
7250
+ if (tokens.length >= 2 && (tokens[0] === "first" && tokens[1] === "baseline" || tokens[0] === "last" && tokens[1] === "baseline")) return true;
7251
+ return tokens.some((token) => !supported.has(token));
7252
+ }
7253
+ function hasUnsupportedGridLineValue(value) {
7254
+ if (value === void 0 || value === null) return false;
7255
+ if (typeof value === "number") return Number.isFinite(value) && value < 1;
7256
+ const normalized = normalizedCssKeyword(value);
7257
+ if (normalized === void 0 || normalized === "auto") return false;
7258
+ if (isCssWideKeyword(normalized)) return false;
7259
+ return !/^(?:span\s+\d+|\d+)$/.test(normalized);
7260
+ }
7261
+ function hasUnsupportedGridPlacementValue(value, allowNamedArea) {
7262
+ if (value === void 0 || value === null) return false;
7263
+ if (typeof value === "number") return Number.isFinite(value) && value < 1;
7264
+ const normalized = normalizedCssKeyword(value);
7265
+ if (normalized === void 0 || normalized === "auto") return false;
7266
+ if (isCssWideKeyword(normalized)) return false;
7267
+ if (allowNamedArea && !normalized.includes("/")) return false;
7268
+ const linePattern = String.raw`(?:\d+|span\s+\d+)`;
7269
+ return !new RegExp(String.raw`^(?:${linePattern}|${linePattern}\s*/\s*${linePattern})$`).test(normalized);
7270
+ }
7271
+ function unsupportedCssLayoutValueSemantics(props) {
7272
+ const unsupported = [];
7273
+ for (const property of [
7274
+ "display",
7275
+ "overflow",
7276
+ "position",
7277
+ "flexDirection",
7278
+ "flexWrap",
7279
+ "alignSelf",
7280
+ "justifySelf",
7281
+ "placeSelf",
7282
+ "alignItems",
7283
+ "justifyItems",
7284
+ "placeItems",
7285
+ "alignContent",
7286
+ "justifyContent",
7287
+ "placeContent",
7288
+ "inset",
7289
+ "top",
7290
+ "right",
7291
+ "bottom",
7292
+ "left",
7293
+ "x",
7294
+ "y",
7295
+ "width",
7296
+ "height",
7297
+ "minWidth",
7298
+ "minHeight",
7299
+ "maxWidth",
7300
+ "maxHeight",
7301
+ "padding",
7302
+ "paddingTop",
7303
+ "paddingRight",
7304
+ "paddingBottom",
7305
+ "paddingLeft",
7306
+ "margin",
7307
+ "marginTop",
7308
+ "marginRight",
7309
+ "marginBottom",
7310
+ "marginLeft",
7311
+ "gap",
7312
+ "rowGap",
7313
+ "columnGap",
7314
+ "fontSize",
7315
+ "lineHeight",
7316
+ "charSpacing",
7317
+ "letterSpacing",
7318
+ "paragraphSpacingBefore",
7319
+ "paragraphSpacingAfter",
7320
+ "textIndent",
7321
+ "borderWidth",
7322
+ "borderTopWidth",
7323
+ "borderRightWidth",
7324
+ "borderBottomWidth",
7325
+ "borderLeftWidth",
7326
+ "outlineWidth",
7327
+ "strokeWidth"
7328
+ ]) {
7329
+ if (!hasCssWideKeywordToken(props[property])) continue;
7330
+ const semantic = unsupportedCssWideKeywordSemantic(property, props[property]);
7331
+ if (semantic) unsupported.push(semantic);
7332
+ }
7333
+ addUnsupportedKeywordSemantic({
7334
+ unsupported,
7335
+ props,
7336
+ property: "display",
7337
+ supported: CSS_SUPPORTED_DISPLAY_VALUES,
7338
+ missing: ["cssDisplayBehavior"]
7339
+ });
7340
+ addUnsupportedKeywordSemantic({
7341
+ unsupported,
7342
+ props,
7343
+ property: "overflow",
7344
+ supported: CSS_SUPPORTED_OVERFLOW_VALUES,
7345
+ missing: ["cssOverflowBehavior"]
7346
+ });
7347
+ addUnsupportedKeywordSemantic({
7348
+ unsupported,
7349
+ props,
7350
+ property: "position",
7351
+ supported: CSS_SUPPORTED_POSITION_VALUES,
7352
+ missing: ["cssPositionBehavior"]
7353
+ });
7354
+ addUnsupportedKeywordSemantic({
7355
+ unsupported,
7356
+ props,
7357
+ property: "flexDirection",
7358
+ supported: CSS_SUPPORTED_FLEX_DIRECTION_VALUES,
7359
+ missing: ["reverseFlexOrdering"]
7360
+ });
7361
+ addUnsupportedKeywordSemantic({
7362
+ unsupported,
7363
+ props,
7364
+ property: "flexWrap",
7365
+ supported: CSS_SUPPORTED_FLEX_WRAP_VALUES,
7366
+ missing: ["reverseFlexLinePacking"]
7367
+ });
7368
+ const alignmentChecks = [
7369
+ {
7370
+ property: "alignSelf",
7371
+ supported: CSS_SUPPORTED_SELF_ALIGNMENT_VALUES,
7372
+ missing: ["cssBoxAlignment"]
7373
+ },
7374
+ {
7375
+ property: "justifySelf",
7376
+ supported: CSS_SUPPORTED_SELF_ALIGNMENT_VALUES,
7377
+ missing: ["cssBoxAlignment"]
7378
+ },
7379
+ {
7380
+ property: "placeSelf",
7381
+ supported: CSS_SUPPORTED_SELF_ALIGNMENT_VALUES,
7382
+ missing: ["cssBoxAlignment"]
7383
+ },
7384
+ {
7385
+ property: "alignItems",
7386
+ supported: CSS_SUPPORTED_SELF_ALIGNMENT_VALUES,
7387
+ missing: ["cssBoxAlignment"]
7388
+ },
7389
+ {
7390
+ property: "justifyItems",
7391
+ supported: CSS_SUPPORTED_SELF_ALIGNMENT_VALUES,
7392
+ missing: ["cssBoxAlignment"]
7393
+ },
7394
+ {
7395
+ property: "placeItems",
7396
+ supported: CSS_SUPPORTED_SELF_ALIGNMENT_VALUES,
7397
+ missing: ["cssBoxAlignment"]
7398
+ },
7399
+ {
7400
+ property: "alignContent",
7401
+ supported: CSS_SUPPORTED_CONTENT_ALIGNMENT_VALUES,
7402
+ missing: ["cssContentDistribution"]
7403
+ },
7404
+ {
7405
+ property: "justifyContent",
7406
+ supported: CSS_SUPPORTED_CONTENT_ALIGNMENT_VALUES,
7407
+ missing: ["cssContentDistribution"]
7408
+ },
7409
+ {
7410
+ property: "placeContent",
7411
+ supported: CSS_SUPPORTED_CONTENT_ALIGNMENT_VALUES,
7412
+ missing: ["cssContentDistribution"]
7413
+ }
7414
+ ];
7415
+ for (const check of alignmentChecks) {
7416
+ if (!hasUnsupportedAlignmentTokens(props[check.property], check.supported)) continue;
7417
+ const semantic = unsupportedCssLayoutValueSemantic(check.property, props[check.property], check.missing);
7418
+ if (semantic) unsupported.push(semantic);
7419
+ }
7420
+ for (const property of [
7421
+ "gridColumnStart",
7422
+ "gridColumnEnd",
7423
+ "gridRowStart",
7424
+ "gridRowEnd"
7425
+ ]) {
7426
+ if (!hasUnsupportedGridLineValue(props[property])) continue;
7427
+ const semantic = unsupportedCssLayoutValueSemantic(property, props[property], ["cssGridNamedOrNegativeLineResolution"]);
7428
+ if (semantic) unsupported.push(semantic);
7429
+ }
7430
+ for (const check of [
7431
+ {
7432
+ property: "gridColumn",
7433
+ allowNamedArea: false
7434
+ },
7435
+ {
7436
+ property: "gridRow",
7437
+ allowNamedArea: false
7438
+ },
7439
+ {
7440
+ property: "gridArea",
7441
+ allowNamedArea: true
7442
+ }
7443
+ ]) {
7444
+ if (!hasUnsupportedGridPlacementValue(props[check.property], check.allowNamedArea)) continue;
7445
+ const semantic = unsupportedCssLayoutValueSemantic(check.property, props[check.property], ["cssGridNamedOrNegativeLineResolution"]);
7446
+ if (semantic) unsupported.push(semantic);
7447
+ }
7448
+ for (const property of [
7449
+ "inset",
7450
+ "top",
7451
+ "right",
7452
+ "bottom",
7453
+ "left",
7454
+ "x",
7455
+ "y"
7456
+ ]) {
7457
+ if (!hasAutoToken(props[property])) continue;
7458
+ const semantic = unsupportedCssLayoutValueSemantic(property, props[property], ["cssAutoInsetResolution"]);
7459
+ if (semantic) unsupported.push(semantic);
7460
+ }
7461
+ for (const property of [
7462
+ "margin",
7463
+ "marginTop",
7464
+ "marginRight",
7465
+ "marginBottom",
7466
+ "marginLeft"
7467
+ ]) {
7468
+ if (!hasAutoToken(props[property])) continue;
7469
+ const semantic = unsupportedCssLayoutValueSemantic(property, props[property], ["cssAutoMarginResolution"]);
7470
+ if (semantic) unsupported.push(semantic);
7471
+ }
7472
+ return unsupported;
7473
+ }
7474
+ 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.";
7475
+ function unsupportedTextLogicalLayoutSemantics(props) {
7476
+ const unsupported = [];
7477
+ if (props.direction === "rtl") {
7478
+ const semantic = unsupportedSemantic({
7479
+ feature: "layout",
7480
+ property: "direction",
7481
+ value: props.direction,
7482
+ error: new Error(CSS_LOGICAL_LAYOUT_AXIS_FALLBACK_REASON),
7483
+ fallback: {
7484
+ strategy: "preserveAuthoredValueOnly",
7485
+ preserves: ["textBodyDirection"],
7486
+ missing: ["logicalLayoutAxes", "cssLogicalStartEndMapping"]
7487
+ }
7488
+ });
7489
+ if (semantic) unsupported.push(semantic);
7490
+ }
7491
+ if (props.writingMode !== void 0 && props.writingMode !== "horizontal-tb") {
7492
+ const semantic = unsupportedSemantic({
7493
+ feature: "layout",
7494
+ property: "writingMode",
7495
+ value: props.writingMode,
7496
+ error: new Error(CSS_LOGICAL_LAYOUT_AXIS_FALLBACK_REASON),
7497
+ fallback: {
7498
+ strategy: "preserveAuthoredValueOnly",
7499
+ preserves: ["textBodyDirection"],
7500
+ missing: ["logicalLayoutAxes", "cssLogicalStartEndMapping"]
7501
+ }
7502
+ });
7503
+ if (semantic) unsupported.push(semantic);
7504
+ }
7505
+ return unsupported;
7506
+ }
6608
7507
  function unsupportedGroupOpacitySemantics$1(props) {
6609
7508
  if (props.opacity === void 0 || props.opacity <= 0 || props.opacity >= 1) return [];
6610
- const semantic = unsupportedSemantic$1({
7509
+ const semantic = unsupportedSemantic({
6611
7510
  feature: "opacity",
6612
7511
  property: "opacity",
6613
7512
  value: props.opacity,
@@ -6622,7 +7521,7 @@ function unsupportedGroupOpacitySemantics$1(props) {
6622
7521
  }
6623
7522
  function unsupportedOpacityStackingContextSemantics$1(props) {
6624
7523
  if (props.opacity === void 0 || props.opacity <= 0 || props.opacity >= 1) return [];
6625
- const semantic = unsupportedSemantic$1({
7524
+ const semantic = unsupportedSemantic({
6626
7525
  feature: "opacity",
6627
7526
  property: "stackingContext",
6628
7527
  value: props.opacity,
@@ -6640,7 +7539,7 @@ function hasProjectedTransform(input) {
6640
7539
  }
6641
7540
  function unsupportedClippingTransformSemantics(input) {
6642
7541
  if (!input.clip || !hasProjectedTransform(input)) return [];
6643
- const semantic = unsupportedSemantic$1({
7542
+ const semantic = unsupportedSemantic({
6644
7543
  feature: "clipping",
6645
7544
  property: "overflow",
6646
7545
  value: `hidden + transform:${input.clip.strategy}`,
@@ -6661,7 +7560,7 @@ function unsupportedClippingTransformSemantics(input) {
6661
7560
  function unsupportedClippedImageSourceRectTransformSemantics(input) {
6662
7561
  if (!input.clip || !hasProjectedTransform(input)) return [];
6663
7562
  const cropSuffix = input.hasExplicitCrop ? "+crop" : "";
6664
- const semantic = unsupportedSemantic$1({
7563
+ const semantic = unsupportedSemantic({
6665
7564
  feature: "clipping",
6666
7565
  property: "imageSourceRect",
6667
7566
  value: `clip:${input.clip.strategy}+transform+fit:${input.fit ?? "contain"}${cropSuffix}`,
@@ -6687,7 +7586,7 @@ function unsupportedTransformStackingContextSemantics$1(props) {
6687
7586
  return [];
6688
7587
  }
6689
7588
  if (!operations?.length) return [];
6690
- const semantic = unsupportedSemantic$1({
7589
+ const semantic = unsupportedSemantic({
6691
7590
  feature: "transform",
6692
7591
  property: "stackingContext",
6693
7592
  value: props.transform,
@@ -6704,7 +7603,7 @@ function unsupportedCompositingSemantics$1(props) {
6704
7603
  const unsupported = [];
6705
7604
  const filter = props.filter?.trim();
6706
7605
  if (filter && filter.toLowerCase() !== "none") {
6707
- const semantic = unsupportedSemantic$1({
7606
+ const semantic = unsupportedSemantic({
6708
7607
  feature: "filter",
6709
7608
  property: "filter",
6710
7609
  value: props.filter,
@@ -6719,7 +7618,7 @@ function unsupportedCompositingSemantics$1(props) {
6719
7618
  }
6720
7619
  const mixBlendMode = props.mixBlendMode?.trim();
6721
7620
  if (mixBlendMode && mixBlendMode.toLowerCase() !== "normal") {
6722
- const semantic = unsupportedSemantic$1({
7621
+ const semantic = unsupportedSemantic({
6723
7622
  feature: "blend",
6724
7623
  property: "mixBlendMode",
6725
7624
  value: props.mixBlendMode,
@@ -6733,7 +7632,7 @@ function unsupportedCompositingSemantics$1(props) {
6733
7632
  if (semantic) unsupported.push(semantic);
6734
7633
  }
6735
7634
  if (props.isolation === "isolate") {
6736
- const semantic = unsupportedSemantic$1({
7635
+ const semantic = unsupportedSemantic({
6737
7636
  feature: "isolation",
6738
7637
  property: "isolation",
6739
7638
  value: props.isolation,
@@ -6782,6 +7681,8 @@ const EMPTY_SPACING = [
6782
7681
  0,
6783
7682
  0
6784
7683
  ];
7684
+ const DEFAULT_TEXT_FONT_SIZE_PT = 18;
7685
+ const DEFAULT_NORMAL_LINE_HEIGHT_MULTIPLE = 1.2;
6785
7686
  function createIdGenerator() {
6786
7687
  let slideCount = 0;
6787
7688
  let nodeCount = 0;
@@ -6813,11 +7714,14 @@ function imageSourceFromProps(props) {
6813
7714
  };
6814
7715
  throw new Error("Image requires either src or data.");
6815
7716
  }
6816
- function originForNode(node, options) {
6817
- return options?.origins?.get(node);
7717
+ function isLayoutInputContentNode(value) {
7718
+ return typeof value === "object" && value !== null && "kind" in value && (value.kind === "view" || value.kind === "text" || value.kind === "image" || value.kind === "shape");
6818
7719
  }
6819
- function layoutChildFromNode(child, siblingOrder, context, options) {
6820
- const origin = originForNode(child, options);
7720
+ function isLayoutInputTextNode(value) {
7721
+ return typeof value === "object" && value !== null && "kind" in value && value.kind === "text";
7722
+ }
7723
+ function layoutChildFromNode(child, siblingOrder, context) {
7724
+ const origin = child.origin;
6821
7725
  switch (child.kind) {
6822
7726
  case "view": return {
6823
7727
  kind: "view",
@@ -6836,7 +7740,7 @@ function layoutChildFromNode(child, siblingOrder, context, options) {
6836
7740
  case "image": return {
6837
7741
  kind: "image",
6838
7742
  source: child,
6839
- props: normalizeImageProps(child.props, context),
7743
+ props: normalizeImagePropsWithIntrinsicAspectRatio(child, context),
6840
7744
  siblingOrder,
6841
7745
  ...origin ? { origin } : {}
6842
7746
  };
@@ -6849,6 +7753,35 @@ function layoutChildFromNode(child, siblingOrder, context, options) {
6849
7753
  };
6850
7754
  }
6851
7755
  }
7756
+ function normalizeImagePropsWithIntrinsicAspectRatio(child, context) {
7757
+ const props = normalizeImageProps(child.props, context);
7758
+ if (props.aspectRatio !== void 0) return props;
7759
+ const width = child.assetProbe?.width;
7760
+ const height = child.assetProbe?.height;
7761
+ if (width === void 0 || height === void 0 || !Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return props;
7762
+ return {
7763
+ ...props,
7764
+ aspectRatio: width / height
7765
+ };
7766
+ }
7767
+ function resolveCornerRadiusEmu$1(value, frame, context) {
7768
+ return parseLength(value, Math.min(frame.widthEmu, frame.heightEmu), 0, context);
7769
+ }
7770
+ function unsupportedObjectPositionSemantics(input) {
7771
+ if (input.value === void 0 || input.resolved !== void 0) return [];
7772
+ const unsupported = unsupportedSemantic({
7773
+ feature: "image",
7774
+ property: "objectPosition",
7775
+ value: input.value,
7776
+ error: /* @__PURE__ */ new Error("Unsupported objectPosition value."),
7777
+ fallback: {
7778
+ strategy: "preserveAuthoredValueOnly",
7779
+ preserves: ["authoredObjectPosition"],
7780
+ missing: ["pptxObjectPosition"]
7781
+ }
7782
+ });
7783
+ return unsupported ? [unsupported] : [];
7784
+ }
6852
7785
  function parseCropValue$1(value) {
6853
7786
  if (value === void 0) return 0;
6854
7787
  if (typeof value === "number") {
@@ -6925,12 +7858,12 @@ function resolveAlignContentOffset(alignContent, availableEmu, usedEmu, lineCoun
6925
7858
  extraSizeEmu: 0
6926
7859
  };
6927
7860
  }
6928
- function getChildPadding(node, context) {
7861
+ function getChildPadding(node, context, percentageBaseEmu = 0) {
6929
7862
  switch (node.kind) {
6930
- case "view": return parseSpacing(node.props.padding, context);
7863
+ case "view": return parseSpacing(node.props.padding, context, percentageBaseEmu);
6931
7864
  case "text": {
6932
7865
  const { props } = node;
6933
- return parseSpacing(props.padding, getTextLengthContext(props, context));
7866
+ return parseSpacing(props.padding, getTextLengthContext(props, context), percentageBaseEmu);
6934
7867
  }
6935
7868
  case "image": return EMPTY_SPACING;
6936
7869
  case "shape": return EMPTY_SPACING;
@@ -6948,46 +7881,68 @@ function resolveChildMainLength(node, axis) {
6948
7881
  if (flexBasis !== void 0 && flexBasis !== "auto") return flexBasis;
6949
7882
  return node.props[axis === "horizontal" ? "width" : "height"];
6950
7883
  }
7884
+ function resolveTextFontSizePt(props, context) {
7885
+ return parsePointValue(props.fontSize, DEFAULT_TEXT_FONT_SIZE_PT, context);
7886
+ }
7887
+ function resolveTextLineHeightPt(props, context) {
7888
+ const fontSizePt = resolveTextFontSizePt(props, context);
7889
+ if (props.lineHeight === void 0 || props.lineHeight === "normal") return fontSizePt * DEFAULT_NORMAL_LINE_HEIGHT_MULTIPLE;
7890
+ if (typeof props.lineHeight === "number") return fontSizePt * props.lineHeight;
7891
+ return parsePointValue(props.lineHeight, fontSizePt * DEFAULT_NORMAL_LINE_HEIGHT_MULTIPLE, {
7892
+ ...context,
7893
+ fontSizePt
7894
+ });
7895
+ }
7896
+ function estimateTextAutoContentSize(node, dimension, parent, context) {
7897
+ const textContext = getTextLengthContext(node.props, context);
7898
+ const [paddingTop, , paddingBottom] = parseSpacing(node.props.padding, textContext, parent.widthEmu);
7899
+ if (dimension === "width") return parent.widthEmu;
7900
+ return resolveTextLineHeightPt(node.props, textContext) / 72 * EMU_PER_INCH + paddingTop + paddingBottom;
7901
+ }
6951
7902
  function estimateChildContentSize(node, dimension, parent, mainAxis, context) {
6952
7903
  const aspectRatio = parseAspectRatio(node.props.aspectRatio);
6953
7904
  const isMainDimension = mainAxis === "horizontal" && dimension === "width" || mainAxis === "vertical" && dimension === "height";
6954
7905
  const basis = dimension === "width" ? parent.widthEmu : parent.heightEmu;
6955
- const directValue = isMainDimension && mainAxis ? resolveChildMainLength(node, mainAxis) : node.props[dimension];
6956
- 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);
7906
+ const authoredValue = authoredLengthOrUndefined(isMainDimension && mainAxis ? resolveChildMainLength(node, mainAxis) : node.props[dimension]);
7907
+ if (authoredValue !== void 0) return inflateSpecifiedBoxSize(parseLength(authoredValue, basis, 0, getNodeLengthContext(node, context)), node.kind === "image" ? "border-box" : node.props.boxSizing ?? "border-box", getChildPadding(node, context, parent.widthEmu), dimension);
7908
+ if (node.kind === "text") {
7909
+ if (dimension === "width" && mainAxis === "horizontal") return 0;
7910
+ return estimateTextAutoContentSize(node, dimension, parent, context);
7911
+ }
6957
7912
  if (aspectRatio === void 0) return 0;
6958
7913
  const oppositeDimension = dimension === "width" ? "height" : "width";
6959
7914
  const oppositeBasis = oppositeDimension === "width" ? parent.widthEmu : parent.heightEmu;
6960
- const oppositeValue = (mainAxis === "horizontal" && oppositeDimension === "width" || mainAxis === "vertical" && oppositeDimension === "height") && mainAxis ? resolveChildMainLength(node, mainAxis) : node.props[oppositeDimension];
6961
- if (oppositeValue === void 0) return 0;
6962
- const oppositeSize = parseLength(oppositeValue, oppositeBasis, 0, getNodeLengthContext(node, context));
6963
- return inflateSpecifiedBoxSize(dimension === "width" ? oppositeSize * aspectRatio : oppositeSize / aspectRatio, node.kind === "image" ? "border-box" : node.props.boxSizing ?? "border-box", getChildPadding(node, context), dimension);
7915
+ const authoredOppositeValue = authoredLengthOrUndefined((mainAxis === "horizontal" && oppositeDimension === "width" || mainAxis === "vertical" && oppositeDimension === "height") && mainAxis ? resolveChildMainLength(node, mainAxis) : node.props[oppositeDimension]);
7916
+ if (authoredOppositeValue === void 0) return 0;
7917
+ const oppositeSize = parseLength(authoredOppositeValue, oppositeBasis, 0, getNodeLengthContext(node, context));
7918
+ return inflateSpecifiedBoxSize(dimension === "width" ? oppositeSize * aspectRatio : oppositeSize / aspectRatio, node.kind === "image" ? "border-box" : node.props.boxSizing ?? "border-box", getChildPadding(node, context, parent.widthEmu), dimension);
6964
7919
  }
6965
- function getNodeMargin(node, context) {
7920
+ function getNodeMargin(node, context, percentageBaseEmu = 0) {
6966
7921
  switch (node.kind) {
6967
- case "view": return parseSpacing(node.props.margin, context);
7922
+ case "view": return parseSpacingAllowAuto(node.props.margin, context, percentageBaseEmu);
6968
7923
  case "text": {
6969
7924
  const { props } = node;
6970
- return parseSpacing(props.margin, getTextLengthContext(props, context));
7925
+ return parseSpacingAllowAuto(props.margin, getTextLengthContext(props, context), percentageBaseEmu);
6971
7926
  }
6972
- case "image": return parseSpacing(node.props.margin, context);
6973
- case "shape": return parseSpacing(node.props.margin, context);
7927
+ case "image": return parseSpacingAllowAuto(node.props.margin, context, percentageBaseEmu);
7928
+ case "shape": return parseSpacingAllowAuto(node.props.margin, context, percentageBaseEmu);
6974
7929
  }
6975
7930
  }
6976
7931
  function estimateChildMainSize(node, axis, parent, context) {
6977
- const [top, right, bottom, left] = getNodeMargin(node, context);
7932
+ const [top, right, bottom, left] = getNodeMargin(node, context, parent.widthEmu);
6978
7933
  const margin = axis === "horizontal" ? left + right : top + bottom;
6979
7934
  return estimateChildContentSize(node, axis === "horizontal" ? "width" : "height", parent, axis, context) + margin;
6980
7935
  }
6981
7936
  function estimateChildCrossSize(node, axis, parent, context) {
6982
- const [top, right, bottom, left] = getNodeMargin(node, context);
7937
+ const [top, right, bottom, left] = getNodeMargin(node, context, parent.widthEmu);
6983
7938
  const margin = axis === "horizontal" ? top + bottom : left + right;
6984
7939
  return estimateChildContentSize(node, axis === "horizontal" ? "height" : "width", parent, axis, context) + margin;
6985
7940
  }
6986
7941
  function shouldStretchGridDimension(node, dimension) {
6987
- if (node.props[dimension] !== void 0) return false;
7942
+ if (hasAuthoredLength(node.props[dimension])) return false;
6988
7943
  if (!parseAspectRatio(node.props.aspectRatio)) return true;
6989
7944
  const oppositeDimension = dimension === "width" ? "height" : "width";
6990
- return node.props[oppositeDimension] === void 0;
7945
+ return !hasAuthoredLength(node.props[oppositeDimension]);
6991
7946
  }
6992
7947
  function resolveChildGridPlacements(node, namedAreas) {
6993
7948
  const explicitRow = resolveGridPlacementFromLonghands(node.props.gridRowStart, node.props.gridRowEnd) ?? parseGridPlacement(node.props.gridRow);
@@ -7006,7 +7961,7 @@ function resolveChildGridPlacements(node, namedAreas) {
7006
7961
  };
7007
7962
  }
7008
7963
  function resolveGridContainerSpec(parentFrame, options, context) {
7009
- const [paddingTop, paddingRight, paddingBottom, paddingLeft] = parseSpacing(options.padding, context);
7964
+ const [paddingTop, paddingRight, paddingBottom, paddingLeft] = parseSpacing(options.padding, context, parentFrame.widthEmu);
7010
7965
  const contentX = parentFrame.xEmu + paddingLeft;
7011
7966
  const contentY = parentFrame.yEmu + paddingTop;
7012
7967
  const contentWidth = Math.max(parentFrame.widthEmu - paddingLeft - paddingRight, 0);
@@ -7017,8 +7972,8 @@ function resolveGridContainerSpec(parentFrame, options, context) {
7017
7972
  widthEmu: contentWidth,
7018
7973
  heightEmu: contentHeight
7019
7974
  };
7020
- const columnGapEmu = parseLength(options.columnGap ?? options.rowGap, 0, 0, context);
7021
- const rowGapEmu = parseLength(options.rowGap ?? options.columnGap, 0, 0, context);
7975
+ const columnGapEmu = parseLength(options.columnGap ?? options.rowGap, contentWidth, 0, context);
7976
+ const rowGapEmu = parseLength(options.rowGap ?? options.columnGap, contentHeight, 0, context);
7022
7977
  const placeItems = parsePlaceItems(options.placeItems);
7023
7978
  const placeContent = parsePlaceContent(options.placeContent);
7024
7979
  const namedAreas = parseGridTemplateAreas(options.gridTemplateAreas);
@@ -7103,7 +8058,7 @@ function compileGridChildren(authorChildren, parentFrame, idGenerator, options,
7103
8058
  const rowOffsets = resolveTrackOffsets(stretchedRowTracks, spec.rowGapEmu).map((offset) => offset + blockPacking.offsetEmu);
7104
8059
  return sortNodesForPaint(placements.map((placement) => {
7105
8060
  const { child, row, column, rowSpan, columnSpan } = placement;
7106
- const [marginTop, marginRight, marginBottom, marginLeft] = getNodeMargin(child, context);
8061
+ const [marginTop, marginRight, marginBottom, marginLeft] = getNodeMargin(child, context, spec.contentWidth);
7107
8062
  const cellWidth = stretchedColumnTracks.slice(column - 1, column - 1 + columnSpan).reduce((sum, size) => sum + size, 0) + Math.max(columnSpan - 1, 0) * spec.columnGapEmu;
7108
8063
  const cellHeight = stretchedRowTracks.slice(row - 1, row - 1 + rowSpan).reduce((sum, size) => sum + size, 0) + Math.max(rowSpan - 1, 0) * spec.rowGapEmu;
7109
8064
  const innerFrame = {
@@ -7130,13 +8085,48 @@ function compileGridChildren(authorChildren, parentFrame, idGenerator, options,
7130
8085
  return compileNode(child, innerFrame, idGenerator, placementOverride, clipRect, context, resolutionOptions);
7131
8086
  }).filter((node) => node !== null));
7132
8087
  }
8088
+ function hasExplicitFrameInput(child) {
8089
+ const { props } = child;
8090
+ const relativePosition = props.position === "relative";
8091
+ 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);
8092
+ }
8093
+ function compileBlockFlowChildren(authorChildren, parentFrame, idGenerator, options, clipRect, context, resolutionOptions) {
8094
+ const [paddingTop, paddingRight, paddingBottom, paddingLeft] = parseSpacing(options.padding, context, parentFrame.widthEmu);
8095
+ const contentFrame = {
8096
+ xEmu: parentFrame.xEmu + paddingLeft,
8097
+ yEmu: parentFrame.yEmu + paddingTop,
8098
+ widthEmu: Math.max(parentFrame.widthEmu - paddingLeft - paddingRight, 0),
8099
+ heightEmu: Math.max(parentFrame.heightEmu - paddingTop - paddingBottom, 0)
8100
+ };
8101
+ const blockGapEmu = resolveMainGap("vertical", options.gap, options.rowGap, options.columnGap, context, contentFrame.heightEmu);
8102
+ let cursorY = contentFrame.yEmu;
8103
+ const flowNodes = [];
8104
+ for (const child of authorChildren) {
8105
+ const [marginTop, marginRight, marginBottom, marginLeft] = getNodeMargin(child, context, contentFrame.widthEmu);
8106
+ const childWidth = authoredLengthOrUndefined(child.props.width) === void 0 ? Math.max(contentFrame.widthEmu - marginLeft - marginRight, 0) : estimateChildContentSize(child, "width", contentFrame, void 0, context);
8107
+ const childHeight = estimateChildContentSize(child, "height", contentFrame, "vertical", context);
8108
+ const compiledNode = compileNode(child, contentFrame, idGenerator, {
8109
+ xEmu: contentFrame.xEmu + marginLeft,
8110
+ yEmu: cursorY + marginTop,
8111
+ widthEmu: childWidth,
8112
+ heightEmu: childHeight
8113
+ }, clipRect, context, resolutionOptions);
8114
+ if (compiledNode) flowNodes.push(compiledNode);
8115
+ cursorY += marginTop + childHeight + marginBottom + blockGapEmu;
8116
+ }
8117
+ return flowNodes;
8118
+ }
8119
+ function compileAbsoluteChildren(authorChildren, parentFrame, idGenerator, options, clipRect, context, resolutionOptions) {
8120
+ const flowChildren = authorChildren.filter((child) => !hasExplicitFrameInput(child));
8121
+ const absoluteChildren = authorChildren.filter(hasExplicitFrameInput);
8122
+ const flowNodes = compileBlockFlowChildren(flowChildren, parentFrame, idGenerator, options, clipRect, context, resolutionOptions);
8123
+ const absoluteNodes = absoluteChildren.map((child) => compileNode(child, parentFrame, idGenerator, void 0, clipRect, context, resolutionOptions)).filter((node) => node !== null);
8124
+ return sortNodesForPaint([...flowNodes, ...absoluteNodes].sort((left, right) => left.siblingOrder - right.siblingOrder));
8125
+ }
7133
8126
  function compileChildren$1(children, parentFrame, idGenerator, layout, options, clipRect, context, resolutionOptions) {
7134
- const authorChildren = children.filter((child) => child !== null && child !== void 0 && child !== false && child !== true).map((child, siblingOrder) => {
7135
- if (!isContentNode(child)) {
7136
- if (isSlideNode(child)) throw new Error("Slide cannot be nested inside another slide or view.");
7137
- throw new Error("Only deckjsx components can be children of View in structured layout.");
7138
- }
7139
- return layoutChildFromNode(child, siblingOrder, context, resolutionOptions);
8127
+ const authorChildren = children.map((child, siblingOrder) => {
8128
+ if (!isLayoutInputContentNode(child)) throw new Error("Only deckjsx components can be children of View in structured layout.");
8129
+ return layoutChildFromNode(child, siblingOrder, context);
7140
8130
  }).filter((child) => child.props.display !== "none");
7141
8131
  if (layout === "grid") return compileGridChildren(authorChildren, parentFrame, idGenerator, {
7142
8132
  padding: options.padding,
@@ -7155,11 +8145,15 @@ function compileChildren$1(children, parentFrame, idGenerator, layout, options,
7155
8145
  placeContent: options.placeContent,
7156
8146
  gridAutoFlow: options.gridAutoFlow
7157
8147
  }, clipRect, context, resolutionOptions);
7158
- if (layout !== "stack") return sortNodesForPaint(authorChildren.map((child) => compileNode(child, parentFrame, idGenerator, void 0, clipRect, context, resolutionOptions)).filter((node) => node !== null));
8148
+ if (layout !== "stack") return compileAbsoluteChildren(authorChildren, parentFrame, idGenerator, {
8149
+ padding: options.padding,
8150
+ gap: options.gap,
8151
+ rowGap: options.rowGap,
8152
+ columnGap: options.columnGap
8153
+ }, clipRect, context, resolutionOptions);
7159
8154
  const direction = options.direction ?? "vertical";
7160
- const mainGapEmu = resolveMainGap(direction, options.gap, options.rowGap, options.columnGap, context);
7161
- const crossGapEmu = resolveCrossGap(direction, options.gap, options.rowGap, options.columnGap, context);
7162
- const [paddingTop, paddingRight, paddingBottom, paddingLeft] = parseSpacing(options.padding, context);
8155
+ const defaultAlignItems = options.alignItems ?? (options.display === "flex" ? "stretch" : void 0);
8156
+ const [paddingTop, paddingRight, paddingBottom, paddingLeft] = parseSpacing(options.padding, context, parentFrame.widthEmu);
7163
8157
  const contentX = parentFrame.xEmu + paddingLeft;
7164
8158
  const contentY = parentFrame.yEmu + paddingTop;
7165
8159
  const contentWidth = Math.max(parentFrame.widthEmu - paddingLeft - paddingRight, 0);
@@ -7170,6 +8164,8 @@ function compileChildren$1(children, parentFrame, idGenerator, layout, options,
7170
8164
  widthEmu: contentWidth,
7171
8165
  heightEmu: contentHeight
7172
8166
  };
8167
+ const mainGapEmu = resolveMainGap(direction, options.gap, options.rowGap, options.columnGap, context, direction === "horizontal" ? contentWidth : contentHeight);
8168
+ const crossGapEmu = resolveCrossGap(direction, options.gap, options.rowGap, options.columnGap, context, direction === "horizontal" ? contentHeight : contentWidth);
7173
8169
  const stackEntries = authorChildren.map((child, sourceIndex) => ({
7174
8170
  child,
7175
8171
  sourceIndex,
@@ -7187,13 +8183,13 @@ function compileChildren$1(children, parentFrame, idGenerator, layout, options,
7187
8183
  const absoluteEntries = stackEntries.filter((entry) => entry.position === "absolute");
7188
8184
  const availableMain = direction === "horizontal" ? contentWidth : contentHeight;
7189
8185
  const availableCross = direction === "horizontal" ? contentHeight : contentWidth;
7190
- const lines = buildStackLines(flowEntries, direction, parentFrame, availableMain, mainGapEmu, options.flexWrap, stackMetrics, context);
8186
+ const lines = buildStackLines(flowEntries, direction, contentFrame, availableMain, mainGapEmu, options.flexWrap, stackMetrics, context);
7191
8187
  const usedCross = lines.reduce((sum, line) => sum + line.crossSizeEmu, 0) + Math.max(lines.length - 1, 0) * crossGapEmu;
7192
8188
  const contentPacking = resolveAlignContentOffset(options.alignContent, availableCross, usedCross, lines.length);
7193
8189
  let crossCursor = contentPacking.offsetEmu;
7194
8190
  const flowNodes = [];
7195
8191
  for (const [lineIndex, line] of lines.entries()) {
7196
- const mainAllocations = resolveFlexMainAllocations(line, direction, parentFrame, availableMain, mainGapEmu, stackMetrics, context);
8192
+ const mainAllocations = resolveFlexMainAllocations(line, direction, contentFrame, availableMain, mainGapEmu, stackMetrics, context);
7197
8193
  const allocatedUsedMain = mainAllocations.reduce((sum, allocation) => sum + allocation.outerMainEmu, 0) + Math.max(line.entries.length - 1, 0) * mainGapEmu;
7198
8194
  const justify = resolveJustifyOffset(options.justifyContent, availableMain, allocatedUsedMain, line.entries.length);
7199
8195
  let mainCursor = justify.offsetEmu;
@@ -7202,10 +8198,10 @@ function compileChildren$1(children, parentFrame, idGenerator, layout, options,
7202
8198
  const mainAllocation = mainAllocations[entryIndex];
7203
8199
  if (mainAllocation === void 0) throw new Error("Stack layout allocation count did not match line entry count.");
7204
8200
  const { child } = entry;
7205
- const childCross = estimateChildCrossSize(child, direction, parentFrame, context);
7206
- const [marginTop, marginRight, marginBottom, marginLeft] = getNodeMargin(child, context);
7207
- let alignment = parsePlaceSelf(child.props.placeSelf).alignSelf ?? child.props.alignSelf ?? options.alignItems;
7208
- if (alignment === "auto") alignment = void 0;
8201
+ const childCross = estimateChildCrossSize(child, direction, contentFrame, context);
8202
+ const [marginTop, marginRight, marginBottom, marginLeft] = getNodeMargin(child, context, contentFrame.widthEmu);
8203
+ const alignSelf = parsePlaceSelf(child.props.placeSelf).alignSelf ?? child.props.alignSelf;
8204
+ let alignment = alignSelf === "auto" ? defaultAlignItems : alignSelf ?? defaultAlignItems;
7209
8205
  if (alignment === "flex-start") alignment = "start";
7210
8206
  if (alignment === "flex-end") alignment = "end";
7211
8207
  const hasExplicitCrossSize = child.props[direction === "horizontal" ? "height" : "width"] !== void 0;
@@ -7251,13 +8247,14 @@ function compileGroupNode(node, parentFrame, idGenerator, placement, clipRect, c
7251
8247
  const visibleFrame = intersectClipRect(originalFrame, clipRect);
7252
8248
  if (!visibleFrame) return null;
7253
8249
  const childClipRect = props.overflow === "hidden" ? intersectClipRect(originalFrame, clipRect) : clipRect;
7254
- const backgroundBoxFrames = resolveBackgroundBoxFrames(visibleFrame, strokes.stroke, strokes.edgeStrokes, parseSpacing(props.padding, context));
8250
+ const backgroundBoxFrames = resolveBackgroundBoxFrames(visibleFrame, strokes.stroke, strokes.edgeStrokes, parseSpacing(props.padding, context, visibleFrame.widthEmu));
7255
8251
  const backgroundFill = resolveBackgroundLayersOrEmpty(backgroundInput(props), props.backgroundTransparency, {
7256
8252
  widthEmu: visibleFrame.widthEmu,
7257
8253
  heightEmu: visibleFrame.heightEmu
7258
8254
  }, visibleFrame, backgroundBoxFrames, props.backgroundPosition, props.backgroundSize, props.backgroundRepeat, props.backgroundOrigin, props.backgroundClip);
7259
8255
  const clip = clippingMetadata(originalFrame, clipRect, visibleFrame);
7260
8256
  const unsupportedSemantics = [
8257
+ ...unsupportedCssLayoutValueSemantics(props),
7261
8258
  ...unsupportedTransformSemantics$1(props),
7262
8259
  ...unsupportedTransformStackingContextSemantics$1(props),
7263
8260
  ...unsupportedCompositingSemantics$1(props),
@@ -7293,9 +8290,10 @@ function compileGroupNode(node, parentFrame, idGenerator, placement, clipRect, c
7293
8290
  ...strokes.edgeStrokes ? { edgeStrokes: strokes.edgeStrokes } : {},
7294
8291
  ...outline.outline ? { outline: outline.outline } : {},
7295
8292
  ...shadow.shadow ? { shadow: shadow.shadow } : {},
7296
- radiusEmu: parseLength(props.borderRadius, 0, 0, context),
8293
+ radiusEmu: resolveCornerRadiusEmu$1(props.borderRadius, visibleFrame, context),
7297
8294
  children: compileChildren$1(node.source.children, originalFrame, idGenerator, props.layout, {
7298
8295
  direction: props.direction,
8296
+ display: props.display,
7299
8297
  gap: props.gap,
7300
8298
  rowGap: props.rowGap,
7301
8299
  columnGap: props.columnGap,
@@ -7323,7 +8321,7 @@ function textStyleFromProps$1(props, textLengthContext) {
7323
8321
  const underlineColor = normalizeColor(props.textDecorationColor);
7324
8322
  const textDirection = resolveTextDirection(props.writingMode);
7325
8323
  const tabStops = resolveTabStops(props.tabStops, textLengthContext);
7326
- const fontSizePt = props.fontSize === void 0 ? void 0 : parsePointValue(props.fontSize, 0, textLengthContext);
8324
+ const fontSizePt = props.fontSize === void 0 || isCssWideKeyword(props.fontSize) ? void 0 : parsePointValue(props.fontSize, 0, textLengthContext);
7327
8325
  return {
7328
8326
  fontFamily: props.fontFamily,
7329
8327
  fontSizePt,
@@ -7339,11 +8337,11 @@ function textStyleFromProps$1(props, textLengthContext) {
7339
8337
  paddingPt: parseSpacingInPoints(props.padding, textLengthContext),
7340
8338
  lineSpacing: props.lineSpacing ?? lineHeight.lineSpacing,
7341
8339
  lineSpacingMultiple: props.lineSpacingMultiple ?? lineHeight.lineSpacingMultiple,
7342
- paragraphSpacingBefore: props.paragraphSpacingBefore,
7343
- paragraphSpacingAfter: props.paragraphSpacingAfter,
8340
+ paragraphSpacingBefore: props.paragraphSpacingBefore === void 0 ? void 0 : parsePointValue(props.paragraphSpacingBefore, 0, textLengthContext),
8341
+ paragraphSpacingAfter: props.paragraphSpacingAfter === void 0 ? void 0 : parsePointValue(props.paragraphSpacingAfter, 0, textLengthContext),
7344
8342
  ...props.textIndent === void 0 ? {} : { textIndentPt: parsePointValue(props.textIndent, 0, textLengthContext) },
7345
8343
  ...tabStops ? { tabStops } : {},
7346
- charSpacing: props.charSpacing,
8344
+ charSpacing: resolveCharacterSpacing(props.charSpacing, textLengthContext),
7347
8345
  ...list ? { list } : {},
7348
8346
  fit: props.fit,
7349
8347
  wrap: props.wrap,
@@ -7356,24 +8354,21 @@ function textStyleFromProps$1(props, textLengthContext) {
7356
8354
  function isEmptyRunStyle(style) {
7357
8355
  return Object.values(style).every((value) => value === void 0);
7358
8356
  }
7359
- function flattenJsxChildren(children) {
7360
- return children.flatMap((child) => Array.isArray(child) ? flattenJsxChildren(child) : [child]);
8357
+ function flattenTextChildren(children) {
8358
+ return children.flatMap((child) => Array.isArray(child) ? flattenTextChildren(child) : [child]);
7361
8359
  }
7362
8360
  function extractRichTextRuns(children, textTransform, textLengthContext) {
7363
8361
  const runs = [];
7364
- for (const child of flattenJsxChildren(children)) {
7365
- if (child === null || child === void 0 || child === false || child === true) continue;
8362
+ for (const child of flattenTextChildren(children)) {
7366
8363
  if (typeof child === "string" || typeof child === "number") {
7367
8364
  runs.push({ text: extractText([child], textTransform) });
7368
8365
  continue;
7369
8366
  }
7370
- if (isAuthorNode(child)) {
7371
- const authorNode = child;
7372
- if (authorNode.kind !== "text") throw new Error("Text nodes can only contain primitive text or inline text runs.");
7373
- const props = normalizeTextProps(authorNode.props);
8367
+ if (isLayoutInputTextNode(child)) {
8368
+ const props = normalizeTextProps(child.props);
7374
8369
  const childLengthContext = getTextLengthContext(props, textLengthContext);
7375
8370
  const style = textStyleFromProps$1(props, childLengthContext);
7376
- const text = extractRichTextRuns(authorNode.children, props.textTransform ?? textTransform, childLengthContext).map((run) => run.text).join("");
8371
+ const text = extractRichTextRuns(child.children, props.textTransform ?? textTransform, childLengthContext).map((run) => run.text).join("");
7377
8372
  runs.push({
7378
8373
  text,
7379
8374
  ...!isEmptyRunStyle(style) ? { style } : {}
@@ -7396,10 +8391,66 @@ function clippingMetadata(originalFrame, clipRect, visibleFrame) {
7396
8391
  visibleFrame
7397
8392
  };
7398
8393
  }
8394
+ function textFramePropsWithFallback(props, placement, context) {
8395
+ let resolved = props;
8396
+ const hasAuthoredWidth = authoredLengthOrUndefined(props.width) !== void 0;
8397
+ const hasAuthoredHeight = authoredLengthOrUndefined(props.height) !== void 0;
8398
+ const hasAuthoredInset = props.inset !== void 0 && !hasCssWideKeywordToken(props.inset);
8399
+ const hasAuthoredLeft = authoredLengthOrUndefined(props.left) !== void 0;
8400
+ const hasAuthoredRight = authoredLengthOrUndefined(props.right) !== void 0;
8401
+ const hasAuthoredTop = authoredLengthOrUndefined(props.top) !== void 0;
8402
+ const hasAuthoredBottom = authoredLengthOrUndefined(props.bottom) !== void 0;
8403
+ const hasAuthoredX = authoredLengthOrUndefined(props.x) !== void 0;
8404
+ if (placement?.widthEmu === void 0 && !hasAuthoredWidth && !hasAuthoredInset) {
8405
+ if (!hasAuthoredRight && (hasAuthoredX || hasAuthoredLeft)) resolved = {
8406
+ ...resolved,
8407
+ right: 0
8408
+ };
8409
+ else if (!hasAuthoredLeft && hasAuthoredRight) resolved = {
8410
+ ...resolved,
8411
+ left: 0
8412
+ };
8413
+ else if (!hasAuthoredLeft && !hasAuthoredRight) resolved = {
8414
+ ...resolved,
8415
+ width: "100%"
8416
+ };
8417
+ }
8418
+ if (placement?.heightEmu === void 0 && !hasAuthoredHeight && !hasAuthoredInset && !(hasAuthoredTop && hasAuthoredBottom)) resolved = {
8419
+ ...resolved,
8420
+ height: `${resolveTextLineHeightPt(props, context)}pt`
8421
+ };
8422
+ return resolved;
8423
+ }
8424
+ function usesTextLineHeightFallback(props, placement) {
8425
+ const hasAuthoredHeight = authoredLengthOrUndefined(props.height) !== void 0;
8426
+ const hasAuthoredInset = props.inset !== void 0 && !hasCssWideKeywordToken(props.inset);
8427
+ const hasAuthoredTop = authoredLengthOrUndefined(props.top) !== void 0;
8428
+ const hasAuthoredBottom = authoredLengthOrUndefined(props.bottom) !== void 0;
8429
+ return placement?.heightEmu === void 0 && !hasAuthoredHeight && !hasAuthoredInset && !(hasAuthoredTop && hasAuthoredBottom);
8430
+ }
8431
+ function textMayNeedWrappedMeasurement(text, props) {
8432
+ if (!text || props.wrap === false) return false;
8433
+ return text.includes("\n") || text.trim().length > 80;
8434
+ }
8435
+ function unsupportedWrappedTextMeasurementSemantics(input) {
8436
+ if (!usesTextLineHeightFallback(input.props, input.placement) || !textMayNeedWrappedMeasurement(input.text, input.props)) return [];
8437
+ const semantic = unsupportedSemantic({
8438
+ feature: "layout",
8439
+ property: "height",
8440
+ value: "auto",
8441
+ 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."),
8442
+ fallback: {
8443
+ strategy: "preserveAuthoredValueOnly",
8444
+ preserves: ["availableInlineSize", "lineHeightAutoHeight"],
8445
+ missing: ["wrappedTextMeasurement"]
8446
+ }
8447
+ });
8448
+ return semantic ? [semantic] : [];
8449
+ }
7399
8450
  function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, context) {
7400
8451
  const { props } = node;
7401
8452
  const textLengthContext = getTextLengthContext(props, context);
7402
- const resolved = frameFromProps(props, parentFrame, placement, textLengthContext);
8453
+ const resolved = frameFromProps(textFramePropsWithFallback(props, placement, textLengthContext), parentFrame, placement, textLengthContext);
7403
8454
  const strokes = resolveNodeStrokesOrFallback(props, textLengthContext);
7404
8455
  const shadow = parseShadowShorthandOrIgnore({
7405
8456
  property: props.textShadow !== void 0 ? "textShadow" : "boxShadow",
@@ -7412,6 +8463,7 @@ function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, co
7412
8463
  } : void 0;
7413
8464
  const style = textStyleFromProps$1(props, textLengthContext);
7414
8465
  const runs = extractRichTextRuns(node.source.children, props.textTransform, textLengthContext);
8466
+ const text = runs.map((run) => run.text).join("");
7415
8467
  const originalFrame = {
7416
8468
  xEmu: resolved.xEmu,
7417
8469
  yEmu: resolved.yEmu,
@@ -7420,13 +8472,15 @@ function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, co
7420
8472
  };
7421
8473
  const visibleFrame = intersectClipRect(originalFrame, clipRect);
7422
8474
  if (!visibleFrame) return null;
7423
- const backgroundBoxFrames = resolveBackgroundBoxFrames(visibleFrame, strokes.stroke, strokes.edgeStrokes, parseSpacing(props.padding, textLengthContext));
8475
+ const backgroundBoxFrames = resolveBackgroundBoxFrames(visibleFrame, strokes.stroke, strokes.edgeStrokes, parseSpacing(props.padding, textLengthContext, visibleFrame.widthEmu));
7424
8476
  const backgroundFill = resolveBackgroundLayersOrEmpty(backgroundInput(props), props.backgroundTransparency, {
7425
8477
  widthEmu: visibleFrame.widthEmu,
7426
8478
  heightEmu: visibleFrame.heightEmu
7427
8479
  }, visibleFrame, backgroundBoxFrames, props.backgroundPosition, props.backgroundSize, props.backgroundRepeat, props.backgroundOrigin, props.backgroundClip);
7428
8480
  const clip = clippingMetadata(originalFrame, clipRect, visibleFrame);
7429
8481
  const unsupportedSemantics = [
8482
+ ...unsupportedCssLayoutValueSemantics(props),
8483
+ ...unsupportedTextLogicalLayoutSemantics(props),
7430
8484
  ...unsupportedTransformSemantics$1(props),
7431
8485
  ...unsupportedCompositingSemantics$1(props),
7432
8486
  ...unsupportedOpacityStackingContextSemantics$1(props),
@@ -7436,6 +8490,11 @@ function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, co
7436
8490
  flipH: resolved.flipH,
7437
8491
  flipV: resolved.flipV
7438
8492
  }),
8493
+ ...unsupportedWrappedTextMeasurementSemantics({
8494
+ props,
8495
+ placement,
8496
+ text
8497
+ }),
7439
8498
  ...strokes.unsupportedSemantics,
7440
8499
  ...outline.unsupportedSemantics,
7441
8500
  ...shadow.unsupportedSemantics,
@@ -7456,7 +8515,7 @@ function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, co
7456
8515
  flipV: resolved.flipV,
7457
8516
  ...unsupportedSemantics.length ? { unsupportedSemantics } : {},
7458
8517
  content: {
7459
- text: runs.map((run) => run.text).join(""),
8518
+ text,
7460
8519
  ...runs.length > 1 || runs.some((run) => run.style) ? { runs } : {}
7461
8520
  },
7462
8521
  style,
@@ -7467,11 +8526,12 @@ function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, co
7467
8526
  ...outline.outline ? { outline: outline.outline } : {},
7468
8527
  ...shadow.shadow ? { shadow: shadow.shadow } : {},
7469
8528
  ...hyperlink ? { hyperlink } : {},
7470
- radiusEmu: parseLength(props.borderRadius, 0, 0, textLengthContext)
8529
+ radiusEmu: resolveCornerRadiusEmu$1(props.borderRadius, visibleFrame, textLengthContext)
7471
8530
  };
7472
8531
  }
7473
8532
  function compileImageNode(node, parentFrame, idGenerator, placement, clipRect, context) {
7474
8533
  const { props } = node;
8534
+ const fit = normalizeProjectedImageFit(props.fit);
7475
8535
  const resolved = frameFromProps(props, parentFrame, placement, context);
7476
8536
  const shadow = parseShadowShorthandOrIgnore({
7477
8537
  property: "boxShadow",
@@ -7497,6 +8557,7 @@ function compileImageNode(node, parentFrame, idGenerator, placement, clipRect, c
7497
8557
  if (!visibleFrame) return null;
7498
8558
  const clip = clippingMetadata(originalFrame, clipRect, visibleFrame);
7499
8559
  const unsupportedSemantics = [
8560
+ ...unsupportedCssLayoutValueSemantics(props),
7500
8561
  ...unsupportedTransformSemantics$1(props),
7501
8562
  ...unsupportedCompositingSemantics$1(props),
7502
8563
  ...unsupportedOpacityStackingContextSemantics$1(props),
@@ -7511,9 +8572,14 @@ function compileImageNode(node, parentFrame, idGenerator, placement, clipRect, c
7511
8572
  rotation: resolved.rotation,
7512
8573
  flipH: resolved.flipH,
7513
8574
  flipV: resolved.flipV,
7514
- fit: props.fit,
8575
+ fit,
7515
8576
  hasExplicitCrop: crop !== void 0
7516
8577
  }),
8578
+ ...unsupportedObjectPositionSemantics({
8579
+ value: props.objectPosition,
8580
+ resolved: objectPosition
8581
+ }),
8582
+ ...unsupportedObjectFitSemantics(props.fit),
7517
8583
  ...shadow.unsupportedSemantics
7518
8584
  ];
7519
8585
  return {
@@ -7531,7 +8597,7 @@ function compileImageNode(node, parentFrame, idGenerator, placement, clipRect, c
7531
8597
  flipH: resolved.flipH,
7532
8598
  flipV: resolved.flipV,
7533
8599
  ...unsupportedSemantics.length ? { unsupportedSemantics } : {},
7534
- fit: props.fit ?? "contain",
8600
+ fit,
7535
8601
  ...objectPosition ? { objectPosition } : {},
7536
8602
  ...crop ? { crop } : {},
7537
8603
  transparency: normalizeTransparency$1(props.transparency),
@@ -7569,6 +8635,7 @@ function compileShapeNode(node, parentFrame, idGenerator, placement, clipRect, c
7569
8635
  }, visibleFrame, backgroundBoxFrames, props.backgroundPosition, props.backgroundSize, props.backgroundRepeat, props.backgroundOrigin, props.backgroundClip);
7570
8636
  const clip = clippingMetadata(originalFrame, clipRect, visibleFrame);
7571
8637
  const unsupportedSemantics = [
8638
+ ...unsupportedCssLayoutValueSemantics(props),
7572
8639
  ...unsupportedTransformSemantics$1(props),
7573
8640
  ...unsupportedCompositingSemantics$1(props),
7574
8641
  ...unsupportedOpacityStackingContextSemantics$1(props),
@@ -7605,7 +8672,7 @@ function compileShapeNode(node, parentFrame, idGenerator, placement, clipRect, c
7605
8672
  ...outline.outline ? { outline: outline.outline } : {},
7606
8673
  ...shadow.shadow ? { shadow: shadow.shadow } : {},
7607
8674
  ...hyperlink ? { hyperlink } : {},
7608
- radiusEmu: parseLength(props.radius, 0, 0, context)
8675
+ radiusEmu: resolveCornerRadiusEmu$1(props.radius, visibleFrame, context)
7609
8676
  };
7610
8677
  }
7611
8678
  function compileNode(child, parentFrame, idGenerator, placement, clipRect, context, resolutionOptions) {
@@ -7616,32 +8683,38 @@ function compileNode(child, parentFrame, idGenerator, placement, clipRect, conte
7616
8683
  case "shape": return compileShapeNode(child, parentFrame, idGenerator, placement, clipRect, context);
7617
8684
  }
7618
8685
  }
7619
- function compileSlide(root, context, slideFrame, idGenerator, lengthContext, resolutionOptions) {
7620
- if (!isSlideNode(root)) throw new Error(`Slide factory at index ${context.slideIndex} must resolve to a slide node.`);
8686
+ function compileSlide(root, context, slideFrame, idGenerator, lengthContext) {
7621
8687
  const slideProps = normalizeSlideProps(root.props);
7622
8688
  const backgroundBoxFrames = resolveBackgroundBoxFrames(slideFrame);
7623
8689
  const backgroundFill = resolveBackgroundLayersOrEmpty(backgroundInput(slideProps), slideProps.backgroundTransparency, {
7624
8690
  widthEmu: slideFrame.widthEmu,
7625
8691
  heightEmu: slideFrame.heightEmu
7626
8692
  }, slideFrame, backgroundBoxFrames, slideProps.backgroundPosition, slideProps.backgroundSize, slideProps.backgroundRepeat, slideProps.backgroundOrigin, slideProps.backgroundClip);
7627
- const nodes = root.children.filter((child) => child !== null && child !== void 0 && child !== false && child !== true).filter(isContentNode).map((child, siblingOrder) => layoutChildFromNode(child, siblingOrder, lengthContext, resolutionOptions)).filter((child) => child.props.display !== "none").map((child) => compileNode(child, slideFrame, idGenerator, void 0, void 0, lengthContext, resolutionOptions)).filter((node) => node !== null);
8693
+ const nodes = compileAbsoluteChildren(root.children.map((child, siblingOrder) => layoutChildFromNode(child, siblingOrder, lengthContext)).filter((child) => child.props.display !== "none"), slideFrame, idGenerator, {
8694
+ padding: void 0,
8695
+ gap: void 0,
8696
+ rowGap: void 0,
8697
+ columnGap: void 0
8698
+ }, void 0, lengthContext);
7628
8699
  return {
7629
8700
  id: idGenerator.nextSlide(),
7630
8701
  name: slideProps.name,
8702
+ ...root.origin ? { origin: root.origin } : {},
7631
8703
  background: backgroundFill.fill,
7632
8704
  ...backgroundFill.backgroundLayers ? { backgroundLayers: backgroundFill.backgroundLayers } : {},
7633
- nodes: sortNodesForPaint(nodes)
8705
+ nodes
7634
8706
  };
7635
8707
  }
7636
- function resolveProjectedLayout(options, slides, resolutionOptions = {}) {
8708
+ function resolveProjectedLayout(options, input) {
7637
8709
  const idGenerator = createIdGenerator();
7638
- const slideSize = options.layout.unit === "in" ? {
8710
+ const slideSize = input.size ? input.size : options.layout.unit === "in" ? {
7639
8711
  widthEmu: options.layout.width * EMU_PER_INCH,
7640
8712
  heightEmu: options.layout.height * EMU_PER_INCH
7641
8713
  } : {
7642
8714
  widthEmu: options.layout.width / 72 * EMU_PER_INCH,
7643
8715
  heightEmu: options.layout.height / 72 * EMU_PER_INCH
7644
8716
  };
8717
+ const slideMeta = input.meta ?? options.meta;
7645
8718
  const slideFrame = {
7646
8719
  xEmu: 0,
7647
8720
  yEmu: 0,
@@ -7653,194 +8726,14 @@ function resolveProjectedLayout(options, slides, resolutionOptions = {}) {
7653
8726
  viewportHeightEmu: slideFrame.heightEmu
7654
8727
  };
7655
8728
  return {
7656
- version: "layout-snapshot/0.6",
7657
- meta: options.meta,
8729
+ ...slideMeta ? { meta: slideMeta } : {},
7658
8730
  size: slideSize,
7659
- slides: slides.map((factory, slideIndex) => {
7660
- return compileSlide(toAuthorJsxNode(factory({ composition: {
7661
- slideIndex,
7662
- totalSlides: slides.length,
7663
- deckSlideIndex: slideIndex,
7664
- deckTotalSlides: slides.length
7665
- } })), { slideIndex }, slideFrame, idGenerator, lengthContext, resolutionOptions);
8731
+ slides: input.slides.map((slide, slideIndex) => {
8732
+ return compileSlide(slide, { slideIndex }, slideFrame, idGenerator, lengthContext);
7666
8733
  })
7667
8734
  };
7668
8735
  }
7669
8736
  //#endregion
7670
- //#region src/layout/graph.ts
7671
- function layoutSlideNode(props, children) {
7672
- return {
7673
- $$typeof: "deckjsx.author-node",
7674
- kind: "slide",
7675
- props,
7676
- children
7677
- };
7678
- }
7679
- function layoutViewNode(props, children) {
7680
- return {
7681
- $$typeof: "deckjsx.author-node",
7682
- kind: "view",
7683
- props,
7684
- children
7685
- };
7686
- }
7687
- function layoutTextNode(props, children) {
7688
- return {
7689
- $$typeof: "deckjsx.author-node",
7690
- kind: "text",
7691
- props,
7692
- children
7693
- };
7694
- }
7695
- function layoutImageNode(props) {
7696
- return {
7697
- $$typeof: "deckjsx.author-node",
7698
- kind: "image",
7699
- props,
7700
- children: []
7701
- };
7702
- }
7703
- function layoutShapeNode(props) {
7704
- return {
7705
- $$typeof: "deckjsx.author-node",
7706
- kind: "shape",
7707
- props,
7708
- children: []
7709
- };
7710
- }
7711
- function resolvedPropsFor(node, resolvedStyles) {
7712
- const resolved = resolvedStyles.get(node.id);
7713
- if (!resolved) return {};
7714
- return Object.fromEntries(Object.entries(resolved.properties).filter(([, property]) => property.source.layer !== "default").map(([key, property]) => [key, property.value]));
7715
- }
7716
- function sourceKeyForOrigin$2(source) {
7717
- return !source || source.kind === "root" ? "root" : source.sourceIdentity;
7718
- }
7719
- function propsWithTemplateAreaFrame(resolvedStyles, node, templates) {
7720
- const props = resolvedPropsFor(node, resolvedStyles);
7721
- const ref = node.templateAreaRef;
7722
- if (!ref) return props;
7723
- const frame = templates?.[ref.template]?.areas?.[ref.area]?.frame;
7724
- if (!frame) return props;
7725
- const resolved = resolvedStyles.get(node.id);
7726
- const frameProps = {};
7727
- if (resolved?.properties.x?.source.layer !== "style") frameProps.x = frame.x;
7728
- if (resolved?.properties.y?.source.layer !== "style") frameProps.y = frame.y;
7729
- if (resolved?.properties.width?.source.layer !== "style") frameProps.width = frame.width;
7730
- if (resolved?.properties.height?.source.layer !== "style") frameProps.height = frame.height;
7731
- return {
7732
- ...props,
7733
- ...frameProps
7734
- };
7735
- }
7736
- function templateAreaKindFor$1(node, templates) {
7737
- const ref = node.templateAreaRef;
7738
- if (!ref) return;
7739
- return templates?.[ref.template]?.areas?.[ref.area]?.kind ?? "generic";
7740
- }
7741
- function pushDefined(values, value) {
7742
- if (value !== void 0) values.push(value);
7743
- }
7744
- function collectTextOrigin(graph, node) {
7745
- const graphNodeIds = [node.id];
7746
- const styleEntityIds = [];
7747
- pushDefined(styleEntityIds, node.styleRef);
7748
- node.inlineChildren.forEach((childId) => {
7749
- const child = graph.nodes.get(childId);
7750
- if (!child) return;
7751
- graphNodeIds.push(child.id);
7752
- pushDefined(styleEntityIds, child.styleRef);
7753
- if (child.kind === "text") {
7754
- const nested = collectTextOrigin(graph, child);
7755
- graphNodeIds.push(...nested.graphNodeIds ?? []);
7756
- styleEntityIds.push(...nested.styleEntityIds ?? []);
7757
- }
7758
- });
7759
- return {
7760
- graphNodeIds: [...new Set(graphNodeIds)],
7761
- ...styleEntityIds.length > 0 ? { styleEntityIds: [...new Set(styleEntityIds)] } : {}
7762
- };
7763
- }
7764
- function layoutOriginFor(graph, node, templates) {
7765
- const templateAreaKind = templateAreaKindFor$1(node, templates);
7766
- if (node.kind === "text") return {
7767
- ...collectTextOrigin(graph, node),
7768
- ...node.origin.source ? { source: node.origin.source } : {},
7769
- ...node.templateAreaRef ? { templateAreaRef: node.templateAreaRef } : {},
7770
- ...templateAreaKind ? { templateAreaKind } : {}
7771
- };
7772
- return {
7773
- graphNodeIds: [node.id],
7774
- ...node.styleRef ? { styleEntityIds: [node.styleRef] } : {},
7775
- ...node.kind === "image" && node.assetRef ? { assetEntityIds: [node.assetRef] } : {},
7776
- ...node.origin.source ? { source: node.origin.source } : {},
7777
- ...node.templateAreaRef ? { templateAreaRef: node.templateAreaRef } : {},
7778
- ...templateAreaKind ? { templateAreaKind } : {}
7779
- };
7780
- }
7781
- function rememberOrigin(node, origin, origins) {
7782
- origins.set(node, origin);
7783
- return node;
7784
- }
7785
- function slideFactoryFor(slide) {
7786
- return () => slide;
7787
- }
7788
- function textChildrenFromGraph(graph, resolvedStyles, childIds, origins, templates) {
7789
- return childIds.flatMap((childId) => {
7790
- const child = graph.nodes.get(childId);
7791
- if (!child) return [];
7792
- if (child.kind === "textRun") return [rememberOrigin(layoutTextNode(resolvedPropsFor(child, resolvedStyles), [child.text]), layoutOriginFor(graph, child, templates), origins)];
7793
- if (child.kind === "text") return textChildrenFromGraph(graph, resolvedStyles, child.inlineChildren, origins, templates);
7794
- return [];
7795
- });
7796
- }
7797
- function contentChildrenFromGraph(graph, resolvedStyles, childIds, origins, templates) {
7798
- return childIds.flatMap((childId) => {
7799
- const child = graph.nodes.get(childId);
7800
- if (!child) return [];
7801
- const node = layoutAuthorNodeFromGraph(graph, resolvedStyles, child, origins, templates);
7802
- return node ? [node] : [];
7803
- });
7804
- }
7805
- function layoutAuthorNodeFromGraph(graph, resolvedStyles, node, origins, templates) {
7806
- switch (node.kind) {
7807
- case "slide": {
7808
- const props = propsWithTemplateAreaFrame(resolvedStyles, node, templates);
7809
- const slideTemplates = graph.templates.get(sourceKeyForOrigin$2(node.origin.source));
7810
- return rememberOrigin(layoutSlideNode({
7811
- ...props,
7812
- name: node.name
7813
- }, contentChildrenFromGraph(graph, resolvedStyles, node.children, origins, slideTemplates)), layoutOriginFor(graph, node, slideTemplates), origins);
7814
- }
7815
- case "container": return rememberOrigin(layoutViewNode(propsWithTemplateAreaFrame(resolvedStyles, node, templates), contentChildrenFromGraph(graph, resolvedStyles, node.children, origins, templates)), layoutOriginFor(graph, node, templates), origins);
7816
- case "text": return rememberOrigin(layoutTextNode(propsWithTemplateAreaFrame(resolvedStyles, node, templates), textChildrenFromGraph(graph, resolvedStyles, node.inlineChildren, origins, templates)), layoutOriginFor(graph, node, templates), origins);
7817
- case "image": {
7818
- const props = propsWithTemplateAreaFrame(resolvedStyles, node, templates);
7819
- const asset = node.assetRef ? graph.assets.get(node.assetRef) : void 0;
7820
- if (!asset) return;
7821
- if (asset.source.kind === "data") return rememberOrigin(layoutImageNode({
7822
- ...props,
7823
- data: asset.source.data
7824
- }), layoutOriginFor(graph, node, templates), origins);
7825
- return rememberOrigin(layoutImageNode({
7826
- ...props,
7827
- src: asset.source.kind === "path" ? asset.source.path : asset.source.url
7828
- }), layoutOriginFor(graph, node, templates), origins);
7829
- }
7830
- case "shape": return rememberOrigin(layoutShapeNode({
7831
- ...propsWithTemplateAreaFrame(resolvedStyles, node, templates),
7832
- shape: node.shape
7833
- }), layoutOriginFor(graph, node, templates), origins);
7834
- case "document":
7835
- case "textRun": return;
7836
- }
7837
- }
7838
- function resolveProjectedLayoutFromGraph(options, graph, resolvedStyles) {
7839
- const origins = /* @__PURE__ */ new WeakMap();
7840
- const document = graph.nodes.get(graph.documentId);
7841
- return resolveProjectedLayout(options, (document?.kind === "document" ? document.children.map((id) => graph.nodes.get(id)).filter((node) => node?.kind === "slide") : []).map((node) => layoutAuthorNodeFromGraph(graph, resolvedStyles, node, origins)).filter((node) => node?.kind === "slide").map(slideFactoryFor), { origins });
7842
- }
7843
- //#endregion
7844
8737
  //#region src/projection/pptx/identity.ts
7845
8738
  const MAX_WRITER_SHAPE_OBJECT_ID = Number.MAX_SAFE_INTEGER - 1;
7846
8739
  function packagePartId(value) {
@@ -8524,24 +9417,23 @@ function shapeFillInputFor(resolved, props) {
8524
9417
  function errorReason(error) {
8525
9418
  return error instanceof Error ? error.message : String(error);
8526
9419
  }
8527
- function semanticValue(value) {
8528
- return typeof value === "string" ? value : JSON.stringify(value);
8529
- }
8530
- function unsupportedSemantic(input) {
8531
- if (input.value === void 0 || input.value === null || input.value === "") return;
8532
- return {
8533
- feature: input.feature,
8534
- property: input.property,
8535
- value: semanticValue(input.value),
8536
- reason: errorReason(input.error),
8537
- ...input.fallback ? { fallback: input.fallback } : {}
8538
- };
8539
- }
8540
9420
  function parseShadowSafely(input) {
8541
9421
  try {
9422
+ const shadow = parseShadowShorthand(input.value);
9423
+ const unsupported = hasShadowSpreadRadius(input.value) ? unsupportedSemantic({
9424
+ feature: "shadow",
9425
+ property: input.property,
9426
+ value: input.value,
9427
+ error: /* @__PURE__ */ new Error(`CSS shadow spread radius is not projected by the current PPTX shadow model: ${input.value}`),
9428
+ fallback: {
9429
+ strategy: "preserveAuthoredValueOnly",
9430
+ preserves: ["projectedShadowWithoutSpread"],
9431
+ missing: ["cssShadowSpreadRadius"]
9432
+ }
9433
+ }) : void 0;
8542
9434
  return {
8543
- shadow: parseShadowShorthand(input.value),
8544
- unsupportedSemantics: []
9435
+ shadow,
9436
+ unsupportedSemantics: unsupported ? [unsupported] : []
8545
9437
  };
8546
9438
  } catch (error) {
8547
9439
  const unsupported = unsupportedSemantic({
@@ -8630,6 +9522,27 @@ function isExplicitNone(value) {
8630
9522
  function isStrokeIntentionallyNone(props) {
8631
9523
  return isExplicitNone(props.border) || isExplicitNone(props.borderTop) || isExplicitNone(props.borderRight) || isExplicitNone(props.borderBottom) || isExplicitNone(props.borderLeft) || props.borderStyle === "none";
8632
9524
  }
9525
+ function unsupportedStrokeCssWideKeywordSemantics(props) {
9526
+ const unsupported = [];
9527
+ for (const property of [
9528
+ "borderWidth",
9529
+ "borderTopWidth",
9530
+ "borderRightWidth",
9531
+ "borderBottomWidth",
9532
+ "borderLeftWidth",
9533
+ "strokeWidth"
9534
+ ]) {
9535
+ if (!hasCssWideKeywordToken(props[property])) continue;
9536
+ const semantic = unsupportedCssWideKeywordSemantic(property, props[property]);
9537
+ if (semantic) unsupported.push(semantic);
9538
+ }
9539
+ return unsupported;
9540
+ }
9541
+ function unsupportedOutlineCssWideKeywordSemantics(props) {
9542
+ if (!hasCssWideKeywordToken(props.outlineWidth)) return [];
9543
+ const semantic = unsupportedCssWideKeywordSemantic("outlineWidth", props.outlineWidth);
9544
+ return semantic ? [semantic] : [];
9545
+ }
8633
9546
  function unsupportedStrokeFallback(props, error) {
8634
9547
  const input = strokeFallbackInput(props);
8635
9548
  return unsupportedSemantic({
@@ -8645,32 +9558,34 @@ function unsupportedStrokeFallback(props, error) {
8645
9558
  });
8646
9559
  }
8647
9560
  function resolveNodeStrokesSafely(props, context) {
9561
+ const cssWideSemantics = unsupportedStrokeCssWideKeywordSemantics(props);
8648
9562
  try {
8649
9563
  const strokes = resolveNodeStrokes(props, context);
8650
9564
  if (!strokes.stroke && !strokes.edgeStrokes && hasAuthoredStrokeInput(props) && !isStrokeIntentionallyNone(props)) {
8651
9565
  const semantic = unsupportedStrokeFallback(props, /* @__PURE__ */ new Error("No PPTX stroke could be produced from the authored stroke input."));
8652
9566
  return {
8653
9567
  ...strokes,
8654
- unsupportedSemantics: semantic ? [semantic] : []
9568
+ unsupportedSemantics: semantic ? [semantic, ...cssWideSemantics] : cssWideSemantics
8655
9569
  };
8656
9570
  }
8657
9571
  return {
8658
9572
  ...strokes,
8659
- unsupportedSemantics: []
9573
+ unsupportedSemantics: cssWideSemantics
8660
9574
  };
8661
9575
  } catch (error) {
8662
9576
  const semantic = unsupportedStrokeFallback(props, error);
8663
- return { unsupportedSemantics: semantic ? [semantic] : [] };
9577
+ return { unsupportedSemantics: semantic ? [semantic, ...cssWideSemantics] : cssWideSemantics };
8664
9578
  }
8665
9579
  }
8666
9580
  function outlineStrokeSafely(props, context) {
8667
9581
  if (!hasAuthoredOutlineInput(props)) return { unsupportedSemantics: [] };
9582
+ const cssWideSemantics = unsupportedOutlineCssWideKeywordSemantics(props);
8668
9583
  try {
8669
9584
  const outlineInput = parseOutlineShorthand(props.outline);
8670
9585
  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);
8671
9586
  if (outline) return {
8672
9587
  outline,
8673
- unsupportedSemantics: []
9588
+ unsupportedSemantics: cssWideSemantics
8674
9589
  };
8675
9590
  const input = outlineFallbackInput(props);
8676
9591
  const semantic = unsupportedSemantic({
@@ -8684,7 +9599,7 @@ function outlineStrokeSafely(props, context) {
8684
9599
  missing: ["pptxOutline"]
8685
9600
  }
8686
9601
  });
8687
- return { unsupportedSemantics: semantic ? [semantic] : [] };
9602
+ return { unsupportedSemantics: semantic ? [semantic, ...cssWideSemantics] : cssWideSemantics };
8688
9603
  } catch (error) {
8689
9604
  const input = outlineFallbackInput(props);
8690
9605
  const semantic = unsupportedSemantic({
@@ -8698,7 +9613,7 @@ function outlineStrokeSafely(props, context) {
8698
9613
  missing: ["pptxOutline"]
8699
9614
  }
8700
9615
  });
8701
- return { unsupportedSemantics: semantic ? [semantic] : [] };
9616
+ return { unsupportedSemantics: semantic ? [semantic, ...cssWideSemantics] : cssWideSemantics };
8702
9617
  }
8703
9618
  }
8704
9619
  function unsupportedTransformSemantics(props) {
@@ -9152,6 +10067,9 @@ function parseObjectPositionValue(objectPosition, frame) {
9152
10067
  y: axisValue(yToken, frame.heightEmu)
9153
10068
  };
9154
10069
  }
10070
+ function resolveCornerRadiusEmu(value, frame, context) {
10071
+ return parseLength(value, Math.min(frame.widthEmu, frame.heightEmu), 0, context);
10072
+ }
9155
10073
  function textStyleFromProps(props, textLengthContext) {
9156
10074
  const list = resolveListStyle(props, textLengthContext);
9157
10075
  const lineHeight = resolveLineHeight(props.lineHeight, textLengthContext);
@@ -9175,11 +10093,11 @@ function textStyleFromProps(props, textLengthContext) {
9175
10093
  paddingPt: parseSpacingInPoints(props.padding, textLengthContext),
9176
10094
  lineSpacing: props.lineSpacing ?? lineHeight.lineSpacing,
9177
10095
  lineSpacingMultiple: props.lineSpacingMultiple ?? lineHeight.lineSpacingMultiple,
9178
- paragraphSpacingBefore: props.paragraphSpacingBefore,
9179
- paragraphSpacingAfter: props.paragraphSpacingAfter,
10096
+ paragraphSpacingBefore: props.paragraphSpacingBefore === void 0 ? void 0 : parsePointValue(props.paragraphSpacingBefore, 0, textLengthContext),
10097
+ paragraphSpacingAfter: props.paragraphSpacingAfter === void 0 ? void 0 : parsePointValue(props.paragraphSpacingAfter, 0, textLengthContext),
9180
10098
  ...props.textIndent === void 0 ? {} : { textIndentPt: parsePointValue(props.textIndent, 0, textLengthContext) },
9181
10099
  ...tabStops ? { tabStops } : {},
9182
- charSpacing: props.charSpacing,
10100
+ charSpacing: resolveCharacterSpacing(props.charSpacing, textLengthContext),
9183
10101
  ...list ? { list } : {},
9184
10102
  fit: props.fit ?? DEFAULT_TEXT_FIT,
9185
10103
  wrap: props.wrap ?? DEFAULT_TEXT_WRAP,
@@ -9444,7 +10362,7 @@ function compileContainer(graph, resolvedStyles, node, templates, packagePartIdV
9444
10362
  ...outlineResult.outline ? { outline: outlineResult.outline } : {},
9445
10363
  ...generatedStrokes ? { generatedStrokes } : {},
9446
10364
  ...shadowResult.shadow ? { shadow: shadowResult.shadow } : {},
9447
- radiusEmu: parseLength(props.borderRadius, 0, 0, context),
10365
+ radiusEmu: resolveCornerRadiusEmu(props.borderRadius, frame, context),
9448
10366
  children: compileChildren(graph, resolvedStyles, node.children, templates, packagePartIdValue, frame, indexPath, context)
9449
10367
  };
9450
10368
  }
@@ -9523,7 +10441,7 @@ function compileText(graph, resolvedStyles, node, templates, packagePartIdValue,
9523
10441
  ...generatedStrokes ? { generatedStrokes } : {},
9524
10442
  ...shadowResult.shadow ? { shadow: shadowResult.shadow } : {},
9525
10443
  ...hyperlink ? { hyperlink } : {},
9526
- radiusEmu: parseLength(props.borderRadius, 0, 0, textLengthContext)
10444
+ radiusEmu: resolveCornerRadiusEmu(props.borderRadius, frame, textLengthContext)
9527
10445
  };
9528
10446
  }
9529
10447
  function compileImage(graph, resolvedStyles, node, templates, packagePartIdValue, parentFrame, indexPath, context) {
@@ -9536,6 +10454,7 @@ function compileImage(graph, resolvedStyles, node, templates, packagePartIdValue
9536
10454
  }, context);
9537
10455
  if (props.display === "none") return;
9538
10456
  const frame = frameToFrameIR$1(frameFromProps(props, parentFrame, void 0, context));
10457
+ const fit = normalizeProjectedImageFit(props.fit);
9539
10458
  const shadowResult = parseShadowSafely({
9540
10459
  property: "boxShadow",
9541
10460
  value: props.boxShadow
@@ -9555,6 +10474,7 @@ function compileImage(graph, resolvedStyles, node, templates, packagePartIdValue
9555
10474
  ...unsupportedTransformSemantics(props),
9556
10475
  ...unsupportedCompositingSemantics(props),
9557
10476
  ...unsupportedOpacityStackingContextSemantics(props),
10477
+ ...unsupportedObjectFitSemantics(props.fit),
9558
10478
  ...shadowResult.unsupportedSemantics
9559
10479
  ]
9560
10480
  });
@@ -9564,7 +10484,7 @@ function compileImage(graph, resolvedStyles, node, templates, packagePartIdValue
9564
10484
  mediaPartId: mediaPartIdForElement(base.id),
9565
10485
  sourceFrame: frame,
9566
10486
  source: assetSource(asset),
9567
- fit: props.fit ?? "contain",
10487
+ fit,
9568
10488
  objectPosition: parseObjectPositionValue(props.objectPosition, frame),
9569
10489
  ...parseImageCrop(props.crop) ? { crop: parseImageCrop(props.crop) } : {},
9570
10490
  transparency: props.transparency,
@@ -9641,7 +10561,7 @@ function compileShape(node, resolvedStyles, templates, packagePartIdValue, paren
9641
10561
  ...generatedStrokes ? { generatedStrokes } : {},
9642
10562
  ...shadowResult.shadow ? { shadow: shadowResult.shadow } : {},
9643
10563
  ...hyperlink ? { hyperlink } : {},
9644
- radiusEmu: parseLength(props.radius, 0, 0, context)
10564
+ radiusEmu: resolveCornerRadiusEmu(props.radius, frame, context)
9645
10565
  };
9646
10566
  }
9647
10567
  function compileElement(input) {
@@ -9688,9 +10608,6 @@ function compileChildrenPartial(graph, resolvedStyles, children, templates, pack
9688
10608
  });
9689
10609
  return elements.sort(comparePptxElementsByPaintOrder);
9690
10610
  }
9691
- function graphNodeForElement(graph, nodeId) {
9692
- return nodeId ? graph.nodes.get(nodeId) : void 0;
9693
- }
9694
10611
  function elementOriginFromLayoutOrigin(origin) {
9695
10612
  return {
9696
10613
  ...origin?.graphNodeIds ? { graphNodeIds: origin.graphNodeIds } : {},
@@ -9701,7 +10618,6 @@ function elementOriginFromLayoutOrigin(origin) {
9701
10618
  }
9702
10619
  function mapProjectedLayoutNodeToElement(input) {
9703
10620
  const graphNodeId = input.node.origin?.graphNodeIds?.[0];
9704
- const graphNode = graphNodeForElement(input.graph, graphNodeId);
9705
10621
  const layoutAnchor = layoutAnchorFor({
9706
10622
  templateAreaRef: input.node.origin?.templateAreaRef,
9707
10623
  templateAreaKind: input.node.origin?.templateAreaKind,
@@ -9715,7 +10631,7 @@ function mapProjectedLayoutNodeToElement(input) {
9715
10631
  }),
9716
10632
  packagePartId: input.packagePartId,
9717
10633
  serialized: { shapeObjectId: shapeObjectId(input.indexPath) },
9718
- origin: input.node.origin ? elementOriginFromLayoutOrigin(input.node.origin) : graphNode ? originFor(graphNode) : {},
10634
+ origin: elementOriginFromLayoutOrigin(input.node.origin),
9719
10635
  frame: input.node.frame,
9720
10636
  measurement: { frame: input.node.frame },
9721
10637
  ...layoutAnchor ? { layoutAnchor } : {},
@@ -9762,7 +10678,6 @@ function mapProjectedLayoutNodeToElement(input) {
9762
10678
  radiusEmu: input.node.radiusEmu,
9763
10679
  children: input.node.children.map((child, index) => mapProjectedLayoutNodeToElement({
9764
10680
  node: child,
9765
- graph: input.graph,
9766
10681
  packagePartId: input.packagePartId,
9767
10682
  indexPath: [...input.indexPath, index]
9768
10683
  }))
@@ -9850,34 +10765,17 @@ function mapProjectedLayoutNodeToElement(input) {
9850
10765
  function pptxSlidePartFor(input) {
9851
10766
  const slideNumber = input.slideIndex + 1;
9852
10767
  const partId = input.slidePartId;
9853
- const resolved = resolvedStyleFor(input.slide, input.resolvedStyles);
9854
- const props = normalizeSlideProps(slideStyleFor(input.slide, input.resolvedStyles));
9855
- const slideTemplates = input.graph.templates.get(sourceKeyForOrigin$1(input.slide.origin.source));
9856
- const backgroundInput = backgroundInputFor(resolved, props);
9857
- const slideFill = resolveBackgroundLayersSafely({
9858
- property: backgroundInput?.property ?? "background",
9859
- value: backgroundInput?.value
9860
- }, props.backgroundTransparency, {
9861
- widthEmu: input.slideFrame.widthEmu,
9862
- heightEmu: input.slideFrame.heightEmu
9863
- }, input.slideFrame, {
9864
- borderBox: input.slideFrame,
9865
- paddingBox: input.slideFrame,
9866
- contentBox: input.slideFrame
9867
- }, props.backgroundPosition, props.backgroundSize, props.backgroundRepeat, props.backgroundOrigin, props.backgroundClip);
9868
10768
  const backgroundLayers = projectBackgroundLayers({
9869
- layers: input.layoutSlide?.backgroundLayers ?? slideFill.backgroundLayers,
10769
+ layers: input.layoutSlide.backgroundLayers,
9870
10770
  indexPath: [5e3 + input.slideIndex]
9871
10771
  });
10772
+ const origin = elementOriginFromLayoutOrigin(input.layoutSlide.origin);
9872
10773
  return {
9873
10774
  id: partId,
9874
10775
  category: "authored-content",
9875
10776
  kind: "slide",
9876
10777
  path: `ppt/slides/slide${slideNumber}.xml`,
9877
- origin: {
9878
- graphNodeIds: [input.slide.id],
9879
- ...input.slide.origin.source ? { source: input.slide.origin.source } : {}
9880
- },
10778
+ origin,
9881
10779
  relationships: [{
9882
10780
  id: serializedId("rId1"),
9883
10781
  target: projectedRelationshipTarget({
@@ -9890,18 +10788,14 @@ function pptxSlidePartFor(input) {
9890
10788
  }],
9891
10789
  payload: {
9892
10790
  slideId: String(256 + input.slideIndex),
9893
- name: input.slide.name,
9894
- background: input.layoutSlide?.background ?? slideFill.fill,
10791
+ name: input.layoutSlide.name,
10792
+ background: input.layoutSlide.background,
9895
10793
  ...backgroundLayers ? { backgroundLayers } : {},
9896
- drawing: drawingFromElements(input.layoutSlide ? input.layoutSlide.nodes.map((node, index) => mapProjectedLayoutNodeToElement({
10794
+ drawing: drawingFromElements(input.layoutSlide.nodes.map((node, index) => mapProjectedLayoutNodeToElement({
9897
10795
  node,
9898
- graph: input.graph,
9899
10796
  packagePartId: partId,
9900
10797
  indexPath: [index]
9901
- })) : compileChildren(input.graph, input.resolvedStyles, input.slide.children, slideTemplates, partId, input.slideFrame, [], {
9902
- viewportWidthEmu: input.slideFrame.widthEmu,
9903
- viewportHeightEmu: input.slideFrame.heightEmu
9904
- }))
10798
+ })))
9905
10799
  }
9906
10800
  };
9907
10801
  }
@@ -10748,7 +11642,15 @@ function projectGraphToPptxPackageInternal(input) {
10748
11642
  size,
10749
11643
  slideIds
10750
11644
  });
10751
- const projectedLayout = input.partial ? void 0 : resolveProjectedLayoutFromGraph(input.options, input.graph, input.resolvedStyles);
11645
+ const layoutInput = input.partial ? void 0 : buildLayoutInputSnapshot({
11646
+ graph: input.graph,
11647
+ resolvedStyles: input.resolvedStyles,
11648
+ assetProbeArtifacts: input.assets,
11649
+ deckSize: size,
11650
+ diagnostics: input.diagnostics,
11651
+ meta: input.options.meta
11652
+ });
11653
+ const projectedLayout = layoutInput ? resolveProjectedLayout(input.options, layoutInput.snapshot) : void 0;
10752
11654
  const slideFrame = {
10753
11655
  xEmu: 0,
10754
11656
  yEmu: 0,
@@ -10758,6 +11660,7 @@ function projectGraphToPptxPackageInternal(input) {
10758
11660
  const projectedSlidesWithMedia = withCanonicalImageMediaPartIds(slideIds.flatMap((slideId, slideIndex) => {
10759
11661
  const slide = input.graph.nodes.get(slideId);
10760
11662
  if (slide?.kind !== "slide") return [];
11663
+ const layoutSlide = projectedLayout?.slides[slideIndex];
10761
11664
  const partId = slidePartIdFor(slide);
10762
11665
  const slideLayoutPart = slideLayoutPartForSlide({
10763
11666
  graph: input.graph,
@@ -10765,7 +11668,7 @@ function projectGraphToPptxPackageInternal(input) {
10765
11668
  slideLayoutParts: supportParts.slideLayoutParts,
10766
11669
  defaultSlideLayoutPart: supportParts.slideLayoutPart
10767
11670
  });
10768
- return [input.partial ? partialPptxSlidePartFor({
11671
+ if (input.partial) return [partialPptxSlidePartFor({
10769
11672
  graph: input.graph,
10770
11673
  resolvedStyles: input.resolvedStyles,
10771
11674
  slide,
@@ -10773,11 +11676,10 @@ function projectGraphToPptxPackageInternal(input) {
10773
11676
  slideFrame,
10774
11677
  slideLayoutPart,
10775
11678
  slidePartId: partId
10776
- }) : pptxSlidePartFor({
10777
- graph: input.graph,
10778
- resolvedStyles: input.resolvedStyles,
10779
- slide,
10780
- layoutSlide: projectedLayout?.slides[slideIndex],
11679
+ })];
11680
+ if (!layoutSlide) return [];
11681
+ return [pptxSlidePartFor({
11682
+ layoutSlide,
10781
11683
  slideIndex,
10782
11684
  slideFrame,
10783
11685
  slideLayoutPart,
@@ -10907,7 +11809,7 @@ async function loadNodeOutputRuntime() {
10907
11809
  const status = nodeOutputRuntimeStatus();
10908
11810
  if (!status.ok) return status;
10909
11811
  try {
10910
- const { createNodeOutputByteSink, writeNodeOutput } = await import("./node-output-ChRpOCV8.mjs");
11812
+ const { createNodeOutputByteSink, writeNodeOutput } = await import("./node-output-L2bV2_8g.mjs");
10911
11813
  return {
10912
11814
  ok: true,
10913
11815
  createByteSink: createNodeOutputByteSink,
@@ -11651,21 +12553,11 @@ async function prepareRenderOutputSink(adapter) {
11651
12553
  path: output,
11652
12554
  runtime: outputRuntime
11653
12555
  };
11654
- try {
11655
- return {
11656
- requested: true,
11657
- mode: "sink",
11658
- path: output,
11659
- sink: outputRuntime.createByteSink({ output })
11660
- };
11661
- } catch (error) {
11662
- return {
11663
- requested: true,
11664
- mode: "sinkCreationFailed",
11665
- path: output,
11666
- error
11667
- };
11668
- }
12556
+ return {
12557
+ requested: true,
12558
+ mode: "deferredWrite",
12559
+ path: output
12560
+ };
11669
12561
  }
11670
12562
  async function writeRenderedArtifact(input) {
11671
12563
  if (!input.preparedOutput.requested) return {