diff --git a/example/assets/code_snippets/accordion.md b/example/assets/code_snippets/accordion.md new file mode 100644 index 00000000..e5bc83bd --- /dev/null +++ b/example/assets/code_snippets/accordion.md @@ -0,0 +1,61 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +enum AccordionItems { first, second } + +class Accordion extends StatefulWidget { + const Accordion({super.key}); + + @override + State createState() => _AccordionState(); +} + +class _AccordionState extends State { + AccordionItems? _currentlyOpenAccordionItem = AccordionItems.first; + + @override + Widget build(BuildContext context) { + const String contentText = + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, " + "sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, " + "quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."; + + return Column( + children: [ + MoonAccordion( + // identityValue and groupIdentityValue can be used to control the + // auto collapse behaviour of the accordion. + identityValue: AccordionItems.first, + groupIdentityValue: _currentlyOpenAccordionItem, + accordionSize: MoonAccordionSize.sm, + childrenPadding: const EdgeInsets.all(12), + onExpansionChanged: (AccordionItems? value) => setState( + () => _currentlyOpenAccordionItem = value, + ), + leading: const Icon(MoonIcons.other_frame_24_light), + title: const Text("Grouped MoonAccordion item #1"), + children: const [ + Text(contentText), + ], + ), + MoonAccordion( + // identityValue and groupIdentityValue can be used to control the + // auto collapse behaviour of the accordion. + identityValue: AccordionItems.second, + groupIdentityValue: _currentlyOpenAccordionItem, + accordionSize: MoonAccordionSize.sm, + hasContentOutside: true, + childrenPadding: const EdgeInsets.all(12), + onExpansionChanged: (AccordionItems? value) => setState( + () => _currentlyOpenAccordionItem = value, + ), + leading: const Icon(MoonIcons.other_frame_24_light), + title: const Text("Grouped MoonAccordion item #2"), + children: const [ + Text(contentText), + ], + ), + ], + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/alert.md b/example/assets/code_snippets/alert.md new file mode 100644 index 00000000..a14aaa16 --- /dev/null +++ b/example/assets/code_snippets/alert.md @@ -0,0 +1,39 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class Alert extends StatelessWidget { + const Alert({super.key}); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + MoonAlert( + show: true, + leading: const Icon(MoonIcons.other_frame_24_light), + title: const Text("Base MoonAlert"), + trailing: MoonButton.icon( + buttonSize: MoonButtonSize.xs, + onTap: () => {}, + icon: const Icon(MoonIcons.controls_close_24_light), + ), + body: const Text("Here goes MoonAlert body"), + ), + MoonFilledAlert( + show: true, + color: context.moonColors!.chichi, + onTrailingTap: () => {}, + leading: const Icon(MoonIcons.notifications_alert_24_light), + title: const Text("Filled error MoonAlert"), + ), + MoonOutlinedAlert( + show: true, + color: context.moonColors!.roshi, + onTrailingTap: () => {}, + leading: const Icon(MoonIcons.generic_check_rounded_24_light), + title: const Text("Outlined success MoonAlert"), + ), + ], + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/auth_code.md b/example/assets/code_snippets/auth_code.md new file mode 100644 index 00000000..0f9789d0 --- /dev/null +++ b/example/assets/code_snippets/auth_code.md @@ -0,0 +1,55 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class AuthCode extends StatefulWidget { + const AuthCode({super.key}); + + @override + State createState() => _AuthCodeState(); +} + +class _AuthCodeState extends State { + late StreamController _errorStreamController; + + @override + void initState() { + super.initState(); + + _errorStreamController = StreamController(); + } + + @override + void dispose() { + _errorStreamController.close(); + + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return SizedBox( + height: 95, // To avoid widget jumping with error text, use a fixed-height wrapper. + child: MoonAuthCode( + errorStreamController: _errorStreamController, + onCompleted: (String pin) { + if (pin != '123456') { + _errorStreamController.add(ErrorAnimationType.shake); + } + }, + validator: (String? pin) => pin?.length == 6 && pin != '123456' + ? 'Invalid authentication code. Please try again.' + : null, + errorBuilder: (BuildContext context, String? errorText) { + return Align( + child: Padding( + padding: const EdgeInsets.only(top: 8), + child: Text(errorText ?? ''), + ), + ); + }, + ), + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/avatar.md b/example/assets/code_snippets/avatar.md new file mode 100644 index 00000000..a94fa4dd --- /dev/null +++ b/example/assets/code_snippets/avatar.md @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class Avatar extends StatelessWidget { + const Avatar({super.key}); + + @override + Widget build(BuildContext context) { + return const MoonAvatar( + avatarSize: MoonAvatarSize.sm, + showBadge: true, + content: Text('MD'), + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/bottom_sheet.md b/example/assets/code_snippets/bottom_sheet.md new file mode 100644 index 00000000..0f327c0b --- /dev/null +++ b/example/assets/code_snippets/bottom_sheet.md @@ -0,0 +1,45 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class BottomSheet extends StatelessWidget { + const BottomSheet({super.key}); + + @override + Widget build(BuildContext context) { + Future bottomSheetBuilder(BuildContext context) { + return showMoonModalBottomSheet( + context: context, + enableDrag: true, + height: MediaQuery.of(context).size.height * 0.7, + builder: (BuildContext context) => Column( + children: [ + // Drag handle for the bottom sheet + Container( + height: 4, + width: 40, + margin: const EdgeInsets.symmetric(vertical: 8), + decoration: ShapeDecoration( + color: context.moonColors!.beerus, + shape: MoonSquircleBorder( + borderRadius: BorderRadius.circular(16).squircleBorderRadius(context), + ), + ), + ), + const Expanded( + child: Align( + child: Text('MoonBottomSheet example'), + ), + ), + ], + ), + ); + } + + return Center( + child: MoonFilledButton( + onTap: () => bottomSheetBuilder(context), + label: const Text("Tap me"), + ), + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/button.md b/example/assets/code_snippets/button.md new file mode 100644 index 00000000..b84ffa48 --- /dev/null +++ b/example/assets/code_snippets/button.md @@ -0,0 +1,47 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class Button extends StatelessWidget { + const Button({super.key}); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + MoonButton( + buttonSize: MoonButtonSize.sm, + onTap: () {}, + leading: const Icon(MoonIcons.other_frame_24_light), + label: const Text('MoonButton'), + trailing: const Icon(MoonIcons.other_frame_24_light), + ), + MoonButton.icon( + buttonSize: MoonButtonSize.sm, + onTap: () {}, + icon: const Icon(MoonIcons.other_frame_24_light), + ), + MoonFilledButton( + buttonSize: MoonButtonSize.sm, + onTap: () {}, + leading: const Icon(MoonIcons.other_frame_24_light), + label: const Text("MoonFilledButton"), + trailing: const Icon(MoonIcons.other_frame_24_light), + ), + MoonOutlinedButton( + buttonSize: MoonButtonSize.sm, + onTap: () {}, + leading: const Icon(MoonIcons.other_frame_24_light), + label: const Text("MoonOutlinedButton"), + trailing: const Icon(MoonIcons.other_frame_24_light), + ), + MoonTextButton( + buttonSize: MoonButtonSize.sm, + onTap: () {}, + leading: const Icon(MoonIcons.other_frame_24_light), + label: const Text("MoonTextButton"), + trailing: const Icon(MoonIcons.other_frame_24_light), + ), + ], + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/carousel.md b/example/assets/code_snippets/carousel.md new file mode 100644 index 00000000..c9c0378d --- /dev/null +++ b/example/assets/code_snippets/carousel.md @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class Carousel extends StatelessWidget { + const Carousel({super.key}); + + @override + Widget build(BuildContext context) { + return OverflowBox( + maxWidth: MediaQuery.of(context).size.width, + minHeight: 110, + maxHeight: 110, + child: MoonCarousel( + itemCount: 10, + itemExtent: 110, + itemBuilder: (BuildContext context, int itemIndex, int _) => Container( + decoration: ShapeDecoration( + color: context.moonColors!.goku, + shape: MoonSquircleBorder( + borderRadius: BorderRadius.circular(12).squircleBorderRadius(context), + ), + ), + child: Center( + child: Text("${itemIndex + 1}"), + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/checkbox.md b/example/assets/code_snippets/checkbox.md new file mode 100644 index 00000000..62b326b1 --- /dev/null +++ b/example/assets/code_snippets/checkbox.md @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class Checkbox extends StatefulWidget { + const Checkbox({super.key}); + + @override + State createState() => _CheckboxState(); +} + +class _CheckboxState extends State { + bool? checkboxValue = false; + bool? checkboxWithLabelValue = false; + + @override + Widget build(BuildContext context) { + return Column( + children: [ + MoonCheckbox( + value: checkboxValue, + onChanged: (bool? newValue) => setState(() => checkboxValue = newValue), + ), + MoonCheckbox.withLabel( + context, + value: checkboxWithLabelValue, + label: "MoonCheckbox with label", + onChanged: (bool? newValue) => setState(() => checkboxWithLabelValue = newValue), + ), + ], + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/chip.md b/example/assets/code_snippets/chip.md new file mode 100644 index 00000000..375c14f6 --- /dev/null +++ b/example/assets/code_snippets/chip.md @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class Chip extends StatelessWidget { + const Chip({super.key}); + + @override + Widget build(BuildContext context) { + return const Column( + children: [ + MoonChip( + chipSize: MoonChipSize.sm, + leading: Icon(MoonIcons.other_frame_24_light), + label: Text('MoonChip'), + trailing: Icon(MoonIcons.other_frame_24_light), + ), + MoonChip.text( + chipSize: MoonChipSize.sm, + leading: Icon(MoonIcons.other_frame_24_light), + label: Text('MoonChip with text'), + trailing: Icon(MoonIcons.other_frame_24_light), + ), + ], + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/circular_loader.md b/example/assets/code_snippets/circular_loader.md new file mode 100644 index 00000000..8e73b7d8 --- /dev/null +++ b/example/assets/code_snippets/circular_loader.md @@ -0,0 +1,13 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class CircularLoader extends StatelessWidget { + const CircularLoader({super.key}); + + @override + Widget build(BuildContext context) { + return const MoonCircularLoader( + circularLoaderSize: MoonCircularLoaderSize.sm, + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/circular_progress.md b/example/assets/code_snippets/circular_progress.md new file mode 100644 index 00000000..b551c12a --- /dev/null +++ b/example/assets/code_snippets/circular_progress.md @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class CircularProgress extends StatelessWidget { + const CircularProgress({super.key}); + + @override + Widget build(BuildContext context) { + return const MoonCircularProgress( + value: 0.75, + circularProgressSize: MoonCircularProgressSize.sm, + ); + } +} + diff --git a/example/assets/code_snippets/dot_indicator.md b/example/assets/code_snippets/dot_indicator.md new file mode 100644 index 00000000..6778ef34 --- /dev/null +++ b/example/assets/code_snippets/dot_indicator.md @@ -0,0 +1,14 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class DotIndicator extends StatelessWidget { + const DotIndicator({super.key}); + + @override + Widget build(BuildContext context) { + return const MoonDotIndicator( + dotCount: 4, + selectedDot: 2, + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/drawer.md b/example/assets/code_snippets/drawer.md new file mode 100644 index 00000000..1c52609e --- /dev/null +++ b/example/assets/code_snippets/drawer.md @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class Drawer extends StatelessWidget { + const Drawer({super.key}); + + @override + Widget build(BuildContext context) { + return OverflowBox( + maxHeight: MediaQuery.of(context).size.height, + maxWidth: MediaQuery.of(context).size.width, + child: Scaffold( + drawer: MoonDrawer( + width: MediaQuery.of(context).size.width * 0.4, + child: const Align( + child: Text("MoonDrawer"), + ), + ), + body: Builder( + builder: (BuildContext context) { + return Center( + child: MoonFilledButton( + label: const Text("Open drawer"), + onTap: () => Scaffold.of(context).openDrawer(), + ), + ); + }, + ), + ), + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/dropdown.md b/example/assets/code_snippets/dropdown.md new file mode 100644 index 00000000..90202254 --- /dev/null +++ b/example/assets/code_snippets/dropdown.md @@ -0,0 +1,166 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +const String _groupId = "dropdown"; + +class Dropdown extends StatefulWidget { + const Dropdown({super.key}); + + @override + State createState() => _DropdownState(); +} + +class _DropdownState extends State { + final Map _availableChoices = { + "Choice #1": false, + "Choice #2": false, + }; + + bool _showChoices = false; + bool _showMenu = false; + bool _showMenuInner = false; + Color? _buttonColor; + String _buttonName = "Piccolo"; + + @override + Widget build(BuildContext context) { + return Column( + children: [ + //Dropdown with multiple choices + MoonDropdown( + show: _showChoices, + constrainWidthToChild: true, + contentPadding: const EdgeInsets.symmetric(horizontal: 16), + onTapOutside: () => setState(() => _showChoices = false), + content: Column( + children: [ + MoonCheckbox.withLabel( + context, + value: _availableChoices["Choice #1"], + label: "Choice #1", + onChanged: (bool? isSelected) => setState( + () => _availableChoices["Choice #1"] = isSelected!, + ), + ), + MoonCheckbox.withLabel( + context, + value: _availableChoices["Choice #2"], + label: "Choice #2", + onChanged: (bool? isSelected) => setState( + () => _availableChoices["Choice #2"] = isSelected!, + ), + ), + ], + ), + child: MoonTextInput( + mouseCursor: MouseCursor.defer, + readOnly: true, + width: 250, + hintText: "Choose an option", + onTap: () => setState(() => _showChoices = !_showChoices), + leading: _availableChoices.values.any((element) => element == true) + ? Center( + child: GestureDetector( + onTap: () => setState( + () => _availableChoices.updateAll((key, value) => false), + ), + child: MoonTag( + tagSize: MoonTagSize.xs, + label: Text( + "${_availableChoices.values.where((element) => element == true).length}", + ), + trailing: const Icon(MoonIcons.controls_close_small_16_light), + ), + ), + ) + : null, + trailing: Center( + child: AnimatedRotation( + duration: const Duration(milliseconds: 200), + turns: _showChoices ? -0.5 : 0, + child: const Icon(MoonIcons.controls_chevron_down_small_16_light), + ), + ), + ), + ), + + // Dropdown as menu + MoonDropdown( + show: _showMenu, + groupId: _groupId, + constrainWidthToChild: true, + onTapOutside: () => setState(() { + _showMenu = false; + _showMenuInner = false; + }), + content: Column( + children: [ + MoonMenuItem( + onTap: () => setState(() { + _showMenu = false; + _buttonName = "Piccolo"; + _buttonColor = context.moonColors!.piccolo; + }), + title: const Text("Piccolo"), + ), + MoonDropdown( + show: _showMenuInner, + groupId: _groupId, + constrainWidthToChild: true, + followerAnchor: Alignment.topLeft, + targetAnchor: Alignment.topRight, + offset: const Offset(8, 0), + content: Column( + children: [ + MoonMenuItem( + onTap: () => setState(() { + _showMenu = false; + _showMenuInner = false; + _buttonName = "Roshi"; + _buttonColor = context.moonColors!.roshi; + }), + title: const Text("Roshi"), + ), + MoonMenuItem( + onTap: () => setState(() { + _showMenu = false; + _showMenuInner = false; + _buttonName = "Roshi60"; + _buttonColor = context.moonColors!.roshi60; + }), + title: const Text("Roshi60"), + ), + MoonMenuItem( + onTap: () => setState(() { + _showMenu = false; + _showMenuInner = false; + _buttonName = "Roshi10"; + _buttonColor = context.moonColors!.roshi10; + }), + title: const Text("Roshi10"), + ), + ], + ), + child: MoonMenuItem( + backgroundColor: _showMenuInner ? context.moonColors!.heles : null, + onTap: () => setState(() => _showMenuInner = !_showMenuInner), + title: const Text("Roshi"), + trailing: const Icon( + MoonIcons.controls_chevron_right_16_light, + size: 16, + ), + ), + ), + ], + ), + child: MoonFilledButton( + width: 120, + backgroundColor: _buttonColor, + onTap: () => setState(() => _showMenu = !_showMenu), + label: Text(_buttonName), + ), + ), + ], + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/icons.md b/example/assets/code_snippets/icons.md new file mode 100644 index 00000000..7b52ac80 --- /dev/null +++ b/example/assets/code_snippets/icons.md @@ -0,0 +1,11 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class Icons extends StatelessWidget { + const Icons({super.key}); + + @override + Widget build(BuildContext context) { + return const Icon(MoonIcons.other_frame_24_light); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/linear_loader.md b/example/assets/code_snippets/linear_loader.md new file mode 100644 index 00000000..1be8c1ee --- /dev/null +++ b/example/assets/code_snippets/linear_loader.md @@ -0,0 +1,13 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class LinearLoader extends StatelessWidget { + const LinearLoader({super.key}); + + @override + Widget build(BuildContext context) { + return const MoonLinearLoader( + linearLoaderSize: MoonLinearLoaderSize.x4s, + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/linear_progress.md b/example/assets/code_snippets/linear_progress.md new file mode 100644 index 00000000..ecc0fe63 --- /dev/null +++ b/example/assets/code_snippets/linear_progress.md @@ -0,0 +1,14 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class LinearProgress extends StatelessWidget { + const LinearProgress({super.key}); + + @override + Widget build(BuildContext context) { + return const MoonLinearProgress( + value: 0.75, + linearProgressSize: MoonLinearProgressSize.x4s, + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/menu_item.md b/example/assets/code_snippets/menu_item.md new file mode 100644 index 00000000..e62f871f --- /dev/null +++ b/example/assets/code_snippets/menu_item.md @@ -0,0 +1,21 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class MenuItem extends StatefulWidget { + const MenuItem({super.key}); + + @override + State createState() => _MenuItemState(); +} + +class _MenuItemState extends State { + @override + Widget build(BuildContext context) { + return MoonMenuItem( + onTap: () {}, + title: const Text("Menu Item"), + leading: const Icon(MoonIcons.notifications_activity_32_regular), + trailing: const Icon(MoonIcons.controls_chevron_right_24_light), + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/modal.md b/example/assets/code_snippets/modal.md new file mode 100644 index 00000000..02775df0 --- /dev/null +++ b/example/assets/code_snippets/modal.md @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class Modal extends StatelessWidget { + const Modal({super.key}); + + @override + Widget build(BuildContext context) { + Future modalBuilder(BuildContext context) { + return showMoonModal( + context: context, + builder: (BuildContext _) { + return MoonModal( + child: SizedBox( + height: 150, + width: MediaQuery.of(context).size.width - 64, + child: const Center( + child: Text("This is MoonModal."), + ), + ), + ); + }, + ); + } + + return Builder( + builder: (BuildContext context) { + return MoonFilledButton( + label: const Text("Open MoonModal"), + onTap: () => modalBuilder(context), + ); + }, + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/popover.md b/example/assets/code_snippets/popover.md new file mode 100644 index 00000000..47c8842e --- /dev/null +++ b/example/assets/code_snippets/popover.md @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class Popover extends StatefulWidget { + const Popover({super.key}); + + @override + State createState() => _PopoverState(); +} + +class _PopoverState extends State { + bool show = false; + + @override + Widget build(BuildContext context) { + return MoonPopover( + show: show, + onTapOutside: () => setState(() => show = false), + content: const Text('This is MoonPopover'), + child: MoonFilledButton( + onTap: () => setState(() => show = !show), + label: const Text("Show MoonPopover"), + ), + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/radio.md b/example/assets/code_snippets/radio.md new file mode 100644 index 00000000..d2163cc1 --- /dev/null +++ b/example/assets/code_snippets/radio.md @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +enum RadioSelection { first, second } + +class Radio extends StatefulWidget { + const Radio({super.key}); + + @override + State createState() => _RadioState(); +} + +class _RadioState extends State { + RadioSelection? radioSelection = RadioSelection.first; + + @override + Widget build(BuildContext context) { + return Column( + children: [ + MoonRadio( + value: RadioSelection.first, + groupValue: radioSelection, + onChanged: (RadioSelection? selection) => setState(() => radioSelection = selection), + ), + MoonRadio.withLabel( + context, + value: RadioSelection.second, + groupValue: radioSelection, + label: "With label", + onChanged: (RadioSelection? selection) => setState(() => radioSelection = selection), + ), + ], + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/segmented_control.md b/example/assets/code_snippets/segmented_control.md new file mode 100644 index 00000000..8eacf13f --- /dev/null +++ b/example/assets/code_snippets/segmented_control.md @@ -0,0 +1,34 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class SegmentedControl extends StatelessWidget { + const SegmentedControl({super.key}); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + MoonSegmentedControl( + segmentedControlSize: MoonSegmentedControlSize.sm, + segments: const [ + Segment( + leading: Icon(MoonIcons.other_frame_24_light), + label: Text('Tab1'), + trailing: Icon(MoonIcons.other_frame_24_light), + ), + Segment( + leading: Icon(MoonIcons.other_frame_24_light), + label: Text('Tab2'), + trailing: Icon(MoonIcons.other_frame_24_light), + ), + Segment( + leading: Icon(MoonIcons.other_frame_24_light), + label: Text('Tab3'), + trailing: Icon(MoonIcons.other_frame_24_light), + ), + ], + ), + ], + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/switch.md b/example/assets/code_snippets/switch.md new file mode 100644 index 00000000..f187d33e --- /dev/null +++ b/example/assets/code_snippets/switch.md @@ -0,0 +1,22 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class Switch extends StatefulWidget { + const Switch({super.key}); + + @override + State createState() => _SwitchState(); +} + +class _SwitchState extends State { + bool switchValue = false; + + @override + Widget build(BuildContext context) { + return MoonSwitch( + value: switchValue, + switchSize: MoonSwitchSize.sm, + onChanged: (bool newValue) => setState(() => switchValue = newValue), + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/tab_bar.md b/example/assets/code_snippets/tab_bar.md new file mode 100644 index 00000000..6b10f0c0 --- /dev/null +++ b/example/assets/code_snippets/tab_bar.md @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class TabBar extends StatelessWidget { + const TabBar({super.key}); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + MoonTabBar( + tabBarSize: MoonTabBarSize.sm, + tabs: const [ + MoonTab( + leading: Icon(MoonIcons.other_frame_24_light), + label: Text('Tab1'), + trailing: Icon(MoonIcons.other_frame_24_light), + ), + MoonTab( + leading: Icon(MoonIcons.other_frame_24_light), + label: Text('Tab2'), + trailing: Icon(MoonIcons.other_frame_24_light), + ), + MoonTab( + leading: Icon(MoonIcons.other_frame_24_light), + label: Text('Tab3'), + trailing: Icon(MoonIcons.other_frame_24_light), + ), + ], + ), + MoonTabBar.pill( + tabBarSize: MoonTabBarSize.sm, + pillTabs: const [ + MoonPillTab( + leading: Icon(MoonIcons.other_frame_24_light), + label: Text('Tab1'), + trailing: Icon(MoonIcons.other_frame_24_light), + ), + MoonPillTab( + leading: Icon(MoonIcons.other_frame_24_light), + label: Text('Tab2'), + trailing: Icon(MoonIcons.other_frame_24_light), + ), + MoonPillTab( + leading: Icon(MoonIcons.other_frame_24_light), + label: Text('Tab3'), + trailing: Icon(MoonIcons.other_frame_24_light), + ), + ], + ), + ], + ); + } +} diff --git a/example/assets/code_snippets/table.md b/example/assets/code_snippets/table.md new file mode 100644 index 00000000..2c5dfe2b --- /dev/null +++ b/example/assets/code_snippets/table.md @@ -0,0 +1,129 @@ +import 'dart:math'; + +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +const int _rowsCount = 50; + +class Table extends StatefulWidget { + const Table({super.key}); + + @override + State createState() => _TableState(); +} + +class _TableState extends State
{ + late List<_TableData> _tableData; + + final List _columnNames = ['ID', 'First name', 'Last name', 'Age', 'Activity']; + final List _columnSorting = List.generate(5, (int _) => true); + + bool _sortAscending = true; + int _sortColumnIndex = 0; + + List<_TableData> _generateTableData() { + return List<_TableData>.generate( + _rowsCount, + (int index) => _TableData( + id: index, + selected: false, + firstName: 'Test$index', + lastName: 'Subject$index', + age: Random().nextInt(81), + activity: Random().nextInt(100), + ), + ); + } + + void _onSort(int columnIndex, bool sortAscending) { + if (_sortColumnIndex == columnIndex || _sortAscending != sortAscending) { + setState(() { + if (columnIndex == _sortColumnIndex) { + _sortAscending = _columnSorting[columnIndex] = sortAscending; + } else { + _sortColumnIndex = columnIndex; + _sortAscending = _columnSorting[columnIndex]; + } + + switch (columnIndex) { + case 0: _tableData.sort((a, b) => a.id.compareTo(b.id)); + case 1: _tableData.sort((a, b) => a.firstName.compareTo(b.firstName)); + case 2: _tableData.sort((a, b) => a.lastName.compareTo(b.lastName)); + case 3: _tableData.sort((a, b) => a.age.compareTo(b.age)); + case 4: _tableData.sort((a, b) => a.activity.compareTo(b.activity)); + } + + if (!_sortAscending) _tableData = _tableData.reversed.toList(); + }); + } + } + + @override + void initState() { + super.initState(); + + _tableData = _generateTableData(); + } + + MoonTableHeader _generateTableHeader() { + return MoonTableHeader( + columns: List.generate( + 5, + (int index) => MoonTableColumn( + onSort: (int columnIndex, bool sortAscending) => _onSort(columnIndex, sortAscending), + cell: Text(_columnNames[index]), + ), + ), + ); + } + + List _generateTableRows() { + return List.generate( + _rowsCount, + (int index) => MoonTableRow( + cells: [ + Text(_tableData[index].id.toString()), + Text(_tableData[index].firstName), + Text(_tableData[index].lastName), + Text(_tableData[index].age.toString()), + Text(_tableData[index].activity.toString()), + ], + ), + ); + } + + @override + Widget build(BuildContext context) { + return OverflowBox( + maxWidth: MediaQuery.of(context).size.width, + child: MoonTable( + columnsCount: 5, + width: 564, + rowSize: MoonTableRowSize.sm, + tablePadding: const EdgeInsets.symmetric(horizontal: 16), + sortAscending: _sortAscending, + sortColumnIndex: _sortColumnIndex, + header: _generateTableHeader(), + rows: _generateTableRows(), + ), + ); + } +} + +class _TableData { + bool selected; + int age; + int activity; + int id; + String firstName; + String lastName; + + _TableData({ + required this.selected, + required this.age, + required this.activity, + required this.id, + required this.firstName, + required this.lastName, + }); +} diff --git a/example/assets/code_snippets/tag.md b/example/assets/code_snippets/tag.md new file mode 100644 index 00000000..7841004d --- /dev/null +++ b/example/assets/code_snippets/tag.md @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class Tag extends StatelessWidget { + const Tag({super.key}); + + @override + Widget build(BuildContext context) { + return MoonTag( + tagSize: MoonTagSize.sm, + onTap: () {}, + leading: const Icon(MoonIcons.controls_close_small_16_light), + label: const Text('This is MoonTag'), + trailing: const Icon(MoonIcons.controls_close_small_16_light), + ); + } +} diff --git a/example/assets/code_snippets/text_area.md b/example/assets/code_snippets/text_area.md new file mode 100644 index 00000000..fc2ab61e --- /dev/null +++ b/example/assets/code_snippets/text_area.md @@ -0,0 +1,30 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class TextArea extends StatelessWidget { + const TextArea({super.key}); + + @override + Widget build(BuildContext context) { + return Form( + child: Builder( + builder: (BuildContext context) { + return Column( + children: [ + MoonTextArea( + height: 200, + validator: (String? value) => value?.length != null && value!.length < 5 + ? "The text should be longer than 5 characters." + : null, + ), + MoonFilledButton( + onTap: () => Form.of(context).validate(), + label: const Text("Submit"), + ), + ], + ); + }, + ), + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/text_input.md b/example/assets/code_snippets/text_input.md new file mode 100644 index 00000000..d6f939f5 --- /dev/null +++ b/example/assets/code_snippets/text_input.md @@ -0,0 +1,42 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class TextInput extends StatefulWidget { + const TextInput({super.key}); + + @override + State createState() => _TextInputState(); +} + +class _TextInputState extends State { + final TextEditingController _textController = TextEditingController(); + + @override + Widget build(BuildContext context) { + return Form( + child: Builder( + builder: (BuildContext context) { + return Column( + children: [ + MoonFormTextInput( + controller: _textController, + validator: (String? value) => value != null && value.length < 5 + ? "The text should be longer than 5 characters." + : null, + onTap: () => _textController.clear(), + leading: const Icon(MoonIcons.generic_search_24_light), + trailing: GestureDetector( + child: const Icon(MoonIcons.controls_close_small_24_light), + ), + ), + MoonFilledButton( + onTap: () => Form.of(context).validate(), + label: const Text("Submit"), + ), + ], + ); + }, + ), + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/text_input_group.md b/example/assets/code_snippets/text_input_group.md new file mode 100644 index 00000000..26ad194b --- /dev/null +++ b/example/assets/code_snippets/text_input_group.md @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class TextInputGroup extends StatefulWidget { + const TextInputGroup({super.key}); + + @override + State createState() => _TextInputGroupState(); +} + +class _TextInputGroupState extends State { + final TextEditingController _textController = TextEditingController(); + final TextEditingController _passwordController = TextEditingController(); + + bool _hidePassword = true; + + @override + Widget build(BuildContext context) { + return Form( + child: Builder( + builder: (context) { + return Column( + children: [ + MoonTextInputGroup( + children: [ + MoonFormTextInput( + textInputSize: MoonTextInputSize.xl, + controller: _textController, + validator: (String? value) => value?.length != null && value!.length < 5 + ? "The text should be longer than 5 characters." + : null, + leading: const Icon(MoonIcons.generic_search_24_light), + trailing: GestureDetector( + onTap: () => _textController.clear(), + child: const Icon(MoonIcons.controls_close_small_24_light), + ), + ), + MoonFormTextInput( + textInputSize: MoonTextInputSize.xl, + obscureText: _hidePassword, + controller: _passwordController, + validator: (String? value) => value != "123" ? "Wrong password." : null, + leading: const Icon(MoonIcons.security_password_24_light), + trailing: GestureDetector( + onTap: () => setState(() => _hidePassword = !_hidePassword), + child: Align( + child: Text(_hidePassword ? "Show" : "Hide"), + ), + ), + ), + ], + ), + MoonFilledButton( + onTap: () => Form.of(context).validate(), + label: const Text("Submit"), + ), + ], + ); + }, + ), + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/toast.md b/example/assets/code_snippets/toast.md new file mode 100644 index 00000000..e5ee841a --- /dev/null +++ b/example/assets/code_snippets/toast.md @@ -0,0 +1,17 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class Toast extends StatelessWidget { + const Toast({super.key}); + + @override + Widget build(BuildContext context) { + return MoonFilledButton( + onTap: () => MoonToast.show( + context, + title: const Text('This is MoonToast'), + ), + label: const Text("Show toast"), + ); + } +} \ No newline at end of file diff --git a/example/assets/code_snippets/tooltip.md b/example/assets/code_snippets/tooltip.md new file mode 100644 index 00000000..ff790f8b --- /dev/null +++ b/example/assets/code_snippets/tooltip.md @@ -0,0 +1,26 @@ +import 'package:flutter/material.dart'; +import 'package:moon_design/moon_design.dart'; + +class Tooltip extends StatefulWidget { + const Tooltip({super.key}); + + @override + State createState() => _TooltipState(); +} + +class _TooltipState extends State { + bool showOnTap = false; + + @override + Widget build(BuildContext context) { + return MoonTooltip( + show: showOnTap, + content: const Text('This is MoonTooltip'), + child: MoonFilledButton( + buttonSize: MoonButtonSize.sm, + onTap: () => setState(() => showOnTap = true), + label: const Text("Show tooltip"), + ), + ); + } +} \ No newline at end of file diff --git a/example/lib/src/storybook/routing/app_router.dart b/example/lib/src/storybook/routing/app_router.dart index e2901061..84e1441e 100644 --- a/example/lib/src/storybook/routing/app_router.dart +++ b/example/lib/src/storybook/routing/app_router.dart @@ -246,161 +246,3 @@ GoRouter router = GoRouter( ), ], ); - -final List routeAwareStories = [ - Story.asRoute( - name: 'Accordion', - routePath: AccordionStory.path, - router: router, - ), - Story.asRoute( - name: 'Alert', - routePath: AlertStory.path, - router: router, - ), - Story.asRoute( - name: 'AuthCode', - routePath: AuthCodeStory.path, - router: router, - ), - Story.asRoute( - name: 'Avatar', - routePath: AvatarStory.path, - router: router, - ), - Story.asRoute( - name: 'BottomSheet', - routePath: BottomSheetStory.path, - router: router, - ), - Story.asRoute( - name: 'Button', - routePath: ButtonStory.path, - router: router, - ), - Story.asRoute( - name: 'Carousel', - routePath: CarouselStory.path, - router: router, - ), - Story.asRoute( - name: 'Checkbox', - routePath: CheckboxStory.path, - router: router, - ), - Story.asRoute( - name: 'Chip', - routePath: ChipStory.path, - router: router, - ), - Story.asRoute( - name: 'Loader/CircularLoader', - routePath: CircularLoaderStory.path, - router: router, - ), - Story.asRoute( - name: 'Progress/CircularProgress', - routePath: CircularProgressStory.path, - router: router, - ), - Story.asRoute( - name: 'DotIndicator', - routePath: DotIndicatorStory.path, - router: router, - ), - Story.asRoute( - name: 'Drawer', - routePath: DrawerStory.path, - router: router, - ), - Story.asRoute( - name: 'Dropdown', - routePath: DropdownStory.path, - router: router, - ), - Story.asRoute( - name: 'Icons', - routePath: IconsStory.path, - router: router, - ), - Story.asRoute( - name: 'Loader/LinearLoader', - routePath: LinearLoaderStory.path, - router: router, - ), - Story.asRoute( - name: 'Progress/LinearProgress', - routePath: LinearProgressStory.path, - router: router, - ), - Story.asRoute( - name: 'MenuItem', - routePath: MenuItemStory.path, - router: router, - ), - Story.asRoute( - name: 'Modal', - routePath: ModalStory.path, - router: router, - ), - Story.asRoute( - name: 'Popover', - routePath: PopoverStory.path, - router: router, - ), - Story.asRoute( - name: 'Radio', - routePath: RadioStory.path, - router: router, - ), - Story.asRoute( - name: 'SegmentedControl', - routePath: SegmentedControlStory.path, - router: router, - ), - Story.asRoute( - name: 'Switch', - routePath: SwitchStory.path, - router: router, - ), - Story.asRoute( - name: 'TabBar', - routePath: TabBarStory.path, - router: router, - ), - Story.asRoute( - name: 'Table', - routePath: TableStory.path, - router: router, - ), - Story.asRoute( - name: 'Tag', - routePath: TagStory.path, - router: router, - ), - Story.asRoute( - name: 'TextArea', - routePath: TextAreaStory.path, - router: router, - ), - Story.asRoute( - name: 'TextInput', - routePath: TextInputStory.path, - router: router, - ), - Story.asRoute( - name: 'TextInputGroup', - routePath: TextInputGroupStory.path, - router: router, - ), - Story.asRoute( - name: 'Toast', - routePath: ToastStory.path, - router: router, - ), - Story.asRoute( - name: 'Tooltip', - routePath: TooltipStory.path, - router: router, - ), -]; diff --git a/example/lib/src/storybook/routing/route_aware_stories.dart b/example/lib/src/storybook/routing/route_aware_stories.dart new file mode 100644 index 00000000..7acce07f --- /dev/null +++ b/example/lib/src/storybook/routing/route_aware_stories.dart @@ -0,0 +1,227 @@ +import 'package:example/src/storybook/routing/app_router.dart'; +import 'package:example/src/storybook/stories/accordion.dart'; +import 'package:example/src/storybook/stories/alert.dart'; +import 'package:example/src/storybook/stories/auth_code.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'; +import 'package:example/src/storybook/stories/circular_progress.dart'; +import 'package:example/src/storybook/stories/dot_indicator.dart'; +import 'package:example/src/storybook/stories/drawer.dart'; +import 'package:example/src/storybook/stories/dropdown.dart'; +import 'package:example/src/storybook/stories/icons.dart'; +import 'package:example/src/storybook/stories/linear_loader.dart'; +import 'package:example/src/storybook/stories/linear_progress.dart'; +import 'package:example/src/storybook/stories/menu_item.dart'; +import 'package:example/src/storybook/stories/modal.dart'; +import 'package:example/src/storybook/stories/popover.dart'; +import 'package:example/src/storybook/stories/radio.dart'; +import 'package:example/src/storybook/stories/segmented_control.dart'; +import 'package:example/src/storybook/stories/switch.dart'; +import 'package:example/src/storybook/stories/tab_bar.dart'; +import 'package:example/src/storybook/stories/table.dart'; +import 'package:example/src/storybook/stories/tag.dart'; +import 'package:example/src/storybook/stories/text_area.dart'; +import 'package:example/src/storybook/stories/text_input.dart'; +import 'package:example/src/storybook/stories/text_input_group.dart'; +import 'package:example/src/storybook/stories/toast.dart'; +import 'package:example/src/storybook/stories/tooltip.dart'; +import 'package:flutter/services.dart'; +import 'package:storybook_flutter/storybook_flutter.dart'; + +const String directory = 'assets/code_snippets/'; + +final List routeAwareStories = [ + Story.asRoute( + name: 'Accordion', + routePath: AccordionStory.path, + router: router, + codeString: fetchAsset('accordion.md'), + ), + Story.asRoute( + name: 'Alert', + routePath: AlertStory.path, + router: router, + codeString: fetchAsset('alert.md'), + ), + Story.asRoute( + name: 'AuthCode', + routePath: AuthCodeStory.path, + router: router, + codeString: fetchAsset('auth_code.md'), + ), + Story.asRoute( + name: 'Avatar', + routePath: AvatarStory.path, + router: router, + codeString: fetchAsset('avatar.md'), + ), + Story.asRoute( + name: 'BottomSheet', + routePath: BottomSheetStory.path, + router: router, + codeString: fetchAsset('bottom_sheet.md'), + ), + Story.asRoute( + name: 'Button', + routePath: ButtonStory.path, + router: router, + codeString: fetchAsset('button.md'), + ), + Story.asRoute( + name: 'Carousel', + routePath: CarouselStory.path, + router: router, + codeString: fetchAsset('carousel.md'), + ), + Story.asRoute( + name: 'Checkbox', + routePath: CheckboxStory.path, + router: router, + codeString: fetchAsset('checkbox.md'), + ), + Story.asRoute( + name: 'Chip', + routePath: ChipStory.path, + router: router, + codeString: fetchAsset('chip.md'), + ), + Story.asRoute( + name: 'Loader/CircularLoader', + routePath: CircularLoaderStory.path, + router: router, + codeString: fetchAsset('circular_loader.md'), + ), + Story.asRoute( + name: 'Progress/CircularProgress', + routePath: CircularProgressStory.path, + router: router, + codeString: fetchAsset('circular_progress.md'), + ), + Story.asRoute( + name: 'DotIndicator', + routePath: DotIndicatorStory.path, + router: router, + codeString: fetchAsset('dot_indicator.md'), + ), + Story.asRoute( + name: 'Drawer', + routePath: DrawerStory.path, + router: router, + codeString: fetchAsset('drawer.md'), + ), + Story.asRoute( + name: 'Dropdown', + routePath: DropdownStory.path, + router: router, + codeString: fetchAsset('dropdown.md'), + ), + Story.asRoute( + name: 'Icons', + routePath: IconsStory.path, + router: router, + codeString: fetchAsset('icons.md'), + ), + Story.asRoute( + name: 'Loader/LinearLoader', + routePath: LinearLoaderStory.path, + router: router, + codeString: fetchAsset('linear_loader.md'), + ), + Story.asRoute( + name: 'Progress/LinearProgress', + routePath: LinearProgressStory.path, + router: router, + codeString: fetchAsset('linear_progress.md'), + ), + Story.asRoute( + name: 'MenuItem', + routePath: MenuItemStory.path, + router: router, + codeString: fetchAsset('menu_item.md'), + ), + Story.asRoute( + name: 'Modal', + routePath: ModalStory.path, + router: router, + codeString: fetchAsset('modal.md'), + ), + Story.asRoute( + name: 'Popover', + routePath: PopoverStory.path, + router: router, + codeString: fetchAsset('popover.md'), + ), + Story.asRoute( + name: 'Radio', + routePath: RadioStory.path, + router: router, + codeString: fetchAsset('radio.md'), + ), + Story.asRoute( + name: 'SegmentedControl', + routePath: SegmentedControlStory.path, + router: router, + codeString: fetchAsset('segmented_control.md'), + ), + Story.asRoute( + name: 'Switch', + routePath: SwitchStory.path, + router: router, + codeString: fetchAsset('switch.md'), + ), + Story.asRoute( + name: 'TabBar', + routePath: TabBarStory.path, + router: router, + codeString: fetchAsset('tab_bar.md'), + ), + Story.asRoute( + name: 'Table', + routePath: TableStory.path, + router: router, + codeString: fetchAsset('table.md'), + ), + Story.asRoute( + name: 'Tag', + routePath: TagStory.path, + router: router, + codeString: fetchAsset('tag.md'), + ), + Story.asRoute( + name: 'TextArea', + routePath: TextAreaStory.path, + router: router, + codeString: fetchAsset('text_area.md'), + ), + Story.asRoute( + name: 'TextInput', + routePath: TextInputStory.path, + router: router, + codeString: fetchAsset('text_input.md'), + ), + Story.asRoute( + name: 'TextInputGroup', + routePath: TextInputGroupStory.path, + router: router, + codeString: fetchAsset('text_input_group.md'), + ), + Story.asRoute( + name: 'Toast', + routePath: ToastStory.path, + router: router, + codeString: fetchAsset('toast.md'), + ), + Story.asRoute( + name: 'Tooltip', + routePath: TooltipStory.path, + router: router, + codeString: fetchAsset('tooltip.md'), + ), +]; + +Future fetchAsset(String assetName) async => rootBundle.loadString('$directory$assetName'); diff --git a/example/lib/src/storybook/stories/table.dart b/example/lib/src/storybook/stories/table.dart index b6d04887..4473fbce 100644 --- a/example/lib/src/storybook/stories/table.dart +++ b/example/lib/src/storybook/stories/table.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:moon_design/moon_design.dart'; import 'package:storybook_flutter/storybook_flutter.dart'; -const int _rowsInPage = 25; +const int _rowsPerPage = 25; class TableStory extends StatefulWidget { static const path = '/table'; @@ -17,8 +17,8 @@ class TableStory extends StatefulWidget { } class _TableStoryState extends State { - final List<_ExampleTableData> _exampleTableData = _generateTableData(); - late List<_ExampleTableData> _exampleTableDataToShow; + late final List<_TableData> _tableDataOriginal; + late List<_TableData> _tableDataToShow; final List _columnNames = ['ID', 'First name', 'Last name', 'Age', 'Activity']; final List _columnSorting = List.generate(6, (int _) => true); @@ -26,7 +26,7 @@ class _TableStoryState extends State { bool _checkAllBoxes = false; bool _sortAscending = true; int _sortColumnIndex = 0; - int _rowsToShow = _rowsInPage; + int _rowsToShow = _rowsPerPage; bool _showCheckboxes = false; bool _showDividerKnob = false; @@ -38,22 +38,37 @@ class _TableStoryState extends State { Color? _textColor; int? _borderRadiusKnob; - void _scrollListener(StateSetter setState, ScrollController verticalScrollController) { + List<_TableData> _generateTableData() { + return List<_TableData>.generate( + _rowsPerPage * 5, + (int index) => _TableData( + id: index, + selected: false, + firstName: 'Test$index', + lastName: 'Subject$index', + age: Random().nextInt(81), + activity: Random().nextInt(100), + colStickyTitle: 'Sticky title $index', + ), + ); + } + + void _scrollListener(ScrollController verticalScrollController) { verticalScrollController.addListener(() { if (verticalScrollController.hasClients && _infiniteScrollKnob) { final double pixels = verticalScrollController.position.pixels; final double maxScrollExtent = verticalScrollController.position.maxScrollExtent; - if (pixels >= maxScrollExtent && _rowsToShow < _rowsInPage * 5) { - _exampleTableDataToShow += _exampleTableData.sublist(_rowsToShow, _rowsToShow + _rowsInPage); + if (pixels >= maxScrollExtent && _rowsToShow < _rowsPerPage * 5) { + _tableDataToShow += _tableDataOriginal.sublist(_rowsToShow, _rowsToShow + _rowsPerPage); - setState(() => _rowsToShow += _rowsInPage); + setState(() => _rowsToShow += _rowsPerPage); } } }); } - void _onSort(StateSetter setState, int columnIndex, bool sortAscending) { + void _onSort(int columnIndex, bool sortAscending) { if (_sortColumnIndex == columnIndex || _sortAscending != sortAscending) { setState(() { if (columnIndex == _sortColumnIndex) { @@ -62,19 +77,21 @@ class _TableStoryState extends State { _sortColumnIndex = columnIndex; _sortAscending = _columnSorting[columnIndex]; } + switch (_showCheckboxes ? columnIndex : columnIndex + 1) { case 1: - _exampleTableDataToShow.sort((a, b) => a.id.compareTo(b.id)); + _tableDataToShow.sort((a, b) => a.id.compareTo(b.id)); case 2: - _exampleTableDataToShow.sort((a, b) => a.firstName.compareTo(b.firstName)); + _tableDataToShow.sort((a, b) => a.firstName.compareTo(b.firstName)); case 3: - _exampleTableDataToShow.sort((a, b) => a.lastName.compareTo(b.lastName)); + _tableDataToShow.sort((a, b) => a.lastName.compareTo(b.lastName)); case 4: - _exampleTableDataToShow.sort((a, b) => a.age.compareTo(b.age)); + _tableDataToShow.sort((a, b) => a.age.compareTo(b.age)); case 5: - _exampleTableDataToShow.sort((a, b) => a.activity.compareTo(b.activity)); + _tableDataToShow.sort((a, b) => a.activity.compareTo(b.activity)); } - if (!_sortAscending) _exampleTableDataToShow = _exampleTableDataToShow.reversed.toList(); + + if (!_sortAscending) _tableDataToShow = _tableDataToShow.reversed.toList(); }); } } @@ -83,10 +100,11 @@ class _TableStoryState extends State { void initState() { super.initState(); - _exampleTableDataToShow = _exampleTableData.sublist(0, _rowsInPage); + _tableDataOriginal = _generateTableData(); + _tableDataToShow = _tableDataOriginal.sublist(0, _rowsPerPage); } - Widget _headerCheckBox(StateSetter setState) { + Widget _headerCheckBox() { return Padding( padding: const EdgeInsetsDirectional.only(start: 16.0), child: MoonCheckbox( @@ -96,7 +114,8 @@ class _TableStoryState extends State { ? (bool? onChanged) => onChanged != null ? setState(() { _checkAllBoxes = onChanged; - for (final item in _exampleTableDataToShow) { + + for (final item in _tableDataToShow) { item.selected = _checkAllBoxes; } }) @@ -106,7 +125,7 @@ class _TableStoryState extends State { ); } - Widget _buildCell(BuildContext context, dynamic label, {bool firstCell = false}) { + Widget _buildCell(dynamic label, {bool firstCell = false}) { return DecoratedBox( decoration: _showDividerKnob && !firstCell ? BoxDecoration( @@ -135,7 +154,7 @@ class _TableStoryState extends State { ); } - MoonTableHeader _generateTableHeader(BuildContext context, StateSetter setState) { + MoonTableHeader _generateTableHeader() { return MoonTableHeader( columns: List.generate( _showCheckboxes ? 6 : 5, @@ -150,19 +169,17 @@ class _TableStoryState extends State { setState(() { _checkAllBoxes = !_checkAllBoxes; - for (final item in _exampleTableDataToShow) { + for (final item in _tableDataToShow) { item.selected = _checkAllBoxes; } }); } }, - onSort: checkboxColumn - ? null - : (int columnIndex, bool sortAscending) => _onSort(setState, columnIndex, sortAscending), + onSort: + checkboxColumn ? null : (int columnIndex, bool sortAscending) => _onSort(columnIndex, sortAscending), cell: checkboxColumn - ? _headerCheckBox(setState) + ? _headerCheckBox() : _buildCell( - context, _columnNames[_showCheckboxes ? index - 1 : index], firstCell: index == 0 && !_showCheckboxes, ), @@ -172,7 +189,7 @@ class _TableStoryState extends State { ); } - MoonTableFooter _generateTableFooter(BuildContext context) { + MoonTableFooter _generateTableFooter() { return MoonTableFooter( cells: List.generate( _showCheckboxes ? 6 : 5, @@ -183,23 +200,23 @@ class _TableStoryState extends State { final String label = index == 0 ? 'Total:' : (index == ageColumnIndex || index == activityColumnIndex) - ? _exampleTableDataToShow - .map((_ExampleTableData item) => index == ageColumnIndex ? item.age : item.activity) + ? _tableDataToShow + .map((_TableData item) => index == ageColumnIndex ? item.age : item.activity) .reduce((int value, int element) => value + element) .toString() : '-'; - return _buildCell(context, label, firstCell: index == 0); + return _buildCell(label, firstCell: index == 0); }, ), ); } - List _generateTableRows(BuildContext context, StateSetter setState) { + List _generateTableRows() { return List.generate( _rowsToShow, (int index) { - final row = _exampleTableDataToShow[index]; + final row = _tableDataToShow[index]; return MoonTableRow( selected: row.selected, @@ -232,11 +249,11 @@ class _TableStoryState extends State { _rowsSelectableKnob ? (bool? onChanged) => setState(() => row.selected = !row.selected) : null, ), ), - _buildCell(context, _exampleTableDataToShow[index].id, firstCell: !_showCheckboxes), - _buildCell(context, _exampleTableDataToShow[index].firstName), - _buildCell(context, _exampleTableDataToShow[index].lastName), - _buildCell(context, _exampleTableDataToShow[index].age), - _buildCell(context, _exampleTableDataToShow[index].activity), + _buildCell(row.id, firstCell: !_showCheckboxes), + _buildCell(row.firstName), + _buildCell(row.lastName), + _buildCell(row.age), + _buildCell(row.activity), ], ); }, @@ -356,8 +373,8 @@ class _TableStoryState extends State { _infiniteScrollKnob = infiniteScrollKnob; if (!infiniteScrollKnob) { - _exampleTableDataToShow = _exampleTableData.sublist(0, _rowsInPage); - _rowsToShow = _rowsInPage; + _tableDataToShow = _tableDataOriginal.sublist(0, _rowsPerPage); + _rowsToShow = _rowsPerPage; } } @@ -376,23 +393,23 @@ class _TableStoryState extends State { sortColumnIndex: _sortColumnIndex, rowGap: rowGapKnob?.toDouble(), rowSize: tableRowSizeKnob ?? MoonTableRowSize.md, - header: _generateTableHeader(context, setState), - footer: _generateTableFooter(context), - rows: _generateTableRows(context, setState), + header: _generateTableHeader(), + footer: _generateTableFooter(), + rows: _generateTableRows(), tablePadding: const EdgeInsets.symmetric(horizontal: 16), cellPadding: EdgeInsets.symmetric(vertical: tableRowSizeKnob == MoonTableRowSize.xs ? 4 : 8), onScrollControllersReady: ( ScrollController verticalScrollController, ScrollController horizontalScrollController, ) => - _scrollListener(setState, verticalScrollController), + _scrollListener(verticalScrollController), ), ), ); } } -class _ExampleTableData { +class _TableData { bool selected; int id; String firstName; @@ -401,7 +418,7 @@ class _ExampleTableData { int activity; String colStickyTitle; - _ExampleTableData({ + _TableData({ required this.selected, required this.id, required this.firstName, @@ -411,18 +428,3 @@ class _ExampleTableData { required this.colStickyTitle, }); } - -List<_ExampleTableData> _generateTableData() { - return List<_ExampleTableData>.generate( - _rowsInPage * 5, - (int index) => _ExampleTableData( - id: index, - selected: false, - firstName: 'Test$index', - lastName: 'Subject$index', - age: Random().nextInt(81), - activity: Random().nextInt(100), - colStickyTitle: 'Sticky title $index', - ), - ); -} diff --git a/example/lib/src/storybook/storybook.dart b/example/lib/src/storybook/storybook.dart index 3f9126d2..b2164a99 100644 --- a/example/lib/src/storybook/storybook.dart +++ b/example/lib/src/storybook/storybook.dart @@ -1,5 +1,5 @@ import 'package:example/src/storybook/common/widgets/version.dart'; -import 'package:example/src/storybook/routing/app_router.dart'; +import 'package:example/src/storybook/routing/route_aware_stories.dart'; import 'package:flutter/material.dart'; import 'package:moon_design/moon_design.dart'; import 'package:storybook_flutter/storybook_flutter.dart'; @@ -10,6 +10,7 @@ class StorybookPage extends StatelessWidget { static const double autoLayoutThreshold = 1000; static final _plugins = initializePlugins( + enableCodeView: true, enableCompactLayoutDeviceFrame: false, initialDeviceFrameData: ( isFrameVisible: true, diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 9cff8ddc..e4ca7607 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -18,7 +18,6 @@ dependencies: storybook_flutter: git: url: https://github.com/coingaming/storybook_flutter.git - ref: d808e2c5bb93419e5e5e351123b6bacec4f28a60 path: packages/storybook_flutter transparent_image: ^2.0.1 dev_dependencies: @@ -33,5 +32,6 @@ flutter: fonts: - asset: assets/DMSans.ttf assets: + - assets/code_snippets/ - assets/images/ - assets/svg/ diff --git a/lib/src/theme/loaders/circular_loader/circular_loader_theme.dart b/lib/src/theme/loaders/circular_loader/circular_loader_theme.dart index 55d459ef..0bad3ace 100644 --- a/lib/src/theme/loaders/circular_loader/circular_loader_theme.dart +++ b/lib/src/theme/loaders/circular_loader/circular_loader_theme.dart @@ -22,7 +22,7 @@ class MoonCircularLoaderTheme extends ThemeExtension wi MoonCircularLoaderSizes? sizes, }) : colors = colors ?? MoonCircularLoaderColors( - color: tokens.colors.hit, + color: tokens.colors.piccolo, backgroundColor: Colors.transparent, ), sizes = sizes ?? MoonCircularLoaderSizes(tokens: tokens); diff --git a/lib/src/theme/loaders/linear_loader/linear_loader_theme.dart b/lib/src/theme/loaders/linear_loader/linear_loader_theme.dart index eb85df9c..e4006d5f 100644 --- a/lib/src/theme/loaders/linear_loader/linear_loader_theme.dart +++ b/lib/src/theme/loaders/linear_loader/linear_loader_theme.dart @@ -22,7 +22,7 @@ class MoonLinearLoaderTheme extends ThemeExtension with D MoonLinearLoaderSizes? sizes, }) : colors = colors ?? MoonLinearLoaderColors( - color: tokens.colors.hit, + color: tokens.colors.piccolo, backgroundColor: Colors.transparent, ), sizes = sizes ?? MoonLinearLoaderSizes(tokens: tokens); diff --git a/lib/src/widgets/loaders/circular_loader.dart b/lib/src/widgets/loaders/circular_loader.dart index 5c1e6667..99d1d97d 100644 --- a/lib/src/widgets/loaders/circular_loader.dart +++ b/lib/src/widgets/loaders/circular_loader.dart @@ -67,10 +67,10 @@ class MoonCircularLoader extends StatelessWidget { Widget build(BuildContext context) { final MoonCircularLoaderSizeProperties effectiveLoaderSize = _getMoonLoaderSize(context, circularLoaderSize); - final Color effectiveColor = color ?? context.moonTheme?.circularLoaderTheme.colors.color ?? MoonColors.light.hit; + final Color effectiveColor = color ?? context.moonTheme?.circularLoaderTheme.colors.color ?? MoonColors.light.piccolo; final Color effectiveBackgroundColor = - backgroundColor ?? context.moonTheme?.circularLoaderTheme.colors.backgroundColor ?? MoonColors.light.trunks; + backgroundColor ?? context.moonTheme?.circularLoaderTheme.colors.backgroundColor ?? Colors.transparent; final double effectiveSize = sizeValue ?? effectiveLoaderSize.loaderSizeValue; diff --git a/lib/src/widgets/loaders/linear_loader.dart b/lib/src/widgets/loaders/linear_loader.dart index f0b224db..b20ebaf0 100644 --- a/lib/src/widgets/loaders/linear_loader.dart +++ b/lib/src/widgets/loaders/linear_loader.dart @@ -64,10 +64,10 @@ class MoonLinearLoader extends StatelessWidget { final BorderRadiusGeometry effectiveBorderRadius = borderRadius ?? effectiveLoaderSize.borderRadius; - final Color effectiveColor = color ?? context.moonTheme?.linearLoaderTheme.colors.color ?? MoonColors.light.hit; + final Color effectiveColor = color ?? context.moonTheme?.linearLoaderTheme.colors.color ?? MoonColors.light.piccolo; final Color effectiveBackgroundColor = - backgroundColor ?? context.moonTheme?.linearLoaderTheme.colors.backgroundColor ?? MoonColors.light.trunks; + backgroundColor ?? context.moonTheme?.linearLoaderTheme.colors.backgroundColor ?? Colors.transparent; final double effectiveHeight = height ?? effectiveLoaderSize.loaderHeight;