Skip to content

Commit c0f8712

Browse files
authored
Merge pull request #11 from jozzdart/dev
v1.0.4
2 parents 5921ca0 + d21c3e9 commit c0f8712

File tree

11 files changed

+955
-118
lines changed

11 files changed

+955
-118
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 1.0.4
2+
3+
- Fixed `SizedBox` extensions to accept `int` values
4+
- Now you can create gaps with `int` values (e.g. `10.gapRow` or `10.gapColumn`)
5+
16
## 1.0.3
27

38
Added detailed tests for all extensions and fixed all issues found

example/pubspec.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ packages:
4747
path: ".."
4848
relative: true
4949
source: path
50-
version: "1.0.2"
50+
version: "1.0.4"
5151
fake_async:
5252
dependency: transitive
5353
description:

lib/src/widget/containers/sized_box_double.dart renamed to lib/src/widget/containers/sized_box_num.dart

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,85 @@ extension SizedBoxDoubleExtension on double {
175175
/// ```
176176
SizedBox get gapRow => sizedWidth;
177177
}
178+
179+
/// Extension methods for [int] that provide convenient spacing and sizing functionality.
180+
///
181+
/// This extension adds methods to easily convert integer values into [SizedBox] widgets
182+
/// for creating spacing and gaps in layouts. All methods return [SizedBox] widgets
183+
/// with the int value used as either width or height.
184+
///
185+
/// The extension provides semantic methods for different spacing contexts:
186+
/// - Width/height sizing: sizedWidth, sizedHeight
187+
/// - Gap creation: gapHorizontal, gapVertical
188+
/// - Layout-specific gaps: gapColumn, gapRow
189+
///
190+
/// Example usage:
191+
/// ```dart
192+
/// Column(
193+
/// children: [
194+
/// Text('First item'),
195+
/// 16.gapVertical, // 16px vertical gap
196+
/// Text('Second item'),
197+
/// 8.gapColumn, // 8px gap in column
198+
/// ],
199+
/// );
200+
/// ```
201+
extension SizedBoxIntExtension on int {
202+
/// Creates a [SizedBox] with this value as the width.
203+
///
204+
/// Returns a [SizedBox] that has the specified width and no height constraint.
205+
///
206+
/// Example:
207+
/// ```dart
208+
/// Row(
209+
/// children: [
210+
/// Text('Left'),
211+
/// 20.sizedWidth, // 20px wide spacer
212+
/// Text('Right'),
213+
/// ],
214+
/// );
215+
/// ```
216+
SizedBox get sizedWidth => SizedBox(width: toDouble());
217+
218+
/// Creates a [SizedBox] with this value as the height.
219+
///
220+
/// Returns a [SizedBox] that has the specified height and no width constraint.
221+
///
222+
/// Example:
223+
/// ```dart
224+
/// Column(
225+
/// children: [
226+
/// Text('Top'),
227+
/// 24.sizedHeight, // 24px tall spacer
228+
/// Text('Bottom'),
229+
/// ],
230+
/// );
231+
/// ```
232+
SizedBox get sizedHeight => SizedBox(height: toDouble());
233+
234+
/// Creates a horizontal gap (spacer) with this value as the width.
235+
///
236+
/// Alias for [sizedWidth].
237+
SizedBox get gapHorizontal => sizedWidth;
238+
239+
/// Creates a vertical gap (spacer) with this value as the height.
240+
///
241+
/// Alias for [sizedHeight].
242+
SizedBox get gapVertical => sizedHeight;
243+
244+
/// Creates a vertical gap specifically for use in columns.
245+
///
246+
/// Alias for [sizedHeight].
247+
SizedBox get gapHeight => sizedHeight;
248+
249+
/// Creates a horizontal gap specifically for use in rows.
250+
///
251+
/// Alias for [sizedWidth].
252+
SizedBox get gapWidth => sizedWidth;
253+
254+
/// Alias for [gapHeight], useful for semantic clarity in [Column] layouts.
255+
SizedBox get gapColumn => sizedHeight;
256+
257+
/// Alias for [gapWidth], useful for semantic clarity in [Row] layouts.
258+
SizedBox get gapRow => sizedWidth;
259+
}

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: exui
22
description: "Build your UI faster. No boilerplate, no dependencies. Just powerful widget extensions."
3-
version: 1.0.3
3+
version: 1.0.4
44
homepage: https://github.com/jozzdart/exui
55
repository: https://github.com/jozzdart/exui
66
issue_tracker: https://github.com/jozzdart/exui/issues

