Skip to content

v2.0.0-beta.6

Pre-release
Pre-release

Choose a tag to compare

@eugeniodepalo eugeniodepalo released this 05 Sep 16:24
· 22 commits to main since this release
v2.0.0-beta.6
1fb24c9

GTKX 2.0 beta 6 fixes the issues found while building a real application on beta 5: cssClasses now owns exactly the classes React declares, AdwSidebar mode changes no longer leak the previous view, large flat collections synchronize without tree discovery, gtkx build output runs with a production environment and locates its data directories from every chunk, and a new onLog API lets tests observe GTK warnings. The publish procedure that produced beta 5 is now gated on a draft GitHub release and waits long enough for the registry.

GTKX 2.0 beta 6 is a prerelease. The final GTKX 2.0 release is scheduled for December 1, 2026, after the migration and hardening period.

React Renderer

  • cssClasses is reconciled as a set of classes React owns instead of being written over the widget's class list. Classes GTK or Adwaita applied on their own, such as background and csd on an AdwApplicationWindow or devel added by hand, survive a cssClasses write, and a class that appears both on the widget and in the prop is kept when the prop drops it. A style prop's generated class is preserved across every cssClasses change, and unmounting removes the classes React added.
  • Behavior change: cssClasses going from an array to undefined now removes the classes it declared, the same as passing []. Previously the classes remained on the widget. Because the classes GTK adds itself now survive a cssClasses write, getCssClasses() and an exact toHaveClass assertion also list them, such as text-button on a button with a label.
  • Empty class names in cssClasses are ignored.
  • AdwSidebar disposes the view it detaches on a mode change. Switching to page mode and back no longer duplicates item suffixes or keeps rows of the previous view alive, and a suffix mounted after the switch lands on the item it belongs to.

Components

  • ListView and ColumnView accept isFlat for a source whose items are all leaves. Synchronizing a large flat collection then skips tree discovery entirely.
  • A change to one item redraws and re-resolves only the realized row that shows it; stable rows are left untouched. Level stores are backed by a Map that holds only the realized slots instead of one entry per item, so a large source costs memory proportional to what is on screen.

Native and Logging

  • onLog(listener) from @gtkx/native subscribes to every GLib log record the process writes, from any thread, and returns a LogSubscription whose unsubscribe removes it. The listener receives the level (error, critical, warning, message, info or debug), the log domain and the message. Delivery is asynchronous, so a check has to yield to the event loop once before reading what the listener collected, and a level made fatal with logSetAlwaysFatal aborts the process before the listener runs. unsubscribe does not cancel records already queued, so the listener can still run for those after it returns. The testing guide shows a setup file that fails a test on the warnings and criticals it provoked.

Build and Deployment

  • gtkx build sets NODE_ENV=production for the whole build and defines it in the bundle, so a build run from a development shell no longer emits development JSX runtime calls that fail at startup.
  • The XDG_DATA_DIRS and GSETTINGS_SCHEMA_DIR banners resolve the output root relative to the chunk they are prepended to and assign through globalThis.process, so shared, application and worker chunks in nested directories all find the installed icons and compiled schemas.
  • desktop-file-validate hints and warnings are reported as warnings; only an error line or a non-zero exit fails the deploy. Previously any output rejected the desktop entry.
  • A development-only .Devel icon tree is documented as a $development overlay of applicationIcon, since an icon-theme directory is packaged verbatim.

Testing

  • The GTKX preload returns immediately outside the main thread, so a node:worker_threads worker that inherits the test runner's execArgv keeps its parent's headless display instead of starting a second compositor and session bus and failing on exit.
  • screenshot() of a toplevel window composites the window's resolved CSS background, so a captured Adwaita window is no longer transparent where no widget paints; a captured subtree keeps its transparent surroundings.
  • userEvent.click and userEvent.pointer on a row inside a container such as AdwSidebar activate the row through the container and no longer drive GTK's internal gestures as well, which double-counted activations.
  • userEvent.keyboard stops propagating a key press once a handler moved focus or changed the root, so an Enter that activates a sidebar row no longer continues into the default button that row focused.
  • The testing guide documents that a GtkButton with a text label is named by that label, and that GTK's relation takes precedence over an accessibleLabel prop, so such a button is queried by its visible text.
  • Queries in @gtkx/testing no longer walk unmapped subtrees except through a GtkNative such as a popover, resolve relation targets from mnemonic labels and descendants before searching the whole tree, and cache hidden state once per query, so a large tree is queried without a visible pause.

Code Generation and Reference

  • The prose stripper removes the cleanup instructions beta 5 still let through: "the caller is responsible for freeing", "the copy/contents/pointer should be freed", "that string needs to be freed", and an "and will eventually be freed with" clause, while sentences that merely mention g_free() as an allocator or a compiler feature are kept intact. Stripping a cleanup clause no longer leaves the fragment that preceded it, such as a dangling "Instead," or "The list", and a sentence that is nothing but a cleanup instruction is dropped whole while the sentences around it are kept.
  • A relative Vitest --root no longer makes the store resolver loop forever.
  • The configuration guide explains the non-exported _Class$InstanceBase tombstone overloads that appear in a generated store when GIR narrows an inherited callable incompatibly.

Project Creation and Documentation

  • create-gtkx pins typescript to ^6.0.3 instead of latest, the version the workspace itself builds and tests with, and the tutorial example's package.json uses the same range. The generated agent rules list gtkx cleanup next to gtkx dev and gtkx codegen.
  • The async-operations guide documents that gtkx dev and Vitest load a worker's import graph through Node's type stripping, so relative imports must name .ts files and avoid enums and parameter properties; the MCP guide explains that a headless development session is tied to the process that was the parent of gtkx dev when it started, which nohup does not change and setsid changes only when it forks.

(#621)

Full changelog: v2.0.0-beta.5...v2.0.0-beta.6