Skip to content

Commit

Permalink
Add Blazor WASM sample (#15)
Browse files Browse the repository at this point in the history
* Add basic Blazor WASM code

* Add HCT graph to Blazor sample

* Add workflow for deploying to Github Pages

* Add MudBlazor, theming and seed selection

* Add SeedColorSelector, display current color on ColorPlot
  • Loading branch information
albi005 authored May 22, 2022
1 parent 8f0ec39 commit 4d25f9f
Show file tree
Hide file tree
Showing 25 changed files with 633 additions and 2 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ jobs:
with:
dotnet-version: 6.0.x

- name: Install .NET MAUI workload
run: dotnet workload install maui
- name: Install .NET workloads
run: dotnet workload install maui && dotnet workload install wasm-tools

- name: Setup NuGet
uses: NuGet/setup-nuget@v1.0.6
Expand Down
43 changes: 43 additions & 0 deletions .github/workflows/gh-pages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# https://swimburger.net/blog/dotnet/how-to-deploy-aspnet-blazor-webassembly-to-github-pages
name: Deploy to GitHub Pages

on:
push:
branches: [ main ]
workflow_dispatch:

jobs:
deploy-to-github-pages:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Setup .NET Core SDK
uses: actions/setup-dotnet@v1
with:
dotnet-version: 6.0.x

- name: Install .NET workload
run: dotnet workload install wasm-tools

- name: Publish .NET Core Project
run: dotnet publish "Samples\MaterialColorUtilities.Samples.Wasm\MaterialColorUtilities.Samples.Wasm.csproj" -c Release -o release --nologo

# change the base-tag in index.html from '/' to 'MaterialColorUtilities' to match GitHub Pages repository subdirectory
- name: Change base-tag in index.html from / to MaterialColorUtilities
run: sed -i 's/<base href="\/" \/>/<base href="\/MaterialColorUtilities\/" \/>/g' release/wwwroot/index.html

# copy index.html to 404.html to serve the same file when a file is not found
- name: copy index.html to 404.html
run: cp release/wwwroot/index.html release/wwwroot/404.html

# add .nojekyll file to tell GitHub pages to not treat this as a Jekyll project. (Allow files and folders starting with an underscore)
- name: Add .nojekyll file
run: touch release/wwwroot/.nojekyll

- name: Commit wwwroot to GitHub Pages
uses: JamesIves/github-pages-deploy-action@3.7.1
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: gh-pages
FOLDER: release/wwwroot
7 changes: 7 additions & 0 deletions MaterialColorUtilities.sln
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MaterialColorUtilities.Samp
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MaterialColorUtilities.Samples.Maui", "Samples\MaterialColorUtilities.Samples.Maui\MaterialColorUtilities.Samples.Maui.csproj", "{1A4BD9E1-4EC5-4D39-B643-08EEDCA3F59E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MaterialColorUtilities.Samples.Wasm", "Samples\MaterialColorUtilities.Samples.Wasm\MaterialColorUtilities.Samples.Wasm.csproj", "{C3E52F2E-BA86-4BA2-A4F4-C88C50516B68}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{097D3E8C-2CB9-49CE-B4D8-2F4BC94A78A5}"
EndProject
Global
Expand Down Expand Up @@ -43,13 +45,18 @@ Global
{1A4BD9E1-4EC5-4D39-B643-08EEDCA3F59E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1A4BD9E1-4EC5-4D39-B643-08EEDCA3F59E}.Release|Any CPU.Build.0 = Release|Any CPU
{1A4BD9E1-4EC5-4D39-B643-08EEDCA3F59E}.Release|Any CPU.Deploy.0 = Release|Any CPU
{C3E52F2E-BA86-4BA2-A4F4-C88C50516B68}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C3E52F2E-BA86-4BA2-A4F4-C88C50516B68}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C3E52F2E-BA86-4BA2-A4F4-C88C50516B68}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C3E52F2E-BA86-4BA2-A4F4-C88C50516B68}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{14D6A693-7174-4A4C-B1EF-3528B98041B2} = {097D3E8C-2CB9-49CE-B4D8-2F4BC94A78A5}
{1A4BD9E1-4EC5-4D39-B643-08EEDCA3F59E} = {097D3E8C-2CB9-49CE-B4D8-2F4BC94A78A5}
{C3E52F2E-BA86-4BA2-A4F4-C88C50516B68} = {097D3E8C-2CB9-49CE-B4D8-2F4BC94A78A5}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BBCD7EC3-2035-4EAC-B506-48CDDAEBC992}
Expand Down
12 changes: 12 additions & 0 deletions Samples/MaterialColorUtilities.Samples.Wasm/App.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
40 changes: 40 additions & 0 deletions Samples/MaterialColorUtilities.Samples.Wasm/AppScheme.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using MaterialColorUtilities.Blend;
using MaterialColorUtilities.Palettes;
using MaterialColorUtilities.Schemes;

