Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
## [next]


- refactor: Flutter 3.47.1 support
- refactor: migrate Material UI imports to the standalone `material_ui` package
- refactor: migrate Cupertino UI imports to the standalone `cupertino_ui` package
- refactor: update localization delegates to use `GlobalMaterialLocalizations.delegates` with the new standalone UI packages
- fix: skip hidden `TitleBar` children when collecting semantics ([#1354](https://github.com/bdlukaa/fluent_ui/pull/1354))
- fix: `ComboBox` no longer throws a layout assertion when opened while fully aligned to the bottom edge of the viewport ([#1350](https://github.com/bdlukaa/fluent_ui/issues/1350))

## 4.16.1

Expand Down
7 changes: 7 additions & 0 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ analyzer:
- lib/src/styles/color_resources.dart
- bin/**
- "**/*.g.dart"
- build/**
- android/**
- ios/**
- web/**
- windows/**
- macos/**
- linux/**
language:
strict-casts: true
strict-inference: true
Expand Down
7 changes: 7 additions & 0 deletions example/analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@ analyzer:
exclude:
- "**/*.g.dart"
- "**/*.freezed.dart"
- build/**
- android/**
- ios/**
- web/**
- windows/**
- macos/**
- linux/**

linter:
rules:
Expand Down
2 changes: 1 addition & 1 deletion example/lib/routes/forms.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export '../screens/forms/auto_suggest_box.dart';
export '../screens/forms/calendar_date_picker.dart';
export '../screens/forms/calendar_view.dart';
export '../screens/forms/color_picker.dart';
export '../screens/forms/combobox.dart';
export '../screens/forms/combo_box.dart';
export '../screens/forms/date_picker.dart';
export '../screens/forms/number_box.dart';
export '../screens/forms/password_box.dart';
Expand Down
2 changes: 1 addition & 1 deletion example/macos/Podfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
platform :osx, '10.15'
platform :osx, '12.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
Expand Down
4 changes: 2 additions & 2 deletions example/macos/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ EXTERNAL SOURCES:
:path: Flutter/ephemeral

SPEC CHECKSUMS:
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
FlutterMacOS: c232990155153907050900a2e175c7773903ba4e

PODFILE CHECKSUM: 0d3963a09fc94f580682bd88480486da345dc3f0
PODFILE CHECKSUM: 505596d150d38022472859d890f709281982e016

COCOAPODS: 1.16.2
6 changes: 3 additions & 3 deletions example/macos/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MACOSX_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
Expand Down Expand Up @@ -476,7 +476,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MACOSX_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
Expand Down Expand Up @@ -523,7 +523,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.15;
MACOSX_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
Expand Down
3 changes: 2 additions & 1 deletion lib/src/controls/flyouts/flyout.dart
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,8 @@ class _FlyoutPositionDelegate extends SingleChildLayoutDelegate {
return clampDouble(
y,
margin,
(rootSize.height - flyoutSize.height - margin).clamp(
clampDouble(
rootSize.height - flyoutSize.height - margin,
margin,
rootSize.height - margin,
),
Expand Down
5 changes: 3 additions & 2 deletions lib/src/controls/flyouts/menu_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -268,8 +268,9 @@ class MenuBarState extends State<MenuBar> {
},
child: Container(
constraints: BoxConstraints(
minHeight: (40 + theme.visualDensity.baseSizeAdjustment.dy).clamp(
0.0,
minHeight: clampDouble(
40 + theme.visualDensity.baseSizeAdjustment.dy,
0,
double.infinity,
),
),
Expand Down
5 changes: 3 additions & 2 deletions lib/src/controls/flyouts/tooltip.dart
Original file line number Diff line number Diff line change
Expand Up @@ -530,8 +530,9 @@ class TooltipThemeData with Diagnosticable {
/// Creates the standard [TooltipThemeData] based on the given [theme].
factory TooltipThemeData.standard(FluentThemeData theme) {
return TooltipThemeData(
height: (32 + theme.visualDensity.baseSizeAdjustment.dy).clamp(
0.0,
height: clampDouble(
32 + theme.visualDensity.baseSizeAdjustment.dy,
0,
double.infinity,
),
verticalOffset: 24,
Expand Down
13 changes: 9 additions & 4 deletions lib/src/controls/form/auto_suggest_box.dart
Original file line number Diff line number Diff line change
Expand Up @@ -653,12 +653,16 @@ class AutoSuggestBoxState<T> extends State<AutoSuggestBox<T>> {
final double overlayOffsetY;
final double maxHeight;
if (showAbove) {
maxHeight = spaceAbove.clamp(0.0, widget.maxPopupHeight);
maxHeight = clampDouble(spaceAbove, 0, widget.maxPopupHeight);
overlayOffsetY = -(maxHeight + 0.8);
} else {
overlayOffsetY = box.size.height + 0.8;
final overlayY = globalOffset.dy + box.size.height;
maxHeight = (screenHeight - overlayY).clamp(0.0, widget.maxPopupHeight);
maxHeight = clampDouble(
screenHeight - overlayY,
0,
widget.maxPopupHeight,
);
}

Widget child = PositionedDirectional(
Expand Down Expand Up @@ -977,8 +981,9 @@ class _AutoSuggestBoxOverlayState<T> extends State<_AutoSuggestBoxOverlay<T>> {
/// Returns the tile height adjusted for the given visual density.
@visibleForTesting
static double adjustedTileHeight(VisualDensity density) {
return (_tileHeight + density.baseSizeAdjustment.dy).clamp(
0.0,
return clampDouble(
_tileHeight + density.baseSizeAdjustment.dy,
0,
double.infinity,
);
}
Expand Down
40 changes: 24 additions & 16 deletions lib/src/controls/form/combo_box.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,13 @@ class _ComboBoxMenuPainter extends CustomPainter {
final maxTopOffset = math.max<double>(0, size.height - scaledItemHeight);
final minBottomOffset = math.min(scaledItemHeight, size.height);
final top = Tween<double>(
begin: selectedItemOffset.clamp(0.0, maxTopOffset),
begin: clampDouble(selectedItemOffset, 0, maxTopOffset),
end: 0,
);

final bottom = Tween<double>(
begin: (top.begin! + scaledItemHeight).clamp(
begin: clampDouble(
top.begin! + scaledItemHeight,
minBottomOffset,
size.height,
),
Expand Down Expand Up @@ -407,12 +408,13 @@ class _ComboBoxResizeClipper extends CustomClipper<RRect> {
final maxTopOffset = math.max<double>(0, size.height - scaledItemHeight);
final minBottomOffset = math.min(scaledItemHeight, size.height);
final top = Tween<double>(
begin: selectedItemOffset.clamp(0.0, maxTopOffset),
begin: clampDouble(selectedItemOffset, 0, maxTopOffset),
end: 0,
);

final bottom = Tween<double>(
begin: (top.begin! + scaledItemHeight).clamp(
begin: clampDouble(
top.begin! + scaledItemHeight,
minBottomOffset,
size.height,
),
Expand Down Expand Up @@ -472,28 +474,33 @@ class _ComboBoxMenuRouteLayout<T> extends SingleChildLayoutDelegate {
size.height,
route.selectedIndex ?? 0,
);
final top = clampDouble(
menuLimits.top,
0,
math.max(0, size.height - childSize.height),
);

assert(() {
final container = Offset.zero & size;
if (container.intersect(buttonRect) == buttonRect) {
// If the button was entirely on-screen, then verify
// that the menu is also on-screen.
// If the button was a bit off-screen, then, oh well.
assert(menuLimits.top >= 0.0);
assert(menuLimits.top + menuLimits.height <= size.height);
assert(top >= 0.0);
assert(top + childSize.height <= size.height);
}
return true;
}());
assert(textDirection != null);
final double left;
switch (textDirection!) {
case TextDirection.rtl:
left = buttonRect.right.clamp(0.0, size.width) - childSize.width;
left = clampDouble(buttonRect.right, 0, size.width) - childSize.width;
case TextDirection.ltr:
left = buttonRect.left.clamp(0.0, size.width - childSize.width);
left = clampDouble(buttonRect.left, 0, size.width - childSize.width);
}

return Offset(left, menuLimits.top);
return Offset(left, top);
}

@override
Expand Down Expand Up @@ -806,14 +813,15 @@ class _ComboBoxItemContainer extends StatelessWidget {

final textScaler = MediaQuery.textScalerOf(context);
final densityAdjustment = theme.visualDensity.baseSizeAdjustment.dy;
final adjustedItemHeight =
(textScaler.scale(kComboBoxItemHeight) + densityAdjustment).clamp(
0.0,
double.infinity,
);
final adjustedItemHeight = clampDouble(
textScaler.scale(kComboBoxItemHeight) + densityAdjustment,
0,
double.infinity,
);
final itemHeight = adjustedItemHeight;
final buttonHeight = (adjustedItemHeight - _kMenuItemBottomPadding).clamp(
0.0,
final buttonHeight = clampDouble(
adjustedItemHeight - _kMenuItemBottomPadding,
0,
double.infinity,
);
return Container(
Expand Down
19 changes: 12 additions & 7 deletions lib/src/controls/form/number_box.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:async';
import 'dart:ui' as ui;
import 'dart:ui';

import 'package:fluent_ui/fluent_ui.dart';
import 'package:flutter/gestures.dart';
Expand Down Expand Up @@ -546,10 +547,12 @@ class NumberBoxState<T extends num> extends State<NumberBox<T>> {
if (boxContext == null) return const SizedBox.shrink();
final box = boxContext.findRenderObject()! as RenderBox;
final isRtl = Directionality.of(context) == TextDirection.rtl;
final overlayHeight =
(kNumberBoxOverlayHeight +
FluentTheme.of(context).visualDensity.baseSizeAdjustment.dy)
.clamp(0.0, double.infinity);
final overlayHeight = clampDouble(
kNumberBoxOverlayHeight +
FluentTheme.of(context).visualDensity.baseSizeAdjustment.dy,
0,
double.infinity,
);

final Widget child = PositionedDirectional(
width: kNumberBoxOverlayWidth,
Expand Down Expand Up @@ -913,9 +916,11 @@ class _NumberBoxCompactOverlay extends StatelessWidget {
Widget build(BuildContext context) {
assert(debugCheckHasFluentTheme(context));
final theme = FluentTheme.of(context);
final overlayHeight =
(kNumberBoxOverlayHeight + theme.visualDensity.baseSizeAdjustment.dy)
.clamp(0.0, double.infinity);
final overlayHeight = clampDouble(
kNumberBoxOverlayHeight + theme.visualDensity.baseSizeAdjustment.dy,
0,
double.infinity,
);

return Padding(
padding: const EdgeInsetsDirectional.only(start: 10),
Expand Down
3 changes: 2 additions & 1 deletion lib/src/controls/form/selection_controls.dart
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,8 @@ class _WindowsTextSelectionControlsToolbarState

assert(debugCheckHasMediaQuery(context));
final midpointAnchor = Offset(
(widget.selectionMidpoint.dx - widget.globalEditableRegion.left).clamp(
clampDouble(
widget.selectionMidpoint.dx - widget.globalEditableRegion.left,
MediaQuery.paddingOf(context).left,
MediaQuery.widthOf(context) - MediaQuery.paddingOf(context).right,
),
Expand Down
8 changes: 5 additions & 3 deletions lib/src/controls/form/text_box.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1609,9 +1609,11 @@ class _TextBoxState extends State<TextBox>
child: Container(
foregroundDecoration: foregroundDecoration,
constraints: BoxConstraints(
minHeight:
(32 + themeData.visualDensity.baseSizeAdjustment.dy)
.clamp(0.0, double.infinity),
minHeight: clampDouble(
32 + themeData.visualDensity.baseSizeAdjustment.dy,
0,
double.infinity,
),
),
child: _selectionGestureDetectorBuilder
.buildGestureDetector(
Expand Down
19 changes: 10 additions & 9 deletions lib/src/controls/inputs/rating.dart
Original file line number Diff line number Diff line change
Expand Up @@ -211,14 +211,14 @@ class _RatingControlState extends State<RatingControl> {
void increase() {
if (widget.rating == widget.amount) return;
widget.onChanged?.call(
(widget.rating + 1).clamp(0, widget.amount).toDouble(),
clampDouble(widget.rating + 1, 0, widget.amount.toDouble()),
);
}

void decrease() {
if (widget.rating == 0) return;
widget.onChanged?.call(
(widget.rating - 1).clamp(0, widget.amount).toDouble(),
clampDouble(widget.rating - 1, 0, widget.amount.toDouble()),
);
}

Expand Down Expand Up @@ -253,19 +253,20 @@ class _RatingControlState extends State<RatingControl> {
/// downstream calculations can assume left-to-right ordering.
double _adjustX(double x) {
if (Directionality.of(context) == TextDirection.rtl) {
return (_totalWidth - x).clamp(0.0, _totalWidth);
return clampDouble(_totalWidth - x, 0, _totalWidth);
}
return x;
}

void _handleUpdate(double x) {
final totalPerStar = widget.iconSize + widget.starSpacing;
final raw = (_adjustX(x) / totalPerStar).clamp(
0.0,
final raw = clampDouble(
_adjustX(x) / totalPerStar,
0,
widget.amount.toDouble(),
);
final snapped = raw.ceil().clamp(0, widget.amount).toDouble();
widget.onChanged?.call(snapped);
final snapped = raw.ceil().clamp(0, widget.amount);
widget.onChanged?.call(snapped.toDouble());
}

void _handleHoverUpdate(double x) {
Expand Down Expand Up @@ -334,7 +335,7 @@ class _RatingControlState extends State<RatingControl> {
final double r;

if (!isEnabled) {
r = (value - index).clamp(0.0, 1.0);
r = clampDouble(value - index, 0, 1);
starRatedColor =
widget.ratedIconColor ??
resources.textFillColorDisabled;
Expand Down Expand Up @@ -363,7 +364,7 @@ class _RatingControlState extends State<RatingControl> {
}
} else {
// Normal (non-hover) state
r = (value - index).clamp(0.0, 1.0);
r = clampDouble(value - index, 0, 1);
starRatedColor =
widget.ratedIconColor ??
accentColor; // SelectedForeground
Expand Down
2 changes: 1 addition & 1 deletion lib/src/controls/inputs/toggle_switch.dart
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ class _ToggleSwitchState extends State<ToggleSwitch> {
) {
setState(() {
_alignment = Alignment(
(localPosition.dx / sliderGestureWidth).clamp(-1, 1),
clampDouble(localPosition.dx / sliderGestureWidth, -1, 1),
0,
);
});
Expand Down
Loading
Loading