sdui_core 0.3.2 copy "sdui_core: ^0.3.2" to clipboard
sdui_core: ^0.3.2 copied to clipboard

A high-performance Server-Driven UI (SDUI) engine for Flutter. Render dynamic, state-aware layouts from JSON payloads at runtime — no App Store review needed for UI changes.

0.3.2 #

Form widgets — createFormWidgets() #

9 new widget builders registered automatically by SduiScope: sdui:text_field, sdui:checkbox, sdui:checkbox_list_tile, sdui:radio, sdui:radio_list_tile, sdui:slider, sdui:range_slider, sdui:switch, sdui:dropdown. All dispatch via onChange / onSubmitted actions.

Error handling #

SduiErrorBoundaryStatefulWidget that catches Flutter build errors in a subtree and shows an inline error tile in debug mode (SizedBox.shrink in release). Accepts an onError callback for logging. Also available as sdui:error_boundary in JSON.

Renderer error protection — builder exceptions in SduiRenderer are now caught per-node. A broken node shows an error tile (debug) or collapses silently (release) — one bad node can no longer crash the whole screen.

JSON Schema & v2.0 #

  • Added schema/v1.json and schema/v2.json (JSON Schema draft-07) for server-side payload validation.
  • SduiSchemaMigrator.migrate() — non-mutating, idempotent v1→v2 migration.
  • Parser and validator accept sdui_version: "2.0". v2 requires explicit version on every node (MISSING_NODE_VERSION). Root metadata field is optional.

0.3.1 #

Bug fixes #

SduiWidgetRegistry defaults were empty

  • SduiWidgetRegistry.withDefaults() and .defaults returned empty registries because _loadDefaults() was a no-op.
  • Added configureDefaultFactory(factory) static method. SduiScope wires it on first build; withDefaults() now calls the factory correctly.
  • configureDefaultFactory merges builders into an already-accessed defaults instance, so custom widget registrations added before SduiScope is built are preserved.

SduiScope only auto-loaded core widgets

  • _buildDefault() now registers core + Material 3 + Cupertino widgets via configureDefaultFactory.
  • No manual registerAll(createCoreWidgets()) call is needed in main().

sdui:bottom_sheet and sdui:dialog rendered inline

  • Both were placeholder builders that rendered content inside the widget tree rather than as overlays.
  • Added SduiOverlayCallback typedef and withOverlayCallback() method to SduiActionRegistry.
  • SduiScreen injects a renderer-aware overlay handler — show_bottom_sheet triggers showModalBottomSheet, show_dialog triggers showDialog.
  • dismiss_bottom_sheet action now calls ctx.navigator?.pop() (was a no-op).
  • sdui:bottom_sheet widget renders a drag-handle header + children inside SafeArea. Supports padding prop.
  • sdui:dialog renders an AlertDialog with optional title, confirmLabel, and cancelLabel props.

Example app

  • Removed redundant SduiWidgetRegistry.defaults.registerAll(createCoreWidgets()) call from main().
  • Refactored to use SduiScope(registry: SduiWidgetRegistry.withDefaults()..register(...)) — the canonical pattern.

0.3.0 #

Architecture: state management overhaul #

SduiController — new ChangeNotifier state machine

  • Extracted the full fetch → cache → parse → diff lifecycle out of _SduiScreenState into a standalone SduiController extends ChangeNotifier.
  • Any state-management framework (Bloc, Provider, Riverpod, get_it, plain setState) can now observe or drive the screen without any boilerplate wiring.
  • New SduiScreen.controlled(controller: myController) named constructor for the controlled pattern; the standard SduiScreen(url: '...') constructor is unchanged.
  • patchNode(nodeId, props) — apply optimistic prop overrides to any node instantly, without a network round-trip. clearPatch / clearAllPatches restore server values.
  • refresh() — programmatic force-reload from anywhere.
  • effectiveNode — the patched tree that the screen renders, safe to observe.

SduiBindings + SduiBindingsNotifier — live state injection

  • New InheritedNotifier-based widget that injects observable key/value state into the SDUI tree.
  • visible_if now supports a "binding.X" expression form in addition to the existing "props.X" form.
  • Update bindings from your state layer; all dependent nodes rebuild automatically — no server round-trip:
    SduiBindings(
      notifier: SduiBindingsNotifier({'user.isPremium': false}),
      child: SduiScope(child: ...),
    )
    // JSON: { "visible_if": "binding.user.isPremium" }
    

SduiScope.navigatorKey — safe async navigation

  • New navigatorKey: GlobalKey<NavigatorState>? on SduiScope.
  • Flows through SduiBuildContext.navigatorKeySduiActionContext.navigatorKey.
  • SduiActionContext.navigator resolves navigatorKey.currentState first, falling back to Navigator.maybeOf(flutterContext) only when the context is still mounted.
  • All three widget builder families (core, material, cupertino) now propagate the key.

BuildContext safety fixes

  • navigate action now uses ctx.navigator?.pushNamed(route) — safe across async middleware gaps, never crashes on unmounted contexts.
  • All built-in action handlers guard ctx.flutterContext.mounted before accessing ScaffoldMessenger or Navigator.

