diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..faf6b49
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,478 @@
+# editorconfig.org
+
+# top-most EditorConfig file
+root = true
+
+# Default settings:
+# A newline ending every file
+# Use 4 spaces as indentation
+[*]
+insert_final_newline = true
+indent_style = space
+indent_size = 4
+
+[project.json]
+indent_size = 2
+
+# C# files
+[*.cs]
+# New line preferences
+csharp_new_line_before_open_brace = all
+csharp_new_line_before_else = true
+csharp_new_line_before_catch = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_members_in_anonymous_types = true
+csharp_new_line_between_query_expression_clauses = true
+
+# Indentation preferences
+csharp_indent_block_contents = true
+csharp_indent_braces = false
+csharp_indent_case_contents = true
+csharp_indent_case_contents_when_block = true
+csharp_indent_switch_labels = true
+csharp_indent_labels = one_less_than_current
+
+# Modifier preferences
+csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:suggestion
+
+# use this.
+dotnet_style_qualification_for_field = true:none
+dotnet_style_qualification_for_property = true:none
+dotnet_style_qualification_for_method = true:none
+dotnet_style_qualification_for_event = true:none
+
+# only use var when it's obvious what the variable type is
+csharp_style_var_for_built_in_types = true:none
+csharp_style_var_when_type_is_apparent = true:none
+csharp_style_var_elsewhere = true:none
+
+# Types: use keywords instead of BCL types, and permit var only when the type is clear
+csharp_style_var_for_built_in_types = false:suggestion
+csharp_style_var_when_type_is_apparent = false:none
+csharp_style_var_elsewhere = false:suggestion
+dotnet_style_predefined_type_for_locals_parameters_members = true:warning
+dotnet_style_predefined_type_for_member_access = true:warning
+
+# name all constant fields using PascalCase
+dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
+dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
+dotnet_naming_symbols.constant_fields.applicable_kinds = field
+dotnet_naming_symbols.constant_fields.required_modifiers = const
+dotnet_naming_style.pascal_case_style.capitalization = pascal_case
+
+# static fields should have s_ prefix
+dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion
+dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields
+dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style
+dotnet_naming_symbols.static_fields.applicable_kinds = field
+dotnet_naming_symbols.static_fields.required_modifiers = static
+dotnet_naming_symbols.static_fields.applicable_accessibilities = private, internal, private_protected
+dotnet_naming_style.static_prefix_style.required_prefix = s_
+dotnet_naming_style.static_prefix_style.capitalization = camel_case
+
+# internal and private fields should be _camelCase
+dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
+dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
+dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
+dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
+dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
+dotnet_naming_style.camel_case_underscore_style.required_prefix = _
+dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
+
+# Code style defaults
+csharp_using_directive_placement = outside_namespace:warning
+dotnet_separate_import_directive_groups = false
+dotnet_sort_system_directives_first = true
+csharp_prefer_braces = true:silent
+csharp_preserve_single_line_blocks = true:none
+csharp_preserve_single_line_statements = false:none
+csharp_prefer_static_local_function = true:suggestion
+csharp_prefer_simple_using_statement = false:none
+
+# Code quality
+dotnet_style_readonly_field = true:suggestion
+dotnet_code_quality_unused_parameters = non_public:suggestion
+
+# Parentheses preferences
+dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
+dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
+dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
+
+# Modifier preferences
+dotnet_style_require_accessibility_modifiers = for_non_interface_members:warning
+
+# Field preferences
+dotnet_style_readonly_field = true:warning
+
+# Expression-level preferences
+dotnet_style_object_initializer = true:suggestion
+dotnet_style_collection_initializer = true:suggestion
+dotnet_style_explicit_tuple_names = true:suggestion
+dotnet_style_coalesce_expression = true:suggestion
+dotnet_style_null_propagation = true:suggestion
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
+dotnet_style_prefer_inferred_tuple_names = true:suggestion
+dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
+dotnet_style_prefer_auto_properties = true:suggestion
+dotnet_style_prefer_conditional_expression_over_assignment = true:silent
+dotnet_style_prefer_conditional_expression_over_return = true:silent
+csharp_prefer_simple_default_expression = true:suggestion
+dotnet_style_prefer_compound_assignment = true:warning
+dotnet_style_prefer_simplified_interpolation = true:suggestion
+
+# Expression-bodied members
+csharp_style_expression_bodied_methods = true:suggestion
+csharp_style_expression_bodied_constructors = true:suggestion
+csharp_style_expression_bodied_operators = true:suggestion
+csharp_style_expression_bodied_properties = true:suggestion
+csharp_style_expression_bodied_indexers = true:suggestion
+csharp_style_expression_bodied_accessors = true:suggestion
+csharp_style_expression_bodied_lambdas = true:suggestion
+csharp_style_expression_bodied_local_functions = true:suggestion
+
+# Pattern matching
+csharp_style_pattern_matching_over_as_with_null_check = true:warning
+csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
+csharp_style_inlined_variable_declaration = true:suggestion
+csharp_style_prefer_switch_expression = true:suggestion
+
+# Null checking preferences
+csharp_style_throw_expression = true:suggestion
+csharp_style_conditional_delegate_call = true:suggestion
+
+# Other features
+csharp_style_prefer_index_operator = false:none
+csharp_style_prefer_range_operator = false:none
+csharp_style_pattern_local_over_anonymous_function = false:none
+
+# Space preferences
+csharp_space_after_cast = false
+csharp_space_after_colon_in_inheritance_clause = true
+csharp_space_after_comma = true
+csharp_space_after_dot = false
+csharp_space_after_keywords_in_control_flow_statements = true
+csharp_space_after_semicolon_in_for_statement = true
+csharp_space_around_binary_operators = before_and_after
+csharp_space_around_declaration_statements = do_not_ignore
+csharp_space_before_colon_in_inheritance_clause = true
+csharp_space_before_comma = false
+csharp_space_before_dot = false
+csharp_space_before_open_square_brackets = false
+csharp_space_before_semicolon_in_for_statement = false
+csharp_space_between_empty_square_brackets = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_between_method_call_parameter_list_parentheses = false
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+csharp_space_between_method_declaration_name_and_open_parenthesis = false
+csharp_space_between_method_declaration_parameter_list_parentheses = false
+csharp_space_between_parentheses = false
+csharp_space_between_square_brackets = false
+
+# analyzers
+# CA1851: Possible multiple enumerations of 'IEnumerable' collection - https://github.com/dotnet/roslyn-analyzers/issues/6379
+dotnet_diagnostic.CA1851.severity = suggestion
+
+dotnet_diagnostic.AvoidAsyncVoid.severity = suggestion
+
+dotnet_diagnostic.CA1000.severity = none
+dotnet_diagnostic.CA1001.severity = error
+dotnet_diagnostic.CA1009.severity = error
+dotnet_diagnostic.CA1016.severity = error
+dotnet_diagnostic.CA1030.severity = none
+dotnet_diagnostic.CA1031.severity = none
+dotnet_diagnostic.CA1033.severity = none
+dotnet_diagnostic.CA1036.severity = none
+dotnet_diagnostic.CA1049.severity = error
+dotnet_diagnostic.CA1056.severity = suggestion
+dotnet_diagnostic.CA1060.severity = error
+dotnet_diagnostic.CA1061.severity = error
+dotnet_diagnostic.CA1063.severity = error
+dotnet_diagnostic.CA1065.severity = error
+dotnet_diagnostic.CA1301.severity = error
+dotnet_diagnostic.CA1303.severity = none
+dotnet_diagnostic.CA1308.severity = none
+dotnet_diagnostic.CA1400.severity = error
+dotnet_diagnostic.CA1401.severity = error
+dotnet_diagnostic.CA1403.severity = error
+dotnet_diagnostic.CA1404.severity = error
+dotnet_diagnostic.CA1405.severity = error
+dotnet_diagnostic.CA1410.severity = error
+dotnet_diagnostic.CA1415.severity = error
+dotnet_diagnostic.CA1507.severity = error
+dotnet_diagnostic.CA1710.severity = suggestion
+dotnet_diagnostic.CA1724.severity = none
+dotnet_diagnostic.CA1810.severity = none
+dotnet_diagnostic.CA1821.severity = error
+dotnet_diagnostic.CA1900.severity = error
+dotnet_diagnostic.CA1901.severity = error
+dotnet_diagnostic.CA2000.severity = none
+dotnet_diagnostic.CA2002.severity = error
+dotnet_diagnostic.CA2007.severity = none
+dotnet_diagnostic.CA2100.severity = error
+dotnet_diagnostic.CA2101.severity = error
+dotnet_diagnostic.CA2108.severity = error
+dotnet_diagnostic.CA2111.severity = error
+dotnet_diagnostic.CA2112.severity = error
+dotnet_diagnostic.CA2114.severity = error
+dotnet_diagnostic.CA2116.severity = error
+dotnet_diagnostic.CA2117.severity = error
+dotnet_diagnostic.CA2122.severity = error
+dotnet_diagnostic.CA2123.severity = error
+dotnet_diagnostic.CA2124.severity = error
+dotnet_diagnostic.CA2126.severity = error
+dotnet_diagnostic.CA2131.severity = error
+dotnet_diagnostic.CA2132.severity = error
+dotnet_diagnostic.CA2133.severity = error
+dotnet_diagnostic.CA2134.severity = error
+dotnet_diagnostic.CA2137.severity = error
+dotnet_diagnostic.CA2138.severity = error
+dotnet_diagnostic.CA2140.severity = error
+dotnet_diagnostic.CA2141.severity = error
+dotnet_diagnostic.CA2146.severity = error
+dotnet_diagnostic.CA2147.severity = error
+dotnet_diagnostic.CA2149.severity = error
+dotnet_diagnostic.CA2200.severity = error
+dotnet_diagnostic.CA2202.severity = error
+dotnet_diagnostic.CA2207.severity = error
+dotnet_diagnostic.CA2212.severity = error
+dotnet_diagnostic.CA2213.severity = error
+dotnet_diagnostic.CA2214.severity = error
+dotnet_diagnostic.CA2216.severity = error
+dotnet_diagnostic.CA2220.severity = error
+dotnet_diagnostic.CA2229.severity = error
+dotnet_diagnostic.CA2231.severity = error
+dotnet_diagnostic.CA2232.severity = error
+dotnet_diagnostic.CA2235.severity = error
+dotnet_diagnostic.CA2236.severity = error
+dotnet_diagnostic.CA2237.severity = error
+dotnet_diagnostic.CA2238.severity = error
+dotnet_diagnostic.CA2240.severity = error
+dotnet_diagnostic.CA2241.severity = error
+dotnet_diagnostic.CA2242.severity = error
+
+dotnet_diagnostic.CS1701.severity = silent
+
+dotnet_diagnostic.RCS1001.severity = error
+dotnet_diagnostic.RCS1018.severity = error
+dotnet_diagnostic.RCS1037.severity = error
+dotnet_diagnostic.RCS1055.severity = error
+dotnet_diagnostic.RCS1062.severity = error
+dotnet_diagnostic.RCS1066.severity = error
+dotnet_diagnostic.RCS1069.severity = suggestion
+dotnet_diagnostic.RCS1071.severity = error
+dotnet_diagnostic.RCS1074.severity = error
+dotnet_diagnostic.RCS1090.severity = suggestion
+dotnet_diagnostic.RCS1138.severity = error
+dotnet_diagnostic.RCS1139.severity = error
+dotnet_diagnostic.RCS1163.severity = suggestion
+dotnet_diagnostic.RCS1168.severity = suggestion
+dotnet_diagnostic.RCS1188.severity = error
+dotnet_diagnostic.RCS1201.severity = error
+dotnet_diagnostic.RCS1207.severity = error
+dotnet_diagnostic.RCS1211.severity = error
+dotnet_diagnostic.RCS1507.severity = error
+
+dotnet_diagnostic.SA1000.severity = error
+dotnet_diagnostic.SA1001.severity = error
+dotnet_diagnostic.SA1002.severity = error
+dotnet_diagnostic.SA1003.severity = error
+dotnet_diagnostic.SA1004.severity = error
+dotnet_diagnostic.SA1005.severity = error
+dotnet_diagnostic.SA1006.severity = error
+dotnet_diagnostic.SA1007.severity = error
+dotnet_diagnostic.SA1008.severity = error
+dotnet_diagnostic.SA1009.severity = error
+dotnet_diagnostic.SA1010.severity = error
+dotnet_diagnostic.SA1011.severity = error
+dotnet_diagnostic.SA1012.severity = error
+dotnet_diagnostic.SA1013.severity = error
+dotnet_diagnostic.SA1014.severity = error
+dotnet_diagnostic.SA1015.severity = error
+dotnet_diagnostic.SA1016.severity = error
+dotnet_diagnostic.SA1017.severity = error
+dotnet_diagnostic.SA1018.severity = error
+dotnet_diagnostic.SA1019.severity = error
+dotnet_diagnostic.SA1020.severity = error
+dotnet_diagnostic.SA1021.severity = error
+dotnet_diagnostic.SA1022.severity = error
+dotnet_diagnostic.SA1023.severity = error
+dotnet_diagnostic.SA1024.severity = error
+dotnet_diagnostic.SA1025.severity = error
+dotnet_diagnostic.SA1026.severity = error
+dotnet_diagnostic.SA1027.severity = error
+dotnet_diagnostic.SA1028.severity = error
+dotnet_diagnostic.SA1100.severity = error
+dotnet_diagnostic.SA1101.severity = silent
+dotnet_diagnostic.SA1102.severity = error
+dotnet_diagnostic.SA1103.severity = error
+dotnet_diagnostic.SA1104.severity = error
+dotnet_diagnostic.SA1105.severity = error
+dotnet_diagnostic.SA1106.severity = error
+dotnet_diagnostic.SA1107.severity = error
+dotnet_diagnostic.SA1108.severity = error
+dotnet_diagnostic.SA1110.severity = error
+dotnet_diagnostic.SA1111.severity = error
+dotnet_diagnostic.SA1112.severity = error
+dotnet_diagnostic.SA1113.severity = error
+dotnet_diagnostic.SA1114.severity = error
+dotnet_diagnostic.SA1115.severity = error
+dotnet_diagnostic.SA1116.severity = error
+dotnet_diagnostic.SA1117.severity = suggestion
+dotnet_diagnostic.SA1118.severity = error
+dotnet_diagnostic.SA1119.severity = error
+dotnet_diagnostic.SA1120.severity = error
+dotnet_diagnostic.SA1121.severity = error
+dotnet_diagnostic.SA1122.severity = error
+dotnet_diagnostic.SA1123.severity = error
+dotnet_diagnostic.SA1124.severity = error
+dotnet_diagnostic.SA1125.severity = error
+dotnet_diagnostic.SA1127.severity = error
+dotnet_diagnostic.SA1128.severity = error
+dotnet_diagnostic.SA1129.severity = error
+dotnet_diagnostic.SA1130.severity = error
+dotnet_diagnostic.SA1131.severity = error
+dotnet_diagnostic.SA1132.severity = suggestion
+dotnet_diagnostic.SA1133.severity = error
+dotnet_diagnostic.SA1134.severity = error
+dotnet_diagnostic.SA1135.severity = error
+dotnet_diagnostic.SA1136.severity = error
+dotnet_diagnostic.SA1137.severity = error
+dotnet_diagnostic.SA1139.severity = error
+dotnet_diagnostic.SA1200.severity = none
+dotnet_diagnostic.SA1201.severity = suggestion
+dotnet_diagnostic.SA1202.severity = suggestion
+dotnet_diagnostic.SA1203.severity = error
+dotnet_diagnostic.SA1204.severity = suggestion
+dotnet_diagnostic.SA1205.severity = error
+dotnet_diagnostic.SA1206.severity = error
+dotnet_diagnostic.SA1207.severity = error
+dotnet_diagnostic.SA1208.severity = error
+dotnet_diagnostic.SA1209.severity = error
+dotnet_diagnostic.SA1210.severity = error
+dotnet_diagnostic.SA1211.severity = error
+dotnet_diagnostic.SA1212.severity = error
+dotnet_diagnostic.SA1213.severity = error
+dotnet_diagnostic.SA1214.severity = error
+dotnet_diagnostic.SA1216.severity = error
+dotnet_diagnostic.SA1217.severity = error
+dotnet_diagnostic.SA1300.severity = suggestion
+dotnet_diagnostic.SA1302.severity = error
+dotnet_diagnostic.SA1303.severity = error
+dotnet_diagnostic.SA1304.severity = error
+dotnet_diagnostic.SA1306.severity = none
+dotnet_diagnostic.SA1307.severity = error
+dotnet_diagnostic.SA1308.severity = error
+dotnet_diagnostic.SA1309.severity = none
+dotnet_diagnostic.SA1310.severity = error
+dotnet_diagnostic.SA1311.severity = none
+dotnet_diagnostic.SA1312.severity = error
+dotnet_diagnostic.SA1313.severity = error
+dotnet_diagnostic.SA1314.severity = error
+dotnet_diagnostic.SA1316.severity = none
+dotnet_diagnostic.SA1400.severity = error
+dotnet_diagnostic.SA1401.severity = suggestion
+dotnet_diagnostic.SA1402.severity = suggestion
+dotnet_diagnostic.SA1403.severity = error
+dotnet_diagnostic.SA1404.severity = error
+dotnet_diagnostic.SA1405.severity = error
+dotnet_diagnostic.SA1406.severity = error
+dotnet_diagnostic.SA1407.severity = error
+dotnet_diagnostic.SA1408.severity = error
+dotnet_diagnostic.SA1410.severity = error
+dotnet_diagnostic.SA1411.severity = error
+dotnet_diagnostic.SA1413.severity = error
+dotnet_diagnostic.SA1500.severity = error
+dotnet_diagnostic.SA1501.severity = error
+dotnet_diagnostic.SA1502.severity = error
+dotnet_diagnostic.SA1503.severity = error
+dotnet_diagnostic.SA1504.severity = error
+dotnet_diagnostic.SA1505.severity = error
+dotnet_diagnostic.SA1506.severity = error
+dotnet_diagnostic.SA1507.severity = error
+dotnet_diagnostic.SA1508.severity = error
+dotnet_diagnostic.SA1509.severity = error
+dotnet_diagnostic.SA1510.severity = error
+dotnet_diagnostic.SA1511.severity = error
+dotnet_diagnostic.SA1512.severity = error
+dotnet_diagnostic.SA1513.severity = error
+dotnet_diagnostic.SA1514.severity = error
+dotnet_diagnostic.SA1515.severity = error
+dotnet_diagnostic.SA1516.severity = error
+dotnet_diagnostic.SA1517.severity = error
+dotnet_diagnostic.SA1518.severity = error
+dotnet_diagnostic.SA1519.severity = error
+dotnet_diagnostic.SA1520.severity = error
+dotnet_diagnostic.SA1600.severity = suggestion
+dotnet_diagnostic.SA1601.severity = error
+dotnet_diagnostic.SA1602.severity = error
+dotnet_diagnostic.SA1604.severity = error
+dotnet_diagnostic.SA1605.severity = error
+dotnet_diagnostic.SA1606.severity = error
+dotnet_diagnostic.SA1607.severity = error
+dotnet_diagnostic.SA1608.severity = error
+dotnet_diagnostic.SA1610.severity = error
+dotnet_diagnostic.SA1611.severity = error
+dotnet_diagnostic.SA1612.severity = error
+dotnet_diagnostic.SA1613.severity = error
+dotnet_diagnostic.SA1614.severity = error
+dotnet_diagnostic.SA1615.severity = error
+dotnet_diagnostic.SA1616.severity = error
+dotnet_diagnostic.SA1617.severity = error
+dotnet_diagnostic.SA1618.severity = error
+dotnet_diagnostic.SA1619.severity = error
+dotnet_diagnostic.SA1620.severity = error
+dotnet_diagnostic.SA1621.severity = error
+dotnet_diagnostic.SA1622.severity = error
+dotnet_diagnostic.SA1623.severity = error
+dotnet_diagnostic.SA1624.severity = error
+dotnet_diagnostic.SA1625.severity = error
+dotnet_diagnostic.SA1626.severity = error
+dotnet_diagnostic.SA1627.severity = error
+dotnet_diagnostic.SA1629.severity = error
+dotnet_diagnostic.SA1633.severity = none
+dotnet_diagnostic.SA1634.severity = error
+dotnet_diagnostic.SA1635.severity = error
+dotnet_diagnostic.SA1636.severity = none
+dotnet_diagnostic.SA1637.severity = none
+dotnet_diagnostic.SA1638.severity = none
+dotnet_diagnostic.SA1640.severity = error
+dotnet_diagnostic.SA1641.severity = error
+dotnet_diagnostic.SA1642.severity = error
+dotnet_diagnostic.SA1643.severity = error
+dotnet_diagnostic.SA1649.severity = warning
+dotnet_diagnostic.SA1651.severity = error
+
+dotnet_diagnostic.SX1101.severity = none
+dotnet_diagnostic.SX1309.severity = error
+dotnet_diagnostic.SX1623.severity = none
+
+# C++ Files
+[*.{cpp,h,in}]
+curly_bracket_next_line = true
+indent_brace_style = Allman
+
+# Xml project files
+[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}]
+indent_size = 2
+
+# Xml build files
+[*.builds]
+indent_size = 2
+
+# Xml files
+[*.{xml,stylecop,resx,ruleset}]
+indent_size = 2
+
+# Xml config files
+[*.{props,targets,config,nuspec}]
+indent_size = 2
+
+# Shell scripts
+[*.sh]
+end_of_line = lf
+[*.{cmd, bat}]
+end_of_line = crlf
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..9befbbf
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,9 @@
+# Set the default behavior, in case people don't have core.autocrlf set.
+* text=auto
+
+# Explicitly declare text files you want to always be normalized and converted
+# to native line endings on checkout.
+*.cs text
+
+# Declare files that will always have CRLF line endings on checkout.
+*.sln text eol=crlf
\ No newline at end of file
diff --git a/.github/workflows/nuget.yml b/.github/workflows/nuget.yml
new file mode 100644
index 0000000..2c03c08
--- /dev/null
+++ b/.github/workflows/nuget.yml
@@ -0,0 +1,41 @@
+# This workflow will build a .NET project
+# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net
+
+name: .NET
+
+on:
+ push:
+ tags:
+ - "v**"
+
+jobs:
+ build:
+ runs-on: macos-latest
+
+ steps:
+ - uses: actions/checkout@v3
+ - uses: actions/setup-dotnet@v3
+ with:
+ dotnet-version: "8.x"
+ source-url: https://nuget.pkg.github.com/theeightbot/index.json
+ env:
+ NUGET_AUTH_TOKEN: ${{secrets.GITHUB_TOKEN}}
+
+ - name: Install MAUI Workloads
+ run: dotnet workload install maui --ignore-failed-sources
+
+ - name: Semver Parse
+ id: version
+ uses: release-kit/semver@v1.0.10
+
+ - name: Build
+ run: dotnet build MauiDrawer/MauiDrawer.csproj
+
+ - name: Create the package
+ run: dotnet pack --configuration Release /p:AssemblyVersion=${{ steps.version.outputs.major }}.${{ steps.version.outputs.minor }}.${{ steps.version.outputs.patch }} /p:Version=${{ steps.version.outputs.major }}.${{ steps.version.outputs.minor }}.${{ steps.version.outputs.patch }} MauiDrawer/MauiDrawer.csproj
+
+ - name: Publish the package to GPR
+ run: dotnet nuget push MauiDrawer/bin/Release/*.nupkg
+
+ - name: Publish the package to NuGet
+ run: dotnet nuget push MauiDrawer/bin/Release/*.nupkg --api-key "${{ secrets.EIGHTBOT_NUGET_APIKEY }}" --source https://api.nuget.org/v3/index.json
diff --git a/.gitignore b/.gitignore
index 92275db..c422ef8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,405 +1,402 @@
-# globs
-Makefile.in
-*.userprefs
-*.usertasks
-config.make
-config.status
-aclocal.m4
-install-sh
-autom4te.cache/
-*.tar.gz
-tarballs/
-test-results/
-
-# Mac bundle stuff
-*.dmg
-*.app
-
-# content below from: https://github.com/github/gitignore/blob/main/Global/macOS.gitignore
-# General
-.DS_Store
-.AppleDouble
-.LSOverride
-
-# Icon must end with two \r
-Icon
-
-
-# Thumbnails
-._*
-
-# Files that might appear in the root of a volume
-.DocumentRevisions-V100
-.fseventsd
-.Spotlight-V100
-.TemporaryItems
-.Trashes
-.VolumeIcon.icns
-.com.apple.timemachine.donotpresent
-
-# Directories potentially created on remote AFP share
-.AppleDB
-.AppleDesktop
-Network Trash Folder
-Temporary Items
-.apdisk
-
-# content below from: https://github.com/github/gitignore/blob/main/Global/Windows.gitignore
-# Windows thumbnail cache files
-Thumbs.db
-ehthumbs.db
-ehthumbs_vista.db
-
-# Dump file
-*.stackdump
-
-# Folder config file
-[Dd]esktop.ini
-
-# Recycle Bin used on file shares
-$RECYCLE.BIN/
-
-# Windows Installer files
-*.cab
-*.msi
-*.msix
-*.msm
-*.msp
-
-# Windows shortcuts
-*.lnk
-
-# content below from: https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
-## Ignore Visual Studio temporary files, build results, and
-## files generated by popular Visual Studio add-ons.
-##
-## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
-
-# User-specific files
-*.suo
-*.user
-*.userosscache
-*.sln.docstates
-
-# User-specific files (MonoDevelop/Xamarin Studio)
-*.userprefs
-
-# Build results
-[Dd]ebug/
-[Dd]ebugPublic/
-[Rr]elease/
-[Rr]eleases/
-x64/
-x86/
-bld/
-[Bb]in/
-[Oo]bj/
-[Ll]og/
-
-# Visual Studio 2015/2017 cache/options directory
-.vs/
-# Uncomment if you have tasks that create the project's static files in wwwroot
-#wwwroot/
-
-# Visual Studio 2017 auto generated files
-Generated\ Files/
-
-# MSTest test Results
-[Tt]est[Rr]esult*/
-[Bb]uild[Ll]og.*
-
-# NUNIT
-*.VisualState.xml
-TestResult.xml
-
-# Build Results of an ATL Project
-[Dd]ebugPS/
-[Rr]eleasePS/
-dlldata.c
-
-# Benchmark Results
-BenchmarkDotNet.Artifacts/
-
-# .NET Core
-project.lock.json
-project.fragment.lock.json
-artifacts/
-
-# StyleCop
-StyleCopReport.xml
-
-# Files built by Visual Studio
-*_i.c
-*_p.c
-*_h.h
-*.ilk
-*.meta
-*.obj
-*.iobj
-*.pch
-*.pdb
-*.ipdb
-*.pgc
-*.pgd
-*.rsp
-*.sbr
-*.tlb
-*.tli
-*.tlh
-*.tmp
-*.tmp_proj
-*_wpftmp.csproj
-*.log
-*.vspscc
-*.vssscc
-.builds
-*.pidb
-*.svclog
-*.scc
-
-# Chutzpah Test files
-_Chutzpah*
-
-# Visual C++ cache files
-ipch/
-*.aps
-*.ncb
-*.opendb
-*.opensdf
-*.sdf
-*.cachefile
-*.VC.db
-*.VC.VC.opendb
-
-# Visual Studio profiler
-*.psess
-*.vsp
-*.vspx
-*.sap
-
-# Visual Studio Trace Files
-*.e2e
-
-# TFS 2012 Local Workspace
-$tf/
-
-# Guidance Automation Toolkit
-*.gpState
-
-# ReSharper is a .NET coding add-in
-_ReSharper*/
-*.[Rr]e[Ss]harper
-*.DotSettings.user
-
-# JustCode is a .NET coding add-in
-.JustCode
-
-# TeamCity is a build add-in
-_TeamCity*
-
-# DotCover is a Code Coverage Tool
-*.dotCover
-
-# AxoCover is a Code Coverage Tool
-.axoCover/*
-!.axoCover/settings.json
-
-# Visual Studio code coverage results
-*.coverage
-*.coveragexml
-
-# NCrunch
-_NCrunch_*
-.*crunch*.local.xml
-nCrunchTemp_*
-
-# MightyMoose
-*.mm.*
-AutoTest.Net/
-
-# Web workbench (sass)
-.sass-cache/
-
-# Installshield output folder
-[Ee]xpress/
-
-# DocProject is a documentation generator add-in
-DocProject/buildhelp/
-DocProject/Help/*.HxT
-DocProject/Help/*.HxC
-DocProject/Help/*.hhc
-DocProject/Help/*.hhk
-DocProject/Help/*.hhp
-DocProject/Help/Html2
-DocProject/Help/html
-
-# Click-Once directory
-publish/
-
-# Publish Web Output
-*.[Pp]ublish.xml
-*.azurePubxml
-# Note: Comment the next line if you want to checkin your web deploy settings,
-# but database connection strings (with potential passwords) will be unencrypted
-*.pubxml
-*.publishproj
-
-# Microsoft Azure Web App publish settings. Comment the next line if you want to
-# checkin your Azure Web App publish settings, but sensitive information contained
-# in these scripts will be unencrypted
-PublishScripts/
-
-# NuGet Packages
-*.nupkg
-# The packages folder can be ignored because of Package Restore
-**/[Pp]ackages/*
-# except build/, which is used as an MSBuild target.
-!**/[Pp]ackages/build/
-# Uncomment if necessary however generally it will be regenerated when needed
-#!**/[Pp]ackages/repositories.config
-# NuGet v3's project.json files produces more ignorable files
-*.nuget.props
-*.nuget.targets
-
-# Microsoft Azure Build Output
-csx/
-*.build.csdef
-
-# Microsoft Azure Emulator
-ecf/
-rcf/
-
-# Windows Store app package directories and files
-AppPackages/
-BundleArtifacts/
-Package.StoreAssociation.xml
-_pkginfo.txt
-*.appx
-
-# Visual Studio cache files
-# files ending in .cache can be ignored
-*.[Cc]ache
-# but keep track of directories ending in .cache
-!*.[Cc]ache/
-
-# Others
-ClientBin/
-~$*
-*~
-*.dbmdl
-*.dbproj.schemaview
-*.jfm
-*.pfx
-*.publishsettings
-orleans.codegen.cs
-
-# Including strong name files can present a security risk
-# (https://github.com/github/gitignore/pull/2483#issue-259490424)
-#*.snk
-
-# Since there are multiple workflows, uncomment next line to ignore bower_components
-# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
-#bower_components/
-
-# RIA/Silverlight projects
-Generated_Code/
-
-# Backup & report files from converting an old project file
-# to a newer Visual Studio version. Backup files are not needed,
-# because we have git ;-)
-_UpgradeReport_Files/
-Backup*/
-UpgradeLog*.XML
-UpgradeLog*.htm
-ServiceFabricBackup/
-*.rptproj.bak
-
-# SQL Server files
-*.mdf
-*.ldf
-*.ndf
-
-# Business Intelligence projects
-*.rdl.data
-*.bim.layout
-*.bim_*.settings
-*.rptproj.rsuser
-
-# Microsoft Fakes
-FakesAssemblies/
-
-# GhostDoc plugin setting file
-*.GhostDoc.xml
-
-# Node.js Tools for Visual Studio
-.ntvs_analysis.dat
-node_modules/
-
-# Visual Studio 6 build log
-*.plg
-
-# Visual Studio 6 workspace options file
-*.opt
-
-# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
-*.vbw
-
-# Visual Studio LightSwitch build output
-**/*.HTMLClient/GeneratedArtifacts
-**/*.DesktopClient/GeneratedArtifacts
-**/*.DesktopClient/ModelManifest.xml
-**/*.Server/GeneratedArtifacts
-**/*.Server/ModelManifest.xml
-_Pvt_Extensions
-
-# Paket dependency manager
-.paket/paket.exe
-paket-files/
-
-# FAKE - F# Make
-.fake/
-
-# JetBrains Rider
-.idea/
-*.sln.iml
-
-# CodeRush personal settings
-.cr/personal
-
-# Python Tools for Visual Studio (PTVS)
-__pycache__/
-*.pyc
-
-# Cake - Uncomment if you are using it
-# tools/**
-# !tools/packages.config
-
-# Tabs Studio
-*.tss
-
-# Telerik's JustMock configuration file
-*.jmconfig
-
-# BizTalk build output
-*.btp.cs
-*.btm.cs
-*.odx.cs
-*.xsd.cs
-
-# OpenCover UI analysis results
-OpenCover/
-
-# Azure Stream Analytics local run output
-ASALocalRun/
-
-# MSBuild Binary and Structured Log
-*.binlog
-
-# NVidia Nsight GPU debugger configuration file
-*.nvuser
-
-# MFractors (Xamarin productivity tool) working folder
-.mfractor/
-
-# Local History for Visual Studio
-.localhistory/
\ No newline at end of file
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+##
+## Get latest from https://github.com/github/gitignore/blob/main/VisualStudio.gitignore
+
+# User-specific files
+*.rsuser
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+
+# User-specific files (MonoDevelop/Xamarin Studio)
+*.userprefs
+
+# Mono auto generated files
+mono_crash.*
+
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+[Ww][Ii][Nn]32/
+[Aa][Rr][Mm]/
+[Aa][Rr][Mm]64/
+bld/
+[Bb]in/
+[Oo]bj/
+[Ll]og/
+[Ll]ogs/
+
+# Visual Studio 2015/2017 cache/options directory
+.vs/
+# Uncomment if you have tasks that create the project's static files in wwwroot
+#wwwroot/
+
+# Visual Studio 2017 auto generated files
+Generated\ Files/
+
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+
+# NUnit
+*.VisualState.xml
+TestResult.xml
+nunit-*.xml
+
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+
+# Benchmark Results
+BenchmarkDotNet.Artifacts/
+
+# .NET Core
+project.lock.json
+project.fragment.lock.json
+artifacts/
+
+# ASP.NET Scaffolding
+ScaffoldingReadMe.txt
+
+# StyleCop
+StyleCopReport.xml
+
+# Files built by Visual Studio
+*_i.c
+*_p.c
+*_h.h
+*.ilk
+*.meta
+*.obj
+*.iobj
+*.pch
+*.pdb
+*.ipdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*_wpftmp.csproj
+*.log
+*.tlog
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+
+# Chutzpah Test files
+_Chutzpah*
+
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opendb
+*.opensdf
+*.sdf
+*.cachefile
+*.VC.db
+*.VC.VC.opendb
+
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+*.sap
+
+# Visual Studio Trace Files
+*.e2e
+
+# TFS 2012 Local Workspace
+$tf/
+
+# Guidance Automation Toolkit
+*.gpState
+
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+
+# TeamCity is a build add-in
+_TeamCity*
+
+# DotCover is a Code Coverage Tool
+*.dotCover
+
+# AxoCover is a Code Coverage Tool
+.axoCover/*
+!.axoCover/settings.json
+
+# Coverlet is a free, cross platform Code Coverage Tool
+coverage*.json
+coverage*.xml
+coverage*.info
+
+# Visual Studio code coverage results
+*.coverage
+*.coveragexml
+
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+nCrunchTemp_*
+
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+
+# Web workbench (sass)
+.sass-cache/
+
+# Installshield output folder
+[Ee]xpress/
+
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+
+# Click-Once directory
+publish/
+
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# Note: Comment the next line if you want to checkin your web deploy settings,
+# but database connection strings (with potential passwords) will be unencrypted
+*.pubxml
+*.publishproj
+
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
+# checkin your Azure Web App publish settings, but sensitive information contained
+# in these scripts will be unencrypted
+PublishScripts/
+
+# NuGet Packages
+*.nupkg
+# NuGet Symbol Packages
+*.snupkg
+# The packages folder can be ignored because of Package Restore
+**/[Pp]ackages/*
+# except build/, which is used as an MSBuild target.
+!**/[Pp]ackages/build/
+# Uncomment if necessary however generally it will be regenerated when needed
+#!**/[Pp]ackages/repositories.config
+# NuGet v3's project.json files produces more ignorable files
+*.nuget.props
+*.nuget.targets
+
+# Microsoft Azure Build Output
+csx/
+*.build.csdef
+
+# Microsoft Azure Emulator
+ecf/
+rcf/
+
+# Windows Store app package directories and files
+AppPackages/
+BundleArtifacts/
+Package.StoreAssociation.xml
+_pkginfo.txt
+*.appx
+*.appxbundle
+*.appxupload
+
+# Visual Studio cache files
+# files ending in .cache can be ignored
+*.[Cc]ache
+# but keep track of directories ending in .cache
+!?*.[Cc]ache/
+
+# Others
+ClientBin/
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.jfm
+*.pfx
+*.publishsettings
+orleans.codegen.cs
+
+# Including strong name files can present a security risk
+# (https://github.com/github/gitignore/pull/2483#issue-259490424)
+#*.snk
+
+# Since there are multiple workflows, uncomment next line to ignore bower_components
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
+#bower_components/
+
+# RIA/Silverlight projects
+Generated_Code/
+
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+ServiceFabricBackup/
+*.rptproj.bak
+
+# SQL Server files
+*.mdf
+*.ldf
+*.ndf
+
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+*.rptproj.rsuser
+*- [Bb]ackup.rdl
+*- [Bb]ackup ([0-9]).rdl
+*- [Bb]ackup ([0-9][0-9]).rdl
+
+# Microsoft Fakes
+FakesAssemblies/
+
+# GhostDoc plugin setting file
+*.GhostDoc.xml
+
+# Node.js Tools for Visual Studio
+.ntvs_analysis.dat
+node_modules/
+
+# Visual Studio 6 build log
+*.plg
+
+# Visual Studio 6 workspace options file
+*.opt
+
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
+*.vbw
+
+# Visual Studio 6 auto-generated project file (contains which files were open etc.)
+*.vbp
+
+# Visual Studio 6 workspace and project file (working project files containing files to include in project)
+*.dsw
+*.dsp
+
+# Visual Studio 6 technical files
+*.ncb
+*.aps
+
+# Visual Studio LightSwitch build output
+**/*.HTMLClient/GeneratedArtifacts
+**/*.DesktopClient/GeneratedArtifacts
+**/*.DesktopClient/ModelManifest.xml
+**/*.Server/GeneratedArtifacts
+**/*.Server/ModelManifest.xml
+_Pvt_Extensions
+
+# Paket dependency manager
+.paket/paket.exe
+paket-files/
+
+# FAKE - F# Make
+.fake/
+
+# CodeRush personal settings
+.cr/personal
+
+# Python Tools for Visual Studio (PTVS)
+__pycache__/
+*.pyc
+
+# Cake - Uncomment if you are using it
+# tools/**
+# !tools/packages.config
+
+# Tabs Studio
+*.tss
+
+# Telerik's JustMock configuration file
+*.jmconfig
+
+# BizTalk build output
+*.btp.cs
+*.btm.cs
+*.odx.cs
+*.xsd.cs
+
+# OpenCover UI analysis results
+OpenCover/
+
+# Azure Stream Analytics local run output
+ASALocalRun/
+
+# MSBuild Binary and Structured Log
+*.binlog
+
+# NVidia Nsight GPU debugger configuration file
+*.nvuser
+
+# MFractors (Xamarin productivity tool) working folder
+.mfractor/
+
+# Local History for Visual Studio
+.localhistory/
+
+# Visual Studio History (VSHistory) files
+.vshistory/
+
+# BeatPulse healthcheck temp database
+healthchecksdb
+
+# Backup folder for Package Reference Convert tool in Visual Studio 2017
+MigrationBackup/
+
+# Ionide (cross platform F# VS Code tools) working folder
+.ionide/
+
+# Fody - auto-generated XML schema
+FodyWeavers.xsd
+
+# VS Code files for those working on multiple tools
+.vscode/*
+!.vscode/settings.json
+!.vscode/tasks.json
+!.vscode/launch.json
+!.vscode/extensions.json
+*.code-workspace
+
+# Local History for Visual Studio Code
+.history/
+
+# Windows Installer files from build outputs
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# JetBrains Rider
+*.sln.iml
+
+*.DS_Store
+
+.idea/
diff --git a/Directory.build.props b/Directory.build.props
new file mode 100644
index 0000000..dea30e0
--- /dev/null
+++ b/Directory.build.props
@@ -0,0 +1,35 @@
+
+
+ true
+ latest
+ $(NoWarn);CS1591
+
+
+ https://eight.bot
+ https://github.com/TheEightBot/Componentizer4k
+ git
+ .NET MAUI;MVVM;Navigation;Component;UI Control;Eight-Bot
+ A bottom drawer or bottom sheet-like component for .NET MAUI.
+ logo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..1741fee
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 Eight-Bot
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/MauiDrawer.Sample/App.xaml.cs b/MauiDrawer.Sample/App.xaml.cs
index 53fce42..0340c7e 100644
--- a/MauiDrawer.Sample/App.xaml.cs
+++ b/MauiDrawer.Sample/App.xaml.cs
@@ -2,11 +2,10 @@
public partial class App : Application
{
- public App()
- {
- InitializeComponent();
+ public App()
+ {
+ InitializeComponent();
- MainPage = new AppShell();
- }
+ MainPage = new AppShell();
+ }
}
-
diff --git a/MauiDrawer.Sample/AppShell.xaml.cs b/MauiDrawer.Sample/AppShell.xaml.cs
index fbaf8e1..0691e2f 100644
--- a/MauiDrawer.Sample/AppShell.xaml.cs
+++ b/MauiDrawer.Sample/AppShell.xaml.cs
@@ -2,9 +2,8 @@
public partial class AppShell : Shell
{
- public AppShell()
- {
- InitializeComponent();
- }
+ public AppShell()
+ {
+ InitializeComponent();
+ }
}
-
diff --git a/MauiDrawer.Sample/MainPage.xaml b/MauiDrawer.Sample/MainPage.xaml
index 2592921..5dec66f 100644
--- a/MauiDrawer.Sample/MainPage.xaml
+++ b/MauiDrawer.Sample/MainPage.xaml
@@ -2,13 +2,29 @@
+ x:Class="MauiDrawer.Sample.MainPage"
+ >
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MauiDrawer.Sample/MainPage.xaml.cs b/MauiDrawer.Sample/MainPage.xaml.cs
index 868f8e1..634d772 100644
--- a/MauiDrawer.Sample/MainPage.xaml.cs
+++ b/MauiDrawer.Sample/MainPage.xaml.cs
@@ -2,12 +2,33 @@
public partial class MainPage : ContentPage
{
- int count = 0;
+ private readonly int _count = 0;
- public MainPage()
- {
- InitializeComponent();
- }
-}
+ public MainPage()
+ {
+ InitializeComponent();
+ }
+
+ private int _incrementer = 0;
+
+ private void Button_Clicked(object sender, System.EventArgs e)
+ {
+ _incrementer++;
+ (sender as Button).Text = $"Tapped {_incrementer} Times";
+ }
+ private void Dismiss_Clicked(object sender, System.EventArgs e)
+ {
+ MainDrawer.Dismiss();
+ }
+ private void Switch_Toggled(object sender, Microsoft.Maui.Controls.ToggledEventArgs e)
+ {
+ MainDrawer.AllowDismiss = !MainDrawer.AllowDismiss;
+ }
+
+ private void Show_Clicked(object sender, System.EventArgs e)
+ {
+ MainDrawer.Display(.65d);
+ }
+}
diff --git a/MauiDrawer.Sample/MauiDrawer.Sample.csproj b/MauiDrawer.Sample/MauiDrawer.Sample.csproj
index bd45052..fe4f844 100644
--- a/MauiDrawer.Sample/MauiDrawer.Sample.csproj
+++ b/MauiDrawer.Sample/MauiDrawer.Sample.csproj
@@ -38,6 +38,9 @@
6.5
+
+ false
+
diff --git a/MauiDrawer.Sample/MauiProgram.cs b/MauiDrawer.Sample/MauiProgram.cs
index 291137d..573757f 100644
--- a/MauiDrawer.Sample/MauiProgram.cs
+++ b/MauiDrawer.Sample/MauiProgram.cs
@@ -4,22 +4,21 @@ namespace MauiDrawer.Sample;
public static class MauiProgram
{
- public static MauiApp CreateMauiApp()
- {
- var builder = MauiApp.CreateBuilder();
- builder
- .UseMauiApp()
- .ConfigureFonts(fonts =>
- {
- fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
- fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
- });
+ public static MauiApp CreateMauiApp()
+ {
+ var builder = MauiApp.CreateBuilder();
+ builder
+ .UseMauiApp()
+ .ConfigureFonts(fonts =>
+ {
+ fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
+ fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
+ });
#if DEBUG
- builder.Logging.AddDebug();
+ builder.Logging.AddDebug();
#endif
- return builder.Build();
- }
+ return builder.Build();
+ }
}
-
diff --git a/MauiDrawer.Sample/Platforms/Android/MainActivity.cs b/MauiDrawer.Sample/Platforms/Android/MainActivity.cs
index dcf8651..5859a1e 100644
--- a/MauiDrawer.Sample/Platforms/Android/MainActivity.cs
+++ b/MauiDrawer.Sample/Platforms/Android/MainActivity.cs
@@ -8,4 +8,3 @@ namespace MauiDrawer.Sample;
public class MainActivity : MauiAppCompatActivity
{
}
-
diff --git a/MauiDrawer.Sample/Platforms/Android/MainApplication.cs b/MauiDrawer.Sample/Platforms/Android/MainApplication.cs
index 9ccb3fc..93974cd 100644
--- a/MauiDrawer.Sample/Platforms/Android/MainApplication.cs
+++ b/MauiDrawer.Sample/Platforms/Android/MainApplication.cs
@@ -6,11 +6,10 @@ namespace MauiDrawer.Sample;
[Application]
public class MainApplication : MauiApplication
{
- public MainApplication(IntPtr handle, JniHandleOwnership ownership)
- : base(handle, ownership)
- {
- }
+ public MainApplication(IntPtr handle, JniHandleOwnership ownership)
+ : base(handle, ownership)
+ {
+ }
- protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}
-
diff --git a/MauiDrawer.Sample/Platforms/MacCatalyst/AppDelegate.cs b/MauiDrawer.Sample/Platforms/MacCatalyst/AppDelegate.cs
index e8c21c1..f585b7b 100644
--- a/MauiDrawer.Sample/Platforms/MacCatalyst/AppDelegate.cs
+++ b/MauiDrawer.Sample/Platforms/MacCatalyst/AppDelegate.cs
@@ -5,6 +5,5 @@ namespace MauiDrawer.Sample;
[Register("AppDelegate")]
public class AppDelegate : MauiUIApplicationDelegate
{
- protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}
-
diff --git a/MauiDrawer.Sample/Platforms/MacCatalyst/Program.cs b/MauiDrawer.Sample/Platforms/MacCatalyst/Program.cs
index 31df732..c7a313b 100644
--- a/MauiDrawer.Sample/Platforms/MacCatalyst/Program.cs
+++ b/MauiDrawer.Sample/Platforms/MacCatalyst/Program.cs
@@ -3,14 +3,13 @@
namespace MauiDrawer.Sample;
-public class Program
+public static class Program
{
- // This is the main entry point of the application.
- static void Main(string[] args)
- {
- // if you want to use a different Application Delegate class from "AppDelegate"
- // you can specify it here.
- UIApplication.Main(args, null, typeof(AppDelegate));
- }
+ // This is the main entry point of the application.
+ private static void Main(string[] args)
+ {
+ // if you want to use a different Application Delegate class from "AppDelegate"
+ // you can specify it here.
+ UIApplication.Main(args, null, typeof(AppDelegate));
+ }
}
-
diff --git a/MauiDrawer.Sample/Platforms/iOS/AppDelegate.cs b/MauiDrawer.Sample/Platforms/iOS/AppDelegate.cs
index e8c21c1..f585b7b 100644
--- a/MauiDrawer.Sample/Platforms/iOS/AppDelegate.cs
+++ b/MauiDrawer.Sample/Platforms/iOS/AppDelegate.cs
@@ -5,6 +5,5 @@ namespace MauiDrawer.Sample;
[Register("AppDelegate")]
public class AppDelegate : MauiUIApplicationDelegate
{
- protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
+ protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}
-
diff --git a/MauiDrawer.Sample/Platforms/iOS/Program.cs b/MauiDrawer.Sample/Platforms/iOS/Program.cs
index 31df732..c7a313b 100644
--- a/MauiDrawer.Sample/Platforms/iOS/Program.cs
+++ b/MauiDrawer.Sample/Platforms/iOS/Program.cs
@@ -3,14 +3,13 @@
namespace MauiDrawer.Sample;
-public class Program
+public static class Program
{
- // This is the main entry point of the application.
- static void Main(string[] args)
- {
- // if you want to use a different Application Delegate class from "AppDelegate"
- // you can specify it here.
- UIApplication.Main(args, null, typeof(AppDelegate));
- }
+ // This is the main entry point of the application.
+ private static void Main(string[] args)
+ {
+ // if you want to use a different Application Delegate class from "AppDelegate"
+ // you can specify it here.
+ UIApplication.Main(args, null, typeof(AppDelegate));
+ }
}
-
diff --git a/MauiDrawer.sln b/MauiDrawer.sln
index 5dc41c9..f5fa5df 100644
--- a/MauiDrawer.sln
+++ b/MauiDrawer.sln
@@ -1,31 +1,49 @@
-
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio Version 16
-VisualStudioVersion = 25.0.1706.7
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MauiDrawer", "MauiDrawer\MauiDrawer.csproj", "{C3ED6C8E-641F-4AD0-B090-816868DFC85A}"
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MauiDrawer.Sample", "MauiDrawer.Sample\MauiDrawer.Sample.csproj", "{D1551D4C-6395-4FA9-A849-52D7110913BD}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {C3ED6C8E-641F-4AD0-B090-816868DFC85A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {C3ED6C8E-641F-4AD0-B090-816868DFC85A}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {C3ED6C8E-641F-4AD0-B090-816868DFC85A}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {C3ED6C8E-641F-4AD0-B090-816868DFC85A}.Release|Any CPU.Build.0 = Release|Any CPU
- {D1551D4C-6395-4FA9-A849-52D7110913BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {D1551D4C-6395-4FA9-A849-52D7110913BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {D1551D4C-6395-4FA9-A849-52D7110913BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {D1551D4C-6395-4FA9-A849-52D7110913BD}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {E3F910E2-2904-4059-9369-543EAFBB01AE}
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 25.0.1706.7
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MauiDrawer", "MauiDrawer\MauiDrawer.csproj", "{C3ED6C8E-641F-4AD0-B090-816868DFC85A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MauiDrawer.Sample", "MauiDrawer.Sample\MauiDrawer.Sample.csproj", "{D1551D4C-6395-4FA9-A849-52D7110913BD}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "[ Actions ]", "[ Actions ]", "{2BBE5391-A783-4CAB-80B6-5FEF32AF7663}"
+ ProjectSection(SolutionItems) = preProject
+ .github\workflows\nuget.yml = .github\workflows\nuget.yml
+ EndProjectSection
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "[ Solution Items ]", "[ Solution Items ]", "{0FDCE5C6-6D4A-40E6-9C01-94EAC8AA0D97}"
+ ProjectSection(SolutionItems) = preProject
+ README.md = README.md
+ .gitignore = .gitignore
+ stylecop.json = stylecop.json
+ global.json = global.json
+ LICENSE = LICENSE
+ Directory.build.props = Directory.build.props
+ .gitattributes = .gitattributes
+ .editorconfig = .editorconfig
+ MauiDrawer.sln = MauiDrawer.sln
+ EndProjectSection
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C3ED6C8E-641F-4AD0-B090-816868DFC85A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C3ED6C8E-641F-4AD0-B090-816868DFC85A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C3ED6C8E-641F-4AD0-B090-816868DFC85A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C3ED6C8E-641F-4AD0-B090-816868DFC85A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D1551D4C-6395-4FA9-A849-52D7110913BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D1551D4C-6395-4FA9-A849-52D7110913BD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D1551D4C-6395-4FA9-A849-52D7110913BD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D1551D4C-6395-4FA9-A849-52D7110913BD}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {E3F910E2-2904-4059-9369-543EAFBB01AE}
+ EndGlobalSection
+EndGlobal
diff --git a/MauiDrawer/Drawer.cs b/MauiDrawer/MauiDrawer.cs
similarity index 61%
rename from MauiDrawer/Drawer.cs
rename to MauiDrawer/MauiDrawer.cs
index 5261155..0883b9c 100644
--- a/MauiDrawer/Drawer.cs
+++ b/MauiDrawer/MauiDrawer.cs
@@ -1,4 +1,6 @@
-using Microsoft.Maui.Controls.Shapes;
+using Microsoft.Maui.Controls.PlatformConfiguration;
+using Microsoft.Maui.Controls.PlatformConfiguration.iOSSpecific;
+using Microsoft.Maui.Controls.Shapes;
namespace MauiDrawer;
@@ -18,7 +20,7 @@ public struct DrawerStop
[ContentProperty(nameof(DrawerContent))]
public class Drawer : Grid
{
- private readonly double TouchBarHeight = 32d;
+ private readonly double _touchBarHeight = 32d;
private readonly BoxView _touchOverlay;
@@ -64,17 +66,25 @@ public View DrawerContent
set => SetValue(DrawerContentProperty, value);
}
+ public static BindableProperty AllowDismissProperty =
+ BindableProperty.Create(nameof(AllowDismiss), typeof(bool), typeof(Drawer), false);
+
+ public bool AllowDismiss
+ {
+ get => (bool)GetValue(AllowDismissProperty);
+ set => SetValue(AllowDismissProperty, value);
+ }
+
public static BindableProperty DrawerColorProperty =
BindableProperty.Create(nameof(DrawerColor), typeof(Color), typeof(Drawer), Colors.White,
propertyChanged:
- (bindable, oldValue, newValue) =>
+ (bindable, _, newValue) =>
{
if (bindable is not Drawer drawer)
{
return;
}
-
if (newValue is Color newColor)
{
drawer._mainContainer.BackgroundColor = newColor;
@@ -89,6 +99,9 @@ public Color DrawerColor
public Drawer()
{
+ this.CascadeInputTransparent = false;
+ this.InputTransparent = true;
+
_drawerStops.Add(new DrawerStop { Measurement = DrawerStopMeasurement.Fixed, Value = 0 });
_drawerStops.Add(new DrawerStop { Measurement = DrawerStopMeasurement.Percentage, Value = .33 });
_drawerStops.Add(new DrawerStop { Measurement = DrawerStopMeasurement.Percentage, Value = .66 });
@@ -98,9 +111,9 @@ public Drawer()
new RoundRectangle
{
HeightRequest = 4,
- WidthRequest = TouchBarHeight,
+ WidthRequest = _touchBarHeight,
CornerRadius = 2,
- BackgroundColor = Colors.DarkGray,
+ BackgroundColor = Colors.DarkGray,
HorizontalOptions = LayoutOptions.Center,
};
@@ -113,7 +126,7 @@ public Drawer()
},
RowDefinitions =
{
- new RowDefinition(TouchBarHeight),
+ new RowDefinition(_touchBarHeight),
new RowDefinition(GridLength.Star),
},
};
@@ -141,7 +154,7 @@ public Drawer()
{
GestureRecognizers = { _touchOverlayPanGesture },
BackgroundColor = Colors.Transparent,
- HeightRequest = TouchBarHeight,
+ HeightRequest = _touchBarHeight,
VerticalOptions = LayoutOptions.Start,
};
@@ -149,6 +162,84 @@ public Drawer()
this.Children.Add(_touchOverlay);
}
+ public void Dismiss()
+ {
+ _touchOverlay.GestureRecognizers.Clear();
+
+ var visibleHeight = this.Height;
+
+ var allowDismiss = AllowDismiss;
+
+ var bottomSafeArea = allowDismiss ? this.ParentPage()?.On()?.SafeAreaInsets().Bottom ?? 0 : 0;
+
+ var touchBarDisplayHeight = allowDismiss ? 0 : _touchBarHeight;
+
+ var dismissAnimation =
+ new Animation(
+ x =>
+ {
+ _mainContainer.TranslationY = x;
+ _mainContainer.Padding = new Thickness(_mainContainer.Margin.Left, _mainContainer.Margin.Top, _mainContainer.Margin.Right, x);
+ },
+ _mainContainer.TranslationY,
+ visibleHeight + bottomSafeArea - touchBarDisplayHeight,
+ Easing.SinInOut);
+
+ dismissAnimation
+ .Commit(
+ this,
+ nameof(Dismiss),
+ finished:
+ (_, __) =>
+ {
+ Dispatcher.Dispatch(
+ () =>
+ {
+ _touchOverlay.TranslationY = _mainContainer.TranslationY;
+ _touchOverlay.GestureRecognizers.Add(_touchOverlayPanGesture);
+ });
+ });
+ }
+
+ public void Display(double displayPercentage)
+ {
+ _touchOverlay.GestureRecognizers.Clear();
+
+ var visibleHeight = this.Height;
+
+ var allowDismiss = AllowDismiss;
+
+ var bottomSafeArea = allowDismiss ? this.ParentPage()?.On()?.SafeAreaInsets().Bottom ?? 0 : 0;
+
+ var touchBarDisplayHeight = allowDismiss ? 0 : _touchBarHeight;
+
+ var dismissAnimation =
+ new Animation(
+ x =>
+ {
+ _mainContainer.TranslationY = x;
+ _mainContainer.Padding = new Thickness(_mainContainer.Margin.Left, _mainContainer.Margin.Top, _mainContainer.Margin.Right, x);
+ },
+ _mainContainer.TranslationY,
+ (visibleHeight * (1d - Math.Max(Math.Min(displayPercentage, 1.0d), 0d))) - touchBarDisplayHeight,
+ Easing.SinInOut);
+
+ dismissAnimation
+ .Commit(
+ this,
+ nameof(Dismiss),
+ finished:
+ (_, __) =>
+ {
+ Dispatcher.Dispatch(
+ () =>
+ {
+ _touchOverlay.TranslationY = _mainContainer.TranslationY;
+ _touchOverlay.GestureRecognizers.Add(_touchOverlayPanGesture);
+ });
+ });
+ }
+
protected override void OnParentChanging(ParentChangingEventArgs args)
{
base.OnParentChanging(args);
@@ -163,22 +254,30 @@ protected override void OnParentChanging(ParentChangingEventArgs args)
private void _touchOverlayPanGesture_PanUpdated(object? sender, PanUpdatedEventArgs e)
{
- if (this.Parent is not VisualElement visualParent)
+ var parentPage = this.ParentPage();
+
+ if (parentPage is null)
{
return;
}
- var visibleParentHeight = this.Height;
+ var visibleHeight = this.Height;
var totalTranslation = this._drawerStartingTranslationY + e.TotalY;
+ var allowDismiss = AllowDismiss;
+
+ var bottomSafeArea = allowDismiss ? this.ParentPage()?.On()?.SafeAreaInsets().Bottom ?? 0 : 0;
+
+ var touchBarDisplayHeight = allowDismiss ? 0 : _touchBarHeight;
+
switch (e.StatusType)
{
case GestureStatus.Started:
_drawerStartingTranslationY = _mainContainer.TranslationY;
break;
case GestureStatus.Running:
- var clampedTranslation = totalTranslation.Clamp(0, visibleParentHeight - TouchBarHeight);
+ var clampedTranslation = totalTranslation.Clamp(0, visibleHeight - touchBarDisplayHeight);
_mainContainer.TranslationY = clampedTranslation;
_mainContainer.Padding = new Thickness(_mainContainer.Margin.Left, _mainContainer.Margin.Top, _mainContainer.Margin.Right, clampedTranslation);
break;
@@ -190,16 +289,16 @@ private void _touchOverlayPanGesture_PanUpdated(object? sender, PanUpdatedEventA
var closestDrawerStop =
_drawerStops
.Select(
- (x, i) =>
+ (x) =>
{
var position =
x.Measurement switch
{
- DrawerStopMeasurement.Fixed => x.Value,
- DrawerStopMeasurement.Percentage => visibleParentHeight * x.Value,
+ DrawerStopMeasurement.Percentage => visibleHeight * x.Value,
+ _ => x.Value,
};
- return (DrawerStop: x, Index: i, Position: position, Distance: Math.Abs(currTranslationY - position));
+ return (DrawerStop: x, Position: position, Distance: Math.Abs(currTranslationY - position));
})
.OrderBy(x => x.Distance)
.FirstOrDefault();
@@ -214,14 +313,14 @@ private void _touchOverlayPanGesture_PanUpdated(object? sender, PanUpdatedEventA
_mainContainer.Padding = new Thickness(_mainContainer.Margin.Left, _mainContainer.Margin.Top, _mainContainer.Margin.Right, x);
},
_mainContainer.TranslationY,
- closestDrawerStop.Position.Clamp(0, visibleParentHeight - TouchBarHeight),
+ closestDrawerStop.Position.Clamp(0, visibleHeight + bottomSafeArea - touchBarDisplayHeight),
Easing.SinInOut);
animateToPosition.Commit(
this,
nameof(animateToPosition),
finished:
- (x, finished) =>
+ (_, __) =>
{
Dispatcher.Dispatch(
() =>
@@ -235,4 +334,3 @@ private void _touchOverlayPanGesture_PanUpdated(object? sender, PanUpdatedEventA
}
}
}
-
diff --git a/MauiDrawer/NumericExtensions.cs b/MauiDrawer/NumericExtensions.cs
index b2823de..c831ecf 100644
--- a/MauiDrawer/NumericExtensions.cs
+++ b/MauiDrawer/NumericExtensions.cs
@@ -1,22 +1,22 @@
using System;
+
namespace MauiDrawer
{
- public static class NumericExtensions
- {
- public static double Clamp(this double val, double min, double max)
- {
- if (val < min)
- {
- return min;
- }
+ public static class NumericExtensions
+ {
+ public static double Clamp(this double val, double min, double max)
+ {
+ if (val < min)
+ {
+ return min;
+ }
- if (val > max)
- {
- return max;
- }
+ if (val > max)
+ {
+ return max;
+ }
- return val;
- }
- }
+ return val;
+ }
+ }
}
-
diff --git a/MauiDrawer/ViewExtensions.cs b/MauiDrawer/ViewExtensions.cs
new file mode 100644
index 0000000..822044f
--- /dev/null
+++ b/MauiDrawer/ViewExtensions.cs
@@ -0,0 +1,21 @@
+namespace MauiDrawer;
+
+public static class ViewExtensions
+{
+ public static Page? ParentPage(this Element view)
+ {
+ var currentParent = view.Parent;
+
+ while (currentParent is not null)
+ {
+ if (currentParent is Page parentPage)
+ {
+ return parentPage;
+ }
+
+ currentParent = currentParent.Parent;
+ }
+
+ return default;
+ }
+}
\ No newline at end of file
diff --git a/README.md b/README.md
index 344fc16..b97a477 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,13 @@
-# MauiDrawer
+# Componentizer4k
+
+Componentizer4k is a navigation component for .NET MAUI applications that simplifies in-page or component-based navigation. It provides a seamless way to navigate between different components within your .NET MAUI app.
+
+## Features
+
+- **In-Page Navigation:** Easily navigate within a single page, updating content dynamically.
+
+- **Multiple Navigation Methods:** Navigate between different components from your views or by using view models with simple registration.
+
+- **Easy Testing:** Everything is backed by interfaces, so you can unit test your little heart out.
+
+- **Simplified API:** A clean and intuitive API for handling navigation within your app.
diff --git a/global.json b/global.json
new file mode 100644
index 0000000..0f70cc6
--- /dev/null
+++ b/global.json
@@ -0,0 +1,6 @@
+{
+ "sdk": {
+ "allowPrerelease": false,
+ "rollForward": "latestMajor"
+ }
+}
diff --git a/images/logo.png b/images/logo.png
new file mode 100644
index 0000000..a8be03f
Binary files /dev/null and b/images/logo.png differ
diff --git a/stylecop.json b/stylecop.json
new file mode 100644
index 0000000..efe9a88
--- /dev/null
+++ b/stylecop.json
@@ -0,0 +1,35 @@
+{
+ "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
+ "settings": {
+ "indentation": {
+ "useTabs": false,
+ "indentationSize": 4
+ },
+ "documentationRules": {
+ "documentExposedElements": false,
+ "documentInternalElements": false,
+ "documentPrivateElements": false,
+ "documentInterfaces": false,
+ "documentPrivateFields": false,
+ "documentationCulture": "en-US",
+ "xmlHeader": false
+ },
+ "layoutRules": {
+ "newlineAtEndOfFile": "allow",
+ "allowConsecutiveUsings": true
+ },
+ "maintainabilityRules": {
+ "topLevelTypes": [
+ "class",
+ "interface",
+ "struct",
+ "enum",
+ "delegate"
+ ]
+ },
+ "orderingRules": {
+ "usingDirectivesPlacement": "outsideNamespace",
+ "systemUsingDirectivesFirst": true
+ }
+ }
+}