From fa63b1aa9bf5857514637a24787062750569ab36 Mon Sep 17 00:00:00 2001 From: Panos Date: Mon, 27 May 2024 22:19:52 +0300 Subject: [PATCH 01/61] fix: _ci.yaml --- .github/workflows/_ci.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/_ci.yaml b/.github/workflows/_ci.yaml index a649543..23b5442 100644 --- a/.github/workflows/_ci.yaml +++ b/.github/workflows/_ci.yaml @@ -44,7 +44,7 @@ jobs: - name: Build working-directory: src/TabKeeper.UI.Wasm - run: dotnet build --no-restore + run: dotnet build -c Release --no-restore - name: Publish if: ${{ inputs.publish }} @@ -52,7 +52,7 @@ jobs: shell: pwsh run: | .\css.ps1 -publish - dotnet publish --no-restore --no-build + dotnet publish --no-restore - name: Push to Cloudflare Pages if: ${{ inputs.publish }} From 7be8a69d83d8ee1270673074c7e685a476c1dd5d Mon Sep 17 00:00:00 2001 From: Panos Date: Sun, 2 Jun 2024 18:58:16 +0300 Subject: [PATCH 02/61] update: Dependencies and root files update: Dependencies and root files minor update: launchSettings.json --- Directory.Build.props | 2 +- TabKeeper.sln | 1 - src-modules/Core | 2 +- .../Properties/launchSettings.json | 13 ------------- .../TabKeeper.UI.Wasm.csproj | 19 ++++++++----------- src/TabKeeper.UI/TabKeeper.UI.csproj | 2 +- .../TabKeeper.UI.UnitTests.csproj | 8 ++++---- 7 files changed, 15 insertions(+), 32 deletions(-) diff --git a/Directory.Build.props b/Directory.Build.props index ddb467f..01e764f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -6,7 +6,7 @@ true true Debug - $(NoWarn);CS8509;IDE0039;IDE0130;IDE0290;IDE0060;RZ10012 + $(NoWarn);CS8509;IDE0039;IDE0130;IDE0290;IDE0060;RZ10012;IDE0052;BL0007; $(MSBuildThisFileDirectory)artifacts/default $(MSBuildThisFileDirectory)artifacts/tests diff --git a/TabKeeper.sln b/TabKeeper.sln index 955f9f4..ac7d84b 100644 --- a/TabKeeper.sln +++ b/TabKeeper.sln @@ -94,4 +94,3 @@ Global SolutionGuid = {26EECD34-43C6-4F7A-A567-0F8AC7F82094} EndGlobalSection EndGlobal -bal diff --git a/src-modules/Core b/src-modules/Core index 68a3c27..f24cfa0 160000 --- a/src-modules/Core +++ b/src-modules/Core @@ -1 +1 @@ -Subproject commit 68a3c27d33bc48a1e7550c94a666f8e148d645fa +Subproject commit f24cfa0c24f5c27f5cd46db655b64bbca881df81 diff --git a/src/TabKeeper.UI.Wasm/Properties/launchSettings.json b/src/TabKeeper.UI.Wasm/Properties/launchSettings.json index bbe560b..85e4afa 100644 --- a/src/TabKeeper.UI.Wasm/Properties/launchSettings.json +++ b/src/TabKeeper.UI.Wasm/Properties/launchSettings.json @@ -9,19 +9,6 @@ "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } - }, - "watch": { - "commandName": "Executable", - "executablePath": "dotnet.exe", - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "workingDirectory": "$(ProjectDir)", - "commandLineArgs": "watch --non-interactive run", - "launchBrowser": false, - "applicationUrl": "https://localhost:5001", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development", - "ASPNETCORE_HTTPS_PORT": "5001" - } } } } diff --git a/src/TabKeeper.UI.Wasm/TabKeeper.UI.Wasm.csproj b/src/TabKeeper.UI.Wasm/TabKeeper.UI.Wasm.csproj index d4809d3..47795d0 100644 --- a/src/TabKeeper.UI.Wasm/TabKeeper.UI.Wasm.csproj +++ b/src/TabKeeper.UI.Wasm/TabKeeper.UI.Wasm.csproj @@ -9,14 +9,16 @@ + - - - - - - + + + + + + + @@ -29,9 +31,4 @@ - - - - - diff --git a/src/TabKeeper.UI/TabKeeper.UI.csproj b/src/TabKeeper.UI/TabKeeper.UI.csproj index 001b71f..862ae8b 100644 --- a/src/TabKeeper.UI/TabKeeper.UI.csproj +++ b/src/TabKeeper.UI/TabKeeper.UI.csproj @@ -6,7 +6,7 @@ - + diff --git a/tests/TabKeeper.UI.UnitTests/TabKeeper.UI.UnitTests.csproj b/tests/TabKeeper.UI.UnitTests/TabKeeper.UI.UnitTests.csproj index 214ffff..bf3af2f 100644 --- a/tests/TabKeeper.UI.UnitTests/TabKeeper.UI.UnitTests.csproj +++ b/tests/TabKeeper.UI.UnitTests/TabKeeper.UI.UnitTests.csproj @@ -8,13 +8,13 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all From 587dffdf0c71fdcb2ee43b6c80668c301ed65dfe Mon Sep 17 00:00:00 2001 From: Panos Date: Sun, 2 Jun 2024 18:53:52 +0300 Subject: [PATCH 03/61] refactor: Button component update: scss --- src/TabKeeper.UI.Wasm/Components/Button.razor | 8 ++++++++ src/TabKeeper.UI.Wasm/assets/_buttons.scss | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/TabKeeper.UI.Wasm/Components/Button.razor b/src/TabKeeper.UI.Wasm/Components/Button.razor index 5fb8bf8..aca98f3 100644 --- a/src/TabKeeper.UI.Wasm/Components/Button.razor +++ b/src/TabKeeper.UI.Wasm/Components/Button.razor @@ -1,8 +1,14 @@ @using System.Diagnostics.CodeAnalysis @using System.Globalization +@using OneOf; @inherits CoreComponent +@if (!If.Match(static v => v, static f => f())) +{ + return; +} + - + + + @code { + private ValidatorFn MinLength3 = Validators.MinLength(3); private const string EntriesKey = "tab-entries"; - private Modal addEntryModal = null!; - private BehaviorSubject NewTabEntryName { get; } = new(""); + private FormGroup newTabForm = new(); + private Modal addEntryModal = null!; private SourceList Entries { get; } = new(); private void AddNewTab() { - if (NewTabEntryName.Value.Length < 3) return; + if (newTabForm.Invalid) return; + + var name = newTabForm.GetControl("name")?.Value; + + if (name is null or "") return; var entryId = Uuid.NewUuid(); - Entries.Insert(0, new TabEntry(entryId, NewTabEntryName.Value)); + Entries.Insert(0, new TabEntry(entryId, name)); nav.NavigateTo($"/tabs/{entryId}"); } protected override void OnInitialized() { ShellContext.Title = "general.home" | translate; - NewTabEntryName.Subscribe(_ => Update()); + // NewTabEntryName.Subscribe(_ => Update()); Entries .Connect() - .OnItemAdded(entry => storage.TrySetItem(entry.Id, new TabKeeper.Tabs.Tab { Id = entry.Id, Name = entry.Name })) + .OnItemAdded(entry => storage.TrySetItem(entry.Id, new TabKeeper.Tabs.Tab { Id = entry.Id, Name = entry.Name, Date = DateOnly.FromDateTime(DateTime.Now) })) .OnItemRemoved(entry => storage.RemoveItem(entry.Id), invokeOnUnsubscribe: false) .QueryWhenChanged() .Do(entries => storage.SetItem(EntriesKey, entries)) .Subscribe(_ => Update()) .DisposeWith(Disposables); - Entries.AddRange(storage.GetItem>(EntriesKey) ?? []); } diff --git a/src/TabKeeper.UI.Wasm/Program.cs b/src/TabKeeper.UI.Wasm/Program.cs index 5b3f75c..037453a 100644 --- a/src/TabKeeper.UI.Wasm/Program.cs +++ b/src/TabKeeper.UI.Wasm/Program.cs @@ -1,4 +1,5 @@ using Annular.Translate; +using Annular.Translate.Abstract; using Annular.Translate.HttpLoader; using Blazored.LocalStorage; using Core.Blazor; diff --git a/src/TabKeeper.UI.Wasm/TabKeeper.UI.Wasm.csproj b/src/TabKeeper.UI.Wasm/TabKeeper.UI.Wasm.csproj index 47795d0..042d675 100644 --- a/src/TabKeeper.UI.Wasm/TabKeeper.UI.Wasm.csproj +++ b/src/TabKeeper.UI.Wasm/TabKeeper.UI.Wasm.csproj @@ -9,7 +9,6 @@ - diff --git a/src/TabKeeper.UI.Wasm/_Imports.razor b/src/TabKeeper.UI.Wasm/_Imports.razor index 419b0b2..05a7674 100644 --- a/src/TabKeeper.UI.Wasm/_Imports.razor +++ b/src/TabKeeper.UI.Wasm/_Imports.razor @@ -6,7 +6,8 @@ @using Core @using Core.Abstractions @using Core.Blazor -@using Core.Blazor.Reactive +@using Core.Blazor.Reactive.Forms +@using Core.Blazor.RxForms; @using Annular.Translate @using DynamicData @using DynamicData.Cache @@ -19,7 +20,6 @@ @using Microsoft.JSInterop @using TabKeeper @using TabKeeper.Components -@using TabKeeper.Components.RxComponents @using TabKeeper.People @using TabKeeper.Tabs @using Ignis.Components diff --git a/src/TabKeeper.UI.Wasm/wwwroot/i18n/el.json b/src/TabKeeper.UI.Wasm/wwwroot/i18n/el.json index 1bf2bce..83cb899 100644 --- a/src/TabKeeper.UI.Wasm/wwwroot/i18n/el.json +++ b/src/TabKeeper.UI.Wasm/wwwroot/i18n/el.json @@ -8,6 +8,8 @@ "description": "Συγγνώμη, δεν υπάρχει τίποτα σε αυτήν τη διεύθυνση." } }, + "errors": { + }, "pages": { } } diff --git a/src/TabKeeper.UI.Wasm/wwwroot/i18n/en.json b/src/TabKeeper.UI.Wasm/wwwroot/i18n/en.json index 19d2cf7..a18cdf8 100644 --- a/src/TabKeeper.UI.Wasm/wwwroot/i18n/en.json +++ b/src/TabKeeper.UI.Wasm/wwwroot/i18n/en.json @@ -8,6 +8,8 @@ "description": "Sorry, there is nothing at this address." } }, + "errors": { + }, "pages": { } } From 752f4100002528d5526528b09a5f85eb4df5d605 Mon Sep 17 00:00:00 2001 From: Panos Date: Sat, 27 Jul 2024 19:48:29 +0300 Subject: [PATCH 16/61] add: Directory.Packages.props --- Directory.Build.props | 38 +++++++++------- Directory.Packages.props | 45 +++++++++++++++++++ TabKeeper.sln | 15 ++++--- TabKeeper.slnx | 35 --------------- src-modules/Core | 2 +- .../TabKeeper.UI.Wasm.csproj | 20 ++++----- src/TabKeeper.UI/TabKeeper.UI.csproj | 4 +- .../TabKeeper.UI.UnitTests.csproj | 18 +++----- 8 files changed, 95 insertions(+), 82 deletions(-) create mode 100644 Directory.Packages.props delete mode 100644 TabKeeper.slnx diff --git a/Directory.Build.props b/Directory.Build.props index 037bc1d..4790e05 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,5 +1,5 @@ - + preview enable @@ -8,29 +8,37 @@ Debug $(NoWarn);CS8509;IDE0039;IDE0130;IDE0290;IDE0060;RZ10012;IDE0052;BL0007; - $(MSBuildThisFileDirectory)artifacts/default - $(MSBuildThisFileDirectory)artifacts/tests - $(MSBuildThisFileDirectory)artifacts/tools - $(MSBuildThisFileDirectory)artifacts/samples - $(MSBuildThisFileDirectory)artifacts/src + $(MSBuildThisFileDirectory)artifacts\$([MSBuild]::MakeRelative($(MSBuildThisFileDirectory),$(MSBuildProjectDirectory)).Replace($(MSBuildProjectName), '')) + true + true + false Panagiotis Athanasiou - panoukos41 - Copyright (c) 2023 $(Authors) - + Copyright (c) 2024 $(Authors) + https://www.github.com/panoukos41/FontAwesome git MIT - - + Project to port great features, component, ideas and libs from the Angular ecosystem to Blazor and .NET. + blazor;angular;components - - - - + + + $(RepositoryUrl) + $(RepositoryLicense) + $(RepositoryDescription) + $(RepositoryTags) + $(RepositoryUrl)/releases + + README.md + + true + true + snupkg + diff --git a/Directory.Packages.props b/Directory.Packages.props new file mode 100644 index 0000000..f959be0 --- /dev/null +++ b/Directory.Packages.props @@ -0,0 +1,45 @@ + + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/TabKeeper.sln b/TabKeeper.sln index e2baba6..1fb8969 100644 --- a/TabKeeper.sln +++ b/TabKeeper.sln @@ -1,5 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 +# 17 VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{1FE5EE5F-70AA-4824-B306-304ADBF3A312}" @@ -11,6 +11,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "root", "root", "{689C1AA2-E .gitignore = .gitignore .gitmodules = .gitmodules Directory.Build.props = Directory.Build.props + Directory.Packages.props = Directory.Packages.props global.json = global.json LICENSE = LICENSE publish.ps1 = publish.ps1 @@ -38,7 +39,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Web", "src-modules\Cor EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blazor", "src-modules\Core\src\Core.Blazor\Core.Blazor.csproj", "{F284A251-6C8E-4F53-8461-E6972204429E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleApp1", "src\ConsoleApp1\ConsoleApp1.csproj", "{C82FCA3D-B469-471D-A320-DFF4E63AFB55}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp1", "src\ConsoleApp1\ConsoleApp1.csproj", "{835E7869-965B-4D97-9043-F598F7AA8557}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -54,10 +55,6 @@ Global {C00185F0-C727-481A-AA5F-23BEF39DAE80}.Debug|Any CPU.Build.0 = Debug|Any CPU {C00185F0-C727-481A-AA5F-23BEF39DAE80}.Release|Any CPU.ActiveCfg = Release|Any CPU {C00185F0-C727-481A-AA5F-23BEF39DAE80}.Release|Any CPU.Build.0 = Release|Any CPU - {C82FCA3D-B469-471D-A320-DFF4E63AFB55}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C82FCA3D-B469-471D-A320-DFF4E63AFB55}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C82FCA3D-B469-471D-A320-DFF4E63AFB55}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C82FCA3D-B469-471D-A320-DFF4E63AFB55}.Release|Any CPU.Build.0 = Release|Any CPU {F9012243-16F3-4CD8-9F86-4F7F6DAEABF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F9012243-16F3-4CD8-9F86-4F7F6DAEABF8}.Debug|Any CPU.Build.0 = Debug|Any CPU {F9012243-16F3-4CD8-9F86-4F7F6DAEABF8}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -82,6 +79,10 @@ Global {F284A251-6C8E-4F53-8461-E6972204429E}.Debug|Any CPU.Build.0 = Debug|Any CPU {F284A251-6C8E-4F53-8461-E6972204429E}.Release|Any CPU.ActiveCfg = Release|Any CPU {F284A251-6C8E-4F53-8461-E6972204429E}.Release|Any CPU.Build.0 = Release|Any CPU + {835E7869-965B-4D97-9043-F598F7AA8557}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {835E7869-965B-4D97-9043-F598F7AA8557}.Debug|Any CPU.Build.0 = Debug|Any CPU + {835E7869-965B-4D97-9043-F598F7AA8557}.Release|Any CPU.ActiveCfg = Release|Any CPU + {835E7869-965B-4D97-9043-F598F7AA8557}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -89,13 +90,13 @@ Global GlobalSection(NestedProjects) = preSolution {38E399A9-B31C-41A4-9594-B672760A7337} = {1FE5EE5F-70AA-4824-B306-304ADBF3A312} {C00185F0-C727-481A-AA5F-23BEF39DAE80} = {1FE5EE5F-70AA-4824-B306-304ADBF3A312} - {C82FCA3D-B469-471D-A320-DFF4E63AFB55} = {1FE5EE5F-70AA-4824-B306-304ADBF3A312} {F9012243-16F3-4CD8-9F86-4F7F6DAEABF8} = {6EEC0350-54B1-4E73-B6EA-3EFB831E01AD} {1E09DF5D-BEB0-4555-8C5E-D68D32817844} = {1FE5EE5F-70AA-4824-B306-304ADBF3A312} {569E0878-B758-42B0-8166-5935C584C03B} = {0F8AC477-3BF8-411F-BC0B-767F820697EA} {FA50AF51-FC1D-4259-BA00-03B5E7592484} = {0F8AC477-3BF8-411F-BC0B-767F820697EA} {6E21EE17-77BD-4072-BDDB-027D38C6D188} = {0F8AC477-3BF8-411F-BC0B-767F820697EA} {F284A251-6C8E-4F53-8461-E6972204429E} = {0F8AC477-3BF8-411F-BC0B-767F820697EA} + {835E7869-965B-4D97-9043-F598F7AA8557} = {1FE5EE5F-70AA-4824-B306-304ADBF3A312} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {26EECD34-43C6-4F7A-A567-0F8AC7F82094} diff --git a/TabKeeper.slnx b/TabKeeper.slnx deleted file mode 100644 index fb40539..0000000 --- a/TabKeeper.slnx +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - -th="Directory.Build.props" /> - - - - - - - \ No newline at end of file diff --git a/src-modules/Core b/src-modules/Core index a16f0f0..6d74274 160000 --- a/src-modules/Core +++ b/src-modules/Core @@ -1 +1 @@ -Subproject commit a16f0f058066fd50aa776b63b8358cd66d47d6eb +Subproject commit 6d74274688eb3b0b7b95806791dc9529850659e0 diff --git a/src/TabKeeper.UI.Wasm/TabKeeper.UI.Wasm.csproj b/src/TabKeeper.UI.Wasm/TabKeeper.UI.Wasm.csproj index 042d675..4ae4c33 100644 --- a/src/TabKeeper.UI.Wasm/TabKeeper.UI.Wasm.csproj +++ b/src/TabKeeper.UI.Wasm/TabKeeper.UI.Wasm.csproj @@ -9,16 +9,16 @@ - - - - - - - - - - + + + + + + + + + + diff --git a/src/TabKeeper.UI/TabKeeper.UI.csproj b/src/TabKeeper.UI/TabKeeper.UI.csproj index 2de529b..8abe319 100644 --- a/src/TabKeeper.UI/TabKeeper.UI.csproj +++ b/src/TabKeeper.UI/TabKeeper.UI.csproj @@ -6,8 +6,8 @@ - - + + diff --git a/tests/TabKeeper.UI.UnitTests/TabKeeper.UI.UnitTests.csproj b/tests/TabKeeper.UI.UnitTests/TabKeeper.UI.UnitTests.csproj index bf3af2f..e52ad51 100644 --- a/tests/TabKeeper.UI.UnitTests/TabKeeper.UI.UnitTests.csproj +++ b/tests/TabKeeper.UI.UnitTests/TabKeeper.UI.UnitTests.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -7,17 +7,11 @@ - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - + + + + + From a009d0beba236fb4f54ceb98101758ac91b133bb Mon Sep 17 00:00:00 2001 From: Panos Date: Sat, 27 Jul 2024 20:02:15 +0300 Subject: [PATCH 17/61] update npm dependenceis --- src/TabKeeper.UI.Wasm/package-lock.json | 507 +++++++++++++----- src/TabKeeper.UI.Wasm/package.json | 3 +- .../tailwind-material-colors.esm.js | 310 ----------- src/TabKeeper.UI.Wasm/tailwind.config.js | 29 +- 4 files changed, 388 insertions(+), 461 deletions(-) delete mode 100644 src/TabKeeper.UI.Wasm/tailwind-material-colors.esm.js diff --git a/src/TabKeeper.UI.Wasm/package-lock.json b/src/TabKeeper.UI.Wasm/package-lock.json index b624150..e7f5441 100644 --- a/src/TabKeeper.UI.Wasm/package-lock.json +++ b/src/TabKeeper.UI.Wasm/package-lock.json @@ -10,7 +10,8 @@ "@tailwindcss/typography": "^0.5.12", "autoprefixer": "^10.4.19", "postcss": "^8.4.38", - "postcss-import": "^16.1.0" + "postcss-import": "^16.1.0", + "tailwind-material-colors": "3.0.2" } }, "node_modules/@alloc/quick-lru": { @@ -18,6 +19,7 @@ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=10" @@ -31,6 +33,7 @@ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "string-width": "^5.1.2", @@ -49,6 +52,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@jridgewell/set-array": "^1.2.1", @@ -64,6 +68,7 @@ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=6.0.0" @@ -74,16 +79,18 @@ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/@jridgewell/trace-mapping": { @@ -91,17 +98,26 @@ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@material/material-color-utilities": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@material/material-color-utilities/-/material-color-utilities-0.2.7.tgz", + "integrity": "sha512-0FCeqG6WvK4/Cc06F/xXMd/pv4FeisI0c1tUpBbfhA2n9Y8eZEv4Karjbmf2ZqQCPUWMrGp8A571tCjizxoTiQ==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -116,6 +132,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">= 8" @@ -126,6 +143,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -140,6 +158,7 @@ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "dev": true, + "license": "MIT", "optional": true, "peer": true, "engines": { @@ -151,6 +170,7 @@ "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.7.tgz", "integrity": "sha512-QE7X69iQI+ZXwldE+rzasvbJiyV/ju1FGHH0Qn2W3FKbuYtqp8LKcy6iSw79fVUT5/Vvf+0XgLCeYVG+UV6hOw==", "dev": true, + "license": "MIT", "dependencies": { "mini-svg-data-uri": "^1.2.3" }, @@ -163,6 +183,7 @@ "resolved": "https://registry.npmjs.org/@tailwindcss/nesting/-/nesting-0.0.0-insiders.565cd3e.tgz", "integrity": "sha512-WhHoFBx19TnH/c+xLwT/sxei6+4RpdfiyG3MYXfmLaMsADmVqBkF7B6lDalgZD9YdM459MF7DtxVbWkOrV7IaQ==", "dev": true, + "license": "MIT", "dependencies": { "postcss-nested": "^5.0.5" }, @@ -171,10 +192,11 @@ } }, "node_modules/@tailwindcss/typography": { - "version": "0.5.12", - "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.12.tgz", - "integrity": "sha512-CNwpBpconcP7ppxmuq3qvaCxiRWnbhANpY/ruH4L5qs2GCiVDJXde/pjj2HWPV1+Q4G9+V/etrwUYopdcjAlyg==", + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.13.tgz", + "integrity": "sha512-ADGcJ8dX21dVVHIwTRgzrcunY6YY9uSlAHHGVKvkA+vLc5qLwEszvKts40lx7z0qc4clpjclwLeK5rVCV2P/uw==", "dev": true, + "license": "MIT", "dependencies": { "lodash.castarray": "^4.4.0", "lodash.isplainobject": "^4.0.6", @@ -185,24 +207,12 @@ "tailwindcss": ">=3.0.0 || insiders" } }, - "node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", - "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", - "dev": true, - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/ansi-regex": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=12" @@ -216,6 +226,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=12" @@ -229,6 +240,7 @@ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/anymatch": { @@ -236,6 +248,7 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "normalize-path": "^3.0.0", @@ -250,6 +263,7 @@ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/autoprefixer": { @@ -271,6 +285,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "browserslist": "^4.23.0", "caniuse-lite": "^1.0.30001599", @@ -294,6 +309,7 @@ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/binary-extensions": { @@ -301,6 +317,7 @@ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -314,28 +331,30 @@ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/browserslist": { - "version": "4.23.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", - "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", + "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", "dev": true, "funding": [ { @@ -351,11 +370,12 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001587", - "electron-to-chromium": "^1.4.668", + "caniuse-lite": "^1.0.30001640", + "electron-to-chromium": "^1.4.820", "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.13" + "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" @@ -369,15 +389,16 @@ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">= 6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001610", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001610.tgz", - "integrity": "sha512-QFutAY4NgaelojVMjY63o6XlZyORPaLfyMnsl3HgnWdJUcX6K0oaJymHjH8PT5Gk7sTm8rvC/c5COUQKXqmOMA==", + "version": "1.0.30001643", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001643.tgz", + "integrity": "sha512-ERgWGNleEilSrHM6iUz/zJNSQTP8Mr21wDWpdgvRwcTXGAq6jMtOUPP4dqFPTdKqZ2wKTdtB+uucZ3MRpAUSmg==", "dev": true, "funding": [ { @@ -392,13 +413,15 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/chokidar": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "anymatch": "~3.1.2", @@ -424,6 +447,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "is-glob": "^4.0.1" @@ -432,12 +456,26 @@ "node": ">= 6" } }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, @@ -450,13 +488,25 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true, - "peer": true + "license": "MIT" + }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">= 6" @@ -467,6 +517,7 @@ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "path-key": "^3.1.0", @@ -482,6 +533,7 @@ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, + "license": "MIT", "bin": { "cssesc": "bin/cssesc" }, @@ -494,6 +546,7 @@ "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", "dev": true, + "license": "Apache-2.0", "peer": true }, "node_modules/dlv": { @@ -501,6 +554,7 @@ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/eastasianwidth": { @@ -508,19 +562,22 @@ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/electron-to-chromium": { - "version": "1.4.738", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.738.tgz", - "integrity": "sha512-lwKft2CLFztD+vEIpesrOtCrko/TFnEJlHFdRhazU7Y/jx5qc4cqsocfVrBg4So4gGe9lvxnbLIoev47WMpg+A==", - "dev": true + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.2.tgz", + "integrity": "sha512-kc4r3U3V3WLaaZqThjYz/Y6z8tJe+7K0bbjUVo3i+LWIypVdMx5nXCkwRe6SWbY6ILqLdc1rKcKmr3HoH7wjSQ==", + "dev": true, + "license": "ISC" }, "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/escalade": { @@ -528,6 +585,7 @@ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -537,6 +595,7 @@ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -554,6 +613,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "is-glob": "^4.0.1" @@ -567,16 +627,18 @@ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "reusify": "^1.0.4" } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "to-regex-range": "^5.0.1" @@ -586,10 +648,11 @@ } }, "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.2.1.tgz", + "integrity": "sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA==", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "cross-spawn": "^7.0.0", @@ -607,6 +670,7 @@ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", "dev": true, + "license": "MIT", "engines": { "node": "*" }, @@ -621,6 +685,7 @@ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -635,29 +700,29 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/glob": { - "version": "10.3.12", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", - "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "foreground-child": "^3.1.0", - "jackspeak": "^2.3.6", - "minimatch": "^9.0.1", - "minipass": "^7.0.4", - "path-scurry": "^1.10.2" + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, "funding": { "url": "https://github.com/sponsors/isaacs" } @@ -667,6 +732,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "is-glob": "^4.0.3" @@ -680,6 +746,7 @@ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, + "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, @@ -687,11 +754,19 @@ "node": ">= 0.4" } }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true, + "license": "MIT" + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "binary-extensions": "^2.0.0" @@ -701,12 +776,16 @@ } }, "node_modules/is-core-module": { - "version": "2.13.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.1.tgz", - "integrity": "sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==", + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", + "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", "dev": true, + "license": "MIT", "dependencies": { - "hasown": "^2.0.0" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -717,6 +796,7 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -727,6 +807,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -737,6 +818,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "is-extglob": "^2.1.1" @@ -750,6 +832,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=0.12.0" @@ -760,20 +843,19 @@ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, + "license": "ISC", "peer": true }, "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, + "license": "BlueOak-1.0.0", "peer": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": ">=14" - }, "funding": { "url": "https://github.com/sponsors/isaacs" }, @@ -782,10 +864,11 @@ } }, "node_modules/jiti": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.0.tgz", - "integrity": "sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q==", + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", "dev": true, + "license": "MIT", "peer": true, "bin": { "jiti": "bin/jiti.js" @@ -796,6 +879,7 @@ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=10" @@ -806,54 +890,58 @@ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/lodash.castarray": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", "dev": true, - "peer": true, - "engines": { - "node": "14 || >=16.14" - } + "license": "ISC", + "peer": true }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">= 8" } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -865,15 +953,17 @@ "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", "dev": true, + "license": "MIT", "bin": { "mini-svg-data-uri": "cli.js" } }, "node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "brace-expansion": "^2.0.1" @@ -886,10 +976,11 @@ } }, "node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, + "license": "ISC", "peer": true, "engines": { "node": ">=16 || 14 >=14.17" @@ -900,6 +991,7 @@ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "any-promise": "^1.0.0", @@ -918,6 +1010,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -926,16 +1019,18 @@ } }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", - "dev": true + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true, + "license": "MIT" }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -946,6 +1041,7 @@ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -955,6 +1051,7 @@ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=0.10.0" @@ -965,16 +1062,26 @@ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">= 6" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", + "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", + "dev": true, + "license": "BlueOak-1.0.0", + "peer": true + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -984,36 +1091,40 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-scurry": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", - "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, + "license": "BlueOak-1.0.0", "peer": true, "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8.6" @@ -1027,6 +1138,7 @@ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -1036,15 +1148,16 @@ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">= 6" } }, "node_modules/postcss": { - "version": "8.4.38", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz", - "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==", + "version": "8.4.40", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.40.tgz", + "integrity": "sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==", "dev": true, "funding": [ { @@ -1060,9 +1173,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.0.0", + "picocolors": "^1.0.1", "source-map-js": "^1.2.0" }, "engines": { @@ -1074,6 +1188,7 @@ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-16.1.0.tgz", "integrity": "sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==", "dev": true, + "license": "MIT", "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", @@ -1091,6 +1206,7 @@ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "camelcase-css": "^2.0.1" @@ -1121,6 +1237,7 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "peer": true, "dependencies": { "lilconfig": "^3.0.0", @@ -1143,10 +1260,11 @@ } }, "node_modules/postcss-load-config/node_modules/lilconfig": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.1.tgz", - "integrity": "sha512-O18pf7nyvHTckunPWCV1XUNXU1piu01y2b7ATJ0ppkUkk8ocqVWBrYjJBCwHDjD/ZWcfyrA0P4gKhzWGi5EINQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=14" @@ -1160,6 +1278,7 @@ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-5.0.6.tgz", "integrity": "sha512-rKqm2Fk0KbA8Vt3AdGN0FB9OBOMDVajMG6ZCf/GoHgdxUJ4sBFp0A/uMIRm+MJUdo33YXEtjqIz8u7DAp8B7DA==", "dev": true, + "license": "MIT", "dependencies": { "postcss-selector-parser": "^6.0.6" }, @@ -1175,10 +1294,11 @@ } }, "node_modules/postcss-selector-parser": { - "version": "6.0.16", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz", - "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==", + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", "dev": true, + "license": "MIT", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -1191,7 +1311,8 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/queue-microtask": { "version": "1.2.3", @@ -1212,6 +1333,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "peer": true }, "node_modules/read-cache": { @@ -1219,6 +1341,7 @@ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", "dev": true, + "license": "MIT", "dependencies": { "pify": "^2.3.0" } @@ -1228,6 +1351,7 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "picomatch": "^2.2.1" @@ -1241,6 +1365,7 @@ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -1258,6 +1383,7 @@ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, + "license": "MIT", "peer": true, "engines": { "iojs": ">=1.0.0", @@ -1283,6 +1409,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "peer": true, "dependencies": { "queue-microtask": "^1.2.2" @@ -1293,6 +1420,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "shebang-regex": "^3.0.0" @@ -1306,6 +1434,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -1316,6 +1445,7 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "dev": true, + "license": "ISC", "peer": true, "engines": { "node": ">=14" @@ -1324,11 +1454,22 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, "node_modules/source-map-js": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } @@ -1338,6 +1479,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "eastasianwidth": "^0.2.0", @@ -1357,6 +1499,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "emoji-regex": "^8.0.0", @@ -1372,6 +1515,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -1382,6 +1526,7 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/string-width-cjs/node_modules/strip-ansi": { @@ -1389,6 +1534,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "ansi-regex": "^5.0.1" @@ -1402,6 +1548,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "ansi-regex": "^6.0.1" @@ -1419,6 +1566,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "ansi-regex": "^5.0.1" @@ -1432,6 +1580,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -1442,6 +1591,7 @@ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", @@ -1465,6 +1615,7 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -1472,11 +1623,53 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/tailwind-material-colors": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tailwind-material-colors/-/tailwind-material-colors-3.0.2.tgz", + "integrity": "sha512-GAOfciMclkv9MdP2DY1JzLQwjBtTCltWZKK8NUuP0GT4Siy7LZ5TWL1cxvGwl/C1LC3XVcxpIZqcv98Je8I6hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@material/material-color-utilities": "^0.2.7", + "tailwind-material-surfaces": "^3.0.2", + "tailwind-mode-aware-colors": "^2.0.2" + }, + "peerDependencies": { + "tailwindcss": "^3.0.0" + } + }, + "node_modules/tailwind-material-surfaces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tailwind-material-surfaces/-/tailwind-material-surfaces-3.0.2.tgz", + "integrity": "sha512-ZElG3IPbSrFr2nzxQ++JvNYtJ2ffDfCc/9idAezXYznHrf9vpO0rV9gH1dPUVmXVSkhHerL34Boz14FGZ2H8uw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tailwindcss-color-mix": "0.0.8" + }, + "peerDependencies": { + "tailwindcss": "^3.0.0" + } + }, + "node_modules/tailwind-mode-aware-colors": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/tailwind-mode-aware-colors/-/tailwind-mode-aware-colors-2.0.2.tgz", + "integrity": "sha512-ohgCFHWrGtT3PY3keun9LUDspt3+DFfaG4tA+MTjv8lCVLe0AxLSUrfAfr2eOcNP2c/V4KpB7qAmAsTJMHrfkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "color": "^4.2.3" + }, + "peerDependencies": { + "tailwindcss": "^3.4.1" + } + }, "node_modules/tailwindcss": { - "version": "3.4.4", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.4.tgz", - "integrity": "sha512-ZoyXOdJjISB7/BcLTR6SEsLgKtDStYyYZVLsUtWChO4Ps20CBad7lfJKVDiejocV4ME1hLmyY0WJE3hSDcmQ2A==", + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.7.tgz", + "integrity": "sha512-rxWZbe87YJb4OcSopb7up2Ba4U82BoiSGUdoDr3Ydrg9ckxFS/YWsvhN323GMcddgU65QRy7JndC7ahhInhvlQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", @@ -1510,11 +1703,22 @@ "node": ">=14.0.0" } }, + "node_modules/tailwindcss-color-mix": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/tailwindcss-color-mix/-/tailwindcss-color-mix-0.0.8.tgz", + "integrity": "sha512-agTN7BAA9eny2WABRX6jpHciQoBoSYGkZfLM1PpHAyNBPErQKFWUm1o1HjwNsZkilJL3hhUi2+H9MoCg+HT89A==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "tailwindcss": "^3.0.0" + } + }, "node_modules/tailwindcss/node_modules/postcss-import": { "version": "15.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "postcss-value-parser": "^4.0.0", @@ -1529,30 +1733,53 @@ } }, "node_modules/tailwindcss/node_modules/postcss-nested": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.1.tgz", - "integrity": "sha512-mEp4xPMi5bSWiMbsgoPfcP74lsWLHkQbZc3sY+jWYd65CUwXrUaTp0fmNpa01ZcETKlIgUdFN/MpS2xZtqL9dQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", "peer": true, "dependencies": { - "postcss-selector-parser": "^6.0.11" + "postcss-selector-parser": "^6.1.1" }, "engines": { "node": ">=12.0" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, "peerDependencies": { "postcss": "^8.2.14" } }, + "node_modules/tailwindcss/node_modules/postcss-selector-parser": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.1.tgz", + "integrity": "sha512-b4dlw/9V8A71rLIDsSwVmak9z2DuBUB7CA1/wSdelNEzqsjoSPeADTWNO09lpH49Diy3/JIZ2bSPB1dI3LJCHg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/thenify": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "any-promise": "^1.0.0" @@ -1563,6 +1790,7 @@ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "thenify": ">= 3.1.0 < 4" @@ -1576,6 +1804,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "is-number": "^7.0.0" @@ -1589,12 +1818,13 @@ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", "dev": true, + "license": "Apache-2.0", "peer": true }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "dev": true, "funding": [ { @@ -1610,9 +1840,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -1625,13 +1856,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "peer": true, "dependencies": { "isexe": "^2.0.0" @@ -1648,6 +1881,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "ansi-styles": "^6.1.0", @@ -1667,6 +1901,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "ansi-styles": "^4.0.0", @@ -1685,6 +1920,7 @@ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "peer": true, "engines": { "node": ">=8" @@ -1695,6 +1931,7 @@ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "color-convert": "^2.0.1" @@ -1711,6 +1948,7 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true, + "license": "MIT", "peer": true }, "node_modules/wrap-ansi-cjs/node_modules/string-width": { @@ -1718,6 +1956,7 @@ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "emoji-regex": "^8.0.0", @@ -1733,6 +1972,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "peer": true, "dependencies": { "ansi-regex": "^5.0.1" @@ -1742,10 +1982,11 @@ } }, "node_modules/yaml": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz", - "integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.0.tgz", + "integrity": "sha512-2wWLbGbYDiSqqIKoPjar3MPgB94ErzCtrNE1FdqGuaO0pi2JGjmE8aW8TDZwzU7vuxcGRdL/4gPQwQ7hD5AMSw==", "dev": true, + "license": "ISC", "peer": true, "bin": { "yaml": "bin.mjs" diff --git a/src/TabKeeper.UI.Wasm/package.json b/src/TabKeeper.UI.Wasm/package.json index 2b4193b..9b1eb31 100644 --- a/src/TabKeeper.UI.Wasm/package.json +++ b/src/TabKeeper.UI.Wasm/package.json @@ -5,6 +5,7 @@ "@tailwindcss/typography": "^0.5.12", "autoprefixer": "^10.4.19", "postcss": "^8.4.38", - "postcss-import": "^16.1.0" + "postcss-import": "^16.1.0", + "tailwind-material-colors": "3.0.2" } } \ No newline at end of file diff --git a/src/TabKeeper.UI.Wasm/tailwind-material-colors.esm.js b/src/TabKeeper.UI.Wasm/tailwind-material-colors.esm.js deleted file mode 100644 index bb28d70..0000000 --- a/src/TabKeeper.UI.Wasm/tailwind-material-colors.esm.js +++ /dev/null @@ -1,310 +0,0 @@ -/** - * @license - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -function t(t){return t<0?-1:0===t?0:1}function r(t,r,e){return(1-e)*t+e*r}function e(t,r,e){return er?r:e}function n(t){return(t%=360)<0&&(t+=360),t}function a(t,r){return[t[0]*r[0][0]+t[1]*r[0][1]+t[2]*r[0][2],t[0]*r[1][0]+t[1]*r[1][1]+t[2]*r[1][2],t[0]*r[2][0]+t[1]*r[2][1]+t[2]*r[2][2]]} -/** - * @license - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */const o=[[.41233895,.35762064,.18051042],[.2126,.7152,.0722],[.01932141,.11916382,.95034478]],i=[[3.2413774792388685,-1.5376652402851851,-.49885366846268053],[-.9691452513005321,1.8758853451067872,.04156585616912061],[.05562093689691305,-.20395524564742123,1.0571799111220335]],s=[95.047,100,108.883];function c(t,r,e){return(255<<24|(255&t)<<16|(255&r)<<8|255&e)>>>0}function l(t){return c(m(t[0]),m(t[1]),m(t[2]))}function u(t){return t>>16&255}function f(t){return t>>8&255}function h(t){return 255&t}function d(t){const r=function(t){return a([b(u(t)),b(f(t)),b(h(t))],o)}(t)[1];return 116*v(r/100)-16}function p(t){return 100*function(t){const r=24389/27,e=t*t*t;return e>216/24389?e:(116*t-16)/r} -/** - * @license - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */((t+16)/116)}function g(t){return 116*v(t/100)-16}function b(t){const r=t/255;return r<=.040449936?r/12.92*100:100*Math.pow((r+.055)/1.055,2.4)}function m(t){const r=t/100;let e=0;return e=r<=.0031308?12.92*r:1.055*Math.pow(r,1/2.4)-.055,n=0,a=255,(o=Math.round(255*e))a?a:o;var n,a,o}function v(t){return t>216/24389?Math.pow(t,1/3):(903.2962962962963*t+16)/116}class y{static make(t=function(){return s}(),e=200/Math.PI*p(50)/100,n=50,a=2,o=!1){const i=t,c=.401288*i[0]+.650173*i[1]+-.051461*i[2],l=-.250268*i[0]+1.204414*i[1]+.045854*i[2],u=-.002079*i[0]+.048952*i[1]+.953127*i[2],f=.8+a/10,h=f>=.9?r(.59,.69,10*(f-.9)):r(.525,.59,10*(f-.8));let d=o?1:f*(1-1/3.6*Math.exp((-e-42)/92));d=d>1?1:d<0?0:d;const g=f,b=[d*(100/c)+1-d,d*(100/l)+1-d,d*(100/u)+1-d],m=1/(5*e+1),v=m*m*m*m,k=1-v,w=v*e+.1*k*k*Math.cbrt(5*e),M=p(n)/t[1],C=1.48+Math.sqrt(M),P=.725/Math.pow(M,.2),x=P,_=[Math.pow(w*b[0]*c/100,.42),Math.pow(w*b[1]*l/100,.42),Math.pow(w*b[2]*u/100,.42)],D=[400*_[0]/(_[0]+27.13),400*_[1]/(_[1]+27.13),400*_[2]/(_[2]+27.13)];return new y(M,(2*D[0]+D[1]+.05*D[2])*P,P,x,h,g,b,w,Math.pow(w,.25),C)}constructor(t,r,e,n,a,o,i,s,c,l){this.n=t,this.aw=r,this.nbb=e,this.ncb=n,this.c=a,this.nc=o,this.rgbD=i,this.fl=s,this.fLRoot=c,this.z=l}}y.DEFAULT=y.make(); -/** - * @license - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -class k{constructor(t,r,e,n,a,o,i,s,c){this.hue=t,this.chroma=r,this.j=e,this.q=n,this.m=a,this.s=o,this.jstar=i,this.astar=s,this.bstar=c}distance(t){const r=this.jstar-t.jstar,e=this.astar-t.astar,n=this.bstar-t.bstar,a=Math.sqrt(r*r+e*e+n*n);return 1.41*Math.pow(a,.63)}static fromInt(t){return k.fromIntInViewingConditions(t,y.DEFAULT)}static fromIntInViewingConditions(r,e){const n=(65280&r)>>8,a=255&r,o=b((16711680&r)>>16),i=b(n),s=b(a),c=.41233895*o+.35762064*i+.18051042*s,l=.2126*o+.7152*i+.0722*s,u=.01932141*o+.11916382*i+.95034478*s,f=.401288*c+.650173*l-.051461*u,h=-.250268*c+1.204414*l+.045854*u,d=-.002079*c+.048952*l+.953127*u,p=e.rgbD[0]*f,g=e.rgbD[1]*h,m=e.rgbD[2]*d,v=Math.pow(e.fl*Math.abs(p)/100,.42),y=Math.pow(e.fl*Math.abs(g)/100,.42),w=Math.pow(e.fl*Math.abs(m)/100,.42),M=400*t(p)*v/(v+27.13),C=400*t(g)*y/(y+27.13),P=400*t(m)*w/(w+27.13),x=(11*M+-12*C+P)/11,_=(M+C-2*P)/9,D=(20*M+20*C+21*P)/20,O=(40*M+20*C+P)/20,I=180*Math.atan2(_,x)/Math.PI,F=I<0?I+360:I>=360?I-360:I,A=F*Math.PI/180,S=O*e.nbb,N=100*Math.pow(S/e.aw,e.c*e.z),T=4/e.c*Math.sqrt(N/100)*(e.aw+4)*e.fLRoot,E=F<20.14?F+360:F,B=5e4/13*(.25*(Math.cos(E*Math.PI/180+2)+3.8))*e.nc*e.ncb*Math.sqrt(x*x+_*_)/(D+.305),L=Math.pow(B,.9)*Math.pow(1.64-Math.pow(.29,e.n),.73),j=L*Math.sqrt(N/100),R=j*e.fLRoot,$=50*Math.sqrt(L*e.c/(e.aw+4)),V=(1+100*.007)*N/(1+.007*N),q=1/.0228*Math.log(1+.0228*R),z=q*Math.cos(A),U=q*Math.sin(A);return new k(F,j,N,T,R,$,V,z,U)}static fromJch(t,r,e){return k.fromJchInViewingConditions(t,r,e,y.DEFAULT)}static fromJchInViewingConditions(t,r,e,n){const a=4/n.c*Math.sqrt(t/100)*(n.aw+4)*n.fLRoot,o=r*n.fLRoot,i=r/Math.sqrt(t/100),s=50*Math.sqrt(i*n.c/(n.aw+4)),c=e*Math.PI/180,l=(1+100*.007)*t/(1+.007*t),u=1/.0228*Math.log(1+.0228*o),f=u*Math.cos(c),h=u*Math.sin(c);return new k(e,r,t,a,o,s,l,f,h)}static fromUcs(t,r,e){return k.fromUcsInViewingConditions(t,r,e,y.DEFAULT)}static fromUcsInViewingConditions(t,r,e,n){const a=r,o=e,i=Math.sqrt(a*a+o*o),s=(Math.exp(.0228*i)-1)/.0228/n.fLRoot;let c=Math.atan2(o,a)*(180/Math.PI);c<0&&(c+=360);const l=t/(1-.007*(t-100));return k.fromJchInViewingConditions(l,s,c,n)}toInt(){return this.viewed(y.DEFAULT)}viewed(r){const e=0===this.chroma||0===this.j?0:this.chroma/Math.sqrt(this.j/100),n=Math.pow(e/Math.pow(1.64-Math.pow(.29,r.n),.73),1/.9),a=this.hue*Math.PI/180,o=.25*(Math.cos(a+2)+3.8),s=r.aw*Math.pow(this.j/100,1/r.c/r.z),l=o*(5e4/13)*r.nc*r.ncb,u=s/r.nbb,f=Math.sin(a),h=Math.cos(a),d=23*(u+.305)*n/(23*l+11*n*h+108*n*f),p=d*h,g=d*f,b=(460*u+451*p+288*g)/1403,v=(460*u-891*p-261*g)/1403,y=(460*u-220*p-6300*g)/1403,k=Math.max(0,27.13*Math.abs(b)/(400-Math.abs(b))),w=t(b)*(100/r.fl)*Math.pow(k,1/.42),M=Math.max(0,27.13*Math.abs(v)/(400-Math.abs(v))),C=t(v)*(100/r.fl)*Math.pow(M,1/.42),P=Math.max(0,27.13*Math.abs(y)/(400-Math.abs(y))),x=t(y)*(100/r.fl)*Math.pow(P,1/.42),_=w/r.rgbD[0],D=C/r.rgbD[1],O=x/r.rgbD[2],I=function(t,r,e){const n=i,a=n[0][0]*t+n[0][1]*r+n[0][2]*e,o=n[1][0]*t+n[1][1]*r+n[1][2]*e,s=n[2][0]*t+n[2][1]*r+n[2][2]*e;return c(m(a),m(o),m(s))}(1.86206786*_-1.01125463*D+.14918677*O,.38752654*_+.62144744*D-.00897398*O,-.0158415*_-.03412294*D+1.04996444*O);return I}static fromXyzInViewingConditions(r,e,n,a){const o=.401288*r+.650173*e-.051461*n,i=-.250268*r+1.204414*e+.045854*n,s=-.002079*r+.048952*e+.953127*n,c=a.rgbD[0]*o,l=a.rgbD[1]*i,u=a.rgbD[2]*s,f=Math.pow(a.fl*Math.abs(c)/100,.42),h=Math.pow(a.fl*Math.abs(l)/100,.42),d=Math.pow(a.fl*Math.abs(u)/100,.42),p=400*t(c)*f/(f+27.13),g=400*t(l)*h/(h+27.13),b=400*t(u)*d/(d+27.13),m=(11*p+-12*g+b)/11,v=(p+g-2*b)/9,y=(20*p+20*g+21*b)/20,w=(40*p+20*g+b)/20,M=180*Math.atan2(v,m)/Math.PI,C=M<0?M+360:M>=360?M-360:M,P=C*Math.PI/180,x=w*a.nbb,_=100*Math.pow(x/a.aw,a.c*a.z),D=4/a.c*Math.sqrt(_/100)*(a.aw+4)*a.fLRoot,O=C<20.14?C+360:C,I=5e4/13*(1/4*(Math.cos(O*Math.PI/180+2)+3.8))*a.nc*a.ncb*Math.sqrt(m*m+v*v)/(y+.305),F=Math.pow(I,.9)*Math.pow(1.64-Math.pow(.29,a.n),.73),A=F*Math.sqrt(_/100),S=A*a.fLRoot,N=50*Math.sqrt(F*a.c/(a.aw+4)),T=(1+100*.007)*_/(1+.007*_),E=Math.log(1+.0228*S)/.0228,B=E*Math.cos(P),L=E*Math.sin(P);return new k(C,A,_,D,S,N,T,B,L)}xyzInViewingConditions(r){const e=0===this.chroma||0===this.j?0:this.chroma/Math.sqrt(this.j/100),n=Math.pow(e/Math.pow(1.64-Math.pow(.29,r.n),.73),1/.9),a=this.hue*Math.PI/180,o=.25*(Math.cos(a+2)+3.8),i=r.aw*Math.pow(this.j/100,1/r.c/r.z),s=o*(5e4/13)*r.nc*r.ncb,c=i/r.nbb,l=Math.sin(a),u=Math.cos(a),f=23*(c+.305)*n/(23*s+11*n*u+108*n*l),h=f*u,d=f*l,p=(460*c+451*h+288*d)/1403,g=(460*c-891*h-261*d)/1403,b=(460*c-220*h-6300*d)/1403,m=Math.max(0,27.13*Math.abs(p)/(400-Math.abs(p))),v=t(p)*(100/r.fl)*Math.pow(m,1/.42),y=Math.max(0,27.13*Math.abs(g)/(400-Math.abs(g))),k=t(g)*(100/r.fl)*Math.pow(y,1/.42),w=Math.max(0,27.13*Math.abs(b)/(400-Math.abs(b))),M=t(b)*(100/r.fl)*Math.pow(w,1/.42),C=v/r.rgbD[0],P=k/r.rgbD[1],x=M/r.rgbD[2];return[1.86206786*C-1.01125463*P+.14918677*x,.38752654*C+.62144744*P-.00897398*x,-.0158415*C-.03412294*P+1.04996444*x]}} -/** - * @license - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */class w{static sanitizeRadians(t){return(t+8*Math.PI)%(2*Math.PI)}static trueDelinearized(t){const r=t/100;let e=0;return e=r<=.0031308?12.92*r:1.055*Math.pow(r,1/2.4)-.055,255*e}static chromaticAdaptation(r){const e=Math.pow(Math.abs(r),.42);return 400*t(r)*e/(e+27.13)}static hueOf(t){const r=a(t,w.SCALED_DISCOUNT_FROM_LINRGB),e=w.chromaticAdaptation(r[0]),n=w.chromaticAdaptation(r[1]),o=w.chromaticAdaptation(r[2]),i=(11*e+-12*n+o)/11,s=(e+n-2*o)/9;return Math.atan2(s,i)}static areInCyclicOrder(t,r,e){return w.sanitizeRadians(r-t)100.01||M[1]>100.01||M[2]>100.01?0:l(M);n-=(_-e)*n/(2*_)}return 0}static solveToInt(t,r,e){if(r<1e-4||e<1e-4||e>99.9999)return function(t){const r=m(p(t));return c(r,r,r)}(e);const a=(t=n(t))/180*Math.PI,o=p(e),i=w.findResultByJ(a,r,o);if(0!==i)return i;return l(w.bisectToLimit(o,a))}static solveToCam(t,r,e){return k.fromInt(w.solveToInt(t,r,e))}}w.SCALED_DISCOUNT_FROM_LINRGB=[[.001200833568784504,.002389694492170889,.0002795742885861124],[.0005891086651375999,.0029785502573438758,.0003270666104008398],[.00010146692491640572,.0005364214359186694,.0032979401770712076]],w.LINRGB_FROM_SCALED_DISCOUNT=[[1373.2198709594231,-1100.4251190754821,-7.278681089101213],[-271.815969077903,559.6580465940733,-32.46047482791194],[1.9622899599665666,-57.173814538844006,308.7233197812385]],w.Y_FROM_LINRGB=[.2126,.7152,.0722],w.CRITICAL_PLANES=[.015176349177441876,.045529047532325624,.07588174588720938,.10623444424209313,.13658714259697685,.16693984095186062,.19729253930674434,.2276452376616281,.2579979360165119,.28835063437139563,.3188300904430532,.350925934958123,.3848314933096426,.42057480301049466,.458183274052838,.4976837250274023,.5391024159806381,.5824650784040898,.6277969426914107,.6751227633498623,.7244668422128921,.775853049866786,.829304845476233,.8848452951698498,.942497089126609,1.0022825574869039,1.0642236851973577,1.1283421258858297,1.1946592148522128,1.2631959812511864,1.3339731595349034,1.407011200216447,1.4823302800086415,1.5599503113873272,1.6398909516233677,1.7221716113234105,1.8068114625156377,1.8938294463134073,1.9832442801866852,2.075074464868551,2.1693382909216234,2.2660538449872063,2.36523901573795,2.4669114995532007,2.5710888059345764,2.6777882626779785,2.7870270208169257,2.898822059350997,3.0131901897720907,3.1301480604002863,3.2497121605402226,3.3718988244681087,3.4967242352587946,3.624204428461639,3.754355295633311,3.887192587735158,4.022731918402185,4.160988767090289,4.301978482107941,4.445716283538092,4.592217266055746,4.741496401646282,4.893568542229298,5.048448422192488,5.20615066083972,5.3666897647573375,5.5300801301023865,5.696336044816294,5.865471690767354,6.037501145825082,6.212438385869475,6.390297286737924,6.571091626112461,6.7548350853498045,6.941541251256611,7.131223617812143,7.323895587840543,7.5195704746346665,7.7182615035334345,7.919981813454504,8.124744458384042,8.332562408825165,8.543448553206703,8.757415699253682,8.974476575321063,9.194643831691977,9.417930041841839,9.644347703669503,9.873909240696694,10.106627003236781,10.342513269534024,10.58158024687427,10.8238400726681,11.069304815507364,11.317986476196008,11.569896988756009,11.825048221409341,12.083451977536606,12.345119996613247,12.610063955123938,12.878295467455942,13.149826086772048,13.42466730586372,13.702830557985108,13.984327217668513,14.269168601521828,14.55736596900856,14.848930523210871,15.143873411576273,15.44220572664832,15.743938506781891,16.04908273684337,16.35764934889634,16.66964922287304,16.985093187232053,17.30399201960269,17.62635644741625,17.95219714852476,18.281524751807332,18.614349837764564,18.95068293910138,19.290534541298456,19.633915083172692,19.98083495742689,20.331304511189067,20.685334046541502,21.042933821039977,21.404114048223256,21.76888489811322,22.137256497705877,22.50923893145328,22.884842241736916,23.264076429332462,23.6469514538663,24.033477234264016,24.42366364919083,24.817520537484558,25.21505769858089,25.61628489293138,26.021211842414342,26.429848230738664,26.842203703840827,27.258287870275353,27.678110301598522,28.10168053274597,28.529008062403893,28.96010235337422,29.39497283293396,29.83362889318845,30.276079891419332,30.722335150426627,31.172403958865512,31.62629557157785,32.08401920991837,32.54558406207592,33.010999283389665,33.4802739966603,33.953417292456834,34.430438229418264,34.911345834551085,35.39614910352207,35.88485700094671,36.37747846067349,36.87402238606382,37.37449765026789,37.87891309649659,38.38727753828926,38.89959975977785,39.41588851594697,39.93615253289054,40.460400508064545,40.98864111053629,41.520882981230194,42.05713473317016,42.597404951718396,43.141702194811224,43.6900349931913,44.24241185063697,44.798841244188324,45.35933162437017,45.92389141541209,46.49252901546552,47.065252796817916,47.64207110610409,48.22299226451468,48.808024568002054,49.3971762874833,49.9904556690408,50.587870934119984,51.189430279724725,51.79514187861014,52.40501387947288,53.0190544071392,53.637271562750364,54.259673423945976,54.88626804504493,55.517063457223934,56.15206766869424,56.79128866487574,57.43473440856916,58.08241284012621,58.734331877617365,59.39049941699807,60.05092333227251,60.715611475655585,61.38457167773311,62.057811747619894,62.7353394731159,63.417162620860914,64.10328893648692,64.79372614476921,65.48848194977529,66.18756403501224,66.89098006357258,67.59873767827808,68.31084450182222,69.02730813691093,69.74813616640164,70.47333615344107,71.20291564160104,71.93688215501312,72.67524319850172,73.41800625771542,74.16517879925733,74.9167682708136,75.67278210128072,76.43322770089146,77.1981124613393,77.96744375590167,78.74122893956174,79.51947534912904,80.30219030335869,81.08938110306934,81.88105503125999,82.67721935322541,83.4778813166706,84.28304815182372,85.09272707154808,85.90692527145302,86.72564993000343,87.54890820862819,88.3767072518277,89.2090541872801,90.04595612594655,90.88742016217518,91.73345337380438,92.58406282226491,93.43925555268066,94.29903859396902,95.16341895893969,96.03240364439274,96.9059996312159,97.78421388448044,98.6670533535366,99.55452497210776]; -/** - * @license - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -class M{static from(t,r,e){return new M(w.solveToInt(t,r,e))}static fromInt(t){return new M(t)}toInt(){return this.argb}get hue(){return this.internalHue}set hue(t){this.setInternalState(w.solveToInt(t,this.internalChroma,this.internalTone))}get chroma(){return this.internalChroma}set chroma(t){this.setInternalState(w.solveToInt(this.internalHue,t,this.internalTone))}get tone(){return this.internalTone}set tone(t){this.setInternalState(w.solveToInt(this.internalHue,this.internalChroma,t))}constructor(t){this.argb=t;const r=k.fromInt(t);this.internalHue=r.hue,this.internalChroma=r.chroma,this.internalTone=d(t),this.argb=t}setInternalState(t){const r=k.fromInt(t);this.internalHue=r.hue,this.internalChroma=r.chroma,this.internalTone=d(t),this.argb=t}inViewingConditions(t){const r=k.fromInt(this.toInt()).xyzInViewingConditions(t),e=k.fromXyzInViewingConditions(r[0],r[1],r[2],y.make());return M.from(e.hue,e.chroma,g(r[1]))}} -/** - * @license - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */class C{static harmonize(t,r){const e=M.fromInt(t),a=M.fromInt(r),o=(i=e.hue,s=a.hue,180-Math.abs(Math.abs(i-s)-180));var i,s;const c=Math.min(.5*o,15),l=n(e.hue+c*(u=e.hue,n(a.hue-u)<=180?1:-1));var u;return M.from(l,e.chroma,e.tone).toInt()}static hctHue(t,r,e){const n=C.cam16Ucs(t,r,e),a=k.fromInt(n),o=k.fromInt(t);return M.from(a.hue,o.chroma,d(t)).toInt()}static cam16Ucs(t,r,e){const n=k.fromInt(t),a=k.fromInt(r),o=n.jstar,i=n.astar,s=n.bstar,c=o+(a.jstar-o)*e,l=i+(a.astar-i)*e,u=s+(a.bstar-s)*e;return k.fromUcs(c,l,u).toInt()}} -/** - * @license - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */class P{static ratioOfTones(t,r){return t=e(0,100,t),r=e(0,100,r),P.ratioOfYs(p(t),p(r))}static ratioOfYs(t,r){const e=t>r?t:r;return(e+5)/((e===r?t:r)+5)}static lighter(t,r){if(t<0||t>100)return-1;const e=p(t),n=r*(e+5)-5,a=P.ratioOfYs(n,e),o=Math.abs(a-r);if(a.04)return-1;const i=g(n)+.4;return i<0||i>100?-1:i}static darker(t,r){if(t<0||t>100)return-1;const e=p(t),n=(e+5)/r-5,a=P.ratioOfYs(e,n),o=Math.abs(a-r);if(a.04)return-1;const i=g(n)-.4;return i<0||i>100?-1:i}static lighterUnsafe(t,r){const e=P.lighter(t,r);return e<0?100:e}static darkerUnsafe(t,r){const e=P.darker(t,r);return e<0?0:e}} -/** - * @license - * Copyright 2023 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */class x{static isDisliked(t){const r=Math.round(t.hue)>=90&&Math.round(t.hue)<=111,e=Math.round(t.chroma)>16,n=Math.round(t.tone)<65;return r&&e&&n}static fixIfDisliked(t){return x.isDisliked(t)?M.from(t.hue,t.chroma,70):t}} -/** - * @license - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */class _{static fromPalette(t){return new _(t.name??"",t.palette,t.tone,t.isBackground??!1,t.background,t.secondBackground,t.contrastCurve,t.toneDeltaPair)}constructor(t,r,e,n,a,o,i,s){if(this.name=t,this.palette=r,this.tone=e,this.isBackground=n,this.background=a,this.secondBackground=o,this.contrastCurve=i,this.toneDeltaPair=s,this.hctCache=new Map,!a&&o)throw new Error(`Color ${t} has secondBackgrounddefined, but background is not defined.`);if(!a&&i)throw new Error(`Color ${t} has contrastCurvedefined, but background is not defined.`);if(a&&!i)throw new Error(`Color ${t} has backgrounddefined, but contrastCurve is not defined.`)}getArgb(t){return this.getHct(t).toInt()}getHct(t){const r=this.hctCache.get(t);if(null!=r)return r;const e=this.getTone(t),n=this.palette(t).getHct(e);return this.hctCache.size>4&&this.hctCache.clear(),this.hctCache.set(t,n),n}getTone(t){const r=t.contrastLevel<0;if(this.toneDeltaPair){const n=this.toneDeltaPair(t),a=n.roleA,o=n.roleB,i=n.delta,s=n.polarity,c=n.stayTogether,l=this.background(t).getTone(t),u="nearer"===s||"lighter"===s&&!t.isDark||"darker"===s&&t.isDark,f=u?a:o,h=u?o:a,d=this.name===f.name,p=t.isDark?1:-1,g=f.contrastCurve.getContrast(t.contrastLevel),b=h.contrastCurve.getContrast(t.contrastLevel),m=f.tone(t);let v=P.ratioOfTones(l,m)>=g?m:_.foregroundTone(l,g);const y=h.tone(t);let k=P.ratioOfTones(l,y)>=b?y:_.foregroundTone(l,b);return r&&(v=_.foregroundTone(l,g),k=_.foregroundTone(l,b)),(k-v)*p>=i||(k=e(0,100,v+i*p),(k-v)*p>=i||(v=e(0,100,k-i*p))),50<=v&&v<60?p>0?(v=60,k=Math.max(k,v+i*p)):(v=49,k=Math.min(k,v+i*p)):50<=k&&k<60&&(c?p>0?(v=60,k=Math.max(k,v+i*p)):(v=49,k=Math.min(k,v+i*p)):k=p>0?60:49),d?v:k}{let e=this.tone(t);if(null==this.background)return e;const n=this.background(t).getTone(t),a=this.contrastCurve.getContrast(t.contrastLevel);if(P.ratioOfTones(n,e)>=a||(e=_.foregroundTone(n,a)),r&&(e=_.foregroundTone(n,a)),this.isBackground&&50<=e&&e<60&&(e=P.ratioOfTones(49,n)>=a?49:60),this.secondBackground){const[r,n]=[this.background,this.secondBackground],[o,i]=[r(t).getTone(t),n(t).getTone(t)],[s,c]=[Math.max(o,i),Math.min(o,i)];if(P.ratioOfTones(s,e)>=a&&P.ratioOfTones(c,e)>=a)return e;const l=P.lighter(s,a),u=P.darker(c,a),f=[];-1!==l&&f.push(l),-1!==u&&f.push(u);return _.tonePrefersLightForeground(o)||_.tonePrefersLightForeground(i)?l<0?100:l:1===f.length?f[0]:u<0?0:u}return e}}static foregroundTone(t,r){const e=P.lighterUnsafe(t,r),n=P.darkerUnsafe(t,r),a=P.ratioOfTones(e,t),o=P.ratioOfTones(n,t);if(_.tonePrefersLightForeground(t)){const t=Math.abs(a-o)<.1&&a=r||a>=o||t?e:n}return o>=r||o>=a?n:e}static tonePrefersLightForeground(t){return Math.round(t)<60}static toneAllowsLightForeground(t){return Math.round(t)<=49}static enableLightForeground(t){return _.tonePrefersLightForeground(t)&&!_.toneAllowsLightForeground(t)?49:t}} -/** - * @license - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */var D;!function(t){t[t.MONOCHROME=0]="MONOCHROME",t[t.NEUTRAL=1]="NEUTRAL",t[t.TONAL_SPOT=2]="TONAL_SPOT",t[t.VIBRANT=3]="VIBRANT",t[t.EXPRESSIVE=4]="EXPRESSIVE",t[t.FIDELITY=5]="FIDELITY",t[t.CONTENT=6]="CONTENT",t[t.RAINBOW=7]="RAINBOW",t[t.FRUIT_SALAD=8]="FRUIT_SALAD"}(D||(D={})); -/** - * @license - * Copyright 2023 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -class O{constructor(t,r,e,n){this.low=t,this.normal=r,this.medium=e,this.high=n}getContrast(t){return t<=-1?this.low:t<0?r(this.low,this.normal,(t- -1)/1):t<.5?r(this.normal,this.medium,(t-0)/.5):t<1?r(this.medium,this.high,(t-.5)/.5):this.high}} -/** - * @license - * Copyright 2023 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */class I{constructor(t,r,e,n,a){this.roleA=t,this.roleB=r,this.delta=e,this.polarity=n,this.stayTogether=a}} -/** - * @license - * Copyright 2022 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */function F(t){return t.variant===D.FIDELITY||t.variant===D.CONTENT}function A(t){return t.variant===D.MONOCHROME}function S(t,r){const e=t.inViewingConditions(function(t){return y.make(void 0,void 0,t.isDark?30:80,void 0,void 0)}(r));return _.tonePrefersLightForeground(t.tone)&&!_.toneAllowsLightForeground(e.tone)?_.enableLightForeground(t.tone):_.enableLightForeground(e.tone)}class N{static highestSurface(t){return t.isDark?N.surfaceBright:N.surfaceDim}}N.contentAccentToneDelta=15,N.primaryPaletteKeyColor=_.fromPalette({name:"primary_palette_key_color",palette:t=>t.primaryPalette,tone:t=>t.primaryPalette.keyColor.tone}),N.secondaryPaletteKeyColor=_.fromPalette({name:"secondary_palette_key_color",palette:t=>t.secondaryPalette,tone:t=>t.secondaryPalette.keyColor.tone}),N.tertiaryPaletteKeyColor=_.fromPalette({name:"tertiary_palette_key_color",palette:t=>t.tertiaryPalette,tone:t=>t.tertiaryPalette.keyColor.tone}),N.neutralPaletteKeyColor=_.fromPalette({name:"neutral_palette_key_color",palette:t=>t.neutralPalette,tone:t=>t.neutralPalette.keyColor.tone}),N.neutralVariantPaletteKeyColor=_.fromPalette({name:"neutral_variant_palette_key_color",palette:t=>t.neutralVariantPalette,tone:t=>t.neutralVariantPalette.keyColor.tone}),N.background=_.fromPalette({name:"background",palette:t=>t.neutralPalette,tone:t=>t.isDark?6:98,isBackground:!0}),N.onBackground=_.fromPalette({name:"on_background",palette:t=>t.neutralPalette,tone:t=>t.isDark?90:10,background:t=>N.background,contrastCurve:new O(3,3,4.5,7)}),N.surface=_.fromPalette({name:"surface",palette:t=>t.neutralPalette,tone:t=>t.isDark?6:98,isBackground:!0}),N.surfaceDim=_.fromPalette({name:"surface_dim",palette:t=>t.neutralPalette,tone:t=>t.isDark?6:87,isBackground:!0}),N.surfaceBright=_.fromPalette({name:"surface_bright",palette:t=>t.neutralPalette,tone:t=>t.isDark?24:98,isBackground:!0}),N.surfaceContainerLowest=_.fromPalette({name:"surface_container_lowest",palette:t=>t.neutralPalette,tone:t=>t.isDark?4:100,isBackground:!0}),N.surfaceContainerLow=_.fromPalette({name:"surface_container_low",palette:t=>t.neutralPalette,tone:t=>t.isDark?10:96,isBackground:!0}),N.surfaceContainer=_.fromPalette({name:"surface_container",palette:t=>t.neutralPalette,tone:t=>t.isDark?12:94,isBackground:!0}),N.surfaceContainerHigh=_.fromPalette({name:"surface_container_high",palette:t=>t.neutralPalette,tone:t=>t.isDark?17:92,isBackground:!0}),N.surfaceContainerHighest=_.fromPalette({name:"surface_container_highest",palette:t=>t.neutralPalette,tone:t=>t.isDark?22:90,isBackground:!0}),N.onSurface=_.fromPalette({name:"on_surface",palette:t=>t.neutralPalette,tone:t=>t.isDark?90:10,background:t=>N.highestSurface(t),contrastCurve:new O(4.5,7,11,21)}),N.surfaceVariant=_.fromPalette({name:"surface_variant",palette:t=>t.neutralVariantPalette,tone:t=>t.isDark?30:90,isBackground:!0}),N.onSurfaceVariant=_.fromPalette({name:"on_surface_variant",palette:t=>t.neutralVariantPalette,tone:t=>t.isDark?80:30,background:t=>N.highestSurface(t),contrastCurve:new O(3,4.5,7,11)}),N.inverseSurface=_.fromPalette({name:"inverse_surface",palette:t=>t.neutralPalette,tone:t=>t.isDark?90:20}),N.inverseOnSurface=_.fromPalette({name:"inverse_on_surface",palette:t=>t.neutralPalette,tone:t=>t.isDark?20:95,background:t=>N.inverseSurface,contrastCurve:new O(4.5,7,11,21)}),N.outline=_.fromPalette({name:"outline",palette:t=>t.neutralVariantPalette,tone:t=>t.isDark?60:50,background:t=>N.highestSurface(t),contrastCurve:new O(1.5,3,4.5,7)}),N.outlineVariant=_.fromPalette({name:"outline_variant",palette:t=>t.neutralVariantPalette,tone:t=>t.isDark?30:80,background:t=>N.highestSurface(t),contrastCurve:new O(1,1,3,7)}),N.shadow=_.fromPalette({name:"shadow",palette:t=>t.neutralPalette,tone:t=>0}),N.scrim=_.fromPalette({name:"scrim",palette:t=>t.neutralPalette,tone:t=>0}),N.surfaceTint=_.fromPalette({name:"surface_tint",palette:t=>t.primaryPalette,tone:t=>t.isDark?80:40,isBackground:!0}),N.primary=_.fromPalette({name:"primary",palette:t=>t.primaryPalette,tone:t=>A(t)?t.isDark?100:0:t.isDark?80:40,isBackground:!0,background:t=>N.highestSurface(t),contrastCurve:new O(3,4.5,7,11),toneDeltaPair:t=>new I(N.primaryContainer,N.primary,15,"nearer",!1)}),N.onPrimary=_.fromPalette({name:"on_primary",palette:t=>t.primaryPalette,tone:t=>A(t)?t.isDark?10:90:t.isDark?20:100,background:t=>N.primary,contrastCurve:new O(4.5,7,11,21)}),N.primaryContainer=_.fromPalette({name:"primary_container",palette:t=>t.primaryPalette,tone:t=>F(t)?S(t.sourceColorHct,t):A(t)?t.isDark?85:25:t.isDark?30:90,isBackground:!0,background:t=>N.highestSurface(t),contrastCurve:new O(1,1,3,7),toneDeltaPair:t=>new I(N.primaryContainer,N.primary,15,"nearer",!1)}),N.onPrimaryContainer=_.fromPalette({name:"on_primary_container",palette:t=>t.primaryPalette,tone:t=>F(t)?_.foregroundTone(N.primaryContainer.tone(t),4.5):A(t)?t.isDark?0:100:t.isDark?90:10,background:t=>N.primaryContainer,contrastCurve:new O(4.5,7,11,21)}),N.inversePrimary=_.fromPalette({name:"inverse_primary",palette:t=>t.primaryPalette,tone:t=>t.isDark?40:80,background:t=>N.inverseSurface,contrastCurve:new O(3,4.5,7,11)}),N.secondary=_.fromPalette({name:"secondary",palette:t=>t.secondaryPalette,tone:t=>t.isDark?80:40,isBackground:!0,background:t=>N.highestSurface(t),contrastCurve:new O(3,4.5,7,11),toneDeltaPair:t=>new I(N.secondaryContainer,N.secondary,15,"nearer",!1)}),N.onSecondary=_.fromPalette({name:"on_secondary",palette:t=>t.secondaryPalette,tone:t=>A(t)?t.isDark?10:100:t.isDark?20:100,background:t=>N.secondary,contrastCurve:new O(4.5,7,11,21)}),N.secondaryContainer=_.fromPalette({name:"secondary_container",palette:t=>t.secondaryPalette,tone:t=>{const r=t.isDark?30:90;if(A(t))return t.isDark?30:85;if(!F(t))return r;let e=function(t,r,e,n){let a=e,o=M.from(t,r,e);if(o.chromai.chroma)break;if(Math.abs(i.chroma-r)<.4)break;Math.abs(i.chroma-r)N.highestSurface(t),contrastCurve:new O(1,1,3,7),toneDeltaPair:t=>new I(N.secondaryContainer,N.secondary,15,"nearer",!1)}),N.onSecondaryContainer=_.fromPalette({name:"on_secondary_container",palette:t=>t.secondaryPalette,tone:t=>F(t)?_.foregroundTone(N.secondaryContainer.tone(t),4.5):t.isDark?90:10,background:t=>N.secondaryContainer,contrastCurve:new O(4.5,7,11,21)}),N.tertiary=_.fromPalette({name:"tertiary",palette:t=>t.tertiaryPalette,tone:t=>A(t)?t.isDark?90:25:t.isDark?80:40,isBackground:!0,background:t=>N.highestSurface(t),contrastCurve:new O(3,4.5,7,11),toneDeltaPair:t=>new I(N.tertiaryContainer,N.tertiary,15,"nearer",!1)}),N.onTertiary=_.fromPalette({name:"on_tertiary",palette:t=>t.tertiaryPalette,tone:t=>A(t)?t.isDark?10:90:t.isDark?20:100,background:t=>N.tertiary,contrastCurve:new O(4.5,7,11,21)}),N.tertiaryContainer=_.fromPalette({name:"tertiary_container",palette:t=>t.tertiaryPalette,tone:t=>{if(A(t))return t.isDark?60:49;if(!F(t))return t.isDark?30:90;const r=S(t.tertiaryPalette.getHct(t.sourceColorHct.tone),t),e=t.tertiaryPalette.getHct(r);return x.fixIfDisliked(e).tone},isBackground:!0,background:t=>N.highestSurface(t),contrastCurve:new O(1,1,3,7),toneDeltaPair:t=>new I(N.tertiaryContainer,N.tertiary,15,"nearer",!1)}),N.onTertiaryContainer=_.fromPalette({name:"on_tertiary_container",palette:t=>t.tertiaryPalette,tone:t=>A(t)?t.isDark?0:100:F(t)?_.foregroundTone(N.tertiaryContainer.tone(t),4.5):t.isDark?90:10,background:t=>N.tertiaryContainer,contrastCurve:new O(4.5,7,11,21)}),N.error=_.fromPalette({name:"error",palette:t=>t.errorPalette,tone:t=>t.isDark?80:40,isBackground:!0,background:t=>N.highestSurface(t),contrastCurve:new O(3,4.5,7,11),toneDeltaPair:t=>new I(N.errorContainer,N.error,15,"nearer",!1)}),N.onError=_.fromPalette({name:"on_error",palette:t=>t.errorPalette,tone:t=>t.isDark?20:100,background:t=>N.error,contrastCurve:new O(4.5,7,11,21)}),N.errorContainer=_.fromPalette({name:"error_container",palette:t=>t.errorPalette,tone:t=>t.isDark?30:90,isBackground:!0,background:t=>N.highestSurface(t),contrastCurve:new O(1,1,3,7),toneDeltaPair:t=>new I(N.errorContainer,N.error,15,"nearer",!1)}),N.onErrorContainer=_.fromPalette({name:"on_error_container",palette:t=>t.errorPalette,tone:t=>t.isDark?90:10,background:t=>N.errorContainer,contrastCurve:new O(4.5,7,11,21)}),N.primaryFixed=_.fromPalette({name:"primary_fixed",palette:t=>t.primaryPalette,tone:t=>A(t)?40:90,isBackground:!0,background:t=>N.highestSurface(t),contrastCurve:new O(1,1,3,7),toneDeltaPair:t=>new I(N.primaryFixed,N.primaryFixedDim,10,"lighter",!0)}),N.primaryFixedDim=_.fromPalette({name:"primary_fixed_dim",palette:t=>t.primaryPalette,tone:t=>A(t)?30:80,isBackground:!0,background:t=>N.highestSurface(t),contrastCurve:new O(1,1,3,7),toneDeltaPair:t=>new I(N.primaryFixed,N.primaryFixedDim,10,"lighter",!0)}),N.onPrimaryFixed=_.fromPalette({name:"on_primary_fixed",palette:t=>t.primaryPalette,tone:t=>A(t)?100:10,background:t=>N.primaryFixedDim,secondBackground:t=>N.primaryFixed,contrastCurve:new O(4.5,7,11,21)}),N.onPrimaryFixedVariant=_.fromPalette({name:"on_primary_fixed_variant",palette:t=>t.primaryPalette,tone:t=>A(t)?90:30,background:t=>N.primaryFixedDim,secondBackground:t=>N.primaryFixed,contrastCurve:new O(3,4.5,7,11)}),N.secondaryFixed=_.fromPalette({name:"secondary_fixed",palette:t=>t.secondaryPalette,tone:t=>A(t)?80:90,isBackground:!0,background:t=>N.highestSurface(t),contrastCurve:new O(1,1,3,7),toneDeltaPair:t=>new I(N.secondaryFixed,N.secondaryFixedDim,10,"lighter",!0)}),N.secondaryFixedDim=_.fromPalette({name:"secondary_fixed_dim",palette:t=>t.secondaryPalette,tone:t=>A(t)?70:80,isBackground:!0,background:t=>N.highestSurface(t),contrastCurve:new O(1,1,3,7),toneDeltaPair:t=>new I(N.secondaryFixed,N.secondaryFixedDim,10,"lighter",!0)}),N.onSecondaryFixed=_.fromPalette({name:"on_secondary_fixed",palette:t=>t.secondaryPalette,tone:t=>10,background:t=>N.secondaryFixedDim,secondBackground:t=>N.secondaryFixed,contrastCurve:new O(4.5,7,11,21)}),N.onSecondaryFixedVariant=_.fromPalette({name:"on_secondary_fixed_variant",palette:t=>t.secondaryPalette,tone:t=>A(t)?25:30,background:t=>N.secondaryFixedDim,secondBackground:t=>N.secondaryFixed,contrastCurve:new O(3,4.5,7,11)}),N.tertiaryFixed=_.fromPalette({name:"tertiary_fixed",palette:t=>t.tertiaryPalette,tone:t=>A(t)?40:90,isBackground:!0,background:t=>N.highestSurface(t),contrastCurve:new O(1,1,3,7),toneDeltaPair:t=>new I(N.tertiaryFixed,N.tertiaryFixedDim,10,"lighter",!0)}),N.tertiaryFixedDim=_.fromPalette({name:"tertiary_fixed_dim",palette:t=>t.tertiaryPalette,tone:t=>A(t)?30:80,isBackground:!0,background:t=>N.highestSurface(t),contrastCurve:new O(1,1,3,7),toneDeltaPair:t=>new I(N.tertiaryFixed,N.tertiaryFixedDim,10,"lighter",!0)}),N.onTertiaryFixed=_.fromPalette({name:"on_tertiary_fixed",palette:t=>t.tertiaryPalette,tone:t=>A(t)?100:10,background:t=>N.tertiaryFixedDim,secondBackground:t=>N.tertiaryFixed,contrastCurve:new O(4.5,7,11,21)}),N.onTertiaryFixedVariant=_.fromPalette({name:"on_tertiary_fixed_variant",palette:t=>t.tertiaryPalette,tone:t=>A(t)?90:30,background:t=>N.tertiaryFixedDim,secondBackground:t=>N.tertiaryFixed,contrastCurve:new O(3,4.5,7,11)}); -/** - * @license - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -class T{static fromInt(t){const r=M.fromInt(t);return T.fromHct(r)}static fromHct(t){return new T(t.hue,t.chroma,t)}static fromHueAndChroma(t,r){return new T(t,r,T.createKeyColor(t,r))}constructor(t,r,e){this.hue=t,this.chroma=r,this.keyColor=e,this.cache=new Map}static createKeyColor(t,r){let e=M.from(t,r,50),n=Math.abs(e.chroma-r);for(let a=1;a<50;a+=1){if(Math.round(r)===Math.round(e.chroma))return e;const o=M.from(t,r,50+a),i=Math.abs(o.chroma-r);i>>0}function R(t){return parseInt(t,16)} -/** - * @license - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */const $=t=>t.split("").map(((t,r)=>t.toUpperCase()===t?`${0!==r?"-":""}${t.toLowerCase()}`:t)).join(""),V=t=>{const{primary:r,...e}=t,n=j(r),a=B.light(n),o=B.dark(n);a.props.onInverseSurface=a.props.inverseOnSurface,delete a.props.inverseOnSurface,o.onInverseSurface=o.props.inverseOnSurface,delete o.props.inverseOnSurface;const i={transparent:"transparent",current:"currentColor",black:"#000000",white:"#ffffff"};return Object.keys(a.props).forEach((t=>{if(!["shadow","scrim"].includes(t)){const r=$(t);i[`${r}-light`]=L(a.props[t]),i[`${r}-dark`]=L(o.props[t])}})),Object.keys(e).forEach((t=>{const r=e[t],a="string"==typeof r?r:r.hex,o=r===a||r.harmonize,{light:s,dark:c}=function(t,r){let e=r.value;const n=e,a=t;r.blend&&(e=C.harmonize(n,a));const o=E.of(e).a1;return{color:r,value:e,light:{color:o.tone(40),onColor:o.tone(100),colorContainer:o.tone(90),onColorContainer:o.tone(10)},dark:{color:o.tone(80),onColor:o.tone(20),colorContainer:o.tone(30),onColorContainer:o.tone(90)}}}(n,{value:j(a),blend:o}),l=$(t);i[`${l}-light`]=L(s.color),i[`on-${l}-light`]=L(s.onColor),i[`${l}-container-light`]=L(s.colorContainer),i[`on-${l}-container-light`]=L(s.onColorContainer),i[`${l}-dark`]=L(c.color),i[`on-${l}-dark`]=L(c.onColor),i[`${l}-container-dark`]=L(c.colorContainer),i[`on-${l}-container-dark`]=L(c.onColorContainer)})),i};"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self&&self;var q={},z={};!function(t){function r(t,r){return{handler:t,config:r}}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:()=>e}),r.withOptions=function(t,r=(()=>({}))){const e=function(e){return{__options:e,handler:t(e),config:r(e)}};return e.__isOptionsFunction=!0,e.__pluginFunction=t,e.__configFunction=r,e};const e=r}(z),function(t){Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:()=>e});function r(t){return t&&t.__esModule?t:{default:t}}const e=r(z).default}(q);var U=(q.__esModule?q:{default:q}).default,H={exports:{}};H.exports=function(){for(var t=function(t,r,e){return void 0===r&&(r=0),void 0===e&&(e=1),te?e:t},r=t,e=function(t){t._clipped=!1,t._unclipped=t.slice(0);for(var e=0;e<=3;e++)e<3?((t[e]<0||t[e]>255)&&(t._clipped=!0),t[e]=r(t[e],0,255)):3===e&&(t[e]=r(t[e],0,1));return t},n={},a=0,o=["Boolean","Number","String","Function","Array","Date","RegExp","Undefined","Null"];a=3?Array.prototype.slice.call(t):"object"==c(t[0])&&r?r.split("").filter((function(r){return void 0!==t[0][r]})).map((function(r){return t[0][r]})):t[0]},u=s,f=function(t){if(t.length<2)return null;var r=t.length-1;return"string"==u(t[r])?t[r].toLowerCase():null},h=Math.PI,d={clip_rgb:e,limit:t,type:s,unpack:l,last:f,PI:h,TWOPI:2*h,PITHIRD:h/3,DEG2RAD:h/180,RAD2DEG:180/h},p={format:{},autodetect:[]},g=d.last,b=d.clip_rgb,m=d.type,v=p,y=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e=this;if("object"===m(t[0])&&t[0].constructor&&t[0].constructor===this.constructor)return t[0];var n=g(t),a=!1;if(!n){a=!0,v.sorted||(v.autodetect=v.autodetect.sort((function(t,r){return r.p-t.p})),v.sorted=!0);for(var o=0,i=v.autodetect;o4?t[4]:1;return 1===o?[0,0,0,i]:[e>=1?0:255*(1-e)*(1-o),n>=1?0:255*(1-n)*(1-o),a>=1?0:255*(1-a)*(1-o),i]},I=O,F=M,A=k,S=p,N=d.unpack,T=d.type,E=_;A.prototype.cmyk=function(){return E(this._rgb)},F.cmyk=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return new(Function.prototype.bind.apply(A,[null].concat(t,["cmyk"])))},S.format.cmyk=I,S.autodetect.push({p:2,test:function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];if(t=N(t,"cmyk"),"array"===T(t)&&4===t.length)return"cmyk"}});var B=d.unpack,L=d.last,j=function(t){return Math.round(100*t)/100},R=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e=B(t,"hsla"),n=L(t)||"lsa";return e[0]=j(e[0]||0),e[1]=j(100*e[1])+"%",e[2]=j(100*e[2])+"%","hsla"===n||e.length>3&&e[3]<1?(e[3]=e.length>3?e[3]:1,n="hsla"):e.length=3,n+"("+e.join(",")+")"},$=R,V=d.unpack,q=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e=(t=V(t,"rgba"))[0],n=t[1],a=t[2];e/=255,n/=255,a/=255;var o,i,s=Math.min(e,n,a),c=Math.max(e,n,a),l=(c+s)/2;return c===s?(o=0,i=Number.NaN):o=l<.5?(c-s)/(c+s):(c-s)/(2-c-s),e==c?i=(n-a)/(c-s):n==c?i=2+(a-e)/(c-s):a==c&&(i=4+(e-n)/(c-s)),(i*=60)<0&&(i+=360),t.length>3&&void 0!==t[3]?[i,o,l,t[3]]:[i,o,l]},z=q,U=d.unpack,H=d.last,G=$,Y=z,K=Math.round,X=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e=U(t,"rgba"),n=H(t)||"rgb";return"hsl"==n.substr(0,3)?G(Y(e),n):(e[0]=K(e[0]),e[1]=K(e[1]),e[2]=K(e[2]),("rgba"===n||e.length>3&&e[3]<1)&&(e[3]=e.length>3?e[3]:1,n="rgba"),n+"("+e.slice(0,"rgb"===n?3:4).join(",")+")")},J=X,W=d.unpack,Z=Math.round,Q=function(){for(var t,r=[],e=arguments.length;e--;)r[e]=arguments[e];var n,a,o,i=(r=W(r,"hsl"))[0],s=r[1],c=r[2];if(0===s)n=a=o=255*c;else{var l=[0,0,0],u=[0,0,0],f=c<.5?c*(1+s):c+s-c*s,h=2*c-f,d=i/360;l[0]=d+1/3,l[1]=d,l[2]=d-1/3;for(var p=0;p<3;p++)l[p]<0&&(l[p]+=1),l[p]>1&&(l[p]-=1),6*l[p]<1?u[p]=h+6*(f-h)*l[p]:2*l[p]<1?u[p]=f:3*l[p]<2?u[p]=h+(f-h)*(2/3-l[p])*6:u[p]=h;n=(t=[Z(255*u[0]),Z(255*u[1]),Z(255*u[2])])[0],a=t[1],o=t[2]}return r.length>3?[n,a,o,r[3]]:[n,a,o,1]},tt=Q,rt=tt,et=p,nt=/^rgb\(\s*(-?\d+),\s*(-?\d+)\s*,\s*(-?\d+)\s*\)$/,at=/^rgba\(\s*(-?\d+),\s*(-?\d+)\s*,\s*(-?\d+)\s*,\s*([01]|[01]?\.\d+)\)$/,ot=/^rgb\(\s*(-?\d+(?:\.\d+)?)%,\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*\)$/,it=/^rgba\(\s*(-?\d+(?:\.\d+)?)%,\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/,st=/^hsl\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*\)$/,ct=/^hsla\(\s*(-?\d+(?:\.\d+)?),\s*(-?\d+(?:\.\d+)?)%\s*,\s*(-?\d+(?:\.\d+)?)%\s*,\s*([01]|[01]?\.\d+)\)$/,lt=Math.round,ut=function(t){var r;if(t=t.toLowerCase().trim(),et.format.named)try{return et.format.named(t)}catch(t){}if(r=t.match(nt)){for(var e=r.slice(1,4),n=0;n<3;n++)e[n]=+e[n];return e[3]=1,e}if(r=t.match(at)){for(var a=r.slice(1,5),o=0;o<4;o++)a[o]=+a[o];return a}if(r=t.match(ot)){for(var i=r.slice(1,4),s=0;s<3;s++)i[s]=lt(2.55*i[s]);return i[3]=1,i}if(r=t.match(it)){for(var c=r.slice(1,5),l=0;l<3;l++)c[l]=lt(2.55*c[l]);return c[3]=+c[3],c}if(r=t.match(st)){var u=r.slice(1,4);u[1]*=.01,u[2]*=.01;var f=rt(u);return f[3]=1,f}if(r=t.match(ct)){var h=r.slice(1,4);h[1]*=.01,h[2]*=.01;var d=rt(h);return d[3]=+r[4],d}};ut.test=function(t){return nt.test(t)||at.test(t)||ot.test(t)||it.test(t)||st.test(t)||ct.test(t)};var ft=ut,ht=M,dt=k,pt=p,gt=d.type,bt=J,mt=ft;dt.prototype.css=function(t){return bt(this._rgb,t)},ht.css=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return new(Function.prototype.bind.apply(dt,[null].concat(t,["css"])))},pt.format.css=mt,pt.autodetect.push({p:5,test:function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];if(!r.length&&"string"===gt(t)&&mt.test(t))return"css"}});var vt=k,yt=M,kt=p,wt=d.unpack;kt.format.gl=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e=wt(t,"rgba");return e[0]*=255,e[1]*=255,e[2]*=255,e},yt.gl=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return new(Function.prototype.bind.apply(vt,[null].concat(t,["gl"])))},vt.prototype.gl=function(){var t=this._rgb;return[t[0]/255,t[1]/255,t[2]/255,t[3]]};var Mt=d.unpack,Ct=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e,n=Mt(t,"rgb"),a=n[0],o=n[1],i=n[2],s=Math.min(a,o,i),c=Math.max(a,o,i),l=c-s,u=100*l/255,f=s/(255-l)*100;return 0===l?e=Number.NaN:(a===c&&(e=(o-i)/l),o===c&&(e=2+(i-a)/l),i===c&&(e=4+(a-o)/l),(e*=60)<0&&(e+=360)),[e,u,f]},Pt=Ct,xt=d.unpack,_t=Math.floor,Dt=function(){for(var t,r,e,n,a,o,i=[],s=arguments.length;s--;)i[s]=arguments[s];var c,l,u,f=(i=xt(i,"hcg"))[0],h=i[1],d=i[2];d*=255;var p=255*h;if(0===h)c=l=u=d;else{360===f&&(f=0),f>360&&(f-=360),f<0&&(f+=360);var g=_t(f/=60),b=f-g,m=d*(1-h),v=m+p*(1-b),y=m+p*b,k=m+p;switch(g){case 0:c=(t=[k,y,m])[0],l=t[1],u=t[2];break;case 1:c=(r=[v,k,m])[0],l=r[1],u=r[2];break;case 2:c=(e=[m,k,y])[0],l=e[1],u=e[2];break;case 3:c=(n=[m,v,k])[0],l=n[1],u=n[2];break;case 4:c=(a=[y,m,k])[0],l=a[1],u=a[2];break;case 5:c=(o=[k,m,v])[0],l=o[1],u=o[2]}}return[c,l,u,i.length>3?i[3]:1]},Ot=Dt,It=d.unpack,Ft=d.type,At=M,St=k,Nt=p,Tt=Pt;St.prototype.hcg=function(){return Tt(this._rgb)},At.hcg=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return new(Function.prototype.bind.apply(St,[null].concat(t,["hcg"])))},Nt.format.hcg=Ot,Nt.autodetect.push({p:1,test:function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];if(t=It(t,"hcg"),"array"===Ft(t)&&3===t.length)return"hcg"}});var Et=d.unpack,Bt=d.last,Lt=Math.round,jt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e=Et(t,"rgba"),n=e[0],a=e[1],o=e[2],i=e[3],s=Bt(t)||"auto";void 0===i&&(i=1),"auto"===s&&(s=i<1?"rgba":"rgb");var c="000000"+((n=Lt(n))<<16|(a=Lt(a))<<8|(o=Lt(o))).toString(16);c=c.substr(c.length-6);var l="0"+Lt(255*i).toString(16);switch(l=l.substr(l.length-2),s.toLowerCase()){case"rgba":return"#"+c+l;case"argb":return"#"+l+c;default:return"#"+c}},Rt=jt,$t=/^#?([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,Vt=/^#?([A-Fa-f0-9]{8}|[A-Fa-f0-9]{4})$/,qt=function(t){if(t.match($t)){4!==t.length&&7!==t.length||(t=t.substr(1)),3===t.length&&(t=(t=t.split(""))[0]+t[0]+t[1]+t[1]+t[2]+t[2]);var r=parseInt(t,16);return[r>>16,r>>8&255,255&r,1]}if(t.match(Vt)){5!==t.length&&9!==t.length||(t=t.substr(1)),4===t.length&&(t=(t=t.split(""))[0]+t[0]+t[1]+t[1]+t[2]+t[2]+t[3]+t[3]);var e=parseInt(t,16);return[e>>24&255,e>>16&255,e>>8&255,Math.round((255&e)/255*100)/100]}throw new Error("unknown hex color: "+t)},zt=M,Ut=k,Ht=d.type,Gt=p,Yt=Rt;Ut.prototype.hex=function(t){return Yt(this._rgb,t)},zt.hex=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return new(Function.prototype.bind.apply(Ut,[null].concat(t,["hex"])))},Gt.format.hex=qt,Gt.autodetect.push({p:4,test:function(t){for(var r=[],e=arguments.length-1;e-- >0;)r[e]=arguments[e+1];if(!r.length&&"string"===Ht(t)&&[3,4,5,6,7,8,9].indexOf(t.length)>=0)return"hex"}});var Kt=d.unpack,Xt=d.TWOPI,Jt=Math.min,Wt=Math.sqrt,Zt=Math.acos,Qt=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e,n=Kt(t,"rgb"),a=n[0],o=n[1],i=n[2],s=Jt(a/=255,o/=255,i/=255),c=(a+o+i)/3,l=c>0?1-s/c:0;return 0===l?e=NaN:(e=(a-o+(a-i))/2,e/=Wt((a-o)*(a-o)+(a-i)*(o-i)),e=Zt(e),i>o&&(e=Xt-e),e/=Xt),[360*e,l,c]},tr=Qt,rr=d.unpack,er=d.limit,nr=d.TWOPI,ar=d.PITHIRD,or=Math.cos,ir=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e,n,a,o=(t=rr(t,"hsi"))[0],i=t[1],s=t[2];return isNaN(o)&&(o=0),isNaN(i)&&(i=0),o>360&&(o-=360),o<0&&(o+=360),(o/=360)<1/3?n=1-((a=(1-i)/3)+(e=(1+i*or(nr*o)/or(ar-nr*o))/3)):o<2/3?a=1-((e=(1-i)/3)+(n=(1+i*or(nr*(o-=1/3))/or(ar-nr*o))/3)):e=1-((n=(1-i)/3)+(a=(1+i*or(nr*(o-=2/3))/or(ar-nr*o))/3)),[255*(e=er(s*e*3)),255*(n=er(s*n*3)),255*(a=er(s*a*3)),t.length>3?t[3]:1]},sr=ir,cr=d.unpack,lr=d.type,ur=M,fr=k,hr=p,dr=tr;fr.prototype.hsi=function(){return dr(this._rgb)},ur.hsi=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return new(Function.prototype.bind.apply(fr,[null].concat(t,["hsi"])))},hr.format.hsi=sr,hr.autodetect.push({p:2,test:function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];if(t=cr(t,"hsi"),"array"===lr(t)&&3===t.length)return"hsi"}});var pr=d.unpack,gr=d.type,br=M,mr=k,vr=p,yr=z;mr.prototype.hsl=function(){return yr(this._rgb)},br.hsl=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return new(Function.prototype.bind.apply(mr,[null].concat(t,["hsl"])))},vr.format.hsl=tt,vr.autodetect.push({p:2,test:function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];if(t=pr(t,"hsl"),"array"===gr(t)&&3===t.length)return"hsl"}});var kr=d.unpack,wr=Math.min,Mr=Math.max,Cr=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e,n,a,o=(t=kr(t,"rgb"))[0],i=t[1],s=t[2],c=wr(o,i,s),l=Mr(o,i,s),u=l-c;return a=l/255,0===l?(e=Number.NaN,n=0):(n=u/l,o===l&&(e=(i-s)/u),i===l&&(e=2+(s-o)/u),s===l&&(e=4+(o-i)/u),(e*=60)<0&&(e+=360)),[e,n,a]},Pr=Cr,xr=d.unpack,_r=Math.floor,Dr=function(){for(var t,r,e,n,a,o,i=[],s=arguments.length;s--;)i[s]=arguments[s];var c,l,u,f=(i=xr(i,"hsv"))[0],h=i[1],d=i[2];if(d*=255,0===h)c=l=u=d;else{360===f&&(f=0),f>360&&(f-=360),f<0&&(f+=360);var p=_r(f/=60),g=f-p,b=d*(1-h),m=d*(1-h*g),v=d*(1-h*(1-g));switch(p){case 0:c=(t=[d,v,b])[0],l=t[1],u=t[2];break;case 1:c=(r=[m,d,b])[0],l=r[1],u=r[2];break;case 2:c=(e=[b,d,v])[0],l=e[1],u=e[2];break;case 3:c=(n=[b,m,d])[0],l=n[1],u=n[2];break;case 4:c=(a=[v,b,d])[0],l=a[1],u=a[2];break;case 5:c=(o=[d,b,m])[0],l=o[1],u=o[2]}}return[c,l,u,i.length>3?i[3]:1]},Or=Dr,Ir=d.unpack,Fr=d.type,Ar=M,Sr=k,Nr=p,Tr=Pr;Sr.prototype.hsv=function(){return Tr(this._rgb)},Ar.hsv=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return new(Function.prototype.bind.apply(Sr,[null].concat(t,["hsv"])))},Nr.format.hsv=Or,Nr.autodetect.push({p:2,test:function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];if(t=Ir(t,"hsv"),"array"===Fr(t)&&3===t.length)return"hsv"}});var Er={Kn:18,Xn:.95047,Yn:1,Zn:1.08883,t0:.137931034,t1:.206896552,t2:.12841855,t3:.008856452},Br=Er,Lr=d.unpack,jr=Math.pow,Rr=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e=Lr(t,"rgb"),n=e[0],a=e[1],o=e[2],i=qr(n,a,o),s=i[0],c=i[1],l=116*c-16;return[l<0?0:l,500*(s-c),200*(c-i[2])]},$r=function(t){return(t/=255)<=.04045?t/12.92:jr((t+.055)/1.055,2.4)},Vr=function(t){return t>Br.t3?jr(t,1/3):t/Br.t2+Br.t0},qr=function(t,r,e){return t=$r(t),r=$r(r),e=$r(e),[Vr((.4124564*t+.3575761*r+.1804375*e)/Br.Xn),Vr((.2126729*t+.7151522*r+.072175*e)/Br.Yn),Vr((.0193339*t+.119192*r+.9503041*e)/Br.Zn)]},zr=Rr,Ur=Er,Hr=d.unpack,Gr=Math.pow,Yr=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e,n,a,o=(t=Hr(t,"lab"))[0],i=t[1],s=t[2];return n=(o+16)/116,e=isNaN(i)?n:n+i/500,a=isNaN(s)?n:n-s/200,n=Ur.Yn*Xr(n),e=Ur.Xn*Xr(e),a=Ur.Zn*Xr(a),[Kr(3.2404542*e-1.5371385*n-.4985314*a),Kr(-.969266*e+1.8760108*n+.041556*a),Kr(.0556434*e-.2040259*n+1.0572252*a),t.length>3?t[3]:1]},Kr=function(t){return 255*(t<=.00304?12.92*t:1.055*Gr(t,1/2.4)-.055)},Xr=function(t){return t>Ur.t1?t*t*t:Ur.t2*(t-Ur.t0)},Jr=Yr,Wr=d.unpack,Zr=d.type,Qr=M,te=k,re=p,ee=zr;te.prototype.lab=function(){return ee(this._rgb)},Qr.lab=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return new(Function.prototype.bind.apply(te,[null].concat(t,["lab"])))},re.format.lab=Jr,re.autodetect.push({p:2,test:function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];if(t=Wr(t,"lab"),"array"===Zr(t)&&3===t.length)return"lab"}});var ne=d.unpack,ae=d.RAD2DEG,oe=Math.sqrt,ie=Math.atan2,se=Math.round,ce=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e=ne(t,"lab"),n=e[0],a=e[1],o=e[2],i=oe(a*a+o*o),s=(ie(o,a)*ae+360)%360;return 0===se(1e4*i)&&(s=Number.NaN),[n,i,s]},le=ce,ue=d.unpack,fe=zr,he=le,de=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e=ue(t,"rgb"),n=e[0],a=e[1],o=e[2],i=fe(n,a,o),s=i[0],c=i[1],l=i[2];return he(s,c,l)},pe=de,ge=d.unpack,be=d.DEG2RAD,me=Math.sin,ve=Math.cos,ye=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e=ge(t,"lch"),n=e[0],a=e[1],o=e[2];return isNaN(o)&&(o=0),[n,ve(o*=be)*a,me(o)*a]},ke=ye,we=d.unpack,Me=ke,Ce=Jr,Pe=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e=(t=we(t,"lch"))[0],n=t[1],a=t[2],o=Me(e,n,a),i=o[0],s=o[1],c=o[2],l=Ce(i,s,c);return[l[0],l[1],l[2],t.length>3?t[3]:1]},xe=Pe,_e=d.unpack,De=xe,Oe=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e=_e(t,"hcl").reverse();return De.apply(void 0,e)},Ie=Oe,Fe=d.unpack,Ae=d.type,Se=M,Ne=k,Te=p,Ee=pe;Ne.prototype.lch=function(){return Ee(this._rgb)},Ne.prototype.hcl=function(){return Ee(this._rgb).reverse()},Se.lch=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return new(Function.prototype.bind.apply(Ne,[null].concat(t,["lch"])))},Se.hcl=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return new(Function.prototype.bind.apply(Ne,[null].concat(t,["hcl"])))},Te.format.lch=xe,Te.format.hcl=Ie,["lch","hcl"].forEach((function(t){return Te.autodetect.push({p:2,test:function(){for(var r=[],e=arguments.length;e--;)r[e]=arguments[e];if(r=Fe(r,t),"array"===Ae(r)&&3===r.length)return t}})}));var Be={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflower:"#6495ed",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",laserlemon:"#ffff54",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrod:"#fafad2",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",maroon2:"#7f0000",maroon3:"#b03060",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",purple2:"#7f007f",purple3:"#a020f0",rebeccapurple:"#663399",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"},Le=k,je=p,Re=d.type,$e=Be,Ve=qt,qe=Rt;Le.prototype.name=function(){for(var t=qe(this._rgb,"rgb"),r=0,e=Object.keys($e);r0;)r[e]=arguments[e+1];if(!r.length&&"string"===Re(t)&&$e[t.toLowerCase()])return"named"}});var ze=d.unpack,Ue=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e=ze(t,"rgb");return(e[0]<<16)+(e[1]<<8)+e[2]},He=Ue,Ge=d.type,Ye=function(t){if("number"==Ge(t)&&t>=0&&t<=16777215)return[t>>16,t>>8&255,255&t,1];throw new Error("unknown num color: "+t)},Ke=Ye,Xe=M,Je=k,We=p,Ze=d.type,Qe=He;Je.prototype.num=function(){return Qe(this._rgb)},Xe.num=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return new(Function.prototype.bind.apply(Je,[null].concat(t,["num"])))},We.format.num=Ke,We.autodetect.push({p:5,test:function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];if(1===t.length&&"number"===Ze(t[0])&&t[0]>=0&&t[0]<=16777215)return"num"}});var tn=M,rn=k,en=p,nn=d.unpack,an=d.type,on=Math.round;rn.prototype.rgb=function(t){return void 0===t&&(t=!0),!1===t?this._rgb.slice(0,3):this._rgb.slice(0,3).map(on)},rn.prototype.rgba=function(t){return void 0===t&&(t=!0),this._rgb.slice(0,4).map((function(r,e){return e<3?!1===t?r:on(r):r}))},tn.rgb=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return new(Function.prototype.bind.apply(rn,[null].concat(t,["rgb"])))},en.format.rgb=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e=nn(t,"rgba");return void 0===e[3]&&(e[3]=1),e},en.autodetect.push({p:3,test:function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];if(t=nn(t,"rgba"),"array"===an(t)&&(3===t.length||4===t.length&&"number"==an(t[3])&&t[3]>=0&&t[3]<=1))return"rgb"}});var sn=Math.log,cn=function(t){var r,e,n,a=t/100;return a<66?(r=255,e=a<6?0:-155.25485562709179-.44596950469579133*(e=a-2)+104.49216199393888*sn(e),n=a<20?0:.8274096064007395*(n=a-10)-254.76935184120902+115.67994401066147*sn(n)):(r=351.97690566805693+.114206453784165*(r=a-55)-40.25366309332127*sn(r),e=325.4494125711974+.07943456536662342*(e=a-50)-28.0852963507957*sn(e),n=255),[r,e,n,1]},ln=cn,un=d.unpack,fn=Math.round,hn=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];for(var e,n=un(t,"rgb"),a=n[0],o=n[2],i=1e3,s=4e4,c=.4;s-i>c;){var l=ln(e=.5*(s+i));l[2]/l[0]>=o/a?s=e:i=e}return fn(e)},dn=M,pn=k,gn=p,bn=hn;pn.prototype.temp=pn.prototype.kelvin=pn.prototype.temperature=function(){return bn(this._rgb)},dn.temp=dn.kelvin=dn.temperature=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return new(Function.prototype.bind.apply(pn,[null].concat(t,["temp"])))},gn.format.temp=gn.format.kelvin=gn.format.temperature=cn;var mn=d.unpack,vn=Math.cbrt,yn=Math.pow,kn=Math.sign,wn=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e=mn(t,"rgb"),n=e[0],a=e[1],o=e[2],i=[Cn(n/255),Cn(a/255),Cn(o/255)],s=i[0],c=i[1],l=i[2],u=vn(.4122214708*s+.5363325363*c+.0514459929*l),f=vn(.2119034982*s+.6806995451*c+.1073969566*l),h=vn(.0883024619*s+.2817188376*c+.6299787005*l);return[.2104542553*u+.793617785*f-.0040720468*h,1.9779984951*u-2.428592205*f+.4505937099*h,.0259040371*u+.7827717662*f-.808675766*h]},Mn=wn;function Cn(t){var r=Math.abs(t);return r<.04045?t/12.92:(kn(t)||1)*yn((r+.055)/1.055,2.4)}var Pn=d.unpack,xn=Math.pow,_n=Math.sign,Dn=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e=(t=Pn(t,"lab"))[0],n=t[1],a=t[2],o=xn(e+.3963377774*n+.2158037573*a,3),i=xn(e-.1055613458*n-.0638541728*a,3),s=xn(e-.0894841775*n-1.291485548*a,3);return[255*In(4.0767416621*o-3.3077115913*i+.2309699292*s),255*In(-1.2684380046*o+2.6097574011*i-.3413193965*s),255*In(-.0041960863*o-.7034186147*i+1.707614701*s),t.length>3?t[3]:1]},On=Dn;function In(t){var r=Math.abs(t);return r>.0031308?(_n(t)||1)*(1.055*xn(r,1/2.4)-.055):12.92*t}var Fn=d.unpack,An=d.type,Sn=M,Nn=k,Tn=p,En=Mn;Nn.prototype.oklab=function(){return En(this._rgb)},Sn.oklab=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return new(Function.prototype.bind.apply(Nn,[null].concat(t,["oklab"])))},Tn.format.oklab=On,Tn.autodetect.push({p:3,test:function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];if(t=Fn(t,"oklab"),"array"===An(t)&&3===t.length)return"oklab"}});var Bn=d.unpack,Ln=Mn,jn=le,Rn=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e=Bn(t,"rgb"),n=e[0],a=e[1],o=e[2],i=Ln(n,a,o),s=i[0],c=i[1],l=i[2];return jn(s,c,l)},$n=Rn,Vn=d.unpack,qn=ke,zn=On,Un=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];var e=(t=Vn(t,"lch"))[0],n=t[1],a=t[2],o=qn(e,n,a),i=o[0],s=o[1],c=o[2],l=zn(i,s,c);return[l[0],l[1],l[2],t.length>3?t[3]:1]},Hn=Un,Gn=d.unpack,Yn=d.type,Kn=M,Xn=k,Jn=p,Wn=$n;Xn.prototype.oklch=function(){return Wn(this._rgb)},Kn.oklch=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];return new(Function.prototype.bind.apply(Xn,[null].concat(t,["oklch"])))},Jn.format.oklch=Hn,Jn.autodetect.push({p:3,test:function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];if(t=Gn(t,"oklch"),"array"===Yn(t)&&3===t.length)return"oklch"}});var Zn=k,Qn=d.type;Zn.prototype.alpha=function(t,r){return void 0===r&&(r=!1),void 0!==t&&"number"===Qn(t)?r?(this._rgb[3]=t,this):new Zn([this._rgb[0],this._rgb[1],this._rgb[2],t],"rgb"):this._rgb[3]},k.prototype.clipped=function(){return this._rgb._clipped||!1};var ta=k,ra=Er;ta.prototype.darken=function(t){void 0===t&&(t=1);var r=this,e=r.lab();return e[0]-=ra.Kn*t,new ta(e,"lab").alpha(r.alpha(),!0)},ta.prototype.brighten=function(t){return void 0===t&&(t=1),this.darken(-t)},ta.prototype.darker=ta.prototype.darken,ta.prototype.brighter=ta.prototype.brighten,k.prototype.get=function(t){var r=t.split("."),e=r[0],n=r[1],a=this[e]();if(n){var o=e.indexOf(n)-("ok"===e.substr(0,2)?2:0);if(o>-1)return a[o];throw new Error("unknown channel "+n+" in mode "+e)}return a};var ea=k,na=d.type,aa=Math.pow,oa=1e-7,ia=20;ea.prototype.luminance=function(t){if(void 0!==t&&"number"===na(t)){if(0===t)return new ea([0,0,0,this._rgb[3]],"rgb");if(1===t)return new ea([255,255,255,this._rgb[3]],"rgb");var r=this.luminance(),e="rgb",n=ia,a=function(r,o){var i=r.interpolate(o,.5,e),s=i.luminance();return Math.abs(t-s)t?a(r,i):a(i,o)},o=(r>t?a(new ea([0,0,0]),this):a(this,new ea([255,255,255]))).rgb();return new ea(o.concat([this._rgb[3]]))}return sa.apply(void 0,this._rgb.slice(0,3))};var sa=function(t,r,e){return.2126*(t=ca(t))+.7152*(r=ca(r))+.0722*(e=ca(e))},ca=function(t){return(t/=255)<=.03928?t/12.92:aa((t+.055)/1.055,2.4)},la={},ua=k,fa=d.type,ha=la,da=function(t,r,e){void 0===e&&(e=.5);for(var n=[],a=arguments.length-3;a-- >0;)n[a]=arguments[a+3];var o=n[0]||"lrgb";if(ha[o]||n.length||(o=Object.keys(ha)[0]),!ha[o])throw new Error("interpolation mode "+o+" is not defined");return"object"!==fa(t)&&(t=new ua(t)),"object"!==fa(r)&&(r=new ua(r)),ha[o](t,r,e).alpha(t.alpha()+e*(r.alpha()-t.alpha()))},pa=k,ga=da;pa.prototype.mix=pa.prototype.interpolate=function(t,r){void 0===r&&(r=.5);for(var e=[],n=arguments.length-2;n-- >0;)e[n]=arguments[n+2];return ga.apply(void 0,[this,t,r].concat(e))};var ba=k;ba.prototype.premultiply=function(t){void 0===t&&(t=!1);var r=this._rgb,e=r[3];return t?(this._rgb=[r[0]*e,r[1]*e,r[2]*e,e],this):new ba([r[0]*e,r[1]*e,r[2]*e,e],"rgb")};var ma=k,va=Er;ma.prototype.saturate=function(t){void 0===t&&(t=1);var r=this,e=r.lch();return e[1]+=va.Kn*t,e[1]<0&&(e[1]=0),new ma(e,"lch").alpha(r.alpha(),!0)},ma.prototype.desaturate=function(t){return void 0===t&&(t=1),this.saturate(-t)};var ya=k,ka=d.type;ya.prototype.set=function(t,r,e){void 0===e&&(e=!1);var n=t.split("."),a=n[0],o=n[1],i=this[a]();if(o){var s=a.indexOf(o)-("ok"===a.substr(0,2)?2:0);if(s>-1){if("string"==ka(r))switch(r.charAt(0)){case"+":case"-":i[s]+=+r;break;case"*":i[s]*=+r.substr(1);break;case"/":i[s]/=+r.substr(1);break;default:i[s]=+r}else{if("number"!==ka(r))throw new Error("unsupported value for Color.set");i[s]=r}var c=new ya(i,a);return e?(this._rgb=c._rgb,this):c}throw new Error("unknown channel "+o+" in mode "+a)}return i};var wa=k,Ma=function(t,r,e){var n=t._rgb,a=r._rgb;return new wa(n[0]+e*(a[0]-n[0]),n[1]+e*(a[1]-n[1]),n[2]+e*(a[2]-n[2]),"rgb")};la.rgb=Ma;var Ca=k,Pa=Math.sqrt,xa=Math.pow,_a=function(t,r,e){var n=t._rgb,a=n[0],o=n[1],i=n[2],s=r._rgb,c=s[0],l=s[1],u=s[2];return new Ca(Pa(xa(a,2)*(1-e)+xa(c,2)*e),Pa(xa(o,2)*(1-e)+xa(l,2)*e),Pa(xa(i,2)*(1-e)+xa(u,2)*e),"rgb")};la.lrgb=_a;var Da=k,Oa=function(t,r,e){var n=t.lab(),a=r.lab();return new Da(n[0]+e*(a[0]-n[0]),n[1]+e*(a[1]-n[1]),n[2]+e*(a[2]-n[2]),"lab")};la.lab=Oa;var Ia=k,Fa=function(t,r,e,n){var a,o,i,s,c,l,u,f,h,d,p,g,b;return"hsl"===n?(i=t.hsl(),s=r.hsl()):"hsv"===n?(i=t.hsv(),s=r.hsv()):"hcg"===n?(i=t.hcg(),s=r.hcg()):"hsi"===n?(i=t.hsi(),s=r.hsi()):"lch"===n||"hcl"===n?(n="hcl",i=t.hcl(),s=r.hcl()):"oklch"===n&&(i=t.oklch().reverse(),s=r.oklch().reverse()),"h"!==n.substr(0,1)&&"oklch"!==n||(c=(a=i)[0],u=a[1],h=a[2],l=(o=s)[0],f=o[1],d=o[2]),isNaN(c)||isNaN(l)?isNaN(c)?isNaN(l)?g=Number.NaN:(g=l,1!=h&&0!=h||"hsv"==n||(p=f)):(g=c,1!=d&&0!=d||"hsv"==n||(p=u)):g=c+e*(l>c&&l-c>180?l-(c+360):l180?l+360-c:l-c),void 0===p&&(p=u+e*(f-u)),b=h+e*(d-h),new Ia("oklch"===n?[b,p,g]:[g,p,b],n)},Aa=Fa,Sa=function(t,r,e){return Aa(t,r,e,"lch")};la.lch=Sa,la.hcl=Sa;var Na=k,Ta=function(t,r,e){var n=t.num(),a=r.num();return new Na(n+e*(a-n),"num")};la.num=Ta;var Ea=Fa,Ba=function(t,r,e){return Ea(t,r,e,"hcg")};la.hcg=Ba;var La=Fa,ja=function(t,r,e){return La(t,r,e,"hsi")};la.hsi=ja;var Ra=Fa,$a=function(t,r,e){return Ra(t,r,e,"hsl")};la.hsl=$a;var Va=Fa,qa=function(t,r,e){return Va(t,r,e,"hsv")};la.hsv=qa;var za=k,Ua=function(t,r,e){var n=t.oklab(),a=r.oklab();return new za(n[0]+e*(a[0]-n[0]),n[1]+e*(a[1]-n[1]),n[2]+e*(a[2]-n[2]),"oklab")};la.oklab=Ua;var Ha=Fa,Ga=function(t,r,e){return Ha(t,r,e,"oklch")};la.oklch=Ga;var Ya=k,Ka=d.clip_rgb,Xa=Math.pow,Ja=Math.sqrt,Wa=Math.PI,Za=Math.cos,Qa=Math.sin,to=Math.atan2,ro=function(t,r,e){void 0===r&&(r="lrgb"),void 0===e&&(e=null);var n=t.length;e||(e=Array.from(new Array(n)).map((function(){return 1})));var a=n/e.reduce((function(t,r){return t+r}));if(e.forEach((function(t,r){e[r]*=a})),t=t.map((function(t){return new Ya(t)})),"lrgb"===r)return eo(t,e);for(var o=t.shift(),i=o.get(r),s=[],c=0,l=0,u=0;u=360;)p-=360;i[d]=p}else i[d]=i[d]/s[d];return h/=n,new Ya(i,r).alpha(h>.99999?1:h,!0)},eo=function(t,r){for(var e=t.length,n=[0,0,0,0],a=0;a.9999999&&(n[3]=1),new Ya(Ka(n))},no=M,ao=d.type,oo=Math.pow,io=function(t){var r="rgb",e=no("#ccc"),n=0,a=[0,1],o=[],i=[0,0],s=!1,c=[],l=!1,u=0,f=1,h=!1,d={},p=!0,g=1,b=function(t){if((t=t||["#fff","#000"])&&"string"===ao(t)&&no.brewer&&no.brewer[t.toLowerCase()]&&(t=no.brewer[t.toLowerCase()]),"array"===ao(t)){1===t.length&&(t=[t[0],t[0]]),t=t.slice(0);for(var r=0;r=s[e];)e++;return e-1}return 0},v=function(t){return t},y=function(t){return t},k=function(t,n){var a,l;if(null==n&&(n=!1),isNaN(t)||null===t)return e;l=n?t:s&&s.length>2?m(t)/(s.length-2):f!==u?(t-u)/(f-u):1,l=y(l),n||(l=v(l)),1!==g&&(l=oo(l,g)),l=i[0]+l*(1-i[0]-i[1]),l=Math.min(1,Math.max(0,l));var h=Math.floor(1e4*l);if(p&&d[h])a=d[h];else{if("array"===ao(c))for(var b=0;b=k&&b===o.length-1){a=c[b];break}if(l>k&&l2){var l=t.map((function(r,e){return e/(t.length-1)})),h=t.map((function(t){return(t-u)/(f-u)}));h.every((function(t,r){return l[r]===t}))||(y=function(t){if(t<=0||t>=1)return t;for(var r=0;t>=h[r+1];)r++;var e=(t-h[r])/(h[r+1]-h[r]);return l[r]+e*(l[r+1]-l[r])})}}return a=[u,f],M},M.mode=function(t){return arguments.length?(r=t,w(),M):r},M.range=function(t,r){return b(t),M},M.out=function(t){return l=t,M},M.spread=function(t){return arguments.length?(n=t,M):n},M.correctLightness=function(t){return null==t&&(t=!0),h=t,w(),v=h?function(t){for(var r=k(0,!0).lab()[0],e=k(1,!0).lab()[0],n=r>e,a=k(t,!0).lab()[0],o=r+(e-r)*t,i=a-o,s=0,c=1,l=20;Math.abs(i)>.01&&l-- >0;)n&&(i*=-1),i<0?(s=t,t+=.5*(c-t)):(c=t,t+=.5*(s-t)),a=k(t,!0).lab()[0],i=a-o;return t}:function(t){return t},M},M.padding=function(t){return null!=t?("number"===ao(t)&&(t=[t,t]),i=t,M):i},M.colors=function(r,e){arguments.length<2&&(e="hex");var n=[];if(0===arguments.length)n=c.slice(0);else if(1===r)n=[M(.5)];else if(r>1){var o=a[0],i=a[1]-o;n=so(0,r,!1).map((function(t){return M(o+t/(r-1)*i)}))}else{t=[];var l=[];if(s&&s.length>2)for(var u=1,f=s.length,h=1<=f;h?uf;h?u++:u--)l.push(.5*(s[u-1]+s[u]));else l=a;n=l.map((function(t){return M(t)}))}return no[e]&&(n=n.map((function(t){return t[e]()}))),n},M.cache=function(t){return null!=t?(p=t,M):p},M.gamma=function(t){return null!=t?(g=t,M):g},M.nodata=function(t){return null!=t?(e=no(t),M):e},M};function so(t,r,e){for(var n=[],a=to;a?i++:i--)n.push(i);return n}var co=k,lo=io,uo=function(t){for(var r=[1,1],e=1;e=5))throw new RangeError("No point in running bezier with only one color.");var l,u,f;l=t.map((function(t){return t.lab()})),f=t.length-1,u=uo(f),a=function(t){var r=1-t,e=[0,1,2].map((function(e){return l.reduce((function(n,a,o){return n+u[o]*Math.pow(r,f-o)*Math.pow(t,o)*a[e]}),0)}));return new co(e,"lab")}}return a},ho=function(t){var r=fo(t);return r.scale=function(){return lo(r)},r},po=M,go=function(t,r,e){if(!go[e])throw new Error("unknown blend mode "+e);return go[e](t,r)},bo=function(t){return function(r,e){var n=po(e).rgb(),a=po(r).rgb();return po.rgb(t(n,a))}},mo=function(t){return function(r,e){var n=[];return n[0]=t(r[0],e[0]),n[1]=t(r[1],e[1]),n[2]=t(r[2],e[2]),n}},vo=function(t){return t},yo=function(t,r){return t*r/255},ko=function(t,r){return t>r?r:t},wo=function(t,r){return t>r?t:r},Mo=function(t,r){return 255*(1-(1-t/255)*(1-r/255))},Co=function(t,r){return r<128?2*t*r/255:255*(1-2*(1-t/255)*(1-r/255))},Po=function(t,r){return 255*(1-(1-r/255)/(t/255))},xo=function(t,r){return 255===t||(t=r/255*255/(1-t/255))>255?255:t};go.normal=bo(mo(vo)),go.multiply=bo(mo(yo)),go.screen=bo(mo(Mo)),go.overlay=bo(mo(Co)),go.darken=bo(mo(ko)),go.lighten=bo(mo(wo)),go.dodge=bo(mo(xo)),go.burn=bo(mo(Po));for(var _o=go,Do=d.type,Oo=d.clip_rgb,Io=d.TWOPI,Fo=Math.pow,Ao=Math.sin,So=Math.cos,No=M,To=function(t,r,e,n,a){void 0===t&&(t=300),void 0===r&&(r=-1.5),void 0===e&&(e=1),void 0===n&&(n=1),void 0===a&&(a=[0,1]);var o,i=0;"array"===Do(a)?o=a[1]-a[0]:(o=0,a=[a,a]);var s=function(s){var c=Io*((t+120)/360+r*s),l=Fo(a[0]+o*s,n),u=(0!==i?e[0]+s*i:e)*l*(1-l)/2,f=So(c),h=Ao(c);return No(Oo([255*(l+u*(-.14861*f+1.78277*h)),255*(l+u*(-.29227*f-.90649*h)),255*(l+u*(1.97294*f)),1]))};return s.start=function(r){return null==r?t:(t=r,s)},s.rotations=function(t){return null==t?r:(r=t,s)},s.gamma=function(t){return null==t?n:(n=t,s)},s.hue=function(t){return null==t?e:("array"===Do(e=t)?0==(i=e[1]-e[0])&&(e=e[1]):i=0,s)},s.lightness=function(t){return null==t?a:("array"===Do(t)?(a=t,o=t[1]-t[0]):(a=[t,t],o=0),s)},s.scale=function(){return No.scale(s)},s.hue(e),s},Eo=k,Bo="0123456789abcdef",Lo=Math.floor,jo=Math.random,Ro=function(){for(var t="#",r=0;r<6;r++)t+=Bo.charAt(Lo(16*jo()));return new Eo(t,"hex")},$o=s,Vo=Math.log,qo=Math.pow,zo=Math.floor,Uo=Math.abs,Ho=function(t,r){void 0===r&&(r=null);var e={min:Number.MAX_VALUE,max:-1*Number.MAX_VALUE,sum:0,values:[],count:0};return"object"===$o(t)&&(t=Object.values(t)),t.forEach((function(t){r&&"object"===$o(t)&&(t=t[r]),null==t||isNaN(t)||(e.values.push(t),e.sum+=t,te.max&&(e.max=t),e.count+=1)})),e.domain=[e.min,e.max],e.limits=function(t,r){return Go(e,t,r)},e},Go=function(t,r,e){void 0===r&&(r="equal"),void 0===e&&(e=7),"array"==$o(t)&&(t=Ho(t));var n=t.min,a=t.max,o=t.values.sort((function(t,r){return t-r}));if(1===e)return[n,a];var i=[];if("c"===r.substr(0,1)&&(i.push(n),i.push(a)),"e"===r.substr(0,1)){i.push(n);for(var s=1;s 0");var c=Math.LOG10E*Vo(n),l=Math.LOG10E*Vo(a);i.push(n);for(var u=1;u200&&(y=!1)}for(var E={},B=0;Bn?(e+.05)/(n+.05):(n+.05)/(e+.05)},Jo=k,Wo=Math.sqrt,Zo=Math.pow,Qo=Math.min,ti=Math.max,ri=Math.atan2,ei=Math.abs,ni=Math.cos,ai=Math.sin,oi=Math.exp,ii=Math.PI,si=function(t,r,e,n,a){void 0===e&&(e=1),void 0===n&&(n=1),void 0===a&&(a=1);var o=function(t){return 360*t/(2*ii)},i=function(t){return 2*ii*t/360};t=new Jo(t),r=new Jo(r);var s=Array.from(t.lab()),c=s[0],l=s[1],u=s[2],f=Array.from(r.lab()),h=f[0],d=f[1],p=f[2],g=(c+h)/2,b=(Wo(Zo(l,2)+Zo(u,2))+Wo(Zo(d,2)+Zo(p,2)))/2,m=.5*(1-Wo(Zo(b,7)/(Zo(b,7)+Zo(25,7)))),v=l*(1+m),y=d*(1+m),k=Wo(Zo(v,2)+Zo(u,2)),w=Wo(Zo(y,2)+Zo(p,2)),M=(k+w)/2,C=o(ri(u,v)),P=o(ri(p,y)),x=C>=0?C:C+360,_=P>=0?P:P+360,D=ei(x-_)>180?(x+_+360)/2:(x+_)/2,O=1-.17*ni(i(D-30))+.24*ni(i(2*D))+.32*ni(i(3*D+6))-.2*ni(i(4*D-63)),I=_-x;I=ei(I)<=180?I:_<=x?I+360:I-360,I=2*Wo(k*w)*ai(i(I)/2);var F=h-c,A=w-k,S=1+.015*Zo(g-50,2)/Wo(20+Zo(g-50,2)),N=1+.045*M,T=1+.015*M*O,E=30*oi(-Zo((D-275)/25,2)),B=-2*Wo(Zo(M,7)/(Zo(M,7)+Zo(25,7)))*ai(2*i(E)),L=Wo(Zo(F/(e*S),2)+Zo(A/(n*N),2)+Zo(I/(a*T),2)+B*(A/(n*N))*(I/(a*T)));return ti(0,Qo(100,L))},ci=k,li=function(t,r,e){void 0===e&&(e="lab"),t=new ci(t),r=new ci(r);var n=t.get(e),a=r.get(e),o=0;for(var i in n){var s=(n[i]||0)-(a[i]||0);o+=s*s}return Math.sqrt(o)},ui=k,fi=function(){for(var t=[],r=arguments.length;r--;)t[r]=arguments[r];try{return new(Function.prototype.bind.apply(ui,[null].concat(t))),!0}catch(t){return!1}},hi=M,di=io,pi={cool:function(){return di([hi.hsl(180,1,.9),hi.hsl(250,.7,.4)])},hot:function(){return di(["#000","#f00","#ff0","#fff"]).mode("rgb")}},gi={OrRd:["#fff7ec","#fee8c8","#fdd49e","#fdbb84","#fc8d59","#ef6548","#d7301f","#b30000","#7f0000"],PuBu:["#fff7fb","#ece7f2","#d0d1e6","#a6bddb","#74a9cf","#3690c0","#0570b0","#045a8d","#023858"],BuPu:["#f7fcfd","#e0ecf4","#bfd3e6","#9ebcda","#8c96c6","#8c6bb1","#88419d","#810f7c","#4d004b"],Oranges:["#fff5eb","#fee6ce","#fdd0a2","#fdae6b","#fd8d3c","#f16913","#d94801","#a63603","#7f2704"],BuGn:["#f7fcfd","#e5f5f9","#ccece6","#99d8c9","#66c2a4","#41ae76","#238b45","#006d2c","#00441b"],YlOrBr:["#ffffe5","#fff7bc","#fee391","#fec44f","#fe9929","#ec7014","#cc4c02","#993404","#662506"],YlGn:["#ffffe5","#f7fcb9","#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#006837","#004529"],Reds:["#fff5f0","#fee0d2","#fcbba1","#fc9272","#fb6a4a","#ef3b2c","#cb181d","#a50f15","#67000d"],RdPu:["#fff7f3","#fde0dd","#fcc5c0","#fa9fb5","#f768a1","#dd3497","#ae017e","#7a0177","#49006a"],Greens:["#f7fcf5","#e5f5e0","#c7e9c0","#a1d99b","#74c476","#41ab5d","#238b45","#006d2c","#00441b"],YlGnBu:["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"],Purples:["#fcfbfd","#efedf5","#dadaeb","#bcbddc","#9e9ac8","#807dba","#6a51a3","#54278f","#3f007d"],GnBu:["#f7fcf0","#e0f3db","#ccebc5","#a8ddb5","#7bccc4","#4eb3d3","#2b8cbe","#0868ac","#084081"],Greys:["#ffffff","#f0f0f0","#d9d9d9","#bdbdbd","#969696","#737373","#525252","#252525","#000000"],YlOrRd:["#ffffcc","#ffeda0","#fed976","#feb24c","#fd8d3c","#fc4e2a","#e31a1c","#bd0026","#800026"],PuRd:["#f7f4f9","#e7e1ef","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#980043","#67001f"],Blues:["#f7fbff","#deebf7","#c6dbef","#9ecae1","#6baed6","#4292c6","#2171b5","#08519c","#08306b"],PuBuGn:["#fff7fb","#ece2f0","#d0d1e6","#a6bddb","#67a9cf","#3690c0","#02818a","#016c59","#014636"],Viridis:["#440154","#482777","#3f4a8a","#31678e","#26838f","#1f9d8a","#6cce5a","#b6de2b","#fee825"],Spectral:["#9e0142","#d53e4f","#f46d43","#fdae61","#fee08b","#ffffbf","#e6f598","#abdda4","#66c2a5","#3288bd","#5e4fa2"],RdYlGn:["#a50026","#d73027","#f46d43","#fdae61","#fee08b","#ffffbf","#d9ef8b","#a6d96a","#66bd63","#1a9850","#006837"],RdBu:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#f7f7f7","#d1e5f0","#92c5de","#4393c3","#2166ac","#053061"],PiYG:["#8e0152","#c51b7d","#de77ae","#f1b6da","#fde0ef","#f7f7f7","#e6f5d0","#b8e186","#7fbc41","#4d9221","#276419"],PRGn:["#40004b","#762a83","#9970ab","#c2a5cf","#e7d4e8","#f7f7f7","#d9f0d3","#a6dba0","#5aae61","#1b7837","#00441b"],RdYlBu:["#a50026","#d73027","#f46d43","#fdae61","#fee090","#ffffbf","#e0f3f8","#abd9e9","#74add1","#4575b4","#313695"],BrBG:["#543005","#8c510a","#bf812d","#dfc27d","#f6e8c3","#f5f5f5","#c7eae5","#80cdc1","#35978f","#01665e","#003c30"],RdGy:["#67001f","#b2182b","#d6604d","#f4a582","#fddbc7","#ffffff","#e0e0e0","#bababa","#878787","#4d4d4d","#1a1a1a"],PuOr:["#7f3b08","#b35806","#e08214","#fdb863","#fee0b6","#f7f7f7","#d8daeb","#b2abd2","#8073ac","#542788","#2d004b"],Set2:["#66c2a5","#fc8d62","#8da0cb","#e78ac3","#a6d854","#ffd92f","#e5c494","#b3b3b3"],Accent:["#7fc97f","#beaed4","#fdc086","#ffff99","#386cb0","#f0027f","#bf5b17","#666666"],Set1:["#e41a1c","#377eb8","#4daf4a","#984ea3","#ff7f00","#ffff33","#a65628","#f781bf","#999999"],Set3:["#8dd3c7","#ffffb3","#bebada","#fb8072","#80b1d3","#fdb462","#b3de69","#fccde5","#d9d9d9","#bc80bd","#ccebc5","#ffed6f"],Dark2:["#1b9e77","#d95f02","#7570b3","#e7298a","#66a61e","#e6ab02","#a6761d","#666666"],Paired:["#a6cee3","#1f78b4","#b2df8a","#33a02c","#fb9a99","#e31a1c","#fdbf6f","#ff7f00","#cab2d6","#6a3d9a","#ffff99","#b15928"],Pastel2:["#b3e2cd","#fdcdac","#cbd5e8","#f4cae4","#e6f5c9","#fff2ae","#f1e2cc","#cccccc"],Pastel1:["#fbb4ae","#b3cde3","#ccebc5","#decbe4","#fed9a6","#ffffcc","#e5d8bd","#fddaec","#f2f2f2"]},bi=0,mi=Object.keys(gi);bi10&&/[0-9](?:\s|\/)/.test(t)&&(n=t.match(/([0-9]+)/g).map((function(t){return parseFloat(t)})),e=t.match(/([a-z])/gi).join("").toLowerCase());else isNaN(t)?Array.isArray(t)||t.length?(n=[t[0],t[1],t[2]],e="rgb",a=4===t.length?t[3]:1):t instanceof Object&&(null!=t.r||null!=t.red||null!=t.R?(e="rgb",n=[t.r||t.red||t.R||0,t.g||t.green||t.G||0,t.b||t.blue||t.B||0]):(e="hsl",n=[t.h||t.hue||t.H||0,t.s||t.saturation||t.S||0,t.l||t.lightness||t.L||t.b||t.brightness]),a=t.a||t.alpha||t.opacity||1,null!=t.opacity&&(a/=100)):(e="rgb",n=[t>>>16,(65280&t)>>>8,255&t]);return{space:e,values:n,alpha:a}},X={red:0,orange:60,yellow:120,green:180,blue:240,purple:300};const J=K;function W(t,r){if(t.space||(t=J(t)),r.space||(r=J(r)),"rgb"!==t.space)throw new Error("First color's space "+t.space+" is not supported.");if("rgb"!==r.space)throw new Error("Second color's space "+r.space+" is not supported.");if(1===t.alpha)return t;if(0===t.alpha)return r;for(var e={space:r.space,values:r.values.slice(),alpha:t.alpha+r.alpha*(1-t.alpha)},n=0;n<3;n++){var a=t.values[n]*t.alpha,o=r.values[n]*r.alpha;e.values[n]=Math.round((a+o*(1-t.alpha))/e.alpha)}return e}var Z={composite:function(t){for(var r=t[0],e=1,n=t.length;e{const{values:[n,a,o]}=tt(Q(t).alpha(e).hex(),r);return`rgb(${n}, ${a}, ${o})`};const et=U,nt=H.exports,at=(t,r,e)=>({hover:rt(r,t,e?.hoverOpacity||.08),press:rt(r,t,e?.pressOpacity||.12),focus:rt(r,t,e?.focusOpacity||.12),drag:rt(r,t,e?.dragOpacity||.16)}),ot={surfacePrefix:"surface",interactiveSurfacePrefix:"interactive-surface",disabledStyles:{textOpacity:.38,backgroundOpacity:.12,colorName:"black"},transition:{duration:150}},it=t=>Object.assign({},...Object.entries(t??{}).flatMap((([t,r])=>"object"==typeof r?Object.entries(it(r)).map((([r,e])=>({[t+("DEFAULT"===r?"":`-${r}`)]:e}))):[{[`${t}`]:r}])));var st={exports:{}},ct={exports:{}},lt=function(t){return!(!t||"string"==typeof t)&&(t instanceof Array||Array.isArray(t)||t.length>=0&&(t.splice instanceof Function||Object.getOwnPropertyDescriptor(t,t.length-1)&&"String"!==t.constructor.name))},ut=Array.prototype.concat,ft=Array.prototype.slice,ht=ct.exports=function(t){for(var r=[],e=0,n=t.length;e=4&&1!==t[3]&&(r=", "+t[3]),"hwb("+t[0]+", "+t[1]+"%, "+t[2]+"%"+r+")"},vt.to.keyword=function(t){return bt[t.slice(0,3)]};const wt=G,Mt={};for(const t of Object.keys(wt))Mt[wt[t]]=t;const Ct={rgb:{channels:3,labels:"rgb"},hsl:{channels:3,labels:"hsl"},hsv:{channels:3,labels:"hsv"},hwb:{channels:3,labels:"hwb"},cmyk:{channels:4,labels:"cmyk"},xyz:{channels:3,labels:"xyz"},lab:{channels:3,labels:"lab"},lch:{channels:3,labels:"lch"},hex:{channels:1,labels:["hex"]},keyword:{channels:1,labels:["keyword"]},ansi16:{channels:1,labels:["ansi16"]},ansi256:{channels:1,labels:["ansi256"]},hcg:{channels:3,labels:["h","c","g"]},apple:{channels:3,labels:["r16","g16","b16"]},gray:{channels:1,labels:["gray"]}};var Pt=Ct;for(const t of Object.keys(Ct)){if(!("channels"in Ct[t]))throw new Error("missing channels property: "+t);if(!("labels"in Ct[t]))throw new Error("missing channel labels property: "+t);if(Ct[t].labels.length!==Ct[t].channels)throw new Error("channel and label counts mismatch: "+t);const{channels:r,labels:e}=Ct[t];delete Ct[t].channels,delete Ct[t].labels,Object.defineProperty(Ct[t],"channels",{value:r}),Object.defineProperty(Ct[t],"labels",{value:e})}Ct.rgb.hsl=function(t){const r=t[0]/255,e=t[1]/255,n=t[2]/255,a=Math.min(r,e,n),o=Math.max(r,e,n),i=o-a;let s,c;o===a?s=0:r===o?s=(e-n)/i:e===o?s=2+(n-r)/i:n===o&&(s=4+(r-e)/i),s=Math.min(60*s,360),s<0&&(s+=360);const l=(a+o)/2;return c=o===a?0:l<=.5?i/(o+a):i/(2-o-a),[s,100*c,100*l]},Ct.rgb.hsv=function(t){let r,e,n,a,o;const i=t[0]/255,s=t[1]/255,c=t[2]/255,l=Math.max(i,s,c),u=l-Math.min(i,s,c),f=function(t){return(l-t)/6/u+.5};return 0===u?(a=0,o=0):(o=u/l,r=f(i),e=f(s),n=f(c),i===l?a=n-e:s===l?a=1/3+r-n:c===l&&(a=2/3+e-r),a<0?a+=1:a>1&&(a-=1)),[360*a,100*o,100*l]},Ct.rgb.hwb=function(t){const r=t[0],e=t[1];let n=t[2];const a=Ct.rgb.hsl(t)[0],o=1/255*Math.min(r,Math.min(e,n));return n=1-1/255*Math.max(r,Math.max(e,n)),[a,100*o,100*n]},Ct.rgb.cmyk=function(t){const r=t[0]/255,e=t[1]/255,n=t[2]/255,a=Math.min(1-r,1-e,1-n);return[100*((1-r-a)/(1-a)||0),100*((1-e-a)/(1-a)||0),100*((1-n-a)/(1-a)||0),100*a]},Ct.rgb.keyword=function(t){const r=Mt[t];if(r)return r;let e,n=1/0;for(const r of Object.keys(wt)){const i=(o=wt[r],((a=t)[0]-o[0])**2+(a[1]-o[1])**2+(a[2]-o[2])**2);i.04045?((r+.055)/1.055)**2.4:r/12.92,e=e>.04045?((e+.055)/1.055)**2.4:e/12.92,n=n>.04045?((n+.055)/1.055)**2.4:n/12.92;return[100*(.4124*r+.3576*e+.1805*n),100*(.2126*r+.7152*e+.0722*n),100*(.0193*r+.1192*e+.9505*n)]},Ct.rgb.lab=function(t){const r=Ct.rgb.xyz(t);let e=r[0],n=r[1],a=r[2];e/=95.047,n/=100,a/=108.883,e=e>.008856?e**(1/3):7.787*e+16/116,n=n>.008856?n**(1/3):7.787*n+16/116,a=a>.008856?a**(1/3):7.787*a+16/116;return[116*n-16,500*(e-n),200*(n-a)]},Ct.hsl.rgb=function(t){const r=t[0]/360,e=t[1]/100,n=t[2]/100;let a,o,i;if(0===e)return i=255*n,[i,i,i];a=n<.5?n*(1+e):n+e-n*e;const s=2*n-a,c=[0,0,0];for(let t=0;t<3;t++)o=r+1/3*-(t-1),o<0&&o++,o>1&&o--,i=6*o<1?s+6*(a-s)*o:2*o<1?a:3*o<2?s+(a-s)*(2/3-o)*6:s,c[t]=255*i;return c},Ct.hsl.hsv=function(t){const r=t[0];let e=t[1]/100,n=t[2]/100,a=e;const o=Math.max(n,.01);n*=2,e*=n<=1?n:2-n,a*=o<=1?o:2-o;return[r,100*(0===n?2*a/(o+a):2*e/(n+e)),100*((n+e)/2)]},Ct.hsv.rgb=function(t){const r=t[0]/60,e=t[1]/100;let n=t[2]/100;const a=Math.floor(r)%6,o=r-Math.floor(r),i=255*n*(1-e),s=255*n*(1-e*o),c=255*n*(1-e*(1-o));switch(n*=255,a){case 0:return[n,c,i];case 1:return[s,n,i];case 2:return[i,n,c];case 3:return[i,s,n];case 4:return[c,i,n];case 5:return[n,i,s]}},Ct.hsv.hsl=function(t){const r=t[0],e=t[1]/100,n=t[2]/100,a=Math.max(n,.01);let o,i;i=(2-e)*n;const s=(2-e)*a;return o=e*a,o/=s<=1?s:2-s,o=o||0,i/=2,[r,100*o,100*i]},Ct.hwb.rgb=function(t){const r=t[0]/360;let e=t[1]/100,n=t[2]/100;const a=e+n;let o;a>1&&(e/=a,n/=a);const i=Math.floor(6*r),s=1-n;o=6*r-i,0!=(1&i)&&(o=1-o);const c=e+o*(s-e);let l,u,f;switch(i){default:case 6:case 0:l=s,u=c,f=e;break;case 1:l=c,u=s,f=e;break;case 2:l=e,u=s,f=c;break;case 3:l=e,u=c,f=s;break;case 4:l=c,u=e,f=s;break;case 5:l=s,u=e,f=c}return[255*l,255*u,255*f]},Ct.cmyk.rgb=function(t){const r=t[0]/100,e=t[1]/100,n=t[2]/100,a=t[3]/100;return[255*(1-Math.min(1,r*(1-a)+a)),255*(1-Math.min(1,e*(1-a)+a)),255*(1-Math.min(1,n*(1-a)+a))]},Ct.xyz.rgb=function(t){const r=t[0]/100,e=t[1]/100,n=t[2]/100;let a,o,i;return a=3.2406*r+-1.5372*e+-.4986*n,o=-.9689*r+1.8758*e+.0415*n,i=.0557*r+-.204*e+1.057*n,a=a>.0031308?1.055*a**(1/2.4)-.055:12.92*a,o=o>.0031308?1.055*o**(1/2.4)-.055:12.92*o,i=i>.0031308?1.055*i**(1/2.4)-.055:12.92*i,a=Math.min(Math.max(0,a),1),o=Math.min(Math.max(0,o),1),i=Math.min(Math.max(0,i),1),[255*a,255*o,255*i]},Ct.xyz.lab=function(t){let r=t[0],e=t[1],n=t[2];r/=95.047,e/=100,n/=108.883,r=r>.008856?r**(1/3):7.787*r+16/116,e=e>.008856?e**(1/3):7.787*e+16/116,n=n>.008856?n**(1/3):7.787*n+16/116;return[116*e-16,500*(r-e),200*(e-n)]},Ct.lab.xyz=function(t){let r,e,n;e=(t[0]+16)/116,r=t[1]/500+e,n=e-t[2]/200;const a=e**3,o=r**3,i=n**3;return e=a>.008856?a:(e-16/116)/7.787,r=o>.008856?o:(r-16/116)/7.787,n=i>.008856?i:(n-16/116)/7.787,r*=95.047,e*=100,n*=108.883,[r,e,n]},Ct.lab.lch=function(t){const r=t[0],e=t[1],n=t[2];let a;a=360*Math.atan2(n,e)/2/Math.PI,a<0&&(a+=360);return[r,Math.sqrt(e*e+n*n),a]},Ct.lch.lab=function(t){const r=t[0],e=t[1],n=t[2]/360*2*Math.PI;return[r,e*Math.cos(n),e*Math.sin(n)]},Ct.rgb.ansi16=function(t,r=null){const[e,n,a]=t;let o=null===r?Ct.rgb.hsv(t)[2]:r;if(o=Math.round(o/50),0===o)return 30;let i=30+(Math.round(a/255)<<2|Math.round(n/255)<<1|Math.round(e/255));return 2===o&&(i+=60),i},Ct.hsv.ansi16=function(t){return Ct.rgb.ansi16(Ct.hsv.rgb(t),t[2])},Ct.rgb.ansi256=function(t){const r=t[0],e=t[1],n=t[2];if(r===e&&e===n)return r<8?16:r>248?231:Math.round((r-8)/247*24)+232;return 16+36*Math.round(r/255*5)+6*Math.round(e/255*5)+Math.round(n/255*5)},Ct.ansi16.rgb=function(t){let r=t%10;if(0===r||7===r)return t>50&&(r+=3.5),r=r/10.5*255,[r,r,r];const e=.5*(1+~~(t>50));return[(1&r)*e*255,(r>>1&1)*e*255,(r>>2&1)*e*255]},Ct.ansi256.rgb=function(t){if(t>=232){const r=10*(t-232)+8;return[r,r,r]}let r;t-=16;return[Math.floor(t/36)/5*255,Math.floor((r=t%36)/6)/5*255,r%6/5*255]},Ct.rgb.hex=function(t){const r=(((255&Math.round(t[0]))<<16)+((255&Math.round(t[1]))<<8)+(255&Math.round(t[2]))).toString(16).toUpperCase();return"000000".substring(r.length)+r},Ct.hex.rgb=function(t){const r=t.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);if(!r)return[0,0,0];let e=r[0];3===r[0].length&&(e=e.split("").map((t=>t+t)).join(""));const n=parseInt(e,16);return[n>>16&255,n>>8&255,255&n]},Ct.rgb.hcg=function(t){const r=t[0]/255,e=t[1]/255,n=t[2]/255,a=Math.max(Math.max(r,e),n),o=Math.min(Math.min(r,e),n),i=a-o;let s,c;return s=i<1?o/(1-i):0,c=i<=0?0:a===r?(e-n)/i%6:a===e?2+(n-r)/i:4+(r-e)/i,c/=6,c%=1,[360*c,100*i,100*s]},Ct.hsl.hcg=function(t){const r=t[1]/100,e=t[2]/100,n=e<.5?2*r*e:2*r*(1-e);let a=0;return n<1&&(a=(e-.5*n)/(1-n)),[t[0],100*n,100*a]},Ct.hsv.hcg=function(t){const r=t[1]/100,e=t[2]/100,n=r*e;let a=0;return n<1&&(a=(e-n)/(1-n)),[t[0],100*n,100*a]},Ct.hcg.rgb=function(t){const r=t[0]/360,e=t[1]/100,n=t[2]/100;if(0===e)return[255*n,255*n,255*n];const a=[0,0,0],o=r%1*6,i=o%1,s=1-i;let c=0;switch(Math.floor(o)){case 0:a[0]=1,a[1]=i,a[2]=0;break;case 1:a[0]=s,a[1]=1,a[2]=0;break;case 2:a[0]=0,a[1]=1,a[2]=i;break;case 3:a[0]=0,a[1]=s,a[2]=1;break;case 4:a[0]=i,a[1]=0,a[2]=1;break;default:a[0]=1,a[1]=0,a[2]=s}return c=(1-e)*n,[255*(e*a[0]+c),255*(e*a[1]+c),255*(e*a[2]+c)]},Ct.hcg.hsv=function(t){const r=t[1]/100,e=r+t[2]/100*(1-r);let n=0;return e>0&&(n=r/e),[t[0],100*n,100*e]},Ct.hcg.hsl=function(t){const r=t[1]/100,e=t[2]/100*(1-r)+.5*r;let n=0;return e>0&&e<.5?n=r/(2*e):e>=.5&&e<1&&(n=r/(2*(1-e))),[t[0],100*n,100*e]},Ct.hcg.hwb=function(t){const r=t[1]/100,e=r+t[2]/100*(1-r);return[t[0],100*(e-r),100*(1-e)]},Ct.hwb.hcg=function(t){const r=t[1]/100,e=1-t[2]/100,n=e-r;let a=0;return n<1&&(a=(e-n)/(1-n)),[t[0],100*n,100*a]},Ct.apple.rgb=function(t){return[t[0]/65535*255,t[1]/65535*255,t[2]/65535*255]},Ct.rgb.apple=function(t){return[t[0]/255*65535,t[1]/255*65535,t[2]/255*65535]},Ct.gray.rgb=function(t){return[t[0]/100*255,t[0]/100*255,t[0]/100*255]},Ct.gray.hsl=function(t){return[0,0,t[0]]},Ct.gray.hsv=Ct.gray.hsl,Ct.gray.hwb=function(t){return[0,100,t[0]]},Ct.gray.cmyk=function(t){return[0,0,0,t[0]]},Ct.gray.lab=function(t){return[t[0],0,0]},Ct.gray.hex=function(t){const r=255&Math.round(t[0]/100*255),e=((r<<16)+(r<<8)+r).toString(16).toUpperCase();return"000000".substring(e.length)+e},Ct.rgb.gray=function(t){return[(t[0]+t[1]+t[2])/3/255*100]};const xt=Pt;function _t(t){const r=function(){const t={},r=Object.keys(xt);for(let e=r.length,n=0;n{At[t]={},Object.defineProperty(At[t],"channels",{value:It[t].channels}),Object.defineProperty(At[t],"labels",{value:It[t].labels});const r=Ft(t);Object.keys(r).forEach((e=>{const n=r[e];At[t][e]=function(t){const r=function(...r){const e=r[0];if(null==e)return e;e.length>1&&(r=e);const n=t(r);if("object"==typeof n)for(let t=n.length,r=0;r1&&(r=e),t(r))};return"conversion"in t&&(r.conversion=t.conversion),r}(n)}))}));var St=At;const Nt=st.exports,Tt=St,Et=["keyword","gray","hex"],Bt={};for(const t of Object.keys(Tt))Bt[[...Tt[t].labels].sort().join("")]=t;const Lt={};function jt(t,r){if(!(this instanceof jt))return new jt(t,r);if(r&&r in Et&&(r=null),r&&!(r in Tt))throw new Error("Unknown model: "+r);let e,n;if(null==t)this.model="rgb",this.color=[0,0,0],this.valpha=1;else if(t instanceof jt)this.model=t.model,this.color=[...t.color],this.valpha=t.valpha;else if("string"==typeof t){const r=Nt.get(t);if(null===r)throw new Error("Unable to parse color from string: "+t);this.model=r.model,n=Tt[this.model].channels,this.color=r.value.slice(0,n),this.valpha="number"==typeof r.value[n]?r.value[n]:1}else if(t.length>0){this.model=r||"rgb",n=Tt[this.model].channels;const e=Array.prototype.slice.call(t,0,n);this.color=qt(e,n),this.valpha="number"==typeof t[n]?t[n]:1}else if("number"==typeof t)this.model="rgb",this.color=[t>>16&255,t>>8&255,255&t],this.valpha=1;else{this.valpha=1;const r=Object.keys(t);"alpha"in t&&(r.splice(r.indexOf("alpha"),1),this.valpha="number"==typeof t.alpha?t.alpha:0);const n=r.sort().join("");if(!(n in Bt))throw new Error("Unable to parse color from object: "+JSON.stringify(t));this.model=Bt[n];const{labels:a}=Tt[this.model],o=[];for(e=0;e(t%360+360)%360)),saturationl:$t("hsl",1,Vt(100)),lightness:$t("hsl",2,Vt(100)),saturationv:$t("hsv",1,Vt(100)),value:$t("hsv",2,Vt(100)),chroma:$t("hcg",1,Vt(100)),gray:$t("hcg",2,Vt(100)),white:$t("hwb",1,Vt(100)),wblack:$t("hwb",2,Vt(100)),cyan:$t("cmyk",0,Vt(100)),magenta:$t("cmyk",1,Vt(100)),yellow:$t("cmyk",2,Vt(100)),black:$t("cmyk",3,Vt(100)),x:$t("xyz",0,Vt(95.047)),y:$t("xyz",1,Vt(100)),z:$t("xyz",2,Vt(108.833)),l:$t("lab",0,Vt(100)),a:$t("lab",1),b:$t("lab",2),keyword(t){return void 0!==t?new jt(t):Tt[this.model].keyword(this.color)},hex(t){return void 0!==t?new jt(t):Nt.to.hex(this.rgb().round().color)},hexa(t){if(void 0!==t)return new jt(t);const r=this.rgb().round().color;let e=Math.round(255*this.valpha).toString(16).toUpperCase();return 1===e.length&&(e="0"+e),Nt.to.hex(r)+e},rgbNumber(){const t=this.rgb().color;return(255&t[0])<<16|(255&t[1])<<8|255&t[2]},luminosity(){const t=this.rgb().color,r=[];for(const[e,n]of t.entries()){const t=n/255;r[e]=t<=.04045?t/12.92:((t+.055)/1.055)**2.4}return.2126*r[0]+.7152*r[1]+.0722*r[2]},contrast(t){const r=this.luminosity(),e=t.luminosity();return r>e?(r+.05)/(e+.05):(e+.05)/(r+.05)},level(t){const r=this.contrast(t);return r>=7?"AAA":r>=4.5?"AA":""},isDark(){const t=this.rgb().color;return(2126*t[0]+7152*t[1]+722*t[2])/1e4<128},isLight(){return!this.isDark()},negate(){const t=this.rgb();for(let r=0;r<3;r++)t.color[r]=255-t.color[r];return t},lighten(t){const r=this.hsl();return r.color[2]+=r.color[2]*t,r},darken(t){const r=this.hsl();return r.color[2]-=r.color[2]*t,r},saturate(t){const r=this.hsl();return r.color[1]+=r.color[1]*t,r},desaturate(t){const r=this.hsl();return r.color[1]-=r.color[1]*t,r},whiten(t){const r=this.hwb();return r.color[1]+=r.color[1]*t,r},blacken(t){const r=this.hwb();return r.color[2]+=r.color[2]*t,r},grayscale(){const t=this.rgb().color,r=.3*t[0]+.59*t[1]+.11*t[2];return jt.rgb(r,r,r)},fade(t){return this.alpha(this.valpha-this.valpha*t)},opaquer(t){return this.alpha(this.valpha+this.valpha*t)},rotate(t){const r=this.hsl();let e=r.color[0];return e=(e+t)%360,e=e<0?360+e:e,r.color[0]=e,r},mix(t,r){if(!t||!t.rgb)throw new Error('Argument to "mix" was not a Color instance, but rather an instance of '+typeof t);const e=t.rgb(),n=this.rgb(),a=void 0===r?.5:r,o=2*a-1,i=e.alpha()-n.alpha(),s=((o*i==-1?o:(o+i)/(1+o*i))+1)/2,c=1-s;return jt.rgb(s*e.red()+c*n.red(),s*e.green()+c*n.green(),s*e.blue()+c*n.blue(),e.alpha()*a+n.alpha()*(1-a))}};for(const t of Object.keys(Tt)){if(Et.includes(t))continue;const{channels:r}=Tt[t];jt.prototype[t]=function(...r){return this.model===t?new jt(this):r.length>0?new jt(r,t):new jt([...(e=Tt[this.model][t].raw(this.color),Array.isArray(e)?e:[e]),this.valpha],t);var e},jt[t]=function(...e){let n=e[0];return"number"==typeof n&&(n=qt(e,r)),new jt(n,t)}}function Rt(t){return function(r){return function(t,r){return Number(t.toFixed(r))}(r,t)}}function $t(t,r,e){t=Array.isArray(t)?t:[t];for(const n of t)(Lt[n]||(Lt[n]=[]))[r]=e;return t=t[0],function(n){let a;return void 0!==n?(e&&(n=e(n)),a=this[t](),a.color[r]=n,a):(a=this[t]().color[r],e&&(a=e(a)),a)}}function Vt(t){return function(r){return Math.max(0,Math.min(t,r))}}function qt(t,r){for(let e=0;eObject.assign({},...Object.entries(t??{}).flatMap((([t,r])=>"object"==typeof r?Object.entries(Ht(r)).map((([r,e])=>({[t+("DEFAULT"===r?"":`-${r}`)]:e}))):[{[`${t}`]:r}])));const Gt=(t,r,e={extend:!1})=>{if(r.primary){const n=V(r);return(t=>{const r=!t.theme.colors,e=Ht(r?t.theme.extend.colors||{}:t.theme.colors),n=Array.isArray(t.darkMode)?"class"!==t.darkMode[0]:"class"!==t.darkMode,a=!n&&(Array.isArray(t.darkMode)&&t.darkMode[1]||".dark"),o={html:{},...n?{"@media (prefers-color-scheme: dark)":{html:{}}}:{[a]:{}}};return Object.keys(e).forEach((t=>{const r=t.match(new RegExp(/^(?:(.+)-)?light(?:-(.+))?$/));if(r){const i=r[1],s=r[2],c=[i,s].filter((t=>t)).join("-"),l=e[t],u=e[[i,"dark",s].filter((t=>t)).join("-")];if(l&&u){if(e[c])throw`withModeAwareColors plugin error: adding the '${c}' mode-aware color would overwrite an existing color.`;{const t=`--color-${c}`;e[c]=`rgb(var(${t}) / )`;const r=Ut(l).rgb().array().join(" "),i=Ut(u).rgb().array().join(" ");o.html[t]=r,n?o["@media (prefers-color-scheme: dark)"].html[t]=i:o[a][t]=i}}}})),{...t,theme:r?{...t.theme,extend:{...t.theme.extend||{},colors:e}}:{...t.theme||[],colors:e},plugins:[...t.plugins||[],zt((({addBase:t})=>t(o)))]}})(((t,r={})=>{const{surfacePrefix:e,interactiveSurfacePrefix:n,disabledStyles:a,transition:o}={...ot,...r},i=!t.theme.colors,s=it(i?t.theme.extend.colors||{}:t.theme.colors);return Object.keys(s).forEach((t=>{const e=`on-${t}`,n=s[t],a=s[e];if(!t.startsWith("on-")&&nt.valid(n)&&nt.valid(a)){const e=at(n,a,r);s[`${t}-hover`]=e.hover,s[`${t}-press`]=e.press,s[`${t}-focus`]=e.focus,s[`${t}-drag`]=e.drag}})),{...t,theme:i?{...t.theme,extend:{...t.theme.extend||{},colors:s}}:{...t.theme||[],colors:s},plugins:[...t.plugins||[],et((({addComponents:t,theme:r})=>{const i=it(r("colors")||{}),s=Object.keys(i).filter((t=>i[`on-${t}`]&&i[`${t}-hover`]&&i[`${t}-focus`]&&i[`${t}-press`]));let c={};s.forEach((t=>{c[`.${e}-${t}`]={..."bg"===e?{}:{[`@apply bg-${t}`]:{}},[`@apply text-on-${t}`]:{}},c[`.${n}-${t}`]={[`@apply bg-${t}`]:{},[`@apply text-on-${t}`]:{},[`@apply hover:bg-${t}-hover`]:{},[`@apply active:bg-${t}-press`]:{},[`@apply focus-visible:bg-${t}-focus`]:{},...o?{"@apply transition-colors":{},[`@apply duration-${o.duration}`]:{}}:{},...a?{[`@apply disabled:text-${a.colorName}/[${a.textOpacity}]`]:{},[`@apply disabled:bg-${a.colorName}/[${a.backgroundOpacity}]`]:{}}:{}}})),t(c)}),{})]}})({...t,theme:e.extend?{...t.theme||{},extend:{...t.theme?.extend||{},colors:{...t.theme?.extend?.colors||{},...n}}}:{...t.theme||{},colors:{...t.theme?.colors||{},...n}}},{surfacePrefix:"bg",interactiveSurfacePrefix:"interactive-bg",disabledStyles:{textOpacity:.38,backgroundOpacity:.12,colorName:"on-surface"}}))}throw"A primary color must be specified"};export{Gt as withMaterialColors}; -//# sourceMappingURL=index.esm.js.map diff --git a/src/TabKeeper.UI.Wasm/tailwind.config.js b/src/TabKeeper.UI.Wasm/tailwind.config.js index 14c3ccf..8829ab2 100644 --- a/src/TabKeeper.UI.Wasm/tailwind.config.js +++ b/src/TabKeeper.UI.Wasm/tailwind.config.js @@ -1,36 +1,31 @@ -import { variants } from './tailwind.config.variants' - -const { withMaterialColors } = require('./tailwind-material-colors.esm'); +import { variants } from "./tailwind.config.variants" +const { withMaterialColors } = require("tailwind-material-colors"); module.exports = withMaterialColors( { - darkMode: 'class', + darkMode: ["selector", "[dark]"], content: [ "./**/*.{razor,html,cshtml}" ], plugins: [ - require('@tailwindcss/typography'), - require('@tailwindcss/forms'), + require("@tailwindcss/typography"), + require("@tailwindcss/forms"), variants, ], theme: { extend: { - screens: {}, // '2xl': {'max': '1535px'} + screens: {}, // "2xl": {"max": "1535px"} } - }, - safelist: [ - 'material-group' - ] + } }, { - // Here, your base colors as HEX values - // primary is required - primary: '#ff0000', - // secondary and/or tertiary are optional, if not set they will be derived from the primary color - //secondary: '#ffff00', - //tertiary: '#0000ff' + primary: "#ff0000", + //secondary: "#ffff00", + //tertiary: "#0000ff" + // error: "#FF5449", }, { + scheme: "content", extend: true } ); From 8ea0a92a3824e0154b7c2c91ebd18ebcdea5dbf9 Mon Sep 17 00:00:00 2001 From: Panos Date: Sat, 27 Jul 2024 20:08:33 +0300 Subject: [PATCH 18/61] add: Theme support --- src/TabKeeper.UI.Wasm/Program.cs | 9 ++++ .../TabKeeper.UI.Wasm.csproj | 2 + src/TabKeeper.UI.Wasm/Theme.cs | 38 ++++++++++++++++ src/TabKeeper.UI.Wasm/wwwroot/index.html | 1 + src/TabKeeper.UI.Wasm/wwwroot/js/index.js | 11 +++++ src/TabKeeper.UI.Wasm/wwwroot/js/theme.js | 44 +++++++++++++++++++ 6 files changed, 105 insertions(+) create mode 100644 src/TabKeeper.UI.Wasm/Theme.cs create mode 100644 src/TabKeeper.UI.Wasm/wwwroot/js/index.js create mode 100644 src/TabKeeper.UI.Wasm/wwwroot/js/theme.js diff --git a/src/TabKeeper.UI.Wasm/Program.cs b/src/TabKeeper.UI.Wasm/Program.cs index 037453a..6a4c7cc 100644 --- a/src/TabKeeper.UI.Wasm/Program.cs +++ b/src/TabKeeper.UI.Wasm/Program.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using Microsoft.JSInterop; +using System.Diagnostics.CodeAnalysis; using System.Reactive.Threading.Tasks; var builder = WebAssemblyHostBuilder.CreateDefault(args); @@ -29,9 +30,17 @@ var app = builder.Build(); +await Import(); await InitializeLang(app); + await app.RunAsync(); +[SuppressMessage("BrowserPlatform", "CA1416")] +static Task Import() +{ + return Theme.Import(); +} + static Task InitializeLang(WebAssemblyHost app) { var localStorage = app.Services.GetRequiredService(); diff --git a/src/TabKeeper.UI.Wasm/TabKeeper.UI.Wasm.csproj b/src/TabKeeper.UI.Wasm/TabKeeper.UI.Wasm.csproj index 4ae4c33..93d2704 100644 --- a/src/TabKeeper.UI.Wasm/TabKeeper.UI.Wasm.csproj +++ b/src/TabKeeper.UI.Wasm/TabKeeper.UI.Wasm.csproj @@ -6,6 +6,8 @@ + true + true diff --git a/src/TabKeeper.UI.Wasm/Theme.cs b/src/TabKeeper.UI.Wasm/Theme.cs new file mode 100644 index 0000000..7fea141 --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Theme.cs @@ -0,0 +1,38 @@ +using System.Runtime.InteropServices.JavaScript; +using System.Runtime.Versioning; + +namespace TabKeeper; + +[SupportedOSPlatform("browser")] +public partial class Theme +{ + private const string name = "WizardCounter.Theme"; + private static int imported; + + public static Task Import(string? url = null) + { + if (Interlocked.Exchange(ref imported, 1) is 1) + return Task.CompletedTask; + + // JSHost starts searching from inside _framework folder so we have to go one up. + return JSHost.ImportAsync(name, url ?? "../js/theme.js"); + } + + [JSImport("updateDom", name)] + public static partial void UpdateDom(); + + [JSImport("toggle", name)] + public static partial void Toggle(); + + [JSImport("setDark", name)] + public static partial void SetDark(); + + [JSImport("setLight", name)] + public static partial void SetLight(); + + [JSImport("setAuto", name)] + public static partial void SetAuto(); + + [JSImport("getTheme", name)] + public static partial string GetTheme(); +} diff --git a/src/TabKeeper.UI.Wasm/wwwroot/index.html b/src/TabKeeper.UI.Wasm/wwwroot/index.html index 8b37461..3f3620d 100644 --- a/src/TabKeeper.UI.Wasm/wwwroot/index.html +++ b/src/TabKeeper.UI.Wasm/wwwroot/index.html @@ -13,6 +13,7 @@ + diff --git a/src/TabKeeper.UI.Wasm/wwwroot/js/index.js b/src/TabKeeper.UI.Wasm/wwwroot/js/index.js new file mode 100644 index 0000000..4a5611b --- /dev/null +++ b/src/TabKeeper.UI.Wasm/wwwroot/js/index.js @@ -0,0 +1,11 @@ +(() => { + const dark = "dark"; + const light = "light"; + const key = "theme"; + + if (localStorage[key] === dark || (!(key in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) { + document.documentElement.setAttribute('dark', true) + } else { + document.documentElement.removeAttribute('dark') + } +})(); \ No newline at end of file diff --git a/src/TabKeeper.UI.Wasm/wwwroot/js/theme.js b/src/TabKeeper.UI.Wasm/wwwroot/js/theme.js new file mode 100644 index 0000000..f7fdabf --- /dev/null +++ b/src/TabKeeper.UI.Wasm/wwwroot/js/theme.js @@ -0,0 +1,44 @@ +const dark = "dark"; +const light = "light"; +const auto = "auto"; +const key = "theme"; + +export function updateDom() { + if (localStorage[key] === dark || (!(key in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) { + document.documentElement.setAttribute('dark', true) + } else { + document.documentElement.removeAttribute('dark') + } +} + +export function toggle() { + if (!(key in localStorage)) return; + + localStorage[key] === light ? setDark() : setLight(); + updateDom(); +} + +export function setDark() { + localStorage[key] = dark; + updateDom(); +} + +export function setLight() { + localStorage[key] = light; + updateDom(); +} + +export function setAuto() { + localStorage.removeItem(key); + updateDom(); +} + +export function getTheme() { + const theme = localStorage[key]; + + if ([dark, light, auto].some(v => v === theme)) + return theme; + + return auto; +} + From 6e734efabf0928a23753ed08b477dbb59ea4fc77 Mon Sep 17 00:00:00 2001 From: Panos Date: Sat, 27 Jul 2024 20:13:20 +0300 Subject: [PATCH 19/61] fix: navigation lings --- src/TabKeeper.UI.Wasm/Pages/Home/About.razor | 11 ----------- src/TabKeeper.UI.Wasm/Pages/Home/HomePage.razor | 7 +++---- 2 files changed, 3 insertions(+), 15 deletions(-) delete mode 100644 src/TabKeeper.UI.Wasm/Pages/Home/About.razor diff --git a/src/TabKeeper.UI.Wasm/Pages/Home/About.razor b/src/TabKeeper.UI.Wasm/Pages/Home/About.razor deleted file mode 100644 index b84ab70..0000000 --- a/src/TabKeeper.UI.Wasm/Pages/Home/About.razor +++ /dev/null @@ -1,11 +0,0 @@ -@page "/about" -@inherits CoreComponent -@inject TranslateService translate - - -@code { - protected override void OnInitialized() - { - ShellContext.Title = "general.about" | translate; - } -} diff --git a/src/TabKeeper.UI.Wasm/Pages/Home/HomePage.razor b/src/TabKeeper.UI.Wasm/Pages/Home/HomePage.razor index ffd7682..98d4331 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Home/HomePage.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Home/HomePage.razor @@ -33,8 +33,7 @@ - @("general.settings" | translate) - @("general.about" | translate) + @("general.settings" | translate) @@ -63,13 +62,13 @@ { if (newTabForm.Invalid) return; - var name = newTabForm.GetControl("name")?.Value; + var name = newTabForm.GetFormControl("name")?.Value; if (name is null or "") return; var entryId = Uuid.NewUuid(); Entries.Insert(0, new TabEntry(entryId, name)); - nav.NavigateTo($"/tabs/{entryId}"); + nav.NavigateTo($"tabs/{entryId}"); } protected override void OnInitialized() From 09a7fa63d8a9244bd390049ef6a929349c8a5eb0 Mon Sep 17 00:00:00 2001 From: Panos Date: Sat, 27 Jul 2024 20:19:39 +0300 Subject: [PATCH 20/61] implement settings page --- .../Pages/Home/HomePage.razor | 2 +- .../Pages/Home/SettingsPage.razor | 26 +++++++++++++++++-- src/TabKeeper.UI.Wasm/wwwroot/i18n/el.json | 13 ++++++---- src/TabKeeper.UI.Wasm/wwwroot/i18n/en.json | 13 ++++++---- 4 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/TabKeeper.UI.Wasm/Pages/Home/HomePage.razor b/src/TabKeeper.UI.Wasm/Pages/Home/HomePage.razor index 98d4331..6dc7ae2 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Home/HomePage.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Home/HomePage.razor @@ -33,7 +33,7 @@ - @("general.settings" | translate) + @("settings.title" | translate) diff --git a/src/TabKeeper.UI.Wasm/Pages/Home/SettingsPage.razor b/src/TabKeeper.UI.Wasm/Pages/Home/SettingsPage.razor index 2ca3780..e28f8a4 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Home/SettingsPage.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Home/SettingsPage.razor @@ -2,11 +2,33 @@ @inherits CoreComponent @inject TranslateService translate - +
+
+

