wip: select option; lanjut syarat ketentuan dulu

This commit is contained in:
Golek 2022-12-09 08:48:18 +07:00
parent abbd0d8cc8
commit 5e8cdba2de
11 changed files with 774 additions and 5 deletions

View File

@ -69,14 +69,43 @@ List<Story> getStories(GolekThemeData theme) {
),
descriptionLabel: k.text(
label: 'descriptionLabel',
initial: 'Maks. 1 Foto, 1 Foto Maks. 2 mb',
),
guidanceLabel: k.text(
label: 'guidanceLabel',
initial:
'Tingkatkan kepercayaan partner bisnis dengan mengunggah foto tentang usaha'
' anda (Contoh foto kantor, armada karyawan dll.)',
),
guidanceLabel: k.text(
label: 'guidanceLabel',
initial: 'Maks. 1 Foto, 1 Foto Maks. 2 mb',
),
),
),
Story(
name: 'Plain Combo Box',
section: 'Form Input',
builder: (_, kb) {
return ComboBoxField(
label: 'Label',
items: const [
DropdownMenuItem(child: Text('Budi'), value: 'Budi'),
DropdownMenuItem(child: Text('Bakti'), value: 'Bakti'),
DropdownMenuItem(child: Text('Riyanto'), value: 'Riyanto'),
],
placeholder: 'Ini placeholder',
onChangeComboBox: (value) {
print(value);
},
);
},
),
Story.simple(
name: 'Autocomplete Plain',
child: SelectOption(
placeholder: 'Ini Placeholder',
suggestions: {
'Guru': 'guru',
'Teka': 'teka'
},
label: 'Ini Label',
),
),
];

View File

@ -118,6 +118,48 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_keyboard_visibility:
dependency: transitive
description:
name: flutter_keyboard_visibility
url: "https://pub.dartlang.org"
source: hosted
version: "5.4.0"
flutter_keyboard_visibility_linux:
dependency: transitive
description:
name: flutter_keyboard_visibility_linux
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_keyboard_visibility_macos:
dependency: transitive
description:
name: flutter_keyboard_visibility_macos
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_keyboard_visibility_platform_interface:
dependency: transitive
description:
name: flutter_keyboard_visibility_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
flutter_keyboard_visibility_web:
dependency: transitive
description:
name: flutter_keyboard_visibility_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
flutter_keyboard_visibility_windows:
dependency: transitive
description:
name: flutter_keyboard_visibility_windows
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_lints:
dependency: "direct dev"
description:
@ -149,6 +191,13 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_typeahead:
dependency: transitive
description:
name: flutter_typeahead
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.1"
flutter_web_plugins:
dependency: transitive
description: flutter
@ -266,6 +315,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
mime:
dependency: transitive
description:
name: mime
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.3"
nested:
dependency: transitive
description:

View File

@ -5,4 +5,6 @@ export 'src/theme/golek_theme.dart';
export 'src/theme/golek_theme_data.dart';
export 'src/input_field.dart';
export 'src/input_file.dart';
export 'src/combo_box.dart';
export 'src/auto_complete.dart';
export 'src/error_message_builder.dart';

View File

