From 8f1ba7a3a0a4ce4243b3ae9a976fda82dcace9cb Mon Sep 17 00:00:00 2001 From: Jia Hao Goh Date: Fri, 27 Mar 2026 02:39:36 +0000 Subject: [PATCH 1/5] Replace rxdart with stream_transform stream_transform is more commonly used internally and is also owned by Google. --- .../lib/src/functions/format_string.dart | 7 ++++--- packages/genui/lib/src/model/data_model.dart | 5 +++-- .../lib/src/utils/stream_extensions.dart | 19 +++++++++++++++++++ .../lib/src/utils/validation_helper.dart | 5 ++--- packages/genui/pubspec.yaml | 2 +- 5 files changed, 29 insertions(+), 9 deletions(-) create mode 100644 packages/genui/lib/src/utils/stream_extensions.dart diff --git a/packages/genui/lib/src/functions/format_string.dart b/packages/genui/lib/src/functions/format_string.dart index 51e44edc0..c1aaa9a00 100644 --- a/packages/genui/lib/src/functions/format_string.dart +++ b/packages/genui/lib/src/functions/format_string.dart @@ -4,12 +4,13 @@ import 'package:json_schema_builder/json_schema_builder.dart'; import 'package:meta/meta.dart'; -import 'package:rxdart/rxdart.dart'; +import 'package:stream_transform/stream_transform.dart'; import '../model/client_function.dart' as cf; import '../model/data_model.dart'; import '../primitives/logging.dart'; import '../primitives/simple_items.dart'; +import '../utils/stream_extensions.dart'; /// Formats a value as a string. class FormatStringFunction implements cf.ClientFunction { @@ -173,7 +174,7 @@ class ExpressionParser { return Stream.value(val); }).toList(); - return CombineLatestStream.list(streams).switchMap((List values) { + return streams.combineLatestAll().switchMap((List values) { final Map combinedArgs = {}; for (var i = 0; i < keys.length; i++) { combinedArgs[keys[i]] = values[i]; @@ -249,7 +250,7 @@ class ExpressionParser { return Stream.value(part); }).toList(); - return CombineLatestStream.list(streams).map((List values) { + return streams.combineLatestAll().map((List values) { return values.map((e) => e?.toString() ?? '').join(''); }); } diff --git a/packages/genui/lib/src/model/data_model.dart b/packages/genui/lib/src/model/data_model.dart index 2aba001ab..9d9bdd213 100644 --- a/packages/genui/lib/src/model/data_model.dart +++ b/packages/genui/lib/src/model/data_model.dart @@ -6,10 +6,11 @@ import 'dart:async'; import 'dart:convert'; import 'package:flutter/foundation.dart'; -import 'package:rxdart/rxdart.dart'; +import 'package:stream_transform/stream_transform.dart'; import '../primitives/logging.dart'; import '../primitives/simple_items.dart'; +import '../utils/stream_extensions.dart'; import 'client_function.dart' as cf; import 'data_path.dart'; @@ -155,7 +156,7 @@ class DataContext implements cf.ExecutionContext { final Stream> combinedStream = streams.isEmpty ? Stream.value([]) - : CombineLatestStream.list(streams); + : streams.combineLatestAll(); return combinedStream.switchMap((List values) { final Map combinedArgs = {}; diff --git a/packages/genui/lib/src/utils/stream_extensions.dart b/packages/genui/lib/src/utils/stream_extensions.dart new file mode 100644 index 000000000..87e85d8e8 --- /dev/null +++ b/packages/genui/lib/src/utils/stream_extensions.dart @@ -0,0 +1,19 @@ +// Copyright 2025 The Flutter Authors. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:stream_transform/stream_transform.dart'; + +/// Extensions for [Iterable] of [Stream]s. +extension CombineLatestAll on Iterable> { + /// Combines all streams in this iterable into a single stream that emits a + /// list of the latest values from each stream. + /// + /// The resulting stream will not emit until every stream in the iterable has + /// emitted at least one value. + Stream> combineLatestAll() { + if (isEmpty) return Stream.value([]); + + return first.combineLatestAll(skip(1)); + } +} diff --git a/packages/genui/lib/src/utils/validation_helper.dart b/packages/genui/lib/src/utils/validation_helper.dart index eaf6262b7..3d7fa769e 100644 --- a/packages/genui/lib/src/utils/validation_helper.dart +++ b/packages/genui/lib/src/utils/validation_helper.dart @@ -2,11 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'package:rxdart/rxdart.dart'; - import '../model/data_model.dart'; import '../primitives/simple_items.dart'; import '../widgets/widget_utilities.dart'; +import 'stream_extensions.dart'; /// A validation error with a message. class ValidationError { @@ -47,7 +46,7 @@ class ValidationHelper { ); } - return CombineLatestStream.list(streams).map((results) { + return streams.combineLatestAll().map((results) { for (final (isValid, msg) in results) { if (!isValid) return msg; } diff --git a/packages/genui/pubspec.yaml b/packages/genui/pubspec.yaml index 17141b3ea..79d7769fe 100644 --- a/packages/genui/pubspec.yaml +++ b/packages/genui/pubspec.yaml @@ -25,7 +25,7 @@ dependencies: json_schema_builder: ^0.1.3 logging: ^1.3.0 meta: ^1.17.0 - rxdart: ^0.28.0 + stream_transform: ^2.1.1 url_launcher: ^6.3.2 uuid: ^4.4.0 From fd284f16ba5331f9296ef90ed48c0cab87acd215 Mon Sep 17 00:00:00 2001 From: Jia Hao Goh Date: Mon, 30 Mar 2026 02:46:25 +0000 Subject: [PATCH 2/5] Move validation_helper.dart to model/ for layerlens --- packages/genui/lib/genui.dart | 1 + .../genui/lib/src/catalog/basic_catalog_widgets/button.dart | 2 +- .../src/catalog/basic_catalog_widgets/date_time_input.dart | 2 +- .../lib/src/catalog/basic_catalog_widgets/text_field.dart | 2 +- .../genui/lib/src/{utils => model}/validation_helper.dart | 4 ++-- 5 files changed, 6 insertions(+), 5 deletions(-) rename packages/genui/lib/src/{utils => model}/validation_helper.dart (97%) diff --git a/packages/genui/lib/genui.dart b/packages/genui/lib/genui.dart index 525d64ba4..290601909 100644 --- a/packages/genui/lib/genui.dart +++ b/packages/genui/lib/genui.dart @@ -29,6 +29,7 @@ export 'src/model/chat_message.dart'; export 'src/model/data_model.dart'; export 'src/model/generation_events.dart'; export 'src/model/ui_models.dart'; +export 'src/model/validation_helper.dart'; export 'src/primitives/cancellation.dart'; export 'src/primitives/constants.dart'; export 'src/primitives/logging.dart'; diff --git a/packages/genui/lib/src/catalog/basic_catalog_widgets/button.dart b/packages/genui/lib/src/catalog/basic_catalog_widgets/button.dart index b1d719498..d7f397e7c 100644 --- a/packages/genui/lib/src/catalog/basic_catalog_widgets/button.dart +++ b/packages/genui/lib/src/catalog/basic_catalog_widgets/button.dart @@ -10,7 +10,7 @@ import '../../model/catalog_item.dart'; import '../../model/ui_models.dart'; import '../../primitives/logging.dart'; import '../../primitives/simple_items.dart'; -import '../../utils/validation_helper.dart'; +import '../../model/validation_helper.dart'; import '../../widgets/widget_utilities.dart'; final _schema = S.object( diff --git a/packages/genui/lib/src/catalog/basic_catalog_widgets/date_time_input.dart b/packages/genui/lib/src/catalog/basic_catalog_widgets/date_time_input.dart index c2401d6c4..7ec7fe064 100644 --- a/packages/genui/lib/src/catalog/basic_catalog_widgets/date_time_input.dart +++ b/packages/genui/lib/src/catalog/basic_catalog_widgets/date_time_input.dart @@ -11,7 +11,7 @@ import '../../model/a2ui_schemas.dart'; import '../../model/catalog_item.dart'; import '../../model/data_model.dart'; import '../../primitives/simple_items.dart'; -import '../../utils/validation_helper.dart'; +import '../../model/validation_helper.dart'; import '../../widgets/widget_utilities.dart'; final _schema = S.object( diff --git a/packages/genui/lib/src/catalog/basic_catalog_widgets/text_field.dart b/packages/genui/lib/src/catalog/basic_catalog_widgets/text_field.dart index 577ecb9ce..da6c123ba 100644 --- a/packages/genui/lib/src/catalog/basic_catalog_widgets/text_field.dart +++ b/packages/genui/lib/src/catalog/basic_catalog_widgets/text_field.dart @@ -12,7 +12,7 @@ import '../../model/catalog_item.dart'; import '../../model/data_model.dart'; import '../../model/ui_models.dart'; import '../../primitives/simple_items.dart'; -import '../../utils/validation_helper.dart'; +import '../../model/validation_helper.dart'; import '../../widgets/widget_utilities.dart'; final _schema = S.object( diff --git a/packages/genui/lib/src/utils/validation_helper.dart b/packages/genui/lib/src/model/validation_helper.dart similarity index 97% rename from packages/genui/lib/src/utils/validation_helper.dart rename to packages/genui/lib/src/model/validation_helper.dart index 3d7fa769e..860a8da4a 100644 --- a/packages/genui/lib/src/utils/validation_helper.dart +++ b/packages/genui/lib/src/model/validation_helper.dart @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import '../model/data_model.dart'; +import 'data_model.dart'; import '../primitives/simple_items.dart'; import '../widgets/widget_utilities.dart'; -import 'stream_extensions.dart'; +import '../utils/stream_extensions.dart'; /// A validation error with a message. class ValidationError { From 4f8df0555d3a30c48b444bf043f5303a77390425 Mon Sep 17 00:00:00 2001 From: Jia Hao Goh Date: Mon, 30 Mar 2026 02:56:09 +0000 Subject: [PATCH 3/5] Fix imports --- .../genui/lib/src/catalog/basic_catalog_widgets/button.dart | 2 +- .../src/catalog/basic_catalog_widgets/date_time_input.dart | 2 +- .../lib/src/catalog/basic_catalog_widgets/text_field.dart | 2 +- packages/genui/lib/src/model/validation_helper.dart | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/genui/lib/src/catalog/basic_catalog_widgets/button.dart b/packages/genui/lib/src/catalog/basic_catalog_widgets/button.dart index d7f397e7c..5bb23f208 100644 --- a/packages/genui/lib/src/catalog/basic_catalog_widgets/button.dart +++ b/packages/genui/lib/src/catalog/basic_catalog_widgets/button.dart @@ -8,9 +8,9 @@ import 'package:json_schema_builder/json_schema_builder.dart'; import '../../model/a2ui_schemas.dart'; import '../../model/catalog_item.dart'; import '../../model/ui_models.dart'; +import '../../model/validation_helper.dart'; import '../../primitives/logging.dart'; import '../../primitives/simple_items.dart'; -import '../../model/validation_helper.dart'; import '../../widgets/widget_utilities.dart'; final _schema = S.object( diff --git a/packages/genui/lib/src/catalog/basic_catalog_widgets/date_time_input.dart b/packages/genui/lib/src/catalog/basic_catalog_widgets/date_time_input.dart index 7ec7fe064..be314b50d 100644 --- a/packages/genui/lib/src/catalog/basic_catalog_widgets/date_time_input.dart +++ b/packages/genui/lib/src/catalog/basic_catalog_widgets/date_time_input.dart @@ -10,8 +10,8 @@ import 'package:json_schema_builder/json_schema_builder.dart'; import '../../model/a2ui_schemas.dart'; import '../../model/catalog_item.dart'; import '../../model/data_model.dart'; -import '../../primitives/simple_items.dart'; import '../../model/validation_helper.dart'; +import '../../primitives/simple_items.dart'; import '../../widgets/widget_utilities.dart'; final _schema = S.object( diff --git a/packages/genui/lib/src/catalog/basic_catalog_widgets/text_field.dart b/packages/genui/lib/src/catalog/basic_catalog_widgets/text_field.dart index da6c123ba..cad6e5c0c 100644 --- a/packages/genui/lib/src/catalog/basic_catalog_widgets/text_field.dart +++ b/packages/genui/lib/src/catalog/basic_catalog_widgets/text_field.dart @@ -11,8 +11,8 @@ import '../../model/a2ui_schemas.dart'; import '../../model/catalog_item.dart'; import '../../model/data_model.dart'; import '../../model/ui_models.dart'; -import '../../primitives/simple_items.dart'; import '../../model/validation_helper.dart'; +import '../../primitives/simple_items.dart'; import '../../widgets/widget_utilities.dart'; final _schema = S.object( diff --git a/packages/genui/lib/src/model/validation_helper.dart b/packages/genui/lib/src/model/validation_helper.dart index 860a8da4a..72d0cecee 100644 --- a/packages/genui/lib/src/model/validation_helper.dart +++ b/packages/genui/lib/src/model/validation_helper.dart @@ -2,10 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import 'data_model.dart'; import '../primitives/simple_items.dart'; -import '../widgets/widget_utilities.dart'; import '../utils/stream_extensions.dart'; +import '../widgets/widget_utilities.dart'; +import 'data_model.dart'; /// A validation error with a message. class ValidationError { From ee8e7008ed0ddf78838094bddb43ebc185a3cbf4 Mon Sep 17 00:00:00 2001 From: Jia Hao Goh Date: Mon, 30 Mar 2026 03:22:50 +0000 Subject: [PATCH 4/5] Break model -> widget dependency --- .../catalog/basic_catalog_widgets/button.dart | 4 +--- .../basic_catalog_widgets/text_field.dart | 6 ++---- .../genui/lib/src/model/client_function.dart | 3 +++ packages/genui/lib/src/model/data_model.dart | 14 ++++++++++++++ .../genui/lib/src/model/validation_helper.dart | 3 +-- .../lib/src/widgets/widget_utilities.dart | 18 ------------------ 6 files changed, 21 insertions(+), 27 deletions(-) diff --git a/packages/genui/lib/src/catalog/basic_catalog_widgets/button.dart b/packages/genui/lib/src/catalog/basic_catalog_widgets/button.dart index 5bb23f208..28242621c 100644 --- a/packages/genui/lib/src/catalog/basic_catalog_widgets/button.dart +++ b/packages/genui/lib/src/catalog/basic_catalog_widgets/button.dart @@ -11,7 +11,6 @@ import '../../model/ui_models.dart'; import '../../model/validation_helper.dart'; import '../../primitives/logging.dart'; import '../../primitives/simple_items.dart'; -import '../../widgets/widget_utilities.dart'; final _schema = S.object( description: 'An interactive button that triggers an action when pressed.', @@ -205,8 +204,7 @@ Future _handlePress( final actionName = eventMap['name'] as String; final contextDefinition = eventMap['context'] as JsonMap?; - final JsonMap resolvedContext = await resolveContext( - itemContext.dataContext, + final JsonMap resolvedContext = await itemContext.dataContext.resolveMap( contextDefinition, ); itemContext.dispatchEvent( diff --git a/packages/genui/lib/src/catalog/basic_catalog_widgets/text_field.dart b/packages/genui/lib/src/catalog/basic_catalog_widgets/text_field.dart index cad6e5c0c..d540aba57 100644 --- a/packages/genui/lib/src/catalog/basic_catalog_widgets/text_field.dart +++ b/packages/genui/lib/src/catalog/basic_catalog_widgets/text_field.dart @@ -253,10 +253,8 @@ final textField = CatalogItem( final eventMap = actionData['event'] as JsonMap; final actionName = eventMap['name'] as String; final contextDefinition = eventMap['context'] as JsonMap?; - final JsonMap resolvedContext = await resolveContext( - itemContext.dataContext, - contextDefinition, - ); + final JsonMap resolvedContext = await itemContext.dataContext + .resolveMap(contextDefinition); itemContext.dispatchEvent( UserActionEvent( name: actionName, diff --git a/packages/genui/lib/src/model/client_function.dart b/packages/genui/lib/src/model/client_function.dart index d025cacf4..54545fa71 100644 --- a/packages/genui/lib/src/model/client_function.dart +++ b/packages/genui/lib/src/model/client_function.dart @@ -43,6 +43,9 @@ abstract interface class ExecutionContext { /// Evaluates a dynamic boolean condition and returns a [Stream]. Stream evaluateConditionStream(Object? condition); + + /// Resolves a map of dynamic values into a map of literal values. + Future resolveMap(JsonMap? map); } /// A function that can be invoked by the GenUI expression system. diff --git a/packages/genui/lib/src/model/data_model.dart b/packages/genui/lib/src/model/data_model.dart index 9d9bdd213..ccb7f25c3 100644 --- a/packages/genui/lib/src/model/data_model.dart +++ b/packages/genui/lib/src/model/data_model.dart @@ -179,6 +179,20 @@ class DataContext implements cf.ExecutionContext { return v != null; }); } + + /// Resolves a map of dynamic values into a map of literal values. + @override + Future resolveMap(JsonMap? map) async { + final resolved = {}; + if (map == null) return resolved; + + for (final MapEntry entry in map.entries) { + final String key = entry.key; + final Object? value = entry.value; + resolved[key] = await resolve(value).first; + } + return resolved; + } } /// Exception thrown when a value in the [DataModel] is not of the expected diff --git a/packages/genui/lib/src/model/validation_helper.dart b/packages/genui/lib/src/model/validation_helper.dart index 72d0cecee..f50d1de3b 100644 --- a/packages/genui/lib/src/model/validation_helper.dart +++ b/packages/genui/lib/src/model/validation_helper.dart @@ -4,7 +4,6 @@ import '../primitives/simple_items.dart'; import '../utils/stream_extensions.dart'; -import '../widgets/widget_utilities.dart'; import 'data_model.dart'; /// A validation error with a message. @@ -64,7 +63,7 @@ class ValidationHelper { final List errors = []; // Resolve schema constraints that might be expressions - final JsonMap resolvedSchema = await resolveContext(dataContext, schema); + final JsonMap resolvedSchema = await dataContext.resolveMap(schema); // simple validation for now, delegating to json_schema_builder would be // ideal, but for now we just check basic constraints we support in genui diff --git a/packages/genui/lib/src/widgets/widget_utilities.dart b/packages/genui/lib/src/widgets/widget_utilities.dart index b7ef26584..0df238770 100644 --- a/packages/genui/lib/src/widgets/widget_utilities.dart +++ b/packages/genui/lib/src/widgets/widget_utilities.dart @@ -9,7 +9,6 @@ import 'package:flutter/material.dart'; import '../model/data_model.dart'; import '../primitives/logging.dart'; -import '../primitives/simple_items.dart'; /// A builder widget that simplifies handling of nullable `ValueListenable`s. /// @@ -376,20 +375,3 @@ class _ToNumberNotifier extends ValueNotifier { super.dispose(); } } - -/// Resolves a context map definition against a [DataContext]. -/// -Future resolveContext( - DataContext dataContext, - JsonMap? contextDefinition, -) async { - final resolved = {}; - if (contextDefinition == null) return resolved; - - for (final MapEntry entry in contextDefinition.entries) { - final String key = entry.key; - final Object? value = entry.value; - resolved[key] = await dataContext.resolve(value).first; - } - return resolved; -} From 127897180a6174a9768d35828316bfec74db059d Mon Sep 17 00:00:00 2001 From: Jia Hao Goh Date: Mon, 30 Mar 2026 07:51:03 +0000 Subject: [PATCH 5/5] Avoid breaking the api --- .../catalog/basic_catalog_widgets/button.dart | 4 ++- .../basic_catalog_widgets/text_field.dart | 6 +++-- .../genui/lib/src/model/client_function.dart | 3 --- packages/genui/lib/src/model/data_model.dart | 27 ++++++++++--------- .../lib/src/model/validation_helper.dart | 2 +- .../lib/src/widgets/widget_utilities.dart | 2 ++ 6 files changed, 25 insertions(+), 19 deletions(-) diff --git a/packages/genui/lib/src/catalog/basic_catalog_widgets/button.dart b/packages/genui/lib/src/catalog/basic_catalog_widgets/button.dart index 28242621c..9c50c80b2 100644 --- a/packages/genui/lib/src/catalog/basic_catalog_widgets/button.dart +++ b/packages/genui/lib/src/catalog/basic_catalog_widgets/button.dart @@ -7,6 +7,7 @@ import 'package:json_schema_builder/json_schema_builder.dart'; import '../../model/a2ui_schemas.dart'; import '../../model/catalog_item.dart'; +import '../../model/data_model.dart'; import '../../model/ui_models.dart'; import '../../model/validation_helper.dart'; import '../../primitives/logging.dart'; @@ -204,7 +205,8 @@ Future _handlePress( final actionName = eventMap['name'] as String; final contextDefinition = eventMap['context'] as JsonMap?; - final JsonMap resolvedContext = await itemContext.dataContext.resolveMap( + final JsonMap resolvedContext = await resolveContext( + itemContext.dataContext, contextDefinition, ); itemContext.dispatchEvent( diff --git a/packages/genui/lib/src/catalog/basic_catalog_widgets/text_field.dart b/packages/genui/lib/src/catalog/basic_catalog_widgets/text_field.dart index d540aba57..cad6e5c0c 100644 --- a/packages/genui/lib/src/catalog/basic_catalog_widgets/text_field.dart +++ b/packages/genui/lib/src/catalog/basic_catalog_widgets/text_field.dart @@ -253,8 +253,10 @@ final textField = CatalogItem( final eventMap = actionData['event'] as JsonMap; final actionName = eventMap['name'] as String; final contextDefinition = eventMap['context'] as JsonMap?; - final JsonMap resolvedContext = await itemContext.dataContext - .resolveMap(contextDefinition); + final JsonMap resolvedContext = await resolveContext( + itemContext.dataContext, + contextDefinition, + ); itemContext.dispatchEvent( UserActionEvent( name: actionName, diff --git a/packages/genui/lib/src/model/client_function.dart b/packages/genui/lib/src/model/client_function.dart index 54545fa71..d025cacf4 100644 --- a/packages/genui/lib/src/model/client_function.dart +++ b/packages/genui/lib/src/model/client_function.dart @@ -43,9 +43,6 @@ abstract interface class ExecutionContext { /// Evaluates a dynamic boolean condition and returns a [Stream]. Stream evaluateConditionStream(Object? condition); - - /// Resolves a map of dynamic values into a map of literal values. - Future resolveMap(JsonMap? map); } /// A function that can be invoked by the GenUI expression system. diff --git a/packages/genui/lib/src/model/data_model.dart b/packages/genui/lib/src/model/data_model.dart index ccb7f25c3..cdd031110 100644 --- a/packages/genui/lib/src/model/data_model.dart +++ b/packages/genui/lib/src/model/data_model.dart @@ -179,20 +179,23 @@ class DataContext implements cf.ExecutionContext { return v != null; }); } +} - /// Resolves a map of dynamic values into a map of literal values. - @override - Future resolveMap(JsonMap? map) async { - final resolved = {}; - if (map == null) return resolved; - - for (final MapEntry entry in map.entries) { - final String key = entry.key; - final Object? value = entry.value; - resolved[key] = await resolve(value).first; - } - return resolved; +/// Resolves a context map definition against a [DataContext]. +/// +Future resolveContext( + DataContext dataContext, + JsonMap? contextDefinition, +) async { + final resolved = {}; + if (contextDefinition == null) return resolved; + + for (final MapEntry entry in contextDefinition.entries) { + final String key = entry.key; + final Object? value = entry.value; + resolved[key] = await dataContext.resolve(value).first; } + return resolved; } /// Exception thrown when a value in the [DataModel] is not of the expected diff --git a/packages/genui/lib/src/model/validation_helper.dart b/packages/genui/lib/src/model/validation_helper.dart index f50d1de3b..731ce2e59 100644 --- a/packages/genui/lib/src/model/validation_helper.dart +++ b/packages/genui/lib/src/model/validation_helper.dart @@ -63,7 +63,7 @@ class ValidationHelper { final List errors = []; // Resolve schema constraints that might be expressions - final JsonMap resolvedSchema = await dataContext.resolveMap(schema); + final JsonMap resolvedSchema = await resolveContext(dataContext, schema); // simple validation for now, delegating to json_schema_builder would be // ideal, but for now we just check basic constraints we support in genui diff --git a/packages/genui/lib/src/widgets/widget_utilities.dart b/packages/genui/lib/src/widgets/widget_utilities.dart index 0df238770..e356a785c 100644 --- a/packages/genui/lib/src/widgets/widget_utilities.dart +++ b/packages/genui/lib/src/widgets/widget_utilities.dart @@ -10,6 +10,8 @@ import 'package:flutter/material.dart'; import '../model/data_model.dart'; import '../primitives/logging.dart'; +export '../model/data_model.dart' show resolveContext; + /// A builder widget that simplifies handling of nullable `ValueListenable`s. /// /// This widget listens to a `ValueListenable` and rebuilds its child