deckjsx 0.8.1 → 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
1
  import { c as isAuthoredTag, i as createAuthorElement, o as isAuthorTreeChild, s as isAuthorTreeNode, t as authorElementPropsFromEntries } from "./tree-DNsco0U3.mjs";
2
- import { A as CompositionDiagnosticError, C as parsePointValue, D as POINTS_PER_INCH, E as EMU_PER_INCH, F as formatDiagnostics, M as SemanticGraphDiagnosticError, N as StyleDiagnosticError, O as createDiagnostics, P as formatDiagnostic, S as parsePointToken, T as pointsToEmu, _ as isDeckLengthString, a as isInspectableThemePayload, b as parseLengthToken, c as fingerprintString, d as createWriterRenderContext, f as createTemplateHandle, g as DEFAULT_FONT_SIZE_PT, h as validateSlideTemplates, i as isContentTypesPayload, j as DeckDiagnosticError, k as diagnostic, l as stableJson, m as templateRefValue, n as pptxMediaAssetLoadRequirements, o as isRecord$2, p as isTemplateAreaRef, r as validatePptxPackageModel, s as projectedRelationshipTarget, t as pptx, u as withPackagePartFingerprints, v as isDeckPointLengthString, w as parseStrokeWidth, x as parsePercentage$1, y as parseLength } from "./adapter-CNSvvD4i.mjs";
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");
@@ -628,7 +628,7 @@ const ELEMENT_DEFAULTS = {
628
628
  rotation: 0,
629
629
  zIndex: 0,
630
630
  overflow: "visible",
631
- position: "relative",
631
+ position: "static",
632
632
  boxSizing: "border-box",
633
633
  backgroundTransparency: 100,
634
634
  borderWidth: 0,
@@ -645,7 +645,7 @@ const ELEMENT_DEFAULTS = {
645
645
  rotation: 0,
646
646
  zIndex: 0,
647
647
  overflow: "visible",
648
- position: "relative",
648
+ position: "static",
649
649
  boxSizing: "border-box",
650
650
  backgroundTransparency: 100,
651
651
  borderWidth: 0,
@@ -705,7 +705,7 @@ const ELEMENT_DEFAULTS = {
705
705
  rotation: 0,
706
706
  zIndex: 0,
707
707
  overflow: "visible",
708
- position: "relative",
708
+ position: "static",
709
709
  fit: "contain",
710
710
  objectFit: "contain",
711
711
  objectPosition: "50% 50%",
@@ -720,7 +720,7 @@ const ELEMENT_DEFAULTS = {
720
720
  rotation: 0,
721
721
  zIndex: 0,
722
722
  overflow: "visible",
723
- position: "relative",
723
+ position: "static",
724
724
  boxSizing: "border-box",
725
725
  backgroundTransparency: 100,
726
726
  borderWidth: 0,
@@ -1274,6 +1274,17 @@ const VIEW_STYLE_KEYS = [
1274
1274
  "gridAutoRows",
1275
1275
  "gridAutoFlow"
1276
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
+ ];
1277
1288
  const TEXT_STYLE_KEYS = [
1278
1289
  ...VIEW_STYLE_KEYS,
1279
1290
  "fontFamily",
@@ -1543,11 +1554,45 @@ function applyProperties(style, source, properties) {
1543
1554
  };
1544
1555
  });
1545
1556
  }
1546
- 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) {
1547
1591
  const properties = {};
1548
1592
  const appliedClasses = [];
1549
1593
  const defaults = elementDefaultsFor(node);
1550
1594
  if (defaults) applyProperties(defaults, { layer: "default" }, properties);
1595
+ applyInheritedProperties(inherited.parentId, inherited.style, properties);
1551
1596
  const themeDefaults = node.authoredTag && theme ? themeInput(theme).defaults : void 0;
1552
1597
  const themeDefault = node.authoredTag ? themeDefaults?.[node.authoredTag] : void 0;
1553
1598
  if (node.authoredTag && themeDefault) applyProperties(themeDefault, {
@@ -1606,9 +1651,10 @@ function resolveStyles(graph, roots) {
1606
1651
  const stylesheets = classesBySource(roots);
1607
1652
  const themes = themesBySource(roots);
1608
1653
  const registries = /* @__PURE__ */ new Map();
1654
+ const parentById = parentMapFor$1(graph);
1609
1655
  const selectorContext = {
1610
1656
  graph,
1611
- parentById: parentMapFor$1(graph),
1657
+ parentById,
1612
1658
  classNamesByNodeId: classNamesByNodeIdFor(graph)
1613
1659
  };
1614
1660
  const resolvedStyles = /* @__PURE__ */ new Map();
@@ -1618,8 +1664,10 @@ function resolveStyles(graph, roots) {
1618
1664
  themes.forEach((theme, sourceKey) => {
1619
1665
  diagnostics.push(...sourceThemeDiagnostics(sourceKey, theme));
1620
1666
  });
1621
- graph.nodes.forEach((node) => {
1667
+ const resolveNode = (node) => {
1622
1668
  if (!isStyleCapableNode(node)) return;
1669
+ const existing = resolvedStyles.get(node.id);
1670
+ if (existing) return existing;
1623
1671
  const sourceKey = sourceKeyFor$2(node.origin.source);
1624
1672
  const entity = node.styleRef ? graph.styles.get(node.styleRef) : void 0;
1625
1673
  let registry = registries.get(sourceKey);
@@ -1627,7 +1675,18 @@ function resolveStyles(graph, roots) {
1627
1675
  registry = registerStylesheets(sourceKey, stylesheets.get(sourceKey), diagnostics);
1628
1676
  registries.set(sourceKey, registry);
1629
1677
  }
1630
- 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);
1631
1690
  });
1632
1691
  return {
1633
1692
  resolvedStyles,
@@ -2015,6 +2074,22 @@ function supportedPropNamesFor(node) {
2015
2074
  ]);
2016
2075
  }
2017
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
+ }
2018
2093
  function sourceFor(context) {
2019
2094
  return context.activeSlot?.source ?? context.source;
2020
2095
  }
@@ -2117,6 +2192,19 @@ function authoringPropDiagnostic(input) {
2117
2192
  ...input.help ? { help: input.help } : {}
2118
2193
  });
2119
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
+ }
2120
2208
  function validateAuthoringProps(state, node, path) {
2121
2209
  const supported = supportedPropNamesFor(node);
2122
2210
  const propPath = node.source.kind === "slide" ? `${path}.options` : `${path}.props`;
@@ -2134,6 +2222,18 @@ function validateAuthoringProps(state, node, path) {
2134
2222
  path: `${propPath}.style`,
2135
2223
  message: "The style prop must be an object when it is provided."
2136
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
+ }
2137
2237
  }
2138
2238
  if (isShapeElement(node) && node.props.shape !== void 0) {
2139
2239
  if (node.props.shape !== "rect" && node.props.shape !== "ellipse" && node.props.shape !== "line") addDiagnostic(state, authoringPropDiagnostic({
@@ -3188,7 +3288,7 @@ function pushDefined(values, value) {
3188
3288
  function resolvedPropsFor(node, resolvedStyles) {
3189
3289
  const resolved = resolvedStyles.get(node.id);
3190
3290
  if (!resolved) return {};
3191
- return Object.fromEntries(Object.entries(resolved.properties).filter(([, property]) => property.source.layer !== "default").map(([key, property]) => [key, property.value]));
3291
+ return Object.fromEntries(Object.entries(resolved.properties).filter(([, property]) => property.source.layer !== "default" && property.source.layer !== "inherited").map(([key, property]) => [key, property.value]));
3192
3292
  }
3193
3293
  function sourceKeyForOrigin$2(source) {
3194
3294
  return !source || source.kind === "root" ? "root" : source.sourceIdentity;
@@ -3913,16 +4013,120 @@ function resolveGridSelfAlignment(value) {
3913
4013
  return value;
3914
4014
  }
3915
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
3916
4036
  //#region src/layout/spacing.ts
3917
- 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) {
4076
+ if (value === void 0) return [
4077
+ 0,
4078
+ 0,
4079
+ 0,
4080
+ 0
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
+ }
4091
+ if (typeof value === "number" || typeof value === "string") {
4092
+ const scalar = parseLength(value, percentageBaseEmu, 0, context);
4093
+ return [
4094
+ scalar,
4095
+ scalar,
4096
+ scalar,
4097
+ scalar
4098
+ ];
4099
+ }
4100
+ return [
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) {
3918
4113
  if (value === void 0) return [
3919
4114
  0,
3920
4115
  0,
3921
4116
  0,
3922
4117
  0
3923
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
+ }
3924
4128
  if (typeof value === "number" || typeof value === "string") {
3925
- const scalar = parseLength(value, 0, 0, context);
4129
+ const scalar = parseLengthOrAuto(value, percentageBaseEmu, autoFallbackEmu, context);
3926
4130
  return [
3927
4131
  scalar,
3928
4132
  scalar,
@@ -3931,10 +4135,10 @@ function parseSpacing(value, context) {
3931
4135
  ];
3932
4136
  }
3933
4137
  return [
3934
- parseLength(value[0], 0, 0, context),
3935
- parseLength(value[1], 0, 0, context),
3936
- parseLength(value[2], 0, 0, context),
3937
- parseLength(value[3], 0, 0, context)
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)
3938
4142
  ];
3939
4143
  }
3940
4144
  function expandRawSpacing(value) {
@@ -3944,12 +4148,21 @@ function expandRawSpacing(value) {
3944
4148
  void 0,
3945
4149
  void 0
3946
4150
  ];
3947
- if (typeof value === "number" || typeof value === "string") return [
3948
- value,
3949
- value,
3950
- value,
3951
- value
3952
- ];
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
+ }
3953
4166
  return [
3954
4167
  value[0],
3955
4168
  value[1],
@@ -3977,9 +4190,9 @@ function resolveInset(value, top, right, bottom, left) {
3977
4190
  left: left ?? baseLeft
3978
4191
  };
3979
4192
  }
3980
- function parseSpacingInPoints(value, context) {
4193
+ function parseSpacingInPoints(value, context, percentageBaseEmu = 0) {
3981
4194
  if (value === void 0) return;
3982
- const spacing = parseSpacing(value, context);
4195
+ const spacing = parseSpacing(value, context, percentageBaseEmu);
3983
4196
  return [
3984
4197
  spacing[0] / EMU_PER_INCH * 72,
3985
4198
  spacing[1] / EMU_PER_INCH * 72,
@@ -5416,7 +5629,7 @@ function parseStrokeDasharray(value, context) {
5416
5629
  if (rawTokens.length === 0) return;
5417
5630
  const lengths = rawTokens.map((token) => {
5418
5631
  if (/^-?(?:\d+|\d*\.\d+)$/.test(token)) return Number.parseFloat(token);
5419
- if (/^-?(?:\d+|\d*\.\d+)(?:pt|in|px|em|rem|vh|vw|ch)$/i.test(token)) return parsePointToken(token, 0, context);
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);
5420
5633
  throw new Error(`Unsupported strokeDasharray token: ${token}`);
5421
5634
  });
5422
5635
  if (lengths.some((length) => !Number.isFinite(length) || length < 0)) throw new Error(`Unsupported strokeDasharray value: ${value}`);
@@ -5504,10 +5717,15 @@ function parseTextDecoration(value) {
5504
5717
  };
5505
5718
  }
5506
5719
  function resolveLineHeight(lineHeight, context) {
5507
- if (lineHeight === void 0 || lineHeight === "normal") return {};
5720
+ if (lineHeight === void 0 || lineHeight === "normal" || isCssWideKeyword(lineHeight)) return {};
5508
5721
  if (typeof lineHeight === "number") return { lineSpacingMultiple: lineHeight };
5509
5722
  return { lineSpacing: parsePointValue(lineHeight, 0, context) };
5510
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
+ }
5511
5729
  function resolveTextWrap(wrap, whiteSpace, wordBreak, overflowWrap) {
5512
5730
  if (wrap !== void 0) return wrap;
5513
5731
  if (wordBreak === "break-all" || wordBreak === "break-word") return true;
@@ -5635,10 +5853,11 @@ function extractText(children, textTransform) {
5635
5853
  }
5636
5854
  //#endregion
5637
5855
  //#region src/layout/normalization.ts
5638
- function resolveFlexDirection(direction, flexDirection) {
5856
+ function resolveFlexDirection(direction, flexDirection, display) {
5639
5857
  if (direction) return direction;
5640
5858
  if (flexDirection === "row") return "horizontal";
5641
5859
  if (flexDirection === "column") return "vertical";
5860
+ if (display === "flex") return "horizontal";
5642
5861
  }
5643
5862
  function resolveLayout(layout, display, position) {
5644
5863
  if (layout) return layout;
@@ -5652,6 +5871,10 @@ function resolveGap(gap, rowGap, columnGap, direction) {
5652
5871
  if (direction === "vertical") return rowGap ?? columnGap;
5653
5872
  return rowGap ?? columnGap;
5654
5873
  }
5874
+ function normalizeImageFit(value) {
5875
+ if (value === "fill") return "stretch";
5876
+ return value;
5877
+ }
5655
5878
  function isCssAlignSelf(value) {
5656
5879
  return value === "start" || value === "flex-start" || value === "center" || value === "end" || value === "flex-end" || value === "stretch" || value === "auto";
5657
5880
  }
@@ -5722,7 +5945,7 @@ function normalizeViewProps(props) {
5722
5945
  authored.gridAutoColumns = resolved.gridAutoColumns ?? gridContainerAuthoring.gridAutoColumns;
5723
5946
  authored.gridAutoRows = resolved.gridAutoRows ?? gridContainerAuthoring.gridAutoRows;
5724
5947
  authored.gridAutoFlow = resolved.gridAutoFlow ?? gridContainerAuthoring.gridAutoFlow;
5725
- const direction = resolveFlexDirection(authored.direction, authored.flexDirection);
5948
+ const direction = resolveFlexDirection(authored.direction, authored.flexDirection, authored.display);
5726
5949
  const inset = resolveInset(authored.inset, authored.top, authored.right, authored.bottom, authored.left);
5727
5950
  return {
5728
5951
  ...authored,
@@ -5781,7 +6004,7 @@ function normalizeTextProps(props) {
5781
6004
  italic: resolved.italic ?? (resolved.fontStyle === "italic" ? true : void 0),
5782
6005
  underline: resolved.underline ?? decoration.underline,
5783
6006
  strike: resolved.strike ?? decoration.strike,
5784
- charSpacing: resolved.charSpacing ?? resolved.letterSpacing,
6007
+ charSpacing: resolved.charSpacing ?? (resolved.letterSpacing === "normal" ? 0 : resolved.letterSpacing),
5785
6008
  backgroundColor: resolved.backgroundColor ?? background.backgroundColor,
5786
6009
  borderColor: resolved.borderColor ?? border.borderColor,
5787
6010
  borderWidth: resolved.borderWidth ?? border.borderWidth,
@@ -5819,7 +6042,7 @@ function normalizeImageProps(props, context) {
5819
6042
  right: inset?.right ?? resolved.right,
5820
6043
  bottom: inset?.bottom ?? resolved.bottom,
5821
6044
  left: inset?.left ?? resolved.left,
5822
- fit: resolved.fit ?? resolved.objectFit,
6045
+ fit: normalizeImageFit(resolved.fit ?? resolved.objectFit),
5823
6046
  objectPosition: resolved.objectPosition,
5824
6047
  crop: resolved.crop,
5825
6048
  rounding: resolved.rounding ?? (resolved.borderRadius !== void 0 ? parseLength(resolved.borderRadius, 0, 0, context) > 0 : void 0),
@@ -6213,7 +6436,8 @@ function matrixTranslatePxToEmu(value) {
6213
6436
  function parseAspectRatio(value) {
6214
6437
  if (value === void 0) return;
6215
6438
  if (typeof value === "number") return value > 0 ? value : void 0;
6216
- const normalized = value.replace(/\s+/g, "");
6439
+ const normalized = value.replace(/\s+/g, "").toLowerCase();
6440
+ if (normalized === "auto") return;
6217
6441
  if (!normalized.includes("/")) {
6218
6442
  const parsed = Number.parseFloat(normalized);
6219
6443
  return Number.isFinite(parsed) && parsed > 0 ? parsed : void 0;
@@ -6245,35 +6469,51 @@ function inflateSpecifiedBoxSize(valueEmu, boxSizing, padding, dimension) {
6245
6469
  if (boxSizing !== "content-box") return valueEmu;
6246
6470
  return valueEmu + (dimension === "width" ? padding[1] + padding[3] : padding[0] + padding[2]);
6247
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
+ }
6248
6479
  function frameFromProps(props, parent, placement, context) {
6249
6480
  const transform = parseTransformShorthandOrIgnore(props.transform);
6250
6481
  const resolvedInset = resolveInset(props.inset, props.top, props.right, props.bottom, props.left);
6251
- const resolvedX = props.x ?? resolvedInset?.left;
6252
- const resolvedY = props.y ?? resolvedInset?.top;
6253
- const resolvedRight = resolvedInset?.right;
6254
- const resolvedBottom = resolvedInset?.bottom;
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;
6255
6493
  const aspectRatio = parseAspectRatio(props.aspectRatio);
6256
- const padding = parseSpacing(props.padding, context);
6494
+ const padding = parseSpacing(props.padding, context, parent.widthEmu);
6257
6495
  const boxSizing = props.boxSizing ?? "border-box";
6258
6496
  const minWidthEmu = parseLength(props.minWidth, parent.widthEmu, 0, context);
6259
6497
  const minHeightEmu = parseLength(props.minHeight, parent.heightEmu, 0, context);
6260
6498
  const maxWidthEmu = parseLength(props.maxWidth, parent.widthEmu, Number.POSITIVE_INFINITY, context);
6261
6499
  const maxHeightEmu = parseLength(props.maxHeight, parent.heightEmu, Number.POSITIVE_INFINITY, context);
6262
6500
  const clampSize = (value, min, max) => Math.max(min, Math.min(value, max));
6263
- const baseWidth = placement?.widthEmu ?? (props.width !== void 0 ? parseLength(props.width, parent.widthEmu, 0, context) : resolvedX !== void 0 && resolvedRight !== void 0 ? Math.max(parent.widthEmu - parseLength(resolvedX, parent.widthEmu, 0, context) - parseLength(resolvedRight, parent.widthEmu, 0, context), 0) : 0);
6264
- const baseHeight = placement?.heightEmu ?? (props.height !== void 0 ? parseLength(props.height, parent.heightEmu, 0, context) : resolvedY !== void 0 && resolvedBottom !== void 0 ? Math.max(parent.heightEmu - parseLength(resolvedY, parent.heightEmu, 0, context) - parseLength(resolvedBottom, parent.heightEmu, 0, context), 0) : 0);
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);
6265
6503
  const aspectResolvedWidth = baseWidth === 0 && aspectRatio !== void 0 && baseHeight > 0 ? baseHeight * aspectRatio : baseWidth;
6266
6504
  const aspectResolvedHeight = baseHeight === 0 && aspectRatio !== void 0 && aspectResolvedWidth > 0 ? aspectResolvedWidth / aspectRatio : baseHeight;
6267
6505
  const clampedWidth = clampSize(aspectResolvedWidth, minWidthEmu, maxWidthEmu);
6268
6506
  const clampedHeight = clampSize(aspectResolvedHeight, minHeightEmu, maxHeightEmu);
6269
- const widthUsesSpecifiedBox = props.width !== void 0 || props.height !== void 0 && aspectRatio !== void 0 && baseWidth === 0;
6270
- const heightUsesSpecifiedBox = props.height !== void 0 || props.width !== void 0 && aspectRatio !== void 0 && baseHeight === 0;
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;
6271
6509
  const resolvedWidth = placement?.widthEmu !== void 0 || !widthUsesSpecifiedBox ? clampedWidth : inflateSpecifiedBoxSize(clampedWidth, boxSizing, padding, "width");
6272
6510
  const resolvedHeight = placement?.heightEmu !== void 0 || !heightUsesSpecifiedBox ? clampedHeight : inflateSpecifiedBoxSize(clampedHeight, boxSizing, padding, "height");
6273
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;
6274
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;
6275
- let transformedX = placement?.xEmu ?? absoluteX;
6276
- 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;
6277
6517
  let transformedWidth = resolvedWidth;
6278
6518
  let transformedHeight = resolvedHeight;
6279
6519
  let transformRotation = 0;
@@ -6468,11 +6708,11 @@ function resolveCrossPlacement(alignment, availableCross, childCross, hasExplici
6468
6708
  sizeEmu: childCross
6469
6709
  };
6470
6710
  }
6471
- function resolveMainGap(direction, gap, rowGap, columnGap, context) {
6472
- 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);
6473
6713
  }
6474
- function resolveCrossGap(direction, gap, rowGap, columnGap, context) {
6475
- 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);
6476
6716
  }
6477
6717
  function buildStackLines(entries, direction, parentFrame, availableMain, mainGapEmu, flexWrap, metrics, context) {
6478
6718
  if (entries.length === 0) return [];
@@ -6598,7 +6838,7 @@ function splitTopLevelCommaList(value) {
6598
6838
  }
6599
6839
  function tryParsePointToken(value) {
6600
6840
  if (value === "0") return 0;
6601
- if (!isDeckPointLengthString(value) || !/^-?(?:\d+|\d*\.\d+)(?:pt|in|px)$/i.test(value)) return;
6841
+ if (!isDeckPointLengthString(value)) return;
6602
6842
  return parsePointToken(value);
6603
6843
  }
6604
6844
  function parseShadowShorthand(value) {
@@ -6640,29 +6880,97 @@ function parseShadowShorthand(value) {
6640
6880
  angle: angle % 360
6641
6881
  };
6642
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
+ }
6643
6896
  //#endregion
6644
- //#region src/layout/resolve.ts
6645
- function errorReason$1(error) {
6897
+ //#region src/layout/unsupported.ts
6898
+ function errorReason$2(error) {
6646
6899
  return error instanceof Error ? error.message : String(error);
6647
6900
  }
6648
- 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) {
6649
6906
  if (input.value === void 0 || input.value === null || input.value === "") return;
6650
6907
  return {
6651
6908
  feature: input.feature,
6652
6909
  property: input.property,
6653
- value: typeof input.value === "string" ? input.value : JSON.stringify(input.value),
6654
- reason: errorReason$1(input.error),
6910
+ value: semanticValue(input.value),
6911
+ reason: errorReason$2(input.error),
6655
6912
  ...input.fallback ? { fallback: input.fallback } : {}
6656
6913
  };
6657
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
+ }
6658
6954
  function parseShadowShorthandOrIgnore(input) {
6659
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;
6660
6968
  return {
6661
- shadow: parseShadowShorthand(input.value),
6662
- unsupportedSemantics: []
6969
+ shadow,
6970
+ unsupportedSemantics: unsupported ? [unsupported] : []
6663
6971
  };
6664
6972
  } catch (error) {
6665
- const unsupported = unsupportedSemantic$1({
6973
+ const unsupported = unsupportedSemantic({
6666
6974
  feature: "shadow",
6667
6975
  property: input.property,
6668
6976
  value: input.value,
@@ -6750,7 +7058,7 @@ function isStrokeIntentionallyNone$1(props) {
6750
7058
  }
6751
7059
  function unsupportedStrokeFallback$1(props, error) {
6752
7060
  const input = strokeFallbackInput$1(props);
6753
- return unsupportedSemantic$1({
7061
+ return unsupportedSemantic({
6754
7062
  feature: input.feature,
6755
7063
  property: input.property,
6756
7064
  value: input.value,
@@ -6791,7 +7099,7 @@ function outlineStrokeOrFallback(props, context) {
6791
7099
  unsupportedSemantics: []
6792
7100
  };
6793
7101
  const input = outlineFallbackInput$1(props);
6794
- const semantic = unsupportedSemantic$1({
7102
+ const semantic = unsupportedSemantic({
6795
7103
  feature: "outline",
6796
7104
  property: input.property,
6797
7105
  value: input.value,
@@ -6805,7 +7113,7 @@ function outlineStrokeOrFallback(props, context) {
6805
7113
  return { unsupportedSemantics: semantic ? [semantic] : [] };
6806
7114
  } catch (error) {
6807
7115
  const input = outlineFallbackInput$1(props);
6808
- const semantic = unsupportedSemantic$1({
7116
+ const semantic = unsupportedSemantic({
6809
7117
  feature: "outline",
6810
7118
  property: input.property,
6811
7119
  value: input.value,
@@ -6823,7 +7131,7 @@ function resolveBackgroundLayersOrEmpty(input, transparency, context, frame, box
6823
7131
  try {
6824
7132
  return resolveBackgroundLayers(input.value, transparency, context, frame, boxFrames, backgroundPosition, backgroundSize, backgroundRepeat, backgroundOrigin, backgroundClip);
6825
7133
  } catch (error) {
6826
- const unsupported = unsupportedSemantic$1({
7134
+ const unsupported = unsupportedSemantic({
6827
7135
  feature: "background",
6828
7136
  property: input.property,
6829
7137
  value: input.value,
@@ -6842,7 +7150,7 @@ function unsupportedTransformSemantics$1(props) {
6842
7150
  try {
6843
7151
  parseTransformShorthand(props.transform);
6844
7152
  } catch (error) {
6845
- const semantic = unsupportedSemantic$1({
7153
+ const semantic = unsupportedSemantic({
6846
7154
  feature: "transform",
6847
7155
  property: "transform",
6848
7156
  value: props.transform,
@@ -6856,7 +7164,7 @@ function unsupportedTransformSemantics$1(props) {
6856
7164
  heightEmu: EMU_PER_INCH
6857
7165
  });
6858
7166
  } catch (error) {
6859
- const semantic = unsupportedSemantic$1({
7167
+ const semantic = unsupportedSemantic({
6860
7168
  feature: "transform",
6861
7169
  property: "transformOrigin",
6862
7170
  value: props.transformOrigin,
@@ -6874,9 +7182,331 @@ const TRANSFORM_STACKING_CONTEXT_FALLBACK_REASON$1 = "CSS transforms create a st
6874
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.";
6875
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.";
6876
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
+ }
6877
7507
  function unsupportedGroupOpacitySemantics$1(props) {
6878
7508
  if (props.opacity === void 0 || props.opacity <= 0 || props.opacity >= 1) return [];
6879
- const semantic = unsupportedSemantic$1({
7509
+ const semantic = unsupportedSemantic({
6880
7510
  feature: "opacity",
6881
7511
  property: "opacity",
6882
7512
  value: props.opacity,
@@ -6891,7 +7521,7 @@ function unsupportedGroupOpacitySemantics$1(props) {
6891
7521
  }
6892
7522
  function unsupportedOpacityStackingContextSemantics$1(props) {
6893
7523
  if (props.opacity === void 0 || props.opacity <= 0 || props.opacity >= 1) return [];
6894
- const semantic = unsupportedSemantic$1({
7524
+ const semantic = unsupportedSemantic({
6895
7525
  feature: "opacity",
6896
7526
  property: "stackingContext",
6897
7527
  value: props.opacity,
@@ -6909,7 +7539,7 @@ function hasProjectedTransform(input) {
6909
7539
  }
6910
7540
  function unsupportedClippingTransformSemantics(input) {
6911
7541
  if (!input.clip || !hasProjectedTransform(input)) return [];
6912
- const semantic = unsupportedSemantic$1({
7542
+ const semantic = unsupportedSemantic({
6913
7543
  feature: "clipping",
6914
7544
  property: "overflow",
6915
7545
  value: `hidden + transform:${input.clip.strategy}`,
@@ -6930,7 +7560,7 @@ function unsupportedClippingTransformSemantics(input) {
6930
7560
  function unsupportedClippedImageSourceRectTransformSemantics(input) {
6931
7561
  if (!input.clip || !hasProjectedTransform(input)) return [];
6932
7562
  const cropSuffix = input.hasExplicitCrop ? "+crop" : "";
6933
- const semantic = unsupportedSemantic$1({
7563
+ const semantic = unsupportedSemantic({
6934
7564
  feature: "clipping",
6935
7565
  property: "imageSourceRect",
6936
7566
  value: `clip:${input.clip.strategy}+transform+fit:${input.fit ?? "contain"}${cropSuffix}`,
@@ -6956,7 +7586,7 @@ function unsupportedTransformStackingContextSemantics$1(props) {
6956
7586
  return [];
6957
7587
  }
6958
7588
  if (!operations?.length) return [];
6959
- const semantic = unsupportedSemantic$1({
7589
+ const semantic = unsupportedSemantic({
6960
7590
  feature: "transform",
6961
7591
  property: "stackingContext",
6962
7592
  value: props.transform,
@@ -6973,7 +7603,7 @@ function unsupportedCompositingSemantics$1(props) {
6973
7603
  const unsupported = [];
6974
7604
  const filter = props.filter?.trim();
6975
7605
  if (filter && filter.toLowerCase() !== "none") {
6976
- const semantic = unsupportedSemantic$1({
7606
+ const semantic = unsupportedSemantic({
6977
7607
  feature: "filter",
6978
7608
  property: "filter",
6979
7609
  value: props.filter,
@@ -6988,7 +7618,7 @@ function unsupportedCompositingSemantics$1(props) {
6988
7618
  }
6989
7619
  const mixBlendMode = props.mixBlendMode?.trim();
6990
7620
  if (mixBlendMode && mixBlendMode.toLowerCase() !== "normal") {
6991
- const semantic = unsupportedSemantic$1({
7621
+ const semantic = unsupportedSemantic({
6992
7622
  feature: "blend",
6993
7623
  property: "mixBlendMode",
6994
7624
  value: props.mixBlendMode,
@@ -7002,7 +7632,7 @@ function unsupportedCompositingSemantics$1(props) {
7002
7632
  if (semantic) unsupported.push(semantic);
7003
7633
  }
7004
7634
  if (props.isolation === "isolate") {
7005
- const semantic = unsupportedSemantic$1({
7635
+ const semantic = unsupportedSemantic({
7006
7636
  feature: "isolation",
7007
7637
  property: "isolation",
7008
7638
  value: props.isolation,
@@ -7051,6 +7681,8 @@ const EMPTY_SPACING = [
7051
7681
  0,
7052
7682
  0
7053
7683
  ];
7684
+ const DEFAULT_TEXT_FONT_SIZE_PT = 18;
7685
+ const DEFAULT_NORMAL_LINE_HEIGHT_MULTIPLE = 1.2;
7054
7686
  function createIdGenerator() {
7055
7687
  let slideCount = 0;
7056
7688
  let nodeCount = 0;
@@ -7108,7 +7740,7 @@ function layoutChildFromNode(child, siblingOrder, context) {
7108
7740
  case "image": return {
7109
7741
  kind: "image",
7110
7742
  source: child,
7111
- props: normalizeImageProps(child.props, context),
7743
+ props: normalizeImagePropsWithIntrinsicAspectRatio(child, context),
7112
7744
  siblingOrder,
7113
7745
  ...origin ? { origin } : {}
7114
7746
  };
@@ -7121,6 +7753,35 @@ function layoutChildFromNode(child, siblingOrder, context) {
7121
7753
  };
7122
7754
  }
7123
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
+ }
7124
7785
  function parseCropValue$1(value) {
7125
7786
  if (value === void 0) return 0;
7126
7787
  if (typeof value === "number") {
@@ -7197,12 +7858,12 @@ function resolveAlignContentOffset(alignContent, availableEmu, usedEmu, lineCoun
7197
7858
  extraSizeEmu: 0
7198
7859
  };
7199
7860
  }
7200
- function getChildPadding(node, context) {
7861
+ function getChildPadding(node, context, percentageBaseEmu = 0) {
7201
7862
  switch (node.kind) {
7202
- case "view": return parseSpacing(node.props.padding, context);
7863
+ case "view": return parseSpacing(node.props.padding, context, percentageBaseEmu);
7203
7864
  case "text": {
7204
7865
  const { props } = node;
7205
- return parseSpacing(props.padding, getTextLengthContext(props, context));
7866
+ return parseSpacing(props.padding, getTextLengthContext(props, context), percentageBaseEmu);
7206
7867
  }
7207
7868
  case "image": return EMPTY_SPACING;
7208
7869
  case "shape": return EMPTY_SPACING;
@@ -7220,46 +7881,68 @@ function resolveChildMainLength(node, axis) {
7220
7881
  if (flexBasis !== void 0 && flexBasis !== "auto") return flexBasis;
7221
7882
  return node.props[axis === "horizontal" ? "width" : "height"];
7222
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
+ }
7223
7902
  function estimateChildContentSize(node, dimension, parent, mainAxis, context) {
7224
7903
  const aspectRatio = parseAspectRatio(node.props.aspectRatio);
7225
7904
  const isMainDimension = mainAxis === "horizontal" && dimension === "width" || mainAxis === "vertical" && dimension === "height";
7226
7905
  const basis = dimension === "width" ? parent.widthEmu : parent.heightEmu;
7227
- const directValue = isMainDimension && mainAxis ? resolveChildMainLength(node, mainAxis) : node.props[dimension];
7228
- if (directValue !== void 0) return inflateSpecifiedBoxSize(parseLength(directValue, basis, 0, getNodeLengthContext(node, context)), node.kind === "image" ? "border-box" : node.props.boxSizing ?? "border-box", getChildPadding(node, context), dimension);
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
+ }
7229
7912
  if (aspectRatio === void 0) return 0;
7230
7913
  const oppositeDimension = dimension === "width" ? "height" : "width";
7231
7914
  const oppositeBasis = oppositeDimension === "width" ? parent.widthEmu : parent.heightEmu;
7232
- const oppositeValue = (mainAxis === "horizontal" && oppositeDimension === "width" || mainAxis === "vertical" && oppositeDimension === "height") && mainAxis ? resolveChildMainLength(node, mainAxis) : node.props[oppositeDimension];
7233
- if (oppositeValue === void 0) return 0;
7234
- const oppositeSize = parseLength(oppositeValue, oppositeBasis, 0, getNodeLengthContext(node, context));
7235
- return inflateSpecifiedBoxSize(dimension === "width" ? oppositeSize * aspectRatio : oppositeSize / aspectRatio, node.kind === "image" ? "border-box" : node.props.boxSizing ?? "border-box", getChildPadding(node, context), dimension);
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);
7236
7919
  }
7237
- function getNodeMargin(node, context) {
7920
+ function getNodeMargin(node, context, percentageBaseEmu = 0) {
7238
7921
  switch (node.kind) {
7239
- case "view": return parseSpacing(node.props.margin, context);
7922
+ case "view": return parseSpacingAllowAuto(node.props.margin, context, percentageBaseEmu);
7240
7923
  case "text": {
7241
7924
  const { props } = node;
7242
- return parseSpacing(props.margin, getTextLengthContext(props, context));
7925
+ return parseSpacingAllowAuto(props.margin, getTextLengthContext(props, context), percentageBaseEmu);
7243
7926
  }
7244
- case "image": return parseSpacing(node.props.margin, context);
7245
- 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);
7246
7929
  }
7247
7930
  }
7248
7931
  function estimateChildMainSize(node, axis, parent, context) {
7249
- const [top, right, bottom, left] = getNodeMargin(node, context);
7932
+ const [top, right, bottom, left] = getNodeMargin(node, context, parent.widthEmu);
7250
7933
  const margin = axis === "horizontal" ? left + right : top + bottom;
7251
7934
  return estimateChildContentSize(node, axis === "horizontal" ? "width" : "height", parent, axis, context) + margin;
7252
7935
  }
7253
7936
  function estimateChildCrossSize(node, axis, parent, context) {
7254
- const [top, right, bottom, left] = getNodeMargin(node, context);
7937
+ const [top, right, bottom, left] = getNodeMargin(node, context, parent.widthEmu);
7255
7938
  const margin = axis === "horizontal" ? top + bottom : left + right;
7256
7939
  return estimateChildContentSize(node, axis === "horizontal" ? "height" : "width", parent, axis, context) + margin;
7257
7940
  }
7258
7941
  function shouldStretchGridDimension(node, dimension) {
7259
- if (node.props[dimension] !== void 0) return false;
7942
+ if (hasAuthoredLength(node.props[dimension])) return false;
7260
7943
  if (!parseAspectRatio(node.props.aspectRatio)) return true;
7261
7944
  const oppositeDimension = dimension === "width" ? "height" : "width";
7262
- return node.props[oppositeDimension] === void 0;
7945
+ return !hasAuthoredLength(node.props[oppositeDimension]);
7263
7946
  }
7264
7947
  function resolveChildGridPlacements(node, namedAreas) {
7265
7948
  const explicitRow = resolveGridPlacementFromLonghands(node.props.gridRowStart, node.props.gridRowEnd) ?? parseGridPlacement(node.props.gridRow);
@@ -7278,7 +7961,7 @@ function resolveChildGridPlacements(node, namedAreas) {
7278
7961
  };
7279
7962
  }
7280
7963
  function resolveGridContainerSpec(parentFrame, options, context) {
7281
- const [paddingTop, paddingRight, paddingBottom, paddingLeft] = parseSpacing(options.padding, context);
7964
+ const [paddingTop, paddingRight, paddingBottom, paddingLeft] = parseSpacing(options.padding, context, parentFrame.widthEmu);
7282
7965
  const contentX = parentFrame.xEmu + paddingLeft;
7283
7966
  const contentY = parentFrame.yEmu + paddingTop;
7284
7967
  const contentWidth = Math.max(parentFrame.widthEmu - paddingLeft - paddingRight, 0);
@@ -7289,8 +7972,8 @@ function resolveGridContainerSpec(parentFrame, options, context) {
7289
7972
  widthEmu: contentWidth,
7290
7973
  heightEmu: contentHeight
7291
7974
  };
7292
- const columnGapEmu = parseLength(options.columnGap ?? options.rowGap, 0, 0, context);
7293
- 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);
7294
7977
  const placeItems = parsePlaceItems(options.placeItems);
7295
7978
  const placeContent = parsePlaceContent(options.placeContent);
7296
7979
  const namedAreas = parseGridTemplateAreas(options.gridTemplateAreas);
@@ -7375,7 +8058,7 @@ function compileGridChildren(authorChildren, parentFrame, idGenerator, options,
7375
8058
  const rowOffsets = resolveTrackOffsets(stretchedRowTracks, spec.rowGapEmu).map((offset) => offset + blockPacking.offsetEmu);
7376
8059
  return sortNodesForPaint(placements.map((placement) => {
7377
8060
  const { child, row, column, rowSpan, columnSpan } = placement;
7378
- const [marginTop, marginRight, marginBottom, marginLeft] = getNodeMargin(child, context);
8061
+ const [marginTop, marginRight, marginBottom, marginLeft] = getNodeMargin(child, context, spec.contentWidth);
7379
8062
  const cellWidth = stretchedColumnTracks.slice(column - 1, column - 1 + columnSpan).reduce((sum, size) => sum + size, 0) + Math.max(columnSpan - 1, 0) * spec.columnGapEmu;
7380
8063
  const cellHeight = stretchedRowTracks.slice(row - 1, row - 1 + rowSpan).reduce((sum, size) => sum + size, 0) + Math.max(rowSpan - 1, 0) * spec.rowGapEmu;
7381
8064
  const innerFrame = {
@@ -7402,6 +8085,44 @@ function compileGridChildren(authorChildren, parentFrame, idGenerator, options,
7402
8085
  return compileNode(child, innerFrame, idGenerator, placementOverride, clipRect, context, resolutionOptions);
7403
8086
  }).filter((node) => node !== null));
7404
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
+ }
7405
8126
  function compileChildren$1(children, parentFrame, idGenerator, layout, options, clipRect, context, resolutionOptions) {
7406
8127
  const authorChildren = children.map((child, siblingOrder) => {
7407
8128
  if (!isLayoutInputContentNode(child)) throw new Error("Only deckjsx components can be children of View in structured layout.");
@@ -7424,11 +8145,15 @@ function compileChildren$1(children, parentFrame, idGenerator, layout, options,
7424
8145
  placeContent: options.placeContent,
7425
8146
  gridAutoFlow: options.gridAutoFlow
7426
8147
  }, clipRect, context, resolutionOptions);
7427
- if (layout !== "stack") return sortNodesForPaint(authorChildren.map((child) => compileNode(child, parentFrame, idGenerator, void 0, clipRect, context, resolutionOptions)).filter((node) => node !== null));
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);
7428
8154
  const direction = options.direction ?? "vertical";
7429
- const mainGapEmu = resolveMainGap(direction, options.gap, options.rowGap, options.columnGap, context);
7430
- const crossGapEmu = resolveCrossGap(direction, options.gap, options.rowGap, options.columnGap, context);
7431
- const [paddingTop, paddingRight, paddingBottom, paddingLeft] = parseSpacing(options.padding, context);
8155
+ const defaultAlignItems = options.alignItems ?? (options.display === "flex" ? "stretch" : void 0);
8156
+ const [paddingTop, paddingRight, paddingBottom, paddingLeft] = parseSpacing(options.padding, context, parentFrame.widthEmu);
7432
8157
  const contentX = parentFrame.xEmu + paddingLeft;
7433
8158
  const contentY = parentFrame.yEmu + paddingTop;
7434
8159
  const contentWidth = Math.max(parentFrame.widthEmu - paddingLeft - paddingRight, 0);
@@ -7439,6 +8164,8 @@ function compileChildren$1(children, parentFrame, idGenerator, layout, options,
7439
8164
  widthEmu: contentWidth,
7440
8165
  heightEmu: contentHeight
7441
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);
7442
8169
  const stackEntries = authorChildren.map((child, sourceIndex) => ({
7443
8170
  child,
7444
8171
  sourceIndex,
@@ -7456,13 +8183,13 @@ function compileChildren$1(children, parentFrame, idGenerator, layout, options,
7456
8183
  const absoluteEntries = stackEntries.filter((entry) => entry.position === "absolute");
7457
8184
  const availableMain = direction === "horizontal" ? contentWidth : contentHeight;
7458
8185
  const availableCross = direction === "horizontal" ? contentHeight : contentWidth;
7459
- 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);
7460
8187
  const usedCross = lines.reduce((sum, line) => sum + line.crossSizeEmu, 0) + Math.max(lines.length - 1, 0) * crossGapEmu;
7461
8188
  const contentPacking = resolveAlignContentOffset(options.alignContent, availableCross, usedCross, lines.length);
7462
8189
  let crossCursor = contentPacking.offsetEmu;
7463
8190
  const flowNodes = [];
7464
8191
  for (const [lineIndex, line] of lines.entries()) {
7465
- const mainAllocations = resolveFlexMainAllocations(line, direction, parentFrame, availableMain, mainGapEmu, stackMetrics, context);
8192
+ const mainAllocations = resolveFlexMainAllocations(line, direction, contentFrame, availableMain, mainGapEmu, stackMetrics, context);
7466
8193
  const allocatedUsedMain = mainAllocations.reduce((sum, allocation) => sum + allocation.outerMainEmu, 0) + Math.max(line.entries.length - 1, 0) * mainGapEmu;
7467
8194
  const justify = resolveJustifyOffset(options.justifyContent, availableMain, allocatedUsedMain, line.entries.length);
7468
8195
  let mainCursor = justify.offsetEmu;
@@ -7471,10 +8198,10 @@ function compileChildren$1(children, parentFrame, idGenerator, layout, options,
7471
8198
  const mainAllocation = mainAllocations[entryIndex];
7472
8199
  if (mainAllocation === void 0) throw new Error("Stack layout allocation count did not match line entry count.");
7473
8200
  const { child } = entry;
7474
- const childCross = estimateChildCrossSize(child, direction, parentFrame, context);
7475
- const [marginTop, marginRight, marginBottom, marginLeft] = getNodeMargin(child, context);
7476
- let alignment = parsePlaceSelf(child.props.placeSelf).alignSelf ?? child.props.alignSelf ?? options.alignItems;
7477
- if (alignment === "auto") alignment = void 0;
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;
7478
8205
  if (alignment === "flex-start") alignment = "start";
7479
8206
  if (alignment === "flex-end") alignment = "end";
7480
8207
  const hasExplicitCrossSize = child.props[direction === "horizontal" ? "height" : "width"] !== void 0;
@@ -7520,13 +8247,14 @@ function compileGroupNode(node, parentFrame, idGenerator, placement, clipRect, c
7520
8247
  const visibleFrame = intersectClipRect(originalFrame, clipRect);
7521
8248
  if (!visibleFrame) return null;
7522
8249
  const childClipRect = props.overflow === "hidden" ? intersectClipRect(originalFrame, clipRect) : clipRect;
7523
- 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));
7524
8251
  const backgroundFill = resolveBackgroundLayersOrEmpty(backgroundInput(props), props.backgroundTransparency, {
7525
8252
  widthEmu: visibleFrame.widthEmu,
7526
8253
  heightEmu: visibleFrame.heightEmu
7527
8254
  }, visibleFrame, backgroundBoxFrames, props.backgroundPosition, props.backgroundSize, props.backgroundRepeat, props.backgroundOrigin, props.backgroundClip);
7528
8255
  const clip = clippingMetadata(originalFrame, clipRect, visibleFrame);
7529
8256
  const unsupportedSemantics = [
8257
+ ...unsupportedCssLayoutValueSemantics(props),
7530
8258
  ...unsupportedTransformSemantics$1(props),
7531
8259
  ...unsupportedTransformStackingContextSemantics$1(props),
7532
8260
  ...unsupportedCompositingSemantics$1(props),
@@ -7562,9 +8290,10 @@ function compileGroupNode(node, parentFrame, idGenerator, placement, clipRect, c
7562
8290
  ...strokes.edgeStrokes ? { edgeStrokes: strokes.edgeStrokes } : {},
7563
8291
  ...outline.outline ? { outline: outline.outline } : {},
7564
8292
  ...shadow.shadow ? { shadow: shadow.shadow } : {},
7565
- radiusEmu: parseLength(props.borderRadius, 0, 0, context),
8293
+ radiusEmu: resolveCornerRadiusEmu$1(props.borderRadius, visibleFrame, context),
7566
8294
  children: compileChildren$1(node.source.children, originalFrame, idGenerator, props.layout, {
7567
8295
  direction: props.direction,
8296
+ display: props.display,
7568
8297
  gap: props.gap,
7569
8298
  rowGap: props.rowGap,
7570
8299
  columnGap: props.columnGap,
@@ -7592,7 +8321,7 @@ function textStyleFromProps$1(props, textLengthContext) {
7592
8321
  const underlineColor = normalizeColor(props.textDecorationColor);
7593
8322
  const textDirection = resolveTextDirection(props.writingMode);
7594
8323
  const tabStops = resolveTabStops(props.tabStops, textLengthContext);
7595
- 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);
7596
8325
  return {
7597
8326
  fontFamily: props.fontFamily,
7598
8327
  fontSizePt,
@@ -7608,11 +8337,11 @@ function textStyleFromProps$1(props, textLengthContext) {
7608
8337
  paddingPt: parseSpacingInPoints(props.padding, textLengthContext),
7609
8338
  lineSpacing: props.lineSpacing ?? lineHeight.lineSpacing,
7610
8339
  lineSpacingMultiple: props.lineSpacingMultiple ?? lineHeight.lineSpacingMultiple,
7611
- paragraphSpacingBefore: props.paragraphSpacingBefore,
7612
- 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),
7613
8342
  ...props.textIndent === void 0 ? {} : { textIndentPt: parsePointValue(props.textIndent, 0, textLengthContext) },
7614
8343
  ...tabStops ? { tabStops } : {},
7615
- charSpacing: props.charSpacing,
8344
+ charSpacing: resolveCharacterSpacing(props.charSpacing, textLengthContext),
7616
8345
  ...list ? { list } : {},
7617
8346
  fit: props.fit,
7618
8347
  wrap: props.wrap,
@@ -7662,10 +8391,66 @@ function clippingMetadata(originalFrame, clipRect, visibleFrame) {
7662
8391
  visibleFrame
7663
8392
  };
7664
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
+ }
7665
8450
  function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, context) {
7666
8451
  const { props } = node;
7667
8452
  const textLengthContext = getTextLengthContext(props, context);
7668
- const resolved = frameFromProps(props, parentFrame, placement, textLengthContext);
8453
+ const resolved = frameFromProps(textFramePropsWithFallback(props, placement, textLengthContext), parentFrame, placement, textLengthContext);
7669
8454
  const strokes = resolveNodeStrokesOrFallback(props, textLengthContext);
7670
8455
  const shadow = parseShadowShorthandOrIgnore({
7671
8456
  property: props.textShadow !== void 0 ? "textShadow" : "boxShadow",
@@ -7678,6 +8463,7 @@ function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, co
7678
8463
  } : void 0;
7679
8464
  const style = textStyleFromProps$1(props, textLengthContext);
7680
8465
  const runs = extractRichTextRuns(node.source.children, props.textTransform, textLengthContext);
8466
+ const text = runs.map((run) => run.text).join("");
7681
8467
  const originalFrame = {
7682
8468
  xEmu: resolved.xEmu,
7683
8469
  yEmu: resolved.yEmu,
@@ -7686,13 +8472,15 @@ function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, co
7686
8472
  };
7687
8473
  const visibleFrame = intersectClipRect(originalFrame, clipRect);
7688
8474
  if (!visibleFrame) return null;
7689
- 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));
7690
8476
  const backgroundFill = resolveBackgroundLayersOrEmpty(backgroundInput(props), props.backgroundTransparency, {
7691
8477
  widthEmu: visibleFrame.widthEmu,
7692
8478
  heightEmu: visibleFrame.heightEmu
7693
8479
  }, visibleFrame, backgroundBoxFrames, props.backgroundPosition, props.backgroundSize, props.backgroundRepeat, props.backgroundOrigin, props.backgroundClip);
7694
8480
  const clip = clippingMetadata(originalFrame, clipRect, visibleFrame);
7695
8481
  const unsupportedSemantics = [
8482
+ ...unsupportedCssLayoutValueSemantics(props),
8483
+ ...unsupportedTextLogicalLayoutSemantics(props),
7696
8484
  ...unsupportedTransformSemantics$1(props),
7697
8485
  ...unsupportedCompositingSemantics$1(props),
7698
8486
  ...unsupportedOpacityStackingContextSemantics$1(props),
@@ -7702,6 +8490,11 @@ function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, co
7702
8490
  flipH: resolved.flipH,
7703
8491
  flipV: resolved.flipV
7704
8492
  }),
8493
+ ...unsupportedWrappedTextMeasurementSemantics({
8494
+ props,
8495
+ placement,
8496
+ text
8497
+ }),
7705
8498
  ...strokes.unsupportedSemantics,
7706
8499
  ...outline.unsupportedSemantics,
7707
8500
  ...shadow.unsupportedSemantics,
@@ -7722,7 +8515,7 @@ function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, co
7722
8515
  flipV: resolved.flipV,
7723
8516
  ...unsupportedSemantics.length ? { unsupportedSemantics } : {},
7724
8517
  content: {
7725
- text: runs.map((run) => run.text).join(""),
8518
+ text,
7726
8519
  ...runs.length > 1 || runs.some((run) => run.style) ? { runs } : {}
7727
8520
  },
7728
8521
  style,
@@ -7733,11 +8526,12 @@ function compileTextNode(node, parentFrame, idGenerator, placement, clipRect, co
7733
8526
  ...outline.outline ? { outline: outline.outline } : {},
7734
8527
  ...shadow.shadow ? { shadow: shadow.shadow } : {},
7735
8528
  ...hyperlink ? { hyperlink } : {},
7736
- radiusEmu: parseLength(props.borderRadius, 0, 0, textLengthContext)
8529
+ radiusEmu: resolveCornerRadiusEmu$1(props.borderRadius, visibleFrame, textLengthContext)
7737
8530
  };
7738
8531
  }
7739
8532
  function compileImageNode(node, parentFrame, idGenerator, placement, clipRect, context) {
7740
8533
  const { props } = node;
8534
+ const fit = normalizeProjectedImageFit(props.fit);
7741
8535
  const resolved = frameFromProps(props, parentFrame, placement, context);
7742
8536
  const shadow = parseShadowShorthandOrIgnore({
7743
8537
  property: "boxShadow",
@@ -7763,6 +8557,7 @@ function compileImageNode(node, parentFrame, idGenerator, placement, clipRect, c
7763
8557
  if (!visibleFrame) return null;
7764
8558
  const clip = clippingMetadata(originalFrame, clipRect, visibleFrame);
7765
8559
  const unsupportedSemantics = [
8560
+ ...unsupportedCssLayoutValueSemantics(props),
7766
8561
  ...unsupportedTransformSemantics$1(props),
7767
8562
  ...unsupportedCompositingSemantics$1(props),
7768
8563
  ...unsupportedOpacityStackingContextSemantics$1(props),
@@ -7777,9 +8572,14 @@ function compileImageNode(node, parentFrame, idGenerator, placement, clipRect, c
7777
8572
  rotation: resolved.rotation,
7778
8573
  flipH: resolved.flipH,
7779
8574
  flipV: resolved.flipV,
7780
- fit: props.fit,
8575
+ fit,
7781
8576
  hasExplicitCrop: crop !== void 0
7782
8577
  }),
8578
+ ...unsupportedObjectPositionSemantics({
8579
+ value: props.objectPosition,
8580
+ resolved: objectPosition
8581
+ }),
8582
+ ...unsupportedObjectFitSemantics(props.fit),
7783
8583
  ...shadow.unsupportedSemantics
7784
8584
  ];
7785
8585
  return {
@@ -7797,7 +8597,7 @@ function compileImageNode(node, parentFrame, idGenerator, placement, clipRect, c
7797
8597
  flipH: resolved.flipH,
7798
8598
  flipV: resolved.flipV,
7799
8599
  ...unsupportedSemantics.length ? { unsupportedSemantics } : {},
7800
- fit: props.fit ?? "contain",
8600
+ fit,
7801
8601
  ...objectPosition ? { objectPosition } : {},
7802
8602
  ...crop ? { crop } : {},
7803
8603
  transparency: normalizeTransparency$1(props.transparency),
@@ -7835,6 +8635,7 @@ function compileShapeNode(node, parentFrame, idGenerator, placement, clipRect, c
7835
8635
  }, visibleFrame, backgroundBoxFrames, props.backgroundPosition, props.backgroundSize, props.backgroundRepeat, props.backgroundOrigin, props.backgroundClip);
7836
8636
  const clip = clippingMetadata(originalFrame, clipRect, visibleFrame);
7837
8637
  const unsupportedSemantics = [
8638
+ ...unsupportedCssLayoutValueSemantics(props),
7838
8639
  ...unsupportedTransformSemantics$1(props),
7839
8640
  ...unsupportedCompositingSemantics$1(props),
7840
8641
  ...unsupportedOpacityStackingContextSemantics$1(props),
@@ -7871,7 +8672,7 @@ function compileShapeNode(node, parentFrame, idGenerator, placement, clipRect, c
7871
8672
  ...outline.outline ? { outline: outline.outline } : {},
7872
8673
  ...shadow.shadow ? { shadow: shadow.shadow } : {},
7873
8674
  ...hyperlink ? { hyperlink } : {},
7874
- radiusEmu: parseLength(props.radius, 0, 0, context)
8675
+ radiusEmu: resolveCornerRadiusEmu$1(props.radius, visibleFrame, context)
7875
8676
  };
7876
8677
  }
7877
8678
  function compileNode(child, parentFrame, idGenerator, placement, clipRect, context, resolutionOptions) {
@@ -7889,14 +8690,19 @@ function compileSlide(root, context, slideFrame, idGenerator, lengthContext) {
7889
8690
  widthEmu: slideFrame.widthEmu,
7890
8691
  heightEmu: slideFrame.heightEmu
7891
8692
  }, slideFrame, backgroundBoxFrames, slideProps.backgroundPosition, slideProps.backgroundSize, slideProps.backgroundRepeat, slideProps.backgroundOrigin, slideProps.backgroundClip);
7892
- const nodes = root.children.map((child, siblingOrder) => layoutChildFromNode(child, siblingOrder, lengthContext)).filter((child) => child.props.display !== "none").map((child) => compileNode(child, slideFrame, idGenerator, void 0, void 0, lengthContext)).filter((node) => node !== null);
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);
7893
8699
  return {
7894
8700
  id: idGenerator.nextSlide(),
7895
8701
  name: slideProps.name,
7896
8702
  ...root.origin ? { origin: root.origin } : {},
7897
8703
  background: backgroundFill.fill,
7898
8704
  ...backgroundFill.backgroundLayers ? { backgroundLayers: backgroundFill.backgroundLayers } : {},
7899
- nodes: sortNodesForPaint(nodes)
8705
+ nodes
7900
8706
  };
7901
8707
  }
7902
8708
  function resolveProjectedLayout(options, input) {
@@ -8611,24 +9417,23 @@ function shapeFillInputFor(resolved, props) {
8611
9417
  function errorReason(error) {
8612
9418
  return error instanceof Error ? error.message : String(error);
8613
9419
  }
8614
- function semanticValue(value) {
8615
- return typeof value === "string" ? value : JSON.stringify(value);
8616
- }
8617
- function unsupportedSemantic(input) {
8618
- if (input.value === void 0 || input.value === null || input.value === "") return;
8619
- return {
8620
- feature: input.feature,
8621
- property: input.property,
8622
- value: semanticValue(input.value),
8623
- reason: errorReason(input.error),
8624
- ...input.fallback ? { fallback: input.fallback } : {}
8625
- };
8626
- }
8627
9420
  function parseShadowSafely(input) {
8628
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;
8629
9434
  return {
8630
- shadow: parseShadowShorthand(input.value),
8631
- unsupportedSemantics: []
9435
+ shadow,
9436
+ unsupportedSemantics: unsupported ? [unsupported] : []
8632
9437
  };
8633
9438
  } catch (error) {
8634
9439
  const unsupported = unsupportedSemantic({
@@ -8717,6 +9522,27 @@ function isExplicitNone(value) {
8717
9522
  function isStrokeIntentionallyNone(props) {
8718
9523
  return isExplicitNone(props.border) || isExplicitNone(props.borderTop) || isExplicitNone(props.borderRight) || isExplicitNone(props.borderBottom) || isExplicitNone(props.borderLeft) || props.borderStyle === "none";
8719
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
+ }
8720
9546
  function unsupportedStrokeFallback(props, error) {
8721
9547
  const input = strokeFallbackInput(props);
8722
9548
  return unsupportedSemantic({
@@ -8732,32 +9558,34 @@ function unsupportedStrokeFallback(props, error) {
8732
9558
  });
8733
9559
  }
8734
9560
  function resolveNodeStrokesSafely(props, context) {
9561
+ const cssWideSemantics = unsupportedStrokeCssWideKeywordSemantics(props);
8735
9562
  try {
8736
9563
  const strokes = resolveNodeStrokes(props, context);
8737
9564
  if (!strokes.stroke && !strokes.edgeStrokes && hasAuthoredStrokeInput(props) && !isStrokeIntentionallyNone(props)) {
8738
9565
  const semantic = unsupportedStrokeFallback(props, /* @__PURE__ */ new Error("No PPTX stroke could be produced from the authored stroke input."));
8739
9566
  return {
8740
9567
  ...strokes,
8741
- unsupportedSemantics: semantic ? [semantic] : []
9568
+ unsupportedSemantics: semantic ? [semantic, ...cssWideSemantics] : cssWideSemantics
8742
9569
  };
8743
9570
  }
8744
9571
  return {
8745
9572
  ...strokes,
8746
- unsupportedSemantics: []
9573
+ unsupportedSemantics: cssWideSemantics
8747
9574
  };
8748
9575
  } catch (error) {
8749
9576
  const semantic = unsupportedStrokeFallback(props, error);
8750
- return { unsupportedSemantics: semantic ? [semantic] : [] };
9577
+ return { unsupportedSemantics: semantic ? [semantic, ...cssWideSemantics] : cssWideSemantics };
8751
9578
  }
8752
9579
  }
8753
9580
  function outlineStrokeSafely(props, context) {
8754
9581
  if (!hasAuthoredOutlineInput(props)) return { unsupportedSemantics: [] };
9582
+ const cssWideSemantics = unsupportedOutlineCssWideKeywordSemantics(props);
8755
9583
  try {
8756
9584
  const outlineInput = parseOutlineShorthand(props.outline);
8757
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);
8758
9586
  if (outline) return {
8759
9587
  outline,
8760
- unsupportedSemantics: []
9588
+ unsupportedSemantics: cssWideSemantics
8761
9589
  };
8762
9590
  const input = outlineFallbackInput(props);
8763
9591
  const semantic = unsupportedSemantic({
@@ -8771,7 +9599,7 @@ function outlineStrokeSafely(props, context) {
8771
9599
  missing: ["pptxOutline"]
8772
9600
  }
8773
9601
  });
8774
- return { unsupportedSemantics: semantic ? [semantic] : [] };
9602
+ return { unsupportedSemantics: semantic ? [semantic, ...cssWideSemantics] : cssWideSemantics };
8775
9603
  } catch (error) {
8776
9604
  const input = outlineFallbackInput(props);
8777
9605
  const semantic = unsupportedSemantic({
@@ -8785,7 +9613,7 @@ function outlineStrokeSafely(props, context) {
8785
9613
  missing: ["pptxOutline"]
8786
9614
  }
8787
9615
  });
8788
- return { unsupportedSemantics: semantic ? [semantic] : [] };
9616
+ return { unsupportedSemantics: semantic ? [semantic, ...cssWideSemantics] : cssWideSemantics };
8789
9617
  }
8790
9618
  }
8791
9619
  function unsupportedTransformSemantics(props) {
@@ -9239,6 +10067,9 @@ function parseObjectPositionValue(objectPosition, frame) {
9239
10067
  y: axisValue(yToken, frame.heightEmu)
9240
10068
  };
9241
10069
  }
10070
+ function resolveCornerRadiusEmu(value, frame, context) {
10071
+ return parseLength(value, Math.min(frame.widthEmu, frame.heightEmu), 0, context);
10072
+ }
9242
10073
  function textStyleFromProps(props, textLengthContext) {
9243
10074
  const list = resolveListStyle(props, textLengthContext);
9244
10075
  const lineHeight = resolveLineHeight(props.lineHeight, textLengthContext);
@@ -9262,11 +10093,11 @@ function textStyleFromProps(props, textLengthContext) {
9262
10093
  paddingPt: parseSpacingInPoints(props.padding, textLengthContext),
9263
10094
  lineSpacing: props.lineSpacing ?? lineHeight.lineSpacing,
9264
10095
  lineSpacingMultiple: props.lineSpacingMultiple ?? lineHeight.lineSpacingMultiple,
9265
- paragraphSpacingBefore: props.paragraphSpacingBefore,
9266
- 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),
9267
10098
  ...props.textIndent === void 0 ? {} : { textIndentPt: parsePointValue(props.textIndent, 0, textLengthContext) },
9268
10099
  ...tabStops ? { tabStops } : {},
9269
- charSpacing: props.charSpacing,
10100
+ charSpacing: resolveCharacterSpacing(props.charSpacing, textLengthContext),
9270
10101
  ...list ? { list } : {},
9271
10102
  fit: props.fit ?? DEFAULT_TEXT_FIT,
9272
10103
  wrap: props.wrap ?? DEFAULT_TEXT_WRAP,
@@ -9531,7 +10362,7 @@ function compileContainer(graph, resolvedStyles, node, templates, packagePartIdV
9531
10362
  ...outlineResult.outline ? { outline: outlineResult.outline } : {},
9532
10363
  ...generatedStrokes ? { generatedStrokes } : {},
9533
10364
  ...shadowResult.shadow ? { shadow: shadowResult.shadow } : {},
9534
- radiusEmu: parseLength(props.borderRadius, 0, 0, context),
10365
+ radiusEmu: resolveCornerRadiusEmu(props.borderRadius, frame, context),
9535
10366
  children: compileChildren(graph, resolvedStyles, node.children, templates, packagePartIdValue, frame, indexPath, context)
9536
10367
  };
9537
10368
  }
@@ -9610,7 +10441,7 @@ function compileText(graph, resolvedStyles, node, templates, packagePartIdValue,
9610
10441
  ...generatedStrokes ? { generatedStrokes } : {},
9611
10442
  ...shadowResult.shadow ? { shadow: shadowResult.shadow } : {},
9612
10443
  ...hyperlink ? { hyperlink } : {},
9613
- radiusEmu: parseLength(props.borderRadius, 0, 0, textLengthContext)
10444
+ radiusEmu: resolveCornerRadiusEmu(props.borderRadius, frame, textLengthContext)
9614
10445
  };
9615
10446
  }
9616
10447
  function compileImage(graph, resolvedStyles, node, templates, packagePartIdValue, parentFrame, indexPath, context) {
@@ -9623,6 +10454,7 @@ function compileImage(graph, resolvedStyles, node, templates, packagePartIdValue
9623
10454
  }, context);
9624
10455
  if (props.display === "none") return;
9625
10456
  const frame = frameToFrameIR$1(frameFromProps(props, parentFrame, void 0, context));
10457
+ const fit = normalizeProjectedImageFit(props.fit);
9626
10458
  const shadowResult = parseShadowSafely({
9627
10459
  property: "boxShadow",
9628
10460
  value: props.boxShadow
@@ -9642,6 +10474,7 @@ function compileImage(graph, resolvedStyles, node, templates, packagePartIdValue
9642
10474
  ...unsupportedTransformSemantics(props),
9643
10475
  ...unsupportedCompositingSemantics(props),
9644
10476
  ...unsupportedOpacityStackingContextSemantics(props),
10477
+ ...unsupportedObjectFitSemantics(props.fit),
9645
10478
  ...shadowResult.unsupportedSemantics
9646
10479
  ]
9647
10480
  });
@@ -9651,7 +10484,7 @@ function compileImage(graph, resolvedStyles, node, templates, packagePartIdValue
9651
10484
  mediaPartId: mediaPartIdForElement(base.id),
9652
10485
  sourceFrame: frame,
9653
10486
  source: assetSource(asset),
9654
- fit: props.fit ?? "contain",
10487
+ fit,
9655
10488
  objectPosition: parseObjectPositionValue(props.objectPosition, frame),
9656
10489
  ...parseImageCrop(props.crop) ? { crop: parseImageCrop(props.crop) } : {},
9657
10490
  transparency: props.transparency,
@@ -9728,7 +10561,7 @@ function compileShape(node, resolvedStyles, templates, packagePartIdValue, paren
9728
10561
  ...generatedStrokes ? { generatedStrokes } : {},
9729
10562
  ...shadowResult.shadow ? { shadow: shadowResult.shadow } : {},
9730
10563
  ...hyperlink ? { hyperlink } : {},
9731
- radiusEmu: parseLength(props.radius, 0, 0, context)
10564
+ radiusEmu: resolveCornerRadiusEmu(props.radius, frame, context)
9732
10565
  };
9733
10566
  }
9734
10567
  function compileElement(input) {
@@ -10976,7 +11809,7 @@ async function loadNodeOutputRuntime() {
10976
11809
  const status = nodeOutputRuntimeStatus();
10977
11810
  if (!status.ok) return status;
10978
11811
  try {
10979
- const { createNodeOutputByteSink, writeNodeOutput } = await import("./node-output-BXQOTLKj.mjs");
11812
+ const { createNodeOutputByteSink, writeNodeOutput } = await import("./node-output-L2bV2_8g.mjs");
10980
11813
  return {
10981
11814
  ok: true,
10982
11815
  createByteSink: createNodeOutputByteSink,
@@ -11720,21 +12553,11 @@ async function prepareRenderOutputSink(adapter) {
11720
12553
  path: output,
11721
12554
  runtime: outputRuntime
11722
12555
  };
11723
- try {
11724
- return {
11725
- requested: true,
11726
- mode: "sink",
11727
- path: output,
11728
- sink: outputRuntime.createByteSink({ output })
11729
- };
11730
- } catch (error) {
11731
- return {
11732
- requested: true,
11733
- mode: "sinkCreationFailed",
11734
- path: output,
11735
- error
11736
- };
11737
- }
12556
+ return {
12557
+ requested: true,
12558
+ mode: "deferredWrite",
12559
+ path: output
12560
+ };
11738
12561
  }
11739
12562
  async function writeRenderedArtifact(input) {
11740
12563
  if (!input.preparedOutput.requested) return {