anchor.diff:    }
   }
   
  +/// Displays the visual elements of a material design text field around an
  +/// arbitrary child widget.
  +///
  +/// Use InputContainer to create widgets that look and behave like the [Input]
  +/// widget.
  +///
  +/// Requires one of its ancestors to be a [Material] widget.
  +///
  +/// See also:
  +///
  +/// * [Input], which combines an [InputContainer] with an [InputField].
  +class InputContainer extends StatefulWidget {
  +  InputContainer({
  +    Key key,
  +    this.focused: false,
  +    this.isEmpty: false,
  +    this.icon,
  +    this.labelText,
  +    this.hintText,
  +    this.errorText,
  +    this.style,
  +    this.isDense: false,
  +    this.child,
  +  }) : super(key: key);
  +
  +  /// An icon to show adjacent to the input field.
  +  ///
  +  /// The size and color of the icon is configured automatically using an
  +  /// [IconTheme] and therefore does not need to be explicitly given in the
  +  /// icon widget.
  +  ///
  +  /// See [Icon], [ImageIcon].
  +  final Widget icon;
  +
  +  /// Text that appears above the child or over it, if isEmpty is true.
  +  final String labelText;
  +
  +  /// Text that appears over the child if isEmpty is true and labelText is null.
  +  final String hintText;
  +
  +  /// Text that appears below the child. If errorText is non-null the divider
  +  /// that appears below the child is red.
  +  final String errorText;
  +
  +  /// The style to use for the hint. It's also used for the label when the label
  +  /// appears over the child.
  +  final TextStyle style;
  +
  +  /// Whether the input container is part of a dense form (i.e., uses less vertical space).
  +  final bool isDense;
  +
  +  /// True if the hint and label should be displayed as if the child had the focus.
  +  final bool focused;
  +
  +  /// Should the hint and label be displayed as if no value had been input
  +  /// to the child.
  +  final bool isEmpty;
  +
  +  final Widget child;
  +
  +  @override
  +  _InputContainerState createState() => new _InputContainerState();
  +}
  +
  +class _InputContainerState extends State<InputContainer> {
  +  @override
  +  Widget build(BuildContext context) {
  +    assert(debugCheckHasMaterial(context));
  +    ThemeData themeData = Theme.of(context);
  +    String errorText = config.errorText;
  +
  +    final TextStyle textStyle = config.style ?? themeData.textTheme.subhead;
  +    Color activeColor = themeData.hintColor;
  +    if (config.focused) {
  +      switch (themeData.brightness) {
  +        case Brightness.dark:
  +          activeColor = themeData.accentColor;
  +          break;
  +        case Brightness.light:
  +          activeColor = themeData.primaryColor;
  +          break;
  +      }
  +    }
  +    double topPadding = config.isDense ? 12.0 : 16.0;
  +
  +    List<Widget> stackChildren = <Widget>[];
  +
  +    // If we're not focused, there's not value, and labelText was provided,
  +    // then the label appears where the hint would. And we will not show
  +    // the hintText.
  +    final bool hasInlineLabel = !config.focused && config.labelText != null && config.isEmpty;
  +
  +    if (config.labelText != null) {
  +      final TextStyle labelStyle = hasInlineLabel ?
  +        textStyle.copyWith(color: themeData.hintColor) :
  +        themeData.textTheme.caption.copyWith(color: activeColor);
  +
  +      final double topPaddingIncrement = themeData.textTheme.caption.fontSize + (config.isDense ? 4.0 : 8.0);
  +      double top = topPadding;
  +      if (hasInlineLabel)
  +        top += topPaddingIncrement + textStyle.fontSize - labelStyle.fontSize;
  +
  +      stackChildren.add(
  +        new AnimatedPositioned(
  +          left: 0.0,
  +          top: top,
  +          duration: _kTransitionDuration,
  +          curve: _kTransitionCurve,
  +          child: new Text(config.labelText, style: labelStyle),
  +        ),
  +      );
  +
  +      topPadding += topPaddingIncrement;
  +    }
  +
  +    if (config.hintText != null && config.isEmpty && !hasInlineLabel) {
  +      TextStyle hintStyle = textStyle.copyWith(color: themeData.hintColor);
  +      stackChildren.add(
  +        new Positioned(
  +          left: 0.0,
  +          top: topPadding + textStyle.fontSize - hintStyle.fontSize,
  +          child: new IgnorePointer(
  +            child: new Text(config.hintText, style: hintStyle),
  +          ),
  +        ),
  +      );
  +    }
  +
  +    Color borderColor = activeColor;
  +    double bottomPadding = 8.0;
  +    double bottomBorder = config.focused ? 2.0 : 1.0;
  +    double bottomHeight = config.isDense ? 14.0 : 18.0;
  +
  +    if (errorText != null) {
  +      borderColor = themeData.errorColor;
  +      bottomBorder = 2.0;
  +      if (!config.isDense)
  +        bottomPadding = 1.0;
  +    }
  +
  +    EdgeInsets padding = new EdgeInsets.only(top: topPadding, bottom: bottomPadding);
  +    Border border = new Border(
  +      bottom: new BorderSide(
  +        color: borderColor,
  +        width: bottomBorder,
  +      )
  +    );
  +    EdgeInsets margin = new EdgeInsets.only(bottom: bottomHeight - (bottomPadding + bottomBorder));
  +
  +    stackChildren.add(new AnimatedContainer(
  +      margin: margin,
  +      padding: padding,
  +      duration: _kTransitionDuration,
  +      curve: _kTransitionCurve,
  +      decoration: new BoxDecoration(
  +        border: border,
  +      ),
  +      child: config.child,
  +    ));
  +
  +    if (errorText != null && !config.isDense) {
  +      TextStyle errorStyle = themeData.textTheme.caption.copyWith(color: themeData.errorColor);
  +      stackChildren.add(new Positioned(
  +        left: 0.0,
  +        bottom: 0.0,
  +        child: new Text(errorText, style: errorStyle)
  +      ));
  +    }
  +
  +    Widget textField = new Stack(children: stackChildren);
  +
  +    if (config.icon != null) {
  +      double iconSize = config.isDense ? 18.0 : 24.0;
  +      double iconTop = topPadding + (textStyle.fontSize - iconSize) / 2.0;
  +      textField = new Row(
  +        crossAxisAlignment: CrossAxisAlignment.start,
  +        children: <Widget>[
  +          new Container(
  +            margin: new EdgeInsets.only(right: 16.0, top: iconTop),
  +            width: config.isDense ? 40.0 : 48.0,
  +            child: new IconTheme.merge(
  +              context: context,
  +              data: new IconThemeData(
  +                color: config.focused ? activeColor : Colors.black45,
  +                size: config.isDense ? 18.0 : 24.0
  +              ),
  +              child: config.icon
  +            )
  +          ),
  +          new Flexible(child: textField)
  +        ]
  +      );
  +    }
  +
  +    return textField;
  +  }
  +}
  +
   /// A material design text input field.
  -///
  -/// Requires one of its ancestors to be a [Material] widget.
   ///
   /// The [value] field must be updated each time the [onChanged] callback is
   /// invoked. Be sure to include the full [value] provided by the [onChanged]
   /// callback, or information like the current selection will be lost.
   ///
  +/// Requires one of its ancestors to be a [Material] widget.
  +///
   /// See also:
   ///
   ///  * <https://material.google.com/components/text-fields.html>
  
positive.code: import 'icon.dart';
  import 'icon_theme.dart';
  import 'icon_theme_data.dart';
  import 'material.dart';
  import 'text_selection.dart';
  import 'theme.dart';
  
  export 'package:flutter/services.dart' show TextInputType;
  
  class InputField extends StatefulWidget {
    InputField({
      Key key,
  
negative.code:   ///
    /// By default, the input uses a keyboard appropriate for text entry.
    //
    //  If you change this constructor signature, please also update
    // InputContainer, InputFormField, InputField.
    Input({
      Key key,
      this.value,
  