Skip to content

feat(portable_text): per-subtree config via PortableTextTheme - #1

Closed
Ortes wants to merge 2 commits into
mainfrom
feat/portable-text-per-subtree-config
Closed

feat(portable_text): per-subtree config via PortableTextTheme#1
Ortes wants to merge 2 commits into
mainfrom
feat/portable-text-per-subtree-config

Conversation

@Ortes

@Ortes Ortes commented Jun 2, 2026

Copy link
Copy Markdown

What

Adds the ability to render different Portable Text subtrees with different configurations, instead of every widget sharing the single global PortableTextConfig.shared.

This mirrors Flutter's own Theme pattern:

  • PortableTextConfig.of(context) — resolves the nearest config from the tree, falling back to shared when none is present (like Theme.of / ThemeData.fallback).
  • PortableTextConfig.copyWith(...) — returns a derived config. Map fields (styles, blocks, blockContainers, markDefs) are merged (provided keys win, the rest are kept); scalars are replaced. Deliberately differs from ThemeData.copyWith because these maps are additive registries.
  • PortableTextTheme — an InheritedWidget that supplies a config to its subtree.
  • PortableTextStyleOverride — ergonomic helper: pass per-style TextStyle → TextStyle deltas (e.g. {'normal': (s) => s.copyWith(fontSize: s.fontSize! - 2)}); it wraps the inherited builders internally (no recursion, no boilerplate).

The render paths (PortableTextBlock, defaultListBuilder, defaultBulletRenderer) now read PortableTextConfig.of(context) instead of .shared directly.

Backward compatibility

Fully non-breaking. With no PortableTextTheme ancestor, of(context) returns shared, so existing apps render identically. The constructor is made public so additional configs can be created.

Note on mark deserialization

_markDefsFromJson runs at JSON-parse time with no BuildContext, so it intentionally keeps reading the context-free shared.markDefs registry. Mark styling is still resolved per subtree at render time. This is documented inline.

Commits

  1. feat — the per-subtree config support (the actual change; upstream-ready).
  2. chore — drops resolution: workspace so the package resolves standalone when consumed as a git/path dependency outside the vyuh workspace. Fork-only — should not be merged upstream.

Ortes added 2 commits June 2, 2026 16:18
Add PortableTextConfig.of(context) + copyWith and a PortableTextTheme InheritedWidget (plus PortableTextStyleOverride) so a subtree can override the rendering config without mutating the global shared instance. Render paths resolve the config from context, falling back to shared. Mark deserialization stays on the context-free shared registry.
…pendency use

Lets the package resolve standalone when consumed as a git/path dependency outside the vyuh workspace. Fork-only; not intended for upstream.
@Ortes

Ortes commented Jun 3, 2026

Copy link
Copy Markdown
Author

Superseded by the upstream contribution vyuh-tech#57. A fork-internal PR isn't the point — the feature goes upstream. The Fullphysio app consumes the change via a pinned git override on the feat/portable-text-per-subtree-config branch (which additionally carries a fork-only resolution: workspace removal needed for standalone git-dependency resolution) until the upstream PR is merged and published.

@Ortes Ortes closed this Jun 3, 2026
@Ortes
Ortes deleted the feat/portable-text-per-subtree-config branch June 10, 2026 22:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant