content: import 'package:flutter/foundation.dart';
  import 'package:flutter/material.dart';
  import 'package:flutter/widgets.dart';
  
  /// A widget that simplify the writing of deeply nested widget trees.
  ///
  /// It relies on the new kind of widget [SingleChildWidget], which has two
  /// concrete implementations:
  /// - [SingleChildStatelessWidget]
  /// - [SingleChildStatefulWidget]
  ///
  /// They are both respectively a [SingleChildWidget] variant of [StatelessWidget]
  /// and [StatefulWidget].
  ///
  /// The difference between a widget and its single-child variant is that they have
  /// a custom `build` method that takes an extra parameter.
  ///
  /// As such, a `StatelessWidget` would be:
  ///
  /// ```dart
  /// class MyWidget extends StatelessWidget {
  ///   MyWidget({Key key, this.child}): super(key: key);
  ///
  ///   final Widget child;
  ///
  ///   @override
  ///   Widget build(BuildContext context) {
  ///     return SomethingWidget(child: child);
  ///   }
  /// }
  /// ```
  ///
  /// Whereas a [SingleChildStatelessWidget] would be:
  ///
  /// ```dart
  /// class MyWidget extends SingleChildStatelessWidget {
  ///   MyWidget({Key key, Widget child}): super(key: key, child: child);
  ///
  ///   @override
  ///   Widget buildWithChild(BuildContext context, Widget child) {
  ///     return SomethingWidget(child: child);
  ///   }
  /// }
  /// ```
  ///
  /// This allows our new `MyWidget` to be used both with:
  ///
  /// ```dart
  /// MyWidget(
  ///   child: AnotherWidget(),
  /// )
  /// ```
  ///
  /// and to be placed inside `children` of [Nested] like so:
  ///
  /// ```dart
  /// Nested(
  ///   children: [
  ///     MyWidget(),
  ///     ...
  ///   ],
  ///   child: AnotherWidget(),
  /// )
  /// ```
  class Nested extends StatelessWidget implements SingleChildWidget {
    /// Allows configuring key, children and child
    Nested({
      Key? key,
      required List<SingleChildWidget> children,
      Widget? child,
    })  : assert(children.isNotEmpty),
          _children = children,
          _child = child,
          super(key: key);
  
    final List<SingleChildWidget> _children;
    final Widget? _child;
  
    @override
    Widget build(BuildContext context) {
      throw StateError('implemented internally');
    }
  
    @override
    _NestedElement createElement() => _NestedElement(this);
  }
  
  class _NestedElement extends StatelessElement
      with SingleChildWidgetElementMixin {
    _NestedElement(Nested widget) : super(widget);
  
    @override
    Nested get widget => super.widget as Nested;
  
    final nodes = <_NestedHookElement>{};
  
    @override
    Widget build() {
      _NestedHook? nestedHook;
      var nextNode = _parent?.injectedChild ?? widget._child;
  
      for (final child in widget._children.reversed) {
        nextNode = nestedHook = _NestedHook(
          owner: this,
          wrappedWidget: child,
          injectedChild: nextNode,
        );
      }
  
      if (nestedHook != null) {
        // We manually update _NestedHookElement instead of letter widgets do their thing
        // because an item N may be constant but N+1 not. So, if we used widgets
        // then N+1 wouldn't rebuild because N didn't change
        for (final node in nodes) {
          node
            ..wrappedChild = nestedHook!.wrappedWidget
            ..injectedChild = nestedHook.injectedChild;
  
          final next = nestedHook.injectedChild;
          if (next is _NestedHook) {
            nestedHook = next;
          } else {
            break;
          }
        }
      }
  
      return nextNode!;
    }
  }
  
  class _NestedHook extends StatelessWidget {
    _NestedHook({
      this.injectedChild,
      required this.wrappedWidget,
      required this.owner,
    });
  
    final SingleChildWidget wrappedWidget;
    final Widget? injectedChild;
    final _NestedElement owner;
  
    @override
    _NestedHookElement createElement() => _NestedHookElement(this);
  
    @override
    Widget build(BuildContext context) => throw StateError('handled internally');
  }
  
  class _NestedHookElement extends StatelessElement {
    _NestedHookElement(_NestedHook widget) : super(widget);
  
    @override
    _NestedHook get widget => super.widget as _NestedHook;
  
    Widget? _injectedChild;
    Widget? get injectedChild => _injectedChild;
    set injectedChild(Widget? value) {
      final previous = _injectedChild;
      if (value is _NestedHook &&
          previous is _NestedHook &&
          Widget.canUpdate(value.wrappedWidget, previous.wrappedWidget)) {
        // no need to rebuild the wrapped widget just for a _NestedHook.
        // The widget doesn't matter here, only its Element.
        return;
      }
      if (previous != value) {
        _injectedChild = value;
        visitChildren((e) => e.markNeedsBuild());
      }
    }
  
    SingleChildWidget? _wrappedChild;
    SingleChildWidget? get wrappedChild => _wrappedChild;
    set wrappedChild(SingleChildWidget? value) {
      if (_wrappedChild != value) {
        _wrappedChild = value;
        markNeedsBuild();
      }
    }
  
    @override
    void mount(Element? parent, dynamic newSlot) {
      widget.owner.nodes.add(this);
      _wrappedChild = widget.wrappedWidget;
      _injectedChild = widget.injectedChild;
      super.mount(parent, newSlot);
    }
  
    @override
    void unmount() {
      widget.owner.nodes.remove(this);
      super.unmount();
    }
  
    @override
    Widget build() {
      return wrappedChild!;
    }
  }
  
  /// A [Widget] that takes a single descendant.
  ///
  /// As opposed to [ProxyWidget], it may have a "build" method.
  ///
  /// See also:
  /// - [SingleChildStatelessWidget]
  /// - [SingleChildStatefulWidget]
  abstract class SingleChildWidget implements Widget {
    @override
    SingleChildWidgetElementMixin createElement();
  }
  
  mixin SingleChildWidgetElementMixin on Element {
    _NestedHookElement? _parent;
  
    @override
    void mount(Element? parent, dynamic newSlot) {
      if (parent is _NestedHookElement?) {
        _parent = parent;
      }
      super.mount(parent, newSlot);
    }
  
    @override
    void activate() {
      super.activate();
      visitAncestorElements((parent) {
        if (parent is _NestedHookElement) {
          _parent = parent;
        }
        return false;
      });
    }
  }
  
  /// A [StatelessWidget] that implements [SingleChildWidget] and is therefore
  /// compatible with [Nested].
  ///
  /// Its [build] method must **not** be overriden. Instead use [buildWithChild].
  abstract class SingleChildStatelessWidget extends StatelessWidget
      implements SingleChildWidget {
    /// Creates a widget that has exactly one child widget.
    const SingleChildStatelessWidget({Key? key, Widget? child})
        : _child = child,
          super(key: key);
  
    final Widget? _child;
  
    /// A [build] method that receives an extra `child` parameter.
    ///
    /// This method may be called with a `child` different from the parameter
    /// passed to the constructor of [SingleChildStatelessWidget].
    /// It may also be called again with a different `child`, without this widget
    /// being recreated.
    Widget buildWithChild(BuildContext context, Widget? child);
  
    @override
    Widget build(BuildContext context) => buildWithChild(context, _child);
  
    @override
    SingleChildStatelessElement createElement() {
      return SingleChildStatelessElement(this);
    }
  }
  
  /// An [Element] that uses a [SingleChildStatelessWidget] as its configuration.
  class SingleChildStatelessElement extends StatelessElement
      with SingleChildWidgetElementMixin {
    /// Creates an element that uses the given widget as its configuration.
    SingleChildStatelessElement(SingleChildStatelessWidget widget)
        : super(widget);
  
    @override
    Widget build() {
      if (_parent != null) {
        return widget.buildWithChild(this, _parent!.injectedChild);
      }
      return super.build();
    }
  
    @override
    SingleChildStatelessWidget get widget =>
        super.widget as SingleChildStatelessWidget;
  }
  
  /// A [StatefulWidget] that is compatible with [Nested].
  abstract class SingleChildStatefulWidget extends StatefulWidget
      implements SingleChildWidget {
    /// Creates a widget that has exactly one child widget.
    const SingleChildStatefulWidget({Key? key, Widget? child})
        : _child = child,
          super(key: key);
  
    final Widget? _child;
  
    @override
    SingleChildStatefulElement createElement() {
      return SingleChildStatefulElement(this);
    }
  }
  
  /// A [State] for [SingleChildStatefulWidget].
  ///
  /// Do not override [build] and instead override [buildWithChild].
  abstract class SingleChildState<T extends SingleChildStatefulWidget>
      extends State<T> {
    /// A [build] method that receives an extra `child` parameter.
    ///
    /// This method may be called with a `child` different from the parameter
    /// passed to the constructor of [SingleChildStatelessWidget].
    /// It may also be called again with a different `child`, without this widget
    /// being recreated.
    Widget buildWithChild(BuildContext context, Widget? child);
  
    @override
    Widget build(BuildContext context) => buildWithChild(context, widget._child);
  }
  
  /// An [Element] that uses a [SingleChildStatefulWidget] as its configuration.
  class SingleChildStatefulElement extends StatefulElement
      with SingleChildWidgetElementMixin {
    /// Creates an element that uses the given widget as its configuration.
    SingleChildStatefulElement(SingleChildStatefulWidget widget) : super(widget);
  
    @override
    SingleChildStatefulWidget get widget =>
        super.widget as SingleChildStatefulWidget;
  
    @override
    SingleChildState<SingleChildStatefulWidget> get state =>
        super.state as SingleChildState<SingleChildStatefulWidget>;
  
    @override
    Widget build() {
      if (_parent != null) {
        return state.buildWithChild(this, _parent!.injectedChild!);
      }
      return super.build();
    }
  }
  
  /// A [SingleChildWidget] that delegates its implementation to a callback.
  ///
  /// It works like [Builder], but is compatible with [Nested].
  class SingleChildBuilder extends SingleChildStatelessWidget {
    /// Creates a widget that delegates its build to a callback.
    ///
    /// The [builder] argument must not be null.
    const SingleChildBuilder({Key? key, required this.builder, Widget? child})
        : super(key: key, child: child);
  
    /// Called to obtain the child widget.
    ///
    /// The `child` parameter may be different from the one parameter passed to
    /// the constructor of [SingleChildBuilder].
    final Widget Function(BuildContext context, Widget? child) builder;
  
    @override
    Widget buildWithChild(BuildContext context, Widget? child) {
      return builder(context, child);
    }
  }
  
  mixin SingleChildStatelessWidgetMixin
      implements StatelessWidget, SingleChildStatelessWidget {
    Widget? get child;
  
    @override
    Widget? get _child => child;
  
    @override
    SingleChildStatelessElement createElement() {
      return SingleChildStatelessElement(this);
    }
  
    @override
    Widget build(BuildContext context) {
      return buildWithChild(context, child);
    }
  }
  
  mixin SingleChildStatefulWidgetMixin on StatefulWidget
      implements SingleChildWidget {
    Widget? get child;
  
    @override
    _SingleChildStatefulMixinElement createElement() =>
        _SingleChildStatefulMixinElement(this);
  }
  
  mixin SingleChildStateMixin<T extends StatefulWidget> on State<T> {
    Widget buildWithChild(BuildContext context, Widget child);
  
    @override
    Widget build(BuildContext context) {
      return buildWithChild(
        context,
        (widget as SingleChildStatefulWidgetMixin).child!,
      );
    }
  }
  
  class _SingleChildStatefulMixinElement extends StatefulElement
      with SingleChildWidgetElementMixin {
    _SingleChildStatefulMixinElement(SingleChildStatefulWidgetMixin widget)
        : super(widget);
  
    @override
    SingleChildStatefulWidgetMixin get widget =>
        super.widget as SingleChildStatefulWidgetMixin;
  
    @override
    SingleChildStateMixin<StatefulWidget> get state =>
        super.state as SingleChildStateMixin<StatefulWidget>;
  
    @override
    Widget build() {
      if (_parent != null) {
        return state.buildWithChild(this, _parent!.injectedChild!);
      }
      return super.build();
    }
  }
  
  mixin SingleChildInheritedElementMixin
      on InheritedElement, SingleChildWidgetElementMixin {
    @override
    Widget build() {
      if (_parent != null) {
        return _parent!.injectedChild!;
      }
      return super.build();
    }
  }
  