fixed diverse little issues that occured while testing

This commit is contained in:
nilsk 2026-03-17 17:20:16 +01:00
parent 9440f132c6
commit 2117df5b9e
10 changed files with 96 additions and 40 deletions

View File

@ -20,7 +20,22 @@ else
}
@code {
private RenderFragment RenderChildren(IEnumerable<IAssistantComponent> children) => @<text>
private RenderFragment RenderSwitch(AssistantSwitch assistantSwitch) => @<MudSwitch T="bool"
Value="@switchFields[assistantSwitch.Name]"
ValueChanged="@((bool value) => ExecuteSwitchChangedAsync(assistantSwitch, value))"
LabelPlacement="@assistantSwitch.GetLabelPlacement()"
Color="@assistantSwitch.GetColor(assistantSwitch.CheckedColor)"
UncheckedColor="@assistantSwitch.GetColor(assistantSwitch.UncheckedColor)"
ThumbIcon="@assistantSwitch.GetIconSvg()"
ThumbIconColor="@assistantSwitch.GetColor(assistantSwitch.IconColor)"
Disabled="@(assistantSwitch.Disabled || IsSwitchActionRunning(assistantSwitch.Name))"
Class="@assistantSwitch.Class"
Style="@GetOptionalStyle(assistantSwitch.Style)">
@(switchFields[assistantSwitch.Name] ? assistantSwitch.LabelOn : assistantSwitch.LabelOff)
</MudSwitch>;
}
@code {private RenderFragment RenderChildren(IEnumerable<IAssistantComponent> children) => @<text>
@foreach (var child in children)
{
@this.RenderComponent(child)
@ -145,12 +160,11 @@ else
var iconSize = AssistantComponentPropHelper.GetComponentSize(button.IconSize, Size.Medium);
var variant = button.GetButtonVariant();
var disabled = this.IsButtonActionRunning(button.Name);
var buttonClass = MergeClass(button.Class, "mb-3");
var buttonClass = MergeClass(button.Class, "");
var style = this.GetOptionalStyle(button.Style);
if (!button.IsIconButton)
{
<div>
<MudButton Variant="@variant"
Color="@color"
OnClick="@(() => this.ExecuteButtonActionAsync(button))"
@ -165,7 +179,6 @@ else
Style="@style">
@button.Text
</MudButton>
</div>
}
else
{
@ -314,23 +327,17 @@ else
if (component is AssistantSwitch switchComponent)
{
var assistantSwitch = switchComponent;
var currentValue = this.switchFields[assistantSwitch.Name];
var disabled = assistantSwitch.Disabled || this.IsSwitchActionRunning(assistantSwitch.Name);
<MudField Label="@assistantSwitch.Label" Variant="Variant.Outlined" Class="mb-3" Disabled="@disabled">
<MudSwitch T="bool"
Value="@currentValue"
ValueChanged="@((bool value) => this.ExecuteSwitchChangedAsync(assistantSwitch, value))"
LabelPlacement="@assistantSwitch.GetLabelPlacement()"
Color="@assistantSwitch.GetColor(assistantSwitch.CheckedColor)"
UncheckedColor="@assistantSwitch.GetColor(assistantSwitch.UncheckedColor)"
ThumbIcon="@assistantSwitch.GetIconSvg()"
ThumbIconColor="@assistantSwitch.GetColor(assistantSwitch.IconColor)"
Disabled="@disabled"
Class="@assistantSwitch.Class"
Style="@this.GetOptionalStyle(assistantSwitch.Style)">
@(currentValue ? assistantSwitch.LabelOn : assistantSwitch.LabelOff)
</MudSwitch>
</MudField>
if (string.IsNullOrEmpty(assistantSwitch.Label))
{
@this.RenderSwitch(assistantSwitch)
}
else
{
<MudField Label="@assistantSwitch.Label" Variant="Variant.Outlined" Class="mb-3" Disabled="@assistantSwitch.Disabled">
@this.RenderSwitch(assistantSwitch)
</MudField>
}
}
break;
case AssistantComponentType.HEADING:
@ -368,13 +375,16 @@ else
<MudList T="string" Class='@MergeClass(list.Class, "mb-6")' Style="@this.GetOptionalStyle(list.Style)">
@foreach (var item in list.Items)
{
var iconColor = AssistantComponentPropHelper.GetColor(item.IconColor, Color.Default);
@if (item.Type == "LINK")
{
<MudListItem T="string" Icon="@Icons.Material.Filled.Link" Target="_blank" Href="@item.Href">@item.Text</MudListItem>
<MudListItem T="string" Icon="@Icons.Material.Filled.Link" IconColor="@iconColor" Target="_blank" Href="@item.Href">@item.Text</MudListItem>
}
else
{
<MudListItem T="string">@item.Text</MudListItem>
var icon = !string.IsNullOrEmpty(item.Icon) ? AssistantComponentPropHelper.GetIconSvg(item.Icon) : string.Empty;
<MudListItem T="string" Icon="@icon" IconColor="@iconColor">@item.Text</MudListItem>
}
}
</MudList>
@ -385,7 +395,6 @@ else
{
var colorPicker = assistantColorPicker;
var variant = colorPicker.GetPickerVariant();
var elevation = variant == PickerVariant.Static ? 6 : 0;
var rounded = variant == PickerVariant.Static;
<MudItem Class="d-flex">
@ -397,8 +406,8 @@ else
ShowModeSwitch="@colorPicker.ShowModeSwitch"
PickerVariant="@variant"
Rounded="@rounded"
Elevation="@elevation"
Style="@($"color: {this.colorPickerFields[colorPicker.Name]};")"
Elevation="@colorPicker.Elevation"
Style="@($"color: {this.colorPickerFields[colorPicker.Name]};{colorPicker.Style}")"
Class="@MergeClass(colorPicker.Class, "mb-3")" />
</MudItem>
}
@ -417,6 +426,7 @@ else
Placeholder="@datePicker.Placeholder"
HelperText="@datePicker.HelperText"
DateFormat="@format"
Elevation="@datePicker.Elevation"
PickerVariant="@AssistantComponentPropHelper.GetPickerVariant(datePicker.PickerVariant, PickerVariant.Static)"
Variant="Variant.Outlined"
Class='@MergeClass(datePicker.Class, "mb-3")'
@ -441,6 +451,7 @@ else
HelperText="@dateRangePicker.HelperText"
DateFormat="@format"
PickerVariant="@AssistantComponentPropHelper.GetPickerVariant(dateRangePicker.PickerVariant, PickerVariant.Static)"
Elevation="@dateRangePicker.Elevation"
Variant="Variant.Outlined"
Class='@MergeClass(dateRangePicker.Class, "mb-3")'
Style="@this.GetOptionalStyle(dateRangePicker.Style)"
@ -464,6 +475,7 @@ else
TimeFormat="@format"
AmPm="@timePicker.AmPm"
PickerVariant="@AssistantComponentPropHelper.GetPickerVariant(timePicker.PickerVariant, PickerVariant.Static)"
Elevation="@timePicker.Elevation"
Variant="Variant.Outlined"
Class='@MergeClass(timePicker.Class, "mb-3")'
Style="@this.GetOptionalStyle(timePicker.Style)"/>

View File

@ -130,7 +130,8 @@ Images referenced via the `plugin://` scheme must exist in the plugin directory
| `TIME_PICKER` | `Name`, `Label` | `Value`, `Placeholder`, `HelperText`, `TimeFormat`, `AmPm`, `PickerVariant`, `UserPrompt`, `Class`, `Style` | [MudTimePicker](https://www.mudblazor.com/components/timepicker) |
| `HEADING` | `Text` | `Level` | [MudText Typo="Typo.<h2\|h3\|h4\|h5\|h6>"](https://www.mudblazor.com/components/typography) |
| `TEXT` | `Content` | `None` | [MudText Typo="Typo.body1"](https://www.mudblazor.com/components/typography) |
| `LIST` | `Type`, `Text` | `Href` | [MudList](https://www.mudblazor.com/componentss/list) |
| `LIST` | `None` | `Items (LIST_ITEM)`, `Class`, `Style` | [MudList](https://www.mudblazor.com/componentss/list) |
| `LIST_ITEM` | `Type`, `Text` | `Href`, `Icon`, `IconColor` | [MudList](https://www.mudblazor.com/componentss/list) |
| `IMAGE` | `Src` | `Alt`, `Caption`,`Src` | [MudImage](https://www.mudblazor.com/components/image) |
| `BUTTON_GROUP` | `None` | `Variant`, `Color`, `Size`, `OverrideStyles`, `Vertical`, `DropShadow`, `Class`, `Style` | [MudButtonGroup](https://www.mudblazor.com/components/buttongroup) |
| `LAYOUT_PAPER` | `None` | `Elevation`, `Height`, `MaxHeight`, `MinHeight`, `Width`, `MaxWidth`, `MinWidth`, `IsOutlined`, `IsSquare`, `Class`, `Style` | [MudPaper](https://www.mudblazor.com/components/paper) |
@ -402,9 +403,9 @@ More information on rendered components can be found [here](https://www.mudblazo
- Use `Type = "SWITCH"` to render a boolean toggle.
- Required props:
- `Name`: unique state key used in prompt assembly and `BuildPrompt(input.fields)`.
- `Label`: visible label for the switch field.
- `Value`: initial boolean state (`true` or `false`).
- Optional props:
- `Label`: If set, renders the switch inside an outlines Box, otherwise renders it raw. Visible label for the switch field.
- `OnChanged`: Lua callback invoked after the switch value changes. It receives the same `input` table as `BUTTON.Action(input)` and may return `{ fields = { ... } }` to update component state. The new switch value is already reflected in `input.fields[Name]`.
- `Disabled`: defaults to `false`; disables user interaction while still allowing the value to be included in prompt assembly.
- `UserPrompt`: prompt context text for this field.

View File

@ -114,7 +114,7 @@ ASSISTANT = {
["Type"] = "SWITCH",
["Props"] = {
["Name"] = "<unique identifier of this component>", -- required
["Label"] = "<heading of your component>", -- required
["Label"] = "<heading of your component>", -- Switches render mode between boxed switch and normal switch
["Value"] = true, -- initial switch state
["OnChanged"] = function(input) -- optional; same input and return contract as BUTTON.Action(input)
return nil
@ -297,13 +297,18 @@ ASSISTANT = {
{
["Type"] = "LINK", -- required
["Text"] = "<user readable link text>",
["Href"] = "<link>" -- required
["Href"] = "<link>", -- required
["IconColor"] = "<Dark|Error|Info|Inherit|Primary|Secondary|Success|Surface|Tertiary|Transparent|Warning>",
},
{
["Type"] = "TEXT", -- required
["Text"] = "<user readable text>"
["Text"] = "<user readable text>",
["Icon"] = "Icons.Material.Filled.HorizontalRule",
["IconColor"] = "<Dark|Error|Info|Inherit|Primary|Secondary|Success|Surface|Tertiary|Transparent|Warning>",
}
}
},
["Class"] = "<optional MudBlazor or css classes>",
["Style"] = "<optional css styles>",
}
},
{

View File

@ -52,6 +52,12 @@ internal sealed class AssistantColorPicker : AssistantComponentBase
get => AssistantComponentPropHelper.ReadString(this.Props, nameof(this.UserPrompt));
set => AssistantComponentPropHelper.WriteString(this.Props, nameof(this.UserPrompt), value);
}
public int Elevation
{
get => AssistantComponentPropHelper.ReadInt(this.Props, nameof(this.Elevation), 6);
set => AssistantComponentPropHelper.WriteInt(this.Props, nameof(this.Elevation), value);
}
public string Class
{

View File

@ -59,6 +59,12 @@ internal sealed class AssistantDatePicker : AssistantComponentBase
get => AssistantComponentPropHelper.ReadString(this.Props, nameof(this.UserPrompt));
set => AssistantComponentPropHelper.WriteString(this.Props, nameof(this.UserPrompt), value);
}
public int Elevation
{
get => AssistantComponentPropHelper.ReadInt(this.Props, nameof(this.Elevation), 6);
set => AssistantComponentPropHelper.WriteInt(this.Props, nameof(this.Elevation), value);
}
public string Class
{

View File

@ -65,6 +65,12 @@ internal sealed class AssistantDateRangePicker : AssistantComponentBase
get => AssistantComponentPropHelper.ReadString(this.Props, nameof(this.UserPrompt));
set => AssistantComponentPropHelper.WriteString(this.Props, nameof(this.UserPrompt), value);
}
public int Elevation
{
get => AssistantComponentPropHelper.ReadInt(this.Props, nameof(this.Elevation), 6);
set => AssistantComponentPropHelper.WriteInt(this.Props, nameof(this.Elevation), value);
}
public string Class
{

View File

@ -4,5 +4,7 @@ public class AssistantListItem
{
public string Type { get; set; } = "TEXT";
public string Text { get; set; } = string.Empty;
public string Icon { get; set; } = string.Empty;
public string IconColor { get; set; } = string.Empty;
public string? Href { get; set; }
}

View File

@ -65,6 +65,12 @@ internal sealed class AssistantTimePicker : AssistantComponentBase
get => AssistantComponentPropHelper.ReadString(this.Props, nameof(this.UserPrompt));
set => AssistantComponentPropHelper.WriteString(this.Props, nameof(this.UserPrompt), value);
}
public int Elevation
{
get => AssistantComponentPropHelper.ReadInt(this.Props, nameof(this.Elevation), 6);
set => AssistantComponentPropHelper.WriteInt(this.Props, nameof(this.Elevation), value);
}
public string Class
{

View File

@ -18,9 +18,9 @@ public static class ComponentPropSpecs
]
),
[AssistantComponentType.BUTTON] = new(
required: ["Name", "Text", "Action"],
required: ["Name", "Action"],
optional: [
"IsIconButton", "Variant", "Color", "IsFullWidth", "Size",
"Text", "IsIconButton", "Variant", "Color", "IsFullWidth", "Size",
"StartIcon", "EndIcon", "IconColor", "IconSize", "Class", "Style"
]
),
@ -44,10 +44,10 @@ public static class ComponentPropSpecs
optional: ["ValidationMessage", "Class", "Style"]
),
[AssistantComponentType.SWITCH] = new(
required: ["Name", "Label", "Value"],
required: ["Name", "Value"],
optional: [
"OnChanged", "LabelOn", "LabelOff", "LabelPlacement", "Icon", "IconColor", "UserPrompt",
"CheckedColor", "UncheckedColor", "Disabled", "Class", "Style",
"Label", "OnChanged", "LabelOn", "LabelOff", "LabelPlacement", "Icon", "IconColor",
"UserPrompt", "CheckedColor", "UncheckedColor", "Disabled", "Class", "Style",
]
),
[AssistantComponentType.HEADING] = new(
@ -84,7 +84,7 @@ public static class ComponentPropSpecs
[AssistantComponentType.DATE_PICKER] = new(
required: ["Name", "Label"],
optional: [
"Value", "Placeholder", "HelperText", "DateFormat", "Color",
"Value", "Placeholder", "HelperText", "DateFormat", "Color", "Elevation",
"PickerVariant", "UserPrompt", "Class", "Style"
]
),
@ -92,14 +92,14 @@ public static class ComponentPropSpecs
required: ["Name", "Label"],
optional: [
"Value", "PlaceholderStart", "PlaceholderEnd", "HelperText", "DateFormat",
"Color", "PickerVariant", "UserPrompt", "Class", "Style"
"Elevation", "Color", "PickerVariant", "UserPrompt", "Class", "Style"
]
),
[AssistantComponentType.TIME_PICKER] = new(
required: ["Name", "Label"],
optional: [
"Value", "Placeholder", "HelperText", "TimeFormat", "AmPm", "Color",
"PickerVariant", "UserPrompt", "Class", "Style"
"Elevation", "PickerVariant", "UserPrompt", "Class", "Style"
]
),
[AssistantComponentType.LAYOUT_ITEM] = new(

View File

@ -1,6 +1,7 @@
using AIStudio.Tools.PluginSystem.Assistants.DataModel;
using AIStudio.Tools.PluginSystem.Assistants.DataModel.Layout;
using Lua;
using System.Text;
namespace AIStudio.Tools.PluginSystem.Assistants;
@ -468,9 +469,20 @@ public sealed class PluginAssistants(bool isInternal, LuaState state, PluginType
if (!table.TryGetValue("Type", out var typeVal) || !typeVal.TryRead<string>(out var type))
return false;
table.TryGetValue("Icon", out var iconVal);
iconVal.TryRead<string>(out var icon);
icon ??= string.Empty;
table.TryGetValue("IconColor", out var iconColorVal);
iconColorVal.TryRead<string>(out var iconColor);
iconColor ??= string.Empty;
item.Text = text;
item.Type = type;
item.Icon = icon;
item.IconColor = iconColor;
if (table.TryGetValue("Href", out var hrefVal) && hrefVal.TryRead<string>(out var href))
{