|
1 | 1 | /* eslint-disable no-continue */
|
2 | 2 |
|
3 | 3 | import getWrap from './getWrap';
|
4 |
| -import getNodesHeight from './getNodesHeight'; |
5 | 4 |
|
6 | 5 | const getBreak = node => node.props?.break || false;
|
7 | 6 |
|
8 |
| -const getMinPresenceAhead = node => node.props?.minPresenceAhead; |
| 7 | +const getMinPresenceAhead = node => node.props?.minPresenceAhead || 0; |
9 | 8 |
|
10 |
| -const defaultPresenceAhead = element => height => |
11 |
| - Math.min(element.box.height, height); |
| 9 | +const getFurthestEnd = elements => |
| 10 | + Math.max(...elements.map(node => node.box.top + node.box.height)); |
12 | 11 |
|
13 |
| -const getPresenceAhead = (elements, height) => { |
14 |
| - let result = 0; |
15 |
| - |
16 |
| - for (let i = 0; i < elements.length; i += 1) { |
17 |
| - const element = elements[i]; |
18 |
| - |
19 |
| - if (!element.box) continue; |
20 |
| - |
21 |
| - const isElementInside = height > element.box.top; |
22 |
| - const presenceAhead = |
23 |
| - element.props.presenceAhead || defaultPresenceAhead(element); |
24 |
| - |
25 |
| - if (element && isElementInside) { |
26 |
| - result += presenceAhead(height - element.box.top); |
27 |
| - } |
28 |
| - } |
| 12 | +const getEndOfMinPresenceAhead = child => { |
| 13 | + return ( |
| 14 | + child.box.top + |
| 15 | + child.box.height + |
| 16 | + child.box.marginBottom + |
| 17 | + getMinPresenceAhead(child) |
| 18 | + ); |
| 19 | +}; |
29 | 20 |
|
30 |
| - return result; |
| 21 | +const getEndOfPresence = (child, futureElements) => { |
| 22 | + const afterMinPresenceAhead = getEndOfMinPresenceAhead(child); |
| 23 | + const endOfFurthestFutureElement = getFurthestEnd( |
| 24 | + futureElements.filter(node => !node.props?.fixed), |
| 25 | + ); |
| 26 | + return Math.min(afterMinPresenceAhead, endOfFurthestFutureElement); |
31 | 27 | };
|
32 | 28 |
|
33 | 29 | const shouldBreak = (child, futureElements, height) => {
|
34 |
| - const minPresenceAhead = getMinPresenceAhead(child); |
35 |
| - const presenceAhead = getPresenceAhead(futureElements, height); |
36 |
| - const futureHeight = getNodesHeight(futureElements); |
| 30 | + if (child.props?.fixed) return false; |
| 31 | + |
37 | 32 | const shouldSplit = height < child.box.top + child.box.height;
|
38 |
| - const shouldWrap = getWrap(child); |
| 33 | + const canWrap = getWrap(child); |
| 34 | + |
| 35 | + // Calculate the y coordinate where the desired presence of the child ends |
| 36 | + const endOfPresence = getEndOfPresence(child, futureElements); |
| 37 | + // If the child is already at the top of the page, breaking won't improve its presence |
| 38 | + // (as long as react-pdf does not support breaking into differently sized containers) |
| 39 | + const breakingImprovesPresence = child.box.top > child.box.marginTop; |
39 | 40 |
|
40 | 41 | return (
|
41 | 42 | getBreak(child) ||
|
42 |
| - (!shouldWrap && shouldSplit) || |
43 |
| - (minPresenceAhead < futureHeight && presenceAhead < minPresenceAhead) |
| 43 | + (shouldSplit && !canWrap) || |
| 44 | + (!shouldSplit && endOfPresence > height && breakingImprovesPresence) |
44 | 45 | );
|
45 | 46 | };
|
46 | 47 |
|
|
0 commit comments