diegomura / react-pdf

📄 Create PDF files using React
https://react-pdf.org
MIT License
14.22k stars 1.11k forks source link

Conditional render if page is about to break #2733

Open Mudbill opened 2 weeks ago

Mudbill commented 2 weeks ago

Is your feature request related to a problem? Please describe.

I want to be able to add a line that says "Content will continue on the next page..." if my table happens to break across into the next page. This is not the same as using fixed as I have multiple such tables that begin and end at dynamic parts of the page.

Describe the solution you'd like


Suggestion 1 - param for conditional render

The simplest solution I can think of (from a user perspective, maybe not dev 😃) is to be able to read the amount of space left inside a render prop's params:

rows.map((row) => (
  <>
    <Text render={({ presenceAhead }) => 
      presenceAhead < 100 
      ? `Continues on next page...` // Only renders if less than 100 units left
      : ''} 
    />
    {/* Renders on the next page if less than 100 units left */}
    <Text minPresenceAhead={100}>My repeating row content</Text>
  </>
))

Suggestion 2 - maxPresenceAhead

While we do have a minPresenceAhead props, we don't have a maxPresenceAhead. Maybe that would be all that's needed (although a different name might be warranted as it doesn't work exactly opposite, so could be confusing).

In this scenario, if an element has maxPresenceAhead={100} and the page contains more than 100 units (pixels?) of space remaining, it would just not render at all.

<View>
  {rows.map((row) => (
    <>
      <Text maxPresenceAhead={100}>Continues on next page...</Text>
      <Text minPresenceAhead={100}>{row.text}</Text>
    </>
  ))}
</View>

The above would in such a situation skip rendering the first line each iteration of rows until only 100 units remain. The line of text immediately after requires at least 100, meaning it would then shift to the next page.

Of course, this would run into issues if the content to render is larger than the remaining space, but that would be an understandable side effect (user error 😄).


Suggestion 3 - Inspector component

A different and possibly more dynamic solution is to introduce a new Spy/Inspector component (name subject to change) that allows to look ahead and inspect some details, and conditionally render based on that. Maybe this is preferable if the previous solutions would introduce performance issues.

<Inspector
  {/* Similar to Suggestion 1 */}
  render={({presenceAhead}) => presenceAhead < 100 && <Text>Continues on next page...</Text>}
  {/* or */}
  renderCondition={(metadata) => true}
  render={() => <View />}
/>

The metadata params here could potentially include other useful information. Space ahead, page numbers, maybe a way to check if this is the last page since I've seen others request such a feature.


Describe alternatives you've considered

I've attempted some hacky solutions around storing the pageNumber from a render prop param, and comparing it in a different render prop, but if those numbers differ, that means we've already moved to the next page, so I can't exactly go back to the last page to add the line at that point.