@lightningtv/solid 3.0.13 → 3.1.1-0
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/README.md +2 -0
- package/dist/src/core/elementNode.d.ts +32 -4
- package/dist/src/core/elementNode.js +5 -1
- package/dist/src/core/elementNode.js.map +1 -1
- package/dist/src/core/flex.js +131 -104
- package/dist/src/core/flex.js.map +1 -1
- package/dist/src/core/flexLayout.d.ts +2 -0
- package/dist/src/core/flexLayout.js +349 -0
- package/dist/src/core/flexLayout.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/docs/AI_CODING_GUIDELINES.md +191 -0
- package/docs/README.md +35 -0
- package/package.json +3 -3
- package/src/core/elementNode.ts +39 -5
- package/src/core/flex.ts +150 -128
- package/src/core/flexLayout.ts +404 -0
package/docs/README.md
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<p>
|
|
2
|
+
<img src="https://assets.solidjs.com/banner?project=Library&type=solid-lightning" alt="SolidJS LightningJS" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
`@lightningtv/solid` is an integration for the [LightningJS 3 Renderer](https://github.com/lightning-js/renderer) built with [SolidJS](https://www.solidjs.com/) [Universal Renderer](https://github.com/solidjs/solid/releases/tag/v1.2.0). It allows you to declaratively construct lightning nodes with SolidJS reactive primitives. It includes everything you need to rapidly build the performant TV Apps.
|
|
6
|
+
|
|
7
|
+
## Starter Template
|
|
8
|
+
|
|
9
|
+
Clone starter template:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
> npx degit lightning-tv/solid-starter-template my-app
|
|
13
|
+
> cd my-app
|
|
14
|
+
> npm i # or yarn or pnpm
|
|
15
|
+
> npm start # or yarn or pnpm
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## In Depth Guides
|
|
19
|
+
|
|
20
|
+
Read the full [Guide on Medium](https://medium.com/@chiefcll/lightning-3-the-basics-of-solidjs-e6e21d73205e) or watch the video:
|
|
21
|
+
|
|
22
|
+
[](https://www.youtube.com/watch?v=9UU7Ntf7Tww)
|
|
23
|
+
|
|
24
|
+
## Why Solid
|
|
25
|
+
|
|
26
|
+
- [Fastest, full featured frontend framework](https://dev.to/ryansolid/introducing-the-solidjs-ui-library-4mck)
|
|
27
|
+
- Established - Solid is widely used in production since 2018 with large community
|
|
28
|
+
- [Router](https://github.com/solidjs/solid-router)
|
|
29
|
+
- [Primitive Libraries](https://github.com/solidjs-community/solid-primitives)
|
|
30
|
+
- [Documentations](https://docs.solidjs.com/)
|
|
31
|
+
- [Demo App](https://lightning-tv.github.io/solid-demo-app/#/)
|
|
32
|
+
- [Playground](https://playground.solidjs.com/)
|
|
33
|
+
- Familiar and easy to use JSX + React like syntax
|
|
34
|
+
- Typescript
|
|
35
|
+
- [Sample Lightning UI Library](https://github.com/rdkcentral/solid-ui) of components with Theming
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lightningtv/solid",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.1-0",
|
|
4
4
|
"description": "Lightning Renderer for Solid Universal",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -65,7 +65,6 @@
|
|
|
65
65
|
"author": "Chris Lorenzo",
|
|
66
66
|
"license": "Apache-2.0",
|
|
67
67
|
"dependencies": {
|
|
68
|
-
"@lightningtv/solid": "link:",
|
|
69
68
|
"@solid-primitives/event-listener": "^2.3.3",
|
|
70
69
|
"@solid-primitives/list": "^0.1.2",
|
|
71
70
|
"@solid-primitives/mouse": "^2.0.20",
|
|
@@ -116,7 +115,8 @@
|
|
|
116
115
|
"jsx-runtime.d.ts",
|
|
117
116
|
"LICENSE",
|
|
118
117
|
"NOTICE",
|
|
119
|
-
"README.md"
|
|
118
|
+
"README.md",
|
|
119
|
+
"docs/AI_CODING_GUIDELINES.md"
|
|
120
120
|
],
|
|
121
121
|
"packageManager": "pnpm@10.8.0"
|
|
122
122
|
}
|
package/src/core/elementNode.ts
CHANGED
|
@@ -23,7 +23,12 @@ import {
|
|
|
23
23
|
NewOmit,
|
|
24
24
|
} from './intrinsicTypes.js';
|
|
25
25
|
import States, { type NodeStates } from './states.js';
|
|
26
|
-
import
|
|
26
|
+
import calculateFlexOld from './flex.js';
|
|
27
|
+
import calculateFlexNew from './flexLayout.js';
|
|
28
|
+
|
|
29
|
+
const calculateFlex = (import.meta as any).env?.VITE_USE_NEW_FLEX
|
|
30
|
+
? calculateFlexNew
|
|
31
|
+
: calculateFlexOld;
|
|
27
32
|
import {
|
|
28
33
|
log,
|
|
29
34
|
isArray,
|
|
@@ -253,7 +258,7 @@ export interface ElementNode extends RendererNode, FocusNode {
|
|
|
253
258
|
*
|
|
254
259
|
* @see https://lightning-tv.github.io/solid/#/flow/layout?id=flex
|
|
255
260
|
*/
|
|
256
|
-
flexWrap?: 'nowrap' | 'wrap';
|
|
261
|
+
flexWrap?: 'nowrap' | 'wrap' | 'wrap-reverse';
|
|
257
262
|
/**
|
|
258
263
|
* Determines if an element is a flex item. If set to `false`, the element will be ignored by the flexbox layout.
|
|
259
264
|
* @default false
|
|
@@ -265,6 +270,17 @@ export interface ElementNode extends RendererNode, FocusNode {
|
|
|
265
270
|
* @see https://lightning-tv.github.io/solid/#/flow/layout?id=flex
|
|
266
271
|
*/
|
|
267
272
|
flexOrder?: number;
|
|
273
|
+
/**
|
|
274
|
+
* Defines the ability for a flex item to shrink if necessary.
|
|
275
|
+
* Defaults to 0 since existing legacy implementations did not shrink layout boxes.
|
|
276
|
+
* Only available in NEW flex layout.
|
|
277
|
+
*/
|
|
278
|
+
flexShrink?: number;
|
|
279
|
+
/**
|
|
280
|
+
* Defines the default size of an element before the remaining space is distributed.
|
|
281
|
+
* Only available in NEW flex layout.
|
|
282
|
+
*/
|
|
283
|
+
flexBasis?: number | string;
|
|
268
284
|
/**
|
|
269
285
|
* Forwards focus to a child element. It can be a numeric index of the child or a handler function.
|
|
270
286
|
*
|
|
@@ -415,7 +431,7 @@ export interface ElementNode extends RendererNode, FocusNode {
|
|
|
415
431
|
*
|
|
416
432
|
* @see https://lightning-tv.github.io/solid/#/flow/layout?id=flex
|
|
417
433
|
*/
|
|
418
|
-
flexDirection?: 'row' | 'column';
|
|
434
|
+
flexDirection?: 'row' | 'column' | 'row-reverse' | 'column-reverse';
|
|
419
435
|
/**
|
|
420
436
|
* The gap between flex items.
|
|
421
437
|
*
|
|
@@ -483,11 +499,17 @@ export interface ElementNode extends RendererNode, FocusNode {
|
|
|
483
499
|
*/
|
|
484
500
|
marginTop?: number;
|
|
485
501
|
/**
|
|
486
|
-
* The padding on all sides of the flex element.
|
|
502
|
+
* The padding on all sides of the flex element, or an array defining [Top, Right, Bottom, Left] padding.
|
|
503
|
+
*
|
|
504
|
+
* @see https://lightning-tv.github.io/solid/#/flow/layout
|
|
505
|
+
*/
|
|
506
|
+
padding?: number | [number, number, number, number];
|
|
507
|
+
/**
|
|
508
|
+
* The margin on all sides of the flex element, or an array defining [Top, Right, Bottom, Left] margins.
|
|
487
509
|
*
|
|
488
510
|
* @see https://lightning-tv.github.io/solid/#/flow/layout
|
|
489
511
|
*/
|
|
490
|
-
|
|
512
|
+
margin?: number | [number, number, number, number];
|
|
491
513
|
/**
|
|
492
514
|
* The x-coordinate of the element's position.
|
|
493
515
|
*
|
|
@@ -620,6 +642,18 @@ export interface ElementNode extends RendererNode, FocusNode {
|
|
|
620
642
|
* @see https://lightning-tv.github.io/solid/#/flow/layout
|
|
621
643
|
*/
|
|
622
644
|
onLayout?: (this: ElementNode, target: ElementNode) => void;
|
|
645
|
+
|
|
646
|
+
/**
|
|
647
|
+
* The individual padding on each side of an element, acting as an override to the `padding` array property.
|
|
648
|
+
* `paddingTop`, `paddingRight`, `paddingBottom`, `paddingLeft`.
|
|
649
|
+
* Only in the new flex engine.
|
|
650
|
+
*
|
|
651
|
+
* @see https://lightning-tv.github.io/solid/#/flow/layout?id=flex
|
|
652
|
+
*/
|
|
653
|
+
paddingTop?: number;
|
|
654
|
+
paddingRight?: number;
|
|
655
|
+
paddingBottom?: number;
|
|
656
|
+
paddingLeft?: number;
|
|
623
657
|
}
|
|
624
658
|
|
|
625
659
|
export class ElementNode extends Object {
|
package/src/core/flex.ts
CHANGED
|
@@ -1,23 +1,11 @@
|
|
|
1
1
|
import { type ElementNode } from './elementNode.js';
|
|
2
2
|
import { isTextNode, isElementText } from './utils.js';
|
|
3
3
|
|
|
4
|
-
interface ProcessedChild {
|
|
5
|
-
node: ElementNode;
|
|
6
|
-
mainSize: number;
|
|
7
|
-
marginStart: number;
|
|
8
|
-
marginEnd: number;
|
|
9
|
-
totalMainSizeOnAxis: number;
|
|
10
|
-
isGrowItem: boolean;
|
|
11
|
-
flexGrowValue: number;
|
|
12
|
-
flexOrder: number;
|
|
13
|
-
crossSize: number;
|
|
14
|
-
crossMarginStart: number;
|
|
15
|
-
crossMarginEnd: number;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
4
|
export default function (node: ElementNode): boolean {
|
|
19
5
|
const direction = node.flexDirection || 'row';
|
|
20
|
-
const isRow = direction === 'row';
|
|
6
|
+
const isRow = direction === 'row' || direction === 'row-reverse';
|
|
7
|
+
const isReverse =
|
|
8
|
+
direction === 'row-reverse' || direction === 'column-reverse';
|
|
21
9
|
const dimension = isRow ? 'width' : 'height';
|
|
22
10
|
const crossDimension = isRow ? 'height' : 'width';
|
|
23
11
|
const marginOne = isRow ? 'marginLeft' : 'marginTop';
|
|
@@ -27,12 +15,19 @@ export default function (node: ElementNode): boolean {
|
|
|
27
15
|
const minDimension = isRow ? 'minWidth' : 'minHeight';
|
|
28
16
|
const crossMinDimension = isRow ? 'minHeight' : 'minWidth';
|
|
29
17
|
|
|
30
|
-
const
|
|
18
|
+
const children = node.children;
|
|
19
|
+
const numChildren = children.length;
|
|
20
|
+
|
|
21
|
+
if (numChildren === 0) {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let processableChildrenIndices: number[] = [];
|
|
31
26
|
let hasOrder = false;
|
|
32
27
|
let totalFlexGrow = 0;
|
|
33
28
|
|
|
34
|
-
for (let i = 0; i <
|
|
35
|
-
const c =
|
|
29
|
+
for (let i = 0; i < numChildren; i++) {
|
|
30
|
+
const c = children[i]!;
|
|
36
31
|
|
|
37
32
|
if (isElementText(c) && c.text && !(c.width || c.height)) {
|
|
38
33
|
return false;
|
|
@@ -42,54 +37,42 @@ export default function (node: ElementNode): boolean {
|
|
|
42
37
|
continue;
|
|
43
38
|
}
|
|
44
39
|
|
|
45
|
-
|
|
46
|
-
if (flexOrder !== undefined) {
|
|
40
|
+
if (c.flexOrder !== undefined) {
|
|
47
41
|
hasOrder = true;
|
|
48
42
|
}
|
|
49
43
|
|
|
50
44
|
const flexGrow = c.flexGrow;
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
totalFlexGrow += flexGrow!;
|
|
45
|
+
if (flexGrow !== undefined && flexGrow >= 0) {
|
|
46
|
+
totalFlexGrow += flexGrow;
|
|
54
47
|
}
|
|
55
48
|
|
|
56
|
-
if (c[minDimension] && (c[dimension] || 0) < c[minDimension]) {
|
|
49
|
+
if (c[minDimension] && (c[dimension] || 0) < c[minDimension]!) {
|
|
57
50
|
c[dimension] = c[minDimension]!;
|
|
58
51
|
}
|
|
59
|
-
const mainSize = c[dimension] || 0;
|
|
60
|
-
const currentMarginStart = c[marginOne] || 0;
|
|
61
|
-
const currentMarginEnd = c[marginTwo] || 0;
|
|
62
52
|
|
|
63
53
|
if (
|
|
64
54
|
c[crossMinDimension] &&
|
|
65
|
-
(c[crossDimension] || 0) < c[crossMinDimension]
|
|
55
|
+
(c[crossDimension] || 0) < c[crossMinDimension]!
|
|
66
56
|
) {
|
|
67
57
|
c[crossDimension] = c[crossMinDimension]!;
|
|
68
58
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
processedChildren.push({
|
|
72
|
-
node: c as ElementNode,
|
|
73
|
-
mainSize: mainSize,
|
|
74
|
-
marginStart: currentMarginStart,
|
|
75
|
-
marginEnd: currentMarginEnd,
|
|
76
|
-
totalMainSizeOnAxis: mainSize + currentMarginStart + currentMarginEnd,
|
|
77
|
-
isGrowItem: isGrowItem,
|
|
78
|
-
flexGrowValue: isGrowItem ? flexGrow! : 0,
|
|
79
|
-
flexOrder: flexOrder || 0,
|
|
80
|
-
crossSize: crossSize,
|
|
81
|
-
crossMarginStart: c[crossMarginOne] || 0,
|
|
82
|
-
crossMarginEnd: c[crossMarginTwo] || 0,
|
|
83
|
-
});
|
|
59
|
+
|
|
60
|
+
processableChildrenIndices.push(i);
|
|
84
61
|
}
|
|
85
62
|
|
|
86
63
|
if (hasOrder) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
64
|
+
processableChildrenIndices.sort((aIdx, bIdx) => {
|
|
65
|
+
const a = children[aIdx] as ElementNode;
|
|
66
|
+
const b = children[bIdx] as ElementNode;
|
|
67
|
+
return (a.flexOrder || 0) - (b.flexOrder || 0);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (isReverse || node.direction === 'rtl') {
|
|
72
|
+
processableChildrenIndices.reverse();
|
|
90
73
|
}
|
|
91
74
|
|
|
92
|
-
const numProcessedChildren =
|
|
75
|
+
const numProcessedChildren = processableChildrenIndices.length;
|
|
93
76
|
if (numProcessedChildren === 0) {
|
|
94
77
|
return false; // No layout changes if no processable children
|
|
95
78
|
}
|
|
@@ -106,23 +89,46 @@ export default function (node: ElementNode): boolean {
|
|
|
106
89
|
node[crossMinDimension] || 0,
|
|
107
90
|
0,
|
|
108
91
|
);
|
|
92
|
+
const isWrapReverse = node.flexWrap === 'wrap-reverse';
|
|
109
93
|
const gap = node.gap || 0;
|
|
110
94
|
const justify = node.justifyContent || 'flexStart';
|
|
95
|
+
const nodePadding = (node.padding as number) || 0;
|
|
111
96
|
let containerUpdated = false;
|
|
112
97
|
|
|
98
|
+
const childMainSizes = new Float32Array(numProcessedChildren);
|
|
99
|
+
const childMarginStarts = new Float32Array(numProcessedChildren);
|
|
100
|
+
const childMarginEnds = new Float32Array(numProcessedChildren);
|
|
101
|
+
const childTotalMainSizes = new Float32Array(numProcessedChildren);
|
|
102
|
+
const childCrossSizes = new Float32Array(numProcessedChildren);
|
|
103
|
+
const childMarginCrossStarts = new Float32Array(numProcessedChildren);
|
|
104
|
+
const childMarginCrossEnds = new Float32Array(numProcessedChildren);
|
|
105
|
+
|
|
106
|
+
let sumOfFlexBaseSizesWithMargins = 0;
|
|
107
|
+
|
|
108
|
+
for (let idx = 0; idx < numProcessedChildren; idx++) {
|
|
109
|
+
const c = children[processableChildrenIndices[idx]!] as ElementNode;
|
|
110
|
+
|
|
111
|
+
const baseMainSize = c[dimension] || 0;
|
|
112
|
+
const marginStart = (c[marginOne] as number) || 0;
|
|
113
|
+
const marginEnd = (c[marginTwo] as number) || 0;
|
|
114
|
+
|
|
115
|
+
childMainSizes[idx] = baseMainSize;
|
|
116
|
+
childMarginStarts[idx] = marginStart;
|
|
117
|
+
childMarginEnds[idx] = marginEnd;
|
|
118
|
+
childTotalMainSizes[idx] = baseMainSize + marginStart + marginEnd;
|
|
119
|
+
|
|
120
|
+
childCrossSizes[idx] = c[crossDimension] || 0;
|
|
121
|
+
childMarginCrossStarts[idx] = (c[crossMarginOne] as number) || 0;
|
|
122
|
+
childMarginCrossEnds[idx] = (c[crossMarginTwo] as number) || 0;
|
|
123
|
+
|
|
124
|
+
sumOfFlexBaseSizesWithMargins += childTotalMainSizes[idx]!;
|
|
125
|
+
}
|
|
126
|
+
|
|
113
127
|
if (totalFlexGrow > 0 && numProcessedChildren > 1) {
|
|
114
128
|
// When flex-grow is used, the container's size is considered fixed for this calculation pass,
|
|
115
129
|
// unless flexBoundary is explicitly set to allow container resizing based on content.
|
|
116
130
|
node.flexBoundary = node.flexBoundary || 'fixed';
|
|
117
131
|
|
|
118
|
-
// Determine the sum of the flex base sizes of all items.
|
|
119
|
-
// The flex base size is the item's mainSize before flex-grow is applied.
|
|
120
|
-
let sumOfFlexBaseSizesWithMargins = 0;
|
|
121
|
-
for (const pc of processedChildren) {
|
|
122
|
-
sumOfFlexBaseSizesWithMargins +=
|
|
123
|
-
pc.mainSize + pc.marginStart + pc.marginEnd;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
132
|
// Calculate the total space occupied by gaps between items.
|
|
127
133
|
const totalGapSpace =
|
|
128
134
|
numProcessedChildren > 0 ? gap * (numProcessedChildren - 1) : 0;
|
|
@@ -132,14 +138,16 @@ export default function (node: ElementNode): boolean {
|
|
|
132
138
|
containerSize - sumOfFlexBaseSizesWithMargins - totalGapSpace;
|
|
133
139
|
|
|
134
140
|
if (availableSpace > 0) {
|
|
135
|
-
for (
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
141
|
+
for (let idx = 0; idx < numProcessedChildren; idx++) {
|
|
142
|
+
const c = children[processableChildrenIndices[idx]!] as ElementNode;
|
|
143
|
+
const flexGrowValue = c.flexGrow;
|
|
144
|
+
if (flexGrowValue !== undefined && flexGrowValue > 0) {
|
|
145
|
+
const shareOfSpace = (flexGrowValue / totalFlexGrow) * availableSpace;
|
|
146
|
+
const newMainSize = childMainSizes[idx]! + shareOfSpace;
|
|
147
|
+
c[dimension] = newMainSize;
|
|
148
|
+
childMainSizes[idx] = newMainSize;
|
|
149
|
+
childTotalMainSizes[idx] =
|
|
150
|
+
newMainSize + childMarginStarts[idx]! + childMarginEnds[idx]!;
|
|
143
151
|
}
|
|
144
152
|
}
|
|
145
153
|
// prevent infinite loops by only doing this once
|
|
@@ -162,42 +170,42 @@ export default function (node: ElementNode): boolean {
|
|
|
162
170
|
justify === 'spaceEvenly' ||
|
|
163
171
|
justify === 'spaceAround'
|
|
164
172
|
) {
|
|
165
|
-
for (
|
|
166
|
-
totalItemSize +=
|
|
173
|
+
for (let idx = 0; idx < numProcessedChildren; idx++) {
|
|
174
|
+
totalItemSize += childTotalMainSizes[idx]!;
|
|
167
175
|
}
|
|
168
176
|
}
|
|
169
177
|
|
|
170
178
|
const align = node.alignItems || (node.flexWrap ? 'flexStart' : undefined);
|
|
171
179
|
const doCrossAlign = containerCrossSize
|
|
172
|
-
? (
|
|
173
|
-
const alignSelf =
|
|
180
|
+
? (c: ElementNode, idx: number, crossCurrentPos: number = 0) => {
|
|
181
|
+
const alignSelf = c.alignSelf || align;
|
|
174
182
|
if (!alignSelf) {
|
|
175
183
|
return;
|
|
176
184
|
}
|
|
177
185
|
if (alignSelf === 'flexStart') {
|
|
178
|
-
|
|
186
|
+
c[crossProp] = crossCurrentPos + childMarginCrossStarts[idx]!;
|
|
179
187
|
} else if (alignSelf === 'center') {
|
|
180
|
-
|
|
188
|
+
c[crossProp] =
|
|
181
189
|
crossCurrentPos +
|
|
182
|
-
(containerCrossSize -
|
|
183
|
-
|
|
190
|
+
(containerCrossSize - childCrossSizes[idx]!) / 2 +
|
|
191
|
+
childMarginCrossStarts[idx]!;
|
|
184
192
|
} else if (alignSelf === 'flexEnd') {
|
|
185
|
-
|
|
193
|
+
c[crossProp] =
|
|
186
194
|
crossCurrentPos +
|
|
187
195
|
containerCrossSize -
|
|
188
|
-
|
|
189
|
-
|
|
196
|
+
childCrossSizes[idx]! -
|
|
197
|
+
childMarginCrossEnds[idx]!;
|
|
190
198
|
}
|
|
191
199
|
}
|
|
192
|
-
: (
|
|
200
|
+
: (_c: ElementNode, _idx: number, _crossCurrentPos: number = 0) => {
|
|
193
201
|
/* no-op */
|
|
194
202
|
};
|
|
195
203
|
|
|
196
204
|
if (isRow && node._calcHeight && !node.flexCrossBoundary) {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
205
|
+
let maxHeight = 0;
|
|
206
|
+
for (let idx = 0; idx < numProcessedChildren; idx++) {
|
|
207
|
+
if (childCrossSizes[idx]! > maxHeight) maxHeight = childCrossSizes[idx]!;
|
|
208
|
+
}
|
|
201
209
|
const newHeight = maxHeight || node.height;
|
|
202
210
|
if (newHeight !== node.height) {
|
|
203
211
|
containerUpdated = true;
|
|
@@ -205,42 +213,52 @@ export default function (node: ElementNode): boolean {
|
|
|
205
213
|
}
|
|
206
214
|
}
|
|
207
215
|
|
|
208
|
-
let currentPos =
|
|
216
|
+
let currentPos = nodePadding;
|
|
209
217
|
if (justify === 'flexStart') {
|
|
210
|
-
if (node.flexWrap === 'wrap') {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
218
|
+
if (node.flexWrap === 'wrap' || isWrapReverse) {
|
|
219
|
+
const childCrossSizeVar =
|
|
220
|
+
numProcessedChildren > 0 ? childCrossSizes[0]! : containerCrossSize;
|
|
221
|
+
let crossCurrentPos = isWrapReverse
|
|
222
|
+
? containerCrossSize - childCrossSizeVar
|
|
223
|
+
: 0;
|
|
215
224
|
const crossGap = isRow ? (node.columnGap ?? gap) : (node.rowGap ?? gap);
|
|
216
|
-
|
|
225
|
+
|
|
226
|
+
for (let idx = 0; idx < numProcessedChildren; idx++) {
|
|
227
|
+
const c = children[processableChildrenIndices[idx]!] as ElementNode;
|
|
217
228
|
if (
|
|
218
|
-
currentPos +
|
|
219
|
-
currentPos >
|
|
229
|
+
currentPos + childTotalMainSizes[idx]! > containerSize &&
|
|
230
|
+
currentPos > nodePadding
|
|
220
231
|
) {
|
|
221
|
-
currentPos =
|
|
222
|
-
crossCurrentPos +=
|
|
232
|
+
currentPos = nodePadding;
|
|
233
|
+
crossCurrentPos += isWrapReverse
|
|
234
|
+
? -(childCrossSizeVar + crossGap)
|
|
235
|
+
: childCrossSizeVar + crossGap;
|
|
223
236
|
}
|
|
224
|
-
|
|
225
|
-
currentPos +=
|
|
226
|
-
doCrossAlign(
|
|
237
|
+
c[prop] = currentPos + childMarginStarts[idx]!;
|
|
238
|
+
currentPos += childTotalMainSizes[idx]! + gap;
|
|
239
|
+
doCrossAlign(c, idx, crossCurrentPos);
|
|
227
240
|
}
|
|
228
|
-
|
|
241
|
+
|
|
242
|
+
const finalCrossSize = isWrapReverse
|
|
243
|
+
? containerCrossSize - crossCurrentPos
|
|
244
|
+
: crossCurrentPos + childCrossSizeVar;
|
|
245
|
+
|
|
229
246
|
if (node[crossDimension] !== finalCrossSize) {
|
|
230
247
|
node[`preFlex${crossDimension}`] = node[crossDimension];
|
|
231
248
|
node[crossDimension] = finalCrossSize;
|
|
232
249
|
containerUpdated = true;
|
|
233
250
|
}
|
|
234
251
|
} else {
|
|
235
|
-
for (
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
252
|
+
for (let idx = 0; idx < numProcessedChildren; idx++) {
|
|
253
|
+
const c = children[processableChildrenIndices[idx]!] as ElementNode;
|
|
254
|
+
c[prop] = currentPos + childMarginStarts[idx]!;
|
|
255
|
+
currentPos += childTotalMainSizes[idx]! + gap;
|
|
256
|
+
doCrossAlign(c, idx);
|
|
239
257
|
}
|
|
240
258
|
}
|
|
241
259
|
// Update container size
|
|
242
260
|
if (node.flexBoundary !== 'fixed' && node.flexWrap !== 'wrap') {
|
|
243
|
-
let calculatedSize = currentPos - gap +
|
|
261
|
+
let calculatedSize = currentPos - gap + nodePadding;
|
|
244
262
|
const minSize = node[minDimension] || 0;
|
|
245
263
|
if (calculatedSize < minSize) {
|
|
246
264
|
calculatedSize = minSize;
|
|
@@ -253,55 +271,59 @@ export default function (node: ElementNode): boolean {
|
|
|
253
271
|
}
|
|
254
272
|
}
|
|
255
273
|
} else if (justify === 'flexEnd') {
|
|
256
|
-
currentPos = containerSize -
|
|
257
|
-
for (let
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
-
currentPos -=
|
|
261
|
-
doCrossAlign(
|
|
274
|
+
currentPos = containerSize - nodePadding;
|
|
275
|
+
for (let idx = numProcessedChildren - 1; idx >= 0; idx--) {
|
|
276
|
+
const c = children[processableChildrenIndices[idx]!] as ElementNode;
|
|
277
|
+
c[prop] = currentPos - childMainSizes[idx]! - childMarginEnds[idx]!;
|
|
278
|
+
currentPos -= childTotalMainSizes[idx]! + gap;
|
|
279
|
+
doCrossAlign(c, idx);
|
|
262
280
|
}
|
|
263
281
|
} else if (justify === 'center') {
|
|
264
282
|
currentPos =
|
|
265
283
|
(containerSize - (totalItemSize + gap * (numProcessedChildren - 1))) / 2 +
|
|
266
|
-
|
|
267
|
-
for (
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
284
|
+
nodePadding;
|
|
285
|
+
for (let idx = 0; idx < numProcessedChildren; idx++) {
|
|
286
|
+
const c = children[processableChildrenIndices[idx]!] as ElementNode;
|
|
287
|
+
c[prop] = currentPos + childMarginStarts[idx]!;
|
|
288
|
+
currentPos += childTotalMainSizes[idx]! + gap;
|
|
289
|
+
doCrossAlign(c, idx);
|
|
271
290
|
}
|
|
272
291
|
} else if (justify === 'spaceBetween') {
|
|
273
292
|
const spaceBetween =
|
|
274
293
|
numProcessedChildren > 1
|
|
275
|
-
? (containerSize - totalItemSize -
|
|
294
|
+
? (containerSize - totalItemSize - nodePadding * 2) /
|
|
276
295
|
(numProcessedChildren - 1)
|
|
277
296
|
: 0;
|
|
278
|
-
currentPos =
|
|
279
|
-
for (
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
297
|
+
currentPos = nodePadding;
|
|
298
|
+
for (let idx = 0; idx < numProcessedChildren; idx++) {
|
|
299
|
+
const c = children[processableChildrenIndices[idx]!] as ElementNode;
|
|
300
|
+
c[prop] = currentPos + childMarginStarts[idx]!;
|
|
301
|
+
currentPos += childTotalMainSizes[idx]! + spaceBetween;
|
|
302
|
+
doCrossAlign(c, idx);
|
|
283
303
|
}
|
|
284
304
|
} else if (justify === 'spaceAround') {
|
|
285
305
|
const spaceAround =
|
|
286
306
|
numProcessedChildren > 0
|
|
287
|
-
? (containerSize - totalItemSize -
|
|
307
|
+
? (containerSize - totalItemSize - nodePadding * 2) /
|
|
288
308
|
numProcessedChildren
|
|
289
309
|
: 0;
|
|
290
|
-
currentPos =
|
|
291
|
-
for (
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
310
|
+
currentPos = nodePadding + spaceAround / 2;
|
|
311
|
+
for (let idx = 0; idx < numProcessedChildren; idx++) {
|
|
312
|
+
const c = children[processableChildrenIndices[idx]!] as ElementNode;
|
|
313
|
+
c[prop] = currentPos + childMarginStarts[idx]!;
|
|
314
|
+
currentPos += childTotalMainSizes[idx]! + spaceAround;
|
|
315
|
+
doCrossAlign(c, idx);
|
|
295
316
|
}
|
|
296
317
|
} else if (justify === 'spaceEvenly') {
|
|
297
318
|
const spaceEvenly =
|
|
298
|
-
(containerSize - totalItemSize -
|
|
319
|
+
(containerSize - totalItemSize - nodePadding * 2) /
|
|
299
320
|
(numProcessedChildren + 1);
|
|
300
|
-
currentPos = spaceEvenly +
|
|
301
|
-
for (
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
321
|
+
currentPos = spaceEvenly + nodePadding;
|
|
322
|
+
for (let idx = 0; idx < numProcessedChildren; idx++) {
|
|
323
|
+
const c = children[processableChildrenIndices[idx]!] as ElementNode;
|
|
324
|
+
c[prop] = currentPos + childMarginStarts[idx]!;
|
|
325
|
+
currentPos += childTotalMainSizes[idx]! + spaceEvenly;
|
|
326
|
+
doCrossAlign(c, idx);
|
|
305
327
|
}
|
|
306
328
|
}
|
|
307
329
|
|