test/cupertino/button_test.dart

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import 'package:exui/src/cupertino.dart';
2+
import 'package:flutter/cupertino.dart';
3+
import 'package:flutter_test/flutter_test.dart';
4+
5+
extension CupertinoButtonWidgetExtensionsTest on Widget {
6+
CupertinoButton getButtonFromCupertinoButton({
7+
required void Function()? onPressed,
8+
}) =>
9+
cupertinoButton(onPressed: onPressed);
10+
11+
CupertinoButton getButtonFromFilledButton({
12+
required void Function()? onPressed,
13+
}) =>
14+
cupertinoFilledButton(onPressed: onPressed);
15+
16+
CupertinoButton getButtonFromTintedButton({
17+
required void Function()? onPressed,
18+
}) =>
19+
cupertinoTintedButton(onPressed: onPressed);
20+
}
21+
22+
void main() {
23+
testWidgets(
24+
'cupertinoButton creates CupertinoButton with correct child and onPressed',
25+
(tester) async {
26+
bool pressed = false;
27+
final widget = Text('Tap me').cupertinoButton(
28+
onPressed: () => pressed = true,
29+
);
30+
31+
await tester.pumpWidget(CupertinoApp(home: widget));
32+
33+
expect(find.text('Tap me'), findsOneWidget);
34+
await tester.tap(find.byType(CupertinoButton));
35+
expect(pressed, true);
36+
});
37+
38+
testWidgets('cupertinoFilledButton creates filled button with correct child',
39+
(tester) async {
40+
bool called = false;
41+
final widget = Text('Submit').cupertinoFilledButton(
42+
onPressed: () => called = true,
43+
);
44+
45+
await tester.pumpWidget(CupertinoApp(home: widget));
46+
expect(find.text('Submit'), findsOneWidget);
47+
await tester.tap(find.byType(CupertinoButton));
48+
expect(called, true);
49+
});
50+
51+
testWidgets('cupertinoTintedButton uses tint color correctly',
52+
(tester) async {
53+
final color = CupertinoColors.systemPink;
54+
final widget = Text('Share').cupertinoTintedButton(
55+
color: color,
56+
onPressed: () {},
57+
);
58+
59+
await tester.pumpWidget(CupertinoApp(home: widget));
60+
final btn = tester.widget<CupertinoButton>(find.byType(CupertinoButton));
61+
expect(btn.color, color);
62+
});
63+
64+
testWidgets('disabled button does not trigger onPressed', (tester) async {
65+
bool pressed = false;
66+
final widget = Text('Disabled').cupertinoButton(
67+
onPressed: null,
68+
);
69+
70+
await tester.pumpWidget(CupertinoApp(home: widget));
71+
await tester.tap(find.byType(CupertinoButton));
72+
expect(pressed, false); // No change
73+
});
74+
75+
testWidgets('cupertinoButton applies borderRadius and alignment',
76+
(tester) async {
77+
const radius = BorderRadius.all(Radius.circular(12));
78+
const align = Alignment.bottomRight;
79+
80+
final button = Text('Align').cupertinoButton(
81+
borderRadius: radius,
82+
alignment: align,
83+
onPressed: () {},
84+
);
85+
86+
expect(button.borderRadius, radius);
87+
expect(button.alignment, align);
88+
});
89+
90+
testWidgets('cupertinoFilledButton applies sizeStyle and pressedOpacity',
91+
(tester) async {
92+
final button = Text('Press').cupertinoFilledButton(
93+
sizeStyle: CupertinoButtonSize.small,
94+
pressedOpacity: 0.2,
95+
onPressed: () {},
96+
);
97+
98+
expect(button.sizeStyle, CupertinoButtonSize.small);
99+
expect(button.pressedOpacity, 0.2);
100+
});
101+
102+
testWidgets('cupertinoTintedButton applies disabledColor and autofocus',
103+
(tester) async {
104+
final button = Text('Auto').cupertinoTintedButton(
105+
disabledColor: CupertinoColors.systemGrey,
106+
autofocus: true,
107+
onPressed: () {},
108+
);
109+
110+
expect(button.disabledColor, CupertinoColors.systemGrey);
111+
expect(button.autofocus, true);
112+
});
113+
114+
testWidgets('cupertinoButton handles focusColor and focusNode',
115+
(tester) async {
116+
final node = FocusNode();
117+
final button = Text('Focus').cupertinoButton(
118+
focusColor: CupertinoColors.activeBlue,
119+
focusNode: node,
120+
onPressed: () {},
121+
);
122+
123+
expect(button.focusNode, node);
124+
expect(button.focusColor, CupertinoColors.activeBlue);
125+
});
126+
127+
testWidgets('cupertinoButton calls onLongPress', (tester) async {
128+
bool longPressed = false;
129+
final widget = Text('Long Press').cupertinoButton(
130+
onPressed: () {},
131+
onLongPress: () => longPressed = true,
132+
);
133+
134+
await tester.pumpWidget(CupertinoApp(home: widget));
135+
await tester.longPress(find.byType(CupertinoButton));
136+
expect(longPressed, true);
137+
});
138+
}

