@dongmingzhixiu/vuexir-compiler 0.7.5 → 0.7.7

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.
@@ -9,6 +9,7 @@ declare const NAV_TEST_KT: (bundleId: string) => string;
9
9
  interface ComposeCtx {
10
10
  parentAxis?: 'row' | 'column' | 'box';
11
11
  inVerticalScroll?: boolean;
12
+ parentColumnHeightBounded?: boolean;
12
13
  runtimeAsset?: string;
13
14
  warnings: string[];
14
15
  pageId: string;
@@ -741,7 +741,10 @@ function borderModifiers(props) {
741
741
  return mods;
742
742
  }
743
743
  function flexModifier(props, ctx) {
744
- if (ctx?.parentAxis === 'box' || (ctx?.inVerticalScroll && ctx.parentAxis !== 'row'))
744
+ if (ctx?.parentAxis === 'box')
745
+ return '';
746
+ if (ctx?.inVerticalScroll && ctx.parentAxis !== 'row' &&
747
+ (!ctx.parentColumnHeightBounded || (props.flex ?? 0) <= 0))
745
748
  return '';
746
749
  if (props.flex === undefined && props.minWidth === 0 && ctx?.parentAxis === 'row')
747
750
  return 'Modifier.weight(1f, fill = false)';
@@ -1163,6 +1166,10 @@ function stretchModifiers(parentStretch, node) {
1163
1166
  return [];
1164
1167
  return ['Modifier.fillMaxWidth()'];
1165
1168
  }
1169
+ function hasDeclaredWidth(props) {
1170
+ return props.width !== undefined || props.widthFraction !== undefined ||
1171
+ props.widthDynamic !== undefined || props.widthFractionDynamic !== undefined;
1172
+ }
1166
1173
  /** R-PAGESCROLL 守卫:子树内是否存在 flex / marginTopAuto(→ Modifier.weight,滚动容器内不可用) */
1167
1174
  function subtreeHasWeight(node) {
1168
1175
  const p = node.props;
@@ -1208,6 +1215,14 @@ function emitNodeInner(node, ctx, depth, loop, useParamModifier = false, parentS
1208
1215
  const decorated = nd.children.flatMap((c, i) => c.props?.position === 'absolute' ? [c] : i === first ? [{ type: 'group', props: { flexDirection: p.flexDirection, alignItems: p.alignItems, justifyContent: p.justifyContent, gap: p.gap, padding: p.padding, ...((p.width !== undefined || p.widthDynamic) && (p.height !== undefined || p.heightDynamic) ? { width: 'fill', height: 'fill' } : {}) }, children: flow }] : []);
1209
1216
  return decorated.map((child) => emitNode(child, { ...ctx, parentAxis: 'box' }, d, loop)).join('\n');
1210
1217
  }
1218
+ const columnHasWidth = nd.type === 'root' || hasDeclaredWidth(p) ||
1219
+ (nd.type === 'group' && stretchModifiers(parentStretch, nd).length > 0) ||
1220
+ (ctx.parentAxis === 'row' && p.flex !== undefined);
1221
+ const rowContentWidth = ctx.parentAxis === 'row' && p.width === undefined && p.flex === undefined;
1222
+ // 普通列的固定高度或父列分配的完整权重重新提供有限的垂直空间。
1223
+ const columnHeightBounded = kind === 'Column' && nd.type === 'group' &&
1224
+ (typeof p.height === 'number' ||
1225
+ (ctx.parentAxis === 'column' && ctx.parentColumnHeightBounded === true && (p.flex ?? 0) > 0));
1211
1226
  return nd.children
1212
1227
  .map((c) => {
1213
1228
  const cp = (c.props ?? {});
@@ -1235,8 +1250,17 @@ function emitNodeInner(node, ctx, depth, loop, useParamModifier = false, parentS
1235
1250
  if (kind === 'Column' && cp.marginBottom !== undefined && cp.marginBottom !== 0) {
1236
1251
  post = post + '\n' + cpad + 'Spacer(\n' + cpad + ' modifier = Modifier.height(' + dp(cp.marginBottom) + '),\n' + cpad + ')\n';
1237
1252
  }
1238
- const stretch = kind === 'Column' && (p.alignItems === undefined || p.alignItems === 'stretch') && !(ctx.parentAxis === 'row' && p.width === undefined && p.flex === undefined) && cp.width === undefined && cp.flex === undefined && cp.position !== 'absolute' && !cp.marginLeftAuto;
1239
- const childCtx = { ...ctx, parentAxis: kind === 'Row' ? 'row' : kind === 'Box' ? 'box' : 'column' };
1253
+ // 纵向 flex 只分配高度,列宽已确定时仍按交叉轴拉伸。
1254
+ const autoWidth = cp.flex === undefined
1255
+ ? cp.width === undefined && !rowContentWidth
1256
+ : columnHasWidth && !hasDeclaredWidth(cp);
1257
+ const stretch = kind === 'Column' && (p.alignItems === undefined || p.alignItems === 'stretch') &&
1258
+ autoWidth && cp.position !== 'absolute' && !cp.marginLeftAuto;
1259
+ const childCtx = {
1260
+ ...ctx,
1261
+ parentAxis: kind === 'Row' ? 'row' : kind === 'Box' ? 'box' : 'column',
1262
+ parentColumnHeightBounded: columnHeightBounded,
1263
+ };
1240
1264
  const result = emitNode(c, childCtx, d, loop, false, stretch);
1241
1265
  if (childCtx.needsScope)
1242
1266
  ctx.needsScope = true;
@@ -510,6 +510,16 @@ export function boxModifiers(props) {
510
510
  mods.push('.clipped()');
511
511
  return mods;
512
512
  }
513
+ function columnStretchAlignment(node) {
514
+ const props = node.props;
515
+ // 将常规行放到拉伸区域的尾端,不插入会多占一份 gap 的 Spacer。
516
+ if (node.type === 'group' && props?.flexDirection === 'row' && props.justifyContent === 'end' &&
517
+ props.widthDynamic === undefined && props.widthFraction === undefined && props.widthFractionDynamic === undefined &&
518
+ !props.flexWrap && !props.gridColumns && !node.children?.some((child) => child.props?.position === 'absolute')) {
519
+ return '.trailing';
520
+ }
521
+ return props?.textAlign === 'center' ? '.center' : props?.textAlign === 'right' ? '.trailing' : '.leading';
522
+ }
513
523
  function emitChildren(children, axis, ctx, alignRaw = 'stretch', stretchCross = false) {
514
524
  if (!children || children.length === 0)
515
525
  return '';
@@ -562,7 +572,7 @@ function emitChildren(children, axis, ctx, alignRaw = 'stretch', stretchCross =
562
572
  // column:仅默认 stretch 时子项填满父宽(div block 语义);显式 start/center/end → 内容宽对齐
563
573
  const explicitCol = alignRaw === 'start' || alignRaw === 'center' || alignRaw === 'end';
564
574
  if (!explicitCol) {
565
- return body + '\n' + indent(ctx.level) + frameExpr('fillW', c.props?.textAlign === 'center' ? '.center' : c.props?.textAlign === 'right' ? '.trailing' : '.leading');
575
+ return body + '\n' + indent(ctx.level) + frameExpr('fillW', columnStretchAlignment(c));
566
576
  }
567
577
  return body;
568
578
  }
@@ -985,7 +995,7 @@ function emitNodeInner(node, ctx) {
985
995
  // 显式 start/center/end → 子项按内容宽对齐(CSS 交叉轴对齐语义)
986
996
  const explicitCol = (c.props?.alignSelf !== undefined && c.props.alignSelf !== 'stretch') || props.alignItems === 'start' || props.alignItems === 'center' || props.alignItems === 'end';
987
997
  if (!explicitCol) {
988
- body.push(indent(L + 1) + frameExpr('fillW', c.props?.textAlign === 'center' ? '.center' : c.props?.textAlign === 'right' ? '.trailing' : '.leading'));
998
+ body.push(indent(L + 1) + frameExpr('fillW', columnStretchAlignment(c)));
989
999
  }
990
1000
  }
991
1001
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dongmingzhixiu/vuexir-compiler",
3
- "version": "0.7.5",
3
+ "version": "0.7.7",
4
4
  "description": "Vue SFC → IR → 原生源码(SwiftUI / Compose)编译器核心:纯函数、零 IO",
5
5
  "type": "module",
6
6
  "license": "MIT",