Skip to content

Commit

Permalink
fix: select with options builder (#187)
Browse files Browse the repository at this point in the history
  • Loading branch information
nank1ro authored Nov 4, 2024
1 parent 57b7305 commit 0f6e54e
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 42 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.15.0

- **FIX**: `ShadSelect` crash when using `optionsBuilder`.
- **FEAT**: Add `itemCount` and `shrinkWrap` to `ShadSelect` and `ShadSelectFormField`.

## 0.14.1

- **FIX**: `ShadApp` scroll behavior.
Expand Down
24 changes: 24 additions & 0 deletions lib/src/components/form/fields/select.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ class ShadSelectFormField<T> extends ShadFormBuilderField<T> {
Widget? footer,
bool allowDeselection = false,
bool closeOnSelect = true,

/// {@macro ShadSelect.itemCount}
int? itemCount,

/// {@macro ShadSelect.shrinkWrap}
bool? shrinkWrap,
}) : super(
decorationBuilder: (context) =>
(ShadTheme.of(context).selectTheme.decoration ??
Expand Down Expand Up @@ -88,6 +94,8 @@ class ShadSelectFormField<T> extends ShadFormBuilderField<T> {
header: header,
footer: footer,
closeOnSelect: closeOnSelect,
itemCount: itemCount,
shrinkWrap: shrinkWrap,
);
},
);
Expand Down Expand Up @@ -143,6 +151,12 @@ class ShadSelectFormField<T> extends ShadFormBuilderField<T> {
Widget? footer,
bool allowDeselection = false,
bool closeOnSelect = true,

/// {@macro ShadSelect.itemCount}
int? itemCount,

/// {@macro ShadSelect.shrinkWrap}
bool? shrinkWrap,
}) : super(
decorationBuilder: (context) =>
(ShadTheme.of(context).selectTheme.decoration ??
Expand Down Expand Up @@ -185,6 +199,8 @@ class ShadSelectFormField<T> extends ShadFormBuilderField<T> {
header: header,
footer: footer,
closeOnSelect: closeOnSelect,
itemCount: itemCount,
shrinkWrap: shrinkWrap,
);
},
);
Expand Down Expand Up @@ -237,6 +253,12 @@ class ShadSelectFormField<T> extends ShadFormBuilderField<T> {
Widget? footer,
bool allowDeselection = false,
bool closeOnSelect = true,

/// {@macro ShadSelect.itemCount}
int? itemCount,

/// {@macro ShadSelect.shrinkWrap}
bool? shrinkWrap,
}) : assert(
variant == ShadSelectVariant.primary || onSearchChanged != null,
'onSearchChanged must be provided when variant is search',
Expand Down Expand Up @@ -287,6 +309,8 @@ class ShadSelectFormField<T> extends ShadFormBuilderField<T> {
footer: footer,
allowDeselection: allowDeselection,
closeOnSelect: closeOnSelect,
itemCount: itemCount,
shrinkWrap: shrinkWrap,
);
},
);
Expand Down
109 changes: 68 additions & 41 deletions lib/src/components/select.dart
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ class ShadSelect<T> extends StatefulWidget {
this.footer,
this.closeOnSelect = true,
this.allowDeselection = false,
this.itemCount,
this.shrinkWrap,
}) : variant = ShadSelectVariant.primary,
onSearchChanged = null,
searchDivider = null,
Expand Down Expand Up @@ -114,6 +116,8 @@ class ShadSelect<T> extends StatefulWidget {
this.footer,
this.closeOnSelect = true,
this.allowDeselection = false,
this.itemCount,
this.shrinkWrap,
}) : variant = ShadSelectVariant.search,
selectedOptionsBuilder = null,
onMultipleChanged = null,
Expand Down Expand Up @@ -152,6 +156,8 @@ class ShadSelect<T> extends StatefulWidget {
this.footer,
this.allowDeselection = true,
this.closeOnSelect = true,
this.itemCount,
this.shrinkWrap,
}) : variant = ShadSelectVariant.multiple,
onSearchChanged = null,
initialValue = null,
Expand Down Expand Up @@ -206,6 +212,8 @@ class ShadSelect<T> extends StatefulWidget {
this.footer,
this.allowDeselection = true,
this.closeOnSelect = true,
this.itemCount,
this.shrinkWrap,
}) : variant = ShadSelectVariant.multipleWithSearch,
selectedOptionBuilder = null,
onChanged = null,
Expand Down Expand Up @@ -257,6 +265,8 @@ class ShadSelect<T> extends StatefulWidget {
this.footer,
this.allowDeselection = false,
this.closeOnSelect = true,
this.itemCount,
this.shrinkWrap,
}) : assert(
variant == ShadSelectVariant.primary || onSearchChanged != null,
'onSearchChanged must be provided when variant is search',
Expand Down Expand Up @@ -418,6 +428,20 @@ class ShadSelect<T> extends StatefulWidget {
/// {@endtemplate}
final bool closeOnSelect;

/// {@template ShadSelect.itemCount}
/// The number of items in the options, used in combination with
/// [optionsBuilder].
/// {@endtemplate}
final int? itemCount;

/// {@template ShadSelect.shrinkWrap}
/// Whether the options returned by [optionsBuilder] should shrink wrap,
/// defaults to `false`.
/// You may set it to `true` when the [itemCount] provided is small and you
/// want the content to be resized.
/// {@endtemplate}
final bool? shrinkWrap;

static ShadSelectState<T> of<T>(BuildContext context, {bool listen = true}) {
return maybeOf<T>(context, listen: listen)!;
}
Expand Down Expand Up @@ -660,7 +684,7 @@ class ShadSelectState<T> extends State<ShadSelect<T>> {
theme.selectTheme.optionsPadding ??
const EdgeInsets.all(4);

Widget? search = switch (widget.variant) {
final search = switch (widget.variant) {
ShadSelectVariant.primary || ShadSelectVariant.multiple => null,
ShadSelectVariant.search ||
ShadSelectVariant.multipleWithSearch =>
Expand Down Expand Up @@ -689,10 +713,6 @@ class ShadSelectState<T> extends State<ShadSelect<T>> {
),
};

if (search != null && effectiveMaxWidth.isInfinite) {
search = search;
}

return CallbackShortcuts(
bindings: {
const SingleActivator(LogicalKeyboardKey.enter): controller.toggle,
Expand Down Expand Up @@ -727,6 +747,8 @@ class ShadSelectState<T> extends State<ShadSelect<T>> {
effectiveChild = ListView.builder(
padding: effectiveOptionsPadding,
controller: scrollController,
itemCount: widget.itemCount,
shrinkWrap: widget.shrinkWrap ?? false,
itemBuilder: (context, index) {
return widget.optionsBuilder?.call(context, index);
},
Expand Down Expand Up @@ -858,48 +880,53 @@ class ShadSelectState<T> extends State<ShadSelect<T>> {
}
});

Widget effectiveColumn = Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisSize: MainAxisSize.min,
children: [
if (search != null)
Flexible(
child: ConstrainedBox(
constraints: effectiveConstraints,
child: search,
),
),
if (widget.header != null)
Flexible(
child: ConstrainedBox(
constraints: effectiveConstraints,
child: widget.header,
),
),
if (scrollToTopChild != null) scrollToTopChild,
Flexible(
child: ConstrainedBox(
constraints: effectiveConstraints,
child: effectiveChild,
),
),
if (scrollToBottomChild != null) scrollToBottomChild,
if (widget.footer != null)
Flexible(
child: ConstrainedBox(
constraints: effectiveConstraints,
child: widget.footer,
),
),
],
);

if (widget.optionsBuilder == null) {
effectiveColumn = IntrinsicWidth(child: effectiveColumn);
}

return ConstrainedBox(
constraints: BoxConstraints(
maxHeight: effectiveMaxHeight,
minWidth: calculatedMinWidth,
maxWidth: effectiveMaxWidth,
),
child: IntrinsicWidth(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
if (search != null)
Flexible(
child: ConstrainedBox(
constraints: effectiveConstraints,
child: search,
),
),
if (widget.header != null)
Flexible(
child: ConstrainedBox(
constraints: effectiveConstraints,
child: widget.header,
),
),
if (scrollToTopChild != null) scrollToTopChild,
Flexible(
child: ConstrainedBox(
constraints: effectiveConstraints,
child: effectiveChild,
),
),
if (scrollToBottomChild != null) scrollToBottomChild,
if (widget.footer != null)
Flexible(
child: ConstrainedBox(
constraints: effectiveConstraints,
child: widget.footer,
),
),
],
),
),
child: effectiveColumn,
);
},
child: select,
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: shadcn_ui
description: shadcn-ui ported in Flutter. Awesome UI components for Flutter, fully customizable.
version: 0.14.1
version: 0.15.0
homepage: https://flutter-shadcn-ui.mariuti.com
repository: https://github.com/nank1ro/flutter-shadcn-ui
documentation: https://flutter-shadcn-ui.mariuti.com
Expand Down

0 comments on commit 0f6e54e

Please sign in to comment.