@codehz/draw-call 0.5.0 → 0.5.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/browser/index.cjs +176 -103
- package/browser/index.d.cts +9 -4
- package/browser/index.d.ts +9 -4
- package/browser/index.js +175 -103
- package/node/index.cjs +176 -103
- package/node/index.d.cts +9 -4
- package/node/index.d.mts +9 -4
- package/node/index.mjs +175 -103
- package/package.json +2 -2
package/browser/index.cjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
1
2
|
|
|
2
3
|
//#region src/compat/index.ts
|
|
3
4
|
const DOMMatrix = typeof window !== "undefined" ? window.DOMMatrix : void 0;
|
|
@@ -82,6 +83,19 @@ function normalizeBorderRadius(value) {
|
|
|
82
83
|
|
|
83
84
|
//#endregion
|
|
84
85
|
//#region src/layout/components/box.ts
|
|
86
|
+
/**
|
|
87
|
+
* 安全获取元素的 margin
|
|
88
|
+
* Transform 元素没有 margin,返回默认 spacing
|
|
89
|
+
*/
|
|
90
|
+
function getElementMargin$2(element) {
|
|
91
|
+
if (element.type === "transform") return {
|
|
92
|
+
top: 0,
|
|
93
|
+
right: 0,
|
|
94
|
+
bottom: 0,
|
|
95
|
+
left: 0
|
|
96
|
+
};
|
|
97
|
+
return normalizeSpacing(element.margin);
|
|
98
|
+
}
|
|
85
99
|
function calcEffectiveSize(element, padding, availableWidth) {
|
|
86
100
|
return {
|
|
87
101
|
width: typeof element.width === "number" ? element.width - padding.left - padding.right : availableWidth > 0 ? availableWidth : 0,
|
|
@@ -91,7 +105,7 @@ function calcEffectiveSize(element, padding, availableWidth) {
|
|
|
91
105
|
function collectChildSizes(children, ctx, availableWidth, padding, measureChild) {
|
|
92
106
|
const childSizes = [];
|
|
93
107
|
for (const child of children) {
|
|
94
|
-
const childMargin =
|
|
108
|
+
const childMargin = getElementMargin$2(child);
|
|
95
109
|
const childSize = measureChild(child, ctx, availableWidth - padding.left - padding.right - childMargin.left - childMargin.right);
|
|
96
110
|
childSizes.push({
|
|
97
111
|
width: childSize.width,
|
|
@@ -160,7 +174,7 @@ function measureBoxSize(element, ctx, availableWidth, measureChild) {
|
|
|
160
174
|
contentHeight = wrapped.height;
|
|
161
175
|
} else for (let i = 0; i < children.length; i++) {
|
|
162
176
|
const child = children[i];
|
|
163
|
-
const childMargin =
|
|
177
|
+
const childMargin = getElementMargin$2(child);
|
|
164
178
|
const childSize = measureChild(child, ctx, availableWidth - padding.left - padding.right - childMargin.left - childMargin.right);
|
|
165
179
|
if (isRow) {
|
|
166
180
|
contentWidth += childSize.width + childMargin.left + childMargin.right;
|
|
@@ -394,6 +408,19 @@ function wrapRichText(ctx, spans, maxWidth, lineHeightScale = 1.2, elementStyle
|
|
|
394
408
|
//#endregion
|
|
395
409
|
//#region src/layout/components/stack.ts
|
|
396
410
|
/**
|
|
411
|
+
* 安全获取元素的 margin
|
|
412
|
+
* Transform 元素没有 margin,返回默认 spacing
|
|
413
|
+
*/
|
|
414
|
+
function getElementMargin$1(element) {
|
|
415
|
+
if (element.type === "transform") return {
|
|
416
|
+
top: 0,
|
|
417
|
+
right: 0,
|
|
418
|
+
bottom: 0,
|
|
419
|
+
left: 0
|
|
420
|
+
};
|
|
421
|
+
return normalizeSpacing(element.margin);
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
397
424
|
* 测量 Stack 元素的固有尺寸
|
|
398
425
|
*/
|
|
399
426
|
function measureStackSize(element, ctx, availableWidth, measureChild) {
|
|
@@ -402,7 +429,7 @@ function measureStackSize(element, ctx, availableWidth, measureChild) {
|
|
|
402
429
|
let contentHeight = 0;
|
|
403
430
|
const children = element.children ?? [];
|
|
404
431
|
for (const child of children) {
|
|
405
|
-
const childMargin =
|
|
432
|
+
const childMargin = getElementMargin$1(child);
|
|
406
433
|
const childSize = measureChild(child, ctx, availableWidth - padding.left - padding.right - childMargin.left - childMargin.right);
|
|
407
434
|
contentWidth = Math.max(contentWidth, childSize.width + childMargin.left + childMargin.right);
|
|
408
435
|
contentHeight = Math.max(contentHeight, childSize.height + childMargin.top + childMargin.bottom);
|
|
@@ -641,18 +668,79 @@ function sizeNeedsParent(size) {
|
|
|
641
668
|
|
|
642
669
|
//#endregion
|
|
643
670
|
//#region src/layout/engine.ts
|
|
671
|
+
/**
|
|
672
|
+
* 类型守卫:检查 Element 是否为 LayoutElement(非 Transform)
|
|
673
|
+
* 由于 Transform 元素在 computeLayoutImpl 开始时被处理,
|
|
674
|
+
* 此时只应处理 LayoutElement
|
|
675
|
+
*/
|
|
676
|
+
function assertLayoutElement(element) {
|
|
677
|
+
if (element.type === "transform") throw new Error("Transform elements should be handled at entry point");
|
|
678
|
+
}
|
|
679
|
+
/**
|
|
680
|
+
* 安全获取元素的 margin
|
|
681
|
+
* Transform 元素没有 margin,返回默认 spacing
|
|
682
|
+
*/
|
|
683
|
+
function getElementMargin(element) {
|
|
684
|
+
if (element.type === "transform") return {
|
|
685
|
+
top: 0,
|
|
686
|
+
right: 0,
|
|
687
|
+
bottom: 0,
|
|
688
|
+
left: 0
|
|
689
|
+
};
|
|
690
|
+
return normalizeSpacing(element.margin);
|
|
691
|
+
}
|
|
692
|
+
/**
|
|
693
|
+
* 安全获取元素的布局属性(width, height, flex等)
|
|
694
|
+
* Transform 元素这些属性为 undefined
|
|
695
|
+
*/
|
|
696
|
+
function getElementLayoutProps(element) {
|
|
697
|
+
if (element.type === "transform") return {
|
|
698
|
+
width: void 0,
|
|
699
|
+
height: void 0,
|
|
700
|
+
flex: void 0,
|
|
701
|
+
minWidth: void 0,
|
|
702
|
+
maxWidth: void 0,
|
|
703
|
+
minHeight: void 0,
|
|
704
|
+
maxHeight: void 0,
|
|
705
|
+
alignSelf: void 0
|
|
706
|
+
};
|
|
707
|
+
const le = element;
|
|
708
|
+
return {
|
|
709
|
+
width: le.width,
|
|
710
|
+
height: le.height,
|
|
711
|
+
flex: le.flex,
|
|
712
|
+
minWidth: le.minWidth,
|
|
713
|
+
maxWidth: le.maxWidth,
|
|
714
|
+
minHeight: le.minHeight,
|
|
715
|
+
maxHeight: le.maxHeight,
|
|
716
|
+
alignSelf: le.alignSelf
|
|
717
|
+
};
|
|
718
|
+
}
|
|
719
|
+
/**
|
|
720
|
+
* 布局计算主函数
|
|
721
|
+
* 内部使用 Element 类型以支持 Transform,外部通过 LayoutElement 约束类型
|
|
722
|
+
*/
|
|
644
723
|
function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
645
|
-
|
|
646
|
-
|
|
724
|
+
return computeLayoutImpl(element, ctx, constraints, x, y);
|
|
725
|
+
}
|
|
726
|
+
/**
|
|
727
|
+
* 内部实现函数,处理所有元素类型包括 Transform
|
|
728
|
+
*/
|
|
729
|
+
function computeLayoutImpl(element, ctx, constraints, x = 0, y = 0) {
|
|
730
|
+
if (element.type === "transform") return computeLayoutImpl(element.children, ctx, constraints, x, y);
|
|
731
|
+
assertLayoutElement(element);
|
|
732
|
+
const layoutElement = element;
|
|
733
|
+
const margin = normalizeSpacing(layoutElement.margin);
|
|
734
|
+
const padding = normalizeSpacing("padding" in layoutElement ? layoutElement.padding : void 0);
|
|
647
735
|
const availableWidth = constraints.maxWidth - margin.left - margin.right;
|
|
648
736
|
const availableHeight = constraints.maxHeight - margin.top - margin.bottom;
|
|
649
|
-
const intrinsic = measureIntrinsicSize(
|
|
650
|
-
let width = constraints.minWidth === constraints.maxWidth && constraints.minWidth > 0 ? constraints.maxWidth - margin.left - margin.right : resolveSize(
|
|
651
|
-
let height = constraints.minHeight === constraints.maxHeight && constraints.minHeight > 0 ? constraints.maxHeight - margin.top - margin.bottom : resolveSize(
|
|
652
|
-
if (
|
|
653
|
-
if (
|
|
654
|
-
if (
|
|
655
|
-
if (
|
|
737
|
+
const intrinsic = measureIntrinsicSize(layoutElement, ctx, availableWidth);
|
|
738
|
+
let width = constraints.minWidth === constraints.maxWidth && constraints.minWidth > 0 ? constraints.maxWidth - margin.left - margin.right : resolveSize(layoutElement.width, availableWidth, intrinsic.width);
|
|
739
|
+
let height = constraints.minHeight === constraints.maxHeight && constraints.minHeight > 0 ? constraints.maxHeight - margin.top - margin.bottom : resolveSize(layoutElement.height, availableHeight, intrinsic.height);
|
|
740
|
+
if (layoutElement.minWidth !== void 0) width = Math.max(width, layoutElement.minWidth);
|
|
741
|
+
if (layoutElement.maxWidth !== void 0) width = Math.min(width, layoutElement.maxWidth);
|
|
742
|
+
if (layoutElement.minHeight !== void 0) height = Math.max(height, layoutElement.minHeight);
|
|
743
|
+
if (layoutElement.maxHeight !== void 0) height = Math.min(height, layoutElement.maxHeight);
|
|
656
744
|
const actualX = x + margin.left;
|
|
657
745
|
const actualY = y + margin.top;
|
|
658
746
|
const contentX = actualX + padding.left;
|
|
@@ -660,7 +748,7 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
660
748
|
const contentWidth = width - padding.left - padding.right;
|
|
661
749
|
const contentHeight = height - padding.top - padding.bottom;
|
|
662
750
|
const node = {
|
|
663
|
-
element,
|
|
751
|
+
element: layoutElement,
|
|
664
752
|
layout: {
|
|
665
753
|
x: actualX,
|
|
666
754
|
y: actualY,
|
|
@@ -673,14 +761,14 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
673
761
|
},
|
|
674
762
|
children: []
|
|
675
763
|
};
|
|
676
|
-
if (
|
|
677
|
-
const font =
|
|
678
|
-
if (
|
|
679
|
-
let { lines, offsets } = wrapText(ctx,
|
|
680
|
-
if (
|
|
681
|
-
lines = lines.slice(0,
|
|
682
|
-
offsets = offsets.slice(0,
|
|
683
|
-
if (
|
|
764
|
+
if (layoutElement.type === "text") {
|
|
765
|
+
const font = layoutElement.font ?? {};
|
|
766
|
+
if (layoutElement.wrap && contentWidth > 0) {
|
|
767
|
+
let { lines, offsets } = wrapText(ctx, layoutElement.content, contentWidth, font);
|
|
768
|
+
if (layoutElement.maxLines && lines.length > layoutElement.maxLines) {
|
|
769
|
+
lines = lines.slice(0, layoutElement.maxLines);
|
|
770
|
+
offsets = offsets.slice(0, layoutElement.maxLines);
|
|
771
|
+
if (layoutElement.ellipsis && lines.length > 0) {
|
|
684
772
|
const lastIdx = lines.length - 1;
|
|
685
773
|
const truncated = truncateText(ctx, lines[lastIdx], contentWidth, font);
|
|
686
774
|
lines[lastIdx] = truncated.text;
|
|
@@ -690,17 +778,17 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
690
778
|
node.lines = lines;
|
|
691
779
|
node.lineOffsets = offsets;
|
|
692
780
|
} else {
|
|
693
|
-
const { text, offset } = truncateText(ctx,
|
|
781
|
+
const { text, offset } = truncateText(ctx, layoutElement.content, contentWidth > 0 && layoutElement.ellipsis ? contentWidth : Infinity, font);
|
|
694
782
|
node.lines = [text];
|
|
695
783
|
node.lineOffsets = [offset];
|
|
696
784
|
}
|
|
697
785
|
}
|
|
698
|
-
if (
|
|
699
|
-
const lineHeight =
|
|
700
|
-
let lines = wrapRichText(ctx,
|
|
701
|
-
if (
|
|
702
|
-
lines = lines.slice(0,
|
|
703
|
-
if (
|
|
786
|
+
if (layoutElement.type === "richtext") {
|
|
787
|
+
const lineHeight = layoutElement.lineHeight ?? 1.2;
|
|
788
|
+
let lines = wrapRichText(ctx, layoutElement.spans, contentWidth, lineHeight);
|
|
789
|
+
if (layoutElement.maxLines && lines.length > layoutElement.maxLines) {
|
|
790
|
+
lines = lines.slice(0, layoutElement.maxLines);
|
|
791
|
+
if (layoutElement.ellipsis && lines.length > 0) {
|
|
704
792
|
const lastLine = lines[lines.length - 1];
|
|
705
793
|
if (lastLine.segments.length > 0) {
|
|
706
794
|
const lastSeg = lastLine.segments[lastLine.segments.length - 1];
|
|
@@ -712,19 +800,19 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
712
800
|
}
|
|
713
801
|
node.richLines = lines;
|
|
714
802
|
}
|
|
715
|
-
if (
|
|
716
|
-
const children =
|
|
717
|
-
if (
|
|
718
|
-
const stackAlign =
|
|
719
|
-
const stackJustify =
|
|
803
|
+
if (layoutElement.type === "box" || layoutElement.type === "stack") {
|
|
804
|
+
const children = layoutElement.children ?? [];
|
|
805
|
+
if (layoutElement.type === "stack") {
|
|
806
|
+
const stackAlign = layoutElement.align ?? "start";
|
|
807
|
+
const stackJustify = layoutElement.justify ?? "start";
|
|
720
808
|
for (const child of children) {
|
|
721
|
-
const childNode =
|
|
809
|
+
const childNode = computeLayoutImpl(child, ctx, {
|
|
722
810
|
minWidth: 0,
|
|
723
811
|
maxWidth: contentWidth,
|
|
724
812
|
minHeight: 0,
|
|
725
813
|
maxHeight: contentHeight
|
|
726
814
|
}, contentX, contentY);
|
|
727
|
-
const childMargin =
|
|
815
|
+
const childMargin = getElementMargin(child);
|
|
728
816
|
const childOuterWidth = childNode.layout.width + childMargin.left + childMargin.right;
|
|
729
817
|
const childOuterHeight = childNode.layout.height + childMargin.top + childMargin.bottom;
|
|
730
818
|
let offsetX = 0;
|
|
@@ -737,19 +825,21 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
737
825
|
node.children.push(childNode);
|
|
738
826
|
}
|
|
739
827
|
} else {
|
|
740
|
-
const
|
|
741
|
-
const
|
|
742
|
-
const
|
|
743
|
-
const
|
|
744
|
-
const
|
|
828
|
+
const boxElement = layoutElement;
|
|
829
|
+
const direction = boxElement.direction ?? "row";
|
|
830
|
+
const justify = boxElement.justify ?? "start";
|
|
831
|
+
const align = boxElement.align ?? "stretch";
|
|
832
|
+
const gap = boxElement.gap ?? 0;
|
|
833
|
+
const wrap = boxElement.wrap ?? false;
|
|
745
834
|
const isRow = direction === "row" || direction === "row-reverse";
|
|
746
835
|
const isReverse = direction === "row-reverse" || direction === "column-reverse";
|
|
747
836
|
const getContentMainSize = () => isRow ? contentWidth : contentHeight;
|
|
748
837
|
const getContentCrossSize = () => isRow ? contentHeight : contentWidth;
|
|
749
838
|
const childInfos = [];
|
|
750
839
|
for (const child of children) {
|
|
751
|
-
const childMargin =
|
|
752
|
-
const
|
|
840
|
+
const childMargin = getElementMargin(child);
|
|
841
|
+
const childProps = getElementLayoutProps(child);
|
|
842
|
+
const childFlex = childProps.flex ?? 0;
|
|
753
843
|
if (childFlex > 0) childInfos.push({
|
|
754
844
|
element: child,
|
|
755
845
|
width: 0,
|
|
@@ -759,10 +849,10 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
759
849
|
});
|
|
760
850
|
else {
|
|
761
851
|
const size = measureIntrinsicSize(child, ctx, contentWidth - childMargin.left - childMargin.right);
|
|
762
|
-
const shouldStretchWidth = !isRow &&
|
|
763
|
-
const shouldStretchHeight = isRow &&
|
|
764
|
-
let w = sizeNeedsParent(
|
|
765
|
-
let h = sizeNeedsParent(
|
|
852
|
+
const shouldStretchWidth = !isRow && childProps.width === void 0 && align === "stretch";
|
|
853
|
+
const shouldStretchHeight = isRow && childProps.height === void 0 && align === "stretch";
|
|
854
|
+
let w = sizeNeedsParent(childProps.width) ? resolveSize(childProps.width, contentWidth - childMargin.left - childMargin.right, size.width) : resolveSize(childProps.width, 0, size.width);
|
|
855
|
+
let h = sizeNeedsParent(childProps.height) ? resolveSize(childProps.height, contentHeight - childMargin.top - childMargin.bottom, size.height) : resolveSize(childProps.height, 0, size.height);
|
|
766
856
|
if (shouldStretchWidth && !wrap) w = contentWidth - childMargin.left - childMargin.right;
|
|
767
857
|
if (shouldStretchHeight && !wrap) h = contentHeight - childMargin.top - childMargin.bottom;
|
|
768
858
|
childInfos.push({
|
|
@@ -803,14 +893,15 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
803
893
|
const availableForFlex = Math.max(0, mainAxisSize - totalFixed - totalGap);
|
|
804
894
|
for (const info of lineInfos) if (info.flex > 0) {
|
|
805
895
|
const flexSize = totalFlex > 0 ? availableForFlex * info.flex / totalFlex : 0;
|
|
896
|
+
const childProps = getElementLayoutProps(info.element);
|
|
806
897
|
if (isRow) {
|
|
807
898
|
info.width = flexSize;
|
|
808
899
|
const size = measureIntrinsicSize(info.element, ctx, flexSize);
|
|
809
|
-
info.height = sizeNeedsParent(
|
|
900
|
+
info.height = sizeNeedsParent(childProps.height) ? resolveSize(childProps.height, contentHeight - info.margin.top - info.margin.bottom, size.height) : resolveSize(childProps.height, 0, size.height);
|
|
810
901
|
} else {
|
|
811
902
|
info.height = flexSize;
|
|
812
903
|
const size = measureIntrinsicSize(info.element, ctx, contentWidth - info.margin.left - info.margin.right);
|
|
813
|
-
info.width = sizeNeedsParent(
|
|
904
|
+
info.width = sizeNeedsParent(childProps.width) ? resolveSize(childProps.width, contentWidth - info.margin.left - info.margin.right, size.width) : resolveSize(childProps.width, 0, size.width);
|
|
814
905
|
}
|
|
815
906
|
}
|
|
816
907
|
}
|
|
@@ -861,17 +952,18 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
861
952
|
const orderedInfos = isReverse ? [...lineInfos].reverse() : lineInfos;
|
|
862
953
|
for (let i = 0; i < orderedInfos.length; i++) {
|
|
863
954
|
const info = orderedInfos[i];
|
|
955
|
+
const childProps = getElementLayoutProps(info.element);
|
|
864
956
|
const crossAxisSize = wrap ? lineCrossSize : getContentCrossSize();
|
|
865
957
|
const childCrossSize = isRow ? info.height + info.margin.top + info.margin.bottom : info.width + info.margin.left + info.margin.right;
|
|
866
958
|
let itemCrossOffset = 0;
|
|
867
|
-
const effectiveAlign =
|
|
959
|
+
const effectiveAlign = childProps.alignSelf ?? align;
|
|
868
960
|
if (effectiveAlign === "start") itemCrossOffset = 0;
|
|
869
961
|
else if (effectiveAlign === "end") itemCrossOffset = crossAxisSize - childCrossSize;
|
|
870
962
|
else if (effectiveAlign === "center") itemCrossOffset = (crossAxisSize - childCrossSize) / 2;
|
|
871
963
|
else if (effectiveAlign === "stretch") {
|
|
872
964
|
itemCrossOffset = 0;
|
|
873
|
-
if (isRow &&
|
|
874
|
-
else if (!isRow &&
|
|
965
|
+
if (isRow && childProps.height === void 0) info.height = crossAxisSize - info.margin.top - info.margin.bottom;
|
|
966
|
+
else if (!isRow && childProps.width === void 0) info.width = crossAxisSize - info.margin.left - info.margin.right;
|
|
875
967
|
}
|
|
876
968
|
const childX = isRow ? contentX + mainOffset + info.margin.left : contentX + crossOffset + itemCrossOffset + info.margin.left;
|
|
877
969
|
const childY = isRow ? contentY + crossOffset + itemCrossOffset + info.margin.top : contentY + mainOffset + info.margin.top;
|
|
@@ -880,26 +972,29 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
880
972
|
let minHeight = 0;
|
|
881
973
|
let maxHeight = info.height;
|
|
882
974
|
let shouldStretchCross = false;
|
|
883
|
-
if (info.flex > 0)
|
|
884
|
-
|
|
885
|
-
if (
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
975
|
+
if (info.flex > 0) {
|
|
976
|
+
const childProps = getElementLayoutProps(info.element);
|
|
977
|
+
if (isRow) {
|
|
978
|
+
minWidth = maxWidth = info.width;
|
|
979
|
+
if (childProps.height === void 0 && align === "stretch") {
|
|
980
|
+
minHeight = info.height;
|
|
981
|
+
maxHeight = boxElement.height !== void 0 ? info.height : Infinity;
|
|
982
|
+
shouldStretchCross = true;
|
|
983
|
+
}
|
|
984
|
+
} else {
|
|
985
|
+
minHeight = maxHeight = info.height;
|
|
986
|
+
if (childProps.width === void 0 && align === "stretch") {
|
|
987
|
+
minWidth = info.width;
|
|
988
|
+
maxWidth = boxElement.width !== void 0 ? info.width : Infinity;
|
|
989
|
+
shouldStretchCross = true;
|
|
990
|
+
}
|
|
889
991
|
}
|
|
890
992
|
} else {
|
|
891
|
-
|
|
892
|
-
if (
|
|
893
|
-
|
|
894
|
-
maxWidth = element.width !== void 0 ? info.width : Infinity;
|
|
895
|
-
shouldStretchCross = true;
|
|
896
|
-
}
|
|
993
|
+
const childProps = getElementLayoutProps(info.element);
|
|
994
|
+
if (!isRow && childProps.width === void 0 && align === "stretch") minWidth = maxWidth = crossAxisSize - info.margin.left - info.margin.right;
|
|
995
|
+
if (isRow && childProps.height === void 0 && align === "stretch") minHeight = maxHeight = crossAxisSize - info.margin.top - info.margin.bottom;
|
|
897
996
|
}
|
|
898
|
-
|
|
899
|
-
if (!isRow && info.element.width === void 0 && align === "stretch") minWidth = maxWidth = crossAxisSize - info.margin.left - info.margin.right;
|
|
900
|
-
if (isRow && info.element.height === void 0 && align === "stretch") minHeight = maxHeight = crossAxisSize - info.margin.top - info.margin.bottom;
|
|
901
|
-
}
|
|
902
|
-
const childNode = computeLayout(info.element, ctx, {
|
|
997
|
+
const childNode = computeLayoutImpl(info.element, ctx, {
|
|
903
998
|
minWidth,
|
|
904
999
|
maxWidth,
|
|
905
1000
|
minHeight,
|
|
@@ -922,12 +1017,12 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
922
1017
|
crossOffset += lineCrossSize;
|
|
923
1018
|
if (lineIndex < lines.length - 1) crossOffset += gap;
|
|
924
1019
|
}
|
|
925
|
-
if (wrap &&
|
|
1020
|
+
if (wrap && boxElement.height === void 0 && isRow) {
|
|
926
1021
|
const actualContentHeight = crossOffset;
|
|
927
1022
|
const actualHeight = actualContentHeight + padding.top + padding.bottom;
|
|
928
1023
|
node.layout.height = actualHeight;
|
|
929
1024
|
node.layout.contentHeight = actualContentHeight;
|
|
930
|
-
} else if (wrap &&
|
|
1025
|
+
} else if (wrap && boxElement.width === void 0 && !isRow) {
|
|
931
1026
|
const actualContentWidth = crossOffset;
|
|
932
1027
|
const actualWidth = actualContentWidth + padding.left + padding.right;
|
|
933
1028
|
node.layout.width = actualWidth;
|
|
@@ -936,7 +1031,7 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
936
1031
|
if (!wrap) {
|
|
937
1032
|
let maxChildCrossSize = 0;
|
|
938
1033
|
for (const childNode of node.children) {
|
|
939
|
-
const childMargin =
|
|
1034
|
+
const childMargin = getElementMargin(childNode.element);
|
|
940
1035
|
if (isRow) {
|
|
941
1036
|
const childOuterHeight = childNode.layout.height + childMargin.top + childMargin.bottom;
|
|
942
1037
|
maxChildCrossSize = Math.max(maxChildCrossSize, childOuterHeight);
|
|
@@ -945,13 +1040,13 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
945
1040
|
maxChildCrossSize = Math.max(maxChildCrossSize, childOuterWidth);
|
|
946
1041
|
}
|
|
947
1042
|
}
|
|
948
|
-
if (isRow &&
|
|
1043
|
+
if (isRow && boxElement.height === void 0) {
|
|
949
1044
|
const actualHeight = maxChildCrossSize + padding.top + padding.bottom;
|
|
950
1045
|
if (actualHeight > node.layout.height) {
|
|
951
1046
|
node.layout.height = actualHeight;
|
|
952
1047
|
node.layout.contentHeight = maxChildCrossSize;
|
|
953
1048
|
}
|
|
954
|
-
} else if (!isRow &&
|
|
1049
|
+
} else if (!isRow && boxElement.width === void 0) {
|
|
955
1050
|
const actualWidth = maxChildCrossSize + padding.left + padding.right;
|
|
956
1051
|
if (actualWidth > node.layout.width) {
|
|
957
1052
|
node.layout.width = actualWidth;
|
|
@@ -961,48 +1056,24 @@ function computeLayout(element, ctx, constraints, x = 0, y = 0) {
|
|
|
961
1056
|
}
|
|
962
1057
|
if (isReverse) node.children.reverse();
|
|
963
1058
|
}
|
|
964
|
-
} else if (
|
|
965
|
-
const child =
|
|
966
|
-
if (child) {
|
|
967
|
-
const childMargin = normalizeSpacing(child.margin);
|
|
968
|
-
const childNode = computeLayout(child, ctx, {
|
|
969
|
-
minWidth: 0,
|
|
970
|
-
maxWidth: contentWidth,
|
|
971
|
-
minHeight: 0,
|
|
972
|
-
maxHeight: contentHeight
|
|
973
|
-
}, contentX, contentY);
|
|
974
|
-
node.children.push(childNode);
|
|
975
|
-
if (element.width === void 0) {
|
|
976
|
-
const childOuterWidth = childNode.layout.width + childMargin.left + childMargin.right;
|
|
977
|
-
const actualWidth = childOuterWidth + padding.left + padding.right;
|
|
978
|
-
node.layout.width = actualWidth;
|
|
979
|
-
node.layout.contentWidth = childOuterWidth;
|
|
980
|
-
}
|
|
981
|
-
if (element.height === void 0) {
|
|
982
|
-
const childOuterHeight = childNode.layout.height + childMargin.top + childMargin.bottom;
|
|
983
|
-
const actualHeight = childOuterHeight + padding.top + padding.bottom;
|
|
984
|
-
node.layout.height = actualHeight;
|
|
985
|
-
node.layout.contentHeight = childOuterHeight;
|
|
986
|
-
}
|
|
987
|
-
}
|
|
988
|
-
} else if (element.type === "customdraw") {
|
|
989
|
-
const child = element.children;
|
|
1059
|
+
} else if (layoutElement.type === "customdraw") {
|
|
1060
|
+
const child = layoutElement.children;
|
|
990
1061
|
if (child) {
|
|
991
1062
|
const childMargin = normalizeSpacing(child.margin);
|
|
992
|
-
const childNode =
|
|
1063
|
+
const childNode = computeLayoutImpl(child, ctx, {
|
|
993
1064
|
minWidth: 0,
|
|
994
1065
|
maxWidth: contentWidth,
|
|
995
1066
|
minHeight: 0,
|
|
996
1067
|
maxHeight: contentHeight
|
|
997
1068
|
}, contentX, contentY);
|
|
998
1069
|
node.children.push(childNode);
|
|
999
|
-
if (
|
|
1070
|
+
if (layoutElement.width === void 0) {
|
|
1000
1071
|
const childOuterWidth = childNode.layout.width + childMargin.left + childMargin.right;
|
|
1001
1072
|
const actualWidth = childOuterWidth + padding.left + padding.right;
|
|
1002
1073
|
node.layout.width = actualWidth;
|
|
1003
1074
|
node.layout.contentWidth = childOuterWidth;
|
|
1004
1075
|
}
|
|
1005
|
-
if (
|
|
1076
|
+
if (layoutElement.height === void 0) {
|
|
1006
1077
|
const childOuterHeight = childNode.layout.height + childMargin.top + childMargin.bottom;
|
|
1007
1078
|
const actualHeight = childOuterHeight + padding.top + padding.bottom;
|
|
1008
1079
|
node.layout.height = actualHeight;
|
|
@@ -2012,10 +2083,12 @@ function getElementType(element) {
|
|
|
2012
2083
|
switch (element.type) {
|
|
2013
2084
|
case "box": return "Box";
|
|
2014
2085
|
case "text": return `Text "${element.content.slice(0, 20)}${element.content.length > 20 ? "..." : ""}"`;
|
|
2086
|
+
case "richtext": return "RichText";
|
|
2015
2087
|
case "stack": return "Stack";
|
|
2016
2088
|
case "image": return "Image";
|
|
2017
2089
|
case "svg": return "Svg";
|
|
2018
|
-
|
|
2090
|
+
case "transform": return "Transform";
|
|
2091
|
+
case "customdraw": return "CustomDraw";
|
|
2019
2092
|
}
|
|
2020
2093
|
}
|
|
2021
2094
|
/**
|
package/browser/index.d.cts
CHANGED
|
@@ -363,7 +363,8 @@ interface CustomDrawProps extends LayoutProps {
|
|
|
363
363
|
interface CustomDrawElement extends ElementBase, CustomDrawProps {
|
|
364
364
|
type: "customdraw";
|
|
365
365
|
}
|
|
366
|
-
type
|
|
366
|
+
type LayoutElement = BoxElement | TextElement | RichTextElement | ImageElement | SvgElement | StackElement | CustomDrawElement;
|
|
367
|
+
type Element = LayoutElement | TransformElement;
|
|
367
368
|
//#endregion
|
|
368
369
|
//#region node_modules/@napi-rs/canvas/index.d.ts
|
|
369
370
|
interface CanvasRenderingContext2D$1 extends CanvasCompositing, CanvasDrawPath, CanvasFillStrokeStyles, CanvasFilters, CanvasImageData, CanvasImageSmoothing, CanvasPath, CanvasPathDrawingStyles, CanvasRect, CanvasSettings, CanvasShadowStyles, CanvasState, CanvasText, CanvasTextDrawingStyles, CanvasTransform, CanvasPDFAnnotations {}
|
|
@@ -926,7 +927,7 @@ interface DrawCallCanvas<T extends HTMLCanvasElement | OffscreenCanvas | Canvas
|
|
|
926
927
|
readonly height: number;
|
|
927
928
|
readonly pixelRatio: number;
|
|
928
929
|
readonly canvas: T;
|
|
929
|
-
render(element:
|
|
930
|
+
render(element: LayoutElement): LayoutNode;
|
|
930
931
|
clear(): void;
|
|
931
932
|
getContext(): CanvasRenderingContext2D;
|
|
932
933
|
toDataURL(type?: string, quality?: number): string;
|
|
@@ -975,7 +976,11 @@ declare function Text(props: TextProps): TextElement;
|
|
|
975
976
|
declare function Transform(props: TransformProps): TransformElement;
|
|
976
977
|
//#endregion
|
|
977
978
|
//#region src/layout/engine.d.ts
|
|
978
|
-
|
|
979
|
+
/**
|
|
980
|
+
* 布局计算主函数
|
|
981
|
+
* 内部使用 Element 类型以支持 Transform,外部通过 LayoutElement 约束类型
|
|
982
|
+
*/
|
|
983
|
+
declare function computeLayout(element: LayoutElement, ctx: MeasureContext, constraints: LayoutConstraints, x?: number, y?: number): LayoutNode;
|
|
979
984
|
//#endregion
|
|
980
985
|
//#region src/layout/utils/print.d.ts
|
|
981
986
|
/**
|
|
@@ -990,4 +995,4 @@ declare function printLayout(node: LayoutNode): void;
|
|
|
990
995
|
*/
|
|
991
996
|
declare function layoutToString(node: LayoutNode, _indent?: string): string;
|
|
992
997
|
//#endregion
|
|
993
|
-
export { type AlignItems, type AlignSelf, type Border, type Bounds, Box, type BoxElement, type BoxProps, type CanvasOptions, type Color, type ColorStop, type ContainerLayoutProps, CustomDraw, type CustomDrawElement, type CustomDrawProps, type DrawCallCanvas, type Element, type FlexDirection, type FontProps, type GradientDescriptor, Image, type JustifyContent, type LayoutNode, type LayoutProps, type LinearGradientDescriptor, type MeasureContext, type ProxiedCanvasContextOptions, type RadialGradientDescriptor, RichText, type RichTextElement, type RichTextProps, type RichTextSpan, type Shadow, type Size, type Spacing, Stack, type StackAlign, type StackElement, type StackProps, type StrokeProps, Svg, type SvgAlign, type SvgChild, type SvgCircleChild, type SvgElement, type SvgEllipseChild, type SvgGroupChild, type SvgLineChild, type SvgPathChild, type SvgPolygonChild, type SvgPolylineChild, type SvgProps, type SvgRectChild, type SvgStyleProps, type SvgTextChild, type SvgTransformProps, Text, type TextElement, type TextProps, Transform, type TransformElement, type TransformProps, computeLayout, createCanvas, createCanvasMeasureContext, layoutToString, linearGradient, printLayout, radialGradient, svg };
|
|
998
|
+
export { type AlignItems, type AlignSelf, type Border, type Bounds, Box, type BoxElement, type BoxProps, type CanvasOptions, type Color, type ColorStop, type ContainerLayoutProps, CustomDraw, type CustomDrawElement, type CustomDrawProps, type DrawCallCanvas, type Element, type FlexDirection, type FontProps, type GradientDescriptor, Image, type JustifyContent, type LayoutElement, type LayoutNode, type LayoutProps, type LinearGradientDescriptor, type MeasureContext, type ProxiedCanvasContextOptions, type RadialGradientDescriptor, RichText, type RichTextElement, type RichTextProps, type RichTextSpan, type Shadow, type Size, type Spacing, Stack, type StackAlign, type StackElement, type StackProps, type StrokeProps, Svg, type SvgAlign, type SvgChild, type SvgCircleChild, type SvgElement, type SvgEllipseChild, type SvgGroupChild, type SvgLineChild, type SvgPathChild, type SvgPolygonChild, type SvgPolylineChild, type SvgProps, type SvgRectChild, type SvgStyleProps, type SvgTextChild, type SvgTransformProps, Text, type TextElement, type TextProps, Transform, type TransformElement, type TransformProps, computeLayout, createCanvas, createCanvasMeasureContext, layoutToString, linearGradient, printLayout, radialGradient, svg };
|
package/browser/index.d.ts
CHANGED
|
@@ -363,7 +363,8 @@ interface CustomDrawProps extends LayoutProps {
|
|
|
363
363
|
interface CustomDrawElement extends ElementBase, CustomDrawProps {
|
|
364
364
|
type: "customdraw";
|
|
365
365
|
}
|
|
366
|
-
type
|
|
366
|
+
type LayoutElement = BoxElement | TextElement | RichTextElement | ImageElement | SvgElement | StackElement | CustomDrawElement;
|
|
367
|
+
type Element = LayoutElement | TransformElement;
|
|
367
368
|
//#endregion
|
|
368
369
|
//#region node_modules/@napi-rs/canvas/index.d.ts
|
|
369
370
|
interface CanvasRenderingContext2D$1 extends CanvasCompositing, CanvasDrawPath, CanvasFillStrokeStyles, CanvasFilters, CanvasImageData, CanvasImageSmoothing, CanvasPath, CanvasPathDrawingStyles, CanvasRect, CanvasSettings, CanvasShadowStyles, CanvasState, CanvasText, CanvasTextDrawingStyles, CanvasTransform, CanvasPDFAnnotations {}
|
|
@@ -926,7 +927,7 @@ interface DrawCallCanvas<T extends HTMLCanvasElement | OffscreenCanvas | Canvas
|
|
|
926
927
|
readonly height: number;
|
|
927
928
|
readonly pixelRatio: number;
|
|
928
929
|
readonly canvas: T;
|
|
929
|
-
render(element:
|
|
930
|
+
render(element: LayoutElement): LayoutNode;
|
|
930
931
|
clear(): void;
|
|
931
932
|
getContext(): CanvasRenderingContext2D;
|
|
932
933
|
toDataURL(type?: string, quality?: number): string;
|
|
@@ -975,7 +976,11 @@ declare function Text(props: TextProps): TextElement;
|
|
|
975
976
|
declare function Transform(props: TransformProps): TransformElement;
|
|
976
977
|
//#endregion
|
|
977
978
|
//#region src/layout/engine.d.ts
|
|
978
|
-
|
|
979
|
+
/**
|
|
980
|
+
* 布局计算主函数
|
|
981
|
+
* 内部使用 Element 类型以支持 Transform,外部通过 LayoutElement 约束类型
|
|
982
|
+
*/
|
|
983
|
+
declare function computeLayout(element: LayoutElement, ctx: MeasureContext, constraints: LayoutConstraints, x?: number, y?: number): LayoutNode;
|
|
979
984
|
//#endregion
|
|
980
985
|
//#region src/layout/utils/print.d.ts
|
|
981
986
|
/**
|
|
@@ -990,4 +995,4 @@ declare function printLayout(node: LayoutNode): void;
|
|
|
990
995
|
*/
|
|
991
996
|
declare function layoutToString(node: LayoutNode, _indent?: string): string;
|
|
992
997
|
//#endregion
|
|
993
|
-
export { type AlignItems, type AlignSelf, type Border, type Bounds, Box, type BoxElement, type BoxProps, type CanvasOptions, type Color, type ColorStop, type ContainerLayoutProps, CustomDraw, type CustomDrawElement, type CustomDrawProps, type DrawCallCanvas, type Element, type FlexDirection, type FontProps, type GradientDescriptor, Image, type JustifyContent, type LayoutNode, type LayoutProps, type LinearGradientDescriptor, type MeasureContext, type ProxiedCanvasContextOptions, type RadialGradientDescriptor, RichText, type RichTextElement, type RichTextProps, type RichTextSpan, type Shadow, type Size, type Spacing, Stack, type StackAlign, type StackElement, type StackProps, type StrokeProps, Svg, type SvgAlign, type SvgChild, type SvgCircleChild, type SvgElement, type SvgEllipseChild, type SvgGroupChild, type SvgLineChild, type SvgPathChild, type SvgPolygonChild, type SvgPolylineChild, type SvgProps, type SvgRectChild, type SvgStyleProps, type SvgTextChild, type SvgTransformProps, Text, type TextElement, type TextProps, Transform, type TransformElement, type TransformProps, computeLayout, createCanvas, createCanvasMeasureContext, layoutToString, linearGradient, printLayout, radialGradient, svg };
|
|
998
|
+
export { type AlignItems, type AlignSelf, type Border, type Bounds, Box, type BoxElement, type BoxProps, type CanvasOptions, type Color, type ColorStop, type ContainerLayoutProps, CustomDraw, type CustomDrawElement, type CustomDrawProps, type DrawCallCanvas, type Element, type FlexDirection, type FontProps, type GradientDescriptor, Image, type JustifyContent, type LayoutElement, type LayoutNode, type LayoutProps, type LinearGradientDescriptor, type MeasureContext, type ProxiedCanvasContextOptions, type RadialGradientDescriptor, RichText, type RichTextElement, type RichTextProps, type RichTextSpan, type Shadow, type Size, type Spacing, Stack, type StackAlign, type StackElement, type StackProps, type StrokeProps, Svg, type SvgAlign, type SvgChild, type SvgCircleChild, type SvgElement, type SvgEllipseChild, type SvgGroupChild, type SvgLineChild, type SvgPathChild, type SvgPolygonChild, type SvgPolylineChild, type SvgProps, type SvgRectChild, type SvgStyleProps, type SvgTextChild, type SvgTransformProps, Text, type TextElement, type TextProps, Transform, type TransformElement, type TransformProps, computeLayout, createCanvas, createCanvasMeasureContext, layoutToString, linearGradient, printLayout, radialGradient, svg };
|