@ -0,0 +1,278 @@
import 'package:component_library/component_library.dart';
import 'package:flutter/material.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
class SelectOption extends StatelessWidget {
const SelectOption({
Key? key,
required this.placeholder,
required this.suggestions,
required this.label,
this.prefixIcon,
this.messagesError,
this.isDisabled = false,
this.isTouched = false,
this.isError = false,
this.suggestionsCallback,
this.changeCallback,
this.messageError,
}) : super(key: key);
final String label;
final String placeholder;
final Map<String, String> suggestions;
final bool? isDisabled;
final bool? isTouched;
final bool? isError;
final Map<String, String>? messagesError;
final Future<void> Function()? suggestionsCallback;
final Function()? changeCallback;
final Widget? prefixIcon;
final String? messageError;
@override
Widget build(BuildContext context) {
final theme = GolekTheme.of(context);
if (isDisabled == true) {
return Container(
height: 52,
decoration: BoxDecoration(
border: Border.all(color: Colors.transparent, width: 3),
borderRadius: BorderRadius.circular(8.0),
),
child: TextFormField(
decoration: InputDecoration(
hintText: placeholder,
hintStyle: theme.textStyle.copyWith(
fontSize: FontSize.style14,
color: theme.neutral70Color,
),
contentPadding: const EdgeInsets.symmetric(
horizontal: 9.5,
vertical: 11,
),
prefix: const Padding(
padding: EdgeInsets.only(left: 14),
),
prefixIcon: prefixIcon != null
? Padding(
padding: const EdgeInsets.only(left: 12),
child: prefixIcon,
)
: prefixIcon,
filled: true,
disabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(6),
borderSide: BorderSide(color: theme.neutral50Color),
),
fillColor: const Color(0xffededed),
suffixIcon: Icon(
Icons.keyboard_arrow_down,
color: theme.neutral90Color,
)),
enabled: false,
),
);
}
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ReactiveTypeAheadBuilder(
isDisabled: isDisabled!,
context: context,
hasValue: true,
suggestions: suggestions,
placeholder: placeholder,
changeCallback: changeCallback,
prefixIcon: prefixIcon,
suggestionsCallback: suggestionsCallback,
isTouched: isTouched!,
isError: isError!,
),
ErrorMessageBuilder(
inputLabel: label,
messageError: messageError ?? '',
)
],
);
}
}
/// widget yang ditampilkan saat tidak ada suggestion
class ListTileNoSuggestionBuilder extends StatelessWidget {
const ListTileNoSuggestionBuilder({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = GolekTheme.of(context);
return ListTile(
tileColor: Colors.white,
visualDensity: VisualDensity.adaptivePlatformDensity,
title: Text(
'Tidak ditemukan data',
style: theme.textStyle.copyWith(
fontSize: FontSize.style14,
color: Colors.black,
),
),
);
}
}
/// widget yang ditampilkan saat tidak ada suggestion
class ListTileSuggestionBuilder extends StatelessWidget {
const ListTileSuggestionBuilder({
Key? key,
required this.isTileSelected,
required this.suggestion,
}) : super(key: key);
final bool isTileSelected;
final String suggestion;
@override
Widget build(BuildContext context) {
final theme = GolekTheme.of(context);
return ListTile(
tileColor: isTileSelected ? theme.primarySurfaceColor : Colors.white,
visualDensity: VisualDensity.adaptivePlatformDensity,
trailing: isTileSelected
? Icon(
Icons.check,
color: theme.primaryMainColor,
)
: null,
title: Text(
suggestion,
style: theme.textStyle.copyWith(
fontSize: FontSize.style14,
color: isTileSelected ? theme.primaryMainColor : Colors.black,
),
),
);
}
}
class ReactiveTypeAheadBuilder extends StatefulWidget {
const ReactiveTypeAheadBuilder({
Key? key,
required this.isDisabled,
required this.isTouched,
required this.isError,
required this.context,
required this.hasValue,
required this.suggestions,
this.suggestionsCallback,
this.changeCallback,
this.prefixIcon,
required this.placeholder,
}) : super(key: key);
final bool isDisabled;
final bool isTouched;
final bool isError;
final BuildContext context;
final bool hasValue;
final String placeholder;
final Map<String, String> suggestions;
final Future<void> Function()? suggestionsCallback;
final Function()? changeCallback;
final Widget? prefixIcon;
@override
State<ReactiveTypeAheadBuilder> createState() =>
_ReactiveTypeAheadBuilderState();
}
class _ReactiveTypeAheadBuilderState extends State<ReactiveTypeAheadBuilder> {
final TextEditingController textEditingController = TextEditingController();
String keySelected = '';
/// fungsi untuk mendapatkan suggestion yang tampil
List<String> _getSuggestions(String query) {
List<String> matches = [];
/// menambahkan semua properti suggestion di list typehead
matches.addAll(widget.suggestions.keys.toList());
/// filter saat user typing untuk mendapatkan suggestion
matches.retainWhere((s) => s.toLowerCase().contains(query.toLowerCase()));
return matches;
}
@override
Widget build(BuildContext context) {
final theme = GolekTheme.of(context);
return Container(
height: 52,
decoration: BoxDecoration(
border: Border.all(color: Colors.transparent, width: 3),
borderRadius: BorderRadius.circular(8.0),
),
child: TypeAheadField(
onSuggestionSelected: (suggestion) {
keySelected = suggestion.toString();
},
noItemsFoundBuilder: (_) => const ListTileNoSuggestionBuilder(),
textFieldConfiguration: TextFieldConfiguration(
decoration: InputDecoration(
prefixIcon: widget.prefixIcon != null
? Padding(
padding: const EdgeInsets.only(left: 12),
child: widget.prefixIcon,
)
: widget.prefixIcon,
fillColor: widget.isDisabled ? theme.neutral30Color : Colors.white,
contentPadding: const EdgeInsets.symmetric(
horizontal: 9.5,
vertical: 10,
),
label: Padding(
padding: const EdgeInsets.only(left: 12),
child: Text(
widget.placeholder,
style: theme.textStyle.copyWith(
fontSize: FontSize.style14,
color: widget.isError&& widget.isTouched? theme.dangerMainColor
: theme.neutral70Color,
),
),
),
floatingLabelBehavior: FloatingLabelBehavior.never,
suffixIcon: IconButton(
icon: Icon(
widget.hasValue ? Icons.cancel : Icons.keyboard_arrow_down,
color: widget.isError && widget.isTouched
? theme.dangerMainColor
: theme.neutral90Color,
),
onPressed: widget.hasValue ? () {} : null,
),
),
),
suggestionsCallback: (pattern) async {
await widget.suggestionsCallback?.call();
return _getSuggestions(pattern);
},
itemBuilder: (context, suggestion) {
var isTileSelected = false;
if (keySelected.isNotEmpty) {
isTileSelected = suggestion == keySelected;
}
return ListTileSuggestionBuilder(
isTileSelected: isTileSelected,
suggestion: suggestion.toString(),
);
},
),
);
}
}

View File

@ -0,0 +1,157 @@
import 'package:component_library/component_library.dart';
import 'package:flutter/material.dart';
class ComboBoxField extends StatefulWidget {
final String label;
final String placeholder;
final double? height;
final InputDecoration? decoration;
final Widget? suffixIcon;
final Widget? suffix;
final Widget? prefix;
final Widget? prefixIcon;
final List<DropdownMenuItem<String>> items;
final bool? isDisabled;
final bool? isTouched;
final bool? isError;
final void Function(String? value)? onChangeComboBox;
const ComboBoxField({
Key? key,
required this.label,
required this.items,
this.height,
this.decoration = const InputDecoration(),
required this.placeholder,
this.suffixIcon,
this.suffix,
this.prefix,
this.prefixIcon,
this.isDisabled = false,
this.isTouched = false,
this.isError = false,
this.onChangeComboBox,
}) : super(key: key);
@override
State<ComboBoxField> createState() => _ComboBoxFieldState();
}
class _ComboBoxFieldState extends State<ComboBoxField> {
String? _dropDownValue;
bool _hasFocus = false;
final _dropDownKey = GlobalKey();
void onTapComboBox() {
GestureDetector? detector;
void searchForGestureDetector(BuildContext? element) {
element?.visitChildElements((element) {
if (element.widget is GestureDetector) {
detector = element.widget as GestureDetector?;
} else {
searchForGestureDetector(element);
}
});
}
searchForGestureDetector(_dropDownKey.currentContext);
assert(detector != null);
detector!.onTap!();
}
@override
Widget build(BuildContext context) {
final theme = GolekTheme.of(context);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.label,
style: theme.textStyle.copyWith(
fontSize: FontSize.style13,
color: theme.neutral100Color,
),
),
GestureDetector(
onTap: onTapComboBox,
child: Focus(
onFocusChange: (value) {
setState(() => _hasFocus = value);
},
child: Container(
height: widget.height ?? 52,
decoration: BoxDecoration(
border: Border.all(
color: _hasFocus
? theme.successBorderColor
: Colors.transparent,
width: 3),
borderRadius: BorderRadius.circular(8.0),
),
child: InputDecorator(
decoration: widget.decoration!.copyWith(
contentPadding: const EdgeInsets.symmetric(
horizontal: 9.5,
vertical: 10,
),
counterText: '',
prefixIcon: widget.prefixIcon != null
? Padding(
padding: const EdgeInsetsDirectional.only(
bottom: 0,
),
child: widget.prefixIcon,
)
: null,
fillColor: widget.isDisabled!
? const Color(0xffededed)
: Colors.transparent,
filled: true,
prefix: widget.prefix,
suffixIcon: widget.suffixIcon,
suffix: widget.suffix,
errorStyle: theme.textStyle.copyWith(
fontSize: 0,
),
prefixIconConstraints: const BoxConstraints(
minHeight: 24,
minWidth: 40,
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(6),
borderSide: BorderSide(color: theme.primaryBorderColor),
),
label: Padding(
padding: const EdgeInsets.only(left: 0, bottom: 1),
child: Text(
widget.placeholder,
style: theme.textStyle.copyWith(
fontSize: FontSize.style14,
color: widget.isTouched! && widget.isError!
? theme.dangerMainColor
: theme.neutral70Color,
),
),
),
floatingLabelBehavior: FloatingLabelBehavior.never,
),
child: DropdownButton<String>(
hint: Text(widget.placeholder),
value: _dropDownValue,
key: _dropDownKey,
items: widget.items,
iconSize: 0,
onChanged:(value) {
setState(() => _dropDownValue = value);
widget.onChangeComboBox?.call(value);
},
),
),
),
),
),
],
);
}
}

