Skip to content

Commit 14d5a86

Browse files
committed
refactor: add menu component
1 parent e1b9dc0 commit 14d5a86

File tree

3 files changed

+197
-1
lines changed

3 files changed

+197
-1
lines changed
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
@implements IAsyncDisposable
2+
@implements IDisposable
3+
@inject IJSRuntime JS
4+
@using System.Drawing
5+
6+
<CascadingValue Value="@this">
7+
@if (Open)
8+
{
9+
@if (Anchored)
10+
{
11+
<AzureOverlay @bind-Visible="@Open" OnClose="@CloseAsync"/>
12+
13+
<AzureAnchoredRegion Anchor="@Anchor" HorizontalDefaultPosition="@HorizontalPosition" HorizontalInset="@HorizontalInset" HorizontalPositioningMode="AzureAnchoredRegion.AxisPositioningMode.Dynamic" HorizontalThreshold="@HorizontalThreshold" VerticalDefaultPosition="@VerticalPosition" VerticalInset="@VerticalInset" VerticalPositioningMode="AzureAnchoredRegion.AxisPositioningMode.Dynamic" VerticalThreshold="@VerticalThreshold">
14+
<div class="flex flex-col bg-white border shadow-md border-alto dark:bg-cod-grey dark:border-masala" role="menu" style="@Style">
15+
@ChildContent
16+
</div>
17+
</AzureAnchoredRegion>
18+
}
19+
else
20+
{
21+
if (Trigger is MouseButton.Right)
22+
{
23+
<AzureOverlay @bind-Visible="@Open" OnClose="@CloseAsync"/>
24+
}
25+
26+
<div class="flex flex-col bg-white border shadow-md border-alto z-9999 w-[unset] h-[unset] dark:bg-cod-grey dark:border-masala" role="menu" style="@Style">
27+
@ChildContent
28+
</div>
29+
}
30+
}
31+
</CascadingValue>
32+
33+
@code {
34+
35+
[Parameter] public string? Anchor { get; set; }
36+
37+
[Parameter] public bool Anchored { get; set; } = true;
38+
39+
[Parameter] public RenderFragment? ChildContent { get; set; }
40+
41+
[Parameter] public bool HorizontalInset { get; set; } = true;
42+
43+
[Parameter] public AzureAnchoredRegion.HorizontalPosition HorizontalPosition { get; set; } = AzureAnchoredRegion.HorizontalPosition.Unset;
44+
45+
[Parameter] public int HorizontalThreshold { get; set; }
46+
47+
[Parameter] public bool Open { get; set; }
48+
49+
[Parameter] public EventCallback<bool> OpenChanged { get; set; }
50+
51+
[Parameter] public MouseButton Trigger { get; set; } = MouseButton.None;
52+
53+
[Parameter] public bool VerticalInset { get; set; }
54+
55+
[Parameter] public AzureAnchoredRegion.VerticalPosition VerticalPosition { get; set; } = AzureAnchoredRegion.VerticalPosition.Bottom;
56+
57+
[Parameter] public int VerticalThreshold { get; set; }
58+
59+
private Point ClickedPoint { get; set; }
60+
61+
private DotNetObjectReference<AzureMenu>? DotNetHelper { get; set; }
62+
63+
private IJSObjectReference? Module { get; set; }
64+
65+
private string Style
66+
{
67+
get
68+
{
69+
var style = "";
70+
71+
if (!Anchored && !string.IsNullOrEmpty(Anchor))
72+
{
73+
style += "position: fixed;";
74+
}
75+
76+
if (!Anchored && ClickedPoint.X is not 0)
77+
{
78+
style += $"left: {ClickedPoint.X}px;";
79+
}
80+
81+
if (!Anchored && ClickedPoint.Y is not 0)
82+
{
83+
style += $"top: {ClickedPoint.Y}px;";
84+
}
85+
86+
return style;
87+
}
88+
}
89+
90+
public async Task CloseAsync()
91+
{
92+
Open = false;
93+
94+
await OpenChanged.InvokeAsync(Open);
95+
96+
StateHasChanged();
97+
}
98+
99+
public void Dispose()
100+
{
101+
DotNetHelper?.Dispose();
102+
}
103+
104+
public async ValueTask DisposeAsync()
105+
{
106+
if (Module is not null)
107+
{
108+
await Module.DisposeAsync();
109+
}
110+
}
111+
112+
[JSInvokable]
113+
public async Task OpenAsync(int x, int y)
114+
{
115+
ClickedPoint = new Point(x, y);
116+
117+
Open = true;
118+
119+
await OpenChanged.InvokeAsync(Open);
120+
121+
StateHasChanged();
122+
}
123+
124+
protected override async Task OnAfterRenderAsync(bool firstRender)
125+
{
126+
if (firstRender)
127+
{
128+
if (Trigger is not MouseButton.None)
129+
{
130+
Module = await JS.InvokeAsync<IJSObjectReference>("import", "./Components/AzureMenu.razor.js");
131+
132+
DotNetHelper = DotNetObjectReference.Create(this);
133+
134+
if (!string.IsNullOrEmpty(Anchor))
135+
{
136+
switch (Trigger)
137+
{
138+
case MouseButton.Left:
139+
await Module.InvokeVoidAsync("addEventLeftClick", Anchor, DotNetHelper);
140+
141+
break;
142+
case MouseButton.Right:
143+
await Module.InvokeVoidAsync("addEventRightClick", Anchor, DotNetHelper);
144+
145+
break;
146+
}
147+
}
148+
}
149+
}
150+
}
151+
152+
protected override void OnInitialized()
153+
{
154+
if (Anchored && string.IsNullOrEmpty(Anchor))
155+
{
156+
Anchored = false;
157+
}
158+
}
159+
160+
/// <summary>
161+
/// Describes the mouse button trigger of an <see cref="AzureMenu"/>.
162+
/// </summary>
163+
public enum MouseButton
164+
{
165+
/// <summary>
166+
/// The menu cannot be opened by clicking on the <see cref="AzureMenu.Anchor"/>.
167+
/// </summary>
168+
None,
169+
170+
/// <summary>
171+
/// The menu can be opened by left clicking on the <see cref="AzureMenu.Anchor"/>.
172+
/// </summary>
173+
Left,
174+
175+
/// <summary>
176+
/// The menu can be opened by right clicking on the <see cref="AzureMenu.Anchor"/>.
177+
/// </summary>
178+
Right
179+
}
180+
181+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export function addEventLeftClick(anchor, dotNetHelper) {
2+
document.getElementById(anchor)?.addEventListener("click", async function (event) {
3+
event.preventDefault();
4+
5+
await dotNetHelper.invokeMethodAsync("OpenAsync", event.clientX, event.clientY);
6+
});
7+
}
8+
9+
export function addEventRightClick(anchor, dotNetHelper) {
10+
document.getElementById(anchor)?.addEventListener("contextmenu", async function (event) {
11+
event.preventDefault();
12+
13+
await dotNetHelper.invokeMethodAsync("OpenAsync", event.clientX, event.clientY);
14+
});
15+
}

0 commit comments

Comments
 (0)