Skip to content

Commit

Permalink
feat: [MDS-565] Create Carousel widget (#200)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kypsis committed Jul 7, 2023
1 parent 79badcb commit fc6534b
Show file tree
Hide file tree
Showing 11 changed files with 1,075 additions and 3 deletions.
96 changes: 96 additions & 0 deletions example/lib/src/storybook/stories/carousel.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import 'package:flutter/material.dart';
import 'package:moon_design/moon_design.dart';
import 'package:storybook_flutter/storybook_flutter.dart';

class CarouselStory extends Story {
CarouselStory()
: super(
name: "Carousel",
builder: (context) {
final itemExtentKnob = context.knobs.nullable.sliderInt(
label: "itemExtent",
description: "MoonCarousel item extent.",
enabled: false,
initial: 120,
max: MediaQuery.of(context).size.width.round(),
);

final gapKnob = context.knobs.nullable.sliderInt(
label: "gap",
description: "The gap between MoonCarousel items.",
enabled: false,
initial: 0,
max: 64,
);

final anchorKnob = context.knobs.nullable.slider(
label: "anchor",
description: "MoonCarousel anchor placement.",
enabled: false,
initial: 0,
);

final velocityFactorKnob = context.knobs.nullable.slider(
label: "velocityFactor",
description: "The velocity factor for MoonCarousel.",
enabled: false,
min: 0.1,
initial: 0.5,
);

final autoPlayKnob = context.knobs.boolean(
label: "autoPlay",
description: "Whether the MoonCarousel is auto playing.",
);

final isCenteredKnob = context.knobs.boolean(
label: "isCentered",
description: "Whether the MoonCarousel items are centered.",
initial: true,
);

final isLoopedKnob = context.knobs.boolean(
label: "loop",
description: "Whether the MoonCarousel is looped or not (infinite scroll).",
);

return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const SizedBox(height: 64),
SizedBox(
height: 120,
child: OverflowBox(
maxWidth: MediaQuery.of(context).size.width,
child: MoonCarousel(
velocityFactor: velocityFactorKnob ?? 0.5,
gap: gapKnob?.toDouble() ?? 8,
//controller: carouselController,
autoPlay: autoPlayKnob,
itemCount: 10,
itemExtent: itemExtentKnob?.toDouble() ?? 120,
isCentered: isCenteredKnob,
anchor: anchorKnob ?? 0,
loop: isLoopedKnob,
itemBuilder: (context, itemIndex, realIndex) => Container(
decoration: ShapeDecoration(
color: context.moonTheme?.colors.gohan,
shape: MoonSquircleBorder(
borderRadius: BorderRadius.circular(12).squircleBorderRadius(context),
),
),
child: Center(
child: Text(itemIndex.toString()),
),
),
),
),
),
const SizedBox(height: 64),
],
),
);
},
);
}
2 changes: 2 additions & 0 deletions example/lib/src/storybook/storybook.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:example/src/storybook/stories/authcode.dart';
import 'package:example/src/storybook/stories/avatar.dart';
import 'package:example/src/storybook/stories/bottom_sheet.dart';
import 'package:example/src/storybook/stories/button.dart';
import 'package:example/src/storybook/stories/carousel.dart';
import 'package:example/src/storybook/stories/checkbox.dart';
import 'package:example/src/storybook/stories/chip.dart';
import 'package:example/src/storybook/stories/circular_loader.dart';
Expand Down Expand Up @@ -88,6 +89,7 @@ class StorybookPage extends StatelessWidget {
AvatarStory(),
BottomSheetStory(),
ButtonStory(),
CarouselStory(),
CheckboxStory(),
ChipStory(),
CircularLoaderStory(),
Expand Down
2 changes: 2 additions & 0 deletions lib/moon_design.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export 'package:moon_design/src/theme/avatar/avatar_theme.dart';
export 'package:moon_design/src/theme/borders.dart';
export 'package:moon_design/src/theme/bottom_sheet/bottom_sheet_theme.dart';
export 'package:moon_design/src/theme/button/button_theme.dart';
export 'package:moon_design/src/theme/carousel/carousel_theme.dart';
export 'package:moon_design/src/theme/checkbox/checkbox_theme.dart';
export 'package:moon_design/src/theme/chip/chip_theme.dart';
export 'package:moon_design/src/theme/colors.dart';
Expand Down Expand Up @@ -56,6 +57,7 @@ export 'package:moon_design/src/widgets/buttons/button.dart';
export 'package:moon_design/src/widgets/buttons/filled_button.dart';
export 'package:moon_design/src/widgets/buttons/outlined_button.dart';
export 'package:moon_design/src/widgets/buttons/text_button.dart';
export 'package:moon_design/src/widgets/carousel/carousel.dart';
export 'package:moon_design/src/widgets/checkbox/checkbox.dart';
export 'package:moon_design/src/widgets/chips/chip.dart';
export 'package:moon_design/src/widgets/common/animated_icon_theme.dart';
Expand Down
59 changes: 59 additions & 0 deletions lib/src/theme/carousel/carousel_colors.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:moon_design/src/theme/icons/icon_theme.dart';
import 'package:moon_design/src/theme/typography/typography.dart';
import 'package:moon_design/src/utils/color_premul_lerp.dart';

@immutable
class MoonCarouselColors extends ThemeExtension<MoonCarouselColors> with DiagnosticableTreeMixin {
static final light = MoonCarouselColors(
textColor: MoonTypography.light.colors.bodyPrimary,
iconColor: MoonIconTheme.light.colors.primaryColor,
);

static final dark = MoonCarouselColors(
textColor: MoonTypography.dark.colors.bodyPrimary,
iconColor: MoonIconTheme.dark.colors.primaryColor,
);

/// Default text color of Carousel items.
final Color textColor;

/// Carousel item icon color.
final Color iconColor;

const MoonCarouselColors({
required this.textColor,
required this.iconColor,
});

@override
MoonCarouselColors copyWith({
Color? textColor,
Color? iconColor,
}) {
return MoonCarouselColors(
textColor: textColor ?? this.textColor,
iconColor: iconColor ?? this.iconColor,
);
}

@override
MoonCarouselColors lerp(ThemeExtension<MoonCarouselColors>? other, double t) {
if (other is! MoonCarouselColors) return this;

return MoonCarouselColors(
textColor: colorPremulLerp(textColor, other.textColor, t)!,
iconColor: colorPremulLerp(iconColor, other.iconColor, t)!,
);
}

@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(DiagnosticsProperty("type", "MoonCarouselColors"))
..add(ColorProperty("textColor", textColor))
..add(ColorProperty("iconColor", iconColor));
}
}
83 changes: 83 additions & 0 deletions lib/src/theme/carousel/carousel_properties.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import 'dart:ui';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import 'package:moon_design/src/theme/sizes.dart';
import 'package:moon_design/src/theme/typography/text_styles.dart';

