@dongmingzhixiu/vuexir-compiler 0.4.5 → 0.4.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.
@@ -612,11 +612,30 @@ function emitNodeInner(node, ctx) {
612
612
  }
613
613
  // M5 position:absolute → 脱离文档流(父容器已转 ZStack;offset 实现 top/left 定位)
614
614
  if (props.position === 'absolute') {
615
- const x = props.absLeft ?? 0;
616
- const y = props.absTop ?? 0;
617
- box.push(`.offset(x: ${x}, y: ${y})`);
618
- if (props.absRight !== undefined || props.absBottom !== undefined) {
619
- ctx.warnings.push(`${ctx.path}: absolute 的 right/bottom 定位暂不支持(仅 left/top),已忽略`);
615
+ const hasRB = props.absRight !== undefined || props.absBottom !== undefined;
616
+ if (hasRB) {
617
+ // R131:right/bottom 定位 → 用对齐 + 内边距表达(此前直接丢弃,导致元素重叠、内容被盖住)
618
+ const v = props.absBottom !== undefined ? 'bottom' : props.absTop !== undefined ? 'top' : 'center';
619
+ const h = props.absRight !== undefined ? 'trailing' : props.absLeft !== undefined ? 'leading' : 'center';
620
+ const align = v === 'center' && h === 'center'
621
+ ? 'center'
622
+ : v === 'center'
623
+ ? h
624
+ : h === 'center'
625
+ ? v
626
+ : `${v}${h[0].toUpperCase()}${h.slice(1)}`;
627
+ box.push(`.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .${align})`);
628
+ if (props.absRight !== undefined)
629
+ box.push(`.padding(.trailing, ${props.absRight})`);
630
+ if (props.absBottom !== undefined)
631
+ box.push(`.padding(.bottom, ${props.absBottom})`);
632
+ if (props.absLeft !== undefined && h !== 'leading')
633
+ box.push(`.padding(.leading, ${props.absLeft})`);
634
+ if (props.absTop !== undefined && v !== 'top')
635
+ box.push(`.padding(.top, ${props.absTop})`);
636
+ }
637
+ else {
638
+ box.push(`.offset(x: ${props.absLeft ?? 0}, y: ${props.absTop ?? 0})`);
620
639
  }
621
640
  }
622
641
  // M5 v-show → opacity 动画切换(保留占位;状态名引用页面/容器同名 @State/@Binding)
@@ -697,6 +716,10 @@ function emitNodeInner(node, ctx) {
697
716
  const align = isRow ? (ALIGN_MAP[alignRaw] ?? '.top') : (FLEX_START_MAP[alignRaw] ?? '.leading');
698
717
  const stack = hasAbsolute ? 'ZStack' : isRow ? 'HStack' : 'VStack';
699
718
  const stackAlign = hasAbsolute ? '.topLeading' : align;
719
+ // R132:ZStack 里必须把「非绝对定位」的兄弟包成一个流式子容器,
720
+ // 否则它们会全部叠在左上角互相覆盖(主卡名字与日期重叠就是这个原因)
721
+ const flowChildren = hasAbsolute ? children.filter((c) => c.props?.position !== 'absolute') : [];
722
+ const absChildren = hasAbsolute ? children.filter((c) => c.props?.position === 'absolute') : [];
700
723
  const just = props.justifyContent;
701
724
  // R-H4:justify-content 的弹性分配仅在「分配方向」有确定空间时有意义。
702
725
  // column(主轴=垂直)需要容器高度确定(CSS:auto 高容器无剩余空间);
@@ -708,6 +731,49 @@ function emitNodeInner(node, ctx) {
708
731
  }
709
732
  // hasAbsolute 时无 flex 语义(ZStack 叠放)
710
733
  const justActive = justFlex && (isRow || selfDefinite) && !hasAbsolute;
734
+ // R132:绝对定位容器 → 非绝对子节点先包成一个流式 VStack(保持原有纵向排布),
735
+ // 绝对定位子节点再叠上去;否则全部叠在左上角互相覆盖
736
+ if (hasAbsolute && flowChildren.length > 0) {
737
+ const flowNode = {
738
+ type: 'group',
739
+ props: { ...props, position: undefined, absTop: undefined, absLeft: undefined, absRight: undefined, absBottom: undefined },
740
+ children: flowChildren,
741
+ };
742
+ const flowCode = emitNode(flowNode, {
743
+ parentAxis: dir,
744
+ level: L + 1,
745
+ definiteHeight: selfDefinite,
746
+ warnings: ctx.warnings,
747
+ runtime: ctx.runtime,
748
+ path: `${ctx.path}{flow}`,
749
+ inheritGap: ctx.inheritGap,
750
+ loop: ctx.loop,
751
+ dataProps: ctx.dataProps,
752
+ });
753
+ const absCode = absChildren
754
+ .map((c, i) => emitNode(c, {
755
+ parentAxis: dir,
756
+ level: L + 1,
757
+ definiteHeight: selfDefinite,
758
+ warnings: ctx.warnings,
759
+ runtime: ctx.runtime,
760
+ path: `${ctx.path}{abs${i}}`,
761
+ inheritGap: undefined,
762
+ loop: ctx.loop,
763
+ dataProps: ctx.dataProps,
764
+ }))
765
+ .join('\n');
766
+ const bg = props.background !== undefined ? pad(`Color(${props.background})`) : null;
767
+ return [
768
+ pad('ZStack(alignment: .topLeading) {'),
769
+ bg ? indent(L + 1) + bg.trim() : null,
770
+ flowCode,
771
+ absCode || null,
772
+ pad('}'),
773
+ ]
774
+ .filter((x) => x !== null)
775
+ .join('\n');
776
+ }
711
777
  // justifyContent:center → 首尾 Spacer;spaceBetween → 子间 Spacer(仅 column 需高度确定)
712
778
  const body = [];
713
779
  if (just === 'center' && justActive) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dongmingzhixiu/vuexir-compiler",
3
- "version": "0.4.5",
3
+ "version": "0.4.7",
4
4
  "description": "Vue SFC → IR → 原生源码(SwiftUI / Compose)编译器核心:纯函数、零 IO",
5
5
  "type": "module",
6
6
  "license": "MIT",