@("settings.theme.title" | translate)

+
+ +
+
+
@code { protected override void OnInitialized() { - ShellContext.Title = "general.settings" | translate; + ShellContext.Title = "settings.title" | translate; + } + + public void OnThemeChange(ChangeEventArgs e) + { + Action execute = e.Value switch + { + "dark" => Theme.SetDark, + "light" => Theme.SetLight, + _ => Theme.SetAuto + }; + execute(); } } diff --git a/src/TabKeeper.UI.Wasm/wwwroot/i18n/el.json b/src/TabKeeper.UI.Wasm/wwwroot/i18n/el.json index 83cb899..db08280 100644 --- a/src/TabKeeper.UI.Wasm/wwwroot/i18n/el.json +++ b/src/TabKeeper.UI.Wasm/wwwroot/i18n/el.json @@ -1,15 +1,18 @@ { "general": { "home": "Αρχική", - "settings": "Ρυθμίσεις", - "about": "Σχετικά", "not-found": { "title": "Δεν βρέθηκε", "description": "Συγγνώμη, δεν υπάρχει τίποτα σε αυτήν τη διεύθυνση." } }, - "errors": { - }, - "pages": { + "settings": { + "title": "Ρυθμίσεις", + "theme": { + "title": "Θέμα", + "auto": "Αυτόματο", + "dark": "Σκοτεινό", + "light": "Φωτεινό" + } } } diff --git a/src/TabKeeper.UI.Wasm/wwwroot/i18n/en.json b/src/TabKeeper.UI.Wasm/wwwroot/i18n/en.json index a18cdf8..31cdb0a 100644 --- a/src/TabKeeper.UI.Wasm/wwwroot/i18n/en.json +++ b/src/TabKeeper.UI.Wasm/wwwroot/i18n/en.json @@ -1,15 +1,18 @@ { "general": { "home": "Home", - "settings": "Settings", - "about": "About", "not-found": { "title": "Not Found", "description": "Sorry, there is nothing at this address." } }, - "errors": { - }, - "pages": { + "settings": { + "title": "Settings", + "theme": { + "title": "Theme", + "auto": "Auto", + "dark": "Dark", + "light": "Light" + } } } From f4acd149236db65c45d837c104f14d61fbe72636 Mon Sep 17 00:00:00 2001 From: Panos Date: Sun, 28 Jul 2024 18:01:35 +0300 Subject: [PATCH 21/61] update: Core submodule --- src-modules/Core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-modules/Core b/src-modules/Core index 6d74274..b4030ca 160000 --- a/src-modules/Core +++ b/src-modules/Core @@ -1 +1 @@ -Subproject commit 6d74274688eb3b0b7b95806791dc9529850659e0 +Subproject commit b4030ca49e8ced0fbd44f1e85cd1c0bb80c98b34 From 499a33fc5afe09a5606cc0990e3df82f2d38d0eb Mon Sep 17 00:00:00 2001 From: Panos Date: Sun, 28 Jul 2024 20:01:11 +0300 Subject: [PATCH 22/61] chore: refactor usings and pages from Core update --- TabKeeper.sln | 7 - .../Common/Mixins/NavigationManagerMixins.cs | 14 ++ .../Common/Mixins/TranslateMixins.cs | 4 +- src/TabKeeper.UI.Wasm/Components/Button.razor | 17 +- .../Components/Dropdown.razor | 2 +- .../Components/DropdownButton.razor | 2 +- .../Components/DropdownContent.razor | 2 +- .../Components/DropdownItem.razor | 2 +- src/TabKeeper.UI.Wasm/Components/Modal.razor | 12 +- src/TabKeeper.UI.Wasm/Layout/ShellContext.cs | 13 ++ .../Layout/ShellLayout.razor | 45 ++++- .../Pages/{Home => }/HomePage.razor | 8 +- src/TabKeeper.UI.Wasm/Pages/HomePage2.razor | 158 ++++++++++++++++++ .../Pages/{Home => }/SettingsPage.razor | 2 +- .../Pages/Tabs/TabPage.razor | 60 ++++--- .../Pages/Tabs/_imports.razor | 3 +- src/TabKeeper.UI.Wasm/Program.cs | 1 - src/TabKeeper.UI.Wasm/ShellContext.cs | 16 -- src/TabKeeper.UI.Wasm/_Imports.razor | 7 +- src/TabKeeper.UI.Wasm/_usings.cs | 2 + src/TabKeeper.UI.Wasm/assets/_cards.scss | 2 +- src/TabKeeper.UI.Wasm/assets/_input.scss | 26 --- .../assets/_material-input.scss | 31 ++-- src/TabKeeper.UI.Wasm/assets/app.scss | 54 +----- src/TabKeeper.UI.Wasm/tailwind.config.js | 8 +- 25 files changed, 317 insertions(+), 181 deletions(-) create mode 100644 src/TabKeeper.UI.Wasm/Common/Mixins/NavigationManagerMixins.cs create mode 100644 src/TabKeeper.UI.Wasm/Layout/ShellContext.cs rename src/TabKeeper.UI.Wasm/Pages/{Home => }/HomePage.razor (94%) create mode 100644 src/TabKeeper.UI.Wasm/Pages/HomePage2.razor rename src/TabKeeper.UI.Wasm/Pages/{Home => }/SettingsPage.razor (92%) delete mode 100644 src/TabKeeper.UI.Wasm/ShellContext.cs delete mode 100644 src/TabKeeper.UI.Wasm/assets/_input.scss diff --git a/TabKeeper.sln b/TabKeeper.sln index 1fb8969..b56e044 100644 --- a/TabKeeper.sln +++ b/TabKeeper.sln @@ -39,8 +39,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Web", "src-modules\Cor EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Core.Blazor", "src-modules\Core\src\Core.Blazor\Core.Blazor.csproj", "{F284A251-6C8E-4F53-8461-E6972204429E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp1", "src\ConsoleApp1\ConsoleApp1.csproj", "{835E7869-965B-4D97-9043-F598F7AA8557}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -79,10 +77,6 @@ Global {F284A251-6C8E-4F53-8461-E6972204429E}.Debug|Any CPU.Build.0 = Debug|Any CPU {F284A251-6C8E-4F53-8461-E6972204429E}.Release|Any CPU.ActiveCfg = Release|Any CPU {F284A251-6C8E-4F53-8461-E6972204429E}.Release|Any CPU.Build.0 = Release|Any CPU - {835E7869-965B-4D97-9043-F598F7AA8557}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {835E7869-965B-4D97-9043-F598F7AA8557}.Debug|Any CPU.Build.0 = Debug|Any CPU - {835E7869-965B-4D97-9043-F598F7AA8557}.Release|Any CPU.ActiveCfg = Release|Any CPU - {835E7869-965B-4D97-9043-F598F7AA8557}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -96,7 +90,6 @@ Global {FA50AF51-FC1D-4259-BA00-03B5E7592484} = {0F8AC477-3BF8-411F-BC0B-767F820697EA} {6E21EE17-77BD-4072-BDDB-027D38C6D188} = {0F8AC477-3BF8-411F-BC0B-767F820697EA} {F284A251-6C8E-4F53-8461-E6972204429E} = {0F8AC477-3BF8-411F-BC0B-767F820697EA} - {835E7869-965B-4D97-9043-F598F7AA8557} = {1FE5EE5F-70AA-4824-B306-304ADBF3A312} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {26EECD34-43C6-4F7A-A567-0F8AC7F82094} diff --git a/src/TabKeeper.UI.Wasm/Common/Mixins/NavigationManagerMixins.cs b/src/TabKeeper.UI.Wasm/Common/Mixins/NavigationManagerMixins.cs new file mode 100644 index 0000000..38a65a6 --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Common/Mixins/NavigationManagerMixins.cs @@ -0,0 +1,14 @@ +namespace Microsoft.AspNetCore.Components; + +public static class NavigationManagerMixins +{ + public static void GoBack(this NavigationManager nav, bool forceLoad = false, bool replace = false) + { + nav.NavigateTo(nav.Uri.RemovePathSegment(), forceLoad, replace); + } + + public static void GoBack(this NavigationManager nav, NavigationOptions options) + { + nav.NavigateTo(nav.Uri.RemovePathSegment(), options); + } +} diff --git a/src/TabKeeper.UI.Wasm/Common/Mixins/TranslateMixins.cs b/src/TabKeeper.UI.Wasm/Common/Mixins/TranslateMixins.cs index 2c95121..f7325b2 100644 --- a/src/TabKeeper.UI.Wasm/Common/Mixins/TranslateMixins.cs +++ b/src/TabKeeper.UI.Wasm/Common/Mixins/TranslateMixins.cs @@ -1,7 +1,7 @@ -using Annular.Translate; +using Core.Blazor; using Microsoft.AspNetCore.Components; -namespace Core.Blazor.Translate; +namespace Annular.Translate; public static class TranslateMixins { diff --git a/src/TabKeeper.UI.Wasm/Components/Button.razor b/src/TabKeeper.UI.Wasm/Components/Button.razor index aca98f3..ca28fd8 100644 --- a/src/TabKeeper.UI.Wasm/Components/Button.razor +++ b/src/TabKeeper.UI.Wasm/Components/Button.razor @@ -1,10 +1,8 @@ -@using System.Diagnostics.CodeAnalysis -@using System.Globalization -@using OneOf; +@using OneOf @inherits CoreComponent -@if (!If.Match(static v => v, static f => f())) +@if (If?.Match(static v => v, static f => f()) is false) { return; } @@ -30,6 +28,9 @@ @code { + [Parameter] + public OneOf>? If { get; set; } + [Parameter] public RenderFragment? ChildContent { get; set; } @@ -45,12 +46,10 @@ [Parameter] public bool PreventDefault { get; set; } - public OneOf> If { get; set; } = true; - - private string TypeAttribute => GetAttributeOrDefault("type", "button"); + private string TypeAttribute => this.GetAttributeOrDefault("type", "button"); - private bool DisabledAttribute => GetAttributeOrDefault("disabled", false) || IsLoading; + private bool DisabledAttribute => this.GetAttributeOrDefault("disabled", false) || IsLoading; private string? ClassAttribute - => Css.Class(TryGetAttribute("class"), ("cursor-not-allowed relative", IsLoading)); + => Css.Class(this.TryGetAttribute("class"), ("cursor-not-allowed relative", IsLoading)); } diff --git a/src/TabKeeper.UI.Wasm/Components/Dropdown.razor b/src/TabKeeper.UI.Wasm/Components/Dropdown.razor index 61661eb..e956193 100644 --- a/src/TabKeeper.UI.Wasm/Components/Dropdown.razor +++ b/src/TabKeeper.UI.Wasm/Components/Dropdown.razor @@ -1,6 +1,6 @@ @inherits CoreComponent - + @ChildContent diff --git a/src/TabKeeper.UI.Wasm/Components/DropdownButton.razor b/src/TabKeeper.UI.Wasm/Components/DropdownButton.razor index 2a7f4f2..0870b5a 100644 --- a/src/TabKeeper.UI.Wasm/Components/DropdownButton.razor +++ b/src/TabKeeper.UI.Wasm/Components/DropdownButton.razor @@ -1,6 +1,6 @@ @inherits CoreComponent - + @(ChildContent?.Invoke(Menu?.IsOpen ?? false)) diff --git a/src/TabKeeper.UI.Wasm/Components/DropdownContent.razor b/src/TabKeeper.UI.Wasm/Components/DropdownContent.razor index 53f8c57..abadac0 100644 --- a/src/TabKeeper.UI.Wasm/Components/DropdownContent.razor +++ b/src/TabKeeper.UI.Wasm/Components/DropdownContent.razor @@ -8,7 +8,7 @@ LeaveFrom="transform opacity-100 scale-100" LeaveTo="transform opacity-0 scale-95" Context="transition"> - + @ChildContent diff --git a/src/TabKeeper.UI.Wasm/Components/DropdownItem.razor b/src/TabKeeper.UI.Wasm/Components/DropdownItem.razor index b364677..643489b 100644 --- a/src/TabKeeper.UI.Wasm/Components/DropdownItem.razor +++ b/src/TabKeeper.UI.Wasm/Components/DropdownItem.razor @@ -2,7 +2,7 @@ diff --git a/src/TabKeeper.UI.Wasm/Components/Modal.razor b/src/TabKeeper.UI.Wasm/Components/Modal.razor index a53a5f6..3be2e50 100644 --- a/src/TabKeeper.UI.Wasm/Components/Modal.razor +++ b/src/TabKeeper.UI.Wasm/Components/Modal.razor @@ -13,11 +13,11 @@ LeaveTo="opacity-0" Context="transition"> -
+
-
+
-
("class") ?? "self-center justify-self-center", transition.CssClass)" @onclick:stopPropagation> +
@(ChildContent?.Invoke(this)) @@ -79,7 +79,7 @@ var sub = IsOpenWhen.Subscribe(open => { IsOpen = open; - base.Update(); + base.TriggerUpdate(); }); DisposeWith(sub); } @@ -94,7 +94,7 @@ { IsOpen = true; OnShow.InvokeAsync(); - base.Update(); + base.TriggerUpdate(); return None.Value; } @@ -102,7 +102,7 @@ { IsOpen = false; OnDismiss.InvokeAsync(); - base.Update(); + base.TriggerUpdate(); return None.Value; } diff --git a/src/TabKeeper.UI.Wasm/Layout/ShellContext.cs b/src/TabKeeper.UI.Wasm/Layout/ShellContext.cs new file mode 100644 index 0000000..41279fb --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Layout/ShellContext.cs @@ -0,0 +1,13 @@ +namespace TabKeeper.Layout; + +public readonly record struct ShellContext +{ + public string Title { get; init; } + + public string? BackUri { get; init; } + + public ShellContext() + { + Title = string.Empty; + } +} diff --git a/src/TabKeeper.UI.Wasm/Layout/ShellLayout.razor b/src/TabKeeper.UI.Wasm/Layout/ShellLayout.razor index ed45bdd..39bdf8e 100644 --- a/src/TabKeeper.UI.Wasm/Layout/ShellLayout.razor +++ b/src/TabKeeper.UI.Wasm/Layout/ShellLayout.razor @@ -1,6 +1,8 @@ @inherits LayoutComponentBase +@implements IDisposable @inject TranslateService translate +@inject NavigationManager nav @if (ThisAssembly.IsPrerelease) { @@ -11,10 +13,11 @@
} -@title +@(string.IsNullOrEmpty(Title) ? "Tab Keeper" : $"Tab Keeper - {Title}") -
-

@ShellContext.Title

+
+ +

@Title

@@ -22,14 +25,38 @@
@code { - private string? title; + private static readonly BehaviorSubject contextSub = new(new()); + private IDisposable? sub; protected override void OnInitialized() { - ShellContext.TitleChanged.Subscribe(title => - { - this.title = string.IsNullOrEmpty(ShellContext.Title) ? "Tab Keeper" : $"Tab Keeper - {title}"; - StateHasChanged(); - }); + sub = contextSub.Subscribe(_ => StateHasChanged()); + } + + public static IObservable ContextChanged { get; } = contextSub.AsObservable(); + + public static ShellContext Context + { + get => contextSub.Value; + set { + if (contextSub.Value == value) return; + contextSub.OnNext(value); + } + } + + public static string Title + { + get => Context.Title; + } + + public static string? BackUri + { + get => Context.BackUri; + } + + public void Dispose() + { + sub?.Dispose(); + sub = null; } } diff --git a/src/TabKeeper.UI.Wasm/Pages/Home/HomePage.razor b/src/TabKeeper.UI.Wasm/Pages/HomePage.razor similarity index 94% rename from src/TabKeeper.UI.Wasm/Pages/Home/HomePage.razor rename to src/TabKeeper.UI.Wasm/Pages/HomePage.razor index 6dc7ae2..4637166 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Home/HomePage.razor +++ b/src/TabKeeper.UI.Wasm/Pages/HomePage.razor @@ -1,5 +1,4 @@ @page "/" -@using Core.Blazor.Reactive.Forms.Primitives @inherits CoreComponent @inject ISyncLocalStorageService storage @inject NavigationManager nav @@ -73,7 +72,8 @@ protected override void OnInitialized() { - ShellContext.Title = "general.home" | translate; + ShellLayout.Context = new() { Title = "general.home" | translate }; + // NewTabEntryName.Subscribe(_ => Update()); Entries .Connect() @@ -81,8 +81,8 @@ .OnItemRemoved(entry => storage.RemoveItem(entry.Id), invokeOnUnsubscribe: false) .QueryWhenChanged() .Do(entries => storage.SetItem(EntriesKey, entries)) - .Subscribe(_ => Update()) - .DisposeWith(Disposables); + .Subscribe(_ => TriggerUpdate()) + .DisposeWith(this); Entries.AddRange(storage.GetItem>(EntriesKey) ?? []); } diff --git a/src/TabKeeper.UI.Wasm/Pages/HomePage2.razor b/src/TabKeeper.UI.Wasm/Pages/HomePage2.razor new file mode 100644 index 0000000..a49c6d9 --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Pages/HomePage2.razor @@ -0,0 +1,158 @@ +@page "/home" + +@inherits CoreComponent +@inject TranslateService translate + +
+
+

Personal

+ @if (personalGroup.Invalid) + { + + } +
+
+
+ + +
+
+
+ +
+
+

Economic

+ @if (economicGroup.Invalid) + { + + } +
+
+
+ + +
+
+
+ +
+
+

Children

+ @if (childrenArray.Invalid) + { + + } +
+
+ @for (int i = 0; i < childrenArray.Count; i++) + { + var index = i; + var formGroup = (FormGroup)childrenArray[index]; + +
+ + +
+ } +
+
+ + + + + + + + +@code { + private static readonly ValidatorFn Required = Validators.Required; + private static readonly ValidatorFn MinLength3 = Validators.MinLength(3); + private static readonly ValidatorFn Min3 = Validators.Min(3M); + + private UpdateRequest Request { get; set; } = new(); + + private FormGroup formGroup; + private FormGroup personalGroup; + private FormGroup economicGroup; + private FormArray childrenArray; + + public HomePage2() + { + formGroup = new() + { + ["Personal"] = personalGroup = new() + { + ["FirstName"] = new FormControl(sync: [Required, MinLength3]), + ["LastName"] = new FormControl(sync: [Required, MinLength3]) + }, + ["Economic"] = economicGroup = new() + { + ["AnnualIncome"] = new FormControl(sync: [Required, Min3]), + ["AssetsValue"] = new FormControl(sync: [Required, Min3]) + }, + ["Children"] = childrenArray = new(), + }; + AddChild(); + } + + protected override void OnInitialized() + { + formGroup.Events.Subscribe(_ => TriggerUpdate()); + } + + private void AddChild() + { + childrenArray.Add(new FormGroup() + { + ["FirstName"] = new FormControl(sync: [Required, MinLength3]), + ["LastName"] = new FormControl(sync: [Required, MinLength3]) + }); + Request.Children.Add(new()); + TriggerUpdate(); + } + + private void RemoveChild(int index) + { + childrenArray.RemoveAt(index); + Request.Children.RemoveAt(index); + TriggerUpdate(); + } + + private void Test() + { + Console.WriteLine($"Income Vs: {formGroup.GetFormControl("Economic.AnnualIncome").Validators.Count()}"); + + Console.WriteLine($"- AnnualIncome: {formGroup.GetFormControl("Economic.AnnualIncome").Value}"); + Console.WriteLine($"- AssetsValue: {formGroup.GetFormControl("Economic.AssetsValue").Value}"); + Console.WriteLine("Children"); + for (int i = 0; i < childrenArray.Count; i++) + { + Console.WriteLine($"- {i,00} - FirstName: {formGroup.GetFormControl($"Children.[{i}].FirstName").Value}"); + Console.WriteLine($"- {i,00} - LastName: {formGroup.GetFormControl($"Children.[{i}].LastName").Value}"); + } + Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(Request)); + } + + private class UpdateRequest + { + public PersonalDetails Personal { get; } = new(); + + public EconomicDetails Economic { get; } = new(); + + public List Children { get; } = []; + } + + private class PersonalDetails + { + public string FirstName { get; set; } = string.Empty; + + public string LastName { get; set; } = string.Empty; + } + + private class EconomicDetails + { + public decimal AnnualIncome { get; set; } + + public decimal AssetsValue { get; set; } + } +} diff --git a/src/TabKeeper.UI.Wasm/Pages/Home/SettingsPage.razor b/src/TabKeeper.UI.Wasm/Pages/SettingsPage.razor similarity index 92% rename from src/TabKeeper.UI.Wasm/Pages/Home/SettingsPage.razor rename to src/TabKeeper.UI.Wasm/Pages/SettingsPage.razor index e28f8a4..563cbbf 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Home/SettingsPage.razor +++ b/src/TabKeeper.UI.Wasm/Pages/SettingsPage.razor @@ -18,7 +18,7 @@ @code { protected override void OnInitialized() { - ShellContext.Title = "settings.title" | translate; + ShellLayout.Context = new() { Title = "settings.title" | translate }; } public void OnThemeChange(ChangeEventArgs e) diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor index bfcb675..ca57e38 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor @@ -63,7 +63,7 @@

@ViewModel.People.Items.Sum(x => x.Total)

- @@ -110,31 +110,33 @@ @foreach (var product in ViewModel.Products.Items) { var key = product.ProductId.ToString(); -
+
- +
} @* Add Product Modal *@ - - @if (NewProduct.Value is null) { return; } - - - - -
- + + +
+ +
+
+
-
- +
+ +
+
+
- - + + @* Add Person Modal *@ @@ -153,20 +155,32 @@ @code { - public override TabViewModel ViewModel { get; set; } + private static ValidatorFn MinLength3 = Validators.MinLength(3); + private static ValidatorFn Min = Validators.MoreThan(0.0M); private BehaviorSubject SelectedProduct { get; } = new(null); private BehaviorSubject SelectedPerson { get; } = new(null); - private BehaviorSubject NewProduct { get; } = new(null); private BehaviorSubject NewPerson { get; } = new(null); + private Modal NewProductModal { get; set; } = null!; + private FormGroup NewProductForm { get; } = new(); + private ProductViewModel NewProductModel { get; set; } = new(); + + private FormGroup NewPersonForm { get; } = new(); + [Parameter] public string Id { get; set; } = string.Empty; private void OnAddProduct() { - ViewModel.AddProduct(NewProduct.Value!); - NewProduct.OnNext(new()); + Console.WriteLine($"Count: {NewProductForm.Count}"); + return; + if (NewProductForm.Invalid) return; + + ViewModel.AddProduct(NewProductModel); + NewProductModel = new(); + NewProductModal.Close(); + // NewProduct.OnNext(new()); } private void OnAddPerson() @@ -175,8 +189,6 @@ NewPerson.OnNext(new()); } - - protected override void OnInitialized() { var tab = storage.GetItem(Id); @@ -186,7 +198,7 @@ return; } - ShellContext.Title = tab.Name; + ShellLayout.Context = new() { Title = tab.Name, BackUri = "" }; ViewModel = new TabViewModel(tab); ViewModel.WhenPropertyChanged .Throttle(TimeSpan.FromSeconds(1)) diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/_imports.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/_imports.razor index e123412..3a63e26 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Tabs/_imports.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/_imports.razor @@ -1 +1,2 @@ -@using TabKeeper.Tabs \ No newline at end of file +@using TabKeeper.Tabs +@using TabKeeper.People diff --git a/src/TabKeeper.UI.Wasm/Program.cs b/src/TabKeeper.UI.Wasm/Program.cs index 6a4c7cc..570a4d1 100644 --- a/src/TabKeeper.UI.Wasm/Program.cs +++ b/src/TabKeeper.UI.Wasm/Program.cs @@ -2,7 +2,6 @@ using Annular.Translate.Abstract; using Annular.Translate.HttpLoader; using Blazored.LocalStorage; -using Core.Blazor; using Ignis.Components.HeadlessUI; using Ignis.Components.WebAssembly; using Microsoft.AspNetCore.Components.Web; diff --git a/src/TabKeeper.UI.Wasm/ShellContext.cs b/src/TabKeeper.UI.Wasm/ShellContext.cs deleted file mode 100644 index 790081c..0000000 --- a/src/TabKeeper.UI.Wasm/ShellContext.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.Reactive.Subjects; - -namespace TabKeeper; - -public sealed class ShellContext -{ - private static readonly BehaviorSubject titleSub = new(string.Empty); - - public static IObservable TitleChanged { get; } = titleSub.AsObservable(); - - public static string Title - { - get => titleSub.Value; - set => titleSub.OnNext(value); - } -} diff --git a/src/TabKeeper.UI.Wasm/_Imports.razor b/src/TabKeeper.UI.Wasm/_Imports.razor index 05a7674..dda6bdd 100644 --- a/src/TabKeeper.UI.Wasm/_Imports.razor +++ b/src/TabKeeper.UI.Wasm/_Imports.razor @@ -5,9 +5,10 @@ @using Blazored.LocalStorage @using Core @using Core.Abstractions -@using Core.Blazor @using Core.Blazor.Reactive.Forms -@using Core.Blazor.RxForms; +@using Core.Blazor.Reactive.Forms.Primitives +@using Core.Components.Forms; +@using Core.Reactive @using Annular.Translate @using DynamicData @using DynamicData.Cache @@ -20,8 +21,6 @@ @using Microsoft.JSInterop @using TabKeeper @using TabKeeper.Components -@using TabKeeper.People -@using TabKeeper.Tabs @using Ignis.Components @using Ignis.Components.HeadlessUI @using Ignis.Components.Reactivity diff --git a/src/TabKeeper.UI.Wasm/_usings.cs b/src/TabKeeper.UI.Wasm/_usings.cs index 07abfab..46d5c75 100644 --- a/src/TabKeeper.UI.Wasm/_usings.cs +++ b/src/TabKeeper.UI.Wasm/_usings.cs @@ -2,5 +2,7 @@ global using Core.Abstractions; global using DynamicData; global using DynamicData.Aggregation; +global using Flurl; global using System.Reactive.Linq; global using TabKeeper; +global using TabKeeper.Layout; diff --git a/src/TabKeeper.UI.Wasm/assets/_cards.scss b/src/TabKeeper.UI.Wasm/assets/_cards.scss index 1e2289d..3160c68 100644 --- a/src/TabKeeper.UI.Wasm/assets/_cards.scss +++ b/src/TabKeeper.UI.Wasm/assets/_cards.scss @@ -1,5 +1,5 @@ @layer components { .card { - @apply rounded-lg bg-surface-variant text-gray-500 p-4; + @apply rounded-lg bg-surface-variant p-4; } } diff --git a/src/TabKeeper.UI.Wasm/assets/_input.scss b/src/TabKeeper.UI.Wasm/assets/_input.scss deleted file mode 100644 index b4c53e2..0000000 --- a/src/TabKeeper.UI.Wasm/assets/_input.scss +++ /dev/null @@ -1,26 +0,0 @@ -@layer components { - /*input[type='checkbox'] { - @apply relative appearance-none min-w-[22px] min-h-[22px] m-1 bg-white border-2 rounded cursor-pointer outline-none;*/ - - /*&:checked { - @apply border-primary; - - &:before { - @apply absolute inset-0 flex items-center justify-center text-sm;*/ - /*content: url(../src/assets/images/icon-check.svg);*/ - /*} - }*/ - - /*&:focus:checked { - @apply border-2 border-primary; - } - - &:focus:not(:checked) { - @apply border-2 border-primary; - } - - &:disabled { - @apply cursor-default border-gray-500; - } - }*/ -} \ No newline at end of file diff --git a/src/TabKeeper.UI.Wasm/assets/_material-input.scss b/src/TabKeeper.UI.Wasm/assets/_material-input.scss index b8e9b5e..2efdba1 100644 --- a/src/TabKeeper.UI.Wasm/assets/_material-input.scss +++ b/src/TabKeeper.UI.Wasm/assets/_material-input.scss @@ -1,24 +1,31 @@ -@layer components { +@layer base { + input, + textarea { + @apply w-full p-2 rounded focus:ring-0; + } + + .error { + @apply text-sm text-error; + } + .material-input { @apply relative; input { - @apply w-full rounded border-2 bg-white p-1 text-gray-900 placeholder-transparent focus:outline-none; - @apply border-gray-300; - @apply focus:border-rose-600; + @apply rounded p-2 pt-5 border-0 placeholder-transparent bg-surface focus:border-on-surface focus:ring-0; } label { /* Defaults */ - @apply pointer-events-none absolute left-2 translate-y-1/2 cursor-text bg-white transition-all; + @apply pointer-events-none absolute top-0 translate-y-1/2 text-on-surface cursor-text text-opacity-70 transition-all duration-200; /* Styling */ - @apply text-sm font-medium text-gray-600; - @apply next-input-placeholder-shown:text-base next-input-placeholder-shown:text-gray-500; + @apply text-sm font-medium; + @apply next-input-placeholder-shown:text-base; @apply next-input-focus:text-sm; /* Placing */ - @apply bottom-full px-1; - @apply next-input-placeholder-shown:bottom-1/2 next-input-placeholder-shown:left-1.5 next-input-placeholder-shown:px-0; - @apply next-input-focus:bottom-full next-input-focus:left-2 next-input-focus:px-1; + @apply bottom-full px-2; + @apply next-input-placeholder-shown:bottom-1/2; + @apply next-input-focus:bottom-full next-input-focus:top-0; } } @@ -27,8 +34,4 @@ @apply appearance-none min-w-[18px] min-h-[18px] rounded-sm; } } - - .error { - @apply text-sm text-red-500; - } } diff --git a/src/TabKeeper.UI.Wasm/assets/app.scss b/src/TabKeeper.UI.Wasm/assets/app.scss index 8229f6a..80abb63 100644 --- a/src/TabKeeper.UI.Wasm/assets/app.scss +++ b/src/TabKeeper.UI.Wasm/assets/app.scss @@ -1,7 +1,6 @@ @import "./_buttons.scss"; @import "./_cards.scss"; @import "./_icons.scss"; -@import "./_input.scss"; @import "./_material-input.scss"; @tailwind base; @@ -22,67 +21,26 @@ h1 { @apply text-2xl font-bold mb-4; } + h2 { - @apply text-xl font-semibold mb-3; + @apply text-xl mb-3; } + h3 { @apply text-lg font-medium mb-2; } + h4 { @apply text-base font-normal mb-1; } p { + @apply text-base; } small { } - /*input[type='checkbox'] { - @apply relative appearance-none min-w-[22px] min-h-[22px] m-1 bg-white border-2 border-grey rounded cursor-pointer outline-none; - - &:checked { - @apply border-grey-130; - - &:before { - @apply absolute inset-0 flex items-center justify-center text-sm; - content: url(../src/assets/images/icon-check.svg); - } - } - - &:focus:checked { - @apply border-2 border-grey-130; - } - - &:focus:not(:checked) { - @apply border-2 border-grey; - } - - &:disabled { - @apply cursor-default border-grey; - } - }*/ -} - -@layer components { - .material-group { - @apply relative; - } - - .material-input { - @apply w-full placeholder:invisible rounded bg-white; - } - - .material-label { - @apply absolute top-0 left-2 px-2 text-sm transition-all ease-linear select-none pointer-events-none; - - @apply peer-placeholder-shown:translate-y-1/2 peer-placeholder-shown:text-gray-500; - - @apply -translate-y-1/2 bg-white text-gray-950; - @apply peer-focus:-translate-y-1/2 peer-focus:text-gray-950; - } - - .material-error { - @apply text-sm text-red-500; + label { } } diff --git a/src/TabKeeper.UI.Wasm/tailwind.config.js b/src/TabKeeper.UI.Wasm/tailwind.config.js index 8829ab2..d15a2c3 100644 --- a/src/TabKeeper.UI.Wasm/tailwind.config.js +++ b/src/TabKeeper.UI.Wasm/tailwind.config.js @@ -19,10 +19,10 @@ module.exports = withMaterialColors( } }, { - primary: "#ff0000", - //secondary: "#ffff00", - //tertiary: "#0000ff" - // error: "#FF5449", + primary: "#32EBDE", + secondary: "#779793", + tertiary: "#7594B4", + error: "#FF5449", }, { scheme: "content", From c0b688f9c7aacc8bab3023cfe024719e500ae366 Mon Sep 17 00:00:00 2001 From: Panos Date: Sun, 28 Jul 2024 20:13:43 +0300 Subject: [PATCH 23/61] fix(TabPage): overflowing number in bar --- src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor index ca57e38..8cbc0fa 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor @@ -58,10 +58,10 @@
-

@ViewModel.Products.Items.Sum(x => x.Total)

+

@ViewModel.Products.Items.Sum(x => x.Total).ToString("0.00")

-

@ViewModel.People.Items.Sum(x => x.Total)

+

@ViewModel.People.Items.Sum(x => x.Total).ToString("0.00")

-

@Title

+

@Title

diff --git a/src/TabKeeper.UI.Wasm/Pages/HomePage.razor b/src/TabKeeper.UI.Wasm/Pages/HomePage.razor index 4637166..e08914e 100644 --- a/src/TabKeeper.UI.Wasm/Pages/HomePage.razor +++ b/src/TabKeeper.UI.Wasm/Pages/HomePage.razor @@ -1,12 +1,13 @@ @page "/" @inherits CoreComponent -@inject ISyncLocalStorageService storage +@inject IndexedDb indexedDb @inject NavigationManager nav @inject TranslateService translate
+ @* Tabs *@
- @foreach(var entry in Entries.Items) + @foreach(var entry in Entries.Items.OrderBy(x => x.Date)) {

@entry.Name

@@ -22,6 +23,7 @@ }
+ @* Options *@
- - -
- -
- -
- + + + @code { - private ValidatorFn MinLength3 = Validators.MinLength(3); - private const string EntriesKey = "tab-entries"; - - private FormGroup newTabForm = new(); private Modal addEntryModal = null!; - private SourceList Entries { get; } = new(); + private bool loading = true; - private void AddNewTab() + private async Task TabValidSubmit(TabKeeper.Tabs.Tab tab) { - if (newTabForm.Invalid) return; - - var name = newTabForm.GetFormControl("name")?.Value; - - if (name is null or "") return; - - var entryId = Uuid.NewUuid(); - Entries.Insert(0, new TabEntry(entryId, name)); - nav.NavigateTo($"tabs/{entryId}"); + await indexedDb.Tabs.AddAsync(tab); + nav.NavigateTo($"tabs/{tab.Id}"); } protected override void OnInitialized() { ShellLayout.Context = new() { Title = "general.home" | translate }; - // NewTabEntryName.Subscribe(_ => Update()); - Entries - .Connect() - .OnItemAdded(entry => storage.TrySetItem(entry.Id, new TabKeeper.Tabs.Tab { Id = entry.Id, Name = entry.Name, Date = DateOnly.FromDateTime(DateTime.Now) })) - .OnItemRemoved(entry => storage.RemoveItem(entry.Id), invokeOnUnsubscribe: false) - .QueryWhenChanged() - .Do(entries => storage.SetItem(EntriesKey, entries)) - .Subscribe(_ => TriggerUpdate()) - .DisposeWith(this); + indexedDb.Tabs + .GetAllAsync() + .ToObservable() + .Do(entries => + { + Entries.AddRange(entries); + Entries + .Connect() + .OnItemRemoved(async entry => await indexedDb.Tabs.BatchDeleteAsync([entry.Id]), invokeOnUnsubscribe: false) + .Subscribe(_ => TriggerUpdate()) + .DisposeWith(this); + loading = false; + }) + .Subscribe(_ => Update()); - Entries.AddRange(storage.GetItem>(EntriesKey) ?? []); + // NewTabEntryName.Subscribe(_ => Update()); } - private record TabEntry(Uuid Id, string Name); + private record TabEntry(Uuid Id, string Name, DateOnly? Date); } diff --git a/src/TabKeeper.UI.Wasm/Pages/People/Components/PersonForm.razor b/src/TabKeeper.UI.Wasm/Pages/People/Components/PersonForm.razor new file mode 100644 index 0000000..0d21587 --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Pages/People/Components/PersonForm.razor @@ -0,0 +1,42 @@ +@inherits CoreComponent +@inject TranslateService translate + + + + +
+ + +
+ + +
+ +@code { + [Parameter, NotNull] + public Person? Person { get; set; } + + [Parameter] + public bool OnValidReset { get; set; } + + [Parameter] + public EventCallback OnValidSubmit { get; set; } + + public void Reset() + { + Person = new(); + Update(); + } + + protected override void OnInitialized() + { + Person ??= new(); + } + + private void ValidSubmit() + { + OnValidSubmit.InvokeAsync(Person); + if (OnValidReset) + Reset(); + } +} diff --git a/src/TabKeeper.UI.Wasm/Pages/People/_imports.razor b/src/TabKeeper.UI.Wasm/Pages/People/_imports.razor new file mode 100644 index 0000000..4b3a7b3 --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Pages/People/_imports.razor @@ -0,0 +1,2 @@ +@using TabKeeper.People +@using TabKeeper.Pages.People.Components diff --git a/src/TabKeeper.UI.Wasm/Pages/SettingsPage.razor b/src/TabKeeper.UI.Wasm/Pages/SettingsPage.razor index 563cbbf..dbe8ebc 100644 --- a/src/TabKeeper.UI.Wasm/Pages/SettingsPage.razor +++ b/src/TabKeeper.UI.Wasm/Pages/SettingsPage.razor @@ -6,7 +6,7 @@

@("settings.theme.title" | translate)

- @@ -25,9 +25,9 @@ { Action execute = e.Value switch { - "dark" => Theme.SetDark, - "light" => Theme.SetLight, - _ => Theme.SetAuto + "dark" => ThemeModule.SetDark, + "light" => ThemeModule.SetLight, + _ => ThemeModule.SetAuto }; execute(); } diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/PersonCardView.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/PersonCardView.razor new file mode 100644 index 0000000..7ea0534 --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/PersonCardView.razor @@ -0,0 +1,16 @@ +@inherits CoreRxComponent + +
+

+ @ViewModel.Name +

+
+ +

@(ViewModel.Total.ToString("0.00"))

+
+
+ +@code { + [Parameter] + public EventCallback OnClick { get; set; } +} diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/PersonCardView.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/PersonDetailView.razor similarity index 79% rename from src/TabKeeper.UI.Wasm/Pages/Tabs/PersonCardView.razor rename to src/TabKeeper.UI.Wasm/Pages/Tabs/Components/PersonDetailView.razor index 1b79fcc..0d6eb5f 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Tabs/PersonCardView.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/PersonDetailView.razor @@ -1,6 +1,14 @@ -@inherits CoreRxComponent +@inherits CoreRxComponent -
+
+ + + + +
+ + +

@ViewModel.Name

@@ -20,6 +28,9 @@
@code { + [Parameter, EditorRequired] + public Person Person { get; set; } = null!; + [Parameter] public EventCallback OnEditClicked { get; set; } diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductCardView.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductCardView.razor new file mode 100644 index 0000000..cdad99e --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductCardView.razor @@ -0,0 +1,36 @@ +@inherits CoreRxComponent + +
+
+

+ @ViewModel.Name +

+
+

@ViewModel.Price.ToString("0.00")

+ +
+
+ +
+

@ViewModel.Quantity

+ + +

@ViewModel.Total.ToString("0.00")

+ +
+ +
+ + + +
+
+ +@code { + [Parameter] + public EventCallback OnClick { get; set; } +} diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/ProductCardView.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductDetailView.razor similarity index 93% rename from src/TabKeeper.UI.Wasm/Pages/Tabs/ProductCardView.razor rename to src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductDetailView.razor index 36f22da..308180e 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Tabs/ProductCardView.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductDetailView.razor @@ -1,4 +1,4 @@ -@inherits CoreRxComponent +@inherits CoreRxComponent
@@ -25,7 +25,7 @@
-

@ViewModel.Divisor

+

@ViewModel.Participants

@@ -37,39 +50,49 @@ }
-
- - - Products - - - People - - +
+
+
+ +

@ViewModel.Total.ToString("0.00")

+
-
-
- -

@ViewModel.Products.Items.Sum(x => x.Total).ToString("0.00")

-
- +
+

@ViewModel.People.Items.Sum(x => x.Total).ToString("0.00")

- *@ + + -
+ + + + + @("products" | translate) + + + + + @("people" | translate) + +
@@ -119,106 +142,75 @@ @* Add Product Modal *@ - - -
- -
-
- -
- -
- -
-
- -
- - -
+ + +
+ + +
@* Add Person Modal *@ - - @if (NewPerson.Value is null) { return; } - - - - -
- -
- - -
+ + +
+ + +
@code { - private static ValidatorFn MinLength3 = Validators.MinLength(3); - private static ValidatorFn Min = Validators.MoreThan(0.0M); + private bool loading = true; - private BehaviorSubject SelectedProduct { get; } = new(null); - private BehaviorSubject SelectedPerson { get; } = new(null); - private BehaviorSubject NewPerson { get; } = new(null); + private BehaviorSubject SelectedProduct { get; } = new(null); + private BehaviorSubject SelectedPerson { get; } = new(null); private Modal NewProductModal { get; set; } = null!; - private FormGroup NewProductForm { get; } = new(); - private ProductViewModel NewProductModel { get; set; } = new(); - - private FormGroup NewPersonForm { get; } = new(); + private Modal NewPersonModal { get; set; } = null!; [Parameter] public string Id { get; set; } = string.Empty; - private void OnAddProduct() + private void OnValidProduct(TabProduct product) { - Console.WriteLine($"Count: {NewProductForm.Count}"); - return; - if (NewProductForm.Invalid) return; - - ViewModel.AddProduct(NewProductModel); - NewProductModel = new(); - NewProductModal.Close(); - // NewProduct.OnNext(new()); + ViewModel.AddProduct(new(product)); } - private void OnAddPerson() + private void OnValidPerson(Person person) { - ViewModel.AddPerson(NewPerson.Value!); - NewPerson.OnNext(new()); + ViewModel.AddPerson(new(new TabPerson(person))); } protected override void OnInitialized() { - var tab = storage.GetItem(Id); - if (tab is null) - { - // show not found. - return; - } - - ShellLayout.Context = new() { Title = tab.Name, BackUri = "" }; - ViewModel = new TabViewModel(tab); - ViewModel.WhenPropertyChanged - .Throttle(TimeSpan.FromSeconds(1)) - .Subscribe(_ => + indexedDb.Tabs + .GetAsync(Id) + .ToObservable() + .Subscribe(tab => { - var tab = ViewModel.Tab; - tab.People.Clear(); - tab.People.AddRange(ViewModel.People.Items.Select(x => new PersonTab(new() { Id = x.PersonId, Name = x.Name }) - { - ProductIds = [.. x.ProductIds] - })); - tab.Products.Clear(); - tab.Products.AddRange(ViewModel.Products.Items.Select(x => new Product - { - Id = x.ProductId, - Name = x.Name, - Price = x.Price, - Quantity = x.Quantity - })); - storage.SetItem(tab.Id, tab); + if (tab is null) return; + + ShellLayout.Context = new() { Title = tab.Name, BackUri = "" }; + ViewModel = new TabViewModel(tab); + ViewModel.WhenPropertyChanged + .Throttle(TimeSpan.FromMilliseconds(500)) + .Subscribe(_ => indexedDb.Tabs.PutAsync(ViewModel.Tab)) + .DisposeWith(this); + + loading = false; + Update(); }); } } diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/_imports.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/_imports.razor index 3a63e26..02c23b0 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Tabs/_imports.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/_imports.razor @@ -1,2 +1,4 @@ @using TabKeeper.Tabs -@using TabKeeper.People +@using TabKeeper.Pages.Tabs.Components +@using TabKeeper.Pages.People.Components +@using TabKeeper.People \ No newline at end of file diff --git a/src/TabKeeper.UI.Wasm/assets/_buttons.scss b/src/TabKeeper.UI.Wasm/assets/_buttons.scss index 04d74c7..084b76b 100644 --- a/src/TabKeeper.UI.Wasm/assets/_buttons.scss +++ b/src/TabKeeper.UI.Wasm/assets/_buttons.scss @@ -11,6 +11,10 @@ @apply interactive-bg-secondary; } + .btn-tertiary { + @apply interactive-bg-tertiary; + } + .btn-danger { @apply interactive-bg-error; } diff --git a/src/TabKeeper.UI.Wasm/assets/_icons.scss b/src/TabKeeper.UI.Wasm/assets/_icons.scss index f16b47d..219fa37 100644 --- a/src/TabKeeper.UI.Wasm/assets/_icons.scss +++ b/src/TabKeeper.UI.Wasm/assets/_icons.scss @@ -1,4 +1,7 @@ @layer base { + .icon-2xs { + @apply w-3 h-3; + } .icon-xs { @apply w-4 h-4; } @@ -14,4 +17,10 @@ .icon-xl { @apply w-8 h-8; } + .icon-2xl { + @apply w-9 h-9; + } + .icon-3xl { + @apply w-10 h-10; + } } diff --git a/src/TabKeeper.UI.Wasm/assets/_material-input.scss b/src/TabKeeper.UI.Wasm/assets/_material-input.scss index 2efdba1..eaa1810 100644 --- a/src/TabKeeper.UI.Wasm/assets/_material-input.scss +++ b/src/TabKeeper.UI.Wasm/assets/_material-input.scss @@ -4,7 +4,8 @@ @apply w-full p-2 rounded focus:ring-0; } - .error { + .error, + .validation-message { @apply text-sm text-error; } @@ -12,7 +13,12 @@ @apply relative; input { - @apply rounded p-2 pt-5 border-0 placeholder-transparent bg-surface focus:border-on-surface focus:ring-0; + @apply rounded p-2 pt-5 border border-transparent placeholder-transparent bg-surface focus:border-on-surface focus:ring-0; + + } + + input.invalid { + @apply border-error; } label { diff --git a/src/TabKeeper.UI.Wasm/wwwroot/index.html b/src/TabKeeper.UI.Wasm/wwwroot/index.html index 921a9d1..e79f7e0 100644 --- a/src/TabKeeper.UI.Wasm/wwwroot/index.html +++ b/src/TabKeeper.UI.Wasm/wwwroot/index.html @@ -38,7 +38,7 @@

Loading...

--> - + diff --git a/src/TabKeeper.UI.Wasm/wwwroot/lottie/loading.lottie b/src/TabKeeper.UI.Wasm/wwwroot/lottie/loading.lottie new file mode 100644 index 0000000000000000000000000000000000000000..e233cccee90d36dfb7254f0ef3e79418f01afbf0 GIT binary patch literal 8341 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 literal 0 HcmV?d00001 diff --git a/src/TabKeeper.UI.Wasm/wwwroot/lottie/not-found.lottie b/src/TabKeeper.UI.Wasm/wwwroot/lottie/not-found.lottie new file mode 100644 index 0000000000000000000000000000000000000000..5ddbf9a06407f4e6990e22e08021379440708d97 GIT binary patch literal 10852 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 literal 0 HcmV?d00001 From e132a69a7f1a5550f645851c33f6083d5fef7b7f Mon Sep 17 00:00:00 2001 From: Panos Date: Fri, 9 Aug 2024 19:03:51 +0300 Subject: [PATCH 32/61] update: IndexedDb dependency --- Directory.Packages.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 27f6d6b..62ee625 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -8,7 +8,7 @@ - + From 8dc10bec162b93db64bf089b0cd40ff5e607dbb0 Mon Sep 17 00:00:00 2001 From: Panos Date: Sun, 11 Aug 2024 01:32:44 +0300 Subject: [PATCH 33/61] updates --- Directory.Build.props | 1 + src-modules/Core | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Directory.Build.props b/Directory.Build.props index 4790e05..f1cfb3e 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -7,6 +7,7 @@ true Debug $(NoWarn);CS8509;IDE0039;IDE0130;IDE0290;IDE0060;RZ10012;IDE0052;BL0007; + $(WarningsAsErrors);RZ2012; $(MSBuildThisFileDirectory)artifacts\$([MSBuild]::MakeRelative($(MSBuildThisFileDirectory),$(MSBuildProjectDirectory)).Replace($(MSBuildProjectName), '')) diff --git a/src-modules/Core b/src-modules/Core index ea8ee57..16bd8eb 160000 --- a/src-modules/Core +++ b/src-modules/Core @@ -1 +1 @@ -Subproject commit ea8ee574a54b1b4d64c33f93e00fe3397a536259 +Subproject commit 16bd8eb341cd09e902cfe09b09c1a2b3de8bd9c6 From a0ef5999dd0455caf0e574bb8a5aa33022a52610 Mon Sep 17 00:00:00 2001 From: Panos Date: Sun, 11 Aug 2024 01:34:09 +0300 Subject: [PATCH 34/61] refactor(TabPage): Product Details Modal --- .../Tabs/Components/ProductDetailView.razor | 69 +++++++++++++++++-- .../Pages/Tabs/TabPage.razor | 20 ++---- src/TabKeeper.UI/Tabs/TabPersonViewModel.cs | 6 +- src/TabKeeper.UI/Tabs/TabProductViewModel.cs | 28 ++++++-- src/TabKeeper.UI/Tabs/TabViewModel.cs | 10 +++ src/TabKeeper/Tabs/TabProduct.cs | 2 +- 6 files changed, 103 insertions(+), 32 deletions(-) diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductDetailView.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductDetailView.razor index 308180e..09763ac 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductDetailView.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductDetailView.razor @@ -1,6 +1,45 @@ @inherits CoreRxComponent +@inject TranslateService translate -
+
+
+

+ @ViewModel.Name +

+ +
+ @if (edit) + { + +
+ + +
+ } + else + { + @foreach (var person in TabViewModel.People.Items) + { + var key = person.PersonId.ToString(); + +
+ + +
+ } + } +
+ + +@*
@@ -38,12 +77,30 @@
-
+
*@ @code { - [Parameter] - public EventCallback OnEditClicked { get; set; } + private bool edit; + + [Parameter, EditorRequired] + public TabViewModel TabViewModel { get; set; } = null!; + + private void StartEdit() + { + edit = true; + TriggerUpdate(); + } + + private void CancelEdit() + { + edit = false; + TriggerUpdate(); + } - [Parameter] - public EventCallback OnRemoveClicked { get; set; } + private void ValidSubmit(TabProduct product) + { + ViewModel.Product = product; + edit = false; + TriggerUpdate(); + } } diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor index 5a730f8..e7869b9 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor @@ -102,21 +102,11 @@ @{ var product = SelectedProduct.Value!; } - -
-

@product.Name

- -
- - @foreach (var person in ViewModel.People.Items) - { - var key = person.PersonId.ToString(); -
- - -
- } - + + @* Person Modal *@ diff --git a/src/TabKeeper.UI/Tabs/TabPersonViewModel.cs b/src/TabKeeper.UI/Tabs/TabPersonViewModel.cs index 68cebe8..b7829e0 100644 --- a/src/TabKeeper.UI/Tabs/TabPersonViewModel.cs +++ b/src/TabKeeper.UI/Tabs/TabPersonViewModel.cs @@ -38,7 +38,7 @@ public TabPersonViewModel(TabPerson tab) .AutoRefresh(x => x.Participants) .OnItemAdded(x => tab.ProductIds.Add(x.ProductId)) .OnItemRemoved(x => tab.ProductIds.Remove(x.ProductId)) - .Transform(x => new ProductProxy(x)) + .Transform(x => new ProductProxy(PersonId, x)) .DisposeMany() // Get the latest changes and compute the sum. .QueryWhenChanged(query => query.Items @@ -90,10 +90,10 @@ public override void Dispose() public decimal Total { get; private set; } - public ProductProxy(TabProductViewModel product) + public ProductProxy(Uuid personId, TabProductViewModel product) { this.product = product; - sub = this.product.Participate().Subscribe(total => Total = total); + sub = this.product.Participate(personId).Subscribe(total => Total = total); } public void Dispose() diff --git a/src/TabKeeper.UI/Tabs/TabProductViewModel.cs b/src/TabKeeper.UI/Tabs/TabProductViewModel.cs index 3fbb7f5..181b877 100644 --- a/src/TabKeeper.UI/Tabs/TabProductViewModel.cs +++ b/src/TabKeeper.UI/Tabs/TabProductViewModel.cs @@ -7,8 +7,13 @@ public sealed class TabProductViewModel : RxObject { private TabProduct product; private int participants = 0; + private readonly HashSet participantIds = []; - public TabProduct Product => product; + public TabProduct Product + { + get => product; + set => SetAndRaise(ref product, value); + } public Uuid ProductId => product.Id; @@ -34,6 +39,8 @@ public decimal Quantity public int Participants => participants; + public IEnumerable ParticipantIds => participantIds; + public TabProductViewModel() : this(new() { Id = Uuid.NewUuid() }) { } @@ -43,19 +50,26 @@ public TabProductViewModel(TabProduct product) this.product = product; } - public IObservable Participate() => + public IObservable Participate(Uuid participantId) => Observable.Defer(() => { - Interlocked.Increment(ref participants); - RaisePropertyChanged(nameof(Participants)); - + if (participantIds.Add(participantId)) + { + RaisePropertyChanged(nameof(ParticipantIds)); + Interlocked.Increment(ref participants); + RaisePropertyChanged(nameof(Participants)); + } return this .WhenValueChanged(x => x.Total) .Select(total => Participants > 0 ? total / Participants : 0) .Finally(() => { - Interlocked.Decrement(ref participants); - RaisePropertyChanged(nameof(Participants)); + if (participantIds.Remove(participantId)) + { + RaisePropertyChanged(nameof(ParticipantIds)); + Interlocked.Decrement(ref participants); + RaisePropertyChanged(nameof(Participants)); + } }); }); diff --git a/src/TabKeeper.UI/Tabs/TabViewModel.cs b/src/TabKeeper.UI/Tabs/TabViewModel.cs index 335fdc9..2e4f4d7 100644 --- a/src/TabKeeper.UI/Tabs/TabViewModel.cs +++ b/src/TabKeeper.UI/Tabs/TabViewModel.cs @@ -62,6 +62,11 @@ public TabViewModel(Tab tab) public decimal Total => products.Items.Sum(x => x.Total); + public TabProductViewModel? GetProduct(Uuid productId) + { + return products.Lookup(productId) is { HasValue: true, Value: { } person } ? person : null; + } + public void AddProduct(TabProductViewModel product) { products.AddOrUpdate(product); @@ -72,6 +77,11 @@ public void RemoveProduct(TabProductViewModel product) products.Remove(product); } + public TabPersonViewModel? GetPerson(Uuid personId) + { + return people.Lookup(personId) is { HasValue: true, Value: { } person } ? person : null; + } + public void AddPerson(TabPersonViewModel person) { people.AddOrUpdate(person); diff --git a/src/TabKeeper/Tabs/TabProduct.cs b/src/TabKeeper/Tabs/TabProduct.cs index f205c8f..6682868 100644 --- a/src/TabKeeper/Tabs/TabProduct.cs +++ b/src/TabKeeper/Tabs/TabProduct.cs @@ -30,7 +30,7 @@ public TabProduct(Uuid id) public int GetSnapshotCode() { - return HashCode.Combine(Id, Name); + return HashCode.Combine(Id, Name, Price, Quantity); } public static IValidator Validator { get; } = InlineValidator.For(data => From 4590c28396f006f3b41dfc9e44bbbcd1abc4f0ef Mon Sep 17 00:00:00 2001 From: Panos Date: Sun, 11 Aug 2024 01:51:34 +0300 Subject: [PATCH 35/61] fix(TabProductViewModel): participate method to return correct observable --- src/TabKeeper.UI/Tabs/TabProductViewModel.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/TabKeeper.UI/Tabs/TabProductViewModel.cs b/src/TabKeeper.UI/Tabs/TabProductViewModel.cs index 181b877..b5db608 100644 --- a/src/TabKeeper.UI/Tabs/TabProductViewModel.cs +++ b/src/TabKeeper.UI/Tabs/TabProductViewModel.cs @@ -60,8 +60,9 @@ public IObservable Participate(Uuid participantId) => RaisePropertyChanged(nameof(Participants)); } return this - .WhenValueChanged(x => x.Total) - .Select(total => Participants > 0 ? total / Participants : 0) + .WhenAnyPropertyChanged(nameof(Total), nameof(Participants)) + .Prepend(this) + .Select(static vm => vm!.Participants > 0 ? vm!.Total / vm!.Participants : 0) .Finally(() => { if (participantIds.Remove(participantId)) From fd8a98394d4e78fe88ff0070f6f5ecd996263394 Mon Sep 17 00:00:00 2001 From: Panos Date: Sun, 11 Aug 2024 01:52:41 +0300 Subject: [PATCH 36/61] chore: remove unused code --- .../Tabs/Components/ProductDetailView.razor | 41 ------------------- 1 file changed, 41 deletions(-) diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductDetailView.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductDetailView.razor index 09763ac..8e04642 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductDetailView.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductDetailView.razor @@ -38,47 +38,6 @@ }
- -@*
-
-
- -

@ViewModel.Name

-
-
- -

@ViewModel.Price

-
- -
-
-
- -

@ViewModel.Quantity

-
-
- -

@ViewModel.Total

-
-
- -

@ViewModel.Participants

-
- - - - -
-
*@ - @code { private bool edit; From 0ae1302ea1251dae1ae7c79039cb1f1f28b4918a Mon Sep 17 00:00:00 2001 From: Panos Date: Sun, 11 Aug 2024 02:04:24 +0300 Subject: [PATCH 37/61] refactor(TabPage): Person Details Modal --- .../Tabs/Components/PersonDetailView.razor | 80 ++++++++++++------- .../Pages/Tabs/TabPage.razor | 30 +++---- src/TabKeeper.UI/Tabs/TabPersonViewModel.cs | 9 ++- src/TabKeeper/Tabs/TabPerson.cs | 2 +- 4 files changed, 72 insertions(+), 49 deletions(-) diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/PersonDetailView.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/PersonDetailView.razor index 0d6eb5f..d5b5419 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/PersonDetailView.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/PersonDetailView.razor @@ -1,39 +1,65 @@ @inherits CoreRxComponent - -
- - - - -
- +@inject TranslateService translate
-
-

@ViewModel.Name

- -
-
-
- -

@(ViewModel.Total.ToString("0.00"))

+ @if (edit) + { + +
+ +
- -
+ } + else + { + @foreach (var product in TabViewModel.Products.Items) + { + var key = product.ProductId.ToString(); + +
+ + +
+ } + }
@code { + private bool edit; + [Parameter, EditorRequired] - public Person Person { get; set; } = null!; + public TabViewModel TabViewModel { get; set; } = null!; + + private void StartEdit() + { + edit = true; + TriggerUpdate(); + } - [Parameter] - public EventCallback OnEditClicked { get; set; } + private void CancelEdit() + { + edit = false; + TriggerUpdate(); + } - [Parameter] - public EventCallback OnRemoveClicked { get; set; } -} \ No newline at end of file + private void ValidSubmit(Person person) + { + ViewModel.Person = person; + edit = false; + TriggerUpdate(); + } +} diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor index e7869b9..63f1827 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor @@ -57,7 +57,7 @@ -
+
@@ -73,13 +73,13 @@ *@ - - + +
@@ -114,21 +114,11 @@ @{ var person = SelectedPerson.Value!; } - -
-

@person.Name

- -
- - @foreach (var product in ViewModel.Products.Items) - { - var key = product.ProductId.ToString(); -
- - -
- } - + + @* Add Product Modal *@ diff --git a/src/TabKeeper.UI/Tabs/TabPersonViewModel.cs b/src/TabKeeper.UI/Tabs/TabPersonViewModel.cs index b7829e0..323ff63 100644 --- a/src/TabKeeper.UI/Tabs/TabPersonViewModel.cs +++ b/src/TabKeeper.UI/Tabs/TabPersonViewModel.cs @@ -11,7 +11,14 @@ public sealed class TabPersonViewModel : RxObject public TabPerson Tab => tab; - public Person Person => Tab.Person; + public Person Person + { + get => tab.Person; + set { + Tab.Person = value; + RaisePropertyChanged(nameof(Person)); + } + } public Uuid PersonId => tab.Person.Id; diff --git a/src/TabKeeper/Tabs/TabPerson.cs b/src/TabKeeper/Tabs/TabPerson.cs index d22fee7..8060ecd 100644 --- a/src/TabKeeper/Tabs/TabPerson.cs +++ b/src/TabKeeper/Tabs/TabPerson.cs @@ -13,7 +13,7 @@ public sealed record TabPerson : ISnapshotCode, IValid /// /// The person this tab belongs to. /// - public Person Person { get; } + public Person Person { get; set; } /// /// A list of product ids that this person shares with other people. From 05b2ad29fc8060ec7364b155eac7b6bf4b729a99 Mon Sep 17 00:00:00 2001 From: Panos Date: Sat, 17 Aug 2024 15:09:31 +0300 Subject: [PATCH 38/61] update: core submodule --- src-modules/Core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-modules/Core b/src-modules/Core index 16bd8eb..3965ae0 160000 --- a/src-modules/Core +++ b/src-modules/Core @@ -1 +1 @@ -Subproject commit 16bd8eb341cd09e902cfe09b09c1a2b3de8bd9c6 +Subproject commit 3965ae08e0ed5f1acf92ef474c1db67250a3a8da From b2293302bfaae2260feaf5e90bdf8b4a6076f4f5 Mon Sep 17 00:00:00 2001 From: Panos Date: Sat, 17 Aug 2024 15:11:49 +0300 Subject: [PATCH 39/61] chore: update dependencies --- Directory.Packages.props | 14 +++++++------- src/TabKeeper.UI.Wasm/package-lock.json | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 62ee625..2f1ae9a 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,33 +7,33 @@ - - + + + + - - - + - + @@ -41,7 +41,7 @@ - + \ No newline at end of file diff --git a/src/TabKeeper.UI.Wasm/package-lock.json b/src/TabKeeper.UI.Wasm/package-lock.json index 60546f7..be6938a 100644 --- a/src/TabKeeper.UI.Wasm/package-lock.json +++ b/src/TabKeeper.UI.Wasm/package-lock.json @@ -1665,9 +1665,9 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.9", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.9.tgz", - "integrity": "sha512-1SEOvRr6sSdV5IDf9iC+NU4dhwdqzF4zKKq3sAbasUWHEM6lsMhX+eNN5gkPx1BvLFEnZQEUFbXnGj8Qlp83Pg==", + "version": "3.4.10", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.10.tgz", + "integrity": "sha512-KWZkVPm7yJRhdu4SRSl9d4AK2wM3a50UsvgHZO7xY77NQr2V+fIrEuoDGQcbvswWvFGbS2f6e+jC/6WJm1Dl0w==", "dev": true, "license": "MIT", "peer": true, From a3fb6d22331b83d08eb8911f8905aa2480aaafc0 Mon Sep 17 00:00:00 2001 From: Panos Date: Sat, 17 Aug 2024 17:00:43 +0300 Subject: [PATCH 40/61] minor UI changes --- .../Pages/Tabs/Components/PersonCardView.razor | 4 ++-- .../Pages/Tabs/Components/ProductCardView.razor | 4 ++-- src/TabKeeper.UI.Wasm/assets/_skeleton.scss | 0 src/TabKeeper.UI.Wasm/assets/app.scss | 9 +++++---- 4 files changed, 9 insertions(+), 8 deletions(-) create mode 100644 src/TabKeeper.UI.Wasm/assets/_skeleton.scss diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/PersonCardView.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/PersonCardView.razor index 7ea0534..480c84f 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/PersonCardView.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/PersonCardView.razor @@ -1,9 +1,9 @@ @inherits CoreRxComponent
-

+

@ViewModel.Name -

+

@(ViewModel.Total.ToString("0.00"))

diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductCardView.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductCardView.razor index cdad99e..a04096e 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductCardView.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductCardView.razor @@ -2,9 +2,9 @@
-

+

@ViewModel.Name -

+

@ViewModel.Price.ToString("0.00")

diff --git a/src/TabKeeper.UI.Wasm/assets/_skeleton.scss b/src/TabKeeper.UI.Wasm/assets/_skeleton.scss new file mode 100644 index 0000000..e69de29 diff --git a/src/TabKeeper.UI.Wasm/assets/app.scss b/src/TabKeeper.UI.Wasm/assets/app.scss index 80abb63..069163b 100644 --- a/src/TabKeeper.UI.Wasm/assets/app.scss +++ b/src/TabKeeper.UI.Wasm/assets/app.scss @@ -2,6 +2,7 @@ @import "./_cards.scss"; @import "./_icons.scss"; @import "./_material-input.scss"; +@import "./_skeleton.scss"; @tailwind base; @tailwind components; @@ -19,19 +20,19 @@ } h1 { - @apply text-2xl font-bold mb-4; + @apply text-2xl font-bold; } h2 { - @apply text-xl mb-3; + @apply text-xl font-medium; } h3 { - @apply text-lg font-medium mb-2; + @apply text-lg font-medium; } h4 { - @apply text-base font-normal mb-1; + @apply text-base font-medium; } p { From 2f3e92b286460db62b153521c2212f511f9ae60f Mon Sep 17 00:00:00 2001 From: Panos Date: Mon, 14 Oct 2024 19:45:24 +0300 Subject: [PATCH 41/61] refactor: root project files - refactor: Directory.Build.props to use path of project inside artifacts - refactor: TabKeepr.sln to also use TabKeeper.slnx --- Directory.Build.props | 6 +++++- TabKeeper.sln | 2 +- TabKeeper.slnx | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 TabKeeper.slnx diff --git a/Directory.Build.props b/Directory.Build.props index f1cfb3e..da8742f 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -9,7 +9,11 @@ $(NoWarn);CS8509;IDE0039;IDE0130;IDE0290;IDE0060;RZ10012;IDE0052;BL0007; $(WarningsAsErrors);RZ2012; - $(MSBuildThisFileDirectory)artifacts\$([MSBuild]::MakeRelative($(MSBuildThisFileDirectory),$(MSBuildProjectDirectory)).Replace($(MSBuildProjectName), '')) + $([System.IO.Path]::Combine( + $(MSBuildThisFileDirectory), + "artifacts", + $([MSBuild]::MakeRelative($(MSBuildThisFileDirectory),$(MSBuildProjectDirectory)).Replace("$(MSBuildProjectName)", '').TrimEnd('/')) + )) true true diff --git a/TabKeeper.sln b/TabKeeper.sln index b56e044..d04a31b 100644 --- a/TabKeeper.sln +++ b/TabKeeper.sln @@ -1,5 +1,5 @@ Microsoft Visual Studio Solution File, Format Version 12.00 -# 17 +# Visual Studio Version 17 VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{1FE5EE5F-70AA-4824-B306-304ADBF3A312}" diff --git a/TabKeeper.slnx b/TabKeeper.slnx new file mode 100644 index 0000000..f727ef1 --- /dev/null +++ b/TabKeeper.slnx @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From dfbf9c439800bef873ff1f0aafa4237082a1dd00 Mon Sep 17 00:00:00 2001 From: Panos Date: Sun, 3 Nov 2024 17:43:04 +0200 Subject: [PATCH 42/61] fix: Dropdown colors --- src/TabKeeper.UI.Wasm/Components/DropdownContent.razor | 2 +- src/TabKeeper.UI.Wasm/Components/DropdownItem.razor | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/TabKeeper.UI.Wasm/Components/DropdownContent.razor b/src/TabKeeper.UI.Wasm/Components/DropdownContent.razor index abadac0..faa5baf 100644 --- a/src/TabKeeper.UI.Wasm/Components/DropdownContent.razor +++ b/src/TabKeeper.UI.Wasm/Components/DropdownContent.razor @@ -8,7 +8,7 @@ LeaveFrom="transform opacity-100 scale-100" LeaveTo="transform opacity-0 scale-95" Context="transition"> - + @ChildContent diff --git a/src/TabKeeper.UI.Wasm/Components/DropdownItem.razor b/src/TabKeeper.UI.Wasm/Components/DropdownItem.razor index 643489b..8fd0eac 100644 --- a/src/TabKeeper.UI.Wasm/Components/DropdownItem.razor +++ b/src/TabKeeper.UI.Wasm/Components/DropdownItem.razor @@ -2,7 +2,7 @@ From ff31502eba09536d9b98cb6ea0162f8167e46a2c Mon Sep 17 00:00:00 2001 From: Panos Date: Sun, 3 Nov 2024 17:53:24 +0200 Subject: [PATCH 43/61] refactor(home): remove buttons and make list item an a tag --- src/TabKeeper.UI.Wasm/Pages/HomePage.razor | 30 +++++++------------ .../Pages/Tabs/TabPage.razor | 2 +- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/src/TabKeeper.UI.Wasm/Pages/HomePage.razor b/src/TabKeeper.UI.Wasm/Pages/HomePage.razor index e08914e..e0903ca 100644 --- a/src/TabKeeper.UI.Wasm/Pages/HomePage.razor +++ b/src/TabKeeper.UI.Wasm/Pages/HomePage.razor @@ -9,34 +9,26 @@
@foreach(var entry in Entries.Items.OrderBy(x => x.Date)) { - + }
- @* Options *@ -
- -
+ @* Bar *@ +
- + - + @("settings.title" | translate) + +
@@ -80,8 +72,6 @@ loading = false; }) .Subscribe(_ => Update()); - - // NewTabEntryName.Subscribe(_ => Update()); } private record TabEntry(Uuid Id, string Name, DateOnly? Date); diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor index 63f1827..cd12a5d 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor @@ -1,4 +1,4 @@ -@page "/tabs/{Id}" +@page "/tab/{Id}" @inherits CoreRxComponent @inject IndexedDb indexedDb @inject TranslateService translate From a6a86d5f23e86bf26dcd1b99392f7507ea0347d9 Mon Sep 17 00:00:00 2001 From: Panos Date: Sun, 3 Nov 2024 17:56:23 +0200 Subject: [PATCH 44/61] update dependencies --- Directory.Packages.props | 6 +++--- TabKeeper.slnx | 5 +++++ src-modules/Core | 2 +- src/TabKeeper.UI.Wasm/package-lock.json | 9 +++++---- src/TabKeeper.UI.Wasm/package.json | 2 ++ 5 files changed, 16 insertions(+), 8 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 2f1ae9a..452b3d9 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -15,8 +15,8 @@ - - + + @@ -41,7 +41,7 @@ - + \ No newline at end of file diff --git a/TabKeeper.slnx b/TabKeeper.slnx index f727ef1..b6e0f9e 100644 --- a/TabKeeper.slnx +++ b/TabKeeper.slnx @@ -29,4 +29,9 @@ + + + + + diff --git a/src-modules/Core b/src-modules/Core index 3965ae0..3426cef 160000 --- a/src-modules/Core +++ b/src-modules/Core @@ -1 +1 @@ -Subproject commit 3965ae08e0ed5f1acf92ef474c1db67250a3a8da +Subproject commit 3426cef0e366329fe1d95722eafd173239c91a18 diff --git a/src/TabKeeper.UI.Wasm/package-lock.json b/src/TabKeeper.UI.Wasm/package-lock.json index be6938a..f12f87f 100644 --- a/src/TabKeeper.UI.Wasm/package-lock.json +++ b/src/TabKeeper.UI.Wasm/package-lock.json @@ -1,9 +1,10 @@ { - "name": "TabKeeper.UI.Wasm", + "name": "tabkeeper", "lockfileVersion": 3, "requires": true, "packages": { "": { + "name": "tabkeeper", "devDependencies": { "@tailwindcss/forms": "^0.5.7", "@tailwindcss/nesting": "^0.0.0-insiders.565cd3e", @@ -1665,9 +1666,9 @@ } }, "node_modules/tailwindcss": { - "version": "3.4.10", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.10.tgz", - "integrity": "sha512-KWZkVPm7yJRhdu4SRSl9d4AK2wM3a50UsvgHZO7xY77NQr2V+fIrEuoDGQcbvswWvFGbS2f6e+jC/6WJm1Dl0w==", + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", + "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", "dev": true, "license": "MIT", "peer": true, diff --git a/src/TabKeeper.UI.Wasm/package.json b/src/TabKeeper.UI.Wasm/package.json index 9b1eb31..7808af4 100644 --- a/src/TabKeeper.UI.Wasm/package.json +++ b/src/TabKeeper.UI.Wasm/package.json @@ -1,4 +1,6 @@ { + "name": "tabkeeper", + "author": "Panagiotis Athanasiou", "devDependencies": { "@tailwindcss/forms": "^0.5.7", "@tailwindcss/nesting": "^0.0.0-insiders.565cd3e", From ebb26b026b4d151d76498eb6dfda4c28a358b0bc Mon Sep 17 00:00:00 2001 From: Panos Date: Sun, 3 Nov 2024 17:56:43 +0200 Subject: [PATCH 45/61] refactor: tailwind config --- src/TabKeeper.UI.Wasm/tailwind.config.js | 15 +++++++++------ src/TabKeeper.UI.Wasm/tailwind.extension.json | 10 +++++++--- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/TabKeeper.UI.Wasm/tailwind.config.js b/src/TabKeeper.UI.Wasm/tailwind.config.js index ff742b3..0d0e052 100644 --- a/src/TabKeeper.UI.Wasm/tailwind.config.js +++ b/src/TabKeeper.UI.Wasm/tailwind.config.js @@ -19,14 +19,17 @@ module.exports = withMaterialColors( } }, { - primary: "#0035BE", - secondary: "#005A6F", - tertiary: "#054C6C", - error: "#D4352F", - neutral: "#919094" + primary: "#E6E6FA", + //secondary: "#005A6F", + //tertiary: "#054C6C", + //error: "#D4352F", + //neutral: "#919094" }, { - scheme: "content", + /* one of 'content', 'expressive', 'fidelity', 'monochrome', 'neutral', 'tonalSpot' or 'vibrant' */ + scheme: "expressive", + // contrast is optional and ranges from -1 (less contrast) to 1 (more contrast). + contrast: 0, extend: true } ); diff --git a/src/TabKeeper.UI.Wasm/tailwind.extension.json b/src/TabKeeper.UI.Wasm/tailwind.extension.json index 77cfe3c..d4650e5 100644 --- a/src/TabKeeper.UI.Wasm/tailwind.extension.json +++ b/src/TabKeeper.UI.Wasm/tailwind.extension.json @@ -1,6 +1,10 @@ { "ConfigurationFile": "tailwind.config.js", - "InputCssFile": "./assets/app.scss", - "OutputCssFile": "./wwwroot/css/app.min.css", + "BuildFiles": [ + { + "Input": "assets\\app.scss", + "Output": "wwwroot\\css\\app.min.css" + } + ], "UseCli": false -} +} \ No newline at end of file From edd1031925db671bff361120b05c56b2a8b580ea Mon Sep 17 00:00:00 2001 From: Panos Date: Sun, 3 Nov 2024 17:56:59 +0200 Subject: [PATCH 46/61] fix: lang localstorage item --- src/TabKeeper.UI.Wasm/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/TabKeeper.UI.Wasm/Program.cs b/src/TabKeeper.UI.Wasm/Program.cs index c28c2ed..54ded7e 100644 --- a/src/TabKeeper.UI.Wasm/Program.cs +++ b/src/TabKeeper.UI.Wasm/Program.cs @@ -62,6 +62,6 @@ static Task InitializeLang(WebAssemblyHost app) { lang = "en"; } - localStorage.SetItem("lang", lang); + localStorage.SetItemAsString("lang", lang); return translate.SetCurrentLang(lang).ToTask(); } From 339d1cab0801b47cd131ac5d940fd68db5ead5ca Mon Sep 17 00:00:00 2001 From: Panos Date: Sun, 3 Nov 2024 17:57:18 +0200 Subject: [PATCH 47/61] update translations --- src/TabKeeper.UI.Wasm/wwwroot/i18n/el.json | 5 +++++ src/TabKeeper.UI.Wasm/wwwroot/i18n/en.json | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/src/TabKeeper.UI.Wasm/wwwroot/i18n/el.json b/src/TabKeeper.UI.Wasm/wwwroot/i18n/el.json index db08280..4247e33 100644 --- a/src/TabKeeper.UI.Wasm/wwwroot/i18n/el.json +++ b/src/TabKeeper.UI.Wasm/wwwroot/i18n/el.json @@ -13,6 +13,11 @@ "auto": "Αυτόματο", "dark": "Σκοτεινό", "light": "Φωτεινό" + }, + "lang": { + "title": "Γλώσσα", + "en": "English", + "el": "Ελληνικά" } } } diff --git a/src/TabKeeper.UI.Wasm/wwwroot/i18n/en.json b/src/TabKeeper.UI.Wasm/wwwroot/i18n/en.json index 31cdb0a..89c0f75 100644 --- a/src/TabKeeper.UI.Wasm/wwwroot/i18n/en.json +++ b/src/TabKeeper.UI.Wasm/wwwroot/i18n/en.json @@ -13,6 +13,11 @@ "auto": "Auto", "dark": "Dark", "light": "Light" + }, + "lang": { + "title": "Language", + "en": "English", + "el": "Ελληνικά" } } } From 26275e816f91b4ee6e0578c483b086b39192e367 Mon Sep 17 00:00:00 2001 From: Panos Date: Sun, 3 Nov 2024 17:58:31 +0200 Subject: [PATCH 48/61] refactor(settings): Implement new preferences API --- .../LocalStorageConfigurationProvider.cs | 46 ++++++++++++++++++ .../PreferenceCollectionComponentBase.cs | 33 +++++++++++++ .../Abstract/PreferenceComponentBase.cs | 24 ++++++++++ .../Abstract/PreferenceValueComponentBase.cs | 16 +++++++ .../EditTextPreferenceComponent.razor | 1 + .../ListBoxPreferenceComponent.razor | 23 +++++++++ .../PreferenceCategoryComponent.razor | 21 +++++++++ .../SwitchPreferenceComponent.razor | 1 + .../Pages/PreferenceScreenPage.razor | 25 ++++++++++ .../Components/Preferences/_imports.razor | 1 + .../Pages/SettingsPage.razor | 47 ++++++++++--------- src/TabKeeper.UI/Preferences.cs | 37 +++++++++++++++ 12 files changed, 252 insertions(+), 23 deletions(-) create mode 100644 src/TabKeeper.UI.Wasm/Common/LocalStorageConfigurationProvider.cs create mode 100644 src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceCollectionComponentBase.cs create mode 100644 src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceComponentBase.cs create mode 100644 src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceValueComponentBase.cs create mode 100644 src/TabKeeper.UI.Wasm/Components/Preferences/Components/EditTextPreferenceComponent.razor create mode 100644 src/TabKeeper.UI.Wasm/Components/Preferences/Components/ListBoxPreferenceComponent.razor create mode 100644 src/TabKeeper.UI.Wasm/Components/Preferences/Components/PreferenceCategoryComponent.razor create mode 100644 src/TabKeeper.UI.Wasm/Components/Preferences/Components/SwitchPreferenceComponent.razor create mode 100644 src/TabKeeper.UI.Wasm/Components/Preferences/Pages/PreferenceScreenPage.razor create mode 100644 src/TabKeeper.UI.Wasm/Components/Preferences/_imports.razor create mode 100644 src/TabKeeper.UI/Preferences.cs diff --git a/src/TabKeeper.UI.Wasm/Common/LocalStorageConfigurationProvider.cs b/src/TabKeeper.UI.Wasm/Common/LocalStorageConfigurationProvider.cs new file mode 100644 index 0000000..402bd5d --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Common/LocalStorageConfigurationProvider.cs @@ -0,0 +1,46 @@ +using Blazored.LocalStorage; + +namespace TabKeeper.Common; + +public sealed class LocalStorageConfigurationProvider : ConfigurationProvider, IConfigurationSource +{ + private readonly ISyncLocalStorageService localStorage; + + public LocalStorageConfigurationProvider(ISyncLocalStorageService localStorage) + { + this.localStorage = localStorage; + } + + public override bool TryGet(string key, out string? value) + { + if (base.TryGet(key, out value)) + return true; + + value = localStorage.GetItemAsString(key); + if (value is null) + return false; + + base.Set(key, value); + return true; + } + + public override void Set(string key, string? value) + { + localStorage.SetItemAsString(key, value ?? string.Empty); + base.Set(key, value); + } + + public override void Load() + { + foreach (var key in localStorage.Keys()) + { + base.Set(key, localStorage.GetItemAsString(key)); + } + OnReload(); + } + + public IConfigurationProvider Build(IConfigurationBuilder builder) + { + return this; + } +} diff --git a/src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceCollectionComponentBase.cs b/src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceCollectionComponentBase.cs new file mode 100644 index 0000000..9dddc7d --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceCollectionComponentBase.cs @@ -0,0 +1,33 @@ +using Core.Preferences; +using Core.Preferences.Abstract; +using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components.Rendering; +using TabKeeper.Components.Preferences.Components; + +namespace TabKeeper.Components.Preferences.Abstract; + +public abstract class PreferenceCollectionComponentBase : PreferenceComponentBase + where TPreferenceCollection : PreferenceCollectionBase +{ + protected RenderFragment RenderPreference(PreferenceBase preference) => builder => + { + _ = preference switch + { + PreferenceCategory categoryPreference => Render(ref builder, ref categoryPreference), + EditTextPreference editTextPreference => Render(ref builder, ref editTextPreference), + SwitchPreference switchPreference => Render(ref builder, ref switchPreference), + ListBoxPreference listBoxPreference => Render(ref builder, ref listBoxPreference), + _ => Nothing.Value + }; + }; + + private static Nothing Render(ref RenderTreeBuilder builder, ref TPreference preference) + where TComponent : notnull, PreferenceComponentBase + where TPreference : PreferenceBase + { + builder.OpenComponent(0); + builder.AddComponentParameter(1, nameof(Preference), preference); + builder.CloseComponent(); + return Nothing.Value; + } +} diff --git a/src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceComponentBase.cs b/src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceComponentBase.cs new file mode 100644 index 0000000..81f178b --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceComponentBase.cs @@ -0,0 +1,24 @@ +using Core.Preferences; +using Core.Preferences.Abstract; +using Microsoft.AspNetCore.Components; + +namespace TabKeeper.Components.Preferences.Abstract; + +public abstract class PreferenceComponentBase : ComponentBase + where TPreference : PreferenceBase +{ + [CascadingParameter] + public PreferenceScreen? Root { get; set; } + + [Parameter, EditorRequired] + public TPreference Preference { get; set; } = null!; + + protected object? GetIcon() + => Root?.IconTransformer is { } transformer ? transformer(Preference.Icon) : Preference.Icon; + + protected string GetTitle() + => Root?.TitleTransformer is { } transformer ? transformer(Preference.Title) : Preference.Title; + + protected string? GetDescription() + => Root?.DescriptionTransformer is { } transformer ? transformer(Preference.Description) : Preference.Description; +} diff --git a/src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceValueComponentBase.cs b/src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceValueComponentBase.cs new file mode 100644 index 0000000..a68d404 --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceValueComponentBase.cs @@ -0,0 +1,16 @@ +using Core.Preferences.Abstract; + +namespace TabKeeper.Components.Preferences.Abstract; + +public abstract class PreferenceValueComponentBase : PreferenceComponentBase + where TPreference : PreferenceValueBase +{ + protected string GetValueSummary() + => Root?.SummaryTransformer is { } transformer ? transformer(Preference.ValueSummary) : Preference.ValueSummary; +} + +public abstract class PreferenceValueComponentBase : PreferenceValueComponentBase + where TPreference : PreferenceValueBase + where TValue : IParsable, new() +{ +} diff --git a/src/TabKeeper.UI.Wasm/Components/Preferences/Components/EditTextPreferenceComponent.razor b/src/TabKeeper.UI.Wasm/Components/Preferences/Components/EditTextPreferenceComponent.razor new file mode 100644 index 0000000..9657624 --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Components/Preferences/Components/EditTextPreferenceComponent.razor @@ -0,0 +1 @@ +@inherits Abstract.PreferenceValueComponentBase diff --git a/src/TabKeeper.UI.Wasm/Components/Preferences/Components/ListBoxPreferenceComponent.razor b/src/TabKeeper.UI.Wasm/Components/Preferences/Components/ListBoxPreferenceComponent.razor new file mode 100644 index 0000000..7ca37a1 --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Components/Preferences/Components/ListBoxPreferenceComponent.razor @@ -0,0 +1,23 @@ +@inherits Abstract.PreferenceValueComponentBase + +
+
+ +
+ +
+ +@code { + public void OnChange(ChangeEventArgs e) + { + if (e.Value is string arg) + { + Preference.Value = arg; + } + } +} diff --git a/src/TabKeeper.UI.Wasm/Components/Preferences/Components/PreferenceCategoryComponent.razor b/src/TabKeeper.UI.Wasm/Components/Preferences/Components/PreferenceCategoryComponent.razor new file mode 100644 index 0000000..72d47a4 --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Components/Preferences/Components/PreferenceCategoryComponent.razor @@ -0,0 +1,21 @@ +@inherits Abstract.PreferenceCollectionComponentBase + +
+
+
+ @if (GetIcon() is { } icon) + { + + } +

@GetTitle()

+
+ @if (GetDescription() is { } desc) + { +

@desc

+ } +
+ @foreach (var preference in Preference) + { + @RenderPreference(preference) + } +
diff --git a/src/TabKeeper.UI.Wasm/Components/Preferences/Components/SwitchPreferenceComponent.razor b/src/TabKeeper.UI.Wasm/Components/Preferences/Components/SwitchPreferenceComponent.razor new file mode 100644 index 0000000..5eb13d3 --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Components/Preferences/Components/SwitchPreferenceComponent.razor @@ -0,0 +1 @@ +@inherits Abstract.PreferenceValueComponentBase diff --git a/src/TabKeeper.UI.Wasm/Components/Preferences/Pages/PreferenceScreenPage.razor b/src/TabKeeper.UI.Wasm/Components/Preferences/Pages/PreferenceScreenPage.razor new file mode 100644 index 0000000..4efe411 --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Components/Preferences/Pages/PreferenceScreenPage.razor @@ -0,0 +1,25 @@ +@using Core.Preferences.Abstract +@inherits Abstract.PreferenceCollectionComponentBase + + + @foreach (var preference in Screen) + { + @RenderPreference(preference) + } + + +@code { + private new PreferenceScreen? Preference { get; set; } + + [Parameter, EditorRequired] + public PreferenceScreen Screen + { + get => base.Preference; + set => base.Preference = value; + } + + protected override void OnParametersSet() + { + Root = Screen; + } +} diff --git a/src/TabKeeper.UI.Wasm/Components/Preferences/_imports.razor b/src/TabKeeper.UI.Wasm/Components/Preferences/_imports.razor new file mode 100644 index 0000000..d381823 --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Components/Preferences/_imports.razor @@ -0,0 +1 @@ +@using Core.Preferences; diff --git a/src/TabKeeper.UI.Wasm/Pages/SettingsPage.razor b/src/TabKeeper.UI.Wasm/Pages/SettingsPage.razor index dbe8ebc..37f54e3 100644 --- a/src/TabKeeper.UI.Wasm/Pages/SettingsPage.razor +++ b/src/TabKeeper.UI.Wasm/Pages/SettingsPage.razor @@ -1,34 +1,35 @@ -@page "/settings" +@using Core.Preferences; +@using Microsoft.Extensions.Configuration.Memory +@using TabKeeper.Components.Preferences.Pages; + +@page "/settings" @inherits CoreComponent @inject TranslateService translate +@inject ISyncLocalStorageService localStorage -
-
-

@("settings.theme.title" | translate)

-
- -
-
-
+ @code { + public static ConfigurationManager Configuration { get; } = new(); + protected override void OnInitialized() { + if (Configuration.Sources.Count is 1) + { + Configuration.Sources.Add(new LocalStorageConfigurationProvider(localStorage)); + } + ShellLayout.Context = new() { Title = "settings.title" | translate }; - } - public void OnThemeChange(ChangeEventArgs e) - { - Action execute = e.Value switch - { - "dark" => ThemeModule.SetDark, - "light" => ThemeModule.SetLight, - _ => ThemeModule.SetAuto - }; - execute(); + Preferences.Screen.TitleTransformer = v => v | translate; + Preferences.Screen.DescriptionTransformer = v => v is {} ? v | translate : v; + Preferences.Screen.SummaryTransformer = v => v | translate; + + Preferences.Screen + .WhenValuePreferenceChanged(Preferences.Theme) + .Throttle(TimeSpan.FromMilliseconds(100)) + .Subscribe(p => ThemeModule.UpdateDom()); + + Preferences.Screen.Initialize(Configuration); } } diff --git a/src/TabKeeper.UI/Preferences.cs b/src/TabKeeper.UI/Preferences.cs new file mode 100644 index 0000000..37d71ab --- /dev/null +++ b/src/TabKeeper.UI/Preferences.cs @@ -0,0 +1,37 @@ +using Core.Preferences; +using Core.Preferences.Builders; + +namespace TabKeeper; + +public static class Preferences +{ + public const string Language = "lang"; + + public const string Theme = "theme"; + + public static PreferenceScreen Screen { get; } = PreferenceScreenBuilder + .CreateEmpty() + .AddCategory(b => b + .WithTitle("settings.lang.title") + .AddListBox(new() + { + Key = Preferences.Language, + Title = "settings.lang.title", + AllowedValues = ["en", "el"], + DefaultValue = "en", + SummaryProvider = value => $"settings.lang.{value}", + }) + ) + .AddCategory(b => b + .WithTitle("settings.theme.title") + .AddListBox(new() + { + Key = Preferences.Theme, + Title = "settings.theme.title", + AllowedValues = ["auto", "dark", "light"], + DefaultValue = "auto", + SummaryProvider = value => $"settings.theme.{value}", + }) + ) + .Build(); +} From 2ef8972ea5fe20aa98c860a7b9c67b88088f577d Mon Sep 17 00:00:00 2001 From: Panos Date: Sun, 3 Nov 2024 17:59:19 +0200 Subject: [PATCH 49/61] refactor: launchSettings.json --- src/TabKeeper.UI.Wasm/Properties/launchSettings.json | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/TabKeeper.UI.Wasm/Properties/launchSettings.json b/src/TabKeeper.UI.Wasm/Properties/launchSettings.json index 85e4afa..f262aa1 100644 --- a/src/TabKeeper.UI.Wasm/Properties/launchSettings.json +++ b/src/TabKeeper.UI.Wasm/Properties/launchSettings.json @@ -1,14 +1,11 @@ { - "$schema": "http://json.schemastore.org/launchsettings.json", "profiles": { - "run": { + "TabKeeper.UI.Wasm": { "commandName": "Project", - "launchBrowser": false, - "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", - "applicationUrl": "https://localhost:5001", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" - } + }, + "applicationUrl": "https://localhost:5001" } } -} +} \ No newline at end of file From e574f74ce31f9273b03c7c28950b84cf9a7c570b Mon Sep 17 00:00:00 2001 From: Panos Date: Tue, 5 Nov 2024 19:24:35 +0200 Subject: [PATCH 50/61] refactor(workflow): to use global.json file instead of hardcoded value --- .github/workflows/_ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/_ci.yaml b/.github/workflows/_ci.yaml index 23b5442..c2ce6bd 100644 --- a/.github/workflows/_ci.yaml +++ b/.github/workflows/_ci.yaml @@ -23,7 +23,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4.0.0 - with: { dotnet-version: 8.0.x } + with: { global-json-file: ./global.json } - name: Setup wasm-tools run: dotnet workload install wasm-tools From 569018e0456e12f51c87df13009c0313440baac1 Mon Sep 17 00:00:00 2001 From: Panos Date: Tue, 5 Nov 2024 19:25:45 +0200 Subject: [PATCH 51/61] update(workflows): to use latest dotnet setup action --- .github/workflows/_ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/_ci.yaml b/.github/workflows/_ci.yaml index c2ce6bd..ea09611 100644 --- a/.github/workflows/_ci.yaml +++ b/.github/workflows/_ci.yaml @@ -22,7 +22,7 @@ jobs: submodules: 'true' - name: Setup .NET - uses: actions/setup-dotnet@v4.0.0 + uses: actions/setup-dotnet@v4 with: { global-json-file: ./global.json } - name: Setup wasm-tools From 6f6bfa12204738733f21df1137d0ced042e9debf Mon Sep 17 00:00:00 2001 From: Panos Date: Wed, 6 Nov 2024 19:15:54 +0200 Subject: [PATCH 52/61] fix(global.json): version --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 2ddda36..0d68aa4 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.0", + "version": "8.0.110", "rollForward": "latestMinor", "allowPrerelease": false } From 31bc238b646573b06ac0dd988bdb3b129fedea75 Mon Sep 17 00:00:00 2001 From: Panos Date: Thu, 7 Nov 2024 21:00:28 +0200 Subject: [PATCH 53/61] refactor: pipeline with global.json version --- .github/workflows/_ci.yaml | 8 +++++++- global.json | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/_ci.yaml b/.github/workflows/_ci.yaml index ea09611..52008ae 100644 --- a/.github/workflows/_ci.yaml +++ b/.github/workflows/_ci.yaml @@ -21,9 +21,15 @@ jobs: fetch-depth: 0 submodules: 'true' + - name: Read .NET Version + shell: pwsh + run: | + $version = $(Get-Content .\global.json -Raw | ConvertFrom-Json).sdk.version.Substring(0,4) + "x" + echo "NET_SDK_VERSION=$version" | Out-File -FilePath $Env:GITHUB_ENV -Encoding utf8 -Append + - name: Setup .NET uses: actions/setup-dotnet@v4 - with: { global-json-file: ./global.json } + with: { dotnet-version: $NET_SDK_VERSION } - name: Setup wasm-tools run: dotnet workload install wasm-tools diff --git a/global.json b/global.json index 0d68aa4..2ddda36 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.110", + "version": "8.0.0", "rollForward": "latestMinor", "allowPrerelease": false } From debc77f796b18e1637674cf543946df628aea63d Mon Sep 17 00:00:00 2001 From: Panos Date: Thu, 7 Nov 2024 21:04:49 +0200 Subject: [PATCH 54/61] fix(ci) --- .github/workflows/_ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/_ci.yaml b/.github/workflows/_ci.yaml index 52008ae..778cbee 100644 --- a/.github/workflows/_ci.yaml +++ b/.github/workflows/_ci.yaml @@ -29,7 +29,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 - with: { dotnet-version: $NET_SDK_VERSION } + with: { dotnet-version: "${{ $NET_SDK_VERSION }}" } - name: Setup wasm-tools run: dotnet workload install wasm-tools From e1871ea6896e2bf3db60d3abf5b0ffda02777f19 Mon Sep 17 00:00:00 2001 From: Panos Date: Thu, 7 Nov 2024 21:05:48 +0200 Subject: [PATCH 55/61] fix(ci) --- .github/workflows/_ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/_ci.yaml b/.github/workflows/_ci.yaml index 778cbee..6e005a3 100644 --- a/.github/workflows/_ci.yaml +++ b/.github/workflows/_ci.yaml @@ -29,7 +29,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 - with: { dotnet-version: "${{ $NET_SDK_VERSION }}" } + with: { dotnet-version: "${{ env.NET_SDK_VERSION }}" } - name: Setup wasm-tools run: dotnet workload install wasm-tools From 73e723ad7111e5f5980ce48a01dfdbcba8935bc7 Mon Sep 17 00:00:00 2001 From: Panos Date: Sat, 9 Nov 2024 14:40:02 +0200 Subject: [PATCH 56/61] update dependencies --- Directory.Packages.props | 8 ++++---- src-modules/Core | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index 452b3d9..93517af 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -31,17 +31,17 @@ - - + + - + - + \ No newline at end of file diff --git a/src-modules/Core b/src-modules/Core index 3426cef..5b7fc57 160000 --- a/src-modules/Core +++ b/src-modules/Core @@ -1 +1 @@ -Subproject commit 3426cef0e366329fe1d95722eafd173239c91a18 +Subproject commit 5b7fc57203098985d9a9911f74573132f271226b From f778a6ccf8639c43c49a23e9b06d897649ddfbf0 Mon Sep 17 00:00:00 2001 From: Panos Date: Sat, 9 Nov 2024 14:40:13 +0200 Subject: [PATCH 57/61] update slnx with workflow files --- TabKeeper.slnx | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/TabKeeper.slnx b/TabKeeper.slnx index b6e0f9e..e1a2160 100644 --- a/TabKeeper.slnx +++ b/TabKeeper.slnx @@ -1,4 +1,5 @@ + @@ -26,10 +27,12 @@ - - - - + + + + + + From 5617728b1eb1df85c5376a02c3e53e6247bcae54 Mon Sep 17 00:00:00 2001 From: Panos Date: Sat, 1 Mar 2025 00:20:18 +0200 Subject: [PATCH 58/61] Refactor root project files --- Directory.Build.props | 28 +++++----------------------- Directory.Packages.props | 28 +++++++++++----------------- GitVersion.yaml | 8 ++++++++ TabKeeper.slnx | 40 ++++++++-------------------------------- global.json | 2 +- src-modules/Core | 2 +- version.json | 20 -------------------- 7 files changed, 34 insertions(+), 94 deletions(-) create mode 100644 GitVersion.yaml delete mode 100644 version.json diff --git a/Directory.Build.props b/Directory.Build.props index da8742f..1f8db99 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -6,7 +6,8 @@ true true Debug - $(NoWarn);CS8509;IDE0039;IDE0130;IDE0290;IDE0060;RZ10012;IDE0052;BL0007; + True + $(NoWarn);CS8509;IDE0039;IDE0130;IDE0290;IDE0060;RZ10012;IDE0052;BL0007;CA1816 $(WarningsAsErrors);RZ2012; $([System.IO.Path]::Combine( @@ -14,36 +15,17 @@ "artifacts", $([MSBuild]::MakeRelative($(MSBuildThisFileDirectory),$(MSBuildProjectDirectory)).Replace("$(MSBuildProjectName)", '').TrimEnd('/')) )) - true true - false + false Panagiotis Athanasiou - Copyright (c) 2024 $(Authors) - https://www.github.com/panoukos41/FontAwesome + Copyright (c) $([System.DateTimeOffset]::UtcNow.ToString("yyyy")) $(Authors) + https://www.github.com/panoukos41/TabKeeper git - MIT - Project to port great features, component, ideas and libs from the Angular ecosystem to Blazor and .NET. - blazor;angular;components - - - - - $(RepositoryUrl) - $(RepositoryLicense) - $(RepositoryDescription) - $(RepositoryTags) - $(RepositoryUrl)/releases - - README.md - - true - true - snupkg diff --git a/Directory.Packages.props b/Directory.Packages.props index 93517af..22b390d 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -7,41 +7,35 @@ - - - + + - - - - - - + + - + - - - - - - + + + + + - + \ No newline at end of file diff --git a/GitVersion.yaml b/GitVersion.yaml new file mode 100644 index 0000000..6e3b19e --- /dev/null +++ b/GitVersion.yaml @@ -0,0 +1,8 @@ +workflow: GitHubFlow/v1 +branches: + main: + label: beta + increment: Patch + feature: + label: alpha + increment: Minor diff --git a/TabKeeper.slnx b/TabKeeper.slnx index e1a2160..eb06f1e 100644 --- a/TabKeeper.slnx +++ b/TabKeeper.slnx @@ -1,40 +1,16 @@ - - - - - - - - - - - - - - - - - - + + + + - - - + + + - - - - - - - - - - - + diff --git a/global.json b/global.json index 2ddda36..93681ff 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.0", + "version": "9.0.0", "rollForward": "latestMinor", "allowPrerelease": false } diff --git a/src-modules/Core b/src-modules/Core index 5b7fc57..ac13f6b 160000 --- a/src-modules/Core +++ b/src-modules/Core @@ -1 +1 @@ -Subproject commit 5b7fc57203098985d9a9911f74573132f271226b +Subproject commit ac13f6b45cf53021dd55a57c28295e3b280d04b4 diff --git a/version.json b/version.json deleted file mode 100644 index 3839403..0000000 --- a/version.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/main/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1-dev", - "release": { - "firstUnstableTag": "dev" - }, - "publicReleaseRefSpec": [ - "^refs/heads/main$", - "^refs/heads/dev$" - ], - "pathFilters": [ - ":/src/" - ], - "cloudBuild": { - "setVersionVariables": true, - "buildNumber": { - "enabled": false - } - } -} \ No newline at end of file From e3062bb2b91a8354feac178ec1a7092cd12548df Mon Sep 17 00:00:00 2001 From: Panos Date: Sat, 1 Mar 2025 00:20:40 +0200 Subject: [PATCH 59/61] Full refactor of UI and Settings page --- src/TabKeeper.UI.Wasm/App.razor | 3 +- .../Common/IndexedDB/IndexedDdJs.cs | 316 +++++++++++++ src/TabKeeper.UI.Wasm/Common/IndexedDb.cs | 34 -- .../IndexedDB_Migration_2024_08_001.cs | 18 +- .../Common/Mixins/NavigationManagerMixins.cs | 14 - .../Common/Mixins/TranslateMixins.cs | 17 +- src/TabKeeper.UI.Wasm/Common/StorageDb.cs | 115 +++++ src/TabKeeper.UI.Wasm/Components/Button.razor | 8 +- src/TabKeeper.UI.Wasm/Components/Js.cs | 11 - src/TabKeeper.UI.Wasm/Components/Modal.razor | 24 +- .../PreferenceCollectionComponentBase.cs | 33 -- .../Abstract/PreferenceComponentBase.cs | 24 - .../Abstract/PreferenceValueComponentBase.cs | 16 - .../EditTextPreferenceComponent.razor | 1 - .../ListBoxPreferenceComponent.razor | 23 - .../PreferenceCategoryComponent.razor | 21 - .../SwitchPreferenceComponent.razor | 1 - .../Pages/PreferenceScreenPage.razor | 25 - .../Components/Preferences/_imports.razor | 1 - .../Layout/ShellLayout.razor | 6 +- src/TabKeeper.UI.Wasm/Pages/HomePage.razor | 24 +- src/TabKeeper.UI.Wasm/Pages/HomePage2.razor | 158 ------- .../Pages/SettingsPage.razor | 20 +- .../Tabs/Components/PersonDetailView.razor | 6 +- .../Tabs/Components/ProductCardView.razor | 6 +- .../Tabs/Components/ProductDetailView.razor | 6 +- .../Pages/Tabs/TabPage.razor | 20 +- src/TabKeeper.UI.Wasm/Program.cs | 15 +- .../TabKeeper.UI.Wasm.csproj | 6 +- src/TabKeeper.UI.Wasm/assets/_details.scss | 47 ++ .../assets/_preferences.scss | 36 ++ src/TabKeeper.UI.Wasm/assets/app.scss | 4 + src/TabKeeper.UI.Wasm/css.ps1 | 6 +- src/TabKeeper.UI.Wasm/package-lock.json | 377 ++++++--------- src/TabKeeper.UI.Wasm/package.json | 5 +- src/TabKeeper.UI.Wasm/tailwind.config.js | 5 +- ...ailwind.config.tailwind-material-colors.js | 440 ++++++++++++++++++ src/TabKeeper.UI.Wasm/tailwind.extension.json | 25 +- src/TabKeeper.UI.Wasm/wwwroot/i18n/el.json | 1 + src/TabKeeper.UI.Wasm/wwwroot/i18n/en.json | 1 + src/TabKeeper.UI.Wasm/wwwroot/index.html | 17 +- .../wwwroot/js/blazor-decompress.js | 19 + .../wwwroot/js/indexed-wrapper.js | 284 +++++++++++ src/TabKeeper.UI/Preferences.cs | 27 +- src/TabKeeper.UI/TabKeeper.UI.csproj | 2 +- src/TabKeeper/TabKeeper.csproj | 2 +- 46 files changed, 1547 insertions(+), 723 deletions(-) create mode 100644 src/TabKeeper.UI.Wasm/Common/IndexedDB/IndexedDdJs.cs delete mode 100644 src/TabKeeper.UI.Wasm/Common/IndexedDb.cs delete mode 100644 src/TabKeeper.UI.Wasm/Common/Mixins/NavigationManagerMixins.cs create mode 100644 src/TabKeeper.UI.Wasm/Common/StorageDb.cs delete mode 100644 src/TabKeeper.UI.Wasm/Components/Js.cs delete mode 100644 src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceCollectionComponentBase.cs delete mode 100644 src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceComponentBase.cs delete mode 100644 src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceValueComponentBase.cs delete mode 100644 src/TabKeeper.UI.Wasm/Components/Preferences/Components/EditTextPreferenceComponent.razor delete mode 100644 src/TabKeeper.UI.Wasm/Components/Preferences/Components/ListBoxPreferenceComponent.razor delete mode 100644 src/TabKeeper.UI.Wasm/Components/Preferences/Components/PreferenceCategoryComponent.razor delete mode 100644 src/TabKeeper.UI.Wasm/Components/Preferences/Components/SwitchPreferenceComponent.razor delete mode 100644 src/TabKeeper.UI.Wasm/Components/Preferences/Pages/PreferenceScreenPage.razor delete mode 100644 src/TabKeeper.UI.Wasm/Components/Preferences/_imports.razor delete mode 100644 src/TabKeeper.UI.Wasm/Pages/HomePage2.razor create mode 100644 src/TabKeeper.UI.Wasm/assets/_details.scss create mode 100644 src/TabKeeper.UI.Wasm/assets/_preferences.scss create mode 100644 src/TabKeeper.UI.Wasm/tailwind.config.tailwind-material-colors.js create mode 100644 src/TabKeeper.UI.Wasm/wwwroot/js/blazor-decompress.js create mode 100644 src/TabKeeper.UI.Wasm/wwwroot/js/indexed-wrapper.js diff --git a/src/TabKeeper.UI.Wasm/App.razor b/src/TabKeeper.UI.Wasm/App.razor index 76d2e1b..c4a6d08 100644 --- a/src/TabKeeper.UI.Wasm/App.razor +++ b/src/TabKeeper.UI.Wasm/App.razor @@ -1,4 +1,5 @@ -@using TabKeeper.Layout +@using System.Runtime.InteropServices.JavaScript +@using TabKeeper.Layout @inject TranslateService translate diff --git a/src/TabKeeper.UI.Wasm/Common/IndexedDB/IndexedDdJs.cs b/src/TabKeeper.UI.Wasm/Common/IndexedDB/IndexedDdJs.cs new file mode 100644 index 0000000..a982cad --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Common/IndexedDB/IndexedDdJs.cs @@ -0,0 +1,316 @@ +using Microsoft.JSInterop; +using System.Collections.Concurrent; +using System.Text.Json; + +namespace TabKeeper.Common.IndexedDB; + +/// +/// A database definition describing the database schema. +/// +public sealed record IDBDatabaseDefinition +{ + /// + /// The database name. + /// + public required string Name { get; init; } + + /// + /// The database version. + /// + public int Version { get; set; } + + /// + /// The database store definitions. + /// + public required IDBObjectStoreDefinition[] ObjectStores { get; init; } +} + +/// +/// A store index definition describing the index. +/// +public sealed record IDBIndexDefinition +{ + /// + /// The index name. + /// + public required string Name { get; init; } + + /// + /// The index key path. + /// + public required string KeyPath { get; init; } + + /// + /// + /// + public bool MultiEntry { get; init; } + + /// + /// + /// + public bool Unique { get; init; } +} + +/// +/// A store definition describing the store. +/// +public class IDBObjectStoreDefinition +{ + /// + /// + /// + public required string Name { get; init; } + + /// + /// + /// + public string? KeyPath { get; init; } + + /// + /// + /// + public bool AutoIncrement { get; init; } + + /// + /// + /// + public IDBIndexDefinition[] Indexes { get; init; } = []; +} + +public abstract class IDBBase +{ + public IJSRuntime JSRuntime { get; } + + public IJSObjectReference JSReference { get; } + + protected IDBBase(IJSRuntime jSRuntime, IJSObjectReference jsReference) + { + JSRuntime = jSRuntime; + JSReference = jsReference; + } + + public virtual ValueTask DisposeAsync() + { + GC.SuppressFinalize(this); + return JSReference.DisposeAsync(); + } +} + +public class IDBFactory +{ + private static IJSObjectReference? module = null; + private readonly IJSRuntime jSRuntime; + + public IDBFactory(IJSRuntime jSRuntime) + { + this.jSRuntime = jSRuntime; + } + + private static ValueTask Import(IJSRuntime jsRuntime) + { + return module is null ? Execute() : new(module); + + async ValueTask Execute() => + module = await jsRuntime.InvokeAsync("import", "./js/indexed-wrapper.js"); + } + + public static async ValueTask Open(IJSRuntime jSRuntime, IDBDatabaseDefinition definition) + { + var module = await Import(jSRuntime); + var database = await module.InvokeAsync("open", definition); + var info = await database.InvokeAsync("getInfo"); + + var db = new IDBDatabase(jSRuntime, database, info.Name, info.Version, info.ObjectStoreNames); + return db; + } + + public static async ValueTask<(string Name, long Version)[]> Databases(IJSRuntime jSRuntime) + { + var module = await Import(jSRuntime); + var database = await module.InvokeAsync("databases"); + return [.. database.Select(d => (d.Name, d.Version))]; + } + + public static async ValueTask DeleteDatabase(IJSRuntime jSRuntime, string name) + { + var module = await Import(jSRuntime); + var result = await module.InvokeAsync("deleteDatabase", name); + return result; + } + + public static DotNetObjectReference? GetObjReferenceWrapper(T? value) where T : class + { + return value is { } ? DotNetObjectReference.Create(value) : null; + } + + private record IndexedDatabaseInfo(string Name, long Version, string[] ObjectStoreNames); + + private record IndexedDatabasesInfo(string Name, long Version); +} + +public sealed class IDBDatabase : IDBBase +{ + private bool closed; + private readonly ConcurrentDictionary stores = []; + + /// + /// A string that contains the name of the connected database. + /// + public string Name { get; } + + /// + /// The version of the connected database. + /// + public long Version { get; } + + /// + /// A string array containing the names of the object stores currently in the connected database. + /// + public string[] ObjectStoreNames { get; } + + public IDBDatabase(IJSRuntime jSRuntime, IJSObjectReference jsReference, string name, long version, string[] objectStoreNames) : base(jSRuntime, jsReference) + { + Name = name; + Version = version; + ObjectStoreNames = objectStoreNames; + } + + public ValueTask GetObjectStore(string name) + { + return stores.TryGetValue(name, out var store) ? new(store) : Execute(this, name); + + static async ValueTask Execute(IDBDatabase db, string name) + { + var objectStore = await db.JSReference.InvokeAsync("objectStore", name); + var info = await objectStore.InvokeAsync("getInfo"); + + var store = new IDBObjectStore(db.JSRuntime, objectStore, info.Name, info.KeyPath, info.AutoIncrement, info.IndexNames); + db.stores.TryAdd(name, store); + return store; + } + } + + public ValueTask Close() + { + return closed ? new() : Execute(this); + + static ValueTask Execute(IDBDatabase db) + { + db.closed = true; + return db.JSReference.InvokeVoidAsync("close"); + } + } + + public override ValueTask DisposeAsync() + { + return stores.IsEmpty + ? base.DisposeAsync() + : new ValueTask(Task.WhenAll(stores.Values.Select(s => s.DisposeAsync().AsTask()).Append(base.DisposeAsync().AsTask()))); + } + + private record IndexedObjectStoreInfo(string Name, string KeyPath, bool AutoIncrement, string[] IndexNames); +} + +public sealed class IDBObjectStore : IDBBase +{ + /// + /// The store name. + /// + public string Name { get; } + + /// + /// The store primary key path. + /// + public string KeyPath { get; } + + /// + /// Whether the key is auto incremented by the database. + /// + public bool AutoIncrement { get; } + + /// + /// A list with all the index names of the store. + /// + public string[] IndexNames { get; } + + public IDBObjectStore(IJSRuntime jSRuntime, IJSObjectReference jsReference, string name, string keyPath, bool autoIncrement, string[] indexNames) : base(jSRuntime, jsReference) + { + Name = name; + KeyPath = keyPath; + AutoIncrement = autoIncrement; + IndexNames = indexNames; + } + + public ValueTask Count() + { + return JSReference.InvokeAsync("count"); + } + + public ValueTask Get(TKey key) + { + return JSReference.InvokeAsync("get", key); + } + + public ValueTask Get(TKey key) + { + return JSReference.InvokeAsync("get", key); + } + + //public ValueTask GetKey() + //{ + // return JSReference.InvokeAsync("get", key); + //} + + //public ValueTask GetKey() + //{ + // return JSReference.InvokeAsync("get", key); + //} + + public ValueTask> GetAll() + { + return JSReference.InvokeAsync>("getAll"); + } + + public ValueTask> GetAll() + { + return JSReference.InvokeAsync>("getAll"); + } + + public ValueTask> GetAllKeys() + { + return JSReference.InvokeAsync>("getAllKeys"); + } + + public ValueTask> GetAllKeys() + { + return JSReference.InvokeAsync>("getAllKeys"); + } + + public ValueTask Add(T obj) + { + return JSReference.InvokeVoidAsync("add", obj); + } + + public ValueTask Put(T obj) + { + return JSReference.InvokeVoidAsync("put", obj); + } + + public ValueTask Delete(TKey key) + { + return JSReference.InvokeVoidAsync("delete", key); + } + + public ValueTask Clear() + { + return JSReference.InvokeVoidAsync("clear"); + } + + //public ValueTask OpenCursor() + //{ + //} + + //public ValueTask OpenKeyCursor() + //{ + //} +} diff --git a/src/TabKeeper.UI.Wasm/Common/IndexedDb.cs b/src/TabKeeper.UI.Wasm/Common/IndexedDb.cs deleted file mode 100644 index e119799..0000000 --- a/src/TabKeeper.UI.Wasm/Common/IndexedDb.cs +++ /dev/null @@ -1,34 +0,0 @@ -using CloudNimble.BlazorEssentials.IndexedDb; -using Microsoft.JSInterop; - -namespace TabKeeper.Common; - -public sealed class IndexedDb : IndexedDbDatabase -{ - [Index(Name = "Name", Path = "name")] - public IndexedDbObjectStore People { get; private set; } = null!; - - [Index(Name = "Name", Path = "name")] - [Index(Name = "Place", Path = "place")] - [Index(Name = "PayerId", Path = "payerId")] - [Index(Name = "Date", Path = "date")] - [Index(Name = "IsLocked", Path = "isLocked")] - public IndexedDbObjectStore Tabs { get; private set; } = null!; - - public IndexedDb(IJSRuntime jsRuntime) : base(jsRuntime) - { - Name = "TabKeeper"; - Version = 1; - - // Indexes are added to the Store in the constructor, so nothing else is needed here. - // People - //_ = new IndexedDbIndex(People, "Name", "name"); - - // Tabs - //_ = new IndexedDbIndex(Tabs, "Name", "name"); - //_ = new IndexedDbIndex(Tabs, "Place", "place"); - //_ = new IndexedDbIndex(Tabs, "PayerId", "payerId"); - //_ = new IndexedDbIndex(Tabs, "Date", "date"); - //_ = new IndexedDbIndex(Tabs, "IsLocked", "isLocked"); - } -} diff --git a/src/TabKeeper.UI.Wasm/Common/Migrations/IndexedDB_Migration_2024_08_001.cs b/src/TabKeeper.UI.Wasm/Common/Migrations/IndexedDB_Migration_2024_08_001.cs index f2c04d5..424c35d 100644 --- a/src/TabKeeper.UI.Wasm/Common/Migrations/IndexedDB_Migration_2024_08_001.cs +++ b/src/TabKeeper.UI.Wasm/Common/Migrations/IndexedDB_Migration_2024_08_001.cs @@ -1,19 +1,21 @@ using Blazored.LocalStorage; +using Microsoft.JSInterop; +using TabKeeper.Common.IndexedDB; using TabKeeper.People; using TabKeeper.Tabs; namespace TabKeeper.Common.Migrations; -public class IndexedDB_Migration_2024_08_001 +public sealed class IndexedDB_Migration_2024_08_001 { private const string EntriesKey = "tab-entries"; private readonly ISyncLocalStorageService localStorage; - private readonly IndexedDb indexedDb; + private readonly StorageDb storage; - public IndexedDB_Migration_2024_08_001(ISyncLocalStorageService localStorage, IndexedDb indexedDb) + public IndexedDB_Migration_2024_08_001(ISyncLocalStorageService localStorage, StorageDb storage) { this.localStorage = localStorage; - this.indexedDb = indexedDb; + this.storage = storage; } public async Task Migrate() @@ -21,7 +23,7 @@ public async Task Migrate() if (localStorage.GetItem(EntriesKey) is not { } tabs) return; - if (await indexedDb.Tabs.CountAsync() is not 0) + if (await storage.Tabs.Count() is not 0) return; foreach (var tab in tabs) @@ -32,10 +34,10 @@ public async Task Migrate() localStorage.RemoveItem(EntriesKey); } - private Task MigrateTab(TabEntry entry) + private ValueTask MigrateTab(TabEntry entry) { if (localStorage.GetItem(entry.Id) is not { } tab) - return Task.CompletedTask; + return new(); var newTab = new Tab(tab.Id) { @@ -45,7 +47,7 @@ private Task MigrateTab(TabEntry entry) Products = [.. tab.Products], People = [.. tab.People.Select(x => new TabPerson(x.Person) { ProductIds = x.ProductIds })], }; - return indexedDb.Tabs.AddAsync(newTab); + return storage.Tabs.Add(newTab); } private sealed record TabEntry(Uuid Id, string Name); diff --git a/src/TabKeeper.UI.Wasm/Common/Mixins/NavigationManagerMixins.cs b/src/TabKeeper.UI.Wasm/Common/Mixins/NavigationManagerMixins.cs deleted file mode 100644 index 38a65a6..0000000 --- a/src/TabKeeper.UI.Wasm/Common/Mixins/NavigationManagerMixins.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Microsoft.AspNetCore.Components; - -public static class NavigationManagerMixins -{ - public static void GoBack(this NavigationManager nav, bool forceLoad = false, bool replace = false) - { - nav.NavigateTo(nav.Uri.RemovePathSegment(), forceLoad, replace); - } - - public static void GoBack(this NavigationManager nav, NavigationOptions options) - { - nav.NavigateTo(nav.Uri.RemovePathSegment(), options); - } -} diff --git a/src/TabKeeper.UI.Wasm/Common/Mixins/TranslateMixins.cs b/src/TabKeeper.UI.Wasm/Common/Mixins/TranslateMixins.cs index f7325b2..a5698cd 100644 --- a/src/TabKeeper.UI.Wasm/Common/Mixins/TranslateMixins.cs +++ b/src/TabKeeper.UI.Wasm/Common/Mixins/TranslateMixins.cs @@ -1,29 +1,30 @@ -using Core.Blazor; -using Microsoft.AspNetCore.Components; +using Microsoft.AspNetCore.Components; +using System.Reactive.Disposables; namespace Annular.Translate; public static class TranslateMixins { - public static void Update(this TranslateService translate, IComponent component) + public static IDisposable Update(this TranslateService translate, IComponent component) { - if (component is not IHandleEvent handleEvent) return; + if (component is not IHandleEvent handleEvent) + return Disposable.Empty; var @ref = new WeakReference(handleEvent); - translate.OnLangChange + return translate.OnLangChange .Select(e => @ref.TryGetTarget(out var target) ? target : null) .TakeUntil(static t => t is not null) .Subscribe(static t => t?.HandleEventAsync(EventCallbackWorkItem.Empty, null)); } - public static void Update(this TranslateService translate, CoreComponent component) + public static IDisposable Update(this TranslateService translate, CoreComponent component) { var @ref = new WeakReference(component); - translate.OnLangChange + return translate.OnLangChange .Select(e => @ref.TryGetTarget(out var target) ? target : null) .TakeUntil(static t => t is not null) - .Subscribe(static t => t?.TriggerUpdate()); + .Subscribe(static t => t?.Update()); } } diff --git a/src/TabKeeper.UI.Wasm/Common/StorageDb.cs b/src/TabKeeper.UI.Wasm/Common/StorageDb.cs new file mode 100644 index 0000000..7863673 --- /dev/null +++ b/src/TabKeeper.UI.Wasm/Common/StorageDb.cs @@ -0,0 +1,115 @@ +using Microsoft.JSInterop; +using TabKeeper.Common.IndexedDB; +using TabKeeper.People; +using TabKeeper.Tabs; + +namespace TabKeeper.Common; + +public static class StorageDefinitions +{ + public static readonly IDBDatabaseDefinition TabKeeper_v1 = new() + { + Name = "TabKeeper", + Version = 1, + ObjectStores = + [ + new() + { + Name = "People", + KeyPath = "id", + Indexes = [ + new() { Name = "Name", KeyPath = "name" }, + ] + }, + new() + { + Name = "Tabs", + KeyPath = "id", + Indexes = [ + new() { Name = "Name", KeyPath = "name" }, + new() { Name = "Place", KeyPath = "place" }, + new() { Name = "PayerId", KeyPath = "payerId" }, + new() { Name = "Date", KeyPath = "date" }, + new() { Name = "IsLocked", KeyPath = "isLocked" }, + ] + }, + ] + }; +} + +public sealed class StorageDb : IAsyncDisposable +{ + private readonly IJSRuntime jSRuntime; + private IDBDatabase db = null!; + + public StorageDb(IJSRuntime jSRuntime) + { + this.jSRuntime = jSRuntime; + } + + public async Task Initialize() + { + db = await IDBFactory.Open(jSRuntime, StorageDefinitions.TabKeeper_v1); + Tabs = new(await db.GetObjectStore("Tabs")); + People = new(await db.GetObjectStore("People")); + } + + public StorageStore Tabs { get; private set; } = null!; + + public StorageStore People { get; private set; } = null!; + + public ValueTask DisposeAsync() + { + return db?.DisposeAsync() ?? new(); + } +} + +public sealed class StorageStore +{ + private readonly IDBObjectStore store; + + public StorageStore(IDBObjectStore store) + { + this.store = store; + } + + public ValueTask Count() + { + return store.Count(); + } + + public ValueTask Get(TKey key) + { + return store.Get(key); + } + + public ValueTask> GetAll() + { + return store.GetAll(); + } + + public ValueTask> GetAllKeys() + { + return store.GetAllKeys(); + } + + public ValueTask Add(T obj) + { + return store.Add(obj); + } + + public ValueTask Put(T obj) + { + return store.Put(obj); + } + + public ValueTask Delete(TKey key) + { + return store.Delete(key); + } + + public ValueTask Clear() + { + return store.Clear(); + } +} diff --git a/src/TabKeeper.UI.Wasm/Components/Button.razor b/src/TabKeeper.UI.Wasm/Components/Button.razor index ca28fd8..5e5baa8 100644 --- a/src/TabKeeper.UI.Wasm/Components/Button.razor +++ b/src/TabKeeper.UI.Wasm/Components/Button.razor @@ -1,8 +1,6 @@ -@using OneOf +@inherits CoreComponent -@inherits CoreComponent - -@if (If?.Match(static v => v, static f => f()) is false) +@if (If is false) { return; } @@ -29,7 +27,7 @@ @code { [Parameter] - public OneOf>? If { get; set; } + public bool If { get; set; } = true; [Parameter] public RenderFragment? ChildContent { get; set; } diff --git a/src/TabKeeper.UI.Wasm/Components/Js.cs b/src/TabKeeper.UI.Wasm/Components/Js.cs deleted file mode 100644 index 060f32b..0000000 --- a/src/TabKeeper.UI.Wasm/Components/Js.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.JSInterop; - -namespace TabKeeper.Components; - -public class Js -{ -} - -public class Window -{ -} diff --git a/src/TabKeeper.UI.Wasm/Components/Modal.razor b/src/TabKeeper.UI.Wasm/Components/Modal.razor index 3be2e50..ffe120b 100644 --- a/src/TabKeeper.UI.Wasm/Components/Modal.razor +++ b/src/TabKeeper.UI.Wasm/Components/Modal.razor @@ -30,9 +30,7 @@ Context="transition">
- - @(ChildContent?.Invoke(this)) - + @(ChildContent?.Invoke(this))
@@ -41,8 +39,6 @@ @code { - private ReactiveValue updateExpression; - [Parameter] public bool IsOpen { get; set; } @@ -67,11 +63,6 @@ [Parameter] public EventCallback OnShow { get; set; } - public Modal() - { - updateExpression = new(this, 0); - } - protected override void OnInitialized() { if (IsOpenWhen is { }) @@ -79,13 +70,13 @@ var sub = IsOpenWhen.Subscribe(open => { IsOpen = open; - base.TriggerUpdate(); + base.Update(); }); DisposeWith(sub); } if (UpdateWhen is { }) { - var updateSub = UpdateWhen.Subscribe(_ => updateExpression.Value = 0); + var updateSub = UpdateWhen.Subscribe(_ => Update()); DisposeWith(updateSub); } } @@ -94,7 +85,7 @@ { IsOpen = true; OnShow.InvokeAsync(); - base.TriggerUpdate(); + base.Update(); return None.Value; } @@ -102,7 +93,7 @@ { IsOpen = false; OnDismiss.InvokeAsync(); - base.TriggerUpdate(); + base.Update(); return None.Value; } @@ -110,9 +101,4 @@ { return IsOpen ? Close() : Show(); } - - public void Update() - { - updateExpression.Value = 0; - } } diff --git a/src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceCollectionComponentBase.cs b/src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceCollectionComponentBase.cs deleted file mode 100644 index 9dddc7d..0000000 --- a/src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceCollectionComponentBase.cs +++ /dev/null @@ -1,33 +0,0 @@ -using Core.Preferences; -using Core.Preferences.Abstract; -using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Components.Rendering; -using TabKeeper.Components.Preferences.Components; - -namespace TabKeeper.Components.Preferences.Abstract; - -public abstract class PreferenceCollectionComponentBase : PreferenceComponentBase - where TPreferenceCollection : PreferenceCollectionBase -{ - protected RenderFragment RenderPreference(PreferenceBase preference) => builder => - { - _ = preference switch - { - PreferenceCategory categoryPreference => Render(ref builder, ref categoryPreference), - EditTextPreference editTextPreference => Render(ref builder, ref editTextPreference), - SwitchPreference switchPreference => Render(ref builder, ref switchPreference), - ListBoxPreference listBoxPreference => Render(ref builder, ref listBoxPreference), - _ => Nothing.Value - }; - }; - - private static Nothing Render(ref RenderTreeBuilder builder, ref TPreference preference) - where TComponent : notnull, PreferenceComponentBase - where TPreference : PreferenceBase - { - builder.OpenComponent(0); - builder.AddComponentParameter(1, nameof(Preference), preference); - builder.CloseComponent(); - return Nothing.Value; - } -} diff --git a/src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceComponentBase.cs b/src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceComponentBase.cs deleted file mode 100644 index 81f178b..0000000 --- a/src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceComponentBase.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Core.Preferences; -using Core.Preferences.Abstract; -using Microsoft.AspNetCore.Components; - -namespace TabKeeper.Components.Preferences.Abstract; - -public abstract class PreferenceComponentBase : ComponentBase - where TPreference : PreferenceBase -{ - [CascadingParameter] - public PreferenceScreen? Root { get; set; } - - [Parameter, EditorRequired] - public TPreference Preference { get; set; } = null!; - - protected object? GetIcon() - => Root?.IconTransformer is { } transformer ? transformer(Preference.Icon) : Preference.Icon; - - protected string GetTitle() - => Root?.TitleTransformer is { } transformer ? transformer(Preference.Title) : Preference.Title; - - protected string? GetDescription() - => Root?.DescriptionTransformer is { } transformer ? transformer(Preference.Description) : Preference.Description; -} diff --git a/src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceValueComponentBase.cs b/src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceValueComponentBase.cs deleted file mode 100644 index a68d404..0000000 --- a/src/TabKeeper.UI.Wasm/Components/Preferences/Abstract/PreferenceValueComponentBase.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Core.Preferences.Abstract; - -namespace TabKeeper.Components.Preferences.Abstract; - -public abstract class PreferenceValueComponentBase : PreferenceComponentBase - where TPreference : PreferenceValueBase -{ - protected string GetValueSummary() - => Root?.SummaryTransformer is { } transformer ? transformer(Preference.ValueSummary) : Preference.ValueSummary; -} - -public abstract class PreferenceValueComponentBase : PreferenceValueComponentBase - where TPreference : PreferenceValueBase - where TValue : IParsable, new() -{ -} diff --git a/src/TabKeeper.UI.Wasm/Components/Preferences/Components/EditTextPreferenceComponent.razor b/src/TabKeeper.UI.Wasm/Components/Preferences/Components/EditTextPreferenceComponent.razor deleted file mode 100644 index 9657624..0000000 --- a/src/TabKeeper.UI.Wasm/Components/Preferences/Components/EditTextPreferenceComponent.razor +++ /dev/null @@ -1 +0,0 @@ -@inherits Abstract.PreferenceValueComponentBase diff --git a/src/TabKeeper.UI.Wasm/Components/Preferences/Components/ListBoxPreferenceComponent.razor b/src/TabKeeper.UI.Wasm/Components/Preferences/Components/ListBoxPreferenceComponent.razor deleted file mode 100644 index 7ca37a1..0000000 --- a/src/TabKeeper.UI.Wasm/Components/Preferences/Components/ListBoxPreferenceComponent.razor +++ /dev/null @@ -1,23 +0,0 @@ -@inherits Abstract.PreferenceValueComponentBase - -
-
- -
- -
- -@code { - public void OnChange(ChangeEventArgs e) - { - if (e.Value is string arg) - { - Preference.Value = arg; - } - } -} diff --git a/src/TabKeeper.UI.Wasm/Components/Preferences/Components/PreferenceCategoryComponent.razor b/src/TabKeeper.UI.Wasm/Components/Preferences/Components/PreferenceCategoryComponent.razor deleted file mode 100644 index 72d47a4..0000000 --- a/src/TabKeeper.UI.Wasm/Components/Preferences/Components/PreferenceCategoryComponent.razor +++ /dev/null @@ -1,21 +0,0 @@ -@inherits Abstract.PreferenceCollectionComponentBase - -
-
-
- @if (GetIcon() is { } icon) - { - - } -

@GetTitle()

-
- @if (GetDescription() is { } desc) - { -

@desc

- } -
- @foreach (var preference in Preference) - { - @RenderPreference(preference) - } -
diff --git a/src/TabKeeper.UI.Wasm/Components/Preferences/Components/SwitchPreferenceComponent.razor b/src/TabKeeper.UI.Wasm/Components/Preferences/Components/SwitchPreferenceComponent.razor deleted file mode 100644 index 5eb13d3..0000000 --- a/src/TabKeeper.UI.Wasm/Components/Preferences/Components/SwitchPreferenceComponent.razor +++ /dev/null @@ -1 +0,0 @@ -@inherits Abstract.PreferenceValueComponentBase diff --git a/src/TabKeeper.UI.Wasm/Components/Preferences/Pages/PreferenceScreenPage.razor b/src/TabKeeper.UI.Wasm/Components/Preferences/Pages/PreferenceScreenPage.razor deleted file mode 100644 index 4efe411..0000000 --- a/src/TabKeeper.UI.Wasm/Components/Preferences/Pages/PreferenceScreenPage.razor +++ /dev/null @@ -1,25 +0,0 @@ -@using Core.Preferences.Abstract -@inherits Abstract.PreferenceCollectionComponentBase - - - @foreach (var preference in Screen) - { - @RenderPreference(preference) - } - - -@code { - private new PreferenceScreen? Preference { get; set; } - - [Parameter, EditorRequired] - public PreferenceScreen Screen - { - get => base.Preference; - set => base.Preference = value; - } - - protected override void OnParametersSet() - { - Root = Screen; - } -} diff --git a/src/TabKeeper.UI.Wasm/Components/Preferences/_imports.razor b/src/TabKeeper.UI.Wasm/Components/Preferences/_imports.razor deleted file mode 100644 index d381823..0000000 --- a/src/TabKeeper.UI.Wasm/Components/Preferences/_imports.razor +++ /dev/null @@ -1 +0,0 @@ -@using Core.Preferences; diff --git a/src/TabKeeper.UI.Wasm/Layout/ShellLayout.razor b/src/TabKeeper.UI.Wasm/Layout/ShellLayout.razor index 5ea6c40..10e461c 100644 --- a/src/TabKeeper.UI.Wasm/Layout/ShellLayout.razor +++ b/src/TabKeeper.UI.Wasm/Layout/ShellLayout.razor @@ -8,7 +8,7 @@ { } @@ -16,8 +16,8 @@ @(string.IsNullOrEmpty(Title) ? "Tab Keeper" : $"Tab Keeper - {Title}")
- -

@Title

+ +

@Title

diff --git a/src/TabKeeper.UI.Wasm/Pages/HomePage.razor b/src/TabKeeper.UI.Wasm/Pages/HomePage.razor index e0903ca..8b75ca9 100644 --- a/src/TabKeeper.UI.Wasm/Pages/HomePage.razor +++ b/src/TabKeeper.UI.Wasm/Pages/HomePage.razor @@ -1,6 +1,6 @@ @page "/" @inherits CoreComponent -@inject IndexedDb indexedDb +@inject StorageDb db @inject NavigationManager nav @inject TranslateService translate @@ -50,28 +50,32 @@ private async Task TabValidSubmit(TabKeeper.Tabs.Tab tab) { - await indexedDb.Tabs.AddAsync(tab); - nav.NavigateTo($"tabs/{tab.Id}"); + await db.Tabs.Add(tab); + nav.NavigateTo($"tab/{tab.Id}"); } - protected override void OnInitialized() + protected override void OnAfterRender(bool firstRender) { + if (!firstRender) return; + ShellLayout.Context = new() { Title = "general.home" | translate }; - indexedDb.Tabs - .GetAllAsync() + db.Tabs + .GetAll() + .AsTask() .ToObservable() .Do(entries => { - Entries.AddRange(entries); + Entries.AddRange(entries.Select(x => new TabEntry(x.Id, x.Name, x.Date))); Entries .Connect() - .OnItemRemoved(async entry => await indexedDb.Tabs.BatchDeleteAsync([entry.Id]), invokeOnUnsubscribe: false) - .Subscribe(_ => TriggerUpdate()) + .OnItemRemoved(async entry => await db.Tabs.Delete(entry.Id), invokeOnUnsubscribe: false) + .Subscribe(_ => Update()) .DisposeWith(this); loading = false; }) - .Subscribe(_ => Update()); + .Subscribe(_ => Update()) + .DisposeWith(this); } private record TabEntry(Uuid Id, string Name, DateOnly? Date); diff --git a/src/TabKeeper.UI.Wasm/Pages/HomePage2.razor b/src/TabKeeper.UI.Wasm/Pages/HomePage2.razor deleted file mode 100644 index a49c6d9..0000000 --- a/src/TabKeeper.UI.Wasm/Pages/HomePage2.razor +++ /dev/null @@ -1,158 +0,0 @@ -@page "/home" - -@inherits CoreComponent -@inject TranslateService translate - -
-
-

Personal

- @if (personalGroup.Invalid) - { - - } -
-
-
- - -
-
-
- -
-
-

Economic

- @if (economicGroup.Invalid) - { - - } -
-
-
- - -
-
-
- -
-
-

Children

- @if (childrenArray.Invalid) - { - - } -
-
- @for (int i = 0; i < childrenArray.Count; i++) - { - var index = i; - var formGroup = (FormGroup)childrenArray[index]; - -
- - -
- } -
-
- - - - - - - - -@code { - private static readonly ValidatorFn Required = Validators.Required; - private static readonly ValidatorFn MinLength3 = Validators.MinLength(3); - private static readonly ValidatorFn Min3 = Validators.Min(3M); - - private UpdateRequest Request { get; set; } = new(); - - private FormGroup formGroup; - private FormGroup personalGroup; - private FormGroup economicGroup; - private FormArray childrenArray; - - public HomePage2() - { - formGroup = new() - { - ["Personal"] = personalGroup = new() - { - ["FirstName"] = new FormControl(sync: [Required, MinLength3]), - ["LastName"] = new FormControl(sync: [Required, MinLength3]) - }, - ["Economic"] = economicGroup = new() - { - ["AnnualIncome"] = new FormControl(sync: [Required, Min3]), - ["AssetsValue"] = new FormControl(sync: [Required, Min3]) - }, - ["Children"] = childrenArray = new(), - }; - AddChild(); - } - - protected override void OnInitialized() - { - formGroup.Events.Subscribe(_ => TriggerUpdate()); - } - - private void AddChild() - { - childrenArray.Add(new FormGroup() - { - ["FirstName"] = new FormControl(sync: [Required, MinLength3]), - ["LastName"] = new FormControl(sync: [Required, MinLength3]) - }); - Request.Children.Add(new()); - TriggerUpdate(); - } - - private void RemoveChild(int index) - { - childrenArray.RemoveAt(index); - Request.Children.RemoveAt(index); - TriggerUpdate(); - } - - private void Test() - { - Console.WriteLine($"Income Vs: {formGroup.GetFormControl("Economic.AnnualIncome").Validators.Count()}"); - - Console.WriteLine($"- AnnualIncome: {formGroup.GetFormControl("Economic.AnnualIncome").Value}"); - Console.WriteLine($"- AssetsValue: {formGroup.GetFormControl("Economic.AssetsValue").Value}"); - Console.WriteLine("Children"); - for (int i = 0; i < childrenArray.Count; i++) - { - Console.WriteLine($"- {i,00} - FirstName: {formGroup.GetFormControl($"Children.[{i}].FirstName").Value}"); - Console.WriteLine($"- {i,00} - LastName: {formGroup.GetFormControl($"Children.[{i}].LastName").Value}"); - } - Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(Request)); - } - - private class UpdateRequest - { - public PersonalDetails Personal { get; } = new(); - - public EconomicDetails Economic { get; } = new(); - - public List Children { get; } = []; - } - - private class PersonalDetails - { - public string FirstName { get; set; } = string.Empty; - - public string LastName { get; set; } = string.Empty; - } - - private class EconomicDetails - { - public decimal AnnualIncome { get; set; } - - public decimal AssetsValue { get; set; } - } -} diff --git a/src/TabKeeper.UI.Wasm/Pages/SettingsPage.razor b/src/TabKeeper.UI.Wasm/Pages/SettingsPage.razor index 37f54e3..10154d7 100644 --- a/src/TabKeeper.UI.Wasm/Pages/SettingsPage.razor +++ b/src/TabKeeper.UI.Wasm/Pages/SettingsPage.razor @@ -1,34 +1,30 @@ -@using Core.Preferences; +@using Core.Preferences +@using Core.Preferences.Controls +@using Core.Preferences.Pages @using Microsoft.Extensions.Configuration.Memory -@using TabKeeper.Components.Preferences.Pages; @page "/settings" @inherits CoreComponent @inject TranslateService translate -@inject ISyncLocalStorageService localStorage +@inject PreferenceManager manager - + @code { public static ConfigurationManager Configuration { get; } = new(); protected override void OnInitialized() { - if (Configuration.Sources.Count is 1) - { - Configuration.Sources.Add(new LocalStorageConfigurationProvider(localStorage)); - } - ShellLayout.Context = new() { Title = "settings.title" | translate }; - Preferences.Screen.TitleTransformer = v => v | translate; - Preferences.Screen.DescriptionTransformer = v => v is {} ? v | translate : v; + Preferences.Screen.DescriptionTransformer = v => v is { } ? v | translate : v; Preferences.Screen.SummaryTransformer = v => v | translate; Preferences.Screen .WhenValuePreferenceChanged(Preferences.Theme) .Throttle(TimeSpan.FromMilliseconds(100)) - .Subscribe(p => ThemeModule.UpdateDom()); + .Subscribe(p => ThemeModule.UpdateDom()) + .DisposeWith(this); Preferences.Screen.Initialize(Configuration); } diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/PersonDetailView.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/PersonDetailView.razor index d5b5419..41f27c4 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/PersonDetailView.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/PersonDetailView.razor @@ -47,19 +47,19 @@ private void StartEdit() { edit = true; - TriggerUpdate(); + Update(); } private void CancelEdit() { edit = false; - TriggerUpdate(); + Update(); } private void ValidSubmit(Person person) { ViewModel.Person = person; edit = false; - TriggerUpdate(); + Update(); } } diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductCardView.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductCardView.razor index a04096e..c58c37c 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductCardView.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductCardView.razor @@ -6,16 +6,16 @@ @ViewModel.Name
-

@ViewModel.Price.ToString("0.00")

+

@ViewModel.Price.ToString("0.00")

-

@ViewModel.Quantity

+

@ViewModel.Quantity

-

@ViewModel.Total.ToString("0.00")

+

@ViewModel.Total.ToString("0.00")

diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductDetailView.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductDetailView.razor index 8e04642..76b0c41 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductDetailView.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/Components/ProductDetailView.razor @@ -47,19 +47,19 @@ private void StartEdit() { edit = true; - TriggerUpdate(); + Update(); } private void CancelEdit() { edit = false; - TriggerUpdate(); + Update(); } private void ValidSubmit(TabProduct product) { ViewModel.Product = product; edit = false; - TriggerUpdate(); + Update(); } } diff --git a/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor b/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor index cd12a5d..923f347 100644 --- a/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor +++ b/src/TabKeeper.UI.Wasm/Pages/Tabs/TabPage.razor @@ -1,6 +1,6 @@ @page "/tab/{Id}" @inherits CoreRxComponent -@inject IndexedDb indexedDb +@inject StorageDb db @inject TranslateService translate @* Loading *@ @@ -61,12 +61,12 @@
-

@ViewModel.Total.ToString("0.00")

+

@ViewModel.Total.ToString("0.00")

-

@ViewModel.People.Items.Sum(x => x.Total).ToString("0.00")

+

@ViewModel.People.Items.Sum(x => x.Total).ToString("0.00")

@*