didvan-app/lib/widgets/didvan/text_field.dart

204 lines
5.7 KiB
Dart

import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/constants/app_icons.dart';
import 'package:didvan/widgets/animated_visibility.dart';
import 'package:didvan/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
import 'package:persian_number_utility/persian_number_utility.dart';
class DidvanTextField extends StatefulWidget {
final void Function(String value)? onChanged;
final void Function(String value)? onSubmitted;
final bool enabled;
final bool autoFocus;
final TextAlign textAlign;
final String? title;
final String? hintText;
final dynamic initialValue;
final bool obsecureText;
final Function(String value)? validator;
final TextInputType? textInputType;
const DidvanTextField({
Key? key,
this.onChanged,
this.enabled = true,
this.title,
this.hintText,
this.initialValue,
this.validator,
this.textInputType,
this.textAlign = TextAlign.right,
this.obsecureText = false,
this.autoFocus = false,
this.onSubmitted,
}) : super(key: key);
@override
State<DidvanTextField> createState() => _DidvanTextFieldState();
}
class _DidvanTextFieldState extends State<DidvanTextField> {
final FocusNode _focusNode = FocusNode();
final TextEditingController _controller = TextEditingController();
bool _hideContent = false;
String? _error;
@override
void initState() {
if (widget.initialValue != null) {
_controller.text = widget.initialValue;
}
_hideContent = widget.obsecureText;
_focusNode.addListener(() {
setState(() {});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (widget.title != null)
DidvanText(
widget.title!,
color: _titleColor(),
),
if (widget.title != null) const SizedBox(height: 8),
Container(
height: 48,
padding: const EdgeInsets.symmetric(horizontal: 12).copyWith(
left: widget.obsecureText ? 0 : 12,
),
decoration: BoxDecoration(
color: _fillColor(),
borderRadius: DesignConfig.lowBorderRadius,
border: Border.all(color: _borderColor()),
),
child: TextFormField(
autofocus: widget.autoFocus,
obscureText: _hideContent,
textAlign: widget.textAlign,
keyboardType: widget.textInputType,
focusNode: _focusNode,
controller: _controller,
onFieldSubmitted: widget.onSubmitted,
onChanged: _onChanged,
validator: _validator,
obscuringCharacter: '*',
style: Theme.of(context).textTheme.bodyText1,
decoration: InputDecoration(
suffixIcon: _suffixBuilder(),
enabled: widget.enabled,
border: InputBorder.none,
hintText: widget.hintText,
errorStyle: const TextStyle(height: 0),
hintStyle: Theme.of(context)
.textTheme
.bodyText2!
.copyWith(color: Theme.of(context).colorScheme.hint),
),
),
),
const SizedBox(height: 8),
AnimatedVisibility(
isVisible: _error != null,
duration: DesignConfig.lowAnimationDuration,
child: Row(
children: [
Icon(
DidvanIcons.lightbulb_exclamation_regular,
color: Theme.of(context).colorScheme.error,
size: 14,
),
DidvanText(
_error ?? '',
style: Theme.of(context).textTheme.caption,
color: Theme.of(context).colorScheme.error,
),
],
))
],
);
}
Color _borderColor() {
if (_focusNode.hasFocus) {
return Theme.of(context).colorScheme.focusedBorder;
} else if (_error != null) {
return Theme.of(context).colorScheme.error;
}
return Theme.of(context).colorScheme.border;
}
Color? _titleColor() {
if (!widget.enabled) {
return Theme.of(context).colorScheme.hint;
}
if (_error != null) {
return Theme.of(context).colorScheme.error;
}
}
Color _fillColor() {
if (!widget.enabled) {
return DesignConfig.isDark
? Theme.of(context).colorScheme.disabledBackground
: Theme.of(context).colorScheme.secondCTA;
}
if (_focusNode.hasFocus) {
return Theme.of(context).colorScheme.focused;
}
if (_error != null) {
return Theme.of(context).colorScheme.errorBack;
}
return Theme.of(context).colorScheme.surface;
}
Widget? _suffixBuilder() {
if (widget.obsecureText) {
return FittedBox(
fit: BoxFit.scaleDown,
child: GestureDetector(
onTap: () {
setState(() {
_hideContent = !_hideContent;
});
},
child: Icon(
_hideContent ? DidvanIcons.eye_solid : DidvanIcons.eye_slash_solid,
),
),
);
}
}
void _onChanged(String value) {
setState(() {
_error = null;
});
value = value.toEnglishDigit();
if (widget.onChanged != null) {
widget.onChanged!(value);
}
}
String? _validator(String? value) {
if (widget.validator != null) {
final String? error = widget.validator!(value!);
if (error != null) {
setState(() {
_error = error;
});
} else {
setState(() {
_error = null;
});
}
}
}
}