Skip to content

Commit

Permalink
Expose FCalendar.raw(...)
Browse files Browse the repository at this point in the history
  • Loading branch information
Pante committed Jul 13, 2024
1 parent 6cf0549 commit c0dbbdf
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 100 deletions.
21 changes: 6 additions & 15 deletions forui/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'package:flutter/material.dart';

import 'package:forui/forui.dart';

import 'package:sugar/sugar.dart';

void main() {
runApp(const Application());
Expand Down Expand Up @@ -43,22 +42,14 @@ class Application extends StatelessWidget {
}

class Testing extends StatelessWidget {

static final _selected = { LocalDate(2024, 7, 16), LocalDate(2024, 7, 17), LocalDate(2024, 7, 18), LocalDate(2024, 7, 29)};
static final _selected = {DateTime(2024, 7, 16), DateTime(2024, 7, 17), DateTime(2024, 7, 18), DateTime(2024, 7, 29)};

const Testing({super.key});

@override
Widget build(BuildContext context) => Calendar(
style: FCalendarStyle.inherit(colorScheme: context.theme.colorScheme, typography: context.theme.typography, style: context.theme.style),
start: LocalDate(1900, 1, 8),
end: LocalDate(2024, 7, 10),
current: LocalDate.now(),
initialMonth: LocalDate(2023, 7),
enabled: (_) => true,
selected: _selected.contains,
date: print,
onPress: print,
onLongPress: print,
);
Widget build(BuildContext context) => FCalendar.raw(
start: DateTime(1900, 1, 8),
end: DateTime(2024, 7, 10),
selected: _selected.contains,
);
}
10 changes: 10 additions & 0 deletions forui/lib/src/theme/theme_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ final class FThemeData with Diagnosticable {
/// The button styles.
final FButtonStyles buttonStyles;

/// The calendar style.
final FCalendarStyle calendarStyle;

/// The card style.
final FCardStyle cardStyle;

Expand Down Expand Up @@ -71,6 +74,7 @@ final class FThemeData with Diagnosticable {
required this.colorScheme,
required this.badgeStyles,
required this.buttonStyles,
required this.calendarStyle,
required this.cardStyle,
required this.checkboxStyle,
required this.dialogStyle,
Expand Down Expand Up @@ -99,6 +103,7 @@ final class FThemeData with Diagnosticable {
style: style,
badgeStyles: FBadgeStyles.inherit(colorScheme: colorScheme, typography: typography, style: style),
buttonStyles: FButtonStyles.inherit(colorScheme: colorScheme, typography: typography, style: style),
calendarStyle: FCalendarStyle.inherit(colorScheme: colorScheme, typography: typography, style: style),
cardStyle: FCardStyle.inherit(colorScheme: colorScheme, typography: typography, style: style),
checkboxStyle: FCheckboxStyle.inherit(colorScheme: colorScheme),
dialogStyle: FDialogStyle.inherit(colorScheme: colorScheme, typography: typography, style: style),
Expand Down Expand Up @@ -135,6 +140,7 @@ final class FThemeData with Diagnosticable {
FStyle? style,
FBadgeStyles? badgeStyles,
FButtonStyles? buttonStyles,
FCalendarStyle? calendarStyle,
FCardStyle? cardStyle,
FCheckboxStyle? checkboxStyle,
FDialogStyle? dialogStyle,
Expand All @@ -152,6 +158,7 @@ final class FThemeData with Diagnosticable {
style: style ?? this.style,
badgeStyles: badgeStyles ?? this.badgeStyles,
buttonStyles: buttonStyles ?? this.buttonStyles,
calendarStyle: calendarStyle ?? this.calendarStyle,
cardStyle: cardStyle ?? this.cardStyle,
checkboxStyle: checkboxStyle ?? this.checkboxStyle,
dialogStyle: dialogStyle ?? this.dialogStyle,
Expand All @@ -173,6 +180,7 @@ final class FThemeData with Diagnosticable {
..add(DiagnosticsProperty('style', style, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('badgeStyles', badgeStyles, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('buttonStyles', buttonStyles, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('calendarStyle', calendarStyle, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('cardStyle', cardStyle, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('checkboxStyle', checkboxStyle, level: DiagnosticLevel.debug))
..add(DiagnosticsProperty('dialogStyle', dialogStyle, level: DiagnosticLevel.debug))
Expand All @@ -195,6 +203,7 @@ final class FThemeData with Diagnosticable {
style == other.style &&
badgeStyles == other.badgeStyles &&
buttonStyles == other.buttonStyles &&
calendarStyle == other.calendarStyle &&
cardStyle == other.cardStyle &&
checkboxStyle == other.checkboxStyle &&
dialogStyle == other.dialogStyle &&
Expand All @@ -213,6 +222,7 @@ final class FThemeData with Diagnosticable {
style.hashCode ^
badgeStyles.hashCode ^
buttonStyles.hashCode ^
calendarStyle.hashCode ^
cardStyle.hashCode ^
checkboxStyle.hashCode ^
dialogStyle.hashCode ^
Expand Down
199 changes: 118 additions & 81 deletions forui/lib/src/widgets/calendar/calendar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,97 +7,134 @@ import 'package:forui/src/widgets/calendar/shared/header.dart';
import 'package:forui/src/widgets/calendar/year_month_picker.dart';
import 'package:sugar/sugar.dart';

export 'day/day_picker.dart' show FCalendarDayPickerStyle, FCalendarDayStyle;
export 'shared/entry.dart' show FCalendarEntryStyle;
export 'shared/header.dart' show FCalendarHeaderStyle, FCalendarPickerType;
export 'year_month_picker.dart' show FCalendarYearMonthPickerStyle;

/// A calendar.
///
/// See:
/// * https://forui.dev/docs/calendar for working examples.
/// * [FCalendarDayStyle] for customizing a card's appearance.
class FCalendar extends StatelessWidget {
static bool _true(DateTime _) => true;

@override
Widget build(BuildContext context) {
// TODO: implement build
throw UnimplementedError();
}
/// The style. Defaults to [FThemeData.calendarStyle].
final FCalendarStyle? style;

}
/// The start date. It is truncated to the nearest date.
///
/// ## Contract:
/// Throws an [AssertionError] if [end] <= [start]
final DateTime start;

/// The end date. It is truncated to the nearest date.
///
/// ## Contract:
/// Throws an [AssertionError] if [end] <= [start]
final DateTime end;

/// The current date. It is truncated to the nearest date. Defaults to the [DateTime.now].
final DateTime today;

/// A predicate that determines if a date can be selected. It may be called more than once for a single date.
///
/// Defaults to returning true for all dates.
final Predicate<DateTime> enabled;

class _Calendar extends StatelessWidget {
final FCalendarStyle style;
final LocalDate start;
final LocalDate end;
final LocalDate today;
final ValueNotifier<FCalendarPickerType> type;
final ValueNotifier<LocalDate> month;
final Predicate<LocalDate> enabled;
final Predicate<LocalDate> selected;
final ValueChanged<LocalDate> onMonthChange;
final ValueChanged<LocalDate> onPress;
final ValueChanged<LocalDate> onLongPress;

const _Calendar({
required this.style,
/// A predicate that determines if a date is selected. It may be called more than once for a single date.
final Predicate<DateTime> selected;

/// A callback for when the displayed month changes.
final ValueChanged<DateTime>? onMonthChange;

/// A callback for when a date in a [FCalendarPickerType.day] picker is pressed.
final ValueChanged<DateTime>? onPress;

/// A callback for when a date in a [FCalendarPickerType.day] picker is long pressed.
final ValueChanged<DateTime>? onLongPress;
final ValueNotifier<FCalendarPickerType> _type;
final ValueNotifier<LocalDate> _month;

/// Creates a [FCalendar] with custom date selection.
///
/// [initialDate] defaults to [today]. It is truncated to the nearest date.
FCalendar.raw({
required this.start,
required this.end,
required this.today,
required this.type,
required this.month,
required this.enabled,
required this.selected,
required this.onMonthChange,
required this.onPress,
required this.onLongPress,
});
this.style,
this.enabled = _true,
this.onMonthChange,
this.onPress,
this.onLongPress,
FCalendarPickerType initialType = FCalendarPickerType.day,
DateTime? today,
DateTime? initialDate,
super.key,
}) : assert(start.toLocalDate() < end.toLocalDate(), 'end date must be greater than start date'),
today = today ?? DateTime.now(),
_type = ValueNotifier(initialType),
_month = ValueNotifier((initialDate ?? today ?? DateTime.now()).toLocalDate().truncate(to: DateUnit.months));

@override
Widget build(BuildContext context) => DecoratedBox(
decoration: style.decoration,
child: Padding(
padding: style.padding,
child: SizedBox(
height: (DayPicker.maxRows * DayPicker.tileDimension) + Header.height + 5,
width: DateTime.daysPerWeek * DayPicker.tileDimension,
child: Stack(
alignment: Alignment.topCenter,
children: [
ValueListenableBuilder(
valueListenable: month,
builder: (context, month, child) => Header(
style: style.headerStyle,
type: type,
month: month,
),
),
ValueListenableBuilder(
valueListenable: type,
builder: (context, value, child) => switch (value) {
FCalendarPickerType.day => PagedDayPicker(
style: style,
start: start,
end: end,
today: today,
initial: month.value.truncate(to: DateUnit.months),
enabled: enabled,
selected: selected,
onMonthChange: (date) {
month.value = date;
onMonthChange(date);
},
onPress: onPress,
onLongPress: onLongPress,
),
FCalendarPickerType.yearMonth => YearMonthPicker(
style: style,
start: start,
end: end,
today: today,
onChange: (date) {
month.value = date;
type.value = FCalendarPickerType.day;
},
),
},
Widget build(BuildContext context) {
final style = this.style ?? context.theme.calendarStyle;
return DecoratedBox(
decoration: style.decoration,
child: Padding(
padding: style.padding,
child: SizedBox(
height: (DayPicker.maxRows * DayPicker.tileDimension) + Header.height + 5,
width: DateTime.daysPerWeek * DayPicker.tileDimension,
child: Stack(
alignment: Alignment.topCenter,
children: [
ValueListenableBuilder(
valueListenable: _month,
builder: (context, month, child) => Header(
style: style.headerStyle,
type: _type,
month: month,
),
],
),
),
ValueListenableBuilder(
valueListenable: _type,
builder: (context, value, child) => switch (value) {
FCalendarPickerType.day => PagedDayPicker(
style: style,
start: start.toLocalDate(),
end: end.toLocalDate(),
today: today.toLocalDate(),
initial: _month.value,
enabled: (date) => enabled(date.toNative()),
selected: (date) => selected(date.toNative()),
onMonthChange: (date) {
_month.value = date;
onMonthChange?.call(date.toNative());
},
onPress: (date) => onPress?.call(date.toNative()),
onLongPress: (date) => onLongPress?.call(date.toNative()),
),
FCalendarPickerType.yearMonth => YearMonthPicker(
style: style,
start: start.toLocalDate(),
end: end.toLocalDate(),
today: today.toLocalDate(),
onChange: (date) {
_month.value = date;
_type.value = FCalendarPickerType.day;
},
),
},
),
],
),
),
);
),
);
}

@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
Expand All @@ -107,8 +144,8 @@ class _Calendar extends StatelessWidget {
..add(DiagnosticsProperty('start', start))
..add(DiagnosticsProperty('end', end))
..add(DiagnosticsProperty('today', today))
..add(DiagnosticsProperty('type', type))
..add(DiagnosticsProperty('month', month))
..add(DiagnosticsProperty('type', _type))
..add(DiagnosticsProperty('month', _month))
..add(DiagnosticsProperty('enabled', enabled))
..add(DiagnosticsProperty('selected', selected))
..add(DiagnosticsProperty('onMonthChange', onMonthChange))
Expand Down
4 changes: 2 additions & 2 deletions forui/lib/src/widgets/calendar/year/year_picker.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class YearPicker extends StatefulWidget {
final LocalDate? focused;
final ValueChanged<LocalDate> onPress;

const YearPicker({
YearPicker({
required this.style,
required this.startYear,
required this.start,
Expand All @@ -28,7 +28,7 @@ class YearPicker extends StatefulWidget {
required this.focused,
required this.onPress,
super.key,
});
}): assert(startYear == startYear.truncate(to: DateUnit.years), 'startYear must be truncated to years.');

@override
State<YearPicker> createState() => _YearPickerState();
Expand Down
2 changes: 0 additions & 2 deletions forui/lib/src/widgets/calendar/year_month_picker.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:forui/forui.dart';
import 'package:forui/src/widgets/calendar/calendar.dart';
import 'package:forui/src/widgets/calendar/month/paged_month_picker.dart';
import 'package:forui/src/widgets/calendar/shared/entry.dart';
import 'package:forui/src/widgets/calendar/year/paged_year_picker.dart';
import 'package:meta/meta.dart';
import 'package:sugar/sugar.dart';
Expand Down
1 change: 1 addition & 0 deletions forui/lib/widgets.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ library forui.widgets;

export 'src/widgets/badge/badge.dart' hide Variant;
export 'src/widgets/button/button.dart' hide Variant;
export 'src/widgets/calendar/calendar.dart';
export 'src/widgets/card/card.dart';
export 'src/widgets/checkbox.dart';
export 'src/widgets/dialog/dialog.dart';
Expand Down

0 comments on commit c0dbbdf

Please sign in to comment.