Compare commits

...
6 Commits
58 changed files with 1073 additions and 233 deletions

No files matched your search

@@ -13,6 +13,7 @@
<link href="system/MudBlazor.Markdown/MudBlazor.Markdown.min.css" rel="stylesheet" />
<link href="app.css" rel="stylesheet" />
<HeadOutlet/>
<script src="diff.js"></script>
</head>
<body style="overflow: hidden;">
@@ -1,4 +1,6 @@
@using AIStudio.Chat
@using AIStudio.Components.Pages
@using AIStudio.Tools
<MudText Typo="Typo.h3" Class="mb-2 mr-3">
@this.Title
</MudText>
@@ -16,10 +18,58 @@
}
</MudForm>
<Issues IssuesData="@this.inputIssues"/>
@if (this.resultingContentBlock is not null)
@if (this.ShowDedicatedProgress && this.isProcessing)
{
<ContentBlockComponent Role="@this.resultingContentBlock.Role" Type="@this.resultingContentBlock.ContentType" Time="@this.resultingContentBlock.Time" Content="@this.resultingContentBlock.Content" Class="mr-2"/>
<MudProgressLinear Color="Color.Primary" Indeterminate="true" Class="mb-6" />
}
<div id="@ASSISTANT_RESULT_DIV_ID" class="mr-2 mt-3">
@if (this.ShowResult && this.resultingContentBlock is not null)
{
<ContentBlockComponent Role="@this.resultingContentBlock.Role" Type="@this.resultingContentBlock.ContentType" Time="@this.resultingContentBlock.Time" Content="@this.resultingContentBlock.Content"/>
}
</div>
<div id="@AFTER_RESULT_DIV_ID" class="mt-3">
</div>
@if (this.FooterButtons.Count > 0)
{
<MudStack Row="@true" Wrap="Wrap.Wrap" Class="mt-3 mr-2">
@foreach (var button in this.FooterButtons)
{
switch (button)
{
case ButtonData buttonData when !string.IsNullOrWhiteSpace(buttonData.Tooltip):
<MudTooltip Text="@buttonData.Tooltip">
<MudButton Variant="Variant.Filled" Color="@buttonData.Color" StartIcon="@GetButtonIcon(buttonData.Icon)" OnClick="async () => await buttonData.AsyncAction()">
@buttonData.Text
</MudButton>
</MudTooltip>
break;
case ButtonData buttonData:
<MudButton Variant="Variant.Filled" Color="@buttonData.Color" StartIcon="@GetButtonIcon(buttonData.Icon)" OnClick="async () => await buttonData.AsyncAction()">
@buttonData.Text
</MudButton>
break;
case SendToButton sendToButton:
<MudMenu StartIcon="@Icons.Material.Filled.Apps" EndIcon="@Icons.Material.Filled.KeyboardArrowDown" Label="Send to ..." Variant="Variant.Filled" Color="Color.Info">
@foreach (var assistant in Enum.GetValues<SendToAssistant>().OrderBy(n => n.Name().Length))
{
if(assistant is Pages.SendToAssistant.NONE || sendToButton.Self == assistant)
continue;
<MudMenuItem OnClick="() => this.SendToAssistant(assistant, sendToButton)">
@assistant.Name()
</MudMenuItem>
}
</MudMenu>
break;
}
}
</MudStack>
}
</ChildContent>
</InnerScrolling>
@@ -1,10 +1,13 @@
using AIStudio.Chat;
using AIStudio.Components.Pages;
using AIStudio.Provider;
using AIStudio.Settings;
using AIStudio.Tools;
using Microsoft.AspNetCore.Components;
using Path = AIStudio.Components.Pages.Path;
namespace AIStudio.Components;
public abstract partial class AssistantBase : ComponentBase
@@ -18,6 +21,18 @@ public abstract partial class AssistantBase : ComponentBase
[Inject]
protected ThreadSafeRandom RNG { get; init; } = null!;
[Inject]
protected ISnackbar Snackbar { get; init; } = null!;
[Inject]
protected Rust Rust { get; init; } = null!;
[Inject]
protected NavigationManager NavigationManager { get; init; } = null!;
internal const string AFTER_RESULT_DIV_ID = "afterAssistantResult";
internal const string ASSISTANT_RESULT_DIV_ID = "assistantResult";
protected abstract string Title { get; }
protected abstract string Description { get; }
@@ -26,6 +41,12 @@ public abstract partial class AssistantBase : ComponentBase
private protected virtual RenderFragment? Body => null;
protected virtual bool ShowResult => true;
protected virtual bool ShowDedicatedProgress => false;
protected virtual IReadOnlyList<IButtonData> FooterButtons => [];
protected static readonly Dictionary<string, object?> USER_INPUT_ATTRIBUTES = new();
protected AIStudio.Settings.Provider providerSettings;
@@ -35,6 +56,7 @@ public abstract partial class AssistantBase : ComponentBase
private ChatThread? chatThread;
private ContentBlock? resultingContentBlock;
private string[] inputIssues = [];
private bool isProcessing;
#region Overrides of ComponentBase
@@ -96,7 +118,7 @@ public abstract partial class AssistantBase : ComponentBase
return time;
}
protected async Task AddAIResponseAsync(DateTimeOffset time)
protected async Task<string> AddAIResponseAsync(DateTimeOffset time)
{
var aiText = new ContentText
{
@@ -114,10 +136,61 @@ public abstract partial class AssistantBase : ComponentBase
};
this.chatThread?.Blocks.Add(this.resultingContentBlock);
this.isProcessing = true;
this.StateHasChanged();
// Use the selected provider to get the AI response.
// By awaiting this line, we wait for the entire
// content to be streamed.
await aiText.CreateFromProviderAsync(this.providerSettings.CreateProvider(), this.JsRuntime, this.SettingsManager, this.providerSettings.Model, this.chatThread);
this.isProcessing = false;
this.StateHasChanged();
// Return the AI response:
return aiText.Text;
}
protected async Task CopyToClipboard(string text)
{
await this.Rust.CopyText2Clipboard(this.JsRuntime, this.Snackbar, text);
}
private static string? GetButtonIcon(string icon)
{
if(string.IsNullOrWhiteSpace(icon))
return null;
return icon;
}
private Task SendToAssistant(SendToAssistant assistant, SendToButton sendToButton)
{
var contentToSend = sendToButton.UseResultingContentBlockData switch
{
false => sendToButton.GetData(),
true => this.resultingContentBlock?.Content switch
{
ContentText textBlock => textBlock.Text,
_ => string.Empty,
},
};
var (eventItem, path) = assistant switch
{
Pages.SendToAssistant.AGENDA_ASSISTANT => (Event.SEND_TO_AGENDA_ASSISTANT, Path.ASSISTANT_AGENDA),
Pages.SendToAssistant.CODING_ASSISTANT => (Event.SEND_TO_CODING_ASSISTANT, Path.ASSISTANT_CODING),
Pages.SendToAssistant.REWRITE_ASSISTANT => (Event.SEND_TO_REWRITE_ASSISTANT, Path.ASSISTANT_REWRITE),
Pages.SendToAssistant.TRANSLATION_ASSISTANT => (Event.SEND_TO_TRANSLATION_ASSISTANT, Path.ASSISTANT_TRANSLATION),
Pages.SendToAssistant.ICON_FINDER_ASSISTANT => (Event.SEND_TO_ICON_FINDER_ASSISTANT, Path.ASSISTANT_ICON_FINDER),
Pages.SendToAssistant.GRAMMAR_SPELLING_ASSISTANT => (Event.SEND_TO_GRAMMAR_SPELLING_ASSISTANT, Path.ASSISTANT_GRAMMAR_SPELLING),
Pages.SendToAssistant.TEXT_SUMMARIZER_ASSISTANT => (Event.SEND_TO_TEXT_SUMMARIZER_ASSISTANT, Path.ASSISTANT_SUMMARIZER),
_ => (Event.NONE, Path.ASSISTANTS),
};
MessageBus.INSTANCE.DeferMessage(this, eventItem, contentToSend);
this.NavigationManager.NavigateTo(path);
return Task.CompletedTask;
}
}
@@ -4,7 +4,7 @@ using Microsoft.AspNetCore.Components.Rendering;
namespace AIStudio.Components;
//
// See https://stackoverflow.com/a/77300384/2258393 for why this class is needed
// See https://stackoverflow.com/a/77300384/2258393 for why this class is necessary
//
public abstract class AssistantBaseCore : AssistantBase
@@ -13,6 +13,8 @@ public partial class Changelog
public static readonly Log[] LOGS =
[
new (171, "v0.8.9, build 171 (2024-08-18 10:35 UTC)", "v0.8.9.md"),
new (170, "v0.8.8, build 170 (2024-08-14 06:30 UTC)", "v0.8.8.md"),
new (169, "v0.8.7, build 169 (2024-08-01 19:08 UTC)", "v0.8.7.md"),
new (168, "v0.8.6, build 168 (2024-08-01 19:50 UTC)", "v0.8.6.md"),
new (167, "v0.8.5, build 167 (2024-07-28 16:44 UTC)", "v0.8.5.md"),
@@ -0,0 +1,24 @@
@typeparam T
<MudButtonGroup Color="@this.Color" Variant="Variant.Filled">
@if (string.IsNullOrWhiteSpace(this.Icon))
{
<MudButton OnClick="() => this.OnClick(this.selectedValue)">
@this.SelectedValueName()
</MudButton>
}
else
{
<MudButton StartIcon="@this.Icon" OnClick="() => this.OnClick(this.selectedValue)">
@this.SelectedValueName()
</MudButton>
}
<MudMenu Icon="@Icons.Material.Filled.ArrowDropDown" Style="align-self: auto;">
@foreach(var item in this.Items)
{
<MudMenuItem OnClick="() => this.SelectItem(item)">
@this.NameFunc(item)
</MudMenuItem>
}
</MudMenu>
</MudButtonGroup>
@@ -0,0 +1,64 @@
using Microsoft.AspNetCore.Components;
namespace AIStudio.Components.Blocks;
public partial class SplitButton<T> : ComponentBase
{
[Parameter]
public Color Color { get; set; } = Color.Default;
[Parameter]
public string Icon { get; set; } = string.Empty;
[Parameter]
public IReadOnlyCollection<T> Items { get; set; } = [];
[Parameter]
public Func<T, string> NameFunc { get; set; } = _ => string.Empty;
[Parameter]
public T? PreselectedValue { get; set; }
[Parameter]
public Func<T?, Task> OnClick { get; set; } = _ => Task.CompletedTask;
/// <summary>
/// What happens when the user selects an item by the dropdown?
/// Immediate = true means that the OnClick event is triggered immediately
/// after the user selects an item. Immediate = false means that the OnClick
/// event is triggered only when the user clicks the button.
/// </summary>
[Parameter]
public bool Immediate { get; set; }
#region Overrides of ComponentBase
protected override async Task OnInitializedAsync()
{
if(this.PreselectedValue is not null)
this.selectedValue = this.PreselectedValue;
else
this.selectedValue = this.Items.FirstOrDefault();
await base.OnInitializedAsync();
}
#endregion
private T? selectedValue;
private string SelectedValueName()
{
if(this.selectedValue is null)
return "Select...";
return this.NameFunc(this.selectedValue!);
}
private void SelectItem(T item)
{
this.selectedValue = item;
if(this.Immediate)
this.OnClick(this.selectedValue);
}
}
@@ -51,12 +51,12 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, IDis
private static readonly IReadOnlyCollection<NavBarItem> NAV_ITEMS = new List<NavBarItem>
{
new("Home", Icons.Material.Filled.Home, Color.Default, "/", true),
new("Chat", Icons.Material.Filled.Chat, Color.Default, "/chat", false),
new("Assistants", Icons.Material.Filled.Apps, Color.Default ,"/assistants", false),
new("Supporters", Icons.Material.Filled.Favorite, Color.Error ,"/supporters", false),
new("About", Icons.Material.Filled.Info, Color.Default ,"/about", false),
new("Settings", Icons.Material.Filled.Settings, Color.Default ,"/settings", false),
new("Home", Icons.Material.Filled.Home, Color.Default, Pages.Path.HOME, true),
new("Chat", Icons.Material.Filled.Chat, Color.Default, Pages.Path.CHAT, false),
new("Assistants", Icons.Material.Filled.Apps, Color.Default, Pages.Path.ASSISTANTS, false),
new("Supporters", Icons.Material.Filled.Favorite, Color.Error, Pages.Path.SUPPORTERS, false),
new("About", Icons.Material.Filled.Info, Color.Default, Pages.Path.ABOUT, false),
new("Settings", Icons.Material.Filled.Settings, Color.Default, Pages.Path.SETTINGS, false),
};
#region Overrides of ComponentBase
@@ -1,4 +1,4 @@
@page "/about"
@attribute [Route(Path.ABOUT)]
@using AIStudio.Tools
<MudText Typo="Typo.h3" Class="mb-2">About MindWork AI Studio</MudText>
@@ -49,6 +49,7 @@
<ThirdPartyComponent Name="flexi_logger" Developer="emabee & Open Source Community" LicenseName="MIT & Apache-2.0" LicenseUrl="https://github.com/emabee/flexi_logger" RepositoryUrl="https://github.com/emabee/flexi_logger" UseCase="This Rust library is used to output the app's messages to the terminal. This is helpful during development and troubleshooting. This feature is initially invisible; when the app is started via the terminal, the messages become visible."/>
<ThirdPartyComponent Name="HtmlAgilityPack" Developer="ZZZ Projects & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/zzzprojects/html-agility-pack/blob/master/LICENSE" RepositoryUrl="https://github.com/zzzprojects/html-agility-pack" UseCase="We use the HtmlAgilityPack to extract content from the web. This is necessary, e.g., when you provide a URL as input for an assistant."/>
<ThirdPartyComponent Name="ReverseMarkdown" Developer="Babu Annamalai & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/mysticmind/reversemarkdown-net/blob/master/LICENSE" RepositoryUrl="https://github.com/mysticmind/reversemarkdown-net" UseCase="This library is used to convert HTML to Markdown. This is necessary, e.g., when you provide a URL as input for an assistant."/>
<ThirdPartyComponent Name="wikEd diff" Developer="Cacycle & Open Source Community" LicenseName="None (public domain)" LicenseUrl="https://en.wikipedia.org/wiki/User:Cacycle/diff#License" RepositoryUrl="https://en.wikipedia.org/wiki/User:Cacycle/diff" UseCase="This library is used to display the differences between two texts. This is necessary, e.g., for the grammar and spelling assistant."/>
</MudGrid>
</ExpansionPanel>
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Verified" HeaderText="License: FSL-1.1-MIT">
@@ -1,4 +1,4 @@
@page "/assistant/agenda"
@attribute [Route(Path.ASSISTANT_AGENDA)]
@using AIStudio.Tools
@inherits AssistantBaseCore
@@ -93,6 +93,14 @@ public partial class AssistantAgenda : AssistantBaseCore
- Mary Jane: Work package 3
""";
protected override IReadOnlyList<IButtonData> FooterButtons =>
[
new SendToButton
{
Self = SendToAssistant.AGENDA_ASSISTANT,
},
];
private string inputTopic = string.Empty;
private string inputName = string.Empty;
private string inputContent = string.Empty;
@@ -145,6 +153,10 @@ public partial class AssistantAgenda : AssistantBaseCore
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.Agenda.PreselectedProvider);
}
var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_AGENDA_ASSISTANT).FirstOrDefault();
if (deferredContent is not null)
this.inputContent = deferredContent;
await base.OnInitializedAsync();
}
@@ -1,4 +1,4 @@
@page "/assistants"
@attribute [Route(Path.ASSISTANTS)]
<MudText Typo="Typo.h3" Class="mb-2 mr-3">
Assistants
@@ -10,23 +10,25 @@
General
</MudText>
<MudStack Row="@true" Wrap="@Wrap.Wrap" Class="mb-3">
<AssistantBlock Name="Text Summarizer" Description="Using a LLM to summarize a given text." Icon="@Icons.Material.Filled.TextSnippet" Link="/assistant/summarizer"/>
<AssistantBlock Name="Translation" Description="Translate text into another language." Icon="@Icons.Material.Filled.Translate" Link="/assistant/translation"/>
<AssistantBlock Name="Text Summarizer" Description="Using a LLM to summarize a given text." Icon="@Icons.Material.Filled.TextSnippet" Link="@Path.ASSISTANT_SUMMARIZER"/>
<AssistantBlock Name="Translation" Description="Translate text into another language." Icon="@Icons.Material.Filled.Translate" Link="@Path.ASSISTANT_TRANSLATION"/>
<AssistantBlock Name="Grammar & Spelling" Description="Check grammar and spelling of a given text." Icon="@Icons.Material.Filled.Edit" Link="@Path.ASSISTANT_GRAMMAR_SPELLING"/>
<AssistantBlock Name="Rewrite & Improve" Description="Rewrite and improve a given text for a chosen style." Icon="@Icons.Material.Filled.Edit" Link="@Path.ASSISTANT_REWRITE"/>
</MudStack>
<MudText Typo="Typo.h4" Class="mb-2 mr-3 mt-6">
Business
</MudText>
<MudStack Row="@true" Wrap="@Wrap.Wrap" Class="mb-3">
<AssistantBlock Name="Agenda Planner" Description="Generate an agenda for a given meeting, seminar, etc." Icon="@Icons.Material.Filled.CalendarToday" Link="/assistant/agenda"/>
<AssistantBlock Name="Icon Finder" Description="Using a LLM to find an icon for a given context." Icon="@Icons.Material.Filled.FindInPage" Link="/assistant/icons"/>
<AssistantBlock Name="Agenda Planner" Description="Generate an agenda for a given meeting, seminar, etc." Icon="@Icons.Material.Filled.CalendarToday" Link="@Path.ASSISTANT_AGENDA"/>
<AssistantBlock Name="Icon Finder" Description="Using a LLM to find an icon for a given context." Icon="@Icons.Material.Filled.FindInPage" Link="@Path.ASSISTANT_ICON_FINDER"/>
</MudStack>
<MudText Typo="Typo.h4" Class="mb-2 mr-3 mt-6">
Software Engineering
</MudText>
<MudStack Row="@true" Wrap="@Wrap.Wrap" Class="mb-3">
<AssistantBlock Name="Coding" Description="Get coding and debugging support from a LLM." Icon="@Icons.Material.Filled.Code" Link="/assistant/coding"/>
<AssistantBlock Name="Coding" Description="Get coding and debugging support from a LLM." Icon="@Icons.Material.Filled.Code" Link="@Path.ASSISTANT_CODING"/>
</MudStack>
</InnerScrolling>
@@ -1,4 +1,4 @@
@page "/chat"
@attribute [Route(Path.CHAT)]
@using AIStudio.Chat
@using AIStudio.Settings.DataModel
@@ -250,11 +250,11 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable
string chatPath;
if (this.chatThread.WorkspaceId == Guid.Empty)
{
chatPath = Path.Join(SettingsManager.DataDirectory, "tempChats", this.chatThread.ChatId.ToString());
chatPath = System.IO.Path.Join(SettingsManager.DataDirectory, "tempChats", this.chatThread.ChatId.ToString());
}
else
{
chatPath = Path.Join(SettingsManager.DataDirectory, "workspaces", this.chatThread.WorkspaceId.ToString(), this.chatThread.ChatId.ToString());
chatPath = System.IO.Path.Join(SettingsManager.DataDirectory, "workspaces", this.chatThread.WorkspaceId.ToString(), this.chatThread.ChatId.ToString());
}
await this.workspaces.DeleteChat(chatPath, askForConfirmation: false, unloadChat: true);
@@ -327,12 +327,12 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable
if (this.chatThread!.WorkspaceId == Guid.Empty)
{
// Case: The chat is stored in the temporary storage:
await this.workspaces.DeleteChat(Path.Join(SettingsManager.DataDirectory, "tempChats", this.chatThread.ChatId.ToString()), askForConfirmation: false, unloadChat: false);
await this.workspaces.DeleteChat(System.IO.Path.Join(SettingsManager.DataDirectory, "tempChats", this.chatThread.ChatId.ToString()), askForConfirmation: false, unloadChat: false);
}
else
{
// Case: The chat is stored in a workspace.
await this.workspaces.DeleteChat(Path.Join(SettingsManager.DataDirectory, "workspaces", this.chatThread.WorkspaceId.ToString(), this.chatThread.ChatId.ToString()), askForConfirmation: false, unloadChat: false);
await this.workspaces.DeleteChat(System.IO.Path.Join(SettingsManager.DataDirectory, "workspaces", this.chatThread.WorkspaceId.ToString(), this.chatThread.ChatId.ToString()), askForConfirmation: false, unloadChat: false);
}
this.chatThread!.WorkspaceId = workspaceId;
@@ -1,4 +1,4 @@
@page "/assistant/coding"
@attribute [Route(Path.ASSISTANT_CODING)]
@inherits AssistantBaseCore
<MudExpansionPanels Class="mb-3">
@@ -1,5 +1,7 @@
using System.Text;
using AIStudio.Tools;
namespace AIStudio.Components.Pages.Coding;
public partial class AssistantCoding : AssistantBaseCore
@@ -24,6 +26,14 @@ public partial class AssistantCoding : AssistantBaseCore
When the user asks in a different language than English, you answer in the same language!
""";
protected override IReadOnlyList<IButtonData> FooterButtons =>
[
new SendToButton
{
Self = SendToAssistant.CODING_ASSISTANT,
},
];
private readonly List<CodingContext> codingContexts = new();
private bool provideCompilerMessages;
private string compilerMessages = string.Empty;
@@ -39,6 +49,10 @@ public partial class AssistantCoding : AssistantBaseCore
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.Coding.PreselectedProvider);
}
var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_CODING_ASSISTANT).FirstOrDefault();
if (deferredContent is not null)
this.questions = deferredContent;
await base.OnInitializedAsync();
}
@@ -0,0 +1,11 @@
@using AIStudio.Tools
@attribute [Route(Path.ASSISTANT_GRAMMAR_SPELLING)]
@inherits AssistantBaseCore
<MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidateText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Your input to check" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Language" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="Custom language" />
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.ProofreadText()">
Proofread
</MudButton>
@@ -0,0 +1,108 @@
using AIStudio.Tools;
namespace AIStudio.Components.Pages.GrammarSpelling;
public partial class AssistantGrammarSpelling : AssistantBaseCore
{
protected override string Title => "Grammar & Spelling Checker";
protected override string Description =>
"""
Check the grammar and spelling of a text.
""";
protected override string SystemPrompt =>
$"""
You are an expert in languages and their rules. For example, you know how US and UK English or German in
Germany and German in Austria differ. You receive text as input. You check the spelling and grammar of
this text according to the rules of {this.SystemPromptLanguage()}. You never add information. You
never ask the user for additional information. You do not attempt to improve the wording of the text.
Your response includes only the corrected text. Do not explain your changes. If no changes are needed,
you return the text unchanged.
""";
protected override bool ShowResult => false;
protected override bool ShowDedicatedProgress => true;
protected override IReadOnlyList<IButtonData> FooterButtons =>
[
new ButtonData("Copy result", Icons.Material.Filled.ContentCopy, Color.Default, string.Empty, () => this.CopyToClipboard(this.correctedText)),
new SendToButton
{
Self = SendToAssistant.GRAMMAR_SPELLING_ASSISTANT,
UseResultingContentBlockData = false,
GetData = () => string.IsNullOrWhiteSpace(this.correctedText) ? this.inputText : this.correctedText
},
];
#region Overrides of ComponentBase
protected override async Task OnInitializedAsync()
{
if (this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)
{
this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedTargetLanguage;
this.customTargetLanguage = this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedOtherLanguage;
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider);
}
var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_GRAMMAR_SPELLING_ASSISTANT).FirstOrDefault();
if (deferredContent is not null)
this.inputText = deferredContent;
await base.OnInitializedAsync();
}
#endregion
private string inputText = string.Empty;
private CommonLanguages selectedTargetLanguage;
private string customTargetLanguage = string.Empty;
private string correctedText = string.Empty;
private string? ValidateText(string text)
{
if(string.IsNullOrWhiteSpace(text))
return "Please provide a text as input. You might copy the desired text from a document or a website.";
return null;
}
private string? ValidateCustomLanguage(string language)
{
if(this.selectedTargetLanguage == CommonLanguages.OTHER && string.IsNullOrWhiteSpace(language))
return "Please provide a custom language.";
return null;
}
private string SystemPromptLanguage()
{
var lang = this.selectedTargetLanguage switch
{
CommonLanguages.AS_IS => "the source language",
CommonLanguages.OTHER => this.customTargetLanguage,
_ => $"{this.selectedTargetLanguage.Name()}",
};
if (string.IsNullOrWhiteSpace(lang))
return "the source language";
return lang;
}
private async Task ProofreadText()
{
await this.form!.Validate();
if (!this.inputIsValid)
return;
this.CreateChatThread();
var time = this.AddUserRequest(this.inputText);
this.correctedText = await this.AddAIResponseAsync(time);
await this.JsRuntime.GenerateAndShowDiff(this.inputText, this.correctedText);
}
}
@@ -1,4 +1,4 @@
@page "/"
@attribute [Route(Path.HOME)]
@using AIStudio.Tools
<MudImage Src="svg/banner.svg" />
@@ -1,4 +1,4 @@
@page "/assistant/icons"
@attribute [Route(Path.ASSISTANT_ICON_FINDER)]
@inherits AssistantBaseCore
<MudTextField T="string" @bind-Text="@this.inputContext" Validation="@this.ValidatingContext" AdornmentIcon="@Icons.Material.Filled.Description" Adornment="Adornment.Start" Label="Your context" Variant="Variant.Outlined" Lines="3" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
@@ -1,3 +1,5 @@
using AIStudio.Tools;
namespace AIStudio.Components.Pages.IconFinder;
public partial class AssistantIconFinder : AssistantBaseCore
@@ -5,21 +7,6 @@ public partial class AssistantIconFinder : AssistantBaseCore
private string inputContext = string.Empty;
private IconSources selectedIconSource;
#region Overrides of ComponentBase
protected override async Task OnInitializedAsync()
{
if (this.SettingsManager.ConfigurationData.IconFinder.PreselectOptions)
{
this.selectedIconSource = this.SettingsManager.ConfigurationData.IconFinder.PreselectedSource;
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.IconFinder.PreselectedProvider);
}
await base.OnInitializedAsync();
}
#endregion
protected override string Title => "Icon Finder";
protected override string Description =>
@@ -40,7 +27,34 @@ public partial class AssistantIconFinder : AssistantBaseCore
related to the keyword "buildings" might be the best match. Provide your keywords in a Markdown list without
quotation marks.
""";
protected override IReadOnlyList<IButtonData> FooterButtons =>
[
new SendToButton
{
Self = SendToAssistant.ICON_FINDER_ASSISTANT,
},
];
#region Overrides of ComponentBase
protected override async Task OnInitializedAsync()
{
if (this.SettingsManager.ConfigurationData.IconFinder.PreselectOptions)
{
this.selectedIconSource = this.SettingsManager.ConfigurationData.IconFinder.PreselectedSource;
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.IconFinder.PreselectedProvider);
}
var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_ICON_FINDER_ASSISTANT).FirstOrDefault();
if (deferredContent is not null)
this.inputContext = deferredContent;
await base.OnInitializedAsync();
}
#endregion
private string? ValidatingContext(string context)
{
if(string.IsNullOrWhiteSpace(context))
@@ -0,0 +1,19 @@
namespace AIStudio.Components.Pages;
public static class Path
{
public const string HOME = "/";
public const string CHAT = "/chat";
public const string ABOUT = "/about";
public const string ASSISTANTS = "/assistants";
public const string SETTINGS = "/settings";
public const string SUPPORTERS = "/supporters";
public const string ASSISTANT_TRANSLATION = "/assistant/translation";
public const string ASSISTANT_REWRITE = "/assistant/rewrite-improve";
public const string ASSISTANT_ICON_FINDER = "/assistant/icons";
public const string ASSISTANT_GRAMMAR_SPELLING = "/assistant/grammar-spelling";
public const string ASSISTANT_SUMMARIZER = "/assistant/summarizer";
public const string ASSISTANT_CODING = "/assistant/coding";
public const string ASSISTANT_AGENDA = "/assistant/agenda";
}
@@ -0,0 +1,12 @@
@using AIStudio.Tools
@attribute [Route(Path.ASSISTANT_REWRITE)]
@inherits AssistantBaseCore
<MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidateText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Your input to improve" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Language" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="Custom language" />
<EnumSelection T="WritingStyles" NameFunc="@(style => style.Name())" @bind-Value="@this.selectedWritingStyle" Icon="@Icons.Material.Filled.Edit" Label="Writing style" AllowOther="@false" />
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.RewriteText()">
Improve
</MudButton>
@@ -0,0 +1,111 @@
using AIStudio.Tools;
namespace AIStudio.Components.Pages.RewriteImprove;
public partial class AssistantRewriteImprove : AssistantBaseCore
{
protected override string Title => "Rewrite & Improve Text";
protected override string Description =>
"""
Rewrite and improve your text. Please note, that the capabilities of the different LLM providers will vary.
""";
protected override string SystemPrompt =>
$"""
You are an expert in language and style. You receive a text as input. First, you review the text. If no
changes are needed, you return the text without modifications. If a change is necessary, you improve the
text. You can also correct spelling and grammar issues. You never add additional information. You never
ask the user for additional information. Your response only contains the improved text. You do not explain
your changes. If no changes are needed, you return the text unchanged.
The style of the text: {this.selectedWritingStyle.Prompt()}. You follow the rules according
to {this.SystemPromptLanguage()} in all your changes.
""";
protected override bool ShowResult => false;
protected override bool ShowDedicatedProgress => true;
protected override IReadOnlyList<IButtonData> FooterButtons =>
[
new ButtonData("Copy result", Icons.Material.Filled.ContentCopy, Color.Default, string.Empty, () => this.CopyToClipboard(this.rewrittenText)),
new SendToButton
{
Self = SendToAssistant.REWRITE_ASSISTANT,
UseResultingContentBlockData = false,
GetData = () => string.IsNullOrWhiteSpace(this.rewrittenText) ? this.inputText : this.rewrittenText,
},
];
#region Overrides of ComponentBase
protected override async Task OnInitializedAsync()
{
if (this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)
{
this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedTargetLanguage;
this.customTargetLanguage = this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedOtherLanguage;
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedProvider);
this.selectedWritingStyle = this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedWritingStyle;
}
var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_REWRITE_ASSISTANT).FirstOrDefault();
if (deferredContent is not null)
this.inputText = deferredContent;
await base.OnInitializedAsync();
}
#endregion
private string inputText = string.Empty;
private CommonLanguages selectedTargetLanguage;
private string customTargetLanguage = string.Empty;
private string rewrittenText = string.Empty;
private WritingStyles selectedWritingStyle;
private string? ValidateText(string text)
{
if(string.IsNullOrWhiteSpace(text))
return "Please provide a text as input. You might copy the desired text from a document or a website.";
return null;
}
private string? ValidateCustomLanguage(string language)
{
if(this.selectedTargetLanguage == CommonLanguages.OTHER && string.IsNullOrWhiteSpace(language))
return "Please provide a custom language.";
return null;
}
private string SystemPromptLanguage()
{
var lang = this.selectedTargetLanguage switch
{
CommonLanguages.AS_IS => "the source language",
CommonLanguages.OTHER => this.customTargetLanguage,
_ => $"{this.selectedTargetLanguage.Name()}",
};
if (string.IsNullOrWhiteSpace(lang))
return "the source language";
return lang;
}
private async Task RewriteText()
{
await this.form!.Validate();
if (!this.inputIsValid)
return;
this.CreateChatThread();
var time = this.AddUserRequest(this.inputText);
this.rewrittenText = await this.AddAIResponseAsync(time);
await this.JsRuntime.GenerateAndShowDiff(this.inputText, this.rewrittenText);
}
}
@@ -0,0 +1,16 @@
namespace AIStudio.Components.Pages.RewriteImprove;
public enum WritingStyles
{
NOT_SPECIFIED = 0,
EVERYDAY,
BUSINESS,
SCIENTIFIC,
JOURNALISTIC,
LITERARY,
TECHNICAL,
MARKETING,
ACADEMIC,
LEGAL,
}
@@ -0,0 +1,40 @@
namespace AIStudio.Components.Pages.RewriteImprove;
public static class WritingStylesExtensions
{
public static string Name(this WritingStyles style)
{
return style switch
{
WritingStyles.EVERYDAY => "Everyday (personal texts, social media)",
WritingStyles.BUSINESS => "Business (business emails, reports, presentations)",
WritingStyles.SCIENTIFIC => "Scientific (scientific papers, research reports)",
WritingStyles.JOURNALISTIC => "Journalistic (magazines, newspapers, news)",
WritingStyles.LITERARY => "Literary (fiction, poetry)",
WritingStyles.TECHNICAL => "Technical (manuals, documentation)",
WritingStyles.MARKETING => "Marketing (advertisements, sales texts)",
WritingStyles.ACADEMIC => "Academic (essays, seminar papers)",
WritingStyles.LEGAL => "Legal (legal texts, contracts)",
_ => "Not specified",
};
}
public static string Prompt(this WritingStyles style)
{
return style switch
{
WritingStyles.EVERYDAY => "Use a everyday style like for personal texts, social media, and informal communication.",
WritingStyles.BUSINESS => "Use a business style like for business emails, reports, and presentations. Most important is clarity and professionalism.",
WritingStyles.SCIENTIFIC => "Use a scientific style like for scientific papers, research reports, and academic writing. Most important is precision and objectivity.",
WritingStyles.JOURNALISTIC => "Use a journalistic style like for magazines, newspapers, and news. Most important is readability and engaging content.",
WritingStyles.LITERARY => "Use a literary style like for fiction, poetry, and creative writing. Most important is creativity and emotional impact.",
WritingStyles.TECHNICAL => "Use a technical style like for manuals, documentation, and technical writing. Most important is clarity and precision.",
WritingStyles.MARKETING => "Use a marketing style like for advertisements, sales texts, and promotional content. Most important is persuasiveness and engagement.",
WritingStyles.ACADEMIC => "Use a academic style like for essays, seminar papers, and academic writing. Most important is clarity and objectivity.",
WritingStyles.LEGAL => "Use a legal style like for legal texts, contracts, and official documents. Most important is precision and legal correctness. Use formal legal language.",
_ => "Keep the style of the text as it is.",
};
}
}
@@ -0,0 +1,14 @@
namespace AIStudio.Components.Pages;
public enum SendToAssistant
{
NONE = 0,
GRAMMAR_SPELLING_ASSISTANT,
ICON_FINDER_ASSISTANT,
REWRITE_ASSISTANT,
TRANSLATION_ASSISTANT,
AGENDA_ASSISTANT,
CODING_ASSISTANT,
TEXT_SUMMARIZER_ASSISTANT,
}
@@ -0,0 +1,20 @@
namespace AIStudio.Components.Pages;
public static class SendToAssistantExtensions
{
public static string Name(this SendToAssistant assistant)
{
return assistant switch
{
SendToAssistant.GRAMMAR_SPELLING_ASSISTANT => "Grammar & Spelling Assistant",
SendToAssistant.TEXT_SUMMARIZER_ASSISTANT => "Text Summarizer Assistant",
SendToAssistant.ICON_FINDER_ASSISTANT => "Icon Finder Assistant",
SendToAssistant.TRANSLATION_ASSISTANT => "Translation Assistant",
SendToAssistant.REWRITE_ASSISTANT => "Rewrite Assistant",
SendToAssistant.AGENDA_ASSISTANT => "Agenda Assistant",
SendToAssistant.CODING_ASSISTANT => "Coding Assistant",
_ => "Send to ...",
};
}
}
@@ -1,4 +1,4 @@
@page "/settings"
@attribute [Route(Path.SETTINGS)]
@using AIStudio.Components.Pages.Coding
@using AIStudio.Components.Pages.TextSummarizer
@using AIStudio.Provider
@@ -106,7 +106,7 @@
<ConfigurationSelect OptionDescription="Preselect the target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Translation.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
@if (this.SettingsManager.ConfigurationData.Translation.PreselectedTargetLanguage is CommonLanguages.OTHER)
{
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Translation.PreselectOtherLanguage = updatedText)"/>
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Translation.PreselectOtherLanguage = updatedText)"/>
}
<ConfigurationProviderSelection Data="@this.availableProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Translation.PreselectedProvider = selectedValue)"/>
</MudPaper>
@@ -168,12 +168,37 @@
<ConfigurationSelect OptionDescription="Preselect the agenda language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesTranslationData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which agenda language should be preselected?"/>
@if (this.SettingsManager.ConfigurationData.Agenda.PreselectedTargetLanguage is CommonLanguages.OTHER)
{
<ConfigurationText OptionDescription="Preselect another agenda language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectedOtherLanguage = updatedText)"/>
<ConfigurationText OptionDescription="Preselect another agenda language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectedOtherLanguage = updatedText)"/>
}
<ConfigurationProviderSelection Data="@this.availableProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectedProvider = selectedValue)"/>
</MudPaper>
</ExpansionPanel>
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Edit" HeaderText="Assistant: Grammar & Spelling Checker">
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
<ConfigurationOption OptionDescription="Preselect grammar & spell checker options?" LabelOn="Grammar & spell checker options are preselected" LabelOff="No grammar & spell checker options are preselected" State="@(() => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the grammar & spell checker options. This is might be useful when you prefer a specific language or LLM model."/>
<ConfigurationSelect OptionDescription="Preselect the target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesTranslationData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
@if (this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedTargetLanguage is CommonLanguages.OTHER)
{
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedOtherLanguage = updatedText)"/>
}
<ConfigurationProviderSelection Data="@this.availableProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider = selectedValue)"/>
</MudPaper>
</ExpansionPanel>
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Edit" HeaderText="Assistant: Rewrite & Improve Text">
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
<ConfigurationOption OptionDescription="Preselect rewrite & improve text options?" LabelOn="Rewrite & improve text options are preselected" LabelOff="No rewrite & improve text options are preselected" State="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the rewrite & improve text options. This is might be useful when you prefer a specific language or LLM model."/>
<ConfigurationSelect OptionDescription="Preselect the target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesTranslationData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
@if (this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedTargetLanguage is CommonLanguages.OTHER)
{
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedOtherLanguage = updatedText)"/>
}
<ConfigurationSelect OptionDescription="Preselect a writing style" Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedWritingStyle)" Data="@ConfigurationSelectDataFactory.GetWritingStylesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedWritingStyle = selectedValue)" OptionHelp="Which writing style should be preselected?"/>
<ConfigurationProviderSelection Data="@this.availableProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedProvider = selectedValue)"/>
</MudPaper>
</ExpansionPanel>
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.TextFields" HeaderText="Agent: Text Content Cleaner Options">
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
<MudText Typo="Typo.body1" Class="mb-3">
@@ -1,4 +1,4 @@
@page "/Supporters"
@attribute [Route(Path.SUPPORTERS)]
<MudText Typo="Typo.h3" Class="mb-2">Supporters</MudText>
@@ -1,4 +1,4 @@
@page "/assistant/summarizer"
@attribute [Route(Path.ASSISTANT_SUMMARIZER)]
@using AIStudio.Tools
@inherits AssistantBaseCore
@@ -23,6 +23,14 @@ public partial class AssistantTextSummarizer : AssistantBaseCore
a summary with the requested complexity. In any case, do not add any information.
""";
protected override IReadOnlyList<IButtonData> FooterButtons =>
[
new SendToButton
{
Self = SendToAssistant.TEXT_SUMMARIZER_ASSISTANT,
},
];
private string inputText = string.Empty;
private bool isAgentRunning;
private CommonLanguages selectedTargetLanguage;
@@ -43,6 +51,10 @@ public partial class AssistantTextSummarizer : AssistantBaseCore
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedProvider);
}
var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_TEXT_SUMMARIZER_ASSISTANT).FirstOrDefault();
if (deferredContent is not null)
this.inputText = deferredContent;
await base.OnInitializedAsync();
}
@@ -1,4 +1,4 @@
@page "/assistant/translation"
@attribute [Route(Path.ASSISTANT_TRANSLATION)]
@using AIStudio.Tools
@inherits AssistantBaseCore
@@ -19,6 +19,14 @@ public partial class AssistantTranslation : AssistantBaseCore
language requires, e.g., shorter sentences, you should split the text into shorter sentences.
""";
protected override IReadOnlyList<IButtonData> FooterButtons =>
[
new SendToButton
{
Self = SendToAssistant.TRANSLATION_ASSISTANT,
},
];
private bool liveTranslation;
private bool isAgentRunning;
private string inputText = string.Empty;
@@ -38,6 +46,10 @@ public partial class AssistantTranslation : AssistantBaseCore
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.Translation.PreselectedProvider);
}
var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_TRANSLATION_ASSISTANT).FirstOrDefault();
if (deferredContent is not null)
this.inputText = deferredContent;
await base.OnInitializedAsync();
}
@@ -69,6 +81,7 @@ public partial class AssistantTranslation : AssistantBaseCore
private async Task TranslateText(bool force)
{
await this.form!.Validate();
if (!this.inputIsValid)
return;
@@ -46,8 +46,8 @@
<ItemGroup>
<PackageReference Include="HtmlAgilityPack" Version="1.11.62" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="8.0.7" />
<PackageReference Include="MudBlazor" Version="7.5.0" />
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="8.0.8" />
<PackageReference Include="MudBlazor" Version="7.6.0" />
<PackageReference Include="MudBlazor.Markdown" Version="1.0.2" />
<PackageReference Include="ReverseMarkdown" Version="4.6.0" />
</ItemGroup>
@@ -1,6 +1,7 @@
using AIStudio.Components.Pages.Agenda;
using AIStudio.Components.Pages.Coding;
using AIStudio.Components.Pages.IconFinder;
using AIStudio.Components.Pages.RewriteImprove;
using AIStudio.Components.Pages.TextSummarizer;
using AIStudio.Settings.DataModel;
using AIStudio.Tools;
@@ -99,4 +100,10 @@ public static class ConfigurationSelectDataFactory
foreach (var number in Enum.GetValues<NumberParticipants>())
yield return new(number.Name(), number);
}
public static IEnumerable<ConfigurationSelectData<WritingStyles>> GetWritingStylesData()
{
foreach (var style in Enum.GetValues<WritingStyles>())
yield return new(style.Name(), style);
}
}
@@ -38,4 +38,8 @@ public sealed class Data
public DataTextContentCleaner TextContentCleaner { get; init; } = new();
public DataAgenda Agenda { get; init; } = new();
public DataGrammarSpelling GrammarSpelling { get; init; } = new();
public DataRewriteImprove RewriteImprove { get; init; } = new();
}
@@ -0,0 +1,26 @@
using AIStudio.Tools;
namespace AIStudio.Settings.DataModel;
public sealed class DataGrammarSpelling
{
/// <summary>
/// Preselect any rewrite options?
/// </summary>
public bool PreselectOptions { get; set; }
/// <summary>
/// Preselect the target language?
/// </summary>
public CommonLanguages PreselectedTargetLanguage { get; set; }
/// <summary>
/// Preselect any other language?
/// </summary>
public string PreselectedOtherLanguage { get; set; } = string.Empty;
/// <summary>
/// Preselect a provider?
/// </summary>
public string PreselectedProvider { get; set; } = string.Empty;
}
@@ -0,0 +1,32 @@
using AIStudio.Components.Pages.RewriteImprove;
using AIStudio.Tools;
namespace AIStudio.Settings.DataModel;
public sealed class DataRewriteImprove
{
/// <summary>
/// Preselect any rewrite options?
/// </summary>
public bool PreselectOptions { get; set; }
/// <summary>
/// Preselect the target language?
/// </summary>
public CommonLanguages PreselectedTargetLanguage { get; set; }
/// <summary>
/// Preselect any other language?
/// </summary>
public string PreselectedOtherLanguage { get; set; } = string.Empty;
/// <summary>
/// Preselect any writing style?
/// </summary>
public WritingStyles PreselectedWritingStyle { get; set; }
/// <summary>
/// Preselect a provider?
/// </summary>
public string PreselectedProvider { get; set; } = string.Empty;
}
@@ -0,0 +1,6 @@
namespace AIStudio.Tools;
public readonly record struct ButtonData(string Text, string Icon, Color Color, string Tooltip, Func<Task> AsyncAction) : IButtonData
{
public ButtonTypes Type => ButtonTypes.BUTTON;
}
@@ -0,0 +1,7 @@
namespace AIStudio.Tools;
public enum ButtonTypes
{
BUTTON = 0,
SEND_TO,
}
@@ -42,4 +42,12 @@ public static class CommonLanguageExtensions
return language.Name();
}
public static string NameSelectingOptional(this CommonLanguages language)
{
if(language is CommonLanguages.AS_IS)
return "Do not specify the language";
return language.Name();
}
}
+9
View File
@@ -15,4 +15,13 @@ public enum Event
// Chat events:
HAS_CHAT_UNSAVED_CHANGES,
RESET_CHAT_STATE,
// Send assistant events:
SEND_TO_GRAMMAR_SPELLING_ASSISTANT,
SEND_TO_ICON_FINDER_ASSISTANT,
SEND_TO_REWRITE_ASSISTANT,
SEND_TO_TRANSLATION_ASSISTANT,
SEND_TO_AGENDA_ASSISTANT,
SEND_TO_CODING_ASSISTANT,
SEND_TO_TEXT_SUMMARIZER_ASSISTANT,
}
@@ -0,0 +1,6 @@
namespace AIStudio.Tools;
public interface IButtonData
{
public ButtonTypes Type { get; }
}
@@ -0,0 +1,11 @@
using AIStudio.Components;
namespace AIStudio.Tools;
public static class JsRuntimeExtensions
{
public static async Task GenerateAndShowDiff(this IJSRuntime jsRuntime, string text1, string text2)
{
await jsRuntime.InvokeVoidAsync("generateDiff", text1, text2, AssistantBase.ASSISTANT_RESULT_DIV_ID, AssistantBase.AFTER_RESULT_DIV_ID);
}
}
@@ -11,6 +11,7 @@ public sealed class MessageBus
private readonly ConcurrentDictionary<IMessageBusReceiver, ComponentBase[]> componentFilters = new();
private readonly ConcurrentDictionary<IMessageBusReceiver, Event[]> componentEvents = new();
private readonly ConcurrentDictionary<Event, ConcurrentQueue<Message>> deferredMessages = new();
private readonly ConcurrentQueue<Message> messageQueue = new();
private readonly SemaphoreSlim sendingSemaphore = new(1, 1);
@@ -65,6 +66,24 @@ public sealed class MessageBus
}
}
public void DeferMessage<T>(ComponentBase? sendingComponent, Event triggeredEvent, T? data = default)
{
if (this.deferredMessages.TryGetValue(triggeredEvent, out var queue))
queue.Enqueue(new Message(sendingComponent, triggeredEvent, data));
else
{
this.deferredMessages[triggeredEvent] = new();
this.deferredMessages[triggeredEvent].Enqueue(new Message(sendingComponent, triggeredEvent, data));
}
}
public IEnumerable<T?> CheckDeferredMessages<T>(Event triggeredEvent)
{
if (this.deferredMessages.TryGetValue(triggeredEvent, out var queue))
while (queue.TryDequeue(out var message))
yield return message.Data is T data ? data : default;
}
public async Task<TResult?> SendMessageUseFirstResult<TPayload, TResult>(ComponentBase? sendingComponent, Event triggeredEvent, TPayload? data = default)
{
foreach (var (receiver, componentFilter) in this.componentFilters)
@@ -0,0 +1,15 @@
using AIStudio.Components.Pages;
namespace AIStudio.Tools;
public readonly record struct SendToButton() : IButtonData
{
public ButtonTypes Type => ButtonTypes.SEND_TO;
public Func<string> GetData { get; init; } = () => string.Empty;
public bool UseResultingContentBlockData { get; init; } = true;
public SendToAssistant Self { get; init; } = SendToAssistant.NONE;
}
+10 -10
View File
@@ -10,24 +10,24 @@
},
"Microsoft.Extensions.FileProviders.Embedded": {
"type": "Direct",
"requested": "[8.0.7, )",
"resolved": "8.0.7",
"contentHash": "ABsn0T09b5lzVNbOcuRc10+kNZkO+RGtZWfzqVay0Ah+/ouhEvG7JrXc+9+7zFgoPuH4E4N6+uWfTp+pJqMeGw==",
"requested": "[8.0.8, )",
"resolved": "8.0.8",
"contentHash": "fefQMlaOIQnc7cn7R/GWCwnA6X0tv5pB9ZKIR6I1JZPmYcoCNY7HtLt0bJPMj+F0StrMkwTk2cPtMGtr9zhkoA==",
"dependencies": {
"Microsoft.Extensions.FileProviders.Abstractions": "8.0.0"
}
},
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
"requested": "[8.0.7, )",
"resolved": "8.0.7",
"contentHash": "iI52ptEKby2ymQ6B7h4TWbFmm85T4VvLgc/HvS45Yr3lgi4IIFbQtjON3bQbX/Vc94jXNSLvrDOp5Kh7SJyFYQ=="
"requested": "[8.0.8, )",
"resolved": "8.0.8",
"contentHash": "P8wR6MUWwYXIjPJuBaZgo5zlI/GWI6QEAo6NyVIbPefa9CCkohYu7dP2rD/mrqnjEqfRHyl+h9VZrDoGpELqYg=="
},
"MudBlazor": {
"type": "Direct",
"requested": "[7.5.0, )",
"resolved": "7.5.0",
"contentHash": "yW1+6b9bG0OjMa7FSUnYZ2D9v09cTru8Hri1cVekRzdQpA/rieSgbfrWY9KQOzMW+1LbOySTEEipun6GCarQNg==",
"requested": "[7.6.0, )",
"resolved": "7.6.0",
"contentHash": "6UVQ7TvIw/czNyjmqdUGYS+Fk3PJTvbhFy4/agqm2pzwam31lYJbZXPYr5w7CG4aw9QTgj02ajd6xTZaeROiiA==",
"dependencies": {
"Microsoft.AspNetCore.Components": "8.0.6",
"Microsoft.AspNetCore.Components.Web": "8.0.6",
@@ -178,6 +178,6 @@
"contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA=="
}
},
"net8.0/osx-arm64": {}
"net8.0/osx-x64": {}
}
}
+19
View File
@@ -0,0 +1,19 @@
window.generateDiff = function (text1, text2, divDiff, divLegend) {
let wikEdDiff = new WikEdDiff();
let targetDiv = document.getElementById(divDiff)
targetDiv.innerHTML = wikEdDiff.diff(text1, text2);
targetDiv.classList.add('mud-typography-body1');
let legend = document.getElementById(divLegend);
legend.innerHTML = `
<div class="legend mt-2">
<h3>Legend</h3>
<ul class="mt-2">
<li><span class="wikEdDiffMarkRight" title="Moved block" id="wikEdDiffMark999" onmouseover="wikEdDiffBlockHandler(undefined, this, 'mouseover');"></span> Original block position</li>
<li><span title="+" class="wikEdDiffInsert">Inserted<span class="wikEdDiffSpace"><span class="wikEdDiffSpaceSymbol"></span> </span>text<span class="wikEdDiffNewline"> </span></span></li>
<li><span title="−" class="wikEdDiffDelete">Deleted<span class="wikEdDiffSpace"><span class="wikEdDiffSpaceSymbol"></span> </span>text<span class="wikEdDiffNewline"> </span></span></li>
<li><span class="wikEdDiffBlockLeft" title="◀" id="wikEdDiffBlock999" onmouseover="wikEdDiffBlockHandler(undefined, this, 'mouseover');">Moved<span class="wikEdDiffSpace"><span class="wikEdDiffSpaceSymbol"></span> </span>block<span class="wikEdDiffNewline"> </span></span></li>
</ul>
</div>
`;
}
@@ -0,0 +1,7 @@
# v0.8.8, build 170 (2024-08-14 06:30 UTC)
- Added a grammar and spell checker assistant
- Added a rewrite and text improvement assistant
- Fixed validation for the translation assistant
- Upgraded MudBlazor to v7.6.0
- Upgraded Rust to v1.80.1
- Upgraded .NET to v8.0.8
@@ -0,0 +1,5 @@
# v0.8.9, build 171 (2024-08-18 10:35 UTC)
- Added the possibility to send an assistant's result to another assistant
- Refactored page paths
- Refactored assistant footer buttons
- Refactored message bus to support deferred messages
+2
View File
@@ -0,0 +1,2 @@
// @license released into the public domain
"use strict";var wikEdDiffConfig,WED,WikEdDiff=function(){this.config={fullDiff:!1,showBlockMoves:!0,charDiff:!0,repeatedDiff:!0,recursiveDiff:!0,recursionMax:10,unlinkBlocks:!0,unlinkMax:5,blockMinLength:3,coloredBlocks:!1,noUnicodeSymbols:!1,stripTrailingNewline:!0,debug:!1,timer:!1,unitTesting:!1,regExpLetters:"a-zA-Z0-9"+"00AA00B500BA00C0-00D600D8-00F600F8-02C102C6-02D102E0-02E402EC02EE0370-037403760377037A-037D03860388-038A038C038E-03A103A3-03F503F7-0481048A-05270531-055605590561-058705D0-05EA05F0-05F20620-064A066E066F0671-06D306D506E506E606EE06EF06FA-06FC06FF07100712-072F074D-07A507B107CA-07EA07F407F507FA0800-0815081A082408280840-085808A008A2-08AC0904-0939093D09500958-09610971-09770979-097F0985-098C098F09900993-09A809AA-09B009B209B6-09B909BD09CE09DC09DD09DF-09E109F009F10A05-0A0A0A0F0A100A13-0A280A2A-0A300A320A330A350A360A380A390A59-0A5C0A5E0A72-0A740A85-0A8D0A8F-0A910A93-0AA80AAA-0AB00AB20AB30AB5-0AB90ABD0AD00AE00AE10B05-0B0C0B0F0B100B13-0B280B2A-0B300B320B330B35-0B390B3D0B5C0B5D0B5F-0B610B710B830B85-0B8A0B8E-0B900B92-0B950B990B9A0B9C0B9E0B9F0BA30BA40BA8-0BAA0BAE-0BB90BD00C05-0C0C0C0E-0C100C12-0C280C2A-0C330C35-0C390C3D0C580C590C600C610C85-0C8C0C8E-0C900C92-0CA80CAA-0CB30CB5-0CB90CBD0CDE0CE00CE10CF10CF20D05-0D0C0D0E-0D100D12-0D3A0D3D0D4E0D600D610D7A-0D7F0D85-0D960D9A-0DB10DB3-0DBB0DBD0DC0-0DC60E01-0E300E320E330E40-0E460E810E820E840E870E880E8A0E8D0E94-0E970E99-0E9F0EA1-0EA30EA50EA70EAA0EAB0EAD-0EB00EB20EB30EBD0EC0-0EC40EC60EDC-0EDF0F000F40-0F470F49-0F6C0F88-0F8C1000-102A103F1050-1055105A-105D106110651066106E-10701075-1081108E10A0-10C510C710CD10D0-10FA10FC-1248124A-124D1250-12561258125A-125D1260-1288128A-128D1290-12B012B2-12B512B8-12BE12C012C2-12C512C8-12D612D8-13101312-13151318-135A1380-138F13A0-13F41401-166C166F-167F1681-169A16A0-16EA1700-170C170E-17111720-17311740-17511760-176C176E-17701780-17B317D717DC1820-18771880-18A818AA18B0-18F51900-191C1950-196D1970-19741980-19AB19C1-19C71A00-1A161A20-1A541AA71B05-1B331B45-1B4B1B83-1BA01BAE1BAF1BBA-1BE51C00-1C231C4D-1C4F1C5A-1C7D1CE9-1CEC1CEE-1CF11CF51CF61D00-1DBF1E00-1F151F18-1F1D1F20-1F451F48-1F4D1F50-1F571F591F5B1F5D1F5F-1F7D1F80-1FB41FB6-1FBC1FBE1FC2-1FC41FC6-1FCC1FD0-1FD31FD6-1FDB1FE0-1FEC1FF2-1FF41FF6-1FFC2071207F2090-209C21022107210A-211321152119-211D212421262128212A-212D212F-2139213C-213F2145-2149214E218321842C00-2C2E2C30-2C5E2C60-2CE42CEB-2CEE2CF22CF32D00-2D252D272D2D2D30-2D672D6F2D80-2D962DA0-2DA62DA8-2DAE2DB0-2DB62DB8-2DBE2DC0-2DC62DC8-2DCE2DD0-2DD62DD8-2DDE2E2F300530063031-3035303B303C3041-3096309D-309F30A1-30FA30FC-30FF3105-312D3131-318E31A0-31BA31F0-31FF3400-4DB54E00-9FCCA000-A48CA4D0-A4FDA500-A60CA610-A61FA62AA62BA640-A66EA67F-A697A6A0-A6E5A717-A71FA722-A788A78B-A78EA790-A793A7A0-A7AAA7F8-A801A803-A805A807-A80AA80C-A822A840-A873A882-A8B3A8F2-A8F7A8FBA90A-A925A930-A946A960-A97CA984-A9B2A9CFAA00-AA28AA40-AA42AA44-AA4BAA60-AA76AA7AAA80-AAAFAAB1AAB5AAB6AAB9-AABDAAC0AAC2AADB-AADDAAE0-AAEAAAF2-AAF4AB01-AB06AB09-AB0EAB11-AB16AB20-AB26AB28-AB2EABC0-ABE2AC00-D7A3D7B0-D7C6D7CB-D7FBF900-FA6DFA70-FAD9FB00-FB06FB13-FB17FB1DFB1F-FB28FB2A-FB36FB38-FB3CFB3EFB40FB41FB43FB44FB46-FBB1FBD3-FD3DFD50-FD8FFD92-FDC7FDF0-FDFBFE70-FE74FE76-FEFCFF21-FF3AFF41-FF5AFF66-FFBEFFC2-FFC7FFCA-FFCFFFD2-FFD7FFDA-FFDC".replace(/(\w{4})/g,"\\u$1"),regExpNewLines:"\\u0085\\u2028",regExpNewLinesAll:"\\n\\r\\u0085\\u2028",regExpBlanks:" \\t\\x0b\\u2000-\\u200b\\u202f\\u205f\\u3000",regExpFullStops:"\\u0589\\u06D4\\u0701\\u0702\\u0964\\u0DF4\\u1362\\u166E\\u1803\\u1809\\u2CF9\\u2CFE\\u2E3C\\u3002\\uA4FF\\uA60E\\uA6F3\\uFE52\\uFF0E\\uFF61",regExpNewParagraph:"\\f\\u2029",regExpExclamationMarks:"\\u01C3\\u01C3\\u01C3\\u055C\\u055C\\u07F9\\u1944\\u1944\\u203C\\u203C\\u2048\\u2048\\uFE15\\uFE57\\uFF01",regExpQuestionMarks:"\\u037E\\u055E\\u061F\\u1367\\u1945\\u2047\\u2049\\u2CFA\\u2CFB\\u2E2E\\uA60F\\uA6F7\\uFE56\\uFF1F",clipHeadingLeft:1500,clipParagraphLeftMax:1500,clipParagraphLeftMin:500,clipLineLeftMax:1e3,clipLineLeftMin:500,clipBlankLeftMax:1e3,clipBlankLeftMin:500,clipCharsLeft:500,clipHeadingRight:1500,clipParagraphRightMax:1500,clipParagraphRightMin:500,clipLineRightMax:1e3,clipLineRightMin:500,clipBlankRightMax:1e3,clipBlankRightMin:500,clipCharsRight:500,clipLinesRightMax:10,clipLinesLeftMax:10,clipSkipLines:5,clipSkipChars:1e3,cssMarkLeft:"◀",cssMarkRight:"▶",stylesheet:'.wikEdDiffInsert {font-weight: bold; background-color: #bbddff; color: #222; border-radius: 0.25em; padding: 0.2em 1px; } .wikEdDiffInsertBlank { background-color: #66bbff; } .wikEdDiffFragment:hover .wikEdDiffInsertBlank { background-color: #bbddff; } .wikEdDiffDelete {font-weight: bold; background-color: #ffe49c; color: #222; border-radius: 0.25em; padding: 0.2em 1px; } .wikEdDiffDeleteBlank { background-color: #ffd064; } .wikEdDiffFragment:hover .wikEdDiffDeleteBlank { background-color: #ffe49c; } .wikEdDiffBlock {font-weight: bold; background-color: #e8e8e8; border-radius: 0.25em; padding: 0.2em 1px; margin: 0 1px; } .wikEdDiffBlock { color: #000; } .wikEdDiffBlock0 { background-color: #ffff80; } .wikEdLine truncated
@@ -2,4 +2,4 @@
* MudBlazor (https://mudblazor.com/)
* Copyright (c) 2021 MudBlazor
* Licensed under MIT (https://github.com/MudBlazor/MudBlazor/blob/master/LICENSE)
*/.mud-primary{background-color:var(--mud-palette-primary) !important}.mud-primary-text{color:var(--mud-palette-primary) !important;--mud-ripple-color: var(--mud-palette-primary) !important}.mud-primary-hover{background-color:var(--mud-palette-primary-hover) !important}@media(hover: hover)and (pointer: fine){.hover\:mud-primary-hover:hover{background-color:var(--mud-palette-primary-hover) !important}}.hover\:mud-primary-hover:focus-visible,.hover\:mud-primary-hover:active{background-color:var(--mud-palette-primary-hover) !important}.mud-border-primary{border-color:var(--mud-palette-primary) !important}.mud-theme-primary{color:var(--mud-palette-primary-text) !important;background-color:var(--mud-palette-primary) !important}.mud-secondary{background-color:var(--mud-palette-secondary) !important}.mud-secondary-text{color:var(--mud-palette-secondary) !important;--mud-ripple-color: var(--mud-palette-secondary) !important}.mud-secondary-hover{background-color:var(--mud-palette-secondary-hover) !important}@media(hover: hover)and (pointer: fine){.hover\:mud-secondary-hover:hover{background-color:var(--mud-palette-secondary-hover) !important}}.hover\:mud-secondary-hover:focus-visible,.hover\:mud-secondary-hover:active{background-color:var(--mud-palette-secondary-hover) !important}.mud-border-secondary{border-color:var(--mud-palette-secondary) !important}.mud-theme-secondary{color:var(--mud-palette-secondary-text) !important;background-color:var(--mud-palette-secondary) !important}.mud-tertiary{background-color:var(--mud-palette-tertiary) !important}.mud-tertiary-text{color:var(--mud-palette-tertiary) !important;--mud-ripple-color: var(--mud-palette-tertiary) !important}.mud-tertiary-hover{background-color:var(--mud-palette-tertiary-hover) !important}@media(hover: hover)and (pointer: fine){.hover\:mud-tertiary-hover:hover{background-color:var(--mud-palette-tertiary-hover) !important}}.hover\:mud-tertiary-hover:focus-visible,.hover\:mud-tertiary-hover:active{background-color:var(--mud-palette-tertiary-hover) !important}.mud-border-tertiary{border-color:var(--mud-palette-tertiary) !important}.mud-theme-tertiary{color:var(--mud-palette-tertiary-text) !important;background-color:var(--mud-palette-tertiary) !important}.mud-info{background-color:var(--mud-palette-info) !important}.mud-info-text{color:var(--mud-palette-info) !important;--mud-ripple-color: var(--mud-palette-info) !important}.mud-info-hover{background-color:var(--mud-palette-info-hover) !important}@media(hover: hover)and (pointer: fine){.hover\:mud-info-hover:hover{background-color:var(--mud-palette-info-hover) !important}}.hover\:mud-info-hover:focus-visible,.hover\:mud-info-hover:active{background-color:var(--mud-palette-info-hover) !important}.mud-border-info{border-color:var(--mud-palette-info) !important}.mud-theme-info{color:var(--mud-palette-info-text) !important;background-color:var(--mud-palette-info) !important}.mud-success{background-color:var(--mud-palette-success) !important}.mud-success-text{color:var(--mud-palette-success) !important;--mud-ripple-color: var(--mud-palette-success) !important}.mud-success-hover{background-color:var(--mud-palette-success-hover) !important}@media(hover: hover)and (pointer: fine){.hover\:mud-success-hover:hover{background-color:var(--mud-palette-success-hover) !important}}.hover\:mud-success-hover:focus-visible,.hover\:mud-success-hover:active{background-color:var(--mud-palette-success-hover) !important}.mud-border-success{border-color:var(--mud-palette-success) !important}.mud-theme-success{color:var(--mud-palette-success-text) !important;background-color:var(--mud-palette-success) !important}.mud-warning{background-color:var(--mud-palette-warning) !important}.mud-warning-text{color:var(--mud-palette-warning) !important;--mud-ripple-color: var(--mud-palette-warning) !important}.mud-warning-hover{background-color:var(--mud-palette-warning-hover) !important}@media(hover: hover)and (pointer: fine){.hover\:mud-warning-hover:hover{background-color:var(--mud-palette-warning-hover) !important}}.hover\:mud-warning-hover:focus-visible,.hover\:mud-warning-hover:active{background-color:var(--mud-palette-warning-hover) !important}.mud-border-warning{border-color:var(--mud-palette-warning) !important}.mud-theme-warning{color:var(--mud-palette-warning-text) !important;background-color:var(--mud-palette-warning) !important}.mud-error{background-color:var(--mud-palette-error) !important}.mud-error-text{color:var(--mud-palette-error) !important;--mud-ripple-color: var(--mud-palette-error) !important}.mud-error-hover{background-color:var(--mud-palette-error-hover) !important}@media(hover: hover)and (pointer: fine){.hover\:mud-error-hover:hover{background-color:var(--mud-palette-error-hover) !important}}.hover\:mud-error-hover:focus-visible,.hover\:mud-error-hover:active{background-color:var(--mud-palette-error-hover) !important}.mud-border-error{border-color:var(--mud-palette-error) !important}.mud-theme-error{color:var(--mud-paleLine truncated
*/.mud-primary{background-color:var(--mud-palette-primary) !important}.mud-primary-text{color:var(--mud-palette-primary) !important;--mud-ripple-color: var(--mud-palette-primary) !important}.mud-primary-hover{background-color:var(--mud-palette-primary-hover) !important}@media(hover: hover)and (pointer: fine){.hover\:mud-primary-hover:hover{background-color:var(--mud-palette-primary-hover) !important}}.hover\:mud-primary-hover:focus-visible,.hover\:mud-primary-hover:active{background-color:var(--mud-palette-primary-hover) !important}.mud-border-primary{border-color:var(--mud-palette-primary) !important}.mud-theme-primary{color:var(--mud-palette-primary-text) !important;background-color:var(--mud-palette-primary) !important}.mud-secondary{background-color:var(--mud-palette-secondary) !important}.mud-secondary-text{color:var(--mud-palette-secondary) !important;--mud-ripple-color: var(--mud-palette-secondary) !important}.mud-secondary-hover{background-color:var(--mud-palette-secondary-hover) !important}@media(hover: hover)and (pointer: fine){.hover\:mud-secondary-hover:hover{background-color:var(--mud-palette-secondary-hover) !important}}.hover\:mud-secondary-hover:focus-visible,.hover\:mud-secondary-hover:active{background-color:var(--mud-palette-secondary-hover) !important}.mud-border-secondary{border-color:var(--mud-palette-secondary) !important}.mud-theme-secondary{color:var(--mud-palette-secondary-text) !important;background-color:var(--mud-palette-secondary) !important}.mud-tertiary{background-color:var(--mud-palette-tertiary) !important}.mud-tertiary-text{color:var(--mud-palette-tertiary) !important;--mud-ripple-color: var(--mud-palette-tertiary) !important}.mud-tertiary-hover{background-color:var(--mud-palette-tertiary-hover) !important}@media(hover: hover)and (pointer: fine){.hover\:mud-tertiary-hover:hover{background-color:var(--mud-palette-tertiary-hover) !important}}.hover\:mud-tertiary-hover:focus-visible,.hover\:mud-tertiary-hover:active{background-color:var(--mud-palette-tertiary-hover) !important}.mud-border-tertiary{border-color:var(--mud-palette-tertiary) !important}.mud-theme-tertiary{color:var(--mud-palette-tertiary-text) !important;background-color:var(--mud-palette-tertiary) !important}.mud-info{background-color:var(--mud-palette-info) !important}.mud-info-text{color:var(--mud-palette-info) !important;--mud-ripple-color: var(--mud-palette-info) !important}.mud-info-hover{background-color:var(--mud-palette-info-hover) !important}@media(hover: hover)and (pointer: fine){.hover\:mud-info-hover:hover{background-color:var(--mud-palette-info-hover) !important}}.hover\:mud-info-hover:focus-visible,.hover\:mud-info-hover:active{background-color:var(--mud-palette-info-hover) !important}.mud-border-info{border-color:var(--mud-palette-info) !important}.mud-theme-info{color:var(--mud-palette-info-text) !important;background-color:var(--mud-palette-info) !important}.mud-success{background-color:var(--mud-palette-success) !important}.mud-success-text{color:var(--mud-palette-success) !important;--mud-ripple-color: var(--mud-palette-success) !important}.mud-success-hover{background-color:var(--mud-palette-success-hover) !important}@media(hover: hover)and (pointer: fine){.hover\:mud-success-hover:hover{background-color:var(--mud-palette-success-hover) !important}}.hover\:mud-success-hover:focus-visible,.hover\:mud-success-hover:active{background-color:var(--mud-palette-success-hover) !important}.mud-border-success{border-color:var(--mud-palette-success) !important}.mud-theme-success{color:var(--mud-palette-success-text) !important;background-color:var(--mud-palette-success) !important}.mud-warning{background-color:var(--mud-palette-warning) !important}.mud-warning-text{color:var(--mud-palette-warning) !important;--mud-ripple-color: var(--mud-palette-warning) !important}.mud-warning-hover{background-color:var(--mud-palette-warning-hover) !important}@media(hover: hover)and (pointer: fine){.hover\:mud-warning-hover:hover{background-color:var(--mud-palette-warning-hover) !important}}.hover\:mud-warning-hover:focus-visible,.hover\:mud-warning-hover:active{background-color:var(--mud-palette-warning-hover) !important}.mud-border-warning{border-color:var(--mud-palette-warning) !important}.mud-theme-warning{color:var(--mud-palette-warning-text) !important;background-color:var(--mud-palette-warning) !important}.mud-error{background-color:var(--mud-palette-error) !important}.mud-error-text{color:var(--mud-palette-error) !important;--mud-ripple-color: var(--mud-palette-error) !important}.mud-error-hover{background-color:var(--mud-palette-error-hover) !important}@media(hover: hover)and (pointer: fine){.hover\:mud-error-hover:hover{background-color:var(--mud-palette-error-hover) !important}}.hover\:mud-error-hover:focus-visible,.hover\:mud-error-hover:active{background-color:var(--mud-palette-error-hover) !important}.mud-border-error{border-color:var(--mud-palette-error) !important}.mud-theme-error{color:var(--mud-paleLine truncated
+160 -161
View File
@@ -1,12 +1,154 @@
window.getTabbableElements=(element)=>{return element.querySelectorAll("a[href]:not([tabindex='-1']),"+"area[href]:not([tabindex='-1']),"+"button:not([disabled]):not([tabindex='-1']),"+"input:not([disabled]):not([tabindex='-1']):not([type='hidden']),"+"select:not([disabled]):not([tabindex='-1']),"+"textarea:not([disabled]):not([tabindex='-1']),"+"iframe:not([tabindex='-1']),"+"details:not([tabindex='-1']),"+"[tabindex]:not([tabindex='-1']),"+"[contentEditable=true]:not([tabindex='-1'])");};window.serializeParameter=(data,spec)=>{if(typeof data=="undefined"||data===null){return null;}
if(typeof data==="number"||typeof data==="string"||typeof data=="boolean"){return data;}
let res=(Array.isArray(data))?[]:{};if(!spec){spec="*";}
for(let i in data){let currentMember=data[i];if(typeof currentMember==='function'||currentMember===null){continue;}
let currentMemberSpec;if(spec!="*"){currentMemberSpec=Array.isArray(data)?spec:spec[i];if(!currentMemberSpec){continue;}}else{currentMemberSpec="*"}
if(typeof currentMember==='object'){if(Array.isArray(currentMember)||currentMember.length){res[i]=[];for(let j=0;j<currentMember.length;j++){const arrayItem=currentMember[j];if(typeof arrayItem==='object'){res[i].push(this.serializeParameter(arrayItem,currentMemberSpec));}else{res[i].push(arrayItem);}}}else{if(currentMember.length===0){res[i]=[];}else{res[i]=this.serializeParameter(currentMember,currentMemberSpec);}}}else{if(currentMember===Infinity){currentMember="Infinity";}
if(currentMember!==null){res[i]=currentMember;}}}
return res;};class MudResizeObserverFactory{constructor(){this._maps={};}
class MudFileUpload{openFilePicker(id){const element=document.getElementById(id);if(!element){return;}
try{element.showPicker();}catch(error){element.click();}}}
window.mudFileUpload=new MudFileUpload();class MudInput{resetValue(id){const input=document.getElementById(id);if(input){input.value='';}}}
window.mudInput=new MudInput();class MudScrollSpy{constructor(){this.lastKnowElement=null;this.handlerRef=null;}
spying(dotnetReference,containerSelector,sectionClassSelector){this.lastKnowElement=null;this.handlerRef=this.handleScroll.bind(this,dotnetReference,containerSelector,sectionClassSelector);document.addEventListener('scroll',this.handlerRef,true);window.addEventListener('resize',this.handlerRef,true);}
handleScroll(dotnetReference,containerSelector,sectionClassSelector,event){const container=document.querySelector(containerSelector);if(container===null){return;}
const elements=document.getElementsByClassName(sectionClassSelector);if(elements.length===0){return;}
const containerTop=container.tagName==='HTML'?0:container.getBoundingClientRect().top;const containerHeight=container.clientHeight;const center=containerTop+containerHeight/2.0;let minDifference=Number.MAX_SAFE_INTEGER;let foundAbove=false;let elementId='';for(let i=0;i<elements.length;i++){const element=elements[i];const rect=element.getBoundingClientRect();const diff=Math.abs(rect.top-center);if(!foundAbove&&rect.top<center){foundAbove=true;minDifference=diff;elementId=element.id;continue;}
if(foundAbove&&rect.top>=center){continue;}
if(diff<minDifference){minDifference=diff;elementId=element.id;}}
if(elementId!==this.lastKnowElement){this.lastKnowElement=elementId;history.replaceState(null,'',window.location.pathname+"#"+elementId);dotnetReference.invokeMethodAsync('SectionChangeOccured',elementId);}}
activateSection(sectionId){const element=document.getElementById(sectionId);if(element){this.lastKnowElement=sectionId;history.replaceState(null,'',window.location.pathname+"#"+sectionId);}}
scrollToSection(sectionId){if(sectionId){let element=document.getElementById(sectionId);if(element){element.scrollIntoView({behavior:'smooth',block:'center',inline:'start'});}}
else{window.scrollTo({top:0,behavior:'smooth'});}}
unspy(){document.removeEventListener('scroll',this.handlerRef,true);window.removeEventListener('resize',this.handlerRef,true);}};window.mudScrollSpy=new MudScrollSpy();window.mudDragAndDrop={initDropZone:(id)=>{const elem=document.getElementById('mud-drop-zone-'+id);elem.addEventListener('dragover',()=>event.preventDefault());elem.addEventListener('dragstart',()=>event.dataTransfer.setData('',event.target.id));},makeDropZonesNotRelative:()=>{var firstDropItems=Array.from(document.getElementsByClassName('mud-drop-item')).filter(x=>x.getAttribute('index')=="-1");for(let dropItem of firstDropItems){dropItem.style.position='static';}
const dropZones=document.getElementsByClassName('mud-drop-zone');for(let dropZone of dropZones){dropZone.style.position='unset';}},getDropZoneIdentifierOnPosition:(x,y)=>{const elems=document.elementsFromPoint(x,y);const dropZones=elems.filter(e=>e.classList.contains('mud-drop-zone'))
const dropZone=dropZones[0];if(dropZone){return dropZone.getAttribute('identifier')||"";}
return"";},getDropIndexOnPosition:(x,y,id)=>{const elems=document.elementsFromPoint(x,y);const dropItems=elems.filter(e=>e.classList.contains('mud-drop-item')&&e.id!=('mud-drop-item-'+id))
const dropItem=dropItems[0];if(dropItem){return dropItem.getAttribute('index')||"";}
return"";},makeDropZonesRelative:()=>{const dropZones=document.getElementsByClassName('mud-drop-zone');for(let dropZone of dropZones){dropZone.style.position='relative';}
var firstDropItems=Array.from(document.getElementsByClassName('mud-drop-item')).filter(x=>x.getAttribute('index')=="-1");for(let dropItem of firstDropItems){dropItem.style.position='relative';}},moveItemByDifference:(id,dx,dy)=>{const elem=document.getElementById('mud-drop-item-'+id);var tx=(parseFloat(elem.getAttribute('data-x'))||0)+dx;var ty=(parseFloat(elem.getAttribute('data-y'))||0)+dy;elem.style.webkitTransform=elem.style.transform='translate3d('+tx+'px, '+ty+'px, 10px)';elem.setAttribute('data-x',tx);elem.setAttribute('data-y',ty);},resetItem:(id)=>{const elem=document.getElementById('mud-drop-item-'+id);if(elem){elem.style.webkitTransform=elem.style.transform='';elem.setAttribute('data-x',0);elem.setAttribute('data-y',0);}}};class MudScrollManager{scrollToYear(elementId,offset){let element=document.getElementById(elementId);if(element){element.parentNode.scrollTop=element.offsetTop-element.parentNode.offsetTop-element.scrollHeight*3;}}
scrollToListItem(elementId){let element=document.getElementById(elementId);if(element){let parent=element.parentElement;if(parent){parent.scrollTop=element.offsetTop;}}}
scrollTo(selector,left,top,behavior){let element=document.querySelector(selector)||document.documentElement;element.scrollTo({left,top,behavior});}
scrollIntoView(selector,behavior){let element=document.querySelector(selector)||document.documentElement;if(element)
element.scrollIntoView({behavior,block:'center',inline:'start'});}
scrollToBottom(selector,behavior){let element=document.querySelector(selector);if(element){element.scrollTo({top:element.scrollHeight,behavior:behavior});}else{window.scrollTo({top:document.body.scrollHeight,behavior:behavior});}}
lockScroll(selector,lockclass){let element=document.querySelector(selector)||document.body;let hasScrollBar=window.innerWidth>document.body.clientWidth;if(hasScrollBar){element.classList.add(lockclass);}else{let lockClassNoPadding=lockclass+"-no-padding";element.classList.add(lockClassNoPadding);}}
unlockScroll(selector,lockclass){let element=document.querySelector(selector)||document.body;element.classList.remove(lockclass);element.classList.remove(lockclass+"-no-padding");}};window.mudScrollManager=new MudScrollManager();class MudWindow{copyToClipboard(text){navigator.clipboard.writeText(text);}
changeCssById(id,css){var element=document.getElementById(id);if(element){element.className=css;}}
updateStyleProperty(elementId,propertyName,value){const element=document.getElementById(elementId);if(element){element.style.setProperty(propertyName,value);}}
changeGlobalCssVariable(name,newValue){document.documentElement.style.setProperty(name,newValue);}
open(args){window.open(args);}}
window.mudWindow=new MudWindow();const darkThemeMediaQuery=window.matchMedia("(prefers-color-scheme: dark)");window.darkModeChange=()=>{return darkThemeMediaQuery.matches;};function darkModeChangeListener(e){dotNetHelperTheme.invokeMethodAsync('SystemPreferenceChanged',e.matches);}
function watchDarkThemeMedia(dotNetHelper){dotNetHelperTheme=dotNetHelper;darkThemeMediaQuery.addEventListener('change',darkModeChangeListener);}
function stopWatchingDarkThemeMedia(){darkThemeMediaQuery.removeEventListener('change',darkModeChangeListener);}
window.mudInputAutoGrow={initAutoGrow:(elem,maxLines)=>{const compStyle=getComputedStyle(elem);const lineHeight=parseFloat(compStyle.getPropertyValue('line-height'));let maxHeight=0;elem.updateParameters=function(newMaxLines){if(newMaxLines>0){maxHeight=lineHeight*newMaxLines;}else{maxHeight=0;}}
elem.adjustAutoGrowHeight=function(didReflow=false){const scrollTops=[];let curElem=elem;while(curElem&&curElem.parentNode&&curElem.parentNode instanceof Element){if(curElem.parentNode.scrollTop){scrollTops.push([curElem.parentNode,curElem.parentNode.scrollTop]);}
curElem=curElem.parentNode;}
elem.style.height=0;if(didReflow){elem.style.textAlign=null;}
let minHeight=lineHeight*elem.rows;let newHeight=Math.max(minHeight,elem.scrollHeight);let initialOverflowY=elem.style.overflowY;if(maxHeight>0&&newHeight>maxHeight){elem.style.overflowY='auto';newHeight=maxHeight;}else{elem.style.overflowY='hidden';}
elem.style.height=newHeight+"px";scrollTops.forEach(([node,scrollTop])=>{node.style.scrollBehavior='auto';node.scrollTop=scrollTop;node.style.scrollBehavior=null;});if(!didReflow&&initialOverflowY!==elem.style.overflowY&&elem.style.overflowY==='hidden'){elem.style.textAlign='end';elem.adjustAutoGrowHeight(true);}}
elem.restoreToInitialState=function(){elem.removeEventListener('input',elem.adjustAutoGrowHeight);elem.style.overflowY=null;elem.style.height=null;}
elem.addEventListener('input',elem.adjustAutoGrowHeight);window.addEventListener('resize',elem.adjustAutoGrowHeight);elem.updateParameters(maxLines);elem.adjustAutoGrowHeight();},adjustHeight:(elem)=>{if(typeof elem.adjustAutoGrowHeight==='function'){elem.adjustAutoGrowHeight();}},updateParams:(elem,maxLines)=>{if(typeof elem.updateParameters==='function'){elem.updateParameters(maxLines);}
if(typeof elem.adjustAutoGrowHeight==='function'){elem.adjustAutoGrowHeight();}},destroy:(elem)=>{window.removeEventListener('resize',elem.adjustAutoGrowHeight);if(typeof elem.restoreToInitialState==='function'){elem.restoreToInitialState();}}};function setRippleOffset(event,target){const rect=target.getBoundingClientRect();const x=event.clientX-rect.left-rect.width/2;const y=event.clientY-rect.top-rect.height/2;target.style.setProperty("--mud-ripple-offset-x",`${x}px`);target.style.setProperty("--mud-ripple-offset-y",`${y}px`);}
document.addEventListener("click",function(event){const target=event.target.closest(".mud-ripple");if(target){setRippleOffset(event,target);}});class MudJsEventFactory{connect(dotNetRef,elementId,options){if(!elementId)
throw"[MudBlazor | JsEvent] elementId: expected element id!";var element=document.getElementById(elementId);if(!element)
throw"[MudBlazor | JsEvent] no element found for id: "+elementId;if(!element.mudJsEvent)
element.mudJsEvent=new MudJsEvent(dotNetRef,options);element.mudJsEvent.connect(element);}
disconnect(elementId){var element=document.getElementById(elementId);if(!element||!element.mudJsEvent)
return;element.mudJsEvent.disconnect();}
subscribe(elementId,eventName){if(!elementId)
throw"[MudBlazor | JsEvent] elementId: expected element id!";var element=document.getElementById(elementId);if(!element)
throw"[MudBlazor | JsEvent] no element found for id: "+elementId;if(!element.mudJsEvent)
throw"[MudBlazor | JsEvent] please connect before subscribing"
element.mudJsEvent.subscribe(eventName);}
unsubscribe(elementId,eventName){var element=document.getElementById(elementId);if(!element||!element.mudJsEvent)
return;element.mudJsEvent.unsubscribe(element,eventName);}}
window.mudJsEvent=new MudJsEventFactory();class MudJsEvent{constructor(dotNetRef,options){this._dotNetRef=dotNetRef;this._options=options||{};this.logger=options.enableLogging?console.log:(message)=>{};this.logger('[MudBlazor | JsEvent] Initialized',{options});this._subscribedEvents={};}
connect(element){if(!this._options)
return;if(!this._options.targetClass)
throw"_options.targetClass: css class name expected";if(this._observer){return;}
var targetClass=this._options.targetClass;this.logger('[MudBlazor | JsEvent] Start observing DOM of element for changes to child with class ',{element,targetClass});this._element=element;this._observer=new MutationObserver(this.onDomChanged);this._observer.mudJsEvent=this;this._observer.observe(this._element,{attributes:false,childList:true,subtree:true});this._observedChildren=[];}
disconnect(){if(!this._observer)
return;this.logger('[MudBlazor | JsEvent] disconnect mutation observer and event handler ');this._observer.disconnect();this._observer=null;for(const child of this._observedChildren)
this.detachHandlers(child);}
subscribe(eventName){if(this._subscribedEvents[eventName]){return;}
var element=this._element;var targetClass=this._options.targetClass;this._subscribedEvents[eventName]=true;for(const child of element.getElementsByClassName(targetClass)){this.attachHandlers(child);}}
unsubscribe(eventName){if(!this._observer)
return;this.logger('[MudBlazor | JsEvent] unsubscribe event handler '+eventName);this._observer.disconnect();this._observer=null;this._subscribedEvents[eventName]=false;for(const child of this._observedChildren){this.detachHandler(child,eventName);}}
attachHandlers(child){child.mudJsEvent=this;for(var eventName of Object.getOwnPropertyNames(this._subscribedEvents)){if(!this._subscribedEvents[eventName])
continue;this.logger('[MudBlazor | JsEvent] attaching event '+eventName,child);child.addEventListener(eventName,this.eventHandler);}
if(this._observedChildren.indexOf(child)<0)
this._observedChildren.push(child);}
detachHandler(child,eventName){this.logger('[MudBlazor | JsEvent] detaching handler '+eventName,child);child.removeEventListener(eventName,this.eventHandler);}
detachHandlers(child){this.logger('[MudBlazor | JsEvent] detaching handlers ',child);for(var eventName of Object.getOwnPropertyNames(this._subscribedEvents)){if(!this._subscribedEvents[eventName])
continue;child.removeEventListener(eventName,this.eventHandler);}
this._observedChildren=this._observedChildren.filter(x=>x!==child);}
onDomChanged(mutationsList,observer){var self=this.mudJsEvent;var targetClass=self._options.targetClass;for(const mutation of mutationsList){for(const element of mutation.addedNodes){if(element.classList&&element.classList.contains(targetClass)){if(!self._options.TagName||element.tagName==self._options.TagName)
self.attachHandlers(element);}}
for(const element of mutation.removedNodes){if(element.classList&&element.classList.contains(targetClass)){if(!self._options.tagName||element.tagName==self._options.tagName)
self.detachHandlers(element);}}}}
eventHandler(e){var self=this.mudJsEvent;var eventName=e.type;self.logger('[MudBlazor | JsEvent] "'+eventName+'"',e);self["on"+eventName](self,e);}
onkeyup(self,e){const caretPosition=e.target.selectionStart;const invoke=self._subscribedEvents["keyup"];if(invoke){self._dotNetRef.invokeMethodAsync('OnCaretPositionChanged',caretPosition);}}
onclick(self,e){const caretPosition=e.target.selectionStart;const invoke=self._subscribedEvents["click"];if(invoke){self._dotNetRef.invokeMethodAsync('OnCaretPositionChanged',caretPosition);}}
onpaste(self,e){const invoke=self._subscribedEvents["paste"];if(invoke){e.preventDefault();e.stopPropagation();const text=(e.originalEvent||e).clipboardData.getData('text/plain');self._dotNetRef.invokeMethodAsync('OnPaste',text);}}
onselect(self,e){const invoke=self._subscribedEvents["select"];if(invoke){const start=e.target.selectionStart;const end=e.target.selectionEnd;if(start===end)
return;self._dotNetRef.invokeMethodAsync('OnSelect',start,end);}}}
class MudScrollListener{constructor(){this.throttleScrollHandlerId=-1;this.handlerRef=null;}
listenForScroll(dotnetReference,selector){let element=selector?document.querySelector(selector):document;this.handlerRef=this.throttleScrollHandler.bind(this,dotnetReference);element.addEventListener('scroll',this.handlerRef,false);}
throttleScrollHandler(dotnetReference,event){clearTimeout(this.throttleScrollHandlerId);this.throttleScrollHandlerId=window.setTimeout(this.scrollHandler.bind(this,dotnetReference,event),100);}
scrollHandler(dotnetReference,event){try{let element=event.target;let scrollTop=element.scrollTop;let scrollHeight=element.scrollHeight;let scrollWidth=element.scrollWidth;let scrollLeft=element.scrollLeft;let nodeName=element.nodeName;let firstChild=element.firstElementChild;let firstChildBoundingClientRect=firstChild.getBoundingClientRect();dotnetReference.invokeMethodAsync('RaiseOnScroll',{firstChildBoundingClientRect,scrollLeft,scrollTop,scrollHeight,scrollWidth,nodeName,});}catch(error){console.log('[MudBlazor] Error in scrollHandler:',{error});}}
cancelListener(selector){let element=selector?document.querySelector(selector):document;element.removeEventListener('scroll',this.handlerRef);}};window.mudScrollListener=new MudScrollListener();class MudElementReference{constructor(){this.listenerId=0;this.eventListeners={};}
focus(element){if(element)
{element.focus();}}
blur(element){if(element){element.blur();}}
focusFirst(element,skip=0,min=0){if(element)
{let tabbables=getTabbableElements(element);if(tabbables.length<=min)
element.focus();else
tabbables[skip].focus();}}
focusLast(element,skip=0,min=0){if(element)
{let tabbables=getTabbableElements(element);if(tabbables.length<=min)
element.focus();else
tabbables[tabbables.length-skip-1].focus();}}
saveFocus(element){if(element)
{element['mudblazor_savedFocus']=document.activeElement;}}
restoreFocus(element){if(element)
{let previous=element['mudblazor_savedFocus'];delete element['mudblazor_savedFocus']
if(previous)
previous.focus();}}
selectRange(element,pos1,pos2){if(element)
{if(element.createTextRange){let selRange=element.createTextRange();selRange.collapse(true);selRange.moveStart('character',pos1);selRange.moveEnd('character',pos2);selRange.select();}else if(element.setSelectionRange){element.setSelectionRange(pos1,pos2);}else if(element.selectionStart){element.selectionStart=pos1;element.selectionEnd=pos2;}
element.focus();}}
select(element){if(element)
{element.select();}}
getBoundingClientRect(element){if(!element)return;var rect=JSON.parse(JSON.stringify(element.getBoundingClientRect()));rect.scrollY=window.scrollY||document.documentElement.scrollTop;rect.scrollX=window.scrollX||document.documentElement.scrollLeft;rect.windowHeight=window.innerHeight;rect.windowWidth=window.innerWidth;return rect;}
changeCss(element,css){if(element)
{element.className=css;}}
removeEventListener(element,event,eventId){element.removeEventListener(event,this.eventListeners[eventId]);delete this.eventListeners[eventId];}
addDefaultPreventingHandler(element,eventName){let listener=function(e){e.preventDefault();}
element.addEventListener(eventName,listener,{passive:false});this.eventListeners[++this.listenerId]=listener;return this.listenerId;}
removeDefaultPreventingHandler(element,eventName,listenerId){this.removeEventListener(element,eventName,listenerId);}
addDefaultPreventingHandlers(element,eventNames){let listeners=[];for(const eventName of eventNames){let listenerId=this.addDefaultPreventingHandler(element,eventName);listeners.push(listenerId);}
return listeners;}
removeDefaultPreventingHandlers(element,eventNames,listenerIds){for(let index=0;index<eventNames.length;++index){const eventName=eventNames[index];const listenerId=listenerIds[index];this.removeDefaultPreventingHandler(element,eventName,listenerId);}}};window.mudElementRef=new MudElementReference();window.mudTimePicker={initPointerEvents:(clock,dotNetHelper)=>{let isPointerDown=false;const startHandler=(event)=>{if(event.button!==0){return;}
isPointerDown=true;event.target.releasePointerCapture(event.pointerId);if(event.target.classList.contains('mud-hour')||event.target.classList.contains('mud-minute')){let attributeValue=event.target.getAttribute('data-stick-value');let stickValue=attributeValue?parseInt(attributeValue):-1;dotNetHelper.invokeMethodAsync('SelectTimeFromStick',stickValue,false);}
event.preventDefault();};const endHandler=(event)=>{if(event.button!==0){return;}
isPointerDown=false;if(event.target.classList.contains('mud-hour')||event.target.classList.contains('mud-minute')){let attributeValue=event.target.getAttribute('data-stick-value');let stickValue=attributeValue?parseInt(attributeValue):-1;dotNetHelper.invokeMethodAsync('OnStickClick',stickValue);}
event.preventDefault();};const moveHandler=(event)=>{if(!isPointerDown||(!event.target.classList.contains('mud-hour')&&!event.target.classList.contains('mud-minute'))){return;}
let attributeValue=event.target.getAttribute('data-stick-value');let stickValue=attributeValue?parseInt(attributeValue):-1;dotNetHelper.invokeMethodAsync('SelectTimeFromStick',stickValue,true);event.preventDefault();};clock.addEventListener('pointerdown',startHandler);clock.addEventListener('pointerup',endHandler);clock.addEventListener('pointercancel',endHandler);clock.addEventListener('pointerover',moveHandler);clock.destroy=()=>{clock.removeEventListener('pointerdown',startHandler);clock.removeEventListener('pointerup',endHandler);clock.removeEventListener('pointercancel',endHandler);clock.removeEventListener('pointerover',moveHandler);};},destroyPointerEvents:(container)=>{if(typeof container.destroy==='function'){container.destroy();}}};class MudResizeListener{constructor(id){this.logger=function(message){};this.options={};this.throttleResizeHandlerId=-1;this.dotnet=undefined;this.breakpoint=-1;this.id=id;this.handleResize=this.throttleResizeHandler.bind(this);}
listenForResize(dotnetRef,options){if(this.dotnet){this.options=options;return;}
this.options=options;this.dotnet=dotnetRef;this.logger=options.enableLogging?console.log:(message)=>{};this.logger(`[MudBlazor]Reporting resize events at rate of:${this.options.reportRate}ms`);window.addEventListener("resize",this.handleResize,false);if(!this.options.suppressInitEvent){this.resizeHandler();}
this.breakpoint=this.getBreakpoint(window.innerWidth);}
throttleResizeHandler(){clearTimeout(this.throttleResizeHandlerId);this.throttleResizeHandlerId=window.setTimeout(this.resizeHandler.bind(this),this.options.reportRate);}
resizeHandler(){if(this.options.notifyOnBreakpointOnly){let bp=this.getBreakpoint(window.innerWidth);if(bp==this.breakpoint){return;}
this.breakpoint=bp;}
try{if(this.id){this.dotnet.invokeMethodAsync('RaiseOnResized',{height:window.innerHeight,width:window.innerWidth},this.getBreakpoint(window.innerWidth),this.id);}
else{this.dotnet.invokeMethodAsync('RaiseOnResized',{height:window.innerHeight,width:window.innerWidth},this.getBreakpoint(window.innerWidth));}}catch(error){this.logger("[MudBlazor] Error in resizeHandler:",{error});}}
cancelListener(){this.dotnet=undefined;window.removeEventListener("resize",this.handleResize);}
matchMedia(query){let m=window.matchMedia(query).matches;return m;}
getBrowserWindowSize(){return{height:window.innerHeight,width:window.innerWidth};}
getBreakpoint(width){if(width>=this.options.breakpointDefinitions["Xxl"])
return 5;else if(width>=this.options.breakpointDefinitions["Xl"])
return 4;else if(width>=this.options.breakpointDefinitions["Lg"])
return 3;else if(width>=this.options.breakpointDefinitions["Md"])
return 2;else if(width>=this.options.breakpointDefinitions["Sm"])
return 1;else
return 0;}};window.mudResizeListener=new MudResizeListener();window.mudResizeListenerFactory={mapping:{},listenForResize:(dotnetRef,options,id)=>{var map=window.mudResizeListenerFactory.mapping;if(map[id]){return;}
var listener=new MudResizeListener(id);listener.listenForResize(dotnetRef,options);map[id]=listener;},cancelListener:(id)=>{var map=window.mudResizeListenerFactory.mapping;if(!map[id]){return;}
var listener=map[id];listener.cancelListener();delete map[id];},cancelListeners:(ids)=>{for(let i=0;i<ids.length;i++){window.mudResizeListenerFactory.cancelListener(ids[i]);}},dispose(){var map=window.mudResizeListenerFactory.mapping;for(var id in map){window.mudResizeListenerFactory.cancelListener(id);}}}
class MudResizeObserverFactory{constructor(){this._maps={};}
connect(id,dotNetRef,elements,elementIds,options){var existingEntry=this._maps[id];if(!existingEntry){var observer=new MudResizeObserver(dotNetRef,options);this._maps[id]=observer;}
var result=this._maps[id].connect(elements,elementIds);return result;}
disconnect(id,element){var existingEntry=this._maps[id];if(existingEntry){existingEntry.disconnect(element);}}
@@ -21,8 +163,7 @@ connect(elements,ids){var result=[];this.logger('[MudBlazor | ResizeObserver] St
return result;}
disconnect(elementId){this.logger('[MudBlazor | ResizeObserver] Try to unobserve element with id',{elementId});var affectedObservedElement=this._observervedElements.find((x)=>x.id==elementId);if(affectedObservedElement){var element=affectedObservedElement.element;this._resizeObserver.unobserve(element);this.logger('[MudBlazor | ResizeObserver] Element found. Ubobserving size changes of element',{element});var index=this._observervedElements.indexOf(affectedObservedElement);this._observervedElements.splice(index,1);}}
cancelListener(){this.logger('[MudBlazor | ResizeObserver] Closing ResizeObserver. Detaching all observed elements');this._resizeObserver.disconnect();this._dotNetRef=undefined;}}
window.mudResizeObserver=new MudResizeObserverFactory();class MudInput{resetValue(id){const input=document.getElementById(id);if(input){input.value='';}}}
window.mudInput=new MudInput();class MudKeyInterceptorFactory{connect(dotNetRef,elementId,options){if(!elementId)
window.mudResizeObserver=new MudResizeObserverFactory();class MudKeyInterceptorFactory{connect(dotNetRef,elementId,options){if(!elementId)
throw"elementId: expected element id!";var element=document.getElementById(elementId);if(!element)
throw"no element found for id: "+elementId;if(!element.mudKeyInterceptor)
element.mudKeyInterceptor=new MudKeyInterceptor(dotNetRef,options);element.mudKeyInterceptor.connect(element);}
@@ -76,102 +217,6 @@ processKeyUp(args,keyOptions){if(this.matchesKeyCombination(keyOptions.preventUp
args.preventDefault();if(this.matchesKeyCombination(keyOptions.stopUp,args))
args.stopPropagation();}
toKeyboardEventArgs(args){return{Key:args.key,Code:args.code,Location:args.location,Repeat:args.repeat,CtrlKey:args.ctrlKey,ShiftKey:args.shiftKey,AltKey:args.altKey,MetaKey:args.metaKey};}}
class MudElementReference{constructor(){this.listenerId=0;this.eventListeners={};}
focus(element){if(element)
{element.focus();}}
blur(element){if(element){element.blur();}}
focusFirst(element,skip=0,min=0){if(element)
{let tabbables=getTabbableElements(element);if(tabbables.length<=min)
element.focus();else
tabbables[skip].focus();}}
focusLast(element,skip=0,min=0){if(element)
{let tabbables=getTabbableElements(element);if(tabbables.length<=min)
element.focus();else
tabbables[tabbables.length-skip-1].focus();}}
saveFocus(element){if(element)
{element['mudblazor_savedFocus']=document.activeElement;}}
restoreFocus(element){if(element)
{let previous=element['mudblazor_savedFocus'];delete element['mudblazor_savedFocus']
if(previous)
previous.focus();}}
selectRange(element,pos1,pos2){if(element)
{if(element.createTextRange){let selRange=element.createTextRange();selRange.collapse(true);selRange.moveStart('character',pos1);selRange.moveEnd('character',pos2);selRange.select();}else if(element.setSelectionRange){element.setSelectionRange(pos1,pos2);}else if(element.selectionStart){element.selectionStart=pos1;element.selectionEnd=pos2;}
element.focus();}}
select(element){if(element)
{element.select();}}
getBoundingClientRect(element){if(!element)return;var rect=JSON.parse(JSON.stringify(element.getBoundingClientRect()));rect.scrollY=window.scrollY||document.documentElement.scrollTop;rect.scrollX=window.scrollX||document.documentElement.scrollLeft;rect.windowHeight=window.innerHeight;rect.windowWidth=window.innerWidth;return rect;}
changeCss(element,css){if(element)
{element.className=css;}}
removeEventListener(element,event,eventId){element.removeEventListener(event,this.eventListeners[eventId]);delete this.eventListeners[eventId];}
addDefaultPreventingHandler(element,eventName){let listener=function(e){e.preventDefault();}
element.addEventListener(eventName,listener,{passive:false});this.eventListeners[++this.listenerId]=listener;return this.listenerId;}
removeDefaultPreventingHandler(element,eventName,listenerId){this.removeEventListener(element,eventName,listenerId);}
addDefaultPreventingHandlers(element,eventNames){let listeners=[];for(const eventName of eventNames){let listenerId=this.addDefaultPreventingHandler(element,eventName);listeners.push(listenerId);}
return listeners;}
removeDefaultPreventingHandlers(element,eventNames,listenerIds){for(let index=0;index<eventNames.length;++index){const eventName=eventNames[index];const listenerId=listenerIds[index];this.removeDefaultPreventingHandler(element,eventName,listenerId);}}};window.mudElementRef=new MudElementReference();const darkThemeMediaQuery=window.matchMedia("(prefers-color-scheme: dark)");window.darkModeChange=()=>{return darkThemeMediaQuery.matches;};function darkModeChangeListener(e){dotNetHelperTheme.invokeMethodAsync('SystemPreferenceChanged',e.matches);}
function watchDarkThemeMedia(dotNetHelper){dotNetHelperTheme=dotNetHelper;darkThemeMediaQuery.addEventListener('change',darkModeChangeListener);}
function stopWatchingDarkThemeMedia(){darkThemeMediaQuery.removeEventListener('change',darkModeChangeListener);}
class MudScrollSpy{constructor(){this.lastKnowElement=null;this.handlerRef=null;}
spying(dotnetReference,containerSelector,sectionClassSelector){this.lastKnowElement=null;this.handlerRef=this.handleScroll.bind(this,dotnetReference,containerSelector,sectionClassSelector);document.addEventListener('scroll',this.handlerRef,true);window.addEventListener('resize',this.handlerRef,true);}
handleScroll(dotnetReference,containerSelector,sectionClassSelector,event){const container=document.querySelector(containerSelector);if(container===null){return;}
const elements=document.getElementsByClassName(sectionClassSelector);if(elements.length===0){return;}
const containerTop=container.tagName==='HTML'?0:container.getBoundingClientRect().top;const containerHeight=container.clientHeight;const center=containerTop+containerHeight/2.0;let minDifference=Number.MAX_SAFE_INTEGER;let foundAbove=false;let elementId='';for(let i=0;i<elements.length;i++){const element=elements[i];const rect=element.getBoundingClientRect();const diff=Math.abs(rect.top-center);if(!foundAbove&&rect.top<center){foundAbove=true;minDifference=diff;elementId=element.id;continue;}
if(foundAbove&&rect.top>=center){continue;}
if(diff<minDifference){minDifference=diff;elementId=element.id;}}
if(elementId!==this.lastKnowElement){this.lastKnowElement=elementId;history.replaceState(null,'',window.location.pathname+"#"+elementId);dotnetReference.invokeMethodAsync('SectionChangeOccured',elementId);}}
activateSection(sectionId){const element=document.getElementById(sectionId);if(element){this.lastKnowElement=sectionId;history.replaceState(null,'',window.location.pathname+"#"+sectionId);}}
scrollToSection(sectionId){if(sectionId){let element=document.getElementById(sectionId);if(element){element.scrollIntoView({behavior:'smooth',block:'center',inline:'start'});}}
else{window.scrollTo({top:0,behavior:'smooth'});}}
unspy(){document.removeEventListener('scroll',this.handlerRef,true);window.removeEventListener('resize',this.handlerRef,true);}};window.mudScrollSpy=new MudScrollSpy();window.mudInputAutoGrow={initAutoGrow:(elem,maxLines)=>{const compStyle=getComputedStyle(elem);const lineHeight=parseFloat(compStyle.getPropertyValue('line-height'));let maxHeight=0;elem.updateParameters=function(newMaxLines){if(newMaxLines>0){maxHeight=lineHeight*newMaxLines;}else{maxHeight=0;}}
elem.adjustAutoGrowHeight=function(didReflow=false){const scrollTops=[];let curElem=elem;while(curElem&&curElem.parentNode&&curElem.parentNode instanceof Element){if(curElem.parentNode.scrollTop){scrollTops.push([curElem.parentNode,curElem.parentNode.scrollTop]);}
curElem=curElem.parentNode;}
elem.style.height=0;if(didReflow){elem.style.textAlign=null;}
let minHeight=lineHeight*elem.rows;let newHeight=Math.max(minHeight,elem.scrollHeight);let initialOverflowY=elem.style.overflowY;if(maxHeight>0&&newHeight>maxHeight){elem.style.overflowY='auto';newHeight=maxHeight;}else{elem.style.overflowY='hidden';}
elem.style.height=newHeight+"px";scrollTops.forEach(([node,scrollTop])=>{node.style.scrollBehavior='auto';node.scrollTop=scrollTop;node.style.scrollBehavior=null;});if(!didReflow&&initialOverflowY!==elem.style.overflowY&&elem.style.overflowY==='hidden'){elem.style.textAlign='end';elem.adjustAutoGrowHeight(true);}}
elem.restoreToInitialState=function(){elem.removeEventListener('input',elem.adjustAutoGrowHeight);elem.style.overflowY=null;elem.style.height=null;}
elem.addEventListener('input',elem.adjustAutoGrowHeight);window.addEventListener('resize',elem.adjustAutoGrowHeight);elem.updateParameters(maxLines);elem.adjustAutoGrowHeight();},adjustHeight:(elem)=>{if(typeof elem.adjustAutoGrowHeight==='function'){elem.adjustAutoGrowHeight();}},updateParams:(elem,maxLines)=>{if(typeof elem.updateParameters==='function'){elem.updateParameters(maxLines);}
if(typeof elem.adjustAutoGrowHeight==='function'){elem.adjustAutoGrowHeight();}},destroy:(elem)=>{window.removeEventListener('resize',elem.adjustAutoGrowHeight);if(typeof elem.restoreToInitialState==='function'){elem.restoreToInitialState();}}}
window.mudTimePicker={initPointerEvents:(clock,dotNetHelper)=>{let isPointerDown=false;const startHandler=(event)=>{if(event.button!==0){return;}
isPointerDown=true;event.target.releasePointerCapture(event.pointerId);if(event.target.classList.contains('mud-hour')||event.target.classList.contains('mud-minute')){let attributeValue=event.target.getAttribute('data-stick-value');let stickValue=attributeValue?parseInt(attributeValue):-1;dotNetHelper.invokeMethodAsync('SelectTimeFromStick',stickValue,false);}
event.preventDefault();};const endHandler=(event)=>{if(event.button!==0){return;}
isPointerDown=false;if(event.target.classList.contains('mud-hour')||event.target.classList.contains('mud-minute')){let attributeValue=event.target.getAttribute('data-stick-value');let stickValue=attributeValue?parseInt(attributeValue):-1;dotNetHelper.invokeMethodAsync('OnStickClick',stickValue);}
event.preventDefault();};const moveHandler=(event)=>{if(!isPointerDown||(!event.target.classList.contains('mud-hour')&&!event.target.classList.contains('mud-minute'))){return;}
let attributeValue=event.target.getAttribute('data-stick-value');let stickValue=attributeValue?parseInt(attributeValue):-1;dotNetHelper.invokeMethodAsync('SelectTimeFromStick',stickValue,true);event.preventDefault();};clock.addEventListener('pointerdown',startHandler);clock.addEventListener('pointerup',endHandler);clock.addEventListener('pointercancel',endHandler);clock.addEventListener('pointerover',moveHandler);clock.destroy=()=>{clock.removeEventListener('pointerdown',startHandler);clock.removeEventListener('pointerup',endHandler);clock.removeEventListener('pointercancel',endHandler);clock.removeEventListener('pointerover',moveHandler);};},destroyPointerEvents:(container)=>{if(typeof container.destroy==='function'){container.destroy();}}};class MudScrollListener{constructor(){this.throttleScrollHandlerId=-1;this.handlerRef=null;}
listenForScroll(dotnetReference,selector){let element=selector?document.querySelector(selector):document;this.handlerRef=this.throttleScrollHandler.bind(this,dotnetReference);element.addEventListener('scroll',this.handlerRef,false);}
throttleScrollHandler(dotnetReference,event){clearTimeout(this.throttleScrollHandlerId);this.throttleScrollHandlerId=window.setTimeout(this.scrollHandler.bind(this,dotnetReference,event),100);}
scrollHandler(dotnetReference,event){try{let element=event.target;let scrollTop=element.scrollTop;let scrollHeight=element.scrollHeight;let scrollWidth=element.scrollWidth;let scrollLeft=element.scrollLeft;let nodeName=element.nodeName;let firstChild=element.firstElementChild;let firstChildBoundingClientRect=firstChild.getBoundingClientRect();dotnetReference.invokeMethodAsync('RaiseOnScroll',{firstChildBoundingClientRect,scrollLeft,scrollTop,scrollHeight,scrollWidth,nodeName,});}catch(error){console.log('[MudBlazor] Error in scrollHandler:',{error});}}
cancelListener(selector){let element=selector?document.querySelector(selector):document;element.removeEventListener('scroll',this.handlerRef);}};window.mudScrollListener=new MudScrollListener();window.mudDragAndDrop={initDropZone:(id)=>{const elem=document.getElementById('mud-drop-zone-'+id);elem.addEventListener('dragover',()=>event.preventDefault());elem.addEventListener('dragstart',()=>event.dataTransfer.setData('',event.target.id));},makeDropZonesNotRelative:()=>{var firstDropItems=Array.from(document.getElementsByClassName('mud-drop-item')).filter(x=>x.getAttribute('index')=="-1");for(let dropItem of firstDropItems){dropItem.style.position='static';}
const dropZones=document.getElementsByClassName('mud-drop-zone');for(let dropZone of dropZones){dropZone.style.position='unset';}},getDropZoneIdentifierOnPosition:(x,y)=>{const elems=document.elementsFromPoint(x,y);const dropZones=elems.filter(e=>e.classList.contains('mud-drop-zone'))
const dropZone=dropZones[0];if(dropZone){return dropZone.getAttribute('identifier')||"";}
return"";},getDropIndexOnPosition:(x,y,id)=>{const elems=document.elementsFromPoint(x,y);const dropItems=elems.filter(e=>e.classList.contains('mud-drop-item')&&e.id!=('mud-drop-item-'+id))
const dropItem=dropItems[0];if(dropItem){return dropItem.getAttribute('index')||"";}
return"";},makeDropZonesRelative:()=>{const dropZones=document.getElementsByClassName('mud-drop-zone');for(let dropZone of dropZones){dropZone.style.position='relative';}
var firstDropItems=Array.from(document.getElementsByClassName('mud-drop-item')).filter(x=>x.getAttribute('index')=="-1");for(let dropItem of firstDropItems){dropItem.style.position='relative';}},moveItemByDifference:(id,dx,dy)=>{const elem=document.getElementById('mud-drop-item-'+id);var tx=(parseFloat(elem.getAttribute('data-x'))||0)+dx;var ty=(parseFloat(elem.getAttribute('data-y'))||0)+dy;elem.style.webkitTransform=elem.style.transform='translate3d('+tx+'px, '+ty+'px, 10px)';elem.setAttribute('data-x',tx);elem.setAttribute('data-y',ty);},resetItem:(id)=>{const elem=document.getElementById('mud-drop-item-'+id);if(elem){elem.style.webkitTransform=elem.style.transform='';elem.setAttribute('data-x',0);elem.setAttribute('data-y',0);}}};class MudWindow{copyToClipboard(text){navigator.clipboard.writeText(text);}
changeCssById(id,css){var element=document.getElementById(id);if(element){element.className=css;}}
updateStyleProperty(elementId,propertyName,value){const element=document.getElementById(elementId);if(element){element.style.setProperty(propertyName,value);}}
changeGlobalCssVariable(name,newValue){document.documentElement.style.setProperty(name,newValue);}
open(args){window.open(args);}}
window.mudWindow=new MudWindow();class MudResizeListener{constructor(id){this.logger=function(message){};this.options={};this.throttleResizeHandlerId=-1;this.dotnet=undefined;this.breakpoint=-1;this.id=id;this.handleResize=this.throttleResizeHandler.bind(this);}
listenForResize(dotnetRef,options){if(this.dotnet){this.options=options;return;}
this.options=options;this.dotnet=dotnetRef;this.logger=options.enableLogging?console.log:(message)=>{};this.logger(`[MudBlazor]Reporting resize events at rate of:${this.options.reportRate}ms`);window.addEventListener("resize",this.handleResize,false);if(!this.options.suppressInitEvent){this.resizeHandler();}
this.breakpoint=this.getBreakpoint(window.innerWidth);}
throttleResizeHandler(){clearTimeout(this.throttleResizeHandlerId);this.throttleResizeHandlerId=window.setTimeout(this.resizeHandler.bind(this),this.options.reportRate);}
resizeHandler(){if(this.options.notifyOnBreakpointOnly){let bp=this.getBreakpoint(window.innerWidth);if(bp==this.breakpoint){return;}
this.breakpoint=bp;}
try{if(this.id){this.dotnet.invokeMethodAsync('RaiseOnResized',{height:window.innerHeight,width:window.innerWidth},this.getBreakpoint(window.innerWidth),this.id);}
else{this.dotnet.invokeMethodAsync('RaiseOnResized',{height:window.innerHeight,width:window.innerWidth},this.getBreakpoint(window.innerWidth));}}catch(error){this.logger("[MudBlazor] Error in resizeHandler:",{error});}}
cancelListener(){this.dotnet=undefined;window.removeEventListener("resize",this.handleResize);}
matchMedia(query){let m=window.matchMedia(query).matches;return m;}
getBrowserWindowSize(){return{height:window.innerHeight,width:window.innerWidth};}
getBreakpoint(width){if(width>=this.options.breakpointDefinitions["Xxl"])
return 5;else if(width>=this.options.breakpointDefinitions["Xl"])
return 4;else if(width>=this.options.breakpointDefinitions["Lg"])
return 3;else if(width>=this.options.breakpointDefinitions["Md"])
return 2;else if(width>=this.options.breakpointDefinitions["Sm"])
return 1;else
return 0;}};window.mudResizeListener=new MudResizeListener();window.mudResizeListenerFactory={mapping:{},listenForResize:(dotnetRef,options,id)=>{var map=window.mudResizeListenerFactory.mapping;if(map[id]){return;}
var listener=new MudResizeListener(id);listener.listenForResize(dotnetRef,options);map[id]=listener;},cancelListener:(id)=>{var map=window.mudResizeListenerFactory.mapping;if(!map[id]){return;}
var listener=map[id];listener.cancelListener();delete map[id];},cancelListeners:(ids)=>{for(let i=0;i<ids.length;i++){window.mudResizeListenerFactory.cancelListener(ids[i]);}},dispose(){var map=window.mudResizeListenerFactory.mapping;for(var id in map){window.mudResizeListenerFactory.cancelListener(id);}}}
window.mudpopoverHelper={calculatePopoverPosition:function(list,boundingRect,selfRect){let top=0;let left=0;if(list.indexOf('mud-popover-anchor-top-left')>=0){left=boundingRect.left;top=boundingRect.top;}else if(list.indexOf('mud-popover-anchor-top-center')>=0){left=boundingRect.left+boundingRect.width/2;top=boundingRect.top;}else if(list.indexOf('mud-popover-anchor-top-right')>=0){left=boundingRect.left+boundingRect.width;top=boundingRect.top;}else if(list.indexOf('mud-popover-anchor-center-left')>=0){left=boundingRect.left;top=boundingRect.top+boundingRect.height/2;}else if(list.indexOf('mud-popover-anchor-center-center')>=0){left=boundingRect.left+boundingRect.width/2;top=boundingRect.top+boundingRect.height/2;}else if(list.indexOf('mud-popover-anchor-center-right')>=0){left=boundingRect.left+boundingRect.width;top=boundingRect.top+boundingRect.height/2;}else if(list.indexOf('mud-popover-anchor-bottom-left')>=0){left=boundingRect.left;top=boundingRect.top+boundingRect.height;}else if(list.indexOf('mud-popover-anchor-bottom-center')>=0){left=boundingRect.left+boundingRect.width/2;top=boundingRect.top+boundingRect.height;}else if(list.indexOf('mud-popover-anchor-bottom-right')>=0){left=boundingRect.left+boundingRect.width;top=boundingRect.top+boundingRect.height;}
let offsetX=0;let offsetY=0;if(list.indexOf('mud-popover-top-left')>=0){offsetX=0;offsetY=0;}else if(list.indexOf('mud-popover-top-center')>=0){offsetX=-selfRect.width/2;offsetY=0;}else if(list.indexOf('mud-popover-top-right')>=0){offsetX=-selfRect.width;offsetY=0;}
else if(list.indexOf('mud-popover-center-left')>=0){offsetX=0;offsetY=-selfRect.height/2;}else if(list.indexOf('mud-popover-center-center')>=0){offsetX=-selfRect.width/2;offsetY=-selfRect.height/2;}else if(list.indexOf('mud-popover-center-right')>=0){offsetX=-selfRect.width;offsetY=-selfRect.height/2;}
@@ -216,60 +261,7 @@ dispose(){for(var i in this.map){disconnect(i);}
this.contentObserver.disconnect();this.contentObserver=null;}
getAllObservedContainers(){const result=[];for(var i in this.map){result.push(i);}
return result;}}
window.mudPopover=new MudPopover();window.addEventListener('scroll',()=>{window.mudpopoverHelper.placePopoverByClassSelector('mud-popover-fixed');window.mudpopoverHelper.placePopoverByClassSelector('mud-popover-overflow-flip-always');});window.addEventListener('resize',()=>{window.mudpopoverHelper.placePopoverByClassSelector();});class MudFileUpload{openFilePicker(id){const element=document.getElementById(id);if(!element){return;}
try{element.showPicker();}catch(error){element.click();}}}
window.mudFileUpload=new MudFileUpload();function setRippleOffset(event,target){const rect=target.getBoundingClientRect();const x=event.clientX-rect.left-rect.width/2;const y=event.clientY-rect.top-rect.height/2;target.style.setProperty("--mud-ripple-offset-x",`${x}px`);target.style.setProperty("--mud-ripple-offset-y",`${y}px`);}
document.addEventListener("click",function(event){const target=event.target.closest(".mud-ripple");if(target){setRippleOffset(event,target);}});class MudScrollManager{scrollToYear(elementId,offset){let element=document.getElementById(elementId);if(element){element.parentNode.scrollTop=element.offsetTop-element.parentNode.offsetTop-element.scrollHeight*3;}}
scrollToListItem(elementId){let element=document.getElementById(elementId);if(element){let parent=element.parentElement;if(parent){parent.scrollTop=element.offsetTop;}}}
scrollTo(selector,left,top,behavior){let element=document.querySelector(selector)||document.documentElement;element.scrollTo({left,top,behavior});}
scrollIntoView(selector,behavior){let element=document.querySelector(selector)||document.documentElement;if(element)
element.scrollIntoView({behavior,block:'center',inline:'start'});}
scrollToBottom(selector,behavior){let element=document.querySelector(selector);if(element){element.scrollTo({top:element.scrollHeight,behavior:behavior});}else{window.scrollTo({top:document.body.scrollHeight,behavior:behavior});}}
lockScroll(selector,lockclass){let element=document.querySelector(selector)||document.body;let hasScrollBar=window.innerWidth>document.body.clientWidth;if(hasScrollBar){element.classList.add(lockclass);}else{let lockClassNoPadding=lockclass+"-no-padding";element.classList.add(lockClassNoPadding);}}
unlockScroll(selector,lockclass){let element=document.querySelector(selector)||document.body;element.classList.remove(lockclass);element.classList.remove(lockclass+"-no-padding");}};window.mudScrollManager=new MudScrollManager();class MudJsEventFactory{connect(dotNetRef,elementId,options){if(!elementId)
throw"[MudBlazor | JsEvent] elementId: expected element id!";var element=document.getElementById(elementId);if(!element)
throw"[MudBlazor | JsEvent] no element found for id: "+elementId;if(!element.mudJsEvent)
element.mudJsEvent=new MudJsEvent(dotNetRef,options);element.mudJsEvent.connect(element);}
disconnect(elementId){var element=document.getElementById(elementId);if(!element||!element.mudJsEvent)
return;element.mudJsEvent.disconnect();}
subscribe(elementId,eventName){if(!elementId)
throw"[MudBlazor | JsEvent] elementId: expected element id!";var element=document.getElementById(elementId);if(!element)
throw"[MudBlazor | JsEvent] no element found for id: "+elementId;if(!element.mudJsEvent)
throw"[MudBlazor | JsEvent] please connect before subscribing"
element.mudJsEvent.subscribe(eventName);}
unsubscribe(elementId,eventName){var element=document.getElementById(elementId);if(!element||!element.mudJsEvent)
return;element.mudJsEvent.unsubscribe(element,eventName);}}
window.mudJsEvent=new MudJsEventFactory();class MudJsEvent{constructor(dotNetRef,options){this._dotNetRef=dotNetRef;this._options=options||{};this.logger=options.enableLogging?console.log:(message)=>{};this.logger('[MudBlazor | JsEvent] Initialized',{options});this._subscribedEvents={};}
connect(element){if(!this._options)
return;if(!this._options.targetClass)
throw"_options.targetClass: css class name expected";if(this._observer){return;}
var targetClass=this._options.targetClass;this.logger('[MudBlazor | JsEvent] Start observing DOM of element for changes to child with class ',{element,targetClass});this._element=element;this._observer=new MutationObserver(this.onDomChanged);this._observer.mudJsEvent=this;this._observer.observe(this._element,{attributes:false,childList:true,subtree:true});this._observedChildren=[];}
disconnect(){if(!this._observer)
return;this.logger('[MudBlazor | JsEvent] disconnect mutation observer and event handler ');this._observer.disconnect();this._observer=null;for(const child of this._observedChildren)
this.detachHandlers(child);}
subscribe(eventName){if(this._subscribedEvents[eventName]){return;}
var element=this._element;var targetClass=this._options.targetClass;this._subscribedEvents[eventName]=true;for(const child of element.getElementsByClassName(targetClass)){this.attachHandlers(child);}}
unsubscribe(eventName){if(!this._observer)
return;this.logger('[MudBlazor | JsEvent] unsubscribe event handler '+eventName);this._observer.disconnect();this._observer=null;this._subscribedEvents[eventName]=false;for(const child of this._observedChildren){this.detachHandler(child,eventName);}}
attachHandlers(child){child.mudJsEvent=this;for(var eventName of Object.getOwnPropertyNames(this._subscribedEvents)){if(!this._subscribedEvents[eventName])
continue;this.logger('[MudBlazor | JsEvent] attaching event '+eventName,child);child.addEventListener(eventName,this.eventHandler);}
if(this._observedChildren.indexOf(child)<0)
this._observedChildren.push(child);}
detachHandler(child,eventName){this.logger('[MudBlazor | JsEvent] detaching handler '+eventName,child);child.removeEventListener(eventName,this.eventHandler);}
detachHandlers(child){this.logger('[MudBlazor | JsEvent] detaching handlers ',child);for(var eventName of Object.getOwnPropertyNames(this._subscribedEvents)){if(!this._subscribedEvents[eventName])
continue;child.removeEventListener(eventName,this.eventHandler);}
this._observedChildren=this._observedChildren.filter(x=>x!==child);}
onDomChanged(mutationsList,observer){var self=this.mudJsEvent;var targetClass=self._options.targetClass;for(const mutation of mutationsList){for(const element of mutation.addedNodes){if(element.classList&&element.classList.contains(targetClass)){if(!self._options.TagName||element.tagName==self._options.TagName)
self.attachHandlers(element);}}
for(const element of mutation.removedNodes){if(element.classList&&element.classList.contains(targetClass)){if(!self._options.tagName||element.tagName==self._options.tagName)
self.detachHandlers(element);}}}}
eventHandler(e){var self=this.mudJsEvent;var eventName=e.type;self.logger('[MudBlazor | JsEvent] "'+eventName+'"',e);self["on"+eventName](self,e);}
onkeyup(self,e){const caretPosition=e.target.selectionStart;const invoke=self._subscribedEvents["keyup"];if(invoke){self._dotNetRef.invokeMethodAsync('OnCaretPositionChanged',caretPosition);}}
onclick(self,e){const caretPosition=e.target.selectionStart;const invoke=self._subscribedEvents["click"];if(invoke){self._dotNetRef.invokeMethodAsync('OnCaretPositionChanged',caretPosition);}}
onpaste(self,e){const invoke=self._subscribedEvents["paste"];if(invoke){e.preventDefault();e.stopPropagation();const text=(e.originalEvent||e).clipboardData.getData('text/plain');self._dotNetRef.invokeMethodAsync('OnPaste',text);}}
onselect(self,e){const invoke=self._subscribedEvents["select"];if(invoke){const start=e.target.selectionStart;const end=e.target.selectionEnd;if(start===end)
return;self._dotNetRef.invokeMethodAsync('OnSelect',start,end);}}}
class MudThrottledEventManager{constructor(){this.mapper={};}
window.mudPopover=new MudPopover();window.addEventListener('scroll',()=>{window.mudpopoverHelper.placePopoverByClassSelector('mud-popover-fixed');window.mudpopoverHelper.placePopoverByClassSelector('mud-popover-overflow-flip-always');});window.addEventListener('resize',()=>{window.mudpopoverHelper.placePopoverByClassSelector();});class MudThrottledEventManager{constructor(){this.mapper={};}
subscribe(eventName,elementId,projection,throotleInterval,key,properties,dotnetReference){const handlerRef=this.throttleEventHandler.bind(this,key);let elem=document.getElementById(elementId);if(elem){elem.addEventListener(eventName,handlerRef,false);let projector=null;if(projection){const parts=projection.split('.');let functionPointer=window;let functionReferenceFound=true;if(parts.length==0||parts.length==1){functionPointer=functionPointer[projection];}
else{for(let i=0;i<parts.length;i++){functionPointer=functionPointer[parts[i]];if(!functionPointer){functionReferenceFound=false;break;}}}
if(functionReferenceFound===true){projector=functionPointer;}}
@@ -284,4 +276,11 @@ if(entry.projection){if(typeof entry.projection==="function"){entry.projection.a
entry.reference.invokeMethodAsync('OnEventOccur',key,JSON.stringify(eventEntry));}
unsubscribe(key){const entry=this.mapper[key];if(!entry){return;}
entry.reference=null;if(document==entry.elementId){document.removeEventListener(entry.eventName,entry.handler,false);}else{const elem=document.getElementById(entry.elementId);if(elem){elem.removeEventListener(entry.eventName,entry.handler,false);}}
delete this.mapper[key];}};window.mudThrottledEventManager=new MudThrottledEventManager();window.mudEventProjections={correctOffset:function(eventEntry,event){var target=event.target.getBoundingClientRect();eventEntry.offsetX=event.clientX-target.x;eventEntry.offsetY=event.clientY-target.y;}};
delete this.mapper[key];}};window.mudThrottledEventManager=new MudThrottledEventManager();window.mudEventProjections={correctOffset:function(eventEntry,event){var target=event.target.getBoundingClientRect();eventEntry.offsetX=event.clientX-target.x;eventEntry.offsetY=event.clientY-target.y;}};window.getTabbableElements=(element)=>{return element.querySelectorAll("a[href]:not([tabindex='-1']),"+"area[href]:not([tabindex='-1']),"+"button:not([disabled]):not([tabindex='-1']),"+"input:not([disabled]):not([tabindex='-1']):not([type='hidden']),"+"select:not([disabled]):not([tabindex='-1']),"+"textarea:not([disabled]):not([tabindex='-1']),"+"iframe:not([tabindex='-1']),"+"details:not([tabindex='-1']),"+"[tabindex]:not([tabindex='-1']),"+"[contentEditable=true]:not([tabindex='-1'])");};window.serializeParameter=(data,spec)=>{if(typeof data=="undefined"||data===null){return null;}
if(typeof data==="number"||typeof data==="string"||typeof data=="boolean"){return data;}
let res=(Array.isArray(data))?[]:{};if(!spec){spec="*";}
for(let i in data){let currentMember=data[i];if(typeof currentMember==='function'||currentMember===null){continue;}
let currentMemberSpec;if(spec!="*"){currentMemberSpec=Array.isArray(data)?spec:spec[i];if(!currentMemberSpec){continue;}}else{currentMemberSpec="*"}
if(typeof currentMember==='object'){if(Array.isArray(currentMember)||currentMember.length){res[i]=[];for(let j=0;j<currentMember.length;j++){const arrayItem=currentMember[j];if(typeof arrayItem==='object'){res[i].push(this.serializeParameter(arrayItem,currentMemberSpec));}else{res[i].push(arrayItem);}}}else{if(currentMember.length===0){res[i]=[];}else{res[i]=this.serializeParameter(currentMember,currentMemberSpec);}}}else{if(currentMember===Infinity){currentMember="Infinity";}
if(currentMember!==null){res[i]=currentMember;}}}
return res;};
+8 -8
View File
@@ -1,9 +1,9 @@
0.8.7
2024-08-05 19:08:00 UTC
169
8.0.107 (commit 1bdaef7265)
8.0.7 (commit 2aade6beb0)
1.80.0 (commit 051478957)
7.5.0
0.8.9
2024-08-18 10:35:05 UTC
171
8.0.108 (commit 665a05cea7)
8.0.8 (commit 08338fcaa5)
1.80.1 (commit 3f5fd8dd4)
7.6.0
1.7.1
bf0a75677d8, release
909fbe89bbb, release
+1 -1
View File
@@ -2308,7 +2308,7 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "mindwork-ai-studio"
version = "0.8.7"
version = "0.8.9"
dependencies = [
"arboard",
"flexi_logger",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "mindwork-ai-studio"
version = "0.8.7"
version = "0.8.9"
edition = "2021"
description = "MindWork AI Studio"
authors = ["Thorsten Sommer"]
+1 -1
View File
@@ -6,7 +6,7 @@
},
"package": {
"productName": "MindWork AI Studio",
"version": "0.8.7"
"version": "0.8.9"
},
"tauri": {
"allowlist": {