Skip to content

Commit 30a44c7

Browse files
committed
[skip ci] Add support for CSS gap
1 parent ba99bd0 commit 30a44c7

File tree

4 files changed

+84
-36
lines changed

4 files changed

+84
-36
lines changed

packages/core/lib/src/core_widget_factory.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ class WidgetFactory extends WidgetFactoryResetter with AnchorWidgetFactory {
229229
CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
230230
required Axis direction,
231231
MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
232+
double spacing = 0.0,
232233
TextBaseline textBaseline = TextBaseline.alphabetic,
233234
TextDirection textDirection = TextDirection.ltr,
234235
}) {
@@ -238,6 +239,7 @@ class WidgetFactory extends WidgetFactoryResetter with AnchorWidgetFactory {
238239
crossAxisAlignment: crossAxisAlignment,
239240
direction: direction,
240241
mainAxisAlignment: mainAxisAlignment,
242+
spacing: spacing,
241243
textBaseline: textBaseline,
242244
textDirection: textDirection,
243245
children: children,

packages/core/lib/src/internal/ops/style_display_flex.dart

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,25 @@
11
part of '../core_ops.dart';
22

3+
const kCssAlignItems = 'align-items';
4+
const kCssAlignItemsFlexStart = 'flex-start';
5+
const kCssAlignItemsFlexEnd = 'flex-end';
6+
const kCssAlignItemsCenter = 'center';
7+
const kCssAlignItemsBaseline = 'baseline';
8+
const kCssAlignItemsStretch = 'stretch';
9+
310
const kCssFlexDirection = 'flex-direction';
411
const kCssFlexDirectionColumn = 'column';
512
const kCssFlexDirectionRow = 'row';
13+
14+
const kCssGap = 'gap';
15+
616
const kCssJustifyContent = 'justify-content';
717
const kCssJustifyContentFlexStart = 'flex-start';
818
const kCssJustifyContentFlexEnd = 'flex-end';
919
const kCssJustifyContentCenter = 'center';
1020
const kCssJustifyContentSpaceBetween = 'space-between';
1121
const kCssJustifyContentSpaceAround = 'space-around';
1222
const kCssJustifyContentSpaceEvenly = 'space-evenly';
13-
const kCssAlignItems = 'align-items';
14-
const kCssAlignItemsFlexStart = 'flex-start';
15-
const kCssAlignItemsFlexEnd = 'flex-end';
16-
const kCssAlignItemsCenter = 'center';
17-
const kCssAlignItemsBaseline = 'baseline';
18-
const kCssAlignItemsStretch = 'stretch';
1923

2024
class StyleDisplayFlex {
2125
final WidgetFactory wf;
@@ -30,21 +34,24 @@ class StyleDisplayFlex {
3034
return null;
3135
}
3236

37+
String alignItems = kCssAlignItemsFlexStart;
3338
String flexDirection = kCssFlexDirectionRow;
39+
CssLength? gap;
3440
String justifyContent = kCssJustifyContentFlexStart;
35-
String alignItems = kCssAlignItemsFlexStart;
3641

3742
for (final element in tree.element.styles) {
3843
final String? value = element.term;
3944

4045
if (value != null) {
4146
switch (element.property) {
47+
case kCssAlignItems:
48+
alignItems = value;
4249
case kCssFlexDirection:
4350
flexDirection = value;
51+
case kCssGap:
52+
gap = tryParseCssLength(element.value);
4453
case kCssJustifyContent:
4554
justifyContent = value;
46-
case kCssAlignItems:
47-
alignItems = value;
4855
}
4956
}
5057
}
@@ -65,6 +72,7 @@ class StyleDisplayFlex {
6572
? Axis.horizontal
6673
: Axis.vertical,
6774
mainAxisAlignment: _toMainAxisAlignment(justifyContent),
75+
spacing: gap?.getValue(resolved) ?? 0.0,
6876
textDirection: resolved.directionOrLtr,
6977
);
7078
},

packages/core/test/_.dart

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -778,20 +778,27 @@ class Explainer {
778778
attr.add(
779779
// TODO: remove ignore when our minimum core version >= 1.0
780780
// ignore: avoid_dynamic_calls
781-
'direction=${dynamicWidget.direction}'.replaceAll('Axis.', ''),
781+
'crossAxisAlignment=${dynamicWidget.crossAxisAlignment}'
782+
.replaceAll('CrossAxisAlignment.', ''),
782783
);
783784
attr.add(
784785
// TODO: remove ignore when our minimum core version >= 1.0
785786
// ignore: avoid_dynamic_calls
786-
'mainAxisAlignment=${dynamicWidget.mainAxisAlignment}'
787-
.replaceAll('MainAxisAlignment.', ''),
787+
'direction=${dynamicWidget.direction}'.replaceAll('Axis.', ''),
788788
);
789789
attr.add(
790790
// TODO: remove ignore when our minimum core version >= 1.0
791791
// ignore: avoid_dynamic_calls
792-
'crossAxisAlignment=${dynamicWidget.crossAxisAlignment}'
793-
.replaceAll('CrossAxisAlignment.', ''),
792+
'mainAxisAlignment=${dynamicWidget.mainAxisAlignment}'
793+
.replaceAll('MainAxisAlignment.', ''),
794794
);
795+
796+
// TODO: remove ignore when our minimum core version >= 1.0
797+
// ignore: avoid_dynamic_calls
798+
final spacing = dynamicWidget.spacing as double;
799+
if (spacing != 0.0) {
800+
attr.add('spacing=$spacing');
801+
}
795802
}
796803
}
797804

packages/core/test/style_display_flex_test.dart

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ Future<void> main() async {
1818
expect(
1919
explained,
2020
equals(
21-
'[HtmlFlex:direction=horizontal,mainAxisAlignment=start,'
22-
'crossAxisAlignment=start,children=[RichText:(:Foo)]]',
21+
'[HtmlFlex:crossAxisAlignment=start,direction=horizontal,'
22+
'mainAxisAlignment=start,children=[RichText:(:Foo)]]',
2323
),
2424
);
2525
});
@@ -31,7 +31,7 @@ Future<void> main() async {
3131
expect(
3232
explained,
3333
equals(
34-
'[HtmlFlex:direction=horizontal,mainAxisAlignment=start,crossAxisAlignment=start,children='
34+
'[HtmlFlex:crossAxisAlignment=start,direction=horizontal,mainAxisAlignment=start,children='
3535
'[CssBlock:child=[RichText:(:Foo)]],'
3636
'[CssBlock:child=[RichText:(:Bar)]]'
3737
']',
@@ -46,7 +46,7 @@ Future<void> main() async {
4646
expect(
4747
explained,
4848
equals(
49-
'[HtmlFlex:direction=horizontal,mainAxisAlignment=start,crossAxisAlignment=start,children='
49+
'[HtmlFlex:crossAxisAlignment=start,direction=horizontal,mainAxisAlignment=start,children='
5050
'[CssBlock:child=[RichText:(:Foo)]],'
5151
'[CssBlock:child=[RichText:(:Bar)]]'
5252
']',
@@ -194,6 +194,27 @@ Future<void> main() async {
194194
expect(barRightAfter, equals(tester.windowWidth));
195195
});
196196

197+
testWidgets('updates spacing', (WidgetTester tester) async {
198+
await explain(
199+
tester,
200+
'<div style="display: flex; gap: 10px">'
201+
'<div>Foo</div><div>Bar</div>'
202+
'</div>',
203+
);
204+
final barBefore = tester.bar;
205+
final barLeftBefore = barBefore.left;
206+
207+
await explain(
208+
tester,
209+
'<div style="display: flex; gap: 20px">'
210+
'<div>Foo</div><div>Bar</div>'
211+
'</div>',
212+
);
213+
final barAfter = tester.bar;
214+
final barLeftAfter = barAfter.left;
215+
expect(barLeftAfter, greaterThan(barLeftBefore));
216+
});
217+
197218
testWidgets('updates textDirection', (WidgetTester tester) async {
198219
await explain(
199220
tester,
@@ -445,6 +466,8 @@ Future<void> main() async {
445466
kCssAlignItemsStretch,
446467
];
447468

469+
const List<double?> gaps = [null, 10];
470+
448471
const justifyContents = [
449472
kCssJustifyContentFlexStart,
450473
kCssJustifyContentFlexEnd,
@@ -457,24 +480,28 @@ Future<void> main() async {
457480
for (final flexDirection in flexDirections) {
458481
for (final alignItem in alignItems) {
459482
for (final justifyContent in justifyContents) {
460-
final key = '$flexDirection/$alignItem/$justifyContent';
461-
testGoldens(
462-
key,
463-
(tester) async {
464-
await tester.pumpWidgetBuilder(
465-
_Golden(
466-
flexDirection: flexDirection,
467-
alignItem: alignItem,
468-
justifyContent: justifyContent,
469-
),
470-
wrapper: materialAppWrapper(theme: ThemeData.light()),
471-
surfaceSize: const Size(316, 166),
472-
);
473-
474-
await screenMatchesGolden(tester, key);
475-
},
476-
skip: goldenSkip != null,
477-
);
483+
for (final gap in gaps) {
484+
final key =
485+
'$flexDirection/$alignItem/${gap != null ? 'gap-${gap}px' : ''}$justifyContent';
486+
testGoldens(
487+
key,
488+
(tester) async {
489+
await tester.pumpWidgetBuilder(
490+
_Golden(
491+
flexDirection: flexDirection,
492+
alignItem: alignItem,
493+
gap: gap,
494+
justifyContent: justifyContent,
495+
),
496+
wrapper: materialAppWrapper(theme: ThemeData.light()),
497+
surfaceSize: const Size(316, 166),
498+
);
499+
500+
await screenMatchesGolden(tester, key);
501+
},
502+
skip: goldenSkip != null,
503+
);
504+
}
478505
}
479506
}
480507
}
@@ -497,11 +524,13 @@ extension on WidgetTester {
497524
class _Golden extends StatelessWidget {
498525
final String flexDirection;
499526
final String alignItem;
527+
final double? gap;
500528
final String justifyContent;
501529

502530
const _Golden({
503531
required this.flexDirection,
504532
required this.alignItem,
533+
this.gap,
505534
required this.justifyContent,
506535
});
507536

@@ -510,6 +539,7 @@ class _Golden extends StatelessWidget {
510539
final inlineStyle = '$kCssDisplay: $kCssDisplayFlex; '
511540
'$kCssFlexDirection: $flexDirection; '
512541
'$kCssAlignItems: $alignItem; '
542+
'${gap != null ? '$kCssGap: ${gap}px' : ''}'
513543
'$kCssJustifyContent: $justifyContent';
514544
return Scaffold(
515545
body: Padding(
@@ -518,6 +548,7 @@ class _Golden extends StatelessWidget {
518548
<div style="background: lightgray; height: 150px; width: 300px; $inlineStyle">
519549
<div style="background: red; padding: 5px">$flexDirection</div>
520550
<div style="background: green; margin-top: 5px; padding: 5px">$alignItem</div><!-- added margin to verify baseline alignment -->
551+
${gap != null ? '<div style="padding: 5px">gap-${gap}px</div>' : ''}
521552
<div style="background: blue; color: white; padding: 5px">$justifyContent</div>
522553
</div>'''),
523554
),

0 commit comments

Comments
 (0)