diff --git a/examples/mirai_gallery/assets/json/home_screen.json b/examples/mirai_gallery/assets/json/home_screen.json index fb077a1c..8dd0463f 100644 --- a/examples/mirai_gallery/assets/json/home_screen.json +++ b/examples/mirai_gallery/assets/json/home_screen.json @@ -1555,6 +1555,41 @@ } } }, + + { + "type": "listTile", + "leading": { + "type": "icon", + "iconType": "material", + "icon": "apartment" + }, + + "title": { + "type": "text", + "data": "Placeholder", + "style": { + "fontSize": 21 + } + }, + "subtitle": { + "type": "text", + "data": "A Material Design Mirai Placeholder widget", + "style": { + "fontSize": 12 + } + }, + "isThreeLine": true, + "onTap": { + "actionType": "navigate", + "navigationStyle": "push", + "widgetJson": { + "type": "exampleScreen", + "assetPath": "assets/json/placeholder_example.json" + } + } + }, + + { "type": "listTile", "leading": { diff --git a/examples/mirai_gallery/assets/json/placeholder_example.json b/examples/mirai_gallery/assets/json/placeholder_example.json new file mode 100644 index 00000000..821ff1da --- /dev/null +++ b/examples/mirai_gallery/assets/json/placeholder_example.json @@ -0,0 +1,37 @@ +{ + "type": "scaffold", + "appBar": { + "type": "appBar", + "title": { + "type": "text", + "data": "Placeholder" + } + }, + "body": { + "type": "listView", + "shrinkWrap": true, + "children": [ + { + "type": "sizedBox", + "height": 25 + }, + { + "type": "placeholder", + "color": "#455A64", + "strokeWidth": 2.0, + "fallbackHeight": 400.0, + "fallbackWidth": 400.0 + }, + { + "type": "sizedBox", + "height": 25 + }, + { + "color": "#672BFF", + "type": "placeholder", + "strokeWidth": 5.0, + "fallbackHeight": 100.0 + } + ] + } +} \ 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 b40c0ba2..5388be24 100644 --- a/packages/mirai/lib/src/framework/mirai.dart +++ b/packages/mirai/lib/src/framework/mirai.dart @@ -91,6 +91,7 @@ class Mirai { const MiraiRadioGroupParser(), const MiraiSliderParser(), const MiraiOpacityParser(), + const MiraiPlaceholderParser(), ]; static final _actionParsers = [ diff --git a/packages/mirai/lib/src/parsers/mirai_placeholder/mirai_placeholder.dart b/packages/mirai/lib/src/parsers/mirai_placeholder/mirai_placeholder.dart new file mode 100644 index 00000000..f71034b1 --- /dev/null +++ b/packages/mirai/lib/src/parsers/mirai_placeholder/mirai_placeholder.dart @@ -0,0 +1,20 @@ +import 'package:freezed_annotation/freezed_annotation.dart'; + +export 'package:mirai/src/parsers/mirai_placeholder/mirai_placeholder_parser.dart'; + +part 'mirai_placeholder.freezed.dart'; +part 'mirai_placeholder.g.dart'; + +@freezed +class MiraiPlaceholder with _$MiraiPlaceholder { + const factory MiraiPlaceholder({ + @Default(2.0) double fallbackWidth, + @Default(400.0) double fallbackHeight, + @Default(400.0) double strokeWidth, + @Default('#455A64') String color, + Map? child, + }) = _MiraiPlaceholder; + + factory MiraiPlaceholder.fromJson(Map json) => + _$MiraiPlaceholderFromJson(json); +} diff --git a/packages/mirai/lib/src/parsers/mirai_placeholder/mirai_placeholder.freezed.dart b/packages/mirai/lib/src/parsers/mirai_placeholder/mirai_placeholder.freezed.dart new file mode 100644 index 00000000..7b6a829e --- /dev/null +++ b/packages/mirai/lib/src/parsers/mirai_placeholder/mirai_placeholder.freezed.dart @@ -0,0 +1,265 @@ +// 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_placeholder.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'); + +MiraiPlaceholder _$MiraiPlaceholderFromJson(Map json) { + return _MiraiPlaceholder.fromJson(json); +} + +/// @nodoc +mixin _$MiraiPlaceholder { + double get fallbackWidth => throw _privateConstructorUsedError; + double get fallbackHeight => throw _privateConstructorUsedError; + double get strokeWidth => throw _privateConstructorUsedError; + String get color => throw _privateConstructorUsedError; + Map? get child => throw _privateConstructorUsedError; + + /// Serializes this MiraiPlaceholder to a JSON map. + Map toJson() => throw _privateConstructorUsedError; + + /// Create a copy of MiraiPlaceholder + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + $MiraiPlaceholderCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $MiraiPlaceholderCopyWith<$Res> { + factory $MiraiPlaceholderCopyWith( + MiraiPlaceholder value, $Res Function(MiraiPlaceholder) then) = + _$MiraiPlaceholderCopyWithImpl<$Res, MiraiPlaceholder>; + @useResult + $Res call( + {double fallbackWidth, + double fallbackHeight, + double strokeWidth, + String color, + Map? child}); +} + +/// @nodoc +class _$MiraiPlaceholderCopyWithImpl<$Res, $Val extends MiraiPlaceholder> + implements $MiraiPlaceholderCopyWith<$Res> { + _$MiraiPlaceholderCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + /// Create a copy of MiraiPlaceholder + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? fallbackWidth = null, + Object? fallbackHeight = null, + Object? strokeWidth = null, + Object? color = null, + Object? child = freezed, + }) { + return _then(_value.copyWith( + fallbackWidth: null == fallbackWidth + ? _value.fallbackWidth + : fallbackWidth // ignore: cast_nullable_to_non_nullable + as double, + fallbackHeight: null == fallbackHeight + ? _value.fallbackHeight + : fallbackHeight // ignore: cast_nullable_to_non_nullable + as double, + strokeWidth: null == strokeWidth + ? _value.strokeWidth + : strokeWidth // ignore: cast_nullable_to_non_nullable + as double, + color: null == color + ? _value.color + : color // ignore: cast_nullable_to_non_nullable + as String, + child: freezed == child + ? _value.child + : child // ignore: cast_nullable_to_non_nullable + as Map?, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$MiraiPlaceholderImplCopyWith<$Res> + implements $MiraiPlaceholderCopyWith<$Res> { + factory _$$MiraiPlaceholderImplCopyWith(_$MiraiPlaceholderImpl value, + $Res Function(_$MiraiPlaceholderImpl) then) = + __$$MiraiPlaceholderImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {double fallbackWidth, + double fallbackHeight, + double strokeWidth, + String color, + Map? child}); +} + +/// @nodoc +class __$$MiraiPlaceholderImplCopyWithImpl<$Res> + extends _$MiraiPlaceholderCopyWithImpl<$Res, _$MiraiPlaceholderImpl> + implements _$$MiraiPlaceholderImplCopyWith<$Res> { + __$$MiraiPlaceholderImplCopyWithImpl(_$MiraiPlaceholderImpl _value, + $Res Function(_$MiraiPlaceholderImpl) _then) + : super(_value, _then); + + /// Create a copy of MiraiPlaceholder + /// with the given fields replaced by the non-null parameter values. + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? fallbackWidth = null, + Object? fallbackHeight = null, + Object? strokeWidth = null, + Object? color = null, + Object? child = freezed, + }) { + return _then(_$MiraiPlaceholderImpl( + fallbackWidth: null == fallbackWidth + ? _value.fallbackWidth + : fallbackWidth // ignore: cast_nullable_to_non_nullable + as double, + fallbackHeight: null == fallbackHeight + ? _value.fallbackHeight + : fallbackHeight // ignore: cast_nullable_to_non_nullable + as double, + strokeWidth: null == strokeWidth + ? _value.strokeWidth + : strokeWidth // ignore: cast_nullable_to_non_nullable + as double, + color: null == color + ? _value.color + : color // ignore: cast_nullable_to_non_nullable + as String, + child: freezed == child + ? _value._child + : child // ignore: cast_nullable_to_non_nullable + as Map?, + )); + } +} + +/// @nodoc +@JsonSerializable() +class _$MiraiPlaceholderImpl implements _MiraiPlaceholder { + const _$MiraiPlaceholderImpl( + {this.fallbackWidth = 2.0, + this.fallbackHeight = 400.0, + this.strokeWidth = 400.0, + this.color = '#455A64', + final Map? child}) + : _child = child; + + factory _$MiraiPlaceholderImpl.fromJson(Map json) => + _$$MiraiPlaceholderImplFromJson(json); + + @override + @JsonKey() + final double fallbackWidth; + @override + @JsonKey() + final double fallbackHeight; + @override + @JsonKey() + final double strokeWidth; + @override + @JsonKey() + final String color; + 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 'MiraiPlaceholder(fallbackWidth: $fallbackWidth, fallbackHeight: $fallbackHeight, strokeWidth: $strokeWidth, color: $color, child: $child)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$MiraiPlaceholderImpl && + (identical(other.fallbackWidth, fallbackWidth) || + other.fallbackWidth == fallbackWidth) && + (identical(other.fallbackHeight, fallbackHeight) || + other.fallbackHeight == fallbackHeight) && + (identical(other.strokeWidth, strokeWidth) || + other.strokeWidth == strokeWidth) && + (identical(other.color, color) || other.color == color) && + const DeepCollectionEquality().equals(other._child, _child)); + } + + @JsonKey(includeFromJson: false, includeToJson: false) + @override + int get hashCode => Object.hash(runtimeType, fallbackWidth, fallbackHeight, + strokeWidth, color, const DeepCollectionEquality().hash(_child)); + + /// Create a copy of MiraiPlaceholder + /// with the given fields replaced by the non-null parameter values. + @JsonKey(includeFromJson: false, includeToJson: false) + @override + @pragma('vm:prefer-inline') + _$$MiraiPlaceholderImplCopyWith<_$MiraiPlaceholderImpl> get copyWith => + __$$MiraiPlaceholderImplCopyWithImpl<_$MiraiPlaceholderImpl>( + this, _$identity); + + @override + Map toJson() { + return _$$MiraiPlaceholderImplToJson( + this, + ); + } +} + +abstract class _MiraiPlaceholder implements MiraiPlaceholder { + const factory _MiraiPlaceholder( + {final double fallbackWidth, + final double fallbackHeight, + final double strokeWidth, + final String color, + final Map? child}) = _$MiraiPlaceholderImpl; + + factory _MiraiPlaceholder.fromJson(Map json) = + _$MiraiPlaceholderImpl.fromJson; + + @override + double get fallbackWidth; + @override + double get fallbackHeight; + @override + double get strokeWidth; + @override + String get color; + @override + Map? get child; + + /// Create a copy of MiraiPlaceholder + /// with the given fields replaced by the non-null parameter values. + @override + @JsonKey(includeFromJson: false, includeToJson: false) + _$$MiraiPlaceholderImplCopyWith<_$MiraiPlaceholderImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/packages/mirai/lib/src/parsers/mirai_placeholder/mirai_placeholder.g.dart b/packages/mirai/lib/src/parsers/mirai_placeholder/mirai_placeholder.g.dart new file mode 100644 index 00000000..37472b76 --- /dev/null +++ b/packages/mirai/lib/src/parsers/mirai_placeholder/mirai_placeholder.g.dart @@ -0,0 +1,27 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'mirai_placeholder.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +_$MiraiPlaceholderImpl _$$MiraiPlaceholderImplFromJson( + Map json) => + _$MiraiPlaceholderImpl( + fallbackWidth: (json['fallbackWidth'] as num?)?.toDouble() ?? 2.0, + fallbackHeight: (json['fallbackHeight'] as num?)?.toDouble() ?? 400.0, + strokeWidth: (json['strokeWidth'] as num?)?.toDouble() ?? 400.0, + color: json['color'] as String? ?? '#455A64', + child: json['child'] as Map?, + ); + +Map _$$MiraiPlaceholderImplToJson( + _$MiraiPlaceholderImpl instance) => + { + 'fallbackWidth': instance.fallbackWidth, + 'fallbackHeight': instance.fallbackHeight, + 'strokeWidth': instance.strokeWidth, + 'color': instance.color, + 'child': instance.child, + }; diff --git a/packages/mirai/lib/src/parsers/mirai_placeholder/mirai_placeholder_parser.dart b/packages/mirai/lib/src/parsers/mirai_placeholder/mirai_placeholder_parser.dart new file mode 100644 index 00000000..5d7027be --- /dev/null +++ b/packages/mirai/lib/src/parsers/mirai_placeholder/mirai_placeholder_parser.dart @@ -0,0 +1,28 @@ +import 'package:flutter/material.dart'; +import 'package:mirai/src/framework/framework.dart'; +import 'package:mirai/src/parsers/mirai_placeholder/mirai_placeholder.dart'; +import 'package:mirai/src/utils/utils.dart'; +import 'package:mirai/src/utils/widget_type.dart'; +import 'package:mirai_framework/mirai_framework.dart'; + +class MiraiPlaceholderParser extends MiraiParser { + const MiraiPlaceholderParser(); + + @override + String get type => WidgetType.placeholder.name; + + @override + MiraiPlaceholder getModel(Map json) => + MiraiPlaceholder.fromJson(json); + + @override + Widget parse(BuildContext context, MiraiPlaceholder model) { + return Placeholder( + fallbackWidth: model.fallbackWidth, + fallbackHeight: model.fallbackHeight, + strokeWidth: model.strokeWidth, + color: model.color.toColor(context) ?? Color(0xFF455A64), + child: Mirai.fromJson(model.child, context), + ); + } +} diff --git a/packages/mirai/lib/src/parsers/parsers.dart b/packages/mirai/lib/src/parsers/parsers.dart index 987b21ef..a6d14bd7 100644 --- a/packages/mirai/lib/src/parsers/parsers.dart +++ b/packages/mirai/lib/src/parsers/parsers.dart @@ -86,3 +86,4 @@ export 'package:mirai/src/parsers/mirai_radio/mirai_radio.dart'; export 'package:mirai/src/parsers/mirai_radio_group/mirai_radio_group.dart'; export 'package:mirai/src/parsers/mirai_slider/mirai_slider.dart'; export 'package:mirai/src/parsers/mirai_opacity/mirai_opacity.dart'; +export 'package:mirai/src/parsers/mirai_placeholder/mirai_placeholder.dart'; diff --git a/packages/mirai/lib/src/utils/widget_type.dart b/packages/mirai/lib/src/utils/widget_type.dart index 21526628..a8262727 100644 --- a/packages/mirai/lib/src/utils/widget_type.dart +++ b/packages/mirai/lib/src/utils/widget_type.dart @@ -61,4 +61,5 @@ enum WidgetType { radioGroup, slider, opacity, + placeholder, } diff --git a/website/docs/widgets/placeholder.md b/website/docs/widgets/placeholder.md new file mode 100644 index 00000000..9dad8603 --- /dev/null +++ b/website/docs/widgets/placeholder.md @@ -0,0 +1,32 @@ +# Placeholder + +The Mirai `Placeholder` widget allows you to build the Flutter Placeholder widget using JSON. +is used to draw a box that serves as a placeholder in your Flutter UI. It is typically used to represent areas where widgets are yet to be added or for debugging layout constraints. + +To learn more about the `Placeholder` widget, refer to the [official Flutter documentation](https://api.flutter.dev/flutter/widgets/Placeholder-class.html). + +--- + +## Properties + +| Property | Type | Description | +| ---------------- | ----------------------- | ------------------------------------------------------------------------------------------------------- | +| `color` | `String?` | The hex color to paint behind the child. Defaults to `#455A64` (Blue Grey 700). | +| `strokeWidth` | `double?` | The width of the lines used to draw the placeholder box. Defaults to `2.0`. | +| `fallbackWidth` | `double?` | The width to use when the placeholder is in a situation with an unbounded width. Defaults to `400.0`. | +| `fallbackHeight` | `double?` | The height to use when the placeholder is in a situation with an unbounded height. Defaults to `400.0`. | +| `child` | `Map?` | The widget to be displayed inside the placeholder box. | + +--- + +## Example JSON + +```json +{ + "type": "placeholder", + "color": "#455A64", + "strokeWidth": 2.0, + "fallbackWidth": 400.0, + "fallbackHeight": 400.0 +} +```