Search by

veilcss / block-framework

veilcss

Shared block infrastructure for the VeilCSS ecosystem.

Package info

github.com/veilcss/block-framework

pkg:composer/veilcss/block-framework

Statistics

Installs: 13

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

1.1.0 2026-07-30 05:11 UTC

This package is auto-updated.

Last update: 2026-08-30 05:20:53 UTC


README

Shared block infrastructure for the VeilCSS ecosystem.

This package is an internal integration boundary for VeilCSS ecosystem plugins. It is not a generic Gutenberg framework and is not intended as a third-party developer platform. It does not compile CSS, register product blocks, manage assets, or replace native WordPress block APIs.

Architecture

Phase 1 contains two boundaries:

  • A guarded global loader arbitrates between copies bundled by different plugins.
  • A namespaced runtime owns the active StyleResolverInterface.

Block registration (block.json, register_block_type(), editor assets) stays owned by the consuming plugin — a Foundation Block module does not call register_block_type() on anyone's behalf, and WordPress does not support two registrations for the same block name. What a Foundation Block module provides instead is render logic: a small, dependency-free class the consumer's own render_callback calls into, so multiple consumer plugins avoid duplicating that logic while each keeps sole ownership of registering the block they actually ship.

Foundation Blocks

src/FoundationBlocks/ holds this shared render logic, one subdirectory per block concept.

FoundationBlocks/Container is the first one (Phase 2a), extracted from VeilBlocks' veil/container. It covers only the seven non-interactive structural presets — none, section, card, stack, grid-2, grid-3, grid-4 — not accordion, tabs, nav, or generic responsive grid, which stay in the consuming plugin because their rendering isn't purely class-token resolution.

  • StructuralPresetRegistry — the seven structural presets and their default utility-token bundles.

  • TokenResolver — conflict-group-aware merge of preset tokens against user-entered override tokens (e.g. py-12 plus py-0 keeps only py-0; py-12 plus pt-0 keeps both, since padding-y and padding-top are independent groups). Generic enough for other Foundation Blocks to reuse.

  • StructuralPresetRenderer::resolve_wrapper() — the actual extraction target. Resolves preset tokens, merges them against the consumer's user-entered tokens, and hands the result to whichever StyleResolverInterface is active via veilcss_block_framework()->get_style_resolver()->resolve(). With the default resolver (or no runtime registered at all), this reproduces plain class-string output — a Foundation Block never requires a real integration to function.

    Whether a consumer's own "extraClasses" attribute should be suppressed in favor of a dedicated utility-token attribute is intentionally not inferred from resolver presence — that's a caller decision ($suppress_extra_classes on resolve_wrapper()), since the framework has no opinion on what "a styling integration is active" means for any particular consumer.

A future consumer wires a Foundation Block by calling its render helper from inside its own existing render_callback, the same way VeilBlocks does for veil/container's structural presets — see that plugin's ARCHITECTURE.md for the concrete call site.

Loader Lifecycle

Each bundling plugin loads loader.php and registers its candidate:

veilcss_block_framework_register_version(
	'1.1.0',
	__DIR__ . '/vendor/veilcss/block-framework/bootstrap.php',
	array( 'source' => 'veilblocks' )
);

Registration never initializes the framework. The loader attaches one callback to plugins_loaded at priority 0. At arbitration it:

  1. Finds the highest manually maintained API version present.
  2. Ignores candidates on lower API versions.
  3. Sorts compatible candidates by package semver using version_compare().
  4. Loads the newest bootstrap, falling back to the next candidate if loading throws.
  5. Records and exposes the selected runtime.

The bootstrap file declares VEILCSS_BLOCK_FRAMEWORK_API_VERSION. This integer is independent of package semver and changes only when StyleResolverInterface, the registration signature, or the runtime accessor breaks compatibility.

Selection is independent of plugin load order. Repeated arbitration returns the same runtime.

Style Resolution

StyleResolverInterface::resolve() receives block attributes, block context, and the block's existing class string. It always returns an immutable ResolvedStyle:

$style = veilcss_block_framework()
	->get_style_resolver()
	->resolve( $attributes, $context, $existing_classes );

ResolvedStyle contains:

  • class_string: output-ready, space-separated classes.
  • inline_styles: CSS property/value pairs.
  • data_attributes: data attribute/value pairs.

The default resolver passes through the existing class string and returns empty arrays for the other fields. An integration replaces it once through Framework::set_style_resolver(); blocks only depend on the interface.

Public APIs

  • veilcss_block_framework_register_version( $version, $bootstrap_path, $metadata )
  • veilcss_block_framework_arbitrate()
  • veilcss_block_framework()
  • veilcss_block_framework_diagnostics()
  • VeilCss\BlockFramework\StyleResolverInterface
  • VeilCss\BlockFramework\ResolvedStyle
  • VeilCss\BlockFramework\Framework

Diagnostics include registered candidates, selected version/source/API, active resolver class, compatibility warnings, and recoverable loader failures. They are structured data only; Phase 1 emits no notices or visible output.

Compatibility

Package releases follow semantic versioning. Loader compatibility follows the separate API version declared by each bootstrap. Within the highest API version in the registry, the newest semver wins. Changes to the resolver interface, resolved-style shape, loader registration signature, or stable runtime accessor require an API version increment.

Development

composer install
composer test