diff --git a/build/build-config.yml b/build/build-config.yml index 9ae248f8cb9..5cef505d104 100644 --- a/build/build-config.yml +++ b/build/build-config.yml @@ -38,3 +38,8 @@ config: dockerfile: flutter/docker/Dockerfile image-name: digit-ui-flutter + - name: builds/Digit-UI-Libraries/flutter/story-book-flutter + build: + - work-dir: flutter/digit-ui-components/storybook + dockerfile: flutter/docker/storybook/Dockerfile + image-name: story-book-flutter \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/.flutter-plugins b/flutter/digit-ui-components/digit_components/.flutter-plugins index cda07282a6d..02b4fc2eccc 100644 --- a/flutter/digit-ui-components/digit_components/.flutter-plugins +++ b/flutter/digit-ui-components/digit_components/.flutter-plugins @@ -1,20 +1,44 @@ # This is a generated file; do not edit or check into version control. +camera=/home/admin1/.pub-cache/hosted/pub.dev/camera-0.10.5+9/ +camera_android=/home/admin1/.pub-cache/hosted/pub.dev/camera_android-0.10.9+1/ +camera_avfoundation=/home/admin1/.pub-cache/hosted/pub.dev/camera_avfoundation-0.9.16/ +camera_web=/home/admin1/.pub-cache/hosted/pub.dev/camera_web-0.3.3/ +file_picker=/home/admin1/.pub-cache/hosted/pub.dev/file_picker-8.0.0+1/ +file_selector_linux=/home/admin1/.pub-cache/hosted/pub.dev/file_selector_linux-0.9.2+1/ +file_selector_macos=/home/admin1/.pub-cache/hosted/pub.dev/file_selector_macos-0.9.4/ +file_selector_windows=/home/admin1/.pub-cache/hosted/pub.dev/file_selector_windows-0.9.3+1/ +flutter_dropzone=/home/admin1/.pub-cache/hosted/pub.dev/flutter_dropzone-3.0.7/ +flutter_dropzone_web=/home/admin1/.pub-cache/hosted/pub.dev/flutter_dropzone_web-3.0.13/ flutter_keyboard_visibility=/home/admin1/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility-5.4.1/ flutter_keyboard_visibility_linux=/home/admin1/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_linux-1.0.0/ flutter_keyboard_visibility_macos=/home/admin1/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_macos-1.0.0/ flutter_keyboard_visibility_web=/home/admin1/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_web-2.0.0/ flutter_keyboard_visibility_windows=/home/admin1/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_windows-1.0.0/ +flutter_plugin_android_lifecycle=/home/admin1/.pub-cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.19/ fluttertoast=/home/admin1/.pub-cache/hosted/pub.dev/fluttertoast-8.2.4/ geolocator=/home/admin1/.pub-cache/hosted/pub.dev/geolocator-10.1.1/ geolocator_android=/home/admin1/.pub-cache/hosted/pub.dev/geolocator_android-4.5.2/ geolocator_apple=/home/admin1/.pub-cache/hosted/pub.dev/geolocator_apple-2.3.6/ geolocator_web=/home/admin1/.pub-cache/hosted/pub.dev/geolocator_web-2.2.1/ geolocator_windows=/home/admin1/.pub-cache/hosted/pub.dev/geolocator_windows-0.2.2/ +image_picker=/home/admin1/.pub-cache/hosted/pub.dev/image_picker-1.0.8/ +image_picker_android=/home/admin1/.pub-cache/hosted/pub.dev/image_picker_android-0.8.9+6/ +image_picker_for_web=/home/admin1/.pub-cache/hosted/pub.dev/image_picker_for_web-3.0.2/ +image_picker_ios=/home/admin1/.pub-cache/hosted/pub.dev/image_picker_ios-0.8.9+2/ +image_picker_linux=/home/admin1/.pub-cache/hosted/pub.dev/image_picker_linux-0.2.1+1/ +image_picker_macos=/home/admin1/.pub-cache/hosted/pub.dev/image_picker_macos-0.2.1+1/ +image_picker_windows=/home/admin1/.pub-cache/hosted/pub.dev/image_picker_windows-0.2.1+1/ location=/home/admin1/.pub-cache/hosted/pub.dev/location-5.0.3/ location_web=/home/admin1/.pub-cache/hosted/pub.dev/location_web-4.2.0/ -package_info_plus=/home/admin1/.pub-cache/hosted/pub.dev/package_info_plus-4.2.0/ path_provider=/home/admin1/.pub-cache/hosted/pub.dev/path_provider-2.1.2/ path_provider_android=/home/admin1/.pub-cache/hosted/pub.dev/path_provider_android-2.2.2/ path_provider_foundation=/home/admin1/.pub-cache/hosted/pub.dev/path_provider_foundation-2.3.2/ path_provider_linux=/home/admin1/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/ path_provider_windows=/home/admin1/.pub-cache/hosted/pub.dev/path_provider_windows-2.2.1/ +url_launcher=/home/admin1/.pub-cache/hosted/pub.dev/url_launcher-6.2.6/ +url_launcher_android=/home/admin1/.pub-cache/hosted/pub.dev/url_launcher_android-6.3.1/ +url_launcher_ios=/home/admin1/.pub-cache/hosted/pub.dev/url_launcher_ios-6.3.0/ +url_launcher_linux=/home/admin1/.pub-cache/hosted/pub.dev/url_launcher_linux-3.1.1/ +url_launcher_macos=/home/admin1/.pub-cache/hosted/pub.dev/url_launcher_macos-3.2.0/ +url_launcher_web=/home/admin1/.pub-cache/hosted/pub.dev/url_launcher_web-2.2.3/ +url_launcher_windows=/home/admin1/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.1/ diff --git a/flutter/digit-ui-components/digit_components/.flutter-plugins-dependencies b/flutter/digit-ui-components/digit_components/.flutter-plugins-dependencies index b73742245d4..64d01d13e1f 100644 --- a/flutter/digit-ui-components/digit_components/.flutter-plugins-dependencies +++ b/flutter/digit-ui-components/digit_components/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_keyboard_visibility","path":"/home/admin1/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility-5.4.1/","native_build":true,"dependencies":[]},{"name":"fluttertoast","path":"/home/admin1/.pub-cache/hosted/pub.dev/fluttertoast-8.2.4/","native_build":true,"dependencies":[]},{"name":"geolocator_apple","path":"/home/admin1/.pub-cache/hosted/pub.dev/geolocator_apple-2.3.6/","native_build":true,"dependencies":[]},{"name":"location","path":"/home/admin1/.pub-cache/hosted/pub.dev/location-5.0.3/","native_build":true,"dependencies":[]},{"name":"package_info_plus","path":"/home/admin1/.pub-cache/hosted/pub.dev/package_info_plus-4.2.0/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/home/admin1/.pub-cache/hosted/pub.dev/path_provider_foundation-2.3.2/","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"android":[{"name":"flutter_keyboard_visibility","path":"/home/admin1/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility-5.4.1/","native_build":true,"dependencies":[]},{"name":"fluttertoast","path":"/home/admin1/.pub-cache/hosted/pub.dev/fluttertoast-8.2.4/","native_build":true,"dependencies":[]},{"name":"geolocator_android","path":"/home/admin1/.pub-cache/hosted/pub.dev/geolocator_android-4.5.2/","native_build":true,"dependencies":[]},{"name":"location","path":"/home/admin1/.pub-cache/hosted/pub.dev/location-5.0.3/","native_build":true,"dependencies":[]},{"name":"package_info_plus","path":"/home/admin1/.pub-cache/hosted/pub.dev/package_info_plus-4.2.0/","native_build":true,"dependencies":[]},{"name":"path_provider_android","path":"/home/admin1/.pub-cache/hosted/pub.dev/path_provider_android-2.2.2/","native_build":true,"dependencies":[]}],"macos":[{"name":"flutter_keyboard_visibility_macos","path":"/home/admin1/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_macos-1.0.0/","native_build":false,"dependencies":[]},{"name":"geolocator_apple","path":"/home/admin1/.pub-cache/hosted/pub.dev/geolocator_apple-2.3.6/","native_build":true,"dependencies":[]},{"name":"location","path":"/home/admin1/.pub-cache/hosted/pub.dev/location-5.0.3/","native_build":true,"dependencies":[]},{"name":"package_info_plus","path":"/home/admin1/.pub-cache/hosted/pub.dev/package_info_plus-4.2.0/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/home/admin1/.pub-cache/hosted/pub.dev/path_provider_foundation-2.3.2/","shared_darwin_source":true,"native_build":true,"dependencies":[]}],"linux":[{"name":"flutter_keyboard_visibility_linux","path":"/home/admin1/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_linux-1.0.0/","native_build":false,"dependencies":[]},{"name":"package_info_plus","path":"/home/admin1/.pub-cache/hosted/pub.dev/package_info_plus-4.2.0/","native_build":false,"dependencies":[]},{"name":"path_provider_linux","path":"/home/admin1/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[]}],"windows":[{"name":"flutter_keyboard_visibility_windows","path":"/home/admin1/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_windows-1.0.0/","native_build":false,"dependencies":[]},{"name":"geolocator_windows","path":"/home/admin1/.pub-cache/hosted/pub.dev/geolocator_windows-0.2.2/","native_build":true,"dependencies":[]},{"name":"package_info_plus","path":"/home/admin1/.pub-cache/hosted/pub.dev/package_info_plus-4.2.0/","native_build":false,"dependencies":[]},{"name":"path_provider_windows","path":"/home/admin1/.pub-cache/hosted/pub.dev/path_provider_windows-2.2.1/","native_build":false,"dependencies":[]}],"web":[{"name":"flutter_keyboard_visibility_web","path":"/home/admin1/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_web-2.0.0/","dependencies":[]},{"name":"fluttertoast","path":"/home/admin1/.pub-cache/hosted/pub.dev/fluttertoast-8.2.4/","dependencies":[]},{"name":"geolocator_web","path":"/home/admin1/.pub-cache/hosted/pub.dev/geolocator_web-2.2.1/","dependencies":[]},{"name":"location_web","path":"/home/admin1/.pub-cache/hosted/pub.dev/location_web-4.2.0/","dependencies":[]},{"name":"package_info_plus","path":"/home/admin1/.pub-cache/hosted/pub.dev/package_info_plus-4.2.0/","dependencies":[]}]},"dependencyGraph":[{"name":"flutter_keyboard_visibility","dependencies":["flutter_keyboard_visibility_linux","flutter_keyboard_visibility_macos","flutter_keyboard_visibility_web","flutter_keyboard_visibility_windows"]},{"name":"flutter_keyboard_visibility_linux","dependencies":[]},{"name":"flutter_keyboard_visibility_macos","dependencies":[]},{"name":"flutter_keyboard_visibility_web","dependencies":[]},{"name":"flutter_keyboard_visibility_windows","dependencies":[]},{"name":"fluttertoast","dependencies":[]},{"name":"geolocator","dependencies":["geolocator_android","geolocator_apple","geolocator_web","geolocator_windows"]},{"name":"geolocator_android","dependencies":[]},{"name":"geolocator_apple","dependencies":[]},{"name":"geolocator_web","dependencies":[]},{"name":"geolocator_windows","dependencies":[]},{"name":"location","dependencies":["location_web"]},{"name":"location_web","dependencies":[]},{"name":"package_info_plus","dependencies":[]},{"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":[]}],"date_created":"2024-03-21 17:26:44.377358","version":"3.16.8"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"camera_avfoundation","path":"/home/admin1/.pub-cache/hosted/pub.dev/camera_avfoundation-0.9.16/","native_build":true,"dependencies":[]},{"name":"file_picker","path":"/home/admin1/.pub-cache/hosted/pub.dev/file_picker-8.0.0+1/","native_build":true,"dependencies":[]},{"name":"flutter_keyboard_visibility","path":"/home/admin1/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility-5.4.1/","native_build":true,"dependencies":[]},{"name":"fluttertoast","path":"/home/admin1/.pub-cache/hosted/pub.dev/fluttertoast-8.2.4/","native_build":true,"dependencies":[]},{"name":"geolocator_apple","path":"/home/admin1/.pub-cache/hosted/pub.dev/geolocator_apple-2.3.6/","native_build":true,"dependencies":[]},{"name":"image_picker_ios","path":"/home/admin1/.pub-cache/hosted/pub.dev/image_picker_ios-0.8.9+2/","native_build":true,"dependencies":[]},{"name":"location","path":"/home/admin1/.pub-cache/hosted/pub.dev/location-5.0.3/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/home/admin1/.pub-cache/hosted/pub.dev/path_provider_foundation-2.3.2/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"url_launcher_ios","path":"/home/admin1/.pub-cache/hosted/pub.dev/url_launcher_ios-6.3.0/","native_build":true,"dependencies":[]}],"android":[{"name":"camera_android","path":"/home/admin1/.pub-cache/hosted/pub.dev/camera_android-0.10.9+1/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"]},{"name":"file_picker","path":"/home/admin1/.pub-cache/hosted/pub.dev/file_picker-8.0.0+1/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"]},{"name":"flutter_keyboard_visibility","path":"/home/admin1/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility-5.4.1/","native_build":true,"dependencies":[]},{"name":"flutter_plugin_android_lifecycle","path":"/home/admin1/.pub-cache/hosted/pub.dev/flutter_plugin_android_lifecycle-2.0.19/","native_build":true,"dependencies":[]},{"name":"fluttertoast","path":"/home/admin1/.pub-cache/hosted/pub.dev/fluttertoast-8.2.4/","native_build":true,"dependencies":[]},{"name":"geolocator_android","path":"/home/admin1/.pub-cache/hosted/pub.dev/geolocator_android-4.5.2/","native_build":true,"dependencies":[]},{"name":"image_picker_android","path":"/home/admin1/.pub-cache/hosted/pub.dev/image_picker_android-0.8.9+6/","native_build":true,"dependencies":["flutter_plugin_android_lifecycle"]},{"name":"location","path":"/home/admin1/.pub-cache/hosted/pub.dev/location-5.0.3/","native_build":true,"dependencies":[]},{"name":"path_provider_android","path":"/home/admin1/.pub-cache/hosted/pub.dev/path_provider_android-2.2.2/","native_build":true,"dependencies":[]},{"name":"url_launcher_android","path":"/home/admin1/.pub-cache/hosted/pub.dev/url_launcher_android-6.3.1/","native_build":true,"dependencies":[]}],"macos":[{"name":"file_selector_macos","path":"/home/admin1/.pub-cache/hosted/pub.dev/file_selector_macos-0.9.4/","native_build":true,"dependencies":[]},{"name":"flutter_keyboard_visibility_macos","path":"/home/admin1/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_macos-1.0.0/","native_build":false,"dependencies":[]},{"name":"geolocator_apple","path":"/home/admin1/.pub-cache/hosted/pub.dev/geolocator_apple-2.3.6/","native_build":true,"dependencies":[]},{"name":"image_picker_macos","path":"/home/admin1/.pub-cache/hosted/pub.dev/image_picker_macos-0.2.1+1/","native_build":false,"dependencies":["file_selector_macos"]},{"name":"location","path":"/home/admin1/.pub-cache/hosted/pub.dev/location-5.0.3/","native_build":true,"dependencies":[]},{"name":"path_provider_foundation","path":"/home/admin1/.pub-cache/hosted/pub.dev/path_provider_foundation-2.3.2/","shared_darwin_source":true,"native_build":true,"dependencies":[]},{"name":"url_launcher_macos","path":"/home/admin1/.pub-cache/hosted/pub.dev/url_launcher_macos-3.2.0/","native_build":true,"dependencies":[]}],"linux":[{"name":"file_selector_linux","path":"/home/admin1/.pub-cache/hosted/pub.dev/file_selector_linux-0.9.2+1/","native_build":true,"dependencies":[]},{"name":"flutter_keyboard_visibility_linux","path":"/home/admin1/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_linux-1.0.0/","native_build":false,"dependencies":[]},{"name":"image_picker_linux","path":"/home/admin1/.pub-cache/hosted/pub.dev/image_picker_linux-0.2.1+1/","native_build":false,"dependencies":["file_selector_linux"]},{"name":"path_provider_linux","path":"/home/admin1/.pub-cache/hosted/pub.dev/path_provider_linux-2.2.1/","native_build":false,"dependencies":[]},{"name":"url_launcher_linux","path":"/home/admin1/.pub-cache/hosted/pub.dev/url_launcher_linux-3.1.1/","native_build":true,"dependencies":[]}],"windows":[{"name":"file_selector_windows","path":"/home/admin1/.pub-cache/hosted/pub.dev/file_selector_windows-0.9.3+1/","native_build":true,"dependencies":[]},{"name":"flutter_keyboard_visibility_windows","path":"/home/admin1/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_windows-1.0.0/","native_build":false,"dependencies":[]},{"name":"geolocator_windows","path":"/home/admin1/.pub-cache/hosted/pub.dev/geolocator_windows-0.2.2/","native_build":true,"dependencies":[]},{"name":"image_picker_windows","path":"/home/admin1/.pub-cache/hosted/pub.dev/image_picker_windows-0.2.1+1/","native_build":false,"dependencies":["file_selector_windows"]},{"name":"path_provider_windows","path":"/home/admin1/.pub-cache/hosted/pub.dev/path_provider_windows-2.2.1/","native_build":false,"dependencies":[]},{"name":"url_launcher_windows","path":"/home/admin1/.pub-cache/hosted/pub.dev/url_launcher_windows-3.1.1/","native_build":true,"dependencies":[]}],"web":[{"name":"camera_web","path":"/home/admin1/.pub-cache/hosted/pub.dev/camera_web-0.3.3/","dependencies":[]},{"name":"file_picker","path":"/home/admin1/.pub-cache/hosted/pub.dev/file_picker-8.0.0+1/","dependencies":[]},{"name":"flutter_dropzone_web","path":"/home/admin1/.pub-cache/hosted/pub.dev/flutter_dropzone_web-3.0.13/","dependencies":[]},{"name":"flutter_keyboard_visibility_web","path":"/home/admin1/.pub-cache/hosted/pub.dev/flutter_keyboard_visibility_web-2.0.0/","dependencies":[]},{"name":"fluttertoast","path":"/home/admin1/.pub-cache/hosted/pub.dev/fluttertoast-8.2.4/","dependencies":[]},{"name":"geolocator_web","path":"/home/admin1/.pub-cache/hosted/pub.dev/geolocator_web-2.2.1/","dependencies":[]},{"name":"image_picker_for_web","path":"/home/admin1/.pub-cache/hosted/pub.dev/image_picker_for_web-3.0.2/","dependencies":[]},{"name":"location_web","path":"/home/admin1/.pub-cache/hosted/pub.dev/location_web-4.2.0/","dependencies":[]},{"name":"url_launcher_web","path":"/home/admin1/.pub-cache/hosted/pub.dev/url_launcher_web-2.2.3/","dependencies":[]}]},"dependencyGraph":[{"name":"camera","dependencies":["camera_android","camera_avfoundation","camera_web","flutter_plugin_android_lifecycle"]},{"name":"camera_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"camera_avfoundation","dependencies":[]},{"name":"camera_web","dependencies":[]},{"name":"file_picker","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"file_selector_linux","dependencies":[]},{"name":"file_selector_macos","dependencies":[]},{"name":"file_selector_windows","dependencies":[]},{"name":"flutter_dropzone","dependencies":["flutter_dropzone_web"]},{"name":"flutter_dropzone_web","dependencies":[]},{"name":"flutter_keyboard_visibility","dependencies":["flutter_keyboard_visibility_linux","flutter_keyboard_visibility_macos","flutter_keyboard_visibility_web","flutter_keyboard_visibility_windows"]},{"name":"flutter_keyboard_visibility_linux","dependencies":[]},{"name":"flutter_keyboard_visibility_macos","dependencies":[]},{"name":"flutter_keyboard_visibility_web","dependencies":[]},{"name":"flutter_keyboard_visibility_windows","dependencies":[]},{"name":"flutter_plugin_android_lifecycle","dependencies":[]},{"name":"fluttertoast","dependencies":[]},{"name":"geolocator","dependencies":["geolocator_android","geolocator_apple","geolocator_web","geolocator_windows"]},{"name":"geolocator_android","dependencies":[]},{"name":"geolocator_apple","dependencies":[]},{"name":"geolocator_web","dependencies":[]},{"name":"geolocator_windows","dependencies":[]},{"name":"image_picker","dependencies":["image_picker_android","image_picker_for_web","image_picker_ios","image_picker_linux","image_picker_macos","image_picker_windows"]},{"name":"image_picker_android","dependencies":["flutter_plugin_android_lifecycle"]},{"name":"image_picker_for_web","dependencies":[]},{"name":"image_picker_ios","dependencies":[]},{"name":"image_picker_linux","dependencies":["file_selector_linux"]},{"name":"image_picker_macos","dependencies":["file_selector_macos"]},{"name":"image_picker_windows","dependencies":["file_selector_windows"]},{"name":"location","dependencies":["location_web"]},{"name":"location_web","dependencies":[]},{"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":"url_launcher","dependencies":["url_launcher_android","url_launcher_ios","url_launcher_linux","url_launcher_macos","url_launcher_web","url_launcher_windows"]},{"name":"url_launcher_android","dependencies":[]},{"name":"url_launcher_ios","dependencies":[]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_web","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2024-09-25 10:19:28.353274","version":"3.16.8"} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/CHANGELOG.md b/flutter/digit-ui-components/digit_components/CHANGELOG.md index 45b92b1820d..39cb4578b27 100644 --- a/flutter/digit-ui-components/digit_components/CHANGELOG.md +++ b/flutter/digit-ui-components/digit_components/CHANGELOG.md @@ -1,7 +1,38 @@ -## 0.0.1-beta +## 0.0.1+7 +* updated color and typography library +* added location fetch bloc +* added utils for date and time conversion +* added utils function to show or hide dialog easily + +## 0.0.1+6 +* enhanced multiselect dropdown to make it searchable +* updated color and typography library + +## 0.0.1+5 +* fixed dropdown setState being called after dispose +* added util function to make text sentence case, caps case and truncate after fix value + +## 0.0.1+4 +* fixed padding for text area +* code refactors for text fields + +## 0.0.1+3 +* dropdown overlay issues fixes +## 0.0.1+2 +* miner bug fixes + +## 0.0.1+1 +* compatible with reactive forms + +## 0.0.1 +* initial release + +## 0.0.3-beta * test release. ## 0.0.2-beta +* test release. +## 0.0.1-beta * test release. diff --git a/flutter/digit-ui-components/digit_components/assets/animated_json/alert.json b/flutter/digit-ui-components/digit_components/assets/animated_json/alert.json new file mode 100644 index 00000000000..171b416cde1 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/assets/animated_json/alert.json @@ -0,0 +1,1127 @@ +{ + "nm": "48 - Warning", + "ddd": 0, + "h": 500, + "w": 500, + "meta": { + "g": "LottieFiles AE " + }, + "layers": [ + { + "ty": 3, + "nm": "48 - Warning", + "sr": 1, + "st": 0, + "op": 144, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + 60, + 60, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 180, + 180, + 100 + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 250.045, + 290.339, + 0 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 0, + "ix": 11 + } + }, + "ef": [], + "ind": 1 + }, + { + "ty": 4, + "nm": "Line", + "sr": 1, + "st": 0, + "op": 144, + "ip": 12, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + -1, + 21.25, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0, + "y": 1 + }, + "s": [ + 0, + 0, + 100 + ], + "t": 12 + }, + { + "s": [ + 55.556, + 55.556, + 100 + ], + "t": 32 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 85.533, + 85.887, + 0 + ], + "ix": 2 + }, + "r": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0, + "y": 1 + }, + "s": [ + 180 + ], + "t": 12 + }, + { + "s": [ + 0 + ], + "t": 32 + } + ], + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "ef": [], + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Shape 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": false, + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -1, + 80 + ], + [ + -1, + -37.5 + ] + ] + }, + "ix": 2 + } + }, + { + "ty": "st", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Stroke", + "nm": "Stroke 1", + "lc": 2, + "lj": 1, + "ml": 4, + "o": { + "a": 0, + "k": 100, + "ix": 4 + }, + "w": { + "a": 0, + "k": 28, + "ix": 5 + }, + "c": { + "a": 0, + "k": [ + 1, + 1, + 1 + ], + "ix": 3 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "tm", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Filter - Trim", + "nm": "Trim Paths 1", + "ix": 2, + "e": { + "a": 0, + "k": 100, + "ix": 2 + }, + "o": { + "a": 0, + "k": 0, + "ix": 3 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0, + "y": 1 + }, + "s": [ + 0 + ], + "t": 22 + }, + { + "s": [ + 40 + ], + "t": 42 + } + ], + "ix": 1 + }, + "m": 1 + } + ], + "ind": 2, + "parent": 5 + }, + { + "ty": 4, + "nm": "Dot", + "sr": 1, + "st": 0, + "op": 144, + "ip": 12, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "ef": [], + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Shape 1", + "ix": 1, + "cix": 2, + "np": 4, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": false, + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -1, + 80 + ], + [ + -1, + -37.5 + ] + ] + }, + "ix": 2 + } + }, + { + "ty": "tm", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Filter - Trim", + "nm": "Trim Paths 1", + "ix": 2, + "e": { + "a": 0, + "k": 0.1, + "ix": 2 + }, + "o": { + "a": 0, + "k": 0, + "ix": 3 + }, + "s": { + "a": 0, + "k": 0, + "ix": 1 + }, + "m": 1 + }, + { + "ty": "st", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Stroke", + "nm": "Stroke 1", + "lc": 2, + "lj": 1, + "ml": 4, + "o": { + "a": 0, + "k": 100, + "ix": 4 + }, + "w": { + "a": 0, + "k": 33, + "ix": 5 + }, + "c": { + "a": 0, + "k": [ + 1, + 1, + 1 + ], + "ix": 3 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 3, + "parent": 2 + }, + { + "ty": 4, + "nm": "Tri Outlines", + "sr": 1, + "st": 0, + "op": 144, + "ip": 10, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + 85.513, + 72.848, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0, + 0, + 100 + ], + "t": 10 + }, + { + "s": [ + 100, + 100, + 100 + ], + "t": 15 + } + ], + "ix": 6, + "x": "var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('Scale - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('Scale - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('Scale - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}" + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 59.955, + 37.467, + 0 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "ef": [ + { + "ty": 5, + "mn": "ADBE Slider Control", + "nm": "Scale - Overshoot", + "ix": 1, + "en": 1, + "ef": [ + { + "ty": 0, + "mn": "ADBE Slider Control-0001", + "nm": "Slider", + "ix": 1, + "v": { + "a": 0, + "k": 10, + "ix": 1, + "x": "var $bm_rt;\n$bm_rt = clamp(value, 0, 100);" + } + } + ] + }, + { + "ty": 5, + "mn": "ADBE Slider Control", + "nm": "Scale - Bounce", + "ix": 2, + "en": 1, + "ef": [ + { + "ty": 0, + "mn": "ADBE Slider Control-0001", + "nm": "Slider", + "ix": 1, + "v": { + "a": 0, + "k": 35, + "ix": 1, + "x": "var $bm_rt;\n$bm_rt = clamp(value, 0, 100);" + } + } + ] + }, + { + "ty": 5, + "mn": "ADBE Slider Control", + "nm": "Scale - Friction", + "ix": 3, + "en": 1, + "ef": [ + { + "ty": 0, + "mn": "ADBE Slider Control-0001", + "nm": "Slider", + "ix": 1, + "v": { + "a": 0, + "k": 65, + "ix": 1, + "x": "var $bm_rt;\n$bm_rt = clamp(value, 0, 100);" + } + } + ] + } + ], + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "ix": 1, + "cix": 2, + "np": 2, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [ + -3.315, + 5.634 + ], + [ + 0, + 0 + ], + [ + -3.267, + -5.554 + ], + [ + 0, + 0 + ], + [ + 6.537, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 3.268, + -5.554 + ], + [ + 0, + 0 + ], + [ + 3.315, + 5.634 + ], + [ + 0, + 0 + ], + [ + -6.536, + 0 + ] + ], + "v": [ + [ + -81.948, + 59.861 + ], + [ + -7.284, + -67.044 + ], + [ + 7.284, + -67.044 + ], + [ + 81.948, + 59.861 + ], + [ + 74.664, + 72.598 + ], + [ + -74.664, + 72.598 + ] + ] + }, + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "c": { + "a": 0, + "k": [ + 0.7255, + 0.098, + 0 + ], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [ + 85.513, + 72.848 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 4, + "parent": 1 + }, + { + "ty": 3, + "nm": "Tri", + "sr": 1, + "st": 0, + "op": 144, + "ip": 10, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + 85.513, + 72.848, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0, + 0, + 100 + ], + "t": 10 + }, + { + "s": [ + 100, + 100, + 100 + ], + "t": 15 + } + ], + "ix": 6, + "x": "var $bm_rt;\nvar amp, freq, decay, n, t, v;\ntry {\n amp = $bm_div(effect('Scale - Overshoot')('ADBE Slider Control-0001'), 2.5), freq = $bm_div(effect('Scale - Bounce')('ADBE Slider Control-0001'), 20), decay = $bm_div(effect('Scale - Friction')('ADBE Slider Control-0001'), 20), n = 0, 0 < numKeys && (n = nearestKey(time).index, key(n).time > time && n--), t = 0 === n ? 0 : $bm_sub(time, key(n).time), $bm_rt = 0 < n ? (v = velocityAtTime($bm_sub(key(n).time, $bm_div(thisComp.frameDuration, 10))), $bm_sum(value, $bm_div($bm_mul($bm_mul($bm_div(v, 100), amp), Math.sin($bm_mul($bm_mul($bm_mul(freq, t), 2), Math.PI))), Math.exp($bm_mul(decay, t))))) : value;\n} catch (e$$4) {\n $bm_rt = value = value;\n}" + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 59.955, + 37.467, + 0 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "ef": [ + { + "ty": 5, + "mn": "ADBE Slider Control", + "nm": "Scale - Overshoot", + "ix": 1, + "en": 1, + "ef": [ + { + "ty": 0, + "mn": "ADBE Slider Control-0001", + "nm": "Slider", + "ix": 1, + "v": { + "a": 0, + "k": 10, + "ix": 1, + "x": "var $bm_rt;\n$bm_rt = clamp(value, 0, 100);" + } + } + ] + }, + { + "ty": 5, + "mn": "ADBE Slider Control", + "nm": "Scale - Bounce", + "ix": 2, + "en": 1, + "ef": [ + { + "ty": 0, + "mn": "ADBE Slider Control-0001", + "nm": "Slider", + "ix": 1, + "v": { + "a": 0, + "k": 35, + "ix": 1, + "x": "var $bm_rt;\n$bm_rt = clamp(value, 0, 100);" + } + } + ] + }, + { + "ty": 5, + "mn": "ADBE Slider Control", + "nm": "Scale - Friction", + "ix": 3, + "en": 1, + "ef": [ + { + "ty": 0, + "mn": "ADBE Slider Control-0001", + "nm": "Slider", + "ix": 1, + "v": { + "a": 0, + "k": 65, + "ix": 1, + "x": "var $bm_rt;\n$bm_rt = clamp(value, 0, 100);" + } + } + ] + } + ], + "ind": 5, + "parent": 1 + }, + { + "ty": 1, + "nm": "Plate_white", + "sr": 1, + "st": 0, + "op": 144, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + 250, + 250, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 250, + 250, + 0 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "ef": [], + "sc": "#ffffff", + "sh": 500, + "sw": 500, + "ind": 6 + } + ], + "v": "5.5.7", + "fr": 48, + "op": 144, + "ip": 0, + "assets": [] +} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/assets/animated_json/error.json b/flutter/digit-ui-components/digit_components/assets/animated_json/error.json new file mode 100644 index 00000000000..96b4f962629 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/assets/animated_json/error.json @@ -0,0 +1,728 @@ +{ + "nm": "ckeck", + "ddd": 0, + "h": 50, + "w": 50, + "meta": { + "g": "@lottiefiles/toolkit-js 0.33.2" + }, + "layers": [ + { + "ty": 4, + "nm": "! Outlines", + "sr": 1, + "st": 0, + "op": 213, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + 2, + 12, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.653, + "y": -0.834 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 100, + 100, + 100 + ], + "t": 60 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 115, + 115, + 100 + ], + "t": 73 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.127, + "y": 1.695 + }, + "s": [ + 115, + 115, + 100 + ], + "t": 83 + }, + { + "s": [ + 100, + 100, + 100 + ], + "t": 90 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 25, + 25, + 0 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "ef": [], + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Group 1", + "ix": 1, + "cix": 2, + "np": 4, + "it": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [ + 0, + 1.104 + ], + [ + -1.104, + 0 + ], + [ + 0, + -1.104 + ], + [ + 1.104, + 0 + ] + ], + "o": [ + [ + 0, + -1.104 + ], + [ + 1.104, + 0 + ], + [ + 0, + 1.104 + ], + [ + -1.104, + 0 + ] + ], + "v": [ + [ + -2, + 10 + ], + [ + 0, + 8 + ], + [ + 2, + 10 + ], + [ + 0, + 12 + ] + ] + }, + "ix": 2 + } + }, + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 2", + "ix": 2, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 0, + 0 + ] + ], + "v": [ + [ + -1.036, + 5 + ], + [ + -2, + -6.625 + ], + [ + -2, + -12 + ], + [ + 2, + -12 + ], + [ + 2, + -6.625 + ], + [ + 1.052, + 5 + ] + ] + }, + "ix": 2 + } + }, + { + "ty": "mm", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Filter - Merge", + "nm": "Merge Paths 1", + "mm": 1 + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "c": { + "a": 0, + "k": [ + 1, + 1, + 1 + ], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0.099, + 9.982 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [ + 2.099, + 21.982 + ], + "ix": 2 + }, + "r": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 0 + ], + "t": 10 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 5 + ], + "t": 12 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + -5 + ], + "t": 14 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 5 + ], + "t": 16 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + -5 + ], + "t": 18 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + 5 + ], + "t": 20 + }, + { + "o": { + "x": 0.167, + "y": 0.167 + }, + "i": { + "x": 0.833, + "y": 0.833 + }, + "s": [ + -5 + ], + "t": 22 + }, + { + "s": [ + 0 + ], + "t": 24 + } + ], + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + } + ], + "ind": 1 + }, + { + "ty": 4, + "nm": "Shape Layer 1", + "sr": 1, + "st": 0, + "op": 193, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + 0, + 10, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.41, + "y": -0.602 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 100, + 100, + 100 + ], + "t": 60 + }, + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.436, + "y": 1.492 + }, + "s": [ + 115, + 115, + 100 + ], + "t": 83 + }, + { + "s": [ + 100, + 100, + 100 + ], + "t": 90 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 25, + 35, + 0 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "ef": [], + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Ellipse 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "el", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Ellipse", + "nm": "Ellipse Path 1", + "d": 1, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 3 + }, + "s": { + "a": 0, + "k": [ + 40, + 40 + ], + "ix": 2 + } + }, + { + "ty": "st", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Stroke", + "nm": "Stroke 1", + "lc": 1, + "lj": 1, + "ml": 4, + "o": { + "a": 0, + "k": 100, + "ix": 4 + }, + "w": { + "a": 0, + "k": 2, + "ix": 5 + }, + "c": { + "a": 0, + "k": [ + 1, + 1, + 1 + ], + "ix": 3 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "tm", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Filter - Trim", + "nm": "Trim Paths 1", + "ix": 2, + "e": { + "a": 0, + "k": 100, + "ix": 2 + }, + "o": { + "a": 0, + "k": 0, + "ix": 3 + }, + "s": { + "a": 0, + "k": 0, + "ix": 1 + }, + "m": 1 + } + ], + "ind": 2 + } + ], + "v": "5.6.5", + "fr": 60, + "op": 180, + "ip": 0, + "assets": [] +} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/assets/animated_json/success.json b/flutter/digit-ui-components/digit_components/assets/animated_json/success.json new file mode 100644 index 00000000000..43192f70849 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/assets/animated_json/success.json @@ -0,0 +1,917 @@ +{ + "nm": "sucess", + "ddd": 0, + "h": 120, + "w": 120, + "meta": { + "g": "LottieFiles AE 0.1.21" + }, + "layers": [ + { + "ty": 3, + "nm": "scale up null", + "sr": 1, + "st": 0, + "op": 300.00001221925, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.167, + "y": 0 + }, + "i": { + "x": 0.833, + "y": 1 + }, + "s": [ + 111, + 111, + 100 + ], + "t": 27 + }, + { + "o": { + "x": 0.167, + "y": 0 + }, + "i": { + "x": 0.833, + "y": 1 + }, + "s": [ + 101, + 101, + 100 + ], + "t": 36 + }, + { + "s": [ + 121, + 121, + 100 + ], + "t": 42.0000017106951 + } + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 60, + 60, + 0 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 0, + "ix": 11 + } + }, + "ef": [], + "ind": 1 + }, + { + "ty": 4, + "nm": "spark", + "sr": 1, + "st": 35.0000014255792, + "op": 335.00001364483, + "ip": 35.0000014255792, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 0, + 0.5, + 0 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "ef": [], + "shapes": [ + { + "ty": "gr", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Group", + "nm": "Rectangle 1", + "ix": 1, + "cix": 2, + "np": 3, + "it": [ + { + "ty": "rc", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Rect", + "nm": "Rectangle Path 1", + "d": 1, + "p": { + "a": 1, + "k": [ + { + "o": { + "x": 0.333, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 0, + -21 + ], + "t": 35, + "ti": [ + 0, + 1.5 + ], + "to": [ + 0, + -1.5 + ] + }, + { + "s": [ + 0, + -30 + ], + "t": 53.0000021587343 + } + ], + "ix": 3 + }, + "r": { + "a": 0, + "k": 0, + "ix": 4 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.976, + "y": 0 + }, + "i": { + "x": 0.667, + "y": 1 + }, + "s": [ + 2, + 0 + ], + "t": 35 + }, + { + "o": { + "x": 0.33299999999999996, + "y": 0 + }, + "i": { + "x": 0.15355432054499818, + "y": 0.9999999999999999 + }, + "s": [ + 2, + 8 + ], + "t": 42 + }, + { + "s": [ + 1.633, + 0 + ], + "t": 53.0000021587343 + } + ], + "ix": 2 + } + }, + { + "ty": "fl", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Fill", + "nm": "Fill 1", + "c": { + "a": 0, + "k": [ + 0.9804, + 0.9804, + 0.9804 + ], + "ix": 4 + }, + "r": 1, + "o": { + "a": 0, + "k": 100, + "ix": 5 + } + }, + { + "ty": "tr", + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0, + "ix": 4 + }, + "p": { + "a": 0, + "k": [ + 0, + -8 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 6 + }, + "sa": { + "a": 0, + "k": 0, + "ix": 5 + }, + "o": { + "a": 0, + "k": 100, + "ix": 7 + } + } + ] + }, + { + "ty": "rp", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Filter - Repeater", + "nm": "Repeater 1", + "ix": 2, + "m": 1, + "c": { + "a": 0, + "k": 8, + "ix": 1 + }, + "o": { + "a": 0, + "k": 0, + "ix": 2 + }, + "tr": { + "a": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100 + ], + "ix": 3 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 0, + 0 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 45, + "ix": 4 + }, + "sa": { + "a": 0, + "k": 0 + }, + "so": { + "a": 0, + "k": 100, + "ix": 5 + }, + "eo": { + "a": 0, + "k": 100, + "ix": 6 + } + } + } + ], + "ind": 2, + "parent": 1 + }, + { + "ty": 4, + "nm": "check", + "sr": 1, + "st": 10.0000004073083, + "op": 310.000012626559, + "ip": 22.0000008960784, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "ef": [], + "shapes": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": false, + "i": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + 3.5, + 3.75 + ], + [ + -12.973, + 5.349 + ], + [ + -6.124, + -9.992 + ], + [ + 12.125, + -7.431 + ], + [ + 7.431, + 12.125 + ] + ], + "o": [ + [ + 0, + 0 + ], + [ + 0, + 0 + ], + [ + -3.5, + -3.75 + ], + [ + 10.764, + -2.941 + ], + [ + 7.431, + 12.125 + ], + [ + -12.125, + 7.431 + ], + [ + -7.431, + -12.125 + ] + ], + "v": [ + [ + 15.25, + -9.688 + ], + [ + -5.75, + 10.062 + ], + [ + -16, + 0.25 + ], + [ + -6.777, + -24.849 + ], + [ + 21.955, + -13.456 + ], + [ + 13.456, + 21.955 + ], + [ + -21.955, + 13.456 + ] + ] + }, + "ix": 2 + } + }, + { + "ty": "tm", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Filter - Trim", + "nm": "Trim Paths 1", + "ix": 2, + "e": { + "a": 1, + "k": [ + { + "o": { + "x": 0.714, + "y": 0 + }, + "i": { + "x": 0.351, + "y": 1 + }, + "s": [ + 100 + ], + "t": 10 + }, + { + "s": [ + 23 + ], + "t": 40.0000016292334 + } + ], + "ix": 2 + }, + "o": { + "a": 0, + "k": 0, + "ix": 3 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.742, + "y": 0 + }, + "i": { + "x": 0.363, + "y": 1 + }, + "s": [ + 100 + ], + "t": 17 + }, + { + "s": [ + 0 + ], + "t": 45.0000018328876 + } + ], + "ix": 1 + }, + "m": 1 + }, + { + "ty": "st", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Stroke", + "nm": "Stroke 1", + "lc": 1, + "lj": 1, + "ml": 4, + "o": { + "a": 0, + "k": 100, + "ix": 4 + }, + "w": { + "a": 0, + "k": 4, + "ix": 5 + }, + "c": { + "a": 0, + "k": [ + 0.9804, + 0.9804, + 0.9804 + ], + "ix": 3 + } + } + ], + "ind": 3, + "parent": 1 + }, + { + "ty": 4, + "nm": "circle", + "sr": 1, + "st": 0, + "op": 300.00001221925, + "ip": 0, + "hd": false, + "ddd": 0, + "bm": 0, + "hasMask": false, + "ao": 0, + "ks": { + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 1 + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ], + "ix": 6 + }, + "sk": { + "a": 0, + "k": 0 + }, + "p": { + "a": 0, + "k": [ + 0, + 0, + 0 + ], + "ix": 2 + }, + "r": { + "a": 0, + "k": 0, + "ix": 10 + }, + "sa": { + "a": 0, + "k": 0 + }, + "o": { + "a": 0, + "k": 100, + "ix": 11 + } + }, + "ef": [], + "shapes": [ + { + "ty": "sh", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Shape - Group", + "nm": "Path 1", + "ix": 1, + "d": 1, + "ks": { + "a": 0, + "k": { + "c": true, + "i": [ + [ + -14.221, + 0 + ], + [ + 0, + -14.221 + ], + [ + 14.221, + 0 + ], + [ + 0, + 14.221 + ] + ], + "o": [ + [ + 14.221, + 0 + ], + [ + 0, + 14.221 + ], + [ + -14.221, + 0 + ], + [ + 0, + -14.221 + ] + ], + "v": [ + [ + 0, + -25.75 + ], + [ + 25.75, + 0 + ], + [ + 0, + 25.75 + ], + [ + -25.75, + 0 + ] + ] + }, + "ix": 2 + } + }, + { + "ty": "st", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Graphic - Stroke", + "nm": "Stroke 1", + "lc": 1, + "lj": 1, + "ml": 4, + "o": { + "a": 0, + "k": 100, + "ix": 4 + }, + "w": { + "a": 0, + "k": 2, + "ix": 5 + }, + "c": { + "a": 0, + "k": [ + 0.9804, + 0.9804, + 0.9804 + ], + "ix": 3 + } + }, + { + "ty": "tm", + "bm": 0, + "hd": false, + "mn": "ADBE Vector Filter - Trim", + "nm": "Trim Paths 1", + "ix": 3, + "e": { + "a": 1, + "k": [ + { + "o": { + "x": 0.714, + "y": 0 + }, + "i": { + "x": 0.351, + "y": 1 + }, + "s": [ + 100 + ], + "t": 0 + }, + { + "s": [ + 100 + ], + "t": 30.0000012219251 + } + ], + "ix": 2 + }, + "o": { + "a": 0, + "k": 0, + "ix": 3 + }, + "s": { + "a": 1, + "k": [ + { + "o": { + "x": 0.742, + "y": 0 + }, + "i": { + "x": 0.363, + "y": 1 + }, + "s": [ + 100 + ], + "t": 7 + }, + { + "s": [ + 0 + ], + "t": 33.0000013441176 + } + ], + "ix": 1 + }, + "m": 1 + } + ], + "ind": 4, + "parent": 1 + } + ], + "v": "5.5.7", + "fr": 29.9700012207031, + "op": 60.0000024438501, + "ip": 0, + "assets": [] +} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/assets/config.json b/flutter/digit-ui-components/digit_components/assets/config.json deleted file mode 100644 index 1f0fb39ad1e..00000000000 --- a/flutter/digit-ui-components/digit_components/assets/config.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "TextArea", - "css_prefix_text": "", - "css_use_suffix": false, - "hinting": true, - "units_per_em": 1000, - "ascent": 850, - "glyphs": [ - { - "uid": "315431fede763db23900c6578b7400ab", - "css": "text-area-expand", - "code": 59392, - "src": "custom_icons", - "selected": true, - "svg": { - "path": "M802.2 83.5L0 883 78.7 961.5 880.9 161.9 802.2 83.5ZM809.9 444.4L361.7 894.3 440.7 972.5 888.9 522.6 809.9 444.4Z", - "width": 889 - }, - "search": [ - "text-area-expand" - ] - } - ] -} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/assets/fonts/TextArea.ttf b/flutter/digit-ui-components/digit_components/assets/fonts/TextArea.ttf deleted file mode 100644 index bf7547f3132..00000000000 Binary files a/flutter/digit-ui-components/digit_components/assets/fonts/TextArea.ttf and /dev/null differ diff --git a/flutter/digit-ui-components/digit_components/assets/icons/svg/doc.svg b/flutter/digit-ui-components/digit_components/assets/icons/svg/doc.svg new file mode 100644 index 00000000000..83ee78f2791 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/assets/icons/svg/doc.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/flutter/digit-ui-components/digit_components/assets/icons/svg/file.svg b/flutter/digit-ui-components/digit_components/assets/icons/svg/file.svg new file mode 100644 index 00000000000..8e5bb9e8929 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/assets/icons/svg/file.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/flutter/digit-ui-components/digit_components/assets/icons/svg/jpg.svg b/flutter/digit-ui-components/digit_components/assets/icons/svg/jpg.svg new file mode 100644 index 00000000000..c57b337cd84 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/assets/icons/svg/jpg.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/flutter/digit-ui-components/digit_components/assets/icons/svg/pdf.svg b/flutter/digit-ui-components/digit_components/assets/icons/svg/pdf.svg new file mode 100644 index 00000000000..1f230123c08 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/assets/icons/svg/pdf.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/flutter/digit-ui-components/digit_components/assets/icons/svg/png.svg b/flutter/digit-ui-components/digit_components/assets/icons/svg/png.svg new file mode 100644 index 00000000000..5a81ef2099b --- /dev/null +++ b/flutter/digit-ui-components/digit_components/assets/icons/svg/png.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/flutter/digit-ui-components/digit_components/assets/icons/svg/profile_icon.svg b/flutter/digit-ui-components/digit_components/assets/icons/svg/profile_icon.svg new file mode 100644 index 00000000000..781da19a414 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/assets/icons/svg/profile_icon.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/flutter/digit-ui-components/digit_components/assets/icons/svg/xlsx.svg b/flutter/digit-ui-components/digit_components/assets/icons/svg/xlsx.svg new file mode 100644 index 00000000000..d744d65b187 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/assets/icons/svg/xlsx.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/flutter/digit-ui-components/digit_components/assets/images/digit_logo_dark.png b/flutter/digit-ui-components/digit_components/assets/images/digit_logo_dark.png new file mode 100644 index 00000000000..bd85d8b700f Binary files /dev/null and b/flutter/digit-ui-components/digit_components/assets/images/digit_logo_dark.png differ diff --git a/flutter/digit-ui-components/digit_components/assets/images/digit_logo_light.png b/flutter/digit-ui-components/digit_components/assets/images/digit_logo_light.png new file mode 100644 index 00000000000..5866bdc2748 Binary files /dev/null and b/flutter/digit-ui-components/digit_components/assets/images/digit_logo_light.png differ diff --git a/flutter/digit-ui-components/digit_components/assets/text_area_icons.dart b/flutter/digit-ui-components/digit_components/assets/text_area_icons.dart deleted file mode 100644 index 15e6f284893..00000000000 --- a/flutter/digit-ui-components/digit_components/assets/text_area_icons.dart +++ /dev/null @@ -1,25 +0,0 @@ -/// Flutter icons TextArea -/// Copyright (C) 2024 by original authors @ fluttericon.com, fontello.com -/// This font was generated by FlutterIcon.com, which is derived from Fontello. -/// -/// To use this font, place it in your fonts/ directory and include the -/// following in your pubspec.yaml -/// -/// flutter: -/// fonts: -/// - family: TextArea -/// fonts: -/// - asset: fonts/TextArea.ttf -/// -/// -/// -import 'package:flutter/widgets.dart'; - -class TextArea { - TextArea._(); - - static const _kFontFam = 'TextArea'; - static const String? _kFontPkg = null; - - static const IconData textAreaExpand = IconData(0xe800, fontFamily: _kFontFam, fontPackage: _kFontPkg); -} diff --git a/flutter/digit-ui-components/digit_components/build.yaml b/flutter/digit-ui-components/digit_components/build.yaml new file mode 100644 index 00000000000..78a37de782f --- /dev/null +++ b/flutter/digit-ui-components/digit_components/build.yaml @@ -0,0 +1,7 @@ +targets: + $default: + builders: + auto_route_generator:auto_route_generator: + options: + generate_for: + - lib/**.dart diff --git a/flutter/digit-ui-components/digit_components/lib/blocs/AppLocalization.dart b/flutter/digit-ui-components/digit_components/lib/blocs/AppLocalization.dart new file mode 100644 index 00000000000..96468aa384b --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/blocs/AppLocalization.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; + +import 'component_localization_delegate.dart'; + +// Class responsible for handling attendance localization +class ComponentLocalization { + final Locale locale; + final Future localizedStrings; + final List languages; + + ComponentLocalization(this.locale, this.localizedStrings, this.languages); + + // Method to get the current localization instance from context + static ComponentLocalization of(BuildContext context) { + return Localizations.of(context, ComponentLocalization)!; + } + + static final List _localizedStrings = []; + + // Method to get the delegate for localization + static LocalizationsDelegate getDelegate( + Future localizedStrings, List languages) => + ComponentLocalizationDelegate(localizedStrings, languages); + + // Method to load localized strings + Future load() async { + _localizedStrings.clear(); + // Iterate over localized strings and filter based on locale + for (var element in await localizedStrings) { + if (element.locale == '${locale.languageCode}_${locale.countryCode}') { + _localizedStrings.add(element); + } + } + + return true; + } + + // Method to translate a given localized value + String translate(String localizedValues) { + if (_localizedStrings.isEmpty) { + return localizedValues; + } else { + final index = _localizedStrings.indexWhere( + (medium) => medium.code == localizedValues, + ); + + return index != -1 ? _localizedStrings[index].message : localizedValues; + } + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/blocs/DateSelection.dart b/flutter/digit-ui-components/digit_components/lib/blocs/DateSelection.dart index 2af953b3f3a..ba4a63e701f 100644 --- a/flutter/digit-ui-components/digit_components/lib/blocs/DateSelection.dart +++ b/flutter/digit-ui-components/digit_components/lib/blocs/DateSelection.dart @@ -4,14 +4,16 @@ import 'package:intl/intl.dart'; class DateSelectionBloc { Future selectDate({ required BuildContext context, DateTime? firstDate, DateTime? lastDate, DateTime? initialDate, - required TextEditingController controller, - DateFormat? dateFormat, /// Added parameter for custom date format + required TextEditingController controller, String? cancelText, String? confirmText, void Function(String)? onChange, + DateFormat? dateFormat, /// Added parameter for custom date format }) async { DateTime? selectedDate = await showDatePicker( context: context, initialDate: initialDate ?? DateTime.now(), firstDate: firstDate ?? DateTime(2000), lastDate: lastDate ?? DateTime(2101), + cancelText: cancelText, + confirmText: confirmText, ); if (selectedDate != null) { String formattedDate = @@ -19,5 +21,9 @@ class DateSelectionBloc { DateFormat('dd/MM/yyyy').format(selectedDate.toLocal()); controller.text = formattedDate; } + + if (onChange != null) { + onChange(controller.text); + } } } \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/blocs/LocationBloc.dart b/flutter/digit-ui-components/digit_components/lib/blocs/LocationBloc.dart index 7a36f265676..8a67081aa80 100644 --- a/flutter/digit-ui-components/digit_components/lib/blocs/LocationBloc.dart +++ b/flutter/digit-ui-components/digit_components/lib/blocs/LocationBloc.dart @@ -2,8 +2,8 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:geolocator/geolocator.dart'; -class LocationBloc { - Future getCurrentLocation(TextEditingController controller) async { +class LocationFetchBloc { + Future getCurrentLocation(TextEditingController controller, void Function(String)? onChange) async { LocationPermission permission = await Geolocator.checkPermission(); if (permission == LocationPermission.denied) { /// Request location permission @@ -19,6 +19,10 @@ class LocationBloc { /// Update the text controller with the current location controller.text = "${position.latitude}, ${position.longitude}"; + + if (onChange != null) { + onChange(controller.text); + } } } } diff --git a/flutter/digit-ui-components/digit_components/lib/blocs/TimeSelectionBloc.dart b/flutter/digit-ui-components/digit_components/lib/blocs/TimeSelectionBloc.dart index 2110692eb54..d5916dd4bd3 100644 --- a/flutter/digit-ui-components/digit_components/lib/blocs/TimeSelectionBloc.dart +++ b/flutter/digit-ui-components/digit_components/lib/blocs/TimeSelectionBloc.dart @@ -5,11 +5,16 @@ class TimeSelectionBloc { Future selectTime({ required BuildContext context, required TextEditingController controller, + String? cancelText, + String? confirmText, + void Function(String)? onChange, }) async { /// Show a time picker and update the controller's value TimeOfDay? selectedTime = await showTimePicker( context: context, initialTime: TimeOfDay.now(), + confirmText: confirmText, + cancelText: cancelText, builder: (BuildContext context, Widget? child) { return MediaQuery( data: MediaQuery.of(context).copyWith(alwaysUse24HourFormat: false), @@ -20,5 +25,9 @@ class TimeSelectionBloc { if (selectedTime != null) { controller.text = formatTime(selectedTime); } + + if (onChange != null) { + onChange(controller.text); + } } } \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/blocs/component_localization_delegate.dart b/flutter/digit-ui-components/digit_components/lib/blocs/component_localization_delegate.dart new file mode 100644 index 00000000000..b9c371b2a41 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/blocs/component_localization_delegate.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; + +import 'AppLocalization.dart'; + +class ComponentLocalizationDelegate + extends LocalizationsDelegate { + final Future localizedStrings; + final List languages; + + const ComponentLocalizationDelegate(this.localizedStrings, this.languages); + + @override + bool isSupported(Locale locale) { + return languages.map((e) { + final results = e.value.split('_'); + if (results.isNotEmpty) return results.first; + }).contains(locale.languageCode); + } + + @override + Future load(Locale locale) async { + ComponentLocalization localization = + ComponentLocalization(locale, localizedStrings, languages); + await localization.load(); + return localization; + } + + @override + bool shouldReload(covariant LocalizationsDelegate old) { + return true; + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/blocs/fetch_location_bloc.dart b/flutter/digit-ui-components/digit_components/lib/blocs/fetch_location_bloc.dart new file mode 100644 index 00000000000..b55ab774003 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/blocs/fetch_location_bloc.dart @@ -0,0 +1,191 @@ +import 'dart:async'; + +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:location/location.dart'; + +part 'fetch_location_bloc.freezed.dart'; + +typedef LocationStateEmitter = Emitter; + +/// LocationBLoC +/// +/// Follow setup instructions for appropriate platform +/// Android - +/// iOS - +/// macOS - +class LocationBloc extends Bloc { + final Location location; + + LocationBloc({required this.location}) : super(const LocationState()) { + on(_handleLoadLocation); + on(_handleRequestPermission); + on(_handleRequestService); + on(_handleSetLatLng); + on(_handleListenLocation); + } + + FutureOr _handleRequestPermission( + RequestLocationPermissionEvent event, + LocationStateEmitter emit, + ) async { + emit(state.copyWith(loading: true)); + try { + final permissions = await location.hasPermission(); + final hasPermissions = [ + PermissionStatus.granted, + PermissionStatus.grantedLimited, + ].contains(permissions); + emit(state.copyWith(hasPermissions: hasPermissions)); + if (!hasPermissions) { + if (event.retry > 0) { + await location.requestPermission(); + add(RequestLocationPermissionEvent(retry: event.retry - 1)); + } else { + throw Exception('Location permission request rejected'); + } + } else { + add(const LoadLocationEvent()); + } + } catch (error) { + rethrow; + } finally { + emit(state.copyWith(loading: false)); + } + } + + FutureOr _handleRequestService( + RequestLocationServiceEvent event, + LocationStateEmitter emit, + ) async { + emit(state.copyWith(loading: true)); + try { + final serviceEnabled = await location.serviceEnabled(); + emit(state.copyWith(serviceEnabled: serviceEnabled)); + if (!serviceEnabled) { + if (event.retry > 0) { + await location.requestService(); + add(RequestLocationServiceEvent(retry: event.retry - 1)); + } else { + throw Exception('Location service request rejected'); + } + } else { + add(const LoadLocationEvent()); + } + } catch (error) { + rethrow; + } finally { + emit(state.copyWith(loading: false)); + } + } + + FutureOr _handleListenLocation( + ListenLocationEvent event, + LocationStateEmitter emit, + ) async { + location.onLocationChanged.listen((locationData) { + if (!isClosed) { + add(LocationSetLatLngEvent(locationData: locationData)); + } + }); + } + + FutureOr _handleLoadLocation( + LoadLocationEvent event, + LocationStateEmitter emit, + ) async { + emit(state.copyWith(loading: true)); + try { + final permissions = await location.hasPermission(); + + if (![ + PermissionStatus.granted, + PermissionStatus.grantedLimited, + ].contains(permissions)) { + emit(state.copyWith(hasPermissions: false)); + add(const RequestLocationPermissionEvent()); + return; + } else { + emit(state.copyWith(hasPermissions: true)); + } + + final serviceEnabled = await location.serviceEnabled(); + emit(state.copyWith(serviceEnabled: serviceEnabled)); + + if (!serviceEnabled) { + add(const RequestLocationServiceEvent()); + return; + } + + add(const ListenLocationEvent()); + final locationData = await location.getLocation(); + add(LocationSetLatLngEvent(locationData: locationData)); + } catch (error) { + rethrow; + } finally { + emit(state.copyWith(loading: false)); + } + } + + void _handleSetLatLng( + LocationSetLatLngEvent event, + LocationStateEmitter emit, + ) { + final locationData = event.locationData; + + if ([ + locationData.latitude, + locationData.longitude, + ].any((element) => element == null)) { + throw Exception('Could not fetch location data'); + } + + emit(state.copyWith( + latitude: locationData.latitude, + longitude: locationData.longitude, + accuracy: locationData.accuracy, + )); + } +} + +@freezed +class LocationEvent with _$LocationEvent { + const factory LocationEvent.load({ + @Default(5) int retry, + }) = LoadLocationEvent; + + const factory LocationEvent.listen({ + @Default(5) int retry, + }) = ListenLocationEvent; + + const factory LocationEvent.requestService({ + @Default(5) int retry, + }) = RequestLocationServiceEvent; + + const factory LocationEvent.requestPermission({ + @Default(1) int retry, + }) = RequestLocationPermissionEvent; + + const factory LocationEvent.setLatLng({ + required LocationData locationData, + }) = LocationSetLatLngEvent; +} + +@freezed +class LocationState with _$LocationState { + const LocationState._(); + + const factory LocationState({ + double? latitude, + double? longitude, + double? accuracy, + @Default(false) hasPermissions, + @Default(false) bool serviceEnabled, + @Default(false) bool loading, + }) = _LocationState; + + String get latLngString { + if (latitude == null || longitude == null) return 'Undefined'; + return [latitude, longitude].join(', '); + } +} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/blocs/fetch_location_bloc.freezed.dart b/flutter/digit-ui-components/digit_components/lib/blocs/fetch_location_bloc.freezed.dart new file mode 100644 index 00000000000..e37730fb7ee --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/blocs/fetch_location_bloc.freezed.dart @@ -0,0 +1,1115 @@ +// coverage:ignore-file +// GENERATED CODE - DO NOT MODIFY BY HAND +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'fetch_location_bloc.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +T _$identity(T value) => value; + +final _privateConstructorUsedError = UnsupportedError( + 'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models'); + +/// @nodoc +mixin _$LocationEvent { + @optionalTypeArgs + TResult when({ + required TResult Function(int retry) load, + required TResult Function(int retry) listen, + required TResult Function(int retry) requestService, + required TResult Function(int retry) requestPermission, + required TResult Function(LocationData locationData) setLatLng, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(int retry)? load, + TResult? Function(int retry)? listen, + TResult? Function(int retry)? requestService, + TResult? Function(int retry)? requestPermission, + TResult? Function(LocationData locationData)? setLatLng, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(int retry)? load, + TResult Function(int retry)? listen, + TResult Function(int retry)? requestService, + TResult Function(int retry)? requestPermission, + TResult Function(LocationData locationData)? setLatLng, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult map({ + required TResult Function(LoadLocationEvent value) load, + required TResult Function(ListenLocationEvent value) listen, + required TResult Function(RequestLocationServiceEvent value) requestService, + required TResult Function(RequestLocationPermissionEvent value) + requestPermission, + required TResult Function(LocationSetLatLngEvent value) setLatLng, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(LoadLocationEvent value)? load, + TResult? Function(ListenLocationEvent value)? listen, + TResult? Function(RequestLocationServiceEvent value)? requestService, + TResult? Function(RequestLocationPermissionEvent value)? requestPermission, + TResult? Function(LocationSetLatLngEvent value)? setLatLng, + }) => + throw _privateConstructorUsedError; + @optionalTypeArgs + TResult maybeMap({ + TResult Function(LoadLocationEvent value)? load, + TResult Function(ListenLocationEvent value)? listen, + TResult Function(RequestLocationServiceEvent value)? requestService, + TResult Function(RequestLocationPermissionEvent value)? requestPermission, + TResult Function(LocationSetLatLngEvent value)? setLatLng, + required TResult orElse(), + }) => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $LocationEventCopyWith<$Res> { + factory $LocationEventCopyWith( + LocationEvent value, $Res Function(LocationEvent) then) = + _$LocationEventCopyWithImpl<$Res, LocationEvent>; +} + +/// @nodoc +class _$LocationEventCopyWithImpl<$Res, $Val extends LocationEvent> + implements $LocationEventCopyWith<$Res> { + _$LocationEventCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; +} + +/// @nodoc +abstract class _$$LoadLocationEventImplCopyWith<$Res> { + factory _$$LoadLocationEventImplCopyWith(_$LoadLocationEventImpl value, + $Res Function(_$LoadLocationEventImpl) then) = + __$$LoadLocationEventImplCopyWithImpl<$Res>; + @useResult + $Res call({int retry}); +} + +/// @nodoc +class __$$LoadLocationEventImplCopyWithImpl<$Res> + extends _$LocationEventCopyWithImpl<$Res, _$LoadLocationEventImpl> + implements _$$LoadLocationEventImplCopyWith<$Res> { + __$$LoadLocationEventImplCopyWithImpl(_$LoadLocationEventImpl _value, + $Res Function(_$LoadLocationEventImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? retry = null, + }) { + return _then(_$LoadLocationEventImpl( + retry: null == retry + ? _value.retry + : retry // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc + +class _$LoadLocationEventImpl implements LoadLocationEvent { + const _$LoadLocationEventImpl({this.retry = 5}); + + @override + @JsonKey() + final int retry; + + @override + String toString() { + return 'LocationEvent.load(retry: $retry)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$LoadLocationEventImpl && + (identical(other.retry, retry) || other.retry == retry)); + } + + @override + int get hashCode => Object.hash(runtimeType, retry); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$LoadLocationEventImplCopyWith<_$LoadLocationEventImpl> get copyWith => + __$$LoadLocationEventImplCopyWithImpl<_$LoadLocationEventImpl>( + this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(int retry) load, + required TResult Function(int retry) listen, + required TResult Function(int retry) requestService, + required TResult Function(int retry) requestPermission, + required TResult Function(LocationData locationData) setLatLng, + }) { + return load(retry); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(int retry)? load, + TResult? Function(int retry)? listen, + TResult? Function(int retry)? requestService, + TResult? Function(int retry)? requestPermission, + TResult? Function(LocationData locationData)? setLatLng, + }) { + return load?.call(retry); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(int retry)? load, + TResult Function(int retry)? listen, + TResult Function(int retry)? requestService, + TResult Function(int retry)? requestPermission, + TResult Function(LocationData locationData)? setLatLng, + required TResult orElse(), + }) { + if (load != null) { + return load(retry); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(LoadLocationEvent value) load, + required TResult Function(ListenLocationEvent value) listen, + required TResult Function(RequestLocationServiceEvent value) requestService, + required TResult Function(RequestLocationPermissionEvent value) + requestPermission, + required TResult Function(LocationSetLatLngEvent value) setLatLng, + }) { + return load(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(LoadLocationEvent value)? load, + TResult? Function(ListenLocationEvent value)? listen, + TResult? Function(RequestLocationServiceEvent value)? requestService, + TResult? Function(RequestLocationPermissionEvent value)? requestPermission, + TResult? Function(LocationSetLatLngEvent value)? setLatLng, + }) { + return load?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(LoadLocationEvent value)? load, + TResult Function(ListenLocationEvent value)? listen, + TResult Function(RequestLocationServiceEvent value)? requestService, + TResult Function(RequestLocationPermissionEvent value)? requestPermission, + TResult Function(LocationSetLatLngEvent value)? setLatLng, + required TResult orElse(), + }) { + if (load != null) { + return load(this); + } + return orElse(); + } +} + +abstract class LoadLocationEvent implements LocationEvent { + const factory LoadLocationEvent({final int retry}) = _$LoadLocationEventImpl; + + int get retry; + @JsonKey(ignore: true) + _$$LoadLocationEventImplCopyWith<_$LoadLocationEventImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$ListenLocationEventImplCopyWith<$Res> { + factory _$$ListenLocationEventImplCopyWith(_$ListenLocationEventImpl value, + $Res Function(_$ListenLocationEventImpl) then) = + __$$ListenLocationEventImplCopyWithImpl<$Res>; + @useResult + $Res call({int retry}); +} + +/// @nodoc +class __$$ListenLocationEventImplCopyWithImpl<$Res> + extends _$LocationEventCopyWithImpl<$Res, _$ListenLocationEventImpl> + implements _$$ListenLocationEventImplCopyWith<$Res> { + __$$ListenLocationEventImplCopyWithImpl(_$ListenLocationEventImpl _value, + $Res Function(_$ListenLocationEventImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? retry = null, + }) { + return _then(_$ListenLocationEventImpl( + retry: null == retry + ? _value.retry + : retry // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc + +class _$ListenLocationEventImpl implements ListenLocationEvent { + const _$ListenLocationEventImpl({this.retry = 5}); + + @override + @JsonKey() + final int retry; + + @override + String toString() { + return 'LocationEvent.listen(retry: $retry)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$ListenLocationEventImpl && + (identical(other.retry, retry) || other.retry == retry)); + } + + @override + int get hashCode => Object.hash(runtimeType, retry); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$ListenLocationEventImplCopyWith<_$ListenLocationEventImpl> get copyWith => + __$$ListenLocationEventImplCopyWithImpl<_$ListenLocationEventImpl>( + this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(int retry) load, + required TResult Function(int retry) listen, + required TResult Function(int retry) requestService, + required TResult Function(int retry) requestPermission, + required TResult Function(LocationData locationData) setLatLng, + }) { + return listen(retry); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(int retry)? load, + TResult? Function(int retry)? listen, + TResult? Function(int retry)? requestService, + TResult? Function(int retry)? requestPermission, + TResult? Function(LocationData locationData)? setLatLng, + }) { + return listen?.call(retry); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(int retry)? load, + TResult Function(int retry)? listen, + TResult Function(int retry)? requestService, + TResult Function(int retry)? requestPermission, + TResult Function(LocationData locationData)? setLatLng, + required TResult orElse(), + }) { + if (listen != null) { + return listen(retry); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(LoadLocationEvent value) load, + required TResult Function(ListenLocationEvent value) listen, + required TResult Function(RequestLocationServiceEvent value) requestService, + required TResult Function(RequestLocationPermissionEvent value) + requestPermission, + required TResult Function(LocationSetLatLngEvent value) setLatLng, + }) { + return listen(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(LoadLocationEvent value)? load, + TResult? Function(ListenLocationEvent value)? listen, + TResult? Function(RequestLocationServiceEvent value)? requestService, + TResult? Function(RequestLocationPermissionEvent value)? requestPermission, + TResult? Function(LocationSetLatLngEvent value)? setLatLng, + }) { + return listen?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(LoadLocationEvent value)? load, + TResult Function(ListenLocationEvent value)? listen, + TResult Function(RequestLocationServiceEvent value)? requestService, + TResult Function(RequestLocationPermissionEvent value)? requestPermission, + TResult Function(LocationSetLatLngEvent value)? setLatLng, + required TResult orElse(), + }) { + if (listen != null) { + return listen(this); + } + return orElse(); + } +} + +abstract class ListenLocationEvent implements LocationEvent { + const factory ListenLocationEvent({final int retry}) = + _$ListenLocationEventImpl; + + int get retry; + @JsonKey(ignore: true) + _$$ListenLocationEventImplCopyWith<_$ListenLocationEventImpl> get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$RequestLocationServiceEventImplCopyWith<$Res> { + factory _$$RequestLocationServiceEventImplCopyWith( + _$RequestLocationServiceEventImpl value, + $Res Function(_$RequestLocationServiceEventImpl) then) = + __$$RequestLocationServiceEventImplCopyWithImpl<$Res>; + @useResult + $Res call({int retry}); +} + +/// @nodoc +class __$$RequestLocationServiceEventImplCopyWithImpl<$Res> + extends _$LocationEventCopyWithImpl<$Res, _$RequestLocationServiceEventImpl> + implements _$$RequestLocationServiceEventImplCopyWith<$Res> { + __$$RequestLocationServiceEventImplCopyWithImpl( + _$RequestLocationServiceEventImpl _value, + $Res Function(_$RequestLocationServiceEventImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? retry = null, + }) { + return _then(_$RequestLocationServiceEventImpl( + retry: null == retry + ? _value.retry + : retry // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc + +class _$RequestLocationServiceEventImpl implements RequestLocationServiceEvent { + const _$RequestLocationServiceEventImpl({this.retry = 5}); + + @override + @JsonKey() + final int retry; + + @override + String toString() { + return 'LocationEvent.requestService(retry: $retry)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$RequestLocationServiceEventImpl && + (identical(other.retry, retry) || other.retry == retry)); + } + + @override + int get hashCode => Object.hash(runtimeType, retry); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$RequestLocationServiceEventImplCopyWith<_$RequestLocationServiceEventImpl> + get copyWith => __$$RequestLocationServiceEventImplCopyWithImpl< + _$RequestLocationServiceEventImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(int retry) load, + required TResult Function(int retry) listen, + required TResult Function(int retry) requestService, + required TResult Function(int retry) requestPermission, + required TResult Function(LocationData locationData) setLatLng, + }) { + return requestService(retry); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(int retry)? load, + TResult? Function(int retry)? listen, + TResult? Function(int retry)? requestService, + TResult? Function(int retry)? requestPermission, + TResult? Function(LocationData locationData)? setLatLng, + }) { + return requestService?.call(retry); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(int retry)? load, + TResult Function(int retry)? listen, + TResult Function(int retry)? requestService, + TResult Function(int retry)? requestPermission, + TResult Function(LocationData locationData)? setLatLng, + required TResult orElse(), + }) { + if (requestService != null) { + return requestService(retry); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(LoadLocationEvent value) load, + required TResult Function(ListenLocationEvent value) listen, + required TResult Function(RequestLocationServiceEvent value) requestService, + required TResult Function(RequestLocationPermissionEvent value) + requestPermission, + required TResult Function(LocationSetLatLngEvent value) setLatLng, + }) { + return requestService(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(LoadLocationEvent value)? load, + TResult? Function(ListenLocationEvent value)? listen, + TResult? Function(RequestLocationServiceEvent value)? requestService, + TResult? Function(RequestLocationPermissionEvent value)? requestPermission, + TResult? Function(LocationSetLatLngEvent value)? setLatLng, + }) { + return requestService?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(LoadLocationEvent value)? load, + TResult Function(ListenLocationEvent value)? listen, + TResult Function(RequestLocationServiceEvent value)? requestService, + TResult Function(RequestLocationPermissionEvent value)? requestPermission, + TResult Function(LocationSetLatLngEvent value)? setLatLng, + required TResult orElse(), + }) { + if (requestService != null) { + return requestService(this); + } + return orElse(); + } +} + +abstract class RequestLocationServiceEvent implements LocationEvent { + const factory RequestLocationServiceEvent({final int retry}) = + _$RequestLocationServiceEventImpl; + + int get retry; + @JsonKey(ignore: true) + _$$RequestLocationServiceEventImplCopyWith<_$RequestLocationServiceEventImpl> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$RequestLocationPermissionEventImplCopyWith<$Res> { + factory _$$RequestLocationPermissionEventImplCopyWith( + _$RequestLocationPermissionEventImpl value, + $Res Function(_$RequestLocationPermissionEventImpl) then) = + __$$RequestLocationPermissionEventImplCopyWithImpl<$Res>; + @useResult + $Res call({int retry}); +} + +/// @nodoc +class __$$RequestLocationPermissionEventImplCopyWithImpl<$Res> + extends _$LocationEventCopyWithImpl<$Res, + _$RequestLocationPermissionEventImpl> + implements _$$RequestLocationPermissionEventImplCopyWith<$Res> { + __$$RequestLocationPermissionEventImplCopyWithImpl( + _$RequestLocationPermissionEventImpl _value, + $Res Function(_$RequestLocationPermissionEventImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? retry = null, + }) { + return _then(_$RequestLocationPermissionEventImpl( + retry: null == retry + ? _value.retry + : retry // ignore: cast_nullable_to_non_nullable + as int, + )); + } +} + +/// @nodoc + +class _$RequestLocationPermissionEventImpl + implements RequestLocationPermissionEvent { + const _$RequestLocationPermissionEventImpl({this.retry = 1}); + + @override + @JsonKey() + final int retry; + + @override + String toString() { + return 'LocationEvent.requestPermission(retry: $retry)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$RequestLocationPermissionEventImpl && + (identical(other.retry, retry) || other.retry == retry)); + } + + @override + int get hashCode => Object.hash(runtimeType, retry); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$RequestLocationPermissionEventImplCopyWith< + _$RequestLocationPermissionEventImpl> + get copyWith => __$$RequestLocationPermissionEventImplCopyWithImpl< + _$RequestLocationPermissionEventImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(int retry) load, + required TResult Function(int retry) listen, + required TResult Function(int retry) requestService, + required TResult Function(int retry) requestPermission, + required TResult Function(LocationData locationData) setLatLng, + }) { + return requestPermission(retry); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(int retry)? load, + TResult? Function(int retry)? listen, + TResult? Function(int retry)? requestService, + TResult? Function(int retry)? requestPermission, + TResult? Function(LocationData locationData)? setLatLng, + }) { + return requestPermission?.call(retry); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(int retry)? load, + TResult Function(int retry)? listen, + TResult Function(int retry)? requestService, + TResult Function(int retry)? requestPermission, + TResult Function(LocationData locationData)? setLatLng, + required TResult orElse(), + }) { + if (requestPermission != null) { + return requestPermission(retry); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(LoadLocationEvent value) load, + required TResult Function(ListenLocationEvent value) listen, + required TResult Function(RequestLocationServiceEvent value) requestService, + required TResult Function(RequestLocationPermissionEvent value) + requestPermission, + required TResult Function(LocationSetLatLngEvent value) setLatLng, + }) { + return requestPermission(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(LoadLocationEvent value)? load, + TResult? Function(ListenLocationEvent value)? listen, + TResult? Function(RequestLocationServiceEvent value)? requestService, + TResult? Function(RequestLocationPermissionEvent value)? requestPermission, + TResult? Function(LocationSetLatLngEvent value)? setLatLng, + }) { + return requestPermission?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(LoadLocationEvent value)? load, + TResult Function(ListenLocationEvent value)? listen, + TResult Function(RequestLocationServiceEvent value)? requestService, + TResult Function(RequestLocationPermissionEvent value)? requestPermission, + TResult Function(LocationSetLatLngEvent value)? setLatLng, + required TResult orElse(), + }) { + if (requestPermission != null) { + return requestPermission(this); + } + return orElse(); + } +} + +abstract class RequestLocationPermissionEvent implements LocationEvent { + const factory RequestLocationPermissionEvent({final int retry}) = + _$RequestLocationPermissionEventImpl; + + int get retry; + @JsonKey(ignore: true) + _$$RequestLocationPermissionEventImplCopyWith< + _$RequestLocationPermissionEventImpl> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class _$$LocationSetLatLngEventImplCopyWith<$Res> { + factory _$$LocationSetLatLngEventImplCopyWith( + _$LocationSetLatLngEventImpl value, + $Res Function(_$LocationSetLatLngEventImpl) then) = + __$$LocationSetLatLngEventImplCopyWithImpl<$Res>; + @useResult + $Res call({LocationData locationData}); +} + +/// @nodoc +class __$$LocationSetLatLngEventImplCopyWithImpl<$Res> + extends _$LocationEventCopyWithImpl<$Res, _$LocationSetLatLngEventImpl> + implements _$$LocationSetLatLngEventImplCopyWith<$Res> { + __$$LocationSetLatLngEventImplCopyWithImpl( + _$LocationSetLatLngEventImpl _value, + $Res Function(_$LocationSetLatLngEventImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? locationData = null, + }) { + return _then(_$LocationSetLatLngEventImpl( + locationData: null == locationData + ? _value.locationData + : locationData // ignore: cast_nullable_to_non_nullable + as LocationData, + )); + } +} + +/// @nodoc + +class _$LocationSetLatLngEventImpl implements LocationSetLatLngEvent { + const _$LocationSetLatLngEventImpl({required this.locationData}); + + @override + final LocationData locationData; + + @override + String toString() { + return 'LocationEvent.setLatLng(locationData: $locationData)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$LocationSetLatLngEventImpl && + (identical(other.locationData, locationData) || + other.locationData == locationData)); + } + + @override + int get hashCode => Object.hash(runtimeType, locationData); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$LocationSetLatLngEventImplCopyWith<_$LocationSetLatLngEventImpl> + get copyWith => __$$LocationSetLatLngEventImplCopyWithImpl< + _$LocationSetLatLngEventImpl>(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function(int retry) load, + required TResult Function(int retry) listen, + required TResult Function(int retry) requestService, + required TResult Function(int retry) requestPermission, + required TResult Function(LocationData locationData) setLatLng, + }) { + return setLatLng(locationData); + } + + @override + @optionalTypeArgs + TResult? whenOrNull({ + TResult? Function(int retry)? load, + TResult? Function(int retry)? listen, + TResult? Function(int retry)? requestService, + TResult? Function(int retry)? requestPermission, + TResult? Function(LocationData locationData)? setLatLng, + }) { + return setLatLng?.call(locationData); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function(int retry)? load, + TResult Function(int retry)? listen, + TResult Function(int retry)? requestService, + TResult Function(int retry)? requestPermission, + TResult Function(LocationData locationData)? setLatLng, + required TResult orElse(), + }) { + if (setLatLng != null) { + return setLatLng(locationData); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(LoadLocationEvent value) load, + required TResult Function(ListenLocationEvent value) listen, + required TResult Function(RequestLocationServiceEvent value) requestService, + required TResult Function(RequestLocationPermissionEvent value) + requestPermission, + required TResult Function(LocationSetLatLngEvent value) setLatLng, + }) { + return setLatLng(this); + } + + @override + @optionalTypeArgs + TResult? mapOrNull({ + TResult? Function(LoadLocationEvent value)? load, + TResult? Function(ListenLocationEvent value)? listen, + TResult? Function(RequestLocationServiceEvent value)? requestService, + TResult? Function(RequestLocationPermissionEvent value)? requestPermission, + TResult? Function(LocationSetLatLngEvent value)? setLatLng, + }) { + return setLatLng?.call(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(LoadLocationEvent value)? load, + TResult Function(ListenLocationEvent value)? listen, + TResult Function(RequestLocationServiceEvent value)? requestService, + TResult Function(RequestLocationPermissionEvent value)? requestPermission, + TResult Function(LocationSetLatLngEvent value)? setLatLng, + required TResult orElse(), + }) { + if (setLatLng != null) { + return setLatLng(this); + } + return orElse(); + } +} + +abstract class LocationSetLatLngEvent implements LocationEvent { + const factory LocationSetLatLngEvent( + {required final LocationData locationData}) = + _$LocationSetLatLngEventImpl; + + LocationData get locationData; + @JsonKey(ignore: true) + _$$LocationSetLatLngEventImplCopyWith<_$LocationSetLatLngEventImpl> + get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +mixin _$LocationState { + double? get latitude => throw _privateConstructorUsedError; + double? get longitude => throw _privateConstructorUsedError; + double? get accuracy => throw _privateConstructorUsedError; + dynamic get hasPermissions => throw _privateConstructorUsedError; + bool get serviceEnabled => throw _privateConstructorUsedError; + bool get loading => throw _privateConstructorUsedError; + + @JsonKey(ignore: true) + $LocationStateCopyWith get copyWith => + throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $LocationStateCopyWith<$Res> { + factory $LocationStateCopyWith( + LocationState value, $Res Function(LocationState) then) = + _$LocationStateCopyWithImpl<$Res, LocationState>; + @useResult + $Res call( + {double? latitude, + double? longitude, + double? accuracy, + dynamic hasPermissions, + bool serviceEnabled, + bool loading}); +} + +/// @nodoc +class _$LocationStateCopyWithImpl<$Res, $Val extends LocationState> + implements $LocationStateCopyWith<$Res> { + _$LocationStateCopyWithImpl(this._value, this._then); + + // ignore: unused_field + final $Val _value; + // ignore: unused_field + final $Res Function($Val) _then; + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? latitude = freezed, + Object? longitude = freezed, + Object? accuracy = freezed, + Object? hasPermissions = freezed, + Object? serviceEnabled = null, + Object? loading = null, + }) { + return _then(_value.copyWith( + latitude: freezed == latitude + ? _value.latitude + : latitude // ignore: cast_nullable_to_non_nullable + as double?, + longitude: freezed == longitude + ? _value.longitude + : longitude // ignore: cast_nullable_to_non_nullable + as double?, + accuracy: freezed == accuracy + ? _value.accuracy + : accuracy // ignore: cast_nullable_to_non_nullable + as double?, + hasPermissions: freezed == hasPermissions + ? _value.hasPermissions + : hasPermissions // ignore: cast_nullable_to_non_nullable + as dynamic, + serviceEnabled: null == serviceEnabled + ? _value.serviceEnabled + : serviceEnabled // ignore: cast_nullable_to_non_nullable + as bool, + loading: null == loading + ? _value.loading + : loading // ignore: cast_nullable_to_non_nullable + as bool, + ) as $Val); + } +} + +/// @nodoc +abstract class _$$LocationStateImplCopyWith<$Res> + implements $LocationStateCopyWith<$Res> { + factory _$$LocationStateImplCopyWith( + _$LocationStateImpl value, $Res Function(_$LocationStateImpl) then) = + __$$LocationStateImplCopyWithImpl<$Res>; + @override + @useResult + $Res call( + {double? latitude, + double? longitude, + double? accuracy, + dynamic hasPermissions, + bool serviceEnabled, + bool loading}); +} + +/// @nodoc +class __$$LocationStateImplCopyWithImpl<$Res> + extends _$LocationStateCopyWithImpl<$Res, _$LocationStateImpl> + implements _$$LocationStateImplCopyWith<$Res> { + __$$LocationStateImplCopyWithImpl( + _$LocationStateImpl _value, $Res Function(_$LocationStateImpl) _then) + : super(_value, _then); + + @pragma('vm:prefer-inline') + @override + $Res call({ + Object? latitude = freezed, + Object? longitude = freezed, + Object? accuracy = freezed, + Object? hasPermissions = freezed, + Object? serviceEnabled = null, + Object? loading = null, + }) { + return _then(_$LocationStateImpl( + latitude: freezed == latitude + ? _value.latitude + : latitude // ignore: cast_nullable_to_non_nullable + as double?, + longitude: freezed == longitude + ? _value.longitude + : longitude // ignore: cast_nullable_to_non_nullable + as double?, + accuracy: freezed == accuracy + ? _value.accuracy + : accuracy // ignore: cast_nullable_to_non_nullable + as double?, + hasPermissions: + freezed == hasPermissions ? _value.hasPermissions! : hasPermissions, + serviceEnabled: null == serviceEnabled + ? _value.serviceEnabled + : serviceEnabled // ignore: cast_nullable_to_non_nullable + as bool, + loading: null == loading + ? _value.loading + : loading // ignore: cast_nullable_to_non_nullable + as bool, + )); + } +} + +/// @nodoc + +class _$LocationStateImpl extends _LocationState { + const _$LocationStateImpl( + {this.latitude, + this.longitude, + this.accuracy, + this.hasPermissions = false, + this.serviceEnabled = false, + this.loading = false}) + : super._(); + + @override + final double? latitude; + @override + final double? longitude; + @override + final double? accuracy; + @override + @JsonKey() + final dynamic hasPermissions; + @override + @JsonKey() + final bool serviceEnabled; + @override + @JsonKey() + final bool loading; + + @override + String toString() { + return 'LocationState(latitude: $latitude, longitude: $longitude, accuracy: $accuracy, hasPermissions: $hasPermissions, serviceEnabled: $serviceEnabled, loading: $loading)'; + } + + @override + bool operator ==(Object other) { + return identical(this, other) || + (other.runtimeType == runtimeType && + other is _$LocationStateImpl && + (identical(other.latitude, latitude) || + other.latitude == latitude) && + (identical(other.longitude, longitude) || + other.longitude == longitude) && + (identical(other.accuracy, accuracy) || + other.accuracy == accuracy) && + const DeepCollectionEquality() + .equals(other.hasPermissions, hasPermissions) && + (identical(other.serviceEnabled, serviceEnabled) || + other.serviceEnabled == serviceEnabled) && + (identical(other.loading, loading) || other.loading == loading)); + } + + @override + int get hashCode => Object.hash( + runtimeType, + latitude, + longitude, + accuracy, + const DeepCollectionEquality().hash(hasPermissions), + serviceEnabled, + loading); + + @JsonKey(ignore: true) + @override + @pragma('vm:prefer-inline') + _$$LocationStateImplCopyWith<_$LocationStateImpl> get copyWith => + __$$LocationStateImplCopyWithImpl<_$LocationStateImpl>(this, _$identity); +} + +abstract class _LocationState extends LocationState { + const factory _LocationState( + {final double? latitude, + final double? longitude, + final double? accuracy, + final dynamic hasPermissions, + final bool serviceEnabled, + final bool loading}) = _$LocationStateImpl; + const _LocationState._() : super._(); + + @override + double? get latitude; + @override + double? get longitude; + @override + double? get accuracy; + @override + dynamic get hasPermissions; + @override + bool get serviceEnabled; + @override + bool get loading; + @override + @JsonKey(ignore: true) + _$$LocationStateImplCopyWith<_$LocationStateImpl> get copyWith => + throw _privateConstructorUsedError; +} diff --git a/flutter/digit-ui-components/digit_components/lib/constants/AppView.dart b/flutter/digit-ui-components/digit_components/lib/constants/AppView.dart index 0b5296d4952..c32807d86cc 100644 --- a/flutter/digit-ui-components/digit_components/lib/constants/AppView.dart +++ b/flutter/digit-ui-components/digit_components/lib/constants/AppView.dart @@ -1,20 +1,20 @@ -class AppSizes { - /// Define breakpoints for different views - static const double mobileViewWidth = 400.0; - static const double tabletViewWidth = 768.0; -} +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; class AppView { - /// Determine the current view based on the screen width - static bool isMobileView(double screenWidth) { - return screenWidth <= AppSizes.mobileViewWidth; + /// Determine the current view based on the screen aspect ratio + static bool isMobileView(Size screenSize) { + double aspectRatio = screenSize.aspectRatio; + return aspectRatio <= 9 / 16; /// Landscape or square aspect ratio } - static bool isTabletView(double screenWidth) { - return screenWidth > AppSizes.mobileViewWidth && screenWidth <= AppSizes.tabletViewWidth; + static bool isTabletView(Size screenSize) { + double aspectRatio = screenSize.aspectRatio; + return aspectRatio > 9 / 16 && aspectRatio <= 3 / 4; /// Portrait aspect ratio } - static bool isDesktopView(double screenWidth) { - return screenWidth >= AppSizes.tabletViewWidth; + static bool isDesktopView(Size screenSize) { + double aspectRatio = screenSize.aspectRatio; + return aspectRatio > 3 / 4; /// Landscape or square aspect ratio } -} +} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/constants/app_constants.dart b/flutter/digit-ui-components/digit_components/lib/constants/app_constants.dart index ea660544d67..aeaa15e205d 100644 --- a/flutter/digit-ui-components/digit_components/lib/constants/app_constants.dart +++ b/flutter/digit-ui-components/digit_components/lib/constants/app_constants.dart @@ -1,20 +1,33 @@ +import 'package:digit_ui_components/digit_components.dart'; import 'package:flutter/material.dart'; +import '../theme/theme.dart'; -import '../theme/colors.dart'; -import '../theme/digit_theme.dart'; - -class Default{ +class Base{ static const double height = 40; static const double mobileInputWidth = 328; static const double desktopInputWidth = 600; static const double tabInputWidth = 440; - static const double defaultChipRadius = 50; - static const EdgeInsets defaultChipPadding = EdgeInsets.only( - left: 12, - right: kPadding / 2, - ); - static const String textAreaSvg = 'assets/icons/svg/textAreaExpand.svg'; + static const double defaultCircularRadius = 50; + static const double defaultBorderWidth = 1; + static const double selectedBorderWidth = 1; + static const double focusedBorderWidth = 1.5; + static const double errorBorderWidth = 1.5; + static const double hoverBorderWidth = 0.5; + static const BorderRadius radius = BorderRadius.zero; + static const double imageSize = 100; + static const String textAreaSvg = 'assets/icons/svg/text_area_expand.svg'; static const String profileSvg = 'assets/icons/svg/Profile.svg'; + static const String docSvg = 'assets/icons/svg/doc.svg'; + static const String jpgSvg = 'assets/icons/svg/jpg.svg'; + static const String pdfSvg = 'assets/icons/svg/pdf.svg'; + static const String pngSvg = 'assets/icons/svg/png.svg'; + static const String xlsxSvg = 'assets/icons/svg/xlsx.svg'; + static const String fileSvg = 'assets/icons/svg/file.svg'; + static const String errorJson = 'assets/animated_json/error.json'; + static const String successJson = 'assets/animated_json/success.json'; + static const String digitLogoDarkSvg = 'assets/images/digit_logo_dark.png'; + static const String digitLogoLightSvg = 'assets/images/digit_logo_light.png'; + static const String profileIconSvg = 'assets/icons/svg/profile_icon.svg'; } class BaseConstants { @@ -28,10 +41,16 @@ class BaseConstants { static const double desktopInputMinWidth = 200.0; static const double tabInputMaxWidth = 440.0; static const double tabInputMinWidth = 200.0; + static const double successAnimationM = 80; + static const double successAnimationT = 100; + static const double successAnimationD = 120; + static const double errorAnimationM = 56; + static const double errorAnimationT = 64; + static const double errorAnimationD = 74; static final OutlineInputBorder focusedBorder = OutlineInputBorder( borderSide: BorderSide( - color: const DigitColors().light.primaryOrange, width: 1.5), + color: const DigitColors().light.primary1, width: 1.5), borderRadius: BorderRadius.zero, ); @@ -46,15 +65,17 @@ class BaseConstants { class ButtonConstants { - static const EdgeInsets defaultButtonPadding = EdgeInsets.all(8.0); - static const EdgeInsets defaultContentPadding = EdgeInsets.only(left: 24.0, top: 7.0, right: 24.0, bottom: 8.0); - static const double defaultIconSize = 24.0; - static final Color defaultDisabledColor = const DigitColors().light.textDisabled; - static final Color defaultPrimaryColor = const DigitColors().light.primaryOrange; - static final Color defaultSecondaryColor = const DigitColors().light.textPrimary; - static final Color defaultTextColor = const DigitColors().light.paperPrimary; - static const double defaultWidth = 1.0; - static const double defaultHoverWidth = 2.0; + static const EdgeInsets defaultButtonPadding = EdgeInsets.all(spacer1); + static const EdgeInsets defaultContentPadding = EdgeInsets.symmetric(horizontal: spacer6, vertical: 0); + static const double largeButtonSize = 40.0; + static const double mediumButtonSize = 32.0; + static const double smallButtonSize = 24.0; + static const double largeIconSize = 24.0; + static const double mediumIconSize = 20.0; + static const double smallIconSize = 14.0; + static const double largeLinkIconSize = 20.0; + static const double mediumLinkIconSize = 20.0; + static const double smallLinkIconSize = 14.0; } class DigitCheckboxConstants { static const double iconSize = 16.0; @@ -66,13 +87,13 @@ class DigitCheckboxConstants { customColor ?? (isDisabled ? const DigitColors().light.textDisabled : const DigitColors().light.textSecondary); static Color checkedBorderColor({required bool isDisabled, required Color? customColor}) => - customColor ?? (isDisabled ? const DigitColors().light.textDisabled : const DigitColors().light.primaryOrange); + customColor ?? (isDisabled ? const DigitColors().light.textDisabled : const DigitColors().light.primary1); static Color intermediateBorderColor({required bool isDisabled, required Color? customColor}) => - customColor ?? (isDisabled ? const DigitColors().light.textDisabled : const DigitColors().light.primaryOrange); + customColor ?? (isDisabled ? const DigitColors().light.textDisabled : const DigitColors().light.primary1); static Color iconColor({required bool isDisabled, required Color? customColor}) => - customColor ?? (isDisabled ? const DigitColors().light.textDisabled : const DigitColors().light.primaryOrange); + customColor ?? (isDisabled ? const DigitColors().light.textDisabled : const DigitColors().light.primary1); } class DropdownConstants { @@ -84,14 +105,31 @@ class DropdownConstants { static const double defaultProfileSize = 32; static const double defaultImageRadius = 72; static const double textIconSize = 20; - static const EdgeInsets noItemAvailablePadding = EdgeInsets.symmetric(horizontal: kPadding*2, vertical: 10.0); + static const EdgeInsets noItemAvailablePadding = EdgeInsets.symmetric(horizontal: spacer4, vertical: 10.0); static const Duration animationDuration = Duration(milliseconds: 200); } class RadioConstant { - static const EdgeInsets defaultPadding = EdgeInsets.all(8); - static const double radioWidth = 24.0; - static const double radioHeight = 24.0; + static const EdgeInsets defaultPadding = EdgeInsets.all(spacer2); + static const double radioWidth = spacer6; + static const double radioHeight = spacer6; +} + +class ToastConstant { + static const double tabMinWidth = 480; + static const double desktopMinWidth = 800; + Duration get toastDuration => const Duration(seconds: 5); +} + +class PopUpCardConstant { + /// Margins + static const double verticalMarginMobile = 64.0; + static const double verticalMarginTab = 100.0; + static const double verticalMarginDesktop = 74.0; + + static const double horizontalMarginMobile = 16.0; + static const double horizontalMarginTab = 98.0; + static const double horizontalMarginDesktop = 446.0; + } -Duration get toastDuration => const Duration(seconds: 5); \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/constants/constant.dart b/flutter/digit-ui-components/digit_components/lib/constants/constant.dart new file mode 100644 index 00000000000..3686d6324f7 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/constants/constant.dart @@ -0,0 +1,2 @@ +export 'app_constants.dart'; +export 'AppView.dart'; \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/digit_components.dart b/flutter/digit-ui-components/digit_components/lib/digit_components.dart index e1e184daa62..5aa64760722 100644 --- a/flutter/digit-ui-components/digit_components/lib/digit_components.dart +++ b/flutter/digit-ui-components/digit_components/lib/digit_components.dart @@ -2,6 +2,9 @@ library digit_ui_components; export 'theme/theme.dart'; export 'widgets/widgets.dart'; +export 'enum/app_enums.dart'; +export 'models/models.dart'; +export 'constants/constant.dart'; class DigitUi { static const DigitUi _instance = DigitUi._internal(); diff --git a/flutter/digit-ui-components/digit_components/lib/enum/app_enums.dart b/flutter/digit-ui-components/digit_components/lib/enum/app_enums.dart index 9c81b9f093a..b7ca3503d54 100644 --- a/flutter/digit-ui-components/digit_components/lib/enum/app_enums.dart +++ b/flutter/digit-ui-components/digit_components/lib/enum/app_enums.dart @@ -6,27 +6,28 @@ enum ButtonType { link, } - -/// Enum representing different types of single select dropdowns. -enum DropdownType { - defaultSelect, - nestedSelect, +/// Enum representing the possible sizes of the button. +enum ButtonSize { + large, + medium, + small, } -/// Enum representing different types of multi select dropdowns. -enum SelectionType { - multiSelect, - nestedMultiSelect, +/// Enum representing the possible type of info buttons +enum InfoButtonType { + error, + info, + success, + warning, } /// Enum representing different types of multi select dropdowns. -enum TreeSelectionType { - singleSelect, - MultiSelect, +enum SelectionType { + defaultSelect, + nestedSelect, + treeSelect, } - - /// Enum representing the possible states of the DigitCheckbox. enum DigitCheckboxState { /// Represents an unchecked state. @@ -39,9 +40,54 @@ enum DigitCheckboxState { checked, } -// Enum representing the scroll for textArea +/// Enum representing the scroll for textArea enum TextAreaScroll{ vertical, smart, none, +} + +/// Enum representing toast types +enum ToastType { + success, + error, + warning, + info, +} + +/// dropdown type and subtype for dropdown wrapper +enum DropdownType { + singleSelect, + multiSelect, +} + +/// Enum to define different types of information for the InfoCard +enum InfoType { info, success, error, warning } + +/// Enum to define different state for timeline +enum TimelineStepState { completed, present, future } + +/// Enum representing different types of popup card - default and alert +enum PopUpType { + simple, + alert, +} + +/// Enum representing different type of divider( small, medium and large) +enum DividerType{ + small, + medium, + large, +} + +/// Enum representing different types of panel(success and error) +enum PanelType { + success, + error, +} + +/// Enum representing different types of card(primary and secondary) +enum CardType { + primary, + secondary, } \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/models/chipModel.dart b/flutter/digit-ui-components/digit_components/lib/models/chipModel.dart deleted file mode 100644 index c33e35cdd27..00000000000 --- a/flutter/digit-ui-components/digit_components/lib/models/chipModel.dart +++ /dev/null @@ -1,35 +0,0 @@ -import 'package:digit_ui_components/digit_components.dart'; -import 'package:flutter/material.dart'; -import '../constants/app_constants.dart'; - -class ChipConfig { - final Icon? deleteIcon; - // final Color deleteIconColor; - // final Color labelColor; - final Color? backgroundColor; - // final TextStyle? labelStyle; - final EdgeInsets padding; - final EdgeInsets labelPadding; - final double radius; - final double spacing; - final double runSpacing; - final Widget? separator; - final bool autoScroll; - - const ChipConfig({ - this.deleteIcon, - // this.deleteIconColor = Colors.paperPrimary, - this.backgroundColor, - this.padding = Default.defaultChipPadding, - this.radius = Default.defaultChipRadius, - this.spacing = kPadding, - this.runSpacing = kPadding, - this.separator, - // this.labelColor = Colors.paperPrimary, - // this.labelStyle, - this.labelPadding = EdgeInsets.zero, - this.autoScroll = false, - }); -} - - diff --git a/flutter/digit-ui-components/digit_components/lib/models/models.dart b/flutter/digit-ui-components/digit_components/lib/models/models.dart new file mode 100644 index 00000000000..60e3e505237 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/models/models.dart @@ -0,0 +1,4 @@ +export 'DropdownModels.dart'; +export 'RadioButtonModel.dart'; +export 'toggleButtonModel.dart'; +export 'TreeModel.dart'; \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/theme/ColorTheme/light_color_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/ColorTheme/light_color_theme.dart new file mode 100644 index 00000000000..8f7ea3d7715 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/ColorTheme/light_color_theme.dart @@ -0,0 +1,235 @@ +import 'package:flutter/material.dart'; + +class DigitColorTheme extends ThemeExtension { + const DigitColorTheme({ + this.alert = const Alert(), + this.text = const Text(), + this.paper = const Paper(), + this.generic = const Generic(), + this.primary = const Primary(), + }); + + final Alert alert; + final Text text; + final Paper paper; + final Generic generic; + final Primary primary; + + @override + DigitColorTheme copyWith({ + Alert? alert, + Text? text, + Paper? paper, + Generic? generic, + Primary? primary, + }) { + return DigitColorTheme( + alert: alert ?? this.alert, + text: text ?? this.text, + paper: paper ?? this.paper, + generic: generic ?? this.generic, + primary: primary ?? this.primary, + ); + } + + @override + DigitColorTheme lerp( + covariant ThemeExtension? other, double t) { + if (other is! DigitColorTheme) { + return this; + } + + return DigitColorTheme( + alert: Alert.lerp(alert, other.alert, t), + text: Text.lerp(text, other.text, t), + paper: Paper.lerp(paper, other.paper, t), + generic: Generic.lerp(generic, other.generic, t), + primary: Primary.lerp(primary, other.primary, t), + ); + } +} + +class Alert { + const Alert({ + this.error = const Color(0xFFB91900), + this.success = const Color(0xFF00703C), + this.info = const Color(0xFF0057BD), + this.warning = const Color(0xFFEA8D00), + this.errorBg = const Color(0xFFFFF5F4), + this.successBg = const Color(0xFFF1FFF8), + this.infoBg = const Color(0xFFDEEFFF), + this.warningBg = const Color(0xFFFFF9F0), + }); + + final Color error; + final Color success; + final Color info; + final Color warning; + final Color errorBg; + final Color successBg; + final Color infoBg; + final Color warningBg; + + Alert copyWith({ + Color? error, + Color? success, + Color? info, + Color? warning, + Color? errorBg, + Color? successBg, + Color? infoBg, + Color? warningBg, + }) { + return Alert( + error: error ?? this.error, + success: success ?? this.success, + info: info ?? this.info, + warning: warning ?? this.warning, + errorBg: errorBg ?? this.errorBg, + successBg: successBg ?? this.successBg, + infoBg: infoBg ?? this.infoBg, + warningBg: warningBg ?? this.warningBg, + ); + } + + static Alert lerp(Alert a, Alert b, double t) { + return Alert( + error: Color.lerp(a.error, b.error, t)!, + success: Color.lerp(a.success, b.success, t)!, + info: Color.lerp(a.info, b.info, t)!, + warning: Color.lerp(a.warning, b.warning, t)!, + errorBg: Color.lerp(a.errorBg, b.errorBg, t)!, + successBg: Color.lerp(a.successBg, b.successBg, t)!, + infoBg: Color.lerp(a.infoBg, b.infoBg, t)!, + warningBg: Color.lerp(a.warningBg, b.warningBg, t)!, + ); + } +} + +class Primary { + const Primary({ + this.primary1 = const Color(0xFFC84C0E), + this.primary2 = const Color(0xFF0B4B66), + this.primaryBg = const Color(0xFFFBEEE8), + }); + + final Color primary1; + final Color primary2; + final Color primaryBg; + + Primary copyWith({ + Color? primary1, + Color? primary2, + Color? primaryBg, + }) { + return Primary( + primary1: primary1 ?? this.primary1, + primary2: primary2 ?? this.primary2, + primaryBg: primaryBg ?? this.primaryBg, + ); + } + + static Primary lerp(Primary a, Primary b, double t) { + return Primary( + primary1: Color.lerp(a.primary1, b.primary1, t)!, + primary2: Color.lerp(a.primary2, b.primary2, t)!, + primaryBg: Color.lerp(a.primaryBg, b.primaryBg, t)!, + ); + } +} + +class Text { + const Text({ + this.primary = const Color(0xFF363636), + this.secondary = const Color(0xFF787878), + this.disabled = const Color(0xFFC5C5C5), + }); + + final Color primary; + final Color secondary; + final Color disabled; + + Text copyWith({ + Color? primary, + Color? secondary, + Color? disabled, + }) { + return Text( + primary: primary ?? this.primary, + secondary: secondary ?? this.secondary, + disabled: disabled ?? this.disabled, + ); + } + + static Text lerp(Text a, Text b, double t) { + return Text( + primary: Color.lerp(a.primary, b.primary, t)!, + secondary: Color.lerp(a.secondary, b.secondary, t)!, + disabled: Color.lerp(a.disabled, b.disabled, t)!, + ); + } +} + +class Paper { + const Paper({ + this.primary = const Color(0xFFFFFFFF), + this.secondary = const Color(0xFFFAFAFA), + }); + + final Color primary; + final Color secondary; + + Paper copyWith({ + Color? primary, + Color? secondary, + }) { + return Paper( + primary: primary ?? this.primary, + secondary: secondary ?? this.secondary, + ); + } + + static Paper lerp(Paper a, Paper b, double t) { + return Paper( + primary: Color.lerp(a.primary, b.primary, t)!, + secondary: Color.lerp(a.secondary, b.secondary, t)!, + ); + } +} + +class Generic { + const Generic({ + this.background = const Color(0xFFEEEEEE), + this.divider = const Color(0xFFD6D5D4), + this.inputBorder = const Color(0xFF505A5F), + this.transparent = const Color(0x00000000), + }); + + final Color background; + final Color divider; + final Color inputBorder; + final Color transparent; + + Generic copyWith({ + Color? background, + Color? divider, + Color? inputBorder, + Color? transparent, + }) { + return Generic( + background: background ?? this.background, + divider: divider ?? this.divider, + inputBorder: inputBorder ?? this.inputBorder, + transparent: transparent ?? this.transparent, + ); + } + + static Generic lerp(Generic a, Generic b, double t) { + return Generic( + background: Color.lerp(a.background, b.background, t)!, + divider: Color.lerp(a.divider, b.divider, t)!, + inputBorder: Color.lerp(a.inputBorder, b.inputBorder, t)!, + transparent: Color.lerp(a.transparent, b.transparent, t)!, + ); + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/action_card_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/action_card_theme.dart new file mode 100644 index 00000000000..b33bd251a97 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/action_card_theme.dart @@ -0,0 +1,86 @@ +import 'dart:ui'; +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:flutter/material.dart'; +import '../../constants/AppView.dart'; + +class DigitActionCardTheme extends ThemeExtension { + final double? width; + final double? height; + final double? spacing; + final Decoration? decoration; + final EdgeInsets? margin; + final EdgeInsets? padding; + + const DigitActionCardTheme({ + this.width, + this.height, + this.spacing, + this.decoration, + this.margin, + this.padding, + }); + + static DigitActionCardTheme defaultTheme(BuildContext context) { + final bool isMobile = AppView.isMobileView(MediaQuery.of(context).size); + final bool isTab = AppView.isTabletView(MediaQuery.of(context).size); + + final theme = Theme.of(context); + + return DigitActionCardTheme( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + color: theme.colorTheme.paper.primary, + boxShadow: [ + BoxShadow( + color: const Color(0xFF000000).withOpacity(.16), + offset: const Offset(0, 1), + spreadRadius: 0, + blurRadius: 2, + ), + ], + ), + padding: EdgeInsets.all(theme.spacerTheme.spacer6), + margin: isMobile ? const EdgeInsets.symmetric(horizontal: 16) : isTab ? const EdgeInsets.symmetric(horizontal: 100) : const EdgeInsets.symmetric(horizontal: 400), + spacing: 24, + ); + } + + @override + DigitActionCardTheme copyWith({ + BuildContext? context, + double? width, + double? height, + double? spacing, + Decoration? decoration, + EdgeInsets? margin, + EdgeInsets? padding, + }) { + /// Ensure context is provided and get default theme if context is not null + final defaultTheme = context != null ? DigitActionCardTheme.defaultTheme(context) : null; + + + + return DigitActionCardTheme( + width: width ?? this.width ?? defaultTheme?.width, + height: height ?? this.height ?? defaultTheme?.height, + spacing: spacing ?? this.spacing ?? defaultTheme?.spacing, + decoration: decoration ?? this.decoration ?? defaultTheme?.decoration, + margin: margin ?? this.margin ?? defaultTheme?.margin, + padding: padding ?? this.padding ?? defaultTheme?.padding, + ); + } + + @override + DigitActionCardTheme lerp(covariant ThemeExtension? other, double t) { + if (other is! DigitActionCardTheme) return this; + + return DigitActionCardTheme( + width: lerpDouble(width, other.width, t), + height: lerpDouble(height, other.height, t), + spacing: lerpDouble(spacing, other.spacing, t), + decoration: Decoration.lerp(decoration, other.decoration, t), + margin: EdgeInsets.lerp(margin, other.margin, t), + padding: EdgeInsets.lerp(padding, other.padding, t), + ); + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/back_button_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/back_button_theme.dart new file mode 100644 index 00000000000..438a60fdca9 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/back_button_theme.dart @@ -0,0 +1,96 @@ +import 'dart:math'; + +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:flutter/material.dart'; +import '../../constants/AppView.dart'; + +class BackNavigationButtonThemeData extends ThemeExtension{ + final Color? textColor; + final Color? disabledTextColor; + final EdgeInsets? contentPadding; + final Widget? backButtonIcon; + final Widget? disabledBackButtonIcon; + final TextStyle? textStyle; + + const BackNavigationButtonThemeData({ + this.textColor, + this.disabledTextColor, + this.contentPadding, + this.backButtonIcon, + this.disabledBackButtonIcon, + this.textStyle, + }); + + static BackNavigationButtonThemeData defaultTheme(BuildContext context) { + + final bool isMobile = AppView.isMobileView(MediaQuery.of(context).size); + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + + return BackNavigationButtonThemeData( + textColor: theme.colorTheme.primary.primary2, + disabledTextColor: theme.colorTheme.text.disabled, + contentPadding: EdgeInsets.zero, + textStyle: textTheme.bodyL, + backButtonIcon: Transform.rotate( + angle: pi, + alignment: Alignment.center, + child: Icon( + Icons.double_arrow, + size: isMobile ? theme.spacerTheme.spacer5 : theme.spacerTheme.spacer6, + color: theme.colorTheme.primary.primary2, + ), + ), + disabledBackButtonIcon: Transform.rotate( + angle: pi, + alignment: Alignment.center, + child: Icon( + Icons.double_arrow, + size: isMobile ? theme.spacerTheme.spacer5 : theme.spacerTheme.spacer6, + color: theme.colorTheme.text.disabled, + ), + ), + ); + } + + @override + BackNavigationButtonThemeData copyWith({ + BuildContext? context, + Color? textColor, + Color? disabledTextColor, + EdgeInsets? contentPadding, + Widget? backButtonIcon, + Widget? disabledBackButtonIcon, + TextStyle? textStyle, + + }) { + /// Ensure context is provided and get default theme if context is not null + final defaultTheme = context != null ? BackNavigationButtonThemeData.defaultTheme(context) : null; + + return BackNavigationButtonThemeData( + textColor: textColor ?? defaultTheme?.textColor ?? this.textColor, + disabledTextColor: disabledTextColor ?? defaultTheme?.disabledTextColor ?? this.disabledTextColor, + contentPadding: contentPadding ?? defaultTheme?.contentPadding ?? this.contentPadding, + backButtonIcon: backButtonIcon ?? defaultTheme?.backButtonIcon ?? this.backButtonIcon, + disabledBackButtonIcon: disabledBackButtonIcon ?? defaultTheme?.disabledBackButtonIcon ?? this.disabledBackButtonIcon, + textStyle: textStyle ?? defaultTheme?.textStyle ?? this.textStyle, + ); + } + + @override + BackNavigationButtonThemeData lerp(covariant ThemeExtension? other, double t) { + if (other is! BackNavigationButtonThemeData) { + return this; + } + + return BackNavigationButtonThemeData( + textColor: Color.lerp(textColor, other.textColor, t), + disabledTextColor: + Color.lerp(disabledTextColor, other.disabledTextColor, t), + contentPadding: EdgeInsets.lerp(contentPadding, other.contentPadding, t), + backButtonIcon: t < 0.5 ? backButtonIcon : other.backButtonIcon, + disabledBackButtonIcon: t < 0.5 ? disabledBackButtonIcon : other.disabledBackButtonIcon, + textStyle: TextStyle.lerp(textStyle, other.textStyle, t), + ); + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/bread_crumb_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/bread_crumb_theme.dart new file mode 100644 index 00000000000..eb775423956 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/bread_crumb_theme.dart @@ -0,0 +1,75 @@ +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:flutter/material.dart'; + +class BreadcrumbThemeData extends ThemeExtension { + final TextStyle? activeTextStyle; + final TextStyle? inactiveTextStyle; + final TextStyle? separatorTextStyle; + final String separatorText; + final EdgeInsets? itemPadding; + + const BreadcrumbThemeData({ + this.activeTextStyle, + this.inactiveTextStyle, + this.separatorTextStyle, + this.separatorText = '/', + this.itemPadding, + }); + + static BreadcrumbThemeData defaultTheme(BuildContext context) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + + return BreadcrumbThemeData( + activeTextStyle: textTheme.bodyS.copyWith( + color: theme.colorTheme.primary.primary1, + decoration: TextDecoration.none, + ), + inactiveTextStyle: textTheme.bodyS.copyWith( + color: theme.colorTheme.text.secondary, + decoration: TextDecoration.none, + ), + separatorTextStyle: textTheme.bodyS.copyWith( + color: theme.colorTheme.text.secondary, + decoration: TextDecoration.none, + ), + itemPadding: EdgeInsets.symmetric(horizontal: theme.spacerTheme.spacer1 ?? 0), + ); + } + + @override + BreadcrumbThemeData copyWith({ + TextStyle? activeTextStyle, + TextStyle? inactiveTextStyle, + TextStyle? separatorTextStyle, + EdgeInsets? itemPadding, + String? separatorText + }) { + return BreadcrumbThemeData( + activeTextStyle: activeTextStyle ?? this.activeTextStyle, + inactiveTextStyle: inactiveTextStyle ?? this.inactiveTextStyle, + separatorTextStyle: separatorTextStyle ?? this.separatorTextStyle, + itemPadding: itemPadding ?? this.itemPadding, + separatorText: separatorText ?? this.separatorText + ); + } + + @override + BreadcrumbThemeData lerp(covariant ThemeExtension? other, double t) { + if (other is! BreadcrumbThemeData) return this; + + return BreadcrumbThemeData( + activeTextStyle: TextStyle.lerp(activeTextStyle, other.activeTextStyle, t), + inactiveTextStyle: TextStyle.lerp(inactiveTextStyle, other.inactiveTextStyle, t), + separatorTextStyle: TextStyle.lerp(separatorTextStyle, other.separatorTextStyle, t), + itemPadding: EdgeInsets.lerp(itemPadding, other.itemPadding, t), + separatorText: _lerpString(separatorText, other.separatorText, t), + ); + + } + String _lerpString(String a, String b, double t) { + /// Interpolate between two strings `a` and `b` based on `t` + /// For simplicity, you can directly return one of the strings if `t` is 0 or 1 + return t < 0.5 ? a : b; + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/button_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/button_theme.dart new file mode 100644 index 00000000000..a3e82874e0e --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/button_theme.dart @@ -0,0 +1,319 @@ +import 'dart:ui'; +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:flutter/material.dart'; + +class DigitButtonThemeData extends ThemeExtension { + final TextStyle smallButtonTextStyle; + final TextStyle mediumButtonTextStyle; + final TextStyle largeButtonTextStyle; + final TextStyle smallLinkTextStyle; + final TextStyle mediumLinkTextStyle; + final TextStyle largeLinkTextStyle; + final double smallIconSize; + final double mediumIconSize; + final double largeIconSize; + final double smallLinkIconSize; + final double mediumLinkIconSize; + final double largeLinkIconSize; + final double smallButtonHeight; + final double mediumButtonHeight; + final double largeButtonHeight; + final double borderWidth; + final BorderRadius radius; + final EdgeInsets padding; + final EdgeInsets linkPadding; + final Color hightlightColor; + final Color splashColor; + final Color focusColor; + final Color hoverColor; + final Color disabledColor; + final Color primaryButtonColor; + final Color buttonColor; + final List buttonMouseDownBoxShadow; + final List buttonHoverBoxShadow; + final List primaryButtonMouseDownBoxShadow; + final List primaryButtonHoverBoxShadow; + + const DigitButtonThemeData({ + required this.smallButtonTextStyle, + required this.mediumButtonTextStyle, + required this.largeButtonTextStyle, + required this.smallLinkTextStyle, + required this.mediumLinkTextStyle, + required this.largeLinkTextStyle, + required this.smallIconSize, + required this.mediumIconSize, + required this.largeIconSize, + required this.smallLinkIconSize, + required this.mediumLinkIconSize, + required this.largeLinkIconSize, + required this.smallButtonHeight, + required this.mediumButtonHeight, + required this.largeButtonHeight, + required this.borderWidth, + required this.radius, + required this.padding, + required this.linkPadding, + required this.hoverColor, + required this.focusColor, + required this.hightlightColor, + required this.splashColor, + required this.buttonColor, + required this.disabledColor, + required this.primaryButtonColor, + required this.buttonHoverBoxShadow, + required this.buttonMouseDownBoxShadow, + required this.primaryButtonHoverBoxShadow, + required this.primaryButtonMouseDownBoxShadow, + }); + + static defaultTheme(BuildContext context) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + final buttonTheme = theme.digitButtonTextTheme; + + return DigitButtonThemeData( + smallButtonTextStyle: buttonTheme.buttonS, + mediumButtonTextStyle: buttonTheme.buttonM, + largeButtonTextStyle: buttonTheme.buttonL, + smallLinkTextStyle: textTheme.linkS, + mediumLinkTextStyle: textTheme.linkM, + largeLinkTextStyle: textTheme.linkL, + smallLinkIconSize: 14.0, + mediumLinkIconSize: 20.0, + largeLinkIconSize: 20.0, + smallIconSize: 14.0, + mediumIconSize: 20.0, + largeIconSize: 24.0, + smallButtonHeight: 24.0, + mediumButtonHeight: 32.0, + largeButtonHeight: 40.0, + borderWidth: 1.0, + radius: BorderRadius.zero, + padding: EdgeInsets.symmetric( + horizontal: theme.spacerTheme.spacer6, vertical: 0), + linkPadding: EdgeInsets.all(theme.spacerTheme.spacer2), + hoverColor: theme.colorTheme.generic.transparent, + focusColor: theme.colorTheme.generic.transparent, + hightlightColor: theme.colorTheme.generic.transparent, + splashColor: theme.colorTheme.generic.transparent, + buttonColor: theme.colorTheme.primary.primary1, + disabledColor: theme.colorTheme.text.disabled, + primaryButtonColor: theme.colorTheme.paper.primary, + buttonHoverBoxShadow: [ + BoxShadow( + color: theme.colorTheme.primary.primary1, + offset: const Offset(0, 2), + spreadRadius: 0, + blurRadius: 0, + ), + ], + buttonMouseDownBoxShadow: [ + BoxShadow( + color: theme.colorTheme.primary.primary1, + offset: const Offset(0, 2), + spreadRadius: 0, + blurRadius: 0, + ), + BoxShadow( + color: theme.colorTheme.primary.primary1.withOpacity(.20), + offset: const Offset(0, 4), + spreadRadius: 0, + blurRadius: 4, + ), + ], + primaryButtonHoverBoxShadow: [ + BoxShadow( + color: theme.colorTheme.text.primary, + offset: const Offset(0, 2), + spreadRadius: 0, + blurRadius: 0, + ), + ], + primaryButtonMouseDownBoxShadow: [ + BoxShadow( + color: theme.colorTheme.text.primary, + offset: const Offset(0, 2), + spreadRadius: 0, + blurRadius: 0, + ), + BoxShadow( + color: theme.colorTheme.text.primary.withOpacity(.25), + offset: const Offset(0, 4), + spreadRadius: 0, + blurRadius:2.8, + ), + ], + ); + } + + @override + DigitButtonThemeData copyWith({ + BuildContext? context, + TextStyle? smallButtonTextStyle, + TextStyle? mediumButtonTextStyle, + TextStyle? largeButtonTextStyle, + TextStyle? smallLinkTextStyle, + TextStyle? mediumLinkTextStyle, + TextStyle? largeLinkTextStyle, + double? smallLinkIconSize, + double? mediumLinkIconSize, + double? largeLinkIconSize, + double? smallIconSize, + double? mediumIconSize, + double? largeIconSize, + double? smallButtonHeight, + double? mediumButtonHeight, + double? largeButtonHeight, + double? borderWidth, + BorderRadius? radius, + EdgeInsets? padding, + EdgeInsets? linkPadding, + Color? hoverColor, + Color? focusColor, + Color? hightlightColor, + Color? splashColor, + Color? buttonColor, + Color? disabledColor, + Color? primaryButtonColor, + List? buttonHoverBoxShadow, + List? buttonMouseDownBoxShadow, + List? primaryButtonHoverBoxShadow, + List? primaryButtonMouseDownBoxShadow, + }) { + /// Ensure context is provided and get default theme if context is not null + final defaultTheme = + context != null ? DigitButtonThemeData.defaultTheme(context) : null; + + return DigitButtonThemeData( + smallButtonTextStyle: smallButtonTextStyle ?? + defaultTheme?.smallButtonTextStyle ?? + this.smallButtonTextStyle, + mediumButtonTextStyle: mediumButtonTextStyle ?? + defaultTheme?.mediumButtonTextStyle ?? + this.mediumButtonTextStyle, + largeButtonTextStyle: largeButtonTextStyle ?? + defaultTheme?.largeButtonTextStyle ?? + this.largeButtonTextStyle, + smallLinkTextStyle: smallLinkTextStyle ?? + defaultTheme?.smallLinkTextStyle ?? + this.smallLinkTextStyle, + mediumLinkTextStyle: mediumLinkTextStyle ?? + defaultTheme?.mediumLinkTextStyle ?? + this.mediumLinkTextStyle, + largeLinkTextStyle: largeLinkTextStyle ?? + defaultTheme?.largeLinkTextStyle ?? + this.largeLinkTextStyle, + smallIconSize: + smallIconSize ?? defaultTheme?.smallIconSize ?? this.smallIconSize, + mediumIconSize: + mediumIconSize ?? defaultTheme?.mediumIconSize ?? this.mediumIconSize, + largeIconSize: + largeIconSize ?? defaultTheme?.largeIconSize ?? this.largeIconSize, + smallLinkIconSize: smallLinkIconSize ?? + defaultTheme?.smallLinkIconSize ?? + this.smallLinkIconSize, + mediumLinkIconSize: mediumLinkIconSize ?? + defaultTheme?.mediumLinkIconSize ?? + this.mediumLinkIconSize, + largeLinkIconSize: largeLinkIconSize ?? + defaultTheme?.largeLinkIconSize ?? + this.largeLinkIconSize, + smallButtonHeight: smallButtonHeight ?? + defaultTheme?.smallButtonHeight ?? + this.smallButtonHeight, + mediumButtonHeight: mediumButtonHeight ?? + defaultTheme?.mediumButtonHeight ?? + this.mediumButtonHeight, + largeButtonHeight: largeButtonHeight ?? + defaultTheme?.largeButtonHeight ?? + this.largeButtonHeight, + borderWidth: borderWidth ?? defaultTheme?.borderWidth ?? this.borderWidth, + radius: radius ?? defaultTheme?.radius ?? this.radius, + padding: padding ?? defaultTheme?.padding ?? this.padding, + linkPadding: linkPadding ?? defaultTheme?.linkPadding ?? this.linkPadding, + hoverColor: hoverColor ?? defaultTheme?.hoverColor ?? this.hoverColor, + focusColor: focusColor ?? defaultTheme?.focusColor ?? this.focusColor, + hightlightColor: hightlightColor ?? + defaultTheme?.hightlightColor ?? + this.hightlightColor, + splashColor: splashColor ?? defaultTheme?.splashColor ?? this.splashColor, + buttonColor: buttonColor ?? defaultTheme?.buttonColor ?? this.buttonColor, + disabledColor: + disabledColor ?? defaultTheme?.disabledColor ?? this.disabledColor, + primaryButtonColor: primaryButtonColor ?? + defaultTheme?.primaryButtonColor ?? + this.primaryButtonColor, + buttonHoverBoxShadow: buttonHoverBoxShadow ?? + defaultTheme?.buttonHoverBoxShadow ?? + this.buttonHoverBoxShadow, + buttonMouseDownBoxShadow: buttonMouseDownBoxShadow ?? + defaultTheme?.buttonMouseDownBoxShadow ?? + this.buttonMouseDownBoxShadow, + primaryButtonHoverBoxShadow: primaryButtonHoverBoxShadow ?? + defaultTheme?.primaryButtonHoverBoxShadow ?? + this.primaryButtonHoverBoxShadow, + primaryButtonMouseDownBoxShadow: primaryButtonMouseDownBoxShadow ?? + defaultTheme?.primaryButtonMouseDownBoxShadow ?? + this.primaryButtonMouseDownBoxShadow, + ); + } + + @override + DigitButtonThemeData lerp( + ThemeExtension? other, double t) { + if (other is! DigitButtonThemeData) return this; + + return DigitButtonThemeData( + smallButtonTextStyle: + TextStyle.lerp(smallButtonTextStyle, other.smallButtonTextStyle, t)!, + mediumButtonTextStyle: TextStyle.lerp( + mediumButtonTextStyle, other.mediumButtonTextStyle, t)!, + largeButtonTextStyle: + TextStyle.lerp(largeButtonTextStyle, other.largeButtonTextStyle, t)!, + smallLinkTextStyle: + TextStyle.lerp(smallLinkTextStyle, other.smallLinkTextStyle, t)!, + mediumLinkTextStyle: + TextStyle.lerp(mediumLinkTextStyle, other.mediumLinkTextStyle, t)!, + largeLinkTextStyle: + TextStyle.lerp(largeLinkTextStyle, other.largeLinkTextStyle, t)!, + smallIconSize: lerpDouble(smallIconSize, other.smallIconSize, t)!, + mediumIconSize: lerpDouble(mediumIconSize, other.mediumIconSize, t)!, + largeIconSize: lerpDouble(largeIconSize, other.largeIconSize, t)!, + smallLinkIconSize: + lerpDouble(smallLinkIconSize, other.smallLinkIconSize, t)!, + mediumLinkIconSize: + lerpDouble(mediumLinkIconSize, other.mediumLinkIconSize, t)!, + largeLinkIconSize: + lerpDouble(largeLinkIconSize, other.largeLinkIconSize, t)!, + smallButtonHeight: + lerpDouble(smallButtonHeight, other.smallButtonHeight, t)!, + mediumButtonHeight: + lerpDouble(mediumButtonHeight, other.mediumButtonHeight, t)!, + largeButtonHeight: + lerpDouble(largeButtonHeight, other.largeButtonHeight, t)!, + borderWidth: lerpDouble(borderWidth, other.borderWidth, t)!, + radius: BorderRadius.lerp(radius, other.radius, t)!, + padding: EdgeInsets.lerp(padding, other.padding, t)!, + linkPadding: EdgeInsets.lerp(linkPadding, other.linkPadding, t)!, + hoverColor: Color.lerp(hoverColor, other.hoverColor, t)!, + focusColor: Color.lerp(focusColor, other.focusColor, t)!, + hightlightColor: Color.lerp(hightlightColor, other.hightlightColor, t)!, + splashColor: Color.lerp(splashColor, other.splashColor, t)!, + buttonColor: Color.lerp(buttonColor, other.buttonColor, t)!, + disabledColor: Color.lerp(disabledColor, other.disabledColor, t)!, + primaryButtonColor: + Color.lerp(primaryButtonColor, other.primaryButtonColor, t)!, + buttonHoverBoxShadow: + t < 0.5 ? buttonHoverBoxShadow : other.buttonHoverBoxShadow, + buttonMouseDownBoxShadow: + t < 0.5 ? buttonMouseDownBoxShadow : other.buttonMouseDownBoxShadow, + primaryButtonHoverBoxShadow: t < 0.5 + ? primaryButtonHoverBoxShadow + : other.primaryButtonHoverBoxShadow, + primaryButtonMouseDownBoxShadow: t < 0.5 + ? primaryButtonMouseDownBoxShadow + : other.primaryButtonMouseDownBoxShadow, + ); + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/checkbox_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/checkbox_theme.dart new file mode 100644 index 00000000000..667e495a72e --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/checkbox_theme.dart @@ -0,0 +1,110 @@ +import 'dart:ui'; +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:flutter/material.dart'; + +class DigitCheckboxThemeData extends ThemeExtension { + final TextStyle? labelTextStyle; + final TextDirection? labelTextDirection; + final TextStyle? disabledLabelTextStyle; + final Color? iconColor; + final Color? disabledIconColor; + final double? iconSize; + final double? borderWidth; + final double? focusBorderWidth; + final double? borderRadius; + final Color? selectedIconColor; + final EdgeInsetsGeometry? padding; + + const DigitCheckboxThemeData({ + this.labelTextStyle, + this.disabledLabelTextStyle, + this.labelTextDirection, + this.iconColor, + this.disabledIconColor, + this.padding, + this.iconSize, + this.borderRadius, + this.borderWidth, + this.focusBorderWidth, + this.selectedIconColor, + }); + + static DigitCheckboxThemeData defaultTheme(BuildContext context) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + + return DigitCheckboxThemeData( + labelTextStyle: textTheme.bodyL.copyWith( + color: theme.colorTheme.text.primary, + decoration: TextDecoration.none, + ), + disabledLabelTextStyle: textTheme.bodyL.copyWith( + color: theme.colorTheme.text.disabled, + decoration: TextDecoration.none, + ), + selectedIconColor: theme.colorTheme.primary.primary1, + iconColor: theme.colorTheme.text.primary, + disabledIconColor: theme.colorTheme.text.disabled, + padding: EdgeInsets.zero, + labelTextDirection: TextDirection.ltr, + iconSize: theme.spacerTheme.spacer6, + borderRadius: 0, + borderWidth: 1.0, + focusBorderWidth: 2.0, + ); + } + + @override + DigitCheckboxThemeData copyWith({ + BuildContext? context, + TextStyle? labelTextStyle, + TextStyle? disabledLabelTextStyle, + TextDirection? labelTextDirection, + Color? iconColor, + Color? disabledIconColor, + EdgeInsetsGeometry? padding, + double? iconSize, + double? borderRadius, + double? borderWidth, + Color? selectedIconColor, + double? focusBorderWidth, + }) { + + /// Ensure context is provided and get default theme if context is not null + final defaultTheme = context != null ? DigitCheckboxThemeData.defaultTheme(context) : null; + + + return DigitCheckboxThemeData( + labelTextStyle: labelTextStyle ?? this.labelTextStyle ?? defaultTheme?.labelTextStyle, + disabledLabelTextStyle: disabledLabelTextStyle ?? this.disabledLabelTextStyle ?? defaultTheme?.disabledLabelTextStyle, + labelTextDirection: labelTextDirection ?? this.labelTextDirection ?? defaultTheme?.labelTextDirection, + iconColor: iconColor ?? this.iconColor ?? defaultTheme?.iconColor, + disabledIconColor: disabledIconColor ?? this.disabledIconColor ?? defaultTheme?.disabledIconColor, + padding: padding ?? this.padding ?? defaultTheme?.padding, + selectedIconColor: selectedIconColor ?? this.selectedIconColor ?? defaultTheme?.selectedIconColor, + iconSize: iconSize ?? this.iconSize ?? defaultTheme?.iconSize, + borderRadius: borderRadius ?? this.borderRadius ?? defaultTheme?.borderRadius, + borderWidth: borderWidth ?? this.borderWidth ?? defaultTheme?.borderWidth, + focusBorderWidth: focusBorderWidth ?? this.focusBorderWidth ?? defaultTheme?.focusBorderWidth, + ); + } + + @override + DigitCheckboxThemeData lerp(covariant ThemeExtension? other, double t) { + if (other is! DigitCheckboxThemeData) return this; + + return DigitCheckboxThemeData( + labelTextStyle: TextStyle.lerp(labelTextStyle, other.labelTextStyle, t), + disabledLabelTextStyle: TextStyle.lerp(disabledLabelTextStyle, other.disabledLabelTextStyle, t), + labelTextDirection: t < 0.5 ? labelTextDirection : other.labelTextDirection, + iconColor: Color.lerp(iconColor, other.iconColor, t), + disabledIconColor: Color.lerp(disabledIconColor, other.disabledIconColor, t), + padding: EdgeInsetsGeometry.lerp(padding, other.padding, t), + iconSize: lerpDouble(iconSize, other.iconSize, t), + selectedIconColor: Color.lerp(selectedIconColor, other.selectedIconColor, t), + borderRadius: lerpDouble(borderRadius, other.borderRadius, t), + borderWidth: lerpDouble(borderWidth, other.borderWidth, t), + focusBorderWidth: lerpDouble(focusBorderWidth, other.focusBorderWidth, t), + ); + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/chip_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/chip_theme.dart new file mode 100644 index 00000000000..a30ffc4e4d6 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/chip_theme.dart @@ -0,0 +1,141 @@ +import 'dart:ui'; +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:flutter/material.dart'; +import '../../constants/AppView.dart'; + +class DigitChipThemeData extends ThemeExtension { + final TextStyle? labelTextStyle; + final TextStyle? labelErrorTextStyle; + final TextStyle? errorTextStyle; + final Color? backgroundColor; + final Color? errorBackgroundColor; + final Color? borderColor; + final Color? errorBorderColor; + final Color? iconColor; + final Color? errorIconColor; + final BoxShadow? errorBoxShadow; + final EdgeInsets? padding; + final double? borderRadius; + final double? borderWidth; + final Icon? cancelIcon; + final Icon? errorIcon; + + const DigitChipThemeData({ + this.labelTextStyle, + this.labelErrorTextStyle, + this.errorTextStyle, + this.backgroundColor, + this.errorBackgroundColor, + this.borderColor, + this.errorBorderColor, + this.iconColor, + this.errorIconColor, + this.errorBoxShadow, + this.padding, + this.borderWidth, + this.borderRadius, + this.errorIcon, + this.cancelIcon, + }); + + static DigitChipThemeData defaultTheme(BuildContext context) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + + bool isDesktop = AppView.isDesktopView(MediaQuery.of(context).size); + + return DigitChipThemeData( + labelTextStyle: textTheme.bodyXS.copyWith( + color: theme.colorTheme.text.primary, + overflow: TextOverflow.ellipsis, + ), + errorTextStyle: textTheme.bodyS.copyWith( + color: theme.colorTheme.alert.error, + ), + labelErrorTextStyle: textTheme.headingXS.copyWith( + color: theme.colorTheme.alert.error, + overflow: TextOverflow.ellipsis, + ), + backgroundColor: theme.colorTheme.generic.background, + errorBackgroundColor: theme.colorTheme.paper.primary, + borderColor: theme.colorTheme.generic.divider, + errorBorderColor: theme.colorTheme.alert.error, + iconColor: theme.colorTheme.text.secondary, + errorIconColor: theme.colorTheme.alert.error, + padding: EdgeInsets.symmetric(horizontal: theme.spacerTheme.spacer2 ?? 0, vertical: theme.spacerTheme.spacer2 ?? 0), + errorBoxShadow: BoxShadow( + color: theme.colorTheme.alert.error + .withOpacity(.15), + offset: const Offset(0, 2), + spreadRadius: 0, + blurRadius: 4, + ), + borderRadius: theme.spacerTheme.spacer1, + borderWidth: 1.0, + errorIcon: Icon( + Icons.info, + color: theme.colorTheme.alert.error, + size: theme.spacerTheme.spacer4, + ), + cancelIcon: Icon( + Icons.close, + size: isDesktop ? theme.spacerTheme.spacer6 : theme.spacerTheme.spacer5, + color: theme.colorTheme.paper.primary, + ), + ); + } + + @override + DigitChipThemeData copyWith({ + TextStyle? labelTextStyle, + TextStyle? labelErrorTextStyle, + TextStyle? errorTextStyle, + Color? backgroundColor, + Color? errorBackgroundColor, + Color? borderColor, + Color? errorBorderColor, + Color? iconColor, + Color? errorIconColor, + EdgeInsets? padding, + BoxShadow? errorBoxShadow, + double? borderRadius, + double? borderWidth, + }) { + return DigitChipThemeData( + labelTextStyle: labelTextStyle ?? this.labelTextStyle, + labelErrorTextStyle: labelErrorTextStyle ?? this.labelErrorTextStyle, + errorTextStyle: errorTextStyle ?? this.errorTextStyle, + backgroundColor: backgroundColor ?? this.backgroundColor, + errorBackgroundColor: errorBackgroundColor ?? this.errorBackgroundColor, + borderColor: borderColor ?? this.borderColor, + errorBorderColor: errorBorderColor ?? this.errorBorderColor, + iconColor: iconColor ?? this.iconColor, + errorIconColor: errorIconColor ?? this.errorIconColor, + padding: padding ?? this.padding, + errorBoxShadow: errorBoxShadow ?? this.errorBoxShadow, + borderRadius: borderRadius ?? this.borderRadius, + borderWidth: borderWidth ?? this.borderWidth, + ); + } + + @override + DigitChipThemeData lerp(covariant ThemeExtension? other, double t) { + if (other is! DigitChipThemeData) return this; + + return DigitChipThemeData( + labelTextStyle: TextStyle.lerp(labelTextStyle, other.labelTextStyle, t), + labelErrorTextStyle: TextStyle.lerp(labelErrorTextStyle, other.labelErrorTextStyle, t), + errorTextStyle: TextStyle.lerp(errorTextStyle, other.errorTextStyle, t), + backgroundColor: Color.lerp(backgroundColor, other.backgroundColor, t), + errorBackgroundColor: Color.lerp(errorBackgroundColor, other.errorBackgroundColor, t), + borderColor: Color.lerp(borderColor, other.borderColor, t), + errorBorderColor: Color.lerp(errorBorderColor, other.errorBorderColor, t), + iconColor: Color.lerp(iconColor, other.iconColor, t), + errorIconColor: Color.lerp(errorIconColor, other.errorIconColor, t), + padding: EdgeInsets.lerp(padding, other.padding, t), + errorBoxShadow: BoxShadow.lerp(errorBoxShadow, other.errorBoxShadow, t), + borderRadius: lerpDouble(borderRadius, other.borderRadius, t), + borderWidth: lerpDouble(borderWidth, other.borderWidth, t), + ); + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/digit_tab_bar_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/digit_tab_bar_theme.dart new file mode 100644 index 00000000000..c5593cb2e46 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/digit_tab_bar_theme.dart @@ -0,0 +1,102 @@ +import 'dart:ui'; + +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:flutter/material.dart'; + +class DigitTabBarThemeData extends ThemeExtension { + final Color? selectedTabColor; + final Color? unselectedTabColor; + final Color? borderColor; + final Color? selectedBorderColor; + final TextStyle? selectedTextStyle; + final TextStyle? unselectedTextStyle; + final double? tabHeight; + final double? selectedTabHeight; + final double? tabWidth; + final int? maxLine; + final EdgeInsets? padding; + + const DigitTabBarThemeData({ + this.selectedTabColor, + this.unselectedTabColor, + this.borderColor, + this.selectedBorderColor, + this.selectedTextStyle, + this.unselectedTextStyle, + this.tabHeight, + this.selectedTabHeight, + this.tabWidth, + this.maxLine, + this.padding, + }); + + static DigitTabBarThemeData defaultTheme(BuildContext context) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + + return DigitTabBarThemeData( + selectedTabColor: theme.colorTheme.paper.primary, + unselectedTabColor: theme.colorTheme.text.secondary, + borderColor: theme.colorTheme.generic.inputBorder, + selectedBorderColor: theme.colorTheme.primary.primary1, + selectedTextStyle: textTheme.headingS.copyWith( + color: theme.colorTheme.primary.primary1, + ), + unselectedTextStyle: textTheme.bodyS.copyWith( + color: theme.colorTheme.text.secondary, + ), + selectedTabHeight: 56.0, + tabHeight: 52.0, + maxLine: 1, + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 24), + ); + } + + @override + DigitTabBarThemeData copyWith({ + Color? selectedTabColor, + Color? unselectedTabColor, + Color? borderColor, + Color? selectedBorderColor, + TextStyle? selectedTextStyle, + TextStyle? unselectedTextStyle, + double? tabHeight, + double? selectedTabHeight, + double? tabWidth, + int? maxLine, + EdgeInsets? padding, + }) { + return DigitTabBarThemeData( + selectedTabColor: selectedTabColor ?? this.selectedTabColor, + unselectedTabColor: unselectedTabColor ?? this.unselectedTabColor, + borderColor: borderColor ?? this.borderColor, + selectedBorderColor: selectedBorderColor ?? this.selectedBorderColor, + selectedTextStyle: selectedTextStyle ?? this.selectedTextStyle, + unselectedTextStyle: unselectedTextStyle ?? this.unselectedTextStyle, + tabHeight: tabHeight ?? this.tabHeight, + selectedTabHeight: selectedTabHeight ?? this.selectedTabHeight, + tabWidth: tabWidth ?? this.tabWidth, + maxLine: maxLine ?? this.maxLine, + padding: padding ?? this.padding, + ); + } + + @override + DigitTabBarThemeData lerp(covariant ThemeExtension? other, double t) { + if (other is! DigitTabBarThemeData) return this; + + return DigitTabBarThemeData( + selectedTabColor: Color.lerp(selectedTabColor, other.selectedTabColor, t), + unselectedTabColor: Color.lerp(unselectedTabColor, other.unselectedTabColor, t), + borderColor: Color.lerp(borderColor, other.borderColor, t), + selectedBorderColor: Color.lerp(selectedBorderColor, other.selectedBorderColor, t), + selectedTextStyle: TextStyle.lerp(selectedTextStyle, other.selectedTextStyle, t), + unselectedTextStyle: TextStyle.lerp(unselectedTextStyle, other.unselectedTextStyle, t), + tabHeight: lerpDouble(tabHeight, other.tabHeight, t), + selectedTabHeight: lerpDouble(selectedTabHeight, other.selectedTabHeight, t), + tabWidth: lerpDouble(tabWidth, other.tabWidth, t), + maxLine: t<0.5 ? maxLine : other.maxLine, + padding: EdgeInsets.lerp(padding, other.padding, t), + ); + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/digit_tag_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/digit_tag_theme.dart new file mode 100644 index 00000000000..f6cf6909bca --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/digit_tag_theme.dart @@ -0,0 +1,147 @@ +import 'dart:ui'; + +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:flutter/material.dart'; + +class TagThemeData extends ThemeExtension { + final Color? successBackgroundColor; + final Color? successColor; + final Icon? successIcon; + + final Color? warningBackgroundColor; + final Color? warningColor; + final Icon? warningIcon; + + final Color? errorBackgroundColor; + final Color? errorColor; + final Icon? errorIcon; + final Color? monochromeColor; + final TextStyle? textStyle; + final EdgeInsets? padding; + final BorderRadius? borderRadius; + final double? borderWidth; + final double? tagWidth; + final int? maxLine; + + const TagThemeData({ + this.successBackgroundColor, + this.successColor, + this.successIcon, + this.warningBackgroundColor, + this.warningColor, + this.warningIcon, + this.errorBackgroundColor, + this.errorColor, + this.errorIcon, + this.monochromeColor, + this.textStyle, + this.padding, + this.borderRadius, + this.borderWidth, + this.tagWidth, + this.maxLine, + }); + + static TagThemeData defaultTheme(BuildContext context) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + + return TagThemeData( + successColor: theme.colorTheme.alert.success, + warningColor: theme.colorTheme.alert.warning, + errorColor: theme.colorTheme.alert.error, + monochromeColor: theme.colorTheme.primary.primary2, + textStyle: textTheme.bodyS, + successBackgroundColor: theme.colorTheme.alert.successBg, + warningBackgroundColor: theme.colorTheme.alert.warningBg, + errorBackgroundColor: theme.colorTheme.alert.errorBg, + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + borderRadius: BorderRadius.circular(4), + borderWidth: .5, + successIcon: Icon( + Icons.check_circle, + color: theme.colorTheme.alert.success, + size: 16, + ), + warningIcon: Icon( + Icons.warning, + color: theme.colorTheme.alert.warning, + size: 16, + ), + errorIcon: Icon( + Icons.error, + color: theme.colorTheme.alert.error, + size: 16, + ), + maxLine: 1, + ); + } + + @override + TagThemeData copyWith({ + Color? successBackgroundColor, + Color? successColor, + Icon? successIcon, + Color? warningBackgroundColor, + Color? warningColor, + Icon? warningIcon, + Color? errorBackgroundColor, + Color? errorColor, + Icon? errorIcon, + Color? monochromeColor, + TextStyle? textStyle, + EdgeInsets? padding, + BorderRadius? borderRadius, + double? borderWidth, + double? tagWidth, + int? maxLine, + }) { + return TagThemeData( + successBackgroundColor: + successBackgroundColor ?? this.successBackgroundColor, + successColor: successColor ?? this.successColor, + successIcon: successIcon ?? this.successIcon, + warningBackgroundColor: + warningBackgroundColor ?? this.warningBackgroundColor, + warningColor: warningColor ?? this.warningColor, + warningIcon: warningIcon ?? this.warningIcon, + errorBackgroundColor: errorBackgroundColor ?? this.errorBackgroundColor, + errorColor: errorColor ?? this.errorColor, + errorIcon: errorIcon ?? this.errorIcon, + monochromeColor: monochromeColor ?? this.monochromeColor, + textStyle: textStyle ?? this.textStyle, + padding: padding ?? this.padding, + borderRadius: borderRadius ?? this.borderRadius, + borderWidth: borderWidth ?? this.borderWidth, + tagWidth: tagWidth ?? this.tagWidth, + maxLine: maxLine ?? this.maxLine, + ); + } + + @override + TagThemeData lerp(ThemeExtension? other, double t) { + if (other is! TagThemeData) return this; + + return TagThemeData( + successBackgroundColor: + Color.lerp(successBackgroundColor, other.successBackgroundColor, t), + successColor: Color.lerp(successColor, other.successColor, t), + successIcon: t < 0.5 ? successIcon : other.successIcon, + warningBackgroundColor: + Color.lerp(warningBackgroundColor, other.warningBackgroundColor, t), + warningColor: Color.lerp(warningColor, other.warningColor, t), + warningIcon: t < 0.5 ? warningIcon : other.warningIcon, + errorBackgroundColor: + Color.lerp(errorBackgroundColor, other.errorBackgroundColor, t), + errorColor: Color.lerp(errorColor, other.errorColor, t), + errorIcon: t < 0.5 ? errorIcon : other.errorIcon, + monochromeColor: Color.lerp(monochromeColor, other.monochromeColor, t), + textStyle: TextStyle.lerp(textStyle, other.textStyle, t), + padding: EdgeInsets.lerp(padding, other.padding, t), + borderRadius: BorderRadius.lerp(borderRadius, other.borderRadius, t), + borderWidth: lerpDouble(borderWidth, other.borderWidth, t), + tagWidth: lerpDouble(tagWidth, other.tagWidth, t), + maxLine: t < 0.5 ? maxLine : other.maxLine, + ); + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/divider_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/divider_theme.dart new file mode 100644 index 00000000000..e00162f155a --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/divider_theme.dart @@ -0,0 +1,62 @@ +import 'dart:ui'; + +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:flutter/material.dart'; + +class DigitDividerThemeData extends ThemeExtension { + final double smallDividerThickness; + final double mediumDividerThickness; + final double largeDividerThickness; + final Color? color; + final double indent; + final double endIndent; + final double? width; + + const DigitDividerThemeData({ + this.smallDividerThickness = 1, + this.mediumDividerThickness = 2, + this.largeDividerThickness = 4, + this.color, + this.indent = 0.0, + this.endIndent = 0.0, + this.width, + }); + + + @override + DigitDividerThemeData copyWith({ + double? smallDividerThickness, + double? mediumDividerThickness, + double? largeDividerThickness, + Color? color, + double? indent, + double? endIndent, + double? width, + }) { + return DigitDividerThemeData( + smallDividerThickness: smallDividerThickness ?? this.smallDividerThickness, + mediumDividerThickness: mediumDividerThickness ?? this.mediumDividerThickness, + largeDividerThickness: largeDividerThickness ?? this.largeDividerThickness, + color: color ?? this.color, + indent: indent ?? this.indent, + endIndent: endIndent ?? this.endIndent, + width: width ?? this.width, + ); + } + + @override + DigitDividerThemeData lerp(covariant ThemeExtension? other, double t) { + if (other is! DigitDividerThemeData) return this; + + return DigitDividerThemeData( + smallDividerThickness: lerpDouble(smallDividerThickness, other.smallDividerThickness, t)!, + mediumDividerThickness: lerpDouble(mediumDividerThickness, other.mediumDividerThickness, t)!, + largeDividerThickness: lerpDouble(largeDividerThickness, other.largeDividerThickness, t)!, + color: Color.lerp(color, other.color, t), + indent: lerpDouble(indent, other.indent, t) ?? 0.0, + endIndent: lerpDouble(endIndent, other.endIndent, t) ?? 0.0, + width: lerpDouble(width, other.width, t), + ); + } +} + diff --git a/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/info_card_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/info_card_theme.dart new file mode 100644 index 00000000000..fc575dcba66 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/info_card_theme.dart @@ -0,0 +1,147 @@ +import 'dart:ui'; + +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:flutter/material.dart'; + +class DigitInfoCardThemeData extends ThemeExtension { + final TextStyle titleTextStyle; + final TextStyle descriptionTextStyle; + final IconData successIcon; + final IconData errorIcon; + final IconData warningIcon; + final IconData infoIcon; + final double iconSize; + final Color successColor; + final Color errorColor; + final Color warningColor; + final Color infoColor; + final double borderWidth; + final BorderRadius borderRadius; + final Color successBackgroundColor; + final Color errorBackgroundColor; + final Color warningBackgroundColor; + final Color infoBackgroundColor; + final EdgeInsets contentPadding; + + const DigitInfoCardThemeData({ + required this.titleTextStyle, + required this.descriptionTextStyle, + required this.successColor, + required this.errorColor, + required this.warningColor, + required this.infoColor, + required this.iconSize, + required this.successIcon, + required this.errorIcon, + required this.warningIcon, + required this.infoIcon, + required this.borderWidth, + required this.borderRadius, + required this.successBackgroundColor, + required this.errorBackgroundColor, + required this.warningBackgroundColor, + required this.infoBackgroundColor, + required this.contentPadding, + }); + + static DigitInfoCardThemeData defaultTheme(BuildContext context) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + + return DigitInfoCardThemeData( + titleTextStyle: textTheme.headingS, + descriptionTextStyle: textTheme.bodyS, + successColor: theme.colorTheme.alert.success, + errorColor: theme.colorTheme.alert.error, + warningColor: theme.colorTheme.alert.warning, + infoColor: theme.colorTheme.alert.info, + iconSize: theme.spacerTheme.spacer6, + successIcon: Icons.check_circle, + errorIcon: Icons.error, + infoIcon: Icons.info, + warningIcon: Icons.warning, + borderWidth: 1.0, + borderRadius: BorderRadius.zero, + successBackgroundColor: theme.colorTheme.alert.successBg, + errorBackgroundColor: theme.colorTheme.alert.errorBg, + warningBackgroundColor: theme.colorTheme.alert.warningBg, + infoBackgroundColor: theme.colorTheme.alert.infoBg, + contentPadding: EdgeInsets.all(theme.spacerTheme.spacer4), + ); + } + + @override + DigitInfoCardThemeData copyWith({ + BuildContext? context, + TextStyle? titleTextStyle, + TextStyle? descriptionTextStyle, + Color? successColor, + Color? errorColor, + Color? warningColor, + Color? infoColor, + IconData? successIcon, + IconData? errorIcon, + IconData? warningIcon, + IconData? infoIcon, + double? iconSize, + double? borderWidth, + BorderRadius? borderRadius, + Color? successBackgroundColor, + Color? errorBackgroundColor, + Color? warningBackgroundColor, + Color? infoBackgroundColor, + EdgeInsets? contentPadding, + }) { + + /// Ensure context is provided and get default theme if context is not null + final defaultTheme = context != null ? DigitInfoCardThemeData.defaultTheme(context) : null; + + return DigitInfoCardThemeData( + titleTextStyle: titleTextStyle ?? defaultTheme?.titleTextStyle ?? this.titleTextStyle, + descriptionTextStyle: descriptionTextStyle ?? defaultTheme?.descriptionTextStyle ?? this.descriptionTextStyle, + successColor: successColor ?? defaultTheme?.successColor ?? this.successColor, + errorColor: errorColor ?? defaultTheme?.errorColor ?? this.errorColor, + warningColor: warningColor ?? defaultTheme?.warningColor ?? this.warningColor, + infoColor: infoColor ?? defaultTheme?.infoColor ?? this.infoColor, + iconSize: iconSize ?? defaultTheme?.iconSize ?? this.iconSize, + successIcon: successIcon ?? defaultTheme?.successIcon ?? this.successIcon, + errorIcon: errorIcon ?? defaultTheme?.errorIcon ?? this.errorIcon, + warningIcon: warningIcon ?? defaultTheme?.warningIcon ?? this.warningIcon, + infoIcon: infoIcon ?? defaultTheme?.infoIcon ?? this.infoIcon, + borderWidth: borderWidth ?? defaultTheme?.borderWidth ?? this.borderWidth, + borderRadius: borderRadius ?? defaultTheme?.borderRadius ?? this.borderRadius, + successBackgroundColor: successBackgroundColor ?? defaultTheme?.successBackgroundColor ?? this.successBackgroundColor, + errorBackgroundColor: errorBackgroundColor ?? defaultTheme?.errorBackgroundColor ?? this.errorBackgroundColor, + warningBackgroundColor: warningBackgroundColor ?? defaultTheme?.warningBackgroundColor ?? this.warningBackgroundColor, + infoBackgroundColor: infoBackgroundColor ?? defaultTheme?.infoBackgroundColor ?? this.infoBackgroundColor, + contentPadding: contentPadding ?? defaultTheme?.contentPadding ?? this.contentPadding, + ); + } + + @override + DigitInfoCardThemeData lerp(covariant ThemeExtension? other, double t) { + if (other is! DigitInfoCardThemeData) return this; + + return DigitInfoCardThemeData( + titleTextStyle: TextStyle.lerp(titleTextStyle, other.titleTextStyle, t)!, + descriptionTextStyle: TextStyle.lerp(descriptionTextStyle, other.descriptionTextStyle, t)!, + successColor: Color.lerp(successColor, other.successColor, t)!, + errorColor: Color.lerp(errorColor, other.errorColor, t)!, + warningColor: Color.lerp(warningColor, other.warningColor, t)!, + infoColor: Color.lerp(infoColor, other.infoColor, t)!, + iconSize: lerpDouble(iconSize, other.iconSize, t)!, + successIcon: t < 0.5 ? successIcon : other.successIcon, + errorIcon: t < 0.5 ? errorIcon : other.errorIcon, + warningIcon: t < 0.5 ? warningIcon : other.warningIcon, + infoIcon: t < 0.5 ? infoIcon : other.infoIcon, + borderWidth: lerpDouble(borderWidth, other.borderWidth, t)!, + borderRadius: BorderRadius.lerp(borderRadius, other.borderRadius, t)!, + successBackgroundColor: Color.lerp(successBackgroundColor, other.successBackgroundColor, t)!, + errorBackgroundColor: Color.lerp(errorBackgroundColor, other.errorBackgroundColor, t)!, + warningBackgroundColor: Color.lerp(warningBackgroundColor, other.warningBackgroundColor, t)!, + infoBackgroundColor: Color.lerp(infoBackgroundColor, other.infoBackgroundColor, t)!, + contentPadding: EdgeInsets.lerp(contentPadding, other.contentPadding, t)!, + ); + } +} + diff --git a/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/panel_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/panel_theme.dart new file mode 100644 index 00000000000..c07b412d3f9 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/panel_theme.dart @@ -0,0 +1,109 @@ +import 'dart:ui'; +import 'package:flutter/material.dart'; +import '../../constants/AppView.dart'; +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; + +class PanelThemeData extends ThemeExtension { + final TextStyle titleTextStyle; + final Color successBackgroundColor; + final Color errorBackgroundColor; + final BorderRadiusGeometry radiusGeometry; + final double successAnimationSize; + final double errorAnimationSize; + final EdgeInsets successPadding; + final EdgeInsets errorPadding; + final double cardWidth; + final String successJson; + final String errorJson; + + const PanelThemeData({ + required this.titleTextStyle, + required this.successBackgroundColor, + required this.errorBackgroundColor, + required this.radiusGeometry, + required this.successAnimationSize, + required this.errorAnimationSize, + required this.successPadding, + required this.errorPadding, + required this.cardWidth, + required this.successJson, + required this.errorJson, + }); + + static PanelThemeData defaultTheme(BuildContext context) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + bool isMobile = AppView.isMobileView(MediaQuery.of(context).size); + bool isTab = AppView.isTabletView(MediaQuery.of(context).size); + + return PanelThemeData( + titleTextStyle: textTheme.headingXl.copyWith(color: theme.colorTheme.paper.primary), + successBackgroundColor: theme.colorTheme.alert.success, + errorBackgroundColor: theme.colorTheme.alert.error, + radiusGeometry: BorderRadius.zero, + successAnimationSize: isMobile ? 80.0 : isTab ? 100.0 : 120.0, + errorAnimationSize: isMobile ? 56.0 : isTab ? 64.0 : 74.0, + successPadding: EdgeInsets.only( + top: isTab || isMobile ? 22 : 18, + left: theme.spacerTheme.spacer10, + right: theme.spacerTheme.spacer10, + bottom: theme.spacerTheme.spacer10,), + errorPadding: EdgeInsets.all(isMobile ? theme.spacerTheme.spacer8 : theme.spacerTheme.spacer10), + cardWidth: MediaQuery.of(context).size.width, + successJson: 'assets/animated_json/success.json', + errorJson: 'assets/animated_json/error.json', + ); + } + + @override + PanelThemeData copyWith({ + BuildContext? context, + TextStyle? titleTextStyle, + Color? successBackgroundColor, + Color? errorBackgroundColor, + BorderRadiusGeometry? radiusGeometry, + double? successAnimationSize, + double? errorAnimationSize, + EdgeInsets? successPadding, + EdgeInsets? errorPadding, + double? cardWidth, + String? successJson, + String? errorJson, + }) { + /// Ensure context is provided and get default theme if context is not null + final defaultTheme = context != null ? PanelThemeData.defaultTheme(context) : null; + + return PanelThemeData( + titleTextStyle: titleTextStyle ?? defaultTheme?.titleTextStyle ?? this.titleTextStyle, + successBackgroundColor: successBackgroundColor ?? defaultTheme?.successBackgroundColor ?? this.successBackgroundColor, + errorBackgroundColor: errorBackgroundColor ?? defaultTheme?.errorBackgroundColor ?? this.errorBackgroundColor, + radiusGeometry: radiusGeometry ?? defaultTheme?.radiusGeometry ?? this.radiusGeometry, + successAnimationSize: successAnimationSize ?? defaultTheme?.successAnimationSize ?? this.successAnimationSize, + errorAnimationSize: errorAnimationSize ?? defaultTheme?.errorAnimationSize ?? this.errorAnimationSize, + successPadding: successPadding ?? defaultTheme?.successPadding ?? this.successPadding, + errorPadding: errorPadding ?? defaultTheme?.errorPadding ?? this.errorPadding, + cardWidth: cardWidth ?? defaultTheme?.cardWidth ?? this.cardWidth, + successJson: successJson ?? defaultTheme?.successJson ?? this.successJson, + errorJson: errorJson ?? defaultTheme?.errorJson ?? this.errorJson, + ); + } + + @override + PanelThemeData lerp(ThemeExtension? other, double t) { + if (other is! PanelThemeData) return this; + + return PanelThemeData( + titleTextStyle: TextStyle.lerp(titleTextStyle, other.titleTextStyle, t)!, + successBackgroundColor: Color.lerp(successBackgroundColor, other.successBackgroundColor, t)!, + errorBackgroundColor: Color.lerp(errorBackgroundColor, other.errorBackgroundColor, t)!, + radiusGeometry: BorderRadiusGeometry.lerp(radiusGeometry, other.radiusGeometry, t)!, + successAnimationSize: lerpDouble(successAnimationSize, other.successAnimationSize, t)!, + errorAnimationSize: lerpDouble(errorAnimationSize, other.errorAnimationSize, t)!, + successPadding: EdgeInsets.lerp(successPadding, other.successPadding, t)!, + errorPadding: EdgeInsets.lerp(errorPadding, other.errorPadding, t)!, + cardWidth: lerpDouble(cardWidth, other.cardWidth, t)!, + successJson: t< 0.5 ? successJson : other.successJson, + errorJson: t < 0.5 ? errorJson : other.errorJson, + ); + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/pop_up_card_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/pop_up_card_theme.dart new file mode 100644 index 00000000000..8b6d3b41fd8 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/pop_up_card_theme.dart @@ -0,0 +1,112 @@ +import 'dart:ui'; +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:flutter/material.dart'; +import '../../constants/AppView.dart'; + +class DigitPopupTheme extends ThemeExtension { + final double? width; + final double? height; + final Decoration? decoration; + final EdgeInsets? padding; + final String? alertAnimation; + final TextStyle? titleTextStyle; + final TextStyle? subHeadingTextStyle; + final TextStyle? descriptionTextStyle; + final double? iconSize; + final EdgeInsets? margin; + + const DigitPopupTheme({ + this.width, + this.height, + this.decoration, + this.padding, + this.titleTextStyle, + this.subHeadingTextStyle, + this.descriptionTextStyle, + this.iconSize, + this.alertAnimation, + this.margin, + }); + + static DigitPopupTheme defaultTheme(BuildContext context) { + final bool isMobile = AppView.isMobileView(MediaQuery.of(context).size); + final bool isTab = AppView.isTabletView(MediaQuery.of(context).size); + + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + + return DigitPopupTheme( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(theme.spacerTheme.spacer1), + color: theme.colorTheme.paper.primary, + boxShadow: [ + BoxShadow( + color: const Color(0xFF000000).withOpacity(.16), + offset: const Offset(0, 1), + spreadRadius: 0, + blurRadius: 2, + ), + ], + ), + margin: isMobile ? const EdgeInsets.symmetric(horizontal: 16) : isTab ? const EdgeInsets.symmetric(horizontal: 100) : const EdgeInsets.symmetric(horizontal: 400), + padding: EdgeInsets.all(isMobile ? 16 : isTab ? 20 : 24), + titleTextStyle: textTheme.headingL.copyWith( + color: theme.colorTheme.text.primary), + subHeadingTextStyle: textTheme.captionS.copyWith( + color: theme.colorTheme.text.primary), + descriptionTextStyle: textTheme.bodyL.copyWith( + color: theme.colorTheme.text.primary, + ), + iconSize: isMobile ? 24.0 : isTab ? 28.0 : 32.0, + alertAnimation: 'assets/animated_json/alert.json', + ); + } + + @override + DigitPopupTheme copyWith({ + BuildContext? context, + double? width, + double? height, + Decoration? decoration, + EdgeInsets? padding, + TextStyle? titleTextStyle, + TextStyle? subHeadingTextStyle, + TextStyle? descriptionTextStyle, + double? iconSize, + String? alertAnimation, + EdgeInsets? margin, + }) { + final defaultTheme = context != null ? DigitPopupTheme.defaultTheme(context) : null; + + return DigitPopupTheme( + width: width ?? defaultTheme?.width ?? this.width, + height: height ?? defaultTheme?.height ?? this.height, + decoration: decoration ?? defaultTheme?.decoration ?? this.decoration, + padding: padding ?? defaultTheme?.padding ?? this.padding, + titleTextStyle: titleTextStyle ?? defaultTheme?.titleTextStyle ?? this.titleTextStyle, + subHeadingTextStyle: subHeadingTextStyle ?? defaultTheme?.subHeadingTextStyle ?? this.subHeadingTextStyle, + descriptionTextStyle: descriptionTextStyle ?? defaultTheme?.descriptionTextStyle ?? this.descriptionTextStyle, + iconSize: iconSize ?? defaultTheme?.iconSize ?? this.iconSize, + alertAnimation: alertAnimation ?? defaultTheme?.alertAnimation ?? this.alertAnimation, + margin: margin ?? defaultTheme?.margin ?? this.margin, + ); + } + + @override + DigitPopupTheme lerp(covariant ThemeExtension? other, double t) { + if (other is! DigitPopupTheme) return this; + + return DigitPopupTheme( + width: lerpDouble(width, other.width, t), + height: lerpDouble(height, other.height, t), + decoration: Decoration.lerp(decoration, other.decoration, t), + padding: EdgeInsets.lerp(padding, other.padding, t), + titleTextStyle: TextStyle.lerp(titleTextStyle, other.titleTextStyle, t), + subHeadingTextStyle: TextStyle.lerp(subHeadingTextStyle, other.subHeadingTextStyle, t), + descriptionTextStyle: TextStyle.lerp(descriptionTextStyle, other.descriptionTextStyle, t), + iconSize: lerpDouble(iconSize, other.iconSize, t), + alertAnimation: t<0.5 ? alertAnimation : other.alertAnimation, + margin: EdgeInsets.lerp(margin, other.margin, t), + ); + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/radio_list_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/radio_list_theme.dart new file mode 100644 index 00000000000..c734b71f210 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/radio_list_theme.dart @@ -0,0 +1,81 @@ +import 'dart:ui'; + +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:flutter/material.dart'; + +class DigitRadioListThemeData extends ThemeExtension { + final TextStyle textStyle; + final Color selectedColor; + final Color unselectedColor; + final Color hoverColor; + final Color disabledColor; + final EdgeInsets containerPadding; + final double radioWidth; + final double radioHeight; + + const DigitRadioListThemeData({ + required this.textStyle, + required this.selectedColor, + required this.unselectedColor, + required this.hoverColor, + required this.disabledColor, + required this.containerPadding, + required this.radioWidth, + required this.radioHeight, + }); + + static DigitRadioListThemeData defaultTheme(BuildContext context) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + + return DigitRadioListThemeData( + textStyle: textTheme.bodyL, + selectedColor: theme.colorTheme.primary.primary1, + unselectedColor: theme.colorTheme.text.disabled, + hoverColor: Colors.lightBlue, + disabledColor: Colors.grey.shade400, + containerPadding: EdgeInsets.all(theme.spacerTheme.spacer2), + radioWidth: theme.spacerTheme.spacer6, + radioHeight: theme.spacerTheme.spacer6, + ); + } + + @override + DigitRadioListThemeData copyWith({ + TextStyle? textStyle, + Color? selectedColor, + Color? unselectedColor, + Color? hoverColor, + Color? disabledColor, + EdgeInsets? containerPadding, + double? radioWidth, + double? radioHeight, + }) { + return DigitRadioListThemeData( + textStyle: textStyle ?? this.textStyle, + selectedColor: selectedColor ?? this.selectedColor, + unselectedColor: unselectedColor ?? this.unselectedColor, + hoverColor: hoverColor ?? this.hoverColor, + disabledColor: disabledColor ?? this.disabledColor, + containerPadding: containerPadding ?? this.containerPadding, + radioWidth: radioWidth ?? this.radioWidth, + radioHeight: radioHeight ?? this.radioHeight, + ); + } + + @override + DigitRadioListThemeData lerp(ThemeExtension? other, double t) { + if (other is! DigitRadioListThemeData) return this; + + return DigitRadioListThemeData( + textStyle: TextStyle.lerp(textStyle, other.textStyle, t)!, + selectedColor: Color.lerp(selectedColor, other.selectedColor, t)!, + unselectedColor: Color.lerp(unselectedColor, other.unselectedColor, t)!, + hoverColor: Color.lerp(hoverColor, other.hoverColor, t)!, + disabledColor: Color.lerp(disabledColor, other.disabledColor, t)!, + containerPadding: EdgeInsets.lerp(containerPadding, other.containerPadding, t)!, + radioWidth: lerpDouble(radioWidth, other.radioWidth, t)!, + radioHeight: lerpDouble(radioHeight, other.radioHeight, t)!, + ); + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/switch_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/switch_theme.dart new file mode 100644 index 00000000000..85e973c7296 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/switch_theme.dart @@ -0,0 +1,89 @@ +import 'dart:ui'; + +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:flutter/material.dart'; + +class DigitSwitchThemeData extends ThemeExtension { + final Color? activeColor; + final Color? inactiveColor; + final Color? symbolColor; + final TextStyle? labelTextStyle; + final double? thumbSize; + final double? trackHeight; + final double? trackWidth; + final EdgeInsets? padding; + final int? animationValue; + + const DigitSwitchThemeData({ + this.activeColor, + this.inactiveColor, + this.symbolColor, + this.labelTextStyle, + this.thumbSize, + this.trackHeight, + this.trackWidth, + this.padding, + this.animationValue, + }); + + static DigitSwitchThemeData defaultTheme(BuildContext context) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + + return DigitSwitchThemeData( + activeColor: theme.colorTheme.primary.primary1, + inactiveColor: theme.colorTheme.text.disabled, + symbolColor: theme.colorTheme.paper.primary, + labelTextStyle: textTheme.bodyS.copyWith( + color: theme.colorTheme.text.primary, + ), + thumbSize: 18.0, + trackHeight: 22.0, + trackWidth: 44, + padding: const EdgeInsets.all(2), + animationValue: 21, + ); + } + + @override + DigitSwitchThemeData copyWith({ + Color? activeColor, + Color? inactiveColor, + Color? symbolColor, + TextStyle? labelTextStyle, + double? thumbSize, + double? trackHeight, + double? trackWidth, + EdgeInsets? padding, + int? animationValue, + }) { + return DigitSwitchThemeData( + activeColor: activeColor ?? this.activeColor, + inactiveColor: inactiveColor ?? this.inactiveColor, + symbolColor: symbolColor ?? this.symbolColor, + labelTextStyle: labelTextStyle ?? this.labelTextStyle, + thumbSize: thumbSize ?? this.thumbSize, + trackHeight: trackHeight ?? this.trackHeight, + trackWidth: trackWidth ?? this.trackWidth, + padding: padding ?? this.padding, + animationValue: animationValue ?? this.animationValue, + ); + } + + @override + DigitSwitchThemeData lerp(covariant ThemeExtension? other, double t) { + if (other is! DigitSwitchThemeData) return this; + + return DigitSwitchThemeData( + activeColor: Color.lerp(activeColor, other.activeColor, t), + inactiveColor: Color.lerp(inactiveColor, other.inactiveColor, t), + symbolColor: Color.lerp(symbolColor, other.symbolColor, t), + labelTextStyle: TextStyle.lerp(labelTextStyle, other.labelTextStyle, t), + thumbSize: lerpDouble(thumbSize, other.thumbSize, t), + trackHeight: lerpDouble(trackHeight, other.trackHeight, t), + trackWidth: lerpDouble(trackWidth, other.trackWidth, t), + padding: EdgeInsets.lerp(padding, other.padding, t), + animationValue:t < 0.5 ? animationValue : other.animationValue, + ); + } +} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/toast_theme_data.dart b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/toast_theme_data.dart new file mode 100644 index 00000000000..070cb5ed57e --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/ComponentTheme/toast_theme_data.dart @@ -0,0 +1,153 @@ +import 'dart:ui'; + +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_styled_toast/flutter_styled_toast.dart'; + +import '../../constants/AppView.dart'; + +class DigitToastThemeData extends ThemeExtension { + final TextStyle? textStyle; + final Color? successColor; + final Color? errorColor; + final Color? warningColor; + final Color? infoColor; + final Icon? successIcon; + final Icon? errorIcon; + final Icon? warningIcon; + final Icon? infoIcon; + final Icon? cancelIcon; + final double? toastWidth; + final int? maxLine; + final EdgeInsets? padding; + final Duration? animationDuration; + final StyledToastAnimation? animation; + final StyledToastAnimation? reverseAnimation; + final StyledToastPosition? toastPosition; + + const DigitToastThemeData({ + this.textStyle, + this.successColor, + this.errorColor, + this.warningColor, + this.infoColor, + this.successIcon, + this.errorIcon, + this.warningIcon, + this.infoIcon, + this.cancelIcon, + this.toastWidth, + this.padding, + this.maxLine, + this.animationDuration, + this.animation, + this.reverseAnimation, + this.toastPosition, + }); + + static DigitToastThemeData defaultTheme(BuildContext context) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + + double width = AppView.isMobileView(MediaQuery.of(context).size) + ? MediaQuery.of(context).size.width + : AppView.isTabletView(MediaQuery.of(context).size) + ? 480 + : 800; + + return DigitToastThemeData( + textStyle: textTheme.captionS.copyWith( + color: theme.colorTheme.paper.primary, + ), + successColor: theme.colorTheme.alert.success, + errorColor: theme.colorTheme.alert.error, + warningColor: theme.colorTheme.alert.warning, + infoColor: theme.colorTheme.alert.info, + successIcon: Icon( + Icons.check_circle, + color: theme.colorTheme.paper.primary, + size: theme.spacerTheme.spacer6, + ), + errorIcon: Icon(Icons.error, color: theme.colorTheme.paper.primary, size: theme.spacerTheme.spacer6,), + warningIcon: Icon(Icons.warning, color: theme.colorTheme.paper.primary, size: theme.spacerTheme.spacer6,), + infoIcon: Icon(Icons.info, color: theme.colorTheme.paper.primary, size: theme.spacerTheme.spacer6,), + cancelIcon: Icon(Icons.close, color: theme.colorTheme.paper.primary, size: theme.spacerTheme.spacer6,), + toastWidth: width, + maxLine: 1, + padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 8), + animationDuration: const Duration(seconds: 5), + animation: StyledToastAnimation.slideFromBottom, + reverseAnimation: StyledToastAnimation.slideToBottom, + toastPosition: const StyledToastPosition( + align: Alignment.bottomCenter, + ), + ); + } + + @override + DigitToastThemeData copyWith({ + TextStyle? textStyle, + Color? successColor, + Color? errorColor, + Color? warningColor, + Color? infoColor, + Icon? successIcon, + Icon? errorIcon, + Icon? warningIcon, + Icon? infoIcon, + Icon? cancelIcon, + double? toastWidth, + int? maxLine, + EdgeInsets? padding, + Duration? animationDuration, + StyledToastAnimation? animation, + StyledToastAnimation? reverseAnimation, + StyledToastPosition? toastPosition, + }) { + return DigitToastThemeData( + textStyle: textStyle ?? this.textStyle, + successColor: successColor ?? this.successColor, + errorColor: errorColor ?? this.errorColor, + warningColor: warningColor ?? this.warningColor, + infoColor: infoColor ?? this.infoColor, + successIcon: successIcon ?? this.successIcon, + errorIcon: errorIcon ?? this.errorIcon, + warningIcon: warningIcon ?? this.warningIcon, + infoIcon: infoIcon ?? this.infoIcon, + cancelIcon: cancelIcon ?? this.cancelIcon, + toastWidth: toastWidth ?? this.toastWidth, + maxLine: maxLine ?? this.maxLine, + padding: padding ?? this.padding, + animationDuration: animationDuration ?? this.animationDuration, + animation: animation ?? this.animation, + reverseAnimation: reverseAnimation ?? this.reverseAnimation, + toastPosition: toastPosition ?? this.toastPosition, + ); + } + + @override + DigitToastThemeData lerp(ThemeExtension? other, double t) { + if (other is! DigitToastThemeData) return this; + + return DigitToastThemeData( + textStyle: TextStyle.lerp(textStyle, other.textStyle, t), + successColor: Color.lerp(successColor, other.successColor, t), + errorColor: Color.lerp(errorColor, other.errorColor, t), + warningColor: Color.lerp(warningColor, other.warningColor, t), + infoColor: Color.lerp(infoColor, other.infoColor, t), + successIcon: t<0.5 ? successIcon : other.successIcon, + errorIcon: t<0.5 ? errorIcon : other.errorIcon, + warningIcon: t<0.5 ? warningIcon : other.warningIcon, + infoIcon: t<0.5 ? infoIcon : other.infoIcon, + cancelIcon: t<0.5 ? cancelIcon : other.cancelIcon, + toastWidth: t<0.5 ? toastWidth : other.toastWidth, + maxLine: t<0.5 ? maxLine : other.maxLine, + padding: EdgeInsets.lerp(padding, other.padding, t), + animationDuration: t<0.5 ? animationDuration : other.animationDuration, + animation: t<0.5 ? animation : other.animation, + reverseAnimation: t<0.5 ? reverseAnimation : other.reverseAnimation, + toastPosition: t<0.5 ? toastPosition : other.toastPosition, + ); + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/theme/SpacerTheme/spacer_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/SpacerTheme/spacer_theme.dart new file mode 100644 index 00000000000..77247f033a2 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/SpacerTheme/spacer_theme.dart @@ -0,0 +1,83 @@ +import 'dart:ui'; +import 'package:flutter/material.dart'; + +class DigitSpacerTheme extends ThemeExtension { + final double spacer1; + final double spacer2; + final double spacer3; + final double spacer4; + final double spacer5; + final double spacer6; + final double spacer7; + final double spacer8; + final double spacer9; + final double spacer10; + final double spacer11; + final double spacer12; + + const DigitSpacerTheme({ + this.spacer1 = 4.0, + this.spacer2 = 8.0, + this.spacer3 = 12.0, + this.spacer4 = 16.0, + this.spacer5 = 20.0, + this.spacer6 = 24.0, + this.spacer7 = 28.0, + this.spacer8 = 32.0, + this.spacer9 = 36.0, + this.spacer10 = 40.0, + this.spacer11 = 44.0, + this.spacer12 = 48.0, + }); + + @override + DigitSpacerTheme copyWith({ + double? spacer1, + double? spacer2, + double? spacer3, + double? spacer4, + double? spacer5, + double? spacer6, + double? spacer7, + double? spacer8, + double? spacer9, + double? spacer10, + double? spacer11, + double? spacer12, + }) { + return DigitSpacerTheme( + spacer1: spacer1 ?? this.spacer1, + spacer2: spacer2 ?? this.spacer2, + spacer3: spacer3 ?? this.spacer3, + spacer4: spacer4 ?? this.spacer4, + spacer5: spacer5 ?? this.spacer5, + spacer6: spacer6 ?? this.spacer6, + spacer7: spacer7 ?? this.spacer7, + spacer8: spacer8 ?? this.spacer8, + spacer9: spacer9 ?? this.spacer9, + spacer10: spacer10 ?? this.spacer10, + spacer11: spacer11 ?? this.spacer11, + spacer12: spacer12 ?? this.spacer12, + ); + } + + @override + DigitSpacerTheme lerp(covariant ThemeExtension? other, double t) { + if (other is! DigitSpacerTheme) return this; + + return DigitSpacerTheme( + spacer1: lerpDouble(spacer1, other.spacer1, t)!, + spacer2: lerpDouble(spacer2, other.spacer2, t)!, + spacer3: lerpDouble(spacer3, other.spacer3, t)!, + spacer4: lerpDouble(spacer4, other.spacer4, t)!, + spacer5: lerpDouble(spacer5, other.spacer5, t)!, + spacer6: lerpDouble(spacer6, other.spacer6, t)!, + spacer7: lerpDouble(spacer7, other.spacer7, t)!, + spacer8: lerpDouble(spacer8, other.spacer8, t)!, + spacer9: lerpDouble(spacer9, other.spacer9, t)!, + spacer10: lerpDouble(spacer10, other.spacer10, t)!, + spacer11: lerpDouble(spacer11, other.spacer11, t)!, + spacer12: lerpDouble(spacer12, other.spacer12, t)!, + ); + } +} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/theme/TextTheme/button_text_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/TextTheme/button_text_theme.dart new file mode 100644 index 00000000000..416e90f5aed --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/TextTheme/button_text_theme.dart @@ -0,0 +1,54 @@ +import 'package:flutter/material.dart'; + +class DigitButtonTextTheme extends ThemeExtension { + final TextStyle buttonL; + final TextStyle buttonM; + final TextStyle buttonS; + + const DigitButtonTextTheme({ + this.buttonL = const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto-bold', + height: 1.14, + ), + this.buttonM = const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto-bold', + height: 1.14, + ), + this.buttonS = const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto-bold', + height: 1.14, + ), + }); + + @override + DigitButtonTextTheme copyWith({ + TextStyle? buttonL, + TextStyle? buttonM, + TextStyle? buttonS, + }) { + return DigitButtonTextTheme( + buttonL: buttonL ?? this.buttonL, + buttonM: buttonM ?? this.buttonM, + buttonS: buttonS ?? this.buttonS, + ); + } + + @override + DigitButtonTextTheme lerp(ThemeExtension? other, double t) { + if (other is! DigitButtonTextTheme) { + return this; + } + return DigitButtonTextTheme( + buttonL: TextStyle.lerp(buttonL, other.buttonL, t)!, + buttonM: TextStyle.lerp(buttonM, other.buttonM, t)!, + buttonS: TextStyle.lerp(buttonS, other.buttonS, t)!, + + ); + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/theme/TextTheme/desktop_text_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/TextTheme/desktop_text_theme.dart new file mode 100644 index 00000000000..1e6f23c6591 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/TextTheme/desktop_text_theme.dart @@ -0,0 +1,93 @@ + +import 'package:flutter/material.dart'; +import 'digit_text_theme.dart'; + +class DigitDesktopTextThemeExtension extends DigitTextTheme { + const DigitDesktopTextThemeExtension() + : super( + headingXl: const TextStyle( + fontSize: 40, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto Condensed', + height: 1.14, + ), + headingL: const TextStyle( + fontSize: 32, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ), + headingM: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ), + headingS: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ), + headingXS: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ), + captionL: const TextStyle( + fontSize: 28, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + height: 1.14, + ), + captionM: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + height: 1.14, + ), + captionS: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + height: 1.14, + ), + bodyL: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + bodyS: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + bodyXS: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + linkL: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + linkM: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + linkS: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + ); +} diff --git a/flutter/digit-ui-components/digit_components/lib/theme/TextTheme/digit_text_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/TextTheme/digit_text_theme.dart new file mode 100644 index 00000000000..fde58c82dc8 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/TextTheme/digit_text_theme.dart @@ -0,0 +1,100 @@ +import 'package:flutter/material.dart'; + +class DigitTextTheme extends ThemeExtension { + final TextStyle headingXl; + final TextStyle headingL; + final TextStyle headingM; + final TextStyle headingS; + final TextStyle headingXS; + final TextStyle captionL; + final TextStyle captionM; + final TextStyle captionS; + final TextStyle bodyL; + final TextStyle bodyS; + final TextStyle bodyXS; + final TextStyle linkL; + final TextStyle linkM; + final TextStyle linkS; + final TextStyle label; + + const DigitTextTheme({ + required this.headingXl, + required this.headingL, + required this.headingM, + required this.headingS, + required this.headingXS, + required this.captionL, + required this.captionM, + required this.captionS, + required this.bodyL, + required this.bodyS, + required this.bodyXS, + required this.linkL, + required this.linkM, + required this.linkS, + this.label = const TextStyle( + fontSize: 16, + fontFamily: 'Roboto', + fontWeight: FontWeight.w400, + height: 1.37, + ) + }); + + @override + DigitTextTheme copyWith({ + TextStyle? headingXl, + TextStyle? headingL, + TextStyle? headingM, + TextStyle? headingS, + TextStyle? headingXS, + TextStyle? captionL, + TextStyle? captionM, + TextStyle? captionS, + TextStyle? bodyL, + TextStyle? bodyS, + TextStyle? bodyXS, + TextStyle? linkL, + TextStyle? linkM, + TextStyle? linkS, + }) { + return DigitTextTheme( + headingXl: headingXl ?? this.headingXl, + headingL: headingL ?? this.headingL, + headingM: headingM ?? this.headingM, + headingS: headingS ?? this.headingS, + headingXS: headingXS ?? this.headingXS, + captionL: captionL ?? this.captionL, + captionM: captionM ?? this.captionM, + captionS: captionS ?? this.captionS, + bodyL: bodyL ?? this.bodyL, + bodyS: bodyS ?? this.bodyS, + bodyXS: bodyXS ?? this.bodyXS, + linkL: linkL ?? this.linkL, + linkM: linkM ?? this.linkM, + linkS: linkS ?? this.linkS, + ); + } + + @override + DigitTextTheme lerp(ThemeExtension? other, double t) { + if (other is! DigitTextTheme) { + return this; + } + return DigitTextTheme( + headingXl: TextStyle.lerp(headingXl, other.headingXl, t)!, + headingL: TextStyle.lerp(headingL, other.headingL, t)!, + headingM: TextStyle.lerp(headingM, other.headingM, t)!, + headingS: TextStyle.lerp(headingS, other.headingS, t)!, + headingXS: TextStyle.lerp(headingXS, other.headingXS, t)!, + captionL: TextStyle.lerp(captionL, other.captionL, t)!, + captionM: TextStyle.lerp(captionM, other.captionM, t)!, + captionS: TextStyle.lerp(captionS, other.captionS, t)!, + bodyL: TextStyle.lerp(bodyL, other.bodyL, t)!, + bodyS: TextStyle.lerp(bodyS, other.bodyS, t)!, + bodyXS: TextStyle.lerp(bodyXS, other.bodyXS, t)!, + linkL: TextStyle.lerp(linkL, other.linkL, t)!, + linkM: TextStyle.lerp(linkM, other.linkM, t)!, + linkS: TextStyle.lerp(linkS, other.linkS, t)!, + ); + } +} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/theme/TextTheme/mobile_text_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/TextTheme/mobile_text_theme.dart new file mode 100644 index 00000000000..2d44c76afba --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/TextTheme/mobile_text_theme.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; +import 'digit_text_theme.dart'; + +class DigitMobileTextThemeExtension extends DigitTextTheme { + const DigitMobileTextThemeExtension() + : super( + headingXl: const TextStyle( + fontSize: 32, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto Condensed', + height: 1.14, + ), + headingL: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ), + headingM: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ), + headingS: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ), + headingXS: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ), + captionL: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + height: 1.14, + ), + captionM: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + height: 1.14, + ), + captionS: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + height: 1.14, + ), + bodyL: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + bodyS: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + bodyXS: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + linkL: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + linkM: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + linkS: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + ); +} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/theme/TextTheme/tab_text_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/TextTheme/tab_text_theme.dart new file mode 100644 index 00000000000..000830c211f --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/TextTheme/tab_text_theme.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; +import 'digit_text_theme.dart'; + +class DigitTabTextThemeExtension extends DigitTextTheme { + const DigitTabTextThemeExtension() + : super( + headingXl: const TextStyle( + fontSize: 36, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto Condensed', + height: 1.14, + ), + headingL: const TextStyle( + fontSize: 28, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ), + headingM: const TextStyle( + fontSize: 22, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ), + headingS: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ), + headingXS: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ), + captionL: const TextStyle( + fontSize: 28, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + height: 1.14, + ), + captionM: const TextStyle( + fontSize: 24, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + height: 1.14, + ), + captionS: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + height: 1.14, + ), + bodyL: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + bodyS: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + bodyXS: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + linkL: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + linkM: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + linkS: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + ); +} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/theme/colors.dart b/flutter/digit-ui-components/digit_components/lib/theme/colors.dart index 198cd1a2161..df972102369 100644 --- a/flutter/digit-ui-components/digit_components/lib/theme/colors.dart +++ b/flutter/digit-ui-components/digit_components/lib/theme/colors.dart @@ -3,45 +3,48 @@ import 'dart:ui'; class DigitColors { const DigitColors(); - Light get light => Light(); + Light get light => const Light(); - - Color get orangeBG => const Color.fromRGBO(255, 250, 247, 1); Color get transparent => const Color.fromRGBO(0, 0, 0, 0); Color get shadowColor => const Color.fromRGBO(244, 119, 56, 0.25); - Color get darkPrimaryOrange => const Color.fromRGBO(234, 99, 31, 1); + Color get darkprimary1 => const Color.fromRGBO(234, 99, 31, 1); + Color get background => const Color(0xFF6F6F6F); + Color get overLayColor => const Color(0xFF0B0C0C); } class Light { - + const Light(); /// Primary - Color get primaryOrange => const Color(0xFFF47738); - Color get primaryBlueGray => const Color(0xFF0B4B66); - Color get primaryOrangeBg => const Color(0xFFFEEFE7); + Color get primary1 => const Color(0xFFC84C0E); + Color get primary1Bg => const Color(0xFFFBEEE8); + Color get primary2 => const Color(0xFF0B4B66); /// Text - Color get textPrimary => const Color(0xFF0B0C0C); - Color get textSecondary => const Color(0xFF505A5F); - Color get textDisabled => const Color(0xFFB1B4B6); + Color get textPrimary => const Color(0xFF363636); + Color get textSecondary => const Color(0xFF787878); + Color get textDisabled => const Color(0xFFC5C5C5); /// Paper Color get paperPrimary => const Color(0xFFFFFFFF); Color get paperSecondary => const Color(0xFFFAFAFA); /// Alert - Color get alertError => const Color(0xFFD4351C); + Color get alertError => const Color(0xFFB91900); Color get alertSuccess => const Color(0xFF00703C); - Color get alertInfo => const Color(0xFF3498DB); - Color get alertErrorBg => const Color(0xFFEFC7C1); - Color get alertSuccessBg => const Color(0xFFBAD6C9); - Color get alertInfoBg => const Color(0xFFC7E0F1); - Color get alertWarning => const Color(0xFFF19100); - Color get alertWarningBg => const Color(0xFFF8E5C8); + Color get alertInfo => const Color(0xFF0057BD); + Color get alertErrorBg => const Color(0xFFFFF5F4); + Color get alertSuccessBg => const Color(0xFFF1FFF8); + Color get alertInfoBg => const Color(0xFFDEEFFF); + Color get alertWarning => const Color(0xFFEA8D00); + Color get alertWarningBg => const Color(0xFFFFF9F0); /// Generic Color get genericBackground => const Color(0xFFEEEEEE); Color get genericDivider => const Color(0xFFD6D5D4); Color get genericInputBorder => const Color(0xFF505A5F); -} +/// Header + + +} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/theme/digit_colors.dart b/flutter/digit-ui-components/digit_components/lib/theme/digit_colors.dart new file mode 100644 index 00000000000..554e1f0a18c --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/digit_colors.dart @@ -0,0 +1,50 @@ +import 'package:flutter/material.dart'; + +/// DigitColors is abstract because we don’t ever need to instantiate it. +abstract class DigitExtendedColors { + const DigitExtendedColors(); + + static const light = _lightTheme(); + + Color get transparent => const Color.fromRGBO(0, 0, 0, 0); + Color get shadowColor => const Color.fromRGBO(244, 119, 56, 0.25); + Color get darkPrimary1 => const Color.fromRGBO(234, 99, 31, 1); + Color get background => const Color(0xFF6F6F6F); + Color get overLayColor => const Color(0xFF0B0C0C); +} + + +/// _lightTheme is private because we don’t allow access to it directly but only through the DigitColors. +class _lightTheme { + const _lightTheme(); + /// Primary + final primary1 = const Color(0xFFC84C0E); + final primary1Bg = const Color(0xFFFBEEE8); + final primary2 = const Color(0xFF0B4B66); + + /// Text + final textPrimary = const Color(0xFF363636); + final textSecondary = const Color(0xFF787878); + final textDisabled = const Color(0xFFC5C5C5); + + /// Paper + final paperPrimary = const Color(0xFFFFFFFF); + final paperSecondary = const Color(0xFFFAFAFA); + + /// Alert + final alertError = const Color(0xFFB91900); + final alertErrorBg = const Color(0xFFFFF5F4); + final alertSuccess = const Color(0xFF00703C); + final alertSuccessBg = const Color(0xFFF1FFF8); + final alertInfo = const Color(0xFF0057BD); + final alertInfoBg = const Color(0xFFDEEFFF); + final alertWarning = const Color(0xFFEA8D00); + final alertWarningBg = const Color(0xFFFFF9F0); + + /// Generic + final genericBackground = const Color(0xFFEEEEEE); + final genericDivider = const Color(0xFFD6D5D4); + final genericInputBorder = const Color(0xFF505A5F); + +/// Header +} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/theme/digit_extended_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/digit_extended_theme.dart new file mode 100644 index 00000000000..6b1beda0374 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/digit_extended_theme.dart @@ -0,0 +1,181 @@ +library digit_theme; + +import 'package:digit_ui_components/digit_components.dart'; +import 'package:digit_ui_components/theme/ColorTheme/light_color_theme.dart'; +import 'package:digit_ui_components/theme/ComponentTheme/bread_crumb_theme.dart'; +import 'package:digit_ui_components/theme/ComponentTheme/chip_theme.dart'; +import 'package:digit_ui_components/theme/TextTheme/button_text_theme.dart'; +import 'package:digit_ui_components/theme/TextTheme/desktop_text_theme.dart'; +import 'package:digit_ui_components/theme/TextTheme/mobile_text_theme.dart'; +import 'package:digit_ui_components/theme/TextTheme/tab_text_theme.dart'; +import 'package:flutter/material.dart'; +import 'ComponentTheme/action_card_theme.dart'; +import 'ComponentTheme/back_button_theme.dart'; +import 'SpacerTheme/spacer_theme.dart'; +import 'TextTheme/digit_text_theme.dart'; + +class DigitExtendedTheme { + static const DigitExtendedTheme _instance = DigitExtendedTheme._internal(); + + static DigitExtendedTheme get instance => _instance; + + const DigitExtendedTheme._internal(); + + ThemeData getTheme(BuildContext context) { + return ThemeData( + colorScheme: colorScheme, + appBarTheme: const AppBarTheme(elevation: 0), + textSelectionTheme: TextSelectionThemeData( + cursorColor: const DigitColors().light.primary1, + selectionColor: const DigitColors().light.primary1Bg, + selectionHandleColor: const DigitColors().transparent, + ), + datePickerTheme: _getDatePickerTheme(), + timePickerTheme: _getTimePickerTheme(), + ); + } + + DatePickerThemeData _getDatePickerTheme() { + return DatePickerThemeData( + headerHeadlineStyle: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto-bold', + ), + headerHelpStyle: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto-bold', + ), + headerBackgroundColor: const DigitColors().light.paperPrimary, + headerForegroundColor: const DigitColors().light.textPrimary, + backgroundColor: const DigitColors().light.paperPrimary, + ); + } + + TimePickerThemeData _getTimePickerTheme() { + return TimePickerThemeData( + backgroundColor: const DigitColors().light.paperPrimary, + hourMinuteShape: RoundedRectangleBorder( + borderRadius: const BorderRadius.all(Radius.circular(4)), + side: BorderSide(color: const DigitColors().light.primary1, width: 1), + ), + dayPeriodBorderSide: + BorderSide(color: const DigitColors().light.primary1, width: 1), + dayPeriodColor: MaterialStateColor.resolveWith( + (states) => states.contains(MaterialState.selected) + ? const DigitColors().light.primary1 + : const DigitColors().transparent, + ), + dayPeriodTextColor: MaterialStateColor.resolveWith( + (states) => states.contains(MaterialState.selected) + ? const DigitColors().light.paperPrimary + : const DigitColors().light.textPrimary, + ), + dayPeriodShape: RoundedRectangleBorder( + borderRadius: const BorderRadius.all(Radius.circular(1)), + side: BorderSide(color: const DigitColors().light.primary1, width: 1), + ), + hourMinuteColor: MaterialStateColor.resolveWith( + (states) => states.contains(MaterialState.selected) + ? const DigitColors().light.primary1 + : const DigitColors().transparent, + ), + hourMinuteTextColor: MaterialStateColor.resolveWith( + (states) => states.contains(MaterialState.selected) + ? const DigitColors().light.paperPrimary + : const DigitColors().light.textPrimary, + ), + dialHandColor: const DigitColors().light.primary1, + dialBackgroundColor: const DigitColors().light.primary1Bg, + hourMinuteTextStyle: + const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + dayPeriodTextStyle: + const TextStyle(fontSize: 12, fontWeight: FontWeight.bold), + helpTextStyle: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto-bold', + color: const DigitColors().light.textPrimary, + ), + inputDecorationTheme: const InputDecorationTheme( + border: InputBorder.none, + contentPadding: EdgeInsets.all(0), + ), + dialTextColor: MaterialStateColor.resolveWith( + (states) => const DigitColors().light.textPrimary, + ), + entryModeIconColor: const DigitColors().light.primary1, + cancelButtonStyle: ButtonStyle( + textStyle: MaterialStateProperty.resolveWith( + (Set states) { + return TextStyle( + fontFamily: 'Roboto', + fontWeight: FontWeight.w500, + fontSize: 19, + color: const DigitColors().light.primary1, + ); + }, + ), + ), + confirmButtonStyle: ButtonStyle( + textStyle: MaterialStateProperty.resolveWith( + (Set states) { + return TextStyle( + fontFamily: 'Roboto', + fontWeight: FontWeight.w500, + fontSize: 19, + color: const DigitColors().light.primary1, + ); + }, + ), + ), + ); + } +} + +ColorScheme get colorScheme => ColorScheme( + brightness: Brightness.light, + primary: const DigitColors().light.primary1, + onPrimary: const DigitColors().light.paperPrimary, + secondary: const DigitColors().light.primary2, + onSecondary: const DigitColors().light.paperPrimary, + error: const DigitColors().light.alertError, + onError: const DigitColors().light.paperPrimary, + background: const DigitColors().light.paperPrimary, + onBackground: const DigitColors().light.textPrimary, + surface: const DigitColors().light.paperSecondary, + onSurface: const DigitColors().light.textPrimary, + onSurfaceVariant: const DigitColors().light.alertSuccess, + inversePrimary: const DigitColors().light.alertSuccessBg, + outline: const DigitColors().light.genericDivider, + shadow: const DigitColors().light.textSecondary, + surfaceTint: const DigitColors().light.paperPrimary, + onTertiaryContainer: const DigitColors().light.alertInfoBg, +); + +/// extension on theme data to access these theme directly +/// Theme.of(context).colorTheme +/// Theme.of(context).textTheme +/// Theme.of(context).spacerTheme + +extension DigitThemeExtension on ThemeData { + DigitColorTheme get colorTheme => + extension() ?? const DigitColorTheme(); + + DigitSpacerTheme get spacerTheme => + extension() ?? const DigitSpacerTheme(); + + DigitButtonTextTheme get digitButtonTextTheme => + extension() ?? const DigitButtonTextTheme(); + + DigitTextTheme digitTextTheme(BuildContext context) { + if (AppView.isMobileView(MediaQuery.of(context).size)) { + return extension() ?? const DigitMobileTextThemeExtension(); + } else if (AppView.isTabletView(MediaQuery.of(context).size)) { + return extension() ?? const DigitTabTextThemeExtension(); + } else { + return extension() ?? const DigitDesktopTextThemeExtension(); + } + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/theme/digit_theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/digit_theme.dart index ae35928794a..ad5b83f50e7 100644 --- a/flutter/digit-ui-components/digit_components/lib/theme/digit_theme.dart +++ b/flutter/digit-ui-components/digit_components/lib/theme/digit_theme.dart @@ -1,11 +1,10 @@ library digit_theme; +import 'package:digit_ui_components/digit_components.dart'; import 'package:digit_ui_components/theme/colors.dart'; import 'package:digit_ui_components/theme/typography.dart'; import 'package:flutter/material.dart'; -const kPadding = 8.0; - class DigitTheme { static const DigitTheme _instance = DigitTheme._internal(); @@ -14,37 +13,49 @@ class DigitTheme { DigitColors get colors => const DigitColors(); DigitTabTypography get tabTypography => DigitTabTypography( - normalBase: const TextStyle( - fontFamily: 'Roboto', - ), - displayBase: const TextStyle( - fontFamily: 'Roboto', - ), - light: colors.light.textSecondary, - normal: colors.light.textPrimary, - ); + normalBase: const TextStyle( + fontFamily: 'Roboto', + ), + displayBase: const TextStyle( + fontFamily: 'Roboto', + ), + light: colors.light.textSecondary, + normal: colors.light.textPrimary, + ); + + ButtonTypography get buttonTypography => ButtonTypography( + normalBase: const TextStyle( + fontFamily: 'Roboto', + ), + displayBase: const TextStyle( + fontFamily: 'Roboto', + ), + light: colors.light.textSecondary, + normal: colors.light.textPrimary, + ); + DigitDesktopTypography get desktopTypography => DigitDesktopTypography( - normalBase: const TextStyle( - fontFamily: 'Roboto', - ), - displayBase: const TextStyle( - fontFamily: 'Roboto', - ), - light: colors.light.textSecondary, - normal: colors.light.textPrimary, - ); + normalBase: const TextStyle( + fontFamily: 'Roboto', + ), + displayBase: const TextStyle( + fontFamily: 'Roboto', + ), + light: colors.light.textSecondary, + normal: colors.light.textPrimary, + ); DigitMobileTypography get mobileTypography => DigitMobileTypography( - normalBase: const TextStyle( - fontFamily: 'Roboto', - ), - displayBase: const TextStyle( - fontFamily: 'Roboto', - ), - light: colors.light.textSecondary, - normal: colors.light.textPrimary, - ); + normalBase: const TextStyle( + fontFamily: 'Roboto', + ), + displayBase: const TextStyle( + fontFamily: 'Roboto', + ), + light: colors.light.textSecondary, + normal: colors.light.textPrimary, + ); const DigitTheme._internal(); @@ -61,10 +72,10 @@ class DigitTheme { textButtonTheme: textButtonTheme, cardTheme: cardTheme, inputDecorationTheme: inputDecorationTheme, - dialogTheme: dialogTheme, + dialogTheme: dialogTheme.copyWith(), textSelectionTheme: TextSelectionThemeData( - cursorColor: const DigitColors().light.primaryOrange, - selectionColor: const DigitColors().light.primaryOrangeBg, + cursorColor: const DigitColors().light.primary1, + selectionColor: const DigitColors().light.primary1Bg, selectionHandleColor: const DigitColors().transparent, ), datePickerTheme: DatePickerThemeData( @@ -87,39 +98,39 @@ class DigitTheme { hourMinuteShape: RoundedRectangleBorder( borderRadius: const BorderRadius.all(Radius.circular(4)), side: BorderSide( - color: const DigitColors().light.primaryOrange, width: 1), + color: const DigitColors().light.primary1, width: 1), ), dayPeriodBorderSide: BorderSide( - color: const DigitColors().light.primaryOrange, width: 1), + color: const DigitColors().light.primary1, width: 1), dayPeriodColor: MaterialStateColor.resolveWith( - (states) => states.contains(MaterialState.selected) - ? const DigitColors().light.primaryOrange + (states) => states.contains(MaterialState.selected) + ? const DigitColors().light.primary1 : const DigitColors().transparent, ), dayPeriodTextColor: MaterialStateColor.resolveWith((states) => - states.contains(MaterialState.selected) - ? const DigitColors().light.paperPrimary - : const DigitColors().light.textPrimary), + states.contains(MaterialState.selected) + ? const DigitColors().light.paperPrimary + : const DigitColors().light.textPrimary), dayPeriodShape: RoundedRectangleBorder( borderRadius: const BorderRadius.all(Radius.circular(1)), side: BorderSide( - color: const DigitColors().light.primaryOrange, width: 1), + color: const DigitColors().light.primary1, width: 1), ), hourMinuteColor: MaterialStateColor.resolveWith( - (states) => states.contains(MaterialState.selected) - ? const DigitColors().light.primaryOrange + (states) => states.contains(MaterialState.selected) + ? const DigitColors().light.primary1 : const DigitColors().transparent, ), hourMinuteTextColor: MaterialStateColor.resolveWith((states) => - states.contains(MaterialState.selected) - ? const DigitColors().light.paperPrimary - : const DigitColors().light.textPrimary), - dialHandColor: const DigitColors().light.primaryOrange, - dialBackgroundColor: const DigitColors().light.primaryOrangeBg, + states.contains(MaterialState.selected) + ? const DigitColors().light.paperPrimary + : const DigitColors().light.textPrimary), + dialHandColor: const DigitColors().light.primary1, + dialBackgroundColor: const DigitColors().light.primary1Bg, hourMinuteTextStyle: - const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + const TextStyle(fontSize: 20, fontWeight: FontWeight.bold), dayPeriodTextStyle: - const TextStyle(fontSize: 12, fontWeight: FontWeight.bold), + const TextStyle(fontSize: 12, fontWeight: FontWeight.bold), helpTextStyle: TextStyle( fontSize: 16, fontWeight: FontWeight.w700, @@ -130,19 +141,19 @@ class DigitTheme { contentPadding: EdgeInsets.all(0), ), dialTextColor: MaterialStateColor.resolveWith( - (states) => const DigitColors().light.textPrimary, + (states) => const DigitColors().light.textPrimary, ), - entryModeIconColor: const DigitColors().light.primaryOrange, + entryModeIconColor: const DigitColors().light.primary1, cancelButtonStyle: ButtonStyle( textStyle: MaterialStateProperty.resolveWith( - (Set states) { - return TextStyle( - fontFamily: 'Roboto', - fontWeight: FontWeight.w500, - fontSize: 19, - color: const DigitColors().light.primaryOrange, - ); - }), + (Set states) { + return TextStyle( + fontFamily: 'Roboto', + fontWeight: FontWeight.w500, + fontSize: 19, + color: const DigitColors().light.primary1, + ); + }), ), confirmButtonStyle: ButtonStyle( textStyle: MaterialStateProperty.resolveWith( @@ -151,7 +162,7 @@ class DigitTheme { fontFamily: 'Roboto', fontWeight: FontWeight.w500, fontSize: 19, - color: const DigitColors().light.primaryOrange, + color: const DigitColors().light.primary1, ); }), ), @@ -160,158 +171,158 @@ class DigitTheme { } ColorScheme get colorScheme => ColorScheme( - brightness: Brightness.light, - primary: colors.light.primaryOrange, - onPrimary: colors.light.paperPrimary, - secondary: colors.light.primaryBlueGray, - onSecondary: colors.light.paperPrimary, - error: colors.light.alertError, - onError: colors.light.paperPrimary, - background: colors.light.paperPrimary, - onBackground: colors.light.textPrimary, - surface: colors.light.paperSecondary, - onSurface: colors.light.textPrimary, - onSurfaceVariant: colors.light.alertSuccess, - inversePrimary: colors.light.alertSuccessBg, - outline: colors.light.genericDivider, - shadow: colors.light.textSecondary, - surfaceTint: colors.light.paperPrimary, - onTertiaryContainer: colors.light.alertInfoBg, - ); + brightness: Brightness.light, + primary: colors.light.primary1, + onPrimary: colors.light.paperPrimary, + secondary: colors.light.primary2, + onSecondary: colors.light.paperPrimary, + error: colors.light.alertError, + onError: colors.light.paperPrimary, + background: colors.light.paperPrimary, + onBackground: colors.light.textPrimary, + surface: colors.light.paperSecondary, + onSurface: colors.light.textPrimary, + onSurfaceVariant: colors.light.alertSuccess, + inversePrimary: colors.light.alertSuccessBg, + outline: colors.light.genericDivider, + shadow: colors.light.textSecondary, + surfaceTint: colors.light.paperPrimary, + onTertiaryContainer: colors.light.alertInfoBg, + ); EdgeInsets get buttonPadding => const EdgeInsets.symmetric( - vertical: kPadding, - horizontal: kPadding * 2, - ); + vertical: spacer2, + horizontal: spacer4, + ); - EdgeInsets get containerMargin => const EdgeInsets.all(kPadding); + EdgeInsets get containerMargin => const EdgeInsets.all(spacer2); EdgeInsets get verticalMargin => const EdgeInsets.symmetric( - vertical: kPadding, - ); + vertical: spacer2, + ); Duration get toastDuration => const Duration(seconds: 2); OutlinedBorder get buttonBorder => const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.zero), - ); + borderRadius: BorderRadius.all(Radius.zero), + ); ElevatedButtonThemeData get elevatedButtonTheme => ElevatedButtonThemeData( - style: ElevatedButton.styleFrom( - shape: buttonBorder, - padding: buttonPadding, - backgroundColor: colorScheme.primary, - foregroundColor: const DigitColors().light.primaryOrange, - disabledBackgroundColor: colorScheme.secondary.withOpacity( - 0.5, - ), - disabledForegroundColor: colorScheme.onSecondary, - elevation: 0, - ), - ); + style: ElevatedButton.styleFrom( + shape: buttonBorder, + padding: buttonPadding, + backgroundColor: colorScheme.primary, + foregroundColor: const DigitColors().light.primary1, + disabledBackgroundColor: colorScheme.secondary.withOpacity( + 0.5, + ), + disabledForegroundColor: colorScheme.onSecondary, + elevation: 0, + ), + ); OutlinedButtonThemeData get outlinedButtonTheme => OutlinedButtonThemeData( - style: OutlinedButton.styleFrom( - foregroundColor: const DigitColors().light.primaryOrange, - side: BorderSide(color: colorScheme.secondary), - padding: buttonPadding, - ), - ); + style: OutlinedButton.styleFrom( + foregroundColor: const DigitColors().light.primary1, + side: BorderSide(color: colorScheme.secondary), + padding: buttonPadding, + ), + ); TextButtonThemeData get textButtonTheme => TextButtonThemeData( - style: TextButton.styleFrom( - shape: buttonBorder, - padding: buttonPadding, - textStyle: TextStyle(fontFamily: 'Roboto', - fontWeight: FontWeight.w500, - fontSize: 19, - color: const DigitColors().light.primaryOrange,), - foregroundColor: const DigitColors().light.primaryOrange, - ), - ); + style: TextButton.styleFrom( + shape: buttonBorder, + padding: buttonPadding, + textStyle: TextStyle(fontFamily: 'Roboto', + fontWeight: FontWeight.w500, + fontSize: 19, + color: const DigitColors().light.primary1,), + foregroundColor: const DigitColors().light.primary1, + ), + ); CardTheme get cardTheme => const CardTheme( - margin: EdgeInsets.fromLTRB(kPadding, kPadding * 2, kPadding, 0), - elevation: 1, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular(4), - ), - ), - ); + margin: EdgeInsets.fromLTRB(spacer2, spacer4, spacer2, 0), + elevation: 1, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(4), + ), + ), + ); InputDecorationTheme get inputDecorationTheme => InputDecorationTheme( - enabledBorder: OutlineInputBorder( - borderRadius: const BorderRadius.all( - Radius.circular( - 0, - ), - ), - borderSide: BorderSide( - color: colors.light.textSecondary, - ), + enabledBorder: OutlineInputBorder( + borderRadius: const BorderRadius.all( + Radius.circular( + 0, ), - focusedBorder: OutlineInputBorder( - borderRadius: const BorderRadius.all( - Radius.circular( - 0, - ), - ), - borderSide: BorderSide( - color: colors.light.primaryOrange, - width: 2, - ), + ), + borderSide: BorderSide( + color: colors.light.textSecondary, + ), + ), + focusedBorder: OutlineInputBorder( + borderRadius: const BorderRadius.all( + Radius.circular( + 0, ), - disabledBorder: OutlineInputBorder( - borderRadius: const BorderRadius.all( - Radius.circular( - 0, - ), - ), - borderSide: BorderSide(color: colors.light.textDisabled, width: 1), + ), + borderSide: BorderSide( + color: colors.light.primary1, + width: 2, + ), + ), + disabledBorder: OutlineInputBorder( + borderRadius: const BorderRadius.all( + Radius.circular( + 0, ), - contentPadding: const EdgeInsets.all(12), - floatingLabelBehavior: FloatingLabelBehavior.never, - errorBorder: OutlineInputBorder( - borderRadius: const BorderRadius.all( - Radius.circular( - 0, - ), - ), - borderSide: BorderSide( - color: colors.light.alertError, - ), + ), + borderSide: BorderSide(color: colors.light.textDisabled, width: 1), + ), + contentPadding: const EdgeInsets.all(12), + floatingLabelBehavior: FloatingLabelBehavior.never, + errorBorder: OutlineInputBorder( + borderRadius: const BorderRadius.all( + Radius.circular( + 0, ), - focusedErrorBorder: OutlineInputBorder( - borderRadius: const BorderRadius.all( - Radius.circular( - 0, - ), - ), - borderSide: BorderSide(color: colors.light.alertError, width: 2), + ), + borderSide: BorderSide( + color: colors.light.alertError, + ), + ), + focusedErrorBorder: OutlineInputBorder( + borderRadius: const BorderRadius.all( + Radius.circular( + 0, ), - ); + ), + borderSide: BorderSide(color: colors.light.alertError, width: 2), + ), + ); DialogTheme get dialogTheme => DialogTheme( - titleTextStyle: mobileTypography.headingL, - contentTextStyle: mobileTypography.bodyL, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all( - Radius.circular( - 4, - ), - ), + titleTextStyle: mobileTypography.headingL, + contentTextStyle: mobileTypography.bodyL, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular( + 4, ), - actionsPadding: const EdgeInsets.all(kPadding), - ); + ), + ), + actionsPadding: const EdgeInsets.all(spacer2), + ); BorderSide get tableCellBorder => BorderSide( - color: colorScheme.outline, - width: 0.5, - ); + color: colorScheme.outline, + width: 0.5, + ); BorderSide get tableCellStrongBorder => BorderSide( - color: colorScheme.outline, - width: 2, - ); -} + color: colorScheme.outline, + width: 2, + ); +} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/theme/digit_typography.dart b/flutter/digit-ui-components/digit_components/lib/theme/digit_typography.dart new file mode 100644 index 00000000000..a5d1baff43b --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/digit_typography.dart @@ -0,0 +1,101 @@ +import 'package:flutter/material.dart'; + +abstract class AppTypography { + + /// heading + static const headingXl = TextStyle( + fontSize: 32, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ); + + static const headingL = TextStyle( + fontSize: 24, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ); + static const headingM = TextStyle( + fontSize: 20, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ); + + static const headingS = TextStyle( + fontSize: 16, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ); + static const headingXS = TextStyle( + fontSize: 12, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ); + + /// caption + static const captionL = TextStyle( + fontSize: 24, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + height: 1.14, + ); + static const captionM = TextStyle( + fontSize: 20, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + height: 1.14, + ); + + static const captionS = TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + height: 1.14, + ); + + /// body + static const bodyL = TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ); + + static const bodyS = TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ); + static const bodyXS = TextStyle( + fontSize: 12, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ); + + /// link + static const linkL = TextStyle( + fontSize: 16, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ); + static const linkM = TextStyle( + fontSize: 14, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ); + + static const linkS = TextStyle( + fontSize: 12, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ); +} diff --git a/flutter/digit-ui-components/digit_components/lib/theme/spacers.dart b/flutter/digit-ui-components/digit_components/lib/theme/spacers.dart new file mode 100644 index 00000000000..d73e5ac93e7 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/spacers.dart @@ -0,0 +1,15 @@ +/// use this digit spacer class to define spaces anywhere in your pages + +const double spacer1 = 4.0; +const double spacer2 = 8.0; +const double spacer3 = 12.0; +const double spacer4 = 16.0; +const double spacer5 = 20.0; +const double spacer6 = 24.0; +const double spacer7 = 28.0; +const double spacer8 = 32.0; +const double spacer9 = 36.0; +const double spacer10 = 40.0; +const double spacer11 = 44.0; +const double spacer12 = 48.0; + diff --git a/flutter/digit-ui-components/digit_components/lib/theme/text_theme_extension.dart b/flutter/digit-ui-components/digit_components/lib/theme/text_theme_extension.dart new file mode 100644 index 00000000000..b497c3b0aad --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/theme/text_theme_extension.dart @@ -0,0 +1,247 @@ +import 'package:flutter/material.dart'; + +class DigitTextThemeExtension extends ThemeExtension { + const DigitTextThemeExtension({ + this.headingXl, + this.headingL, + this.headingM, + this.headingS, + this.headingXS, + this.captionL, + this.captionM, + this.captionS, + this.bodyL, + this.bodyS, + this.bodyXS, + this.linkL, + this.linkM, + this.linkS, + }); + + final TextStyle? headingXl; + final TextStyle? headingL; + final TextStyle? headingM; + final TextStyle? headingS; + final TextStyle? headingXS; + final TextStyle? captionL; + final TextStyle? captionM; + final TextStyle? captionS; + final TextStyle? bodyL; + final TextStyle? bodyS; + final TextStyle? bodyXS; + final TextStyle? linkL; + final TextStyle? linkM; + final TextStyle? linkS; + + static DigitTextThemeExtension defaultTheme(BuildContext context) { + + final bool isMobile = MediaQuery.of(context).size.width < 600; + final bool isTab = MediaQuery.of(context).size.width >= 600 && + MediaQuery.of(context).size.width < 1200; + + return DigitTextThemeExtension( + headingXl: TextStyle( + fontSize: isMobile + ? 32 + : isTab + ? 36 + : 40, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ), + headingL: TextStyle( + fontSize: isMobile + ? 24 + : isTab + ? 28 + : 32, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ), + headingM: TextStyle( + fontSize: isMobile + ? 20 + : isTab + ? 22 + : 24, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ), + headingS: TextStyle( + fontSize: isMobile + ? 16 + : isTab + ? 16 + : 16, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ), + headingXS: TextStyle( + fontSize: isMobile + ? 12 + : isTab + ? 14 + : 14, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + height: 1.14, + ), + captionL: TextStyle( + fontSize: isMobile + ? 24 + : isTab + ? 28 + : 28, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + height: 1.14, + ), + captionM: TextStyle( + fontSize: isMobile + ? 20 + : isTab + ? 24 + : 24, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + height: 1.14, + ), + captionS: TextStyle( + fontSize: isMobile + ? 16 + : isTab + ? 20 + : 20, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + height: 1.14, + ), + bodyL: TextStyle( + fontSize: isMobile + ? 16 + : isTab + ? 20 + : 20, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + bodyS: TextStyle( + fontSize: isMobile + ? 14 + : isTab + ? 16 + : 16, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + bodyXS: TextStyle( + fontSize: isMobile + ? 12 + : isTab + ? 14 + : 14, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + linkL: TextStyle( + fontSize: isMobile + ? 16 + : isTab + ? 20 + : 20, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + linkM: TextStyle( + fontSize: isMobile + ? 14 + : isTab + ? 16 + : 16, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + linkS: TextStyle( + fontSize: isMobile + ? 12 + : isTab + ? 14 + : 14, + fontWeight: FontWeight.w400, + fontFamily: 'Roboto', + height: 1.37, + ), + ); + } + + @override + ThemeExtension copyWith({ + TextStyle? headingXl, + TextStyle? headingL, + TextStyle? headingM, + TextStyle? headingS, + TextStyle? headingXS, + TextStyle? captionL, + TextStyle? captionM, + TextStyle? captionS, + TextStyle? bodyL, + TextStyle? bodyS, + TextStyle? bodyXS, + TextStyle? linkL, + TextStyle? linkM, + TextStyle? linkS, + }) { + return DigitTextThemeExtension( + headingXl: headingXl ?? this.headingXl, + headingL: headingL ?? this.headingL, + headingM: headingM ?? this.headingM, + headingS: headingS ?? this.headingS, + headingXS: headingXS ?? this.headingXS, + captionL: captionL ?? this.captionL, + captionM: captionM ?? this.captionM, + captionS: captionS ?? this.captionS, + bodyL: bodyL ?? this.bodyL, + bodyS: bodyS ?? this.bodyS, + bodyXS: bodyXS ?? this.bodyXS, + linkL: linkL ?? this.linkL, + linkM: linkM ?? this.linkM, + linkS: linkS ?? this.linkS, + ); + } + + @override + ThemeExtension lerp( + covariant ThemeExtension? other, + double t, + ) { + if (other is! DigitTextThemeExtension) { + return this; + } + + return DigitTextThemeExtension( + headingXl: TextStyle.lerp(headingXl, other.headingXl, t)!, + headingL: TextStyle.lerp(headingL, other.headingL, t)!, + headingM: TextStyle.lerp(headingM, other.headingM, t)!, + headingS: TextStyle.lerp(headingS, other.headingS, t)!, + headingXS: TextStyle.lerp(headingXS, other.headingXS, t)!, + captionL: TextStyle.lerp(captionL, other.captionL, t)!, + captionM: TextStyle.lerp(captionM, other.captionM, t)!, + captionS: TextStyle.lerp(captionS, other.captionS, t)!, + bodyL: TextStyle.lerp(bodyL, other.bodyL, t)!, + bodyS: TextStyle.lerp(bodyS, other.bodyS, t)!, + bodyXS: TextStyle.lerp(bodyXS, other.bodyXS, t)!, + linkL: TextStyle.lerp(linkL, other.linkL, t)!, + linkM: TextStyle.lerp(linkM, other.linkM, t)!, + linkS: TextStyle.lerp(linkS, other.linkS, t)!, + ); + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/theme/theme.dart b/flutter/digit-ui-components/digit_components/lib/theme/theme.dart index e69bdb61a74..57a28470791 100644 --- a/flutter/digit-ui-components/digit_components/lib/theme/theme.dart +++ b/flutter/digit-ui-components/digit_components/lib/theme/theme.dart @@ -1,3 +1,4 @@ export './typography.dart'; export './digit_theme.dart'; export './colors.dart'; +export './spacers.dart'; diff --git a/flutter/digit-ui-components/digit_components/lib/theme/typography.dart b/flutter/digit-ui-components/digit_components/lib/theme/typography.dart index ed63ecf9c8b..4d0f84ac9e4 100644 --- a/flutter/digit-ui-components/digit_components/lib/theme/typography.dart +++ b/flutter/digit-ui-components/digit_components/lib/theme/typography.dart @@ -46,6 +46,12 @@ abstract class DigitTypography { TextStyle get bodyS => textTheme.bodyMedium!; TextStyle get bodyXS => textTheme.bodySmall!; + + /// link + TextStyle get linkL => textTheme.bodyLarge!; + TextStyle get linkM => textTheme.bodyMedium!; + TextStyle get linkS => textTheme.bodySmall!; + /// Miscellaneous styles TextStyle get label => textTheme.bodyLarge!; TextStyle get link => textTheme.bodyLarge!.copyWith( @@ -78,57 +84,68 @@ class DigitMobileTypography extends DigitTypography { displayMedium: _big.copyWith( fontSize: 32, fontWeight: FontWeight.w700, - fontFamily: 'Roboto Condensed Bold', + fontFamily: 'Roboto', + height: 1.14, ), headlineLarge: _normal.copyWith( fontSize: 24, fontWeight: FontWeight.w700, - fontFamily: 'Roboto-bold', + fontFamily: 'Roboto', + height: 1.14, ), headlineMedium: _normal.copyWith( fontSize: 20, fontWeight: FontWeight.w700, - fontFamily: 'Roboto-bold', + fontFamily: 'Roboto', + height: 1.14, ), headlineSmall: _normal.copyWith( fontSize: 16, fontWeight: FontWeight.w700, - fontFamily: 'Roboto-bold', + fontFamily: 'Roboto', + height: 1.14, ), displaySmall: _normal.copyWith( fontSize: 12, fontWeight: FontWeight.w700, - fontFamily: 'Roboto-bold', + fontFamily: 'Roboto', + height: 1.14, ), bodyLarge: _normal.copyWith( fontSize: 16, fontWeight: FontWeight.w400, fontFamily: 'Roboto', + height: 1.37, ), bodyMedium: _normal.copyWith( fontSize: 14, fontWeight: FontWeight.w400, fontFamily: 'Roboto', + height: 1.37, ), bodySmall: _normal.copyWith( fontSize: 12, fontWeight: FontWeight.w400, fontFamily: 'Roboto', + height: 1.37, ), labelLarge: _normal.copyWith( fontSize: 24, fontWeight: FontWeight.w500, - fontFamily: 'Roboto Italic', + fontFamily: 'Roboto', + height: 1.14, ), labelMedium: _light.copyWith( fontSize: 20, fontWeight: FontWeight.w500, - fontFamily: 'Roboto Italic', + fontFamily: 'Roboto', + height: 1.14, ), labelSmall: _normal.copyWith( fontSize: 16, fontWeight: FontWeight.w500, - fontFamily: 'Roboto Italic', + fontFamily: 'Roboto', + height: 1.14, ), ); } @@ -154,57 +171,68 @@ class DigitTabTypography extends DigitTypography { displayMedium: _big.copyWith( fontSize: 36, fontWeight: FontWeight.w700, - fontFamily: 'Roboto Condensed Bold', + fontFamily: 'Roboto', + height: 1.14, ), headlineLarge: _normal.copyWith( fontSize: 28, fontWeight: FontWeight.w700, - fontFamily: 'Roboto-bold', + fontFamily: 'Roboto', + height: 1.14, ), headlineMedium: _normal.copyWith( fontSize: 22, fontWeight: FontWeight.w700, - fontFamily: 'Roboto-bold', + fontFamily: 'Roboto', + height: 1.14, ), headlineSmall: _normal.copyWith( fontSize: 16, fontWeight: FontWeight.w700, - fontFamily: 'Roboto-bold', + fontFamily: 'Roboto', + height: 1.14, ), displaySmall: _normal.copyWith( - fontSize: 12, + fontSize: 14, fontWeight: FontWeight.w700, - fontFamily: 'Roboto-bold', + fontFamily: 'Roboto', + height: 1.14, ), bodyLarge: _normal.copyWith( fontSize: 20, fontWeight: FontWeight.w400, fontFamily: 'Roboto', + height: 1.37, ), bodyMedium: _normal.copyWith( fontSize: 16, fontWeight: FontWeight.w400, fontFamily: 'Roboto', + height: 1.37, ), bodySmall: _normal.copyWith( fontSize: 14, fontWeight: FontWeight.w400, fontFamily: 'Roboto', + height: 1.37, ), labelLarge: _normal.copyWith( fontSize: 28, fontWeight: FontWeight.w500, - fontFamily: 'Roboto Italic', + fontFamily: 'Roboto', + height: 1.14, ), labelMedium: _light.copyWith( fontSize: 24, fontWeight: FontWeight.w500, - fontFamily: 'Roboto Italic', + fontFamily: 'Roboto', + height: 1.14, ), labelSmall: _normal.copyWith( fontSize: 20, fontWeight: FontWeight.w500, - fontFamily: 'Roboto Italic', + fontFamily: 'Roboto', + height: 1.14, ), ); } @@ -251,57 +279,68 @@ class DigitDesktopTypography extends DigitTypography { displayMedium: _big.copyWith( fontSize: 40, fontWeight: FontWeight.w700, - fontFamily: 'Roboto Condensed Bold', + fontFamily: 'Roboto', + height: 1.14, ), headlineLarge: _normal.copyWith( fontSize: 32, fontWeight: FontWeight.w700, - fontFamily: 'Robot-bold', + fontFamily: 'Roboto', + height: 1.14, ), headlineMedium: _normal.copyWith( fontSize: 24, fontWeight: FontWeight.w700, - fontFamily: 'Robot-bold', + fontFamily: 'Roboto', + height: 1.14, ), headlineSmall: _normal.copyWith( fontSize: 16, fontWeight: FontWeight.w700, - fontFamily: 'Robot-bold', + fontFamily: 'Roboto', + height: 1.14, ), displaySmall: _normal.copyWith( - fontSize: 12, + fontSize: 14, fontWeight: FontWeight.w700, - fontFamily: 'Robot-bold', + fontFamily: 'Roboto', + height: 1.14, ), bodyLarge: _normal.copyWith( fontSize: 20, fontWeight: FontWeight.w400, fontFamily: 'Roboto', + height: 1.37, ), bodyMedium: _normal.copyWith( fontSize: 16, fontWeight: FontWeight.w400, fontFamily: 'Roboto', + height: 1.37, ), bodySmall: _normal.copyWith( fontSize: 14, fontWeight: FontWeight.w400, fontFamily: 'Roboto', + height: 1.37, ), labelLarge: _normal.copyWith( fontSize: 28, fontWeight: FontWeight.w500, - fontFamily: 'Roboto Italic', + fontFamily: 'Roboto', + height: 1.14, ), labelMedium: _light.copyWith( fontSize: 24, fontWeight: FontWeight.w500, - fontFamily: 'Roboto Italic', + fontFamily: 'Roboto', + height: 1.14, ), labelSmall: _normal.copyWith( fontSize: 20, fontWeight: FontWeight.w500, - fontFamily: 'Roboto Italic', + fontFamily: 'Roboto', + height: 1.14, ), ); } @@ -329,12 +368,69 @@ class DigitDesktopTypography extends DigitTypography { } -DigitTypography getTypography(BuildContext context) { - if (AppView.isDesktopView(MediaQuery.of(context).size.width)) { +/// Button-specific typography class +class ButtonTypography extends DigitTypography{ + + const ButtonTypography({ + required TextStyle normalBase, + required TextStyle displayBase, + Color? normal, + Color? light, + }) : super( + normal: normal, + light: light, + displayBase: displayBase, + normalBase: normalBase, + ); + + TextStyle get _normal => + _normalBase.copyWith(color: _textColorNormal, fontFamily: 'Roboto'); + TextStyle get _light => + _normalBase.copyWith(color: _textColorLight, fontFamily: 'Roboto'); + TextStyle get _big => + _displayBase.copyWith(color: _textColorNormal, fontFamily: 'Roboto'); + @override + TextTheme get textTheme { + return TextTheme( + + headlineLarge: _normal.copyWith( + fontSize: 20, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto-bold', + height: 1.14, + ), + headlineMedium: _normal.copyWith( + fontSize: 16, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto-bold', + height: 1.14, + ), + headlineSmall: _normal.copyWith( + fontSize: 14, + fontWeight: FontWeight.w500, + fontFamily: 'Roboto-bold', + height: 1.14, + ), + ); + } + + /// Heading styles + TextStyle get buttonLarge => textTheme.headlineLarge!; + TextStyle get buttonMedium => textTheme.headlineMedium!; + TextStyle get buttonSmall => textTheme.headlineSmall!; +} + +DigitTypography getTypography(BuildContext context, isButtonTypography) { + + if(isButtonTypography){ + return DigitTheme.instance.buttonTypography; + } + + if (AppView.isDesktopView(MediaQuery.of(context).size)) { /// Desktop return DigitTheme.instance.desktopTypography; - } else if (AppView.isTabletView(MediaQuery.of(context).size.width)) { + } else if (AppView.isTabletView(MediaQuery.of(context).size)) { /// Tablet return DigitTheme.instance.tabTypography; } else { diff --git a/flutter/digit-ui-components/digit_components/lib/utils/app_logger.dart b/flutter/digit-ui-components/digit_components/lib/utils/app_logger.dart new file mode 100644 index 00000000000..ac7d1837260 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/utils/app_logger.dart @@ -0,0 +1,59 @@ +import 'package:flutter/foundation.dart'; +import 'package:logging/logging.dart'; + +class AppLogger { + static AppLogger get instance => _instance; + static const _instance = AppLogger._(); + + const AppLogger._(); + + void debug(dynamic input, {String? title}) => + _printMessage(input, title: title, level: Level.CONFIG); + + void info(dynamic input, {String? title}) => + _printMessage(input, title: title, level: Level.INFO); + + void error({ + required String title, + String? message, + StackTrace? stackTrace, + }) => + _printError( + message: message, + title: title, + stackTrace: stackTrace, + ); + + void _printError({ + required String title, + String? message, + StackTrace? stackTrace, + }) { + if (stackTrace != null) { + debugPrintStack( + label: title, + stackTrace: stackTrace, + ); + } else { + _printMessage( + message, + title: title, + level: Level.SEVERE, + ); + } + } + + void _printMessage( + dynamic input, { + String? title, + required Level level, + }) => + debugPrint( + [ + '[${level.name.padRight(4, ' ').substring(0, 4)}] ', + '${(title ?? runtimeType.toString())}\n', + '${input.toString()}\n', + ].join(''), + wrapWidth: 120, + ); +} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/utils/component_utils.dart b/flutter/digit-ui-components/digit_components/lib/utils/component_utils.dart new file mode 100644 index 00000000000..dcf1cc9586d --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/utils/component_utils.dart @@ -0,0 +1,131 @@ +import 'package:digit_ui_components/digit_components.dart'; +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:flutter/material.dart'; + +class DigitComponentsUtils { + static void hideDialog(BuildContext context) { + Navigator.of( + context, + rootNavigator: true, + ).popUntil( + (route) => route is! PopupRoute, + ); + } + + static void showDialog( + BuildContext context, String? label, DialogType dialogType) { + DigitSyncDialog.show( + context, + type: dialogType, + label: label, + ); + } + +} + + +class DigitSyncDialog { + static Future show( + BuildContext context, { + Key? key, + bool barrierDismissible = false, + required DialogType type, String? label, + DigitDialogActions? primaryAction, + DigitDialogActions? secondaryAction, + }) async { + return showDialog( + context: context, + barrierDismissible: barrierDismissible, + barrierColor: const DigitColors().overLayColor.withOpacity(.70), + builder: (context) => DigitSyncDialogContent(type: type, label: label, primaryAction: primaryAction, secondaryAction: secondaryAction), + ); + } + +} + +class DigitSyncDialogContent extends StatelessWidget { + final String? label; + final DialogType type; + + final DigitDialogActions? primaryAction; + final DigitDialogActions? secondaryAction; + + const DigitSyncDialogContent({ + super.key, + this.label, + required this.type, + this.primaryAction, + this.secondaryAction, + }); + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + final textTheme = theme.digitTextTheme(context); + IconData icon; + Color color; + TextStyle? labelStyle; + + switch (type) { + case DialogType.inProgress: + icon = Icons.autorenew; + color = theme.colorTheme.primary.primary1; + labelStyle = textTheme.headingM; + break; + case DialogType.complete: + icon = Icons.check_circle_outline; + color = theme.colorTheme.alert.success; + labelStyle = textTheme.headingM; + break; + case DialogType.failed: + icon = Icons.error_outline; + color = theme.colorTheme.alert.error; + labelStyle = textTheme.headingM; + break; + } + + return Dialog.fullscreen( + backgroundColor: const DigitColors().transparent, + child: Center( + child: Container( + padding: const EdgeInsets.all(spacer6), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + color: theme.colorTheme.paper.primary, + boxShadow: [ + BoxShadow( + color: const Color(0xFF000000).withOpacity(.16), + offset: const Offset(0, 1), + spreadRadius: 0, + blurRadius: 2, + ), + ], + ), + width: 300, + child: Column( + mainAxisSize: MainAxisSize.min, + children: + [ + Icon(icon, size: 32, color: color), + if(label != null) + ...[ const SizedBox(height: spacer4), + Text(label!, style: labelStyle.copyWith(color: color)),] + ], + ) + ), + ), + ); + } +} + +enum DialogType { inProgress, complete, failed } + +class DigitDialogActions { + final String label; + final T Function(BuildContext context)? action; + + const DigitDialogActions({ + required this.label, + this.action, + }); +} diff --git a/flutter/digit-ui-components/digit_components/lib/utils/date_utils.dart b/flutter/digit-ui-components/digit_components/lib/utils/date_utils.dart index 4ad6e214c76..179924490f9 100644 --- a/flutter/digit-ui-components/digit_components/lib/utils/date_utils.dart +++ b/flutter/digit-ui-components/digit_components/lib/utils/date_utils.dart @@ -3,7 +3,7 @@ import 'package:intl/intl.dart'; class DigitDateUtils { // Function to calculate age in years and months based on the selected date. - static DigitDOBAge calculateAge(DateTime selectedDate) { + static DigitDOBAgeConvertor calculateAge(DateTime selectedDate) { DateTime currentDate = DateTime.now(); // Calculate the difference in years, months, and days @@ -25,7 +25,7 @@ class DigitDateUtils { ageInMonths += 12; } - return DigitDOBAge( + return DigitDOBAgeConvertor( years: ageInYears >= 0 ? ageInYears : 0, months: ageInMonths, days: ageInDays); @@ -125,9 +125,9 @@ class DigitDateUtils { // Function to get the number of years or months between a provided date and the current date. static getYearsAndMonthsFromDateTime( - DateTime dateTime, [ - bool getMonths = false, - ]) { + DateTime dateTime, [ + bool getMonths = false, + ]) { int days = DateTime.now().difference(dateTime).inDays; int years = days ~/ 365; int months = (days - (years * 365)) ~/ 30; @@ -166,10 +166,10 @@ class DigitDateUtils { } } -class DigitDOBAge { +class DigitDOBAgeConvertor { final int years; final int months; final int days; - DigitDOBAge({this.years = 0, this.months = 0, this.days = 0}); -} + DigitDOBAgeConvertor({this.years = 0, this.months = 0, this.days = 0}); +} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/utils/fileService/file_download.dart b/flutter/digit-ui-components/digit_components/lib/utils/fileService/file_download.dart new file mode 100644 index 00000000000..3a9af39fe5e --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/utils/fileService/file_download.dart @@ -0,0 +1,14 @@ +import 'package:digit_ui_components/widgets/atoms/upload_drag.dart'; +import 'package:flutter/foundation.dart' show kIsWeb; +import 'mobile_file_download.dart'; +import 'web_file_download.dart'; + +class FileDownloaderService { + final dynamic _fileDownloader; + + FileDownloaderService() : _fileDownloader = kIsWeb ? WebFileDownloader() : MobileFileDownloader(); + + Future downloadFile(DroppedFile file) { + return _fileDownloader.downloadFile(file); + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/utils/fileService/file_service.dart b/flutter/digit-ui-components/digit_components/lib/utils/fileService/file_service.dart new file mode 100644 index 00000000000..53ebff5c82a --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/utils/fileService/file_service.dart @@ -0,0 +1,14 @@ +import 'dart:typed_data'; +import 'package:flutter/foundation.dart' show kIsWeb; +import 'mobile_file_service.dart'; +import 'web_file_service.dart'; + +class FileService { + final dynamic _fileWriter; + + FileService() : _fileWriter = kIsWeb ? WebFileWriter() : MobileFileWriter(); + + Future writeToTemporaryFile(Uint8List dataBytes, String fileName) { + return _fileWriter.writeToTemporaryFile(dataBytes, fileName); + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/utils/fileService/mobile_file_download.dart b/flutter/digit-ui-components/digit_components/lib/utils/fileService/mobile_file_download.dart new file mode 100644 index 00000000000..9cb11e17bbe --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/utils/fileService/mobile_file_download.dart @@ -0,0 +1,12 @@ +import 'dart:io' as io; +import 'package:path_provider/path_provider.dart'; +import '../../widgets/atoms/upload_drag.dart'; + +class MobileFileDownloader { + Future downloadFile(DroppedFile file) async { + final directory = await getTemporaryDirectory(); + final path = directory.path + io.Platform.pathSeparator + file.name; + final localFile = io.File(path); + await localFile.writeAsBytes(file.data); + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/utils/fileService/mobile_file_service.dart b/flutter/digit-ui-components/digit_components/lib/utils/fileService/mobile_file_service.dart new file mode 100644 index 00000000000..6ce8410ca7b --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/utils/fileService/mobile_file_service.dart @@ -0,0 +1,12 @@ +import 'dart:typed_data'; +import 'dart:io' as io; +import 'package:path_provider/path_provider.dart'; + +class MobileFileWriter { + Future writeToTemporaryFile(Uint8List dataBytes, String fileName) async { + final directory = await getTemporaryDirectory(); + final file = io.File('${directory.path}/$fileName'); + await file.writeAsBytes(dataBytes); + return file.path; + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/utils/fileService/web_file_download.dart b/flutter/digit-ui-components/digit_components/lib/utils/fileService/web_file_download.dart new file mode 100644 index 00000000000..02ac6e81d90 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/utils/fileService/web_file_download.dart @@ -0,0 +1,12 @@ +import 'dart:typed_data'; +import 'package:universal_html/html.dart' as html; +import 'package:digit_ui_components/widgets/atoms/upload_drag.dart'; + +class WebFileDownloader { + Future downloadFile(DroppedFile file) async { + html.AnchorElement( + href: html.Url.createObjectUrlFromBlob(html.Blob([file.data]))) + ..setAttribute("download", file.name) + ..click(); + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/utils/fileService/web_file_service.dart b/flutter/digit-ui-components/digit_components/lib/utils/fileService/web_file_service.dart new file mode 100644 index 00000000000..cb1f55ef2d1 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/utils/fileService/web_file_service.dart @@ -0,0 +1,30 @@ +import 'dart:typed_data'; +import 'package:universal_html/html.dart' as html; + +class WebFileWriter { + Future writeToTemporaryFile(Uint8List dataBytes, String fileName) async { + final Map mimeTypes = { + 'pdf': 'application/pdf', + 'doc': 'application/msword', + 'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'xls': 'application/vnd.ms-excel', + 'xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'jpg': 'image/jpeg', + 'jpeg': 'image/jpeg', + 'png': 'image/png', + }; + + final extension = fileName.split('.').last.toLowerCase(); + final mimeType = mimeTypes[extension]; + + if (mimeType != null) { + final blob = html.Blob([dataBytes], mimeType); + final url = html.Url.createObjectUrlFromBlob(blob); + html.window.open(url, '_blank'); + return url; + } else { + print('Unsupported file type: $extension'); + return ''; + } + } +} diff --git a/flutter/digit-ui-components/digit_components/lib/utils/i18_key_constants.dart b/flutter/digit-ui-components/digit_components/lib/utils/i18_key_constants.dart new file mode 100644 index 00000000000..2c58abd7c87 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/utils/i18_key_constants.dart @@ -0,0 +1,7 @@ +const common = Common(); + +class Common { + const Common(); + String get camera => 'CAMERA'; +} + diff --git a/flutter/digit-ui-components/digit_components/lib/utils/utils.dart b/flutter/digit-ui-components/digit_components/lib/utils/utils.dart new file mode 100644 index 00000000000..46dd9d6ff3d --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/utils/utils.dart @@ -0,0 +1,83 @@ +import 'package:digit_ui_components/models/DropdownModels.dart'; +import 'package:url_launcher/url_launcher.dart'; + +/// Utility function to capitalize the first letter of the first word +/// and make all other letters lowercase in the entire message +String? convertInToSentenceCase(String? text) { + if (text == null || text.isEmpty) { + return text; + } + + /// Trim the text to remove leading and trailing whitespace + text = text.trim(); + + /// Split the text into words + List words = text.split(' '); + + /// Initialize an empty list to hold the processed words + List sentenceCase = []; + + /// Process the first word separately to capitalize its first letter + if (words.isNotEmpty) { + String firstWord = words[0]; + String capitalizedFirstWord = + firstWord[0].toUpperCase() + firstWord.substring(1).toLowerCase(); + sentenceCase.add(capitalizedFirstWord); + + /// Process the remaining words to make all letters lowercase + for (int i = 1; i < words.length; i++) { + sentenceCase.add(words[i].toLowerCase()); + } + } + + /// Join the processed words back into a single string + return sentenceCase.join(' '); +} + +/// Utility function to capitalize the first letter of every word +String capitalizeFirstLetterOfEveryWord(String text) { + if (text.isEmpty) { + return text; + } + List words = text.split(' '); + List capitalizedWords = []; + + for (String word in words) { + if (word.isNotEmpty) { + String capitalizedWord = + word[0].toUpperCase() + word.substring(1).toLowerCase(); + capitalizedWords.add(capitalizedWord); + } + } + + return capitalizedWords.join(' '); +} + +/// Helper function to get the associated value from the value mapper +String getAssociatedValue(String code, List valueMapper ) { + ValueMapper? mappedValue = valueMapper.firstWhere( + (value) => value.code == code, + orElse: () => const ValueMapper(code: '', name: ''), + + /// Provide default values here + ); + return mappedValue.name; +} + +/// truncate string with after a max length +String truncateWithEllipsis(int maxLength, String text) { + if (text.length <= maxLength) { + return text; + } else { + return '${text.substring(0, maxLength)}...'; + } +} + +void viewDocument(String url) async { + Uri uri = Uri.parse(url); + if (await canLaunchUrl(uri)) { + await launchUrl(uri); + } else { + throw 'Could not launch $url'; + } +} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/utils/validators/file_validator.dart b/flutter/digit-ui-components/digit_components/lib/utils/validators/file_validator.dart new file mode 100644 index 00000000000..bb20134c0b8 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/utils/validators/file_validator.dart @@ -0,0 +1,66 @@ +import 'package:file_picker/file_picker.dart'; + +enum FileValidatorType { + fileType, + minSize, + maxSize, +} + +class FileValidator { + final FileValidatorType type; + final dynamic value; + final String? errorMessage; + + FileValidator(this.type, this.value, {this.errorMessage}); +} + + +String? validateFile(PlatformFile file, List validators) { + // Perform validation for the given file using the provided validators + for (var validator in validators) { + switch (validator.type) { + case FileValidatorType.fileType: + if (!_isFileTypeAllowed(file, validator.value)) { + return validator.errorMessage ?? 'Invalid file type'; + } + break; + case FileValidatorType.minSize: + if (!_isFileSizeAboveMin(file, validator.value)) { + return validator.errorMessage ?? 'File size is too small'; + } + break; + case FileValidatorType.maxSize: + if (!_isFileSizeBelowMax(file, validator.value)) { + return validator.errorMessage ?? 'File size exceeds maximum limit'; + } + break; + } + } + + /// If the file passes all validations, return null + return null; +} + +bool _isFileTypeAllowed(PlatformFile file, List allowedExtensions) { + // Get the file extension + String fileExtension = file.name!.split('.').last.toLowerCase(); + + // Check if the file extension is in the list of allowed file types + return allowedExtensions.contains(fileExtension); +} + +bool _isFileSizeAboveMin(PlatformFile file, int minFileSizeInBytes) { + // Get the file size in bytes + int fileSizeInBytes = file.size ?? 0; + + // Check if the file size is above the minimum threshold + return fileSizeInBytes >= minFileSizeInBytes; +} + +bool _isFileSizeBelowMax(PlatformFile file, int maxFileSizeInBytes) { + // Get the file size in bytes + int fileSizeInBytes = file.size ?? 0; + + // Check if the file size is below the maximum threshold + return fileSizeInBytes <= maxFileSizeInBytes; +} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/utils/validators/image_validator.dart b/flutter/digit-ui-components/digit_components/lib/utils/validators/image_validator.dart new file mode 100644 index 00000000000..d499020efbc --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/utils/validators/image_validator.dart @@ -0,0 +1,37 @@ +import 'dart:io'; +import 'package:camera/camera.dart'; +import 'file_validator.dart'; + +String? validateImage( + XFile xFile, List validators, String? name) { + final file = File(xFile.path); + for (var validator in validators) { + switch (validator.type) { + case FileValidatorType.fileType: + final List allowedTypes = validator.value; + print(name); + final fileType = name?.split('.').last.toLowerCase(); + + if (!allowedTypes.contains(fileType)) { + print(fileType); + return validator.errorMessage; + } + break; + case FileValidatorType.minSize: + final int minSize = validator.value; + final fileSize = file.lengthSync(); + if (fileSize < minSize) { + return validator.errorMessage; + } + break; + case FileValidatorType.maxSize: + final int maxSize = validator.value; + final fileSize = file.lengthSync(); + if (fileSize > maxSize) { + return validator.errorMessage; + } + break; + } + } + return null; // Validation passed +} \ No newline at end of file diff --git a/flutter/digit-ui-components/digit_components/lib/widgets/atoms/accordion.dart b/flutter/digit-ui-components/digit_components/lib/widgets/atoms/accordion.dart new file mode 100644 index 00000000000..c1a76cdc9f7 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/widgets/atoms/accordion.dart @@ -0,0 +1,199 @@ +import 'package:digit_ui_components/digit_components.dart'; +import 'package:digit_ui_components/widgets/atoms/digit_divider.dart'; +import 'package:flutter/material.dart'; + +class DigitAccordion extends StatefulWidget { + final List items; + final bool allowMultipleOpen; + final Duration animationDuration; + final Color headerBackgroundColor; + final Color contentBackgroundColor; + final double headerElevation; + final bool divider; + + const DigitAccordion({ + Key? key, + required this.items, + this.allowMultipleOpen = false, + this.animationDuration = const Duration(milliseconds: 300), + this.headerBackgroundColor = Colors.white, + this.contentBackgroundColor = Colors.white, + this.headerElevation = 0, + this.divider = false, + }) : super(key: key); + + @override + _DigitAccordionState createState() => _DigitAccordionState(); +} + +class _DigitAccordionState extends State + with TickerProviderStateMixin { + late List _expandedStates; + late List _animationControllers; + + @override + void initState() { + super.initState(); + _expandedStates = + widget.items.map((item) => item.initiallyExpanded).toList(); + _animationControllers = widget.items.map((item) { + return AnimationController( + vsync: this, + duration: widget.animationDuration, + ); + }).toList(); + + for (int i = 0; i < _expandedStates.length; i++) { + if (_expandedStates[i]) { + _animationControllers[i].forward(); + } + } + } + + @override + void dispose() { + for (var controller in _animationControllers) { + controller.dispose(); + } + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Column( + children: widget.items.asMap().entries.map((entry) { + int index = entry.key; + DigitAccordionItem item = entry.value; + return Column( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: _buildAccordionItem(item, index), + ), + if (widget.divider && index < widget.items.length - 1) + ...[ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20.0), + child: Divider( + color: const DigitColors().light.genericDivider, + height: 1, + ), + ), + ], + ], + ); + }).toList(), + ); + } + + Widget _buildAccordionItem(DigitAccordionItem item, int index) { + bool isExpanded = _expandedStates[index]; + return AnimatedContainer( + duration: widget.animationDuration, + curve: Curves.easeOut, + decoration: BoxDecoration( + color: widget.headerBackgroundColor, + borderRadius: BorderRadius.circular(4), + border: item.showBorder + ? Border.all( + color: const DigitColors().light.genericDivider, width: 1.0) + : null, // Conditional border based on showBorder + boxShadow: [ + if (widget.headerElevation > 0) + BoxShadow( + color: Colors.black26, + blurRadius: widget.headerElevation, + offset: Offset(0, widget.headerElevation / 2), + ), + ], + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + GestureDetector( + onTap: () { + setState(() { + if (!widget.allowMultipleOpen) { + for (int i = 0; i < _expandedStates.length; i++) { + if (i != index) { + _expandedStates[i] = false; + _animationControllers[i].reverse(); + } + } + } + _expandedStates[index] = !isExpanded; + if (isExpanded) { + _animationControllers[index].reverse(); + } else { + _animationControllers[index].forward(); + } + }); + }, + child: Container( + decoration: BoxDecoration( + color: widget.headerBackgroundColor, + borderRadius: BorderRadius.circular(4), + boxShadow: [ + if (widget.headerElevation > 0) + BoxShadow( + color: Colors.black26, + blurRadius: widget.headerElevation, + offset: Offset(0, widget.headerElevation / 2), + ), + ], + ), + padding: const EdgeInsets.all(16), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded(child: item.header), + RotationTransition( + turns: _animationControllers[index].drive( + Tween(begin: 0.0, end: 0.25), + ), + child: const Icon( + Icons.chevron_right, + size: 24, + ), + ), + ], + ), + ), + ), + if(item.divider && isExpanded) ...[const DigitDivider(dividerType: DividerType.small,), const SizedBox(height: 8,)], + SizeTransition( + sizeFactor: CurvedAnimation( + parent: _animationControllers[index], + curve: Curves.easeOut, + ), + child: Container( + decoration: BoxDecoration( + color: widget.contentBackgroundColor, + borderRadius: BorderRadius.circular(4), + ), + padding: const EdgeInsets.symmetric(horizontal: 8.0, vertical: 4.0), + child: item.content, + ), + ), + ], + ), + ); + } +} + +class DigitAccordionItem { + final Widget header; + final Widget content; + final bool divider; + final bool initiallyExpanded; + final bool showBorder; + + DigitAccordionItem({ + required this.header, + required this.content, + this.divider = false, + this.initiallyExpanded = false, + this.showBorder = true, + }); +} diff --git a/flutter/digit-ui-components/digit_components/lib/widgets/atoms/digit_action_card.dart b/flutter/digit-ui-components/digit_components/lib/widgets/atoms/digit_action_card.dart new file mode 100644 index 00000000000..3b4d09e2553 --- /dev/null +++ b/flutter/digit-ui-components/digit_components/lib/widgets/atoms/digit_action_card.dart @@ -0,0 +1,100 @@ +/// A widget that displays a dialog with a list of action buttons. +/// The dialog can be customized with width, height, and spacing between buttons. + +///Example usage: +///``` ActionCard( +/// width: 300, +/// height: 400, +/// spacing: 16, +/// actions: [ +/// Button( +/// label: 'Action 1', +/// onPressed: () { +/// // Handle Action 1 +/// }, +/// ), +/// Button( +/// label: 'Action 2', +/// onPressed: () { +/// // Handle Action 2 +/// }, +/// ), +/// ], +/// )``` + +import 'package:digit_ui_components/digit_components.dart'; +import 'package:digit_ui_components/theme/digit_extended_theme.dart'; +import 'package:flutter/material.dart'; +import '../../theme/ComponentTheme/action_card_theme.dart'; +import '../helper_widget/button_list.dart'; + +class ActionCard extends StatelessWidget { + final DigitActionCardTheme? actionCardTheme; + + /// A list of action buttons to be displayed in the dialog. + final List