namespace MaterialColorUtilities.Samples.Wasm;

public partial class AppScheme<TColor> : Scheme<TColor>
{
public TColor Elevation1 { get; set; }
public TColor Elevation2 { get; set; }
public TColor Elevation3 { get; set; }
public TColor Elevation4 { get; set; }
public TColor Elevation5 { get; set; }
}

public class DarkAppSchemeMapper : DarkSchemeMapper<CorePalette, AppScheme<int>>
{
protected override void MapCore(CorePalette corePalette, AppScheme<int> scheme)
{
base.MapCore(corePalette, scheme);
scheme.Elevation1 = Blender.Cam16Ucs(scheme.Background, scheme.Primary, .05);
scheme.Elevation2 = Blender.Cam16Ucs(scheme.Background, scheme.Primary, .08);
scheme.Elevation3 = Blender.Cam16Ucs(scheme.Background, scheme.Primary, .11);
scheme.Elevation4 = Blender.Cam16Ucs(scheme.Background, scheme.Primary, .12);
scheme.Elevation5 = Blender.Cam16Ucs(scheme.Background, scheme.Primary, .14);
}
}

public class LightAppSchemeMapper : LightSchemeMapper<CorePalette, AppScheme<int>>
{
protected override void MapCore(CorePalette corePalette, AppScheme<int> scheme)
{
base.MapCore(corePalette, scheme);
scheme.Elevation1 = Blender.Cam16Ucs(scheme.Background, scheme.Primary, .05);
scheme.Elevation2 = Blender.Cam16Ucs(scheme.Background, scheme.Primary, .08);
scheme.Elevation3 = Blender.Cam16Ucs(scheme.Background, scheme.Primary, .11);
scheme.Elevation4 = Blender.Cam16Ucs(scheme.Background, scheme.Primary, .12);
scheme.Elevation5 = Blender.Cam16Ucs(scheme.Background, scheme.Primary, .14);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using MaterialColorUtilities.Utils;
using MudBlazor.Utilities;

namespace MaterialColorUtilities.Samples.Wasm.Extensions
{
public static class IntExtensions
{
public static MudColor ToMudColor(this int argb) => new(
ColorUtils.RedFromArgb(argb),
ColorUtils.GreenFromArgb(argb),
ColorUtils.BlueFromArgb(argb),
ColorUtils.AlphaFromArgb(argb));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.5" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.5" PrivateAssets="all" />
<PackageReference Include="MudBlazor" Version="6.0.11-dev.2" />
<PackageReference Include="SkiaSharp.Views.Blazor" Version="2.88.0-preview.266" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\MaterialColorUtilities.SourceGenerators\MaterialColorUtilities.SourceGenerators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
<ProjectReference Include="..\..\MaterialColorUtilities\MaterialColorUtilities.csproj" />
</ItemGroup>

</Project>
28 changes: 28 additions & 0 deletions Samples/MaterialColorUtilities.Samples.Wasm/Pages/Index.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@page "/"
@using MaterialColorUtilities.ColorAppearance
@using MaterialColorUtilities.Palettes
@using MaterialColorUtilities.Samples.Wasm.Services
@using MaterialColorUtilities.Schemes
@using MaterialColorUtilities.Utils
@using MudBlazor.Utilities
@using SkiaSharp
@using SkiaSharp.Views.Blazor
@inject ThemeService themeService

<PageTitle>Material Color Utilities for .NET</PageTitle>

<MudMainContent>
<MudContainer>

<HctSliders />

<div class="mx-auto">
<ColorPlot Resolution="100" />
</div>

<MudButton Variant="Variant.Filled" Color="Color.Primary">Primary</MudButton>
<MudButton Variant="Variant.Filled" Color="Color.Secondary">Secondary</MudButton>
<MudButton Variant="Variant.Filled" Color="Color.Tertiary">Tertiary</MudButton>

</MudContainer>
</MudMainContent>
16 changes: 16 additions & 0 deletions Samples/MaterialColorUtilities.Samples.Wasm/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using MaterialColorUtilities.Samples.Wasm;
using MaterialColorUtilities.Samples.Wasm.Services;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using MudBlazor;
using MudBlazor.Services;

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddMudServices();
builder.Services.AddSingleton<ThemeService>();

await builder.Build().RunAsync();
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:5178",
"sslPort": 44306
}
},
"profiles": {
"MaterialColorUtilities.Samples.Wasm": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"applicationUrl": "https://localhost:7019;http://localhost:5019",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using MaterialColorUtilities.Palettes;
using MaterialColorUtilities.Samples.Wasm.Extensions;
using MudBlazor;
using MudBlazor.Utilities;

namespace MaterialColorUtilities.Samples.Wasm.Services;

public class ThemeService
{
private int _seed = Score.Scorer.Default;

public ThemeService() => Apply();

public int Seed
{
get => _seed;
set
{
_seed = value;
Apply();
}
}

public void Apply()
{
CorePalette corePalette = new(Seed);
AppScheme<MudColor> lightScheme = new LightAppSchemeMapper()
.Map(corePalette)
.ConvertTo(IntExtensions.ToMudColor);
MudTheme.Palette = new()
{
Primary = lightScheme.Primary,
Secondary = lightScheme.Secondary,
Tertiary = lightScheme.Tertiary,
Background = lightScheme.Background,
AppbarBackground = lightScheme.Elevation2,
AppbarText = lightScheme.OnBackground,
DrawerBackground = lightScheme.Elevation1,
Surface = lightScheme.Elevation1,
};
ThemeChanged?.Invoke(this, EventArgs.Empty);
}

public MudTheme MudTheme { get; } = new()
{
ZIndex = new()
{
AppBar = 2000
}
};
public event EventHandler ThemeChanged;
}
19 changes: 19 additions & 0 deletions Samples/MaterialColorUtilities.Samples.Wasm/Shared/ColorPlot.razor
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
@page "/hct"
@using MaterialColorUtilities.ColorAppearance
@using MaterialColorUtilities.Palettes
@using MaterialColorUtilities.Samples.Wasm.Services
@using MaterialColorUtilities.Schemes
@using MaterialColorUtilities.Utils
@using MudBlazor.Utilities
@using SkiaSharp
@using SkiaSharp.Views.Blazor
@inject ThemeService themeService
@inherits SeedColorSelector

<SKCanvasView
@ref=@view
OnPaintSurface=OnPaintSurface
@onclick=OnClick
width="400"
height="200"
style="display: block" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using MaterialColorUtilities.ColorAppearance;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
using SkiaSharp;
using SkiaSharp.Views.Blazor;

namespace MaterialColorUtilities.Samples.Wasm.Shared
{
public partial class ColorPlot
{
private SKBitmap bitmap;
private SKCanvasView view;
private double x;
private double y;

/// <summary>
/// The width of the bitmap that will be generated.
/// </summary>
[Parameter] public int Resolution { get; set; } = 400;

protected override void OnInitialized()
{
bitmap = new(Resolution, Resolution / 2);
for (int x = 0; x < bitmap.Width; x++)
{
for (int y = 0; y < bitmap.Height; y++)
{
Hct hct = Hct.From(360 * x / bitmap.Width, 100, 100 * y / bitmap.Height);
bitmap.SetPixel(x, y, new SKColor((uint)hct.ToInt()));
}
}
bitmap = bitmap.Resize(new SKImageInfo(400, 200), SKFilterQuality.None);
base.OnInitialized();
}

public void OnPaintSurface(SKPaintSurfaceEventArgs args)
{
var canvas = args.Surface.Canvas;
canvas.DrawBitmap(bitmap, 0, 0);
canvas.DrawCircle((float)x, (float)y, 4, new SKPaint { Color = SKColors.White, Style = SKPaintStyle.Stroke });
}

public void OnClick(MouseEventArgs args)
{
x = args.OffsetX;
y = args.OffsetY;
Hct hct = Hct.From(360 * x / bitmap.Width, 100, 100 * y / bitmap.Height);
themeService.Seed = hct.ToInt();
}

protected override void SetFromSeed(int seed)
{
Hct hct = Hct.FromInt(seed);
x = bitmap.Width * hct.Hue / 360;
y = bitmap.Height * hct.Tone / 100;
view?.Invalidate();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@inherits SeedColorSelector

<MudSlider @bind-Value="Hue" Variant="@Variant.Filled" ValueLabel="@true" Max="360" >Hue</MudSlider>
<MudSlider @bind-Value="Chroma" Variant="@Variant.Filled" ValueLabel="@true" Max="100">Chroma</MudSlider>
<MudSlider @bind-Value="Tone" Variant="@Variant.Filled" ValueLabel="@true" Max="100">Tone</MudSlider>
Loading

0 comments on commit 4d25f9f

Please sign in to comment.