97 lines
2.7 KiB
Dart
97 lines
2.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import '../../about/internal/application/TextType.dart';
|
|
import '../../utils/Colors.dart';
|
|
import '../text/Text.dart';
|
|
|
|
/// The standard labelled text field. Every form in the app uses this rather
|
|
/// than building a bare [TextFormField], so labels, spacing and validation
|
|
/// messages stay identical everywhere.
|
|
Widget inputField({
|
|
required String label,
|
|
required String initial,
|
|
required void Function(String) onSaved,
|
|
String? hint,
|
|
bool required = false,
|
|
bool obscure = false,
|
|
TextInputType? keyboardType,
|
|
Widget? suffix,
|
|
String? Function(String?)? validator,
|
|
void Function(String)? onChanged,
|
|
TextEditingController? controller,
|
|
int? maxLines = 1,
|
|
bool enabled = true,
|
|
}) {
|
|
return Padding(
|
|
padding: const EdgeInsets.only(bottom: 12),
|
|
child: TextFormField(
|
|
initialValue: controller == null ? initial : null,
|
|
controller: controller,
|
|
obscureText: obscure,
|
|
keyboardType: keyboardType,
|
|
maxLines: obscure ? 1 : maxLines,
|
|
enabled: enabled,
|
|
onChanged: onChanged,
|
|
decoration: InputDecoration(
|
|
labelText: label,
|
|
hintText: hint,
|
|
suffixIcon: suffix,
|
|
),
|
|
validator:
|
|
validator ??
|
|
(required
|
|
? (v) => (v == null || v.trim().isEmpty) ? 'Required' : null
|
|
: null),
|
|
onSaved: (v) => onSaved(v ?? ''),
|
|
),
|
|
);
|
|
}
|
|
|
|
/// A section heading inside a form.
|
|
Widget inputSection(BuildContext context, String title) => Padding(
|
|
padding: const EdgeInsets.only(top: 20, bottom: 10),
|
|
child: text(
|
|
title.toUpperCase(),
|
|
12,
|
|
TextType.Bold,
|
|
color: context.jp.textDim,
|
|
letterSpacing: 1.2,
|
|
),
|
|
);
|
|
|
|
/// A one-line explanatory note under a field.
|
|
Widget inputHint(BuildContext context, IconData icon, String message) =>
|
|
Padding(
|
|
padding: const EdgeInsets.only(left: 4, top: 2, bottom: 8),
|
|
child: Row(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Icon(icon, size: 13, color: context.jp.textFaint),
|
|
const SizedBox(width: 6),
|
|
Expanded(
|
|
child: text(
|
|
message,
|
|
12,
|
|
TextType.Regular,
|
|
color: context.jp.textFaint,
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
|
|
/// A labelled switch row, matching the field spacing.
|
|
Widget inputSwitch({
|
|
required BuildContext context,
|
|
required String title,
|
|
required String subtitle,
|
|
required bool value,
|
|
required void Function(bool) onChanged,
|
|
}) => SwitchListTile(
|
|
contentPadding: EdgeInsets.zero,
|
|
value: value,
|
|
onChanged: onChanged,
|
|
title: text(title, 14, TextType.Regular, color: context.jp.text),
|
|
subtitle: text(subtitle, 12, TextType.Light, color: context.jp.textDim),
|
|
);
|