0.2.3 #

  • WASM fix: replaced dart:isolate / Isolate.run() in SduiParser.parseString with Flutter's compute() from flutter/foundation.dart. compute() is WASM-compatible and still offloads JSON parsing to a background isolate on native platforms. This resolves the pub.dev "Package not compatible with runtime wasm" score penalty.
  • README: added use-case diagrams (e-commerce, A/B testing, feature flags, white-labelling) and integration recipes for bloc, provider, riverpod, go_router, get_it, dio, freezed, and firebase_remote_config.
  • Diagrams: added 8 new Mermaid-generated PNG assets — lifecycle, usecase_ecommerce, usecase_ab_testing, usecase_feature_flags, integration_bloc, integration_state_mgmt, integration_go_router, integration_get_it.

0.2.2 #

  • Replaced cached_network_image with Flutter's built-in Image.network to achieve full WASM compatibility. The sdui:image builder preserves the same loading spinner and broken-image error icon.
  • Removed cached_network_image from pubspec.yaml; no API changes for consumers.

0.2.1 #

  • Documentation updates, branding improvements, and README overhaul for pub.dev structure.

0.2.0 #

Breaking changes #

  • SduiWidgetRegistry and SduiActionRegistry are no longer singletons. The .instance accessor has been removed. Use SduiWidgetRegistry() to create a fresh instance or SduiWidgetRegistry.defaults for the shared default. Pass registries via SduiScope rather than relying on global state — this makes tests and multi-tenant apps trivially correct.
  • SduiParser.parseAsync renamed to SduiParser.parseString to reflect that the method accepts a raw JSON string (not a Future). The background-isolate behaviour is unchanged.
  • SduiWidgetRegistry.resolve now requires the named parameter nodePath:. Previously the tree path was positional and easy to omit accidentally.

New features #

Transport layer

  • Abstract SduiTransport interface. Swap HTTP for WebSocket — or a custom gRPC/mock transport — with a single constructor argument.
  • HttpSduiTransport — default HTTP transport with exponential back-off retry. Configurable maxRetries, retryDelay, timeout, and custom headers.
  • WebSocketSduiTransport — streams every server message as a fresh layout. Auto-reconnects with exponential back-off; configurable maxReconnectAttempts and pingInterval to keep the connection alive.

Caching

  • SduiCache — stale-while-revalidate cache backed by shared_preferences. Serves the last-known layout instantly on app launch while a fresh fetch runs in the background. Enabled by default on SduiScreen; opt out with enableCache: false.
  • SduiCacheException (code SDUI_006) added to the sealed exception hierarchy for cache read/write failures.

Validation

  • SduiValidator — full-tree pre-parse validation with structured error codes. Reports MISSING_VERSION, INVALID_VERSION, MISSING_TYPE, MISSING_ID, DUPLICATE_ID, MISSING_ACTION_TYPE, MISSING_ACTION_EVENT, and more. Call SduiParser.validate(map) before parsing to surface user-friendly errors without catching parse exceptions.

Diffing

  • SduiDiffer — incremental tree diff by id + version. Returns changed, added, removed, and moved node sets. Feed the updatedTree into setState to let Flutter reconcile only the changed subtrees.

Props

  • SduiProps — type-safe prop accessor wrapping Map<String, Object?>. Helpers: getString, getBool, getDouble, getInt, getColor, getColorOrNull, getEdgeInsets, getAlignment, getDoubleOrNull.

