Skip to content

Commit

Permalink
v6.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Salim Lachdhaf committed Sep 21, 2024
1 parent f4b890e commit e7f1b04
Show file tree
Hide file tree
Showing 15 changed files with 202 additions and 201 deletions.
44 changes: 27 additions & 17 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
## [6.0.1] - 2024.09.21
* #### New Feature:
* add `Semantics` to searchBox to support voiceOver/TalkBack ...

* #### Fix bugs:
* duplicated GlobalKey issue [672](https://github.com/salim-lachdhaf/searchable_dropdown/issues/672)
* multiSelection chips height issue [602](https://github.com/salim-lachdhaf/searchable_dropdown/issues/602)
* hint and dropdownBuilder issue [515](https://github.com/salim-lachdhaf/searchable_dropdown/issues/515)


## [6.0.0] - 2024.09.14

* #### New features:
* infinite list / lazy loading
* add click properties to the dropdown
* add custom mode
* dropdown button can be changed depending on state (opened/closed)
* add property ```cacheItems``` for popupProps
* add property ```onItemLoaded```
* add property `cacheItems` for popupProps
* add property `onItemLoaded`
* adding new properties for a lot of widget (scrollBar, modal, bottomSheet,...)
* add to possibility to change position of ```clearButton``` and ```dropdownButton```
using ```direction``` property

* #### Breaking changes :
* ```AsyncItems``` and ```items``` are replaced by ```items:(filter, infiniteScrollProps)```
* Add ```isDisabled``` to ```itemBuilder``` params
* ```FavoriteItems``` renamed to ```SuggestedItems```
* ```isFilterOnline``` renamed to ```disableFilter```
* ```selectionWidget``` renamed to ```checkBoxBuilder```
* ```dropdownDecoratorProps``` renamed to ```decoratorProps```
* ```clearButtonProps``` and ```dropdownButtonProps``` are placed to ```suffixProps```
* `AsyncItems` and `items` are replaced by `items:(filter, infiniteScrollProps)`
* Add `isDisabled` to `itemBuilder` params
* `FavoriteItems` renamed to `SuggestedItems`
* `isFilterOnline` renamed to `disableFilter`
* `selectionWidget` renamed to `checkBoxBuilder`
* `dropdownDecoratorProps` renamed to `decoratorProps`
* `clearButtonProps` and `dropdownButtonProps` are placed to `suffixProps`
* #### Fix bugs:
* Search delay issue [542](https://github.com/salim-lachdhaf/searchable_dropdown/issues/542),
* Multiselection triggers didChange
Expand Down Expand Up @@ -60,7 +70,7 @@

## [5.0.2] - 2022.06.04

* add ```interceptCallBacks``` for popupProps
* add `interceptCallBacks` for popupProps

## [5.0.1] - 2022.05.29

Expand All @@ -74,8 +84,8 @@
* replace ``IconButtonProps`` with DropdownButtonProps and ``ClearButtonProps`` for ``clearButtonProps``
and dropdownButtonProps
* add a full custom container for the pop `containerBuilder` to ``popup_props``
* add ```isVisible``` prop to `DropdownButtonProps`
* change ``validationMultiSelectionWidget`` to ``validationWidgetBuilder``
* add `isVisible` prop to `DropdownButtonProps`
* change `validationMultiSelectionWidget` to `validationWidgetBuilder`

## [4.0.1] - 2022.05.17

Expand Down Expand Up @@ -103,11 +113,11 @@
## [3.0.1] - 2022.04.15

* breaking changes:
- remove ``hint`` and ``label`` properties, use ``dropdownSearchDecoration`` instead
- remove ``showAsSuffixIcons`` property, now always are as suffixIcon
- replace '``clearButtonSplashRadius``' and '``clearButtonBuilder``' into one property '``IconButtonProps``'
- replace '``dropdownButtonSplashRadius``' and '``dropdownButtonBuilder``' into one property '
``IconButtonProps``'
- remove `hint` and `label` properties, use `dropdownSearchDecoration` instead
- remove `showAsSuffixIcons` property, now always are as suffixIcon
- replace '`clearButtonSplashRadius`' and '`clearButtonBuilder`' into one property '`IconButtonProps`'
- replace '`dropdownButtonSplashRadius`' and '`dropdownButtonBuilder`' into one property '
`IconButtonProps`'
* fix issue [380](https://github.com/salim-lachdhaf/searchable_dropdown/issues/380)

## [2.0.1] - 2021.11.15
Expand Down
127 changes: 76 additions & 51 deletions lib/dropdown_search.dart
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,15 @@ typedef LoadingBuilder<T> = Widget Function(
typedef BeforeChange<T> = Future<bool?> Function(T? prevItem, T? nextItem);
typedef BeforePopupOpening<T> = Future<bool?> Function(T? selectedItem);
typedef BeforePopupOpeningMultiSelection<T> = Future<bool?> Function(
List<T> selItems);
List<T> selectedItem);
typedef BeforeChangeMultiSelection<T> = Future<bool?> Function(
List<T> prevItems, List<T> nextItems);
typedef FavoriteItemsBuilder<T> = Widget Function(
BuildContext context, T item, bool isSelected);
typedef ValidationMultiSelectionBuilder<T> = Widget Function(
BuildContext context, List<T> items);
typedef PositionCallback = RelativeRect Function(
RenderBox popupButtonObject, RenderBox overlay);
RenderBox dropdownBox, RenderBox overlay);
typedef OnItemAdded<T> = void Function(List<T> selectedItems, T addedItem);
typedef OnItemRemoved<T> = void Function(List<T> selectedItems, T removedItem);
typedef PopupBuilder<T> = Widget Function(
Expand Down Expand Up @@ -96,13 +96,15 @@ class DropdownSearch<T> extends StatefulWidget {

/// scroll props for selected item on the dropdown.
/// example :
/// SizedBox(
/// height: 50,
/// child: DropdownSearch<int>.multiSelection(
/// items: (f, cs) => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
/// selectedItemsScrollProps: ScrollProps(),
/// ),
/// ),
/// ```dart
/// SizedBox(
/// height: 50,
/// child: DropdownSearch<int>.multiSelection(
/// items: (f, cs) => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
/// selectedItemsScrollProps: ScrollProps(),
/// ),
/// ),
///```
final ScrollProps? selectedItemsScrollProps;

///customize the fields the be shown
Expand Down Expand Up @@ -169,13 +171,10 @@ class DropdownSearch<T> extends StatefulWidget {
super.key,
T? selectedItem,
this.mode = Mode.form,
this.onSaved,
this.validator,
this.autoValidateMode = AutovalidateMode.disabled,
this.onChanged,
this.items,
this.dropdownBuilder,
this.decoratorProps = const DropDownDecoratorProps(),
this.suffixProps = const DropdownSuffixProps(),
this.clickProps = const ClickProps(),
this.enabled = true,
Expand All @@ -185,8 +184,24 @@ class DropdownSearch<T> extends StatefulWidget {
this.onBeforeChange,
this.onBeforePopupOpening,
PopupProps<T> popupProps = const PopupProps.menu(),
}) : assert(T == String || T == int || T == double || compareFn != null),
assert(mode != Mode.custom || dropdownBuilder != null),
//form properties
this.onSaved,
this.validator,
DropDownDecoratorProps? decoratorProps,
}) : assert(
T == String || T == int || T == double || compareFn != null,
'`compareFn` is required',
),
assert(
mode != Mode.custom || dropdownBuilder != null,
'Please implement your `dropdownBuilder`',
),
assert(
mode != Mode.custom ||
(decoratorProps == null && onSaved == null && validator == null),
'Custom mode has no form properties',
),
decoratorProps = decoratorProps ?? const DropDownDecoratorProps(),
selectedItems = _itemToList(selectedItem),
popupProps = PopupPropsMultiSelection.from(popupProps),
isMultiSelectionMode = false,
Expand All @@ -203,7 +218,6 @@ class DropdownSearch<T> extends StatefulWidget {
this.mode = Mode.form,
this.autoValidateMode = AutovalidateMode.disabled,
this.items,
this.decoratorProps = const DropDownDecoratorProps(),
this.suffixProps = const DropdownSuffixProps(),
this.clickProps = const ClickProps(),
this.enabled = true,
Expand All @@ -213,14 +227,28 @@ class DropdownSearch<T> extends StatefulWidget {
this.selectedItems = const [],
this.popupProps = const PopupPropsMultiSelection.menu(),
this.selectedItemsScrollProps,
FormFieldSetter<List<T>>? onSaved,
ValueChanged<List<T>>? onChanged,
BeforeChangeMultiSelection<T>? onBeforeChange,
BeforePopupOpeningMultiSelection<T>? onBeforePopupOpening,
FormFieldValidator<List<T>>? validator,
DropdownSearchBuilderMultiSelection<T>? dropdownBuilder,
}) : assert(T == String || T == int || T == double || compareFn != null),
assert(mode != Mode.custom || dropdownBuilder != null),
//form properties
FormFieldSetter<List<T>>? onSaved,
FormFieldValidator<List<T>>? validator,
DropDownDecoratorProps? decoratorProps,
}) : assert(
T == String || T == int || T == double || compareFn != null,
'`compareFn` is required',
),
assert(
mode != Mode.custom || dropdownBuilder != null,
'Please implement your `dropdownBuilder`',
),
assert(
mode != Mode.custom ||
(decoratorProps == null && onSaved == null && validator == null),
"Custom mode has no form properties",
),
decoratorProps = decoratorProps ?? const DropDownDecoratorProps(),
onChangedMultiSelection = onChanged,
onBeforePopupOpeningMultiSelection = onBeforePopupOpening,
onSavedMultiSelection = onSaved,
Expand Down Expand Up @@ -301,7 +329,6 @@ class DropdownSearchState<T> extends State<DropdownSearch<T>> {
Widget _defaultSelectedItemWidget() {
Widget defaultItemMultiSelectionMode(T item) {
return Container(
height: 32,
padding: EdgeInsets.only(left: 8, right: 1),
margin: EdgeInsets.symmetric(horizontal: 2, vertical: 1),
decoration: BoxDecoration(
Expand All @@ -312,24 +339,20 @@ class DropdownSearchState<T> extends State<DropdownSearch<T>> {
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Flexible(
child: Text(
_selectedItemAsString(item),
style: Theme.of(context).textTheme.titleSmall,
overflow: TextOverflow.ellipsis,
),
Text(
_itemAsString(item),
style: Theme.of(context).textTheme.titleSmall,
overflow: TextOverflow.ellipsis,
),
MaterialButton(
height: 20,
shape: const CircleBorder(),
padding: const EdgeInsets.all(0),
minWidth: 20,
onPressed: () {
removeItem(item);
},
child: Icon(
Icons.close_outlined,
size: 20,
Padding(padding: EdgeInsets.only(left: 8)),
SizedBox(
width: 32,
height: 32,
child: IconButton(
iconSize: 20,
padding: EdgeInsets.zero,
icon: Icon(Icons.close_outlined, size: 20),
onPressed: () => removeItem(item),
),
)
],
Expand All @@ -346,13 +369,15 @@ class DropdownSearchState<T> extends State<DropdownSearch<T>> {
return CustomSingleScrollView(
scrollProps: widget.selectedItemsScrollProps ?? ScrollProps(),
child: Wrap(
children: getSelectedItems
.map((e) => defaultItemMultiSelectionMode(e))
.toList()),
crossAxisAlignment: WrapCrossAlignment.center,
children: getSelectedItems
.map((e) => defaultItemMultiSelectionMode(e))
.toList(),
),
);
}
return Text(
_selectedItemAsString(getSelectedItem),
_itemAsString(getSelectedItem),
style: _getBaseTextStyle(),
textAlign: widget.decoratorProps.textAlign,
);
Expand Down Expand Up @@ -398,8 +423,7 @@ class DropdownSearchState<T> extends State<DropdownSearch<T>> {
baseStyle: _getBaseTextStyle(),
textAlign: widget.decoratorProps.textAlign,
textAlignVertical: widget.decoratorProps.textAlignVertical,
isEmpty:
getSelectedItem == null && widget.dropdownBuilder == null,
isEmpty: getSelectedItem == null,
isFocused: isFocused,
expands: widget.decoratorProps.expands,
isHovering: widget.decoratorProps.isHovering,
Expand Down Expand Up @@ -433,8 +457,7 @@ class DropdownSearchState<T> extends State<DropdownSearch<T>> {
baseStyle: _getBaseTextStyle(),
textAlign: widget.decoratorProps.textAlign,
textAlignVertical: widget.decoratorProps.textAlignVertical,
isEmpty: getSelectedItems.isEmpty &&
widget.dropdownBuilderMultiSelection == null,
isEmpty: getSelectedItems.isEmpty,
expands: widget.decoratorProps.expands,
isHovering: widget.decoratorProps.isHovering,
isFocused: isFocused,
Expand All @@ -458,14 +481,14 @@ class DropdownSearchState<T> extends State<DropdownSearch<T>> {
}

///function that return the String value of an object
String _selectedItemAsString(T? data) {
String _itemAsString(T? data) {
if (data == null) {
return "";
} else if (widget.itemAsString != null) {
return widget.itemAsString!(data);
} else {
return data.toString();
}

return data.toString();
}

///function that manage Trailing icons(close, dropDown)
Expand Down Expand Up @@ -545,7 +568,6 @@ class DropdownSearchState<T> extends State<DropdownSearch<T>> {
transitionBuilder: widget.popupProps.dialogProps.transitionBuilder,
pageBuilder: (context, animation, secondaryAnimation) {
return AlertDialog(
key: widget.popupProps.dialogProps.key,
buttonPadding: widget.popupProps.dialogProps.buttonPadding,
actionsOverflowButtonSpacing:
widget.popupProps.dialogProps.actionsOverflowButtonSpacing,
Expand Down Expand Up @@ -720,6 +742,10 @@ class DropdownSearchState<T> extends State<DropdownSearch<T>> {
///If we close the popup , or maybe we just selected
///another widget we should clear the focus
Future<void> _selectSearchMode() async {
//fix Duplicate GlobalKey detected in widget tree.
//if the popup not yet disposed do nothing => solve issue fast click
if (_popupStateKey.currentState != null) return;

//handle onBefore popupOpening
if (widget.onBeforePopupOpening != null) {
if (await widget.onBeforePopupOpening!(getSelectedItem) == false) return;
Expand All @@ -738,8 +764,7 @@ class DropdownSearchState<T> extends State<DropdownSearch<T>> {
} else {
await _openSelectDialog();
}
//dismiss either by selecting items OR clicking outside the popup
widget.popupProps.onDismissed?.call();

_handleFocus(false);
}

Expand Down
1 change: 0 additions & 1 deletion lib/src/properties/clear_button_props.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import 'package:flutter/material.dart';

class ClearButtonProps extends IconButtonProps {
const ClearButtonProps({
super.key,
super.icon = const Icon(Icons.clear, size: 24),
super.isVisible = false,
super.iconSize = 24.0,
Expand Down
2 changes: 0 additions & 2 deletions lib/src/properties/dialog_props.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import 'package:flutter/material.dart';

class DialogProps {
final Key? key;
final List<Widget>? actions;
final MainAxisAlignment? actionsAlignment;
final OverflowBarAlignment? actionsOverflowAlignment;
Expand Down Expand Up @@ -29,7 +28,6 @@ class DialogProps {
final Color? surfaceTintColor;

const DialogProps({
this.key,
this.alignment,
this.elevation,
this.semanticLabel,
Expand Down
4 changes: 0 additions & 4 deletions lib/src/properties/dropdown_props.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ class DropdownButtonProps extends IconButtonProps {
final Widget iconOpened;

const DropdownButtonProps({
super.key,
this.iconOpened = const Icon(Icons.arrow_drop_up, size: 24),
Widget iconClosed = const Icon(Icons.arrow_drop_down, size: 24),
super.isVisible = true,
Expand Down Expand Up @@ -313,10 +312,7 @@ class ClickProps {
/// The default is 50ms.
final Duration? hoverDuration;

final Key? key;

const ClickProps({
this.key,
this.containedInkWell = true,
this.highlightShape = BoxShape.rectangle,
this.onFocusChange,
Expand Down
2 changes: 0 additions & 2 deletions lib/src/properties/icon_button_props.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'package:flutter/material.dart';

///see [IconButton] props for more details
class IconButtonProps {
final Key? key;
final double iconSize;
final VisualDensity? visualDensity;
final EdgeInsetsGeometry padding;
Expand All @@ -27,7 +26,6 @@ class IconButtonProps {
final Widget? selectedIcon;

const IconButtonProps({
this.key,
required this.icon,
this.isVisible = false,
this.iconSize = 24.0,
Expand Down
Loading

0 comments on commit e7f1b04

Please sign in to comment.