Line data Source code
1 : import 'package:basf_flutter_components/basf_flutter_components.dart';
2 : import 'package:flutter/material.dart';
3 :
4 : /// {@template dropdown_input}
5 : /// A BASF-styled dropdown input
6 : /// {@endtemplate}
7 : class BasfDropDownInput extends StatefulWidget {
8 : /// {@macro dropdown_input}
9 1 : const BasfDropDownInput({
10 : super.key,
11 : required this.controller,
12 : required this.values,
13 : this.labelText,
14 : this.crossAxisAlignment = CrossAxisAlignment.center,
15 : this.mainAxisAlignment = MainAxisAlignment.end,
16 : this.isExpanded = false,
17 : this.isLoading = false,
18 : });
19 :
20 : /// Controller
21 : final TextEditingController controller;
22 :
23 : /// Label for the dropdown
24 : final String? labelText;
25 :
26 : /// List of values
27 : final List<String> values;
28 :
29 : /// Cross alignment
30 : final CrossAxisAlignment crossAxisAlignment;
31 :
32 : /// Main alignment
33 : final MainAxisAlignment mainAxisAlignment;
34 :
35 : /// Wheter or not the dropdown should expand itself
36 : final bool isExpanded;
37 :
38 : /// Wheter or not the dropdown is loading
39 : final bool isLoading;
40 :
41 1 : @override
42 1 : State<BasfDropDownInput> createState() => _BasfDropDownInputState();
43 : }
44 :
45 : class _BasfDropDownInputState extends State<BasfDropDownInput> {
46 1 : @override
47 : void initState() {
48 7 : if (widget.values.contains(widget.controller.text.trim())) {
49 3 : widget.controller.text =
50 9 : widget.values.firstWhere((e) => e == widget.controller.text.trim());
51 : } else {
52 6 : widget.controller.text = widget.values.first;
53 : }
54 1 : super.initState();
55 : }
56 :
57 1 : @override
58 : Widget build(BuildContext context) {
59 1 : final theme = Theme.of(context);
60 :
61 1 : return Container(
62 : height: 48,
63 1 : decoration: BoxDecoration(
64 1 : borderRadius: BasfThemes.defaultBorderRadius,
65 1 : border: Border.all(
66 : color: BasfInputThemes
67 4 : .mainInputDecorationTheme.enabledBorder!.borderSide.color,
68 : ),
69 : ),
70 1 : child: Stack(
71 1 : children: [
72 1 : Opacity(
73 2 : opacity: !widget.isLoading ? 1 : 0,
74 1 : child: Row(
75 2 : crossAxisAlignment: widget.crossAxisAlignment,
76 2 : mainAxisAlignment: widget.mainAxisAlignment,
77 1 : children: [
78 1 : Padding(
79 : padding: const EdgeInsets.only(left: Dimens.paddingMedium),
80 1 : child: Text(
81 3 : widget.controller.text,
82 2 : style: BasfThemes.mainTextTheme.headline6
83 2 : ?.copyWith(color: theme.primaryColor),
84 : ),
85 : ),
86 2 : if (widget.isExpanded) const Spacer(),
87 1 : _menuButton(),
88 : ],
89 : ),
90 : ),
91 2 : if (widget.isLoading)
92 1 : Positioned(
93 : top: 0,
94 : bottom: 0,
95 : right: 0,
96 : left: 0,
97 2 : child: Center(child: _loader(theme)),
98 : ),
99 : ],
100 : ),
101 : );
102 : }
103 :
104 1 : Widget _loader(ThemeData theme) {
105 1 : return Container(
106 : width: 20,
107 : height: 20,
108 : alignment: Alignment.centerLeft,
109 1 : child: CircularProgressIndicator(
110 1 : color: theme.primaryColor,
111 : strokeWidth: 3,
112 : ),
113 : );
114 : }
115 :
116 1 : Widget _menuButton() {
117 1 : return Theme(
118 3 : data: Theme.of(context).copyWith(
119 1 : highlightColor: BasfColors.darkBlue.shade100,
120 : ),
121 1 : child: PopupMenuButton<String>(
122 : icon: const Icon(BasfIcons.arrow_down, size: 16),
123 : iconSize: 18,
124 : tooltip: 'menu',
125 3 : initialValue: widget.controller.text,
126 1 : shape: RoundedRectangleBorder(
127 1 : borderRadius: BasfThemes.defaultBorderRadius,
128 : ),
129 1 : onSelected: (String value) {
130 2 : setState(() {
131 3 : widget.controller.text = value;
132 : });
133 : },
134 1 : itemBuilder: (context) {
135 5 : return List.generate(widget.values.length, (index) {
136 1 : return PopupMenuItem<String>(
137 3 : value: widget.values[index],
138 4 : child: Text(widget.values[index]),
139 : );
140 : });
141 : },
142 : ),
143 : );
144 : }
145 : }
|