From 9854dd3bb26c0c848fee90fbaf76f4592f62abff Mon Sep 17 00:00:00 2001 From: ishanvaghani Date: Tue, 7 Jan 2025 21:16:35 +0530 Subject: [PATCH 1/4] Added support for radio widget --- .../assets/json/home_screen.json | 34 ++ .../assets/json/radio_example.json | 69 +++ packages/mirai/lib/src/framework/mirai.dart | 4 +- .../mirai_mouse_cursor.dart | 117 ++++ .../src/parsers/mirai_radio/mirai_radio.dart | 37 ++ .../mirai_radio/mirai_radio.freezed.dart | 558 ++++++++++++++++++ .../parsers/mirai_radio/mirai_radio.g.dart | 108 ++++ .../mirai_radio/mirai_radio_parser.dart | 150 +++++ .../mirai_radio_group/mirai_radio_group.dart | 20 + .../mirai_radio_group.freezed.dart | 214 +++++++ .../mirai_radio_group.g.dart | 23 + .../mirai_radio_group_parser.dart | 74 +++ .../mirai_radio_group_scope.dart | 33 ++ packages/mirai/lib/src/parsers/parsers.dart | 2 + packages/mirai/lib/src/utils/widget_type.dart | 4 +- website/docs/widgets/radio_group.md | 100 ++++ 16 files changed, 1545 insertions(+), 2 deletions(-) create mode 100644 examples/mirai_gallery/assets/json/radio_example.json create mode 100644 packages/mirai/lib/src/parsers/mirai_mouse_cursor/mirai_mouse_cursor.dart create mode 100644 packages/mirai/lib/src/parsers/mirai_radio/mirai_radio.dart create mode 100644 packages/mirai/lib/src/parsers/mirai_radio/mirai_radio.freezed.dart create mode 100644 packages/mirai/lib/src/parsers/mirai_radio/mirai_radio.g.dart create mode 100644 packages/mirai/lib/src/parsers/mirai_radio/mirai_radio_parser.dart create mode 100644 packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group.dart create mode 100644 packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group.freezed.dart create mode 100644 packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group.g.dart create mode 100644 packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group_parser.dart create mode 100644 packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group_scope.dart create mode 100644 website/docs/widgets/radio_group.md diff --git a/examples/mirai_gallery/assets/json/home_screen.json b/examples/mirai_gallery/assets/json/home_screen.json index 8b2b65b1..ad36cf1f 100644 --- a/examples/mirai_gallery/assets/json/home_screen.json +++ b/examples/mirai_gallery/assets/json/home_screen.json @@ -1353,6 +1353,40 @@ } } }, + { + "type": "listTile", + "leading": { + "type": "icon", + "iconType": "material", + "icon": "radio" + }, + "title": { + "type": "text", + "data": "Mirai Radio", + "align": "center", + "style": { + "fontSize": 21 + } + }, + "subtitle": { + "type": "text", + "data": "A Material Design Radio widget", + "align": "center", + "style": { + "fontSize": 12 + } + }, + "isThreeLine": false, + "style": "list", + "onTap": { + "actionType": "navigate", + "navigationStyle": "push", + "widgetJson": { + "type": "exampleScreen", + "assetPath": "assets/json/radio_example.json" + } + } + }, { "type": "sizedBox", "height": 24.0 diff --git a/examples/mirai_gallery/assets/json/radio_example.json b/examples/mirai_gallery/assets/json/radio_example.json new file mode 100644 index 00000000..0c61ecbf --- /dev/null +++ b/examples/mirai_gallery/assets/json/radio_example.json @@ -0,0 +1,69 @@ +{ + "type": "scaffold", + "appBar": { + "type": "appBar", + "title": { + "type": "text", + "data": "Mirai Radio" + } + }, + "body": { + "type": "radioGroup", + "child": { + "type": "column", + "children": [ + { + "type": "listTile", + "leading": { + "type": "radio", + "radioType": "adaptive", + "value": "1", + "groupValue": "1" + }, + "title": { + "type": "text", + "data": "Male", + "align": "center", + "style": { + "fontSize": 21 + } + } + }, + { + "type": "listTile", + "leading": { + "type": "radio", + "radioType": "adaptive", + "value": "2", + "groupValue": "1" + }, + "title": { + "type": "text", + "data": "Female", + "align": "center", + "style": { + "fontSize": 21 + } + } + }, + { + "type": "listTile", + "leading": { + "type": "radio", + "radioType": "adaptive", + "value": "3", + "groupValue": "1" + }, + "title": { + "type": "text", + "data": "Other", + "align": "center", + "style": { + "fontSize": 21 + } + } + } + ] + } + } +} \ No newline at end of file diff --git a/packages/mirai/lib/src/framework/mirai.dart b/packages/mirai/lib/src/framework/mirai.dart index 403acd7e..c5cf0b3e 100644 --- a/packages/mirai/lib/src/framework/mirai.dart +++ b/packages/mirai/lib/src/framework/mirai.dart @@ -83,7 +83,9 @@ class Mirai { const MiraiTableCellParser(), const MiraiCarouselViewParser(), const MiraiColoredBoxParser(), - const MiraiDividerParser() + const MiraiDividerParser(), + const MiraiRadioParser(), + const MiraiRadioGroupParser(), ]; static final _actionParsers = [ diff --git a/packages/mirai/lib/src/parsers/mirai_mouse_cursor/mirai_mouse_cursor.dart b/packages/mirai/lib/src/parsers/mirai_mouse_cursor/mirai_mouse_cursor.dart new file mode 100644 index 00000000..bff708c7 --- /dev/null +++ b/packages/mirai/lib/src/parsers/mirai_mouse_cursor/mirai_mouse_cursor.dart @@ -0,0 +1,117 @@ +import 'package:flutter/services.dart'; + +enum MiraiMouseCursor { + none, + basic, + click, + forbidden, + wait, + progress, + contextMenu, + help, + text, + verticalText, + cell, + precise, + move, + grab, + grabbing, + noDrop, + alias, + copy, + disappearing, + allScroll, + resizeLeftRight, + resizeUpDown, + resizeUpLeftDownRight, + resizeUpRightDownLeft, + resizeUp, + resizeDown, + resizeLeft, + resizeRight, + resizeUpLeft, + resizeUpRight, + resizeDownLeft, + resizeDownRight, + resizeColumn, + resizeRow, + zoomIn, + zoomOut; + + SystemMouseCursor get value { + switch (this) { + case MiraiMouseCursor.none: + return SystemMouseCursors.none; + case MiraiMouseCursor.basic: + return SystemMouseCursors.basic; + case MiraiMouseCursor.click: + return SystemMouseCursors.click; + case MiraiMouseCursor.forbidden: + return SystemMouseCursors.forbidden; + case MiraiMouseCursor.wait: + return SystemMouseCursors.wait; + case MiraiMouseCursor.progress: + return SystemMouseCursors.progress; + case MiraiMouseCursor.contextMenu: + return SystemMouseCursors.contextMenu; + case MiraiMouseCursor.help: + return SystemMouseCursors.help; + case MiraiMouseCursor.text: + return SystemMouseCursors.text; + case MiraiMouseCursor.verticalText: + return SystemMouseCursors.verticalText; + case MiraiMouseCursor.cell: + return SystemMouseCursors.cell; + case MiraiMouseCursor.precise: + return SystemMouseCursors.precise; + case MiraiMouseCursor.move: + return SystemMouseCursors.move; + case MiraiMouseCursor.grab: + return SystemMouseCursors.grab; + case MiraiMouseCursor.grabbing: + return SystemMouseCursors.grabbing; + case MiraiMouseCursor.noDrop: + return SystemMouseCursors.noDrop; + case MiraiMouseCursor.alias: + return SystemMouseCursors.alias; + case MiraiMouseCursor.copy: + return SystemMouseCursors.copy; + case MiraiMouseCursor.disappearing: + return SystemMouseCursors.disappearing; + case MiraiMouseCursor.allScroll: + return SystemMouseCursors.allScroll; + case MiraiMouseCursor.resizeLeftRight: + return SystemMouseCursors.resizeLeftRight; + case MiraiMouseCursor.resizeUpDown: + return SystemMouseCursors.resizeUpDown; + case MiraiMouseCursor.resizeUpLeftDownRight: + return SystemMouseCursors.resizeUpLeftDownRight; + case MiraiMouseCursor.resizeUpRightDownLeft: + return SystemMouseCursors.resizeUpRightDownLeft; + case MiraiMouseCursor.resizeUp: + return SystemMouseCursors.resizeUp; + case MiraiMouseCursor.resizeDown: + return SystemMouseCursors.resizeDown; + case MiraiMouseCursor.resizeLeft: + return SystemMouseCursors.resizeLeft; + case MiraiMouseCursor.resizeRight: + return SystemMouseCursors.resizeRight; + case MiraiMouseCursor.resizeUpLeft: + return SystemMouseCursors.resizeUpLeft; + case MiraiMouseCursor.resizeUpRight: + return SystemMouseCursors.resizeUpRight; + case MiraiMouseCursor.resizeDownLeft: + return SystemMouseCursors.resizeDownLeft; + case MiraiMouseCursor.resizeDownRight: + return SystemMouseCursors.resizeDownRight; + case MiraiMouseCursor.resizeColumn: + return SystemMouseCursors.resizeColumn; + case MiraiMouseCursor.resizeRow: + return SystemMouseCursors.resizeRow; + case MiraiMouseCursor.zoomIn: + return SystemMouseCursors.zoomIn; + case MiraiMouseCursor.zoomOut: + return SystemMouseCursors.zoomOut; + } + } +} diff --git a/packages/mirai/lib/src/parsers/mirai_radio/mirai_radio.dart b/packages/mirai/lib/src/parsers/mirai_radio/mirai_radio.dart new file mode 100644 index 00000000..1302f19b --- /dev/null +++ b/packages/mirai/lib/src/parsers/mirai_radio/mirai_radio.dart @@ -0,0 +1,37 @@ +import 'package:flutter/material.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:mirai/mirai.dart'; +import 'package:mirai/src/parsers/mirai_mouse_cursor/mirai_mouse_cursor.dart'; + +export 'package:mirai/src/parsers/mirai_radio/mirai_radio_parser.dart'; + +part 'mirai_radio.freezed.dart'; +part 'mirai_radio.g.dart'; + +enum MiraiRadioType { adaptive, cupertino, material } + +@freezed +class MiraiRadio with _$MiraiRadio { + const factory MiraiRadio({ + @Default(MiraiRadioType.material) MiraiRadioType radioType, + dynamic value, + Map? onChanged, + MiraiMouseCursor? mouseCursor, + @Default(false) bool toggleable, + String? activeColor, + String? inactiveColor, + String? fillColor, + String? focusColor, + String? hoverColor, + String? overlayColor, + double? splashRadius, + MaterialTapTargetSize? materialTapTargetSize, + MiraiVisualDensity? visualDensity, + @Default(false) bool autofocus, + @Default(false) bool useCheckmarkStyle, + @Default(false) bool useCupertinoCheckmarkStyle, + }) = _MiraiRadio; + + factory MiraiRadio.fromJson(Map json) => + _$MiraiRadioFromJson(json); +} diff --git a/packages/mirai/lib/src/parsers/mirai_radio/mirai_radio.freezed.dart b/packages/mirai/lib/src/parsers/mirai_radio/mirai_radio.freezed.dart new file mode 100644 index 00000000..8e38b61f --- /dev/null +++ b/packages/mirai/lib/src/parsers/mirai_radio/mirai_radio.freezed.dart @@ -0,0 +1,558 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'mirai_radio.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +MiraiRadio _$MiraiRadioFromJson(Map json) { + return _MiraiRadio.fromJson(json); +} + +/// @nodoc +mixin _$MiraiRadio { + MiraiRadioType get radioType => throw _privateConstructorUsedError; + dynamic get value => throw _privateConstructorUsedError; + Map? get onChanged => throw _privateConstructorUsedError; + MiraiMouseCursor? get mouseCursor => throw _privateConstructorUsedError; + bool get toggleable => throw _privateConstructorUsedError; + String? get activeColor => throw _privateConstructorUsedError; + String? get inactiveColor => throw _privateConstructorUsedError; + String? get fillColor => throw _privateConstructorUsedError; + String? get focusColor => throw _privateConstructorUsedError; + String? get hoverColor => throw _privateConstructorUsedError; + String? get overlayColor => throw _privateConstructorUsedError; + double? get splashRadius => throw _privateConstructorUsedError; + MaterialTapTargetSize? get materialTapTargetSize => + throw _privateConstructorUsedError; + MiraiVisualDensity? get visualDensity => throw _privateConstructorUsedError; + bool get autofocus => throw _privateConstructorUsedError; + bool get useCheckmarkStyle => throw _privateConstructorUsedError; + bool get useCupertinoCheckmarkStyle => throw _privateConstructorUsedError; + + /// Serializes this MiraiRadio to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of MiraiRadio + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $MiraiRadioCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $MiraiRadioCopyWith<$Res> { + factory $MiraiRadioCopyWith( + MiraiRadio value, $Res Function(MiraiRadio) then) = + _$MiraiRadioCopyWithImpl<$Res, MiraiRadio>; + @useResult + $Res call( + {MiraiRadioType radioType, + dynamic value, + Map? onChanged, + MiraiMouseCursor? mouseCursor, + bool toggleable, + String? activeColor, + String? inactiveColor, + String? fillColor, + String? focusColor, + String? hoverColor, + String? overlayColor, + double? splashRadius, + MaterialTapTargetSize? materialTapTargetSize, + MiraiVisualDensity? visualDensity, + bool autofocus, + bool useCheckmarkStyle, + bool useCupertinoCheckmarkStyle}); + + $MiraiVisualDensityCopyWith<$Res>? get visualDensity; +} + +/// @nodoc +class _$MiraiRadioCopyWithImpl<$Res, $Val extends MiraiRadio> + implements $MiraiRadioCopyWith<$Res> { + _$MiraiRadioCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of MiraiRadio + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? radioType = null, + Object? value = freezed, + Object? onChanged = freezed, + Object? mouseCursor = freezed, + Object? toggleable = null, + Object? activeColor = freezed, + Object? inactiveColor = freezed, + Object? fillColor = freezed, + Object? focusColor = freezed, + Object? hoverColor = freezed, + Object? overlayColor = freezed, + Object? splashRadius = freezed, + Object? materialTapTargetSize = freezed, + Object? visualDensity = freezed, + Object? autofocus = null, + Object? useCheckmarkStyle = null, + Object? useCupertinoCheckmarkStyle = null, + }) { + return _then(_value.copyWith( + radioType: null == radioType + ? _value.radioType + : radioType // ignore: cast_nullable_to_non_nullable + as MiraiRadioType, + value: freezed == value + ? _value.value + : value // ignore: cast_nullable_to_non_nullable + as dynamic, + onChanged: freezed == onChanged + ? _value.onChanged + : onChanged // ignore: cast_nullable_to_non_nullable + as Map?, + mouseCursor: freezed == mouseCursor + ? _value.mouseCursor + : mouseCursor // ignore: cast_nullable_to_non_nullable + as MiraiMouseCursor?, + toggleable: null == toggleable + ? _value.toggleable + : toggleable // ignore: cast_nullable_to_non_nullable + as bool, + activeColor: freezed == activeColor + ? _value.activeColor + : activeColor // ignore: cast_nullable_to_non_nullable + as String?, + inactiveColor: freezed == inactiveColor + ? _value.inactiveColor + : inactiveColor // ignore: cast_nullable_to_non_nullable + as String?, + fillColor: freezed == fillColor + ? _value.fillColor + : fillColor // ignore: cast_nullable_to_non_nullable + as String?, + focusColor: freezed == focusColor + ? _value.focusColor + : focusColor // ignore: cast_nullable_to_non_nullable + as String?, + hoverColor: freezed == hoverColor + ? _value.hoverColor + : hoverColor // ignore: cast_nullable_to_non_nullable + as String?, + overlayColor: freezed == overlayColor + ? _value.overlayColor + : overlayColor // ignore: cast_nullable_to_non_nullable + as String?, + splashRadius: freezed == splashRadius + ? _value.splashRadius + : splashRadius // ignore: cast_nullable_to_non_nullable + as double?, + materialTapTargetSize: freezed == materialTapTargetSize + ? _value.materialTapTargetSize + : materialTapTargetSize // ignore: cast_nullable_to_non_nullable + as MaterialTapTargetSize?, + visualDensity: freezed == visualDensity + ? _value.visualDensity + : visualDensity // ignore: cast_nullable_to_non_nullable + as MiraiVisualDensity?, + autofocus: null == autofocus + ? _value.autofocus + : autofocus // ignore: cast_nullable_to_non_nullable + as bool, + useCheckmarkStyle: null == useCheckmarkStyle + ? _value.useCheckmarkStyle + : useCheckmarkStyle // ignore: cast_nullable_to_non_nullable + as bool, + useCupertinoCheckmarkStyle: null == useCupertinoCheckmarkStyle + ? _value.useCupertinoCheckmarkStyle + : useCupertinoCheckmarkStyle // ignore: cast_nullable_to_non_nullable + as bool, + ) as $Val); + } + + /// Create a copy of MiraiRadio + /// with the given fields replaced by the non-null parameter values. + @override + @pragma('vm:prefer-inline') + $MiraiVisualDensityCopyWith<$Res>? get visualDensity { + if (_value.visualDensity == null) { + return null; + } + + return $MiraiVisualDensityCopyWith<$Res>(_value.visualDensity!, (value) { + return _then(_value.copyWith(visualDensity: value) as $Val); + }); + } +} + +/// @nodoc +abstract class _$$MiraiRadioImplCopyWith<$Res> + implements $MiraiRadioCopyWith<$Res> { + factory _$$MiraiRadioImplCopyWith( + _$MiraiRadioImpl value, $Res Function(_$MiraiRadioImpl) then) = + __$$MiraiRadioImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {MiraiRadioType radioType, + dynamic value, + Map? onChanged, + MiraiMouseCursor? mouseCursor, + bool toggleable, + String? activeColor, + String? inactiveColor, + String? fillColor, + String? focusColor, + String? hoverColor, + String? overlayColor, + double? splashRadius, + MaterialTapTargetSize? materialTapTargetSize, + MiraiVisualDensity? visualDensity, + bool autofocus, + bool useCheckmarkStyle, + bool useCupertinoCheckmarkStyle}); + + @override + $MiraiVisualDensityCopyWith<$Res>? get visualDensity; +} + +/// @nodoc +class __$$MiraiRadioImplCopyWithImpl<$Res> + extends _$MiraiRadioCopyWithImpl<$Res, _$MiraiRadioImpl> + implements _$$MiraiRadioImplCopyWith<$Res> { + __$$MiraiRadioImplCopyWithImpl( + _$MiraiRadioImpl _value, $Res Function(_$MiraiRadioImpl) _then) + : super(_value, _then); + + /// Create a copy of MiraiRadio + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? radioType = null, + Object? value = freezed, + Object? onChanged = freezed, + Object? mouseCursor = freezed, + Object? toggleable = null, + Object? activeColor = freezed, + Object? inactiveColor = freezed, + Object? fillColor = freezed, + Object? focusColor = freezed, + Object? hoverColor = freezed, + Object? overlayColor = freezed, + Object? splashRadius = freezed, + Object? materialTapTargetSize = freezed, + Object? visualDensity = freezed, + Object? autofocus = null, + Object? useCheckmarkStyle = null, + Object? useCupertinoCheckmarkStyle = null, + }) { + return _then(_$MiraiRadioImpl( + radioType: null == radioType + ? _value.radioType + : radioType // ignore: cast_nullable_to_non_nullable + as MiraiRadioType, + value: freezed == value + ? _value.value + : value // ignore: cast_nullable_to_non_nullable + as dynamic, + onChanged: freezed == onChanged + ? _value._onChanged + : onChanged // ignore: cast_nullable_to_non_nullable + as Map?, + mouseCursor: freezed == mouseCursor + ? _value.mouseCursor + : mouseCursor // ignore: cast_nullable_to_non_nullable + as MiraiMouseCursor?, + toggleable: null == toggleable + ? _value.toggleable + : toggleable // ignore: cast_nullable_to_non_nullable + as bool, + activeColor: freezed == activeColor + ? _value.activeColor + : activeColor // ignore: cast_nullable_to_non_nullable + as String?, + inactiveColor: freezed == inactiveColor + ? _value.inactiveColor + : inactiveColor // ignore: cast_nullable_to_non_nullable + as String?, + fillColor: freezed == fillColor + ? _value.fillColor + : fillColor // ignore: cast_nullable_to_non_nullable + as String?, + focusColor: freezed == focusColor + ? _value.focusColor + : focusColor // ignore: cast_nullable_to_non_nullable + as String?, + hoverColor: freezed == hoverColor + ? _value.hoverColor + : hoverColor // ignore: cast_nullable_to_non_nullable + as String?, + overlayColor: freezed == overlayColor + ? _value.overlayColor + : overlayColor // ignore: cast_nullable_to_non_nullable + as String?, + splashRadius: freezed == splashRadius + ? _value.splashRadius + : splashRadius // ignore: cast_nullable_to_non_nullable + as double?, + materialTapTargetSize: freezed == materialTapTargetSize + ? _value.materialTapTargetSize + : materialTapTargetSize // ignore: cast_nullable_to_non_nullable + as MaterialTapTargetSize?, + visualDensity: freezed == visualDensity + ? _value.visualDensity + : visualDensity // ignore: cast_nullable_to_non_nullable + as MiraiVisualDensity?, + autofocus: null == autofocus + ? _value.autofocus + : autofocus // ignore: cast_nullable_to_non_nullable + as bool, + useCheckmarkStyle: null == useCheckmarkStyle + ? _value.useCheckmarkStyle + : useCheckmarkStyle // ignore: cast_nullable_to_non_nullable + as bool, + useCupertinoCheckmarkStyle: null == useCupertinoCheckmarkStyle + ? _value.useCupertinoCheckmarkStyle + : useCupertinoCheckmarkStyle // ignore: cast_nullable_to_non_nullable + as bool, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$MiraiRadioImpl implements _MiraiRadio { + const _$MiraiRadioImpl( + {this.radioType = MiraiRadioType.material, + this.value, + final Map? onChanged, + this.mouseCursor, + this.toggleable = false, + this.activeColor, + this.inactiveColor, + this.fillColor, + this.focusColor, + this.hoverColor, + this.overlayColor, + this.splashRadius, + this.materialTapTargetSize, + this.visualDensity, + this.autofocus = false, + this.useCheckmarkStyle = false, + this.useCupertinoCheckmarkStyle = false}) + : _onChanged = onChanged; + + factory _$MiraiRadioImpl.fromJson(Map json) => + _$$MiraiRadioImplFromJson(json); + + @override + @JsonKey() + final MiraiRadioType radioType; + @override + final dynamic value; + final Map? _onChanged; + @override + Map? get onChanged { + final value = _onChanged; + if (value == null) return null; + if (_onChanged is EqualUnmodifiableMapView) return _onChanged; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); + } + + @override + final MiraiMouseCursor? mouseCursor; + @override + @JsonKey() + final bool toggleable; + @override + final String? activeColor; + @override + final String? inactiveColor; + @override + final String? fillColor; + @override + final String? focusColor; + @override + final String? hoverColor; + @override + final String? overlayColor; + @override + final double? splashRadius; + @override + final MaterialTapTargetSize? materialTapTargetSize; + @override + final MiraiVisualDensity? visualDensity; + @override + @JsonKey() + final bool autofocus; + @override + @JsonKey() + final bool useCheckmarkStyle; + @override + @JsonKey() + final bool useCupertinoCheckmarkStyle; + + @override + String toString() { + return 'MiraiRadio(radioType: $radioType, value: $value, onChanged: $onChanged, mouseCursor: $mouseCursor, toggleable: $toggleable, activeColor: $activeColor, inactiveColor: $inactiveColor, fillColor: $fillColor, focusColor: $focusColor, hoverColor: $hoverColor, overlayColor: $overlayColor, splashRadius: $splashRadius, materialTapTargetSize: $materialTapTargetSize, visualDensity: $visualDensity, autofocus: $autofocus, useCheckmarkStyle: $useCheckmarkStyle, useCupertinoCheckmarkStyle: $useCupertinoCheckmarkStyle)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$MiraiRadioImpl && + (identical(other.radioType, radioType) || + other.radioType == radioType) && + const DeepCollectionEquality().equals(other.value, value) && + const DeepCollectionEquality() + .equals(other._onChanged, _onChanged) && + (identical(other.mouseCursor, mouseCursor) || + other.mouseCursor == mouseCursor) && + (identical(other.toggleable, toggleable) || + other.toggleable == toggleable) && + (identical(other.activeColor, activeColor) || + other.activeColor == activeColor) && + (identical(other.inactiveColor, inactiveColor) || + other.inactiveColor == inactiveColor) && + (identical(other.fillColor, fillColor) || + other.fillColor == fillColor) && + (identical(other.focusColor, focusColor) || + other.focusColor == focusColor) && + (identical(other.hoverColor, hoverColor) || + other.hoverColor == hoverColor) && + (identical(other.overlayColor, overlayColor) || + other.overlayColor == overlayColor) && + (identical(other.splashRadius, splashRadius) || + other.splashRadius == splashRadius) && + (identical(other.materialTapTargetSize, materialTapTargetSize) || + other.materialTapTargetSize == materialTapTargetSize) && + (identical(other.visualDensity, visualDensity) || + other.visualDensity == visualDensity) && + (identical(other.autofocus, autofocus) || + other.autofocus == autofocus) && + (identical(other.useCheckmarkStyle, useCheckmarkStyle) || + other.useCheckmarkStyle == useCheckmarkStyle) && + (identical(other.useCupertinoCheckmarkStyle, + useCupertinoCheckmarkStyle) || + other.useCupertinoCheckmarkStyle == + useCupertinoCheckmarkStyle)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + radioType, + const DeepCollectionEquality().hash(value), + const DeepCollectionEquality().hash(_onChanged), + mouseCursor, + toggleable, + activeColor, + inactiveColor, + fillColor, + focusColor, + hoverColor, + overlayColor, + splashRadius, + materialTapTargetSize, + visualDensity, + autofocus, + useCheckmarkStyle, + useCupertinoCheckmarkStyle); + + /// Create a copy of MiraiRadio + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$MiraiRadioImplCopyWith<_$MiraiRadioImpl> get copyWith => + __$$MiraiRadioImplCopyWithImpl<_$MiraiRadioImpl>(this, _$identity); + + @override + Map toJson() { + return _$$MiraiRadioImplToJson( + this, + ); + } +} + +abstract class _MiraiRadio implements MiraiRadio { + const factory _MiraiRadio( + {final MiraiRadioType radioType, + final dynamic value, + final Map? onChanged, + final MiraiMouseCursor? mouseCursor, + final bool toggleable, + final String? activeColor, + final String? inactiveColor, + final String? fillColor, + final String? focusColor, + final String? hoverColor, + final String? overlayColor, + final double? splashRadius, + final MaterialTapTargetSize? materialTapTargetSize, + final MiraiVisualDensity? visualDensity, + final bool autofocus, + final bool useCheckmarkStyle, + final bool useCupertinoCheckmarkStyle}) = _$MiraiRadioImpl; + + factory _MiraiRadio.fromJson(Map json) = + _$MiraiRadioImpl.fromJson; + + @override + MiraiRadioType get radioType; + @override + dynamic get value; + @override + Map? get onChanged; + @override + MiraiMouseCursor? get mouseCursor; + @override + bool get toggleable; + @override + String? get activeColor; + @override + String? get inactiveColor; + @override + String? get fillColor; + @override + String? get focusColor; + @override + String? get hoverColor; + @override + String? get overlayColor; + @override + double? get splashRadius; + @override + MaterialTapTargetSize? get materialTapTargetSize; + @override + MiraiVisualDensity? get visualDensity; + @override + bool get autofocus; + @override + bool get useCheckmarkStyle; + @override + bool get useCupertinoCheckmarkStyle; + + /// Create a copy of MiraiRadio + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$MiraiRadioImplCopyWith<_$MiraiRadioImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/packages/mirai/lib/src/parsers/mirai_radio/mirai_radio.g.dart b/packages/mirai/lib/src/parsers/mirai_radio/mirai_radio.g.dart new file mode 100644 index 00000000..03700449 --- /dev/null +++ b/packages/mirai/lib/src/parsers/mirai_radio/mirai_radio.g.dart @@ -0,0 +1,108 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'mirai_radio.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$MiraiRadioImpl _$$MiraiRadioImplFromJson(Map json) => + _$MiraiRadioImpl( + radioType: + $enumDecodeNullable(_$MiraiRadioTypeEnumMap, json['radioType']) ?? + MiraiRadioType.material, + value: json['value'], + onChanged: json['onChanged'] as Map?, + mouseCursor: + $enumDecodeNullable(_$MiraiMouseCursorEnumMap, json['mouseCursor']), + toggleable: json['toggleable'] as bool? ?? false, + activeColor: json['activeColor'] as String?, + inactiveColor: json['inactiveColor'] as String?, + fillColor: json['fillColor'] as String?, + focusColor: json['focusColor'] as String?, + hoverColor: json['hoverColor'] as String?, + overlayColor: json['overlayColor'] as String?, + splashRadius: (json['splashRadius'] as num?)?.toDouble(), + materialTapTargetSize: $enumDecodeNullable( + _$MaterialTapTargetSizeEnumMap, json['materialTapTargetSize']), + visualDensity: json['visualDensity'] == null + ? null + : MiraiVisualDensity.fromJson( + json['visualDensity'] as Map), + autofocus: json['autofocus'] as bool? ?? false, + useCheckmarkStyle: json['useCheckmarkStyle'] as bool? ?? false, + useCupertinoCheckmarkStyle: + json['useCupertinoCheckmarkStyle'] as bool? ?? false, + ); + +Map _$$MiraiRadioImplToJson(_$MiraiRadioImpl instance) => + { + 'radioType': _$MiraiRadioTypeEnumMap[instance.radioType]!, + 'value': instance.value, + 'onChanged': instance.onChanged, + 'mouseCursor': _$MiraiMouseCursorEnumMap[instance.mouseCursor], + 'toggleable': instance.toggleable, + 'activeColor': instance.activeColor, + 'inactiveColor': instance.inactiveColor, + 'fillColor': instance.fillColor, + 'focusColor': instance.focusColor, + 'hoverColor': instance.hoverColor, + 'overlayColor': instance.overlayColor, + 'splashRadius': instance.splashRadius, + 'materialTapTargetSize': + _$MaterialTapTargetSizeEnumMap[instance.materialTapTargetSize], + 'visualDensity': instance.visualDensity, + 'autofocus': instance.autofocus, + 'useCheckmarkStyle': instance.useCheckmarkStyle, + 'useCupertinoCheckmarkStyle': instance.useCupertinoCheckmarkStyle, + }; + +const _$MiraiRadioTypeEnumMap = { + MiraiRadioType.adaptive: 'adaptive', + MiraiRadioType.cupertino: 'cupertino', + MiraiRadioType.material: 'material', +}; + +const _$MiraiMouseCursorEnumMap = { + MiraiMouseCursor.none: 'none', + MiraiMouseCursor.basic: 'basic', + MiraiMouseCursor.click: 'click', + MiraiMouseCursor.forbidden: 'forbidden', + MiraiMouseCursor.wait: 'wait', + MiraiMouseCursor.progress: 'progress', + MiraiMouseCursor.contextMenu: 'contextMenu', + MiraiMouseCursor.help: 'help', + MiraiMouseCursor.text: 'text', + MiraiMouseCursor.verticalText: 'verticalText', + MiraiMouseCursor.cell: 'cell', + MiraiMouseCursor.precise: 'precise', + MiraiMouseCursor.move: 'move', + MiraiMouseCursor.grab: 'grab', + MiraiMouseCursor.grabbing: 'grabbing', + MiraiMouseCursor.noDrop: 'noDrop', + MiraiMouseCursor.alias: 'alias', + MiraiMouseCursor.copy: 'copy', + MiraiMouseCursor.disappearing: 'disappearing', + MiraiMouseCursor.allScroll: 'allScroll', + MiraiMouseCursor.resizeLeftRight: 'resizeLeftRight', + MiraiMouseCursor.resizeUpDown: 'resizeUpDown', + MiraiMouseCursor.resizeUpLeftDownRight: 'resizeUpLeftDownRight', + MiraiMouseCursor.resizeUpRightDownLeft: 'resizeUpRightDownLeft', + MiraiMouseCursor.resizeUp: 'resizeUp', + MiraiMouseCursor.resizeDown: 'resizeDown', + MiraiMouseCursor.resizeLeft: 'resizeLeft', + MiraiMouseCursor.resizeRight: 'resizeRight', + MiraiMouseCursor.resizeUpLeft: 'resizeUpLeft', + MiraiMouseCursor.resizeUpRight: 'resizeUpRight', + MiraiMouseCursor.resizeDownLeft: 'resizeDownLeft', + MiraiMouseCursor.resizeDownRight: 'resizeDownRight', + MiraiMouseCursor.resizeColumn: 'resizeColumn', + MiraiMouseCursor.resizeRow: 'resizeRow', + MiraiMouseCursor.zoomIn: 'zoomIn', + MiraiMouseCursor.zoomOut: 'zoomOut', +}; + +const _$MaterialTapTargetSizeEnumMap = { + MaterialTapTargetSize.padded: 'padded', + MaterialTapTargetSize.shrinkWrap: 'shrinkWrap', +}; diff --git a/packages/mirai/lib/src/parsers/mirai_radio/mirai_radio_parser.dart b/packages/mirai/lib/src/parsers/mirai_radio/mirai_radio_parser.dart new file mode 100644 index 00000000..a82acfd4 --- /dev/null +++ b/packages/mirai/lib/src/parsers/mirai_radio/mirai_radio_parser.dart @@ -0,0 +1,150 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:mirai/mirai.dart'; +import 'package:mirai/src/parsers/mirai_radio_group/mirai_radio_group_scope.dart'; + +import '../../utils/widget_type.dart'; + +class MiraiRadioParser extends MiraiParser { + const MiraiRadioParser(); + + @override + MiraiRadio getModel(Map json) => MiraiRadio.fromJson(json); + + @override + String get type => WidgetType.radio.name; + + @override + Widget parse(BuildContext context, MiraiRadio model) { + return _RadioWidget( + model: model, + radioGroupScope: MiraiRadioGroupScope.of(context), + ); + } +} + +class _RadioWidget extends StatelessWidget { + const _RadioWidget({ + required this.radioGroupScope, + required this.model, + }); + + final MiraiRadioGroupScope? radioGroupScope; + final MiraiRadio model; + + @override + Widget build(BuildContext context) { + final FocusNode focusNode = FocusNode(); + + switch (model.radioType) { + case MiraiRadioType.cupertino: + return _buildCupertinoRadio(context, model, focusNode); + case MiraiRadioType.adaptive: + return _buildAdaptiveRadio(context, model, focusNode); + case MiraiRadioType.material: + return _buildMaterialRadio(context, model, focusNode); + } + } + + void _onChanged(dynamic value, BuildContext context) { + if (model.onChanged != null) { + Mirai.onCallFromJson(model.onChanged, context); + } + radioGroupScope?.onSelect(value); + } + + Widget _buildCupertinoRadio( + BuildContext context, + MiraiRadio model, + FocusNode focusNode, + ) { + return ValueListenableBuilder( + valueListenable: radioGroupScope!.radioGroupValue, + builder: (context, value, child) { + return CupertinoRadio( + value: model.value, + groupValue: value, + onChanged: (dynamic value) { + _onChanged(value, context); + }, + mouseCursor: model.mouseCursor?.value, + toggleable: model.toggleable, + activeColor: model.activeColor.toColor(context), + inactiveColor: model.inactiveColor?.toColor(context), + fillColor: model.fillColor?.toColor(context), + focusColor: model.focusColor?.toColor(context), + focusNode: focusNode, + autofocus: model.autofocus, + useCheckmarkStyle: model.useCheckmarkStyle, + ); + }, + ); + } + + Widget _buildAdaptiveRadio( + BuildContext context, + MiraiRadio model, + FocusNode focusNode, + ) { + return ValueListenableBuilder( + valueListenable: radioGroupScope!.radioGroupValue, + builder: (context, value, child) { + return Radio.adaptive( + value: model.value, + groupValue: value, + onChanged: (dynamic value) { + _onChanged(value, context); + }, + mouseCursor: model.mouseCursor?.value, + toggleable: model.toggleable, + activeColor: model.activeColor?.toColor(context), + fillColor: WidgetStateProperty.all(model.fillColor?.toColor(context)), + focusColor: model.focusColor?.toColor(context), + hoverColor: model.hoverColor?.toColor(context), + overlayColor: WidgetStateProperty.all( + model.overlayColor?.toColor(context), + ), + splashRadius: model.splashRadius, + materialTapTargetSize: model.materialTapTargetSize, + visualDensity: model.visualDensity?.parse, + focusNode: focusNode, + autofocus: model.autofocus, + useCupertinoCheckmarkStyle: model.useCupertinoCheckmarkStyle, + ); + }, + ); + } + + Widget _buildMaterialRadio( + BuildContext context, + MiraiRadio model, + FocusNode focusNode, + ) { + return ValueListenableBuilder( + valueListenable: radioGroupScope!.radioGroupValue, + builder: (context, value, child) { + return Radio( + value: model.value, + groupValue: value, + onChanged: (dynamic value) { + _onChanged(value, context); + }, + mouseCursor: model.mouseCursor?.value, + toggleable: model.toggleable, + activeColor: model.activeColor.toColor(context), + fillColor: WidgetStateProperty.all(model.fillColor?.toColor(context)), + focusColor: model.focusColor?.toColor(context), + hoverColor: model.hoverColor?.toColor(context), + overlayColor: WidgetStateProperty.all( + model.overlayColor?.toColor(context), + ), + splashRadius: model.splashRadius, + materialTapTargetSize: model.materialTapTargetSize, + visualDensity: model.visualDensity?.parse, + focusNode: focusNode, + autofocus: model.autofocus, + ); + }, + ); + } +} diff --git a/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group.dart b/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group.dart new file mode 100644 index 00000000..694b7bc4 --- /dev/null +++ b/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group.dart @@ -0,0 +1,20 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +export 'package:mirai/src/parsers/mirai_radio_group/mirai_radio_group_parser.dart'; + +part 'mirai_radio_group.freezed.dart'; +part 'mirai_radio_group.g.dart'; + +enum RadioAlignment { vertical, horizontal } + +@freezed +class MiraiRadioGroup with _$MiraiRadioGroup { + const factory MiraiRadioGroup({ + String? id, + dynamic groupValue, + Map? child, + }) = _MiraiRadioGroup; + + factory MiraiRadioGroup.fromJson(Map json) => + _$MiraiRadioGroupFromJson(json); +} diff --git a/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group.freezed.dart b/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group.freezed.dart new file mode 100644 index 00000000..666315f2 --- /dev/null +++ b/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group.freezed.dart @@ -0,0 +1,214 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'mirai_radio_group.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +MiraiRadioGroup _$MiraiRadioGroupFromJson(Map json) { + return _MiraiRadioGroup.fromJson(json); +} + +/// @nodoc +mixin _$MiraiRadioGroup { + String? get id => throw _privateConstructorUsedError; + dynamic get groupValue => throw _privateConstructorUsedError; + Map? get child => throw _privateConstructorUsedError; + + /// Serializes this MiraiRadioGroup to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of MiraiRadioGroup + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $MiraiRadioGroupCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $MiraiRadioGroupCopyWith<$Res> { + factory $MiraiRadioGroupCopyWith( + MiraiRadioGroup value, $Res Function(MiraiRadioGroup) then) = + _$MiraiRadioGroupCopyWithImpl<$Res, MiraiRadioGroup>; + @useResult + $Res call({String? id, dynamic groupValue, Map? child}); +} + +/// @nodoc +class _$MiraiRadioGroupCopyWithImpl<$Res, $Val extends MiraiRadioGroup> + implements $MiraiRadioGroupCopyWith<$Res> { + _$MiraiRadioGroupCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of MiraiRadioGroup + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? groupValue = freezed, + Object? child = freezed, + }) { + return _then(_value.copyWith( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + groupValue: freezed == groupValue + ? _value.groupValue + : groupValue // ignore: cast_nullable_to_non_nullable + as dynamic, + child: freezed == child + ? _value.child + : child // ignore: cast_nullable_to_non_nullable + as Map?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$MiraiRadioGroupImplCopyWith<$Res> + implements $MiraiRadioGroupCopyWith<$Res> { + factory _$$MiraiRadioGroupImplCopyWith(_$MiraiRadioGroupImpl value, + $Res Function(_$MiraiRadioGroupImpl) then) = + __$$MiraiRadioGroupImplCopyWithImpl<$Res>; + @override + @useResult + $Res call({String? id, dynamic groupValue, Map? child}); +} + +/// @nodoc +class __$$MiraiRadioGroupImplCopyWithImpl<$Res> + extends _$MiraiRadioGroupCopyWithImpl<$Res, _$MiraiRadioGroupImpl> + implements _$$MiraiRadioGroupImplCopyWith<$Res> { + __$$MiraiRadioGroupImplCopyWithImpl( + _$MiraiRadioGroupImpl _value, $Res Function(_$MiraiRadioGroupImpl) _then) + : super(_value, _then); + + /// Create a copy of MiraiRadioGroup + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? id = freezed, + Object? groupValue = freezed, + Object? child = freezed, + }) { + return _then(_$MiraiRadioGroupImpl( + id: freezed == id + ? _value.id + : id // ignore: cast_nullable_to_non_nullable + as String?, + groupValue: freezed == groupValue + ? _value.groupValue + : groupValue // ignore: cast_nullable_to_non_nullable + as dynamic, + child: freezed == child + ? _value._child + : child // ignore: cast_nullable_to_non_nullable + as Map?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$MiraiRadioGroupImpl implements _MiraiRadioGroup { + const _$MiraiRadioGroupImpl( + {this.id, this.groupValue, final Map? child}) + : _child = child; + + factory _$MiraiRadioGroupImpl.fromJson(Map json) => + _$$MiraiRadioGroupImplFromJson(json); + + @override + final String? id; + @override + final dynamic groupValue; + final Map? _child; + @override + Map? get child { + final value = _child; + if (value == null) return null; + if (_child is EqualUnmodifiableMapView) return _child; + // ignore: implicit_dynamic_type + return EqualUnmodifiableMapView(value); + } + + @override + String toString() { + return 'MiraiRadioGroup(id: $id, groupValue: $groupValue, child: $child)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$MiraiRadioGroupImpl && + (identical(other.id, id) || other.id == id) && + const DeepCollectionEquality() + .equals(other.groupValue, groupValue) && + const DeepCollectionEquality().equals(other._child, _child)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash( + runtimeType, + id, + const DeepCollectionEquality().hash(groupValue), + const DeepCollectionEquality().hash(_child)); + + /// Create a copy of MiraiRadioGroup + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$MiraiRadioGroupImplCopyWith<_$MiraiRadioGroupImpl> get copyWith => + __$$MiraiRadioGroupImplCopyWithImpl<_$MiraiRadioGroupImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$MiraiRadioGroupImplToJson( + this, + ); + } +} + +abstract class _MiraiRadioGroup implements MiraiRadioGroup { + const factory _MiraiRadioGroup( + {final String? id, + final dynamic groupValue, + final Map? child}) = _$MiraiRadioGroupImpl; + + factory _MiraiRadioGroup.fromJson(Map json) = + _$MiraiRadioGroupImpl.fromJson; + + @override + String? get id; + @override + dynamic get groupValue; + @override + Map? get child; + + /// Create a copy of MiraiRadioGroup + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$MiraiRadioGroupImplCopyWith<_$MiraiRadioGroupImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group.g.dart b/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group.g.dart new file mode 100644 index 00000000..8fa3718e --- /dev/null +++ b/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group.g.dart @@ -0,0 +1,23 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'mirai_radio_group.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$MiraiRadioGroupImpl _$$MiraiRadioGroupImplFromJson( + Map json) => + _$MiraiRadioGroupImpl( + id: json['id'] as String?, + groupValue: json['groupValue'], + child: json['child'] as Map?, + ); + +Map _$$MiraiRadioGroupImplToJson( + _$MiraiRadioGroupImpl instance) => + { + 'id': instance.id, + 'groupValue': instance.groupValue, + 'child': instance.child, + }; diff --git a/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group_parser.dart b/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group_parser.dart new file mode 100644 index 00000000..65d84d6e --- /dev/null +++ b/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group_parser.dart @@ -0,0 +1,74 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:mirai/mirai.dart'; +import 'package:mirai/src/parsers/mirai_radio_group/mirai_radio_group_scope.dart'; +import 'package:mirai/src/utils/widget_type.dart'; + +import '../mirai_form/mirai_form_scope.dart'; + +class MiraiRadioGroupParser extends MiraiParser { + const MiraiRadioGroupParser(); + + @override + String get type => WidgetType.radioGroup.name; + + @override + MiraiRadioGroup getModel(Map json) => + MiraiRadioGroup.fromJson(json); + + @override + Widget parse(BuildContext context, MiraiRadioGroup model) { + return _RadioGroupWidget( + model: model, + formScope: MiraiFormScope.of(context), + ); + } +} + +class _RadioGroupWidget extends StatefulWidget { + const _RadioGroupWidget({ + required this.model, + required this.formScope, + }); + + final MiraiRadioGroup model; + final MiraiFormScope? formScope; + + @override + State<_RadioGroupWidget> createState() => __RadioGroupWidgetState(); +} + +class __RadioGroupWidgetState extends State<_RadioGroupWidget> { + late ValueNotifier groupValue; + + @override + void initState() { + super.initState(); + groupValue = ValueNotifier(widget.model.groupValue); + _saveValueInFormData(); + } + + void _updateGroupValue(dynamic value) { + groupValue.value = value; + _saveValueInFormData(); + } + + void _saveValueInFormData() { + if (widget.model.id != null) { + widget.formScope?.formData[widget.model.id!] = groupValue; + } + } + + @override + Widget build(BuildContext context) { + final MiraiRadioGroup model = widget.model; + + return MiraiRadioGroupScope( + radioGroupValue: groupValue, + onSelect: _updateGroupValue, + child: Builder(builder: (context) { + return Mirai.fromJson(model.child, context) ?? const SizedBox(); + }), + ); + } +} diff --git a/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group_scope.dart b/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group_scope.dart new file mode 100644 index 00000000..921a13a5 --- /dev/null +++ b/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group_scope.dart @@ -0,0 +1,33 @@ +import 'package:flutter/widgets.dart'; + +import '../../utils/log.dart'; + +class MiraiRadioGroupScope extends InheritedWidget { + const MiraiRadioGroupScope({ + super.key, + required this.radioGroupValue, + required this.onSelect, + required super.child, + }); + + final ValueNotifier radioGroupValue; + final Function(dynamic value) onSelect; + + static MiraiRadioGroupScope? of(BuildContext context) { + final MiraiRadioGroupScope? result = + context.dependOnInheritedWidgetOfExactType(); + + if (result != null) { + return result; + } else { + Log.e( + "MiraiRadioGroupScope.of() called with a context that does not contain a MiraiRadioGroupScope."); + return null; + } + } + + @override + bool updateShouldNotify(covariant InheritedWidget oldWidget) { + return oldWidget.child != child; + } +} diff --git a/packages/mirai/lib/src/parsers/parsers.dart b/packages/mirai/lib/src/parsers/parsers.dart index c5d7220b..5db31295 100644 --- a/packages/mirai/lib/src/parsers/parsers.dart +++ b/packages/mirai/lib/src/parsers/parsers.dart @@ -78,3 +78,5 @@ export 'package:mirai/src/parsers/mirai_text_form_field/mirai_text_form_field.da export 'package:mirai/src/parsers/mirai_text_style/mirai_text_style.dart'; export 'package:mirai/src/parsers/mirai_theme/mirai_theme.dart'; export 'package:mirai/src/parsers/mirai_wrap/mirai_wrap.dart'; +export 'package:mirai/src/parsers/mirai_radio/mirai_radio.dart'; +export 'package:mirai/src/parsers/mirai_radio_group/mirai_radio_group.dart'; diff --git a/packages/mirai/lib/src/utils/widget_type.dart b/packages/mirai/lib/src/utils/widget_type.dart index 1277b0e1..0661c8bf 100644 --- a/packages/mirai/lib/src/utils/widget_type.dart +++ b/packages/mirai/lib/src/utils/widget_type.dart @@ -53,5 +53,7 @@ enum WidgetType { tableCell, carouselView, coloredBox, - divider + divider, + radio, + radioGroup, } diff --git a/website/docs/widgets/radio_group.md b/website/docs/widgets/radio_group.md new file mode 100644 index 00000000..eeae7208 --- /dev/null +++ b/website/docs/widgets/radio_group.md @@ -0,0 +1,100 @@ +# RadioGroup + +Mirai radioGroup allows you to build the Flutter Radio widgets using JSON. +To know more about the container widget in Flutter, refer to the [official documentation](https://api.flutter.dev/flutter/material/Radio-class.html). + +## RadioGroup Properties + +| Property | Type | Description | +| --- |-------------------|---------------------------------------------------| +| id | `String` | The id will be used to save the selected value of radio. | +| groupValue | `dynamic` | The currently selected value for a group of radio buttons. | +| child | `Map` | The child of radioGroup. | + +## Radio Properties + +| Property | Type | Description | +| --- |-------------------|---------------------------------------------------| +| radioType | `MiraiRadioType` | The type of radio. | +| value | `dynamic` | The value represented by this radio. | +| onChanged | `Map` | The action needs trigger when radio value change. | +| mouseCursor | `MiraiMouseCursor` | The cursor for a mouse pointer when it enters or is hovering over the radio. | +| toggleable | `bool` | Set to true if this wanted to deselect when selected. | +| activeColor | `String` | The color to use when this radio button is selected. | +| inactiveColor | `String` | The color to use when this radio button is not selected. | +| fillColor | `String` | The color that fills the radio button, in all WidgetStates. | +| focusColor | `String` | The color for the radio's Material when it has the input focus. | +| hoverColor | `String` | The color for the radio's Material when a pointer is hovering over it. | +| overlayColor | `String` | The color for the radio's Material. | +| splashRadius | `double` | The splash radius of the circular Material ink response. | +| materialTapTargetSize | `MaterialTapTargetSize` | Configures the minimum size of the tap target. | +| visualDensity | `MiraiVisualDensity` | Defines how compact the radio's layout will be. | +| autofocus | `bool` | True if this widget will be selected as the initial focus when no other node in its scope is currently focused. | +| useCheckmarkStyle | `bool` | Controls whether the radio displays in a checkbox style or the default iOS radio style. | +| useCupertinoCheckmarkStyle | `bool` | Controls whether the checkmark style is used in an iOS-style radio. | + + +## Example JSON + +```json +{ + "type": "radioGroup", + "child": { + "type": "column", + "children": [ + { + "type": "listTile", + "leading": { + "type": "radio", + "radioType": "adaptive", + "value": "1", + "groupValue": "1" + }, + "title": { + "type": "text", + "data": "Male", + "align": "center", + "style": { + "fontSize": 21 + } + } + }, + { + "type": "listTile", + "leading": { + "type": "radio", + "radioType": "adaptive", + "value": "2", + "groupValue": "1" + }, + "title": { + "type": "text", + "data": "Female", + "align": "center", + "style": { + "fontSize": 21 + } + } + }, + { + "type": "listTile", + "leading": { + "type": "radio", + "radioType": "adaptive", + "value": "3", + "groupValue": "1" + }, + "title": { + "type": "text", + "data": "Other", + "align": "center", + "style": { + "fontSize": 21 + } + } + } + ] + } +} +``` + From c9adab632c3c53b3ad951c42a31c45ef736f5a5a Mon Sep 17 00:00:00 2001 From: ishanvaghani Date: Tue, 7 Jan 2025 21:48:28 +0530 Subject: [PATCH 2/4] Disposed value notifier --- .../parsers/mirai_radio_group/mirai_radio_group_parser.dart | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group_parser.dart b/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group_parser.dart index 65d84d6e..72262cf0 100644 --- a/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group_parser.dart +++ b/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group_parser.dart @@ -48,6 +48,12 @@ class __RadioGroupWidgetState extends State<_RadioGroupWidget> { _saveValueInFormData(); } + @override + void dispose() { + groupValue.dispose(); + super.dispose(); + } + void _updateGroupValue(dynamic value) { groupValue.value = value; _saveValueInFormData(); From 933eae279278a9620166a9bfeae4f874832749d2 Mon Sep 17 00:00:00 2001 From: ishanvaghani Date: Wed, 8 Jan 2025 09:15:23 +0530 Subject: [PATCH 3/4] Fixed bug --- .../src/parsers/mirai_radio_group/mirai_radio_group_parser.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group_parser.dart b/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group_parser.dart index 72262cf0..9565d141 100644 --- a/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group_parser.dart +++ b/packages/mirai/lib/src/parsers/mirai_radio_group/mirai_radio_group_parser.dart @@ -61,7 +61,7 @@ class __RadioGroupWidgetState extends State<_RadioGroupWidget> { void _saveValueInFormData() { if (widget.model.id != null) { - widget.formScope?.formData[widget.model.id!] = groupValue; + widget.formScope?.formData[widget.model.id!] = groupValue.value; } } From 7ddaff85c8b23a2c4d3f0b0ffc1d3868bcefc20e Mon Sep 17 00:00:00 2001 From: ishanvaghani Date: Wed, 8 Jan 2025 20:39:50 +0530 Subject: [PATCH 4/4] Wrapped radioGroup inside form --- .../assets/json/radio_example.json | 101 +++++++++--------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/examples/mirai_gallery/assets/json/radio_example.json b/examples/mirai_gallery/assets/json/radio_example.json index 0c61ecbf..4788ec3e 100644 --- a/examples/mirai_gallery/assets/json/radio_example.json +++ b/examples/mirai_gallery/assets/json/radio_example.json @@ -8,62 +8,65 @@ } }, "body": { - "type": "radioGroup", + "type": "form", "child": { - "type": "column", - "children": [ - { - "type": "listTile", - "leading": { - "type": "radio", - "radioType": "adaptive", - "value": "1", - "groupValue": "1" - }, - "title": { - "type": "text", - "data": "Male", - "align": "center", - "style": { - "fontSize": 21 + "type": "radioGroup", + "child": { + "type": "column", + "children": [ + { + "type": "listTile", + "leading": { + "type": "radio", + "radioType": "adaptive", + "value": "1", + "groupValue": "1" + }, + "title": { + "type": "text", + "data": "Male", + "align": "center", + "style": { + "fontSize": 21 + } } - } - }, - { - "type": "listTile", - "leading": { - "type": "radio", - "radioType": "adaptive", - "value": "2", - "groupValue": "1" }, - "title": { - "type": "text", - "data": "Female", - "align": "center", - "style": { - "fontSize": 21 + { + "type": "listTile", + "leading": { + "type": "radio", + "radioType": "adaptive", + "value": "2", + "groupValue": "1" + }, + "title": { + "type": "text", + "data": "Female", + "align": "center", + "style": { + "fontSize": 21 + } } - } - }, - { - "type": "listTile", - "leading": { - "type": "radio", - "radioType": "adaptive", - "value": "3", - "groupValue": "1" }, - "title": { - "type": "text", - "data": "Other", - "align": "center", - "style": { - "fontSize": 21 + { + "type": "listTile", + "leading": { + "type": "radio", + "radioType": "adaptive", + "value": "3", + "groupValue": "1" + }, + "title": { + "type": "text", + "data": "Other", + "align": "center", + "style": { + "fontSize": 21 + } } } - } - ] + ] + } } } } \ No newline at end of file