@immutable
class MoonCarouselProperties extends ThemeExtension<MoonCarouselProperties> with DiagnosticableTreeMixin {
static final properties = MoonCarouselProperties(
gap: MoonSizes.sizes.x2s,
textStyle: MoonTextStyles.body.textDefault,
autoPlayDelay: const Duration(seconds: 3),
transitionDuration: const Duration(milliseconds: 800),
transitionCurve: Curves.fastOutSlowIn,
);

/// Gap between Carousel items.
final double gap;

/// Carousel item text style.
final TextStyle textStyle;

/// Carousel auto play delay between items.
final Duration autoPlayDelay;

/// Carousel transition duration.
final Duration transitionDuration;

/// Carousel transition curve.
final Curve transitionCurve;

const MoonCarouselProperties({
required this.gap,
required this.textStyle,
required this.autoPlayDelay,
required this.transitionDuration,
required this.transitionCurve,
});

@override
MoonCarouselProperties copyWith({
double? gap,
TextStyle? textStyle,
Duration? autoPlayDelay,
Duration? transitionDuration,
Curve? transitionCurve,
}) {
return MoonCarouselProperties(
gap: gap ?? this.gap,
textStyle: textStyle ?? this.textStyle,
autoPlayDelay: autoPlayDelay ?? this.autoPlayDelay,
transitionDuration: transitionDuration ?? this.transitionDuration,
transitionCurve: transitionCurve ?? this.transitionCurve,
);
}

@override
MoonCarouselProperties lerp(ThemeExtension<MoonCarouselProperties>? other, double t) {
if (other is! MoonCarouselProperties) return this;

return MoonCarouselProperties(
gap: lerpDouble(gap, other.gap, t)!,
textStyle: TextStyle.lerp(textStyle, other.textStyle, t)!,
autoPlayDelay: lerpDuration(autoPlayDelay, other.autoPlayDelay, t),
transitionDuration: lerpDuration(transitionDuration, other.transitionDuration, t),
transitionCurve: other.transitionCurve,
);
}

@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties
..add(DiagnosticsProperty("type", "MoonCarouselProperties"))
..add(DoubleProperty("gap", gap))
..add(DiagnosticsProperty<TextStyle>("textStyle", textStyle))
..add(DiagnosticsProperty<Duration>("autoPlayDelay", autoPlayDelay))
..add(DiagnosticsProperty<Duration>("transitionDuration", transitionDuration))
..add(DiagnosticsProperty<Curve>("transitionCurve", transitionCurve));
}
}
59 changes: 59 additions & 0 deletions lib/src/theme/carousel/carousel_theme.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

