diff --git a/.flutter-plugins b/.flutter-plugins index 7adee4f..82b3770 100644 --- a/.flutter-plugins +++ b/.flutter-plugins @@ -1,7 +1,7 @@ # This is a generated file; do not edit or check into version control. -path_provider=/Users/micazi/.pub-cache/hosted/pub.dev/path_provider-2.1.3/ -path_provider_android=/Users/micazi/.pub-cache/hosted/pub.dev/path_provider_android-2.2.4/ -path_provider_foundation=/Users/micazi/.pub-cache/hosted/pub.dev/path_provider_foundation-2.3.2/ -path_provider_linux=/Users/micazi/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ -path_provider_windows=/Users/micazi/.pub-cache/hosted/pub.dev/path_provider_windows-2.2.1/ -sqflite=/Users/micazi/.pub-cache/hosted/pub.dev/sqflite-2.3.3/ +path_provider=C:\\Users\\micwa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider-2.1.3\\ +path_provider_android=C:\\Users\\micwa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_android-2.2.6\\ +path_provider_foundation=C:\\Users\\micwa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_foundation-2.4.0\\ +path_provider_linux=C:\\Users\\micwa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_linux-2.2.1\\ +path_provider_windows=C:\\Users\\micwa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\path_provider_windows-2.2.1\\ +sqflite=C:\\Users\\micwa\\AppData\\Local\\Pub\\Cache\\hosted\\pub.dev\\sqflite-2.3.3+1\\ diff --git a/.flutter-plugins-dependencies b/.flutter-plugins-dependencies index 247267d..f6ef29d 100644 --- a/.flutter-plugins-dependencies +++ b/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"/Users/micazi/.pub-cache/hosted/pub.dev/path_provider_foundation-2.3.2/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"sqflite","path":"/Users/micazi/.pub-cache/hosted/pub.dev/sqflite-2.3.3/","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"android":[{"name":"path_provider_android","path":"/Users/micazi/.pub-cache/hosted/pub.dev/path_provider_android-2.2.4/","native_build":true,"dependencies":[]},{"name":"sqflite","path":"/Users/micazi/.pub-cache/hosted/pub.dev/sqflite-2.3.3/","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"/Users/micazi/.pub-cache/hosted/pub.dev/path_provider_foundation-2.3.2/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"sqflite","path":"/Users/micazi/.pub-cache/hosted/pub.dev/sqflite-2.3.3/","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/micazi/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/micazi/.pub-cache/hosted/pub.dev/path_provider_windows-2.2.1/","native_build":false,"dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2024-09-17 12:51:18.099992","version":"3.24.1","swift_package_manager_enabled":false} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\micwa\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.4.0\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\micwa\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\sqflite-2.3.3+1\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"android":[{"name":"path_provider_android","path":"C:\\\\Users\\\\micwa\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_android-2.2.6\\\\","native_build":true,"dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\micwa\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\sqflite-2.3.3+1\\\\","native_build":true,"dependencies":[]}],"macos":[{"name":"path_provider_foundation","path":"C:\\\\Users\\\\micwa\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_foundation-2.4.0\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"sqflite","path":"C:\\\\Users\\\\micwa\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\sqflite-2.3.3+1\\\\","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"C:\\\\Users\\\\micwa\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_linux-2.2.1\\\\","native_build":false,"dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"C:\\\\Users\\\\micwa\\\\AppData\\\\Local\\\\Pub\\\\Cache\\\\hosted\\\\pub.dev\\\\path_provider_windows-2.2.1\\\\","native_build":false,"dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"path_provider","dependencies":["path_provider_android","path_provider_foundation","path_provider_linux","path_provider_windows"]},{"name":"path_provider_android","dependencies":[]},{"name":"path_provider_foundation","dependencies":[]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"sqflite","dependencies":[]}],"date_created":"2025-02-09 15:39:20.757997","version":"3.27.1","swift_package_manager_enabled":false} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 02b0934..a5a2125 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ -## 0.0.1 + - - Initial release with mostly all of the components of this module. +## 0.1.0 + +- **INIT**: Initial commit in the new repo. diff --git a/README.md b/README.md index cdbf8d1..a6b6ef0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -## Atromic Mobile: Elements +## Atromic Elements -The elements module of the **Astromic Mobile** Presentation System +The elements module of the **Astromic** Presentation System Developed, Maintained, and is property of Michael W. Aziz (Micazi) ### Content diff --git a/TODO.md b/TODO.md deleted file mode 100644 index 9f54fc8..0000000 --- a/TODO.md +++ /dev/null @@ -1,3 +0,0 @@ -### Chip Selector - -[-] Investigate how to detect last enabled chip and check it's status in consequent mode. diff --git a/analysis_options.yaml b/analysis_options.yaml index 7c2f3d3..91cc0d7 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,4 +1,5 @@ -include: package:flutter_lints/flutter.yaml +include: package:lints/recommended.yaml + linter: rules: - prefer_relative_imports diff --git a/lib/Dependencies/gradient_border/box_borders/gradient_box_border.dart b/lib/Dependencies/gradient_border/box_borders/gradient_box_border.dart new file mode 100644 index 0000000..b56ac6a --- /dev/null +++ b/lib/Dependencies/gradient_border/box_borders/gradient_box_border.dart @@ -0,0 +1,67 @@ +import 'package:flutter/widgets.dart'; + +class GradientBoxBorder extends Border { + const GradientBoxBorder({required this.gradient, this.width = 1.0, super.bottom, super.left, super.right, super.top}); + + final Gradient gradient; + + final double width; + + @override + EdgeInsetsGeometry get dimensions => EdgeInsets.all(width); + + @override + void paint( + Canvas canvas, + Rect rect, { + TextDirection? textDirection, + BoxShape shape = BoxShape.rectangle, + BorderRadius? borderRadius, + }) { + switch (shape) { + case BoxShape.circle: + assert( + borderRadius == null, + 'A borderRadius can only be given for rectangular boxes.', + ); + _paintCircle(canvas, rect); + break; + case BoxShape.rectangle: + if (borderRadius != null) { + _paintRRect(canvas, rect, borderRadius); + return; + } + _paintRect(canvas, rect); + break; + } + } + + void _paintRect(Canvas canvas, Rect rect) { + // canvas.drawRect(rect.deflate(width / 2), _getPaint(rect)); + canvas.drawLine(rect.bottomLeft, rect.bottomRight, _getPaint(rect)); + } + + void _paintRRect(Canvas canvas, Rect rect, BorderRadius borderRadius) { + // final rrect = borderRadius.toRRect().deflate(width / 2); + + canvas.drawLine(rect.bottomLeft, rect.bottomRight, _getPaint(rect)); + } + + void _paintCircle(Canvas canvas, Rect rect) { + final paint = _getPaint(rect); + final radius = (rect.shortestSide - width) / 2.0; + canvas.drawCircle(rect.center, radius, paint); + } + + @override + Border scale(double t) { + return this; + } + + Paint _getPaint(Rect rect) { + return Paint() + ..strokeWidth = width + ..shader = gradient.createShader(rect) + ..style = PaintingStyle.stroke; + } +} diff --git a/lib/Dependencies/gradient_border/gradient_borders.dart b/lib/Dependencies/gradient_border/gradient_borders.dart new file mode 100644 index 0000000..2c51c61 --- /dev/null +++ b/lib/Dependencies/gradient_border/gradient_borders.dart @@ -0,0 +1,4 @@ +library gradient_borders; + +export 'box_borders/gradient_box_border.dart'; +export 'input_borders/gradient_outline_input_border.dart'; diff --git a/lib/Dependencies/gradient_border/input_borders/gradient_outline_input_border.dart b/lib/Dependencies/gradient_border/input_borders/gradient_outline_input_border.dart new file mode 100644 index 0000000..a92415b --- /dev/null +++ b/lib/Dependencies/gradient_border/input_borders/gradient_outline_input_border.dart @@ -0,0 +1,176 @@ +import 'dart:math' as math; +import 'dart:ui'; + +import 'package:flutter/material.dart'; + +class GradientOutlineInputBorder extends InputBorder { + const GradientOutlineInputBorder({ + required this.gradient, + this.width = 1.0, + this.gapPadding = 4.0, + this.borderRadius = const BorderRadius.all(Radius.circular(4)), + }); + + final double width; + + final BorderRadius borderRadius; + + final Gradient gradient; + + final double gapPadding; + + @override + InputBorder copyWith({BorderSide? borderSide}) { + return this; + } + + @override + bool get isOutline => true; + + @override + EdgeInsetsGeometry get dimensions => EdgeInsets.all(width); + + @override + Path getInnerPath(Rect rect, {TextDirection? textDirection}) { + return Path() + ..addRRect( + borderRadius + .resolve(textDirection) + .toRRect(rect) + .deflate(borderSide.width), + ); + } + + @override + Path getOuterPath(Rect rect, {TextDirection? textDirection}) { + return Path()..addRRect(borderRadius.resolve(textDirection).toRRect(rect)); + } + + @override + void paint( + Canvas canvas, + Rect rect, { + double? gapStart, + double gapExtent = 0.0, + double gapPercentage = 0.0, + TextDirection? textDirection, + }) { + final paint = _getPaint(rect); + final outer = borderRadius.toRRect(rect); + final center = outer.deflate(borderSide.width / 2.0); + if (gapStart == null || gapExtent <= 0.0 || gapPercentage == 0.0) { + canvas.drawRRect(center, paint); + } else { + final extent = + lerpDouble(0.0, gapExtent + gapPadding * 2.0, gapPercentage)!; + switch (textDirection!) { + case TextDirection.rtl: + final path = _gapBorderPath( + canvas, + center, + math.max(0, gapStart + gapPadding - extent), + extent, + ); + canvas.drawPath(path, paint); + break; + + case TextDirection.ltr: + final path = _gapBorderPath( + canvas, + center, + math.max(0, gapStart - gapPadding), + extent, + ); + canvas.drawPath(path, paint); + break; + } + } + } + + @override + ShapeBorder scale(double t) { + return GradientOutlineInputBorder( + width: width * t, + borderRadius: borderRadius * t, + gradient: gradient, + ); + } + + Paint _getPaint(Rect rect) { + return Paint() + ..strokeWidth = width + ..shader = gradient.createShader(rect) + ..style = PaintingStyle.stroke; + } + + Path _gapBorderPath( + Canvas canvas, + RRect center, + double start, + double extent, + ) { + // When the corner radii on any side add up to be greater than the + // given height, each radius has to be scaled to not exceed the + // size of the width/height of the RRect. + final scaledRRect = center.scaleRadii(); + + final tlCorner = Rect.fromLTWH( + scaledRRect.left, + scaledRRect.top, + scaledRRect.tlRadiusX * 2.0, + scaledRRect.tlRadiusY * 2.0, + ); + final trCorner = Rect.fromLTWH( + scaledRRect.right - scaledRRect.trRadiusX * 2.0, + scaledRRect.top, + scaledRRect.trRadiusX * 2.0, + scaledRRect.trRadiusY * 2.0, + ); + final brCorner = Rect.fromLTWH( + scaledRRect.right - scaledRRect.brRadiusX * 2.0, + scaledRRect.bottom - scaledRRect.brRadiusY * 2.0, + scaledRRect.brRadiusX * 2.0, + scaledRRect.brRadiusY * 2.0, + ); + final blCorner = Rect.fromLTWH( + scaledRRect.left, + scaledRRect.bottom - scaledRRect.blRadiusY * 2.0, + scaledRRect.blRadiusX * 2.0, + scaledRRect.blRadiusX * 2.0, + ); + + const cornerArcSweep = math.pi / 2.0; + final tlCornerArcSweep = start < scaledRRect.tlRadiusX + ? math.asin((start / scaledRRect.tlRadiusX).clamp(-1.0, 1.0)) + : math.pi / 2.0; + + final path = Path() + ..addArc(tlCorner, math.pi, tlCornerArcSweep) + ..moveTo(scaledRRect.left + scaledRRect.tlRadiusX, scaledRRect.top); + + if (start > scaledRRect.tlRadiusX) { + path.lineTo(scaledRRect.left + start, scaledRRect.top); + } + + const trCornerArcStart = (3 * math.pi) / 2.0; + const trCornerArcSweep = cornerArcSweep; + if (start + extent < scaledRRect.width - scaledRRect.trRadiusX) { + path + ..relativeMoveTo(extent, 0) + ..lineTo(scaledRRect.right - scaledRRect.trRadiusX, scaledRRect.top) + ..addArc(trCorner, trCornerArcStart, trCornerArcSweep); + } else if (start + extent < scaledRRect.width) { + final dx = scaledRRect.width - (start + extent); + final sweep = math.acos(dx / scaledRRect.trRadiusX); + path.addArc(trCorner, trCornerArcStart + sweep, trCornerArcSweep - sweep); + } + + return path + ..moveTo(scaledRRect.right, scaledRRect.top + scaledRRect.trRadiusY) + ..lineTo(scaledRRect.right, scaledRRect.bottom - scaledRRect.brRadiusY) + ..addArc(brCorner, 0, cornerArcSweep) + ..lineTo(scaledRRect.left + scaledRRect.blRadiusX, scaledRRect.bottom) + ..addArc(blCorner, math.pi / 2.0, cornerArcSweep) + ..lineTo(scaledRRect.left, scaledRRect.top + scaledRRect.tlRadiusY); + } +} diff --git a/lib/Dependencies/gradient_border/input_borders/gradient_underline_input_border.dart b/lib/Dependencies/gradient_border/input_borders/gradient_underline_input_border.dart new file mode 100644 index 0000000..4f06874 --- /dev/null +++ b/lib/Dependencies/gradient_border/input_borders/gradient_underline_input_border.dart @@ -0,0 +1,75 @@ +import 'dart:math' as math; +import 'dart:ui'; + +import 'package:flutter/material.dart'; + +class GradientUnderlineInputBorder extends InputBorder { + const GradientUnderlineInputBorder({ + required this.gradient, + this.width = 1.0, + this.gapPadding = 4.0, + this.borderRadius = const BorderRadius.all(Radius.circular(4)), + }); + + final double width; + + final BorderRadius borderRadius; + + final Gradient gradient; + + final double gapPadding; + + @override + InputBorder copyWith({BorderSide? borderSide}) { + return this; + } + + @override + bool get isOutline => true; + + @override + EdgeInsetsGeometry get dimensions => EdgeInsets.all(width); + + @override + Path getInnerPath(Rect rect, {TextDirection? textDirection}) { + return Path() + ..addRRect( + borderRadius.resolve(textDirection).toRRect(rect).deflate(borderSide.width), + ); + } + + @override + Path getOuterPath(Rect rect, {TextDirection? textDirection}) { + return Path()..addRRect(borderRadius.resolve(textDirection).toRRect(rect)); + } + + @override + void paint( + Canvas canvas, + Rect rect, { + double? gapStart, + double gapExtent = 0.0, + double gapPercentage = 0.0, + TextDirection? textDirection, + }) { + final paint = _getPaint(rect); + Rect underlineRect = Rect.fromLTWH(rect.left, rect.height - width, rect.width, width); + canvas.drawRect(underlineRect, paint); + } + + @override + ShapeBorder scale(double t) { + return GradientUnderlineInputBorder( + width: width * t, + borderRadius: borderRadius * t, + gradient: gradient, + ); + } + + Paint _getPaint(Rect rect) { + return Paint() + ..strokeWidth = width + ..shader = gradient.createShader(rect) + ..style = PaintingStyle.stroke; + } +} diff --git a/lib/Infrastructure/border_extensions.dart b/lib/Infrastructure/border_extensions.dart deleted file mode 100644 index 58e9fb0..0000000 --- a/lib/Infrastructure/border_extensions.dart +++ /dev/null @@ -1,7 +0,0 @@ -import "package:flutter/painting.dart"; - -extension BorderExtension on BorderDirectional { - BorderDirectional all(BorderSide side) { - return BorderDirectional(top: side, bottom: side, start: side, end: side); - } -} diff --git a/lib/Infrastructure/infrastructure.exports.dart b/lib/Infrastructure/infrastructure.exports.dart deleted file mode 100644 index 3eb61e2..0000000 --- a/lib/Infrastructure/infrastructure.exports.dart +++ /dev/null @@ -1,7 +0,0 @@ -export './border_extensions.dart'; -export './insets_extension.dart'; -export './list_extensions.dart'; -export './misc_extensions.dart'; -export './radius_extensions.dart'; -export './string_extensions.dart'; -export './transparent_image.dart'; diff --git a/lib/Infrastructure/insets_extension.dart b/lib/Infrastructure/insets_extension.dart deleted file mode 100644 index a557276..0000000 --- a/lib/Infrastructure/insets_extension.dart +++ /dev/null @@ -1,12 +0,0 @@ -import 'package:flutter/widgets.dart'; - -extension InsetsExtension on EdgeInsetsGeometry { - copyWith(EdgeInsetsGeometry g) => add(g); - // - EdgeInsetsDirectional resolveToDirectional(TextDirection direction) { - // - return EdgeInsetsDirectional.fromSTEB(direction == TextDirection.ltr ? resolve(direction).left : resolve(direction).right, resolve(direction).top, - direction == TextDirection.ltr ? resolve(direction).right : resolve(direction).left, resolve(direction).bottom); - // - } -} diff --git a/lib/Infrastructure/list_extensions.dart b/lib/Infrastructure/list_extensions.dart deleted file mode 100644 index b6b5b3a..0000000 --- a/lib/Infrastructure/list_extensions.dart +++ /dev/null @@ -1,20 +0,0 @@ -extension ListExtension on List { - bool containsAll(List otherList) { - List checks = []; - // - for (E thisElement in otherList) { - checks.add(contains(thisElement)); - } - return !checks.contains(false); - } - - List getUnique() { - List uniqueItems = []; - for (E thisElement in this) { - if (!uniqueItems.contains(thisElement)) { - uniqueItems.add(thisElement); - } - } - return uniqueItems; - } -} diff --git a/lib/Infrastructure/misc_extensions.dart b/lib/Infrastructure/misc_extensions.dart deleted file mode 100644 index f93cff4..0000000 --- a/lib/Infrastructure/misc_extensions.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:flutter/material.dart'; - -extension TextAlignVerticalExtension on TextAlignVertical { - toAlignment() { - switch (this) { - case TextAlignVertical.top: - return Alignment.topCenter; - case TextAlignVertical.center: - return Alignment.center; - case TextAlignVertical.bottom: - return Alignment.bottomCenter; - default: - return Alignment.center; - } - } -} diff --git a/lib/Infrastructure/radius_extensions.dart b/lib/Infrastructure/radius_extensions.dart deleted file mode 100644 index 0563f5a..0000000 --- a/lib/Infrastructure/radius_extensions.dart +++ /dev/null @@ -1,15 +0,0 @@ -import 'package:flutter/widgets.dart'; - -extension RadiusExtension on BorderRadiusGeometry { - copyWith(BorderRadiusGeometry g) => add(g); - // - BorderRadiusDirectional resolveToDirectional(TextDirection direction) { - // - return BorderRadiusDirectional.only( - topStart: direction == TextDirection.ltr ? resolve(direction).topLeft : resolve(direction).topRight, - topEnd: direction == TextDirection.rtl ? resolve(direction).topLeft : resolve(direction).topRight, - bottomEnd: direction == TextDirection.rtl ? resolve(direction).bottomRight : resolve(direction).bottomRight, - bottomStart: direction == TextDirection.ltr ? resolve(direction).bottomLeft : resolve(direction).bottomRight, - ); - } -} diff --git a/lib/Infrastructure/string_extensions.dart b/lib/Infrastructure/string_extensions.dart deleted file mode 100644 index 050d38c..0000000 --- a/lib/Infrastructure/string_extensions.dart +++ /dev/null @@ -1,19 +0,0 @@ -import 'package:flutter/material.dart'; - -extension StringExtensions on String { - /// Parse the HexCode to color - Color get toColor { - if (this == '') return const Color(0xFF000000); - String hexColor = replaceAll('#', ''); - hexColor = hexColor.replaceAll('0x', ''); - hexColor = hexColor.padLeft(6, '0'); - hexColor = hexColor.padLeft(8, 'F'); - final int length = hexColor.length; - return Color(int.tryParse('0x${hexColor.substring(length - 8, length)}') ?? 0xFF000000); - } - - /// Capitalize the first letter in a string. - String get capitalize { - return (length > 1) ? this[0].toUpperCase() + substring(1) : toUpperCase(); - } -} diff --git a/lib/Infrastructure/transparent_image.dart b/lib/Infrastructure/transparent_image.dart deleted file mode 100644 index ec0b755..0000000 --- a/lib/Infrastructure/transparent_image.dart +++ /dev/null @@ -1,73 +0,0 @@ -library transparent_image; - -import 'dart:typed_data'; - -final Uint8List kTransparentImage = Uint8List.fromList([ - 0x89, - 0x50, - 0x4E, - 0x47, - 0x0D, - 0x0A, - 0x1A, - 0x0A, - 0x00, - 0x00, - 0x00, - 0x0D, - 0x49, - 0x48, - 0x44, - 0x52, - 0x00, - 0x00, - 0x00, - 0x01, - 0x00, - 0x00, - 0x00, - 0x01, - 0x08, - 0x06, - 0x00, - 0x00, - 0x00, - 0x1F, - 0x15, - 0xC4, - 0x89, - 0x00, - 0x00, - 0x00, - 0x0A, - 0x49, - 0x44, - 0x41, - 0x54, - 0x78, - 0x9C, - 0x63, - 0x00, - 0x01, - 0x00, - 0x00, - 0x05, - 0x00, - 0x01, - 0x0D, - 0x0A, - 0x2D, - 0xB4, - 0x00, - 0x00, - 0x00, - 0x00, - 0x49, - 0x45, - 0x4E, - 0x44, - 0xAE, - 0x42, - 0x60, - 0x82, -]); diff --git a/lib/astromic_mobile_elements.dart b/lib/astromic_elements.dart similarity index 81% rename from lib/astromic_mobile_elements.dart rename to lib/astromic_elements.dart index 302c35e..9840125 100644 --- a/lib/astromic_mobile_elements.dart +++ b/lib/astromic_elements.dart @@ -1,4 +1,4 @@ -library astromic_mobile_elements; +library astromic_elements; export './src/Spacing/spacing.astromic.dart'; export './src/Widgets/widgets.astromic.dart'; @@ -6,6 +6,4 @@ export './src/Selectors/selectors.astromic.dart'; export './src/Toggles/toggles.astromic.dart'; export './src/Buttons/buttons.astromic.dart'; export './src/Fields/fields.astromic.dart'; -export './Infrastructure/infrastructure.exports.dart'; export 'package:flutter_svg/flutter_svg.dart' show SvgPicture, BytesLoader, SvgAssetLoader; //Needed for assets manipulation - diff --git a/lib/src/Buttons/buttons.astromic.dart b/lib/src/Buttons/buttons.astromic.dart index 571dd97..6dc3ce1 100644 --- a/lib/src/Buttons/buttons.astromic.dart +++ b/lib/src/Buttons/buttons.astromic.dart @@ -1,30 +1,34 @@ -//s2 Core Packages Imports +//s1 Imports +//s2 Core Package Imports import 'package:flutter/material.dart'; -// +//s2 1st-party Package Imports +//s2 3rd-party Package Imports +//s2 Dependancies Imports +//s3 Routes +//s3 Services +//s3 Models import 'src/icon_button.dart'; import 'src/link_button.dart'; import 'src/state_button.dart'; // -import 'src/sizing_strategy.enum.dart'; -import 'src/style.dart'; -// -export 'src/sizing_strategy.enum.dart'; -export 'src/style.dart'; +import 'src/enums/enums.exports.dart'; +import 'src/models/models.exports.dart'; +//s1 Exports +export 'src/enums/enums.exports.dart'; +export 'src/models/models.exports.dart'; +/// A collection of the available Astromic buttons. class AstromicButtons { - //S1 -- State + /// an `AstromicStateButton` is a button whoose style is affected by it's state. static Widget state({ // void Function(VoidCallback start, VoidCallback stop)? onTap, Function(VoidCallback start, VoidCallback stop)? onHold, // - bool? isEnabled, - bool? withFeedback, - bool? withHighlightChange, - TextDirection? textDirection, + AstromicButtonConfiguration? configuration, // - SizingStrategy? widthSizingStrategy, - SizingStrategy? heightSizingStrategy, + AstromicSizingStrategy? widthSizingStrategy, + AstromicSizingStrategy? heightSizingStrategy, InteractiveInkFeatureFactory? splashFactory, required AstromicButtonStyle Function(bool isEnabled, bool isHighlighted, bool isLoading) style, // @@ -35,30 +39,23 @@ class AstromicButtons { onTap: onTap, onHold: onHold, // - isEnabled: isEnabled ?? true, - withFeedback: withFeedback ?? true, - withHighlightChange: withHighlightChange ?? true, - textDirection: textDirection ?? TextDirection.ltr, + configuration: configuration, // widthSizingStrategy: widthSizingStrategy, heightSizingStrategy: heightSizingStrategy, - splashFactory: splashFactory, style: style, // loadingContent: loadingContent, content: content, ); - //S1 -- Icon + /// an `AstromicIconButton` is a button specifically for mapping to an IconButton. static Widget icon({ // void Function(VoidCallback start, VoidCallback stop)? onTap, Function(VoidCallback start, VoidCallback stop)? onHold, // - bool? isEnabled, - bool? withFeedback, - bool? withHighlightChange, - TextDirection? textDirection, + AstromicButtonConfiguration? configuration, // bool? isCircular, InteractiveInkFeatureFactory? splashFactory, @@ -71,27 +68,22 @@ class AstromicButtons { onTap: onTap, onHold: onHold, // - isEnabled: isEnabled ?? true, - withFeedback: withFeedback ?? true, - withHighlightChange: withHighlightChange ?? true, - textDirection: textDirection ?? TextDirection.ltr, + configuration: configuration, // isCircular: isCircular ?? true, - splashFactory: splashFactory, style: style, // loadingContent: loadingContent, icon: icon, ); - //S1 -- Link + /// an `AstromicLinkButton` is a button specifically for mapping to LinkButton. static Widget link({ // VoidCallback? onTap, VoidCallback? onHold, // - bool? isEnabled, - TextDirection? textDirection, + AstromicButtonConfiguration? configuration, // bool Function(bool isEnabled)? isUnderlined, EdgeInsetsGeometry? contentPadding, @@ -106,8 +98,7 @@ class AstromicButtons { onTap: onTap, onHold: onHold, // - isEnabled: isEnabled ?? true, - textDirection: textDirection ?? TextDirection.ltr, + configuration: configuration, // isUnderlined: isUnderlined ?? (e) => e, contentPadding: contentPadding, diff --git a/lib/src/Buttons/src/base.dart b/lib/src/Buttons/src/base.dart index 2ede509..123bea8 100644 --- a/lib/src/Buttons/src/base.dart +++ b/lib/src/Buttons/src/base.dart @@ -1,22 +1,15 @@ -//SECTION - Imports -// -//s1 PACKAGES -//--------------- -//s2 CORE +//s1 Imports +//s2 Core Package Imports import 'package:flutter/material.dart'; -//s2 3RD-PARTY -// -//s1 DEPENDENCIES -//---------------- -//s2 SERVICES -//s2 MODELS -import 'style.dart'; -//s2 MISC -//!SECTION - Imports -// -//SECTION - Exports -//!SECTION - Exports -// +//s2 1st-party Package Imports +import '../../../Dependencies/gradient_border/gradient_borders.dart'; +//s2 3rd-party Package Imports +//s2 Dependancies Imports +//s3 Routes +//s3 Services +//s3 Models +import 'models/models.exports.dart'; +//s1 Exports class AstromicButtonBase extends StatefulWidget { //SECTION - Widget Arguments @@ -24,13 +17,9 @@ class AstromicButtonBase extends StatefulWidget { final VoidCallback? onTap; final VoidCallback? onHold; //s1 -- Configurations - final bool isEnabled; - final bool withFeedback; - final bool withHighlightChange; - final TextDirection textDirection; + final AstromicButtonConfiguration? configuration; //s1 -- Style - final InteractiveInkFeatureFactory? splashFactory; - final AstromicButtonStyle Function(bool isEnabled, bool isHighlighted) style; + final AstromicButtonStyle Function(bool isEnabled, bool isHighlighted)? style; //s1 -- Content final Widget Function(bool isEnabled, bool isHighlighted) child; //!SECTION @@ -41,13 +30,9 @@ class AstromicButtonBase extends StatefulWidget { this.onTap, this.onHold, // - this.isEnabled = true, - this.withFeedback = true, - this.withHighlightChange = true, - required this.textDirection, + this.configuration, //s1 -- Style - this.splashFactory, - required this.style, + this.style, //s1 -- Content required this.child, }) : super( @@ -66,6 +51,8 @@ class _AstromicButtonBaseState extends State { // //s1 --State late bool _isHighlighted; + late AstromicButtonConfiguration _config; + late AstromicButtonStyle _style; //s1 --State // //s1 --Constants @@ -93,6 +80,8 @@ class _AstromicButtonBaseState extends State { Widget build(BuildContext context) { //SECTION - Build Setup //s1 -Values + _config = widget.configuration ?? AstromicButtonConfiguration(isEnabled: true, withFeedback: true, withHighlightChange: true, textDirection: TextDirection.ltr); + _style = widget.style?.call(_config.isEnabled, _isHighlighted) ?? const AstromicButtonStyle(); //s1 -Values // //s1 -Widgets @@ -101,30 +90,37 @@ class _AstromicButtonBaseState extends State { //SECTION - Build Return return Material( - color: widget.style(widget.isEnabled, _isHighlighted).backgroundGradient != null ? Colors.transparent : widget.style(widget.isEnabled, _isHighlighted).backgroundColor, - shape: OutlineInputBorder( - borderSide: BorderSide( - width: widget.style(widget.isEnabled, _isHighlighted).borderWidth ?? 1, - color: widget.style(widget.isEnabled, _isHighlighted).borderColor ?? Colors.black, - ), - borderRadius: widget.style(widget.isEnabled, _isHighlighted).borderRadius?.resolve(widget.textDirection) ?? BorderRadius.circular(0), - ), + color: _style.backgroundGradient != null ? Colors.transparent : _style.backgroundColor, + shape: _style.borderGradient != null + ? GradientOutlineInputBorder( + gapPadding: 0, + gradient: _style.borderGradient!, + borderRadius: _style.borderRadius?.resolve(_config.textDirection) ?? BorderRadius.circular(0), + width: _style.borderWidth ?? 1, + ) + : OutlineInputBorder( + borderSide: BorderSide( + width: _style.borderWidth ?? 1, + color: _style.borderColor ?? Colors.black, + ), + borderRadius: _style.borderRadius?.resolve(_config.textDirection) ?? BorderRadius.circular(0), + ), child: Ink( decoration: BoxDecoration( - borderRadius: widget.style(widget.isEnabled, _isHighlighted).borderRadius?.resolve(widget.textDirection) ?? BorderRadius.circular(0), - gradient: widget.style(widget.isEnabled, _isHighlighted).backgroundGradient, + borderRadius: _style.borderRadius?.resolve(_config.textDirection) ?? BorderRadius.circular(0), + gradient: _style.backgroundGradient, ), child: InkWell( - splashFactory: widget.splashFactory, - splashColor: widget.withFeedback ? widget.style(widget.isEnabled, _isHighlighted).splashColor : Colors.transparent, - hoverColor: widget.withFeedback ? widget.style(widget.isEnabled, _isHighlighted).hoverColor : Colors.transparent, - highlightColor: widget.withFeedback ? widget.style(widget.isEnabled, _isHighlighted).highlightColor : Colors.transparent, + splashFactory: _style.splashFactory, + splashColor: _config.withFeedback ? _style.splashColor : Colors.transparent, + hoverColor: _config.withFeedback ? _style.hoverColor : Colors.transparent, + highlightColor: _config.withFeedback ? _style.highlightColor : Colors.transparent, // - borderRadius: widget.style(widget.isEnabled, _isHighlighted).borderRadius?.resolve(widget.textDirection) ?? BorderRadius.circular(0), + borderRadius: _style.borderRadius?.resolve(_config.textDirection) ?? BorderRadius.circular(0), // - onTap: widget.isEnabled && widget.onTap != null ? widget.onTap : null, - onLongPress: widget.isEnabled && widget.onHold != null ? widget.onHold : null, - onHighlightChanged: widget.withHighlightChange + onTap: _config.isEnabled && widget.onTap != null ? widget.onTap : null, + onLongPress: _config.isEnabled && widget.onHold != null ? widget.onHold : null, + onHighlightChanged: _config.withHighlightChange ? (v) { setState(() { _isHighlighted = v; @@ -133,9 +129,9 @@ class _AstromicButtonBaseState extends State { : null, // child: Padding( - padding: widget.style(widget.isEnabled, _isHighlighted).contentPadding ?? EdgeInsets.zero, + padding: _style.contentPadding ?? EdgeInsets.zero, child: widget.child( - widget.isEnabled, + _config.isEnabled, _isHighlighted, ), ), diff --git a/lib/src/Buttons/src/enums/enums.exports.dart b/lib/src/Buttons/src/enums/enums.exports.dart new file mode 100644 index 0000000..2c39c52 --- /dev/null +++ b/lib/src/Buttons/src/enums/enums.exports.dart @@ -0,0 +1 @@ +export './sizing_strategy.enum.dart'; diff --git a/lib/src/Buttons/src/enums/sizing_strategy.enum.dart b/lib/src/Buttons/src/enums/sizing_strategy.enum.dart new file mode 100644 index 0000000..b80cc7c --- /dev/null +++ b/lib/src/Buttons/src/enums/sizing_strategy.enum.dart @@ -0,0 +1,6 @@ +/// Sizing strategy for how the element is sized in it's bounds; Fill it, Hug it's content, or Fixed. +enum AstromicSizingStrategy { + hug, + fill, + fixed, +} diff --git a/lib/src/Buttons/src/icon_button.dart b/lib/src/Buttons/src/icon_button.dart index 360bf36..4136da0 100644 --- a/lib/src/Buttons/src/icon_button.dart +++ b/lib/src/Buttons/src/icon_button.dart @@ -1,23 +1,15 @@ -//SECTION - Imports -// -//s1 PACKAGES -//--------------- -//s2 CORE +//s1 Imports +//s2 Core Package Imports import 'package:flutter/material.dart'; +//s2 1st-party Package Imports +//s2 3rd-party Package Imports +//s2 Dependancies Imports +//s3 Routes +//s3 Services +//s3 Models import 'base.dart'; -import 'style.dart'; -//s2 3RD-PARTY -// -//s1 DEPENDENCIES -//--------------- -//s2 SERVICES -//s2 MODELS -//s2 MISC -//!SECTION - Imports -// -//SECTION - Exports -//!SECTION - Exports -// +import 'models/models.exports.dart'; +//s1 Exports class AstromicIconButton extends StatefulWidget { //SECTION - Widget Arguments @@ -25,12 +17,8 @@ class AstromicIconButton extends StatefulWidget { final void Function(VoidCallback start, VoidCallback stop)? onTap; final Function(VoidCallback start, VoidCallback stop)? onHold; //s1 -- Configurations - final bool isEnabled; - final bool withFeedback; - final bool withHighlightChange; - final TextDirection textDirection; + final AstromicButtonConfiguration? configuration; //s1 -- Style - final InteractiveInkFeatureFactory? splashFactory; final bool isCircular; final AstromicButtonStyle Function(bool isEnabled, bool isHighlighted, bool isLoading)? style; //s1 -- Content @@ -44,13 +32,9 @@ class AstromicIconButton extends StatefulWidget { this.onTap, this.onHold, // - required this.isEnabled, - required this.withFeedback, - required this.withHighlightChange, - required this.textDirection, + this.configuration, //s1 -- Style - this.splashFactory, - required this.isCircular, + this.isCircular = true, this.style, //s1 -- Content this.loadingContent, @@ -103,10 +87,7 @@ class _AstromicIconButtonState extends State { //s1 -Widgets //----- Widget baseChild = AstromicButtonBase( - isEnabled: widget.isEnabled, - withFeedback: widget.withFeedback, - withHighlightChange: widget.withHighlightChange, - textDirection: widget.textDirection, + configuration: widget.configuration, // onTap: !isLoading && context.mounted && widget.onTap != null ? () { @@ -134,10 +115,11 @@ class _AstromicIconButtonState extends State { }); } : null, - splashFactory: widget.splashFactory, - style: (enabled, highlighted) => widget.style!(enabled, highlighted, isLoading).copyWith( - borderRadius: widget.isCircular ? BorderRadiusDirectional.circular(100000000000) : null, - ), + style: widget.style == null + ? null + : (enabled, highlighted) => widget.style!.call(enabled, highlighted, isLoading).copyWith( + borderRadius: widget.isCircular ? BorderRadiusDirectional.circular(100000000000) : null, + ), child: (enabled, highlighted) => isLoading && widget.loadingContent != null ? widget.loadingContent! : widget.icon(enabled, highlighted), ); diff --git a/lib/src/Buttons/src/link_button.dart b/lib/src/Buttons/src/link_button.dart index 114d939..8dc1d7f 100644 --- a/lib/src/Buttons/src/link_button.dart +++ b/lib/src/Buttons/src/link_button.dart @@ -1,32 +1,23 @@ -//SECTION - Imports -// -//s1 PACKAGES -//--------------- -//s2 CORE +//s1 Imports +//s2 Core Package Imports import 'package:flutter/material.dart'; -//s2 3RD-PARTY -// -//s1 DEPENDENCIES -//--------------- -//s2 SERVICES -//s2 MODELS -//s2 MISC +//s2 1st-party Package Imports +//s2 3rd-party Package Imports +//s2 Dependancies Imports +//s3 Routes +//s3 Services +//s3 Models import 'base.dart'; -import 'style.dart'; +import 'models/models.exports.dart'; +//s1 Exports -//!SECTION - Imports -// -//SECTION - Exports -//!SECTION - Exports -// class AstromicLinkButton extends StatelessWidget { //SECTION - Widget Arguments //s1 -- Functionality final VoidCallback? onTap; final VoidCallback? onHold; //s1 -- Configurations - final bool isEnabled; - final TextDirection textDirection; + final AstromicButtonConfiguration? configuration; //s1 -- Style final bool Function(bool isEnabled) isUnderlined; final EdgeInsetsGeometry? contentPadding; @@ -45,8 +36,7 @@ class AstromicLinkButton extends StatelessWidget { this.onTap, this.onHold, //s1 -- Configurations - required this.isEnabled, - required this.textDirection, + this.configuration, //s1 -- Style required this.isUnderlined, this.contentPadding, @@ -76,16 +66,13 @@ class AstromicLinkButton extends StatelessWidget { mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, - textDirection: textDirection, + textDirection: configuration?.textDirection, children: [ AstromicButtonBase( onTap: onTap, onHold: onHold, // - isEnabled: isEnabled, - withFeedback: false, - withHighlightChange: false, - textDirection: textDirection, + configuration: configuration, // style: (isEnabled, isHighlighted) => AstromicButtonStyle( contentPadding: contentPadding, diff --git a/lib/src/Buttons/src/models/configuration.model.dart b/lib/src/Buttons/src/models/configuration.model.dart new file mode 100644 index 0000000..3c3a259 --- /dev/null +++ b/lib/src/Buttons/src/models/configuration.model.dart @@ -0,0 +1,30 @@ +// ignore_for_file: public_member_api_docs, sort_constructors_first +import 'package:flutter/widgets.dart'; + +/// Configuration model for the button element. +class AstromicButtonConfiguration { + final bool isEnabled; + final bool withFeedback; + final bool withHighlightChange; + final TextDirection textDirection; + AstromicButtonConfiguration({ + required this.isEnabled, + required this.withFeedback, + required this.withHighlightChange, + required this.textDirection, + }); + + AstromicButtonConfiguration copyWith({ + bool? isEnabled, + bool? withFeedback, + bool? withHighlightChange, + TextDirection? textDirection, + }) { + return AstromicButtonConfiguration( + isEnabled: isEnabled ?? this.isEnabled, + withFeedback: withFeedback ?? this.withFeedback, + withHighlightChange: withHighlightChange ?? this.withHighlightChange, + textDirection: textDirection ?? this.textDirection, + ); + } +} diff --git a/lib/src/Buttons/src/models/models.exports.dart b/lib/src/Buttons/src/models/models.exports.dart new file mode 100644 index 0000000..40d868b --- /dev/null +++ b/lib/src/Buttons/src/models/models.exports.dart @@ -0,0 +1,2 @@ +export 'style.model.dart'; +export 'configuration.model.dart'; diff --git a/lib/src/Buttons/src/style.dart b/lib/src/Buttons/src/models/style.model.dart similarity index 82% rename from lib/src/Buttons/src/style.dart rename to lib/src/Buttons/src/models/style.model.dart index f0ba198..e3c4704 100644 --- a/lib/src/Buttons/src/style.dart +++ b/lib/src/Buttons/src/models/style.model.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; +/// Styling model for the button element. class AstromicButtonStyle { //s1 -- Colors final Color? backgroundColor; @@ -8,6 +9,7 @@ class AstromicButtonStyle { final Color? splashColor; final Color? highlightColor; final Color? borderColor; + final Gradient? borderGradient; // //s1 -- Spacing & Insets final double? fixedHeight; @@ -15,6 +17,8 @@ class AstromicButtonStyle { final EdgeInsetsGeometry? contentPadding; final BorderRadiusGeometry? borderRadius; final double? borderWidth; + //s1 -- Interactions + final InteractiveInkFeatureFactory? splashFactory; const AstromicButtonStyle({ this.backgroundColor = Colors.transparent, this.backgroundGradient, @@ -22,6 +26,7 @@ class AstromicButtonStyle { this.splashColor, this.highlightColor, this.borderColor, + this.borderGradient, // this.fixedHeight, this.fixedWidth, @@ -29,6 +34,8 @@ class AstromicButtonStyle { this.borderRadius, this.borderWidth, // + this.splashFactory, + // }); AstromicButtonStyle copyWith({ @@ -38,11 +45,13 @@ class AstromicButtonStyle { Color? splashColor, Color? highlightColor, Color? borderColor, + Gradient? borderGradient, double? fixedHeight, double? fixedWidth, EdgeInsetsGeometry? contentPadding, BorderRadiusGeometry? borderRadius, double? borderWidth, + InteractiveInkFeatureFactory? splashFactory, }) { return AstromicButtonStyle( backgroundGradient: backgroundGradient ?? this.backgroundGradient, @@ -51,11 +60,13 @@ class AstromicButtonStyle { splashColor: splashColor ?? this.splashColor, highlightColor: highlightColor ?? this.highlightColor, borderColor: borderColor ?? this.borderColor, + borderGradient: borderGradient ?? this.borderGradient, fixedHeight: fixedHeight == -1 ? null : fixedHeight ?? this.fixedHeight, fixedWidth: fixedWidth == -1 ? null : fixedWidth ?? this.fixedWidth, contentPadding: contentPadding ?? this.contentPadding, borderRadius: borderRadius ?? this.borderRadius, borderWidth: borderWidth ?? this.borderWidth, + splashFactory: splashFactory ?? this.splashFactory, ); } } diff --git a/lib/src/Buttons/src/sizing_strategy.enum.dart b/lib/src/Buttons/src/sizing_strategy.enum.dart deleted file mode 100644 index 71eede4..0000000 --- a/lib/src/Buttons/src/sizing_strategy.enum.dart +++ /dev/null @@ -1,5 +0,0 @@ -enum SizingStrategy { - hug, - fill, - fixed, -} diff --git a/lib/src/Buttons/src/state_button.dart b/lib/src/Buttons/src/state_button.dart index 0c77f8d..0a11a97 100644 --- a/lib/src/Buttons/src/state_button.dart +++ b/lib/src/Buttons/src/state_button.dart @@ -1,24 +1,16 @@ -//SECTION - Imports -// -//s1 PACKAGES -//--------------- -//s2 CORE +//s1 Imports +//s2 Core Package Imports import 'package:flutter/material.dart'; +//s2 1st-party Package Imports +//s2 3rd-party Package Imports +//s2 Dependancies Imports +//s3 Routes +//s3 Services +//s3 Models import 'base.dart'; -//s2 3RD-PARTY -// -//s1 DEPENDENCIES -//--------------- -//s2 SERVICES -//s2 MODELS -import 'sizing_strategy.enum.dart'; -import 'style.dart'; -//s2 MISC -//!SECTION - Imports -// -//SECTION - Exports -//!SECTION - Exports -// +import 'enums/enums.exports.dart'; +import 'models/models.exports.dart'; +//s1 Exports class AstromicStateButton extends StatefulWidget { //SECTION - Widget Arguments @@ -26,14 +18,11 @@ class AstromicStateButton extends StatefulWidget { final void Function(VoidCallback start, VoidCallback stop)? onTap; final Function(VoidCallback start, VoidCallback stop)? onHold; //s1 -- Configurations - final bool isEnabled; - final bool withFeedback; - final bool withHighlightChange; - final TextDirection textDirection; + final AstromicButtonConfiguration? configuration; + //s1 -- Style - final SizingStrategy? widthSizingStrategy; - final SizingStrategy? heightSizingStrategy; - final InteractiveInkFeatureFactory? splashFactory; + final AstromicSizingStrategy? widthSizingStrategy; + final AstromicSizingStrategy? heightSizingStrategy; final AstromicButtonStyle Function(bool isEnabled, bool isHighlighted, bool isLoading)? style; //s1 -- Content final Widget? loadingContent; @@ -46,19 +35,15 @@ class AstromicStateButton extends StatefulWidget { this.onTap, this.onHold, // - required this.isEnabled, - required this.withFeedback, - required this.withHighlightChange, - required this.textDirection, + this.configuration, //s1 -- Style - this.widthSizingStrategy = SizingStrategy.hug, - this.heightSizingStrategy = SizingStrategy.hug, - this.splashFactory, + this.widthSizingStrategy = AstromicSizingStrategy.hug, + this.heightSizingStrategy = AstromicSizingStrategy.hug, this.style, //s1 -- Content this.loadingContent, required this.content, - }) : assert(heightSizingStrategy != SizingStrategy.fill, 'Height strategy cannot be fill'); + }) : assert(heightSizingStrategy != AstromicSizingStrategy.fill, 'Height strategy cannot be fill'); @override State createState() => _AstromicStateButtonState(); @@ -106,10 +91,7 @@ class _AstromicStateButtonState extends State { //s1 -Widgets //----- Widget baseChild = AstromicButtonBase( - isEnabled: widget.isEnabled, - withFeedback: widget.withFeedback, - withHighlightChange: widget.withHighlightChange, - textDirection: widget.textDirection, + configuration: widget.configuration, // onTap: !isLoading && context.mounted && widget.onTap != null ? () { @@ -137,16 +119,15 @@ class _AstromicStateButtonState extends State { }); } : null, - splashFactory: widget.splashFactory, style: (enabled, highlighted) => widget.style!(enabled, highlighted, isLoading).copyWith( - contentPadding: widget.heightSizingStrategy == SizingStrategy.fixed && widget.widthSizingStrategy == SizingStrategy.fixed + contentPadding: widget.heightSizingStrategy == AstromicSizingStrategy.fixed && widget.widthSizingStrategy == AstromicSizingStrategy.fixed ? EdgeInsets.zero - : widget.heightSizingStrategy == SizingStrategy.fixed && widget.widthSizingStrategy != SizingStrategy.fixed + : widget.heightSizingStrategy == AstromicSizingStrategy.fixed && widget.widthSizingStrategy != AstromicSizingStrategy.fixed ? EdgeInsets.symmetric( horizontal: widget.style!(enabled, highlighted, isLoading).contentPadding?.horizontal ?? 0, vertical: 0, ) - : widget.widthSizingStrategy == SizingStrategy.fixed && widget.heightSizingStrategy != SizingStrategy.fixed + : widget.widthSizingStrategy == AstromicSizingStrategy.fixed && widget.heightSizingStrategy != AstromicSizingStrategy.fixed ? EdgeInsets.symmetric( vertical: widget.style!(enabled, highlighted, isLoading).contentPadding?.vertical ?? 0, horizontal: 0, @@ -161,18 +142,24 @@ class _AstromicStateButtonState extends State { //SECTION - Build Return return Row( - mainAxisSize: widget.widthSizingStrategy == SizingStrategy.hug ? MainAxisSize.min : MainAxisSize.max, + mainAxisSize: widget.widthSizingStrategy == AstromicSizingStrategy.hug ? MainAxisSize.min : MainAxisSize.max, children: [ - widget.widthSizingStrategy == SizingStrategy.fill + widget.widthSizingStrategy == AstromicSizingStrategy.fill ? Expanded( child: SizedBox( - height: widget.heightSizingStrategy == SizingStrategy.fixed && widget.style != null ? widget.style!(widget.isEnabled, isHighlighted, isLoading).fixedHeight : null, + height: widget.heightSizingStrategy == AstromicSizingStrategy.fixed && widget.style != null + ? widget.style!(widget.configuration?.isEnabled ?? true, isHighlighted, isLoading).fixedHeight + : null, child: baseChild, ), ) : SizedBox( - width: widget.widthSizingStrategy == SizingStrategy.fixed && widget.style != null ? widget.style!(widget.isEnabled, isHighlighted, isLoading).fixedWidth : null, - height: widget.heightSizingStrategy == SizingStrategy.fixed && widget.style != null ? widget.style!(widget.isEnabled, isHighlighted, isLoading).fixedHeight : null, + width: widget.widthSizingStrategy == AstromicSizingStrategy.fixed && widget.style != null + ? widget.style!(widget.configuration?.isEnabled ?? true, isHighlighted, isLoading).fixedWidth + : null, + height: widget.heightSizingStrategy == AstromicSizingStrategy.fixed && widget.style != null + ? widget.style!(widget.configuration?.isEnabled ?? true, isHighlighted, isLoading).fixedHeight + : null, child: baseChild, ), ], diff --git a/lib/src/Fields/fields.astromic.dart b/lib/src/Fields/fields.astromic.dart index c4eb6c3..7fd4f3d 100644 --- a/lib/src/Fields/fields.astromic.dart +++ b/lib/src/Fields/fields.astromic.dart @@ -1,16 +1,14 @@ -import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; // -import 'src/action_field.dart'; import 'src/text_field.dart'; -import 'src/configuration.dart'; -import 'src/style.dart'; +import 'src/action_field.dart'; +import 'src/models/models.exports.dart'; // -export 'src/configuration.dart'; -export 'src/style.dart'; +export 'src/models/models.exports.dart'; +export 'src/enums/enums.exports.dart'; class AstromicFields { - //S1 -- Text Field + /// Astromic TextField element. static Widget text({ required TextEditingController controller, Key? stateKey, @@ -18,15 +16,9 @@ class AstromicFields { void Function(String v)? onChanged, void Function(String v)? onSubmited, // - required AstromicFieldConfiguration configuration, + AstromicFieldConfiguration? configuration, // - AutovalidateMode? validatingMode, - String? Function(bool isEnabled, bool isFocused, String? text)? validator, - List? inputFormatters, - bool? obscureText, - // - // - required AstromicFieldStyle Function(bool isEnabled, bool isFocused) style, + AstromicFieldStyle Function(bool isEnabled, bool isFocused)? style, // String? hint, // @@ -44,10 +36,6 @@ class AstromicFields { onChanged: onChanged, onSubmited: onSubmited, configuration: configuration, - validatingMode: validatingMode, - validator: validator, - inputFormatters: inputFormatters, - obscureText: obscureText, style: style, hint: hint, prefixWidget: prefixWidget, @@ -58,7 +46,7 @@ class AstromicFields { ], ); - //S1 -- Action Field + /// Astromic ActionField element. static Widget action( {Key? stateKey, (T item, String label)? initialValue, @@ -66,15 +54,13 @@ class AstromicFields { // Future<(T item, String label)?> Function((T item, String label)? currentValue)? onTap, Future<(T item, String label)?> Function((T item, String label)? currentValue)? onHold, - required String Function(String? oldValue, String newValue) textFieldMapper, + + /// Map the old controller value and the new selected value to how it will look in the field. e.g Adding a new choosen value as a list in the field. + required String Function(String? oldValue, String newValue) onValueChangedMapper, // - required AstromicFieldConfiguration configuration, + AstromicFieldConfiguration? configuration, // - AutovalidateMode? validatingMode, - String? Function(bool isEnabled, String? text)? validator, - List? inputFormatters, - // - required AstromicFieldStyle Function(bool isEnabled) style, + AstromicFieldStyle Function(bool isEnabled)? style, // String? hint, // @@ -89,11 +75,8 @@ class AstromicFields { initialValue: initialValue, onTap: onTap, onHold: onHold, - textFieldMapper: textFieldMapper, + onValueChangedMapper: onValueChangedMapper, configuration: configuration, - validatingMode: validatingMode, - validator: validator, - inputFormatters: inputFormatters, style: style, hint: hint, prefixWidget: prefixWidget, diff --git a/lib/src/Fields/src/action_field.dart b/lib/src/Fields/src/action_field.dart index 634f065..715cc00 100644 --- a/lib/src/Fields/src/action_field.dart +++ b/lib/src/Fields/src/action_field.dart @@ -1,51 +1,31 @@ -// ignore_for_file: depend_on_referenced_packages -//SECTION - Imports -// -//s1 PACKAGES -//--------------- -//s2 CORE -import '../../../Infrastructure/insets_extension.dart'; -import '../../../Infrastructure/misc_extensions.dart'; -import '../../../astromic_mobile_elements.dart'; +//s1 Imports +//s2 Core Package Imports import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:intl/intl.dart' as intl; -import 'dart:ui' as ui; +//s2 1st-party Package Imports +//s2 3rd-party Package Imports +//s2 Dependancies Imports +//s3 Routes +//s3 Services +//s3 Models +import 'base.dart'; +import 'models/models.exports.dart'; +//s1 Exports -//s2 3RD-PARTY -// -//s1 DEPENDENCIES -//--------------- -//s2 SERVICES -//s2 MODELS - -//s2 MISC - -//!SECTION - Imports -// -//SECTION - Exports -//!SECTION - Exports -// class AstromicActionField extends StatefulWidget { //SECTION - Widget Arguments //s1 -- Functionality final Key? stateKey; - final (T item, String label)? initialValue; final TextEditingController textController; + final (T item, String label)? initialValue; final Future<(T item, String label)?> Function((T item, String label)? currentValue)? onTap; final Future<(T item, String label)?> Function((T item, String label)? currentValue)? onHold; - final String Function(String? oldValue, String newValue) textFieldMapper; + final String Function(String? oldValue, String newValue) onValueChangedMapper; // //s1 -- Configurations - final AstromicFieldConfiguration configuration; - // - final AutovalidateMode? validatingMode; - final String? Function(bool isEnabled, String? text)? validator; - final List? inputFormatters; - final bool? obscureText; + final AstromicFieldConfiguration? configuration; // //s1 -- Style - final AstromicFieldStyle Function(bool isEnabled) style; + final AstromicFieldStyle Function(bool isEnabled)? style; // //s1 -- Content final String? hint; @@ -61,18 +41,12 @@ class AstromicActionField extends StatefulWidget { this.initialValue, this.stateKey, required this.textController, - required this.textFieldMapper, + required this.onValueChangedMapper, this.onTap, this.onHold, // - required this.configuration, - // - this.validatingMode, - this.validator, - this.inputFormatters, - this.obscureText, - // - required this.style, + this.configuration, + this.style, // this.hint, this.prefixWidget, @@ -87,15 +61,14 @@ class AstromicActionField extends StatefulWidget { class _AstromicActionFieldState extends State> { // //SECTION - State Variables + //s1 --State + (T item, String label)? _currentValue; + //s1 --State + // //s1 --Controllers late TextEditingController _textController; //s1 --Controllers // - //s1 --State - (T item, String label)? _currentValue; - // - //s1 --State - // //s1 --Constants //s1 --Constants //!SECTION @@ -105,15 +78,15 @@ class _AstromicActionFieldState extends State> { super.initState(); // //SECTION - State Variables initializations & Listeners + //s1 --State + //s1 --State + // //s1 --Controllers & Listeners _currentValue = widget.initialValue; _textController = widget.textController; - _textController.text = widget.initialValue?.$2 ?? ''; + _textController.text = _currentValue?.$2 ?? ''; //s1 --Controllers & Listeners // - //s1 --State - //s1 --State - // //s1 --Late & Async Initializers //s1 --Late & Async Initializers //!SECTION @@ -126,6 +99,10 @@ class _AstromicActionFieldState extends State> { //SECTION - State Variables initializations & Listeners //s1 --State //s1 --State + // + //s1 --Controllers & Listeners + //s1 --Controllers & Listeners + // //!SECTION } @@ -133,81 +110,6 @@ class _AstromicActionFieldState extends State> { //!SECTION //SECTION - Stateless functions - getTextHeight(String text, TextStyle style, ui.TextDirection direction) { - final span = TextSpan(text: text, style: style); - final tp = TextPainter(text: span, textDirection: direction); - tp.layout(maxWidth: double.infinity); - return tp.height; - } - - //- - //---------------------------------------------------------------- - //- - - ui.TextDirection finalTextDirection() { - ui.TextDirection fromLocale = intl.Bidi.isRtlLanguage(Localizations.localeOf(context).languageCode) ? ui.TextDirection.rtl : ui.TextDirection.ltr; - // - if (widget.configuration.textDirection != null) { - // Get form Style - return widget.configuration.textDirection!; - } else { - // Detect form Text - return _textController.text != '' - ? widget.configuration.withAutomaticDirectionalitySwitching - ? intl.Bidi.startsWithLtr(_textController.text) - ? ui.TextDirection.ltr - : ui.TextDirection.rtl - : fromLocale - : fromLocale; - } - } - - //- - //---------------------------------------------------------------- - //- - EdgeInsetsGeometry finalVerticalPadding( - AstromicFieldStyle style, { - bool forceRespectBorder = false, - }) { - double desiredFixedHeight = style.fixedHeight ?? 0; - // - double providedPadding = style.contentPadding.vertical; - // - double borderOffset = widget.configuration.respectBorderWidthPadding || forceRespectBorder ? style.border?.borderSide.strokeInset ?? 0.0 : 0.0; - // - double fontOffset = getTextHeight( - widget.textController.text.isNotEmpty - ? widget.textController.text - : (widget.hint?.isNotEmpty ?? false) - ? widget.hint! - : "", - widget.textController.text.isNotEmpty && widget.style(widget.configuration.isEnabled).textStyle != null - ? widget.style(widget.configuration.isEnabled).textStyle! - : widget.style(widget.configuration.isEnabled).hintStyle != null - ? widget.style(widget.configuration.isEnabled).hintStyle! - : const TextStyle(), - finalTextDirection(), - ); - // - double finalVertical = - //- - widget.configuration.isFixedHeight - ? - //- - widget.configuration.isTextArea - ? - //s1 Fixed Height with Text Area - borderOffset + providedPadding - : - //s1 Fixed Height and not Text Area - desiredFixedHeight - (fontOffset + borderOffset) - //s1 - Not Fixed Height - : providedPadding + (borderOffset / 2); - // - return EdgeInsets.symmetric( - vertical: finalVertical / 2, - ); - } //!SECTION //SECTION - Action Callbacks @@ -222,195 +124,59 @@ class _AstromicActionFieldState extends State> { //s1 --Values // //s1 --Contexted Widgets - InputDecoration inputDecoration = InputDecoration( - //s1 -- Functionality - enabled: widget.configuration.isEnabled, - //s1 -- Configurations - isDense: true, - hintTextDirection: widget.configuration.hintDirection ?? finalTextDirection(), - //s1 -- Style - filled: widget.style(widget.configuration.isEnabled).isFilled, - fillColor: widget.style(widget.configuration.isEnabled).fillColor, - // - hintStyle: widget.style(widget.configuration.isEnabled).hintStyle, - // - enabledBorder: widget.style(widget.configuration.isEnabled).border, - focusedBorder: widget.style(widget.configuration.isEnabled).border, - disabledBorder: widget.style(widget.configuration.isEnabled).border, - errorBorder: widget.style(widget.configuration.isEnabled).border, - focusedErrorBorder: widget.style(widget.configuration.isEnabled).border, - // - errorStyle: const TextStyle(height: 0), - contentPadding: finalVerticalPadding(widget.style(widget.configuration.isEnabled)), - //s1 -- Content - hintText: widget.hint, - // - prefixIcon: widget.prefixWidget != null && - widget.prefixWidget!(widget.configuration.isEnabled, () { - setState(() {}); - }) != - null - ? Container( - margin: EdgeInsetsDirectional.fromSTEB( - widget.style(widget.configuration.isEnabled).prefixSpacing, 0, widget.style(widget.configuration.isEnabled).contentPadding.resolveToDirectional(finalTextDirection()).start, 0), - child: widget.prefixWidget!(widget.configuration.isEnabled, () { - setState(() {}); - }), - ) - : SizedBox(width: widget.style(widget.configuration.isEnabled).contentPadding.resolveToDirectional(finalTextDirection()).start), - // - prefixIconConstraints: widget.prefixWidget != null && - widget.prefixWidget!(widget.configuration.isEnabled, () { - setState(() {}); - }) != - null - ? widget.style(widget.configuration.isEnabled).prefixSize != 0 - ? BoxConstraints.expand( - width: widget.style(widget.configuration.isEnabled).prefixSize + - widget.style(widget.configuration.isEnabled).prefixSpacing + - widget.style(widget.configuration.isEnabled).contentPadding.resolveToDirectional(finalTextDirection()).start, - height: widget.style(widget.configuration.isEnabled).prefixSize, - ) - : const BoxConstraints.tightForFinite() - : BoxConstraints.tightForFinite(width: widget.style(widget.configuration.isEnabled).contentPadding.resolveToDirectional(finalTextDirection()).start), - // - suffixIcon: widget.suffixWidget != null && - widget.suffixWidget!(widget.configuration.isEnabled, () { - setState(() {}); - }) != - null - ? Container( - margin: EdgeInsetsDirectional.fromSTEB( - widget.style(widget.configuration.isEnabled).contentPadding.resolveToDirectional(finalTextDirection()).end, 0, widget.style(widget.configuration.isEnabled).suffixSpacing, 0), - child: widget.suffixWidget!(widget.configuration.isEnabled, () { - setState(() {}); - }), - ) - : SizedBox(width: widget.style(widget.configuration.isEnabled).contentPadding.resolveToDirectional(finalTextDirection()).end), - suffixIconConstraints: widget.suffixWidget != null && - widget.suffixWidget != null && - widget.suffixWidget!(widget.configuration.isEnabled, () { - setState(() {}); - }) != - null - ? widget.style(widget.configuration.isEnabled).suffixSize != 0 - ? BoxConstraints.expand( - width: widget.style(widget.configuration.isEnabled).suffixSize + - widget.style(widget.configuration.isEnabled).suffixSpacing + - widget.style(widget.configuration.isEnabled).contentPadding.resolveToDirectional(finalTextDirection()).end, - height: widget.style(widget.configuration.isEnabled).suffixSize, - ) - : const BoxConstraints.tightForFinite() - : BoxConstraints.tightForFinite(width: widget.style(widget.configuration.isEnabled).contentPadding.resolveToDirectional(finalTextDirection()).end), - ); //s1 --Contexted Widgets //!SECTION - // - //SECTION - Build Return - return Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Directionality( - textDirection: finalTextDirection(), - child: Container( - height: widget.configuration.isFixedHeight - ? !widget.configuration.isTextArea - ? null - : widget.style(widget.configuration.isEnabled).fixedHeight - : null, - alignment: widget.style(widget.configuration.isEnabled).textAlignVertical.toAlignment(), - child: Stack( - children: [ - TextFormField( - //s1 -- Functionality - key: widget.stateKey, - controller: _textController, - textInputAction: widget.configuration.inputAction, - // - //s1 -- Configurations - autovalidateMode: widget.validatingMode, - autofocus: widget.configuration.withAutofocus, - keyboardType: widget.configuration.inputType, - textDirection: finalTextDirection(), - obscureText: widget.configuration.withObscurity ? (widget.obscureText ?? false) : false, - inputFormatters: widget.inputFormatters, - // - minLines: widget.configuration.isFixedHeight && widget.configuration.isTextArea ? null : widget.style(widget.configuration.isEnabled).minLines, - maxLines: widget.configuration.isFixedHeight - ? widget.configuration.isTextArea - ? null - : widget.style(widget.configuration.isEnabled).maxLines - : widget.style(widget.configuration.isEnabled).maxLines, - // - maxLength: widget.style(widget.configuration.isEnabled).maxLength, - maxLengthEnforcement: widget.configuration.maxLengthEnforcement, - // - expands: widget.configuration.isFixedHeight && widget.configuration.isTextArea ? true : false, - // - Validation - validator: widget.validator != null ? (s) => widget.validator!(widget.configuration.isEnabled, s) : null, - // - Validation - //s1 -- Style - style: widget.style(widget.configuration.isEnabled).textStyle, - cursorColor: widget.style(widget.configuration.isEnabled).cursorColor, - textAlign: widget.style(widget.configuration.isEnabled).textAlign, - textAlignVertical: widget.style(widget.configuration.isEnabled).textAlignVertical, - // - //s1 -- Input Decoration - decoration: inputDecoration, - ), - SizedBox( - width: double.infinity, - height: finalVerticalPadding(widget.style(widget.configuration.isEnabled), forceRespectBorder: true).vertical * 2, - child: Material( - type: MaterialType.transparency, - child: InkWell( - onTap: () async { - if (widget.onTap != null) { - (T item, String label)? c = _currentValue; - (T item, String label)? newValue = await widget.onTap!(_currentValue); - if (newValue != null) { - setState(() { - _currentValue = newValue; - _textController.text = widget.textFieldMapper(c?.$2, newValue.$2); - }); - } - } - }, - splashFactory: NoSplash.splashFactory, - onLongPress: () async { - if (widget.onHold != null) { - (T item, String label)? c = _currentValue; - (T item, String label)? newValue = await widget.onHold!(_currentValue); - if (newValue != null) { - setState(() { - _currentValue = newValue; - _textController.text = widget.textFieldMapper(c?.$2, newValue.$2); - }); - } - } - }, - customBorder: widget.style(widget.configuration.isEnabled).border, - highlightColor: Colors.transparent, - ), - ), - ) - ], - ), + //SECTION - Build Return + + return AstromicFieldBase( + key: widget.key, + textController: _textController, + stateKey: widget.stateKey, + // onChanged: (v) {}, + // onSubmited: (v) {}, + configuration: widget.configuration, + style: widget.style == null ? null : (enabled, focused) => widget.style!(enabled), + hint: widget.hint, + prefixWidget: widget.prefixWidget == null ? null : (enabled, focused, stateSetter) => widget.prefixWidget!(enabled, stateSetter), + suffixWidget: widget.suffixWidget == null ? null : (enabled, focused, stateSetter) => widget.suffixWidget!(enabled, stateSetter), + messageBuilder: widget.messageBuilder == null ? null : (enabled, focused) => widget.messageBuilder!(enabled), + fieldStackedWidget: (finalHeight, border) => SizedBox( + width: double.infinity, + height: finalHeight, + child: Material( + type: MaterialType.transparency, + child: InkWell( + onTap: () async { + if (widget.onTap != null) { + (T item, String label)? c = _currentValue; + (T item, String label)? newValue = await widget.onTap!(_currentValue); + if (newValue != null) { + setState(() { + _currentValue = newValue; + _textController.text = widget.onValueChangedMapper(c?.$2, newValue.$2); + }); + } + } + }, + splashFactory: NoSplash.splashFactory, + onLongPress: () async { + if (widget.onHold != null) { + (T item, String label)? c = _currentValue; + (T item, String label)? newValue = await widget.onHold!(_currentValue); + if (newValue != null) { + setState(() { + _currentValue = newValue; + _textController.text = widget.onValueChangedMapper(c?.$2, newValue.$2); + }); + } + } + }, + customBorder: border, + highlightColor: Colors.transparent, ), ), - widget.messageBuilder != null && - widget.messageBuilder!( - widget.configuration.isEnabled, - ) != - null - ? Padding( - padding: widget.style(widget.configuration.isEnabled).messagePadding, - child: widget.messageBuilder!(widget.configuration.isEnabled) ?? Container(), - ) - : Container() - ], + ), ); //!SECTION } diff --git a/lib/src/Fields/src/base.dart b/lib/src/Fields/src/base.dart new file mode 100644 index 0000000..3703af6 --- /dev/null +++ b/lib/src/Fields/src/base.dart @@ -0,0 +1,450 @@ +//s1 Imports +//s2 Core Package Imports +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart' as intl; +import 'dart:ui' as ui; +//s2 1st-party Package Imports +import 'package:astromic_extensions/astromic_extensions.dart'; +//s2 3rd-party Package Imports +//s2 Dependancies Imports +//s3 Routes +//s3 Services +//s3 Models +import '../../../Dependencies/gradient_border/gradient_borders.dart'; +import '../../../Dependencies/gradient_border/input_borders/gradient_underline_input_border.dart'; +import 'enums/enums.exports.dart'; +import 'models/models.exports.dart'; +//s1 Exports + +class AstromicFieldBase extends StatefulWidget { + //SECTION - Widget Arguments + //s1 -- Functionality + final TextEditingController textController; + final Key? stateKey; + // + final void Function(String v)? onChanged; + final void Function(String v)? onSubmited; + // + //s1 -- Configurations + final AstromicFieldConfiguration? configuration; + // + //s1 -- Style + final AstromicFieldStyle Function(bool isEnabled, bool isFocused)? style; + // + //s1 -- Content + final Widget Function(double finalHeight, ShapeBorder? border)? fieldStackedWidget; + final String? hint; + // + final Widget? Function(bool isEnabled, bool isFocused, VoidCallback stateSetter)? prefixWidget; + final Widget? Function(bool isEnabled, bool isFocused, VoidCallback stateSetter)? suffixWidget; + final Widget? Function(bool isEnabled, bool isFocused)? messageBuilder; + // + final Iterable? contextButtons; + //!SECTION + // + const AstromicFieldBase({ + super.key, + // + required this.textController, + this.stateKey, + this.onChanged, + this.onSubmited, + // + this.configuration, + // + this.style, + // + this.fieldStackedWidget, + this.hint, + this.prefixWidget, + this.suffixWidget, + this.messageBuilder, + this.contextButtons, + }); + + @override + State createState() => _AstromicFieldBaseState(); +} + +class _AstromicFieldBaseState extends State { + // + //SECTION - State Variables + //s1 --Controllers + late TextEditingController _textController; + //s1 --Controllers + // + //s1 --State + // late bool widget.configuration.isEnabled; + final FocusNode _focusNode = FocusNode(); + late bool _isFocused; + // + late AstromicFieldStyle Function([bool isFocused]) _style; + late AstromicFieldConfiguration _config; + // + //s1 --State + // + //s1 --Constants + //s1 --Constants + //!SECTION + + @override + void initState() { + super.initState(); + // + //SECTION - State Variables initializations & Listeners + //s1 --Controllers & Listeners + _textController = widget.textController; + //s1 --Controllers & Listeners + // + //s1 --State + // widget.configuration.isEnabled = widget.configuration.isEnabled; + _isFocused = false; + //s1 --State + // + //s1 --Late & Async Initializers + //s1 --Late & Async Initializers + //!SECTION + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + // + //SECTION - State Variables initializations & Listeners + //s1 --State + _focusNode.addListener(() { + if (mounted) { + setState(() { + _isFocused = _focusNode.hasFocus; + }); + } + }); + //s1 --State + //!SECTION + } + + //SECTION - Dumb Widgets + //!SECTION + + //SECTION - Stateless functions + _getTextHeight(String text, TextStyle style, ui.TextDirection direction) { + final span = TextSpan(text: text, style: style); + final tp = TextPainter(text: span, textDirection: direction); + tp.layout(maxWidth: double.infinity); + return tp.height; + } + + ui.TextDirection _finalTextDirection() { + ui.TextDirection fromLocale = intl.Bidi.isRtlLanguage(Localizations.localeOf(context).languageCode) ? ui.TextDirection.rtl : ui.TextDirection.ltr; + // + if (_config.textDirection != null) { + // Get form Style + return _config.textDirection!; + } else { + // Detect form Text + return _textController.text != '' + ? _config.withAutomaticDirectionalitySwitching + ? intl.Bidi.startsWithLtr(_textController.text) + ? ui.TextDirection.ltr + : ui.TextDirection.rtl + : fromLocale + : fromLocale; + } + } + + EdgeInsetsGeometry _finalVerticalPadding( + AstromicFieldStyle style, { + bool? forceRespectBorder, + }) { + double desiredFixedHeight = style.fixedHeight ?? 0; + // + double providedPadding = style.contentPadding.vertical; + // + double borderOffset = (forceRespectBorder ?? _config.respectBorderWidthPadding) ? _finalBorderShape(style)?.borderSide.strokeInset ?? 0.0 : 0.0; + // + double fontOffset = _getTextHeight( + widget.textController.text.isNotEmpty + ? widget.textController.text + : (widget.hint?.isNotEmpty ?? false) + ? widget.hint! + : "", + widget.textController.text.isNotEmpty && _style().textStyle != null + ? _style().textStyle! + : _style().hintStyle != null + ? _style().hintStyle! + : const TextStyle(), + _finalTextDirection(), + ); + // + double finalVertical = + //- + _config.isFixedHeight + ? + //- + _config.isTextArea + ? + //s1 Fixed Height with Text Area + borderOffset + providedPadding + : + //s1 Fixed Height and not Text Area + desiredFixedHeight - (fontOffset + borderOffset) + //s1 - Not Fixed Height + : providedPadding + borderOffset; + // + return EdgeInsets.symmetric( + vertical: finalVertical / 2, + ); + } + + InputBorder? _finalBorderShape(AstromicFieldStyle style) { + InputBorder defaultBorder = const UnderlineInputBorder(borderSide: BorderSide(color: Colors.grey, width: 2)); + + switch (style.borderType) { + case AstromicFieldBorderType.cusotm: + return style.customBorder ?? defaultBorder; + case AstromicFieldBorderType.outlined: + return style.borderGradient != null + ? GradientOutlineInputBorder( + gradient: style.borderGradient!, + gapPadding: 0, + width: style.borderWidth ?? 2.0, + borderRadius: style.borderRadius?.resolve( + _config.textDirection, + ) ?? + BorderRadius.circular(0)) + : OutlineInputBorder( + borderSide: BorderSide(color: style.borderColor ?? Colors.grey, width: style.borderWidth ?? 2.0, style: BorderStyle.solid), + borderRadius: style.borderRadius?.resolve( + _config.textDirection, + ) ?? + BorderRadius.circular(0)); + case AstromicFieldBorderType.underlined: + return style.borderGradient != null + ? GradientUnderlineInputBorder( + gradient: style.borderGradient!, + gapPadding: 0, + width: style.borderWidth ?? 2.0, + borderRadius: style.borderRadius?.resolve( + _config.textDirection, + ) ?? + BorderRadius.circular(0)) + : UnderlineInputBorder( + borderSide: BorderSide(color: style.borderColor ?? Colors.grey, width: style.borderWidth ?? 2.0, style: BorderStyle.solid), + borderRadius: style.borderRadius?.resolve( + _config.textDirection, + ) ?? + BorderRadius.circular(0)); + } + } + //!SECTION + + //SECTION - Action Callbacks + //!SECTION + + @override + Widget build(BuildContext context) { + //SECTION - Build Setup + //s1 --Values + //double w = MediaQuery.of(context).size.width; + //double h = MediaQuery.of(context).size.height; + _config = widget.configuration ?? const AstromicFieldConfiguration(); + _style = ([bool? isFocused]) => widget.style?.call(_config.isEnabled, isFocused ?? _isFocused) ?? const AstromicFieldStyle(); + //s1 --Values + // + //s1 --Contexted Widgets + InputDecoration inputDecoration = InputDecoration( + //s1 -- Functionality + enabled: _config.isEnabled, + //s1 -- Configurations + isDense: true, + hintTextDirection: _config.hintDirection ?? _finalTextDirection(), + //s1 -- Style + filled: _style().isFilled, + fillColor: _style().fillColor, + // + hintStyle: _style().hintStyle, + // + enabledBorder: _finalBorderShape(_style(false)), + focusedBorder: _finalBorderShape(_style(true)), + disabledBorder: _finalBorderShape(_style()), + errorBorder: _finalBorderShape(_style(false)), + focusedErrorBorder: _finalBorderShape(_style(true)), + // + errorStyle: const TextStyle(height: 0), + contentPadding: _finalVerticalPadding(_style()), + //s1 -- Content + hintText: widget.hint, + // + prefixIcon: widget.prefixWidget != null && + widget.prefixWidget!(_config.isEnabled, _isFocused, () { + setState(() {}); + }) != + null + ? Container( + margin: EdgeInsetsDirectional.fromSTEB(_style().prefixSpacing, 0, _style().contentPadding.resolveToDirectional(_finalTextDirection()).start, 0), + child: widget.prefixWidget!(_config.isEnabled, _isFocused, () { + setState(() {}); + }), + ) + : SizedBox(width: _style().contentPadding.resolveToDirectional(_finalTextDirection()).start), + // + prefixIconConstraints: widget.prefixWidget != null && + widget.prefixWidget!(_config.isEnabled, _isFocused, () { + setState(() {}); + }) != + null + ? _style().prefixSize != 0 + ? BoxConstraints.expand( + width: _style().prefixSize + _style().prefixSpacing + _style().contentPadding.resolveToDirectional(_finalTextDirection()).start, + height: _style().prefixSize, + ) + : const BoxConstraints.tightForFinite() + : BoxConstraints.tightForFinite(width: _style().contentPadding.resolveToDirectional(_finalTextDirection()).start), + // + suffixIcon: widget.suffixWidget != null && + widget.suffixWidget!(_config.isEnabled, _isFocused, () { + setState(() {}); + }) != + null + ? Container( + margin: EdgeInsetsDirectional.fromSTEB(_style().contentPadding.resolveToDirectional(_finalTextDirection()).end, 0, _style().suffixSpacing, 0), + child: widget.suffixWidget!(_config.isEnabled, _isFocused, () { + setState(() {}); + }), + ) + : SizedBox(width: _style().contentPadding.resolveToDirectional(_finalTextDirection()).end), + suffixIconConstraints: widget.suffixWidget != null && + widget.suffixWidget != null && + widget.suffixWidget!(_config.isEnabled, _isFocused, () { + setState(() {}); + }) != + null + ? _style().suffixSize != 0 + ? BoxConstraints.expand( + width: _style().suffixSize + _style().suffixSpacing + _style().contentPadding.resolveToDirectional(_finalTextDirection()).end, + height: _style().suffixSize, + ) + : const BoxConstraints.tightForFinite() + : BoxConstraints.tightForFinite(width: _style().contentPadding.resolveToDirectional(_finalTextDirection()).end), + ); + //s1 --Contexted Widgets + //!SECTION + // + //SECTION - Build Return + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Directionality( + textDirection: _finalTextDirection(), + child: Container( + height: _config.isFixedHeight + ? !_config.isTextArea + ? null + : _style().fixedHeight + : null, + alignment: _style().textAlignVertical.toAlignment(), + child: Stack( + children: [ + TextFormField( + //s1 -- Functionality + key: widget.stateKey, + controller: _textController, + focusNode: _focusNode, + textInputAction: _config.inputAction, + // + onChanged: (v) { + setState(() { + if (widget.onChanged != null) { + widget.onChanged!(v); + } + }); + }, + // + onFieldSubmitted: (v) { + // + if (_config.inputAction == TextInputAction.next) { + _focusNode.nextFocus(); + } + if (widget.onSubmited != null) { + widget.onSubmited!(v); + } + }, + // + onTapOutside: (tapEvent) { + if (_config.unfocusOnTapOutside) { + _focusNode.unfocus(); + } + }, + // + //s1 -- Configurations + autovalidateMode: _config.validatingMode, + autofocus: _config.withAutofocus, + keyboardType: _config.inputType, + textDirection: _finalTextDirection(), + obscureText: _config.withObscurity ? (_config.isTextObscured ?? false) : false, + inputFormatters: _config.inputFormatters, + // + minLines: _config.isFixedHeight && _config.isTextArea ? null : _style().minLines, + maxLines: _config.isFixedHeight + ? _config.isTextArea + ? null + : _style().maxLines + : _style().maxLines, + + // + maxLength: _style().maxLength, + maxLengthEnforcement: _config.maxLengthEnforcement, + // + expands: _config.isFixedHeight && _config.isTextArea ? true : false, + // - Validation + validator: _config.validator != null ? (s) => _config.validator!(_config.isEnabled, _isFocused, s) : null, + // - Validation + //s1 -- Style + style: _style().textStyle, + cursorColor: _style().cursorColor, + textAlign: _style().textAlign, + textAlignVertical: _style().textAlignVertical, + // + //s1 -- Input Decoration + decoration: inputDecoration, + //s1 -- Content + contextMenuBuilder: (_, state) { + List baseContextButtons = state.contextMenuButtonItems; + if (widget.contextButtons != null) { + baseContextButtons.addAll(widget.contextButtons!); + } + return AdaptiveTextSelectionToolbar.buttonItems( + buttonItems: baseContextButtons, + anchors: state.contextMenuAnchors, + ); + }, + ), + widget.fieldStackedWidget != null ? widget.fieldStackedWidget!(_finalVerticalPadding(_style(), forceRespectBorder: true).vertical * 2, _finalBorderShape(_style())) : Container(), + ], + ), + ), + ), + widget.messageBuilder != null && + widget.messageBuilder!( + _config.isEnabled, + _isFocused, + ) != + null + ? Padding( + padding: _style().messagePadding, + child: widget.messageBuilder!(_config.isEnabled, _isFocused) ?? Container(), + ) + : Container() + ], + ); + //!SECTION + } + + @override + void dispose() { + //SECTION - Disposable variables + //!SECTION + super.dispose(); + } +} diff --git a/lib/src/Fields/src/enums/border_type.enum.dart b/lib/src/Fields/src/enums/border_type.enum.dart new file mode 100644 index 0000000..a28dbf5 --- /dev/null +++ b/lib/src/Fields/src/enums/border_type.enum.dart @@ -0,0 +1,5 @@ +enum AstromicFieldBorderType { + outlined, + underlined, + cusotm, +} diff --git a/lib/src/Fields/src/enums/enums.exports.dart b/lib/src/Fields/src/enums/enums.exports.dart new file mode 100644 index 0000000..ff95ce4 --- /dev/null +++ b/lib/src/Fields/src/enums/enums.exports.dart @@ -0,0 +1 @@ +export './border_type.enum.dart'; diff --git a/lib/src/Fields/src/configuration.dart b/lib/src/Fields/src/models/configuration.model.dart similarity index 75% rename from lib/src/Fields/src/configuration.dart rename to lib/src/Fields/src/models/configuration.model.dart index 9419040..814b8c0 100644 --- a/lib/src/Fields/src/configuration.dart +++ b/lib/src/Fields/src/models/configuration.model.dart @@ -1,11 +1,13 @@ -// ignore_for_file: public_member_api_docs, sort_constructors_first import 'dart:ui' as ui; - +import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +/// Configuration model for the field element. class AstromicFieldConfiguration { // final bool isEnabled; + final bool? isTextObscured; final bool isFixedHeight; final bool isTextArea; // @@ -24,8 +26,13 @@ class AstromicFieldConfiguration { // final MaxLengthEnforcement maxLengthEnforcement; // + final AutovalidateMode? validatingMode; + final String? Function(bool isEnabled, bool isFocused, String? text)? validator; + final List? inputFormatters; + // const AstromicFieldConfiguration({ this.isEnabled = true, + this.isTextObscured = false, this.respectBorderWidthPadding = false, this.isFixedHeight = false, this.isTextArea = false, @@ -41,11 +48,17 @@ class AstromicFieldConfiguration { this.inputType = TextInputType.text, this.inputAction = TextInputAction.done, this.maxLengthEnforcement = MaxLengthEnforcement.none, + // + this.validatingMode, + this.validator, + this.inputFormatters, + // }); // AstromicFieldConfiguration copyWith({ bool? isEnabled, + bool? isTextObscured, bool? isFixedHeight, bool? isTextArea, bool? withAutofocus, @@ -60,9 +73,13 @@ class AstromicFieldConfiguration { TextInputAction? inputAction, TextCapitalization? capitalizationMode, MaxLengthEnforcement? maxLengthEnforcement, + AutovalidateMode? validatingMode, + String? Function(bool isEnabled, bool isFocused, String? text)? validator, + List? inputFormatters, }) { return AstromicFieldConfiguration( isEnabled: isEnabled ?? this.isEnabled, + isTextObscured: isTextObscured ?? this.isTextObscured, isFixedHeight: isFixedHeight ?? this.isFixedHeight, isTextArea: isTextArea ?? this.isTextArea, withAutofocus: withAutofocus ?? this.withAutofocus, @@ -76,6 +93,9 @@ class AstromicFieldConfiguration { inputType: inputType ?? this.inputType, inputAction: inputAction ?? this.inputAction, maxLengthEnforcement: maxLengthEnforcement ?? this.maxLengthEnforcement, + validatingMode: validatingMode ?? this.validatingMode, + validator: validator ?? this.validator, + inputFormatters: inputFormatters ?? this.inputFormatters, ); } } diff --git a/lib/src/Fields/src/models/models.exports.dart b/lib/src/Fields/src/models/models.exports.dart new file mode 100644 index 0000000..be581d0 --- /dev/null +++ b/lib/src/Fields/src/models/models.exports.dart @@ -0,0 +1,2 @@ +export './style.model.dart'; +export './configuration.model.dart'; diff --git a/lib/src/Fields/src/style.dart b/lib/src/Fields/src/models/style.model.dart similarity index 73% rename from lib/src/Fields/src/style.dart rename to lib/src/Fields/src/models/style.model.dart index d313a73..1b26f24 100644 --- a/lib/src/Fields/src/style.dart +++ b/lib/src/Fields/src/models/style.model.dart @@ -1,6 +1,7 @@ -// ignore_for_file: public_member_api_docs, sort_constructors_first import 'package:flutter/material.dart'; +import '../enums/border_type.enum.dart'; +/// Styling model for the field element. class AstromicFieldStyle { //s1 - Styling Configs final bool isFilled; @@ -16,6 +17,11 @@ class AstromicFieldStyle { /// Only works when it's a Text Area. final TextAlignVertical textAlignVertical; // + final BorderRadiusGeometry? borderRadius; + final double? borderWidth; + final AstromicFieldBorderType borderType; + final InputBorder? customBorder; + // final EdgeInsetsGeometry contentPadding; final EdgeInsetsGeometry messagePadding; // @@ -27,11 +33,11 @@ class AstromicFieldStyle { //s1 - Colors final Color fillColor; final Color? cursorColor; + final Color? borderColor; + final Gradient? borderGradient; //s1 - Styling final TextStyle? hintStyle; final TextStyle? textStyle; - //s1 - MISC - final InputBorder? border; const AstromicFieldStyle({ this.isFilled = true, @@ -43,6 +49,12 @@ class AstromicFieldStyle { this.textAlignVertical = TextAlignVertical.center, // this.fixedHeight, + // + this.borderRadius, + this.borderWidth, + this.borderType = AstromicFieldBorderType.underlined, + this.customBorder, + // this.contentPadding = EdgeInsets.zero, this.messagePadding = EdgeInsets.zero, this.prefixSpacing = 4, @@ -51,11 +63,11 @@ class AstromicFieldStyle { this.suffixSize = 24, // this.fillColor = const Color(0xffffffff), + this.borderColor, + this.borderGradient, this.cursorColor, this.hintStyle, this.textStyle, - // - this.border, }); // AstromicFieldStyle copyWith({ @@ -66,6 +78,10 @@ class AstromicFieldStyle { int? maxLength, TextAlign? textAlign, TextAlignVertical? textAlignVertical, + BorderRadiusGeometry? borderRadius, + double? borderWidth, + AstromicFieldBorderType? borderType, + InputBorder? customBorder, EdgeInsetsGeometry? contentPadding, EdgeInsetsGeometry? messagePadding, double? prefixSpacing, @@ -76,9 +92,10 @@ class AstromicFieldStyle { CrossAxisAlignment? suffixAlignment, Color? fillColor, Color? cursorColor, + Color? borderColor, + Gradient? borderGradient, TextStyle? hintStyle, TextStyle? textStyle, - InputBorder? border, }) { return AstromicFieldStyle( isFilled: isFilled ?? this.isFilled, @@ -88,6 +105,10 @@ class AstromicFieldStyle { maxLength: maxLength ?? this.maxLength, textAlign: textAlign ?? this.textAlign, textAlignVertical: textAlignVertical ?? this.textAlignVertical, + borderRadius: borderRadius ?? this.borderRadius, + borderWidth: borderWidth ?? this.borderWidth, + borderType: borderType ?? this.borderType, + customBorder: customBorder ?? this.customBorder, contentPadding: contentPadding ?? this.contentPadding, messagePadding: messagePadding ?? this.messagePadding, prefixSpacing: prefixSpacing ?? this.prefixSpacing, @@ -96,9 +117,10 @@ class AstromicFieldStyle { suffixSize: suffixSize ?? this.suffixSize, fillColor: fillColor ?? this.fillColor, cursorColor: cursorColor ?? this.cursorColor, + borderColor: borderColor ?? this.borderColor, + borderGradient: borderGradient ?? this.borderGradient, hintStyle: hintStyle ?? this.hintStyle, textStyle: textStyle ?? this.textStyle, - border: border ?? this.border, ); } // diff --git a/lib/src/Fields/src/text_field.dart b/lib/src/Fields/src/text_field.dart index 4af06bd..68a1cfa 100644 --- a/lib/src/Fields/src/text_field.dart +++ b/lib/src/Fields/src/text_field.dart @@ -1,33 +1,18 @@ -// ignore_for_file: depend_on_referenced_packages -//SECTION - Imports -// -//s1 PACKAGES -//--------------- -//s2 CORE +//s1 Imports +//s2 Core Package Imports import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:intl/intl.dart' as intl; -import 'dart:ui' as ui; +//s2 1st-party Package Imports +//s2 3rd-party Package Imports +//s2 Dependancies Imports +//s3 Routes +//s3 Services +//s3 Models +import 'base.dart'; +import 'models/models.exports.dart'; +//s1 Exports -//s2 3RD-PARTY -// -//s1 DEPENDENCIES -//--------------- -//s2 SERVICES -//s2 MODELS -import 'configuration.dart'; -import 'style.dart'; -//s2 MISC -import '../../../Infrastructure/insets_extension.dart'; -import '../../../Infrastructure/misc_extensions.dart'; - -//!SECTION - Imports -// -//SECTION - Exports -//!SECTION - Exports -// -class AstromicTextField extends StatefulWidget { - //SECTION - Widget Arguments +class AstromicTextField extends StatelessWidget { +//SECTION - Widget Arguments //s1 -- Functionality final TextEditingController textController; final Key? stateKey; @@ -36,15 +21,10 @@ class AstromicTextField extends StatefulWidget { final void Function(String v)? onSubmited; // //s1 -- Configurations - final AstromicFieldConfiguration configuration; - // - final AutovalidateMode? validatingMode; - final String? Function(bool isEnabled, bool isFocused, String? text)? validator; - final List? inputFormatters; - final bool? obscureText; + final AstromicFieldConfiguration? configuration; // //s1 -- Style - final AstromicFieldStyle Function(bool isEnabled, bool isFocused) style; + final AstromicFieldStyle Function(bool isEnabled, bool isFocused)? style; // //s1 -- Content final String? hint; @@ -64,14 +44,9 @@ class AstromicTextField extends StatefulWidget { this.onChanged, this.onSubmited, // - required this.configuration, + this.configuration, // - this.validatingMode, - this.validator, - this.inputFormatters, - this.obscureText, - // - required this.style, + this.style, // this.hint, this.prefixWidget, @@ -80,350 +55,33 @@ class AstromicTextField extends StatefulWidget { this.contextButtons, }); - @override - State createState() => _AstromicTextFieldState(); -} - -class _AstromicTextFieldState extends State { - // - //SECTION - State Variables - //s1 --Controllers - late TextEditingController _textController; - //s1 --Controllers - // - //s1 --State - // late bool widget.configuration.isEnabled; - final FocusNode _focusNode = FocusNode(); - late bool _isFocused; - // - //s1 --State - // - //s1 --Constants - //s1 --Constants - //!SECTION - - @override - void initState() { - super.initState(); - // - //SECTION - State Variables initializations & Listeners - //s1 --Controllers & Listeners - _textController = widget.textController; - //s1 --Controllers & Listeners - // - //s1 --State - // widget.configuration.isEnabled = widget.configuration.isEnabled; - _isFocused = false; - //s1 --State - // - //s1 --Late & Async Initializers - //s1 --Late & Async Initializers - //!SECTION - } - - @override - void didChangeDependencies() { - super.didChangeDependencies(); - // - //SECTION - State Variables initializations & Listeners - //s1 --State - _focusNode.addListener(() { - if (mounted) { - setState(() { - _isFocused = _focusNode.hasFocus; - }); - } - }); - //s1 --State - //!SECTION - } - - //SECTION - Dumb Widgets - //!SECTION - - //SECTION - Stateless functions - getTextHeight(String text, TextStyle style, ui.TextDirection direction) { - final span = TextSpan(text: text, style: style); - final tp = TextPainter(text: span, textDirection: direction); - tp.layout(maxWidth: double.infinity); - return tp.height; - } - - //- - //---------------------------------------------------------------- - //- - - ui.TextDirection finalTextDirection() { - ui.TextDirection fromLocale = intl.Bidi.isRtlLanguage(Localizations.localeOf(context).languageCode) ? ui.TextDirection.rtl : ui.TextDirection.ltr; - // - if (widget.configuration.textDirection != null) { - // Get form Style - return widget.configuration.textDirection!; - } else { - // Detect form Text - return _textController.text != '' - ? widget.configuration.withAutomaticDirectionalitySwitching - ? intl.Bidi.startsWithLtr(_textController.text) - ? ui.TextDirection.ltr - : ui.TextDirection.rtl - : fromLocale - : fromLocale; - } - } - - //- - //---------------------------------------------------------------- - //- - EdgeInsetsGeometry finalVerticalPadding( - AstromicFieldStyle style, - ) { - double desiredFixedHeight = style.fixedHeight ?? 0; - // - double providedPadding = style.contentPadding.vertical; - // - double borderOffset = widget.configuration.respectBorderWidthPadding ? style.border?.borderSide.strokeInset ?? 0.0 : 0.0; - // - double fontOffset = getTextHeight( - widget.textController.text.isNotEmpty - ? widget.textController.text - : (widget.hint?.isNotEmpty ?? false) - ? widget.hint! - : "", - widget.textController.text.isNotEmpty && widget.style(widget.configuration.isEnabled, _isFocused).textStyle != null - ? widget.style(widget.configuration.isEnabled, _isFocused).textStyle! - : widget.style(widget.configuration.isEnabled, _isFocused).hintStyle != null - ? widget.style(widget.configuration.isEnabled, _isFocused).hintStyle! - : const TextStyle(), - finalTextDirection(), - ); - // - double finalVertical = - //- - widget.configuration.isFixedHeight - ? - //- - widget.configuration.isTextArea - ? - //s1 Fixed Height with Text Area - borderOffset + providedPadding - : - //s1 Fixed Height and not Text Area - desiredFixedHeight - (fontOffset + borderOffset) - //s1 - Not Fixed Height - : providedPadding + borderOffset; - // - return EdgeInsets.symmetric( - vertical: finalVertical / 2, - ); - } - //!SECTION - - //SECTION - Action Callbacks - //!SECTION - @override Widget build(BuildContext context) { //SECTION - Build Setup - //s1 --Values + //s1 -Values //double w = MediaQuery.of(context).size.width; //double h = MediaQuery.of(context).size.height; - //s1 --Values + //s1 -Values // - //s1 --Contexted Widgets - InputDecoration inputDecoration = InputDecoration( - //s1 -- Functionality - enabled: widget.configuration.isEnabled, - //s1 -- Configurations - isDense: true, - hintTextDirection: widget.configuration.hintDirection ?? finalTextDirection(), - //s1 -- Style - filled: widget.style(widget.configuration.isEnabled, _isFocused).isFilled, - fillColor: widget.style(widget.configuration.isEnabled, _isFocused).fillColor, - // - hintStyle: widget.style(widget.configuration.isEnabled, _isFocused).hintStyle, - // - enabledBorder: widget.style(widget.configuration.isEnabled, false).border, - focusedBorder: widget.style(widget.configuration.isEnabled, true).border, - disabledBorder: widget.style(widget.configuration.isEnabled, _isFocused).border, - errorBorder: widget.style(widget.configuration.isEnabled, false).border, - focusedErrorBorder: widget.style(widget.configuration.isEnabled, true).border, - // - errorStyle: const TextStyle(height: 0), - contentPadding: finalVerticalPadding(widget.style(widget.configuration.isEnabled, _isFocused)), - //s1 -- Content - hintText: widget.hint, - // - prefixIcon: widget.prefixWidget != null && - widget.prefixWidget!(widget.configuration.isEnabled, _isFocused, () { - setState(() {}); - }) != - null - ? Container( - margin: EdgeInsetsDirectional.fromSTEB(widget.style(widget.configuration.isEnabled, _isFocused).prefixSpacing, 0, - widget.style(widget.configuration.isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).start, 0), - child: widget.prefixWidget!(widget.configuration.isEnabled, _isFocused, () { - setState(() {}); - }), - ) - : SizedBox(width: widget.style(widget.configuration.isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).start), - // - prefixIconConstraints: widget.prefixWidget != null && - widget.prefixWidget!(widget.configuration.isEnabled, _isFocused, () { - setState(() {}); - }) != - null - ? widget.style(widget.configuration.isEnabled, _isFocused).prefixSize != 0 - ? BoxConstraints.expand( - width: widget.style(widget.configuration.isEnabled, _isFocused).prefixSize + - widget.style(widget.configuration.isEnabled, _isFocused).prefixSpacing + - widget.style(widget.configuration.isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).start, - height: widget.style(widget.configuration.isEnabled, _isFocused).prefixSize, - ) - : const BoxConstraints.tightForFinite() - : BoxConstraints.tightForFinite(width: widget.style(widget.configuration.isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).start), - // - suffixIcon: widget.suffixWidget != null && - widget.suffixWidget!(widget.configuration.isEnabled, _isFocused, () { - setState(() {}); - }) != - null - ? Container( - margin: EdgeInsetsDirectional.fromSTEB(widget.style(widget.configuration.isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).end, 0, - widget.style(widget.configuration.isEnabled, _isFocused).suffixSpacing, 0), - child: widget.suffixWidget!(widget.configuration.isEnabled, _isFocused, () { - setState(() {}); - }), - ) - : SizedBox(width: widget.style(widget.configuration.isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).end), - suffixIconConstraints: widget.suffixWidget != null && - widget.suffixWidget != null && - widget.suffixWidget!(widget.configuration.isEnabled, _isFocused, () { - setState(() {}); - }) != - null - ? widget.style(widget.configuration.isEnabled, _isFocused).suffixSize != 0 - ? BoxConstraints.expand( - width: widget.style(widget.configuration.isEnabled, _isFocused).suffixSize + - widget.style(widget.configuration.isEnabled, _isFocused).suffixSpacing + - widget.style(widget.configuration.isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).end, - height: widget.style(widget.configuration.isEnabled, _isFocused).suffixSize, - ) - : const BoxConstraints.tightForFinite() - : BoxConstraints.tightForFinite(width: widget.style(widget.configuration.isEnabled, _isFocused).contentPadding.resolveToDirectional(finalTextDirection()).end), - ); - //s1 --Contexted Widgets + //s1 -Widgets + //s1 -Widgets //!SECTION - // + //SECTION - Build Return - return Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Directionality( - textDirection: finalTextDirection(), - child: Container( - height: widget.configuration.isFixedHeight - ? !widget.configuration.isTextArea - ? null - : widget.style(widget.configuration.isEnabled, _isFocused).fixedHeight - : null, - alignment: widget.style(widget.configuration.isEnabled, _isFocused).textAlignVertical.toAlignment(), - child: TextFormField( - //s1 -- Functionality - key: widget.stateKey, - controller: _textController, - focusNode: _focusNode, - textInputAction: widget.configuration.inputAction, - // - onChanged: (v) { - setState(() { - if (widget.onChanged != null) { - widget.onChanged!(v); - } - }); - }, - // - onFieldSubmitted: (v) { - // - if (widget.configuration.inputAction == TextInputAction.next) { - _focusNode.nextFocus(); - } - if (widget.onSubmited != null) { - widget.onSubmited!(v); - } - }, - // - onTapOutside: (tapEvent) { - if (widget.configuration.unfocusOnTapOutside) { - _focusNode.unfocus(); - } - }, - // - //s1 -- Configurations - autovalidateMode: widget.validatingMode, - autofocus: widget.configuration.withAutofocus, - keyboardType: widget.configuration.inputType, - textDirection: finalTextDirection(), - obscureText: widget.configuration.withObscurity ? (widget.obscureText ?? false) : false, - inputFormatters: widget.inputFormatters, - // - minLines: widget.configuration.isFixedHeight && widget.configuration.isTextArea ? null : widget.style(widget.configuration.isEnabled, _isFocused).minLines, - maxLines: widget.configuration.isFixedHeight - ? widget.configuration.isTextArea - ? null - : widget.style(widget.configuration.isEnabled, _isFocused).maxLines - : widget.style(widget.configuration.isEnabled, _isFocused).maxLines, - - // - maxLength: widget.style(widget.configuration.isEnabled, _isFocused).maxLength, - maxLengthEnforcement: widget.configuration.maxLengthEnforcement, - // - expands: widget.configuration.isFixedHeight && widget.configuration.isTextArea ? true : false, - // - Validation - validator: widget.validator != null ? (s) => widget.validator!(widget.configuration.isEnabled, _isFocused, s) : null, - // - Validation - //s1 -- Style - style: widget.style(widget.configuration.isEnabled, _isFocused).textStyle, - cursorColor: widget.style(widget.configuration.isEnabled, _isFocused).cursorColor, - textAlign: widget.style(widget.configuration.isEnabled, _isFocused).textAlign, - textAlignVertical: widget.style(widget.configuration.isEnabled, _isFocused).textAlignVertical, - // - //s1 -- Input Decoration - decoration: inputDecoration, - //s1 -- Content - contextMenuBuilder: (_, state) { - List baseContextButtons = state.contextMenuButtonItems; - if (widget.contextButtons != null) { - baseContextButtons.addAll(widget.contextButtons!); - } - return AdaptiveTextSelectionToolbar.buttonItems( - buttonItems: baseContextButtons, - anchors: state.contextMenuAnchors, - ); - }, - ), - ), - ), - widget.messageBuilder != null && - widget.messageBuilder!( - widget.configuration.isEnabled, - _isFocused, - ) != - null - ? Padding( - padding: widget.style(widget.configuration.isEnabled, _isFocused).messagePadding, - child: widget.messageBuilder!(widget.configuration.isEnabled, _isFocused) ?? Container(), - ) - : Container() - ], + return AstromicFieldBase( + key: key, + textController: textController, + stateKey: stateKey, + onChanged: onChanged, + onSubmited: onSubmited, + configuration: configuration, + style: style, + hint: hint, + prefixWidget: prefixWidget, + suffixWidget: suffixWidget, + messageBuilder: messageBuilder, + contextButtons: contextButtons, ); //!SECTION } - - @override - void dispose() { - //SECTION - Disposable variables - //!SECTION - super.dispose(); - } } diff --git a/lib/src/Selectors/selectors.astromic.dart b/lib/src/Selectors/selectors.astromic.dart index e10fabf..da20aa1 100644 --- a/lib/src/Selectors/selectors.astromic.dart +++ b/lib/src/Selectors/selectors.astromic.dart @@ -2,11 +2,11 @@ import 'package:flutter/widgets.dart'; import 'src/Radio/radio.selector.dart'; import 'src/Chip/chip.selector.dart'; -import 'src/Radio/configuration.dart'; -import 'src/Chip/configuration.dart'; +import 'src/Radio/models/configuration.model.dart'; +import 'src/Chip/models/configuration.model.dart'; // -export 'src/Radio/configuration.dart'; -export 'src/Chip/configuration.dart'; +export 'src/Radio/models/configuration.model.dart'; +export 'src/Chip/models/configuration.model.dart'; class AstromicSelectors { //S1 -- Radio diff --git a/lib/src/Selectors/src/Chip/chip.selector.dart b/lib/src/Selectors/src/Chip/chip.selector.dart index 65d245f..d892285 100644 --- a/lib/src/Selectors/src/Chip/chip.selector.dart +++ b/lib/src/Selectors/src/Chip/chip.selector.dart @@ -3,6 +3,7 @@ //s1 PACKAGES //--------------- //s2 CORE +import 'package:astromic_extensions/astromic_extensions.dart'; import 'package:flutter/material.dart'; //s2 3RD-PARTY // @@ -10,8 +11,7 @@ import 'package:flutter/material.dart'; //--------------- //s2 SERVICES //s2 MODELS -import '../../../../Infrastructure/list_extensions.dart'; -import 'configuration.dart'; +import 'models/configuration.model.dart'; //s2 MISC //!SECTION - Imports diff --git a/lib/src/Selectors/src/Chip/configuration.dart b/lib/src/Selectors/src/Chip/models/configuration.model.dart similarity index 100% rename from lib/src/Selectors/src/Chip/configuration.dart rename to lib/src/Selectors/src/Chip/models/configuration.model.dart diff --git a/lib/src/Selectors/src/Radio/configuration.dart b/lib/src/Selectors/src/Radio/models/configuration.model.dart similarity index 100% rename from lib/src/Selectors/src/Radio/configuration.dart rename to lib/src/Selectors/src/Radio/models/configuration.model.dart diff --git a/lib/src/Selectors/src/Radio/radio.selector.dart b/lib/src/Selectors/src/Radio/radio.selector.dart index abe60f1..fdff460 100644 --- a/lib/src/Selectors/src/Radio/radio.selector.dart +++ b/lib/src/Selectors/src/Radio/radio.selector.dart @@ -11,7 +11,7 @@ import 'package:flutter/widgets.dart'; //s2 SERVICES //s2 MODELS import '../../../Spacing/spacing.astromic.dart'; -import 'configuration.dart'; +import 'models/configuration.model.dart'; //s2 MISC //!SECTION - Imports // diff --git a/lib/src/Widgets/src/image.widget.dart b/lib/src/Widgets/src/image.widget.dart index 1c6f412..0543f16 100644 --- a/lib/src/Widgets/src/image.widget.dart +++ b/lib/src/Widgets/src/image.widget.dart @@ -4,7 +4,6 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:octo_image/octo_image.dart'; -import '../../../Infrastructure/transparent_image.dart'; Widget astromicImage( BuildContext context, { @@ -214,3 +213,73 @@ Widget astromicImage( ), ); } + +final Uint8List kTransparentImage = Uint8List.fromList([ + 0x89, + 0x50, + 0x4E, + 0x47, + 0x0D, + 0x0A, + 0x1A, + 0x0A, + 0x00, + 0x00, + 0x00, + 0x0D, + 0x49, + 0x48, + 0x44, + 0x52, + 0x00, + 0x00, + 0x00, + 0x01, + 0x00, + 0x00, + 0x00, + 0x01, + 0x08, + 0x06, + 0x00, + 0x00, + 0x00, + 0x1F, + 0x15, + 0xC4, + 0x89, + 0x00, + 0x00, + 0x00, + 0x0A, + 0x49, + 0x44, + 0x41, + 0x54, + 0x78, + 0x9C, + 0x63, + 0x00, + 0x01, + 0x00, + 0x00, + 0x05, + 0x00, + 0x01, + 0x0D, + 0x0A, + 0x2D, + 0xB4, + 0x00, + 0x00, + 0x00, + 0x00, + 0x49, + 0x45, + 0x4E, + 0x44, + 0xAE, + 0x42, + 0x60, + 0x82, +]); diff --git a/pubspec.yaml b/pubspec.yaml index a77b744..8546282 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,49 +1,28 @@ -##SECTION --Project Information -name: astromic_mobile_elements -description: The elements module of the Astromic Mobile Presentation System +name: astromic_elements +description: The elements module of the Astromic Presentation System publish_to: "none" -## App Version scheme: Major.Feature.Fixes+Build -version: 0.0.1+2 -##!SECTION --Project Information -# -# -##SECTION --Environment Constraints +version: 0.1.0 + environment: - sdk: ">=3.1.1 <4.0.0" - flutter: ">3.10.0" -##!SECTION --Environment Constraints -# -# -##SECTION -- Dependencies Overrides -# dependency_overrides: -# intl: ^0.18.1 -##!SECTION -- Dependencies Overrides -# -# -##SECTION --Development Dependencies + sdk: ">=3.6.0" + flutter: ">3.27.0" + dev_dependencies: - flutter_test: - sdk: flutter flutter_lints: ^2.0.3 - ## -##!SECTION --Development Dependencies -# -# -##SECTION --Dependencies + dependencies: flutter: sdk: flutter - ##S1 -- Widgets + astromic_extensions: + git: + url: https://git.micazi.dev/astromic_extensions.git cached_network_image: ^3.3.1 flutter_svg: ^2.0.10+1 octo_image: ^2.0.0 flutter_switch: ^0.3.2 intl: ^0.19.0 - # -##!SECTION --Dependencies -# -# -##SECTION --App Assets + + flutter: uses-material-design: true -##!SECTION --App Assets + diff --git a/pubspec_overrides.yaml b/pubspec_overrides.yaml new file mode 100644 index 0000000..0876870 --- /dev/null +++ b/pubspec_overrides.yaml @@ -0,0 +1,4 @@ +dependency_overrides: + astromic_extensions: + git: + url: https://git.prox/micazi/astromic_extensions.git