test/cupertino/colored_box_test.dart

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import 'package:exui/cupertino.dart';
2+
import 'package:flutter/cupertino.dart';
3+
import 'package:flutter_test/flutter_test.dart';
4+
5+
void main() {
6+
testWidgets('CupertinoBoxColorsExtension applies correct colors',
7+
(tester) async {
8+
final widget = const Text('test');
9+
10+
await tester.pumpWidget(
11+
Directionality(
12+
textDirection: TextDirection.ltr,
13+
child: Column(
14+
children: [
15+
widget.redBox(),
16+
widget.destructiveRedBox(),
17+
widget.greenBox(),
18+
widget.activeGreenBox(),
19+
widget.blueBox(),
20+
widget.activeBlueBox(),
21+
widget.yellowBox(),
22+
widget.orangeBox(),
23+
widget.orangeAccentBox(),
24+
widget.purpleBox(),
25+
widget.pinkBox(),
26+
widget.brownBox(),
27+
widget.tealBox(),
28+
widget.cyanBox(),
29+
widget.greyBox(),
30+
widget.blackBox(),
31+
widget.whiteBox(),
32+
widget.darkGrayBox(),
33+
widget.lightGrayBox(),
34+
],
35+
),
36+
),
37+
);
38+
39+
final colors = [
40+
CupertinoColors.systemRed,
41+
CupertinoColors.destructiveRed,
42+
CupertinoColors.systemGreen,
43+
CupertinoColors.activeGreen,
44+
CupertinoColors.systemBlue,
45+
CupertinoColors.activeBlue,
46+
CupertinoColors.systemYellow,
47+
CupertinoColors.systemOrange,
48+
CupertinoColors.activeOrange,
49+
CupertinoColors.systemPurple,
50+
CupertinoColors.systemPink,
51+
CupertinoColors.systemBrown,
52+
CupertinoColors.systemTeal,
53+
CupertinoColors.systemCyan,
54+
CupertinoColors.systemGrey,
55+
CupertinoColors.black,
56+
CupertinoColors.white,
57+
CupertinoColors.darkBackgroundGray,
58+
CupertinoColors.lightBackgroundGray,
59+
];
60+
61+
final coloredBoxes = find.byType(ColoredBox);
62+
expect(coloredBoxes, findsNWidgets(colors.length));
63+
64+
for (int i = 0; i < colors.length; i++) {
65+
final box = tester.widget<ColoredBox>(coloredBoxes.at(i));
66+
expect(box.color, equals(colors[i]));
67+
expect(box.child, isA<Text>());
68+
expect((box.child as Text).data, equals('test'));
69+
}
70+
});
71+
}

0 commit comments

Comments
 (0)