import 'package:moon_design/src/theme/carousel/carousel_colors.dart';
import 'package:moon_design/src/theme/carousel/carousel_properties.dart';

@immutable
class MoonCarouselTheme extends ThemeExtension<MoonCarouselTheme> with DiagnosticableTreeMixin {
static final light = MoonCarouselTheme(
colors: MoonCarouselColors.light,
properties: MoonCarouselProperties.properties,
);

static final dark = MoonCarouselTheme(
colors: MoonCarouselColors.dark,
properties: MoonCarouselProperties.properties,
);

/// Carousel colors.
final MoonCarouselColors colors;

/// Carousel properties.
final MoonCarouselProperties properties;

const MoonCarouselTheme({
required this.colors,
required this.properties,
});

@override
MoonCarouselTheme copyWith({
MoonCarouselColors? colors,
MoonCarouselProperties? properties,
}) {
return MoonCarouselTheme(
colors: colors ?? this.colors,
properties: properties ?? this.properties,
);
}

@override
MoonCarouselTheme lerp(ThemeExtension<MoonCarouselTheme>? other, double t) {
if (other is! MoonCarouselTheme) return this;

return MoonCarouselTheme(
properties: properties.lerp(other.properties, t),
colors: colors.lerp(other.colors, t),
);
}

@override
void debugFillProperties(DiagnosticPropertiesBuilder diagnosticProperties) {
super.debugFillProperties(diagnosticProperties);
diagnosticProperties
..add(DiagnosticsProperty("type", "MoonCarouselTheme"))
..add(DiagnosticsProperty<MoonCarouselColors>("colors", colors))
..add(DiagnosticsProperty<MoonCarouselProperties>("properties", properties));
}
}
2 changes: 1 addition & 1 deletion lib/src/theme/opacity.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import 'package:flutter/material.dart';

@immutable
class MoonOpacity extends ThemeExtension<MoonOpacity> with DiagnosticableTreeMixin {
static const opacities = MoonOpacity(disabled: 0.32);
static const opacities = MoonOpacity(disabled: 0.6);

/// Disabled opacity value.
final double disabled;
Expand Down
Loading

0 comments on commit fc6534b

Please sign in to comment.