View File

@ -139,6 +139,48 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_keyboard_visibility:
dependency: transitive
description:
name: flutter_keyboard_visibility
url: "https://pub.dartlang.org"
source: hosted
version: "5.4.0"
flutter_keyboard_visibility_linux:
dependency: transitive
description:
name: flutter_keyboard_visibility_linux
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_keyboard_visibility_macos:
dependency: transitive
description:
name: flutter_keyboard_visibility_macos
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_keyboard_visibility_platform_interface:
dependency: transitive
description:
name: flutter_keyboard_visibility_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
flutter_keyboard_visibility_web:
dependency: transitive
description:
name: flutter_keyboard_visibility_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
flutter_keyboard_visibility_windows:
dependency: transitive
description:
name: flutter_keyboard_visibility_windows
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_lints:
dependency: "direct dev"
description:
@ -170,6 +212,13 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_typeahead:
dependency: "direct main"
description:
name: flutter_typeahead
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.1"
flutter_web_plugins:
dependency: transitive
description: flutter
@ -309,7 +358,7 @@ packages:
source: hosted
version: "1.8.0"
mime:
dependency: transitive
dependency: "direct main"
description:
name: mime
url: "https://pub.dartlang.org"

View File

@ -15,6 +15,8 @@ dependencies:
image_picker: ^0.8.6
file_picker: ^5.2.3
extended_image: ^6.3.4
mime: ^1.0.3
flutter_typeahead: ^4.1.1
dev_dependencies:
flutter_test:

