From 53fd91964aa78b6884c077f75cb9739c38ed5776 Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Wed, 29 Jul 2020 13:27:38 -0700 Subject: [PATCH 01/28] Initial implementation --- lib/over_react.dart | 2 +- lib/src/builder/parsing/ast_util.dart | 4 +- lib/src/builder/parsing/members/factory.dart | 4 +- lib/src/builder/parsing/members_from_ast.dart | 2 +- lib/src/component/ref_util.dart | 110 ++++++++++++++++++ .../function_component.dart | 12 +- 6 files changed, 123 insertions(+), 11 deletions(-) diff --git a/lib/over_react.dart b/lib/over_react.dart index 11642bd9a..17f4485b2 100644 --- a/lib/over_react.dart +++ b/lib/over_react.dart @@ -61,7 +61,7 @@ export 'src/component_declaration/component_base_2.dart' show UiStatefulMixin2; export 'src/component_declaration/built_redux_component.dart'; export 'src/component_declaration/flux_component.dart'; -export 'src/component_declaration/function_component.dart'; +export 'src/component_declaration/function_component.dart' hide getFunctionName, GenericUiProps; export 'src/util/character_constants.dart'; export 'src/util/class_names.dart'; export 'src/util/constants_base.dart'; diff --git a/lib/src/builder/parsing/ast_util.dart b/lib/src/builder/parsing/ast_util.dart index 7326794b4..e1ef4274d 100644 --- a/lib/src/builder/parsing/ast_util.dart +++ b/lib/src/builder/parsing/ast_util.dart @@ -46,7 +46,7 @@ extension InitializerHelperTopLevel on TopLevelVariableDeclaration { bool get hasGeneratedConfigArg { return firstInitializer != null && anyDescendantIdentifiers(firstInitializer, (identifier) { - if (identifier.name == 'uiFunction') { + if (identifier.isFunctionType) { final args = identifier.thisOrAncestorOfType()?.argumentList?.arguments; if (args == null || args.length < 2) return false; @@ -79,6 +79,8 @@ extension NameHelper on Identifier { final self = this; return self is PrefixedIdentifier ? self.identifier.name : self.name; } + + bool get isFunctionType => ['uiFunction', 'uiForwardRef'].contains(this.name); } /// Utilities related to detecting a super class on a [MixinDeclaration] diff --git a/lib/src/builder/parsing/members/factory.dart b/lib/src/builder/parsing/members/factory.dart index dcb3e8442..4396ee52d 100644 --- a/lib/src/builder/parsing/members/factory.dart +++ b/lib/src/builder/parsing/members/factory.dart @@ -40,7 +40,7 @@ class BoilerplateFactory extends BoilerplateMember { if (isFunctionComponentFactory) { final uiFunctionInvocation = getDescendantIdentifier( - node.variables.firstInitializer, (identifier) => identifier.name == 'uiFunction'); + node.variables.firstInitializer, (identifier) => identifier.isFunctionType); final methodInvocation = uiFunctionInvocation.thisOrAncestorOfType(); final typeArgs = methodInvocation?.typeArguments?.arguments?.first; return typeArgs; @@ -56,7 +56,7 @@ class BoilerplateFactory extends BoilerplateMember { bool get isFunctionComponentFactory => node.variables.firstInitializer != null && anyDescendantIdentifiers( - node.variables.firstInitializer, (identifier) => identifier.name == 'uiFunction'); + node.variables.firstInitializer, (identifier) => identifier.isFunctionType); /// Verifies the correct implementation of a boilerplate factory /// diff --git a/lib/src/builder/parsing/members_from_ast.dart b/lib/src/builder/parsing/members_from_ast.dart index 02380d3ac..01cb2999c 100644 --- a/lib/src/builder/parsing/members_from_ast.dart +++ b/lib/src/builder/parsing/members_from_ast.dart @@ -170,7 +170,7 @@ class _BoilerplateMemberDetector { final rightHandSide = node.variables.firstInitializer; if (rightHandSide != null && - anyDescendantIdentifiers(rightHandSide, (identifier) => identifier.name == 'uiFunction')) { + anyDescendantIdentifiers(rightHandSide, (identifier) => identifier.isFunctionType)) { onFactory(BoilerplateFactory( node, VersionConfidences( diff --git a/lib/src/component/ref_util.dart b/lib/src/component/ref_util.dart index 9d0b42300..083b64e03 100644 --- a/lib/src/component/ref_util.dart +++ b/lib/src/component/ref_util.dart @@ -15,6 +15,9 @@ import 'dart:js_util'; import 'package:over_react/src/component_declaration/component_type_checking.dart'; +import 'package:over_react/src/component_declaration/function_component.dart'; +import 'package:over_react/src/component_declaration/builder_helpers.dart' as bh; +import 'package:react/react_client/js_backed_map.dart'; import 'package:react/react_client/react_interop.dart' as react_interop; import 'package:react/react_client.dart'; import 'package:over_react/component_base.dart'; @@ -212,3 +215,110 @@ UiFactory Function(UiFactory) forwardRef return wrapWithForwardRef; } + +/// Automatically passes a [Ref] through a component to one of its children. +/// +/// > __NOTE:__ This should only be used to wrap components that extend from `Component2` +/// > or components using the function syntax. +/// +/// __Example__: +/// +/// mixin FooProps on UiProps { +/// Ref forwardedRef; +/// } +/// +/// final FunctionComponentSyntax = uiForwardRef((props, ref) { +/// return (Dom.button() +/// ..ref = ref +/// )('Click this button'); +/// }, +/// $FunctionSyntaxConfig, // ignore: undefined_identifier +/// ); +/// +/// ___ OR ___ +/// +/// final DomComponentForwarded = uiForwardRef((props, ref) { +/// return (Dom.div() +/// ..ref = ref +/// ..className = 'special-class' +/// )( +/// props.children +/// ); +/// })(Dom.div); +/// +/// ___ OR ___ +/// +/// final FooForwarded = uiForwardRef((props, ref) { +/// return (Foo() +/// ..forwardedRef = ref +/// )(); +/// })(Foo); +/// +/// UiFactory Foo = _$Foo; +/// +/// mixin FooProps on UiProps { +/// Ref forwardedRef; +/// } +/// +/// @Component2() +/// class FooComponent extends UiComponent2 { +/// @override +/// render() { +/// return (Dom.button() +/// ..ref = props.forwardedRef +/// )('Click this button'); +/// } +/// } +/// +/// Learn more: . +UiFactory uiForwardRef( + dynamic Function(TProps props, dynamic ref) functionComponent, + FunctionComponentConfig config) { + ArgumentError.checkNotNull(config, 'config'); + + // ignore: invalid_use_of_protected_member + var propsFactory = config.propsFactory; + + // Get the display name from the inner function if possible so it doesn't become `_uiFunctionWrapper` + final displayName = config.displayName ?? getFunctionName(functionComponent); + + dynamic _uiFunctionWrapper(dynamic props, dynamic ref) { + return functionComponent(propsFactory.jsMap(props), ref); + } + + ReactJsComponentFactoryProxy factory; + + // It's not expected that `displayName` should ever be null, but if it is ever null and get's passed to `forwardRef` + // the name of the component becomes ' ' (an empty string). To protect against this ever happening, this check is in + // place so the name falls back to 'Anonymous'. + if (displayName != null) { + factory = react_interop.forwardRef(_uiFunctionWrapper, displayName: displayName); + } else { + factory = react_interop.forwardRef(_uiFunctionWrapper); + } + + if (propsFactory == null) { + if (TProps != UiProps && TProps != GenericUiProps) { + throw ArgumentError( + 'config.propsFactory must be provided when using custom props classes'); + } + propsFactory = PropsFactory.fromUiFactory( + ([backingMap]) => GenericUiProps(factory, backingMap)) + as PropsFactory; + } + + TProps _uiFactory([Map backingMap]) { + TProps builder; + if (backingMap == null) { + builder = propsFactory.jsMap(JsBackedMap()); + } else if (backingMap is JsBackedMap) { + builder = propsFactory.jsMap(backingMap); + } else { + builder = propsFactory.map(backingMap); + } + + return builder..componentFactory = factory; + } + + return _uiFactory; +} diff --git a/lib/src/component_declaration/function_component.dart b/lib/src/component_declaration/function_component.dart index 419ce6d13..20a74491b 100644 --- a/lib/src/component_declaration/function_component.dart +++ b/lib/src/component_declaration/function_component.dart @@ -98,7 +98,7 @@ UiFactory uiFunction( var propsFactory = config.propsFactory; // Get the display name from the inner function if possible so it doesn't become `_uiFunctionWrapper` - final displayName = config.displayName ?? _getFunctionName(functionComponent); + final displayName = config.displayName ?? getFunctionName(functionComponent); dynamic _uiFunctionWrapper(JsBackedMap props) { return functionComponent(propsFactory.jsMap(props)); @@ -110,12 +110,12 @@ UiFactory uiFunction( ); if (propsFactory == null) { - if (TProps != UiProps && TProps != _GenericUiProps) { + if (TProps != UiProps && TProps != GenericUiProps) { throw ArgumentError( 'config.propsFactory must be provided when using custom props classes'); } propsFactory = PropsFactory.fromUiFactory( - ([backingMap]) => _GenericUiProps(factory, backingMap)) + ([backingMap]) => GenericUiProps(factory, backingMap)) as PropsFactory; } @@ -135,16 +135,16 @@ UiFactory uiFunction( return _uiFactory; } -String _getFunctionName(Function function) { +String getFunctionName(Function function) { return getProperty(function, 'name') ?? getProperty(function, '\$static_name'); } -class _GenericUiProps extends UiProps { +class GenericUiProps extends UiProps { @override final Map props; - _GenericUiProps(ReactComponentFactoryProxy componentFactory, [Map props]) + GenericUiProps(ReactComponentFactoryProxy componentFactory, [Map props]) : this.props = props ?? JsBackedMap() { this.componentFactory = componentFactory; } From 968de33e4502819a796123d56b153eda098d1f0d Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Wed, 29 Jul 2020 13:28:18 -0700 Subject: [PATCH 02/28] Add first go at examples --- web/component2/index.dart | 17 +- web/component2/index.html | 12 +- web/component2/src/demos/forward_ref.dart | 256 ++++- .../src/demos/forward_ref.over_react.g.dart | 897 ++++++++++++++++-- 4 files changed, 1085 insertions(+), 97 deletions(-) diff --git a/web/component2/index.dart b/web/component2/index.dart index 962f9ff5a..2ee42ccd4 100644 --- a/web/component2/index.dart +++ b/web/component2/index.dart @@ -22,7 +22,6 @@ import 'src/demos.dart'; void main() { setClientConfiguration(); - final fancyButtonNodeRef = createRef(); react_dom.render( buttonExamplesDemo(), querySelector('$demoMountNodeSelectorPrefix--button')); @@ -42,18 +41,6 @@ void main() { react_dom.render( radioToggleButtonDemo(), querySelector('$demoMountNodeSelectorPrefix--radio-toggle')); - react_dom.render( - (LogProps() - ..builder = FancyButton - ..className = 'btn btn-primary' - ..ref = fancyButtonNodeRef - ..onClick = (_) { - print(fancyButtonNodeRef.current.outerHtml); - } - )(), - querySelector('$demoMountNodeSelectorPrefix--forwardRef'), - ); - react_dom.render( (v2.ErrorBoundary() ..onComponentDidCatch = (error, info) { @@ -102,4 +89,8 @@ void main() { react_dom.render(ListExample()(), querySelector('$demoMountNodeSelectorPrefix--list-component')); react_dom.render(NumExample()(), querySelector('$demoMountNodeSelectorPrefix--num-component')); react_dom.render(StringExample()(), querySelector('$demoMountNodeSelectorPrefix--string-component')); + react_dom.render( + (RefDemoContainer())(), + querySelector('$demoMountNodeSelectorPrefix--forwardRef'), + ); } diff --git a/web/component2/index.html b/web/component2/index.html index bf1dee7aa..17e432657 100644 --- a/web/component2/index.html +++ b/web/component2/index.html @@ -67,12 +67,6 @@

ToggleButton (Radio)

around with the component rendered below.

-
-

ForwardRef

-

Modify the source of /web/component2/src/demos/forward_ref.dart to play - around with the component rendered below.

-
-

Component That Throws A Caught Error

(Deprecated ErrorBoundary Component)

@@ -129,6 +123,12 @@

String Component

Num Component

+
+

Ref Examples

+

Modify the source of /web/component2/src/demos/forward_ref.dart to play + around with the component rendered below.

+
+
diff --git a/web/component2/src/demos/forward_ref.dart b/web/component2/src/demos/forward_ref.dart index 3b0fffb1f..fb49a9dc4 100644 --- a/web/component2/src/demos/forward_ref.dart +++ b/web/component2/src/demos/forward_ref.dart @@ -1,31 +1,99 @@ +import 'dart:html'; + import 'package:over_react/over_react.dart'; // ignore: uri_has_not_been_generated part 'forward_ref.over_react.g.dart'; -final FancyButton = forwardRef((props, ref) { - final classes = ClassNameBuilder.fromProps(props) - ..add('FancyButton'); +// ------------ `uiForwardRef` with a function component (simple) ------------ +mixin UiForwardRefLogsFunctionComponentProps on UiProps { + BuilderOnlyUiFactory builder; + + // Private since we only use this to pass along the value of `ref` to + // the return value of forwardRef. + // + // Consumers can set this private field value using the public `ref` setter. + Ref _forwardedRef; +} + +final UiForwardRefLogsFunctionComponent = uiForwardRef( + (props, ref) { + return ((props.builder() + ..id = props.id + ..className = props.className + ..onClick = props.onClick + ..ref = ref)(props.children)); + }, + $UiForwardRefLogsFunctionComponentConfig, // ignore: undefined_identifier +); + +// ------------ `uiForwardRef` with a function component (complex) ------------ +mixin UiForwardRefLogsPropsComplexFunctionComponentPropsMixin on UiProps { + String buttonDescription; +} + +class UiForwardRefLogsPropsComplexFunctionComponentProps = UiProps + with + UiForwardRefLogsPropsComplexFunctionComponentPropsMixin, + UiForwardRefLogsFunctionComponentProps; + +final UiForwardRefLogsPropsComplexFunctionComponent = + uiForwardRef( + (props, ref) { + return (Fragment()( + Dom.div()(props.buttonDescription), + (props.builder() + ..id = props.id + ..className = props.className + ..onClick = props.onClick + ..ref = ref)(props.children), + )); + }, + $UiForwardRefLogsPropsComplexFunctionComponentConfig, // ignore: undefined_identifier +); + +// ------------ `uiForwardRef` with a class component (simple) ------------ +final UiForwardRefLogsPropsComponent = uiForwardRef( + (props, ref) { + return (_LogsPropsFunctionComponent() + ..addProps(props) + .._forwardedRef = ref)(); + }, + FunctionComponentConfig( + propsFactory: PropsFactory.fromUiFactory(_LogsPropsFunctionComponent), displayName: null), +); + +// ------------ `uiForwardRef` with a class component (complex) ------------ +mixin UiForwardRefLogsPropsComplexComponentPropsMixin on UiProps { + String buttonDescription; +} + +class UiForwardRefLogsPropsComplexComponentProps = UiProps + with UiForwardRefLogsPropsComplexFunctionComponentPropsMixin, LogPropsProps; - return (Dom.button() - ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) - ..className = classes.toClassName() - ..ref = ref - )('Click me!'); -}, displayName: 'FancyButton')(Dom.button); +final UiForwardRefLogsPropsComplexComponent = + uiForwardRef( + (props, ref) { + return Fragment()( + Dom.div()(props.buttonDescription), + (_LogsPropsFunctionComponent() + ..addProps(props) + .._forwardedRef = ref)(), + ); + }, + $UiForwardRefLogsPropsComplexComponentConfig, // ignore: undefined_identifier +); +// ------------ `forwardRef` (deprecated) with class component ------------ final LogProps = forwardRef((props, ref) { return (_LogProps() ..addProps(props) - .._forwardedRef = ref - )('Click me!'); + .._forwardedRef = ref)(); }, displayName: 'LogProps')(_LogProps); -@Factory() UiFactory _LogProps = _$_LogProps; -@Props() -class _$LogPropsProps extends UiProps { +mixin LogPropsProps on UiProps { BuilderOnlyUiFactory builder; // Private since we only use this to pass along the value of `ref` to @@ -35,7 +103,6 @@ class _$LogPropsProps extends UiProps { Ref _forwardedRef; } -@Component2() class LogPropsComponent extends UiComponent2 { @override void componentDidUpdate(Map prevProps, _, [__]) { @@ -47,7 +114,160 @@ class LogPropsComponent extends UiComponent2 { render() { return (props.builder() ..modifyProps(addUnconsumedDomProps) - ..ref = props._forwardedRef - )(props.children); + ..ref = props._forwardedRef)(props.children); } -} \ No newline at end of file +} + +// ------------ `forwardRef` (deprecated) with Function component ------------ +final LogsPropsFunctionComponent = forwardRef<_LogsPropsFunctionComponentProps>((props, ref) { + return (_LogsPropsFunctionComponent() + ..addProps(props) + .._forwardedRef = ref)(); +}, displayName: 'LogsPropsFunctionComponent')(_LogsPropsFunctionComponent); + +class _LogsPropsFunctionComponentProps = UiProps with LogPropsProps; + +final _LogsPropsFunctionComponent = uiFunction<_LogsPropsFunctionComponentProps>( + (props) { + return ((props.builder() + ..id = props.id + ..className = props.className + ..onClick = props.onClick + ..ref = props._forwardedRef)(props.children)); + }, + $_LogsPropsFunctionComponentConfig, // ignore: undefined_identifier +); + +// -------------------------------- Demo Display Logic -------------------------------- +final FancyButton = uiForwardRef( + (props, ref) { + final classes = ClassNameBuilder.fromProps(props)..add('FancyButton'); + + return (Dom.button() + ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) + ..className = classes.toClassName() + ..ref = ref)('Click me!'); + }, + FunctionComponentConfig(propsFactory: PropsFactory.fromUiFactory(Dom.button), displayName: null), +); + +mixin RefDemoProps on UiProps {} + +final RefDemoContainer = uiFunction( + (props) { + // `uiForwardRef` Refs + final buttonNodeRefForSimpleFunctionComponent = createRef(); + final buttonNodeRefForComplexFunctionComponent = createRef(); + final buttonNodeRefForSimpleComponent = createRef(); + final buttonNodeRefForComplexComponent = createRef(); + + // `forwardRef` Refs + final fancyButtonNodeRef = createRef(); + final fancyFunctionalButtonNodeRef = createRef(); + + return ((Dom.div()..style = {'padding': 10})( + (RefDemoSection()..sectionTitle = 'uiForwardRef Demos')( + (RefDemoHoc()..demoTitle = '`uiForwardRef` with a function component (simple)')( + (UiForwardRefLogsFunctionComponent() + ..builder = FancyButton + ..id = 'uiForwardRef-function-component' + ..className = 'btn btn-primary' + ..ref = buttonNodeRefForSimpleFunctionComponent + ..onClick = (_) { + print(buttonNodeRefForSimpleFunctionComponent.current.outerHtml); + })(), + ), + (RefDemoHoc()..demoTitle = '`uiForwardRef` with a function component (complex)')( + (UiForwardRefLogsPropsComplexFunctionComponent() + ..buttonDescription = 'A button that logs the innerHtml' + ..builder = FancyButton + ..id = 'uiForwardRef-function-complex-component' + ..className = 'btn btn-success' + ..ref = buttonNodeRefForComplexFunctionComponent + ..onClick = (_) { + print(buttonNodeRefForComplexFunctionComponent.current.outerHtml); + })(), + ), + (RefDemoHoc()..demoTitle = '`uiForwardRef` with a class component (simple)')( + (UiForwardRefLogsPropsComponent() + ..builder = FancyButton + ..id = 'uiForwardRef-component' + ..className = 'btn btn-warning' + ..ref = buttonNodeRefForSimpleComponent + ..onClick = (_) { + print(buttonNodeRefForSimpleComponent.current.outerHtml); + })(), + ), + (RefDemoHoc()..demoTitle = '`uiForwardRef` with a class component (complex)')( + (UiForwardRefLogsPropsComplexComponent() + ..buttonDescription = 'A button that logs the innerHtml' + ..builder = FancyButton + ..id = 'uiForwardRef-complex-component' + ..className = 'btn btn-danger' + ..ref = buttonNodeRefForComplexComponent + ..onClick = (_) { + print(buttonNodeRefForComplexComponent.current.outerHtml); + })(), + ), + ), + (RefDemoSection()..sectionTitle = 'forwardRef (deprecated) Demos')( + (RefDemoHoc()..demoTitle = '`forwardRef` with class component')( + (LogProps() + ..builder = FancyButton + ..id = 'forwardRef-component' + ..className = 'btn btn-primary' + ..ref = fancyButtonNodeRef + ..onClick = (_) { + print(fancyButtonNodeRef.current.outerHtml); + })(), + ), + (RefDemoHoc()..demoTitle = '`uiForwardRef` with function component')( + (LogsPropsFunctionComponent() + ..builder = FancyButton + ..id = 'forwardRef-function-component' + ..className = 'btn btn-success' + ..ref = fancyFunctionalButtonNodeRef + ..onClick = (_) { + print(fancyFunctionalButtonNodeRef.current.outerHtml); + })(), + ), + ), + )); + }, + $RefDemoContainerConfig, // ignore: undefined_identifier +); + +mixin RefDemoSectionProps on UiProps { + String sectionTitle; +} + +final RefDemoSection = uiFunction( + (props) { + return (Fragment()( + (Dom.h3()..style = {'color': 'gray', 'borderBottom': '1px solid gray', 'marginTop': 10})( + props.sectionTitle, + ), + (Dom.div() + ..style = { + 'display': 'flex', + 'flexWrap': 'wrap', + })( + props.children, + ))); + }, + $RefDemoSectionConfig, // ignore: undefined_identifier +); + +mixin RefDemoHocProps on UiProps { + String demoTitle; +} + +final RefDemoHoc = uiFunction( + (props) { + return ((Dom.div()..style = {'flex': '0 50%', 'width': '100%', 'marginTop': 10})( + Dom.h4()(props.demoTitle), + props.children, + )); + }, + $RefDemoHocConfig, // ignore: undefined_identifier +); diff --git a/web/component2/src/demos/forward_ref.over_react.g.dart b/web/component2/src/demos/forward_ref.over_react.g.dart index ff2b05aa5..3abfce35a 100644 --- a/web/component2/src/demos/forward_ref.over_react.g.dart +++ b/web/component2/src/demos/forward_ref.over_react.g.dart @@ -10,66 +10,17 @@ part of 'forward_ref.dart'; // React component factory implementation. // // Registers component implementation and links type meta to builder factory. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') final $LogPropsComponentFactory = registerComponent2( () => _$LogPropsComponent(), - builderFactory: _LogProps, + builderFactory: _$_LogProps, componentClass: LogPropsComponent, isWrapper: false, parentType: null, displayName: '_LogProps', ); -abstract class _$LogPropsPropsAccessorsMixin implements _$LogPropsProps { - @override - Map get props; - - /// - @override - BuilderOnlyUiFactory get builder => - props[_$key__builder___$LogPropsProps] ?? - null; // Add ` ?? null` to workaround DDC bug: ; - /// - @override - set builder(BuilderOnlyUiFactory value) => - props[_$key__builder___$LogPropsProps] = value; - - /// - @override - Ref get _forwardedRef => - props[_$key___forwardedRef___$LogPropsProps] ?? - null; // Add ` ?? null` to workaround DDC bug: ; - /// - @override - set _forwardedRef(Ref value) => - props[_$key___forwardedRef___$LogPropsProps] = value; - /* GENERATED CONSTANTS */ - static const PropDescriptor _$prop__builder___$LogPropsProps = - PropDescriptor(_$key__builder___$LogPropsProps); - static const PropDescriptor _$prop___forwardedRef___$LogPropsProps = - PropDescriptor(_$key___forwardedRef___$LogPropsProps); - static const String _$key__builder___$LogPropsProps = 'LogPropsProps.builder'; - static const String _$key___forwardedRef___$LogPropsProps = - 'LogPropsProps._forwardedRef'; - - static const List $props = [ - _$prop__builder___$LogPropsProps, - _$prop___forwardedRef___$LogPropsProps - ]; - static const List $propKeys = [ - _$key__builder___$LogPropsProps, - _$key___forwardedRef___$LogPropsProps - ]; -} - -const PropsMeta _$metaForLogPropsProps = PropsMeta( - fields: _$LogPropsPropsAccessorsMixin.$props, - keys: _$LogPropsPropsAccessorsMixin.$propKeys, -); - -class LogPropsProps extends _$LogPropsProps with _$LogPropsPropsAccessorsMixin { - static const PropsMeta meta = _$metaForLogPropsProps; -} - _$$LogPropsProps _$_LogProps([Map backingProps]) => backingProps == null ? _$$LogPropsProps$JsMap(JsBackedMap()) : _$$LogPropsProps(backingProps); @@ -77,9 +28,13 @@ _$$LogPropsProps _$_LogProps([Map backingProps]) => backingProps == null // Concrete props implementation. // // Implements constructor and backing map, and links up to generated component factory. -abstract class _$$LogPropsProps extends _$LogPropsProps - with _$LogPropsPropsAccessorsMixin - implements LogPropsProps { +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +abstract class _$$LogPropsProps extends UiProps + with + LogPropsProps, + $LogPropsProps // If this generated mixin is undefined, it's likely because LogPropsProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of LogPropsProps. +{ _$$LogPropsProps._(); factory _$$LogPropsProps(Map backingMap) { @@ -101,10 +56,12 @@ abstract class _$$LogPropsProps extends _$LogPropsProps /// The default namespace for the prop getters/setters generated for this class. @override - String get propKeyNamespace => 'LogPropsProps.'; + String get propKeyNamespace => ''; } // Concrete props implementation that can be backed by any [Map]. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') class _$$LogPropsProps$PlainMap extends _$$LogPropsProps { // This initializer of `_props` to an empty map, as well as the reassignment // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 @@ -122,6 +79,8 @@ class _$$LogPropsProps$PlainMap extends _$$LogPropsProps { // Concrete props implementation that can only be backed by [JsMap], // allowing dart2js to compile more optimal code for key-value pair reads/writes. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') class _$$LogPropsProps$JsMap extends _$$LogPropsProps { // This initializer of `_props` to an empty map, as well as the reassignment // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 @@ -141,6 +100,8 @@ class _$$LogPropsProps$JsMap extends _$$LogPropsProps { // // Implements typed props/state factories, defaults `consumedPropKeys` to the keys // generated for the associated props class. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') class _$LogPropsComponent extends LogPropsComponent { _$$LogPropsProps$JsMap _cachedTypedProps; @@ -172,10 +133,826 @@ class _$LogPropsComponent extends LogPropsComponent { @override bool get $isClassGenerated => true; - /// The default consumed props, taken from _$LogPropsProps. - /// Used in `ConsumedProps` if [consumedProps] is not overridden. + /// The default consumed props, comprising all props mixins used by LogPropsProps. + /// Used in `*ConsumedProps` methods if [consumedProps] is not overridden. + @override + get $defaultConsumedProps => propsMeta.all; + + @override + PropsMetaCollection get propsMeta => const PropsMetaCollection({ + // If this generated mixin is undefined, it's likely because LogPropsProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of LogPropsProps. + LogPropsProps: $LogPropsProps.meta, + }); +} + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.' + ' EXCEPTION: this may be used in legacy boilerplate until' + ' it is transitioned to the new mixin-based boilerplate.') +mixin $UiForwardRefLogsFunctionComponentProps + on UiForwardRefLogsFunctionComponentProps { + static const PropsMeta meta = _$metaForUiForwardRefLogsFunctionComponentProps; @override - final List $defaultConsumedProps = const [ - _$metaForLogPropsProps + BuilderOnlyUiFactory get builder => + props[_$key__builder__UiForwardRefLogsFunctionComponentProps] ?? + null; // Add ` ?? null` to workaround DDC bug: ; + @override + set builder(BuilderOnlyUiFactory value) => + props[_$key__builder__UiForwardRefLogsFunctionComponentProps] = value; + @override + Ref get _forwardedRef => + props[_$key___forwardedRef__UiForwardRefLogsFunctionComponentProps] ?? + null; // Add ` ?? null` to workaround DDC bug: ; + @override + set _forwardedRef(Ref value) => + props[_$key___forwardedRef__UiForwardRefLogsFunctionComponentProps] = + value; + /* GENERATED CONSTANTS */ + static const PropDescriptor + _$prop__builder__UiForwardRefLogsFunctionComponentProps = + PropDescriptor(_$key__builder__UiForwardRefLogsFunctionComponentProps); + static const PropDescriptor + _$prop___forwardedRef__UiForwardRefLogsFunctionComponentProps = + PropDescriptor( + _$key___forwardedRef__UiForwardRefLogsFunctionComponentProps); + static const String _$key__builder__UiForwardRefLogsFunctionComponentProps = + 'UiForwardRefLogsFunctionComponentProps.builder'; + static const String + _$key___forwardedRef__UiForwardRefLogsFunctionComponentProps = + 'UiForwardRefLogsFunctionComponentProps._forwardedRef'; + + static const List $props = [ + _$prop__builder__UiForwardRefLogsFunctionComponentProps, + _$prop___forwardedRef__UiForwardRefLogsFunctionComponentProps + ]; + static const List $propKeys = [ + _$key__builder__UiForwardRefLogsFunctionComponentProps, + _$key___forwardedRef__UiForwardRefLogsFunctionComponentProps + ]; +} + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +const PropsMeta _$metaForUiForwardRefLogsFunctionComponentProps = PropsMeta( + fields: $UiForwardRefLogsFunctionComponentProps.$props, + keys: $UiForwardRefLogsFunctionComponentProps.$propKeys, +); + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.' + ' EXCEPTION: this may be used in legacy boilerplate until' + ' it is transitioned to the new mixin-based boilerplate.') +mixin $UiForwardRefLogsPropsComplexFunctionComponentPropsMixin + on UiForwardRefLogsPropsComplexFunctionComponentPropsMixin { + static const PropsMeta meta = + _$metaForUiForwardRefLogsPropsComplexFunctionComponentPropsMixin; + @override + String get buttonDescription => + props[ + _$key__buttonDescription__UiForwardRefLogsPropsComplexFunctionComponentPropsMixin] ?? + null; // Add ` ?? null` to workaround DDC bug: ; + @override + set buttonDescription(String value) => props[ + _$key__buttonDescription__UiForwardRefLogsPropsComplexFunctionComponentPropsMixin] = + value; + /* GENERATED CONSTANTS */ + static const PropDescriptor + _$prop__buttonDescription__UiForwardRefLogsPropsComplexFunctionComponentPropsMixin = + PropDescriptor( + _$key__buttonDescription__UiForwardRefLogsPropsComplexFunctionComponentPropsMixin); + static const String + _$key__buttonDescription__UiForwardRefLogsPropsComplexFunctionComponentPropsMixin = + 'UiForwardRefLogsPropsComplexFunctionComponentPropsMixin.buttonDescription'; + + static const List $props = [ + _$prop__buttonDescription__UiForwardRefLogsPropsComplexFunctionComponentPropsMixin + ]; + static const List $propKeys = [ + _$key__buttonDescription__UiForwardRefLogsPropsComplexFunctionComponentPropsMixin + ]; +} + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +const PropsMeta + _$metaForUiForwardRefLogsPropsComplexFunctionComponentPropsMixin = + PropsMeta( + fields: $UiForwardRefLogsPropsComplexFunctionComponentPropsMixin.$props, + keys: $UiForwardRefLogsPropsComplexFunctionComponentPropsMixin.$propKeys, +); + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.' + ' EXCEPTION: this may be used in legacy boilerplate until' + ' it is transitioned to the new mixin-based boilerplate.') +mixin $UiForwardRefLogsPropsComplexComponentPropsMixin + on UiForwardRefLogsPropsComplexComponentPropsMixin { + static const PropsMeta meta = + _$metaForUiForwardRefLogsPropsComplexComponentPropsMixin; + @override + String get buttonDescription => + props[ + _$key__buttonDescription__UiForwardRefLogsPropsComplexComponentPropsMixin] ?? + null; // Add ` ?? null` to workaround DDC bug: ; + @override + set buttonDescription(String value) => props[ + _$key__buttonDescription__UiForwardRefLogsPropsComplexComponentPropsMixin] = + value; + /* GENERATED CONSTANTS */ + static const PropDescriptor + _$prop__buttonDescription__UiForwardRefLogsPropsComplexComponentPropsMixin = + PropDescriptor( + _$key__buttonDescription__UiForwardRefLogsPropsComplexComponentPropsMixin); + static const String + _$key__buttonDescription__UiForwardRefLogsPropsComplexComponentPropsMixin = + 'UiForwardRefLogsPropsComplexComponentPropsMixin.buttonDescription'; + + static const List $props = [ + _$prop__buttonDescription__UiForwardRefLogsPropsComplexComponentPropsMixin + ]; + static const List $propKeys = [ + _$key__buttonDescription__UiForwardRefLogsPropsComplexComponentPropsMixin + ]; +} + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +const PropsMeta _$metaForUiForwardRefLogsPropsComplexComponentPropsMixin = + PropsMeta( + fields: $UiForwardRefLogsPropsComplexComponentPropsMixin.$props, + keys: $UiForwardRefLogsPropsComplexComponentPropsMixin.$propKeys, +); + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.' + ' EXCEPTION: this may be used in legacy boilerplate until' + ' it is transitioned to the new mixin-based boilerplate.') +mixin $LogPropsProps on LogPropsProps { + static const PropsMeta meta = _$metaForLogPropsProps; + @override + BuilderOnlyUiFactory get builder => + props[_$key__builder__LogPropsProps] ?? + null; // Add ` ?? null` to workaround DDC bug: ; + @override + set builder(BuilderOnlyUiFactory value) => + props[_$key__builder__LogPropsProps] = value; + @override + Ref get _forwardedRef => + props[_$key___forwardedRef__LogPropsProps] ?? + null; // Add ` ?? null` to workaround DDC bug: ; + @override + set _forwardedRef(Ref value) => + props[_$key___forwardedRef__LogPropsProps] = value; + /* GENERATED CONSTANTS */ + static const PropDescriptor _$prop__builder__LogPropsProps = + PropDescriptor(_$key__builder__LogPropsProps); + static const PropDescriptor _$prop___forwardedRef__LogPropsProps = + PropDescriptor(_$key___forwardedRef__LogPropsProps); + static const String _$key__builder__LogPropsProps = 'LogPropsProps.builder'; + static const String _$key___forwardedRef__LogPropsProps = + 'LogPropsProps._forwardedRef'; + + static const List $props = [ + _$prop__builder__LogPropsProps, + _$prop___forwardedRef__LogPropsProps + ]; + static const List $propKeys = [ + _$key__builder__LogPropsProps, + _$key___forwardedRef__LogPropsProps + ]; +} + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +const PropsMeta _$metaForLogPropsProps = PropsMeta( + fields: $LogPropsProps.$props, + keys: $LogPropsProps.$propKeys, +); + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.' + ' EXCEPTION: this may be used in legacy boilerplate until' + ' it is transitioned to the new mixin-based boilerplate.') +mixin $RefDemoProps on RefDemoProps { + static const PropsMeta meta = _$metaForRefDemoProps; + /* GENERATED CONSTANTS */ + + static const List $props = []; + static const List $propKeys = []; +} + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +const PropsMeta _$metaForRefDemoProps = PropsMeta( + fields: $RefDemoProps.$props, + keys: $RefDemoProps.$propKeys, +); + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.' + ' EXCEPTION: this may be used in legacy boilerplate until' + ' it is transitioned to the new mixin-based boilerplate.') +mixin $RefDemoSectionProps on RefDemoSectionProps { + static const PropsMeta meta = _$metaForRefDemoSectionProps; + @override + String get sectionTitle => + props[_$key__sectionTitle__RefDemoSectionProps] ?? + null; // Add ` ?? null` to workaround DDC bug: ; + @override + set sectionTitle(String value) => + props[_$key__sectionTitle__RefDemoSectionProps] = value; + /* GENERATED CONSTANTS */ + static const PropDescriptor _$prop__sectionTitle__RefDemoSectionProps = + PropDescriptor(_$key__sectionTitle__RefDemoSectionProps); + static const String _$key__sectionTitle__RefDemoSectionProps = + 'RefDemoSectionProps.sectionTitle'; + + static const List $props = [ + _$prop__sectionTitle__RefDemoSectionProps + ]; + static const List $propKeys = [ + _$key__sectionTitle__RefDemoSectionProps ]; } + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +const PropsMeta _$metaForRefDemoSectionProps = PropsMeta( + fields: $RefDemoSectionProps.$props, + keys: $RefDemoSectionProps.$propKeys, +); + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.' + ' EXCEPTION: this may be used in legacy boilerplate until' + ' it is transitioned to the new mixin-based boilerplate.') +mixin $RefDemoHocProps on RefDemoHocProps { + static const PropsMeta meta = _$metaForRefDemoHocProps; + @override + String get demoTitle => + props[_$key__demoTitle__RefDemoHocProps] ?? + null; // Add ` ?? null` to workaround DDC bug: ; + @override + set demoTitle(String value) => + props[_$key__demoTitle__RefDemoHocProps] = value; + /* GENERATED CONSTANTS */ + static const PropDescriptor _$prop__demoTitle__RefDemoHocProps = + PropDescriptor(_$key__demoTitle__RefDemoHocProps); + static const String _$key__demoTitle__RefDemoHocProps = + 'RefDemoHocProps.demoTitle'; + + static const List $props = [ + _$prop__demoTitle__RefDemoHocProps + ]; + static const List $propKeys = [_$key__demoTitle__RefDemoHocProps]; +} + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +const PropsMeta _$metaForRefDemoHocProps = PropsMeta( + fields: $RefDemoHocProps.$props, + keys: $RefDemoHocProps.$propKeys, +); + +final FunctionComponentConfig<_$$UiForwardRefLogsFunctionComponentProps> + $UiForwardRefLogsFunctionComponentConfig = FunctionComponentConfig( + propsFactory: PropsFactory( + map: (map) => _$$UiForwardRefLogsFunctionComponentProps(map), + jsMap: (map) => _$$UiForwardRefLogsFunctionComponentProps$JsMap(map), + ), + displayName: 'UiForwardRefLogsFunctionComponent'); + +// Concrete props implementation. +// +// Implements constructor and backing map, and links up to generated component factory. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +abstract class _$$UiForwardRefLogsFunctionComponentProps extends UiProps + with + UiForwardRefLogsFunctionComponentProps, + $UiForwardRefLogsFunctionComponentProps // If this generated mixin is undefined, it's likely because UiForwardRefLogsFunctionComponentProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of UiForwardRefLogsFunctionComponentProps. +{ + _$$UiForwardRefLogsFunctionComponentProps._(); + + factory _$$UiForwardRefLogsFunctionComponentProps(Map backingMap) { + if (backingMap == null || backingMap is JsBackedMap) { + return _$$UiForwardRefLogsFunctionComponentProps$JsMap(backingMap); + } else { + return _$$UiForwardRefLogsFunctionComponentProps$PlainMap(backingMap); + } + } + + /// Let `UiProps` internals know that this class has been generated. + @override + bool get $isClassGenerated => true; + + /// The default namespace for the prop getters/setters generated for this class. + @override + String get propKeyNamespace => ''; +} + +// Concrete props implementation that can be backed by any [Map]. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$UiForwardRefLogsFunctionComponentProps$PlainMap + extends _$$UiForwardRefLogsFunctionComponentProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$UiForwardRefLogsFunctionComponentProps$PlainMap(Map backingMap) + : this._props = {}, + super._() { + this._props = backingMap ?? {}; + } + + /// The backing props map proxied by this class. + @override + Map get props => _props; + Map _props; +} + +// Concrete props implementation that can only be backed by [JsMap], +// allowing dart2js to compile more optimal code for key-value pair reads/writes. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$UiForwardRefLogsFunctionComponentProps$JsMap + extends _$$UiForwardRefLogsFunctionComponentProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$UiForwardRefLogsFunctionComponentProps$JsMap(JsBackedMap backingMap) + : this._props = JsBackedMap(), + super._() { + this._props = backingMap ?? JsBackedMap(); + } + + /// The backing props map proxied by this class. + @override + JsBackedMap get props => _props; + JsBackedMap _props; +} + +final FunctionComponentConfig< + _$$UiForwardRefLogsPropsComplexFunctionComponentProps> + $UiForwardRefLogsPropsComplexFunctionComponentConfig = + FunctionComponentConfig( + propsFactory: PropsFactory( + map: (map) => + _$$UiForwardRefLogsPropsComplexFunctionComponentProps(map), + jsMap: (map) => + _$$UiForwardRefLogsPropsComplexFunctionComponentProps$JsMap(map), + ), + displayName: 'UiForwardRefLogsPropsComplexFunctionComponent'); + +// Concrete props implementation. +// +// Implements constructor and backing map, and links up to generated component factory. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +abstract class _$$UiForwardRefLogsPropsComplexFunctionComponentProps + extends UiProps + with + UiForwardRefLogsPropsComplexFunctionComponentPropsMixin, + $UiForwardRefLogsPropsComplexFunctionComponentPropsMixin, // If this generated mixin is undefined, it's likely because UiForwardRefLogsPropsComplexFunctionComponentPropsMixin is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of UiForwardRefLogsPropsComplexFunctionComponentPropsMixin. + UiForwardRefLogsFunctionComponentProps, + $UiForwardRefLogsFunctionComponentProps // If this generated mixin is undefined, it's likely because UiForwardRefLogsFunctionComponentProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of UiForwardRefLogsFunctionComponentProps. + implements + UiForwardRefLogsPropsComplexFunctionComponentProps { + _$$UiForwardRefLogsPropsComplexFunctionComponentProps._(); + + factory _$$UiForwardRefLogsPropsComplexFunctionComponentProps( + Map backingMap) { + if (backingMap == null || backingMap is JsBackedMap) { + return _$$UiForwardRefLogsPropsComplexFunctionComponentProps$JsMap( + backingMap); + } else { + return _$$UiForwardRefLogsPropsComplexFunctionComponentProps$PlainMap( + backingMap); + } + } + + /// Let `UiProps` internals know that this class has been generated. + @override + bool get $isClassGenerated => true; + + /// The default namespace for the prop getters/setters generated for this class. + @override + String get propKeyNamespace => ''; +} + +// Concrete props implementation that can be backed by any [Map]. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$UiForwardRefLogsPropsComplexFunctionComponentProps$PlainMap + extends _$$UiForwardRefLogsPropsComplexFunctionComponentProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$UiForwardRefLogsPropsComplexFunctionComponentProps$PlainMap(Map backingMap) + : this._props = {}, + super._() { + this._props = backingMap ?? {}; + } + + /// The backing props map proxied by this class. + @override + Map get props => _props; + Map _props; +} + +// Concrete props implementation that can only be backed by [JsMap], +// allowing dart2js to compile more optimal code for key-value pair reads/writes. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$UiForwardRefLogsPropsComplexFunctionComponentProps$JsMap + extends _$$UiForwardRefLogsPropsComplexFunctionComponentProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$UiForwardRefLogsPropsComplexFunctionComponentProps$JsMap( + JsBackedMap backingMap) + : this._props = JsBackedMap(), + super._() { + this._props = backingMap ?? JsBackedMap(); + } + + /// The backing props map proxied by this class. + @override + JsBackedMap get props => _props; + JsBackedMap _props; +} + +final FunctionComponentConfig<_$$UiForwardRefLogsPropsComplexComponentProps> + $UiForwardRefLogsPropsComplexComponentConfig = FunctionComponentConfig( + propsFactory: PropsFactory( + map: (map) => _$$UiForwardRefLogsPropsComplexComponentProps(map), + jsMap: (map) => + _$$UiForwardRefLogsPropsComplexComponentProps$JsMap(map), + ), + displayName: 'UiForwardRefLogsPropsComplexComponent'); + +// Concrete props implementation. +// +// Implements constructor and backing map, and links up to generated component factory. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +abstract class _$$UiForwardRefLogsPropsComplexComponentProps extends UiProps + with + UiForwardRefLogsPropsComplexFunctionComponentPropsMixin, + $UiForwardRefLogsPropsComplexFunctionComponentPropsMixin, // If this generated mixin is undefined, it's likely because UiForwardRefLogsPropsComplexFunctionComponentPropsMixin is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of UiForwardRefLogsPropsComplexFunctionComponentPropsMixin. + LogPropsProps, + $LogPropsProps // If this generated mixin is undefined, it's likely because LogPropsProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of LogPropsProps. + implements + UiForwardRefLogsPropsComplexComponentProps { + _$$UiForwardRefLogsPropsComplexComponentProps._(); + + factory _$$UiForwardRefLogsPropsComplexComponentProps(Map backingMap) { + if (backingMap == null || backingMap is JsBackedMap) { + return _$$UiForwardRefLogsPropsComplexComponentProps$JsMap(backingMap); + } else { + return _$$UiForwardRefLogsPropsComplexComponentProps$PlainMap(backingMap); + } + } + + /// Let `UiProps` internals know that this class has been generated. + @override + bool get $isClassGenerated => true; + + /// The default namespace for the prop getters/setters generated for this class. + @override + String get propKeyNamespace => ''; +} + +// Concrete props implementation that can be backed by any [Map]. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$UiForwardRefLogsPropsComplexComponentProps$PlainMap + extends _$$UiForwardRefLogsPropsComplexComponentProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$UiForwardRefLogsPropsComplexComponentProps$PlainMap(Map backingMap) + : this._props = {}, + super._() { + this._props = backingMap ?? {}; + } + + /// The backing props map proxied by this class. + @override + Map get props => _props; + Map _props; +} + +// Concrete props implementation that can only be backed by [JsMap], +// allowing dart2js to compile more optimal code for key-value pair reads/writes. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$UiForwardRefLogsPropsComplexComponentProps$JsMap + extends _$$UiForwardRefLogsPropsComplexComponentProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$UiForwardRefLogsPropsComplexComponentProps$JsMap(JsBackedMap backingMap) + : this._props = JsBackedMap(), + super._() { + this._props = backingMap ?? JsBackedMap(); + } + + /// The backing props map proxied by this class. + @override + JsBackedMap get props => _props; + JsBackedMap _props; +} + +final FunctionComponentConfig<_$$_LogsPropsFunctionComponentProps> + $_LogsPropsFunctionComponentConfig = FunctionComponentConfig( + propsFactory: PropsFactory( + map: (map) => _$$_LogsPropsFunctionComponentProps(map), + jsMap: (map) => _$$_LogsPropsFunctionComponentProps$JsMap(map), + ), + displayName: '_LogsPropsFunctionComponent'); + +// Concrete props implementation. +// +// Implements constructor and backing map, and links up to generated component factory. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +abstract class _$$_LogsPropsFunctionComponentProps extends UiProps + with + LogPropsProps, + $LogPropsProps // If this generated mixin is undefined, it's likely because LogPropsProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of LogPropsProps. + implements + _LogsPropsFunctionComponentProps { + _$$_LogsPropsFunctionComponentProps._(); + + factory _$$_LogsPropsFunctionComponentProps(Map backingMap) { + if (backingMap == null || backingMap is JsBackedMap) { + return _$$_LogsPropsFunctionComponentProps$JsMap(backingMap); + } else { + return _$$_LogsPropsFunctionComponentProps$PlainMap(backingMap); + } + } + + /// Let `UiProps` internals know that this class has been generated. + @override + bool get $isClassGenerated => true; + + /// The default namespace for the prop getters/setters generated for this class. + @override + String get propKeyNamespace => ''; +} + +// Concrete props implementation that can be backed by any [Map]. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$_LogsPropsFunctionComponentProps$PlainMap + extends _$$_LogsPropsFunctionComponentProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$_LogsPropsFunctionComponentProps$PlainMap(Map backingMap) + : this._props = {}, + super._() { + this._props = backingMap ?? {}; + } + + /// The backing props map proxied by this class. + @override + Map get props => _props; + Map _props; +} + +// Concrete props implementation that can only be backed by [JsMap], +// allowing dart2js to compile more optimal code for key-value pair reads/writes. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$_LogsPropsFunctionComponentProps$JsMap + extends _$$_LogsPropsFunctionComponentProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$_LogsPropsFunctionComponentProps$JsMap(JsBackedMap backingMap) + : this._props = JsBackedMap(), + super._() { + this._props = backingMap ?? JsBackedMap(); + } + + /// The backing props map proxied by this class. + @override + JsBackedMap get props => _props; + JsBackedMap _props; +} + +final FunctionComponentConfig<_$$RefDemoProps> $RefDemoContainerConfig = + FunctionComponentConfig( + propsFactory: PropsFactory( + map: (map) => _$$RefDemoProps(map), + jsMap: (map) => _$$RefDemoProps$JsMap(map), + ), + displayName: 'RefDemoContainer'); + +// Concrete props implementation. +// +// Implements constructor and backing map, and links up to generated component factory. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +abstract class _$$RefDemoProps extends UiProps + with + RefDemoProps, + $RefDemoProps // If this generated mixin is undefined, it's likely because RefDemoProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of RefDemoProps. +{ + _$$RefDemoProps._(); + + factory _$$RefDemoProps(Map backingMap) { + if (backingMap == null || backingMap is JsBackedMap) { + return _$$RefDemoProps$JsMap(backingMap); + } else { + return _$$RefDemoProps$PlainMap(backingMap); + } + } + + /// Let `UiProps` internals know that this class has been generated. + @override + bool get $isClassGenerated => true; + + /// The default namespace for the prop getters/setters generated for this class. + @override + String get propKeyNamespace => ''; +} + +// Concrete props implementation that can be backed by any [Map]. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$RefDemoProps$PlainMap extends _$$RefDemoProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$RefDemoProps$PlainMap(Map backingMap) + : this._props = {}, + super._() { + this._props = backingMap ?? {}; + } + + /// The backing props map proxied by this class. + @override + Map get props => _props; + Map _props; +} + +// Concrete props implementation that can only be backed by [JsMap], +// allowing dart2js to compile more optimal code for key-value pair reads/writes. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$RefDemoProps$JsMap extends _$$RefDemoProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$RefDemoProps$JsMap(JsBackedMap backingMap) + : this._props = JsBackedMap(), + super._() { + this._props = backingMap ?? JsBackedMap(); + } + + /// The backing props map proxied by this class. + @override + JsBackedMap get props => _props; + JsBackedMap _props; +} + +final FunctionComponentConfig<_$$RefDemoSectionProps> $RefDemoSectionConfig = + FunctionComponentConfig( + propsFactory: PropsFactory( + map: (map) => _$$RefDemoSectionProps(map), + jsMap: (map) => _$$RefDemoSectionProps$JsMap(map), + ), + displayName: 'RefDemoSection'); + +// Concrete props implementation. +// +// Implements constructor and backing map, and links up to generated component factory. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +abstract class _$$RefDemoSectionProps extends UiProps + with + RefDemoSectionProps, + $RefDemoSectionProps // If this generated mixin is undefined, it's likely because RefDemoSectionProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of RefDemoSectionProps. +{ + _$$RefDemoSectionProps._(); + + factory _$$RefDemoSectionProps(Map backingMap) { + if (backingMap == null || backingMap is JsBackedMap) { + return _$$RefDemoSectionProps$JsMap(backingMap); + } else { + return _$$RefDemoSectionProps$PlainMap(backingMap); + } + } + + /// Let `UiProps` internals know that this class has been generated. + @override + bool get $isClassGenerated => true; + + /// The default namespace for the prop getters/setters generated for this class. + @override + String get propKeyNamespace => ''; +} + +// Concrete props implementation that can be backed by any [Map]. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$RefDemoSectionProps$PlainMap extends _$$RefDemoSectionProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$RefDemoSectionProps$PlainMap(Map backingMap) + : this._props = {}, + super._() { + this._props = backingMap ?? {}; + } + + /// The backing props map proxied by this class. + @override + Map get props => _props; + Map _props; +} + +// Concrete props implementation that can only be backed by [JsMap], +// allowing dart2js to compile more optimal code for key-value pair reads/writes. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$RefDemoSectionProps$JsMap extends _$$RefDemoSectionProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$RefDemoSectionProps$JsMap(JsBackedMap backingMap) + : this._props = JsBackedMap(), + super._() { + this._props = backingMap ?? JsBackedMap(); + } + + /// The backing props map proxied by this class. + @override + JsBackedMap get props => _props; + JsBackedMap _props; +} + +final FunctionComponentConfig<_$$RefDemoHocProps> $RefDemoHocConfig = + FunctionComponentConfig( + propsFactory: PropsFactory( + map: (map) => _$$RefDemoHocProps(map), + jsMap: (map) => _$$RefDemoHocProps$JsMap(map), + ), + displayName: 'RefDemoHoc'); + +// Concrete props implementation. +// +// Implements constructor and backing map, and links up to generated component factory. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +abstract class _$$RefDemoHocProps extends UiProps + with + RefDemoHocProps, + $RefDemoHocProps // If this generated mixin is undefined, it's likely because RefDemoHocProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of RefDemoHocProps. +{ + _$$RefDemoHocProps._(); + + factory _$$RefDemoHocProps(Map backingMap) { + if (backingMap == null || backingMap is JsBackedMap) { + return _$$RefDemoHocProps$JsMap(backingMap); + } else { + return _$$RefDemoHocProps$PlainMap(backingMap); + } + } + + /// Let `UiProps` internals know that this class has been generated. + @override + bool get $isClassGenerated => true; + + /// The default namespace for the prop getters/setters generated for this class. + @override + String get propKeyNamespace => ''; +} + +// Concrete props implementation that can be backed by any [Map]. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$RefDemoHocProps$PlainMap extends _$$RefDemoHocProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$RefDemoHocProps$PlainMap(Map backingMap) + : this._props = {}, + super._() { + this._props = backingMap ?? {}; + } + + /// The backing props map proxied by this class. + @override + Map get props => _props; + Map _props; +} + +// Concrete props implementation that can only be backed by [JsMap], +// allowing dart2js to compile more optimal code for key-value pair reads/writes. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$RefDemoHocProps$JsMap extends _$$RefDemoHocProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$RefDemoHocProps$JsMap(JsBackedMap backingMap) + : this._props = JsBackedMap(), + super._() { + this._props = backingMap ?? JsBackedMap(); + } + + /// The backing props map proxied by this class. + @override + JsBackedMap get props => _props; + JsBackedMap _props; +} From c5420330a3ec08455d3bcb7a16a36a5ab34cb4e8 Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Thu, 30 Jul 2020 12:02:17 -0700 Subject: [PATCH 03/28] Add extension method --- lib/src/component/ref_util.dart | 260 +++++++++++++++--- .../component_declaration/component_base.dart | 6 + web/component2/src/demos/forward_ref.dart | 76 +++-- .../src/demos/forward_ref.over_react.g.dart | 34 +-- 4 files changed, 292 insertions(+), 84 deletions(-) diff --git a/lib/src/component/ref_util.dart b/lib/src/component/ref_util.dart index 083b64e03..57bf3ccfc 100644 --- a/lib/src/component/ref_util.dart +++ b/lib/src/component/ref_util.dart @@ -80,7 +80,6 @@ Ref createRef() { /// // ---------- Component Consumption ---------- /// /// void main() { -/// setClientConfiguration(); /// final ref = createRef(); /// /// react_dom.render( @@ -137,7 +136,6 @@ Ref createRef() { /// Ref _forwardedRef; /// } /// -/// @Component2() /// class LogPropsComponent extends UiComponent2 { /// @override /// void componentDidUpdate(Map prevProps, _, [__]) { @@ -221,54 +219,233 @@ UiFactory Function(UiFactory) forwardRef /// > __NOTE:__ This should only be used to wrap components that extend from `Component2` /// > or components using the function syntax. /// -/// __Example__: +/// __Example 1:__ Forwarding refs to DOM components /// -/// mixin FooProps on UiProps { -/// Ref forwardedRef; -/// } +/// ```dart +/// import 'dart:html'; +/// import 'package:over_react/over_react.dart'; +/// import 'package:over_react/react_dom.dart' as react_dom; /// -/// final FunctionComponentSyntax = uiForwardRef((props, ref) { -/// return (Dom.button() -/// ..ref = ref -/// )('Click this button'); -/// }, -/// $FunctionSyntaxConfig, // ignore: undefined_identifier -/// ); +/// // ---------- Component Definition ---------- /// -/// ___ OR ___ +/// final FancyButton = uiForwardRef((props, ref) { +/// final classes = ClassNameBuilder.fromProps(props)..add('FancyButton'); /// -/// final DomComponentForwarded = uiForwardRef((props, ref) { -/// return (Dom.div() +/// return (Dom.button() +/// ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) +/// ..className = classes.toClassName() +/// ..ref = ref +/// )('Click me!'); +/// }, +/// Dom.button.asForwardRefConfig(displayName: 'FancyButton'), +/// ); +/// +/// // ---------- Component Consumption ---------- +/// +/// void main() { +/// final ref = createRef(); +/// +/// react_dom.render( +/// (FancyButton() /// ..ref = ref -/// ..className = 'special-class' -/// )( -/// props.children -/// ); -/// })(Dom.div); +/// ..onClick = (_) { +/// print(ref.current.outerHtml); +/// } +/// )(), +/// querySelector('#idOfSomeNodeInTheDom') +/// ); /// -/// ___ OR ___ +/// // You can still get a ref directly to the DOM button: +/// final buttonNode = ref.current; +/// } +/// ``` /// -/// final FooForwarded = uiForwardRef((props, ref) { -/// return (Foo() -/// ..forwardedRef = ref -/// )(); -/// })(Foo); +/// __Example 2:__ Forwarding refs in higher-order (non-function) components /// -/// UiFactory Foo = _$Foo; +/// ```dart +/// import 'dart:html'; +/// import 'package:over_react/over_react.dart'; +/// import 'package:over_react/react_dom.dart' as react_dom; /// -/// mixin FooProps on UiProps { -/// Ref forwardedRef; -/// } +/// // ---------- Component Definitions ---------- /// -/// @Component2() -/// class FooComponent extends UiComponent2 { -/// @override -/// render() { -/// return (Dom.button() -/// ..ref = props.forwardedRef -/// )('Click this button'); +/// final FancyButton = uiForwardRef((props, ref) { +/// final classes = ClassNameBuilder.fromProps(props)..add('FancyButton'); +/// +/// return (Dom.button() +/// ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) +/// ..className = classes.toClassName() +/// ..ref = ref +/// )('Click me!'); +/// }, +/// Dom.button.asForwardRefConfig(displayName: 'FancyButton'), +/// ); +/// +/// // ---------- Wrapping a Class Component ---------- +/// // Here you have two options: +/// // - Option 1: Use the class component's UI Factory to construct a function +/// // component config. This needs to be done because the builder recognizes +/// // `LogPropsProps` as already consumed (by the class component). +/// // +/// // - Option 2: Create a new props class. This just works around the issue +/// // described for Option 1 because it is creating a new props class, but it +/// // only needs to mixin in the props mixins that the original props class used. +/// // +/// // Choosing between the options is likely circumstantial or at least preferential +/// // if all else is the same. The advantage to Option 1 is that if the class component +/// // has numerous mixins, it is much more concise to create the function component +/// // config. Option 2 has the benefit that it matches the declaration of standard +/// // function components (which `uiForwardRef` returns). Additionally, Option 2 +/// // illustrates how one could add additional props to the wrapping function component. +/// +/// // Option 1 Example +/// final LogsPropsComponent = uiForwardRef((props, ref) { +/// return (_LogProps() +/// ..addProps(props) +/// .._forwardedRef = ref)(); +/// }, +/// _LogProps.asForwardRefConfig(displayName: 'LogsProps'), +/// ); +/// +/// // Option 2 Example: +/// +/// // This is not necessary but is just in place to illustrate that more props +/// // can be specified and consumed. +/// mixin AnotherPropsMixin on UiProps { +/// String anExampleAdditionalProp; +/// } +/// +/// class LogsPropsComponent2Props = UiProps with AnotherPropsMixin, LogPropsProps; +/// +/// final LogsPropsComponent2 = uiForwardRef((props, ref) { +/// useEffect(() { +/// print(props.anExampleAdditionalProp); +/// }); +/// +/// return (_LogProps() +/// ..addProps(props) +/// .._forwardedRef = ref)(); +/// }, +/// $LogsPropsComponent2Config +/// ); +/// +/// UiFactory _LogProps = _$_LogProps; +/// +/// mixin LogPropsProps on UiProps { +/// BuilderOnlyUiFactory builder; +/// +/// // Private since we only use this to pass along the value of `ref` to +/// // the return value of forwardRef. +/// // +/// // Consumers can set this private field value using the public `ref` setter. +/// Ref _forwardedRef; +/// } +/// +/// class LogPropsComponent extends UiComponent2 { +/// @override +/// void componentDidUpdate(Map prevProps, _, [__]) { +/// print('old props: $prevProps'); +/// print('new props: $props'); +/// } +/// +/// @override +/// render() { +/// return (props.builder() +/// ..modifyProps(addUnconsumedDomProps) +/// ..ref = props._forwardedRef +/// )(props.children); +/// } +/// } +/// +/// // ---------- Component Consumption ---------- +/// +/// void main() { +/// final ref = createRef(); +/// +/// react_dom.render( +/// (LogProps() +/// ..builder = FancyButton +/// ..className = 'btn btn-primary' +/// ..ref = ref +/// ..onClick = (_) { +/// print(ref.current.outerHtml); +/// } +/// )(), +/// querySelector('#idOfSomeNodeInTheDom') +/// ); +/// +/// // You can still get a ref directly to the DOM button: +/// final buttonNode = ref.current; +/// } +/// ``` +/// +/// __Example 3:__ Forwarding refs in higher-order (all function) components +/// +/// ```dart +/// import 'dart:html'; +/// import 'package:over_react/over_react.dart'; +/// import 'package:over_react/react_dom.dart' as react_dom; +/// import 'package:react/hooks.dart'; +/// +/// // ---------- Component Definitions ---------- +/// +/// final FancyButton = uiForwardRef((props, ref) { +/// final classes = ClassNameBuilder.fromProps(props)..add('FancyButton'); +/// +/// return (Dom.button() +/// ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) +/// ..className = classes.toClassName() +/// ..ref = ref +/// )('Click me!'); +/// }, +/// Dom.button.asForwardRefConfig(displayName: 'FancyButton'), +/// ); +/// +/// mixin LogPropsProps on UiProps { +/// BuilderOnlyUiFactory builder; +/// } +/// +/// final LogProps = uiForwardRef( +/// (props, ref) { +/// final prevPropsRef = useRef(null); +/// +/// useEffect(() { +/// if (prevPropsRef.current != null) { +/// print('old props: ${prevPropsRef.current}'); +/// print('new props: $props'); /// } -/// } +/// +/// prevPropsRef.current = props; +/// }); +/// +/// return ((props.builder() +/// ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) +/// ..ref = ref)(props.children)); +/// }, +/// $LogPropsConfig, // ignore: undefined_identifier +/// ); +/// +/// // ---------- Component Consumption ---------- +/// +/// void main() { +/// final ref = createRef(); +/// +/// react_dom.render( +/// (LogProps() +/// ..builder = FancyButton +/// ..className = 'btn btn-primary' +/// ..ref = ref +/// ..onClick = (_) { +/// print(ref.current.outerHtml); +/// } +/// )(), +/// querySelector('#idOfSomeNodeInTheDom') +/// ); +/// +/// // You can still get a ref directly to the DOM button: +/// final buttonNode = ref.current; +/// } +/// ``` /// /// Learn more: . UiFactory uiForwardRef( @@ -288,9 +465,8 @@ UiFactory uiForwardRef( ReactJsComponentFactoryProxy factory; - // It's not expected that `displayName` should ever be null, but if it is ever null and get's passed to `forwardRef` - // the name of the component becomes ' ' (an empty string). To protect against this ever happening, this check is in - // place so the name falls back to 'Anonymous'. + // If a consumer uses `asForwardRefConfig` to generate the function component + // config, displayName could be `null`. if (displayName != null) { factory = react_interop.forwardRef(_uiFunctionWrapper, displayName: displayName); } else { diff --git a/lib/src/component_declaration/component_base.dart b/lib/src/component_declaration/component_base.dart index f775d21bb..4c018ade6 100644 --- a/lib/src/component_declaration/component_base.dart +++ b/lib/src/component_declaration/component_base.dart @@ -20,6 +20,8 @@ import 'dart:collection'; import 'package:meta/meta.dart'; import 'package:over_react/src/component/dummy_component.dart'; import 'package:over_react/src/component/prop_mixins.dart'; +import 'package:over_react/src/component_declaration/builder_helpers.dart' as bh; +import 'package:over_react/src/component_declaration/function_component.dart'; import 'package:over_react/src/util/class_names.dart'; import 'package:over_react/src/util/map_util.dart'; import 'package:over_react/src/util/pretty_print.dart'; @@ -91,6 +93,10 @@ ReactDartComponentFactoryProxy registerAbstractComponent(Type abstractComponentC /// via a fluent-style builder interface. typedef TProps UiFactory([Map backingProps]); +extension UiFactoryHelpers on UiFactory { + FunctionComponentConfig asForwardRefConfig({String displayName}) => FunctionComponentConfig(propsFactory: PropsFactory.fromUiFactory(this), displayName: displayName); +} + /// A utility variation on [UiFactory], __without__ a `backingProps` parameter. /// /// I.e., a function that takes no parameters and returns a new [TProps] instance backed by a new, empty Map. diff --git a/web/component2/src/demos/forward_ref.dart b/web/component2/src/demos/forward_ref.dart index fb49a9dc4..a6b16ed73 100644 --- a/web/component2/src/demos/forward_ref.dart +++ b/web/component2/src/demos/forward_ref.dart @@ -1,6 +1,7 @@ import 'dart:html'; import 'package:over_react/over_react.dart'; +import 'package:react/hooks.dart'; // ignore: uri_has_not_been_generated part 'forward_ref.over_react.g.dart'; @@ -8,20 +9,23 @@ part 'forward_ref.over_react.g.dart'; // ------------ `uiForwardRef` with a function component (simple) ------------ mixin UiForwardRefLogsFunctionComponentProps on UiProps { BuilderOnlyUiFactory builder; - - // Private since we only use this to pass along the value of `ref` to - // the return value of forwardRef. - // - // Consumers can set this private field value using the public `ref` setter. - Ref _forwardedRef; } final UiForwardRefLogsFunctionComponent = uiForwardRef( (props, ref) { + final prevPropsRef = useRef(null); + + useEffect(() { + if (prevPropsRef.current != null) { + print(prevPropsRef.current); + print(props); + } + + prevPropsRef.current = props; + }); + return ((props.builder() - ..id = props.id - ..className = props.className - ..onClick = props.onClick + ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) ..ref = ref)(props.children)); }, $UiForwardRefLogsFunctionComponentConfig, // ignore: undefined_identifier @@ -40,12 +44,21 @@ class UiForwardRefLogsPropsComplexFunctionComponentProps = UiProps final UiForwardRefLogsPropsComplexFunctionComponent = uiForwardRef( (props, ref) { + final prevPropsRef = useRef(null); + + useEffect(() { + if (prevPropsRef.current != null) { + print(prevPropsRef.current); + print(props); + } + + prevPropsRef.current = props; + }); + return (Fragment()( Dom.div()(props.buttonDescription), (props.builder() - ..id = props.id - ..className = props.className - ..onClick = props.onClick + ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) ..ref = ref)(props.children), )); }, @@ -55,12 +68,11 @@ final UiForwardRefLogsPropsComplexFunctionComponent = // ------------ `uiForwardRef` with a class component (simple) ------------ final UiForwardRefLogsPropsComponent = uiForwardRef( (props, ref) { - return (_LogsPropsFunctionComponent() + return (_LogProps() ..addProps(props) .._forwardedRef = ref)(); }, - FunctionComponentConfig( - propsFactory: PropsFactory.fromUiFactory(_LogsPropsFunctionComponent), displayName: null), + _LogProps.asForwardRefConfig(displayName: 'UiForwardRefLogsProps'), ); // ------------ `uiForwardRef` with a class component (complex) ------------ @@ -76,7 +88,7 @@ final UiForwardRefLogsPropsComplexComponent = (props, ref) { return Fragment()( Dom.div()(props.buttonDescription), - (_LogsPropsFunctionComponent() + (_LogProps() ..addProps(props) .._forwardedRef = ref)(), ); @@ -96,6 +108,9 @@ UiFactory _LogProps = _$_LogProps; mixin LogPropsProps on UiProps { BuilderOnlyUiFactory builder; + // A simple prop to change in order to trigger the print. + bool thisWasClickedLast; + // Private since we only use this to pass along the value of `ref` to // the return value of forwardRef. // @@ -112,9 +127,11 @@ class LogPropsComponent extends UiComponent2 { @override render() { - return (props.builder() - ..modifyProps(addUnconsumedDomProps) - ..ref = props._forwardedRef)(props.children); + return Dom.div()( + Dom.p()('This was the last button clicked: ${props.thisWasClickedLast}'), + (props.builder() + ..modifyProps(addUnconsumedDomProps) + ..ref = props._forwardedRef)(props.children)); } } @@ -129,10 +146,19 @@ class _LogsPropsFunctionComponentProps = UiProps with LogPropsProps; final _LogsPropsFunctionComponent = uiFunction<_LogsPropsFunctionComponentProps>( (props) { + final prevPropsRef = useRef<_LogsPropsFunctionComponentProps>(null); + + useEffect(() { + if (prevPropsRef.current != null) { + print(prevPropsRef.current); + print(props); + } + + prevPropsRef.current = props; + }); + return ((props.builder() - ..id = props.id - ..className = props.className - ..onClick = props.onClick + ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) ..ref = props._forwardedRef)(props.children)); }, $_LogsPropsFunctionComponentConfig, // ignore: undefined_identifier @@ -148,7 +174,7 @@ final FancyButton = uiForwardRef( ..className = classes.toClassName() ..ref = ref)('Click me!'); }, - FunctionComponentConfig(propsFactory: PropsFactory.fromUiFactory(Dom.button), displayName: null), + Dom.button.asForwardRefConfig(displayName: 'FancyButton'), ); mixin RefDemoProps on UiProps {} @@ -165,6 +191,8 @@ final RefDemoContainer = uiFunction( final fancyButtonNodeRef = createRef(); final fancyFunctionalButtonNodeRef = createRef(); + final lastClickedRef = useState(null); + return ((Dom.div()..style = {'padding': 10})( (RefDemoSection()..sectionTitle = 'uiForwardRef Demos')( (RefDemoHoc()..demoTitle = '`uiForwardRef` with a function component (simple)')( @@ -219,6 +247,7 @@ final RefDemoContainer = uiFunction( ..ref = fancyButtonNodeRef ..onClick = (_) { print(fancyButtonNodeRef.current.outerHtml); + lastClickedRef.set(fancyButtonNodeRef); })(), ), (RefDemoHoc()..demoTitle = '`uiForwardRef` with function component')( @@ -229,6 +258,7 @@ final RefDemoContainer = uiFunction( ..ref = fancyFunctionalButtonNodeRef ..onClick = (_) { print(fancyFunctionalButtonNodeRef.current.outerHtml); + lastClickedRef.set(fancyFunctionalButtonNodeRef); })(), ), ), diff --git a/web/component2/src/demos/forward_ref.over_react.g.dart b/web/component2/src/demos/forward_ref.over_react.g.dart index 3abfce35a..b6ee921af 100644 --- a/web/component2/src/demos/forward_ref.over_react.g.dart +++ b/web/component2/src/demos/forward_ref.over_react.g.dart @@ -159,35 +159,18 @@ mixin $UiForwardRefLogsFunctionComponentProps @override set builder(BuilderOnlyUiFactory value) => props[_$key__builder__UiForwardRefLogsFunctionComponentProps] = value; - @override - Ref get _forwardedRef => - props[_$key___forwardedRef__UiForwardRefLogsFunctionComponentProps] ?? - null; // Add ` ?? null` to workaround DDC bug: ; - @override - set _forwardedRef(Ref value) => - props[_$key___forwardedRef__UiForwardRefLogsFunctionComponentProps] = - value; /* GENERATED CONSTANTS */ static const PropDescriptor _$prop__builder__UiForwardRefLogsFunctionComponentProps = PropDescriptor(_$key__builder__UiForwardRefLogsFunctionComponentProps); - static const PropDescriptor - _$prop___forwardedRef__UiForwardRefLogsFunctionComponentProps = - PropDescriptor( - _$key___forwardedRef__UiForwardRefLogsFunctionComponentProps); static const String _$key__builder__UiForwardRefLogsFunctionComponentProps = 'UiForwardRefLogsFunctionComponentProps.builder'; - static const String - _$key___forwardedRef__UiForwardRefLogsFunctionComponentProps = - 'UiForwardRefLogsFunctionComponentProps._forwardedRef'; static const List $props = [ - _$prop__builder__UiForwardRefLogsFunctionComponentProps, - _$prop___forwardedRef__UiForwardRefLogsFunctionComponentProps + _$prop__builder__UiForwardRefLogsFunctionComponentProps ]; static const List $propKeys = [ - _$key__builder__UiForwardRefLogsFunctionComponentProps, - _$key___forwardedRef__UiForwardRefLogsFunctionComponentProps + _$key__builder__UiForwardRefLogsFunctionComponentProps ]; } @@ -297,6 +280,13 @@ mixin $LogPropsProps on LogPropsProps { set builder(BuilderOnlyUiFactory value) => props[_$key__builder__LogPropsProps] = value; @override + bool get thisWasClickedLast => + props[_$key__thisWasClickedLast__LogPropsProps] ?? + null; // Add ` ?? null` to workaround DDC bug: ; + @override + set thisWasClickedLast(bool value) => + props[_$key__thisWasClickedLast__LogPropsProps] = value; + @override Ref get _forwardedRef => props[_$key___forwardedRef__LogPropsProps] ?? null; // Add ` ?? null` to workaround DDC bug: ; @@ -306,18 +296,24 @@ mixin $LogPropsProps on LogPropsProps { /* GENERATED CONSTANTS */ static const PropDescriptor _$prop__builder__LogPropsProps = PropDescriptor(_$key__builder__LogPropsProps); + static const PropDescriptor _$prop__thisWasClickedLast__LogPropsProps = + PropDescriptor(_$key__thisWasClickedLast__LogPropsProps); static const PropDescriptor _$prop___forwardedRef__LogPropsProps = PropDescriptor(_$key___forwardedRef__LogPropsProps); static const String _$key__builder__LogPropsProps = 'LogPropsProps.builder'; + static const String _$key__thisWasClickedLast__LogPropsProps = + 'LogPropsProps.thisWasClickedLast'; static const String _$key___forwardedRef__LogPropsProps = 'LogPropsProps._forwardedRef'; static const List $props = [ _$prop__builder__LogPropsProps, + _$prop__thisWasClickedLast__LogPropsProps, _$prop___forwardedRef__LogPropsProps ]; static const List $propKeys = [ _$key__builder__LogPropsProps, + _$key__thisWasClickedLast__LogPropsProps, _$key___forwardedRef__LogPropsProps ]; } From 841d102292a3dd7cdfeb9a6f1de6750b272b3acc Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Mon, 3 Aug 2020 10:05:39 -0700 Subject: [PATCH 04/28] Add tests --- lib/src/component/ref_util.dart | 2 +- test/over_react/component/ref_test.dart | 331 +++++++++++++++++ .../component/ref_test.over_react.g.dart | 343 ++++++++++++++++++ test/over_react_component_test.dart | 7 +- 4 files changed, 677 insertions(+), 6 deletions(-) create mode 100644 test/over_react/component/ref_test.dart create mode 100644 test/over_react/component/ref_test.over_react.g.dart diff --git a/lib/src/component/ref_util.dart b/lib/src/component/ref_util.dart index 57bf3ccfc..bbd055461 100644 --- a/lib/src/component/ref_util.dart +++ b/lib/src/component/ref_util.dart @@ -467,7 +467,7 @@ UiFactory uiForwardRef( // If a consumer uses `asForwardRefConfig` to generate the function component // config, displayName could be `null`. - if (displayName != null) { + if (displayName != null && displayName.trim().isNotEmpty) { factory = react_interop.forwardRef(_uiFunctionWrapper, displayName: displayName); } else { factory = react_interop.forwardRef(_uiFunctionWrapper); diff --git a/test/over_react/component/ref_test.dart b/test/over_react/component/ref_test.dart new file mode 100644 index 000000000..4841d1792 --- /dev/null +++ b/test/over_react/component/ref_test.dart @@ -0,0 +1,331 @@ +// Copyright 2020 Workiva Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +library forward_ref_test; + +import 'dart:html'; +import 'dart:js_util'; + +import 'package:meta/meta.dart'; +import 'package:test/test.dart'; +import 'package:over_react/over_react.dart'; +import 'package:over_react/src/component/dom_components.dart'; + +import '../../test_util/test_util.dart'; +import '../component/fixtures/basic_child_component.dart'; +import 'fixtures/basic_ui_component.dart'; + +part 'ref_test.over_react.g.dart'; // ignore: uri_has_not_been_generated + +main() { + group('forward ref -', () { + test('errors when wrapping a UiComponent', () { + expect(() => forwardRef((props, ref) { + return (BasicUiComponent() + ..ref = ref + )(); + })(BasicUiComponent), throwsArgumentError); + }); + + commonRefForwardingTests(); + }); + + group('uiForwardRef -', () { + group('fundamentally behaves the same as `forwardRef', () { + commonRefForwardingTests(useUiForwardRef: true); + }); + + group('on a function component child', () { + standardForwardRefTest(BasicChild, verifyRefValue: (ref) { + expect(ref, TypeMatcher()); + }, useUiForwardRef: true); + + group('using the factory\'s `asForwardRefConfig` syntax', () { + test('- sets displayName on the rendered component as expected', () { + final BasicForwarded = uiForwardRef((props, ref) { + return (BasicUiFunction()..ref = ref)(); + }, BasicUiFunction.asForwardRefConfig()); + + final Ref refObject = createRef(); + final vDomElement = (BasicForwarded()..ref = refObject)(); + + expect(getProperty(getProperty(vDomElement.type, 'render'), 'displayName'), 'Anonymous'); + }); + + test('when displayName argument is passed to the config constructor', () { + final BasicForwarded = uiForwardRef((props, ref) { + return (BasicUiFunction()..ref = ref)(); + }, BasicUiFunction.asForwardRefConfig(displayName: displayName)); + + final Ref refObject = createRef(); + final vDomElement = (BasicForwarded()..ref = refObject)(); + + expect(getProperty(getProperty(vDomElement.type, 'render'), 'displayName'), displayName); + }); + + group('returns normally when passed children', () { + test('that are in a List literal', () { + final BasicForwarded = uiForwardRef((props, ref) { + return (BasicUiFunction()..ref = ref)(); + }, BasicUiFunction.asForwardRefConfig()); + + expect(() => mount(BasicForwarded()(['test'])), returnsNormally); + }); + + test('that are not in a List literal', () { + final BasicForwarded = uiForwardRef((props, ref) { + return (BasicUiFunction()..ref = ref)(); + }, BasicUiFunction.asForwardRefConfig()); + + expect(() => mount(BasicForwarded()('test')), returnsNormally); + }); + }); + }); + }); + + group('using a generated factory', () { + test('- sets displayName on the rendered component as expected', () { + final Ref refObject = createRef(); + final vDomElement = (TopLevelForwardUiRefFunction()..ref = refObject)(); + + expect(getProperty(getProperty(vDomElement.type, 'render'), 'displayName'), 'TopLevelForwardUiRefFunction'); + }); + + group('returns normally when passed children', () { + test('that are in a List literal', () { + expect(() => mount(TopLevelForwardUiRefFunction()(['test'])), returnsNormally); + }); + + test('that are not in a List literal', () { + expect(() => mount(TopLevelForwardUiRefFunction()('test')), returnsNormally); + }); + }); + }); + + test('throws an argument error if the config is null', () { + expect(() { + uiForwardRef((_, __) => Dom.div()('Example'), null); + }, throwsArgumentError); + }); + }); +} + +@isTestGroup +void commonRefForwardingTests({bool useUiForwardRef = false}) { + UiFactory getFactoryForBasic({ + String displayName, + }) { + if (useUiForwardRef) { + if (displayName == null) { + return uiForwardRef((props, ref) { + return (Basic()..ref = ref)(props.children); + }, Basic.asForwardRefConfig()); + } else { + return uiForwardRef((props, ref) { + return (Basic()..ref = ref)(props.children); + }, Basic.asForwardRefConfig(displayName: displayName)); + } + } else { + if (displayName == null) { + return forwardRef((props, ref) { + return (Basic()..ref = ref)(props.children); + })(Basic); + } else { + return forwardRef((props, ref) { + return (Basic()..ref = ref)(props.children); + }, displayName: displayName)(Basic); + } + } + } + + UiFactory getFactoryForDiv({ + String displayName, + }) { + ReactElement div(Ref ref, dynamic children) => (Dom.div() + ..ref = ref + )(children); + + if (useUiForwardRef) { + if (displayName == null) { + return uiForwardRef((props, ref) { + return div(ref, props.children); + }, Dom.div.asForwardRefConfig()); + } else { + return uiForwardRef((props, ref) { + return div(ref, props.children); + }, Dom.div.asForwardRefConfig(displayName: displayName)); + } + } else { + if (displayName == null) { + return forwardRef((props, ref) { + return div(ref, props.children); + })(Dom.div); + } else { + return forwardRef((props, ref) { + return div(ref, props.children); + }, displayName: displayName)(Dom.div); + } + } + } + + group('- commonRefForwardingTests -', () { + group('on a component with a dom component child', () { + standardForwardRefTest(Dom.span, verifyRefValue: (ref) { + expect(ref, TypeMatcher()); + }, useUiForwardRef: useUiForwardRef); + + test('- using DomProps', () { + UiFactory DivForwarded = getFactoryForDiv(); + + final Ref refObject = createRef(); + + mount((DivForwarded() + ..ref = refObject + )()); + + expect(refObject.current, TypeMatcher()); + }); + + group('- sets displayName on the rendered component as expected', () { + test('when displayName argument is not passed to forwardRef', () { + UiFactory DivForwarded = getFactoryForDiv(); + + final refObject = createRef(); + final vDomElement = (DivForwarded()..ref = refObject)(); + + expect(getProperty(getProperty(vDomElement.type, 'render'), 'displayName'), useUiForwardRef ? 'Anonymous' : 'div'); + }); + + test('when displayName argument is passed to the config constructor', () { + UiFactory DivForwarded = getFactoryForDiv(displayName: displayName); + + final refObject = createRef(); + final vDomElement = (DivForwarded()..ref = refObject)(); + + expect(getProperty(getProperty(vDomElement.type, 'render'), 'displayName'), displayName); + }); + }); + + group('returns normally when passed children', () { + test('that are in a List literal', () { + expect(() => mount(getFactoryForDiv()()(['test'])), returnsNormally); + }); + + test('that are not in a List literal', () { + expect(() => mount(getFactoryForDiv()()('test')), returnsNormally); + }); + }); + }); + + group('on a component with a dart component child', () { + standardForwardRefTest(Basic, verifyRefValue: (ref) { + expect(ref, TypeMatcher()); + }, useUiForwardRef: useUiForwardRef); + + group('- sets displayName on the rendered component as expected', () { + test('when displayName argument is not passed to forwardRef', () { + final BasicForwarded = getFactoryForBasic(); + + final Ref refObject = createRef(); + final vDomElement = (BasicForwarded()..ref = refObject)(); + + expect(getProperty(getProperty(vDomElement.type, 'render'), 'displayName'), useUiForwardRef ? 'Anonymous' : 'Basic'); + }); + + test('when displayName argument is passed to the config constructor', () { + final BasicForwarded = getFactoryForBasic(displayName: displayName); + + final Ref refObject = createRef(); + final vDomElement = (BasicForwarded()..ref = refObject)(); + + expect(getProperty(getProperty(vDomElement.type, 'render'), 'displayName'), displayName); + }); + }); + + group('returns normally when passed children', () { + test('that are in a List literal', () { + expect(() => mount(getFactoryForBasic()()(['test'])), returnsNormally); + }); + + test('that are not in a List literal', () { + expect(() => mount(getFactoryForBasic()()('test')), returnsNormally); + }); + }); + }); + }); +} + +const displayName = 'AVerySpecificDisplayName'; + +void standardForwardRefTest(dynamic factory, {void Function(dynamic refValue) verifyRefValue, useUiForwardRef = false}) { + test('- passes a ref through the parent to its child', () { + UiFactory BasicForwarded = useUiForwardRef ? uiForwardRef((props, ref) { + return (factory() + ..ref = ref + ..id = props.childId + )(); + }, Basic.asForwardRefConfig()) : forwardRef((props, ref) { + return (factory() + ..ref = ref + ..id = props.childId + )(); + })(Basic); + + final Ref refObject = createRef(); + + mount((BasicForwarded() + ..ref = refObject + ..childId = 'test' + )()); + + // component props are accessed differently depending on if it is a dom component + // or a dart component + String idValue; + if (refObject.current is Element) { + idValue = refObject.current.id; + } else { + idValue = refObject.current.props['id']; + } + + expect(idValue, equals('test'), reason: 'child component should have access to parent props'); + verifyRefValue(refObject.current); + }); +} + +UiFactory Basic = _$Basic; // ignore: undefined_identifier + +mixin BasicProps on UiProps { + String childId; +} + +class BasicComponent extends UiComponent2 { + @override + render() => props.children.isEmpty ? 'basic component' : props.children; +} + +mixin BasicUiFunctionProps on UiProps {} + +class SecondaryBasicUiFunctionProps = UiProps with BasicUiFunctionProps; + +final BasicUiFunction = uiFunction((props) { + return props.children.isEmpty ? 'basic component' : props.children; + }, + $BasicUiFunctionConfig, // ignore: undefined_identifier +); + +final TopLevelForwardUiRefFunction = uiForwardRef((props, ref) { + return (BasicUiFunction()..ref = ref)(props.children); +}, + $TopLevelForwardUiRefFunctionConfig, // ignore: undefined_identifier +); \ No newline at end of file diff --git a/test/over_react/component/ref_test.over_react.g.dart b/test/over_react/component/ref_test.over_react.g.dart new file mode 100644 index 000000000..85bd54ee2 --- /dev/null +++ b/test/over_react/component/ref_test.over_react.g.dart @@ -0,0 +1,343 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +// ignore_for_file: deprecated_member_use_from_same_package, unnecessary_null_in_if_null_operators, prefer_null_aware_operators +part of 'ref_test.dart'; + +// ************************************************************************** +// OverReactBuilder (package:over_react/src/builder.dart) +// ************************************************************************** + +// React component factory implementation. +// +// Registers component implementation and links type meta to builder factory. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +final $BasicComponentFactory = registerComponent2( + () => _$BasicComponent(), + builderFactory: _$Basic, + componentClass: BasicComponent, + isWrapper: false, + parentType: null, + displayName: 'Basic', +); + +_$$BasicProps _$Basic([Map backingProps]) => backingProps == null + ? _$$BasicProps$JsMap(JsBackedMap()) + : _$$BasicProps(backingProps); + +// Concrete props implementation. +// +// Implements constructor and backing map, and links up to generated component factory. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +abstract class _$$BasicProps extends UiProps + with + BasicProps, + $BasicProps // If this generated mixin is undefined, it's likely because BasicProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of BasicProps. +{ + _$$BasicProps._(); + + factory _$$BasicProps(Map backingMap) { + if (backingMap == null || backingMap is JsBackedMap) { + return _$$BasicProps$JsMap(backingMap); + } else { + return _$$BasicProps$PlainMap(backingMap); + } + } + + /// Let `UiProps` internals know that this class has been generated. + @override + bool get $isClassGenerated => true; + + /// The `ReactComponentFactory` associated with the component built by this class. + @override + ReactComponentFactoryProxy get componentFactory => + super.componentFactory ?? $BasicComponentFactory; + + /// The default namespace for the prop getters/setters generated for this class. + @override + String get propKeyNamespace => ''; +} + +// Concrete props implementation that can be backed by any [Map]. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$BasicProps$PlainMap extends _$$BasicProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$BasicProps$PlainMap(Map backingMap) + : this._props = {}, + super._() { + this._props = backingMap ?? {}; + } + + /// The backing props map proxied by this class. + @override + Map get props => _props; + Map _props; +} + +// Concrete props implementation that can only be backed by [JsMap], +// allowing dart2js to compile more optimal code for key-value pair reads/writes. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$BasicProps$JsMap extends _$$BasicProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$BasicProps$JsMap(JsBackedMap backingMap) + : this._props = JsBackedMap(), + super._() { + this._props = backingMap ?? JsBackedMap(); + } + + /// The backing props map proxied by this class. + @override + JsBackedMap get props => _props; + JsBackedMap _props; +} + +// Concrete component implementation mixin. +// +// Implements typed props/state factories, defaults `consumedPropKeys` to the keys +// generated for the associated props class. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$BasicComponent extends BasicComponent { + _$$BasicProps$JsMap _cachedTypedProps; + + @override + _$$BasicProps$JsMap get props => _cachedTypedProps; + + @override + set props(Map value) { + assert( + getBackingMap(value) is JsBackedMap, + 'Component2.props should never be set directly in ' + 'production. If this is required for testing, the ' + 'component should be rendered within the test. If ' + 'that does not have the necessary result, the last ' + 'resort is to use typedPropsFactoryJs.'); + super.props = value; + _cachedTypedProps = typedPropsFactoryJs(getBackingMap(value)); + } + + @override + _$$BasicProps$JsMap typedPropsFactoryJs(JsBackedMap backingMap) => + _$$BasicProps$JsMap(backingMap); + + @override + _$$BasicProps typedPropsFactory(Map backingMap) => _$$BasicProps(backingMap); + + /// Let `UiComponent` internals know that this class has been generated. + @override + bool get $isClassGenerated => true; + + /// The default consumed props, comprising all props mixins used by BasicProps. + /// Used in `*ConsumedProps` methods if [consumedProps] is not overridden. + @override + get $defaultConsumedProps => propsMeta.all; + + @override + PropsMetaCollection get propsMeta => const PropsMetaCollection({ + // If this generated mixin is undefined, it's likely because BasicProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of BasicProps. + BasicProps: $BasicProps.meta, + }); +} + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.' + ' EXCEPTION: this may be used in legacy boilerplate until' + ' it is transitioned to the new mixin-based boilerplate.') +mixin $BasicProps on BasicProps { + static const PropsMeta meta = _$metaForBasicProps; + @override + String get childId => + props[_$key__childId__BasicProps] ?? + null; // Add ` ?? null` to workaround DDC bug: ; + @override + set childId(String value) => props[_$key__childId__BasicProps] = value; + /* GENERATED CONSTANTS */ + static const PropDescriptor _$prop__childId__BasicProps = + PropDescriptor(_$key__childId__BasicProps); + static const String _$key__childId__BasicProps = 'BasicProps.childId'; + + static const List $props = [_$prop__childId__BasicProps]; + static const List $propKeys = [_$key__childId__BasicProps]; +} + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +const PropsMeta _$metaForBasicProps = PropsMeta( + fields: $BasicProps.$props, + keys: $BasicProps.$propKeys, +); + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.' + ' EXCEPTION: this may be used in legacy boilerplate until' + ' it is transitioned to the new mixin-based boilerplate.') +mixin $BasicUiFunctionProps on BasicUiFunctionProps { + static const PropsMeta meta = _$metaForBasicUiFunctionProps; + /* GENERATED CONSTANTS */ + + static const List $props = []; + static const List $propKeys = []; +} + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +const PropsMeta _$metaForBasicUiFunctionProps = PropsMeta( + fields: $BasicUiFunctionProps.$props, + keys: $BasicUiFunctionProps.$propKeys, +); + +final FunctionComponentConfig<_$$BasicUiFunctionProps> $BasicUiFunctionConfig = + FunctionComponentConfig( + propsFactory: PropsFactory( + map: (map) => _$$BasicUiFunctionProps(map), + jsMap: (map) => _$$BasicUiFunctionProps$JsMap(map), + ), + displayName: 'BasicUiFunction'); + +// Concrete props implementation. +// +// Implements constructor and backing map, and links up to generated component factory. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +abstract class _$$BasicUiFunctionProps extends UiProps + with + BasicUiFunctionProps, + $BasicUiFunctionProps // If this generated mixin is undefined, it's likely because BasicUiFunctionProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of BasicUiFunctionProps. +{ + _$$BasicUiFunctionProps._(); + + factory _$$BasicUiFunctionProps(Map backingMap) { + if (backingMap == null || backingMap is JsBackedMap) { + return _$$BasicUiFunctionProps$JsMap(backingMap); + } else { + return _$$BasicUiFunctionProps$PlainMap(backingMap); + } + } + + /// Let `UiProps` internals know that this class has been generated. + @override + bool get $isClassGenerated => true; + + /// The default namespace for the prop getters/setters generated for this class. + @override + String get propKeyNamespace => ''; +} + +// Concrete props implementation that can be backed by any [Map]. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$BasicUiFunctionProps$PlainMap extends _$$BasicUiFunctionProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$BasicUiFunctionProps$PlainMap(Map backingMap) + : this._props = {}, + super._() { + this._props = backingMap ?? {}; + } + + /// The backing props map proxied by this class. + @override + Map get props => _props; + Map _props; +} + +// Concrete props implementation that can only be backed by [JsMap], +// allowing dart2js to compile more optimal code for key-value pair reads/writes. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$BasicUiFunctionProps$JsMap extends _$$BasicUiFunctionProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$BasicUiFunctionProps$JsMap(JsBackedMap backingMap) + : this._props = JsBackedMap(), + super._() { + this._props = backingMap ?? JsBackedMap(); + } + + /// The backing props map proxied by this class. + @override + JsBackedMap get props => _props; + JsBackedMap _props; +} + +final FunctionComponentConfig<_$$SecondaryBasicUiFunctionProps> + $TopLevelForwardUiRefFunctionConfig = FunctionComponentConfig( + propsFactory: PropsFactory( + map: (map) => _$$SecondaryBasicUiFunctionProps(map), + jsMap: (map) => _$$SecondaryBasicUiFunctionProps$JsMap(map), + ), + displayName: 'TopLevelForwardUiRefFunction'); + +// Concrete props implementation. +// +// Implements constructor and backing map, and links up to generated component factory. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +abstract class _$$SecondaryBasicUiFunctionProps extends UiProps + with + BasicUiFunctionProps, + $BasicUiFunctionProps // If this generated mixin is undefined, it's likely because BasicUiFunctionProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of BasicUiFunctionProps. + implements + SecondaryBasicUiFunctionProps { + _$$SecondaryBasicUiFunctionProps._(); + + factory _$$SecondaryBasicUiFunctionProps(Map backingMap) { + if (backingMap == null || backingMap is JsBackedMap) { + return _$$SecondaryBasicUiFunctionProps$JsMap(backingMap); + } else { + return _$$SecondaryBasicUiFunctionProps$PlainMap(backingMap); + } + } + + /// Let `UiProps` internals know that this class has been generated. + @override + bool get $isClassGenerated => true; + + /// The default namespace for the prop getters/setters generated for this class. + @override + String get propKeyNamespace => ''; +} + +// Concrete props implementation that can be backed by any [Map]. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$SecondaryBasicUiFunctionProps$PlainMap + extends _$$SecondaryBasicUiFunctionProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$SecondaryBasicUiFunctionProps$PlainMap(Map backingMap) + : this._props = {}, + super._() { + this._props = backingMap ?? {}; + } + + /// The backing props map proxied by this class. + @override + Map get props => _props; + Map _props; +} + +// Concrete props implementation that can only be backed by [JsMap], +// allowing dart2js to compile more optimal code for key-value pair reads/writes. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$SecondaryBasicUiFunctionProps$JsMap + extends _$$SecondaryBasicUiFunctionProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$SecondaryBasicUiFunctionProps$JsMap(JsBackedMap backingMap) + : this._props = JsBackedMap(), + super._() { + this._props = backingMap ?? JsBackedMap(); + } + + /// The backing props map proxied by this class. + @override + JsBackedMap get props => _props; + JsBackedMap _props; +} diff --git a/test/over_react_component_test.dart b/test/over_react_component_test.dart index d13cb8078..ee940a875 100644 --- a/test/over_react_component_test.dart +++ b/test/over_react_component_test.dart @@ -20,7 +20,6 @@ library over_react_component_test; import 'package:over_react/over_react.dart'; -import 'package:react/react_client.dart'; import 'package:test/test.dart'; import 'over_react/component/_deprecated/abstract_transition_test.dart' as deprecated_abstract_transition_test; @@ -29,7 +28,7 @@ import 'over_react/component/dom_components_test.dart' as dom_components_test; import 'over_react/component/error_boundary_test.dart' as error_boundary_test; import 'over_react/component/_deprecated/error_boundary_mixin_test.dart' as deprecated_error_boundary_mixin_test; import 'over_react/component/_deprecated/error_boundary_test.dart' as deprecated_error_boundary_test; -import 'over_react/component/forward_ref_test.dart' as forward_ref_test; +import 'over_react/component/ref_test.dart' as ref_test; import 'over_react/component/prop_mixins_test.dart' as prop_mixins_test; import 'over_react/component/prop_typedefs_test.dart' as prop_typedefs_test; import 'over_react/component/pure_component_mixin_test.dart' as pure_component_mixin_test; @@ -41,8 +40,6 @@ import 'over_react/component/context_test.dart' as context_test; import 'over_react/component/typed_factory_test.dart' as typed_factory_test; void main() { - setClientConfiguration(); - enableTestMode(); pure_component_mixin_test.main(); @@ -51,7 +48,7 @@ void main() { error_boundary_test.main(); deprecated_error_boundary_mixin_test.main(); deprecated_error_boundary_test.main(); - forward_ref_test.main(); + ref_test.main(); dom_components_test.main(); prop_mixins_test.main(); prop_typedefs_test.main(); From 117cadb5bf276f05fa27e3f31f48ef812ba87910 Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Mon, 3 Aug 2020 11:24:16 -0700 Subject: [PATCH 05/28] Format tests --- test/over_react/component/ref_test.dart | 73 +++++++++++++------------ 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/test/over_react/component/ref_test.dart b/test/over_react/component/ref_test.dart index 4841d1792..b0ddbae1d 100644 --- a/test/over_react/component/ref_test.dart +++ b/test/over_react/component/ref_test.dart @@ -31,11 +31,11 @@ part 'ref_test.over_react.g.dart'; // ignore: uri_has_not_been_generated main() { group('forward ref -', () { test('errors when wrapping a UiComponent', () { - expect(() => forwardRef((props, ref) { - return (BasicUiComponent() - ..ref = ref - )(); - })(BasicUiComponent), throwsArgumentError); + expect( + () => forwardRef((props, ref) { + return (BasicUiComponent()..ref = ref)(); + })(BasicUiComponent), + throwsArgumentError); }); commonRefForwardingTests(); @@ -99,7 +99,8 @@ main() { final Ref refObject = createRef(); final vDomElement = (TopLevelForwardUiRefFunction()..ref = refObject)(); - expect(getProperty(getProperty(vDomElement.type, 'render'), 'displayName'), 'TopLevelForwardUiRefFunction'); + expect(getProperty(getProperty(vDomElement.type, 'render'), 'displayName'), + 'TopLevelForwardUiRefFunction'); }); group('returns normally when passed children', () { @@ -152,9 +153,7 @@ void commonRefForwardingTests({bool useUiForwardRef = false}) { UiFactory getFactoryForDiv({ String displayName, }) { - ReactElement div(Ref ref, dynamic children) => (Dom.div() - ..ref = ref - )(children); + ReactElement div(Ref ref, dynamic children) => (Dom.div()..ref = ref)(children); if (useUiForwardRef) { if (displayName == null) { @@ -190,9 +189,7 @@ void commonRefForwardingTests({bool useUiForwardRef = false}) { final Ref refObject = createRef(); - mount((DivForwarded() - ..ref = refObject - )()); + mount((DivForwarded()..ref = refObject)()); expect(refObject.current, TypeMatcher()); }); @@ -204,7 +201,8 @@ void commonRefForwardingTests({bool useUiForwardRef = false}) { final refObject = createRef(); final vDomElement = (DivForwarded()..ref = refObject)(); - expect(getProperty(getProperty(vDomElement.type, 'render'), 'displayName'), useUiForwardRef ? 'Anonymous' : 'div'); + expect(getProperty(getProperty(vDomElement.type, 'render'), 'displayName'), + useUiForwardRef ? 'Anonymous' : 'div'); }); test('when displayName argument is passed to the config constructor', () { @@ -240,7 +238,8 @@ void commonRefForwardingTests({bool useUiForwardRef = false}) { final Ref refObject = createRef(); final vDomElement = (BasicForwarded()..ref = refObject)(); - expect(getProperty(getProperty(vDomElement.type, 'render'), 'displayName'), useUiForwardRef ? 'Anonymous' : 'Basic'); + expect(getProperty(getProperty(vDomElement.type, 'render'), 'displayName'), + useUiForwardRef ? 'Anonymous' : 'Basic'); }); test('when displayName argument is passed to the config constructor', () { @@ -268,26 +267,26 @@ void commonRefForwardingTests({bool useUiForwardRef = false}) { const displayName = 'AVerySpecificDisplayName'; -void standardForwardRefTest(dynamic factory, {void Function(dynamic refValue) verifyRefValue, useUiForwardRef = false}) { +void standardForwardRefTest(dynamic factory, + {void Function(dynamic refValue) verifyRefValue, useUiForwardRef = false}) { test('- passes a ref through the parent to its child', () { - UiFactory BasicForwarded = useUiForwardRef ? uiForwardRef((props, ref) { - return (factory() - ..ref = ref - ..id = props.childId - )(); - }, Basic.asForwardRefConfig()) : forwardRef((props, ref) { - return (factory() - ..ref = ref - ..id = props.childId - )(); - })(Basic); + UiFactory BasicForwarded = useUiForwardRef + ? uiForwardRef((props, ref) { + return (factory() + ..ref = ref + ..id = props.childId)(); + }, Basic.asForwardRefConfig()) + : forwardRef((props, ref) { + return (factory() + ..ref = ref + ..id = props.childId)(); + })(Basic); final Ref refObject = createRef(); mount((BasicForwarded() ..ref = refObject - ..childId = 'test' - )()); + ..childId = 'test')()); // component props are accessed differently depending on if it is a dom component // or a dart component @@ -318,14 +317,16 @@ mixin BasicUiFunctionProps on UiProps {} class SecondaryBasicUiFunctionProps = UiProps with BasicUiFunctionProps; -final BasicUiFunction = uiFunction((props) { - return props.children.isEmpty ? 'basic component' : props.children; - }, - $BasicUiFunctionConfig, // ignore: undefined_identifier +final BasicUiFunction = uiFunction( + (props) { + return props.children.isEmpty ? 'basic component' : props.children; + }, + $BasicUiFunctionConfig, // ignore: undefined_identifier ); -final TopLevelForwardUiRefFunction = uiForwardRef((props, ref) { - return (BasicUiFunction()..ref = ref)(props.children); -}, +final TopLevelForwardUiRefFunction = uiForwardRef( + (props, ref) { + return (BasicUiFunction()..ref = ref)(props.children); + }, $TopLevelForwardUiRefFunctionConfig, // ignore: undefined_identifier -); \ No newline at end of file +); From 96ba4ff72e9e3c80ace929e65f6cf0fbf118dd02 Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Mon, 3 Aug 2020 12:44:16 -0700 Subject: [PATCH 06/28] Clean up --- test/over_react/component/{ref_test.dart => ref_util_test.dart} | 2 +- ...f_test.over_react.g.dart => ref_util_test.over_react.g.dart} | 2 +- test/over_react_component_test.dart | 2 +- web/component2/src/demos/forward_ref.dart | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) rename test/over_react/component/{ref_test.dart => ref_util_test.dart} (99%) rename test/over_react/component/{ref_test.over_react.g.dart => ref_util_test.over_react.g.dart} (99%) diff --git a/test/over_react/component/ref_test.dart b/test/over_react/component/ref_util_test.dart similarity index 99% rename from test/over_react/component/ref_test.dart rename to test/over_react/component/ref_util_test.dart index b0ddbae1d..064957d1b 100644 --- a/test/over_react/component/ref_test.dart +++ b/test/over_react/component/ref_util_test.dart @@ -26,7 +26,7 @@ import '../../test_util/test_util.dart'; import '../component/fixtures/basic_child_component.dart'; import 'fixtures/basic_ui_component.dart'; -part 'ref_test.over_react.g.dart'; // ignore: uri_has_not_been_generated +part 'ref_util_test.over_react.g.dart'; // ignore: uri_has_not_been_generated main() { group('forward ref -', () { diff --git a/test/over_react/component/ref_test.over_react.g.dart b/test/over_react/component/ref_util_test.over_react.g.dart similarity index 99% rename from test/over_react/component/ref_test.over_react.g.dart rename to test/over_react/component/ref_util_test.over_react.g.dart index 85bd54ee2..6052baf77 100644 --- a/test/over_react/component/ref_test.over_react.g.dart +++ b/test/over_react/component/ref_util_test.over_react.g.dart @@ -1,7 +1,7 @@ // GENERATED CODE - DO NOT MODIFY BY HAND // ignore_for_file: deprecated_member_use_from_same_package, unnecessary_null_in_if_null_operators, prefer_null_aware_operators -part of 'ref_test.dart'; +part of 'ref_util_test.dart'; // ************************************************************************** // OverReactBuilder (package:over_react/src/builder.dart) diff --git a/test/over_react_component_test.dart b/test/over_react_component_test.dart index 08b3f121a..93ea59e4f 100644 --- a/test/over_react_component_test.dart +++ b/test/over_react_component_test.dart @@ -32,7 +32,7 @@ import 'over_react/component/_deprecated/error_boundary_mixin_test.dart' as deprecated_error_boundary_mixin_test; import 'over_react/component/_deprecated/error_boundary_test.dart' as deprecated_error_boundary_test; -import 'over_react/component/ref_test.dart' as ref_test; +import 'over_react/component/ref_util_test.dart' as ref_test; import 'over_react/component/memo_test.dart' as memo_test; import 'over_react/component/prop_mixins_test.dart' as prop_mixins_test; import 'over_react/component/prop_typedefs_test.dart' as prop_typedefs_test; diff --git a/web/component2/src/demos/forward_ref.dart b/web/component2/src/demos/forward_ref.dart index a6b16ed73..af88c0ca7 100644 --- a/web/component2/src/demos/forward_ref.dart +++ b/web/component2/src/demos/forward_ref.dart @@ -1,7 +1,6 @@ import 'dart:html'; import 'package:over_react/over_react.dart'; -import 'package:react/hooks.dart'; // ignore: uri_has_not_been_generated part 'forward_ref.over_react.g.dart'; From de947874649dfc632e33ae7ddcc943b23732b139 Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Mon, 3 Aug 2020 12:57:34 -0700 Subject: [PATCH 07/28] Rename FunctionComponentConfig to UiFactoryConfig --- doc/new_boilerplate_migration.md | 4 +- example/builder/src/function_component.dart | 4 +- .../src/function_component.over_react.g.dart | 28 ++++++------ .../use_callback_example.over_react.g.dart | 4 +- .../use_context_example.over_react.g.dart | 8 ++-- .../use_debug_value_example.over_react.g.dart | 8 ++-- ...mperative_handle_example.over_react.g.dart | 17 ++++---- ...se_layout_effect_example.over_react.g.dart | 4 +- .../hooks/use_memo_example.over_react.g.dart | 4 +- .../use_reducer_example.over_react.g.dart | 4 +- .../hooks/use_ref_example.over_react.g.dart | 4 +- .../hooks/use_state_example.over_react.g.dart | 4 +- .../codegen/typed_map_impl_generator.dart | 8 ++-- lib/src/component/ref_util.dart | 2 +- .../component_declaration/component_base.dart | 2 +- .../function_component.dart | 10 ++--- lib/src/util/memo.dart | 2 +- test/over_react/component/memo_test.dart | 2 +- .../component/memo_test.over_react.g.dart | 4 +- .../component/ref_util_test.over_react.g.dart | 8 ++-- .../function_component_test.dart | 6 +-- .../function_component_test.over_react.g.dart | 43 +++++++++---------- test/vm_tests/builder/codegen_test.dart | 8 ++-- .../builder/declaration_parsing_test.dart | 8 ++-- .../builder/parsing/ast_util_test.dart | 4 +- .../src/demos/forward_ref.over_react.g.dart | 39 ++++++++--------- 26 files changed, 115 insertions(+), 124 deletions(-) diff --git a/doc/new_boilerplate_migration.md b/doc/new_boilerplate_migration.md index 0781a2ea7..2fbf73ea3 100644 --- a/doc/new_boilerplate_migration.md +++ b/doc/new_boilerplate_migration.md @@ -772,7 +772,7 @@ UiFactory Foo = uiFunction( (props) { return 'id: ${props.id}'; }, - FunctionComponentConfig( + UiFactoryConfig( displayName: 'Foo', ), ); @@ -823,7 +823,7 @@ UiFactory createFooHoc(UiFactory otherFactory) { Dom.div()('prop foo: ${props.foo}'), ); }, - FunctionComponentConfig( + UiFactoryConfig( displayName: 'FooHoc', propsFactory: PropsFactory.fromUiFactory(Foo), ), diff --git a/example/builder/src/function_component.dart b/example/builder/src/function_component.dart index 704996b3a..453cbf978 100644 --- a/example/builder/src/function_component.dart +++ b/example/builder/src/function_component.dart @@ -78,7 +78,7 @@ ReactElement functionComponentContent() { final genericFactory = uiFunction( GenericFactory, - FunctionComponentConfig(), + UiFactoryConfig(), ); final basicFactory = uiFunction( @@ -88,7 +88,7 @@ ReactElement functionComponentContent() { Dom.div()('prop basic1: ${props.basic1}'), ); }, - FunctionComponentConfig( + UiFactoryConfig( propsFactory: PropsFactory.fromUiFactory(Basic), displayName: 'basicFactory', ) diff --git a/example/builder/src/function_component.over_react.g.dart b/example/builder/src/function_component.over_react.g.dart index 068a71a8e..7ac74f604 100644 --- a/example/builder/src/function_component.over_react.g.dart +++ b/example/builder/src/function_component.over_react.g.dart @@ -123,21 +123,19 @@ const PropsMeta _$metaForFooProps = PropsMeta( keys: $FooProps.$propKeys, ); -final FunctionComponentConfig<_$$BasicProps> $_BasicConfig = - FunctionComponentConfig( - propsFactory: PropsFactory( - map: (map) => _$$BasicProps(map), - jsMap: (map) => _$$BasicProps$JsMap(map), - ), - displayName: '_Basic'); +final UiFactoryConfig<_$$BasicProps> $_BasicConfig = UiFactoryConfig( + propsFactory: PropsFactory( + map: (map) => _$$BasicProps(map), + jsMap: (map) => _$$BasicProps$JsMap(map), + ), + displayName: '_Basic'); -final FunctionComponentConfig<_$$BasicProps> $SimpleConfig = - FunctionComponentConfig( - propsFactory: PropsFactory( - map: (map) => _$$BasicProps(map), - jsMap: (map) => _$$BasicProps$JsMap(map), - ), - displayName: 'Simple'); +final UiFactoryConfig<_$$BasicProps> $SimpleConfig = UiFactoryConfig( + propsFactory: PropsFactory( + map: (map) => _$$BasicProps(map), + jsMap: (map) => _$$BasicProps$JsMap(map), + ), + displayName: 'Simple'); // Concrete props implementation. // @@ -205,7 +203,7 @@ class _$$BasicProps$JsMap extends _$$BasicProps { JsBackedMap _props; } -final FunctionComponentConfig<_$$FooProps> $FooConfig = FunctionComponentConfig( +final UiFactoryConfig<_$$FooProps> $FooConfig = UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$FooProps(map), jsMap: (map) => _$$FooProps$JsMap(map), diff --git a/example/hooks/use_callback_example.over_react.g.dart b/example/hooks/use_callback_example.over_react.g.dart index 513cb3a26..17a76bbdf 100644 --- a/example/hooks/use_callback_example.over_react.g.dart +++ b/example/hooks/use_callback_example.over_react.g.dart @@ -26,8 +26,8 @@ const PropsMeta _$metaForUseCallbackExampleProps = PropsMeta( keys: $UseCallbackExampleProps.$propKeys, ); -final FunctionComponentConfig<_$$UseCallbackExampleProps> - $UseCallbackExampleConfig = FunctionComponentConfig( +final UiFactoryConfig<_$$UseCallbackExampleProps> $UseCallbackExampleConfig = + UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$UseCallbackExampleProps(map), jsMap: (map) => _$$UseCallbackExampleProps$JsMap(map), diff --git a/example/hooks/use_context_example.over_react.g.dart b/example/hooks/use_context_example.over_react.g.dart index 1faa2a374..ebc10b77c 100644 --- a/example/hooks/use_context_example.over_react.g.dart +++ b/example/hooks/use_context_example.over_react.g.dart @@ -45,8 +45,8 @@ const PropsMeta _$metaForNewContextProviderProps = PropsMeta( keys: $NewContextProviderProps.$propKeys, ); -final FunctionComponentConfig<_$$UseContextExampleProps> - $UseContextExampleConfig = FunctionComponentConfig( +final UiFactoryConfig<_$$UseContextExampleProps> $UseContextExampleConfig = + UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$UseContextExampleProps(map), jsMap: (map) => _$$UseContextExampleProps$JsMap(map), @@ -119,8 +119,8 @@ class _$$UseContextExampleProps$JsMap extends _$$UseContextExampleProps { JsBackedMap _props; } -final FunctionComponentConfig<_$$NewContextProviderProps> - $NewContextProviderConfig = FunctionComponentConfig( +final UiFactoryConfig<_$$NewContextProviderProps> $NewContextProviderConfig = + UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$NewContextProviderProps(map), jsMap: (map) => _$$NewContextProviderProps$JsMap(map), diff --git a/example/hooks/use_debug_value_example.over_react.g.dart b/example/hooks/use_debug_value_example.over_react.g.dart index 27f140c6d..ddea2e6e4 100644 --- a/example/hooks/use_debug_value_example.over_react.g.dart +++ b/example/hooks/use_debug_value_example.over_react.g.dart @@ -58,8 +58,8 @@ const PropsMeta _$metaForUseDebugValueExampleProps = PropsMeta( keys: $UseDebugValueExampleProps.$propKeys, ); -final FunctionComponentConfig<_$$FriendListItemProps> $FriendListItemConfig = - FunctionComponentConfig( +final UiFactoryConfig<_$$FriendListItemProps> $FriendListItemConfig = + UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$FriendListItemProps(map), jsMap: (map) => _$$FriendListItemProps$JsMap(map), @@ -132,8 +132,8 @@ class _$$FriendListItemProps$JsMap extends _$$FriendListItemProps { JsBackedMap _props; } -final FunctionComponentConfig<_$$UseDebugValueExampleProps> - $UseDebugValueExampleConfig = FunctionComponentConfig( +final UiFactoryConfig<_$$UseDebugValueExampleProps> + $UseDebugValueExampleConfig = UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$UseDebugValueExampleProps(map), jsMap: (map) => _$$UseDebugValueExampleProps$JsMap(map), diff --git a/example/hooks/use_imperative_handle_example.over_react.g.dart b/example/hooks/use_imperative_handle_example.over_react.g.dart index 3b50275c3..721eec8d9 100644 --- a/example/hooks/use_imperative_handle_example.over_react.g.dart +++ b/example/hooks/use_imperative_handle_example.over_react.g.dart @@ -83,13 +83,12 @@ const PropsMeta _$metaForUseImperativeHandleExampleProps = PropsMeta( keys: $UseImperativeHandleExampleProps.$propKeys, ); -final FunctionComponentConfig<_$$FancyInputProps> $_FancyInputConfig = - FunctionComponentConfig( - propsFactory: PropsFactory( - map: (map) => _$$FancyInputProps(map), - jsMap: (map) => _$$FancyInputProps$JsMap(map), - ), - displayName: '_FancyInput'); +final UiFactoryConfig<_$$FancyInputProps> $_FancyInputConfig = UiFactoryConfig( + propsFactory: PropsFactory( + map: (map) => _$$FancyInputProps(map), + jsMap: (map) => _$$FancyInputProps$JsMap(map), + ), + displayName: '_FancyInput'); // Concrete props implementation. // @@ -157,8 +156,8 @@ class _$$FancyInputProps$JsMap extends _$$FancyInputProps { JsBackedMap _props; } -final FunctionComponentConfig<_$$UseImperativeHandleExampleProps> - $UseImperativeHandleExampleConfig = FunctionComponentConfig( +final UiFactoryConfig<_$$UseImperativeHandleExampleProps> + $UseImperativeHandleExampleConfig = UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$UseImperativeHandleExampleProps(map), jsMap: (map) => _$$UseImperativeHandleExampleProps$JsMap(map), diff --git a/example/hooks/use_layout_effect_example.over_react.g.dart b/example/hooks/use_layout_effect_example.over_react.g.dart index 05e554d0f..65006e460 100644 --- a/example/hooks/use_layout_effect_example.over_react.g.dart +++ b/example/hooks/use_layout_effect_example.over_react.g.dart @@ -26,8 +26,8 @@ const PropsMeta _$metaForUseLayoutEffectProps = PropsMeta( keys: $UseLayoutEffectProps.$propKeys, ); -final FunctionComponentConfig<_$$UseLayoutEffectProps> - $UseLayoutEffectExampleConfig = FunctionComponentConfig( +final UiFactoryConfig<_$$UseLayoutEffectProps> $UseLayoutEffectExampleConfig = + UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$UseLayoutEffectProps(map), jsMap: (map) => _$$UseLayoutEffectProps$JsMap(map), diff --git a/example/hooks/use_memo_example.over_react.g.dart b/example/hooks/use_memo_example.over_react.g.dart index f830d9a29..dbce4a042 100644 --- a/example/hooks/use_memo_example.over_react.g.dart +++ b/example/hooks/use_memo_example.over_react.g.dart @@ -26,8 +26,8 @@ const PropsMeta _$metaForUseMemoExampleProps = PropsMeta( keys: $UseMemoExampleProps.$propKeys, ); -final FunctionComponentConfig<_$$UseMemoExampleProps> $UseMemoExampleConfig = - FunctionComponentConfig( +final UiFactoryConfig<_$$UseMemoExampleProps> $UseMemoExampleConfig = + UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$UseMemoExampleProps(map), jsMap: (map) => _$$UseMemoExampleProps$JsMap(map), diff --git a/example/hooks/use_reducer_example.over_react.g.dart b/example/hooks/use_reducer_example.over_react.g.dart index 25c35d9ed..be8c974fe 100644 --- a/example/hooks/use_reducer_example.over_react.g.dart +++ b/example/hooks/use_reducer_example.over_react.g.dart @@ -41,8 +41,8 @@ const PropsMeta _$metaForUseReducerExampleProps = PropsMeta( keys: $UseReducerExampleProps.$propKeys, ); -final FunctionComponentConfig<_$$UseReducerExampleProps> - $UseReducerExampleConfig = FunctionComponentConfig( +final UiFactoryConfig<_$$UseReducerExampleProps> $UseReducerExampleConfig = + UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$UseReducerExampleProps(map), jsMap: (map) => _$$UseReducerExampleProps$JsMap(map), diff --git a/example/hooks/use_ref_example.over_react.g.dart b/example/hooks/use_ref_example.over_react.g.dart index ee23135ec..bdb66cbb3 100644 --- a/example/hooks/use_ref_example.over_react.g.dart +++ b/example/hooks/use_ref_example.over_react.g.dart @@ -26,8 +26,8 @@ const PropsMeta _$metaForUseRefExampleProps = PropsMeta( keys: $UseRefExampleProps.$propKeys, ); -final FunctionComponentConfig<_$$UseRefExampleProps> $UseRefExampleConfig = - FunctionComponentConfig( +final UiFactoryConfig<_$$UseRefExampleProps> $UseRefExampleConfig = + UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$UseRefExampleProps(map), jsMap: (map) => _$$UseRefExampleProps$JsMap(map), diff --git a/example/hooks/use_state_example.over_react.g.dart b/example/hooks/use_state_example.over_react.g.dart index 83c3ca39c..138da435c 100644 --- a/example/hooks/use_state_example.over_react.g.dart +++ b/example/hooks/use_state_example.over_react.g.dart @@ -26,8 +26,8 @@ const PropsMeta _$metaForUseStateExampleProps = PropsMeta( keys: $UseStateExampleProps.$propKeys, ); -final FunctionComponentConfig<_$$UseStateExampleProps> $UseStateExampleConfig = - FunctionComponentConfig( +final UiFactoryConfig<_$$UseStateExampleProps> $UseStateExampleConfig = + UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$UseStateExampleProps(map), jsMap: (map) => _$$UseStateExampleProps$JsMap(map), diff --git a/lib/src/builder/codegen/typed_map_impl_generator.dart b/lib/src/builder/codegen/typed_map_impl_generator.dart index 19f095119..8e860d278 100644 --- a/lib/src/builder/codegen/typed_map_impl_generator.dart +++ b/lib/src/builder/codegen/typed_map_impl_generator.dart @@ -377,9 +377,9 @@ class _TypedMapImplGenerator extends TypedMapImplGenerator { @override bool get isComponent2 => true; - String _generateFunctionComponentConfig(FactoryNames factoryName) { - return 'final FunctionComponentConfig<${names.implName}> ' - '${factoryName.configName} = FunctionComponentConfig(\n' + String _generateUiFactoryConfig(FactoryNames factoryName) { + return 'final UiFactoryConfig<${names.implName}> ' + '${factoryName.configName} = UiFactoryConfig(\n' 'propsFactory: PropsFactory(\n' 'map: (map) => ${names.implName}(map),\n' 'jsMap: (map) => ${names.jsMapImplName}(map),),\n' @@ -390,7 +390,7 @@ class _TypedMapImplGenerator extends TypedMapImplGenerator { void _generateFactory() { if (isFunctionComponentDeclaration) { for (final factoryName in factoryNames) { - outputContentsBuffer.write(_generateFunctionComponentConfig(factoryName)); + outputContentsBuffer.write(_generateUiFactoryConfig(factoryName)); } } else { super._generateFactory(); diff --git a/lib/src/component/ref_util.dart b/lib/src/component/ref_util.dart index bbd055461..6092e1170 100644 --- a/lib/src/component/ref_util.dart +++ b/lib/src/component/ref_util.dart @@ -450,7 +450,7 @@ UiFactory Function(UiFactory) forwardRef /// Learn more: . UiFactory uiForwardRef( dynamic Function(TProps props, dynamic ref) functionComponent, - FunctionComponentConfig config) { + UiFactoryConfig config) { ArgumentError.checkNotNull(config, 'config'); // ignore: invalid_use_of_protected_member diff --git a/lib/src/component_declaration/component_base.dart b/lib/src/component_declaration/component_base.dart index 4c018ade6..412761385 100644 --- a/lib/src/component_declaration/component_base.dart +++ b/lib/src/component_declaration/component_base.dart @@ -94,7 +94,7 @@ ReactDartComponentFactoryProxy registerAbstractComponent(Type abstractComponentC typedef TProps UiFactory([Map backingProps]); extension UiFactoryHelpers on UiFactory { - FunctionComponentConfig asForwardRefConfig({String displayName}) => FunctionComponentConfig(propsFactory: PropsFactory.fromUiFactory(this), displayName: displayName); + UiFactoryConfig asForwardRefConfig({String displayName}) => UiFactoryConfig(propsFactory: PropsFactory.fromUiFactory(this), displayName: displayName); } /// A utility variation on [UiFactory], __without__ a `backingProps` parameter. diff --git a/lib/src/component_declaration/function_component.dart b/lib/src/component_declaration/function_component.dart index c306c2604..64fb2e9ce 100644 --- a/lib/src/component_declaration/function_component.dart +++ b/lib/src/component_declaration/function_component.dart @@ -69,7 +69,7 @@ export 'component_type_checking.dart' /// (props) { /// return (Dom.button()..disabled = props.isDisabled)('Click me!'); /// }, -/// FunctionComponentConfig( +/// UiFactoryConfig( /// propsFactory: PropsFactory.fromUiFactory(Foo), /// displayName: 'Bar', /// ), @@ -83,7 +83,7 @@ export 'component_type_checking.dart' /// (props) { /// return Dom.div()('prop id: ${props.id}'); /// }, -/// FunctionComponentConfig( +/// UiFactoryConfig( /// displayName: 'Foo', /// ), /// ); @@ -93,7 +93,7 @@ export 'component_type_checking.dart' // TODO: right now only top level factory declarations will generate props configs. UiFactory uiFunction( dynamic Function(TProps props) functionComponent, - FunctionComponentConfig config, + UiFactoryConfig config, ) { ArgumentError.checkNotNull(config, 'config'); @@ -161,12 +161,12 @@ class GenericUiProps extends UiProps { } /// Helper class used to keep track of generated information for [uiFunction]. -class FunctionComponentConfig { +class UiFactoryConfig { @protected final PropsFactory propsFactory; final String displayName; - FunctionComponentConfig({this.propsFactory, this.displayName}); + UiFactoryConfig({this.propsFactory, this.displayName}); } /// Helper class to keep track of props factories used by [uiFunction], diff --git a/lib/src/util/memo.dart b/lib/src/util/memo.dart index 93f208f0d..d348edd60 100644 --- a/lib/src/util/memo.dart +++ b/lib/src/util/memo.dart @@ -36,7 +36,7 @@ import 'package:over_react/component_base.dart'; /// (props) { /// // render using props /// }, -/// FunctionComponentConfig(), +/// UiFactoryConfig(), /// )); /// ``` /// diff --git a/test/over_react/component/memo_test.dart b/test/over_react/component/memo_test.dart index 83ef2a7ce..dc6886104 100644 --- a/test/over_react/component/memo_test.dart +++ b/test/over_react/component/memo_test.dart @@ -53,7 +53,7 @@ main() { (props) { return Dom.div()('prop id: ${props.id}'); }, - FunctionComponentConfig(), + UiFactoryConfig(), ); UiFactory FunctionMemo = memo(FunctionTest); diff --git a/test/over_react/component/memo_test.over_react.g.dart b/test/over_react/component/memo_test.over_react.g.dart index 048ffe6c2..c86027a9f 100644 --- a/test/over_react/component/memo_test.over_react.g.dart +++ b/test/over_react/component/memo_test.over_react.g.dart @@ -202,8 +202,8 @@ const PropsMeta _$metaForFunctionCustomPropsProps = PropsMeta( keys: $FunctionCustomPropsProps.$propKeys, ); -final FunctionComponentConfig<_$$FunctionCustomPropsProps> - $FunctionCustomPropsConfig = FunctionComponentConfig( +final UiFactoryConfig<_$$FunctionCustomPropsProps> $FunctionCustomPropsConfig = + UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$FunctionCustomPropsProps(map), jsMap: (map) => _$$FunctionCustomPropsProps$JsMap(map), diff --git a/test/over_react/component/ref_util_test.over_react.g.dart b/test/over_react/component/ref_util_test.over_react.g.dart index 6052baf77..853fcf916 100644 --- a/test/over_react/component/ref_util_test.over_react.g.dart +++ b/test/over_react/component/ref_util_test.over_react.g.dart @@ -191,8 +191,8 @@ const PropsMeta _$metaForBasicUiFunctionProps = PropsMeta( keys: $BasicUiFunctionProps.$propKeys, ); -final FunctionComponentConfig<_$$BasicUiFunctionProps> $BasicUiFunctionConfig = - FunctionComponentConfig( +final UiFactoryConfig<_$$BasicUiFunctionProps> $BasicUiFunctionConfig = + UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$BasicUiFunctionProps(map), jsMap: (map) => _$$BasicUiFunctionProps$JsMap(map), @@ -265,8 +265,8 @@ class _$$BasicUiFunctionProps$JsMap extends _$$BasicUiFunctionProps { JsBackedMap _props; } -final FunctionComponentConfig<_$$SecondaryBasicUiFunctionProps> - $TopLevelForwardUiRefFunctionConfig = FunctionComponentConfig( +final UiFactoryConfig<_$$SecondaryBasicUiFunctionProps> + $TopLevelForwardUiRefFunctionConfig = UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$SecondaryBasicUiFunctionProps(map), jsMap: (map) => _$$SecondaryBasicUiFunctionProps$JsMap(map), diff --git a/test/over_react/component_declaration/builder_integration_tests/new_boilerplate/function_component_test.dart b/test/over_react/component_declaration/builder_integration_tests/new_boilerplate/function_component_test.dart index d2fea0f61..58f780ddf 100644 --- a/test/over_react/component_declaration/builder_integration_tests/new_boilerplate/function_component_test.dart +++ b/test/over_react/component_declaration/builder_integration_tests/new_boilerplate/function_component_test.dart @@ -44,7 +44,7 @@ main() { group('with UiProps', () { UiFactory TestUiProps = uiFunction( (props) => (Dom.div()..addTestId('testId3'))('id: ${props.id}'), - FunctionComponentConfig(), + UiFactoryConfig(), ); test( @@ -100,7 +100,7 @@ main() { expect( () => uiFunction( (props) => Dom.div()(), - FunctionComponentConfig(displayName: 'Foo'), + UiFactoryConfig(displayName: 'Foo'), ), throwsArgumentError); }); @@ -213,7 +213,7 @@ UiFactory TestCustom = uiFunction( ..addProp('data-prop-custom-key-and-namespace-prop', props.customKeyAndNamespaceProp))('rendered content'); }, - FunctionComponentConfig( + UiFactoryConfig( propsFactory: PropsFactory.fromUiFactory(Test), ) ); diff --git a/test/over_react/component_declaration/builder_integration_tests/new_boilerplate/function_component_test.over_react.g.dart b/test/over_react/component_declaration/builder_integration_tests/new_boilerplate/function_component_test.over_react.g.dart index 7d501af18..33d4e536e 100644 --- a/test/over_react/component_declaration/builder_integration_tests/new_boilerplate/function_component_test.over_react.g.dart +++ b/test/over_react/component_declaration/builder_integration_tests/new_boilerplate/function_component_test.over_react.g.dart @@ -106,29 +106,26 @@ const PropsMeta _$metaForTestProps = PropsMeta( keys: $TestProps.$propKeys, ); -final FunctionComponentConfig<_$$TestProps> $TestConfig = - FunctionComponentConfig( - propsFactory: PropsFactory( - map: (map) => _$$TestProps(map), - jsMap: (map) => _$$TestProps$JsMap(map), - ), - displayName: 'Test'); - -final FunctionComponentConfig<_$$TestProps> $NoLHSTestConfig = - FunctionComponentConfig( - propsFactory: PropsFactory( - map: (map) => _$$TestProps(map), - jsMap: (map) => _$$TestProps$JsMap(map), - ), - displayName: 'NoLHSTest'); - -final FunctionComponentConfig<_$$TestProps> $_TestConfig = - FunctionComponentConfig( - propsFactory: PropsFactory( - map: (map) => _$$TestProps(map), - jsMap: (map) => _$$TestProps$JsMap(map), - ), - displayName: '_Test'); +final UiFactoryConfig<_$$TestProps> $TestConfig = UiFactoryConfig( + propsFactory: PropsFactory( + map: (map) => _$$TestProps(map), + jsMap: (map) => _$$TestProps$JsMap(map), + ), + displayName: 'Test'); + +final UiFactoryConfig<_$$TestProps> $NoLHSTestConfig = UiFactoryConfig( + propsFactory: PropsFactory( + map: (map) => _$$TestProps(map), + jsMap: (map) => _$$TestProps$JsMap(map), + ), + displayName: 'NoLHSTest'); + +final UiFactoryConfig<_$$TestProps> $_TestConfig = UiFactoryConfig( + propsFactory: PropsFactory( + map: (map) => _$$TestProps(map), + jsMap: (map) => _$$TestProps$JsMap(map), + ), + displayName: '_Test'); // Concrete props implementation. // diff --git a/test/vm_tests/builder/codegen_test.dart b/test/vm_tests/builder/codegen_test.dart index cf6b1d5ce..fad51b903 100644 --- a/test/vm_tests/builder/codegen_test.dart +++ b/test/vm_tests/builder/codegen_test.dart @@ -658,8 +658,8 @@ main() { group('and generates props config for function components', () { String generatedConfig(String propsName, String factoryName) { - return 'final FunctionComponentConfig<_\$\$$propsName> ' - '\$${factoryName}Config = FunctionComponentConfig(\n' + return 'final UiFactoryConfig<_\$\$$propsName> ' + '\$${factoryName}Config = UiFactoryConfig(\n' 'propsFactory: PropsFactory(\n' 'map: (map) => _\$\$$propsName(map),\n' 'jsMap: (map) => _\$\$$propsName\$JsMap(map),),\n' @@ -767,7 +767,7 @@ main() { (props) { return Dom.div()(); }, - FunctionComponentConfig(), + UiFactoryConfig(), ); final Foo = uiFunction( @@ -781,7 +781,7 @@ main() { (props) { return Dom.div()(); }, - FunctionComponentConfig( + UiFactoryConfig( propsFactory: PropsFactory.fromUiFactory(Foo), ) ); diff --git a/test/vm_tests/builder/declaration_parsing_test.dart b/test/vm_tests/builder/declaration_parsing_test.dart index e12814d2b..8415f7f0d 100644 --- a/test/vm_tests/builder/declaration_parsing_test.dart +++ b/test/vm_tests/builder/declaration_parsing_test.dart @@ -1586,7 +1586,7 @@ main() { (props) { return Dom.div()(); }, - FunctionComponentConfig( + UiFactoryConfig( propsFactory: PropsFactory.fromUiFactory(Foo), ), ); @@ -1645,7 +1645,7 @@ main() { (props) { return Dom.div()(); }, - FunctionComponentConfig(), + UiFactoryConfig(), ); '''); @@ -1672,7 +1672,7 @@ main() { (props) { return Dom.div()(); }, - FunctionComponentConfig( + UiFactoryConfig( propsFactory: PropsFactory.uiFactory(Foo), ), )); @@ -1681,7 +1681,7 @@ main() { (props) { return Dom.div()(); }, - FunctionComponentConfig(), + UiFactoryConfig(), )); mixin FooPropsMixin on UiProps {} diff --git a/test/vm_tests/builder/parsing/ast_util_test.dart b/test/vm_tests/builder/parsing/ast_util_test.dart index b013cdc01..f897e61ac 100644 --- a/test/vm_tests/builder/parsing/ast_util_test.dart +++ b/test/vm_tests/builder/parsing/ast_util_test.dart @@ -82,7 +82,7 @@ main() { expect(InitializerHelperTopLevel(parseAndGetSingleWithType(''' final Foo = uiFunction( (props) => Dom.div()(), - FunctionComponentConfig(), + UiFactoryConfig(), ); ''')).hasGeneratedConfigArg, false); @@ -96,7 +96,7 @@ main() { expect(InitializerHelperTopLevel(parseAndGetSingleWithType(''' final Foo = uiFunction( (props) => Dom.div()(), - FunctionComponentConfig( + UiFactoryConfig( propsFactory: PropsFactory.fromUiFactory(Bar), ), ); diff --git a/web/component2/src/demos/forward_ref.over_react.g.dart b/web/component2/src/demos/forward_ref.over_react.g.dart index b6ee921af..60f4c252e 100644 --- a/web/component2/src/demos/forward_ref.over_react.g.dart +++ b/web/component2/src/demos/forward_ref.over_react.g.dart @@ -410,8 +410,8 @@ const PropsMeta _$metaForRefDemoHocProps = PropsMeta( keys: $RefDemoHocProps.$propKeys, ); -final FunctionComponentConfig<_$$UiForwardRefLogsFunctionComponentProps> - $UiForwardRefLogsFunctionComponentConfig = FunctionComponentConfig( +final UiFactoryConfig<_$$UiForwardRefLogsFunctionComponentProps> + $UiForwardRefLogsFunctionComponentConfig = UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$UiForwardRefLogsFunctionComponentProps(map), jsMap: (map) => _$$UiForwardRefLogsFunctionComponentProps$JsMap(map), @@ -486,10 +486,8 @@ class _$$UiForwardRefLogsFunctionComponentProps$JsMap JsBackedMap _props; } -final FunctionComponentConfig< - _$$UiForwardRefLogsPropsComplexFunctionComponentProps> - $UiForwardRefLogsPropsComplexFunctionComponentConfig = - FunctionComponentConfig( +final UiFactoryConfig<_$$UiForwardRefLogsPropsComplexFunctionComponentProps> + $UiForwardRefLogsPropsComplexFunctionComponentConfig = UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$UiForwardRefLogsPropsComplexFunctionComponentProps(map), @@ -574,8 +572,8 @@ class _$$UiForwardRefLogsPropsComplexFunctionComponentProps$JsMap JsBackedMap _props; } -final FunctionComponentConfig<_$$UiForwardRefLogsPropsComplexComponentProps> - $UiForwardRefLogsPropsComplexComponentConfig = FunctionComponentConfig( +final UiFactoryConfig<_$$UiForwardRefLogsPropsComplexComponentProps> + $UiForwardRefLogsPropsComplexComponentConfig = UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$UiForwardRefLogsPropsComplexComponentProps(map), jsMap: (map) => @@ -654,8 +652,8 @@ class _$$UiForwardRefLogsPropsComplexComponentProps$JsMap JsBackedMap _props; } -final FunctionComponentConfig<_$$_LogsPropsFunctionComponentProps> - $_LogsPropsFunctionComponentConfig = FunctionComponentConfig( +final UiFactoryConfig<_$$_LogsPropsFunctionComponentProps> + $_LogsPropsFunctionComponentConfig = UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$_LogsPropsFunctionComponentProps(map), jsMap: (map) => _$$_LogsPropsFunctionComponentProps$JsMap(map), @@ -731,8 +729,8 @@ class _$$_LogsPropsFunctionComponentProps$JsMap JsBackedMap _props; } -final FunctionComponentConfig<_$$RefDemoProps> $RefDemoContainerConfig = - FunctionComponentConfig( +final UiFactoryConfig<_$$RefDemoProps> $RefDemoContainerConfig = + UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$RefDemoProps(map), jsMap: (map) => _$$RefDemoProps$JsMap(map), @@ -805,8 +803,8 @@ class _$$RefDemoProps$JsMap extends _$$RefDemoProps { JsBackedMap _props; } -final FunctionComponentConfig<_$$RefDemoSectionProps> $RefDemoSectionConfig = - FunctionComponentConfig( +final UiFactoryConfig<_$$RefDemoSectionProps> $RefDemoSectionConfig = + UiFactoryConfig( propsFactory: PropsFactory( map: (map) => _$$RefDemoSectionProps(map), jsMap: (map) => _$$RefDemoSectionProps$JsMap(map), @@ -879,13 +877,12 @@ class _$$RefDemoSectionProps$JsMap extends _$$RefDemoSectionProps { JsBackedMap _props; } -final FunctionComponentConfig<_$$RefDemoHocProps> $RefDemoHocConfig = - FunctionComponentConfig( - propsFactory: PropsFactory( - map: (map) => _$$RefDemoHocProps(map), - jsMap: (map) => _$$RefDemoHocProps$JsMap(map), - ), - displayName: 'RefDemoHoc'); +final UiFactoryConfig<_$$RefDemoHocProps> $RefDemoHocConfig = UiFactoryConfig( + propsFactory: PropsFactory( + map: (map) => _$$RefDemoHocProps(map), + jsMap: (map) => _$$RefDemoHocProps$JsMap(map), + ), + displayName: 'RefDemoHoc'); // Concrete props implementation. // From ea10a41d2864c7ac4bd67697533f6bfaaf4bb345 Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Mon, 3 Aug 2020 16:38:34 -0700 Subject: [PATCH 08/28] Check for generated config --- lib/src/builder/parsing/ast_util.dart | 18 +++++++++++++----- lib/src/builder/parsing/members_from_ast.dart | 5 +++-- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/src/builder/parsing/ast_util.dart b/lib/src/builder/parsing/ast_util.dart index 6bb09e36a..e2877e203 100644 --- a/lib/src/builder/parsing/ast_util.dart +++ b/lib/src/builder/parsing/ast_util.dart @@ -46,12 +46,15 @@ extension InitializerHelperTopLevel on TopLevelVariableDeclaration { bool get hasGeneratedConfigArg { return firstInitializer != null && anyDescendantIdentifiers(firstInitializer, (identifier) { - if (identifier.isFunctionType) { - final args = - identifier.thisOrAncestorOfType()?.argumentList?.arguments; + final uiFactoryDeclaration = identifier.thisOrAncestorOfType(); + final methodInvocation = identifier.thisOrAncestorOfType(); + if (methodInvocation != null && uiFactoryDeclaration != null) { + final args = methodInvocation.argumentList?.arguments; if (args == null || args.length < 2) return false; - return args[1].toString().startsWith(RegExp(r'\$')); + + return args[1].toString() == '\$${uiFactoryDeclaration.name.name}Config'; } + return false; }); } @@ -80,7 +83,12 @@ extension NameHelper on Identifier { return self is PrefixedIdentifier ? self.identifier.name : self.name; } - bool get isFunctionType => ['uiFunction', 'uiForwardRef'].contains(this.name); + bool get isFunctionType => ['uiFunction', 'uiForwardRef', 'uiJsComponent'].contains(this.name); + + bool get isAttachedToAGeneratedUiFactory { + final uiFactoryDeclaration = this.thisOrAncestorOfType(); + return uiFactoryDeclaration?.hasGeneratedConfigArg; + } } /// Utilities related to detecting a super class on a [MixinDeclaration] diff --git a/lib/src/builder/parsing/members_from_ast.dart b/lib/src/builder/parsing/members_from_ast.dart index 01cb2999c..a44046782 100644 --- a/lib/src/builder/parsing/members_from_ast.dart +++ b/lib/src/builder/parsing/members_from_ast.dart @@ -170,11 +170,12 @@ class _BoilerplateMemberDetector { final rightHandSide = node.variables.firstInitializer; if (rightHandSide != null && - anyDescendantIdentifiers(rightHandSide, (identifier) => identifier.isFunctionType)) { + anyDescendantIdentifiers( + rightHandSide, (identifier) => identifier.isAttachedToAGeneratedUiFactory)) { onFactory(BoilerplateFactory( node, VersionConfidences( - v4_mixinBased: node.hasGeneratedConfigArg ? Confidence.likely : Confidence.neutral, + v4_mixinBased: Confidence.likely, v3_legacyDart2Only: Confidence.none, v2_legacyBackwardsCompat: Confidence.none, ))); From d435a1f3f3d6669f22b9da6ddd359a7a1ffa0eb2 Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Tue, 4 Aug 2020 13:59:04 -0700 Subject: [PATCH 09/28] Fix parsing --- lib/src/builder/parsing/ast_util.dart | 13 ++++++++++++- .../src/demos/{forward_ref.dart => ref.dart} | 0 2 files changed, 12 insertions(+), 1 deletion(-) rename web/component2/src/demos/{forward_ref.dart => ref.dart} (100%) diff --git a/lib/src/builder/parsing/ast_util.dart b/lib/src/builder/parsing/ast_util.dart index e2877e203..e1d10934c 100644 --- a/lib/src/builder/parsing/ast_util.dart +++ b/lib/src/builder/parsing/ast_util.dart @@ -52,7 +52,18 @@ extension InitializerHelperTopLevel on TopLevelVariableDeclaration { final args = methodInvocation.argumentList?.arguments; if (args == null || args.length < 2) return false; - return args[1].toString() == '\$${uiFactoryDeclaration.name.name}Config'; + if (args[1] is SimpleIdentifier) { + return args[1].toString() == '\$${uiFactoryDeclaration.name.name}Config'; + } else if (args[1] is PrefixedIdentifier) { + return args[1] + .childEntities + .where((child) { + return child is SimpleIdentifier && + child.name == '\$${uiFactoryDeclaration.name.name}Config'; + }) + .toList() + .isNotEmpty; + } } return false; diff --git a/web/component2/src/demos/forward_ref.dart b/web/component2/src/demos/ref.dart similarity index 100% rename from web/component2/src/demos/forward_ref.dart rename to web/component2/src/demos/ref.dart From d865b24acee13d258193a799f1ee99c5dccf52c0 Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Wed, 5 Aug 2020 08:29:51 -0700 Subject: [PATCH 10/28] Fix up example --- pubspec.yaml | 1 - web/component2/src/demos.dart | 2 +- web/component2/src/demos/ref.dart | 55 ++++++++++++------- ...ver_react.g.dart => ref.over_react.g.dart} | 47 +++++++++++----- 4 files changed, 67 insertions(+), 38 deletions(-) rename web/component2/src/demos/{forward_ref.over_react.g.dart => ref.over_react.g.dart} (95%) diff --git a/pubspec.yaml b/pubspec.yaml index 4e5d33c7e..28b3740bc 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -48,7 +48,6 @@ dev_dependencies: test: ^1.9.1 yaml: ^2.2.1 - dependency_overrides: react: git: diff --git a/web/component2/src/demos.dart b/web/component2/src/demos.dart index da00f6dd6..b32b3c337 100644 --- a/web/component2/src/demos.dart +++ b/web/component2/src/demos.dart @@ -23,7 +23,7 @@ export 'demos/button/button-active.dart'; export 'demos/button/button-disabled.dart'; export 'demos/custom_error_boundary.dart'; -export 'demos/forward_ref.dart'; +export 'demos/ref.dart'; export '../src/demo_components/prop_validation_wrap.dart'; diff --git a/web/component2/src/demos/ref.dart b/web/component2/src/demos/ref.dart index af88c0ca7..9c5597d97 100644 --- a/web/component2/src/demos/ref.dart +++ b/web/component2/src/demos/ref.dart @@ -3,11 +3,12 @@ import 'dart:html'; import 'package:over_react/over_react.dart'; // ignore: uri_has_not_been_generated -part 'forward_ref.over_react.g.dart'; +part 'ref.over_react.g.dart'; // ------------ `uiForwardRef` with a function component (simple) ------------ mixin UiForwardRefLogsFunctionComponentProps on UiProps { BuilderOnlyUiFactory builder; + Ref lastClickedButton; } final UiForwardRefLogsFunctionComponent = uiForwardRef( @@ -16,8 +17,8 @@ final UiForwardRefLogsFunctionComponent = uiForwardRef( @@ -108,7 +109,7 @@ mixin LogPropsProps on UiProps { BuilderOnlyUiFactory builder; // A simple prop to change in order to trigger the print. - bool thisWasClickedLast; + Ref lastClickedButton; // Private since we only use this to pass along the value of `ref` to // the return value of forwardRef. @@ -126,11 +127,9 @@ class LogPropsComponent extends UiComponent2 { @override render() { - return Dom.div()( - Dom.p()('This was the last button clicked: ${props.thisWasClickedLast}'), - (props.builder() - ..modifyProps(addUnconsumedDomProps) - ..ref = props._forwardedRef)(props.children)); + return Dom.div()((props.builder() + ..modifyProps(addUnconsumedDomProps) + ..ref = props._forwardedRef)(props.children)); } } @@ -149,8 +148,8 @@ final _LogsPropsFunctionComponent = uiFunction<_LogsPropsFunctionComponentProps> useEffect(() { if (prevPropsRef.current != null) { - print(prevPropsRef.current); - print(props); + print('old props: ${prevPropsRef.current}'); + print('new props: $props'); } prevPropsRef.current = props; @@ -190,50 +189,58 @@ final RefDemoContainer = uiFunction( final fancyButtonNodeRef = createRef(); final fancyFunctionalButtonNodeRef = createRef(); - final lastClickedRef = useState(null); + final lastClickedRef = useState>(buttonNodeRefForComplexComponent); return ((Dom.div()..style = {'padding': 10})( (RefDemoSection()..sectionTitle = 'uiForwardRef Demos')( (RefDemoHoc()..demoTitle = '`uiForwardRef` with a function component (simple)')( (UiForwardRefLogsFunctionComponent() ..builder = FancyButton + ..lastClickedButton = lastClickedRef.value ..id = 'uiForwardRef-function-component' ..className = 'btn btn-primary' ..ref = buttonNodeRefForSimpleFunctionComponent ..onClick = (_) { - print(buttonNodeRefForSimpleFunctionComponent.current.outerHtml); + printButtonOuterHtml(buttonNodeRefForSimpleFunctionComponent); + lastClickedRef.set(buttonNodeRefForSimpleFunctionComponent); })(), ), (RefDemoHoc()..demoTitle = '`uiForwardRef` with a function component (complex)')( (UiForwardRefLogsPropsComplexFunctionComponent() ..buttonDescription = 'A button that logs the innerHtml' ..builder = FancyButton + ..lastClickedButton = lastClickedRef.value ..id = 'uiForwardRef-function-complex-component' ..className = 'btn btn-success' ..ref = buttonNodeRefForComplexFunctionComponent ..onClick = (_) { - print(buttonNodeRefForComplexFunctionComponent.current.outerHtml); + printButtonOuterHtml(buttonNodeRefForComplexFunctionComponent); + lastClickedRef.set(buttonNodeRefForComplexFunctionComponent); })(), ), (RefDemoHoc()..demoTitle = '`uiForwardRef` with a class component (simple)')( (UiForwardRefLogsPropsComponent() ..builder = FancyButton + ..lastClickedButton = lastClickedRef.value ..id = 'uiForwardRef-component' ..className = 'btn btn-warning' ..ref = buttonNodeRefForSimpleComponent ..onClick = (_) { - print(buttonNodeRefForSimpleComponent.current.outerHtml); + printButtonOuterHtml(buttonNodeRefForSimpleComponent); + lastClickedRef.set(buttonNodeRefForSimpleComponent); })(), ), (RefDemoHoc()..demoTitle = '`uiForwardRef` with a class component (complex)')( (UiForwardRefLogsPropsComplexComponent() ..buttonDescription = 'A button that logs the innerHtml' ..builder = FancyButton + ..lastClickedButton = lastClickedRef.value ..id = 'uiForwardRef-complex-component' ..className = 'btn btn-danger' ..ref = buttonNodeRefForComplexComponent ..onClick = (_) { - print(buttonNodeRefForComplexComponent.current.outerHtml); + printButtonOuterHtml(buttonNodeRefForComplexComponent); + lastClickedRef.set(buttonNodeRefForComplexComponent); })(), ), ), @@ -241,22 +248,24 @@ final RefDemoContainer = uiFunction( (RefDemoHoc()..demoTitle = '`forwardRef` with class component')( (LogProps() ..builder = FancyButton + ..lastClickedButton = lastClickedRef.value ..id = 'forwardRef-component' ..className = 'btn btn-primary' ..ref = fancyButtonNodeRef ..onClick = (_) { - print(fancyButtonNodeRef.current.outerHtml); + printButtonOuterHtml(fancyButtonNodeRef); lastClickedRef.set(fancyButtonNodeRef); })(), ), (RefDemoHoc()..demoTitle = '`uiForwardRef` with function component')( (LogsPropsFunctionComponent() ..builder = FancyButton + ..lastClickedButton = lastClickedRef.value ..id = 'forwardRef-function-component' ..className = 'btn btn-success' ..ref = fancyFunctionalButtonNodeRef ..onClick = (_) { - print(fancyFunctionalButtonNodeRef.current.outerHtml); + printButtonOuterHtml(fancyFunctionalButtonNodeRef); lastClickedRef.set(fancyFunctionalButtonNodeRef); })(), ), @@ -266,6 +275,10 @@ final RefDemoContainer = uiFunction( $RefDemoContainerConfig, // ignore: undefined_identifier ); +void printButtonOuterHtml(Ref buttonRef) { + print('this button outerHTML: ${buttonRef.current.outerHtml}'); +} + mixin RefDemoSectionProps on UiProps { String sectionTitle; } diff --git a/web/component2/src/demos/forward_ref.over_react.g.dart b/web/component2/src/demos/ref.over_react.g.dart similarity index 95% rename from web/component2/src/demos/forward_ref.over_react.g.dart rename to web/component2/src/demos/ref.over_react.g.dart index 60f4c252e..4b7083266 100644 --- a/web/component2/src/demos/forward_ref.over_react.g.dart +++ b/web/component2/src/demos/ref.over_react.g.dart @@ -1,7 +1,7 @@ // GENERATED CODE - DO NOT MODIFY BY HAND // ignore_for_file: deprecated_member_use_from_same_package, unnecessary_null_in_if_null_operators, prefer_null_aware_operators -part of 'forward_ref.dart'; +part of 'ref.dart'; // ************************************************************************** // OverReactBuilder (package:over_react/src/builder.dart) @@ -159,18 +159,35 @@ mixin $UiForwardRefLogsFunctionComponentProps @override set builder(BuilderOnlyUiFactory value) => props[_$key__builder__UiForwardRefLogsFunctionComponentProps] = value; + @override + Ref get lastClickedButton => + props[_$key__lastClickedButton__UiForwardRefLogsFunctionComponentProps] ?? + null; // Add ` ?? null` to workaround DDC bug: ; + @override + set lastClickedButton(Ref value) => + props[_$key__lastClickedButton__UiForwardRefLogsFunctionComponentProps] = + value; /* GENERATED CONSTANTS */ static const PropDescriptor _$prop__builder__UiForwardRefLogsFunctionComponentProps = PropDescriptor(_$key__builder__UiForwardRefLogsFunctionComponentProps); + static const PropDescriptor + _$prop__lastClickedButton__UiForwardRefLogsFunctionComponentProps = + PropDescriptor( + _$key__lastClickedButton__UiForwardRefLogsFunctionComponentProps); static const String _$key__builder__UiForwardRefLogsFunctionComponentProps = 'UiForwardRefLogsFunctionComponentProps.builder'; + static const String + _$key__lastClickedButton__UiForwardRefLogsFunctionComponentProps = + 'UiForwardRefLogsFunctionComponentProps.lastClickedButton'; static const List $props = [ - _$prop__builder__UiForwardRefLogsFunctionComponentProps + _$prop__builder__UiForwardRefLogsFunctionComponentProps, + _$prop__lastClickedButton__UiForwardRefLogsFunctionComponentProps ]; static const List $propKeys = [ - _$key__builder__UiForwardRefLogsFunctionComponentProps + _$key__builder__UiForwardRefLogsFunctionComponentProps, + _$key__lastClickedButton__UiForwardRefLogsFunctionComponentProps ]; } @@ -280,12 +297,12 @@ mixin $LogPropsProps on LogPropsProps { set builder(BuilderOnlyUiFactory value) => props[_$key__builder__LogPropsProps] = value; @override - bool get thisWasClickedLast => - props[_$key__thisWasClickedLast__LogPropsProps] ?? + Ref get lastClickedButton => + props[_$key__lastClickedButton__LogPropsProps] ?? null; // Add ` ?? null` to workaround DDC bug: ; @override - set thisWasClickedLast(bool value) => - props[_$key__thisWasClickedLast__LogPropsProps] = value; + set lastClickedButton(Ref value) => + props[_$key__lastClickedButton__LogPropsProps] = value; @override Ref get _forwardedRef => props[_$key___forwardedRef__LogPropsProps] ?? @@ -296,24 +313,24 @@ mixin $LogPropsProps on LogPropsProps { /* GENERATED CONSTANTS */ static const PropDescriptor _$prop__builder__LogPropsProps = PropDescriptor(_$key__builder__LogPropsProps); - static const PropDescriptor _$prop__thisWasClickedLast__LogPropsProps = - PropDescriptor(_$key__thisWasClickedLast__LogPropsProps); + static const PropDescriptor _$prop__lastClickedButton__LogPropsProps = + PropDescriptor(_$key__lastClickedButton__LogPropsProps); static const PropDescriptor _$prop___forwardedRef__LogPropsProps = PropDescriptor(_$key___forwardedRef__LogPropsProps); static const String _$key__builder__LogPropsProps = 'LogPropsProps.builder'; - static const String _$key__thisWasClickedLast__LogPropsProps = - 'LogPropsProps.thisWasClickedLast'; + static const String _$key__lastClickedButton__LogPropsProps = + 'LogPropsProps.lastClickedButton'; static const String _$key___forwardedRef__LogPropsProps = 'LogPropsProps._forwardedRef'; static const List $props = [ _$prop__builder__LogPropsProps, - _$prop__thisWasClickedLast__LogPropsProps, + _$prop__lastClickedButton__LogPropsProps, _$prop___forwardedRef__LogPropsProps ]; static const List $propKeys = [ _$key__builder__LogPropsProps, - _$key__thisWasClickedLast__LogPropsProps, + _$key__lastClickedButton__LogPropsProps, _$key___forwardedRef__LogPropsProps ]; } @@ -588,8 +605,8 @@ final UiFactoryConfig<_$$UiForwardRefLogsPropsComplexComponentProps> ' Do not reference it in your code, as it may change at any time.') abstract class _$$UiForwardRefLogsPropsComplexComponentProps extends UiProps with - UiForwardRefLogsPropsComplexFunctionComponentPropsMixin, - $UiForwardRefLogsPropsComplexFunctionComponentPropsMixin, // If this generated mixin is undefined, it's likely because UiForwardRefLogsPropsComplexFunctionComponentPropsMixin is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of UiForwardRefLogsPropsComplexFunctionComponentPropsMixin. + UiForwardRefLogsPropsComplexComponentPropsMixin, + $UiForwardRefLogsPropsComplexComponentPropsMixin, // If this generated mixin is undefined, it's likely because UiForwardRefLogsPropsComplexComponentPropsMixin is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of UiForwardRefLogsPropsComplexComponentPropsMixin. LogPropsProps, $LogPropsProps // If this generated mixin is undefined, it's likely because LogPropsProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of LogPropsProps. implements From 378a58d34b261a401c7961f32542a5d44f52cf63 Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Wed, 5 Aug 2020 08:54:18 -0700 Subject: [PATCH 11/28] Fix CI --- lib/src/component/ref_util.dart | 37 ++++++++----------- test/over_react/component/ref_util_test.dart | 8 ++-- test/vm_tests/builder/codegen_test.dart | 2 +- .../builder/declaration_parsing_test.dart | 2 +- 4 files changed, 22 insertions(+), 27 deletions(-) diff --git a/lib/src/component/ref_util.dart b/lib/src/component/ref_util.dart index 6092e1170..6d22c268b 100644 --- a/lib/src/component/ref_util.dart +++ b/lib/src/component/ref_util.dart @@ -177,11 +177,11 @@ Ref createRef() { /// /// Learn more: . UiFactory Function(UiFactory) forwardRef( - Function(TProps props, Ref ref) wrapperFunction, {String displayName}) { - + Function(TProps props, Ref ref) wrapperFunction, + {String displayName}) { UiFactory wrapWithForwardRef(UiFactory factory) { enforceMinimumComponentVersionFor(factory().componentFactory); - + if (displayName == null) { final componentFactoryType = factory().componentFactory.type; if (componentFactoryType is String) { @@ -197,10 +197,11 @@ UiFactory Function(UiFactory) forwardRef } } } - + Object wrapProps(Map props, Ref ref) { return wrapperFunction(factory(props), ref); } + ReactComponentFactoryProxy hoc = react_interop.forwardRef(wrapProps, displayName: displayName); setComponentTypeMeta(hoc, isHoc: true, parentType: factory().componentFactory); @@ -216,9 +217,6 @@ UiFactory Function(UiFactory) forwardRef /// Automatically passes a [Ref] through a component to one of its children. /// -/// > __NOTE:__ This should only be used to wrap components that extend from `Component2` -/// > or components using the function syntax. -/// /// __Example 1:__ Forwarding refs to DOM components /// /// ```dart @@ -283,20 +281,20 @@ UiFactory Function(UiFactory) forwardRef /// /// // ---------- Wrapping a Class Component ---------- /// // Here you have two options: -/// // - Option 1: Use the class component's UI Factory to construct a function +/// // - Option 1: Use the class component's UI Factory to construct a UI /// // component config. This needs to be done because the builder recognizes /// // `LogPropsProps` as already consumed (by the class component). /// // /// // - Option 2: Create a new props class. This just works around the issue /// // described for Option 1 because it is creating a new props class, but it -/// // only needs to mixin in the props mixins that the original props class used. +/// // only needs to mix in the props mixins that the original props class used. /// // -/// // Choosing between the options is likely circumstantial or at least preferential -/// // if all else is the same. The advantage to Option 1 is that if the class component -/// // has numerous mixins, it is much more concise to create the function component -/// // config. Option 2 has the benefit that it matches the declaration of standard +/// // Choosing between the options is likely circumstantial or preferential. +/// // The advantage to Option 1 is that if the class component has numerous mixins, +/// // it is much more concise to create the function component config. +/// // Option 2 has the benefit that it matches the declaration of standard /// // function components (which `uiForwardRef` returns). Additionally, Option 2 -/// // illustrates how one could add additional props to the wrapping function component. +/// // illustrates how one could add additional props to the wrapped function component. /// /// // Option 1 Example /// final LogsPropsComponent = uiForwardRef((props, ref) { @@ -449,8 +447,7 @@ UiFactory Function(UiFactory) forwardRef /// /// Learn more: . UiFactory uiForwardRef( - dynamic Function(TProps props, dynamic ref) functionComponent, - UiFactoryConfig config) { + dynamic Function(TProps props, dynamic ref) functionComponent, UiFactoryConfig config) { ArgumentError.checkNotNull(config, 'config'); // ignore: invalid_use_of_protected_member @@ -475,12 +472,10 @@ UiFactory uiForwardRef( if (propsFactory == null) { if (TProps != UiProps && TProps != GenericUiProps) { - throw ArgumentError( - 'config.propsFactory must be provided when using custom props classes'); + throw ArgumentError('config.propsFactory must be provided when using custom props classes'); } - propsFactory = PropsFactory.fromUiFactory( - ([backingMap]) => GenericUiProps(factory, backingMap)) - as PropsFactory; + propsFactory = PropsFactory.fromUiFactory(([backingMap]) => GenericUiProps(factory, backingMap)) + as PropsFactory; } TProps _uiFactory([Map backingMap]) { diff --git a/test/over_react/component/ref_util_test.dart b/test/over_react/component/ref_util_test.dart index 064957d1b..eddea6749 100644 --- a/test/over_react/component/ref_util_test.dart +++ b/test/over_react/component/ref_util_test.dart @@ -47,7 +47,7 @@ main() { }); group('on a function component child', () { - standardForwardRefTest(BasicChild, verifyRefValue: (ref) { + testForwardRefWith(BasicChild, verifyRefValue: (ref) { expect(ref, TypeMatcher()); }, useUiForwardRef: true); @@ -180,7 +180,7 @@ void commonRefForwardingTests({bool useUiForwardRef = false}) { group('- commonRefForwardingTests -', () { group('on a component with a dom component child', () { - standardForwardRefTest(Dom.span, verifyRefValue: (ref) { + testForwardRefWith(Dom.span, verifyRefValue: (ref) { expect(ref, TypeMatcher()); }, useUiForwardRef: useUiForwardRef); @@ -227,7 +227,7 @@ void commonRefForwardingTests({bool useUiForwardRef = false}) { }); group('on a component with a dart component child', () { - standardForwardRefTest(Basic, verifyRefValue: (ref) { + testForwardRefWith(Basic, verifyRefValue: (ref) { expect(ref, TypeMatcher()); }, useUiForwardRef: useUiForwardRef); @@ -267,7 +267,7 @@ void commonRefForwardingTests({bool useUiForwardRef = false}) { const displayName = 'AVerySpecificDisplayName'; -void standardForwardRefTest(dynamic factory, +void testForwardRefWith(dynamic factory, {void Function(dynamic refValue) verifyRefValue, useUiForwardRef = false}) { test('- passes a ref through the parent to its child', () { UiFactory BasicForwarded = useUiForwardRef diff --git a/test/vm_tests/builder/codegen_test.dart b/test/vm_tests/builder/codegen_test.dart index fad51b903..f54e03e8c 100644 --- a/test/vm_tests/builder/codegen_test.dart +++ b/test/vm_tests/builder/codegen_test.dart @@ -707,7 +707,7 @@ main() { (props) { return Dom.div()(); }, - $BarPropsMixinConfig, // ignore: undefined_identifier + $BarConfig, // ignore: undefined_identifier ); final Foo = uiFunction( diff --git a/test/vm_tests/builder/declaration_parsing_test.dart b/test/vm_tests/builder/declaration_parsing_test.dart index 8415f7f0d..35b199f0d 100644 --- a/test/vm_tests/builder/declaration_parsing_test.dart +++ b/test/vm_tests/builder/declaration_parsing_test.dart @@ -1665,7 +1665,7 @@ main() { (props) { return Dom.div()(); }, - \$FooConfig, // ignore: undefined_identifier + \$BarConfig, // ignore: undefined_identifier )); final Foo2 = someHOC(uiFunction( From 7d288eb4ecab102694bb6cbd19d8ae58d23e74e1 Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Wed, 5 Aug 2020 09:43:54 -0700 Subject: [PATCH 12/28] Fix breakages from analyzer 0.39.16 --- .../lib/src/diagnostic/arrow_function_prop.dart | 1 - .../lib/src/diagnostic/boilerplate_validator.dart | 10 ---------- .../lib/src/diagnostic/missing_cascade_parens.dart | 8 ++++---- web/component2/src/demos/ref.dart | 2 +- 4 files changed, 5 insertions(+), 16 deletions(-) diff --git a/tools/analyzer_plugin/lib/src/diagnostic/arrow_function_prop.dart b/tools/analyzer_plugin/lib/src/diagnostic/arrow_function_prop.dart index fa10b8ca4..a45484421 100644 --- a/tools/analyzer_plugin/lib/src/diagnostic/arrow_function_prop.dart +++ b/tools/analyzer_plugin/lib/src/diagnostic/arrow_function_prop.dart @@ -3,7 +3,6 @@ import 'package:analyzer_plugin/protocol/protocol_common.dart'; import 'package:analyzer_plugin/utilities/fixes/fixes.dart'; import 'package:over_react_analyzer_plugin/src/diagnostic_contributor.dart'; import 'package:over_react_analyzer_plugin/src/fluent_interface_util.dart'; -import 'package:over_react_analyzer_plugin/src/util/ast_util.dart'; const _desc = "Props can't be cascaded after unparenthesized arrow functions."; // diff --git a/tools/analyzer_plugin/lib/src/diagnostic/boilerplate_validator.dart b/tools/analyzer_plugin/lib/src/diagnostic/boilerplate_validator.dart index cf44a8082..03ec8631f 100644 --- a/tools/analyzer_plugin/lib/src/diagnostic/boilerplate_validator.dart +++ b/tools/analyzer_plugin/lib/src/diagnostic/boilerplate_validator.dart @@ -253,16 +253,6 @@ extension on SourceSpan { SourceRange asRangeOrEmpty() => this == null ? SourceRange.EMPTY : asRange(); } -extension on Iterable { - void forEachIndexed(void Function(E, int) callback) { - var i = 0; - forEach((e) { - callback(e, i); - i++; - }); - } -} - // TODO use the version from over_react instead after initial release Iterable getNonGeneratedParts(CompilationUnit libraryUnit) { return libraryUnit.directives diff --git a/tools/analyzer_plugin/lib/src/diagnostic/missing_cascade_parens.dart b/tools/analyzer_plugin/lib/src/diagnostic/missing_cascade_parens.dart index b1a3a4c94..0d1b06c94 100644 --- a/tools/analyzer_plugin/lib/src/diagnostic/missing_cascade_parens.dart +++ b/tools/analyzer_plugin/lib/src/diagnostic/missing_cascade_parens.dart @@ -1,6 +1,6 @@ // ignore: deprecated_member_use import 'package:analyzer/analyzer.dart' - show CompileTimeErrorCode, NodeLocator, StaticTypeWarningCode, StaticWarningCode; + show CompileTimeErrorCode, NodeLocator; import 'package:analyzer/dart/ast/ast.dart'; import 'package:over_react_analyzer_plugin/src/util/react_types.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; @@ -63,8 +63,8 @@ class MissingCascadeParensDiagnostic extends DiagnosticContributor { computeErrors(result, collector) async { for (final error in result.errors) { final isBadFunction = const { - StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION, - StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION, + CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION, + CompileTimeErrorCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION, }.contains(error.errorCode); final isBadArity = const { CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS, @@ -72,7 +72,7 @@ class MissingCascadeParensDiagnostic extends DiagnosticContributor { CompileTimeErrorCode.EXTRA_POSITIONAL_ARGUMENTS, }.contains(error.errorCode); final isVoidUsage = const { - StaticWarningCode.USE_OF_VOID_RESULT, + CompileTimeErrorCode.USE_OF_VOID_RESULT, }.contains(error.errorCode); if (isBadFunction || isBadArity || isVoidUsage) { diff --git a/web/component2/src/demos/ref.dart b/web/component2/src/demos/ref.dart index 9c5597d97..830e26aca 100644 --- a/web/component2/src/demos/ref.dart +++ b/web/component2/src/demos/ref.dart @@ -179,7 +179,7 @@ mixin RefDemoProps on UiProps {} final RefDemoContainer = uiFunction( (props) { - // `uiForwardRef` Refs + // `uiForwardRef` Refs final buttonNodeRefForSimpleFunctionComponent = createRef(); final buttonNodeRefForComplexFunctionComponent = createRef(); final buttonNodeRefForSimpleComponent = createRef(); From 861fda75be05439bfdb8b2a99b559387e329a14a Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Wed, 5 Aug 2020 10:15:51 -0700 Subject: [PATCH 13/28] Format --- .../lib/src/diagnostic/missing_cascade_parens.dart | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tools/analyzer_plugin/lib/src/diagnostic/missing_cascade_parens.dart b/tools/analyzer_plugin/lib/src/diagnostic/missing_cascade_parens.dart index 0d1b06c94..9695cd795 100644 --- a/tools/analyzer_plugin/lib/src/diagnostic/missing_cascade_parens.dart +++ b/tools/analyzer_plugin/lib/src/diagnostic/missing_cascade_parens.dart @@ -1,6 +1,5 @@ // ignore: deprecated_member_use -import 'package:analyzer/analyzer.dart' - show CompileTimeErrorCode, NodeLocator; +import 'package:analyzer/analyzer.dart' show CompileTimeErrorCode, NodeLocator; import 'package:analyzer/dart/ast/ast.dart'; import 'package:over_react_analyzer_plugin/src/util/react_types.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; From fa6eb84d5f8f98b933ada552a34675d6ae2b152b Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Thu, 6 Aug 2020 08:32:41 -0700 Subject: [PATCH 14/28] Address feedback --- example/hooks/use_context_example.dart | 2 - .../hooks/use_imperative_handle_example.dart | 15 +- .../codegen/typed_map_impl_generator.dart | 2 +- lib/src/builder/parsing/ast_util.dart | 32 +- lib/src/builder/parsing/declarations.dart | 3 +- .../parsing/declarations_from_members.dart | 8 +- lib/src/builder/parsing/members/factory.dart | 9 +- lib/src/builder/parsing/members_from_ast.dart | 4 +- lib/src/component/ref_util.dart | 281 +++++++----------- .../component_declaration/component_base.dart | 8 +- .../component/forward_ref_test.dart | 164 ---------- .../forward_ref_test.over_react.g.dart | 157 ---------- test/over_react/component/ref_util_test.dart | 6 +- .../component_type_checking_test.dart | 3 +- test/vm_tests/builder/codegen_test.dart | 112 +++++-- .../builder/parsing/ast_util_test.dart | 8 +- .../builder/parsing/members_test.dart | 4 +- web/component2/src/demos/ref.dart | 29 +- 18 files changed, 250 insertions(+), 597 deletions(-) delete mode 100644 test/over_react/component/forward_ref_test.dart delete mode 100644 test/over_react/component/forward_ref_test.over_react.g.dart diff --git a/example/hooks/use_context_example.dart b/example/hooks/use_context_example.dart index 5f099a1cc..97f71d6f4 100644 --- a/example/hooks/use_context_example.dart +++ b/example/hooks/use_context_example.dart @@ -45,11 +45,9 @@ mixin NewContextProviderProps on UiProps {} final NewContextProvider = uiFunction( (props) { final renderCount = useState(0); - final complexMap = useState(false); _onButtonClick(event) { renderCount.setWithUpdater((oldValue) => oldValue + 1); - complexMap.set(false); } final provideMap = {'renderCount': renderCount.value}; diff --git a/example/hooks/use_imperative_handle_example.dart b/example/hooks/use_imperative_handle_example.dart index 65e9f31c1..da7f566bb 100644 --- a/example/hooks/use_imperative_handle_example.dart +++ b/example/hooks/use_imperative_handle_example.dart @@ -31,13 +31,14 @@ class FancyInputApi { FancyInputApi(this.focus); } -UiFactory FancyInput = - forwardRef((props, ref) { - return (_FancyInput() - ..forwardedRef = ref - ..addProps(props) - )(); -})(_FancyInput); +UiFactory FancyInput = uiForwardRef((props, ref) { + return (_FancyInput() + ..forwardedRef = ref + ..addProps(props) + )(); + }, + _FancyInput.asForwardRefConfig(displayName: 'FancyInputForwardRef') +); UiFactory _FancyInput = uiFunction( (props) { diff --git a/lib/src/builder/codegen/typed_map_impl_generator.dart b/lib/src/builder/codegen/typed_map_impl_generator.dart index 8e860d278..9c9a904f9 100644 --- a/lib/src/builder/codegen/typed_map_impl_generator.dart +++ b/lib/src/builder/codegen/typed_map_impl_generator.dart @@ -371,7 +371,7 @@ class _TypedMapImplGenerator extends TypedMapImplGenerator { member = declaration.props.either, isProps = true, componentFactoryName = 'null', - isFunctionComponentDeclaration = declaration.factories.first.isFunctionComponentFactory, + isFunctionComponentDeclaration = declaration.factories.first.shouldGenerateConfig, version = declaration.version; @override diff --git a/lib/src/builder/parsing/ast_util.dart b/lib/src/builder/parsing/ast_util.dart index e1d10934c..ce69ce2b7 100644 --- a/lib/src/builder/parsing/ast_util.dart +++ b/lib/src/builder/parsing/ast_util.dart @@ -43,30 +43,15 @@ extension InitializerHelperTopLevel on TopLevelVariableDeclaration { VariableDeclaration get firstVariable => variables.firstVariable; /// Returns whether or not the config argument of a Function type is generated. - bool get hasGeneratedConfigArg { + bool get usesAGeneratedConfig { return firstInitializer != null && anyDescendantIdentifiers(firstInitializer, (identifier) { final uiFactoryDeclaration = identifier.thisOrAncestorOfType(); - final methodInvocation = identifier.thisOrAncestorOfType(); - if (methodInvocation != null && uiFactoryDeclaration != null) { - final args = methodInvocation.argumentList?.arguments; - if (args == null || args.length < 2) return false; - - if (args[1] is SimpleIdentifier) { - return args[1].toString() == '\$${uiFactoryDeclaration.name.name}Config'; - } else if (args[1] is PrefixedIdentifier) { - return args[1] - .childEntities - .where((child) { - return child is SimpleIdentifier && - child.name == '\$${uiFactoryDeclaration.name.name}Config'; - }) - .toList() - .isNotEmpty; - } - } - - return false; + + return firstInitializer != null && + anyDescendantIdentifiers(firstInitializer, (identifier) { + return identifier.nameWithoutPrefix == '\$${uiFactoryDeclaration.name.name}Config'; + }); }); } } @@ -95,11 +80,6 @@ extension NameHelper on Identifier { } bool get isFunctionType => ['uiFunction', 'uiForwardRef', 'uiJsComponent'].contains(this.name); - - bool get isAttachedToAGeneratedUiFactory { - final uiFactoryDeclaration = this.thisOrAncestorOfType(); - return uiFactoryDeclaration?.hasGeneratedConfigArg; - } } /// Utilities related to detecting a super class on a [MixinDeclaration] diff --git a/lib/src/builder/parsing/declarations.dart b/lib/src/builder/parsing/declarations.dart index 0c81667be..8215961c3 100644 --- a/lib/src/builder/parsing/declarations.dart +++ b/lib/src/builder/parsing/declarations.dart @@ -362,8 +362,7 @@ class FactoryGroup { return factoriesInitializedToIdentifier.first; } - final functionComponentFactories = - factories.where((factory) => factory.isFunctionComponentFactory); + final functionComponentFactories = factories.where((factory) => factory.shouldGenerateConfig); if (functionComponentFactories.isNotEmpty) { return functionComponentFactories.first; } diff --git a/lib/src/builder/parsing/declarations_from_members.dart b/lib/src/builder/parsing/declarations_from_members.dart index 2f242cf52..59f74f1d1 100644 --- a/lib/src/builder/parsing/declarations_from_members.dart +++ b/lib/src/builder/parsing/declarations_from_members.dart @@ -243,12 +243,10 @@ Iterable getBoilerplateDeclarations( } } - if (factory.isFunctionComponentFactory) { + if (factory.shouldGenerateConfig) { final factories = factoryGroups.firstWhere((group) => group.bestFactory == factory); - final generatedFactories = factories.factories.where((factory) => - factory.node.hasGeneratedConfigArg && - factory.isFunctionComponentFactory && - factory.versionConfidences.maxConfidence.shouldGenerate); + final generatedFactories = factories.factories + .where((factory) => factory.versionConfidences.maxConfidence.shouldGenerate); final associatedProps = getPropsForFunctionComponent(members.props, members.propsMixins, factory); if (generatedFactories.isNotEmpty && diff --git a/lib/src/builder/parsing/members/factory.dart b/lib/src/builder/parsing/members/factory.dart index 4396ee52d..79b50ed28 100644 --- a/lib/src/builder/parsing/members/factory.dart +++ b/lib/src/builder/parsing/members/factory.dart @@ -38,7 +38,7 @@ class BoilerplateFactory extends BoilerplateMember { } } - if (isFunctionComponentFactory) { + if (shouldGenerateConfig) { final uiFunctionInvocation = getDescendantIdentifier( node.variables.firstInitializer, (identifier) => identifier.isFunctionType); final methodInvocation = uiFunctionInvocation.thisOrAncestorOfType(); @@ -53,10 +53,7 @@ class BoilerplateFactory extends BoilerplateMember { bool get hasFactoryAnnotation => node.hasAnnotationWithName('Factory'); - bool get isFunctionComponentFactory => - node.variables.firstInitializer != null && - anyDescendantIdentifiers( - node.variables.firstInitializer, (identifier) => identifier.isFunctionType); + bool get shouldGenerateConfig => node.usesAGeneratedConfig; /// Verifies the correct implementation of a boilerplate factory /// @@ -94,7 +91,7 @@ class BoilerplateFactory extends BoilerplateMember { anyDescendantIdentifiers( initializer, (identifier) => identifier.name == generatedFactoryName); - if (!referencesGeneratedFactory && !isFunctionComponentFactory) { + if (!referencesGeneratedFactory && !shouldGenerateConfig) { errorCollector.addError( 'Factory variables are stubs for the generated factories, and must ' 'be initialized with or otherwise reference the generated factory. Should be: `$factoryName = $generatedFactoryName`', diff --git a/lib/src/builder/parsing/members_from_ast.dart b/lib/src/builder/parsing/members_from_ast.dart index a44046782..64be11acc 100644 --- a/lib/src/builder/parsing/members_from_ast.dart +++ b/lib/src/builder/parsing/members_from_ast.dart @@ -169,9 +169,7 @@ class _BoilerplateMemberDetector { } final rightHandSide = node.variables.firstInitializer; - if (rightHandSide != null && - anyDescendantIdentifiers( - rightHandSide, (identifier) => identifier.isAttachedToAGeneratedUiFactory)) { + if (rightHandSide != null && node.usesAGeneratedConfig) { onFactory(BoilerplateFactory( node, VersionConfidences( diff --git a/lib/src/component/ref_util.dart b/lib/src/component/ref_util.dart index 6d22c268b..934f460d1 100644 --- a/lib/src/component/ref_util.dart +++ b/lib/src/component/ref_util.dart @@ -176,6 +176,7 @@ Ref createRef() { /// ``` /// /// Learn more: . +@Deprecated('Use uiForwardRef instead. Will be removed in 4.0.0') UiFactory Function(UiFactory) forwardRef( Function(TProps props, Ref ref) wrapperFunction, {String displayName}) { @@ -215,75 +216,120 @@ UiFactory Function(UiFactory) forwardRef return wrapWithForwardRef; } -/// Automatically passes a [Ref] through a component to one of its children. +/// Creates a function component capable of forwarding its ref to +/// a component it renders. /// -/// __Example 1:__ Forwarding refs to DOM components +/// Learn more: . +/// +/// ### Example 1: Updating a function component to forward a ref: +/// +/// _This example mirrors the JS example in the link above._ /// +/// Consider a `FancyButton` function component that renders the native button DOM element: /// ```dart -/// import 'dart:html'; -/// import 'package:over_react/over_react.dart'; -/// import 'package:over_react/react_dom.dart' as react_dom; +/// mixin FancyButtonProps on UiProps {} /// -/// // ---------- Component Definition ---------- +/// UiFactory FancyButton = uiFunction( +/// (props) { +/// return (Dom.button() +/// ..className = 'FancyButton' +/// )(props.children); +/// }, +/// $FancyButtonConfig, // ignore: undefined_identifier +/// ); +/// ``` +/// +/// Normally, you can't set a ref on function components, but if you change +/// [uiFunction] to `uiForwardRef`, you'll get a new `ref` argument that will be +/// populate with any ref set on `FancyButton`. We This ref can then be +/// "forwarded" to some other component. /// -/// final FancyButton = uiForwardRef((props, ref) { -/// final classes = ClassNameBuilder.fromProps(props)..add('FancyButton'); +/// ```dart +/// mixin FancyButtonProps on UiProps {} /// +/// UiFactory FancyButton = uiForwardRef( +/// (props, ref) { /// return (Dom.button() -/// ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) -/// ..className = classes.toClassName() /// ..ref = ref -/// )('Click me!'); +/// ..className = 'FancyButton' +/// )(props.children); /// }, -/// Dom.button.asForwardRefConfig(displayName: 'FancyButton'), +/// $FancyButtonConfig, // ignore: undefined_identifier /// ); /// -/// // ---------- Component Consumption ---------- +/// usageExample() { +/// // You can now get a ref directly to the DOM button: +/// final ref = createRef(); +/// return (FancyButton()..ref = ref)(); +/// } +/// ``` /// -/// void main() { -/// final ref = createRef(); +/// ### Example 2: Creating a [higher-order component](https://reactjs.org/docs/higher-order-components.html) +/// that forwards its ref to the wrapped component. /// -/// react_dom.render( -/// (FancyButton() +/// ```dart +/// /// Wraps a component ([factoryToWrap]) in a new component that logs when rendered. +/// UiFactory withLogging(UiFactory factoryToWrap) { +/// return uiForwardRef( +/// (props, ref) { +/// useEffect(() => 'the component rendered!'); +/// +/// return (factoryToWrap() +/// ..addAll(props) /// ..ref = ref -/// ..onClick = (_) { -/// print(ref.current.outerHtml); -/// } -/// )(), -/// querySelector('#idOfSomeNodeInTheDom') +/// )(props.children); +/// }, +/// factoryToBeWrapped.asForwardRefConfig( +/// displayName: 'withLogging(${getDisplayName(factoryToWrap)})', +/// ), /// ); -/// -/// // You can still get a ref directly to the DOM button: -/// final buttonNode = ref.current; /// } +/// +/// UiFactory FancyButton = ...; +/// +/// /// This can be used just like FancyButton, and setting a ref on it will work the same! +/// UiFactory FancyButtonWithLogging = withLogging(FancyButton); /// ``` /// -/// __Example 2:__ Forwarding refs in higher-order (non-function) components +/// ### Example 3: Exposing inner refs in class components /// -/// ```dart -/// import 'dart:html'; -/// import 'package:over_react/over_react.dart'; -/// import 'package:over_react/react_dom.dart' as react_dom; +/// While it's usually easier to pass `uiForwardRef`'s `ref` argument directly +/// to the desired component, sometimes it's nested within a class component +/// that can't forward refs itself, and it's non-trivial to update that class +/// component to a function component. /// -/// // ---------- Component Definitions ---------- +/// In this case, you can pass the ref to the class component as a custom prop, +/// and have the class component forward it to the right location. /// -/// final FancyButton = uiForwardRef((props, ref) { -/// final classes = ClassNameBuilder.fromProps(props)..add('FancyButton'); +/// Here, we'll make our class component factory private and only expose a +/// version wrapped in `uiForwardRef`: /// -/// return (Dom.button() -/// ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) -/// ..className = classes.toClassName() -/// ..ref = ref -/// )('Click me!'); -/// }, -/// Dom.button.asForwardRefConfig(displayName: 'FancyButton'), -/// ); +/// ```dart +/// UiFactory _Foo = _$_Foo; // ignore: undefined_identifier +/// mixin FooProps on UiProps { +/// // Private since we only use this to pass along the ref provided in +/// // uiForwardRef. +/// // +/// // Consumers will effectively be setting this when they set `ref` on the public factory. +/// dynamic _inputRef; +/// } +/// class FooComponent extends UiComponent2 { +/// @override +/// render() { +/// return Dom.div()( +/// (Dom.input() +/// ..type = 'text' +/// ..ref = _inputRef +/// )(); +/// ) +/// } +/// } /// /// // ---------- Wrapping a Class Component ---------- /// // Here you have two options: -/// // - Option 1: Use the class component's UI Factory to construct a UI -/// // component config. This needs to be done because the builder recognizes -/// // `LogPropsProps` as already consumed (by the class component). +/// // - Option 1: Use the class component's factory as the UiFactoryConfig arg. +/// // This needs to be done because the builder recognizes +/// // `FooProps` as already consumed (by the class component). /// // /// // - Option 2: Create a new props class. This just works around the issue /// // described for Option 1 because it is creating a new props class, but it @@ -296,15 +342,18 @@ UiFactory Function(UiFactory) forwardRef /// // function components (which `uiForwardRef` returns). Additionally, Option 2 /// // illustrates how one could add additional props to the wrapped function component. /// +/// // /// // Option 1 Example -/// final LogsPropsComponent = uiForwardRef((props, ref) { -/// return (_LogProps() +/// UiFactory Foo = uiForwardRef((props, ref) { +/// return (_Foo() /// ..addProps(props) -/// .._forwardedRef = ref)(); +/// .._inputRef = ref +/// )(); /// }, -/// _LogProps.asForwardRefConfig(displayName: 'LogsProps'), +/// _Foo.asForwardRefConfig(), /// ); /// +/// // /// // Option 2 Example: /// /// // This is not necessary but is just in place to illustrate that more props @@ -313,139 +362,17 @@ UiFactory Function(UiFactory) forwardRef /// String anExampleAdditionalProp; /// } /// -/// class LogsPropsComponent2Props = UiProps with AnotherPropsMixin, LogPropsProps; +/// class Foo2Props = UiProps with AnotherPropsMixin, FooProps; +/// final Foo2 = uiForwardRef((props, ref) { +/// print(props.anExampleAdditionalProp); /// -/// final LogsPropsComponent2 = uiForwardRef((props, ref) { -/// useEffect(() { -/// print(props.anExampleAdditionalProp); -/// }); -/// -/// return (_LogProps() +/// return (_Foo() /// ..addProps(props) -/// .._forwardedRef = ref)(); +/// .._inputRef = ref +/// )(); /// }, -/// $LogsPropsComponent2Config +/// $Foo2Config, // ignore: undefined_identifier /// ); -/// -/// UiFactory _LogProps = _$_LogProps; -/// -/// mixin LogPropsProps on UiProps { -/// BuilderOnlyUiFactory builder; -/// -/// // Private since we only use this to pass along the value of `ref` to -/// // the return value of forwardRef. -/// // -/// // Consumers can set this private field value using the public `ref` setter. -/// Ref _forwardedRef; -/// } -/// -/// class LogPropsComponent extends UiComponent2 { -/// @override -/// void componentDidUpdate(Map prevProps, _, [__]) { -/// print('old props: $prevProps'); -/// print('new props: $props'); -/// } -/// -/// @override -/// render() { -/// return (props.builder() -/// ..modifyProps(addUnconsumedDomProps) -/// ..ref = props._forwardedRef -/// )(props.children); -/// } -/// } -/// -/// // ---------- Component Consumption ---------- -/// -/// void main() { -/// final ref = createRef(); -/// -/// react_dom.render( -/// (LogProps() -/// ..builder = FancyButton -/// ..className = 'btn btn-primary' -/// ..ref = ref -/// ..onClick = (_) { -/// print(ref.current.outerHtml); -/// } -/// )(), -/// querySelector('#idOfSomeNodeInTheDom') -/// ); -/// -/// // You can still get a ref directly to the DOM button: -/// final buttonNode = ref.current; -/// } -/// ``` -/// -/// __Example 3:__ Forwarding refs in higher-order (all function) components -/// -/// ```dart -/// import 'dart:html'; -/// import 'package:over_react/over_react.dart'; -/// import 'package:over_react/react_dom.dart' as react_dom; -/// import 'package:react/hooks.dart'; -/// -/// // ---------- Component Definitions ---------- -/// -/// final FancyButton = uiForwardRef((props, ref) { -/// final classes = ClassNameBuilder.fromProps(props)..add('FancyButton'); -/// -/// return (Dom.button() -/// ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) -/// ..className = classes.toClassName() -/// ..ref = ref -/// )('Click me!'); -/// }, -/// Dom.button.asForwardRefConfig(displayName: 'FancyButton'), -/// ); -/// -/// mixin LogPropsProps on UiProps { -/// BuilderOnlyUiFactory builder; -/// } -/// -/// final LogProps = uiForwardRef( -/// (props, ref) { -/// final prevPropsRef = useRef(null); -/// -/// useEffect(() { -/// if (prevPropsRef.current != null) { -/// print('old props: ${prevPropsRef.current}'); -/// print('new props: $props'); -/// } -/// -/// prevPropsRef.current = props; -/// }); -/// -/// return ((props.builder() -/// ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) -/// ..ref = ref)(props.children)); -/// }, -/// $LogPropsConfig, // ignore: undefined_identifier -/// ); -/// -/// // ---------- Component Consumption ---------- -/// -/// void main() { -/// final ref = createRef(); -/// -/// react_dom.render( -/// (LogProps() -/// ..builder = FancyButton -/// ..className = 'btn btn-primary' -/// ..ref = ref -/// ..onClick = (_) { -/// print(ref.current.outerHtml); -/// } -/// )(), -/// querySelector('#idOfSomeNodeInTheDom') -/// ); -/// -/// // You can still get a ref directly to the DOM button: -/// final buttonNode = ref.current; -/// } -/// ``` -/// -/// Learn more: . UiFactory uiForwardRef( dynamic Function(TProps props, dynamic ref) functionComponent, UiFactoryConfig config) { ArgumentError.checkNotNull(config, 'config'); diff --git a/lib/src/component_declaration/component_base.dart b/lib/src/component_declaration/component_base.dart index 412761385..d8b9ff9e5 100644 --- a/lib/src/component_declaration/component_base.dart +++ b/lib/src/component_declaration/component_base.dart @@ -93,8 +93,12 @@ ReactDartComponentFactoryProxy registerAbstractComponent(Type abstractComponentC /// via a fluent-style builder interface. typedef TProps UiFactory([Map backingProps]); -extension UiFactoryHelpers on UiFactory { - UiFactoryConfig asForwardRefConfig({String displayName}) => UiFactoryConfig(propsFactory: PropsFactory.fromUiFactory(this), displayName: displayName); +extension UiFactoryHelpers on UiFactory { + /// Generates the configuration necessary to construct a UiFactory while invoking + /// `uiForwardRef` with a props class that has already been consumed. + /// + /// See `uiForwardRef` for examples and context. + UiFactoryConfig asForwardRefConfig({String displayName}) => UiFactoryConfig(propsFactory: PropsFactory.fromUiFactory(this), displayName: displayName); } /// A utility variation on [UiFactory], __without__ a `backingProps` parameter. diff --git a/test/over_react/component/forward_ref_test.dart b/test/over_react/component/forward_ref_test.dart deleted file mode 100644 index 471d3a772..000000000 --- a/test/over_react/component/forward_ref_test.dart +++ /dev/null @@ -1,164 +0,0 @@ -// Copyright 2019 Workiva Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -library forward_ref_test; - -import 'dart:html'; -import 'dart:js_util'; - -import 'package:test/test.dart'; -import 'package:over_react/over_react.dart'; -import 'package:over_react/src/component/dom_components.dart'; - -import '../../test_util/test_util.dart'; -import '../component/fixtures/basic_child_component.dart'; -import 'fixtures/basic_ui_component.dart'; - -part 'forward_ref_test.over_react.g.dart'; - -main() { - group('forward ref -', () { - test('errors when wrapping a UiComponent', () { - expect(() => forwardRef((props, ref) { - return (BasicUiComponent() - ..ref = ref - )(); - })(BasicUiComponent), throwsArgumentError); - }); - - group('on a component with a dom component child', () { - forwardRefTest(Dom.span, verifyRefValue: (ref) { - expect(ref, TypeMatcher()); - }); - - test('- using DomProps', () { - UiFactory DivForwarded = forwardRef((props, ref) { - return (Dom.div() - ..ref = ref - )(); - })(Dom.div); - - final Ref refObject = createRef(); - - mount((DivForwarded() - ..ref = refObject - )()); - - expect(refObject.current, TypeMatcher()); - }); - - group('- sets displayName on the rendered component as expected', () { - test('when displayName argument is not passed to forwardRef', () { - UiFactory DivForwarded = forwardRef((props, ref) { - return (Dom.div() - ..ref = ref - )(); - })(Dom.div); - - final refObject = createRef(); - final vDomElement = (DivForwarded()..ref = refObject)(); - - expect(getProperty(getProperty(vDomElement.type, 'render'), 'displayName'), 'div'); - }); - - test('when displayName argument is passed to forwardRef', () { - UiFactory DivForwarded = forwardRef((props, ref) { - return (Dom.div() - ..ref = ref - )(); - }, displayName: 'SomethingCustom')(Dom.div); - - final refObject = createRef(); - final vDomElement = (DivForwarded()..ref = refObject)(); - - expect(getProperty(getProperty(vDomElement.type, 'render'), 'displayName'), 'SomethingCustom'); - }); - }); - }); - - group('on a component with a dart component child', () { - forwardRefTest(BasicChild, verifyRefValue: (ref) { - expect(ref, TypeMatcher()); - }); - - group('- sets displayName on the rendered component as expected', () { - test('when displayName argument is not passed to forwardRef', () { - UiFactory BasicForwarded = forwardRef((props, ref) { - return (BasicChild()..ref = ref)(); - })(Basic); - - final Ref refObject = createRef(); - final vDomElement = (BasicForwarded()..ref = refObject)(); - - expect(getProperty(getProperty(vDomElement.type, 'render'), 'displayName'), 'Basic'); - }); - - test('when displayName argument is passed to forwardRef', () { - UiFactory BasicForwarded = forwardRef((props, ref) { - return (BasicChild()..ref = ref)(); - }, displayName: 'BasicForwarded')(Basic); - - final Ref refObject = createRef(); - final vDomElement = (BasicForwarded()..ref = refObject)(); - - expect(getProperty(getProperty(vDomElement.type, 'render'), 'displayName'), 'BasicForwarded'); - }); - }); - }); - }); -} - -void forwardRefTest(dynamic factory, {void Function(dynamic refValue) verifyRefValue}) { - test('- passes a ref through the parent to its child', () { - UiFactory BasicForwarded = forwardRef((props, ref) { - return (factory() - ..ref = ref - ..id = props.childId - )(); - })(Basic); - - final Ref refObject = createRef(); - - mount((BasicForwarded() - ..ref = refObject - ..childId = 'test' - )()); - - // component props are accessed differently depending on if it is a dom component - // or a dart component - String idValue; - if (refObject.current is Element) { - idValue = refObject.current.id; - } else { - idValue = refObject.current.props['id']; - } - - expect(idValue, equals('test'), reason: 'child component should have access to parent props'); - verifyRefValue(refObject.current); - }); -} - -@Factory() -UiFactory Basic = _$Basic; - -@Props() -class _$BasicProps extends UiProps { - String childId; -} - -@Component2() -class BasicComponent extends UiComponent2 { - @override - render() => 'basic component'; -} diff --git a/test/over_react/component/forward_ref_test.over_react.g.dart b/test/over_react/component/forward_ref_test.over_react.g.dart deleted file mode 100644 index aca31c8cf..000000000 --- a/test/over_react/component/forward_ref_test.over_react.g.dart +++ /dev/null @@ -1,157 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -// ignore_for_file: deprecated_member_use_from_same_package, unnecessary_null_in_if_null_operators, prefer_null_aware_operators -part of 'forward_ref_test.dart'; - -// ************************************************************************** -// OverReactBuilder (package:over_react/src/builder.dart) -// ************************************************************************** - -// React component factory implementation. -// -// Registers component implementation and links type meta to builder factory. -final $BasicComponentFactory = registerComponent2( - () => _$BasicComponent(), - builderFactory: _$Basic, - componentClass: BasicComponent, - isWrapper: false, - parentType: null, - displayName: 'Basic', -); - -abstract class _$BasicPropsAccessorsMixin implements _$BasicProps { - @override - Map get props; - - /// - @override - String get childId => - props[_$key__childId___$BasicProps] ?? - null; // Add ` ?? null` to workaround DDC bug: ; - /// - @override - set childId(String value) => props[_$key__childId___$BasicProps] = value; - /* GENERATED CONSTANTS */ - static const PropDescriptor _$prop__childId___$BasicProps = - PropDescriptor(_$key__childId___$BasicProps); - static const String _$key__childId___$BasicProps = 'BasicProps.childId'; - - static const List $props = [_$prop__childId___$BasicProps]; - static const List $propKeys = [_$key__childId___$BasicProps]; -} - -const PropsMeta _$metaForBasicProps = PropsMeta( - fields: _$BasicPropsAccessorsMixin.$props, - keys: _$BasicPropsAccessorsMixin.$propKeys, -); - -class BasicProps extends _$BasicProps with _$BasicPropsAccessorsMixin { - static const PropsMeta meta = _$metaForBasicProps; -} - -_$$BasicProps _$Basic([Map backingProps]) => backingProps == null - ? _$$BasicProps$JsMap(JsBackedMap()) - : _$$BasicProps(backingProps); - -// Concrete props implementation. -// -// Implements constructor and backing map, and links up to generated component factory. -abstract class _$$BasicProps extends _$BasicProps - with _$BasicPropsAccessorsMixin - implements BasicProps { - _$$BasicProps._(); - - factory _$$BasicProps(Map backingMap) { - if (backingMap == null || backingMap is JsBackedMap) { - return _$$BasicProps$JsMap(backingMap); - } else { - return _$$BasicProps$PlainMap(backingMap); - } - } - - /// Let `UiProps` internals know that this class has been generated. - @override - bool get $isClassGenerated => true; - - /// The `ReactComponentFactory` associated with the component built by this class. - @override - ReactComponentFactoryProxy get componentFactory => - super.componentFactory ?? $BasicComponentFactory; - - /// The default namespace for the prop getters/setters generated for this class. - @override - String get propKeyNamespace => 'BasicProps.'; -} - -// Concrete props implementation that can be backed by any [Map]. -class _$$BasicProps$PlainMap extends _$$BasicProps { - // This initializer of `_props` to an empty map, as well as the reassignment - // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 - _$$BasicProps$PlainMap(Map backingMap) - : this._props = {}, - super._() { - this._props = backingMap ?? {}; - } - - /// The backing props map proxied by this class. - @override - Map get props => _props; - Map _props; -} - -// Concrete props implementation that can only be backed by [JsMap], -// allowing dart2js to compile more optimal code for key-value pair reads/writes. -class _$$BasicProps$JsMap extends _$$BasicProps { - // This initializer of `_props` to an empty map, as well as the reassignment - // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 - _$$BasicProps$JsMap(JsBackedMap backingMap) - : this._props = JsBackedMap(), - super._() { - this._props = backingMap ?? JsBackedMap(); - } - - /// The backing props map proxied by this class. - @override - JsBackedMap get props => _props; - JsBackedMap _props; -} - -// Concrete component implementation mixin. -// -// Implements typed props/state factories, defaults `consumedPropKeys` to the keys -// generated for the associated props class. -class _$BasicComponent extends BasicComponent { - _$$BasicProps$JsMap _cachedTypedProps; - - @override - _$$BasicProps$JsMap get props => _cachedTypedProps; - - @override - set props(Map value) { - assert( - getBackingMap(value) is JsBackedMap, - 'Component2.props should never be set directly in ' - 'production. If this is required for testing, the ' - 'component should be rendered within the test. If ' - 'that does not have the necessary result, the last ' - 'resort is to use typedPropsFactoryJs.'); - super.props = value; - _cachedTypedProps = typedPropsFactoryJs(getBackingMap(value)); - } - - @override - _$$BasicProps$JsMap typedPropsFactoryJs(JsBackedMap backingMap) => - _$$BasicProps$JsMap(backingMap); - - @override - _$$BasicProps typedPropsFactory(Map backingMap) => _$$BasicProps(backingMap); - - /// Let `UiComponent` internals know that this class has been generated. - @override - bool get $isClassGenerated => true; - - /// The default consumed props, taken from _$BasicProps. - /// Used in `*ConsumedProps` methods if [consumedProps] is not overridden. - @override - final List $defaultConsumedProps = const [_$metaForBasicProps]; -} diff --git a/test/over_react/component/ref_util_test.dart b/test/over_react/component/ref_util_test.dart index eddea6749..dd7450ee3 100644 --- a/test/over_react/component/ref_util_test.dart +++ b/test/over_react/component/ref_util_test.dart @@ -11,7 +11,7 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. - +// ignore_for_file: deprecated_member_use_from_same_package library forward_ref_test; import 'dart:html'; @@ -184,7 +184,7 @@ void commonRefForwardingTests({bool useUiForwardRef = false}) { expect(ref, TypeMatcher()); }, useUiForwardRef: useUiForwardRef); - test('- using DomProps', () { + test('- while consuming the `DomProps` props class', () { UiFactory DivForwarded = getFactoryForDiv(); final Ref refObject = createRef(); @@ -297,7 +297,7 @@ void testForwardRefWith(dynamic factory, idValue = refObject.current.props['id']; } - expect(idValue, equals('test'), reason: 'child component should have access to parent props'); + expect(idValue, equals('test'), reason: 'child component receives props passed to it'); verifyRefValue(refObject.current); }); } diff --git a/test/over_react/component_declaration/component_type_checking_test.dart b/test/over_react/component_declaration/component_type_checking_test.dart index ec9e01c62..adece47ea 100644 --- a/test/over_react/component_declaration/component_type_checking_test.dart +++ b/test/over_react/component_declaration/component_type_checking_test.dart @@ -11,13 +11,14 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. - +// ignore_for_file: deprecated_member_use_from_same_package library over_react.component_declaration.component_type_checking_test; import 'package:js/js.dart'; import 'package:over_react/over_react.dart'; import 'package:over_react/over_react_redux.dart' show connect; import 'package:over_react/src/component_declaration/component_type_checking.dart'; +import 'package:over_react/src/component_declaration/component_base.dart'; import 'package:react/react_client.dart'; import 'package:react/react_client/react_interop.dart' as react_interop; import 'package:test/test.dart'; diff --git a/test/vm_tests/builder/codegen_test.dart b/test/vm_tests/builder/codegen_test.dart index f54e03e8c..8609937a8 100644 --- a/test/vm_tests/builder/codegen_test.dart +++ b/test/vm_tests/builder/codegen_test.dart @@ -656,7 +656,7 @@ main() { testStaticMetaField('abstract state', OverReactSrc.abstractState()); }); - group('and generates props config for function components', () { + group('and generates props config for function components constructed with', () { String generatedConfig(String propsName, String factoryName) { return 'final UiFactoryConfig<_\$\$$propsName> ' '\$${factoryName}Config = UiFactoryConfig(\n' @@ -696,49 +696,50 @@ main() { '}\n'; } - test('with multiple props mixins and function components in file', () { - setUpAndGenerate(r''' + void sharedUiConfigGenerationTests(String wrapperFunction) { + test('with multiple props mixins and function components in file', () { + setUpAndGenerate(''' mixin FooPropsMixin on UiProps {} class FooProps = UiProps with FooPropsMixin; mixin BarPropsMixin on UiProps {} - final Bar = uiFunction( + UiFactory Bar = $wrapperFunction( (props) { return Dom.div()(); }, - $BarConfig, // ignore: undefined_identifier + \$BarConfig, // ignore: undefined_identifier ); - final Foo = uiFunction( + UiFactory Foo = $wrapperFunction( (props) { return Dom.div()(); }, - $FooConfig, // ignore: undefined_identifier + \$FooConfig, // ignore: undefined_identifier ); - UiFactory Baz = uiFunction( + UiFactory Baz = $wrapperFunction( (props) { return Dom.div()(); }, - $BazConfig, // ignore: undefined_identifier + \$BazConfig, // ignore: undefined_identifier ); mixin UnusedPropsMixin on UiProps {} '''); - expect(implGenerator.outputContentsBuffer.toString().contains(generatedPropsMapsForConfig('UnusedPropsMixin')), isFalse); - expect(implGenerator.outputContentsBuffer.toString(), contains(generatedPropsMapsForConfig('BarPropsMixin'))); - expect(implGenerator.outputContentsBuffer.toString(), contains(generatedPropsMapsForConfig('FooProps'))); + expect(implGenerator.outputContentsBuffer.toString().contains(generatedPropsMapsForConfig('UnusedPropsMixin')), isFalse); + expect(implGenerator.outputContentsBuffer.toString(), contains(generatedPropsMapsForConfig('BarPropsMixin'))); + expect(implGenerator.outputContentsBuffer.toString(), contains(generatedPropsMapsForConfig('FooProps'))); - expect(implGenerator.outputContentsBuffer.toString(), contains(generatedConfig('BarPropsMixin', 'Bar'))); - expect(implGenerator.outputContentsBuffer.toString(), contains(generatedConfig('BarPropsMixin', 'Foo'))); - expect(implGenerator.outputContentsBuffer.toString(), contains(generatedConfig('FooProps', 'Baz'))); - }); + expect(implGenerator.outputContentsBuffer.toString(), contains(generatedConfig('BarPropsMixin', 'Bar'))); + expect(implGenerator.outputContentsBuffer.toString(), contains(generatedConfig('BarPropsMixin', 'Foo'))); + expect(implGenerator.outputContentsBuffer.toString(), contains(generatedConfig('FooProps', 'Baz'))); + }); - test('wrapped in an hoc', () { - setUpAndGenerate(''' - UiFactory Foo = someHOC(uiFunction( + test('wrapped in an hoc', () { + setUpAndGenerate(''' + UiFactory Foo = someHOC($wrapperFunction( (props) { return Dom.div()(); }, @@ -748,9 +749,66 @@ main() { mixin FooPropsMixin on UiProps {} '''); - expect(implGenerator.outputContentsBuffer.toString(), contains(generatedPropsMapsForConfig('FooPropsMixin'))); + expect(implGenerator.outputContentsBuffer.toString(), contains(generatedPropsMapsForConfig('FooPropsMixin'))); - expect(implGenerator.outputContentsBuffer.toString(), contains(generatedConfig('FooPropsMixin', 'Foo'))); + expect(implGenerator.outputContentsBuffer.toString(), contains(generatedConfig('FooPropsMixin', 'Foo'))); + }); + } + + group('uiFunction', () { + sharedUiConfigGenerationTests('uiFunction'); + }); + + group('uiForwardRef', () { + // Note: this doesn't test any of the ref forwarding capabilities of `uiForwardRef`, + // and just tests the generation of the UiFactoryConfig for `uiForwardRef` + // explicitly. + sharedUiConfigGenerationTests('uiForwardRef'); + + test('when the config does not need to be generated', () { + setUpAndGenerate(r''' + UiFactory ForwardRefFoo = uiForwardRef((props, ref) { + return (Foo() + ..ref = ref + )(); + }, Foo.asForwardRefConfig()); + '''); + + expect(implGenerator.outputContentsBuffer.toString().contains(generatedConfig('FooProps', 'ForwardRefFoo')), isFalse); + }); + + test('when the config does need to be generated but mixes in an already consumed props class', () { + setUpAndGenerate(r''' + UiFactory Foo = _$Foo; + + mixin FooProps on UiProps {} + + class FooComponent extends UiComponent2{ + @override + render() => null; + } + + class UiForwardRefFooProps = UiProps with FooProps; + + UiFactory UiForwardRefFoo = uiForwardRef( + (props, ref) { + return (Foo() + ..ref = ref + )(); + }, + $UiForwardRefFooConfig, + ); + '''); + + expect(implGenerator.outputContentsBuffer.toString(), contains(generatedPropsMapsForConfig('UiForwardRefFooProps'))); + expect(implGenerator.outputContentsBuffer.toString(), contains(generatedConfig('UiForwardRefFooProps', 'UiForwardRefFoo'))); + }); + }); + + // The builder should support generation of UiFactoryConfig's whenever + // it recognizes that a generated config is being referenced + group('arbitrary HOC', () { + sharedUiConfigGenerationTests('anArbitraryHOC'); }); test('unless function component is generic or does not have a props config', () { @@ -763,6 +821,17 @@ main() { )(); })(Foo); + UiFactory ArbitraryFoo = anArbitraryHoc( + (props) { + return (Foo() + ..ref = ref + )(); + }, + UiFactoryConfig( + propsFactory: PropsFactory.fromUiFactory(Foo) + ) + ); + final Bar = uiFunction( (props) { return Dom.div()(); @@ -790,6 +859,7 @@ main() { expect(implGenerator.outputContentsBuffer.toString(), contains(generatedPropsMapsForConfig('FooPropsMixin'))); expect(implGenerator.outputContentsBuffer.toString().contains(generatedConfig('UiProps', 'Bar')), isFalse, reason: '2'); + expect(implGenerator.outputContentsBuffer.toString().contains(generatedConfig('FooPropsMixin', 'ArbitraryFoo')), isFalse, reason: '2'); expect(implGenerator.outputContentsBuffer.toString(), contains(generatedConfig('FooPropsMixin', 'Foo')), reason: '1'); expect(implGenerator.outputContentsBuffer.toString().contains(generatedConfig('FooPropsMixin', 'Baz')), isFalse, reason: '3'); }); diff --git a/test/vm_tests/builder/parsing/ast_util_test.dart b/test/vm_tests/builder/parsing/ast_util_test.dart index f897e61ac..e41de8440 100644 --- a/test/vm_tests/builder/parsing/ast_util_test.dart +++ b/test/vm_tests/builder/parsing/ast_util_test.dart @@ -77,21 +77,21 @@ main() { (props) => Dom.div()(), \$FooConfig, // ignore: undefined_identifier ); - ''')).hasGeneratedConfigArg, true); + ''')).usesAGeneratedConfig, true); expect(InitializerHelperTopLevel(parseAndGetSingleWithType(''' final Foo = uiFunction( (props) => Dom.div()(), UiFactoryConfig(), ); - ''')).hasGeneratedConfigArg, false); + ''')).usesAGeneratedConfig, false); expect(InitializerHelperTopLevel(parseAndGetSingleWithType(''' final Foo = someHOC(uiFunction( (props) => Dom.div()(), \$FooConfig, // ignore: undefined_identifier )); - ''')).hasGeneratedConfigArg, true); + ''')).usesAGeneratedConfig, true); expect(InitializerHelperTopLevel(parseAndGetSingleWithType(''' final Foo = uiFunction( @@ -100,7 +100,7 @@ main() { propsFactory: PropsFactory.fromUiFactory(Bar), ), ); - ''')).hasGeneratedConfigArg, false); + ''')).usesAGeneratedConfig, false); }); }); diff --git a/test/vm_tests/builder/parsing/members_test.dart b/test/vm_tests/builder/parsing/members_test.dart index edd850e20..2922b58e2 100644 --- a/test/vm_tests/builder/parsing/members_test.dart +++ b/test/vm_tests/builder/parsing/members_test.dart @@ -303,7 +303,7 @@ main() { final factory = BoilerplateFactory(parseAndGetSingleWithType(r''' UiFactory Foo = _$Foo; '''), VersionConfidences.none()); - expect(factory.isFunctionComponentFactory, isFalse); + expect(factory.shouldGenerateConfig, isFalse); }); test('returns true for function component factories', () { @@ -315,7 +315,7 @@ main() { $FooConfig, // ignore: undefined_identifier ); '''), VersionConfidences.none()); - expect(factory.isFunctionComponentFactory, isTrue); + expect(factory.shouldGenerateConfig, isTrue); }); }); diff --git a/web/component2/src/demos/ref.dart b/web/component2/src/demos/ref.dart index 830e26aca..3c424a40a 100644 --- a/web/component2/src/demos/ref.dart +++ b/web/component2/src/demos/ref.dart @@ -1,3 +1,4 @@ +// ignore_for_file: deprecated_member_use_from_same_package import 'dart:html'; import 'package:over_react/over_react.dart'; @@ -11,7 +12,7 @@ mixin UiForwardRefLogsFunctionComponentProps on UiProps { Ref lastClickedButton; } -final UiForwardRefLogsFunctionComponent = uiForwardRef( +UiFactory UiForwardRefLogsFunctionComponent = uiForwardRef( (props, ref) { final prevPropsRef = useRef(null); @@ -41,8 +42,8 @@ class UiForwardRefLogsPropsComplexFunctionComponentProps = UiProps UiForwardRefLogsPropsComplexFunctionComponentPropsMixin, UiForwardRefLogsFunctionComponentProps; -final UiForwardRefLogsPropsComplexFunctionComponent = - uiForwardRef( +UiFactory UiForwardRefLogsPropsComplexFunctionComponent = + uiForwardRef( (props, ref) { final prevPropsRef = useRef(null); @@ -66,13 +67,13 @@ final UiForwardRefLogsPropsComplexFunctionComponent = ); // ------------ `uiForwardRef` with a class component (simple) ------------ -final UiForwardRefLogsPropsComponent = uiForwardRef( +UiFactory UiForwardRefLogsPropsComponent = uiForwardRef( (props, ref) { return (_LogProps() ..addProps(props) .._forwardedRef = ref)(); }, - _LogProps.asForwardRefConfig(displayName: 'UiForwardRefLogsProps'), + _LogProps.asForwardRefConfig(), ); // ------------ `uiForwardRef` with a class component (complex) ------------ @@ -83,8 +84,8 @@ mixin UiForwardRefLogsPropsComplexComponentPropsMixin on UiProps { class UiForwardRefLogsPropsComplexComponentProps = UiProps with UiForwardRefLogsPropsComplexComponentPropsMixin, LogPropsProps; -final UiForwardRefLogsPropsComplexComponent = - uiForwardRef( +UiFactory UiForwardRefLogsPropsComplexComponent = + uiForwardRef( (props, ref) { return Fragment()( Dom.div()(props.buttonDescription), @@ -97,7 +98,7 @@ final UiForwardRefLogsPropsComplexComponent = ); // ------------ `forwardRef` (deprecated) with class component ------------ -final LogProps = forwardRef((props, ref) { +UiFactory LogProps = forwardRef((props, ref) { return (_LogProps() ..addProps(props) .._forwardedRef = ref)(); @@ -134,7 +135,7 @@ class LogPropsComponent extends UiComponent2 { } // ------------ `forwardRef` (deprecated) with Function component ------------ -final LogsPropsFunctionComponent = forwardRef<_LogsPropsFunctionComponentProps>((props, ref) { +UiFactory<_LogsPropsFunctionComponentProps> LogsPropsFunctionComponent = forwardRef<_LogsPropsFunctionComponentProps>((props, ref) { return (_LogsPropsFunctionComponent() ..addProps(props) .._forwardedRef = ref)(); @@ -163,7 +164,7 @@ final _LogsPropsFunctionComponent = uiFunction<_LogsPropsFunctionComponentProps> ); // -------------------------------- Demo Display Logic -------------------------------- -final FancyButton = uiForwardRef( +UiFactory FancyButton = uiForwardRef( (props, ref) { final classes = ClassNameBuilder.fromProps(props)..add('FancyButton'); @@ -172,12 +173,12 @@ final FancyButton = uiForwardRef( ..className = classes.toClassName() ..ref = ref)('Click me!'); }, - Dom.button.asForwardRefConfig(displayName: 'FancyButton'), + Dom.button.asForwardRefConfig(displayName: 'FancyButton'), ); mixin RefDemoProps on UiProps {} -final RefDemoContainer = uiFunction( +UiFactory RefDemoContainer = uiFunction( (props) { // `uiForwardRef` Refs final buttonNodeRefForSimpleFunctionComponent = createRef(); @@ -283,7 +284,7 @@ mixin RefDemoSectionProps on UiProps { String sectionTitle; } -final RefDemoSection = uiFunction( +UiFactory RefDemoSection = uiFunction( (props) { return (Fragment()( (Dom.h3()..style = {'color': 'gray', 'borderBottom': '1px solid gray', 'marginTop': 10})( @@ -304,7 +305,7 @@ mixin RefDemoHocProps on UiProps { String demoTitle; } -final RefDemoHoc = uiFunction( +UiFactory RefDemoHoc = uiFunction( (props) { return ((Dom.div()..style = {'flex': '0 50%', 'width': '100%', 'marginTop': 10})( Dom.h4()(props.demoTitle), From 1de88bbb79674a15f6822cefc16bd6aa6b06fe83 Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Thu, 6 Aug 2020 08:36:11 -0700 Subject: [PATCH 15/28] Revert unintentional change --- example/hooks/use_context_example.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/example/hooks/use_context_example.dart b/example/hooks/use_context_example.dart index 97f71d6f4..5f099a1cc 100644 --- a/example/hooks/use_context_example.dart +++ b/example/hooks/use_context_example.dart @@ -45,9 +45,11 @@ mixin NewContextProviderProps on UiProps {} final NewContextProvider = uiFunction( (props) { final renderCount = useState(0); + final complexMap = useState(false); _onButtonClick(event) { renderCount.setWithUpdater((oldValue) => oldValue + 1); + complexMap.set(false); } final provideMap = {'renderCount': renderCount.value}; From d66db3f9f37f37f3c036244eff4b8f10ad546fe8 Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Thu, 6 Aug 2020 08:59:15 -0700 Subject: [PATCH 16/28] Fix empty name issue --- lib/src/component/ref_util.dart | 2 +- .../component_declaration/function_component.dart | 13 +++++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/lib/src/component/ref_util.dart b/lib/src/component/ref_util.dart index 934f460d1..0066f9c71 100644 --- a/lib/src/component/ref_util.dart +++ b/lib/src/component/ref_util.dart @@ -391,7 +391,7 @@ UiFactory uiForwardRef( // If a consumer uses `asForwardRefConfig` to generate the function component // config, displayName could be `null`. - if (displayName != null && displayName.trim().isNotEmpty) { + if (displayName != null) { factory = react_interop.forwardRef(_uiFunctionWrapper, displayName: displayName); } else { factory = react_interop.forwardRef(_uiFunctionWrapper); diff --git a/lib/src/component_declaration/function_component.dart b/lib/src/component_declaration/function_component.dart index 64fb2e9ce..404b13732 100644 --- a/lib/src/component_declaration/function_component.dart +++ b/lib/src/component_declaration/function_component.dart @@ -140,8 +140,13 @@ UiFactory uiFunction( } String getFunctionName(Function function) { - return getProperty(function, 'name') ?? + String functionName = getProperty(function, 'name') ?? getProperty(function, '\$static_name'); + + // Anonymous JS functions do get a name property, but it's an empty string. + if (functionName.isEmpty) return null; + + return functionName; } class GenericUiProps extends UiProps { @@ -166,7 +171,11 @@ class UiFactoryConfig { final PropsFactory propsFactory; final String displayName; - UiFactoryConfig({this.propsFactory, this.displayName}); + UiFactoryConfig({this.propsFactory, this.displayName}) { + print('ayoo'); + print(displayName); + print(displayName == null); + } } /// Helper class to keep track of props factories used by [uiFunction], From 0e3f5ef41818852cf7ce2668227cd31717e5a71c Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Thu, 6 Aug 2020 09:35:14 -0700 Subject: [PATCH 17/28] Revert change to getFunctionName --- lib/src/component/ref_util.dart | 2 +- .../component_declaration/function_component.dart | 14 ++------------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/lib/src/component/ref_util.dart b/lib/src/component/ref_util.dart index 0066f9c71..1630e8aed 100644 --- a/lib/src/component/ref_util.dart +++ b/lib/src/component/ref_util.dart @@ -391,7 +391,7 @@ UiFactory uiForwardRef( // If a consumer uses `asForwardRefConfig` to generate the function component // config, displayName could be `null`. - if (displayName != null) { + if (displayName != null && displayName.isNotEmpty) { factory = react_interop.forwardRef(_uiFunctionWrapper, displayName: displayName); } else { factory = react_interop.forwardRef(_uiFunctionWrapper); diff --git a/lib/src/component_declaration/function_component.dart b/lib/src/component_declaration/function_component.dart index 404b13732..24c7b32e5 100644 --- a/lib/src/component_declaration/function_component.dart +++ b/lib/src/component_declaration/function_component.dart @@ -140,13 +140,7 @@ UiFactory uiFunction( } String getFunctionName(Function function) { - String functionName = getProperty(function, 'name') ?? - getProperty(function, '\$static_name'); - - // Anonymous JS functions do get a name property, but it's an empty string. - if (functionName.isEmpty) return null; - - return functionName; + return getProperty(function, 'name') ?? getProperty(function, '\$static_name'); } class GenericUiProps extends UiProps { @@ -171,11 +165,7 @@ class UiFactoryConfig { final PropsFactory propsFactory; final String displayName; - UiFactoryConfig({this.propsFactory, this.displayName}) { - print('ayoo'); - print(displayName); - print(displayName == null); - } + UiFactoryConfig({this.propsFactory, this.displayName}); } /// Helper class to keep track of props factories used by [uiFunction], From 236f3441c016c3ea645b53a570e14b638818d1dc Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Thu, 6 Aug 2020 09:55:53 -0700 Subject: [PATCH 18/28] Fix doc comment --- lib/src/component/ref_util.dart | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/src/component/ref_util.dart b/lib/src/component/ref_util.dart index 1630e8aed..ddf5308d9 100644 --- a/lib/src/component/ref_util.dart +++ b/lib/src/component/ref_util.dart @@ -380,7 +380,9 @@ UiFactory uiForwardRef( // ignore: invalid_use_of_protected_member var propsFactory = config.propsFactory; - // Get the display name from the inner function if possible so it doesn't become `_uiFunctionWrapper` + // Get the display name from the inner function if possible so it doesn't become `_uiFunctionWrapper`. + // If the function is an anonymous function and a display name is not set, + // this will be an empty string. final displayName = config.displayName ?? getFunctionName(functionComponent); dynamic _uiFunctionWrapper(dynamic props, dynamic ref) { @@ -390,7 +392,7 @@ UiFactory uiForwardRef( ReactJsComponentFactoryProxy factory; // If a consumer uses `asForwardRefConfig` to generate the function component - // config, displayName could be `null`. + // config, displayName could be `null` or an empty string. if (displayName != null && displayName.isNotEmpty) { factory = react_interop.forwardRef(_uiFunctionWrapper, displayName: displayName); } else { From ac8a42c3f08cfab2964d2181319c56a05e347fe6 Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Thu, 6 Aug 2020 10:10:04 -0700 Subject: [PATCH 19/28] Improve example logging readability --- web/component2/src/demos/ref.dart | 22 ++++++++++++ .../src/demos/ref.over_react.g.dart | 34 ++++++++++++++++--- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/web/component2/src/demos/ref.dart b/web/component2/src/demos/ref.dart index 3c424a40a..3604f1a23 100644 --- a/web/component2/src/demos/ref.dart +++ b/web/component2/src/demos/ref.dart @@ -10,6 +10,7 @@ part 'ref.over_react.g.dart'; mixin UiForwardRefLogsFunctionComponentProps on UiProps { BuilderOnlyUiFactory builder; Ref lastClickedButton; + String demoTitle; } UiFactory UiForwardRefLogsFunctionComponent = uiForwardRef( @@ -18,8 +19,11 @@ UiFactory UiForwardRefLogsFunctionCompon useEffect(() { if (prevPropsRef.current != null) { + print('/////////////////// ${props.demoTitle} /////////////////////'); print('old props: ${prevPropsRef.current}'); print('new props: $props'); + print(''); + print(''); } prevPropsRef.current = props; @@ -49,8 +53,11 @@ UiFactory UiForwardRefLogsPr useEffect(() { if (prevPropsRef.current != null) { + print('/////////////////// ${props.demoTitle} /////////////////////'); print('old props: ${prevPropsRef.current}'); print('new props: $props'); + print(''); + print(''); } prevPropsRef.current = props; @@ -117,13 +124,19 @@ mixin LogPropsProps on UiProps { // // Consumers can set this private field value using the public `ref` setter. Ref _forwardedRef; + + // Title just to improve readability of logs. + String demoTitle; } class LogPropsComponent extends UiComponent2 { @override void componentDidUpdate(Map prevProps, _, [__]) { + print('/////////////////// ${props.demoTitle} ///////////////////'); print('old props: $prevProps'); print('new props: $props'); + print(''); + print(''); } @override @@ -149,8 +162,11 @@ final _LogsPropsFunctionComponent = uiFunction<_LogsPropsFunctionComponentProps> useEffect(() { if (prevPropsRef.current != null) { + print('/////////////////// ${props.demoTitle} /////////////////////'); print('old props: ${prevPropsRef.current}'); print('new props: $props'); + print(''); + print(''); } prevPropsRef.current = props; @@ -198,6 +214,7 @@ UiFactory RefDemoContainer = uiFunction( (UiForwardRefLogsFunctionComponent() ..builder = FancyButton ..lastClickedButton = lastClickedRef.value + ..demoTitle = '`uiForwardRef` with a function component (simple)' ..id = 'uiForwardRef-function-component' ..className = 'btn btn-primary' ..ref = buttonNodeRefForSimpleFunctionComponent @@ -211,6 +228,7 @@ UiFactory RefDemoContainer = uiFunction( ..buttonDescription = 'A button that logs the innerHtml' ..builder = FancyButton ..lastClickedButton = lastClickedRef.value + ..demoTitle = '`uiForwardRef` with a function component (complex)' ..id = 'uiForwardRef-function-complex-component' ..className = 'btn btn-success' ..ref = buttonNodeRefForComplexFunctionComponent @@ -223,6 +241,7 @@ UiFactory RefDemoContainer = uiFunction( (UiForwardRefLogsPropsComponent() ..builder = FancyButton ..lastClickedButton = lastClickedRef.value + ..demoTitle = '`uiForwardRef` with a class component (simple)' ..id = 'uiForwardRef-component' ..className = 'btn btn-warning' ..ref = buttonNodeRefForSimpleComponent @@ -236,6 +255,7 @@ UiFactory RefDemoContainer = uiFunction( ..buttonDescription = 'A button that logs the innerHtml' ..builder = FancyButton ..lastClickedButton = lastClickedRef.value + ..demoTitle = '`uiForwardRef` with a class component (complex)' ..id = 'uiForwardRef-complex-component' ..className = 'btn btn-danger' ..ref = buttonNodeRefForComplexComponent @@ -250,6 +270,7 @@ UiFactory RefDemoContainer = uiFunction( (LogProps() ..builder = FancyButton ..lastClickedButton = lastClickedRef.value + ..demoTitle = '`forwardRef` with class component' ..id = 'forwardRef-component' ..className = 'btn btn-primary' ..ref = fancyButtonNodeRef @@ -262,6 +283,7 @@ UiFactory RefDemoContainer = uiFunction( (LogsPropsFunctionComponent() ..builder = FancyButton ..lastClickedButton = lastClickedRef.value + ..demoTitle = '`uiForwardRef` with function component' ..id = 'forwardRef-function-component' ..className = 'btn btn-success' ..ref = fancyFunctionalButtonNodeRef diff --git a/web/component2/src/demos/ref.over_react.g.dart b/web/component2/src/demos/ref.over_react.g.dart index 4b7083266..2a1df0911 100644 --- a/web/component2/src/demos/ref.over_react.g.dart +++ b/web/component2/src/demos/ref.over_react.g.dart @@ -167,6 +167,13 @@ mixin $UiForwardRefLogsFunctionComponentProps set lastClickedButton(Ref value) => props[_$key__lastClickedButton__UiForwardRefLogsFunctionComponentProps] = value; + @override + String get demoTitle => + props[_$key__demoTitle__UiForwardRefLogsFunctionComponentProps] ?? + null; // Add ` ?? null` to workaround DDC bug: ; + @override + set demoTitle(String value) => + props[_$key__demoTitle__UiForwardRefLogsFunctionComponentProps] = value; /* GENERATED CONSTANTS */ static const PropDescriptor _$prop__builder__UiForwardRefLogsFunctionComponentProps = @@ -175,19 +182,26 @@ mixin $UiForwardRefLogsFunctionComponentProps _$prop__lastClickedButton__UiForwardRefLogsFunctionComponentProps = PropDescriptor( _$key__lastClickedButton__UiForwardRefLogsFunctionComponentProps); + static const PropDescriptor + _$prop__demoTitle__UiForwardRefLogsFunctionComponentProps = + PropDescriptor(_$key__demoTitle__UiForwardRefLogsFunctionComponentProps); static const String _$key__builder__UiForwardRefLogsFunctionComponentProps = 'UiForwardRefLogsFunctionComponentProps.builder'; static const String _$key__lastClickedButton__UiForwardRefLogsFunctionComponentProps = 'UiForwardRefLogsFunctionComponentProps.lastClickedButton'; + static const String _$key__demoTitle__UiForwardRefLogsFunctionComponentProps = + 'UiForwardRefLogsFunctionComponentProps.demoTitle'; static const List $props = [ _$prop__builder__UiForwardRefLogsFunctionComponentProps, - _$prop__lastClickedButton__UiForwardRefLogsFunctionComponentProps + _$prop__lastClickedButton__UiForwardRefLogsFunctionComponentProps, + _$prop__demoTitle__UiForwardRefLogsFunctionComponentProps ]; static const List $propKeys = [ _$key__builder__UiForwardRefLogsFunctionComponentProps, - _$key__lastClickedButton__UiForwardRefLogsFunctionComponentProps + _$key__lastClickedButton__UiForwardRefLogsFunctionComponentProps, + _$key__demoTitle__UiForwardRefLogsFunctionComponentProps ]; } @@ -310,6 +324,12 @@ mixin $LogPropsProps on LogPropsProps { @override set _forwardedRef(Ref value) => props[_$key___forwardedRef__LogPropsProps] = value; + @override + String get demoTitle => + props[_$key__demoTitle__LogPropsProps] ?? + null; // Add ` ?? null` to workaround DDC bug: ; + @override + set demoTitle(String value) => props[_$key__demoTitle__LogPropsProps] = value; /* GENERATED CONSTANTS */ static const PropDescriptor _$prop__builder__LogPropsProps = PropDescriptor(_$key__builder__LogPropsProps); @@ -317,21 +337,27 @@ mixin $LogPropsProps on LogPropsProps { PropDescriptor(_$key__lastClickedButton__LogPropsProps); static const PropDescriptor _$prop___forwardedRef__LogPropsProps = PropDescriptor(_$key___forwardedRef__LogPropsProps); + static const PropDescriptor _$prop__demoTitle__LogPropsProps = + PropDescriptor(_$key__demoTitle__LogPropsProps); static const String _$key__builder__LogPropsProps = 'LogPropsProps.builder'; static const String _$key__lastClickedButton__LogPropsProps = 'LogPropsProps.lastClickedButton'; static const String _$key___forwardedRef__LogPropsProps = 'LogPropsProps._forwardedRef'; + static const String _$key__demoTitle__LogPropsProps = + 'LogPropsProps.demoTitle'; static const List $props = [ _$prop__builder__LogPropsProps, _$prop__lastClickedButton__LogPropsProps, - _$prop___forwardedRef__LogPropsProps + _$prop___forwardedRef__LogPropsProps, + _$prop__demoTitle__LogPropsProps ]; static const List $propKeys = [ _$key__builder__LogPropsProps, _$key__lastClickedButton__LogPropsProps, - _$key___forwardedRef__LogPropsProps + _$key___forwardedRef__LogPropsProps, + _$key__demoTitle__LogPropsProps ]; } From 9e3f6d36ce4e41a83edf21c3b6f8e09906607f60 Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Thu, 6 Aug 2020 10:19:45 -0700 Subject: [PATCH 20/28] Improve deprecation doc comment --- lib/src/component/ref_util.dart | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/lib/src/component/ref_util.dart b/lib/src/component/ref_util.dart index ddf5308d9..f3b4d923c 100644 --- a/lib/src/component/ref_util.dart +++ b/lib/src/component/ref_util.dart @@ -176,6 +176,27 @@ Ref createRef() { /// ``` /// /// Learn more: . +/// +/// DEPRECATED: use [uiForwardRef] instead. Updating an existing usage can be done +/// like so: +/// +/// ```dart +/// // Before: +/// final FooForwarded = forwardRef((props, ref) { +/// return (Foo() +/// ..addAll(props) +/// ..forwardedRef = ref +/// )(); +/// })(Foo); +/// +/// // After: +/// UiFactory FooForwarded = uiForwardRef((props, ref) { +/// return (Foo() +/// ..addAll(props) +/// ..forwardedRef = ref +/// )(); +/// }, Foo.asForwardRefConfig(displayName: 'FooForwarded')); +/// ``` @Deprecated('Use uiForwardRef instead. Will be removed in 4.0.0') UiFactory Function(UiFactory) forwardRef( Function(TProps props, Ref ref) wrapperFunction, From e5001d25f249113c01c85f4f88669053c40c68f3 Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Thu, 6 Aug 2020 12:42:52 -0700 Subject: [PATCH 21/28] Address parser feedback --- lib/src/builder/parsing/ast_util.dart | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/src/builder/parsing/ast_util.dart b/lib/src/builder/parsing/ast_util.dart index ce69ce2b7..489eb4b33 100644 --- a/lib/src/builder/parsing/ast_util.dart +++ b/lib/src/builder/parsing/ast_util.dart @@ -46,12 +46,7 @@ extension InitializerHelperTopLevel on TopLevelVariableDeclaration { bool get usesAGeneratedConfig { return firstInitializer != null && anyDescendantIdentifiers(firstInitializer, (identifier) { - final uiFactoryDeclaration = identifier.thisOrAncestorOfType(); - - return firstInitializer != null && - anyDescendantIdentifiers(firstInitializer, (identifier) { - return identifier.nameWithoutPrefix == '\$${uiFactoryDeclaration.name.name}Config'; - }); + return identifier.nameWithoutPrefix == '\$${firstVariable.name.name}Config'; }); } } From 8189f1c57527950beff88ec36ba864d7adf072b3 Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Fri, 7 Aug 2020 07:41:51 -0700 Subject: [PATCH 22/28] Fix up example --- lib/src/component/ref_util.dart | 14 +- web/component2/src/demos/ref.dart | 343 +++++------ .../src/demos/ref.over_react.g.dart | 575 +++++++++--------- 3 files changed, 436 insertions(+), 496 deletions(-) diff --git a/lib/src/component/ref_util.dart b/lib/src/component/ref_util.dart index f3b4d923c..704b1970a 100644 --- a/lib/src/component/ref_util.dart +++ b/lib/src/component/ref_util.dart @@ -293,7 +293,7 @@ UiFactory Function(UiFactory) forwardRef /// UiFactory withLogging(UiFactory factoryToWrap) { /// return uiForwardRef( /// (props, ref) { -/// useEffect(() => 'the component rendered!'); +/// useEffect(() => '${factoryToWrap().componentFactory.type} rendered!'); /// /// return (factoryToWrap() /// ..addAll(props) @@ -301,7 +301,7 @@ UiFactory Function(UiFactory) forwardRef /// )(props.children); /// }, /// factoryToBeWrapped.asForwardRefConfig( -/// displayName: 'withLogging(${getDisplayName(factoryToWrap)})', +/// displayName: 'WithLogging', /// ), /// ); /// } @@ -326,7 +326,7 @@ UiFactory Function(UiFactory) forwardRef /// version wrapped in `uiForwardRef`: /// /// ```dart -/// UiFactory _Foo = _$_Foo; // ignore: undefined_identifier +/// UiFactory _Foo = _$_Foo; // ignore: undefined_identifier /// mixin FooProps on UiProps { /// // Private since we only use this to pass along the ref provided in /// // uiForwardRef. @@ -340,9 +340,9 @@ UiFactory Function(UiFactory) forwardRef /// return Dom.div()( /// (Dom.input() /// ..type = 'text' -/// ..ref = _inputRef -/// )(); -/// ) +/// ..ref = props._inputRef +/// )() +/// ); /// } /// } /// @@ -384,7 +384,7 @@ UiFactory Function(UiFactory) forwardRef /// } /// /// class Foo2Props = UiProps with AnotherPropsMixin, FooProps; -/// final Foo2 = uiForwardRef((props, ref) { +/// final Foo2 = uiForwardRef((props, ref) { /// print(props.anExampleAdditionalProp); /// /// return (_Foo() diff --git a/web/component2/src/demos/ref.dart b/web/component2/src/demos/ref.dart index 3604f1a23..1fb01a161 100644 --- a/web/component2/src/demos/ref.dart +++ b/web/component2/src/demos/ref.dart @@ -6,138 +6,139 @@ import 'package:over_react/over_react.dart'; // ignore: uri_has_not_been_generated part 'ref.over_react.g.dart'; -// ------------ `uiForwardRef` with a function component (simple) ------------ -mixin UiForwardRefLogsFunctionComponentProps on UiProps { - BuilderOnlyUiFactory builder; - Ref lastClickedButton; - String demoTitle; -} - -UiFactory UiForwardRefLogsFunctionComponent = uiForwardRef( - (props, ref) { - final prevPropsRef = useRef(null); - - useEffect(() { - if (prevPropsRef.current != null) { - print('/////////////////// ${props.demoTitle} /////////////////////'); - print('old props: ${prevPropsRef.current}'); - print('new props: $props'); - print(''); - print(''); - } - - prevPropsRef.current = props; - }); - - return ((props.builder() +//----------------------------------------------------------------------------// +//----------------------------------------------------------------------------// +// UiForwardRef Examples +//----------------------------------------------------------------------------// +//----------------------------------------------------------------------------// + +//----------------------------------------------------------------------------// +// ### Example 1: Updating a function component to forward a ref: +//----------------------------------------------------------------------------// +mixin FancyButtonProps on UiProps {} + +UiFactory FancyButton = uiForwardRef( + (props, ref) { + final classes = ClassNameBuilder.fromProps(props)..add('FancyButton'); + return (Dom.button() + ..ref = ref ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) - ..ref = ref)(props.children)); - }, - $UiForwardRefLogsFunctionComponentConfig, // ignore: undefined_identifier + ..className = classes.toClassName() + )('Click me!'); + }, + $FancyButtonConfig, // ignore: undefined_identifier ); -// ------------ `uiForwardRef` with a function component (complex) ------------ -mixin UiForwardRefLogsPropsComplexFunctionComponentPropsMixin on UiProps { - String buttonDescription; +//----------------------------------------------------------------------------// +// ### Example 2: Creating a higher-order component (https://reactjs.org/docs/higher-order-components.html) +// that forwards its ref to the wrapped component. +//----------------------------------------------------------------------------// + +/// Wraps a component ([factoryToWrap]) in a new component that logs when rendered. +UiFactory withLogging(UiFactory factoryToWrap) { + return uiForwardRef((props, ref) { + useEffect(() => 'withLogging rendered!'); + + // This requires an ignore until https://github.com/dart-lang/sdk/issues/42975 + // is fixed. + return (factoryToWrap() // ignore: invocation_of_non_function_expression + ..addAll(props) + ..ref = ref + )(props.children); + }, + factoryToWrap.asForwardRefConfig( + displayName: 'WithLogging', + ), + ); } -class UiForwardRefLogsPropsComplexFunctionComponentProps = UiProps - with - UiForwardRefLogsPropsComplexFunctionComponentPropsMixin, - UiForwardRefLogsFunctionComponentProps; - -UiFactory UiForwardRefLogsPropsComplexFunctionComponent = - uiForwardRef( - (props, ref) { - final prevPropsRef = useRef(null); +/// This can be used just like FancyButton, and setting a ref on it will work the same! +UiFactory FancyButtonWithLogging = withLogging(FancyButton); - useEffect(() { - if (prevPropsRef.current != null) { - print('/////////////////// ${props.demoTitle} /////////////////////'); - print('old props: ${prevPropsRef.current}'); - print('new props: $props'); - print(''); - print(''); - } +//----------------------------------------------------------------------------// +// ### Example 3: Exposing inner refs in class components +//----------------------------------------------------------------------------// +UiFactory _Foo = _$_Foo; // ignore: undefined_identifier - prevPropsRef.current = props; - }); +mixin FooProps on UiProps { + // Private since we only use this to pass along the ref provided in + // uiForwardRef. + // + // Consumers will effectively be setting this when they set `ref` on the public factory. + dynamic _inputRef; +} - return (Fragment()( - Dom.div()(props.buttonDescription), - (props.builder() - ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) - ..ref = ref)(props.children), - )); - }, - $UiForwardRefLogsPropsComplexFunctionComponentConfig, // ignore: undefined_identifier -); +class FooComponent extends UiComponent2 { + @override + render() { + return Dom.div()( + (Dom.input() + ..modifyProps(addUnconsumedDomProps) + ..type = 'text' + ..ref = props._inputRef + )() + ); + } +} -// ------------ `uiForwardRef` with a class component (simple) ------------ -UiFactory UiForwardRefLogsPropsComponent = uiForwardRef( - (props, ref) { - return (_LogProps() +// Option 1: Use the class component's factory as the UiFactoryConfig arg. +UiFactory Foo = uiForwardRef((props, ref) { + return (_Foo() ..addProps(props) - .._forwardedRef = ref)(); + .._inputRef = ref + )(); }, - _LogProps.asForwardRefConfig(), + _Foo.asForwardRefConfig(), ); -// ------------ `uiForwardRef` with a class component (complex) ------------ -mixin UiForwardRefLogsPropsComplexComponentPropsMixin on UiProps { - String buttonDescription; +// Option 2: Create a new props class. +mixin AnotherPropsMixin on UiProps { + String anExampleAdditionalProp; } -class UiForwardRefLogsPropsComplexComponentProps = UiProps - with UiForwardRefLogsPropsComplexComponentPropsMixin, LogPropsProps; - -UiFactory UiForwardRefLogsPropsComplexComponent = - uiForwardRef( - (props, ref) { - return Fragment()( - Dom.div()(props.buttonDescription), - (_LogProps() - ..addProps(props) - .._forwardedRef = ref)(), - ); +class Foo2Props = UiProps with AnotherPropsMixin, FooProps; + +final Foo2 = uiForwardRef((props, ref) { + print(props.anExampleAdditionalProp); + return (_Foo() + ..addProps(props) + .._inputRef = ref + )(); }, - $UiForwardRefLogsPropsComplexComponentConfig, // ignore: undefined_identifier + $Foo2Config, // ignore: undefined_identifier ); -// ------------ `forwardRef` (deprecated) with class component ------------ +//----------------------------------------------------------------------------// +//----------------------------------------------------------------------------// +// forwardRef Examples (deprecated) +//----------------------------------------------------------------------------// +//----------------------------------------------------------------------------// + + +//----------------------------------------------------------------------------// +// ### Example 1: Exposing inner refs in class components: +//----------------------------------------------------------------------------// UiFactory LogProps = forwardRef((props, ref) { return (_LogProps() ..addProps(props) .._forwardedRef = ref)(); }, displayName: 'LogProps')(_LogProps); -UiFactory _LogProps = _$_LogProps; +UiFactory _LogProps = _$_LogProps; // ignore: undefined_identifier mixin LogPropsProps on UiProps { - BuilderOnlyUiFactory builder; - - // A simple prop to change in order to trigger the print. - Ref lastClickedButton; + BuilderOnlyUiFactory builder; // Private since we only use this to pass along the value of `ref` to // the return value of forwardRef. // // Consumers can set this private field value using the public `ref` setter. Ref _forwardedRef; - - // Title just to improve readability of logs. - String demoTitle; } -class LogPropsComponent extends UiComponent2 { +class _LogPropsComponent extends UiComponent2 { @override - void componentDidUpdate(Map prevProps, _, [__]) { - print('/////////////////// ${props.demoTitle} ///////////////////'); - print('old props: $prevProps'); - print('new props: $props'); - print(''); - print(''); - } + void componentDidUpdate(_, __, [___]) => print('${props.builder().componentFactory.type} rendered!'); @override render() { @@ -147,149 +148,99 @@ class LogPropsComponent extends UiComponent2 { } } -// ------------ `forwardRef` (deprecated) with Function component ------------ -UiFactory<_LogsPropsFunctionComponentProps> LogsPropsFunctionComponent = forwardRef<_LogsPropsFunctionComponentProps>((props, ref) { - return (_LogsPropsFunctionComponent() +//----------------------------------------------------------------------------// +// ### Example 2: Exposing inner refs in functional components: +//----------------------------------------------------------------------------// +UiFactory LoggingFunctionWrapper = forwardRef((props, ref) { + print('LoggingFunctionWrapper rendered!'); + + return (Baz() ..addProps(props) + ..builder = props.builder .._forwardedRef = ref)(); -}, displayName: 'LogsPropsFunctionComponent')(_LogsPropsFunctionComponent); +}, displayName: 'LoggingFunctionWrapper')(Baz); -class _LogsPropsFunctionComponentProps = UiProps with LogPropsProps; +mixin BazProps on UiProps { + BuilderOnlyUiFactory builder; -final _LogsPropsFunctionComponent = uiFunction<_LogsPropsFunctionComponentProps>( - (props) { - final prevPropsRef = useRef<_LogsPropsFunctionComponentProps>(null); - - useEffect(() { - if (prevPropsRef.current != null) { - print('/////////////////// ${props.demoTitle} /////////////////////'); - print('old props: ${prevPropsRef.current}'); - print('new props: $props'); - print(''); - print(''); - } - - prevPropsRef.current = props; - }); + // Private since we only use this to pass along the value of `ref` to + // the return value of forwardRef. + // + // Consumers can set this private field value using the public `ref` setter. + Ref _forwardedRef; +} +final Baz = uiFunction( + (props) { return ((props.builder() ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) ..ref = props._forwardedRef)(props.children)); }, - $_LogsPropsFunctionComponentConfig, // ignore: undefined_identifier + $BazConfig, // ignore: undefined_identifier ); // -------------------------------- Demo Display Logic -------------------------------- -UiFactory FancyButton = uiForwardRef( - (props, ref) { - final classes = ClassNameBuilder.fromProps(props)..add('FancyButton'); - - return (Dom.button() - ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) - ..className = classes.toClassName() - ..ref = ref)('Click me!'); - }, - Dom.button.asForwardRefConfig(displayName: 'FancyButton'), -); mixin RefDemoProps on UiProps {} UiFactory RefDemoContainer = uiFunction( (props) { // `uiForwardRef` Refs - final buttonNodeRefForSimpleFunctionComponent = createRef(); - final buttonNodeRefForComplexFunctionComponent = createRef(); - final buttonNodeRefForSimpleComponent = createRef(); - final buttonNodeRefForComplexComponent = createRef(); + final fancyButtonUiForwardRef = createRef(); + final fancyButtonWithLoggingReg = createRef(); + final fooInputRef = createRef(); + final foo2InputRef = createRef(); // `forwardRef` Refs final fancyButtonNodeRef = createRef(); final fancyFunctionalButtonNodeRef = createRef(); - final lastClickedRef = useState>(buttonNodeRefForComplexComponent); - return ((Dom.div()..style = {'padding': 10})( (RefDemoSection()..sectionTitle = 'uiForwardRef Demos')( - (RefDemoHoc()..demoTitle = '`uiForwardRef` with a function component (simple)')( - (UiForwardRefLogsFunctionComponent() - ..builder = FancyButton - ..lastClickedButton = lastClickedRef.value - ..demoTitle = '`uiForwardRef` with a function component (simple)' - ..id = 'uiForwardRef-function-component' + (RefDemoHoc()..demoTitle = 'Basic `uiForwardRef`')( + (FancyButton() ..className = 'btn btn-primary' - ..ref = buttonNodeRefForSimpleFunctionComponent - ..onClick = (_) { - printButtonOuterHtml(buttonNodeRefForSimpleFunctionComponent); - lastClickedRef.set(buttonNodeRefForSimpleFunctionComponent); - })(), + ..ref = fancyButtonUiForwardRef + ..onClick = (_) => printButtonOuterHtml(fancyButtonUiForwardRef) + )(), ), - (RefDemoHoc()..demoTitle = '`uiForwardRef` with a function component (complex)')( - (UiForwardRefLogsPropsComplexFunctionComponent() - ..buttonDescription = 'A button that logs the innerHtml' - ..builder = FancyButton - ..lastClickedButton = lastClickedRef.value - ..demoTitle = '`uiForwardRef` with a function component (complex)' - ..id = 'uiForwardRef-function-complex-component' + (RefDemoHoc()..demoTitle = '`uiForwardRef` wrapped in HOC')( + (FancyButtonWithLogging() ..className = 'btn btn-success' - ..ref = buttonNodeRefForComplexFunctionComponent - ..onClick = (_) { - printButtonOuterHtml(buttonNodeRefForComplexFunctionComponent); - lastClickedRef.set(buttonNodeRefForComplexFunctionComponent); - })(), + ..ref = fancyButtonWithLoggingReg + ..onClick = (_) => printButtonOuterHtml(fancyButtonUiForwardRef) + )(), ), - (RefDemoHoc()..demoTitle = '`uiForwardRef` with a class component (simple)')( - (UiForwardRefLogsPropsComponent() - ..builder = FancyButton - ..lastClickedButton = lastClickedRef.value - ..demoTitle = '`uiForwardRef` with a class component (simple)' - ..id = 'uiForwardRef-component' - ..className = 'btn btn-warning' - ..ref = buttonNodeRefForSimpleComponent - ..onClick = (_) { - printButtonOuterHtml(buttonNodeRefForSimpleComponent); - lastClickedRef.set(buttonNodeRefForSimpleComponent); - })(), + (RefDemoHoc()..demoTitle = '`uiForwardRef` wrapping a class (option 1)')( + (Foo() + ..ref=fooInputRef + ..onChange=(e) => print('Foo Input Ref: ${e.target.value}') + )() ), - (RefDemoHoc()..demoTitle = '`uiForwardRef` with a class component (complex)')( - (UiForwardRefLogsPropsComplexComponent() - ..buttonDescription = 'A button that logs the innerHtml' - ..builder = FancyButton - ..lastClickedButton = lastClickedRef.value - ..demoTitle = '`uiForwardRef` with a class component (complex)' - ..id = 'uiForwardRef-complex-component' - ..className = 'btn btn-danger' - ..ref = buttonNodeRefForComplexComponent - ..onClick = (_) { - printButtonOuterHtml(buttonNodeRefForComplexComponent); - lastClickedRef.set(buttonNodeRefForComplexComponent); - })(), + (RefDemoHoc()..demoTitle = '`uiForwardRef` wrapping a class (option 2)')( + (Foo2() + ..anExampleAdditionalProp = 'This additional prop logs on renders!' + ..ref=foo2InputRef + ..onChange=(e) => print('Foo2 Input Ref: ${e.target.value}') + )() ), ), (RefDemoSection()..sectionTitle = 'forwardRef (deprecated) Demos')( (RefDemoHoc()..demoTitle = '`forwardRef` with class component')( (LogProps() ..builder = FancyButton - ..lastClickedButton = lastClickedRef.value - ..demoTitle = '`forwardRef` with class component' - ..id = 'forwardRef-component' - ..className = 'btn btn-primary' ..ref = fancyButtonNodeRef - ..onClick = (_) { - printButtonOuterHtml(fancyButtonNodeRef); - lastClickedRef.set(fancyButtonNodeRef); - })(), + ..className = 'btn btn-primary' + ..onClick = (_) => printButtonOuterHtml(fancyButtonNodeRef) + )(), ), (RefDemoHoc()..demoTitle = '`uiForwardRef` with function component')( - (LogsPropsFunctionComponent() + (LoggingFunctionWrapper() ..builder = FancyButton - ..lastClickedButton = lastClickedRef.value - ..demoTitle = '`uiForwardRef` with function component' - ..id = 'forwardRef-function-component' ..className = 'btn btn-success' ..ref = fancyFunctionalButtonNodeRef ..onClick = (_) { printButtonOuterHtml(fancyFunctionalButtonNodeRef); - lastClickedRef.set(fancyFunctionalButtonNodeRef); })(), ), ), diff --git a/web/component2/src/demos/ref.over_react.g.dart b/web/component2/src/demos/ref.over_react.g.dart index 2a1df0911..2cc2683ac 100644 --- a/web/component2/src/demos/ref.over_react.g.dart +++ b/web/component2/src/demos/ref.over_react.g.dart @@ -12,10 +12,147 @@ part of 'ref.dart'; // Registers component implementation and links type meta to builder factory. @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -final $LogPropsComponentFactory = registerComponent2( - () => _$LogPropsComponent(), +final $FooComponentFactory = registerComponent2( + () => _$FooComponent(), + builderFactory: _$_Foo, + componentClass: FooComponent, + isWrapper: false, + parentType: null, + displayName: '_Foo', +); + +_$$FooProps _$_Foo([Map backingProps]) => backingProps == null + ? _$$FooProps$JsMap(JsBackedMap()) + : _$$FooProps(backingProps); + +// Concrete props implementation. +// +// Implements constructor and backing map, and links up to generated component factory. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +abstract class _$$FooProps extends UiProps + with + FooProps, + $FooProps // If this generated mixin is undefined, it's likely because FooProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of FooProps. +{ + _$$FooProps._(); + + factory _$$FooProps(Map backingMap) { + if (backingMap == null || backingMap is JsBackedMap) { + return _$$FooProps$JsMap(backingMap); + } else { + return _$$FooProps$PlainMap(backingMap); + } + } + + /// Let `UiProps` internals know that this class has been generated. + @override + bool get $isClassGenerated => true; + + /// The `ReactComponentFactory` associated with the component built by this class. + @override + ReactComponentFactoryProxy get componentFactory => + super.componentFactory ?? $FooComponentFactory; + + /// The default namespace for the prop getters/setters generated for this class. + @override + String get propKeyNamespace => ''; +} + +// Concrete props implementation that can be backed by any [Map]. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$FooProps$PlainMap extends _$$FooProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$FooProps$PlainMap(Map backingMap) + : this._props = {}, + super._() { + this._props = backingMap ?? {}; + } + + /// The backing props map proxied by this class. + @override + Map get props => _props; + Map _props; +} + +// Concrete props implementation that can only be backed by [JsMap], +// allowing dart2js to compile more optimal code for key-value pair reads/writes. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$$FooProps$JsMap extends _$$FooProps { + // This initializer of `_props` to an empty map, as well as the reassignment + // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 + _$$FooProps$JsMap(JsBackedMap backingMap) + : this._props = JsBackedMap(), + super._() { + this._props = backingMap ?? JsBackedMap(); + } + + /// The backing props map proxied by this class. + @override + JsBackedMap get props => _props; + JsBackedMap _props; +} + +// Concrete component implementation mixin. +// +// Implements typed props/state factories, defaults `consumedPropKeys` to the keys +// generated for the associated props class. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +class _$FooComponent extends FooComponent { + _$$FooProps$JsMap _cachedTypedProps; + + @override + _$$FooProps$JsMap get props => _cachedTypedProps; + + @override + set props(Map value) { + assert( + getBackingMap(value) is JsBackedMap, + 'Component2.props should never be set directly in ' + 'production. If this is required for testing, the ' + 'component should be rendered within the test. If ' + 'that does not have the necessary result, the last ' + 'resort is to use typedPropsFactoryJs.'); + super.props = value; + _cachedTypedProps = typedPropsFactoryJs(getBackingMap(value)); + } + + @override + _$$FooProps$JsMap typedPropsFactoryJs(JsBackedMap backingMap) => + _$$FooProps$JsMap(backingMap); + + @override + _$$FooProps typedPropsFactory(Map backingMap) => _$$FooProps(backingMap); + + /// Let `UiComponent` internals know that this class has been generated. + @override + bool get $isClassGenerated => true; + + /// The default consumed props, comprising all props mixins used by FooProps. + /// Used in `*ConsumedProps` methods if [consumedProps] is not overridden. + @override + get $defaultConsumedProps => propsMeta.all; + + @override + PropsMetaCollection get propsMeta => const PropsMetaCollection({ + // If this generated mixin is undefined, it's likely because FooProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of FooProps. + FooProps: $FooProps.meta, + }); +} + +// React component factory implementation. +// +// Registers component implementation and links type meta to builder factory. +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +final $_LogPropsComponentFactory = registerComponent2( + () => _$_LogPropsComponent(), builderFactory: _$_LogProps, - componentClass: LogPropsComponent, + componentClass: _LogPropsComponent, isWrapper: false, parentType: null, displayName: '_LogProps', @@ -52,7 +189,7 @@ abstract class _$$LogPropsProps extends UiProps /// The `ReactComponentFactory` associated with the component built by this class. @override ReactComponentFactoryProxy get componentFactory => - super.componentFactory ?? $LogPropsComponentFactory; + super.componentFactory ?? $_LogPropsComponentFactory; /// The default namespace for the prop getters/setters generated for this class. @override @@ -102,7 +239,7 @@ class _$$LogPropsProps$JsMap extends _$$LogPropsProps { // generated for the associated props class. @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -class _$LogPropsComponent extends LogPropsComponent { +class _$_LogPropsComponent extends _LogPropsComponent { _$$LogPropsProps$JsMap _cachedTypedProps; @override @@ -149,152 +286,82 @@ class _$LogPropsComponent extends LogPropsComponent { ' Do not reference it in your code, as it may change at any time.' ' EXCEPTION: this may be used in legacy boilerplate until' ' it is transitioned to the new mixin-based boilerplate.') -mixin $UiForwardRefLogsFunctionComponentProps - on UiForwardRefLogsFunctionComponentProps { - static const PropsMeta meta = _$metaForUiForwardRefLogsFunctionComponentProps; - @override - BuilderOnlyUiFactory get builder => - props[_$key__builder__UiForwardRefLogsFunctionComponentProps] ?? - null; // Add ` ?? null` to workaround DDC bug: ; - @override - set builder(BuilderOnlyUiFactory value) => - props[_$key__builder__UiForwardRefLogsFunctionComponentProps] = value; - @override - Ref get lastClickedButton => - props[_$key__lastClickedButton__UiForwardRefLogsFunctionComponentProps] ?? - null; // Add ` ?? null` to workaround DDC bug: ; - @override - set lastClickedButton(Ref value) => - props[_$key__lastClickedButton__UiForwardRefLogsFunctionComponentProps] = - value; - @override - String get demoTitle => - props[_$key__demoTitle__UiForwardRefLogsFunctionComponentProps] ?? - null; // Add ` ?? null` to workaround DDC bug: ; - @override - set demoTitle(String value) => - props[_$key__demoTitle__UiForwardRefLogsFunctionComponentProps] = value; +mixin $FancyButtonProps on FancyButtonProps { + static const PropsMeta meta = _$metaForFancyButtonProps; /* GENERATED CONSTANTS */ - static const PropDescriptor - _$prop__builder__UiForwardRefLogsFunctionComponentProps = - PropDescriptor(_$key__builder__UiForwardRefLogsFunctionComponentProps); - static const PropDescriptor - _$prop__lastClickedButton__UiForwardRefLogsFunctionComponentProps = - PropDescriptor( - _$key__lastClickedButton__UiForwardRefLogsFunctionComponentProps); - static const PropDescriptor - _$prop__demoTitle__UiForwardRefLogsFunctionComponentProps = - PropDescriptor(_$key__demoTitle__UiForwardRefLogsFunctionComponentProps); - static const String _$key__builder__UiForwardRefLogsFunctionComponentProps = - 'UiForwardRefLogsFunctionComponentProps.builder'; - static const String - _$key__lastClickedButton__UiForwardRefLogsFunctionComponentProps = - 'UiForwardRefLogsFunctionComponentProps.lastClickedButton'; - static const String _$key__demoTitle__UiForwardRefLogsFunctionComponentProps = - 'UiForwardRefLogsFunctionComponentProps.demoTitle'; - static const List $props = [ - _$prop__builder__UiForwardRefLogsFunctionComponentProps, - _$prop__lastClickedButton__UiForwardRefLogsFunctionComponentProps, - _$prop__demoTitle__UiForwardRefLogsFunctionComponentProps - ]; - static const List $propKeys = [ - _$key__builder__UiForwardRefLogsFunctionComponentProps, - _$key__lastClickedButton__UiForwardRefLogsFunctionComponentProps, - _$key__demoTitle__UiForwardRefLogsFunctionComponentProps - ]; + static const List $props = []; + static const List $propKeys = []; } @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -const PropsMeta _$metaForUiForwardRefLogsFunctionComponentProps = PropsMeta( - fields: $UiForwardRefLogsFunctionComponentProps.$props, - keys: $UiForwardRefLogsFunctionComponentProps.$propKeys, +const PropsMeta _$metaForFancyButtonProps = PropsMeta( + fields: $FancyButtonProps.$props, + keys: $FancyButtonProps.$propKeys, ); @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.' ' EXCEPTION: this may be used in legacy boilerplate until' ' it is transitioned to the new mixin-based boilerplate.') -mixin $UiForwardRefLogsPropsComplexFunctionComponentPropsMixin - on UiForwardRefLogsPropsComplexFunctionComponentPropsMixin { - static const PropsMeta meta = - _$metaForUiForwardRefLogsPropsComplexFunctionComponentPropsMixin; - @override - String get buttonDescription => - props[ - _$key__buttonDescription__UiForwardRefLogsPropsComplexFunctionComponentPropsMixin] ?? +mixin $FooProps on FooProps { + static const PropsMeta meta = _$metaForFooProps; + @override + dynamic get _inputRef => + props[_$key___inputRef__FooProps] ?? null; // Add ` ?? null` to workaround DDC bug: ; @override - set buttonDescription(String value) => props[ - _$key__buttonDescription__UiForwardRefLogsPropsComplexFunctionComponentPropsMixin] = - value; + set _inputRef(dynamic value) => props[_$key___inputRef__FooProps] = value; /* GENERATED CONSTANTS */ - static const PropDescriptor - _$prop__buttonDescription__UiForwardRefLogsPropsComplexFunctionComponentPropsMixin = - PropDescriptor( - _$key__buttonDescription__UiForwardRefLogsPropsComplexFunctionComponentPropsMixin); - static const String - _$key__buttonDescription__UiForwardRefLogsPropsComplexFunctionComponentPropsMixin = - 'UiForwardRefLogsPropsComplexFunctionComponentPropsMixin.buttonDescription'; + static const PropDescriptor _$prop___inputRef__FooProps = + PropDescriptor(_$key___inputRef__FooProps); + static const String _$key___inputRef__FooProps = 'FooProps._inputRef'; - static const List $props = [ - _$prop__buttonDescription__UiForwardRefLogsPropsComplexFunctionComponentPropsMixin - ]; - static const List $propKeys = [ - _$key__buttonDescription__UiForwardRefLogsPropsComplexFunctionComponentPropsMixin - ]; + static const List $props = [_$prop___inputRef__FooProps]; + static const List $propKeys = [_$key___inputRef__FooProps]; } @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -const PropsMeta - _$metaForUiForwardRefLogsPropsComplexFunctionComponentPropsMixin = - PropsMeta( - fields: $UiForwardRefLogsPropsComplexFunctionComponentPropsMixin.$props, - keys: $UiForwardRefLogsPropsComplexFunctionComponentPropsMixin.$propKeys, +const PropsMeta _$metaForFooProps = PropsMeta( + fields: $FooProps.$props, + keys: $FooProps.$propKeys, ); @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.' ' EXCEPTION: this may be used in legacy boilerplate until' ' it is transitioned to the new mixin-based boilerplate.') -mixin $UiForwardRefLogsPropsComplexComponentPropsMixin - on UiForwardRefLogsPropsComplexComponentPropsMixin { - static const PropsMeta meta = - _$metaForUiForwardRefLogsPropsComplexComponentPropsMixin; - @override - String get buttonDescription => - props[ - _$key__buttonDescription__UiForwardRefLogsPropsComplexComponentPropsMixin] ?? +mixin $AnotherPropsMixin on AnotherPropsMixin { + static const PropsMeta meta = _$metaForAnotherPropsMixin; + @override + String get anExampleAdditionalProp => + props[_$key__anExampleAdditionalProp__AnotherPropsMixin] ?? null; // Add ` ?? null` to workaround DDC bug: ; @override - set buttonDescription(String value) => props[ - _$key__buttonDescription__UiForwardRefLogsPropsComplexComponentPropsMixin] = - value; + set anExampleAdditionalProp(String value) => + props[_$key__anExampleAdditionalProp__AnotherPropsMixin] = value; /* GENERATED CONSTANTS */ static const PropDescriptor - _$prop__buttonDescription__UiForwardRefLogsPropsComplexComponentPropsMixin = - PropDescriptor( - _$key__buttonDescription__UiForwardRefLogsPropsComplexComponentPropsMixin); - static const String - _$key__buttonDescription__UiForwardRefLogsPropsComplexComponentPropsMixin = - 'UiForwardRefLogsPropsComplexComponentPropsMixin.buttonDescription'; + _$prop__anExampleAdditionalProp__AnotherPropsMixin = + PropDescriptor(_$key__anExampleAdditionalProp__AnotherPropsMixin); + static const String _$key__anExampleAdditionalProp__AnotherPropsMixin = + 'AnotherPropsMixin.anExampleAdditionalProp'; static const List $props = [ - _$prop__buttonDescription__UiForwardRefLogsPropsComplexComponentPropsMixin + _$prop__anExampleAdditionalProp__AnotherPropsMixin ]; static const List $propKeys = [ - _$key__buttonDescription__UiForwardRefLogsPropsComplexComponentPropsMixin + _$key__anExampleAdditionalProp__AnotherPropsMixin ]; } @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -const PropsMeta _$metaForUiForwardRefLogsPropsComplexComponentPropsMixin = - PropsMeta( - fields: $UiForwardRefLogsPropsComplexComponentPropsMixin.$props, - keys: $UiForwardRefLogsPropsComplexComponentPropsMixin.$propKeys, +const PropsMeta _$metaForAnotherPropsMixin = PropsMeta( + fields: $AnotherPropsMixin.$props, + keys: $AnotherPropsMixin.$propKeys, ); @Deprecated('This API is for use only within generated code.' @@ -304,60 +371,35 @@ const PropsMeta _$metaForUiForwardRefLogsPropsComplexComponentPropsMixin = mixin $LogPropsProps on LogPropsProps { static const PropsMeta meta = _$metaForLogPropsProps; @override - BuilderOnlyUiFactory get builder => + BuilderOnlyUiFactory get builder => props[_$key__builder__LogPropsProps] ?? null; // Add ` ?? null` to workaround DDC bug: ; @override - set builder(BuilderOnlyUiFactory value) => + set builder(BuilderOnlyUiFactory value) => props[_$key__builder__LogPropsProps] = value; @override - Ref get lastClickedButton => - props[_$key__lastClickedButton__LogPropsProps] ?? - null; // Add ` ?? null` to workaround DDC bug: ; - @override - set lastClickedButton(Ref value) => - props[_$key__lastClickedButton__LogPropsProps] = value; - @override Ref get _forwardedRef => props[_$key___forwardedRef__LogPropsProps] ?? null; // Add ` ?? null` to workaround DDC bug: ; @override set _forwardedRef(Ref value) => props[_$key___forwardedRef__LogPropsProps] = value; - @override - String get demoTitle => - props[_$key__demoTitle__LogPropsProps] ?? - null; // Add ` ?? null` to workaround DDC bug: ; - @override - set demoTitle(String value) => props[_$key__demoTitle__LogPropsProps] = value; /* GENERATED CONSTANTS */ static const PropDescriptor _$prop__builder__LogPropsProps = PropDescriptor(_$key__builder__LogPropsProps); - static const PropDescriptor _$prop__lastClickedButton__LogPropsProps = - PropDescriptor(_$key__lastClickedButton__LogPropsProps); static const PropDescriptor _$prop___forwardedRef__LogPropsProps = PropDescriptor(_$key___forwardedRef__LogPropsProps); - static const PropDescriptor _$prop__demoTitle__LogPropsProps = - PropDescriptor(_$key__demoTitle__LogPropsProps); static const String _$key__builder__LogPropsProps = 'LogPropsProps.builder'; - static const String _$key__lastClickedButton__LogPropsProps = - 'LogPropsProps.lastClickedButton'; static const String _$key___forwardedRef__LogPropsProps = 'LogPropsProps._forwardedRef'; - static const String _$key__demoTitle__LogPropsProps = - 'LogPropsProps.demoTitle'; static const List $props = [ _$prop__builder__LogPropsProps, - _$prop__lastClickedButton__LogPropsProps, - _$prop___forwardedRef__LogPropsProps, - _$prop__demoTitle__LogPropsProps + _$prop___forwardedRef__LogPropsProps ]; static const List $propKeys = [ _$key__builder__LogPropsProps, - _$key__lastClickedButton__LogPropsProps, - _$key___forwardedRef__LogPropsProps, - _$key__demoTitle__LogPropsProps + _$key___forwardedRef__LogPropsProps ]; } @@ -368,6 +410,50 @@ const PropsMeta _$metaForLogPropsProps = PropsMeta( keys: $LogPropsProps.$propKeys, ); +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.' + ' EXCEPTION: this may be used in legacy boilerplate until' + ' it is transitioned to the new mixin-based boilerplate.') +mixin $BazProps on BazProps { + static const PropsMeta meta = _$metaForBazProps; + @override + BuilderOnlyUiFactory get builder => + props[_$key__builder__BazProps] ?? + null; // Add ` ?? null` to workaround DDC bug: ; + @override + set builder(BuilderOnlyUiFactory value) => + props[_$key__builder__BazProps] = value; + @override + Ref get _forwardedRef => + props[_$key___forwardedRef__BazProps] ?? + null; // Add ` ?? null` to workaround DDC bug: ; + @override + set _forwardedRef(Ref value) => props[_$key___forwardedRef__BazProps] = value; + /* GENERATED CONSTANTS */ + static const PropDescriptor _$prop__builder__BazProps = + PropDescriptor(_$key__builder__BazProps); + static const PropDescriptor _$prop___forwardedRef__BazProps = + PropDescriptor(_$key___forwardedRef__BazProps); + static const String _$key__builder__BazProps = 'BazProps.builder'; + static const String _$key___forwardedRef__BazProps = 'BazProps._forwardedRef'; + + static const List $props = [ + _$prop__builder__BazProps, + _$prop___forwardedRef__BazProps + ]; + static const List $propKeys = [ + _$key__builder__BazProps, + _$key___forwardedRef__BazProps + ]; +} + +@Deprecated('This API is for use only within generated code.' + ' Do not reference it in your code, as it may change at any time.') +const PropsMeta _$metaForBazProps = PropsMeta( + fields: $BazProps.$props, + keys: $BazProps.$propKeys, +); + @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.' ' EXCEPTION: this may be used in legacy boilerplate until' @@ -453,116 +539,30 @@ const PropsMeta _$metaForRefDemoHocProps = PropsMeta( keys: $RefDemoHocProps.$propKeys, ); -final UiFactoryConfig<_$$UiForwardRefLogsFunctionComponentProps> - $UiForwardRefLogsFunctionComponentConfig = UiFactoryConfig( - propsFactory: PropsFactory( - map: (map) => _$$UiForwardRefLogsFunctionComponentProps(map), - jsMap: (map) => _$$UiForwardRefLogsFunctionComponentProps$JsMap(map), - ), - displayName: 'UiForwardRefLogsFunctionComponent'); +final UiFactoryConfig<_$$FancyButtonProps> $FancyButtonConfig = UiFactoryConfig( + propsFactory: PropsFactory( + map: (map) => _$$FancyButtonProps(map), + jsMap: (map) => _$$FancyButtonProps$JsMap(map), + ), + displayName: 'FancyButton'); // Concrete props implementation. // // Implements constructor and backing map, and links up to generated component factory. @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -abstract class _$$UiForwardRefLogsFunctionComponentProps extends UiProps +abstract class _$$FancyButtonProps extends UiProps with - UiForwardRefLogsFunctionComponentProps, - $UiForwardRefLogsFunctionComponentProps // If this generated mixin is undefined, it's likely because UiForwardRefLogsFunctionComponentProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of UiForwardRefLogsFunctionComponentProps. + FancyButtonProps, + $FancyButtonProps // If this generated mixin is undefined, it's likely because FancyButtonProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of FancyButtonProps. { - _$$UiForwardRefLogsFunctionComponentProps._(); - - factory _$$UiForwardRefLogsFunctionComponentProps(Map backingMap) { - if (backingMap == null || backingMap is JsBackedMap) { - return _$$UiForwardRefLogsFunctionComponentProps$JsMap(backingMap); - } else { - return _$$UiForwardRefLogsFunctionComponentProps$PlainMap(backingMap); - } - } - - /// Let `UiProps` internals know that this class has been generated. - @override - bool get $isClassGenerated => true; - - /// The default namespace for the prop getters/setters generated for this class. - @override - String get propKeyNamespace => ''; -} - -// Concrete props implementation that can be backed by any [Map]. -@Deprecated('This API is for use only within generated code.' - ' Do not reference it in your code, as it may change at any time.') -class _$$UiForwardRefLogsFunctionComponentProps$PlainMap - extends _$$UiForwardRefLogsFunctionComponentProps { - // This initializer of `_props` to an empty map, as well as the reassignment - // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 - _$$UiForwardRefLogsFunctionComponentProps$PlainMap(Map backingMap) - : this._props = {}, - super._() { - this._props = backingMap ?? {}; - } - - /// The backing props map proxied by this class. - @override - Map get props => _props; - Map _props; -} - -// Concrete props implementation that can only be backed by [JsMap], -// allowing dart2js to compile more optimal code for key-value pair reads/writes. -@Deprecated('This API is for use only within generated code.' - ' Do not reference it in your code, as it may change at any time.') -class _$$UiForwardRefLogsFunctionComponentProps$JsMap - extends _$$UiForwardRefLogsFunctionComponentProps { - // This initializer of `_props` to an empty map, as well as the reassignment - // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 - _$$UiForwardRefLogsFunctionComponentProps$JsMap(JsBackedMap backingMap) - : this._props = JsBackedMap(), - super._() { - this._props = backingMap ?? JsBackedMap(); - } - - /// The backing props map proxied by this class. - @override - JsBackedMap get props => _props; - JsBackedMap _props; -} - -final UiFactoryConfig<_$$UiForwardRefLogsPropsComplexFunctionComponentProps> - $UiForwardRefLogsPropsComplexFunctionComponentConfig = UiFactoryConfig( - propsFactory: PropsFactory( - map: (map) => - _$$UiForwardRefLogsPropsComplexFunctionComponentProps(map), - jsMap: (map) => - _$$UiForwardRefLogsPropsComplexFunctionComponentProps$JsMap(map), - ), - displayName: 'UiForwardRefLogsPropsComplexFunctionComponent'); - -// Concrete props implementation. -// -// Implements constructor and backing map, and links up to generated component factory. -@Deprecated('This API is for use only within generated code.' - ' Do not reference it in your code, as it may change at any time.') -abstract class _$$UiForwardRefLogsPropsComplexFunctionComponentProps - extends UiProps - with - UiForwardRefLogsPropsComplexFunctionComponentPropsMixin, - $UiForwardRefLogsPropsComplexFunctionComponentPropsMixin, // If this generated mixin is undefined, it's likely because UiForwardRefLogsPropsComplexFunctionComponentPropsMixin is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of UiForwardRefLogsPropsComplexFunctionComponentPropsMixin. - UiForwardRefLogsFunctionComponentProps, - $UiForwardRefLogsFunctionComponentProps // If this generated mixin is undefined, it's likely because UiForwardRefLogsFunctionComponentProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of UiForwardRefLogsFunctionComponentProps. - implements - UiForwardRefLogsPropsComplexFunctionComponentProps { - _$$UiForwardRefLogsPropsComplexFunctionComponentProps._(); + _$$FancyButtonProps._(); - factory _$$UiForwardRefLogsPropsComplexFunctionComponentProps( - Map backingMap) { + factory _$$FancyButtonProps(Map backingMap) { if (backingMap == null || backingMap is JsBackedMap) { - return _$$UiForwardRefLogsPropsComplexFunctionComponentProps$JsMap( - backingMap); + return _$$FancyButtonProps$JsMap(backingMap); } else { - return _$$UiForwardRefLogsPropsComplexFunctionComponentProps$PlainMap( - backingMap); + return _$$FancyButtonProps$PlainMap(backingMap); } } @@ -578,11 +578,10 @@ abstract class _$$UiForwardRefLogsPropsComplexFunctionComponentProps // Concrete props implementation that can be backed by any [Map]. @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -class _$$UiForwardRefLogsPropsComplexFunctionComponentProps$PlainMap - extends _$$UiForwardRefLogsPropsComplexFunctionComponentProps { +class _$$FancyButtonProps$PlainMap extends _$$FancyButtonProps { // This initializer of `_props` to an empty map, as well as the reassignment // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 - _$$UiForwardRefLogsPropsComplexFunctionComponentProps$PlainMap(Map backingMap) + _$$FancyButtonProps$PlainMap(Map backingMap) : this._props = {}, super._() { this._props = backingMap ?? {}; @@ -598,12 +597,10 @@ class _$$UiForwardRefLogsPropsComplexFunctionComponentProps$PlainMap // allowing dart2js to compile more optimal code for key-value pair reads/writes. @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -class _$$UiForwardRefLogsPropsComplexFunctionComponentProps$JsMap - extends _$$UiForwardRefLogsPropsComplexFunctionComponentProps { +class _$$FancyButtonProps$JsMap extends _$$FancyButtonProps { // This initializer of `_props` to an empty map, as well as the reassignment // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 - _$$UiForwardRefLogsPropsComplexFunctionComponentProps$JsMap( - JsBackedMap backingMap) + _$$FancyButtonProps$JsMap(JsBackedMap backingMap) : this._props = JsBackedMap(), super._() { this._props = backingMap ?? JsBackedMap(); @@ -615,35 +612,33 @@ class _$$UiForwardRefLogsPropsComplexFunctionComponentProps$JsMap JsBackedMap _props; } -final UiFactoryConfig<_$$UiForwardRefLogsPropsComplexComponentProps> - $UiForwardRefLogsPropsComplexComponentConfig = UiFactoryConfig( - propsFactory: PropsFactory( - map: (map) => _$$UiForwardRefLogsPropsComplexComponentProps(map), - jsMap: (map) => - _$$UiForwardRefLogsPropsComplexComponentProps$JsMap(map), - ), - displayName: 'UiForwardRefLogsPropsComplexComponent'); +final UiFactoryConfig<_$$Foo2Props> $Foo2Config = UiFactoryConfig( + propsFactory: PropsFactory( + map: (map) => _$$Foo2Props(map), + jsMap: (map) => _$$Foo2Props$JsMap(map), + ), + displayName: 'Foo2'); // Concrete props implementation. // // Implements constructor and backing map, and links up to generated component factory. @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -abstract class _$$UiForwardRefLogsPropsComplexComponentProps extends UiProps +abstract class _$$Foo2Props extends UiProps with - UiForwardRefLogsPropsComplexComponentPropsMixin, - $UiForwardRefLogsPropsComplexComponentPropsMixin, // If this generated mixin is undefined, it's likely because UiForwardRefLogsPropsComplexComponentPropsMixin is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of UiForwardRefLogsPropsComplexComponentPropsMixin. - LogPropsProps, - $LogPropsProps // If this generated mixin is undefined, it's likely because LogPropsProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of LogPropsProps. + AnotherPropsMixin, + $AnotherPropsMixin, // If this generated mixin is undefined, it's likely because AnotherPropsMixin is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of AnotherPropsMixin. + FooProps, + $FooProps // If this generated mixin is undefined, it's likely because FooProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of FooProps. implements - UiForwardRefLogsPropsComplexComponentProps { - _$$UiForwardRefLogsPropsComplexComponentProps._(); + Foo2Props { + _$$Foo2Props._(); - factory _$$UiForwardRefLogsPropsComplexComponentProps(Map backingMap) { + factory _$$Foo2Props(Map backingMap) { if (backingMap == null || backingMap is JsBackedMap) { - return _$$UiForwardRefLogsPropsComplexComponentProps$JsMap(backingMap); + return _$$Foo2Props$JsMap(backingMap); } else { - return _$$UiForwardRefLogsPropsComplexComponentProps$PlainMap(backingMap); + return _$$Foo2Props$PlainMap(backingMap); } } @@ -659,11 +654,10 @@ abstract class _$$UiForwardRefLogsPropsComplexComponentProps extends UiProps // Concrete props implementation that can be backed by any [Map]. @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -class _$$UiForwardRefLogsPropsComplexComponentProps$PlainMap - extends _$$UiForwardRefLogsPropsComplexComponentProps { +class _$$Foo2Props$PlainMap extends _$$Foo2Props { // This initializer of `_props` to an empty map, as well as the reassignment // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 - _$$UiForwardRefLogsPropsComplexComponentProps$PlainMap(Map backingMap) + _$$Foo2Props$PlainMap(Map backingMap) : this._props = {}, super._() { this._props = backingMap ?? {}; @@ -679,11 +673,10 @@ class _$$UiForwardRefLogsPropsComplexComponentProps$PlainMap // allowing dart2js to compile more optimal code for key-value pair reads/writes. @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -class _$$UiForwardRefLogsPropsComplexComponentProps$JsMap - extends _$$UiForwardRefLogsPropsComplexComponentProps { +class _$$Foo2Props$JsMap extends _$$Foo2Props { // This initializer of `_props` to an empty map, as well as the reassignment // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 - _$$UiForwardRefLogsPropsComplexComponentProps$JsMap(JsBackedMap backingMap) + _$$Foo2Props$JsMap(JsBackedMap backingMap) : this._props = JsBackedMap(), super._() { this._props = backingMap ?? JsBackedMap(); @@ -695,32 +688,30 @@ class _$$UiForwardRefLogsPropsComplexComponentProps$JsMap JsBackedMap _props; } -final UiFactoryConfig<_$$_LogsPropsFunctionComponentProps> - $_LogsPropsFunctionComponentConfig = UiFactoryConfig( - propsFactory: PropsFactory( - map: (map) => _$$_LogsPropsFunctionComponentProps(map), - jsMap: (map) => _$$_LogsPropsFunctionComponentProps$JsMap(map), - ), - displayName: '_LogsPropsFunctionComponent'); +final UiFactoryConfig<_$$BazProps> $BazConfig = UiFactoryConfig( + propsFactory: PropsFactory( + map: (map) => _$$BazProps(map), + jsMap: (map) => _$$BazProps$JsMap(map), + ), + displayName: 'Baz'); // Concrete props implementation. // // Implements constructor and backing map, and links up to generated component factory. @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -abstract class _$$_LogsPropsFunctionComponentProps extends UiProps +abstract class _$$BazProps extends UiProps with - LogPropsProps, - $LogPropsProps // If this generated mixin is undefined, it's likely because LogPropsProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of LogPropsProps. - implements - _LogsPropsFunctionComponentProps { - _$$_LogsPropsFunctionComponentProps._(); + BazProps, + $BazProps // If this generated mixin is undefined, it's likely because BazProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of BazProps. +{ + _$$BazProps._(); - factory _$$_LogsPropsFunctionComponentProps(Map backingMap) { + factory _$$BazProps(Map backingMap) { if (backingMap == null || backingMap is JsBackedMap) { - return _$$_LogsPropsFunctionComponentProps$JsMap(backingMap); + return _$$BazProps$JsMap(backingMap); } else { - return _$$_LogsPropsFunctionComponentProps$PlainMap(backingMap); + return _$$BazProps$PlainMap(backingMap); } } @@ -736,11 +727,10 @@ abstract class _$$_LogsPropsFunctionComponentProps extends UiProps // Concrete props implementation that can be backed by any [Map]. @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -class _$$_LogsPropsFunctionComponentProps$PlainMap - extends _$$_LogsPropsFunctionComponentProps { +class _$$BazProps$PlainMap extends _$$BazProps { // This initializer of `_props` to an empty map, as well as the reassignment // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 - _$$_LogsPropsFunctionComponentProps$PlainMap(Map backingMap) + _$$BazProps$PlainMap(Map backingMap) : this._props = {}, super._() { this._props = backingMap ?? {}; @@ -756,11 +746,10 @@ class _$$_LogsPropsFunctionComponentProps$PlainMap // allowing dart2js to compile more optimal code for key-value pair reads/writes. @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -class _$$_LogsPropsFunctionComponentProps$JsMap - extends _$$_LogsPropsFunctionComponentProps { +class _$$BazProps$JsMap extends _$$BazProps { // This initializer of `_props` to an empty map, as well as the reassignment // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 - _$$_LogsPropsFunctionComponentProps$JsMap(JsBackedMap backingMap) + _$$BazProps$JsMap(JsBackedMap backingMap) : this._props = JsBackedMap(), super._() { this._props = backingMap ?? JsBackedMap(); From 49df84cf6ff37258250eb1967b779720113073be Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Fri, 7 Aug 2020 07:57:56 -0700 Subject: [PATCH 23/28] Add integration tests --- .../function_component_test.dart | 202 ++++++++++++++---- 1 file changed, 158 insertions(+), 44 deletions(-) diff --git a/test/over_react/component_declaration/builder_integration_tests/new_boilerplate/function_component_test.dart b/test/over_react/component_declaration/builder_integration_tests/new_boilerplate/function_component_test.dart index 58f780ddf..1499dd8a9 100644 --- a/test/over_react/component_declaration/builder_integration_tests/new_boilerplate/function_component_test.dart +++ b/test/over_react/component_declaration/builder_integration_tests/new_boilerplate/function_component_test.dart @@ -41,50 +41,10 @@ main() { functionComponentTestHelper(_Test, testId: '_testId'); }); - group('with UiProps', () { - UiFactory TestUiProps = uiFunction( - (props) => (Dom.div()..addTestId('testId3'))('id: ${props.id}'), - UiFactoryConfig(), - ); - - test( - 'renders a component from end to end, successfully reading props via typed getters', - () { - final jacket = mount((TestUiProps()..id = '1')()); - final node = queryAllByTestId(jacket.mountNode, 'testId3').first; - - expect(node, isA()); - expect(node.text, 'id: 1'); - }); - - group('initializes the factory variable with a function', () { - test('that returns a new props class implementation instance', () { - final instance = TestUiProps(); - expect(instance, isA()); - expect(instance, isA()); - }); - - test( - 'that returns a new props class implementation instance backed by an existing map', - () { - Map existingMap = {'key': 'test'}; - final props = TestUiProps(existingMap); - - expect(props.key, equals('test')); - - props.key = 'modified'; - expect(props.key, equals('modified')); - expect(existingMap['key'], equals('modified')); - }); - }); - - test( - 'generates prop getters/setters with the prop name as the key by default', - () { - expect(TestUiProps()..key = 'test', containsPair('key', 'test')); - expect(TestUiProps()..id = '2', containsPair('id', '2')); - }); - }); + uiPropsTest(uiFunction( + (props) => (Dom.div()..addTestId('testId3'))('id: ${props.id}'), + UiFactoryConfig(), + )); group('throws an error when', () { test('config is null', () { @@ -106,6 +66,94 @@ main() { }); }); }); + + group('uiForwardRef', () { + group('with generated props config', () { + functionComponentTestHelper(BasicUiForwardRef); + }); + + group('with custom PropsFactory', () { + functionComponentTestHelper(CustomUiForwardRef, testId: 'testIdCustom'); + }); + + group('with no left hand typing', () { + functionComponentTestHelper(NoLHSUiForwardRefTest, testId: 'testIdNoLHS'); + }); + + group('with private prefix', () { + functionComponentTestHelper(_UiForwardRef, testId: '_testId'); + }); + + uiPropsTest(uiForwardRef( + (props, ref) => (Dom.div() + ..addTestId('testId3') + ..ref = ref + )('id: ${props.id}'), + Dom.div.asForwardRefConfig(), + )); + + group('throws an error when', () { + test('config is null', () { + expect( + () => uiForwardRef( + (props, ref) => Dom.div()(), + null, + ), + throwsArgumentError); + }); + + test('props factory is not provided when using custom props class', () { + expect( + () => uiForwardRef( + (props, ref) => Dom.div()(), + UiFactoryConfig(displayName: 'Foo'), + ), + throwsArgumentError); + }); + }); + }); +} + +void uiPropsTest(UiFactory factory) { + group('with UiProps', () { + test( + 'renders a component from end to end, successfully reading props via typed getters', + () { + final jacket = mount((factory()..id = '1')()); + final node = queryAllByTestId(jacket.mountNode, 'testId3').first; + + expect(node, isA()); + expect(node.text, 'id: 1'); + }); + + group('initializes the factory variable with a function', () { + test('that returns a new props class implementation instance', () { + final instance = factory(); + expect(instance, isA()); + expect(instance, isA()); + }); + + test( + 'that returns a new props class implementation instance backed by an existing map', + () { + Map existingMap = {'key': 'test'}; + final props = factory(existingMap); + + expect(props.key, equals('test')); + + props.key = 'modified'; + expect(props.key, equals('modified')); + expect(existingMap['key'], equals('modified')); + }); + }); + + test( + 'generates prop getters/setters with the prop name as the key by default', + () { + expect(factory()..key = 'test', containsPair('key', 'test')); + expect(factory()..id = '2', containsPair('id', '2')); + }); + }); } void functionComponentTestHelper(UiFactory factory, @@ -186,6 +234,72 @@ void functionComponentTestHelper(UiFactory factory, }); } +UiFactory BasicUiForwardRef = uiForwardRef( + (props, ref) { + return (Dom.div() + ..ref = ref + ..addTestId('testId') + ..addProp('data-prop-string-prop', props.stringProp) + ..addProp('data-prop-dynamic-prop', props.dynamicProp) + ..addProp('data-prop-untyped-prop', props.untypedProp) + ..addProp('data-prop-custom-key-prop', props.customKeyProp) + ..addProp('data-prop-custom-namespace-prop', props.customNamespaceProp) + ..addProp('data-prop-custom-key-and-namespace-prop', + props.customKeyAndNamespaceProp))('rendered content'); + }, + $TestConfig, // ignore: undefined_identifier +); + +UiFactory CustomUiForwardRef = uiForwardRef( + (props, ref) { + return (Dom.div() + ..ref = ref + ..addTestId('testIdCustom') + ..addProp('data-prop-string-prop', props.stringProp) + ..addProp('data-prop-dynamic-prop', props.dynamicProp) + ..addProp('data-prop-untyped-prop', props.untypedProp) + ..addProp('data-prop-custom-key-prop', props.customKeyProp) + ..addProp('data-prop-custom-namespace-prop', props.customNamespaceProp) + ..addProp('data-prop-custom-key-and-namespace-prop', + props.customKeyAndNamespaceProp))('rendered content'); + }, + UiFactoryConfig( + propsFactory: PropsFactory.fromUiFactory(BasicUiForwardRef), + ) +); + +final NoLHSUiForwardRefTest = uiForwardRef( + (props, ref) { + return (Dom.div() + ..ref = ref + ..addTestId('testIdNoLHS') + ..addProp('data-prop-string-prop', props.stringProp) + ..addProp('data-prop-dynamic-prop', props.dynamicProp) + ..addProp('data-prop-untyped-prop', props.untypedProp) + ..addProp('data-prop-custom-key-prop', props.customKeyProp) + ..addProp('data-prop-custom-namespace-prop', props.customNamespaceProp) + ..addProp('data-prop-custom-key-and-namespace-prop', + props.customKeyAndNamespaceProp))('rendered content'); + }, + $NoLHSTestConfig, // ignore: undefined_identifier +); + +UiFactory _UiForwardRef = uiForwardRef( + (props, ref) { + return (Dom.div() + ..ref = ref + ..addTestId('_testId') + ..addProp('data-prop-string-prop', props.stringProp) + ..addProp('data-prop-dynamic-prop', props.dynamicProp) + ..addProp('data-prop-untyped-prop', props.untypedProp) + ..addProp('data-prop-custom-key-prop', props.customKeyProp) + ..addProp('data-prop-custom-namespace-prop', props.customNamespaceProp) + ..addProp('data-prop-custom-key-and-namespace-prop', + props.customKeyAndNamespaceProp))('rendered content'); + }, + $_TestConfig, // ignore: undefined_identifier +); + UiFactory Test = uiFunction( (props) { return (Dom.div() From acf2582fe4da7368ff99866173890dd17ed35f2b Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Fri, 7 Aug 2020 08:10:40 -0700 Subject: [PATCH 24/28] Format --- web/component2/src/demos/ref.dart | 105 ++++++++---------- .../src/demos/ref.over_react.g.dart | 99 ++++++++--------- 2 files changed, 95 insertions(+), 109 deletions(-) diff --git a/web/component2/src/demos/ref.dart b/web/component2/src/demos/ref.dart index 1fb01a161..f9424a8a0 100644 --- a/web/component2/src/demos/ref.dart +++ b/web/component2/src/demos/ref.dart @@ -18,15 +18,14 @@ part 'ref.over_react.g.dart'; mixin FancyButtonProps on UiProps {} UiFactory FancyButton = uiForwardRef( - (props, ref) { - final classes = ClassNameBuilder.fromProps(props)..add('FancyButton'); - return (Dom.button() + (props, ref) { + final classes = ClassNameBuilder.fromProps(props)..add('FancyButton'); + return (Dom.button() ..ref = ref ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) - ..className = classes.toClassName() - )('Click me!'); - }, - $FancyButtonConfig, // ignore: undefined_identifier + ..className = classes.toClassName())('Click me!'); + }, + $FancyButtonConfig, // ignore: undefined_identifier ); //----------------------------------------------------------------------------// @@ -36,15 +35,15 @@ UiFactory FancyButton = uiForwardRef( /// Wraps a component ([factoryToWrap]) in a new component that logs when rendered. UiFactory withLogging(UiFactory factoryToWrap) { - return uiForwardRef((props, ref) { - useEffect(() => 'withLogging rendered!'); - - // This requires an ignore until https://github.com/dart-lang/sdk/issues/42975 - // is fixed. - return (factoryToWrap() // ignore: invocation_of_non_function_expression - ..addAll(props) - ..ref = ref - )(props.children); + return uiForwardRef( + (props, ref) { + useEffect(() => 'withLogging rendered!'); + + // This requires an ignore until https://github.com/dart-lang/sdk/issues/42975 + // is fixed. + return (factoryToWrap() // ignore: invocation_of_non_function_expression + ..addAll(props) + ..ref = ref)(props.children); }, factoryToWrap.asForwardRefConfig( displayName: 'WithLogging', @@ -71,22 +70,19 @@ mixin FooProps on UiProps { class FooComponent extends UiComponent2 { @override render() { - return Dom.div()( - (Dom.input() - ..modifyProps(addUnconsumedDomProps) - ..type = 'text' - ..ref = props._inputRef - )() - ); + return Dom.div()((Dom.input() + ..modifyProps(addUnconsumedDomProps) + ..type = 'text' + ..ref = props._inputRef)()); } } // Option 1: Use the class component's factory as the UiFactoryConfig arg. -UiFactory Foo = uiForwardRef((props, ref) { +UiFactory Foo = uiForwardRef( + (props, ref) { return (_Foo() ..addProps(props) - .._inputRef = ref - )(); + .._inputRef = ref)(); }, _Foo.asForwardRefConfig(), ); @@ -98,12 +94,12 @@ mixin AnotherPropsMixin on UiProps { class Foo2Props = UiProps with AnotherPropsMixin, FooProps; -final Foo2 = uiForwardRef((props, ref) { +final Foo2 = uiForwardRef( + (props, ref) { print(props.anExampleAdditionalProp); return (_Foo() ..addProps(props) - .._inputRef = ref - )(); + .._inputRef = ref)(); }, $Foo2Config, // ignore: undefined_identifier ); @@ -114,19 +110,18 @@ final Foo2 = uiForwardRef((props, ref) { //----------------------------------------------------------------------------// //----------------------------------------------------------------------------// - //----------------------------------------------------------------------------// // ### Example 1: Exposing inner refs in class components: //----------------------------------------------------------------------------// -UiFactory LogProps = forwardRef((props, ref) { - return (_LogProps() +UiFactory LogPropsHoc = forwardRef((props, ref) { + return (_Log() ..addProps(props) .._forwardedRef = ref)(); -}, displayName: 'LogProps')(_LogProps); +}, displayName: 'LogProps')(_Log); -UiFactory _LogProps = _$_LogProps; // ignore: undefined_identifier +UiFactory _Log = _$_Log; // ignore: undefined_identifier -mixin LogPropsProps on UiProps { +mixin LogProps on UiProps { BuilderOnlyUiFactory builder; // Private since we only use this to pass along the value of `ref` to @@ -136,9 +131,12 @@ mixin LogPropsProps on UiProps { Ref _forwardedRef; } -class _LogPropsComponent extends UiComponent2 { +class _LogComponent extends UiComponent2 { @override - void componentDidUpdate(_, __, [___]) => print('${props.builder().componentFactory.type} rendered!'); + void componentDidUpdate(Map prevProps, _, [__]) { + print('old props: $prevProps'); + print('new props: $props'); + } @override render() { @@ -185,7 +183,7 @@ mixin RefDemoProps on UiProps {} UiFactory RefDemoContainer = uiFunction( (props) { - // `uiForwardRef` Refs + // `uiForwardRef` Refs final fancyButtonUiForwardRef = createRef(); final fancyButtonWithLoggingReg = createRef(); final fooInputRef = createRef(); @@ -201,38 +199,29 @@ UiFactory RefDemoContainer = uiFunction( (FancyButton() ..className = 'btn btn-primary' ..ref = fancyButtonUiForwardRef - ..onClick = (_) => printButtonOuterHtml(fancyButtonUiForwardRef) - )(), + ..onClick = (_) => printButtonOuterHtml(fancyButtonUiForwardRef))(), ), (RefDemoHoc()..demoTitle = '`uiForwardRef` wrapped in HOC')( (FancyButtonWithLogging() ..className = 'btn btn-success' ..ref = fancyButtonWithLoggingReg - ..onClick = (_) => printButtonOuterHtml(fancyButtonUiForwardRef) - )(), - ), - (RefDemoHoc()..demoTitle = '`uiForwardRef` wrapping a class (option 1)')( - (Foo() - ..ref=fooInputRef - ..onChange=(e) => print('Foo Input Ref: ${e.target.value}') - )() - ), - (RefDemoHoc()..demoTitle = '`uiForwardRef` wrapping a class (option 2)')( - (Foo2() - ..anExampleAdditionalProp = 'This additional prop logs on renders!' - ..ref=foo2InputRef - ..onChange=(e) => print('Foo2 Input Ref: ${e.target.value}') - )() + ..onClick = (_) => printButtonOuterHtml(fancyButtonUiForwardRef))(), ), + (RefDemoHoc()..demoTitle = '`uiForwardRef` wrapping a class (option 1)')((Foo() + ..ref = fooInputRef + ..onChange = (e) => print('Foo Input Ref: ${e.target.value}'))()), + (RefDemoHoc()..demoTitle = '`uiForwardRef` wrapping a class (option 2)')((Foo2() + ..anExampleAdditionalProp = 'This additional prop logs on renders!' + ..ref = foo2InputRef + ..onChange = (e) => print('Foo2 Input Ref: ${e.target.value}'))()), ), (RefDemoSection()..sectionTitle = 'forwardRef (deprecated) Demos')( (RefDemoHoc()..demoTitle = '`forwardRef` with class component')( - (LogProps() + (LogPropsHoc() ..builder = FancyButton ..ref = fancyButtonNodeRef ..className = 'btn btn-primary' - ..onClick = (_) => printButtonOuterHtml(fancyButtonNodeRef) - )(), + ..onClick = (_) => printButtonOuterHtml(fancyButtonNodeRef))(), ), (RefDemoHoc()..demoTitle = '`uiForwardRef` with function component')( (LoggingFunctionWrapper() diff --git a/web/component2/src/demos/ref.over_react.g.dart b/web/component2/src/demos/ref.over_react.g.dart index 2cc2683ac..43d30531d 100644 --- a/web/component2/src/demos/ref.over_react.g.dart +++ b/web/component2/src/demos/ref.over_react.g.dart @@ -149,36 +149,36 @@ class _$FooComponent extends FooComponent { // Registers component implementation and links type meta to builder factory. @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -final $_LogPropsComponentFactory = registerComponent2( - () => _$_LogPropsComponent(), - builderFactory: _$_LogProps, - componentClass: _LogPropsComponent, +final $_LogComponentFactory = registerComponent2( + () => _$_LogComponent(), + builderFactory: _$_Log, + componentClass: _LogComponent, isWrapper: false, parentType: null, - displayName: '_LogProps', + displayName: '_Log', ); -_$$LogPropsProps _$_LogProps([Map backingProps]) => backingProps == null - ? _$$LogPropsProps$JsMap(JsBackedMap()) - : _$$LogPropsProps(backingProps); +_$$LogProps _$_Log([Map backingProps]) => backingProps == null + ? _$$LogProps$JsMap(JsBackedMap()) + : _$$LogProps(backingProps); // Concrete props implementation. // // Implements constructor and backing map, and links up to generated component factory. @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -abstract class _$$LogPropsProps extends UiProps +abstract class _$$LogProps extends UiProps with - LogPropsProps, - $LogPropsProps // If this generated mixin is undefined, it's likely because LogPropsProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of LogPropsProps. + LogProps, + $LogProps // If this generated mixin is undefined, it's likely because LogProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of LogProps. { - _$$LogPropsProps._(); + _$$LogProps._(); - factory _$$LogPropsProps(Map backingMap) { + factory _$$LogProps(Map backingMap) { if (backingMap == null || backingMap is JsBackedMap) { - return _$$LogPropsProps$JsMap(backingMap); + return _$$LogProps$JsMap(backingMap); } else { - return _$$LogPropsProps$PlainMap(backingMap); + return _$$LogProps$PlainMap(backingMap); } } @@ -189,7 +189,7 @@ abstract class _$$LogPropsProps extends UiProps /// The `ReactComponentFactory` associated with the component built by this class. @override ReactComponentFactoryProxy get componentFactory => - super.componentFactory ?? $_LogPropsComponentFactory; + super.componentFactory ?? $_LogComponentFactory; /// The default namespace for the prop getters/setters generated for this class. @override @@ -199,10 +199,10 @@ abstract class _$$LogPropsProps extends UiProps // Concrete props implementation that can be backed by any [Map]. @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -class _$$LogPropsProps$PlainMap extends _$$LogPropsProps { +class _$$LogProps$PlainMap extends _$$LogProps { // This initializer of `_props` to an empty map, as well as the reassignment // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 - _$$LogPropsProps$PlainMap(Map backingMap) + _$$LogProps$PlainMap(Map backingMap) : this._props = {}, super._() { this._props = backingMap ?? {}; @@ -218,10 +218,10 @@ class _$$LogPropsProps$PlainMap extends _$$LogPropsProps { // allowing dart2js to compile more optimal code for key-value pair reads/writes. @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -class _$$LogPropsProps$JsMap extends _$$LogPropsProps { +class _$$LogProps$JsMap extends _$$LogProps { // This initializer of `_props` to an empty map, as well as the reassignment // of `_props` in the constructor body is necessary to work around a DDC bug: https://github.com/dart-lang/sdk/issues/36217 - _$$LogPropsProps$JsMap(JsBackedMap backingMap) + _$$LogProps$JsMap(JsBackedMap backingMap) : this._props = JsBackedMap(), super._() { this._props = backingMap ?? JsBackedMap(); @@ -239,11 +239,11 @@ class _$$LogPropsProps$JsMap extends _$$LogPropsProps { // generated for the associated props class. @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -class _$_LogPropsComponent extends _LogPropsComponent { - _$$LogPropsProps$JsMap _cachedTypedProps; +class _$_LogComponent extends _LogComponent { + _$$LogProps$JsMap _cachedTypedProps; @override - _$$LogPropsProps$JsMap get props => _cachedTypedProps; + _$$LogProps$JsMap get props => _cachedTypedProps; @override set props(Map value) { @@ -259,26 +259,25 @@ class _$_LogPropsComponent extends _LogPropsComponent { } @override - _$$LogPropsProps$JsMap typedPropsFactoryJs(JsBackedMap backingMap) => - _$$LogPropsProps$JsMap(backingMap); + _$$LogProps$JsMap typedPropsFactoryJs(JsBackedMap backingMap) => + _$$LogProps$JsMap(backingMap); @override - _$$LogPropsProps typedPropsFactory(Map backingMap) => - _$$LogPropsProps(backingMap); + _$$LogProps typedPropsFactory(Map backingMap) => _$$LogProps(backingMap); /// Let `UiComponent` internals know that this class has been generated. @override bool get $isClassGenerated => true; - /// The default consumed props, comprising all props mixins used by LogPropsProps. + /// The default consumed props, comprising all props mixins used by LogProps. /// Used in `*ConsumedProps` methods if [consumedProps] is not overridden. @override get $defaultConsumedProps => propsMeta.all; @override PropsMetaCollection get propsMeta => const PropsMetaCollection({ - // If this generated mixin is undefined, it's likely because LogPropsProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of LogPropsProps. - LogPropsProps: $LogPropsProps.meta, + // If this generated mixin is undefined, it's likely because LogProps is not a valid `mixin`-based props mixin, or because it is but the generated mixin was not exported. Check the declaration of LogProps. + LogProps: $LogProps.meta, }); } @@ -368,46 +367,44 @@ const PropsMeta _$metaForAnotherPropsMixin = PropsMeta( ' Do not reference it in your code, as it may change at any time.' ' EXCEPTION: this may be used in legacy boilerplate until' ' it is transitioned to the new mixin-based boilerplate.') -mixin $LogPropsProps on LogPropsProps { - static const PropsMeta meta = _$metaForLogPropsProps; +mixin $LogProps on LogProps { + static const PropsMeta meta = _$metaForLogProps; @override BuilderOnlyUiFactory get builder => - props[_$key__builder__LogPropsProps] ?? + props[_$key__builder__LogProps] ?? null; // Add ` ?? null` to workaround DDC bug: ; @override set builder(BuilderOnlyUiFactory value) => - props[_$key__builder__LogPropsProps] = value; + props[_$key__builder__LogProps] = value; @override Ref get _forwardedRef => - props[_$key___forwardedRef__LogPropsProps] ?? + props[_$key___forwardedRef__LogProps] ?? null; // Add ` ?? null` to workaround DDC bug: ; @override - set _forwardedRef(Ref value) => - props[_$key___forwardedRef__LogPropsProps] = value; + set _forwardedRef(Ref value) => props[_$key___forwardedRef__LogProps] = value; /* GENERATED CONSTANTS */ - static const PropDescriptor _$prop__builder__LogPropsProps = - PropDescriptor(_$key__builder__LogPropsProps); - static const PropDescriptor _$prop___forwardedRef__LogPropsProps = - PropDescriptor(_$key___forwardedRef__LogPropsProps); - static const String _$key__builder__LogPropsProps = 'LogPropsProps.builder'; - static const String _$key___forwardedRef__LogPropsProps = - 'LogPropsProps._forwardedRef'; + static const PropDescriptor _$prop__builder__LogProps = + PropDescriptor(_$key__builder__LogProps); + static const PropDescriptor _$prop___forwardedRef__LogProps = + PropDescriptor(_$key___forwardedRef__LogProps); + static const String _$key__builder__LogProps = 'LogProps.builder'; + static const String _$key___forwardedRef__LogProps = 'LogProps._forwardedRef'; static const List $props = [ - _$prop__builder__LogPropsProps, - _$prop___forwardedRef__LogPropsProps + _$prop__builder__LogProps, + _$prop___forwardedRef__LogProps ]; static const List $propKeys = [ - _$key__builder__LogPropsProps, - _$key___forwardedRef__LogPropsProps + _$key__builder__LogProps, + _$key___forwardedRef__LogProps ]; } @Deprecated('This API is for use only within generated code.' ' Do not reference it in your code, as it may change at any time.') -const PropsMeta _$metaForLogPropsProps = PropsMeta( - fields: $LogPropsProps.$props, - keys: $LogPropsProps.$propKeys, +const PropsMeta _$metaForLogProps = PropsMeta( + fields: $LogProps.$props, + keys: $LogProps.$propKeys, ); @Deprecated('This API is for use only within generated code.' From af9e2e4c38c83f02f44ac5fbe31169aef294d87b Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Fri, 7 Aug 2020 08:21:06 -0700 Subject: [PATCH 25/28] Update doc comment --- lib/src/builder/parsing/ast_util.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/builder/parsing/ast_util.dart b/lib/src/builder/parsing/ast_util.dart index 489eb4b33..5fd91688e 100644 --- a/lib/src/builder/parsing/ast_util.dart +++ b/lib/src/builder/parsing/ast_util.dart @@ -42,7 +42,7 @@ extension InitializerHelperTopLevel on TopLevelVariableDeclaration { /// The first variable in this list. VariableDeclaration get firstVariable => variables.firstVariable; - /// Returns whether or not the config argument of a Function type is generated. + /// Returns whether or not there is a generated config being used. bool get usesAGeneratedConfig { return firstInitializer != null && anyDescendantIdentifiers(firstInitializer, (identifier) { From 31b3414d9ba4bbffdb2d86624922fd1565dc16fa Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Fri, 7 Aug 2020 10:27:28 -0700 Subject: [PATCH 26/28] Address more feedback :tada: --- web/component2/src/demos/ref.dart | 99 ++++++++++++------- .../src/demos/ref.over_react.g.dart | 10 +- 2 files changed, 68 insertions(+), 41 deletions(-) diff --git a/web/component2/src/demos/ref.dart b/web/component2/src/demos/ref.dart index f9424a8a0..86aea7b79 100644 --- a/web/component2/src/demos/ref.dart +++ b/web/component2/src/demos/ref.dart @@ -23,7 +23,8 @@ UiFactory FancyButton = uiForwardRef( return (Dom.button() ..ref = ref ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) - ..className = classes.toClassName())('Click me!'); + ..className = classes.toClassName() + )('Click me!'); }, $FancyButtonConfig, // ignore: undefined_identifier ); @@ -43,7 +44,8 @@ UiFactory withLogging(UiFactory factoryT // is fixed. return (factoryToWrap() // ignore: invocation_of_non_function_expression ..addAll(props) - ..ref = ref)(props.children); + ..ref = ref + )(props.children); }, factoryToWrap.asForwardRefConfig( displayName: 'WithLogging', @@ -70,10 +72,13 @@ mixin FooProps on UiProps { class FooComponent extends UiComponent2 { @override render() { - return Dom.div()((Dom.input() - ..modifyProps(addUnconsumedDomProps) - ..type = 'text' - ..ref = props._inputRef)()); + return Dom.div()( + (Dom.input() + ..modifyProps(addUnconsumedDomProps) + ..type = 'text' + ..ref = props._inputRef + )(), + ); } } @@ -82,7 +87,8 @@ UiFactory Foo = uiForwardRef( (props, ref) { return (_Foo() ..addProps(props) - .._inputRef = ref)(); + .._inputRef = ref + )(); }, _Foo.asForwardRefConfig(), ); @@ -99,7 +105,8 @@ final Foo2 = uiForwardRef( print(props.anExampleAdditionalProp); return (_Foo() ..addProps(props) - .._inputRef = ref)(); + .._inputRef = ref + )(); }, $Foo2Config, // ignore: undefined_identifier ); @@ -116,7 +123,8 @@ final Foo2 = uiForwardRef( UiFactory LogPropsHoc = forwardRef((props, ref) { return (_Log() ..addProps(props) - .._forwardedRef = ref)(); + .._forwardedRef = ref + )(); }, displayName: 'LogProps')(_Log); UiFactory _Log = _$_Log; // ignore: undefined_identifier @@ -128,7 +136,7 @@ mixin LogProps on UiProps { // the return value of forwardRef. // // Consumers can set this private field value using the public `ref` setter. - Ref _forwardedRef; + dynamic _forwardedRef; } class _LogComponent extends UiComponent2 { @@ -140,9 +148,12 @@ class _LogComponent extends UiComponent2 { @override render() { - return Dom.div()((props.builder() - ..modifyProps(addUnconsumedDomProps) - ..ref = props._forwardedRef)(props.children)); + return Dom.div()( + (props.builder() + ..modifyProps(addUnconsumedDomProps) + ..ref = props._forwardedRef + )(props.children), + ); } } @@ -155,7 +166,8 @@ UiFactory LoggingFunctionWrapper = forwardRef((props, ref) { return (Baz() ..addProps(props) ..builder = props.builder - .._forwardedRef = ref)(); + .._forwardedRef = ref + )(); }, displayName: 'LoggingFunctionWrapper')(Baz); mixin BazProps on UiProps { @@ -165,14 +177,15 @@ mixin BazProps on UiProps { // the return value of forwardRef. // // Consumers can set this private field value using the public `ref` setter. - Ref _forwardedRef; + dynamic _forwardedRef; } final Baz = uiFunction( (props) { return ((props.builder() ..addProps(getPropsToForward(props, onlyCopyDomProps: true)) - ..ref = props._forwardedRef)(props.children)); + ..ref = props._forwardedRef + )(props.children)); }, $BazConfig, // ignore: undefined_identifier ); @@ -199,21 +212,29 @@ UiFactory RefDemoContainer = uiFunction( (FancyButton() ..className = 'btn btn-primary' ..ref = fancyButtonUiForwardRef - ..onClick = (_) => printButtonOuterHtml(fancyButtonUiForwardRef))(), + ..onClick = (_) => printButtonOuterHtml(fancyButtonUiForwardRef) + )(), ), (RefDemoHoc()..demoTitle = '`uiForwardRef` wrapped in HOC')( (FancyButtonWithLogging() ..className = 'btn btn-success' ..ref = fancyButtonWithLoggingReg - ..onClick = (_) => printButtonOuterHtml(fancyButtonUiForwardRef))(), + ..onClick = (_) => printButtonOuterHtml(fancyButtonUiForwardRef) + )(), + ), + (RefDemoHoc()..demoTitle = '`uiForwardRef` wrapping a class (option 1)')( + (Foo() + ..ref = fooInputRef + ..onChange = (e) => print('Foo Input Ref: ${e.target.value}') + )(), + ), + (RefDemoHoc()..demoTitle = '`uiForwardRef` wrapping a class (option 2)')( + (Foo2() + ..anExampleAdditionalProp = 'This additional prop logs on renders!' + ..ref = foo2InputRef + ..onChange = (e) => print('Foo2 Input Ref: ${e.target.value}') + )(), ), - (RefDemoHoc()..demoTitle = '`uiForwardRef` wrapping a class (option 1)')((Foo() - ..ref = fooInputRef - ..onChange = (e) => print('Foo Input Ref: ${e.target.value}'))()), - (RefDemoHoc()..demoTitle = '`uiForwardRef` wrapping a class (option 2)')((Foo2() - ..anExampleAdditionalProp = 'This additional prop logs on renders!' - ..ref = foo2InputRef - ..onChange = (e) => print('Foo2 Input Ref: ${e.target.value}'))()), ), (RefDemoSection()..sectionTitle = 'forwardRef (deprecated) Demos')( (RefDemoHoc()..demoTitle = '`forwardRef` with class component')( @@ -221,7 +242,8 @@ UiFactory RefDemoContainer = uiFunction( ..builder = FancyButton ..ref = fancyButtonNodeRef ..className = 'btn btn-primary' - ..onClick = (_) => printButtonOuterHtml(fancyButtonNodeRef))(), + ..onClick = (_) => printButtonOuterHtml(fancyButtonNodeRef) + )(), ), (RefDemoHoc()..demoTitle = '`uiForwardRef` with function component')( (LoggingFunctionWrapper() @@ -230,7 +252,8 @@ UiFactory RefDemoContainer = uiFunction( ..ref = fancyFunctionalButtonNodeRef ..onClick = (_) { printButtonOuterHtml(fancyFunctionalButtonNodeRef); - })(), + } + )(), ), ), )); @@ -249,16 +272,18 @@ mixin RefDemoSectionProps on UiProps { UiFactory RefDemoSection = uiFunction( (props) { return (Fragment()( - (Dom.h3()..style = {'color': 'gray', 'borderBottom': '1px solid gray', 'marginTop': 10})( - props.sectionTitle, - ), - (Dom.div() - ..style = { - 'display': 'flex', - 'flexWrap': 'wrap', - })( - props.children, - ))); + (Dom.h3()..style = {'color': 'gray', 'borderBottom': '1px solid gray', 'marginTop': 10})( + props.sectionTitle, + ), + (Dom.div() + ..style = { + 'display': 'flex', + 'flexWrap': 'wrap', + } + )( + props.children, + ), + )); }, $RefDemoSectionConfig, // ignore: undefined_identifier ); diff --git a/web/component2/src/demos/ref.over_react.g.dart b/web/component2/src/demos/ref.over_react.g.dart index 43d30531d..a2880592b 100644 --- a/web/component2/src/demos/ref.over_react.g.dart +++ b/web/component2/src/demos/ref.over_react.g.dart @@ -377,11 +377,12 @@ mixin $LogProps on LogProps { set builder(BuilderOnlyUiFactory value) => props[_$key__builder__LogProps] = value; @override - Ref get _forwardedRef => + dynamic get _forwardedRef => props[_$key___forwardedRef__LogProps] ?? null; // Add ` ?? null` to workaround DDC bug: ; @override - set _forwardedRef(Ref value) => props[_$key___forwardedRef__LogProps] = value; + set _forwardedRef(dynamic value) => + props[_$key___forwardedRef__LogProps] = value; /* GENERATED CONSTANTS */ static const PropDescriptor _$prop__builder__LogProps = PropDescriptor(_$key__builder__LogProps); @@ -421,11 +422,12 @@ mixin $BazProps on BazProps { set builder(BuilderOnlyUiFactory value) => props[_$key__builder__BazProps] = value; @override - Ref get _forwardedRef => + dynamic get _forwardedRef => props[_$key___forwardedRef__BazProps] ?? null; // Add ` ?? null` to workaround DDC bug: ; @override - set _forwardedRef(Ref value) => props[_$key___forwardedRef__BazProps] = value; + set _forwardedRef(dynamic value) => + props[_$key___forwardedRef__BazProps] = value; /* GENERATED CONSTANTS */ static const PropDescriptor _$prop__builder__BazProps = PropDescriptor(_$key__builder__BazProps); From b0f98775f95f292fde79a4215ab60433e16b49c5 Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Fri, 7 Aug 2020 10:54:52 -0700 Subject: [PATCH 27/28] Add displayName to doc comment --- lib/src/component/ref_util.dart | 2 +- web/component2/src/demos/ref.dart | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/lib/src/component/ref_util.dart b/lib/src/component/ref_util.dart index 704b1970a..648c4aa4d 100644 --- a/lib/src/component/ref_util.dart +++ b/lib/src/component/ref_util.dart @@ -371,7 +371,7 @@ UiFactory Function(UiFactory) forwardRef /// .._inputRef = ref /// )(); /// }, -/// _Foo.asForwardRefConfig(), +/// _Foo.asForwardRefConfig(displayName: 'Foo'), /// ); /// /// // diff --git a/web/component2/src/demos/ref.dart b/web/component2/src/demos/ref.dart index 86aea7b79..ca71bbe6c 100644 --- a/web/component2/src/demos/ref.dart +++ b/web/component2/src/demos/ref.dart @@ -90,6 +90,9 @@ UiFactory Foo = uiForwardRef( .._inputRef = ref )(); }, + // Note that `displayName` is not passed in here. + // In the React devtools, the name of `Foo` will be + // 'Anonymous'. _Foo.asForwardRefConfig(), ); From d12bca5be576ac4f422190f8d71f8d03de44f13e Mon Sep 17 00:00:00 2001 From: Joe Bingham Date: Fri, 7 Aug 2020 11:17:52 -0700 Subject: [PATCH 28/28] Fix example title --- web/component2/src/demos/ref.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/component2/src/demos/ref.dart b/web/component2/src/demos/ref.dart index ca71bbe6c..877b54d9e 100644 --- a/web/component2/src/demos/ref.dart +++ b/web/component2/src/demos/ref.dart @@ -92,7 +92,7 @@ UiFactory Foo = uiForwardRef( }, // Note that `displayName` is not passed in here. // In the React devtools, the name of `Foo` will be - // 'Anonymous'. + // 'Anonymous'. _Foo.asForwardRefConfig(), ); @@ -248,7 +248,7 @@ UiFactory RefDemoContainer = uiFunction( ..onClick = (_) => printButtonOuterHtml(fancyButtonNodeRef) )(), ), - (RefDemoHoc()..demoTitle = '`uiForwardRef` with function component')( + (RefDemoHoc()..demoTitle = '`forwardRef` with function component')( (LoggingFunctionWrapper() ..builder = FancyButton ..className = 'btn btn-success'