diff --git a/core/lib/core.dart b/core/lib/core.dart index 55679faaa..9ae33dc4b 100644 --- a/core/lib/core.dart +++ b/core/lib/core.dart @@ -54,6 +54,7 @@ export 'presentation/views/responsive/responsive_widget.dart'; export 'presentation/views/list/tree_view.dart'; export 'presentation/views/button/button_builder.dart'; export 'presentation/views/button/icon_button_web.dart'; +export 'presentation/views/button/tmail_button_widget.dart'; export 'presentation/views/image/avatar_builder.dart'; export 'presentation/views/list/sliver_grid_delegate_fixed_height.dart'; export 'presentation/views/image/icon_builder.dart'; @@ -82,6 +83,7 @@ export 'presentation/views/toast/toast_position.dart'; export 'presentation/views/toast/tmail_toast.dart'; export 'presentation/views/bottom_popup/full_screen_action_sheet_builder.dart'; export 'presentation/views/checkbox/labeled_checkbox.dart'; +export 'presentation/views/container/tmail_container_widget.dart'; // Resources export 'presentation/resources/assets_paths.dart'; @@ -105,4 +107,7 @@ export 'presentation/state/failure.dart'; // Model export 'data/model/source_type/data_source_type.dart'; -export 'data/model/query/query_parameter.dart'; \ No newline at end of file +export 'data/model/query/query_parameter.dart'; + +// Action +export 'presentation/action/action_callback_define.dart'; \ No newline at end of file diff --git a/core/lib/presentation/action/action_callback_define.dart b/core/lib/presentation/action/action_callback_define.dart new file mode 100644 index 000000000..8bce05143 --- /dev/null +++ b/core/lib/presentation/action/action_callback_define.dart @@ -0,0 +1,5 @@ + +import 'package:flutter/material.dart'; + +typedef OnTapActionCallback = void Function(); +typedef OnTapActionAtPositionCallback = void Function(RelativeRect position); \ No newline at end of file diff --git a/core/lib/presentation/views/button/tmail_button_widget.dart b/core/lib/presentation/views/button/tmail_button_widget.dart new file mode 100644 index 000000000..256bfe328 --- /dev/null +++ b/core/lib/presentation/views/button/tmail_button_widget.dart @@ -0,0 +1,161 @@ + +import 'package:core/presentation/action/action_callback_define.dart'; +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:core/presentation/views/container/tmail_container_widget.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; + +class TMailButtonWidget extends StatelessWidget { + + final OnTapActionCallback? onTapActionCallback; + final OnTapActionAtPositionCallback? onTapActionAtPositionCallback; + + final double borderRadius; + final double? width; + final double maxWidth; + final double maxHeight; + final String? tooltipMessage; + final Color? backgroundColor; + final EdgeInsetsGeometry? padding; + final String text; + final String? icon; + final bool verticalDirection; + final double iconSize; + final Color? iconColor; + final TextStyle? textStyle; + + const TMailButtonWidget({ + super.key, + required this.text, + this.onTapActionCallback, + this.onTapActionAtPositionCallback, + this.borderRadius = 20, + this.width, + this.maxWidth = double.infinity, + this.maxHeight = double.infinity, + this.tooltipMessage, + this.backgroundColor, + this.padding, + this.verticalDirection = false, + this.icon, + this.iconSize = 24, + this.iconColor, + this.textStyle, + }); + + factory TMailButtonWidget.fromIcon({ + required String icon, + final Key? key, + OnTapActionCallback? onTapActionCallback, + OnTapActionAtPositionCallback? onTapActionAtPositionCallback, + double borderRadius = 20, + double? width, + double maxWidth = double.infinity, + double maxHeight = double.infinity, + String? tooltipMessage, + Color? backgroundColor, + EdgeInsetsGeometry? padding, + String text = '', + bool verticalDirection = false, + double iconSize = 24, + Color? iconColor, + TextStyle? textStyle, + }) { + return TMailButtonWidget( + key: key, + text: text, + onTapActionCallback: onTapActionCallback, + onTapActionAtPositionCallback: onTapActionAtPositionCallback, + borderRadius: borderRadius, + width: width, + maxWidth : maxWidth, + maxHeight: maxHeight, + tooltipMessage: tooltipMessage, + backgroundColor: backgroundColor, + padding: padding, + verticalDirection: verticalDirection, + icon: icon, + iconSize: iconSize, + iconColor: iconColor, + textStyle: textStyle, + ); + } + + @override + Widget build(BuildContext context) { + Widget childWidget; + + if (icon != null && text.isNotEmpty) { + if (verticalDirection) { + childWidget = Column( + mainAxisSize: MainAxisSize.min, + children: [ + SvgPicture.asset( + icon!, + width: iconSize, + height: iconSize, + fit: BoxFit.fill, + colorFilter: iconColor?.asFilter() + ), + Text( + text, + style: textStyle ?? const TextStyle( + fontSize: 12, + color: AppColor.colorTextButtonHeaderThread + ), + ), + ] + ); + } else { + childWidget = Row( + mainAxisSize: MainAxisSize.min, + children: [ + SvgPicture.asset( + icon!, + width: iconSize, + height: iconSize, + fit: BoxFit.fill, + colorFilter: iconColor?.asFilter() + ), + Text( + text, + style: textStyle ?? const TextStyle( + fontSize: 12, + color: AppColor.colorTextButtonHeaderThread + ), + ), + ] + ); + } + } else if (icon != null) { + childWidget = SvgPicture.asset( + icon!, + width: iconSize, + height: iconSize, + fit: BoxFit.fill, + colorFilter: iconColor?.asFilter() + ); + } else { + childWidget = Text( + text, + style: textStyle ?? const TextStyle( + fontSize: 12, + color: AppColor.colorTextButtonHeaderThread + ), + ); + } + + return TMailContainerWidget( + onTapActionCallback: onTapActionCallback, + onTapActionAtPositionCallback: onTapActionAtPositionCallback, + borderRadius: borderRadius, + width: width, + maxWidth: maxWidth, + maxHeight: maxHeight, + tooltipMessage: tooltipMessage, + backgroundColor: backgroundColor, + padding: padding, + child: childWidget, + ); + } +} \ No newline at end of file diff --git a/core/lib/presentation/views/container/tmail_container_widget.dart b/core/lib/presentation/views/container/tmail_container_widget.dart new file mode 100644 index 000000000..909729108 --- /dev/null +++ b/core/lib/presentation/views/container/tmail_container_widget.dart @@ -0,0 +1,83 @@ + +import 'package:core/presentation/action/action_callback_define.dart'; +import 'package:core/presentation/extensions/color_extension.dart'; +import 'package:flutter/material.dart'; + +class TMailContainerWidget extends StatelessWidget { + + final OnTapActionCallback? onTapActionCallback; + final OnTapActionAtPositionCallback? onTapActionAtPositionCallback; + + final Widget child; + final double borderRadius; + final double? width; + final double maxWidth; + final double maxHeight; + final String? tooltipMessage; + final Color? backgroundColor; + final EdgeInsetsGeometry? padding; + + const TMailContainerWidget({ + super.key, + required this.child, + this.onTapActionCallback, + this.onTapActionAtPositionCallback, + this.borderRadius = 20, + this.width, + this.maxWidth = double.infinity, + this.maxHeight = double.infinity, + this.tooltipMessage, + this.backgroundColor, + this.padding, + }); + + @override + Widget build(BuildContext context) { + return Material( + color: Colors.transparent, + child: InkWell( + onTap: onTapActionCallback, + onTapDown: (detail) { + if (onTapActionAtPositionCallback != null) { + final screenSize = MediaQuery.of(context).size; + final offset = detail.globalPosition; + final position = RelativeRect.fromLTRB( + offset.dx, + offset.dy, + screenSize.width - offset.dx, + screenSize.height - offset.dy, + ); + onTapActionAtPositionCallback!.call(position); + } + }, + borderRadius: BorderRadius.all(Radius.circular(borderRadius)), + child: tooltipMessage != null + ? Tooltip( + message: tooltipMessage, + child: Container( + alignment: Alignment.center, + decoration: BoxDecoration( + color: backgroundColor ?? AppColor.colorButtonHeaderThread, + borderRadius: BorderRadius.all(Radius.circular(borderRadius)), + ), + width: width, + constraints: BoxConstraints(maxWidth: maxWidth, maxHeight: maxHeight), + padding: padding ?? const EdgeInsetsDirectional.all(8), + child: child + ) + ) + : Container( + alignment: Alignment.center, + decoration: BoxDecoration( + color: backgroundColor ?? AppColor.colorButtonHeaderThread, + borderRadius: BorderRadius.all(Radius.circular(borderRadius)), + ), + width: width, + constraints: BoxConstraints(maxWidth: maxWidth, maxHeight: maxHeight), + padding: padding ?? const EdgeInsetsDirectional.all(8), + child: child + ) + ), + ); + } +} \ No newline at end of file