View File

@ -160,6 +160,48 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "8.1.1"
flutter_keyboard_visibility:
dependency: transitive
description:
name: flutter_keyboard_visibility
url: "https://pub.dartlang.org"
source: hosted
version: "5.4.0"
flutter_keyboard_visibility_linux:
dependency: transitive
description:
name: flutter_keyboard_visibility_linux
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_keyboard_visibility_macos:
dependency: transitive
description:
name: flutter_keyboard_visibility_macos
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_keyboard_visibility_platform_interface:
dependency: transitive
description:
name: flutter_keyboard_visibility_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
flutter_keyboard_visibility_web:
dependency: transitive
description:
name: flutter_keyboard_visibility_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
flutter_keyboard_visibility_windows:
dependency: transitive
description:
name: flutter_keyboard_visibility_windows
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_lints:
dependency: "direct dev"
description:
@ -191,6 +233,13 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_typeahead:
dependency: transitive
description:
name: flutter_typeahead
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.1"
flutter_web_plugins:
dependency: transitive
description: flutter

View File

@ -160,6 +160,48 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "8.1.1"
flutter_keyboard_visibility:
dependency: transitive
description:
name: flutter_keyboard_visibility
url: "https://pub.dartlang.org"
source: hosted
version: "5.4.0"
flutter_keyboard_visibility_linux:
dependency: transitive
description:
name: flutter_keyboard_visibility_linux
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_keyboard_visibility_macos:
dependency: transitive
description:
name: flutter_keyboard_visibility_macos
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_keyboard_visibility_platform_interface:
dependency: transitive
description:
name: flutter_keyboard_visibility_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
flutter_keyboard_visibility_web:
dependency: transitive
description:
name: flutter_keyboard_visibility_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
flutter_keyboard_visibility_windows:
dependency: transitive
description:
name: flutter_keyboard_visibility_windows
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_lints:
dependency: "direct dev"
description:
@ -191,6 +233,13 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_typeahead:
dependency: transitive
description:
name: flutter_typeahead
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.1"
flutter_web_plugins:
dependency: transitive
description: flutter

