diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml
index f1461b5..9ee4649 100644
--- a/.github/workflows/deploy.yml
+++ b/.github/workflows/deploy.yml
@@ -1,8 +1,8 @@
name: Deploy to GitHub Pages
env:
- PROJECT_PATH: demo/Ursa.Demo.Browser/Ursa.Demo.Browser.csproj
- OUTPUT_PATH: demo/Ursa.Demo.Browser/bin/Debug/net7.0/browser-wasm/AppBundle
+ PROJECT_PATH: demo/Ursa.Demo.Browser/Ursa.Demo.Browser.csproj
+ OUTPUT_PATH: demo/Ursa.Demo.Browser/bin/Release/net7.0/browser-wasm/AppBundle
on:
push:
branches: [ "deploy" ]
@@ -13,38 +13,41 @@ jobs:
deploy-to-github-pages:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - name: Checkout
+ uses: actions/checkout@v4.1.1
- - name: Setup .NET Core SDK
- uses: actions/setup-dotnet@v1.9.0
+ - name: Setup .NET 7
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: 7.0.405
- - name: Install wasm-tools
- run: dotnet workload install wasm-tools wasm-experimental
+ - name: Install wasm-tools
+ run: dotnet workload install wasm-tools wasm-tools-net7
- - name: Install DotNetCompress
- run: dotnet tool install --global DotNetCompress --version 2.0.0 --no-cache
+ - name: Install DotNetCompress
+ run: dotnet tool install --global DotNetCompress --version 3.0.0 --no-cache
- - name: Publish .NET Project
- run: dotnet publish $PROJECT_PATH -c Debug -o debug --nologo
+ - name: Publish .NET Project
+ run: dotnet publish $PROJECT_PATH -c Release -o release --nologo
- - name: Change base-tag in index.html
- run: sed -i 's///g' $OUTPUT_PATH/index.html
+ - name: Change base-tag in index.html
+ run: sed -i 's///g' $OUTPUT_PATH/index.html
- - name: copy index.html to 404.html
- run: cp $OUTPUT_PATH/index.html $OUTPUT_PATH/404.html
+ - name: copy index.html to 404.html
+ run: cp $OUTPUT_PATH/index.html $OUTPUT_PATH/404.html
- - name: Compress Output using Brotli
- run: DotNetCompress -d $OUTPUT_PATH -p "*.dll" "*.js" "*.wasm" --format br --threads 4
+ - name: Compress Output using Brotli
+ run: DotNetCompress -d $OUTPUT_PATH -p "*.dll" "*.js" "*.wasm" --format br --threads 4
- - name: Compress Output using GZip
- run: DotNetCompress -d $OUTPUT_PATH -p "*.dll" "*.js" "*.wasm" --format gz --threads 4
+ - name: Compress Output using GZip
+ run: DotNetCompress -d $OUTPUT_PATH -p "*.dll" "*.js" "*.wasm" --format gz --threads 4
- - name: Add .nojekyll file
- run: touch $OUTPUT_PATH/.nojekyll
+ - name: Add .nojekyll file
+ run: touch $OUTPUT_PATH/.nojekyll
- - name: Commit wwwroot to GitHub Pages
- uses: JamesIves/github-pages-deploy-action@4.1.7
- with:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- BRANCH: gh-pages
- FOLDER: ${{ env.OUTPUT_PATH }}
+ - name: Commit wwwroot to GitHub Pages
+ uses: JamesIves/github-pages-deploy-action@v4.5.0
+ with:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+ BRANCH: gh-pages
+ FOLDER: ${{ env.OUTPUT_PATH }}
diff --git a/README.md b/README.md
index b9f27a1..dced897 100644
--- a/README.md
+++ b/README.md
@@ -6,12 +6,14 @@
Ursa is a UI library for building cross-platform UIs with Avalonia UI.
+
+
## How to use
1. Ursa
Add nuget package:
```bash
-dotnet add package Irihi.Ursa --version 0.1.0-beta20230702
+dotnet add package Irihi.Ursa
```
You can now use Ursa controls in your Avalonia Application.
@@ -39,14 +41,24 @@ Ursa.Themes.Semi is a theme package for Ursa inspired by Semi Design. You can ad
Add nuget package:
```bash
-dotnet add package Semi.Avalonia --version 11.0.0-rc1
-dotnet add package Irihi.Ursa.Themes.Semi --version 0.1.0-beta20230702
+dotnet add package Semi.Avalonia --version 11.0.7
+dotnet add package Irihi.Ursa.Themes.Semi
```
Include Styles in application:
```xaml
+
+
-
+
-```
\ No newline at end of file
+```
+
+## Support
+
+We offer limited free community support for Semi Avalonia and Ursa. Please join our group via FeiShu(Lark)
+
+
\ No newline at end of file
diff --git a/Ursa.sln b/Ursa.sln
index 9b2953a..a7328fd 100644
--- a/Ursa.sln
+++ b/Ursa.sln
@@ -16,6 +16,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ursa.Demo.iOS", "demo\Ursa.
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ursa.Demo.Browser", "demo\Ursa.Demo.Browser\Ursa.Demo.Browser.csproj", "{D1942476-8473-4608-BB9F-5AC01083BBDA}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ursa.PrismExtension", "src\Ursa.PrismExtension\Ursa.PrismExtension.csproj", "{2E934F60-F5DF-4856-B05A-B949C7F9D948}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ursa.PrismDialogDemo", "demo\Ursa.PrismDialogDemo\Ursa.PrismDialogDemo.csproj", "{F99B3D07-4560-4B05-892C-0FF2757FEF2E}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Files", "Solution Files", "{9D34CC2C-9BFA-4138-BA5A-CD3744F9B589}"
+ ProjectSection(SolutionItems) = preProject
+ src\Package.props = src\Package.props
+ demo\Directory.Build.props = demo\Directory.Build.props
+ EndProjectSection
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -50,6 +60,14 @@ Global
{D1942476-8473-4608-BB9F-5AC01083BBDA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D1942476-8473-4608-BB9F-5AC01083BBDA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D1942476-8473-4608-BB9F-5AC01083BBDA}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2E934F60-F5DF-4856-B05A-B949C7F9D948}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2E934F60-F5DF-4856-B05A-B949C7F9D948}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2E934F60-F5DF-4856-B05A-B949C7F9D948}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2E934F60-F5DF-4856-B05A-B949C7F9D948}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F99B3D07-4560-4B05-892C-0FF2757FEF2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F99B3D07-4560-4B05-892C-0FF2757FEF2E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F99B3D07-4560-4B05-892C-0FF2757FEF2E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F99B3D07-4560-4B05-892C-0FF2757FEF2E}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{407A91FD-A88B-459B-8DCE-8C6AA98279FE} = {A41BAF0D-DA61-4A63-889A-084BAD36FD66}
@@ -57,5 +75,6 @@ Global
{B6BAB821-A9FE-44F3-B9CD-06E27FDB63F6} = {A41BAF0D-DA61-4A63-889A-084BAD36FD66}
{94C2BBD9-8B57-4AE9-AAFD-7D4335B15A8E} = {A41BAF0D-DA61-4A63-889A-084BAD36FD66}
{D1942476-8473-4608-BB9F-5AC01083BBDA} = {A41BAF0D-DA61-4A63-889A-084BAD36FD66}
+ {F99B3D07-4560-4B05-892C-0FF2757FEF2E} = {A41BAF0D-DA61-4A63-889A-084BAD36FD66}
EndGlobalSection
EndGlobal
diff --git a/assets/community-support.png b/assets/community-support.png
new file mode 100644
index 0000000..fa4206c
Binary files /dev/null and b/assets/community-support.png differ
diff --git a/assets/demo.png b/assets/demo.png
new file mode 100644
index 0000000..8bee762
Binary files /dev/null and b/assets/demo.png differ
diff --git a/demo/Directory.Build.props b/demo/Directory.Build.props
index ae8bdf5..3a82054 100644
--- a/demo/Directory.Build.props
+++ b/demo/Directory.Build.props
@@ -1,6 +1,6 @@
enable
- 11.0.0
+ 11.0.10
diff --git a/demo/Ursa.Demo.Android/Ursa.Demo.Android.csproj b/demo/Ursa.Demo.Android/Ursa.Demo.Android.csproj
index 4071d05..f5730c1 100644
--- a/demo/Ursa.Demo.Android/Ursa.Demo.Android.csproj
+++ b/demo/Ursa.Demo.Android/Ursa.Demo.Android.csproj
@@ -1,7 +1,7 @@
Exe
- net7.0-android
+ net8.0-android
21
enable
com.irihitech.Ursa
diff --git a/demo/Ursa.Demo.Browser/Ursa.Demo.Browser.csproj b/demo/Ursa.Demo.Browser/Ursa.Demo.Browser.csproj
index f51b5fb..31ef39b 100644
--- a/demo/Ursa.Demo.Browser/Ursa.Demo.Browser.csproj
+++ b/demo/Ursa.Demo.Browser/Ursa.Demo.Browser.csproj
@@ -1,6 +1,6 @@
- net7.0
+ net8.0
browser-wasm
AppBundle\main.js
Exe
diff --git a/demo/Ursa.Demo.Desktop/Ursa.Demo.Desktop.csproj b/demo/Ursa.Demo.Desktop/Ursa.Demo.Desktop.csproj
index 3d3f388..6566753 100644
--- a/demo/Ursa.Demo.Desktop/Ursa.Demo.Desktop.csproj
+++ b/demo/Ursa.Demo.Desktop/Ursa.Demo.Desktop.csproj
@@ -3,9 +3,10 @@
WinExe
- net7.0
+ net8.0
enable
true
+ false
diff --git a/demo/Ursa.Demo.iOS/Ursa.Demo.iOS.csproj b/demo/Ursa.Demo.iOS/Ursa.Demo.iOS.csproj
index 5f70ccb..65fad79 100644
--- a/demo/Ursa.Demo.iOS/Ursa.Demo.iOS.csproj
+++ b/demo/Ursa.Demo.iOS/Ursa.Demo.iOS.csproj
@@ -1,7 +1,7 @@
Exe
- net6.0-ios
+ net8.0-ios
13.0
enable
diff --git a/demo/Ursa.Demo/App.axaml b/demo/Ursa.Demo/App.axaml
index 8326f56..abf9048 100644
--- a/demo/Ursa.Demo/App.axaml
+++ b/demo/Ursa.Demo/App.axaml
@@ -1,9 +1,10 @@
+ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+ xmlns:u-semi="https://irihi.tech/ursa/themes/semi">
-
+
\ No newline at end of file
diff --git a/demo/Ursa.Demo/Assets/3x.png b/demo/Ursa.Demo/Assets/3x.png
new file mode 100644
index 0000000..6dd5bf1
Binary files /dev/null and b/demo/Ursa.Demo/Assets/3x.png differ
diff --git a/demo/Ursa.Demo/Assets/IRIHI.png b/demo/Ursa.Demo/Assets/IRIHI.png
new file mode 100644
index 0000000..3f405aa
Binary files /dev/null and b/demo/Ursa.Demo/Assets/IRIHI.png differ
diff --git a/demo/Ursa.Demo/Assets/WORLD.png b/demo/Ursa.Demo/Assets/WORLD.png
new file mode 100644
index 0000000..7c5b71f
Binary files /dev/null and b/demo/Ursa.Demo/Assets/WORLD.png differ
diff --git a/demo/Ursa.Demo/Converters/IconNameConverter.cs b/demo/Ursa.Demo/Converters/IconNameConverter.cs
index 309a0e8..4d1fe99 100644
--- a/demo/Ursa.Demo/Converters/IconNameConverter.cs
+++ b/demo/Ursa.Demo/Converters/IconNameConverter.cs
@@ -13,7 +13,7 @@ namespace Ursa.Demo.Converters;
public class IconNameConverter: IValueConverter
{
[Content]
- public Dictionary Paths { get; set; } = new();
+ public Dictionary Paths { get; set; } = new();
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
diff --git a/demo/Ursa.Demo/Converters/IconNameToPathConverter.cs b/demo/Ursa.Demo/Converters/IconNameToPathConverter.cs
new file mode 100644
index 0000000..4451895
--- /dev/null
+++ b/demo/Ursa.Demo/Converters/IconNameToPathConverter.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Globalization;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Data.Converters;
+using Avalonia.Media;
+
+namespace Ursa.Demo.Converters;
+
+public class IconNameToPathConverter: IValueConverter
+{
+ private string[] paths = new[]
+ {
+ "M12,4A4,4 0 0,1 16,8A4,4 0 0,1 12,12A4,4 0 0,1 8,8A4,4 0 0,1 12,4M12,14C16.42,14 20,15.79 20,18V20H4V18C4,15.79 7.58,14 12,14Z",
+ "M16 12L9 2L2 12H3.86L0 18H7V22H11V18H18L14.14 12H16M20.14 12H22L15 2L12.61 5.41L17.92 13H15.97L19.19 18H24L20.14 12M13 19H17V22H13V19Z",
+ "M15,9H5V5H15M12,19A3,3 0 0,1 9,16A3,3 0 0,1 12,13A3,3 0 0,1 15,16A3,3 0 0,1 12,19M17,3H5C3.89,3 3,3.9 3,5V19A2,2 0 0,0 5,21H19A2,2 0 0,0 21,19V7L17,3Z",
+ "M5 21C3.9 21 3 20.1 3 19V5C3 3.9 3.9 3 5 3H19C20.1 3 21 3.9 21 5V19C21 20.1 20.1 21 19 21H5M15.3 16L13.2 13.9L17 10L14.2 7.2L10.4 11.1L8.2 8.9V16H15.3Z",
+ "M16,9V7H12V12.5C11.58,12.19 11.07,12 10.5,12A2.5,2.5 0 0,0 8,14.5A2.5,2.5 0 0,0 10.5,17A2.5,2.5 0 0,0 13,14.5V9H16M12,2A10,10 0 0,1 22,12A10,10 0 0,1 12,22A10,10 0 0,1 2,12A10,10 0 0,1 12,2Z",
+ "M16.67,4H15V2H9V4H7.33A1.33,1.33 0 0,0 6,5.33V20.67C6,21.4 6.6,22 7.33,22H16.67A1.33,1.33 0 0,0 18,20.67V5.33C18,4.6 17.4,4 16.67,4Z",
+ "M12 2C6.5 2 2 6.5 2 12C2 17.5 6.5 22 12 22C17.5 22 22 17.5 22 12S17.5 2 12 2M12.5 13H11V7H12.5V11.3L16.2 9.2L17 10.5L12.5 13Z"
+ };
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ if (value is int i)
+ {
+ string s = paths[i % paths.Length];
+ return StreamGeometry.Parse(s);
+ }
+ else if (value is string s)
+ {
+ int hash = s.GetHashCode();
+ string path = paths[Math.Abs(hash) % paths.Length];
+ return StreamGeometry.Parse(path);
+ }
+ return AvaloniaProperty.UnsetValue;
+ }
+
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ return AvaloniaProperty.UnsetValue;
+ }
+}
\ No newline at end of file
diff --git a/demo/Ursa.Demo/Converters/TimelineIconConverter.cs b/demo/Ursa.Demo/Converters/TimelineIconConverter.cs
new file mode 100644
index 0000000..04d46f4
--- /dev/null
+++ b/demo/Ursa.Demo/Converters/TimelineIconConverter.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Globalization;
+using Avalonia;
+using Avalonia.Data;
+using Avalonia.Data.Converters;
+using Avalonia.Media;
+using Ursa.Controls;
+
+namespace Ursa.Demo.Converters;
+
+public class TimelineIconConverter: IValueConverter
+{
+ public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ if (value is TimelineItemType t)
+ {
+ return t switch
+ {
+ TimelineItemType.Success => Brushes.Green,
+ TimelineItemType.Ongoing => Brushes.Blue,
+ TimelineItemType.Error => Brushes.Red,
+ _ => Brushes.Gray
+ };
+ }
+ return AvaloniaProperty.UnsetValue;
+ }
+
+ public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
+ {
+ throw new NotImplementedException();
+ }
+}
\ No newline at end of file
diff --git a/demo/Ursa.Demo/Converters/MenuDataTemplateSelector.cs b/demo/Ursa.Demo/DataTemplates/MenuDataTemplateSelector.cs
similarity index 100%
rename from demo/Ursa.Demo/Converters/MenuDataTemplateSelector.cs
rename to demo/Ursa.Demo/DataTemplates/MenuDataTemplateSelector.cs
diff --git a/demo/Ursa.Demo/DataTemplates/ToolBarItemTemplateSelector.cs b/demo/Ursa.Demo/DataTemplates/ToolBarItemTemplateSelector.cs
new file mode 100644
index 0000000..bfd9c76
--- /dev/null
+++ b/demo/Ursa.Demo/DataTemplates/ToolBarItemTemplateSelector.cs
@@ -0,0 +1,56 @@
+using Avalonia.Controls;
+using Avalonia.Controls.Primitives;
+using Avalonia.Controls.Templates;
+using Avalonia.Data;
+using Ursa.Controls;
+using Ursa.Demo.ViewModels;
+
+namespace Ursa.Demo.Converters;
+
+public class ToolBarItemTemplateSelector: IDataTemplate
+{
+
+ public static ToolBarItemTemplateSelector Instance { get; } = new();
+ public Control? Build(object? param)
+ {
+ if (param is null) return null;
+ if (param is ToolBarSeparatorViewModel sep)
+ {
+ return new ToolBarSeparator();
+ }
+ if (param is ToolBarButtonItemViewModel vm)
+ {
+ return new Button()
+ {
+ [!ContentControl.ContentProperty] = new Binding() { Path = "Content" },
+ [!Button.CommandProperty] = new Binding() { Path = "Command" },
+ [!ToolBar.OverflowModeProperty] = new Binding(){Path = nameof(ToolBarItemViewModel.OverflowMode)},
+ };
+ }
+ if (param is ToolBarCheckBoxItemViweModel cb)
+ {
+ return new CheckBox()
+ {
+ [!ContentControl.ContentProperty] = new Binding() { Path = "Content" },
+ [!ToggleButton.IsCheckedProperty] = new Binding() { Path = "IsChecked" },
+ [!ToolBar.OverflowModeProperty] = new Binding(){Path = nameof(ToolBarItemViewModel.OverflowMode)},
+ };
+ }
+ if (param is ToolBarComboBoxItemViewModel combo)
+ {
+ return new ComboBox()
+ {
+ [!ContentControl.ContentProperty] = new Binding() { Path = "Content" },
+ [!SelectingItemsControl.SelectedItemProperty] = new Binding() { Path = "SelectedItem" },
+ [!ItemsControl.ItemsSourceProperty] = new Binding() { Path = "Items" },
+ [!ToolBar.OverflowModeProperty] = new Binding(){Path = nameof(ToolBarItemViewModel.OverflowMode)},
+ };
+ }
+ return new Button() { Content = "Undefined Item" };
+ }
+
+ public bool Match(object? data)
+ {
+ return data is ToolBarItemViewModel;
+ }
+}
\ No newline at end of file
diff --git a/demo/Ursa.Demo/Converters/ViewLocator.cs b/demo/Ursa.Demo/DataTemplates/ViewLocator.cs
similarity index 100%
rename from demo/Ursa.Demo/Converters/ViewLocator.cs
rename to demo/Ursa.Demo/DataTemplates/ViewLocator.cs
diff --git a/demo/Ursa.Demo/Dialogs/DialogWithAction.axaml b/demo/Ursa.Demo/Dialogs/DialogWithAction.axaml
new file mode 100644
index 0000000..4132581
--- /dev/null
+++ b/demo/Ursa.Demo/Dialogs/DialogWithAction.axaml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+ A
+ B
+ C
+
+
+
+
diff --git a/demo/Ursa.Demo/Dialogs/DialogWithAction.axaml.cs b/demo/Ursa.Demo/Dialogs/DialogWithAction.axaml.cs
new file mode 100644
index 0000000..783f47b
--- /dev/null
+++ b/demo/Ursa.Demo/Dialogs/DialogWithAction.axaml.cs
@@ -0,0 +1,13 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Markup.Xaml;
+
+namespace Ursa.Demo.Dialogs;
+
+public partial class DialogWithAction : UserControl
+{
+ public DialogWithAction()
+ {
+ InitializeComponent();
+ }
+}
\ No newline at end of file
diff --git a/demo/Ursa.Demo/Dialogs/DialogWithActionViewModel.cs b/demo/Ursa.Demo/Dialogs/DialogWithActionViewModel.cs
new file mode 100644
index 0000000..6615fb4
--- /dev/null
+++ b/demo/Ursa.Demo/Dialogs/DialogWithActionViewModel.cs
@@ -0,0 +1,51 @@
+using System;
+using System.Threading.Tasks;
+using System.Windows.Input;
+using CommunityToolkit.Mvvm.ComponentModel;
+using CommunityToolkit.Mvvm.Input;
+using Irihi.Avalonia.Shared.Contracts;
+using Ursa.Controls;
+
+namespace Ursa.Demo.Dialogs;
+
+public partial class DialogWithActionViewModel: ObservableObject, IDialogContext
+{
+ [ObservableProperty] private string _title;
+ [ObservableProperty] private DateTime _date;
+
+ public void Close()
+ {
+ RequestClose?.Invoke(this, false);
+ }
+
+ public event EventHandler