Conditional rendering

  • "visible_if" prop — evaluated by the renderer before any builder is called. Accepts bool literals, "props.X" expressions (resolved against the node's own props), and plain truthy strings. Returns SizedBox.shrink() when false. The single most-requested SDUI feature; enables A/B testing, feature flags, and role-based layout without a native release.

Theming

  • SduiThemeInheritedWidget holding a Map<String, TextStyle> named style registry. The sdui:text builder checks SduiTheme before the built-in Material TextTheme mappings, so the server can control brand typography ('promo', 'fine_print', etc.) without a native release.

Debug tooling

  • SduiDebugOverlay — wraps every rendered node in debug builds. Long-pressing any node opens a floating inspector panel showing the node id, type, version, tree path, prop count, action count, and child count. Enable with SduiDebugOverlay.enabled = true. No-op in release builds.

Screen machine

  • SduiScreen is now a 7-state machine: loading, loadingWithCache, success, refreshing, error, errorWithCache, empty.
  • New constructor parameters: transport, pullToRefresh, onLoad, onError, onEvent, onRefresh, emptyBuilder.

Rendering

  • SduiWidget — renders a pre-parsed SduiNode directly without a network request. Embed dynamic sub-trees anywhere in an existing screen.

Action system

  • SduiActionRegistry.addMiddleware — middleware chain for logging, analytics, and action transformation. Each middleware receives the action and a next callback.
  • SduiActionRegistry.withEventInterceptor — convenience factory for wiring SduiScreen.onEvent into the registry without subclassing.
  • SduiAction.debounceMs — built-in double-tap protection; debounces repeated triggers at the action definition level, not the call site.

Widget builders

  • Namespace wildcard resolution: register('myapp:*', builder) matches any type in the myapp: namespace that has no more-specific registration.
  • createMaterialWidgets() — 12 Material 3 builders: sdui:list_tile, sdui:switch_tile, sdui:progress, sdui:fab, sdui:bottom_nav, sdui:nav_rail, sdui:drawer, sdui:app_bar, sdui:search_bar, sdui:tab_bar, sdui:bottom_sheet, sdui:dialog.
  • createCupertinoWidgets() — 7 Cupertino builders: sdui:cupertino_button, sdui:cupertino_nav_bar, sdui:cupertino_list_tile, sdui:cupertino_switch, sdui:cupertino_slider, sdui:cupertino_activity, sdui:cupertino_dialog.
  • 10 additional core types: sdui:safe_area, sdui:aspect_ratio, sdui:fitted_box, sdui:clip_r_rect, sdui:opacity, sdui:transform_scale, sdui:hero, sdui:badge, sdui:chip, sdui:placeholder.

Utilities

  • SduiLogger — category-based debug logging with network, render, action, cache, and warn channels. Silenced in release builds.
  • SduiIcons — 100+ icon name → IconData mappings for use in sdui:icon.
  • SduiColorParsing extension — "#RRGGBB" / "#AARRGGBB" / named color string → Color parsing.
  • SduiContextExtension — convenience methods on BuildContext for accessing SduiScope data inline.

Quality

  • All node types are @immutable with copyWith, ==, hashCode, and debugFillProperties for the Flutter widget inspector.
  • 171 tests across unit, widget, and integration suites.
  • GitHub Actions CI matrix (stable + beta channel, ubuntu/macOS/Windows).
  • OIDC-based automated publish workflow on v*.*.* tags.

0.1.0 #

Initial release of sdui_core.

Rendering engine #

  • JSON-in, native-Flutter-out rendering engine. A JSON payload from any server is parsed once and rendered as a real Flutter widget tree — no eval, no WebView, no code generation.
  • Isolate-based JSON parsing via SduiParser.parseAsync. The JSON decode and node tree construction run on a background isolate, keeping the UI thread free during heavy payloads.
  • RepaintBoundary at every SduiScreen root. Per-subtree opt-in via "isolateRepaint": true in any node's props.
  • SduiKeyManager — deterministic ValueKey generation from id + parentPath. Ensures Flutter's reconciler reuses element state across rebuilds rather than tearing down and re-mounting subtrees on every refresh.
  • SduiScopeInheritedWidget that makes the widget registry and action registry available to every builder without prop-drilling.

Built-in widget types (18) #

sdui:text (Text with style mapping), sdui:image (Image.network with fit/width/height), sdui:container (color, padding, border-radius), sdui:column, sdui:row, sdui:stack (alignment props), sdui:button (elevated / outlined / filled variants), sdui:icon (icon name → IconData), sdui:divider / sdui:spacer, sdui:grid (GridView with columns, spacing, aspectRatio), sdui:list (ListView / ListView.builder), sdui:card (elevation, color), sdui:padding (directional), sdui:center, sdui:expanded (flex prop), sdui:visibility (show/hide on visible bool), sdui:inkwell (InkWell tap wrapper).

Actions (5 built-in types) #

navigate (Navigator.pushNamed with payload.route), open_url (launchUrl with payload.url), show_snackbar (ScaffoldMessenger with payload.message), copy_to_clipboard (Clipboard.setData with payload.text), dispatch (calls a registered custom handler).

Registries (singletons in 0.1.0, replaced in 0.2.0) #

SduiWidgetRegistry.instance — global widget builder registry with register, registerAll, resolve, and wildcard resolution.
SduiActionRegistry.instance — global action handler registry with register, dispatch, and middleware support.

Exception hierarchy #

Typed, sealed exception hierarchy — every error includes a code, a human-readable message, and an actionable hint string:

  • SduiParseException (SDUI_001) — JSON parsing failed.
  • SduiVersionException (SDUI_002) — unsupported sdui_version field.
  • SduiNetworkException (SDUI_003) — HTTP / network failure.
  • SduiUnknownWidgetException (SDUI_004) — no builder registered for type.
  • SduiActionException (SDUI_005) — no handler registered for event.

Auto-refresh #

SduiScreen(refreshInterval: Duration(minutes: 5)) — polls the server on a timer and re-renders on change without any application code.

2
likes
160
points
304
downloads

Documentation

API reference

Publisher

verified publisherhrushikeshdesai.com

Weekly Downloads

A high-performance Server-Driven UI (SDUI) engine for Flutter. Render dynamic, state-aware layouts from JSON payloads at runtime — no App Store review needed for UI changes.

Repository (GitHub)
View/report issues

Topics

#dynamic-widgets #json #remote-widgets #sdui #server-driven-ui

License

MIT (license)

Dependencies

flutter, http, meta, shared_preferences, url_launcher, web_socket_channel

More

Packages that depend on sdui_core