chore(deps): bump @opentui/solid from 0.7.0 to 0.8.1

DE
1d ago
+19-9

Bumps @opentui/solid from 0.7.0 to 0.8.1.

Release notes

Sourced from @​opentui/solid's releases.

Release v0.8.1

OpenTUI 0.8.1 can play video. VideoRenderable, and <video> in React and Solid, plays an MP4 file with H.264 video and AAC audio. Native code does the decoding, the media clock, the audio, and the drawing. Frames draw like an ImageRenderable, with Kitty, Sixel, or Unicode blocks:

const video = new VideoRenderable(renderer, {
  source: "./clip.mp4",
  width: 60,
  height: 20,
  autoplay: true,
  loop: true,
  onError: console.error,
})
renderer.root.add(video)

To show only part of a clip, you could make a node the size of the whole board and let its parent clip it. That gets expensive quickly. Nine such tiles of one 1080p clip used 2.3 cores and sent 58 MB of Kitty data per frame, which is far over the output limit. The new crop option selects a region in source pixels, and the decoder scales and copies only that region. The same nine tiles use 0.93 cores and 5.1 MB per frame. There is a second cost: each player of a clip with audio opens its own audio device, even when it is muted. Set audio: false on every tile except the one that plays sound:

// The top-left quarter of a 1920x1080 clip, with no audio device.
const tile = new VideoRenderable(renderer, {
  source: "./clip.mp4",
  crop: { left: 0, top: 0, width: 960, height: 540 },
  audio: false,
  width: 30,
  height: 10,
})

ImageRenderable takes the same crop. To decode video, the native library now statically links a decode-only LGPL build of FFmpeg 9.0.2. This makes each stripped library 2.6 to 3.5 MB larger. On linux-x64 it grows from 5.20 MB to 8.40 MB.

Over a slow link such as ssh, the terminal reads frames more slowly than OpenTUI writes them. Once the pty and the link filled up, the JavaScript thread waited inside write(2), and keys and timers waited behind it. On a 48 KB/s link it spent 79% of its time there, and the median key wait was 123.7 ms. In 0.8.1, on Linux and macOS when stdout is a terminal, a native thread owned by the Session does the write. On the same link, the JavaScript thread spends no time in write(2), and the median key wait is 0.1 ms. The screen still lags by the size of the link's buffers. The app also uses more CPU per run, because it now does the updates that it used to skip while it waited. Set OTUI_STDOUT_THREAD=0 to write on the JavaScript thread as before.

A slow link also made exit unreliable. In 0.8.0, the close gave up after one second and cancelled the session before it wrote the restore sequence. A 40-row quit at 16 KB/s left the terminal in the alternate screen with mouse reporting on. Now the close waits as long as output keeps moving. If nothing is written for one second, or if the close has run for ten seconds, the renderer stops waiting. It lets the write in progress finish, drops the queued output, writes the restore, and rejects closed as late.

The Session writes at most 8 MiB in one frame. In 0.8.0, a larger frame failed, and the repaint after it was just as large. The screen froze, but input still worked. Three 1000x700 Kitty images were enough to cause it. Now a frame sends its cells and the images that fit, and later frames send the rest. If one image is too large for a frame on its own, OpenTUI sends a copy at the size it is shown. A 1272x2015 photo shown at 880x1400 pixels sends 6.6 MB instead of 13.7 MB. The image draws as blocks only if that copy is too large as well. If a frame's cells alone are too large, the new frame:dropped event reports it once for each content. In 0.8.0, console.error reported it on every frame:

renderer.on(CliRenderEvents.FRAME_DROPPED, ({ bytes, limit }) => {
  console.warn(`dropped a frame of ${bytes} bytes (limit ${limit})`)
})

One layout change can show in existing apps. When Yoga gives a node zero width or height, OpenTUI used to paint and hit-test it as one cell, on top of its siblings. A common case is a one-row header above a ScrollBox with flexGrow. Once the list is taller than the screen, Yoga shrinks the header to zero rows. The header and the first list row then mixed into one line. Now the header is not drawn at all. To keep it, give the header flexShrink: 0, or give the ScrollBox flexBasis: 0:

const column = new BoxRenderable(renderer, { flexDirection: "column", height: "100%" })
column.add(new TextRenderable(renderer, { content: "filter: (type)", flexShrink: 0 }))
column.add(new ScrollBoxRenderable(renderer, { flexGrow: 1, minHeight: 0 }))

... (truncated)

Commits
  • 9a09079 Release v0.8.1
  • 4b10d91 core: make the TypeScript tests faster and fix two test-order flakes (#1895)
  • 9b7d5fb native: show a source region on video and image nodes (#1888)
  • 1823930 native: add an audio option to play video without a device (#1884)
  • b8032e2 native: add a video player node (#1800)
  • 60b7ce7 core: fix ScrollBox Markdown collapse and selection listener leak (#1863)
  • 738067f Release v0.8.0
  • 2dbd917 core: make ScrollBox a facade over the native scroll control (#1805)
  • 6c56a69 core: share one animation clock between components (#1803)
  • 577d67e solid: update Solid to resolve security warnings and allow compatible solid u...
  • See full diff in compare view

Dependabot compatibility score

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


Dependabot commands and options

You can trigger Dependabot actions by commenting on this PR:

  • @dependabot rebase will rebase this PR
  • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
  • @dependabot show <dependency name> ignore conditions will show all of the ignore conditions of the specified dependency
  • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
  • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)

Ask Polylane for an impact assessment of this pull request:

Assess with Polylane


Summary by cubic

Bumps @opentui/solid from 0.7.0 to 0.8.1, which also pulls in @opentui/core 0.8.1 and updated solid-js and babel-preset-solid versions.

Behavior changes to be aware of

  • Nodes with zero width or height are no longer painted or hit-tested; give them flexShrink: 0 to keep them visible.
  • Frames larger than the 8 MiB output limit are now split across later frames instead of failing, and oversized frames are reported once via a frame:dropped event.
  • On Linux and macOS with a terminal stdout, the session now writes output on a native thread; set OTUI_STDOUT_THREAD=0 to write on the JavaScript thread as before.