View File

@ -139,6 +139,48 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_keyboard_visibility:
dependency: transitive
description:
name: flutter_keyboard_visibility
url: "https://pub.dartlang.org"
source: hosted
version: "5.4.0"
flutter_keyboard_visibility_linux:
dependency: transitive
description:
name: flutter_keyboard_visibility_linux
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_keyboard_visibility_macos:
dependency: transitive
description:
name: flutter_keyboard_visibility_macos
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_keyboard_visibility_platform_interface:
dependency: transitive
description:
name: flutter_keyboard_visibility_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
flutter_keyboard_visibility_web:
dependency: transitive
description:
name: flutter_keyboard_visibility_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
flutter_keyboard_visibility_windows:
dependency: transitive
description:
name: flutter_keyboard_visibility_windows
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_localizations:
dependency: "direct main"
description: flutter
@ -158,6 +200,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.6"
flutter_typeahead:
dependency: transitive
description:
name: flutter_typeahead
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.1"
flutter_web_plugins:
dependency: transitive
description: flutter

View File

@ -363,6 +363,48 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "8.1.1"
flutter_keyboard_visibility:
dependency: transitive
description:
name: flutter_keyboard_visibility
url: "https://pub.dartlang.org"
source: hosted
version: "5.4.0"
flutter_keyboard_visibility_linux:
dependency: transitive
description:
name: flutter_keyboard_visibility_linux
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_keyboard_visibility_macos:
dependency: transitive
description:
name: flutter_keyboard_visibility_macos
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_keyboard_visibility_platform_interface:
dependency: transitive
description:
name: flutter_keyboard_visibility_platform_interface
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
flutter_keyboard_visibility_web:
dependency: transitive
description:
name: flutter_keyboard_visibility_web
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.0"
flutter_keyboard_visibility_windows:
dependency: transitive
description:
name: flutter_keyboard_visibility_windows
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_lints:
dependency: "direct dev"
description:
@ -394,6 +436,13 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
flutter_typeahead:
dependency: transitive
description:
name: flutter_typeahead
url: "https://pub.dartlang.org"
source: hosted
version: "4.1.1"
flutter_web_plugins:
dependency: transitive
description: flutter